def detectors_dark_proc(parser): args = parser.parse_args() #expnam, runnum, dnames, ifname, ofname, events, evskip, intlow, inthig, rmslow, rmshig, fraclm, nsigma,\ # plotim, verbos, savebw, intnlo, intnhi, rmsnlo, rmsnhi, evcode EVSKIP = args.evskip EVENTS = args.events + EVSKIP logger.info('Raw data processing of exp: %s run: %d for detector(s): %s' % (args.expnam, args.runnum, args.dnames)) logger.info('input file: %s' % (args.ifname)) ds = DataSource(files=args.ifname) run = next(ds.runs()) logger.info('\t RunInfo expt: %s runnum: %d\n' % (run.expt, run.runnum)) print('dir(run):', dir(run)) print(':', run.timestamp) print(':', run._get_runinfo()) print(':', run.xtcinfo) print(':', run.id) #print(':', ) #print(':', ) #sys.exit('TEST EXIT') ###================== lst_dpo = [ DetRawDarkProc(run, dname, args) for dname in args.dnames.split(',') ] #ecm = EventCodeManager(evcode, verbos) t0_sec = time() tdt = t0_sec for i, evt in enumerate(run.events()): if i < EVSKIP: continue if not i < EVENTS: break #if not ecm.select(evt) : continue for dpo in lst_dpo: dpo.event(evt) if do_print(i): tsec = time() dt = tsec - tdt tdt = tsec logger.info(' Event: %4d, time=%7.3f sec, dt=%5.3f sec' % (i, time() - t0_sec, dt)) for dpo in lst_dpo: dpo.summary(evt) logger.info('%s\n Processed %d events, consumed time = %f sec.' % (80 * '_', i, time() - t0_sec))
def convert_hdf5_to_xtc2_with_runinfo(): import dgramCreate as dc import numpy as np import os import h5py nameinfo = dc.nameinfo(DETNAME, DETTYPE, SERNUM, NAMESID) alg = dc.alg('raw', [0, 0, 1]) cydgram = dc.CyDgram() #---------- for runinfo runinfo_detname = 'runinfo' runinfo_dettype = 'runinfo' runinfo_detid = '' runinfo_namesid = 1 runinfo_nameinfo = dc.nameinfo(runinfo_detname, runinfo_dettype, runinfo_detid, runinfo_namesid) runinfo_alg = dc.alg('runinfo', [0, 0, 1]) runinfo_data = {'expt': EXPNAME, 'runnum': RUNNUM} #---------- ifname = FNAME_HDF5 ofname = FNAME_XTC2 print('Input file: %s\nOutput file: %s' % (ifname, ofname)) f = open(ofname, 'wb') h5f = h5py.File(ifname) #waveforms = h5f['waveforms'] #times = h5f['times'] raw = h5f['raw'] #for nevt,(wfs,times) in enumerate(zip(waveforms,times)): for nevt, nda in enumerate(raw): my_data = {'array': nda} #'times': times if do_print(nevt): print('Event %3d' % nevt, ' nda.shape:', nda.shape) #---------- for runinfo if nevt < 2: cydgram.addDet(runinfo_nameinfo, runinfo_alg, runinfo_data) cydgram.addDet(nameinfo, alg, my_data) timestamp = nevt pulseid = nevt if (nevt == 0): transitionid = 2 # Configure elif (nevt == 1): transitionid = 4 # BeginRun else: transitionid = 12 # L1Accept xtc_bytes = cydgram.get(timestamp, transitionid) #xtc_bytes = cydgram.get(timestamp, pulseid, transitionid) f.write(xtc_bytes) f.close()
def proc_data(**kwargs): logger.info(str_kwargs(kwargs, title='Input parameters:')) DSNAME = kwargs.get( 'dsname', '/reg/g/psdm/detector/data2_test/xtc/data-amox27716-r0100-acqiris-e000100.xtc2' ) DETNAME = kwargs.get('detname', 'tmo_quadanode') EVSKIP = kwargs.get('evskip', 0) EVENTS = kwargs.get('events', 100) + EVSKIP OFPREFIX = kwargs.get('ofprefix', './') VERBOSE = kwargs.get('verbose', False) ds = DataSource(files=DSNAME) orun = next(ds.runs()) det = orun.Detector(DETNAME) kwargs['consts'] = det.calibconst peaks = WFPeaks(**kwargs) proc = DLDProcessor(**kwargs) stats = DLDStatistics(proc, **kwargs) for nev, evt in enumerate(orun.events()): if nev < EVSKIP: continue if nev > EVENTS: break if do_print(nev): logger.info('Event %3d' % nev) t0_sec = time() wts = det.raw.times(evt) wfs = det.raw.waveforms(evt) nhits, pkinds, pkvals, pktsec = peaks(wfs, wts) if VERBOSE: print(" waveforms processing time = %.6f sec" % (time() - t0_sec)) print_ndarr(wfs, ' waveforms : ', last=4) print_ndarr(wts, ' times : ', last=4) print_ndarr(nhits, ' number_of_hits: ') print_ndarr(pktsec, ' peak_times_sec: ', last=4) proc.event_proc(nev, nhits, pktsec) stats.fill_data(nhits, pktsec) if VERBOSE: for i, (x, y, r, t) in enumerate(proc.xyrt_list(nev, nhits, pktsec)): print(' hit:%2d x:%7.3f y:%7.3f t:%10.5g r:%7.3f' % (i, x, y, t, r)) draw_plots(stats, prefix=OFPREFIX, do_save=True, hwin_x0y0=(0, 10))
def proc_data(**kwargs): logger.info(str_kwargs(kwargs, title='Input parameters:')) IFNAME = kwargs.get( 'ifname', '/reg/g/psdm/detector/data_test/hdf5/amox27716-r0100-e060000-single-node.h5' ) EVSKIP = kwargs.get('evskip', 0) EVENTS = kwargs.get('events', 10) + EVSKIP OFPREFIX = kwargs.get('ofprefix', './') VERBOSE = kwargs.get('verbose', False) proc = DLDProcessor(**kwargs) stats = DLDStatistics(proc, **kwargs) f = open_input_h5file(IFNAME, **kwargs) print(' file: %s\n number of events in file %d' % (IFNAME, f.events_in_h5file())) t0_sec = time() nev = 0 while f.next_event(): nev = f.event_number() if nev < EVSKIP: continue if nev > EVENTS: break if do_print(nev): logger.info('Event %3d' % nev) nhits, pktsec = f.peak_arrays() if VERBOSE: print_ndarr(nhits, ' number_of_hits: ') print_ndarr(pktsec, ' peak_times_sec: ', last=4) proc.event_proc(nev, nhits, pktsec) stats.fill_data(nhits, pktsec) if VERBOSE: for i, (x, y, r, t) in enumerate(proc.xyrt_list(nev, nhits, pktsec)): print(' hit:%2d x:%7.3f y:%7.3f t:%10.5g r:%7.3f' % (i, x, y, t, r)) dt = time() - t0_sec print('%d events processing time = %.3f sec or %.6f sec/event or %.3f Hz' % (nev, dt, dt / nev, nev / dt)) draw_plots(stats, prefix=OFPREFIX, do_save=True, hwin_x0y0=(0, 10))
def proc_data(**kwargs): logger.info(str_kwargs(kwargs, title='Input parameters:')) DSNAME = kwargs.get( 'dsname', '/reg/g/psdm/detector/data2_test/xtc/data-amox27716-r0100-acqiris-e001000.xtc2' ) DETNAME = kwargs.get('detname', 'tmo_quadanode') EVSKIP = kwargs.get('evskip', 0) EVENTS = kwargs.get('events', 10) + EVSKIP EXP = kwargs.get('exp', 'amox27716') RUN = kwargs.get('run', 100) VERBOSE = kwargs.get('verbose', False) OFPREFIX = kwargs.get('ofprefix', './') ofname = '%s%s-r%04d-e%06d-ex-22_lowerthresh.h5' % (OFPREFIX, EXP, int(RUN), EVENTS) peaks = WFPeaks(**kwargs) ofile = open_output_h5file(ofname, peaks, **kwargs) ds = DataSource(files=DSNAME) orun = next(ds.runs()) det = orun.Detector(DETNAME) for nev, evt in enumerate(orun.events()): if nev < EVSKIP: continue if nev > EVENTS: break if do_print(nev): logger.info('Event %4d' % nev) t0_sec = time() wts = det.raw.times(evt) wfs = det.raw.waveforms(evt) nhits, pkinds, pkvals, pktsec = peaks(wfs, wts) # ACCESS TO PEAK INFO if VERBOSE: print(" ev:%4d waveforms processing time = %.6f sec" % (nev, time() - t0_sec)) print_ndarr(wfs, ' waveforms : ', last=4) print_ndarr(wts, ' times : ', last=4) print_ndarr(nhits, ' number_of_hits : ') print_ndarr(pktsec, ' peak_times_sec : ', last=4) ofile.add_event_to_h5file()
def proc_data(**kwargs): logger.info(str_kwargs(kwargs, title='Input parameters:')) DSNAME = kwargs.get( 'dsname', '/reg/g/psdm/detector/data2_test/xtc/data-amox27716-r0100-acqiris-e000100.xtc2' ) DETNAME = kwargs.get('detname', 'tmo_quadanode') EVSKIP = kwargs.get('evskip', 0) EVENTS = kwargs.get('events', 10) + EVSKIP VERBOSE = kwargs.get('verbose', False) ds = DataSource(files=DSNAME) orun = next(ds.runs()) print('\nruninfo expt: %s runnum: %d' % (orun.expt, orun.runnum)) det = orun.Detector(DETNAME) #kwargs['detobj'] = det kwargs['consts'] = det.calibconst peaks = WFPeaks(**kwargs) proc = DLDProcessor(**kwargs) #detobj=det to get cfg/calib constants for nev, evt in enumerate(orun.events()): if nev < EVSKIP: continue if nev > EVENTS: break if do_print(nev): logger.info('Event %3d' % nev) t0_sec = time() wts = det.raw.times(evt) wfs = det.raw.waveforms(evt) nhits, pkinds, pkvals, pktsec = peaks(wfs, wts) # ACCESS TO PEAK INFO if VERBOSE: print(" waveforms processing time = %.6f sec" % (time() - t0_sec)) print_ndarr(wfs, ' waveforms : ', last=4) print_ndarr(wts, ' times : ', last=4) print_ndarr(nhits, ' number_of_hits : ') print_ndarr(pktsec, ' peak_times_sec : ', last=4) for i, (x, y, r, t) in enumerate(proc.xyrt_list(nev, nhits, pktsec)): print(' hit:%2d x:%7.3f y:%7.3f t:%10.5g r:%7.3f' % (i, x, y, t, r))
def convert_hdf5_to_xtc2_with_runinfo(): import dgramCreate as dc # .../psana/peakFinder/dgramCreate.pyx (Lord, why it is here?) import numpy as np import os import h5py if RAW in LIST_SAVE: #xxxxxx_nameinfo = dc.nameinfo(DETNAME, DETTYPE, SERNUM, NAMESID) #raw_nameinfo = dc.nameinfo(DETNAME, DETTYPE, SERNUM, NAMESID) raw_nameinfo = dc.nameinfo('xtcav', 'camera', '1234', RAW) raw_alg = dc.alg('raw', [0, 0, 1]) if RUNINFO in LIST_SAVE: runinfo_nameinfo = dc.nameinfo('runinfo', 'runinfo', '', RUNINFO) runinfo_alg = dc.alg('runinfo', [0, 0, 1]) if EBEAM in LIST_SAVE: ebeam_nameinfo = dc.nameinfo('ebeam', 'ebeam', '', EBEAM) ebeam_alg = dc.alg('valsebm', [0, 0, 1]) if EVENTID in LIST_SAVE: eventid_nameinfo = dc.nameinfo('eventid', 'eventid', '', EVENTID) eventid_alg = dc.alg('valseid', [0, 0, 1]) if GASDET in LIST_SAVE: gasdet_nameinfo = dc.nameinfo('gasdetector', 'gasdetector', '', GASDET) gasdet_alg = dc.alg('valsgd', [0, 0, 1]) if XTCAVPARS in LIST_SAVE: xtcav_nameinfo = dc.nameinfo('xtcavpars', 'xtcavpars', '', XTCAVPARS) xtcav_alg = dc.alg('valsxtp', [0, 0, 1]) #---------- cydgram = dc.CyDgram() ifname = FNAME_HDF5 ofname = FNAME_XTC2 print('Input file: %s\nOutput file: %s' % (ifname, ofname)) f = open(ofname, 'wb') h5f = h5py.File(ifname, 'r') eventid = h5f['EventId'] ebeam = h5f['EBeam'] gasdet = h5f['GasDetector'] xtcav = h5f['XTCAV'] raw = h5f['raw'] for nevt, nda in enumerate(raw): if nevt > EVENTS: print('Reached maximum number of events %s' % EVENTS) break #if nevt < EVSKIP : # print(' - skip event') # continue #print('Event %3d'%nevt, ' nda.shape:', nda.shape) if do_print(nevt): print('Event %3d' % nevt, ' nda.shape:', nda.shape) print(' -> RUNINFO EXPNAME :', EXPNAME) print(' -> RUNINFO RUNNUM :', RUNNUM) print(' HDF5 -> EVENTID exp :', eventid['experiment'][nevt].decode()) print(' HDF5 -> EVENTID run :', eventid['run'][nevt]) print(' HDF5 -> EVENTID time :', eventid['time'][nevt]) print(' HDF5 -> EBEAM charge :', ebeam['Charge'][nevt]) print(' HDF5 -> EBEAM dumpcharge :', ebeam['DumpCharge'][nevt]) print(' HDF5 -> GASDET f_11_ENRC :', gasdet['f_11_ENRC'][nevt]) print(' HDF5 -> XTCAVPARS Beam_energy:', xtcav['XTCAV_Beam_energy_dump_GeV'][nevt]) print_ndarr(nda, ' HDF5 RAW raw:') if RUNINFO in LIST_SAVE: if nevt < 2: runinfo_data = {'expt': EXPNAME, 'runnum': RUNNUM} cydgram.addDet(runinfo_nameinfo, runinfo_alg, runinfo_data) if EBEAM in LIST_SAVE: cydgram.addDet(ebeam_nameinfo, ebeam_alg, {\ 'Charge' : ebeam['Charge' ][nevt],\ 'DumpCharge': ebeam['DumpCharge'][nevt],\ 'XTCAVAmpl' : ebeam['XTCAVAmpl' ][nevt],\ 'XTCAVPhase': ebeam['XTCAVPhase'][nevt],\ 'PkCurrBC2' : ebeam['PkCurrBC2' ][nevt],\ 'L3Energy' : ebeam['L3Energy' ][nevt],\ #'cpohack' : np.array([3]),\ }) if EVENTID in LIST_SAVE: cydgram.addDet(eventid_nameinfo, eventid_alg, {\ 'experiment': eventid['experiment'][nevt].decode(),\ 'run' : eventid['run' ][nevt],\ 'fiducials' : eventid['fiducials' ][nevt],\ 'time' : eventid['time' ][nevt],\ }) if GASDET in LIST_SAVE: cydgram.addDet(gasdet_nameinfo, gasdet_alg, {\ 'f_11_ENRC': gasdet['f_11_ENRC'][nevt],\ 'f_12_ENRC': gasdet['f_12_ENRC'][nevt],\ 'f_21_ENRC': gasdet['f_21_ENRC'][nevt],\ 'f_22_ENRC': gasdet['f_22_ENRC'][nevt],\ 'f_63_ENRC': gasdet['f_63_ENRC'][nevt],\ 'f_64_ENRC': gasdet['f_64_ENRC'][nevt],\ }) if XTCAVPARS in LIST_SAVE: cydgram.addDet(xtcav_nameinfo, xtcav_alg, {\ 'XTCAV_Analysis_Version' : xtcav['XTCAV_Analysis_Version' ][nevt],\ 'XTCAV_ROI_sizeX' : xtcav['XTCAV_ROI_sizeX' ][nevt],\ 'XTCAV_ROI_sizeY' : xtcav['XTCAV_ROI_sizeY' ][nevt],\ 'XTCAV_ROI_startX' : xtcav['XTCAV_ROI_startX' ][nevt],\ 'XTCAV_ROI_startY' : xtcav['XTCAV_ROI_startY' ][nevt],\ 'XTCAV_calib_umPerPx' : xtcav['XTCAV_calib_umPerPx' ][nevt],\ 'OTRS_DMP1_695_RESOLUTION' : xtcav['OTRS:DMP1:695:RESOLUTION' ][nevt],\ 'XTCAV_strength_par_S' : xtcav['XTCAV_strength_par_S' ][nevt],\ 'OTRS_DMP1_695_TCAL_X' : xtcav['OTRS:DMP1:695:TCAL_X' ][nevt],\ 'XTCAV_Amp_Des_calib_MV' : xtcav['XTCAV_Amp_Des_calib_MV' ][nevt],\ 'SIOC_SYS0_ML01_AO214' : xtcav['SIOC:SYS0:ML01:AO214' ][nevt],\ 'XTCAV_Phas_Des_calib_deg' : xtcav['XTCAV_Phas_Des_calib_deg' ][nevt],\ 'SIOC_SYS0_ML01_AO215' : xtcav['SIOC:SYS0:ML01:AO215' ][nevt],\ 'XTCAV_Beam_energy_dump_GeV' : xtcav['XTCAV_Beam_energy_dump_GeV' ][nevt],\ 'REFS_DMP1_400_EDES' : xtcav['REFS:DMP1:400:EDES' ][nevt],\ 'XTCAV_calib_disp_posToEnergy': xtcav['XTCAV_calib_disp_posToEnergy'][nevt],\ 'SIOC_SYS0_ML01_AO216' : xtcav['SIOC:SYS0:ML01:AO216' ][nevt],\ }) if RAW in LIST_SAVE: cydgram.addDet(raw_nameinfo, raw_alg, {'array': nda}) t_sec_nsec = eventid['time'][nevt] timestamp = time_stamp(t_sec_nsec) t_sec, t_nsec = t_sec_nsec timestamp = timestamp if t_sec else nevt transitionid = None if (nevt == 0): transitionid = 2 # Configure elif (nevt == 1): transitionid = 4 # BeginRun else: transitionid = 12 # L1Accept xtc_bytes = cydgram.get(timestamp, transitionid) f.write(xtc_bytes) f.close()
def proc_data(**kwargs): logger.info(str_kwargs(kwargs, title='Input parameters:')) DSNAME = kwargs.get( 'dsname', '/reg/g/psdm/detector/data2_test/xtc/data-amox27716-r0100-acqiris-e001000.xtc2' ) DETNAME = kwargs.get('detname', 'tmo_quadanode') EVSKIP = kwargs.get('evskip', 0) EVENTS = kwargs.get('events', 10) + EVSKIP EXP = kwargs.get('exp', 'amox27716') RUN = kwargs.get('run', 85) VERBOSE = kwargs.get('verbose', True) PLOT = kwargs.get('plot', False) OFPREFIX = kwargs.get('ofprefix', './') PARAMSCFD = kwargs.get('paramsCFD') NUMCHS = kwargs.get('numchs', 5) NUMHITS = kwargs.get('numhits', 16) ds = DataSource(files=DSNAME) orun = next(ds.runs()) det = orun.Detector(DETNAME) dldpars = {'consts': det.calibconst} # Update calibcfg and calibtab kwargs.update(dldpars) tb_sec = time() nev = 0 # Counts no. of channels with different no. peaks from CFD(raw) and CFD(win) cn_match = 0 cn_unmatch = 0 cn_match_dld = 0 cn_unmatch_dld = 0 # Summing differences between each peak from CFD(raw) and CFD(win) sum_err = 0 sum_pks = 0 # Summing differences between x,y,r,t (output from Roentdek) sum_err_dld = np.zeros([EVENTS, 4], dtype=np.float64) # Initialize PyCFD per channel cfds = {} for i_chan in range(NUMCHS): CFD_params = PARAMSCFD[i_chan] cfds[i_chan] = PyCFD(CFD_params) # This is used for calculate Roentdek algorithm (_c is for checking # peaks from simulated fex data). proc = DLDProcessor(**kwargs) proc_c = DLDProcessor(**kwargs) # Initialize dgrampy and generate starting transitions for xtc2 out_i_chan = 4 out_xtcfname = f"data-r0085-s{str(out_i_chan).zfill(3)}-c000.xtc2" segment_id = 4 ts = 0 data_names, datadef = dgrampy_start(EXP, RUN, out_xtcfname, segment_id, ts) ts += 4 # Configure, BeginRun, BeginStep, Enable for nev, evt in enumerate(orun.events()): if nev < EVSKIP: continue if nev >= EVENTS: break if do_print(nev): logger.info('Event %4d' % nev) t0_sec = time() wts = det.raw.times(evt) wfs = det.raw.waveforms(evt) # Function peaks returns `pktsec` for each channel. We need to locate # index of these peaks in wts. The indices will be used to identify # windows of waveform wfs and startpos in wts. NUMCHS = wfs.shape[0] window_size = 8 nhits = np.zeros(NUMCHS, dtype=np.int64) pktsec = np.zeros([NUMCHS, NUMHITS], dtype=wts.dtype) nhits_fex = np.zeros(NUMCHS, dtype=np.int64) pktsec_fex = np.zeros([NUMCHS, NUMHITS], dtype=wts.dtype) for i_chan in range(NUMCHS): # Find peaks using CFD CFD_params = PARAMSCFD[i_chan] CFD = cfds[i_chan] pktsec_chan = CFD.CFD(wfs[i_chan, :], wts[i_chan, :]) nhits_chan = min(len(pktsec_chan), NUMHITS) nhits[i_chan] = nhits_chan pktsec[i_chan, :nhits_chan] = pktsec_chan[:nhits_chan] # Calculate sample interval sample_intervals = wts[i_chan, 1:] - wts[i_chan, :-1] # Find peak indices peak_ind = np.searchsorted(wts[i_chan, :], pktsec_chan) if False: plt.plot(wts[i_chan, :], wfs[i_chan, :], label='waveform') # Get peak values from found indices pktval = wfs[i_chan, peak_ind] plt.scatter(pktsec_chan, pktval, marker='o', c='r', label=f'CFD peaks #{nhits[i_chan]}') plt.scatter( wts[i_chan, peak_ind], pktval, marker='x', c='g', label=f'ts from found indices #{len(wts[i_chan, peak_ind])}' ) plt.legend() plt.show() # Find peak windows pkwin_list, startpos_list, result_peaks = get_window_from_peaks( wfs[i_chan, :], wts[i_chan, :], peak_ind, window_size, plot=PLOT, CFD=CFD, sample_period=CFD_params['sample_interval'], threshold=CFD_params['threshold']) # Save hits and peaks from fex data nhits_chan_fex = min(len(result_peaks), NUMHITS) nhits_fex[i_chan] = nhits_chan_fex pktsec_fex[i_chan, :nhits_chan_fex] = result_peaks[:nhits_chan_fex] # Write out one channel at a time (change out_i_chan to switch file) if i_chan == out_i_chan: dgrampy_adddata(data_names, datadef, startpos_list, pkwin_list, ts) ts += 1 # Calculate the differences betwen CFD(raw) and CFD(windows) if len(result_peaks) == nhits[i_chan]: sum_err += np.sum( np.absolute( np.asarray(pktsec_chan) - np.asarray(result_peaks))) sum_pks += nhits[i_chan] cn_match += 1 else: cn_unmatch += 1 # end for i_chan... # Test RoenDek algorithm proc.event_proc(nev, nhits, pktsec) proc_c.event_proc(nev, nhits_fex, pktsec_fex) xyrt = proc.xyrt_list(nev, nhits, pktsec) xyrt_c = proc_c.xyrt_list(nev, nhits_fex, pktsec_fex) if len(xyrt) == len(xyrt_c): for i, ((x, y, r, t), (x_c, y_c, r_c, t_c)) in enumerate(zip(xyrt, xyrt_c)): dx = abs(x - x_c) dy = abs(y - y_c) dr = abs(r - r_c) dt = abs(t - t_c) sum_err_dld[nev, :] = [dx, dy, dr, dt] print(' ev:%4d hit:%2d dx:%7.3f dy:%7.3f dt:%10.5g dr:%7.3f' % (nev, i, dx, dy, dt, dr)) cn_match_dld += 1 else: cn_unmatch_dld += 1 if VERBOSE: print(" ev:%4d waveforms processing time = %.6f sec" % (nev, time() - t0_sec)) print_ndarr(wfs, ' waveforms : ', last=4) print_ndarr(wts, ' times : ', last=4) print_ndarr(nhits, ' number_of_hits : ') # end for nev, evt in... dgrampy_done(ts) print("Summary ev:%4d processing time = %.6f sec" % (nev, time() - tb_sec)) print( f"average err per channel: {sum_err/sum_pks} #unmatch: {cn_unmatch} ({(cn_unmatch/(5*nev))*100:.2f} %)" ) print( f"average err(x,y,r,t) per evt: {np.sum(sum_err_dld, axis=0)/nev} #unmatch: {cn_unmatch_dld} ({(cn_unmatch_dld/nev)*100:.2f} %)" )