From f2939e62bd3daddf40f02db21dd75c6bec2b5751 Mon Sep 17 00:00:00 2001 From: nkx Date: Thu, 16 Jun 2022 01:59:38 +0800 Subject: [PATCH 1/4] added v2.2 readout and v2.2 TRestSignalZeroSuppresionProcess, use preprocessor to define processes --- CMakeLists.txt | 4 +- inc/TRestHitsEvent.h | 190 ++++ inc/TRestLegacyProcess.h | 19 + inc/TRestRawZeroSuppresionProcess.h | 15 +- inc/TRestReadout.h | 104 +++ inc/TRestReadoutChannel.h | 104 +++ inc/TRestReadoutMapping.h | 93 ++ inc/TRestReadoutModule.h | 265 ++++++ inc/TRestReadoutPixel.h | 123 +++ inc/TRestReadoutPlane.h | 175 ++++ inc/TRestSignal.h | 176 ++++ inc/TRestSignalEvent.h | 104 +++ inc/TRestSignalZeroSuppresionProcess.h | 85 ++ src/TRestHitsEvent.cxx | 1034 ++++++++++++++++++++++ src/TRestReadout.cxx | 997 +++++++++++++++++++++ src/TRestReadoutChannel.cxx | 106 +++ src/TRestReadoutMapping.cxx | 182 ++++ src/TRestReadoutModule.cxx | 478 ++++++++++ src/TRestReadoutPixel.cxx | 165 ++++ src/TRestReadoutPlane.cxx | 450 ++++++++++ src/TRestSignal.cxx | 520 +++++++++++ src/TRestSignalEvent.cxx | 240 +++++ src/TRestSignalZeroSuppresionProcess.cxx | 89 ++ 23 files changed, 5705 insertions(+), 13 deletions(-) create mode 100644 inc/TRestHitsEvent.h create mode 100644 inc/TRestReadout.h create mode 100644 inc/TRestReadoutChannel.h create mode 100644 inc/TRestReadoutMapping.h create mode 100644 inc/TRestReadoutModule.h create mode 100644 inc/TRestReadoutPixel.h create mode 100644 inc/TRestReadoutPlane.h create mode 100644 inc/TRestSignal.h create mode 100644 inc/TRestSignalEvent.h create mode 100644 inc/TRestSignalZeroSuppresionProcess.h create mode 100644 src/TRestHitsEvent.cxx create mode 100644 src/TRestReadout.cxx create mode 100644 src/TRestReadoutChannel.cxx create mode 100644 src/TRestReadoutMapping.cxx create mode 100644 src/TRestReadoutModule.cxx create mode 100644 src/TRestReadoutPixel.cxx create mode 100644 src/TRestReadoutPlane.cxx create mode 100644 src/TRestSignal.cxx create mode 100644 src/TRestSignalEvent.cxx create mode 100644 src/TRestSignalZeroSuppresionProcess.cxx diff --git a/CMakeLists.txt b/CMakeLists.txt index b75de8d..34e9858 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,7 @@ set(LibraryVersion "1.0") add_definitions(-DLIBRARY_VERSION="${LibraryVersion}") -COMPILELIB("") +set(deps detector) + +COMPILELIB(deps) diff --git a/inc/TRestHitsEvent.h b/inc/TRestHitsEvent.h new file mode 100644 index 0000000..1f084f3 --- /dev/null +++ b/inc/TRestHitsEvent.h @@ -0,0 +1,190 @@ + +#ifndef TRestSoft_TRestHitsEvent +#define TRestSoft_TRestHitsEvent + +#include + +#include "TArrayI.h" +#include "TAxis.h" +#include "TGraph2D.h" +#include "TH2F.h" +#include "TMath.h" +#include "TObject.h" + +#include +#include "TH2F.h" + +#include "TVector3.h" + +#include "TRestEvent.h" +#include "TRestHits.h" +#include "TVector3.h" + +//! An event data type that register a vector of TRestHits, +//! allowing us to save a 3-coordinate position and energy. +class TRestHitsEvent : public TRestEvent { + private: + /// An auxiliar TRestHits structure to register hits on XZ projection + TRestHits* fXZHits; //! + /// An auxiliar TRestHits structure to register hits on YZ projection + TRestHits* fYZHits; //! + + /// An auxiliar TRestHits structure to register hits on XYZ projection + TRestHits* fXYZHits; //! + + /// Stores the minimum x-position value. It is initialized by SetBoundaries. + Double_t fMinX; //! + /// Stores the maximum x-position value. It is initialized by SetBoundaries. + Double_t fMaxX; //! + + /// Stores the minimum y-position value. It is initialized by SetBoundaries. + Double_t fMinY; //! + /// Stores the maximum y-position value. It is initialized by SetBoundaries. + Double_t fMaxY; //! + + /// Stores the minimum z-position value. It is initialized by SetBoundaries. + Double_t fMinZ; //! + /// Stores the maximum z-position value. It is initialized by SetBoundaries. + Double_t fMaxZ; //! + + protected: + // TODO These graphs should be placed in TRestHits? + // (following similar GetGraph implementation in TRestSignal) + + /// An auxiliar TGraph pointer to visualize hits on XY-projection. + TGraph* fXYHitGraph; //! + /// An auxiliar TGraph pointer to visualize hits on XZ-projection. + TGraph* fXZHitGraph; //! + /// An auxiliar TGraph pointer to visualize hits on YZ-projection. + TGraph* fYZHitGraph; //! + + /// An auxiliar TH2F histogram to visualize hits on XY-projection. + TH2F* fXYHisto; //! + /// An auxiliar TH2F histogram to visualize hits on YZ-projection. + TH2F* fYZHisto; //! + /// An auxiliar TH2F histogram to visualize hits on XZ-projection. + TH2F* fXZHisto; //! + + TGraph2D* gxz = NULL; //! + TGraph2D* gyz = NULL; //! + + /// An auxiliar TH1F histogram to visualize hits on X-projection. + TH1F* fXHisto; //! + /// An auxiliar TH1F histogram to visualize hits on Y-projection. + TH1F* fYHisto; //! + /// An auxiliar TH1F histogram to visualize hits on Z-projection. + TH1F* fZHisto; //! + + /// The hits structure that is is saved to disk. + TRestHits fHits; // + + public: + void AddHit(Double_t x, Double_t y, Double_t z, Double_t en, Double_t t = 0, REST_HitType type = XYZ); + void AddHit(TVector3 pos, Double_t en, Double_t t = 0, REST_HitType type = XYZ); + + void SetBoundaries(); + void Sort(bool(comparecondition)(const TRestHits::iterator& hit1, const TRestHits::iterator& hit2) = 0); + void Shuffle(int NLoop); + + Int_t GetNumberOfHits() { return fHits.GetNumberOfHits(); } + + TRestHits* GetHits() { return &fHits; } + + /// Returns the X-coordinate of hit entry `n` in mm. + Double_t GetX(int n) { return fHits.GetX(n); } + + /// Returns the Y-coordinate of hit entry `n` in mm. + Double_t GetY(int n) { return fHits.GetY(n); } + + /// Returns the Z-coordinate of hit entry `n` in mm. + Double_t GetZ(int n) { return fHits.GetZ(n); } + + REST_HitType GetType(int n) { return fHits.GetType(n); } + + /// Returns the squared distance between hits `n` and `m`. + Double_t GetDistance2(int n, int m) { return fHits.GetDistance2(n, m); } + + TRestHits* GetXZHits(); + TRestHits* GetYZHits(); + TRestHits* GetXYZHits(); + + virtual void Initialize(); + + virtual void PrintEvent() { TRestHitsEvent::PrintEvent(-1); }; + virtual void PrintEvent(Int_t nHits); + + TVector3 GetPosition(int n) { return fHits.GetPosition(n); } + + TVector3 GetMeanPosition() { return fHits.GetMeanPosition(); } + + Int_t GetNumberOfHitsX() { return fHits.GetNumberOfHitsX(); } + Int_t GetNumberOfHitsY() { return fHits.GetNumberOfHitsY(); } + + Double_t GetMeanPositionX() { return fHits.GetMeanPositionX(); } + Double_t GetMeanPositionY() { return fHits.GetMeanPositionY(); } + Double_t GetMeanPositionZ() { return fHits.GetMeanPositionZ(); } + Double_t GetSigmaXY2() { return fHits.GetSigmaXY2(); } + Double_t GetSigmaX() { return fHits.GetSigmaX(); } + Double_t GetGaussSigmaX() { return GetXZHits()->GetGaussSigmaX(); } + Double_t GetGaussSigmaY() { return GetYZHits()->GetGaussSigmaY(); } + Double_t GetGaussSigmaZ() { return fHits.GetGaussSigmaZ(); } + + Double_t GetSigmaZ2() { return fHits.GetSigmaZ2(); } + Double_t GetSkewXY() { return fHits.GetSkewXY(); } + Double_t GetSkewZ() { return fHits.GetSkewZ(); } + + Double_t GetMaximumHitEnergy() { return fHits.GetMaximumHitEnergy(); } + Double_t GetMinimumHitEnergy() { return fHits.GetMinimumHitEnergy(); } + Double_t GetMeanHitEnergy() { return fHits.GetMeanHitEnergy(); } + + Double_t GetEnergyX() { return fHits.GetEnergyX(); } + Double_t GetEnergyY() { return fHits.GetEnergyY(); } + Double_t CalculateTotalDepositedEnergy(); + Double_t GetTotalDepositedEnergy() { return fHits.GetTotalDepositedEnergy(); } + Double_t GetEnergy(int n) { return fHits.GetEnergy(n); } + Double_t GetTime(int n) { return fHits.GetTime(n); } // return value in us + + Int_t GetClosestHit(TVector3 position) { return fHits.GetClosestHit(position); } + + // Inside Cylinder methods + Bool_t anyHitInsideCylinder(TVector3 x0, TVector3 x1, Double_t radius); + Bool_t allHitsInsideCylinder(TVector3 x0, TVector3 x1, Double_t radius); + Double_t GetEnergyInCylinder(TVector3 x0, TVector3 x1, Double_t radius); + Int_t GetNumberOfHitsInsideCylinder(TVector3 x0, TVector3 x1, Double_t radius); + TVector3 GetMeanPositionInCylinder(TVector3 x0, TVector3 x1, Double_t radius); + + // Inside Prim methods + Bool_t anyHitInsidePrism(TVector3 x0, TVector3 x1, Double_t sizeX, Double_t sizeY, Double_t theta); + Bool_t allHitsInsidePrism(TVector3 x0, TVector3 x1, Double_t sX, Double_t sY, Double_t theta); + + Double_t GetEnergyInPrism(TVector3 x0, TVector3 x1, Double_t sizeX, Double_t sizeY, Double_t theta); + Int_t GetNumberOfHitsInsidePrism(TVector3 x0, TVector3 x1, Double_t sizeX, Double_t sizeY, + Double_t theta); + TVector3 GetMeanPositionInPrism(TVector3 x0, TVector3 x1, Double_t sizeX, Double_t sizeY, Double_t theta); + + // Get closest distance to cylinder walls methods + Double_t GetClosestHitInsideDistanceToCylinderWall(TVector3 x0, TVector3 x1, Double_t radius); + Double_t GetClosestHitInsideDistanceToCylinderTop(TVector3 x0, TVector3 x1, Double_t radius); + Double_t GetClosestHitInsideDistanceToCylinderBottom(TVector3 x0, TVector3 x1, Double_t radius); + + // Get closest distance to prism walls methods + Double_t GetClosestHitInsideDistanceToPrismWall(TVector3 x0, TVector3 x1, Double_t sizeX, Double_t sizeY, + Double_t theta); + Double_t GetClosestHitInsideDistanceToPrismTop(TVector3 x0, TVector3 x1, Double_t sizeX, Double_t sizeY, + Double_t theta); + Double_t GetClosestHitInsideDistanceToPrismBottom(TVector3 x0, TVector3 x1, Double_t sizeX, + Double_t sizeY, Double_t theta); + + TPad* DrawEvent(const TString& option = ""); + void DrawHistograms(Int_t& column, Double_t pitch = 3, TString histOption = ""); + void DrawGraphs(Int_t& column); + void DrawGraph2D(); + + // Construtor + TRestHitsEvent(); + // Destructor + ~TRestHitsEvent(); + + ClassDef(TRestHitsEvent, 2); +}; +#endif diff --git a/inc/TRestLegacyProcess.h b/inc/TRestLegacyProcess.h index f100ca4..20882fa 100644 --- a/inc/TRestLegacyProcess.h +++ b/inc/TRestLegacyProcess.h @@ -52,4 +52,23 @@ class TRestLegacyProcess : public TRestEventProcess { ClassDefOverride(TRestLegacyProcess, 0); }; + +#define LegacyProcessDef(thisname, newname, n) \ + any GetInputEvent() const final { return any((TRestEvent*)nullptr); } \ + any GetOutputEvent() const final { return any((TRestEvent*)nullptr); } \ + void InitProcess() final{}; \ + TRestEvent* ProcessEvent(TRestEvent* eventInput) final { \ + RESTError << "You are trying to execute a legacy process " #thisname << RESTendl; \ + RESTError << "This is not allow, this class is kept for backward compatibility" << RESTendl; \ + exit(1); \ + return nullptr; \ + } \ + void EndProcess() final{}; \ + const char* GetProcessName() const final { return #thisname; } \ + thisname() { \ + RESTWarning << "Creating legacy process " #thisname << RESTendl; \ + RESTWarning << "This process is now implemented under" #newname << RESTendl; \ + } \ + ClassDef(thisname, n) + #endif diff --git a/inc/TRestRawZeroSuppresionProcess.h b/inc/TRestRawZeroSuppresionProcess.h index a45b411..f49a6a8 100644 --- a/inc/TRestRawZeroSuppresionProcess.h +++ b/inc/TRestRawZeroSuppresionProcess.h @@ -26,7 +26,7 @@ #include "TRestLegacyProcess.h" //! A process to identify signal and remove baseline noise from a TRestRawSignalEvent. -class TRestRawZeroSuppresionProcess : public TRestLegacyProcess { +class TRestRawZeroSuppresionProcess : public TRestEventProcess { private: /// The ADC range used for baseline offset definition TVector2 fBaseLineRange; @@ -54,7 +54,7 @@ class TRestRawZeroSuppresionProcess : public TRestLegacyProcess { public: /// It prints out the process parameters stored in the metadata structure - void PrintMetadata() override { + void PrintMetadata() { BeginPrintProcess(); RESTMetadata << "Base line range definition : ( " << fBaseLineRange.X() << " , " << fBaseLineRange.Y() << " ) " << RESTendl; @@ -71,15 +71,6 @@ class TRestRawZeroSuppresionProcess : public TRestLegacyProcess { EndPrintProcess(); } - TRestRawZeroSuppresionProcess() { - RESTWarning << "Creating legacy process TRestRawZeroSuppresionProcess" << RESTendl; - RESTWarning << "This process is now implemented under TRestRawToDetectorSignalProcess" << RESTendl; - } - TRestRawZeroSuppresionProcess(char* cfgFileName) { - RESTWarning << "Creating legacy process TRestRawZeroSuppresionProcess" << RESTendl; - RESTWarning << "This process is now implemented under TRestRawToDetectorSignalProcess" << RESTendl; - } - - ClassDefOverride(TRestRawZeroSuppresionProcess, 4); + LegacyProcessDef(TRestRawZeroSuppresionProcess, TRestRawToDetectorSignalProcess, 4); }; #endif diff --git a/inc/TRestReadout.h b/inc/TRestReadout.h new file mode 100644 index 0000000..9a06e0c --- /dev/null +++ b/inc/TRestReadout.h @@ -0,0 +1,104 @@ +/************************************************************************* + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * REST is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +#ifndef RestCore_TRestReadout +#define RestCore_TRestReadout + +#include + +#include "TObject.h" +#include "TRestMetadata.h" +#include "TRestReadoutPlane.h" + +/// A metadata class to generate/store a readout description. +class TRestReadout : public TRestMetadata { + private: + void InitFromConfigFile(); + void DoReadoutMapping(TRestReadoutModule* mod, int nodes = 0); + + void Initialize(); + + /// Defines if a decoding file was used to match physical readout channel id with signal daq id + Bool_t fDecoding; + /// Number of nodes per axis used on the readout coordinate mapping. See also TRestReadoutMapping. + Int_t fMappingNodes; + /// Number of readout planes present on the readout + Int_t fNReadoutPlanes; + /// A vector storing the TRestReadoutPlane definitions. + std::vector fReadoutPlanes; + /// A vector storing the TRestReadoutMapping for each kind of readout modules. + std::map fReadoutMappings; + + void ValidateReadout(); + + public: + TRestReadoutPlane& operator[](int p) { return fReadoutPlanes[p]; } + + TRestReadoutPlane* GetReadoutPlane(int p); + void AddReadoutPlane(TRestReadoutPlane plane); + + ///////////////////////////////////// + //{ + TRestReadoutPlane* GetReadoutPlaneWithID(int id); + TRestReadoutModule* GetReadoutModuleWithID(int id); + TRestReadoutChannel* GetReadoutChannelWithdaqID(int daqId); + //} + ///////////////////////////////////// + + Int_t GetNumberOfReadoutPlanes(); + Int_t GetNumberOfModules(); + Int_t GetNumberOfChannels(); + + ///////////////////////////////////// + //{ + TRestReadoutModule* ParseModuleDefinition(TiXmlElement* moduleDefinition); + void GetPlaneModuleChannel(Int_t daqID, Int_t& planeID, Int_t& moduleID, Int_t& channelID); + Int_t GetHitsDaqChannel(TVector3 hitpos, Int_t& planeID, Int_t& moduleID, Int_t& channelID); + Double_t GetX(Int_t signalID); + Double_t GetY(Int_t signalID); + //} + ///////////////////////////////////// + + Double_t GetX(Int_t planeID, Int_t modID, Int_t chID); + Double_t GetY(Int_t planeID, Int_t modID, Int_t chID); + + // Detal Level: + // 0->this readout + // 1->+all readout plane + // 2->+all readout module + // 3->+all readout channel + // 4->+all readout pixel + void PrintMetadata() { PrintMetadata(1); } + void PrintMetadata(Int_t DetailLevel); + + void Draw(); + + // Construtor + TRestReadout(); + TRestReadout(const char* cfgFileName); + TRestReadout(const char* cfgFileName, std::string name); + // Destructor + virtual ~TRestReadout(); + + ClassDef(TRestReadout, 2); +}; +#endif diff --git a/inc/TRestReadoutChannel.h b/inc/TRestReadoutChannel.h new file mode 100644 index 0000000..557ff4a --- /dev/null +++ b/inc/TRestReadoutChannel.h @@ -0,0 +1,104 @@ +/************************************************************************* + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * REST is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +#ifndef RestCore_TRestReadoutChannel +#define RestCore_TRestReadoutChannel + +#include + +#include "TObject.h" +#include "TRestMetadata.h" + +#include "TRestReadoutPixel.h" + +enum TRestReadoutChannelType { + Channel_NoType = 0, + Channel_Pixel = 1, + Channel_X = 2, + Channel_Y = 3, + Channel_U = 4, + Channel_V = 5, + Channel_W = 6, +}; + +/// A class to store the readout channel definition used in TRestReadoutModule. +/// It allows to integrate any number of independent readout pixels. +class TRestReadoutChannel : public TObject { + private: + Int_t fDaqID; ///< Defines the corresponding daq channel id. See decoding + ///< details at TRestReadout. + + std::vector fReadoutPixel; ///< A vector storing the different TRestReadoutPixel + ///< definitions. + + Short_t fChannelId = -1; ///< It stores the corresponding physical readout channel + + void Initialize(); + + public: + /// Returns the corresponding daq channel id + Int_t GetDaqID() { return fDaqID; } + + /// Returns the corresponding channel id + Int_t GetChannelId() { return fChannelId; } + + /// Returns the total number of pixels inside the readout channel + Int_t GetNumberOfPixels() { return fReadoutPixel.size(); } + + TRestReadoutPixel& operator[](int n) { return fReadoutPixel[n]; } + + /// Returns a pointer to the pixel *n* by index. + TRestReadoutPixel* GetPixel(int n) { + if (n >= GetNumberOfPixels()) return NULL; + return &fReadoutPixel[n]; + } + + void SetType(TRestReadoutChannelType type) { + // in future we may implement this + } + + TRestReadoutChannelType GetType() { + // in future we may implement this + return Channel_NoType; + } + + /// Sets the daq channel number id + void SetDaqID(Int_t id) { fDaqID = id; } + + /// Sets the readout channel number id + void SetChannelID(Int_t id) { fChannelId = id; } + + /// Adds a new pixel to the readout channel + void AddPixel(TRestReadoutPixel pix) { fReadoutPixel.push_back(pix); } + + Int_t isInside(Double_t x, Double_t y); + + void Print(int DetailLevel = 0); + + // Construtor + TRestReadoutChannel(); + // Destructor + virtual ~TRestReadoutChannel(); + + ClassDef(TRestReadoutChannel, 3); // REST run class +}; +#endif diff --git a/inc/TRestReadoutMapping.h b/inc/TRestReadoutMapping.h new file mode 100644 index 0000000..09a588d --- /dev/null +++ b/inc/TRestReadoutMapping.h @@ -0,0 +1,93 @@ +/************************************************************************* + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * REST is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +#ifndef RestCore_TRestReadoutMapping +#define RestCore_TRestReadoutMapping + +#include + +#include +#include + +/// This class defines a uniform 2-dimensional grid relating its nodes to the +/// pixels of a readout. +class TRestReadoutMapping : public TObject { + private: + Int_t fNodesX; ///< The number of nodes in the x-axis. + Int_t fNodesY; ///< The number of nodes in the y-axis. + + Double_t fNetSizeX; ///< The size of the net/grid in the x-axis. + Double_t fNetSizeY; ///< The size of the net/grid in the y-axis. + + TMatrixD fChannel; ///< A matrix containning the channel id for the + ///< corresponding XY-node. + TMatrixD fPixel; ///< A matrix containning the pixel id of fChannel for the + ///< corresponding XY-node. + + public: + // Getters + /// Returns the number of nodes in X. + Int_t GetNumberOfNodesX() { return fNodesX; } + + /// Returns the number of nodes in Y. + Int_t GetNumberOfNodesY() { return fNodesY; } + + /// Gets the channel id correspoding to a given node (i,j) + Int_t GetChannelByNode(Int_t i, Int_t j) { return fChannel[i][j]; } + + /// Gets the pixel id correspoding to a given node (i,j) + Int_t GetPixelByNode(Int_t i, Int_t j) { return fPixel[i][j]; } + + Bool_t isNodeSet(Int_t i, Int_t j); + + Bool_t AllNodesSet(); + + Int_t GetNumberOfNodesNotSet(); + + Int_t GetNodeX_ForChannelAndPixel(Int_t ch, Int_t px); + + Int_t GetNodeY_ForChannelAndPixel(Int_t ch, Int_t px); + + Int_t GetNodeX(Double_t x); + + Int_t GetNodeY(Double_t y); + + Double_t GetX(Int_t nodeX); + + Double_t GetY(Int_t nodeY); + + Int_t GetChannel(Double_t x, Double_t y); + + Int_t GetPixel(Double_t x, Double_t y); + + void SetNode(Int_t i, Int_t j, Int_t ch, Int_t pix); + + void Initialize(Int_t nX, Int_t nY, Double_t sX, Double_t sY); + + // Construtor + TRestReadoutMapping(); + // Destructor + ~TRestReadoutMapping(); + + ClassDef(TRestReadoutMapping, 1); +}; +#endif diff --git a/inc/TRestReadoutModule.h b/inc/TRestReadoutModule.h new file mode 100644 index 0000000..c258105 --- /dev/null +++ b/inc/TRestReadoutModule.h @@ -0,0 +1,265 @@ +/************************************************************************* + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * REST is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +#ifndef RestCore_TRestReadoutModule +#define RestCore_TRestReadoutModule + +#include + +#include +#include "TObject.h" + +#include +#include +#include + +/// A class to store the readout module definition used in TRestReadoutPlane. It +/// allows to integrate any number of independent readout channels. +class TRestReadoutModule : public TObject { + private: + Int_t fModuleID; ///< The module id given by the readout definition. + + TString fModuleName; ///< The assigned module name. i.e, microbulk, thermalbounding + ///< Modules with same name could share a same mapping + + TString fModuleUniqueName; ///< The unique module name. i.e, M2, M0, V508 + + Double_t fModuleOriginX; ///< The module x-position (left-bottom corner) + ///< relative to the readout plane position. + Double_t fModuleOriginY; ///< The module y-position (left-bottom corner) + ///< relative to the readout plane position. + + Double_t fModuleSizeX; ///< X-size of the module. All pixels should be + ///< containned within this size. + Double_t fModuleSizeY; ///< Y-size of the module. All pixels should be + ///< containned within this size. + + Double_t fModuleRotation; ///< The rotation of the module around the + ///< position=(fModuleOriginX, fModuleOriginY) in + ///< degrees. + + Int_t fMininimumDaqId; ///< The minimum daq channel id associated to the + ///< module. + Int_t fMaximumDaqId; ///< The maximum daq channel id associated to the module. + + std::vector fReadoutChannel; ///< A vector of the instances of TRestReadoutChannel + ///< containned in the readout module. + Double_t fTolerance; ///< Tolerance allowed in overlaps at the pixel + ///< boundaries in mm. + +#ifndef __CINT__ + Bool_t showWarnings; //!///< Flag to enable/disable warning outputs. Disabled by + //! default. REST_Warning in TRestReadout will enable it. + TRestReadoutMapping* fMapping; //!///< The readout module uniform grid mapping. +#endif + + void Initialize(); + + /// Converts the coordinates given by TVector2 in the readout plane reference + /// system to the readout module reference system. + TVector2 TransformToModuleCoordinates(TVector2 p) { return TransformToModuleCoordinates(p.X(), p.Y()); } + + /// Converts the coordinates (xPhys,yPhys) in the readout plane reference + /// system to the readout module reference system. + TVector2 TransformToModuleCoordinates(Double_t xPhys, Double_t yPhys) { + TVector2 coords(xPhys - fModuleOriginX, yPhys - fModuleOriginY); + TVector2 rot = coords.Rotate(-fModuleRotation * TMath::Pi() / 180.); + + return rot; + } + + /// Converts the coordinates (xMod,yMod) in the readout module reference + /// system to the readout plane reference system. + TVector2 TransformToPhysicalCoordinates(Double_t xMod, Double_t yMod) { + TVector2 coords(xMod, yMod); + + coords = coords.Rotate(fModuleRotation * TMath::Pi() / 180.); + coords = coords + TVector2(fModuleOriginX, fModuleOriginY); + + return coords; + } + + protected: + public: + // Setters + + /// Sets the module by id definition + void SetModuleID(Int_t modID) { fModuleID = modID; } + + /// Sets the module size by definition using (sX, sY) coordinates + void SetSize(Double_t sX, Double_t sY) { + fModuleSizeX = sX; + fModuleSizeY = sY; + } + + /// Sets the module size by definition using TVector2 input + void SetSize(TVector2 s) { + fModuleSizeX = s.X(); + fModuleSizeY = s.Y(); + } + + /// Sets the module origin by definition using (x,y) coordinates + void SetOrigin(Double_t x, Double_t y) { + fModuleOriginX = x; + fModuleOriginY = y; + } + + /// Sets the module origin by definition using TVector2 input + void SetOrigin(TVector2 c) { + fModuleOriginX = c.X(); + fModuleOriginY = c.Y(); + } + + /// Sets the module rotation in degrees + void SetRotation(Double_t rot) { fModuleRotation = rot; } + + /// Sets the name of the readout module + void SetName(TString name) { fModuleName = name; } + + /// Sets the unique name of the readout module + void SetUniqueName(TString name) { fModuleUniqueName = name; } + + /// Sets the tolerance for independent pixel overlaps + void SetTolerance(Double_t tol) { fTolerance = tol; } + + /// Gets the tolerance for independent pixel overlaps + Double_t GetTolerance() { return fTolerance; } + + /// Returns the minimum daq id number + Int_t GetMinDaqID() { return fMininimumDaqId; } + + /// Returns the maximum daq id number + Int_t GetMaxDaqID() { return fMaximumDaqId; } + + /// Returns the physical readout channel index for a given daq id channel + /// number + Int_t DaqToReadoutChannel(Int_t daqChannel) { + for (int n = 0; n < GetNumberOfChannels(); n++) + if (GetChannel(n)->GetDaqID() == daqChannel) return n; + return -1; + } + + /// Returns the module id + Int_t GetModuleID() { return fModuleID; } + + /// Returns the module x-coordinate origin + Double_t GetModuleOriginX() { return fModuleOriginX; } + + /// Returns the module y-coordinate origin + Double_t GetModuleOriginY() { return fModuleOriginY; } + + /// Returns the module x-coordinate origin + Double_t GetOriginX() { return fModuleOriginX; } + + /// Returns the module y-coordinate origin + Double_t GetOriginY() { return fModuleOriginY; } + + /// Returns the module size x-coordinate + Double_t GetModuleSizeX() { return fModuleSizeX; } + + /// Returns the module size y-coordinate + Double_t GetModuleSizeY() { return fModuleSizeY; } + + /// Returns the module rotation in degrees + Double_t GetModuleRotation() { return fModuleRotation; } + + /// Converts the coordinates given by TVector2 in the readout plane reference + /// system to the readout module reference system. + TVector2 GetModuleCoordinates(TVector2 p) { return TransformToModuleCoordinates(p); } + + /// Converts the coordinates given by TVector2 in the readout module reference + /// system to the readout plane reference system. + TVector2 GetPhysicalCoordinates(TVector2 p) { return TransformToPhysicalCoordinates(p.X(), p.Y()); } + + /// Returns the module name + TString GetName() { return fModuleName; } + + /// Returns the unique module name + TString GetUniqueName() { return fModuleUniqueName; } + + /// Returns a pointer to the readout mapping + TRestReadoutMapping* GetMapping() { return fMapping; } + + TRestReadoutChannel& operator[](int n) { return fReadoutChannel[n]; } + + /// Returns a pointer to a readout channel by index + TRestReadoutChannel* GetChannel(int n) { + if (n >= GetNumberOfChannels()) return NULL; + return &fReadoutChannel[n]; + } + + /// Returns the total number of channels defined inside the module + Int_t GetNumberOfChannels() { return fReadoutChannel.size(); } + + /// Enables warning output + void EnableWarnings() { showWarnings = true; } + + /// Disables warning output + void DisableWarnings() { showWarnings = false; } + + void SetReadoutMapping(TRestReadoutMapping* mapping) { fMapping = mapping; } + + Bool_t isInside(Double_t x, Double_t y); + Bool_t isInside(TVector2 pos); + + Bool_t isInsideChannel(Int_t channel, Double_t x, Double_t y); + Bool_t isInsideChannel(Int_t channel, TVector2 pos); + + Bool_t isInsidePixel(Int_t channel, Int_t pixel, Double_t x, Double_t y); + Bool_t isInsidePixel(Int_t channel, Int_t pixel, TVector2 pos); + + Bool_t isInsidePixelRelative(Int_t channel, Int_t pixel, Double_t x, Double_t y); + Bool_t isInsidePixelRelative(Int_t channel, Int_t pixel, TVector2 pos); + + Bool_t isDaqIDInside(Int_t daqID); + Int_t FindChannel(Double_t x, Double_t y); + TVector2 GetDistanceToModule(TVector2 pos); + + TVector2 GetPixelOrigin(Int_t channel, Int_t pixel); + TVector2 GetPixelVertex(Int_t channel, Int_t pixel, Int_t vertex); + TVector2 GetPixelCenter(Int_t channel, Int_t pixel); + Bool_t GetPixelTriangle(Int_t channel, Int_t pixel); + + TVector2 GetPixelOrigin(TRestReadoutPixel* pix); + TVector2 GetPixelVertex(TRestReadoutPixel* pix, Int_t vertex); + TVector2 GetPixelCenter(TRestReadoutPixel* pix); + Bool_t GetPixelTriangle(TRestReadoutPixel* pix); + + TVector2 GetVertex(int n) const; + + void AddChannel(TRestReadoutChannel& rChannel); + + void SetMinMaxDaqIDs(); + + void Draw(); + + void Print(Int_t DetailLevel = 0); + + void PrintDecoding(); + // Construtor + TRestReadoutModule(); + // Destructor + virtual ~TRestReadoutModule(); + + ClassDef(TRestReadoutModule, 2); +}; +#endif diff --git a/inc/TRestReadoutPixel.h b/inc/TRestReadoutPixel.h new file mode 100644 index 0000000..5c7cd74 --- /dev/null +++ b/inc/TRestReadoutPixel.h @@ -0,0 +1,123 @@ +/************************************************************************* + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * REST is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +#ifndef RestCore_TRestReadoutPixel +#define RestCore_TRestReadoutPixel + +#include + +#include +#include +#include "TObject.h" +#include "TRestMetadata.h" + +/// A class to store the readout pixel definition used in TRestReadoutChannel. +class TRestReadoutPixel : public TObject { + private: + Double_t fPixelOriginX; ///< The pixel x-origin position, left-bottom corner. + Double_t fPixelOriginY; ///< The pixel y-origin position, left-bottom corner. + + Double_t fPixelSizeX; ///< The pixel x size. + Double_t fPixelSizeY; ///< The pixel y size. + + Double_t fRotation; ///< The pixel rotation angle in degrees, rotation with + ///< axis at the origin position. + + Bool_t fTriangle; ///< The type of the pixel : false is rectangular, true is + ///< triangle + void Initialize(); + + protected: + public: + /// Returns the x-coordinate pixel origin. + Double_t GetOriginX() const { return fPixelOriginX; } + + /// Returns the y-coordinate pixel origin. + Double_t GetOriginY() const { return fPixelOriginY; } + + /// Returns a TVector2 with the pixel origin. + TVector2 GetOrigin() const { return TVector2(fPixelOriginX, fPixelOriginY); } + + /// Returns the rotation angle in degrees + Double_t GetRotation() const { return fRotation; } + + /// Returns the pixel size in X + Double_t GetSizeX() { return fPixelSizeX; } + + /// Returns the pixel size in Y + Double_t GetSizeY() { return fPixelSizeY; } + + /// Returns a TVector2 with the pixel size. + TVector2 GetSize() { return TVector2(fPixelSizeX, fPixelSizeY); } + + /// Returns true if the pixel is a triangle. + Bool_t GetTriangle() const { return fTriangle; } + + TVector2 GetCenter() const; + + TVector2 GetVertex(int n) const; + + /// Sets the origin of the pixel using the coordinate values *x*,*y*. + void SetOrigin(Double_t x, Double_t y) { + fPixelOriginX = x; + fPixelOriginY = y; + } + + /// Sets the origin of the pixel using a TVector2. + void SetOrigin(TVector2 origin) { + fPixelOriginX = origin.X(); + fPixelOriginY = origin.Y(); + } + + /// Sets the size of the pixel using the coordinate values *sx*,*sy*. + void SetSize(Double_t sx, Double_t sy) { + fPixelSizeX = sx; + fPixelSizeY = sy; + } + + /// Sets the size of the pixel using a TVector2. + void SetSize(TVector2 size) { + fPixelSizeX = size.X(); + fPixelSizeY = size.Y(); + } + + /// Sets the rotation angle of the pixel in degrees + void SetRotation(Double_t rot) { fRotation = rot; } + + /// Sets the type of the pixel + void SetTriangle(Bool_t type) { fTriangle = type; } + + Bool_t isInside(TVector2 pos); + Bool_t isInside(Double_t x, Double_t y); + + TVector2 TransformToPixelCoordinates(TVector2 p); + + void Print(); + + // Construtor + TRestReadoutPixel(); + // Destructor + virtual ~TRestReadoutPixel(); + + ClassDef(TRestReadoutPixel, 4); +}; +#endif diff --git a/inc/TRestReadoutPlane.h b/inc/TRestReadoutPlane.h new file mode 100644 index 0000000..b641d04 --- /dev/null +++ b/inc/TRestReadoutPlane.h @@ -0,0 +1,175 @@ +/************************************************************************* + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * REST is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +#ifndef RestCore_TRestReadoutPlane +#define RestCore_TRestReadoutPlane + +#include + +#include "TObject.h" + +#include "TRestMetadata.h" +#include "TRestReadoutChannel.h" +#include "TRestReadoutModule.h" + +#include +#include + +/// A class to store the readout plane definition used in TRestReadout. It +/// allows to integrate any number of independent readout modules. +class TRestReadoutPlane : public TObject { + private: + Int_t fPlaneID; ///< The readout plane id. The id number is imposed by the + ///< order of creation. Being the first id=0. + + TVector3 fPosition; ///< The position of the readout plane. The relative position + ///< of the modules will be shifted by this value. + TVector3 fPlaneVector; ///< The plane vector definning the plane orientation + ///< and the side of the active volume. + TVector3 fCathodePosition; ///< The cathode position which delimites the active + ///< volume together with the readout plane. + Double_t fChargeCollection; ///< A parameter between 0 and 1 definning how + ///< much charge should be collected from a + ///< charge hit. It might be used to distribute + ///< the charge between different readout planes. + Double_t fTotalDriftDistance; ///< A parameter storing the total drift distance, + ///< defined between cathode and readout plane. + + Int_t fNModules; ///< The number of modules that have been added to the + ///< readout plane + std::vector fReadoutModules; ///< A vector of the instances of TRestReadoutModule + ///< containned in the readout plane. + + void Initialize(); + + protected: + public: + // Setters + /// Sets the planeId. This is done by TRestReadout during initialization + void SetID(int id) { fPlaneID = id; } + + /// Sets the readout plane position + void SetPosition(TVector3 pos) { fPosition = pos; } + + /// Sets the cathode plane position. By default is parallel to the readout + /// plane. + void SetCathodePosition(TVector3 pos) { fCathodePosition = pos; } + + /// Sets the orientation of the readout plane, and defines the side of the + /// active volume. + void SetPlaneVector(TVector3 vect) { fPlaneVector = vect.Unit(); } + + /// Sets the value for the charge collection. + void SetChargeCollection(Double_t charge) { fChargeCollection = charge; } + + /// Sets the value for the total drift distance + void SetTotalDriftDistance(Double_t d) { fTotalDriftDistance = d; } + + // Getters + /// Returns an integer with the plane id number. + Int_t GetID() { return fPlaneID; } + + /// Returns a TVector3 with the readout plane position + TVector3 GetPosition() { return fPosition; } + + /// Returns a TVector3 with the cathode position + TVector3 GetCathodePosition() { return fCathodePosition; } + + /// Returns a TVector3 with a vector normal to the readout plane + TVector3 GetPlaneVector() { return fPlaneVector; } + + /// Returns the charge collection ratio at this readout plane + Double_t GetChargeCollection() { return fChargeCollection; } + + /// Returns the total drift distance + Double_t GetTotalDriftDistance() { return fTotalDriftDistance; } + + /// Returns the perpendicular distance to the readout plane from a given + /// position *pos*. + Double_t GetDistanceTo(TVector3 pos); + + /// Returns the perpendicular distance to the readout plane from a given + /// position *x*, *y*, *z*. + Double_t GetDistanceTo(Double_t x, Double_t y, Double_t z); + + /// Returns a TVector2 oriented as the shortest distance of a given position + /// *pos* on the plane to a specific module with id *mod* + TVector2 GetDistanceToModule(Int_t mod, TVector2 pos) { + return GetModuleByID(mod)->GetDistanceToModule(pos); + } + + TRestReadoutModule& operator[](int mod) { return fReadoutModules[mod]; } + + /// Returns a pointer to a readout module using its vector index + TRestReadoutModule* GetModule(int mod) { + if (mod >= GetNumberOfModules()) return NULL; + return &fReadoutModules[mod]; + } + + /// Returns the total number of modules in the readout plane + Int_t GetNumberOfModules() { return fReadoutModules.size(); } + + /// Adds a new module to the readout plane + void AddModule(TRestReadoutModule& rModule) { + fReadoutModules.push_back(rModule); + fNModules++; + } + + /// Prints the readout plane description + void PrintMetadata() { Print(); } + + Int_t GetNumberOfChannels(); + + TRestReadoutModule* GetModuleByID(Int_t modID); + + Int_t isZInsideDriftVolume(Double_t z); + + Int_t isZInsideDriftVolume(TVector3 pos); + + Bool_t isDaqIDInside(Int_t daqId); + + Int_t GetModuleIDFromPosition(TVector3 pos); + + Int_t GetModuleIDFromPosition(Double_t x, Double_t y, Double_t z); + + void SetDriftDistance(); + + void Draw(); + + void Print(Int_t DetailLevel = 0); + + Int_t FindChannel(Int_t module, Double_t absX, Double_t absY); + + Double_t GetX(Int_t modID, Int_t chID); + Double_t GetY(Int_t modID, Int_t chID); + + TH2Poly* GetReadoutHistogram(); + void GetBoundaries(double& xmin, double& xmax, double& ymin, double& ymax); + + // Construtor + TRestReadoutPlane(); + // Destructor + virtual ~TRestReadoutPlane(); + + ClassDef(TRestReadoutPlane, 1); +}; +#endif diff --git a/inc/TRestSignal.h b/inc/TRestSignal.h new file mode 100644 index 0000000..79714c0 --- /dev/null +++ b/inc/TRestSignal.h @@ -0,0 +1,176 @@ +///______________________________________________________________________________ +///______________________________________________________________________________ +///______________________________________________________________________________ +/// +/// +/// RESTSoft : Software for Rare Event Searches with TPCs +/// +/// TRestSignal.h +/// +/// Event class to store signals fromm simulation and acquisition +/// events +/// +/// sept 2015: First concept +/// Created as part of the conceptualization of existing REST +/// software. +/// JuanAn Garcia/Javier Galan +/// nov 2015: +/// Changed vectors fSignalTime and fSignalCharge from to +///< Float_t> JuanAn Garcia +///_______________________________________________________________________________ + +#ifndef RestCore_TRestSignal +#define RestCore_TRestSignal + +#include + +#include +#include +#include +#include + +class TRestSignal : public TObject { + private: + Int_t GetMinIndex(); + Int_t GetTimeIndex(Double_t t); + + protected: + Int_t fSignalID; + + std::vector fSignalTime; // Vector with the time of the signal + std::vector fSignalCharge; // Vector with the charge of the signal + + void AddPoint(TVector2 p); + void SetPoint(TVector2 p); + + public: +#ifndef __CINT__ + + TGraph* fGraph; //! + + std::vector fPointsOverThreshold; //! +#endif + + void Initialize() { + fSignalCharge.clear(); + fSignalTime.clear(); + fSignalID = -1; + } + + // TODO other objects should probably skip using GetMaxIndex direclty + Int_t GetMaxIndex(Int_t from = 0, Int_t to = 0); + + // Getters + TVector2 GetPoint(Int_t n) { + TVector2 vector2(GetTime(n), GetData(n)); + + return vector2; + } + + Int_t GetSignalID() { return fSignalID; } + Int_t GetID() { return fSignalID; } + + void IncreaseTimeBinBy(Int_t bin, Double_t data) { + if (bin >= GetNumberOfPoints()) { + std::cout << "Increase time bin: outside limits" << std::endl; + return; + } + + fSignalCharge[bin] += data; + } + + Int_t GetNumberOfPoints() { + if (fSignalTime.size() != fSignalCharge.size()) { + std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl; + std::cout << "WARNING, the two vector sizes did not match" << std::endl; + std::cout << "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!" << std::endl; + } + return fSignalTime.size(); + } + + Double_t GetIntegralWithTime(Double_t startTime, Double_t endTime); + Double_t GetIntegral(Int_t startBin = 0, Int_t endBin = 0); + /* +Double_t GetIntegralWithThreshold(Int_t from, Int_t to, Int_t startBaseline, Int_t endBaseline, + Double_t threshold = 2, Int_t nPointsOverThreshold = 5, + Double_t nMinSigmas = 5); +Double_t GetIntegralWithThreshold(Int_t from, Int_t to, Double_t baseline, Double_t pointThreshold, + Int_t nPointsOverThreshold, Double_t signalThreshold); + */ + + void Normalize(Double_t scale = 1.); + + std::vector GetPointsOverThreshold() { return fPointsOverThreshold; } + + Double_t GetAverage(Int_t start = 0, Int_t end = 0); + Int_t GetMaxPeakWidth(); + Double_t GetMaxPeakWithTime(Double_t startTime, Double_t endTime); + + Double_t GetMaxPeakValue(); + Double_t GetMinPeakValue(); + + Double_t GetMaxPeakTime(Int_t from = 0, Int_t to = 0); + + Double_t GetMaxValue() { return GetMaxPeakValue(); } + Double_t GetMinValue() { return GetMinPeakValue(); } + + Double_t GetMinTime(); + Double_t GetMaxTime(); + + Double_t GetData(Int_t index) { return (double)fSignalCharge[index]; } + Double_t GetTime(Int_t index) { return (double)fSignalTime[index]; } + + // Setters + void SetSignalID(Int_t sID) { fSignalID = sID; } + void SetID(Int_t sID) { fSignalID = sID; } + + void NewPoint(Float_t time, Float_t data); + void AddPoint(Double_t t, Double_t d); + void AddCharge(Double_t t, Double_t d); + void AddDeposit(Double_t t, Double_t d); + + void SetPoint(Double_t t, Double_t d); + void SetPoint(Int_t index, Double_t t, Double_t d); + + Double_t GetStandardDeviation(Int_t startBin, Int_t endBin); + Double_t GetBaseLine(Int_t startBin, Int_t endBin); + Double_t GetBaseLineSigma(Int_t startBin, Int_t endBin, Double_t baseline = 0); + + Double_t SubstractBaseline(Int_t startBin, Int_t endBin); + void AddOffset(Double_t offset); + + void MultiplySignalBy(Double_t factor); + void ExponentialConvolution(Double_t fromTime, Double_t decayTime, Double_t offset = 0); + void SignalAddition(TRestSignal* inSgnl); + + Bool_t isSorted(); + void Sort(); + + void GetDifferentialSignal(TRestSignal* diffSgnl, Int_t smearPoints = 5); + void GetSignalDelayed(TRestSignal* delayedSignal, Int_t delay); + void GetSignalSmoothed(TRestSignal* smthSignal, Int_t averagingPoints = 3); + + void GetWhiteNoiseSignal(TRestSignal* noiseSgnl, Double_t noiseLevel = 1.); + void GetSignalGaussianConvolution(TRestSignal* convSgnl, Double_t sigma = 100., Int_t nSigmas = 5); + + void AddGaussianSignal(Double_t amp, Double_t sigma, Double_t time, Int_t N, Double_t fromTime, + Double_t toTime); + + void Reset() { + fSignalTime.clear(); + fSignalCharge.clear(); + } + + void WriteSignalToTextFile(TString filename); + void Print(); + + TGraph* GetGraph(Int_t color = 1); + + // Construtor + TRestSignal(); + // Destructor + ~TRestSignal(); + + ClassDef(TRestSignal, 1); +}; +#endif diff --git a/inc/TRestSignalEvent.h b/inc/TRestSignalEvent.h new file mode 100644 index 0000000..c8f4ee7 --- /dev/null +++ b/inc/TRestSignalEvent.h @@ -0,0 +1,104 @@ +///______________________________________________________________________________ +///______________________________________________________________________________ +///______________________________________________________________________________ +/// +/// +/// RESTSoft : Software for Rare Event Searches with TPCs +/// +/// TRestSignalEvent.h +/// +/// Event class to store DAQ events either from simulation and +/// acquisition +/// +/// sept 2015: First concept +/// Created as part of the conceptualization of existing REST +/// software. +/// JuanAn Garcia +///_______________________________________________________________________________ + +#ifndef RestDAQ_TRestSignalEvent +#define RestDAQ_TRestSignalEvent + +#include + +#include +#include +#include +#include +#include +#include + +#include "TRestEvent.h" +#include "TRestSignal.h" + +class TRestSignalEvent : public TRestEvent { + protected: +#ifndef __CINT__ + Double_t fMinTime; //! + Double_t fMaxTime; //! + Double_t fMinValue; //! + Double_t fMaxValue; //! +#endif + + std::vector fSignal; // Collection of signals that define the event + + private: + void SetMaxAndMin(); + + public: + Bool_t signalIDExists(Int_t sID) { + if (GetSignalIndex(sID) == -1) return false; + return true; + } + + void SortSignals() { + for (int n = 0; n < GetNumberOfSignals(); n++) fSignal[n].Sort(); + } + + // Setters + void AddSignal(TRestSignal s); + + void AddChargeToSignal(Int_t sgnlID, Double_t tm, Double_t chrg); + + // Getters + Int_t GetNumberOfSignals() { return fSignal.size(); } + TRestSignal* GetSignal(Int_t n) { return &fSignal[n]; } + + TRestSignal* GetSignalById(Int_t sid) { + Int_t index = GetSignalIndex(sid); + if (index < 0) return NULL; + + return &fSignal[index]; + } + + Int_t GetSignalIndex(Int_t signalID); + + Double_t GetBaseLineAverage(Int_t startBin, Int_t endBin); + Double_t GetBaseLineSigmaAverage(Int_t startBin, Int_t endBin); + void SubstractBaselines(Int_t startBin, Int_t endBin); + Double_t GetIntegral(Int_t startBin = 0, Int_t endBin = 0); + // Double_t GetIntegralWithThreshold(Int_t from, Int_t to, Int_t startBaseline, Int_t endBaseline, + // Double_t nSigmas, Int_t nPointsOverThreshold, + // Double_t minPeakAmplitude); + + Double_t GetMaxValue(); + Double_t GetMinValue(); + Double_t GetMinTime(); + Double_t GetMaxTime(); + + Double_t GetIntegralWithTime(Double_t startTime, Double_t endTime); + + // Default + void Initialize(); + void PrintEvent(); + + TPad* DrawEvent(const TString& option = ""); + + // Construtor + TRestSignalEvent(); + // Destructor + ~TRestSignalEvent(); + + ClassDef(TRestSignalEvent, 1); // REST event superclass +}; +#endif diff --git a/inc/TRestSignalZeroSuppresionProcess.h b/inc/TRestSignalZeroSuppresionProcess.h new file mode 100644 index 0000000..4292c62 --- /dev/null +++ b/inc/TRestSignalZeroSuppresionProcess.h @@ -0,0 +1,85 @@ +/************************************************************************* + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * REST is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +#ifndef RestCore_TRestSignalZeroSuppresionProcess +#define RestCore_TRestSignalZeroSuppresionProcess + +//#include +//#include + +#include "TRestLegacyProcess.h" + +//! A process to identify signal and remove baseline noise from a TRestRawSignalEvent. +class TRestSignalZeroSuppresionProcess : public TRestEventProcess { + private: + /// The ADC range used for baseline offset definition + TVector2 fBaseLineRange; + + /// The ADC range used for integral definition and signal identification + TVector2 fIntegralRange; + + /// Number of sigmas over baseline fluctuation to accept a point is over threshold. + Double_t fPointThreshold; + + /// A threshold parameter to accept or reject a pre-identified signal. See process description. + Double_t fSignalThreshold; + + /// Number of consecutive points over threshold required to accept a signal. + Int_t fPointsOverThreshold; + + Int_t fNPointsFlatThreshold; + + /// A parameter to determine if baseline correction has been applied by a previous process, not used + bool fBaseLineCorrection; + + /// A parameter to determine whether to cut empty events + bool fCutEmptyEvents; + + /// The ADC sampling used to transform ADC units to physical time in the output TRestSignalEvent. Given in + /// us. + Double_t fSampling; + + public: + /// It prints out the process parameters stored in the RESTMetadata structure + void PrintMetadata() { + BeginPrintProcess(); + + RESTMetadata << "Base line range definition : ( " << fBaseLineRange.X() << " , " << fBaseLineRange.Y() + << " ) " << RESTendl; + RESTMetadata << "Integral range : ( " << fIntegralRange.X() << " , " << fIntegralRange.Y() << " ) " + << RESTendl; + RESTMetadata << "Point Threshold : " << fPointThreshold << " sigmas" << RESTendl; + RESTMetadata << "Signal threshold : " << fSignalThreshold << " sigmas" << RESTendl; + RESTMetadata << "Number of points over threshold : " << fPointsOverThreshold << RESTendl; + RESTMetadata << "Sampling rate : " << 1. / fSampling << " MHz" << RESTendl; + RESTMetadata << "Max Number of points of flat signal tail : " << fNPointsFlatThreshold << RESTendl; + RESTMetadata << "Cut empty events : " << (fCutEmptyEvents ? "true" : "false") << RESTendl; + + if (fBaseLineCorrection) + RESTMetadata << "BaseLine correction is enabled for TRestRawSignalAnalysisProcess" << RESTendl; + + EndPrintProcess(); + } + + LegacyProcessDef(TRestSignalZeroSuppresionProcess, TRestRawToDetectorSignalProcess, 4); +}; +#endif diff --git a/src/TRestHitsEvent.cxx b/src/TRestHitsEvent.cxx new file mode 100644 index 0000000..deb274f --- /dev/null +++ b/src/TRestHitsEvent.cxx @@ -0,0 +1,1034 @@ +/************************************************************************* + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * REST is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +/// TRestHitsEvent is a structure that ... +/// +///-------------------------------------------------------------------------- +/// +/// RESTsoft - Software for Rare Event Searches with TPCs +/// +/// History of developments: +/// +/// 2016-March: First implementation of hits event data type into REST_v2. +/// Javier Galan +/// +/// \class TRestHitsEvent +/// \author Javier Galan +/// +///
+/// +#include "TRestHitsEvent.h" + +#include "TCanvas.h" +#include "TRandom.h" +#include "TRestStringHelper.h" +#include "TRestTools.h" +#include "TStyle.h" + +using namespace std; +using namespace TMath; + +ClassImp(TRestHitsEvent); + +/////////////////////////////////////////////// +/// \brief TRestHitsEvent default constructor +/// +/// If no configuration path is defined using TRestMetadata::SetConfigFilePath +/// the path to the config file must be specified using full path, absolute or +/// relative. +/// +/// The default behaviour is that the config file must be specified with +/// full path, absolute or relative. +/// +/// \param cfgFileName A const char* giving the path to an RML file. +/// +TRestHitsEvent::TRestHitsEvent() { + fPad = NULL; + + fXYHitGraph = NULL; + fXZHitGraph = NULL; + fYZHitGraph = NULL; + + fXYHisto = NULL; + fXZHisto = NULL; + fYZHisto = NULL; + + fXZHits = NULL; + fYZHits = NULL; + fXYZHits = NULL; + + fXHisto = NULL; + fYHisto = NULL; + fZHisto = NULL; + + fMinX = -10; + fMaxX = 10; + + fMinY = -10; + fMaxY = 10; + + fMinZ = -10; + fMaxZ = 10; + + RESTWarning << "Creating legacy event TRestHitsEvent" << RESTendl; + RESTWarning << "This event is now named TRestDetectorHitsEvent" << RESTendl; +} + +/////////////////////////////////////////////// +/// \brief TRestHitsEvent default destructor +/// +TRestHitsEvent::~TRestHitsEvent() {} + +/////////////////////////////////////////////// +/// \brief Adds a new hit to this event +/// +/// It adds a new hit with coordinates `x`,`y`,`z` in mm, and energy `en` in keV, to this TRestHitsEvent +/// structure. Additionaly a time delay value in `us` may be added to the hits. +void TRestHitsEvent::AddHit(Double_t x, Double_t y, Double_t z, Double_t en, Double_t t, REST_HitType type) { + fHits.AddHit(x, y, z, en, t, type); +} + +/////////////////////////////////////////////// +/// \brief Adds a new hit to this event +/// +/// It adds a new hit with position `pos` in mm, and energy `en` in keV, to this TRestHitsEvent +/// structure. Additionaly a time delay value in `us` may be added to the hits. +void TRestHitsEvent::AddHit(TVector3 pos, Double_t en, Double_t t, REST_HitType type) { + fHits.AddHit(pos, en, t, type); +} + +/////////////////////////////////////////////// +/// \brief Removes all hits from this event, and clears all auxiliar variables. +/// +void TRestHitsEvent::Initialize() { + TRestEvent::Initialize(); + + fHits.RemoveHits(); + + if (fXZHits) { + delete fXZHits; + fXZHits = NULL; + } + if (fYZHits) { + delete fYZHits; + fYZHits = NULL; + } + if (fXYZHits) { + delete fXYZHits; + fXYZHits = NULL; + } + + fXZHits = new TRestHits(); + fYZHits = new TRestHits(); + fXYZHits = new TRestHits(); + + fMinX = 0; + fMaxX = 0; + fMinY = 0; + fMaxY = 0; + fMinZ = 0; + fMaxZ = 0; +} + +void TRestHitsEvent::Sort(bool(comparecondition)(const TRestHits::iterator& hit1, + const TRestHits::iterator& hit2)) { + if (comparecondition == 0) { + // default sort logic: z from smaller to greater + std::sort(fHits.begin(), fHits.end(), + [](const TRestHits::iterator& hit1, const TRestHits::iterator& hit2) -> bool { + return hit1.z() < hit2.z(); + }); + } else { + std::sort(fHits.begin(), fHits.end(), comparecondition); + } +} + +void TRestHitsEvent::Shuffle(int NLoop) { + Int_t nHits = fHits.GetNumberOfHits(); + if (nHits >= 2) { + for (int n = 0; n < NLoop; n++) { + Int_t hit1 = (Int_t)(nHits * gRandom->Uniform(0, 1)); + Int_t hit2 = (Int_t)(nHits * gRandom->Uniform(0, 1)); + + fHits.SwapHits(hit1, hit2); + } + } +} + +/////////////////////////////////////////////// +/// \brief This method collects all hits which are compatible with a XZ-projected hit. +/// +/// A hit compatible with XZ projection are those hits that have undetermined Y coordinate, +/// and valid X and Z coordinates. +/// +/// \return It returns back a TRestHits structure with the hits fulfilling the XZ condition. +TRestHits* TRestHitsEvent::GetXZHits() { + fXZHits->RemoveHits(); + + for (int i = 0; i < this->GetNumberOfHits(); i++) + if (GetType(i) == XZ) + fXZHits->AddHit(this->GetX(i), this->GetY(i), this->GetZ(i), this->GetEnergy(i), this->GetTime(i), + XZ); + + return fXZHits; +} + +/////////////////////////////////////////////// +/// \brief This method collects all hits which are compatible with a YZ-projected hit. +/// +/// A hit compatible with XZ projection are those hits that have undetermined X coordinate, +/// and valid Y and Z coordinates. +/// +/// \return It returns back a TRestHits structure with the hits fulfilling the XZ condition. +TRestHits* TRestHitsEvent::GetYZHits() { + fYZHits->RemoveHits(); + + for (int i = 0; i < this->GetNumberOfHits(); i++) + if (GetType(i) == YZ) + fYZHits->AddHit(this->GetX(i), this->GetY(i), this->GetZ(i), this->GetEnergy(i), this->GetTime(i), + YZ); + + return fYZHits; +} + +/////////////////////////////////////////////// +/// \brief This method collects all hits which are compatible with a XYZ hit. +/// +/// A XYZ hit compatible are those hits that have valid X, Y and Z coordinates. +/// +/// \return It returns back a TRestHits structure with the hits fulfilling the XYZ condition. +TRestHits* TRestHitsEvent::GetXYZHits() { + fXYZHits->RemoveHits(); + + for (int i = 0; i < this->GetNumberOfHits(); i++) + if (GetType(i) == XYZ) + fXYZHits->AddHit(this->GetX(i), this->GetY(i), this->GetZ(i), this->GetEnergy(i), + this->GetTime(i), XYZ); + + return fXYZHits; +} + +/////////////////////////////////////////////// +/// \brief This method returns true if at least 1 hit is found inside the cylinder volume given by argument. +/// +/// \param x0 The center of the bottom face of the cylinder. +/// \param x1 The center of the top face of the cylinder. +/// \param radius The radius of the cylinder. +/// +Bool_t TRestHitsEvent::anyHitInsideCylinder(TVector3 x0, TVector3 x1, Double_t radius) { + if (fHits.GetNumberOfHitsInsideCylinder(x0, x1, radius) > 0) return true; + + return false; +} + +/////////////////////////////////////////////// +/// \brief This method returns true if all hits are containned inside the cylinder volume given by argument. +/// +/// \param x0 The center of the bottom face of the cylinder. +/// \param x1 The center of the top face of the cylinder. +/// \param radius The radius of the cylinder. +/// +Bool_t TRestHitsEvent::allHitsInsideCylinder(TVector3 x0, TVector3 x1, Double_t radius) { + if (fHits.GetNumberOfHitsInsideCylinder(x0, x1, radius) == GetNumberOfHits()) return true; + + return false; +} + +/////////////////////////////////////////////// +/// \brief This method returns the total integrated energy of all hits found inside the cylinder volume given +/// by argument. +/// +/// \param x0 The center of the bottom face of the cylinder. +/// \param x1 The center of the top face of the cylinder. +/// \param radius The radius of the cylinder. +/// +Double_t TRestHitsEvent::GetEnergyInCylinder(TVector3 x0, TVector3 x1, Double_t radius) { + return fHits.GetEnergyInCylinder(x0, x1, radius); +} + +/////////////////////////////////////////////// +/// \brief This method returns the total number hits found inside the cylinder volume given +/// by argument. +/// +/// \param x0 The center of the bottom face of the cylinder. +/// \param x1 The center of the top face of the cylinder. +/// \param radius The radius of the cylinder. +/// +Int_t TRestHitsEvent::GetNumberOfHitsInsideCylinder(TVector3 x0, TVector3 x1, Double_t radius) { + return fHits.GetNumberOfHitsInsideCylinder(x0, x1, radius); +} + +/////////////////////////////////////////////// +/// \brief This method returns the mean position of the hits found inside the cylinder volume given +/// by argument. +/// +/// \param x0 The center of the bottom face of the cylinder. +/// \param x1 The center of the top face of the cylinder. +/// \param radius The radius of the cylinder. +/// +TVector3 TRestHitsEvent::GetMeanPositionInCylinder(TVector3 x0, TVector3 x1, Double_t radius) { + return fHits.GetMeanPositionInCylinder(x0, x1, radius); +} + +/////////////////////////////////////////////// +/// \brief This method returns true if at least 1 hit is found inside the prism volume given by argument. +/// +/// \param x0 The center of the bottom face of the prism. +/// \param x1 The center of the top face of the prism. +/// \param sizeX Size of the side X of the prism face. +/// \param sizeY Size of the side X of the prism face. +/// \param theta An angle in radians to rotate the face of the prism. +/// +Bool_t TRestHitsEvent::anyHitInsidePrism(TVector3 x0, TVector3 x1, Double_t sizeX, Double_t sizeY, + Double_t theta) { + if (fHits.GetNumberOfHitsInsidePrism(x0, x1, sizeX, sizeY, theta) > 0) return true; + + return false; +} + +/////////////////////////////////////////////// +/// \brief This method returns true if all hits are found inside the prism volume given by argument. +/// +/// \param x0 The center of the bottom face of the prism. +/// \param x1 The center of the top face of the prism. +/// \param sizeX Size of the side X of the prism face. +/// \param sizeY Size of the side X of the prism face. +/// \param theta An angle in radians to rotate the face of the prism. +/// +Bool_t TRestHitsEvent::allHitsInsidePrism(TVector3 x0, TVector3 x1, Double_t sizeX, Double_t sizeY, + Double_t theta) { + if (fHits.GetNumberOfHitsInsidePrism(x0, x1, sizeX, sizeY, theta) == GetNumberOfHits()) return true; + + return false; +} + +/////////////////////////////////////////////// +/// \brief This method returns the total integrated energy of all hits found inside the prism volume given +/// by argument. +/// +/// \param x0 The center of the bottom face of the prism. +/// \param x1 The center of the top face of the prism. +/// \param sizeX Size of the side X of the prism face. +/// \param sizeY Size of the side X of the prism face. +/// \param theta An angle in radians to rotate the face of the prism. +/// +Double_t TRestHitsEvent::GetEnergyInPrism(TVector3 x0, TVector3 x1, Double_t sizeX, Double_t sizeY, + Double_t theta) { + return fHits.GetEnergyInPrism(x0, x1, sizeX, sizeY, theta); +} + +/////////////////////////////////////////////// +/// \brief This method returns the total number of hits found inside the prism volume given +/// by argument. +/// +/// \param x0 The center of the bottom face of the prism. +/// \param x1 The center of the top face of the prism. +/// \param sizeX Size of the side X of the prism face. +/// \param sizeY Size of the side X of the prism face. +/// \param theta An angle in radians to rotate the face of the prism. +/// +Int_t TRestHitsEvent::GetNumberOfHitsInsidePrism(TVector3 x0, TVector3 x1, Double_t sizeX, Double_t sizeY, + Double_t theta) { + return fHits.GetNumberOfHitsInsidePrism(x0, x1, sizeX, sizeY, theta); +} + +/////////////////////////////////////////////// +/// \brief This method returns the mean position of all hits found inside the prism volume given +/// by argument. +/// +/// \param x0 The center of the bottom face of the prism. +/// \param x1 The center of the top face of the prism. +/// \param sizeX Size of the side X of the prism face. +/// \param sizeY Size of the side X of the prism face. +/// \param theta An angle in radians to rotate the face of the prism. +/// +TVector3 TRestHitsEvent::GetMeanPositionInPrism(TVector3 x0, TVector3 x1, Double_t sizeX, Double_t sizeY, + Double_t theta) { + return fHits.GetMeanPositionInPrism(x0, x1, sizeX, sizeY, theta); +} + +/////////////////////////////////////////////// +/// \brief This method returns the distance to the cylinder wall from the closest hit containned inside the +/// cylinder volume given by argument. +/// +/// \param x0 The center of the bottom face of the cylinder. +/// \param x1 The center of the top face of the cylinder. +/// \param radius The radius of the cylinder. +/// +/// \return If no hit is found inside the cylinder, -1 is returned. +/// +Double_t TRestHitsEvent::GetClosestHitInsideDistanceToCylinderWall(TVector3 x0, TVector3 x1, + Double_t radius) { + Double_t rad2 = radius * radius; + Double_t hitDistance = rad2; + + Double_t d2, l; + + TVector3 axis = x1 - x0; + Double_t cylLength = axis.Mag(); + + Int_t nhits = 0; + for (int n = 0; n < GetNumberOfHits(); n++) { + if (fHits.isHitNInsideCylinder(n, x0, x1, radius)) { + l = axis.Dot(this->GetPosition(n) - x0) / cylLength; + + d2 = rad2 - (this->GetPosition(n) - x0).Mag2() + l * l; + + if (d2 < hitDistance) hitDistance = d2; + + nhits++; + } + } + + if (nhits == 0) return -1; + + return TMath::Sqrt(hitDistance); +} + +/////////////////////////////////////////////// +/// \brief This method returns the distance to the cylinder **top** face from the closest hit containned +/// inside the cylinder volume given by argument. +/// +/// \param x0 The center of the bottom face of the cylinder. +/// \param x1 The center of the top face of the cylinder. +/// \param radius The radius of the cylinder. +/// +/// \return If no hit is found inside the cylinder, -1 is returned. +/// +Double_t TRestHitsEvent::GetClosestHitInsideDistanceToCylinderTop(TVector3 x0, TVector3 x1, Double_t radius) { + TVector3 axis = x1 - x0; + Double_t cylLength = axis.Mag(); + + Double_t hitDistance = cylLength; + Double_t d = cylLength; + + Int_t nhits = 0; + for (int n = 0; n < GetNumberOfHits(); n++) { + if (fHits.isHitNInsideCylinder(n, x0, x1, radius)) { + d = cylLength - axis.Dot(this->GetPosition(n) - x0) / cylLength; + + if (d < hitDistance) hitDistance = d; + + nhits++; + } + } + + if (nhits == 0) return -1; + + return hitDistance; +} + +/////////////////////////////////////////////// +/// \brief This method returns the distance to the cylinder **bottom** face from the closest hit containned +/// inside the cylinder volume given by argument. +/// +/// \param x0 The center of the bottom face of the cylinder. +/// \param x1 The center of the top face of the cylinder. +/// \param radius The radius of the cylinder. +/// +/// \return If no hit is found inside the cylinder, -1 is returned. +/// +Double_t TRestHitsEvent::GetClosestHitInsideDistanceToCylinderBottom(TVector3 x0, TVector3 x1, + Double_t radius) { + TVector3 axis = x1 - x0; + Double_t cylLength = axis.Mag(); + + Double_t hitDistance = cylLength; + Double_t d = cylLength; + + Int_t nhits = 0; + for (int n = 0; n < GetNumberOfHits(); n++) { + if (fHits.isHitNInsideCylinder(n, x0, x1, radius)) { + d = axis.Dot(this->GetPosition(n) - x0) / cylLength; + + if (d < hitDistance) hitDistance = d; + + nhits++; + } + } + + if (nhits == 0) return -1; + + return hitDistance; +} + +/////////////////////////////////////////////// +/// \brief This method returns the distance to the prism **wall** from the closest hit containned +/// inside the prism volume given by argument. +/// +/// \param x0 The center of the bottom face of the prism. +/// \param x1 The center of the top face of the prism. +/// \param sizeX Size of the side X of the prism face. +/// \param sizeY Size of the side X of the prism face. +/// \param theta An angle in radians to rotate the face of the prism. +/// +/// \return If no hit is found inside the prism, -1 is returned. +/// +Double_t TRestHitsEvent::GetClosestHitInsideDistanceToPrismWall(TVector3 x0, TVector3 x1, Double_t sizeX, + Double_t sizeY, Double_t theta) { + Double_t dX = sizeX / 2; + Double_t dY = sizeY / 2; + + Double_t hitDistance = max(dX, dY); + + Double_t d; + Int_t nhits = 0; + for (int n = 0; n < GetNumberOfHits(); n++) { + if (fHits.isHitNInsidePrism(n, x0, x1, sizeX, sizeY, theta)) { + dX = sizeX / 2 - TMath::Abs((this->GetPosition(n) - x0).X()); + dY = sizeY / 2 - TMath::Abs((this->GetPosition(n) - x0).Y()); + + d = min(dX, dY); + + if (d < hitDistance) hitDistance = d; + + nhits++; + } + } + + if (nhits == 0) return -1; + + return hitDistance; +} + +/////////////////////////////////////////////// +/// \brief This method returns the distance to the prism **top** face from the closest hit containned +/// inside the prism volume given by argument. +/// +/// \param x0 The center of the bottom face of the prism. +/// \param x1 The center of the top face of the prism. +/// \param sizeX Size of the side X of the prism face. +/// \param sizeY Size of the side X of the prism face. +/// \param theta An angle in radians to rotate the face of the prism. +/// +/// \return If no hit is found inside the prism, -1 is returned. +/// +Double_t TRestHitsEvent::GetClosestHitInsideDistanceToPrismTop(TVector3 x0, TVector3 x1, Double_t sizeX, + Double_t sizeY, Double_t theta) { + TVector3 axis = x1 - x0; + Double_t prismLength = axis.Mag(); + + Double_t hitDistance = prismLength; + + Double_t d; + Int_t nhits = 0; + for (int n = 0; n < GetNumberOfHits(); n++) { + if (fHits.isHitNInsidePrism(n, x0, x1, sizeX, sizeY, theta)) { + d = prismLength - axis.Dot(this->GetPosition(n) - x0) / prismLength; + + if (d < hitDistance) hitDistance = d; + + nhits++; + } + } + + if (nhits == 0) return -1; + + return hitDistance; +} + +/////////////////////////////////////////////// +/// \brief This method returns the distance to the prism **bottom** face from the closest hit containned +/// inside the prism volume given by argument. +/// +/// \param x0 The center of the bottom face of the prism. +/// \param x1 The center of the top face of the prism. +/// \param sizeX Size of the side X of the prism face. +/// \param sizeY Size of the side X of the prism face. +/// \param theta An angle in radians to rotate the face of the prism. +/// +/// \return If no hit is found inside the prism, -1 is returned. +/// +Double_t TRestHitsEvent::GetClosestHitInsideDistanceToPrismBottom(TVector3 x0, TVector3 x1, Double_t sizeX, + Double_t sizeY, Double_t theta) { + TVector3 axis = x1 - x0; + Double_t prismLength = axis.Mag(); + + Double_t hitDistance = prismLength; + + Double_t d; + Int_t nhits = 0; + for (int n = 0; n < GetNumberOfHits(); n++) { + if (fHits.isHitNInsidePrism(n, x0, x1, sizeX, sizeY, theta)) { + d = axis.Dot(this->GetPosition(n) - x0) / prismLength; + + if (d < hitDistance) hitDistance = d; + + nhits++; + } + } + + if (nhits == 0) return -1; + + return hitDistance; +} + +Double_t TRestHitsEvent::CalculateTotalDepositedEnergy() { + Double_t sum = 0; + for (int i = 0; i < GetNumberOfHits(); i++) sum += GetEnergy(i); + fHits.fTotEnergy = sum; + return sum; +} + +/////////////////////////////////////////////// +/// \brief This method draws the hits event structure into a TPad. +/// +/// This method receives as argument a string that defines the different plots to be produced. +/// +/// The following options are allowed: +/// +/// * **graph**: +/// * **hist**: +/// * **print**: +/// +/// The different options must separated by colons, as "option1:option2:option3". +/// +/// +/// \return A pointer to the TPad where the event was drawn is returned. +/// +TPad* TRestHitsEvent::DrawEvent(const TString& option) { + vector optList = Vector_cast(TRestTools::GetOptions((string)option)); + + SetBoundaries(); + + for (unsigned int n = 0; n < optList.size(); n++) { + if (optList[n] == "print") this->PrintEvent(); + } + + optList.erase(std::remove(optList.begin(), optList.end(), "print"), optList.end()); + + if (optList.size() == 0) optList.push_back("graph2d"); + + if (fPad != NULL) { + delete fPad; + fPad = NULL; + } + + fPad = new TPad(this->GetName(), " ", 0, 0, 1, 1); + fPad->Divide(3, 2 * optList.size()); + fPad->Draw(); + + Int_t column = 0; + for (unsigned int n = 0; n < optList.size(); n++) { + string optionStr = (string)optList[n]; + TString drawEventOption = optList[n]; + + // Generating drawOption argument + size_t startPos = optionStr.find("("); + if (startPos != string::npos) drawEventOption = optList[n](0, startPos); + + // Generating histogram option argument + string histOption = ""; + size_t endPos = optionStr.find(")"); + if (endPos != string::npos) { + TString histOptionTmp = optList[n](startPos + 1, endPos - startPos - 1); + + histOption = (string)histOptionTmp; + size_t pos = 0; + while ((pos = histOption.find(",", pos)) != string::npos) { + histOption.replace(pos, 1, ":"); + pos = pos + 1; + } + } + + // Generating histogram pitch argument + string pitchOption = ""; + + startPos = optionStr.find("["); + endPos = optionStr.find("]"); + Double_t pitch = 3; + if (endPos != string::npos) { + TString pitchOption = optList[n](startPos + 1, endPos - startPos - 1); + pitch = stod((string)pitchOption); + } + + if (drawEventOption == "graph") this->DrawGraphs(column); + + if (drawEventOption == "graph2d") this->DrawGraph2D(); + + if (drawEventOption == "hist") this->DrawHistograms(column, pitch, histOption); + } + + return fPad; +} + +void TRestHitsEvent::SetBoundaries() { + Double_t maxX = -1e10, minX = 1e10, maxZ = -1e10, minZ = 1e10, maxY = -1e10, minY = 1e10; + + for (int nhit = 0; nhit < this->GetNumberOfHits(); nhit++) { + Double_t x = fHits.GetX(nhit); + Double_t y = fHits.GetY(nhit); + Double_t z = fHits.GetZ(nhit); + + if (x > maxX) maxX = x; + if (x < minX) minX = x; + if (y > maxY) maxY = y; + if (y < minY) minY = y; + if (z > maxZ) maxZ = z; + if (z < minZ) minZ = z; + } + + fMinX = minX; + fMaxX = maxX; + + fMinY = minY; + fMaxY = maxY; + + fMinZ = minZ; + fMaxZ = maxZ; +} + +void TRestHitsEvent::DrawGraphs(Int_t& column) { + if (fXYHitGraph != NULL) { + delete fXYHitGraph; + fXYHitGraph = NULL; + } + if (fXZHitGraph != NULL) { + delete fXZHitGraph; + fXZHitGraph = NULL; + } + if (fYZHitGraph != NULL) { + delete fYZHitGraph; + fYZHitGraph = NULL; + } + + vector> xz(2, vector(this->GetNumberOfHits())); + vector> yz(2, vector(this->GetNumberOfHits())); + vector> xy(2, vector(this->GetNumberOfHits())); + + /* {{{ Creating xz, yz, and xy arrays and initializing graphs */ + Int_t nXZ = 0; + Int_t nYZ = 0; + Int_t nXY = 0; + + for (int nhit = 0; nhit < this->GetNumberOfHits(); nhit++) { + Double_t x = fHits.GetX(nhit); + Double_t y = fHits.GetY(nhit); + Double_t z = fHits.GetZ(nhit); + int type = fHits.GetType(nhit); + + if (type % XZ == 0) { + xz[0][nXZ] = x; + xz[1][nXZ] = z; + nXZ++; + } + + if (type % YZ == 0) { + yz[0][nYZ] = y; + yz[1][nYZ] = z; + nYZ++; + } + + if (type % XY == 0) { + xy[0][nXY] = x; + xy[1][nXY] = y; + nXY++; + } + } + + fXZHitGraph = new TGraph(nXZ, &xz[0][0], &xz[1][0]); + fXZHitGraph->SetMarkerColor(kBlue); + fXZHitGraph->SetMarkerSize(0.3); + fXZHitGraph->SetMarkerStyle(20); + + fYZHitGraph = new TGraph(nYZ, &yz[0][0], &yz[1][0]); + fYZHitGraph->SetMarkerColor(kRed); + fYZHitGraph->SetMarkerSize(0.3); + fYZHitGraph->SetMarkerStyle(20); + + fXYHitGraph = new TGraph(nXY, &xy[0][0], &xy[1][0]); + fXYHitGraph->SetMarkerColor(kBlack); + fXYHitGraph->SetMarkerSize(0.3); + fXYHitGraph->SetMarkerStyle(20); + /* }}} */ + + char title[256]; + sprintf(title, "Event ID %d", this->GetID()); + + if (nXZ > 0) { + fPad->cd(1 + 3 * column); + fXZHitGraph->SetTitle(title); + fXZHitGraph->Draw("AP*"); + + fXZHitGraph->GetXaxis()->SetTitle("X-axis (mm)"); + fXZHitGraph->GetYaxis()->SetTitle("Z-axis (mm)"); + } + + if (nYZ > 0) { + fPad->cd(2 + 3 * column); + fYZHitGraph->SetTitle(title); + fYZHitGraph->Draw("AP"); + + fYZHitGraph->GetXaxis()->SetTitle("Y-axis (mm)"); + fYZHitGraph->GetYaxis()->SetTitle("Z-axis (mm)"); + } + + if (nXY > 0) { + fPad->cd(3 + 3 * column); + fXYHitGraph->SetTitle(title); + fXYHitGraph->Draw("AP"); + + fXYHitGraph->GetXaxis()->SetTitle("X-axis (mm)"); + fXYHitGraph->GetYaxis()->SetTitle("Y-axis (mm)"); + } + + column++; +} + +void TRestHitsEvent::DrawGraph2D() { + if (gxz != NULL) { + delete gxz; + gxz = NULL; + } + if (gyz != NULL) { + delete gyz; + gyz = NULL; + } + + // prepare signal data + vector _xzx; + vector _xzz; + vector _xze; + vector _yzy; + vector _yzz; + vector _yze; + + for (auto hit : fHits) { + if (hit.type() == XZ) { + _xzx.push_back(hit.x()); + _xze.push_back(hit.e()); + _xzz.push_back(hit.z()); + } + if (hit.type() == YZ) { + _yzy.push_back(hit.y()); + _yze.push_back(hit.e()); + _yzz.push_back(hit.z()); + } + } + + // cout << _xzz.size() << " " << _yzz.size() << endl; + + // double max = _xzx.size() > 0 ? *max_element(begin(_xzx), end(_xzx)) + 3 : 3; + // double min = _xzx.size() > 0 ? *min_element(begin(_xzx), end(_xzx)) - 3 : -3; + // for (int j = 0; j < fNz; j++) { + // _xzx.push_back(max); + // _xze.push_back(0); + // _xzz.push_back(-j); + // _xzx.push_back(min); + // _xze.push_back(0); + // _xzz.push_back(-j); + //} + + // max = _yzy.size() > 0 ? *max_element(begin(_yzy), end(_yzy)) + 3 : 3; + // min = _yzy.size() > 0 ? *min_element(begin(_yzy), end(_yzy)) - 3 : -3; + // for (int j = 0; j < fNz; j++) { + // _yzy.push_back(max); + // _yze.push_back(0); + // _yzz.push_back(-j); + // _yzy.push_back(min); + // _yze.push_back(0); + // _yzz.push_back(-j); + //} + + gxz = new TGraph2D("gxz", "gxz", _xzz.size(), &_xzx[0], &_xzz[0], &_xze[0]); + gxz->SetTitle((TString) "XZ plot, " + ToString(GetNumberOfHitsX()) + " Signals"); + gxz->GetXaxis()->SetTitle("X"); + gxz->GetYaxis()->SetTitle("Z"); + gxz->SetNpx(100); + gxz->SetNpy(500); + + gyz = new TGraph2D("gyz", "gyz", _yzz.size(), &_yzy[0], &_yzz[0], &_yze[0]); + gyz->SetTitle((TString) "YZ plot, " + ToString(GetNumberOfHitsY()) + " Signals"); + gyz->GetXaxis()->SetTitle("Y"); + gyz->GetYaxis()->SetTitle("Z"); + gyz->SetNpx(100); + gyz->SetNpy(500); + + // fPad->Divide(2, 1); + + auto pad = fPad->cd(1); + pad->SetRightMargin(0.15); + if (gxz != NULL) gxz->Draw("colz"); + + pad = fPad->cd(2); + pad->SetLeftMargin(0); + pad->SetRightMargin(0.15); + if (gyz != NULL) gyz->Draw("colz"); +} + +void TRestHitsEvent::DrawHistograms(Int_t& column, Double_t pitch, TString histOption) { + if (fXYHisto != NULL) { + delete fXYHisto; + fXYHisto = NULL; + } + if (fXZHisto != NULL) { + delete fXZHisto; + fXZHisto = NULL; + } + if (fYZHisto != NULL) { + delete fYZHisto; + fYZHisto = NULL; + } + + if (fXHisto != NULL) { + delete fXHisto; + fXHisto = NULL; + } + if (fYHisto != NULL) { + delete fYHisto; + fYHisto = NULL; + } + if (fZHisto != NULL) { + delete fZHisto; + fZHisto = NULL; + } + + Int_t nBinsX = (fMaxX - fMinX + 20) / pitch; + Int_t nBinsY = (fMaxY - fMinY + 20) / pitch; + Int_t nBinsZ = (fMaxZ - fMinZ + 20) * 3 / pitch; + + fXYHisto = new TH2F("XY", "", nBinsX, fMinX - 10, fMinX + pitch * nBinsX, nBinsY, fMinY - 10, + fMinY + pitch * nBinsY); + fXZHisto = new TH2F("XZ", "", nBinsX, fMinX - 10, fMinX + pitch * nBinsX, nBinsZ, fMinZ - 10, + fMinZ + (pitch / 3) * nBinsZ); + fYZHisto = new TH2F("YZ", "", nBinsY, fMinY - 10, fMinY + pitch * nBinsY, nBinsZ, fMinZ - 10, + fMinZ + (pitch / 3) * nBinsZ); + + fXHisto = new TH1F("X", "", nBinsX, fMinX - 10, fMinX + pitch * nBinsX); + fYHisto = new TH1F("Y", "", nBinsY, fMinY - 10, fMinY + pitch * nBinsY); + fZHisto = new TH1F("Z", "", nBinsZ, fMinZ - 10, fMinZ + pitch * nBinsZ); + + Int_t nYZ = 0, nXZ = 0, nXY = 0; + Int_t nX = 0, nY = 0, nZ = 0; + + for (int nhit = 0; nhit < this->GetNumberOfHits(); nhit++) { + Double_t x = fHits.GetX(nhit); + Double_t y = fHits.GetY(nhit); + Double_t z = fHits.GetZ(nhit); + int type = fHits.GetType(nhit); + + if (type % XZ == 0) { + fXZHisto->Fill(x, z); + nXZ++; + } + + if (type % YZ == 0) { + fYZHisto->Fill(y, z); + nYZ++; + } + + if (type % XY == 0) { + fXYHisto->Fill(x, y); + nXY++; + } + + if (type % X == 0) { + fXHisto->Fill(x); + nX++; + } + + if (type % Y == 0) { + fYHisto->Fill(y); + nY++; + } + + if (type % Z == 0) { + fZHisto->Fill(z); + nZ++; + } + } + + TStyle style; + style.SetPalette(1); + + if (nXZ > 0) { + fPad->cd(1 + 3 * column); + fXZHisto->Draw(histOption); + fXZHisto->GetXaxis()->SetTitle("X-axis (mm)"); + fXZHisto->GetYaxis()->SetTitle("Z-axis (mm)"); + fXZHisto->GetYaxis()->SetTitleSize(1.4 * fXZHisto->GetYaxis()->GetTitleSize()); + fXZHisto->GetXaxis()->SetTitleSize(1.4 * fXZHisto->GetXaxis()->GetTitleSize()); + fXZHisto->GetYaxis()->SetLabelSize(1.25 * fXZHisto->GetYaxis()->GetLabelSize()); + fXZHisto->GetXaxis()->SetLabelSize(1.25 * fXZHisto->GetXaxis()->GetLabelSize()); + fXZHisto->GetYaxis()->SetTitleOffset(1.75); + } + + if (nYZ > 0) { + fPad->cd(2 + 3 * column); + fYZHisto->Draw(histOption); + fYZHisto->GetXaxis()->SetTitle("Y-axis (mm)"); + fYZHisto->GetYaxis()->SetTitle("Z-axis (mm)"); + fYZHisto->GetYaxis()->SetTitleSize(1.4 * fYZHisto->GetYaxis()->GetTitleSize()); + fYZHisto->GetXaxis()->SetTitleSize(1.4 * fYZHisto->GetXaxis()->GetTitleSize()); + fYZHisto->GetYaxis()->SetLabelSize(1.25 * fYZHisto->GetYaxis()->GetLabelSize()); + fYZHisto->GetXaxis()->SetLabelSize(1.25 * fYZHisto->GetXaxis()->GetLabelSize()); + fYZHisto->GetYaxis()->SetTitleOffset(1.75); + } + + if (nXY > 0) { + fPad->cd(3 + 3 * column); + fXYHisto->Draw(histOption); + fXYHisto->GetXaxis()->SetTitle("X-axis (mm)"); + fXYHisto->GetYaxis()->SetTitle("Y-axis (mm)"); + } + + column++; + + if (nX > 0) { + fPad->cd(1 + 3 * column); + fXHisto->Draw(histOption); + fXHisto->GetXaxis()->SetTitle("X-axis (mm)"); + fXHisto->GetYaxis()->SetTitle("Number of events"); + } + + if (nY > 0) { + fPad->cd(2 + 3 * column); + fYHisto->Draw(histOption); + fYHisto->GetYaxis()->SetTitle("Y-axis (mm)"); + fYHisto->GetYaxis()->SetTitle("Number of events"); + } + + if (nZ > 0) { + fPad->cd(3 + 3 * column); + fZHisto->Draw(histOption); + fZHisto->GetZaxis()->SetTitle("Z-axis (mm)"); + fZHisto->GetYaxis()->SetTitle("Number of events"); + } + + column++; +} + +void TRestHitsEvent::PrintEvent(Int_t nHits) { + TRestEvent::PrintEvent(); + + cout << "Total energy : " << GetTotalDepositedEnergy() << endl; + cout << "Mean position : ( " << GetMeanPositionX() << " , " << GetMeanPositionY() << " , " + << GetMeanPositionZ() << " ) " << endl; + cout << "Number of hits : " << fHits.GetNumberOfHits() << endl; + if (nHits != -1) { + cout << "+++++++++++++++++++++++" << endl; + cout << "Printing only the first " << nHits << " hits" << endl; + } + + fHits.PrintHits(nHits); +} diff --git a/src/TRestReadout.cxx b/src/TRestReadout.cxx new file mode 100644 index 0000000..b6944be --- /dev/null +++ b/src/TRestReadout.cxx @@ -0,0 +1,997 @@ +/************************************************************************* + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * REST is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +/// +/// This is the main RESTMetadata readout class of REST. The readout class +/// defines the methods allowing to stablish a relation between the hits +/// inside the TPC and the signals read out by the electronics daq. +/// +/// A full readout description is composed by at least one readout plane, +/// (TRestReadoutPlane), where we can place any number of readout modules +/// (TRestReadoutModule). A readout module is composed by readout channels +/// (TRestReadoutChannel) which describe the basic active detection area, +/// which can take any complex shape by combinning primitive geometry +/// elements (TRestReadoutPixel). +/// +/// REST processes such as TRestSignalToHitsProcess and +/// TRestHitsToSignalProcess use the TRestReadout class to transform the +/// spatial coordinates into raw signal data, and viceversa. +/// +/// ### Constructing the readout through an RML file +/// +/// The readout definition must be initialized through a RML file. The +/// basic RESTMetadata structure of a readout follows this scheme +/// +/// \code +///
+/// +/// +/// +/// // First, we need to construct the different readout modules we will +/// // use inside the readout plane definition. +/// +/// +/// // Later, when we construct the readout plane we will use "modName" +/// // to add the module to the readout plane definition. +/// +/// +/// +/// +/// ... +/// // Add as many pixel definitions as needed to create the channel +/// definition +/// ... +/// +/// +/// // And add as many readout channels as need to construct your +/// readout module +/// ... +/// ... +/// +/// +/// // The id number given to the readout channel is the physical +/// readout +/// // channel used inside the decoding. +/// +/// ... +/// ... +/// +/// +/// +/// +/// // If your readout is composed by modules with different size or channel +/// topologies, +/// // you will need add additional definitions here. +/// +/// // The readout plane allows to define the position, the orientation +/// (planeVector), +/// // and the position of the cathode that will define the detector active +/// volume. +/// +/// // We can then insert the modules inside each readout plane +/// // Offset +/// introduced to the daq signal channel inside the +/// decoding file. +/// +/// +/// +/// ... +/// +/// // Add as many modules as needed to construct your readout. +/// +/// +/// // If needed you may add any additional readout layers to your +/// definition adding new +/// // readout plane definitions here. +/// +/// +///
+/// \endcode +/// +/// +/// The *mappingNodes* parameter allows to specify the size of the virtual grid +/// that will be used to map the readout. The mapping allows to speed up the +/// process finding a pixel inside a module for a given x,y coordinates. +/// In general, the number of mapping nodes should be high enough so that every +/// pixel from any readout channel is associated to, or contains, a node in the +/// grid. However, as higher is the number of nodes in the mapping grid, higher +/// will be the required computation time to find a pixel for a given x,y +/// coordinates. If this value is not defined REST will try to find an optimum +/// value for this parameter. Therefore, it is recommended to do not specify +/// this parameter, except for solving readout problems or optimization +/// purposes. +/// +/// ### The decoding +/// +/// The relation between the channel number imposed by the electronic +/// acquisition and the readout channel id defined inside *readoutChannel* is +/// given to TRestReadout through a decoding file. +/// +/// The *decodingFile* parameter inside each module added to the readout plane +/// allows to set the filename (in the code above, *module.dec*) of a file +/// used to define the relation between the physical readout *id* defined +/// at each readout channel, as +/// and the daq channel number defined at the acquisition system. +/// If *no decoding* file is defined the relation between daq and readout +/// channel is assigned *one to one*. +/// The decoding file must be a text file definning two columns with as +/// many columns as the number of channels defined in the readout module. +/// The first column is the daq channel number, and the second column is +/// the readout channel defined in the RML file. +/// +/// An example of contents of a decoding file. Here 0, 1, 2, 3, ... are +/// the physical readout channels corresponding to the daq channels 67, +/// 65, 63, 61, ... +/// +/// \code +/// 67 0 +/// 65 1 +/// 63 2 +/// 61 3 +/// 59 4 +/// 57 5 +/// 54 6 +/// ... +/// ... +/// \endcode +/// +/// The channel number defined on the left column will be shifted by the +/// value *firstDaqChannel* defined when adding the readout module to the +/// readout plane. This may allow to re-use a decoding file for different +/// readout modules in case we have a repetitive connection pattern. +/// +/// ### Using the readout class +/// +/// Once TRestReadout has been initialized, through and RML file or a +/// previously stored TRestReadout class stored in a ROOT file, +/// we can find the corresponding xy-position for a given readout channel +/// id, module id, and readout plane, or the corresponding coordinates for +/// a given channel inside a module containned in a readout plane. +/// +/// The following code shows how we can identify the readout plane +/// (*planeId*), the readout module (*moduleId*), and the readout channel +/// (*chanId*) for a given x,y,z coordinates. +/// +/// \code +/// for( int p = 0; p < fReadout->GetNumberOfReadoutPlanes(); p++ ) +/// { +/// // We check if the xyz coordinates are in the volume defined by +/// the readout plane modId = +/// fReadout->GetReadoutPlane(p)->isInsideDriftVolume( x, y, z ); +/// +/// // If the hit is containned in the readout, the last function +/// returns the id of the +/// // readout module that contains the x,y coordinates. +/// if( modId >= 0 ) +/// { +/// // We found the hit at planeId +/// planeId = p; +/// +/// // Then we obtain the readoutChannel *id* as defined in the +/// readout. Int_t chanId = fReadout->GetReadoutPlane( p +/// )->FindChannel( modId, x, y ); +/// +/// break; +/// } +/// } +/// \endcode +/// +/// Once we found the readout channel, we can obtain the associated daq +/// channel number, that was defined using the decoding file. +/// +/// \code +/// Int_t daqId = fReadout->GetReadoutPlane( planeId ) +/// ->GetModule( modId ) +/// ->GetChannel( chanId )->GetDaqID( ); +/// \endcode +/// +/// The other way around we can obtain the corresponding x and y coordinates for +/// a given daq channel id. The following code shows the basic idea to find +/// *signalId*. +/// +/// \code +/// for( int p = 0; p < fReadout->GetNumberOfReadoutPlanes(); p++ ) +/// { +/// TRestReadoutPlane *plane = fReadout->GetReadoutPlane( p ); +/// for( int m = 0; m < plane->GetNumberOfModules(); m++ ) +/// { +/// TRestReadoutModule *mod = plane->GetModule( m ); +/// +/// // We iterate over all readout modules searching for the one +/// that contains our signal id if( mod->isDaqIDInside( signalID +/// ) ) +/// { +/// // If we find it we use the readoutModule id, and the +/// signalId corresponding +/// // to the physical readout channel and obtain the x,y +/// coordinates. +/// +/// readoutChannelID = mod->DaqToReadoutChannel( signalID ); +/// readoutModuleID = mod->GetModuleID(); +/// +/// x = plane->GetX( readoutModuleID, readoutChannelID ); +/// y = plane->GetY( readoutModuleID, readoutChannelID ); +/// break; +/// } +/// } +/// } +/// \endcode +///-------------------------------------------------------------------------- +/// +/// RESTsoft - Software for Rare Event Searches with TPCs +/// +/// History of developments: +/// +/// 2015-aug: First concept. +/// Javier Galan +/// +/// \class TRestReadout +/// \author Javier Galan +/// +///
+/// +/// + +#include "TRestReadout.h" +using namespace std; +bool RESTREADOUT_DECODINGFILE_ERROR = false; + +ClassImp(TRestReadout); +/////////////////////////////////////////////// +/// \brief TRestReadout default constructor +/// +TRestReadout::TRestReadout() { + RESTWarning << "Creating legacy metadata TRestReadout" << RESTendl; + RESTWarning << "This class is now implemented under TRestDetectorReadout" << RESTendl; + Initialize(); +} + +/////////////////////////////////////////////// +/// \brief TRestReadout constructor loading data from a config file +/// +/// If no configuration path was defined using TRestMetadata::SetConfigFilePath +/// the path to the config file must be specified using full path, absolute or +/// relative. +/// +/// By default the config file must be specified with full path, absolute or +/// relative. +/// +/// First TRestReadout section occurrence will be loaded. +/// +/// \param cfgFileName A const char* giving the path to an RML file. +/// +TRestReadout::TRestReadout(const char* cfgFileName) : TRestMetadata(cfgFileName) { + cout << "Loading readout. This might take few seconds" << endl; + RESTWarning << "Creating legacy metadata TRestReadout" << RESTendl; + RESTWarning << "This class is now implemented under TRestDetectorReadout" << RESTendl; + Initialize(); + + LoadConfigFromFile(fConfigFileName); +} + +/////////////////////////////////////////////// +/// \brief TRestReadout constructor loading data from a config file +/// +/// If no configuration path was defined using TRestMetadata::SetConfigFilePath +/// the path to the config file must be specified using full path, absolute or +/// relative. +/// +/// By default the config file must be specified with full path, absolute or +/// relative. +/// +/// \param cfgFileName A const char* giving the path to an RML file. +/// \param name The name of the TRestReadout section to be loaded +/// +TRestReadout::TRestReadout(const char* cfgFileName, string name) : TRestMetadata(cfgFileName) { + cout << "Loading readout. This might take few seconds" << endl; + RESTWarning << "Creating legacy metadata TRestReadout" << RESTendl; + RESTWarning << "This class is now implemented under TRestDetectorReadout" << RESTendl; + Initialize(); + + LoadConfigFromFile(fConfigFileName, name); +} + +/////////////////////////////////////////////// +/// \brief Initializes the readout members and defines the section name +/// +void TRestReadout::Initialize() { + SetSectionName(this->ClassName()); + + fDecoding = false; + + fNReadoutPlanes = 0; + fReadoutPlanes.clear(); +} + +/////////////////////////////////////////////// +/// \brief TRestReadout default destructor +/// +TRestReadout::~TRestReadout() {} + +/////////////////////////////////////////////// +/// \brief Returns the number of readout planes defined on the readout +/// +Int_t TRestReadout::GetNumberOfReadoutPlanes() { return fReadoutPlanes.size(); } + +/////////////////////////////////////////////// +/// \brief Returns the **total** number of modules implemented in **all** +/// the readout planes. +/// +Int_t TRestReadout::GetNumberOfModules() { + Int_t modules = 0; + for (int p = 0; p < GetNumberOfReadoutPlanes(); p++) modules += fReadoutPlanes[p].GetNumberOfModules(); + return modules; +} + +/////////////////////////////////////////////// +/// \brief Returns the **total** number of channels implemented in **all** +/// the readout planes and modules. +/// +Int_t TRestReadout::GetNumberOfChannels() { + Int_t channels = 0; + for (int p = 0; p < GetNumberOfReadoutPlanes(); p++) + for (int m = 0; m < fReadoutPlanes[p].GetNumberOfModules(); m++) + channels += fReadoutPlanes[p][m].GetNumberOfChannels(); + return channels; +} + +/////////////////////////////////////////////// +/// \brief Returns a pointer to the readout plane by ID +/// +TRestReadoutPlane* TRestReadout::GetReadoutPlaneWithID(int id) { + for (int i = 0; i < this->GetNumberOfReadoutPlanes(); i++) { + if (fReadoutPlanes[i].GetID() == id) { + return &fReadoutPlanes[i]; + } + } + + return NULL; +} + +/////////////////////////////////////////////// +/// \brief Returns a pointer to the readout module by ID +/// +/// e.g. micromegas M0 has id 0, M5 has id 5. The **ID** is Unique of all the +/// readout mudules +TRestReadoutModule* TRestReadout::GetReadoutModuleWithID(int id) { + for (int i = 0; i < this->GetNumberOfReadoutPlanes(); i++) { + TRestReadoutPlane& plane = fReadoutPlanes[i]; + + for (int j = 0; j < plane.GetNumberOfModules(); j++) { + if (plane[j].GetModuleID() == id) { + return &plane[j]; + } + } + } + return NULL; +} + +TRestReadoutChannel* TRestReadout::GetReadoutChannelWithdaqID(int daqId) { + int planeID = -1, moduleID = -1, channelID = -1; + + GetPlaneModuleChannel(daqId, planeID, moduleID, channelID); + if (channelID >= 0) { + return &fReadoutPlanes[planeID][moduleID][channelID]; + } + + return NULL; +} + +/////////////////////////////////////////////// +/// \brief Returns a pointer to the readout plane by index +/// +TRestReadoutPlane* TRestReadout::GetReadoutPlane(int p) { + if (p < fNReadoutPlanes) + return &fReadoutPlanes[p]; + else { + RESTWarning << "TRestReadout::GetReadoutPlane." << RESTendl; + RESTWarning << "Readout plane index exceeded." << RESTendl; + RESTWarning << "Index requested : " << p << RESTendl; + RESTWarning << "Number of readout planes defined : " << fNReadoutPlanes << RESTendl; + } + + return NULL; +} + +/////////////////////////////////////////////// +/// \brief Adds a readout plane to the readout +/// +void TRestReadout::AddReadoutPlane(TRestReadoutPlane plane) { + fReadoutPlanes.push_back(plane); + fNReadoutPlanes++; +} + +/////////////////////////////////////////////// +/// \brief Initializes the readout members using the information given in +/// the TRestReadout RML section. +/// +void TRestReadout::InitFromConfigFile() { + fMappingNodes = StringToInteger(GetParameter("mappingNodes", "0")); + +#pragma region ParseModuledefinition + vector fModuleDefinitions; + TiXmlElement* moduleDefinition = GetElement("readoutModule"); + while (moduleDefinition != NULL) { + if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { + cout << "------module-----------------" << endl; + cout << moduleDefinition << endl; + cout << "-----------------------------" << endl; + GetChar(); + } + + TRestReadoutModule module = *ParseModuleDefinition(moduleDefinition); + // module.DoReadoutMapping(fMappingNodes); + fModuleDefinitions.push_back(module); + moduleDefinition = GetNextElement(moduleDefinition); + } +#pragma endregion + TiXmlElement* planeDefinition = GetElement("readoutPlane"); + vector moduleVector; + Int_t addedChannels = 0; + while (planeDefinition != NULL) { + TRestReadoutPlane plane; + + plane.SetID(GetNumberOfReadoutPlanes()); + plane.SetPosition(Get3DVectorParameterWithUnits("position", planeDefinition)); + plane.SetCathodePosition(Get3DVectorParameterWithUnits("cathodePosition", planeDefinition)); + plane.SetPlaneVector(StringTo3DVector(GetFieldValue("planeVector", planeDefinition))); + plane.SetChargeCollection(StringToDouble(GetFieldValue("chargeCollection", planeDefinition))); + + Double_t tDriftDistance = plane.GetDistanceTo(plane.GetCathodePosition()); + plane.SetTotalDriftDistance(tDriftDistance); + +#pragma region addReadoutModuleToPlane + + moduleVector.clear(); + TiXmlElement* moduleDefinition = GetElement("addReadoutModule", planeDefinition); + while (moduleDefinition != NULL) { + TString modName = GetFieldValue("name", moduleDefinition); + Int_t mid = -1; + for (unsigned int i = 0; i < fModuleDefinitions.size(); i++) { + if (fModuleDefinitions[i].GetName() == modName) { + mid = i; + } + } + + if (mid == -1) { + RESTError << "TRestReadout at . Module name " << modName << " not found!" + << RESTendl; + RESTError << "Please, check spelling" << RESTendl; + exit(1); + } + + fModuleDefinitions[mid].SetModuleID(StringToInteger(GetFieldValue("id", moduleDefinition))); + if (fModuleDefinitions[mid].GetModuleID() < -1) { + RESTWarning << "Module id must be positive!" << RESTendl; + fModuleDefinitions[mid].SetModuleID(-1); // set to -1 to generate from hash later on + } + fModuleDefinitions[mid].SetUniqueName(GetFieldValue("uniqueName", moduleDefinition)); + fModuleDefinitions[mid].SetOrigin(StringTo2DVector(GetFieldValue("origin", moduleDefinition))); + fModuleDefinitions[mid].SetRotation(StringToDouble(GetFieldValue("rotation", moduleDefinition))); + +#pragma region SetupDecodingFile + + Int_t firstDaqChannel = StringToInteger(GetFieldValue("firstDaqChannel", moduleDefinition)); + if (firstDaqChannel == -1) firstDaqChannel = addedChannels; + + string decodingFile = GetFieldValue("decodingFile", moduleDefinition); + if (decodingFile == PARAMETER_NOT_FOUND_STR || decodingFile == "" || + RESTREADOUT_DECODINGFILE_ERROR) + fDecoding = false; + else + fDecoding = true; + + string _decodingFile = SearchFile(decodingFile); + + if (fDecoding && !TRestTools::fileExists(_decodingFile.c_str())) { + RESTWarning << "The decoding file does not exist!" << RESTendl; + RESTWarning << "--------------------------------" << RESTendl; + RESTWarning << "File : " << decodingFile << RESTendl; + RESTWarning << "Default decoding will be used. readoutChannel=daqChannel" << RESTendl; + RESTWarning << "To avoid this message and use the default decoding define : " + "decodingFile=\"\"" + << RESTendl; + RESTWarning << "--------------------------------" << RESTendl; + RESTWarning << "Press a KEY to continue..." << RESTendl; + getchar(); + fDecoding = false; + RESTREADOUT_DECODINGFILE_ERROR = true; + } + + decodingFile = _decodingFile; + + vector rChannel; + vector dChannel; + if (fDecoding && TRestTools::fileExists(decodingFile.c_str())) { + FILE* f = fopen(decodingFile.c_str(), "r"); + + Int_t daq, readout; + while (!feof(f)) { + if (fscanf(f, "%d\t%d\n", &daq, &readout) <= 0) { + RESTError << "TRestReadout::InitFromConfigFile. Problem reading decoding" << RESTendl; + RESTError << "This error might need support at REST forum" << RESTendl; + exit(-1); + } + // we skip blank daq channels if readout id is <0 + // e.g. daq id: 22, readout id: -1 + if (readout >= 0) { + rChannel.push_back(readout); + dChannel.push_back(daq + firstDaqChannel); + } + } + fclose(f); + } + + if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { + cout << "------module-----------------" << endl; + cout << moduleDefinition << endl; + cout << "-----------------------------" << endl; + getchar(); + } + + if (fDecoding && (unsigned int)fModuleDefinitions[mid].GetNumberOfChannels() != rChannel.size()) { + RESTError << "TRestReadout." + << " The number of channels defined in the readout is not the same" + << " as the number of channels found in the decoding." << RESTendl; + exit(1); + } + + for (int ch = 0; ch < fModuleDefinitions[mid].GetNumberOfChannels(); ch++) { + if (!fDecoding) { + Int_t id = ch; + rChannel.push_back(id); + dChannel.push_back(id + firstDaqChannel); + } + + // WRONG version before --> + // fModuleDefinitions[mid].GetChannel(ch)->SetID( rChannel[ch] ); + fModuleDefinitions[mid].GetChannel(rChannel[ch])->SetDaqID(dChannel[ch]); + fModuleDefinitions[mid].GetChannel(rChannel[ch])->SetChannelID(rChannel[ch]); + +#pragma endregion + addedChannels++; + } + fModuleDefinitions[mid].SetMinMaxDaqIDs(); + + moduleVector.push_back(fModuleDefinitions[mid]); + // plane.AddModule( fModuleDefinitions[mid] ); + + moduleDefinition = GetNextElement(moduleDefinition); + } + + // We removed the constraint that module id's should start by 0 and have no + // missing numbers in a multi-module readout plane. Modules can have their + // special "id", e.g. M0, M2, M3, M4 in SJTU proto. We don't have M1 + // edit: 2022/04: modules now have their special names. If so, the id will automatically + // be assigned if not right. + + for (Int_t i(0); i < (Int_t)moduleVector.size(); i++) { + if (moduleVector[i].GetModuleID() == -1) { + if (moduleVector[i].GetUniqueName() != "" && + moduleVector[i].GetUniqueName() != PARAMETER_NOT_FOUND_STR) { + moduleVector[i].SetModuleID(abs((int)ToHash(moduleVector[i].GetUniqueName()))); + } else { + RESTError + << "TRestReadout::InitFromConfigFile() Module id and unique name are both empty!" + << RESTendl; + exit(0); + } + } + + plane.AddModule(moduleVector[i]); + } +#pragma endregion + + this->AddReadoutPlane(plane); + planeDefinition = GetNextElement(planeDefinition); + } + + ValidateReadout(); +} + +TRestReadoutModule* TRestReadout::ParseModuleDefinition(TiXmlElement* moduleDefinition) { + TRestReadoutModule* mod = new TRestReadoutModule(); + TRestReadoutModule& module = *mod; + if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Warning) module.EnableWarnings(); + + module.SetName(GetFieldValue("name", moduleDefinition)); + module.SetSize(StringTo2DVector(GetFieldValue("size", moduleDefinition))); + module.SetTolerance(StringToDouble(GetFieldValue("tolerance", moduleDefinition))); + +#pragma region addChannel + vector channelVector; + vector channelIDVector; + TiXmlElement* channelDefinition = GetElement("readoutChannel", moduleDefinition); + while (channelDefinition != NULL) { + TRestReadoutChannel channel; + + Int_t id = StringToInteger(GetFieldValue("id", channelDefinition)); + if (id != -1) channelIDVector.push_back(id); + channel.SetDaqID(-1); + +#pragma region addPixel + vector pixelVector; + vector pixelIDVector; + TiXmlElement* pixelDefinition = GetElement("addPixel", channelDefinition); + while (pixelDefinition != NULL) { + TRestReadoutPixel pixel; + + pixel.SetOrigin(StringTo2DVector(GetFieldValue("origin", pixelDefinition))); + pixel.SetSize(StringTo2DVector(GetFieldValue("size", pixelDefinition))); + pixel.SetRotation(StringToDouble(GetFieldValue("rotation", pixelDefinition))); + pixel.SetTriangle(StringToBool(GetFieldValue("triangle", pixelDefinition))); + + if (StringToInteger(GetFieldValue("id", pixelDefinition)) != -1) + pixelIDVector.push_back(StringToInteger(GetFieldValue("id", pixelDefinition))); + pixelVector.push_back(pixel); + // channel.AddPixel( pixel ); + pixelDefinition = GetNextElement(pixelDefinition); + } + + if (pixelIDVector.size() > 0 && pixelIDVector.size() != pixelVector.size()) { + RESTError + << "pixel id definition may be wrong! It must be coherent and starts from 0. Check your " + "readout module definition!" + << RESTendl; + exit(0); + } + + // Creating the vector fReadoutPixel in the channel with pixels added in the + // order of their ID. + for (Int_t i(0); i < (Int_t)pixelVector.size(); i++) { + for (Int_t j(0); j < (Int_t)pixelVector.size(); j++) { + if (pixelIDVector[j] == i) { + channel.AddPixel(pixelVector[j]); + break; + } + } + } + + if (channel.GetNumberOfPixels() != pixelVector.size()) { + RESTError << "pixel id definition may be wrong! check your " + "readout module definition!" + << RESTendl; + exit(0); + } +#pragma endregion + + channelVector.push_back(channel); + channelDefinition = GetNextElement(channelDefinition); + } + + if (channelIDVector.size() > 0 && channelIDVector.size() != channelVector.size()) { + RESTError << "TRestReadout::ParseModuleDefinition. Channel id definition may be wrong!" + << "check your readout module definition!" << RESTendl; + RESTError << " " << RESTendl; + RESTError << "channelIDVector size : " << channelIDVector.size() << RESTendl; + RESTError << "channel vector size : " << channelVector.size() << RESTendl; + + exit(0); + } + + // Creating the vector fReadoutChannel in the module with channels added in + // the order of their ID. + for (Int_t i(0); i < (Int_t)channelVector.size(); i++) { + for (Int_t j(0); j < (Int_t)channelVector.size(); j++) { + if (channelIDVector[j] == i) { + module.AddChannel(channelVector[j]); + break; + } + } + } + + if (module.GetNumberOfChannels() != channelVector.size()) { + RESTError << "TRestReadout::ParseModuleDefinition. Channel id definition may be wrong!" + << "check your readout module definition!" << RESTendl; + RESTError << " " << RESTendl; + RESTError << "Module number of channels : " << module.GetNumberOfChannels() << RESTendl; + RESTError << "channel vector size : " << channelVector.size() << RESTendl; + + exit(0); + } +#pragma endregion + + return mod; +} + +/////////////////////////////////////////////// +/// \brief Starts the readout mapping initialization. This process +/// is computationally expensive but it greatly optimizes the FindChannel +/// process later on. +/// +void TRestReadout::DoReadoutMapping(TRestReadoutModule* mod, int nodes) { + /////////////////////////////////////////////////////////////////////////////// + // We initialize the mapping readout net to sqrt(numberOfPixels) + // However this might not be good for readouts where the pixels are + // assymmetric + // ///////////////////////////////////////////////////////////////////////////// + Int_t totalNumberOfPixels = 0; + for (int ch = 0; ch < mod->GetNumberOfChannels(); ch++) + totalNumberOfPixels += mod->GetChannel(ch)->GetNumberOfPixels(); + + if (nodes == 0) { + nodes = TMath::Sqrt(totalNumberOfPixels); + nodes = 2 * nodes; + } + + cout << "Performing readout mapping optimization (This might require long " + "computation time)" + << endl; + cout << "--------------------------------------------------------------------" + "--------------" + << endl; + cout << "Total number of pixels : " << totalNumberOfPixels << endl; + cout << "Nodes : " << nodes << endl; + + TRestReadoutMapping& fMapping = fReadoutMappings[mod->GetName()]; + fMapping.Initialize(nodes, nodes, mod->GetModuleSizeX(), mod->GetModuleSizeY()); + + // 1. loop for each pixel, find the mapping nodes for the pixel position, + // and assign the pixel/channel id to the nodes. + for (int ch = 0; ch < mod->GetNumberOfChannels(); ch++) { + for (int px = 0; px < mod->GetChannel(ch)->GetNumberOfPixels(); px++) { + Double_t xPix = mod->GetChannel(ch)->GetPixel(px)->GetCenter().X(); + Double_t yPix = mod->GetChannel(ch)->GetPixel(px)->GetCenter().Y(); + + Int_t nodeX = fMapping.GetNodeX(xPix); + Int_t nodeY = fMapping.GetNodeY(yPix); + + // This means that two pixels in the readout are associated to the same + // node. + // If the granularity of the readout is not high enough this may happen + // often. This should be just a RESTWarning I guess. + if (fMapping.isNodeSet(nodeX, nodeY)) { + cout << endl; + RESTWarning << "TRestReadoutModule. Node is already SET!!" << RESTendl; + RESTWarning << "Trying to associate channel : " << ch << " Pixel : " << px << RESTendl; + RESTWarning << "Pixel coordinates : ( " << xPix << " , " << yPix << " ) " << RESTendl; + + Int_t tempCh = fMapping.GetChannelByNode(nodeX, nodeY); + Int_t tempPix = fMapping.GetPixelByNode(nodeX, nodeY); + RESTWarning << "Already associated channel : " << tempCh << " pixel : " << tempPix + << RESTendl; + Double_t xP = mod->GetChannel(tempCh)->GetPixel(tempPix)->GetCenter().X(); + Double_t yP = mod->GetChannel(tempCh)->GetPixel(tempPix)->GetCenter().Y(); + RESTWarning << "Pixel coordinates : ( " << xP << " , " << yP << " ) " << RESTendl; + cout << endl; + + cout << "Increasing the number of mapping of nodes may solve this issue." << endl; + cout << endl; + } + fMapping.SetNode(nodeX, nodeY, ch, px); + } + } + + // 2. There should still be some nodes without channel/pixel id assignment. Now + // we loop for all the nodes and find the pixel on their position + for (int i = 0; i < nodes; i++) { + printf("Completed : %.2lf %%\r", 100. * (i * (Double_t)nodes) / nodes / nodes); + fflush(stdout); + for (int j = 0; j < nodes; j++) { + Double_t x = fMapping.GetX(i); + Double_t y = fMapping.GetY(j); + + if (!fMapping.isNodeSet(i, j)) { + // find the nearby nodes with channel/pixel ids set + // const int NNearby = 5; + // for (int ii = i - NNearby; ii <= i + NNearby; ii++) { + // if (ii < 0 || ii >= nodes || ii == i) continue; + // for (int jj = j - NNearby; jj <= j + NNearby; jj++) { + // if (jj < 0 || jj >= nodes || jj == i) continue; + + // if (fMapping.isNodeSet(ii, jj)) { + // Int_t ch = fMapping.GetChannelByNode(ii, jj); + // Int_t px = fMapping.GetPixelByNode(ii, jj); + + // if (mod->isInsidePixelRelative(ch, px, x, y)) { + // fMapping.SetNode(i, j, ch, px); + // } + // } + // } + //} + + // if cannot find pixel within nearby 10*10 nodes, do a thorough scan + if (!fMapping.isNodeSet(i, j)) { + for (int ch = 0; ch < GetNumberOfChannels() && !fMapping.isNodeSet(i, j); ch++) { + for (int px = 0; + px < mod->GetChannel(ch)->GetNumberOfPixels() && !fMapping.isNodeSet(i, j); + px++) { + if (mod->isInsidePixelRelative(ch, px, x, y)) { + fMapping.SetNode(i, j, ch, px); + } + } + } + } + } + } + } + + if (!fMapping.AllNodesSet()) + cout << "Not all nodes set" << endl; + else + cout << "All Nodes set" << endl; + + // save this generated mapping + for (int i = 0; i < fReadoutPlanes.size(); i++) { + TRestReadoutPlane* p = &fReadoutPlanes[i]; + for (int j = 0; j < p->GetNumberOfModules(); j++) { + TRestReadoutModule* m = p->GetModule(j); + if (m->GetName() == mod->GetName()) { + m->SetReadoutMapping(&fMapping); + } + } + } + return; +} + +/////////////////////////////////////////////// +/// \brief This method is not implemented yet. But it could +/// do some checks to help verifying the readout. +/// +void TRestReadout::ValidateReadout() { + // cout << "--------------------------------------------------" << endl; + // cout << "TRestReadout::ValidateReadout:: NOT IMPLEMENTED" << endl; + // cout << "This function should crosscheck that there are no repeated " + // "DaqChannels IDs" + // << endl; + // cout << "If any checks are implemented in the future. Those checks should be " + // "an option." + // << endl; + // cout << "No dead area in the readout module" << endl; + // cout << "And other checks" << endl; + // cout << "--------------------------------------------------" << endl; +} + +void TRestReadout::GetPlaneModuleChannel(Int_t signalID, Int_t& planeID, Int_t& moduleID, Int_t& channelID) { + for (int p = 0; p < GetNumberOfReadoutPlanes(); p++) { + TRestReadoutPlane* plane = &fReadoutPlanes[p]; + for (int m = 0; m < plane->GetNumberOfModules(); m++) { + TRestReadoutModule* mod = &(*plane)[m]; + + if (mod->isDaqIDInside(signalID)) { + planeID = plane->GetID(); + moduleID = mod->GetModuleID(); + channelID = mod->DaqToReadoutChannel(signalID); + } + } + } +} + +Int_t TRestReadout::GetHitsDaqChannel(TVector3 hitpos, Int_t& planeID, Int_t& moduleID, Int_t& channelID) { + double x = hitpos.X(); + double y = hitpos.Y(); + double z = hitpos.Z(); + + for (int p = 0; p < GetNumberOfReadoutPlanes(); p++) { + TRestReadoutPlane* plane = &fReadoutPlanes[p]; + int m = plane->GetModuleIDFromPosition(x, y, z); + if (m >= 0) { + // TRestReadoutModule* mod = plane->GetModuleByID(m); + TRestReadoutModule* mod = plane->GetModuleByID(m); + + if (mod->GetMapping() == NULL) { + if (fReadoutMappings.count(mod->GetName()) != 0) { + mod->SetReadoutMapping(&fReadoutMappings[mod->GetName()]); + } else { + DoReadoutMapping(mod, fMappingNodes); + } + } + + Int_t readoutChannel = mod->FindChannel(x, y); + if (readoutChannel >= 0) { + planeID = plane->GetID(); + moduleID = mod->GetModuleID(); + channelID = readoutChannel; + return mod->GetChannel(readoutChannel)->GetDaqID(); + } + } + } + return -1; +} + +Double_t TRestReadout::GetX(Int_t signalID) { + Int_t planeID, readoutChannel = -1, readoutModule; + GetPlaneModuleChannel(signalID, planeID, readoutModule, readoutChannel); + if (readoutChannel == -1) { + // cout << "REST Warning : Readout channel not found for daq ID : " << signalID << endl; + return numeric_limits::quiet_NaN(); + } + return GetX(planeID, readoutModule, readoutChannel); +} + +Double_t TRestReadout::GetY(Int_t signalID) { + Int_t planeID, readoutChannel = -1, readoutModule; + GetPlaneModuleChannel(signalID, planeID, readoutModule, readoutChannel); + if (readoutChannel == -1) { + // cout << "REST Warning : Readout channel not found for daq ID : " << signalID << endl; + return numeric_limits::quiet_NaN(); + } + return GetY(planeID, readoutModule, readoutChannel); +} +/////////////////////////////////////////////// +/// \brief It returns the x-coordinate for the given readout +/// plane, *plane*, a given module, *modID*, and a given +/// channel, *chID*. +/// +Double_t TRestReadout::GetX(Int_t plane, Int_t modID, Int_t chID) { + return GetReadoutPlaneWithID(plane)->GetX(modID, chID); +} + +/////////////////////////////////////////////// +/// \brief It returns the y-coordinate for the given readout +/// plane, *plane*, a given module, *modID*, and a given +/// channel, *chID*. +/// +Double_t TRestReadout::GetY(Int_t plane, Int_t modID, Int_t chID) { + return GetReadoutPlaneWithID(plane)->GetY(modID, chID); +} + +/////////////////////////////////////////////// +/// \brief Prints on screen the details about the readout +/// definition. +/// +/// \param fullDetail Prints all modules, channels and pixels info. +/// +void TRestReadout::PrintMetadata(Int_t DetailLevel) { + if (DetailLevel >= 0) { + TRestMetadata::PrintMetadata(); + + RESTMetadata << "Number of readout planes : " << fNReadoutPlanes << RESTendl; + RESTMetadata << "Decoding was defined : "; + if (fDecoding) + RESTMetadata << "YES" << RESTendl; + else + RESTMetadata << "NO" << RESTendl; + RESTMetadata << "-----------------------------------" << RESTendl; + for (int p = 0; p < GetNumberOfReadoutPlanes(); p++) fReadoutPlanes[p].Print(DetailLevel - 1); + RESTMetadata << "****************************************" << RESTendl; + cout << RESTendl; + } +} + +/////////////////////////////////////////////// +/// \brief Draws the readout on screen. Not yet implemented. +/// +void TRestReadout::Draw() { + cout << " TRestReadout::Draw() is not implemented" << endl; + cout << " To draw a TRestReadout class with name \"readoutName\""; + cout << " stored in a ROOT file \"rootFile.root\"" << endl; + cout << " You can use the script : REST_Readout_Viewer( \"rootFile.root\", " + "\"readoutName\" )" + << endl; + cout << endl; + cout << " Or you can access directly a readout plane and draw using : " << endl; + cout << " readout->GetReadoutPlane( 0 )->Draw( ); " << endl; +} diff --git a/src/TRestReadoutChannel.cxx b/src/TRestReadoutChannel.cxx new file mode 100644 index 0000000..e33ccdd --- /dev/null +++ b/src/TRestReadoutChannel.cxx @@ -0,0 +1,106 @@ +/************************************************************************* + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * REST is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +/// +/// This class stores the readout pixel geometrical description, origin +/// position, orientation, and size. A readout pixel is the most elementary +/// component of a readout used to construct a readout channel. +/// +///-------------------------------------------------------------------------- +/// +/// RESTsoft - Software for Rare Event Searches with TPCs +/// +/// History of developments: +/// +/// 2015-aug: First concept. +/// Javier Galan +/// +/// \class TRestReadoutChannel +/// \author Javier Galan +/// +///
+/// + +#include "TRestReadoutChannel.h" +using namespace std; + +ClassImp(TRestReadoutChannel); +/////////////////////////////////////////////// +/// \brief TRestReadoutChannel default constructor +/// +TRestReadoutChannel::TRestReadoutChannel() { Initialize(); } + +/////////////////////////////////////////////// +/// \brief TRestReadoutChannel default destructor +/// +TRestReadoutChannel::~TRestReadoutChannel() {} + +/////////////////////////////////////////////// +/// \brief Initializes the channel members +/// +void TRestReadoutChannel::Initialize() { fDaqID = -1; } + +/////////////////////////////////////////////// +/// \brief Determines if (x,y) referenced to module coordinates is inside the +/// channel +/// +Int_t TRestReadoutChannel::isInside(Double_t x, Double_t y) { + for (unsigned int i = 0; i < fReadoutPixel.size(); i++) + if (fReadoutPixel[i].isInside(x, y)) return true; + return false; +} + +/////////////////////////////////////////////// +/// \brief Prints the details of the readout channel including pixel +/// coordinates. +/// +void TRestReadoutChannel::Print(int DetailLevel) { + if (DetailLevel >= 0) { + RESTMetadata << "++++ Channel : " << GetChannelId() << " Daq channel : " << GetDaqID() << RESTendl; + + string typestr; + if (GetType() == Channel_NoType) + typestr = "NoType"; + else if (GetType() == Channel_Pixel) + typestr = "Pixel"; + else if (GetType() == Channel_X) + typestr = "X"; + else if (GetType() == Channel_Y) + typestr = "Y"; + else if (GetType() == Channel_U) + typestr = "U"; + else if (GetType() == Channel_V) + typestr = "V"; + else if (GetType() == Channel_W) + typestr = "W"; + + RESTMetadata << " Total pixels : " << GetNumberOfPixels() << " Channel type : " << typestr + << RESTendl; + RESTMetadata << "+++++++++++++++++++++++++++++++++++++++++++++++++" << RESTendl; + + if (DetailLevel - 1 >= 0) + for (int n = 0; n < GetNumberOfPixels(); n++) { + fReadoutPixel[n].Print(); + } + } +} diff --git a/src/TRestReadoutMapping.cxx b/src/TRestReadoutMapping.cxx new file mode 100644 index 0000000..515766a --- /dev/null +++ b/src/TRestReadoutMapping.cxx @@ -0,0 +1,182 @@ +/************************************************************************* + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * REST is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +/// +/// This class defines a uniform coordinate grid with XY-nodes. Each node +/// is associated to a channel and pixel from the readout module definition. +/// It is TRestReadoutModule::DoReadoutMapping the responsible to establish +/// the correspondence between nodes and the set (channel,pixel). +/// +/// In complex readouts the pixel and channel can be hard to identify. +/// This class will be used by TRestReadoutModule::FindChannel in order to +/// try to guess the pixel and channel where a given coordinate is found. +/// +///-------------------------------------------------------------------------- +/// +/// RESTsoft - Software for Rare Event Searches with TPCs +/// +/// History of developments: +/// +/// 2015-aug: First concept. +/// Javier Galan +/// +/// \class TRestReadoutMapping +/// \author Javier Galan +/// +///
+/// + +#include "TRestReadoutMapping.h" +using namespace std; + +ClassImp(TRestReadoutMapping) + /////////////////////////////////////////////// + /// \brief TRestReadoutMapping constructor + /// + TRestReadoutMapping::TRestReadoutMapping() {} + +/////////////////////////////////////////////// +/// \brief TRestReadoutMapping destructor +/// +TRestReadoutMapping::~TRestReadoutMapping() {} + +/////////////////////////////////////////////// +/// \brief Gets the X position of node (i,j) +/// +Double_t TRestReadoutMapping::GetX(Int_t nodeX) { return (fNetSizeX / fNodesX) * nodeX; } + +/////////////////////////////////////////////// +/// \brief Gets the Y position of node (i,j) +/// +Double_t TRestReadoutMapping::GetY(Int_t nodeY) { return (fNetSizeY / fNodesY) * nodeY; } + +/////////////////////////////////////////////// +/// \brief Gets the nodeX index corresponding to the x coordinate +/// +Int_t TRestReadoutMapping::GetNodeX(Double_t x) { + Int_t nX = (Int_t)((x / fNetSizeX) * fNodesX); + if (nX >= fNodesX) return fNodesX - 1; + return nX; +} + +/////////////////////////////////////////////// +/// \brief Gets the nodeY index corresponding to the y coordinate +/// +Int_t TRestReadoutMapping::GetNodeY(Double_t y) { + Int_t nY = (Int_t)((y / fNetSizeY) * fNodesY); + if (nY >= fNodesY) return fNodesY - 1; + return nY; +} + +/////////////////////////////////////////////// +/// \brief Gets the channel number corresponding to coordinates (x,y) +/// +Int_t TRestReadoutMapping::GetChannel(Double_t x, Double_t y) { return fChannel[GetNodeX(x)][GetNodeY(y)]; } + +/////////////////////////////////////////////// +/// \brief Gets the pixel number corresponding to coordinates (x,y) +/// +Int_t TRestReadoutMapping::GetPixel(Double_t x, Double_t y) { return fPixel[GetNodeX(x)][GetNodeY(y)]; } + +/////////////////////////////////////////////// +/// \brief Returns the number of nodes that have not been initialized. +/// +Int_t TRestReadoutMapping::GetNumberOfNodesNotSet() { + Int_t counter = 0; + for (int i = 0; i < fNodesX; i++) + for (int j = 0; j < fNodesY; j++) { + if (!isNodeSet(i, j)) counter++; + } + return counter; +} + +/////////////////////////////////////////////// +/// \brief Finds the node index in X for a given channel and pixel ids. +/// +Int_t TRestReadoutMapping::GetNodeX_ForChannelAndPixel(Int_t ch, Int_t px) { + for (int i = 0; i < fNodesX; i++) + for (int j = 0; j < fNodesY; j++) { + if (fChannel[i][j] == ch && fPixel[i][j] == px) return i; + } + return -1; +} + +/////////////////////////////////////////////// +/// \brief Finds the node index in Y for a given channel and pixel ids. +/// +Int_t TRestReadoutMapping::GetNodeY_ForChannelAndPixel(Int_t ch, Int_t px) { + for (int i = 0; i < fNodesX; i++) + for (int j = 0; j < fNodesY; j++) { + if (fChannel[i][j] == ch && fPixel[i][j] == px) return j; + } + return -1; +} + +/////////////////////////////////////////////// +/// \brief Resets the matrix values and allocates memory for the given net size. +/// +void TRestReadoutMapping::Initialize(Int_t nX, Int_t nY, Double_t sX, Double_t sY) { + fNodesX = nX; + fNodesY = nY; + fNetSizeX = sX; + fNetSizeY = sY; + fChannel.ResizeTo(fNodesX, fNodesY); + fPixel.ResizeTo(fNodesX, fNodesY); + + for (int i = 0; i < fNodesX; i++) + for (int j = 0; j < fNodesY; j++) { + fChannel[i][j] = -1; + fPixel[i][j] = -1; + } +} + +/////////////////////////////////////////////// +/// \brief Sets the readout channel and pixel corresponding to a mapping node +/// +void TRestReadoutMapping::SetNode(Int_t i, Int_t j, Int_t ch, Int_t pix) { + fChannel[i][j] = ch; + fPixel[i][j] = pix; +} + +/////////////////////////////////////////////// +/// \brief Checks if the node (i,j) is defined. +/// +Bool_t TRestReadoutMapping::isNodeSet(Int_t i, Int_t j) { + if (fChannel[i][j] == -1 || fPixel[i][j] == -1) return false; + return true; +} + +/////////////////////////////////////////////// +/// \brief Checks if all the nodes in the net have been defined. +/// +Bool_t TRestReadoutMapping::AllNodesSet() { + for (int i = 0; i < fNodesX; i++) + for (int j = 0; j < fNodesY; j++) { + if (!isNodeSet(i, j)) { + cout << "Node : " << i << " , " << j << " is NOT set. Ch : " << fChannel[i][j] + << " Pix : " << fPixel[i][j] << endl; + return false; + } + } + return true; +} diff --git a/src/TRestReadoutModule.cxx b/src/TRestReadoutModule.cxx new file mode 100644 index 0000000..4c29cfc --- /dev/null +++ b/src/TRestReadoutModule.cxx @@ -0,0 +1,478 @@ +/************************************************************************* + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * REST is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +/// +/// This class stores the readout module geometrical description, module +/// position, orientation, and size. It contains a vector of +/// TRestReadoutChannel with the definition of the readout channels +/// existing in the readout module. +/// +///-------------------------------------------------------------------------- +/// +/// RESTsoft - Software for Rare Event Searches with TPCs +/// +/// History of developments: +/// +/// 2015-aug: First concept. +/// Javier Galan +/// +/// \class TRestReadoutModule +/// \author Javier Galan +/// +///
+/// + +#include "TRestReadoutModule.h" +using namespace std; + +ClassImp(TRestReadoutModule); +/////////////////////////////////////////////// +/// \brief Default TRestReadoutModule constructor +/// +TRestReadoutModule::TRestReadoutModule() { Initialize(); } + +/////////////////////////////////////////////// +/// \brief Default TRestReadoutModule destructor +/// +TRestReadoutModule::~TRestReadoutModule() {} + +/////////////////////////////////////////////// +/// \brief TRestReadoutModule initialization +/// +void TRestReadoutModule::Initialize() { + fReadoutChannel.clear(); + fModuleID = -1; + + fMapping = NULL; + + fModuleOriginX = 0; + fModuleOriginY = 0; + + fModuleSizeX = 0; + fModuleSizeY = 0; + + fModuleRotation = 0; + + fMaximumDaqId = -1; + fMininimumDaqId = -1; + + fTolerance = 1.e-6; + + showWarnings = false; +} + +/////////////////////////////////////////////// +/// \brief Initializes the max and min values for the daq channel number +/// +void TRestReadoutModule::SetMinMaxDaqIDs() { + Int_t maxID = GetChannel(0)->GetDaqID(); + Int_t minID = GetChannel(0)->GetDaqID(); + for (int ch = 0; ch < this->GetNumberOfChannels(); ch++) { + Int_t daqID = GetChannel(ch)->GetDaqID(); + if (daqID > maxID) maxID = daqID; + + if (daqID < minID) minID = daqID; + } + + fMaximumDaqId = maxID; + fMininimumDaqId = minID; +} + +/////////////////////////////////////////////// +/// \brief Determines if a given *daqID* number is in the range of the module +/// +Bool_t TRestReadoutModule::isDaqIDInside(Int_t daqID) { + if (daqID >= fMininimumDaqId && daqID <= fMaximumDaqId) return true; + return false; +} + +/////////////////////////////////////////////// +/// \brief Returns the channel index corresponding to the absolute coordinates, +/// i.e, relative to the readout plane coordinate system +/// +/// The readout mapping (see TRestReadoutMapping) is used to help finding +/// the pixel where coordinates absX and absY fall in. +/// +Int_t TRestReadoutModule::FindChannel(Double_t absX, Double_t absY) { + if (!isInside(absX, absY)) return -1; + + Double_t x = TransformToModuleCoordinates(absX, absY).X(); + Double_t y = TransformToModuleCoordinates(absX, absY).Y(); + + Int_t nodeX = fMapping->GetNodeX(x); + Int_t nodeY = fMapping->GetNodeY(y); + + Int_t channel = fMapping->GetChannelByNode(nodeX, nodeY); + Int_t pixel = fMapping->GetPixelByNode(nodeX, nodeY); + + Int_t repeat = 1; + Int_t count = 0; + Int_t forward = 1; + Int_t xAxis = 1; + + Int_t totalNodes = fMapping->GetNumberOfNodesX() * fMapping->GetNumberOfNodesY(); + + // We test if x,y is inside the channel/pixel obtained from the readout + // mapping If not we start to look in the readout mapping neighbours + while (!this->isInsidePixel(channel, pixel, absX, absY)) { + count++; + if (xAxis == 1 && forward == 1) + nodeX++; + else if (xAxis == 0 && forward == 1) + nodeY++; + else if (xAxis == 1 && forward == 0) + nodeX--; + else if (xAxis == 0 && forward == 0) + nodeY--; + + Int_t nNodes = fMapping->GetNumberOfNodesX(); + + if (nodeX < 0) nodeX = nNodes - 1; + if (nodeY < 0) nodeY = nNodes - 1; + if (nodeX >= nNodes) nodeX = 0; + if (nodeY >= nNodes) nodeY = 0; + + if (count >= repeat) { + if (xAxis == 1 && forward == 1) { + xAxis = 0; + forward = 0; + } else if (xAxis == 0 && forward == 0) { + xAxis = 1; + forward = 0; + repeat++; + } else if (xAxis == 1 && forward == 0) { + xAxis = 0; + forward = 1; + } else if (xAxis == 0 && forward == 1) { + xAxis = 1; + forward = 1; + repeat++; + } + + count = 0; + } + + channel = fMapping->GetChannelByNode(nodeX, nodeY); + pixel = fMapping->GetPixelByNode(nodeX, nodeY); + + if (count > totalNodes / 10) { + cout << "REST Error? I did not find any channel for hit position (" << x << "," << y << ")" + << endl; + + for (int ch = 0; ch < GetNumberOfChannels(); ch++) + for (int px = 0; px < GetChannel(ch)->GetNumberOfPixels(); px++) + if (isInsidePixel(ch, px, absX, absX)) { + cout << "( " << x << " , " << y << ") Should be in channel " << ch + << " pixel : " << px << endl; + + cout << "Corresponding node : nX: " << fMapping->GetNodeX_ForChannelAndPixel(ch, px) + << " nY : " << fMapping->GetNodeY_ForChannelAndPixel(ch, px) << endl; + cout << "Channel : " << ch << " Pixel : " << px << endl; + cout << "Pix X : " << GetChannel(ch)->GetPixel(px)->GetCenter().X() + << " Pix Y : " << GetChannel(ch)->GetPixel(px)->GetCenter().Y() << endl; + } + sleep(5); + // getchar(); + return -1; + } + } + + return channel; +} + +/////////////////////////////////////////////// +/// \brief Determines if the position *x,y* (in readout plane coordinate) relative to the readout +/// plane are inside this readout module. +/// +Bool_t TRestReadoutModule::isInside(Double_t x, Double_t y) { + TVector2 v(x, y); + return isInside(v); +} + +/////////////////////////////////////////////// +/// \brief Determines if the position TVector2 *pos* (in readout plane coordinate) relative to the readout +/// plane are inside this readout module. +/// +Bool_t TRestReadoutModule::isInside(TVector2 pos) { + TVector2 rotPos = TransformToModuleCoordinates(pos); + + if (rotPos.X() >= 0 && rotPos.X() < fModuleSizeX) + if (rotPos.Y() >= 0 && rotPos.Y() < fModuleSizeY) return true; + + return false; +} + +/////////////////////////////////////////////// +/// \brief Determines if the position *x,y* (in readout plane coordinate) is found in any of the pixels +/// of the readout *channel* index given. +/// +Bool_t TRestReadoutModule::isInsideChannel(Int_t channel, Double_t x, Double_t y) { + TVector2 pos(x, y); + + return isInsideChannel(channel, pos); +} + +/////////////////////////////////////////////// +/// \brief Determines if the position TVector2 *pos* (in readout plane coordinate) is found in any of the +/// pixels of the readout *channel* index given. +/// +Bool_t TRestReadoutModule::isInsideChannel(Int_t channel, TVector2 pos) { + pos = TransformToModuleCoordinates(pos); + for (int idx = 0; idx < GetChannel(channel)->GetNumberOfPixels(); idx++) + if (GetChannel(channel)->GetPixel(idx)->isInside(pos)) return true; + return false; +} + +/////////////////////////////////////////////// +/// \brief Determines if the position *x,y* (in readout plane coordinate) is found at a specific *pixel* id +/// inside the readout *channel* given. +/// +Bool_t TRestReadoutModule::isInsidePixel(Int_t channel, Int_t pixel, Double_t x, Double_t y) { + TVector2 pos(x, y); + + if (channel < 0 || pixel < 0) return false; + + return isInsidePixel(channel, pixel, pos); +} + +/////////////////////////////////////////////// +/// \brief Determines if the position TVector2 *pos* (in readout plane coordinate) is found at a specific +/// *pixel* id inside the readout *channel* given. +/// +Bool_t TRestReadoutModule::isInsidePixel(Int_t channel, Int_t pixel, TVector2 pos) { + if (channel < 0 || pixel < 0) return false; + + pos = TransformToModuleCoordinates(pos); + if (GetChannel(channel)->GetPixel(pixel)->isInside(pos)) return true; + return false; +} + +/////////////////////////////////////////////// +/// \brief Determines if the position *x,y* (relative to module coordinate) is found at a specific *pixel* id +/// inside the readout *channel* given. +/// +Bool_t TRestReadoutModule::isInsidePixelRelative(Int_t channel, Int_t pixel, Double_t x, Double_t y) { + TVector2 pos(x, y); + + if (channel < 0 || pixel < 0) return false; + + return isInsidePixelRelative(channel, pixel, pos); +} + +/////////////////////////////////////////////// +/// \brief Determines if the position TVector2 *pos* (relative to module coordinate) is found at a specific +/// *pixel* id inside the readout *channel* given. +/// +Bool_t TRestReadoutModule::isInsidePixelRelative(Int_t channel, Int_t pixel, TVector2 pos) { + if (channel < 0 || pixel < 0) return false; + + if (GetChannel(channel)->GetPixel(pixel)->isInside(pos)) return true; + return false; +} + +/////////////////////////////////////////////// +/// \brief Creates a TVector2 with shortest norm going from the given position +/// *pos* to the module. +/// It can be seen as the vector to add to move from the position to the +/// closest border of the module. +/// +TVector2 TRestReadoutModule::GetDistanceToModule(TVector2 pos) { + TVector2 newPos = TransformToModuleCoordinates(pos); + + Double_t dx = 0, dy = 0; + if (newPos.X() < 0) + dx = -newPos.X(); + else if (fModuleSizeX - newPos.X() < 0) + dx = fModuleSizeX - newPos.X(); + + if (newPos.Y() < 0) + dy = -newPos.Y(); + else if (fModuleSizeY - newPos.Y() < 0) + dy = fModuleSizeY - newPos.Y(); + + TVector2 dist = TVector2(dx, dy); + return dist; +} +/////////////////////////////////////////////// +/// \brief Returns the pixel origin (left-bottom) position for a given *channel* +/// and *pixel* indexes. +/// +TVector2 TRestReadoutModule::GetPixelOrigin(Int_t channel, Int_t pixel) { + return GetPixelVertex(channel, pixel, 0); +} + +/////////////////////////////////////////////// +/// \brief Returns any of the pixel vertex position for a given *channel* and +/// *pixel* indexes. +/// +/// \param vertex A value between 0-3 definning the vertex position to be +/// returned +/// +TVector2 TRestReadoutModule::GetPixelVertex(Int_t channel, Int_t pixel, Int_t vertex) { + TVector2 pixPosition = GetChannel(channel)->GetPixel(pixel)->GetVertex(vertex); + + pixPosition = pixPosition.Rotate(fModuleRotation * TMath::Pi() / 180.); + pixPosition = pixPosition + TVector2(fModuleOriginX, fModuleOriginY); + return pixPosition; +} + +/////////////////////////////////////////////// +/// \brief Returns the center pixel position for a given *channel* and +/// *pixel* indexes. +/// +/// \param vertex A value between 0-3 definning the vertex position to be +/// returned +/// +TVector2 TRestReadoutModule::GetPixelCenter(Int_t channel, Int_t pixel) { + TVector2 pixCenter = GetChannel(channel)->GetPixel(pixel)->GetCenter(); + + pixCenter = pixCenter.Rotate(fModuleRotation * TMath::Pi() / 180.); + pixCenter = pixCenter + TVector2(fModuleOriginX, fModuleOriginY); + return pixCenter; +} + +/////////////////////////////////////////////// +/// \brief Returns the pixel type for a given *channel* and +/// *pixel* indexes. +/// +/// \param vertex A boolean that is true if the pixel is triangular, false +/// otherwise +/// +Bool_t TRestReadoutModule::GetPixelTriangle(Int_t channel, Int_t pixel) { + Bool_t type = GetChannel(channel)->GetPixel(pixel)->GetTriangle(); + + return type; +} + +TVector2 TRestReadoutModule::GetPixelOrigin(TRestReadoutPixel* pix) { return GetPixelVertex(pix, 0); } + +TVector2 TRestReadoutModule::GetPixelVertex(TRestReadoutPixel* pix, Int_t vertex) { + TVector2 pixPosition = pix->GetVertex(vertex); + pixPosition = pixPosition.Rotate(fModuleRotation * TMath::Pi() / 180.); + pixPosition = pixPosition + TVector2(fModuleOriginX, fModuleOriginY); + return pixPosition; +} + +TVector2 TRestReadoutModule::GetPixelCenter(TRestReadoutPixel* pix) { + TVector2 corner1(GetPixelVertex(pix, 0)); + TVector2 corner2(GetPixelVertex(pix, 2)); + TVector2 center = (corner1 + corner2) / 2.; + return center; +} + +Bool_t TRestReadoutModule::GetPixelTriangle(TRestReadoutPixel* pix) { return pix->GetTriangle(); } + +/////////////////////////////////////////////// +/// \brief Returns the coordinates of the specified vertex index *n*. The +/// physical coordinates relative to the readout plane are returned, including +/// rotation. +/// +/// \param n A value between 0-3 definning the vertex position to be returned +/// +TVector2 TRestReadoutModule::GetVertex(int n) const { + TVector2 vertex(0, 0); + TVector2 origin(fModuleOriginX, fModuleOriginY); + + if (n % 4 == 0) + return origin; + else if (n % 4 == 1) { + vertex.Set(fModuleSizeX, 0); + vertex = vertex.Rotate(fModuleRotation * TMath::Pi() / 180.); + + vertex = vertex + origin; + } else if (n % 4 == 2) { + vertex.Set(fModuleSizeX, fModuleSizeY); + vertex = vertex.Rotate(fModuleRotation * TMath::Pi() / 180.); + + vertex = vertex + origin; + } else if (n % 4 == 3) { + vertex.Set(0, fModuleSizeY); + vertex = vertex.Rotate(fModuleRotation * TMath::Pi() / 180.); + + vertex = vertex + origin; + } + return vertex; +} + +/////////////////////////////////////////////// +/// \brief Adds a new channel to the module +/// +void TRestReadoutModule::AddChannel(TRestReadoutChannel& rChannel) { + for (int i = 0; i < rChannel.GetNumberOfPixels(); i++) { + // TODO we expect here that the user will only do pixel rotations between 0 + // and 90 degrees, we must force that on pixel definition or fix it here + Double_t oX = rChannel.GetPixel(i)->GetVertex(3).X(); + Double_t oY = rChannel.GetPixel(i)->GetVertex(3).Y(); + Double_t sX = rChannel.GetPixel(i)->GetVertex(1).X(); + Double_t sY = rChannel.GetPixel(i)->GetVertex(1).Y(); + + if (oX + fTolerance < 0 || oY + fTolerance < 0 || sX - fTolerance > fModuleSizeX || + sY - fTolerance > fModuleSizeY) { + if (showWarnings) { + cout << "REST Warning (AddChannel) pixel outside the module boundaries" << endl; + cout << "Channel: " << fReadoutChannel.size() << ", Pixel : " << i << endl; + cout << "Pixel origin = (" << oX << " , " << oY << ")" << endl; + cout << "Pixel size = (" << sX << " , " << sY << ")" << endl; + cout << "Module size = (" << fModuleSizeX << " , " << fModuleSizeY << ")" << endl; + } + } + } + + fReadoutChannel.push_back(rChannel); +} + +/////////////////////////////////////////////// +/// \brief Not implemented +/// +void TRestReadoutModule::Draw() {} + +/////////////////////////////////////////////// +/// \brief Prints the module details and channels if *fullDetail* is enabled. +/// +void TRestReadoutModule::Print(Int_t DetailLevel) { + if (DetailLevel >= 0) { + RESTMetadata << "-- Readout module : " << GetModuleID() << RESTendl; + RESTMetadata << "----------------------------------------------------------------" << RESTendl; + RESTMetadata << "-- Origin position : X = " << fModuleOriginX << " mm " + << " Y : " << fModuleOriginY << " mm" << RESTendl; + RESTMetadata << "-- Size : X = " << fModuleSizeX << " Y : " << fModuleSizeY << RESTendl; + RESTMetadata << "-- Rotation : " << fModuleRotation << " degrees" << RESTendl; + RESTMetadata << "-- Total channels : " << GetNumberOfChannels() << RESTendl; + RESTMetadata << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << RESTendl; + + for (int n = 0; n < GetNumberOfChannels(); n++) fReadoutChannel[n].Print(DetailLevel - 1); + } +} + +void TRestReadoutModule::PrintDecoding() { + cout << "daqChannel\tphysicalChannel" << endl; + + map channelmap; + for (int i = 0; i < GetNumberOfChannels(); i++) { + TRestReadoutChannel* chn = &fReadoutChannel[i]; + channelmap[chn->GetDaqID()] = i; + } + for (auto iter : channelmap) { + cout << iter.first << "\t" << iter.second << endl; + } +} \ No newline at end of file diff --git a/src/TRestReadoutPixel.cxx b/src/TRestReadoutPixel.cxx new file mode 100644 index 0000000..8623e07 --- /dev/null +++ b/src/TRestReadoutPixel.cxx @@ -0,0 +1,165 @@ +/************************************************************************* + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * REST is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +/// +/// This class stores the readout pixel geometrical description, origin +/// position, orientation, and size. A readout pixel is the most elementary +/// component of a readout used to construct a readout channel. +/// +///-------------------------------------------------------------------------- +/// +/// RESTsoft - Software for Rare Event Searches with TPCs +/// +/// History of developments: +/// +/// 2015-aug: First concept. +/// Javier Galan +/// +/// \class TRestReadoutPixel +/// \author Javier Galan +/// +///
+/// + +double delta = 1.e-6; + +#include "TRestReadoutPixel.h" +using namespace std; + +ClassImp(TRestReadoutPixel); +/////////////////////////////////////////////// +/// \brief TRestReadoutPixel default constructor +/// +TRestReadoutPixel::TRestReadoutPixel() { Initialize(); } + +/////////////////////////////////////////////// +/// \brief TRestReadoutPixel default destructor +/// +TRestReadoutPixel::~TRestReadoutPixel() {} + +/////////////////////////////////////////////// +/// \brief Initializes the pixel members +/// +void TRestReadoutPixel::Initialize() {} + +/////////////////////////////////////////////// +/// \brief Returns the center TVector2 position of the pixel +/// +TVector2 TRestReadoutPixel::GetCenter() const { + TVector2 center(0, 0); + TVector2 origin(fPixelOriginX, fPixelOriginY); + TVector2 opositeVertex = GetVertex(2); + + if (fTriangle) + center = (opositeVertex - origin) / 4. + origin; + else + center = (origin + opositeVertex) / 2.; + + return center; + //*/ +} + +/////////////////////////////////////////////// +/// \brief Returns the specified pixel vertex position +/// +/// \param n A value between 0-3 definning the vertex position to be returned. +/// +TVector2 TRestReadoutPixel::GetVertex(int n) const { + TVector2 vertex(0, 0); + TVector2 origin(fPixelOriginX, fPixelOriginY); + + if (n % 4 == 0) + return origin; + else if (n % 4 == 1) { + vertex.Set(fPixelSizeX, 0); + vertex = vertex.Rotate(fRotation * TMath::Pi() / 180.); + + vertex = vertex + origin; + } else if (n % 4 == 2) { + vertex.Set(fPixelSizeX, fPixelSizeY); + vertex = vertex.Rotate(fRotation * TMath::Pi() / 180.); + + vertex = vertex + origin; + } else if (n % 4 == 3) { + vertex.Set(0, fPixelSizeY); + vertex = vertex.Rotate(fRotation * TMath::Pi() / 180.); + + vertex = vertex + origin; + } + return vertex; +} + +/////////////////////////////////////////////// +/// \brief Determines if a given *x,y* coordinates are found inside the pixel. +/// The coordinates are referenced to the readout module system. +/// +Bool_t TRestReadoutPixel::isInside(Double_t x, Double_t y) { + TVector2 pos(x, y); + return isInside(pos); +} + +/////////////////////////////////////////////// +/// \brief Determines if a given TVector2 *pos* coordinates are found inside +/// the pixel. The coordinates are referenced to the readout module system. +/// +Bool_t TRestReadoutPixel::isInside(TVector2 pos) { + pos = TransformToPixelCoordinates(pos); + Double_t const x = pos.X(); + if (pos.X() >= -delta && pos.X() <= fPixelSizeX + delta) // Condition on X untouched + { + if (fTriangle && pos.Y() >= -delta && + pos.Y() <= fPixelSizeY + delta - + x * (fPixelSizeY / fPixelSizeX)) // if triangle, third condition depends on x + return true; + if (!fTriangle && pos.Y() >= -delta && + pos.Y() <= fPixelSizeY + delta) // for a normal rectangular pixel, same + // simple conditions + return true; + } + return false; +} + +/////////////////////////////////////////////// +/// \brief Transforms the coordinates given in a TVector2 to the internal +/// pixel coordinate system. The coordinates are referenced to the readout +/// module system. +/// +TVector2 TRestReadoutPixel::TransformToPixelCoordinates(TVector2 p) { + TVector2 pos(p.X() - fPixelOriginX, p.Y() - fPixelOriginY); + pos = pos.Rotate(-fRotation * TMath::Pi() / 180.); + return pos; +} + +/////////////////////////////////////////////// +/// \brief Prints on screen the pixel details, origin, size, rotation +/// +void TRestReadoutPixel::Print() { + RESTMetadata << " ## Pixel position : (" << GetOriginX() << "," << GetOriginY() << ") mm size : (" + << GetSizeX() << "," << GetSizeY() << ") mm" << RESTendl; + RESTMetadata << " rotation : " << fRotation << " degrees" + << " type : "; + if (fTriangle) + RESTMetadata << "triangle" << RESTendl; + else + RESTMetadata << "rectangle" << RESTendl; +} diff --git a/src/TRestReadoutPlane.cxx b/src/TRestReadoutPlane.cxx new file mode 100644 index 0000000..5fdc975 --- /dev/null +++ b/src/TRestReadoutPlane.cxx @@ -0,0 +1,450 @@ +/************************************************************************* + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * REST is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +/// +/// This class stores the readout plane geometrical description, plane +/// position, orientation, and cathode position. It contains +/// a vector of TRestReadoutModule with the readout modules that are +/// implemented in the readout plane. +/// +///-------------------------------------------------------------------------- +/// +/// RESTsoft - Software for Rare Event Searches with TPCs +/// +/// History of developments: +/// +/// 2016-mar: First concept. +/// Javier Galan +/// +/// \class TRestReadoutPlane +/// \author Javier Galan +/// +///
+/// + +#include "TRestReadoutPlane.h" +using namespace std; + +ClassImp(TRestReadoutPlane); +/////////////////////////////////////////////// +/// \brief Default TRestReadoutPlane constructor +/// +TRestReadoutPlane::TRestReadoutPlane() { Initialize(); } + +/////////////////////////////////////////////// +/// \brief Default TRestReadoutPlane destructor +/// +TRestReadoutPlane::~TRestReadoutPlane() {} + +/////////////////////////////////////////////// +/// \brief TRestReadoutPlane initialization +/// +void TRestReadoutPlane::Initialize() { + fCathodePosition = TVector3(0, 0, 0); + fPosition = TVector3(0, 0, 0); + fPlaneVector = TVector3(0, 0, 0); + + fNModules = 0; + fReadoutModules.clear(); +} + +/////////////////////////////////////////////// +/// \brief Returns the total number of channels in the readout plane +/// +Int_t TRestReadoutPlane::GetNumberOfChannels() { + Int_t nChannels = 0; + for (int md = 0; md < GetNumberOfModules(); md++) nChannels += fReadoutModules[md].GetNumberOfChannels(); + return nChannels; +} + +/////////////////////////////////////////////// +/// \brief Calculates the drift distance between readout plane and cathode +/// +void TRestReadoutPlane::SetDriftDistance() { + Double_t tDriftDistance = this->GetDistanceTo(this->GetCathodePosition()); + this->SetTotalDriftDistance(tDriftDistance); +} + +/////////////////////////////////////////////// +/// \brief Returns a pointer to a module using its internal module id +/// +TRestReadoutModule* TRestReadoutPlane::GetModuleByID(Int_t modID) { + for (int md = 0; md < GetNumberOfModules(); md++) + if (fReadoutModules[md].GetModuleID() == modID) return &fReadoutModules[md]; + + cout << "REST ERROR (GetReadoutModuleByID) : Module ID : " << modID << " was not found" << endl; + return NULL; +} + +/////////////////////////////////////////////// +/// \brief Returns the X coordinate of a given channel in a given module using +/// their internal module and channel ids. +/// +/// This method evaluates if the channel is a strip or a pixel. If it is a +/// strip and the X-axis is not localized, this function returns NaN. +/// +/// \param modID Internal module id. As defined on the readout. +/// \param chID Internal channel id. As defined on the readout. +/// +/// \return The value of the X-coordinate relative to the readout position +Double_t TRestReadoutPlane::GetX(Int_t modID, Int_t chID) { + TRestReadoutModule* rModule = GetModuleByID(modID); + Double_t xOrigin = rModule->GetModuleOriginX(); + + TRestReadoutChannel* rChannel = rModule->GetChannel(chID); + + Double_t x = numeric_limits::quiet_NaN(); + + if (rChannel->GetNumberOfPixels() == 1) { + Double_t sX = rChannel->GetPixel(0)->GetSize().X(); + Double_t sY = rChannel->GetPixel(0)->GetSize().Y(); + + if (sX > 2 * sY) return x; + + x = rModule->GetPixelCenter(chID, 0).X(); + + return x; + } + + if (rChannel->GetNumberOfPixels() > 1) { + Int_t nPix = rChannel->GetNumberOfPixels(); + + // We check the origin of consecutive pixels to check if it goes X or Y + // direction. Perhaps more complex readouts need some changes here + Double_t x1 = rChannel->GetPixel(0)->GetCenter().X(); + Double_t x2 = rChannel->GetPixel(nPix - 1)->GetCenter().X(); + + Double_t y1 = rChannel->GetPixel(0)->GetCenter().Y(); + Double_t y2 = rChannel->GetPixel(nPix - 1)->GetCenter().Y(); + + /* + cout << "Pixel 0. X : " << x1 << " Y : " << y1 endl; + cout << "Pixel N. X : " << x2 << " Y : " << y2 endl; + */ + + Double_t deltaX = abs(x2 - x1); + Double_t deltaY = abs(y2 - y1); + + Int_t rotation = (Int_t)rModule->GetModuleRotation(); + if (rotation % 90 == 0) { + if (rotation / 90 % 2 == 0) // rotation is 0, 180, 360... + { + if (deltaY > deltaX) x = rModule->GetPixelCenter(chID, 0).X(); + } else // rotation is 90, 270... We need to invert x and y + { + if (deltaY < deltaX) x = rModule->GetPixelCenter(chID, 0).X(); + } + } else { + // we choose to ouput x only when deltaY > deltaX under non-90 rotation + // otherwise it is a y channel and should return nan + if (deltaY > deltaX) x = rModule->GetPixelCenter(chID, 0).X(); + } + } + + return x; +} + +/////////////////////////////////////////////// +/// \brief Returns the Y coordinate of a given channel in a given module using +/// their internal module and channel ids. +/// +/// This method evaluates if the channel is a strip or a pixel. If it is a +/// strip and the Y-axis is not localized, this function returns NaN. +/// +/// \param modID Internal module id. As defined on the readout. +/// \param chID Internal channel id. As defined on the readout. +/// +/// \return The value of the X-coordinate relative to the readout position +Double_t TRestReadoutPlane::GetY(Int_t modID, Int_t chID) { + TRestReadoutModule* rModule = GetModuleByID(modID); + Double_t yOrigin = rModule->GetModuleOriginY(); + + TRestReadoutChannel* rChannel = rModule->GetChannel(chID); + + Double_t y = numeric_limits::quiet_NaN(); + + if (rChannel->GetNumberOfPixels() == 1) { + Double_t sX = rChannel->GetPixel(0)->GetSize().X(); + Double_t sY = rChannel->GetPixel(0)->GetSize().Y(); + + if (sY > 2 * sX) return y; + + y = rModule->GetPixelCenter(chID, 0).Y(); + + return y; + } + + if (rChannel->GetNumberOfPixels() > 1) { + Int_t nPix = rChannel->GetNumberOfPixels(); + + // We check the origin of consecutive pixels to check if it goes X or Y + // direction. Perhaps more complex readouts need some changes here + Double_t x1 = rChannel->GetPixel(0)->GetCenter().X(); + Double_t x2 = rChannel->GetPixel(nPix - 1)->GetCenter().X(); + + Double_t y1 = rChannel->GetPixel(0)->GetCenter().Y(); + Double_t y2 = rChannel->GetPixel(nPix - 1)->GetCenter().Y(); + + /* + cout << "Pix id : " << rChannel->GetPixel(0)->GetID() << " X1 : " << x1 + << endl; cout << "Pix id : " << rChannel->GetPixel(1)->GetID() << " X2 : + " << x2 << endl; cout << "Pix id : " << rChannel->GetPixel(0)->GetID() << + " Y1 : " << y1 << endl; cout << "Pix id : " << + rChannel->GetPixel(1)->GetID() << " Y2 : " << y2 << endl; + */ + + Double_t deltaX = abs(x2 - x1); + Double_t deltaY = abs(y2 - y1); + + Int_t rotation = (Int_t)rModule->GetModuleRotation(); + if (rotation % 90 == 0) { + if (rotation / 90 % 2 == 0) // rotation is 0, 180, 360... + { + if (deltaY < deltaX) y = rModule->GetPixelCenter(chID, 0).Y(); + } else // rotation is 90, 270... We need to invert x and y + { + if (deltaY > deltaX) y = rModule->GetPixelCenter(chID, 0).Y(); + } + } else { + // we choose to ouput y only when deltaY < deltaX under non-90 rotation + // otherwise it is a x channel and should return nan + if (deltaY < deltaX) y = rModule->GetPixelCenter(chID, 0).Y(); + } + } + + return y; +} + +/////////////////////////////////////////////// +/// \brief Finds the readout channel index for a given module stored in a given +/// module index stored in the readout plane (internal readout plane module id). +/// +/// \param absX It is the x absolut physical position +/// \param absY It is the y absolut physical position +/// \return The corresponding channel id +Int_t TRestReadoutPlane::FindChannel(Int_t module, Double_t absX, Double_t absY) { + Double_t modX = absX - fPosition.X(); + Double_t modY = absY - fPosition.Y(); + + // TODO : check first if (modX,modY) is inside the module. + // If not return error. + // FindChannel will take a long time to search for the channel if it is not + // there. It will be faster + + return fReadoutModules[module].FindChannel(modX, modY); +} + +/////////////////////////////////////////////// +/// \brief Returns the perpendicular distance to the readout plane of a given +/// *x*, *y*, *z* position +/// +Double_t TRestReadoutPlane::GetDistanceTo(Double_t x, Double_t y, Double_t z) { + return GetDistanceTo(TVector3(x, y, z)); +} + +/////////////////////////////////////////////// +/// \brief Returns the perpendicular distance to the readout plane of a given +/// TVector3 position +/// +Double_t TRestReadoutPlane::GetDistanceTo(TVector3 pos) { + return (pos - GetPosition()).Dot(GetPlaneVector()); +} + +/////////////////////////////////////////////// +/// \brief This method determines if a given position in *z* is inside the drift +/// volume drifting distance for this readout plane. +/// +/// \return 1 if the Z-position is found inside the drift volume definition. 0 +/// otherwise returns -1. +/// +Int_t TRestReadoutPlane::isZInsideDriftVolume(Double_t z) { + TVector3 pos = TVector3(0, 0, z); + + return isZInsideDriftVolume(pos); +} + +/////////////////////////////////////////////// +/// \brief This method determines if the daqId given is associated to any of the +/// readout readout channels in any readout modules. +/// +/// \return true if daqId is found +/// returns false if daqId is not found +/// +Bool_t TRestReadoutPlane::isDaqIDInside(Int_t daqId) { + for (int m = 0; m < GetNumberOfModules(); m++) + if (fReadoutModules[m].isDaqIDInside(daqId)) return true; + + return false; +} + +/////////////////////////////////////////////// +/// \brief This method determines if the z-coordinate is inside the drift volume +/// for this readout plane. +/// +/// \param pos A TVector3 definning the position. +/// +/// \return 1 if the Z-position is found inside the drift volume definition. 0 +/// otherwise +/// +Int_t TRestReadoutPlane::isZInsideDriftVolume(TVector3 pos) { + TVector3 posNew = TVector3(pos.X() - fPosition.X(), pos.Y() - fPosition.Y(), pos.Z()); + + Double_t distance = GetDistanceTo(posNew); + + if (distance > 0 && distance < fTotalDriftDistance) return 1; + + return 0; +} + +/////////////////////////////////////////////// +/// \brief This method returns the module id where the hits with coordinates +/// (x,y,z) is found. The z-coordinate must be found in between the cathode and +/// the readout plane. The *x* and *y* values must be found inside one of the +/// readout modules defined inside the readout plane. +/// +/// \param x,y,z Three Double_t definning the position. +/// +/// \return the module *id* where the hit is found. If no module *id* is found +/// it returns -1. +/// +Int_t TRestReadoutPlane::GetModuleIDFromPosition(Double_t x, Double_t y, Double_t z) { + TVector3 pos = TVector3(x, y, z); + + return GetModuleIDFromPosition(pos); +} +/////////////////////////////////////////////// +/// \brief This method returns the module id where *pos* is found. +/// The z-coordinate must be found in between +/// the cathode and the readout plane. The *x* and *y* values must be found +/// inside one of the readout modules defined inside the readout plane. +/// +/// \param pos A TVector3 definning the position. +/// +/// \return the module *id* where the hit is found. If no module *id* is found +/// it returns -1. +/// +Int_t TRestReadoutPlane::GetModuleIDFromPosition(TVector3 pos) { + TVector3 posNew = TVector3(pos.X() - fPosition.X(), pos.Y() - fPosition.Y(), pos.Z()); + + Double_t distance = GetDistanceTo(posNew); + + if (distance > 0 && distance < fTotalDriftDistance) { + for (int m = 0; m < GetNumberOfModules(); m++) + if (fReadoutModules[m].isInside(posNew.X(), posNew.Y())) return fReadoutModules[m].GetModuleID(); + } + + return -1; +} + +/////////////////////////////////////////////// +/// \brief Prints information with details of the readout plane and modules +/// defined inside the readout plane. +/// +void TRestReadoutPlane::Print(Int_t DetailLevel) { + if (DetailLevel >= 0) { + RESTMetadata << "-- Readout plane : " << GetID() << RESTendl; + RESTMetadata << "----------------------------------------------------------------" << RESTendl; + RESTMetadata << "-- Position : X = " << fPosition.X() << " mm, " + << " Y : " << fPosition.Y() << " mm, Z : " << fPosition.Z() << " mm" << RESTendl; + RESTMetadata << "-- Vector : X = " << fPlaneVector.X() << " mm, " + << " Y : " << fPlaneVector.Y() << " mm, Z : " << fPlaneVector.Z() << " mm" << RESTendl; + RESTMetadata << "-- Cathode Position : X = " << fCathodePosition.X() << " mm, " + << " Y : " << fCathodePosition.Y() << " mm, Z : " << fCathodePosition.Z() << " mm" + << RESTendl; + RESTMetadata << "-- Total drift distance : " << fTotalDriftDistance << " mm" << RESTendl; + RESTMetadata << "-- Charge collection : " << fChargeCollection << RESTendl; + RESTMetadata << "-- Total modules : " << GetNumberOfModules() << RESTendl; + RESTMetadata << "-- Total channels : " << GetNumberOfChannels() << RESTendl; + RESTMetadata << "----------------------------------------------------------------" << RESTendl; + + for (int i = 0; i < GetNumberOfModules(); i++) fReadoutModules[i].Print(DetailLevel - 1); + } +} + +/////////////////////////////////////////////// +/// \brief Draws the readout plane using GetReadoutHistogram. +/// +void TRestReadoutPlane::Draw() { this->GetReadoutHistogram()->Draw(); } + +/////////////////////////////////////////////// +/// \brief Creates and resturns a TH2Poly object with the +/// readout pixel description. +/// +TH2Poly* TRestReadoutPlane::GetReadoutHistogram() { + Double_t x[4]; + Double_t y[4]; + + double xmin, xmax, ymin, ymax; + + GetBoundaries(xmin, xmax, ymin, ymax); + + TH2Poly* readoutHistogram = new TH2Poly("ReadoutHistogram", "ReadoutHistogram", xmin, xmax, ymin, ymax); + + for (int mdID = 0; mdID < this->GetNumberOfModules(); mdID++) { + TRestReadoutModule* module = &fReadoutModules[mdID]; + + int nChannels = module->GetNumberOfChannels(); + + for (int ch = 0; ch < nChannels; ch++) { + TRestReadoutChannel* channel = module->GetChannel(ch); + Int_t nPixels = channel->GetNumberOfPixels(); + + for (int px = 0; px < nPixels; px++) { + for (int v = 0; v < 4; v++) { + x[v] = module->GetPixelVertex(ch, px, v).X(); + y[v] = module->GetPixelVertex(ch, px, v).Y(); + } + + readoutHistogram->AddBin(4, x, y); + } + } + } + + readoutHistogram->SetStats(0); + + return readoutHistogram; +} + +/////////////////////////////////////////////// +/// \brief Finds the xy boundaries of the readout plane delimited by the modules +/// +void TRestReadoutPlane::GetBoundaries(double& xmin, double& xmax, double& ymin, double& ymax) { + Double_t x[4]; + Double_t y[4]; + + xmin = 1E9, xmax = -1E9, ymin = 1E9, ymax = -1E9; + + for (int mdID = 0; mdID < this->GetNumberOfModules(); mdID++) { + TRestReadoutModule* module = &fReadoutModules[mdID]; + + for (int v = 0; v < 4; v++) { + x[v] = module->GetVertex(v).X(); + y[v] = module->GetVertex(v).Y(); + + if (x[v] < xmin) xmin = x[v]; + if (y[v] < ymin) ymin = y[v]; + if (x[v] > xmax) xmax = x[v]; + if (y[v] > ymax) ymax = y[v]; + } + } +} diff --git a/src/TRestSignal.cxx b/src/TRestSignal.cxx new file mode 100644 index 0000000..263a9af --- /dev/null +++ b/src/TRestSignal.cxx @@ -0,0 +1,520 @@ +///______________________________________________________________________________ +///______________________________________________________________________________ +///______________________________________________________________________________ +/// +/// +/// RESTSoft : Software for Rare Event Searches with TPCs +/// +/// TRestSignal.cxx +/// +/// Event class to store signals from simulation and acquisition +/// events +/// +/// sept 2015: First concept +/// Created as part of the conceptualization of existing REST +/// software. +/// JuanAn Garcia/Javier Galan +/// nov 2015: +/// Changed vectors fSignalTime and fSignalCharge from +/// to +///< Float_t> JuanAn Garcia +// dec 2015: +// +// Javier Galan +///_______________________________________________________________________________ + +#include "TRestSignal.h" +using namespace std; + +#include +#include +#include + +ClassImp(TRestSignal) + //______________________________________________________________________________ + TRestSignal::TRestSignal() { + // TRestSignal default constructor + fGraph = NULL; + fSignalID = -1; + fSignalTime.clear(); + fSignalCharge.clear(); + + fPointsOverThreshold.clear(); +} + +//______________________________________________________________________________ +TRestSignal::~TRestSignal() { + // TRestSignal destructor +} + +void TRestSignal::NewPoint(Float_t time, Float_t data) { + fSignalTime.push_back(time); + fSignalCharge.push_back(data); +} + +void TRestSignal::AddPoint(TVector2 p) { + Int_t index = GetTimeIndex(p.X()); + Float_t x = p.X(); + Float_t y = p.Y(); + + if (index >= 0) { + fSignalTime[index] = x; + fSignalCharge[index] += y; + } else { + fSignalTime.push_back(x); + fSignalCharge.push_back(y); + } +} +void TRestSignal::SetPoint(TVector2 p) { + Int_t index = GetTimeIndex(p.X()); + Float_t x = p.X(); + Float_t y = p.Y(); + + if (index >= 0) { + fSignalTime[index] = x; + fSignalCharge[index] = y; + } else { + fSignalTime.push_back(x); + fSignalCharge.push_back(y); + } +} + +void TRestSignal::AddPoint(Double_t t, Double_t d) { + TVector2 p(t, d); + AddPoint(p); +} +void TRestSignal::AddCharge(Double_t t, Double_t d) { + TVector2 p(t, d); + AddPoint(p); +} +void TRestSignal::AddDeposit(Double_t t, Double_t d) { + TVector2 p(t, d); + AddPoint(p); +} + +void TRestSignal::SetPoint(Double_t t, Double_t d) { + TVector2 p(t, d); + SetPoint(p); +} +void TRestSignal::SetPoint(Int_t index, Double_t t, Double_t d) { + fSignalTime[index] = t; + fSignalCharge[index] = d; +} + +Double_t TRestSignal::GetIntegral(Int_t startBin, Int_t endBin) { + if (startBin < 0) startBin = 0; + if (endBin <= 0 || endBin > GetNumberOfPoints()) endBin = GetNumberOfPoints(); + + Double_t sum = 0; + for (int i = startBin; i < endBin; i++) sum += GetData(i); + + return sum; +} + +void TRestSignal::Normalize(Double_t scale) { + Double_t sum = GetIntegral(); + + for (int i = 0; i < GetNumberOfPoints(); i++) fSignalCharge[i] = scale * GetData(i) / sum; +} + +Double_t TRestSignal::GetIntegralWithTime(Double_t startTime, Double_t endTime) { + Double_t sum = 0; + for (int i = 0; i < GetNumberOfPoints(); i++) + if (GetTime(i) >= startTime && GetTime(i) < endTime) sum += GetData(i); + + return sum; +} + +Double_t TRestSignal::GetMaxPeakWithTime(Double_t startTime, Double_t endTime) { + Double_t max = -1E10; + + for (int i = 0; i < GetNumberOfPoints(); i++) + if (GetTime(i) >= startTime && GetTime(i) < endTime) { + if (this->GetData(i) > max) max = GetData(i); + } + + return max; +} + +/* {{{ +Double_t TRestSignal::GetIntegralWithThreshold(Int_t from, Int_t to, Int_t startBaseline, Int_t endBaseline, + Double_t nSigmas, Int_t nPointsOverThreshold, + Double_t nMinSigmas) { + if (startBaseline < 0) startBaseline = 0; + if (endBaseline <= 0 || endBaseline > GetNumberOfPoints()) endBaseline = GetNumberOfPoints(); + + Double_t baseLine = GetBaseLine(startBaseline, endBaseline); + + Double_t pointThreshold = nSigmas * GetBaseLineSigma(startBaseline, endBaseline); + Double_t signalThreshold = nMinSigmas * GetBaseLineSigma(startBaseline, endBaseline); + + return GetIntegralWithThreshold(from, to, baseLine, pointThreshold, nPointsOverThreshold, + signalThreshold); +} + +Double_t TRestSignal::GetIntegralWithThreshold(Int_t from, Int_t to, Double_t baseline, + Double_t pointThreshold, Int_t nPointsOverThreshold, + Double_t signalThreshold) { + Double_t sum = 0; + Int_t nPoints = 0; + fPointsOverThreshold.clear(); + + if (to > GetNumberOfPoints()) to = GetNumberOfPoints(); + + Float_t maxValue = 0; + for (int i = from; i < to; i++) { + if (GetData(i) > baseline + pointThreshold) { + if (GetData(i) > maxValue) maxValue = GetData(i); + nPoints++; + } else { + if (nPoints >= nPointsOverThreshold) { + Double_t sig = GetStandardDeviation(i - nPoints, i); + if (sig > signalThreshold) { + for (int j = i - nPoints; j < i; j++) { + sum += this->GetData(j); + fPointsOverThreshold.push_back(j); + } + } + } + nPoints = 0; + maxValue = 0; + } + } + + if (nPoints >= nPointsOverThreshold) { + Double_t sig = GetStandardDeviation(to - nPoints, to); + if (sig > signalThreshold) { + for (int j = to - nPoints; j < to; j++) { + sum += this->GetData(j); + fPointsOverThreshold.push_back(j); + } + } + } + + return sum; +} +}}} */ + +Double_t TRestSignal::GetAverage(Int_t start, Int_t end) { + this->Sort(); + + if (end == 0) end = this->GetNumberOfPoints(); + + Double_t sum = 0; + for (int i = start; i <= end; i++) { + sum += this->GetData(i); + } + return sum / (end - start + 1); +} + +Int_t TRestSignal::GetMaxPeakWidth() { + this->Sort(); + + Int_t mIndex = this->GetMaxIndex(); + Double_t maxValue = this->GetData(mIndex); + + Double_t value = maxValue; + Int_t rightIndex = mIndex; + while (value > maxValue / 2) { + value = this->GetData(rightIndex); + rightIndex++; + } + Int_t leftIndex = mIndex; + value = maxValue; + while (value > maxValue / 2) { + value = this->GetData(leftIndex); + leftIndex--; + } + + return rightIndex - leftIndex; +} + +Double_t TRestSignal::GetMaxPeakValue() { return GetData(GetMaxIndex()); } + +Int_t TRestSignal::GetMaxIndex(Int_t from, Int_t to) { + Double_t max = -1E10; + Int_t index = 0; + + if (from < 0) from = 0; + if (to > GetNumberOfPoints()) to = GetNumberOfPoints(); + + if (to == 0) to = GetNumberOfPoints(); + + for (int i = from; i < to; i++) { + if (this->GetData(i) > max) { + max = GetData(i); + index = i; + } + } + + return index; +} + +Double_t TRestSignal::GetMaxPeakTime(Int_t from, Int_t to) { return GetTime(GetMaxIndex(from, to)); } + +Double_t TRestSignal::GetMinPeakValue() { return GetData(GetMinIndex()); } + +Int_t TRestSignal::GetMinIndex() { + Double_t min = 1E10; + Int_t index = 0; + + for (int i = 0; i < GetNumberOfPoints(); i++) { + if (this->GetData(i) < min) { + min = GetData(i); + index = i; + } + } + + return index; +} + +Double_t TRestSignal::GetMinTime() { + Double_t minTime = 1E10; + for (int n = 0; n < GetNumberOfPoints(); n++) + if (minTime > fSignalTime[n]) minTime = fSignalTime[n]; + + return minTime; +} + +Double_t TRestSignal::GetMaxTime() { + Double_t maxTime = -1E10; + for (int n = 0; n < GetNumberOfPoints(); n++) + if (maxTime < fSignalTime[n]) maxTime = fSignalTime[n]; + + return maxTime; +} + +Int_t TRestSignal::GetTimeIndex(Double_t t) { + Float_t time = t; + + for (int n = 0; n < GetNumberOfPoints(); n++) + if (time == fSignalTime[n]) return n; + return -1; +} + +Bool_t TRestSignal::isSorted() { + for (int i = 0; i < GetNumberOfPoints() - 1; i++) { + if (GetTime(i + 1) < GetTime(i)) return false; + } + return true; +} + +void TRestSignal::Sort() { + while (!isSorted()) { + for (int i = 0; i < GetNumberOfPoints(); i++) { + for (int j = i; j < GetNumberOfPoints(); j++) { + if (GetTime(i) > GetTime(j)) { + iter_swap(fSignalTime.begin() + i, fSignalTime.begin() + j); + iter_swap(fSignalCharge.begin() + i, fSignalCharge.begin() + j); + } + } + } + } +} + +void TRestSignal::GetDifferentialSignal(TRestSignal* diffSgnl, Int_t smearPoints) { + this->Sort(); + + for (int i = 0; i < smearPoints; i++) diffSgnl->AddPoint(GetTime(i), 0); + + for (int i = smearPoints; i < this->GetNumberOfPoints() - smearPoints; i++) { + Double_t value = (this->GetData(i + smearPoints) - GetData(i - smearPoints)) / + (GetTime(i + smearPoints) - GetTime(i - smearPoints)); + Double_t time = (GetTime(i + smearPoints) + GetTime(i - smearPoints)) / 2.; + + diffSgnl->AddPoint(time, value); + } + + for (int i = GetNumberOfPoints() - smearPoints; i < GetNumberOfPoints(); i++) + diffSgnl->AddPoint(GetTime(i), 0); +} + +void TRestSignal::GetSignalDelayed(TRestSignal* delayedSignal, Int_t delay) { + this->Sort(); + + for (int i = 0; i < delay; i++) delayedSignal->AddPoint(GetTime(i), GetData(i)); + + for (int i = delay; i < GetNumberOfPoints(); i++) delayedSignal->AddPoint(GetTime(i), GetData(i - delay)); +} + +void TRestSignal::GetSignalSmoothed(TRestSignal* smthSignal, Int_t averagingPoints) { + this->Sort(); + + averagingPoints = (averagingPoints / 2) * 2 + 1; // make it odd >= averagingPoints + + Double_t sum = GetIntegral(0, averagingPoints); + for (int i = 0; i <= averagingPoints / 2; i++) smthSignal->AddPoint(GetTime(i), sum / averagingPoints); + + for (int i = averagingPoints / 2 + 1; i < GetNumberOfPoints() - averagingPoints / 2; i++) { + sum -= this->GetData(i - (averagingPoints / 2 + 1)); + sum += this->GetData(i + averagingPoints / 2); + smthSignal->AddPoint(this->GetTime(i), sum / averagingPoints); + } + + for (int i = GetNumberOfPoints() - averagingPoints / 2; i < GetNumberOfPoints(); i++) + smthSignal->AddPoint(GetTime(i), sum / averagingPoints); +} + +Double_t TRestSignal::GetBaseLine(Int_t startBin, Int_t endBin) { + if (endBin - startBin <= 0) return 0.; + + Double_t baseLine = 0; + for (int i = startBin; i < endBin; i++) baseLine += fSignalCharge[i]; + + return baseLine / (endBin - startBin); +} + +Double_t TRestSignal::GetStandardDeviation(Int_t startBin, Int_t endBin) { + Double_t bL = GetBaseLine(startBin, endBin); + return GetBaseLineSigma(startBin, endBin, bL); +} + +Double_t TRestSignal::GetBaseLineSigma(Int_t startBin, Int_t endBin, Double_t baseline) { + Double_t bL = baseline; + if (bL == 0) bL = GetBaseLine(startBin, endBin); + + Double_t baseLineSigma = 0; + for (int i = startBin; i < endBin; i++) + baseLineSigma += (bL - fSignalCharge[i]) * (bL - fSignalCharge[i]); + + return TMath::Sqrt(baseLineSigma / (endBin - startBin)); +} + +Double_t TRestSignal::SubstractBaseline(Int_t startBin, Int_t endBin) { + Double_t bL = GetBaseLine(startBin, endBin); + + AddOffset(-bL); + + return bL; +} + +void TRestSignal::AddOffset(Double_t offset) { + for (int i = 0; i < GetNumberOfPoints(); i++) fSignalCharge[i] = fSignalCharge[i] + offset; +} + +void TRestSignal::MultiplySignalBy(Double_t factor) { + for (int i = 0; i < GetNumberOfPoints(); i++) fSignalCharge[i] = factor * fSignalCharge[i]; +} + +void TRestSignal::ExponentialConvolution(Double_t fromTime, Double_t decayTime, Double_t offset) { + for (int i = 0; i < GetNumberOfPoints(); i++) { + if (fSignalTime[i] > fromTime) + fSignalCharge[i] = + (fSignalCharge[i] - offset) * exp(-(fSignalTime[i] - fromTime) / decayTime) + offset; + } +} + +void TRestSignal::SignalAddition(TRestSignal* inSgnl) { + if (this->GetNumberOfPoints() != inSgnl->GetNumberOfPoints()) { + cout << "ERROR : I cannot add two signals with different number of points" << endl; + return; + } + + Int_t badSignalTimes = 0; + + for (int i = 0; i < GetNumberOfPoints(); i++) + if (GetTime(i) != inSgnl->GetTime(i)) { + cout << "Time : " << GetTime(i) << " != " << inSgnl->GetTime(i) << endl; + badSignalTimes++; + } + + if (badSignalTimes) { + cout << "ERROR : The times of signal addition must be the same" << endl; + return; + } + + for (int i = 0; i < GetNumberOfPoints(); i++) fSignalCharge[i] += inSgnl->GetData(i); +} + +void TRestSignal::AddGaussianSignal(Double_t amp, Double_t sigma, Double_t time, Int_t N, Double_t fromTime, + Double_t toTime) { + for (int i = 0; i < N; i++) { + Double_t tme = fromTime + (double)i / (N - 1) * (toTime - fromTime); + + Double_t dta = 300 + amp * TMath::Exp(-0.5 * (tme - time) * (tme - time) / sigma / sigma); + + cout << "T : " << tme << " D : " << dta << endl; + AddPoint(tme, dta); + } +} + +void TRestSignal::GetWhiteNoiseSignal(TRestSignal* noiseSgnl, Double_t noiseLevel) { + this->Sort(); + + for (int i = 0; i < GetNumberOfPoints(); i++) { + TRandom3* fRandom = new TRandom3(0); + + noiseSgnl->AddPoint(GetTime(i), GetData(i) + fRandom->Gaus(0, noiseLevel)); + + delete fRandom; + } +} + +void TRestSignal::GetSignalGaussianConvolution(TRestSignal* convSgnl, Double_t sigma, Int_t nSigmas) { + this->Sort(); + + Int_t nPoints = GetMaxTime() - GetMinTime(); + TF1* fGaus = new TF1("fGauss", "exp(-0.5*((x-[1])/[2])**2)", -nPoints, nPoints); + sigma = sigma * 1000.; // conversion to nanoseconds + fGaus->SetParameter(2, sigma); // the width of the gaussian is set + + Double_t totChargeInitial = 0.; + Double_t totChargeFinal = 0.; + + Double_t sum; + + // We calculate the charge of the event before convolution + for (int i = 0; i < GetNumberOfPoints(); i++) totChargeInitial += fSignalCharge[i]; + + // The gaussian convolution of the initial signal is performed + for (int i = GetMinTime() - nSigmas * sigma; i < GetMaxTime() + nSigmas * sigma; i++) { + for (int j = 0; j < GetNumberOfPoints(); j++) { + if (TMath::Abs(i - GetTime(j)) > nSigmas * sigma) continue; + if (TMath::Abs(i - GetTime(j)) > nSigmas * sigma && i < GetTime(j)) break; + + fGaus->SetParameter(1, GetTime(j)); + sum = fSignalCharge[j] / TMath::Sqrt(2. * TMath::Pi()) / sigma * fGaus->Integral(i, i + 1); + + convSgnl->AddPoint(i, sum); + totChargeFinal += sum; + } + } + + cout << "Initial charge of the pulse " << totChargeInitial << endl; + cout << "Final charge of the pulse " << totChargeFinal << endl; +} + +void TRestSignal::WriteSignalToTextFile(TString filename) { + FILE* fff = fopen(filename.Data(), "w"); + for (int i = 0; i < GetNumberOfPoints(); i++) fprintf(fff, "%e\t%e\n", GetTime(i), GetData(i)); + fclose(fff); +} + +void TRestSignal::Print() { + for (int i = 0; i < GetNumberOfPoints(); i++) + cout << "Time : " << GetTime(i) << " Charge : " << GetData(i) << endl; +} + +TGraph* TRestSignal::GetGraph(Int_t color) { + if (fGraph != NULL) { + delete fGraph; + fGraph = NULL; + } + + fGraph = new TGraph(); + + // cout << "Signal ID " << this->GetSignalID( ) << " points " << + // this->GetNumberOfPoints() << endl; + + fGraph->SetLineWidth(2); + fGraph->SetLineColor(color); + fGraph->SetMarkerStyle(7); + + int points = 0; + for (int n = 0; n < GetNumberOfPoints(); n++) { + fGraph->SetPoint(points, GetTime(n), GetData(n)); + points++; + } + + return fGraph; +} diff --git a/src/TRestSignalEvent.cxx b/src/TRestSignalEvent.cxx new file mode 100644 index 0000000..5012973 --- /dev/null +++ b/src/TRestSignalEvent.cxx @@ -0,0 +1,240 @@ +//______________________________________________________________________________ +///______________________________________________________________________________ +///______________________________________________________________________________ +/// +/// +/// RESTSoft : Software for Rare Event Searches with TPCs +/// +/// TRestSignalEvent.h +/// +/// Event class to store DAQ events either from simulation and +/// acquisition +/// +/// sept 2015: First concept +/// Created as part of the conceptualization of existing REST +/// software. +/// JuanAn Garcia/Javier Galan +/// +/// feb 2016: Added titles to axis in DrawGraph using TMultiGraph +/// Javier Gracia +///_______________________________________________________________________________ + +#include + +#include "TRestRun.h" +#include "TRestSignalEvent.h" +using namespace std; + +ClassImp(TRestSignalEvent) + //______________________________________________________________________________ + TRestSignalEvent::TRestSignalEvent() { + // TRestSignalEvent default constructor + RESTWarning << "Creating legacy event TRestSignalEvent" << RESTendl; + RESTWarning << "This event is now named TRestDetectorSignalEvent" << RESTendl; + Initialize(); +} + +//______________________________________________________________________________ +TRestSignalEvent::~TRestSignalEvent() { + // TRestSignalEvent destructor +} + +void TRestSignalEvent::Initialize() { + TRestEvent::Initialize(); + fSignal.clear(); + fPad = NULL; + fMinValue = 1E10; + fMaxValue = -1E10; + fMinTime = 1E10; + fMaxTime = -1E10; +} + +void TRestSignalEvent::AddSignal(TRestSignal s) { + if (signalIDExists(s.GetSignalID())) { + cout << "Warning. Signal ID : " << s.GetSignalID() + << " already exists. Signal will not be added to signal event" << endl; + return; + } + + fSignal.push_back(s); +} + +Int_t TRestSignalEvent::GetSignalIndex(Int_t signalID) { + for (int i = 0; i < GetNumberOfSignals(); i++) + if (fSignal[i].GetSignalID() == signalID) return i; + return -1; +} + +Double_t TRestSignalEvent::GetIntegral(Int_t startBin, Int_t endBin) { + Double_t sum = 0; + + for (int i = 0; i < GetNumberOfSignals(); i++) sum += fSignal[i].GetIntegral(startBin, endBin); + + return sum; +} + +Double_t TRestSignalEvent::GetIntegralWithTime(Double_t startTime, Double_t endTime) { + Double_t sum = 0; + for (int n = 0; n < GetNumberOfSignals(); n++) sum += fSignal[n].GetIntegralWithTime(startTime, endTime); + + return sum; +} + +/* +Double_t TRestSignalEvent::GetIntegralWithThreshold(Int_t from, Int_t to, Int_t startBaseline, + Int_t endBaseline, Double_t nSigmas, + Int_t nPointsOverThreshold, Double_t minPeakAmplitude) { + Double_t sum = 0; + + for (int i = 0; i < GetNumberOfSignals(); i++) + sum += fSignal[i].GetIntegralWithThreshold(from, to, startBaseline, endBaseline, nSigmas, + nPointsOverThreshold, minPeakAmplitude); + + return sum; +} +*/ + +Double_t TRestSignalEvent::GetBaseLineAverage(Int_t startBin, Int_t endBin) { + Double_t baseLineMean = 0; + + for (int sgnl = 0; sgnl < GetNumberOfSignals(); sgnl++) { + Double_t baseline = GetSignal(sgnl)->GetBaseLine(startBin, endBin); + baseLineMean += baseline; + } + + return baseLineMean / GetNumberOfSignals(); +} + +Double_t TRestSignalEvent::GetBaseLineSigmaAverage(Int_t startBin, Int_t endBin) { + Double_t baseLineSigmaMean = 0; + + for (int sgnl = 0; sgnl < GetNumberOfSignals(); sgnl++) { + Double_t baselineSigma = GetSignal(sgnl)->GetBaseLineSigma(startBin, endBin); + baseLineSigmaMean += baselineSigma; + } + + return baseLineSigmaMean / GetNumberOfSignals(); +} + +void TRestSignalEvent::SubstractBaselines(Int_t startBin, Int_t endBin) { + for (int sgnl = 0; sgnl < GetNumberOfSignals(); sgnl++) + GetSignal(sgnl)->SubstractBaseline(startBin, endBin); +} + +void TRestSignalEvent::AddChargeToSignal(Int_t sgnlID, Double_t tm, Double_t chrg) { + Int_t sgnlIndex = GetSignalIndex(sgnlID); + if (sgnlIndex == -1) { + sgnlIndex = GetNumberOfSignals(); + + TRestSignal sgnl; + sgnl.SetSignalID(sgnlID); + AddSignal(sgnl); + } + + fSignal[sgnlIndex].AddDeposit(tm, chrg); +} + +void TRestSignalEvent::PrintEvent() { + TRestEvent::PrintEvent(); + + for (int i = 0; i < GetNumberOfSignals(); i++) { + cout << "================================================" << endl; + cout << "Signal ID : " << fSignal[i].GetSignalID() << endl; + cout << "Integral : " << fSignal[i].GetIntegral() << endl; + cout << "------------------------------------------------" << endl; + fSignal[i].Print(); + cout << "================================================" << endl; + } +} + +// TODO: GetMaxTimeFast, GetMinTimeFast, GetMaxValueFast that return the value +// of fMinTime, fMaxTime, etc +void TRestSignalEvent::SetMaxAndMin() { + fMinValue = 1E10; + fMaxValue = -1E10; + fMinTime = 1E10; + fMaxTime = -1E10; + + for (int s = 0; s < GetNumberOfSignals(); s++) { + if (fMinTime > fSignal[s].GetMinTime()) fMinTime = fSignal[s].GetMinTime(); + if (fMaxTime < fSignal[s].GetMaxTime()) fMaxTime = fSignal[s].GetMaxTime(); + + if (fMinValue > fSignal[s].GetMinValue()) fMinValue = fSignal[s].GetMinValue(); + if (fMaxValue < fSignal[s].GetMaxValue()) fMaxValue = fSignal[s].GetMaxValue(); + } +} + +Double_t TRestSignalEvent::GetMaxValue() { + SetMaxAndMin(); + return fMaxValue; +} + +Double_t TRestSignalEvent::GetMinValue() { + SetMaxAndMin(); + return fMinValue; +} + +Double_t TRestSignalEvent::GetMinTime() { + Double_t minTime = 1.e10; + for (int s = 0; s < GetNumberOfSignals(); s++) + if (minTime > fSignal[s].GetMinTime()) minTime = fSignal[s].GetMinTime(); + return minTime; +} + +Double_t TRestSignalEvent::GetMaxTime() { + Double_t maxTime = -1.e10; + for (int s = 0; s < GetNumberOfSignals(); s++) + if (maxTime < fSignal[s].GetMaxTime()) maxTime = fSignal[s].GetMaxTime(); + return maxTime; +} + +// Draw current event in a Tpad +TPad* TRestSignalEvent::DrawEvent(const TString& option) { + if (fPad != NULL) { + delete fPad; + fPad = NULL; + } + + int nSignals = this->GetNumberOfSignals(); + + if (nSignals == 0) { + cout << "Empty event " << endl; + return NULL; + } + + fMinValue = 1E10; + fMaxValue = -1E10; + fMinTime = 1E10; + fMaxTime = -1E10; + + fPad = new TPad(this->GetName(), " ", 0, 0, 1, 1); + fPad->Draw(); + fPad->cd(); + fPad->DrawFrame(GetMinTime(), GetMinValue(), GetMaxTime(), GetMaxValue()); + + char title[256]; + sprintf(title, "Event ID %d", this->GetID()); + + TMultiGraph* mg = new TMultiGraph(); + mg->SetTitle(title); + mg->GetXaxis()->SetTitle("Time [us]"); + mg->GetXaxis()->SetTitleOffset(1.1); + mg->GetYaxis()->SetTitle("Amplitude [a.u.]"); + mg->GetYaxis()->SetTitleOffset(0.8); + + mg->GetYaxis()->SetTitleSize(1.4 * mg->GetYaxis()->GetTitleSize()); + mg->GetXaxis()->SetTitleSize(1.4 * mg->GetXaxis()->GetTitleSize()); + mg->GetYaxis()->SetLabelSize(1.25 * mg->GetYaxis()->GetLabelSize()); + mg->GetXaxis()->SetLabelSize(1.25 * mg->GetXaxis()->GetLabelSize()); + + for (int n = 0; n < nSignals; n++) { + TGraph* gr = fSignal[n].GetGraph(n + 1); + + mg->Add(gr); + } + + fPad->cd(); + mg->Draw(""); + + return fPad; +} diff --git a/src/TRestSignalZeroSuppresionProcess.cxx b/src/TRestSignalZeroSuppresionProcess.cxx new file mode 100644 index 0000000..41395df --- /dev/null +++ b/src/TRestSignalZeroSuppresionProcess.cxx @@ -0,0 +1,89 @@ +/************************************************************************* + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * REST is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +/// The TRestSignalZeroSuppresionProcess identifies the points that are over +/// threshold from the input TRestRawSignalEvent. The resulting points, that +/// are presumed to be a physical signal, will be transported to the output +/// TRestSignalEvent returned by this process. The data points transferred to +/// the output TRestSignalEvent will have physical time units related to the +/// sampling rate of the raw signal received as input, and defined as a +/// parameter in this process. +/// +/// The different parameters required by this process are: +/// * baselineRange : A 2D-vector definning the range, in number of bins, +/// where the baseline properties will be calculated. +/// * integralRange : A 2D-vector definning the time window, in number of bins, +/// where the signal will be considered. +/// * pointThreshold : The number of sigmas over the baseline flunctuations to +/// consider a point is over the threshold. +/// * pointsOverThreshold : The number of consecutive points over threshold +/// required to consider them as a physical signal. +/// * signalThreshold : The number of sigmas a set of consecutive points +/// identified over threshold must be over the baseline fluctuations to be +/// finally considered a physical signal. +/// * pointsFlatThreshold : A parameter to help removing the un-physical or +/// un-expected tail that follows the physical signal. \TODO more details? +/// * sampling : The time duration of a time bin from the input TRestRawSignalEvent. +/// If no units are specified, the default units, microseconds, will be +/// considered. +/// +/// \TODO Add description of observables here. +/// +/// +/// An example of definition of this process inside a data processing chain, +/// inside the `` section. +/// +/// The values given between `${}` are enviroment variables that can be defined +/// at the system or at the `` section. See also TRestMetadata for +/// additional details. +/// +/// \code +/// +/// \endcode +/// +///-------------------------------------------------------------------------- +/// +/// RESTsoft - Software for Rare Event Searches with TPCs +/// +/// History of developments: +/// +/// 2016-January: Conception and implementation of signal zero suppression +/// process. +/// Javier Galan +/// +/// \class TRestSignalZeroSuppresionProcess +/// \author Javier Galan +/// \author Kaixiang Ni +/// +///
+/// + +#include "TRestSignalZeroSuppresionProcess.h" \ No newline at end of file From c5297c33ffe3c619c9493b427b4906d5e9cf2b19 Mon Sep 17 00:00:00 2001 From: nkx Date: Sun, 19 Jun 2022 00:45:11 +0800 Subject: [PATCH 2/4] added more legacy classes --- inc/TRestDriftVolume.h | 8 + inc/TRestGainMap.h | 9 + inc/TRestGas.h | 8 + inc/TRestHitsEvent.h | 186 +------ inc/TRestReadout.h | 72 +-- inc/TRestReadoutChannel.h | 73 +-- inc/TRestReadoutMapping.h | 61 +-- inc/TRestReadoutModule.h | 232 +-------- inc/TRestReadoutPixel.h | 95 +--- inc/TRestReadoutPlane.h | 144 +----- src/TRestDriftVolume.cxx | 1 + src/TRestGainMap.cxx | 1 + src/TRestGas.cxx | 1 + src/TRestHitsEvent.cxx | 996 +----------------------------------- src/TRestReadout.cxx | 732 +------------------------- src/TRestReadoutChannel.cxx | 64 +-- src/TRestReadoutMapping.cxx | 135 +---- src/TRestReadoutModule.cxx | 435 +--------------- src/TRestReadoutPixel.cxx | 123 +---- src/TRestReadoutPlane.cxx | 407 +-------------- 20 files changed, 49 insertions(+), 3734 deletions(-) create mode 100644 inc/TRestDriftVolume.h create mode 100644 inc/TRestGainMap.h create mode 100644 inc/TRestGas.h create mode 100644 src/TRestDriftVolume.cxx create mode 100644 src/TRestGainMap.cxx create mode 100644 src/TRestGas.cxx diff --git a/inc/TRestDriftVolume.h b/inc/TRestDriftVolume.h new file mode 100644 index 0000000..4aa3c94 --- /dev/null +++ b/inc/TRestDriftVolume.h @@ -0,0 +1,8 @@ +#ifndef RestCore_TRestDriftVolume +#define RestCore_TRestDriftVolume + +#include "TRestDetectorDriftVolume.h" + +typedef TRestDetectorDriftVolume TRestDriftVolume; + +#endif \ No newline at end of file diff --git a/inc/TRestGainMap.h b/inc/TRestGainMap.h new file mode 100644 index 0000000..1d26cbc --- /dev/null +++ b/inc/TRestGainMap.h @@ -0,0 +1,9 @@ +#ifndef RestCore_TRestGainMap +#define RestCore_TRestGainMap + + +#include "TRestDetectorGainMap.h" + +typedef TRestDetectorGainMap TRestGainMap; + +#endif \ No newline at end of file diff --git a/inc/TRestGas.h b/inc/TRestGas.h new file mode 100644 index 0000000..bfe4781 --- /dev/null +++ b/inc/TRestGas.h @@ -0,0 +1,8 @@ +#ifndef RestCore_TRestGas +#define RestCore_TRestGas + +#include "TRestDetectorGas.h" + +typedef TRestDetectorGas TRestGas; + +#endif \ No newline at end of file diff --git a/inc/TRestHitsEvent.h b/inc/TRestHitsEvent.h index 1f084f3..24a86ec 100644 --- a/inc/TRestHitsEvent.h +++ b/inc/TRestHitsEvent.h @@ -2,189 +2,7 @@ #ifndef TRestSoft_TRestHitsEvent #define TRestSoft_TRestHitsEvent -#include +#include "TRestDetectorHitsEvent.h" -#include "TArrayI.h" -#include "TAxis.h" -#include "TGraph2D.h" -#include "TH2F.h" -#include "TMath.h" -#include "TObject.h" - -#include -#include "TH2F.h" - -#include "TVector3.h" - -#include "TRestEvent.h" -#include "TRestHits.h" -#include "TVector3.h" - -//! An event data type that register a vector of TRestHits, -//! allowing us to save a 3-coordinate position and energy. -class TRestHitsEvent : public TRestEvent { - private: - /// An auxiliar TRestHits structure to register hits on XZ projection - TRestHits* fXZHits; //! - /// An auxiliar TRestHits structure to register hits on YZ projection - TRestHits* fYZHits; //! - - /// An auxiliar TRestHits structure to register hits on XYZ projection - TRestHits* fXYZHits; //! - - /// Stores the minimum x-position value. It is initialized by SetBoundaries. - Double_t fMinX; //! - /// Stores the maximum x-position value. It is initialized by SetBoundaries. - Double_t fMaxX; //! - - /// Stores the minimum y-position value. It is initialized by SetBoundaries. - Double_t fMinY; //! - /// Stores the maximum y-position value. It is initialized by SetBoundaries. - Double_t fMaxY; //! - - /// Stores the minimum z-position value. It is initialized by SetBoundaries. - Double_t fMinZ; //! - /// Stores the maximum z-position value. It is initialized by SetBoundaries. - Double_t fMaxZ; //! - - protected: - // TODO These graphs should be placed in TRestHits? - // (following similar GetGraph implementation in TRestSignal) - - /// An auxiliar TGraph pointer to visualize hits on XY-projection. - TGraph* fXYHitGraph; //! - /// An auxiliar TGraph pointer to visualize hits on XZ-projection. - TGraph* fXZHitGraph; //! - /// An auxiliar TGraph pointer to visualize hits on YZ-projection. - TGraph* fYZHitGraph; //! - - /// An auxiliar TH2F histogram to visualize hits on XY-projection. - TH2F* fXYHisto; //! - /// An auxiliar TH2F histogram to visualize hits on YZ-projection. - TH2F* fYZHisto; //! - /// An auxiliar TH2F histogram to visualize hits on XZ-projection. - TH2F* fXZHisto; //! - - TGraph2D* gxz = NULL; //! - TGraph2D* gyz = NULL; //! - - /// An auxiliar TH1F histogram to visualize hits on X-projection. - TH1F* fXHisto; //! - /// An auxiliar TH1F histogram to visualize hits on Y-projection. - TH1F* fYHisto; //! - /// An auxiliar TH1F histogram to visualize hits on Z-projection. - TH1F* fZHisto; //! - - /// The hits structure that is is saved to disk. - TRestHits fHits; // - - public: - void AddHit(Double_t x, Double_t y, Double_t z, Double_t en, Double_t t = 0, REST_HitType type = XYZ); - void AddHit(TVector3 pos, Double_t en, Double_t t = 0, REST_HitType type = XYZ); - - void SetBoundaries(); - void Sort(bool(comparecondition)(const TRestHits::iterator& hit1, const TRestHits::iterator& hit2) = 0); - void Shuffle(int NLoop); - - Int_t GetNumberOfHits() { return fHits.GetNumberOfHits(); } - - TRestHits* GetHits() { return &fHits; } - - /// Returns the X-coordinate of hit entry `n` in mm. - Double_t GetX(int n) { return fHits.GetX(n); } - - /// Returns the Y-coordinate of hit entry `n` in mm. - Double_t GetY(int n) { return fHits.GetY(n); } - - /// Returns the Z-coordinate of hit entry `n` in mm. - Double_t GetZ(int n) { return fHits.GetZ(n); } - - REST_HitType GetType(int n) { return fHits.GetType(n); } - - /// Returns the squared distance between hits `n` and `m`. - Double_t GetDistance2(int n, int m) { return fHits.GetDistance2(n, m); } - - TRestHits* GetXZHits(); - TRestHits* GetYZHits(); - TRestHits* GetXYZHits(); - - virtual void Initialize(); - - virtual void PrintEvent() { TRestHitsEvent::PrintEvent(-1); }; - virtual void PrintEvent(Int_t nHits); - - TVector3 GetPosition(int n) { return fHits.GetPosition(n); } - - TVector3 GetMeanPosition() { return fHits.GetMeanPosition(); } - - Int_t GetNumberOfHitsX() { return fHits.GetNumberOfHitsX(); } - Int_t GetNumberOfHitsY() { return fHits.GetNumberOfHitsY(); } - - Double_t GetMeanPositionX() { return fHits.GetMeanPositionX(); } - Double_t GetMeanPositionY() { return fHits.GetMeanPositionY(); } - Double_t GetMeanPositionZ() { return fHits.GetMeanPositionZ(); } - Double_t GetSigmaXY2() { return fHits.GetSigmaXY2(); } - Double_t GetSigmaX() { return fHits.GetSigmaX(); } - Double_t GetGaussSigmaX() { return GetXZHits()->GetGaussSigmaX(); } - Double_t GetGaussSigmaY() { return GetYZHits()->GetGaussSigmaY(); } - Double_t GetGaussSigmaZ() { return fHits.GetGaussSigmaZ(); } - - Double_t GetSigmaZ2() { return fHits.GetSigmaZ2(); } - Double_t GetSkewXY() { return fHits.GetSkewXY(); } - Double_t GetSkewZ() { return fHits.GetSkewZ(); } - - Double_t GetMaximumHitEnergy() { return fHits.GetMaximumHitEnergy(); } - Double_t GetMinimumHitEnergy() { return fHits.GetMinimumHitEnergy(); } - Double_t GetMeanHitEnergy() { return fHits.GetMeanHitEnergy(); } - - Double_t GetEnergyX() { return fHits.GetEnergyX(); } - Double_t GetEnergyY() { return fHits.GetEnergyY(); } - Double_t CalculateTotalDepositedEnergy(); - Double_t GetTotalDepositedEnergy() { return fHits.GetTotalDepositedEnergy(); } - Double_t GetEnergy(int n) { return fHits.GetEnergy(n); } - Double_t GetTime(int n) { return fHits.GetTime(n); } // return value in us - - Int_t GetClosestHit(TVector3 position) { return fHits.GetClosestHit(position); } - - // Inside Cylinder methods - Bool_t anyHitInsideCylinder(TVector3 x0, TVector3 x1, Double_t radius); - Bool_t allHitsInsideCylinder(TVector3 x0, TVector3 x1, Double_t radius); - Double_t GetEnergyInCylinder(TVector3 x0, TVector3 x1, Double_t radius); - Int_t GetNumberOfHitsInsideCylinder(TVector3 x0, TVector3 x1, Double_t radius); - TVector3 GetMeanPositionInCylinder(TVector3 x0, TVector3 x1, Double_t radius); - - // Inside Prim methods - Bool_t anyHitInsidePrism(TVector3 x0, TVector3 x1, Double_t sizeX, Double_t sizeY, Double_t theta); - Bool_t allHitsInsidePrism(TVector3 x0, TVector3 x1, Double_t sX, Double_t sY, Double_t theta); - - Double_t GetEnergyInPrism(TVector3 x0, TVector3 x1, Double_t sizeX, Double_t sizeY, Double_t theta); - Int_t GetNumberOfHitsInsidePrism(TVector3 x0, TVector3 x1, Double_t sizeX, Double_t sizeY, - Double_t theta); - TVector3 GetMeanPositionInPrism(TVector3 x0, TVector3 x1, Double_t sizeX, Double_t sizeY, Double_t theta); - - // Get closest distance to cylinder walls methods - Double_t GetClosestHitInsideDistanceToCylinderWall(TVector3 x0, TVector3 x1, Double_t radius); - Double_t GetClosestHitInsideDistanceToCylinderTop(TVector3 x0, TVector3 x1, Double_t radius); - Double_t GetClosestHitInsideDistanceToCylinderBottom(TVector3 x0, TVector3 x1, Double_t radius); - - // Get closest distance to prism walls methods - Double_t GetClosestHitInsideDistanceToPrismWall(TVector3 x0, TVector3 x1, Double_t sizeX, Double_t sizeY, - Double_t theta); - Double_t GetClosestHitInsideDistanceToPrismTop(TVector3 x0, TVector3 x1, Double_t sizeX, Double_t sizeY, - Double_t theta); - Double_t GetClosestHitInsideDistanceToPrismBottom(TVector3 x0, TVector3 x1, Double_t sizeX, - Double_t sizeY, Double_t theta); - - TPad* DrawEvent(const TString& option = ""); - void DrawHistograms(Int_t& column, Double_t pitch = 3, TString histOption = ""); - void DrawGraphs(Int_t& column); - void DrawGraph2D(); - - // Construtor - TRestHitsEvent(); - // Destructor - ~TRestHitsEvent(); - - ClassDef(TRestHitsEvent, 2); -}; +typedef TRestDetectorHitsEvent TRestHitsEvent; #endif diff --git a/inc/TRestReadout.h b/inc/TRestReadout.h index 9a06e0c..6e68ddf 100644 --- a/inc/TRestReadout.h +++ b/inc/TRestReadout.h @@ -27,78 +27,10 @@ #include "TObject.h" #include "TRestMetadata.h" -#include "TRestReadoutPlane.h" +#include "TRestDetectorReadout.h" /// A metadata class to generate/store a readout description. -class TRestReadout : public TRestMetadata { - private: - void InitFromConfigFile(); - void DoReadoutMapping(TRestReadoutModule* mod, int nodes = 0); +typedef TRestDetectorReadout TRestReadout; - void Initialize(); - /// Defines if a decoding file was used to match physical readout channel id with signal daq id - Bool_t fDecoding; - /// Number of nodes per axis used on the readout coordinate mapping. See also TRestReadoutMapping. - Int_t fMappingNodes; - /// Number of readout planes present on the readout - Int_t fNReadoutPlanes; - /// A vector storing the TRestReadoutPlane definitions. - std::vector fReadoutPlanes; - /// A vector storing the TRestReadoutMapping for each kind of readout modules. - std::map fReadoutMappings; - - void ValidateReadout(); - - public: - TRestReadoutPlane& operator[](int p) { return fReadoutPlanes[p]; } - - TRestReadoutPlane* GetReadoutPlane(int p); - void AddReadoutPlane(TRestReadoutPlane plane); - - ///////////////////////////////////// - //{ - TRestReadoutPlane* GetReadoutPlaneWithID(int id); - TRestReadoutModule* GetReadoutModuleWithID(int id); - TRestReadoutChannel* GetReadoutChannelWithdaqID(int daqId); - //} - ///////////////////////////////////// - - Int_t GetNumberOfReadoutPlanes(); - Int_t GetNumberOfModules(); - Int_t GetNumberOfChannels(); - - ///////////////////////////////////// - //{ - TRestReadoutModule* ParseModuleDefinition(TiXmlElement* moduleDefinition); - void GetPlaneModuleChannel(Int_t daqID, Int_t& planeID, Int_t& moduleID, Int_t& channelID); - Int_t GetHitsDaqChannel(TVector3 hitpos, Int_t& planeID, Int_t& moduleID, Int_t& channelID); - Double_t GetX(Int_t signalID); - Double_t GetY(Int_t signalID); - //} - ///////////////////////////////////// - - Double_t GetX(Int_t planeID, Int_t modID, Int_t chID); - Double_t GetY(Int_t planeID, Int_t modID, Int_t chID); - - // Detal Level: - // 0->this readout - // 1->+all readout plane - // 2->+all readout module - // 3->+all readout channel - // 4->+all readout pixel - void PrintMetadata() { PrintMetadata(1); } - void PrintMetadata(Int_t DetailLevel); - - void Draw(); - - // Construtor - TRestReadout(); - TRestReadout(const char* cfgFileName); - TRestReadout(const char* cfgFileName, std::string name); - // Destructor - virtual ~TRestReadout(); - - ClassDef(TRestReadout, 2); -}; #endif diff --git a/inc/TRestReadoutChannel.h b/inc/TRestReadoutChannel.h index 557ff4a..de0a85a 100644 --- a/inc/TRestReadoutChannel.h +++ b/inc/TRestReadoutChannel.h @@ -28,77 +28,8 @@ #include "TObject.h" #include "TRestMetadata.h" -#include "TRestReadoutPixel.h" +#include "TRestDetectorReadoutChannel.h" -enum TRestReadoutChannelType { - Channel_NoType = 0, - Channel_Pixel = 1, - Channel_X = 2, - Channel_Y = 3, - Channel_U = 4, - Channel_V = 5, - Channel_W = 6, -}; +typedef TRestDetectorReadoutChannel TRestReadoutChannel; -/// A class to store the readout channel definition used in TRestReadoutModule. -/// It allows to integrate any number of independent readout pixels. -class TRestReadoutChannel : public TObject { - private: - Int_t fDaqID; ///< Defines the corresponding daq channel id. See decoding - ///< details at TRestReadout. - - std::vector fReadoutPixel; ///< A vector storing the different TRestReadoutPixel - ///< definitions. - - Short_t fChannelId = -1; ///< It stores the corresponding physical readout channel - - void Initialize(); - - public: - /// Returns the corresponding daq channel id - Int_t GetDaqID() { return fDaqID; } - - /// Returns the corresponding channel id - Int_t GetChannelId() { return fChannelId; } - - /// Returns the total number of pixels inside the readout channel - Int_t GetNumberOfPixels() { return fReadoutPixel.size(); } - - TRestReadoutPixel& operator[](int n) { return fReadoutPixel[n]; } - - /// Returns a pointer to the pixel *n* by index. - TRestReadoutPixel* GetPixel(int n) { - if (n >= GetNumberOfPixels()) return NULL; - return &fReadoutPixel[n]; - } - - void SetType(TRestReadoutChannelType type) { - // in future we may implement this - } - - TRestReadoutChannelType GetType() { - // in future we may implement this - return Channel_NoType; - } - - /// Sets the daq channel number id - void SetDaqID(Int_t id) { fDaqID = id; } - - /// Sets the readout channel number id - void SetChannelID(Int_t id) { fChannelId = id; } - - /// Adds a new pixel to the readout channel - void AddPixel(TRestReadoutPixel pix) { fReadoutPixel.push_back(pix); } - - Int_t isInside(Double_t x, Double_t y); - - void Print(int DetailLevel = 0); - - // Construtor - TRestReadoutChannel(); - // Destructor - virtual ~TRestReadoutChannel(); - - ClassDef(TRestReadoutChannel, 3); // REST run class -}; #endif diff --git a/inc/TRestReadoutMapping.h b/inc/TRestReadoutMapping.h index 09a588d..0971b98 100644 --- a/inc/TRestReadoutMapping.h +++ b/inc/TRestReadoutMapping.h @@ -28,66 +28,9 @@ #include #include -/// This class defines a uniform 2-dimensional grid relating its nodes to the -/// pixels of a readout. -class TRestReadoutMapping : public TObject { - private: - Int_t fNodesX; ///< The number of nodes in the x-axis. - Int_t fNodesY; ///< The number of nodes in the y-axis. +#include "TRestDetectorReadoutMapping.h" - Double_t fNetSizeX; ///< The size of the net/grid in the x-axis. - Double_t fNetSizeY; ///< The size of the net/grid in the y-axis. +typedef TRestDetectorReadoutMapping TRestReadoutMapping; - TMatrixD fChannel; ///< A matrix containning the channel id for the - ///< corresponding XY-node. - TMatrixD fPixel; ///< A matrix containning the pixel id of fChannel for the - ///< corresponding XY-node. - public: - // Getters - /// Returns the number of nodes in X. - Int_t GetNumberOfNodesX() { return fNodesX; } - - /// Returns the number of nodes in Y. - Int_t GetNumberOfNodesY() { return fNodesY; } - - /// Gets the channel id correspoding to a given node (i,j) - Int_t GetChannelByNode(Int_t i, Int_t j) { return fChannel[i][j]; } - - /// Gets the pixel id correspoding to a given node (i,j) - Int_t GetPixelByNode(Int_t i, Int_t j) { return fPixel[i][j]; } - - Bool_t isNodeSet(Int_t i, Int_t j); - - Bool_t AllNodesSet(); - - Int_t GetNumberOfNodesNotSet(); - - Int_t GetNodeX_ForChannelAndPixel(Int_t ch, Int_t px); - - Int_t GetNodeY_ForChannelAndPixel(Int_t ch, Int_t px); - - Int_t GetNodeX(Double_t x); - - Int_t GetNodeY(Double_t y); - - Double_t GetX(Int_t nodeX); - - Double_t GetY(Int_t nodeY); - - Int_t GetChannel(Double_t x, Double_t y); - - Int_t GetPixel(Double_t x, Double_t y); - - void SetNode(Int_t i, Int_t j, Int_t ch, Int_t pix); - - void Initialize(Int_t nX, Int_t nY, Double_t sX, Double_t sY); - - // Construtor - TRestReadoutMapping(); - // Destructor - ~TRestReadoutMapping(); - - ClassDef(TRestReadoutMapping, 1); -}; #endif diff --git a/inc/TRestReadoutModule.h b/inc/TRestReadoutModule.h index c258105..9588f76 100644 --- a/inc/TRestReadoutModule.h +++ b/inc/TRestReadoutModule.h @@ -28,238 +28,10 @@ #include #include "TObject.h" -#include -#include #include -/// A class to store the readout module definition used in TRestReadoutPlane. It -/// allows to integrate any number of independent readout channels. -class TRestReadoutModule : public TObject { - private: - Int_t fModuleID; ///< The module id given by the readout definition. +#include "TRestDetectorReadoutModule.h" - TString fModuleName; ///< The assigned module name. i.e, microbulk, thermalbounding - ///< Modules with same name could share a same mapping +typedef TRestDetectorReadoutModule TRestReadoutModule; - TString fModuleUniqueName; ///< The unique module name. i.e, M2, M0, V508 - - Double_t fModuleOriginX; ///< The module x-position (left-bottom corner) - ///< relative to the readout plane position. - Double_t fModuleOriginY; ///< The module y-position (left-bottom corner) - ///< relative to the readout plane position. - - Double_t fModuleSizeX; ///< X-size of the module. All pixels should be - ///< containned within this size. - Double_t fModuleSizeY; ///< Y-size of the module. All pixels should be - ///< containned within this size. - - Double_t fModuleRotation; ///< The rotation of the module around the - ///< position=(fModuleOriginX, fModuleOriginY) in - ///< degrees. - - Int_t fMininimumDaqId; ///< The minimum daq channel id associated to the - ///< module. - Int_t fMaximumDaqId; ///< The maximum daq channel id associated to the module. - - std::vector fReadoutChannel; ///< A vector of the instances of TRestReadoutChannel - ///< containned in the readout module. - Double_t fTolerance; ///< Tolerance allowed in overlaps at the pixel - ///< boundaries in mm. - -#ifndef __CINT__ - Bool_t showWarnings; //!///< Flag to enable/disable warning outputs. Disabled by - //! default. REST_Warning in TRestReadout will enable it. - TRestReadoutMapping* fMapping; //!///< The readout module uniform grid mapping. -#endif - - void Initialize(); - - /// Converts the coordinates given by TVector2 in the readout plane reference - /// system to the readout module reference system. - TVector2 TransformToModuleCoordinates(TVector2 p) { return TransformToModuleCoordinates(p.X(), p.Y()); } - - /// Converts the coordinates (xPhys,yPhys) in the readout plane reference - /// system to the readout module reference system. - TVector2 TransformToModuleCoordinates(Double_t xPhys, Double_t yPhys) { - TVector2 coords(xPhys - fModuleOriginX, yPhys - fModuleOriginY); - TVector2 rot = coords.Rotate(-fModuleRotation * TMath::Pi() / 180.); - - return rot; - } - - /// Converts the coordinates (xMod,yMod) in the readout module reference - /// system to the readout plane reference system. - TVector2 TransformToPhysicalCoordinates(Double_t xMod, Double_t yMod) { - TVector2 coords(xMod, yMod); - - coords = coords.Rotate(fModuleRotation * TMath::Pi() / 180.); - coords = coords + TVector2(fModuleOriginX, fModuleOriginY); - - return coords; - } - - protected: - public: - // Setters - - /// Sets the module by id definition - void SetModuleID(Int_t modID) { fModuleID = modID; } - - /// Sets the module size by definition using (sX, sY) coordinates - void SetSize(Double_t sX, Double_t sY) { - fModuleSizeX = sX; - fModuleSizeY = sY; - } - - /// Sets the module size by definition using TVector2 input - void SetSize(TVector2 s) { - fModuleSizeX = s.X(); - fModuleSizeY = s.Y(); - } - - /// Sets the module origin by definition using (x,y) coordinates - void SetOrigin(Double_t x, Double_t y) { - fModuleOriginX = x; - fModuleOriginY = y; - } - - /// Sets the module origin by definition using TVector2 input - void SetOrigin(TVector2 c) { - fModuleOriginX = c.X(); - fModuleOriginY = c.Y(); - } - - /// Sets the module rotation in degrees - void SetRotation(Double_t rot) { fModuleRotation = rot; } - - /// Sets the name of the readout module - void SetName(TString name) { fModuleName = name; } - - /// Sets the unique name of the readout module - void SetUniqueName(TString name) { fModuleUniqueName = name; } - - /// Sets the tolerance for independent pixel overlaps - void SetTolerance(Double_t tol) { fTolerance = tol; } - - /// Gets the tolerance for independent pixel overlaps - Double_t GetTolerance() { return fTolerance; } - - /// Returns the minimum daq id number - Int_t GetMinDaqID() { return fMininimumDaqId; } - - /// Returns the maximum daq id number - Int_t GetMaxDaqID() { return fMaximumDaqId; } - - /// Returns the physical readout channel index for a given daq id channel - /// number - Int_t DaqToReadoutChannel(Int_t daqChannel) { - for (int n = 0; n < GetNumberOfChannels(); n++) - if (GetChannel(n)->GetDaqID() == daqChannel) return n; - return -1; - } - - /// Returns the module id - Int_t GetModuleID() { return fModuleID; } - - /// Returns the module x-coordinate origin - Double_t GetModuleOriginX() { return fModuleOriginX; } - - /// Returns the module y-coordinate origin - Double_t GetModuleOriginY() { return fModuleOriginY; } - - /// Returns the module x-coordinate origin - Double_t GetOriginX() { return fModuleOriginX; } - - /// Returns the module y-coordinate origin - Double_t GetOriginY() { return fModuleOriginY; } - - /// Returns the module size x-coordinate - Double_t GetModuleSizeX() { return fModuleSizeX; } - - /// Returns the module size y-coordinate - Double_t GetModuleSizeY() { return fModuleSizeY; } - - /// Returns the module rotation in degrees - Double_t GetModuleRotation() { return fModuleRotation; } - - /// Converts the coordinates given by TVector2 in the readout plane reference - /// system to the readout module reference system. - TVector2 GetModuleCoordinates(TVector2 p) { return TransformToModuleCoordinates(p); } - - /// Converts the coordinates given by TVector2 in the readout module reference - /// system to the readout plane reference system. - TVector2 GetPhysicalCoordinates(TVector2 p) { return TransformToPhysicalCoordinates(p.X(), p.Y()); } - - /// Returns the module name - TString GetName() { return fModuleName; } - - /// Returns the unique module name - TString GetUniqueName() { return fModuleUniqueName; } - - /// Returns a pointer to the readout mapping - TRestReadoutMapping* GetMapping() { return fMapping; } - - TRestReadoutChannel& operator[](int n) { return fReadoutChannel[n]; } - - /// Returns a pointer to a readout channel by index - TRestReadoutChannel* GetChannel(int n) { - if (n >= GetNumberOfChannels()) return NULL; - return &fReadoutChannel[n]; - } - - /// Returns the total number of channels defined inside the module - Int_t GetNumberOfChannels() { return fReadoutChannel.size(); } - - /// Enables warning output - void EnableWarnings() { showWarnings = true; } - - /// Disables warning output - void DisableWarnings() { showWarnings = false; } - - void SetReadoutMapping(TRestReadoutMapping* mapping) { fMapping = mapping; } - - Bool_t isInside(Double_t x, Double_t y); - Bool_t isInside(TVector2 pos); - - Bool_t isInsideChannel(Int_t channel, Double_t x, Double_t y); - Bool_t isInsideChannel(Int_t channel, TVector2 pos); - - Bool_t isInsidePixel(Int_t channel, Int_t pixel, Double_t x, Double_t y); - Bool_t isInsidePixel(Int_t channel, Int_t pixel, TVector2 pos); - - Bool_t isInsidePixelRelative(Int_t channel, Int_t pixel, Double_t x, Double_t y); - Bool_t isInsidePixelRelative(Int_t channel, Int_t pixel, TVector2 pos); - - Bool_t isDaqIDInside(Int_t daqID); - Int_t FindChannel(Double_t x, Double_t y); - TVector2 GetDistanceToModule(TVector2 pos); - - TVector2 GetPixelOrigin(Int_t channel, Int_t pixel); - TVector2 GetPixelVertex(Int_t channel, Int_t pixel, Int_t vertex); - TVector2 GetPixelCenter(Int_t channel, Int_t pixel); - Bool_t GetPixelTriangle(Int_t channel, Int_t pixel); - - TVector2 GetPixelOrigin(TRestReadoutPixel* pix); - TVector2 GetPixelVertex(TRestReadoutPixel* pix, Int_t vertex); - TVector2 GetPixelCenter(TRestReadoutPixel* pix); - Bool_t GetPixelTriangle(TRestReadoutPixel* pix); - - TVector2 GetVertex(int n) const; - - void AddChannel(TRestReadoutChannel& rChannel); - - void SetMinMaxDaqIDs(); - - void Draw(); - - void Print(Int_t DetailLevel = 0); - - void PrintDecoding(); - // Construtor - TRestReadoutModule(); - // Destructor - virtual ~TRestReadoutModule(); - - ClassDef(TRestReadoutModule, 2); -}; #endif diff --git a/inc/TRestReadoutPixel.h b/inc/TRestReadoutPixel.h index 5c7cd74..92ea5d7 100644 --- a/inc/TRestReadoutPixel.h +++ b/inc/TRestReadoutPixel.h @@ -25,99 +25,8 @@ #include -#include -#include -#include "TObject.h" -#include "TRestMetadata.h" +#include "TRestDetectorReadoutPixel.h" -/// A class to store the readout pixel definition used in TRestReadoutChannel. -class TRestReadoutPixel : public TObject { - private: - Double_t fPixelOriginX; ///< The pixel x-origin position, left-bottom corner. - Double_t fPixelOriginY; ///< The pixel y-origin position, left-bottom corner. +typedef TRestDetectorReadoutPixel TRestReadoutPixel; - Double_t fPixelSizeX; ///< The pixel x size. - Double_t fPixelSizeY; ///< The pixel y size. - - Double_t fRotation; ///< The pixel rotation angle in degrees, rotation with - ///< axis at the origin position. - - Bool_t fTriangle; ///< The type of the pixel : false is rectangular, true is - ///< triangle - void Initialize(); - - protected: - public: - /// Returns the x-coordinate pixel origin. - Double_t GetOriginX() const { return fPixelOriginX; } - - /// Returns the y-coordinate pixel origin. - Double_t GetOriginY() const { return fPixelOriginY; } - - /// Returns a TVector2 with the pixel origin. - TVector2 GetOrigin() const { return TVector2(fPixelOriginX, fPixelOriginY); } - - /// Returns the rotation angle in degrees - Double_t GetRotation() const { return fRotation; } - - /// Returns the pixel size in X - Double_t GetSizeX() { return fPixelSizeX; } - - /// Returns the pixel size in Y - Double_t GetSizeY() { return fPixelSizeY; } - - /// Returns a TVector2 with the pixel size. - TVector2 GetSize() { return TVector2(fPixelSizeX, fPixelSizeY); } - - /// Returns true if the pixel is a triangle. - Bool_t GetTriangle() const { return fTriangle; } - - TVector2 GetCenter() const; - - TVector2 GetVertex(int n) const; - - /// Sets the origin of the pixel using the coordinate values *x*,*y*. - void SetOrigin(Double_t x, Double_t y) { - fPixelOriginX = x; - fPixelOriginY = y; - } - - /// Sets the origin of the pixel using a TVector2. - void SetOrigin(TVector2 origin) { - fPixelOriginX = origin.X(); - fPixelOriginY = origin.Y(); - } - - /// Sets the size of the pixel using the coordinate values *sx*,*sy*. - void SetSize(Double_t sx, Double_t sy) { - fPixelSizeX = sx; - fPixelSizeY = sy; - } - - /// Sets the size of the pixel using a TVector2. - void SetSize(TVector2 size) { - fPixelSizeX = size.X(); - fPixelSizeY = size.Y(); - } - - /// Sets the rotation angle of the pixel in degrees - void SetRotation(Double_t rot) { fRotation = rot; } - - /// Sets the type of the pixel - void SetTriangle(Bool_t type) { fTriangle = type; } - - Bool_t isInside(TVector2 pos); - Bool_t isInside(Double_t x, Double_t y); - - TVector2 TransformToPixelCoordinates(TVector2 p); - - void Print(); - - // Construtor - TRestReadoutPixel(); - // Destructor - virtual ~TRestReadoutPixel(); - - ClassDef(TRestReadoutPixel, 4); -}; #endif diff --git a/inc/TRestReadoutPlane.h b/inc/TRestReadoutPlane.h index b641d04..ffadf0d 100644 --- a/inc/TRestReadoutPlane.h +++ b/inc/TRestReadoutPlane.h @@ -27,149 +27,9 @@ #include "TObject.h" -#include "TRestMetadata.h" -#include "TRestReadoutChannel.h" -#include "TRestReadoutModule.h" +#include "TRestDetectorReadoutPlane.h" -#include -#include +typedef TRestDetectorReadoutPlane TRestReadoutPlane; -/// A class to store the readout plane definition used in TRestReadout. It -/// allows to integrate any number of independent readout modules. -class TRestReadoutPlane : public TObject { - private: - Int_t fPlaneID; ///< The readout plane id. The id number is imposed by the - ///< order of creation. Being the first id=0. - TVector3 fPosition; ///< The position of the readout plane. The relative position - ///< of the modules will be shifted by this value. - TVector3 fPlaneVector; ///< The plane vector definning the plane orientation - ///< and the side of the active volume. - TVector3 fCathodePosition; ///< The cathode position which delimites the active - ///< volume together with the readout plane. - Double_t fChargeCollection; ///< A parameter between 0 and 1 definning how - ///< much charge should be collected from a - ///< charge hit. It might be used to distribute - ///< the charge between different readout planes. - Double_t fTotalDriftDistance; ///< A parameter storing the total drift distance, - ///< defined between cathode and readout plane. - - Int_t fNModules; ///< The number of modules that have been added to the - ///< readout plane - std::vector fReadoutModules; ///< A vector of the instances of TRestReadoutModule - ///< containned in the readout plane. - - void Initialize(); - - protected: - public: - // Setters - /// Sets the planeId. This is done by TRestReadout during initialization - void SetID(int id) { fPlaneID = id; } - - /// Sets the readout plane position - void SetPosition(TVector3 pos) { fPosition = pos; } - - /// Sets the cathode plane position. By default is parallel to the readout - /// plane. - void SetCathodePosition(TVector3 pos) { fCathodePosition = pos; } - - /// Sets the orientation of the readout plane, and defines the side of the - /// active volume. - void SetPlaneVector(TVector3 vect) { fPlaneVector = vect.Unit(); } - - /// Sets the value for the charge collection. - void SetChargeCollection(Double_t charge) { fChargeCollection = charge; } - - /// Sets the value for the total drift distance - void SetTotalDriftDistance(Double_t d) { fTotalDriftDistance = d; } - - // Getters - /// Returns an integer with the plane id number. - Int_t GetID() { return fPlaneID; } - - /// Returns a TVector3 with the readout plane position - TVector3 GetPosition() { return fPosition; } - - /// Returns a TVector3 with the cathode position - TVector3 GetCathodePosition() { return fCathodePosition; } - - /// Returns a TVector3 with a vector normal to the readout plane - TVector3 GetPlaneVector() { return fPlaneVector; } - - /// Returns the charge collection ratio at this readout plane - Double_t GetChargeCollection() { return fChargeCollection; } - - /// Returns the total drift distance - Double_t GetTotalDriftDistance() { return fTotalDriftDistance; } - - /// Returns the perpendicular distance to the readout plane from a given - /// position *pos*. - Double_t GetDistanceTo(TVector3 pos); - - /// Returns the perpendicular distance to the readout plane from a given - /// position *x*, *y*, *z*. - Double_t GetDistanceTo(Double_t x, Double_t y, Double_t z); - - /// Returns a TVector2 oriented as the shortest distance of a given position - /// *pos* on the plane to a specific module with id *mod* - TVector2 GetDistanceToModule(Int_t mod, TVector2 pos) { - return GetModuleByID(mod)->GetDistanceToModule(pos); - } - - TRestReadoutModule& operator[](int mod) { return fReadoutModules[mod]; } - - /// Returns a pointer to a readout module using its vector index - TRestReadoutModule* GetModule(int mod) { - if (mod >= GetNumberOfModules()) return NULL; - return &fReadoutModules[mod]; - } - - /// Returns the total number of modules in the readout plane - Int_t GetNumberOfModules() { return fReadoutModules.size(); } - - /// Adds a new module to the readout plane - void AddModule(TRestReadoutModule& rModule) { - fReadoutModules.push_back(rModule); - fNModules++; - } - - /// Prints the readout plane description - void PrintMetadata() { Print(); } - - Int_t GetNumberOfChannels(); - - TRestReadoutModule* GetModuleByID(Int_t modID); - - Int_t isZInsideDriftVolume(Double_t z); - - Int_t isZInsideDriftVolume(TVector3 pos); - - Bool_t isDaqIDInside(Int_t daqId); - - Int_t GetModuleIDFromPosition(TVector3 pos); - - Int_t GetModuleIDFromPosition(Double_t x, Double_t y, Double_t z); - - void SetDriftDistance(); - - void Draw(); - - void Print(Int_t DetailLevel = 0); - - Int_t FindChannel(Int_t module, Double_t absX, Double_t absY); - - Double_t GetX(Int_t modID, Int_t chID); - Double_t GetY(Int_t modID, Int_t chID); - - TH2Poly* GetReadoutHistogram(); - void GetBoundaries(double& xmin, double& xmax, double& ymin, double& ymax); - - // Construtor - TRestReadoutPlane(); - // Destructor - virtual ~TRestReadoutPlane(); - - ClassDef(TRestReadoutPlane, 1); -}; #endif diff --git a/src/TRestDriftVolume.cxx b/src/TRestDriftVolume.cxx new file mode 100644 index 0000000..72076b7 --- /dev/null +++ b/src/TRestDriftVolume.cxx @@ -0,0 +1 @@ +#include "TRestDriftVolume.h" \ No newline at end of file diff --git a/src/TRestGainMap.cxx b/src/TRestGainMap.cxx new file mode 100644 index 0000000..ba8781a --- /dev/null +++ b/src/TRestGainMap.cxx @@ -0,0 +1 @@ +#include "TRestGainMap.h" diff --git a/src/TRestGas.cxx b/src/TRestGas.cxx new file mode 100644 index 0000000..1fe460d --- /dev/null +++ b/src/TRestGas.cxx @@ -0,0 +1 @@ +#include "TRestGas.h" \ No newline at end of file diff --git a/src/TRestHitsEvent.cxx b/src/TRestHitsEvent.cxx index deb274f..892037e 100644 --- a/src/TRestHitsEvent.cxx +++ b/src/TRestHitsEvent.cxx @@ -37,998 +37,4 @@ /// ///
/// -#include "TRestHitsEvent.h" - -#include "TCanvas.h" -#include "TRandom.h" -#include "TRestStringHelper.h" -#include "TRestTools.h" -#include "TStyle.h" - -using namespace std; -using namespace TMath; - -ClassImp(TRestHitsEvent); - -/////////////////////////////////////////////// -/// \brief TRestHitsEvent default constructor -/// -/// If no configuration path is defined using TRestMetadata::SetConfigFilePath -/// the path to the config file must be specified using full path, absolute or -/// relative. -/// -/// The default behaviour is that the config file must be specified with -/// full path, absolute or relative. -/// -/// \param cfgFileName A const char* giving the path to an RML file. -/// -TRestHitsEvent::TRestHitsEvent() { - fPad = NULL; - - fXYHitGraph = NULL; - fXZHitGraph = NULL; - fYZHitGraph = NULL; - - fXYHisto = NULL; - fXZHisto = NULL; - fYZHisto = NULL; - - fXZHits = NULL; - fYZHits = NULL; - fXYZHits = NULL; - - fXHisto = NULL; - fYHisto = NULL; - fZHisto = NULL; - - fMinX = -10; - fMaxX = 10; - - fMinY = -10; - fMaxY = 10; - - fMinZ = -10; - fMaxZ = 10; - - RESTWarning << "Creating legacy event TRestHitsEvent" << RESTendl; - RESTWarning << "This event is now named TRestDetectorHitsEvent" << RESTendl; -} - -/////////////////////////////////////////////// -/// \brief TRestHitsEvent default destructor -/// -TRestHitsEvent::~TRestHitsEvent() {} - -/////////////////////////////////////////////// -/// \brief Adds a new hit to this event -/// -/// It adds a new hit with coordinates `x`,`y`,`z` in mm, and energy `en` in keV, to this TRestHitsEvent -/// structure. Additionaly a time delay value in `us` may be added to the hits. -void TRestHitsEvent::AddHit(Double_t x, Double_t y, Double_t z, Double_t en, Double_t t, REST_HitType type) { - fHits.AddHit(x, y, z, en, t, type); -} - -/////////////////////////////////////////////// -/// \brief Adds a new hit to this event -/// -/// It adds a new hit with position `pos` in mm, and energy `en` in keV, to this TRestHitsEvent -/// structure. Additionaly a time delay value in `us` may be added to the hits. -void TRestHitsEvent::AddHit(TVector3 pos, Double_t en, Double_t t, REST_HitType type) { - fHits.AddHit(pos, en, t, type); -} - -/////////////////////////////////////////////// -/// \brief Removes all hits from this event, and clears all auxiliar variables. -/// -void TRestHitsEvent::Initialize() { - TRestEvent::Initialize(); - - fHits.RemoveHits(); - - if (fXZHits) { - delete fXZHits; - fXZHits = NULL; - } - if (fYZHits) { - delete fYZHits; - fYZHits = NULL; - } - if (fXYZHits) { - delete fXYZHits; - fXYZHits = NULL; - } - - fXZHits = new TRestHits(); - fYZHits = new TRestHits(); - fXYZHits = new TRestHits(); - - fMinX = 0; - fMaxX = 0; - fMinY = 0; - fMaxY = 0; - fMinZ = 0; - fMaxZ = 0; -} - -void TRestHitsEvent::Sort(bool(comparecondition)(const TRestHits::iterator& hit1, - const TRestHits::iterator& hit2)) { - if (comparecondition == 0) { - // default sort logic: z from smaller to greater - std::sort(fHits.begin(), fHits.end(), - [](const TRestHits::iterator& hit1, const TRestHits::iterator& hit2) -> bool { - return hit1.z() < hit2.z(); - }); - } else { - std::sort(fHits.begin(), fHits.end(), comparecondition); - } -} - -void TRestHitsEvent::Shuffle(int NLoop) { - Int_t nHits = fHits.GetNumberOfHits(); - if (nHits >= 2) { - for (int n = 0; n < NLoop; n++) { - Int_t hit1 = (Int_t)(nHits * gRandom->Uniform(0, 1)); - Int_t hit2 = (Int_t)(nHits * gRandom->Uniform(0, 1)); - - fHits.SwapHits(hit1, hit2); - } - } -} - -/////////////////////////////////////////////// -/// \brief This method collects all hits which are compatible with a XZ-projected hit. -/// -/// A hit compatible with XZ projection are those hits that have undetermined Y coordinate, -/// and valid X and Z coordinates. -/// -/// \return It returns back a TRestHits structure with the hits fulfilling the XZ condition. -TRestHits* TRestHitsEvent::GetXZHits() { - fXZHits->RemoveHits(); - - for (int i = 0; i < this->GetNumberOfHits(); i++) - if (GetType(i) == XZ) - fXZHits->AddHit(this->GetX(i), this->GetY(i), this->GetZ(i), this->GetEnergy(i), this->GetTime(i), - XZ); - - return fXZHits; -} - -/////////////////////////////////////////////// -/// \brief This method collects all hits which are compatible with a YZ-projected hit. -/// -/// A hit compatible with XZ projection are those hits that have undetermined X coordinate, -/// and valid Y and Z coordinates. -/// -/// \return It returns back a TRestHits structure with the hits fulfilling the XZ condition. -TRestHits* TRestHitsEvent::GetYZHits() { - fYZHits->RemoveHits(); - - for (int i = 0; i < this->GetNumberOfHits(); i++) - if (GetType(i) == YZ) - fYZHits->AddHit(this->GetX(i), this->GetY(i), this->GetZ(i), this->GetEnergy(i), this->GetTime(i), - YZ); - - return fYZHits; -} - -/////////////////////////////////////////////// -/// \brief This method collects all hits which are compatible with a XYZ hit. -/// -/// A XYZ hit compatible are those hits that have valid X, Y and Z coordinates. -/// -/// \return It returns back a TRestHits structure with the hits fulfilling the XYZ condition. -TRestHits* TRestHitsEvent::GetXYZHits() { - fXYZHits->RemoveHits(); - - for (int i = 0; i < this->GetNumberOfHits(); i++) - if (GetType(i) == XYZ) - fXYZHits->AddHit(this->GetX(i), this->GetY(i), this->GetZ(i), this->GetEnergy(i), - this->GetTime(i), XYZ); - - return fXYZHits; -} - -/////////////////////////////////////////////// -/// \brief This method returns true if at least 1 hit is found inside the cylinder volume given by argument. -/// -/// \param x0 The center of the bottom face of the cylinder. -/// \param x1 The center of the top face of the cylinder. -/// \param radius The radius of the cylinder. -/// -Bool_t TRestHitsEvent::anyHitInsideCylinder(TVector3 x0, TVector3 x1, Double_t radius) { - if (fHits.GetNumberOfHitsInsideCylinder(x0, x1, radius) > 0) return true; - - return false; -} - -/////////////////////////////////////////////// -/// \brief This method returns true if all hits are containned inside the cylinder volume given by argument. -/// -/// \param x0 The center of the bottom face of the cylinder. -/// \param x1 The center of the top face of the cylinder. -/// \param radius The radius of the cylinder. -/// -Bool_t TRestHitsEvent::allHitsInsideCylinder(TVector3 x0, TVector3 x1, Double_t radius) { - if (fHits.GetNumberOfHitsInsideCylinder(x0, x1, radius) == GetNumberOfHits()) return true; - - return false; -} - -/////////////////////////////////////////////// -/// \brief This method returns the total integrated energy of all hits found inside the cylinder volume given -/// by argument. -/// -/// \param x0 The center of the bottom face of the cylinder. -/// \param x1 The center of the top face of the cylinder. -/// \param radius The radius of the cylinder. -/// -Double_t TRestHitsEvent::GetEnergyInCylinder(TVector3 x0, TVector3 x1, Double_t radius) { - return fHits.GetEnergyInCylinder(x0, x1, radius); -} - -/////////////////////////////////////////////// -/// \brief This method returns the total number hits found inside the cylinder volume given -/// by argument. -/// -/// \param x0 The center of the bottom face of the cylinder. -/// \param x1 The center of the top face of the cylinder. -/// \param radius The radius of the cylinder. -/// -Int_t TRestHitsEvent::GetNumberOfHitsInsideCylinder(TVector3 x0, TVector3 x1, Double_t radius) { - return fHits.GetNumberOfHitsInsideCylinder(x0, x1, radius); -} - -/////////////////////////////////////////////// -/// \brief This method returns the mean position of the hits found inside the cylinder volume given -/// by argument. -/// -/// \param x0 The center of the bottom face of the cylinder. -/// \param x1 The center of the top face of the cylinder. -/// \param radius The radius of the cylinder. -/// -TVector3 TRestHitsEvent::GetMeanPositionInCylinder(TVector3 x0, TVector3 x1, Double_t radius) { - return fHits.GetMeanPositionInCylinder(x0, x1, radius); -} - -/////////////////////////////////////////////// -/// \brief This method returns true if at least 1 hit is found inside the prism volume given by argument. -/// -/// \param x0 The center of the bottom face of the prism. -/// \param x1 The center of the top face of the prism. -/// \param sizeX Size of the side X of the prism face. -/// \param sizeY Size of the side X of the prism face. -/// \param theta An angle in radians to rotate the face of the prism. -/// -Bool_t TRestHitsEvent::anyHitInsidePrism(TVector3 x0, TVector3 x1, Double_t sizeX, Double_t sizeY, - Double_t theta) { - if (fHits.GetNumberOfHitsInsidePrism(x0, x1, sizeX, sizeY, theta) > 0) return true; - - return false; -} - -/////////////////////////////////////////////// -/// \brief This method returns true if all hits are found inside the prism volume given by argument. -/// -/// \param x0 The center of the bottom face of the prism. -/// \param x1 The center of the top face of the prism. -/// \param sizeX Size of the side X of the prism face. -/// \param sizeY Size of the side X of the prism face. -/// \param theta An angle in radians to rotate the face of the prism. -/// -Bool_t TRestHitsEvent::allHitsInsidePrism(TVector3 x0, TVector3 x1, Double_t sizeX, Double_t sizeY, - Double_t theta) { - if (fHits.GetNumberOfHitsInsidePrism(x0, x1, sizeX, sizeY, theta) == GetNumberOfHits()) return true; - - return false; -} - -/////////////////////////////////////////////// -/// \brief This method returns the total integrated energy of all hits found inside the prism volume given -/// by argument. -/// -/// \param x0 The center of the bottom face of the prism. -/// \param x1 The center of the top face of the prism. -/// \param sizeX Size of the side X of the prism face. -/// \param sizeY Size of the side X of the prism face. -/// \param theta An angle in radians to rotate the face of the prism. -/// -Double_t TRestHitsEvent::GetEnergyInPrism(TVector3 x0, TVector3 x1, Double_t sizeX, Double_t sizeY, - Double_t theta) { - return fHits.GetEnergyInPrism(x0, x1, sizeX, sizeY, theta); -} - -/////////////////////////////////////////////// -/// \brief This method returns the total number of hits found inside the prism volume given -/// by argument. -/// -/// \param x0 The center of the bottom face of the prism. -/// \param x1 The center of the top face of the prism. -/// \param sizeX Size of the side X of the prism face. -/// \param sizeY Size of the side X of the prism face. -/// \param theta An angle in radians to rotate the face of the prism. -/// -Int_t TRestHitsEvent::GetNumberOfHitsInsidePrism(TVector3 x0, TVector3 x1, Double_t sizeX, Double_t sizeY, - Double_t theta) { - return fHits.GetNumberOfHitsInsidePrism(x0, x1, sizeX, sizeY, theta); -} - -/////////////////////////////////////////////// -/// \brief This method returns the mean position of all hits found inside the prism volume given -/// by argument. -/// -/// \param x0 The center of the bottom face of the prism. -/// \param x1 The center of the top face of the prism. -/// \param sizeX Size of the side X of the prism face. -/// \param sizeY Size of the side X of the prism face. -/// \param theta An angle in radians to rotate the face of the prism. -/// -TVector3 TRestHitsEvent::GetMeanPositionInPrism(TVector3 x0, TVector3 x1, Double_t sizeX, Double_t sizeY, - Double_t theta) { - return fHits.GetMeanPositionInPrism(x0, x1, sizeX, sizeY, theta); -} - -/////////////////////////////////////////////// -/// \brief This method returns the distance to the cylinder wall from the closest hit containned inside the -/// cylinder volume given by argument. -/// -/// \param x0 The center of the bottom face of the cylinder. -/// \param x1 The center of the top face of the cylinder. -/// \param radius The radius of the cylinder. -/// -/// \return If no hit is found inside the cylinder, -1 is returned. -/// -Double_t TRestHitsEvent::GetClosestHitInsideDistanceToCylinderWall(TVector3 x0, TVector3 x1, - Double_t radius) { - Double_t rad2 = radius * radius; - Double_t hitDistance = rad2; - - Double_t d2, l; - - TVector3 axis = x1 - x0; - Double_t cylLength = axis.Mag(); - - Int_t nhits = 0; - for (int n = 0; n < GetNumberOfHits(); n++) { - if (fHits.isHitNInsideCylinder(n, x0, x1, radius)) { - l = axis.Dot(this->GetPosition(n) - x0) / cylLength; - - d2 = rad2 - (this->GetPosition(n) - x0).Mag2() + l * l; - - if (d2 < hitDistance) hitDistance = d2; - - nhits++; - } - } - - if (nhits == 0) return -1; - - return TMath::Sqrt(hitDistance); -} - -/////////////////////////////////////////////// -/// \brief This method returns the distance to the cylinder **top** face from the closest hit containned -/// inside the cylinder volume given by argument. -/// -/// \param x0 The center of the bottom face of the cylinder. -/// \param x1 The center of the top face of the cylinder. -/// \param radius The radius of the cylinder. -/// -/// \return If no hit is found inside the cylinder, -1 is returned. -/// -Double_t TRestHitsEvent::GetClosestHitInsideDistanceToCylinderTop(TVector3 x0, TVector3 x1, Double_t radius) { - TVector3 axis = x1 - x0; - Double_t cylLength = axis.Mag(); - - Double_t hitDistance = cylLength; - Double_t d = cylLength; - - Int_t nhits = 0; - for (int n = 0; n < GetNumberOfHits(); n++) { - if (fHits.isHitNInsideCylinder(n, x0, x1, radius)) { - d = cylLength - axis.Dot(this->GetPosition(n) - x0) / cylLength; - - if (d < hitDistance) hitDistance = d; - - nhits++; - } - } - - if (nhits == 0) return -1; - - return hitDistance; -} - -/////////////////////////////////////////////// -/// \brief This method returns the distance to the cylinder **bottom** face from the closest hit containned -/// inside the cylinder volume given by argument. -/// -/// \param x0 The center of the bottom face of the cylinder. -/// \param x1 The center of the top face of the cylinder. -/// \param radius The radius of the cylinder. -/// -/// \return If no hit is found inside the cylinder, -1 is returned. -/// -Double_t TRestHitsEvent::GetClosestHitInsideDistanceToCylinderBottom(TVector3 x0, TVector3 x1, - Double_t radius) { - TVector3 axis = x1 - x0; - Double_t cylLength = axis.Mag(); - - Double_t hitDistance = cylLength; - Double_t d = cylLength; - - Int_t nhits = 0; - for (int n = 0; n < GetNumberOfHits(); n++) { - if (fHits.isHitNInsideCylinder(n, x0, x1, radius)) { - d = axis.Dot(this->GetPosition(n) - x0) / cylLength; - - if (d < hitDistance) hitDistance = d; - - nhits++; - } - } - - if (nhits == 0) return -1; - - return hitDistance; -} - -/////////////////////////////////////////////// -/// \brief This method returns the distance to the prism **wall** from the closest hit containned -/// inside the prism volume given by argument. -/// -/// \param x0 The center of the bottom face of the prism. -/// \param x1 The center of the top face of the prism. -/// \param sizeX Size of the side X of the prism face. -/// \param sizeY Size of the side X of the prism face. -/// \param theta An angle in radians to rotate the face of the prism. -/// -/// \return If no hit is found inside the prism, -1 is returned. -/// -Double_t TRestHitsEvent::GetClosestHitInsideDistanceToPrismWall(TVector3 x0, TVector3 x1, Double_t sizeX, - Double_t sizeY, Double_t theta) { - Double_t dX = sizeX / 2; - Double_t dY = sizeY / 2; - - Double_t hitDistance = max(dX, dY); - - Double_t d; - Int_t nhits = 0; - for (int n = 0; n < GetNumberOfHits(); n++) { - if (fHits.isHitNInsidePrism(n, x0, x1, sizeX, sizeY, theta)) { - dX = sizeX / 2 - TMath::Abs((this->GetPosition(n) - x0).X()); - dY = sizeY / 2 - TMath::Abs((this->GetPosition(n) - x0).Y()); - - d = min(dX, dY); - - if (d < hitDistance) hitDistance = d; - - nhits++; - } - } - - if (nhits == 0) return -1; - - return hitDistance; -} - -/////////////////////////////////////////////// -/// \brief This method returns the distance to the prism **top** face from the closest hit containned -/// inside the prism volume given by argument. -/// -/// \param x0 The center of the bottom face of the prism. -/// \param x1 The center of the top face of the prism. -/// \param sizeX Size of the side X of the prism face. -/// \param sizeY Size of the side X of the prism face. -/// \param theta An angle in radians to rotate the face of the prism. -/// -/// \return If no hit is found inside the prism, -1 is returned. -/// -Double_t TRestHitsEvent::GetClosestHitInsideDistanceToPrismTop(TVector3 x0, TVector3 x1, Double_t sizeX, - Double_t sizeY, Double_t theta) { - TVector3 axis = x1 - x0; - Double_t prismLength = axis.Mag(); - - Double_t hitDistance = prismLength; - - Double_t d; - Int_t nhits = 0; - for (int n = 0; n < GetNumberOfHits(); n++) { - if (fHits.isHitNInsidePrism(n, x0, x1, sizeX, sizeY, theta)) { - d = prismLength - axis.Dot(this->GetPosition(n) - x0) / prismLength; - - if (d < hitDistance) hitDistance = d; - - nhits++; - } - } - - if (nhits == 0) return -1; - - return hitDistance; -} - -/////////////////////////////////////////////// -/// \brief This method returns the distance to the prism **bottom** face from the closest hit containned -/// inside the prism volume given by argument. -/// -/// \param x0 The center of the bottom face of the prism. -/// \param x1 The center of the top face of the prism. -/// \param sizeX Size of the side X of the prism face. -/// \param sizeY Size of the side X of the prism face. -/// \param theta An angle in radians to rotate the face of the prism. -/// -/// \return If no hit is found inside the prism, -1 is returned. -/// -Double_t TRestHitsEvent::GetClosestHitInsideDistanceToPrismBottom(TVector3 x0, TVector3 x1, Double_t sizeX, - Double_t sizeY, Double_t theta) { - TVector3 axis = x1 - x0; - Double_t prismLength = axis.Mag(); - - Double_t hitDistance = prismLength; - - Double_t d; - Int_t nhits = 0; - for (int n = 0; n < GetNumberOfHits(); n++) { - if (fHits.isHitNInsidePrism(n, x0, x1, sizeX, sizeY, theta)) { - d = axis.Dot(this->GetPosition(n) - x0) / prismLength; - - if (d < hitDistance) hitDistance = d; - - nhits++; - } - } - - if (nhits == 0) return -1; - - return hitDistance; -} - -Double_t TRestHitsEvent::CalculateTotalDepositedEnergy() { - Double_t sum = 0; - for (int i = 0; i < GetNumberOfHits(); i++) sum += GetEnergy(i); - fHits.fTotEnergy = sum; - return sum; -} - -/////////////////////////////////////////////// -/// \brief This method draws the hits event structure into a TPad. -/// -/// This method receives as argument a string that defines the different plots to be produced. -/// -/// The following options are allowed: -/// -/// * **graph**: -/// * **hist**: -/// * **print**: -/// -/// The different options must separated by colons, as "option1:option2:option3". -/// -/// -/// \return A pointer to the TPad where the event was drawn is returned. -/// -TPad* TRestHitsEvent::DrawEvent(const TString& option) { - vector optList = Vector_cast(TRestTools::GetOptions((string)option)); - - SetBoundaries(); - - for (unsigned int n = 0; n < optList.size(); n++) { - if (optList[n] == "print") this->PrintEvent(); - } - - optList.erase(std::remove(optList.begin(), optList.end(), "print"), optList.end()); - - if (optList.size() == 0) optList.push_back("graph2d"); - - if (fPad != NULL) { - delete fPad; - fPad = NULL; - } - - fPad = new TPad(this->GetName(), " ", 0, 0, 1, 1); - fPad->Divide(3, 2 * optList.size()); - fPad->Draw(); - - Int_t column = 0; - for (unsigned int n = 0; n < optList.size(); n++) { - string optionStr = (string)optList[n]; - TString drawEventOption = optList[n]; - - // Generating drawOption argument - size_t startPos = optionStr.find("("); - if (startPos != string::npos) drawEventOption = optList[n](0, startPos); - - // Generating histogram option argument - string histOption = ""; - size_t endPos = optionStr.find(")"); - if (endPos != string::npos) { - TString histOptionTmp = optList[n](startPos + 1, endPos - startPos - 1); - - histOption = (string)histOptionTmp; - size_t pos = 0; - while ((pos = histOption.find(",", pos)) != string::npos) { - histOption.replace(pos, 1, ":"); - pos = pos + 1; - } - } - - // Generating histogram pitch argument - string pitchOption = ""; - - startPos = optionStr.find("["); - endPos = optionStr.find("]"); - Double_t pitch = 3; - if (endPos != string::npos) { - TString pitchOption = optList[n](startPos + 1, endPos - startPos - 1); - pitch = stod((string)pitchOption); - } - - if (drawEventOption == "graph") this->DrawGraphs(column); - - if (drawEventOption == "graph2d") this->DrawGraph2D(); - - if (drawEventOption == "hist") this->DrawHistograms(column, pitch, histOption); - } - - return fPad; -} - -void TRestHitsEvent::SetBoundaries() { - Double_t maxX = -1e10, minX = 1e10, maxZ = -1e10, minZ = 1e10, maxY = -1e10, minY = 1e10; - - for (int nhit = 0; nhit < this->GetNumberOfHits(); nhit++) { - Double_t x = fHits.GetX(nhit); - Double_t y = fHits.GetY(nhit); - Double_t z = fHits.GetZ(nhit); - - if (x > maxX) maxX = x; - if (x < minX) minX = x; - if (y > maxY) maxY = y; - if (y < minY) minY = y; - if (z > maxZ) maxZ = z; - if (z < minZ) minZ = z; - } - - fMinX = minX; - fMaxX = maxX; - - fMinY = minY; - fMaxY = maxY; - - fMinZ = minZ; - fMaxZ = maxZ; -} - -void TRestHitsEvent::DrawGraphs(Int_t& column) { - if (fXYHitGraph != NULL) { - delete fXYHitGraph; - fXYHitGraph = NULL; - } - if (fXZHitGraph != NULL) { - delete fXZHitGraph; - fXZHitGraph = NULL; - } - if (fYZHitGraph != NULL) { - delete fYZHitGraph; - fYZHitGraph = NULL; - } - - vector> xz(2, vector(this->GetNumberOfHits())); - vector> yz(2, vector(this->GetNumberOfHits())); - vector> xy(2, vector(this->GetNumberOfHits())); - - /* {{{ Creating xz, yz, and xy arrays and initializing graphs */ - Int_t nXZ = 0; - Int_t nYZ = 0; - Int_t nXY = 0; - - for (int nhit = 0; nhit < this->GetNumberOfHits(); nhit++) { - Double_t x = fHits.GetX(nhit); - Double_t y = fHits.GetY(nhit); - Double_t z = fHits.GetZ(nhit); - int type = fHits.GetType(nhit); - - if (type % XZ == 0) { - xz[0][nXZ] = x; - xz[1][nXZ] = z; - nXZ++; - } - - if (type % YZ == 0) { - yz[0][nYZ] = y; - yz[1][nYZ] = z; - nYZ++; - } - - if (type % XY == 0) { - xy[0][nXY] = x; - xy[1][nXY] = y; - nXY++; - } - } - - fXZHitGraph = new TGraph(nXZ, &xz[0][0], &xz[1][0]); - fXZHitGraph->SetMarkerColor(kBlue); - fXZHitGraph->SetMarkerSize(0.3); - fXZHitGraph->SetMarkerStyle(20); - - fYZHitGraph = new TGraph(nYZ, &yz[0][0], &yz[1][0]); - fYZHitGraph->SetMarkerColor(kRed); - fYZHitGraph->SetMarkerSize(0.3); - fYZHitGraph->SetMarkerStyle(20); - - fXYHitGraph = new TGraph(nXY, &xy[0][0], &xy[1][0]); - fXYHitGraph->SetMarkerColor(kBlack); - fXYHitGraph->SetMarkerSize(0.3); - fXYHitGraph->SetMarkerStyle(20); - /* }}} */ - - char title[256]; - sprintf(title, "Event ID %d", this->GetID()); - - if (nXZ > 0) { - fPad->cd(1 + 3 * column); - fXZHitGraph->SetTitle(title); - fXZHitGraph->Draw("AP*"); - - fXZHitGraph->GetXaxis()->SetTitle("X-axis (mm)"); - fXZHitGraph->GetYaxis()->SetTitle("Z-axis (mm)"); - } - - if (nYZ > 0) { - fPad->cd(2 + 3 * column); - fYZHitGraph->SetTitle(title); - fYZHitGraph->Draw("AP"); - - fYZHitGraph->GetXaxis()->SetTitle("Y-axis (mm)"); - fYZHitGraph->GetYaxis()->SetTitle("Z-axis (mm)"); - } - - if (nXY > 0) { - fPad->cd(3 + 3 * column); - fXYHitGraph->SetTitle(title); - fXYHitGraph->Draw("AP"); - - fXYHitGraph->GetXaxis()->SetTitle("X-axis (mm)"); - fXYHitGraph->GetYaxis()->SetTitle("Y-axis (mm)"); - } - - column++; -} - -void TRestHitsEvent::DrawGraph2D() { - if (gxz != NULL) { - delete gxz; - gxz = NULL; - } - if (gyz != NULL) { - delete gyz; - gyz = NULL; - } - - // prepare signal data - vector _xzx; - vector _xzz; - vector _xze; - vector _yzy; - vector _yzz; - vector _yze; - - for (auto hit : fHits) { - if (hit.type() == XZ) { - _xzx.push_back(hit.x()); - _xze.push_back(hit.e()); - _xzz.push_back(hit.z()); - } - if (hit.type() == YZ) { - _yzy.push_back(hit.y()); - _yze.push_back(hit.e()); - _yzz.push_back(hit.z()); - } - } - - // cout << _xzz.size() << " " << _yzz.size() << endl; - - // double max = _xzx.size() > 0 ? *max_element(begin(_xzx), end(_xzx)) + 3 : 3; - // double min = _xzx.size() > 0 ? *min_element(begin(_xzx), end(_xzx)) - 3 : -3; - // for (int j = 0; j < fNz; j++) { - // _xzx.push_back(max); - // _xze.push_back(0); - // _xzz.push_back(-j); - // _xzx.push_back(min); - // _xze.push_back(0); - // _xzz.push_back(-j); - //} - - // max = _yzy.size() > 0 ? *max_element(begin(_yzy), end(_yzy)) + 3 : 3; - // min = _yzy.size() > 0 ? *min_element(begin(_yzy), end(_yzy)) - 3 : -3; - // for (int j = 0; j < fNz; j++) { - // _yzy.push_back(max); - // _yze.push_back(0); - // _yzz.push_back(-j); - // _yzy.push_back(min); - // _yze.push_back(0); - // _yzz.push_back(-j); - //} - - gxz = new TGraph2D("gxz", "gxz", _xzz.size(), &_xzx[0], &_xzz[0], &_xze[0]); - gxz->SetTitle((TString) "XZ plot, " + ToString(GetNumberOfHitsX()) + " Signals"); - gxz->GetXaxis()->SetTitle("X"); - gxz->GetYaxis()->SetTitle("Z"); - gxz->SetNpx(100); - gxz->SetNpy(500); - - gyz = new TGraph2D("gyz", "gyz", _yzz.size(), &_yzy[0], &_yzz[0], &_yze[0]); - gyz->SetTitle((TString) "YZ plot, " + ToString(GetNumberOfHitsY()) + " Signals"); - gyz->GetXaxis()->SetTitle("Y"); - gyz->GetYaxis()->SetTitle("Z"); - gyz->SetNpx(100); - gyz->SetNpy(500); - - // fPad->Divide(2, 1); - - auto pad = fPad->cd(1); - pad->SetRightMargin(0.15); - if (gxz != NULL) gxz->Draw("colz"); - - pad = fPad->cd(2); - pad->SetLeftMargin(0); - pad->SetRightMargin(0.15); - if (gyz != NULL) gyz->Draw("colz"); -} - -void TRestHitsEvent::DrawHistograms(Int_t& column, Double_t pitch, TString histOption) { - if (fXYHisto != NULL) { - delete fXYHisto; - fXYHisto = NULL; - } - if (fXZHisto != NULL) { - delete fXZHisto; - fXZHisto = NULL; - } - if (fYZHisto != NULL) { - delete fYZHisto; - fYZHisto = NULL; - } - - if (fXHisto != NULL) { - delete fXHisto; - fXHisto = NULL; - } - if (fYHisto != NULL) { - delete fYHisto; - fYHisto = NULL; - } - if (fZHisto != NULL) { - delete fZHisto; - fZHisto = NULL; - } - - Int_t nBinsX = (fMaxX - fMinX + 20) / pitch; - Int_t nBinsY = (fMaxY - fMinY + 20) / pitch; - Int_t nBinsZ = (fMaxZ - fMinZ + 20) * 3 / pitch; - - fXYHisto = new TH2F("XY", "", nBinsX, fMinX - 10, fMinX + pitch * nBinsX, nBinsY, fMinY - 10, - fMinY + pitch * nBinsY); - fXZHisto = new TH2F("XZ", "", nBinsX, fMinX - 10, fMinX + pitch * nBinsX, nBinsZ, fMinZ - 10, - fMinZ + (pitch / 3) * nBinsZ); - fYZHisto = new TH2F("YZ", "", nBinsY, fMinY - 10, fMinY + pitch * nBinsY, nBinsZ, fMinZ - 10, - fMinZ + (pitch / 3) * nBinsZ); - - fXHisto = new TH1F("X", "", nBinsX, fMinX - 10, fMinX + pitch * nBinsX); - fYHisto = new TH1F("Y", "", nBinsY, fMinY - 10, fMinY + pitch * nBinsY); - fZHisto = new TH1F("Z", "", nBinsZ, fMinZ - 10, fMinZ + pitch * nBinsZ); - - Int_t nYZ = 0, nXZ = 0, nXY = 0; - Int_t nX = 0, nY = 0, nZ = 0; - - for (int nhit = 0; nhit < this->GetNumberOfHits(); nhit++) { - Double_t x = fHits.GetX(nhit); - Double_t y = fHits.GetY(nhit); - Double_t z = fHits.GetZ(nhit); - int type = fHits.GetType(nhit); - - if (type % XZ == 0) { - fXZHisto->Fill(x, z); - nXZ++; - } - - if (type % YZ == 0) { - fYZHisto->Fill(y, z); - nYZ++; - } - - if (type % XY == 0) { - fXYHisto->Fill(x, y); - nXY++; - } - - if (type % X == 0) { - fXHisto->Fill(x); - nX++; - } - - if (type % Y == 0) { - fYHisto->Fill(y); - nY++; - } - - if (type % Z == 0) { - fZHisto->Fill(z); - nZ++; - } - } - - TStyle style; - style.SetPalette(1); - - if (nXZ > 0) { - fPad->cd(1 + 3 * column); - fXZHisto->Draw(histOption); - fXZHisto->GetXaxis()->SetTitle("X-axis (mm)"); - fXZHisto->GetYaxis()->SetTitle("Z-axis (mm)"); - fXZHisto->GetYaxis()->SetTitleSize(1.4 * fXZHisto->GetYaxis()->GetTitleSize()); - fXZHisto->GetXaxis()->SetTitleSize(1.4 * fXZHisto->GetXaxis()->GetTitleSize()); - fXZHisto->GetYaxis()->SetLabelSize(1.25 * fXZHisto->GetYaxis()->GetLabelSize()); - fXZHisto->GetXaxis()->SetLabelSize(1.25 * fXZHisto->GetXaxis()->GetLabelSize()); - fXZHisto->GetYaxis()->SetTitleOffset(1.75); - } - - if (nYZ > 0) { - fPad->cd(2 + 3 * column); - fYZHisto->Draw(histOption); - fYZHisto->GetXaxis()->SetTitle("Y-axis (mm)"); - fYZHisto->GetYaxis()->SetTitle("Z-axis (mm)"); - fYZHisto->GetYaxis()->SetTitleSize(1.4 * fYZHisto->GetYaxis()->GetTitleSize()); - fYZHisto->GetXaxis()->SetTitleSize(1.4 * fYZHisto->GetXaxis()->GetTitleSize()); - fYZHisto->GetYaxis()->SetLabelSize(1.25 * fYZHisto->GetYaxis()->GetLabelSize()); - fYZHisto->GetXaxis()->SetLabelSize(1.25 * fYZHisto->GetXaxis()->GetLabelSize()); - fYZHisto->GetYaxis()->SetTitleOffset(1.75); - } - - if (nXY > 0) { - fPad->cd(3 + 3 * column); - fXYHisto->Draw(histOption); - fXYHisto->GetXaxis()->SetTitle("X-axis (mm)"); - fXYHisto->GetYaxis()->SetTitle("Y-axis (mm)"); - } - - column++; - - if (nX > 0) { - fPad->cd(1 + 3 * column); - fXHisto->Draw(histOption); - fXHisto->GetXaxis()->SetTitle("X-axis (mm)"); - fXHisto->GetYaxis()->SetTitle("Number of events"); - } - - if (nY > 0) { - fPad->cd(2 + 3 * column); - fYHisto->Draw(histOption); - fYHisto->GetYaxis()->SetTitle("Y-axis (mm)"); - fYHisto->GetYaxis()->SetTitle("Number of events"); - } - - if (nZ > 0) { - fPad->cd(3 + 3 * column); - fZHisto->Draw(histOption); - fZHisto->GetZaxis()->SetTitle("Z-axis (mm)"); - fZHisto->GetYaxis()->SetTitle("Number of events"); - } - - column++; -} - -void TRestHitsEvent::PrintEvent(Int_t nHits) { - TRestEvent::PrintEvent(); - - cout << "Total energy : " << GetTotalDepositedEnergy() << endl; - cout << "Mean position : ( " << GetMeanPositionX() << " , " << GetMeanPositionY() << " , " - << GetMeanPositionZ() << " ) " << endl; - cout << "Number of hits : " << fHits.GetNumberOfHits() << endl; - if (nHits != -1) { - cout << "+++++++++++++++++++++++" << endl; - cout << "Printing only the first " << nHits << " hits" << endl; - } - - fHits.PrintHits(nHits); -} +#include "TRestHitsEvent.h" \ No newline at end of file diff --git a/src/TRestReadout.cxx b/src/TRestReadout.cxx index b6944be..edae262 100644 --- a/src/TRestReadout.cxx +++ b/src/TRestReadout.cxx @@ -264,734 +264,4 @@ /// /// -#include "TRestReadout.h" -using namespace std; -bool RESTREADOUT_DECODINGFILE_ERROR = false; - -ClassImp(TRestReadout); -/////////////////////////////////////////////// -/// \brief TRestReadout default constructor -/// -TRestReadout::TRestReadout() { - RESTWarning << "Creating legacy metadata TRestReadout" << RESTendl; - RESTWarning << "This class is now implemented under TRestDetectorReadout" << RESTendl; - Initialize(); -} - -/////////////////////////////////////////////// -/// \brief TRestReadout constructor loading data from a config file -/// -/// If no configuration path was defined using TRestMetadata::SetConfigFilePath -/// the path to the config file must be specified using full path, absolute or -/// relative. -/// -/// By default the config file must be specified with full path, absolute or -/// relative. -/// -/// First TRestReadout section occurrence will be loaded. -/// -/// \param cfgFileName A const char* giving the path to an RML file. -/// -TRestReadout::TRestReadout(const char* cfgFileName) : TRestMetadata(cfgFileName) { - cout << "Loading readout. This might take few seconds" << endl; - RESTWarning << "Creating legacy metadata TRestReadout" << RESTendl; - RESTWarning << "This class is now implemented under TRestDetectorReadout" << RESTendl; - Initialize(); - - LoadConfigFromFile(fConfigFileName); -} - -/////////////////////////////////////////////// -/// \brief TRestReadout constructor loading data from a config file -/// -/// If no configuration path was defined using TRestMetadata::SetConfigFilePath -/// the path to the config file must be specified using full path, absolute or -/// relative. -/// -/// By default the config file must be specified with full path, absolute or -/// relative. -/// -/// \param cfgFileName A const char* giving the path to an RML file. -/// \param name The name of the TRestReadout section to be loaded -/// -TRestReadout::TRestReadout(const char* cfgFileName, string name) : TRestMetadata(cfgFileName) { - cout << "Loading readout. This might take few seconds" << endl; - RESTWarning << "Creating legacy metadata TRestReadout" << RESTendl; - RESTWarning << "This class is now implemented under TRestDetectorReadout" << RESTendl; - Initialize(); - - LoadConfigFromFile(fConfigFileName, name); -} - -/////////////////////////////////////////////// -/// \brief Initializes the readout members and defines the section name -/// -void TRestReadout::Initialize() { - SetSectionName(this->ClassName()); - - fDecoding = false; - - fNReadoutPlanes = 0; - fReadoutPlanes.clear(); -} - -/////////////////////////////////////////////// -/// \brief TRestReadout default destructor -/// -TRestReadout::~TRestReadout() {} - -/////////////////////////////////////////////// -/// \brief Returns the number of readout planes defined on the readout -/// -Int_t TRestReadout::GetNumberOfReadoutPlanes() { return fReadoutPlanes.size(); } - -/////////////////////////////////////////////// -/// \brief Returns the **total** number of modules implemented in **all** -/// the readout planes. -/// -Int_t TRestReadout::GetNumberOfModules() { - Int_t modules = 0; - for (int p = 0; p < GetNumberOfReadoutPlanes(); p++) modules += fReadoutPlanes[p].GetNumberOfModules(); - return modules; -} - -/////////////////////////////////////////////// -/// \brief Returns the **total** number of channels implemented in **all** -/// the readout planes and modules. -/// -Int_t TRestReadout::GetNumberOfChannels() { - Int_t channels = 0; - for (int p = 0; p < GetNumberOfReadoutPlanes(); p++) - for (int m = 0; m < fReadoutPlanes[p].GetNumberOfModules(); m++) - channels += fReadoutPlanes[p][m].GetNumberOfChannels(); - return channels; -} - -/////////////////////////////////////////////// -/// \brief Returns a pointer to the readout plane by ID -/// -TRestReadoutPlane* TRestReadout::GetReadoutPlaneWithID(int id) { - for (int i = 0; i < this->GetNumberOfReadoutPlanes(); i++) { - if (fReadoutPlanes[i].GetID() == id) { - return &fReadoutPlanes[i]; - } - } - - return NULL; -} - -/////////////////////////////////////////////// -/// \brief Returns a pointer to the readout module by ID -/// -/// e.g. micromegas M0 has id 0, M5 has id 5. The **ID** is Unique of all the -/// readout mudules -TRestReadoutModule* TRestReadout::GetReadoutModuleWithID(int id) { - for (int i = 0; i < this->GetNumberOfReadoutPlanes(); i++) { - TRestReadoutPlane& plane = fReadoutPlanes[i]; - - for (int j = 0; j < plane.GetNumberOfModules(); j++) { - if (plane[j].GetModuleID() == id) { - return &plane[j]; - } - } - } - return NULL; -} - -TRestReadoutChannel* TRestReadout::GetReadoutChannelWithdaqID(int daqId) { - int planeID = -1, moduleID = -1, channelID = -1; - - GetPlaneModuleChannel(daqId, planeID, moduleID, channelID); - if (channelID >= 0) { - return &fReadoutPlanes[planeID][moduleID][channelID]; - } - - return NULL; -} - -/////////////////////////////////////////////// -/// \brief Returns a pointer to the readout plane by index -/// -TRestReadoutPlane* TRestReadout::GetReadoutPlane(int p) { - if (p < fNReadoutPlanes) - return &fReadoutPlanes[p]; - else { - RESTWarning << "TRestReadout::GetReadoutPlane." << RESTendl; - RESTWarning << "Readout plane index exceeded." << RESTendl; - RESTWarning << "Index requested : " << p << RESTendl; - RESTWarning << "Number of readout planes defined : " << fNReadoutPlanes << RESTendl; - } - - return NULL; -} - -/////////////////////////////////////////////// -/// \brief Adds a readout plane to the readout -/// -void TRestReadout::AddReadoutPlane(TRestReadoutPlane plane) { - fReadoutPlanes.push_back(plane); - fNReadoutPlanes++; -} - -/////////////////////////////////////////////// -/// \brief Initializes the readout members using the information given in -/// the TRestReadout RML section. -/// -void TRestReadout::InitFromConfigFile() { - fMappingNodes = StringToInteger(GetParameter("mappingNodes", "0")); - -#pragma region ParseModuledefinition - vector fModuleDefinitions; - TiXmlElement* moduleDefinition = GetElement("readoutModule"); - while (moduleDefinition != NULL) { - if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { - cout << "------module-----------------" << endl; - cout << moduleDefinition << endl; - cout << "-----------------------------" << endl; - GetChar(); - } - - TRestReadoutModule module = *ParseModuleDefinition(moduleDefinition); - // module.DoReadoutMapping(fMappingNodes); - fModuleDefinitions.push_back(module); - moduleDefinition = GetNextElement(moduleDefinition); - } -#pragma endregion - TiXmlElement* planeDefinition = GetElement("readoutPlane"); - vector moduleVector; - Int_t addedChannels = 0; - while (planeDefinition != NULL) { - TRestReadoutPlane plane; - - plane.SetID(GetNumberOfReadoutPlanes()); - plane.SetPosition(Get3DVectorParameterWithUnits("position", planeDefinition)); - plane.SetCathodePosition(Get3DVectorParameterWithUnits("cathodePosition", planeDefinition)); - plane.SetPlaneVector(StringTo3DVector(GetFieldValue("planeVector", planeDefinition))); - plane.SetChargeCollection(StringToDouble(GetFieldValue("chargeCollection", planeDefinition))); - - Double_t tDriftDistance = plane.GetDistanceTo(plane.GetCathodePosition()); - plane.SetTotalDriftDistance(tDriftDistance); - -#pragma region addReadoutModuleToPlane - - moduleVector.clear(); - TiXmlElement* moduleDefinition = GetElement("addReadoutModule", planeDefinition); - while (moduleDefinition != NULL) { - TString modName = GetFieldValue("name", moduleDefinition); - Int_t mid = -1; - for (unsigned int i = 0; i < fModuleDefinitions.size(); i++) { - if (fModuleDefinitions[i].GetName() == modName) { - mid = i; - } - } - - if (mid == -1) { - RESTError << "TRestReadout at . Module name " << modName << " not found!" - << RESTendl; - RESTError << "Please, check spelling" << RESTendl; - exit(1); - } - - fModuleDefinitions[mid].SetModuleID(StringToInteger(GetFieldValue("id", moduleDefinition))); - if (fModuleDefinitions[mid].GetModuleID() < -1) { - RESTWarning << "Module id must be positive!" << RESTendl; - fModuleDefinitions[mid].SetModuleID(-1); // set to -1 to generate from hash later on - } - fModuleDefinitions[mid].SetUniqueName(GetFieldValue("uniqueName", moduleDefinition)); - fModuleDefinitions[mid].SetOrigin(StringTo2DVector(GetFieldValue("origin", moduleDefinition))); - fModuleDefinitions[mid].SetRotation(StringToDouble(GetFieldValue("rotation", moduleDefinition))); - -#pragma region SetupDecodingFile - - Int_t firstDaqChannel = StringToInteger(GetFieldValue("firstDaqChannel", moduleDefinition)); - if (firstDaqChannel == -1) firstDaqChannel = addedChannels; - - string decodingFile = GetFieldValue("decodingFile", moduleDefinition); - if (decodingFile == PARAMETER_NOT_FOUND_STR || decodingFile == "" || - RESTREADOUT_DECODINGFILE_ERROR) - fDecoding = false; - else - fDecoding = true; - - string _decodingFile = SearchFile(decodingFile); - - if (fDecoding && !TRestTools::fileExists(_decodingFile.c_str())) { - RESTWarning << "The decoding file does not exist!" << RESTendl; - RESTWarning << "--------------------------------" << RESTendl; - RESTWarning << "File : " << decodingFile << RESTendl; - RESTWarning << "Default decoding will be used. readoutChannel=daqChannel" << RESTendl; - RESTWarning << "To avoid this message and use the default decoding define : " - "decodingFile=\"\"" - << RESTendl; - RESTWarning << "--------------------------------" << RESTendl; - RESTWarning << "Press a KEY to continue..." << RESTendl; - getchar(); - fDecoding = false; - RESTREADOUT_DECODINGFILE_ERROR = true; - } - - decodingFile = _decodingFile; - - vector rChannel; - vector dChannel; - if (fDecoding && TRestTools::fileExists(decodingFile.c_str())) { - FILE* f = fopen(decodingFile.c_str(), "r"); - - Int_t daq, readout; - while (!feof(f)) { - if (fscanf(f, "%d\t%d\n", &daq, &readout) <= 0) { - RESTError << "TRestReadout::InitFromConfigFile. Problem reading decoding" << RESTendl; - RESTError << "This error might need support at REST forum" << RESTendl; - exit(-1); - } - // we skip blank daq channels if readout id is <0 - // e.g. daq id: 22, readout id: -1 - if (readout >= 0) { - rChannel.push_back(readout); - dChannel.push_back(daq + firstDaqChannel); - } - } - fclose(f); - } - - if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Debug) { - cout << "------module-----------------" << endl; - cout << moduleDefinition << endl; - cout << "-----------------------------" << endl; - getchar(); - } - - if (fDecoding && (unsigned int)fModuleDefinitions[mid].GetNumberOfChannels() != rChannel.size()) { - RESTError << "TRestReadout." - << " The number of channels defined in the readout is not the same" - << " as the number of channels found in the decoding." << RESTendl; - exit(1); - } - - for (int ch = 0; ch < fModuleDefinitions[mid].GetNumberOfChannels(); ch++) { - if (!fDecoding) { - Int_t id = ch; - rChannel.push_back(id); - dChannel.push_back(id + firstDaqChannel); - } - - // WRONG version before --> - // fModuleDefinitions[mid].GetChannel(ch)->SetID( rChannel[ch] ); - fModuleDefinitions[mid].GetChannel(rChannel[ch])->SetDaqID(dChannel[ch]); - fModuleDefinitions[mid].GetChannel(rChannel[ch])->SetChannelID(rChannel[ch]); - -#pragma endregion - addedChannels++; - } - fModuleDefinitions[mid].SetMinMaxDaqIDs(); - - moduleVector.push_back(fModuleDefinitions[mid]); - // plane.AddModule( fModuleDefinitions[mid] ); - - moduleDefinition = GetNextElement(moduleDefinition); - } - - // We removed the constraint that module id's should start by 0 and have no - // missing numbers in a multi-module readout plane. Modules can have their - // special "id", e.g. M0, M2, M3, M4 in SJTU proto. We don't have M1 - // edit: 2022/04: modules now have their special names. If so, the id will automatically - // be assigned if not right. - - for (Int_t i(0); i < (Int_t)moduleVector.size(); i++) { - if (moduleVector[i].GetModuleID() == -1) { - if (moduleVector[i].GetUniqueName() != "" && - moduleVector[i].GetUniqueName() != PARAMETER_NOT_FOUND_STR) { - moduleVector[i].SetModuleID(abs((int)ToHash(moduleVector[i].GetUniqueName()))); - } else { - RESTError - << "TRestReadout::InitFromConfigFile() Module id and unique name are both empty!" - << RESTendl; - exit(0); - } - } - - plane.AddModule(moduleVector[i]); - } -#pragma endregion - - this->AddReadoutPlane(plane); - planeDefinition = GetNextElement(planeDefinition); - } - - ValidateReadout(); -} - -TRestReadoutModule* TRestReadout::ParseModuleDefinition(TiXmlElement* moduleDefinition) { - TRestReadoutModule* mod = new TRestReadoutModule(); - TRestReadoutModule& module = *mod; - if (GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Warning) module.EnableWarnings(); - - module.SetName(GetFieldValue("name", moduleDefinition)); - module.SetSize(StringTo2DVector(GetFieldValue("size", moduleDefinition))); - module.SetTolerance(StringToDouble(GetFieldValue("tolerance", moduleDefinition))); - -#pragma region addChannel - vector channelVector; - vector channelIDVector; - TiXmlElement* channelDefinition = GetElement("readoutChannel", moduleDefinition); - while (channelDefinition != NULL) { - TRestReadoutChannel channel; - - Int_t id = StringToInteger(GetFieldValue("id", channelDefinition)); - if (id != -1) channelIDVector.push_back(id); - channel.SetDaqID(-1); - -#pragma region addPixel - vector pixelVector; - vector pixelIDVector; - TiXmlElement* pixelDefinition = GetElement("addPixel", channelDefinition); - while (pixelDefinition != NULL) { - TRestReadoutPixel pixel; - - pixel.SetOrigin(StringTo2DVector(GetFieldValue("origin", pixelDefinition))); - pixel.SetSize(StringTo2DVector(GetFieldValue("size", pixelDefinition))); - pixel.SetRotation(StringToDouble(GetFieldValue("rotation", pixelDefinition))); - pixel.SetTriangle(StringToBool(GetFieldValue("triangle", pixelDefinition))); - - if (StringToInteger(GetFieldValue("id", pixelDefinition)) != -1) - pixelIDVector.push_back(StringToInteger(GetFieldValue("id", pixelDefinition))); - pixelVector.push_back(pixel); - // channel.AddPixel( pixel ); - pixelDefinition = GetNextElement(pixelDefinition); - } - - if (pixelIDVector.size() > 0 && pixelIDVector.size() != pixelVector.size()) { - RESTError - << "pixel id definition may be wrong! It must be coherent and starts from 0. Check your " - "readout module definition!" - << RESTendl; - exit(0); - } - - // Creating the vector fReadoutPixel in the channel with pixels added in the - // order of their ID. - for (Int_t i(0); i < (Int_t)pixelVector.size(); i++) { - for (Int_t j(0); j < (Int_t)pixelVector.size(); j++) { - if (pixelIDVector[j] == i) { - channel.AddPixel(pixelVector[j]); - break; - } - } - } - - if (channel.GetNumberOfPixels() != pixelVector.size()) { - RESTError << "pixel id definition may be wrong! check your " - "readout module definition!" - << RESTendl; - exit(0); - } -#pragma endregion - - channelVector.push_back(channel); - channelDefinition = GetNextElement(channelDefinition); - } - - if (channelIDVector.size() > 0 && channelIDVector.size() != channelVector.size()) { - RESTError << "TRestReadout::ParseModuleDefinition. Channel id definition may be wrong!" - << "check your readout module definition!" << RESTendl; - RESTError << " " << RESTendl; - RESTError << "channelIDVector size : " << channelIDVector.size() << RESTendl; - RESTError << "channel vector size : " << channelVector.size() << RESTendl; - - exit(0); - } - - // Creating the vector fReadoutChannel in the module with channels added in - // the order of their ID. - for (Int_t i(0); i < (Int_t)channelVector.size(); i++) { - for (Int_t j(0); j < (Int_t)channelVector.size(); j++) { - if (channelIDVector[j] == i) { - module.AddChannel(channelVector[j]); - break; - } - } - } - - if (module.GetNumberOfChannels() != channelVector.size()) { - RESTError << "TRestReadout::ParseModuleDefinition. Channel id definition may be wrong!" - << "check your readout module definition!" << RESTendl; - RESTError << " " << RESTendl; - RESTError << "Module number of channels : " << module.GetNumberOfChannels() << RESTendl; - RESTError << "channel vector size : " << channelVector.size() << RESTendl; - - exit(0); - } -#pragma endregion - - return mod; -} - -/////////////////////////////////////////////// -/// \brief Starts the readout mapping initialization. This process -/// is computationally expensive but it greatly optimizes the FindChannel -/// process later on. -/// -void TRestReadout::DoReadoutMapping(TRestReadoutModule* mod, int nodes) { - /////////////////////////////////////////////////////////////////////////////// - // We initialize the mapping readout net to sqrt(numberOfPixels) - // However this might not be good for readouts where the pixels are - // assymmetric - // ///////////////////////////////////////////////////////////////////////////// - Int_t totalNumberOfPixels = 0; - for (int ch = 0; ch < mod->GetNumberOfChannels(); ch++) - totalNumberOfPixels += mod->GetChannel(ch)->GetNumberOfPixels(); - - if (nodes == 0) { - nodes = TMath::Sqrt(totalNumberOfPixels); - nodes = 2 * nodes; - } - - cout << "Performing readout mapping optimization (This might require long " - "computation time)" - << endl; - cout << "--------------------------------------------------------------------" - "--------------" - << endl; - cout << "Total number of pixels : " << totalNumberOfPixels << endl; - cout << "Nodes : " << nodes << endl; - - TRestReadoutMapping& fMapping = fReadoutMappings[mod->GetName()]; - fMapping.Initialize(nodes, nodes, mod->GetModuleSizeX(), mod->GetModuleSizeY()); - - // 1. loop for each pixel, find the mapping nodes for the pixel position, - // and assign the pixel/channel id to the nodes. - for (int ch = 0; ch < mod->GetNumberOfChannels(); ch++) { - for (int px = 0; px < mod->GetChannel(ch)->GetNumberOfPixels(); px++) { - Double_t xPix = mod->GetChannel(ch)->GetPixel(px)->GetCenter().X(); - Double_t yPix = mod->GetChannel(ch)->GetPixel(px)->GetCenter().Y(); - - Int_t nodeX = fMapping.GetNodeX(xPix); - Int_t nodeY = fMapping.GetNodeY(yPix); - - // This means that two pixels in the readout are associated to the same - // node. - // If the granularity of the readout is not high enough this may happen - // often. This should be just a RESTWarning I guess. - if (fMapping.isNodeSet(nodeX, nodeY)) { - cout << endl; - RESTWarning << "TRestReadoutModule. Node is already SET!!" << RESTendl; - RESTWarning << "Trying to associate channel : " << ch << " Pixel : " << px << RESTendl; - RESTWarning << "Pixel coordinates : ( " << xPix << " , " << yPix << " ) " << RESTendl; - - Int_t tempCh = fMapping.GetChannelByNode(nodeX, nodeY); - Int_t tempPix = fMapping.GetPixelByNode(nodeX, nodeY); - RESTWarning << "Already associated channel : " << tempCh << " pixel : " << tempPix - << RESTendl; - Double_t xP = mod->GetChannel(tempCh)->GetPixel(tempPix)->GetCenter().X(); - Double_t yP = mod->GetChannel(tempCh)->GetPixel(tempPix)->GetCenter().Y(); - RESTWarning << "Pixel coordinates : ( " << xP << " , " << yP << " ) " << RESTendl; - cout << endl; - - cout << "Increasing the number of mapping of nodes may solve this issue." << endl; - cout << endl; - } - fMapping.SetNode(nodeX, nodeY, ch, px); - } - } - - // 2. There should still be some nodes without channel/pixel id assignment. Now - // we loop for all the nodes and find the pixel on their position - for (int i = 0; i < nodes; i++) { - printf("Completed : %.2lf %%\r", 100. * (i * (Double_t)nodes) / nodes / nodes); - fflush(stdout); - for (int j = 0; j < nodes; j++) { - Double_t x = fMapping.GetX(i); - Double_t y = fMapping.GetY(j); - - if (!fMapping.isNodeSet(i, j)) { - // find the nearby nodes with channel/pixel ids set - // const int NNearby = 5; - // for (int ii = i - NNearby; ii <= i + NNearby; ii++) { - // if (ii < 0 || ii >= nodes || ii == i) continue; - // for (int jj = j - NNearby; jj <= j + NNearby; jj++) { - // if (jj < 0 || jj >= nodes || jj == i) continue; - - // if (fMapping.isNodeSet(ii, jj)) { - // Int_t ch = fMapping.GetChannelByNode(ii, jj); - // Int_t px = fMapping.GetPixelByNode(ii, jj); - - // if (mod->isInsidePixelRelative(ch, px, x, y)) { - // fMapping.SetNode(i, j, ch, px); - // } - // } - // } - //} - - // if cannot find pixel within nearby 10*10 nodes, do a thorough scan - if (!fMapping.isNodeSet(i, j)) { - for (int ch = 0; ch < GetNumberOfChannels() && !fMapping.isNodeSet(i, j); ch++) { - for (int px = 0; - px < mod->GetChannel(ch)->GetNumberOfPixels() && !fMapping.isNodeSet(i, j); - px++) { - if (mod->isInsidePixelRelative(ch, px, x, y)) { - fMapping.SetNode(i, j, ch, px); - } - } - } - } - } - } - } - - if (!fMapping.AllNodesSet()) - cout << "Not all nodes set" << endl; - else - cout << "All Nodes set" << endl; - - // save this generated mapping - for (int i = 0; i < fReadoutPlanes.size(); i++) { - TRestReadoutPlane* p = &fReadoutPlanes[i]; - for (int j = 0; j < p->GetNumberOfModules(); j++) { - TRestReadoutModule* m = p->GetModule(j); - if (m->GetName() == mod->GetName()) { - m->SetReadoutMapping(&fMapping); - } - } - } - return; -} - -/////////////////////////////////////////////// -/// \brief This method is not implemented yet. But it could -/// do some checks to help verifying the readout. -/// -void TRestReadout::ValidateReadout() { - // cout << "--------------------------------------------------" << endl; - // cout << "TRestReadout::ValidateReadout:: NOT IMPLEMENTED" << endl; - // cout << "This function should crosscheck that there are no repeated " - // "DaqChannels IDs" - // << endl; - // cout << "If any checks are implemented in the future. Those checks should be " - // "an option." - // << endl; - // cout << "No dead area in the readout module" << endl; - // cout << "And other checks" << endl; - // cout << "--------------------------------------------------" << endl; -} - -void TRestReadout::GetPlaneModuleChannel(Int_t signalID, Int_t& planeID, Int_t& moduleID, Int_t& channelID) { - for (int p = 0; p < GetNumberOfReadoutPlanes(); p++) { - TRestReadoutPlane* plane = &fReadoutPlanes[p]; - for (int m = 0; m < plane->GetNumberOfModules(); m++) { - TRestReadoutModule* mod = &(*plane)[m]; - - if (mod->isDaqIDInside(signalID)) { - planeID = plane->GetID(); - moduleID = mod->GetModuleID(); - channelID = mod->DaqToReadoutChannel(signalID); - } - } - } -} - -Int_t TRestReadout::GetHitsDaqChannel(TVector3 hitpos, Int_t& planeID, Int_t& moduleID, Int_t& channelID) { - double x = hitpos.X(); - double y = hitpos.Y(); - double z = hitpos.Z(); - - for (int p = 0; p < GetNumberOfReadoutPlanes(); p++) { - TRestReadoutPlane* plane = &fReadoutPlanes[p]; - int m = plane->GetModuleIDFromPosition(x, y, z); - if (m >= 0) { - // TRestReadoutModule* mod = plane->GetModuleByID(m); - TRestReadoutModule* mod = plane->GetModuleByID(m); - - if (mod->GetMapping() == NULL) { - if (fReadoutMappings.count(mod->GetName()) != 0) { - mod->SetReadoutMapping(&fReadoutMappings[mod->GetName()]); - } else { - DoReadoutMapping(mod, fMappingNodes); - } - } - - Int_t readoutChannel = mod->FindChannel(x, y); - if (readoutChannel >= 0) { - planeID = plane->GetID(); - moduleID = mod->GetModuleID(); - channelID = readoutChannel; - return mod->GetChannel(readoutChannel)->GetDaqID(); - } - } - } - return -1; -} - -Double_t TRestReadout::GetX(Int_t signalID) { - Int_t planeID, readoutChannel = -1, readoutModule; - GetPlaneModuleChannel(signalID, planeID, readoutModule, readoutChannel); - if (readoutChannel == -1) { - // cout << "REST Warning : Readout channel not found for daq ID : " << signalID << endl; - return numeric_limits::quiet_NaN(); - } - return GetX(planeID, readoutModule, readoutChannel); -} - -Double_t TRestReadout::GetY(Int_t signalID) { - Int_t planeID, readoutChannel = -1, readoutModule; - GetPlaneModuleChannel(signalID, planeID, readoutModule, readoutChannel); - if (readoutChannel == -1) { - // cout << "REST Warning : Readout channel not found for daq ID : " << signalID << endl; - return numeric_limits::quiet_NaN(); - } - return GetY(planeID, readoutModule, readoutChannel); -} -/////////////////////////////////////////////// -/// \brief It returns the x-coordinate for the given readout -/// plane, *plane*, a given module, *modID*, and a given -/// channel, *chID*. -/// -Double_t TRestReadout::GetX(Int_t plane, Int_t modID, Int_t chID) { - return GetReadoutPlaneWithID(plane)->GetX(modID, chID); -} - -/////////////////////////////////////////////// -/// \brief It returns the y-coordinate for the given readout -/// plane, *plane*, a given module, *modID*, and a given -/// channel, *chID*. -/// -Double_t TRestReadout::GetY(Int_t plane, Int_t modID, Int_t chID) { - return GetReadoutPlaneWithID(plane)->GetY(modID, chID); -} - -/////////////////////////////////////////////// -/// \brief Prints on screen the details about the readout -/// definition. -/// -/// \param fullDetail Prints all modules, channels and pixels info. -/// -void TRestReadout::PrintMetadata(Int_t DetailLevel) { - if (DetailLevel >= 0) { - TRestMetadata::PrintMetadata(); - - RESTMetadata << "Number of readout planes : " << fNReadoutPlanes << RESTendl; - RESTMetadata << "Decoding was defined : "; - if (fDecoding) - RESTMetadata << "YES" << RESTendl; - else - RESTMetadata << "NO" << RESTendl; - RESTMetadata << "-----------------------------------" << RESTendl; - for (int p = 0; p < GetNumberOfReadoutPlanes(); p++) fReadoutPlanes[p].Print(DetailLevel - 1); - RESTMetadata << "****************************************" << RESTendl; - cout << RESTendl; - } -} - -/////////////////////////////////////////////// -/// \brief Draws the readout on screen. Not yet implemented. -/// -void TRestReadout::Draw() { - cout << " TRestReadout::Draw() is not implemented" << endl; - cout << " To draw a TRestReadout class with name \"readoutName\""; - cout << " stored in a ROOT file \"rootFile.root\"" << endl; - cout << " You can use the script : REST_Readout_Viewer( \"rootFile.root\", " - "\"readoutName\" )" - << endl; - cout << endl; - cout << " Or you can access directly a readout plane and draw using : " << endl; - cout << " readout->GetReadoutPlane( 0 )->Draw( ); " << endl; -} +#include "TRestReadout.h" \ No newline at end of file diff --git a/src/TRestReadoutChannel.cxx b/src/TRestReadoutChannel.cxx index e33ccdd..4a38262 100644 --- a/src/TRestReadoutChannel.cxx +++ b/src/TRestReadoutChannel.cxx @@ -41,66 +41,4 @@ ///
/// -#include "TRestReadoutChannel.h" -using namespace std; - -ClassImp(TRestReadoutChannel); -/////////////////////////////////////////////// -/// \brief TRestReadoutChannel default constructor -/// -TRestReadoutChannel::TRestReadoutChannel() { Initialize(); } - -/////////////////////////////////////////////// -/// \brief TRestReadoutChannel default destructor -/// -TRestReadoutChannel::~TRestReadoutChannel() {} - -/////////////////////////////////////////////// -/// \brief Initializes the channel members -/// -void TRestReadoutChannel::Initialize() { fDaqID = -1; } - -/////////////////////////////////////////////// -/// \brief Determines if (x,y) referenced to module coordinates is inside the -/// channel -/// -Int_t TRestReadoutChannel::isInside(Double_t x, Double_t y) { - for (unsigned int i = 0; i < fReadoutPixel.size(); i++) - if (fReadoutPixel[i].isInside(x, y)) return true; - return false; -} - -/////////////////////////////////////////////// -/// \brief Prints the details of the readout channel including pixel -/// coordinates. -/// -void TRestReadoutChannel::Print(int DetailLevel) { - if (DetailLevel >= 0) { - RESTMetadata << "++++ Channel : " << GetChannelId() << " Daq channel : " << GetDaqID() << RESTendl; - - string typestr; - if (GetType() == Channel_NoType) - typestr = "NoType"; - else if (GetType() == Channel_Pixel) - typestr = "Pixel"; - else if (GetType() == Channel_X) - typestr = "X"; - else if (GetType() == Channel_Y) - typestr = "Y"; - else if (GetType() == Channel_U) - typestr = "U"; - else if (GetType() == Channel_V) - typestr = "V"; - else if (GetType() == Channel_W) - typestr = "W"; - - RESTMetadata << " Total pixels : " << GetNumberOfPixels() << " Channel type : " << typestr - << RESTendl; - RESTMetadata << "+++++++++++++++++++++++++++++++++++++++++++++++++" << RESTendl; - - if (DetailLevel - 1 >= 0) - for (int n = 0; n < GetNumberOfPixels(); n++) { - fReadoutPixel[n].Print(); - } - } -} +#include "TRestReadoutChannel.h" \ No newline at end of file diff --git a/src/TRestReadoutMapping.cxx b/src/TRestReadoutMapping.cxx index 515766a..454a265 100644 --- a/src/TRestReadoutMapping.cxx +++ b/src/TRestReadoutMapping.cxx @@ -46,137 +46,4 @@ ///
/// -#include "TRestReadoutMapping.h" -using namespace std; - -ClassImp(TRestReadoutMapping) - /////////////////////////////////////////////// - /// \brief TRestReadoutMapping constructor - /// - TRestReadoutMapping::TRestReadoutMapping() {} - -/////////////////////////////////////////////// -/// \brief TRestReadoutMapping destructor -/// -TRestReadoutMapping::~TRestReadoutMapping() {} - -/////////////////////////////////////////////// -/// \brief Gets the X position of node (i,j) -/// -Double_t TRestReadoutMapping::GetX(Int_t nodeX) { return (fNetSizeX / fNodesX) * nodeX; } - -/////////////////////////////////////////////// -/// \brief Gets the Y position of node (i,j) -/// -Double_t TRestReadoutMapping::GetY(Int_t nodeY) { return (fNetSizeY / fNodesY) * nodeY; } - -/////////////////////////////////////////////// -/// \brief Gets the nodeX index corresponding to the x coordinate -/// -Int_t TRestReadoutMapping::GetNodeX(Double_t x) { - Int_t nX = (Int_t)((x / fNetSizeX) * fNodesX); - if (nX >= fNodesX) return fNodesX - 1; - return nX; -} - -/////////////////////////////////////////////// -/// \brief Gets the nodeY index corresponding to the y coordinate -/// -Int_t TRestReadoutMapping::GetNodeY(Double_t y) { - Int_t nY = (Int_t)((y / fNetSizeY) * fNodesY); - if (nY >= fNodesY) return fNodesY - 1; - return nY; -} - -/////////////////////////////////////////////// -/// \brief Gets the channel number corresponding to coordinates (x,y) -/// -Int_t TRestReadoutMapping::GetChannel(Double_t x, Double_t y) { return fChannel[GetNodeX(x)][GetNodeY(y)]; } - -/////////////////////////////////////////////// -/// \brief Gets the pixel number corresponding to coordinates (x,y) -/// -Int_t TRestReadoutMapping::GetPixel(Double_t x, Double_t y) { return fPixel[GetNodeX(x)][GetNodeY(y)]; } - -/////////////////////////////////////////////// -/// \brief Returns the number of nodes that have not been initialized. -/// -Int_t TRestReadoutMapping::GetNumberOfNodesNotSet() { - Int_t counter = 0; - for (int i = 0; i < fNodesX; i++) - for (int j = 0; j < fNodesY; j++) { - if (!isNodeSet(i, j)) counter++; - } - return counter; -} - -/////////////////////////////////////////////// -/// \brief Finds the node index in X for a given channel and pixel ids. -/// -Int_t TRestReadoutMapping::GetNodeX_ForChannelAndPixel(Int_t ch, Int_t px) { - for (int i = 0; i < fNodesX; i++) - for (int j = 0; j < fNodesY; j++) { - if (fChannel[i][j] == ch && fPixel[i][j] == px) return i; - } - return -1; -} - -/////////////////////////////////////////////// -/// \brief Finds the node index in Y for a given channel and pixel ids. -/// -Int_t TRestReadoutMapping::GetNodeY_ForChannelAndPixel(Int_t ch, Int_t px) { - for (int i = 0; i < fNodesX; i++) - for (int j = 0; j < fNodesY; j++) { - if (fChannel[i][j] == ch && fPixel[i][j] == px) return j; - } - return -1; -} - -/////////////////////////////////////////////// -/// \brief Resets the matrix values and allocates memory for the given net size. -/// -void TRestReadoutMapping::Initialize(Int_t nX, Int_t nY, Double_t sX, Double_t sY) { - fNodesX = nX; - fNodesY = nY; - fNetSizeX = sX; - fNetSizeY = sY; - fChannel.ResizeTo(fNodesX, fNodesY); - fPixel.ResizeTo(fNodesX, fNodesY); - - for (int i = 0; i < fNodesX; i++) - for (int j = 0; j < fNodesY; j++) { - fChannel[i][j] = -1; - fPixel[i][j] = -1; - } -} - -/////////////////////////////////////////////// -/// \brief Sets the readout channel and pixel corresponding to a mapping node -/// -void TRestReadoutMapping::SetNode(Int_t i, Int_t j, Int_t ch, Int_t pix) { - fChannel[i][j] = ch; - fPixel[i][j] = pix; -} - -/////////////////////////////////////////////// -/// \brief Checks if the node (i,j) is defined. -/// -Bool_t TRestReadoutMapping::isNodeSet(Int_t i, Int_t j) { - if (fChannel[i][j] == -1 || fPixel[i][j] == -1) return false; - return true; -} - -/////////////////////////////////////////////// -/// \brief Checks if all the nodes in the net have been defined. -/// -Bool_t TRestReadoutMapping::AllNodesSet() { - for (int i = 0; i < fNodesX; i++) - for (int j = 0; j < fNodesY; j++) { - if (!isNodeSet(i, j)) { - cout << "Node : " << i << " , " << j << " is NOT set. Ch : " << fChannel[i][j] - << " Pix : " << fPixel[i][j] << endl; - return false; - } - } - return true; -} +#include "TRestReadoutMapping.h" \ No newline at end of file diff --git a/src/TRestReadoutModule.cxx b/src/TRestReadoutModule.cxx index 4c29cfc..14b0979 100644 --- a/src/TRestReadoutModule.cxx +++ b/src/TRestReadoutModule.cxx @@ -42,437 +42,4 @@ ///
/// -#include "TRestReadoutModule.h" -using namespace std; - -ClassImp(TRestReadoutModule); -/////////////////////////////////////////////// -/// \brief Default TRestReadoutModule constructor -/// -TRestReadoutModule::TRestReadoutModule() { Initialize(); } - -/////////////////////////////////////////////// -/// \brief Default TRestReadoutModule destructor -/// -TRestReadoutModule::~TRestReadoutModule() {} - -/////////////////////////////////////////////// -/// \brief TRestReadoutModule initialization -/// -void TRestReadoutModule::Initialize() { - fReadoutChannel.clear(); - fModuleID = -1; - - fMapping = NULL; - - fModuleOriginX = 0; - fModuleOriginY = 0; - - fModuleSizeX = 0; - fModuleSizeY = 0; - - fModuleRotation = 0; - - fMaximumDaqId = -1; - fMininimumDaqId = -1; - - fTolerance = 1.e-6; - - showWarnings = false; -} - -/////////////////////////////////////////////// -/// \brief Initializes the max and min values for the daq channel number -/// -void TRestReadoutModule::SetMinMaxDaqIDs() { - Int_t maxID = GetChannel(0)->GetDaqID(); - Int_t minID = GetChannel(0)->GetDaqID(); - for (int ch = 0; ch < this->GetNumberOfChannels(); ch++) { - Int_t daqID = GetChannel(ch)->GetDaqID(); - if (daqID > maxID) maxID = daqID; - - if (daqID < minID) minID = daqID; - } - - fMaximumDaqId = maxID; - fMininimumDaqId = minID; -} - -/////////////////////////////////////////////// -/// \brief Determines if a given *daqID* number is in the range of the module -/// -Bool_t TRestReadoutModule::isDaqIDInside(Int_t daqID) { - if (daqID >= fMininimumDaqId && daqID <= fMaximumDaqId) return true; - return false; -} - -/////////////////////////////////////////////// -/// \brief Returns the channel index corresponding to the absolute coordinates, -/// i.e, relative to the readout plane coordinate system -/// -/// The readout mapping (see TRestReadoutMapping) is used to help finding -/// the pixel where coordinates absX and absY fall in. -/// -Int_t TRestReadoutModule::FindChannel(Double_t absX, Double_t absY) { - if (!isInside(absX, absY)) return -1; - - Double_t x = TransformToModuleCoordinates(absX, absY).X(); - Double_t y = TransformToModuleCoordinates(absX, absY).Y(); - - Int_t nodeX = fMapping->GetNodeX(x); - Int_t nodeY = fMapping->GetNodeY(y); - - Int_t channel = fMapping->GetChannelByNode(nodeX, nodeY); - Int_t pixel = fMapping->GetPixelByNode(nodeX, nodeY); - - Int_t repeat = 1; - Int_t count = 0; - Int_t forward = 1; - Int_t xAxis = 1; - - Int_t totalNodes = fMapping->GetNumberOfNodesX() * fMapping->GetNumberOfNodesY(); - - // We test if x,y is inside the channel/pixel obtained from the readout - // mapping If not we start to look in the readout mapping neighbours - while (!this->isInsidePixel(channel, pixel, absX, absY)) { - count++; - if (xAxis == 1 && forward == 1) - nodeX++; - else if (xAxis == 0 && forward == 1) - nodeY++; - else if (xAxis == 1 && forward == 0) - nodeX--; - else if (xAxis == 0 && forward == 0) - nodeY--; - - Int_t nNodes = fMapping->GetNumberOfNodesX(); - - if (nodeX < 0) nodeX = nNodes - 1; - if (nodeY < 0) nodeY = nNodes - 1; - if (nodeX >= nNodes) nodeX = 0; - if (nodeY >= nNodes) nodeY = 0; - - if (count >= repeat) { - if (xAxis == 1 && forward == 1) { - xAxis = 0; - forward = 0; - } else if (xAxis == 0 && forward == 0) { - xAxis = 1; - forward = 0; - repeat++; - } else if (xAxis == 1 && forward == 0) { - xAxis = 0; - forward = 1; - } else if (xAxis == 0 && forward == 1) { - xAxis = 1; - forward = 1; - repeat++; - } - - count = 0; - } - - channel = fMapping->GetChannelByNode(nodeX, nodeY); - pixel = fMapping->GetPixelByNode(nodeX, nodeY); - - if (count > totalNodes / 10) { - cout << "REST Error? I did not find any channel for hit position (" << x << "," << y << ")" - << endl; - - for (int ch = 0; ch < GetNumberOfChannels(); ch++) - for (int px = 0; px < GetChannel(ch)->GetNumberOfPixels(); px++) - if (isInsidePixel(ch, px, absX, absX)) { - cout << "( " << x << " , " << y << ") Should be in channel " << ch - << " pixel : " << px << endl; - - cout << "Corresponding node : nX: " << fMapping->GetNodeX_ForChannelAndPixel(ch, px) - << " nY : " << fMapping->GetNodeY_ForChannelAndPixel(ch, px) << endl; - cout << "Channel : " << ch << " Pixel : " << px << endl; - cout << "Pix X : " << GetChannel(ch)->GetPixel(px)->GetCenter().X() - << " Pix Y : " << GetChannel(ch)->GetPixel(px)->GetCenter().Y() << endl; - } - sleep(5); - // getchar(); - return -1; - } - } - - return channel; -} - -/////////////////////////////////////////////// -/// \brief Determines if the position *x,y* (in readout plane coordinate) relative to the readout -/// plane are inside this readout module. -/// -Bool_t TRestReadoutModule::isInside(Double_t x, Double_t y) { - TVector2 v(x, y); - return isInside(v); -} - -/////////////////////////////////////////////// -/// \brief Determines if the position TVector2 *pos* (in readout plane coordinate) relative to the readout -/// plane are inside this readout module. -/// -Bool_t TRestReadoutModule::isInside(TVector2 pos) { - TVector2 rotPos = TransformToModuleCoordinates(pos); - - if (rotPos.X() >= 0 && rotPos.X() < fModuleSizeX) - if (rotPos.Y() >= 0 && rotPos.Y() < fModuleSizeY) return true; - - return false; -} - -/////////////////////////////////////////////// -/// \brief Determines if the position *x,y* (in readout plane coordinate) is found in any of the pixels -/// of the readout *channel* index given. -/// -Bool_t TRestReadoutModule::isInsideChannel(Int_t channel, Double_t x, Double_t y) { - TVector2 pos(x, y); - - return isInsideChannel(channel, pos); -} - -/////////////////////////////////////////////// -/// \brief Determines if the position TVector2 *pos* (in readout plane coordinate) is found in any of the -/// pixels of the readout *channel* index given. -/// -Bool_t TRestReadoutModule::isInsideChannel(Int_t channel, TVector2 pos) { - pos = TransformToModuleCoordinates(pos); - for (int idx = 0; idx < GetChannel(channel)->GetNumberOfPixels(); idx++) - if (GetChannel(channel)->GetPixel(idx)->isInside(pos)) return true; - return false; -} - -/////////////////////////////////////////////// -/// \brief Determines if the position *x,y* (in readout plane coordinate) is found at a specific *pixel* id -/// inside the readout *channel* given. -/// -Bool_t TRestReadoutModule::isInsidePixel(Int_t channel, Int_t pixel, Double_t x, Double_t y) { - TVector2 pos(x, y); - - if (channel < 0 || pixel < 0) return false; - - return isInsidePixel(channel, pixel, pos); -} - -/////////////////////////////////////////////// -/// \brief Determines if the position TVector2 *pos* (in readout plane coordinate) is found at a specific -/// *pixel* id inside the readout *channel* given. -/// -Bool_t TRestReadoutModule::isInsidePixel(Int_t channel, Int_t pixel, TVector2 pos) { - if (channel < 0 || pixel < 0) return false; - - pos = TransformToModuleCoordinates(pos); - if (GetChannel(channel)->GetPixel(pixel)->isInside(pos)) return true; - return false; -} - -/////////////////////////////////////////////// -/// \brief Determines if the position *x,y* (relative to module coordinate) is found at a specific *pixel* id -/// inside the readout *channel* given. -/// -Bool_t TRestReadoutModule::isInsidePixelRelative(Int_t channel, Int_t pixel, Double_t x, Double_t y) { - TVector2 pos(x, y); - - if (channel < 0 || pixel < 0) return false; - - return isInsidePixelRelative(channel, pixel, pos); -} - -/////////////////////////////////////////////// -/// \brief Determines if the position TVector2 *pos* (relative to module coordinate) is found at a specific -/// *pixel* id inside the readout *channel* given. -/// -Bool_t TRestReadoutModule::isInsidePixelRelative(Int_t channel, Int_t pixel, TVector2 pos) { - if (channel < 0 || pixel < 0) return false; - - if (GetChannel(channel)->GetPixel(pixel)->isInside(pos)) return true; - return false; -} - -/////////////////////////////////////////////// -/// \brief Creates a TVector2 with shortest norm going from the given position -/// *pos* to the module. -/// It can be seen as the vector to add to move from the position to the -/// closest border of the module. -/// -TVector2 TRestReadoutModule::GetDistanceToModule(TVector2 pos) { - TVector2 newPos = TransformToModuleCoordinates(pos); - - Double_t dx = 0, dy = 0; - if (newPos.X() < 0) - dx = -newPos.X(); - else if (fModuleSizeX - newPos.X() < 0) - dx = fModuleSizeX - newPos.X(); - - if (newPos.Y() < 0) - dy = -newPos.Y(); - else if (fModuleSizeY - newPos.Y() < 0) - dy = fModuleSizeY - newPos.Y(); - - TVector2 dist = TVector2(dx, dy); - return dist; -} -/////////////////////////////////////////////// -/// \brief Returns the pixel origin (left-bottom) position for a given *channel* -/// and *pixel* indexes. -/// -TVector2 TRestReadoutModule::GetPixelOrigin(Int_t channel, Int_t pixel) { - return GetPixelVertex(channel, pixel, 0); -} - -/////////////////////////////////////////////// -/// \brief Returns any of the pixel vertex position for a given *channel* and -/// *pixel* indexes. -/// -/// \param vertex A value between 0-3 definning the vertex position to be -/// returned -/// -TVector2 TRestReadoutModule::GetPixelVertex(Int_t channel, Int_t pixel, Int_t vertex) { - TVector2 pixPosition = GetChannel(channel)->GetPixel(pixel)->GetVertex(vertex); - - pixPosition = pixPosition.Rotate(fModuleRotation * TMath::Pi() / 180.); - pixPosition = pixPosition + TVector2(fModuleOriginX, fModuleOriginY); - return pixPosition; -} - -/////////////////////////////////////////////// -/// \brief Returns the center pixel position for a given *channel* and -/// *pixel* indexes. -/// -/// \param vertex A value between 0-3 definning the vertex position to be -/// returned -/// -TVector2 TRestReadoutModule::GetPixelCenter(Int_t channel, Int_t pixel) { - TVector2 pixCenter = GetChannel(channel)->GetPixel(pixel)->GetCenter(); - - pixCenter = pixCenter.Rotate(fModuleRotation * TMath::Pi() / 180.); - pixCenter = pixCenter + TVector2(fModuleOriginX, fModuleOriginY); - return pixCenter; -} - -/////////////////////////////////////////////// -/// \brief Returns the pixel type for a given *channel* and -/// *pixel* indexes. -/// -/// \param vertex A boolean that is true if the pixel is triangular, false -/// otherwise -/// -Bool_t TRestReadoutModule::GetPixelTriangle(Int_t channel, Int_t pixel) { - Bool_t type = GetChannel(channel)->GetPixel(pixel)->GetTriangle(); - - return type; -} - -TVector2 TRestReadoutModule::GetPixelOrigin(TRestReadoutPixel* pix) { return GetPixelVertex(pix, 0); } - -TVector2 TRestReadoutModule::GetPixelVertex(TRestReadoutPixel* pix, Int_t vertex) { - TVector2 pixPosition = pix->GetVertex(vertex); - pixPosition = pixPosition.Rotate(fModuleRotation * TMath::Pi() / 180.); - pixPosition = pixPosition + TVector2(fModuleOriginX, fModuleOriginY); - return pixPosition; -} - -TVector2 TRestReadoutModule::GetPixelCenter(TRestReadoutPixel* pix) { - TVector2 corner1(GetPixelVertex(pix, 0)); - TVector2 corner2(GetPixelVertex(pix, 2)); - TVector2 center = (corner1 + corner2) / 2.; - return center; -} - -Bool_t TRestReadoutModule::GetPixelTriangle(TRestReadoutPixel* pix) { return pix->GetTriangle(); } - -/////////////////////////////////////////////// -/// \brief Returns the coordinates of the specified vertex index *n*. The -/// physical coordinates relative to the readout plane are returned, including -/// rotation. -/// -/// \param n A value between 0-3 definning the vertex position to be returned -/// -TVector2 TRestReadoutModule::GetVertex(int n) const { - TVector2 vertex(0, 0); - TVector2 origin(fModuleOriginX, fModuleOriginY); - - if (n % 4 == 0) - return origin; - else if (n % 4 == 1) { - vertex.Set(fModuleSizeX, 0); - vertex = vertex.Rotate(fModuleRotation * TMath::Pi() / 180.); - - vertex = vertex + origin; - } else if (n % 4 == 2) { - vertex.Set(fModuleSizeX, fModuleSizeY); - vertex = vertex.Rotate(fModuleRotation * TMath::Pi() / 180.); - - vertex = vertex + origin; - } else if (n % 4 == 3) { - vertex.Set(0, fModuleSizeY); - vertex = vertex.Rotate(fModuleRotation * TMath::Pi() / 180.); - - vertex = vertex + origin; - } - return vertex; -} - -/////////////////////////////////////////////// -/// \brief Adds a new channel to the module -/// -void TRestReadoutModule::AddChannel(TRestReadoutChannel& rChannel) { - for (int i = 0; i < rChannel.GetNumberOfPixels(); i++) { - // TODO we expect here that the user will only do pixel rotations between 0 - // and 90 degrees, we must force that on pixel definition or fix it here - Double_t oX = rChannel.GetPixel(i)->GetVertex(3).X(); - Double_t oY = rChannel.GetPixel(i)->GetVertex(3).Y(); - Double_t sX = rChannel.GetPixel(i)->GetVertex(1).X(); - Double_t sY = rChannel.GetPixel(i)->GetVertex(1).Y(); - - if (oX + fTolerance < 0 || oY + fTolerance < 0 || sX - fTolerance > fModuleSizeX || - sY - fTolerance > fModuleSizeY) { - if (showWarnings) { - cout << "REST Warning (AddChannel) pixel outside the module boundaries" << endl; - cout << "Channel: " << fReadoutChannel.size() << ", Pixel : " << i << endl; - cout << "Pixel origin = (" << oX << " , " << oY << ")" << endl; - cout << "Pixel size = (" << sX << " , " << sY << ")" << endl; - cout << "Module size = (" << fModuleSizeX << " , " << fModuleSizeY << ")" << endl; - } - } - } - - fReadoutChannel.push_back(rChannel); -} - -/////////////////////////////////////////////// -/// \brief Not implemented -/// -void TRestReadoutModule::Draw() {} - -/////////////////////////////////////////////// -/// \brief Prints the module details and channels if *fullDetail* is enabled. -/// -void TRestReadoutModule::Print(Int_t DetailLevel) { - if (DetailLevel >= 0) { - RESTMetadata << "-- Readout module : " << GetModuleID() << RESTendl; - RESTMetadata << "----------------------------------------------------------------" << RESTendl; - RESTMetadata << "-- Origin position : X = " << fModuleOriginX << " mm " - << " Y : " << fModuleOriginY << " mm" << RESTendl; - RESTMetadata << "-- Size : X = " << fModuleSizeX << " Y : " << fModuleSizeY << RESTendl; - RESTMetadata << "-- Rotation : " << fModuleRotation << " degrees" << RESTendl; - RESTMetadata << "-- Total channels : " << GetNumberOfChannels() << RESTendl; - RESTMetadata << "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++" << RESTendl; - - for (int n = 0; n < GetNumberOfChannels(); n++) fReadoutChannel[n].Print(DetailLevel - 1); - } -} - -void TRestReadoutModule::PrintDecoding() { - cout << "daqChannel\tphysicalChannel" << endl; - - map channelmap; - for (int i = 0; i < GetNumberOfChannels(); i++) { - TRestReadoutChannel* chn = &fReadoutChannel[i]; - channelmap[chn->GetDaqID()] = i; - } - for (auto iter : channelmap) { - cout << iter.first << "\t" << iter.second << endl; - } -} \ No newline at end of file +#include "TRestReadoutModule.h" \ No newline at end of file diff --git a/src/TRestReadoutPixel.cxx b/src/TRestReadoutPixel.cxx index 8623e07..66d37a6 100644 --- a/src/TRestReadoutPixel.cxx +++ b/src/TRestReadoutPixel.cxx @@ -41,125 +41,4 @@ ///
/// -double delta = 1.e-6; - -#include "TRestReadoutPixel.h" -using namespace std; - -ClassImp(TRestReadoutPixel); -/////////////////////////////////////////////// -/// \brief TRestReadoutPixel default constructor -/// -TRestReadoutPixel::TRestReadoutPixel() { Initialize(); } - -/////////////////////////////////////////////// -/// \brief TRestReadoutPixel default destructor -/// -TRestReadoutPixel::~TRestReadoutPixel() {} - -/////////////////////////////////////////////// -/// \brief Initializes the pixel members -/// -void TRestReadoutPixel::Initialize() {} - -/////////////////////////////////////////////// -/// \brief Returns the center TVector2 position of the pixel -/// -TVector2 TRestReadoutPixel::GetCenter() const { - TVector2 center(0, 0); - TVector2 origin(fPixelOriginX, fPixelOriginY); - TVector2 opositeVertex = GetVertex(2); - - if (fTriangle) - center = (opositeVertex - origin) / 4. + origin; - else - center = (origin + opositeVertex) / 2.; - - return center; - //*/ -} - -/////////////////////////////////////////////// -/// \brief Returns the specified pixel vertex position -/// -/// \param n A value between 0-3 definning the vertex position to be returned. -/// -TVector2 TRestReadoutPixel::GetVertex(int n) const { - TVector2 vertex(0, 0); - TVector2 origin(fPixelOriginX, fPixelOriginY); - - if (n % 4 == 0) - return origin; - else if (n % 4 == 1) { - vertex.Set(fPixelSizeX, 0); - vertex = vertex.Rotate(fRotation * TMath::Pi() / 180.); - - vertex = vertex + origin; - } else if (n % 4 == 2) { - vertex.Set(fPixelSizeX, fPixelSizeY); - vertex = vertex.Rotate(fRotation * TMath::Pi() / 180.); - - vertex = vertex + origin; - } else if (n % 4 == 3) { - vertex.Set(0, fPixelSizeY); - vertex = vertex.Rotate(fRotation * TMath::Pi() / 180.); - - vertex = vertex + origin; - } - return vertex; -} - -/////////////////////////////////////////////// -/// \brief Determines if a given *x,y* coordinates are found inside the pixel. -/// The coordinates are referenced to the readout module system. -/// -Bool_t TRestReadoutPixel::isInside(Double_t x, Double_t y) { - TVector2 pos(x, y); - return isInside(pos); -} - -/////////////////////////////////////////////// -/// \brief Determines if a given TVector2 *pos* coordinates are found inside -/// the pixel. The coordinates are referenced to the readout module system. -/// -Bool_t TRestReadoutPixel::isInside(TVector2 pos) { - pos = TransformToPixelCoordinates(pos); - Double_t const x = pos.X(); - if (pos.X() >= -delta && pos.X() <= fPixelSizeX + delta) // Condition on X untouched - { - if (fTriangle && pos.Y() >= -delta && - pos.Y() <= fPixelSizeY + delta - - x * (fPixelSizeY / fPixelSizeX)) // if triangle, third condition depends on x - return true; - if (!fTriangle && pos.Y() >= -delta && - pos.Y() <= fPixelSizeY + delta) // for a normal rectangular pixel, same - // simple conditions - return true; - } - return false; -} - -/////////////////////////////////////////////// -/// \brief Transforms the coordinates given in a TVector2 to the internal -/// pixel coordinate system. The coordinates are referenced to the readout -/// module system. -/// -TVector2 TRestReadoutPixel::TransformToPixelCoordinates(TVector2 p) { - TVector2 pos(p.X() - fPixelOriginX, p.Y() - fPixelOriginY); - pos = pos.Rotate(-fRotation * TMath::Pi() / 180.); - return pos; -} - -/////////////////////////////////////////////// -/// \brief Prints on screen the pixel details, origin, size, rotation -/// -void TRestReadoutPixel::Print() { - RESTMetadata << " ## Pixel position : (" << GetOriginX() << "," << GetOriginY() << ") mm size : (" - << GetSizeX() << "," << GetSizeY() << ") mm" << RESTendl; - RESTMetadata << " rotation : " << fRotation << " degrees" - << " type : "; - if (fTriangle) - RESTMetadata << "triangle" << RESTendl; - else - RESTMetadata << "rectangle" << RESTendl; -} +#include "TRestReadoutPixel.h" \ No newline at end of file diff --git a/src/TRestReadoutPlane.cxx b/src/TRestReadoutPlane.cxx index 5fdc975..06bdd8b 100644 --- a/src/TRestReadoutPlane.cxx +++ b/src/TRestReadoutPlane.cxx @@ -42,409 +42,4 @@ ///
/// -#include "TRestReadoutPlane.h" -using namespace std; - -ClassImp(TRestReadoutPlane); -/////////////////////////////////////////////// -/// \brief Default TRestReadoutPlane constructor -/// -TRestReadoutPlane::TRestReadoutPlane() { Initialize(); } - -/////////////////////////////////////////////// -/// \brief Default TRestReadoutPlane destructor -/// -TRestReadoutPlane::~TRestReadoutPlane() {} - -/////////////////////////////////////////////// -/// \brief TRestReadoutPlane initialization -/// -void TRestReadoutPlane::Initialize() { - fCathodePosition = TVector3(0, 0, 0); - fPosition = TVector3(0, 0, 0); - fPlaneVector = TVector3(0, 0, 0); - - fNModules = 0; - fReadoutModules.clear(); -} - -/////////////////////////////////////////////// -/// \brief Returns the total number of channels in the readout plane -/// -Int_t TRestReadoutPlane::GetNumberOfChannels() { - Int_t nChannels = 0; - for (int md = 0; md < GetNumberOfModules(); md++) nChannels += fReadoutModules[md].GetNumberOfChannels(); - return nChannels; -} - -/////////////////////////////////////////////// -/// \brief Calculates the drift distance between readout plane and cathode -/// -void TRestReadoutPlane::SetDriftDistance() { - Double_t tDriftDistance = this->GetDistanceTo(this->GetCathodePosition()); - this->SetTotalDriftDistance(tDriftDistance); -} - -/////////////////////////////////////////////// -/// \brief Returns a pointer to a module using its internal module id -/// -TRestReadoutModule* TRestReadoutPlane::GetModuleByID(Int_t modID) { - for (int md = 0; md < GetNumberOfModules(); md++) - if (fReadoutModules[md].GetModuleID() == modID) return &fReadoutModules[md]; - - cout << "REST ERROR (GetReadoutModuleByID) : Module ID : " << modID << " was not found" << endl; - return NULL; -} - -/////////////////////////////////////////////// -/// \brief Returns the X coordinate of a given channel in a given module using -/// their internal module and channel ids. -/// -/// This method evaluates if the channel is a strip or a pixel. If it is a -/// strip and the X-axis is not localized, this function returns NaN. -/// -/// \param modID Internal module id. As defined on the readout. -/// \param chID Internal channel id. As defined on the readout. -/// -/// \return The value of the X-coordinate relative to the readout position -Double_t TRestReadoutPlane::GetX(Int_t modID, Int_t chID) { - TRestReadoutModule* rModule = GetModuleByID(modID); - Double_t xOrigin = rModule->GetModuleOriginX(); - - TRestReadoutChannel* rChannel = rModule->GetChannel(chID); - - Double_t x = numeric_limits::quiet_NaN(); - - if (rChannel->GetNumberOfPixels() == 1) { - Double_t sX = rChannel->GetPixel(0)->GetSize().X(); - Double_t sY = rChannel->GetPixel(0)->GetSize().Y(); - - if (sX > 2 * sY) return x; - - x = rModule->GetPixelCenter(chID, 0).X(); - - return x; - } - - if (rChannel->GetNumberOfPixels() > 1) { - Int_t nPix = rChannel->GetNumberOfPixels(); - - // We check the origin of consecutive pixels to check if it goes X or Y - // direction. Perhaps more complex readouts need some changes here - Double_t x1 = rChannel->GetPixel(0)->GetCenter().X(); - Double_t x2 = rChannel->GetPixel(nPix - 1)->GetCenter().X(); - - Double_t y1 = rChannel->GetPixel(0)->GetCenter().Y(); - Double_t y2 = rChannel->GetPixel(nPix - 1)->GetCenter().Y(); - - /* - cout << "Pixel 0. X : " << x1 << " Y : " << y1 endl; - cout << "Pixel N. X : " << x2 << " Y : " << y2 endl; - */ - - Double_t deltaX = abs(x2 - x1); - Double_t deltaY = abs(y2 - y1); - - Int_t rotation = (Int_t)rModule->GetModuleRotation(); - if (rotation % 90 == 0) { - if (rotation / 90 % 2 == 0) // rotation is 0, 180, 360... - { - if (deltaY > deltaX) x = rModule->GetPixelCenter(chID, 0).X(); - } else // rotation is 90, 270... We need to invert x and y - { - if (deltaY < deltaX) x = rModule->GetPixelCenter(chID, 0).X(); - } - } else { - // we choose to ouput x only when deltaY > deltaX under non-90 rotation - // otherwise it is a y channel and should return nan - if (deltaY > deltaX) x = rModule->GetPixelCenter(chID, 0).X(); - } - } - - return x; -} - -/////////////////////////////////////////////// -/// \brief Returns the Y coordinate of a given channel in a given module using -/// their internal module and channel ids. -/// -/// This method evaluates if the channel is a strip or a pixel. If it is a -/// strip and the Y-axis is not localized, this function returns NaN. -/// -/// \param modID Internal module id. As defined on the readout. -/// \param chID Internal channel id. As defined on the readout. -/// -/// \return The value of the X-coordinate relative to the readout position -Double_t TRestReadoutPlane::GetY(Int_t modID, Int_t chID) { - TRestReadoutModule* rModule = GetModuleByID(modID); - Double_t yOrigin = rModule->GetModuleOriginY(); - - TRestReadoutChannel* rChannel = rModule->GetChannel(chID); - - Double_t y = numeric_limits::quiet_NaN(); - - if (rChannel->GetNumberOfPixels() == 1) { - Double_t sX = rChannel->GetPixel(0)->GetSize().X(); - Double_t sY = rChannel->GetPixel(0)->GetSize().Y(); - - if (sY > 2 * sX) return y; - - y = rModule->GetPixelCenter(chID, 0).Y(); - - return y; - } - - if (rChannel->GetNumberOfPixels() > 1) { - Int_t nPix = rChannel->GetNumberOfPixels(); - - // We check the origin of consecutive pixels to check if it goes X or Y - // direction. Perhaps more complex readouts need some changes here - Double_t x1 = rChannel->GetPixel(0)->GetCenter().X(); - Double_t x2 = rChannel->GetPixel(nPix - 1)->GetCenter().X(); - - Double_t y1 = rChannel->GetPixel(0)->GetCenter().Y(); - Double_t y2 = rChannel->GetPixel(nPix - 1)->GetCenter().Y(); - - /* - cout << "Pix id : " << rChannel->GetPixel(0)->GetID() << " X1 : " << x1 - << endl; cout << "Pix id : " << rChannel->GetPixel(1)->GetID() << " X2 : - " << x2 << endl; cout << "Pix id : " << rChannel->GetPixel(0)->GetID() << - " Y1 : " << y1 << endl; cout << "Pix id : " << - rChannel->GetPixel(1)->GetID() << " Y2 : " << y2 << endl; - */ - - Double_t deltaX = abs(x2 - x1); - Double_t deltaY = abs(y2 - y1); - - Int_t rotation = (Int_t)rModule->GetModuleRotation(); - if (rotation % 90 == 0) { - if (rotation / 90 % 2 == 0) // rotation is 0, 180, 360... - { - if (deltaY < deltaX) y = rModule->GetPixelCenter(chID, 0).Y(); - } else // rotation is 90, 270... We need to invert x and y - { - if (deltaY > deltaX) y = rModule->GetPixelCenter(chID, 0).Y(); - } - } else { - // we choose to ouput y only when deltaY < deltaX under non-90 rotation - // otherwise it is a x channel and should return nan - if (deltaY < deltaX) y = rModule->GetPixelCenter(chID, 0).Y(); - } - } - - return y; -} - -/////////////////////////////////////////////// -/// \brief Finds the readout channel index for a given module stored in a given -/// module index stored in the readout plane (internal readout plane module id). -/// -/// \param absX It is the x absolut physical position -/// \param absY It is the y absolut physical position -/// \return The corresponding channel id -Int_t TRestReadoutPlane::FindChannel(Int_t module, Double_t absX, Double_t absY) { - Double_t modX = absX - fPosition.X(); - Double_t modY = absY - fPosition.Y(); - - // TODO : check first if (modX,modY) is inside the module. - // If not return error. - // FindChannel will take a long time to search for the channel if it is not - // there. It will be faster - - return fReadoutModules[module].FindChannel(modX, modY); -} - -/////////////////////////////////////////////// -/// \brief Returns the perpendicular distance to the readout plane of a given -/// *x*, *y*, *z* position -/// -Double_t TRestReadoutPlane::GetDistanceTo(Double_t x, Double_t y, Double_t z) { - return GetDistanceTo(TVector3(x, y, z)); -} - -/////////////////////////////////////////////// -/// \brief Returns the perpendicular distance to the readout plane of a given -/// TVector3 position -/// -Double_t TRestReadoutPlane::GetDistanceTo(TVector3 pos) { - return (pos - GetPosition()).Dot(GetPlaneVector()); -} - -/////////////////////////////////////////////// -/// \brief This method determines if a given position in *z* is inside the drift -/// volume drifting distance for this readout plane. -/// -/// \return 1 if the Z-position is found inside the drift volume definition. 0 -/// otherwise returns -1. -/// -Int_t TRestReadoutPlane::isZInsideDriftVolume(Double_t z) { - TVector3 pos = TVector3(0, 0, z); - - return isZInsideDriftVolume(pos); -} - -/////////////////////////////////////////////// -/// \brief This method determines if the daqId given is associated to any of the -/// readout readout channels in any readout modules. -/// -/// \return true if daqId is found -/// returns false if daqId is not found -/// -Bool_t TRestReadoutPlane::isDaqIDInside(Int_t daqId) { - for (int m = 0; m < GetNumberOfModules(); m++) - if (fReadoutModules[m].isDaqIDInside(daqId)) return true; - - return false; -} - -/////////////////////////////////////////////// -/// \brief This method determines if the z-coordinate is inside the drift volume -/// for this readout plane. -/// -/// \param pos A TVector3 definning the position. -/// -/// \return 1 if the Z-position is found inside the drift volume definition. 0 -/// otherwise -/// -Int_t TRestReadoutPlane::isZInsideDriftVolume(TVector3 pos) { - TVector3 posNew = TVector3(pos.X() - fPosition.X(), pos.Y() - fPosition.Y(), pos.Z()); - - Double_t distance = GetDistanceTo(posNew); - - if (distance > 0 && distance < fTotalDriftDistance) return 1; - - return 0; -} - -/////////////////////////////////////////////// -/// \brief This method returns the module id where the hits with coordinates -/// (x,y,z) is found. The z-coordinate must be found in between the cathode and -/// the readout plane. The *x* and *y* values must be found inside one of the -/// readout modules defined inside the readout plane. -/// -/// \param x,y,z Three Double_t definning the position. -/// -/// \return the module *id* where the hit is found. If no module *id* is found -/// it returns -1. -/// -Int_t TRestReadoutPlane::GetModuleIDFromPosition(Double_t x, Double_t y, Double_t z) { - TVector3 pos = TVector3(x, y, z); - - return GetModuleIDFromPosition(pos); -} -/////////////////////////////////////////////// -/// \brief This method returns the module id where *pos* is found. -/// The z-coordinate must be found in between -/// the cathode and the readout plane. The *x* and *y* values must be found -/// inside one of the readout modules defined inside the readout plane. -/// -/// \param pos A TVector3 definning the position. -/// -/// \return the module *id* where the hit is found. If no module *id* is found -/// it returns -1. -/// -Int_t TRestReadoutPlane::GetModuleIDFromPosition(TVector3 pos) { - TVector3 posNew = TVector3(pos.X() - fPosition.X(), pos.Y() - fPosition.Y(), pos.Z()); - - Double_t distance = GetDistanceTo(posNew); - - if (distance > 0 && distance < fTotalDriftDistance) { - for (int m = 0; m < GetNumberOfModules(); m++) - if (fReadoutModules[m].isInside(posNew.X(), posNew.Y())) return fReadoutModules[m].GetModuleID(); - } - - return -1; -} - -/////////////////////////////////////////////// -/// \brief Prints information with details of the readout plane and modules -/// defined inside the readout plane. -/// -void TRestReadoutPlane::Print(Int_t DetailLevel) { - if (DetailLevel >= 0) { - RESTMetadata << "-- Readout plane : " << GetID() << RESTendl; - RESTMetadata << "----------------------------------------------------------------" << RESTendl; - RESTMetadata << "-- Position : X = " << fPosition.X() << " mm, " - << " Y : " << fPosition.Y() << " mm, Z : " << fPosition.Z() << " mm" << RESTendl; - RESTMetadata << "-- Vector : X = " << fPlaneVector.X() << " mm, " - << " Y : " << fPlaneVector.Y() << " mm, Z : " << fPlaneVector.Z() << " mm" << RESTendl; - RESTMetadata << "-- Cathode Position : X = " << fCathodePosition.X() << " mm, " - << " Y : " << fCathodePosition.Y() << " mm, Z : " << fCathodePosition.Z() << " mm" - << RESTendl; - RESTMetadata << "-- Total drift distance : " << fTotalDriftDistance << " mm" << RESTendl; - RESTMetadata << "-- Charge collection : " << fChargeCollection << RESTendl; - RESTMetadata << "-- Total modules : " << GetNumberOfModules() << RESTendl; - RESTMetadata << "-- Total channels : " << GetNumberOfChannels() << RESTendl; - RESTMetadata << "----------------------------------------------------------------" << RESTendl; - - for (int i = 0; i < GetNumberOfModules(); i++) fReadoutModules[i].Print(DetailLevel - 1); - } -} - -/////////////////////////////////////////////// -/// \brief Draws the readout plane using GetReadoutHistogram. -/// -void TRestReadoutPlane::Draw() { this->GetReadoutHistogram()->Draw(); } - -/////////////////////////////////////////////// -/// \brief Creates and resturns a TH2Poly object with the -/// readout pixel description. -/// -TH2Poly* TRestReadoutPlane::GetReadoutHistogram() { - Double_t x[4]; - Double_t y[4]; - - double xmin, xmax, ymin, ymax; - - GetBoundaries(xmin, xmax, ymin, ymax); - - TH2Poly* readoutHistogram = new TH2Poly("ReadoutHistogram", "ReadoutHistogram", xmin, xmax, ymin, ymax); - - for (int mdID = 0; mdID < this->GetNumberOfModules(); mdID++) { - TRestReadoutModule* module = &fReadoutModules[mdID]; - - int nChannels = module->GetNumberOfChannels(); - - for (int ch = 0; ch < nChannels; ch++) { - TRestReadoutChannel* channel = module->GetChannel(ch); - Int_t nPixels = channel->GetNumberOfPixels(); - - for (int px = 0; px < nPixels; px++) { - for (int v = 0; v < 4; v++) { - x[v] = module->GetPixelVertex(ch, px, v).X(); - y[v] = module->GetPixelVertex(ch, px, v).Y(); - } - - readoutHistogram->AddBin(4, x, y); - } - } - } - - readoutHistogram->SetStats(0); - - return readoutHistogram; -} - -/////////////////////////////////////////////// -/// \brief Finds the xy boundaries of the readout plane delimited by the modules -/// -void TRestReadoutPlane::GetBoundaries(double& xmin, double& xmax, double& ymin, double& ymax) { - Double_t x[4]; - Double_t y[4]; - - xmin = 1E9, xmax = -1E9, ymin = 1E9, ymax = -1E9; - - for (int mdID = 0; mdID < this->GetNumberOfModules(); mdID++) { - TRestReadoutModule* module = &fReadoutModules[mdID]; - - for (int v = 0; v < 4; v++) { - x[v] = module->GetVertex(v).X(); - y[v] = module->GetVertex(v).Y(); - - if (x[v] < xmin) xmin = x[v]; - if (y[v] < ymin) ymin = y[v]; - if (x[v] > xmax) xmax = x[v]; - if (y[v] > ymax) ymax = y[v]; - } - } -} +#include "TRestReadoutPlane.h" \ No newline at end of file From 8d991ad3823c3c64b60fbc1266e616edefebda1b Mon Sep 17 00:00:00 2001 From: nkx Date: Sun, 26 Jun 2022 18:25:05 +0800 Subject: [PATCH 3/4] removed TRestGas class since it causes seg.fault --- inc/TRestGas.h | 8 -------- src/TRestGas.cxx | 1 - 2 files changed, 9 deletions(-) delete mode 100644 inc/TRestGas.h delete mode 100644 src/TRestGas.cxx diff --git a/inc/TRestGas.h b/inc/TRestGas.h deleted file mode 100644 index bfe4781..0000000 --- a/inc/TRestGas.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef RestCore_TRestGas -#define RestCore_TRestGas - -#include "TRestDetectorGas.h" - -typedef TRestDetectorGas TRestGas; - -#endif \ No newline at end of file diff --git a/src/TRestGas.cxx b/src/TRestGas.cxx deleted file mode 100644 index 1fe460d..0000000 --- a/src/TRestGas.cxx +++ /dev/null @@ -1 +0,0 @@ -#include "TRestGas.h" \ No newline at end of file From 959f33b28dc41d7f11f5aad58313c7e539c991d9 Mon Sep 17 00:00:00 2001 From: nkx Date: Sun, 26 Jun 2022 20:38:20 +0800 Subject: [PATCH 4/4] TRestHitsEvent fixed reading --- inc/TRestGas.h | 8 ++++ inc/TRestHitsEvent.h | 86 +++++++++++++++++++++++++++++++++++++++++- src/TRestGas.cxx | 1 + src/TRestHitsEvent.cxx | 4 +- 4 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 inc/TRestGas.h create mode 100644 src/TRestGas.cxx diff --git a/inc/TRestGas.h b/inc/TRestGas.h new file mode 100644 index 0000000..bfe4781 --- /dev/null +++ b/inc/TRestGas.h @@ -0,0 +1,8 @@ +#ifndef RestCore_TRestGas +#define RestCore_TRestGas + +#include "TRestDetectorGas.h" + +typedef TRestDetectorGas TRestGas; + +#endif \ No newline at end of file diff --git a/inc/TRestHitsEvent.h b/inc/TRestHitsEvent.h index 24a86ec..d3a67ef 100644 --- a/inc/TRestHitsEvent.h +++ b/inc/TRestHitsEvent.h @@ -2,7 +2,89 @@ #ifndef TRestSoft_TRestHitsEvent #define TRestSoft_TRestHitsEvent -#include "TRestDetectorHitsEvent.h" +#include -typedef TRestDetectorHitsEvent TRestHitsEvent; +#include + +#include "TArrayI.h" +#include "TAxis.h" +#include "TGraph2D.h" +#include "TH2F.h" +#include "TMath.h" +#include "TObject.h" +#include "TRestEvent.h" +#include "TRestHits.h" +#include "TVector3.h" + +//! An event data type that register a vector of TRestHits, +//! allowing us to save a 3-coordinate position and energy. +class TRestHitsEvent : public TRestEvent { + private: + /// An auxiliar TRestHits structure to register hits on XZ projection + TRestHits* fXZHits; //! + /// An auxiliar TRestHits structure to register hits on YZ projection + TRestHits* fYZHits; //! + + /// An auxiliar TRestHits structure to register hits on XYZ projection + TRestHits* fXYZHits; //! + + /// Stores the minimum x-position value. It is initialized by SetBoundaries. + Double_t fMinX; //! + /// Stores the maximum x-position value. It is initialized by SetBoundaries. + Double_t fMaxX; //! + + /// Stores the minimum y-position value. It is initialized by SetBoundaries. + Double_t fMinY; //! + /// Stores the maximum y-position value. It is initialized by SetBoundaries. + Double_t fMaxY; //! + + /// Stores the minimum z-position value. It is initialized by SetBoundaries. + Double_t fMinZ; //! + /// Stores the maximum z-position value. It is initialized by SetBoundaries. + Double_t fMaxZ; //! + + protected: + // TODO These graphs should be placed in TRestHits? + // (following similar GetGraph implementation in TRestSignal) + + /// An auxiliar TGraph pointer to visualize hits on XY-projection. + TGraph* fXYHitGraph; //! + /// An auxiliar TGraph pointer to visualize hits on XZ-projection. + TGraph* fXZHitGraph; //! + /// An auxiliar TGraph pointer to visualize hits on YZ-projection. + TGraph* fYZHitGraph; //! + + /// An auxiliar TH2F histogram to visualize hits on XY-projection. + TH2F* fXYHisto; //! + /// An auxiliar TH2F histogram to visualize hits on YZ-projection. + TH2F* fYZHisto; //! + /// An auxiliar TH2F histogram to visualize hits on XZ-projection. + TH2F* fXZHisto; //! + + TGraph2D* gxz = NULL; //! + TGraph2D* gyz = NULL; //! + + /// An auxiliar TH1F histogram to visualize hits on X-projection. + TH1F* fXHisto; //! + /// An auxiliar TH1F histogram to visualize hits on Y-projection. + TH1F* fYHisto; //! + /// An auxiliar TH1F histogram to visualize hits on Z-projection. + TH1F* fZHisto; //! + + /// The hits structure that is is saved to disk. + TRestHits fHits; // + + public: + void Initialize() { + TRestEvent::Initialize(); + fHits.RemoveHits(); + } + + // Construtor + TRestHitsEvent() {} + // Destructor + ~TRestHitsEvent() {} + + ClassDef(TRestHitsEvent, 2); +}; #endif diff --git a/src/TRestGas.cxx b/src/TRestGas.cxx new file mode 100644 index 0000000..1fe460d --- /dev/null +++ b/src/TRestGas.cxx @@ -0,0 +1 @@ +#include "TRestGas.h" \ No newline at end of file diff --git a/src/TRestHitsEvent.cxx b/src/TRestHitsEvent.cxx index 892037e..cc72222 100644 --- a/src/TRestHitsEvent.cxx +++ b/src/TRestHitsEvent.cxx @@ -37,4 +37,6 @@ /// ///
/// -#include "TRestHitsEvent.h" \ No newline at end of file +#include "TRestHitsEvent.h" + +ClassImp(TRestHitsEvent) \ No newline at end of file