30 #include <THistPainter.h>
40 void help_bfield(
int argc,
char** argv) {
42 "Usage: DD4hep_DrawBField -arg [-arg] \n"
43 " The plugin implicitly assumes that the geometry is already loaded. \n"
44 " -area <string> Define area for which the B-field will be drawn\n"
45 " -nx: <number> Number of bins in X direction \n"
46 " -ny: <number> Number of bins in Y direction \n"
47 " -dx: <range> Definition of the range in X \n"
48 " -dy: <range> Definition of the range in Y \n"
49 " -dz: <range> Definition of the range in Z \n"
50 " Range definition as tuple: min,max \n"
51 " min: lower boundary \n"
52 " max: upper boundary \n"
53 "\tArguments given: " << arguments(argc,argv) << std::endl << std::flush;
58 double rmin=0e0, rmax=0e0;
65 range_t get_range(
const std::string& s,
int argc,
char** argv) {
69 for(std::size_t i=0; i<s.length()+1; ++i) {
70 char c = s.c_str()[i];
71 if ( c ==
',' || i == s.length() ) {
80 except(
"",
"+++ Too many value for range descriptor provided: %s", s.c_str());
90 help_bfield(argc, argv);
95 class MyHistPainter :
public THistPainter {
97 using THistPainter::THistPainter;
98 TH2* paintArrows(TH2* histo,
const std::vector<field_t>& points) {
99 fYaxis->SetTitle(
"Y coordinate [cm]");
100 fXaxis->SetTitle(
"X coordinate [cm]");
101 for(
const auto& p : points) {
102 double strength2 = p.bfield.mag2();
103 if ( strength2 > 1e-8 ) {
104 double strength = sqrt(p.bfield.X()*p.bfield.X()+p.bfield.Y()*p.bfield.Y());
105 int ix = fXaxis->FindBin(p.position.X());
106 int iy = fYaxis->FindBin(p.position.Y());
107 double xlo = fXaxis->GetBinLowEdge(ix);
108 double xhi = fXaxis->GetBinLowEdge(ix+1);
109 double ylo = fYaxis->GetBinLowEdge(iy);
110 double yhi = fYaxis->GetBinLowEdge(iy+1);
111 auto norm_field = p.bfield * ((xhi-xlo) / strength);
112 double x1 = xlo + (xhi-xlo)/2.0;
113 double x2 = x1 + norm_field.X();
114 double y1 = ylo + (yhi-ylo)/2.0;
115 double y2 = y1 + norm_field.Y();
116 auto* arrow =
new TArrow(x1, y1, x2, y2, 0.015,
"|>");
118 arrow->SetFillColor(kRed);
119 arrow->SetLineColor(kRed);
121 histo->Fill(p.position.X(), p.position.X(), strength);
122 ::fprintf(stdout,
"Arrow %+15.8e %+15.8e %+15.8e %+15.8e %+15.8e %+15.8e\n",
123 x1, y1, x2, y2, x2-x1, y2-y1);
145 static long draw_bfield(
Detector& description,
int argc,
char** argv) {
146 std::vector<std::string> srange_x, srange_y, srange_z;
147 std::size_t nbin_x = 100, nbin_y = 100, nbin_z = 1;
149 double z_value = 0e0;
152 printout(WARNING,
"DrawBField",
"This is a TEST. It does not function properly!");
154 for(
int i = 0; i < argc && argv[i]; ++i) {
155 if ( 0 == ::strncmp(
"-rx",argv[i],4) )
156 srange_x.push_back(argv[++i]);
157 else if ( 0 == ::strncmp(
"-ry",argv[i],3) )
158 srange_y.push_back(argv[++i]);
159 else if ( 0 == ::strncmp(
"-rz",argv[i],3) )
160 srange_z.push_back(argv[++i]);
161 else if ( 0 == ::strncmp(
"-nx",argv[i],3) )
163 else if ( 0 == ::strncmp(
"-ny",argv[i],3) )
165 else if ( 0 == ::strncmp(
"-nz",argv[i],3) )
167 else if ( 0 == ::strncmp(
"-z",argv[i],2) )
169 else if ( 0 == ::strncmp(
"-draw",argv[i],4) )
171 else if ( 0 == ::strncmp(
"-output",argv[i],4) )
173 else if ( 0 == ::strncmp(
"-help",argv[i],2) )
174 help_bfield(argc, argv);
176 if ( srange_x.empty() || srange_y.empty() ) {
177 help_bfield(argc, argv);
179 std::vector<range_t> range_x, range_y, range_z;
180 for(
const auto& r : srange_x) {
181 range_t rg = get_range(r, argc, argv);
182 range_x.push_back(rg);
184 for(
const auto& r : srange_y) {
185 range_t rg = get_range(r, argc, argv);
186 range_y.push_back(rg);
188 for(
const auto& r : srange_z) {
189 range_t rg = get_range(r, argc, argv);
190 range_z.push_back(rg);
193 double ma = std::numeric_limits<double>::max();
194 range_t envelope_x { ma, -ma };
195 range_t envelope_y { ma, -ma };
196 range_t envelope_z { ma, -ma };
197 for(
const auto& range : range_x ) {
198 envelope_x.rmin = std::min(range.rmin, envelope_x.rmin);
199 envelope_x.rmax = std::max(range.rmax, envelope_x.rmax);
201 for(
const auto& range : range_y ) {
202 envelope_y.rmin = std::min(range.rmin, envelope_y.rmin);
203 envelope_y.rmax = std::max(range.rmax, envelope_y.rmax);
205 for(
const auto& range : range_z ) {
206 envelope_z.rmin = std::min(range.rmin, envelope_z.rmin);
207 envelope_z.rmax = std::max(range.rmax, envelope_z.rmax);
210 double dx = (envelope_x.rmax - envelope_x.rmin) /
double(nbin_x);
211 double dy = (envelope_y.rmax - envelope_y.rmin) /
double(nbin_y);
212 double dz = nbin_z == 1 ? 0e0 : (envelope_z.rmax - envelope_z.rmin) /
double(nbin_z);
213 printf(
"Range(x) min:%4ld bins %+15.8e cm max:%+15.8e cm dx:%+15.8e cm\n",
214 nbin_x, envelope_x.rmin/cm, envelope_x.rmax/cm, dx/cm);
215 printf(
"Range(y) min:%4ld bins %+15.8e cm max:%+15.8e cm dx:%+15.8e cm\n",
216 nbin_y, envelope_y.rmin/cm, envelope_y.rmax/cm, dy/cm);
217 if ( nbin_z > 1 ) printf(
"Range(z) min:%4ld bins %+15.8e cm max:%+15.8e cm dx:%+15.8e cm\n",
218 nbin_z, envelope_z.rmin/cm, envelope_z.rmax/cm, dz/cm);
220 FILE* out_file = ::fopen(output.empty() ?
"/dev/null" : output.c_str(),
"w");
221 ::fprintf(out_file,
"#######################################################################################################\n");
222 ::fprintf(out_file,
" x[cm] y[cm] z[cm] Bx[Tesla] By[Tesla] Bz[Tesla] \n");
223 std::vector<field_t> field_values;
224 for( std::size_t i = 0; i < nbin_x; ++i ) {
225 float x = envelope_x.rmin + double(i)*dx + dx/2e0;
226 for( std::size_t j = 0; j < nbin_y; ++j ) {
227 float y = envelope_y.rmin + double(j)*dy + dy/2e0;
228 for( std::size_t k = 0; k < nbin_z; ++k ) {
229 float z = nbin_z == 1 ? z_value : envelope_z.rmin + double(k)*dz + dz/2e0;
231 value.position = { x, y, z };
232 value.bfield = { 0e0, 0e0, 0e0 };
234 ::fprintf(out_file,
" %+15.8e %+15.8e %+15.8e %+15.8e %+15.8e %+15.8e\n",
235 value.position.X()/cm, value.position.Y()/cm, value.position.Z()/cm,
236 value.bfield.X()/dd4hep::tesla, value.bfield.Y()/dd4hep::tesla, value.bfield.Z()/dd4hep::tesla);
237 field_values.emplace_back(value);
243 if ( 0 == gApplication ) {
244 std::pair<int, char**> a(argc,argv);
245 gApplication =
new TRint(
"DD4hepRint", &a.first, a.second);
246 printout(INFO,
"DD4hepRint",
"++ Created ROOT interpreter instance for DD4hepUI.");
248 auto* histo =
new TH2F(
"Bfield",
"B-Field strength in Tesla",
249 nbin_x, envelope_x.rmin, envelope_x.rmax,
250 nbin_y, envelope_y.rmin, envelope_y.rmax);
252 paint.SetHistogram(histo);
253 TCanvas* c1 =
new TCanvas(
"B-Field");
254 c1->SetWindowSize(1000,1000);
256 histo->SetStats(kFALSE);
258 paint.paintArrows(histo, field_values);
259 histo->Draw(
"COLZ SAME");
262 if ( !gApplication->IsRunning() ) {