From 84ebe0ed7aba3144778eabc377db6b1055b07f7d Mon Sep 17 00:00:00 2001 From: Pavol Strizenec <Pavol.Strizenec@cern.ch> Date: Wed, 14 Dec 2016 11:10:51 +0100 Subject: [PATCH] fix for HVPathologies (case of more HVlines per channel was not covered) (LArCondUtils-00-03-41) * fix for HVPathologies (case of more HVlines per channel was not covered) * tag LArCondUtils-00-03-41 2016-11-16 scott snyder <snyder@bnl.gov> * Tagging LArCondUtils-00-03-40. * Add missing virtual/override keywords. Remove unused member. * Tagging LArCondUtils-00-03-39. * Making methods of LArHVToolMC and LArHVToolDB const. LArHVToolDB still has some mutable members that need to be fixed (memoization). 2016-09-19 scott snyder <snyder@bnl.gov> * Tagging LArCondUtils-00-03-38. * src/LArHV2Ntuple.cxx: Fix use of CaloPhiRange. 8-9-2016 Pavol Strizenec <pavol @ mail.cern.ch> * fixing fillPileUpNoiseLumi.py, LArHVPathologyDbWrite.py and LArHVPathologyDbRead.py ... (Long ChangeLog diff - truncated) Former-commit-id: ddc8e9d25d70ae3231a07ef6b32ce81816c3ef52 --- .../LArCondUtils/LArCondUtils/LArHVToolDB.h | 34 +++++++++-------- .../LArCondUtils/LArCondUtils/LArHVToolMC.h | 14 +++---- .../share/LArHVPathologyDbRead.py | 13 +++++-- .../share/LArHVPathologyDbWrite.py | 6 +-- .../LArCondUtils/share/fillPileUpNoiseLumi.py | 4 +- .../LArCondUtils/src/LArHV2Ntuple.cxx | 11 +++--- .../LArCondUtils/src/LArHVToolDB.cxx | 37 +++++++++---------- .../LArCondUtils/src/LArHVToolMC.cxx | 14 ++----- 8 files changed, 66 insertions(+), 67 deletions(-) diff --git a/LArCalorimeter/LArCondUtils/LArCondUtils/LArHVToolDB.h b/LArCalorimeter/LArCondUtils/LArCondUtils/LArHVToolDB.h index 4fbaaad9b4d..ae3655b10fe 100755 --- a/LArCalorimeter/LArCondUtils/LArCondUtils/LArHVToolDB.h +++ b/LArCalorimeter/LArCondUtils/LArCondUtils/LArHVToolDB.h @@ -50,32 +50,32 @@ class LArHVToolDB: public AthAlgTool, virtual public ILArHVTool LArHVToolDB(const std::string& type, const std::string& name, const IInterface* parent); - virtual ~LArHVToolDB(); + virtual ~LArHVToolDB() override; - virtual StatusCode initialize(); - virtual StatusCode finalize(); + virtual StatusCode initialize() override; + virtual StatusCode finalize() override; // Given a Offline Readout ID, return values of HV and Weight virtual StatusCode getHV(const Identifier& id, - std::vector< HV_t > & v ) ; + std::vector< HV_t > & v ) const override ; // Given a Offline Readout ID, return values of Current and Weight virtual StatusCode getCurrent(const Identifier& id, - std::vector< CURRENT_t > & ihv ) ; + std::vector< CURRENT_t > & ihv ) const override ; - virtual StatusCode LoadCalibration(IOVSVC_CALLBACK_ARGS); + virtual StatusCode LoadCalibration(IOVSVC_CALLBACK_ARGS) override; - const std::vector<HWIdentifier>& getUpdatedElectrodes(); + virtual const std::vector<HWIdentifier>& getUpdatedElectrodes() override; private: static const unsigned m_nHVCoolChannels; - StatusCode getPayload(const Identifier& id,std::vector< HV_t > & v,std::vector< CURRENT_t > & ihv); - void addHV(std::vector< HV_t > & v, double hv, double wt); - void addCurr(std::vector< CURRENT_t > & ihv, double curr, double wt); - std::vector<unsigned int> getElecList(const Identifier& id); + StatusCode getPayload(const Identifier& id,std::vector< HV_t > & v,std::vector< CURRENT_t > & ihv) const; + void addHV(std::vector< HV_t > & v, double hv, double wt) const; + void addCurr(std::vector< CURRENT_t > & ihv, double curr, double wt) const; + std::vector<unsigned int> getElecList(const Identifier& id) const; StatusCode fillUpdatedHVChannelsVec(const std::set<size_t>& folderIndices); @@ -87,9 +87,11 @@ class LArHVToolDB: public AthAlgTool, virtual public ILArHVTool const LArElectrodeID* m_electrodeID; const LArHVLineID* m_hvLineID; - Identifier m_id; - std::vector<HV_t> m_v; - std::vector<CURRENT_t> m_i; + // FIXME: mutable + // These are used for memoization. + mutable Identifier m_id; + mutable std::vector<HV_t> m_v; + mutable std::vector<CURRENT_t> m_i; const DataHandle<AthenaAttributeList> m_pathologiesHandle; @@ -100,8 +102,8 @@ class LArHVToolDB: public AthAlgTool, virtual public ILArHVTool LArHVPathologiesDb* m_pathologyContainer; std::vector<std::vector<unsigned short> > m_hasPathologyEM; - std::vector<std::vector<unsigned short> > m_hasPathologyHEC; - std::vector<std::vector<unsigned short> > m_hasPathologyFCAL; + std::vector<std::vector<unsigned short> > m_hasPathologyHEC; + std::vector<std::vector<unsigned short> > m_hasPathologyFCAL; std::string m_HVPathologiesFolderName; std::vector<HWIdentifier> m_updatedElectrodes; diff --git a/LArCalorimeter/LArCondUtils/LArCondUtils/LArHVToolMC.h b/LArCalorimeter/LArCondUtils/LArCondUtils/LArHVToolMC.h index 60d36416ea2..baa8da93e5b 100755 --- a/LArCalorimeter/LArCondUtils/LArCondUtils/LArHVToolMC.h +++ b/LArCalorimeter/LArCondUtils/LArCondUtils/LArHVToolMC.h @@ -39,21 +39,21 @@ class LArHVToolMC: public AthAlgTool, virtual public ILArHVTool virtual ~LArHVToolMC(); - virtual StatusCode initialize(); - virtual StatusCode finalize(){return StatusCode::SUCCESS;} + virtual StatusCode initialize() override; + virtual StatusCode finalize() override {return StatusCode::SUCCESS;} // Given a Offline Readout ID, return values of HV and Weight virtual StatusCode getHV(const Identifier& id, - std::vector< HV_t > & v ) ; + std::vector< HV_t > & v ) const override ; // Given a Offline Readout ID, return values of Current and Weight virtual StatusCode getCurrent(const Identifier& id, - std::vector< CURRENT_t > & v ) ; + std::vector< CURRENT_t > & v ) const override ; - virtual StatusCode LoadCalibration(IOVSVC_CALLBACK_ARGS); + virtual StatusCode LoadCalibration(IOVSVC_CALLBACK_ARGS) override; - const std::vector<HWIdentifier>& getUpdatedElectrodes(); + virtual const std::vector<HWIdentifier>& getUpdatedElectrodes() override; private: @@ -61,8 +61,6 @@ class LArHVToolMC: public AthAlgTool, virtual public ILArHVTool double m_hv[2][1024][7][2]; - bool m_first; - const LArEM_ID* m_larem_id; const DataHandle<CaloIdManager> m_caloIdMgr; diff --git a/LArCalorimeter/LArCondUtils/share/LArHVPathologyDbRead.py b/LArCalorimeter/LArCondUtils/share/LArHVPathologyDbRead.py index 09597dd2113..56836d7e252 100755 --- a/LArCalorimeter/LArCondUtils/share/LArHVPathologyDbRead.py +++ b/LArCalorimeter/LArCondUtils/share/LArHVPathologyDbRead.py @@ -5,7 +5,12 @@ from time import strptime,time from calendar import timegm if "GloablTag" not in dir(): - GlobalTag = 'CONDBR2-BLKPA-2015-05' + GlobalTag = 'CONDBR2-BLKPA-2016-14' + +if "inputsqlite" not in dir(): + dbConn="COOLOFL_LAR/CONDBR2" +else: + dbConn="sqlite://;schema="+inputsqlite+";dbname=CONDBR2" if "foldertag" not in dir(): foldertag="LARHVPathologiesOflPathologies-RUN2-UPD1-00" @@ -50,7 +55,7 @@ globalflags.InputFormat = 'bytestream' globalflags.DatabaseInstance="CONDBR2" from AthenaCommon.GlobalFlags import jobproperties -jobproperties.Global.DetDescrVersion='ATLAS-GEO-20-00-00' +jobproperties.Global.DetDescrVersion='ATLAS-R2-2015-03-01-00' from AtlasGeoModel import SetGeometryVersion from AtlasGeoModel import GeoModelInit @@ -90,8 +95,8 @@ else: conddb.addFolder("LAR_OFL","/LAR/HVPathologiesOfl/Pathologies<tag>"+foldertag+"</tag>") svcMgr.MessageSvc.OutputLevel = 4 -svcMgr.MessageSvc.debugLimit = 100000 -svcMgr.MessageSvc.infoLimit = 100000 +svcMgr.MessageSvc.debugLimit = 99999999 +svcMgr.MessageSvc.infoLimit = 99999999 LArHVPathologyDbAlg.OutputLevel = 3 svcMgr.IOVDbSvc.OutputLevel = 3 diff --git a/LArCalorimeter/LArCondUtils/share/LArHVPathologyDbWrite.py b/LArCalorimeter/LArCondUtils/share/LArHVPathologyDbWrite.py index 800158f701b..5a153623574 100755 --- a/LArCalorimeter/LArCondUtils/share/LArHVPathologyDbWrite.py +++ b/LArCalorimeter/LArCondUtils/share/LArHVPathologyDbWrite.py @@ -56,7 +56,7 @@ globalflags.InputFormat = 'bytestream' from AthenaCommon.GlobalFlags import jobproperties -jobproperties.Global.DetDescrVersion='ATLAS-GEO-20-00-00' +jobproperties.Global.DetDescrVersion='ATLAS-R2-2015-03-01-00' from AtlasGeoModel import SetGeometryVersion from AtlasGeoModel import GeoModelInit @@ -100,8 +100,8 @@ topSequence += LArHVPathologyDbAlg svcMgr.IOVDbSvc.dbConnection = "sqlite://;schema="+OutputFile+";dbname=CONDBR2" svcMgr.MessageSvc.OutputLevel = 4 -svcMgr.MessageSvc.debugLimit = 100000 -svcMgr.MessageSvc.infoLimit = 100000 +svcMgr.MessageSvc.debugLimit = 99999999 +svcMgr.MessageSvc.infoLimit = 99999999 topSequence.LArHVPathologyDbAlg.OutputLevel = 2 svcMgr.IOVDbSvc.OutputLevel = 3 diff --git a/LArCalorimeter/LArCondUtils/share/fillPileUpNoiseLumi.py b/LArCalorimeter/LArCondUtils/share/fillPileUpNoiseLumi.py index b63fa9ccff3..e4a82bca75f 100755 --- a/LArCalorimeter/LArCondUtils/share/fillPileUpNoiseLumi.py +++ b/LArCalorimeter/LArCondUtils/share/fillPileUpNoiseLumi.py @@ -9,7 +9,9 @@ def createFolder(db,name): spec = cool.RecordSpecification() spec.extend('LBAvInstLumi',cool.StorageType.Float) spec.extend('Valid',cool.StorageType.UInt32) - return db.createFolder(name,spec,desc,cool.FolderVersioning.MULTI_VERSION, True) + folderSpec=cool.FolderSpecification(cool.FolderVersioning.MULTI_VERSION, spec) + #return db.createFolder(name,spec,desc,cool.FolderVersioning.MULTI_VERSION, True) + return db.createFolder(name,folderSpec,desc, True) diff --git a/LArCalorimeter/LArCondUtils/src/LArHV2Ntuple.cxx b/LArCalorimeter/LArCondUtils/src/LArHV2Ntuple.cxx index 230df45a21f..64d4564d7d0 100644 --- a/LArCalorimeter/LArCondUtils/src/LArHV2Ntuple.cxx +++ b/LArCalorimeter/LArCondUtils/src/LArHV2Ntuple.cxx @@ -369,7 +369,6 @@ }//HECHVManager const FCALHVManager *hvManager_FCAL=manager->getFCALHVManager(); - CaloPhiRange _range; for (unsigned int iSide=hvManager_FCAL->beginSideIndex();iSide<hvManager_FCAL->endSideIndex();iSide++) { // loop over HV modules float eta_min=3.1,eta_max=4.9; if (iSide==0) { eta_min=-4.9; eta_max=-3.1; } @@ -382,12 +381,12 @@ //std::cout << " FCAL HVModule side,sampling,sector " << iSide << " " << iSampling << " " << iSector << std::endl; //std::cout << " HV nominal " << HVnominal << std::endl; - float dphi=_range.twopi()/16; - if (iSampling==1) dphi=_range.twopi()/8.; - if (iSampling==2) dphi=_range.twopi()/4.; + float dphi=CaloPhiRange::twopi()/16; + if (iSampling==1) dphi=CaloPhiRange::twopi()/8.; + if (iSampling==2) dphi=CaloPhiRange::twopi()/4.; float phi_min = ((float)(iSector))*dphi; - phi_min = _range.fix(phi_min); - float phi_max = _range.fix(dphi+phi_min); + phi_min = CaloPhiRange::fix(phi_min); + float phi_max = CaloPhiRange::fix(dphi+phi_min); float phi = 0.5*(phi_min+phi_max); for (unsigned int iLine=0;iLine<hvMod->getNumHVLines();iLine++) { diff --git a/LArCalorimeter/LArCondUtils/src/LArHVToolDB.cxx b/LArCalorimeter/LArCondUtils/src/LArHVToolDB.cxx index bd49beeb751..ee2aaf3ba83 100755 --- a/LArCalorimeter/LArCondUtils/src/LArHVToolDB.cxx +++ b/LArCalorimeter/LArCondUtils/src/LArHVToolDB.cxx @@ -128,7 +128,7 @@ StatusCode LArHVToolDB::LoadCalibration(IOVSVC_CALLBACK_ARGS_K( keys)) { unsigned int index = (unsigned int)(idHash); if (index<m_hasPathologyEM.size()) { if(m_hasPathologyEM[index].size()) { - if(m_hasPathologyEM[index].size()<electPath.electInd+1) m_hasPathologyEM[index].resize(electPath.electInd+1); + if(m_hasPathologyEM[index].size()<abs(electPath.electInd+1)) m_hasPathologyEM[index].resize(electPath.electInd+1); m_hasPathologyEM[index][electPath.electInd]=electPath.pathologyType; } else { std::vector<unsigned short> svec; @@ -143,7 +143,7 @@ StatusCode LArHVToolDB::LoadCalibration(IOVSVC_CALLBACK_ARGS_K( keys)) { unsigned int index = (unsigned int)(idHash); if (index<m_hasPathologyHEC.size()) { if(m_hasPathologyHEC[index].size()) { - if(m_hasPathologyHEC[index].size()<electPath.electInd+1) m_hasPathologyHEC[index].resize(electPath.electInd+1); + if(m_hasPathologyHEC[index].size()<abs(electPath.electInd+1)) m_hasPathologyHEC[index].resize(electPath.electInd+1); m_hasPathologyHEC[index][electPath.electInd]=electPath.pathologyType; } else { std::vector<unsigned short> svec; @@ -158,7 +158,7 @@ StatusCode LArHVToolDB::LoadCalibration(IOVSVC_CALLBACK_ARGS_K( keys)) { unsigned int index = (unsigned int)(idHash); if (index<m_hasPathologyFCAL.size()) { if(m_hasPathologyFCAL[index].size()) { - if(m_hasPathologyFCAL[index].size()<electPath.electInd+1) m_hasPathologyFCAL[index].resize(electPath.electInd+1); + if(m_hasPathologyFCAL[index].size()<abs(electPath.electInd+1)) m_hasPathologyFCAL[index].resize(electPath.electInd+1); m_hasPathologyFCAL[index][electPath.electInd]=electPath.pathologyType; } else { std::vector<unsigned short> svec; @@ -268,21 +268,21 @@ StatusCode LArHVToolDB::initialize(){ StatusCode LArHVToolDB::getHV(const Identifier& id, - std::vector< HV_t > & v ) + std::vector< HV_t > & v ) const { std::vector< CURRENT_t> ihv; return getPayload(id,v,ihv); } StatusCode LArHVToolDB::getCurrent(const Identifier& id, - std::vector< CURRENT_t > & ihv ) + std::vector< CURRENT_t > & ihv ) const { std::vector< HV_t> v; return getPayload(id,v,ihv); } -StatusCode LArHVToolDB::getPayload(const Identifier& id, std::vector< HV_t > & v, std::vector< CURRENT_t > & ihv) +StatusCode LArHVToolDB::getPayload(const Identifier& id, std::vector< HV_t > & v, std::vector< CURRENT_t > & ihv) const { if (id==m_id) { @@ -306,10 +306,10 @@ StatusCode LArHVToolDB::getPayload(const Identifier& id, std::vector< HV_t > & v unsigned int index = (unsigned int)(m_larem_id->channel_hash(id)); bool hasPathology=false; if (index<m_hasPathologyEM.size()) { - if (m_hasPathologyEM[index].size()) { - hasPathology=true; - listElec = getElecList(id); - } + if (m_hasPathologyEM[index].size()) { + hasPathology=true; + listElec = getElecList(id); + } } const EMBDetectorElement* embElement = dynamic_cast<const EMBDetectorElement*>(m_calodetdescrmgr->get_element(id)); if (!embElement) std::abort(); @@ -328,8 +328,7 @@ StatusCode LArHVToolDB::getPayload(const Identifier& id, std::vector< HV_t > & v double curr; electrode->voltage_current(igap,hv,curr); if (hasPathology) { - //msg(MSG::DEBUG) << "Has pathology for id: "<< m_larem_id->print_to_string(id)<<" "<<m_hasPathologyEM[index]<<endmsg; - msg(MSG::DEBUG) << "Has pathology for id: "<<id.get_identifier32().get_compact()<<" "<<m_hasPathologyEM[index].size()<<endmsg; + msg(MSG::DEBUG) << "Has pathology for id: "<< m_larem_id->print_to_string(id)<<" "<<m_hasPathologyEM[index]<<endmsg; msg(MSG::DEBUG) << "Original hv: "<<hv<<" "; for (unsigned int ii=0;ii<listElec.size();ii++) { if (listElec[ii]==(2*i+igap) && listElec[ii]<m_hasPathologyEM[index].size() && m_hasPathologyEM[index][listElec[ii]]) { @@ -376,7 +375,7 @@ StatusCode LArHVToolDB::getPayload(const Identifier& id, std::vector< HV_t > & v double curr; electrode->voltage_current(igap,hv,curr); if (hasPathology) { - msg(MSG::DEBUG) << "Has pathology for id: "<< m_larem_id->print_to_string(id)<<" "<<m_hasPathologyEM[index].size()<<endmsg; + msg(MSG::DEBUG) << "Has pathology for id: "<< m_larem_id->print_to_string(id)<<" "<<m_hasPathologyEM[index]<<endmsg; for (unsigned int ii=0;ii<listElec.size();ii++) { if (listElec[ii]==(2*i+igap) && listElec[ii]<m_hasPathologyEM[index].size() && m_hasPathologyEM[index][listElec[ii]]) { if(m_hasPathologyEM[index][listElec[ii]]&0xF) hv=0.; else hv=((m_hasPathologyEM[index][listElec[ii]]&0xFFF0)>>4); @@ -417,9 +416,9 @@ StatusCode LArHVToolDB::getPayload(const Identifier& id, std::vector< HV_t > & v subgap->voltage_current(hv,curr); //std::cout << " hv value " << hv << std::endl; if (hasPathology) { - msg(MSG::DEBUG) << "Has pathology for id: "<< m_larhec_id->print_to_string(id)<<" "<<m_hasPathologyHEC[index].size()<<endmsg; + msg(MSG::DEBUG) << "Has pathology for id: "<< m_larhec_id->print_to_string(id)<<" "<<m_hasPathologyHEC[index]<<endmsg; for (unsigned int ii=0;ii<listElec.size();ii++) { - if (listElec[ii]==i && listElec[ii]<m_hasPathologyHEC[index].size() && m_hasPathologyHEC[index][listElec[ii]]) { + if (listElec[ii]==i && listElec[ii]<m_hasPathologyHEC[index].size() && m_hasPathologyHEC[index][listElec[ii]]) { if(m_hasPathologyHEC[index][listElec[ii]]&0xF) hv=0.; else hv=((m_hasPathologyHEC[index][listElec[ii]]&0xFFF0)>>4); curr=0.; } @@ -465,7 +464,7 @@ StatusCode LArHVToolDB::getPayload(const Identifier& id, std::vector< HV_t > & v double curr; line->voltage_current(hv,curr); if (hasPathology) { - msg(MSG::DEBUG) << "Has pathology for id: "<< m_larfcal_id->print_to_string(id)<<" "<<m_hasPathologyFCAL[index].size()<<endmsg; + msg(MSG::DEBUG) << "Has pathology for id: "<< m_larfcal_id->print_to_string(id)<<" "<<m_hasPathologyFCAL[index]<<endmsg; for (unsigned int ii=0;ii<listElec.size();ii++) { if (listElec[ii]==i && listElec[ii]<m_hasPathologyFCAL[index].size() && m_hasPathologyFCAL[index][listElec[ii]]) { if(m_hasPathologyFCAL[index][listElec[ii]]&0xF) hv=0.; else hv=((m_hasPathologyFCAL[index][listElec[ii]]&0xFFF0)>>4); @@ -530,7 +529,7 @@ StatusCode LArHVToolDB::getPayload(const Identifier& id, std::vector< HV_t > & v return StatusCode::SUCCESS; } -void LArHVToolDB::addHV(std::vector< HV_t > & v , double hv, double wt) +void LArHVToolDB::addHV(std::vector< HV_t > & v , double hv, double wt) const { bool found=false; for (unsigned int i=0;i<v.size();i++) { @@ -548,7 +547,7 @@ void LArHVToolDB::addHV(std::vector< HV_t > & v , double hv, double wt) } // not already in the list } -void LArHVToolDB::addCurr(std::vector< CURRENT_t > & ihv , double current, double wt) +void LArHVToolDB::addCurr(std::vector< CURRENT_t > & ihv , double current, double wt) const { bool found=false; for (unsigned int i=0;i<ihv.size();i++) { @@ -566,7 +565,7 @@ void LArHVToolDB::addCurr(std::vector< CURRENT_t > & ihv , double current, doubl } // not already in the list } -std::vector<unsigned int> LArHVToolDB::getElecList(const Identifier& id) +std::vector<unsigned int> LArHVToolDB::getElecList(const Identifier& id) const { std::vector<unsigned int> myList; myList.clear(); diff --git a/LArCalorimeter/LArCondUtils/src/LArHVToolMC.cxx b/LArCalorimeter/LArCondUtils/src/LArHVToolMC.cxx index c5ef5d0623f..654224e3a27 100755 --- a/LArCalorimeter/LArCondUtils/src/LArHVToolMC.cxx +++ b/LArCalorimeter/LArCondUtils/src/LArHVToolMC.cxx @@ -29,7 +29,6 @@ LArHVToolMC::LArHVToolMC(const std::string& type, const IInterface* parent) : AthAlgTool(type,name,parent), m_readASCII(false), - m_first(false), m_larem_id(nullptr) { declareInterface< ILArHVTool >( this ); @@ -46,7 +45,6 @@ StatusCode LArHVToolMC::initialize() ATH_CHECK( detStore()->retrieve( m_caloIdMgr ) ); m_larem_id = m_caloIdMgr->getEM_ID(); - m_first=true; const LArElectrodeID* electrodeID = nullptr; ATH_CHECK( detStore()->retrieve(electrodeID) ); @@ -57,20 +55,16 @@ StatusCode LArHVToolMC::initialize() m_updatedElectrodes.push_back(electrodeID->ElectrodeId(IdentifierHash(i))); } + InitHV(); + return StatusCode::SUCCESS; } StatusCode LArHVToolMC::getHV(const Identifier& id, - std::vector< HV_t > & v ) + std::vector< HV_t > & v ) const { - - if (m_first) { - this->InitHV(); - m_first=false; - } - v.clear(); // check identifier in LAR @@ -137,7 +131,7 @@ StatusCode LArHVToolMC::getHV(const Identifier& id, } StatusCode LArHVToolMC::getCurrent(const Identifier& /* id */, - std::vector< CURRENT_t > & v ) + std::vector< CURRENT_t > & v ) const { ATH_MSG_WARNING ( " LArHVToolMC: getCurrent not implemented " ); CURRENT_t cu; -- GitLab