From e600c2373ce1884ea6f2dd3a342f58eaa894f0c9 Mon Sep 17 00:00:00 2001 From: Andrei Gheata <Andrei.Gheata@cern.ch> Date: Mon, 29 Apr 2019 17:03:39 +0200 Subject: [PATCH] Added support for material constant properties, including GDML persistency. --- geom/gdml/inc/TGDMLWrite.h | 2 ++ geom/gdml/src/TGDMLParse.cxx | 43 +++++++++++++++++++++++++------ geom/gdml/src/TGDMLWrite.cxx | 29 +++++++++++++++++++++ geom/geom/inc/TGeoManager.h | 1 + geom/geom/inc/TGeoMaterial.h | 14 ++++++++-- geom/geom/src/TGeoManager.cxx | 18 +++++++++++++ geom/geom/src/TGeoMaterial.cxx | 47 +++++++++++++++++++++++++++++++++- 7 files changed, 143 insertions(+), 11 deletions(-) diff --git a/geom/gdml/inc/TGDMLWrite.h b/geom/gdml/inc/TGDMLWrite.h index 7b19e943562..d0f008aa507 100644 --- a/geom/gdml/inc/TGDMLWrite.h +++ b/geom/gdml/inc/TGDMLWrite.h @@ -140,6 +140,7 @@ private: TString ExtractSolid(TGeoShape* volShape); //adds <shape> to <solids> void ExtractVolumes(TGeoVolume* volume); //result <volume> node... + corresp. shape void ExtractMatrices(TObjArray *matrices); //adds <matrix> to <define> + void ExtractConstants(TGeoManager *geom); //adds <constant> to <define> void ExtractOpticalSurfaces(TObjArray *surfaces); //adds <opticalsurface> to <solids> void ExtractSkinSurfaces(TObjArray *surfaces); //adds <skinsurface> to <structure> void ExtractBorderSurfaces(TObjArray *surfaces); //adds <bordersurface> to <structure> @@ -206,6 +207,7 @@ private: XMLNodePointer_t CreatePositionN(const char * name, Xyz position, const char * type = "position", const char * unit = "cm"); XMLNodePointer_t CreateRotationN(const char * name, Xyz rotation, const char * type = "rotation", const char * unit = "deg"); XMLNodePointer_t CreateMatrixN(TGDMLMatrix const *matrix); + XMLNodePointer_t CreateConstantN(const char *name, Double_t value); TGeoCompositeShape* CreateFakeCtub(TGeoCtub * geoShape); //create fake cut tube as intersection //check name (2nd parameter) whether it is in the list (1st parameter) diff --git a/geom/gdml/src/TGDMLParse.cxx b/geom/gdml/src/TGDMLParse.cxx index 189d6c0abb4..45b92c9f789 100644 --- a/geom/gdml/src/TGDMLParse.cxx +++ b/geom/gdml/src/TGDMLParse.cxx @@ -471,7 +471,9 @@ XMLNodePointer_t TGDMLParse::ConProcess(TXMLEngine* gdml, XMLNodePointer_t node, // name = TString::Format("%s_%s", name.Data(), fCurrentFile); //} - fconsts[name.Data()] = Value(value); + Double_t val = Value(value); + fconsts[name.Data()] = val; + gGeoManager->AddProperty(name.Data(), val); return node; } @@ -1275,8 +1277,9 @@ XMLNodePointer_t TGDMLParse::MatProcess(TXMLEngine* gdml, XMLNodePointer_t node, TGeoManager* mgr = gGeoManager; TGeoElementTable* tab_ele = mgr->GetElementTable(); - TList properties; + TList properties, constproperties; properties.SetOwner(); + constproperties.SetOwner(); // We have to assume the media are monotonic increasing starting with 1 static int medid = mgr->GetListOfMedia()->GetSize()+1; XMLNodePointer_t child = gdml->GetChild(node); @@ -1314,9 +1317,15 @@ XMLNodePointer_t TGDMLParse::MatProcess(TXMLEngine* gdml, XMLNodePointer_t node, else if(tempattr == "ref") { property->SetTitle(gdml->GetAttrValue(attr)); TGDMLMatrix *matrix = fmatrices[property->GetTitle()]; - if (!matrix) - Error("MatProcess", "Reference matrix %s for material %s not found", property->GetTitle(), name.Data()); - properties.Add(property); + if (matrix) properties.Add(property); + else { + Bool_t error = 0; + gGeoManager->GetProperty(property->GetTitle(), &error); + if (error) + Error("MatProcess", "Reference %s for material %s not found", property->GetTitle(), name.Data()); + else + constproperties.Add(property); + } } attr = gdml->GetNextAttr(attr); } @@ -1373,6 +1382,12 @@ XMLNodePointer_t TGDMLParse::MatProcess(TXMLEngine* gdml, XMLNodePointer_t node, while ((property = (TNamed*)next())) mat->AddProperty(property->GetName(), property->GetTitle()); } + if (constproperties.GetSize()) { + TNamed *property; + TIter next(&constproperties); + while ((property = (TNamed*)next())) + mat->AddConstProperty(property->GetName(), property->GetTitle()); + } mixflag = 0; //Note: Object(name, title) corresponds to Element(formula, name) TGeoElement* mat_ele = tab_ele->FindElement(mat_name); @@ -1405,9 +1420,15 @@ XMLNodePointer_t TGDMLParse::MatProcess(TXMLEngine* gdml, XMLNodePointer_t node, else if(tempattr == "ref") { property->SetTitle(gdml->GetAttrValue(attr)); TGDMLMatrix *matrix = fmatrices[property->GetTitle()]; - if (!matrix) - Error("MatProcess", "Reference matrix %s for material %s not found", property->GetTitle(), name.Data()); - properties.Add(property); + if (matrix) properties.Add(property); + else { + Bool_t error = 0; + gGeoManager->GetProperty(property->GetTitle(), &error); + if (error) + Error("MatProcess", "Reference %s for material %s not found", property->GetTitle(), name.Data()); + else + constproperties.Add(property); + } } attr = gdml->GetNextAttr(attr); } @@ -1495,6 +1516,12 @@ XMLNodePointer_t TGDMLParse::MatProcess(TXMLEngine* gdml, XMLNodePointer_t node, while ((property = (TNamed*)next())) mix->AddProperty(property->GetName(), property->GetTitle()); } + if (constproperties.GetSize()) { + TNamed *property; + TIter next(&constproperties); + while ((property = (TNamed*)next())) + mix->AddConstProperty(property->GetName(), property->GetTitle()); + } Int_t natoms; Double_t weight; diff --git a/geom/gdml/src/TGDMLWrite.cxx b/geom/gdml/src/TGDMLWrite.cxx index f6758caa5f1..958d45be607 100644 --- a/geom/gdml/src/TGDMLWrite.cxx +++ b/geom/gdml/src/TGDMLWrite.cxx @@ -354,6 +354,7 @@ void TGDMLWrite::WriteGDMLfile(TGeoManager * geomanager, time_t startT, endT; startT = time(NULL); ExtractMatrices(geomanager->GetListOfGDMLMatrices()); + ExtractConstants(geomanager); fMaterialsNode = ExtractMaterials(materialsLst); Info("WriteGDMLfile", "Extracting volumes"); @@ -402,6 +403,22 @@ void TGDMLWrite::ExtractMatrices(TObjArray* matrixList) } } +//////////////////////////////////////////////////////////////////////////////// +/// Method exporting GDML matrices + +void TGDMLWrite::ExtractConstants(TGeoManager *geom) +{ + if (!geom->GetNproperties()) return; + XMLNodePointer_t constantN; + TString property; + Double_t value; + for (Int_t i = 0; i < geom->GetNproperties(); ++i) { + value = geom->GetProperty(i, property); + constantN = CreateConstantN(property.Data(), value); + fGdmlE->AddChild(fDefineNode, constantN); + } +} + //////////////////////////////////////////////////////////////////////////////// /// Method exporting optical surfaces @@ -1804,6 +1821,18 @@ XMLNodePointer_t TGDMLWrite::CreateMatrixN(TGDMLMatrix const *matrix) return mainN; } +//////////////////////////////////////////////////////////////////////////////// +/// Creates "constant" kind of node for GDML + +XMLNodePointer_t TGDMLWrite::CreateConstantN(const char *name, Double_t value) +{ + XMLNodePointer_t mainN = fGdmlE->NewChild(0, 0, "constant", 0); + const TString fltPrecision = TString::Format("%%.%dg", fFltPrecision); + fGdmlE->NewAttr(mainN, 0, "name", name); + fGdmlE->NewAttr(mainN, 0, "value", TString::Format(fltPrecision.Data(), value)); + return mainN; +} + //////////////////////////////////////////////////////////////////////////////// /// Creates "setup" node for GDML diff --git a/geom/geom/inc/TGeoManager.h b/geom/geom/inc/TGeoManager.h index 51fdd36c0d2..c8f40e40abd 100644 --- a/geom/geom/inc/TGeoManager.h +++ b/geom/geom/inc/TGeoManager.h @@ -177,6 +177,7 @@ public: TGeoNavigator *AddNavigator(); Bool_t AddProperty(const char *property, Double_t value); Double_t GetProperty(const char *name, Bool_t *error = nullptr) const; + Double_t GetProperty(size_t i, TString &name, Bool_t *error = nullptr) const; Int_t GetNproperties() const { return fProperties.size(); } void ClearOverlaps(); void RegisterMatrix(const TGeoMatrix *matrix); diff --git a/geom/geom/inc/TGeoMaterial.h b/geom/geom/inc/TGeoMaterial.h index 5325832f10c..c6dc87e7f85 100644 --- a/geom/geom/inc/TGeoMaterial.h +++ b/geom/geom/inc/TGeoMaterial.h @@ -54,6 +54,7 @@ protected: TObject *fCerenkov; // pointer to class with Cerenkov properties TGeoElement *fElement; // pointer to element composing the material TList fProperties; // user-defined properties + TList fConstProperties; // user-defined constant properties TGeoExtension *fUserExtension; //! Transient user-defined extension to materials TGeoExtension *fFWExtension; //! Transient framework-defined extension to materials @@ -81,8 +82,17 @@ public: virtual void FillMaterialEvolution(TObjArray *population, Double_t precision=0.001); // getters & setters bool AddProperty(const char *property, const char *ref); - const char *GetPropertyRef(const char *property); + bool AddConstProperty(const char *property, const char *ref); + Int_t GetNproperties() const { return fProperties.GetSize(); } + Int_t GetNconstProperties() const { return fConstProperties.GetSize(); } + const char *GetPropertyRef(const char *property) const; + const char *GetPropertyRef(Int_t i) const { return (fProperties.At(i) ? fProperties.At(i)->GetTitle() : nullptr); } + Double_t GetConstProperty(const char *property, Bool_t *error = nullptr) const; + Double_t GetConstProperty(Int_t i, Bool_t *error = nullptr) const; + const char *GetConstPropertyRef(const char *property) const; + const char *GetConstPropertyRef(Int_t i) const { return (fConstProperties.At(i) ? fConstProperties.At(i)->GetTitle() : nullptr); } TList const &GetProperties() const { return fProperties; } + TList const &GetConstProperties() const { return fConstProperties; } virtual Int_t GetByteCount() const {return sizeof(*this);} virtual Double_t GetA() const {return fA;} virtual Double_t GetZ() const {return fZ;} @@ -128,7 +138,7 @@ public: - ClassDef(TGeoMaterial, 6) // base material class + ClassDef(TGeoMaterial, 7) // base material class //***** Need to add classes and globals to LinkDef.h ***** }; diff --git a/geom/geom/src/TGeoManager.cxx b/geom/geom/src/TGeoManager.cxx index d4eaf3ae03b..066ce7e5b5c 100644 --- a/geom/geom/src/TGeoManager.cxx +++ b/geom/geom/src/TGeoManager.cxx @@ -776,6 +776,24 @@ Double_t TGeoManager::GetProperty(const char *property, Bool_t *error) const return pos->second; } +//////////////////////////////////////////////////////////////////////////////// +/// Get a user-defined property from a given index + +Double_t TGeoManager::GetProperty(size_t i, TString &name, Bool_t *error) const +{ + // This is a quite inefficient way to access map elements, but needed for the GDML writer to + if (i >= fProperties.size()) { + if (error) *error = kTRUE; + return 0.; + } + size_t pos = 0; + auto it = fProperties.begin(); + while (pos < i) { ++it; ++pos; } + if (error) *error = kFALSE; + name = (*it).first; + return (*it).second; +} + //////////////////////////////////////////////////////////////////////////////// /// Add a matrix to the list. Returns index of the matrix in list. diff --git a/geom/geom/src/TGeoMaterial.cxx b/geom/geom/src/TGeoMaterial.cxx index c3207756d29..84feabbf717 100644 --- a/geom/geom/src/TGeoMaterial.cxx +++ b/geom/geom/src/TGeoMaterial.cxx @@ -286,13 +286,45 @@ void TGeoMaterial::SetUserExtension(TGeoExtension *ext) } //_____________________________________________________________________________ -const char *TGeoMaterial::GetPropertyRef(const char *property) +const char *TGeoMaterial::GetPropertyRef(const char *property) const { // Find reference for a given property TNamed *prop = (TNamed*)fProperties.FindObject(property); return (prop) ? prop->GetTitle() : nullptr; } +//_____________________________________________________________________________ +const char *TGeoMaterial::GetConstPropertyRef(const char *property) const +{ + // Find reference for a given constant property + TNamed *prop = (TNamed*)fConstProperties.FindObject(property); + return (prop) ? prop->GetTitle() : nullptr; +} + +//_____________________________________________________________________________ +Double_t TGeoMaterial::GetConstProperty(const char *property, Bool_t *err) const +{ + // Find reference for a given constant property + TNamed *prop = (TNamed*)fConstProperties.FindObject(property); + if (!prop) { + if (err) *err = kTRUE; + return 0.; + } + return gGeoManager->GetProperty(prop->GetTitle(), err); +} + +//_____________________________________________________________________________ +Double_t TGeoMaterial::GetConstProperty(Int_t i, Bool_t *err) const +{ + // Find reference for a given constant property + TNamed *prop = (TNamed*)fConstProperties.At(i); + if (!prop) { + if (err) *err = kTRUE; + return 0.; + } + return gGeoManager->GetProperty(prop->GetTitle(), err); +} + //_____________________________________________________________________________ bool TGeoMaterial::AddProperty(const char *property, const char *ref) { @@ -306,6 +338,19 @@ bool TGeoMaterial::AddProperty(const char *property, const char *ref) return true; } +//_____________________________________________________________________________ +bool TGeoMaterial::AddConstProperty(const char *property, const char *ref) +{ + fConstProperties.SetOwner(); + if (GetConstPropertyRef(property)) { + Error("AddConstProperty", "Constant property %s already added to material %s", + property, GetName()); + return false; + } + fConstProperties.Add(new TNamed(property, ref)); + return true; +} + //////////////////////////////////////////////////////////////////////////////// /// Connect framework defined extension to the material. The material "grabs" a copy, /// so the original object can be released by the producer. Release the previously -- GitLab