@@ -209,8 +209,11 @@ def from_level1(cls, l1product, parent='', idlprocessor=None):
209209 ob_elut , sci_channels = ELUTManager .instance .get_elut (date )
210210
211211 e_actual_list = []
212- e_actual_calib_list = []
213212 off_gain_list = []
213+
214+ ecc_only_e_actual_list = []
215+ ecc_only_off_gain_list = []
216+
214217 ecc_err_list = []
215218 gain_range_ok_list = []
216219
@@ -301,20 +304,31 @@ def from_level1(cls, l1product, parent='', idlprocessor=None):
301304 if process .returncode != 0 :
302305 raise RuntimeError (f"ECC Bash script failed: { process .stderr } " )
303306
304- logger .info ("ECC bash script executed successfully: %s" , process .stdout )
307+ logger .info ("ECC bash script executed successfully: \n %s" , process .stdout )
305308
306309 if not erg_path .exists ():
307310 raise FileNotFoundError (f"Failed to read ECC result file { erg_path } " )
308311
309312 control_idx = l2 .data ['control_index' ][spec_idx ]
310313 livetime = l1product .control ['live_time' ][control_idx ].to_value (u .s )
311- ecc_pf_df = ecc_post_fit (spec_all_erg , erg_path , livetime )
314+ ecc_pf_df , idx_ecc = ecc_post_fit (spec_all_erg , erg_path , livetime )
315+ logger .info ("Run ecc post fit: replaced [%s %%] gain "
316+ "offset pairs with 'better fits'" ,
317+ round ((len (idx_ecc )- idx_ecc .sum ())/ max (1 , len (idx_ecc )) * 100 ,
318+ ndigits = 1 ))
312319
313320 off_gain = np .array ([4.0 * ecc_pf_df ["Offset_Cor" ].values .reshape (32 , 12 ),
314321 1.0 / (4.0 * ecc_pf_df ["Gain_Cor" ].values .reshape (32 , 12 )),
315322 ecc_pf_df ["goc" ].values .reshape (32 , 12 )])
316- l2 .control ['ob_elut_name' ][l2 .data ['control_index' ][spec_idx ]] = ob_elut .file
317323 off_gain_list .append (off_gain )
324+
325+ off_gain_ecc = np .array ([4.0 * ecc_pf_df ["Offset_ECC" ].values .reshape (32 , 12 ),
326+ 1.0 / (4.0 * ecc_pf_df ["Gain_ECC" ].values .reshape (32 , 12 )),
327+ ecc_pf_df ["goc" ].values .reshape (32 , 12 )])
328+ ecc_only_off_gain_list .append (off_gain_ecc )
329+
330+ l2 .control ['ob_elut_name' ][l2 .data ['control_index' ][spec_idx ]] = ob_elut .file
331+
318332 ecc_err_list .append (np .array ([ecc_pf_df ["err_P31" ].values .reshape (32 , 12 ),
319333 ecc_pf_df ["err_dE31" ].values .reshape (32 , 12 ),
320334 ecc_pf_df ["err_P81" ].values .reshape (32 , 12 ),
@@ -366,35 +380,44 @@ def from_level1(cls, l1product, parent='', idlprocessor=None):
366380 )
367381 e_actual_list .append (e_actual_ext )
368382
369- # calculate the actual energy edges independent of the applied ELUT
370- adc = np .round (offset [..., None ] + (sci_channels ["Elower" ].to_value ()
371- / gain [..., None ])).astype (np .uint16 )
372- e_actual_calib = (np .searchsorted (np .arange (4096 ), adc ) -
373- offset [..., None ]) * gain [..., None ]
374- e_actual_calib [:, :, - 1 ] = np .inf
375- e_actual_calib [:, :, 0 ] = 0.0
383+ gain_ecc = off_gain_ecc [1 , :, :]
384+ offset_ecc = off_gain_ecc [0 , :, :]
376385
377- e_actual_calib_list .append (e_actual_calib )
378-
379- # end of ECC context block
380-
381- l2 .data .add_column (Column (name = 'e_edges_actual' , data = e_actual_list ,
382- description = "actual energy edges fitted by ECC with applied ELUT" )) # noqa
383- l2 .data ["e_edges_actual" ].unit = u .keV
384-
385- l2 .data .add_column (Column (name = 'e_edges_actual_calib' , data = e_actual_calib_list ,
386- description = "actual energy edges fitted by ECC without applied ELUT" )) # noqa
387- l2 .data ["e_edges_actual_calib" ].unit = u .keV
388-
389- l2 .data .add_column (Column (name = 'ecc_offset_gain_goc' , data = off_gain_list ,
390- description = "result of the ecc fitting: offset, gain, goc" ))
391- l2 .data .add_column (Column (name = 'ecc_error' , data = ecc_err_list ,
392- description = "error estimate from ECC: err_P31, err_dE31, "
393- "err_P81, err_dE81" ))
394- l2 .data .add_column (Column (name = 'gain_range_ok' , data = gain_range_ok_list ,
395- description = "is gain in expected range" ))
396-
397- del l2 .data ["counts_comp_err" ]
398- del l2 .data ["counts" ]
386+ # calculate the actual energy edges taking the applied ELUT into
387+ # account for calibration of data recorded with the ELUT
388+ e_actual_ecc = (ob_elut .adc - offset_ecc [..., None ]) * gain_ecc [..., None ]
389+
390+ e_actual_ext_ecc = np .pad (e_actual_ecc ,
391+ # pad last axis by 1 on both sides
392+ pad_width = ((0 , 0 ), (0 , 0 ), (1 , 1 )),
393+ mode = 'constant' ,
394+ # first pad with 0, last pad with inf
395+ constant_values = (0 , np .inf )
396+ )
397+ ecc_only_e_actual_list .append (e_actual_ext_ecc )
398+
399+ # end of ECC context block
400+ # end of for each spectrum
401+ l2 .data .add_column (Column (name = 'e_edges_actual' , data = e_actual_list ,
402+ description = "actual energy edges fitted by ECC and post fitting" )) # noqa
403+ l2 .data ["e_edges_actual" ].unit = u .keV
404+
405+ l2 .data .add_column (Column (name = 'offset_gain_goc' , data = off_gain_list ,
406+ description = "result of the ecc fitting: offset, gain, goc and post fitting" )) # noqa
407+
408+ l2 .data .add_column (Column (name = 'ecc_only_e_edges_actual' , data = ecc_only_e_actual_list ,
409+ description = "actual energy edges fitted by ECC only" )) # noqa
410+ l2 .data ["ecc_only_e_edges_actual" ].unit = u .keV
411+
412+ l2 .data .add_column (Column (name = 'ecc_only_offset_gain_goc' , data = ecc_only_off_gain_list ,
413+ description = "result of the ecc fitting only: offset, gain, goc" )) # noqa
414+
415+ l2 .data .add_column (Column (name = 'ecc_error' , data = ecc_err_list ,
416+ description = "error estimate from ECC: err_P31, err_dE31, err_P81, err_dE81" )) # noqa
417+ l2 .data .add_column (Column (name = 'gain_range_ok' , data = gain_range_ok_list ,
418+ description = "is gain in expected range" ))
419+
420+ del l2 .data ["counts_comp_err" ]
421+ del l2 .data ["counts" ]
399422
400423 return [l2 ]
0 commit comments