BmnRoot
Loading...
Searching...
No Matches
BmnSsdSetup.cxx
Go to the documentation of this file.
1
7// Include class header
8#include "BmnSsdSetup.h"
9
10// Includes from C++
11#include <cassert>
12#include <fstream>
13#include <iostream>
14#include <iomanip>
15
16// Includes from ROOT
17#include "TFile.h"
18#include "TGeoBBox.h"
19#include "TGeoManager.h"
20#include "TKey.h"
21#include "TSystem.h"
22
23// Includes form FairRoot
24#include "FairField.h"
25
26// Includes from BmnRoot
27#include "BmnSsdAddress.h"
29#include "BmnSsdMC.h"
30#include "BmnSsdModule.h"
31#include "BmnSsdPhysics.h"
32#include "BmnSsdSensor.h"
33#include "BmnSsdSensorDssd.h"
35#include "BmnSsdStation.h"
36
37using namespace std;
38
39
40// ----- Initialisation of static singleton pointer --------------------
41BmnSsdSetup* BmnSsdSetup::fgInstance = NULL;
42// -------------------------------------------------------------------------
43
44
45
46// ----- Constructor ---------------------------------------------------
47BmnSsdSetup::BmnSsdSetup() : BmnSsdElement(kSSD, kSsdSystem),
48 fDigitizer(NULL), fSettings(NULL),fIsInitialised(kFALSE),
49 fIsOld(kFALSE), fNofSensorsDefault(0), fSensorDinact(0.), fSensorPitch(0.),
50 fSensorStereoF(0.), fSensorStereoB(0.),
51 fSensors(), fModules(), fModuleVector(),
52 fStations()
53{
54}
55// -------------------------------------------------------------------------
56
57
58
59// ----- Assign a sensor object to an address --------------------------
61 TGeoPhysicalNode* node) {
62
63 BmnSsdSensor* sensor = nullptr;
64 auto it = fSensors.find(address);
65 if ( it != fSensors.end() ) {
66 sensor = it->second; // Found in sensor list
67 assert (sensor->GetAddress() == address);
68 sensor->SetNode(node);
69 sensor->Init();
70 LOG(debug1) << GetName() << ": Assigning " << sensor->ToString()
71 << "\n\t\t to node " << node->GetName();
72 }
73 else {
74 sensor = DefaultSensor(address, node); // Not found; create and add.
75 LOG(debug1) << GetName() << ": Assigning default " << sensor->ToString()
76 << "\n\t\t to node " << node->GetName();
77 fNofSensorsDefault++;
78 }
79
80 return sensor;
81}
82// -------------------------------------------------------------------------
83
84
85
86// ----- Create station objects ----------------------------------------
87Int_t BmnSsdSetup::CreateStations() {
88
89 // For old geometries: the station corresponds to the unit
90 if ( fIsOld ) {
91
92 for (Int_t iUnit = 0; iUnit < GetNofDaughters(); iUnit++) {
93 BmnSsdElement* unit = GetDaughter(iUnit);
94
95 // Create one station for each unit
96 Int_t stationId = unit->GetIndex();
97 TString name = Form("SSD_S%02i", stationId+1);
98 TString title = Form("SSD Station %i", stationId+1);
99 BmnSsdStation* station = new BmnSsdStation(name, title,
100 unit->GetPnode());
101 // Add all ladders of the unit to the station
102 for (Int_t iLadder = 0; iLadder < unit->GetNofDaughters(); iLadder++)
103 station->AddLadder(unit->GetDaughter(iLadder));
104 // Initialise station parameters
105 station->Init();
106 // Add station to station map
107 assert ( fStations.find(stationId) == fStations.end() );
108 fStations[stationId] = station;
109 } //# units
110
111 return fStations.size();
112 } //? is old geometry?
113
114
115 // Loop over all ladders. They are associated to a station.
116 for (Int_t iUnit = 0; iUnit < GetNofDaughters(); iUnit++) {
117 BmnSsdElement* unit = GetDaughter(iUnit);
118 for ( Int_t iLadder = 0; iLadder < unit->GetNofDaughters(); iLadder++) {
119 BmnSsdElement* ladder = unit->GetDaughter(iLadder);
120 // This convention must be followed by the SSD geometry
121 Int_t nodeNumber = ladder->GetPnode()->GetNode()->GetNumber();
122 Int_t stationId = nodeNumber / 100 - 1;
123 // Get the station from the map. If not there, create it.
124 BmnSsdStation* station = NULL;
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);
128 station = new BmnSsdStation(name, title);
129 fStations[stationId] = station;
130 } //? station not yet in map
131 else station = fStations[stationId];
132
133 // Add ladder to station
134 station->AddLadder(ladder);
135
136 } //# ladders
137 } //# units
138
139 // Initialise the stations
140 auto it = fStations.begin();
141 while ( it != fStations.end() ) {
142 it->second->Init();
143 it++;
144 } //# stations
145
146 // Check that the station number is set consecutively and that the
147 // stations are ordered w.r.t. position along the beam
148 Bool_t isOk = kTRUE;
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!";
155 isOk = kFALSE;
156 } //? station 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."
161 ;
162 isOk = kFALSE;
163 } //? disordered in z
164 } //# stations
165 if ( ! isOk ) LOG(fatal) << GetName() << ": Error in creation of stations."
166 ;
167
168 return fStations.size();
169}
170// -------------------------------------------------------------------------
171
172
173
174// ----- Instantiate default sensor ------------------------------------
176 TGeoPhysicalNode* node) {
177
178 // There should not already be a sensor object for this address
179 assert ( fSensors.find(address) == fSensors.end() );
180
181 // Sensor volume extension in x and y
182 assert(node);
183 TGeoBBox* shape = dynamic_cast<TGeoBBox*>(node->GetShape());
184 assert(shape);
185 Double_t volX = 2. * shape->GetDX();
186 Double_t volY = 2. * shape->GetDY();
187
188 // Default pitch and stereo angles
189 Double_t pitch = 0.0058;
190 Double_t stereoF = 0.;
191 Double_t stereoB = 7.5;
192
193 // Size of inactive area in both x and y (total left+right/top+bottom)
194 Double_t dInact = 0.24;
195
196 // Number of strips. Calculated from active size in x, except for 6.2 cm
197 // sensors, where it is 1024.
198 Int_t nStrips = 1024;
199 if ( TMath::Abs(volX-6.2) > 0.01 )
200 nStrips = Int_t( (volX - dInact) / pitch );
201
202 // Active size in y
203 Double_t dy = volY - dInact;
204
205 // Create default sensor type DssdStereo
207 = new BmnSsdSensorDssdStereo(dy, nStrips, pitch, stereoF, stereoB);
208
209 // Assign address and node and add sensor to sensor list
210 sensor->SetAddress(address);
211 sensor->SetNode(node);
212 Bool_t status = sensor->Init();
213 assert(status);
214 fSensors[address] = sensor;
215
216 return sensor;
217}
218// -------------------------------------------------------------------------
219
220
221
222// ----- Get an element from the SSD setup -----------------------------
223BmnSsdElement* BmnSsdSetup::GetElement(Int_t address, Int_t level) {
224
225 // --- Check for initialisation
226 if ( ! fAddress ) LOG(fatal) << fName << ": not initialised!"
227 ;
228
229 // --- Catch non-SSD addresses
230 if ( BmnSsdAddress::GetSystemId(address) != kSSD ) {
231 LOG(WARNING) << fName << ": No SSD address " << address
232 ;
233 return NULL;
234 }
235
236 // --- Catch illegal level numbers
237 if ( level < 0 || level >= kSsdNofLevels ) {
238 LOG(WARNING) << fName << ": Illegal level " << level
239 ;
240 return NULL;
241 }
242
243 BmnSsdElement* element = this;
244 for (Int_t iLevel = 1; iLevel <= level; iLevel++) {
245 element =
246 element->GetDaughter(BmnSsdAddress::GetElementId(address, iLevel));
247 assert(element);
248 }
249
250 return element;
251}
252// -------------------------------------------------------------------------
253
254
255
256// ----- Get hierarchy level name ---------------------------------------
257const char* BmnSsdSetup::GetLevelName(Int_t level) {
258
259 // --- Catch legacy (setup with stations)
260 if ( fIsOld && level == kSsdUnit ) return "station";
261
262 switch(level) {
263 case kSsdSystem: return "ssd"; break;
264 case kSsdUnit: return "unit"; break;
265 case kSsdLadder: return "ladder"; break;
266 case kSsdHalfLadder: return "halfladder"; break;
267 case kSsdModule: return "module"; break;
268 case kSsdSensor: return "sensor"; break;
269 case kSsdSide: return "side"; break;
270 default: return ""; break;
271 }
272
273}
274// -------------------------------------------------------------------------
275
276
277
278// ----- Get the station number from an address ------------------------
279Int_t BmnSsdSetup::GetStationNumber(Int_t address) {
280
281 // In old, station-based geometries, the station equals the unit
282 if ( fIsOld ) return BmnSsdAddress::GetElementId(address, kSsdUnit);
283
284 // In new, unit-based geometries, the station is obtained from the ladder
286 assert(ladder);
287 return ladder->GetPnode()->GetNode()->GetNumber() / 100 - 1;
288
289}
290// -------------------------------------------------------------------------
291
292
293
294// ----- Initialisation ------------------------------------------------
295Bool_t BmnSsdSetup::Init(const char* /*geoFile*/, const char* parFile) {
296
297 // Prevent duplicate initialisation
298 assert( ! fIsInitialised );
299
300 cout << endl;
301 LOG(info) << "=========================================================="
302 ;
303 LOG(info) << "Initialising SSD Setup "
304 ;
305 LOG(info);
306
307 // Read sensor parameters from file, if specified
308 if ( parFile ) ReadSensorParameters(parFile);
309
310 // --- Set system address
312
313 // --- If a geometry file was specified, read the geometry from file
314 if ( parFile ) ReadGeometry(parFile);
315
316 // --- Else, read the geometry from TGeoManager
317 else {
318 assert(gGeoManager);
319 ReadGeometry(gGeoManager);
320 }
321
322 // --- Statistics
323 LOG(info) << fName << ": Elements in setup: ";
324 for (Int_t iLevel = 1; iLevel <= kSsdSensor; iLevel++) {
325 TString name = GetLevelName(iLevel);
326 name += "s";
327 LOG(info) << " " << setw(12) << name << setw(5) << right
328 << GetNofElements(iLevel);
329 }
330 LOG(info) << GetName() << ": " << fNofSensorsDefault
331 << " sensors created from default.";
332
333 // --- Build the module map
334 for (Int_t iUnit = 0; iUnit < GetNofDaughters(); iUnit++) {
335 BmnSsdElement* unit = GetDaughter(iUnit);
336 for (Int_t iLad = 0; iLad < unit->GetNofDaughters(); iLad++) {
337 BmnSsdElement* ladd = unit->GetDaughter(iLad);
338 for (Int_t iHla = 0; iHla < ladd->GetNofDaughters(); iHla++) {
339 BmnSsdElement* hlad = ladd->GetDaughter(iHla);
340 for (Int_t iMod = 0; iMod < hlad->GetNofDaughters(); iMod++) {
341 BmnSsdElement* modu = hlad->GetDaughter(iMod);
342 Int_t address = modu->GetAddress();
343 if ( fModules.find(address) != fModules.end() ) {
344 LOG(fatal) << GetName() << ": Duplicate module address "
345 << address << " for " << modu->GetName();
346 }
347 BmnSsdModule* module = dynamic_cast<BmnSsdModule*>(modu);
348 fModules[address] = module;
349 fModuleVector.push_back(module);
350 } //# modules in half-ladder
351 } //# half-ladders in ladder
352 } //# ladders in unit
353 } //# units in system
354
355 // --- Create station objects
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();
363 it++;
364 } //# stations
365 } //? Debug
366
367 // --- Consistency check
369 LOG(fatal) << GetName() << ": inconsistent number of sensors! "
371 ;
372 if ( fModules.size() != GetNofElements(kSsdModule) )
373 LOG(fatal) << GetName() << ": inconsistent number of modules! "
374 << GetNofElements(kSsdModule) << " "
375 << fModules.size();
376
377 LOG(info) << "=========================================================="
378 << "\n";
379 cout << endl;
380
381 fIsInitialised = kTRUE;
382 return kTRUE;
383}
384// -------------------------------------------------------------------------
385
386
387
388// ----- Singleton instance --------------------------------------------
390 if ( ! fgInstance ) fgInstance = new BmnSsdSetup();
391 return fgInstance;
392}
393// -------------------------------------------------------------------------
394
395
396
397// ----- Print list of modules -----------------------------------------
399 for (auto it = fModules.begin(); it != fModules.end(); it++)
400 LOG(info) << it->second->ToString();
401}
402// -------------------------------------------------------------------------
403
404
405
406// ----- Modify the strip pitch for all sensors ------------------------
407Int_t BmnSsdSetup::ModifyStripPitch(Double_t pitch) {
408
409 Int_t nModified = 0;
410 for ( auto it = fSensors.begin(); it != fSensors.end(); it++ ) {
411
412 BmnSsdSensorDssd* sensor = dynamic_cast<BmnSsdSensorDssd*>(it->second);
413 if ( ! sensor ) continue;
414 sensor->ModifyStripPitch(pitch);
415 nModified++;
416 }
417
418 return nModified;
419}
420// -------------------------------------------------------------------------
421
422
423
424// ----- Read geometry from TGeoManager --------------------------------
425Bool_t BmnSsdSetup::ReadGeometry(TGeoManager* geo) {
426
427 // --- Catch non-existence of GeoManager
428 assert (geo);
429 LOG(info) << fName << ": Reading geometry from TGeoManager "
430 << geo->GetName();
431
432 // --- Get cave (top node)
433 geo->CdTop();
434 TGeoNode* cave = geo->GetCurrentNode();
435
436 // --- Get top SSD node
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)) ) { //for backward compatibility
444 ssd = cave->GetDaughter(iNode);
445 LOG(info) << fName << ": SSD top node is " << ssd->GetName()
446 ;
447 break;
448 }
449 }
450 if ( ! ssd ) {
451 LOG(error) << fName << ": No top SSD node found in geometry!"
452 ;
453 return kFALSE;
454 }
455
456 // --- Create physical node for ssd
457 TString path = cave->GetName();
458 path = path + "/" + ssd->GetName();
459 fNode = new TGeoPhysicalNode(path);
460
461 // --- Check for old geometry (with stations) or new geometry (with units)
462 Bool_t hasStation = kFALSE;
463 Bool_t hasUnit = kFALSE;
464 for (Int_t iDaughter = 0; iDaughter < fNode->GetNode()->GetNdaughters();
465 iDaughter++) {
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;
469 }
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 "
475 << "nor stations!";
476 if ( fIsOld ) LOG(WARNING) << GetName() << ": using old geometry (with stations)"
477 ;
478
479 // --- Recursively initialise daughter elements
481
482 return kTRUE;
483}
484// -------------------------------------------------------------------------
485
486
487
488// ----- Read geometry from geometry file ------------------------------
489Bool_t BmnSsdSetup::ReadGeometry(const char* fileName) {
490
491 LOG(info) << fName << ": Reading geometry from file "
492 << fileName;
493
494 // Exit if a TGeoManager is already present
495 assert ( ! gGeoManager );
496
497 // --- Open geometry file
498 TFile geoFile(fileName);
499 if ( ! geoFile.IsOpen() ) {
500 LOG(fatal) << GetName() << ": Could not open geometry file "
501 << fileName;
502 return kFALSE;
503 }
504
505 // Create a new TGeoManager
506 TGeoManager* ssdGeometry = new TGeoManager("SsdGeo",
507 "SSD stand-alone geometry");
508
509 // --- Get top volume from file
510 TGeoVolume* topVolume = NULL;
511 TList* keyList = geoFile.GetListOfKeys();
512 TKey* key = NULL;
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 ) {
518 topVolume = volume;
519 break;
520 } //? volume name is "TOP"
521 } //? object class is TGeoVolumeAssembly
522 }
523 if ( ! topVolume) {
524 LOG(fatal) << GetName() << ": No TOP volume in file!";
525 return kFALSE;
526 }
527 ssdGeometry->SetTopVolume(topVolume);
528
529 // --- Get cave (top node)
530 ssdGeometry->CdTop();
531 TGeoNode* cave = ssdGeometry->GetCurrentNode();
532
533 // --- Get top SSD node
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)) ) { //for backward compatibility
539 ssd = cave->GetDaughter(iNode);
540 ssdGeometry->CdDown(iNode);
541 LOG(info) << fName << ": SSD top node is " << ssd->GetName()
542 ;
543 break;
544 }
545 }
546 if ( ! ssd ) {
547 LOG(error) << fName << ": No top SSD node found in geometry!"
548 ;
549 return kFALSE;
550 }
551
552 // --- Create physical node for ssd
553 TString path = cave->GetName();
554 path = path + "/" + ssd->GetName();
555 fNode = new TGeoPhysicalNode(path);
556
557 // --- Check for old geometry (with stations) or new geometry (with units)
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 "
563 << dName;
564 if ( fIsOld ) LOG(WARNING) << GetName() << ": using old geometry (with stations)"
565 ;
566
567 // --- Recursively initialise daughter elements
569
570 return kTRUE;
571}
572// -------------------------------------------------------------------------
573
574
575
576// ----- Set sensor types ----------------------------------------------
577Int_t BmnSsdSetup::ReadSensorParameters(const char* fileName) {
578
579 // Input file
580 std::fstream inFile;
581 TString inputFile = fileName;
582
583 // Try with argument as is (absolute path or current directory)
584 inFile.open(inputFile.Data());
585
586 // If not successful, look in the standard parameter directory
587 if ( ! inFile.is_open() ) {
588 inputFile = gSystem->Getenv("VMCWORKDIR");
589 inputFile += "/parameters/ssd/" + TString(fileName);
590 inFile.open(inputFile.Data());
591 }
592
593 // If still not open, throw an error
594 if ( ! inFile.is_open() ) {
595 LOG(fatal) << GetName() << ": Cannot read file " << fileName
596 << " nor " << inputFile;
597 return -1;
598 }
599
600 string input;
601 TString sName, sType;
602 Int_t nSensors = 0;
603
604 while ( kTRUE ) { // read one line
605 if ( inFile.eof() ) break;
606 getline(inFile, input);
607 if (input.empty() || input[0] == '#') continue; // Comment line
608 std::stringstream line(input);
609 line >> sName >> sType;
610
611 // Look for sensor in setup
612 Int_t address = BmnSsdSensor::GetAddressFromName(sName);
613
614 // Bail out if sensor is already known
615 if ( fSensors.find(address) != fSensors.end() ) {
616 LOG(error) << GetName() << ": sensor " << sName
617 << " is already in the setup!";
618 continue;
619 }
620
621 // Case sensor type DssdStereo
622 if ( sType.EqualTo("DssdStereo", TString::kIgnoreCase) ) {
623 Double_t dy = 0.; // active length in y
624 Int_t nStrips = 0; // number of strips
625 Double_t pitch = 0.; // strip pitch
626 Double_t stereoF = 0.; // stereo angle front side
627 Double_t stereoB = 0.; // stereo angle back side
628 line >> dy >> nStrips >> pitch >> stereoF >> stereoB;
630 = new BmnSsdSensorDssdStereo(dy, nStrips, pitch, stereoF, stereoB);
631 sensor->SetAddress(address);
632 LOG(debug) << "Created " << sensor->ToString();
633 fSensors[address] = sensor;
634 nSensors++;
635 } //? sensor type DssdStereo
636
637 else {
638 LOG(fatal) << GetName() << ": Unknown sensor type " << sType
639 << " for sensor " << sName;
640 } //? Unknown sensor type
641
642 } //# input lines
643
644 inFile.close();
645 LOG(info) << GetName() << ": Read " << nSensors
646 << (nSensors == 1 ? " sensor" : " sensors") << " from "
647 << inputFile;
648 assert( nSensors = fSensors.size() );
649
650 return nSensors;
651}
652// -------------------------------------------------------------------------
653
654
655
656// ----- Set the default sensor parameters -----------------------------
658 Double_t pitch,
659 Double_t stereoF,
660 Double_t stereoB) {
661 assert( ! fIsInitialised );
662 assert( dInact >= 0.);
663 assert( pitch >= 0. );
664 fSensorDinact = dInact;
665 fSensorPitch = pitch;
666 fSensorStereoF = stereoF;
667 fSensorStereoB = stereoB;
668}
669// -------------------------------------------------------------------------
670
671
672
673// ----- Set global parameters for all modules -------------------------
674Int_t BmnSsdSetup::SetModuleParameters(Double_t dynRange,
675 Double_t threshold,
676 Int_t nAdc, Double_t tResolution,
677 Double_t tDead, Double_t noise,
678 Double_t zeroNoiseRate,
679 Double_t fracDeadChannels) {
680
681 Int_t nModules = 0;
682 for ( auto it = fModules.begin(); it != fModules.end(); it++) {
683 it->second->SetParameters(dynRange, threshold, nAdc, tResolution,
684 tDead, noise, zeroNoiseRate, fracDeadChannels);
685 nModules++;
686 }
687
688 return nModules;
689}
690// -------------------------------------------------------------------------
691
692
693
694// ----- Set module parameters from file -------------------------------
695Int_t BmnSsdSetup::SetModuleParameters(const char* fileName) {
696
697 // Input file
698 std::fstream inFile;
699 TString inputFile = fileName;
700
701 // Try with argument as is (absolute path or current directory)
702 inFile.open(inputFile.Data());
703
704 // If not successful, look in the standard parameter directory
705 if ( ! inFile.is_open() ) {
706 inputFile = gSystem->Getenv("VMCWORKDIR");
707 inputFile += "/parameters/ssd/" + TString(fileName);
708 inFile.open(inputFile.Data());
709 }
710
711 // If still not open, throw an error
712 if ( ! inFile.is_open() ) {
713 LOG(fatal) << GetName() << ": Cannot read file " << fileName
714 << " nor " << inputFile;
715 return 0;
716 }
717
718 string input;
719 TString mName;
720 Double_t dynRange = -1.e10;
721 Double_t threshold = -1.e10;
722 Int_t nAdc = -1;
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;
728 UInt_t nModules = 0;
729
730 while ( kTRUE ) { // read one line
731 if ( inFile.eof() ) break;
732 getline(inFile, input);
733 if (input.empty() || input[0] == '#') continue; // Comment line
734 std::stringstream line(input);
735 line >> mName >> dynRange >> threshold >> nAdc >> tResol >> tDead >> noise
736 >> zeroNoise >> fracDead;
737
738 // Look for module in setup
739 Int_t address = BmnSsdModule::GetAddressFromName(mName);
740 if ( fModules.find(address) == fModules.end() ) {
741 LOG(error) << GetName() << ": Module " << mName
742 << " not found in the setup!";
743 continue;
744 }
745 BmnSsdModule* module = fModules.find(address)->second;
746 assert(module);
747
748 // Check for double occurrences of sensors
749 if ( module->IsSet() ) {
750 LOG(error) << GetName() << ": Parameters of module "
751 << module->GetName() << " are already set!";
752 continue;
753 }
754
755 // Check presence of module parameters
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;
764 continue;
765 }
766
767 // --- Set parameters of module
768 module->SetParameters(dynRange, threshold, nAdc, tResol, tDead, noise,
769 zeroNoise, fracDead);
770 LOG(debug1) << GetName() << ": Set " << module->ToString()
771 ;
772 nModules++;
773
774 } //# input lines
775
776 inFile.close();
777 LOG(info) << GetName() << ": Read conditions of " << nModules
778 << (nModules == 1 ? " module" : " modules") << " from "
779 << inputFile;
780
781 // Check that all sensors have their conditions set
782 if ( nModules!= fModules.size() ) {
783 LOG(fatal) << GetName() << ": " << fModules.size()
784 << " modules in setup, but parameters for " << nModules
785 << " in parameter file!";
786 }
787
788 return nModules;
789}
790// -------------------------------------------------------------------------
791
792
793
794// ----- Set conditions for all sensors --------------------------------
796
797 Int_t nSensors = 0; // Sensor counter
798
799 // Get conditions from parameter object
800 assert(fSettings);
801 Double_t vDep = fSettings->GetVdep(); // Full depletion voltage
802 Double_t vBias = fSettings->GetVbias(); // Bias voltage
803 Double_t temperature = fSettings->GetTemperature(); // Temperature
804 Double_t cCoup = fSettings->GetCcoup(); // Coupling capacitance
805 Double_t cIs = fSettings->GetCis(); // Inter-strip capacitance
806
807 // Workaround for separate reconstruction and digitisation
808 vDep = 70.;
809 vBias = 140.;
810 temperature = 268.;
811 cCoup = 17.5;
812 cIs = 1.;
813
814 // --- Control output of parameters
815 LOG(info) << GetName() << ": Set conditions for all sensors:"
816 ;
817 LOG(info) << "\t Full depletion voltage " << vDep
818 << " V";
819 LOG(info) << "\t Bias voltage " << vBias
820 << " V";
821 LOG(info) << "\t Temperature " << temperature << " K"
822 ;
823 LOG(info) << "\t Coupling capacitance " << cCoup
824 << " pF";
825 LOG(info) << "\t Inter-strip capacitance " << cIs
826 << " pF";
827
828 // --- Set conditions for all sensors
829 for ( auto it = fSensors.begin(); it != fSensors.end(); it++ ) {
830
831 // Get sensor centre coordinates in the global c.s.
832 Double_t local[3] = { 0., 0., 0.}; // sensor centre in local C.S.
833 Double_t global[3]; // sensor centre in global C.S.
834 it->second->GetNode()->GetMatrix()->LocalToMaster(local, global);
835
836 // Get the field in the sensor centre. Note that the values are in kG
837 // and have to be converted to T
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.);
843
844 nSensors++;
845 } //# sensors
846
847 return nSensors;
848}
849// -------------------------------------------------------------------------
850
851
852
853// ----- Set conditions for all sensors --------------------------------
854Int_t BmnSsdSetup::SetSensorConditions(Double_t vDep, Double_t vBias,
855 Double_t temperature,
856 Double_t cCoupling,
857 Double_t cInterstrip) {
858
859 Int_t nSensors = 0; // Sensor counter
860
861 // --- Set conditions for all sensors
862 for ( auto it = fSensors.begin(); it != fSensors.end(); it++ ) {
863
864 // Get sensor centre coordinates in the global c.s.
865 Double_t local[3] = { 0., 0., 0.}; // sensor centre in local C.S.
866 Double_t global[3]; // sensor centre in global C.S.
867 it->second->GetNode()->GetMatrix()->LocalToMaster(local, global);
868
869 // Get the field in the sensor centre
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,
874 cInterstrip,
875 field[0]/10., field[1]/10., field[2]/10.);
876
877 nSensors++;
878 } //# sensors
879
880 return nSensors;
881}
882// -------------------------------------------------------------------------
883
884
885
886// ----- Set sensor conditions from file -------------------------------
887Int_t BmnSsdSetup::SetSensorConditions(const char* fileName) {
888
889 // Input file
890 std::fstream inFile;
891 TString inputFile = fileName;
892
893 // Try with argument as is (absolute path or current directory)
894 inFile.open(inputFile.Data());
895
896 // If not successful, look in the standard parameter directory
897 if ( ! inFile.is_open() ) {
898 inputFile = gSystem->Getenv("VMCWORKDIR");
899 inputFile += "/parameters/ssd/" + TString(fileName);
900 inFile.open(inputFile.Data());
901 }
902
903 // If still not open, throw an error
904 if ( ! inFile.is_open() ) {
905 LOG(fatal) << GetName() << ": Cannot read file " << fileName
906 << " nor " << inputFile;
907 return 0;
908 }
909
910 string input;
911 TString sName;
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;
917 UInt_t nSensors = 0;
918
919 while ( kTRUE ) { // read one line
920 if ( inFile.eof() ) break;
921 getline(inFile, input);
922 if (input.empty() || input[0] == '#') continue; // Comment line
923 std::stringstream line(input);
924 line >> sName >> vDep >> vBias >> temperature >> cCoupling >> cInterstrip;
925
926 // Look for sensor in setup
927 Int_t address = BmnSsdSensor::GetAddressFromName(sName);
928 if ( fSensors.find(address) == fSensors.end() ) {
929 LOG(error) << GetName() << ": Sensor " << sName
930 << " not found in the setup!";
931 continue;
932 }
933 BmnSsdSensor* sensor = fSensors.find(address)->second;
934 assert(sensor);
935
936 // Check for double occurrences of sensors
937 if ( sensor->GetConditions() ) {
938 LOG(error) << GetName() << ": Conditions of sensor "
939 << sensor->GetName() << " are already set!";
940 continue;
941 }
942
943 // Check presence of condition parameters
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
950 ;
951 continue;
952 }
953
954 // --- Get the field in the sensor centre
955 Double_t local[3] = { 0., 0., 0.}; // sensor centre in local C.S.
956 Double_t global[3]; // sensor centre in global C.S.
957 sensor->GetNode()->GetMatrix()->LocalToMaster(local, global);
958 Double_t field[3] = { 0., 0., 0.}; // field in sensor centre
959 if ( FairRun::Instance()->GetField() )
960 FairRun::Instance()->GetField()->Field(global, field);
961
962 // --- Set conditions of sensor (n.b. conversion from kG to T)
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()
966 << " " << sensor->GetConditions()->ToString();
967 nSensors++;
968
969 } //# input lines
970
971 inFile.close();
972 LOG(info) << GetName() << ": Read conditions of " << nSensors
973 << (nSensors == 1 ? " sensor" : " sensors") << " from "
974 << inputFile;
975
976 // Check that all sensors have their conditions set
977 if ( nSensors != fSensors.size() ) {
978 LOG(fatal) << GetName() << ": " << fSensors.size()
979 << " sensors in setup, but conditions for " << nSensors
980 << " in conditions file!";
981 }
982
983 return nSensors;
984}
985// -------------------------------------------------------------------------
@ kSsdLadder
@ kSsdUnit
@ kSsdNofLevels
@ kSsdSystem
@ kSsdSensor
@ kSsdSide
@ kSsdModule
@ kSsdHalfLadder
Bool_t fIsInitialised
kTRUE if Init() was called
@ kSSD
Class representing an element of the SSD setup.
Int_t GetAddress() const
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
Int_t GetIndex() 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)
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.
Definition BmnSsdSetup.h:30
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)
void ListModules() const
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.
name
Definition setup.py:7
STL namespace.