Skip to content

Commit 58756d9

Browse files
Merge: opticomlib-v1.5.0
2 parents 6636b49 + e44df3b commit 58756d9

File tree

4 files changed

+80
-75
lines changed

4 files changed

+80
-75
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
**/__pycache__/*
22
test*.py
3+
test*.ipynb
34
build/*
45
dist/*
56
opticomlib.egg-info/*

examples/ook_transmision.py

Lines changed: 57 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,83 @@
1-
from opticomlib.ook import (
2-
DSP,
3-
THRESHOLD_EST,
4-
BER_analizer,
1+
"""
2+
This example will simulate the transmission over 50 km of SMF optical fiber of a 10 Gbps OOK
3+
signal with a PRBS of 2^7-1 bits. NRZ modulation with gaussian pulse shaping will be used.
4+
5+
required opticomlib-v1.5
6+
"""
7+
8+
import opticomlib.ook as ook
9+
10+
import opticomlib.devices as dvs
11+
12+
from opticomlib import (
13+
dbm,
14+
idbm,
15+
optical_signal,
16+
gv,
517
theory_BER
618
)
719

8-
from opticomlib.devices import (
9-
PRBS,
10-
DAC,
11-
MODULATOR,
12-
FIBER,
13-
PD,
14-
GET_EYE,
15-
gv
16-
)
20+
nm = 1e-9
1721

1822
import numpy as np
19-
from numpy.fft import fft, fftshift
2023
import matplotlib.pyplot as plt
21-
from scipy.constants import k as kB, e
2224

23-
"""
24-
En este ejemplo se simulará la transmisión sobre 50 km de fibra óptica SMF de una señal OOK de 10 Gbps con un PRBS de 2^7-1 bits.
25-
Se utilizará un DAC con una frecuencia de muestreo de 20 GSPS y una modulación NRZ.
26-
"""
2725

28-
# Parámetros de la simulación
29-
gv(sps=16, R=1e9)
26+
# Simulation parameters
27+
gv(sps=64, R=10e9, wavelength=1550*nm, Vpi=5).print()
3028

3129
# prbs
32-
tx_seq = PRBS(order=15)
30+
tx_seq = dvs.PRBS(order=7, len=2**10)
3331

34-
# DAC y pulse shaping
35-
dig_signal = DAC(tx_seq, Vout=1, pulse_shape='rect')
32+
# DAC and pulse shaping
33+
v = dvs.DAC(~tx_seq, Vout=gv.Vpi, pulse_shape='gaussian')
3634

37-
# modulador
38-
mod_signal = MODULATOR(dig_signal, p_laser=-21)
35+
# optical source
36+
cw_laser = optical_signal(np.ones_like(v.signal)*idbm(-6)**0.5) # 5 dBm CW optical source, 1-polarization
3937

40-
# fibra óptica
41-
fiber_signal = FIBER(mod_signal, length=50, alpha=0.1, beta_2=20, gamma=2, show_progress=True)
38+
# Mach-Zehnder modulator
39+
mod_signal = dvs.MZM(cw_laser, v, bias=0, Vpi=gv.Vpi, loss_dB=1, ER_dB=26)
4240

43-
# fotodetector
44-
pd_signal = PD(fiber_signal, BW=gv.R*0.75, responsivity=1, noise='all')
41+
# optical fiber
42+
fiber_signal = dvs.FIBER(mod_signal, length=50, alpha=0.2, beta_2=-20, gamma=2, show_progress=True)
43+
P_avg = dbm( fiber_signal.power() )
4544

46-
# parámetros del diagrama de ojos
47-
eye_ = GET_EYE(pd_signal, sps_resamplig=128)
45+
# photo-detector
46+
pd_signal = dvs.PD(fiber_signal, BW=gv.R*0.75, r=1, include_noise='all')
4847

4948
# DSP
50-
rx_seq = DSP(pd_signal, eye_)
49+
rx_seq, eye_, rth = ook.DSP(pd_signal) # return received bits, eye diagram and decision threshold
5150

5251
# BER
53-
ber = BER_analizer('counter', Tx=tx_seq, Rx=rx_seq)
54-
55-
56-
# Cálculo teórico de la BER
57-
58-
59-
responsivity = 1 # Responsividad del fotodetector
60-
T = 300 # Temperatura equivalente del receptor
61-
BW = gv.R*0.75 # Ancho de banda del receptor
62-
R_load = 50 # Resistencia de carga del fotodetector
63-
64-
mu0 = 0
65-
mu1 = fiber_signal.power('signal')[0] * responsivity * 2
66-
67-
sT = (4*kB*T*BW/R_load)**0.5
68-
sS = 2*e*mu1*BW
69-
70-
s0 = sT
71-
s1 = (sT**2 + sS**2)**0.5
72-
73-
ber_theory = theory_BER(mu0, mu1, s0, s1)
52+
ber = ook.BER_analizer('counter', Tx=tx_seq, Rx=rx_seq)
53+
54+
55+
# Theoretical BER
56+
ber_theory = theory_BER(
57+
P_avg = P_avg,
58+
modulation = 'ook',
59+
ER = 26,
60+
amplify=False,
61+
BW_el=0.75*gv.R,
62+
r=1.0,
63+
T=300,
64+
R_L=50,
65+
)
7466

75-
print(f'BER medida: {ber:.2e} ({ber*tx_seq.len():.0f} errores de {tx_seq.len()} bits transmitidos)')
76-
print(f'BER teórica: {ber_theory:.2e}')
67+
print(f'BER counts: {ber:.2e} ({ber*tx_seq.len():.0f} errors of {tx_seq.len()} transmitted bits)')
68+
print(f'BER theoretical: {ber_theory:.2e}')
7769

7870

7971
## PLOTS
72+
mod_signal.psd(label='Fiber input PSD')
73+
fiber_signal.psd(label='Fiber output PSD', grid=True)
8074

81-
mod_signal.psd(label='Señal modulada')
82-
fiber_signal.psd(label='Señal de salida de la fibra')
83-
plt.ylim(1e-11, 1e-1)
84-
plt.grid()
75+
plt.figure()
76+
mod_signal.plot('r', n=50*gv.sps, label = 'Fiber input')
77+
fiber_signal.plot('b', n=50*gv.sps, label='Fiber output', grid=True)
8578

8679
plt.figure()
87-
mod_signal.plot('r', n=50*gv.sps, label = 'Señal modulada')
88-
fiber_signal.plot('b', n=50*gv.sps, label='Señal de salida de la fibra')
89-
pd_signal.plot('g', n=50*gv.sps, label='Señal photodetectada').grid(n=50)
90-
plt.axhline(THRESHOLD_EST(eye_), color='r', linestyle='--', label='Umbral de decisión')
91-
plt.legend(loc='upper right')
92-
93-
eye_.plot(THRESHOLD_EST(eye_))
94-
plt.show()
80+
pd_signal.plot('g', n=50*gv.sps, label='Photodetected signal', grid=True)
81+
plt.axhline(rth, color='r', linestyle='--', label='Decision threshold')
82+
83+
eye_.plot().show()

opticomlib/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from .typing import *
22
from .utils import *
33

4-
__version__ = '1.4.6'
4+
__version__ = '1.5.0'
55

opticomlib/typing.py

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ def __call__(self, sps: int=None, R: float=None, fs: float=None, wavelength: flo
200200
self.sps = int(fs/self.R)
201201

202202
else:
203-
msg = f'`sps`, `R` and `fs` will be set to default values ({self.sps} samples per slot, {self.R:.2e} Hz, {self.fs:.2e} Samples/s)'
203+
msg = f'`sps`, `R` and `fs` will be set to previous values ({self.sps} samples per slot, {self.R:.2e} Hz, {self.fs:.2e} Samples/s)'
204204
warnings.warn(msg)
205205

206206
self.dt = 1/self.fs
@@ -210,11 +210,6 @@ def __call__(self, sps: int=None, R: float=None, fs: float=None, wavelength: flo
210210
self.t = np.linspace(0, N*self.sps*self.dt, N*self.sps, endpoint=True)
211211
self.dw = 2*pi*self.fs/(N*self.sps)
212212
self.w = 2*pi*fftshift(fftfreq(N*self.sps))*self.fs
213-
else:
214-
self.N = None
215-
self.t = None
216-
self.dw = None
217-
self.w = None
218213

219214
self.wavelength = wavelength
220215
self.f0 = c/wavelength
@@ -265,6 +260,26 @@ def print(self):
265260
"""
266261
np.set_printoptions(precision=0, threshold=10)
267262
print(self)
263+
264+
def clean(self):
265+
""" Return all attributes to default values.
266+
267+
"""
268+
self.sps = 16
269+
self.R = 1e9
270+
self.fs = self.R*self.sps
271+
self.dt = 1/self.fs
272+
self.wavelength = 1550e-9
273+
self.f0 = c/self.wavelength
274+
self.N = None
275+
self.t = None
276+
self.dw = None
277+
self.w = None
278+
279+
attrs = [attr for attr in dir(gv) if not callable(getattr(gv, attr)) and not attr.startswith("__") and not (attr in ['sps', 'R', 'fs', 'dt', 'wavelength', 'f0', 'N', 't', 'w', 'dw'])]
280+
281+
for attr in attrs:
282+
delattr(self, attr)
268283

269284

270285
gv = global_variables()

0 commit comments

Comments
 (0)