Compare commits

..

5 Commits

Author SHA1 Message Date
Joseph Hopfmüller
fa85fca978 add data to lfs 2024-11-15 17:01:29 +01:00
Joseph Hopfmüller
9c43ce4c85 git lfs setup cont'd 2 2024-11-15 16:54:03 +01:00
Joseph Hopfmüller
c76bfd20fe lfs setup cont'd 2024-11-15 16:49:09 +01:00
Joseph Hopfmüller
f3544bc9ce setup lfs 2024-11-15 16:46:49 +01:00
Joseph Hopfmüller
0564969a50 signal generation working 2024-11-15 16:46:09 +01:00
6 changed files with 362 additions and 143 deletions

27
.gitattributes vendored Normal file
View File

@@ -0,0 +1,27 @@
data/**/* filter=lfs diff=lfs merge=lfs -text
data/*.ini filter=lfs diff=lfs merge=lfs text
## lfs setup
# Archives
*.7z filter=lfs diff=lfs merge=lfs -text
*.br filter=lfs diff=lfs merge=lfs -text
*.gz filter=lfs diff=lfs merge=lfs -text
*.tar filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
# Documents
*.pdf filter=lfs diff=lfs merge=lfs -text
# Images
*.gif filter=lfs diff=lfs merge=lfs -text
*.ico filter=lfs diff=lfs merge=lfs -text
*.jpg filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.psd filter=lfs diff=lfs merge=lfs -text
*.webp filter=lfs diff=lfs merge=lfs -text
# Fonts
*.woff2 filter=lfs diff=lfs merge=lfs -text
# Other
*.exe filter=lfs diff=lfs merge=lfs -text

10
.gitignore vendored
View File

@@ -1,3 +1,9 @@
pypho
# VSCode
.vscode
# Byte-compiled / optimized / DLL files # Byte-compiled / optimized / DLL files
__pycache__/ __pycache__/
*.py[cod] *.py[cod]
@@ -160,7 +166,3 @@ cython_debug/
# and can be added to the global gitignore or merged into this file. For a more nuclear # and can be added to the global gitignore or merged into this file. For a more nuclear
# option (not recommended) you can uncomment the following to ignore the entire idea folder. # option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/ #.idea/
# VSCode
.vscode
pypho

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:fc7d0ef00516cff602c32e0ab75495b6ae411031f2f28c4ad2c244e67e6537d6
size 581

View File

@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a84cb2f8c58b3219f1d3931bfdd7140582290a6e12d31f25ea4f0d71a1388d8e
size 134217856

View File

@@ -3,24 +3,20 @@ from datetime import datetime
import hashlib import hashlib
from pathlib import Path from pathlib import Path
import time import time
from matplotlib import pyplot as plt from matplotlib import pyplot as plt # noqa: F401
import scipy
import numpy as np import numpy as np
from rich import inspect
import _path_fix # noqa: F401 import _path_fix # noqa: F401
import pypho import pypho
import io
# import inspect # import inspect
default_config = f""" default_config = f"""
[glova] [glova]
sps = 256
nos = 256 nos = 256
sps = 256
f0 = 193414489032258.06 f0 = 193414489032258.06
symbolrate = 10e9 symbolrate = 10e9
wisdom_dir = "{str((Path.home()/".pypho"))}" wisdom_dir = "{str((Path.home() / ".pypho"))}"
flags = "FFTW_PATIENT" flags = "FFTW_PATIENT"
nthreads = 32 nthreads = 32
@@ -34,19 +30,26 @@ birefsteps = 1
; birefseed = 0xC0FFEE ; birefseed = 0xC0FFEE
[signal] [signal]
; seed = 0xC0FFEE
modulation = "pam" modulation = "pam"
mod_order = 4 mod_order = 4
mod_depth = 0.5 mod_depth = 0.8
laser_power = 0
; seed = 0xC0FFEE max_jitter = 0.02
pulse_shape = "gauss_rz"
fwhm = 0.33
; jitter_seed = 0xC0FFEE ; jitter_seed = 0xC0FFEE
[script] laser_power = 0
data_dir = "{str((Path.home()/".pypho"/"data"))}" edfa_power = 3
""" edfa_nf = 5
pulse_shape = "gauss"
fwhm = 0.33
[data]
dir = "data"
npy_dir = "npys"
"""
def get_config(config_file=None): def get_config(config_file=None):
@@ -72,8 +75,17 @@ def get_config(config_file=None):
# conf[section][key] = config[section][key].strip('"') # conf[section][key] = config[section][key].strip('"')
return conf return conf
class pam_generator: class pam_generator:
def __init__(self, glova, mod_order=None, mod_depth=0.5, pulse_shape='gauss', fwhm=0.33, seed=None) -> None: def __init__(
self,
glova,
mod_order=None,
mod_depth=0.5,
pulse_shape="gauss",
fwhm=0.33,
seed=None,
) -> None:
self.glova = glova self.glova = glova
self.pulse_shape = pulse_shape self.pulse_shape = pulse_shape
self.modulation_depth = mod_depth self.modulation_depth = mod_depth
@@ -82,21 +94,24 @@ class pam_generator:
self.seed = seed self.seed = seed
def __call__(self, E, symbols, max_jitter=0): def __call__(self, E, symbols, max_jitter=0):
symbols_x = symbols[0]/(self.mod_order or np.max(symbols[0])) symbols_x = symbols[0] / (self.mod_order or np.max(symbols[0]))
symbols_y = symbols[1]/(self.mod_order or np.max(symbols[1])) symbols_y = symbols[1] / (self.mod_order or np.max(symbols[1]))
diffs_x = np.diff(symbols_x, prepend=symbols_x[0]) diffs_x = np.diff(symbols_x, prepend=symbols_x[0])
diffs_y = np.diff(symbols_y, prepend=symbols_y[0]) diffs_y = np.diff(symbols_y, prepend=symbols_y[0])
max_jitter = int(round(max_jitter*self.glova.sps)) max_jitter = int(round(max_jitter * self.glova.sps))
digital_x = self.generate_digital_signal(diffs_x, max_jitter) digital_x = self.generate_digital_signal(diffs_x, max_jitter)
digital_y = self.generate_digital_signal(diffs_y, max_jitter) digital_y = self.generate_digital_signal(diffs_y, max_jitter)
digital_x = np.pad(digital_x, (0, self.glova.sps//2), 'constant', constant_values=(0,0)) digital_x = np.pad(
digital_y = np.pad(digital_y, (0, self.glova.sps//2), 'constant', constant_values=(0,0)) digital_x, (0, self.glova.sps // 2), "constant", constant_values=(0, 0)
)
digital_y = np.pad(
digital_y, (0, self.glova.sps // 2), "constant", constant_values=(0, 0)
)
if self.pulse_shape == 'gauss': if self.pulse_shape == "gauss":
wavelet = self.gauss(oversampling=6) wavelet = self.gauss(oversampling=6)
else: else:
raise ValueError(f"Unknown pulse shape: {self.pulse_shape}") raise ValueError(f"Unknown pulse shape: {self.pulse_shape}")
@@ -106,108 +121,154 @@ class pam_generator:
E_y = np.convolve(digital_y, wavelet) E_y = np.convolve(digital_y, wavelet)
# convert to pam and set modulation depth (scale and move up such that 1 stays at 1) # convert to pam and set modulation depth (scale and move up such that 1 stays at 1)
E_x = np.cumsum(E_x)*self.modulation_depth + (1-self.modulation_depth) E_x = np.cumsum(E_x) * self.modulation_depth + (1 - self.modulation_depth)
E_y = np.cumsum(E_y)*self.modulation_depth + (1-self.modulation_depth) E_y = np.cumsum(E_y) * self.modulation_depth + (1 - self.modulation_depth)
# cut off the wavelet tails # cut off the wavelet tails
E_x = E_x[self.glova.sps//2+len(wavelet)//2-1:-len(wavelet)//2] E_x = E_x[self.glova.sps // 2 + len(wavelet) // 2 - 1 : -len(wavelet) // 2]
E_y = E_y[self.glova.sps//2+len(wavelet)//2-1:-len(wavelet)//2] E_y = E_y[self.glova.sps // 2 + len(wavelet) // 2 - 1 : -len(wavelet) // 2]
# modulate the laser # modulate the laser
np.multiply(E[0]['E'][0],E_x, out=E[0]['E'][0]) E[0]["E"][0] = np.sqrt(np.multiply(np.square(E[0]["E"][0]), E_x))
np.multiply(E[0]['E'][1],E_y, out=E[0]['E'][1]) E[0]["E"][1] = np.sqrt(np.multiply(np.square(E[0]["E"][1]), E_y))
return E return E
def generate_digital_signal(self, symbols, max_jitter=0): def generate_digital_signal(self, symbols, max_jitter=0):
rs = np.random.RandomState(self.seed) rs = np.random.RandomState(self.seed)
signal = np.zeros(self.glova.nos*self.glova.sps) signal = np.zeros(self.glova.nos * self.glova.sps)
for index in range(self.glova.nos): for index in range(self.glova.nos):
jitter = max_jitter != 0 and rs.randint(-max_jitter, max_jitter) jitter = max_jitter != 0 and rs.randint(-max_jitter, max_jitter)
signal_index = index*self.glova.sps + jitter signal_index = index * self.glova.sps + jitter
if signal_index < 0: if signal_index < 0:
continue continue
if signal_index >= len(signal): if signal_index >= len(signal):
continue continue
signal[signal_index] = symbols[index] signal[signal_index] = symbols[index]
return signal return signal
def gauss(self, oversampling=1): def gauss(self, oversampling=1):
sample_points = np.linspace(-oversampling*self.glova.sps, oversampling*self.glova.sps, oversampling*2*self.glova.sps, endpoint=True) sample_points = np.linspace(
sigma = self.fwhm/(1*np.sqrt(2*np.log(2)))*self.glova.sps -oversampling * self.glova.sps,
pulse = 1/(sigma*np.sqrt(2*np.pi))*np.exp(-np.square(sample_points)/(2*np.square(sigma))) oversampling * self.glova.sps,
oversampling * 2 * self.glova.sps,
endpoint=True,
)
sigma = self.fwhm / (1 * np.sqrt(2 * np.log(2))) * self.glova.sps
pulse = (
1
/ (sigma * np.sqrt(2 * np.pi))
* np.exp(-np.square(sample_points) / (2 * np.square(sigma)))
)
return pulse return pulse
def initialize_fiber_and_data(config, input_data_override=None): def initialize_fiber_and_data(config, input_data_override=None):
py_glova = pypho.setup( py_glova = pypho.setup(
nos = config['glova']['nos'], nos=config["glova"]["nos"],
sps = config['glova']['sps'], sps=config["glova"]["sps"],
f0 = config['glova']['f0'], f0=config["glova"]["f0"],
symbolrate=config['glova']['symbolrate'], symbolrate=config["glova"]["symbolrate"],
wisdom_dir = config['glova']['wisdom_dir'], wisdom_dir=config["glova"]["wisdom_dir"],
flags = config['glova']['flags'], flags=config["glova"]["flags"],
nthreads = config['glova']['nthreads'], nthreads=config["glova"]["nthreads"],
) )
c_glova = pypho.cfiber.GlovaWrapper.from_setup(py_glova) c_glova = pypho.cfiber.GlovaWrapper.from_setup(py_glova)
c_data = pypho.cfiber.DataWrapper(py_glova.sps * py_glova.nos) c_data = pypho.cfiber.DataWrapper(py_glova.sps * py_glova.nos)
py_edfa = pypho.oamp(py_glova, Pmean=config["signal"]["edfa_power"], NF=config["signal"]["edfa_nf"])
if input_data_override is not None: if input_data_override is not None:
c_data.E_in = input_data_override c_data.E_in = input_data_override[0]
noise = input_data_override[1]
else: else:
config['signal']['seed'] = config['signal'].get('seed',(int(time.time()*1000))%2**32) config["signal"]["seed"] = config["signal"].get(
config['signal']['jitter_seed'] = config['signal'].get('jitter_seed', (int(time.time()*1000))%2**32) "seed", (int(time.time() * 1000)) % 2**32
symbolsrc = pypho.symbols(py_glova, py_glova.nos, pattern='ones', seed=config['signal']['seed']) )
laser = pypho.lasmod(py_glova, power=config['signal']['laser_power'], Df=0, theta=np.pi/4) config["signal"]["jitter_seed"] = config["signal"].get(
modulator = pam_generator(py_glova, mod_depth=config['signal']['mod_depth'], pulse_shape=config['signal']['pulse_shape'], fwhm=config['signal']['fwhm'], seed=config['signal']['jitter_seed']) "jitter_seed", (int(time.time() * 1000)) % 2**32
)
symbolsrc = pypho.symbols(
py_glova, py_glova.nos, pattern="ones", seed=config["signal"]["seed"]
)
laser = pypho.lasmod(
py_glova, power=config["signal"]["laser_power"]+1.5, Df=0, theta=np.pi / 4
)
modulator = pam_generator(
py_glova,
mod_depth=config["signal"]["mod_depth"],
pulse_shape=config["signal"]["pulse_shape"],
fwhm=config["signal"]["fwhm"],
seed=config["signal"]["jitter_seed"],
)
symbols_x = symbolsrc(pattern='random', p1=config['signal']['mod_order']) symbols_x = symbolsrc(pattern="random", p1=config["signal"]["mod_order"])
symbols_y = symbolsrc(pattern='random', p1=config['signal']['mod_order']) symbols_y = symbolsrc(pattern="random", p1=config["signal"]["mod_order"])
symbols_x[:3] = 0 symbols_x[:3] = 0
symbols_y[:3] = 0 symbols_y[:3] = 0
cw = laser() cw = laser()
cw[0]['E']*=np.sqrt(2)
source_signal = modulator(E=cw, symbols=(symbols_x, symbols_y)) source_signal = modulator(E=cw, symbols=(symbols_x, symbols_y))
source_signal = py_edfa(E=source_signal)
c_data.E_in = source_signal[0]['E'] c_data.E_in = source_signal[0]["E"]
noise = source_signal[0]["noise"]
py_fiber = pypho.fiber( py_fiber = pypho.fiber(
glova = py_glova, glova=py_glova,
l=config['fiber']['length'], l=config["fiber"]["length"],
alpha=pypho.functions.dB_to_Neper(config['fiber']['alpha'])/1000, alpha=pypho.functions.dB_to_Neper(config["fiber"]["alpha"]) / 1000,
gamma=config['fiber']['gamma'], gamma=config["fiber"]["gamma"],
D=config['fiber']['d'], D=config["fiber"]["d"],
S=config['fiber']['s'], S=config["fiber"]["s"],
)
if config["fiber"]["birefsteps"] > 0:
config["fiber"]["birefseed"] = config["fiber"].get(
"birefseed", (int(time.time() * 1000)) % 2**32
)
py_fiber.birefarray = pypho.birefringence_segment.create_pmd_fibre(
py_fiber.l,
py_fiber.l / config["fiber"]["birefsteps"],
0,
config["fiber"]["birefseed"],
)
c_params = pypho.cfiber.ParamsWrapper.from_fiber(
py_fiber, max_step=1e3 if py_fiber.gamma == 0 else 200
) )
if config['fiber']['birefsteps'] > 0:
config['fiber']['birefseed'] = config['fiber'].get('birefseed', (int(time.time()*1000))%2**32)
py_fiber.birefarray = pypho.birefringence_segment.create_pmd_fibre(py_fiber.l, py_fiber.l/config['fiber']['birefsteps'], 0, config['fiber']['birefseed'])
c_params = pypho.cfiber.ParamsWrapper.from_fiber(py_fiber, max_step=1e3)
c_fiber = pypho.cfiber.FiberWrapper(c_data, c_params, c_glova) c_fiber = pypho.cfiber.FiberWrapper(c_data, c_params, c_glova)
return c_fiber, c_data return c_fiber, c_data, noise, py_edfa
def save_data(data, config): def save_data(data, config):
data_dir = Path(config['script']['data_dir']) data_dir = Path(config["data"]["dir"])
save_dir = data_dir npy_dir = config["data"].get("npy_dir", "")
save_dir = data_dir / npy_dir if len(npy_dir) else data_dir
save_dir.mkdir(parents=True, exist_ok=True) save_dir.mkdir(parents=True, exist_ok=True)
save_data = np.column_stack([data.E_in[0], data.E_in[1], data.E_out[0], data.E_out[1]]) save_data = np.column_stack([
data.E_in[0],
data.E_in[1],
data.E_out[0],
data.E_out[1],
])
timestamp = datetime.now() timestamp = datetime.now()
config_content = '\n'.join(( seed = config["signal"].get("seed", False)
f"; Generated by {str(Path(__file__).name)} @ {timestamp.strftime("%Y-%m-%d %H:%M:%S")}", jitter_seed = config["signal"].get("jitter_seed", False)
birefseed = config["fiber"].get("birefseed", False)
config_content = "\n".join((
f"; Generated by {str(Path(__file__).name)} @ {timestamp.strftime('%Y-%m-%d %H:%M:%S')}",
"[glova]", "[glova]",
f"sps = {config['glova']['sps']}", f"sps = {config['glova']['sps']}",
f"nos = {config['glova']['nos']}", f"nos = {config['glova']['nos']}",
f"f0 = {config['glova']['f0']}", f"f0 = {config['glova']['f0']}",
f"symbolrate = {config['glova']['symbolrate']}", f"symbolrate = {config['glova']['symbolrate']}",
f'wisdom_dir = "{config['glova']['wisdom_dir']}"', f'wisdom_dir = "{config["glova"]["wisdom_dir"]}"',
f'flags = "{config["glova"]["flags"]}"', f'flags = "{config["glova"]["flags"]}"',
f"nthreads = {config['glova']['nthreads']}", f"nthreads = {config['glova']['nthreads']}",
"", " ",
"[fiber]", "[fiber]",
f"length = {config['fiber']['length']}", f"length = {config['fiber']['length']}",
f"gamma = {config['fiber']['gamma']}", f"gamma = {config['fiber']['gamma']}",
@@ -215,34 +276,43 @@ def save_data(data, config):
f"D = {config['fiber']['d']}", f"D = {config['fiber']['d']}",
f"S = {config['fiber']['s']}", f"S = {config['fiber']['s']}",
f"birefsteps = {config['fiber']['birefsteps']}", f"birefsteps = {config['fiber']['birefsteps']}",
f"birefseed = {config['fiber'].get('birefseed', 'not set')}", f"birefseed = {hex(birefseed)}" if birefseed else "; birefseed = not set",
"", "",
"[signal]", "[signal]",
f'modulation = "{config['signal']['modulation']}"', f"seed = {hex(seed)}" if seed else "; seed = not set",
"",
f'modulation = "{config["signal"]["modulation"]}"',
f"mod_order = {config['signal']['mod_order']}", f"mod_order = {config['signal']['mod_order']}",
f"mod_depth = {config['signal']['mod_depth']}", f"mod_depth = {config['signal']['mod_depth']}",
f"seed = {config['signal'].get('seed', 'not set')}", ""
f"max_jitter = {config['signal']['max_jitter']}",
f"jitter_seed = {hex(jitter_seed)}" if jitter_seed else "; jitter_seed = not set",
""
f"laser_power = {config['signal']['laser_power']}",
f"edfa_power = {config['signal']['edfa_power']}",
f"edfa_nf = {config['signal']['edfa_nf']}",
""
f'pulse_shape = "{config["signal"]["pulse_shape"]}"', f'pulse_shape = "{config["signal"]["pulse_shape"]}"',
f"fwhm = {config['signal']['fwhm']}", f"fwhm = {config['signal']['fwhm']}",
f"max_jitter = {config['signal']['max_jitter']}",
f"jitter_seed = {config['signal'].get('jitter_seed', 'not set')}",
"", "",
"[script]", "[data]",
f'data_dir = "{config["script"]["data_dir"]}"', f'dir = "{str(data_dir)}"',
f'npy_dir = "{npy_dir}"',
"file = "
)) ))
config_hash = hashlib.md5(config_content.encode()).hexdigest() config_hash = hashlib.md5(config_content.encode()).hexdigest()
save_file = f"npys/{config_hash}.npy" save_file = f"{config_hash}.npy"
config_content += f'\n\n[DATA]\nfile = "{str(save_file)}\n"' config_content += f'"{str(save_file)}"\n'
filename_components = ( filename_components = (
timestamp.strftime("%Y%m%d-%H%M%S"), timestamp.strftime("%Y%m%d-%H%M%S"),
config['glova']['sps'], config["glova"]["sps"],
config['glova']['nos'], config["glova"]["nos"],
config['fiber']['length'], config["fiber"]["length"],
config['fiber']['gamma'], config["fiber"]["gamma"],
config['fiber']['alpha'], config["fiber"]["alpha"],
config['fiber']['d'], config["fiber"]["d"],
config['fiber']['s'], config["fiber"]["s"],
f"{config['signal']['modulation'].upper()}{config['signal']['mod_order']}", f"{config['signal']['modulation'].upper()}{config['signal']['mod_order']}",
) )
@@ -255,65 +325,174 @@ def save_data(data, config):
print("Saved config to", data_dir / lookup_file) print("Saved config to", data_dir / lookup_file)
print("Saved data to", save_dir / f"{config_hash}.npy") print("Saved data to", save_dir / f"{config_hash}.npy")
def length_loop(config):
# loop over lengths
# lengths = [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000, 2000, 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000, 20000, 30000, 40000, 50000, 60000, 70000, 80000, 90000, 100000]
ranges = [1, 10, 100, 1000, 10000, 100000]
lengths = [list(range(length_range,10*length_range, length_range)) for length_range in ranges]
lengths = [length for length_range in lengths for length in length_range]
def length_loop(config, lengths):
lengths = sorted(lengths) lengths = sorted(lengths)
input_override = None input_override = None
for lind, length in enumerate(lengths): for lind, length in enumerate(lengths):
# print(f"\nGenerating data for fiber length {length}") # print(f"\nGenerating data for fiber length {length}")
if lind > 0: if lind > 0:
# set the length to the difference between the current and previous length -> incremental # set the length to the difference between the current and previous length -> incremental
length = lengths[lind] - lengths[lind-1] length = lengths[lind] - lengths[lind - 1]
print(f"\nGenerating data for fiber length {lengths[lind]}m -> {length}m") print(
config['fiber']['length'] = length f"\nGenerating data for fiber length {lengths[lind]}m [using {length}m increment]"
)
config["fiber"]["length"] = length
# set the input data to the output data of the previous run # set the input data to the output data of the previous run
cfiber, cdata = initialize_fiber_and_data(config, input_data_override=input_override) cfiber, cdata, noise, edfa = initialize_fiber_and_data(
config, input_data_override=input_override
)
if lind == 0: if lind == 0:
cdata_orig = cdata cdata_orig = cdata
energy_in = np.sum(np.abs(cdata.E_in[0])**2 + np.abs(cdata.E_in[1])**2)/(cfiber.glova.symbolrate*cfiber.glova.sps) mean_power_in = np.sum(pypho.functions.getpower_W(cdata.E_in))
print(f"Energy in: {energy_in} J") print(
f"Mean power in: {mean_power_in:.3e} W ({pypho.functions.W_to_dBm(mean_power_in):.3e} dBm)"
)
cfiber() cfiber()
energy_out = np.sum(np.abs(cdata.E_out[0])**2 + np.abs(cdata.E_out[1])**2)/(cfiber.glova.symbolrate*cfiber.glova.sps)
print(f"Energy out: {energy_out} J")
input_override = cdata.E_out mean_power_out = np.sum(pypho.functions.getpower_W(cdata.E_out))
print(
f"Mean power out: {mean_power_out:.3e} W ({pypho.functions.W_to_dBm(mean_power_out):.3e} dBm)"
)
input_override = (cdata.E_out, noise)
cdata.E_in = cdata_orig.E_in cdata.E_in = cdata_orig.E_in
config['fiber']['length'] = lengths[lind] config["fiber"]["length"] = lengths[lind]
E_tmp = [{'E': cdata.E_out, 'noise': noise*(-cfiber.params.l*cfiber.params.alpha)}]
E_tmp = edfa(E=E_tmp)
cdata.E_out = E_tmp[0]['E']
save_data(cdata, config) save_data(cdata, config)
in_out_eyes(cfiber, cdata)
def single_run_with_plot(config):
cfiber, cdata, noise, edfa = initialize_fiber_and_data(config)
mean_power_in = np.sum(pypho.functions.getpower_W(cdata.E_in))
print(
f"Mean power in: {mean_power_in:.3e} W ({pypho.functions.W_to_dBm(mean_power_in):.3e} dBm)"
)
cfiber()
mean_power_out = np.sum(pypho.functions.getpower_W(cdata.E_out))
print(
f"Mean power out: {mean_power_out:.3e} W ({pypho.functions.W_to_dBm(mean_power_out):.3e} dBm)"
)
E_tmp = [{'E': cdata.E_out, 'noise': noise*(-cfiber.params.l*cfiber.params.alpha)}]
E_tmp = edfa(E=E_tmp)
cdata.E_out = E_tmp[0]['E']
save_data(cdata, config)
in_out_eyes(cfiber, cdata)
def in_out_eyes(cfiber, cdata):
fig, axs = plt.subplots(2, 2, sharex=True, sharey=True)
eye_head = min(cfiber.glova.nos, 2000)
symbolrate_scale = 1e12
amplitude_scale = 1e3
plot_eye_diagram(
amplitude_scale * np.abs(cdata.E_in[0]) ** 2,
2 * cfiber.glova.sps,
normalize=False,
samplerate=cfiber.glova.symbolrate * cfiber.glova.sps / symbolrate_scale,
head=eye_head,
ax=axs[0][0],
show=False,
)
plot_eye_diagram(
amplitude_scale * np.abs(cdata.E_out[0]) ** 2,
2 * cfiber.glova.sps,
normalize=False,
samplerate=cfiber.glova.symbolrate * cfiber.glova.sps / symbolrate_scale,
head=eye_head,
ax=axs[0][1],
color="C1",
show=False,
)
plot_eye_diagram(
amplitude_scale * np.abs(cdata.E_in[1]) ** 2,
2 * cfiber.glova.sps,
normalize=False,
samplerate=cfiber.glova.symbolrate * cfiber.glova.sps / symbolrate_scale,
head=eye_head,
ax=axs[1][0],
show=False,
)
plot_eye_diagram(
amplitude_scale * np.abs(cdata.E_out[1]) ** 2,
2 * cfiber.glova.sps,
normalize=False,
samplerate=cfiber.glova.symbolrate * cfiber.glova.sps / symbolrate_scale,
head=eye_head,
ax=axs[1][1],
color="C1",
show=False,
)
title_map = [
["Input x", "Output x"],
["Input y", "Output y"],
]
title_map = np.array(title_map)
for ax, title in zip(axs.flatten(), title_map.flatten()):
ax.grid(True)
ax.set_xlabel("Time [ps]")
ax.set_ylabel("Power [mW]")
ax.set_title(title)
fig.tight_layout()
plt.show()
def plot_eye_diagram(
signal: np.ndarray,
eye_width,
offset=0,
*,
head=None,
samplerate=1,
normalize=True,
ax=None,
color="C0",
show=True,
):
ax = ax or plt.gca()
if head is not None:
signal = signal[: head * eye_width]
if normalize:
signal = signal / np.max(signal)
slices = np.lib.stride_tricks.sliding_window_view(signal, eye_width + 1)[
offset % (eye_width + 1) :: eye_width
]
plt_ax = np.arange(-eye_width // 2, eye_width // 2 + 1) / samplerate
for slice in slices:
ax.plot(plt_ax, slice, color=color, alpha=0.1)
ax.grid()
if show:
plt.show()
if __name__ == "__main__": if __name__ == "__main__":
config = get_config() config = get_config()
length_loop(config) length_ranges = [1, 10, 100, 1000, 10000]
length_ranges = [1000, 10000]
length_scales = [1, 2, 5]
# cfiber, cdata = initialize_fiber_and_data(config) lengths = [
# cfiber() length_scale * length_range
for length_range in length_ranges
for length_scale in length_scales
]
lengths.append(max(length_ranges))
# energy_in = np.sum(np.abs(cdata.E_in[0])**2 + np.abs(cdata.E_in[1])**2)/(cfiber.glova.symbolrate*cfiber.glova.sps) # length_loop(config, lengths)
# energy_out = np.sum(np.abs(cdata.E_out[0])**2 + np.abs(cdata.E_out[1])**2)/(cfiber.glova.symbolrate*cfiber.glova.sps)
# print(f"Energy in: {energy_in} J")
# print(f"Energy out: {energy_out} J")
# save_data(cdata, config)
# fig, axs = plt.subplots(2, 1, sharex=True, sharey=True) single_run_with_plot(config)
# xax = np.linspace(0, cfiber.glova.nos, cfiber.glova.nos*cfiber.glova.sps)-0.5
# axs[0].plot(xax,np.abs(cdata.E_in[0])**2)
# axs[0].plot(xax,np.abs(cdata.E_out[0])**2)
# axs[0].set_title("x")
# axs[0].grid()
# axs[1].plot(xax,np.abs(cdata.E_in[1])**2)
# axs[1].plot(xax,np.abs(cdata.E_out[1])**2)
# axs[1].set_title("y")
# axs[1].grid()
# plt.show()

View File

@@ -1,8 +1,6 @@
[glova] [glova]
; sps = 256
; nos = 2**17
sps = 128
nos = 2**14 nos = 2**14
sps = 128
f0 = 193414489032258.06 f0 = 193414489032258.06
; -> delta0 = 1550.0 nm ; -> delta0 = 1550.0 nm
symbolrate = 10e9 symbolrate = 10e9
@@ -11,9 +9,9 @@ flags = "FFTW_PATIENT"
nthreads = 32 nthreads = 32
[fiber] [fiber]
length = 100000 length = 100
gamma = 0 gamma = 0
alpha = 0.2 alpha = 0
D = 17 D = 17
; 1700 ps/nm/km @ 1 km length is equivalent to 17 ps/nm/km @ 100 km length but the simulation is way faster ; 1700 ps/nm/km @ 1 km length is equivalent to 17 ps/nm/km @ 100 km length but the simulation is way faster
S = 0 S = 0
@@ -21,15 +19,22 @@ birefsteps = 0
; birefseed = 0xC0FFEE ; birefseed = 0xC0FFEE
[signal] [signal]
seed = 0xC0FFEE
modulation = "pam" modulation = "pam"
mod_order = 4 mod_order = 4
mod_depth = 1 mod_depth = 0.8
laser_power = 0
seed = 0xC0FFEE
pulse_shape = "gauss"
fwhm = 0.33
max_jitter=0.02 max_jitter=0.02
; jitter_seed = 0xC0FFEE ; jitter_seed = 0xC0FFEE
[script] laser_power = 0
data_dir = "/home/suppl/.pypho/data" edfa_power = 3
edfa_nf = 5
pulse_shape = "gauss"
fwhm = 0.33
[data]
dir = "data"
npy_dir = "npys"