Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ChargeMapReader.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ChargeMapReader.cc
1 #include "ChargeMapReader.h"
2 
3 #include "MultiArray.h"
4 
5 #include <TAxis.h>
6 #include <TFile.h>
7 #include <TH2.h>
8 #include <TH3.h>
9 
10 #include <cassert>
11 #include <cmath>
12 #include <cstdio>
13 
14 #define DEBUG false
15 
17  : ChargeMapReader(20, 20.0, 78.0, 20, 0, 2 * M_PI, 40, -105.5, 105.5)
18 {
19  printf("made a new ChargeMapReader with default values -- cascading to next constructor\n");
20  return;
21 }
22 
23 ChargeMapReader::ChargeMapReader(int _nr, float _rmin, float _rmax, int _nphi, float _phimin, float _phimax, int _nz, float _zmin, float _zmax)
24 {
25  printf("made a new ChargeMapReader with defined values:\n %d %.2f %.2f\n %d %.2f %.2f\n %d %.2f %.2f\n",
26  _nr, _rmin, _rmax, _nphi, _phimin, _phimax, _nz, _zmin, _zmax);
27  SetOutputParameters(_nr, _rmin, _rmax, _nphi, _phimin, _phimax, _nz, _zmin, _zmax);
28  return;
29 }
30 
32 {
33  // printf("deleting histograms in ChargeMapReader\n");
34  // we don't explicitly malloc() anything, so we shouldn't need to free() anything.
35  return;
36 }
37 
38 bool ChargeMapReader::CanInterpolateAt(float r, float phi, float z)
39 {
40  return CanInterpolateAt(phi, r, z, hChargeDensity);
41 }
42 
43 // a convenient method to check whether it's safe to interpolate for a particular histogram.
44 bool ChargeMapReader::CanInterpolateAt(float x, float y, float z, TH3* h)
45 {
46  if (h == nullptr)
47  {
48  return false;
49  }
50  float pos[3] = {x, y, z};
51  // todo: is it worth keeping these values somewhere for ease of access?
52  TAxis* ax[3] = {nullptr, nullptr, nullptr};
53  ax[0] = h->GetXaxis();
54  ax[1] = h->GetYaxis();
55  ax[2] = h->GetZaxis();
56 
57  int nbins[3];
58  for (int i = 0; i < 3; i++)
59  {
60  nbins[i] = ax[i]->GetNbins(); // number of bins, not counting under and overflow.
61  if (nbins[i] == 1)
62  {
63  return false; // if there's only one non over/under bin, then no place is safe to interpolate.
64  }
65  }
66 
67  // 0 1 2 ... n-1 n n+1
68  // under|first| ..| .. | .. |last| over
69  for (int i = 0; i < 3; i++)
70  { // check each axis:
71  int axbin = ax[i]->FindBin(pos[i]);
72 
73  if (axbin < 1 || axbin > nbins[i])
74  {
75  return false; // before the first bin, or after the last bin
76  }
77  if (axbin > 1 && axbin < nbins[i])
78  {
79  continue; // if we're in a middle bin, we're fine on this axis.
80  }
81 
82  // now we need to check if we're in the safe parts of the first and last bins:
83  float low = ax[i]->GetBinLowEdge(axbin);
84  float high = ax[i]->GetBinUpEdge(axbin);
85  float binmid = 0.5 * (high + low);
86 
87  if (axbin == 1 && pos[i] <= binmid)
88  {
89  return false; // we're in the first bin, but below the midpoint, so we would interpolate out of bounds
90  }
91  if (axbin == nbins[i] && pos[i] >= binmid)
92  {
93  return false; // we're in the last bin, but above the midpoint, so we would interpolate out of bounds
94  }
95  }
96 
97  // if we get here, we are in the okay-range of all three axes.
98  return true;
99 }
100 
102 {
103  // fills the provided histogram with the data from the internal representation.
104 
105  // 0 1 2 ... n-1
106  // first| ..| .. | .. |last
107  float dphi, dr, dz; // bin widths in each dimension. Got too confusing to make these an array.
108  if (DEBUG)
109  {
110  printf("filling chargehistogram\n");
111  }
112 
113  dr = binWidth[0];
114  dphi = binWidth[1];
115  dz = binWidth[2];
116 
117  float phimid, zmid; // midpoints at each step.
118  int i[3];
119  for (i[0] = 0; i[0] < nBins[0]; i[0]++)
120  { // r
121  float rmid = lowerBound[0] + (i[0] + 0.5) * dr;
122  for (i[1] = 0; i[1] < nBins[1]; i[1]++)
123  { // phi
124  phimid = lowerBound[1] + (i[1] + 0.5) * dphi;
125  for (i[2] = 0; i[2] < nBins[2]; i[2]++)
126  { // z
127  zmid = lowerBound[2] + (i[2] + 0.5) * dz;
128  h->Fill(phimid, rmid, zmid, charge->Get(i[0], i[1], i[2]));
129  } // z
130  } // phi
131  } // r
132  return;
133 }
134 
136 {
137  // Builds the charge 3D array (internal representation) from the internal charge density map.
138  // either the density map has changed, or the binning of the output has changed (hopefully not the latter, because that's a very unusual thing to change mid-run.
139  // we want to rebuild the charge per bin of our output representation in any case. Generally, we will interpolate from the charge density that we know we have, but we need to be careful not to ask to interpolate in regions where that is not allowed.
140  if (DEBUG)
141  {
142  printf("regenerating charge array contents with axis scale=%1.2E and charge scale=%1.2E\n", inputAxisScale, inputChargeScale);
143  }
144  if (hChargeDensity == nullptr)
145  {
146  // we don't have charge information, so set everything to zeroes
147  printf("no charge data found. Setting all charges to 0.0\n");
148  charge->SetAll(0); // otherwise set the array to all zeroes.
149  return;
150  }
151 
152  // 0 1 2 ... n-1
153  // first| ..| .. | .. |last
154  float dphi, dr, dz; // internal rep bin widths in each dimension. Got too confusing to make these an array.
155  dr = binWidth[0];
156  dphi = binWidth[1];
157  dz = binWidth[2];
158  float dzhist, drhist;
159  dzhist = dz / inputAxisScale;
160  drhist = dr / inputAxisScale;
161 
162  float phimid, zmid; // position of the center of each fixed-width array bin, in the input histogram units
163  // note that since we computed density using the hist units, we must use those units for the volume term again here.
164  int i[3];
165  for (i[0] = 0; i[0] < nBins[0]; i[0]++)
166  { // r
167  float rmid = (lowerBound[0] + (i[0] + 0.5) * dr) / inputAxisScale;
168  // float rlow = (lowerBound[0] + dr * i[0]) / inputAxisScale;
169  float histBinVolume = dzhist * dphi * rmid * drhist; // volume of our output bin in histogram units.
170  // note that since we have equal bin widths, the volume term depends only on r.
171  // Q_bin=Density_ion_interp*bin_volume*(coulomb/ion)
172  float scaleFactor = histBinVolume * inputChargeScale; // hence the total scale factor is the volume term times the charge scale factor
173  for (i[1] = 0; i[1] < nBins[1]; i[1]++)
174  { // phi
175  phimid = lowerBound[1] + (i[1] + 0.5) * dphi;
176  for (i[2] = 0; i[2] < nBins[2]; i[2]++)
177  { // z
178  zmid = (lowerBound[2] + (i[2] + 0.5) * dz) / inputAxisScale;
179  float q = 0;
180  if (CanInterpolateAt(phimid, rmid, zmid, hChargeDensity))
181  { // interpolate if we can
182  if (false)
183  { // deep debug statements.
184  printf("function said we could interpolate at (r,phi,z)=(%.2f, %.2f,%.2f), bounds are:\n", rmid, phimid, zmid);
185  printf(" r: %.2f < %.2f < %.2f\n", hChargeDensity->GetYaxis()->GetXmin(), rmid, hChargeDensity->GetYaxis()->GetXmax());
186  printf(" p: %.2f < %.2f < %.2f\n", hChargeDensity->GetXaxis()->GetXmin(), phimid, hChargeDensity->GetXaxis()->GetXmax());
187  printf(" z: %.2f < %.2f < %.2f\n", hChargeDensity->GetZaxis()->GetXmin(), zmid, hChargeDensity->GetZaxis()->GetXmax());
188  }
189  q = scaleFactor * hChargeDensity->Interpolate(phimid, rmid, zmid);
190  }
191  else
192  { // otherwise, just take the central value and assume it's flat. Better than a zero.
193  q = scaleFactor * hChargeDensity->GetBinContent(hChargeDensity->FindBin(phimid, rmid, zmid));
194  }
195  if (false)
196  { // deep debug statements.
197  int global = hSourceCharge->FindBin(phimid, rmid, zmid);
198  if (CanInterpolateAt(phimid, rmid, zmid, hChargeDensity))
199  {
200  printf("density debug report (interp) (r,phi,z)=(%.2f, %.2f,%.2f), glob=%d, q_dens=%E", rmid, phimid, zmid, global, q);
201  printf(", density=%E, vol=%E", hChargeDensity->Interpolate(phimid, rmid, zmid), histBinVolume);
202  printf(", q_bin=%E, q_bin_coul=%E",
203  hSourceCharge->GetBinContent(hSourceCharge->FindBin(phimid, rmid, zmid)),
204  hSourceCharge->GetBinContent(hSourceCharge->FindBin(phimid, rmid, zmid)) * inputChargeScale);
205  printf(", q_interp=%E, q_bin_coul/vol=%E\n",
206  hSourceCharge->Interpolate(phimid, rmid, zmid),
207  hSourceCharge->GetBinContent(hSourceCharge->FindBin(phimid, rmid, zmid)) / histBinVolume);
208  }
209  else
210  {
211  printf("density debug report (getbin) (r,phi,z)=(%.2f, %.2f,%.2f), glob=%d, q_dens=%E", rmid, phimid, zmid, global, q);
212  printf(", density=%E, vol=%E", hChargeDensity->GetBinContent(hChargeDensity->FindBin(phimid, rmid, zmid)), histBinVolume);
213  printf(", q_bin=%E, q_bin_ions=%E",
214  hSourceCharge->GetBinContent(hSourceCharge->FindBin(phimid, rmid, zmid)),
215  hSourceCharge->GetBinContent(hSourceCharge->FindBin(phimid, rmid, zmid)) / inputChargeScale);
216  printf(", q_bin_ions/vol=%E\n",
217  hSourceCharge->GetBinContent(hSourceCharge->FindBin(phimid, rmid, zmid)) / scaleFactor);
218  }
219  }
220  charge->Set(i[0], i[1], i[2], q);
221 
222  } // z
223  } // phi
224  } // r
225 
226  if (DEBUG)
227  {
228  printf("done regenerating charge array contents\n");
229  }
230 
231  return;
232 }
233 
235 {
236  // assume the input map has changed, so we need to rebuild our internal representation of the density.
237  // this is done by cloning the SourceCharge histogram and dividing each bin in it by its volume
238  if (DEBUG)
239  {
240  printf("regenerating density histogram\n");
241  }
242 
243  // if we have one already, delete it.
244  if (hChargeDensity != nullptr)
245  {
246  if (DEBUG)
247  {
248  printf("deleting old density histogram\n");
249  }
250  delete hChargeDensity;
251  }
252  if (hSourceCharge == nullptr)
253  {
254  // the source data doesn't exist, so we will fail if we try to clone
255  printf("no source charge data file is open, or the histogram was not found.\n");
256  return;
257  }
258 
259  // clone this from the source histogram, which we assume is open.
260  hChargeDensity = static_cast<TH3*>(hSourceCharge->Clone("hChargeDensity"));
261  hChargeDensity->Reset();
262 
263  // then go through it, bin by bin, and replace each bin content with the corresponding density, so we can interpolate correctly.
264  // TODO: Does this mean we once again need 'guard' bins? Gross.
265 
266  TAxis* ax[3] = {nullptr, nullptr, nullptr};
267  ax[0] = hChargeDensity->GetXaxis();
268  ax[1] = hChargeDensity->GetYaxis();
269  ax[2] = hChargeDensity->GetZaxis();
270 
271  int nbins[3];
272  for (int i = 0; i < 3; i++)
273  {
274  nbins[i] = ax[i]->GetNbins(); // number of bins, not counting under and overflow.
275  }
276 
277  // 0 1 2 ... n-1 n n+1
278  // under|first| ..| .. | .. |last| over
279  int i[3];
280  float low[3], high[3];
281  float dr, dz; // bin widths in each dimension. Got too confusing to make these an array.
282  // note that all of this is done in the native units of the source data, specifically, the volume element is in hist units, not our internal units.
283 
284  for (i[0] = 1; i[0] <= nbins[0]; i[0]++)
285  { // phi
286  int a = 0;
287  low[a] = ax[a]->GetBinLowEdge(i[a]);
288  high[a] = ax[a]->GetBinUpEdge(i[a]);
289  float dphi = high[a] - low[a];
290  for (i[1] = 1; i[1] <= nbins[1]; i[1]++)
291  { // r
292  a = 1;
293  low[a] = ax[a]->GetBinLowEdge(i[a]);
294  high[a] = ax[a]->GetBinUpEdge(i[a]);
295  dr = high[a] - low[a];
296  float rphiterm = dphi * (low[1] + 0.5 * dr) * dr;
297  for (i[2] = 1; i[2] <= nbins[2]; i[2]++)
298  { // z
299  a = 2;
300  low[a] = ax[a]->GetBinLowEdge(i[a]);
301  high[a] = ax[a]->GetBinUpEdge(i[a]);
302  dz = high[a] - low[a];
303  // float volume=dz*dphi*(low[1]+0.5*dr)*dr;
304  float volume = dz * rphiterm;
305  int globalBin = hSourceCharge->GetBin(i[0], i[1], i[2]);
306  float q = hSourceCharge->GetBinContent(globalBin);
307  hChargeDensity->SetBinContent(globalBin, q / volume);
308  if (false)
309  { // deep debug statements.
310  printf("iprz=(%d,%d,%d),glob=%d", i[0], i[1], i[2], globalBin);
311  printf("edges=[%.2f,%.2f],[%.1f,%.1f],[%.1f,%f.1],", low[0], high[0], low[1], high[1], low[2], high[2]);
312  printf("\tq=%E,vol=%E,dens=%E\n", q, volume, hChargeDensity->GetBinContent(globalBin));
313  }
314  }
315  }
316  }
317  if (DEBUG)
318  {
319  printf("done regenerating density histogram\n");
320  }
321 
322  return;
323 }
324 
325 bool ChargeMapReader::ReadSourceCharge(const char* filename, const char* histname, float axisScale, float contentScale)
326 {
327  // load the charge-per-bin data from the specified file.
328  inputAxisScale = axisScale;
329  inputChargeScale = contentScale;
330  TFile* inputFile = TFile::Open(filename, "READ");
331  inputFile->GetObject(histname, hSourceCharge);
332  if (hSourceCharge == nullptr)
333  {
334  return false;
335  }
338  inputFile->Close();
339  // after this, the source histogram doesn't exist anymore.
340  return true;
341 }
342 
343 bool ChargeMapReader::ReadSourceCharge(TH3* sourceHist, float axisScale, float contentScale)
344 {
345  if (DEBUG)
346  {
347  printf("reading charge from %s\n", sourceHist->GetName());
348  }
349  inputAxisScale = axisScale;
350  inputChargeScale = contentScale;
351  hSourceCharge = sourceHist; // note that this means we don't own this histogram!
352  if (hSourceCharge == nullptr)
353  {
354  return false;
355  }
358 
359  if (DEBUG)
360  {
361  printf("done reading charge from %s\n", sourceHist->GetName());
362  }
363 
364  return true;
365 }
366 
367 bool ChargeMapReader::ReadSourceAdc(const char* adcfilename, const char* adchistname, const char* ibfgainfilename, const char* ibfgainhistname, float axisScale, float contentScale)
368 {
369  // load the adc-per-bin data from the specified file.
370  TFile* adcInputFile = TFile::Open(adcfilename, "READ");
371  TH3* hAdc = nullptr;
372  adcInputFile->GetObject(adchistname, hAdc);
373  if (hSourceCharge == nullptr)
374  {
375  printf("Source Charge hist or file %s not found!\n", adcfilename);
376  return false;
377  }
378  // load the conversion factor from adc sum to ibf
379  TFile* ibfGainInputFile = TFile::Open(ibfgainfilename, "READ");
380  TH2* hIbfGain = nullptr;
381  ibfGainInputFile->GetObject(ibfgainhistname, hIbfGain);
382  if (hIbfGain == nullptr)
383  {
384  printf("IBF Gain hist or file %s not found!\n", ibfgainfilename);
385  return false;
386  }
387 
388  // and then hand the task off to the next function
389  bool ret = ReadSourceAdc(hAdc, hIbfGain, axisScale, contentScale);
390  adcInputFile->Close();
391  // after this, the source histograms don't exist anymore.
392  return ret;
393 }
394 
395 bool ChargeMapReader::ReadSourceAdc(TH3* adcHist, TH2* gainHist, float axisScale, float contentScale)
396 {
397  if (DEBUG)
398  {
399  printf("reading ADCs from %s, ibfGain from %s\n", adcHist->GetName(), gainHist->GetName());
400  }
401  inputAxisScale = axisScale;
402  inputChargeScale = contentScale;
403  hSourceCharge = adcHist; // note that this means we don't own this histogram! It may disappear.
404  if (hSourceCharge == nullptr)
405  {
406  return false;
407  }
408 
409  // scale the voxels of the sourcecharge by the gainhist data.
410 
411  TAxis* ax[3] = {nullptr, nullptr, nullptr};
412  ax[0] = hSourceCharge->GetXaxis();
413  ax[1] = hSourceCharge->GetYaxis();
414  ax[2] = hSourceCharge->GetZaxis();
415 
416  int nbins[3];
417  for (int i = 0; i < 3; i++)
418  {
419  nbins[i] = ax[i]->GetNbins(); // number of bins, not counting under and overflow.
420  }
421 
422  // 0 1 2 ... n-1 n n+1
423  // under|first| ..| .. | .. |last| over
424  int i[3];
425 
426  for (i[0] = 1; i[0] <= nbins[0]; i[0]++)
427  { // phi
428  for (i[1] = 1; i[1] <= nbins[1]; i[1]++)
429  { // r
430  int globalBin2D = gainHist->GetBin(i[0], i[1]);
431  float scalefactor = gainHist->GetBinContent(globalBin2D);
432  for (i[2] = 1; i[2] <= nbins[2]; i[2]++)
433  { // z
434  int globalBin = hSourceCharge->GetBin(i[0], i[1], i[2]);
435  float q = hSourceCharge->GetBinContent(globalBin);
436  hSourceCharge->SetBinContent(globalBin, q * scalefactor);
437  if (false)
438  { // deep debug statements.
439  printf("applying gain to adc input: iprz=(%d,%d,%d), glob3d=%d, glob2d=%d, adc=%f, scale=%f\n", i[0], i[1], i[2], globalBin, globalBin2D, q, scalefactor);
440  }
441  } // z
442  } // r
443  } // phi
444  if (DEBUG)
445  {
446  printf("done converting adc hist to ions\n");
447  }
448 
451 
452  if (DEBUG)
453  {
454  printf("done converting ADCs from %s\n", adcHist->GetName());
455  }
456 
457  return true;
458 }
459 
460 bool ChargeMapReader::SetOutputParameters(int _nr, float _rmin, float _rmax, int _nphi, float _phimin, float _phimax, int _nz, float _zmin, float _zmax)
461 {
462  // change all the parameters of our output array and rebuild the array from scratch.
463  if (!(_rmax > _rmin) || !(_phimax > _phimin) || !(_zmax > _zmin))
464  {
465  return false; // the bounds are not well-ordered.
466  }
467  if (_nr < 1 || _nphi < 1 || _nz < 1)
468  {
469  return false; // must be at least one bin wide.
470  }
471 
472  nBins[0] = _nr;
473  nBins[1] = _nphi;
474  nBins[2] = _nz;
475  lowerBound[0] = _rmin;
476  lowerBound[1] = _phimin;
477  lowerBound[2] = _zmin;
478  upperBound[0] = _rmax;
479  upperBound[1] = _phimax;
480  upperBound[2] = _zmax;
481 
482  for (int i = 0; i < 3; i++)
483  {
484  binWidth[i] = (upperBound[i] - lowerBound[i]) / (1.0 * nBins[i]);
485  }
486 
487  // if the array exists, delete it.
488  if (charge != nullptr)
489  {
490  if (DEBUG)
491  {
492  printf("charge array existed. deleting\n");
493  }
494  delete charge;
495  charge = nullptr;
496  }
497  if (DEBUG)
498  {
499  printf("building new charge array\n");
500  }
501  if (DEBUG)
502  {
503  printf("should have %d elements\n", nBins[0] * nBins[1] * nBins[2]);
504  }
505 
506  charge = new MultiArray<float>(nBins[0], nBins[1], nBins[2]);
507 
508  if (hChargeDensity != nullptr)
509  {
510  if (DEBUG)
511  {
512  printf("charge density data exists, regenerating charge\n");
513  }
514  RegenerateCharge(); // fill the array with the charge data if available
515  }
516  else
517  {
518  charge->SetAll(0); // otherwise set the array to all zeroes.
519  }
520  if (DEBUG)
521  {
522  printf("finished building array\n");
523  }
524 
525  return true;
526 }
527 
528 bool ChargeMapReader::SetOutputBounds(float _rmin, float _rmax, float _phimin, float _phimax, float _zmin, float _zmax)
529 {
530  // change all the bounds of our output array and rebuild the array from scratch, leaving the original binning
531 
532  if (!(_rmax > _rmin) || !(_phimax > _phimin) || !(_zmax > _zmin))
533  {
534  return false; // the bounds are not well-ordered.
535  }
536 
537  lowerBound[0] = _rmin;
538  lowerBound[1] = _phimin;
539  lowerBound[2] = _zmin;
540  upperBound[0] = _rmax;
541  upperBound[1] = _phimax;
542  upperBound[2] = _zmax;
543 
544  for (int i = 0; i < 3; i++)
545  {
546  binWidth[i] = (upperBound[i] - lowerBound[i]) / (1.0 * nBins[i]);
547  }
548 
549  // if the array exists, delete it.
550  if (charge != nullptr)
551  {
552  delete charge;
553  charge = nullptr;
554  }
555  charge = new MultiArray<float>(nBins[0], nBins[1], nBins[2]);
556 
557  if (hChargeDensity != nullptr)
558  {
559  RegenerateCharge(); // fill the array with the charge data if available
560  }
561  else
562  {
563  charge->SetAll(0); // otherwise set the array to all zeroes.
564  }
565  return true;
566 
567  return true;
568 }
569 
570 bool ChargeMapReader::SetOutputBins(int _nr, int _nphi, int _nz)
571 {
572  // change the number of bins of our output array and rebuild the array from scratch, leaving the bounds alone.
573  if (_nr < 1 || _nphi < 1 || _nz < 1)
574  {
575  return false; // must be at least one bin wide.
576  }
577  nBins[0] = _nr;
578  nBins[1] = _nphi;
579  nBins[2] = _nz;
580 
581  for (int i = 0; i < 3; i++)
582  {
583  binWidth[i] = (upperBound[i] - lowerBound[i]) / (1.0 * nBins[i]);
584  }
585 
586  // if the array exists, delete it.
587  if (charge != nullptr)
588  {
589  delete charge;
590  charge = nullptr;
591  }
592  charge = new MultiArray<float>(nBins[0], nBins[1], nBins[2]);
593 
594  if (hChargeDensity != nullptr)
595  {
596  RegenerateCharge(); // fill the array with the charge data if available
597  }
598  else
599  {
600  charge->SetAll(0); // otherwise set the array to all zeroes.
601  }
602  return true;
603 }
604 
605 void ChargeMapReader::AddChargeInBin(int r, int phi, int z, float q)
606 {
607  assert(r > 0 && r < nBins[0]);
608  assert(phi > 0 && phi < nBins[1]);
609  assert(z > 0 && z < nBins[2]);
610  if (DEBUG)
611  {
612  printf("adding charge in array element %d %d %d to %.2E\n", r, phi, z, q);
613  }
614 
615  charge->Add(r, phi, z, q);
616  return;
617 }
618 
619 void ChargeMapReader::AddChargeAtPosition(float r, float phi, float z, float q)
620 {
621  // bounds checking are handled by the binwise function, so no need to do so here:
622  AddChargeInBin((r - lowerBound[0]) / binWidth[0], (phi - lowerBound[1]) / binWidth[1], (z - lowerBound[2]) / binWidth[2], q);
623  return;
624 }
625 
627 {
628  if (!(r >= 0 && r < nBins[0]))
629  {
630  printf("requested rbin %d, but bounds are %d to %d. Failing.\n", r, 0, nBins[0]);
631  assert(r >= 0 && r < nBins[0]);
632  }
633  if (!(phi >= 0 && phi < nBins[1]))
634  {
635  printf("requested phibin %d, but bounds are %d to %d. Failing.\n", phi, 0, nBins[1]);
636  assert(phi >= 0 && phi < nBins[1]);
637  }
638  if (!(z >= 0 && z < nBins[2]))
639  {
640  printf("requested rbin %d, but bounds are %d to %d. Failing.\n", z, 0, nBins[2]);
641  assert(z >= 0 && z < nBins[2]);
642  }
643 
644  if (DEBUG)
645  {
646  printf("getting charge in array element %d %d %d\n", r, phi, z);
647  }
648 
649  return charge->Get(r, phi, z);
650 }
651 
652 float ChargeMapReader::GetChargeAtPosition(float r, float phi, float z)
653 {
654  // bounds checking are handled by the binwise function, so no need to do so here:
655  return GetChargeInBin((r - lowerBound[0]) / binWidth[0], (phi - lowerBound[1]) / binWidth[1], (z - lowerBound[2]) / binWidth[2]);
656 }
657 
658 void ChargeMapReader::SetChargeInBin(int r, int phi, int z, float q)
659 {
660  if (!(r >= 0 && r < nBins[0]))
661  {
662  printf("requested rbin %d, but bounds are %d to %d. Failing.\n", r, 0, nBins[0]);
663  assert(r >= 0 && r < nBins[0]);
664  }
665  if (!(phi >= 0 && phi < nBins[1]))
666  {
667  printf("requested phibin %d, but bounds are %d to %d. Failing.\n", phi, 0, nBins[1]);
668  assert(phi >= 0 && phi < nBins[1]);
669  }
670  if (!(z >= 0 && z < nBins[2]))
671  {
672  printf("requested rbin %d, but bounds are %d to %d. Failing.\n", z, 0, nBins[2]);
673  assert(z >= 0 && z < nBins[2]);
674  }
675  if (DEBUG)
676  {
677  printf("setting charge in array element %d %d %d to %.2E\n", r, phi, z, q);
678  }
679 
680  charge->Set(r, phi, z, q);
681  return;
682 }
683 
684 void ChargeMapReader::SetChargeAtPosition(float r, float phi, float z, float q)
685 {
686  // bounds checking are handled by the binwise function, so no need to do so here:
687  SetChargeInBin((r - lowerBound[0]) / binWidth[0], (phi - lowerBound[1]) / binWidth[1], (z - lowerBound[2]) / binWidth[2], q);
688  return;
689 }