CHARGE HISTOGRAM#
Make sure that you have access to data files (have a look at some examples in
/eos/experiment/neutplatform/protodune/experiments/ProtoDUNE-II/PDS_Commissioning/waffles/0_TUTORIAL)If you want to analyze new data, you need to pre-process the decoder first to extract PDS information from the raw
hdf5file provided by the data acquisition system. Have a look at the00_HDF5toROOTscripts for this.
[ ]:
# IMPORT ALL THE LIBRARIES USED IN THE NOTEBOOK
import os
import numpy as np
import plotly.subplots as psu
from data.ProtoDUNE_HD_APA_maps import APA_map
# IMPORT ALL THE CLASSES/METHODS DEFINED IN WAFFLES
import waffles
[ ]:
def constraint_adcs_range_in_integration_window(waveform : waffles.Waveform,
analysis_label : str = 'standard',
min_adcs_in_int_range : int = -300,
max_adcs_in_int_range : int = 50) -> bool:
int_ll = waveform.Analyses[analysis_label].IntLl
int_ul = waveform.Analyses[analysis_label].IntUl
if np.min(waveform.Adcs[ int_ll : int_ul ] - waveform.Analyses['standard'].Result.Baseline) < min_adcs_in_int_range:
return False
elif np.max(waveform.Adcs[ int_ll : int_ul ] - waveform.Analyses['standard'].Result.Baseline) > max_adcs_in_int_range:
return False
else:
return True
[ ]:
# # APAs 3 and 4
# range(27089, 27099)
# APAs 3 and 4 with actual trim
# range(27909, 27913)
# # APA 2
# range(27120, 27131)
# APAs 1 & 2
# range(27818, 27828)
[ ]:
filepaths = ['/eos/experiment/neutplatform/protodune/experiments/ProtoDUNE-II/PDS_Commissioning/waffles/0_TUTORIAL/run26687.root']
saving_folderpath = '.'
runs = [26687]
[ ]:
## AUXILIARY CELLS WHEN WORKING WITH MULTIPLE RUNS ##
# base_folderpath = 'path/to/data/folder' # The folder where all of the .root files are stored
# data_folderpath = f"{base_folderpath}/data"
# saving_folderpath = f"{base_folderpath}/plots"
# filepaths = []
# runs = []
# for file_name in os.listdir(filepath):
# if file_name.endswith('.root'):
# runs.append( int(file_name.split('_')[1]) )
# filepaths.append( os.path.join(data_folderpath, file_name) )
# sorting_idcs = np.argsort(runs)
# runs = [runs[idx] for idx in sorting_idcs]
# filepaths = [filepaths[idx] for idx in sorting_idcs]
[ ]:
label = 'standard'
analyser_name = 'standard_analyser'
baseline_limits = [0, 100, 900, 1000] # Used for APAs 2, 3 and 4
# baseline_limits = [100, 400] # Used for APA 1 in short-window runs
starting_tick = { 27818 : 621, # Used for APA 1
27820 : 615,
27822 : 615,
27823 : 615,
27824 : 615,
27825 : 615,
27826 : 615,
27827 : 632,
27828 : 626}
# When working with several runs you can use a dictionary to specify the starting tick for each run
starting_tick = {run : 125 for run in runs} # Used for APAs 2, 3 and 4
aux_width = 40
analysis_args = (analyser_name, baseline_limits)
analysis_kwargs = dict( overwrite = True,
prominence = 100,
rel_height = 0.5,
width = [0,75],
return_peaks_properties = True)
# filter_args = (label,)
# filter_kwargs = dict( min_adcs_in_int_range = -300,
# max_adcs_in_int_range = 50)
[ ]:
apas = []
bins_number = 200
figures = {}
for rdx,run in enumerate(runs): # Useful if you are working with several runs
wfset = waffles.WaveformSet.from_ROOT_file( filepaths[rdx],
library = 'pyroot',
bulk_data_tree_name = 'raw_waveforms',
meta_data_tree_name = 'metadata',
set_offset_wrt_daq_window = False,
read_full_streaming_data = False,
truncate_wfs_to_minimum = False,
start_fraction = 0.0,
stop_fraction = 1.0,
subsample = 1)
print(f"Done reading run {run} stored in {filepaths[rdx]}")
aux = wfset.get_set_of_endpoints()
apas.append([])
print(f"In run {run} there's information for the following APAs: ", end='')
if 104 in aux or 105 in aux or 107 in aux:
print("APA 1 ", end='')
apas[-1].append(1)
if 109 in aux:
print("APA 2 ", end='')
apas[-1].append(2)
if 111 in aux:
print("APA 3 ", end='')
apas[-1].append(3)
if 112 in aux or 113 in aux:
print("APA 4 ", end='')
apas[-1].append(4)
print('', end='\n')
print(f"wfset.PointsPerWf = {wfset.PointsPerWf}")
analysis_kwargs['int_ll'] = starting_tick[run]
analysis_kwargs['int_ul'] = starting_tick[run] + aux_width
# Future waffles release will include amp_ll and amp_ul as arguments
# analysis_kwargs['amp_ll'] = starting_tick[run]
# analysis_kwargs['amp_ul'] = starting_tick[run] + aux_width
_ = wfset.analyse( label,
*analysis_args,
**analysis_kwargs)
print(f"Done analysing run {runs}")
## Uncomment this if you want to filter the WaveformSet ##
# wfset = WaveformSet.from_filtered_WaveformSet( wfset,
# constraint_adcs_range_in_integration_window,
# *filter_args,
# **filter_kwargs)
# print(f"Done filtering run {runs}")
for apa in apas[-1]:
print(f"Now plotting {apa}")
identifier = f"Run {list(wfset.Runs)[0]} - APA{apa}"
grid_apa = waffles.ChannelWSGrid( APA_map[apa],
wfset,
compute_calib_histo = True,
bins_number = bins_number,
domain = np.array((-10000., 50000.)),
variable = 'integral',
analysis_label = None)
figure = grid_apa.plot( share_x_scale = True,
share_y_scale = True,
mode = 'heatmap',
wfs_per_axes = None,
analysis_label = 'standard',
time_bins = aux_width,
adc_bins = 175,
time_range_lower_limit = starting_tick[run],
time_range_upper_limit = starting_tick[run] + aux_width,
adc_range_above_baseline = 25,
adc_range_below_baseline = 150,
detailed_label = True)
figure.update_layout( width = 1100,
height=1200,
showlegend = True,
title = identifier)
figure.show()
figure.write_image(f"{saving_folderpath}/{identifier}_heatmap.png")
figure.write_json(f"{saving_folderpath}/{identifier}_heatmap.json")
figure = grid_apa.plot( share_x_scale = False,
share_y_scale = False,
mode = 'calibration',
wfs_per_axes = None,
analysis_label = 'standard',
plot_peaks_fits = False,
detailed_label = True)
figure.update_layout( width = 1100,
height=1200,
showlegend = True,
title = identifier)
figure.show()
figure.write_image(f"{saving_folderpath}/{identifier}_calibration.png")
figure.write_json(f"{saving_folderpath}/{identifier}_calibration.json")
print(f"Done plotting {apa}")
print(f"Done saving {identifier}")
del wfset