mirror of
https://github.com/Telecominfraproject/oopt-gnpy.git
synced 2025-11-02 02:57:52 +00:00
code wrap up and edfa model augmentation v2 (#30)
* 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>
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
"dfg": [25.13596985, 25.11822814, 25.09542133, 25.06245771, 25.02602765, 24.99637953, 24.98167255, 24.97530668, 24.98320726, 24.99718565, 25.01757247, 25.03832781, 25.05495585, 25.0670719, 25.07091411, 25.07094365, 25.07114324, 25.07533627, 25.08731018, 25.10313936, 25.12276204, 25.14239479, 25.15945633, 25.17392704, 25.17673767, 25.17037141, 25.15216254, 25.1311431, 25.10802335, 25.08548777, 25.06916675, 25.05848176, 25.05447313, 25.05154441, 25.04946059, 25.04717849, 25.04551656, 25.04467649, 25.0407292, 25.03285408, 25.0234883, 25.01659234, 25.01332136, 25.01123434, 25.01030015, 25.00936548, 25.00873964, 25.00842535, 25.00696466, 25.0040431, 25.00070998, 24.9984232, 24.99306332, 24.98352421, 24.97125103, 24.96038108, 24.94888721, 24.93531489, 24.92131927, 24.90898697, 24.89896514, 24.88958463, 24.8808387, 24.87210092, 24.86462026, 24.85839773, 24.85445838, 24.85155443, 24.85176601, 24.85408014, 24.85909624, 24.86474458, 24.87203486, 24.8803652, 24.88910669, 24.89721313, 24.90282604, 24.9065669, 24.9086508, 24.91093944, 24.91343079, 24.91592344, 24.92155351, 24.93031861, 24.94052812, 24.94904669, 24.95757123, 24.96781845, 24.98180093, 24.99782686, 25.01393183, 25.02809846, 25.04032575, 25.05256981, 25.06479701, 25.07704697],
|
||||
"dgt": [2.714526681131686, 2.705443819238505, 2.6947834587664494, 2.6841217449620203, 2.6681935771243177, 2.6521732021128046, 2.630396440815385, 2.602860350286428, 2.5696460593920065, 2.5364027376452056, 2.499446286796604, 2.4587748041127506, 2.414398437185221, 2.3699990328716107, 2.322373696229342, 2.271520771371253, 2.2174389328192197, 2.16337565384239, 2.1183028432496016, 2.082225099873648, 2.055100772005235, 2.0279625371819305, 2.0008103857988204, 1.9736443063300082, 1.9482128147680253, 1.9245345552113182, 1.9026104247588487, 1.8806927939516411, 1.862235672444246, 1.847275503201129, 1.835814081380705, 1.824381436842932, 1.8139629377087627, 1.8045606557581335, 1.7961751115773796, 1.7877868031023945, 1.7793941781790852, 1.7709972329654864, 1.7625959636196327, 1.7541903672600494, 1.7459181197626403, 1.737780757913635, 1.7297783508684146, 1.7217732861435076, 1.7137640932265894, 1.7057507692361864, 1.6918150918099673, 1.6719047669939942, 1.6460167077689267, 1.6201194134191075, 1.5986915141218316, 1.5817353179379183, 1.569199764184379, 1.5566577309558969, 1.545374152761467, 1.5353620432989845, 1.5266220576235803, 1.5178910621476225, 1.5097346239790443, 1.502153039909686, 1.495145456062699, 1.488134243479226, 1.48111939735681, 1.474100442252211, 1.4670307626366115, 1.4599103316162523, 1.45273959485914, 1.445565137158368, 1.4340878115214444, 1.418273806730323, 1.3981208704326855, 1.3779439775587023, 1.3598972673004606, 1.3439818461440451, 1.3301807335621048, 1.316383926863083, 1.3040618749785347, 1.2932153453410835, 1.2838336236692311, 1.2744470198196236, 1.2650555289898042, 1.2556591482982988, 1.2428104897182262, 1.2264996957264114, 1.2067249615595257, 1.1869318618366975, 1.1672278304018044, 1.1476135933863398, 1.1280891949729075, 1.108555289615659, 1.0895983485572227, 1.0712204022764056, 1.0534217504465226, 1.0356155337864215, 1.017807767853702, 1.0],
|
||||
"nf_fit_coeff": [0.000168241, 0.0469961, 0.0359549, 5.82851],
|
||||
"nf_ripple": [-0.315374332, -0.315374332, -0.3154009157100272, -0.3184914611751095, -0.32158358425400546, -0.3246772861549999, -0.32762368641496226, -0.3205413846123276, -0.31345546385118733, -0.3063659213569748, -0.29920267890990127, -0.27061972852631744, -0.24202215770774693, -0.21340995523361256, -0.18478227130158695, -0.14809761118389625, -0.11139416731807622, -0.07467192527357988, -0.038026748965679924, -0.019958469399422092, -0.0018809287980157928, 0.01620587996057356, 0.03430196400570967, 0.05240733047405406, 0.07052198650959736, 0.079578036683472, 0.08854664736190952, 0.0975198632319653, 0.10649768784154924, 0.0977413804499074, 0.08880343717266004, 0.07986089973284587, 0.0709137645874038, 0.06333589274056531, 0.055756212252058776, 0.04817263174786321, 0.04058514821716236, 0.03338159167571013, 0.026178308595650738, 0.018971315351761126, 0.011760609076833628, 0.01695029492275999, 0.02227499135770144, 0.02760243318910433, 0.03293262254079026, 0.038265561538776145, 0.04360125231127117, 0.03485699074348155, 0.025991055149117932, 0.017120541224980364, 0.008275758735920322, 0.0019423214065246042, -0.004394389017104359, -0.010734375072893196, -0.017077639301414434, -0.02467970289957285, -0.03229797040382168, -0.03992018009047725, -0.04753456632753024, -0.049234003141433724, -0.05093432003654719, -0.05263551769669225, -0.05433759680640246, -0.0560405580509193, -0.057718452237076875, -0.056840590379175944, -0.055962273198734966, -0.05508350034141658, -0.054204271452516814, -0.05839608872695511, -0.06262733016971533, -0.0668607690892037, -0.07090173625606945, -0.05209609730905224, -0.03328068412141294, -0.014455489070928059, 0.004315038757905716, 0.014839202394482527, 0.025368841662503576, 0.03590396083646565, 0.0464445641953214, 0.05699065602246746, 0.06754224060577406, 0.10002709623672751, 0.13258013095133617, 0.1651501336277331, 0.1977371175359939, 0.23194802687829724, 0.26618779883837107, 0.3004454365808535, 0.33472095409250663, 0.35929034770587287, 0.38384389188855605, 0.40841026111391787, 0.43298946543290784, 0.43298946543290784]
|
||||
"nf_ripple": [-0.315374332, -0.315374332, -0.3154009157100272, -0.3184914611751095, -0.32158358425400546, -0.3246772861549999, -0.32762368641496226, -0.3205413846123276, -0.31345546385118733, -0.3063659213569748, -0.29920267890990127, -0.27061972852631744, -0.24202215770774693, -0.21340995523361256, -0.18478227130158695, -0.14809761118389625, -0.11139416731807622, -0.07467192527357988, -0.038026748965679924, -0.019958469399422092, -0.0018809287980157928, 0.01620587996057356, 0.03430196400570967, 0.05240733047405406, 0.07052198650959736, 0.079578036683472, 0.08854664736190952, 0.0975198632319653, 0.10649768784154924, 0.0977413804499074, 0.08880343717266004, 0.07986089973284587, 0.0709137645874038, 0.06333589274056531, 0.055756212252058776, 0.04817263174786321, 0.04058514821716236, 0.03338159167571013, 0.026178308595650738, 0.018971315351761126, 0.011760609076833628, 0.01695029492275999, 0.02227499135770144, 0.02760243318910433, 0.03293262254079026, 0.038265561538776145, 0.04360125231127117, 0.03485699074348155, 0.025991055149117932, 0.017120541224980364, 0.008275758735920322, 0.0019423214065246042, -0.004394389017104359, -0.010734375072893196, -0.017077639301414434, -0.02467970289957285, -0.03229797040382168, -0.03992018009047725, -0.04753456632753024, -0.049234003141433724, -0.05093432003654719, -0.05263551769669225, -0.05433759680640246, -0.0560405580509193, -0.057718452237076875, -0.056840590379175944, -0.055962273198734966, -0.05508350034141658, -0.054204271452516814, -0.05839608872695511, -0.06262733016971533, -0.0668607690892037, -0.07090173625606945, -0.05209609730905224, -0.03328068412141294, -0.014455489070928059, 0.004315038757905716, 0.014839202394482527, 0.025368841662503576, 0.03590396083646565, 0.0464445641953214, 0.05699065602246746, 0.06754224060577406, 0.10002709623672751, 0.13258013095133617, 0.1651501336277331, 0.1977371175359939, 0.23194802687829724, 0.26618779883837107, 0.3004454365808535, 0.33472095409250663, 0.35929034770587287, 0.38384389188855605, 0.40841026111391787, 0.43298946543290784, 0.43298946543290784],
|
||||
"frequencies": []
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
"type": "Fiber",
|
||||
"params": {
|
||||
"length": 80,
|
||||
"loss_coef": 0.2,
|
||||
"length_units": "km"
|
||||
},
|
||||
"metadata": {
|
||||
@@ -23,6 +24,10 @@
|
||||
{
|
||||
"uid": "Edfa1",
|
||||
"type": "Edfa",
|
||||
"operational": {
|
||||
"gain_target": 16,
|
||||
"tilt_target": 0
|
||||
},
|
||||
"config_from_json": "edfa_config.json",
|
||||
"metadata": {
|
||||
"latitude": 2,
|
||||
|
||||
313
examples/edfa_config.json
Normal file
313
examples/edfa_config.json
Normal file
@@ -0,0 +1,313 @@
|
||||
{
|
||||
"params": {
|
||||
"gain_flatmax": 25,
|
||||
"gain_min": 15,
|
||||
"p_max": 21,
|
||||
"nf_fit_coeff": [
|
||||
0.000168241,
|
||||
0.0469961,
|
||||
0.0359549,
|
||||
5.82851
|
||||
],
|
||||
"nf_ripple": [
|
||||
-0.3110761646066259,
|
||||
-0.3110761646066259,
|
||||
-0.31110274831665313,
|
||||
-0.31419329378173544,
|
||||
-0.3172854168606314,
|
||||
-0.32037911876162584,
|
||||
-0.3233255190215882,
|
||||
-0.31624321721895354,
|
||||
-0.30915729645781326,
|
||||
-0.30206775396360075,
|
||||
-0.2949045115165272,
|
||||
-0.26632156113294336,
|
||||
-0.23772399031437283,
|
||||
-0.20911178784023846,
|
||||
-0.18048410390821285,
|
||||
-0.14379944379052215,
|
||||
-0.10709599992470213,
|
||||
-0.07037375788020579,
|
||||
-0.03372858157230583,
|
||||
-0.015660302006048,
|
||||
0.0024172385953583004,
|
||||
0.020504047353947653,
|
||||
0.03860013139908377,
|
||||
0.05670549786742816,
|
||||
0.07482015390297145,
|
||||
0.0838762040768461,
|
||||
0.09284481475528361,
|
||||
0.1018180306253394,
|
||||
0.11079585523492333,
|
||||
0.1020395478432815,
|
||||
0.09310160456603413,
|
||||
0.08415906712621996,
|
||||
0.07521193198077789,
|
||||
0.0676340601339394,
|
||||
0.06005437964543287,
|
||||
0.052470799141237305,
|
||||
0.044883315610536455,
|
||||
0.037679759069084225,
|
||||
0.03047647598902483,
|
||||
0.02326948274513522,
|
||||
0.01605877647020772,
|
||||
0.021248462316134083,
|
||||
0.02657315875107553,
|
||||
0.03190060058247842,
|
||||
0.03723078993416436,
|
||||
0.04256372893215024,
|
||||
0.047899419704645264,
|
||||
0.03915515813685565,
|
||||
0.030289222542492025,
|
||||
0.021418708618354456,
|
||||
0.012573926129294415,
|
||||
0.006240488799898697,
|
||||
-9.622162373026585e-05,
|
||||
-0.006436207679519103,
|
||||
-0.012779471908040341,
|
||||
-0.02038153550619876,
|
||||
-0.027999803010447587,
|
||||
-0.035622012697103154,
|
||||
-0.043236398934156144,
|
||||
-0.04493583574805963,
|
||||
-0.04663615264317309,
|
||||
-0.048337350303318156,
|
||||
-0.050039429413028365,
|
||||
-0.051742390657545205,
|
||||
-0.05342028484370278,
|
||||
-0.05254242298580185,
|
||||
-0.05166410580536087,
|
||||
-0.05078533294804249,
|
||||
-0.04990610405914272,
|
||||
-0.05409792133358102,
|
||||
-0.05832916277634124,
|
||||
-0.06256260169582961,
|
||||
-0.06660356886269536,
|
||||
-0.04779792991567815,
|
||||
-0.028982516728038848,
|
||||
-0.010157321677553965,
|
||||
0.00861320615127981,
|
||||
0.01913736978785662,
|
||||
0.029667009055877668,
|
||||
0.04020212822983975,
|
||||
0.050742731588695494,
|
||||
0.061288823415841555,
|
||||
0.07184040799914815,
|
||||
0.1043252636301016,
|
||||
0.13687829834471027,
|
||||
0.1694483010211072,
|
||||
0.202035284929368,
|
||||
0.23624619427167134,
|
||||
0.27048596623174515,
|
||||
0.30474360397422756,
|
||||
0.3390191214858807,
|
||||
0.36358851509924695,
|
||||
0.38814205928193013,
|
||||
0.41270842850729195,
|
||||
0.4372876328262819,
|
||||
0.4372876328262819
|
||||
],
|
||||
"dgt": [
|
||||
2.714526681131686,
|
||||
2.705443819238505,
|
||||
2.6947834587664494,
|
||||
2.6841217449620203,
|
||||
2.6681935771243177,
|
||||
2.6521732021128046,
|
||||
2.630396440815385,
|
||||
2.602860350286428,
|
||||
2.5696460593920065,
|
||||
2.5364027376452056,
|
||||
2.499446286796604,
|
||||
2.4587748041127506,
|
||||
2.414398437185221,
|
||||
2.3699990328716107,
|
||||
2.322373696229342,
|
||||
2.271520771371253,
|
||||
2.2174389328192197,
|
||||
2.16337565384239,
|
||||
2.1183028432496016,
|
||||
2.082225099873648,
|
||||
2.055100772005235,
|
||||
2.0279625371819305,
|
||||
2.0008103857988204,
|
||||
1.9736443063300082,
|
||||
1.9482128147680253,
|
||||
1.9245345552113182,
|
||||
1.9026104247588487,
|
||||
1.8806927939516411,
|
||||
1.862235672444246,
|
||||
1.847275503201129,
|
||||
1.835814081380705,
|
||||
1.824381436842932,
|
||||
1.8139629377087627,
|
||||
1.8045606557581335,
|
||||
1.7961751115773796,
|
||||
1.7877868031023945,
|
||||
1.7793941781790852,
|
||||
1.7709972329654864,
|
||||
1.7625959636196327,
|
||||
1.7541903672600494,
|
||||
1.7459181197626403,
|
||||
1.737780757913635,
|
||||
1.7297783508684146,
|
||||
1.7217732861435076,
|
||||
1.7137640932265894,
|
||||
1.7057507692361864,
|
||||
1.6918150918099673,
|
||||
1.6719047669939942,
|
||||
1.6460167077689267,
|
||||
1.6201194134191075,
|
||||
1.5986915141218316,
|
||||
1.5817353179379183,
|
||||
1.569199764184379,
|
||||
1.5566577309558969,
|
||||
1.545374152761467,
|
||||
1.5353620432989845,
|
||||
1.5266220576235803,
|
||||
1.5178910621476225,
|
||||
1.5097346239790443,
|
||||
1.502153039909686,
|
||||
1.495145456062699,
|
||||
1.488134243479226,
|
||||
1.48111939735681,
|
||||
1.474100442252211,
|
||||
1.4670307626366115,
|
||||
1.4599103316162523,
|
||||
1.45273959485914,
|
||||
1.445565137158368,
|
||||
1.4340878115214444,
|
||||
1.418273806730323,
|
||||
1.3981208704326855,
|
||||
1.3779439775587023,
|
||||
1.3598972673004606,
|
||||
1.3439818461440451,
|
||||
1.3301807335621048,
|
||||
1.316383926863083,
|
||||
1.3040618749785347,
|
||||
1.2932153453410835,
|
||||
1.2838336236692311,
|
||||
1.2744470198196236,
|
||||
1.2650555289898042,
|
||||
1.2556591482982988,
|
||||
1.2428104897182262,
|
||||
1.2264996957264114,
|
||||
1.2067249615595257,
|
||||
1.1869318618366975,
|
||||
1.1672278304018044,
|
||||
1.1476135933863398,
|
||||
1.1280891949729075,
|
||||
1.108555289615659,
|
||||
1.0895983485572227,
|
||||
1.0712204022764056,
|
||||
1.0534217504465226,
|
||||
1.0356155337864215,
|
||||
1.017807767853702,
|
||||
1.0
|
||||
],
|
||||
"nf_model": {
|
||||
"enabled": true,
|
||||
"nf1": 5.727887800964238,
|
||||
"nf2": 7.727887800964238,
|
||||
"delta_p": 5.238350271545567
|
||||
},
|
||||
"gain_ripple": [
|
||||
0.1359703369791596,
|
||||
0.11822862697916037,
|
||||
0.09542181697916163,
|
||||
0.06245819697916133,
|
||||
0.02602813697916062,
|
||||
-0.0036199830208403228,
|
||||
-0.018326963020840026,
|
||||
-0.0246928330208398,
|
||||
-0.016792253020838643,
|
||||
-0.0028138630208403015,
|
||||
0.017572956979162058,
|
||||
0.038328296979159404,
|
||||
0.054956336979159914,
|
||||
0.0670723869791594,
|
||||
0.07091459697916136,
|
||||
0.07094413697916124,
|
||||
0.07114372697916238,
|
||||
0.07533675697916209,
|
||||
0.08731066697916035,
|
||||
0.10313984697916112,
|
||||
0.12276252697916235,
|
||||
0.14239527697916188,
|
||||
0.15945681697916214,
|
||||
0.1739275269791598,
|
||||
0.1767381569791624,
|
||||
0.17037189697916233,
|
||||
0.15216302697916007,
|
||||
0.13114358697916018,
|
||||
0.10802383697916085,
|
||||
0.08548825697916129,
|
||||
0.06916723697916183,
|
||||
0.05848224697916038,
|
||||
0.05447361697916264,
|
||||
0.05154489697916276,
|
||||
0.04946107697915991,
|
||||
0.04717897697916129,
|
||||
0.04551704697916037,
|
||||
0.04467697697916151,
|
||||
0.04072968697916224,
|
||||
0.03285456697916089,
|
||||
0.023488786979161347,
|
||||
0.01659282697915998,
|
||||
0.013321846979160057,
|
||||
0.011234826979162449,
|
||||
0.01030063697916006,
|
||||
0.00936596697916059,
|
||||
0.00874012697916271,
|
||||
0.00842583697916055,
|
||||
0.006965146979162284,
|
||||
0.0040435869791615175,
|
||||
0.0007104669791608842,
|
||||
-0.0015763130208377163,
|
||||
-0.006936193020838033,
|
||||
-0.016475303020840215,
|
||||
-0.028748483020837767,
|
||||
-0.039618433020837784,
|
||||
-0.051112303020840244,
|
||||
-0.06468462302083822,
|
||||
-0.07868024302083754,
|
||||
-0.09101254302083817,
|
||||
-0.10103437302083762,
|
||||
-0.11041488302083735,
|
||||
-0.11916081302083725,
|
||||
-0.12789859302083784,
|
||||
-0.1353792530208402,
|
||||
-0.14160178302083892,
|
||||
-0.1455411330208385,
|
||||
-0.1484450830208388,
|
||||
-0.14823350302084037,
|
||||
-0.14591937302083835,
|
||||
-0.1409032730208395,
|
||||
-0.13525493302083902,
|
||||
-0.1279646530208396,
|
||||
-0.11963431302083904,
|
||||
-0.11089282302084058,
|
||||
-0.1027863830208382,
|
||||
-0.09717347302083823,
|
||||
-0.09343261302083761,
|
||||
-0.0913487130208388,
|
||||
-0.08906007302083907,
|
||||
-0.0865687230208394,
|
||||
-0.08407607302083875,
|
||||
-0.07844600302084004,
|
||||
-0.06968090302083851,
|
||||
-0.05947139302083926,
|
||||
-0.05095282302083959,
|
||||
-0.042428283020839785,
|
||||
-0.03218106302083967,
|
||||
-0.01819858302084043,
|
||||
-0.0021726530208390216,
|
||||
0.01393231697916164,
|
||||
0.028098946979159933,
|
||||
0.040326236979161934,
|
||||
0.05257029697916238,
|
||||
0.06479749697916048,
|
||||
0.07704745697916238
|
||||
]
|
||||
}
|
||||
}
|
||||
15
examples/edfa_model/OA.json
Normal file
15
examples/edfa_model/OA.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"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
|
||||
}
|
||||
}
|
||||
164
examples/edfa_model/build_oa_json.py
Normal file
164
examples/edfa_model/build_oa_json.py
Normal file
@@ -0,0 +1,164 @@
|
||||
#!/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)
|
||||
313
examples/edfa_model/edfa_config.json
Normal file
313
examples/edfa_model/edfa_config.json
Normal file
@@ -0,0 +1,313 @@
|
||||
{
|
||||
"params": {
|
||||
"gain_flatmax": 25,
|
||||
"gain_min": 15,
|
||||
"p_max": 21,
|
||||
"nf_fit_coeff": [
|
||||
0.000168241,
|
||||
0.0469961,
|
||||
0.0359549,
|
||||
5.82851
|
||||
],
|
||||
"nf_ripple": [
|
||||
-0.3110761646066259,
|
||||
-0.3110761646066259,
|
||||
-0.31110274831665313,
|
||||
-0.31419329378173544,
|
||||
-0.3172854168606314,
|
||||
-0.32037911876162584,
|
||||
-0.3233255190215882,
|
||||
-0.31624321721895354,
|
||||
-0.30915729645781326,
|
||||
-0.30206775396360075,
|
||||
-0.2949045115165272,
|
||||
-0.26632156113294336,
|
||||
-0.23772399031437283,
|
||||
-0.20911178784023846,
|
||||
-0.18048410390821285,
|
||||
-0.14379944379052215,
|
||||
-0.10709599992470213,
|
||||
-0.07037375788020579,
|
||||
-0.03372858157230583,
|
||||
-0.015660302006048,
|
||||
0.0024172385953583004,
|
||||
0.020504047353947653,
|
||||
0.03860013139908377,
|
||||
0.05670549786742816,
|
||||
0.07482015390297145,
|
||||
0.0838762040768461,
|
||||
0.09284481475528361,
|
||||
0.1018180306253394,
|
||||
0.11079585523492333,
|
||||
0.1020395478432815,
|
||||
0.09310160456603413,
|
||||
0.08415906712621996,
|
||||
0.07521193198077789,
|
||||
0.0676340601339394,
|
||||
0.06005437964543287,
|
||||
0.052470799141237305,
|
||||
0.044883315610536455,
|
||||
0.037679759069084225,
|
||||
0.03047647598902483,
|
||||
0.02326948274513522,
|
||||
0.01605877647020772,
|
||||
0.021248462316134083,
|
||||
0.02657315875107553,
|
||||
0.03190060058247842,
|
||||
0.03723078993416436,
|
||||
0.04256372893215024,
|
||||
0.047899419704645264,
|
||||
0.03915515813685565,
|
||||
0.030289222542492025,
|
||||
0.021418708618354456,
|
||||
0.012573926129294415,
|
||||
0.006240488799898697,
|
||||
-9.622162373026585e-05,
|
||||
-0.006436207679519103,
|
||||
-0.012779471908040341,
|
||||
-0.02038153550619876,
|
||||
-0.027999803010447587,
|
||||
-0.035622012697103154,
|
||||
-0.043236398934156144,
|
||||
-0.04493583574805963,
|
||||
-0.04663615264317309,
|
||||
-0.048337350303318156,
|
||||
-0.050039429413028365,
|
||||
-0.051742390657545205,
|
||||
-0.05342028484370278,
|
||||
-0.05254242298580185,
|
||||
-0.05166410580536087,
|
||||
-0.05078533294804249,
|
||||
-0.04990610405914272,
|
||||
-0.05409792133358102,
|
||||
-0.05832916277634124,
|
||||
-0.06256260169582961,
|
||||
-0.06660356886269536,
|
||||
-0.04779792991567815,
|
||||
-0.028982516728038848,
|
||||
-0.010157321677553965,
|
||||
0.00861320615127981,
|
||||
0.01913736978785662,
|
||||
0.029667009055877668,
|
||||
0.04020212822983975,
|
||||
0.050742731588695494,
|
||||
0.061288823415841555,
|
||||
0.07184040799914815,
|
||||
0.1043252636301016,
|
||||
0.13687829834471027,
|
||||
0.1694483010211072,
|
||||
0.202035284929368,
|
||||
0.23624619427167134,
|
||||
0.27048596623174515,
|
||||
0.30474360397422756,
|
||||
0.3390191214858807,
|
||||
0.36358851509924695,
|
||||
0.38814205928193013,
|
||||
0.41270842850729195,
|
||||
0.4372876328262819,
|
||||
0.4372876328262819
|
||||
],
|
||||
"dgt": [
|
||||
2.714526681131686,
|
||||
2.705443819238505,
|
||||
2.6947834587664494,
|
||||
2.6841217449620203,
|
||||
2.6681935771243177,
|
||||
2.6521732021128046,
|
||||
2.630396440815385,
|
||||
2.602860350286428,
|
||||
2.5696460593920065,
|
||||
2.5364027376452056,
|
||||
2.499446286796604,
|
||||
2.4587748041127506,
|
||||
2.414398437185221,
|
||||
2.3699990328716107,
|
||||
2.322373696229342,
|
||||
2.271520771371253,
|
||||
2.2174389328192197,
|
||||
2.16337565384239,
|
||||
2.1183028432496016,
|
||||
2.082225099873648,
|
||||
2.055100772005235,
|
||||
2.0279625371819305,
|
||||
2.0008103857988204,
|
||||
1.9736443063300082,
|
||||
1.9482128147680253,
|
||||
1.9245345552113182,
|
||||
1.9026104247588487,
|
||||
1.8806927939516411,
|
||||
1.862235672444246,
|
||||
1.847275503201129,
|
||||
1.835814081380705,
|
||||
1.824381436842932,
|
||||
1.8139629377087627,
|
||||
1.8045606557581335,
|
||||
1.7961751115773796,
|
||||
1.7877868031023945,
|
||||
1.7793941781790852,
|
||||
1.7709972329654864,
|
||||
1.7625959636196327,
|
||||
1.7541903672600494,
|
||||
1.7459181197626403,
|
||||
1.737780757913635,
|
||||
1.7297783508684146,
|
||||
1.7217732861435076,
|
||||
1.7137640932265894,
|
||||
1.7057507692361864,
|
||||
1.6918150918099673,
|
||||
1.6719047669939942,
|
||||
1.6460167077689267,
|
||||
1.6201194134191075,
|
||||
1.5986915141218316,
|
||||
1.5817353179379183,
|
||||
1.569199764184379,
|
||||
1.5566577309558969,
|
||||
1.545374152761467,
|
||||
1.5353620432989845,
|
||||
1.5266220576235803,
|
||||
1.5178910621476225,
|
||||
1.5097346239790443,
|
||||
1.502153039909686,
|
||||
1.495145456062699,
|
||||
1.488134243479226,
|
||||
1.48111939735681,
|
||||
1.474100442252211,
|
||||
1.4670307626366115,
|
||||
1.4599103316162523,
|
||||
1.45273959485914,
|
||||
1.445565137158368,
|
||||
1.4340878115214444,
|
||||
1.418273806730323,
|
||||
1.3981208704326855,
|
||||
1.3779439775587023,
|
||||
1.3598972673004606,
|
||||
1.3439818461440451,
|
||||
1.3301807335621048,
|
||||
1.316383926863083,
|
||||
1.3040618749785347,
|
||||
1.2932153453410835,
|
||||
1.2838336236692311,
|
||||
1.2744470198196236,
|
||||
1.2650555289898042,
|
||||
1.2556591482982988,
|
||||
1.2428104897182262,
|
||||
1.2264996957264114,
|
||||
1.2067249615595257,
|
||||
1.1869318618366975,
|
||||
1.1672278304018044,
|
||||
1.1476135933863398,
|
||||
1.1280891949729075,
|
||||
1.108555289615659,
|
||||
1.0895983485572227,
|
||||
1.0712204022764056,
|
||||
1.0534217504465226,
|
||||
1.0356155337864215,
|
||||
1.017807767853702,
|
||||
1.0
|
||||
],
|
||||
"nf_model": {
|
||||
"enabled": true,
|
||||
"nf1": 5.727887800964238,
|
||||
"nf2": 7.727887800964238,
|
||||
"delta_p": 5.238350271545567
|
||||
},
|
||||
"gain_ripple": [
|
||||
0.1359703369791596,
|
||||
0.11822862697916037,
|
||||
0.09542181697916163,
|
||||
0.06245819697916133,
|
||||
0.02602813697916062,
|
||||
-0.0036199830208403228,
|
||||
-0.018326963020840026,
|
||||
-0.0246928330208398,
|
||||
-0.016792253020838643,
|
||||
-0.0028138630208403015,
|
||||
0.017572956979162058,
|
||||
0.038328296979159404,
|
||||
0.054956336979159914,
|
||||
0.0670723869791594,
|
||||
0.07091459697916136,
|
||||
0.07094413697916124,
|
||||
0.07114372697916238,
|
||||
0.07533675697916209,
|
||||
0.08731066697916035,
|
||||
0.10313984697916112,
|
||||
0.12276252697916235,
|
||||
0.14239527697916188,
|
||||
0.15945681697916214,
|
||||
0.1739275269791598,
|
||||
0.1767381569791624,
|
||||
0.17037189697916233,
|
||||
0.15216302697916007,
|
||||
0.13114358697916018,
|
||||
0.10802383697916085,
|
||||
0.08548825697916129,
|
||||
0.06916723697916183,
|
||||
0.05848224697916038,
|
||||
0.05447361697916264,
|
||||
0.05154489697916276,
|
||||
0.04946107697915991,
|
||||
0.04717897697916129,
|
||||
0.04551704697916037,
|
||||
0.04467697697916151,
|
||||
0.04072968697916224,
|
||||
0.03285456697916089,
|
||||
0.023488786979161347,
|
||||
0.01659282697915998,
|
||||
0.013321846979160057,
|
||||
0.011234826979162449,
|
||||
0.01030063697916006,
|
||||
0.00936596697916059,
|
||||
0.00874012697916271,
|
||||
0.00842583697916055,
|
||||
0.006965146979162284,
|
||||
0.0040435869791615175,
|
||||
0.0007104669791608842,
|
||||
-0.0015763130208377163,
|
||||
-0.006936193020838033,
|
||||
-0.016475303020840215,
|
||||
-0.028748483020837767,
|
||||
-0.039618433020837784,
|
||||
-0.051112303020840244,
|
||||
-0.06468462302083822,
|
||||
-0.07868024302083754,
|
||||
-0.09101254302083817,
|
||||
-0.10103437302083762,
|
||||
-0.11041488302083735,
|
||||
-0.11916081302083725,
|
||||
-0.12789859302083784,
|
||||
-0.1353792530208402,
|
||||
-0.14160178302083892,
|
||||
-0.1455411330208385,
|
||||
-0.1484450830208388,
|
||||
-0.14823350302084037,
|
||||
-0.14591937302083835,
|
||||
-0.1409032730208395,
|
||||
-0.13525493302083902,
|
||||
-0.1279646530208396,
|
||||
-0.11963431302083904,
|
||||
-0.11089282302084058,
|
||||
-0.1027863830208382,
|
||||
-0.09717347302083823,
|
||||
-0.09343261302083761,
|
||||
-0.0913487130208388,
|
||||
-0.08906007302083907,
|
||||
-0.0865687230208394,
|
||||
-0.08407607302083875,
|
||||
-0.07844600302084004,
|
||||
-0.06968090302083851,
|
||||
-0.05947139302083926,
|
||||
-0.05095282302083959,
|
||||
-0.042428283020839785,
|
||||
-0.03218106302083967,
|
||||
-0.01819858302084043,
|
||||
-0.0021726530208390216,
|
||||
0.01393231697916164,
|
||||
0.028098946979159933,
|
||||
0.040326236979161934,
|
||||
0.05257029697916238,
|
||||
0.06479749697916048,
|
||||
0.07704745697916238
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,120 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
Created on Fri Nov 10 17:50:46 2017
|
||||
|
||||
@author: briantaylor
|
||||
"""
|
||||
import numpy as np
|
||||
from numpy import pi, cos, sqrt, log10
|
||||
|
||||
def c():
|
||||
"""
|
||||
Returns the speed of light in meters per second
|
||||
"""
|
||||
return 299792458.0
|
||||
|
||||
def itufs(spacing, startf=191.35, stopf=196.10):
|
||||
"""Creates an array of frequencies whose default range is
|
||||
191.35-196.10 THz
|
||||
|
||||
:param spacing: Frequency spacing in THz
|
||||
:param starf: Start frequency in THz
|
||||
:param stopf: Stop frequency in THz
|
||||
:type spacing: float
|
||||
:type startf: float
|
||||
:type stopf: float
|
||||
:return an array of frequnecies determined by the spacing parameter
|
||||
:rtype: numpy.ndarray
|
||||
"""
|
||||
return np.arange(startf, stopf + spacing/2, spacing)
|
||||
|
||||
def h():
|
||||
"""
|
||||
Returns plank's constant in J*s
|
||||
"""
|
||||
return 6.62607004e-34
|
||||
|
||||
def lin2db(value):
|
||||
return 10*log10(value)
|
||||
|
||||
|
||||
def db2lin(value):
|
||||
return 10**(value/10)
|
||||
|
||||
|
||||
def wavelength2freq(value):
|
||||
""" Converts wavelength units to frequeuncy units.
|
||||
"""
|
||||
return c()/value
|
||||
|
||||
|
||||
def freq2wavelength(value):
|
||||
""" Converts frequency units to wavelength units.
|
||||
"""
|
||||
return c()/value
|
||||
|
||||
|
||||
def deltawl2deltaf(delta_wl, wavelength):
|
||||
""" deltawl2deltaf(delta_wl, wavelength):
|
||||
delta_wl is BW in wavelength units
|
||||
wavelength is the center wl
|
||||
units for delta_wl and wavelength must be same
|
||||
|
||||
|
||||
|
||||
:param delta_wl: delta wavelength BW in same units as wavelength
|
||||
:param wavelength: wavelength BW is relevant for
|
||||
:type delta_wl: float or numpy.ndarray
|
||||
:type wavelength: float
|
||||
:return: The BW in frequency units
|
||||
:rtype: float or ndarray
|
||||
|
||||
"""
|
||||
f = wavelength2freq(wavelength)
|
||||
return delta_wl*f/wavelength
|
||||
|
||||
|
||||
def deltaf2deltawl(delta_f, frequency):
|
||||
""" deltawl2deltaf(delta_f, frequency):
|
||||
converts delta frequency to delta wavelength
|
||||
units for delta_wl and wavelength must be same
|
||||
|
||||
|
||||
:param delta_f: delta frequency in same units as frequency
|
||||
:param frequency: frequency BW is relevant for
|
||||
:type delta_f: float or numpy.ndarray
|
||||
:type frequency: float
|
||||
:return: The BW in wavelength units
|
||||
:rtype: float or ndarray
|
||||
|
||||
"""
|
||||
wl = freq2wavelength(frequency)
|
||||
return delta_f*wl/frequency
|
||||
|
||||
|
||||
def rrc(ffs, baud_rate, alpha):
|
||||
""" rrc(ffs, baud_rate, alpha): computes the root-raised cosine filter
|
||||
function.
|
||||
|
||||
:param ffs: A numpy array of frequencies
|
||||
:param baud_rate: The Baud Rate of the System
|
||||
:param alpha: The roll-off factor of the filter
|
||||
:type ffs: numpy.ndarray
|
||||
:type baud_rate: float
|
||||
:type alpha: float
|
||||
:return: hf a numpy array of the filter shape
|
||||
:rtype: numpy.ndarray
|
||||
|
||||
"""
|
||||
Ts = 1/baud_rate
|
||||
l_lim = (1 - alpha)/(2 * Ts)
|
||||
r_lim = (1 + alpha)/(2 * Ts)
|
||||
hf = np.zeros(np.shape(ffs))
|
||||
slope_inds = np.where(
|
||||
np.logical_and(np.abs(ffs) > l_lim, np.abs(ffs) < r_lim))
|
||||
hf[slope_inds] = 0.5 * (1 + cos((pi * Ts / alpha) *
|
||||
(np.abs(ffs[slope_inds]) - l_lim)))
|
||||
p_inds = np.where(np.logical_and(np.abs(ffs) > 0, np.abs(ffs) < l_lim))
|
||||
hf[p_inds] = 1
|
||||
return sqrt(hf)
|
||||
@@ -1,3 +1,13 @@
|
||||
#!/usr/bin/env
|
||||
"""
|
||||
@author: briantaylor
|
||||
@author: giladgoldfarb
|
||||
@author: jeanluc-auge
|
||||
|
||||
Transmission setup example:
|
||||
reads from network json (default = examples/edfa/edfa_example_network.json)
|
||||
propagates a 96 channels comb
|
||||
"""
|
||||
from argparse import ArgumentParser
|
||||
from json import load
|
||||
from sys import exit
|
||||
@@ -6,12 +16,12 @@ from logging import getLogger, basicConfig, INFO, ERROR, DEBUG
|
||||
|
||||
from matplotlib.pyplot import show, axis
|
||||
from networkx import (draw_networkx_nodes, draw_networkx_edges,
|
||||
draw_networkx_labels)
|
||||
draw_networkx_labels, dijkstra_path)
|
||||
|
||||
from gnpy.core import network_from_json
|
||||
from gnpy.core.elements import Transceiver, Fiber
|
||||
from gnpy.core.elements import Transceiver, Fiber, Edfa
|
||||
from gnpy.core.info import SpectralInformation, Channel, Power
|
||||
from gnpy.core.algorithms import closed_paths
|
||||
#from gnpy.core.algorithms import closed_paths
|
||||
|
||||
logger = getLogger(__package__ or __file__)
|
||||
|
||||
@@ -29,6 +39,7 @@ def main(args):
|
||||
json_data = load(f)
|
||||
|
||||
network = network_from_json(json_data)
|
||||
"""jla put in comment
|
||||
pos = {n: (n.lng, n.lat) for n in network.nodes()}
|
||||
labels_pos = {n: (long-.5, lat-.5) for n, (long, lat) in pos.items()}
|
||||
size = [20 if isinstance(n, Fiber) else 80 for n in network.nodes()]
|
||||
@@ -36,17 +47,27 @@ def main(args):
|
||||
for n in network.nodes()]
|
||||
labels = {n: n.location.city if isinstance(n, Transceiver) else ''
|
||||
for n in network.nodes()}
|
||||
"""
|
||||
|
||||
si = SpectralInformation(
|
||||
Channel(1, 193.95e12, '16-qam', 32e9, 0, # 193.95 THz, 32 Gbaud
|
||||
Power(1e-3, 1e-6, 1e-6)), # 1 mW, 1uW, 1uW
|
||||
Channel(1, 195.95e12, '16-qam', 32e9, 0, # 195.95 THz, 32 Gbaud
|
||||
Power(1.2e-3, 1e-6, 1e-6)), # 1.2 mW, 1uW, 1uW
|
||||
)
|
||||
spacing = 0.05 #THz
|
||||
si = SpectralInformation() # !! SI units W, Hz
|
||||
si = si.update(carriers=tuple(Channel(f+1, (191.3+spacing*(f+1))*1e12,
|
||||
32e9, 0.15, Power(1e-3, 0, 0)) for f in range(96)))
|
||||
|
||||
nodes = [n for n in network.nodes() if isinstance(n, Transceiver)]
|
||||
source, sink = choice(nodes), choice(nodes)
|
||||
source, sink = nodes[0], nodes[1]
|
||||
results = dijkstra_path(network, source, sink)
|
||||
print('dijkstra path:', results)
|
||||
|
||||
for ne in results:
|
||||
si = ne(si)
|
||||
|
||||
print('total SNR comb in signal bandwidth', sink.snr(si))
|
||||
|
||||
#print(Rx_signal_power[0])
|
||||
#p.array([c.power.signal+c.power.nli+c.power.ase for c in carriers])
|
||||
|
||||
"""jla put in comment
|
||||
results = list(islice(closed_paths(network, source, sink, si), 3))
|
||||
paths = [[n for _, n, _ in r] for r in results]
|
||||
infos = {}
|
||||
@@ -70,10 +91,11 @@ def main(args):
|
||||
title(f'Propagating from {source.loc.city} to {sink.loc.city}')
|
||||
axis('off')
|
||||
show()
|
||||
"""
|
||||
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument('filename', nargs='?', type=Path,
|
||||
default= Path(__file__).parent / '../examples/coronet.conus.json')
|
||||
default= Path(__file__).parent / 'edfa/edfa_example_network.json')
|
||||
parser.add_argument('-v', '--verbose', action='count')
|
||||
|
||||
if __name__ == '__main__':
|
||||
@@ -1,31 +1,56 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Network elements class with SpectralInformation propagation using
|
||||
__call__ and propagate methods
|
||||
@author: giladgoldfarb
|
||||
@author: briantaylor
|
||||
@author: jeanluc-auge
|
||||
@acknowledgement : Dave Boertjes
|
||||
"""
|
||||
import numpy as np
|
||||
from scipy.constants import c, h
|
||||
|
||||
from gnpy.core.node import Node
|
||||
from gnpy.core.units import UNITS
|
||||
from gnpy.core.utils import lin2db, db2lin
|
||||
from gnpy.core.utils import lin2db, db2lin, itufs
|
||||
|
||||
|
||||
class Transceiver(Node):
|
||||
def __init__(self, config):
|
||||
super().__init__(config)
|
||||
|
||||
def snr(self, spectral_info):
|
||||
osnr_ase = [lin2db(c.power.signal/c.power.ase)
|
||||
for c in spectral_info.carriers
|
||||
if c.power.ase>1e-13]
|
||||
ratio_01nm = [lin2db(12.5e9/c.baud_rate) for c in spectral_info.carriers]
|
||||
osnr_ase_01nm = [ase - ratio for ase, ratio in zip(osnr_ase, ratio_01nm)]
|
||||
osnr_nli = [lin2db(c.power.signal/c.power.nli) for c in spectral_info.carriers]
|
||||
snr = [lin2db(c.power.signal/(c.power.nli+c.power.ase)) for c in spectral_info.carriers]
|
||||
print('OSNR in signal bandwidth={}dB and in 0.1nm={}dB'.format(osnr_ase[0], osnr_ase_01nm[0]))
|
||||
return snr
|
||||
|
||||
def __call__(self, spectral_info):
|
||||
return spectral_info
|
||||
|
||||
|
||||
class Fiber(Node):
|
||||
def __init__(self, config):
|
||||
super().__init__(config)
|
||||
self.length = self.params.length * \
|
||||
UNITS[self.params.length_units]
|
||||
UNITS[self.params.length_units] #length in km
|
||||
self.loss_coef = self.params.loss_coef #lineic loss dB/km
|
||||
self.lin_loss_coef = self.params.loss_coef / 4.3429448190325184
|
||||
#TODO discuss factor 2 in the linear lineic attenuation
|
||||
|
||||
def __repr__(self):
|
||||
return f'{type(self).__name__}(uid={self.uid}, length={self.length})'
|
||||
|
||||
def lin_attenuation(self):
|
||||
attenuation = self.length * self.loss_coef
|
||||
return db2lin(attenuation)
|
||||
|
||||
def effective_length(self, loss_coef):
|
||||
alpha_dict = self.dbkm_2_lin(loss_coef)
|
||||
alpha = alpha_dict['alpha_acoef']
|
||||
@@ -63,11 +88,15 @@ class Fiber(Node):
|
||||
return b2
|
||||
|
||||
def propagate(self, *carriers):
|
||||
#TODO integrate and call the gn.ole module to calculate carrier nli noise in fiber
|
||||
carrier_nli = db2lin(-28)*1e-3 #temporary Cte nli noise is added for debug
|
||||
i=0
|
||||
for carrier in carriers:
|
||||
pwr = carrier.power
|
||||
pwr = pwr._replace(signal=0.5 * pwr.signal * .5,
|
||||
nonlinear_interference=2 * pwr.nli,
|
||||
amplified_spontaneous_emission=2 * pwr.ase)
|
||||
pwr = pwr._replace(signal=pwr.signal/self.lin_attenuation(),
|
||||
nonlinear_interference=(pwr.nli+carrier_nli)/self.lin_attenuation(),
|
||||
amplified_spontaneous_emission=pwr.ase/self.lin_attenuation())
|
||||
i+=1
|
||||
yield carrier._replace(power=pwr)
|
||||
|
||||
def __call__(self, spectral_info):
|
||||
@@ -78,23 +107,60 @@ class Fiber(Node):
|
||||
class Edfa(Node):
|
||||
def __init__(self, config):
|
||||
super().__init__(config)
|
||||
self.gain_target = None
|
||||
self.tilt_target = None
|
||||
self.nf = None
|
||||
self.interpol_dgt = None #inerpolated dynamic gain tilt: N numpy array
|
||||
self.interpol_gain_ripple = None #gain ripple: N numpy array
|
||||
self.interpol_nf_ripple = None #nf_ripple: N numpy array
|
||||
self.channel_freq = None #SI channel frequencies: N numpy array
|
||||
"""nf and gprofile attributs are set by interpol_params"""
|
||||
self.nf = None #edfa nf @ operational.gain_target: N numpy array
|
||||
self.gprofile = None
|
||||
|
||||
def noise_profile(self, gain, ffs, df):
|
||||
""" noise_profile(nf, gain, ffs, df) computes amplifier ase
|
||||
def interpol_params(self, frequencies, pin):
|
||||
"""interpolate SI channel frequencies with the edfa dgt and gain_ripple frquencies from json
|
||||
set the edfa class __init__ None parameters :
|
||||
self.channel_freq, self.nf, self.interpol_dgt and self.interpol_gain_ripple
|
||||
"""
|
||||
#TODO read amplifier actual frequencies from additional params in json
|
||||
amplifier_freq = itufs(0.05)*1e12 # Hz
|
||||
self.channel_freq = frequencies
|
||||
self.interpol_dgt = np.interp(self.channel_freq, amplifier_freq, self.params.dgt)
|
||||
self.interpol_gain_ripple = np.interp(self.channel_freq, amplifier_freq, self.params.gain_ripple)
|
||||
self.interpol_nf_ripple = np.interp(self.channel_freq, amplifier_freq, self.params.nf_ripple)
|
||||
|
||||
:param nf: Noise figure in dB
|
||||
:param gain: Actual gain calculated for the EDFA in dB units
|
||||
:param ffs: A numpy array of frequencies
|
||||
:param df: the reference bw in THz
|
||||
:type nf: numpy.ndarray
|
||||
:type gain: numpy.ndarray
|
||||
:type ffs: numpy.ndarray
|
||||
:type df: float
|
||||
:return: the asepower in dBm
|
||||
:rtype: numpy.ndarray
|
||||
"""check power saturation and correct target_gain accordingly:"""
|
||||
tot_in_power_db = lin2db(np.sum(pin*1e3))
|
||||
gain_target = min(self.operational.gain_target, self.params.p_max-tot_in_power_db)
|
||||
self.operational.gain_target = gain_target
|
||||
|
||||
self._calc_nf()
|
||||
self._gain_profile(pin)
|
||||
|
||||
def _calc_nf(self):
|
||||
"""nf calculation based on 2 models: self.params.nf_model.enabled from json import:
|
||||
True => 2 stages amp modelling based on precalculated nf1, nf2 and delta_p in build_OA_json
|
||||
False => polynomial fit based on self.params.nf_fit_coeff"""
|
||||
#TODO : tbd alarm rising or input VOA padding in case
|
||||
#gain_min > gain_target TBD:
|
||||
pad = max(self.params.gain_min - self.operational.gain_target, 0)
|
||||
gain_target = self.operational.gain_target + pad
|
||||
|
||||
dg = gain_target - self.params.gain_flatmax # ! <0
|
||||
if self.params.nf_model.enabled:
|
||||
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))
|
||||
else:
|
||||
nf_avg = np.polyval(self.params.nf_fit_coeff, dg)
|
||||
self.nf = self.interpol_nf_ripple + nf_avg + pad #input VOA = 1 for 1 NF degradation
|
||||
|
||||
def noise_profile(self, bw):
|
||||
""" noise_profile(bw) computes amplifier ase (W) in signal bw (Hz)
|
||||
noise is calculated at amplifier input
|
||||
|
||||
:bw: signal bandwidth = baud rate in Hz
|
||||
:type bw: float
|
||||
|
||||
:return: the asepower in W in the signal bandwidth bw for 96 channels
|
||||
:return type: numpy array of float
|
||||
|
||||
ASE POWER USING PER CHANNEL GAIN PROFILE
|
||||
INPUTS:
|
||||
@@ -122,22 +188,22 @@ class Edfa(Node):
|
||||
quoting power spectral density in the same BW for both signal and ASE,
|
||||
e.g. 12.5GHz."""
|
||||
|
||||
h_mWThz = 1e-3 * h * (1e14)**2
|
||||
nf_lin = db2lin(self.nf)
|
||||
g_lin = db2lin(gain)
|
||||
ase = h_mWThz * df * ffs * (nf_lin * g_lin - 1)
|
||||
asedb = lin2db(ase)
|
||||
nchan = list(range(len(self.channel_freq)))
|
||||
df = np.array([bw]*(nchan[-1] + 1)) #Hz
|
||||
ase = h * df * self.channel_freq * db2lin(self.nf) #W
|
||||
return ase #in W, @amplifier input
|
||||
#checked 02/15/2018 @ 02:00pm -45dBm @ nf = 8.8dB in 32GHz
|
||||
|
||||
return asedb
|
||||
|
||||
def gain_profile(self, Pin):
|
||||
def _gain_profile(self, pin):
|
||||
"""
|
||||
:param dfg: design flat gain
|
||||
Pin : input power / channel in W
|
||||
|
||||
:param gain_ripple: design flat gain
|
||||
:param dgt: design gain tilt
|
||||
:param Pin: channing input power profile
|
||||
:param Pin: total input power in W
|
||||
:param gp: Average gain setpoint in dB units
|
||||
:param gtp: gain tilt setting
|
||||
:type dfg: numpy.ndarray
|
||||
:type gain_ripple: numpy.ndarray
|
||||
:type dgt: numpy.ndarray
|
||||
:type Pin: numpy.ndarray
|
||||
:type gp: float
|
||||
@@ -147,7 +213,7 @@ class Edfa(Node):
|
||||
|
||||
AMPLIFICATION USING INPUT PROFILE
|
||||
INPUTS:
|
||||
DFG - vector of length number of channels or spectral slices
|
||||
gain_ripple - vector of length number of channels or spectral slices
|
||||
DGT - vector of length number of channels or spectral slices
|
||||
Pin - input powers vector of length number of channels or
|
||||
spectral slices
|
||||
@@ -158,6 +224,7 @@ class Edfa(Node):
|
||||
amp gain per channel or spectral slice
|
||||
NOTE: there is no checking done for violations of the total output
|
||||
power capability of the amp.
|
||||
EDIT OF PREVIOUS NOTE: power violation now added in interpol_params
|
||||
Ported from Matlab version written by David Boerges at Ciena.
|
||||
Based on:
|
||||
R. di Muro, "The Er3+ fiber gain coefficient derived from a dynamic
|
||||
@@ -168,25 +235,23 @@ class Edfa(Node):
|
||||
err_tolerance = 1.0e-11
|
||||
simple_opt = True
|
||||
|
||||
# TODO make all values linear unit and convert to dB units as needed
|
||||
# within this function.
|
||||
nchan = np.arange(len(Pin))
|
||||
# TODO check what param should be used (currently length(dgt))
|
||||
nchan = np.arange(len(self.interpol_dgt))
|
||||
|
||||
# TODO find a way to use these or lose them. Primarily we should have
|
||||
# a way to determine if exceeding the gain or output power of the amp
|
||||
tot_in_power_db = lin2db(np.sum(db2lin(Pin)))
|
||||
tot_in_power_db = lin2db(np.sum(pin*1e3)) # ! Pin expressed in W
|
||||
|
||||
# Linear fit to get the
|
||||
p = np.polyfit(nchan, self.params.dgt, 1)
|
||||
p = np.polyfit(nchan, self.interpol_dgt, 1)
|
||||
dgt_slope = p[0]
|
||||
|
||||
# Calculate the target slope- Currently assumes equal spaced channels
|
||||
# TODO make it so that supports arbitrary channel spacing.
|
||||
targ_slope = self.tilt_target / (len(nchan) - 1)
|
||||
targ_slope = self.operational.tilt_target / (len(nchan) - 1)
|
||||
|
||||
# 1st estimate of DGT scaling
|
||||
dgts1 = targ_slope / dgt_slope
|
||||
|
||||
# when simple_opt is true code makes 2 attempts to compute gain and
|
||||
# the internal voa value. This is currently here to provide direct
|
||||
# comparison with original Matlab code. Will be removed.
|
||||
@@ -195,52 +260,73 @@ class Edfa(Node):
|
||||
if simple_opt:
|
||||
|
||||
# 1st estimate of Er gain & voa loss
|
||||
g1st = np.array(self.params.dfg) + \
|
||||
np.array(self.params.dgt) * dgts1
|
||||
voa = lin2db(np.mean(db2lin(g1st))) - self.gain_target
|
||||
g1st = np.array(self.interpol_gain_ripple) + self.params.gain_flatmax + \
|
||||
np.array(self.interpol_dgt) * dgts1
|
||||
voa = lin2db(np.mean(db2lin(g1st))) - self.operational.gain_target
|
||||
|
||||
# 2nd estimate of Amp ch gain using the channel input profile
|
||||
g2nd = g1st - voa
|
||||
pout_db = lin2db(np.sum(db2lin(Pin + g2nd)))
|
||||
dgts2 = self.gain_target - (pout_db - tot_in_power_db)
|
||||
pout_db = lin2db(np.sum(pin*1e3*db2lin(g2nd)))
|
||||
dgts2 = self.operational.gain_target - (pout_db - tot_in_power_db)
|
||||
|
||||
# Center estimate of amp ch gain
|
||||
xcent = dgts2
|
||||
gcent = g1st - voa + np.array(self.params.dgt) * xcent
|
||||
pout_db = lin2db(np.sum(db2lin(Pin + gcent)))
|
||||
gcent = g1st - voa + np.array(self.interpol_dgt) * xcent
|
||||
pout_db = lin2db(np.sum(pin*1e3*db2lin(gcent)))
|
||||
gavg_cent = pout_db - tot_in_power_db
|
||||
|
||||
# Lower estimate of Amp ch gain
|
||||
deltax = np.max(g1st) - np.min(g1st)
|
||||
xlow = dgts2 - deltax
|
||||
glow = g1st - voa + np.array(self.params.dgt) * xlow
|
||||
pout_db = lin2db(np.sum(db2lin(Pin + glow)))
|
||||
glow = g1st - voa + np.array(self.interpol_dgt) * xlow
|
||||
pout_db = lin2db(np.sum(pin*1e3*db2lin(glow)))
|
||||
gavg_low = pout_db - tot_in_power_db
|
||||
|
||||
# Upper gain estimate
|
||||
xhigh = dgts2 + deltax
|
||||
ghigh = g1st - voa + np.array(self.params.dgt) * xhigh
|
||||
pout_db = lin2db(np.sum(db2lin(Pin + ghigh)))
|
||||
ghigh = g1st - voa + np.array(self.interpol_dgt) * xhigh
|
||||
pout_db = lin2db(np.sum(pin*1e3*db2lin(ghigh)))
|
||||
gavg_high = pout_db - tot_in_power_db
|
||||
|
||||
# compute slope
|
||||
slope1 = (gavg_low - gavg_cent) / (xlow - xcent)
|
||||
slope2 = (gavg_cent - gavg_high) / (xcent - xhigh)
|
||||
|
||||
if np.abs(self.gain_target - gavg_cent) <= err_tolerance:
|
||||
if np.abs(self.operational.gain_target - gavg_cent) <= err_tolerance:
|
||||
dgts3 = xcent
|
||||
elif self.gain_target < gavg_cent:
|
||||
dgts3 = xcent - (gavg_cent - self.gain_target) / slope1
|
||||
elif self.operational.gain_target < gavg_cent:
|
||||
dgts3 = xcent - (gavg_cent - self.operational.gain_target) / slope1
|
||||
else:
|
||||
dgts3 = xcent + (-gavg_cent + self.gain_target) / slope2
|
||||
dgts3 = xcent + (-gavg_cent + self.operational.gain_target) / slope2
|
||||
|
||||
gprofile = g1st - voa + np.array(self.params.dgt) * dgts3
|
||||
gprofile = g1st - voa + np.array(self.interpol_dgt) * dgts3
|
||||
#print(gprofile[0])
|
||||
else:
|
||||
gprofile = None
|
||||
|
||||
return gprofile
|
||||
self.gprofile = gprofile
|
||||
|
||||
def calc_nf(self):
|
||||
dg = self.gain_target - np.mean(self.params.dfg)
|
||||
nf_avg = np.polyval(self.params.nf_fit_coeff, dg)
|
||||
self.nf = self.params.nf_ripple + nf_avg
|
||||
def propagate(self, *carriers):
|
||||
"""add ase noise to the propagating carriers of SpectralInformation"""
|
||||
i = 0
|
||||
pin = np.array([c.power.signal+c.power.nli+c.power.ase for c in carriers]) #pin in W
|
||||
freq = np.array([c.frequency for c in carriers])
|
||||
#interpolate the amplifier vectors with the carriers freq, calculate nf & gain profile
|
||||
self.interpol_params(freq, pin)
|
||||
gain = db2lin(self.gprofile)
|
||||
|
||||
for carrier in carriers:
|
||||
|
||||
pwr = carrier.power
|
||||
bw = carrier.baud_rate
|
||||
carrier_ase = self.noise_profile(bw)[i]
|
||||
|
||||
pwr = pwr._replace(signal=pwr.signal*gain[i],
|
||||
nonlinear_interference=pwr.nli*gain[i],
|
||||
amplified_spontaneous_emission=(pwr.ase+carrier_ase)*gain[i])
|
||||
i += 1
|
||||
yield carrier._replace(power=pwr)
|
||||
|
||||
def __call__(self, spectral_info):
|
||||
carriers = tuple(self.propagate(*spectral_info.carriers))
|
||||
return spectral_info.update(carriers=carriers)
|
||||
|
||||
@@ -17,10 +17,9 @@ class Power(namedtuple('Power', 'signal nonlinear_interference amplified_spontan
|
||||
_ABBREVS = {'nli': 'nonlinear_interference',
|
||||
'ase': 'amplified_spontaneous_emission',}
|
||||
|
||||
class Channel(namedtuple('Channel', 'channel_number frequency modulation baud_rate alpha power'), ConvenienceAccess):
|
||||
class Channel(namedtuple('Channel', 'channel_number frequency baud_rate roll_off power'), ConvenienceAccess):
|
||||
_ABBREVS = {'channel': 'channel_number',
|
||||
'num_chan': 'channel_number',
|
||||
'num_carriers': 'num_carriers',
|
||||
'ffs': 'frequency',
|
||||
'freq': 'frequency',}
|
||||
|
||||
@@ -30,13 +29,22 @@ class SpectralInformation(namedtuple('SpectralInformation', 'carriers'), Conveni
|
||||
|
||||
if __name__ == '__main__':
|
||||
si = SpectralInformation(
|
||||
Channel(1, 193.95e12, '16-qam', 32e9, 0, # 193.95 THz, 32 Gbaud
|
||||
Channel(1, 193.95e12, 32e9, 0.15, # 193.95 THz, 32 Gbaud
|
||||
Power(1e-3, 1e-6, 1e-6)), # 1 mW, 1uW, 1uW
|
||||
Channel(1, 195.95e12, '16-qam', 32e9, 0, # 195.95 THz, 32 Gbaud
|
||||
Channel(1, 195.95e12, 32e9, 0.15, # 195.95 THz, 32 Gbaud
|
||||
Power(1.2e-3, 1e-6, 1e-6)), # 1.2 mW, 1uW, 1uW
|
||||
)
|
||||
|
||||
si = SpectralInformation()
|
||||
spacing = 0.05 #THz
|
||||
|
||||
si = si.update(carriers=tuple(Channel(f+1, 191.3+spacing*(f+1), 32e9, 0.15, Power(1e-3, f, 1)) for f in range(96)))
|
||||
|
||||
print(f'si = {si}')
|
||||
print(f'si = {si.carriers[0].power.nli}')
|
||||
print(f'si = {si.carriers[20].power.nli}')
|
||||
"""
|
||||
si2 = si.update(carriers=tuple(c.update(power = c.power.update(nli = c.power.nli * 1e5))
|
||||
for c in si.carriers))
|
||||
print(f'si2 = {si2}')
|
||||
"""
|
||||
@@ -36,6 +36,8 @@ class Node:
|
||||
self.params = self.config.params
|
||||
if hasattr(self.config, 'metadata'):
|
||||
self.metadata = self.config.metadata
|
||||
if hasattr(self.config, 'operational'):
|
||||
self.operational = self.config.operational
|
||||
|
||||
@property
|
||||
def coords(self):
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
UNITS = {'m': 1,
|
||||
'km': 1e3}
|
||||
UNITS = {'m': 1e-3,
|
||||
'km': 1}
|
||||
|
||||
Reference in New Issue
Block a user