@@ -272,8 +272,11 @@ def from_level1(cls, l1product, parent='', idlprocessor=None):
272272 ob_elut , sci_channels = ELUTManager .instance .get_elut (date )
273273
274274 e_actual_list = []
275- e_actual_calib_list = []
276275 off_gain_list = []
276+
277+ ecc_only_e_actual_list = []
278+ ecc_only_off_gain_list = []
279+
277280 ecc_err_list = []
278281 gain_range_ok_list = []
279282
@@ -364,20 +367,31 @@ def from_level1(cls, l1product, parent='', idlprocessor=None):
364367 if process .returncode != 0 :
365368 raise RuntimeError (f"ECC Bash script failed: { process .stderr } " )
366369
367- logger .info ("ECC bash script executed successfully: %s" , process .stdout )
370+ logger .info ("ECC bash script executed successfully: \n %s" , process .stdout )
368371
369372 if not erg_path .exists ():
370373 raise FileNotFoundError (f"Failed to read ECC result file { erg_path } " )
371374
372375 control_idx = l2 .data ['control_index' ][spec_idx ]
373376 livetime = l1product .control ['live_time' ][control_idx ].to_value (u .s )
374- ecc_pf_df = ecc_post_fit (spec_all_erg , erg_path , livetime )
377+ ecc_pf_df , idx_ecc = ecc_post_fit (spec_all_erg , erg_path , livetime )
378+ logger .info ("Run ecc post fit: replaced [%s %%] gain "
379+ "offset pairs with 'better fits'" ,
380+ round ((len (idx_ecc )- idx_ecc .sum ())/ max (1 , len (idx_ecc )) * 100 ,
381+ ndigits = 1 ))
375382
376383 off_gain = np .array ([4.0 * ecc_pf_df ["Offset_Cor" ].values .reshape (32 , 12 ),
377384 1.0 / (4.0 * ecc_pf_df ["Gain_Cor" ].values .reshape (32 , 12 )),
378385 ecc_pf_df ["goc" ].values .reshape (32 , 12 )])
379- l2 .control ['ob_elut_name' ][l2 .data ['control_index' ][spec_idx ]] = ob_elut .file
380386 off_gain_list .append (off_gain )
387+
388+ off_gain_ecc = np .array ([4.0 * ecc_pf_df ["Offset_ECC" ].values .reshape (32 , 12 ),
389+ 1.0 / (4.0 * ecc_pf_df ["Gain_ECC" ].values .reshape (32 , 12 )),
390+ ecc_pf_df ["goc" ].values .reshape (32 , 12 )])
391+ ecc_only_off_gain_list .append (off_gain_ecc )
392+
393+ l2 .control ['ob_elut_name' ][l2 .data ['control_index' ][spec_idx ]] = ob_elut .file
394+
381395 ecc_err_list .append (np .array ([ecc_pf_df ["err_P31" ].values .reshape (32 , 12 ),
382396 ecc_pf_df ["err_dE31" ].values .reshape (32 , 12 ),
383397 ecc_pf_df ["err_P81" ].values .reshape (32 , 12 ),
@@ -429,35 +443,44 @@ def from_level1(cls, l1product, parent='', idlprocessor=None):
429443 )
430444 e_actual_list .append (e_actual_ext )
431445
432- # calculate the actual energy edges independent of the applied ELUT
433- adc = np .round (offset [..., None ] + (sci_channels ["Elower" ].to_value ()
434- / gain [..., None ])).astype (np .uint16 )
435- e_actual_calib = (np .searchsorted (np .arange (4096 ), adc ) -
436- offset [..., None ]) * gain [..., None ]
437- e_actual_calib [:, :, - 1 ] = np .inf
438- e_actual_calib [:, :, 0 ] = 0.0
446+ gain_ecc = off_gain_ecc [1 , :, :]
447+ offset_ecc = off_gain_ecc [0 , :, :]
439448
440- e_actual_calib_list .append (e_actual_calib )
441-
442- # end of ECC context block
443-
444- l2 .data .add_column (Column (name = 'e_edges_actual' , data = e_actual_list ,
445- description = "actual energy edges fitted by ECC with applied ELUT" )) # noqa
446- l2 .data ["e_edges_actual" ].unit = u .keV
447-
448- l2 .data .add_column (Column (name = 'e_edges_actual_calib' , data = e_actual_calib_list ,
449- description = "actual energy edges fitted by ECC without applied ELUT" )) # noqa
450- l2 .data ["e_edges_actual_calib" ].unit = u .keV
451-
452- l2 .data .add_column (Column (name = 'ecc_offset_gain_goc' , data = off_gain_list ,
453- description = "result of the ecc fitting: offset, gain, goc" ))
454- l2 .data .add_column (Column (name = 'ecc_error' , data = ecc_err_list ,
455- description = "error estimate from ECC: err_P31, err_dE31, "
456- "err_P81, err_dE81" ))
457- l2 .data .add_column (Column (name = 'gain_range_ok' , data = gain_range_ok_list ,
458- description = "is gain in expected range" ))
459-
460- del l2 .data ["counts_comp_err" ]
461- del l2 .data ["counts" ]
449+ # calculate the actual energy edges taking the applied ELUT into
450+ # account for calibration of data recorded with the ELUT
451+ e_actual_ecc = (ob_elut .adc - offset_ecc [..., None ]) * gain_ecc [..., None ]
452+
453+ e_actual_ext_ecc = np .pad (e_actual_ecc ,
454+ # pad last axis by 1 on both sides
455+ pad_width = ((0 , 0 ), (0 , 0 ), (1 , 1 )),
456+ mode = 'constant' ,
457+ # first pad with 0, last pad with inf
458+ constant_values = (0 , np .inf )
459+ )
460+ ecc_only_e_actual_list .append (e_actual_ext_ecc )
461+
462+ # end of ECC context block
463+ # end of for each spectrum
464+ l2 .data .add_column (Column (name = 'e_edges_actual' , data = e_actual_list ,
465+ description = "actual energy edges fitted by ECC and post fitting" )) # noqa
466+ l2 .data ["e_edges_actual" ].unit = u .keV
467+
468+ l2 .data .add_column (Column (name = 'offset_gain_goc' , data = off_gain_list ,
469+ description = "result of the ecc fitting: offset, gain, goc and post fitting" )) # noqa
470+
471+ l2 .data .add_column (Column (name = 'ecc_only_e_edges_actual' , data = ecc_only_e_actual_list ,
472+ description = "actual energy edges fitted by ECC only" )) # noqa
473+ l2 .data ["ecc_only_e_edges_actual" ].unit = u .keV
474+
475+ l2 .data .add_column (Column (name = 'ecc_only_offset_gain_goc' , data = ecc_only_off_gain_list ,
476+ description = "result of the ecc fitting only: offset, gain, goc" )) # noqa
477+
478+ l2 .data .add_column (Column (name = 'ecc_error' , data = ecc_err_list ,
479+ description = "error estimate from ECC: err_P31, err_dE31, err_P81, err_dE81" )) # noqa
480+ l2 .data .add_column (Column (name = 'gain_range_ok' , data = gain_range_ok_list ,
481+ description = "is gain in expected range" ))
482+
483+ del l2 .data ["counts_comp_err" ]
484+ del l2 .data ["counts" ]
462485
463486 return [l2 ]
0 commit comments