From cc3c95fe31b21f268dcf5ceee626fb3d92c8423b Mon Sep 17 00:00:00 2001 From: Eric Torrence <eric.torrence@cern.ch> Date: Thu, 21 Apr 2022 05:47:26 +0200 Subject: [PATCH] Waveform updates --- CablingDB/cablingDB.py | 61 ++++++++++++++- CablingDB/extractDigitizerMapping.py | 48 +++++++++++- CablingDB/extractDigitizerScale.py | 107 +++++++++++++++++++++++++++ 3 files changed, 212 insertions(+), 4 deletions(-) create mode 100755 CablingDB/extractDigitizerScale.py diff --git a/CablingDB/cablingDB.py b/CablingDB/cablingDB.py index 50a742f..07757ea 100755 --- a/CablingDB/cablingDB.py +++ b/CablingDB/cablingDB.py @@ -528,10 +528,46 @@ digi_map = { ('preshower', 0, 0, 0), ('preshower', 0, 1, 0), ('none', 0), + ('clock', 0)], + 6525: [('calo', 0, 1, 0), + ('calo', 0, 0, 0), + ('calo', 1, 1, 0), + ('calo', 1, 0, 0), + ('vetonu', 0, 0, 0), + ('vetonu', 0, 1, 0), + ('veto', 1, 0, 0), + ('veto', 1, 1, 0), + ('timing', 0, 0, 1), + ('timing', 0, 0, 0), + ('timing', 0, 1, 1), + ('timing', 0, 1, 0), + ('preshower', 0, 0, 0), + ('preshower', 0, 1, 0), + ('veto', 0, 1, 0), ('clock', 0)] } +# Range map from extractDigitizerScale.py +range_map = { + 432: {0: 2.0, + 1: 2.0, + 2: 2.0, + 3: 2.0, + 4: 2.0, + 5: 2.0, + 6: 2.0, + 7: 2.0, + 8: 2.0, + 9: 2.0, + 10: 2.0, + 11: 2.0, + 12: 2.0, + 13: 2.0, + 14: 2.0, + 15: 2.0} +} + # Look for data entry errors print('Validating TRB data') @@ -573,7 +609,7 @@ for run, data in digi_map.items(): assert isinstance(data[i][1], int), 'Digitizer station is not int' assert isinstance(data[i][2], int), 'Digitizer plane is not int' assert isinstance(data[i][3], int), 'Digitizer pmt is not int' - assert data[i][0] in ['trigger', 'veto', 'preshower', 'calo'], 'Invalid type' + assert data[i][0] in ['trigger', 'timing', 'veto', 'vetonu', 'preshower', 'calo'], 'Invalid type' assert data[i][1] >= -1 and data[i][1] <= 1, 'Invalid station number' assert data[i][2] >= -1 and data[i][2] <= 3, 'Invalid plate number' assert data[i][3] >= -1 and data[i][3] <= 1, 'Invalid pmt number' @@ -635,7 +671,8 @@ for firstValidRun, mapping in reversed(digi_map.items()): cableRecord['row'] = mapping[channel][1] cableRecord['module'] = mapping[channel][2] cableRecord['pmt'] = mapping[channel][3] - elif cableRecord['type'] in ['trigger', 'veto', 'preshower']: + # Already asserted allowable types above + elif len(mapping[channel]) == 4: cableRecord['station'] = mapping[channel][1] cableRecord['plate'] = mapping[channel][2] cableRecord['pmt'] = mapping[channel][3] @@ -644,7 +681,27 @@ for firstValidRun, mapping in reversed(digi_map.items()): lastValid = ((firstValidRun - 1) << 32) | (cool.ValidityKeyMax & 0x00000000FFFFFFFF) +# Add digitizer scale +print('Recreating digitizer scale') + +digiSpec = cool.RecordSpecification() +digiSpec.extend('range', cool.StorageType.Float) + +digiFolderSpec = cool.FolderSpecification(cool.FolderVersioning.SINGLE_VERSION, digiSpec) +digiFolder = db.createFolder('/WAVE/DAQ/Range', digiFolderSpec, description, True) + +# There should be one record entered per IOV +lastValid = cool.ValidityKeyMax +for firstValidRun, mapping in reversed(range_map.items()): + firstValid = (firstValidRun << 32) + for channel in range(16): + digiRecord = cool.Record(digiSpec) + digiRecord['range'] = mapping[channel] + digiFolder.storeObject( firstValid, lastValid, digiRecord, int(channel) ) + + lastValid = ((firstValidRun - 1) << 32) | (cool.ValidityKeyMax & 0x00000000FFFFFFFF) +# Done db.closeDatabase() print('Database completed') diff --git a/CablingDB/extractDigitizerMapping.py b/CablingDB/extractDigitizerMapping.py index 9619462..a5278d9 100755 --- a/CablingDB/extractDigitizerMapping.py +++ b/CablingDB/extractDigitizerMapping.py @@ -5,6 +5,21 @@ import copy import pprint import sys import requests +import argparse + +# Parse any command-line options +parser = argparse.ArgumentParser(description="Digitizer Mapping Checker") + +parser.add_argument("-r", "--firstRun", default=0, + help="Specify first run to consider (default: all)") + +args = parser.parse_args() +try: + first_run = int(args.firstRun) +except Exception as e: + print("Error parsing first run:") + print(e) + sys.exit(-1) # This only works on lxplus response = requests.get("http://faser-runnumber.web.cern.ch/RunList") @@ -16,6 +31,7 @@ digitizer_map={} # Calo: (row, mod, pmt) # Veto/Preshower/Trigger: (station, plate, pmt) +# Orignal TI12 detector, without FASERnu veto TI12_map = [ ('calo', 0, 1, 0), # Digitizer 0 ('calo', 0, 0, 0), @@ -35,6 +51,28 @@ TI12_map = [ ('clock', 0) # Digitizer 15 ] +# TI12 map as of run 6520, when the FASERnu veto is installed +# Installed 3/15/2022, first non-test run 6525 +# Also, rename trigger to timing +TI12_6520_map = [ + ('calo', 0, 1, 0), # Digitizer 0 + ('calo', 0, 0, 0), + ('calo', 1, 1, 0), + ('calo', 1, 0, 0), + ('vetonu', 0, 0, 0), # Digitizer 4 + ('vetonu', 0, 1, 0), + ('veto', 1, 0, 0), # Digitizer 6 + ('veto', 1, 1, 0), + ('timing', 0, 0, 1), # Digitizer 8 + ('timing', 0, 0, 0), + ('timing', 0, 1, 1), + ('timing', 0, 1, 0), + ('preshower', 0, 0, 0), # Digitizer 12 + ('preshower', 0, 1, 0), + ('veto', 0, 1, 0), # Digitizer 14 + ('clock', 0) # Digitizer 15 +] + TB_map = [ ('calo', 1, 2, 0), # Digitizer 0 ('calo', 0, 2, 0), @@ -55,12 +93,15 @@ TB_map = [ ] for info in runs: + + runno=info["runnumber"] + if runno < first_run: continue + # Skip runtypes we don't want to reconstruct runtype = info['type'] if "Calibration" in runtype: continue if runtype == "Test": continue - runno=info["runnumber"] detectors=info["detectors"] digs=[det for det in detectors if det.startswith("DIG")] if not digs: continue @@ -147,7 +188,10 @@ for info in runs: print(f"ERROR: TI12 run {runno} with unusal number of TRBs: {trbIDs}") sys.exit(1) - digitizer_map[runno] = copy.copy(TI12_map) + if runno < 6520: + digitizer_map[runno] = copy.copy(TI12_map) + else: + digitizer_map[runno] = copy.copy(TI12_6520_map) # Remove any channels not enabled in readout first = True diff --git a/CablingDB/extractDigitizerScale.py b/CablingDB/extractDigitizerScale.py new file mode 100755 index 0000000..27a182c --- /dev/null +++ b/CablingDB/extractDigitizerScale.py @@ -0,0 +1,107 @@ +#!/usr/bin/env python3 + +import json +import copy +import pprint +import sys +import requests +import argparse + +# Parse any command-line options +parser = argparse.ArgumentParser(description="Digitizer Scale Checker") + +parser.add_argument("-r", "--firstRun", default=0, + help="Specify first run to consider (default: all)") + +args = parser.parse_args() +try: + first_run = int(args.firstRun) +except Exception as e: + print("Error parsing first run:") + print(e) + sys.exit(-1) + +# This only works on lxplus +response = requests.get("http://faser-runnumber.web.cern.ch/RunList") +runs = response.json() +runs.reverse() + +# Keyed by run number, contains map of channels => ranges +range_map = dict() +prev_map = None + +for info in runs: + + runno=info["runnumber"] + if runno < first_run: continue + + # Skip runtypes we don't want to reconstruct + runtype = info['type'] + if "Calibration" in runtype: continue + if runtype == "Test": continue + + detectors=info["detectors"] + digs=[det for det in detectors if det.startswith("DIG")] + if not digs: continue + trbs=[det for det in detectors if det.startswith("TRB")] + if not trbs: continue + trbIDs=[int(trb[3:]) for trb in trbs] + trbIDs.sort() + host=info["host"].split(".")[0] + + # Check if host makes sense + if not host in ["faser-daq-002","faser-daq-006","faser-daq-009","faser-daq-010"]: + print(f"ERROR: run {runno} is running on unusual host {host} - not on list of runs to ignore") + sys.exit(1) + + # Find the readout channels + query = f"https://faser-runinfo.app.cern.ch/cgibin/getRunInfo.py?runno={runno}" + response = requests.get(query) + config = response.json().get('configuration', None) + + if not config: + print(f"ERROR: run {runno} has no configuration!") + sys.exit(1) + + comps = config['components'] + digi_channels = [] + dynamic_range = dict() + + for comp in comps: + if comp['name'] != "digitizer01": continue + + if not comp.get('modules', None): + + if not comp.get('settings', None): + print(f"ERROR run {runno} has no modules or settings!") + sys.exit(1) + + else: + dig = comp['settings'] + readout = dig['channel_readout'] + + else: + dig = comp['modules'][0] + if dig['name'] != "digitizer01": continue + settings = dig['settings'] + readout = settings['channel_readout'] + + for chan in readout: + chid = int(chan['channel']) + digi_channels.append(chid) + dynamic_range[chid] = float(chan['dynamic_range']) + + break + + # Done filling dynamic_range map + + if prev_map is None or prev_map != dynamic_range: + range_map[runno] = copy.copy(dynamic_range) + prev_map = range_map[runno] + +pprint.pprint(range_map) +#print(digitizer_map) +print(f"Entries: {len(range_map)} runs") + +#FIXME: should add check that last run always have full TI12 detector map future runs... + -- GitLab