19#include "TGeoManager.h"
49 fIsOld(kFALSE), fNofSensorsDefault(0), fSensorDinact(0.), fSensorPitch(0.),
50 fSensorStereoF(0.), fSensorStereoB(0.),
51 fSensors(), fModules(), fModuleVector(),
61 TGeoPhysicalNode* node) {
64 auto it = fSensors.find(address);
65 if ( it != fSensors.end() ) {
70 LOG(debug1) << GetName() <<
": Assigning " << sensor->
ToString()
71 <<
"\n\t\t to node " << node->GetName();
75 LOG(debug1) << GetName() <<
": Assigning default " << sensor->
ToString()
76 <<
"\n\t\t to node " << node->GetName();
87Int_t BmnSsdSetup::CreateStations() {
97 TString name = Form(
"SSD_S%02i", stationId+1);
98 TString title = Form(
"SSD Station %i", stationId+1);
107 assert ( fStations.find(stationId) == fStations.end() );
108 fStations[stationId] = station;
111 return fStations.size();
118 for ( Int_t iLadder = 0; iLadder < unit->
GetNofDaughters(); iLadder++) {
121 Int_t nodeNumber = ladder->
GetPnode()->GetNode()->GetNumber();
122 Int_t stationId = nodeNumber / 100 - 1;
125 if ( fStations.find(stationId) == fStations.end() ) {
126 TString
name = Form(
"SSD_S%02i", stationId+1);
127 TString title = Form(
"SSD Station %i", stationId+1);
129 fStations[stationId] = station;
131 else station = fStations[stationId];
140 auto it = fStations.begin();
141 while ( it != fStations.end() ) {
149 Double_t zPrevious = -999999;
150 for (UInt_t iStation = 0; iStation < fStations.size(); iStation++) {
151 if ( fStations.find(iStation) == fStations.end() ) {
152 LOG(error) << GetName() <<
": Number of stations is "
153 << fStations.size() <<
", but station " << iStation
154 <<
"is not present!";
157 if ( fStations[iStation]->GetZ() <= zPrevious ) {
158 LOG(error) << GetName() <<
": Disordered stations. Station "
159 << iStation <<
" is at z = " << fStations[iStation]->GetZ()
160 <<
"cm , previous is at z = " << zPrevious <<
" cm."
165 if ( ! isOk ) LOG(fatal) << GetName() <<
": Error in creation of stations."
168 return fStations.size();
176 TGeoPhysicalNode* node) {
179 assert ( fSensors.find(address) == fSensors.end() );
183 TGeoBBox* shape =
dynamic_cast<TGeoBBox*
>(node->GetShape());
185 Double_t volX = 2. * shape->GetDX();
186 Double_t volY = 2. * shape->GetDY();
189 Double_t pitch = 0.0058;
190 Double_t stereoF = 0.;
191 Double_t stereoB = 7.5;
194 Double_t dInact = 0.24;
198 Int_t nStrips = 1024;
199 if ( TMath::Abs(volX-6.2) > 0.01 )
200 nStrips = Int_t( (volX - dInact) / pitch );
203 Double_t dy = volY - dInact;
212 Bool_t status = sensor->
Init();
214 fSensors[address] = sensor;
226 if ( !
fAddress ) LOG(fatal) << fName <<
": not initialised!"
231 LOG(WARNING) << fName <<
": No SSD address " << address
238 LOG(WARNING) << fName <<
": Illegal level " << level
244 for (Int_t iLevel = 1; iLevel <= level; iLevel++) {
260 if ( fIsOld && level ==
kSsdUnit )
return "station";
264 case kSsdUnit:
return "unit";
break;
269 case kSsdSide:
return "side";
break;
270 default:
return "";
break;
287 return ladder->
GetPnode()->GetNode()->GetNumber() / 100 - 1;
298 assert( ! fIsInitialised );
301 LOG(info) <<
"=========================================================="
303 LOG(info) <<
"Initialising SSD Setup "
308 if ( parFile ) ReadSensorParameters(parFile);
314 if ( parFile ) ReadGeometry(parFile);
319 ReadGeometry(gGeoManager);
323 LOG(info) << fName <<
": Elements in setup: ";
324 for (Int_t iLevel = 1; iLevel <=
kSsdSensor; iLevel++) {
327 LOG(info) <<
" " << setw(12) << name << setw(5) << right
330 LOG(info) << GetName() <<
": " << fNofSensorsDefault
331 <<
" sensors created from default.";
343 if ( fModules.find(address) != fModules.end() ) {
344 LOG(fatal) << GetName() <<
": Duplicate module address "
345 << address <<
" for " << modu->GetName();
347 BmnSsdModule*
module = dynamic_cast<BmnSsdModule*>(modu);
348 fModules[address] =
module;
349 fModuleVector.push_back(module);
356 Int_t nStations = CreateStations();
357 LOG(info) << GetName() <<
": Setup contains " << nStations
358 <<
" stations objects.";
359 if ( FairLogger::GetLogger()->IsLogNeeded(DEBUG) ) {
360 auto it = fStations.begin();
361 while ( it != fStations.end() ) {
362 LOG(debug) <<
" " << it->second->ToString();
369 LOG(fatal) << GetName() <<
": inconsistent number of sensors! "
373 LOG(fatal) << GetName() <<
": inconsistent number of modules! "
377 LOG(info) <<
"=========================================================="
381 fIsInitialised = kTRUE;
390 if ( ! fgInstance ) fgInstance =
new BmnSsdSetup();
399 for (
auto it = fModules.begin(); it != fModules.end(); it++)
400 LOG(info) << it->second->ToString();
410 for (
auto it = fSensors.begin(); it != fSensors.end(); it++ ) {
413 if ( ! sensor )
continue;
425Bool_t BmnSsdSetup::ReadGeometry(TGeoManager* geo) {
429 LOG(info) << fName <<
": Reading geometry from TGeoManager "
434 TGeoNode* cave = geo->GetCurrentNode();
437 TGeoNode* ssd = NULL;
438 for (Int_t iNode = 0; iNode < cave->GetNdaughters(); iNode++) {
439 cout <<
"$$$$$$$ iNode = " << iNode <<
"\n";
440 TString name = cave->GetDaughter(iNode)->GetName();
441 cout <<
"$$$$$$$ name = " << name <<
"\n";
442 if ((name.Contains(
"ssd", TString::kIgnoreCase)) ||
443 (name.Contains(
"sts", TString::kIgnoreCase)) ) {
444 ssd = cave->GetDaughter(iNode);
445 LOG(info) << fName <<
": SSD top node is " << ssd->GetName()
451 LOG(error) << fName <<
": No top SSD node found in geometry!"
457 TString path = cave->GetName();
458 path = path +
"/" + ssd->GetName();
459 fNode =
new TGeoPhysicalNode(path);
462 Bool_t hasStation = kFALSE;
463 Bool_t hasUnit = kFALSE;
464 for (Int_t iDaughter = 0; iDaughter <
fNode->GetNode()->GetNdaughters();
466 TString dName =
fNode->GetNode()->GetDaughter(iDaughter)->GetName();
467 if ( dName.Contains(
"station", TString::kIgnoreCase) ) hasStation = kTRUE;
468 if ( dName.Contains(
"unit", TString::kIgnoreCase) ) hasUnit = kTRUE;
470 if ( hasUnit && (! hasStation) ) fIsOld = kFALSE;
471 else if ( (! hasUnit) && hasStation) fIsOld = kTRUE;
472 else if ( hasUnit && hasStation) LOG(fatal) << GetName()
473 <<
": geometry contains both units and stations!";
474 else LOG(fatal) << GetName() <<
": geometry contains neither units "
476 if ( fIsOld ) LOG(WARNING) << GetName() <<
": using old geometry (with stations)"
489Bool_t BmnSsdSetup::ReadGeometry(
const char* fileName) {
491 LOG(info) << fName <<
": Reading geometry from file "
495 assert ( ! gGeoManager );
498 TFile geoFile(fileName);
499 if ( ! geoFile.IsOpen() ) {
500 LOG(fatal) << GetName() <<
": Could not open geometry file "
506 TGeoManager* ssdGeometry =
new TGeoManager(
"SsdGeo",
507 "SSD stand-alone geometry");
510 TGeoVolume* topVolume = NULL;
511 TList* keyList = geoFile.GetListOfKeys();
513 TIter keyIter(keyList);
514 while ( (key = (TKey*) keyIter() ) ) {
515 if ( strcmp(
key->GetClassName(),
"TGeoVolumeAssembly" ) == 0 ) {
516 TGeoVolume* volume = (TGeoVolume*)
key->ReadObj();
517 if ( strcmp(volume->GetName(),
"TOP") == 0 ) {
524 LOG(fatal) << GetName() <<
": No TOP volume in file!";
527 ssdGeometry->SetTopVolume(topVolume);
530 ssdGeometry->CdTop();
531 TGeoNode* cave = ssdGeometry->GetCurrentNode();
534 TGeoNode* ssd = NULL;
535 for (Int_t iNode = 0; iNode < cave->GetNdaughters(); iNode++) {
536 TString
name = cave->GetDaughter(iNode)->GetName();
537 if ((
name.Contains(
"ssd", TString::kIgnoreCase)) ||
538 (
name.Contains(
"sts", TString::kIgnoreCase)) ) {
539 ssd = cave->GetDaughter(iNode);
540 ssdGeometry->CdDown(iNode);
541 LOG(info) << fName <<
": SSD top node is " << ssd->GetName()
547 LOG(error) << fName <<
": No top SSD node found in geometry!"
553 TString path = cave->GetName();
554 path = path +
"/" + ssd->GetName();
555 fNode =
new TGeoPhysicalNode(path);
558 TString dName =
fNode->GetNode()->GetDaughter(0)->GetName();
559 LOG(debug) <<
"First node is " << dName;
560 if ( dName.Contains(
"station", TString::kIgnoreCase) ) fIsOld = kTRUE;
561 else if ( dName.Contains(
"unit", TString::kIgnoreCase) ) fIsOld = kFALSE;
562 else LOG(fatal) << GetName() <<
": unknown geometry type; first level name is "
564 if ( fIsOld ) LOG(WARNING) << GetName() <<
": using old geometry (with stations)"
577Int_t BmnSsdSetup::ReadSensorParameters(
const char* fileName) {
581 TString inputFile = fileName;
584 inFile.open(inputFile.Data());
587 if ( ! inFile.is_open() ) {
588 inputFile = gSystem->Getenv(
"VMCWORKDIR");
589 inputFile +=
"/parameters/ssd/" + TString(fileName);
590 inFile.open(inputFile.Data());
594 if ( ! inFile.is_open() ) {
595 LOG(fatal) << GetName() <<
": Cannot read file " << fileName
596 <<
" nor " << inputFile;
601 TString sName, sType;
605 if ( inFile.eof() )
break;
606 getline(inFile, input);
607 if (input.empty() || input[0] ==
'#')
continue;
608 std::stringstream line(input);
609 line >> sName >> sType;
615 if ( fSensors.find(address) != fSensors.end() ) {
616 LOG(error) << GetName() <<
": sensor " << sName
617 <<
" is already in the setup!";
622 if ( sType.EqualTo(
"DssdStereo", TString::kIgnoreCase) ) {
626 Double_t stereoF = 0.;
627 Double_t stereoB = 0.;
628 line >> dy >> nStrips >> pitch >> stereoF >> stereoB;
632 LOG(debug) <<
"Created " << sensor->
ToString();
633 fSensors[address] = sensor;
638 LOG(fatal) << GetName() <<
": Unknown sensor type " << sType
639 <<
" for sensor " << sName;
645 LOG(info) << GetName() <<
": Read " << nSensors
646 << (nSensors == 1 ?
" sensor" :
" sensors") <<
" from "
648 assert( nSensors = fSensors.size() );
661 assert( ! fIsInitialised );
662 assert( dInact >= 0.);
663 assert( pitch >= 0. );
664 fSensorDinact = dInact;
665 fSensorPitch = pitch;
666 fSensorStereoF = stereoF;
667 fSensorStereoB = stereoB;
676 Int_t nAdc, Double_t tResolution,
677 Double_t tDead, Double_t noise,
678 Double_t zeroNoiseRate,
679 Double_t fracDeadChannels) {
682 for (
auto it = fModules.begin(); it != fModules.end(); it++) {
683 it->second->SetParameters(dynRange, threshold, nAdc, tResolution,
684 tDead, noise, zeroNoiseRate, fracDeadChannels);
699 TString inputFile = fileName;
702 inFile.open(inputFile.Data());
705 if ( ! inFile.is_open() ) {
706 inputFile = gSystem->Getenv(
"VMCWORKDIR");
707 inputFile +=
"/parameters/ssd/" + TString(fileName);
708 inFile.open(inputFile.Data());
712 if ( ! inFile.is_open() ) {
713 LOG(fatal) << GetName() <<
": Cannot read file " << fileName
714 <<
" nor " << inputFile;
720 Double_t dynRange = -1.e10;
721 Double_t threshold = -1.e10;
723 Double_t tResol = -1.e10;
724 Double_t tDead = -1.e10;
725 Double_t noise = -1.e10;
726 Double_t zeroNoise = -1.e10;
727 Double_t fracDead = -1.e10;
731 if ( inFile.eof() )
break;
732 getline(inFile, input);
733 if (input.empty() || input[0] ==
'#')
continue;
734 std::stringstream line(input);
735 line >> mName >> dynRange >> threshold >> nAdc >> tResol >> tDead >> noise
736 >> zeroNoise >> fracDead;
740 if ( fModules.find(address) == fModules.end() ) {
741 LOG(error) << GetName() <<
": Module " << mName
742 <<
" not found in the setup!";
749 if ( module->IsSet() ) {
750 LOG(error) << GetName() <<
": Parameters of module "
751 <<
module->GetName() << " are already set!";
756 if ( dynRange < 1.e-9 || threshold < 1.e-9 || nAdc < 0
757 || tResol < 1.e-9 || tDead < 1.e-9 || noise < 1.e-9
758 || zeroNoise < 1.e-9 || fracDead < 0. || fracDead > 1.) {
759 LOG(error) << GetName()
760 <<
": Missing or illegal parameters for module "
761 <<
module->GetName() << ";
" << dynRange << " " << threshold << " "
762 << nAdc << " " << tResol << " " << tDead << " " << noise << " "
763 << zeroNoise << " " << fracDead;
767 // --- Set parameters of module
768 module->SetParameters(dynRange, threshold, nAdc, tResol, tDead, noise,
769 zeroNoise, fracDead);
770 LOG(debug1) << GetName() << ": Set
" << module->ToString()
777 LOG(info) << GetName() << ": Read conditions of
" << nModules
778 << (nModules == 1 ? " module" : " modules") << " from "
782 if ( nModules!= fModules.size() ) {
783 LOG(fatal) << GetName() <<
": " << fModules.size()
784 <<
" modules in setup, but parameters for " << nModules
785 <<
" in parameter file!";
801 Double_t vDep = fSettings->
GetVdep();
802 Double_t vBias = fSettings->
GetVbias();
804 Double_t cCoup = fSettings->
GetCcoup();
805 Double_t cIs = fSettings->
GetCis();
815 LOG(info) << GetName() <<
": Set conditions for all sensors:"
817 LOG(info) <<
"\t Full depletion voltage " << vDep
819 LOG(info) <<
"\t Bias voltage " << vBias
821 LOG(info) <<
"\t Temperature " << temperature <<
" K"
823 LOG(info) <<
"\t Coupling capacitance " << cCoup
825 LOG(info) <<
"\t Inter-strip capacitance " << cIs
829 for (
auto it = fSensors.begin(); it != fSensors.end(); it++ ) {
832 Double_t local[3] = { 0., 0., 0.};
834 it->second->GetNode()->GetMatrix()->LocalToMaster(local, global);
838 Double_t field[3] = { 0., 0., 0.};
839 if ( FairRun::Instance()->GetField() )
840 FairRun::Instance()->GetField()->Field(global, field);
841 it->second->SetConditions(vDep, vBias, temperature, cCoup,
842 cIs, field[0]/10., field[1]/10., field[2]/10.);
855 Double_t temperature,
857 Double_t cInterstrip) {
862 for (
auto it = fSensors.begin(); it != fSensors.end(); it++ ) {
865 Double_t local[3] = { 0., 0., 0.};
867 it->second->GetNode()->GetMatrix()->LocalToMaster(local, global);
870 Double_t field[3] = { 0., 0., 0.};
871 if ( FairRun::Instance()->GetField() )
872 FairRun::Instance()->GetField()->Field(global, field);
873 it->second->SetConditions(vDep, vBias, temperature, cCoupling,
875 field[0]/10., field[1]/10., field[2]/10.);
891 TString inputFile = fileName;
894 inFile.open(inputFile.Data());
897 if ( ! inFile.is_open() ) {
898 inputFile = gSystem->Getenv(
"VMCWORKDIR");
899 inputFile +=
"/parameters/ssd/" + TString(fileName);
900 inFile.open(inputFile.Data());
904 if ( ! inFile.is_open() ) {
905 LOG(fatal) << GetName() <<
": Cannot read file " << fileName
906 <<
" nor " << inputFile;
912 Double_t vDep = -1.e10;
913 Double_t vBias = -1.e10;
914 Double_t temperature = -1.e10;
915 Double_t cCoupling = -1.e10;
916 Double_t cInterstrip = -1.e10;
920 if ( inFile.eof() )
break;
921 getline(inFile, input);
922 if (input.empty() || input[0] ==
'#')
continue;
923 std::stringstream line(input);
924 line >> sName >> vDep >> vBias >> temperature >> cCoupling >> cInterstrip;
928 if ( fSensors.find(address) == fSensors.end() ) {
929 LOG(error) << GetName() <<
": Sensor " << sName
930 <<
" not found in the setup!";
938 LOG(error) << GetName() <<
": Conditions of sensor "
939 << sensor->GetName() <<
" are already set!";
944 if ( vDep < 1.e-9 || vBias < 1.e-9 || temperature < 1.e-9
945 || cCoupling < 1.e-9 || cInterstrip < 1.e-9 ) {
946 LOG(error) << GetName()
947 <<
": Missing or illegal condition parameters for sensor "
948 << sensor->GetName() <<
"; " << vDep <<
" " << vBias <<
" "
949 << temperature <<
" " << cCoupling <<
" " << cInterstrip
955 Double_t local[3] = { 0., 0., 0.};
957 sensor->
GetNode()->GetMatrix()->LocalToMaster(local, global);
958 Double_t field[3] = { 0., 0., 0.};
959 if ( FairRun::Instance()->GetField() )
960 FairRun::Instance()->GetField()->Field(global, field);
963 sensor->
SetConditions(vDep, vBias, temperature, cCoupling, cInterstrip,
964 field[0]/10., field[1]/10., field[2]/10.);
965 LOG(debug1) << GetName() <<
": Conditions of sensor " << sensor->GetName()
972 LOG(info) << GetName() <<
": Read conditions of " << nSensors
973 << (nSensors == 1 ?
" sensor" :
" sensors") <<
" from "
977 if ( nSensors != fSensors.size() ) {
978 LOG(fatal) << GetName() <<
": " << fSensors.size()
979 <<
" sensors in setup, but conditions for " << nSensors
980 <<
" in conditions file!";
Bool_t fIsInitialised
kTRUE if Init() was called
Double_t GetTemperature() const
Double_t GetVbias() const
Double_t GetCcoup() const
Class representing an element of the SSD setup.
virtual void InitDaughters()
TGeoPhysicalNode * fNode
Pointer to geometry.
Int_t GetNofDaughters() const
Int_t GetNofElements(Int_t level) const
Int_t fAddress
Unique element address.
BmnSsdElement * GetDaughter(Int_t index) const
TGeoPhysicalNode * GetPnode() const
Class representing an instance of a readout unit in the BMN-SSD.
static Int_t GetAddressFromName(TString name)
Get the address from the module name (static)
std::string ToString() const
Detector response for DSSD sensors with stereo angles and cross-connection by double metal layers.
std::string ToString() const
Set the internal sensor parameters.
virtual Bool_t Init()
Initialisation @value kTRUE if parameters and node are consistent.
Class describing double-sided silicon strip sensors.
virtual void ModifyStripPitch(Double_t pitch)=0
Modify the strip pitch.
Class representing an instance of a sensor in the BMN-SSD.
virtual Bool_t Init()
Initialise the sensor, if needed.
void SetAddress(Int_t address)
Set sensor address.
virtual std::string ToString() const =0
void SetConditions(Double_t vFD, Double_t vBias, Double_t temperature, Double_t cCoupling, Double_t cInterstrip, Double_t bX, Double_t bY, Double_t bZ)
const BmnSsdSensorConditions * GetConditions() const
void SetNode(TGeoPhysicalNode *node)
Set the physical node.
static UInt_t GetAddressFromName(TString name)
Get the address from the sensor name (static)
TGeoPhysicalNode * GetNode() const
Class representing the top level of the SSD setup.
Int_t GetStationNumber(Int_t address)
void SetDefaultSensorParameters(Double_t dInact, Double_t pitch, Double_t stereoF, Double_t stereoB)
Set the default sensor parameters.
static BmnSsdSetup * Instance()
Int_t SetModuleParameters(Double_t dynRange, Double_t threshold, Int_t nAdc, Double_t timeResolution, Double_t deadTime, Double_t noise, Double_t zeroNoiseRate, Double_t fracDeadChannels)
Set parameters for all modules.
Int_t ModifyStripPitch(Double_t pitch)
Modify the strip pitch for all sensors.
Int_t GetNofSensors() const
const char * GetLevelName(Int_t level)
Bool_t Init(const char *geometryFile=nullptr, const char *sensorParameterFile=nullptr)
Initialise the setup.
Int_t SetSensorConditions()
Set conditions for all sensors (same values for all)
BmnSsdElement * GetElement(Int_t address, Int_t level)
BmnSsdSensor * AssignSensor(Int_t address, TGeoPhysicalNode *node=nullptr)
BmnSsdSensor * DefaultSensor(Int_t address, TGeoPhysicalNode *node)
Instantiate the default sensor class for a given node.
Class representing a station of the SsdSystem.
void Init()
Initialise the station parameters.
void AddLadder(BmnSsdElement *ladder)
UInt_t GetSystemId(Int_t address)
Get system Id (should be kSSD)
UInt_t GetElementId(Int_t address, Int_t level)
Get the index of an element.
Int_t GetAddress(UInt_t unit=0, UInt_t ladder=0, UInt_t halfladder=0, UInt_t module=0, UInt_t sensor=0, UInt_t side=0, UInt_t version=kCurrentVersion)
Construct address.