235#include "TRestAxionMagneticField.h"
239#include "TRestPhysics.h"
266 RESTDebug <<
"Entering TRestAxionMagneticField constructor( cfgFileName, name )" <<
RESTendl;
279 RESTDebug <<
"Entering ... TRestAxionMagneticField() destructor." <<
RESTendl;
338 Double_t step, TString style, Double_t depth) {
339 Double_t step_x, step_y, step_z;
352 if (volIndex < 0) volIndex = 0;
355 RESTError << volIndex <<
" corresponds to none volume index " <<
RESTendl;
357 RESTError <<
"Setting volIndex to the first volume" <<
RESTendl;
366 step_x = step_y = step_z = step;
371 if (!(projection ==
"XY" || projection ==
"XZ" || projection ==
"YZ")) {
372 RESTError <<
"You entered : " << projection <<
" as a projection but you have to choose XY, XZ or YZ"
381 Double_t halfSizeX = vol->mesh.GetNetSizeX() / 2.;
382 Double_t halfSizeY = vol->mesh.GetNetSizeY() / 2.;
383 Double_t halfSizeZ = vol->mesh.GetNetSizeZ() / 2.;
385 Double_t xMin = centerX - halfSizeX;
386 Double_t yMin = centerY - halfSizeY;
387 Double_t zMin = centerZ - halfSizeZ;
389 Double_t xMax = centerX + halfSizeX;
390 Double_t yMax = centerY + halfSizeY;
391 Double_t zMax = centerZ + halfSizeZ;
393 Int_t nBinsX = (xMax - xMin) / step_x;
394 Int_t nBinsY = (yMax - yMin) / step_y;
395 Int_t nBinsZ = (zMax - zMin) / step_z;
397 Double_t x = -1, y = -1, z = -1;
401 if (projection ==
"XY") {
402 fCanvas =
new TCanvas(
"fCanvas",
"");
403 fHisto =
new TH2D(
"",
"", nBinsX, xMin, xMax, nBinsY, yMin, yMax);
405 if (depth < -100000.0)
406 z = (zMin + zMax) / 2.0;
407 else if ((depth >= zMin) && (depth <= zMax))
410 RESTError <<
"You entered depth = " << depth <<
", but you have to choose depth between " << zMin
414 for (Int_t i = 0; i < nBinsX; i++) {
416 for (Int_t j = 0; j < nBinsY; j++) {
427 RESTError <<
"You entered : " << Bcomp
428 <<
" as a B component but you have to choose X, Y or Z" <<
RESTendl;
438 fHisto->SetBit(TH1::kNoStats);
439 fHisto->GetXaxis()->SetTitle(
"x (mm)");
440 fHisto->GetYaxis()->SetTitle(
"y (mm)");
443 TString title = Form(
"B_{x} against x and y @ z = %.1f", z);
448 TString title = Form(
"B_{y} against x and y @ z = %.1f", z);
453 TString title = Form(
"B_{z} against x and y @ z = %.1f", z);
462 if (projection ==
"XZ") {
463 TCanvas*
fCanvas =
new TCanvas(
"fCanvas",
"");
464 fHisto =
new TH2D(
"",
"", nBinsX, xMin, xMax, nBinsZ, zMin, zMax);
466 if (depth < -100000.0)
467 y = (yMin + yMax) / 2.0;
468 else if ((depth >= yMin) && (depth <= yMax))
471 RESTError <<
"You entered depth = " << depth <<
", but you have to choose depth between " << yMin
475 for (Int_t i = 0; i < nBinsX; i++) {
477 for (Int_t j = 0; j < nBinsZ; j++) {
488 RESTError <<
"You entered : " << Bcomp
489 <<
" as a B component but you have to choose X, Y or Z" <<
RESTendl;
499 fHisto->SetBit(TH1::kNoStats);
500 fHisto->GetXaxis()->SetTitle(
"x (mm)");
501 fHisto->GetYaxis()->SetTitle(
"z (mm)");
504 TString title = Form(
"B_{x} against x and z @ y = %.1f", y);
509 TString title = Form(
"B_{y} against x and z @ y = %.1f", y);
514 TString title = Form(
"B_{z} against x and z @ y = %.1f", y);
523 if (projection ==
"YZ") {
524 TCanvas*
fCanvas =
new TCanvas(
"fCanvas",
"");
525 fHisto =
new TH2D(
"",
"", nBinsY, yMin, yMax, nBinsZ, zMin, zMax);
527 if (depth < -100000.0)
528 x = (xMin + xMax) / 2.0;
529 else if ((depth >= xMin) && (depth <= xMax))
532 RESTError <<
"You entered depth = " << depth <<
", but you have to choose depth between " << xMin
536 for (Int_t i = 0; i < nBinsY; i++) {
538 for (Int_t j = 0; j < nBinsZ; j++) {
549 RESTError <<
"You entered : " << Bcomp
550 <<
" as a B component but you have to choose X, Y or Z" <<
RESTendl;
560 fHisto->SetBit(TH1::kNoStats);
561 fHisto->GetXaxis()->SetTitle(
"y (mm)");
562 fHisto->GetYaxis()->SetTitle(
"z (mm)");
565 TString title = Form(
"B_{x} against y and z @ x = %.1f", x);
570 TString title = Form(
"B_{y} against y and z @ x = %.1f", x);
575 TString title = Form(
"B_{z} against y and z @ x = %.1f", x);
596 fCanvas =
new TCanvas(
"fCanvas",
"", 1600, 600);
598 TPad* pad1 =
new TPad(
"pad1",
"This is pad1", 0.01, 0.02, 0.99, 0.97);
604 Double_t genSizeY =
fBoundMax[volId].Y() * 3.;
609 TGraph* bBox =
new TGraph();
621 RESTDebug <<
"Gen position : " << genPositionZ <<
RESTendl;
623 bBox->GetXaxis()->SetLimits(genPositionZ - 500, finalPositionZ + 500);
624 bBox->GetHistogram()->SetMaximum(genSizeY + 100);
625 bBox->GetHistogram()->SetMinimum(-genSizeY - 100);
627 bBox->GetXaxis()->SetTitle(
"Z [mm]");
628 bBox->GetXaxis()->SetTitleSize(0.05);
629 bBox->GetXaxis()->SetLabelSize(0.05);
630 bBox->GetYaxis()->SetTitle(
"Y [mm]");
631 bBox->GetYaxis()->SetTitleOffset(1.3);
632 bBox->GetYaxis()->SetTitleSize(0.05);
633 bBox->GetYaxis()->SetLabelSize(0.05);
634 bBox->SetLineWidth(2);
638 for (Double_t y = genSizeY; y >= -genSizeY; y -=
fBoundMax[volId].Y()) {
639 TVector3 position(0, y, genPositionZ);
640 TVector3 direction = (vanishingPoint - position).Unit();
643 TGraph* grB =
new TGraph();
644 grB->SetPoint(0, trackBounds[0].Z(), trackBounds[0].Y());
645 grB->SetPoint(1, trackBounds[1].Z(), trackBounds[1].Y());
652 RESTDebug <<
"Start moving along" <<
RESTendl;
653 RESTDebug <<
"++++++++++++++++++" <<
RESTendl;
655 TGraph* fieldGr =
new TGraph();
657 Double_t delta =
fBoundMax[volId][2] * 2. / divisions;
660 fieldGr->SetPoint(fieldGr->GetN(), posZ, field);
665 position =
MoveToPlane(position, direction, TVector3(0, 0, 1), posAlongAxis);
668 fieldGr->SetPoint(fieldGr->GetN(), posZ, field);
674 position =
MoveToPlane(position, direction, TVector3(0, 0, 1), posAlongAxis);
677 fieldGr->SetPoint(fieldGr->GetN(), posZ, field2);
680 fieldGr->SetLineWidth(3);
681 fieldGr->SetLineColor(38 + n);
682 fieldGr->GetXaxis()->SetLimits(genPositionZ - 500, finalPositionZ + 500);
683 fieldGr->GetHistogram()->SetMaximum(2.5);
684 fieldGr->GetHistogram()->SetMinimum(0);
685 fieldGr->GetXaxis()->SetTitle(
"Z [mm]");
686 fieldGr->GetXaxis()->SetTitleSize(0.05);
687 fieldGr->GetXaxis()->SetLabelSize(0.05);
688 fieldGr->GetYaxis()->SetTitle(
"B [T]");
689 fieldGr->GetYaxis()->SetTitleOffset(1.3);
690 fieldGr->GetYaxis()->SetTitleSize(0.05);
691 fieldGr->GetYaxis()->SetLabelSize(0.05);
698 TGraph* gr =
new TGraph();
699 gr->SetPoint(0, genPositionZ, y);
700 position =
MoveToPlane(position, direction, TVector3(0, 0, 1), TVector3(0, 0, finalPositionZ));
701 gr->SetPoint(1, finalPositionZ, position.Y());
703 gr->SetLineWidth(1.5);
705 grB->SetLineColor(38 + n);
707 grB->SetLineWidth(3);
722 std::vector<std::vector<Float_t>> data) {
723 mVol.field.resize(mVol.mesh.GetNodesX());
724 for (
unsigned int n = 0; n < mVol.field.size(); n++) {
725 mVol.field[n].resize(mVol.mesh.GetNodesY());
726 for (
unsigned int m = 0; m < mVol.field[n].size(); m++)
727 mVol.field[n][m].resize(mVol.mesh.GetNodesZ());
730 RESTDebug <<
"TRestAxionMagneticField::LoadMagneticFieldData. Printing first 5 data rows" <<
RESTendl;
731 for (
unsigned int n = 0; n < data.size(); n++) {
735 Int_t nX = mVol.mesh.GetNodeX((Int_t)(data[n][0] + mVol.mesh.GetNetSizeX() / 2.),
true);
736 Int_t nY = mVol.mesh.GetNodeY((Int_t)(data[n][1] + mVol.mesh.GetNetSizeY() / 2.),
true);
737 Int_t nZ = mVol.mesh.GetNodeZ((Int_t)(data[n][2] + mVol.mesh.GetNetSizeZ() / 2.),
true);
740 RESTDebug <<
"X: " << data[n][0] <<
" Y: " << data[n][1] <<
" Z: " << data[n][2] <<
RESTendl;
741 RESTDebug <<
"absX: " << data[n][0] + mVol.position.X()
742 <<
" absY: " << data[n][1] + mVol.position.Y()
743 <<
" absZ: " << data[n][2] + mVol.position.Z() <<
RESTendl;
744 RESTDebug <<
"nX: " << nX <<
" nY: " << nY <<
" nZ: " << nZ <<
RESTendl;
745 RESTDebug <<
"Bx: " << data[n][3] <<
" By: " << data[n][4] <<
" Bz: " << data[n][5] <<
RESTendl;
749 if (mVol.field[nX][nY][nZ] != TVector3(0.0, 0.0, 0.0)) {
750 RESTWarning <<
"X: " << data[n][0] <<
" Y: " << data[n][1] <<
" Z: " << data[n][2] <<
RESTendl;
751 RESTWarning <<
"nX: " << nX <<
" nY: " << nY <<
" nZ: " << nZ <<
RESTendl;
752 RESTWarning <<
"WARNING: field[nX][nY][nZ] element not equal to initial value (0, 0, 0) !!"
754 RESTWarning <<
"It has value: "
755 <<
"mVol.field[" << nX <<
"][" << nY <<
"][" << nZ <<
"] = ("
756 << mVol.field[nX][nY][nZ].X() <<
" , " << mVol.field[nX][nY][nZ].Y() <<
" , "
757 << mVol.field[nX][nY][nZ].Z() <<
")" <<
RESTendl;
758 RESTWarning <<
"Values to write: "
759 <<
"Bx: " << data[n][3] <<
" By: " << data[n][4] <<
" Bz: " << data[n][5] <<
RESTendl
762 this->
SetError(
"There was a problem assigning the field matrix!");
766 mVol.field[nX][nY][nZ] = TVector3(data[n][3], data[n][4], data[n][5]);
776 for (
unsigned int n = 0; n <
fPositions.size(); n++) {
779 RESTDebug <<
"Full path : " << fullPathName <<
RESTendl;
781 if (
fFileNames[n] !=
"none" && fullPathName ==
"") {
782 RESTError <<
"TRestAxionMagneticField::LoadMagneticVolumes. File " <<
fFileNames[n]
785 <<
"REST will look for this file at any path given by <searchPath at globals definitions"
790 std::vector<std::vector<Float_t>> fieldData;
792 if (fullPathName.find(
".dat") != string::npos) {
793 RESTDebug <<
"Reading ASCII format" <<
RESTendl;
795 RESTError <<
"Problem reading file : " << fullPathName <<
RESTendl;
799 if (fullPathName.find(
".bin") != string::npos) {
800 RESTDebug <<
"Reading binary format" <<
RESTendl;
802 RESTError <<
"Problem reading file : " << fullPathName <<
RESTendl;
808 RESTError <<
"Filename : " << fullPathName <<
RESTendl;
809 RESTError <<
"File format not recognized!" <<
RESTendl;
813 if (
fFileNames[n] !=
"none" && fieldData.size() < 2) {
814 RESTError <<
"Field data size is no more than 2 grid points!" <<
RESTendl;
815 RESTError <<
"Filename : " << fullPathName <<
RESTendl;
816 RESTError <<
"Probably something went wrong loading the file" <<
RESTendl;
825 if (fieldData.size() > 0) {
826 RESTDebug <<
"Reading max boundary values" <<
RESTendl;
832 if (
fBoundMax[n] != TVector3(xMax, yMax, zMax)) {
833 RESTWarning <<
"Volume : " << n <<
RESTendl;
834 RESTWarning <<
"boundMax was defined in RML but does not match the field map boundaries!"
836 RESTWarning <<
"Max. Field map boundaries : (" << xMax <<
", " << yMax <<
", " << zMax
841 RESTDebug <<
"Reading min boundary values" <<
RESTendl;
847 if (-
fBoundMax[n] != TVector3(xMin, yMin, zMin)) {
848 RESTWarning <<
"Volume : " << n <<
RESTendl;
849 RESTWarning <<
"boundMax was defined in RML but does not match the field map boundaries"
851 RESTWarning <<
"Min. Field map boundaries : (" << xMin <<
", " << yMin <<
", " << zMin
855 fBoundMax[n] = TVector3(xMax, yMax, zMax);
857 RESTDebug <<
"Reading mesh size" <<
RESTendl;
863 if (
fMeshSize[n] != TVector3(meshSizeX, meshSizeY, meshSizeZ)) {
864 RESTWarning <<
"Volume : " << n <<
RESTendl;
866 <<
"MeshSize was defined in RML but does not match the mesh size deduced from "
869 RESTWarning <<
"Mesh size : (" << meshSizeX <<
", " << meshSizeY <<
", " << meshSizeZ
873 fMeshSize[n] = TVector3(meshSizeX, meshSizeY, meshSizeZ);
877 RESTDebug <<
"Reading magnetic field map" <<
RESTendl;
878 RESTDebug <<
"--------------------------" <<
RESTendl;
880 RESTDebug <<
"Full path : " << fullPathName <<
RESTendl;
882 RESTDebug <<
"Boundaries" <<
RESTendl;
883 RESTDebug <<
"xMin: " << xMin <<
" yMin: " << yMin <<
" zMin: " << zMin <<
RESTendl;
884 RESTDebug <<
"xMax: " << xMax <<
" yMax: " << yMax <<
" zMax: " << zMax <<
RESTendl;
885 RESTDebug <<
"Mesh size" <<
RESTendl;
887 RESTDebug <<
"sX: " << meshSizeX <<
" sY: " << meshSizeY <<
" sZ: " << meshSizeZ <<
RESTendl;
889 if (fieldData.size() > 4) {
890 RESTDebug <<
"Printing beginning of magnetic file table : " << fieldData.size() <<
RESTendl;
893 RESTDebug <<
"The data file contains no field map" <<
RESTendl;
899 Int_t nx = (Int_t)(2 * xMax / meshSizeX) + 1;
900 Int_t ny = (Int_t)(2 * yMax / meshSizeY) + 1;
901 Int_t nz = (Int_t)(2 * zMax / meshSizeZ) + 1;
907 restMesh.
SetSize(2 * xMax, 2 * yMax, 2 * zMax);
915 MagneticFieldVolume mVolume;
917 mVolume.mesh = restMesh;
922 RESTError <<
"The bounding box was not defined for volume " << n <<
"!" <<
RESTendl;
923 RESTError <<
"Please review RML configuration for TRestAxionMagneticField" <<
RESTendl;
925 }
else if (
fMeshSize[n] == TVector3(0, 0, 0)) {
926 RESTError <<
"The mesh grid size was not defined for volume " << n <<
"!" <<
RESTendl;
927 RESTError <<
"Please review RML configuration for TRestAxionMagneticField" <<
RESTendl;
934 RESTError <<
"TRestAxionMagneticField::LoadMagneticVolumes. Volumes overlap!" <<
RESTendl;
941 RESTDebug <<
"Finished loading magnetic volumes" <<
RESTendl;
964 RESTWarning <<
"TRestAxionMagneticField::GetMagneticField position (" << pos.X() <<
", "
965 << pos.Y() <<
", " << pos.Z() <<
") is outside any volume" <<
RESTendl;
966 return TVector3(0, 0, 0);
974 Int_t nX_1, nY_1, nZ_1;
1004 xd = (pos.X() - x0) / (x1 - x0);
1005 if ((xd < -0.00001) || (xd > 1.00001))
1006 RESTWarning <<
"TRestAxionMagneticField::GetMagneticField Error: xd NOT between 0 and 1"
1015 yd = (pos.Y() - y0) / (y1 - y0);
1016 if ((yd < -0.00001) || (yd > 1.00001))
1017 RESTWarning <<
"TRestAxionMagneticField::GetMagneticField Error: yd NOT between 0 and 1"
1026 zd = (pos.Z() - z0) / (z1 - z0);
1027 if ((zd < -0.00001) || (zd > 1.00001))
1028 RESTWarning <<
"TRestAxionMagneticField::GetMagneticField Error: zd NOT between 0 and 1"
1032 TVector3 C00 = C000 * (1.0 - xd) + C100 * xd;
1033 TVector3 C01 = C001 * (1.0 - xd) + C101 * xd;
1034 TVector3 C10 = C010 * (1.0 - xd) + C110 * xd;
1035 TVector3 C11 = C011 * (1.0 - xd) + C111 * xd;
1038 TVector3 C0 = C00 * (1.0 - yd) + C10 * yd;
1039 TVector3 C1 = C01 * (1.0 - yd) + C11 * yd;
1042 TVector3 C = C0 * (1.0 - zd) + C1 * zd;
1044 RESTDebug <<
"position = (" << pos.X() <<
", " << pos.Y() <<
", " << pos.Z() <<
") ";
1045 RESTDebug <<
"nX = " << nX <<
" nY = " << nY <<
" nZ = " << nZ <<
" nX_1 = " << nX_1
1047 RESTDebug <<
"C000 = (" << C000.X() <<
", " << C000.Y() <<
", " << C000.Z() <<
")" <<
RESTendl
1049 RESTDebug <<
"C100 = (" << C100.X() <<
", " << C100.Y() <<
", " << C100.Z() <<
")" <<
RESTendl
1051 RESTDebug <<
"C010 = (" << C010.X() <<
", " << C010.Y() <<
", " << C010.Z() <<
")" <<
RESTendl
1053 RESTDebug <<
"C110 = (" << C110.X() <<
", " << C110.Y() <<
", " << C110.Z() <<
")" <<
RESTendl
1055 RESTDebug <<
"C001 = (" << C001.X() <<
", " << C001.Y() <<
", " << C001.Z() <<
")" <<
RESTendl
1057 RESTDebug <<
"C101 = (" << C101.X() <<
", " << C101.Y() <<
", " << C101.Z() <<
")" <<
RESTendl
1059 RESTDebug <<
"C011 = (" << C011.X() <<
", " << C011.Y() <<
", " << C011.Z() <<
")" <<
RESTendl
1061 RESTDebug <<
"C111 = (" << C111.X() <<
", " << C111.Y() <<
", " << C111.Z() <<
")" <<
RESTendl
1063 RESTDebug <<
" -------------------------------------------------------" <<
RESTendl;
1064 RESTDebug <<
"C00 = (" << C00.X() <<
", " << C00.Y() <<
", " << C00.Z() <<
")" <<
RESTendl
1066 RESTDebug <<
"C01 = (" << C01.X() <<
", " << C01.Y() <<
", " << C01.Z() <<
")" <<
RESTendl
1068 RESTDebug <<
"C10 = (" << C10.X() <<
", " << C10.Y() <<
", " << C10.Z() <<
")" <<
RESTendl
1070 RESTDebug <<
"C11 = (" << C11.X() <<
", " << C11.Y() <<
", " << C11.Z() <<
")" <<
RESTendl
1072 RESTDebug <<
" -------------------------------------------------------" <<
RESTendl;
1073 RESTDebug <<
"C0 = (" << C0.X() <<
", " << C0.Y() <<
", " << C0.Z() <<
")" <<
RESTendl <<
RESTendl;
1074 RESTDebug <<
"C1 = (" << C1.X() <<
", " << C1.Y() <<
", " << C1.Z() <<
")" <<
RESTendl <<
RESTendl;
1075 RESTDebug <<
" -------------------------------------------------------" <<
RESTendl;
1076 RESTDebug <<
"C = (" << C.X() <<
", " << C.Y() <<
", " << C.Z() <<
")" <<
RESTendl <<
RESTendl;
1088 if (newMapSize.X() == 0 || newMapSize.Y() == 0 || newMapSize.Z() == 0) {
1089 RESTError <<
"TRestAxionMagneticField::ReMap. The mesh granularity cannot be 0" <<
RESTendl;
1090 RESTError <<
"Remapping will not take effect" <<
RESTendl;
1094 Double_t remainder = std::fmod(newMapSize.X(),
fMeshSize[n].X()) +
1095 std::fmod(newMapSize.Y(),
fMeshSize[n].Y()) +
1096 std::fmod(newMapSize.Z(),
fMeshSize[n].Z());
1097 if (remainder != 0) {
1098 RESTError <<
"TRestAxionMagneticField::ReMap. The field cannot be remapped." <<
RESTendl;
1099 RESTError <<
"The new mesh granularity must be a multiple of the existing granularity." <<
RESTendl;
1100 RESTError <<
"Present mesh size : (" <<
fMeshSize[n].X() <<
", " <<
fMeshSize[n].Y() <<
", "
1102 RESTError <<
"Requested mesh size : (" << newMapSize.X() <<
", " << newMapSize.Y() <<
", "
1103 << newMapSize.Z() <<
")" <<
RESTendl;
1104 RESTError <<
"Remapping will not take effect" <<
RESTendl;
1108 Int_t scaleX = (Int_t)(newMapSize.X() /
fMeshSize[n].X());
1109 Int_t scaleY = (Int_t)(newMapSize.Y() /
fMeshSize[n].Y());
1110 Int_t scaleZ = (Int_t)(newMapSize.Z() /
fMeshSize[n].Z());
1116 for (Int_t nx = 0; nx < newNodesX; nx++)
1117 for (Int_t ny = 0; ny < newNodesY; ny++)
1118 for (Int_t nz = 0; nz < newNodesZ; nz++)
1166 RESTWarning <<
"TRestAxionMagneticField::GetVolumePosition. Id : " <<
id <<
" out of range!"
1169 return TVector3(0, 0, 0);
1193 Double_t dl, Int_t Nmax) {
1194 Double_t length = (to - from).Mag();
1198 if (length / dl > Nmax) {
1199 diff = length / Nmax;
1200 RESTWarning <<
"TRestAxionMagneticField::GetTransversalComponentAlongPath. Nmax reached!"
1202 RESTWarning <<
"Nmax = " << Nmax <<
RESTendl;
1203 RESTWarning <<
"Adjusting differential step to : " << diff <<
" mm" <<
RESTendl;
1207 TVector3 direction = (to - from).Unit();
1209 std::vector<Double_t> Bt;
1210 for (Double_t d = 0; d < length; d += diff) {
1224 if (trackBounds.size() != 2) {
1231 fTrackLength = (trackBounds[1] - trackBounds[0]).Mag() - 1;
1263 for (
auto& b : Bt) Bavg += b;
1265 if (Bt.size() > 0)
return Bavg / Bt.size();
1267 RESTError <<
"TRestAxionMagneticField::GetTransversalFieldAverage. Lenght is zero!" <<
RESTendl;
1284 Double_t length = (to - from).Mag();
1288 if (length / dl > Nmax) {
1289 diff = length / Nmax;
1290 RESTWarning <<
"TRestAxionMagneticField::GetFieldAverageTransverseVector Nmax reached!"
1292 RESTWarning <<
"Nmax = " << Nmax <<
RESTendl;
1293 RESTWarning <<
"Adjusting differential step to : " << diff <<
" mm" <<
RESTendl;
1297 TVector3 direction = (to - from).Unit();
1298 TVector3 Bavg = TVector3(0.0, 0.0, 0.0);
1299 TVector3 BTavg = TVector3(0.0, 0.0, 0.0);
1300 Int_t numberofpoints = 0;
1302 for (Double_t d = 0; d <= length; d += diff) {
1304 numberofpoints = numberofpoints + 1;
1307 if ((length > 0) && (numberofpoints > 0)) {
1308 Bavg = Bavg * (1.0 / numberofpoints);
1310 Bavg - (Bavg * direction) *
1312 RESTDebug <<
"B average vector = (" << Bavg.x() <<
", " << Bavg.y() <<
", " << Bavg.z() <<
")"
1314 RESTDebug <<
"Transverse B average vector = (" << BTavg.x() <<
", " << BTavg.y() <<
", " << BTavg.z()
1318 RESTError <<
"TRestAxionMagneticField::GetTransversalFieldAverage. Lenght is zero!" <<
RESTendl;
1319 return TVector3(0.0, 0.0, 0.0);
1331 Int_t nx = mVol.mesh.GetNodeX(pos.X());
1332 Int_t ny = mVol.mesh.GetNodeY(pos.Y());
1333 Int_t nz = mVol.mesh.GetNodeZ(pos.Z());
1334 return TVector3(nx, ny, nz);
1341 RESTDebug <<
"Checking overlaps" <<
RESTendl;
1344 if (m == n)
continue;
1345 RESTDebug <<
"Volume : " << m <<
RESTendl;
1348 RESTDebug <<
"Relative bottom vertex : (" << b.X() <<
", " << b.Y() <<
", " << b.Z() <<
")"
1353 RESTDebug <<
"Relative top vertex : (" << t.X() <<
", " << t.Y() <<
", " << t.Z() <<
")"
1377 std::vector<TVector3> boundaries;
1379 if (vol) boundaries = vol->mesh.GetTrackBoundaries(pos, dir);
1395 Double_t precision, Int_t
id) {
1397 if (volumeBoundaries.size() != 2)
return volumeBoundaries;
1402 if (!vol)
return volumeBoundaries;
1406 TVector3 unit = dir.Unit();
1407 std::vector<TVector3> fieldBoundaries;
1409 TVector3 in = volumeBoundaries[0];
1412 if (((volumeBoundaries[1] - in) * dir) > 0)
1413 fieldBoundaries.push_back(in);
1415 return fieldBoundaries;
1417 TVector3 out = volumeBoundaries[1];
1419 (((out - in) * dir) > 0))
1421 if ((((volumeBoundaries[0] - out) * dir) < 0) && (((out - in) * dir) > 0))
1422 fieldBoundaries.push_back(out);
1424 return fieldBoundaries;
1426 return fieldBoundaries;
1435 auto magVolumeDef =
GetElement(
"addMagneticVolume");
1436 while (magVolumeDef) {
1438 if (filename ==
"Not defined")
1443 TVector3 position = Get3DVectorParameterWithUnits(
"position", magVolumeDef);
1444 if (position == TVector3(-1, -1, -1))
1449 TVector3 field = Get3DVectorParameterWithUnits(
"field", magVolumeDef);
1450 if (field == TVector3(-1, -1, -1))
1455 TVector3 boundMax = Get3DVectorParameterWithUnits(
"boundMax", magVolumeDef);
1456 if (boundMax == TVector3(-1, -1, -1))
1461 TVector3 meshSize = Get3DVectorParameterWithUnits(
"meshSize", magVolumeDef);
1462 if (meshSize == TVector3(-1, -1, -1))
1468 if (type ==
"NO_SUCH_PARA")
1475 RESTWarning <<
"Mesh type is cylinder. But X and Y inside boundMax are not the same!" <<
RESTendl;
1476 RESTWarning <<
"Making second bound component Y equal to the X bound component!" <<
RESTendl;
1480 RESTDebug <<
"Reading new magnetic volume" <<
RESTendl;
1482 RESTDebug <<
"Filename : " << filename <<
RESTendl;
1483 RESTDebug <<
"Position: ( " << position.X() <<
", " << position.Y() <<
", " << position.Z() <<
") mm"
1485 RESTDebug <<
"Field: ( " << field.X() <<
", " << field.Y() <<
", " << field.Z() <<
") T" <<
RESTendl;
1486 RESTDebug <<
"Max bounding box ( " << boundMax.X() <<
", " << boundMax.Y() <<
", " << boundMax.Z()
1488 RESTDebug <<
"Mesh size ( " << meshSize.X() <<
", " << meshSize.Y() <<
", " << meshSize.Z() <<
")"
1506 if (
fReMap != TVector3(0, 0, 0)) {
1507 RESTMetadata <<
"Fields original mesh size has been remapped" <<
RESTendl;
1512 RESTMetadata <<
" ------------------------------------------------ " <<
RESTendl;
1514 if (p > 0) RESTMetadata <<
" ------------------------------------------------ " <<
RESTendl;
1524 Double_t xMin = centerX - halfSizeX;
1525 Double_t yMin = centerY - halfSizeY;
1526 Double_t zMin = centerZ - halfSizeZ;
1528 Double_t xMax = centerX + halfSizeX;
1529 Double_t yMax = centerY + halfSizeY;
1530 Double_t zMax = centerZ + halfSizeZ;
1532 RESTMetadata <<
"* Volume " << p <<
" centered at (" << centerX <<
"," << centerY <<
"," << centerZ
1534 RESTMetadata <<
" - Grid mesh element size. X: " <<
fMeshSize[p].X() <<
"mm "
1541 RESTMetadata <<
" - Bounds : " <<
RESTendl;
1542 RESTMetadata <<
" xmin : " << xMin <<
" mm , xmax : " << xMax <<
" mm" <<
RESTendl;
1543 RESTMetadata <<
" ymin : " << yMin <<
" mm, ymax : " << yMax <<
" mm" <<
RESTendl;
1544 RESTMetadata <<
" zmin : " << zMin <<
" mm, zmax : " << zMax <<
" mm" <<
RESTendl;
1547 RESTMetadata <<
"+++++++++++++++++++++++++++++++++++++++++++++++++" <<
RESTendl;
A class to load magnetic field maps and evaluate the field on those maps including interpolation.
TVector3 GetVolumeCenter(Int_t id)
it returns the volume position (or center) for the given volume id.
void PrintMetadata()
Prints on screen the information about the metadata members of TRestAxionMagneticField.
TVector3 GetVolumePosition(Int_t id)
it returns the volume position (or center) for the given volume id.
TVector3 fTrackDirection
The track direction used to parameterize the field along a track.
void InitFromConfigFile()
Initialization of TRestAxionMagnetic field members through a RML file.
Double_t fTrackLength
The total length of the track which defines the limit for field parameterization.
void LoadMagneticVolumes()
It will load the magnetic field data from the data filenames specified at the RML definition.
std::vector< TVector3 > fConstantField
A constant field component that will be added to the field map.
std::vector< TVector3 > fPositions
The absolute position of each of the magnetic volumes defined in this class.
void SetTrack(const TVector3 &position, const TVector3 &direction)
It initializes the field track boundaries data members of this class using a track position and direc...
TVector3 fReMap
A vector that defines the new mesh cell volume. It will re-scale the original fMeshSize.
std::vector< TVector3 > GetFieldBoundaries(TVector3 pos, TVector3 dir, Double_t precision=0, Int_t id=0)
Finds the in/out particle trajectory boundaries for a particular magnetic region, similar to the meth...
unsigned int GetNumberOfVolumes()
The number of magnetic volumes loaded into the object.
Bool_t CheckOverlaps()
It will return true if the magnetic the regions overlap.
TVector3 GetFieldAverageTransverseVector(TVector3 from, TVector3 to, Double_t dl=10., Int_t Nmax=0)
It returns the transverse component of the average magnetic field vector calculated along the line th...
TCanvas * DrawTracks(TVector3 vanishingPoint, Int_t divisions, Int_t volId=0)
A method that creates a canvas where tracks traversing the magnetic volume are drawm together with th...
TRestAxionMagneticField()
Default constructor.
std::vector< TVector3 > GetVolumeBoundaries(TVector3 pos, TVector3 dir, Int_t id=0)
Finds the in/out particle trajectory boundaries for a particular magnetic region bounding box.
void ReMap(const size_t &n, const TVector3 &newMapSize)
It allows to remap the magnetic field to a larger mesh size. The new mesh size granularity must be pr...
Int_t GetVolumeIndex(TVector3 pos)
It returns the corresponding volume index at the given position. If not found it will return -1.
std::vector< TVector3 > fBoundMax
A vector to store the maximum bounding box values.
TCanvas * DrawHistogram(TString projection, TString Bcomp, Int_t volIndex=-1, Double_t step=-1, TString style="COLZ0", Double_t depth=-100010.0)
A method that creates a canvas where magnetic field map is drawn.
Bool_t IsFieldConstant(Int_t id)
It returns true if no magnetic field map was loaded for that volume.
MagneticFieldVolume * GetMagneticVolume(Int_t id)
It returns a pointer to the corresponding magnetic volume id.
TVector3 fTrackStart
The start track position used to parameterize the field along a track.
TVector3 GetMagneticVolumeNode(MagneticFieldVolume mVol, TVector3 pos)
It returns the corresponding mesh node in the magnetic volume.
TVector3 GetMagneticField(Double_t x, Double_t y, Double_t z)
It returns the magnetic field vector at x,y,z.
std::vector< TVector3 > fMeshSize
std::vector< MagneticFieldVolume > fMagneticFieldVolumes
A magnetic field volume structure to store field data and mesh.
std::vector< Double_t > GetTransversalComponentAlongPath(TVector3 from, TVector3 to, Double_t dl=1., Int_t Nmax=0)
It returns a vector describing the transversal magnetic field component between from and to positions...
std::vector< TString > fMeshType
The type of the mesh used (default is cylindrical)
void LoadMagneticFieldData(MagneticFieldVolume &mVol, std::vector< std::vector< Float_t > > data)
A method to help loading magnetic field data, as x,y,z,Bx,By,Bz into a magnetic volume definition usi...
Double_t GetTransversalComponent(TVector3 position, TVector3 direction)
It returns the intensity of the transversal magnetic field component for the defined propagation dire...
std::vector< std::string > fFileNames
The name of the filenames containing the field data.
TH2D * fHisto
A helper histogram to plot the field.
TCanvas * fCanvas
A canvas to insert the histogram drawing.
~TRestAxionMagneticField()
Default destructor.
Bool_t IsInside(TVector3 pos)
It returns true if the given position is found inside a magnetic volume. False otherwise.
void Initialize()
Initialization of TRestAxionMagneticField members.
Double_t GetTransversalFieldAverage(TVector3 from, TVector3 to, Double_t dl=1., Int_t Nmax=0)
It returns the average of the transversal magnetic field intensity between the 3-d coordinates from a...
Double_t GetTransversalComponentInParametricTrack(Double_t x)
It will return the transversal magnetic field component evaluated at a parametric distance x (given b...
Bool_t FieldLoaded()
This private method returns true if the magnetic field volumes loaded are the same as the volumes def...
A basic class inheriting from TObject to help creating a node grid definition.
void SetSize(Double_t sX, Double_t sY, Double_t sZ)
Sets the origin of the bounding-box and initializes the nodes vector to zero.
void SetOrigin(Double_t oX, Double_t oY, Double_t oZ)
Sets the origin of the bounding-box and initializes the nodes vector to zero.
void SetCylindrical(Bool_t v)
Sets the coordinate system to cylindrical.
void SetNodes(Int_t nX, Int_t nY, Int_t nZ)
Sets the number of nodes and initializes the nodes vector to zero.
@ REST_Extreme
show everything
@ REST_Info
+show most of the information for each steps
@ REST_Debug
+show the defined debug messages
This namespace serves to define physics constants and other basic physical operations.
TVector3 MoveToPlane(const TVector3 &pos, const TVector3 &dir, const TVector3 &n, const TVector3 &a)
This method will translate the vector with direction dir starting at position pos to the plane define...
TVector3 MoveByDistanceFast(const TVector3 &pos, const TVector3 &dir, Double_t d)
This method transports a position pos by a distance d in the direction defined by dir....
Int_t GetChar(std::string hint="Press a KEY to continue ...")
Helps to pause the program, printing a message before pausing.