mirror of
				https://github.com/Telecominfraproject/oopt-gnpy.git
				synced 2025-10-31 01:57:54 +00:00 
			
		
		
		
	 0d3a86f1d8
			
		
	
	0d3a86f1d8
	
	
	
		
			
			* JSON file based on Orange operator typical input Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com> * update of the standalone edfa model creation of a new amlifier2.py = v2 creation of a json parser build_oa_json.py the parser takes OA.json as input and newOA.json as output creation of a pytest verification module amplifier_pytest.py Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com> * put the code together and transmission example script -basic dijkstra propagation -ase noise propagation based on amplifier model -fake nli noise propagation -integration of the amplifier model -interpolation function in the edfa class -code cleaning and units harmonization Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com> * mv transmission_main_example and rm _main__ Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com> * 2nd edfa model and build_oa_json file add a dual coil stages edfa model in case the nf polynomial fit is not known add a build_oa_json file that convert the input files in edfa_config.json file and pre-calculate the nf_model nf1, nf2 and delta_p parameters adding power violation check and input padding (below minimum gain) in the edfa model class Signed-off-by: Jean-Luc Auge <jeanluc.auge@orange.com>
		
			
				
	
	
		
			164 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			164 lines
		
	
	
		
			6.4 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| #!/usr/bin/env python3
 | |
| # -*- coding: utf-8 -*-
 | |
| """
 | |
| Created on Tue Jan 30 12:32:00 2018
 | |
| 
 | |
| @author: jeanluc-auge
 | |
| @comments about amplifier input files from Brian Taylor & Dave Boertjes
 | |
| 
 | |
| update an existing json file with all the 96ch txt files for a given amplifier type
 | |
| amplifier type 'OA_type1' is hard coded but can be modified and other types added
 | |
| returns an updated amplifier json file: output_json_file_name = 'edfa_config.json'
 | |
| """
 | |
| import re
 | |
| import sys
 | |
| import json
 | |
| import numpy as np
 | |
| from gnpy.core.utils import lin2db, db2lin
 | |
| 
 | |
| """amplifier file names
 | |
| convert a set of amplifier files + input json definiton file into a valid edfa_json_file:
 | |
| nf_fit_coeff: NF polynomial coefficients txt file (optional)
 | |
| nf_ripple: NF ripple excursion txt file
 | |
| dfg: gain txt file
 | |
| dgt: dynamic gain txt file
 | |
| input json file in argument (defult = 'OA.json')
 | |
| the json input file should have the following fields:
 | |
| {
 | |
|     "gain_flatmax": 25,
 | |
|     "gain_min": 15,
 | |
|     "p_max": 21,
 | |
|     "nf_fit_coeff": "pNFfit3.txt",
 | |
|     "nf_ripple": "NFR_96.txt", 
 | |
|     "dfg": "DFG_96.txt",
 | |
|     "dgt": "DGT_96.txt",
 | |
|     "nf_model": 
 | |
|         {
 | |
|         "enabled": true,
 | |
|         "nf_min": 5.8,
 | |
|         "nf_max": 10
 | |
|         }
 | |
| }
 | |
| gain_flat = max flat gain (dB)
 | |
| gain_min = min gain (dB) : will consider an input VOA if below (TBD vs throwing an exception)
 | |
| p_max = max power (dBm)
 | |
| nf_fit = boolean (True, False) : 
 | |
|         if False nf_fit_coeff are ignored and nf_model fields are used
 | |
| """
 | |
| 
 | |
| input_json_file_name = "OA.json" #default path
 | |
| output_json_file_name = "edfa_config.json"
 | |
| param_field  ="params"
 | |
| gain_min_field = "gain_min"
 | |
| gain_max_field = "gain_flatmax"
 | |
| gain_ripple_field = "dfg"
 | |
| nf_ripple_field = "nf_ripple"
 | |
| nf_fit_coeff = "nf_fit_coeff"
 | |
| nf_model_field = "nf_model"
 | |
| nf_model_enabled_field = "enabled"
 | |
| nf_min_field  ="nf_min"
 | |
| nf_max_field = "nf_max"
 | |
| 
 | |
| def read_file(field, file_name):
 | |
|     """read and format the 96 channels txt files describing the amplifier NF and ripple
 | |
|         convert dfg into gain ripple by removing the mean component
 | |
|     """
 | |
| 
 | |
|     #with open(path + file_name,'r') as this_file:
 | |
|     #   data = this_file.read()
 | |
|     #data.strip()
 | |
|     #data = re.sub(r"([0-9])([ ]{1,3})([0-9-+])",r"\1,\3",data)
 | |
|     #data = list(data.split(","))
 | |
|     #data = [float(x) for x in data]
 | |
|     data = np.loadtxt(file_name)
 | |
|     if field == gain_ripple_field or field == nf_ripple_field:
 | |
|         #consider ripple excursion only to avoid redundant information
 | |
|         #because the max flat_gain is already given by the 'gain_flat' field in json
 | |
|         #remove the mean component
 | |
|         data = data - data.mean()
 | |
|     data = data.tolist()
 | |
|     return data
 | |
| 
 | |
| def nf_model(amp_dict):
 | |
|     if amp_dict[nf_model_field][nf_model_enabled_field] == True:
 | |
|         gain_min = amp_dict[gain_min_field]
 | |
|         gain_max = amp_dict[gain_max_field]
 | |
|         nf_min = amp_dict[nf_model_field][nf_min_field]
 | |
|         nf_max = amp_dict[nf_model_field][nf_max_field]
 | |
|         #use NF estimation model based on NFmin and NFmax in json OA file
 | |
|         delta_p = 5 #max power dB difference between 1st and 2nd stage coils
 | |
|         #dB g1a = (1st stage gain) - (internal voa attenuation)
 | |
|         g1a_min = gain_min - (gain_max-gain_min) - delta_p
 | |
|         g1a_max = gain_max - delta_p
 | |
|         #nf1 and nf2 are the nf of the 1st and 2nd stage coils
 | |
|         #calculate nf1 and nf2 values that solve nf_[min/max] = nf1 + nf2 / g1a[min/max]
 | |
|         nf2 = lin2db((db2lin(nf_min) - db2lin(nf_max)) / (1/db2lin(g1a_max)-1/db2lin(g1a_min)))
 | |
|         nf1 = lin2db(db2lin(nf_min)- db2lin(nf2)/db2lin(g1a_max)) #expression (1)
 | |
| 
 | |
|         """ now checking and recalculating the results:
 | |
|         recalculate delta_p to check it is within [1-6] boundaries
 | |
|         This is to check that the nf_min and nf_max values from the json file
 | |
|         make sense. If not a warning is printed """
 | |
|         if nf1 < 4:
 | |
|             print('1st coil nf calculated value {} is too low: revise inputs'.format(nf1))
 | |
|         if nf2 < nf1 + 0.3 or nf2 > nf1 + 2: 
 | |
|             """nf2 should be with [nf1+0.5 - nf1 +2] boundaries
 | |
|             there shouldn't be very high nf differences between 2 coils
 | |
|             => recalculate delta_p 
 | |
|             """            
 | |
|             nf2 = max(nf2, nf1+0.3)
 | |
|             nf2 = min(nf2, nf1+2)
 | |
|             g1a_max = lin2db(db2lin(nf2) / (db2lin(nf_min) - db2lin(nf1))) #use expression (1)
 | |
|             delta_p = gain_max - g1a_max
 | |
|             g1a_min = gain_min - (gain_max-gain_min) - delta_p
 | |
|             if delta_p < 1 or delta_p > 6:
 | |
|                 #delta_p should be > 1dB and < 6dB => consider user warning if not
 | |
|                 print('1st coil vs 2nd coil calculated DeltaP {} is not valid: revise inputs'
 | |
|                             .format(delta_p))
 | |
|         #check the calculated values for nf1 & nf2:
 | |
|         nf_min_calc = lin2db(db2lin(nf1) + db2lin(nf2)/db2lin(g1a_max))
 | |
|         nf_max_calc = lin2db(db2lin(nf1) + db2lin(nf2)/db2lin(g1a_min))
 | |
|         if (abs(nf_min_calc-nf_min) > 0.01) or (abs(nf_max_calc-nf_max) > 0.01):
 | |
|             print('nf model calculation failed with nf_min {} and nf_max {} calculated'
 | |
|                     .format(nf_min_calc, nf_max_calc))
 | |
|             print('do not use the generated edfa_config.json file')
 | |
|     else :
 | |
|         (nf1, nf2, delta_p) = (0, 0, 0)
 | |
| 
 | |
|     return (nf1, nf2, delta_p)
 | |
| 
 | |
| def input_json(path):
 | |
|     """read the json input file and add all the 96 channels txt files
 | |
|     create the output json file with output_json_file_name"""
 | |
|     with open(path,'r') as edfa_json_file:
 | |
|         amp_text = edfa_json_file.read()
 | |
|     amp_dict = json.loads(amp_text)
 | |
| 
 | |
|     for k, v in amp_dict.items():
 | |
|         if re.search(r'.txt$',str(v)) :
 | |
|             amp_dict[k] = read_file(k, v)
 | |
| 
 | |
|     #calculate nf of 1st and 2nd coil for the nf_model if 'enabled'==true
 | |
|     (nf1, nf2, delta_p) = nf_model(amp_dict)
 | |
|     #rename nf_min and nf_max in nf1 and nf2 after the nf model calculation:
 | |
|     del amp_dict[nf_model_field][nf_min_field]
 | |
|     del amp_dict[nf_model_field][nf_max_field]
 | |
|     amp_dict[nf_model_field]['nf1'] = nf1
 | |
|     amp_dict[nf_model_field]['nf2'] = nf2
 | |
|     amp_dict[nf_model_field]['delta_p'] = delta_p
 | |
|     #rename dfg into gain_ripple after removing the average part:
 | |
|     amp_dict['gain_ripple'] = amp_dict.pop(gain_ripple_field)
 | |
| 
 | |
|     new_amp_dict = {}
 | |
|     new_amp_dict[param_field] = amp_dict
 | |
|     amp_text = json.dumps(new_amp_dict, indent=4)
 | |
|     #print(amp_text)
 | |
|     with  open(output_json_file_name,'w') as edfa_json_file:
 | |
|         edfa_json_file.write(amp_text)
 | |
| 
 | |
| if __name__ == '__main__':
 | |
|     if len(sys.argv) == 2:
 | |
|         path = sys.argv[1]
 | |
|     else:
 | |
|         path = input_json_file_name
 | |
|     input_json(path) |