diff --git a/DDCore/include/DD4hep/DetectorLoad.h b/DDCore/include/DD4hep/DetectorLoad.h index 4c1f35ba4ca7ffd7cc6ae53919915c90be51a192..2cc77806015269bc2587757e0534b2bfda72393b 100644 --- a/DDCore/include/DD4hep/DetectorLoad.h +++ b/DDCore/include/DD4hep/DetectorLoad.h @@ -31,10 +31,15 @@ namespace dd4hep { class Detector; /// Data implementation class of the Detector interface - /** @class DetectorLoad DetectorLoad.h dd4hep/DetectorLoad.h + /** + * This class is a view on the generic Detector implementation and deals with + * all issues parsing XML files. * - * @author M.Frank - * @version 1.0 + * The calls "fromXML" and "fromCompact" in the Detector implementation + * call this subclass. + * + * \author M.Frank + * \version 1.0 */ class DetectorLoad { public: @@ -42,17 +47,44 @@ namespace dd4hep { protected: /// Reference to the Detector instance - Detector* m_detDesc; - /// Default constructor + Detector* m_detDesc = 0; + + protected: + /// Default constructor (protected, for sub-classes) DetectorLoad(Detector* description); + + public: +#ifdef G__ROOT + /// No defautl constructor + DetectorLoad() = default; +#else + /// No defautl constructor + DetectorLoad() = delete; +#endif + /// No move constructor + DetectorLoad(DetectorLoad&& copy) = delete; + /// Default copy constructor + DetectorLoad(const DetectorLoad& copy) = default; + + /// Default constructor (public, if used as a handle) + DetectorLoad(Detector& description); /// Default destructor virtual ~DetectorLoad(); + /// Copy assignment constructor + DetectorLoad& operator=(const DetectorLoad& copy) = default; + /// No move assignment + DetectorLoad& operator=(DetectorLoad&& copy) = delete; - public: /// Process XML unit and adopt all data from source structure. virtual void processXML(const std::string& fname, xml::UriReader* entity_resolver=0); /// Process XML unit and adopt all data from source structure. virtual void processXML(const xml::Handle_t& base, const std::string& fname, xml::UriReader* entity_resolver=0); + /// Process XML unit and adopt all data from source string in momory. + virtual void processXMLString(const char* xmldata); + /// Process XML unit and adopt all data from source string in momory. + /** Subsequent parsers may use the entity resolver. + */ + virtual void processXMLString(const char* xmldata, xml::UriReader* entity_resolver); /// Process a given DOM (sub-) tree virtual void processXMLElement(const std::string& msg_source, const xml::Handle_t& root); /// Process a given DOM (sub-) tree diff --git a/DDCore/src/DetectorLoad.cpp b/DDCore/src/DetectorLoad.cpp index dc0665f02a2861013481eb28f5ec62363a994aff..04e24fa266df14f5c599c9e2a744fd6e2394a6c4 100644 --- a/DDCore/src/DetectorLoad.cpp +++ b/DDCore/src/DetectorLoad.cpp @@ -34,10 +34,14 @@ namespace dd4hep { using namespace dd4hep; using namespace std; -/// Default constructor +/// Default constructor (protected, for sub-classes) DetectorLoad::DetectorLoad(Detector* description) : m_detDesc(description) { } +/// Default constructor (public, if used as a handle) +DetectorLoad::DetectorLoad(Detector& description) : m_detDesc(&description) { +} + /// Standard destructor DetectorLoad::~DetectorLoad() { } @@ -60,7 +64,6 @@ void DetectorLoad::processXML(const string& xmlfile, xml::UriReader* entity_reso } } - /// Process XML unit and adopt all data from source structure. void DetectorLoad::processXML(const xml::Handle_t& base, const string& xmlfile, xml::UriReader* entity_resolver) { try { @@ -80,6 +83,33 @@ void DetectorLoad::processXML(const xml::Handle_t& base, const string& xmlfile, } } +/// Process XML unit and adopt all data from source string in momory. +void DetectorLoad::processXMLString(const char* xmldata) { + processXMLString(xmldata, 0); +} + +/// Process XML unit and adopt all data from source string in momory. Subsequent parsers may use the entity resolver. +void DetectorLoad::processXMLString(const char* xmldata, xml::UriReader* entity_resolver) { + try { + if ( xmldata) { + xml::DocumentHolder doc(xml::DocumentHandler().parse(xmldata,::strlen(xmldata),"In-Memory",entity_resolver)); + xml::Handle_t handle = doc.root(); + processXMLElement("In-Memory-XML",handle); + return; + } + throw runtime_error("DetectorLoad::processXMLString: Invalid XML In-memory source [NULL]"); + } + catch (const xml::XmlException& e) { + throw runtime_error(xml::_toString(e.msg) + "\ndd4hep: XML-DOM Exception while parsing XML in-memory string."); + } + catch (const exception& e) { + throw runtime_error(string(e.what()) + "\ndd4hep: while parsing XML in-memory string."); + } + catch (...) { + throw runtime_error("dd4hep: UNKNOWN exception while parsing XML in-memory string."); + } +} + /// Process a given DOM (sub-) tree void DetectorLoad::processXMLElement(const std::string& xmlfile, const xml::Handle_t& xml_root) { string tag = xml_root.tag(); diff --git a/DDCore/src/XML/DocumentHandler.cpp b/DDCore/src/XML/DocumentHandler.cpp index 0a694a21eb05dc24d3b3d6a34f20dacf3b291eb1..35bd6829f524a06cfe221e825001aa0909353be2 100644 --- a/DDCore/src/XML/DocumentHandler.cpp +++ b/DDCore/src/XML/DocumentHandler.cpp @@ -274,9 +274,16 @@ Document DocumentHandler::load(Handle_t base, const XMLCh* fname, UriReader* rea string path; DOMElement* elt = (DOMElement*)base.ptr(); try { - Strng_t p = _toString(fname); - XMLURL ref_url(elt->getBaseURI(), p); - path = _toString(ref_url.getURLText()); + Document doc; + Strng_t p = _toString(fname); + path = _toString(fname); + /// This is a bit complicated, but if the primary source is in-memory + try { + XMLURL ref_url(elt->getBaseURI(), p); + path = _toString(ref_url.getURLText()); + } + catch(...) { + } return load(path, reader); } catch(const exception& exc) { diff --git a/DDCore/src/plugins/StandardPlugins.cpp b/DDCore/src/plugins/StandardPlugins.cpp index 3a570f6e58a6d2ad2f5d04956faf648aaebd4c6e..d21f449063f1bbf73c0a01d1326d85d165daead5 100644 --- a/DDCore/src/plugins/StandardPlugins.cpp +++ b/DDCore/src/plugins/StandardPlugins.cpp @@ -33,6 +33,7 @@ #include "TGeoElement.h" #include "TGeoManager.h" #include "TGeoVolume.h" +#include "TSystem.h" #include "TClass.h" #include "TRint.h" @@ -145,6 +146,53 @@ static long display(Detector& description, int argc, char** argv) { } DECLARE_APPLY(DD4hep_GeometryDisplay,display) +/// Basic entry point to execute a public function from a library +/** + * Factory: DD4hep_Function + * + * \author M.Frank + * \version 1.0 + * \date 01/04/2014 + */ +static long run_function(Detector&, int argc, char** argv) { + string lib, func; + std::vector<char*> args; + for(int i = 0; i < argc && argv[i]; ++i) { + if ( 0 == ::strncmp("-library",argv[i],4) ) + lib = argv[++i]; + else if ( 0 == ::strncmp("-function",argv[i],4) ) + func = argv[++i]; + else + args.push_back(argv[i]); + } + if ( lib.empty() || func.empty() ) { + cout << + "Usage: -plugin <name> -arg [-arg] \n" + " -library <string> Library to be loaded \n" + " -function <string> name of the entry point to be executed. \n" + "\tArguments given: " << arguments(argc,argv) << endl << flush; + ::exit(EINVAL); + } + Func_t f = gSystem->DynFindSymbol("*",func.c_str()); + int ret; + if ( !f ) { + ret = gSystem->Load(lib.c_str()); + if ( ret != 0 ) { + except("DD4hep_Function","+++ Failed to load library: %s",lib.c_str()); + } + f = gSystem->DynFindSymbol("*",func.c_str()); + if ( !f ) { + except("DD4hep_Function","+++ Failed to find function %s in library: %s", + func.c_str(),lib.c_str()); + } + } + typedef int (*call_t)(int, char**); + call_t ff = (call_t)f; + ret = (*ff)(args.size(),&args[0]); + return ret; +} +DECLARE_APPLY(DD4hep_Function,run_function) + /// Basic entry point to start the ROOT interpreter. /** * Factory: DD4hep_Rint diff --git a/DDG4/CMakeLists.txt b/DDG4/CMakeLists.txt index 99440da5e5408de8e0904dfaee188bb4a3a921aa..38687720772dd61ae0169e65e6992ce5ea754a64 100644 --- a/DDG4/CMakeLists.txt +++ b/DDG4/CMakeLists.txt @@ -14,6 +14,7 @@ dd4hep_package( DDG4 OPTIONAL CLHEP [XercesC QUIET] INCLUDE_DIRS include INSTALL_INCLUDES include/DDG4 ) +MESSAGE(STATUS "CLHEP_LIBRARIES ${CLHEP_LIBRARIES} ${CLHEP_LIBRARY}") #---Add Library--------------------------------------------------------------------- dd4hep_add_package_library(DDG4 SOURCES src/*.cpp ) #--------------------------- Legacy libraries (for Frank) ------------------------- diff --git a/cmake/DD4hepBuild.cmake b/cmake/DD4hepBuild.cmake index 23291e2fe4ec3c3f2a0863ac214b29e934938658..5944b301073619edfaeda34f69cf710187c05db5 100644 --- a/cmake/DD4hepBuild.cmake +++ b/cmake/DD4hepBuild.cmake @@ -15,7 +15,6 @@ message ( STATUS "INCLUDING DD4hepBuild.cmake" ) include ( CMakeParseArguments ) set ( DD4hepBuild_included ON ) - #--------------------------------------------------------------------------------------------------- macro(dd4hep_to_parent_scope val) set ( ${val} ${${val}} PARENT_SCOPE ) @@ -56,6 +55,9 @@ macro(dd4hep_set_compiler_flags) ENDIF() ENDFOREACH() + CHECK_CXX_COMPILER_FLAG("-std=c++17" CXX_FLAG_WORKS_CXX17) + CHECK_CXX_COMPILER_FLAG("-std=c++14" CXX_FLAG_WORKS_CXX14) + CHECK_CXX_COMPILER_FLAG("-std=c++11" CXX_FLAG_WORKS_CXX11) CHECK_CXX_COMPILER_FLAG("-ftls-model=global-dynamic" CXX_FLAG_WORKS_FTLS_global_dynamic) if (CXX_FLAG_WORKS_FTLS_global_dynamic) @@ -65,6 +67,23 @@ macro(dd4hep_set_compiler_flags) endif() find_package(Threads REQUIRED) + if ( DD4HEP_USE_CXX17 ) + message( FATAL_ERROR "Using the C++17 standard" ) + set ( CMAKE_CXX_FLAGS "-std=c++17 -ftls-model=global-dynamic ${CMAKE_CXX_FLAGS} ") + #set ( DD4HEP_USE_CXX11 OFF ) + set ( DD4HEP_USE_STDCXX 17 ) + add_definitions(-DDD4HEP_USE_STDCXX=17) + elseif ( DD4HEP_USE_CXX14 ) + set ( CMAKE_CXX_FLAGS "-std=c++14 -ftls-model=global-dynamic ${CMAKE_CXX_FLAGS} ") + #set ( DD4HEP_USE_CXX11 OFF ) + set ( DD4HEP_USE_STDCXX 14 ) + add_definitions(-DDD4HEP_USE_STDCXX=14) + else() + set ( CMAKE_CXX_FLAGS "-std=c++11 -ftls-model=global-dynamic ${CMAKE_CXX_FLAGS} ") + #set ( DD4HEP_USE_CXX14 OFF ) + set ( DD4HEP_USE_STDCXX 11 ) + add_definitions(-DDD4HEP_USE_STDCXX=11) + endif() if ( THREADS_HAVE_PTHREAD_ARG OR CMAKE_USE_PTHREADS_INIT ) set ( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread") @@ -276,6 +295,8 @@ function( dd4hep_print_cmake_options ) dd4hep_print ( "| Requires LCIO_DIR to be set |") dd4hep_print ( "| or LCIO in CMAKE_MODULE_PATH |") dd4hep_print ( "| DD4HEP_USE_GEAR Build gear wrapper for backward compatibility OFF |") + dd4hep_print ( "| DD4HEP_USE_CXX17 Build DD4hep using c++17 OFF |") + dd4hep_print ( "| DD4HEP_USE_CXX14 Build DD4hep using c++14 OFF |") dd4hep_print ( "| BUILD_TESTING Enable and build tests ON |") dd4hep_print ( "| DD4HEP_USE_PYROOT Enable 'Detector Builders' based on PyROOT OFF |") dd4hep_print ( "+---------------------------------------------------------------------------+") @@ -307,16 +328,16 @@ macro ( dd4hep_configure_output ) set ( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR}/bin ) endif() #------------- set the default installation directory to be the source directory - dd4hep_debug( "DD4hep_configure_output: CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT=${CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT}" ) + dd4hep_debug( "dd4hep_configure_output: CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX} CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT=${CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT}" ) if ( NOT "${ARG_INSTALL}" STREQUAL "" ) set ( CMAKE_INSTALL_PREFIX ${ARG_INSTALL} CACHE PATH "Set install prefix path." FORCE ) dd4hep_print( "DD4hep_configure_output: set CMAKE_INSTALL_PREFIX to ${ARG_INSTALL}" ) elseif ( CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT ) set( CMAKE_INSTALL_PREFIX ${CMAKE_SOURCE_DIR} CACHE PATH "install prefix path - overwrite with -D CMAKE_INSTALL_PREFIX = ..." FORCE ) - dd4hep_print ( "DD4hep_configure_output: CMAKE_INSTALL_PREFIX is ${CMAKE_INSTALL_PREFIX} - overwrite with -D CMAKE_INSTALL_PREFIX" ) + dd4hep_print ( "|++> dd4hep_configure_output: CMAKE_INSTALL_PREFIX is ${CMAKE_INSTALL_PREFIX} - overwrite with -D CMAKE_INSTALL_PREFIX" ) elseif ( CMAKE_INSTALL_PREFIX ) - dd4hep_print( "DD4hep_configure_output: set CMAKE_INSTALL_PREFIX to ${CMAKE_INSTALL_PREFIX}" ) + dd4hep_print( "|++> dd4hep_configure_output: set CMAKE_INSTALL_PREFIX to ${CMAKE_INSTALL_PREFIX}" ) set ( CMAKE_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX} ) endif() dd4hep_debug("|++> Installation goes to: ${CMAKE_INSTALL_PREFIX} <${ARG_INSTALL}>" ) diff --git a/cmake/DD4hepConfig.cmake.in b/cmake/DD4hepConfig.cmake.in index a61dcf79eccd926b37db23d9b44a518cc6caa700..6c843ba17eb2cd0d7a43b1768fb1fe7349da9147 100644 --- a/cmake/DD4hepConfig.cmake.in +++ b/cmake/DD4hepConfig.cmake.in @@ -72,13 +72,13 @@ endif() CHECK_PACKAGE_LIBS(DD4hep DDCore) IF(DD4hep_FIND_COMPONENTS) - MESSAGE( STATUS "DD4hep: Looking for Components: ${DD4hep_FIND_COMPONENTS}" ) + dd4hep_print( "|++> DD4hep: Looking for Components: ${DD4hep_FIND_COMPONENTS}" ) FOREACH(comp ${DD4hep_FIND_COMPONENTS}) #CHECK_PACKAGE_LIBS is looking for components too, just need to check if they were found, if requested STRING( TOUPPER ${comp} _ulibname ) if(NOT DD4hep_${_ulibname}_FOUND) - MESSAGE(FATAL_ERROR "Did not find required component: ${comp}") + MESSAGE(FATAL_ERROR "|++> Did not find required component: ${comp}") ENDIF() ENDFOREACH() ENDIF() diff --git a/cmake/DD4hepMacros.cmake b/cmake/DD4hepMacros.cmake index 50ccad2061673fa4e83d52a774344deb88d93a4a..f09f28dcc4a53d0b36a45471970ae63013cdbf71 100644 --- a/cmake/DD4hepMacros.cmake +++ b/cmake/DD4hepMacros.cmake @@ -147,9 +147,9 @@ MACRO( CHECK_PACKAGE_LIBS _pkgname ) ENDIF() IF( NOT ${_pkgname}_FIND_QUIETLY ) - MESSAGE( STATUS "Check for ${_pkgname}_LIBRARIES: ${_std_libnames}" ) + MESSAGE( STATUS "|++> Check for ${_pkgname}_LIBRARIES: ${_std_libnames}" ) IF( _ext_libnames ) - MESSAGE( STATUS "Check for ${_pkgname}_COMPONENT_LIBRARIES: ${_ext_libnames}" ) + MESSAGE( STATUS "|++> Check for ${_pkgname}_COMPONENT_LIBRARIES: ${_ext_libnames}" ) ENDIF() ENDIF() @@ -220,7 +220,7 @@ MACRO( CHECK_PACKAGE_LIBS _pkgname ) LIST( APPEND ${_pkgname}_LIBRARY_DIRS ${_aux} ) IF( NOT ${_pkgname}_FIND_QUIETLY ) - MESSAGE( STATUS "Check for ${_pkgname}_${_ulibname}_LIBRARY: ${${_pkgname}_${_ulibname}_LIBRARY} -- ok" ) + MESSAGE( STATUS "|++> Check for ${_pkgname}_${_ulibname}_LIBRARY: ${${_pkgname}_${_ulibname}_LIBRARY} -- ok" ) ENDIF() ELSE() # library not found @@ -234,7 +234,7 @@ MACRO( CHECK_PACKAGE_LIBS _pkgname ) ENDIF() IF( NOT ${_pkgname}_FIND_QUIETLY ) - MESSAGE( STATUS "Check for ${_pkgname}_${_ulibname}_LIBRARY: ${_libname} -- failed" ) + MESSAGE( STATUS "|++> Check for ${_pkgname}_${_ulibname}_LIBRARY: ${_libname} -- failed" ) ENDIF() ENDIF() diff --git a/cmake/MakeGaudiMap.cmake b/cmake/MakeGaudiMap.cmake index cea1478035c8005bcd75517dae9f63e25efb6e4c..12da90c2d4f358fe693720539a2ac622a8e8fbcd 100644 --- a/cmake/MakeGaudiMap.cmake +++ b/cmake/MakeGaudiMap.cmake @@ -12,6 +12,7 @@ message(STATUS " *** Gaudi listcomponents: Generate map for ${libname} ..." ) SET ( ENV{DYLD_LIBRARY_PATH} ${genmap_install_dir}:$ENV{DYLD_LIBRARY_PATH}:$ENV{DD4HEP_LIBRARY_PATH} ) else() SET ( ENV{LD_LIBRARY_PATH} ${genmap_install_dir}:$ENV{LD_LIBRARY_PATH} ) + #SET ( ENV{LD_PRELOAD} /lib64/libglapi.so ) endif() # EXECUTE_PROCESS( COMMAND echo LD_LIBRARY_PATH = $ENV{LD_LIBRARY_PATH} ) EXECUTE_PROCESS( COMMAND diff --git a/doc/usermanuals/DDAlign/DDAlignManual.tex b/doc/usermanuals/DDAlign/DDAlignManual.tex index 7535fe32523f696bda26bc50e31b722cc447247d..33d57568fdc949a16d5208a0931be4db27f32833 100644 --- a/doc/usermanuals/DDAlign/DDAlignManual.tex +++ b/doc/usermanuals/DDAlign/DDAlignManual.tex @@ -110,22 +110,49 @@ To avoid confusion within this document, a few terms need to be defined with respect to detector alignment: \begin{itemize}\itemcompact \item The {\it{ideal geometry}} describes the detector as it was designed. - Such a detector is an utopic object, which can never be realized in terms + Such a detector is an utopia, which can never be realized in terms of the placement of the individual components as such. -\item The {\it{actual geometry}} describes the real detector - in the configuration at - a given time. This includes all the changes i.e. {\it{deltas}} to the - {\it{ideal}} geometry. These changes are also called the - {\it{alignment parameters}}. These parameters typically are only valid - for a defined time interval. -\item {\it{Realignment}} defines the procedure to apply a new set of - temporary {\it{misalignment parameters}} to the ideal geometry. - Such a procedure - is applied, if a previously applied set of parameters is no longer valid with - respect to the event data to be processed. In short {\it{realignment}} - is necessary if the {\it{actual geometry}} of the detector is time dependent. +\item The {\it{actual geometry}} describes - as a first approximation + to the real world - the real detector at a given time valid for a rather + significant amount of time e.g. for a year of data taking. + The {\it{actual geometry}} typically includes corrections deduced + e.g. from optical surveys etc. The {\it{actual geometry}} does not + change during the life-time of an analysis or calibration process. + In the following this is called {\it{Global Alignment}}. + The transformation of the ideal geometry to the actual geometry + is steered by alignment parameters aka {\it{Alignment Deltas}}. + Such {\it{deltas}} may be applied at any level of the geometrical + hierarchy. + In short, the {\it{actual geometry}} results from the {\it{ideal geometry}} + after applying the global {\it{Alignment Deltas}} and is then + the {\it{geometry in memory}}. The ROOT geometry + toolkit is the only one, which allows for global alignment procedures + \footnote{A conversion of this geometry e.g. to Geant4 (using the functionality + provided by \DDG allow to simulate distorted geometries with the Geant4 toolkit.}. +\item {\it{Realignment}} then defines the procedures to correct data + collected in particle collisions. These data are taken with the real, + a priori unknown geometry, which on top of the actual geometry suffers + from small shifts e.g. due to temperature or pressure changes. These + shifts normally are frequently computed by specialized applications + with respect to the to the actual geometry and typically are valid + for relatively short time periods \cal{O}(1 hour). These shifts, called + {\it{Alignment Deltas}}, are used to re-align the detector response + for physics analysis. This process in the following is called + {\it{Local Alignment}}. + The handling of the {\it{Alignment Deltas}} for local alignments in fact + is very similar to the handling of detector conditions implemented in the + package \DDC\cite{bib:DDCond}. + In section~\ref{sect:ddalign-local-aligments} + this issue is further elaborated. \end{itemize} +\noindent +Technically the {\it{Alignment Deltas}} used for the global alignment +and the {\it{Alignment Deltas}} used for the local alignment are identical. +Though it should be stressed that the use is entirely different: +Whereas the first actually alter the geometry, the latter are only used +to properly interpret the data collected. + \noindent \DDA formalizes both the access and the application of alignment parameters to the ideal geometry. The possibility to properly describe actual geometries @@ -175,7 +202,7 @@ the all TPC geometrical dimensions, the alignment and calibration constants and other slow varying conditions such as the gas pressure, end-plate temperatures etc. The $Detector$ $Element$ acts as a data concentrator. Applications may access the full experiment geometry and all connected data -through a singleton object called $LCDD$, which provides +through a singleton object of type $Detector$, which provides management, bookkeeping and ownership to the model instances. \noindent @@ -260,13 +287,15 @@ a volume it is e.g. irrelevant if the volume is sensitive or not. \end{center} \end{figure} - - %============================================================================= -\subsection{Alignment Parameters of Detector Components} +\section{Global Alignment} +\label{sect:ddalign-global-aligments} +%============================================================================= +\subsection{Global Alignment of Detector Components} \label{subsect:ddalign-intro-aligments} %============================================================================= \noindent +In this section the backgrounds of the {\it{Global Alignment}} is described. Alignment parameters never apply in the same way to {\it{all}} placements of the same volume in this hierarchy. Hence, to (re-)align a volume in the hierarchy means to logically lift a full branch of placements from the top volume down to @@ -354,30 +383,6 @@ rotation or both with a pivot point in the origin. These simplifications are supported in the user interface described in Section~\ref{sec:ddalign-user-manual-ddalign-interface}. -\noindent -Generally such a behavior can be achieved in two ways. The usage strongly depends -on the use-case required by the client: -\begin{enumerate} -\item either the ideal geometry in memory is changed directly to - reflect the measured geometry. This approach has the - disadvantage, that all measurement points on a daughter - volume can only be transformed to the global coordinate - system using one single transformation. Time-dependent changes of - these transformations cannot be modeled. Hence, for multi-threaded - systems this approach is of limited use. However, this is the - perfect approach to simulate distorted geometries. This approach - is naturally supported by the ROOT geometry toolkit. -\item The second possibility is to not modify the ideal geometry in memory, - but to provide instead transformations to move measured coordinates - to their correct place in space. This approach allows to keep - several - also time-dependent - transformations in memory. - Ideal to support multi-threaded data processing frameworks, - which become more and more popular. -\end{enumerate} - -\noindent -\DDA supports both possibilities as will be described in the following sections. - %============================================================================= \begin{figure}[t] \begin{center} @@ -396,14 +401,16 @@ on the use-case required by the client: \end{figure} %============================================================================= -\subsection{Iterative Application of Alignments} +\subsection{Iterative Application of Global Alignments} \label{subsect:ddalign-intro-iterative-alignments} %============================================================================= \noindent -In the general case a given set of alignment parameters is not static and -may very well change with time. For this reason it is highly important to -support not only one single realignment step. -Hence, the following scenario is an important use case: +Technically it is possible to apply global alignment procedures iteratively. +This however id {\bf{deprecated}} and violates thread safety for the simple reason +that the {\it{geometry in memory}} is altered. If applied, it is duty of the +client framework to ensure that during the change of global alignment +no processing of event data is ongoing. +Hence, the procedure is described here only for completeness: \begin{enumerate}\itemcompact \item Create the ideal detector using an ideal geometry. \item Apply a set of alignment parameters for a given time @@ -420,7 +427,7 @@ Section~\ref{sec:ddalign-user-manual-ddalign-interface} the implementation to realize this use case is described. %============================================================================= -\subsection{Procedures to Determine Alignment Parameters} +\subsection{Procedures to Determine Global Alignment Parameters} \label{subsect:ddalign-intro-determine-alignment-params} %============================================================================= \noindent @@ -436,12 +443,11 @@ are, like the alignment parameters, provided in terms of {\it{changes}} with respect to the ideal position and hence may be treated in a similar way. \noindent -The survey parameters are - like alignment parameters - accessible to users +The survey parameters are accessible to users through the interface offered by the $DetElement$ objects. - %============================================================================= -\subsection{Simulation of Non-Ideal, Real Detector Geometries} +\subsection{Simulation of Non-Ideal Detector Geometries} \label{subsect:ddalign-intro-simulate-misaligned-geometries} %============================================================================= \noindent @@ -480,20 +486,21 @@ section~\ref{sec:ddalign-user-manual-ddalign-global-interface}. \newpage %============================================================================= -\section{The Global Alignment Interface} +\subsection{The Global Alignment Interface} \label{sec:ddalign-user-manual-ddalign-global-interface} %============================================================================= \noindent In this chapter will be documented how to use the $Global$ $Alignment$ interface of \DDA. As already mentioned in -section~\ref{}, this interface allows to alter the layout of the +section~\ref{sec:ddalign-user-manual-introduction}, +this interface allows to alter the layout of the geometry in memory. Use cases are e.g. the simulation of non-ideal geometries. \noindent Global alignment can be applied to detector elements using a specialized -interface $GlobalDetectorAlignment$~\footnote{See the header file +interface {\it{GlobalDetectorAlignment}}~\footnote{See the header file $DDAlign/GlobalDetectorAlignment.h$ for details.}. This interface provides the API to apply global changes to the geometry provided the presence of alignment parameters as shown in the following @@ -501,7 +508,8 @@ code snippet: \begin{code} /// First install the global alignment cache to build proper transactions - GlobalAlignmentCache* cache = GlobalAlignmentCache::install(lcdd); + Detector& detector = ...; + GlobalAlignmentCache* cache = GlobalAlignmentCache::install(detector); /// Now create the tranaction context. There may only be one context present GlobalAlignmentStack::create(); @@ -526,29 +534,37 @@ code snippet: {\bf{Explanation:}} \\ \begin{tabular} {l||p{0cm}} \docline{Line}{} -\docline{2}{Install the $GlobalAlignmentCache$. Required to be done -once. The object is registered to the LCDD instance and kept there.} -\docline{2-7}{The fact that the classes $GlobalAlignmentCache$ and +\docline{3}{Install the $GlobalAlignmentCache$. Required to be done +once. The object is registered to the $Detector$ instance and kept there.} +\docline{3-8}{The fact that the classes $GlobalAlignmentCache$ and $GlobalAlignmentStack$ are singletons is not a fundamental issue. However, we want to call the XML parser (or other database sources) iteratively and currently cannot chain a context (stack).} -\docline{15-19}{The created stacked entries are automatically released +\docline{16-21}{The created stacked entries are automatically released once the transaction is committed.} \end{tabular} +\noindent +Please note, that this interface normally is not directly invoked +by users, but rather called by plugin mechanisms as the one described below +capable of reading the global misalignments from XML. + \noindent %============================================================================= \subsubsection{Loading Global Geometrical Imperfections from XML} \label{sec:ddalign-user-manual-global-misalignment-manip-xml} %============================================================================= \noindent -In this section we describe how to load geometry imperfections and to apply them +In this section we describe how to load global geometry +imperfections and to apply them to an existing geometry. Loading the XML file is done automatically using the -standard XML loader plugin provided by \DDhep. This plugin is interfaced to -the {\tt LCDD} instance and invoked from code as follows: +standard XML loader plugin provided by \DDhep. This mechanism is favoured and +much simpler than programming the global misalignment directly. +This plugin is interfaced to +the {\tt Detector} instance and invoked from code as follows: \begin{code} - LCDD& lcdd = ....; - lcdd.fromXML("file:AlepTPC_alignment.xml"); + Detector& detector = ....; + detector.fromXML("file:AlepTPC_alignment.xml"); \end{code} To fully exploit the capabilities it is important to understand the interpreted structure of the XML file being processed. At the top level of the primary @@ -649,15 +665,12 @@ coordinate system of the closest mother-volume in the volume hierarchy, i.e. translations, rotations and pivot points are local to the mother coordinate system. -\newpage \noindent Included files may directly start with the {\tt root} tags {\tt subdetectors}, {\tt detelements} or {\tt detelement} and may recursively include other files. Except for the top level these files are processed in the calling context. +The result of this procedure is shown in Figure~\ref{fig:dd4hep-aligned-hierarchies}. -\vspace{1cm} -\noindent -And finally, the result: %============================================================================= \begin{figure}[h] \begin{center} @@ -681,10 +694,10 @@ In this section we describe how to export geometry imperfections to an XML file. A small helper class {\tt AlignmentWriter} achieves this task as shown in the snippet: \begin{code} - LCDD& lcdd = ....; - DetElement top = ....; + Detector& detector = ....; + DetElement top = detector.world(); if ( top.isValid() ) { - AlignmentWriter wr(lcdd); + AlignmentWriter wr(detector); return wr.write(top,output,enable\_transactions); } \end{code} @@ -696,14 +709,56 @@ file. The output file conforms to the specifications described in Section~\ref{sec:ddalign-user-manual-misalignment-manip-xml} and may later be imported by another process. +\noindent +{\bf{FIXME: This chapter sort of still has to be written/completed!!!!}} +\newpage +\section{Up to here the manual should be pretty much correct.\\ +Everything below is at least questionable.} -\vspace{3cm} -\noindent -FIXME: This chapter sort of still has to be written!!!! +%============================================================================= +\section{Local Alignment} +\label{sect:ddalign-local-aligments} +%============================================================================= +bla bla bla %%%% Here we are now. + + + + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + + +\noindent +Generally such a behavior can be achieved in two ways. The usage strongly depends +on the use-case required by the client: +\begin{enumerate} +\item either the ideal geometry in memory is changed directly to + reflect the measured geometry. This approach has the + disadvantage, that all measurement points on a daughter + volume can only be transformed to the global coordinate + system using one single transformation. Time-dependent changes of + these transformations cannot be modeled. Hence, for multi-threaded + systems this approach is of limited use. However, this is the + perfect approach to simulate distorted geometries. This approach + is naturally supported by the ROOT geometry toolkit. +\item The second possibility is to not modify the ideal geometry in memory, + but to provide instead transformations to move measured coordinates + to their correct place in space. This approach allows to keep + several - also time-dependent - transformations in memory. + Ideal to support multi-threaded data processing frameworks, + which become more and more popular. +\end{enumerate} + +\noindent +\DDA supports both possibilities as will be described in the following sections. + + + \vspace{3cm} \newpage @@ -908,7 +963,7 @@ There are multiple possibilities to apply alignment parameters: In this section we describe how to apply geometry imperfections to an existing detector geometry in memory using {\tt C++}. To apply misalignment to an existing geometry two classes are collaborating, the {\tt AlignmentCache} attached to -the geometry container {\tt LCDD} and a temporary structure the {\tt AlignmentStack}. +the geometry container {\tt Detector} and a temporary structure the {\tt AlignmentStack}. The {\tt AlignmentCache} allows to access all existing alignment entries based on their subdetector. The {\tt AlignmentStack} may exist in exactly one instance and is used to @@ -933,8 +988,8 @@ opening and closing a transaction: // Required include file(s) #include "DDAlign/AlignmentCache.h" - LCDD& lcdd = ....; - AlignmentCache* cache = lcdd.extension<Geometry::AlignmentCache>(); + Detector& detector = ....; + AlignmentCache* cache = detector.extension<Geometry::AlignmentCache>(); // First things first: open the transaction. cache->openTransaction(); @@ -1060,6 +1115,7 @@ the geometry. For further shortcuts in the calling sequence please consult the \bibitem{bib:geant4} S. Agostinelli et al., "Geant4 - A Simulation Toolkit", \\ Nuclear Instruments and Methods {\bf{A}} 506 (2003) 250-303. +\bibitem{bib:DDCond} M.Frank, "DDCond -- Conditions Support for the DD4hep Geometry Description Toolkit". \end{thebibliography} %============================================================================= diff --git a/doc/usermanuals/DDCond/DDCondManual.tex b/doc/usermanuals/DDCond/DDCondManual.tex index 115edffee6cdeda4d61811cea8d9f840f78dac37..8f2b9a914aaf47b23df52ac5f3808767e319d2d3 100644 --- a/doc/usermanuals/DDCond/DDCondManual.tex +++ b/doc/usermanuals/DDCond/DDCondManual.tex @@ -35,7 +35,7 @@ M. Frank \\ \normalsize Experimental setups in High Energy Physics are highly complex assemblies consisting of various detector devices typically called {\it{subdetectors}}. -To properly interprete the electronic signals which form the response of +To properly interpret the electronic signals which form the response of particle collisions inside these subdetectors other auxiliary data are necessary. These auxiliary data typically are time dependent - though normally at a much longer scale than the event data itself. The conditions part of the diff --git a/examples/CLICSiD/CMakeLists.txt b/examples/CLICSiD/CMakeLists.txt index 77ac2587a77073e12b1a6694723fee4cc5a3d659..60d1f1aa67fccbe227fa6f22495894944651e6ce 100644 --- a/examples/CLICSiD/CMakeLists.txt +++ b/examples/CLICSiD/CMakeLists.txt @@ -145,4 +145,11 @@ if (DD4HEP_USE_GEANT4) REGEX_PASS "UserEvent_1 INFO Geant4TestEventAction> calling end.event_id=9" REGEX_FAIL "Exception;EXCEPTION;ERROR;Error" ) endforeach(script) + # + # Invoke G4 multi-threading tests if enabled + if (Geant4_TLS_MODEL) + dd4hep_print("|++> Geant4 Multi-threading ENABLED. Configuring multi-threaded DDG4 tests.") + else() + dd4hep_print("|++> Geant4 Multi-threading NOT ENABLED. Shall not execute multi-threaded DDG4 tests.") + endif() endif() diff --git a/examples/ClientTests/CMakeLists.txt b/examples/ClientTests/CMakeLists.txt index 5dc1900945f84b689c5727c19b9a78a160bb9549..f7d19a0c463c45a9ac834e47ac442ad81635154a 100644 --- a/examples/ClientTests/CMakeLists.txt +++ b/examples/ClientTests/CMakeLists.txt @@ -185,6 +185,14 @@ endforeach() # foreach (test BoxTrafos IronCylinder MiniTel SiliconBlock NestedSimple MultiCollections ) # + # Read data from XML file. Then parse the pure XML string. + dd4hep_add_test_reg( ClientTests_parse_xml_string_${test} + COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh" + EXEC_ARGS geoPluginRun -destroy -print WARNING + -plugin DD4hep_XML_InMemory -input ${CMAKE_CURRENT_SOURCE_DIR}/compact/${test}.xml + -plugin DD4hep_VolumeDump -materials + REGEX_PASS "\\+\\+\\+ Checked [1-9][0-9]* materials in volume placements. 0 are BAD." ) + # # ROOT Geometry checks dd4hep_add_test_reg( ClientTests_check_geometry_${test}_LONGTEST COMMAND "${CMAKE_INSTALL_PREFIX}/bin/run_test_ClientTests.sh" diff --git a/examples/ClientTests/compact/BoxTrafos.xml b/examples/ClientTests/compact/BoxTrafos.xml index 7d1f97b982f8c0352299686a5534b8fd9e0aedf7..c09dd0499f82fe8d28a97eeff7449328d686d59d 100644 --- a/examples/ClientTests/compact/BoxTrafos.xml +++ b/examples/ClientTests/compact/BoxTrafos.xml @@ -32,14 +32,14 @@ <detectors> <comment>Boxes</comment> - <detector id="3" name="B3" type="BoxSegment" vis="B2_vis"> + <detector id="3" name="B3" type="DD4hep_BoxSegment" vis="B2_vis"> <comment>Vertical box</comment> <material name="Steel235"/> <box x="10" y="20" z="30"/> <position x="-10" y="30" z="10"/> <rotation x="0" y="0" z="0"/> </detector> - <detector id="3" name="B4" type="BoxSegment" vis="B1_vis"> + <detector id="3" name="B4" type="DD4hep_BoxSegment" vis="B1_vis"> <comment>Vertical box</comment> <material name="Steel235"/> <box x="10" y="20" z="30"/> diff --git a/examples/ClientTests/src/LheD_tracker_BeamPipe_geo.cpp b/examples/ClientTests/src/LheD_tracker_BeamPipe_geo.cpp index 88d9f6f23bc43094ddd1a7bcec9f10fed9ea0202..7fc480a9a00888652431c239cbaa88abbf3458e0 100644 --- a/examples/ClientTests/src/LheD_tracker_BeamPipe_geo.cpp +++ b/examples/ClientTests/src/LheD_tracker_BeamPipe_geo.cpp @@ -1,4 +1,3 @@ -// $Id: LhePolyconeSupport_geo.cpp 513 2013-04-05 14:31:53Z gaede $ //==================================================================== // AIDA Detector description implementation //-------------------------------------------------------------------- diff --git a/examples/ClientTests/src/XML_InMemory.cpp b/examples/ClientTests/src/XML_InMemory.cpp new file mode 100644 index 0000000000000000000000000000000000000000..75443c6d3d5a5775d3ba75a47458daba1edbb4bc --- /dev/null +++ b/examples/ClientTests/src/XML_InMemory.cpp @@ -0,0 +1,83 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +// Author : M.Frank +// +//========================================================================== +/* + Plugin invocation: + ================== + This plugin behaves like a main program. + Invoke the plugin with something like this: + + geoPluginRun -destroy -plugin DD4hep_XML-In-Memory -input <file name> + +*/ +// Framework include files +#include "DD4hep/Printout.h" +#include "DD4hep/Factories.h" +#include "DD4hep/DetectorLoad.h" +#include <fstream> +#include <cerrno> + +using namespace std; +using namespace dd4hep; + +/// Plugin function: Test in memory XML parsing of a simple sub detector +/** + * Factory: DD4hep_XML-In-Memory + * + * Though there is a file name given, it is read FIRST and then parsed. + * Similar to a in memory XML string. + * + * \author M.Frank + * \version 1.0 + * \date 20/01/2018 + */ +static int XML_In_Memory (Detector& detector, int argc, char** argv) { + string input; + bool arg_error = false; + for(int i=0; i<argc && argv[i]; ++i) { + if ( 0 == ::strncmp("-input",argv[i],4) ) + input = argv[++i]; + else + arg_error = true; + } + if ( arg_error || input.empty() ) { + /// Help printout describing the basic command line interface + cout << + "Usage: -plugin <name> -arg [-arg] \n" + " name: factory name DD4hep_AlignmentExample_read_xml \n" + " -input <string> Geometry file \n" + "\tArguments given: " << arguments(argc,argv) << endl << flush; + ::exit(EINVAL); + } + ifstream is (input, ifstream::binary); + if (is) { + // get length of file: + is.seekg (0, is.end); + int length = is.tellg(); + is.seekg (0, is.beg); + char* buffer = new char[length+1]; + printout(INFO,"Read","Read a total of %ld charactors from %s.", + length, input.c_str()); + // read data as a block: + is.read (buffer,length); + buffer[length] = 0; + /// So here is the actual test: We parse the raw XML string + DetectorLoad loader(detector); + loader.processXMLString(buffer,0); + return 1; + } + printout(INFO,"Read","FAILED to load xml data from %s [%s].", + input.c_str(), ::strerror(errno)); + return 0; +} + +DECLARE_APPLY(DD4hep_XML_InMemory,XML_In_Memory)