From dbe6ab3f51b22118c366680145e6b4935f51e8df Mon Sep 17 00:00:00 2001 From: Christopher Dilks Date: Mon, 23 Feb 2026 17:21:56 -0500 Subject: [PATCH 1/2] test: track usage of hard-coded scaler clock frequencies The DSC2 and STRUCK scaler clock frequencies are stored in CCDB, but they are also hard-coded. This branch adds a magic number to each of the hard-coded assignments, and checks for that magic number when they're (likely) used. Printouts to `stderr` starting with `clockbug` are used to investigate. --- .../java/org/jlab/detector/scalers/DaqScaler.java | 13 +++++++++++++ .../java/org/jlab/detector/scalers/Dsc2Scaler.java | 4 ++-- .../org/jlab/detector/scalers/StruckScaler.java | 6 +++--- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/common-tools/clas-detector/src/main/java/org/jlab/detector/scalers/DaqScaler.java b/common-tools/clas-detector/src/main/java/org/jlab/detector/scalers/DaqScaler.java index 8ae107969c..a144b11142 100644 --- a/common-tools/clas-detector/src/main/java/org/jlab/detector/scalers/DaqScaler.java +++ b/common-tools/clas-detector/src/main/java/org/jlab/detector/scalers/DaqScaler.java @@ -74,6 +74,18 @@ public void add(DaqScaler other) { protected void calibrate(IndexedTable fcupTable,IndexedTable slmTable,double seconds,double liveSeconds) { if (this.clock > 0) { + + String prefix = String.format("clockbug [%s]", this.getClass().getSimpleName()); + if(Math.abs(this.clockFreq - ((1e6)+1)) < 0.1) + System.err.println(String.format("%s: used hard-coded clockFreq from Dsc2Scaler(bank,table,table,seconds)", prefix)); + else if(Math.abs(this.clockFreq - ((1e6)+2)) < 0.1) + System.err.println(String.format("%s: used hard-coded clockFreq from StruckScaler()", prefix)); + else if(Math.abs(this.clockFreq - ((1e6)+3)) < 0.1) + System.err.println(String.format("%s: used hard-coded clockFreq from StruckScaler(table,table,table)", prefix)); + else + System.err.println(String.format("%s: clockFreq OK (value=%f)", prefix, this.clockFreq)); + System.err.println(String.format("%s: %s", prefix, this.toString())); + final double fcup_slope = fcupTable.getDoubleValue("slope",0,0,0); // Hz/nA final double fcup_offset = fcupTable.getDoubleValue("offset",0,0,0); // Hz final double fcup_atten = fcupTable.getDoubleValue("atten",0,0,0); // attenuation @@ -97,6 +109,7 @@ protected void calibrate(IndexedTable fcupTable,IndexedTable slmTable,double sec this.beamCharge = q * fcup_atten / fcup_slope; this.beamChargeGated = qg * fcup_atten / fcup_slope; } + System.err.println(String.format("%s: beamCharge=%f beamChargeGated=%f", prefix, this.beamCharge, this.beamChargeGated)); } } diff --git a/common-tools/clas-detector/src/main/java/org/jlab/detector/scalers/Dsc2Scaler.java b/common-tools/clas-detector/src/main/java/org/jlab/detector/scalers/Dsc2Scaler.java index 5f48d43421..5e4aa3a3d2 100644 --- a/common-tools/clas-detector/src/main/java/org/jlab/detector/scalers/Dsc2Scaler.java +++ b/common-tools/clas-detector/src/main/java/org/jlab/detector/scalers/Dsc2Scaler.java @@ -38,7 +38,7 @@ public Dsc2Scaler() {} * @param seconds dwell time, provided in case the clock rolls over */ public Dsc2Scaler(Bank bank, IndexedTable fcupTable, IndexedTable slmTable, double seconds) { - this.clockFreq=1e6; + this.clockFreq=(1e6)+1; this.read(bank); this.calibrate(fcupTable,slmTable,seconds); } @@ -110,4 +110,4 @@ public final void read(Bank bank) { } } -} \ No newline at end of file +} diff --git a/common-tools/clas-detector/src/main/java/org/jlab/detector/scalers/StruckScaler.java b/common-tools/clas-detector/src/main/java/org/jlab/detector/scalers/StruckScaler.java index 14237ebe62..f940271c61 100644 --- a/common-tools/clas-detector/src/main/java/org/jlab/detector/scalers/StruckScaler.java +++ b/common-tools/clas-detector/src/main/java/org/jlab/detector/scalers/StruckScaler.java @@ -164,7 +164,7 @@ public final Interval getStableInterval(Bank bank, IndexedTable helTable) { } public StruckScaler() { - this.clockFreq = 1e6; + this.clockFreq = (1e6)+2; } /** @@ -178,7 +178,7 @@ public StruckScaler() { public StruckScaler(Bank bank,IndexedTable fcupTable, IndexedTable slmTable, IndexedTable helTable) { // the STRUCK's clock is 1 MHz - this.clockFreq = 1e6; + this.clockFreq = (1e6)+3; // Here we're going to assume the stable period is the same Struck // period throughout a single readout. Almost always correct ... @@ -239,4 +239,4 @@ else if (Input.equals(Input.CLOCK, chan)) { this.calibrate(fcupTable,slmTable); } -} \ No newline at end of file +} From f47e0b933a1021bd8d7dbcf6165cc1f39962bba5 Mon Sep 17 00:00:00 2001 From: Christopher Dilks Date: Wed, 18 Mar 2026 12:30:49 -0400 Subject: [PATCH 2/2] feat: start testing --- .../org/jlab/detector/scalers/DaqScaler.java | 61 +++++++++++++++++-- scan.groovy | 28 +++++++++ test.sh | 19 ++++++ 3 files changed, 103 insertions(+), 5 deletions(-) create mode 100644 scan.groovy create mode 100755 test.sh diff --git a/common-tools/clas-detector/src/main/java/org/jlab/detector/scalers/DaqScaler.java b/common-tools/clas-detector/src/main/java/org/jlab/detector/scalers/DaqScaler.java index a144b11142..ac67b84e7b 100644 --- a/common-tools/clas-detector/src/main/java/org/jlab/detector/scalers/DaqScaler.java +++ b/common-tools/clas-detector/src/main/java/org/jlab/detector/scalers/DaqScaler.java @@ -75,16 +75,38 @@ protected void calibrate(IndexedTable fcupTable,IndexedTable slmTable,double sec if (this.clock > 0) { + // complain if a hard-coded clock frequency was used String prefix = String.format("clockbug [%s]", this.getClass().getSimpleName()); - if(Math.abs(this.clockFreq - ((1e6)+1)) < 0.1) + boolean clockbug = false; + if(Math.abs(this.clockFreq - ((1e6)+1)) < 0.1) { System.err.println(String.format("%s: used hard-coded clockFreq from Dsc2Scaler(bank,table,table,seconds)", prefix)); - else if(Math.abs(this.clockFreq - ((1e6)+2)) < 0.1) + clockbug = true; + } + else if(Math.abs(this.clockFreq - ((1e6)+2)) < 0.1) { System.err.println(String.format("%s: used hard-coded clockFreq from StruckScaler()", prefix)); - else if(Math.abs(this.clockFreq - ((1e6)+3)) < 0.1) + clockbug = true; + } + else if(Math.abs(this.clockFreq - ((1e6)+3)) < 0.1) { System.err.println(String.format("%s: used hard-coded clockFreq from StruckScaler(table,table,table)", prefix)); + clockbug = true; + } else System.err.println(String.format("%s: clockFreq OK (value=%f)", prefix, this.clockFreq)); - System.err.println(String.format("%s: %s", prefix, this.toString())); + + // the hard-coded clock frequency is 1 MHz, but if it was used, it'll be 1 MHz + a few Hz; correct it now, along + // with the `seconds` and `liveSeconds` + if(clockbug) { + seconds *= this.clockFreq / 1e6; + liveSeconds *= this.clockFreq / 1e6; + this.clockFreq = 1e6; + } + + // print the clock + System.err.println(String.format("%s: toString: %s", prefix, this.toString())); + + // ================================================================================== + // original code + // ================================================================================== final double fcup_slope = fcupTable.getDoubleValue("slope",0,0,0); // Hz/nA final double fcup_offset = fcupTable.getDoubleValue("offset",0,0,0); // Hz @@ -109,7 +131,36 @@ else if(Math.abs(this.clockFreq - ((1e6)+3)) < 0.1) this.beamCharge = q * fcup_atten / fcup_slope; this.beamChargeGated = qg * fcup_atten / fcup_slope; } - System.err.println(String.format("%s: beamCharge=%f beamChargeGated=%f", prefix, this.beamCharge, this.beamChargeGated)); + + // ================================================================================== + + // print the beamCharge from the original code + System.err.println(String.format("%s: clockFreq@%f beamCharge=%f beamChargeGated=%f", prefix, this.clockFreq, this.beamCharge, this.beamChargeGated)); + + // now redo the calculation as if the clock frequency were 100 kHz + double clockFreq100 = 100000; + double seconds100 = seconds * this.clockFreq / clockFreq100; + double liveSeconds100 = liveSeconds * this.clockFreq / clockFreq100; + double beamCharge100; + double beamChargeGated100; + + double q100 = (double)this.slm - slm_offset * seconds100; + double qg100 = (double)this.gatedSlm - slm_offset * liveSeconds100; + double beamChargeSLM100 = q100 * slm_atten / slm_slope; + double beamChargeGatedSLM100 = qg100 * slm_atten / slm_slope; + // double livetime100 = (double)this.gatedClock / this.clock; + + if (fcup_atten<1e-8 || fcup_slope<1e-8) { + beamCharge100 = beamChargeSLM100; + beamChargeGated100 = beamChargeGatedSLM100; + } + else { + q100 = (double)this.fcup - fcup_offset * seconds100; + qg100 = (double)this.gatedFcup - fcup_offset * liveSeconds100; + beamCharge100 = q100 * fcup_atten / fcup_slope; + beamChargeGated100 = qg100 * fcup_atten / fcup_slope; + } + System.err.println(String.format("%s: clockFreq@%f beamCharge=%f beamChargeGated=%f", prefix, clockFreq100, beamCharge100, beamChargeGated100)); } } diff --git a/scan.groovy b/scan.groovy new file mode 100644 index 0000000000..7f8ade404f --- /dev/null +++ b/scan.groovy @@ -0,0 +1,28 @@ +// a more general monitor, for things like or helicity +// - this reads DST files or skim files +// - can be run on slurm +// - note: search for 'CUT' to find which cuts are applied + +import org.jlab.jnp.hipo4.io.HipoReader; +import org.jlab.jnp.hipo4.data.Event; +import org.jlab.jnp.hipo4.data.Bank; +import org.jlab.jnp.hipo4.data.SchemaFactory; + +def filename = args[0]; + +HipoReader reader = new HipoReader(); +reader.setTags(0); +reader.open(filename); +SchemaFactory schema = reader.getSchemaFactory(); + +while(reader.hasNext()) { + Bank scalerBank = new Bank(schema.getSchema("RUN::scaler")); + Event event = new Event(); + reader.nextEvent(event); + event.read(scalerBank); + if(scalerBank.getRows()>0) { + System.out.println("beamCharge=${scalerBank.getFloat('fcup', 0)} beamChargeGated=${scalerBank.getFloat('fcupgated', 0)}"); + } +} + +reader.close(); diff --git a/test.sh b/test.sh new file mode 100755 index 0000000000..3cf831add2 --- /dev/null +++ b/test.sh @@ -0,0 +1,19 @@ +#!/usr/bin/env bash +set -euo pipefail +sep() { echo '=================================================================================='; } +# ./build-coatjava.sh -T8 --clara +rm -vfr tmp +coatjava/bin/run-clara \ + -y etc/services/rgd-clarode.yml \ + -t 8 \ + -n 500 \ + -c ./clara \ + -o ./tmp \ + validation/advanced-tests/data/evio/rg-d/clas_018779.evio.01339 +sep +grep \ + --color \ + '^clockbug.*' \ + $(find tmp/log -type f -name '*dpe.log') +sep +run-groovy scan.groovy tmp/rec_clas_018779.evio.01339.hipo