diff --git a/common-tools/clas-detector/src/main/java/org/jlab/detector/base/DetectorDescriptor.java b/common-tools/clas-detector/src/main/java/org/jlab/detector/base/DetectorDescriptor.java index 81d12615d..058916d69 100644 --- a/common-tools/clas-detector/src/main/java/org/jlab/detector/base/DetectorDescriptor.java +++ b/common-tools/clas-detector/src/main/java/org/jlab/detector/base/DetectorDescriptor.java @@ -64,6 +64,14 @@ public void setOrder(int order){ } } + public int[] getCSC() { + return new int[]{hw_CRATE,hw_SLOT,hw_CHANNEL}; + } + + public int[] getSLCO() { + return new int[]{dt_SECTOR,dt_LAYER,dt_COMPONENT,dt_ORDER}; + } + public DetectorType getType(){ return this.detectorType;} public final void setType(DetectorType type){ diff --git a/common-tools/clas-detector/src/main/java/org/jlab/detector/decode/CLASDecoder4.java b/common-tools/clas-detector/src/main/java/org/jlab/detector/decode/CLASDecoder4.java index 0796b64e0..b7a935565 100644 --- a/common-tools/clas-detector/src/main/java/org/jlab/detector/decode/CLASDecoder4.java +++ b/common-tools/clas-detector/src/main/java/org/jlab/detector/decode/CLASDecoder4.java @@ -14,6 +14,7 @@ import org.jlab.detector.helicity.HelicityBit; import org.jlab.detector.helicity.HelicitySequence; import org.jlab.detector.helicity.HelicityState; +import org.jlab.detector.pulse.Mode3; import org.jlab.logging.DefaultLogger; @@ -47,6 +48,7 @@ public class CLASDecoder4 { private boolean isRunNumberFixed = false; private int decoderDebugMode = 0; private SchemaFactory schemaFactory = new SchemaFactory(); + private Mode3 mode3 = new Mode3(); public CLASDecoder4(boolean development){ codaDecoder = new CodaEventDecoder(); @@ -244,6 +246,26 @@ public List getEntriesSCALER(DetectorType type, return scaler; } + public void extractPulses(Event event) { + mode3.update(6, null, event, schemaFactory, "BMT::wf", "BMT::adc"); + } + + public Bank getDataBankWF(String name, DetectorType type) { + List a = this.getEntriesADC(type); + Bank b = new Bank(schemaFactory.getSchema(name), a.size()); + for (int i=0; i adcDGTZ = this.getEntriesADC(type); @@ -393,6 +415,9 @@ public Event getDataEvent(){ Event event = new Event(); + String[] wfBankNames = new String[]{"BMT::wf"}; + DetectorType[] wfBankTypes = new DetectorType[]{DetectorType.BMT}; + String[] adcBankNames = new String[]{"FTOF::adc","ECAL::adc","FTCAL::adc","FTHODO::adc","FTTRK::adc", "HTCC::adc","BST::adc","CTOF::adc","CND::adc","LTCC::adc","BMT::adc", "FMT::adc","HEL::adc","RF::adc","BAND::adc","RASTER::adc"}; @@ -413,6 +438,13 @@ public Event getDataEvent(){ } } + for(int i = 0; i < wfBankTypes.length; i++){ + Bank wfBank = getDataBankWF(wfBankNames[i],wfBankTypes[i]); + if(wfBank!=null && wfBank.getRows()>0){ + event.write(wfBank); + } + } + for(int i = 0; i < tdcBankTypes.length; i++){ Bank tdcBank = getDataBankTDC(tdcBankNames[i],tdcBankTypes[i]); if(tdcBank!=null){ @@ -771,7 +803,9 @@ public static void main(String[] args){ decodedEvent.read(rawScaler); decodedEvent.read(rawRunConf); decodedEvent.read(helicityAdc); - + + decoder.extractPulses(decodedEvent); + helicityReadings.add(HelicityState.createFromFadcBank(helicityAdc, rawRunConf, decoder.detectorDecoder.scalerManager)); @@ -813,4 +847,5 @@ public static void main(String[] args){ writer.close(); } + } diff --git a/common-tools/clas-detector/src/main/java/org/jlab/detector/pulse/HipoExtractor.java b/common-tools/clas-detector/src/main/java/org/jlab/detector/pulse/HipoExtractor.java new file mode 100644 index 000000000..fba8012e4 --- /dev/null +++ b/common-tools/clas-detector/src/main/java/org/jlab/detector/pulse/HipoExtractor.java @@ -0,0 +1,160 @@ + +package org.jlab.detector.pulse; + +import java.util.ArrayList; +import java.util.List; +import org.jlab.io.base.DataBank; +import org.jlab.io.base.DataEvent; +import org.jlab.jnp.hipo4.data.Bank; +import org.jlab.jnp.hipo4.data.Event; +import org.jlab.jnp.hipo4.data.SchemaFactory; +import org.jlab.utils.groups.IndexedTable; + +/** + * For now, a place to store standard boilerplate for waveform/pulse HIPO + * manipulations. No bounds checking regarding number of samples. + * + * Here an IndexedTable object from CCDB is used to pass initialization parameters + * to the extractor. If that object is null, the @{link org.jlab.detector.pulse.IExtractor.extract} + * method should know what to do, e.g., hardcoded, channel-independent parameters. + * + * FIXME: Passing the #samples around is obviously bad, and there's probably a + * few non-horrible ways that can be addressed without changing bank format. + * + * @author baltzell + */ +public abstract class HipoExtractor implements IExtractor { + + /** + * @param n number of samples in readout + * @param it CCDB table containing extraction initialization parameters + * @param event the event to modify + * @param schema bank schema factory + * @param wfBankName name of the input waveform bank + * @param adcBankName name of the output ADC bank + */ + public void update(int n, IndexedTable it, Event event, SchemaFactory schema, String wfBankName, String adcBankName) { + Bank wf = new Bank(schema.getSchema(wfBankName)); + event.read(wf); + if (wf.getRows() > 0) { + Bank adc = new Bank(schema.getSchema(adcBankName)); + update(n, it, wf, adc); + event.remove(schema.getSchema(adcBankName)); + if (adc.getRows() > 0) event.write(adc); + } + } + + /** + * This could be overriden, e.g., for non-standard ADC banks. + * @param n number of samples in readout + * @param it CCDB table containing extraction initialization parameters + * @param event the event to modify + * @param wfBankName name of the input waveform bank + * @param adcBankName name of the output ADC bank + */ + public void update(int n, IndexedTable it, DataEvent event, String wfBankName, String adcBankName) { + DataBank wf = event.getBank(wfBankName); + if (wf.rows() > 0) { + event.removeBank(adcBankName); + List pulses = getPulses(n, it, wf); + if (pulses != null && !pulses.isEmpty()) { + DataBank adc = event.createBank(adcBankName, pulses.size()); + for (int i=0; i 0) { + List pulses = getPulses(n, it, wfBank); + adcBank.reset(); + adcBank.setRows(pulses!=null ? pulses.size() : 0); + if (pulses!=null && !pulses.isEmpty()) { + for (int i=0; i getPulses(int n, IndexedTable it, DataBank wfBank) { + List pulses = null; + short[] samples = new short[n]; + for (int i=0; i p = it==null ? extract(null, i, samples) : + extract(it.getNamedEntry(getIndices(wfBank,i)), i, samples); + if (p!=null && !p.isEmpty()) { + if (pulses == null) pulses = new ArrayList<>(); + pulses.addAll(p); + } + } + return pulses; + } + + private List getPulses(int n, IndexedTable it, Bank wfBank) { + List pulses = null; + short[] samples = new short[n]; + for (int i=0; i(); + pulses.addAll(p); + } + } + return pulses; + } + +} \ No newline at end of file diff --git a/common-tools/clas-detector/src/main/java/org/jlab/detector/pulse/IExtractor.java b/common-tools/clas-detector/src/main/java/org/jlab/detector/pulse/IExtractor.java new file mode 100644 index 000000000..bfa765d84 --- /dev/null +++ b/common-tools/clas-detector/src/main/java/org/jlab/detector/pulse/IExtractor.java @@ -0,0 +1,10 @@ +package org.jlab.detector.pulse; + +import java.util.List; +import org.jlab.utils.groups.NamedEntry; + +public interface IExtractor { + + public List extract(NamedEntry pars, int id, short... samples); + +} diff --git a/common-tools/clas-detector/src/main/java/org/jlab/detector/pulse/Mode3.java b/common-tools/clas-detector/src/main/java/org/jlab/detector/pulse/Mode3.java new file mode 100644 index 000000000..bf4049f60 --- /dev/null +++ b/common-tools/clas-detector/src/main/java/org/jlab/detector/pulse/Mode3.java @@ -0,0 +1,65 @@ +package org.jlab.detector.pulse; + +import java.util.ArrayList; +import java.util.List; +import org.jlab.utils.groups.NamedEntry; + +/** + * Similar to a FADC250 Mode-3 pulse extraction. + * + * @author baltzell + */ +public class Mode3 extends HipoExtractor { + + // Fixed extraction parameters: + final double ped = 2000; + final double tet = 2000; + final int nsa = 30; + final int nsb = 5; + + /** + * @param pars CCDB row + * @param id link to row in source bank + * @param samples ADC samples + * @return extracted pulses + */ + @Override + public List extract(NamedEntry pars, int id, short... samples) { + + List pulses = null; + + /* + // Retrive extraction parameters from a CCDB table: + double ped = pars.getValue("ped").doubleValue(); + double tet = pars.getValue("tet").doubleValue(); + int nsa = pars.getValue("nsa").intValue(); + int nsb = pars.getValue("nsb").intValue(); + */ + + // Perform the extraction: + for (int i=0; i ped+tet && samples[i+1] > samples[i]) { + int n = 0; + float integral = 0; + // Integrate the pulse: + for (int j=i-nsb; j<=i+nsa; ++j) { + if (j<0) continue; + if (j>=samples.length) break; + integral += samples[j]; + n++; + } + integral -= n * ped; + Pulse p = new Pulse(integral, i, 0x0, id); + p.pedestal = (float)(ped); + // Add the new pulse to the list: + if (pulses == null) pulses = new ArrayList<>(); + pulses.add(p); + // Add a holdoff time before next possible pulse: + i += nsa; + } + } + return pulses; + } + +} diff --git a/common-tools/clas-detector/src/main/java/org/jlab/detector/pulse/Mode7.java b/common-tools/clas-detector/src/main/java/org/jlab/detector/pulse/Mode7.java new file mode 100644 index 000000000..b7f58f2c7 --- /dev/null +++ b/common-tools/clas-detector/src/main/java/org/jlab/detector/pulse/Mode7.java @@ -0,0 +1,39 @@ +package org.jlab.detector.pulse; + +import java.util.List; +import org.jlab.utils.groups.NamedEntry; + +/** + * Similar to a Mode-7 FADC250 pulse extraction. + * + * @author baltzell + */ +public class Mode7 extends Mode3 { + + /** + * @param t0 threshold-crossing sample index + * @param ped pedestal (for calculating pulse half-height) + * @param samples + * @return pulse time + */ + private static float calculateTime(int t0, float ped, short... samples) { + for (int j=t0+1; j extract(NamedEntry pars, int id, short... samples) { + List pulses = super.extract(pars, id, samples); + for (Pulse p : pulses) + p.time = calculateTime((int)p.time, p.pedestal, samples); + return pulses; + } + +} diff --git a/common-tools/clas-detector/src/main/java/org/jlab/detector/pulse/Pulse.java b/common-tools/clas-detector/src/main/java/org/jlab/detector/pulse/Pulse.java new file mode 100644 index 000000000..36592136f --- /dev/null +++ b/common-tools/clas-detector/src/main/java/org/jlab/detector/pulse/Pulse.java @@ -0,0 +1,38 @@ +package org.jlab.detector.pulse; + +import org.jlab.detector.base.DetectorDescriptor; + +/** + * Just a dumb data container + */ +public class Pulse { + + public DetectorDescriptor descriptor; + public long timestamp; + public float integral; + public float time; + public float pedestal; + public long flags; + public int id; + + /** + * Units are the same as the raw units of the samples. + * @param integral pulse integral, pedestal-subtracted + * @param time pulse time + * @param flags user flags + * @param id link to row in source bank + */ + public Pulse(float integral, float time, long flags, int id) { + this.integral = integral; + this.time = time; + this.flags = flags; + this.id = id; + } + + @Override + public String toString() { + return String.format("pulse: integral=%f time=%f flags=%d id=%d", + integral, time, flags, id); + } + +} \ No newline at end of file diff --git a/common-tools/clas-reco/src/main/java/org/jlab/clas/reco/ReconstructionEngine.java b/common-tools/clas-reco/src/main/java/org/jlab/clas/reco/ReconstructionEngine.java index 79b4fc6f1..cce8c4301 100644 --- a/common-tools/clas-reco/src/main/java/org/jlab/clas/reco/ReconstructionEngine.java +++ b/common-tools/clas-reco/src/main/java/org/jlab/clas/reco/ReconstructionEngine.java @@ -96,6 +96,10 @@ public void registerOutputBank(String... bankName) { } } + protected SchemaFactory getSchemaFactory() { + return this.engineDictionary; + } + protected RawBank getRawBankReader(String bankName) { return new RawDataBank(bankName, this.rawBankOrders); } diff --git a/common-tools/clas-reco/src/main/java/org/jlab/clas/service/PulseExtractorEngine.java b/common-tools/clas-reco/src/main/java/org/jlab/clas/service/PulseExtractorEngine.java new file mode 100644 index 000000000..caf6702f2 --- /dev/null +++ b/common-tools/clas-reco/src/main/java/org/jlab/clas/service/PulseExtractorEngine.java @@ -0,0 +1,50 @@ +package org.jlab.clas.service; + +import org.jlab.clas.reco.ReconstructionEngine; +import org.jlab.detector.pulse.Mode3; +import org.jlab.detector.pulse.Mode7; +import org.jlab.io.base.DataEvent; + +/** + * An example of using a {@link org.jlab.detector.pulse.HipoExtractor} from a + * {@link org.jlab.clas.reco.ReconstructionEngine}. + * + * @author baltzell + */ +public class PulseExtractorEngine extends ReconstructionEngine { + + Mode3 mode3 = new Mode3(); + Mode3 mode7 = new Mode7(); + + public PulseExtractorEngine() { + super("PULSE", "baltzell", "0.0"); + } + + @Override + public boolean init() { + // If using a CCDB table, must register it here: + //requireConstants("/daq/config/ahdc"); + return true; + } + + @Override + public boolean processDataEvent(DataEvent event) { + + // No CCDB table, hardcoded parameters in the extractor: + mode3.update(6, null, event, "BMT::wf", "BMT::adc"); + //mode7.update(80, null, event, "AHDC::wf", "AHDC::adc"); + + /* + // Requiring a CCDB table: + DataBank runConfig = event.getBank("RUN::config"); + if (runConfig.rows()>0) { + IndexedTable it = getConstantsManager().getConstants( + runConfig.getInt("run", 0), "/daq/config/ahdc"); + basic.update(136, it, event, "AHDC::wf", "AHDC::adc"); + } + */ + + return true; + } + +} diff --git a/common-tools/clas-utils/src/main/java/org/jlab/utils/groups/IndexedTable.java b/common-tools/clas-utils/src/main/java/org/jlab/utils/groups/IndexedTable.java index 2c4bb9a5d..a0865613f 100644 --- a/common-tools/clas-utils/src/main/java/org/jlab/utils/groups/IndexedTable.java +++ b/common-tools/clas-utils/src/main/java/org/jlab/utils/groups/IndexedTable.java @@ -65,7 +65,7 @@ public void setPrecision(Integer precision){ str.append("f"); this.precisionFormat = str.toString(); } - + public boolean hasEntry(int... index){ return this.entries.hasItem(index); } @@ -145,7 +145,11 @@ public double getDoubleValue(String item, int... index){ } return 0; } - + + public NamedEntry getNamedEntry(int... index) { + return NamedEntry.create(entries.getItem(index), entryNames, index); + } + public IndexedList getList(){ return this.entries; } @@ -295,7 +299,7 @@ public Object getValueAt(int row, int column) { } return trow.getValue(column-ic).toString(); } - + public class RowConstraint { public int COLUMN = 0; @@ -377,4 +381,5 @@ public void setSize(int size){ } } } + } diff --git a/common-tools/clas-utils/src/main/java/org/jlab/utils/groups/NamedEntry.java b/common-tools/clas-utils/src/main/java/org/jlab/utils/groups/NamedEntry.java new file mode 100644 index 000000000..b221ad99e --- /dev/null +++ b/common-tools/clas-utils/src/main/java/org/jlab/utils/groups/NamedEntry.java @@ -0,0 +1,34 @@ +package org.jlab.utils.groups; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.jlab.utils.groups.IndexedTable.IndexedEntry; + +/** + * IndexedEntry wrapper for names and indices. + */ +public class NamedEntry { + + IndexedEntry entry; + Map names = new HashMap<>(); + int[] index; + + public static NamedEntry create(IndexedEntry entry, List names, int... index) { + NamedEntry e = new NamedEntry(); + for (int i=0; i