diff --git a/DDCore/include/DD4hep/Segmentations.h b/DDCore/include/DD4hep/Segmentations.h index 6d0171c9c84cbbfbb0ac484cd32d9dd1746e91e1..0e427fa9ce3315ed93eddb45a761fdd031972351 100644 --- a/DDCore/include/DD4hep/Segmentations.h +++ b/DDCore/include/DD4hep/Segmentations.h @@ -141,6 +141,8 @@ namespace DD4hep { struct GridXY : public Segmentation { /// Constructor to be used when reading the already parsed object template <typename Q> GridXY(const Handle<Q>& e) : Segmentation(e) {} + /// Constructor to create a new segmentation object + GridXY(); /// Constructor to be used when creating a new object. Data are taken from the input handle GridXY(const std::string& tag); /// Constructor to be used when creating a new object. @@ -149,6 +151,10 @@ namespace DD4hep { void setGridSizeX(double value); /// Accessors: set grid size in Y void setGridSizeY(double value); + /// Accessors: get grid size in X + double getGridSizeX()const; + /// Accessors: get grid size in Y + double getGridSizeY()const; }; /** @class GridXYZ Segmentations.h DD4hep/lcdd/Segmentations.h diff --git a/DDCore/include/XML/XMLDetector.h b/DDCore/include/XML/XMLDetector.h index ea5457988d9260a49ca38d74b6fdc0552572a485..1cfc04d3f2cbab8569ec92548b6cbb4ffebb3a4f 100644 --- a/DDCore/include/XML/XMLDetector.h +++ b/DDCore/include/XML/XMLDetector.h @@ -79,7 +79,10 @@ namespace DD4hep { int nModules() const; int RowID() const; double moduleHeight() const; + double moduleWidth() const; double modulePitch() const; + double modulePosX() const; + double modulePosY() const; double rowPitch() const; std::string padType() const; diff --git a/DDCore/include/XML/XMLTags.h b/DDCore/include/XML/XMLTags.h index bd27d26fbebddd415cbb013e32209f8e48280274..60da3b5560c4120c8187933a706acef62f0e8b67 100644 --- a/DDCore/include/XML/XMLTags.h +++ b/DDCore/include/XML/XMLTags.h @@ -436,7 +436,10 @@ namespace DD4hep { namespace XML { extern const Tag_t Tag_modules; extern const Tag_t Tag_row; extern const Tag_t Attr_nModules; + extern const Tag_t Attr_modulePosX; + extern const Tag_t Attr_modulePosY; extern const Tag_t Attr_moduleHeight; + extern const Tag_t Attr_moduleWidth; extern const Tag_t Attr_modulePitch; extern const Tag_t Attr_rowPitch; extern const Tag_t Attr_pads; diff --git a/DDCore/src/Segementations.cpp b/DDCore/src/Segementations.cpp index 1cf06135f143931aa0f5c3907554d8eee27acd10..929f1f6edad93080e447a02a894d4a8ac581fc7f 100644 --- a/DDCore/src/Segementations.cpp +++ b/DDCore/src/Segementations.cpp @@ -97,6 +97,9 @@ void ProjectiveZPlane::setPhiBins(int value) { _data().data.cylindrical_binning.nphi = value; } +GridXY::GridXY() +: Segmentation("grid_xy") {} + /// Constructor to be used when creating a new object. Data are taken from the input handle GridXY::GridXY(const std::string& tag) : Segmentation(tag) @@ -111,6 +114,16 @@ GridXY::GridXY(const std::string& tag, double size_x, double size_y) _data().data.cartesian_grid.grid_size_y = size_y; } +/// Accessors: get grid size in X +double GridXY::getGridSizeX() const { + return _data().data.cartesian_grid.grid_size_x; +} + +/// Accessors: get grid size in Y +double GridXY::getGridSizeY() const { + return _data().data.cartesian_grid.grid_size_y; +} + /// Accessors: set grid size in X void GridXY::setGridSizeX(double value) { _data().data.cartesian_grid.grid_size_x = value; diff --git a/DDCore/src/XML/XMLDetector.cpp b/DDCore/src/XML/XMLDetector.cpp index f3ed5e3f252f33550f7b881031dba4bca487ec8f..55b98b13801567c86c959497b705f1bf387c160c 100644 --- a/DDCore/src/XML/XMLDetector.cpp +++ b/DDCore/src/XML/XMLDetector.cpp @@ -160,6 +160,18 @@ double Dimension::moduleHeight() const { return m_element.attr<int>(Attr_moduleHeight); } +double Dimension::moduleWidth() const { + return m_element.attr<int>(Attr_moduleWidth); +} + +double Dimension::modulePosX() const { + return m_element.attr<int>(Attr_modulePosX); +} + +double Dimension::modulePosY() const { + return m_element.attr<int>(Attr_modulePosY); +} + double Dimension::modulePitch() const { return m_element.attr<int>(Attr_modulePitch); } diff --git a/DDCore/src/XML/XMLTags.cpp b/DDCore/src/XML/XMLTags.cpp index fcb14b542d2f1227038a6eb7916719274439d236..4d5b335db492f91a9cfcf5d6075a10c79654daa1 100644 --- a/DDCore/src/XML/XMLTags.cpp +++ b/DDCore/src/XML/XMLTags.cpp @@ -322,6 +322,9 @@ namespace DD4hep { namespace XML { TAG(row); ATTR(nModules); ATTR(moduleHeight); + ATTR(moduleWidth); + ATTR(modulePosX); + ATTR(modulePosY); ATTR(modulePitch); ATTR(rowPitch); ATTR(pads); diff --git a/DDExamples/ILDExDet/compact/TPCPrototype.xml b/DDExamples/ILDExDet/compact/TPCPrototype.xml new file mode 100644 index 0000000000000000000000000000000000000000..0faca095b02ee2628438e4095b2693953fc093f0 --- /dev/null +++ b/DDExamples/ILDExDet/compact/TPCPrototype.xml @@ -0,0 +1,117 @@ +<lccdd xmlns:compact="http://www.lcsim.org/schemas/compact/1.0" + xmlns:xs="http://www.w3.org/2001/XMLSchema" + xs:noNamespaceSchemaLocation="http://www.lcsim.org/schemas/compact/1.0/compact.xsd"> + + <info name="proto_TPC" + title="example TPC Prototype" + author="Astrid Muennich" + status="development" + version="$Id: compact.xml,v 1.3 2010/12/02 16:34:00 grefe Exp $"> + <comment>compact discription of simple TPC prototype</comment> + </info> + + <includes> + <gdmlFile ref="elements.xml"/> + <gdmlFile ref="materials.xml"/> + <pyBuilder ref="../drivers"/> + </includes> + + <define> + <constant name="world_side" value="10*m"/> + <constant name="world_x" value="world_side/2"/> + <constant name="world_y" value="world_side/2"/> + <constant name="world_z" value="world_side/2"/> + <constant name="CrossingAngle" value="0.020"/> + + <constant name="TPC_zhalf" value="500*mm"/> + <constant name="TPC_outer_radius" value="500*mm"/> + <constant name="TPC_inner_radius" value="0*mm"/> + <constant name="TPC_outer_thickness" value="3*mm"/> + <constant name="TPC_endcap_thickness" value="3*mm"/> + + <constant name="tracking_region_radius" value="TPC_outer_radius + 1.0"/> + <constant name="tracking_region_zmax" value="TPC_zhalf + 1.0"/> + </define> + + <materials> + <material name="Graphite"> + <D value="1.7" unit="g/cm3"/> + <composite n="1" ref="C"/> + </material> + </materials> + + <limits> + <limitset name="cal_limits"> + <limit name="step_length_max" particles="*" value="5.0" unit="mm" /> + </limitset> + </limits> + + <display> + <vis name="TPCVis" alpha="1.0" r="0" g="1.0" b="0.0" showDaughters="true" visible="false"/> + <vis name="TPCEndplateVis" alpha="1.0" r="0" g="1.0" b="0.0" showDaughters="false" visible="true"/> + <vis name="TPCModuleVis" alpha="1.0" r="0" g="0.0" b="1.0" showDaughters="false" visible="true"/> + <vis name="TPCSupportVis" alpha="1.0" r="0" g="0.4" b="0.4" showDaughters="false" visible="true"/> + <vis name="TPCGasVis" alpha="0.5" r="0.7" g="0" b="0" showDaughters="false" visible="false"/> + </display> + + <detectors> + <comment>Trackers</comment> + + + <detector name="TPC" type="TPCPrototype" vis="TPCVis" id="3"> + <tubs rmin="TPC_inner_radius" rmax="TPC_outer_radius" zhalf="TPC_zhalf"/> + + <material name="Air"/> + + + <detector name="TPC_OuterWall" type="TubeSegment" reflect="false" vis="TPCSupportVis" id="3"> + <material name="Carbon" /> + <tubs rmin="TPC_outer_radius - TPC_outer_thickness" rmax="TPC_outer_radius" zhalf="TPC_zhalf"/> + <position x="0" y="0" z="TPC_zhalf"/> + <rotation x="0" y="0" z="0"/> + </detector> + + <detector name="TPC_EndPlate" type="TubeSegment" reflect="false" vis="TPCEndPlateVis" id="0"> + <material name="Carbon" /> + <tubs rmin="TPC_inner_radius" rmax="TPC_outer_radius-TPC_outer_thickness" zhalf="0.5*TPC_endcap_thickness"/> + <position x="0" y="0" z="2*TPC_zhalf-0.5*TPC_endcap_thickness"/> + <rotation x="0" y="0" z="0"/> + + <modules name="TPC_Module" vis="TPCModuleVis"> + <row type ="Box" modulePosX="-15*cm" modulePosY="20*cm" moduleHeight="15*cm" moduleWidth="10*cm" modulePitch="10*cm" pads="PadLayout0" nModules="3" RowID="0"/> + <row type ="Box" modulePosX="-15*cm" modulePosY="0" moduleHeight="15*cm" moduleWidth="10*cm" modulePitch="10*cm" pads="PadLayout0" nModules="3" RowID="1"/> + <row type ="Box" modulePosX="-15*cm" modulePosY="-20*cm" moduleHeight="15*cm" moduleWidth="10*cm" modulePitch="10*cm" pads="PadLayout0" nModules="3" RowID="2"/> + </modules> + </detector> + + + <detector name="TPC_GasVolume" type="TubeSegment" reflect="false" vis="TPCGasVis" id="4"> + <material name="Argon"/> + <tubs rmin="TPC_inner_radius" rmax="TPC_outer_radius-TPC_outer_thickness" zhalf="TPC_zhalf-TPC_endcap_thickness"/> + <position x="0" y="0" z="TPC_zhalf"/> + <rotation x="0" y="0" z="0"/> + </detector> + + <detector name="TPC_Cathode" type="TubeSegment" reflect="false" vis="TPCSupportVis" id="5"> + <material name="Argon"/> + <tubs rmin="TPC_inner_radius" rmax="TPC_outer_radius" zhalf="0.5"/> + <position x="0" y="0" z="0"/> + <rotation x="0" y="0" z="0"/> + </detector> + </detector> + + </detectors> + + <readouts> + <readout name="PadLayout0"> + <segmentation type="CartesianGridXY" gridSizeX="2*mm" gridSizeY="6*mm"/> + <id>system:6</id> + </readout> + </readouts> + + <fields> + <field type="Solenoid" name="GlobalSolenoid" inner_field="5.0" + outer_field="-1.5" zmax="SolenoidCoilOuterZ" + outer_radius="SolenoidalFieldRadius" /> + </fields> +</lccdd> diff --git a/DDExamples/ILDExDet/include/RectangularPadRowLayout.h b/DDExamples/ILDExDet/include/RectangularPadRowLayout.h new file mode 100644 index 0000000000000000000000000000000000000000..8e0051a87b98297244c331338a1d444971fa1fe6 --- /dev/null +++ b/DDExamples/ILDExDet/include/RectangularPadRowLayout.h @@ -0,0 +1,79 @@ +// $Id:$ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : A.Muennich +// +//==================================================================== +#ifndef RectangularPadRowLayout_H +#define RectangularPadRowLayout_H + +#include "DD4hep/Detector.h" +#include "DD4hep/Segmentations.h" +#include "PadLayout.h" +#include <Exceptions.h> + +namespace DD4hep { + + + struct RectangularPadRowLayout : public PadLayout { + + Geometry::DetElement module; + Geometry::CartesianGridXY pads; + Geometry::Box box; + /// Default empty constructor + RectangularPadRowLayout() : module(), pads(), box() {} + + /// Standard constructor with arguments + RectangularPadRowLayout(const Geometry::DetElement& d); + + /// Standard extension constructor. det is the NEW detector element e.g. when reflecting a detector + RectangularPadRowLayout(const RectangularPadRowLayout& c,const Geometry::DetElement& det); + + /// Default destructor + virtual ~RectangularPadRowLayout() {} + + /** The type of pad layout (segmentation) on this module. + */ + virtual std::string getPadType() const; + /** The total number of pads on this module. + */ + virtual int getNPads() const; + /** The total number of rows on this module. + */ + virtual int getNRows() const; + /** The number of pads in a given row on this module. + */ + virtual int getNPadsInRow(int row)const; + /** The height of a given row on this module. + */ + virtual double getRowHeight (int row) const; + /** The pad pitch (sensitive plus surroundings = effective size) of a given pad on this module. + */ + virtual double getPadPitch (int padIndex) const; + /** The row which contains the given pad on this module. + */ + virtual int getRowNumber (int padIndex) const; + /** The position of a pad within the row on this module. + */ + virtual int getPadNumber (int padIndex) const; + /** The pad id for a pad with padNum in row with rowNum on this module. + */ + virtual int getPadIndex (int rowNum, int padNum)const ; + /** The right neighbour of a pad with the given index on this module. + */ + virtual int getRightNeighbour (int padIndex) const; + /** The left neighbour of a pad with the given index on this module. + */ + virtual int getLeftNeighbour (int padIndex) const; + /** The center of a pad on this module in global coordinates. + */ + virtual std::vector<double> getPadCenter (int padIndex) const; + /** Closest pad to a given location. + */ + virtual int getNearestPad (double c0, double c1) const; + }; + +} +#endif diff --git a/DDExamples/ILDExDet/include/TPCModule.h b/DDExamples/ILDExDet/include/TPCModule.h index 9ab2b0b90108eb1dc81480338403990b63e7c864..c0bb0a69c0dc470f055a23fcefe57785f17e0b68 100644 --- a/DDExamples/ILDExDet/include/TPCModule.h +++ b/DDExamples/ILDExDet/include/TPCModule.h @@ -5,6 +5,8 @@ // // Author : A.Muennich // +// Interface to PadLayout functions +// //==================================================================== #ifndef TPCMODULE_H #define TPCMODULE_H @@ -37,9 +39,6 @@ namespace DD4hep { /** ID of this module. */ int getID() const; - /**Helper function to get the z position of the module in local coordinates. - */ - double getModuleZPosition() const; //Now all the functionality that depends on specific implementation of padlayout /** The type of pad layout (segmentation) on this module. diff --git a/DDExamples/ILDExDet/include/TPCModuleTemplated.h b/DDExamples/ILDExDet/include/TPCModuleTemplated.h deleted file mode 100644 index bf570a5e119c7f60bc15182f249c309b41cf6410..0000000000000000000000000000000000000000 --- a/DDExamples/ILDExDet/include/TPCModuleTemplated.h +++ /dev/null @@ -1,91 +0,0 @@ -// $Id:AIDA -//==================================================================== -// $ Detector description implementation for LCD -//-------------------------------------------------------------------- -// -// Author : A.Muennich -// -//==================================================================== -#ifndef TPCMODULETEMPLATED_H -#define TPCMODULETEMPLATED_H - -#include "DD4hep/Detector.h" -#include <Exceptions.h> -#include "TPCModuleData.h" - -namespace DD4hep { - - struct TPCModuleData; - //template for the PadLayouts - template <class PL> - - struct TPCModuleTemplated : public Geometry::DetElement { - typedef Geometry::Ref_t Ref_t; - //template for PadLayout - PL padlayout; - - TPCModuleData* m_modData; - void getExtension(){ m_modData = isValid() ? extension<TPCModuleData>() : 0;} - - //various constructors - TPCModuleTemplated() : m_modData(0) {} - TPCModuleTemplated(const Ref_t& e) : Geometry::DetElement(e), m_modData(0) {getExtension();} - TPCModuleTemplated(const Geometry::DetElement& e) : Geometry::DetElement(e), m_modData(0) {getExtension();} - TPCModuleTemplated(const std::string& name, const std::string& type, int id) : Geometry::DetElement(name,type,id), m_modData(0) {getExtension();} - template<typename T> TPCModuleTemplated& operator=(const T& h) { - m_element = h.m_element; - getExtension(); - return *this; - } - - /** ID of this module. - */ - int getID() const { return _data().id; } - - //Now all the functionality that depends on specific implementation of padlayout - /** The type of pad layout (segmentation) on this module. - */ - std::string getPadType() const { padlayout.getPadType(); } - /** The total number of pads on this module. - */ - int getNPads() const { padlayout.getNPads(); } - /** The total number of rows on this module. - */ - int getNRows() const { padlayout.getNRows(); } - /** The number of pads in a given row on this module. - */ - int getNPadsInRow(int row)const { padlayout.getNPadsInRow(row); } - /** The height of a given row on this module. - */ - double getRowHeight (int row) const { padlayout.getRowHeight (row); } - /** The pad pitch (sensitive plus surroundings = effective size) of a given pad on this module. - */ - double getPadPitch (int padIndex) const { padlayout.getPadPitch (padIndex); } - /** The row which contains the given pad on this module. - */ - int getRowNumber (int padIndex) const { padlayout.getRowNumber (padIndex);} - /** The position of a pad within the row on this module. - */ - int getPadNumber (int padIndex) const { padlayout.getPadNumber (padIndex); } - /** The pad id for a pad with padNum in row with rowNum on this module. - */ - int getPadIndex (int rowNum, int padNum)const { padlayout.getPadIndex (rowNum, padNum); } - /** The right neighbour of a pad with the given index on this module. - */ - int getRightNeighbour (int padIndex) const { padlayout.getRightNeighbour (padIndex); } - /** The left neighbour of a pad with the given index on this module. - */ - int getLeftNeighbour (int padIndex) const { padlayout.getLeftNeighbour (padIndex) ;} - /** The center of a pad on this module in global coordinates. - */ - std::vector<double> getPadCenter (int padIndex) const { padlayout.getPadCenter (padIndex) ;} - /** Closest pad to a given location. - */ - int getNearestPad (double c0, double c1) const { padlayout.getNearestPad (c0,c1); } - /**Helper function to get the z position of the module in local coordinates. - */ - double getModuleZPosition() const { padlayout.getModuleZPosition(); } - }; - -} -#endif diff --git a/DDExamples/ILDExDet/src/FixedPadAngleDiskLayout.cpp b/DDExamples/ILDExDet/src/FixedPadAngleDiskLayout.cpp index 6ff40424353f4b0af287eaa35ee8646ae4315714..6383e45fcbc5855ccfa386c8a490dc6cb21324e9 100644 --- a/DDExamples/ILDExDet/src/FixedPadAngleDiskLayout.cpp +++ b/DDExamples/ILDExDet/src/FixedPadAngleDiskLayout.cpp @@ -6,9 +6,8 @@ // Author : A.Muennich // // This is a special implementation for a FixedPadAngleDiskLayout! -// The number of pads is distrubuted on a wedge shaped segment starting -// with the right edge of the first pad in the row at phiMin to the left -// edge of the last pad in the row at phiMax. All rows have the same height, +// The number of pads is distrubuted on a tube shaped segment starting +// on the lower left corner. All rows have the same height, // starting at rmin for the lower edge of the first row to rmax for the // upper edge of the last row. The row height is calculated from the number of pads. // @@ -18,10 +17,7 @@ #include "DD4hep/LCDD.h" #include "FixedPadAngleDiskLayout.h" -//#include "TPCModule.h" #include "TGeoTube.h" -#include "TGeoMatrix.h" -#include "TGeoManager.h" #include <math.h> #include <iostream> @@ -46,22 +42,18 @@ namespace DD4hep { } std::string FixedPadAngleDiskLayout::getPadType()const { - //ProjectiveCylinder pads= module.readout().segmentation(); return pads.type(); } int FixedPadAngleDiskLayout::getNPads()const { - //ProjectiveCylinder pads= module.readout().segmentation(); return pads.thetaBins()* pads.phiBins(); } int FixedPadAngleDiskLayout::getNRows()const { - //ProjectiveCylinder pads= module.readout().segmentation(); return pads.thetaBins(); } int FixedPadAngleDiskLayout::getNPadsInRow(int row)const { - //ProjectiveCylinder pads= module.readout().segmentation(); return pads.phiBins(); } @@ -69,7 +61,6 @@ namespace DD4hep { if(row>getNRows() || row<0) throw OutsideGeometryException("getRowHeight: Requested row not on module querried!"); //all rows are the same for FixedPadAngleDiskLayout=ProjectiveCylinder - ////Tube tube=module.volume().solid(); double module_height= tube->GetRmax()-tube->GetRmin(); return module_height/getNRows(); } @@ -84,7 +75,6 @@ namespace DD4hep { if(pad>getNPads() || pad<0) throw OutsideGeometryException("getPadPitch: Requested pad not on module querried!"); int row=getRowNumber(pad); - /////Tube tube=module.volume().solid(); double pad_radius=tube->GetRmin()+(row+0.5)*getRowHeight(0); double module_width= tube->GetPhi2()-tube->GetPhi1(); double pad_angle=module_width/getNPadsInRow(row); @@ -106,6 +96,7 @@ namespace DD4hep { } int FixedPadAngleDiskLayout::getRightNeighbour(int pad)const { + //what is left and what is right is a matter of definition //if on edge their is no neighbour, should throw an exception int row=getRowNumber(pad); if(getPadNumber(pad)==getNPadsInRow(row)-1) @@ -127,7 +118,6 @@ namespace DD4hep { if(pad>getNPads()) throw OutsideGeometryException("getPadCenter: Requested pad not on module querried!"); int row=getRowNumber(pad); - //////Tube tube=module.volume().solid(); double pad_radius=tube->GetRmin()+(row+0.5)*getRowHeight(0); double module_width= tube->GetPhi2()-tube->GetPhi1(); double pad_angle=(getPadNumber(pad)+0.5)*module_width/getNPadsInRow(row); @@ -136,7 +126,7 @@ namespace DD4hep { double pad_y = pad_radius*sin(pad_angle*M_PI/180.); //trafo to global coordinates - Position global_w, local(pad_x,pad_y,0);//TPCModule(module).getModuleZPosition(); + Position global_w, local(pad_x,pad_y,0); module.localToWorld(local,global_w); vector<double> center; @@ -146,8 +136,8 @@ namespace DD4hep { } int FixedPadAngleDiskLayout::getNearestPad(double c0,double c1)const { + //input coordinates are global //find z position of module in world coordinates - Position fake_local(0,0,0); Position fake_global; module.localToWorld(fake_local,fake_global); @@ -156,19 +146,21 @@ namespace DD4hep { module.worldToLocal(global,local); Double_t point_local[3]={local.x,local.y,local.z}; //check if it is on that module - ////Tube tube=module.volume().solid(); bool onMod=tube->Contains(point_local); if(!onMod) throw OutsideGeometryException("getNearestPad: Requested point not on module querried!"); double module_width= tube->GetPhi2()-tube->GetPhi1(); double radius=sqrt(point_local[0]*point_local[0]+point_local[1]*point_local[1]); int row=(radius-tube->GetRmin())/getRowHeight(0); - //outer edge of last row belongs to last row + //outer edge of last row belongs to last row, same for the pad if(row==getNRows()) row=getNRows()-1; double pad_width=module_width/getNPadsInRow(row); double angle=atan2(point_local[1],point_local[0])/M_PI*180; int padNr=static_cast<int>(angle/pad_width); + if(padNr==getNPadsInRow(row)) + padNr=padNr-1; + return getPadIndex(row,padNr); } diff --git a/DDExamples/ILDExDet/src/RectangularPadRowLayout.cpp b/DDExamples/ILDExDet/src/RectangularPadRowLayout.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d66ddefc069cd6bc173fc42ee911d9756ea15230 --- /dev/null +++ b/DDExamples/ILDExDet/src/RectangularPadRowLayout.cpp @@ -0,0 +1,154 @@ +// $Id:$ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : A.Muennich +// +// This is a special implementation for a RectangularPadRowLayout! +// for a rectangular row based layout where all pads in a given row are +// equal and have rectangular shape ditributed on a rectangular shaped module. +// +// Row height and pad height are identical, and pad gap is 0 +// (the only thing that matters is the effective pitch). +//==================================================================== +#include "DD4hep/LCDD.h" + +#include "RectangularPadRowLayout.h" +#include "TGeoBBox.h" +#include <math.h> +#include <iostream> + +using namespace std; + +namespace DD4hep { + + using namespace Geometry; + + /// Standard constructor with arguments + RectangularPadRowLayout::RectangularPadRowLayout(const Geometry::DetElement& d) : module(d) { + pads = module.readout().segmentation(); + box = module.volume().solid(); + } + + /// Standard extension constructor. det is the NEW detector element e.g. when reflecting a detector + RectangularPadRowLayout::RectangularPadRowLayout(const RectangularPadRowLayout& /* c */, const Geometry::DetElement& det) + : module(det) + { + pads = module.readout().segmentation(); + box = module.volume().solid(); + } + + std::string RectangularPadRowLayout::getPadType()const { + return pads.type(); + } + + int RectangularPadRowLayout::getNPads()const { + return getNRows()*getNPadsInRow(0); + } + + int RectangularPadRowLayout::getNRows()const { + return box->GetDY()*2/pads.getGridSizeY(); + } + + int RectangularPadRowLayout::getNPadsInRow(int row)const { + return box->GetDX()*2/pads.getGridSizeX(); + } + + double RectangularPadRowLayout::getRowHeight(int row)const { + if(row>getNRows() || row<0) + throw OutsideGeometryException("getRowHeight: Requested row not on module querried!"); + //all rows are the same for RectangularPadRowLayout=cartesian_grid + double module_height= 2*box->GetDY(); + return module_height/getNRows(); + } + + int RectangularPadRowLayout::getRowNumber(int pad)const { + if(pad>getNPads() || pad<0) + throw OutsideGeometryException("getRowNumber: Requested pad not on module querried!"); + return pad/getNPadsInRow(0); + } + + double RectangularPadRowLayout::getPadPitch(int pad)const { + if(pad>getNPads() || pad<0) + throw OutsideGeometryException("getPadPitch: Requested pad not on module querried!"); + int row=getRowNumber(pad); + double module_width= 2*box->GetDX(); + return module_width/getNPadsInRow(row); + } + + int RectangularPadRowLayout::getPadNumber(int pad)const { + if(pad>getNPads() || pad<0) + throw OutsideGeometryException("getPadNumber: Requested pad not on module querried!"); + return pad % getNPadsInRow(0); + } + + int RectangularPadRowLayout::getPadIndex(int row,int padNr)const { + if(padNr>=getNPadsInRow(row) || padNr<0) + throw OutsideGeometryException("getPadIndex: Requested pad not on module querried!"); + if(row>=getNRows() || padNr<0 ) + throw OutsideGeometryException("getPadIndex: Requested row not on module querried!"); + return padNr + row*getNPadsInRow(row); + } + + int RectangularPadRowLayout::getRightNeighbour(int pad)const { + //if on edge their is no neighbour, should throw an exception + int row=getRowNumber(pad); + if(getPadNumber(pad)==getNPadsInRow(row)-1) + throw OutsideGeometryException("getRightNeighbour: Requested pad is on right edge and has no right neighbour!"); + // if not on edge + return pad + 1; + } + + int RectangularPadRowLayout::getLeftNeighbour(int pad)const { + //if on edge their is no neighbour, should throw an exception + if(getPadNumber(pad)==0) + throw OutsideGeometryException("getLeftNeighbour: Requested pad is on left edge and has no left neighbour!"); + // if not on edge + return pad - 1; + } + + + std::vector<double> RectangularPadRowLayout::getPadCenter (int pad) const { + if(pad>getNPads()) + throw OutsideGeometryException("getPadCenter: Requested pad not on module querried!"); + int row=getRowNumber(pad); + //shift coordinates from pad system where 0,0 is on lower left corner of module into module + //system where 0,0 is in the middle of the module box + double pad_y=(row+0.5)*getRowHeight(0)-box->GetDY(); + double pad_x = (getPadNumber(pad)+0.5)*getPadPitch(pad)-box->GetDX(); + //trafo to global coordinates + Position global_w, local(pad_x,pad_y,0); + module.localToWorld(local,global_w); + + vector<double> center; + center.push_back(global_w.x); + center.push_back(global_w.y); + return center; + } + + int RectangularPadRowLayout::getNearestPad(double c0,double c1)const { + //find z position of module in world coordinates + Position fake_local(0,0,0); + Position fake_global; + module.localToWorld(fake_local,fake_global); + // trafo to local coordinates + Position global(c0,c1,fake_global.z), local; + module.worldToLocal(global,local); + Double_t point_local[3]={local.x,local.y,local.z}; + //check if it is on that module + bool onMod=box->Contains(point_local); + if(!onMod) + throw OutsideGeometryException("getNearestPad: Requested point not on module querried!"); + //shift coordinates into pad system where 0,0 is on lower left corner of module + int row=static_cast<int>((point_local[1]+box->GetDY())/getRowHeight(0)); + //outer edge of last row belongs to last row, same goes for pad + if(row==getNRows()) + row=getNRows()-1; + int padNr=static_cast<int>((point_local[0]+box->GetDX())/getPadPitch(0)); + if(padNr==getNPadsInRow(row)) + padNr=padNr-1; + return getPadIndex(row,padNr); + } + +} diff --git a/DDExamples/ILDExDet/src/TPCModule.cpp b/DDExamples/ILDExDet/src/TPCModule.cpp index 6ecacd078213a9a9ed87bca5dd1267ee516632bf..7fb5937240010e542e44c0567bc948a3605c384b 100644 --- a/DDExamples/ILDExDet/src/TPCModule.cpp +++ b/DDExamples/ILDExDet/src/TPCModule.cpp @@ -15,8 +15,6 @@ #include "TPCModule.h" #include "TPCModuleData.h" #include "TGeoTube.h" -#include "TGeoMatrix.h" -#include "TGeoManager.h" #include <cmath> #include <iostream> @@ -34,10 +32,4 @@ namespace DD4hep { return _data().id; } - double TPCModule::getModuleZPosition() const { - //for internal use only, gives back coordinate in local system - TGeoMatrix *nm = placement()->GetMatrix(); - const Double_t *trans = nm->GetTranslation(); - return trans[2]; - } -} + } diff --git a/DDExamples/ILDExDet/src/compact/ILDExTPC_geo.cpp b/DDExamples/ILDExDet/src/compact/ILDExTPC_geo.cpp index b796fdd106785bd199813dadb0aa5fa44a9d311a..20b378d413f0282af651095689f532c2cd299978 100644 --- a/DDExamples/ILDExDet/src/compact/ILDExTPC_geo.cpp +++ b/DDExamples/ILDExDet/src/compact/ILDExTPC_geo.cpp @@ -11,7 +11,6 @@ #include "DD4hep/Detector.h" #include "TPCModuleData.h" #include "TPCModule.h" -#include "TPCModuleTemplated.h" #include "FixedPadAngleDiskLayout.h" using namespace std; @@ -73,8 +72,7 @@ static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens) //placing modules for(int md=0;md<nmodules;md++){ string m_nam=m_name+_toString(rowID,"_Row%d")+_toString(md,"_M%d"); - - //templated TPCModule + DetElement module(part_det,m_nam,mdcount); mdcount++; double rotz=md*2*M_PI/nmodules+row.modulePitch()/(rmin+(rmax-rmin))/2; diff --git a/DDExamples/ILDExDet/src/compact/TPCPrototype_geo.cpp b/DDExamples/ILDExDet/src/compact/TPCPrototype_geo.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9980b254c114e0c683aa25c8d57a49a8ff2fcb9d --- /dev/null +++ b/DDExamples/ILDExDet/src/compact/TPCPrototype_geo.cpp @@ -0,0 +1,111 @@ +// $Id:$ +//==================================================================== +// AIDA Detector description implementation for LCD +//-------------------------------------------------------------------- +// +// Author : A.Muennich +// +//==================================================================== + +#include "DD4hep/DetFactoryHelper.h" +#include "DD4hep/Detector.h" +#include "TPCModuleData.h" +#include "TPCModule.h" +#include "RectangularPadRowLayout.h" + +using namespace std; +using namespace DD4hep; +using namespace DD4hep::Geometry; + +static Ref_t create_element(LCDD& lcdd, const xml_h& e, SensitiveDetector& sens) { + xml_det_t x_det = e; + xml_comp_t x_tube (x_det.child(_X(tubs))); + string name = x_det.nameStr(); + Material mat (lcdd.material(x_det.materialStr())); + DetElement tpc (name,x_det.typeStr(),x_det.id()); + Tube tpc_tub(x_tube.rmin(),x_tube.rmax(),x_tube.zhalf()); + Volume tpc_vol(name+"_envelope_volume", tpc_tub, mat); + + for(xml_coll_t c(e,_X(detector)); c; ++c) { + xml_comp_t px_det (c); + xml_comp_t px_tube (px_det.child(_X(tubs))); + xml_dim_t px_pos (px_det.child(_X(position))); + xml_dim_t px_rot (px_det.child(_X(rotation))); + xml_comp_t px_mat (px_det.child(_X(material))); + string part_nam(px_det.nameStr()); + Material part_mat(lcdd.material(px_mat.nameStr())); + DetElement part_det(part_nam,px_det.typeStr(),px_det.id()); + Tube part_tub(px_tube.rmin(),px_tube.rmax(),px_tube.zhalf()); + Volume part_vol(part_nam,part_tub,part_mat); + Position part_pos(px_pos.x(),px_pos.y(),px_pos.z()); + Rotation part_rot(px_rot.x(),px_rot.y(),px_rot.z()); + bool reflect = px_det.reflect(); + + part_vol.setVisAttributes(lcdd,px_det.visStr()); + //Endplate + if(part_det.id()== 0){ + //modules + int mdcount=0; + for(xml_coll_t m(px_det,_X(modules)); m; ++m) { + xml_comp_t modules (m); + string m_name = modules.nameStr(); + for(xml_coll_t r(modules,_X(row)); r; ++r) { + xml_comp_t row(r); + int nmodules = row.nModules(); + int rowID=row.RowID(); + //shape of module + double pitch=row.modulePitch(); + double height=row.moduleHeight(); + double width=row.moduleWidth(); + double zhalf=px_tube.zhalf(); + string mr_nam=m_name+_toString(rowID,"_Row%d"); + Volume mr_vol(mr_nam,Box(width/2,height/2,zhalf),part_mat); + Material mr_mat(lcdd.material(px_mat.nameStr())); + Readout xml_pads(lcdd.readout(row.padType())); + + //placing modules + for(int md=0;md<nmodules;md++){ + string m_nam=m_name+_toString(rowID,"_Row%d")+_toString(md,"_M%d"); + DetElement module(part_det,m_nam,mdcount); + mdcount++; + double posx=row.modulePosX()+md*(width/2+pitch); + double posy=row.modulePosY(); + PlacedVolume m_phv = part_vol.placeVolume(mr_vol,Position(posx,posy,0),Rotation(0,0,0)); + m_phv.addPhysVolID("module",md); + module.setPlacement(m_phv); + module.setReadout(xml_pads); + // Readout and placement must be present before adding extension, + // since they are aquired internally for optimisation reasons. (MF) + module.addExtension<PadLayout>(new RectangularPadRowLayout(module)); + }//modules + }//rows + }//module groups + }//endplate + + PlacedVolume part_phv = tpc_vol.placeVolume(part_vol,part_pos,part_rot); + part_phv.addPhysVolID(part_nam,px_det.id()); + part_det.setPlacement(part_phv); + tpc.add(part_det); + //now reflect it + if(reflect){ + Position r_pos(px_pos.x(),px_pos.y(),-px_pos.z()); + //Attention: rotation is given in euler angles + Rotation r_rot(M_PI,0,M_PI); + // Volume part_vol_r(lcdd,part_nam+"_negativ",part_tub,part_mat); + PlacedVolume part_phv2 = tpc_vol.placeVolume(part_vol,r_pos,r_rot); + part_phv2.addPhysVolID(part_nam+"_negativ",px_det.id()+1); + // needs a copy function for DetElement + // DetElement rdet(lcdd,part_nam+"_negativ",px_det.typeStr(),px_det.id()+1); + DetElement rdet = part_det.clone(part_nam+"_negativ",px_det.id()+1); + rdet.setPlacement(part_phv2); + tpc.add(rdet); + } + }//subdetectors + tpc_vol.setVisAttributes(lcdd, x_det.visStr()); + PlacedVolume phv = lcdd.pickMotherVolume(tpc).placeVolume(tpc_vol); + tpc.setPlacement(phv); + return tpc; +} + +//first argument is the type from the xml file +DECLARE_DETELEMENT(TPCPrototype,create_element) diff --git a/DDExamples/ILDExReco/CMakeLists.txt b/DDExamples/ILDExReco/CMakeLists.txt index 22029ab9abc6e9ef41895a3cbefb4457a7ac00f6..4e1e6b60b19a9442e31dd391e5403352c77c5027 100644 --- a/DDExamples/ILDExReco/CMakeLists.txt +++ b/DDExamples/ILDExReco/CMakeLists.txt @@ -6,12 +6,14 @@ include_directories( ${CMAKE_SOURCE_DIR}/DDCore/include ${ROOT_INCLUDE_DIR}) add_executable(ILDExReco ILDExReco.cpp src/GearTPC.cpp) +add_executable(TestTPCPrototype TestTPCPrototype.cpp src/GearTPC.cpp) add_executable(TPCDigitisation TPCDigitisation.cpp src/GearTPC.cpp) add_executable(TPCHitReco TPCHitReco.cpp src/GearTPC.cpp) add_executable(CalculateTPCPadBinning CalculateTPCPadBinning.cpp src/GearTPC.cpp) add_executable(TPCToySimulation TPCToySimulation.cpp src/GearTPC.cpp) add_executable(TPCMaterialScan TPCMaterialScan.cpp src/GearTPC.cpp) target_link_libraries(ILDExReco DD4hepCore ILDEx ${ROOT_LIBRARIES}) +target_link_libraries(TestTPCPrototype DD4hepCore ILDEx ${ROOT_LIBRARIES}) target_link_libraries(TPCDigitisation DD4hepCore ILDEx ${ROOT_LIBRARIES}) target_link_libraries(TPCHitReco DD4hepCore ILDEx ${ROOT_LIBRARIES}) target_link_libraries(CalculateTPCPadBinning DD4hepCore ILDEx ${ROOT_LIBRARIES}) diff --git a/DDExamples/ILDExReco/ILDExReco.cpp b/DDExamples/ILDExReco/ILDExReco.cpp index 831dd3bf15b1c3df77e62ff57b9b2a9fcf41aaba..9f609a631c72fc2287807fc306d8b8c5cc51d05b 100644 --- a/DDExamples/ILDExReco/ILDExReco.cpp +++ b/DDExamples/ILDExReco/ILDExReco.cpp @@ -61,9 +61,7 @@ int main(int argc,char** argv) { TPCModule mymod=tpc.getModule(10,1); cout << "-----> Module 10 EP 1 ID:\t " << mymod.getID()<<endl; - string typ = mymod.getPadType(); - //cout << "-----> Module 10 Pads:\t " << mymod.getPadType()<<endl; - cout << "-----> Module 10 Pads:\t " << typ<<endl; + cout << "-----> Module 10 Pads:\t " << mymod.getPadType()<<endl; cout << "-----> Module 10 NPads:\t " << mymod.getNPads()<<endl; cout << "-----> Module 10 pad rows:\t " << mymod.getNRows()<<endl; cout << "-----> Module 10 pads in rows:\t " << mymod.getNPadsInRow(0)<<endl; diff --git a/DDExamples/ILDExReco/TPCDigitisation.cpp b/DDExamples/ILDExReco/TPCDigitisation.cpp index e55e6f94eac3fcff1e019fea10622b1576fd5062..db8461bfa90b9e016966aaef2ebb5c083cd3088e 100644 --- a/DDExamples/ILDExReco/TPCDigitisation.cpp +++ b/DDExamples/ILDExReco/TPCDigitisation.cpp @@ -85,12 +85,17 @@ int main(int argc,char** argv) { if(z<0) endplate=1; //check if point is over module. If not move to next point - bool measured=tpc.isInsideModule(x,y,endplate); + bool measured=false; + try{ + measured=tpc.isInsideModule(x,y,endplate); + } + catch(OutsideGeometryException e){}; if(!measured) continue; TPCModule mymod=tpc.getNearestModule(x,y,endplate); int modID=mymod.getID(); int padID= mymod.getNearestPad(x,y); + std::pair<int,int> ID_pair=make_pair(modID,padID); //check if that pad has already been hit diff --git a/DDExamples/ILDExReco/TPCHitReco.cpp b/DDExamples/ILDExReco/TPCHitReco.cpp index 1259a27fb63552cc9278ea16e1a29924f88b1a17..1010598e555b92b78ffde630955d44ca2442e7fb 100644 --- a/DDExamples/ILDExReco/TPCHitReco.cpp +++ b/DDExamples/ILDExReco/TPCHitReco.cpp @@ -103,6 +103,13 @@ int main(int argc,char** argv) { //negative endplate for ( it2=padmap_EP2.begin() ; it2 != padmap_EP2.end(); it2++ ) { + bool endplate2=true; + try{ + tpc.getModule(it2->first.first,1); + } + catch(OutsideGeometryException e){endplate2=false;}; + if(!endplate2) + continue; std::vector<double> center=tpc.getModule(it2->first.first,1).getPadCenter(it2->first.second); xPos.push_back(center[0]); diff --git a/DDExamples/ILDExReco/TPCToySimulation.cpp b/DDExamples/ILDExReco/TPCToySimulation.cpp index 5aa8486ff75c02ef74a641cc25675d9c95f998f8..d9ffdb9c169acb378a7e37d91fa62f06de0593f1 100644 --- a/DDExamples/ILDExReco/TPCToySimulation.cpp +++ b/DDExamples/ILDExReco/TPCToySimulation.cpp @@ -64,7 +64,13 @@ int main(int argc,char** argv) { //point loop for (int p=0;p<NPOINTS;p++) { - double radius=tpc.getInnerRadius()+(tpc.getOuterRadius()-tpc.getInnerRadius())*p/NPOINTS; + double inner_r=0; + try{ + inner_r=tpc.getInnerRadius(); + } + catch(OutsideGeometryException e){}; + + double radius=inner_r+(tpc.getOuterRadius()-inner_r)*p/NPOINTS; xPos.push_back(radius*cos(phi)); yPos.push_back(radius*sin(phi)); zPos.push_back(sign_z*radius/tan(theta)); diff --git a/DDExamples/ILDExReco/TestTPCPrototype.cpp b/DDExamples/ILDExReco/TestTPCPrototype.cpp new file mode 100644 index 0000000000000000000000000000000000000000..10453e968b37498de7b40b71ba4caf10f0f64298 --- /dev/null +++ b/DDExamples/ILDExReco/TestTPCPrototype.cpp @@ -0,0 +1,85 @@ +// +// pymain.cpp +// +// +// Created by Pere Mato on 20/1/12. +// Copyright 2012 __MyCompanyName__. All rights reserved. +// +//==================================================================== +// Test application for TPC functionality +//-------------------------------------------------------------------- +// +// Author : A.Muennich +// +// +//==================================================================== + +#include "DD4hep/LCDD.h" +#include <iostream> +#include <vector> +#include <string> +#include "GearTPC.h" +#include "TPCModuleData.h" + + +using namespace std; +using namespace DD4hep; +using namespace Geometry; + +#include "TPCModuleData.h" + + +int main(int argc,char** argv) { + + LCDD& lcdd = LCDD::getInstance(); + lcdd.fromCompact(argv[1]); + + GearTPC tpc(lcdd.detector("TPC")); + cout << "Gear TPC functionality:"<<endl; + cout << "-----> Outer Radius:\t " << tpc.getOuterRadius() << endl; + cout << "-----> DriftLength:\t " << tpc.getMaxDriftLength() << endl; + + cout << "-----> EndplateThickness 0:\t " << tpc.getEndPlateThickness(0) <<endl; + cout << "-----> EndplateZPosition 0:\t "<< tpc.getEndPlateZPosition(0)<<endl; + try{ + cout << "-----> EndplateThickness 1:\t " << tpc.getEndPlateThickness(1) <<endl; + cout << "-----> EndplateZPosition 1:\t "<< tpc.getEndPlateZPosition(1)<<endl; + } + catch(OutsideGeometryException e){cout<<"-----> Exception test: "<<e.what()<<endl;}; + + std::vector<TPCModule> mymods=tpc.getModules(0); + cout << "-----> NModules EP0:\t " << mymods.size()<< endl; + int npads=0; + for(int p=0;p<mymods.size();p++) + npads+=tpc.getModule(p,0).getNPads(); + cout << "-----> NPads EP0:\t " << npads << endl; + cout << "-----> Inside Module (-150,0):\t "<<tpc.isInsideModule(-150,0,0)<<endl; + cout << "-----> Nearest Module (-150,0):\t "<<tpc.getNearestModule(-150,0,0).getID()<<endl; + cout << "-----> Nearest Module (800,0):\t "<<tpc.getNearestModule(800,0,0).getID()<<endl; + cout << "TPC Module functionality:"<<endl; + + TPCModule mymod=tpc.getModule(4,0); + cout << "-----> Module 4 EP 0 ID:\t " << mymod.getID()<<endl; + cout << "-----> Module 4 Pads:\t " << mymod.getPadType()<<endl; + cout << "-----> Module 4 NPads:\t " << mymod.getNPads()<<endl; + cout << "-----> Module 4 pad rows:\t " << mymod.getNRows()<<endl; + cout << "-----> Module 4 pads in row:\t " << mymod.getNPadsInRow(0)<<endl; + cout << "-----> Module 4 row height:\t " << mymod.getRowHeight(0)<<endl; + cout << "-----> Module 4 pad pitch:\t " << mymod.getPadPitch(1)<<endl; + cout << "-----> Module 4 row number pad 15:\t " << mymod.getRowNumber(15)<<endl; + cout << "-----> Module 4 pad number pad 15:\t " << mymod.getPadNumber(15)<<endl; + cout << "-----> Module 4 pad index (1,5):\t " << mymod.getPadIndex(1,5)<<endl; + cout << "-----> RightNeighbour of 0:\t "<<tpc.getModule(0,0).getRightNeighbour(0)<<endl; + cout << "-----> LeftNeighbour of 3:\t "<<tpc.getModule(0,0).getLeftNeighbour(3)<<endl; + std::vector<double> center1=tpc.getModule(0,0).getPadCenter(10); + cout <<"-----> Center of mod0/pad10 EP0:\t "<<center1[0]<<" "<<center1[1]<<endl; + std::vector<double> center2=tpc.getModule(8,0).getPadCenter(10); + cout <<"-----> Center of mod9/pad10 EP0:\t "<<center2[0]<<" "<<center2[1]<<endl; + cout <<"-----> Nearest Pad 10:\t "<<tpc.getModule(0,0).getNearestPad(tpc.getModule(0,0).getPadCenter(10)[0],tpc.getModule(0,0).getPadCenter(10)[1])<<endl; + cout <<"-----> Nearest Pad 0:\t "<<tpc.getModule(0,0).getNearestPad(tpc.getModule(0,0).getPadCenter(0)[0],tpc.getModule(0,0).getPadCenter(0)[1])<<endl; + cout <<"-----> Nearest Pad 5:\t "<<tpc.getModule(0,0).getNearestPad(tpc.getModule(0,0).getPadCenter(5)[0],tpc.getModule(0,0).getPadCenter(5)[1])<<endl; + cout <<"-----> Nearest Pad 120:\t "<<tpc.getModule(0,0).getNearestPad(tpc.getModule(0,0).getPadCenter(120)[0],tpc.getModule(0,0).getPadCenter(120)[1])<<endl; + + + return 0; +} diff --git a/DDExamples/ILDExReco/src/GearTPC.cpp b/DDExamples/ILDExReco/src/GearTPC.cpp index d6abf1ef7f8bf36a78252ea8d8811ce03ebc9858..dcaebbcca048422f1885614304810b22e7f634df 100644 --- a/DDExamples/ILDExReco/src/GearTPC.cpp +++ b/DDExamples/ILDExReco/src/GearTPC.cpp @@ -86,6 +86,8 @@ namespace DD4hep { TPCModule GearTPC::getModule(int ID, int endplate) const { //ID is defined in the compact xml + if(ID>getNModules(endplate)) + throw OutsideGeometryException("TPC Module not found!"); DetElement ep=getEndPlate(endplate); string myname; std::map<std::string,DetElement>::const_iterator it; @@ -153,8 +155,7 @@ namespace DD4hep { //if not on module, compute distance from point to each shape //FIXME: not sure if this is exact. Sometimes more than one module has the same safety distance. - Tube tube = it->second.volume().solid(); - double dist=tube->Safety(point_local,0); + double dist=it->second.volume().solid()->Safety(point_local,0); if(dist<safe_dist) { safe_dist=dist;