EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ThreeDeePolySpace.cxx
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ThreeDeePolySpace.cxx
1 /* -------------------------------------------------------------------------- */
2 /* ThreeDeePolySpace.cc */
3 /* */
4 /* Collection of fitting routines with orthogonal polynomials. */
5 /* */
6 /* A.Kisselev, PNPI, St.Petersburg, Russia. */
7 /* e-mail: kisselev@hermes.desy.de */
8 /* -------------------------------------------------------------------------- */
9 
10 #include <cstdio>
11 #include <cstdlib>
12 #include <cstring>
13 #include <cmath>
14 #include <cassert>
15 
16 #include <ayk.h>
17 #include <ThreeDeePolySpace.h>
18 
19 /* ========================================================================== */
20 
21 ThreeDeePolySpace::ThreeDeePolySpace(int max_power[3], int _point_num, unsigned char _parity[3])
22 {
23  int odd, even;
24 
25  // Check later, whether this is really needed;
26  memset(this, 0x00, sizeof(ThreeDeePolySpace));
27 
28  // Start off "1"; the actual calculation is below;
29  dim = 1;
30 
31  // Figure out overall dimension;
32  for(int ik=0; ik<3; ik++)
33  {
34  _max_power[ik] = max_power[ik];
35 
36  parity[ik] = _parity ? _parity[ik] : _BOTH_;
37 
38  // Figure out actual number of degrees of freedom;
39  degrees_of_freedom[ik] = 0;
40  odd = even = max_power[ik]/2;
41  if (max_power[ik]%2) even++;
42  if (parity[ik] & _ODD_) degrees_of_freedom[ik] += odd;
43  if (parity[ik] & _EVEN_) degrees_of_freedom[ik] += even;
44 
45  dim *= degrees_of_freedom[ik];
46  } /*for*/
47 
48  // Allocate memory for basis and derivatives;
49  basis = new ThreeDeePolynomial* [dim];
50  for(int ik=0; ik<dim; ik++)
51  basis[ik] = new ThreeDeePolynomial(this);
52 
53  dbasis = new ThreeDeePolynomial** [dim];
54  for(int ii=0; ii<dim; ii++)
55  {
56  dbasis[ii] = new ThreeDeePolynomial* [3];
57 
58  for(int ik=0; ik<3; ik++)
59  dbasis[ii][ik] = new ThreeDeePolynomial(this);
60  } /*for*/
61 
62  // Working space;
63  buffer = new ThreeDeePolynomial(this);
64 
65  // Allocate 3D points;
66  point_num = _point_num;
68 
69  // A reasonable default for weight, please;
70  for(int ik=0; ik<point_num; ik++)
71  points[ik].weight = 1.;
72 } /* ThreeDeePolySpace::ThreeDeePolySpace */
73 
74 /* ========================================================================== */
75 /* Does not take into account possibility that some of the directions may */
76 /* have too few points; fix later; */
77 
79 {
80  return point_num - dim;
81 } /* ThreeDeePolySpace::getNDF */
82 
83 /* ========================================================================== */
84 
85 //
86 // -> do not bother to create operators; just convert functions to methods;
87 // since at least few of these are logically related to ThreeDeePolySpace rather
88 // than ThreeDeePolynomial class, put them all into ThreeDeePolySpace;
89 //
90 
92 {
93  double ret = 0.0;
94 
95  for(int pt=0; pt<point_num; pt++)
96  {
98 
99  assert(0);
100  //@@@ ret += point->weight*p1->value(point->xx)*p2->value(point->xx);
101  } /*for*/
102 
103  return ret;
104 } /* ThreeDeePolySpace::polyProduct */
105 
106 /* -------------------------------------------------------------------------- */
107 
109 {
110  double ret = 0.0;
111 
112  if (poly->off) return 0.0;
113 
114  for(int pt=0; pt<point_num; pt++)
115  {
117 
118  assert(0);
119  //@@@ ret += point->weight*poly->value(point->xx)*point->f;
120  } /*for*/
121 
122  return ret;
123 } /* ThreeDeePolySpace::polyProjection */
124 
125 /* -------------------------------------------------------------------------- */
126 
128 {
129  int ix, iy, iz;
130 
131  for(ix=0; ix<_max_power[_X_]; ix++)
132  {
133  if (!PARITY_CHECK(this, _X_, ix)) continue;
134 
135  for(iy=0; iy<_max_power[_Y_]; iy++)
136  {
137  if (!PARITY_CHECK(this, _Y_, iy)) continue;
138 
139  for(iz=0; iz<_max_power[_Z_]; iz++)
140  {
141  if (!PARITY_CHECK(this, _Z_, iz)) continue;
142 
143  dest->cff[ix][iy][iz] = source->cff[ix][iy][iz];
144  } /*for*/
145  } /*for*/
146  } /*for*/
147 } /* ThreeDeePolySpace::polyCopy */
148 
149 /* -------------------------------------------------------------------------- */
150 
152 {
153  // Do I actually need this "off_counter"?;
154  int id = 0, off_counter = 0;
155 
156  // Start with 1, x, x^2, ...;
157  for(int ix=0; ix<_max_power[_X_]; ix++)
158  for(int iy=0; iy<_max_power[_Y_]; iy++)
159  for(int iz=0; iz<_max_power[_Z_]; iz++)
160  {
161  if (!PARITY_CHECK(this, _X_, ix) ||
162  !PARITY_CHECK(this, _Y_, iy) ||
163  !PARITY_CHECK(this, _Z_, iz))
164  continue;
165 
166  {
167  ThreeDeePolynomial *poly = basis[id++];
168 
169  for(int qx=0; qx<_max_power[_X_]; qx++)
170  for(int qy=0; qy<_max_power[_Y_]; qy++)
171  for(int qz=0; qz<_max_power[_Z_]; qz++)
172  poly->cff[qx][qy][qz] = 0.;
173 
174  poly->cff[ix][iy][iz] = 1.;
175  }
176  } /*for..for*/
177 
178  for(int ii=0; ii<dim; ii++)
179  {
180  for(int ik=0; ik<ii; ik++)
181  {
182  double projection = polyProduct(basis[ii], basis[ik]);
183 
184  polyCopy(buffer, basis[ik]);
185  buffer->multiply(-projection);
186  basis[ii]->increment(buffer);
187  } /*for*/
188 
189  if (basis[ii]->normalize()) off_counter++;
190  } /*for*/
191 } /* ThreeDeePolySpace::buildOrthogonalPolynomials */
192 
193 /* ========================================================================== */
194 
196 {
197  for(int ii=0; ii<dim; ii++)
198  if (basis[ii]->calculateGradient(dbasis[ii]))
199  return -1;
200 
201  return 0;
202 } /* ThreeDeePolySpace::buildBasisGradients */
203 
204 /* ========================================================================== */
205 
206 //
207 // -> yes, at least here I should use ThreeDeePolySpace-based routine (not to
208 // blindly reuse fit->space pointer);
209 //
210 
212 {
213  for(int ii=0; ii<dim; ii++)
214  fit->linear[ii] = polyProjection(basis[ii]);
215 
216  fit->convertLinearToCff();
217 } /* ThreeDeePolySpace::calculateFittingPolynomial */
218 
219 /* ========================================================================== */
220 
221 //
222 // -> yes, as any point-coupled routine this one should be ThreeDeePolySpace-related;
223 //
224 
226 {
227  double ret = 0.0;
228 
229  for(int pt=0; pt<point_num; pt++)
230  {
232 
233  assert(0);
234  //@@@ ret += point->weight*SQR(fit->value(point->xx) - point->f);
235  } /*for*/
236 
237  return ret;
238 } /* ThreeDeePolySpace::getPolyFitChiSquare */
239 
240 /* ========================================================================== */
241 /* This calculation assumes that chi^2 is correct; in this case errors on */
242 /* 'linear' coefficients are all equal '1.' and below calculation is Ok; */
243 
245 {
246  double err = 0.0;
247 
248  for(int ii=0; ii<dim; ii++)
249  err += SQR(basis[ii]->value(xx));
250 
251  return sqrt(err);
252 } /* ThreeDeePolySpace::getNaivePolyFitError */
253 
254 /* ========================================================================== */
255 /* This calculation takes chi^2 into account and renormalizes naive error */
256 /* estimate by sqrt(chi^2/ndf); this way error estimate will not depend on the*/
257 /* weight scaling factor; so for instance if errors in all points are more or */
258 /* less the same, they can be safely set to 1. and this function will provide */
259 /* best guess error estimate; */
260 
261 //
262 // -> not sure this has ever been checked;
263 //
264 
266 {
267  int ndf = getNDF();
268  double err = 0.0, chi2 = getPolyFitChiSquare(fit);
269 
270  for(int ii=0; ii<dim; ii++)
271  err += SQR(basis[ii]->value(xx));
272 
273  return sqrt(err*chi2/ndf);
274 } /* ThreeDeePolySpace::getRealisticPolyFitError */
275 
276 /* ========================================================================== */