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 4ee7c44cf8..a07cbc2452 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 @@ -33,7 +33,8 @@ public enum DetectorType { URWT (23, "URWT"), AHDC (24, "AHDC"), ATOF (25, "ATOF"), - RECOIL (26, "RECOIL"), + RTRK (26, "RTRK"), + RTOF (27, "RTOF"), MUCAL (28, "MUCAL"), MUVT (29, "MUVT"), MURT (30, "MURT"), diff --git a/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/recoil/RecoilConstants.java b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/recoil/RecoilConstants.java deleted file mode 100644 index 805407434e..0000000000 --- a/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/recoil/RecoilConstants.java +++ /dev/null @@ -1,108 +0,0 @@ -package org.jlab.detector.geant4.v2.recoil; - - -import org.jlab.detector.calib.utils.DatabaseConstantProvider; -import org.jlab.geom.prim.Point3D; - - -public class RecoilConstants { - - private final static String CCDBPATH = "/geometry/recoil/"; - - public final static int NMAXREGIONS = 3; //max number of regions - public final static int NREGIONS = 3; //number of regions - public final static int NSECTORS = 2; //number of sectors - public final static int NLAYERS = 2; //number of layers - public final static int NCHAMBERS = 1; //number of chambers in a sector - - public final static double HORIZONTHAL_OPENING_ANGLE = 34.; - public final static double VERTICAL_OPENING_ANGLE = 50.; - public final static double RADIUS[] = {33.5,55.5,79.5}; - public final static double WIDTH[] = new double[NMAXREGIONS]; - public final static double HEIGHT[] = new double[NMAXREGIONS]; - - public final static double THTILT = 0; // theta tilt (deg) - /* 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 = 34.; // opening angle between endplate planes (deg) - public final static double THTILT = 0; // 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 PITCH = 0.1 ; // cm - public final static double STEREOANGLE = 90; // deg - - /* - * @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_Recoil_" + 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"); - - RecoilConstants.connect(cp); - - RecoilGeant4Factory factory = new RecoilGeant4Factory(cp, 1); - - factory.getAllVolumes().forEach(volume -> { - System.out.println(volume.gemcString()); - }); - - } -} diff --git a/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/recoil/tof/RTOFConstants.java b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/recoil/tof/RTOFConstants.java new file mode 100644 index 0000000000..5ef906db7b --- /dev/null +++ b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/recoil/tof/RTOFConstants.java @@ -0,0 +1,43 @@ +package org.jlab.detector.geant4.v2.recoil.tof; + +import org.jlab.detector.calib.utils.DatabaseConstantProvider; + +public class RTOFConstants { + + public final static int NSECTORS = 2; //number of sectors + public final static int NROWS = 5; //number of rows of bars in a sector + public final static int NCOLUMNS = 63; //number of columns of bars in a sector + + public final static double LONG_BAR_LENGTH = 27.5; // cm + public final static double SHORT_BAR_LENGTH = 4; // cm + + public final static double BAR_WIDTH = 1; // cm + public final static double BAR_THICKNESS = 0.5; // cm + + public final static double HORIZONTAL_STARTING_ANGLE = 40.; + public final static double HORIZONTAL_OPENING_ANGLE = 29.; + public final static double RADIUS = 122.; // cm + + public final static double WIDTH = NCOLUMNS * BAR_WIDTH; + public final static double LENGTH = (NROWS-1) * LONG_BAR_LENGTH + SHORT_BAR_LENGTH; + public final static double THICKNESS = 0.5; // cm + + public static DatabaseConstantProvider connect( DatabaseConstantProvider cp ) + { + 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 ) + { + //WIDTH = NCOLUMNS * BAR_WIDTH; + //LENGTH = (NROWS-1) * LONG_BAR_LENGTH + SHORT_BAR_LENGTH; + //THICKNESS = 0.5; // cm + } + +} \ No newline at end of file diff --git a/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/recoil/tof/RTOFGeant4Factory.java b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/recoil/tof/RTOFGeant4Factory.java new file mode 100644 index 0000000000..82926db40a --- /dev/null +++ b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/recoil/tof/RTOFGeant4Factory.java @@ -0,0 +1,129 @@ +package org.jlab.detector.geant4.v2.recoil.tof; + +import eu.mihosoft.vrl.v3d.Vector3d; +import org.jlab.detector.geant4.v2.Geant4Factory; +import org.jlab.detector.volume.G4World; +import org.jlab.detector.volume.G4Box; +import org.jlab.detector.volume.Geant4Basic; +import org.jlab.detector.calib.utils.DatabaseConstantProvider; + +/** + * Generate GEANT4 volume for the RECOIL TOF detector + * + * @author Nilanga Wickramaarachchi + */ +public final class RTOFGeant4Factory extends Geant4Factory { + + private int nSectors = RTOFConstants.NSECTORS; + private int nRows = RTOFConstants.NROWS; + private int nCols = RTOFConstants.NCOLUMNS; + + public RTOFGeant4Factory( DatabaseConstantProvider cp) { + RTOFConstants.connect(cp ); + this.init(cp); + } + + public void init(DatabaseConstantProvider cp) { + motherVolume = new G4World("root"); + for (int isector = 0; isector < nSectors; isector++) { + Geant4Basic sectorVolume = createSector(isector, nRows, nCols); + sectorVolume.setName("recoil_tof_sector" + (isector + 1)); + sectorVolume.setMother(motherVolume); + } + } + + public Vector3d getCenterCoordinate(int isector) + { + int is=isector; + Vector3d vCenter = new Vector3d(0, 0, 0); + vCenter.x = (-1+is*2)*(RTOFConstants.RADIUS)*Math.sin(Math.toRadians(RTOFConstants.HORIZONTAL_OPENING_ANGLE/2+RTOFConstants.HORIZONTAL_STARTING_ANGLE)); + vCenter.y = 0; + vCenter.z =RTOFConstants.RADIUS*Math.cos(Math.toRadians(RTOFConstants.HORIZONTAL_OPENING_ANGLE/2+RTOFConstants.HORIZONTAL_STARTING_ANGLE)); + return vCenter; + } + + public Geant4Basic createSector(int isector, int nRows, int nCols ) { + + double hlx = RTOFConstants.WIDTH/2+1; + double hly = RTOFConstants.LENGTH/2+1; + double hlz = RTOFConstants.THICKNESS/2+1; + + Vector3d vCenter = this.getCenterCoordinate(isector); + + Geant4Basic sectorVolume = new G4Box("recoil_tof_sector" + (isector + 1), hlx, hly, hlz); + + if(isector==0) sectorVolume.rotate("yxz",Math.toRadians((RTOFConstants.HORIZONTAL_OPENING_ANGLE/2+RTOFConstants.HORIZONTAL_STARTING_ANGLE)),0,0); + if(isector==1) sectorVolume.rotate("yxz",Math.toRadians(-(RTOFConstants.HORIZONTAL_OPENING_ANGLE/2+RTOFConstants.HORIZONTAL_STARTING_ANGLE)),0,0); + sectorVolume.translate(vCenter.x, vCenter.y, vCenter.z); + sectorVolume.setId(isector + 1, 0, 0); + + // Bars construction + for (int row = 0; row < nRows; row++) { + for (int col = 0; col < nCols; col++) { + + Geant4Basic barVolume = this.createBar(isector, row, col); + + barVolume.setName("bar_sector" + (isector + 1) + "_row" + (row + 1) + "_column" + (col + 1)); + + barVolume.setMother(sectorVolume); + + barVolume.setId(isector + 1, row +1, col+1, 0); + } + } + + return sectorVolume; + } + + public Geant4Basic createBar(int iSector, int iRow, int iCol) { + + int nCols = RTOFConstants.NCOLUMNS; + + double barDX = RTOFConstants.BAR_WIDTH/2; + double barDY; + + if (iRow == (nRows - 1) / 2) barDY = RTOFConstants.SHORT_BAR_LENGTH/2; + else barDY = RTOFConstants.LONG_BAR_LENGTH/2; + + double barDZ = RTOFConstants.BAR_THICKNESS/2; + + Geant4Basic barVolume = new G4Box("bar_sector" + (iSector + 1) + "_row" + (iRow + 1) + "_column" + (iCol + 1), barDX, barDY, barDZ); + + // Constants for positioning + double y_start = -(RTOFConstants.LENGTH - RTOFConstants.LONG_BAR_LENGTH)/2; // Starting Y position + double x_spacing = RTOFConstants.BAR_WIDTH; + double x_start = -(RTOFConstants.WIDTH - x_spacing)/2; // starting X position + double dy_long = RTOFConstants.LONG_BAR_LENGTH; + double dy_short = RTOFConstants.SHORT_BAR_LENGTH; + + //Position calculation + double z_pos = 0; + double x_pos = x_start + (iCol * x_spacing); + + double y_pos; + if (iRow < (nRows - 1) / 2) { + y_pos = y_start + (iRow * dy_long); + } + else if (iRow == (nRows - 1) / 2) {// middle row + y_pos = 0; + } + else { + y_pos = y_start + (iRow -1) * dy_long + dy_short; + } + + barVolume.setPosition(x_pos, y_pos, z_pos); + + return barVolume; + } + + public static void main(String[] args) { + DatabaseConstantProvider cp = new DatabaseConstantProvider(11, "default"); + + RTOFConstants.connect(cp); + + RTOFGeant4Factory factory = new RTOFGeant4Factory(cp); + + factory.getAllVolumes().forEach(volume -> { + System.out.println(volume.gemcString()); + }); + } +} \ No newline at end of file diff --git a/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/recoil/trk/RTRKConstants.java b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/recoil/trk/RTRKConstants.java new file mode 100644 index 0000000000..5df67bf460 --- /dev/null +++ b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/recoil/trk/RTRKConstants.java @@ -0,0 +1,106 @@ +package org.jlab.detector.geant4.v2.recoil.trk; + +import org.jlab.detector.calib.utils.DatabaseConstantProvider; + +public class RTRKConstants { + + private final static String CCDBPATH = "/geometry/recoil/trk/"; + + public final static int NMAXREGIONS = 3; //max number of regions + public final static int NREGIONS = 3; //number of regions + public final static int NSECTORS = 2; //number of sectors + public final static int NLAYERS = 2; //number of layers + public final static int NCHAMBERS = 1; //number of chambers in a sector + + public final static double HORIZONTHAL_OPENING_ANGLE = 34.; + public final static double VERTICAL_OPENING_ANGLE = 50.; + public final static double RADIUS[] = {33.5,55.5,79.5}; + public final static double WIDTH[] = new double[NMAXREGIONS]; + public final static double HEIGHT[] = new double[NMAXREGIONS]; + + public final static double THTILT = 0; // theta tilt (deg) + /* 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 = 34.; // opening angle between endplate planes (deg) + public final static double THTILT = 0; // 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 PITCH = 0.1 ; // cm + public final static double STEREOANGLE = 90; // deg + + /* + * @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_rtrk_" + 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"); + RTRKConstants.connect(cp); + RTRKGeant4Factory factory = new RTRKGeant4Factory(cp, 1); + factory.getAllVolumes().forEach(volume -> { + System.out.println(volume.gemcString()); + }); + } +} diff --git a/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/recoil/RecoilStripFactory.java b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/recoil/trk/RTRKStripFactory.java similarity index 54% rename from common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/recoil/RecoilStripFactory.java rename to common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/recoil/trk/RTRKStripFactory.java index 9a4144f2a6..7368335c7e 100644 --- a/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/recoil/RecoilStripFactory.java +++ b/common-tools/clas-jcsg/src/main/java/org/jlab/detector/geant4/v2/recoil/trk/RTRKStripFactory.java @@ -1,4 +1,4 @@ -package org.jlab.detector.geant4.v2.recoil; +package org.jlab.detector.geant4.v2.recoil.trk; import eu.mihosoft.vrl.v3d.Vector3d; import java.util.List; @@ -15,12 +15,12 @@ /** * Creates and handles the URWELL detector strips as 3D lines - * + * * @author bondi, niccolai */ -public final class RecoilStripFactory { - - private RecoilGeant4Factory factory; +public final class RTRKStripFactory { + + private RTRKGeant4Factory factory; private IndexedList globalStrips = new IndexedList(3); private IndexedList localStrips = new IndexedList(3); private IndexedList planeStrips = new IndexedList(3); @@ -29,16 +29,16 @@ public final class RecoilStripFactory { private int nChambers; private int nLayers; - public RecoilStripFactory() { + public RTRKStripFactory() { } /** * Create the strip factory based on constants from CCDB. - * Currently constants are defined in the RecoilConstants class. + * Currently constants are defined in the RTRKConstants class. * They will be moved to CCDB when finalized). * @param cp database provide */ - public RecoilStripFactory(DatabaseConstantProvider cp) { + public RTRKStripFactory(DatabaseConstantProvider cp) { this.init(cp); } @@ -49,15 +49,15 @@ public RecoilStripFactory(DatabaseConstantProvider cp) { public void init(DatabaseConstantProvider cp) { this.init(cp, 1); } - + /** * Create the strip factory based on constants from CCDB. - * Currently constants are defined in the URWellConstants class. + * Currently constants are defined in the RTRKConstants class. * They will be moved to CCDB when finalized). * @param cp database provide * @param regions */ - public RecoilStripFactory(DatabaseConstantProvider cp, int regions) { + public RTRKStripFactory(DatabaseConstantProvider cp, int regions) { this.init(cp, regions); } @@ -67,45 +67,45 @@ public RecoilStripFactory(DatabaseConstantProvider cp, int regions) { * @param regions */ public void init(DatabaseConstantProvider cp, int regions) { - factory = new RecoilGeant4Factory(cp, regions); - nRegions = Math.min(RecoilConstants.NMAXREGIONS, regions); - nSectors = RecoilConstants.NSECTORS; - nChambers = RecoilConstants.NCHAMBERS; - nLayers = RecoilConstants.NLAYERS; + factory = new RTRKGeant4Factory(cp, regions); + nRegions = Math.min(RTRKConstants.NMAXREGIONS, regions); + nSectors = RTRKConstants.NSECTORS; + nChambers = RTRKConstants.NCHAMBERS; + nLayers = RTRKConstants.NLAYERS; this.fillStripLists(); - // this.fillPlaneLists(); + // 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++) { - for (int j = 0; j < nRegions; j++) { - nStrips += getNStripChamber(i,j); - } - } + for (int j = 0; j < nRegions; j++) { + nStrips += getNStripChamber(i,j); + } + } 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, int regions) { - - int iregion = regions; - int chamber = ichamber; + + int iregion = regions; + int chamber = ichamber; double[] dim = factory.getChamber_daughter_Dimensions(iregion,chamber); - + double yHalf = dim[1]; - double xHalf = dim[0]; - + double xHalf = dim[0]; + // C-------------D // // ------------- // // ------------- // @@ -113,56 +113,56 @@ public int getNStripChamber(int ichamber, int regions) { /** * * number of strip in AB** */ - - int nAB = (int) (2 * xHalf / RecoilConstants.PITCH); - int nAC = (int) (2 * yHalf / RecoilConstants.PITCH); - - int nStrips = nAB + nAC; - + + int nAB = (int) (2 * xHalf / RTRKConstants.PITCH); + int nAC = (int) (2 * yHalf / RTRKConstants.PITCH); + + int nStrips = nAB + nAC; + 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++) { - for (int j = 0; j < nRegions; j++) { - nStripTotal += this.getNStripChamber(i,j); - } - } + for (int j = 0; j < nRegions; j++) { + nStripTotal += this.getNStripChamber(i,j); + } + } } - - //Strip ID: from 1 to getNStripChamber + + //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) @@ -171,79 +171,79 @@ private int getLocalStripId(int strip) { * @return the 3D strip line as a Line3d */ private Line3d createStrip(int sector, int region, 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(region-1,chamberIndex); double yHalf = dim[1]; - double xHalf = dim[0]; - - double DY = -xHalf; //v strip - + double xHalf = dim[0]; + + double DY = -xHalf; //v strip + // Y coordinate of the intersection point between the x=0 and the strip line crossing for B - - if (layer % 2 != 0) { //u strip - DY = -yHalf; - } - // ID of the strip - int nS = (int) (DY / RecoilConstants.PITCH); + + if (layer % 2 != 0) { //u strip + DY = -yHalf; + } + // ID of the strip + int nS = (int) (DY / RTRKConstants.PITCH); int nCStrip = nS + (cStrip - 1); - double c = nCStrip * RecoilConstants.PITCH; - - // Take 2 points in the strip straight line. They needs to define Line object + double c = nCStrip * RTRKConstants.PITCH; + + // Take 2 points in the strip straight line. They needs to define Line object //u strips double oX = -xHalf; double oY = c; double oZ = 0; - + double eX = xHalf; double eY = c; double eZ = 0; - + if (layer % 2 == 0) { //v strips - oX = c; - oY = -yHalf; - oZ = 0; - - eX = c; - eY = yHalf; - eZ = 0; - } - - Vector3d origin = new Vector3d(oX, oY, oZ); - Vector3d end = new Vector3d(eX, eY, eZ); - + oX = c; + oY = -yHalf; + oZ = 0; + + eX = c; + eY = yHalf; + eZ = 0; + } + + Vector3d origin = new Vector3d(oX, oY, oZ); + Vector3d end = new Vector3d(eX, eY, eZ); + // Get Chamber Volume Geant4Basic chamberVolume = factory.getChamberVolume(sector, region, chamberIndex+1, layer); - - // 2 point defined before wrt the GLOBAL frame + + // 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(); - + + 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) @@ -251,19 +251,19 @@ private Line3d createStrip(int sector, int region, int layer, int strip) { * @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, region, layer, strip); - Geant4Basic chamberVolume = factory.getChamberVolume(sector, region, chamber, layer); - - Vector3d origin = chamberVolume.getGlobalTransform().invert().transform(globalStrip.origin()); - Vector3d end = chamberVolume.getGlobalTransform().invert().transform(globalStrip.end()); - - Line3d localStrip = new Line3d(origin, end); - - return localStrip; + + Line3d globalStrip = createStrip(sector, region, layer, strip); + Geant4Basic chamberVolume = factory.getChamberVolume(sector, region, chamber, layer); + + 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) @@ -272,20 +272,18 @@ private Line3d getChamberStrip(int region, int sector, int chamber, int layer, i * @return the 3D strip line as a Line3d */ private Line3d getLocalStrip(int region, int sector, int layer, int strip) { - - + Line3d globalStrip = createStrip(sector, region, 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; ir-xHalf && c-yHalf && c-xHalf && c-yHalf && c-xHalf && c-yHalf && c-xHalf && c-yHalf && c + * Uses found hits information. Creates a {@link RTOFCluster} matching them. + *

+ * + * @author pilleux, Nilanga Wickramaarachchi + */ +public class ClusterFinder { + + /** + * list of clusters. + */ + private ArrayList clusters; + + /** + * Sets the list of clusters. + * + * @param clusters a {@link ArrayList} of {@link RTOFCluster}. + * + */ + public void setClusters(ArrayList clusters) { + this.clusters = clusters; + } + + /** + * Gets the list of clusters. + * + * @return a {@link ArrayList} of {@link RTOFCluster}. + * + */ + public ArrayList getClusters() { + return clusters; + } + + + /** + * Cluster hits around a given hit, based on the time and geometric + * proximity. + * + * Hits are compared based on their y difference, which + * is distance in cm and time difference. + * + * If the hit satisfies all conditions, it is marked as clustered and added + * to the cluster hit list. + * + * + * @param The type of the hit objects, which must extend + * {@link RTOFRawHit}. This allows the method to work with different types of + * hits that are subclasses of {@link RTOFRawHit} (e.g., {@link RTOFHit}). + * @param i The index from which hits are read in the list to compare + * against the current hit. + * @param hits The list of hits to be clustered, can be any subclass of + * {@link RTOFRawHit}. + * @param this_hit The hit currently being considered for clustering. + * @param sigma_y The threshold for the y-distance [cm] between the hits. + * @param sigma_t The threshold for the time difference [ns] between the + * hits. + * @param cluster_id The ID of the cluster being formed. + * @param this_cluster_hits The list that will store the clustered hits. + * This list can accept hits of type RTOFRawHit or RTOFHit. Clustered hits are + * added to this list. + * + */ + public void clusterHits(int i, ArrayList hits, RTOFRawHit this_hit, Number sigma_y, double sigma_t, int cluster_id, ArrayList this_cluster_hits) { + // Loop through less energetic clusters + for (int j = i + 1; j < hits.size(); j++) { + T other_hit = hits.get(j); + // Skip already clustered hits + if (other_hit.getIsInACluster()) { + continue; + } + // Check the distance between the hits + double delta_T = Math.abs(this_hit.getTime() - other_hit.getTime()); + //The y distance is a distance in cm + Boolean condition_y; + double delta_Y = Math.abs(this_hit.getY() - other_hit.getY()); + condition_y = (delta_Y <= sigma_y.doubleValue()); + + //If hit is within limits, it is clustered + if (condition_y) { + if (delta_T < sigma_t) { + other_hit.setIsInACluster(true); + other_hit.setAssociatedClusterIndex(cluster_id); + this_cluster_hits.add(other_hit); + } + } + } + } + + + /** + * Builds clusters in the {@link DateEvent} using hits found and stored in a + * {@link HitFinder}. + * + * @param hitfinder the {@link HitFinder} containing the hits that were + * found + * + * @param sigma_y the tolerance for clustering in y [cm] + * + * @param sigma_t the tolerance for clustering in time [ns] + * + */ + public void makeClusters(HitFinder hitfinder, double sigma_y, double sigma_t, DataEvent event) { + + //A list of clusters is built for each event + clusters.clear(); + int cluster_id = 1; + + //Getting the list of hits, they must have been ordered by energy already + ArrayList rtof_hits = hitfinder.getRTOFHits(); + + //Loop through all bar hits + for (int i_bar = 0; i_bar < rtof_hits.size(); i_bar++) { + RTOFHit this_rtof_hit = rtof_hits.get(i_bar); + //Skip hits that have already been clustered + if (this_rtof_hit.getIsInACluster()) { + continue; + } + + ArrayList this_cluster_rtof_hits = new ArrayList<>(); + this_rtof_hit.setIsInACluster(true); + this_rtof_hit.setAssociatedClusterIndex(cluster_id); + this_cluster_rtof_hits.add(this_rtof_hit); + + //Matching bar hits in clusters + clusterHits(i_bar, rtof_hits, this_rtof_hit, sigma_y, sigma_t, cluster_id, this_cluster_rtof_hits); + + RTOFCluster cluster = new RTOFCluster(this_cluster_rtof_hits, event); + clusters.add(cluster); + cluster_id++; + } + } + + /** + * Builds clusters in the {@link DataEvent} using hits found and stored in a + * {@link HitFinder}. + * + * @param event the {@link DataEvent} containing the clusters to be built + * + * @param hitfinder the {@link HitFinder} containing the hits that were + * found + * + */ + public void makeClusters(DataEvent event, HitFinder hitfinder) { + makeClusters(hitfinder, + Parameters.SIGMA_Y_CLUSTERING, + Parameters.SIGMA_T_CLUSTERING, event); + } + + /** + * Default constructor that initializes the list clusters as new empty list. + */ + public ClusterFinder() { + clusters = new ArrayList<>(); + } +} diff --git a/reconstruction/recoil/src/main/java/org/jlab/service/recoil/tof/HitFinder.java b/reconstruction/recoil/src/main/java/org/jlab/service/recoil/tof/HitFinder.java new file mode 100644 index 0000000000..d79024693c --- /dev/null +++ b/reconstruction/recoil/src/main/java/org/jlab/service/recoil/tof/HitFinder.java @@ -0,0 +1,113 @@ +package org.jlab.service.recoil.tof; + +import java.util.ArrayList; +import java.util.Collections; +import org.jlab.io.base.DataBank; +import org.jlab.io.base.DataEvent; + +/** + * The {@code HitFinder} class finds hits in the recoil tof. + * + *

+ * Uses recoil tof tdc bank information + * + * Creates a {@link ArrayList} of {@link RTOFHit} for rtof hits read. + * + *

+ * + * @author pilleux, Nilanga Wickramaarachchi + */ +public class HitFinder { + + /** + * list of rtof hits + */ + private ArrayList rtofHits; + + /** + * Default constructor that initializes the list of hits as new empty lists. + */ + public HitFinder() { + this.rtofHits = new ArrayList<>(); + } + + // Getter and Setter for rtofHits + public ArrayList getRTOFHits() { + return rtofHits; + } + + public void setRTOFHits(ArrayList rtof_hits) { + this.rtofHits = rtof_hits; + } + + /** + * + * @param event the {@link DataEvent} containing hits. + * + */ + public void findHits(DataEvent event) { + //For each event a list of rtof hits is filled + this.rtofHits.clear(); + //They are read from the RTOF TDC bank + DataBank bank = event.getBank("RTOF::tdc"); + int nt = bank.rows(); // number of hits + //Hits in the bar downstream and upstream will be matched + ArrayList hit_up = new ArrayList<>(); + ArrayList hit_down = new ArrayList<>(); + + //Looping through all hits + for (int i = 0; i < nt; i++) { + //Getting their properties + int sector = bank.getByte("sector", i); + int layer = bank.getByte("layer", i); + int component = bank.getByte("component", i); + int order = bank.getShort("order", i); + int tdc = bank.getShort("TDC", i); + int tot = bank.getShort("ToT", i); + + //Building a Hit + RTOFRawHit hit = new RTOFRawHit(sector, layer, component, order, tdc, tot); + if (hit.getEnergy() < 0.01) { + continue; //energy threshold + } + + //Sorting the hits into upstream and downstream bar hits + //Lists are built for up/down bar to match them after + if (null == hit.getType()) { + System.out.print("Undefined hit type \n"); + } else { + switch (hit.getType()) { + case "bar up" -> + hit_up.add(hit); + case "bar down" -> + hit_down.add(hit); + default -> + System.out.print("Undefined hit type \n"); + } + } + }//End loop through all hits + + //Starting loop through up hits in the bar + for (int i_up = 0; i_up < hit_up.size(); i_up++) { + RTOFRawHit this_hit_up = hit_up.get(i_up); + int countMatches = 0; + //Starting loop through down hits in the bar + for (int i_down = 0; i_down < hit_down.size(); i_down++) { + RTOFRawHit this_hit_down = hit_down.get(i_down); + //Matching the hits: if same bar and different order, they make up a rtof hit + if (this_hit_up.matchBar(this_hit_down)) { + if (countMatches > 0) { + //If the up hit was already involved in a match, do not make an additionnal match + //Chosing to ignore double matches for now because it happened for <1% of events in cosmic runs + continue; + } + RTOFHit this_rtof_hit = new RTOFHit(this_hit_down, this_hit_up); + this.rtofHits.add(this_rtof_hit); + countMatches++; + } + } + } + //Once all has been listed, hits are sorted by energy + Collections.sort(this.rtofHits, (hit1, hit2) -> Double.compare(hit2.getEnergy(), hit1.getEnergy())); + } +} diff --git a/reconstruction/recoil/src/main/java/org/jlab/service/recoil/tof/Parameters.java b/reconstruction/recoil/src/main/java/org/jlab/service/recoil/tof/Parameters.java new file mode 100644 index 0000000000..c6b8f7f9fc --- /dev/null +++ b/reconstruction/recoil/src/main/java/org/jlab/service/recoil/tof/Parameters.java @@ -0,0 +1,25 @@ +package org.jlab.service.recoil.tof; + +/** + * + * @author npilleux, Nilanga Wickramaarachchi + */ +public class Parameters { + + public static final double VEFF = 20.0;//cm/ns + public static final double TDC2TIME = 0.015625;//ns per channel bin + public static final double ATT_L = 160.0;//cm + public static final double TOT2ENERGY = 1.956 * 0.5 /1000;//to MeV + + //public static double SIGMA_Y_TRACK_MATCHING_BAR = 20.0;//in cm + public static double SIGMA_Y_CLUSTERING = 4.0;//in cm + public static double SIGMA_T_CLUSTERING = 100;// in ns + + /** + * @param args the command line arguments + */ + public static void main(String[] args) { + // TODO code application logic here + } + +} diff --git a/reconstruction/recoil/src/main/java/org/jlab/service/recoil/tof/RTOFCluster.java b/reconstruction/recoil/src/main/java/org/jlab/service/recoil/tof/RTOFCluster.java new file mode 100644 index 0000000000..a5cf256a59 --- /dev/null +++ b/reconstruction/recoil/src/main/java/org/jlab/service/recoil/tof/RTOFCluster.java @@ -0,0 +1,240 @@ +package org.jlab.service.recoil.tof; + +import java.util.ArrayList; +import org.jlab.io.base.DataEvent; + +/** + * The {@code RTOFCluster} represents clusters in the recoil tof + * + *

+ * Create clusters and compute their basic properties from the hits composing + * them. + *

+ * + * @author pilleux, Nilanga Wickramaarachchi + */ +public class RTOFCluster { + + /** + * list of hits in the bars. + */ + ArrayList rtofHits; + /** + * cluster properties:position [cm], time [ns], energy[MeV], + * type of the maximum hit (to set resolutions) and index and sector of the maximum hit. + */ + double x, y, z, time, energy; + String typeMaxHit; + int indexMaxHit, sectorMaxHit; + + public ArrayList getRTOFHits() { + return rtofHits; + } + + public void setRTOFHits(ArrayList rtof_hits) { + this.rtofHits = rtof_hits; + } + + public double getX() { + return x; + } + + public void setX(double x) { + this.x = x; + } + + public double getY() { + return y; + } + + public void setY(double y) { + this.y = y; + } + + public double getZ() { + return z; + } + + public void setZ(double z) { + this.z = z; + } + + public double getTime() { + return time; + } + + public void setTime(double time) { + this.time = time; + } + + public double getEnergy() { + return energy; + } + + public void setEnergy(double energy) { + this.energy = energy; + } + + + public String getTypeMaxHit() { + return typeMaxHit; + } + + public void setTypeMaxHit(String typeMaxHit) { + this.typeMaxHit = typeMaxHit; + } + + public int getIndexMaxHit() { + return indexMaxHit; + } + + public void setIndexMaxHit(int indexMaxHit) { + this.indexMaxHit = indexMaxHit; + } + + public int getSectorMaxHit() { + return sectorMaxHit; + } + + public void setSectorMaxHit(int sectorMaxHit) { + this.sectorMaxHit = sectorMaxHit; + } + + /** + * Compute the cluster properties. + * + * Cluster coordinates and time are defined as the coordinates and time of + * the max energy hit. + * + * TO DO: Test other choices for the definitions. + * + */ + public final void computeClusterProperties() { + this.energy = 0; + double max_energy = -1; + RTOFRawHit max_energy_hit = new RTOFRawHit(); + + for (int i_bar = 0; i_bar < this.rtofHits.size(); i_bar++) { + RTOFHit this_rtof_hit = this.rtofHits.get(i_bar); + double this_energy = this_rtof_hit.getEnergy(); + this.energy += this_energy; + if (this_energy > max_energy) { + max_energy_hit = this_rtof_hit; + max_energy = this_energy; + } + } + + this.time = max_energy_hit.getTime(); + this.x = max_energy_hit.getX(); + this.y = max_energy_hit.getY(); + this.z = max_energy_hit.getZ(); + this.typeMaxHit = max_energy_hit.getType(); + this.sectorMaxHit = max_energy_hit.getSector(); + } + + + /** + * Computes the energy deposited in the bars. + * + * @return the energy deposited in the bars. + * + */ + public double getEdepBar() { + double energy = 0; + for (int i = 0; i < this.rtofHits.size(); i++) { + RTOFRawHit this_hit = this.rtofHits.get(i); + energy += this_hit.getEnergy(); + } + return energy; + } + + /** + * Compute the cluster phi angle in radians. + * + * @return a double that is angle in radians + * + */ + public double getPhi() { + return Math.atan2(this.y, this.x); + } + + + /** + * Retrieve the hit with maximal energy in the cluster. It must have been + * computed previously. + * + * @return a RTOFRawHit that is the maximal energy hit in the cluster + * + */ + public final RTOFRawHit getMaxHit() { + if (this.typeMaxHit == null) { + System.out.print("You did not compute the maximal hit! \n"); + return null; + } + if (null == this.typeMaxHit) { + System.out.print("Unrecognized type! \n"); + return null; + } else { + switch (this.typeMaxHit) { + case "bar" -> { + return this.rtofHits.get(this.indexMaxHit); + } + default -> { + System.out.print("Unrecognized type! \n"); + return null; + } + } + } + } + + /** + * Computes the sum of TOT in the cluster. + * + * @return an int representing the summed TOT + * + */ + public int getTot() { + int tot = 0; + for (int i = 0; i < this.rtofHits.size(); i++) { + RTOFHit this_hit = this.rtofHits.get(i); + tot += this_hit.getTot(); + } + return tot; + } + + /** + * Returns the TDC of the maximal hit in the cluster. + * + * @return an int representing the TDC of the maximal hit. + * + */ + public int getTdc() { + return this.getMaxHit().getTdc(); + } + + /** + * Constructor that initializes the list of bar hits + * and computes the cluster properties. + * + * @param rtof_hits a {@link ArrayList} of {@link RTOFHit}. + * + */ + public RTOFCluster(ArrayList rtof_hits) { + this.rtofHits = rtof_hits; + this.computeClusterProperties(); + } + + /** + * Constructor that initializes the list of bar hits + * and computes the cluster properties. + * + * @param rtof_hits a {@link ArrayList} of {@link RTOFHit}. + * @param event a {@link DataEvent} with which track matching will be done. + * + */ + public RTOFCluster(ArrayList rtof_hits, DataEvent event) { + this.rtofHits = rtof_hits; + this.computeClusterProperties(); + } + +} diff --git a/reconstruction/recoil/src/main/java/org/jlab/service/recoil/tof/RTOFEngine.java b/reconstruction/recoil/src/main/java/org/jlab/service/recoil/tof/RTOFEngine.java new file mode 100644 index 0000000000..0bde218987 --- /dev/null +++ b/reconstruction/recoil/src/main/java/org/jlab/service/recoil/tof/RTOFEngine.java @@ -0,0 +1,82 @@ +package org.jlab.service.recoil.tof; + +import java.util.ArrayList; + +import org.jlab.clas.reco.ReconstructionEngine; +import org.jlab.io.base.DataBank; +import org.jlab.io.base.DataEvent; + +import java.util.concurrent.atomic.AtomicInteger; +import org.jlab.detector.calib.utils.DatabaseConstantProvider; +import org.jlab.io.hipo.HipoDataSource; +import org.jlab.service.recoil.tof.RecoBankWriter; +import org.jlab.service.recoil.tof.RTOFCluster; +import org.jlab.service.recoil.tof.ClusterFinder; +import org.jlab.service.recoil.tof.RTOFRawHit; +import org.jlab.service.recoil.tof.RTOFHit; +import org.jlab.service.recoil.tof.HitFinder; + +/** + * Service to return reconstructed RTOF hits and clusters + * + * @author npilleux, Nilanga Wickramaarachchi + * + */ +public class RTOFEngine extends ReconstructionEngine { + + public RTOFEngine() { + super("RTOF", "Nilanga Wickramaarachchi", "1.0"); + } + + RecoBankWriter rbc; + + private final AtomicInteger run = new AtomicInteger(0); + + @Override + public boolean processDataEventUser(DataEvent event) { + + if (!event.hasBank("RUN::config")) { + return true; + } + + + //Hit finder init + HitFinder hitfinder = new HitFinder(); + hitfinder.findHits(event); + + ArrayList RTOFHits = hitfinder.getRTOFHits(); + + //Exit if hit list is empty + if (RTOFHits.isEmpty()) { + // System.out.println("No hits : "); + // event.show(); + return true; + } + + ClusterFinder clusterFinder = new ClusterFinder(); + clusterFinder.makeClusters(event,hitfinder); + ArrayList Clusters = clusterFinder.getClusters(); + + if (RTOFHits.size() != 0) { + rbc.appendRTOFBanks(event, RTOFHits, Clusters); + } + return true; + } + + @Override + public boolean init() { + rbc = new RecoBankWriter(); + + this.registerOutputBank("RTOF::hits", "RTOF::clusters"); + + return true; + } + + public static void main(String arg[]) { + } + + @Override + public void detectorChanged(int run) {} + +} + diff --git a/reconstruction/recoil/src/main/java/org/jlab/service/recoil/tof/RTOFHit.java b/reconstruction/recoil/src/main/java/org/jlab/service/recoil/tof/RTOFHit.java new file mode 100644 index 0000000000..87330bc1ce --- /dev/null +++ b/reconstruction/recoil/src/main/java/org/jlab/service/recoil/tof/RTOFHit.java @@ -0,0 +1,140 @@ +package org.jlab.service.recoil.tof; + +import org.jlab.detector.geant4.v2.recoil.tof.RTOFConstants; + +/** + * + * Represents a hit in the recoil tof bar. Extends class RTOFRawHit. Is further defined + * by the two hits upstream and downstream composing a full rtof hit. y position, + * time and energy are defined from the up/down hits. + * + * @author npilleux, Nilanga Wickramaarachchi + */ +public class RTOFHit extends RTOFRawHit { + + //A rtof hit is the combination of a downstream and upstream hits + private RTOFRawHit hitUp, hitDown; + + public RTOFRawHit getHitUp() { + return hitUp; + } + + public void setHitUp(RTOFRawHit hit_up) { + this.hitUp = hit_up; + } + + public RTOFRawHit getHitDown() { + return hitDown; + } + + public void setHitDown(RTOFRawHit hit_down) { + this.hitDown = hit_down; + } + + /** + * Computes rtof hit y local coordinate from up/downstream hit times. + * + */ + public final void computeLocalY() { + this.setLocalY(Parameters.VEFF/2. * (hitUp.getTime() - hitDown.getTime())); + } + + /** + * Computes rtof hit y coordinate in the global coordinate system. + * + */ + public final void computeGlobalY() { + double localY = this.getLocalY(); + int nRows = RTOFConstants.NROWS; + double y_start = -(RTOFConstants.LENGTH - RTOFConstants.LONG_BAR_LENGTH)/2; // Starting Y position + double dy_long = RTOFConstants.LONG_BAR_LENGTH; + double dy_short = RTOFConstants.SHORT_BAR_LENGTH; + + double y_pos; // y coordinate of the center of bar wrt to the global coordinate system + if(hitUp.getRow()-1 < (nRows - 1)/2) + { + y_pos = y_start + ((hitUp.getRow()-1) * dy_long); + } + else if (hitUp.getRow()-1 == (nRows-1) / 2) // middle row + { + y_pos = 0; + } + else + { + y_pos = y_start + (hitUp.getRow()-2) * dy_long + dy_short; + } + + this.setY(y_pos + localY); + } + + /** + * Computes rtof hit time from up/downstream hit times. + * The time is set as the time of the most energetic hit. + * It is corrected for propagation time. + * + */ + public final void computeTime() { + //We pick the most energetic signal as the timing signal + double time_at_sipm, distance_to_sipm; + if(this.hitDown.getEnergy() > this.hitUp.getEnergy()) { + time_at_sipm = this.hitDown.getTime(); + if(this.hitDown.getRow() == 3) distance_to_sipm = RTOFConstants.SHORT_BAR_LENGTH/2. - this.getLocalY(); + else distance_to_sipm = RTOFConstants.LONG_BAR_LENGTH/2. - this.getLocalY(); + } + else { + time_at_sipm = this.hitUp.getTime(); + if(this.hitUp.getRow() == 3) distance_to_sipm = RTOFConstants.SHORT_BAR_LENGTH/2. + this.getLocalY(); + else distance_to_sipm = RTOFConstants.LONG_BAR_LENGTH/2. + this.getLocalY(); + } + this.setTime(time_at_sipm - distance_to_sipm/Parameters.VEFF); + } + + /** + * Computes rtof hit energy from up/downstream hits. + * The energy of the up/downstream hits is corrected for attenuation now that y is known. + * The energy of the rtof hit is the sum of the energy of the up/downstream hits. + * + */ + public final void computeEnergy() { + this.computeLocalY(); + double distance_hit_to_sipm_up, distance_hit_to_sipm_down; + + if (hitUp.getRow() == 3) distance_hit_to_sipm_up = RTOFConstants.SHORT_BAR_LENGTH / 2. + this.getLocalY(); + else distance_hit_to_sipm_up = RTOFConstants.LONG_BAR_LENGTH / 2. + this.getLocalY(); + + if (hitDown.getRow() == 3) distance_hit_to_sipm_down = RTOFConstants.SHORT_BAR_LENGTH / 2. - this.getLocalY(); + else distance_hit_to_sipm_down = RTOFConstants.LONG_BAR_LENGTH / 2. - this.getLocalY(); + + double Edep_up = hitUp.getEnergy() * Math.exp(distance_hit_to_sipm_up / Parameters.ATT_L); + double Edep_down = hitDown.getEnergy() * Math.exp(distance_hit_to_sipm_down / Parameters.ATT_L); + this.setEnergy(Edep_up + Edep_down); + } + + public RTOFHit(RTOFRawHit hit_down, RTOFRawHit hit_up) { + boolean hits_match = hit_down.matchBar(hit_up); + if (!hits_match) { + throw new UnsupportedOperationException("Hits do not match \n"); + } + this.setType("bar"); + this.setOrder(2);//Fake order for bar hits + this.hitUp = hit_up; + this.hitDown = hit_down; + this.setSector(hit_up.getSector()); + this.setRow(hit_up.getRow()); + this.setColumn(hit_up.getColumn()); + this.setX(hit_up.getX()); + this.setZ(hit_up.getZ()); + this.computeLocalY(); + this.computeGlobalY(); + this.computeTime(); + this.computeEnergy(); + this.setTdc((hit_down.getTdc() + hit_up.getTdc())/2); + this.setTot((hit_down.getTot() + hit_up.getTot())); + } + + public RTOFHit() { + super(); + this.setType("bar"); + this.setOrder(2);//Fake order for rtof hits + } +} diff --git a/reconstruction/recoil/src/main/java/org/jlab/service/recoil/tof/RTOFRawHit.java b/reconstruction/recoil/src/main/java/org/jlab/service/recoil/tof/RTOFRawHit.java new file mode 100644 index 0000000000..3feabdc5ac --- /dev/null +++ b/reconstruction/recoil/src/main/java/org/jlab/service/recoil/tof/RTOFRawHit.java @@ -0,0 +1,398 @@ +package org.jlab.service.recoil.tof; + +import org.jlab.detector.geant4.v2.recoil.tof.RTOFConstants; + +/** + * + * Represents a hit in the recoil tof. Stores info about the sector, row, column, + * order, TDC, ToT. Type is bar up/bar down/ bar. Stores whether + * the hit is part of a cluster. Calculates time, energy based on TDC/ToT. + * + * @author npilleux, Nilanga Wickramaarachchi + */ +public class RTOFRawHit { + + private int sector, row, column, order; + private int tdc, tot; + private double time, energy, x, y, z, local_y; + private String type; + private boolean isInACluster; + private int associatedClusterIndex; + int idTDC; + + /** + * Constructor for a hit in the recoil tof. Initializes the hit's sector, row, + * column, order, TDC, ToT. Sets the hit's initial state regarding + * clustering. Set up the hit's type, time, energy, and spatial coordinates. + * + * @param sector The sector of the detector where the hit occurred. + * @param row The row of the detector where the hit was detected. + * @param column The column within the row that registered the hit. + * @param order Order of the hit. + * @param tdc TDC value. + * @param tot ToT value. + * + */ + public RTOFRawHit(int sector, int row, int column, int order, int tdc, int tot) { + this.sector = sector; + this.row = row; + this.column = column; + this.order = order; + this.tdc = tdc; + this.tot = tot; + this.isInACluster = false; + + this.makeType(); + this.convertTdcToTime(); + this.convertTotToEnergy(); + this.calculateXYZ(); + } + + public RTOFRawHit() { + } + + public int getSector() { + return sector; + } + + public void setSector(int sector) { + this.sector = sector; + } + + public int getRow() { + return row; + } + + public void setRow(int row) { + this.row = row; + } + + public int getOrder() { + return order; + } + + public void setOrder(int order) { + this.order = order; + } + + public int getColumn() { + return column; + } + + public void setColumn(int column) { + this.column = column; + } + + public int getTdc() { + return tdc; + } + + public void setTdc(int tdc) { + this.tdc = tdc; + } + + public int getTot() { + return tot; + } + + public void setTot(int tot) { + this.tot = tot; + } + + public double getTime() { + return time; + } + + public void setTime(double time) { + this.time = time; + } + + public double getEnergy() { + return energy; + } + + public void setEnergy(double energy) { + this.energy = energy; + } + + public double getX() { + return x; + } + + public void setX(double x) { + this.x = x; + } + + public double getY() { + return y; + } + + public void setY(double y) { + this.y = y; + } + + public double getLocalY() { + return local_y; + } + + public void setLocalY(double local_y) { + this.local_y = local_y; + } + + public double getZ() { + return z; + } + + public void setZ(double z) { + this.z = z; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public boolean getIsInACluster() { + return isInACluster; + } + + public void setIsInACluster(boolean is_in_a_cluster) { + this.isInACluster = is_in_a_cluster; + } + + public int getAssociatedClusterIndex() { + return associatedClusterIndex; + } + + public void setAssociatedClusterIndex(int index) { + this.associatedClusterIndex = index; + } + + public int getIdTDC() { + return idTDC; + } + + public void setIdTDC(int index) { + this.idTDC = index; + } + + + /** + * Assigns a type to the hit. + * + */ + public final String makeType() { + //Type of hit can be bar up, bar down or bar. + //Avoids testing components and order every time. + String itype = "undefined"; + if (this.order == 0) { + itype = "bar down"; + } else if (this.order == 1) { + itype = "bar up"; + } + this.type = itype; + return itype; + } + + /** + * Converts TDC to time (ns). Sets the hit time parameter to a raw time for + * up/down bar hits. + * + * @return 0 if the time was successfully set, or 1 if the hit type is + * unsupported. + */ + public final int convertTdcToTime() { + double tdc2time, veff, distance_to_sipm; + if (null == this.type) { + System.out.print("Null hit type, cannot convert tdc to time."); + return 1; + } else { + switch (this.type) { + case "bar up" -> { + tdc2time = Parameters.TDC2TIME; + veff = Parameters.VEFF; + //The distance will be computed at barhit level when y information is available + distance_to_sipm = 0; + } + case "bar down" -> { + tdc2time = Parameters.TDC2TIME; + veff = Parameters.VEFF; + //The distance will be computed at barhit level when y information is available + distance_to_sipm = 0; + } + case "bar" -> { + System.out.print("Bar hit type, cannot convert tdc to time."); + return 1; + } + default -> { + System.out.print("Undefined hit type, cannot convert tdc to time."); + return 1; + } + } + } + //Hit time. Will need implementation of offsets. + this.time = tdc2time * this.tdc - distance_to_sipm / veff; + return 0; + } + + /** + * Converts ToT to energy (MeV). Sets the hit energy parameter to a raw + * energy for up/down bar hits. + * + * @return 0 if the energy was successfully set, or 1 if the hit type is + * unsupported. + */ + public final int convertTotToEnergy() { + double tot2energy; + if (null == this.type) { + System.out.print("Null hit type, cannot convert tot to energy."); + return 1; + } else { + switch (this.type) { + case "bar up" -> { + tot2energy = Parameters.TOT2ENERGY; + //only half the information in the bar, + //the attenuation will be computed when the full hit is formed + this.energy = tot2energy * this.tot; + } + case "bar down" -> { + tot2energy = Parameters.TOT2ENERGY; + //only half the information in the bar, + //the attenuation will be computed when the full hit is formed + this.energy = tot2energy * this.tot; + } + case "bar" -> { + System.out.print("Bar hit type, cannot convert tot to energy."); + return 1; + } + default -> { + System.out.print("Undefined hit type, cannot convert tot to energy."); + return 1; + } + } + } + return 0; + } + + /** + * Calculates spatial coordinates (cm) for the hit based on row and column number of the bar within a sector. + * The row and column variables are obtained from the bank information. + * + * @return 0 if the coordinates were successfully set, or 1 if the hit type + * is undefined or unsupported. + */ + public final int calculateXYZ() { + + // Constants for positioning + int nRows = RTOFConstants.NROWS; + double y_start = -(RTOFConstants.LENGTH - RTOFConstants.LONG_BAR_LENGTH)/2; // Starting Y position + double x_spacing = RTOFConstants.BAR_WIDTH; + double x_start = -(RTOFConstants.WIDTH - x_spacing)/2; // starting X position + double dy_long = RTOFConstants.LONG_BAR_LENGTH; + double dy_short = RTOFConstants.SHORT_BAR_LENGTH; + + //Position calculation + double z_pos = 0; + double x_pos = x_start + ((this.column-1) * x_spacing); + + double y_pos; + if(this.row-1 < (nRows - 1) / 2) + { + y_pos = y_start + ((this.row-1) * dy_long); + } + else if (this.row-1 == (nRows - 1) / 2) // middle row + { + y_pos = 0; + } + else + { + y_pos = y_start + (this.row -2) * dy_long + dy_short; + } + + double[] localCoords = {x_pos, y_pos, z_pos}; + + // Calculate center coordinates for the sector + double sector_x = (-1+(this.sector-1)*2)*(RTOFConstants.RADIUS)*Math.sin(Math.toRadians(RTOFConstants.HORIZONTAL_OPENING_ANGLE/2+RTOFConstants.HORIZONTAL_STARTING_ANGLE)); + double sector_y = 0; + double sector_z = RTOFConstants.RADIUS*Math.cos(Math.toRadians(RTOFConstants.HORIZONTAL_OPENING_ANGLE/2+RTOFConstants.HORIZONTAL_STARTING_ANGLE)); + + // Global coordinates of the sector + double[] globalCoordsSector = {sector_x, sector_y, sector_z}; + + // Rotation angle in radians + double thetaY = 0; + + if(this.sector==1) thetaY = Math.toRadians(-(RTOFConstants.HORIZONTAL_OPENING_ANGLE/2+RTOFConstants.HORIZONTAL_STARTING_ANGLE)); + if(this.sector==2) thetaY = Math.toRadians(RTOFConstants.HORIZONTAL_OPENING_ANGLE/2+RTOFConstants.HORIZONTAL_STARTING_ANGLE); + + // Rotation matrix around the Y-axis + double[][] Ry = { + {Math.cos(thetaY), 0, Math.sin(thetaY)}, + {0, 1, 0}, + {-Math.sin(thetaY), 0, Math.cos(thetaY)} + }; + + // Rotate local coordinates + double[] rotatedCoords = new double[3]; + for (int i = 0; i < 3; i++) { + rotatedCoords[i] = Ry[i][0] * localCoords[0] + Ry[i][1] * localCoords[1] + Ry[i][2] * localCoords[2]; + } + + // Calculate global coordinates for the hit + double[] globalCoordsBar = new double[3]; + for (int i = 0; i < 3; i++) { + globalCoordsBar[i] = globalCoordsSector[i] + rotatedCoords[i]; + } + + + this.x = globalCoordsBar[0]; + this.y = globalCoordsBar[1]; + this.z = globalCoordsBar[2]; + return 0; + } + + /** + * Compares two RTOFRawHit objects to check if they match in the bar. + *
    + *
  • If the sector or row or column of the two hits do not match, the method + * returns {@code false}.
  • + *
  • If both hits are in the same SiPM (i.e., their order is the same), or + * have incorrect order, the method returns {@code false}.
  • + *
+ * If none of these conditions are violated, the method returns + * {@code true}, indicating the two hits match. + * + * @param hit2match The RTOFRawHit object to compare with the current instance. + * @return {@code true} if the hits match; {@code false} otherwise. + */ + public boolean matchBar(RTOFRawHit hit2match) { + if (this.getSector() != hit2match.getSector()) { + //Two hits in different sectors + return false; + } else if (this.getRow() != hit2match.getRow()) { + //Two hits in different rows + return false; + } else if (this.getColumn() != hit2match.getColumn()) { + //Two hits in different columns + return false; + } else if (this.getOrder() > 1 || hit2match.getOrder() > 1) { + //At least one hit has incorrect order + return false; + } else { + //Match if one is order 0 and the other is order 1 + return this.getOrder() != hit2match.getOrder(); + } + } + + /** + * Computes the azimuthal angle (phi) of the hit in rad. + * + * @return The azimuthal angle (phi) in radians, in the range [-π, π]. + */ + public double getPhi() { + return Math.atan2(this.y, this.x); + } +} diff --git a/reconstruction/recoil/src/main/java/org/jlab/service/recoil/tof/RecoBankWriter.java b/reconstruction/recoil/src/main/java/org/jlab/service/recoil/tof/RecoBankWriter.java new file mode 100644 index 0000000000..1383871435 --- /dev/null +++ b/reconstruction/recoil/src/main/java/org/jlab/service/recoil/tof/RecoBankWriter.java @@ -0,0 +1,115 @@ +package org.jlab.service.recoil.tof; + +import java.util.ArrayList; +import org.jlab.io.base.DataBank; +import org.jlab.io.base.DataEvent; + +/** + * The {@code RecoBankWriter} writes the banks needed for the recoil tof + * reconstruction: hits and clusters info. + * + * @author pilleux, Nilanga Wickramaarachchi + */ +public class RecoBankWriter { + + /** + * Writes the bank of recoil tof hits. + * + * @param event the {@link DataEvent} in which to add the bank + * @param rtofHits the {@link ArrayList} of {@link RTOFHit} containing the rtof + * hits to be added to the bank + * + * @return {@link DataBank} the bank with all the hits read in the event. + * + */ + public static DataBank fillRTOFRawHitBank(DataEvent event, ArrayList rtofHits) { + + ArrayList hitList = new ArrayList<>(); + hitList.addAll(rtofHits); + + DataBank bank = event.createBank("RTOF::hits", hitList.size()); + + if (bank == null) { + System.err.println("COULD NOT CREATE A RTOF::hits BANK!!!!!!"); + return null; + } + + for (int i = 0; i < hitList.size(); i++) { + bank.setShort("id", i, (short) (i + 1)); + bank.setShort("clusterid", i, (short) hitList.get(i).getAssociatedClusterIndex()); + bank.setByte("sector", i, (byte) hitList.get(i).getSector()); + bank.setByte("layer", i, (byte) hitList.get(i).getRow()); + bank.setByte("component", i, (byte) hitList.get(i).getColumn()); + bank.setFloat("time", i, (float) hitList.get(i).getTime()); + bank.setFloat("x", i, (float) (hitList.get(i).getX())); + bank.setFloat("y", i, (float) (hitList.get(i).getY())); + bank.setFloat("z", i, (float) (hitList.get(i).getZ())); + bank.setFloat("energy", i, (float) hitList.get(i).getEnergy()); + } + return bank; + } + + /** + * Writes the bank of rtof clusters. + * + * @param event the {@link DataEvent} in which to add the bank + * @param clusterList the {@link ArrayList} of {@link RTOFCluster} + * containing the clusters info to be added to the bank + * + * @return {@link DataBank} the bank with all the clusters built in the + * event. + * + */ + public static DataBank fillRTOFClusterBank(DataEvent event, ArrayList clusterList) { + + DataBank bank = event.createBank("RTOF::clusters", clusterList.size()); + + if (bank == null) { + System.err.println("COULD NOT CREATE A RTOF::clusters BANK!!!!!!"); + return null; + } + + for (int i = 0; i < clusterList.size(); i++) { + bank.setShort("id", i, (short) (i + 1)); + bank.setShort("size", i, (short) clusterList.get(i).getRTOFHits().size()); + bank.setByte("sector", i, (byte) clusterList.get(i).getSectorMaxHit()); + bank.setFloat("time", i, (float) clusterList.get(i).getTime()); + bank.setFloat("x", i, (float) (clusterList.get(i).getX())); + bank.setFloat("y", i, (float) (clusterList.get(i).getY())); + bank.setFloat("z", i, (float) (clusterList.get(i).getZ())); + bank.setFloat("energy", i, (float) clusterList.get(i).getEnergy()); + } + return bank; + } + + /** + * Appends the rtof banks to an event. + * + * @param event the {@link DataEvent} in which to append the banks + * @param clusterList the {@link ArrayList} of {@link RTOFCluster} + * containing the clusters info to be added to the bank + * @param rtofHits the {@link ArrayList} of {@link RTOFHit} containing the bar + * hits info to be added + * + * @return 0 if it worked, 1 if it failed + * + */ + public int appendRTOFBanks(DataEvent event, ArrayList rtofHits, ArrayList clusterList) { + + DataBank hitbank = this.fillRTOFRawHitBank(event, rtofHits); + if (hitbank != null) { + event.appendBank(hitbank); + } else { + return 1; + } + + DataBank clusterbank = fillRTOFClusterBank(event, clusterList); + if (clusterbank != null) { + event.appendBank(clusterbank); + } else { + return 1; + } + + return 0; + } +} diff --git a/reconstruction/recoil/src/main/java/org/jlab/service/recoil/RecoilCluster.java b/reconstruction/recoil/src/main/java/org/jlab/service/recoil/trk/RTRKCluster.java similarity index 72% rename from reconstruction/recoil/src/main/java/org/jlab/service/recoil/RecoilCluster.java rename to reconstruction/recoil/src/main/java/org/jlab/service/recoil/trk/RTRKCluster.java index 66a6a5d914..c8c2ac152f 100644 --- a/reconstruction/recoil/src/main/java/org/jlab/service/recoil/RecoilCluster.java +++ b/reconstruction/recoil/src/main/java/org/jlab/service/recoil/trk/RTRKCluster.java @@ -1,7 +1,8 @@ -package org.jlab.service.recoil; +package org.jlab.service.recoil.trk; import java.util.ArrayList; import java.util.List; +import org.jlab.detector.geant4.v2.recoil.trk.RTRKConstants; import org.jlab.detector.base.DetectorDescriptor; import org.jlab.detector.base.DetectorType; import org.jlab.geom.prim.Line3D; @@ -9,21 +10,21 @@ /** * recoil in-layer cluster - * + * * @author bondi, devita, niccolai */ -public class RecoilCluster extends ArrayList { - +public class RTRKCluster extends ArrayList { - private DetectorDescriptor desc = new DetectorDescriptor(DetectorType.RECOIL); - private int id; + + private DetectorDescriptor desc = new DetectorDescriptor(DetectorType.RTRK); + private int id; private Line3D clusterLine = new Line3D(); public int indexMaxStrip = -1; private byte clusterStatus = 1; - public RecoilCluster(RecoilStrip strip){ - this.desc.setSectorLayerComponent(strip.getDescriptor().getSector(), - strip.getDescriptor().getLayer(), 0); + public RTRKCluster(RTRKStrip strip){ + this.desc.setSectorLayerComponent(strip.getDescriptor().getSector(), + strip.getDescriptor().getLayer(), 0); this.add(strip); this.clusterLine.copy(strip.getLine()); this.indexMaxStrip = 0; @@ -49,11 +50,11 @@ public int getChamber() { return this.get(0).getChamber(); } - public Line3D getLine() {return this.clusterLine;} + public Line3D getLine() {return this.clusterLine;} public double getEnergy(){ double energy = 0.0; - for(RecoilStrip strip : this){ + for(RTRKStrip strip : this){ energy += strip.getEnergy(); } return energy; @@ -61,7 +62,7 @@ public double getEnergy(){ public double getTime(){ double time = 0.0; - for(RecoilStrip strip : this){ + for(RTRKStrip strip : this){ time += strip.getTime()*strip.getEnergy(); } time /= this.getEnergy(); @@ -72,19 +73,19 @@ public double getSeedTime(){ if(this.indexMaxStrip >= 0 && this.indexMaxStrip < this.size()){ return this.get(indexMaxStrip).getTime(); } - return 0.0; + return 0.0; } - - public RecoilStrip getSeedStrip() { - return this.get(this.indexMaxStrip); + + public RTRKStrip getSeedStrip() { + return this.get(this.indexMaxStrip); } public int getMaxStrip(){ return this.get(this.indexMaxStrip).getDescriptor().getComponent(); } - public boolean addStrip(RecoilStrip strip){ - for(RecoilStrip s : this){ + public boolean addStrip(RTRKStrip strip){ + for(RTRKStrip s : this){ if(s.isNeighbour(strip)){ this.add(strip); if(strip.getEnergy()>this.get(indexMaxStrip).getEnergy()){ @@ -99,7 +100,7 @@ public boolean addStrip(RecoilStrip strip){ public int getADC(){ int adc = 0; - for(RecoilStrip s : this){ + for(RTRKStrip s : this){ adc+= s.getADC(); } return adc; @@ -107,15 +108,15 @@ public int getADC(){ public void setStatus(int val) {this.clusterStatus+=val;} - public byte getStatus() {return clusterStatus;} + public byte getStatus() {return clusterStatus;} public void setClusterId(int id){ this.id = id; - for(RecoilStrip strip : this){ + for(RTRKStrip strip : this){ strip.setClusterId(id); } } - + public void redoClusterLine(){ Point3D pointOrigin = new Point3D(0.0,0.0,0.0); @@ -138,37 +139,36 @@ public void redoClusterLine(){ pointEnd.setX(pointEnd.x()+line.end().x()*le); pointEnd.setY(pointEnd.y()+line.end().y()*le); pointEnd.setZ(pointEnd.z()+line.end().z()*le); - + logSumm += le; summE += energy; } - + this.clusterLine.set( - pointOrigin.x()/logSumm, - pointOrigin.y()/logSumm, - pointOrigin.z()/logSumm, - pointEnd.x()/logSumm, - pointEnd.y()/logSumm, - pointEnd.z()/logSumm + pointOrigin.x()/logSumm, + pointOrigin.y()/logSumm, + pointOrigin.z()/logSumm, + pointEnd.x()/logSumm, + pointEnd.y()/logSumm, + pointEnd.z()/logSumm ); } - - public static List createClusters(List stripList){ - - List clusterList = new ArrayList<>(); + public static List createClusters(List stripList){ + + List clusterList = new ArrayList<>(); if(!stripList.isEmpty()){ - for(int loop = 0; loop < stripList.size(); loop++){ //Loop over all strips - boolean stripAdded = false; - for(RecoilCluster cluster : clusterList) { + for(int loop = 0; loop < stripList.size(); loop++){ //Loop over all strips + boolean stripAdded = false; + for(RTRKCluster cluster : clusterList) { if(cluster.addStrip(stripList.get(loop))){ //Add adjacent strip to newly seeded peak stripAdded = true; } } if(!stripAdded){ - RecoilCluster newPeak = new RecoilCluster(stripList.get(loop)); //Non-adjacent strip seeds new peak + RTRKCluster newPeak = new RTRKCluster(stripList.get(loop)); //Non-adjacent strip seeds new peak clusterList.add(newPeak); } } @@ -178,11 +178,11 @@ public static List createClusters(List stripList){ clusterList.get(loop).redoClusterLine(); } return clusterList; - } + } - public static List getClusters(List clusters, int sector, int layer) { - List selectedClusters = new ArrayList<>(); - for(RecoilCluster cluster : clusters) { + public static List getClusters(List clusters, int sector, int layer) { + List selectedClusters = new ArrayList<>(); + for(RTRKCluster cluster : clusters) { if(cluster.getSector()==sector && cluster.getLayer()==layer) selectedClusters.add(cluster); } @@ -192,11 +192,11 @@ public static List getClusters(List clusters, int @Override public String toString(){ StringBuilder str = new StringBuilder(); - str.append(String.format("----> cluster ( %3d %3d ) ENERGY = %12.5f\n", - this.desc.getSector(),this.desc.getLayer(), this.getEnergy())); + str.append(String.format("----> cluster ( %3d %3d ) ENERGY = %12.5f\n", + this.desc.getSector(),this.desc.getLayer(), this.getEnergy())); str.append(this.clusterLine.toString()); str.append("\n"); - for(RecoilStrip strip : this){ + for(RTRKStrip strip : this){ str.append("\t\t"); str.append(strip.toString()); str.append("\n"); @@ -204,9 +204,5 @@ public String toString(){ return str.toString(); } - - - - } diff --git a/reconstruction/recoil/src/main/java/org/jlab/service/recoil/RecoilCross.java b/reconstruction/recoil/src/main/java/org/jlab/service/recoil/trk/RTRKCross.java similarity index 68% rename from reconstruction/recoil/src/main/java/org/jlab/service/recoil/RecoilCross.java rename to reconstruction/recoil/src/main/java/org/jlab/service/recoil/trk/RTRKCross.java index a2a2ba85e5..4ff69ec157 100644 --- a/reconstruction/recoil/src/main/java/org/jlab/service/recoil/RecoilCross.java +++ b/reconstruction/recoil/src/main/java/org/jlab/service/recoil/trk/RTRKCross.java @@ -1,7 +1,8 @@ -package org.jlab.service.recoil; +package org.jlab.service.recoil.trk; import java.util.ArrayList; import java.util.List; +import org.jlab.detector.geant4.v2.recoil.trk.RTRKConstants; import org.jlab.geom.prim.Plane3D; import org.jlab.geom.prim.Point3D; import org.jlab.geom.prim.Vector3D; @@ -10,8 +11,8 @@ * recoil V-W clusters * @author devita, niccolai */ -public class RecoilCross { - +public class RTRKCross { + private int id; private int sector; @@ -26,17 +27,15 @@ public class RecoilCross { private double time; private int status; - - - public RecoilCross(RecoilCluster c1, RecoilCluster c2) { + public RTRKCross(RTRKCluster c1, RTRKCluster c2) { - Vector3D dir = c1.getLine().direction().cross(c2.getLine().direction()); + Vector3D dir = c1.getLine().direction().cross(c2.getLine().direction()); Plane3D plane = new Plane3D(c1.getLine().origin(), c1.getLine().direction().cross(dir)); Point3D point = new Point3D(); int nint = plane.intersectionSegment(c2.getLine(), point); if(nint==1) { this.sector = c1.getSector(); - this.region = (c1.getLayer()-1)/(RecoilConstants.NLAYER/RecoilConstants.NREGION)+1; + this.region = (c1.getLayer()-1)/(RTRKConstants.NLAYERS/RTRKConstants.NREGIONS)+1; this.cross = point; this.energy = c1.getEnergy() + c2.getEnergy(); this.time = (c1.getTime() + c2.getTime())/2; @@ -44,11 +43,11 @@ public RecoilCross(RecoilCluster c1, RecoilCluster c2) { this.cluster2 = c2.getId(); } } - + public void setId(int id) { this.id = id; } - + public int getId() { return id; } @@ -68,19 +67,19 @@ public int getChamber() { public int getCluster1() { return cluster1; } - + public int getCluster2() { return cluster2; } - + public Point3D point() { return cross; - } - + } + public double getEnergy() { return energy; } - + public double getTime() { return time; } @@ -88,21 +87,21 @@ public double getTime() { 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 = RecoilCluster.getClusters(clusters, is+1, (RecoilConstants.NLAYER/RecoilConstants.NREGION)*ir+1); - List clustersW = RecoilCluster.getClusters(clusters, is+1, (RecoilConstants.NLAYER/RecoilConstants.NREGION)*ir+2); + for(int is=0; is clustersV = RTRKCluster.getClusters(clusters, is+1, (RTRKConstants.NLAYERS/RTRKConstants.NREGIONS)*ir+1); + List clustersW = RTRKCluster.getClusters(clusters, is+1, (RTRKConstants.NLAYERS/RTRKConstants.NREGIONS)*ir+2); - for(RecoilCluster v : clustersV) { - for(RecoilCluster w : clustersW) { + for(RTRKCluster v : clustersV) { + for(RTRKCluster w : clustersW) { if(v.getChamber()==w.getChamber()) { - RecoilCross cross = new RecoilCross(v, w); + RTRKCross cross = new RTRKCross(v, w); if(cross.point()!=null) crosses.add(cross); cross.setId(crosses.size()); } diff --git a/reconstruction/recoil/src/main/java/org/jlab/service/recoil/RecoilEngine.java b/reconstruction/recoil/src/main/java/org/jlab/service/recoil/trk/RTRKEngine.java similarity index 76% rename from reconstruction/recoil/src/main/java/org/jlab/service/recoil/RecoilEngine.java rename to reconstruction/recoil/src/main/java/org/jlab/service/recoil/trk/RTRKEngine.java index bbb1bc8bfc..e8263b3533 100644 --- a/reconstruction/recoil/src/main/java/org/jlab/service/recoil/RecoilEngine.java +++ b/reconstruction/recoil/src/main/java/org/jlab/service/recoil/trk/RTRKEngine.java @@ -1,4 +1,4 @@ -package org.jlab.service.recoil; +package org.jlab.service.recoil.trk; import java.util.List; import java.util.Optional; @@ -8,7 +8,8 @@ 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.recoil.RecoilStripFactory; +import org.jlab.detector.geant4.v2.recoil.trk.RTRKConstants; +import org.jlab.detector.geant4.v2.recoil.trk.RTRKStripFactory; import org.jlab.geom.prim.Point3D; import org.jlab.groot.data.H1F; import org.jlab.groot.fitter.DataFitter; @@ -22,69 +23,65 @@ /** * * recoil reconstruction engine - * + * * @author bondi, devita, niccolai */ -public class RecoilEngine extends ReconstructionEngine { - - public static Logger LOGGER = Logger.getLogger(RecoilEngine.class.getName()); - - public static RecoilStripFactory factory = new RecoilStripFactory(); - - public RecoilEngine() { - super("Recoil","niccolai","1.0"); +public class RTRKEngine extends ReconstructionEngine { + + public static Logger LOGGER = Logger.getLogger(RTRKEngine.class.getName()); + + public static RTRKStripFactory factory = new RTRKStripFactory(); + + public RTRKEngine() { + super("RTRK","niccolai","1.0"); } - + @Override 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, RecoilConstants.NREGION); - // register output banks for drop option - this.registerOutputBank("RECOIL::hits"); - this.registerOutputBank("RECOIL::clusters"); - this.registerOutputBank("RECOIL::crosses"); - + factory.init(cp, RTRKConstants.NREGIONS); + // register output banks for drop option + this.registerOutputBank("RTRK::hits"); + this.registerOutputBank("RTRK::clusters"); + this.registerOutputBank("RTRK::crosses"); + LOGGER.log(Level.INFO, "--> recoil is ready..."); return true; } - - - - + @Override public boolean processDataEventUser(DataEvent event) { - List strips = RecoilStrip.getStrips(event, factory, this.getConstantsManager()); - List clusters = RecoilCluster.createClusters(strips); - List crosses = RecoilCross.createCrosses(clusters); + List strips = RTRKStrip.getStrips(event, factory, this.getConstantsManager()); + List clusters = RTRKCluster.createClusters(strips); + List crosses = RTRKCross.createCrosses(clusters); this.writeHipoBanks(event, strips, clusters, crosses); return true; } - - private void writeHipoBanks(DataEvent de, - List strips, - List clusters, - List crosses){ - - DataBank bankS = de.createBank("RECOIL::hits", strips.size()); + private void writeHipoBanks(DataEvent de, + List strips, + List clusters, + List crosses){ + + DataBank bankS = de.createBank("RTRK::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()); bankS.setByte("layer", h, (byte) strips.get(h).getDescriptor().getLayer()); bankS.setShort("strip", h, (short) strips.get(h).getDescriptor().getComponent()); bankS.setFloat("energy", h, (float) strips.get(h).getEnergy()); - bankS.setFloat("time", h, (float) strips.get(h).getTime()); + bankS.setFloat("time", h, (float) strips.get(h).getTime()); bankS.setShort("status", h, (short) strips.get(h).getStatus()); bankS.setShort("clusterId", h, (short) strips.get(h).getClusterId()); } - DataBank bankC = de.createBank("RECOIL::clusters", clusters.size()); + DataBank bankC = de.createBank("RTRK::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()); @@ -99,10 +96,10 @@ private void writeHipoBanks(DataEvent de, bankC.setFloat("ye", c, (float) clusters.get(c).getLine().end().y()); bankC.setFloat("ze", c, (float) clusters.get(c).getLine().end().z()); bankC.setShort("size", c, (short) clusters.get(c).size()); - bankC.setShort("status", c, (short) clusters.get(c).getStatus()); - } + bankC.setShort("status", c, (short) clusters.get(c).getStatus()); + } - DataBank bankX = de.createBank("RECOIL::crosses", crosses.size()); + DataBank bankX = de.createBank("RTRK::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()); @@ -112,13 +109,12 @@ private void writeHipoBanks(DataEvent de, bankX.setFloat("x", c, (float) crosses.get(c).point().x()); bankX.setFloat("y", c, (float) crosses.get(c).point().y()); bankX.setFloat("z", c, (float) crosses.get(c).point().z()); - bankX.setShort("cluster1", c, (short) crosses.get(c).getCluster1()); - bankX.setShort("cluster2", c, (short) crosses.get(c).getCluster2()); - bankX.setShort("status", c, (short) crosses.get(c).getStatus()); - } + bankX.setShort("cluster1", c, (short) crosses.get(c).getCluster1()); + bankX.setShort("cluster2", c, (short) crosses.get(c).getCluster2()); + bankX.setShort("status", c, (short) crosses.get(c).getStatus()); + } de.appendBanks(bankS,bankC,bankX); } - public static void fitGauss(H1F histo) { double mean = histo.getMean(); @@ -135,7 +131,7 @@ public static void fitGauss(H1F histo) { f1.setParameter(0, amp); f1.setParameter(1, mean); f1.setParameter(2, sigma); - + if(amp>5) { f1.setParLimits(0, amp*0.2, amp*1.2); f1.setParLimits(1, mean*0.5, mean*1.5); @@ -149,36 +145,36 @@ public static void fitGauss(H1F histo) { f1.setRange(mean-2.0*sigma,mean+2.0*sigma); DataFitter.fit(f1, histo, "Q"); } - } + } public static void main (String arg[]) { - - RecoilEngine engine = new RecoilEngine(); + + RTRKEngine engine = new RTRKEngine(); engine.init(); - + String input = "/Users/devita/urwell3d.hipo"; - + DataGroup dg = new DataGroup(3, 2); String[] axes = {"x", "y"}; - for(int il=0; il this.desc.getSector()) return -1; if(ob.getDescriptor().getLayer() < this.desc.getLayer()) return 1; @@ -161,46 +160,46 @@ public int compareTo(Object o) { return -1; } - public static List getStrips(DataEvent event, RecoilStripFactory factory, ConstantsManager ccdb) { + public static List getStrips(DataEvent event, RTRKStripFactory factory, ConstantsManager ccdb) { - List strips = new ArrayList<>(); + List strips = new ArrayList<>(); - if(event.hasBank("RECOIL::adc")){ - RawDataBank bank = new RawDataBank("RECOIL::adc"); + if(event.hasBank("RTRK::adc")){ + RawDataBank bank = new RawDataBank("RTRK::adc"); bank.read(event); - //DataBank bank = event.getBank("RECOIL::adc"); + //DataBank bank = event.getBank("RTRK::adc"); for(int i = 0; i < bank.rows(); i++){ int sector = bank.getByte("sector", i); int layer = bank.getByte("layer", i); int comp = bank.getShort("component", i); int adc = bank.getInt("ADC", i); double time = bank.getFloat("time", i); - - RecoilStrip strip = new RecoilStrip(sector, layer, comp); -// strip.setTriggerPhase(triggerPhase); - strip.setId(bank.trueIndex(i)+1); - strip.setADC(adc); - strip.setTDC((int) time); - strip.setEnergy(strip.ADC*RecoilConstants.ADCTOENERGY); - strip.setTime(strip.TDC*RecoilConstants.TDCTOTIME); - strip.setLine(factory.getStrip(sector, layer, comp)); - strip.setChamber(factory.getChamberIndex(comp)+1); - strip.setStatus(0); + RTRKStrip strip = new RTRKStrip(sector, layer, comp); - if(strip.getEnergy()>RecoilConstants.THRESHOLD) strips.add(strip); +// strip.setTriggerPhase(triggerPhase); +strip.setId(bank.trueIndex(i)+1); +strip.setADC(adc); +strip.setTDC((int) time); +strip.setEnergy(strip.ADC*RTRKParameters.ADCTOENERGY); +strip.setTime(strip.TDC*RTRKParameters.TDCTOTIME); +strip.setLine(factory.getStrip(sector, layer, comp)); +strip.setChamber(factory.getChamberIndex(comp)+1); +strip.setStatus(0); + +if(strip.getEnergy()>RTRKParameters.THRESHOLD) strips.add(strip); } - } + } return strips; } @Override public String toString(){ StringBuilder str = new StringBuilder(); - str.append(String.format("----> strip (%3d %3d %3d) ADC/TDC %5d %5d ENERGY = %8.5f TIME = %8.5f ", - this.desc.getSector(),this.desc.getLayer(),this.desc.getComponent(), - this.ADC,this.TDC,this.getEnergy(),this.getTime())); + str.append(String.format("----> strip (%3d %3d %3d) ADC/TDC %5d %5d ENERGY = %8.5f TIME = %8.5f ", + this.desc.getSector(),this.desc.getLayer(),this.desc.getComponent(), + this.ADC,this.TDC,this.getEnergy(),this.getTime())); return str.toString(); } }