diff --git a/CODEOWNERS b/CODEOWNERS index 0469d696f7..ea7190a46e 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -88,7 +88,7 @@ reconstruction/rtpc/ @mathieuouillon @Hattawy reconstruction/swaps/ @baltzell @raffaelladevita reconstruction/tof/ @zieglerv @raffaelladevita reconstruction/uber/ @baltzell @raffaelladevita -reconstruction/urwell/ @raffaelladevita @tongtongcao +reconstruction/urwt/ @raffaelladevita @tongtongcao reconstruction/vtx/ @zieglerv # etc diff --git a/common-tools/clas-analysis/src/main/java/org/jlab/analysis/eventmerger/EventMergerConstants.java b/common-tools/clas-analysis/src/main/java/org/jlab/analysis/eventmerger/EventMergerConstants.java index f32d5a9de6..e0311bf64f 100644 --- a/common-tools/clas-analysis/src/main/java/org/jlab/analysis/eventmerger/EventMergerConstants.java +++ b/common-tools/clas-analysis/src/main/java/org/jlab/analysis/eventmerger/EventMergerConstants.java @@ -36,7 +36,7 @@ public class EventMergerConstants { public static final String[] TDCBANKTYPES = {"tot","tdc"}; public static final String[] ADCDETECTORS = {"BAND","BMT", "BST","CND","CTOF","ECAL","FMT","FTCAL", - "FTHODO","FTOF","FTTRK","HTCC","LTCC","URWELL"}; + "FTHODO","FTOF","FTTRK","HTCC","LTCC","URWT"}; public static final String[] TDCDETECTORS = {"BAND","CND","CTOF","DC","ECAL","FTOF"}; diff --git a/common-tools/clas-detector/src/main/java/org/jlab/detector/base/DetectorType.java b/common-tools/clas-detector/src/main/java/org/jlab/detector/base/DetectorType.java index ff90cc4a11..388fa0619a 100644 --- a/common-tools/clas-detector/src/main/java/org/jlab/detector/base/DetectorType.java +++ b/common-tools/clas-detector/src/main/java/org/jlab/detector/base/DetectorType.java @@ -30,7 +30,7 @@ public enum DetectorType { HEL (20, "HEL"), BAND (21, "BAND"), RASTER (22, "RASTER"), - URWELL (23, "URWELL"), + URWT (23, "URWT"), AHDC (24, "AHDC"), ATOF (25, "ATOF"), RECOIL (26, "RECOIL"), diff --git a/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/MUVT/MUVTConstants.java b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/MUVT/MUVTConstants.java new file mode 100644 index 0000000000..17fe3eed46 --- /dev/null +++ b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/MUVT/MUVTConstants.java @@ -0,0 +1,32 @@ +package org.jlab.detector.geant4.v2.MPGD.MUVT; + +import org.jlab.detector.calib.utils.DatabaseConstantProvider; +import org.jlab.detector.geant4.v2.MPGD.trapezoid.MPGDTrapezoidConstants; + +/** + * MUVT-specific constants. + */ +public final class MUVTConstants extends MPGDTrapezoidConstants { + + private MUVTConstants() { + super( + "/test/muvt/", // CCDB base path + "muvt_global", // global table name + "muvt_material", // material table name + "muvt" // detector nams + ); + } + + public MUVTConstants(int run, String variation) { + this(); + DatabaseConstantProvider cp = new DatabaseConstantProvider(run, variation); + this.load(cp); + cp.disconnect(); + } + + public MUVTConstants(DatabaseConstantProvider cp) { + this(); + this.load(cp); + } + +} diff --git a/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/MUVT/MUVTGeant4Factory.java b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/MUVT/MUVTGeant4Factory.java new file mode 100644 index 0000000000..7753288cd8 --- /dev/null +++ b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/MUVT/MUVTGeant4Factory.java @@ -0,0 +1,60 @@ +package org.jlab.detector.geant4.v2.MPGD.MUVT; + +import org.jlab.detector.calib.utils.DatabaseConstantProvider; +import org.jlab.detector.geant4.v2.MPGD.trapezoid.MPGDTrapezoidGeant4Factory; + +/** + * Geant4 factory for the muCLAS Forward Vertex Tracker (muVT). + * + * This class specializes the generic + * {@link MPGDTrapezoidGeant4Factory} by: + * - passing the MUVT-specific constants + * - using "MUVT" as detector name in volume names + * + * All the geometry construction (sectors, regions, material stack) + * is implemented in the base class. + */ +public final class MUVTGeant4Factory extends MPGDTrapezoidGeant4Factory { + + private final String variation; + + + public MUVTGeant4Factory(DatabaseConstantProvider cp, String variation) { + super(new MUVTConstants(cp)); + this.variation = variation; + } + + public MUVTGeant4Factory(int run, String variation) { + super(new MUVTConstants(run, variation)); + this.variation = variation; + } + + + public static void main(String[] args) { + + int run = 11; + String variation = "default"; + + if (args.length > 0) { + try { + run = Integer.parseInt(args[0]); + } catch (NumberFormatException e) { + System.err.println("Invalid run number \"" + args[0] + "\", using default 11."); + } + } + if (args.length > 1) { + variation = args[1]; + } + + MUVTGeant4Factory factory = new MUVTGeant4Factory(run, variation); + + System.out.println("MUVT geometry for run " + run + " (variation=\"" + variation + "\")"); + System.out.println("Total volumes: " + factory.getAllVolumes().size()); + + factory.getAllVolumes().forEach(volume -> { + System.out.println(volume.gemcString()); + }); + } +} + + diff --git a/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/MUVT/MUVTStripFactory.java b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/MUVT/MUVTStripFactory.java new file mode 100644 index 0000000000..59bc9230eb --- /dev/null +++ b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/MUVT/MUVTStripFactory.java @@ -0,0 +1,101 @@ +package org.jlab.detector.geant4.v2.MPGD.MUVT; + +import org.jlab.detector.calib.utils.DatabaseConstantProvider; +import org.jlab.detector.geant4.v2.MPGD.trapezoid.MPGDTrapezoidStripFactory; +import org.jlab.detector.volume.Geant4Basic; + +import java.util.HashMap; +import java.util.Map; + +/** + * MUVT strip factory. + * + * It relies entirely on AbstractMPGDTrapezoidStripFactory for: + * - strip building (component IDs, endpoints) + * - surfaces + * - planes + * + * The ONLY detector-specific thing here is the mapping "volume name -> Geant4Basic", + * used by the abstract class to find the sensitive volume (Sensitivity==1) and its transform. + */ +public final class MUVTStripFactory extends MPGDTrapezoidStripFactory { + + private final Map volumeByName = new HashMap<>(); + + /** + * Build using an already-configured DatabaseConstantProvider. + */ + public MUVTStripFactory(DatabaseConstantProvider cp, String variation) { + super(new MUVTConstants(cp)); + + + for (Geant4Basic v : geo.getAllVolumes()) { + if (v.getName() != null) { + volumeByName.put(v.getName(), v); + } + } + + buildAll(); + } + + + /** + * Convenience constructor: internally creates a DatabaseConstantProvider. + * @param run + * @param variation + */ + public MUVTStripFactory(int run, String variation) { + super(new MUVTConstants(run, variation)); + + for (Geant4Basic v : geo.getAllVolumes()) { + if (v.getName() != null) { + volumeByName.put(v.getName(), v); + } + } + + buildAll(); + } + + @Override + protected Geant4Basic getVolumeByName(String name) { + return volumeByName.get(name); + } + + + @Override + protected boolean is2DReadout() { + // change to true if your MUVT readout is truly 2D + return true; + } + + /** + * Small test / debug. + */ + public static void main(String[] args) { + + int run = 11; + String variation = "default"; + + if (args.length > 0) { + try { run = Integer.parseInt(args[0]); } catch (Exception ignored) {} + } + if (args.length > 1) variation = args[1]; + + MUVTStripFactory sf = new MUVTStripFactory(run, variation); + + int sector = 2; + int layer = 12; + + System.out.println("MUVT strips: sector=" + sector + " layer=" + layer + + " nComponents=" + sf.getNComponents(sector, layer)); + + // print first strip global/local/tilted + int comp = 10; + System.out.println("Global strip(1): " + sf.getStrip(sector, layer, comp)); + System.out.println("Local strip(1): " + sf.getStripLocal(sector, layer, comp)); + System.out.println("Tilted strip(1): " + sf.getStripTilted(sector, layer, comp)); + + System.out.println("Plane: " + sf.getPlane(sector, layer)); + System.out.println("Surface: " + sf.getSurface(sector, layer)); + } +} diff --git a/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/URWT/URWTConstants.java b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/URWT/URWTConstants.java new file mode 100644 index 0000000000..b8a271b257 --- /dev/null +++ b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/URWT/URWTConstants.java @@ -0,0 +1,32 @@ +package org.jlab.detector.geant4.v2.MPGD.URWT; + +import org.jlab.detector.calib.utils.DatabaseConstantProvider; +import org.jlab.detector.geant4.v2.MPGD.trapezoid.MPGDTrapezoidConstants; + +/** + * URWT-specific constants. + */ +public final class URWTConstants extends MPGDTrapezoidConstants { + + private URWTConstants() { + super( + "/test/urwt/", // CCDB base path + "urwt_global", // global table name + "urwt_material", // material table name + "urwt" // detector nams + ); + } + + public URWTConstants(int run, String variation) { + this(); + DatabaseConstantProvider cp = new DatabaseConstantProvider(run, variation); + this.load(cp); + cp.disconnect(); + } + + public URWTConstants(DatabaseConstantProvider cp) { + this(); + this.load(cp); + } + +} diff --git a/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/URWT/URWTGeant4Factory.java b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/URWT/URWTGeant4Factory.java new file mode 100644 index 0000000000..31a0a13d32 --- /dev/null +++ b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/URWT/URWTGeant4Factory.java @@ -0,0 +1,88 @@ +package org.jlab.detector.geant4.v2.MPGD.URWT; + +import org.jlab.detector.calib.utils.DatabaseConstantProvider; +import org.jlab.detector.geant4.v2.MPGD.trapezoid.MPGDTrapezoidGeant4Factory; + +/** + * Geant4 factory for the uRWell Tracker (URWT). + * + * This class specializes the generic {@link MPGDTrapezoidGeant4Factory} + * by: - passing the URWT-specific constants - using "uRWT" as detector name in + * volume names + * + * All the geometry construction (sectors, regions, material stack) is + * implemented in the base class. + */ +public final class URWTGeant4Factory extends MPGDTrapezoidGeant4Factory { + + private final String variation; + + public URWTGeant4Factory(DatabaseConstantProvider cp, String variation) { + super(new URWTConstants(cp)); + this.variation = variation; + } + + public URWTGeant4Factory(int run, String variation) { + super(new URWTConstants(run, variation)); + this.variation = variation; + } + + /** + * + * @param region + * @return + */ + @Override + public SectorDimensions getSectorActiveVolumeDimensions(int region) { + + if (variation != null && variation.toLowerCase().contains("proto")) { + + double halfThickness = this.getSectorThickness() / 2.0; + double tiltRad = Math.toRadians(C.THTILT); + + // da vertici (mm) + double halfLargeBase = 72.71785; + double halfSmallBase = 50.44350; + double halfHeight = 24.74554; + + return new SectorDimensions(halfThickness, halfHeight, halfLargeBase, halfSmallBase, tiltRad); + } + + return super.getSectorActiveVolumeDimensions(region); + } + + /** + * Standalone test: builds the URWT geometry and prints all volumes in GEMC + * format. + * + * Usage: java org.jlab.detector.geant4.v2.URWT.URWTGeant4Factory [run] + * [variation] + * + * Defaults: run = 11 variation = "default" + */ + public static void main(String[] args) { + + int run = 11; + String variation = "default"; + + if (args.length > 0) { + try { + run = Integer.parseInt(args[0]); + } catch (NumberFormatException e) { + System.err.println("Invalid run number \"" + args[0] + "\", using default 11."); + } + } + if (args.length > 1) { + variation = args[1]; + } + + URWTGeant4Factory factory = new URWTGeant4Factory(run, variation); + + System.out.println("uRWT geometry for run " + run + " (variation=\"" + variation + "\")"); + System.out.println("Total volumes: " + factory.getAllVolumes().size()); + + factory.getAllVolumes().forEach(volume -> { + System.out.println(volume.gemcString()); + }); + } +} diff --git a/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/URWT/URWTStripFactory.java b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/URWT/URWTStripFactory.java new file mode 100644 index 0000000000..2c2a735388 --- /dev/null +++ b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/URWT/URWTStripFactory.java @@ -0,0 +1,103 @@ +package org.jlab.detector.geant4.v2.MPGD.URWT; + +import org.jlab.detector.calib.utils.DatabaseConstantProvider; +import org.jlab.detector.geant4.v2.MPGD.trapezoid.MPGDTrapezoidStripFactory; +import org.jlab.detector.volume.Geant4Basic; + +import java.util.HashMap; +import java.util.Map; + +/** + * URWT strip factory. + * + * It relies entirely on AbstractMPGDTrapezoidStripFactory for: + * - strip building (component IDs, endpoints) + * - surfaces + * - planes + * + * The ONLY detector-specific thing here is the mapping "volume name -> Geant4Basic", + * used by the abstract class to find the sensitive volume (Sensitivity==1) and its transform. + */ +public final class URWTStripFactory extends MPGDTrapezoidStripFactory { + + private final Map volumeByName = new HashMap<>(); + + /** + * Build using an already-configured DatabaseConstantProvider. + * @param cp + */ + public URWTStripFactory(DatabaseConstantProvider cp) { + super(new URWTConstants(cp)); + + for (Geant4Basic v : geo.getAllVolumes()) { + if (v.getName() != null) { + volumeByName.put(v.getName(), v); + } + } + + buildAll(); + } + + /** + * Convenience constructor: internally creates a DatabaseConstantProvider. + * @param run + * @param variation + */ + public URWTStripFactory(int run, String variation) { + super(new URWTConstants(run, variation)); + + for (Geant4Basic v : geo.getAllVolumes()) { + if (v.getName() != null) { + volumeByName.put(v.getName(), v); + } + } + + buildAll(); + } + + @Override + protected Geant4Basic getVolumeByName(String name) { + return volumeByName.get(name); + } + + /** + * If URWT uses 2D readout (same readout Z for both layers), enable this. + * Otherwise leave it false (default 1D: z = +/- zHalf). + */ + @Override + protected boolean is2DReadout() { + // change to true if your URWT readout is truly 2D + return false; + } + + /** + * Small test / debug. + */ + public static void main(String[] args) { + + int run = 11; + String variation = "urwt1"; + + if (args.length > 0) { + try { run = Integer.parseInt(args[0]); } catch (Exception ignored) {} + } + if (args.length > 1) variation = args[1]; + + URWTStripFactory sf = new URWTStripFactory(run, variation); + + int sector = 1; + int layer = 4; + + System.out.println("URWT strips: sector=" + sector + " layer=" + layer + + " nComponents=" + sf.getNComponents(sector, layer)); + + // print first strip global/local/tilted + int comp = 10; + System.out.println("Global strip(1): " + sf.getStrip(sector, layer, comp)); + System.out.println("Local strip(1): " + sf.getStripLocal(sector, layer, comp)); + System.out.println("Tilted strip(1): " + sf.getStripTilted(sector, layer, comp)); + + System.out.println("Plane: " + sf.getPlane(sector, layer)); + System.out.println("Surface: " + sf.getSurface(sector, layer)); + } +} diff --git a/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/trapezoid/MPGDTrapezoidConstants.java b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/trapezoid/MPGDTrapezoidConstants.java new file mode 100644 index 0000000000..2857345d8a --- /dev/null +++ b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/trapezoid/MPGDTrapezoidConstants.java @@ -0,0 +1,224 @@ +package org.jlab.detector.geant4.v2.MPGD.trapezoid; + +import org.jlab.detector.calib.utils.DatabaseConstantProvider; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.logging.Logger; + +/** + * Generic constants for trapezoidal MPGD-like trackers loaded from CCDB. + * Concrete detectors (e.g. URWT) should extend this class and provide: - CCDB + * base path - global table name - material table name + */ +public class MPGDTrapezoidConstants { + + // ------------------------------------------------------------------------ + // Logging / verbosity + // ------------------------------------------------------------------------ + public static final Logger LOGGER + = Logger.getLogger(MPGDTrapezoidConstants.class.getName()); + + public static boolean VERBOSE = false; + + // ------------------------------------------------------------------------ + // CCDB configuration + // ------------------------------------------------------------------------ + /** + * Base CCDB path (e.g. "/test/urwt/"). + */ + protected final String ccdbPath; + + /** + * Name of the global geometry table (e.g. "urwt_global"). + */ + protected final String globalTableName; + + /** + * Name of the material table (e.g. "urwt_material_geo"). + */ + protected final String materialTableName; + + /** + * Short detector name used in volume names (e.g. "uRWT"). + */ + public final String detectorName; + + // ------------------------------------------------------------------------ + // Geometry parameters (from global table) + // ------------------------------------------------------------------------ + public int NSECTORS; // number of sectors + public int NLAYERS; // number of layers (readout planes) + public int NCOMPONENTS; // number of components (e.g. strips) per layer + + public double THOPEN; // opening angle between endplate planes (deg) + public double THTILT; // tilt angle (deg) + public double THMIN; // minimum polar angle (deg) + public double THMAX; // maximum polar angle (deg) + public double TGTDET; // distance from target to first plane (cm) + public double DZ; // spacing between regions (cm) + public double TWIDTH; // Trapezoid width: distance from a corner to the oblique (non-parallel) side (cm) + + public double PITCH; // strip pitch (mm) + public double WIDTH; // strip width (mm) + public double STEREOANGLE; // strip stereo angle (deg) + + // ------------------------------------------------------------------------ + // Geometry enlargement (used when building volumes) + // ------------------------------------------------------------------------ + public static final double XENLARGEMENT = 0.15; // cm + public static final double YENLARGEMENT = 0.15; // cm + public static final double ZENLARGEMENT = 0.02; // cm + + // ------------------------------------------------------------------------ + // Material description: (layer, component) -> parameters + // ------------------------------------------------------------------------ + /** + * Simple container for material parameters associated to (layer, + * component). thickness : material thickness (mm) sensitivity: flag or ID + * for sensitivity (as defined in CCDB) + */ + public static class LayerComponentInfo { + + public final double thickness; + public final int sensitivity; + + public LayerComponentInfo(double thickness, int sensitivity) { + this.thickness = thickness; + this.sensitivity = sensitivity; + } + } + + /** + * Material structure: outer key = layer index (from CCDB column "Layer") + * inner key = component index (from CCDB column "Component") value = + * material parameters (thickness, sensitivity) + */ + protected final Map> detectorStructure + = new LinkedHashMap<>(); + + /** + * @param ccdbPath base CCDB path (e.g. "/test/urwt/") + * @param globalTableName name of the global table (e.g. "urwt_global") + * @param materialTableName name of the material table (e.g. + * "urwt_material_geo") + */ + protected MPGDTrapezoidConstants(String ccdbPath, + String globalTableName, + String materialTableName, + String detectorName) { + this.ccdbPath = ccdbPath.endsWith("/") ? ccdbPath : ccdbPath + "/"; + this.globalTableName = globalTableName; + this.materialTableName = materialTableName; + this.detectorName = detectorName; + } + + /** + * Read-only access to the material structure. + * + * @return + */ + public Map> getDetectorStructure() { + return detectorStructure; + } + + // ------------------------------------------------------------------------ + // CCDB loading API + // ------------------------------------------------------------------------ + /** + * Loads the relevant CCDB tables into the given provider and fills this + * object's fields. + * + * @param cp + * @return + */ + public DatabaseConstantProvider load(DatabaseConstantProvider cp) { + cp.loadTable(ccdbPath + globalTableName); + cp.loadTable(ccdbPath + materialTableName); + getConstants(cp); + return cp; + } + + /** + * Reads the already-loaded CCDB tables from the provider and fills geometry + * and material parameters.This method assumes: - global table has at least + * one row - material table has at least one row + * + * @param cp + */ + public synchronized void getConstants(DatabaseConstantProvider cp) { + + // --------------------------- Global table --------------------------- + String globalBase = ccdbPath + globalTableName; + + int nGlobalRows = cp.length(globalBase + "/Nsectors"); + if (nGlobalRows <= 0) { + throw new IllegalStateException("Table " + globalBase + " has no rows in CCDB"); + } + + int row = 0; // global table is expected to have a single row + + NSECTORS = cp.getInteger(globalBase + "/Nsectors", row); + NLAYERS = cp.getInteger(globalBase + "/NLayers", row); + NCOMPONENTS = cp.getInteger(globalBase + "/NComponents", row); + THOPEN = cp.getDouble(globalBase + "/Thopen", row); + THTILT = cp.getDouble(globalBase + "/Thtilt", row); + THMIN = cp.getDouble(globalBase + "/Thmin", row); + THMAX = cp.getDouble(globalBase + "/Thmax", row); + TGTDET = cp.getDouble(globalBase + "/Tgt", row); + DZ = cp.getDouble(globalBase + "/Dz", row); + TWIDTH = cp.getDouble(globalBase + "/TWidth", row); + PITCH = cp.getDouble(globalBase + "/Pitch", row); + WIDTH = cp.getDouble(globalBase + "/Width", row); + STEREOANGLE = cp.getDouble(globalBase + "/StereoAngle", row); + + if (VERBOSE) { + System.out.printf( + "%s global: Nsectors=%d Nlayers=%d Ncomponents=%d Thopen=%.3f Thtilt=%.3f " + + "Thmin=%.3f Thmax=%.3f Tgt=%.3f Dz=%.3f TWidth=%.3f Pitch=%.3f Width=%.3f StereoAngle=%.3f%n", + globalTableName, + NSECTORS, NLAYERS, NCOMPONENTS, + THOPEN, THTILT, THMIN, THMAX, + TGTDET, DZ, TWIDTH, PITCH, WIDTH, STEREOANGLE + ); + } + + // --------------------------- Material table ------------------------ + String matBase = ccdbPath + materialTableName; + + // Use a numeric column (e.g. Layer) to get the number of rows + int nRows = cp.length(matBase + "/Layer"); + + if (VERBOSE) { + System.out.printf("%s material table rows=%d%n", materialTableName, nRows); + } + + detectorStructure.clear(); + + // Expected schema (all numeric): + // Layer (int) + // Component (int) + // thickness (double) mm + // sensitivity (int) + for (int i = 0; i < nRows; i++) { + + int layer = cp.getInteger(matBase + "/Layer", i); + int component = cp.getInteger(matBase + "/Component", i); + double thickness = (cp.getDouble(matBase + "/Thickness", i)) * 0.1; // convert in cm + int sensitivity = cp.getInteger(matBase + "/Sensitivity", i); + + if (VERBOSE) { + System.out.printf( + "%s row %d: layer=%d comp=%d thick=%.5f sens=%d%n", + materialTableName, i, layer, component, thickness, sensitivity + ); + } + + LayerComponentInfo info = new LayerComponentInfo(thickness, sensitivity); + + detectorStructure + .computeIfAbsent(layer, l -> new LinkedHashMap<>()) + .put(component, info); + } + } +} diff --git a/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/trapezoid/MPGDTrapezoidGeant4Factory.java b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/trapezoid/MPGDTrapezoidGeant4Factory.java new file mode 100644 index 0000000000..82904ccb61 --- /dev/null +++ b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/trapezoid/MPGDTrapezoidGeant4Factory.java @@ -0,0 +1,343 @@ +package org.jlab.detector.geant4.v2.MPGD.trapezoid; + +import eu.mihosoft.vrl.v3d.Vector3d; +import org.jlab.detector.geant4.v2.Geant4Factory; +import org.jlab.detector.volume.G4Trap; +import org.jlab.detector.volume.G4World; +import org.jlab.detector.volume.Geant4Basic; + +import java.util.Map; + +/** + * Generic Geant4 factory for trapezoidal MPGD-like trackers. + * + * It builds: - a world volume - NREGIONS = NLAYERS/2 (by convention) - NSECTORS + * per region + * + * The exact geometry parameters and material stack are taken from an + * {@link MPGDTrapezoidConstants} instance. + * + * Concrete detectors should: - extend this class - pass the appropriate + * constants + detector name in the constructor + */ +public class MPGDTrapezoidGeant4Factory extends Geant4Factory { + + /** + * Detector constants (geometry + materials from CCDB). + */ + protected final MPGDTrapezoidConstants C; + + public static record SectorDimensions( + double halfThickness, + double halfHeight, + double halfLargeBase, + double halfSmallBase, + double tiltRad + ) { + + } + + /** + * @param constants detector constants (already configured with CCDB + * paths/table names) + */ + protected MPGDTrapezoidGeant4Factory(MPGDTrapezoidConstants constants) { + this.C = constants; + this.init(); + } + + // ------------------------------------------------------------------------ + // Top-level geometry construction + // ------------------------------------------------------------------------ + /** + * Initializes the world volume and constructs all regions and sectors. + * + * This must be called after the constants have been loaded from CCDB. + */ + protected final void init() { + + // World volume for this detector + motherVolume = new G4World("root"); + + int NREGIONS = (int) Math.round(C.NLAYERS / 2.0); + for (int iregion = 0; iregion < NREGIONS; iregion++) { + for (int isector = 0; isector < C.NSECTORS; isector++) { + Geant4Basic sectorVolume = createSector(isector, iregion); + sectorVolume.setMother(motherVolume); + } + } + } + + // ------------------------------------------------------------------------ + // Sector geometry helpers + // ------------------------------------------------------------------------ + /** + * Computes the total thickness (mm) of a sector by summing the thickness of + * all material volumes. + * + * @return + */ + public double getSectorThickness() { + return C.getDetectorStructure().values() + .stream() + .flatMap(componentMap -> componentMap.values().stream()) + .mapToDouble(info -> info.thickness) + .sum(); + } + + /** + * + * @param region + * @return + */ + public SectorDimensions getSectorActiveVolumeDimensions(int region) { + + double baseDistance = C.TGTDET + region * C.DZ; + + double sectorHeight = baseDistance + * (Math.tan(Math.toRadians(C.THMAX - C.THTILT)) + + Math.tan(Math.toRadians(C.THTILT - C.THMIN))); + + double halfThickness = this.getSectorThickness() / 2.0; + double halfHeight = sectorHeight / 2.0; + + // Distance from target to the bottom base along the tilted axis + double W2TGT = (C.TGTDET + region * C.DZ) + / Math.cos(Math.toRadians(C.THTILT - C.THMIN)); + + double YMIN = W2TGT * Math.sin(Math.toRadians(C.THMIN)); // distance from beamline (Y) + double h = sectorHeight * Math.cos(Math.toRadians(C.THTILT)); + double halfSmallBase = 0.5 * (YMIN * Math.tan(Math.toRadians(C.THOPEN) / 2)); + + double halfLargeBase = halfSmallBase + sectorHeight * Math.tan(Math.toRadians(C.THOPEN / 2.0)); + + double tiltRad = Math.toRadians(C.THTILT); + + double twidth_Check = 2 * halfLargeBase * Math.sin(Math.toRadians(C.THOPEN)); + + if (MPGDTrapezoidConstants.VERBOSE) { + System.out.printf("C.TWIDT=%.3f vs %.3f", C.TWIDTH, twidth_Check); + + System.out.printf("YMIN=%.3f", YMIN); + + System.out.printf( + "SectorDimensionsPhysical [%s] region=%d : height=%.3f | halfT=%.3f halfH=%.3f " + + "halfLarge=%.3f halfSmall=%.3f tilt(deg)=%.3f%n", + C.detectorName, region, sectorHeight, + halfThickness, halfHeight, + halfLargeBase, halfSmallBase, + C.THTILT + ); + } + + return new SectorDimensions(halfThickness, halfHeight, halfLargeBase, halfSmallBase, tiltRad); + } + + /** + * + * @param region + * @return + */ + public SectorDimensions getSectorContainerDimensions(int region) { + + SectorDimensions phys = getSectorActiveVolumeDimensions(region); + + double halfThickness = phys.halfThickness() + MPGDTrapezoidConstants.ZENLARGEMENT; + double halfHeight = phys.halfHeight() + MPGDTrapezoidConstants.YENLARGEMENT; + double halfLargeBase = phys.halfLargeBase() + MPGDTrapezoidConstants.XENLARGEMENT; + double halfSmallBase = phys.halfSmallBase() + MPGDTrapezoidConstants.XENLARGEMENT; + + return new SectorDimensions(halfThickness, halfHeight, halfLargeBase, halfSmallBase, phys.tiltRad()); + } + + /** + * Computes the sector height (longitudinal extension in the RZ plane) for a + * given region. + * + * @param region + * @return + */ + public double getSectorHeight(int region) { + + double baseDistance = C.TGTDET + region * C.DZ; + + double sectorHeight = baseDistance + * (Math.tan(Math.toRadians(C.THMAX - C.THTILT)) + + Math.tan(Math.toRadians(C.THTILT - C.THMIN))); + + if (MPGDTrapezoidConstants.VERBOSE) { + System.out.printf( + "SectorHeight [%s] region=%d : baseDistance=%.3f THMIN=%.3f THMAX=%.3f THTILT=%.3f -> height=%.3f%n", + C.detectorName, + region, + baseDistance, + C.THMIN, C.THMAX, C.THTILT, + sectorHeight + ); + } + + return sectorHeight; + } + + /** + * Computes the barycenter coordinates of a given sector/region in the + * CLAS12 coordinate system. + * + * @param isector + * @param iregion + * @return + */ + public Vector3d getCenterCoordinate(int isector, int iregion) { + + Vector3d vCenter = new Vector3d(0, 0, 0); + + // Distance from target to the bottom base along the tilted axis + double W2TGT = (C.TGTDET + iregion * C.DZ) + / Math.cos(Math.toRadians(C.THTILT - C.THMIN)); + + double YMIN = W2TGT * Math.sin(Math.toRadians(C.THMIN)); // distance from beamline (Y) + double ZMIN = W2TGT * Math.cos(Math.toRadians(C.THMIN)); // Z of the bottom base + + SectorDimensions dimCont = this.getSectorContainerDimensions(iregion); + double sectorHeight = 2 * dimCont.halfHeight(); + + vCenter.x = 0.0; + vCenter.y = (sectorHeight / 2.0) * Math.cos(Math.toRadians(C.THTILT)) + YMIN; + vCenter.z = -(sectorHeight / 2.0) * Math.sin(Math.toRadians(C.THTILT)) + ZMIN; + + // Rotate to the correct sector around Z (assumes 6 sectors, 60° apart) + vCenter.rotateZ(-Math.toRadians(90.0 - isector * 60.0)); + + return vCenter; + } + + // ------------------------------------------------------------------------ + // Sector + material volume construction + // ------------------------------------------------------------------------ + /** + * Builds a single sector for a given region and returns its volume. + * + * @param isector + * @param iregion + * @return + */ + public Geant4Basic createSector(int isector, int iregion) { + + SectorDimensions dimPhys = this.getSectorActiveVolumeDimensions(iregion); + SectorDimensions dimCont = this.getSectorContainerDimensions(iregion); + + Geant4Basic sectorVolume = createSectorVolume(isector, iregion, dimCont); + populateSectorWithDetectorStructure(sectorVolume, isector, iregion, dimPhys); + + return sectorVolume; + } + + /** + * Creates the main trapezoidal sector volume and places it in the world. + * + * @param isector + * @param iregion + * @param dimSect + * @return + */ + protected Geant4Basic createSectorVolume(int isector, + int iregion, + SectorDimensions dimSect) { + + double sectorDZ = dimSect.halfThickness(); + double sectorDY = dimSect.halfHeight(); + double sectorDX1 = dimSect.halfLargeBase(); + double sectorDX0 = dimSect.halfSmallBase(); + double sectorTtilt = dimSect.tiltRad(); + + Vector3d vCenter = this.getCenterCoordinate(isector, iregion); + + Geant4Basic sectorVolume = new G4Trap( + "region_" + C.detectorName + "_" + (iregion + 1) + "_s" + (isector + 1), + sectorDZ, -sectorTtilt, Math.toRadians(90.0), + sectorDY, sectorDX0, sectorDX1, 0.0, + sectorDY, sectorDX0, sectorDX1, 0.0 + ); + + sectorVolume.rotate("yxz", 0.0, sectorTtilt, Math.toRadians(90.0 - isector * 60.0)); + sectorVolume.translate(vCenter.x, vCenter.y, vCenter.z); + sectorVolume.setId(isector + 1, iregion + 1, 0, 0); + + return sectorVolume; + } + + /** + * Fills the given sector volume with material sub-volumes according to the + * CCDB material structure (layer/component stack).Stacking is done along + * the local Z direction (thickness). + * + * @param sectorVolume + * @param isector + * @param iregion + * @param dimSect + */ + protected void populateSectorWithDetectorStructure(Geant4Basic sectorVolume, + int isector, + int iregion, + SectorDimensions dimSect) { + + double halfThickness = dimSect.halfThickness(); + double halfHeight = dimSect.halfHeight(); + double halfLargeBase = dimSect.halfLargeBase(); + double halfSmallBase = dimSect.halfSmallBase(); + double tiltRad = dimSect.tiltRad(); + + double totalThickness = 2.0 * halfThickness; + double accumulatedThickness = 0.0; + + for (Map.Entry> layerEntry + : C.getDetectorStructure().entrySet()) { + + int LayerId = layerEntry.getKey(); + Map componentMap + = layerEntry.getValue(); + + for (Map.Entry componentEntry + : componentMap.entrySet()) { + + int materialComponentId = componentEntry.getKey(); + MPGDTrapezoidConstants.LayerComponentInfo info = componentEntry.getValue(); + + double thick = info.thickness; + + // Protect against zero or negative thickness: skip such entries + if (thick <= 0.0) { + System.err.printf( + "WARNING: skipping material volume with non-positive thickness: " + + "layer=%d comp=%d thick=%f%n", + LayerId, materialComponentId, thick + ); + continue; + } + + // place from "front" to "back" along local Z + double localZ = -totalThickness / 2.0 + accumulatedThickness + thick / 2.0; + double localY = -localZ * Math.tan(Math.toRadians(C.THTILT)); + + Geant4Basic matVolume = new G4Trap( + "matVolume", + thick / 2.0, -tiltRad, Math.toRadians(90.0), + halfHeight, halfSmallBase, halfLargeBase, 0.0, + halfHeight, halfSmallBase, halfLargeBase, 0.0 + ); + + matVolume.setName( + "rg_" + C.detectorName + "_" + (iregion + 1) + + "_s" + (isector + 1) + + "_l" + (LayerId + iregion * 2) + + "_matC" + materialComponentId + ); + + matVolume.setMother(sectorVolume); + matVolume.setPosition(0.0, localY, localZ); + + accumulatedThickness += thick; + } + } + } +} diff --git a/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/trapezoid/MPGDTrapezoidStripFactory.java b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/trapezoid/MPGDTrapezoidStripFactory.java new file mode 100644 index 0000000000..283adf2b21 --- /dev/null +++ b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/MPGD/trapezoid/MPGDTrapezoidStripFactory.java @@ -0,0 +1,673 @@ +package org.jlab.detector.geant4.v2.MPGD.trapezoid; + +import eu.mihosoft.vrl.v3d.Vector3d; +import org.jlab.detector.volume.Geant4Basic; +import org.jlab.geom.prim.Line3D; +import org.jlab.geom.prim.Plane3D; +import org.jlab.geom.prim.Point3D; +import org.jlab.geom.prim.Trap3D; +import org.jlab.geom.prim.Vector3D; +import org.jlab.utils.groups.IndexedList; + +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; + +/** + * Base class implementing strip/surface/plane geometry for trapezoidal MPGD + * detectors. + */ +public abstract class MPGDTrapezoidStripFactory { + + // ------------------------------------------------------------------------ + // Inputs + // ------------------------------------------------------------------------ + protected final MPGDTrapezoidConstants C; + protected final MPGDTrapezoidGeant4Factory geo; + + protected MPGDTrapezoidStripFactory(MPGDTrapezoidConstants constants) { + this.C = constants; + this.geo = new MPGDTrapezoidGeant4Factory(constants); + } + + /** + * Detector-specific hook: Must return the volume object given its + * name.Typically implemented by indexing geo.getAllVolumes() into a + * Map. + * + * @param name + * @return + */ + protected abstract Geant4Basic getVolumeByName(String name); + + // ------------------------------------------------------------------------ + // Cached geometry (CLAS12 indices) + // ------------------------------------------------------------------------ + protected final IndexedList globalStrips = new IndexedList<>(3); // (sector, layer, component) + protected final IndexedList localStrips = new IndexedList<>(3); // (sector, layer, component) sensitive-local + protected final IndexedList tiltedStrips = new IndexedList<>(3); // (sector, layer, component) + protected final IndexedList planes = new IndexedList<>(2); // (sector, layer) + protected final IndexedList surfaceLayers = new IndexedList<>(2); // (sector, layer) + protected final IndexedList nComponents = new IndexedList<>(2); // (sector, layer) + + // ------------------------------------------------------------------------ + // Internal geometry containers (mirror the C++ digitizer) + // ------------------------------------------------------------------------ + protected static class StripConstants { + + public double xHalfSmall; // cm + public double xHalfLarge; // cm + public double yHalf; // cm + public double zReadoutLocal; // cm (in sensitive-local) + public double pitch; // cm + public double width; // cm + public double stereoAngle; // rad + } + + protected static class Trap2D { + + Vector3d bl, br, tl, tr; + + static Trap2D fromConstants(StripConstants c) { + Trap2D t = new Trap2D(); + double z = c.zReadoutLocal; + t.bl = new Vector3d(-c.xHalfSmall, -c.yHalf, z); + t.br = new Vector3d(c.xHalfSmall, -c.yHalf, z); + t.tl = new Vector3d(-c.xHalfLarge, c.yHalf, z); + t.tr = new Vector3d(c.xHalfLarge, c.yHalf, z); + return t; + } + + List edges() { + List e = new ArrayList<>(4); + e.add(new Vector3d[]{bl, br}); + e.add(new Vector3d[]{br, tr}); + e.add(new Vector3d[]{tr, tl}); + e.add(new Vector3d[]{tl, bl}); + return e; + } + } + + protected static class StripGeom { + + int internalIndex; + int component; + Vector3d p1Local, p2Local; // endpoints in sensitive-local + double orderXLocal; // local midpoint X ordering key + } + + // ------------------------------------------------------------------------ + // Options / defaults + // ------------------------------------------------------------------------ + /** + * If true: readout is 2D => same zReadoutLocal for both layers.Override in + * detector. + * + * @return + */ + protected boolean is2DReadout() { + return false; + } + + protected int baseLayerForCCDB(int layer) { + if (is2DReadout()) { + return 1; + } + return (layer % 2 == 0) ? 2 : 1; + } + + /** + * Pitch in cm (CCDB stored in mm). Override if detector is different. + */ + protected double defaultPitchCm() { + return C.PITCH * 0.1; + } + + /** + * Width in cm (CCDB stored in mm). Override if detector is different. + */ + protected double defaultWidthCm() { + return C.WIDTH * 0.1; + } + + /** + * Stereo angle in rad (CCDB stored in deg). Override if detector is + * layer-dependent. + */ + protected double defaultStereoAngleRad() { + return Math.toRadians(C.STEREOANGLE); + } + + // ------------------------------------------------------------------------ + // Sensitive volume discovery (Sensitivity==1) + // ------------------------------------------------------------------------ + /** + * Return the CCDB "Component" index (matC) whose Sensitivity==1 for a given + * layer. + * + * @param layer + * @return + */ + protected int getSensitiveMatComponentId(int layer) { + int baseLayer = baseLayerForCCDB(layer); + var layerMap = C.getDetectorStructure().get(baseLayer); + if (layerMap == null) { + throw new IllegalStateException("No detectorStructure entry for layer=" + layer); + } + for (var e : layerMap.entrySet()) { + int matC = e.getKey(); + var info = e.getValue(); + if (info.sensitivity == 1) { + return matC; + } + } + throw new IllegalStateException("No Sensitivity==1 found for layer=" + layer); + } + + /** + * Compute the sensitive half thickness (cm) from CCDB (Sensitivity==1). + * + * @param layer + * @return + */ + protected double getSensitiveHalfThicknessCm(int layer) { + int baseLayer = baseLayerForCCDB(layer); + var layerMap = C.getDetectorStructure().get(baseLayer); + if (layerMap == null) { + throw new IllegalStateException("No detectorStructure entry for layer=" + layer); + } + for (var e : layerMap.entrySet()) { + var info = e.getValue(); + if (info.sensitivity == 1) { + return info.thickness / 2.0; // thickness already cm in your loader + } + } + throw new IllegalStateException("No sensitive thickness (Sensitivity==1) for layerInRegion=" + layer); + } + + /** + * Readout plane z in sensitive-local.Convention: - 1D: even layerInRegion + * => +zHalf, odd => -zHalf - 2D: always +zHalf + * + * @param layer + * @return + */ + protected double findReadoutZLocal(int layer) { + double zHalf = getSensitiveHalfThicknessCm(layer); + if (is2DReadout()) { + return +zHalf; + } + return (layer % 2 == 0) ? (+zHalf) : (-zHalf); + } + + /** + * Build expected sensitive-volume name using the naming convention from + * AbstractMPGDTrapezoidGeant4Factory.populateSectorWithDetectorStructure(): + * + * rg{region}_s{sector}_l{layerGlobal0Based}_matC{matC} + * + * where: - region is 1-based in the name - sector is 1-based in the name - + * matC is the CCDB material "Component" id for Sensitivity==1 + * + * @param region + * @param sector + * @param layer + * @return + */ + protected String getSensitiveVolumeName(int region, int sector, int layer) { + int matC = getSensitiveMatComponentId(layer); + if (is2DReadout()) { + if (layer % 2 == 0) { // layer pari + layer = layer - 1; + } +} + + return "rg_" + C.detectorName + "_" + region + + "_s" + sector + + "_l" + layer + + "_matC" + matC; + } + + /** + * Transform a point from sensitive-local -> global using the sensitive + * volume transform. + * + * @param region + * @param sector + * @param layer + * @param local + * @return + */ + protected Vector3d toGlobalSensitive(int region, int sector, int layer, Vector3d local) { + String name = getSensitiveVolumeName(region, sector, layer); + Geant4Basic v = getVolumeByName(name); + if (v == null) { + throw new IllegalStateException("Sensitive volume not found: " + name); + } + + return v.getGlobalTransform().transform(local); + } + + // ------------------------------------------------------------------------ + // Strip constants builder (GENERAL: uses geo physical dims + CCDB thickness) + // ------------------------------------------------------------------------ + /** + * Build StripConstants using: - XY trapezoid from + * geo.getSectorDimensionsPhysical(region) (NOT enlarged) - zReadoutLocal + * from CCDB sensitive thickness (findReadoutZLocal) - pitch/width/stereo + * from CCDB + * + * @param region + * @param layer + * @return + */ + protected StripConstants buildStripConstants(int region, int layer) { + + MPGDTrapezoidGeant4Factory.SectorDimensions phys + = geo.getSectorActiveVolumeDimensions(region - 1); + + StripConstants sc = new StripConstants(); + sc.yHalf = phys.halfHeight(); + sc.xHalfSmall = phys.halfSmallBase(); + sc.xHalfLarge = phys.halfLargeBase(); + + // sc.zReadoutLocal = findReadoutZLocal(layer); + sc.zReadoutLocal = 0.0; + sc.pitch = defaultPitchCm(); + sc.width = defaultWidthCm(); + if (layer % 2 == 0) { + // layer pari + sc.stereoAngle = -defaultStereoAngleRad(); + } else { + // layer dispari + sc.stereoAngle = defaultStereoAngleRad(); + } + + + return sc; + } + + // ------------------------------------------------------------------------ + // Strip-frame transforms (IDENTICAL to C++) + // ------------------------------------------------------------------------ + protected static double[] toStripFrameXY(double x, double y, StripConstants c) { + double sa = Math.sin(c.stereoAngle); + double ca = Math.cos(c.stereoAngle); + double xs = sa * x + ca * y; + double ys = ca * x - sa * y; + return new double[]{xs, ys}; + } + + // ------------------------------------------------------------------------ + // Line / edge intersection (normal form) + // ------------------------------------------------------------------------ + protected static boolean intersectEdgeWithLineNormal( + Vector3d A, Vector3d B, + Vector3d nXY, double rhs, + Vector3d out + ) { + double nA = nXY.x * A.x + nXY.y * A.y; + double nB = nXY.x * B.x + nXY.y * B.y; + double denom = nB - nA; + + if (Math.abs(denom) < 1e-12) { + return false; + } + + double t = (rhs - nA) / denom; + if (t < 0.0 || t > 1.0) { + return false; + } + + out.x = A.x + t * (B.x - A.x); + out.y = A.y + t * (B.y - A.y); + out.z = A.z + t * (B.z - A.z); + return true; + } + + protected static boolean buildStripSegment(int internalIndex, StripConstants c, Vector3d out1, Vector3d out2) { + + Trap2D tr = Trap2D.fromConstants(c); + + double sa = Math.sin(c.stereoAngle); + double ca = Math.cos(c.stereoAngle); + + // line: ca*x - sa*y = rhs + Vector3d nXY = new Vector3d(ca, -sa, 0.0); + double rhs = (internalIndex + 0.5) * c.pitch; + + List inters = new ArrayList<>(4); + + for (Vector3d[] e : tr.edges()) { + Vector3d P = new Vector3d(0, 0, 0); + if (intersectEdgeWithLineNormal(e[0], e[1], nXY, rhs, P)) { + inters.add(new Vector3d(P.x, P.y, P.z)); + } + } + + if (inters.size() < 2) { + return false; + } + + // choose farthest pair (robust at vertices) + double best = -1; + Vector3d a = null, b = null; + for (int i = 0; i < inters.size(); i++) { + for (int j = i + 1; j < inters.size(); j++) { + double dx = inters.get(i).x - inters.get(j).x; + double dy = inters.get(i).y - inters.get(j).y; + double d2 = dx * dx + dy * dy; + if (d2 > best) { + best = d2; + a = inters.get(i); + b = inters.get(j); + } + } + } + + out1.set(a.x, a.y, a.z); + out2.set(b.x, b.y, b.z); + return true; + } + + /** + * Build full strip list (LOCAL) and assign CLAS12 component IDs by sorting + * on local X midpoint. + * + * @param c + * @return + */ + protected List buildStripCache(StripConstants c) { + + Trap2D tr = Trap2D.fromConstants(c); + + double ys1 = toStripFrameXY(tr.bl.x, tr.bl.y, c)[1]; + double ys2 = toStripFrameXY(tr.br.x, tr.br.y, c)[1]; + double ys3 = toStripFrameXY(tr.tl.x, tr.tl.y, c)[1]; + double ys4 = toStripFrameXY(tr.tr.x, tr.tr.y, c)[1]; + + double ysMin = Math.min(Math.min(ys1, ys2), Math.min(ys3, ys4)); + double ysMax = Math.max(Math.max(ys1, ys2), Math.max(ys3, ys4)); + + int iMin = (int) Math.floor(ysMin / c.pitch) - 2; + int iMax = (int) Math.ceil(ysMax / c.pitch) + 2; + + List tmp = new ArrayList<>(); + + for (int idx = iMin; idx <= iMax; idx++) { + + Vector3d p1 = new Vector3d(0, 0, 0); + Vector3d p2 = new Vector3d(0, 0, 0); + + if (!buildStripSegment(idx, c, p1, p2)) { + continue; + } + + StripGeom s = new StripGeom(); + s.internalIndex = idx; + s.p1Local = p1; + s.p2Local = p2; + + Vector3d mid = new Vector3d( + 0.5 * (p1.x + p2.x), + 0.5 * (p1.y + p2.y), + 0.5 * (p1.z + p2.z) + ); + s.orderXLocal = mid.x; + + tmp.add(s); + } + + tmp.sort(Comparator + .comparingDouble((StripGeom s) -> s.orderXLocal) + .thenComparingInt(s -> s.internalIndex)); + + int comp = 1; + for (StripGeom s : tmp) { + s.component = comp++; + } + + return tmp; + } + + // ------------------------------------------------------------------------ + // Tilted frame + // ------------------------------------------------------------------------ + /** + * + * @param sector + * @param global + * @return + */ + protected Line3D toTilted(int sector, Line3D global) { + Line3D tilted = new Line3D(); + tilted.copy(global); + + double dPhi = 360.0 / C.NSECTORS; + double phi = -Math.toRadians(dPhi * (sector - 1)); + + tilted.rotateZ(phi); + tilted.rotateY(Math.toRadians(-C.THTILT)); + + return tilted; + } + + // ------------------------------------------------------------------------ + // Surface + Plane builders (GLOBAL) + // ------------------------------------------------------------------------ + /** + * + * @param sector + * @param layer + * @return + */ + protected Trap3D createSurface(int sector, int layer) { + + int region = (layer + 1) / 2; + + StripConstants c = buildStripConstants(region, layer); + + Vector3d blL = new Vector3d(-c.xHalfSmall, -c.yHalf, c.zReadoutLocal); + Vector3d brL = new Vector3d(c.xHalfSmall, -c.yHalf, c.zReadoutLocal); + Vector3d tlL = new Vector3d(-c.xHalfLarge, c.yHalf, c.zReadoutLocal); + Vector3d trL = new Vector3d(c.xHalfLarge, c.yHalf, c.zReadoutLocal); + + Vector3d blG = toGlobalSensitive(region, sector, layer, blL); + Vector3d brG = toGlobalSensitive(region, sector, layer, brL); + Vector3d tlG = toGlobalSensitive(region, sector, layer, tlL); + Vector3d trG = toGlobalSensitive(region, sector, layer, trL); + + return new Trap3D( + blG.x, blG.y, blG.z, + brG.x, brG.y, brG.z, + tlG.x, tlG.y, tlG.z, + trG.x, trG.y, trG.z + ); + } + + /** + * + * @param sector + * @param layer + * @return + */ + protected Plane3D createPlane(int sector, int layer) { + + int region = (layer + 1) / 2; + + StripConstants c = buildStripConstants(region, layer); + + // 3 points on the readout plane in sensitive-local + Vector3d p1L = new Vector3d(-c.xHalfSmall, -c.yHalf, c.zReadoutLocal); + Vector3d p2L = new Vector3d(c.xHalfSmall, -c.yHalf, c.zReadoutLocal); + Vector3d p3L = new Vector3d(-c.xHalfLarge, c.yHalf, c.zReadoutLocal); + + // transform to global + Vector3d p1G = toGlobalSensitive(region, sector, layer, p1L); + Vector3d p2G = toGlobalSensitive(region, sector, layer, p2L); + Vector3d p3G = toGlobalSensitive(region, sector, layer, p3L); + + Point3D P1 = new Point3D(p1G.x, p1G.y, p1G.z); + Point3D P2 = new Point3D(p2G.x, p2G.y, p2G.z); + Point3D P3 = new Point3D(p3G.x, p3G.y, p3G.z); + + // normal = (P1->P2) x (P1->P3) + Vector3D v1 = P1.vectorTo(P2); + Vector3D v2 = P1.vectorTo(P3); + Vector3D n = v1.cross(v2); + n.unit(); + + // If you want a stable sign convention, uncomment: + // if (n.z() < 0) n.setXYZ(-n.x(), -n.y(), -n.z()); + return new Plane3D(P1, n); + } + + // ------------------------------------------------------------------------ + // Build orchestration + // ------------------------------------------------------------------------ + public final void buildAll() { + clearCaches(); + fillStripLists(); + fillSurfaceLists(); + fillPlaneLists(); + } + + protected void clearCaches() { + globalStrips.clear(); + localStrips.clear(); + tiltedStrips.clear(); + planes.clear(); + surfaceLayers.clear(); + nComponents.clear(); + } + + protected void fillStripLists() { + + for (int sector = 1; sector <= C.NSECTORS; sector++) { + for (int layer = 1; layer <= C.NLAYERS; layer++) { + + int region = (layer + 1) / 2; + + StripConstants sc = buildStripConstants(region, layer); + List strips = buildStripCache(sc); + + nComponents.add(strips.size(), sector, layer); + + for (StripGeom s : strips) { + + // local line (sensitive-local) + Line3D local = new Line3D( + s.p1Local.x, s.p1Local.y, s.p1Local.z, + s.p2Local.x, s.p2Local.y, s.p2Local.z + ); + + // global endpoints + Vector3d g1 = toGlobalSensitive(region, sector, layer, s.p1Local); + + Vector3d g2 = toGlobalSensitive(region, sector, layer, s.p2Local); + + Line3D global = new Line3D( + g1.x, g1.y, g1.z, + g2.x, g2.y, g2.z + ); + + Line3D tilted = toTilted(sector, global); + + // cache with CLAS12 indices: (sector, layer, component) + localStrips.add(local, sector, layer, s.component); + globalStrips.add(global, sector, layer, s.component); + tiltedStrips.add(tilted, sector, layer, s.component); + } + } + } + } + + protected void fillSurfaceLists() { + for (int sector = 1; sector <= C.NSECTORS; sector++) { + for (int layer = 1; layer <= C.NLAYERS; layer++) { + surfaceLayers.add(createSurface(sector, layer), sector, layer); + } + } + } + + protected void fillPlaneLists() { + for (int sector = 1; sector <= C.NSECTORS; sector++) { + for (int layer = 1; layer <= C.NLAYERS; layer++) { + planes.add(createPlane(sector, layer), sector, layer); + } + } + } + + // ------------------------------------------------------------------------ + // Public API (cached getters) + // ------------------------------------------------------------------------ + /** + * Global strip line in CLAS12 frame. + * + * @param sector + * @param layer + * @param component + * @return + */ + public Line3D getStrip(int sector, int layer, int component) { + return globalStrips.getItem(sector, layer, component); + } + + /** + * Strip line in sensitive-volume local frame. + * + * @param sector + * @param layer + * @param component + * @return + */ + public Line3D getStripLocal(int sector, int layer, int component) { + return localStrips.getItem(sector, layer, component); + } + + /** + * Strip line in legacy tilted frame (debug/plot). + * + * @param sector + * @param layer + * @param component + * @return + */ + public Line3D getStripTilted(int sector, int layer, int component) { + return tiltedStrips.getItem(sector, layer, component); + } + + /** + * Readout plane in global frame. + * + * @param sector + * @param layer + * @return + */ + public Plane3D getPlane(int sector, int layer) { + return planes.getItem(sector, layer); + } + + /** + * Readout trapezoid surface in global frame. + * + * @param sector + * @param layer + * @return + */ + public Trap3D getSurface(int sector, int layer) { + return surfaceLayers.getItem(sector, layer); + } + + /** + * Number of components (strips) for this (sector, layer). + * + * @param sector + * @param layer + * @return + */ + public int getNComponents(int sector, int layer) { + Integer n = nComponents.getItem(sector, layer); + return (n == null) ? 0 : n; + } +} diff --git a/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/URWELL/URWellConstants.java b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/URWELL/URWellConstants.java deleted file mode 100644 index 81b08bf569..0000000000 --- a/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/URWELL/URWellConstants.java +++ /dev/null @@ -1,132 +0,0 @@ -package org.jlab.detector.geant4.v2.URWELL; - - -import org.jlab.detector.calib.utils.DatabaseConstantProvider; -import org.jlab.geom.prim.Point3D; - - -public class URWellConstants { - - private final static String CCDBPATH = "/geometry/urwell/"; - - public final static int NMAXREGIONS = 2; //max number of regions - public final static int NREGIONS = 1; //number of regions - public final static int NSECTORS = 6; //number of sectors - public final static int NLAYERS = 2; //number of layers - public final static int NCHAMBERS = 3; //number of chambers in a sector - - public final static double XENLARGEMENT = 0.5; // cm - public final static double YENLARGEMENT = 1.; // cm - public final static double ZENLARGEMENT = 0.1; // cm - - // Sector geometrical parameters - public final static double THOPEN = 54.; // opening angle between endplate planes (deg) - public final static double THTILT = 25; // theta tilt (deg) - public final static double THMIN = 4.694; // polar angle to the base of first chamber (deg) - public final static double SECTORHEIGHT = 146.21; //height of each sector (cm) - public final static double DX0CHAMBER0 = 5.197; // halfbase of chamber 1 (cm) - - // Chamber volumes and materials (units are cm) - public final static double[] CHAMBERVOLUMESTHICKNESS = {0.0025, 0.0005,0.3, // window - 0.0025, 0.0005,0.4, // cathode - 0.0005, 0.005, 0.0005, // uRWell + DlC - 0.0005, 0.005, 0.0005, // Capacitive sharing layer1 - 0.0005, 0.005, 0.0005, // Capacitive sharing layer2 - 0.005, 0.0005,0.005, 0.005, 0.0005,0.005, 0.005, // Readout - 0.0127, 0.3, 0.0125}; // support - public final static String[] CHAMBERVOLUMESNAME = {"window_kapton", "window_Al", "window_gas", - "cathode_kapton", "cathode_Al", "cathode_gas", - "muRwell_Cu", "muRwell_kapton", "muRwell_dlc", - "capa_sharing_layer1_glue","capa_sharing_layer1_Cr","capa_sharing_layer1_kapton", - "capa_sharing_layer2_glue","capa_sharing_layer2_Cr","capa_sharing_layer2_kapton", - "readout1_glue", "readout1_Cu", "readout1_kapton", "readout2_glue", "readout2_Cu", "readout2_kapton", "readout3_glue", - "support_skin1_g10", "support_honeycomb_nomex", "support_skin2_g10"}; - - // URWELL position in the CLAS12 frame - public final static double TGT2DC0 = 228.078; // cm - // public final static double URWELL2DC0 = 2; // cm - public final static double URWELL2DC0[] = new double[NMAXREGIONS]; - public final static double DIST2TGT[] = new double[NMAXREGIONS]; - public final static double W2TGT[] = new double[NMAXREGIONS];; - public final static double YMIN[] = new double[NMAXREGIONS]; - public final static double ZMIN[] = new double[NMAXREGIONS]; - - // public final static double DIST2TGT = (TGT2DC0-URWELL2DC0); - // public final static double W2TGT = DIST2TGT/Math.cos(Math.toRadians(THTILT-THMIN)); - // public final static double YMIN = W2TGT*Math.sin(Math.toRadians(THMIN)); // distance from the base chamber1 and beamline - // public final static double ZMIN = W2TGT*Math.cos(Math.toRadians(THMIN)); - public final static double PITCH = 0.1 ; // cm - public final static double STEREOANGLE = 10; // deg - - - - // URWELL - PROTO information // - /* - public final static double DX0_PROTO = 101.2; //cm - public final static double DX1_PROTO = 146.2; //cm - public final static double HEIGHT_PROTO = 50; //cm - */ - // public final static int THILT_PROTO; // theta tilt (deg) - public final static int NREGIONS_PROTO = 1; //number of regions - public final static int NSECTORS_PROTO = 1; //number of sectors - public final static int NCHAMBERS_PROTO = 1; //number of chambers in a sector - - - // URWELL-PROTO position in CLAS12 frame - - // 4 URWELL-PROTO vertex - sensitive plane - public static Point3D Apoint = new Point3D(22.9545, -337.005, 465.9); // {X,Y,Z} - public static Point3D Bpoint = new Point3D(148.906, -264.288, 465.9); // {X,Y,Z} - public static Point3D Cpoint = new Point3D(152.047, -314.276, 445.0); // {X,Y,Z} - public static Point3D Dpoint = new Point3D(64.676, -364.719, 445.0); // {X,Y,Z} - - /* - * @return String a path to a directory in CCDB of the format {@code "/geometry/detector/"} - */ - public static String getCcdbPath() - { - return CCDBPATH; - } - - - - /** - * Loads the the necessary tables for the URWELL geometry for a given DatabaseConstantProvider. - * - * @return DatabaseConstantProvider the same thing - */ - public static DatabaseConstantProvider connect( DatabaseConstantProvider cp ) - { - // cp.loadTable( CCDBPATH +"RWELL"); - - load(cp ); - return cp; - } - - /** - * Reads all the necessary constants from CCDB into static variables. - * Please use a DatabaseConstantProvider to access CCDB and load the following tables: - * @param cp a ConstantProvider that has loaded the necessary tables - */ - - public static synchronized void load( DatabaseConstantProvider cp ) - { - // read constants from svt table -// NREGIONS = cp.getInteger( CCDBPATH+"svt/nRegions", 0 ); - - for (int i=0; i (volume.getName().contains(volumeName))) - .findAny() - .orElse(null); - } - - /** - * Returns the sector volume for the given sector number - * - * @param sector (1-6) - * @return the sector volume - */ - public Geant4Basic getSectorVolume(int region, int sector) { - - int r = region; - int s = sector; - - String volName = "region_uRwell_" + r + "_s" + s; - return this.getAllVolumes().stream() - .filter(volume -> (volume.getName().contains(volName))) - .findAny() - .orElse(null); - } - - - - - - public static void main(String[] args) { - DatabaseConstantProvider cp = new DatabaseConstantProvider(11, "default"); - - URWellConstants.connect(cp); - - URWellGeant4Factory factory = new URWellGeant4Factory(cp, false, 2); - - factory.getAllVolumes().forEach(volume -> { - System.out.println(volume.gemcString()); - }); - - - - } - -} diff --git a/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/URWELL/URWellStripFactory.java b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/URWELL/URWellStripFactory.java deleted file mode 100644 index a7ec2edb5f..0000000000 --- a/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/URWELL/URWellStripFactory.java +++ /dev/null @@ -1,456 +0,0 @@ -package org.jlab.detector.geant4.v2.URWELL; - - -import eu.mihosoft.vrl.v3d.Vector3d; -import java.util.List; -import org.jlab.detector.calib.utils.DatabaseConstantProvider; -import org.jlab.detector.hits.DetHit; -import org.jlab.detector.volume.Geant4Basic; -import org.jlab.geom.prim.Line3D; -import org.jlab.geom.prim.Plane3D; -import org.jlab.geom.prim.Point3D; -import org.jlab.geom.prim.Vector3D; -import org.jlab.geometry.prim.Line3d; -import org.jlab.geometry.prim.Straight; -import org.jlab.utils.groups.IndexedList; - -/** - * Creates and handles the URWELL detector strips as 3D lines - * - * @author bondi - */ -public final class URWellStripFactory { - - private URWellGeant4Factory factory; - private IndexedList globalStrips = new IndexedList(3); - private IndexedList localStrips = new IndexedList(3); - private IndexedList planeStrips = new IndexedList(3); - private int nRegions; - private int nSectors; - private int nChambers; - private int nLayers; - private boolean isProto; - - public URWellStripFactory() { - } - - /** - * Create the strip factory based on constants from CCDB. - * Currently constants are defined in the URWellConstants class. - * They will be moved to CCDB when finalized). - * @param cp database provide - */ - public URWellStripFactory(DatabaseConstantProvider cp) { - this.init(cp); - } - - /** - * Initialize the factory by the strip maps - * @param cp - */ - public void init(DatabaseConstantProvider cp) { - this.init(cp, false, 1); - } - - /** - * Create the strip factory based on constants from CCDB. - * Currently constants are defined in the URWellConstants class. - * They will be moved to CCDB when finalized). - * @param cp database provide - * @param prototype - * @param regions - */ - public URWellStripFactory(DatabaseConstantProvider cp, boolean prototype, int regions) { - this.init(cp, prototype, regions); - } - - /** - * Initialize the factory by the strip maps - * @param cp - * @param prototype - * @param regions - */ - public void init(DatabaseConstantProvider cp, boolean prototype, int regions) { - factory = new URWellGeant4Factory(cp, prototype, regions); - isProto = prototype; - if(!isProto){ - nRegions = Math.min(URWellConstants.NMAXREGIONS, regions); - nSectors = URWellConstants.NSECTORS; - nChambers = URWellConstants.NCHAMBERS; - nLayers = URWellConstants.NLAYERS; - } - else { - nRegions = URWellConstants.NREGIONS_PROTO; - nSectors = URWellConstants.NSECTORS_PROTO; - nChambers = URWellConstants.NCHAMBERS_PROTO; - nLayers = URWellConstants.NLAYERS; - } - this.fillStripLists(); - this.fillPlaneLists(); - } - - /** - * Calculates the total number of strips in a sector - * - * @return the strip number - */ - public int getNStripSector() { - int nStrips = 0; - for (int i = 0; i < nChambers; i++) { - nStrips += getNStripChamber(i); - } - return nStrips; - } - - /** - * Calculates the number of strips in the given chamber - * - * @param ichamber (0, 1, 2) - * @return the strip number (1-N) - */ - public int getNStripChamber(int ichamber) { - - double[] dim = factory.getChamber_daughter_Dimensions(ichamber); - - double yHalf = dim[0]; - double xHalfSmallBase = dim[1]; - double xHalfLargeBase = dim[2]; - - // C-------------D // - // ------------- // - // ----------- // - // A-------B // - /** - * * number of strip in AB** - */ - int nAB = (int) (2 * xHalfSmallBase / (URWellConstants.PITCH - / Math.sin(Math.toRadians(URWellConstants.STEREOANGLE)))); - - double AC = Math.sqrt((Math.pow((xHalfSmallBase - xHalfLargeBase), 2) + Math.pow((2 * yHalf), 2))); - double theta = Math.acos(2 * yHalf / AC); - int nAC = (int) (AC / (URWellConstants.PITCH - / Math.cos(theta - Math.toRadians(URWellConstants.STEREOANGLE)))); - - int nStrips = nAB + nAC +1 ; - - return nStrips; - } - - /** - * Provides the index of the chamber containing the strip with the given ID - * - * @param strip (1 to N) - * @return the chamber index (0, 1, 2) - */ - public int getChamberIndex(int strip) { - int nStripTotal = 0; - - for(int i=0; i strip ID chamber (from 1 to getNStripChamber) - int nStripTotal = 0; - if (chamberIndex > 0) { - for (int i = 0; i < chamberIndex; i++) { - nStripTotal += this.getNStripChamber(i); - } - } - - //Strip ID: from 1 to getNStripChamber - int cStrip = strip - nStripTotal; - - return cStrip; - } - - /** - * Builds the given strip line in the CLAS12 frame - * @param sector (1-6) - * @param layer (1-2) - * @param strip (1-N) - * @return the 3D strip line as a Line3d - */ - private Line3d createStrip(int sector, int layer, int strip) { - - int chamberIndex = getChamberIndex(strip); - - int cStrip = this.getLocalStripId(strip); - - - // CHAMBER reference frame - // new numeration with stri ID_strip=0 crossing (0,0,0) of chamber - double[] dim = factory.getChamber_daughter_Dimensions(chamberIndex); - - double yHalf = dim[0]; - double xHalfSmallBase = dim[1]; - double xHalfLargeBase = dim[2]; - - - - // Y coordinate of the intersection point between the x=0 and the strip line crossing for B - - double DY = -yHalf - Math.tan(Math.toRadians(URWellConstants.STEREOANGLE)) *xHalfSmallBase; - - // ID of the strip - int nS = (int) (DY * Math.cos(Math.toRadians(URWellConstants.STEREOANGLE)) / URWellConstants.PITCH); - int nCStrip = nS + (cStrip - 1); - - //strip straight line chamber reference frame -> y = mx +c; - double stereoAngle = URWellConstants.STEREOANGLE; - if (layer % 2 != 0) { - stereoAngle = -URWellConstants.STEREOANGLE; - } - double m = Math.tan(Math.toRadians(stereoAngle)); - double c = nCStrip * URWellConstants.PITCH / Math.cos(Math.toRadians(stereoAngle)); - - // Take 2 points in the strip straight line. They needs to define Line object - double oX = -xHalfLargeBase; - double oY = -xHalfLargeBase * m + c; - double oZ = 0; - Vector3d origin = new Vector3d(oX, oY, oZ); - - double eX = xHalfLargeBase; - double eY = xHalfLargeBase * m + c; - double eZ = 0; - Vector3d end = new Vector3d(eX, eY, eZ); - - // Get Chamber Volume - Geant4Basic chamberVolume = factory.getChamberVolume(sector, chamberIndex+1, layer, isProto); - - // 2 point defined before wrt the GLOBAL frame - Vector3d globalOrigin = chamberVolume.getGlobalTransform().transform(origin); - - Vector3d globalEnd = chamberVolume.getGlobalTransform().transform(end); - - - Straight line = new Line3d(globalOrigin, globalEnd); - - // CHECK intersections between line and volume - chamberVolume.makeSensitive(); - List Hits = chamberVolume.getIntersections(line); - - if (Hits.size() >= 1) { - - Vector3d TestOrigin = Hits.get(0).origin(); - Vector3d TestEnd = Hits.get(0).end(); - - return new Line3d(Hits.get(0).origin(), Hits.get(0).end()); - - } else { - return null; - } - } - - /** - * Provides the given strip line in the Chamber local frame - * @param region (1-2) - * @param sector (1-6) - * @param layer (1-4) - * @param strip (1-N) - * @return the 3D strip line as a Line3d - */ - - private Line3d getChamberStrip(int region, int sector, int chamber, int layer, int strip) { - - - Line3d globalStrip = createStrip(sector, layer, strip); - Geant4Basic chamberVolume = factory.getChamberVolume(sector, chamber, layer, isProto); - - Vector3d origin = chamberVolume.getGlobalTransform().invert().transform(globalStrip.origin()); - Vector3d end = chamberVolume.getGlobalTransform().invert().transform(globalStrip.end()); - - Line3d localStrip = new Line3d(origin, end); - - - return localStrip; - } - - - - /** - * Provides the given strip line in the sector local frame - * @param sector (1-6) - * @param layer (1-2) - * @param strip (1-N) - * @return the 3D strip line as a Line3d - */ - private Line3d getLocalStrip(int region, int sector, int layer, int strip) { - - Line3d globalStrip = createStrip(sector, layer, strip); - Geant4Basic sVolume = factory.getSectorVolume(region, sector); - - Vector3d origin = sVolume.getGlobalTransform().invert().transform(globalStrip.origin()); - Vector3d end = sVolume.getGlobalTransform().invert().transform(globalStrip.end()); - - Line3d localStrip = new Line3d(origin, end); - - return localStrip; - } - - - private void fillStripLists() { - - for(int ir=0; irswaps raster vtx - urwell + urwt alert bg postproc diff --git a/reconstruction/urwell/pom.xml b/reconstruction/urwt/pom.xml similarity index 93% rename from reconstruction/urwell/pom.xml rename to reconstruction/urwt/pom.xml index 492d409652..6baba51d51 100644 --- a/reconstruction/urwell/pom.xml +++ b/reconstruction/urwt/pom.xml @@ -3,7 +3,7 @@ 4.0.0 org.jlab.clas12.detector - clas12detector-urwell + clas12detector-urwt 13.6.0-SNAPSHOT jar @@ -44,5 +44,5 @@ 13.6.0-SNAPSHOT - - + clas12detector-urwt + diff --git a/reconstruction/urwell/src/main/java/org/jlab/service/urwell/URWellStrip.java b/reconstruction/urwt/src/main/java/org/jlab/service/urwt/URWRStrip.java similarity index 79% rename from reconstruction/urwell/src/main/java/org/jlab/service/urwell/URWellStrip.java rename to reconstruction/urwt/src/main/java/org/jlab/service/urwt/URWRStrip.java index cbfbfdf4fb..64f5c7c614 100644 --- a/reconstruction/urwell/src/main/java/org/jlab/service/urwell/URWellStrip.java +++ b/reconstruction/urwt/src/main/java/org/jlab/service/urwt/URWRStrip.java @@ -1,4 +1,4 @@ -package org.jlab.service.urwell; +package org.jlab.service.urwt; import java.util.ArrayList; import java.util.List; @@ -6,21 +6,21 @@ import org.jlab.detector.base.DetectorDescriptor; import org.jlab.detector.base.DetectorType; import org.jlab.detector.calib.utils.ConstantsManager; -import org.jlab.detector.geant4.v2.URWELL.URWellStripFactory; +import org.jlab.detector.geant4.v2.MPGD.URWT.URWTStripFactory; import org.jlab.geom.prim.Line3D; import org.jlab.io.base.DataEvent; /** - * URWell strip, defined based on ADC bank information and 3D line provided + * URWT strip, defined based on ADC bank information and 3D line provided * by the geometry service * * @author bondi, devita */ -public class URWellStrip implements Comparable { +public class URWRStrip implements Comparable { - private DetectorDescriptor desc = new DetectorDescriptor(DetectorType.URWELL); + private DetectorDescriptor desc = new DetectorDescriptor(DetectorType.URWT); private int chamber = 0; @@ -36,11 +36,11 @@ public class URWellStrip implements Comparable { private double time = 0; - public URWellStrip(int sector, int layer, int component){ + public URWRStrip(int sector, int layer, int component){ this.desc.setSectorLayerComponent(sector, layer, component); } - public URWellStrip(int sector, int layer, int component, int ADC, int TDC){ + public URWRStrip(int sector, int layer, int component, int ADC, int TDC){ this.desc.setSectorLayerComponent(sector, layer, component); this.ADC = ADC; this.TDC = TDC; @@ -135,7 +135,7 @@ public void setStatus(int status) { this.status = status; } - public boolean isNeighbour(URWellStrip strip){ + public boolean isNeighbour(URWRStrip strip){ if(strip.getDescriptor().getSector()==this.desc.getSector()&& strip.getDescriptor().getLayer()==this.desc.getLayer()){ int s1 = strip.getDescriptor().getComponent(); @@ -145,13 +145,13 @@ public boolean isNeighbour(URWellStrip strip){ return false; } - public boolean isInTime(URWellStrip strip) { - return Math.abs(this.getTime() - strip.getTime()) < URWellConstants.COINCTIME; + public boolean isInTime(URWRStrip strip) { + return Math.abs(this.getTime() - strip.getTime()) < URWTConstants.COINCTIME; } @Override public int compareTo(Object o) { - URWellStrip ob = (URWellStrip) o; + URWRStrip ob = (URWRStrip) o; if(ob.getDescriptor().getSector() < this.desc.getSector()) return 1; if(ob.getDescriptor().getSector() > this.desc.getSector()) return -1; if(ob.getDescriptor().getLayer() < this.desc.getLayer()) return 1; @@ -161,14 +161,14 @@ public int compareTo(Object o) { return -1; } - public static List getStrips(DataEvent event, URWellStripFactory factory, ConstantsManager ccdb) { + public static List getStrips(DataEvent event, URWTStripFactory factory, ConstantsManager ccdb) { - List strips = new ArrayList<>(); + List strips = new ArrayList<>(); - if(event.hasBank("URWELL::adc")){ - RawDataBank bank = new RawDataBank("URWELL::adc"); + if(event.hasBank("URWT::adc")){ + RawDataBank bank = new RawDataBank("URWT::adc"); bank.read(event); - //DataBank bank = event.getBank("URWELL::adc"); + //DataBank bank = event.getBank("URWT::adc"); for(int i = 0; i < bank.rows(); i++){ int sector = bank.getByte("sector", i); int layer = bank.getByte("layer", i); @@ -176,19 +176,19 @@ public static List getStrips(DataEvent event, URWellStripFactory fa int adc = bank.getInt("ADC", i); double time = bank.getFloat("time", i); - URWellStrip strip = new URWellStrip(sector, layer, comp); + URWRStrip strip = new URWRStrip(sector, layer, comp); // strip.setTriggerPhase(triggerPhase); strip.setId(bank.trueIndex(i)+1); strip.setADC(adc); strip.setTDC((int) time); - strip.setEnergy(strip.ADC*URWellConstants.ADCTOENERGY); - strip.setTime(strip.TDC*URWellConstants.TDCTOTIME); + strip.setEnergy(strip.ADC*URWTConstants.ADCTOENERGY); + strip.setTime(strip.TDC*URWTConstants.TDCTOTIME); strip.setLine(factory.getStrip(sector, layer, comp)); - strip.setChamber(factory.getChamberIndex(comp)+1); +// strip.setChamber(factory.getChamberIndex(comp)+1); strip.setStatus(0); - if(strip.getEnergy()>URWellConstants.THRESHOLD) strips.add(strip); + if(strip.getEnergy()>URWTConstants.THRESHOLD) strips.add(strip); } } diff --git a/reconstruction/urwell/src/main/java/org/jlab/service/urwell/URWellCluster.java b/reconstruction/urwt/src/main/java/org/jlab/service/urwt/URWTCluster.java similarity index 83% rename from reconstruction/urwell/src/main/java/org/jlab/service/urwell/URWellCluster.java rename to reconstruction/urwt/src/main/java/org/jlab/service/urwt/URWTCluster.java index 8f5987754f..683d8bd2a7 100644 --- a/reconstruction/urwell/src/main/java/org/jlab/service/urwell/URWellCluster.java +++ b/reconstruction/urwt/src/main/java/org/jlab/service/urwt/URWTCluster.java @@ -1,4 +1,4 @@ -package org.jlab.service.urwell; +package org.jlab.service.urwt; import java.util.ArrayList; import java.util.List; @@ -8,20 +8,20 @@ import org.jlab.geom.prim.Point3D; /** - * URWell in-layer cluster + * URWT in-layer cluster * * @author bondi, devita */ -public class URWellCluster extends ArrayList { +public class URWTCluster extends ArrayList { - private DetectorDescriptor desc = new DetectorDescriptor(DetectorType.URWELL); + private DetectorDescriptor desc = new DetectorDescriptor(DetectorType.URWT); private int id; private Line3D clusterLine = new Line3D(); public int indexMaxStrip = -1; private byte clusterStatus = 1; - public URWellCluster(URWellStrip strip){ + public URWTCluster(URWRStrip strip){ this.desc.setSectorLayerComponent(strip.getDescriptor().getSector(), strip.getDescriptor().getLayer(), 0); this.add(strip); @@ -53,7 +53,7 @@ public int getChamber() { public double getEnergy(){ double energy = 0.0; - for(URWellStrip strip : this){ + for(URWRStrip strip : this){ energy += strip.getEnergy(); } return energy; @@ -61,7 +61,7 @@ public double getEnergy(){ public double getTime(){ double time = 0.0; - for(URWellStrip strip : this){ + for(URWRStrip strip : this){ time += strip.getTime()*strip.getEnergy(); } time /= this.getEnergy(); @@ -75,7 +75,7 @@ public double getSeedTime(){ return 0.0; } - public URWellStrip getSeedStrip() { + public URWRStrip getSeedStrip() { return this.get(this.indexMaxStrip); } @@ -83,8 +83,8 @@ public int getMaxStrip(){ return this.get(this.indexMaxStrip).getDescriptor().getComponent(); } - public boolean addStrip(URWellStrip strip){ - for(URWellStrip s : this){ + public boolean addStrip(URWRStrip strip){ + for(URWRStrip s : this){ if(s.isNeighbour(strip)){ this.add(strip); if(strip.getEnergy()>this.get(indexMaxStrip).getEnergy()){ @@ -99,7 +99,7 @@ public boolean addStrip(URWellStrip strip){ public int getADC(){ int adc = 0; - for(URWellStrip s : this){ + for(URWRStrip s : this){ adc+= s.getADC(); } return adc; @@ -111,7 +111,7 @@ public int getADC(){ public void setClusterId(int id){ this.id = id; - for(URWellStrip strip : this){ + for(URWRStrip strip : this){ strip.setClusterId(id); } } @@ -155,20 +155,20 @@ public void redoClusterLine(){ } - public static List createClusters(List stripList){ + public static List createClusters(List stripList){ - List clusterList = new ArrayList<>(); + List clusterList = new ArrayList<>(); if(!stripList.isEmpty()){ for(int loop = 0; loop < stripList.size(); loop++){ //Loop over all strips boolean stripAdded = false; - for(URWellCluster cluster : clusterList) { + for(URWTCluster cluster : clusterList) { if(cluster.addStrip(stripList.get(loop))){ //Add adjacent strip to newly seeded peak stripAdded = true; } } if(!stripAdded){ - URWellCluster newPeak = new URWellCluster(stripList.get(loop)); //Non-adjacent strip seeds new peak + URWTCluster newPeak = new URWTCluster(stripList.get(loop)); //Non-adjacent strip seeds new peak clusterList.add(newPeak); } } @@ -180,9 +180,9 @@ public static List createClusters(List stripList){ return clusterList; } - public static List getClusters(List clusters, int sector, int layer) { - List selectedClusters = new ArrayList<>(); - for(URWellCluster cluster : clusters) { + public static List getClusters(List clusters, int sector, int layer) { + List selectedClusters = new ArrayList<>(); + for(URWTCluster cluster : clusters) { if(cluster.getSector()==sector && cluster.getLayer()==layer) selectedClusters.add(cluster); } @@ -196,7 +196,7 @@ public String toString(){ this.desc.getSector(),this.desc.getLayer(), this.getEnergy())); str.append(this.clusterLine.toString()); str.append("\n"); - for(URWellStrip strip : this){ + for(URWRStrip strip : this){ str.append("\t\t"); str.append(strip.toString()); str.append("\n"); diff --git a/reconstruction/urwell/src/main/java/org/jlab/service/urwell/URWellConstants.java b/reconstruction/urwt/src/main/java/org/jlab/service/urwt/URWTConstants.java similarity index 93% rename from reconstruction/urwell/src/main/java/org/jlab/service/urwell/URWellConstants.java rename to reconstruction/urwt/src/main/java/org/jlab/service/urwt/URWTConstants.java index a825418809..09d657ab75 100644 --- a/reconstruction/urwell/src/main/java/org/jlab/service/urwell/URWellConstants.java +++ b/reconstruction/urwt/src/main/java/org/jlab/service/urwt/URWTConstants.java @@ -1,10 +1,10 @@ -package org.jlab.service.urwell; +package org.jlab.service.urwt; /** * * @author bondi, devita */ -public class URWellConstants { +public class URWTConstants { // geometry diff --git a/reconstruction/urwell/src/main/java/org/jlab/service/urwell/URWellCross.java b/reconstruction/urwt/src/main/java/org/jlab/service/urwt/URWTCross.java similarity index 72% rename from reconstruction/urwell/src/main/java/org/jlab/service/urwell/URWellCross.java rename to reconstruction/urwt/src/main/java/org/jlab/service/urwt/URWTCross.java index 90fa1d2c4f..758c83ca03 100644 --- a/reconstruction/urwell/src/main/java/org/jlab/service/urwell/URWellCross.java +++ b/reconstruction/urwt/src/main/java/org/jlab/service/urwt/URWTCross.java @@ -1,4 +1,4 @@ -package org.jlab.service.urwell; +package org.jlab.service.urwt; import java.util.ArrayList; import java.util.List; @@ -10,7 +10,7 @@ * URWell V-W clusters * @author devita */ -public class URWellCross { +public class URWTCross { private int id; @@ -28,7 +28,7 @@ public class URWellCross { - public URWellCross(URWellCluster c1, URWellCluster c2) { + public URWTCross(URWTCluster c1, URWTCluster c2) { Vector3D dir = c1.getLine().direction().cross(c2.getLine().direction()); Plane3D plane = new Plane3D(c1.getLine().origin(), c1.getLine().direction().cross(dir)); @@ -36,7 +36,7 @@ public URWellCross(URWellCluster c1, URWellCluster c2) { int nint = plane.intersectionSegment(c2.getLine(), point); if(nint==1) { this.sector = c1.getSector(); - this.region = (c1.getLayer()-1)/(URWellConstants.NLAYER/URWellConstants.NREGION)+1; + this.region = (c1.getLayer()-1)/(URWTConstants.NLAYER/URWTConstants.NREGION)+1; this.cross = point; this.energy = c1.getEnergy() + c2.getEnergy(); this.time = (c1.getTime() + c2.getTime())/2; @@ -89,20 +89,20 @@ public int getStatus() { return status; } - public static List createCrosses(List clusters) { + public static List createCrosses(List clusters) { - List crosses = new ArrayList<>(); + List crosses = new ArrayList<>(); - for(int is=0; is clustersV = URWellCluster.getClusters(clusters, is+1, (URWellConstants.NLAYER/URWellConstants.NREGION)*ir+1); - List clustersW = URWellCluster.getClusters(clusters, is+1, (URWellConstants.NLAYER/URWellConstants.NREGION)*ir+2); + for(int is=0; is clustersV = URWTCluster.getClusters(clusters, is+1, (URWTConstants.NLAYER/URWTConstants.NREGION)*ir+1); + List clustersW = URWTCluster.getClusters(clusters, is+1, (URWTConstants.NLAYER/URWTConstants.NREGION)*ir+2); - for(URWellCluster v : clustersV) { - for(URWellCluster w : clustersW) { + for(URWTCluster v : clustersV) { + for(URWTCluster w : clustersW) { if(v.getChamber()==w.getChamber()) { - URWellCross cross = new URWellCross(v, w); + URWTCross cross = new URWTCross(v, w); if(cross.point()!=null) crosses.add(cross); cross.setId(crosses.size()); } diff --git a/reconstruction/urwell/src/main/java/org/jlab/service/urwell/URWellEngine.java b/reconstruction/urwt/src/main/java/org/jlab/service/urwt/URWTEngine.java similarity index 80% rename from reconstruction/urwell/src/main/java/org/jlab/service/urwell/URWellEngine.java rename to reconstruction/urwt/src/main/java/org/jlab/service/urwt/URWTEngine.java index fcb53c5ad1..de555dbf26 100644 --- a/reconstruction/urwell/src/main/java/org/jlab/service/urwell/URWellEngine.java +++ b/reconstruction/urwt/src/main/java/org/jlab/service/urwt/URWTEngine.java @@ -1,4 +1,4 @@ -package org.jlab.service.urwell; +package org.jlab.service.urwt; import java.util.List; import java.util.Optional; @@ -8,7 +8,7 @@ import org.jlab.clas.reco.ReconstructionEngine; import org.jlab.detector.base.DetectorType; import org.jlab.detector.calib.utils.DatabaseConstantProvider; -import org.jlab.detector.geant4.v2.URWELL.URWellStripFactory; +import org.jlab.detector.geant4.v2.MPGD.URWT.URWTStripFactory; import org.jlab.geom.prim.Point3D; import org.jlab.groot.data.H1F; import org.jlab.groot.fitter.DataFitter; @@ -21,18 +21,18 @@ /** * - * URWell reconstruction engine + * URWT reconstruction engine * * @author bondi, devita */ -public class URWellEngine extends ReconstructionEngine { +public class URWTEngine extends ReconstructionEngine { - public static Logger LOGGER = Logger.getLogger(URWellEngine.class.getName()); + public static Logger LOGGER = Logger.getLogger(URWTEngine.class.getName()); - public static URWellStripFactory factory = new URWellStripFactory(); + public URWTStripFactory factory = null; - public URWellEngine() { - super("URWell","bondi","1.0"); + public URWTEngine() { + super("URWT","bondi","1.0"); } @Override @@ -40,14 +40,14 @@ public boolean init() { // init ConstantsManager to read constants from CCDB String variationName = Optional.ofNullable(this.getEngineConfigString("variation")).orElse("default"); - DatabaseConstantProvider cp = new DatabaseConstantProvider(11, variationName); - factory.init(cp, false, URWellConstants.NREGION); + + factory = new URWTStripFactory(11, variationName); // register output banks for drop option - this.registerOutputBank("URWELL::hits"); - this.registerOutputBank("URWELL::clusters"); - this.registerOutputBank("URWELL::crosses"); + this.registerOutputBank("URWT::hits"); + this.registerOutputBank("URWT::clusters"); + this.registerOutputBank("URWT::crosses"); - LOGGER.log(Level.INFO, "--> URWells are ready..."); + LOGGER.log(Level.INFO, "--> URWTs are ready..."); return true; } @@ -57,9 +57,9 @@ public boolean init() { @Override public boolean processDataEvent(DataEvent event) { - List strips = URWellStrip.getStrips(event, factory, this.getConstantsManager()); - List clusters = URWellCluster.createClusters(strips); - List crosses = URWellCross.createCrosses(clusters); + List strips = URWRStrip.getStrips(event, factory, this.getConstantsManager()); + List clusters = URWTCluster.createClusters(strips); + List crosses = URWTCross.createCrosses(clusters); this.writeHipoBanks(event, strips, clusters, crosses); @@ -68,11 +68,11 @@ public boolean processDataEvent(DataEvent event) { private void writeHipoBanks(DataEvent de, - List strips, - List clusters, - List crosses){ + List strips, + List clusters, + List crosses){ - DataBank bankS = de.createBank("URWELL::hits", strips.size()); + DataBank bankS = de.createBank("URWT::hits", strips.size()); for(int h = 0; h < strips.size(); h++){ bankS.setShort("id", h, (short) strips.get(h).getId()); bankS.setByte("sector", h, (byte) strips.get(h).getDescriptor().getSector()); @@ -84,7 +84,7 @@ private void writeHipoBanks(DataEvent de, bankS.setShort("clusterId", h, (short) strips.get(h).getClusterId()); } - DataBank bankC = de.createBank("URWELL::clusters", clusters.size()); + DataBank bankC = de.createBank("URWT::clusters", clusters.size()); for(int c = 0; c < clusters.size(); c++){ bankC.setShort("id", c, (short) clusters.get(c).getId()); bankC.setByte("sector", c, (byte) clusters.get(c).get(0).getDescriptor().getSector()); @@ -102,7 +102,7 @@ private void writeHipoBanks(DataEvent de, bankC.setShort("status", c, (short) clusters.get(c).getStatus()); } - DataBank bankX = de.createBank("URWELL::crosses", crosses.size()); + DataBank bankX = de.createBank("URWT::crosses", crosses.size()); for(int c = 0; c < crosses.size(); c++){ bankX.setShort("id", c, (short) crosses.get(c).getId()); bankX.setByte("sector", c, (byte) crosses.get(c).getSector()); @@ -154,14 +154,14 @@ public static void fitGauss(H1F histo) { public static void main (String arg[]) { - URWellEngine engine = new URWellEngine(); + URWTEngine engine = new URWTEngine(); engine.init(); String input = "/Users/devita/urwell3d.hipo"; DataGroup dg = new DataGroup(3, 2); String[] axes = {"x", "y"}; - for(int il=0; il