mirror of
				https://github.com/Telecominfraproject/oopt-gnpy.git
				synced 2025-10-31 01:57:54 +00:00 
			
		
		
		
	strip whitespace
This commit is contained in:
		| @@ -7,11 +7,11 @@ xls to json parser, that can be called directly from the transmission_main_examp | |||||||
| xls examples are meshTopologyExampleV2.xls and CORONET_Global_Topology.xls | xls examples are meshTopologyExampleV2.xls and CORONET_Global_Topology.xls | ||||||
| Require Nodes and Links sheets, Eqpt sheet is optional | Require Nodes and Links sheets, Eqpt sheet is optional | ||||||
| *in Nodes sheet, only the 'City' column is mandatory. The column 'Type' is discovered based | *in Nodes sheet, only the 'City' column is mandatory. The column 'Type' is discovered based | ||||||
| on the topology: degree 2 = ILA, other degrees = ROADM. The value is also corrected if the user  | on the topology: degree 2 = ILA, other degrees = ROADM. The value is also corrected if the user | ||||||
| specifies an ILA of degree != 2. | specifies an ILA of degree != 2. | ||||||
| *In Links sheet only the 3 first columns (Node A, Node Z and east Distance (km)) are mandatory.  | *In Links sheet only the 3 first columns (Node A, Node Z and east Distance (km)) are mandatory. | ||||||
| Missing west information are copied from east information so it is possible to input undir data | Missing west information are copied from east information so it is possible to input undir data | ||||||
| *in Eqpt sheet  | *in Eqpt sheet | ||||||
|  |  | ||||||
| """ | """ | ||||||
| from sys import exit | from sys import exit | ||||||
| @@ -39,19 +39,19 @@ class Link(namedtuple('Link', 'from_city to_city \ | |||||||
|     west_distance west_fiber west_lineic west_con_in west_con_out west_pmd west_cable \ |     west_distance west_fiber west_lineic west_con_in west_con_out west_pmd west_cable \ | ||||||
|     distance_units')): |     distance_units')): | ||||||
|     def __new__(cls, from_city, to_city, |     def __new__(cls, from_city, to_city, | ||||||
|       east_distance, east_fiber='SSMF', east_lineic=0.2,  |       east_distance, east_fiber='SSMF', east_lineic=0.2, | ||||||
|       east_con_in=None, east_con_out=None, east_pmd=0.1, east_cable='',  |       east_con_in=None, east_con_out=None, east_pmd=0.1, east_cable='', | ||||||
|       west_distance='', west_fiber='', west_lineic='',  |       west_distance='', west_fiber='', west_lineic='', | ||||||
|       west_con_in='', west_con_out='', west_pmd='', west_cable='', |       west_con_in='', west_con_out='', west_pmd='', west_cable='', | ||||||
|       distance_units='km'): |       distance_units='km'): | ||||||
|         east_values = [east_distance, east_fiber, east_lineic, east_con_in, east_con_out,  |         east_values = [east_distance, east_fiber, east_lineic, east_con_in, east_con_out, | ||||||
|                         east_pmd, east_cable] |                         east_pmd, east_cable] | ||||||
|         west_values = [west_distance, west_fiber, west_lineic, west_con_in, west_con_out,  |         west_values = [west_distance, west_fiber, west_lineic, west_con_in, west_con_out, | ||||||
|                         west_pmd, west_cable] |                         west_pmd, west_cable] | ||||||
|         default_values = [80,'SSMF',0.2,None,None,0.1,''] |         default_values = [80,'SSMF',0.2,None,None,0.1,''] | ||||||
|         east_values = [x[0] if x[0] != '' else x[1] for x in zip(east_values,default_values)] |         east_values = [x[0] if x[0] != '' else x[1] for x in zip(east_values,default_values)] | ||||||
|         west_values = [x[0] if x[0] != '' else x[1] for x in zip(west_values,east_values)] |         west_values = [x[0] if x[0] != '' else x[1] for x in zip(west_values,east_values)] | ||||||
|         return super().__new__(cls, from_city, to_city, *east_values, *west_values, distance_units)      |         return super().__new__(cls, from_city, to_city, *east_values, *west_values, distance_units) | ||||||
|  |  | ||||||
| class Eqpt(namedtuple('Eqpt', 'from_city to_city \ | class Eqpt(namedtuple('Eqpt', 'from_city to_city \ | ||||||
|     egress_amp_type egress_att_in egress_amp_gain egress_amp_tilt egress_amp_att_out\ |     egress_amp_type egress_att_in egress_amp_gain egress_amp_tilt egress_amp_att_out\ | ||||||
| @@ -64,7 +64,7 @@ class Eqpt(namedtuple('Eqpt', 'from_city to_city \ | |||||||
|             ingress_amp_type, ingress_att_in, ingress_amp_gain, ingress_amp_tilt, ingress_amp_att_out] |             ingress_amp_type, ingress_att_in, ingress_amp_gain, ingress_amp_tilt, ingress_amp_att_out] | ||||||
|         default_values = ['','','',0,0,0,0,'',0,0,0,0] |         default_values = ['','','',0,0,0,0,'',0,0,0,0] | ||||||
|         values = [x[0] if x[0] != '' else x[1] for x in zip(values,default_values)] |         values = [x[0] if x[0] != '' else x[1] for x in zip(values,default_values)] | ||||||
|         return super().__new__(cls, *values)         |         return super().__new__(cls, *values) | ||||||
|  |  | ||||||
| def sanity_check(nodes, nodes_by_city, links_by_city, eqpts_by_city): | def sanity_check(nodes, nodes_by_city, links_by_city, eqpts_by_city): | ||||||
|     try : |     try : | ||||||
| @@ -83,7 +83,7 @@ def sanity_check(nodes, nodes_by_city, links_by_city, eqpts_by_city): | |||||||
|  |  | ||||||
|     for city,link in links_by_city.items(): |     for city,link in links_by_city.items(): | ||||||
|         if nodes_by_city[city].node_type.lower()=='ila' and len(link) != 2: |         if nodes_by_city[city].node_type.lower()=='ila' and len(link) != 2: | ||||||
|             #wrong input: ILA sites can only be Degree 2  |             #wrong input: ILA sites can only be Degree 2 | ||||||
|             # => correct to make it a ROADM and remove entry in links_by_city |             # => correct to make it a ROADM and remove entry in links_by_city | ||||||
|             #TODO : put in log rather than print |             #TODO : put in log rather than print | ||||||
|             print(f'invalid node type ({nodes_by_city[city].node_type})\ |             print(f'invalid node type ({nodes_by_city[city].node_type})\ | ||||||
| @@ -115,7 +115,7 @@ def convert_file(input_filename, filter_region=[]): | |||||||
|     global eqpts_by_city |     global eqpts_by_city | ||||||
|     eqpts_by_city = defaultdict(list) |     eqpts_by_city = defaultdict(list) | ||||||
|     for eqpt in eqpts: |     for eqpt in eqpts: | ||||||
|         eqpts_by_city[eqpt.from_city].append(eqpt)  |         eqpts_by_city[eqpt.from_city].append(eqpt) | ||||||
|  |  | ||||||
|     nodes = sanity_check(nodes, nodes_by_city, links_by_city, eqpts_by_city) |     nodes = sanity_check(nodes, nodes_by_city, links_by_city, eqpts_by_city) | ||||||
|  |  | ||||||
| @@ -148,7 +148,7 @@ def convert_file(input_filename, filter_region=[]): | |||||||
|                                         'latitude':  x.latitude, |                                         'latitude':  x.latitude, | ||||||
|                                         'longitude': x.longitude}}, |                                         'longitude': x.longitude}}, | ||||||
|               'type': 'Fused'} |               'type': 'Fused'} | ||||||
|              for x in nodes_by_city.values() if x.node_type.lower() == 'fused'] +                                     |              for x in nodes_by_city.values() if x.node_type.lower() == 'fused'] + | ||||||
|             [{'uid': f'fiber ({x.from_city} → {x.to_city})-{x.east_cable}', |             [{'uid': f'fiber ({x.from_city} → {x.to_city})-{x.east_cable}', | ||||||
|               'metadata': {'location': midpoint(nodes_by_city[x.from_city], |               'metadata': {'location': midpoint(nodes_by_city[x.from_city], | ||||||
|                                                 nodes_by_city[x.to_city])}, |                                                 nodes_by_city[x.to_city])}, | ||||||
| @@ -171,7 +171,7 @@ def convert_file(input_filename, filter_region=[]): | |||||||
|                          'loss_coef': x.west_lineic, |                          'loss_coef': x.west_lineic, | ||||||
|                          'con_in':x.west_con_in, |                          'con_in':x.west_con_in, | ||||||
|                          'con_out':x.west_con_out} |                          'con_out':x.west_con_out} | ||||||
|             } # missing ILA construction  |             } # missing ILA construction | ||||||
|               for x in links] + |               for x in links] + | ||||||
|             [{'uid': f'egress edfa in {e.from_city} to {e.to_city}', |             [{'uid': f'egress edfa in {e.from_city} to {e.to_city}', | ||||||
|               'metadata': {'location': {'city':      nodes_by_city[e.from_city].city, |               'metadata': {'location': {'city':      nodes_by_city[e.from_city].city, | ||||||
| @@ -193,7 +193,7 @@ def convert_file(input_filename, filter_region=[]): | |||||||
|               'type_variety': e.ingress_amp_type, |               'type_variety': e.ingress_amp_type, | ||||||
|               'operational': {'gain_target': e.ingress_amp_gain, |               'operational': {'gain_target': e.ingress_amp_gain, | ||||||
|                               'tilt_target': e.ingress_amp_tilt} |                               'tilt_target': e.ingress_amp_tilt} | ||||||
|               }               |               } | ||||||
|              for e in eqpts if e.ingress_amp_type.lower() != ''], |              for e in eqpts if e.ingress_amp_type.lower() != ''], | ||||||
|         'connections': |         'connections': | ||||||
|             list(chain.from_iterable([eqpt_connection_by_city(n.city) |             list(chain.from_iterable([eqpt_connection_by_city(n.city) | ||||||
| @@ -205,7 +205,7 @@ def convert_file(input_filename, filter_region=[]): | |||||||
|              for x in nodes_by_city.values() if x.node_type.lower()=='roadm'], |              for x in nodes_by_city.values() if x.node_type.lower()=='roadm'], | ||||||
|             [{'from_node': f'roadm {x.city}', |             [{'from_node': f'roadm {x.city}', | ||||||
|               'to_node':   f'trx {x.city}'} |               'to_node':   f'trx {x.city}'} | ||||||
|              for x in nodes_by_city.values() if x.node_type.lower()=='roadm'])))             |              for x in nodes_by_city.values() if x.node_type.lower()=='roadm']))) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     #print(dumps(data, indent=2)) |     #print(dumps(data, indent=2)) | ||||||
| @@ -235,20 +235,20 @@ def parse_excel(input_filename): | |||||||
|         expected = ['City', 'State', 'Country', 'Region', 'Latitude', 'Longitude'] |         expected = ['City', 'State', 'Country', 'Region', 'Latitude', 'Longitude'] | ||||||
|         if header != expected: |         if header != expected: | ||||||
|             raise ValueError(f'Malformed header on Nodes sheet: {header} != {expected}') |             raise ValueError(f'Malformed header on Nodes sheet: {header} != {expected}') | ||||||
|         """  |         """ | ||||||
|  |  | ||||||
|         nodes = [] |         nodes = [] | ||||||
|         for row in all_rows(nodes_sheet, start=5): |         for row in all_rows(nodes_sheet, start=5): | ||||||
|             nodes.append(Node(*(x.value for x in row[0:NODES_COLUMN]))) |             nodes.append(Node(*(x.value for x in row[0:NODES_COLUMN]))) | ||||||
|         #check input |         #check input | ||||||
|         expected_node_types = ('ROADM', 'ILA', 'FUSED') |         expected_node_types = ('ROADM', 'ILA', 'FUSED') | ||||||
|         nodes = [n._replace(node_type='ILA')  |         nodes = [n._replace(node_type='ILA') | ||||||
|                 if not (n.node_type in expected_node_types) else n for n in nodes] |                 if not (n.node_type in expected_node_types) else n for n in nodes] | ||||||
|  |  | ||||||
|         # sanity check |         # sanity check | ||||||
|         """ |         """ | ||||||
|         header = [x.value.strip() for x in links_sheet.row(4)] |         header = [x.value.strip() for x in links_sheet.row(4)] | ||||||
|         expected = ['Node A', 'Node Z',  |         expected = ['Node A', 'Node Z', | ||||||
|             'Distance (km)', 'Fiber type', 'lineic att', 'Con_in', 'Con_out', 'PMD', 'Cable id', |             'Distance (km)', 'Fiber type', 'lineic att', 'Con_in', 'Con_out', 'PMD', 'Cable id', | ||||||
|             'Distance (km)', 'Fiber type', 'lineic att', 'Con_in', 'Con_out', 'PMD', 'Cable id'] |             'Distance (km)', 'Fiber type', 'lineic att', 'Con_in', 'Con_out', 'PMD', 'Cable id'] | ||||||
|         if header != expected: |         if header != expected: | ||||||
| @@ -280,7 +280,7 @@ def eqpt_connection_by_city(city_name): | |||||||
|     if nodes_by_city[city_name].node_type.lower() in ('ila', 'fused'): |     if nodes_by_city[city_name].node_type.lower() in ('ila', 'fused'): | ||||||
|         # Then len(other_cities) == 2 |         # Then len(other_cities) == 2 | ||||||
|         direction = ['ingress', 'egress'] |         direction = ['ingress', 'egress'] | ||||||
|         for i in range(2):      |         for i in range(2): | ||||||
|             from_ = fiber_link(other_cities[i], city_name) |             from_ = fiber_link(other_cities[i], city_name) | ||||||
|             in_ = eqpt_in_city_to_city(city_name, other_cities[0],direction[i]) |             in_ = eqpt_in_city_to_city(city_name, other_cities[0],direction[i]) | ||||||
|             to_ = fiber_link(city_name, other_cities[1-i]) |             to_ = fiber_link(city_name, other_cities[1-i]) | ||||||
| @@ -334,7 +334,7 @@ def fiber_dest_from_source(city_name): | |||||||
|     destinations = [] |     destinations = [] | ||||||
|     links_from_city = links_by_city[city_name] |     links_from_city = links_by_city[city_name] | ||||||
|     for l in links_from_city: |     for l in links_from_city: | ||||||
|         if l.from_city == city_name:  |         if l.from_city == city_name: | ||||||
|             destinations.append(l.to_city) |             destinations.append(l.to_city) | ||||||
|         else: |         else: | ||||||
|             destinations.append(l.from_city) |             destinations.append(l.from_city) | ||||||
|   | |||||||
| @@ -109,7 +109,7 @@ class Roadm(Node): | |||||||
|                 'metadata'      : { |                 'metadata'      : { | ||||||
|                     'location': self.metadata['location']._asdict() |                     'location': self.metadata['location']._asdict() | ||||||
|                                     } |                                     } | ||||||
|                 }         |                 } | ||||||
|  |  | ||||||
|     def __repr__(self): |     def __repr__(self): | ||||||
|         return f'{type(self).__name__}(uid={self.uid!r}, loss={self.loss!r})' |         return f'{type(self).__name__}(uid={self.uid!r}, loss={self.loss!r})' | ||||||
| @@ -174,7 +174,7 @@ class Fused(Node): | |||||||
|                                nonlinear_interference=pwr.nli/attenuation, |                                nonlinear_interference=pwr.nli/attenuation, | ||||||
|                                amplified_spontaneous_emission=pwr.ase/attenuation) |                                amplified_spontaneous_emission=pwr.ase/attenuation) | ||||||
|             yield carrier._replace(power=pwr) |             yield carrier._replace(power=pwr) | ||||||
|      |  | ||||||
|     def update_pref(self, pref): |     def update_pref(self, pref): | ||||||
|         return pref._replace(p_span0=pref.p0, p_spani=pref.pi - self.loss) |         return pref._replace(p_span0=pref.p0, p_spani=pref.pi - self.loss) | ||||||
|  |  | ||||||
| @@ -192,7 +192,7 @@ class Fiber(Node): | |||||||
|             params = {} |             params = {} | ||||||
|         if 'con_in' not in params: |         if 'con_in' not in params: | ||||||
|             # if not defined in the network json connector loss in/out |             # if not defined in the network json connector loss in/out | ||||||
|             # the None value will be updated in network.py[build_network]  |             # the None value will be updated in network.py[build_network] | ||||||
|             # with default values from eqpt_config.json[Spans] |             # with default values from eqpt_config.json[Spans] | ||||||
|             params['con_in'] = None |             params['con_in'] = None | ||||||
|             params['con_out'] = None |             params['con_out'] = None | ||||||
| @@ -209,8 +209,8 @@ class Fiber(Node): | |||||||
|         self.con_in = self.params.con_in |         self.con_in = self.params.con_in | ||||||
|         self.con_out = self.params.con_out |         self.con_out = self.params.con_out | ||||||
|         self.dispersion = self.params.dispersion  # s/m/m |         self.dispersion = self.params.dispersion  # s/m/m | ||||||
|         self.gamma = self.params.gamma # 1/W/m      |         self.gamma = self.params.gamma # 1/W/m | ||||||
|         self.pch_out = None   |         self.pch_out = None | ||||||
|         # TODO|jla: discuss factor 2 in the linear lineic attenuation |         # TODO|jla: discuss factor 2 in the linear lineic attenuation | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
| @@ -249,15 +249,15 @@ class Fiber(Node): | |||||||
|     def fiber_loss(self): |     def fiber_loss(self): | ||||||
|         # dB fiber loss, not including padding attenuator |         # dB fiber loss, not including padding attenuator | ||||||
|         return self.loss_coef * self.length + self.con_in + self.con_out |         return self.loss_coef * self.length + self.con_in + self.con_out | ||||||
|      |  | ||||||
|     @property |     @property | ||||||
|     def loss(self): |     def loss(self): | ||||||
|         #total loss incluiding padding att_in: useful for polymorphism with roadm loss |         #total loss incluiding padding att_in: useful for polymorphism with roadm loss | ||||||
|         return self.loss_coef * self.length + self.con_in + self.con_out + self.att_in |         return self.loss_coef * self.length + self.con_in + self.con_out + self.att_in | ||||||
|      |  | ||||||
|     @property |     @property | ||||||
|     def passive(self): |     def passive(self): | ||||||
|         return True    |         return True | ||||||
|  |  | ||||||
|     @property |     @property | ||||||
|     def lin_attenuation(self): |     def lin_attenuation(self): | ||||||
| @@ -459,7 +459,7 @@ class Edfa(Node): | |||||||
|         if self.pin_db is None or self.pout_db is None: |         if self.pin_db is None or self.pout_db is None: | ||||||
|             return f'{type(self).__name__} {self.uid}' |             return f'{type(self).__name__} {self.uid}' | ||||||
|         nf = mean(self.nf) |         nf = mean(self.nf) | ||||||
|         return '\n'.join([f'{type(self).__name__} {self.uid}',  |         return '\n'.join([f'{type(self).__name__} {self.uid}', | ||||||
|                           f'  type_variety:           {self.params.type_variety}', |                           f'  type_variety:           {self.params.type_variety}', | ||||||
|                           f'  effective gain(dB):     {self.effective_gain:.2f}', |                           f'  effective gain(dB):     {self.effective_gain:.2f}', | ||||||
|                           f'  (before att_in and before output VOA)', |                           f'  (before att_in and before output VOA)', | ||||||
| @@ -519,13 +519,13 @@ class Edfa(Node): | |||||||
|             g1a = gain_target - self.params.nf_model.delta_p - dg |             g1a = gain_target - self.params.nf_model.delta_p - dg | ||||||
|             nf_avg = lin2db(db2lin(self.params.nf_model.nf1) + db2lin(self.params.nf_model.nf2)/db2lin(g1a)) |             nf_avg = lin2db(db2lin(self.params.nf_model.nf1) + db2lin(self.params.nf_model.nf2)/db2lin(g1a)) | ||||||
|         elif self.params.type_def == 'fixed_gain': |         elif self.params.type_def == 'fixed_gain': | ||||||
|             nf_avg = self.params.nf_model.nf0             |             nf_avg = self.params.nf_model.nf0 | ||||||
|         else: |         else: | ||||||
|             nf_avg = polyval(self.params.nf_fit_coeff, -dg) |             nf_avg = polyval(self.params.nf_fit_coeff, -dg) | ||||||
|         if avg: |         if avg: | ||||||
|             return nf_avg + pad |             return nf_avg + pad | ||||||
|         else: |         else: | ||||||
|             return self.interpol_nf_ripple + nf_avg + pad # input VOA = 1 for 1 NF degradation             |             return self.interpol_nf_ripple + nf_avg + pad # input VOA = 1 for 1 NF degradation | ||||||
|  |  | ||||||
|     def noise_profile(self, df): |     def noise_profile(self, df): | ||||||
|         """ noise_profile(bw) computes amplifier ase (W) in signal bw (Hz) |         """ noise_profile(bw) computes amplifier ase (W) in signal bw (Hz) | ||||||
| @@ -704,7 +704,7 @@ class Edfa(Node): | |||||||
|             yield carrier._replace(power=pwr) |             yield carrier._replace(power=pwr) | ||||||
|  |  | ||||||
|     def update_pref(self, pref): |     def update_pref(self, pref): | ||||||
|         return pref._replace(p_span0=pref.p0,  |         return pref._replace(p_span0=pref.p0, | ||||||
|                             p_spani=pref.pi + self.effective_gain - self.operational.out_voa) |                             p_spani=pref.pi + self.effective_gain - self.operational.out_voa) | ||||||
|  |  | ||||||
|     def __call__(self, spectral_info): |     def __call__(self, spectral_info): | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
| ''' | ''' | ||||||
| nf model parameters calculation | nf model parameters calculation | ||||||
| calculate nf1, nf2 and Delta_P of a 2 coils edfa with internal VOA | calculate nf1, nf2 and Delta_P of a 2 coils edfa with internal VOA | ||||||
| from nf_min and nf_max inputs  | from nf_min and nf_max inputs | ||||||
| ''' | ''' | ||||||
| from numpy import clip, polyval | from numpy import clip, polyval | ||||||
| from sys import exit | from sys import exit | ||||||
| @@ -31,12 +31,12 @@ AmpBase = namedtuple( | |||||||
|     ' nf_model nf_fit_coeff nf_ripple dgt gain_ripple out_voa_auto allowed_for_design') |     ' nf_model nf_fit_coeff nf_ripple dgt gain_ripple out_voa_auto allowed_for_design') | ||||||
| class Amp(AmpBase): | class Amp(AmpBase): | ||||||
|     def __new__(cls, |     def __new__(cls, | ||||||
|             type_variety, type_def, gain_flatmax, gain_min, p_max, nf_model=None,  |             type_variety, type_def, gain_flatmax, gain_min, p_max, nf_model=None, | ||||||
|             nf_fit_coeff=None, nf_ripple=None, dgt=None, gain_ripple=None,  |             nf_fit_coeff=None, nf_ripple=None, dgt=None, gain_ripple=None, | ||||||
|              out_voa_auto=False, allowed_for_design=True): |              out_voa_auto=False, allowed_for_design=True): | ||||||
|         return super().__new__(cls, |         return super().__new__(cls, | ||||||
|             type_variety, type_def, gain_flatmax, gain_min, p_max,  |             type_variety, type_def, gain_flatmax, gain_min, p_max, | ||||||
|             nf_model, nf_fit_coeff, nf_ripple, dgt, gain_ripple,  |             nf_model, nf_fit_coeff, nf_ripple, dgt, gain_ripple, | ||||||
|             out_voa_auto, allowed_for_design) |             out_voa_auto, allowed_for_design) | ||||||
|  |  | ||||||
|     @classmethod |     @classmethod | ||||||
| @@ -162,7 +162,7 @@ def trx_mode_params(equipment, trx_type_variety='', trx_mode='', error_message=F | |||||||
|             print('Computation stopped.') |             print('Computation stopped.') | ||||||
|             exit() |             exit() | ||||||
|         else: |         else: | ||||||
|             # default transponder charcteristics  |             # default transponder charcteristics | ||||||
|             trx_params['frequency'] = {'min': default_si_data.f_min, 'max': default_si_data.f_max} |             trx_params['frequency'] = {'min': default_si_data.f_min, 'max': default_si_data.f_max} | ||||||
|             trx_params['baud_rate'] = default_si_data.baud_rate |             trx_params['baud_rate'] = default_si_data.baud_rate | ||||||
|             trx_params['spacing'] = default_si_data.spacing |             trx_params['spacing'] = default_si_data.spacing | ||||||
| @@ -178,10 +178,10 @@ def trx_mode_params(equipment, trx_type_variety='', trx_mode='', error_message=F | |||||||
|  |  | ||||||
| def automatic_spacing(baud_rate): | def automatic_spacing(baud_rate): | ||||||
|     """return the min possible channel spacing for a given baud rate""" |     """return the min possible channel spacing for a given baud rate""" | ||||||
|     spacing_list = [(38e9,50e9), (67e9,75e9), (92e9,100e9)] #list of possible tuples  |     spacing_list = [(38e9,50e9), (67e9,75e9), (92e9,100e9)] #list of possible tuples | ||||||
|                                                 #[(max_baud_rate, spacing_for_this_baud_rate)] |                                                 #[(max_baud_rate, spacing_for_this_baud_rate)] | ||||||
|     acceptable_spacing_list = list(filter(lambda x : x[0]>baud_rate, spacing_list)) |     acceptable_spacing_list = list(filter(lambda x : x[0]>baud_rate, spacing_list)) | ||||||
|     if len(acceptable_spacing_list) < 1:  |     if len(acceptable_spacing_list) < 1: | ||||||
|         #can't find an adequate spacing from the list, so default to: |         #can't find an adequate spacing from the list, so default to: | ||||||
|         return baud_rate*1.2 |         return baud_rate*1.2 | ||||||
|     else: |     else: | ||||||
|   | |||||||
| @@ -25,7 +25,7 @@ class ConvenienceAccess: | |||||||
|             if abbrev in kwargs: |             if abbrev in kwargs: | ||||||
|                 kwargs[field] = kwargs.pop(abbrev) |                 kwargs[field] = kwargs.pop(abbrev) | ||||||
|         return self._replace(**kwargs) |         return self._replace(**kwargs) | ||||||
|          |  | ||||||
|     #def ptot_dbm(self): |     #def ptot_dbm(self): | ||||||
|     #    p = array([c.power.signal+c.power.nli+c.power.ase for c in self.carriers]) |     #    p = array([c.power.signal+c.power.nli+c.power.ase for c in self.carriers]) | ||||||
|     #    return lin2db(sum(p*1e3)) |     #    return lin2db(sum(p*1e3)) | ||||||
| @@ -64,7 +64,7 @@ def create_input_spectral_information(f_min, roll_off, baud_rate, power, spacing | |||||||
|     pref = lin2db(power * 1e3) |     pref = lin2db(power * 1e3) | ||||||
|     si = SpectralInformation(pref=Pref(pref, pref)) |     si = SpectralInformation(pref=Pref(pref, pref)) | ||||||
|     si = si.update(carriers=[ |     si = si.update(carriers=[ | ||||||
|             Channel(f, (f_min+spacing*f),  |             Channel(f, (f_min+spacing*f), | ||||||
|             baud_rate, roll_off, Power(power, 0, 0)) for f in range(1,nb_channel+1) |             baud_rate, roll_off, Power(power, 0, 0)) for f in range(1,nb_channel+1) | ||||||
|             ]) |             ]) | ||||||
|     return si |     return si | ||||||
|   | |||||||
| @@ -26,7 +26,7 @@ logger = getLogger(__name__) | |||||||
| def load_network(filename, equipment): | def load_network(filename, equipment): | ||||||
|     json_filename = '' |     json_filename = '' | ||||||
|     if filename.suffix.lower() == '.xls': |     if filename.suffix.lower() == '.xls': | ||||||
|         logger.info('Automatically generating topology JSON file')         |         logger.info('Automatically generating topology JSON file') | ||||||
|         json_filename = convert_file(filename) |         json_filename = convert_file(filename) | ||||||
|     elif filename.suffix.lower() == '.json': |     elif filename.suffix.lower() == '.json': | ||||||
|         json_filename = filename |         json_filename = filename | ||||||
| @@ -95,7 +95,7 @@ def select_edfa(gain_target, power_target, equipment): | |||||||
|                 power=min( |                 power=min( | ||||||
|                     pin |                     pin | ||||||
|                     +edfa.gain_flatmax |                     +edfa.gain_flatmax | ||||||
|                     +TARGET_EXTENDED_GAIN,  |                     +TARGET_EXTENDED_GAIN, | ||||||
|                     edfa.p_max |                     edfa.p_max | ||||||
|                     ) |                     ) | ||||||
|                     -power_target, |                     -power_target, | ||||||
| @@ -106,7 +106,7 @@ def select_edfa(gain_target, power_target, equipment): | |||||||
|  |  | ||||||
|     acceptable_gain_list = \ |     acceptable_gain_list = \ | ||||||
|     list(filter(lambda x : x.gain>-TARGET_EXTENDED_GAIN, edfa_list)) |     list(filter(lambda x : x.gain>-TARGET_EXTENDED_GAIN, edfa_list)) | ||||||
|     if len(acceptable_gain_list) < 1:  |     if len(acceptable_gain_list) < 1: | ||||||
|         #no amplifier satisfies the required gain, so pick the highest gain: |         #no amplifier satisfies the required gain, so pick the highest gain: | ||||||
|         gain_max = max(edfa_list, key=itemgetter(2)).gain |         gain_max = max(edfa_list, key=itemgetter(2)).gain | ||||||
|         #pick up all amplifiers that share this max gain: |         #pick up all amplifiers that share this max gain: | ||||||
| @@ -127,10 +127,10 @@ def select_edfa(gain_target, power_target, equipment): | |||||||
|  |  | ||||||
| def set_roadm_loss(network, equipment, pref_ch_db): | def set_roadm_loss(network, equipment, pref_ch_db): | ||||||
|     roadms = [roadm for roadm in network if isinstance(roadm, Roadm)] |     roadms = [roadm for roadm in network if isinstance(roadm, Roadm)] | ||||||
|     power_mode = equipment['Spans']['default'].power_mode     |     power_mode = equipment['Spans']['default'].power_mode | ||||||
|     default_roadm_loss = equipment['Roadms']['default'].gain_mode_default_loss |     default_roadm_loss = equipment['Roadms']['default'].gain_mode_default_loss | ||||||
|     pref_roadm_db = equipment['Roadms']['default'].power_mode_pref |     pref_roadm_db = equipment['Roadms']['default'].power_mode_pref | ||||||
|     roadm_loss = pref_ch_db - pref_roadm_db  |     roadm_loss = pref_ch_db - pref_roadm_db | ||||||
|  |  | ||||||
|     for roadm in roadms: |     for roadm in roadms: | ||||||
|         if power_mode: |         if power_mode: | ||||||
| @@ -165,7 +165,7 @@ def target_power(dp_from_gain, network, node, equipment): #get_fiber_dp | |||||||
|     #print(f'{repr(node)} delta power in:\n{dp}dB') |     #print(f'{repr(node)} delta power in:\n{dp}dB') | ||||||
|  |  | ||||||
|     return dp |     return dp | ||||||
|      |  | ||||||
|  |  | ||||||
| def prev_node_generator(network, node): | def prev_node_generator(network, node): | ||||||
|     """fused spans interest: |     """fused spans interest: | ||||||
| @@ -187,7 +187,7 @@ def next_node_generator(network, node): | |||||||
|         yield next_node |         yield next_node | ||||||
|         yield from next_node_generator(network, next_node) |         yield from next_node_generator(network, next_node) | ||||||
|     else: |     else: | ||||||
|         StopIteration  |         StopIteration | ||||||
|  |  | ||||||
| def span_loss(network, node): | def span_loss(network, node): | ||||||
|     """Fused span interest: |     """Fused span interest: | ||||||
| @@ -197,10 +197,10 @@ def span_loss(network, node): | |||||||
|         prev_node = next(n for n in network.predecessors(node)) |         prev_node = next(n for n in network.predecessors(node)) | ||||||
|         if isinstance(prev_node, Fused): |         if isinstance(prev_node, Fused): | ||||||
|             loss += sum(n.loss for n in prev_node_generator(network, node)) |             loss += sum(n.loss for n in prev_node_generator(network, node)) | ||||||
|     except StopIteration:  |     except StopIteration: | ||||||
|         pass |         pass | ||||||
|     try: |     try: | ||||||
|         next_node = next(n for n in network.successors(node))         |         next_node = next(n for n in network.successors(node)) | ||||||
|         if isinstance(next_node, Fused): |         if isinstance(next_node, Fused): | ||||||
|             loss += sum(n.loss for n in next_node_generator(network, node)) |             loss += sum(n.loss for n in next_node_generator(network, node)) | ||||||
|     except StopIteration: |     except StopIteration: | ||||||
| @@ -209,7 +209,7 @@ def span_loss(network, node): | |||||||
|  |  | ||||||
| def find_first_node(network, node): | def find_first_node(network, node): | ||||||
|     """Fused node interest: |     """Fused node interest: | ||||||
|     returns the 1st node at the origin of a succession of fused nodes  |     returns the 1st node at the origin of a succession of fused nodes | ||||||
|     (aka no amp in between)""" |     (aka no amp in between)""" | ||||||
|     this_node = node |     this_node = node | ||||||
|     for this_node in prev_node_generator(network, node): |     for this_node in prev_node_generator(network, node): | ||||||
| @@ -218,7 +218,7 @@ def find_first_node(network, node): | |||||||
|  |  | ||||||
| def find_last_node(network, node): | def find_last_node(network, node): | ||||||
|     """Fused node interest: |     """Fused node interest: | ||||||
|     returns the last node in a succession of fused nodes  |     returns the last node in a succession of fused nodes | ||||||
|     (aka no amp in between)""" |     (aka no amp in between)""" | ||||||
|     this_node = node |     this_node = node | ||||||
|     for this_node in next_node_generator(network, node): |     for this_node in next_node_generator(network, node): | ||||||
| @@ -231,7 +231,7 @@ def set_amplifier_voa(amp, pref_total_db, power_mode): | |||||||
|         if power_mode: |         if power_mode: | ||||||
|             gain_target = amp.operational.gain_target |             gain_target = amp.operational.gain_target | ||||||
|             pout = pref_total_db + amp.dp_db |             pout = pref_total_db + amp.dp_db | ||||||
|             voa = min(amp.params.p_max-pout,  |             voa = min(amp.params.p_max-pout, | ||||||
|                       amp.params.gain_flatmax-amp.operational.gain_target) |                       amp.params.gain_flatmax-amp.operational.gain_target) | ||||||
|             voa = round2float(max(voa, 0), 0.5) - VOA_MARGIN if amp.params.out_voa_auto else 0 |             voa = round2float(max(voa, 0), 0.5) - VOA_MARGIN if amp.params.out_voa_auto else 0 | ||||||
|             amp.dp_db = amp.dp_db + voa |             amp.dp_db = amp.dp_db + voa | ||||||
| @@ -283,7 +283,7 @@ def set_egress_amplifier(network, roadm, equipment, pref_total_db): | |||||||
|  |  | ||||||
|  |  | ||||||
| def add_egress_amplifier(network, node): | def add_egress_amplifier(network, node): | ||||||
|     next_nodes = [n for n in network.successors(node)  |     next_nodes = [n for n in network.successors(node) | ||||||
|         if not (isinstance(n, Transceiver) or isinstance(n, Fused) or isinstance(n, Edfa))] |         if not (isinstance(n, Transceiver) or isinstance(n, Fused) or isinstance(n, Edfa))] | ||||||
|         #no amplification for fused spans or TRX |         #no amplification for fused spans or TRX | ||||||
|     for i, next_node in enumerate(next_nodes): |     for i, next_node in enumerate(next_nodes): | ||||||
| @@ -393,16 +393,16 @@ def build_network(network, equipment, pref_ch_db, pref_total_db): | |||||||
|     padding = default_span_data.padding |     padding = default_span_data.padding | ||||||
|  |  | ||||||
|     #set raodm loss for gain_mode before to build network |     #set raodm loss for gain_mode before to build network | ||||||
|     set_roadm_loss(network, equipment, pref_ch_db)  |     set_roadm_loss(network, equipment, pref_ch_db) | ||||||
|     fibers = [f for f in network.nodes() if isinstance(f, Fiber)] |     fibers = [f for f in network.nodes() if isinstance(f, Fiber)] | ||||||
|     add_connector_loss(fibers, con_in, con_out, default_span_data.EOL) |     add_connector_loss(fibers, con_in, con_out, default_span_data.EOL) | ||||||
|     add_fiber_padding(network, fibers, padding) |     add_fiber_padding(network, fibers, padding) | ||||||
|     # don't group split fiber and add amp in the same loop  |     # don't group split fiber and add amp in the same loop | ||||||
|     # =>for code clarity (at the expense of speed): |     # =>for code clarity (at the expense of speed): | ||||||
|     for fiber in fibers: |     for fiber in fibers: | ||||||
|         split_fiber(network, fiber, bounds, target_length, equipment) |         split_fiber(network, fiber, bounds, target_length, equipment) | ||||||
|  |  | ||||||
|     amplified_nodes = [n for n in network.nodes()  |     amplified_nodes = [n for n in network.nodes() | ||||||
|                         if isinstance(n, Fiber) or isinstance(n, Roadm)] |                         if isinstance(n, Fiber) or isinstance(n, Roadm)] | ||||||
|     for node in amplified_nodes: |     for node in amplified_nodes: | ||||||
|         add_egress_amplifier(network, node) |         add_egress_amplifier(network, node) | ||||||
| @@ -411,9 +411,9 @@ def build_network(network, equipment, pref_ch_db, pref_total_db): | |||||||
|     for roadm in roadms: |     for roadm in roadms: | ||||||
|         set_egress_amplifier(network, roadm, equipment, pref_total_db) |         set_egress_amplifier(network, roadm, equipment, pref_total_db) | ||||||
|  |  | ||||||
|     #support older json input topology wo Roadms:       |     #support older json input topology wo Roadms: | ||||||
|     if len(roadms) == 0:  |     if len(roadms) == 0: | ||||||
|         trx = [t for t in network.nodes() if isinstance(t, Transceiver)] |         trx = [t for t in network.nodes() if isinstance(t, Transceiver)] | ||||||
|         for t in trx: |         for t in trx: | ||||||
|             set_egress_amplifier(network, t, equipment, pref_total_db)         |             set_egress_amplifier(network, t, equipment, pref_total_db) | ||||||
|  |  | ||||||
|   | |||||||
| @@ -1,7 +1,7 @@ | |||||||
| #!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||||
| # TelecomInfraProject/gnpy/examples | # TelecomInfraProject/gnpy/examples | ||||||
| # Module name : path_requests_run.py | # Module name : path_requests_run.py | ||||||
| # Version :  | # Version : | ||||||
| # License : BSD 3-Clause Licence | # License : BSD 3-Clause Licence | ||||||
| # Copyright (c) 2018, Telecom Infra Project | # Copyright (c) 2018, Telecom Infra Project | ||||||
|  |  | ||||||
| @@ -10,7 +10,7 @@ | |||||||
| @author: jeanluc-auge | @author: jeanluc-auge | ||||||
| read json request file in accordance with: | read json request file in accordance with: | ||||||
|     Yang model for requesting Path Computation |     Yang model for requesting Path Computation | ||||||
|     draft-ietf-teas-yang-path-computation-01.txt.  |     draft-ietf-teas-yang-path-computation-01.txt. | ||||||
| and returns path results in terms of path and feasibility | and returns path results in terms of path and feasibility | ||||||
|  |  | ||||||
| """ | """ | ||||||
| @@ -76,8 +76,8 @@ class Result_element(Element): | |||||||
|         self.computed_path = computed_path |         self.computed_path = computed_path | ||||||
|         hop_type = [] |         hop_type = [] | ||||||
|         for e in computed_path : |         for e in computed_path : | ||||||
|             if isinstance(e, Transceiver) :  |             if isinstance(e, Transceiver) : | ||||||
|                 hop_type.append(' - '.join([path_request.tsp,path_request.tsp_mode]))  |                 hop_type.append(' - '.join([path_request.tsp,path_request.tsp_mode])) | ||||||
|             else: |             else: | ||||||
|                 hop_type.append('not recorded') |                 hop_type.append('not recorded') | ||||||
|         self.hop_type = hop_type |         self.hop_type = hop_type | ||||||
| @@ -203,10 +203,10 @@ class Result_element(Element): | |||||||
|                             ] |                             ] | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                      |  | ||||||
|     @property |     @property | ||||||
|     def json(self): |     def json(self): | ||||||
|         return self.pathresult  |         return self.pathresult | ||||||
|  |  | ||||||
| def compute_constrained_path(network, req): | def compute_constrained_path(network, req): | ||||||
|     trx = [n for n in network.nodes() if isinstance(n, Transceiver)] |     trx = [n for n in network.nodes() if isinstance(n, Transceiver)] | ||||||
| @@ -226,7 +226,7 @@ def compute_constrained_path(network, req): | |||||||
|                 node = next(el for el in roadm if el.uid == f'roadm {n}') |                 node = next(el for el in roadm if el.uid == f'roadm {n}') | ||||||
|             except StopIteration: |             except StopIteration: | ||||||
|                 try: |                 try: | ||||||
|                     node = next(el for el in edfa  |                     node = next(el for el in edfa | ||||||
|                         if el.uid.startswith(f'egress edfa in {n}')) |                         if el.uid.startswith(f'egress edfa in {n}')) | ||||||
|                 except StopIteration: |                 except StopIteration: | ||||||
|                     msg = f'could not find node : {n} in network topology: \ |                     msg = f'could not find node : {n} in network topology: \ | ||||||
| @@ -257,7 +257,7 @@ def compute_constrained_path(network, req): | |||||||
|     #     target=next(el for el in trx if el.uid == req.destination)): |     #     target=next(el for el in trx if el.uid == req.destination)): | ||||||
|     #     print([e.uid for e in p if isinstance(e,Roadm)]) |     #     print([e.uid for e in p if isinstance(e,Roadm)]) | ||||||
|  |  | ||||||
|     return total_path  |     return total_path | ||||||
|  |  | ||||||
| def propagate(path, req, equipment, show=False): | def propagate(path, req, equipment, show=False): | ||||||
|     #update roadm loss in case of power sweep (power mode only) |     #update roadm loss in case of power sweep (power mode only) | ||||||
| @@ -269,13 +269,13 @@ def propagate(path, req, equipment, show=False): | |||||||
|         si = el(si) |         si = el(si) | ||||||
|         if show : |         if show : | ||||||
|             print(el) |             print(el) | ||||||
|     return path     |     return path | ||||||
|  |  | ||||||
|  |  | ||||||
| def jsontocsv(json_data,equipment,fileout): | def jsontocsv(json_data,equipment,fileout): | ||||||
|     # read json path result file in accordance with: |     # read json path result file in accordance with: | ||||||
|     # Yang model for requesting Path Computation |     # Yang model for requesting Path Computation | ||||||
|     # draft-ietf-teas-yang-path-computation-01.txt.  |     # draft-ietf-teas-yang-path-computation-01.txt. | ||||||
|     # and write results in an CSV file |     # and write results in an CSV file | ||||||
|  |  | ||||||
|     mywriter = writer(fileout) |     mywriter = writer(fileout) | ||||||
| @@ -290,32 +290,32 @@ def jsontocsv(json_data,equipment,fileout): | |||||||
|         ['path-route-object']['unnumbered-hop']['node-id'] |         ['path-route-object']['unnumbered-hop']['node-id'] | ||||||
|         destination = p['path-properties']['path-route-objects'][-1]\ |         destination = p['path-properties']['path-route-objects'][-1]\ | ||||||
|         ['path-route-object']['unnumbered-hop']['node-id'] |         ['path-route-object']['unnumbered-hop']['node-id'] | ||||||
|         pth        = ' | '.join([ e['path-route-object']['unnumbered-hop']['node-id']  |         pth        = ' | '.join([ e['path-route-object']['unnumbered-hop']['node-id'] | ||||||
|                  for e in p['path-properties']['path-route-objects']]) |                  for e in p['path-properties']['path-route-objects']]) | ||||||
|  |  | ||||||
|         [tsp,mode] = p['path-properties']['path-route-objects'][0]\ |         [tsp,mode] = p['path-properties']['path-route-objects'][0]\ | ||||||
|         ['path-route-object']['unnumbered-hop']['hop-type'].split(' - ') |         ['path-route-object']['unnumbered-hop']['hop-type'].split(' - ') | ||||||
|          |  | ||||||
|         # find the min  acceptable OSNR, baud rate from the eqpt library based on tsp (tupe) and mode (format) |         # find the min  acceptable OSNR, baud rate from the eqpt library based on tsp (tupe) and mode (format) | ||||||
|         try: |         try: | ||||||
|             [minosnr, baud_rate] = next([m['OSNR'] , m['baud_rate']]   |             [minosnr, baud_rate] = next([m['OSNR'] , m['baud_rate']] | ||||||
|                 for m in equipment['Transceiver'][tsp].mode if  m['format']==mode) |                 for m in equipment['Transceiver'][tsp].mode if  m['format']==mode) | ||||||
|  |  | ||||||
|         # for debug |         # for debug | ||||||
|         # print(f'coucou {baud_rate}') |         # print(f'coucou {baud_rate}') | ||||||
|         except IndexError: |         except IndexError: | ||||||
|             msg = f'could not find tsp : {self.tsp} with mode: {self.tsp_mode} in eqpt library' |             msg = f'could not find tsp : {self.tsp} with mode: {self.tsp_mode} in eqpt library' | ||||||
|              |  | ||||||
|             raise ValueError(msg) |             raise ValueError(msg) | ||||||
|         output_snr = next(e['accumulative-value']  |         output_snr = next(e['accumulative-value'] | ||||||
|             for e in p['path-properties']['path-metric'] if e['metric-type'] == 'SNR@0.1nm') |             for e in p['path-properties']['path-metric'] if e['metric-type'] == 'SNR@0.1nm') | ||||||
|         output_snrbandwidth = next(e['accumulative-value']  |         output_snrbandwidth = next(e['accumulative-value'] | ||||||
|             for e in p['path-properties']['path-metric'] if e['metric-type'] == 'SNR@bandwidth') |             for e in p['path-properties']['path-metric'] if e['metric-type'] == 'SNR@bandwidth') | ||||||
|         output_osnr = next(e['accumulative-value']  |         output_osnr = next(e['accumulative-value'] | ||||||
|             for e in p['path-properties']['path-metric'] if e['metric-type'] == 'OSNR@0.1nm') |             for e in p['path-properties']['path-metric'] if e['metric-type'] == 'OSNR@0.1nm') | ||||||
|         output_osnrbandwidth = next(e['accumulative-value']  |         output_osnrbandwidth = next(e['accumulative-value'] | ||||||
|             for e in p['path-properties']['path-metric'] if e['metric-type'] == 'OSNR@bandwidth') |             for e in p['path-properties']['path-metric'] if e['metric-type'] == 'OSNR@bandwidth') | ||||||
|         power = next(e['accumulative-value']  |         power = next(e['accumulative-value'] | ||||||
|             for e in p['path-properties']['path-metric'] if e['metric-type'] == 'reference_power') |             for e in p['path-properties']['path-metric'] if e['metric-type'] == 'reference_power') | ||||||
|         if isinstance(output_snr, str): |         if isinstance(output_snr, str): | ||||||
|             isok = '' |             isok = '' | ||||||
| @@ -333,5 +333,5 @@ def jsontocsv(json_data,equipment,fileout): | |||||||
|             output_osnr, |             output_osnr, | ||||||
|             output_snrbandwidth, |             output_snrbandwidth, | ||||||
|             output_snr, |             output_snr, | ||||||
|             isok  |             isok | ||||||
|             )) |             )) | ||||||
|   | |||||||
| @@ -61,10 +61,10 @@ def write_csv(obj, filename): | |||||||
|             #main header |             #main header | ||||||
|             w.writerow([data_key]) |             w.writerow([data_key]) | ||||||
|             #sub headers: |             #sub headers: | ||||||
|             headers = [_ for _ in data_list[0].keys()]             |             headers = [_ for _ in data_list[0].keys()] | ||||||
|             w.writerow(headers) |             w.writerow(headers) | ||||||
|             for data_dict in data_list: |             for data_dict in data_list: | ||||||
|                 w.writerow([_ for _ in data_dict.values()])      |                 w.writerow([_ for _ in data_dict.values()]) | ||||||
|  |  | ||||||
| def c(): | def c(): | ||||||
|     """ |     """ | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 James Powell
					James Powell