diff --git a/GeoModelExamples/CMakeLists.txt b/GeoModelExamples/CMakeLists.txt index 0484346f4ef61f7fecfdd6c38ac9fcccf27b2cbc..4f322aa26a3cb5b1d88345c6fe778b7deba9129f 100644 --- a/GeoModelExamples/CMakeLists.txt +++ b/GeoModelExamples/CMakeLists.txt @@ -11,10 +11,14 @@ project( "GeoModelExamples" VERSION 4.1.0 LANGUAGES CXX ) # Getting-started examples add_subdirectory( KitchenSinkPlugin ) +add_subdirectory( MinimalPlugin ) add_subdirectory( HelloGeo ) add_subdirectory( HelloGeoWrite ) -#add_subdirectory( HelloGeoRead ) +add_subdirectory( HelloGeoWriteReadWrite ) +add_subdirectory( HelloGeoRead ) +add_subdirectory( HelloGeoReadNodeAction ) + #add_subdirectory( HelloDummyMaterial ) #add_subdirectory( HelloToy ) #add_subdirectory( HelloToyDetectorFactory ) diff --git a/GeoModelExamples/HelloGeoRead/main.cpp b/GeoModelExamples/HelloGeoRead/main.cpp index afd8567165d297ab23f7ae4780c57f38c028ce17..00765ec207682ef11689d1d56d713b07442c1636 100644 --- a/GeoModelExamples/HelloGeoRead/main.cpp +++ b/GeoModelExamples/HelloGeoRead/main.cpp @@ -1,4 +1,4 @@ -// Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration +// Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration /* * HelloGeo.cpp @@ -66,25 +66,35 @@ GeoPhysVol* createTheWorld(GeoPhysVol* world) int main(int argc, char *argv[]) { - // QCoreApplication app(argc, argv); - // GET GEOMETRY FROM LOCAL DB - // Set valid db path before first run - const std::string path = "geometry.db"; - std::cout << "Using this DB file:" << path << std::endl; + if(argc != 2) + { + fprintf(stderr, "\nERROR!\nusage: %s input.db\n\n", argv[0]); + return 1; + } + // Get the input SQLite '.db' file containing the geometry + std::string line; + std::string fileName; + fileName = argv[1]; + std::cout << "Using this SQLite '.db' file:" << fileName << std::endl; + // check if DB file exists. If not, return. // FIXME: TODO: this check should go in the 'GMDBManager' constructor. - std::ifstream infile(path.c_str()); + std::ifstream infile(fileName.c_str()); if ( ! infile.good() ) { - std::cout << "\n\tERROR!! A '" << path << "' file does not exist!! Please, check the path of the input file before running this program. Exiting..."; + std::cout << "\n\tERROR!! A '" << fileName << "' file does not exist!! Please, check the path of the input file before running this program. Exiting..."; exit(EXIT_FAILURE); } infile.close(); + + + // GET GEOMETRY FROM LOCAL DB + // open the DB - GMDBManager* db = new GMDBManager(path); + GMDBManager* db = new GMDBManager(fileName); /* Open database */ if (db->checkIsDBOpen()) { std::cout << "OK! Database is open!\n"; diff --git a/GeoModelExamples/HelloGeoReadNodeAction/CMakeLists.txt b/GeoModelExamples/HelloGeoReadNodeAction/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..68ce5cafcd820bc195654e8f1747a7969ed43ee3 --- /dev/null +++ b/GeoModelExamples/HelloGeoReadNodeAction/CMakeLists.txt @@ -0,0 +1,35 @@ +# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration + +################################################################################ +# Package: HelloGeoReadNodeAction +# author: Riccardo Maria BIANCHI @ CERN - May, 2022 +################################################################################ + +cmake_minimum_required(VERSION 3.1.0) + +#project(HelloGeoRead) + +# Compile with C++17 +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS ON) + +# Find the needed dependencies, when building individually +if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) + find_package( GeoModelCore REQUIRED ) + find_package( GeoModelIO REQUIRED ) +endif() + +# Find includes in current dir +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +# Populate a CMake variable with the sources +FILE(GLOB SRCS *.cxx) +FILE(GLOB HEADERS *.h) + + +# Tell CMake to create the helloworld executable +add_executable( hellogeoReadNodeAction ${HEADERS} ${SRCS} ) + +# Link all needed libraries +target_link_libraries( hellogeoReadNodeAction GeoModelIO::GeoModelRead GeoModelCore::GeoModelKernel) diff --git a/GeoModelExamples/HelloGeoReadNodeAction/GeoInventoryGraphAction.cxx b/GeoModelExamples/HelloGeoReadNodeAction/GeoInventoryGraphAction.cxx new file mode 100644 index 0000000000000000000000000000000000000000..7852fe2c352a5688b491458e98fc6d026db28e16 --- /dev/null +++ b/GeoModelExamples/HelloGeoReadNodeAction/GeoInventoryGraphAction.cxx @@ -0,0 +1,115 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "GeoInventoryGraphAction.h" + +GeoInventoryGraphAction::GeoInventoryGraphAction (std::ostream &o) + : m_nameTag(nullptr) + , m_serialDenominator(nullptr) + , m_idTag(nullptr) + , m_transformState(true) + , m_volumeState(true) + , m_nametagState(true) + , m_serialDenominatorState(true) + , m_serialTransformerState(true) + , m_identifierState(true) + , m_o(o) + , m_indented(false) +{ +} + +GeoInventoryGraphAction::~GeoInventoryGraphAction() +{ +} + +void GeoInventoryGraphAction::handleTransform (const GeoTransform *xform) +{ + m_pendingTransformList.push_back(xform); + if (m_transformState) { + indent(); + m_o << "XF(" << xform << ")"; + } +} + +void GeoInventoryGraphAction::handlePhysVol (const GeoPhysVol *vol) +{ + if (m_volumeState) { + indent(); + m_o << "PV(" << vol << "),LV(" << vol->getLogVol()<< "),lvname=" << vol->getLogVol()->getName() << std::endl; + } + m_pendingTransformList.erase(m_pendingTransformList.begin(),m_pendingTransformList.end()); + m_indented=false; +} + +void GeoInventoryGraphAction::handleFullPhysVol (const GeoFullPhysVol *vol) +{ + if (m_volumeState) { + indent(); + m_o << "FPV(" << vol << "),LV(" << vol->getLogVol()<< "),lvname=" << vol->getLogVol()->getName() << std::endl; + } + m_pendingTransformList.erase(m_pendingTransformList.begin(),m_pendingTransformList.end()); + m_indented=false; +} + +void GeoInventoryGraphAction::handleNameTag (const GeoNameTag *nameTag) +{ + if (m_nametagState) { + indent(); + m_o << "NT("<<nameTag <<")" << nameTag->getName() << "+"; + } +} + +void GeoInventoryGraphAction::handleSerialDenominator (const GeoSerialDenominator *sD) +{ + if (m_nametagState) { + indent(); + m_o << "SD("<< sD <<")" << sD->getBaseName() << "+"; + } +} + +void GeoInventoryGraphAction::handleSerialTransformer (const GeoSerialTransformer *sT) +{ + if (m_volumeState) { + indent(); + m_o << sT->getNCopies() << " PARAMETERIZED VOLUMES(" << sT->getVolume()->getLogVol()->getName() << ")" << std::endl; + } + m_pendingTransformList.erase(m_pendingTransformList.begin(),m_pendingTransformList.end()); + m_indented=false; +} + +void GeoInventoryGraphAction::handleIdentifierTag (const GeoIdentifierTag *idTag) +{ + if (m_identifierState) { + indent(); + m_o << "ID(" << idTag <<")" << idTag->getIdentifier() << "+"; + } +} + +void GeoInventoryGraphAction::setNotification (Type type, bool state) +{ + if (type==TRANSFORM) { + m_transformState=state; + } + else if (type==VOLUME) { + m_volumeState=state; + } + else if (type==NAMETAG) { + m_nametagState=state; + } + else if (type==IDENTIFIERTAG) { + m_identifierState=state; + } +} + +void GeoInventoryGraphAction::indent () +{ + if (!m_indented) { + m_indented=true; + for (size_t i=0;i<getPath()->getLength(); i++) { + m_o << " "; + } + } +} + + diff --git a/GeoModelExamples/HelloGeoReadNodeAction/GeoInventoryGraphAction.h b/GeoModelExamples/HelloGeoReadNodeAction/GeoInventoryGraphAction.h new file mode 100644 index 0000000000000000000000000000000000000000..e960fdce279ca7ba9fbe8dce92ccc37a5c8bb876 --- /dev/null +++ b/GeoModelExamples/HelloGeoReadNodeAction/GeoInventoryGraphAction.h @@ -0,0 +1,102 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#ifndef GEOMODELKERNEL_GEOPRINTGRAPHACTION_H +#define GEOMODELKERNEL_GEOPRINTGRAPHACTION_H + +/** + * @class GeoInventoryGraphAction + * + * @brief This action prints the node tree. It can be configured + * to print a message on the following types of nodes: + * * Transforms + * * Physical Volumes and Full Physical Volumes + * * SerialDenominators + * * SerialTransforms + * * IdentifierTag + */ + +#include "GeoModelKernel/GeoNodeAction.h" +#include <iostream> + +class GeoInventoryGraphAction : public GeoNodeAction +{ + enum Type { TRANSFORM, + VOLUME, + NAMETAG, + IDENTIFIERTAG}; + public: + GeoInventoryGraphAction (std::ostream &o); + virtual ~GeoInventoryGraphAction(); + + // Handles a Transform. + virtual void handleTransform (const GeoTransform *xform); + + // Handles a physical volume. + virtual void handlePhysVol (const GeoPhysVol *vol); + + // Handles a physical volume. + virtual void handleFullPhysVol (const GeoFullPhysVol *vol); + + // Handles a Name Tag. + virtual void handleNameTag (const GeoNameTag *nameTag); + + // Handles a Serial Denominator. + virtual void handleSerialDenominator (const GeoSerialDenominator *sD); + + // Handles a Serial Transformer + virtual void handleSerialTransformer (const GeoSerialTransformer *sT); + + // Handles an Identifier Tag. + virtual void handleIdentifierTag (const GeoIdentifierTag *idTag); + + // Sets the notification state. Default: everything on. + void setNotification (Type type, bool state); + + private: + GeoInventoryGraphAction(const GeoInventoryGraphAction &right); + GeoInventoryGraphAction & operator=(const GeoInventoryGraphAction &right); + + // Indent the print. + void indent (); + + // A pointer to a name tag. If the volume is named. + const GeoNameTag *m_nameTag; + + // A pointer to a serial denominator. If one exists. + const GeoSerialDenominator *m_serialDenominator; + + // A pointer to an identifier tag. If the volume is + // identified. + const GeoIdentifierTag *m_idTag; + + // List of Pending Transformations. + std::vector<const GeoTransform *> m_pendingTransformList; + + // On/off flag for transforms. + bool m_transformState; + + // On/off flag for physical volumes. + bool m_volumeState; + + // On/off flag for name tags. + bool m_nametagState; + + // On/off flag for serial denominators. + bool m_serialDenominatorState; + + // On/off flag for serial transformers. + bool m_serialTransformerState; + + // On/off flag for identifier tags. + bool m_identifierState; + + std::ostream &m_o; + + // Flag for indent (intially 0) + mutable bool m_indented; +}; + + +#endif diff --git a/GeoModelExamples/HelloGeoReadNodeAction/README.md b/GeoModelExamples/HelloGeoReadNodeAction/README.md new file mode 100644 index 0000000000000000000000000000000000000000..8bfbbf64e13d6c6c767c9eb9193ec744f5ff8e7e --- /dev/null +++ b/GeoModelExamples/HelloGeoReadNodeAction/README.md @@ -0,0 +1,82 @@ +# The 'helloGeoRead' GeoModel example + +The `helloGeoRead` example shows you how to read persistified GeoModel data in a standalone program. + +The example program: + + 1. loads the geometry from the `.db` file + 2. prints all GeoMaterial entries found in the `.db` + 3. builds the GeoModel tree, storing it in memory + 4. gets the RootVolume of the GeoModel tree and it prints out the number of its children + 5. loops over all the RootVolume's children volumes (GeoPhysVol and GeoFullPhysVol instances), printing the name of the GeoLogVol associated to them + + The example program uses many of the GeoModel packages. + + +## Dependencies + +### Install Qt5 + +To build and run GeoModel libraries, you must have a working Qt5 installation on your computer. +If you are not sure how to install it, please take a look at the Appendix on Qt5, below. + +### Build GeoModelCore + +```bash +git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelCore.git +mkdir build_gmcore +cd build_gmcore +cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelCore +make -j 4 +make install +``` + +### Build GeoModelIO + +```bash +git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelIO.git +mkdir build_gmio +cd build_gmio +cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelIO +make -j 4 +make install +``` + +## Build + +From your work folder: + +```bash +git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelExamples.git +mkdir build_hellogeoRead +cd build_hellogeoRead +cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelExamples/HelloGeoRead +make -j4 +make install +``` + +## Run + +Get sample geometry data to play with: + +```bash +wget https://atlas-vp1.web.cern.ch/atlas-vp1/doc_new/sample_datafiles/geometry/geometry-ATLAS-R2-2015-03-01-00.db +ln -s $PWD/geometry-ATLAS-R2-2015-03-01-00.db ../geometry.db +``` + +Now, you can run the example by typing: + +```bash +./hellogeoRead +``` + + + ---- + +## Appendix + +### Notes on Qt5 + +To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. Qt5 classes are used for I/O operations with the underlying SQLite daemon, to store/handle data, and to handle logging. + +If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/master/README_QT5_NOTES.md). diff --git a/GeoModelExamples/HelloGeoReadNodeAction/main.cxx b/GeoModelExamples/HelloGeoReadNodeAction/main.cxx new file mode 100644 index 0000000000000000000000000000000000000000..0107074b3c99c1ba1307d02b45a43cc8d141a0db --- /dev/null +++ b/GeoModelExamples/HelloGeoReadNodeAction/main.cxx @@ -0,0 +1,191 @@ +// Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration + +/* + * HelloGeo.cpp + * + * Author: Riccardo Maria BIANCHI @ CERN + * Created on: May, 2022 + * + */ + +// local includes +#include "GeoInventoryGraphAction.h" + +// GeoModel includes +#include "GeoModelDBManager/GMDBManager.h" +#include "GeoModelRead/ReadGeoModel.h" +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelKernel/GeoFullPhysVol.h" +#include "GeoModelKernel/GeoNameTag.h" + +// C++ includes +#include <iostream> +#include <fstream> +#include <cstdlib> // EXIT_FAILURE + + +// Units +#include "GeoModelKernel/Units.h" +#define SYSTEM_OF_UNITS GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm' + + +GeoPhysVol* createTheWorld(GeoPhysVol* world) +{ + if (world == nullptr) + { + //-----------------------------------------------------------------------------------// + // Define the materials that we shall use. // + // ----------------------------------------------------------------------------------// + + // Define the units + #define gr SYSTEM_OF_UNITS::gram + #define mole SYSTEM_OF_UNITS::mole + #define cm3 SYSTEM_OF_UNITS::cm3 + + // Define the chemical elements + GeoElement* Nitrogen = new GeoElement ("Nitrogen" ,"N" , 7.0 , 14.0067 *gr/mole); + GeoElement* Oxygen = new GeoElement ("Oxygen" ,"O" , 8.0 , 15.9995 *gr/mole); + GeoElement* Argon = new GeoElement ("Argon" ,"Ar" , 18.0 , 39.948 *gr/mole); + GeoElement* Hydrogen = new GeoElement ("Hydrogen" ,"H" , 1.0 , 1.00797 *gr/mole); + + // Define the materials + double densityOfAir=0.001214 *gr/cm3; + GeoMaterial *air = new GeoMaterial("Air", densityOfAir); + air->add(Nitrogen , 0.7494); + air->add(Oxygen, 0.2369); + air->add(Argon, 0.0129); + air->add(Hydrogen, 0.0008); + air->lock(); + + const GeoBox* worldBox = new GeoBox(1000*SYSTEM_OF_UNITS::cm, 1000*SYSTEM_OF_UNITS::cm, 1000*SYSTEM_OF_UNITS::cm); + const GeoLogVol* worldLog = new GeoLogVol("WorldLog", worldBox, air); + world = new GeoPhysVol(worldLog); + } + return world; +} + + + +int main(int argc, char *argv[]) +{ + + if(argc != 2) + { + fprintf(stderr, "\nERROR!\nusage: %s input.db\n\n", argv[0]); + return 1; + } + // Get the input SQLite '.db' file containing the geometry + std::string line; + std::string fileName; + fileName = argv[1]; + std::cout << "Using this SQLite '.db' file:" << fileName << std::endl; + + + // check if DB file exists. If not, return. + // FIXME: TODO: this check should go in the 'GMDBManager' constructor. + std::ifstream infile(fileName.c_str()); + if ( ! infile.good() ) { + std::cout << "\n\tERROR!! A '" << fileName << "' file does not exist!! Please, check the path of the input file before running this program. Exiting..."; + exit(EXIT_FAILURE); + } + infile.close(); + + + // GET GEOMETRY FROM LOCAL DB + + + + // open the DB + GMDBManager* db = new GMDBManager(fileName); + /* Open database */ + if (db->checkIsDBOpen()) { + std::cout << "OK! Database is open!\n"; + } + else { + std::cout << "Database is not open!\n"; + // return; + throw; + } + + // -- testing the input database +// std::cout << "Printing the list of all GeoMaterial nodes" << std::endl; +// db->printAllMaterials(); +// std::cout << "Printing the list of all GeoElement nodes" << std::endl; +// db->printAllElements(); + + /* setup the GeoModel reader */ + GeoModelIO::ReadGeoModel geoReader = GeoModelIO::ReadGeoModel(db); + std::cout << "OK! ReadGeoModel is set." << std::endl; + + + /* build the GeoModel geometry */ + GeoPhysVol* dbPhys = geoReader.buildGeoModel(); // builds the whole GeoModel tree in memory + std::cout << "ReadGeoModel::buildGeoModel() done." << std::endl; + + std::cout << "Reading records from the imported geometry DB file..." << std::endl; + geoReader.printDBTable("SerialIdentifiers"); + geoReader.printDBTable("IdentifierTags"); + + + // create the world volume container and + // get the 'world' volume, i.e. the root volume of the GeoModel tree + std::cout << "Getting the 'world' GeoPhysVol, i.e. the root volume of the GeoModel tree" << std::endl; + GeoPhysVol* world = createTheWorld(dbPhys); + std::cout << "Getting the GeoLogVol used by the 'world' volume" << std::endl; + const GeoLogVol* logVol = world->getLogVol(); + std::cout << "'world' GeoLogVol name: " << logVol->getName() << std::endl; + std::cout << "'world' GeoMaterial name: " << logVol->getMaterial()->getName() << std::endl; + + + // --- testing the imported Geometry + + // get number of children volumes + unsigned int nChil = world->getNChildVols(); + std:: cout << "'world' number of children: " << nChil << std::endl; + + // loop over all children nodes + std::cout << "Looping over all 'volume' children (i.e., GeoPhysVol and GeoFullPhysVol)..." << std::endl; + for (unsigned int idx=0; idx<nChil; ++idx) { + PVConstLink nodeLink = world->getChildVol(idx); + + if ( dynamic_cast<const GeoVPhysVol*>( &(*( nodeLink ))) ) { + + std::cout << "\t" << "the child n. " << idx << " "; + const GeoVPhysVol *childVolV = &(*( nodeLink )); + + if ( dynamic_cast<const GeoPhysVol*>(childVolV) ) { + const GeoPhysVol* childVol = dynamic_cast<const GeoPhysVol*>(childVolV); + std::cout << "is a GeoPhysVol, whose GeoLogVol name is: " << childVol->getLogVol()->getName(); + std::cout<< " and it has "<<childVol->getNChildVols()<<" child volumes" << std::endl; + } + else if ( dynamic_cast<const GeoFullPhysVol*>(childVolV) ) { + const GeoFullPhysVol* childVol = dynamic_cast<const GeoFullPhysVol*>(childVolV); + std::cout << "is a GeoFullPhysVol, whose GeoLogVol name is: " << childVol->getLogVol()->getName(); + std::cout<< " and it has "<<childVol->getNChildVols()<<" child volumes" << std::endl; + } + } + else if ( dynamic_cast<const GeoNameTag*>( &(*( nodeLink ))) ) { + std::cout << "\t" << "the child n. " << idx << " is a GeoNameTag" << std::endl; + const GeoNameTag *childVol = dynamic_cast<const GeoNameTag*>(&(*( nodeLink ))); + std::cout << "\t\t GeoNameTag's name: " << childVol->getName() << std::endl; + } + else if ( dynamic_cast<const GeoMaterial*>( &(*( nodeLink ))) ) { + std::cout << "\t" << "the child n. " << idx << " is a GeoMaterial" << std::endl; + const GeoMaterial *childVol = dynamic_cast<const GeoMaterial*>(&(*( nodeLink ))); + std::cout << "\t\t GeoMaterial's name: " << childVol->getName() << std::endl; + std::cout << "\t\t GeoMaterial's number of elements: " << childVol->getNumElements() << std::endl; + } + } + + + GeoInventoryGraphAction action(std::cout); + world->exec(&action); + + + + std::cout << "Everything done." << std::endl; + + // return app.exec(); + return 0; +} diff --git a/GeoModelExamples/HelloGeoWriteReadWrite/CMakeLists.txt b/GeoModelExamples/HelloGeoWriteReadWrite/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..c10f7fc3e210175d4862acbbab7818af720fa268 --- /dev/null +++ b/GeoModelExamples/HelloGeoWriteReadWrite/CMakeLists.txt @@ -0,0 +1,32 @@ +# Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration + +################################################################################ +# Package: HelloGeoWriteReadWrite +# author: Riccardo Maria BIANCHI @ CERN - May, 2022 +################################################################################ + +cmake_minimum_required(VERSION 3.1.0) + +#project(HelloGeoWrite) + +# Compile with C++17 +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS ON) + +if(CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) # when building individually + find_package( GeoModelCore REQUIRED ) + find_package( GeoModelIO REQUIRED ) +endif() + +# Find includes in current dir +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +# Populate a CMake variable with the sources +set(SRCS main.cpp ) + +# Tell CMake to create the helloworld executable +add_executable( hellogeoWriteReadWrite ${SRCS} ) + +# Link all needed libraries +target_link_libraries( hellogeoWriteReadWrite GeoModelCore::GeoModelKernel GeoModelIO::GeoModelWrite GeoModelIO::GeoModelRead) diff --git a/GeoModelExamples/HelloGeoWriteReadWrite/README.md b/GeoModelExamples/HelloGeoWriteReadWrite/README.md new file mode 100644 index 0000000000000000000000000000000000000000..f9d98f364d3ae07f54458cb6e3312559e0467d33 --- /dev/null +++ b/GeoModelExamples/HelloGeoWriteReadWrite/README.md @@ -0,0 +1,74 @@ +# The 'helloGeoWrite' GeoModel example + +The `helloGeoWrite` example shows you how to create a simple geometry, by using GeoModel nodes. + +The example program: + + 1. Builds an example geometry: + 2. Writes the geometry to an SQLite file + 3. It accesses the persistent copy of the geometry, as a test + + +## Dependencies + +### Install Qt5 + +To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. +If you are not sure how to install it, please take a look at the Appendix, below. + + +#### GeoModelCore + +```bash +git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelCore.git +mkdir build_gmcore +cd build_gmcore +cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelCore +make -j 4 +make install +cd .. +``` + +#### GeoModelIO + +```bash +git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelIO.git +mkdir build_gmio +cd build_gmio +cmake -DCMAKE_INSTALL_PREFIX=../install -DCMAKE_BUILD_TYPE=RelWithDebInfo ../GeoModelIO +make -j 4 +make install +``` + + + +## Build + +From your work folder: + +```bash +git clone ssh://git@gitlab.cern.ch:7999/GeoModelDev/GeoModelExamples.git +mkdir build_hellogeo +cd build_hellogeo +cmake -DCMAKE_INSTALL_PREFIX=../install ../GeoModelExamples/HelloGeoWrite/ +make -j4 +``` + +## Run + +Now, you can **run the example** by typing: + +```bash +./hellogeoWrite +``` + + +---- + +## Appendix + +### Notes on Qt5 + +To build and run GeoModel I/O libraries, you must have a working Qt5 installation on your computer. Qt5 classes are used for I/O operations with the underlying SQLite daemon, to store/handle data, and to handle logging. + +If you are not sure how to install it, please take a look at [the notes on Qt5, in the GeoModelIO repository](https://gitlab.cern.ch/GeoModelDev/GeoModelIO/blob/master/README_QT5_NOTES.md). diff --git a/GeoModelExamples/HelloGeoWriteReadWrite/main.cpp b/GeoModelExamples/HelloGeoWriteReadWrite/main.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8e2051a5fb1cf9a4473aa365a94f99238607bfa4 --- /dev/null +++ b/GeoModelExamples/HelloGeoWriteReadWrite/main.cpp @@ -0,0 +1,233 @@ +// Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration + +/* + * This example writes a sample geometry, reads it back in, then writes it again. + * It is meant to test the GeoModel I/O packages and methods. + * + * Author: Riccardo Maria BIANCHI @ CERN + * Created on: May, 2022 + * + */ + +// GeoModel includes +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoTube.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelKernel/GeoFullPhysVol.h" +#include "GeoModelKernel/GeoNameTag.h" +#include "GeoModelDBManager/GMDBManager.h" +#include "GeoModelWrite/WriteGeoModel.h" +#include "GeoModelRead/ReadGeoModel.h" + +// C++ includes +#include <iostream> +#include <fstream> +#include <cstdlib> // EXIT_FAILURE + + +// Units +#include "GeoModelKernel/Units.h" +#define SYSTEM_OF_UNITS GeoModelKernelUnits // so we will get, e.g., 'GeoModelKernelUnits::cm' + + +int main(int argc, char *argv[]) +{ + //-----------------------------------------------------------------------------------// + // Define the materials that we shall use. // + // ----------------------------------------------------------------------------------// + + // Define the units + #define gr SYSTEM_OF_UNITS::gram + #define mole SYSTEM_OF_UNITS::mole + #define cm3 SYSTEM_OF_UNITS::cm3 + + // Define the chemical elements + GeoElement* Nitrogen = new GeoElement ("Nitrogen" ,"N" , 7.0 , 14.0067 *gr/mole); + GeoElement* Oxygen = new GeoElement ("Oxygen" ,"O" , 8.0 , 15.9995 *gr/mole); + GeoElement* Argon = new GeoElement ("Argon" ,"Ar" , 18.0 , 39.948 *gr/mole); + GeoElement* Hydrogen = new GeoElement ("Hydrogen" ,"H" , 1.0 , 1.00797 *gr/mole); + GeoElement* Iron = new GeoElement ("Iron" ,"Fe" , 26.0 , 55.847 *gr/mole); + GeoElement* Carbon = new GeoElement ("Carbon" ,"C" , 6.0 , 12.0107 *gr/mole); + GeoElement* Sillicon = new GeoElement ("Silicon" ,"Si" , 14.0 , 28.085 *gr/mole); + + // Define the materials + + double densityOfAir=0.001214 *gr/cm3; + GeoMaterial *air = new GeoMaterial("Air", densityOfAir); + air->add(Nitrogen , 0.7494); + air->add(Oxygen, 0.2369); + air->add(Argon, 0.0129); + air->add(Hydrogen, 0.0008); + air->lock(); + + + //-----------------------------------------------------------------------------------// + // create the world volume container and + // get the 'world' volume, i.e. the root volume of the GeoModel tree + std::cout << "Creating the 'world' volume, i.e. the root volume of the GeoModel tree..." << std::endl; + const GeoBox* worldBox = new GeoBox(1000*SYSTEM_OF_UNITS::cm, 1000*SYSTEM_OF_UNITS::cm, 1000*SYSTEM_OF_UNITS::cm); + const GeoLogVol* worldLog = new GeoLogVol("WorldLog", worldBox, air); + GeoPhysVol* world = new GeoPhysVol(worldLog); + + + const double degree=M_PI/180.0; + + // Define elements used in this example: + GeoElement *aluminium = new GeoElement("Aluminium", "Al", 13, 26 * gr/mole ); + + // Define materials: + // Define Aluminium + double densityOfAluminium=2.7; // g/cm^3 + GeoMaterial *Aluminium = new GeoMaterial("Aluminium", densityOfAluminium); + Aluminium->add(aluminium,1.0); + Aluminium->lock(); + + // Some dimensions used below: + double platformHeight=34.5; // Height to the top of the flanges + //double flangeDiameter=3.375; // Diameter of the flanges + double flangeThickness=3.0/16.0; // Thickness of the flanges + double t1TubeLength = platformHeight-flangeThickness; // Overall length of tube t1; + double innerRadius=0.75/2.0; // 3/4 inch (inner diameter) pipe + double outerRadius=(17.0/16.0)/2.0; // 1-1/16 (outer diameter) + double leftRightLegSeparation=61.0+11.0/16.0; // Distance between legs, in x. + double frontBackLegSeparation=19.0+3.0/4.0; // Distance between legs, in y. + //const double barWidth1=4.0; // Width of front-back primary support + //const double barWidth2=3.0; // Width of secondary aluminium support + //double barThickness =1.25; // Thickness of Aluminium bars + //double cutoutDepth = 21.5; // Depth of the cutout hole + //double cutoutWidth = 32.375; // Width of the cutout hole + + // Add the four legs of the kitchen sink: + { + const GeoTube *t1Tube = new GeoTube(innerRadius,outerRadius, t1TubeLength/2.0); + const GeoLogVol *t1Log = new GeoLogVol("T1Log", t1Tube, Aluminium); + const GeoLogVol *t2Log = new GeoLogVol("T2Log", t1Tube, Aluminium); + GeoPhysVol *t1Phys = new GeoPhysVol(t1Log); + GeoPhysVol *t2Phys = new GeoPhysVol(t2Log); + //GeoPhysVol *t3Phys = new GeoPhysVol(t1Log); + GeoTransform *xform1 = new GeoTransform(GeoTrf::Translate3D(leftRightLegSeparation/2.0, frontBackLegSeparation/2.0, 0)); + GeoTransform *xform2 = new GeoTransform(GeoTrf::Translate3D(leftRightLegSeparation/2.0, -frontBackLegSeparation/2.0, 0)); + GeoTransform *xform3 = new GeoTransform(GeoTrf::Translate3D(-leftRightLegSeparation/2.0, -frontBackLegSeparation/2.0, 0)); + //GeoTransform *xform4 = new GeoTransform(GeoTrf::Translate3D(-leftRightLegSeparation/2.0, frontBackLegSeparation/2.0, 0)); + world->add(xform1); + + world->add(t1Phys); + + world->add(xform2); + world->add(t2Phys); + + world->add(xform3); + world->add(t2Phys); + world->add(t2Phys); + world->add(t2Phys); + } + + + + + + + //------------------------------------------------------------------------------------// + // 1 -- Writing the geometry to file + //------------------------------------------------------------------------------------// + std::string path = "geometry_1.db"; + + // check if DB file exists. If not, return. + // FIXME: TODO: this check should go in the 'GMDBManager' constructor. + std::ifstream infile(path.c_str()); + if ( infile.good() ) { + std::cout << "\n\tERROR!! A '" << path << "' file exists already!! Please, remove, move, or rename it before running this program. Exiting..."; + exit(EXIT_FAILURE); + } + infile.close(); + + // open the DB connection + GMDBManager db(path); + + // check the DB connection + if (db.checkIsDBOpen()) { + std::cout << "OK! Database is open!" << std::endl; + } else { + std::cout << "Database ERROR!! Exiting..." << std::endl; + exit(EXIT_FAILURE); + } + + // Dump the tree volumes to a local file + std::cout << "Dumping the GeoModel geometry to the DB file..." << std::endl; + GeoModelIO::WriteGeoModel dumpGeoModelGraph(db); // init the GeoModel node action + world->exec(&dumpGeoModelGraph); // visit all GeoModel nodes + dumpGeoModelGraph.saveToDB(); // save to the SQlite DB file + std::cout << "DONE. Geometry saved." <<std::endl; + + + + //std::cout << "\nTest - list of all the GeoMaterial nodes in the persistified geometry:" << std::endl; + //db.printAllMaterials(); + //std::cout << "\nTest - list of all the GeoElement nodes in the persistified geometry:" << std::endl; + //db.printAllElements(); + + //------------------------------------------------------------------------------------// + // 2 -- Reading back the geometry from file + //------------------------------------------------------------------------------------// + + std::ifstream infile2(path.c_str()); + if ( ! infile2.good() ) { + std::cout << "\n\tERROR!! A '" << path << "' file does not exist!! Please, check the path of the input file before running this program. Exiting..."; + exit(EXIT_FAILURE); + } + infile2.close(); + // open the DB + GMDBManager* db2 = new GMDBManager(path); + /* Open database */ + if (db2->checkIsDBOpen()) { + std::cout << "OK! Database is open!\n"; + } + else { + std::cout << "Database is not open!\n"; + // return; + throw; + } + /* setup the GeoModel reader */ + GeoModelIO::ReadGeoModel geoReader = GeoModelIO::ReadGeoModel(db2); + std::cout << "OK! ReadGeoModel is set." << std::endl; + /* build the GeoModel geometry */ + GeoPhysVol* dbPhys = geoReader.buildGeoModel(); // builds the whole GeoModel tree in memory + std::cout << "ReadGeoModel::buildGeoModel() done." << std::endl; + + + //------------------------------------------------------------------------------------// + // 3 -- Writing the geometry to file + //------------------------------------------------------------------------------------// + path = "geometry_2.db"; + + // check if DB file exists. If not, return. + // FIXME: TODO: this check should go in the 'GMDBManager' constructor. + std::ifstream infile3(path.c_str()); + if ( infile3.good() ) { + std::cout << "\n\tERROR!! A '" << path << "' file exists already!! Please, remove, move, or rename it before running this program. Exiting..."; + exit(EXIT_FAILURE); + } + infile3.close(); + + // open the DB connection + GMDBManager db3(path); + + // check the DB connection + if (db.checkIsDBOpen()) { + std::cout << "OK! Database is open!" << std::endl; + } else { + std::cout << "Database ERROR!! Exiting..." << std::endl; + exit(EXIT_FAILURE); + } + + // Dump the tree volumes to a local file + std::cout << "Dumping the GeoModel geometry to the DB file..." << std::endl; + GeoModelIO::WriteGeoModel dumpGeoModelGraph3(db3); // init the GeoModel node action + //world->exec(&dumpGeoModelGraph3); // visit all GeoModel nodes + dbPhys->exec(&dumpGeoModelGraph3); // visit all GeoModel nodes + dumpGeoModelGraph3.saveToDB(); // save to the SQlite DB file + std::cout << "DONE. Geometry saved." <<std::endl; + + + return 0; +} diff --git a/GeoModelExamples/MinimalPlugin/CMakeLists.txt b/GeoModelExamples/MinimalPlugin/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..3b35d67b5339ae27a73cec14021d1fe0f8044987 --- /dev/null +++ b/GeoModelExamples/MinimalPlugin/CMakeLists.txt @@ -0,0 +1,47 @@ +# Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + +################################################################################ +# Package: MinimalPlugin +# author: Riccardo Maria BIANCHI @ CERN - May, 2022 +################################################################################ + +cmake_minimum_required(VERSION 3.1.0) + +# Compile with C++17 +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS ON) + + +# Find the needed dependencies, when building individually + message (${CMAKE_SOURCE_DIR}) + message (${PROJECT_SOURCE_DIR}) + +if ( CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR ) # when buildingindividually + find_package( GeoModelCore REQUIRED ) +endif() + + +# Find the header and source files. +file( GLOB SOURCES src/*.cxx ) + +add_library( MinimalPlugin SHARED ${SOURCES} ) +target_link_libraries( MinimalPlugin PUBLIC GeoModelCore::GeoModelKernel) + +target_include_directories( MinimalPlugin PUBLIC + $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}> + $<INSTALL_INTERFACE:include> ) + +source_group( "src" FILES ${SOURCES} ) + +set_target_properties( MinimalPlugin PROPERTIES + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} ) + +# Install the library. +install( TARGETS MinimalPlugin + EXPORT ${PROJECT_NAME}-export + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + COMPONENT Runtime + NAMELINK_SKIP ) + diff --git a/GeoModelExamples/MinimalPlugin/src/MinimalPlugin.cxx b/GeoModelExamples/MinimalPlugin/src/MinimalPlugin.cxx new file mode 100644 index 0000000000000000000000000000000000000000..2bde380f4ea6b642bcecf1feb2ade1cbb32cee5d --- /dev/null +++ b/GeoModelExamples/MinimalPlugin/src/MinimalPlugin.cxx @@ -0,0 +1,139 @@ +/* + Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration +*/ + +// ------------------------------------------------------------------- +// +// Minimal Plugin +// Riccardo Maria BIANCHI, 2022 May 6 +// +// This is an example plugin. It compiles to a shared library +// (with .so or .dylib extension) which can be viewed with gmex. +// In this example there is no "envelope", all the components of +// the minimal example geometry are placed into the world. +// +// This example illustrates the use of: +// +// --the plugin mechanism. +// --simple shapes, logical volumes, physical volumes +// --chemical elements and pure materials (aluminium) +// +// -------------------------------------------------------------------- + +#include "GeoModelKernel/GeoVGeometryPlugin.h" +#include "GeoModelKernel/GeoDefinitions.h" +#include "GeoModelKernel/GeoMaterial.h" +#include "GeoModelKernel/GeoBox.h" +#include "GeoModelKernel/GeoTube.h" +#include "GeoModelKernel/GeoLogVol.h" +#include "GeoModelKernel/GeoPhysVol.h" +#include "GeoModelKernel/GeoTransform.h" +#include "GeoModelKernel/GeoShapeSubtraction.h" +#include "GeoModelKernel/GeoShapeShift.h" + +// Class Declaration + +class MinimalPlugin : public GeoVGeometryPlugin { + + public: + + // Constructor: + MinimalPlugin(); + + // Destructor: + ~MinimalPlugin(); + + // Creation of geometry: + virtual void create(GeoPhysVol *world, bool publish=false); + + private: + + // Illegal operations: + const MinimalPlugin & operator=(const MinimalPlugin &right)=delete; + MinimalPlugin(const MinimalPlugin &right) = delete; + +}; + + +// Class definition: + +// Constructor +MinimalPlugin::MinimalPlugin() +{ +} + +// Destructor +MinimalPlugin::~MinimalPlugin() +{ +} + +// The create algorithm creates a tree of physical volumes rooted under the +// "world" physical volume. The optional flag publish is not used in this +// example (normally one may "publish" a list of FullPhysVol's and Alignable +// transforms, but this example has none such). +// +void MinimalPlugin::create(GeoPhysVol *world, bool /*publish*/) +{ + const double degree=M_PI/180.0; + + // Define elements used in this example: + GeoElement *aluminium = new GeoElement("Aluminium", "Al", 13, 26 * GeoModelKernelUnits::g/GeoModelKernelUnits::mole); + + // Define materials: + // Define Aluminium + double densityOfAluminium=2.7; // g/cm^3 + GeoMaterial *Aluminium = new GeoMaterial("Aluminium", densityOfAluminium); + Aluminium->add(aluminium,1.0); + Aluminium->lock(); + + // Some dimensions used below: + double platformHeight=34.5; // Height to the top of the flanges + //double flangeDiameter=3.375; // Diameter of the flanges + double flangeThickness=3.0/16.0; // Thickness of the flanges + double t1TubeLength = platformHeight-flangeThickness; // Overall length of tube t1; + double innerRadius=0.75/2.0; // 3/4 inch (inner diameter) pipe + double outerRadius=(17.0/16.0)/2.0; // 1-1/16 (outer diameter) + double leftRightLegSeparation=61.0+11.0/16.0; // Distance between legs, in x. + double frontBackLegSeparation=19.0+3.0/4.0; // Distance between legs, in y. + //const double barWidth1=4.0; // Width of front-back primary support + //const double barWidth2=3.0; // Width of secondary aluminium support + //double barThickness =1.25; // Thickness of Aluminium bars + //double cutoutDepth = 21.5; // Depth of the cutout hole + //double cutoutWidth = 32.375; // Width of the cutout hole + + // Add the four legs of the kitchen sink: + { + const GeoTube *t1Tube = new GeoTube(innerRadius,outerRadius, t1TubeLength/2.0); + const GeoLogVol *t1Log = new GeoLogVol("T1Log", t1Tube, Aluminium); + const GeoLogVol *t2Log = new GeoLogVol("T2Log", t1Tube, Aluminium); + GeoPhysVol *t1Phys = new GeoPhysVol(t1Log); + GeoPhysVol *t2Phys = new GeoPhysVol(t2Log); + //GeoPhysVol *t3Phys = new GeoPhysVol(t1Log); + GeoTransform *xform1 = new GeoTransform(GeoTrf::Translate3D(leftRightLegSeparation/2.0, frontBackLegSeparation/2.0, 0)); + GeoTransform *xform2 = new GeoTransform(GeoTrf::Translate3D(leftRightLegSeparation/2.0, -frontBackLegSeparation/2.0, 0)); + GeoTransform *xform3 = new GeoTransform(GeoTrf::Translate3D(-leftRightLegSeparation/2.0, -frontBackLegSeparation/2.0, 0)); + //GeoTransform *xform4 = new GeoTransform(GeoTrf::Translate3D(-leftRightLegSeparation/2.0, frontBackLegSeparation/2.0, 0)); + world->add(xform1); + + world->add(t1Phys); + + world->add(xform2); + world->add(t2Phys); + + world->add(xform3); + world->add(t2Phys); + world->add(t2Phys); + world->add(t2Phys); + + } + + + //--------------------------------------// +} + +// The name of this routine must correspond to the name of the class, +// and also to the name of the source code file (this file) + +extern "C" MinimalPlugin *createMinimalPlugin() { + return new MinimalPlugin; +} diff --git a/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h b/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h index e612722f23ad72e3c9ad6f99a76eb72e41e1d7d8..403138e1c1b59edeccd611b34bfdf076711c79c0 100644 --- a/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h +++ b/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.h @@ -1,3 +1,8 @@ + +/* + Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +*/ + /* * ReadGeoModel.h * @@ -9,6 +14,11 @@ * - 2020 May, R.M.Bianchi - Added parallel read * - 2020 Aug, R.M.Bianchi - Added support for reading back published nodes * - 2021 Aug, R.M.Bianchi <riccardo.maria.bianchi@cern.ch> - Added support GeoIdentifierTag and GeoSerialIdentifier nodes + * - Jun 2022, R.M.Bianchi <riccardo.maria.bianchi@cern.ch> + * Fixed the duplication of VPhysVol instances due to a wrong key used for caching volumes that were built already + * The copyNumber was wrongly used together with tableID and volID + * For details, see: https://gitlab.cern.ch/GeoModelDev/GeoModel/-/issues/39 + * */ #ifndef GeoModelRead_ReadGeoModel_H_ @@ -166,8 +176,10 @@ private: void storeBuiltAlignableTransform(GeoAlignableTransform* node); GeoAlignableTransform* getBuiltAlignableTransform(const unsigned int id); - void storeVPhysVol(const unsigned int id, const unsigned int tableId, const unsigned int copyNumber, GeoGraphNode* node); - GeoGraphNode* getVPhysVol(const unsigned int id, const unsigned int tableId, const unsigned int copyNumber); + //void storeVPhysVol(const unsigned int id, const unsigned int tableId, const unsigned int copyNumber, GeoGraphNode* node); + //GeoGraphNode* getVPhysVol(const unsigned int id, const unsigned int tableId, const unsigned int copyNumber); + void storeVPhysVol(const unsigned int id, const unsigned int tableId, GeoGraphNode* node); + GeoGraphNode* getVPhysVol(const unsigned int id, const unsigned int tableId); bool isBuiltLog(const unsigned int id); void storeBuiltLog(GeoLogVol* nodePtr); diff --git a/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.tpp b/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.tpp index c62ef478f101911ea6766b1650c3ae8b8450f15b..9e6d1ec7013528725f036c5377537a6faadd4dac 100644 --- a/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.tpp +++ b/GeoModelIO/GeoModelRead/GeoModelRead/ReadGeoModel.tpp @@ -38,13 +38,9 @@ namespace GeoModelIO { std::string volID = record[2]; if(0==ii) keyType = record[3];//this is the same for all records. TODO: it should be stored in a metadata table ++ii; - - //std::cout << "keyStr: " << keyStr << ", volID: " << volID - // << ", keyType: " << keyType << std::endl; // debug msg - N volPtr = nullptr; if constexpr ( std::is_same_v<GeoFullPhysVol*, N> ) { - volPtr = dynamic_cast<GeoFullPhysVol*>( getVPhysVol(std::stoul(volID), 2, 1) ); //always table=2, copyN=1 (because FullPhysVols are not sharable + volPtr = dynamic_cast<GeoFullPhysVol*>( getVPhysVol(std::stoul(volID), 2) ); //always table=2, and we should have copyN=1 because FullPhysVols are not sharable } else if constexpr ( std::is_same_v<GeoAlignableTransform*, N> ) { volPtr = getBuiltAlignableTransform(std::stoul(volID)); } else { diff --git a/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp b/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp index b909a4f78528ba626e089a2c36fbab737d067ccf..768e4706a1a734dbd04bf1e6eb6368799f23c2c1 100644 --- a/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp +++ b/GeoModelIO/GeoModelRead/src/ReadGeoModel.cpp @@ -15,6 +15,10 @@ * - May 2020, R.M.Bianchi * - Aug 2020, R.M.Bianchi - Added support to read published FullPhysVols and AlignableTransforms back in * - Aug 2021, R.M.Bianchi <riccardo.maria.bianchi@cern.ch> - Added support for GeoSerialIdentifier and GeoIdentifierTag + * - Jun 2022, R.M.Bianchi <riccardo.maria.bianchi@cern.ch> + * Fixed the duplication of VPhysVol instances due to a wrong key used for caching volumes that were built already + * The copyNumber was wrongly used together with tableID and volID + * For details, see: https://gitlab.cern.ch/GeoModelDev/GeoModel/-/issues/39 */ @@ -325,7 +329,7 @@ GeoPhysVol* ReadGeoModel::buildGeoModelPrivate() if (m_debug || m_deepDebug) { muxCout.lock(); - std::cout << "Thread " << std::this_thread::get_id() << " - processing " << nChildrenRecords << " keys..." << std::endl; + std::cout << "\nReadGeoModel::loopOverAllChildrenRecords -- Thread " << std::this_thread::get_id() << " - processing " << nChildrenRecords << " keys..." << std::endl; muxCout.unlock(); } @@ -664,6 +668,14 @@ void ReadGeoModel::loopOverAllChildrenInBunches() void ReadGeoModel::processParentChild(const std::vector<std::string> &parentchild) { + if (m_deepDebug) { + muxCout.lock(); + std::cout << "\nReadGeoModel::processParentChild()..." << std::endl; + for (auto& rec : parentchild) std::cout << rec << "-"; + std::cout << std::endl; + muxCout.unlock(); + } + // safety check if (parentchild.size() < 8) { std::cout << "ERROR!!! Probably you are using an old geometry file. Please, get a new one. Exiting..." << std::endl; @@ -687,7 +699,7 @@ void ReadGeoModel::loopOverAllChildrenInBunches() std::string childNodeType = m_tableID_toTableName[childTableId]; if ( "" == childNodeType || 0 == childNodeType.size()) { - std::cout << "ERROR!!! childNodeType is empty!!! Aborting..." << std::endl; + std::cout << "ReadGeoModel -- ERROR!!! childNodeType is empty!!! Aborting..." << std::endl; exit(EXIT_FAILURE); } @@ -695,6 +707,7 @@ void ReadGeoModel::loopOverAllChildrenInBunches() // build or get parent volume. // Using the parentCopyNumber here, to get a given instance of the parent volume + if (m_deepDebug) { muxCout.lock(); std::cout << "build/get parent volume...\n"; muxCout.unlock(); } parentVol = dynamic_cast<GeoVPhysVol*>( buildVPhysVolInstance(parentId, parentTableId, parentCopyN) ); std::string parentName = parentVol->getLogVol()->getName(); @@ -723,6 +736,7 @@ void ReadGeoModel::loopOverAllChildrenInBunches() volAddHelper(parentVol, childNode); } else if (childNodeType == "GeoTransform") { + if (m_deepDebug) { muxCout.lock(); std::cout << "get transform child...\n"; muxCout.unlock(); } GeoTransform* childNode = getBuiltTransform(childId); volAddHelper(parentVol, childNode); } @@ -779,20 +793,24 @@ GeoVPhysVol* ReadGeoModel::buildVPhysVolInstance(const unsigned int id, const un { if (m_deepDebug) { muxCout.lock(); - std::cout << "ReadGeoModel::buildVPhysVolInstance() - " << id << ", " << tableId << ", " << copyN << std::endl; + std::cout << "ReadGeoModel::buildVPhysVolInstance() - id: " << id + << ", tableId: " << tableId + << ", copyN: " << copyN << std::endl; muxCout.unlock(); } - // A - if the instance has been previously built, return that - if ( nullptr != getVPhysVol(id, tableId, copyN)) { -// if (isVPhysVolBuilt(id, tableId, copyN)) { - if (m_deepDebug) { - muxCout.lock(); - std::cout << "getting the instance volume from memory..." << std::endl; - muxCout.unlock(); + // A - if the instance has been previously built, return that + //if ( nullptr != getVPhysVol(id, tableId, copyN)) { + if ( nullptr != getVPhysVol(id, tableId)) { + if (m_deepDebug) { + muxCout.lock(); + //std::cout << "getting the instance volume from memory... Returning: [" << getVPhysVol(id, tableId, copyN) << "] -- logvol: " << ((GeoVPhysVol*)getVPhysVol(id, tableId, copyN))->getLogVol()->getName() << std::endl; + std::cout << "getting the instance volume from memory... Returning: [" << getVPhysVol(id, tableId) << "] -- logvol: " << ((GeoVPhysVol*)getVPhysVol(id, tableId))->getLogVol()->getName() << std::endl; + muxCout.unlock(); + } + //return dynamic_cast<GeoVPhysVol*>(getVPhysVol(id, tableId, copyN)); + return dynamic_cast<GeoVPhysVol*>(getVPhysVol(id, tableId)); } - return dynamic_cast<GeoVPhysVol*>(getVPhysVol(id, tableId, copyN)); - } // B - if not built already, then get the actual volume, // which should be already built by now, @@ -802,8 +820,14 @@ GeoVPhysVol* ReadGeoModel::buildVPhysVolInstance(const unsigned int id, const un GeoVPhysVol* vol = nullptr; bool volFound = true; if (1==tableId) { - if(isBuiltPhysVol(id)) + if(isBuiltPhysVol(id)) { vol = new GeoPhysVol( getBuiltPhysVol(id)->getLogVol() ); + if (m_deepDebug) { + muxCout.lock(); + std::cout << "PhysVol not instanced yet, building the instance now [" << vol << "] -- logvol: " << vol->getLogVol()->getName() << std::endl; + muxCout.unlock(); + } + } else volFound = false; } @@ -817,7 +841,8 @@ GeoVPhysVol* ReadGeoModel::buildVPhysVolInstance(const unsigned int id, const un std::cout << "ERROR! VPhysVol not found! It should be already built, by now. Exiting...\n"; exit(EXIT_FAILURE); } - storeVPhysVol(id, tableId, copyN, vol); + //storeVPhysVol(id, tableId, copyN, vol); + storeVPhysVol(id, tableId, vol); return vol; } @@ -862,6 +887,7 @@ GeoVPhysVol* ReadGeoModel::buildVPhysVol(const unsigned int id, const unsigned i std::cout << "ERROR!!! LogVol is NULL!" << std::endl; // exit(EXIT_FAILURE); } + if (m_deepDebug) { muxCout.lock(); std::cout << "using the cached LogVol [" << logVol_ID << "] w/ address: " << logVol << "...\n"; ; muxCout.unlock(); } // a pointer to the VPhysVol GeoVPhysVol* vol = nullptr; @@ -2533,7 +2559,10 @@ GeoBox* ReadGeoModel::buildDummyShape() { GeoLogVol* ReadGeoModel::buildLogVol(const unsigned int id) { + if (m_deepDebug) { muxCout.lock(); std::cout << "buildLogVol(), testing LogVol id: " << id << "...\n"; ; muxCout.unlock(); } + if (isBuiltLog(id)) { + if (m_deepDebug) { muxCout.lock(); std::cout << "getting the LogVol from cache...\n"; ; muxCout.unlock(); } return getBuiltLog(id); } @@ -2570,9 +2599,14 @@ GeoLogVol* ReadGeoModel::buildLogVol(const unsigned int id) exit(EXIT_FAILURE); } - GeoLogVol* logPtr = new GeoLogVol(logVolName, shape, mat); + GeoLogVol* logPtr = new GeoLogVol(logVolName, shape, mat); storeBuiltLog(logPtr); - return logPtr; + if (m_deepDebug) { + muxCout.lock(); + std::cout << "buildLogVol() - address of the stored LogVol:" << logPtr << std::endl; + muxCout.unlock(); + } + return logPtr; } @@ -2985,21 +3019,30 @@ GeoSerialTransformer* ReadGeoModel::getBuiltSerialTransformer(const unsigned int */ // --- methods for caching GeoPhysVol/GeoFullPhysVol nodes --- -std::string getVPhysVolKey(const unsigned int id, const unsigned int tableId, const unsigned int copyNumber) +//std::string getVPhysVolKey(const unsigned int id, const unsigned int tableId, const unsigned int copyNumber) +//{ + //std::string key = std::to_string(id) + ":" + std::to_string(tableId) + ":" + std::to_string(copyNumber); + //return key; +//} +std::string getVPhysVolKey(const unsigned int id, const unsigned int tableId) { - std::string key = std::to_string(id) + ":" + std::to_string(tableId) + ":" + std::to_string(copyNumber); + std::string key = std::to_string(id) + ":" + std::to_string(tableId); return key; } -void ReadGeoModel::storeVPhysVol(const unsigned int id, const unsigned int tableId, const unsigned int copyN, GeoGraphNode* nodePtr) +//void ReadGeoModel::storeVPhysVol(const unsigned int id, const unsigned int tableId, const unsigned int copyN, GeoGraphNode* nodePtr) +void ReadGeoModel::storeVPhysVol(const unsigned int id, const unsigned int tableId, GeoGraphNode* nodePtr) { std::lock_guard<std::mutex> lk(muxVPhysVol); - std::string key = getVPhysVolKey(id, tableId, copyN); + //std::string key = getVPhysVolKey(id, tableId, copyN); + std::string key = getVPhysVolKey(id, tableId); m_memMap[key] = nodePtr; } -GeoGraphNode* ReadGeoModel::getVPhysVol(const unsigned int id, const unsigned int tableId, const unsigned int copyN) +//GeoGraphNode* ReadGeoModel::getVPhysVol(const unsigned int id, const unsigned int tableId, const unsigned int copyN) +GeoGraphNode* ReadGeoModel::getVPhysVol(const unsigned int id, const unsigned int tableId) { - std::lock_guard<std::mutex> lk(muxVPhysVol); - std::string key = getVPhysVolKey(id, tableId, copyN); + std::lock_guard<std::mutex> lk(muxVPhysVol); + //std::string key = getVPhysVolKey(id, tableId, copyN); + std::string key = getVPhysVolKey(id, tableId); if (m_memMap.find(key) == m_memMap.end()) { return nullptr; // if volume is not found in cache } diff --git a/GeoModelIO/GeoModelWrite/src/WriteGeoModel.cpp b/GeoModelIO/GeoModelWrite/src/WriteGeoModel.cpp index a35ede516272f13ba69a01ae835d421c83c55202..1341cce946b5b598222f8a8838d6c890dbd6dc64 100644 --- a/GeoModelIO/GeoModelWrite/src/WriteGeoModel.cpp +++ b/GeoModelIO/GeoModelWrite/src/WriteGeoModel.cpp @@ -1,5 +1,5 @@ /* - Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration + Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration */ // author: Riccardo.Maria.Bianchi@cern.ch, 2017 @@ -148,6 +148,8 @@ void WriteGeoModel::handleFullPhysVol (const GeoFullPhysVol *vol) void WriteGeoModel::handleVPhysVolObjects(const GeoVPhysVol* vol) { + //std::cout << "WriteGeoModel::handleVPhysVolObjects() -- visiting... " << vol << std::endl; // debug msg + // get the address string for the current volume std::string address = getAddressStringFromPointer( vol ); @@ -270,7 +272,7 @@ void WriteGeoModel::handleVPhysVolObjects(const GeoVPhysVol* vol) // LOGVOL const GeoLogVol* logVol = vol->getLogVol(); - const std::string logName = logVol->getName(); + const std::string logName = logVol->getName(); // MATERIAL const GeoMaterial * mat = vol->getLogVol()->getMaterial(); @@ -300,27 +302,29 @@ void WriteGeoModel::handleVPhysVolObjects(const GeoVPhysVol* vol) const GeoPhysVol* physVol = dynamic_cast<const GeoPhysVol*>(vol); // store the PhysVol volume into the DB physId = storeObj(physVol, logvolId, parentId, storeRootVolume); // with parent info - volTypeStr = "GeoPhysVol"; + volTypeStr = "GeoPhysVol"; } else if (dynamic_cast<const GeoFullPhysVol*>(vol)) { const GeoFullPhysVol* fullVol = dynamic_cast<const GeoFullPhysVol*>(vol); physId = storeObj(fullVol, logvolId, parentId, storeRootVolume); // with parent info - volTypeStr = "GeoFullPhysVol"; + volTypeStr = "GeoFullPhysVol"; } else { - std::cout << "WARNING!! Unknown GeoVPhysVol type!! Exiting..." << std::endl; - exit(EXIT_FAILURE); + std::cout << "GeoModelWrite -- WARNING!! Unknown GeoVPhysVol type!! Exiting..." << std::endl; + exit(EXIT_FAILURE); } } else { physId = getStoredIdFromAddress(address); - volTypeStr = getGeoTypeFromVPhysVol(vol); + volTypeStr = getGeoTypeFromVPhysVol(vol); } // Now we get the 'copy number' for this volume, // to distinguish this volume from the other volumes created from the same shared node (if any) - if (volTypeStr == "NULL") std::cout << "ERROR!! volTypeStr is 'NULL'!!!\n"; + if (volTypeStr == "NULL") std::cout << "ERROR!! volTypeStr is 'NULL'!!!\n"; const unsigned int volCopyN = setVolumeCopyNumber(physId, volTypeStr); - //JFB Commented out: qDebug() << "physId: " << physId << "- volume copy number: " << volCopyN; + + // debug msg + //std::cout << "WriteGeoModel -- physId: " << physId << "- volume copy number: " << volCopyN << std::endl; if ( isRootVolume || parentId == 0) { //qDebug() << "This is the RootVolume or the volume has 'NULL' parent (unconnected subtree?) - So, we do not store the child position for this volume!"; @@ -347,7 +351,7 @@ void WriteGeoModel::handleVPhysVolObjects(const GeoVPhysVol* vol) else if (dynamic_cast<const GeoFullPhysVol*>(vol)) { geoType = "GeoFullPhysVol"; } else { - std::cout << "WARNING!! Unknown GeoVPhysVol type!!" << std::endl; + std::cout << "GeoModelWrite -- WARNING!! Unknown GeoVPhysVol type!!" << std::endl; } return geoType; } @@ -498,7 +502,7 @@ void WriteGeoModel::handleSerialTransformer (const GeoSerialTransformer *node) try { persistifier.persistify(*func); } catch (const std::runtime_error & error) { - std::cout << "SEVERE WARNING!! Handling std::runtime_error! -->" << error.what() << std::endl; + std::cout << "GeoModelWrite -- SEVERE WARNING!! Handling std::runtime_error! -->" << error.what() << std::endl; } std::string expression = persistifier.getCodedString(); @@ -652,7 +656,7 @@ void WriteGeoModel::handleNameTag(const GeoNameTag* node) } } else{ - std::cout << "WARNING!! Len == 0, but this cannot be the Root volume!" << std::endl; + std::cout << "GeoModelWrite -- WARNING!! Len == 0, but this cannot be the Root volume!" << std::endl; } std::vector<std::string> parentList; @@ -1124,7 +1128,7 @@ std::string WriteGeoModel::getShapeParameters(const GeoShape* shape) // shapePars=pars.join(";"); // } else { - std::cout << "\n\tWARNING!!! - Shape '" << shapeType << "' needs to be persistified!!\n\n"; + std::cout << "\n\tGeoModelWrite -- WARNING!!! - Shape '" << shapeType << "' needs to be persistified!!\n\n"; printStdVectorStrings(m_objectsNotPersistified); } @@ -1702,7 +1706,7 @@ void WriteGeoModel::saveToDB( std::vector<GeoPublisher*>& publishers ) if ( !m_objectsNotPersistified.empty() ) { - std::cout << "\n\tWARNING!! There are shapes/nodes which need to be persistified! --> "; + std::cout << "\n\tGeoModelWrite -- WARNING!! There are shapes/nodes which need to be persistified! --> "; printStdVectorStrings(m_objectsNotPersistified); std::cout << "\n\n"; } @@ -1741,12 +1745,12 @@ void WriteGeoModel::storePublishedNodes(GeoPublisher* store) if (mapAXF.size() > 0) { m_dbManager->addListOfPublishedAlignableTransforms(m_publishedAlignableTransforms_String, storeName); } else { - std::cout << "\nWARNING! A pointer to a GeoPublisher was provided, but no GeoAlignableTransform nodes have been published. Please, check if that was intended. (If in doubt, please ask to 'geomodel-developers@cern.ch')\n" << std::endl; + std::cout << "\nGeoModelWrite -- WARNING! A pointer to a GeoPublisher was provided, but no GeoAlignableTransform nodes have been published. Please, check if that was intended. (If in doubt, please ask to 'geomodel-developers@cern.ch')\n" << std::endl; } if (mapFPV.size() > 0) { m_dbManager->addListOfPublishedFullPhysVols(m_publishedFullPhysVols_String, storeName); } else { - std::cout << "\nWARNING! A pointer to a GeoPublisher was provided, but no GeoFullPhysVol nodes have been published. Please, check if that was intended. (If in doubt, please ask to 'geomodel-developers@cern.ch')\n" << std::endl; + std::cout << "\nGeoModelWrite -- WARNING! A pointer to a GeoPublisher was provided, but no GeoFullPhysVol nodes have been published. Please, check if that was intended. (If in doubt, please ask to 'geomodel-developers@cern.ch')\n" << std::endl; } // clear the caches diff --git a/GeoModelTools/GMCAT/src/gmcat.cxx b/GeoModelTools/GMCAT/src/gmcat.cxx index 31b4873199ce6fb252155a5f4db01a5f5e9e2a7e..c486d4ab2db40423b9dd92591b06da324a0359d6 100644 --- a/GeoModelTools/GMCAT/src/gmcat.cxx +++ b/GeoModelTools/GMCAT/src/gmcat.cxx @@ -1,3 +1,7 @@ +/* + * Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration +*/ + #include "GeoModelKernel/GeoVGeometryPlugin.h" #include "GeoModelDBManager/GMDBManager.h" #include "GeoModelRead/ReadGeoModel.h" @@ -84,19 +88,19 @@ int main(int argc, char ** argv) { if (access(outputFile.c_str(),F_OK)==0) { if (!access(outputFile.c_str(),W_OK)) { if (system(("rm -f "+ outputFile).c_str())) { - std::cerr << "Error, cannot overwrite existing file " << outputFile << std::endl; + std::cerr << "gmcat -- Error, cannot overwrite existing file " << outputFile << std::endl; return 3; } } else { - std::cerr << "Error, cannot overwrite existing file " << outputFile << " (permission denied)" << std::endl; + std::cerr << "gmcat -- Error, cannot overwrite existing file " << outputFile << " (permission denied)" << std::endl; return 4; } } // - // Create elements and materials: + // Create elements and materials for the "World" volume, which is the container: // const double gr = SYSTEM_OF_UNITS::gram; @@ -133,7 +137,7 @@ int main(int argc, char ** argv) { GeoGeometryPluginLoader loader; GeoVGeometryPlugin *factory=loader.load(plugin); if (!factory) { - std::cerr << "Could not load plugin " << plugin << std::endl; + std::cerr << "gmcat -- Could not load plugin " << plugin << std::endl; return 5; } @@ -155,7 +159,7 @@ int main(int argc, char ** argv) { for (const std::string & file : inputFiles) { GMDBManager* db = new GMDBManager(file); if (!db->checkIsDBOpen()){ - std::cerr << "Error opening input file " << file << std::endl; + std::cerr << "gmcat -- Error opening the input file: " << file << std::endl; return 6; } @@ -165,8 +169,10 @@ int main(int argc, char ** argv) { /* build the GeoModel geometry */ GeoPhysVol* dbPhys = readInGeo.buildGeoModel(); // builds the whole GeoModel tree in memory + /* get an handle on a Volume Cursor, to traverse the whole set of Volumes */ GeoVolumeCursor aV(dbPhys); + /* loop over the Volumes in the tree */ while (!aV.atEnd()) { GeoNameTag *nameTag=new GeoNameTag(aV.getName()); GeoTransform *transform= new GeoTransform(aV.getTransform()); @@ -175,6 +181,7 @@ int main(int argc, char ** argv) { world->add((GeoVPhysVol *) &*aV.getVolume()); aV.next(); } + delete db; } // @@ -185,13 +192,17 @@ int main(int argc, char ** argv) { // check the DB connection // if (!db.checkIsDBOpen()) { - std::cerr << "Error opening output file " << outputFile << std::endl; + std::cerr << "gmcat -- Error opening the output file: " << outputFile << std::endl; return 7; } GeoModelIO::WriteGeoModel dumpGeoModelGraph(db); world->exec(&dumpGeoModelGraph); - dumpGeoModelGraph.saveToDB(vecPluginsPublishers); + if (vecPluginsPublishers.size() > 0) { + dumpGeoModelGraph.saveToDB(vecPluginsPublishers); + } else { + dumpGeoModelGraph.saveToDB(); + } world->unref();