#ifndef MAPSSENSOR_HH_ #define MAPSSENSOR_HH_ #include #include #include #include #include "TH1F.h" #include "TH2F.h" #include "ToString.h" #include "Operators.h" #include "MapsException.hh" /** MapsSensor.hh * * Jamie Ballin, Imperial College London * February 2008 * * * A MapsSensor object knows its id, position in z, its clockwise angle of rotation * relative to a world system, and its alignment relative to the world system. * The sign convention of alignments is equal to that found from the sensor's residuals. * i.e. positive residual => set positive alignment. * * Sensors should be told when they confirm or deny a hit in a track by calling the * appropriate methods. * * Description of global geometry: physical coordiates (as opposed to pixel coordinates) * enter and leave this class in a global coordinate basis UNLESS otherwise specified by the * member method. On receipt of a global physical coordinate, this class will subtract its * alignment and then rotate the coordinate by -1.0 * phi. Hits leaving this class are rotated * by phi, and then have the alignment added before being returned. * */ class MapsSensor { public: typedef std::pair coord; typedef std::pair physXY; /** * MapsSensor constructors */ MapsSensor(unsigned id, double zpos, double phi = 0) : myId(id), myPosition(zpos), myPhi(phi), myAlignment(0, 0) { } ; MapsSensor(unsigned id, double zpos, physXY alignment, double phi = 0) : myId(id), myPosition(zpos), myPhi(phi), myAlignment(alignment) { } ; MapsSensor::physXY getAlignment() const; /** * All units in mm please. */ void setAlignment(MapsSensor::physXY alignment); /** * Clockwise angle relative to world system, in radians. */ inline void setPhi(const double phi) { myPhi = phi; } /** * z position in mm */ inline void setZPosition(const double zpos) { myPosition = zpos; } /** * Returns the sensor id */ inline unsigned id() { return myId; } ; /** * Returns the z position of this sensor */ inline double zPosition() const { return myPosition; } ; /** * Returns the global polar angle of the sensor */ inline double phi() { return myPhi; } ; virtual ~MapsSensor(); /** * Call this when the sensor should confirm a track */ void registerTrackConfirm(unsigned threshold, coord place, unsigned bx); /** * Call this when the sensor should confirm a track */ void registerTrackConfirm(unsigned threshold, coord place, unsigned bx, physXY fourthHitResid); /** * Call this when it apparently misses a hit, with the predicted pixel coordinate */ void registerTrackMiss(unsigned threshold, coord predicted, unsigned bx); /** * Call when the sensor misses a hit, with the predicted physical coordinate */ void registerTrackMiss(unsigned threshold, physXY predicted, unsigned bx); /** * A general purpose hit storage mechanism, not currently in use. */ void registerGeneralHit(unsigned threshold, coord place, unsigned bx); /** * An xy plot of where inefficiencies were found using predicted hits */ void getInefficiencyXYPlot(TH2F& plot, bool physicalXY = false); /** * An xy plot of where the sensor was efficient */ void getEfficiencyXYPlot(TH2F& plot); /** * Plots the difference between the extrapolated 3 hit track's position with the fourth * sensor, and the actual hit in the fourth sensor when this fourth sensor was judged efficient. */ void getFourthHitResidualPlot(TH2F& plot); /** * Adds a residual to the list (a residual = predicted hit - actual hit) */ void setResidual(physXY resid); /** * Efficiency as a function of bunch crossing. */ void getEfficiencyTimestamps(TH1F& plot); /** * Inefficiency as a function of bunch crossing. */ void getInefficiencyTimestamps(TH1F& plot); /** * Returns the efficiency, optionally excluding shapers or samplers. */ double getEfficiency(unsigned threshold, bool withShapers = true, bool withSamplers = true); /** * Returns the efficiency, optionally excluding shapers or samplers. */ void getEfficiencyCurve(TH1F&, int bins, int low, int high, bool withShapers = true, bool withSamplers = true); /** * Plots the efficiency by pixel group. If the threshold is not specified, * a summation over all thresholds is given. Otherwise, only selected thresholds * are presented. */ void getEfficiencyByGroup(TH2F&, unsigned threshold = 0); /** * Plots the resdiuals as a function of local physical coordindates */ void getResidualXYPlot(TH2F&) const; friend std::ostream& operator<<(std::ostream& s, const MapsSensor& ms); /** * Returns true if the specified coordinate falls in a dead area of the sensor */ bool isDeadArea(const physXY) const; /** * Converts a pixel x,y to a physical xy in the global coordinate system */ void convertHitToPhysical(const coord&, physXY&) const; /** * Converts a physical xy to a pixel hit where possible. * * Throws a MapsException if the hit falls in a dead area; application * code should check for this first with isDeadArea(physXY). */ void convertPhysicalToHit(const physXY&, coord&) const throw(MapsException); /** * Prints all sort of information about this sensor's efficiency as a function of threshold */ void printEfficiencies(std::ostream&); /** * Finds mutually dead areas as projected in the z direction for the supplied sensors. */ static void mutualSensorMask(const std::vector&, TH2F&); /** * Convenience method to decode the region for a given hit. */ unsigned decodeRegion(const coord&) const; /** * Convenient method to decode the region from a given physical hit, if possible. */ unsigned decodeRegion(const physXY&) const throw(MapsException); protected: MapsSensor& operator=(MapsSensor& ms) { return *this; } private: MapsSensor(MapsSensor* ms); unsigned myId; double myPosition; double myPhi; /** * The key is the threshold; the first element of the pair counts efficient hits, * the second counts inefficient hits. */ std::map* > myHitsByThreshold; std::map* > myShaperHitsByThreshold; std::map* > mySamplerHitsByThreshold; /** * All thresholds thusfar encountered in usage. */ std::vector myKnownThresholds; /** * Allows for efficiency as a function of time to be studied. */ std::map* > myTimes; physXY myAlignment; std::vector myResiduals; std::vector myFourthHitResids; /** * Pixel coordinate of efficient hits */ std::vector myEfficientHits; //std::vector myEfficientPlaces; /** * Pixel coordinate of inefficient would-be hits */ std::vector myInefficientHits; /** * Physical coordinate (local system) of inefficient would-be hits */ std::vector myInefficientPlaces; /** * Not in use yet. */ std::vector myGeneralHits; /** * This has to be private, since much efficiency based code depends on knowing * where we weren't efficient. */ void registerTrackMiss(unsigned threshold, unsigned bx); /** * Returns the lowest threshold the sensor knows of */ unsigned getLowestThresh() const; unsigned getHighestThresh() const; /** * Rotates hits from the local coordinate system to the global coordinate * system. Then you should align them. */ void rotateLocalToGlobal(physXY&) const; /** * Rotates hits from the global coordinate system (POST alignment) * to the local system. */ void rotateGlobalToLocal(physXY&) const; /** * Adds the alignment to the position. */ void align(physXY&) const; /** * Subtracts the alignment from the position. */ void malign(physXY&) const; }; std::ostream& operator<<(std::ostream& s, const MapsSensor& ms); #endif /**MAPSSENSOR_HH_*/