Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
298969d
Fix path to Raman gain profile
marbre Apr 4, 2019
67841ea
Fixed: BaseExample.evaluate_results(...) was actually showing rx powe…
wahls Apr 8, 2019
8395f0e
Fix attenuation
marbre Jun 5, 2019
52f7df8
added dummy file
Jun 17, 2019
096aea4
modified the DUMMY FILE to see how to update the
Jun 17, 2019
fc294f0
Removed the dummy file.
Jun 17, 2019
1ddb1d9
Added MPSK modulation feature to GuiEtAl2018 ( b-Modulation code)
Jun 18, 2019
b403996
Added matched filtering functionality for the symbol detection in
Jun 18, 2019
4d40282
Added dispersion decreasing fiber function.
Jun 18, 2019
6c30ee3
Added modified version BuelowArefIdler2016 example, which simulate
Jun 18, 2019
d7cef2f
Added PSK modulation reshaping file, which was left behind in previous
Jun 18, 2019
a082273
Added b Modulation example for propagation in Dispersion Decreasing
Jun 19, 2019
3bc35c7
Normalizing the Rx symbols (constellation) with respect to RMS power of
Jun 21, 2019
cac4988
Made a factor that is used to determine step sizes in Examples/GuiEtA…
wahls Sep 2, 2019
ca8adbe
Started to work on a conventional time-domain transceiver, added Exam…
wahls Sep 2, 2019
0b67f93
Moved functionality to embed/extract symbols in/from sums of shifted …
wahls Sep 4, 2019
9030908
Fixed a typo in the doc of BaseModulator
wahls Oct 5, 2019
8e9f3aa
TimeDomainPulseShaping now implements proper normalization. TimeDomai…
wahls Oct 5, 2019
d4a2d34
TimeDomainPulseShaping example now has an option to enforce that numb…
wahls Oct 7, 2019
a7cd9d2
Reference added for EVM calculation
VinodBajaj Oct 30, 2019
8d14135
Renamed TimeDomainModulator to TimeDomainPulseShapingModulator, added…
wahls Sep 3, 2021
726f7b4
Fixed a numpy.VisibleDeprecationWarning: Creating an ndarray from rag…
wahls Sep 3, 2021
c63c1c7
Registered new components with sphinx, fixed typo in docs, add note t…
wahls Sep 3, 2021
361e23c
Merge pull request #3 from FastNFT/conventional_transceiver
wahls Sep 24, 2021
4993238
Delete DDFDiscSpecModulator.py
VinodBajaj Dec 30, 2021
abcd0ab
Deleted ContSpecModulator
VinodBajaj Dec 30, 2021
4fac965
DDF modulators are deleted.
VinodBajaj Dec 30, 2021
17cc014
Updated DDFssprop
VinodBajaj Dec 30, 2021
300e726
Update DDFSplitStep
VinodBajaj Dec 30, 2021
b81aa25
Update SMFSplitStep
VinodBajaj Dec 30, 2021
db3270a
Binary files update
VinodBajaj Dec 30, 2021
3b29491
polishing the files for better description
VinodBajaj Dec 30, 2021
ad45ec4
Merge pull request #4 from VinodBajaj/DDF
VinodBajaj Dec 30, 2021
143f707
Update index.rst
VinodBajaj May 18, 2022
5728b1e
removed cache files
Feb 29, 2024
4397ceb
Fixed: example.alpha being a 1d array caused problems with newer Pyth…
Feb 29, 2024
898601a
added the BajajEtAl2020_... examples to the documentation
Mar 1, 2024
24da5ea
removed some files that appear to be left-overs from testing
Mar 1, 2024
e3a53bb
Merge branch 'develop' into DDF
Mar 1, 2024
91d7211
corrected two merge issues
Mar 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions Constellations/ReshapedPSKConstellation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# This file is part of NFDMLab.
#
# NFDMLab is free software; you can redistribute it and/or
# modify it under the terms of the version 2 of the GNU General
# Public License as published by the Free Software Foundation.
#
# NFDMLab is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with NFDMLab; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
# Contributors:
# Sander Wahls (TU Delft) 2018
# Shrinivas Chimmalgi (TU Delft) 2018

import numpy as np
import scipy.integrate as integrate
import warnings

from Constellations import MPSKConstellation

class ReshapedPSKConstellation(MPSKConstellation):
"""Reshaped phase shift keying (PSK) constellation (implements
BaseConstellation).

The goal of the reshaping procedure is to fit the average (normalized)
energy of the generated pulses to a desired value Ed. For details, see
Gui et al., Opt. Express 26(21), 2018.
"""

def __init__(self, m, b0_fun, Ed, bnds):
"""Constructor for a reshaped m x n PSK constellation.

Parameters
----------
m : int

b0_fun : function
Carrier waveform. The function should maps any input vector of the
type numpy.array(float), which represents a vector of nonlinear
frequencies xi, to a output vector of the type numpy.array(complex),
which represents the values of the carrier waveform at these xi.
Ed : float
Desired average energy of the generated pulses (with respect to
normalized units). Should be positive.
bnds : numpy.array(float)
Vector with two entries [a,b], which are used as initial bounds in
the bisection produdure based on which the constellation is
reshaped. It should be 0<a<b.
"""
super().__init__(m)
alphabet0 = self.alphabet / np.max(np.abs(self.alphabet))
niter = 35
abs_vals = np.unique(np.abs(alphabet0))
M = np.size(alphabet0)
K = np.size(abs_vals)
for k in range(0, K):
Ek_target = Ed*M*abs_vals[k]**2/(np.linalg.norm(alphabet0)**2)
lb = bnds[0]
ub = bnds[1]
for iter in range(0, niter):
Ak = 0.5*(lb + ub)
with warnings.catch_warnings():
warnings.simplefilter("ignore")
I = integrate.quad(lambda xi: -np.log(1 - Ak*(abs_vals[k]**2)*(np.abs(b0_fun(xi))**2)), -np.inf, np.inf)
Ek = I[0]/np.pi
if Ek<Ek_target:
lb = Ak
else:
ub = Ak
if Ek<0.95*Ek_target:
raise ValueError('scale_modulation failed - try to increase upper bound')
Ak = lb
idx = np.abs(alphabet0) == abs_vals[k]
self._alphabet[idx] = np.sqrt(Ak)*alphabet0[idx]
self._name = "Reshaped %d-PSK Constellation" % self.size()
1 change: 1 addition & 0 deletions Constellations/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@
from Constellations.QAMConstellation import QAMConstellation
from Constellations.MPSKConstellation import MPSKConstellation
from Constellations.ReshapedQAMConstellation import ReshapedQAMConstellation
from Constellations.ReshapedPSKConstellation import ReshapedPSKConstellation
9 changes: 9 additions & 0 deletions Documentation/examples.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,12 @@ Examples

.. autoclass:: Examples.GuiEtAl2018
:members:

.. autoclass:: Examples.BajajEtAl2020_b_modulation
:members:

.. autoclass:: Examples.BajajEtAl2020_multi_soliton
:members:

.. autoclass:: Examples.TimeDomainPulseShaping
:members:
2 changes: 1 addition & 1 deletion Documentation/getting_started.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Users can create a instance of an existing example class in order to perform sim
.. code-block:: python

import Examples
ex = Example.BuelowArefIdler2016()
ex = Examples.BuelowArefIdler2016()

A list of existing examples is provided under :doc:`examples`.

Expand Down
3 changes: 3 additions & 0 deletions Documentation/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ paper:
<https://doi.org/10.1364/OFC.2019.M3Z.13>`_ Optical Networking and
Communication Conference & Exhibition (OFC), paper M3Z.13, Mar. 2019.

Please consider citing this paper if NFDMLab contributes to your research.

First Steps
-----------

Expand All @@ -37,6 +39,7 @@ Acknowledgements
----------------

- This project has received funding from the European Research Council (ERC) under the European Union’s Horizon 2020 research and innovation programme (grant agreement No 716669).
- This project has received funding from the European Union’s Horizon 2020 research and innovation programme under the Marie Skłodowska-Curie grant agreement No 766115.
- Fiber-topic transmissions are simulated using a slightly modified port of `SSPROP <https://www.photonics.umd.edu/software/ssprop/>`_.
- Alexander Geisler has contributed a Raman gain profile.

Expand Down
4 changes: 4 additions & 0 deletions Documentation/modulators.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,9 @@ Modulators
:special-members:

.. autoclass:: Modulators.DiscSpecModulator
:members:
:special-members:

.. autoclass:: Modulators.TimeDomainPulseShapingModulator
:members:
:special-members:
58 changes: 58 additions & 0 deletions Example_b_Modulation_SMF_DDF.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import Examples
import sys
import numpy as np
import scipy.io as scio

Fiber_type = 'DDF' # 'DDF' or 'SSMF'

if Fiber_type == 'DDF':
example = Examples.BajajEtAl2020_b_modulation()
example.n_steps_per_span = 500
example.path_average = False
example.beta2 = -25.491e-27
example.gamma = 1.3e-3
elif Fiber_type == 'SSMF':
example = Examples.GuiEtAl2018()
example.n_steps_per_span = 200
Factor_gamma_eff_80km = 0.2646
example.beta2 = -25.49e-27*Factor_gamma_eff_80km #-8.414e-27
example.gamma = 1.3e-3
example.path_average = True
else:
raise Exception('Specify the correct fiber type')
example.n_spans = 1
#example.gamma = 1.3e-3 #2.2e-3
#example.alpha = 0
example.constellation_type = 'PSK'
example.constellation_level = 8
example.n_symbols_per_block = 9
example.fiber_span_length = 80e3
example.noise = True
example.noise_figure = 6
example.tx_bandwidth = 40e9
example.rx_bandwidth = 40e9
example.Ed = 16
example.reconfigure()
runs = 10
tx_data, rx_data = example.run(runs)


#Rotation compensation
###########################################################################################
#Compensate for the rotation mismatch
RotationCompensation = 1
if RotationCompensation == 1:
#Find the average rotation error
Rotation_Error = (np.angle(rx_data["symbols"])-np.angle(tx_data["symbols"])-np.pi)%(2*np.pi)+np.pi
MeanRotation = np.mean(Rotation_Error)
#Compensate for the average rotation
rx_data["symbols"] = rx_data["symbols"] * np.exp(-1j*MeanRotation)
###########################################################################################

#Plot the result

example.evaluate_results(tx_data, rx_data)


print('Energy per carrier',example.Ed)
print('Fiber type : ', Fiber_type)
178 changes: 178 additions & 0 deletions Examples/BajajEtAl2020_b_modulation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
# This file is part of NFDMLab.
#
# NFDMLab is free software; you can redistribute it and/or
# modify it under the terms of the version 2 of the GNU General
# Public License as published by the Free Software Foundation.
#
# NFDMLab is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public
# License along with NFDMLab; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA
#
# Contributors:
# Vinod Bajaj (TU Delft) 2019, 2021
# Sander Wahls (TU Delft) 2018-2019
# Shrinivas Chimmalgi (TU Delft) 2018
# Sander Wahls (KIT), 2024

import numpy as np
import math

from Examples import BaseExample

class BajajEtAl2020_b_modulation(BaseExample):
'''This example recreates the b-modulation transmission in dispersion-decreasing
fiber from the paper

"Exact NFDM Transmission in the Presence of Fiber-Loss" by V. Bajaj,
S. Chimmalgi, V. Aref, and S. Wahls,

published in the Journal of Lightwave Technology 38(11), 2020.'''

def __init__(self):
# Fiber parameters

self.beta2 = -25.491e-27
"""Dispersion parameter in s**2/m."""

self.gamma = 1.3e-3
"""Nonlinearity parameter in (W m)**(-1)."""

self.fiber_type = "DDF"
"""Fiber type: "DDF" for dispersion decreasing fiber or "SSMF" for standard single mode fiber."""

self.Tscale = 1.25e-9 # s
"""Time scale used during normalization in s."""

self.alpha = 0.2e-3
"""Loss coefficient in 1/m."""

self.post_boost = True
"""Boost at the end of each span (lumped amplification). True or
False."""

self.path_average = False
"""Use path-averaged fiber parameters during normalization. True or
False."""

self.noise = True
"""Add ASE noise during amplification (only if post_boost == True).
True or False."""

self.noise_figure = 3
"""Noise figure in dB."""

self.n_spans = 8
"""Number of fiber spans."""

self.fiber_span_length = 80e3
"""Length of a fiber span in m."""

self.n_steps_per_span = 500
"""Number of spatial steps per span during the numerical simulation of
the fiber transmission."""

# Modulator parameters
self.constellation_type = 'PSK'
"""We support 'QAM' and 'PSK'."""

self.constellation_level = 16
"""Level of the QAM constellation used as input for the reshaping
process (4, 16, 256, ...)."""

self.n_symbols_per_block = 9
"""Number of carriers."""

self.Ed = 4
"""Desired average pulse energy in normalized units. Used during the
reshaping of the constellation. (See the paper for details.)"""

# Filters

self.tx_bandwidth = 33e9
"""Bandwidth of the (ideal) low-pass filter at the transmitter in Hz."""

self.rx_bandwidth = 33e9 # in GHz
"""Bandwidth of the (ideal) low-pass filter at the receiver in Hz."""

self.reconfigure()

def reconfigure(self):
distance = self.n_spans*self.fiber_span_length #m
from Modulators.CarrierWaveforms import flat_top
carrier_waveform = lambda xi : flat_top(xi, T0)
self._carrier_spacing = 15.0
T0 = 4.5
T = np.array([-2.25, 2.25]) # changed from -1 1

# Normalization

if self.path_average == True:
from Normalization import Lumped
self._normalization = Lumped(self.beta2,
self.gamma,
self.Tscale,
alpha=np.mean(self.alpha)*np.log(10)*0.1,
zamp=self.fiber_span_length)
else:
from Normalization import Lossless
self._normalization = Lossless(self.beta2, self.gamma, self.Tscale)

# Constellation
if self.constellation_type == 'QAM':
from Constellations import ReshapedQAMConstellation
m = int(math.sqrt(self.constellation_level))
assert self.constellation_level == m*m
bnds = np.array([0, 4/np.abs(carrier_waveform(0.0))])
self._constellation = ReshapedQAMConstellation(m, m,carrier_waveform,self.Ed, bnds)
elif self.constellation_type == 'PSK':
from Constellations import ReshapedPSKConstellation
bnds = np.array([0,4/np.abs(carrier_waveform(0.0))])
self._constellation = ReshapedPSKConstellation(self.constellation_level,carrier_waveform,self.Ed,bnds)
else:
raise Exception('Constellation not supported')


from Links.DDF_profile import Get_Beta_Gamma_Profile
dz = self.fiber_span_length/self.n_steps_per_span
profile = Get_Beta_Gamma_Profile(self.alpha * np.log(10) * 0.1, self.beta2, self.gamma, dz,
self.n_steps_per_span)



# Modulator

from Modulators import ContSpecModulator
normalized_distance = self.normalization.norm_dist(distance)
normalized_duration = T[1] - T[0]
required_normalized_dt = normalized_duration/self.n_symbols_per_block/128 # originally it was 8 instead of 128 in denominator
required_dxi = self._carrier_spacing / 8
self._modulator = ContSpecModulator(carrier_waveform,
self._carrier_spacing,
self.n_symbols_per_block,
normalized_distance*profile['avg_D_z'],
T,
required_normalized_dt,
required_dxi,
"b",
matched_filter_percentage=70)

# Link

from Links import SMFSplitStep
dt = self._normalization.denorm_time(self.modulator.normalized_dt)
self._link = SMFSplitStep(dt, dz, self.n_steps_per_span, self.fiber_type,
self.alpha, self.beta2, self.gamma, False, self.n_spans,
self.post_boost, self.noise, self.noise_figure)

# Filters

from Filters import PassThrough
self._tx_filter = PassThrough()
from Filters import FFTLowPass
self._rx_filter = FFTLowPass(self.rx_bandwidth/2, dt)
Loading