Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TpcSpaceChargeReconstructionHelper.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file TpcSpaceChargeReconstructionHelper.cc
1 
8 
10 
11 #include <TH3.h>
12 #include <TString.h>
13 
14 #include <iostream>
15 
16 namespace
17 {
19  template<class T>
20  inline constexpr T square( T x ) { return x*x; }
21 
22  // regularize angle between 0 and 2PI
23  template<class T>
24  inline constexpr T get_bound_angle( T phi )
25  {
26  while( phi < 0 ) phi += 2*M_PI;
27  while( phi >= 2*M_PI ) phi -= 2*M_PI;
28  return phi;
29  }
30 
31  // angle from a given sector
32  constexpr double get_sector_phi( int isec ) { return isec*M_PI/6; }
33 
34  // Micromegas geometry
35  // TODO: should get those numbers from actual geometry configuration
36 
38  static constexpr double isec_ref = 9;
39  static constexpr double phi_ref = get_sector_phi(isec_ref);
40 
41  // radius of the outermost micromegas layer
42  static constexpr double r_ref = 85.1;
43 
45 
49  static constexpr double delta_phi_mm = 0.6*(31.6/CylinderGeomMicromegas::reference_radius);
50 
52  static constexpr double zextrap_min = 53.2 - 5.0;
53  static constexpr double zextrap_max = 56.6 + 5.0;
54 
55 }
56 
57 //____________________________________________________________________________________
59 {
60  if( !hin ) return;
61 
62  // get reference phi bin
63  const int phibin_ref = hin->GetXaxis()->FindBin( phi_ref );
64 
65  // loop over radial bins
66  for( int ir = 0; ir < hin->GetYaxis()->GetNbins(); ++ir )
67  {
68 
69  // get current radius
70  const auto r = hin->GetYaxis()->GetBinCenter( ir+1 );
71 
72  // get z integration window for reference
73  const auto zextrap_min_loc = zextrap_min * r/r_ref;
74  const auto zextrap_max_loc = zextrap_max * r/r_ref;
75 
76  // get corresponding bins
77  const int zbin_min[2] = { hin->GetZaxis()->FindBin( -zextrap_max_loc ), hin->GetZaxis()->FindBin( zextrap_min_loc ) };
78  const int zbin_max[2] = { hin->GetZaxis()->FindBin( -zextrap_min_loc ), hin->GetZaxis()->FindBin( zextrap_max_loc ) };
79 
80  for( int isign = 0; isign < 2; ++isign )
81  {
82  // adjust z positions
83  const auto z_min = hin->GetZaxis()->GetBinCenter( zbin_min[isign] );
84  const auto z_max = hin->GetZaxis()->GetBinCenter( zbin_max[isign] );
85 
86  // get reference
87  const auto content_min = hin->GetBinContent( phibin_ref, ir+1, zbin_min[isign] );
88  const auto content_max = hin->GetBinContent( phibin_ref, ir+1, zbin_max[isign] );
89  const auto error_min = hin->GetBinError( phibin_ref, ir+1, zbin_min[isign] );
90  const auto error_max = hin->GetBinError( phibin_ref, ir+1, zbin_max[isign] );
91 
92  // loop over z bins
93  for( int iz = zbin_min[isign]+1; iz < zbin_max[isign]; ++iz )
94  {
95 
96  const auto z = hin->GetZaxis()->GetBinCenter( iz );
97 
98  // interpolate
99  const auto alpha_min = (z_max-z)/(z_max-z_min);
100  const auto alpha_max = (z-z_min)/(z_max-z_min);
101 
102  const auto content = alpha_min*content_min + alpha_max*content_max;
103  const auto error = std::sqrt(square( alpha_min * error_min ) + square( alpha_max*error_max));
104 
105  hin->SetBinContent( phibin_ref, ir+1, iz, content );
106  hin->SetBinError( phibin_ref, ir+1, iz, error );
107  }
108  }
109  }
110 }
111 
112 //____________________________________________________________________________________
114 {
115  if( !hin ) return;
116 
117  // get phi bin range for a given sector
118  auto get_phibin_range = []( TH3* hin, int isec )
119  {
120 
121  // get corresponding first and last bin
122  const double phi = get_sector_phi( isec );
123  const double phi_min = get_bound_angle( phi - M_PI/12 );
124  const double phi_max = get_bound_angle( phi + M_PI/12 );
125 
126  // find corresponding bins
127  const int phibin_min = hin->GetXaxis()->FindBin( phi_min );
128  const int phibin_max = hin->GetXaxis()->FindBin( phi_max );
129  return std::make_pair( phibin_min, phibin_max );
130  };
131 
132  // get reference bins
133  const auto [phibin_min_ref, phibin_max_ref] = get_phibin_range( hin, isec_ref );
134 
135  // get number of phi bins
136  const int nphibins = hin->GetNbinsX();
137 
138  // copy all r and z bins from reference phi bin to destination
139  auto copy_phi_bin = []( TH3* hin, int phibin_ref, int phibin_dest )
140  {
141 
142  // loop over radial bins
143  for( int ir = 0; ir < hin->GetYaxis()->GetNbins(); ++ir )
144  {
145 
146  // loop over z bins
147  for( int iz = 0; iz < hin->GetZaxis()->GetNbins(); ++iz )
148  {
149  const auto content_ref = hin->GetBinContent( phibin_ref, ir+1, iz+1 );
150  const auto error_ref = hin->GetBinError( phibin_ref, ir+1, iz+1 );
151 
152  // calculate scale factor
153  const auto scale = 1;
154 
155  // assign to output histogram
156  hin->SetBinContent( phibin_dest, ir+1, iz+1, content_ref*scale );
157  hin->SetBinError( phibin_dest, ir+1, iz+1, error_ref*std::abs(scale) );
158  }
159  }
160 
161  };
162 
163  // loop over sectors
164  for( int isec = 0; isec < 12; ++isec )
165  {
166  // skip reference sector
167  if( isec == isec_ref ) continue;
168 
169  const auto [phibin_min, phibin_max] = get_phibin_range( hin, isec );
170 
171  // loop over bins
172  for( int ibin = 0; ibin < phibin_max_ref - phibin_min_ref; ++ibin )
173  {
174  int phibin_ref = (phibin_min_ref + ibin);
175  if( phibin_ref > nphibins ) phibin_ref -= nphibins;
176 
177  int phibin = (phibin_min + ibin);
178  if( phibin > nphibins ) phibin -= nphibins;
179 
180  copy_phi_bin( hin, phibin_ref, phibin );
181  }
182  }
183 }
184 
185 //_______________________________________________
187 {
188  if( !hin ) return;
189 
190 
191  // loop over sectors
192  for( int isec = 0; isec < 12; ++isec )
193  {
194  // get phi range for interpolation from this sector to the next
195  const double phi_min = get_sector_phi(isec)+delta_phi_mm/2;
196  const double phi_max = get_sector_phi(isec+1)-delta_phi_mm/2;
197 
198  // get corresponding bins
199  const int phibin_min = hin->GetXaxis()->FindBin(get_bound_angle(phi_min));
200  const int phibin_max = hin->GetXaxis()->FindBin(get_bound_angle(phi_max));
201 
202  // loop over radial bins
203  for( int ir = 0; ir < hin->GetYaxis()->GetNbins(); ++ir )
204  {
205 
206  // loop over z bins
207  for( int iz = 0; iz < hin->GetZaxis()->GetNbins(); ++iz )
208  {
209  const auto content_min = hin->GetBinContent( phibin_min, ir+1, iz+1 );
210  const auto content_max = hin->GetBinContent( phibin_max, ir+1, iz+1 );
211  const auto error_min = hin->GetBinError( phibin_min, ir+1, iz+1 );
212  const auto error_max = hin->GetBinError( phibin_max, ir+1, iz+1 );
213 
214  // loop over relevant phi bins
215  for( int iphi = phibin_min+1; iphi < phibin_max; ++iphi )
216  {
217  // get phi
218  const auto phi = hin->GetXaxis()->GetBinCenter( iphi );
219 
220  // perform linear extrapolation
221  const auto alpha_min = (phi_max-phi)/(phi_max-phi_min);
222  const auto alpha_max = (phi-phi_min)/(phi_max-phi_min);
223 
224  const auto content = alpha_min*content_min + alpha_max*content_max;
225  const auto error = std::sqrt(square( alpha_min * error_min ) + square( alpha_max*error_max));
226 
227  hin->SetBinContent( iphi, ir+1, iz+1, content );
228  hin->SetBinError( iphi, ir+1, iz+1, error );
229  }
230  }
231  }
232  }
233 
234 }
235 
236 //_______________________________________________
237 std::tuple<TH3*, TH3*> TpcSpaceChargeReconstructionHelper::split( TH3* hin )
238 {
239  if( !hin ) return std::make_tuple<TH3*, TH3*>( nullptr, nullptr );
240 
241  auto xaxis = hin->GetXaxis();
242  auto yaxis = hin->GetYaxis();
243  auto zaxis = hin->GetZaxis();
244  auto ibin = zaxis->FindBin( (double) 0 );
245 
246  // create histograms
247  auto hneg = new TH3F(
248  Form( "%s_negz", hin->GetName() ), Form( "%s_negz", hin->GetTitle() ),
249  xaxis->GetNbins(), xaxis->GetXmin(), xaxis->GetXmax(),
250  yaxis->GetNbins(), yaxis->GetXmin(), yaxis->GetXmax(),
251  ibin-1, zaxis->GetXmin(), zaxis->GetBinUpEdge( ibin-1 ) );
252 
253  auto hpos = new TH3F(
254  Form( "%s_posz", hin->GetName() ), Form( "%s_posz", hin->GetTitle() ),
255  xaxis->GetNbins(), xaxis->GetXmin(), xaxis->GetXmax(),
256  yaxis->GetNbins(), yaxis->GetXmin(), yaxis->GetXmax(),
257  zaxis->GetNbins() - (ibin-1), zaxis->GetBinLowEdge(ibin), zaxis->GetXmax() );
258 
259  // copy content and errors
260  for( int ix = 0; ix < xaxis->GetNbins(); ++ix )
261  for( int iy = 0; iy < yaxis->GetNbins(); ++iy )
262  for( int iz = 0; iz < zaxis->GetNbins(); ++iz )
263  {
264  const auto content = hin->GetBinContent( ix+1, iy+1, iz+1 );
265  const auto error = hin->GetBinError( ix+1, iy+1, iz+1 );
266 
267  if( iz < ibin-1 )
268  {
269  hneg->SetBinContent( ix+1, iy+1, iz+1, content );
270  hneg->SetBinError( ix+1, iy+1, iz+1, error );
271  } else {
272  hpos->SetBinContent( ix+1, iy+1, iz - (ibin-1) + 1, content );
273  hpos->SetBinError( ix+1, iy+1, iz - (ibin-1) + 1, error );
274  }
275  }
276 
277  // also copy axis titles
278  for( const auto h: {hneg, hpos} )
279  {
280  h->GetXaxis()->SetTitle( hin->GetXaxis()->GetTitle() );
281  h->GetYaxis()->SetTitle( hin->GetYaxis()->GetTitle() );
282  h->GetZaxis()->SetTitle( hin->GetZaxis()->GetTitle() );
283  }
284 
285  return std::make_tuple( hneg, hpos );
286 }
287 
288 //___________________________________________________________________________
290 {
291  std::array<int, 3> bins;
292  std::array<double, 3> x_min;
293  std::array<double, 3> x_max;
294 
295  int index = 0;
296  for( const auto axis:{ hin->GetXaxis(), hin->GetYaxis(), hin->GetZaxis() } )
297  {
298  // calculate bin width
299  const auto bin_width = (axis->GetXmax() - axis->GetXmin())/axis->GetNbins();
300 
301  // increase the number of bins by two
302  bins[index] = axis->GetNbins()+2;
303 
304  // update axis limits accordingly
305  x_min[index] = axis->GetXmin()-bin_width;
306  x_max[index] = axis->GetXmax()+bin_width;
307  ++index;
308  }
309 
310  // create new histogram
311  auto hout = new TH3F( name, name,
312  bins[0], x_min[0], x_max[0],
313  bins[1], x_min[1], x_max[1],
314  bins[2], x_min[2], x_max[2] );
315 
316  // update axis legend
317  hout->GetXaxis()->SetTitle( hin->GetXaxis()->GetTitle() );
318  hout->GetYaxis()->SetTitle( hin->GetYaxis()->GetTitle() );
319  hout->GetZaxis()->SetTitle( hin->GetZaxis()->GetTitle() );
320 
321  // copy content
322  const auto phibins = hin->GetXaxis()->GetNbins();
323  const auto rbins = hin->GetYaxis()->GetNbins();
324  const auto zbins = hin->GetZaxis()->GetNbins();
325 
326  // fill center
327  for( int iphi = 0; iphi < phibins; ++iphi )
328  for( int ir = 0; ir < rbins; ++ir )
329  for( int iz = 0; iz < zbins; ++iz )
330  {
331  hout->SetBinContent( iphi+2, ir+2, iz+2, hin->GetBinContent( iphi+1, ir+1, iz+1 ) );
332  hout->SetBinError( iphi+2, ir+2, iz+2, hin->GetBinError( iphi+1, ir+1, iz+1 ) );
333  }
334 
335  // fill guarding phi bins
336  /*
337  * we use 2pi periodicity to do that:
338  * - last valid bin is copied to first guarding bin;
339  * - first valid bin is copied to last guarding bin
340  */
341  for( int ir = 0; ir < rbins+2; ++ir )
342  for( int iz = 0; iz < zbins+2; ++iz )
343  {
344  // copy last bin to first guarding bin
345  hout->SetBinContent( 1, ir+1, iz+1, hout->GetBinContent( phibins+1, ir+1, iz+1 ) );
346  hout->SetBinError( 1, ir+1, iz+1, hout->GetBinError( phibins+1, ir+1, iz+1 ) );
347 
348  // copy first bin to last guarding bin
349  hout->SetBinContent( phibins+2, ir+1, iz+1, hout->GetBinContent( 2, ir+1, iz+1 ) );
350  hout->SetBinError( phibins+2, ir+1, iz+1, hout->GetBinError( 2, ir+1, iz+1 ) );
351  }
352 
353  // fill guarding r bins
354  for( int iphi = 0; iphi < phibins+2; ++iphi )
355  for( int iz = 0; iz < zbins+2; ++iz )
356  {
357  hout->SetBinContent( iphi+1, 1, iz+1, hout->GetBinContent( iphi+1, 2, iz+1 ) );
358  hout->SetBinError( iphi+1, 1, iz+1, hout->GetBinError( iphi+1, 2, iz+1 ) );
359 
360  hout->SetBinContent( iphi+1, rbins+2, iz+1, hout->GetBinContent( iphi+1, rbins+1, iz+1 ) );
361  hout->SetBinError( iphi+1, rbins+2, iz+1, hout->GetBinError( iphi+1, rbins+1, iz+1 ) );
362  }
363 
364  // fill guarding z bins
365  for( int iphi = 0; iphi < phibins+2; ++iphi )
366  for( int ir = 0; ir < rbins+2; ++ir )
367  {
368  hout->SetBinContent( iphi+1, ir+1, 1, hout->GetBinContent( iphi+1, ir+1, 2 ) );
369  hout->SetBinError( iphi+1, ir+1, 1, hout->GetBinError( iphi+1, ir+1, 2 ) );
370 
371  hout->SetBinContent( iphi+1, ir+1, zbins+2, hout->GetBinContent( iphi+1, ir+1, zbins+1 ) );
372  hout->SetBinError( iphi+1, ir+1, zbins+2, hout->GetBinError( iphi+1, ir+1, zbins+1 ) );
373  }
374 
375  return hout;
376 
377 }