ToolDAQFramework
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
dimfit.cpp
Go to the documentation of this file.
1 #include "dimfit.h"
2 
3 dimfit::dimfit():Tool(){}
4 
5 
6 bool dimfit::Initialise(std::string configfile, DataModel &data){
7 
8  if(configfile!="") m_variables.Initialise(configfile);
9  //m_variables.Print();
10 
11  m_verbose = 0;
12  m_variables.Get("verbose", m_verbose);
13 
14  //Setup and start the stopwatch
15  bool use_stopwatch = false;
16  m_variables.Get("use_stopwatch", use_stopwatch);
17  m_stopwatch = use_stopwatch ? new util::Stopwatch("dimfit") : 0;
18 
19  m_stopwatch_file = "";
20  m_variables.Get("stopwatch_file", m_stopwatch_file);
21 
23 
24  m_data= &data;
25 
26  //parameters determining which events to read in
27  if(!m_variables.Get("input_filter_name", fInputFilterName)) {
28  Log("INFO: input_filter_name not given. Using ALL", WARN, m_verbose);
29  fInputFilterName = "ALL";
30  }
31  fInFilter = m_data->GetFilter(fInputFilterName, false);
32  if(!fInFilter) {
33  ss << "FATAL: no filter named " << fInputFilterName << " found. Returning false";
35  return false;
36  }
37 
38  //sliding time window parameters
39  double time_window_s;
40  if(!m_variables.Get("time_window", time_window_s)) {
41  time_window_s = 20;
42  Log("WARN: No time_window parameter found. Using a value of 20 (seconds)", WARN, m_verbose);
43  }
44  m_time_window = time_window_s * TimeDelta::s;
45  double time_window_step_s;
46  if(!m_variables.Get("time_window_step", time_window_step_s)) {
47  time_window_step_s = 0.2;
48  Log("WARN: No time_window_step parameter found. Using a value of 0.2 (seconds)", WARN, m_verbose);
49  }
50  m_time_window_step = time_window_step_s * TimeDelta::s;
51  if(!m_variables.Get("min_events", min_events)) {
52  min_events = 3;
53  Log("WARN: No min_events parameter found. Using a value of 3", WARN, m_verbose);
54  }
55 
56  //dimfit parameters
57  if(!m_variables.Get("R2MIN", R2MIN)) {
58  R2MIN = 300000;
59  Log("WARN: No R2MIN parameter found. Using a value of 300000", WARN, m_verbose);
60  }
61  if(!m_variables.Get("LOWDBIAS", LOWDBIAS)) {
62  LOWDBIAS = 1.15;
63  Log("WARN: No LOWDBIAS parameter found. Using a value of 1.15", WARN, m_verbose);
64  }
65  if(!m_variables.Get("GOODPOINT", GOODPOINT)) {
66  GOODPOINT = 40000;
67  Log("WARN: No GOODPOINT parameter found. Using a value of 40000", WARN, m_verbose);
68  }
69  if(!m_variables.Get("MAXMEANPOS", MAXMEANPOS)) {
70  MAXMEANPOS = 250000;
71  Log("WARN: No MAXMEANPOS parameter found. Using a value of 250000", WARN, m_verbose);
72  }
73 
74  //nclusters parameters
75  if(!m_variables.Get("nclusters_silent_warning", nclusters_silent_warning)) {
77  Log("WARN: No nclusters_silent_warning parameter found. Using a value of 200", WARN, m_verbose);
78  }
79  if(!m_variables.Get("nclusters_normal_warning", nclusters_normal_warning)) {
81  Log("WARN: No nclusters_normal_warning parameter found. Using a value of 435", WARN, m_verbose);
82  }
83  if(!m_variables.Get("nclusters_golden_warning", nclusters_golden_warning)) {
85  Log("WARN: No nclusters_golden_warning parameter found. Using a value of 630", WARN, m_verbose);
86  }
87 
88  //allocate memory for a relatively large number of events
89  const int n_event_max = 10000;
90  fEventPos = new std::vector<double>(n_event_max * 3);
91 
92  if(m_stopwatch) Log(m_stopwatch->Result("Initialise"), INFO, m_verbose);
93 
94  return true;
95 }
96 
97 
100 
101  const int N = fInFilter->GetNRecons();
102 
103  //get first/last times
104  TimeDelta tstart = fInFilter->GetFirstTime();
105  TimeDelta tend = fInFilter->GetLastTime();
106  ss << "DEBUG: dimfit looping in time from " << tstart << " to " << tend << " in steps of " << m_time_window_step;
108 
109  //use a sliding window to loop over the events
110  TimeDelta tloop = tstart;
111  TimeDelta tloopend = tloop + m_time_window;
112  tloopend = tloopend < tend ? tloopend : tend; //ensure the loop runs at least once
113  while(tloopend <= tend) {
114  fEventPos->clear();
115 
116  unsigned int nclusters = 0;
117  for(int irecon = 0; irecon < N; irecon++) {
118  //skip events reconstructed outside the time window
119  TimeDelta t = fInFilter->GetTime(irecon);
120  if(t < tloop || t > tloopend)
121  continue;
122 
123  //get the vertex position
124  Pos3D pos = fInFilter->GetVertex(irecon);
125 
126  //we'll use this event! Put it in the vertex array
127  fEventPos->push_back(pos.x);
128  fEventPos->push_back(pos.y);
129  fEventPos->push_back(pos.z);
130  nclusters++;
131 
132  ss << "DEBUG: Adding vertex " << pos.x << ", " << pos.y << "\t" << pos.z << " to run through dimfit";
134  }//irecon
135 
136  //only call dimfit if there are over (or equal to) the minimum number of vertices
137  if(nclusters >= min_events) {
138  ss << "DEBUG: Running " << nclusters << " event positions through dimfit";
140 
141  dimfit_(nclusters, fEventPos->data(), fCentr, fRot, fRMean, fDim, fExitPoint, m_verbose);
142 
143  ss << "INFO: Dimfit returns " << fDim << " Exited at " << fExitPoint;
144  StreamToLog(INFO);
145  }
146 
147  //compare nclusters to nclusters warning thresholds
148  NClustersWarning_t nclusters_warning = kNClustersUndefined;
149  if (nclusters > nclusters_golden_warning) nclusters_warning = kNClustersGolden;
150  else if(nclusters > nclusters_normal_warning) nclusters_warning = kNClustersNormal;
151  else if(nclusters > nclusters_silent_warning) nclusters_warning = kNClustersSilent;
152  else if(nclusters) nclusters_warning = kNClustersStandard;
153 
154  ss << "INFO: nclusters_warning = " << ReconInfo::EnumAsString(nclusters_warning) << ", nclusters = " << nclusters << " in " << m_time_window;
155  StreamToLog(INFO);
156 
157  SNWarningParams supernova_warning_parameters(nclusters,fDim,nclusters_warning);
158  m_data->SupernovaWarningParameters.push_back(supernova_warning_parameters);
159 
160  //increment the sliding time window
161  tloop += m_time_window_step;
162  tloopend = tloop + m_time_window;
163 
164  }//while(tloop < tend)
165 
167 
168  return true;
169 }
170 
171 
173  if(m_stopwatch) {
175  m_stopwatch->Start();
176  }
177 
178  delete fEventPos;
179 
180  if(m_stopwatch) {
181  Log(m_stopwatch->Result("Finalise"), INFO, m_verbose);
182  delete m_stopwatch;
183  }
184 
185  return true;
186 }
187 
188 
189 /**************************************************
190 The following functions are taken verbatim from SK.
191 It is what SK use for SN monitoring (up to at least 2019)
192 https://arxiv.org/abs/1601.04778
193 Credit for the code (and allowing us to use it) go to Michael Smy
194 **************************************************/
195 
196 //this is the main SK function. From what I understand
197 //INPUTS
198 // n = the number of vertices
199 // points[n*3] = vector of the points. In the order [x1,y1,z1,x2,y2,z2,...]
200 //OUTPUTS
201 // centr[15] = [0]-[2] have centroids
202 // [3]-[8] have the covariance matix
203 // [9]-[14] have the rotated matix (guess: this is approximately diagonal), with the eigenvalues in [9]-[11]
204 // rot[9] = the rotation matix (I presume used to go from covariance matrix to rotated matrix
205 // rmean[5] = [0] stores the sqrt of the chosen reduced chisq (i.e. root3 for d=2)
206 // [1]-[3] store the reduced chisq (not sqrt!) of root, root2, root3
207 // note this is code convention. SK technote convention is lambda1, 1/2(lambda1 + lambda2), 1/3(lambda1 + lambda2 + lambda3)
208 // These are what's plotted in fig 3 of the SK paper
209 // [4] mean position
210 // dim = the D value the algoithm thinks it is
211 //RETURN VALUE
212 // -1 if input n < 1
213 // dim otherwise
214 
215 int dimfit::dimfit_(int n,double *points,double *centr,double *rot,double *rmean, int &dim,int &exitpoint, bool verbose)
216 {
217  double *matrix;
218  double x,y,z,root,root2,root3;
219  int i;
220 
221  for(i=0; i<12; i++) centr[i]=0;
222  if (n<1) {
223  exitpoint=-1;
224  return -1;
225  }
226  //matrix[0] is centr[3]
227  matrix=centr+3;
228  for(i=0; i<n; i++)
229  {
230  x=*points++; y=*points++; z=*points++;
231  // printf("in dimfit position %f %f %f\n", x, y, z );
232  *centr+=x;
233  centr[1]+=y;
234  centr[2]+=z;
235  centr[3]+=x*x;
236  centr[4]+=y*y;
237  centr[5]+=z*z;
238  centr[6]+=x*y;
239  centr[7]+=y*z;
240  centr[8]+=x*z;
241  }
242  for(i=0; i<9; i++) centr[i]/=n;
243  //centr[0] to centr[8] have the average values of x, y, z, xx, yy, zz, xy, yz, xz
244  for(i=0; i<3; i++) matrix[i]-=centr[i]*centr[i];
245  //centr[3] to centr[5] have xx/n - (x/n)^2, yy/n - (y/n)^2, zz/n - (z/n)^2
246  matrix[3]-=*centr*centr[1];
247  //centr[6] has xy/n - (x/n)(y/n)
248  matrix[4]-=centr[1]*centr[2];
249  //centr[7] has yz/n - (y/n)(z/n)
250  matrix[5]-=*centr*centr[2];
251  //centr[8] has xz/n - (x/n)(z/n)
252  for(i=0; i<6; i++)
253  matrix[i+6]=matrix[i];
254  //centr[9] has centr[3], centr[10] has centr[4], ..., centr[14] has centr[8]
255 
256  //if only 1 vertex, assume a point source
257  if (n==1)
258  {
259  rmean[0]=0;
260  dim=0;
261  exitpoint = 1;
262  return(0); // assume point source
263  }
264 
265  //call the eigen function with centr[9]
266  //I don't know the maths of this, but you should look into it.
267  //From what I can tell (i.e. what's used next) centr[9] to centr[11] have been
268  // modified to the eigenvalues
269  //And rot is also set. I'm guessing it's a rotation matrix
270  //The printout statements here should help you
271  eigen(matrix+6,rot);
272  if(verbose) {
273  printf("centroid: %lf %lf %lf\n",centr[0],centr[1],centr[2]);
274  printf("covariance: %lf %lf %lf\n",centr[3],centr[6],centr[8]);
275  printf("covariance: %lf %lf %lf\n",centr[6],centr[4],centr[7]);
276  printf("covariance: %lf %lf %lf\n",centr[8],centr[7],centr[5]);
277  printf("rotated: %lf %lf %lf\n",centr[9],centr[12],centr[14]);
278  printf("rotated: %lf %lf %lf\n",centr[12],centr[10],centr[13]);
279  printf("rotated: %lf %lf %lf\n",centr[14],centr[13],centr[11]);
280  printf("rotation: %lf %lf %lf\n",rot[0],rot[1],rot[2]);
281  printf("rotation: %lf %lf %lf\n",rot[3],rot[4],rot[5]);
282  printf("rotation: %lf %lf %lf\n",rot[6],rot[7],rot[8]);
283  }
284 
285  //the root values here are the reduced chisq from the technote.
286  root=n*(centr[9]+centr[10]+centr[11])/(3*(n-1));
287  //std::cout << root << std::endl;
288  root2=n*(centr[9]+centr[10])/(2*(n-2));
289  if (n>3) root3=n*centr[9]/(n-3); else root3=1e10;
290  double Pos = centr[0]*centr[0]+centr[1]*centr[1]+centr[2]*centr[2];
291  if(verbose)
292  std::cout << "dimfit av x,y,z\t" << centr[0] << "\t" << centr[1] << "\t" << centr[2] << std::endl;
293  rmean[1] = root;
294  rmean[2] = root2;
295  rmean[3] = root3;
296  rmean[4] = Pos;
297  if(verbose) {
298  printf("3 values %lf %lf %lf\n",sqrt(root),sqrt(root2),sqrt(root3));
299  printf("Mean position %lf\n", Pos);
300  }
301 
302  //Here the decisions are made as to how many dimensions the vertex distribution is
303  if ((n==2) || root<GOODPOINT)
304  {
305  rmean[0]=sqrt(root);
306  dim=0;
307  exitpoint = 2;
308  return(0); // it is from a point source!
309  }
310  if ((n>3) && (root3*LOWDBIAS<root2) && (root3*LOWDBIAS<root))
311  {
312  if ((root3>R2MIN) &&
313  (Pos < MAXMEANPOS))
314  {
315  rmean[0]=sqrt(root);
316  dim=3;
317  exitpoint = 3;
318  return(3); // it is a uniform volume source!
319  }
320  else
321  {
322  rmean[0]=sqrt(root3);
323  dim=2;
324  exitpoint = 4;
325  return(2); // it is an area source!
326  }
327  }
328  if (root2*LOWDBIAS<root)
329  {
330  if ((root2>R2MIN) &&
331  (Pos < MAXMEANPOS))
332  {
333  rmean[0]=sqrt(root);
334  dim=3;
335  exitpoint = 5;
336  return(3); // it is a uniform volume source!
337  }
338  else
339  {
340  rmean[0]=sqrt(root2);
341  dim=1;
342  exitpoint = 6;
343  return(1); // it is a line source
344  }
345  }
346  rmean[0]=sqrt(root);
347 
348  if( (root > R2MIN ) &&
349  (Pos < MAXMEANPOS)){
350  dim=3;
351  exitpoint = 7;
352  return(3); // it is a uniform volume source!
353  }
354  dim=0;
355  exitpoint = 8;
356  return(0); // it is a point source!
357 }
358 
359 /* add in quadrature */
360 double dimfit::d_pythag(double a,double b)
361 {
362  double ma=fabs(a),mb=fabs(b),rat;
363 
364  if (ma>mb)
365  {
366  rat=mb/ma;
367  return(ma*sqrt(1+rat*rat));
368  }
369  if (mb==0) return(0);
370  rat=ma/mb;
371  return(mb*sqrt(1+rat*rat));
372 }
373 
374 /* test zero offdiagonal element */
375 int dimfit::d_iszero(double *matrix,int sta)
376 {
377  double add=fabs(matrix[sta+1])+fabs(matrix[sta]);
378  return(add+fabs(matrix[sta+3])==add);
379 }
380 
381 void dimfit::setvec(double *vectors,short int vect,double val1,double val2,double val3)
382 {
383  vectors[vect]=val1;
384  vectors[vect+3]=val2;
385  vectors[vect+6]=val3;
386 }
387 
388 void dimfit::rotate(double *vectors,short int vect,double si,double co)
389 {
390  double save;
391 
392  /* correct trafo matrix */
393  save=vectors[vect+1];
394  vectors[vect+1]=si*vectors[vect]+co*save;
395  vectors[vect] =co*vectors[vect]-si*save;
396  save=vectors[vect+4];
397  vectors[vect+4]=si*vectors[vect+3]+co*save;
398  vectors[vect+3]=co*vectors[vect+3]-si*save;
399  save=vectors[vect+7];
400  vectors[vect+7]=si*vectors[vect+6]+co*save;
401  vectors[vect+6]=co*vectors[vect+6]-si*save;
402 }
403 
404 /* first a plane rotation, then a Givens rotation */
405 int dimfit::planegivens(double *matrix,double *rot,double shift)
406 {
407  double si,co,sub,siodiag,coodiag,denom,pkiip1;
408  int ii,iii;
409 
410  shift+=matrix[2];
411  si=co=1;
412  sub=0;
413  for(ii=1; ii>=0; ii--)
414  {
415  siodiag=si*matrix[ii+3];
416  coodiag=co*matrix[ii+3];
417  denom=d_pythag(siodiag,shift);
418  matrix[ii+4]=denom;
419  if (denom==0)
420  {
421  matrix[ii+1]-=sub;
422  matrix[5]=0;
423  return(-1);
424  }
425  si=siodiag/denom; /* do rotation */
426  co=shift/denom;
427  shift=matrix[ii+1]-sub;
428  denom=(matrix[ii]-shift)*si+2*co*coodiag;
429  sub=si*denom;
430  matrix[ii+1]=shift+sub;
431  shift=co*denom-coodiag;
432  rotate(rot,ii,si,co);
433  }
434  matrix[0]-=sub;
435  matrix[3]=shift;
436  matrix[5]=0;
437  return(0);
438 }
439 
440 /* tridiagonalize matrix with a Householder transformation */
441 void dimfit::tridiag(double *matrix,double *rot)
442 {
443  double n=d_pythag(matrix[3],matrix[5]);
444  double u1=matrix[3]-n,u2=matrix[5],u=u1*u1+u2*u2;
445  double h,p1,p2;
446 
447  if ((n==0) || (u==0)) return;
448 
449  h=2/u;
450  p1=h*(matrix[1]*u1+matrix[4]*u2);
451  p2=h*(matrix[4]*u1+matrix[2]*u2);
452 
453  setvec(rot,0,1,0, 0);
454  setvec(rot,1,0,1-u1*u1*h, -u1*u2*h);
455  setvec(rot,2,0, -u1*u2*h,1-u2*u2*h);
456  h*=0.5*(u1*p1+u2*p2);
457  p1-=h*u1;
458  p2-=h*u2;
459 
460  matrix[1]-=2*p1*u1; matrix[4]-=p1*u2+p2*u1; matrix[5]=0;
461  matrix[2]-=2*p2*u2;
462  matrix[3]=n;
463 }
464 
465 /* swap eigenvalues and eigenvectors */
466 void dimfit::d_swap(double *val,double *rot,int c1,int c2)
467 {
468  double save;
469 
470  save=val[c1]; val[c1] =val[c2]; val[c2]= save;
471  save=rot[c1]; rot[c1] =rot[c2]; rot[c2]= save;
472  save=rot[c1+3]; rot[c1+3]=rot[c2+3]; rot[c2+3]=save;
473  save=rot[c1+6]; rot[c1+6]=rot[c2+6]; rot[c2+6]=save;
474 }
475 
476 void dimfit::eigen(double *matrix,double *rot)
477 {
478  double rat,root,shift,add,add2,si,co,u2i;
479  int sta,iter;
480 
481  tridiag(matrix,rot); //tridiagonalize
482  for(sta=0; sta<2; sta++)
483  for(iter=0; iter<20; iter++)
484  {
485  if (d_iszero(matrix,sta)) break;
486  rat=(matrix[sta+1]-matrix[sta])/(2*matrix[sta+3]);
487  root=d_pythag(1,rat);
488  if (rat*root<0) root=-root;
489  root+=rat;
490  add=matrix[sta+3]/root;
491  /* in case a simple plane rotation is needed */
492  if ((sta==1) || d_iszero(matrix,sta+1))
493  {
494  co=root/d_pythag(1,root);
495  si=co/root;
496  matrix[sta]-=add;
497  matrix[sta+1]+=add;
498  matrix[sta+3]=0;
499  rotate(rot,sta,si,co);
500  if (matrix[2]<matrix[1])
501  d_swap(matrix,rot,2,1);
502  if (matrix[1]<matrix[0])
503  d_swap(matrix,rot,0,1);
504  if (matrix[2]<matrix[1])
505  d_swap(matrix,rot,2,1);
506  return;
507  }
508  /* otherwise do a QL algorithm with implicit shift */
509  planegivens(matrix,rot,add-matrix[sta]);
510  }
511  if (matrix[2]<matrix[1]) d_swap(matrix,rot,2,1);
512  if (matrix[1]<matrix[0]) d_swap(matrix,rot,0,1);
513  if (matrix[2]<matrix[1]) d_swap(matrix,rot,2,1);
514  return;
515 }
std::string Result(std::string method_name, std::string output_file="")
Definition: Stopwatch.cpp:38
Pos3D GetVertex(int irecon)
Definition: ReconInfo.h:93
TimeDelta GetTime(int irecon)
Definition: ReconInfo.h:92
TimeDelta m_time_window
Definition: dimfit.h:28
std::stringstream ss
Definition: dimfit.h:64
double y
Definition: ReconInfo.h:37
int dimfit_(int n, double *points, double *centr, double *rot, double *rmean, int &dim, int &exitpoint, bool verbose)
Definition: dimfit.cpp:215
void Start()
Start the stopwatch.
Definition: Stopwatch.cpp:18
std::string m_stopwatch_file
Image filename to save the histogram to, if required.
Definition: dimfit.h:60
int fDim
Definition: dimfit.h:35
enum NClustersWarnings NClustersWarning_t
StopwatchTimes Stop()
Stop the stopwatch, returning the CPU time.
Definition: Stopwatch.cpp:24
bool Finalise()
Definition: dimfit.cpp:172
double fCentr[15]
Definition: dimfit.h:32
void d_swap(double *val, double *rot, int c1, int c2)
Definition: dimfit.cpp:466
void tridiag(double *matrix, double *rot)
Definition: dimfit.cpp:441
int min_events
Definition: dimfit.h:30
void StreamToLog(int level)
Definition: dimfit.h:66
double MAXMEANPOS
Definition: dimfit.h:41
bool Initialise(std::string configfile, DataModel &data)
Definition: dimfit.cpp:6
void setvec(double *vectors, short int vect, double val1, double val2, double val3)
Definition: dimfit.cpp:381
TimeDelta GetFirstTime()
Definition: ReconInfo.h:85
TimeDelta GetLastTime()
Definition: ReconInfo.h:86
std::string fInputFilterName
Definition: dimfit.h:25
util::Stopwatch * m_stopwatch
The stopwatch, if we&#39;re using one.
Definition: dimfit.h:58
bool Execute()
Definition: dimfit.cpp:98
TimeDelta m_time_window_step
Definition: dimfit.h:29
int nclusters_silent_warning
Definition: dimfit.h:43
double R2MIN
Definition: dimfit.h:38
void rotate(double *vectors, short int vect, double si, double co)
Definition: dimfit.cpp:388
int nclusters_normal_warning
Definition: dimfit.h:44
int nclusters_golden_warning
Definition: dimfit.h:45
double x
Definition: ReconInfo.h:37
int fExitPoint
Definition: dimfit.h:36
int m_verbose
Definition: dimfit.h:62
double z
Definition: ReconInfo.h:37
std::vector< double > * fEventPos
Definition: dimfit.h:27
double LOWDBIAS
Definition: dimfit.h:39
int planegivens(double *matrix, double *rot, double shift)
Definition: dimfit.cpp:405
void Log(const std::string &message, const int message_level)
Format messages in the same way as for tools.
Definition: Utilities.cpp:276
static std::string EnumAsString(Reconstructer_t r)
Definition: ReconInfo.cpp:78
double fRot[9]
Definition: dimfit.h:33
int d_iszero(double *matrix, int sta)
Definition: dimfit.cpp:375
ReconInfo * fInFilter
Definition: dimfit.h:24
double GOODPOINT
Definition: dimfit.h:40
double fRMean[5]
Definition: dimfit.h:34
int GetNRecons()
Definition: ReconInfo.h:84
static const TimeDelta s
TimeDelta of 1 s.
Definition: TimeDelta.h:63
dimfit()
Definition: dimfit.cpp:3
double d_pythag(double a, double b)
Definition: dimfit.cpp:360
void eigen(double *matrix, double *rot)
Definition: dimfit.cpp:476