SND@LHC Software
Loading...
Searching...
No Matches
ShipFieldMaker Class Reference

Creates various magnetic fields and assigns them to geometry regions. More...

#include <ShipFieldMaker.h>

Inheritance diagram for ShipFieldMaker:
Collaboration diagram for ShipFieldMaker:

Classes

struct  fieldInfo
 Structure to hold volume name, field name and field scaling factor. More...
 
struct  transformInfo
 Structure to hold transformation information. More...
 

Public Types

typedef std::map< TString, TVirtualMagField * > SFMap
 Typedef for a TString-TVirtualMagField* map.
 
typedef std::vector< std::string > stringVect
 Typedef of a vector of strings.
 

Public Member Functions

 ShipFieldMaker (Bool_t verbose=kFALSE)
 Constructor.
 
virtual ~ShipFieldMaker ()
 Destructor.
 
virtual void Construct ()
 Set-up all local and regional fields and assign them to volumes.
 
void readInputFile (const std::string &inputFile)
 Read an input file to define fields and associated volumes.
 
void defineUniform (const TString &name, const TVector3 &BVector)
 Define a uniform field.
 
void defineConstant (const TString &name, const TVector2 &xRange, const TVector2 &yRange, const TVector2 &zRange, const TVector3 &BVector)
 Define a constant field.
 
void defineBell (const TString &name, Double_t BPeak, Double_t zMiddle, Int_t orient=1, Double_t tubeR=500.0, Double_t xy=0.0, Double_t z=0.0, Double_t L=0.0)
 Define a Bell field.
 
void defineFieldMap (const TString &name, const TString &mapFileName, const TVector3 &localCentre=TVector3(0.0, 0.0, 0.0), const TVector3 &localAngles=TVector3(0.0, 0.0, 0.0), Bool_t useSymmetry=kFALSE)
 
void defineFieldMapCopy (const TString &name, const TString &mapNameToCopy, const TVector3 &translation, const TVector3 &eulerAngles=TVector3(0.0, 0.0, 0.0))
 Define a copy of a field map with a coordinate translation and optional rotation.
 
void defineComposite (const TString &name, const TString &field1Name, const TString &field2Name, const TString &field3Name="", const TString &field4Name="")
 Define a composite field from up to four fields.
 
void defineComposite (const TString &name, std::vector< TString > fieldNames)
 Define a composite field from a vector of field names.
 
void defineGlobalField (const TString &field1Name, const TString &field2Name="", const TString &field3Name="", const TString &field4Name="")
 Define a composite field from up to four fields.
 
void defineGlobalField (std::vector< TString > fieldNames)
 Define the Global field using a vector of field names.
 
void defineRegionField (const TString &volName, const TString &fieldName, Double_t scale=1.0)
 Define a regional (local + global) field and volume pairing.
 
void defineLocalField (const TString &volName, const TString &fieldName, Double_t scale=1.0)
 Define a localised field and volume pairing.
 
ShipCompFieldgetGlobalField () const
 Get the global magnetic field.
 
SFMap getAllFields () const
 Get the map storing volume names and their associated local magnetic fields.
 
TVirtualMagField * getVolumeField (const TString &volName) const
 Get the magnetic field for the given volume.
 
Bool_t gotField (const TString &name) const
 Check if we have a field stored with the given name name.
 
TVirtualMagField * getField (const TString &name) const
 Get the field stored with the given name name.
 
void plotXYField (const TVector3 &xAxis, const TVector3 &yAxis, const std::string &plotFile) const
 Plot the magnetic field in x-y plane.
 
void plotZXField (const TVector3 &zAxis, const TVector3 &xAxis, const std::string &plotFile) const
 Plot the magnetic field in z-x plane.
 
void plotZYField (const TVector3 &zAxis, const TVector3 &yAxis, const std::string &plotFile) const
 Plot the magnetic field in z-y plane.
 
void plotField (Int_t type, const TVector3 &xAxis, const TVector3 &yAxis, const std::string &plotFile) const
 Plot the magnetic field in "x-y" plane.
 
void generateFieldMap (TString fileName, const float step=2.5, const float xRange=179, const float yRange=317, const float zRange=1515.5, const float zShift=-4996)
 
 ClassDef (ShipFieldMaker, 1)
 Generate fieldMap csv file in the given region.
 

Protected Member Functions

void defineUniform (const stringVect &inputLine)
 Define a uniform field based on information from the inputLine.
 
void defineConstant (const stringVect &inputLine)
 Define a constant field based on information from the inputLine.
 
void defineBell (const stringVect &inputLine)
 Define a Bell field based on information from the inputLine.
 
void defineFieldMap (const stringVect &inputLine, Bool_t useSymmetry=kFALSE)
 Define a field map based on information from the inputLine.
 
void defineFieldMapCopy (const stringVect &inputLine)
 Define a (translated) copy of a field map based on information from the inputLine.
 
void defineComposite (const stringVect &inputLine)
 Define a composite field based on information from the inputLine.
 
void defineGlobalField (const stringVect &inputLine)
 Define the global field based on information from the inputLine.
 
void defineRegionField (const stringVect &inputLine)
 Define a regional (local+global) field based on the info from the inputLine.
 
void setAllRegionFields ()
 
void defineLocalField (const stringVect &inputLine)
 Define a local field only based on information from the inputLine.
 
void checkLocalFieldMap (TVirtualMagField *&localField, const TString &volName, Double_t scale)
 Check if we have a local field map and store the volume global transformation.
 
void setAllLocalFields ()
 
void getTransformation (const TString &volName, transformInfo &theInfo)
 Get the transformation matrix for the volume position and orientation.
 
void findNode (TGeoVolume *aVolume, const TString &volName)
 Update the current geometry node pointer that matches the required volume name.
 

Private Member Functions

stringVect splitString (std::string &theString, std::string &splitter) const
 Split a string.
 

Private Attributes

ShipCompFieldglobalField_
 The global magnetic field.
 
SFMap theFields_
 The map storing all created magnetic fields.
 
std::vector< fieldInforegionInfo_
 Vector of fieldInfo for regional fields.
 
std::vector< fieldInfolocalInfo_
 Vector of fieldInfo for local fields.
 
Bool_t verbose_
 Verbose boolean.
 
Double_t Tesla_
 Double converting Tesla to kiloGauss (for VMC/FairRoot B field units)
 
TGeoNode * theNode_
 The current volume node: used for finding volume transformations.
 
Bool_t gotNode_
 Boolean to specify if we have found the volume node we need.
 

Detailed Description

Creates various magnetic fields and assigns them to geometry regions.

The internal units here are cm for distances and Tesla for fields. Geant4 units for distance are mm, B fields = 0.001 megaVolt*ns/mm^2 (1 Tesla). VMC units require cm and kGauss (0.1 Tesla). Internally, use cm and Tesla, so keep distances unchanged but multiply B fields by 10 (1 Tesla = 10 kGauss)

Author
John Back J.J.B.nosp@m.ack@.nosp@m.warwi.nosp@m.ck.a.nosp@m.c.uk
John Back J.J.B.nosp@m.ack@.nosp@m.warwi.nosp@m.ck.a.nosp@m.c.uk

This inherits from TG4VUserPostDetConstruction and overloads the Contruct() function so that the VMC (re)assigns the G4 magnetic fields to volumes using the input configuration file defined in this class constructor, together with the code below used in the addVMCFields function in python/geomGeant4.py:

geom = ROOT.TG4GeometryManager.Instance() geom.SetUserPostDetConstruction(fieldMaker) geom.ConstructSDandField()

Definition at line 35 of file ShipFieldMaker.h.

Member Typedef Documentation

◆ SFMap

typedef std::map<TString, TVirtualMagField*> ShipFieldMaker::SFMap

Typedef for a TString-TVirtualMagField* map.

Definition at line 47 of file ShipFieldMaker.h.

◆ stringVect

typedef std::vector<std::string> ShipFieldMaker::stringVect

Typedef of a vector of strings.

Definition at line 50 of file ShipFieldMaker.h.

Constructor & Destructor Documentation

◆ ShipFieldMaker()

ShipFieldMaker::ShipFieldMaker ( Bool_t  verbose = kFALSE)

Constructor.

Definition at line 37 of file ShipFieldMaker.cxx.

37 :
38 TG4VUserPostDetConstruction(),
39 globalField_(0),
40 theFields_(),
42 localInfo_(),
43 verbose_(verbose),
44 Tesla_(10.0), // To convert T to kGauss for VMC/FairRoot
45 theNode_(0),
46 gotNode_(kFALSE)
47{
48}
std::vector< fieldInfo > localInfo_
Vector of fieldInfo for local fields.
Bool_t gotNode_
Boolean to specify if we have found the volume node we need.
SFMap theFields_
The map storing all created magnetic fields.
ShipCompField * globalField_
The global magnetic field.
std::vector< fieldInfo > regionInfo_
Vector of fieldInfo for regional fields.
TGeoNode * theNode_
The current volume node: used for finding volume transformations.
Double_t Tesla_
Double converting Tesla to kiloGauss (for VMC/FairRoot B field units)
Bool_t verbose_
Verbose boolean.

◆ ~ShipFieldMaker()

ShipFieldMaker::~ShipFieldMaker ( )
virtual

Destructor.

Definition at line 50 of file ShipFieldMaker.cxx.

51{
52
53 // Delete the various magnetic fields
54 SFMap::iterator iter;
55 for (iter = theFields_.begin(); iter != theFields_.end(); ++iter) {
56
57 delete iter->second;
58
59 }
60
61 theFields_.clear();
62
63}

Member Function Documentation

◆ checkLocalFieldMap()

void ShipFieldMaker::checkLocalFieldMap ( TVirtualMagField *&  localField,
const TString &  volName,
Double_t  scale 
)
protected

Check if we have a local field map and store the volume global transformation.

Parameters
[in]localFieldThe pointer (reference) to the field map (which may be updated)
[in]volNameThe name of the volume (which is used to find the transformation)
[in]scaleThe B field magnitude scaling factor

Definition at line 951 of file ShipFieldMaker.cxx.

952 {
953
954 // We assume that local field maps are stored using co-ordinates centred
955 // on the volume. However, GetField() uses global co-ordinates, so we need
956 // to find the global volume transformation (translation and rotation) so
957 // that we can find the equivalent local co-ordinates. This also means that each
958 // local volume needs to have its own lightweight field map copy, where we
959 // reuse the field map data but just change the co-ordinate transformation info
960
961 ShipBFieldMap* mapField = dynamic_cast<ShipBFieldMap*>(localField);
962 if (mapField) {
963
964 TString fieldName(mapField->GetName());
965 TString localName(fieldName); localName += volName;
966
967 if (verbose_) {
968 std::cout<<"Checking local field map "<<fieldName
969 <<" co-ord transformation for volume "<<volName<<std::endl;
970 }
971
972 // Check if we already have the local map to avoid duplication
973 ShipBFieldMap* localMap = dynamic_cast<ShipBFieldMap*>(this->getField(localName));
974
975 if (!localMap && volName.Length() > 0) {
976
977 // Get the volume and its associate global transformation
978 TString volName1(volName); volName1 += "_1";
979
980 transformInfo theInfo;
981 this->getTransformation(volName1, theInfo);
982
983 // The original field map may have defined its own translation and rotation.
984 // Apply this before the volume global transformation
985 Double_t origX0 = mapField->GetXOffset();
986 Double_t origY0 = mapField->GetYOffset();
987 Double_t origZ0 = mapField->GetZOffset();
988 TGeoTranslation origTrans("origTrans", origX0, origY0, origZ0);
989
990 Double_t origPhi = mapField->GetPhi();
991 Double_t origTheta = mapField->GetTheta();
992 Double_t origPsi = mapField->GetPsi();
993 TGeoRotation origRot("origRot", origPhi, origTheta, origPsi);
994
995 TGeoCombiTrans origComb(origTrans, origRot);
996 if (verbose_) {
997 std::cout<<"The original field map transformation:"<<std::endl;
998 origComb.Print();
999 }
1000
1001 TGeoTranslation newTrans("newTrans", theInfo.x0_, theInfo.y0_, theInfo.z0_);
1002 TGeoRotation newRot("newRot", theInfo.phi_, theInfo.theta_, theInfo.psi_);
1003
1004 TGeoCombiTrans newComb(newTrans, newRot);
1005
1006 if (verbose_) {
1007 std::cout<<"The volume transformation:"<<std::endl;
1008 newComb.Print();
1009 }
1010
1011 // The full transformation
1012 newComb = newComb*origComb;
1013
1014 if (verbose_) {
1015 std::cout<<"The combined transformation:"<<std::endl;
1016 newComb.Print();
1017 }
1018
1019 // Update transformation info
1020 const Double_t* newTransArray = newComb.GetTranslation();
1021 theInfo.x0_ = newTransArray[0];
1022 theInfo.y0_ = newTransArray[1];
1023 theInfo.z0_ = newTransArray[2];
1024
1025 const TGeoRotation* fullRot = newComb.GetRotation();
1026 if (fullRot) {
1027 fullRot->GetAngles(theInfo.phi_, theInfo.theta_, theInfo.psi_);
1028 }
1029
1030 // Create a lightweight copy, reusing the map data but just updating
1031 // the global transformation
1032 if (verbose_) {
1033 std::cout<<"Creating field map copy for "<<localName
1034 <<" based on "<<mapField->GetName()
1035 <<": x0 = "<<theInfo.x0_<<", y0 = "<<theInfo.y0_
1036 <<", z0 = "<<theInfo.z0_<<", phi = "<<theInfo.phi_
1037 <<", theta = "<<theInfo.theta_
1038 <<", psi = "<<theInfo.psi_<<", scale = "<<scale
1039 <<" and symmetry = "<<mapField->HasSymmetry()<<std::endl;
1040 }
1041
1042 localMap = new ShipBFieldMap(localName.Data(), *mapField,
1043 theInfo.x0_, theInfo.y0_, theInfo.z0_,
1044 theInfo.phi_, theInfo.theta_, theInfo.psi_, scale);
1045 // Keep track that we have created this field pointer
1046 theFields_[localName] = localMap;
1047
1048 }
1049
1050 // Set the localField pointer to use the (new or already existing) localMap pointer
1051 localField = localMap;
1052
1053 }
1054
1055}
Class that defines a (3d) magnetic field map (distances in cm, fields in tesla)
Bool_t HasSymmetry() const
Get the boolean flag to specify if we have quadrant symmetry.
Float_t GetYOffset() const
Get the y offset co-ordinate of the map for global positioning.
Float_t GetTheta() const
Get the second Euler rotation angle about the new x axis for global positioning.
Float_t GetPsi() const
Get the third Euler rotation angle about the new z axis for global positioning.
Float_t GetPhi() const
Get the first Euler rotation angle about the z axis for global positioning.
Float_t GetXOffset() const
Get the x offset co-ordinate of the map for global positioning.
Float_t phi_
The first Euler rotation angle about the z axis.
Float_t GetZOffset() const
Get the z offset co-ordinate of the map for global positioning.
TVirtualMagField * getField(const TString &name) const
Get the field stored with the given name name.
void getTransformation(const TString &volName, transformInfo &theInfo)
Get the transformation matrix for the volume position and orientation.

◆ ClassDef()

ShipFieldMaker::ClassDef ( ShipFieldMaker  ,
 
)

Generate fieldMap csv file in the given region.

ClassDef for ROOT

◆ Construct()

void ShipFieldMaker::Construct ( )
virtual

Set-up all local and regional fields and assign them to volumes.

Definition at line 65 of file ShipFieldMaker.cxx.

66{
67
68 // Assign volumes with their regional (local + global) or local B fields
69 this->setAllRegionFields();
70 this->setAllLocalFields();
71
72}

◆ defineBell() [1/2]

void ShipFieldMaker::defineBell ( const stringVect inputLine)
protected

Define a Bell field based on information from the inputLine.

Parameters
[in]inputLineThe space separated input line

Definition at line 320 of file ShipFieldMaker.cxx.

321{
322
323 size_t nWords = inputLine.size();
324
325 // Expecting a line such as:
326 // Bell Name BPeak zMiddle orientationInt tubeRadius
327
328 if (nWords == 6 || nWords == 9) {
329
330 TString name(inputLine[1].c_str());
331
332 Double_t BPeak = std::atof(inputLine[2].c_str());
333 Double_t zMiddle = std::atof(inputLine[3].c_str()); // cm
334
335 Int_t orient = std::atoi(inputLine[4].c_str());
336 Double_t tubeR = std::atof(inputLine[5].c_str()); // cm
337
338 Double_t xy(0.0), z(0.0), L(0.0);
339
340 if (nWords == 9) {
341 // Specify "target" dimensions (cm)
342 xy = std::atof(inputLine[6].c_str());
343 z = std::atof(inputLine[7].c_str());
344 L = std::atof(inputLine[8].c_str());
345 }
346
347 this->defineBell(name, BPeak, zMiddle, orient, tubeR, xy, z, L);
348
349 } else {
350
351 std::cout<<"Expecting 6 or 9 words for the definition of the Bell field: "
352 <<"Bell Name BPeak zMiddle orientationInt tubeRadius [targetXY targetZ0 targetL]"<<std::endl;
353
354 }
355
356}
void defineBell(const TString &name, Double_t BPeak, Double_t zMiddle, Int_t orient=1, Double_t tubeR=500.0, Double_t xy=0.0, Double_t z=0.0, Double_t L=0.0)
Define a Bell field.

◆ defineBell() [2/2]

void ShipFieldMaker::defineBell ( const TString &  name,
Double_t  BPeak,
Double_t  zMiddle,
Int_t  orient = 1,
Double_t  tubeR = 500.0,
Double_t  xy = 0.0,
Double_t  z = 0.0,
Double_t  L = 0.0 
)

Define a Bell field.

Parameters
[in]nameThe name of the field
[in]BPeakThe peak B field magnitude (Tesla)
[in]zMiddleThe middle z global position of the magnet (cm)
[in]orientOrientation flag: 1 => Bx = 0 (default), 0 => By = 0
[in]tubeRThe largest inner radius of the tube ellipse (cm); default = 500 cm
[in]xyOptional target xy radius region (cm)
[in]zOptional target start z global position (cm)
[in]LOptional target region length (cm)

Definition at line 358 of file ShipFieldMaker.cxx.

360{
361
362 if (!this->gotField(name)) {
363
364 ShipBellField* theField = new ShipBellField(name.Data(), BPeak*Tesla_, zMiddle, orient, tubeR);
365
366 // Set additional parameters if we have a non-zero target length
367 if (fabs(L) > 0.0) {
368 theField->IncludeTarget(xy, z, L);
369 }
370
371 theFields_[name] = theField;
372
373 } else {
374
375 if (verbose_) {
376 std::cout<<"We already have a Bell field with the name "
377 <<name.Data()<<std::endl;
378 }
379 }
380}
void IncludeTarget(Double_t xy, Double_t z, Double_t l)
Bool_t gotField(const TString &name) const
Check if we have a field stored with the given name name.

◆ defineComposite() [1/3]

void ShipFieldMaker::defineComposite ( const stringVect inputLine)
protected

Define a composite field based on information from the inputLine.

Parameters
[in]inputLineThe space separated input line

Definition at line 557 of file ShipFieldMaker.cxx.

558{
559
560 size_t nWords = inputLine.size();
561
562 // Expecting a line such as:
563 // Composite Name Field1 Field2 ... FieldN
564
565 if (nWords > 2) {
566
567 TString name(inputLine[1].c_str());
568
569 std::vector<TString> fieldNames;
570 for (size_t i = 2; i < nWords; i++) {
571
572 TString aName(inputLine[i].c_str());
573 fieldNames.push_back(aName);
574
575 }
576
577 this->defineComposite(name, fieldNames);
578
579 } else {
580
581 std::cout<<"Expecting at least 3 words for the composite definition: "
582 <<"Composite Name Field1 Field2 ... FieldN"<<std::endl;
583
584 }
585
586}
void defineComposite(const TString &name, const TString &field1Name, const TString &field2Name, const TString &field3Name="", const TString &field4Name="")
Define a composite field from up to four fields.
int i
Definition ShipAna.py:86

◆ defineComposite() [2/3]

void ShipFieldMaker::defineComposite ( const TString &  name,
const TString &  field1Name,
const TString &  field2Name,
const TString &  field3Name = "",
const TString &  field4Name = "" 
)

Define a composite field from up to four fields.

Parameters
[in]nameThe name of the composite field
[in]field1NameThe name of the first field
[in]field2NameThe name of the second field
[in]field3NameThe name of the third field (optional)
[in]field4NameThe name of the fourth field (optional)

Definition at line 588 of file ShipFieldMaker.cxx.

591{
592
593 std::vector<TString> fieldNames;
594 fieldNames.push_back(field1Name);
595 fieldNames.push_back(field2Name);
596
597 if (field3Name.Length() > 0) {
598 fieldNames.push_back(field3Name);
599 }
600 if (field4Name.Length() > 0) {
601 fieldNames.push_back(field4Name);
602 }
603
604 this->defineComposite(name, fieldNames);
605
606}

◆ defineComposite() [3/3]

void ShipFieldMaker::defineComposite ( const TString &  name,
std::vector< TString >  fieldNames 
)

Define a composite field from a vector of field names.

Parameters
[in]nameThe name of the composite field
[in]fieldNamesVector of all of the field names to be combined

Definition at line 608 of file ShipFieldMaker.cxx.

609{
610
611 // Check if the field is already in the map
612 if (!this->gotField(name)) {
613
614 // Loop over the list of fields and add them to the composite
615 std::vector<TVirtualMagField*> vectFields;
616
617 std::vector<TString>::iterator iter;
618 for (iter = fieldNames.begin(); iter != fieldNames.end(); ++iter) {
619
620 TString aName = *iter;
621 TVirtualMagField* aField = this->getField(aName);
622 if (aField) {
623 if (verbose_) {std::cout<<"Adding field "<<aName<<std::endl;}
624 vectFields.push_back(aField);
625 }
626
627 ShipCompField* composite = new ShipCompField(name.Data(), vectFields);
628 theFields_[name] = composite;
629
630 }
631
632 } else {
633
634 std::cout<<"We already have a composite field with the name "
635 <<name.Data()<<std::endl;
636 }
637
638}
Class that defines a magnetic field composed from many fields.

◆ defineConstant() [1/2]

void ShipFieldMaker::defineConstant ( const stringVect inputLine)
protected

Define a constant field based on information from the inputLine.

Parameters
[in]inputLineThe space separated input line

Definition at line 247 of file ShipFieldMaker.cxx.

248{
249
250 size_t nWords = inputLine.size();
251
252 // Expecting a line such as:
253 // Constant Name xMin xMax yMin yMax zMin zMax Bx By Bz
254
255 if (nWords == 11) {
256
257 TString name(inputLine[1].c_str());
258
259 Double_t xMin = std::atof(inputLine[2].c_str());
260 Double_t xMax = std::atof(inputLine[3].c_str());
261
262 Double_t yMin = std::atof(inputLine[4].c_str());
263 Double_t yMax = std::atof(inputLine[5].c_str());
264
265 Double_t zMin = std::atof(inputLine[6].c_str());
266 Double_t zMax = std::atof(inputLine[7].c_str());
267
268 // Input field in Tesla_, interface needs kGauss units
269 Double_t Bx = std::atof(inputLine[8].c_str());
270 Double_t By = std::atof(inputLine[9].c_str());
271 Double_t Bz = std::atof(inputLine[10].c_str());
272
273 const TVector2 xRange(xMin, xMax);
274 const TVector2 yRange(yMin, yMax);
275 const TVector2 zRange(zMin, zMax);
276 const TVector3 BVector(Bx, By, Bz);
277
278 this->defineConstant(name, xRange, yRange, zRange, BVector);
279
280 } else {
281
282 std::cout<<"Expecting 11 words for the definition of the constant field: "
283 <<"Constant Name xMin xMax yMin yMax zMin zMax Bx By Bz"<<std::endl;
284
285 }
286
287}
void defineConstant(const TString &name, const TVector2 &xRange, const TVector2 &yRange, const TVector2 &zRange, const TVector3 &BVector)
Define a constant field.

◆ defineConstant() [2/2]

void ShipFieldMaker::defineConstant ( const TString &  name,
const TVector2 &  xRange,
const TVector2 &  yRange,
const TVector2 &  zRange,
const TVector3 &  BVector 
)

Define a constant field.

Parameters
[in]nameThe name of the field
[in]xRangeThe x range as a TVector2(xMin, xMax)
[in]yRangeThe y range as a TVector2(yMin, yMax)
[in]zRangeThe z range as a TVector2(zMin, zMax)
[in]BVectorThe vector of B field components (Bx, By, Bz) in Tesla

Definition at line 289 of file ShipFieldMaker.cxx.

291{
292
293 // Check if the field is already in the map
294 if (!this->gotField(name)) {
295
296 Double_t xMin = xRange.X();
297 Double_t xMax = xRange.Y();
298 Double_t yMin = yRange.X();
299 Double_t yMax = yRange.Y();
300 Double_t zMin = zRange.X();
301 Double_t zMax = zRange.Y();
302
303 Double_t Bx = BVector.X()*Tesla_;
304 Double_t By = BVector.Y()*Tesla_;
305 Double_t Bz = BVector.Z()*Tesla_;
306
307 ShipConstField* theField = new ShipConstField(name.Data(), xMin, xMax, yMin, yMax,
308 zMin, zMax, Bx, By, Bz);
309 theFields_[name] = theField;
310
311 } else {
312
313 if (verbose_) {
314 std::cout<<"We already have a constant field with the name "
315 <<name.Data()<<std::endl;
316 }
317 }
318}

◆ defineFieldMap() [1/2]

void ShipFieldMaker::defineFieldMap ( const stringVect inputLine,
Bool_t  useSymmetry = kFALSE 
)
protected

Define a field map based on information from the inputLine.

Parameters
[in]inputLineThe space separated input line
[in]useSymmetryBoolean to specify if we have x-y quadrant symmetry

Definition at line 383 of file ShipFieldMaker.cxx.

384{
385
386 size_t nWords = inputLine.size();
387
388 // Expecting the line:
389 // FieldMap Name mapFileName [x0 y0 z0] [phi theta psi]
390
391 if (nWords == 3 || nWords == 6 || nWords == 9) {
392
393 const TString name(inputLine[1].c_str());
394 const TString mapFileName(inputLine[2].c_str());
395
396 Double_t x0(0.0), y0(0.0), z0(0.0);
397 Double_t phi(0.0), theta(0.0), psi(0.0);
398
399 if (nWords > 5) {
400 x0 = std::atof(inputLine[3].c_str());
401 y0 = std::atof(inputLine[4].c_str());
402 z0 = std::atof(inputLine[5].c_str());
403 }
404
405 if (nWords == 9) {
406 phi = std::atof(inputLine[6].c_str());
407 theta = std::atof(inputLine[7].c_str());
408 psi = std::atof(inputLine[8].c_str());
409 }
410
411 const TVector3 localCentre(x0, y0, z0);
412 const TVector3 localAngles(phi, theta, psi);
413
414 this->defineFieldMap(name, mapFileName, localCentre, localAngles, useSymmetry);
415
416 } else {
417
418 std::cout<<"Expecting 3, 6 or 9 words for the definition of the field map: "
419 <<"(Sym)FieldMap Name mapFileName [x0 y0 z0] [[phi theta psi]]"<<std::endl;
420
421 }
422}
void defineFieldMap(const TString &name, const TString &mapFileName, const TVector3 &localCentre=TVector3(0.0, 0.0, 0.0), const TVector3 &localAngles=TVector3(0.0, 0.0, 0.0), Bool_t useSymmetry=kFALSE)

◆ defineFieldMap() [2/2]

void ShipFieldMaker::defineFieldMap ( const TString &  name,
const TString &  mapFileName,
const TVector3 &  localCentre = TVector3(0.0, 0.0, 0.0),
const TVector3 &  localAngles = TVector3(0.0, 0.0, 0.0),
Bool_t  useSymmetry = kFALSE 
)
Parameters
[in]nameThe name of the field
[in]mapFileNameThe location of the field map ROOT file relative to VMCWORKDIR
[in]localCentreThe TVector3(x,y,z) offset shift applied to all field map coordinates
[in]localAnglesThe TVector3(phi, theta, psi) Euler rotation applied to all map coords
[in]useSymmetryBoolean to specify if the map has quadrant symmetry (default = false)

Definition at line 424 of file ShipFieldMaker.cxx.

427{
428 // Check if the field is already in the map
429 if (!this->gotField(name)) {
430
431 // Add the VMCWORKDIR prefix to this map file location
432 std::string fullFileName = getenv("VMCWORKDIR");
433 fullFileName += "/"; fullFileName += mapFileName.Data();
434
435 if (verbose_) {
436 if (useSymmetry) {
437 std::cout<<"Creating symmetric field map called "<<name.Data()<<" using "<<fullFileName<<std::endl;
438 } else {
439 std::cout<<"Creating field map called "<<name.Data()<<" using "<<fullFileName<<std::endl;
440 }
441 }
442
443 // Since field maps use floating point precision we convert any double parameter
444 // values to floats, i.e. we can't simply pass TVector3 objects
445 Float_t x0 = localCentre.X();
446 Float_t y0 = localCentre.Y();
447 Float_t z0 = localCentre.Z();
448
449 Float_t phi = localAngles.X();
450 Float_t theta = localAngles.Y();
451 Float_t psi = localAngles.Z();
452
453 Float_t scale(1.0);
454
455 ShipBFieldMap* mapField = new ShipBFieldMap(name.Data(), fullFileName, x0, y0, z0,
456 phi, theta, psi, scale, useSymmetry);
457 theFields_[name] = mapField;
458
459 } else {
460
461 if (verbose_) {
462 std::cout<<"We already have a field map with the name "
463 <<name.Data()<<std::endl;
464 }
465
466 }
467
468}

◆ defineFieldMapCopy() [1/2]

void ShipFieldMaker::defineFieldMapCopy ( const stringVect inputLine)
protected

Define a (translated) copy of a field map based on information from the inputLine.

Parameters
[in]inputLineThe space separated input line

Definition at line 470 of file ShipFieldMaker.cxx.

471{
472
473 // Define a (translated) copy of a field map based in the input file line
474
475 size_t nWords = inputLine.size();
476
477 // Expecting the line:
478 // CopyMap Name MapNameToCopy x0 y0 z0 [phi theta psi]
479
480 if (nWords == 6 || nWords == 9) {
481
482 const TString name(inputLine[1].c_str());
483
484 // We want to try to copy and transpose an already existing field map
485 const TString mapNameToCopy(inputLine[2].c_str());
486
487 Double_t x0 = std::atof(inputLine[3].c_str());
488 Double_t y0 = std::atof(inputLine[4].c_str());
489 Double_t z0 = std::atof(inputLine[5].c_str());
490
491 Double_t phi(0.0), theta(0.0), psi(0.0), scale(1.0);
492
493 if (nWords == 9) {
494 phi = std::atof(inputLine[6].c_str());
495 theta = std::atof(inputLine[7].c_str());
496 psi = std::atof(inputLine[8].c_str());
497 }
498
499 const TVector3 translation(x0, y0, z0);
500 const TVector3 eulerAngles(phi, theta, psi);
501
502 this->defineFieldMapCopy(name, mapNameToCopy, translation, eulerAngles);
503
504 } else {
505
506 std::cout<<"Expecting 6 or 9 words for the copy of a field map: "
507 <<"CopyMap Name MapNameToCopy x0 y0 z0 [phi theta psi]"<<std::endl;
508
509 }
510
511}
void defineFieldMapCopy(const TString &name, const TString &mapNameToCopy, const TVector3 &translation, const TVector3 &eulerAngles=TVector3(0.0, 0.0, 0.0))
Define a copy of a field map with a coordinate translation and optional rotation.

◆ defineFieldMapCopy() [2/2]

void ShipFieldMaker::defineFieldMapCopy ( const TString &  name,
const TString &  mapNameToCopy,
const TVector3 &  translation,
const TVector3 &  eulerAngles = TVector3(0.0, 0.0, 0.0) 
)

Define a copy of a field map with a coordinate translation and optional rotation.

Parameters
[in]nameThe name of the field
[in]mapNameToCopyThe name of the field map that is to be copied
[in]translationThe TVector3(x,y,z) coordinate translation
[in]eulerAnglesThe TVector3(phi, theta, psi) Euler angle rotation

Definition at line 513 of file ShipFieldMaker.cxx.

515{
516
517 // Check if the field is already in the map
518 if (!this->gotField(name)) {
519
520 ShipBFieldMap* fieldToCopy =
521 dynamic_cast<ShipBFieldMap*>(this->getField(mapNameToCopy));
522
523 if (fieldToCopy) {
524
525 if (verbose_) {
526 std::cout<<"Creating map field copy "<<name.Data()
527 <<" based on "<<mapNameToCopy.Data()<<std::endl;
528 }
529
530 // Since field maps use floating point precision we convert any double parameter
531 // values to floats, i.e. we can't simply pass TVector3 objects
532 Float_t x0 = translation.X();
533 Float_t y0 = translation.Y();
534 Float_t z0 = translation.Z();
535
536 Float_t phi = eulerAngles.X();
537 Float_t theta = eulerAngles.Y();
538 Float_t psi = eulerAngles.Z();
539
540 Float_t scale(1.0);
541
542 ShipBFieldMap* copiedMap = new ShipBFieldMap(name.Data(), *fieldToCopy,
543 x0, y0, z0, phi, theta, psi, scale);
544 theFields_[name] = copiedMap;
545
546 }
547
548 } else {
549
550 std::cout<<"We already have a copied field map with the name "
551 <<name.Data()<<std::endl;
552 }
553
554}

◆ defineGlobalField() [1/3]

void ShipFieldMaker::defineGlobalField ( const stringVect inputLine)
protected

Define the global field based on information from the inputLine.

Parameters
[in]inputLineThe space separated input line

Definition at line 640 of file ShipFieldMaker.cxx.

641{
642
643 // Define the global field using the input file line
644
645 size_t nWords = inputLine.size();
646
647 // Expecting the line:
648 // Global Field1 ... FieldN
649
650 if (nWords > 1) {
651
652 TString name("Global");
653
654 std::vector<TString> fieldNames;
655 for (size_t i = 1; i < nWords; i++) {
656
657 TString aName(inputLine[i].c_str());
658 fieldNames.push_back(aName);
659
660 }
661
662 this->defineGlobalField(fieldNames);
663
664 } else {
665
666 std::cout<<"Expecting at least two words for the global field definition: "
667 <<"Global Field1 ... FieldN"<<std::endl;
668
669 }
670
671}
void defineGlobalField(const TString &field1Name, const TString &field2Name="", const TString &field3Name="", const TString &field4Name="")
Define a composite field from up to four fields.

◆ defineGlobalField() [2/3]

void ShipFieldMaker::defineGlobalField ( const TString &  field1Name,
const TString &  field2Name = "",
const TString &  field3Name = "",
const TString &  field4Name = "" 
)

Define a composite field from up to four fields.

Parameters
[in]field1NameThe name of the first field
[in]field2NameThe name of the second field (optional)
[in]field3NameThe name of the third field (optional)
[in]field4NameThe name of the fourth field (optional)

Definition at line 673 of file ShipFieldMaker.cxx.

675{
676
677 std::vector<TString> fieldNames;
678 fieldNames.push_back(field1Name);
679
680 if (field2Name.Length() > 0) {
681 fieldNames.push_back(field2Name);
682 }
683 if (field3Name.Length() > 0) {
684 fieldNames.push_back(field3Name);
685 }
686 if (field4Name.Length() > 0) {
687 fieldNames.push_back(field4Name);
688 }
689
690 this->defineGlobalField(fieldNames);
691
692}

◆ defineGlobalField() [3/3]

void ShipFieldMaker::defineGlobalField ( std::vector< TString >  fieldNames)

Define the Global field using a vector of field names.

Parameters
[in]fieldNamesVector of all of the field names to be combined

Definition at line 694 of file ShipFieldMaker.cxx.

695{
696
697 if (globalField_) {
698 if (verbose_) {
699 std::cout<<"Deleting already existing Global field"<<std::endl;
700 }
701 delete globalField_;
702 }
703
704 if (verbose_) {std::cout<<"Setting the Global field"<<std::endl;}
705
706 std::vector<TVirtualMagField*> vectFields;
707
708 std::vector<TString>::iterator iter;
709 for (iter = fieldNames.begin(); iter != fieldNames.end(); ++iter) {
710
711 TString aName = *iter;
712 TVirtualMagField* aField = this->getField(aName);
713
714 if (aField) {
715 if (verbose_) {std::cout<<"Adding field "<<aName<<" to Global"<<std::endl;}
716 vectFields.push_back(aField);
717 } else {
718 std::cout<<"Could not find the field "<<aName<<std::endl;
719 }
720
721 }
722
723 TString name("Global");
724 globalField_ = new ShipCompField(name.Data(), vectFields);
725
726 // Set this as the global field in the virtual MC
727 if (gMC) {
728 gMC->SetMagField(globalField_);
729 } else {
730 std::cout<<"The virtual MC pointer gMC is null! The global field can't be used by Geant4 but will work for track fitting and track extrapolation"<<std::endl;
731 }
732
733}

◆ defineLocalField() [1/2]

void ShipFieldMaker::defineLocalField ( const stringVect inputLine)
protected

Define a local field only based on information from the inputLine.

Parameters
[in]inputLineThe space separated input line

Definition at line 865 of file ShipFieldMaker.cxx.

866{
867
868 // Set only the local field for the region using info from inputLine
869 size_t nWords = inputLine.size();
870
871 // Expecting the line:
872 // Local VolName FieldName [FieldMapScaleFactor]
873
874 if (nWords == 3 || nWords == 4) {
875
876 TString volName(inputLine[1].c_str());
877 TString fieldName(inputLine[2].c_str());
878
879 Double_t scale(1.0);
880 if (nWords == 4) {scale = std::atof(inputLine[3].c_str());}
881
882 this->defineLocalField(volName, fieldName, scale);
883
884 } else {
885
886 std::cout<<"Expecting 3 or 4 words for the local field definition: "
887 <<"Local VolName LocalFieldName [FieldMapScale]"<<std::endl;
888
889 }
890
891}
void defineLocalField(const TString &volName, const TString &fieldName, Double_t scale=1.0)
Define a localised field and volume pairing.

◆ defineLocalField() [2/2]

void ShipFieldMaker::defineLocalField ( const TString &  volName,
const TString &  fieldName,
Double_t  scale = 1.0 
)

Define a localised field and volume pairing.

Parameters
[in]volNameThe name of the volume
[in]fieldNameThe name of the local field for the volume
[in]scaleOptional scale factor for field maps (default = 1.0)

Definition at line 893 of file ShipFieldMaker.cxx.

894{
895
896 if (verbose_) {
897 std::cout<<"ShipFieldMaker::defineLocalField for volume "
898 <<volName.Data()<<" and field "<<fieldName.Data()
899 <<" with scale = "<<scale<<std::endl;
900 }
901
902 fieldInfo theInfo(volName, fieldName,scale);
903 localInfo_.push_back(theInfo);
904
905}

◆ defineRegionField() [1/2]

void ShipFieldMaker::defineRegionField ( const stringVect inputLine)
protected

Define a regional (local+global) field based on the info from the inputLine.

Parameters
[in]inputLineThe space separated input line

Definition at line 735 of file ShipFieldMaker.cxx.

736{
737
738 // Set the local + global field for the region using info from inputLine
739 size_t nWords = inputLine.size();
740
741 // Expecting the line:
742 // Region VolName FieldName [FieldMapScaleFactor]
743
744 if (nWords == 3 || nWords == 4) {
745
746 TString volName(inputLine[1].c_str());
747 TString fieldName(inputLine[2].c_str());
748
749 Double_t scale(1.0);
750 if (nWords == 4) {scale = std::atof(inputLine[3].c_str());}
751
752 this->defineRegionField(volName, fieldName, scale);
753
754 } else {
755
756 std::cout<<"Expecting 3 or 4 words for the region (local + global) field definition: "
757 <<"Region VolName LocalFieldName [LocalFieldMapScale]"<<std::endl;
758
759 }
760
761}
void defineRegionField(const TString &volName, const TString &fieldName, Double_t scale=1.0)
Define a regional (local + global) field and volume pairing.

◆ defineRegionField() [2/2]

void ShipFieldMaker::defineRegionField ( const TString &  volName,
const TString &  fieldName,
Double_t  scale = 1.0 
)

Define a regional (local + global) field and volume pairing.

Parameters
[in]volNameThe name of the volume
[in]fieldNameThe name of the field for the volume
[in]scaleOptional scale factor for field maps (default = 1.0)

Definition at line 763 of file ShipFieldMaker.cxx.

764{
765
766 if (verbose_) {
767 std::cout<<"ShipFieldMaker::defineRegionField for volume "
768 <<volName.Data()<<" and field "<<fieldName.Data()
769 <<" with scale = "<<scale<<std::endl;
770 }
771
772 fieldInfo theInfo(volName, fieldName, scale);
773 regionInfo_.push_back(theInfo);
774
775}

◆ defineUniform() [1/2]

void ShipFieldMaker::defineUniform ( const stringVect inputLine)
protected

Define a uniform field based on information from the inputLine.

Parameters
[in]inputLineThe space separated input line

Definition at line 194 of file ShipFieldMaker.cxx.

195{
196
197 size_t nWords = inputLine.size();
198
199 // Expecting a line such as:
200 // Uniform Name Bx By Bz
201
202 if (nWords == 5) {
203
204 const TString name(inputLine[1].c_str());
205
206 Double_t Bx = std::atof(inputLine[2].c_str());
207 Double_t By = std::atof(inputLine[3].c_str());
208 Double_t Bz = std::atof(inputLine[4].c_str());
209 const TVector3 BVector(Bx, By, Bz);
210
211 this->defineUniform(name, BVector);
212
213 } else {
214
215 std::cout<<"Expecting 5 words for the definition of the uniform field: "
216 <<"Uniform Name Bx By Bz"<<std::endl;
217
218 }
219
220}
void defineUniform(const TString &name, const TVector3 &BVector)
Define a uniform field.

◆ defineUniform() [2/2]

void ShipFieldMaker::defineUniform ( const TString &  name,
const TVector3 &  BVector 
)

Define a uniform field.

Parameters
[in]nameThe name of the field
[in]BVectorThe vector of B field components (Bx, By, Bz) in Tesla

Definition at line 222 of file ShipFieldMaker.cxx.

223{
224
225 // Check if the field is already in the map
226 if (!this->gotField(name)) {
227
228 if (verbose_) {std::cout<<"Creating uniform field for "<<name.Data()<<std::endl;}
229
230 Double_t Bx = BVector.X()*Tesla_;
231 Double_t By = BVector.Y()*Tesla_;
232 Double_t Bz = BVector.Z()*Tesla_;
233
234 TGeoUniformMagField* uField = new TGeoUniformMagField(Bx, By, Bz);
235 theFields_[name] = uField;
236
237 } else {
238
239 if (verbose_) {
240 std::cout<<"We already have a uniform field with the name "
241 <<name.Data()<<std::endl;
242 }
243 }
244}

◆ findNode()

void ShipFieldMaker::findNode ( TGeoVolume *  aVolume,
const TString &  volName 
)
protected

Update the current geometry node pointer that matches the required volume name.

Parameters
[in]aVolumeThe current volume, whose nodes are looked at
[in]volNameThe required volume name we want to find

Definition at line 1115 of file ShipFieldMaker.cxx.

1115 {
1116
1117 // Find the geometry node that matches the required volume name
1118
1119 // Immediately exit the function if we have already found the volume
1120 if (gotNode_) {return;}
1121
1122 if (aVolume) {
1123
1124 TObjArray* volNodes = aVolume->GetNodes();
1125
1126 if (volNodes) {
1127
1128 // Loop over the geometry nodes
1129 int nNodes = volNodes->GetEntries();
1130 for (int i = 0; i < nNodes; i++) {
1131
1132 TGeoNode* node = dynamic_cast<TGeoNode*>(volNodes->At(i));
1133
1134 if (node) {
1135
1136 const TString nodeName(node->GetName());
1137 if (!nodeName.CompareTo(volName, TString::kExact)) {
1138
1139 // We have a match. The node has the transformation we need
1140 theNode_ = node;
1141 gotNode_ = kTRUE;
1142 break;
1143
1144 } else if (node->GetNodes()) {
1145
1146 // We have sub-volumes. Recursively call this function
1147 this->findNode(node->GetVolume(), volName);
1148
1149 }
1150
1151 }
1152
1153 }
1154
1155 }
1156
1157 }
1158
1159}
void findNode(TGeoVolume *aVolume, const TString &volName)
Update the current geometry node pointer that matches the required volume name.

◆ generateFieldMap()

void ShipFieldMaker::generateFieldMap ( TString  fileName,
const float  step = 2.5,
const float  xRange = 179,
const float  yRange = 317,
const float  zRange = 1515.5,
const float  zShift = -4996 
)

Definition at line 1383 of file ShipFieldMaker.cxx.

1383 {
1384 std::ofstream myfile;
1385 myfile.open (fileName);
1386 int xSteps = ceil(xRange/step) + 1; //field map has X range from 0 to xMax
1387 int ySteps = ceil(yRange/step) + 1; //from 0 up to yMax
1388 int zSteps = ceil(zRange*2./step) + 1;//from -zMax up to zMax
1389 Double_t position[3] = {0.0, 0.0, 0.0};
1390 myfile<<xSteps<<" "<<ySteps<<" "<<zSteps<<" "<<step<<" "<<xRange<<" "<<yRange<<" "<<zRange<<std::endl;
1391 for (int i =0 ; i < xSteps; i++){
1392 for (int k=0; k<ySteps;k++){
1393 for (int m=0; m<zSteps; m++){
1394 Double_t B[3] = {0.0, 0.0, 0.0};
1395 Double_t x = step*i;
1396 Double_t y = step * k;
1397 Double_t z = m * step - zRange + zShift;
1398 position[0] = x;
1399 position[1] = y;
1400 position[2] = z;
1401 Bool_t inside(kFALSE);
1402 TGeoNode* theNode = gGeoManager->FindNode(position[0], position[1], position[2]);
1403 if (theNode) {
1404 TGeoVolume* theVol = theNode->GetVolume();
1405 if (theVol) {
1406 TVirtualMagField* theField = dynamic_cast<TVirtualMagField*>(theVol->GetField());
1407 if (theField) {
1408 theField->Field(position, B);
1409 inside = kTRUE;
1410 }
1411 }
1412 }
1413 if (inside == kFALSE && globalField_) {
1414 globalField_->Field(position, B);
1415 }
1416 myfile<<x<<" "<<y<<" "<<z<<" "<<B[0]/Tesla_<<" "<<B[1]/Tesla_<<" "<<B[2]/Tesla_<<std::endl;
1417 }
1418 }
1419 }
1420 myfile.close();
1421}
Double_t m
virtual void Field(const Double_t *position, Double_t *B)
The total magnetic field from all of the composite sources (linear superposition)

◆ getAllFields()

SFMap ShipFieldMaker::getAllFields ( ) const
inline

Get the map storing volume names and their associated local magnetic fields.

Returns
the map of volume names and their corresponding magnetic field pointers

Definition at line 201 of file ShipFieldMaker.h.

201{return theFields_;}

◆ getField()

TVirtualMagField * ShipFieldMaker::getField ( const TString &  name) const

Get the field stored with the given name name.

Parameters
[in]nameThe name of the field
Returns
the pointer to the magnetic field object

Definition at line 1201 of file ShipFieldMaker.cxx.

1202{
1203
1204 TVirtualMagField* theField(0);
1205
1206 // Iterate over the internal map and see if we have a match
1207 SFMap::const_iterator iter;
1208 for (iter = theFields_.begin(); iter != theFields_.end(); ++iter) {
1209
1210 TString key = iter->first;
1211 TVirtualMagField* BField = iter->second;
1212
1213 // Check that we have the key already stored
1214 if (!key.CompareTo(name, TString::kExact)) {
1215 theField = BField;
1216 break;
1217 }
1218
1219 }
1220
1221 return theField;
1222
1223}

◆ getGlobalField()

ShipCompField * ShipFieldMaker::getGlobalField ( ) const
inline

Get the global magnetic field.

Returns
the global magnetic field pointer

Definition at line 195 of file ShipFieldMaker.h.

195{return globalField_;}

◆ getTransformation()

void ShipFieldMaker::getTransformation ( const TString &  volName,
transformInfo theInfo 
)
protected

Get the transformation matrix for the volume position and orientation.

Parameters
[in]volNameThe name of the volume
[in]theInfoThe transformation information structure

Definition at line 1057 of file ShipFieldMaker.cxx.

1057 {
1058
1059 // Find the geometry node that matches the volume name. We need to search
1060 // the geometry hierarchy recursively until we get a match. Note that nodes
1061 // have "_1" appended to the volume name.
1062
1063 theInfo.x0_ = 0.0; theInfo.y0_ = 0.0; theInfo.z0_ = 0.0;
1064 theInfo.phi_ = 0.0; theInfo.theta_ = 0.0; theInfo.psi_ = 0.0;
1065
1066 TGeoMatrix* theMatrix(0);
1067
1068 TGeoVolume* topVolume = gGeoManager->GetTopVolume();
1069 if (!topVolume) {
1070 std::cout<<"Can't find the top volume in ShipFieldMaker::getTransformation"<<std::endl;
1071 return;
1072 }
1073
1074 if (verbose_) {std::cout<<"Finding transformation for "<<volName<<std::endl;}
1075
1076 // Find the geometry node that matches the required name
1077 theNode_ = 0;
1078 gotNode_ = kFALSE;
1079 this->findNode(topVolume, volName);
1080
1081 if (theNode_) {theMatrix = theNode_->GetMatrix();}
1082
1083 // Retrieve the translation and rotation information
1084 if (theMatrix) {
1085
1086 // Translation displacement components
1087 const Double_t* theTrans = theMatrix->GetTranslation();
1088 theInfo.x0_ = theTrans[0];
1089 theInfo.y0_ = theTrans[1];
1090 theInfo.z0_ = theTrans[2];
1091
1092 // Euler rotation angles. First check if we have a combined translation
1093 // and rotation, then check if we just have a pure rotation
1094 if (theMatrix->IsCombi()) {
1095
1096 TGeoCombiTrans* theCombi = dynamic_cast<TGeoCombiTrans*>(theMatrix);
1097 if (theCombi) {
1098 TGeoRotation* combRotn = theCombi->GetRotation();
1099 if (combRotn) {
1100 combRotn->GetAngles(theInfo.phi_, theInfo.theta_, theInfo.psi_);
1101 }
1102 }
1103
1104 } else if (theMatrix->IsRotation()) {
1105
1106 TGeoRotation* theRotn = dynamic_cast<TGeoRotation*>(theMatrix);
1107 if (theRotn) {
1108 theRotn->GetAngles(theInfo.phi_, theInfo.theta_, theInfo.psi_);
1109 }
1110 }
1111 }
1112
1113}

◆ getVolumeField()

TVirtualMagField * ShipFieldMaker::getVolumeField ( const TString &  volName) const

Get the magnetic field for the given volume.

Parameters
[in]volNameThe name of the TGeo volume
Returns
the pointer of the local magnetic field for the volume

Definition at line 1161 of file ShipFieldMaker.cxx.

1162{
1163
1164 TVirtualMagField* theField(0);
1165 TGeoVolume* theVol(0);
1166 if (gGeoManager) {theVol = gGeoManager->FindVolumeFast(volName.Data());}
1167
1168 if (theVol) {
1169 // Need to cast the TObject* to a TVirtualMagField*
1170 theField = dynamic_cast<TVirtualMagField*>(theVol->GetField());
1171 }
1172
1173 return theField;
1174
1175}

◆ gotField()

Bool_t ShipFieldMaker::gotField ( const TString &  name) const

Check if we have a field stored with the given name name.

Parameters
[in]nameThe name of the field
Returns
a boolean to say if we already have the field stored in the internal map

Definition at line 1177 of file ShipFieldMaker.cxx.

1178{
1179
1180 Bool_t result(kFALSE);
1181
1182 // Iterate over the internal map and see if we have a match
1183 SFMap::const_iterator iter;
1184 for (iter = theFields_.begin(); iter != theFields_.end(); ++iter) {
1185
1186 TString key = iter->first;
1187 TVirtualMagField* theField = iter->second;
1188
1189 // Check that we have the key already stored and the pointer is not null
1190 if (!key.CompareTo(name, TString::kExact) && theField) {
1191 result = kTRUE;
1192 break;
1193 }
1194
1195 }
1196
1197 return result;
1198
1199}

◆ plotField()

void ShipFieldMaker::plotField ( Int_t  type,
const TVector3 &  xAxis,
const TVector3 &  yAxis,
const std::string &  plotFile 
) const

Plot the magnetic field in "x-y" plane.

Parameters
[in]typeThe co-ordinate type: 0 = x-y, 1 = z-x and 2 = z-y
[in]xAxisThree vector specifying the min, max and bin width of the x axis
[in]yAxisThree vector specifying the min, max and bin width of the y axis
[in]plotFileThe name of the output file containing the plot of the magnetic field

Definition at line 1243 of file ShipFieldMaker.cxx.

1245{
1246
1247 std::cout<<"ShipFieldMaker plotField "<<plotFile<<": type = "<<type<<std::endl;
1248
1249 Double_t xMin = xAxis(0);
1250 Double_t xMax = xAxis(1);
1251 Double_t dx = xAxis(2);
1252 Int_t Nx(0);
1253 if (dx > 0.0) {Nx = static_cast<Int_t>(((xMax - xMin)/dx) + 0.5);}
1254
1255 Double_t yMin = yAxis(0);
1256 Double_t yMax = yAxis(1);
1257 Double_t dy = yAxis(2);
1258 Int_t Ny(0);
1259 if (dy > 0.0) {Ny = static_cast<Int_t>(((yMax - yMin)/dy) + 0.5);}
1260
1261 // Create a 2d histogram
1262 const int nhistograms = 4; //x,y,z,and magnitude
1263 const int ncoordinates = 3; //x,y,z
1264
1265 TH2D theHist[nhistograms];
1266 std::string titles[nhistograms] = {"Bx (T)","By (T)","Bz (T)","B (T)"};
1267 for (int icomponent = 0; icomponent< nhistograms; icomponent++){
1268 theHist[icomponent] = TH2D(Form("theHist[%i]",icomponent), titles[icomponent].data(), Nx, xMin, xMax, Ny, yMin, yMax);
1269 theHist[icomponent].SetDirectory(0);
1270 if (type == 0) {
1271 // x-y
1272 theHist[icomponent].SetXTitle("x (cm)");
1273 theHist[icomponent].SetYTitle("y (cm)");
1274 }
1275 else if (type == 1) {
1276 // z-x
1277 theHist[icomponent].SetXTitle("z (cm)");
1278 theHist[icomponent].SetYTitle("x (cm)");
1279 }
1280 else if (type == 2) {
1281 // z-y
1282 theHist[icomponent].SetXTitle("z (cm)");
1283 theHist[icomponent].SetYTitle("y (cm)");
1284 }
1285 }
1286 // Get list of volumes (to check for local fields)
1287 TObjArray* theVolumes = gGeoManager->GetListOfVolumes();
1288 Int_t nVol(0);
1289 if (theVolumes) {nVol = theVolumes->GetSize();}
1290
1291 // Loop over "x" axis
1292 for (Int_t ix = 0; ix < Nx; ix++) {
1293
1294 Double_t x = dx*ix + xMin;
1295
1296 // Loop over "y" axis
1297 for (Int_t iy = 0; iy < Ny; iy++) {
1298
1299 Double_t y = dy*iy + yMin;
1300
1301 // Initialise the B field array to zero
1302 Double_t B[ncoordinates] = {0.0, 0.0, 0.0};
1303
1304 // Initialise the position array to zero
1305 Double_t position[ncoordinates] = {0.0, 0.0, 0.0};
1306 if (type == 0) {
1307 // x-y
1308 position[0] = x, position[1] = y;
1309 } else if (type == 1) {
1310 // z-x
1311 position[0] = y, position[2] = x;
1312 } else if (type == 2) {
1313 // z-y
1314 position[1] = y; position[2] = x;
1315 }
1316
1317 // Find out if the point is inside one of the geometry volumes
1318 Bool_t inside(kFALSE);
1319
1320 // Find the geoemtry node (volume path)
1321 TGeoNode* theNode = gGeoManager->FindNode(position[0], position[1], position[2]);
1322
1323 if (theNode) {
1324
1325 // Get the volume
1326 TGeoVolume* theVol = theNode->GetVolume();
1327
1328 if (theVol) {
1329
1330 // Get the magnetic field
1331 TVirtualMagField* theField = dynamic_cast<TVirtualMagField*>(theVol->GetField());
1332
1333 if (theField) {
1334
1335 // Find the "local" field inside the volume (using global co-ords)
1336 theField->Field(position, B);
1337 inside = kTRUE;
1338
1339 } // theField
1340
1341 } // volume
1342
1343 } // node
1344
1345 // If no local volumes found, use global field if it exists
1346 if (inside == kFALSE && globalField_) {
1347 globalField_->Field(position, B);
1348 }
1349
1350 // Divide by the Tesla_ factor, since we want to plot Tesla_ not kGauss (VMC/FairRoot units)
1351 for (int icomponent = 0; icomponent<ncoordinates; icomponent++){
1352 theHist[icomponent].Fill(x,y, B[icomponent]/Tesla_);
1353 }
1354 Double_t BMag = sqrt(B[0]*B[0] + B[1]*B[1] + B[2]*B[2])/Tesla_;
1355 theHist[3].Fill(x, y, BMag);
1356
1357 } // "y" axis
1358
1359 } // "x" axis
1360
1361 Bool_t wasBatch = gROOT->IsBatch();
1362 // Disable pop-up windows
1363 gROOT->SetBatch(kTRUE);
1364 TCanvas theCanvas("theCanvas", "", 900, 700);
1365 gROOT->SetStyle("Plain");
1366 gStyle->SetOptStat(0);
1367 // Set colour style
1368 gStyle->SetPalette(kBird);
1369 theCanvas.UseCurrentStyle();
1370
1371 theCanvas.Divide(2,2);
1372 for (int icomponent = 0; icomponent < nhistograms; icomponent++){
1373 theCanvas.cd(icomponent+1);
1374 theHist[icomponent].Draw("colz");
1375 }
1376 theCanvas.Print(plotFile.c_str());
1377
1378 // Reset the batch boolean
1379 if (wasBatch == kFALSE) {gROOT->SetBatch(kFALSE);}
1380
1381}

◆ plotXYField()

void ShipFieldMaker::plotXYField ( const TVector3 &  xAxis,
const TVector3 &  yAxis,
const std::string &  plotFile 
) const

Plot the magnetic field in x-y plane.

Parameters
[in]xAxisThree vector specifying the min, max and bin width of the x axis
[in]yAxisThree vector specifying the min, max and bin width of the y axis
[in]plotFileThe name of the output file containing the plot of the magnetic field

Definition at line 1225 of file ShipFieldMaker.cxx.

1227{
1228 this->plotField(0, xAxis, yAxis, plotFile);
1229}
void plotField(Int_t type, const TVector3 &xAxis, const TVector3 &yAxis, const std::string &plotFile) const
Plot the magnetic field in "x-y" plane.

◆ plotZXField()

void ShipFieldMaker::plotZXField ( const TVector3 &  zAxis,
const TVector3 &  xAxis,
const std::string &  plotFile 
) const

Plot the magnetic field in z-x plane.

Parameters
[in]zAxisThree vector specifying the min, max and bin width of the z axis
[in]xAxisThree vector specifying the min, max and bin width of the x axis
[in]plotFileThe name of the output file containing the plot of the magnetic field

Definition at line 1231 of file ShipFieldMaker.cxx.

1233{
1234 this->plotField(1, zAxis, xAxis, plotFile);
1235}

◆ plotZYField()

void ShipFieldMaker::plotZYField ( const TVector3 &  zAxis,
const TVector3 &  yAxis,
const std::string &  plotFile 
) const

Plot the magnetic field in z-y plane.

Parameters
[in]zAxisThree vector specifying the min, max and bin width of the z axis
[in]yAxisThree vector specifying the min, max and bin width of the y axis
[in]plotFileThe name of the output file containing the plot of the magnetic field

Definition at line 1237 of file ShipFieldMaker.cxx.

1239{
1240 this->plotField(2, zAxis, yAxis, plotFile);
1241}

◆ readInputFile()

void ShipFieldMaker::readInputFile ( const std::string &  inputFile)

Read an input file to define fields and associated volumes.

Parameters
[in]inputFileThe input text file

Definition at line 74 of file ShipFieldMaker.cxx.

75{
76
77 // Check that we have a non-empty string
78 if (inputFile.size() < 1) {
79 std::cerr<<"Skipping ShipFieldMaker::readInputFile(): file name is empty"<<std::endl;
80 return;
81 }
82
83 std::string fullFileName = getenv("VMCWORKDIR");
84 fullFileName += "/"; fullFileName += inputFile.c_str();
85
86 std::cout<<"ShipFieldMaker::makeFields inputFile = "<<fullFileName<<std::endl;
87
88 std::ifstream getData(fullFileName);
89 std::string whiteSpace(" ");
90
91 // Loop while the input file is readable
92 while (getData.good()) {
93
94 if (getData.peek() == '\n') {
95
96 // Finish reading line
97 char c;
98 getData.get(c);
99
100 // Stop while loop if we have reached the end of the file
101 if (getData.eof()) {break;}
102
103 } else if (getData.peek() == '#') {
104
105 // Skip comment line
106 getData.ignore(1000, '\n');
107 getData.putback('\n');
108
109 // Stop while loop if we have reached the end of the file
110 if (getData.eof()) {break;}
111
112 } else {
113
114 // Read data line
115 std::string line("");
116 std::getline(getData, line);
117
118 // Stop while loop if we have reached the end of the file
119 if (getData.eof()) {break;}
120
121 // Split up the line according to white spaces
122 std::vector<std::string> lineVect = this->splitString(line, whiteSpace);
123
124 size_t nWords = lineVect.size();
125
126 // Check to see if we have at least one keyword at the start of the line
127 if (nWords > 1) {
128
129 TString keyWord(lineVect[0].c_str());
130 keyWord.ToLower();
131
132 if (!keyWord.CompareTo("uniform")) {
133
134 // Define the uniform magnetic field
135 this->defineUniform(lineVect);
136
137 } else if (!keyWord.CompareTo("constant")) {
138
139 // Define a uniform field with an x,y,z boundary
140 this->defineConstant(lineVect);
141
142 } else if (!keyWord.CompareTo("bell")) {
143
144 // Define the Bell-shaped field
145 this->defineBell(lineVect);
146
147 } else if (!keyWord.CompareTo("fieldmap")) {
148
149 // Define the field map
150 this->defineFieldMap(lineVect);
151
152 } else if (!keyWord.CompareTo("symfieldmap")) {
153
154 // Define the symmetric field map
155 this->defineFieldMap(lineVect, kTRUE);
156
157 } else if (!keyWord.CompareTo("copymap")) {
158
159 // Copy (& translate) the field map
160 this->defineFieldMapCopy(lineVect);
161
162 } else if (!keyWord.CompareTo("composite")) {
163
164 // Define the composite field
165 this->defineComposite(lineVect);
166
167 } else if (!keyWord.CompareTo("global")) {
168
169 // Define which fields are global
170 this->defineGlobalField(lineVect);
171
172 } else if (!keyWord.CompareTo("region")) {
173
174 // Define the local and global fields for the given volume
175 this->defineRegionField(lineVect);
176
177 } else if (!keyWord.CompareTo("local")) {
178
179 // Define the field for the given volume as the local one only
180 this->defineLocalField(lineVect);
181
182 }
183
184 }
185
186 }
187
188 }
189
190 getData.close();
191
192}
stringVect splitString(std::string &theString, std::string &splitter) const
Split a string.
c
Definition hnl.py:100

◆ setAllLocalFields()

void ShipFieldMaker::setAllLocalFields ( )
protected

Definition at line 907 of file ShipFieldMaker.cxx.

908{
909
910 // Loop over all entries in the localInfo_ vector and assign fields to their volumes
911 std::vector<fieldInfo>::iterator localIter;
912
913 for (localIter = localInfo_.begin(); localIter != localInfo_.end(); ++localIter) {
914
915 fieldInfo theInfo = *localIter;
916 const TString volName = theInfo.volName_;
917 TString fieldName = theInfo.fieldName_;
918 Double_t scale = theInfo.scale_;
919
920 TGeoVolume* theVol(0);
921 if (gGeoManager) {theVol = gGeoManager->FindVolumeFast(volName.Data());}
922
923 if (theVol) {
924
925 TVirtualMagField* localField = this->getField(fieldName);
926
927 if (localField) {
928
929 this->checkLocalFieldMap(localField, volName, scale);
930 theVol->SetField(localField);
931
932 if (verbose_) {
933 std::cout<<"Setting local field "<<localField->GetName()
934 <<" for volume "<<volName<<std::endl;
935 }
936
937 } else {
938
939 std::cout<<"Could not find the field "<<fieldName.Data()<<std::endl;
940 }
941
942 } else {
943
944 std::cout<<"Could not find the volume "<<volName.Data()<<std::endl;
945 }
946
947 } // localIter loop
948
949}
void checkLocalFieldMap(TVirtualMagField *&localField, const TString &volName, Double_t scale)
Check if we have a local field map and store the volume global transformation.

◆ setAllRegionFields()

void ShipFieldMaker::setAllRegionFields ( )
protected

Definition at line 777 of file ShipFieldMaker.cxx.

778{
779
780 // Loop over all entries in the regionInfo_ vector and assign fields to their volumes
781 std::vector<fieldInfo>::iterator regionIter;
782
783 for (regionIter = regionInfo_.begin(); regionIter != regionInfo_.end(); ++regionIter) {
784
785 fieldInfo theInfo = *regionIter;
786 const TString volName = theInfo.volName_;
787 TString fieldName = theInfo.fieldName_;
788 Double_t scale = theInfo.scale_;
789
790 // Find the volume
791 TGeoVolume* theVol(0);
792 if (gGeoManager) {theVol = gGeoManager->FindVolumeFast(volName.Data());}
793
794 if (theVol) {
795
796 // Find the local field
797 TVirtualMagField* localField = this->getField(fieldName);
798
799 if (localField) {
800
801 // Check local field maps know about their associated volume position and orientation.
802 // This will update the localField pointer if required
803 this->checkLocalFieldMap(localField, volName, scale);
804
805 // Reset the fieldName to use the name from the localField pointer, since this
806 // could have changed for a local field map, for example
807 fieldName = localField->GetName();
808
809 // See if we have already combined this local field with the global field
810 if (globalField_ && fieldName.Length() > 0) {
811
812 TString lgName(fieldName); lgName += "Global";
813 TVirtualMagField* lgField = this->getField(lgName);
814
815 if (!lgField) {
816
817 // Create the combined local + global field and store in the internal map.
818 // Other volumes that use the same combined field will use the stored pointer
819 if (verbose_) {
820 std::cout<<"Creating the combined field "<<lgName.Data()<<", with local field "
821 <<fieldName.Data()<<" with the global field for volume "
822 <<volName.Data()<<std::endl;
823 }
824
825 ShipCompField* combField = new ShipCompField(lgName.Data(), localField, globalField_);
826 theFields_[lgName] = combField;
827 theVol->SetField(combField);
828
829 } else {
830
831 if (verbose_) {
832 std::cout<<"Setting the field "<<lgName.Data()
833 <<" for volume "<<volName.Data()<<std::endl;
834 }
835 theVol->SetField(lgField);
836
837 }
838
839 } else {
840
841 if (verbose_) {
842 std::cout<<"There is no global field defined. Just setting the local field"<<std::endl;
843 }
844 theVol->SetField(localField);
845
846 }
847
848 } else {
849
850 std::cout<<"Could not find the local field "<<fieldName.Data()<<std::endl;
851
852 }
853
854
855 } else {
856
857 std::cout<<"Could not find the volume "<<volName<<std::endl;
858
859 }
860
861 } // regionIter loop
862
863}

◆ splitString()

ShipFieldMaker::stringVect ShipFieldMaker::splitString ( std::string &  theString,
std::string &  splitter 
) const
private

Split a string.

Parameters
[in]theStringThe string to be split up
[in]splittedThe delimiter that will be used to split up the string
Returns
a vector of the delimiter-separated strings

Definition at line 1423 of file ShipFieldMaker.cxx.

1424 {
1425
1426 // Code from STLplus
1428
1429 if (!theString.empty() && !splitter.empty()) {
1430
1431 for (std::string::size_type offset = 0;;) {
1432
1433 std::string::size_type found = theString.find(splitter, offset);
1434
1435 if (found != std::string::npos) {
1436 std::string tmpString = theString.substr(offset, found-offset);
1437 if (tmpString.size() > 0) {result.push_back(tmpString);}
1438 offset = found + splitter.size();
1439 } else {
1440 std::string tmpString = theString.substr(offset, theString.size()-offset);
1441 if (tmpString.size() > 0) {result.push_back(tmpString);}
1442 break;
1443 }
1444 }
1445 }
1446
1447 return result;
1448
1449}
std::vector< std::string > stringVect
Typedef of a vector of strings.

Member Data Documentation

◆ globalField_

ShipCompField* ShipFieldMaker::globalField_
private

The global magnetic field.

Definition at line 374 of file ShipFieldMaker.h.

◆ gotNode_

Bool_t ShipFieldMaker::gotNode_
private

Boolean to specify if we have found the volume node we need.

Definition at line 395 of file ShipFieldMaker.h.

◆ localInfo_

std::vector<fieldInfo> ShipFieldMaker::localInfo_
private

Vector of fieldInfo for local fields.

Definition at line 383 of file ShipFieldMaker.h.

◆ regionInfo_

std::vector<fieldInfo> ShipFieldMaker::regionInfo_
private

Vector of fieldInfo for regional fields.

Definition at line 380 of file ShipFieldMaker.h.

◆ Tesla_

Double_t ShipFieldMaker::Tesla_
private

Double converting Tesla to kiloGauss (for VMC/FairRoot B field units)

Definition at line 389 of file ShipFieldMaker.h.

◆ theFields_

SFMap ShipFieldMaker::theFields_
private

The map storing all created magnetic fields.

Definition at line 377 of file ShipFieldMaker.h.

◆ theNode_

TGeoNode* ShipFieldMaker::theNode_
private

The current volume node: used for finding volume transformations.

Definition at line 392 of file ShipFieldMaker.h.

◆ verbose_

Bool_t ShipFieldMaker::verbose_
private

Verbose boolean.

Definition at line 386 of file ShipFieldMaker.h.


The documentation for this class was generated from the following files: