diff --git a/ForwardDetectors/AFP/AFP_DBTools/AFP_DBTools/DBObjectBuilder.h b/ForwardDetectors/AFP/AFP_DBTools/AFP_DBTools/DBObjectBuilder.h new file mode 100644 index 0000000000000000000000000000000000000000..2be342dc98e0b6e59732f6dd2d9af22a667217c9 --- /dev/null +++ b/ForwardDetectors/AFP/AFP_DBTools/AFP_DBTools/DBObjectBuilder.h @@ -0,0 +1,164 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** + * @file DBObjectBuilder.h + * @author Grzegorz Gach <grzegorz.gach@cern.ch> + * @date 2018-01-16 + * + * @brief Header file for base class for database objects builders + * + */ + +#ifndef AFP_DBTOOLS_DBOBJECTBUILDER_H +#define AFP_DBTOOLS_DBOBJECTBUILDER_H + +#include "DBObjectBuilderBase.h" + +#include <boost/property_tree/ptree.hpp> + +#include <vector> +#include <string> +#include <list> + +namespace AFP +{ + + /// @brief Base class for builders producing objects based on database information. + /// + /// Classes building database objects should derive from this + /// template. It should be enough to override only + /// DBObjectBuilderBase::addBuilderCommand function. + template<typename OUTPUT_TYPE> + class DBObjectBuilder : public DBObjectBuilderBase + { + public: + /// Deletes #m_inputData + virtual ~DBObjectBuilder () {for (CommandBase* comm : m_commands) delete comm;} + + /// The method sets value of the given field of #m_object. + /// + /// @param field pointer to class member field which value is to be set + /// @param value value to be assigned to the field + template <typename VALUE_TYPE> + void setFieldValue (VALUE_TYPE OUTPUT_TYPE::* const field, const VALUE_TYPE value) + {if (field) m_object->*field = value;} + + /// @brief Method creating a database object based on passed input data. + /// + /// The method creates a new output database object and fills with + /// data from the input argument. + OUTPUT_TYPE build (const boost::property_tree::ptree::value_type& inputData); + + /// @copydoc DBObjectbuilder::generateBuilderCommands + std::string generateBuilderCommands () override final; + + /// @brief This method adds new command objects to the list depending on argument + /// + /// This is the only method that needs to be overridden when + /// creating a new builder. + /// + /// @param name name of the element in database + /// + /// @return true if name was recognised, false if not + virtual bool addBuilderCommand (const std::string& name) = 0; + + protected: + // --------------- NESTED CLASSES --------------- + /// Nested class base for storing commands for building objects + class CommandBase + { + public: + /// Does nothing + virtual ~CommandBase() {} + + /// Execute method which calls proper method of the DBObjectBuilder in order to create output object. + virtual void executeSetFieldValue (const boost::property_tree::ptree::value_type& inputData, DBObjectBuilder<OUTPUT_TYPE>* parentObject) const = 0; + }; + + /// Template of nested command class that calls the method setting the object value with proper type. + template <typename VALUE_TYPE> + class Command : public CommandBase + { + public: + /// Sets pointer to the output object field to be set + Command (VALUE_TYPE OUTPUT_TYPE::*field) : m_field (field) {} + + /// Does nothing + virtual ~Command() {} + + /// @copydoc CommandBase::executeSetfieldvalue + void executeSetFieldValue (const boost::property_tree::ptree::value_type& inputData, DBObjectBuilder<OUTPUT_TYPE>* parentObject) const override + {parentObject->setFieldValue<VALUE_TYPE>(m_field, inputData.second.get_value<VALUE_TYPE>());} + + protected: + /// Pointer to class member to be set by this command. + VALUE_TYPE OUTPUT_TYPE::*m_field; + }; + // --------------- END NESTED CLASSES --------------- + + /// List of commands used for creating an object. The order is important. + std::list<CommandBase*> m_commands; + + /// Pointer to the conditions object that is being set. Used by the DBObjectBuilder::build method. + OUTPUT_TYPE* m_object; + + }; // end of DBObjectBuilder class declaration + + + // ============================================== + // =============== IMPLEMENTATION =============== + // ============================================== + + template<typename OUTPUT_TYPE> + std::string DBObjectBuilder<OUTPUT_TYPE>::generateBuilderCommands () + { + // clear list of commnads + for (CommandBase* comm : this->m_commands) + delete comm; + this->m_commands.clear(); + + + // fill list with commands + std::stringstream unknownVariables; + for (const std::vector<std::string>& element : this->m_specification) + if (addBuilderCommand(element[0]) == false) + unknownVariables<<element[0]<<", "; + + std::stringstream warningMessage; + // if list of unknown variables is not empty generate warning message + if (!unknownVariables.str().empty()) + warningMessage <<"DBObjectBuilder will skip following variables present in database: "<<unknownVariables.str(); + + return warningMessage.str(); + } + + + template<typename OUTPUT_TYPE> + OUTPUT_TYPE DBObjectBuilder<OUTPUT_TYPE>::build (const boost::property_tree::ptree::value_type& inputData) + { + OUTPUT_TYPE output; + m_object = &output; + typedef std::list<DBObjectBuilder<OUTPUT_TYPE>::CommandBase*> CommandsList_t; + + typename CommandsList_t::const_iterator commandIter = m_commands.begin(); + const typename CommandsList_t::const_iterator commandIterEnd = m_commands.end(); + for (const boost::property_tree::ptree::value_type& data : inputData.second) { + if (commandIterEnd != commandIter) { + DBObjectBuilder<OUTPUT_TYPE>::CommandBase* comm = *commandIter; + ++commandIter; + + comm->executeSetFieldValue(data, this); + } + } + + m_object = nullptr; + + return output; + } + + +} // namespace AFP + +#endif // AFP_DBTOOLS_DBOBJECTBUILDER_H diff --git a/ForwardDetectors/AFP/AFP_DBTools/AFP_DBTools/DBObjectBuilderBase.h b/ForwardDetectors/AFP/AFP_DBTools/AFP_DBTools/DBObjectBuilderBase.h new file mode 100644 index 0000000000000000000000000000000000000000..df9c68a4678440cf7974d2711b9c9191265b4383 --- /dev/null +++ b/ForwardDetectors/AFP/AFP_DBTools/AFP_DBTools/DBObjectBuilderBase.h @@ -0,0 +1,91 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** + * @file DBObjectBuilderBase.h + * @author Grzegorz Gach <grzegorz.gach@cern.ch> + * @date 2018-01-19 + * + * @brief Header file for DBObjectBuilderBase class + * + */ + +#include<string> +#include<vector> + +namespace AFP +{ + + /// @brief Class parsing conditions database specification + /// + /// This class contains DBObjectBuilder methods which do not need + /// templates. + class DBObjectBuilderBase + { + public: + /// Does nothing + virtual ~DBObjectBuilderBase() {} + + /// @brief Parses specification string from database and prepare + /// list of builder methods. + /// + /// @param specification a string with specification format is + /// described in: + /// https://twiki.cern.ch/twiki/bin/view/AtlasComputing/JsonFormatForCrest + /// + /// @return string with warning message - should be used to report + /// not recognised variables names in the database (the message is + /// returned instead of being printed because this is not Athena + /// algorithm) + std::string setSpecification (const std::string specification); + + /// @brief Creates a list of Command objects to be called when + /// reading database record. + /// + /// This method generates a list of builder command objects + /// DBObjectBuilder::m_commands that will construct output object + /// in the same order as information in the database is + /// saved. When object is being build the input data and list of + /// commands are iterated simultaneously and input data element is + /// passed as an argument to the corresponding command from the + /// list. + /// + /// The list of commands is generated based on #m_specification. + /// + /// @note For each field in the database there should be a + /// corresponding command object. If the database field is not + /// processed a command object with nullptr should be created. + /// + /// @return string with warning message - should be used to report + /// not recognised variables names in the database (the message is + /// returned instead of being printed because this is not Athena + /// algorithm) + virtual std::string generateBuilderCommands () = 0; + + protected: + /// Calls DBObjectBuilderBase::trimSpaces (std::string) for each string in the vector + void trimSpaces (std::vector<std::string>& toTrim) const; + + /// Removes spaces from the beginning and end of the string + void trimSpaces (std::string& toTrim) const; + + /// @brief Parses payload specification string and saves output to vector + /// + + /// Payload specification stream format is described in: + /// https://twiki.cern.ch/twiki/bin/view/AtlasComputing/JsonFormatForCrest + /// The function splits the string into pairs name-type and saves + /// them as a vector of strings with two elements. All pairs are + /// added to a global output vector. + void parsePayloadSpec (const std::string& input, std::vector< std::vector<std::string> >& output) const; + + /// @brief vector describing format of the data saved in the database + /// + /// A vector of vectors. Each subvector contains exactly two + /// elements: name and type. The elements are in the same order as + /// data. + std::vector< std::vector<std::string> > m_specification; + }; + +} // AFP namespace diff --git a/ForwardDetectors/AFP/AFP_DBTools/AFP_DBTools/ISiLocAlignDBTool.h b/ForwardDetectors/AFP/AFP_DBTools/AFP_DBTools/ISiLocAlignDBTool.h new file mode 100644 index 0000000000000000000000000000000000000000..94f450024928cb47ee6341bdce99f1067bb2d6d3 --- /dev/null +++ b/ForwardDetectors/AFP/AFP_DBTools/AFP_DBTools/ISiLocAlignDBTool.h @@ -0,0 +1,72 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/// @file ISiLocAlignDBTool.h +/// @author Grzegorz Gach <gach@agh.edu.pl> +/// @date 2017-12-03 +/// +/// @brief Header file for interface of SiLocAlignDBTool used to read local alignment for database +#ifndef AFP_DBTOOLS_ISILOCALIGNDBTOOL_H +#define AFP_DBTOOLS_ISILOCALIGNDBTOOL_H + + +// FrameWork includes +#include "GaudiKernel/IAlgTool.h" + +// database access +#include "AthenaKernel/IOVSvcDefs.h" + +// general includes +#include <vector> +#include <memory> + +namespace AFP +{ + // forward declarations + class SiLocAlignData; + + static const InterfaceID IID_ISiLocAlignDBTool ("ISiLocAlignDBTool", 1, 0); + + + /// Interface to tool providing local alignment of silicon detectors from the conditions database. + class ISiLocAlignDBTool : virtual public IAlgTool + { + public: + static const InterfaceID &interfaceID() + {return IID_ISiLocAlignDBTool;} + + /// Does nothing + virtual ~ISiLocAlignDBTool() override {} + + /// Initilise tool + virtual StatusCode initialize() = 0; + + /// Finalise tool + virtual StatusCode finalize() = 0; + + /// Provide alignment parameters for a given plane. Returns nullptr if no data available. + virtual const SiLocAlignData* alignment (const int stationID, const int planeID) const = 0; + + /// Returns reference to a vector of alignments for a given station. + /// + /// It is enough to get this reference only once, because the + /// vector is a member of the class. Whenever new conditions are + /// loaded the values in the vector will be updated. + /// + /// @warning if in database there was no data about the given + /// layer a nullptr will be stored in the vector. + virtual const std::vector<std::unique_ptr<const SiLocAlignData> >& alignment (const int stationID) const = 0; + + + protected: + /// @brief Method called when new conditions are loaded + /// + /// The method copies information from #m_conditionsData to + virtual StatusCode update (IOVSVC_CALLBACK_ARGS) = 0; + }; + + +} // namespace AFP + +#endif // > ! AFP_DBTOOLS_SILOCALIGNDBTOOL_H diff --git a/ForwardDetectors/AFP/AFP_DBTools/AFP_DBTools/SiLocAlignDBTool.h b/ForwardDetectors/AFP/AFP_DBTools/AFP_DBTools/SiLocAlignDBTool.h new file mode 100644 index 0000000000000000000000000000000000000000..154d4c84e0c5d22d21d59260cce01f6807ed872e --- /dev/null +++ b/ForwardDetectors/AFP/AFP_DBTools/AFP_DBTools/SiLocAlignDBTool.h @@ -0,0 +1,102 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/// @file SiLocAlignDBTool.h +/// @author Grzegorz Gach <gach@agh.edu.pl> +/// @date 2017-12-03 +/// +/// @brief Header file for SiLocAlignDBTool used to read local alignment for database +#ifndef AFP_DBTOOLS_SILOCALIGNDBTOOL_H +#define AFP_DBTOOLS_SILOCALIGNDBTOOL_H + +// Local includes +#include "AFP_DBTools/ISiLocAlignDBTool.h" +#include "AFP_DBTools/SiLocAlignData.h" + +// FrameWork includes +#include "AthenaBaseComps/AthAlgTool.h" + +// database access +#include "AthenaKernel/IOVSvcDefs.h" +#include "AthenaPoolUtilities/CondAttrListCollection.h" +#include "AthenaPoolUtilities/AthenaAttributeList.h" +// general includes +#include <cassert> +#include <string> +#include <vector> +#include <memory> + +namespace AFP +{ + /// Tool providing local alignment of silicon detectors from the conditions database. + class SiLocAlignDBTool : virtual public AFP::ISiLocAlignDBTool, + public AthAlgTool + { + public: + SiLocAlignDBTool(const std::string& type, + const std::string& name, + const IInterface* parent); + + /// Does nothing + virtual ~SiLocAlignDBTool() override {} + + /// Register method SiLocAlignDBTool::update() to be called when conditions change + virtual StatusCode initialize() override; + + /// Does nothing + virtual StatusCode finalize() override {return StatusCode::SUCCESS;} + + /// Provide alignment parameters for a given plane. Returns nullptr if no data available. + const SiLocAlignData* alignment (const int stationID, const int planeID) const override; + + /// Returns reference to a vector of alignments for a given station. + /// + /// It is enough to get this reference only once, because the + /// vector is a member of the class. Whenever new conditions are + /// loaded the values in the vector will be updated. + /// + /// @warning if in database there was no data about the given + /// layer a nullptr will be stored in the vector. + const std::vector<std::unique_ptr<const SiLocAlignData> >& alignment (const int stationID) const override + {assert (stationID < s_numberOfStations); return m_alignments.at(stationID);} + + + private: + /// @brief Method called when new conditions are loaded + /// + /// The method copies information from #m_conditionsData to + StatusCode update (IOVSVC_CALLBACK_ARGS) override; + + /// @brief Resizes #m_alignments to size of maxLayers and sets size of layers for each station + /// + /// @warning The method first deletes existing alignments by + /// calling SiLocAlignDBTool::clearAlignments(). This is done in + /// order to prevent memory leaks originating from shrinking + /// #m_alignments + /// + /// @param maxLayers vector with numbers of layers in each station + void resizeAlignments (const std::vector<int>& maxLayers); + + /// Attributes list storing bare information from the database + const DataHandle<AthenaAttributeList> m_conditionsData; + + /// @brief Information about alignments represented with SiLocAlignData objects + /// + /// Main variable storing information about alignment. The index + /// of the first vector represents stationID number. The index of + /// the second vector represents plane number in the station. If + /// there is no information about plane a nullptr is stored. + std::vector<std::vector<std::unique_ptr<const SiLocAlignData> > > m_alignments; + + /// Name of the database folder with alignment information + std::string m_folderName; + + /// Number of AFP stations for which the tool should work + static const int s_numberOfStations; + }; + + +} // namespace AFP + +#endif // > ! AFP_DBTOOLS_SILOCALIGNDBTOOL_H diff --git a/ForwardDetectors/AFP/AFP_DBTools/AFP_DBTools/SiLocAlignData.h b/ForwardDetectors/AFP/AFP_DBTools/AFP_DBTools/SiLocAlignData.h new file mode 100644 index 0000000000000000000000000000000000000000..4a73647986c5ec8ae796d435c752fd4afea8acbe --- /dev/null +++ b/ForwardDetectors/AFP/AFP_DBTools/AFP_DBTools/SiLocAlignData.h @@ -0,0 +1,65 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** + * @file SiLocAlignData.h + * @author Grzegorz Gach <grzegorz.gach@cern.ch> + * @date 2018-01-17 + * + * @brief Header file for class SiLocAlignData. + * + */ + + +#ifndef AFP_DBTOOLS_SILOCALIGNDATA_H +#define AFP_DBTOOLS_SILOCALIGNDATA_H + + +namespace AFP +{ + + /// Class storing information about alignment. + class SiLocAlignData + { + /// allow only builder to change object values + friend class SiLocAlignDataBuilder; + public: + /// ID of the station to which aligment applies (see xAOD::AFPStationID) + int stationID () const {return m_stationID;} + + /// ID of the layer in station to which aligment applies (see xAOD::AFPPixelLayerID) + int layerID () const {return m_layerID;} + + /// Shift of the plane in X direction with respect to the nominal position + double xShift () const {return m_xShift;} + + /// Shift of the plane in Y direction with respect to the nominal position + double yShift () const {return m_yShift;} + + /// Shift of the plane in Z direction with respect to the nominal position + double zShift () const {return m_zShift;} + + /// Rotation angle + double alpha () const {return m_alpha;} + + /// Rotation angle + double beta () const {return m_beta;} + + /// Rotation angle + double gamma () const {return m_gamma;} + + private: + int m_stationID; + int m_layerID; + double m_xShift; + double m_yShift; + double m_zShift; + double m_alpha; + double m_beta; + double m_gamma; + }; + +} // namespace AFP + +#endif // AFP_DBTOOLS_SILOCALIGNDATA_H diff --git a/ForwardDetectors/AFP/AFP_DBTools/AFP_DBTools/SiLocAlignDataBuilder.h b/ForwardDetectors/AFP/AFP_DBTools/AFP_DBTools/SiLocAlignDataBuilder.h new file mode 100644 index 0000000000000000000000000000000000000000..6655ec59da4ca0148b6e1dc92fcad7ce32ff6ec4 --- /dev/null +++ b/ForwardDetectors/AFP/AFP_DBTools/AFP_DBTools/SiLocAlignDataBuilder.h @@ -0,0 +1,35 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** + * @file SiLocAlignDataBuilder.h + * @author Grzegorz Gach <grzegorz.gach@cern.ch> + * @date 2018-01-17 + * + * @brief Header file for class SiLocAlignDataBuilder. + * + */ + +#ifndef AFP_DBTOOLS_SILOCALIGNDATABUILDER_H +#define AFP_DBTOOLS_SILOCALIGNDATABUILDER_H + +#include"DBObjectBuilder.h" +#include"SiLocAlignData.h" + +#include<string> + +namespace AFP +{ + /// Class for building tracking detectors local alignment info from conditions database + class SiLocAlignDataBuilder : public DBObjectBuilder<SiLocAlignData> + { + public: + + /// @copydoc DBObjectBuilder::addBuilderCommand + virtual bool addBuilderCommand (const std::string& name) override; + }; + +} // namespace AFP + +#endif // AFP_DBTOOLS_SILOCALIGNDATABUILDER_H diff --git a/ForwardDetectors/AFP/AFP_DBTools/CMakeLists.txt b/ForwardDetectors/AFP/AFP_DBTools/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..11c39fe296fbfe1cc1927f863a6589b7627db549 --- /dev/null +++ b/ForwardDetectors/AFP/AFP_DBTools/CMakeLists.txt @@ -0,0 +1,27 @@ +################################################################################ +# Package: AFP_DBTools +################################################################################ + +# Declare the package name: +atlas_subdir( AFP_DBTools ) + +# Declare the package's dependencies: +atlas_depends_on_subdirs( PUBLIC + Control/AthenaBaseComps + Control/AthenaKernel + Control/StoreGate + Database/AthenaPOOL/AthenaPoolUtilities + GaudiKernel) + +# External dependencies: +find_package( Boost ) + +# Component(s) in the package: +atlas_add_component( AFP_DBTools + src/*.cxx + src/components/*.cxx + LINK_LIBRARIES AthenaBaseComps AthenaKernel StoreGateLib SGtests AthenaPoolUtilities GaudiKernel ${Boost_LIBRARIES}) + +# Install files from the package: +atlas_install_headers( AFP_DBTools ) +atlas_install_python_modules( python/*.py ) \ No newline at end of file diff --git a/ForwardDetectors/AFP/AFP_DBTools/python/AFPDBBase.py b/ForwardDetectors/AFP/AFP_DBTools/python/AFPDBBase.py new file mode 100644 index 0000000000000000000000000000000000000000..bb48e8bd6f1d8c9e619f5627b15b747b2fd80af3 --- /dev/null +++ b/ForwardDetectors/AFP/AFP_DBTools/python/AFPDBBase.py @@ -0,0 +1,109 @@ +#!/bin/env python + +from PyCool import cool + +class AFPDBRecordBase(object): + def serialiseValues (self): + output = "[" + for quantity in dir(self): # loop over all elements in class + if not callable(getattr(self, quantity)) and not quantity.startswith("__"): # select only user variables + # print "Moj " + quantity + " wynosi: " + str(getattr(self, quantity)) + output += str(getattr(self, quantity)) + ", " + + output = output[:-2] # remove the last comma and space ", " + output += "]" # close bracket + + return output + + def serialiseTypes (self): + output = '"folder_payloadspec": "' + for quantity in dir(self): # loop over all elements in class + if not callable(getattr(self, quantity)) and not quantity.startswith('__'): # select only user variables + output += quantity + ': ' + self.translateType(type(getattr(self, quantity))) + ', ' # append variable name and type + + output = output[:-2] # remove the last comma and space ", " + output += '"' # close parenthisis + + return output + + def translateType (self, typeName): + if (typeName == int): + return "Int32" + elif (typeName == float): + return "Float" + else: + raise ValueError ("Unknown type of field. Need to update method translateType") + + +class AFPDBTableBase (object): + def __init__ (self): + self.records = [] + self.iovStartRun = 0 + self.iovStartLumiBlock = 0 + self.iovEndRun = 0 + self.iovEndLumiBlock = 0 + + self.tag = "AFPTest-00-00-00" + self.folderName = "/FWD/AFP/TEST" + self.spec = cool.RecordSpecification() +# self.spec.extend("data", cool.StorageType.Blob64k) + self.spec.extend("data", cool.StorageType.String16M) +# self.desc = '<timeStamp>run-lumi</timeStamp><addrHeader><address_header service_type="71" clid="1238547719" /></addrHeader><typeName>CondAttrListCollection</typeName>' + self.desc = '<timeStamp>run-lumi</timeStamp><addrHeader><address_header service_type="71" clid="40774348" /></addrHeader><typeName>AthenaAttributeList</typeName>' + self.data = cool.Record(self.spec) + self.folderSpec = cool.FolderSpecification(cool.FolderVersioning.MULTI_VERSION, self.spec) + + + + def serialiseHeader (self): + output = '"node_description": ' +# output += '"<timeStamp>run-lumi</timeStamp><addrHeader><address_header service_type="71" clid="1238547719" /></addrHeader<typeName>CondAttrListCollection</typeName>"' + output += '"<timeStamp>run-lumi</timeStamp><addrHeader><address_header service_type=\\"71\\" clid=\\"40774348\\" /></addrHeader><typeName>AthenaAttributeList</typeName> "' + + return output + + def serialiseRecords (self): + output = '"data_array": [' + if (len(self.records) > 0): + channelID = 1 + + for entry in self.records: + output += '{' + output += '"' + str(channelID) + '" : ' + output += entry.serialiseValues() + output += '}, ' + channelID += 1 + + # remove the last comma and space ", " + output = output[:-2] + # close bracket + output += ']' + + return output + + def serialiseTable (self): + if (len(self.records) < 1): + raise ValueError ("Empty records list. Please, fill records before serialising table.") + + output = '{' + output += self.serialiseHeader() + ', ' + output += self.records[0].serialiseTypes() + ', ' + output += self.serialiseRecords() + output += '}' + + return output + + def saveToDB (self): + self.data['data'] = self.serialiseTable() + iovStart=(self.iovStartRun<<32) + self.iovStartLumiBlock; + print "before self.iovEndRun=" + str(self.iovEndRun) + iovEnd=(self.iovEndRun<<32) + self.iovEndLumiBlock; + print "after self.iovEndRun=" + str(self.iovEndRun) + + self.folder.storeObject(iovStart, iovEnd, self.data, 0, self.tag) + + def createFolder (self, db): + print self.folderSpec + self.folder = db.createFolder(self.folderName, self.folderSpec, self.desc, True) + + diff --git a/ForwardDetectors/AFP/AFP_DBTools/scripts/AFPLocalAlignDBCreate.py b/ForwardDetectors/AFP/AFP_DBTools/scripts/AFPLocalAlignDBCreate.py new file mode 100644 index 0000000000000000000000000000000000000000..8a966985b02b25ed56101c664d772b25e25b9392 --- /dev/null +++ b/ForwardDetectors/AFP/AFP_DBTools/scripts/AFPLocalAlignDBCreate.py @@ -0,0 +1,108 @@ +#!/bin/env python + +# Taken from InnerDetector/InDetRecTools/TRT_ElectronPidTools/DatabaseTools/WritePyCoolAll.py + +import json +import sys + +from AFP_DBTools.AFPDBBase import AFPDBRecordBase, AFPDBTableBase + +from PyCool import cool + +class AFPLocalAlignRecord(AFPDBRecordBase): + def __init__ (self): + self.reset() + + def reset (self): + self.stationID=-1 + self.layerID=-1 + + self.shiftX=0.1 + self.shiftY=0.4 + self.shiftZ=0.6 + + self.alpha=0. + self.beta=0. + self.gamma=0. + +class AFPLocalAlignRecordHandler: + def __init__ (self): + self.reset() + + def reset (self): + self.iovSet=False + self.anglesSet=False + self.shiftSet=False + self.idSet=False # true if stationID and laeryID were set + + self.record = AFPLocalAlignRecord() + + + +class AFPLocalAlignmentFiller (AFPDBTableBase): + """A class that creates a conditions database with AFP internal alignment.""" + + def __init__ (self): + super(AFPLocalAlignmentFiller, self).__init__() + + self.folderName="/FWD/AFP/LocalAlignment/SiliconPlanes" + self.tag="TestTag-00" + +def main(): + dbFile = "Example.db" + dbName = "CONDBR2" + + # remove the old db file so that we can write the new one + try: + import os + os.remove(dbFile) + except: + pass + + # get database service and open database + dbSvc = cool.DatabaseSvcFactory.databaseService() + + # database accessed via physical name + dbString = "sqlite://;schema=%s;dbname=%s" % (dbFile, dbName) + try: + db = dbSvc.createDatabase(dbString) + except Exception, e: + print 'Problem creating database', e + sys.exit(-1) + print "Created database", dbString + + filler = AFPLocalAlignmentFiller() + for statID in range (0, 4): + for layID in range (0, 4): + rec = AFPLocalAlignRecord() + rec.stationID = statID + rec.layerID = layID + fstatID = float(statID) + flayID = float(layID) + rec.shiftX = fstatID + (flayID/10) + rec.shiftY = -fstatID - (flayID/10) + rec.shiftZ = +fstatID - (flayID/10) + rec.alpha = -fstatID + (flayID/10) + + filler.records.append(rec); + + print filler.serialiseTable() + + filler.iovStartRun = 305359 + filler.iovStartLumiBlock = 0 + + filler.iovEndRun = 305360 + filler.iovEndLumiBlock = 0 + + filler.folderName = "/FWD/AFP/LocalAlignment/SiliconPlanes" + filler.createFolder(db) + + filler.saveToDB() + + + print "\nClose database" + db.closeDatabase() + + +if __name__=="__main__": + main() diff --git a/ForwardDetectors/AFP/AFP_DBTools/src/DBObjectBuilderBase.cxx b/ForwardDetectors/AFP/AFP_DBTools/src/DBObjectBuilderBase.cxx new file mode 100644 index 0000000000000000000000000000000000000000..4b54a3e5284f1670d48ec28d6bc7738ae0670eab --- /dev/null +++ b/ForwardDetectors/AFP/AFP_DBTools/src/DBObjectBuilderBase.cxx @@ -0,0 +1,80 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** + * @file DBObjectBuilderBase.cxx + * @author Grzegorz Gach <grzegorz.gach@cern.ch> + * @date 2018-01-19 + * + * @brief Implementation file for DBObjectBuilderBase + * + */ + +#include "../AFP_DBTools/DBObjectBuilderBase.h" +#include <sstream> +#include <list> + +namespace AFP +{ + + std::string DBObjectBuilderBase::setSpecification (const std::string specification) + { + parsePayloadSpec(specification, m_specification); + return generateBuilderCommands(); + } + + void DBObjectBuilderBase::trimSpaces (std::vector<std::string>& toTrim) const + { + for (std::string& element : toTrim) + trimSpaces (element); + } + + void DBObjectBuilderBase::trimSpaces (std::string& toTrim) const + { + const size_t first = toTrim.find_first_not_of(' '); + if (std::string::npos == first) { + toTrim = ""; + } + else { + const size_t last = toTrim.find_last_not_of(' '); + toTrim = toTrim.substr(first, (last - first + 1)); + } + } + + void DBObjectBuilderBase::parsePayloadSpec (const std::string& input, std::vector< std::vector<std::string> >& output) const + { + using namespace std; + + // split string into element strings (i.e. text with pairs name:type) + stringstream inputStream (input); + + const char elementsSeparator = ','; + std::list<string> inputElements; + + string token; + while ( getline(inputStream, token, elementsSeparator) ) + inputElements.push_back(token); + + // save final output as a vector and parse element strings + const char typeSeparator = ':'; + output.resize(inputElements.size()); + unsigned int index = 0; + for (const string& element : inputElements) { + stringstream inputElementStream (element); + // element strings should be pairs of strings separated with a colon + output[index].resize(2); + // read name of the variable + getline(inputElementStream, token, typeSeparator); + output[index][0] = token; + // read type of the variable + getline(inputElementStream, token, typeSeparator); + output[index][1] = token; // trim spaces and assign + // trim spaces and assign + trimSpaces(output[index]); + + ++index; + } + } + +} // AFP namespace diff --git a/ForwardDetectors/AFP/AFP_DBTools/src/SiLocAlignDBTool.cxx b/ForwardDetectors/AFP/AFP_DBTools/src/SiLocAlignDBTool.cxx new file mode 100644 index 0000000000000000000000000000000000000000..740e9af7258e9a17a93fd3b37b8b8391a5ec9fae --- /dev/null +++ b/ForwardDetectors/AFP/AFP_DBTools/src/SiLocAlignDBTool.cxx @@ -0,0 +1,121 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** + * @file SiLocAlignDBTool.cxx + * @author Grzegorz Gach <grzegorz.gach@cern.ch> + * @date 2017-12-03 + * + * @brief File with implementation of SiLocAlignDBTool + */ + +#include "../AFP_DBTools/SiLocAlignDBTool.h" +#include "../AFP_DBTools/SiLocAlignDataBuilder.h" +#include "../AFP_DBTools/SiLocAlignData.h" + +#include <boost/property_tree/ptree.hpp> +#include <boost/property_tree/json_parser.hpp> + +#include <sstream> +#include <string> +#include <list> +#include <map> + +namespace AFP +{ + const int SiLocAlignDBTool::s_numberOfStations = 4; + + SiLocAlignDBTool::SiLocAlignDBTool(const std::string& type, + const std::string& name, + const IInterface* parent) : + AthAlgTool (type, name, parent), + m_alignments (s_numberOfStations) + { + declareInterface<AFP::ISiLocAlignDBTool>(this); + declareProperty( "folderName", m_folderName = "/FWD/AFP/LocalAlignment/SiliconPlanes", "Name of the folder in database"); + } + + StatusCode SiLocAlignDBTool::initialize() + { + StatusCode regSC = detStore()->regFcn(&SiLocAlignDBTool::update, this, m_conditionsData , m_folderName.data(), true); + if (regSC.isFailure()) + ATH_MSG_WARNING ("Failed to register SiLocAlignDBTool::update in detStore()."); + + return StatusCode::SUCCESS; + } + + const SiLocAlignData* SiLocAlignDBTool::alignment (const int stationID, const int planeID) const + { + assert (stationID < s_numberOfStations); + + try { + return m_alignments[stationID].at(planeID).get(); + } + catch (const std::out_of_range& excpetion) { + ATH_MSG_WARNING ("Access to SiLocAlignDBTool::m_alignments["<<stationID<<"].at("<<planeID<<") is out of range."); + return nullptr; + } + + return nullptr; + } + + void SiLocAlignDBTool::resizeAlignments (const std::vector<int>& maxLayers) + { + m_alignments.resize (maxLayers.size()); + + int stationID = 0; + for (int layersN : maxLayers) + m_alignments[stationID++].resize(layersN); + } + + + StatusCode SiLocAlignDBTool::update (IOVSVC_CALLBACK_ARGS) + { + // read database content + boost::property_tree::ptree inputData; + const coral::AttributeList attrList = m_conditionsData->coralList(); + std::stringstream inputJSON (attrList["data"].data<std::string>()); + boost::property_tree::read_json(inputJSON, inputData); + boost::property_tree::ptree& payload = inputData.get_child("data_array"); + + SiLocAlignDataBuilder builder; + // configure builder and check for warning messages + std::string builderWarning = builder.setSpecification(inputData.get<std::string>("folder_payloadspec")); + if (!builderWarning.empty()) + ATH_MSG_WARNING(builderWarning); + + // Create alignment objects based on parsed information from database. Also find number of stations and layers + std::list<std::unique_ptr<const SiLocAlignData> > alignmentsList; + int maxStationID = 0; + std::vector<int> maxLayers (maxStationID+1, 0); + for (boost::property_tree::ptree::value_type node : payload) + for (boost::property_tree::ptree::value_type nodeData : node.second) { + + // create new alignment object and read station and layer ID + std::unique_ptr<const SiLocAlignData> newAlignment = std::make_unique<const SiLocAlignData> (builder.build(nodeData)); + const int stationID = newAlignment->stationID(); + const int layerID = newAlignment->layerID(); + + // find highest stationID and highest layerID for a given station + if (maxStationID < stationID) { + maxStationID = stationID; + maxLayers.resize(maxStationID + 1, 0); + } + + if (layerID >= maxLayers[stationID]) + maxLayers[stationID] = layerID+1; + + // add alignment object to output list + alignmentsList.push_back(std::move(newAlignment)); + } + + resizeAlignments (maxLayers); + + // rewrite new alignments to the output vector + for (std::unique_ptr<const SiLocAlignData>& locAlign : alignmentsList) + m_alignments[locAlign->stationID()][locAlign->layerID()] = std::move(locAlign); + + return StatusCode::SUCCESS; + } +} diff --git a/ForwardDetectors/AFP/AFP_DBTools/src/SiLocAlignDataBuilder.cxx b/ForwardDetectors/AFP/AFP_DBTools/src/SiLocAlignDataBuilder.cxx new file mode 100644 index 0000000000000000000000000000000000000000..f05684014a6adb80c460f806d1820186e6d86b82 --- /dev/null +++ b/ForwardDetectors/AFP/AFP_DBTools/src/SiLocAlignDataBuilder.cxx @@ -0,0 +1,55 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +/** + * @file SiLocAlignDataBuilder.cxx + * @author Grzegorz Gach <grzegorz.gach@cern.ch> + * @date 2018-01-17 + * + * @brief Source file for class SiLocAlignDataBuilder. + * + */ + + +#include "../AFP_DBTools/SiLocAlignDataBuilder.h" + +#include <sstream> + +namespace AFP +{ + bool SiLocAlignDataBuilder::addBuilderCommand (const std::string& name) + { + if (name == "stationID") + this->m_commands.push_back(new Command<int> (&SiLocAlignData::m_stationID)); + + else if (name == "layerID") + this->m_commands.push_back(new Command<int> (&SiLocAlignData::m_layerID)); + + else if (name == "shiftX") + this->m_commands.push_back(new Command<double> (&SiLocAlignData::m_xShift)); + + else if (name == "shiftY") + this->m_commands.push_back(new Command<double> (&SiLocAlignData::m_yShift)); + + else if (name == "shiftZ") + this->m_commands.push_back(new Command<double> (&SiLocAlignData::m_zShift)); + + else if (name == "alpha") + this->m_commands.push_back(new Command<double> (&SiLocAlignData::m_alpha)); + + else if (name == "beta") + this->m_commands.push_back(new Command<double> (&SiLocAlignData::m_beta)); + + else if (name == "gamma") + this->m_commands.push_back(new Command<double> (&SiLocAlignData::m_gamma)); + + else { + this->m_commands.push_back(new Command<double> (nullptr)); + return false; + } + + return true; + } + +} // AFP namespace diff --git a/ForwardDetectors/AFP/AFP_DBTools/src/components/AFP_DBTools_entries.cxx b/ForwardDetectors/AFP/AFP_DBTools/src/components/AFP_DBTools_entries.cxx new file mode 100644 index 0000000000000000000000000000000000000000..c34c4e0a48e6d3605a22f6d52f7dbe9b472ffa0d --- /dev/null +++ b/ForwardDetectors/AFP/AFP_DBTools/src/components/AFP_DBTools_entries.cxx @@ -0,0 +1,12 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "AFP_DBTools/SiLocAlignDBTool.h" +#include "GaudiKernel/DeclareFactoryEntries.h" + +DECLARE_NAMESPACE_TOOL_FACTORY(AFP, SiLocAlignDBTool) + +DECLARE_FACTORY_ENTRIES(AFP_DBTools) { + DECLARE_NAMESPACE_TOOL(AFP, SiLocAlignDBTool) +} diff --git a/ForwardDetectors/AFP/AFP_DBTools/src/components/AFP_DBTools_load.cxx b/ForwardDetectors/AFP/AFP_DBTools/src/components/AFP_DBTools_load.cxx new file mode 100644 index 0000000000000000000000000000000000000000..e5ca5ca2598cc1d24c9e07a4af015f090f24e877 --- /dev/null +++ b/ForwardDetectors/AFP/AFP_DBTools/src/components/AFP_DBTools_load.cxx @@ -0,0 +1,8 @@ +/* + Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration +*/ + +#include "GaudiKernel/LoadFactoryEntries.h" + +LOAD_FACTORY_ENTRIES(AFP_DBTools) +