ECCE @ EIC 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
2 
3 #include <TH3.h>
4 #include <TString.h>
5 
6 namespace
7 {
8 
10  template<class T> T square( T x ) { return x*x; }
11 
14  // fully equiped sector
15  static constexpr double isec_ref = 3;
16  static constexpr double phi_ref = isec_ref*M_PI/6 + M_PI/12;
17 
18  // radius of the micromegas layer
19  static constexpr double r_ref = 82;
20 
21  // z extrapolation window
22  static constexpr double zextrap_min = 48;
23  static constexpr double zextrap_max = 58;
24 
25  // Micromegas acceptance in incomplete sectors
26  static constexpr double zref = 33.25;
27  static constexpr double length = 50 - 5;
28  static constexpr double zref_min = zref - length/2;
29  static constexpr double zref_max = zref + length/2;
30 
31 }
32 
33 //____________________________________________________________________________________
35 {
36  if( !hin ) return;
37 
38  // get reference phi bin
39  const int phibin_ref = hin->GetXaxis()->FindBin( phi_ref );
40 
41  // loop over radial bins
42  for( int ir = 0; ir < hin->GetYaxis()->GetNbins(); ++ir )
43  {
44 
45  // get current radius
46  const auto r = hin->GetYaxis()->GetBinCenter( ir+1 );
47 
48  // get z integration window for reference
49  const auto zextrap_min_loc = zextrap_min * r/r_ref;
50  const auto zextrap_max_loc = zextrap_max * r/r_ref;
51 
52  // get corresponding bins
53  const int zbin_min[2] = { hin->GetZaxis()->FindBin( -zextrap_max_loc ), hin->GetZaxis()->FindBin( zextrap_min_loc ) };
54  const int zbin_max[2] = { hin->GetZaxis()->FindBin( -zextrap_min_loc ), hin->GetZaxis()->FindBin( zextrap_max_loc ) };
55 
56  for( int isign = 0; isign < 2; ++isign )
57  {
58  // adjust z positions
59  const auto z_min = hin->GetZaxis()->GetBinCenter( zbin_min[isign] );
60  const auto z_max = hin->GetZaxis()->GetBinCenter( zbin_max[isign] );
61 
62  // get reference
63  const auto content_min = hin->GetBinContent( phibin_ref, ir+1, zbin_min[isign] );
64  const auto content_max = hin->GetBinContent( phibin_ref, ir+1, zbin_max[isign] );
65  const auto error_min = hin->GetBinError( phibin_ref, ir+1, zbin_min[isign] );
66  const auto error_max = hin->GetBinError( phibin_ref, ir+1, zbin_max[isign] );
67 
68  // loop over z bins
69  for( int iz = zbin_min[isign]+1; iz < zbin_max[isign]; ++iz )
70  {
71 
72  const auto z = hin->GetZaxis()->GetBinCenter( iz );
73 
74  // interpolate
75  const auto alpha_min = (z_max-z)/(z_max-z_min);
76  const auto alpha_max = (z-z_min)/(z_max-z_min);
77 
78  const auto content = alpha_min*content_min + alpha_max*content_max;
79  const auto error = std::sqrt(square( alpha_min * error_min ) + square( alpha_max*error_max));
80 
81  hin->SetBinContent( phibin_ref, ir+1, iz, content );
82  hin->SetBinError( phibin_ref, ir+1, iz, error );
83  }
84  }
85  }
86 }
87 
88 //____________________________________________________________________________________
89 std::tuple<double, double> TpcSpaceChargeReconstructionHelper::get_zref_range( double r )
90 { return std::make_tuple( zref_min * r/r_ref, zref_max * r/r_ref ); }
91 
92 //____________________________________________________________________________________
94 {
95  if( !hin ) return;
96 
97  // get reference phi bin
98  const int phibin_ref = hin->GetXaxis()->FindBin( phi_ref );
99 
100  // loop over sectors
101  for( int isec = 0; isec < 12; ++isec )
102  {
103 
104  // skip reference sector
105  if( isec == isec_ref ) continue;
106 
107  // get relevant phi and corresponding bin
108  const double phi = isec*M_PI/6 + M_PI/12;
109  const int phibin = hin->GetXaxis()->FindBin( phi );
110 
111  // loop over radial bins
112  for( int ir = 0; ir < hin->GetYaxis()->GetNbins(); ++ir )
113  {
114 
115  // get current radius
116  const auto r = hin->GetYaxis()->GetBinCenter( ir+1 );
117 
118  // get z integration window for reference
119  double zref_min_loc, zref_max_loc;
120  std::tie( zref_min_loc, zref_max_loc ) = get_zref_range( r );
121 
122  // get corresponding bins
123  const std::array<int,2> zbin_min = {{ hin->GetZaxis()->FindBin( -zref_max_loc ), hin->GetZaxis()->FindBin( zref_min_loc ) }};
124  const std::array<int,2> zbin_max = {{ hin->GetZaxis()->FindBin( -zref_min_loc ), hin->GetZaxis()->FindBin( zref_max_loc ) }};
125 
126  // get corresponding normalizations
127  auto safe_ratio = []( double numerator, double denominator ) -> double { return denominator == 0 ? 1. : numerator / denominator; };
128  const std::array<double,2> scale_factor =
129  {{
130  safe_ratio( hin->Integral( phibin, phibin, ir+1, ir+1, zbin_min[0], zbin_max[0] ), hin->Integral( phibin_ref, phibin_ref, ir+1, ir+1, zbin_min[0], zbin_max[0] ) ),
131  safe_ratio( hin->Integral( phibin, phibin, ir+1, ir+1, zbin_min[1], zbin_max[1] ), hin->Integral( phibin_ref, phibin_ref, ir+1, ir+1, zbin_min[1], zbin_max[1] ) )
132  }};
133 
134  // loop over z bins
135  for( int iz = 0; iz < hin->GetZaxis()->GetNbins(); ++iz )
136  {
137  const auto content_ref = hin->GetBinContent( phibin_ref, ir+1, iz+1 );
138  const auto error_ref = hin->GetBinError( phibin_ref, ir+1, iz+1 );
139 
140  // calculate scale factor
141  const auto z = hin->GetZaxis()->GetBinCenter( iz+1 );
142  const auto scale = (z > 0) ? scale_factor[1]:scale_factor[0];
143 
144  // assign to output histogram
145  hin->SetBinContent( phibin, ir+1, iz+1, content_ref*scale );
146  hin->SetBinError( phibin, ir+1, iz+1, error_ref*std::abs(scale) );
147  }
148  }
149  }
150 }
151 
152 //_______________________________________________
154 {
155  if( !hin ) return;
156 
157  for( int iphi = 0; iphi < hin->GetXaxis()->GetNbins(); ++iphi )
158  {
159 
160  // find nearest sector phi bins
161  const auto phi = hin->GetXaxis()->GetBinCenter( iphi+1 );
162  const int isec = std::floor( (phi - M_PI/12)/(M_PI/6) );
163  double phi_min = isec*M_PI/6 + M_PI/12;
164  double phi_max = phi_min + M_PI/6;
165 
166  if( phi_min < 0 ) phi_min += 2*M_PI;
167  if( phi_max >= 2*M_PI ) phi_max -= 2*M_PI;
168 
169  const auto phibin_min = hin->GetXaxis()->FindBin( phi_min );
170  if( phibin_min == iphi+1 ) continue;
171 
172  const auto phibin_max = hin->GetXaxis()->FindBin( phi_max );
173  if( phibin_max == iphi+1 ) continue;
174 
175  // loop over radial bins
176  for( int ir = 0; ir < hin->GetYaxis()->GetNbins(); ++ir )
177  {
178 
179  // loop over z bins
180  for( int iz = 0; iz < hin->GetZaxis()->GetNbins(); ++iz )
181  {
182  const auto content_min = hin->GetBinContent( phibin_min, ir+1, iz+1 );
183  const auto content_max = hin->GetBinContent( phibin_max, ir+1, iz+1 );
184  const auto error_min = hin->GetBinError( phibin_min, ir+1, iz+1 );
185  const auto error_max = hin->GetBinError( phibin_max, ir+1, iz+1 );
186 
187  // perform linear extrapolation
188  const auto alpha_min = (phi_max-phi)/(phi_max-phi_min);
189  const auto alpha_max = (phi-phi_min)/(phi_max-phi_min);
190 
191  const auto content = alpha_min*content_min + alpha_max*content_max;
192  const auto error = std::sqrt(square( alpha_min * error_min ) + square( alpha_max*error_max));
193 
194  hin->SetBinContent( iphi+1, ir+1, iz+1, content );
195  hin->SetBinError( iphi+1, ir+1, iz+1, error );
196  }
197 
198  }
199  }
200 }
201 
202 //_______________________________________________
203 std::tuple<TH3*, TH3*> TpcSpaceChargeReconstructionHelper::split( TH3* hin )
204 {
205  if( !hin ) return std::make_tuple<TH3*, TH3*>( nullptr, nullptr );
206 
207  auto xaxis = hin->GetXaxis();
208  auto yaxis = hin->GetYaxis();
209  auto zaxis = hin->GetZaxis();
210  auto ibin = zaxis->FindBin( (double) 0 );
211 
212  // create histograms
213  auto hneg = new TH3F(
214  Form( "%s_negz", hin->GetName() ), Form( "%s_negz", hin->GetTitle() ),
215  xaxis->GetNbins(), xaxis->GetXmin(), xaxis->GetXmax(),
216  yaxis->GetNbins(), yaxis->GetXmin(), yaxis->GetXmax(),
217  ibin-1, zaxis->GetXmin(), zaxis->GetBinUpEdge( ibin-1 ) );
218 
219  auto hpos = new TH3F(
220  Form( "%s_posz", hin->GetName() ), Form( "%s_posz", hin->GetTitle() ),
221  xaxis->GetNbins(), xaxis->GetXmin(), xaxis->GetXmax(),
222  yaxis->GetNbins(), yaxis->GetXmin(), yaxis->GetXmax(),
223  zaxis->GetNbins() - (ibin-1), zaxis->GetBinLowEdge(ibin), zaxis->GetXmax() );
224 
225  // copy content and errors
226  for( int ix = 0; ix < xaxis->GetNbins(); ++ix )
227  for( int iy = 0; iy < yaxis->GetNbins(); ++iy )
228  for( int iz = 0; iz < zaxis->GetNbins(); ++iz )
229  {
230  const auto content = hin->GetBinContent( ix+1, iy+1, iz+1 );
231  const auto error = hin->GetBinError( ix+1, iy+1, iz+1 );
232 
233  if( iz < ibin-1 )
234  {
235  hneg->SetBinContent( ix+1, iy+1, iz+1, content );
236  hneg->SetBinError( ix+1, iy+1, iz+1, error );
237  } else {
238  hpos->SetBinContent( ix+1, iy+1, iz - (ibin-1) + 1, content );
239  hpos->SetBinError( ix+1, iy+1, iz - (ibin-1) + 1, error );
240  }
241  }
242 
243  // also copy axis titles
244  for( const auto h: {hneg, hpos} )
245  {
246  h->GetXaxis()->SetTitle( hin->GetXaxis()->GetTitle() );
247  h->GetYaxis()->SetTitle( hin->GetYaxis()->GetTitle() );
248  h->GetZaxis()->SetTitle( hin->GetZaxis()->GetTitle() );
249  }
250 
251  return std::make_tuple( hneg, hpos );
252 }
253 
254 //___________________________________________________________________________
256 {
257  std::array<int, 3> bins;
258  std::array<double, 3> x_min;
259  std::array<double, 3> x_max;
260 
261  int index = 0;
262  for( const auto axis:{ hin->GetXaxis(), hin->GetYaxis(), hin->GetZaxis() } )
263  {
264  // calculate bin width
265  const auto bin_width = (axis->GetXmax() - axis->GetXmin())/axis->GetNbins();
266 
267  // increase the number of bins by two
268  bins[index] = axis->GetNbins()+2;
269 
270  // update axis limits accordingly
271  x_min[index] = axis->GetXmin()-bin_width;
272  x_max[index] = axis->GetXmax()+bin_width;
273  ++index;
274  }
275 
276  // create new histogram
277  auto hout = new TH3F( name, name,
278  bins[0], x_min[0], x_max[0],
279  bins[1], x_min[1], x_max[1],
280  bins[2], x_min[2], x_max[2] );
281 
282  // update axis legend
283  hout->GetXaxis()->SetTitle( hin->GetXaxis()->GetTitle() );
284  hout->GetYaxis()->SetTitle( hin->GetYaxis()->GetTitle() );
285  hout->GetZaxis()->SetTitle( hin->GetZaxis()->GetTitle() );
286 
287  // copy content
288  const auto phibins = hin->GetXaxis()->GetNbins();
289  const auto rbins = hin->GetYaxis()->GetNbins();
290  const auto zbins = hin->GetZaxis()->GetNbins();
291 
292  // fill center
293  for( int iphi = 0; iphi < phibins; ++iphi )
294  for( int ir = 0; ir < rbins; ++ir )
295  for( int iz = 0; iz < zbins; ++iz )
296  {
297  hout->SetBinContent( iphi+2, ir+2, iz+2, hin->GetBinContent( iphi+1, ir+1, iz+1 ) );
298  hout->SetBinError( iphi+2, ir+2, iz+2, hin->GetBinError( iphi+1, ir+1, iz+1 ) );
299  }
300 
301  // fill guarding phi bins
302  /*
303  * we use 2pi periodicity to do that:
304  * - last valid bin is copied to first guarding bin;
305  * - first valid bin is copied to last guarding bin
306  */
307  for( int ir = 0; ir < rbins+2; ++ir )
308  for( int iz = 0; iz < zbins+2; ++iz )
309  {
310  // copy last bin to first guarding bin
311  hout->SetBinContent( 1, ir+1, iz+1, hout->GetBinContent( phibins+1, ir+1, iz+1 ) );
312  hout->SetBinError( 1, ir+1, iz+1, hout->GetBinError( phibins+1, ir+1, iz+1 ) );
313 
314  // copy first bin to last guarding bin
315  hout->SetBinContent( phibins+2, ir+1, iz+1, hout->GetBinContent( 2, ir+1, iz+1 ) );
316  hout->SetBinError( phibins+2, ir+1, iz+1, hout->GetBinError( 2, ir+1, iz+1 ) );
317  }
318 
319  // fill guarding r bins
320  for( int iphi = 0; iphi < phibins+2; ++iphi )
321  for( int iz = 0; iz < zbins+2; ++iz )
322  {
323  hout->SetBinContent( iphi+1, 1, iz+1, hout->GetBinContent( iphi+1, 2, iz+1 ) );
324  hout->SetBinError( iphi+1, 1, iz+1, hout->GetBinError( iphi+1, 2, iz+1 ) );
325 
326  hout->SetBinContent( iphi+1, rbins+2, iz+1, hout->GetBinContent( iphi+1, rbins+1, iz+1 ) );
327  hout->SetBinError( iphi+1, rbins+1, iz+1, hout->GetBinError( iphi+1, rbins+1, iz+1 ) );
328  }
329 
330  // fill guarding z bins
331  for( int iphi = 0; iphi < phibins+2; ++iphi )
332  for( int ir = 0; ir < rbins+2; ++ir )
333  {
334  hout->SetBinContent( iphi+1, ir+1, 1, hout->GetBinContent( iphi+1, ir+1, 2 ) );
335  hout->SetBinError( iphi+1, ir+1, 1, hout->GetBinError( iphi+1, ir+1, 2 ) );
336 
337  hout->SetBinContent( iphi+1, ir+1, zbins+2, hout->GetBinContent( iphi+1, ir+1, zbins+1 ) );
338  hout->SetBinError( iphi+1, ir+1, zbins+2, hout->GetBinError( iphi+1, ir+1, zbins+1 ) );
339  }
340 
341  return hout;
342 
343 }