FairShip
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))
 
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
 
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)
 
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)
 
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)
 
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)
 

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 Construct() 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 38 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)
explicit

Constructor.

Definition at line 43 of file ShipFieldMaker.cxx.

44 : TG4VUserPostDetConstruction(),
45 globalField_(nullptr),
46 theFields_(),
48 localInfo_(),
49 verbose_(verbose),
50 Tesla_(10.0), // To convert T to kGauss for VMC/FairRoot
51 theNode_(nullptr),
52 gotNode_(kFALSE) {}
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 54 of file ShipFieldMaker.cxx.

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

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 876 of file ShipFieldMaker.cxx.

878 {
879 // We assume that local field maps are stored using coordinates centred
880 // on the volume. However, GetField() uses global coordinates, so we need
881 // to find the global volume transformation (translation and rotation) so
882 // that we can find the equivalent local coordinates. This also means that
883 // each local volume needs to have its own lightweight field map copy, where
884 // we reuse the field map data but just change the coordinate transformation
885 // info
886
887 ShipBFieldMap* mapField = dynamic_cast<ShipBFieldMap*>(localField);
888 if (mapField) {
889 TString fieldName(mapField->GetName());
890 TString localName(fieldName);
891 localName += volName;
892
893 if (verbose_) {
894 std::cout << "Checking local field map " << fieldName
895 << " co-ord transformation for volume " << volName << std::endl;
896 }
897
898 // Check if we already have the local map to avoid duplication
899 ShipBFieldMap* localMap =
900 dynamic_cast<ShipBFieldMap*>(this->getField(localName));
901
902 if (!localMap && volName.Length() > 0) {
903 // Get the volume and its associate global transformation
904 TString volName1(volName);
905 volName1 += "_1";
906
907 transformInfo theInfo;
908 this->getTransformation(volName1, theInfo);
909
910 // The original field map may have defined its own translation and
911 // rotation. Apply this before the volume global transformation
912 Double_t origX0 = mapField->GetXOffset();
913 Double_t origY0 = mapField->GetYOffset();
914 Double_t origZ0 = mapField->GetZOffset();
915 TGeoTranslation origTrans("origTrans", origX0, origY0, origZ0);
916
917 Double_t origPhi = mapField->GetPhi();
918 Double_t origTheta = mapField->GetTheta();
919 Double_t origPsi = mapField->GetPsi();
920 TGeoRotation origRot("origRot", origPhi, origTheta, origPsi);
921
922 TGeoCombiTrans origComb(origTrans, origRot);
923 if (verbose_) {
924 std::cout << "The original field map transformation:" << std::endl;
925 origComb.Print();
926 }
927
928 TGeoTranslation newTrans("newTrans", theInfo.x0_, theInfo.y0_,
929 theInfo.z0_);
930 TGeoRotation newRot("newRot", theInfo.phi_, theInfo.theta_, theInfo.psi_);
931
932 TGeoCombiTrans newComb(newTrans, newRot);
933
934 if (verbose_) {
935 std::cout << "The volume transformation:" << std::endl;
936 newComb.Print();
937 }
938
939 // The full transformation
940 newComb = newComb * origComb;
941
942 if (verbose_) {
943 std::cout << "The combined transformation:" << std::endl;
944 newComb.Print();
945 }
946
947 // Update transformation info
948 const Double_t* newTransArray = newComb.GetTranslation();
949 theInfo.x0_ = newTransArray[0];
950 theInfo.y0_ = newTransArray[1];
951 theInfo.z0_ = newTransArray[2];
952
953 const TGeoRotation* fullRot = newComb.GetRotation();
954 if (fullRot) {
955 fullRot->GetAngles(theInfo.phi_, theInfo.theta_, theInfo.psi_);
956 }
957
958 // Create a lightweight copy, reusing the map data but just updating
959 // the global transformation
960 if (verbose_) {
961 std::cout << "Creating field map copy for " << localName << " based on "
962 << mapField->GetName() << ": x0 = " << theInfo.x0_
963 << ", y0 = " << theInfo.y0_ << ", z0 = " << theInfo.z0_
964 << ", phi = " << theInfo.phi_
965 << ", theta = " << theInfo.theta_
966 << ", psi = " << theInfo.psi_ << ", scale = " << scale
967 << " and symmetry = " << mapField->HasSymmetry() << std::endl;
968 }
969
970 localMap = new ShipBFieldMap(localName.Data(), *mapField, theInfo.x0_,
971 theInfo.y0_, theInfo.z0_, theInfo.phi_,
972 theInfo.theta_, theInfo.psi_, scale);
973 // Keep track that we have created this field pointer
974 theFields_[localName] = localMap;
975 }
976
977 // Set the localField pointer to use the (new or already existing) localMap
978 // pointer
979 localField = localMap;
980 }
981}
Class that defines a (3d) magnetic field map (distances in cm, fields in tesla)
Definition: ShipBFieldMap.h:20
Bool_t HasSymmetry() const
Get the boolean flag to specify if we have quadrant symmetry.
Float_t GetYOffset() const
Get the y offset coordinate of the map for global positioning.
Float_t GetTheta() const
Float_t GetPsi() const
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 coordinate 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 coordinate 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 64 of file ShipFieldMaker.cxx.

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

◆ 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 293 of file ShipFieldMaker.cxx.

293 {
294 size_t nWords = inputLine.size();
295
296 // Expecting a line such as:
297 // Bell Name BPeak zMiddle orientationInt tubeRadius
298
299 if (nWords == 6 || nWords == 9) {
300 TString name(inputLine[1].c_str());
301
302 Double_t BPeak = std::atof(inputLine[2].c_str());
303 Double_t zMiddle = std::atof(inputLine[3].c_str()); // cm
304
305 Int_t orient = std::atoi(inputLine[4].c_str());
306 Double_t tubeR = std::atof(inputLine[5].c_str()); // cm
307
308 Double_t xy(0.0), z(0.0), L(0.0);
309
310 if (nWords == 9) {
311 // Specify "target" dimensions (cm)
312 xy = std::atof(inputLine[6].c_str());
313 z = std::atof(inputLine[7].c_str());
314 L = std::atof(inputLine[8].c_str());
315 }
316
317 this->defineBell(name, BPeak, zMiddle, orient, tubeR, xy, z, L);
318
319 } else {
320 std::cout << "Expecting 6 or 9 words for the definition of the Bell field: "
321 << "Bell Name BPeak zMiddle orientationInt tubeRadius [targetXY "
322 "targetZ0 targetL]"
323 << std::endl;
324 }
325}
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 327 of file ShipFieldMaker.cxx.

329 {
330 if (!this->gotField(name)) {
331 ShipBellField* theField =
332 new ShipBellField(name.Data(), BPeak * Tesla_, zMiddle, orient, tubeR);
333
334 // Set additional parameters if we have a non-zero target length
335 if (fabs(L) > 0.0) {
336 theField->IncludeTarget(xy, z, L);
337 }
338
339 theFields_[name] = theField;
340
341 } else {
342 if (verbose_) {
343 std::cout << "We already have a Bell field with the name " << name.Data()
344 << std::endl;
345 }
346 }
347}
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 517 of file ShipFieldMaker.cxx.

517 {
518 size_t nWords = inputLine.size();
519
520 // Expecting a line such as:
521 // Composite Name Field1 Field2 ... FieldN
522
523 if (nWords > 2) {
524 TString name(inputLine[1].c_str());
525
526 std::vector<TString> fieldNames;
527 for (size_t i = 2; i < nWords; i++) {
528 TString aName(inputLine[i].c_str());
529 fieldNames.push_back(aName);
530 }
531
532 this->defineComposite(name, fieldNames);
533
534 } else {
535 std::cout << "Expecting at least 3 words for the composite definition: "
536 << "Composite Name Field1 Field2 ... FieldN" << std::endl;
537 }
538}
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:97

◆ 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 540 of file ShipFieldMaker.cxx.

544 {
545 std::vector<TString> fieldNames;
546 fieldNames.push_back(field1Name);
547 fieldNames.push_back(field2Name);
548
549 if (field3Name.Length() > 0) {
550 fieldNames.push_back(field3Name);
551 }
552 if (field4Name.Length() > 0) {
553 fieldNames.push_back(field4Name);
554 }
555
556 this->defineComposite(name, fieldNames);
557}

◆ 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 559 of file ShipFieldMaker.cxx.

560 {
561 // Check if the field is already in the map
562 if (!this->gotField(name)) {
563 // Loop over the list of fields and add them to the composite
564 std::vector<TVirtualMagField*> vectFields;
565
566 std::vector<TString>::iterator iter;
567 for (iter = fieldNames.begin(); iter != fieldNames.end(); ++iter) {
568 TString aName = *iter;
569 TVirtualMagField* aField = this->getField(aName);
570 if (aField) {
571 if (verbose_) {
572 std::cout << "Adding field " << aName << std::endl;
573 }
574 vectFields.push_back(aField);
575 }
576
577 ShipCompField* composite = new ShipCompField(name.Data(), vectFields);
578 theFields_[name] = composite;
579 }
580
581 } else {
582 std::cout << "We already have a composite field with the name "
583 << name.Data() << std::endl;
584 }
585}
Class that defines a magnetic field composed from many fields.
Definition: ShipCompField.h:19

◆ 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 227 of file ShipFieldMaker.cxx.

227 {
228 size_t nWords = inputLine.size();
229
230 // Expecting a line such as:
231 // Constant Name xMin xMax yMin yMax zMin zMax Bx By Bz
232
233 if (nWords == 11) {
234 TString name(inputLine[1].c_str());
235
236 Double_t xMin = std::atof(inputLine[2].c_str());
237 Double_t xMax = std::atof(inputLine[3].c_str());
238
239 Double_t yMin = std::atof(inputLine[4].c_str());
240 Double_t yMax = std::atof(inputLine[5].c_str());
241
242 Double_t zMin = std::atof(inputLine[6].c_str());
243 Double_t zMax = std::atof(inputLine[7].c_str());
244
245 // Input field in Tesla_, interface needs kGauss units
246 Double_t Bx = std::atof(inputLine[8].c_str());
247 Double_t By = std::atof(inputLine[9].c_str());
248 Double_t Bz = std::atof(inputLine[10].c_str());
249
250 const TVector2 xRange(xMin, xMax);
251 const TVector2 yRange(yMin, yMax);
252 const TVector2 zRange(zMin, zMax);
253 const TVector3 BVector(Bx, By, Bz);
254
255 this->defineConstant(name, xRange, yRange, zRange, BVector);
256
257 } else {
258 std::cout << "Expecting 11 words for the definition of the constant field: "
259 << "Constant Name xMin xMax yMin yMax zMin zMax Bx By Bz"
260 << std::endl;
261 }
262}
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 264 of file ShipFieldMaker.cxx.

267 {
268 // Check if the field is already in the map
269 if (!this->gotField(name)) {
270 Double_t xMin = xRange.X();
271 Double_t xMax = xRange.Y();
272 Double_t yMin = yRange.X();
273 Double_t yMax = yRange.Y();
274 Double_t zMin = zRange.X();
275 Double_t zMax = zRange.Y();
276
277 Double_t Bx = BVector.X() * Tesla_;
278 Double_t By = BVector.Y() * Tesla_;
279 Double_t Bz = BVector.Z() * Tesla_;
280
281 ShipConstField* theField = new ShipConstField(name.Data(), xMin, xMax, yMin,
282 yMax, zMin, zMax, Bx, By, Bz);
283 theFields_[name] = theField;
284
285 } else {
286 if (verbose_) {
287 std::cout << "We already have a constant field with the name "
288 << name.Data() << std::endl;
289 }
290 }
291}

◆ 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 349 of file ShipFieldMaker.cxx.

350 {
351 size_t nWords = inputLine.size();
352
353 // Expecting the line:
354 // FieldMap Name mapFileName [x0 y0 z0] [phi theta psi]
355
356 if (nWords == 3 || nWords == 6 || nWords == 9) {
357 const TString name(inputLine[1].c_str());
358 const TString mapFileName(inputLine[2].c_str());
359
360 Double_t x0(0.0), y0(0.0), z0(0.0);
361 Double_t phi(0.0), theta(0.0), psi(0.0);
362
363 if (nWords > 5) {
364 x0 = std::atof(inputLine[3].c_str());
365 y0 = std::atof(inputLine[4].c_str());
366 z0 = std::atof(inputLine[5].c_str());
367 }
368
369 if (nWords == 9) {
370 phi = std::atof(inputLine[6].c_str());
371 theta = std::atof(inputLine[7].c_str());
372 psi = std::atof(inputLine[8].c_str());
373 }
374
375 const TVector3 localCentre(x0, y0, z0);
376 const TVector3 localAngles(phi, theta, psi);
377
378 this->defineFieldMap(name, mapFileName, localCentre, localAngles,
379 useSymmetry);
380
381 } else {
382 std::cout
383 << "Expecting 3, 6 or 9 words for the definition of the field map: "
384 << "(Sym)FieldMap Name mapFileName [x0 y0 z0] [[phi theta psi]]"
385 << std::endl;
386 }
387}
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 389 of file ShipFieldMaker.cxx.

393 {
394 // Check if the field is already in the map
395 if (!this->gotField(name)) {
396 // Add the VMCWORKDIR prefix to this map file location
397 const char* vmcworkdir = getenv("VMCWORKDIR");
398 if (!vmcworkdir) {
399 LOG(fatal) << "VMCWORKDIR environment variable not set";
400 return;
401 }
402 std::string fullFileName = vmcworkdir;
403 fullFileName += "/";
404 fullFileName += mapFileName.Data();
405
406 if (verbose_) {
407 if (useSymmetry) {
408 std::cout << "Creating symmetric field map called " << name.Data()
409 << " using " << fullFileName << std::endl;
410 } else {
411 std::cout << "Creating field map called " << name.Data() << " using "
412 << fullFileName << std::endl;
413 }
414 }
415
416 // Since field maps use floating point precision we convert any double
417 // parameter values to floats, i.e. we can't simply pass TVector3 objects
418 Float_t x0 = localCentre.X();
419 Float_t y0 = localCentre.Y();
420 Float_t z0 = localCentre.Z();
421
422 Float_t phi = localAngles.X();
423 Float_t theta = localAngles.Y();
424 Float_t psi = localAngles.Z();
425
426 Float_t scale(1.0);
427
428 ShipBFieldMap* mapField =
429 new ShipBFieldMap(name.Data(), fullFileName, x0, y0, z0, phi, theta,
430 psi, scale, useSymmetry);
431 theFields_[name] = mapField;
432
433 } else {
434 if (verbose_) {
435 std::cout << "We already have a field map with the name " << name.Data()
436 << std::endl;
437 }
438 }
439}

◆ 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 441 of file ShipFieldMaker.cxx.

441 {
442 // Define a (translated) copy of a field map based in the input file line
443
444 size_t nWords = inputLine.size();
445
446 // Expecting the line:
447 // CopyMap Name MapNameToCopy x0 y0 z0 [phi theta psi]
448
449 if (nWords == 6 || nWords == 9) {
450 const TString name(inputLine[1].c_str());
451
452 // We want to try to copy and transpose an already existing field map
453 const TString mapNameToCopy(inputLine[2].c_str());
454
455 Double_t x0 = std::atof(inputLine[3].c_str());
456 Double_t y0 = std::atof(inputLine[4].c_str());
457 Double_t z0 = std::atof(inputLine[5].c_str());
458
459 Double_t phi(0.0), theta(0.0), psi(0.0);
460
461 if (nWords == 9) {
462 phi = std::atof(inputLine[6].c_str());
463 theta = std::atof(inputLine[7].c_str());
464 psi = std::atof(inputLine[8].c_str());
465 }
466
467 const TVector3 translation(x0, y0, z0);
468 const TVector3 eulerAngles(phi, theta, psi);
469
470 this->defineFieldMapCopy(name, mapNameToCopy, translation, eulerAngles);
471
472 } else {
473 std::cout << "Expecting 6 or 9 words for the copy of a field map: "
474 << "CopyMap Name MapNameToCopy x0 y0 z0 [phi theta psi]"
475 << std::endl;
476 }
477}
void defineFieldMapCopy(const TString &name, const TString &mapNameToCopy, const TVector3 &translation, const TVector3 &eulerAngles=TVector3(0.0, 0.0, 0.0))

◆ 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 479 of file ShipFieldMaker.cxx.

482 {
483 // Check if the field is already in the map
484 if (!this->gotField(name)) {
485 ShipBFieldMap* fieldToCopy =
486 dynamic_cast<ShipBFieldMap*>(this->getField(mapNameToCopy));
487
488 if (fieldToCopy) {
489 if (verbose_) {
490 std::cout << "Creating map field copy " << name.Data() << " based on "
491 << mapNameToCopy.Data() << std::endl;
492 }
493
494 // Since field maps use floating point precision we convert any double
495 // parameter values to floats, i.e. we can't simply pass TVector3 objects
496 Float_t x0 = translation.X();
497 Float_t y0 = translation.Y();
498 Float_t z0 = translation.Z();
499
500 Float_t phi = eulerAngles.X();
501 Float_t theta = eulerAngles.Y();
502 Float_t psi = eulerAngles.Z();
503
504 Float_t scale(1.0);
505
506 ShipBFieldMap* copiedMap = new ShipBFieldMap(
507 name.Data(), *fieldToCopy, x0, y0, z0, phi, theta, psi, scale);
508 theFields_[name] = copiedMap;
509 }
510
511 } else {
512 std::cout << "We already have a copied field map with the name "
513 << name.Data() << std::endl;
514 }
515}

◆ 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 587 of file ShipFieldMaker.cxx.

587 {
588 // Define the global field using the input file line
589
590 size_t nWords = inputLine.size();
591
592 // Expecting the line:
593 // Global Field1 ... FieldN
594
595 if (nWords > 1) {
596 TString name("Global");
597
598 std::vector<TString> fieldNames;
599 for (size_t i = 1; i < nWords; i++) {
600 TString aName(inputLine[i].c_str());
601 fieldNames.push_back(aName);
602 }
603
604 this->defineGlobalField(fieldNames);
605
606 } else {
607 std::cout
608 << "Expecting at least two words for the global field definition: "
609 << "Global Field1 ... FieldN" << std::endl;
610 }
611}
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 613 of file ShipFieldMaker.cxx.

616 {
617 std::vector<TString> fieldNames;
618 fieldNames.push_back(field1Name);
619
620 if (field2Name.Length() > 0) {
621 fieldNames.push_back(field2Name);
622 }
623 if (field3Name.Length() > 0) {
624 fieldNames.push_back(field3Name);
625 }
626 if (field4Name.Length() > 0) {
627 fieldNames.push_back(field4Name);
628 }
629
630 this->defineGlobalField(fieldNames);
631}

◆ 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 633 of file ShipFieldMaker.cxx.

633 {
634 if (globalField_) {
635 if (verbose_) {
636 std::cout << "Deleting already existing Global field" << std::endl;
637 }
638 delete globalField_;
639 }
640
641 if (verbose_) {
642 std::cout << "Setting the Global field" << std::endl;
643 }
644
645 std::vector<TVirtualMagField*> vectFields;
646
647 std::vector<TString>::iterator iter;
648 for (iter = fieldNames.begin(); iter != fieldNames.end(); ++iter) {
649 TString aName = *iter;
650 TVirtualMagField* aField = this->getField(aName);
651
652 if (aField) {
653 if (verbose_) {
654 std::cout << "Adding field " << aName << " to Global" << std::endl;
655 }
656 vectFields.push_back(aField);
657 } else {
658 std::cout << "Could not find the field " << aName << std::endl;
659 }
660 }
661
662 TString name("Global");
663 globalField_ = new ShipCompField(name.Data(), vectFields);
664
665 // Set this as the global field in the virtual MC
666 if (gMC) {
667 gMC->SetMagField(globalField_);
668 } else {
669 std::cout
670 << "The virtual MC pointer gMC is null! The global field can't be used "
671 "by Geant4 but will work for track fitting and track extrapolation"
672 << std::endl;
673 }
674}

◆ 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 798 of file ShipFieldMaker.cxx.

798 {
799 // Set only the local field for the region using info from inputLine
800 size_t nWords = inputLine.size();
801
802 // Expecting the line:
803 // Local VolName FieldName [FieldMapScaleFactor]
804
805 if (nWords == 3 || nWords == 4) {
806 TString volName(inputLine[1].c_str());
807 TString fieldName(inputLine[2].c_str());
808
809 Double_t scale(1.0);
810 if (nWords == 4) {
811 scale = std::atof(inputLine[3].c_str());
812 }
813
814 this->defineLocalField(volName, fieldName, scale);
815
816 } else {
817 std::cout << "Expecting 3 or 4 words for the local field definition: "
818 << "Local VolName LocalFieldName [FieldMapScale]" << std::endl;
819 }
820}
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 822 of file ShipFieldMaker.cxx.

824 {
825 if (verbose_) {
826 std::cout << "ShipFieldMaker::defineLocalField for volume "
827 << volName.Data() << " and field " << fieldName.Data()
828 << " with scale = " << scale << std::endl;
829 }
830
831 fieldInfo theInfo(volName, fieldName, scale);
832 localInfo_.push_back(theInfo);
833}

◆ 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 676 of file ShipFieldMaker.cxx.

676 {
677 // Set the local + global field for the region using info from inputLine
678 size_t nWords = inputLine.size();
679
680 // Expecting the line:
681 // Region VolName FieldName [FieldMapScaleFactor]
682
683 if (nWords == 3 || nWords == 4) {
684 TString volName(inputLine[1].c_str());
685 TString fieldName(inputLine[2].c_str());
686
687 Double_t scale(1.0);
688 if (nWords == 4) {
689 scale = std::atof(inputLine[3].c_str());
690 }
691
692 this->defineRegionField(volName, fieldName, scale);
693
694 } else {
695 std::cout << "Expecting 3 or 4 words for the region (local + global) field "
696 "definition: "
697 << "Region VolName LocalFieldName [LocalFieldMapScale]"
698 << std::endl;
699 }
700}
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 702 of file ShipFieldMaker.cxx.

704 {
705 if (verbose_) {
706 std::cout << "ShipFieldMaker::defineRegionField for volume "
707 << volName.Data() << " and field " << fieldName.Data()
708 << " with scale = " << scale << std::endl;
709 }
710
711 fieldInfo theInfo(volName, fieldName, scale);
712 regionInfo_.push_back(theInfo);
713}

◆ 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 182 of file ShipFieldMaker.cxx.

182 {
183 size_t nWords = inputLine.size();
184
185 // Expecting a line such as:
186 // Uniform Name Bx By Bz
187
188 if (nWords == 5) {
189 const TString name(inputLine[1].c_str());
190
191 Double_t Bx = std::atof(inputLine[2].c_str());
192 Double_t By = std::atof(inputLine[3].c_str());
193 Double_t Bz = std::atof(inputLine[4].c_str());
194 const TVector3 BVector(Bx, By, Bz);
195
196 this->defineUniform(name, BVector);
197
198 } else {
199 std::cout << "Expecting 5 words for the definition of the uniform field: "
200 << "Uniform Name Bx By Bz" << std::endl;
201 }
202}
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 204 of file ShipFieldMaker.cxx.

205 {
206 // Check if the field is already in the map
207 if (!this->gotField(name)) {
208 if (verbose_) {
209 std::cout << "Creating uniform field for " << name.Data() << std::endl;
210 }
211
212 Double_t Bx = BVector.X() * Tesla_;
213 Double_t By = BVector.Y() * Tesla_;
214 Double_t Bz = BVector.Z() * Tesla_;
215
216 TGeoUniformMagField* uField = new TGeoUniformMagField(Bx, By, Bz);
217 theFields_[name] = uField;
218
219 } else {
220 if (verbose_) {
221 std::cout << "We already have a uniform field with the name "
222 << name.Data() << std::endl;
223 }
224 }
225}

◆ 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 1047 of file ShipFieldMaker.cxx.

1047 {
1048 // Find the geometry node that matches the required volume name
1049
1050 // Immediately exit the function if we have already found the volume
1051 if (gotNode_) {
1052 return;
1053 }
1054
1055 if (aVolume) {
1056 TObjArray* volNodes = aVolume->GetNodes();
1057
1058 if (volNodes) {
1059 // Loop over the geometry nodes
1060 int nNodes = volNodes->GetEntries();
1061 for (int i = 0; i < nNodes; i++) {
1062 TGeoNode* node = dynamic_cast<TGeoNode*>(volNodes->At(i));
1063
1064 if (node) {
1065 const TString nodeName(node->GetName());
1066 if (!nodeName.CompareTo(volName, TString::kExact)) {
1067 // We have a match. The node has the transformation we need
1068 theNode_ = node;
1069 gotNode_ = kTRUE;
1070 break;
1071
1072 } else if (node->GetNodes()) {
1073 // We have sub-volumes. Recursively call this function
1074 this->findNode(node->GetVolume(), volName);
1075 }
1076 }
1077 }
1078 }
1079 }
1080}
void findNode(TGeoVolume *aVolume, const TString &volName)

◆ 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 1290 of file ShipFieldMaker.cxx.

1292 {
1293 std::ofstream myfile;
1294 myfile.open(fileName);
1295 int xSteps = ceil(xRange / step) + 1; // field map has X range from 0 to xMax
1296 int ySteps = ceil(yRange / step) + 1; // from 0 up to yMax
1297 int zSteps = ceil(zRange * 2. / step) + 1; // from -zMax up to zMax
1298 Double_t position[3] = {0.0, 0.0, 0.0};
1299 myfile << xSteps << " " << ySteps << " " << zSteps << " " << step
1300 << " " << xRange << " " << yRange << " " << zRange
1301 << std::endl;
1302 for (int i = 0; i < xSteps; i++) {
1303 for (int k = 0; k < ySteps; k++) {
1304 for (int m = 0; m < zSteps; m++) {
1305 Double_t B[3] = {0.0, 0.0, 0.0};
1306 Double_t x = step * i;
1307 Double_t y = step * k;
1308 Double_t z = m * step - zRange + zShift;
1309 position[0] = x;
1310 position[1] = y;
1311 position[2] = z;
1312 Bool_t inside(kFALSE);
1313 TGeoNode* theNode =
1314 gGeoManager->FindNode(position[0], position[1], position[2]);
1315 if (theNode) {
1316 TGeoVolume* theVol = theNode->GetVolume();
1317 if (theVol) {
1318 TVirtualMagField* theField =
1319 dynamic_cast<TVirtualMagField*>(theVol->GetField());
1320 if (theField) {
1321 theField->Field(position, B);
1322 inside = kTRUE;
1323 }
1324 }
1325 }
1326 if (inside == kFALSE && globalField_) {
1327 globalField_->Field(position, B);
1328 }
1329 myfile << x << " " << y << " " << z << " " << B[0] / Tesla_
1330 << " " << B[1] / Tesla_ << " " << B[2] / Tesla_
1331 << std::endl;
1332 }
1333 }
1334 }
1335 myfile.close();
1336}
Double_t m
Definition: diagrams_b.h:4
virtual void Field(const Double_t *position, Double_t *B)

◆ 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 212 of file ShipFieldMaker.h.

212{ 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 1116 of file ShipFieldMaker.cxx.

1116 {
1117 TVirtualMagField* theField(0);
1118
1119 // Iterate over the internal map and see if we have a match
1120 SFMap::const_iterator iter;
1121 for (iter = theFields_.begin(); iter != theFields_.end(); ++iter) {
1122 TString key = iter->first;
1123 TVirtualMagField* BField = iter->second;
1124
1125 // Check that we have the key already stored
1126 if (!key.CompareTo(name, TString::kExact)) {
1127 theField = BField;
1128 break;
1129 }
1130 }
1131
1132 return theField;
1133}

◆ getGlobalField()

ShipCompField * ShipFieldMaker::getGlobalField ( ) const
inline

Get the global magnetic field.

Returns
the global magnetic field pointer

Definition at line 204 of file ShipFieldMaker.h.

204{ 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 983 of file ShipFieldMaker.cxx.

984 {
985 // Find the geometry node that matches the volume name. We need to search
986 // the geometry hierarchy recursively until we get a match. Note that nodes
987 // have "_1" appended to the volume name.
988
989 theInfo.x0_ = 0.0;
990 theInfo.y0_ = 0.0;
991 theInfo.z0_ = 0.0;
992 theInfo.phi_ = 0.0;
993 theInfo.theta_ = 0.0;
994 theInfo.psi_ = 0.0;
995
996 TGeoMatrix* theMatrix(0);
997
998 TGeoVolume* topVolume = gGeoManager->GetTopVolume();
999 if (!topVolume) {
1000 std::cout
1001 << "Can't find the top volume in ShipFieldMaker::getTransformation"
1002 << std::endl;
1003 return;
1004 }
1005
1006 if (verbose_) {
1007 std::cout << "Finding transformation for " << volName << std::endl;
1008 }
1009
1010 // Find the geometry node that matches the required name
1011 theNode_ = 0;
1012 gotNode_ = kFALSE;
1013 this->findNode(topVolume, volName);
1014
1015 if (theNode_) {
1016 theMatrix = theNode_->GetMatrix();
1017 }
1018
1019 // Retrieve the translation and rotation information
1020 if (theMatrix) {
1021 // Translation displacement components
1022 const Double_t* theTrans = theMatrix->GetTranslation();
1023 theInfo.x0_ = theTrans[0];
1024 theInfo.y0_ = theTrans[1];
1025 theInfo.z0_ = theTrans[2];
1026
1027 // Euler rotation angles. First check if we have a combined translation
1028 // and rotation, then check if we just have a pure rotation
1029 if (theMatrix->IsCombi()) {
1030 TGeoCombiTrans* theCombi = dynamic_cast<TGeoCombiTrans*>(theMatrix);
1031 if (theCombi) {
1032 TGeoRotation* combRotn = theCombi->GetRotation();
1033 if (combRotn) {
1034 combRotn->GetAngles(theInfo.phi_, theInfo.theta_, theInfo.psi_);
1035 }
1036 }
1037
1038 } else if (theMatrix->IsRotation()) {
1039 TGeoRotation* theRotn = dynamic_cast<TGeoRotation*>(theMatrix);
1040 if (theRotn) {
1041 theRotn->GetAngles(theInfo.phi_, theInfo.theta_, theInfo.psi_);
1042 }
1043 }
1044 }
1045}

◆ 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 1082 of file ShipFieldMaker.cxx.

1082 {
1083 TVirtualMagField* theField(0);
1084 TGeoVolume* theVol(0);
1085 if (gGeoManager) {
1086 theVol = gGeoManager->FindVolumeFast(volName.Data());
1087 }
1088
1089 if (theVol) {
1090 // Need to cast the TObject* to a TVirtualMagField*
1091 theField = dynamic_cast<TVirtualMagField*>(theVol->GetField());
1092 }
1093
1094 return theField;
1095}

◆ 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 1097 of file ShipFieldMaker.cxx.

1097 {
1098 Bool_t result(kFALSE);
1099
1100 // Iterate over the internal map and see if we have a match
1101 SFMap::const_iterator iter;
1102 for (iter = theFields_.begin(); iter != theFields_.end(); ++iter) {
1103 TString key = iter->first;
1104 TVirtualMagField* theField = iter->second;
1105
1106 // Check that we have the key already stored and the pointer is not null
1107 if (!key.CompareTo(name, TString::kExact) && theField) {
1108 result = kTRUE;
1109 break;
1110 }
1111 }
1112
1113 return result;
1114}

◆ 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 coordinate 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 1150 of file ShipFieldMaker.cxx.

1152 {
1153 std::cout << "ShipFieldMaker plotField " << plotFile << ": type = " << type
1154 << std::endl;
1155
1156 Double_t xMin = xAxis(0);
1157 Double_t xMax = xAxis(1);
1158 Double_t dx = xAxis(2);
1159 Int_t Nx(0);
1160 if (dx > 0.0) {
1161 Nx = std::lround((xMax - xMin) / dx);
1162 }
1163
1164 Double_t yMin = yAxis(0);
1165 Double_t yMax = yAxis(1);
1166 Double_t dy = yAxis(2);
1167 Int_t Ny(0);
1168 if (dy > 0.0) {
1169 Ny = std::lround((yMax - yMin) / dy);
1170 }
1171
1172 // Create a 2d histogram
1173 const int nhistograms = 4; // x,y,z,and magnitude
1174 const int ncoordinates = 3; // x,y,z
1175
1176 TH2D theHist[nhistograms];
1177 std::string titles[nhistograms] = {"Bx (T)", "By (T)", "Bz (T)", "B (T)"};
1178 for (int icomponent = 0; icomponent < nhistograms; icomponent++) {
1179 theHist[icomponent] =
1180 TH2D(Form("theHist[%i]", icomponent), titles[icomponent].data(), Nx,
1181 xMin, xMax, Ny, yMin, yMax);
1182 theHist[icomponent].SetDirectory(0);
1183 if (type == 0) {
1184 // x-y
1185 theHist[icomponent].SetXTitle("x (cm)");
1186 theHist[icomponent].SetYTitle("y (cm)");
1187 } else if (type == 1) {
1188 // z-x
1189 theHist[icomponent].SetXTitle("z (cm)");
1190 theHist[icomponent].SetYTitle("x (cm)");
1191 } else if (type == 2) {
1192 // z-y
1193 theHist[icomponent].SetXTitle("z (cm)");
1194 theHist[icomponent].SetYTitle("y (cm)");
1195 }
1196 }
1197
1198 // Loop over "x" axis
1199 for (Int_t ix = 0; ix < Nx; ix++) {
1200 Double_t x = dx * ix + xMin;
1201
1202 // Loop over "y" axis
1203 for (Int_t iy = 0; iy < Ny; iy++) {
1204 Double_t y = dy * iy + yMin;
1205
1206 // Initialise the B field array to zero
1207 Double_t B[ncoordinates] = {0.0, 0.0, 0.0};
1208
1209 // Initialise the position array to zero
1210 Double_t position[ncoordinates] = {0.0, 0.0, 0.0};
1211 if (type == 0) {
1212 // x-y
1213 position[0] = x, position[1] = y;
1214 } else if (type == 1) {
1215 // z-x
1216 position[0] = y, position[2] = x;
1217 } else if (type == 2) {
1218 // z-y
1219 position[1] = y;
1220 position[2] = x;
1221 }
1222
1223 // Find out if the point is inside one of the geometry volumes
1224 Bool_t inside(kFALSE);
1225
1226 // Find the geometry node (volume path)
1227 TGeoNode* theNode =
1228 gGeoManager->FindNode(position[0], position[1], position[2]);
1229
1230 if (theNode) {
1231 // Get the volume
1232 TGeoVolume* theVol = theNode->GetVolume();
1233
1234 if (theVol) {
1235 // Get the magnetic field
1236 TVirtualMagField* theField =
1237 dynamic_cast<TVirtualMagField*>(theVol->GetField());
1238
1239 if (theField) {
1240 // Find the "local" field inside the volume (using global co-ords)
1241 theField->Field(position, B);
1242 inside = kTRUE;
1243
1244 } // theField
1245
1246 } // volume
1247
1248 } // node
1249
1250 // If no local volumes found, use global field if it exists
1251 if (inside == kFALSE && globalField_) {
1252 globalField_->Field(position, B);
1253 }
1254
1255 // Divide by the Tesla_ factor, since we want to plot Tesla_ not kGauss
1256 // (VMC/FairRoot units)
1257 for (int icomponent = 0; icomponent < ncoordinates; icomponent++) {
1258 theHist[icomponent].Fill(x, y, B[icomponent] / Tesla_);
1259 }
1260 Double_t BMag = sqrt(B[0] * B[0] + B[1] * B[1] + B[2] * B[2]) / Tesla_;
1261 theHist[3].Fill(x, y, BMag);
1262
1263 } // "y" axis
1264
1265 } // "x" axis
1266
1267 Bool_t wasBatch = gROOT->IsBatch();
1268 // Disable pop-up windows
1269 gROOT->SetBatch(kTRUE);
1270 TCanvas theCanvas("theCanvas", "", 900, 700);
1271 gROOT->SetStyle("Plain");
1272 gStyle->SetOptStat(0);
1273 // Set colour style
1274 gStyle->SetPalette(kBird);
1275 theCanvas.UseCurrentStyle();
1276
1277 theCanvas.Divide(2, 2);
1278 for (int icomponent = 0; icomponent < nhistograms; icomponent++) {
1279 theCanvas.cd(icomponent + 1);
1280 theHist[icomponent].Draw("colz");
1281 }
1282 theCanvas.Print(plotFile.c_str());
1283
1284 // Reset the batch boolean
1285 if (wasBatch == kFALSE) {
1286 gROOT->SetBatch(kFALSE);
1287 }
1288}

◆ 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 1135 of file ShipFieldMaker.cxx.

1136 {
1137 this->plotField(0, xAxis, yAxis, plotFile);
1138}
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 1140 of file ShipFieldMaker.cxx.

1141 {
1142 this->plotField(1, zAxis, xAxis, plotFile);
1143}

◆ 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 1145 of file ShipFieldMaker.cxx.

1146 {
1147 this->plotField(2, zAxis, yAxis, plotFile);
1148}

◆ 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 70 of file ShipFieldMaker.cxx.

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

◆ setAllLocalFields()

void ShipFieldMaker::setAllLocalFields ( )
protected

Definition at line 835 of file ShipFieldMaker.cxx.

835 {
836 // Loop over all entries in the localInfo_ vector and assign fields to their
837 // volumes
838 std::vector<fieldInfo>::iterator localIter;
839
840 for (localIter = localInfo_.begin(); localIter != localInfo_.end();
841 ++localIter) {
842 fieldInfo theInfo = *localIter;
843 const TString volName = theInfo.volName_;
844 TString fieldName = theInfo.fieldName_;
845 Double_t scale = theInfo.scale_;
846
847 TGeoVolume* theVol(0);
848 if (gGeoManager) {
849 theVol = gGeoManager->FindVolumeFast(volName.Data());
850 }
851
852 if (theVol) {
853 TVirtualMagField* localField = this->getField(fieldName);
854
855 if (localField) {
856 this->checkLocalFieldMap(localField, volName, scale);
857 theVol->SetField(localField);
858
859 if (verbose_) {
860 std::cout << "Setting local field " << localField->GetName()
861 << " for volume " << volName << std::endl;
862 }
863
864 } else {
865 std::cout << "Could not find the field " << fieldName.Data()
866 << std::endl;
867 }
868
869 } else {
870 std::cout << "Could not find the volume " << volName.Data() << std::endl;
871 }
872
873 } // localIter loop
874}
void checkLocalFieldMap(TVirtualMagField *&localField, const TString &volName, Double_t scale)

◆ setAllRegionFields()

void ShipFieldMaker::setAllRegionFields ( )
protected

Definition at line 715 of file ShipFieldMaker.cxx.

715 {
716 // Loop over all entries in the regionInfo_ vector and assign fields to their
717 // volumes
718 std::vector<fieldInfo>::iterator regionIter;
719
720 for (regionIter = regionInfo_.begin(); regionIter != regionInfo_.end();
721 ++regionIter) {
722 fieldInfo theInfo = *regionIter;
723 const TString volName = theInfo.volName_;
724 TString fieldName = theInfo.fieldName_;
725 Double_t scale = theInfo.scale_;
726
727 // Find the volume
728 TGeoVolume* theVol(0);
729 if (gGeoManager) {
730 theVol = gGeoManager->FindVolumeFast(volName.Data());
731 }
732
733 if (theVol) {
734 // Find the local field
735 TVirtualMagField* localField = this->getField(fieldName);
736
737 if (localField) {
738 // Check local field maps know about their associated volume position
739 // and orientation. This will update the localField pointer if required
740 this->checkLocalFieldMap(localField, volName, scale);
741
742 // Reset the fieldName to use the name from the localField pointer,
743 // since this could have changed for a local field map, for example
744 fieldName = localField->GetName();
745
746 // See if we have already combined this local field with the global
747 // field
748 if (globalField_ && fieldName.Length() > 0) {
749 TString lgName(fieldName);
750 lgName += "Global";
751 TVirtualMagField* lgField = this->getField(lgName);
752
753 if (!lgField) {
754 // Create the combined local + global field and store in the
755 // internal map. Other volumes that use the same combined field will
756 // use the stored pointer
757 if (verbose_) {
758 std::cout << "Creating the combined field " << lgName.Data()
759 << ", with local field " << fieldName.Data()
760 << " with the global field for volume "
761 << volName.Data() << std::endl;
762 }
763
764 ShipCompField* combField =
765 new ShipCompField(lgName.Data(), localField, globalField_);
766 theFields_[lgName] = combField;
767 theVol->SetField(combField);
768
769 } else {
770 if (verbose_) {
771 std::cout << "Setting the field " << lgName.Data()
772 << " for volume " << volName.Data() << std::endl;
773 }
774 theVol->SetField(lgField);
775 }
776
777 } else {
778 if (verbose_) {
779 std::cout << "There is no global field defined. Just setting the "
780 "local field"
781 << std::endl;
782 }
783 theVol->SetField(localField);
784 }
785
786 } else {
787 std::cout << "Could not find the local field " << fieldName.Data()
788 << std::endl;
789 }
790
791 } else {
792 std::cout << "Could not find the volume " << volName << std::endl;
793 }
794
795 } // regionIter loop
796}

◆ 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]splitterThe delimiter that will be used to split up the string
Returns
a vector of the delimiter-separated strings

Definition at line 1338 of file ShipFieldMaker.cxx.

1339 {
1340 // Code from STLplus
1341 stringVect result;
1342
1343 if (!theString.empty() && !splitter.empty()) {
1344 for (std::string::size_type offset = 0;;) {
1345 std::string::size_type found = theString.find(splitter, offset);
1346
1347 if (found != std::string::npos) {
1348 std::string tmpString = theString.substr(offset, found - offset);
1349 if (tmpString.size() > 0) {
1350 result.push_back(tmpString);
1351 }
1352 offset = found + splitter.size();
1353 } else {
1354 std::string tmpString =
1355 theString.substr(offset, theString.size() - offset);
1356 if (tmpString.size() > 0) {
1357 result.push_back(tmpString);
1358 }
1359 break;
1360 }
1361 }
1362 }
1363
1364 return result;
1365}
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 404 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 425 of file ShipFieldMaker.h.

◆ localInfo_

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

Vector of fieldInfo for local fields.

Definition at line 413 of file ShipFieldMaker.h.

◆ regionInfo_

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

Vector of fieldInfo for regional fields.

Definition at line 410 of file ShipFieldMaker.h.

◆ Tesla_

Double_t ShipFieldMaker::Tesla_
private

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

Definition at line 419 of file ShipFieldMaker.h.

◆ theFields_

SFMap ShipFieldMaker::theFields_
private

The map storing all created magnetic fields.

Definition at line 407 of file ShipFieldMaker.h.

◆ theNode_

TGeoNode* ShipFieldMaker::theNode_
private

The current volume node: used for finding volume transformations.

Definition at line 422 of file ShipFieldMaker.h.

◆ verbose_

Bool_t ShipFieldMaker::verbose_
private

Verbose boolean.

Definition at line 416 of file ShipFieldMaker.h.


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