diff --git a/src/toolbox_scs/constants.py b/src/toolbox_scs/constants.py index 09784e727a6e1934cd13f2e3117b5402113c13ef..0390277670b1a707e0c6db49719043034361a505 100644 --- a/src/toolbox_scs/constants.py +++ b/src/toolbox_scs/constants.py @@ -147,6 +147,17 @@ mnemonics = { 'key': 'interlock.AActionState.value', 'dim': None},), + # XTD10 MCP (after GATT) + 'XTD10_MCP3raw': ({'source': 'SA3_XTD10_MCP/ADC/1:channel_3.output', + 'key': 'data.rawData', + 'dim': ['XTD10_MCPsampleId']},), + 'XTD10_MCP5raw': ({'source': 'SA3_XTD10_MCP/ADC/1:channel_5.output', + 'key': 'data.rawData', + 'dim': ['XTD10_MCPsampleId']},), + 'XTD10_MCP9raw': ({'source': 'SA3_XTD10_MCP/ADC/1:channel_9.output', + 'key': 'data.rawData', + 'dim': ['XTD10_MCPsampleId']},), + # DPS imagers "DPS1CAM2": ({'source': 'SCS_BLU_DPS-1/CAM/IMAGER2CAMERA:daqOutput', 'key': 'data.image.pixels', diff --git a/src/toolbox_scs/detectors/digitizers.py b/src/toolbox_scs/detectors/digitizers.py index 339d17a90ec6448bdb095573e5af590adc0a73e6..eb3ba8f53bb55fb0e1ddb95292b8e9d862c84021 100644 --- a/src/toolbox_scs/detectors/digitizers.py +++ b/src/toolbox_scs/detectors/digitizers.py @@ -279,6 +279,7 @@ def get_peaks(run, # 2. Use raw data from digitizer # minimum pulse period @ 4.5MHz, according to digitizer type + digitizer = digitizer_type(source=source) min_distance = 1 if digitizer == 'FastADC': min_distance = 24 @@ -356,8 +357,7 @@ def get_peaks(run, return peaks.assign_coords({extra_dim: pid}) -def channel_peak_params(run, source, key=None, digitizer=None, - channel=None, board=None): +def channel_peak_params(run, source, key=None, channel=None, board=None): """ Extract peak-integration parameters used by a channel of the digitizer. @@ -372,13 +372,12 @@ def channel_peak_params(run, source, key=None, digitizer=None, key: str optional, used in combination of source (if source is not a ToolBox mnemonics) instead of digitizer, channel and board. - digitizer: {"FastADC", "ADQ412"} str - Type of digitizer. If None, inferred from the source mnemonic. channel: int or str The digitizer channel for which to retrieve the parameters. If None, - inferred from the source mnemonic. + inferred from the source mnemonic or source + key arguments. board: int - Board of the ADQ412. If None, inferred from the source mnemonic. + Board of the ADQ412. If None, inferred from the source mnemonic or + source + key arguments. Returns ------- @@ -389,58 +388,116 @@ def channel_peak_params(run, source, key=None, digitizer=None, m = run_mnemonics[source] source = m['source'] key = m['key'] - if key is not None: - if 'network' in source: - digitizer = 'ADQ412' - ch_to_int = {'A': 0, 'B': 1, 'C': 2, 'D': 3} - k = key.split('.')[1].split('_') - channel = ch_to_int[k[2]] - board = k[1] - else: - digitizer = 'FastADC' - channel = int(source.split(':')[1].split('.')[0].split('_')[1]) - if digitizer is None: - raise ValueError('digitizer argument is missing.') + if 'network' in source: + return adq412_channel_peak_params(run, source, key, channel, board) + else: + return fastADC_channel_peak_params(run, source, channel) + + +def fastADC_channel_peak_params(run, source, channel=None): + """ + Extract peak-integration parameters used by a channel of the Fast ADC. + + Parameters + ---------- + run: extra_data.DataCollection + DataCollection containing the digitizer data. + source: str + Name of Fast ADC source, e.g. 'SCS_UTC1_MCP/ADC/1:channel_5.output'. + channel: int + The Fast ADC channel for which to retrieve the parameters. If None, + inferred from the source. + + Returns + ------- + dict with peak integration parameters. + """ + fastADC_keys = { + 'baseStart': ('baselineSettings.baseStart.value', + 'baseStart.value'), + 'baseStop': ('baseStop.value',), + 'baseLength': ('baselineSettings.length.value',), + 'enable': ('enablePeakComputation.value',), + 'pulseStart': ('initialDelay.value',), + 'pulseLength': ('peakSamples.value',), + 'npulses': ('numPulses.value',), + 'period': ('pulsePeriod.value',) + } if channel is None: - raise ValueError('channel argument is missing.') - if isinstance(channel, str): - ch_to_int = {'A': 0, 'B': 1, 'C': 2, 'D': 3} - channel = ch_to_int[channel] - if board is None and digitizer == 'ADQ412': - raise ValueError('board argument is missing.') - keys = None - if digitizer == 'ADQ412': - baseKey = f'board{board}.apd.channel_{channel}.' - keys = ['baseStart', 'baseStop', 'pulseStart', - 'pulseStop', 'initialDelay', 'upperLimit', - 'enable'] - keys = {k: baseKey + k + '.value' for k in keys} - keys['npulses'] = f'board{board}.apd.numberOfPulses.value' - if digitizer == 'FastADC': - if ":" in source: - baseKey = source.split(':')[1].split('.')[0]+'.' - else: - baseKey = f'channel_{channel}.' - keys = ['baseStart', 'baseStop', 'initialDelay', - 'peakSamples', 'numPulses', 'pulsePeriod', - 'enablePeakComputation'] - keys = {k: baseKey + k + '.value' for k in keys} - if ":" in source: - source = source.split(':')[0] - tid, data = run.select(source).train_from_index(0) - result = [data[source][k] for k in keys.values()] - result = dict(zip(keys.keys(), result)) - if digitizer == 'ADQ412': - result['period'] = result.pop('upperLimit') - \ - result.pop('initialDelay') - if digitizer == 'FastADC': - result['period'] = result.pop('pulsePeriod') - result['npulses'] = result.pop('numPulses') - result['pulseStart'] = result['initialDelay'] - result['pulseStop'] = result.pop('initialDelay') + \ - result.pop('peakSamples') - result['enable'] = result.pop('enablePeakComputation') + channel = int(source.split(':')[1].split('.')[0].split('_')[1]) + baseName = f'channel_{channel}.' + source = source.split(':')[0] + data = run.select(source).train_from_index(0)[1][source] + result = {} + for mnemo, versions in fastADC_keys.items(): + for v in versions: + key = baseName + v + if key in data: + result[mnemo] = data[key] + if 'baseLength' in result: + result['baseStop'] = result['baseStart'] + \ + result.pop('baseLength') + if 'pulseLength' in result: + result['pulseStop'] = result['pulseStart'] + \ + result.pop('pulseLength') + return result + + +def adq412_channel_peak_params(run, source, key=None, + channel=None, board=None): + """ + Extract peak-integration parameters used by a channel of the ADQ412. + + Parameters + ---------- + run: extra_data.DataCollection + DataCollection containing the digitizer data. + source: str + Nname of ADQ412 source, e.g. 'SCS_UTC1_ADQ/ADC/1:network'. + key: str + optional, e.g. 'digitizers.channel_1_D.apd.pulseIntegral', used in + combination of source instead of channel and board. + channel: int or str + The ADQ412 channel for which to retrieve the parameters. If None, + inferred from the source mnemonic or source + key arguments. + board: int + Board of the ADQ412. If None, inferred from the source mnemonic or + source + key arguments. + Returns + ------- + dict with peak integration parameters. + """ + if key is None: + if channel is None or board is None: + raise ValueError('key or channel + board arguments are ' + 'missing.') + else: + k = key.split('.')[1].split('_') + ch_to_int = {'A': 0, 'B': 1, 'C': 2, 'D': 3} + channel = ch_to_int[k[2]] + board = k[1] + baseName = f'board{board}.apd.channel_{channel}.' + source = source.split(':')[0] + adq412_keys = { + 'baseStart': (baseName + 'baseStart.value',), + 'baseStop': (baseName + 'baseStop.value',), + 'enable': (baseName + 'enable.value',), + 'pulseStart': (baseName + 'pulseStart.value',), + 'pulseStop': (baseName + 'pulseStop.value',), + 'initialDelay': (baseName + 'initialDelay.value',), + 'upperLimit': (baseName + 'upperLimit.value',), + 'npulses': (f'board{board}.apd.numberOfPulses.value',) + } + + data = run.select(source).train_from_index(0)[1][source] + result = {} + for mnemo, versions in adq412_keys.items(): + for key in versions: + if key in data: + result[mnemo] = data[key] + result['period'] = result.pop('upperLimit') - \ + result.pop('initialDelay') return result @@ -531,7 +588,8 @@ def get_peak_params(run, mnemonic, raw_trace=None, ntrains=200): title = 'Digitizer peak params' else: mnemo_raw = mnemonic - min_distance = 24 if "FastADC" in mnemonic else 440 + digitizer = digitizer_type(mnemonic, run_mnemonics) + min_distance = 24 if digitizer == "FastADC" else 440 title = 'Auto-find peak params' if raw_trace is None: sel = run.select_trains(np.s_[:ntrains]) @@ -597,7 +655,8 @@ def check_peak_params(run, mnemonic, raw_trace=None, ntrains=200, params=None, log.warning('The digitizer did not record peak-integrated data.') if not plot: return params - min_distance = 24 if "FastADC" in mnemonic else 440 + digitizer = digitizer_type(mnemonic, run_mnemonics) + min_distance = 24 if digitizer == "FastADC" else 440 if 'bunchPatternTable' in run_mnemonics and bunchPattern != 'None': sel = run.select_trains(np.s_[:ntrains]) bp_params = {} @@ -697,6 +756,24 @@ def plotPeakIntegrationWindow(raw_trace, params, bp_params, show_all=False): return fig, ax +def digitizer_type(mnemonic=None, mnemo_dict=None, source=None): + if mnemonic is not None: + source = mnemo_dict[mnemonic]['source'] + if ':channel' in source: + return 'FastADC' + if ':network' in source: + return 'ADQ412' + dic = {'XTD10_MCP': 'FastADC', + 'FastADC': 'FastADC', + 'PES': 'ADQ412', + 'MCP': 'ADQ412'} + for k, v in dic.items(): + if k in mnemonic: + return v + log.warning(f'Could not find digitizer type from mnemonic {mnemonic}.') + return 'ADQ412' + + def get_tim_peaks(run, mnemonics=None, merge_with=None, bunchPattern='sase3', integParams=None, keepAllSase=False): @@ -845,6 +922,9 @@ def get_digitizer_peaks(run, mnemonics, digitizer, merge_with=None, elif 'bunchPatternTable' in run_mnemonics: bpt = run.get_array(*run_mnemonics['bunchPatternTable'].values()) log.debug('Loaded bpt from DataCollection.') + elif 'bunchPatternTable_SA3' in run_mnemonics: + bpt = run.get_array(*run_mnemonics['bunchPatternTable_SA3'].values()) + log.debug('Loaded bpt from DataCollection.') else: bpt = None diff --git a/src/toolbox_scs/load.py b/src/toolbox_scs/load.py index d51b5b1933d2f17b22e5d5080992e2ab15846677..b959361ed7f9938f249da2db6b9415ca1e93b63e 100644 --- a/src/toolbox_scs/load.py +++ b/src/toolbox_scs/load.py @@ -130,20 +130,13 @@ def load(proposalNB=None, runNB=None, run.info() data_arrays = [] - run_mnemonics = mnemonics_for_run(run) # load pulse pattern info - if 'bunchPatternTable' in run_mnemonics: - bpt = run.get_array(*run_mnemonics['bunchPatternTable'].values(), - name='bunchPatternTable') - data_arrays.append(bpt) - elif 'bunchPatternTable_SA3' in run_mnemonics: - log.info('Did not find SCS bunch pattern table but found the SA3 one.') - bpt = run.get_array(*run_mnemonics['bunchPatternTable_SA3'].values(), - name='bunchPatternTable') - data_arrays.append(bpt) - else: + bpt = load_bpt(run, run_mnemonics=run_mnemonics) + if bpt is None: log.warning('Bunch pattern table not found in run. Skipping!') + else: + data_arrays.append(bpt) for f in fields: if type(f) == dict: @@ -329,3 +322,20 @@ def get_array(run, mnemonic_key=None, stepsize=None): raise return data + + +def load_bpt(run, merge_with=None, run_mnemonics=None): + if run_mnemonics is None: + run_mnemonics = mnemonics_for_run(run) + + for key in ['bunchPatternTable', 'bunchPatternTable_SA3']: + if bool(merge_with) and key in merge_with: + log.debug(f'Using {key} from merge_with dataset.') + return merge_with[key] + if key in run_mnemonics: + bpt = run.get_array(*run_mnemonics[key].values(), + name='bunchPatternTable') + log.debug(f'Loaded {key} from DataCollection.') + return bpt + log.debug('Could not find bunch pattern table.') + return None diff --git a/src/toolbox_scs/mnemonics_machinery.py b/src/toolbox_scs/mnemonics_machinery.py index a3aa8f03d230542ed426c0ca985d43619e65f5c9..f7b5a031c23005e9da889813f2dd184a57f33602 100644 --- a/src/toolbox_scs/mnemonics_machinery.py +++ b/src/toolbox_scs/mnemonics_machinery.py @@ -87,7 +87,7 @@ def mnemonics_to_process(mnemo_list, merge_with, detector, func=None): merge_with: xarray Dataset Dataset that may contain non-processed arrays detector: str - One in {'ADQ412', 'FastADC', 'XGM', 'BAM'} + One in {'ADQ412', 'FastADC', 'XGM', 'BAM', 'PES'} func: function function that takes one argument, an unprocessed mnemonic string, and converts it into a processed one, i.e. from 'MCP2apd' to @@ -114,7 +114,8 @@ def mnemonics_to_process(mnemo_list, merge_with, detector, func=None): default_mnemo = 'SCS_SA3' default_processed = 'SCS_SA3' if detector == 'ADQ412': - det_mnemos = [m for m in _mnemonics if 'MCP' in m] + det_mnemos = [m for m in _mnemonics if 'MCP' in m and + 'XTD10_' not in m] default_mnemo = 'MCP2apd' default_processed = 'MCP2peaks' if detector == 'FastADC':