This page outlines a proposal for an interface to access CalorimeterHit data along with information from the associated detector description.

A single interface was used for the purpose of discussion, though multiple interfaces might be a better (at least more traditionally OO) approach.

Comments welcome as either additions to this page or using the usual comment box.

package org.lcsim.geometry;

import hep.physics.vec.Hep3Vector;

/**
 * 
 * A preliminary proposal of an interface to Calorimeter hit data 
 * based on methods from @IDDecoder, @Subdetector, @Calorimeter, @CalorimeterType,
 * @CalorimeterHit, @Segmentation, @SegmentationBase (and its 4 subclasses), and 
 * @BarrelEndcapFlag.  For convenience, CalorimeterCell would combine functionality 
 * from these classes into a single "flattened" API so that users can avoid 
 * lots of subcasting and/or method chaining in order to access the information
 * required for their analysis.  It also replaces calls using "magic" field
 * names (primarily in IDDecoder) with proper interface methods.
 *   
 * Measurements, such as the position, are within a global coordinate 
 * system based at (0,0,0), unless otherwise noted.  Indices, however,
 * may refer to a local or global system.  For instance, ix would probably
 * translate to local coordinates in a readout plate, while iphi is most
 * likely a global phi index.
 *   
 * @author Jeremy McCormick
 *  
 */
public interface CalorimeterCell 
{
	/** 
	 * 64-bit identifier of this cell
	 * 
	 * @see CalorimeterHit.getCellId() 
	 */
	long cellId();	
	
	/**
	 * Hash code uniquely identifying the CalorimeterCell object
	 * 
	 * NOTE: Could be different from cellId()
	 * 
	 * FIXME: Java provides this already automatically?
	 * 
	 */
	long hashcode();
	
	/** 
	 * Raw energy in GeV
	 * 
	 * @see CalorimeterHit.getRawEnergy()
	 */
	double energyRaw();
	
	/** 
	 * Corrected energy in GeV
	 * 
	 * @see CalorimeterHit.getCorrectedEnergy() 	
	 *  
	 */
	double energyCorrected();
	
	/** 
	 * Shortcut for energy != 0 
	 */
	boolean isHit();
	
	/**
	 * Time in nanoseconds
	 * 
	 * @see CalorimeterHit.getTime()
	 *  
	 */
	double time();
			
	/** 
	 * Center position in mm
	 *
	 * @see CalorimeterHit.getPosition()
	 * @see IDDecoder.getPosition()
	 */
	Hep3Vector position();
	
	/** 
	 * x at cell center in mm
	 *
	 * @see IDDecoder.getX()
	 * 
	 */
	double x();
	
	/** 
	 * y at cell center in mm
	 *
	 * @see IDDecoder.getY()
	 * 
	 */
	double y();
	
	/** 
	 * z at cell center in mm
	 *
	 * @see IDDecoder.getZ()
	 * 
	 */
	double z();
	
	/** 
	 * Is the given point within tolerance of the cell center? 
	 */
	boolean isNear(Hep3Vector point, double tolerance);
	
	/** 
	 * Distance to center of cell from point 
	 */
	double howNear(Hep3Vector point);
	
	/** 
	 * Is the given point inside this cell?
	 */
	boolean isInside(Hep3Vector point);
	
	/** 
	 * Theta at cell center in radians 
	 *
	 * @see IDDecoder.getTheta()
	 * 
	 */
	double theta();
	
	/** 
	 * Minimum theta extent at edge of cell in radians 
	 */
	double thetaMin();	
	
	/** 
	 * Maximum theta extent at edge of cell in radians
	 */
	double thetaMax();
	
	/** 
	 * Size of the cell in theta, i.e. thetaMax() - thetaMin(), in radians 
	 */
	double thetaSize();
	
	/** 
	 * Phi at cell center, in radians
	 *
	 * @see IDDecoder.getPhi()
	 *
	 */
	double phi();
	
	/** 
	 * Minimum phi measurement at one edge of the cell in radians
	 */
	double phiMin();
	
	/** 
	 * Maximum phi measurement at one edge of the cell in radians
	 */
	double phiMax();
	
	/** 	
	 * Size of the cell in phi, i.e. phiMax - phiMin, in radians
	 */
	double phiSize();
	
	/** 
	 * Radius to the cell midpoint in mm
	 */
	double rho();

	/** 
	 * Minimum radius, i.e. inner radius, in mm
	 */
	double rhoMin();
	
	/** 
	 * Maximum radius, i.e. outer radius, in mm 
	 */
	double rhoMax();
	
	/** 
	 * Size of the cell in rho, i.e. rhoMax - rhoMin, in mm
	 * 
	 * NOTE: This method could also be called thickness() or width().
	 *  
	 */
	double rhoSize();
		
	/** 
	 * X index 
	 *
	 * @see IDDecoder.getValue()
	 * @see GridXYZ.getXBin()	
	 * 
	 */
	int ix();
	
	/** 
	 * Y index 
	 * 
	 * @see IDDecoder.getValue()
	 * @see GridXYZ.getYBin()	 
	 * 
	 */
	int iy();
	
	/** 
	 * Z index 
	 *
	 * @see IDDecoder.getValue()
	 * @see GridXYZ.getZBin()
	 * 
	 */
	int iz();
	
	/** 
	 * Theta index 
	 */
	int itheta();
	
	/** 
	 * Phi index 
	 */
	int iphi();
	
	/** 
	 * System number uniquely identifying the Subdetector of this cell
	 * 
	 * @see IDDecoder.getSystemID()
	 * 
	 */
	int system();
	
	/** 
	 * Section of the calorimeter along the z axis 
	 * 
	 * NOTE: See Mokka's HCAL models for an example of calorimeter's with sections along z.
	 * 
	 * NOTE: Only applies to calorimeter's that are subdivided in z, though other types
	 *       could "fake it" based on iz() or z().
	 * 
	 */
	int section();		
	
	/** 
	 * Module number in the section 
	 * 
	 * NOTE: Usually there are as many modules as sides to the calorimeter's polyhedra envelope.
	 * 
	 * NOTE: Only applies to realistic polyhedra calorimeters, though cylindrical types
	 *       could "fake it" based on iphi() or phi().
	 * 
	 */
	int module();
	
	/** 
	 * Stave number in the module
	 * 
	 * NOTE: Mokka's HCAL is an example of a calorimeter with multiple staves per module.
	 * 
	 */
	int stave();
	
	/** 
	 * Layer number 
	 * 
	 * @see IDDecoder.getLayer()
	 * 	 
	 */
	int layer();
	
	/** 
	 * Row number in a plate of cells 
	 * 
	 * NOTE: This is primarily applicable to calorimeters with planar readout volumes,
	 *       such as those within trapezoidal staves.  It could also apply to testbeams. 
	 */
	int row();
	
	/** 
	 * Column number in a plate of cells
	 * 
	 * NOTE: This is primarily applicable to calorimeters with planar readout volumes,
	 *       such as those within trapezoidal staves.  It could also apply to testbeams. 	
	 * 
	 */
	int column();	
	
	/** 
	 * Tower number
	 * 
	 * NOTE: The tower number identifies a projective tower spanning calorimeter subsystems.
	 * 
	 * FIXME: Possibly a deprecated/superceded concept?
	 * 
	 */
	int tower();
	
	/** 
	 * Is the cell flagged as an absorber layer that has been made sensitive for debugging? 
	 * 
	 * NOTE: There are possibly other ways to know whether a cell is actually from an absorber,
	 *       but an interface method is the most straightforward way for user's to access this
	 *       information.
	 * 
	 */
	boolean isAbsorber();
	
	/** 
	 * Is the cell in a barrel? 
	 * 	 
	 * @see IDDecoder.getBarrelEndcapFlag()
	 * @see BarrelEndcapFlag.isBarrel()
	 * 
	 */
	boolean isBarrel();
	
	/** 
	 * Is the cell in an endcap? 
	 *
	 * @see IDDecoder.getBarrelEndcapFlag()
	 * @see BarrelEndcapFlag.isEndcap()
	 */
	boolean isEndcap();	
	
	/** 
	 * Does the cell have a positive z measurement?
	 * 
	 * NOTE: This function may use the encoded setting from the barrel field 
	 *       or just examine the sign of CalorimeterCell.z().	 
	 * 
	 * @see IDDecoder.getBarrelEndcapFlag()
	 * @see BarrelEndcapFlag.isEndcapNorth()
	 * 
	 */
	boolean isNorth();
	
	/** 
	 * Does the cell have a negative z measurement?
	 * 
	 * NOTE: This function may use the encoded setting from the barrel field 
	 *       or just examine the sign of CalorimeterCell.z().	 
	 *       	 
	 * @see IDDecoder.getBarrelEndcapFlag()
	 * @see BarrelEndcapFlag.isEndcapSouth()
	 * 	 
	 */
	boolean isSouth();
		
	/** 
	 * Is the cell from an ECAL subdetector? 
	 * 
	 * @see Calorimeter.getCalorimeterType()
	 * @see CalorimeterType
	 * 	 
	 */
	boolean isECAL();
	
	/** 
	 * Is the cell from an HCAL subdetector? 
	 * 	  
	 * @see Calorimeter.getCalorimeterType()
	 * @see CalorimeterType
	 * 	 
	 */
	boolean isHCAL();
	
	/** 
	 * Is the cell from a MUON subdetector? 
	 * 
	 * @see Calorimeter.getCalorimeterType()
	 * @see CalorimeterType
	 * 
	 */
	boolean isMUON();
	
	/** 
	 * Is the cell from a FWD subdetector? (forward calorimeter)
	 *  
	 * @see Calorimeter.getCalorimeterType()
	 * @see CalorimeterType
	 * 
	 */
	boolean isFWD();	
	
	/** 
	 * Subdetector associated with this CalorimeterCell
	 * 
	 * @see CalorimeterHit.getSubdetector()
	 * @see IDDecoder.getSubdetector()
	 * 
	 * FIXME: This breaks the usual OO heuristic that a contained object should not
	 *        reference its container.
	 *        
	 * FIXME: Need to make sure that a Subdetector reference is not stored with each CalorimeterCell.
	 *  
	 */
	Subdetector subdetector();
	
	/** 
	 * IDDecoder associated with this CalorimeterCell
	 * 
	 * @see CalorimeterHit.getIDDecoder()
	 * 
	 * FIXME: Need to make sure that an IDDecoder reference is not stored with each CalorimeterCell.
	 * 
	 */
	IDDecoder decoder();
	
	/**
	 * Neighbor indices 
	 * 
	 * @see Calorimeter.getNeighbors()
	 * 
	 * FIXME: This should be spelled "neighbors".  Oh, well!
	 * 
	 * FIXME: Neighbor-finding should return a Neighborhood class rather
	 *        than double array.
	 *        
	 * FIXME: It should be possible to specifiy the type of neighbors.
	 *        For instance, crosstalk is usually only applied to cardinal
	 *        neighbors, rather than the Moore Neighborhood (i.e. cardinal
	 *        and ordinal neighbors).
	 *        
	 * FIXME: In my opinion, neighbor-finding should be completely externalized 
	 *        to allow for greater flexibility and functionality, though
	 *        removal of neighbor-finding from IDDecoder would break a
	 *        lot of existing code.
	 */
	long[] neighbours(int deltaLayer, int deltaTheta, int deltaPhi);	
	
	/**
	 * Does this cell type support neighbor-finding?
	 * 
	 * @see IDDecoder.supportsNeighbours()	 
	 * 
	 * FIXME: This is a superfluous function, because the IDDecoder 
	 *        interface has a neighbor-finding function.  Shouldn't 
	 *        it just throw an exception if not implemented?	
	 */
         boolean supportsNeighbours();	
	
	/**
	 * 
	 * Get the generic DetectorElement for this cell.
	 *  
	 * NOTE: For the future!
	 *  
	 * FIXME: Need a DetectorElement interface, first.
	 * 	 
	 */
	DetectorElement detectorElement();	
}
  • No labels