Logo coherent WaveBurst  
Library Reference Guide
Logo
netcluster.cc
Go to the documentation of this file.
1 /*
2 # Copyright (C) 2019 Sergey Klimenko, Gabriele Vedovato, Valentin Necula, Vaibhav Tiwari
3 #
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
8 #
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
13 #
14 # You should have received a copy of the GNU General Public License
15 # along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17 
18 
19 //---------------------------------------------------
20 // WAT cluster class for network analysis
21 // S. Klimenko, University of Florida
22 //---------------------------------------------------
23 
24 #define NETCLUSTER_CC
25 #include <time.h>
26 #include <iostream>
27 #include <stdexcept>
28 #include <set>
29 #include <limits>
30 #include "netcluster.hh"
31 #include "detector.hh"
32 #include "network.hh"
33 #include "constants.hh"
34 
35 #include "TCanvas.h"
36 #include "TH2F.h"
37 #include "TMath.h"
38 #include "TRandom3.h"
39 #include "TTreeFormula.h"
40 
41 using namespace std;
42 
43 ClassImp(netcluster)
44 
45 // used to check duplicated entries in vector<int>
46 template<typename T>
47 void removeDuplicates(std::vector<T>& vec)
48 {
49  std::sort(vec.begin(), vec.end());
50  vec.erase(std::unique(vec.begin(), vec.end()), vec.end());
51 }
52 
53 // sort netpixel objects on time
54 int compare_PIX(const void *x, const void *y){
55  netpixel* p = *((netpixel**)x);
56  netpixel* q = *((netpixel**)y);
57  double a = double(p->time)/p->rate/p->layers
58  - double(q->time)/q->rate/q->layers;
59  if(a > 0) return 1;
60  if(a < 0) return -1;
61  return 0;
62 }
63 
64 // sort netpixel objects on likelihood (decreasind)
65 int compareLIKE(const void *x, const void *y){
66  netpixel* p = *((netpixel**)x);
67  netpixel* q = *((netpixel**)y);
68  double a = double(p->likelihood - q->likelihood);
69  if(a > 0) return -1;
70  if(a < 0) return 1;
71  return 0;
72 }
73 
74 
75 // structure and comparison function needed for optimizing mchirp
76 typedef struct{ double value; int type;} EndPoint;
77 
78 int compEndP(const void* p, const void* q)
79 { EndPoint* a = (EndPoint*)p;
80  EndPoint* b = (EndPoint*)q;
81  if(a->value > b->value)return 1;
82  return -1;
83 }
84 
85 // constructors
86 
88 {
89  this->clear();
90  this->rate = 0.;
91  this->start = 0.;
92  this->stop = 0.;
93  this->shift = 0.;
94  this->bpp = 1.;
95  this->flow = 0.;
96  this->fhigh = 1.e6;
97  this->run = 0;
98  this->nPIX = 3;
99  this->pair = true;
100  this->nSUB = 0;
101 
102  SetName("netcluster");
103 }
104 
106 {
107  *this = value;
108 }
109 
110 // destructor
111 
113 
114 // copyfrom function - copy selected clusters and pixels
115 // does not copy error regions
116 
117 size_t netcluster::cpf(const netcluster& value, bool optres, int nBIG)
118 {
119 // copy function (used in operator (=) as x.cpf(y,false)
120 //: copy content of y into x.
121 // If no clusters are reconstructed - copy all pixels.
122 // If clusters are reconstructed - copy selected clusters.
123 // value: netcluster object y
124 // optres: condition to select clusters:
125 // true - copy selected clusters with core pixels
126 // false - copy all selected clusters
127 // nBIG: min size of BIG clusters
128 // =0 - copy all clusters regardles of their size
129 // >0 - ignore BIG clusters with size >= nBIG
130 // <0 - copy BIG clusters with size >= nBIG
131  size_t n,m,k,K,ID;
132  size_t nbig = abs(nBIG);
133  size_t N = 0;
134  size_t cid = 0; // new cluster ID
135  size_t pid = 0; // new pixel ID
136  int R; // resolution
137 
138  std::vector<int> id; // list of pixels IDs in a cluster
139  std::vector<int> vr; // rate array
140  std::vector<int> refI; // reference integer
141  std::vector<float> refF; // reference float
142  std::vector<vector_int>::const_iterator it;
143 
144  netpixel pix;
145 
146  this->clear();
147  this->rate = value.rate;
148  this->start = value.start;
149  this->stop = value.stop;
150  this->shift = value.shift;
151  this->bpp = value.bpp;
152  this->run = value.run;
153  this->nPIX = value.nPIX;
154  this->flow = value.flow;
155  this->fhigh = value.fhigh;
156  this->pair = value.pair;
157  this->nSUB = value.nSUB;
158 
159  if(!value.cList.size()) { // not clustered value
160  this->pList = value.pList;
161  this->cluster();
162  return this->pList.size();
163  }
164 
165  for(it=value.cList.begin(); it!=value.cList.end(); it++){
166 
167  ID = value.pList[(*it)[0]].clusterID;
168  K = it->size(); // cluster size
169  if(value.sCuts[ID-1]>0) continue; // apply selection cuts
170  if(nBIG>0 && K>nbig) continue; // do not copy BIG clusters
171  if(nBIG<0 && K<nbig) continue; // copy only BIG clusters
172 
173  vr = value.cRate[ID-1]; // rate array
174  m = vr.size(); // size of rate array
175  if(m && optres) { // count only optimal resolution pixels
176  for(k=0; k<K; k++) {
177  R = int(value.pList[(*it)[k]].rate+0.1);
178  if(vr[0] == R) N++;
179  }
180  }
181  else N += K; // count all pixels
182  }
183  this->pList.reserve(N+2);
184 
185  for(it=value.cList.begin(); it!=value.cList.end(); it++){
186 
187  K = it->size();
188  ID = value.pList[(*it)[0]].clusterID;
189  if(value.sCuts[ID-1]>0) continue; // apply selection cuts
190  if(!K) continue; // skip empty cluster (e.g. after defragmentation)
191 
192  vr = value.cRate[ID-1]; // rate array
193  m = vr.size(); // size of rate array
194 
195  cid++; // increment cluster ID
196  id.clear(); // clear pixel list
197 
198  for(k=0; k<K; k++) { // loop over pixels
199  pix = value.pList[(*it)[k]];
200  R = int(value.pList[(*it)[k]].rate+0.1);
201 
202  if(m && optres) { // skip if not optimal resolution
203  if(vr[0] != R) continue;
204  }
205 
206  pix.neighbors.clear();
207  std::vector<int>().swap(pix.neighbors); // free memory
208  pix.clusterID = cid;
209  n = this->pList.size();
210  if(id.size()) {
211  pix.append(-1); // append a neighbor on the left
212  this->pList[n-1].append(1); // append a neighbor on the right
213  }
214  id.push_back(pid++); // update pixel list
215  this->append(pix); // append pixel to pList
216  }
217 
218  if(!id.size()) cout<<"netcluster::cpf() error: empty cluster.";
219 
220  cList.push_back(id); // fill cluster list
221  cData.push_back(value.cData[ID-1]); // copy cluster metadata
222  sCuts.push_back(0); // fill selection cuts
223  cRate.push_back(vr); // fill in rate array
224  p_Ind.push_back(refI); // create other arrays
225  p_Map.push_back(refF);
226  sArea.push_back(refF);
227  nTofF.push_back(refI);
228  cTime.push_back(value.cTime[ID-1]); // save supercluster central time
229  cFreq.push_back(value.cFreq[ID-1]); // save supercluster frequency
230  }
231  return this->pList.size();
232 }
233 
234 // netcluster::operator - copy only selected clusters
235 
237 {
238  this->cpf(value,false);
239  return *this;
240 }
241 
242 
243 size_t netcluster::setcore(bool core, int id)
244 {
245 // set pixel core field to be equal to the input parameter core
246 // reset cluster type to 0 except for rejecter clusters (type=1)
247  const vector_int* v;
248  size_t i,k,K;
249 
250  for(i=0; i<this->cList.size(); i++){
251 
252  v = &(this->cList[i]);
253  K = v->size();
254 
255  for(k=0; k<K; k++) {
256  if(id && this->pList[(*v)[k]].clusterID != id) continue;
257  this->pList[(*v)[k]].core = core;
258  }
259  }
260  return this->size();
261 }
262 
264 {
265 // select clusters - work with a single resolution
266 // name - parameter name
267 // thr - parameter threshold
268 
269  if(!this->pList.size()) return 0;
270 
271  if(!this->nSUB) this->nSUB=(2*iGamma(pList[0].size()-1,0.314));
272 
273  double aa,ee,mm;
274  wavearray<double> ID = this->get(const_cast<char*>("ID")); // get cluster ID
275  wavearray<double> out = ID; out=0;
276  int I = ID.size();
277 
278  if(strstr(name,"subnet")) { // subnetwork power;
279  out = this->get(const_cast<char*>("subnet"),0,'S'); // get subnetwork power
280  for(int i=0; i<I; i++){
281  aa = out.data[i];
282  if(aa<thr) this->ignore(ID.data[i]);
283  }
284  }
285 
286  if(strstr(name,"subrho")) { // subnetwork power;
287  out = this->get(const_cast<char*>("subrho"),0,'S'); // get subnetwork power
288  for(int i=0; i<I; i++){
289  aa = out.data[i];
290  if(aa<thr) this->ignore(ID.data[i]);
291  }
292  }
293 
294  if(strstr(name,"SUBCUT")) { // subnetwork
295  wavearray<double> sub = this->get(const_cast<char*>("subnrg"),0,'S'); // get subnetwork energy
296  wavearray<double> siz = this->get(const_cast<char*>("size"),0,'S'); // get cluster size
297  wavearray<double> max = this->get(const_cast<char*>("maxnrg"),0,'S'); // get maximum detector energy
298  double prl,qrl,ptime,qtime,pfreq,qfreq;
299  int N = pList.size();
300  netpixel* p; // pointer to pixel structure
301  netpixel* q; // pointer to pixel structure
302 
303  for(int i=0; i<I; i++){
304  aa = sub.data[i];
305  mm = siz.data[i];
306  aa = aa*(1+aa/max.data[i]);
307  out.data[i] = aa/(aa+mm+max.data[i]/10.);
308  if(out.data[i]>thr) continue;
309  this->ignore(ID.data[i]); // reject cluster
310 
311  const vector_int& vint = cList[ID.data[i]-1];
312  int K = vint.size();
313 
314  for(int n=0; n<N; n++) { // search for fragments
315  p = &(pList[n]);
316  if(sCuts[p->clusterID-1]>0) continue; // skip rejected pixels
317  prl = p->rate*p->layers;
318  ptime = p->time/prl; // time in seconds
319  pfreq = p->frequency*p->rate/2.; // frequency in Hz
320 
321  for(int k; k<K; k++){ // loop over rejected cluster
322  q = &pList[vint[k]];
323  qrl = q->rate*q->layers;
324  qtime = q->time/qrl; // time in seconds
325  qfreq = q->frequency*q->rate/2.; // frequency in Hz
326 
327  if(fabs(qfreq-pfreq)>128 &&
328  fabs(qtime-ptime)>0.125) continue;
329  sCuts[p->clusterID-1] = 1;
330  }
331  }
332  }
333  }
334  return out;
335 }
336 
338 {
339 //: clean input wseries ws removing rejected clusters
340 //: output number of remaining pixels
341  if(!pList.size() || !cList.size()) return 0;
342 
343  int i,ID;
344  int N = ws.pWavelet->nWWS/ws.pWavelet->nSTS;
345  int I = ws.pWavelet->nWWS/N;
346  int J = N>1? I : 0;
347  int K = pList.size();
348 
349  netpixel* pix = NULL;
350  vector<vector_int>::iterator it;
351 
352  for(it=this->cList.begin(); it != this->cList.end(); it++) { // loop over clusters
353 
354  pix = &(this->pList[((*it)[0])]);
355  ID = pix->clusterID;
356  if(this->sCuts[ID-1]==0) continue; // skip selected clusters
357 
358  for(size_t n=0; n<it->size(); n++) { // loop over pixels in the cluster
359  pix = &(this->pList[((*it)[n])]);
360  i = pix->time;
361  if(i < I) {
362  ws.data[i] = 0;
363  ws.data[i+J]=0;
364  K--;
365  }
366  }
367  }
368  return K;
369 }
370 
371 
372 // delink superclusters)
374 {
375 // delink superclusters
376 // - destroy supercluster neighbors links
377 // - preserve links for pixels with the same wavelet resolution
378 
379  size_t K = this->pList.size();
380  size_t n,k,N;
381 
382  if(!K) return 0;
383 
384  std::vector<int> v;
385  std::vector<int>* u;
386  netpixel* q;
387  netpixel* p;
388 
389  for(k=0; k<K; k++) {
390  q = &(this->pList[k]);
391  u = &(this->pList[k].neighbors);
392  v = *u;
393  u->clear();
394  N = v.size();
395  for(n=0; n<N; n++) {
396  p = q+v[n]; // pixel index in pList
397  if(p->clusterID != q->clusterID) {
398  cout<<"netcluster::delink(): cluster ID mismatch"<<endl;
399  continue;
400  }
401  // restore neighbors for the same resolution
402  if(p->rate == q->rate) q->append(v[n]);
403  }
404  }
405  return this->cluster();
406 }
407 
408 
409 size_t netcluster::cluster(int kt, int kf)
410 {
411 // produce time-frequency clusters at a single TF resolution
412 // any two pixels are associated if they are closer than both kt/kf
413 // samples in time/ftrequency
414  size_t i,j;
415  size_t n = this->pList.size();
416  if(n==0) return 0;
417  size_t M = this->pList[0].layers;
418  double R = this->pList[0].rate;
419 
420  int index;
421 
422  if(kt<=0) kt = 1;
423  if(kf<=0) kf = 1;
424  if(!n) return 0;
425  if(n==1) return this->cluster();
426 
427  netpixel** pp = (netpixel**)malloc(n*sizeof(netpixel*));
428  netpixel* p;
429  netpixel* q;
430 
431  for(i=0; i<n; i++) { pp[i] = &(pList[i]); pp[i]->neighbors.clear();}
432 
433  qsort(pp, n, sizeof(netpixel*), &compare_PIX); // sorted pixels
434 
435  for(i=0; i<n; i++) {
436  p = pp[i];
437  bool isWavelet = (size_t(this->rate/R+0.1) == pp[i]->layers) ? true : false; // wavelet : WDM
438 
439  if(R != p->rate || M != p->layers)
440  cout<<"netcluster::cluster(int,int) applied to mixed pixel list"<<endl;
441 
442  for(j=i+1; j<n; j++){
443  q = pp[j];
444  if(isWavelet) {
445  index = int(q->time) - int(p->time); // wavelet
446  } else {
447  index = int(q->time/M) - int(p->time/M); // WDM
448  }
449 
450  if(index < 0) cout<<"netcluster::cluster(int,int) sort error"<<endl;
451  if(isWavelet) {
452  if(index/M > kt) break; // wavelet
453  } else {
454  if(index > kt) break; // WDM
455  }
456 
457  if(abs(int(q->frequency) - int(p->frequency)) <= kf) { // set neighbours
458  p->append(q-p); // insert in p
459  q->append(p-q); // insert in q
460  }
461  }
462  }
463 
464  free(pp);
465  return this->cluster();
466 }
467 
468 
470 {
471 // perform cluster analysis
472 // this function initializes the netcluster data structures and
473 // call recursive cluster(netpixel) function to break pixel set into
474 // clusters.
475  size_t volume;
476  size_t i,m;
477  vector<int> refMask;
478  vector<int> refRate;
479  vector<float> refArea;
480  clusterdata refCD;
481  size_t nCluster = 0;
482  size_t n = pList.size();
483 
484  if(!pList.size()) return 0;
485 
486  // clear/initialize netcluster metadata
487 
488  cList.clear();
489  cData.clear();
490  sCuts.clear();
491  cRate.clear();
492  cTime.clear();
493  cFreq.clear();
494  sArea.clear();
495  p_Ind.clear();
496  p_Map.clear();
497  nTofF.clear();
498 
499  for(i=0; i<n; i++) pList[i].clusterID = 0;
500 
501  // loop over pixels
502 
503  for(i=0; i<n; i++){
504  if(pList[i].clusterID) continue; // pixel is clustered
505  pList[i].clusterID = ++nCluster; // new seed pixel - set ID
506  volume = cluster(&pList[i]); // cluster and return number of pixels
507  refMask.clear(); // to the end of the loop
508  cRate.push_back(refRate); // initialize cluster metadata
509  cTime.push_back(-1.);
510  cFreq.push_back(-1.);
511  p_Ind.push_back(refRate);
512  p_Map.push_back(refArea);
513  sArea.push_back(refArea);
514  nTofF.push_back(refRate);
515  refMask.resize(volume);
516  cList.push_back(refMask);
517  cData.push_back(refCD);
518  sCuts.push_back(0);
519  }
520 
521  vector<vector_int>::iterator it;
522  nCluster = 0;
523  if(!cList.size()) return 0;
524 
525  for(it=cList.begin(); it != cList.end(); it++) {
526  nCluster++;
527 
528  m = 0;
529  for(i=0; i<n; i++) {
530  if(pList[i].clusterID == nCluster) (*it)[m++] = i;
531  }
532 
533  if(it->size() != m) {
534  cout<<"cluster::cluster() size mismatch error: ";
535  cout<<m<<" size="<<it->size()<<" "<<nCluster<<endl;
536  }
537  }
538  return nCluster;
539 }
540 
542 {
543 // recursive clustering function used in cluster()
544 // it check neighbors and set the cluster ID field
545  size_t volume = 1;
546  int i = p->neighbors.size();
547  netpixel* q;
548 
549  while(--i >= 0){
550  q = p + p->neighbors[i];
551  if(!q->clusterID){
552  q->clusterID = p->clusterID;
553  volume += cluster(q);
554  }
555  }
556  return volume;
557 }
558 
559 
560 
561 size_t netcluster::cleanhalo(bool keepid)
562 {
563 // remove halo pixels from the pixel list
564 
565  if(!pList.size() || !cList.size()) return 0;
566 
567  size_t i,n,ID;
568  size_t cid = 0; // new cluster ID
569  size_t pid = 0; // new pixel ID
570 
571  netpixel* pix = NULL;
572  vector<vector_int>::iterator it;
573  std::vector<int> id; // list of pixels IDs in a cluster
574  std::vector<int>* pr; // pointer to rate array
575  std::vector<int> refI; // reference integer
576  std::vector<float> refF; // reference float
577 
578  netcluster x(*this);
579 
580  this->clear();
581 
582  for(it=x.cList.begin(); it != x.cList.end(); it++) { // loop over clusters
583 
584  pix = &(x.pList[((*it)[0])]);
585  ID = pix->clusterID;
586  if(x.sCuts[ID-1]>0) continue; // apply selection cuts
587  n = x.cRate.size();
588  pr = n ? &(x.cRate[ID-1]) : NULL; // pointer to the rate array
589 
590  cid++;
591  id.clear();
592  for(i=0; i<it->size(); i++) { // loop over pixels in the cluster
593  pix = &(x.pList[((*it)[i])]);
594  if(pix->core) {
595  pix->clusterID = keepid ? cid : 0;
596  pix->neighbors.clear();
597  std::vector<int>().swap(pix->neighbors); // free memory
598  id.push_back(pid++);
599  this->append(*pix); // fill pixel list
600  }
601  }
602 
603  i = id.size();
604  if(!i) cout<<"netcluster::cleanhalo() error: empty cluster.";
605 
606  if(keepid) {
607  cList.push_back(id); // fill cluster list
608  cData.push_back(x.cData[ID-1]); // fillin cluster metadata
609  sCuts.push_back(0); // fill selection cuts
610  if(pr) cRate.push_back(*pr); // fill in rate array
611  p_Ind.push_back(refI); // create other arrays
612  p_Map.push_back(refF);
613  sArea.push_back(refF);
614  nTofF.push_back(refI);
615  cTime.push_back(x.cTime[ID-1]); // fillin cluster central time
616  cFreq.push_back(x.cFreq[ID-1]); // fillin cluster frequency
617  }
618 
619  if(i<2) continue;
620 
621  while(--i > 0) { // set neighbors
622  pList[id[i-1]].append(id[i]-id[i-1]);
623  pList[id[i]].append(id[i-1]-id[i]);
624  }
625 
626 
627  }
628  return pList.size();
629 }
630 
632 {
633 // add halo pixels to the pixel list
634 // set pixel neighbours to match the packet pattern defined by mode
635 
636  if(!pList.size() || !cList.size()) return 0;
637  if(mode==0) return pList.size();
638 
639  size_t i,j,k,n,nIFO,ID,K,JJ;
640  int N,M,J;
641  size_t cid = 0; // new cluster ID
642  size_t pid = 0; // new pixel ID
643  bool save;
644 
645  netpixel* pix = NULL;
646  netpixel* PIX = NULL;
647  netpixel tmp;
648  vector<vector_int>::iterator it;
649  std::vector<int> id; // list of pixels IDs in a cluster
650  std::vector<int> jj; // time index array
651  std::vector<int> nid; // neighbors ID
652  std::vector<int>* pn; // pointer to neighbors array
653  std::vector<int> refI; // reference integer
654  std::vector<float> refF; // reference float
655 
656  netcluster x(*this);
657  this->clear();
658 
659  for(k=0; k<9; k++) {nid.push_back(0); jj.push_back(0);}
660 
661  for(it=x.cList.begin(); it != x.cList.end(); it++) { // loop over clusters
662 
663  pix = &(x.pList[((*it)[0])]);
664  ID = pix->clusterID;
665  if(x.sCuts[ID-1]>0) continue; // apply selection cuts
666 
667  cid++;
668  id.clear(); // clear list of pixel IDs
669 
670  for(i=0; i<it->size(); i++) { // loop over pixels in the cluster
671  pix = &(x.pList[((*it)[i])]);
672  pix->neighbors.clear();
673  std::vector<int>().swap(pix->neighbors); // free memory
674  id.push_back(pid++);
675  this->append(*pix); // fill pixel list
676  }
677 
678  for(i=0; i<it->size(); i++) { // loop over pixels in the cluster
679  pix = &(x.pList[((*it)[i])]);
680  M = int(pix->layers); // number of wavelet layers
681  J = int(pix->time); // pixel index
682  if(!(J%M) || !((J-1)%M) || !((J-2)%M) || !((J+1)%M)) continue;
683 
684  jj[0] = J;
685  if(mode==1) { // store packet pattern in jj
686  jj[1]=J-M+1; jj[2]=J+1; jj[3]=J+M+1;
687  jj[4]=J-M-1; jj[5]=J-1; jj[6]=J+M-1;
688  K = 7;
689  } else if(mode==3) {
690  jj[1]=J-M-1; jj[2]=J+M+1; K=3;
691  } else if(mode==-3) {
692  jj[1]=J+M-1; jj[2]=J-M+1; K=3;
693  } else if(mode==5) {
694  jj[1]=J-2*M-2; jj[2]=J+2*M+3;
695  jj[3]=J-M-1; jj[4]=J+M+1; K=5;
696  } else if(mode==-5) {
697  jj[1]=J+2*M-2; jj[2]=J-2*M+3;
698  jj[3]=J+M-1; jj[4]=J-M+1; K=5;
699  } else {
700  jj[1]=J-M-1; jj[2]=J+M+1;
701  jj[3]=J+M-1; jj[4]=J-M+1; K=5;
702  }
703 
704  for(k=0; k<K; k++) nid[k]=0;
705  for(j=0; j<id.size(); j++) { // loop over pixels in the cluster
706  PIX = &(this->pList[id[j]]);
707  N = int(PIX->layers); // number of wavelet bands (binary wavelet)
708  if(N!=M) continue; // skip different resolutions
709  J = int(PIX->time); // number of wavelet bands (binary wavelet)
710  for(k=0; k<K; k++) { // find pixels already in the pattern
711  if(J==jj[k]) nid[k] = id[j]+1; // already saved
712  }
713  }
714 
715  tmp = *pix;
716  for(k=1; k<K; k++) {
717  if(nid[k]!=0) continue;
718  id.push_back(pid++);
719  nid[k] = pid;
720  tmp.time = jj[k];
721  for(n=0; n<nIFO; n++) { // store original index
722  pix->data[n].index+=jj[k]-jj[0]; // update index in the detectors
723  }
724  pix->core = false;
725  this->append(tmp); // append halo pixel
726  }
727 
728  pn = &(this->pList[nid[0]-1].neighbors); // neighbour size in test pixel
729  for(k=1; k<K; k++) {
730  save = true;
731  for(j=0; j<pn->size(); j++)
732  if(nid[k]==(*pn)[j]+1) save=false; // find is naighbor is already saved
733  if(save) pn->push_back(nid[k]-1); // save packet neighbor
734  }
735  }
736 
737  cList.push_back(id); // fill cluster list
738  sCuts.push_back(0); // fill selection cuts
739  cData.push_back(x.cData[ID-1]); // fill cluster metadata
740  cRate.push_back(refI);
741  p_Ind.push_back(refI); // create other arrays
742  p_Map.push_back(refF);
743  sArea.push_back(refF);
744  nTofF.push_back(refI);
745  cTime.push_back(x.cTime[ID-1]); // fill cluster central time
746  cFreq.push_back(x.cFreq[ID-1]); // fill cluster frequency
747 
748  i = id.size();
749  if(!i) cout<<"netcluster::addhalo() error: empty cluster.";
750  if(i<2) continue;
751 
752  pList[id[i-1]].append(id[0]-id[i-1]);
753  pList[id[0]].append(id[i-1]-id[0]);
754  while(--i > 0) { // set neighbors
755  pList[id[i-1]].append(id[i]-id[i-1]);
756  pList[id[i]].append(id[i-1]-id[i]);
757  }
758 
759  //cout<<"new cluster\n";
760  //for(j=0; j<id.size(); j++) { // loop over pixels in the cluster
761  // PIX = &(this->pList[id[j]]);
762  // cout<<"list: "<<PIX->clusterID<<" "<<PIX->neighbors.size()<<" "<<PIX->layers<<endl;
763  //}
764 
765  }
766  return pList.size();
767 }
768 
770 {
771 // append pixel list.
772 // - to reconstruct clusters and cluster metadata run cluster() utility
773 
774  size_t i;
775  size_t in = w.pList.size();
776  size_t on = pList.size();
777 
778  if(!on) {
779  *this = w;
780  this->clear();
781  return in;
782  }
783  if(!in) { return on; }
784 
785  netpixel p;
786 
787  if(w.start!=start || w.shift!=shift || w.rate!=rate) {
788  printf("\n netcluster::append(): cluster type mismatch");
789  printf("%f / %f, %f / %f\n",w.start,start,w.shift,shift);
790 
791  return on;
792  }
793 
794  this->pList.reserve(in+on+2);
795  for(i=0; i<in; i++){
796  p = w.pList[i];
797  p.clusterID = 0; // update cluster ID
798  this->append(p); // add pixel to pList
799  }
800 
801  return pList.size();
802 }
803 
804 
805 //**************************************************************************
806 // construct super clusters (used in 1G pipeline)
807 //**************************************************************************
808 size_t netcluster::supercluster(char atype, double S, bool core)
809 {
810  size_t i,j,k,m,M;
811  size_t n = pList.size();
812  int l;
813 
814  if(!n) return 0;
815 
816  netpixel* p = NULL; // pointer to pixel structure
817  netpixel* q = NULL; // pointer to pixel structure
818  std::vector<int>* v;
819  float eps;
820  double E;
821  bool insert;
822  double ptime, pfreq;
823  double qtime, qfreq;
824 
825  netpixel** pp = (netpixel**)malloc(n*sizeof(netpixel*));
826  netpixel** ppo = pp;
827  netpixel* g;
828 
829 // sort pixels
830 
831  for(i=0; i<n; i++) { pp[i] = &(pList[i]);}
832  g = pp[0];
833  qsort(pp, n, sizeof(netpixel*), &compare_PIX); // sort pixels
834 
835 // update neighbors
836 
837  for(i=0; i<n; i++) {
838  p = pp[i];
839  M = size_t(this->rate/p->rate+0.5); // number of frequency layers
840  ptime = (p->time/M+0.5)/p->rate; // extract time
841  pfreq = (p->frequency+0.5)*p->rate;
842 
843  for(j=i+1; j<n; j++){
844  q = pp[j];
845 
846  eps = 0.55/p->rate + 0.55/q->rate;
847  M = size_t(this->rate/q->rate+0.5); // number of frequency layers
848  qtime = (q->time/M+0.5)/q->rate;
849 
850  if(qtime<ptime-eps) cout<<"netcluster::merge() error"<<endl;
851 
852  if(qtime-ptime > 1.) break;
853  if(fabs(qtime-ptime) > eps) continue;
854  if(p->rate==q->rate) continue;
855  if(!(p->rate==2*q->rate || q->rate==2*p->rate)) continue;
856 
857  eps = 0.55*(p->rate+q->rate);
858  qfreq = (q->frequency+0.5)*q->rate;
859  if(fabs(pfreq-qfreq) > eps) continue;
860 
861 // insert in p
862 
863  l = q-p;
864 
865  insert = true;
866  v = &(p->neighbors);
867  m = v->size();
868  for(k=0; k<m; k++) {
869  if((*v)[k] == l) {insert=false; break;}
870  }
871  if(insert) p->append(l); // add new neighbor
872 
873 // insert in q
874 
875  l = p-q;
876 
877  insert = true;
878  v = &(q->neighbors);
879  m = v->size();
880  for(k=0; k<m; k++) {
881  if((*v)[k] == l) {insert=false; break;}
882  }
883  if(insert) q->append(l); // add new neighbor
884 
885  }
886  }
887 
888  if(ppo==pp) free(pp);
889  else {cout<<"netcluster::cluster() free()\n"; exit(1);}
890 
891 //***************
892  cluster();
893 //***************
894 
895  std::vector<vector_int>::iterator it;
896  netpixel* pix = NULL;
897  std::vector<int> rate;
898  std::vector<int> temp;
899  std::vector<int> sIZe;
900  std::vector<bool> cuts;
901  std::vector<double> ampl;
902  std::vector<double> powr;
903  std::vector<double> like;
904 
905  double a,L,e,tt,cT,cF,nT,nF;
906  size_t ID,mm;
907  size_t max = 0;
908  size_t min = 0;
909  size_t count=0;
910  bool cut;
911  bool oEo = atype=='E' || atype=='P';
912 
913  for(it=cList.begin(); it != cList.end(); it++) {
914  k = it->size();
915  if(!k) cout<<"netcluster::supercluster() error: empty cluster.\n";
916 
917 // fill cluster statistics
918 
919  m = 0; E = 0;
920  cT=cF=nT=nF=0.;
921  rate.clear();
922  ampl.clear();
923  powr.clear();
924  like.clear();
925  cuts.clear();
926  sIZe.clear();
927  temp.clear();
928 
929  ID = pList[((*it)[0])].clusterID;
930 
931  for(i=0; i<k; i++) {
932  pix = &(pList[((*it)[i])]);
933  if(!pix->core && core) continue;
934  L = pix->likelihood;
935  e = 0.;
936  for(j=0; j<pix->size(); j++) {
937  a = pix->data[j].asnr;
938  e+= fabs(a)>1. ? a*a-1 : 0.;
939  }
940 
941  a = atype=='L' ? L : e;
942  tt = 1./pix->rate; // wavelet time resolution
943  mm = size_t(this->rate*tt+0.1); // number of wavelet layers
944  cT += (pix->time/mm + 0.5)*a; // pixel time sum
945  nT += a/tt; // use weight L/t
946  cF += (pix->frequency+0.5)*a; // pixel frequency sum
947  nF += a*2.*tt; // use weight L*2t
948 
949  insert = true;
950  for(j=0; j<rate.size(); j++) {
951  if(rate[j] == int(pix->rate+0.1)) {
952  insert=false;
953  ampl[j] += e;
954  sIZe[j] += 1;
955  like[j] += L;
956  }
957  }
958 
959  if(insert) {
960  rate.push_back(int(pix->rate+0.1));
961  ampl.push_back(e);
962  powr.push_back(0.);
963  sIZe.push_back(1);
964  cuts.push_back(true);
965  like.push_back(L);
966  }
967 
968  m++; E += e;
969 
970  if(ID != pix->clusterID)
971  cout<<"netcluster::merge() error: cluster ID mismatch.\n";
972  }
973 
974 // cut off single level clusters
975 // coincidence between levels
976 
977  if(rate.size()<size_t(1+this->pair) || m<nPIX){ sCuts[ID-1] = true; continue; }
978 
979  cut = true;
980  for(i=0; i<rate.size(); i++) {
981  if((atype=='L' && like[i]<S) || (oEo && ampl[i]<S)) continue;
982  if(!pair) { cuts[i] = cut = false; continue; }
983  for(j=0; j<rate.size(); j++) {
984  if((atype=='L' && like[j]<S) || (oEo && ampl[j]<S)) continue;
985  if(rate[i]/2==rate[j] || rate[j]/2==rate[i]) {
986  cuts[i] = cuts[j] = cut = false;
987  }
988  }
989  }
990  if(cut || sCuts[ID-1]) { sCuts[ID-1] = true; continue; }
991 
992 // select optimal resolution
993 
994  a = -1.e99;
995  for(j=0; j<rate.size(); j++) { // select max excess power or likelihood
996  powr[j] = ampl[j]/sIZe[j];
997  if(atype=='E' && ampl[j]>a && !cuts[j]) {max=j; a=ampl[j];}
998  if(atype=='L' && like[j]>a && !cuts[j]) {max=j; a=like[j];}
999  if(atype=='P' && powr[j]>a && !cuts[j]) {max=j; a=powr[j];}
1000  }
1001 
1002  if(a<S) { sCuts[ID-1] = true; continue; }
1003 
1004  a = -1.e99;
1005  for(j=0; j<rate.size(); j++) {
1006  if(max==j) continue;
1007  if(atype=='E' && ampl[j]>a && !cuts[j]) {min=j; a=ampl[j];}
1008  if(atype=='L' && like[j]>a && !cuts[j]) {min=j; a=like[j];}
1009  if(atype=='P' && powr[j]>a && !cuts[j]) {max=j; a=powr[j];}
1010  }
1011 
1012  temp.push_back(rate[max]);
1013  temp.push_back(rate[min]);
1014  cTime[ID-1] = cT/nT;
1015  cFreq[ID-1] = cF/nF;
1016  cRate[ID-1] = temp;
1017  count++;
1018 
1019  }
1020 
1021  return count;
1022 }
1023 
1024 
1025 //**************************************************************************
1026 // construct super clusters for 2G analysis
1027 //**************************************************************************
1028 size_t netcluster::supercluster(char atype, double S, double gap, bool core, TH1F* his)
1029 {
1030 //:reconstruct clusters at several TF resolutions (superclusters)
1031 //!param: statistic: 'E' - excess power, 'L' - likelihood
1032 //!param: selection threshold S defines a threshold on clusters
1033 //! in a superclusters.
1034 //!param: time-frequency gap used for clustering
1035 //!param: true - use only core pixels, false - use core & halo pixels
1036 //!return size of pixel list of selected superclusters.
1037 // algorithm:
1038 // - sort the pixel list with compare_PIX condition
1039 // - calculate the tim-frequency gap between pixels (1&2) with the same or
1040 // adjacent resolutions: eps = (dT>0?dT*R:0) + (dF>0?dF*T:0), where
1041 // dT/dF are time/frequency gaps, R/T are average rate and time:
1042 // R = rate1+rate2, T = 1/rate1+1/rqte2.
1043 // - if the clustering condition is satisfied, update the neighbor array
1044 // - cluster
1045 // - select superclusters with with clusters in the adjacent resolutions if
1046 // this->pair is true.
1047 // in this function the optimal resolution is defined but not used
1048 
1049  size_t i,j,k,m;
1050  size_t n = pList.size();
1051  int l;
1052 
1053  if(!n) return 0;
1054 
1055  netpixel* p = NULL; // pointer to pixel structure
1056  netpixel* q = NULL; // pointer to pixel structure
1057  std::vector<int>* v;
1058  double eps,E,R,T,dT,dF,prl,qrl,aa;
1059  bool insert;
1060  double ptime, pfreq;
1061  double qtime, qfreq;
1062  double Tgap = 0.;
1063  size_t nIFO = pList[0].size(); // number of detectors
1064 
1065  netpixel** pp = (netpixel**)malloc(n*sizeof(netpixel*));
1066  netpixel** ppo = pp;
1067  netpixel* g;
1068 
1069 // sort pixels
1070 
1071  for(i=0; i<n; i++) {
1072  pp[i] = &(pList[i]);
1073  R = pp[i]->rate;
1074  if(1./R > Tgap) Tgap = 1./R; // calculate max time bin
1075  }
1076  Tgap *= (1.+gap);
1077 
1078  // printf("gap = %lf\t dF = %lf\t S = %lf\n", gap, dF, S);
1079 
1080  g = pp[0];
1081  qsort(pp, n, sizeof(netpixel*), &compare_PIX); // sort pixels
1082 
1083  // update neighbors
1084 
1085  for(i=0; i<n; i++) {
1086  p = pp[i];
1087  prl = p->rate*p->layers;
1088  ptime = p->time/prl; // time in seconds
1089  pfreq = p->frequency*p->rate; // frequency in Hz
1090 
1091  for(j=i+1; j<n; j++){
1092  q = pp[j];
1093  qrl = q->rate*q->layers;
1094  if(p->clusterID && p->clusterID==q->clusterID) continue;
1095  qtime = q->time/qrl; // time in seconds
1096  if(qtime-ptime > Tgap) {break;} //printf("gap breaking!\n"); break;}
1097  if(p->rate/q->rate > 3) continue;
1098  if(q->rate/p->rate > 3) continue;
1099  qfreq = q->frequency*q->rate; // frequency in Hz
1100 
1101  if(qtime<ptime) {
1102  cout<<"netcluster::supercluster() error "<<qtime-ptime<<endl;
1103  cout<<p->rate<<" "<<q->rate<<" "<<p->time<<" "<<q->time<<endl;
1104  }
1105 
1106  R = p->rate+q->rate;
1107  T = 1/p->rate+1/q->rate;
1108 
1109  dT = 0.;
1110  for(k=0; k<nIFO; k++) { // max time gap among all detectors
1111  aa = p->data[k].index/prl; // time in seconds
1112  aa-= q->data[k].index/qrl; // time in seconds
1113  if(fabs(aa)>dT) dT = fabs(aa);
1114  }
1115 
1116  dT -= 0.5*T; // time gap between pixels
1117  dF = fabs(qfreq-pfreq) - 0.5*R; // frequency gap between pixels
1118  eps = (dT>0?dT*R:0) + (dF>0?dF*T:0); // 2 x number of pixels
1119  if(his) his->Fill(eps);
1120  if(gap < eps) continue;
1121 
1122  // insert in p
1123 
1124  l = q-p;
1125  insert = true;
1126  v = &(p->neighbors);
1127  m = v->size();
1128 
1129  for(k=0; k<m; k++) {
1130  if((*v)[k] == l) {insert=false; break;}
1131  }
1132 
1133  if(insert) p->append(l); // add new neighbor
1134 
1135  // insert in q
1136 
1137  l = p-q;
1138  insert = true;
1139  v = &(q->neighbors);
1140  m = v->size();
1141 
1142  for(k=0; k<m; k++) {
1143  if((*v)[k] == l) {insert=false; break;}
1144  }
1145 
1146  if(insert) q->append(l); // add new neighbor
1147  }
1148  }
1149 
1150  if(ppo==pp) free(pp);
1151  else {cout<<"netcluster::supercluster() free()\n"; exit(1);}
1152 
1153 //***************
1154  cluster();
1155 //***************
1156 
1157  std::vector<vector_int>::iterator it;
1158  netpixel* pix = NULL;
1159  std::vector<int> rate;
1160  std::vector<int> temp;
1161  std::vector<int> sIZe;
1162  std::vector<bool> cuts;
1163  std::vector<double> ampl;
1164  std::vector<double> powr;
1165  std::vector<double> like;
1166 
1167  double a,L,e,tt,cT,cF,nT,nF;
1168  size_t ID,mm;
1169  size_t max = 0;
1170  size_t min = 0;
1171  size_t count=0;
1172  bool cut;
1173  bool oEo = atype=='E' || atype=='P';
1174 
1175  for(it=cList.begin(); it != cList.end(); it++) {
1176  k = it->size();
1177  if(!k) cout<<"netcluster::supercluster() error: empty cluster.\n";
1178 
1179  // fill cluster statistics
1180 
1181  m = 0; E = 0;
1182  cT=cF=nT=nF=0.;
1183  rate.clear();
1184  ampl.clear();
1185  powr.clear();
1186  like.clear();
1187  cuts.clear();
1188  sIZe.clear();
1189  temp.clear();
1190 
1191  ID = pList[((*it)[0])].clusterID;
1192 
1193  for(i=0; i<k; i++) { // for each pixel in the cluster
1194  pix = &(pList[((*it)[i])]);
1195  if(!pix->core && core) continue;
1196  L = pix->likelihood;
1197  e = 0.;
1198  for(j=0; j<pix->size(); j++) {
1199  a = pix->data[j].asnr; // asnr is an energy
1200  e+= fabs(a)>1. ? a : 0.;
1201  }
1202 
1203  a = atype=='L' ? L : e;
1204  tt = 1./pix->rate; // wavelet time resolution
1205  mm = pix->layers; // number of wavelet layers
1206  cT += int(pix->time/mm)*a; // pixel time sum
1207  nT += a/tt; // use weight L/t
1208  cF += (pix->frequency+dF)*a; // pixel frequency sum
1209  nF += a*2.*tt; // use weight L*2t
1210 
1211  insert = true;
1212  for(j=0; j<rate.size(); j++) {
1213  if(rate[j] == int(pix->rate+0.1)) {
1214  insert=false;
1215  ampl[j] += e;
1216  sIZe[j] += 1;
1217  like[j] += L;
1218  }
1219  }
1220 
1221  if(insert) {
1222  rate.push_back(int(pix->rate+0.1));
1223  ampl.push_back(e);
1224  powr.push_back(0.);
1225  sIZe.push_back(1);
1226  cuts.push_back(true);
1227  like.push_back(L);
1228  }
1229 
1230  m++; E += e;
1231 
1232  if(ID != pix->clusterID)
1233  cout<<"netcluster::supercluster() error: cluster ID mismatch.\n";
1234  }
1235 
1236  // cut off single level clusters
1237  // coincidence between levels
1238 
1239  if((int)rate.size()< this->pair+1 || m<nPIX){ sCuts[ID-1] = 1; continue; }
1240 
1241  cut = true;
1242  for(i=0; i<rate.size(); i++) {
1243  if((atype=='L' && like[i]<S) || (oEo && ampl[i]<S)) continue;
1244  if(!pair) { cuts[i] = cut = false; continue; }
1245  for(j=0; j<rate.size(); j++) {
1246  if((atype=='L' && like[j]<S) || (oEo && ampl[j]<S)) continue;
1247  if(rate[i]/2==rate[j] || rate[j]/2==rate[i]) {
1248  cuts[i] = cuts[j] = cut = false;
1249  }
1250  }
1251  }
1252  if(cut || sCuts[ID-1]) { sCuts[ID-1] = 1; continue; }
1253 
1254  // select optimal resolution
1255 
1256  a = -1.e99;
1257  for(j=0; j<rate.size(); j++) { // select max excess power or likelihood
1258  powr[j] = ampl[j]/sIZe[j];
1259  if(atype=='E' && ampl[j]>a && !cuts[j]) {max=j; a=ampl[j];}
1260  if(atype=='L' && like[j]>a && !cuts[j]) {max=j; a=like[j];}
1261  if(atype=='P' && powr[j]>a && !cuts[j]) {max=j; a=powr[j];}
1262  }
1263 
1264  if(a<S) { sCuts[ID-1] = 1; continue; }
1265 
1266  a = -1.e99;
1267  for(j=0; j<rate.size(); j++) {
1268  if(max==j) continue;
1269  if(atype=='E' && ampl[j]>a && !cuts[j]) {min=j; a=ampl[j];}
1270  if(atype=='L' && like[j]>a && !cuts[j]) {min=j; a=like[j];}
1271  if(atype=='P' && powr[j]>a && !cuts[j]) {min=j; a=powr[j];}
1272  }
1273 
1274  temp.push_back(rate[max]);
1275  temp.push_back(rate[min]);
1276  temp.push_back(E);
1277  cTime[ID-1] = cT/nT;
1278  cFreq[ID-1] = cF/nF;
1279  cRate[ID-1] = temp;
1280  cData[ID-1].cTime = cT/nT;
1281  cData[ID-1].cFreq = cF/nF;
1282  cData[ID-1].energy = E;
1283  cData[ID-1].likenet = E;
1284  count++;
1285 
1286  }
1287 
1288  return count;
1289 }
1290 
1291 //**************************************************************************
1292 // construct duperclusters for 2G analysis
1293 //**************************************************************************
1294 size_t netcluster::defragment(double tgap, double fgap, TH2F* his)
1295 {
1296 // construct duperclusters for 2G analysis
1297 // merge clusters if they are close to each other in time and frequency
1298 // tgap - maximum time gap in seconds
1299 // fgap - maximum frequency gap in Hz
1300 
1301  size_t i,j,k;
1302  size_t I = pList.size();
1303  int l,n,m;
1304 
1305  if(!I) return 0;
1306  if(tgap<=0 && fgap<=0) return 0;
1307 
1308  netpixel* p = NULL; // pointer to pixel structure
1309  netpixel* q = NULL; // pointer to pixel structure
1310  std::vector<int>* v;
1311  std::vector<int>* u;
1312  double R,T,dT,dF,x,a,E,prl,qrl;
1313  bool insert;
1314  double ptime, pfreq;
1315  double qtime, qfreq;
1316  double Tgap = 0.;
1317  size_t nIFO = pList[0].size(); // number of detectors
1318 
1319  netpixel** pp = (netpixel**)malloc(I*sizeof(netpixel*));
1320  netpixel** ppo = pp;
1321 
1322  for(i=0; i<I; i++) {
1323  pp[i] = &(pList[i]);
1324  R = pp[i]->rate;
1325  if(!(pp[i]->clusterID)) {
1326  cout<<"defragment: un-clustered pixel list \n"; exit(1);
1327  }
1328  if(1./R > Tgap) Tgap = 1./R; // calculate max time bin
1329  }
1330  if(Tgap<tgap) Tgap = tgap;
1331 
1332  //printf("gap = %lf\t dF = %lf\t I = %d\n", Tgap, Fgap, I);
1333 
1334  // sort pixels
1335 
1336  qsort(pp, I, sizeof(netpixel*), &compare_PIX); // sort pixels
1337 
1338  // update neighbors
1339 
1340  for(i=0; i<I; i++) {
1341  p = pp[i];
1342  n = p->clusterID;
1343  prl = p->rate*p->layers;
1344  if(sCuts[n-1]==1) continue; // skip rejected pixels
1345  ptime = p->time/prl; // time in seconds
1346  pfreq = p->frequency*p->rate/2.; // frequency in Hz
1347 
1348  for(j=i+1; j<I; j++){
1349  q = pp[j];
1350  m = q->clusterID;
1351  qrl = q->rate*q->layers;
1352  if(sCuts[m-1]==1) continue; // skip rejected pixels
1353  if(n==m) continue; // skip the same cluster
1354  qtime = q->time/qrl; // time in seconds
1355  if(qtime-ptime > Tgap) {break;} //printf("gap breaking!\n"); break;}
1356  if(p->rate/q->rate > 3) continue;
1357  if(q->rate/p->rate > 3) continue;
1358  qfreq = q->frequency*q->rate/2.; // frequency in Hz
1359  T = 1/p->rate+1/q->rate;
1360  R = p->rate+q->rate;
1361 
1362  if(qtime<ptime) {
1363  cout<<"netcluster::defragment() error "<<qtime-ptime<<endl;
1364  cout<<p->rate<<" "<<q->rate<<" "<<p->time<<" "<<q->time<<endl;
1365  exit(1);
1366  }
1367 
1368  dT = 0.;
1369  for(k=0; k<nIFO; k++) { // max time gap among all detectors
1370  a = p->data[k].index/prl; // time in seconds
1371  a -= q->data[k].index/qrl; // time in seconds
1372  if(fabs(a)>dT) dT = fabs(a);
1373  }
1374 
1375  dT -= 0.5*T; // time gap between pixels
1376  dF = fabs(qfreq-pfreq) - 0.25*R; // frequency gap between pixels
1377  if(his) his->Fill(dT,dF);
1378  if(dT > tgap) continue;
1379  if(dF > fgap) continue;
1380 
1381  // insert in p
1382 
1383  l = q-p;
1384  insert = true;
1385  v = &(p->neighbors);
1386 
1387  for(k=0; k<v->size(); k++) {
1388  if((*v)[k] == l) {insert=false; break;}
1389  }
1390 
1391  if(insert) p->append(l); // add new neighbor
1392 
1393  // insert in q
1394 
1395  l = p-q;
1396  insert = true;
1397  v = &(q->neighbors);
1398 
1399  for(k=0; k<v->size(); k++) {
1400  if((*v)[k] == l) {insert=false; break;}
1401  }
1402 
1403  if(insert) q->append(l); // add new neighbor
1404 
1405  // replace cluster ID
1406 
1407  v = &(this->cList[n-1]); // append to this pixel list
1408  u = &(this->cList[m-1]); // append from this pixel list
1409  for(k=0; k<u->size(); k++) {
1410  pList[(*u)[k]].clusterID = n; // set cluster ID=n in q-pixel
1411  v->push_back((*u)[k]); // add q-pixel to n-cluster
1412  }
1413  sCuts[m-1] = 1; // mask m cluster
1414  u->clear(); // clear pixel list
1415  }
1416  }
1417 
1418  if(ppo==pp) free(pp);
1419  else {cout<<"netcluster::defragment() free()\n"; exit(1);}
1420  return esize();
1421 }
1422 
1423 
1424 double netcluster::mchirp(int ID, double chi2_thr, double tmerger_cut, double zmax_thr)
1425 {
1426 // Reconstruction of time-frequency trend parametrizied by the chirp mass parameter,
1427 // which becomes an astrophysical charp mass only in case of CBC sources.
1428 // param 1 - cluster ID
1429 // param 2 - chi2 threshold for selection of chirp pixels
1430 // param 3 - tmerger cut: exclude pixels with time > tmerger+param3 - special use
1431 // param 4 - threshold for pixel selection - special use
1432 // returns reconstructed chirp energy
1433  const double G = watconstants::GravitationalConstant();
1434  const double SM = watconstants::SolarMass();
1435  const double C = watconstants::SpeedOfLightInVacuo();
1436  const double Pi = TMath::Pi();
1437  double kk = 256.*Pi/5*pow(G*SM*Pi/C/C/C, 5./3);
1438 
1439  std::vector<int>* vint = &this->cList[ID-1];
1440  int V = vint->size();
1441  if(!V) return -1;
1442 
1443  bool chi2_cut = chi2_thr<0 ? true : false;
1444  chi2_thr = fabs(chi2_thr);
1445 
1446  double* x = new double[V];
1447  double* y = new double[V];
1448  double* xerr = new double[V];
1449  double* yerr = new double[V];
1450  double* wgt = new double[V];
1451 
1452  double tmin=1e20;
1453  double tmax=0.;
1454  double T, rms;
1455 
1456 
1457  this->cData[ID-1].chi2chirp = 0;
1458  this->cData[ID-1].mchirp = 0 ;
1459  this->cData[ID-1].mchirperr = -1;
1460  this->cData[ID-1].tmrgr = 0;
1461  this->cData[ID-1].tmrgrerr = -1;
1462  this->cData[ID-1].chirpEllip = 0; // chirp ellipticity
1463  this->cData[ID-1].chirpEfrac = 0; // chirp energy fraction
1464  this->cData[ID-1].chirpPfrac = 0; // chirp pixel fraction
1465 
1466  // scaling of frequency: in units of 128Hz
1467  double sF = 128;
1468  kk *= pow(sF, 8./3);
1469  int np = 0;
1470  double xmin,ymin, xmax, ymax;
1471  xmin = ymin = 1e100;
1472  xmax = ymax = -1e100;
1473 
1474  double emax = -1e100;
1475  for(int j=0; j<V; j++) {
1476  netpixel* pix = this->getPixel(ID, j);
1477  if(pix->likelihood>emax) emax = pix->likelihood;
1478  }
1479  double zthr = zmax_thr*emax;
1480 
1481  for(int j=0; j<V; j++) {
1482  netpixel* pix = this->getPixel(ID, j);
1483  if(pix->likelihood<=zthr || pix->frequency==0) continue;
1484 
1485  T = int(double(pix->time)/pix->layers);
1486  T = T/pix->rate; // time in seconds from the start
1487  if(T<tmin) tmin=T;
1488  if(T>tmax) tmax=T;
1489 
1490  x[np] = T ;
1491  xerr[np] = 0.5/pix->rate;
1492  xerr[np] = xerr[np]*sqrt(2.);
1493 
1494  y[np] = pix->frequency*pix->rate/2.;
1495  yerr[np] = pix->rate/4;
1496  yerr[np] = yerr[np]/sqrt(3.);
1497 
1498  y[np] /= sF;
1499  yerr[np] /= sF;
1500  wgt[np] = pix->likelihood;
1501  yerr[np] *= 8./3/pow(y[np], 11./3); // frequency transformation
1502  y[np] = 1./pow(y[np], 8./3);
1503 
1504  if(x[np]>xmax) xmax = x[np];
1505  if(x[np]<xmin) xmin = x[np];
1506  if(y[np]>ymax) ymax = y[np];
1507  if(y[np]<ymin) ymin = y[np];
1508  ++np;
1509  }
1510  if(np<5) return -1;
1511 
1512  double xcm, ycm, qxx, qyy, qxy;
1513  xcm = ycm = qxx = qyy = qxy = 0;
1514 
1515  for(int i=0; i<np; ++i){
1516  xcm += x[i];
1517  ycm += y[i];
1518  }
1519  xcm /= np;
1520  ycm /= np;
1521 
1522  for(int i=0; i<np; ++i){
1523  qxx += (x[i] - xcm)*(x[i] - xcm);
1524  qyy += (y[i] - ycm)*(y[i] - ycm);
1525  qxy += (x[i] - xcm)*(y[i] - ycm);
1526  }
1527 
1528  //printf(" | %lf , %lf |\n", qxx, qxy);
1529  //printf(" | %lf , %lf |\n", qxy, qyy);
1530 
1531  double sq_delta = sqrt( (qxx - qyy)*(qxx - qyy) + 4*qxy*qxy );
1532  double lam1 = (qxx + qyy + sq_delta)/2;
1533  double lam2 = (qxx + qyy - sq_delta)/2;
1534  lam1 = sqrt(lam1);
1535  lam2 = sqrt(lam2);
1536  double ellipt = fabs((lam1 - lam2)/(lam1 + lam2));
1537 
1538  const double maxM = 100;
1539  const double stepM = 0.2;
1540  const int massPoints = 1001;
1541 
1542  int maxMasses[massPoints];
1543  int nmaxm = 0;
1544 
1545  EndPoint* bint[massPoints]; // stores b intervals for all pixels, satisfying chi2<2
1546  for(int j=0; j<massPoints; ++j) bint[j] = new EndPoint[2*np];
1547 
1548  int nselmax = 0;
1549  int massIndex = 0;
1550 
1551  for(double m = -maxM; m<maxM + 0.01; m+=stepM){
1552  double sl = kk*pow(fabs(m), 5./3);
1553  if(m>0) sl = -sl; // this is real slope, proper sign
1554 
1555  int j=0;
1556  for(int i=0; i<np; ++i){
1557  double Db = sqrt( 2 * (sl*sl*xerr[i]*xerr[i] + yerr[i]*yerr[i]) );
1558  double bmini = y[i] - sl*x[i] - Db;
1559  double bmaxi = bmini + 2*Db;
1560  bint[massIndex][j].value = bmini;
1561  bint[massIndex][j].type = 1;
1562  bint[massIndex][++j].value = bmaxi;
1563  bint[massIndex][j++].type = -1;
1564  }
1565  qsort(bint[massIndex], 2*np, sizeof(EndPoint), compEndP);
1566 
1567  int nsel = 1;
1568  for(j=1; j<2*np; ++j){
1569  bint[massIndex][j].type += bint[massIndex][j-1].type;
1570  if(bint[massIndex][j].type>nsel)nsel = bint[massIndex][j].type;
1571  }
1572  if(nsel>nselmax){
1573  nselmax = nsel;
1574  maxMasses[0] = massIndex;
1575  nmaxm = 1;
1576  }
1577  else if(nsel == nselmax) maxMasses[nmaxm++] = massIndex;
1578 
1579  ++massIndex;
1580  }
1581 
1582 
1583  double m0, b0;
1584  double chi2min = 1e100;
1585 
1586  // fine parsing in b range, optimize chi2:
1587  for(int j=0; j<nmaxm; ++j){
1588  double m = -maxM + maxMasses[j]*stepM;
1589  double sl = kk*pow(fabs(m), 5./3);
1590  if(m>0) sl = -sl;
1591 
1592  for(int k=0; k<2*np-1; ++k)if(bint[maxMasses[j]][k].type==nselmax)
1593  for(double b = bint[maxMasses[j]][k].value; b<bint[maxMasses[j]][k+1].value; b+=0.0025){
1594  double totchi = 0;
1595  double totwgt = 0;
1596  for(int i=0; i<np; ++i){
1597  double chi2 = y[i] - sl*x[i] - b;
1598  chi2 *= chi2;
1599  chi2 /= (sl*sl*xerr[i]*xerr[i] + yerr[i]*yerr[i]);
1600  if(chi2>chi2_thr) continue;
1601  totchi += chi2*wgt[i];
1602  totwgt += wgt[i];
1603  }
1604  totchi = totwgt ? totchi/totwgt : 2e100;
1605  if(totchi<chi2min){
1606  chi2min = totchi;
1607  m0 = m;
1608  b0 = b;
1609  }
1610  }
1611  }
1612 
1613  for(int j=0; j<massPoints; ++j) delete [] bint[j];
1614 
1615 
1616  double sl = kk*pow(fabs(m0), 5./3);
1617  if(m0>0) sl = -sl;
1618 
1619 
1620  double totEn = 0.;
1621  double selEn = 0.;
1622  double tmax2 = 0.;
1623  double chi2T = 0;
1624 
1625  for(int i=0; i<np; ++i){
1626  totEn += wgt[i];
1627  double chi2 = y[i] - sl*x[i] - b0;
1628  chi2 *= chi2;
1629  chi2 /= (sl*sl*xerr[i]*xerr[i] + yerr[i]*yerr[i]);
1630  chi2T += chi2*wgt[i];
1631  if(chi2>chi2_thr) continue;
1632  selEn += wgt[i];
1633  if(x[i]>tmax2) tmax2 = x[i];
1634  }
1635 
1636  double Efrac = selEn/totEn;
1637  chi2T = chi2T/totEn;
1638 
1639  tmax2 += 1e-6;
1640 
1641  // shift selected pixels on first positions
1642  double echirp=0;
1643  int j=0;
1644  double Pfrac = 0;
1645  int nifo = pList[0].size();
1646  for(int i=0; i<np; ++i){
1647  if(x[i]<tmax2) Pfrac += 1.0;
1648  double chi2 = y[i] - sl*x[i] -b0;
1649  chi2 *= chi2;
1650  chi2 /= (sl*sl*xerr[i]*xerr[i] + yerr[i]*yerr[i]);
1651 
1652  if(chi2>chi2_thr) continue;
1653  x[j] = x[i]; xerr[j] = xerr[i];
1654  y[j] = y[i]; yerr[j] = yerr[i];
1655  ++j;
1656  }
1657  np = j;
1658  Pfrac = np/Pfrac;
1659 
1660  // set pix->likelihood=0 for all pixels with chi2<chi2_thr
1661  // compute chirp energy for chi2<chi2_thr
1662  for(int i=0; i<V; ++i){
1663  netpixel* pix = this->getPixel(ID, i);
1664 
1665  T = int(double(pix->time)/pix->layers);
1666  T = T/pix->rate; // time in seconds from the start
1667 
1668  double eT = 0.5/pix->rate;
1669  double F = pix->frequency*pix->rate/2.;
1670  double eF = pix->rate/4;
1671  F /= sF;
1672  eF /= sF;
1673 
1674  eT*=sqrt(2.);
1675  eF/=sqrt(3.);
1676 
1677  eF *= 8./3/pow(F, 11./3); // frequency transformation
1678  F = 1./pow(F, 8./3);
1679 
1680  double chi2 = F - sl*T -b0;
1681  chi2 *= chi2;
1682  chi2 /= (sl*sl*eT*eT + eF*eF);
1683  if(chi2_cut && chi2<chi2_thr) { // set pixels likelihood=0 (used to select higher order mode)
1684  if(pix->likelihood>0) echirp += pix->likelihood;
1685  pix->likelihood=0;
1686  }
1687  }
1688 
1689 
1690  //if(Efrac > 1) printf("MCHIRP5ERR_EFRAC\n");
1691  //if(frac > 1) printf("MCHIRP5ERR_FRAC\n");
1692 
1693  // recompute ellipticity
1694 
1695  xcm = ycm = qxx = qyy = qxy = 0;
1696 
1697  for(int i=0; i<np; ++i){
1698  xcm += x[i];
1699  ycm += y[i];
1700  }
1701  xcm /= np;
1702  ycm /= np;
1703 
1704  for(int i=0; i<np; ++i){
1705  qxx += (x[i] - xcm)*(x[i] - xcm);
1706  qyy += (y[i] - ycm)*(y[i] - ycm);
1707  qxy += (x[i] - xcm)*(y[i] - ycm);
1708  }
1709 
1710  //printf(" | %lf , %lf |\n", qxx, qxy);
1711  //printf(" | %lf , %lf |\n", qxy, qyy);
1712 
1713  sq_delta = sqrt( (qxx - qyy)*(qxx - qyy) + 4*qxy*qxy );
1714  lam1 = (qxx + qyy + sq_delta)/2;
1715  lam2 = (qxx + qyy - sq_delta)/2;
1716  lam1 = sqrt(lam1);
1717  lam2 = sqrt(lam2);
1718  double ellipt2 = fabs((lam1 - lam2)/(lam1 + lam2));
1719 
1720 
1721  // bootstrapping section
1722 
1723  if(np<=0)return 0;
1724  //printf("MCHIRP5ERR_NPZERO\n");
1725 
1726  wavearray<int> used(np);
1727 
1728  int np2 = np*0.5, Trials=500;
1729  if(np2<3)np2 = np-1;
1730 
1731  if(np2<8)Trials = np2;
1732  else if(np2<15) Trials = np2*np2/2;
1733  else if(np2<20) Trials = np2*np2*np2/6;
1734  if(Trials>500) Trials = 500;
1735  if(Trials<0) Trials=0;
1736 
1737  this->cData[ID-1].mchpdf.resize(Trials);
1738  TRandom3 rnd(0);
1739  wavearray<float> slpv(Trials);
1740  wavearray<float> mchv(Trials);
1741  wavearray<float> bv(Trials);
1742 
1743  for(int ii=0; ii<Trials; ++ii){
1744  // generate random sequence
1745  used = 0;
1746  for(int k, i=0; i<np2; ++i){
1747  do k = rnd.Uniform(0. , np - 1e-10);
1748  while(used[k]);
1749  used[k]=1;
1750  }
1751 
1752  // linear fit, no weights for now
1753  double sx=0, sy=0, sx2=0, sxy=0;
1754  for(int i=0; i<np; ++i)if(used[i]){
1755  //x[i] -= tmin;
1756  sx += x[i];
1757  sy += y[i];
1758  sx2 += x[i]*x[i];
1759  sxy += x[i]*y[i];
1760  }
1761  double slp = (sy/np2 - sxy/sx)/(sx2/sx - sx/np2);
1762  double b = (sy + slp*sx)/np2;
1763 
1764  slpv.data[ii] = slp;
1765  mchv.data[ii] = slp>0 ? pow(slp/kk,0.6) : -pow(-slp/kk, 0.6);
1766  bv.data[ii] = b/slp;
1767  this->cData[ID-1].mchpdf.data[ii] = mchv.data[ii];
1768  }
1769 
1770 
1771  size_t nn = mchv.size()-1;
1772  size_t ns = size_t(mchv.size()*0.16);
1773  cData[ID-1].mchirperr = Trials>8 ? ( mchv.waveSplit(0,nn,nn-ns)-mchv.waveSplit(0,nn,ns) ) / 2 : 2*mchv.rms();
1774 
1775  // end bootstrapping section
1776 
1777  char name[100];
1778  sprintf(name, "netcluster::mchirp5:func_%d", ID);
1779 
1780 #ifdef _USE_ROOT6
1781  TGraphErrors *gr = new TGraphErrors(np, x, y, xerr, yerr);
1782  TF1 *f = new TF1(name, "[0]*x + [1]", xmin, xmax);
1783 
1784  this->cData[ID-1].chirp.Set(np);
1785  for(int i=0;i<np;i++) {
1786  this->cData[ID-1].chirp.SetPoint(i,x[i],y[i]);
1787  this->cData[ID-1].chirp.SetPointError(i,xerr[i],yerr[i]);
1788  }
1789  this->cData[ID-1].fit.SetName(TString("TGraphErrors_"+TString(name)).Data());
1790  this->cData[ID-1].chirp.SetName(TString("TF1_"+TString(name)).Data());
1791 #else
1792  TF1* f = &(this->cData[ID-1].fit);
1793  TGraphErrors* gr = &(this->cData[ID-1].chirp);
1794 
1795  *gr = TGraphErrors(np, x, y, xerr, yerr);
1796  *f = TF1(name, "[0]*x + [1]", xmin, xmax);
1797 #endif
1798 
1799  f->SetParameter(0, sl);
1800  f->SetParameter(1, b0);
1801  gr->Fit(f,"Q");
1802 
1803 
1804  int ndf = f->GetNDF();
1805  double mch = -f->GetParameter(0)/kk;
1806  double relerr = fabs(f->GetParError(0)/f->GetParameter(0));
1807  if(ndf==0) return -1;
1808  this->cData[ID-1].mchirp = mch>0 ? pow(mch, 0.6) : -pow(-mch, 0.6);
1809  this->cData[ID-1].tmrgr = -f->GetParameter(1)/f->GetParameter(0);
1810  this->cData[ID-1].tmrgrerr = chi2T; // total chi2 statistic;
1811  this->cData[ID-1].chirpEllip = ellipt2; // chirp ellipticity
1812  this->cData[ID-1].chirpEfrac = Efrac; // chirp energy fraction
1813  this->cData[ID-1].chirpPfrac = Pfrac; // chirp pixel fraction
1814  this->cData[ID-1].chi2chirp = chi2T; //f->GetChisquare()/ndf;
1815  //this->cData[ID-1].chi2chirp = f->GetChisquare()/ndf;
1816  this->cData[ID-1].tmrgrerr = 0.; // tmerger error
1817 
1818  // cut pixels with time > tmerger+tmerger_cut
1819  double tmerger = -f->GetParameter(1)/f->GetParameter(0);
1820  for(int i=0; i<V; ++i){
1821  netpixel* pix = this->getPixel(ID, i);
1822  T = int(double(pix->time)/pix->layers);
1823  T = T/pix->rate; // time in seconds from the start
1824  if(T>(tmerger+tmerger_cut)) pix->likelihood=0;
1825  }
1826 
1827 #ifdef _USE_ROOT6
1828  this->cData[ID-1].fit = *f;
1829  delete f;
1830  delete gr;
1831 #endif
1832 
1833  delete [] x;
1834  delete [] y;
1835  delete [] xerr;
1836  delete [] yerr;
1837  delete [] wgt;
1838 
1839  return echirp;
1840 
1841 }
1842 
1843 
1845 {
1846  const double G = watconstants::GravitationalConstant();
1847  const double SM = watconstants::SolarMass();
1848  const double C = watconstants::SpeedOfLightInVacuo();
1849  const double Pi = TMath::Pi();
1850  //double kk = 256.*Pi/5*pow(G*SM*Pi/C/C/C, 5./3);
1851 
1852  this->cData[ID-1].chi2chirp = 0;
1853  this->cData[ID-1].mchirp = 0 ;
1854  this->cData[ID-1].mchirperr = -1;
1855  this->cData[ID-1].tmrgr = 0;
1856  this->cData[ID-1].tmrgrerr = -1;
1857 
1858  double kf = pow(5./256, 3./8) * pow( C*C*C/G/SM, 5./8) / Pi; // f(t) = kf / Mc^(5/8) / (t0-t)^(3/8)
1859  double kdf = sqrt(0.6*kf*3./8); // df(t) = kdf / Mc^(5/16) / (t0-t)^(11/16)
1860 
1861  std::vector<int>* vint = &this->cList[ID-1];
1862  int V = vint->size();
1863  if(!V) return -1;
1864 
1865  int np=0;
1866  double minDT=1e10, minFreq=1e10;
1867 
1868  for(int j=0; j<V; j++) {
1869  netpixel* pix = this->getPixel(ID, j);
1870  if(pix->likelihood<1. || pix->frequency==0 || !pix->core) continue;
1871  ++np;
1872  if(pix->rate/2. < minFreq) minFreq = pix->rate/2;
1873  if(1./pix->rate < minDT) minDT = 1./pix->rate;
1874  }
1875  if(np<3)return -1;
1876  int naux = 1./(2*minDT*minFreq) + 0.5; // division
1877  int Vp = naux*V;
1878 
1879  //printf("minDT = %lf \t minFreq = %lf \t naux = %d\n", minDT, minFreq, naux);
1880 
1881  double* x = new double[Vp];
1882  double* y = new double[Vp];
1883  double* wgt = new double[Vp];
1884  bool* sel = new bool[Vp];
1885 
1886  np = 0;
1887  double tmin=1e20;
1888  double tmax=0.;
1889  double T; //, rms;
1890 
1891  double xmin,ymin, xmax, ymax;
1892  xmin = ymin = 1e100;
1893  xmax = ymax = -1e100;
1894 
1895  // break regular pixels
1896 
1897  for(int j=0; j<V; j++) {
1898  netpixel* pix = this->getPixel(ID, j);
1899  if(pix->likelihood<1. || pix->frequency==0 || !pix->core) continue;
1900  T = int(double(pix->time)/pix->layers);
1901  T = T/pix->rate; // time in seconds from the start
1902  if(T<tmin) tmin=T;
1903  if(T>tmax) tmax=T;
1904  int nx = 1./pix->rate/minDT + 0.5;
1905  int ny = pix->rate/2/minFreq + 0.5;
1906  //printf("nx = %d ny = %d\n", nx, ny);
1907  for(int ix=0; ix<nx; ++ix) {
1908  for(int iy=0; iy<ny; ++iy){
1909  x[np] = T - 0.5/pix->rate + (ix+0.5)*minDT; //xerr[np] = 0.5/pix->rate;
1910  y[np] = pix->frequency*pix->rate/2. - pix->rate/4 + (iy+0.5)*minFreq; //yerr[np] = pix->rate/4;
1911  wgt[np] = pix->likelihood/naux;
1912 
1913  if(x[np]>xmax)xmax = x[np];
1914  if(x[np]<xmin)xmin = x[np];
1915  if(y[np]>ymax)ymax = y[np];
1916  if(y[np]<ymin)ymin = y[np];
1917  ++np;
1918  }
1919  }
1920  }
1921 
1922  const double maxM = 30; // maximum chirp mass
1923  const double stepM = 0.1; // step
1924  //const int massPoints = 601;
1925 
1926  int nselmax = 0;
1927  double m0 = 0, t0max = 0;
1928  double t0 = (tmin*2 + tmax)/3;
1929 
1930  /*
1931  for(; t0<tmax+1; t0 += minDT){ // intercept loop
1932  for(double m = 0.1; m<maxM; m += stepM){ // mass scan
1933  double cf = kf/pow(m, 5./8);
1934  double cdf = kdf/pow(m, 5./16);
1935  int nsel = 0;
1936  for(int i=0; i<np; ++i){ // scan over elementary pixels
1937  double a = t0 - x[i];
1938  if(a<=0)continue;
1939  double b = sqrt(sqrt(a));
1940  b *= sqrt(b);
1941  double fi = cf/b;
1942  double df = cdf/sqrt(b*a); // evelope width in frequency
1943  if(y[i]>fi+df) continue;
1944  if(y[i]<fi-df) continue;
1945  ++nsel;
1946  }
1947  if(nsel>nselmax){ // new optimum
1948  nselmax = nsel;
1949  m0 = m;
1950  t0max = t0;
1951  }
1952  }
1953  }
1954  */
1955 
1956 
1957  int tPoints = (tmax + 1 - t0)/minDT + 1;
1958  double* maxTimes = new double[tPoints];
1959  double* maxMasses = new double[tPoints];
1960  int nmaxt = 0;
1961 
1962  EndPoint** mint = new EndPoint*[tPoints]; // stores valid m intervals for all pixels
1963  for(int j=0; j<tPoints; ++j) mint[j] = new EndPoint[2*np];
1964 
1965  int tIndex = 0;
1966  for(; t0<tmax+1; t0 += minDT){ // intercept loop
1967  int j=0;
1968  for(int i=0; i<np; ++i){
1969  double dt = t0 - x[i];
1970  if(dt<=0)continue;
1971  double dt38 = sqrt(sqrt(dt));
1972  dt38 *= sqrt(dt38);
1973  double a = kf/dt38;
1974  double b = kdf/sqrt(dt*dt38);
1975  double Delta = sqrt(b*b + 4*a*y[i]);
1976 
1977  mint[tIndex][j].value = pow( 2*a/(Delta + b), 16./5);
1978  mint[tIndex][j].type = 1;
1979  mint[tIndex][++j].value = pow( 2*a/(Delta - b), 16./5);
1980  mint[tIndex][j++].type = -1;
1981  //printf("%lf %lf\n", mint[tIndex][j-2].value, mint[tIndex][j-1].value) ;
1982  }
1983  qsort(mint[tIndex], j, sizeof(EndPoint), compEndP);
1984 
1985  int nsel = 1;
1986  double mmax;
1987  for(int k=1; k<j; ++k){
1988  mint[tIndex][k].type += mint[tIndex][k-1].type;
1989  if(mint[tIndex][k].type>=nsel){
1990  mmax = (mint[tIndex][k].value + mint[tIndex][k+1].value)/2;
1991  nsel = mint[tIndex][k].type;
1992  }
1993  }
1994  if(nsel>nselmax){
1995  nselmax = nsel;
1996  maxTimes[0] = t0;
1997  maxMasses[0] = mmax;
1998  nmaxt = 1;
1999  }
2000  else if(nsel == nselmax){ maxMasses[nmaxt] = mmax; maxTimes[nmaxt++] = t0;}
2001  ++tIndex;
2002  }
2003 
2004  t0max = maxTimes[nmaxt-1];
2005  m0 = maxMasses[nmaxt-1];
2006 
2007  for(int j=0; j<tPoints; ++j) delete [] mint[j];
2008  delete [] mint;
2009  delete [] maxTimes;
2010  delete [] maxMasses;
2011 
2012 
2013  // find selected pixels, max t among them
2014 
2015  double tmax2 = 0.;
2016 
2017  double cf = kf/pow(m0, 5./8);
2018  double cdf = kdf/pow(m0, 5./16);
2019  for(int i=0; i<np; ++i){
2020  sel[i] = false;
2021  double a = t0max - x[i];
2022  if(a<=0) continue;
2023  double b = sqrt(sqrt(a));
2024  b *= sqrt(b);
2025  double fi = cf/b;
2026  double df = cdf/sqrt(b*a);
2027  if(y[i]>fi+df) continue;
2028  if(y[i]<fi-df) continue;
2029  sel[i] = true; // flag pixels
2030  if(x[i]>tmax2) tmax2 = x[i];
2031  }
2032 
2033 
2034  // compute energy fraction (global) , pixel fraction (among those below tmax2!)s
2035  // shift selected pixels on first positions, too
2036 
2037  double totEn = 0.;
2038  double selEn = 0.;
2039  int j=0;
2040  double frac = 0;
2041  tmax2 += 1e-6;
2042 
2043  for(int i=0; i<np; ++i){
2044  totEn += wgt[i];
2045  if(x[i]<tmax2) frac += 1.0;
2046  if(sel[i]){
2047  selEn += wgt[i];
2048  x[j] = x[i];
2049  y[j] = y[i];
2050  ++j;
2051  }
2052  }
2053 
2054  double Efrac = selEn/totEn;
2055  np = j;
2056  frac = np/frac;
2057 
2058  // compute ellipticity
2059 
2060  double xcm, ycm, qxx, qyy, qxy;
2061  xcm = ycm = qxx = qyy = qxy = 0;
2062 
2063  for(int i=0; i<np; ++i){
2064  xcm += x[i];
2065  ycm += y[i];
2066  }
2067  xcm /= np;
2068  ycm /= np;
2069 
2070  for(int i=0; i<np; ++i){
2071  qxx += (x[i] - xcm)*(x[i] - xcm);
2072  qyy += (y[i] - ycm)*(y[i] - ycm);
2073  qxy += (x[i] - xcm)*(y[i] - ycm);
2074  }
2075 
2076  //printf(" | %lf , %lf |\n", qxx, qxy);
2077  //printf(" | %lf , %lf |\n", qxy, qyy);
2078 
2079  double sq_delta = sqrt( (qxx - qyy)*(qxx - qyy) + 4*qxy*qxy );
2080  double lam1 = (qxx + qyy + sq_delta)/2;
2081  double lam2 = (qxx + qyy - sq_delta)/2;
2082  lam1 = sqrt(lam1);
2083  lam2 = sqrt(lam2);
2084  double ellipt2 = fabs((lam1 - lam2)/(lam1 + lam2));
2085 
2086 
2087  /*/ bootstrapping section
2088 
2089  if(np<=0)return 0;
2090  //printf("MCHIRP5ERR_NPZERO\n");
2091 
2092  wavearray<int> used(np);
2093 
2094  int np2 = np*0.5, Trials=500;
2095  if(np2<3)np2 = np-1;
2096 
2097  if(np2<8)Trials = np2;
2098  else if(np2<15) Trials = np2*np2/2;
2099  else if(np2<20) Trials = np2*np2*np2/6;
2100  if(Trials>500) Trials = 500;
2101  if(Trials<0) Trials=0;
2102 
2103  this->cData[ID-1].mchpdf.resize(Trials);
2104  TRandom3 rnd(0);
2105  wavearray<float> slpv(Trials);
2106  wavearray<float> mchv(Trials);
2107  wavearray<float> bv(Trials);
2108 
2109  for(int ii=0; ii<Trials; ++ii){
2110  // generate random sequence
2111  used = 0;
2112  for(int k, i=0; i<np2; ++i){
2113  do k = rnd.Uniform(0. , np - 1e-10);
2114  while(used[k]);
2115  used[k]=1;
2116  }
2117 
2118  // linear fit, no weights for now
2119  double sx=0, sy=0, sx2=0, sxy=0;
2120  for(int i=0; i<np; ++i)if(used[i]){
2121  //x[i] -= tmin;
2122  sx += x[i];
2123  sy += y[i];
2124  sx2 += x[i]*x[i];
2125  sxy += x[i]*y[i];
2126  }
2127  double slp = (sy/np2 - sxy/sx)/(sx2/sx - sx/np2);
2128  double b = (sy + slp*sx)/np2;
2129 
2130  slpv.data[ii] = slp;
2131  mchv.data[ii] = slp>0 ? pow(slp/kk,0.6) : -pow(-slp/kk, 0.6);
2132  bv.data[ii] = b/slp;
2133  this->cData[ID-1].mchpdf.data[ii] = mchv.data[ii];
2134  }
2135 
2136 
2137  size_t nn = mchv.size()-1;
2138  size_t ns = size_t(mchv.size()*0.16);
2139  cData[ID-1].mchirperr = Trials>8 ? ( mchv.waveSplit(0,nn,nn-ns)-mchv.waveSplit(0,nn,ns) ) / 2 : 2*mchv.rms();
2140 
2141  // end bootstrapping section
2142 
2143 
2144  char name[100];
2145  sprintf(name, "netcluster::mchirp5:func_%d", ID);
2146  TF1* f = &(this->cData[ID-1].fit);
2147  TGraphErrors* gr = &(this->cData[ID-1].chirp);
2148 
2149  *gr = TGraphErrors(np, x, y, xerr, yerr);
2150  *f = TF1(name, "[0]*x + [1]", xmin, xmax);
2151  f->SetParameter(0, sl);
2152  f->SetParameter(1, b0);
2153  gr->Fit(f,"Q");
2154 
2155 
2156 
2157  int ndf = f->GetNDF();
2158  double mch = -f->GetParameter(0)/kk;
2159  double relerr = fabs(f->GetParError(0)/f->GetParameter(0));
2160  if(ndf==0) return -1;
2161  */
2162  this->cData[ID-1].chi2chirp = Efrac; //f->GetChisquare()/ndf;
2163  this->cData[ID-1].mchirp = m0; // mch>0 ? pow(mch, 0.6) : 0.0001;
2164  //this->cData[ID-1].mchirperr = 0.6*this->cData[ID-1].mchirp*relerr; // determined by bootstrapping!
2165  this->cData[ID-1].tmrgr = ellipt2; //-f->GetParameter(1)/f->GetParameter(0);
2166  this->cData[ID-1].tmrgrerr = frac; //ellipt;
2167 
2168  delete [] x;
2169  delete [] y;
2170  delete [] sel;
2171  delete [] wgt;
2172 
2173  return 0;
2174 
2175 }
2176 // draw chirp cluster
2178 {
2179 // Draw chirp object for cluster id
2180  TCanvas* c = new TCanvas("chirp", ""); c->cd();
2181  this->cData[id-1].chirp.Draw("AP");
2182  this->cData[id-1].fit.Draw("same");
2183  return;
2184 }
2185 
2187 { TCanvas* c = new TCanvas("cpc", "", 1200, 800);
2188  TH2F* h2 = new TH2F("h2h", "", 600, 0, 600, 2048, 0, 2048);
2189  int cntr = 0;
2190  std::vector<vector_int>::iterator it;
2191  for(it=cList.begin(); it != cList.end(); it++){
2192  size_t ID = pList[((*it)[0])].clusterID;
2193  if(sCuts[ID-1]==0){
2194  h2->Fill(cTime[ID-1], cFreq[ID-1], cRate[ID-1][2]);
2195  //printf("\nID = %lu time = %lf\t freq = %lf ", ID, cTime[ID-1], cFreq[ID-1]);
2196  ++cntr;
2197  }
2198  else if(sCuts[ID-1]==1)printf("*");
2199  }
2200  printf("\n# of zero sCuts lusters:%d\n", cntr);
2201  c->cd();
2202  h2->Draw("colz");
2203 }
2204 
2205 //**************************************************************************
2206 //**************************************************************************
2207 wavearray<double> netcluster::get(char* name, size_t index, char atype, int type, bool core)
2208 {
2209 // return cluster parameters defined by name
2210 // name="ID" clusterID
2211 // name="size" core size
2212 // name="SIZE" core+halo size
2213 // name="volume" volume
2214 // name="start" actual start time relative to segment start
2215 // name="stop" actual stop time relative to segment stop
2216 // name="duration" energy-weighted duration
2217 // name="low" low frequency
2218 // name="high" high frequency
2219 // name="energy" energy; 'R' - rank, 'S' - Gauss
2220 // name="subrho" subnetwork limit on coherent energy;
2221 // name="subnet" subnetwork energy fraction;
2222 // name="subnrg" subnetwork energy;
2223 // name="maxnrg" maximum detector energy;
2224 // name="power" energy/size
2225 // name="conf" cluster confidence; 'R' - rank, 'S' - Gauss
2226 // name="like" network likelihood
2227 // name="null" network null statistic
2228 // name="sign" significance; index<0 - rank, index>0 - Gauss
2229 // name="corr" xcorrelation
2230 // name="asym" asymmetry
2231 // name="grand" grandAmplitude
2232 // name="rate" cluster rate
2233 // name="SNR" cluster SNR: 'R' - rank, 'S' - Gaussian
2234 // name="hrss" log10(calibrated cluster hrss)
2235 // name="noise" log10(average calibrated noise): average of sigma^2
2236 // name="NOISE" log10(average calibrated noise): average of 1/sigma^2
2237 // name="elli" ellipticity
2238 // name="psi" source polarisation angle
2239 // name="phi" source coordinate phi
2240 // name="theta" source coordinate theta
2241 // name="time" zero lag time averaged over: 'S'-gSNR, 'R'-rSNR, 'L'-likelihood
2242 // name="TIME" zero lag time averaged over energy and all resolutions
2243 // name="freq" frequency averaged over: 'S'-gSNR, 'R'-rSNR, 'L'-likelihood
2244 // name="FREQ" frequency averaged over energy and all resolutions
2245 // name="bandwidth"energy-weighted bandwidth
2246 // name="chi2" chi2 significance: 1 - cumulative probability
2247 
2249  if(!cList.size() || !pList.size()) return out;
2250 
2251  size_t i,j,k,K,n,nifo;
2252  size_t mp,mm;
2253  size_t it_size;
2254  size_t it_core;
2255  size_t it_halo;
2256  size_t it_like;
2257  size_t out_size = 0;
2258  double x,y;
2259  double a,b,d,e;
2260  double t,r;
2261  double sum = 0.;
2262  double logbpp = -log(bpp);
2263  double nsd,msd,esub,emax,rho,subnet;
2264 
2265  // before Feb, 2007: ampbpp = sqrt(2*1.07*logbpp)-1.11/2.;
2266  // after Feb, 2007: more accurate approximation
2267  double ampbpp = sqrt(2*logbpp-2*log(1+pow(log(1+logbpp*(1+1.5*exp(-logbpp))),2)));
2268 
2269  int ID, rate, min_rate, max_rate;
2270  int RATE = abs(type)>2 ? abs(type) : 0;
2271 
2272  wavearray<int> skip;
2273  vector<vector_int>::iterator it;
2274  vector_int* pv = NULL;
2275  size_t M = pList.size();
2276  size_t m = index ? index : index+1;
2277 
2278  out.resize(cList.size());
2279  out.start(start);
2280  out.rate(1.);
2281  out = 0.;
2282 
2283  char c = '0';
2284 
2285  if(strstr(name,"ID")) c = 'i'; // clusterID
2286  if(strstr(name,"size")) c = 'k'; // core size
2287  if(strstr(name,"SIZE")) c = 'K'; // core+halo size
2288  if(strstr(name,"volume")) c = 'v'; // volume
2289  if(strstr(name,"VOLUME")) c = 'V'; // volume with likelihood>0
2290  if(strstr(name,"start")) c = 's'; // actual start time relative to segment start
2291  if(strstr(name,"stop")) c = 'd'; // actual stop time relative to segment stop
2292  if(strstr(name,"dura")) c = 'D'; // energy weghted duration for all resolutions
2293  if(strstr(name,"low")) c = 'l'; // low frequency
2294  if(strstr(name,"high")) c = 'h'; // high frequency
2295  if(strstr(name,"energy")) c = 'e'; // energy; 'R' - rank, 'S' - Gauss
2296  if(strstr(name,"subrho")) c = 'R'; // subnetwork limit on coherent energy;
2297  if(strstr(name,"subnet")) c = 'U'; // subnetwork energy fraction;
2298  if(strstr(name,"subnrg")) c = 'u'; // subnetwork energy;
2299  if(strstr(name,"maxnrg")) c = 'm'; // maximum detector energy;
2300  if(strstr(name,"power")) c = 'w'; // energy/size
2301  if(strstr(name,"conf")) c = 'Y'; // cluster confidence; 'R' - rank, 'S' - Gauss
2302  if(strstr(name,"like")) c = 'L'; // network likelihood
2303  if(strstr(name,"null")) c = 'N'; // network null statistic
2304  if(strstr(name,"sign")) c = 'z'; // significance; index<0 - rank, index>0 - Gauss
2305  if(strstr(name,"corr")) c = 'x'; // xcorrelation
2306  if(strstr(name,"asym")) c = 'a'; // asymmetry
2307  if(strstr(name,"grand")) c = 'g'; // grandAmplitude
2308  if(strstr(name,"rate")) c = 'r'; // cluster rate
2309  if(strstr(name,"SNR")) c = 'S'; // cluster SNR: 'R' - rank, 'S' - Gaussian
2310  if(strstr(name,"hrss")) c = 'H'; // log10(calibrated cluster hrss)
2311  if(strstr(name,"noise")) c = 'n'; // log10(average calibrated noise): average of sigma^2
2312  if(strstr(name,"NOISE")) c = 'I'; // log10(average calibrated noise): average of 1/sigma^2
2313  if(strstr(name,"elli")) c = 'o'; // ellipticity
2314  if(strstr(name,"psi")) c = 'O'; // source polarisation angle
2315  if(strstr(name,"phi")) c = 'P'; // source coordinate phi
2316  if(strstr(name,"theta")) c = 'p'; // source coordinate theta
2317  if(strstr(name,"time")) c = 't'; // zero lag time averaged over: 'S'-gSNR, 'R'-rSNR, 'L'-likelihood
2318  if(strstr(name,"TIME")) c = 'T'; // zero lag time averaged over energy and all resolutions
2319  if(strstr(name,"freq")) c = 'f'; // frequency averaged over: 'S'-gSNR, 'R'-rSNR, 'L'-likelihood
2320  if(strstr(name,"FREQ")) c = 'F'; // frequency averaged over energy and all resolutions
2321  if(strstr(name,"band")) c = 'B'; // energy weghted bandwidth for all resolutions
2322  if(strstr(name,"chi2")) c = 'C'; // chi2 significance: 1 - cumulative probability
2323 
2324  if(c=='0') return out;
2325 
2326  k = K = 0;
2327 
2328  for(it=cList.begin(); it!=cList.end(); it++){
2329 
2330  ID = pList[((*it)[0])].clusterID;
2331  if(sCuts[ID-1]>0) continue; // apply selection cuts
2332  it_size = it->size();
2333  if(!it_size) continue;
2334 
2335  it_core = 0;
2336  it_halo = 0;
2337  it_like = 0;
2338  skip.resize(it_size);
2339  pv = cRate.size() ? &(cRate[ID-1]) : NULL;
2340  rate = 0;
2341 
2342  if(type<0) rate = -type;
2343  else if(!pv) rate = 0;
2344  else if(type==1 && pv->size()) rate = (*pv)[0];
2345  else if(pv->size() && RATE) rate = ((*pv)[0]==RATE) ? RATE : -1;
2346 
2347  min_rate=std::numeric_limits<int>::max();
2348  max_rate=0;
2349  for(k=0; k<it_size; k++) { // fill skip array
2350  M = (*it)[k];
2351  skip.data[k] = 1;
2352  int prate = int(pList[M].rate+0.1);
2353  if(rate && prate!=rate) continue;
2354  if(prate>max_rate) max_rate = prate;
2355  if(prate<min_rate) min_rate = prate;
2356  it_halo++;
2357  if(pList[M].core && pList[M].likelihood>0) it_like++;
2358  if(!pList[M].core && core) continue;
2359  skip.data[k] = 0;
2360  it_core++;
2361  }
2362 
2363  if(!it_core) continue; // skip cluster
2364 
2365  switch (c) {
2366 
2367  case 'i': // get cluster ID
2368  for(k=0; k<it_size; k++){
2369  M = (*it)[k];
2370  if(!skip.data[k]) {
2371  out.data[out_size++] = pList[M].clusterID;
2372  break;
2373  }
2374  }
2375  break;
2376 
2377  case 'k': // get cluster core size
2378  case 'K': // get cluster core+halo size
2379  out.data[out_size++] = c=='k' ? float(it_core) : float(it_halo);
2380  break;
2381 
2382  case 'P': // get source coordinate phi
2383  case 'p': // get source coordinate theta
2384  for(k=0; k<it_size; k++){
2385  M = (*it)[k];
2386  if(!skip.data[k]) {
2387  out.data[out_size++] = (c=='p') ? pList[M].theta : pList[M].phi;
2388  break;
2389  }
2390  }
2391  break;
2392 
2393  case 'O': // get source polarisation angle
2394  case 'o': // get source ellipticity
2395  for(k=0; k<it_size; k++){
2396  M = (*it)[k];
2397  if(!skip.data[k]) {
2398  out.data[out_size++] = (c=='o') ? pList[M].ellipticity : pList[M].polarisation;
2399  break;
2400  }
2401  }
2402  break;
2403 
2404  case 'r': // get cluster rate
2405  for(k=0; k<it_size; k++){
2406  M = (*it)[k];
2407  if(!skip.data[k]) {
2408  out.data[out_size++] = pList[M].rate;
2409  break;
2410  }
2411  }
2412  break;
2413 
2414  case 'a': // get cluster asymmetry
2415  case 'x': // get cluster x-correlation parameter
2416  mp = 0; mm = 0;
2417  for(k=0; k<it_size; k++){
2418  M = (*it)[k];
2419 
2420  if(!index) continue;
2421  if(skip.data[k]) continue;
2422  if(pList[M].size()<m) continue;
2423  x = pList[M].getdata(atype,m-1);
2424  if(x>0.) mp++;
2425  else mm++;
2426  }
2427  if(c == 'a') out.data[out_size++] = mp+mm>0 ? (float(mp)-float(mm))/(mp+mm) : 0;
2428  else out.data[out_size++] = mp+mm>0 ? signPDF(mp,mm) : 0;
2429  break;
2430 
2431  case 'u': // get subnetwork energy
2432  case 'm': // get maximum detector energy
2433  case 'U': // get subnetwork statistic (subnet energy fraction)
2434  case 'R': // subnetwork limit on coherent energy
2435  double v,E;
2436  mm = it_core;
2437  esub = emax = sum = rho = 0;
2438  for(k=0; k<it_size; k++){
2439  M = (*it)[k];
2440  nifo = pList[M].size();
2441  if(skip.data[k]) continue;
2442  a = E = e = nsd = 0;
2443  for(n=0; n<nifo; n++) {
2444  a+= fabs(pList[M].getdata(atype,n)); // pixel amplitude
2445  x = pList[M].getdata(atype,n); x*=x; // pixel energy
2446  v = pList[M].data[n].noiserms; v*=v; // noise variance
2447  if(x>E) {E=x; msd=v;}
2448  e += x;
2449  nsd += v>0 ? 1/v : 0.;
2450  }
2451 
2452  if(nsd==0. && c=='U') {
2453  cout<<"netcluster::get():empty noiserms array"<<endl; exit(0);
2454  }
2455 
2456  a = a>0 ? e/(a*a) : 1;
2457  rho += (1-a)*(e-nSUB*2); // estimator of coherent energy
2458  y = e-E;
2459  x = y*(1+y/(E+1.e-5)); // corrected subnetwork energy
2460  nsd -= msd>0 ? 1./msd : 0; // subnetwork inverse PSD
2461  v = (2*E-e)*msd*nsd/10.;
2462  esub+= e-E;
2463  emax+= E;
2464  a = x/(x+nSUB);
2465  sum += (e*x/(x+(v>0?v:1.e-5)))*(a>0.5?a:0);
2466  }
2467  sum = sum/(emax+esub+0.01);
2468  if(c=='u') out.data[out_size++] = esub;
2469  if(c=='m') out.data[out_size++] = emax;
2470  if(c=='U') out.data[out_size++] = sum;
2471  if(c=='R') out.data[out_size++] = sqrt(rho); // coherent amplitude
2472  //if(rho<0.01) cout<<"debugx: "<<mm<<" "<<a<<" "<<esub<<" "<<emax<<" "<<rho<<" "<<sum<<endl;
2473  break;
2474 
2475  case 'e': // get cluster energy
2476  case 'S': // get cluster SNR
2477  case 'Y': // get cluster confidence
2478  case 'z': // get cluster significance
2479  case 'w': // get cluster power
2480  case 'C': // get cluster chi2 probability
2481  y = 0.;
2482  mm = 0;
2483  for(k=0; k<it_size; k++){
2484  M = (*it)[k];
2485 
2486  if(!index) continue;
2487  if(skip.data[k]) continue;
2488  if(pList[M].size()<m) continue;
2489 
2490  x = pList[M].getdata(atype,m-1);
2491  x/= (atype=='W' || atype=='w') ? pList[M].data[m-1].noiserms : 1.;
2492  x/= (atype=='U' || atype=='u') ? pList[M].data[m-1].noiserms : 1.;
2493  x = fabs(x);
2494 
2495  if(atype=='R' || atype=='r'){ // get rank statistics
2496  a = x+logbpp;
2497  a-= log(1+pow(log(1+a*(1+1.5*exp(-a))),2)); // new approximation for rank SNR
2498  a = sqrt(2*a); // was a = sqrt(2*1.07*(x+logbpp))-1.11/2.;
2499 
2500  if(x==0.) a = 0.;
2501 
2502  if(c=='Y' || c=='z') {
2503  if(atype=='R') { y += x; mm++; }
2504  if(atype=='r' && x>0) { y += x; mm++; }
2505  }
2506  else if(c=='e' || c=='C') { y += a*a; mm++; }
2507  else if(a*a>1.) { y += a*a; mm++; }
2508  }
2509 
2510  else { // get Gaussian statistics
2511  if(c=='Y' || c=='z') {
2512  a = pow(x+1.11/2,2)/2./1.07;
2513  y+= (a>logbpp) ? a-logbpp : 0.;
2514  if(atype=='S' || atype=='W' || atype=='P' || atype=='U') mm++; // total size
2515  else if(a>logbpp) mm++; // reduced size
2516  }
2517  else if(c=='e' || c=='C' || c=='w') {
2518  if(atype=='S' || atype=='W' || atype=='P'|| atype=='U') {
2519  y += x*x; mm++; // total energy
2520  }
2521  else if(x>ampbpp) { y += x*x; mm++; } // reduced energy
2522  }
2523  else if(x*x>1.) { y += x*x; mm++; }
2524  }
2525 
2526  }
2527 
2528  if(c=='S' && mm) y -= double(mm);
2529  if(c=='w' && mm) y /= double(mm);
2530  if(c=='z' && mm) y = gammaCL(y,mm);
2531 
2532  out.data[out_size++] = y;
2533  break;
2534 
2535  case 'g': // get cluster grand amplitude
2536  y = 0.;
2537  for(k=0; k<it_size; k++){
2538  M = (*it)[k];
2539 
2540  if(!index) continue;
2541  if(skip.data[k]) continue;
2542  if(pList[M].size()<m) continue;
2543 
2544  x = fabs(pList[M].getdata(atype,m-1));
2545  if(x>y) y = x;
2546  }
2547  out.data[out_size++] = y;
2548  break;
2549 
2550  case 's': // get cluster start time
2551  case 'd': // get cluster stop time
2552  a = 1.e99;
2553  b = 0.;
2554  for(k=0; k<it_size; k++){
2555  M = (*it)[k];
2556  if(skip.data[k]) continue;
2557  y = 1./pList[M].rate; // time resolution
2558  mm= pList[M].layers;
2559  x = index ? y*int(pList[M].data[m-1].index/mm) :
2560  y*int(pList[M].time/mm);
2561  if(x <a) a = x; // first channel may be shifted
2562  if(x+y>b) b = x+y;
2563  }
2564  out.data[out_size++] = (c=='s') ? a : b;
2565  break;
2566 
2567  case 'l': // get low frequency
2568  case 'h': // get high frequency
2569  a = 1.e99;
2570  b = 0.;
2571  for(k=0; k<it_size; k++){
2572  M = (*it)[k];
2573  if(skip.data[k]) continue;
2574  mp= size_t(this->rate/pList[M].rate+0.1);
2575  mm= pList[M].layers; // number of wavelet layers
2576  double dF = mm==mp ? 0. : -0.5; // wavelet : WDM
2577  y = pList[M].rate/2.; // frequency resolution
2578  x = y * (pList[M].frequency+dF); // pixel frequency
2579  if(x <a) a = x;
2580  if(x+y>b) b = x+y;
2581  }
2582  out.data[out_size++] = (c=='l') ? a : b;
2583  break;
2584 
2585  case 'L': // get network likelihood
2586  case 'N': // get network null stream
2587  a = 0.;
2588  x = 0.;
2589  for(k=0; k<it_size; k++){
2590  M = (*it)[k];
2591  if(skip.data[k]) continue;
2592 
2593  if(atype=='S' || atype=='s' || atype=='P' || atype=='p' || !index) {
2594  for(i=0; i<pList[M].size(); i++) {
2595  x += pow(pList[M].data[i].asnr,2);
2596  }
2597  x -= 2*pList[M].likelihood;
2598  }
2599  else if(c=='N'){
2600  b = pList[M].data[m-1].asnr;
2601  b -= pList[M].data[m-1].wave/pList[M].data[m-1].noiserms;
2602  x += b*b;
2603  }
2604 
2605  a += pList[M].likelihood; // pixel network likelihood
2606  }
2607  if(c=='N') a=x;
2608  out.data[out_size++] = a;
2609  break;
2610 
2611  case 't': // get central time optimal resolution
2612  case 'T': // get central time for all resolutions
2613  case 'f': // get central frequency for optimal resolution
2614  case 'F': // get central frequency for all resolutions
2615  case 'D': // get energy-weighted duration for all resolutions
2616  case 'B': // get energy-weighted bandwidth for all resolutions
2617  a = 0.;
2618  b = 0.;
2619  d = 0.;
2620 
2621  if(c=='F' && (int)cFreq.size()>ID-1) { // get supercluster frequency
2622  out.data[out_size++] = cFreq[ID-1];
2623  break;
2624  }
2625  if(c=='T' && (int)cTime.size()>ID-1) { // get supercluster time
2626  out.data[out_size++] = cTime[ID-1];
2627  break;
2628  }
2629 
2630  for(k=0; k<it_size; k++) {
2631  M = (*it)[k];
2632 
2633  if(!index && atype!='L') continue;
2634  if(skip.data[k]) continue;
2635  if(pList[M].size()<m && atype!='L') continue;
2636 
2637  mp= size_t(this->rate/pList[M].rate+0.1);
2638  t = 1./pList[M].rate; // wavelet time resolution
2639  mm= pList[M].layers; // number of wavelet layers
2640  if(atype=='S' || atype=='s' || atype=='P' || atype=='p') { // get Gaussian statistics
2641  x = pList[M].getdata(atype,m-1);
2642  x = x*x;
2643  }
2644  else if (atype=='R' || atype=='r'){ // get rank statistics
2645  x = pList[M].getdata(atype,m-1);
2646  x = pow(sqrt(2*1.07*(fabs(x)-log(bpp)))-1.11/2.,2);
2647  }
2648  else {
2649  x = pList[M].likelihood;
2650  }
2651  if(x<0.) x = 0.;
2652 
2653  if(c=='t' || c=='T' || c=='D') {
2654  double dT = mm==mp ? 0. : 0.5; // wavelet : WDM
2655  double iT = (pList[M].time/mm - dT)*t; // left bin time (all detectors)
2656 
2657  if(index)
2658  iT = (pList[M].data[m-1].index/mm - dT)*t; // left bin time (individual detectors)
2659 
2660  int n = max_rate*t; // number of sub time bins
2661  double dt = 1./max_rate; // max time resolution
2662  iT+=dt/2.; // central bin time
2663  x/=n*n; // rescale weight
2664  for(j=0;j<n;j++) {
2665  a += iT*x; // pixel time sum
2666  b += x; // use weight x
2667  d += iT*iT*x; // duration
2668  iT += dt; // increment time
2669  }
2670  }
2671  else {
2672  double dF = mm==mp ? 0. : 0.5; // wavelet : WDM
2673  double iF = (pList[M].frequency - dF)/t/2.; // left bin frequency (all detectors)
2674 
2675  int n = 1./(min_rate*t); // number of sub freq bins
2676  double df = min_rate/2.; // max frequency resolution
2677  iF+=df/2.; // central bin frequency
2678  x/=n*n; // rescale weight
2679  for(j=0;j<n;j++) {
2680  a += iF*x; // pixel frequency sum
2681  b += x; // use weight x
2682  d += iF*iF*x; // bandwidth
2683  iF += df; // increment freq
2684  }
2685  }
2686  }
2687 
2688  if(c=='B' && b>0) {
2689  a = (d-a*a/b)/b; // bandwidth^2
2690  a = a>0 ? sqrt(a)*b : min_rate/2.; // bandwidth * b
2691  }
2692 
2693  if(c=='D' && b>0) {
2694  a = (d-a*a/b)/b; // duration^2
2695  a = a>0 ? sqrt(a)*b : 1./max_rate; // duration * b
2696  }
2697 
2698  out.data[out_size++] = b>0. ? a/b : -1.;
2699  break;
2700 
2701  case 'H': // get calibrated hrss
2702  case 'n': // get calibrated noise sigma^2
2703  case 'I': // get calibrated noise 1/sigma^2
2704 
2705  mp = 0;
2706  sum = 0.;
2707  out.data[out_size] = 0.;
2708 
2709  for(k=0; k<it_size; k++) {
2710  M = (*it)[k];
2711 
2712  if(!index) continue;
2713  if(skip.data[k]) continue;
2714  if(pList[M].size()<m) continue;
2715 
2716  r = pList[M].getdata('N',m-1);
2717 
2718  mp++;
2719 
2720  if(c == 'H'){
2721  a = pow(pList[M].getdata(atype,m-1),2);
2722  if(atype=='S' || atype=='s' || atype=='P' || atype=='p') { a -= 1.; a *= r*r; }
2723  sum += a<0. ? 0. : a;
2724  }
2725  else if(r>0){
2726  sum += c=='n' ? r*r : 1./r/r;
2727  }
2728 
2729  }
2730 
2731  if(c != 'H' && mp) { sum = sum/double(mp); } // noise hrss
2732  if(c == 'I' && mp) { sum = 1./sum; }
2733  out.data[out_size++] = sum>0. ? float(log(sum)/2./log(10.)) : 0.;
2734  break;
2735 
2736  case 'V': // get cluster core size with likelihood>0
2737  out.data[out_size++] = float(it_like);
2738  break;
2739 
2740  case 'v':
2741  default:
2742  for(k=0; k<it_size; k++){
2743  M = (*it)[k];
2744  if(!skip.data[k]) {
2745  out.data[out_size++] = it_size;
2746  break;
2747  }
2748  }
2749  break;
2750  }
2751  }
2752 
2753  out.resize(out_size);
2754  return out;
2755 }
2756 
2757 
2758 //**************************************************************************
2759 // extract WSeries for specified cluster ID and detector index
2760 // does not work with WDM
2761 //**************************************************************************
2762 double netcluster::getwave(int cid, WSeries<double>& W, char atype, size_t n)
2763 {
2764  if(!cList.size()) return 0.;
2765 // if(atype != 'W' && atype != 'S') return 0.;
2766 
2767  int t,offset;
2768  int ID, R;
2769  int level,mm;
2770 
2771  size_t k,f;
2772  size_t mp = 0;
2773  size_t max_layer;
2774  size_t max,min;
2775  size_t it_size;
2776  size_t it_core;
2777  size_t pixtime;
2778 
2779  double a;
2780  double tsRate = W.rate();
2781  double fl = tsRate/2.;
2782  double fh = 0.;
2783  double sum = 0.;
2784  double temp=0.;
2785 
2786  slice S;
2787 
2788  wavearray<int> skip;
2789  vector<vector_int>::iterator it;
2790  vector_int* pv = NULL;
2791  netpixel* pix;
2792  size_t M = pList.size();
2793 
2794 // extract cluster
2795 
2796  for(it=cList.begin(); it!=cList.end(); it++){
2797 
2798  ID = pList[((*it)[0])].clusterID;
2799  it_size = it->size();
2800 
2801  if(ID != cid) continue; // find the cluster
2802  if(!it_size) continue; // skip empty cluster
2803 
2804  it_core = 0;
2805  skip.resize(it_size);
2806 
2807  pv =&(cRate[ID-1]);
2808  R = pv->size() ? (*pv)[0] : 0;
2809 
2810  max = 0; // max time index
2811  min = 1234567890; // min time index
2812 
2813  for(k=0; k<it_size; k++) { // fill skip array
2814  M = (*it)[k];
2815  pix = &pList[M];
2816 
2817  skip.data[k] = 1;
2818  if(!pList[M].core) continue;
2819  if(R && int(pix->rate+0.1)!=R) continue;
2820  if(!R) R = int(pix->rate+0.1); // case of elementary clusters
2821  mm = pix->layers; // number of wavelet layers
2822  pixtime = pix->getdata('I',n)/mm;
2823  if(pixtime > max) max = pixtime; // max pixel time index
2824  if(pixtime < min) min = pixtime; // min pixel time index
2825  skip.data[k] = 0;
2826  it_core++;
2827  }
2828 
2829  k = size_t((max-min+2*W.pWavelet->m_H)/R)+1; // W duration in seconds
2830 
2831 // cout<<"duration="<<k<<" filter="<<W.pWavelet->m_L<<endl;
2832 
2833 // setup WSeries metadata
2834 
2835 // cout<<"wrate="<<tsRate<<" rate="<<R<<endl;
2836 
2837  W.resize(size_t(k*this->rate+0.1));
2838  W.setLevel(0);
2839  level = int(log(tsRate/R)/log(2.)+0.1);
2840  while(W.getMaxLevel()<level) W.resize(W.size()*2);
2841  W.Forward(level);
2842  W = 0.;
2843 
2844  max_layer = W.maxLayer();
2845 
2846 // cout<<"maxlayer="<<max_layer<<" wsize="<<W.size()<<endl;
2847 
2848  S = W.getSlice(0);
2849  offset = (int(max+min) - int(S.size()))/2;
2850  W.start(double(offset)/R);
2851 
2852 // cout<<"min="<<min<<" max="<<max<<" Ssize="<<S.size()<<endl;
2853 // cout<<"offset="<<offset<<" wsize="<<W.size()<<endl;
2854 
2855  if(!it_core) continue; // skip cluster
2856 
2857  for(k=0; k<it_size; k++){
2858  M = (*it)[k];
2859  pix = &pList[M];
2860 
2861  if(skip.data[k]) continue;
2862  if(!(pix->size())) continue;
2863  mm = pix->layers; // number of wavelet layers
2864  pixtime = size_t(pix->getdata('I',n)/mm);
2865 
2866  f = pix->frequency; // pixel frequency
2867  t = int(pixtime)-offset; // pixel time index
2868 
2869  if(f > max_layer) continue;
2870  if(f*R/2. <= fl) { fl = f*R/2.; W.setlow(fl); }
2871  if((f+1)*R/2. >= fh) { fh = (f+1)*R/2.; W.sethigh(fh); }
2872 
2873  S = W.getSlice(f);
2874 
2875  if(t < 0 || size_t(t) >= S.size()) continue;
2876  if(pix->size() <= n) continue;
2877 
2878  a = pix->getdata(atype,n);
2879  if(atype=='W') a /= pix->getdata('N',n);
2880  W.data[S.start()+t*S.stride()] = a;
2881 
2882  a = pix->getdata('N',n);
2883  mp++; sum += 1./a/a;
2884  temp += pList[M].time/double(R);
2885 
2886  }
2887 
2888 // cout<<"cid="<<cid<<" size="<<mp<<" "<<pow(W.rms(),2.)*W.size()/tsRate;
2889 // cout<<" time="<<temp/mp<<" rate="<<R<<" duration="<<W.size()/tsRate<<endl;
2890 
2891  sum = sqrt(double(mp)/sum); // noise hrss
2892 
2893  return sum;
2894  }
2895  return 0.;
2896 }
2897 
2898 
2900 {
2901 //**************************************************************************
2902 // !!! may violate WDM parity for non-integer seconds lags !!!!
2903 // construct waveform from MRA pixels at different resolutions
2904 // extract MRA waveforms for specified cluster ID and detector index n
2905 // works only with WDM. Create WSeries<> objects for each resolution,
2906 // find principle components, fill in waveForm and waveBand arrays
2907 // atype = 'W' - get whitened detector output (Wavelet data)
2908 // atype = 'w' - get detector output (Wavelet data)
2909 // atype = 'S' - get whitened reconstructed response (Signal)
2910 // atype = 's' - get reconstructed response (Signal)
2911 // mode: -1/0/1 - return 90/mra/0 phase
2912 //**************************************************************************
2914 
2915  if(!cList.size()) return z;
2916 
2917  bool signal = atype=='S' || atype=='s';
2918  bool strain = atype=='w' || atype=='s';
2919 
2920  int nRES = net->wdmList.size();
2921 
2922  double maxfLen = 0; // find max filter length
2923  for(int l=0;l<nRES;l++) {
2924  double fLen = net->wdmList[l]->m_H/this->rate;
2925  if(maxfLen<fLen) maxfLen=fLen;
2926  }
2927 
2928  WDM<double>* wdm;
2929  wavearray<double> x00;
2930  wavearray<double> x90;
2931  std::vector<int>* vint;
2932  wavearray<double> cid;
2933  netpixel* pix;
2934 
2935  cid = this->get((char*)"ID",0,'S',0); // get cluster ID
2936 
2937  int K = cid.size();
2938 
2939  for(int k=0; k<K; k++) { // loop over clusters
2940 
2941  int id = size_t(cid.data[k]+0.1);
2942  if(id!=ID) continue;
2943 
2944  vint = &(this->cList[id-1]); // pixel list
2945 
2946  int V = vint->size();
2947  if(!V) continue;
2948 
2949 // find event time interval, fill in amplitudes
2950 
2951  double tmin=1e20;
2952  double tmax=0.;
2953  double T, a00, a90, rms;
2954  for(int j=0; j<V; j++) {
2955  pix = this->getPixel(id,j);
2956  T = int(pix->time/pix->layers); // get time index
2957  T = T/pix->rate; // time in seconds from the start
2958  if(T<tmin) tmin=T;
2959  if(T>tmax) tmax=T;
2960  }
2961 
2962  tmin = int(tmin-maxfLen)-1; // start event time in sec
2963  tmax = int(tmax+maxfLen)+1; // end event time in sec
2964  z.resize(size_t(this->rate*(tmax-tmin)+0.1));
2965  z.rate(this->rate); z.start(tmin); z.stop(tmax), z=0;
2966 
2967  int io = int(tmin*z.rate()+0.01); // index offset of z-array
2968  int M, j00, j90;
2969 
2970  //cout<<"+++ "<<tmin<<" "<<tmax<<" "<<io<<" "<<z.rate()<<" "<<z.size()<<" "<<maxfLen<<endl;
2971 
2972  float s00=0.;
2973  float s90=0.;
2974 
2975  for(int j=0; j<V; j++) {
2976  pix = this->getPixel(id,j);
2977  if(!pix->core) continue;
2978 
2979  rms = pix->getdata('N',ifo);
2980  a00 = signal ? pix->getdata('s',ifo) : pix->getdata('w',ifo);
2981  a90 = signal ? pix->getdata('p',ifo) : pix->getdata('u',ifo);
2982  a00*= strain ? rms : 1.;
2983  a90*= strain ? rms : 1.;
2984  wdm = net->getwdm(pix->layers); // pointer to WDM transform stored in network
2985  j00 = wdm->getBaseWave(pix->time,x00,false)-io;
2986  j90 = wdm->getBaseWave(pix->time,x90,true)-io;
2987  if(mode < 0) a00=0.; // select phase 90
2988  if(mode > 0) a90=0.; // select phase 00
2989 
2990  s00 += a00*a00;
2991  s90 += a90*a90;
2992 
2993  for(int i=0; i<x00.size(); i++){
2994  if(j00+i<0 || j00+i>=z.size()) continue;
2995  z.data[j00+i] += x00[i]*a00;
2996  z.data[j90+i] += x90[i]*a90;
2997  }
2998  //cout<<"*** "<<pix->layers<<" "<<pix->data[ifo].index<<" "<<j00<<" "<<j90<<" "
2999  // <<x00.size()<<" "<<x90.size()<<" "<<z.size()<<endl;
3000  }
3001  //cout<<mode<<" s00/s90: "<<s00<<" "<<s90<<" "<<z.rms()*z.rms()*z.size()<<endl;
3002 
3003  break;
3004  }
3005  return z;
3006 }
3007 
3008 size_t netcluster::write(const char *fname, int app)
3009 {
3010 // write the entire pixel structure into a file
3011 // only metadata and pixels are written, no cluster metadata is stored
3012 // app = 0 - open new file and dump metadata and pixel structure
3013 // app = 1 - append pixel structure to existing file
3014 
3015  size_t i;
3016  size_t I = this->pList.size(); // number of pixels;
3017  FILE *fp;
3018 
3019  if(app) fp=fopen(fname, "ab");
3020  else fp=fopen(fname, "wb");
3021 
3022  if(!fp) {
3023  cout<<"netcluster::write() error : cannot open file "<<fname<<"\n";
3024  fclose(fp); return 0;
3025  }
3026 
3027  if(!app) { // write metadata
3028  if(!write(fp,app)) { fclose(fp); return 0; };
3029  }
3030 
3031  for(i=0; i<I; i++) { // write pixels
3032  if(!pList[i].write(fp)) { fclose(fp); return 0; }
3033  }
3034  fclose(fp);
3035  return I;
3036 }
3037 
3038 size_t netcluster::write(FILE *fp, int app)
3039 {
3040 // write pixel structure with TD vectors attached into a file
3041 // only some metadata and pixels are written, no cluster metadata is stored
3042 // app = 0 - store metadata
3043 // app = 1 - store pixels with the TD vectors attached by setTDAmp()
3044 
3045  size_t i,k;
3046  size_t I = this->pList.size(); // number of pixels;
3047  size_t II= 0;
3048  netpixel pix;
3049 
3050  // write metadata
3051 
3052  if(!app) {
3053  double db[9];
3054  double rest = this->nPIX*10+2*this->pair;
3055  db[0] = this->rate; // original Time series rate
3056  db[1] = this->start; // interval start GPS time
3057  db[2] = this->stop; // interval stop GPS time
3058  db[3] = this->bpp; // black pixel probability
3059  db[4] = this->shift; // time shift
3060  db[5] = this->flow; // low frequency boundary
3061  db[6] = this->fhigh; // high frequency boundary
3062  db[7] = (double)this->run; // run ID
3063  db[8] = rest; // store the rest
3064  if(fwrite(db, 9*sizeof(double), 1, fp) !=1) {
3065  fclose(fp); return 0;
3066  }
3067  return 1;
3068  }
3069 
3070  if(!I) return 0;
3071 
3072  // write pixels
3073 
3074  for(i=0; i<this->cList.size(); ++i) {
3075  if(sCuts[i]==1) continue;
3076 
3077  const vector_int& v = cList[i];
3078  size_t K = v.size();
3079  bool skip = true;
3080  if(!K) continue;
3081 
3082  for(k=0; k<K; ++k) { // loop over pixels
3083  if(pList[v[k]].tdAmp.size()) skip=false;
3084  }
3085  if(skip) continue;
3086 
3087  netpixel** pp = (netpixel**)malloc(K*sizeof(netpixel*));
3088  for(k=0; k<K; k++) pp[k] = &pList[v[k]];
3089  qsort(pp, K, sizeof(netpixel*), &compareLIKE); // sort pixels
3090 
3091  for(k=0; k<K; k++) { // loop over pixels
3092  if(!pp[k]->tdAmp.size()) continue;
3093  pix = *pp[k];
3094  pp[k]->clean(); // clean TD amplitudes
3095  pix.neighbors.clear();
3096  if(k<K-1) pix.neighbors.push_back(1);
3097  if(k>0) pix.neighbors.push_back(-1);
3098  // set right index (set in subNetCuts) for netcc[3] after pixels sorting
3099  if(k==0) pix.ellipticity = pList[v[0]].ellipticity;
3100  if(k==1) pix.ellipticity = pList[v[1]].ellipticity;
3101  if(k==0) pix.polarisation = pList[v[0]].polarisation;
3102  if(k==1) pix.polarisation = pList[v[1]].polarisation;
3103  pix.write(fp);
3104  II++;
3105  //printf("k = %lu , clID = %lu\n", k, pix->clusterID);
3106  //printf("pixel %d from cluster %d written\n", k, i);
3107  }
3108 
3109  free(pp);
3110  }
3111  return II;
3112 }
3113 
3114 
3115 size_t netcluster::read(const char* fname)
3116 {
3117 // read pixel structure from file
3118 // the entire content is loaded into pList structure
3119  size_t i;
3120  netpixel pix;
3121 
3122  FILE *fp = fopen(fname,"rb");
3123 
3124  if (!fp) {
3125  cout << "netcluster::read() error : cannot open file " << fname <<". \n";
3126  fclose(fp); return 0;
3127  }
3128 
3129  if(!read(fp,0)) {fclose(fp); return 0;} // read metadata
3130 
3131  // read pixels
3132  bool end = false;
3133  do {
3134  pList.push_back(pix);
3135  i = pList.size()-1;
3136  end = pList[i].read(fp);
3137  } while(end);
3138  pList.pop_back();
3139 
3140  size_t I = pList.size();
3141  fclose(fp);
3142  if(I) this->cluster();
3143  return I;
3144 }
3145 
3146 
3147 // read clusters from file
3148 size_t netcluster::read(FILE* fp, int nmax)
3149 {
3150 // read metadata and pixels stored in a file on cluster by cluster basis
3151 // clusters should be contiguous in the file (written by write(FILE*))
3152 // nmax = 0 - read metadata
3153 // nmax > 0 - read no more than maxPix pixels from a cluster
3154 
3155  size_t i;
3156 
3157  if(nmax==0){ // read nextcluster metadata from file
3158  this->clear();
3159  double db[9];
3160  if(fread(db, 9*sizeof(double), 1, fp) !=1) return 0;
3161  int kk = int(db[8]+0.1); // rest
3162  db[8] += db[8]>0. ? 0.1 : -0.1; // prepare for conversion to int
3163  this->rate = db[0]; // original Time series rate
3164  this->start = db[1]; // interval start GPS time
3165  this->stop = db[2]; // interval stop GPS time
3166  this->bpp = db[3]; // black pixel probability
3167  this->shift = db[4]; // time shift
3168  this->flow = db[5]; // low frequency boundary
3169  this->fhigh = db[6]; // high frequency boundary
3170  this->run = int(db[7]+0.1); // run ID
3171  this->nPIX = kk/10; // recover nPIX
3172  this->pair = (kk%10)/2; // recover pair
3173  return 1;
3174  }
3175 
3176  // clean TD amplitudes in pList structure
3177  size_t I = pList.size();
3178  for(i=0; i<I; ++i) pList[i].clean(); // clean TD amplitudes
3179 
3180  // reads first pixel
3181  netpixel pix;
3182  bool stop = false;
3183  size_t II = 0;
3184  int ID = cList.size()+1;
3185 
3186  while(pix.read(fp)){
3187  II++; // update counter
3188  if(II<2 && pix.neighbors.size()<1) stop=true; // just one pixel
3189  if(II>1 && pix.neighbors.size()<2) stop=true; // last pixel
3190  if((int)II>nmax) pix.clean(); // clean cluster tail
3191  pix.clusterID = ID; // setup new ID
3192  pList.push_back(pix); // update pList and counter
3193  if(stop) break;
3194  }
3195 
3196  if(!II) return II;
3197  sCuts.push_back(0); // to be processed by likelihood
3198 
3199  std::vector<int> list(II); // update cluster list
3200  std::vector<int> vtof(NIFO); // recreate time configuration array
3201  std::vector<int> vtmp; // recreate sky index array
3202  for(i=0; i<II; ++i) list[i] = I++;
3203  cList.push_back(list);
3204  nTofF.push_back(vtof);
3205  p_Ind.push_back(vtmp);
3206  return II;
3207 }
3208 
3209 
3210 //**************************************************************************
3211 // set arrays for time-delayed amplitudes in collected coherent pixels
3212 // !!! works only with WDM transformation
3213 //**************************************************************************
3214 size_t netcluster::loadTDamp(network &net, char c, size_t BATCH, size_t LOUD)
3215 {
3216 // set time-delayed amplitude vectors in collected coherent pixels
3217 // returns number of pixels to process, if zero - nothing to process
3218 // net: network
3219 // c: 'a','A' - delayed amplitudes, 'p','P' - delayed power
3220 // BATCH - max number of pixels to process in one batch
3221 // LOUD - max number of loudest pixels to process in a cluster
3222 // state of pixel core field (true/false) indicates if the pixel was
3223 // visited/not_visited by loadTDamp. Time-delay amplitudes are attached only
3224 // if core=false. Therefore, before the first loadTDamp call the core status
3225 // of pixels should be set to false.
3226 
3227  if(!net.ifoListSize()) {
3228  cout<<"netcluster::setTDvec() error: empty network.";
3229  exit(1);
3230  }
3231  if(net.rTDF<=0.) {
3232  cout<<"netcluster::setTDvec() error: run network::setDelayIndex() first.";
3233  exit(1);
3234  }
3235 
3236  WSeries<double>* pTF = net.getifo(0)->getTFmap();
3237 
3238  size_t i,j,k,K,KK;
3239  size_t batch = BATCH ? BATCH : this->size()+1;
3240  size_t L = size_t(net.getDelay((char*)"MAX")*net.rTDF)+1;
3241  size_t nIFO = net.ifoListSize();
3242  size_t loud = LOUD ? LOUD : batch;
3243  size_t count = 0;
3244  size_t npix = 0;
3245  int waveR = int(pTF->wrate()+0.1); // wavelet rate
3246  int ind;
3247 
3248  netpixel* pix; // pointer to pixel
3249  const vector_int* v; // pointer to cluster array of pixels
3250  wavearray<float> vec; // storage for delayed amplitudes
3251 
3252 // set time delayed amplitudes
3253 
3254  for(i=0; i<this->cList.size(); i++){
3255 
3256  if(this->sCuts[i]==1) continue; // skip rejected clusters
3257  v = &(this->cList[i]);
3258  K = v->size();
3259  if(!K) continue;
3260  KK = LOUD && K>loud ? loud : K;
3261  if(this->sCuts[i]==-2) {count+=KK; continue;} // skip loaded clusters
3262 
3263  bool skip = true;
3264  npix = 0;
3265  for(k=0; k<K; k++) { // loop over pixels
3266  pix = &(this->pList[(*v)[k]]);
3267  if(!pix->core) skip=false;
3268  if(pix->tdAmp.size()) {skip=false; npix++;}
3269  }
3270  if(npix==K) {count+=K; continue;} // skip loaded clusters
3271  if(skip) continue; // skip processed clusters
3272 
3273 // sort pixels
3274 
3275  netpixel** pp = (netpixel**)malloc(K*sizeof(netpixel*));
3276  for(k=0; k<K; k++) pp[k] = &(pList[(*v)[k]]);
3277  qsort(pp, K, sizeof(netpixel*), &compareLIKE);
3278 
3279  skip = false;
3280  npix = 0;
3281  for(k=0; k<KK; k++) { // loop over loud pixels
3282  pix = pp[k];
3283 
3284  if(count>=batch) {skip = true; break;}
3285  if(pix->tdAmp.size() && pix->core) {
3286  npix++; // count loaded pixels in the cluster
3287  count++; // count loaded pixels in the batch
3288  continue; // skip loaded pixels
3289  }
3290  if(!pix->core) count++; //
3291  else continue; // skip processed pixels
3292  if(int(pix->rate+0.1)!= waveR) continue; // skip wrong resolutions
3293 
3294  for(j=0; j<nIFO; j++) { // loop over detectors
3295  pTF = net.getifo(j)->getTFmap(); // pointer to TF array
3296  ind = int(pix->data[j].index); // index in TF array
3297  vec = pTF->pWavelet->getTDvec(ind,L,c); // obtain TD vector
3298  pix->tdAmp.push_back(vec); // store TD vector
3299  }
3300 
3301  pix->core = true; // mark pixel as processed
3302  npix++;
3303  }
3304  //cout<<i<<" "<<npix<<" "<<KK<<" "<<K<<" "<<LOUD<<endl;
3305  free(pp);
3306  if(LOUD && npix==KK) this->sCuts[i] = -2; // mark fully loaded cluster
3307  if(skip) break;
3308  }
3309  return count;
3310 }
3311 
3312 
3313 //**************************************************************************
3314 // set arrays for time-delayed amplitudes in collected coherent pixels
3315 // !!! works only with WDM transformation
3316 //**************************************************************************
3317 size_t netcluster::loadTDampSSE(network &net, char c, size_t BATCH, size_t LOUD)
3318 {
3319 // set time-delayed amplitude vectors in collected coherent pixels
3320 // fast version by using sparse TF arrays and SSE instructions
3321 // returns number of pixels to process, if zero - nothing to process
3322 // net: network
3323 // c: 'a','A' - delayed amplitudes, 'p','P' - delayed power
3324 // BATCH - max number of pixels to process in one batch
3325 // LOUD - max number of loudest pixels to process in a cluster
3326 // state of pixel core field (true/false) indicates if the pixel was
3327 // visited/not_visited by loadTDamp. Time-delay amplitudes are attached only
3328 // if core=false. Therefore, before the first loadTDamp call the core status
3329 // of pixels should be set to false.
3330 
3331  if(!net.ifoListSize()) {
3332  cout<<"netcluster::setTDvec() error: empty network.";
3333  exit(1);
3334  }
3335  if(net.rTDF<=0.) {
3336  cout<<"netcluster::setTDvec() error: run network::setDelayIndex() first.";
3337  exit(1);
3338  }
3339 
3340  size_t i,j,k,K,KK,M;
3341  size_t batch = BATCH ? BATCH : this->size()+1;
3342  size_t L = size_t(net.getDelay((char*)"MAX")*net.rTDF)+1;
3343  size_t nIFO = net.ifoListSize();
3344  size_t loud = LOUD ? LOUD : batch;
3345  size_t count = 0;
3346  size_t npix = 0;
3347  size_t nres = net.getifo(0)->ssize(); // number of resolutions
3348  int ind;
3349 
3350  netpixel* pix; // pointer to pixel
3351  const vector_int* v; // pointer to cluster array of pixels
3352  wavearray<float> vec; // storage for delayed amplitudes
3353  WDM<double>* wdm; // pointer to wdm transform
3354  SSeries<double>* pSS; // pointer to sparse TF map
3355 
3356 // set time delayed amplitudes
3357 
3358  for(i=0; i<this->cList.size(); i++){
3359 
3360  if(this->sCuts[i]==-1) continue; // skip analized clusters
3361  if(this->sCuts[i]==1) continue; // skip rejected clusters
3362  v = &(this->cList[i]);
3363  K = v->size();
3364  if(!K) continue;
3365  KK = LOUD && K>loud ? loud : K;
3366  if(this->sCuts[i]==-2) {count+=KK; continue;} // skip loaded clusters
3367 
3368  bool skip = true;
3369  npix = 0;
3370  for(k=0; k<K; k++) { // loop over pixels
3371  pix = &(this->pList[(*v)[k]]);
3372  if(!pix->core) skip=false;
3373  if(pix->tdAmp.size()) {skip=false; npix++;}
3374  }
3375  if(npix==K) {count+=K; continue;} // skip loaded clusters
3376  if(skip) continue; // skip processed clusters
3377 
3378 // sort pixels
3379 
3380  netpixel** pp = (netpixel**)malloc(K*sizeof(netpixel*));
3381  for(k=0; k<K; k++) pp[k] = &(pList[(*v)[k]]);
3382  qsort(pp, K, sizeof(netpixel*), &compareLIKE);
3383 
3384  skip = false;
3385  npix = 0;
3386  for(k=0; k<KK; k++) { // loop over loud pixels
3387  pix = pp[k];
3388 
3389  if(count>=batch) {skip = true; break;}
3390  if(pix->tdAmp.size() && pix->core) {
3391  npix++; // count loaded pixels in the cluster
3392  count++; // count loaded pixels in the batch
3393  continue; // skip loaded pixels
3394  }
3395  if(!pix->core) count++;
3396  else continue; // skip processed pixels
3397 
3398  for(j=0; j<nIFO; j++) { // loop over detectors
3399  ind = net.getifo(j)->getSTFind(pix->rate); // pointer to sparse TF array
3400  pSS = net.getifo(j)->getSTFmap(ind); // pointer to sparse TF array
3401  M = pSS->maxLayer()+1; // number of layers
3402  wdm = net.getwdm(M); // pointer to WDM transform stored in network
3403  ind = int(pix->data[j].index); // index in TF array
3404  vec = wdm->getTDvecSSE(ind,L,c,pSS); // obtain TD vector
3405 
3406  for(int qqq=0; qqq<vec.size(); qqq++){
3407  if(fabs(vec.data[qqq])>1.e6) cout<<vec.data[qqq]<<" nun in loadTDampSSE\n";
3408  }
3409 
3410  pix->tdAmp.push_back(vec); // store TD vector
3411  }
3412 
3413  pix->core = true; // mark pixel as processed
3414  npix++;
3415  }
3416  //cout<<i<<" "<<npix<<" "<<KK<<" "<<K<<endl;
3417  free(pp);
3418  if(LOUD && npix==KK) this->sCuts[i] = -2; // mark fully loaded cluster
3419  if(skip) break;
3420  }
3421  return count;
3422 }
3423 
3424 
3425 size_t netcluster::write(TFile *froot, TString tdir, TString tname, int app, int cycle, int irate, int cID)
3426 {
3427 // write pixel structure with TD vectors attached into a file
3428 // froot - root file pointer
3429 // tdir - internal root directory where the tree is located
3430 // tname - name of tree containing the cluster
3431 // app = 0 - store light netcluster
3432 // app = 1 - store pixels with the TD vectors attached by setTDAmp()
3433 // app < 0 - store all pixels
3434 // cycle - sim -> it is factor id : prod -> it is the lag number
3435 // irate - wavelet layer irate
3436 // if irate is negative the value 'irate' is used to build the tree name
3437 // this permits to create a tree for each irate
3438 // cID - cluster id (cID=0 -> write all clusters)
3439 
3440  size_t i,k;
3441  size_t I = this->pList.size(); // number of pixels;
3442  size_t II= 0;
3443 
3444  // check root file mode
3445  if(TString(froot->GetOption())!="CREATE" && TString(froot->GetOption())!="UPDATE") {
3446  cout<<"netcluster::write error: input root file wrong mode (must be CREATE or UPDATE) "
3447  <<froot->GetPath()<<endl;
3448  exit(1);
3449  } else froot->cd();
3450 
3451  // check if tdir exists otherwise it is created
3452  TDirectory* cdtree = tdir!="" ? (TDirectory*)froot->Get(tdir) : (TDirectory*)froot;
3453  if(cdtree==NULL) cdtree = froot->mkdir(tdir);
3454  cdtree->cd();
3455 
3456  int cid;
3457  int rate; // rate = pix->rate
3458  int orate; // optimal rate
3459  float ctime; // supercluster central time
3460  float cfreq; // supercluster central frequency
3461  netpixel* pix = new netpixel;
3462 
3463  // check if tree tname exists otherwise it is created
3464  char trName[64];
3465  if(irate<0) sprintf(trName,"%s-cycle:%d:%d",tname.Data(),cycle,-irate);
3466  else sprintf(trName,"%s-cycle:%d",tname.Data(),cycle);
3467  TTree* tree = (TTree*)cdtree->Get(trName);
3468  if(tree==NULL) {
3469  tree = new TTree(trName,trName);
3470  tree->Branch("cid",&cid,"cid/I");
3471  tree->Branch("rate",&rate,"rate/I");
3472  tree->Branch("orate",&orate,"orate/I");
3473  tree->Branch("ctime",&ctime,"ctime/F");
3474  tree->Branch("cfreq",&cfreq,"cfreq/F");
3475  tree->Branch("pix","netpixel",&pix,32000,0);
3476  } else {
3477  tree->SetBranchAddress("cid",&cid);
3478  tree->SetBranchAddress("rate",&rate);
3479  tree->SetBranchAddress("orate",&orate);
3480  tree->SetBranchAddress("ctime",&ctime);
3481  tree->SetBranchAddress("cfreq",&cfreq);
3482  tree->SetBranchAddress("pix",&pix);
3483  }
3484 
3485  // disable the AutoFlush mechanism : corrupts the tree (probably a ROOT bug)
3486  tree->SetAutoFlush(0);
3487 
3488  // write metadata netcluster object to the tree user info
3489 
3490  if(!app) {
3491  TList* ulist = tree->GetUserInfo();
3492  if(ulist->GetSize()>0) return 1; // cluster header already presents
3493  netcluster* nc = new netcluster;
3494  nc->cpf(*this,false,0);
3495  nc->clear();
3496  char title[256];sprintf(title,"cycle:%d",cycle);
3497  nc->SetTitle(title);
3498  ulist->Add(nc);
3499  return 0;
3500  }
3501 
3502  if(!I) return 0;
3503 
3504  // write pixels to the cluster tree
3505 
3506  for(i=0; i<this->cList.size(); ++i) {
3507  if(sCuts[i]==1) continue;
3508 
3509  const vector_int& r = cRate[i];
3510  orate = r.size()>0 ? r[0] : 0; // optimal rate
3511 
3512  ctime = cTime[i]; // supercluster central time
3513  cfreq = cFreq[i]; // supercluster central frequency
3514 
3515  const vector_int& v = cList[i];
3516  size_t K = v.size();
3517  if(!K) continue; // skip empty clusters
3518 
3519  if((cID!=0)&&(pList[v[0]].clusterID!=cID)) continue;
3520 
3521  bool skip = true;
3522  for(k=0; k<K; ++k) { // loop over pixels
3523  if(pList[v[k]].tdAmp.size()) skip=false;
3524  }
3525  if(app>0 && skip) continue;
3526 
3527  netpixel** pp = (netpixel**)malloc(K*sizeof(netpixel*));
3528  for(k=0; k<K; k++) pp[k] = &pList[v[k]];
3529  qsort(pp, K, sizeof(netpixel*), &compareLIKE); // sort pixels
3530 
3531  for(k=0; k<K; k++) { // loop over pixels
3532  if(app>0 && !pp[k]->tdAmp.size()) continue;
3533  *pix = *pp[k];
3534  pp[k]->clean(); // clean TD amplitudes
3535  pix->neighbors.clear();
3536  if(k<K-1) pix->neighbors.push_back(1);
3537  if(k>0) pix->neighbors.push_back(-1);
3538 
3539  // set right index (set in subNetCuts) for netcc[3] after pixels sorting
3540  if(k==0) pix->ellipticity = pList[v[0]].ellipticity;
3541  if(k==1) pix->ellipticity = pList[v[1]].ellipticity;
3542  if(k==0) pix->polarisation = pList[v[0]].polarisation;
3543  if(k==1) pix->polarisation = pList[v[1]].polarisation;
3544  cid = pix->clusterID; // setup new ID
3545  rate = pix->rate;
3546  tree->Fill();
3547  II++;
3548 
3549  //printf("k = %lu , clID = %lu\n", k, pix->clusterID);
3550  //printf("pixel %d from cluster %d written\n", k, i);
3551  }
3552 
3553  free(pp);
3554  }
3555 
3556  delete pix;
3557 
3558  return II;
3559 }
3560 
3561 // read clusters from root file
3562 std::vector<int>
3563 netcluster::read(TFile* froot, TString tdir, TString tname, int nmax, int cycle, int rate, int cID)
3564 {
3565 // read metadata and pixels stored in a file on cluster by cluster basis
3566 // clusters should be contiguous in the file (written by write(FILE*))
3567 // froot - root file pointer
3568 // tdir - internal root directory where the tree is located
3569 // tname - name of tree containing the cluster
3570 // nmax = 0 - read metadata
3571 // nmax > 0 - read no more than maxPix heavy pixels from a cluster
3572 // nmax < 0 - read all heavy pixels from a cluster
3573 // nmax -2 - as for (nmax<0) & skip heavy instructions to speedup read
3574 // cycle - sim -> it is factor id : prod -> it is the lag number
3575 // rate - wavelet layer rate
3576 // if rate is negative the value 'rate' is used to build the tree name
3577 // cID - cluster ID
3578 
3579  size_t i;
3580  int cid;
3581  int orate;
3582  float ctime;
3583  float cfreq;
3584  netpixel* pix = new netpixel;
3585 
3586  std::vector<int> list; // cluster list
3587  std::vector<int> vtof(NIFO); // time configuration array
3588  std::vector<int> vtmp; // sky index array
3589  std::vector<float> varea; // sky error regions array
3590  std::vector<float> vpmap; // sky pixel map array
3591  clusterdata cd; // dummy cluster data
3592 
3593  bool skip = nmax==-2 ? true : false;
3594  if(nmax<0) nmax=std::numeric_limits<int>::max();
3595 
3596  // check if dir tdir exist
3597  TObject* obj = tdir!="" ? froot->Get(tdir) : (TObject*)froot;
3598  if(obj==NULL) {
3599  cout<<"netcluster::read error: input dir " << tdir << " not exist" << endl;
3600  exit(1);
3601  }
3602  if(tdir!="" && !TString(obj->ClassName()).Contains("TDirectory")) {
3603  cout<<"netcluster::read error: input dir " << tdir << " is not a directory" << endl;
3604  exit(1);
3605  }
3606  TDirectory* cdtree = tdir!="" ? (TDirectory*)froot->Get(tdir) : (TDirectory*)froot;
3607  if(cdtree==NULL) {
3608  cout<<"netcluster::read error: tree dir " << tdir
3609  << " not present in input root file " << froot->GetPath() << endl;
3610  exit(1);
3611  } else cdtree->cd();
3612 
3613  // check if tree tname exist
3614  char trName[64];
3615  if(rate<0) sprintf(trName,"%s-cycle:%d:%d",tname.Data(),cycle,-rate);
3616  else sprintf(trName,"%s-cycle:%d",tname.Data(),cycle);
3617  TTree* tree = (TTree*)cdtree->Get(trName);
3618  if(rate<0) {tree->LoadBaskets(100000000);rate=abs(rate);} // load baskets in memory
3619  if(tree==NULL) {
3620  cout<<"netcluster::read error: tree " << trName
3621  << " not present in input root file " << froot->GetPath() << endl;
3622  exit(1);
3623  } else {
3624  tree->SetBranchAddress("cid",&cid);
3625  tree->SetBranchAddress("orate",&orate);
3626  tree->SetBranchAddress("ctime",&ctime);
3627  tree->SetBranchAddress("cfreq",&cfreq);
3628  tree->SetBranchAddress("pix",&pix);
3629  }
3630 
3631  // Extract requested infos from tree
3632  char sel[128]="";
3633  if(rate>0) sprintf(sel,"rate==%d ",rate);
3634  if(cID) {if(TString(sel)=="") sprintf(sel,"cid==%d",cID);
3635  else sprintf(sel,"%s && cid==%d",sel,cID);}
3636  if(TString(sel)=="") sprintf(sel,"1==1"); // TTreeFormula needs a non empty string
3637  TTreeFormula cut("cuts", sel, tree); // Draw substituted with TTreeFormula because of bug
3638  // sstrace -> -1 ENOENT (No such file or directory)
3639  // this get rid of the unwanted htemp;1 in root file created by Draw
3640  if(cdtree->Get("htemp")!=NULL) cdtree->Delete("htemp");
3641 
3642  // fill entry,icint arrays with the selected entries
3643  size_t size = tree->GetEntries();
3644  wavearray<double> entry(size);
3645  wavearray<double> icid(size);
3646  int cnt=0;
3647  tree->SetBranchStatus("orate",false);
3648  tree->SetBranchStatus("ctime",false);
3649  tree->SetBranchStatus("cfreq",false);
3650  tree->SetBranchStatus("pix",false);
3651  for(i=0;i<size;i++) {
3652  tree->GetEntry(i);
3653  if(cut.EvalInstance()==0) continue;
3654  entry[cnt]=i;
3655  icid[cnt]=cid;
3656  cnt++;
3657  }
3658  tree->SetBranchStatus("orate",true);
3659  tree->SetBranchStatus("ctime",true);
3660  tree->SetBranchStatus("cfreq",true);
3661  tree->SetBranchStatus("pix",true);
3662  size=cnt;
3663 
3664  // fill vector with cluster ids
3665  std::vector<int> clist;
3666  for(i=0;i<size;i++) clist.push_back(int(icid[i]+0.5));
3667  // erase duplicate entries
3668  removeDuplicates<int>(clist);
3669 
3670  if(nmax==0) {
3671  if(rate<=0 && cID==0){ // read nextcluster metadata from file
3672  TList* ulist = tree->GetUserInfo();
3673  if(ulist->GetSize()==0) {
3674  cout<<"netcluster::read error: header is null" << endl; exit(1);
3675  }
3676  this->clear();
3677  *this = *(netcluster*)ulist->At(0);
3678  delete tree;
3679  return clist; // return the full list of clusters in the tree
3680  } else {
3681  delete tree;
3682  return clist; // return the selected list of clusters in the tree
3683  }
3684  }
3685 
3686  if(rate<0) {cout<<"netcluster::read error: input rate par must be >= 0" << endl; exit(1);}
3687 
3688  int os=0;
3689  for(size_t k=0;k<clist.size();k++) { // read cluster id in the list
3690 
3691  int id = clist[k];
3692 
3693  // clean TD amplitudes in pList structure
3694  size_t I = pList.size();
3695  if(!skip) for(i=0; i<I; ++i) pList[i].clean(); // clean TD amplitudes
3696 
3697  // reads first pixel
3698  bool stop = false;
3699  size_t II = 0;
3700  int ID = cList.size()+1;
3701 
3702  std::vector<int> crate;
3703  for(i=os;i<size;i++) {
3704  if(int(icid[i]+0.5)!=id) continue;
3705  tree->GetEntry(int(entry[i]+0.5));
3706  II++; // update counter
3707  if(II<2 && pix->neighbors.size()<1) stop=true; // just one pixel
3708  if(II>1 && pix->neighbors.size()<2) stop=true; // last pixel
3709  if(II>nmax) pix->clean(); // clean cluster tail
3710  pix->clusterID = ID; // setup new ID
3711  pList.push_back(*pix); // update pList and counter
3712  if(orate&&!crate.size()) crate.push_back(orate);// update cluster rate
3713  if(os==i) os++; // updated the already processed entry index
3714  if(stop) break;
3715  }
3716 
3717  if(!II) {delete tree;return clist;}
3718  sCuts.push_back(0); // to be processed by likelihood
3719 
3720  list.clear();
3721  for(i=0; i<II; ++i) list.push_back(I++); // update cluster list
3722  cList.push_back(list);
3723  cRate.push_back(crate);
3724  cTime.push_back(ctime);
3725  cFreq.push_back(cfreq);
3726  sArea.push_back(varea); // recreate sky error regions array
3727  p_Map.push_back(vpmap); // recreate sky pixel map array
3728  nTofF.push_back(vtof); // recreate time configuration array
3729  p_Ind.push_back(vtmp); // recreate sky index array
3730  if(!skip) cData.push_back(cd); // recreate dummy cluster data
3731  }
3732  delete pix;
3733  delete tree;
3734  return clist; // return the selected list of clusters in the tree
3735 }
3736 
3738 {
3739  int nhpix = 0; // total number of heavy pixels in the netcluster object
3740  for(size_t i=0; i<this->cList.size(); ++i) {
3741  if(sCuts[i]==1) continue;
3742 
3743  const vector_int& v = cList[i];
3744  size_t K = v.size();
3745  if(!K) continue;
3746 
3747  for(size_t k=0; k<K; ++k) { // loop over pixels
3748  if(pList[v[k]].tdAmp.size()) nhpix++;
3749  }
3750  }
3751  ;
3752  cout << endl;
3753  cout.precision(14);
3754  cout << "rate\t= " << this->rate << endl;
3755  cout << "start\t= " << this->start << endl;
3756  cout << "stop\t= " << this->stop << endl;
3757  cout << "shift\t= " << this->shift << endl;
3758  cout << "bpp\t= " << this->bpp << endl;
3759  cout << "flow\t= " << this->flow << endl;
3760  cout << "ghigh\t= " << this->fhigh << endl;
3761  cout << "run\t= " << this->run << endl;
3762  cout << "nPIX\t= " << this->nPIX << endl;
3763  cout << "pair\t= " << this->pair << endl;
3764  cout << endl;
3765  cout << "cList\t= " << this->cList.size() << endl;
3766  cout << "pList\t= " << this->pList.size() << endl;
3767  cout << "hpList\t= " << nhpix << endl;
3768  cout << endl;
3769 
3770  return;
3771 }
3772 
3773 
3774 
wavearray< double > t(hp.size())
TTree * tree
Definition: TimeSortTree.C:20
void sethigh(double f)
Definition: wseries.hh:132
detector * getifo(size_t n)
param: detector index
Definition: network.hh:436
virtual size_t defragment(double T, double F, TH2F *=NULL)
T - maximum time gap in seconds F - maximum frequency gap in Hz.
Definition: netcluster.cc:1294
double rho
double stop
Definition: netcluster.hh:380
virtual void resize(unsigned int)
Definition: wseries.cc:901
std::vector< int > vector_int
Definition: cluster.hh:35
int getBaseWave(int m, int n, SymmArray< double > &w)
Definition: WDM.cc:323
static const double C
Definition: GNGen.cc:28
#define NIFO
Definition: wat.hh:74
size_t write(const char *file, int app=0)
Definition: netcluster.cc:3008
double gammaCL(double x, double n)
Definition: watfun.hh:131
std::vector< vector_int > cRate
Definition: netcluster.hh:398
static double g(double e)
Definition: GNGen.cc:116
double M
Definition: DrawEBHH.C:13
par [0] value
wavearray< double > getMRAwave(network *net, int ID, size_t n, char atype='S', int mode=0)
Definition: netcluster.cc:2899
int j00
int getMaxLevel()
Definition: wseries.cc:103
size_t clusterID
Definition: netpixel.hh:109
double min(double x, double y)
Definition: eBBH.cc:31
int offset
Definition: TestSTFT_2.C:19
virtual void rate(double r)
Definition: wavearray.hh:141
std::vector< wavearray< float > > tdAmp
Definition: netpixel.hh:123
int compEndP(const void *p, const void *q)
Definition: netcluster.cc:78
int irate
std::vector< pixel > cluster
Definition: wavepath.hh:61
CWB run(runID)
wavearray< float > getTDvecSSE(int j, int K, char c, SSeries< double > *pss)
Definition: WDM.cc:1201
#define np
plot hist2D SetName("WSeries-1")
wavearray< double > a(hp.size())
size_t frequency
Definition: netpixel.hh:111
float likelihood
Definition: netpixel.hh:114
WSeries< float > v[nIFO]
Definition: cwb_net.C:80
par [0] name
int n
Definition: cwb_net.C:28
wavearray< double > z
Definition: Test10.C:32
double fhigh
Definition: netcluster.hh:384
std::vector< int > neighbors
Definition: netpixel.hh:124
double iGamma(double r, double p)
Definition: watfun.hh:205
TString("c")
int ID
Definition: TestMDC.C:70
ofstream out
Definition: cwb_merge.C:214
cout<< endl;cout<< "ts size = "<< ts.size()<< " ts rate = "<< ts.rate()<< endl;tf.Forward(ts, wdm);int levels=tf.getLevel();cout<< "tf size = "<< tf.size()<< endl;double dF=tf.resolution();double dT=1./(2 *dF);cout<< "rate(hz) : "<< RATE<< "\ layers : "<< nLAYERS<< "\ dF(hz) : "<< dF<< "\ dT(ms) : "<< dT *1000.<< endl;int itime=TIME_PIXEL_INDEX;int ifreq=FREQ_PIXEL_INDEX;int index=(levels+1) *itime+ifreq;double time=itime *dT;double freq=(ifreq >0) ? ifreq *dF :dF/4;cout<< endl;cout<< "PIXEL TIME = "<< time<< " sec "<< endl;cout<< "PIXEL FREQ = "<< freq<< " Hz "<< endl;cout<< endl;wavearray< double > x
std::vector< pixdata > data
Definition: netpixel.hh:122
wavearray< double > get(char *name, size_t index=0, char atype='R', int type=1, bool=true)
param: string with parameter name param: index in the amplitude array, which define detector param: c...
Definition: netcluster.cc:2207
double SolarMass()
Definition: constants.hh:202
double bpp
Definition: test_config1.C:22
float theta
double mchirpTEST(int ID)
Definition: netcluster.cc:1844
WDM< double > wdm(nLAYERS, nLAYERS, 6, 10)
netpixel pix(nifo)
void setlow(double f)
Definition: wseries.hh:125
double flow
Definition: netcluster.hh:383
STL namespace.
std::slice getSlice(double n)
Definition: wseries.hh:152
double & gap
size_t setcore(bool core, int id=0)
Definition: netcluster.cc:243
Long_t size
virtual size_t supercluster(char atype, double S, bool core)
param: statistic: E - excess power, L - likelihood param: selection threshold T for likelihood cluste...
Definition: netcluster.cc:808
size_t layers
Definition: netpixel.hh:112
int m
Definition: cwb_net.C:28
std::vector< vector_int > cList
Definition: netcluster.hh:397
virtual void start(double s)
Definition: wavearray.hh:137
int j
Definition: cwb_net.C:28
canvas cd(1)
i drho i
TRandom3 rnd(1)
double rate
Definition: netcluster.hh:378
TList * list
bool write(const FILE *)
Definition: netpixel.cc:91
wc clear()
#define N
cout<< "SNR "<< xsnr<< endl;wavearray< double > f
Definition: ComputeSNR.C:75
bool core
Definition: netpixel.hh:120
char ifo[NIFO_MAX][8]
double Tgap
Definition: test_config1.C:23
size_t ssize()
Definition: detector.hh:190
network ** net
NOISE_MDC_SIMULATION.
size_t ifoListSize()
Definition: network.hh:431
WDM< double > * getwdm(size_t M)
param: number of wdm layers
Definition: network.hh:448
void clean(int cID=0)
Definition: netcluster.hh:451
size_t mode
virtual void waveSplit(DataType_t **pp, size_t l, size_t r, size_t m) const
Definition: wavearray.cc:1499
virtual double rms()
Definition: wavearray.cc:1206
wavearray< double > w
Definition: Test1.C:27
#define nIFO
nc append(pix)
void wrate(double r)
Definition: wseries.hh:120
virtual size_t size() const
Definition: wavearray.hh:145
float phi
double signPDF(const size_t m, const size_t k)
Definition: watfun.hh:97
size_t size()
Definition: netpixel.hh:89
virtual size_t cluster()
return number of clusters
Definition: netcluster.cc:469
int BATCH
double G
Definition: DrawEBHH.C:12
size_t size() const
Definition: wslice.hh:89
double shift
Definition: netcluster.hh:382
unsigned long nSTS
Definition: WaveDWT.hh:143
TGraph * gr
size_t start() const
Definition: wslice.hh:85
virtual ~netcluster()
Definition: netcluster.cc:112
double getwave(int, WSeries< double > &, char='W', size_t=0)
param: cluster ID param: WSeries where to put the waveform return: noise rms
Definition: netcluster.cc:2762
static const double SM
Definition: GNGen.cc:26
i() int(T_cor *100))
std::vector< netpixel > pList
Definition: netcluster.hh:390
size_t stride() const
Definition: wslice.hh:93
float polarisation
Definition: netpixel.hh:119
double Pi
bool log
Definition: WaveMDC.C:41
double fhigh
double * tmp
Definition: testWDM_5.C:31
double getDelay(const char *c="")
Definition: network.cc:2818
std::vector< WDM< double > * > wdmList
Definition: network.hh:617
WSeries< double > pTF[nRES]
Definition: revMonster.cc:8
char cut[512]
double start
Definition: netcluster.hh:379
printf("total live time: non-zero lags = %10.1f \, liveTot)
int l
char fname[1024]
int compareLIKE(const void *x, const void *y)
Definition: netcluster.cc:65
virtual wavearray< float > getTDvec(int j, int k, char c='p')
Definition: WaveDWT.hh:84
std::vector< float > cFreq
Definition: netcluster.hh:400
virtual size_t append(netcluster &wc)
param: input netcluster return size of appended pixel list
Definition: netcluster.cc:769
int k
void append(int n)
Definition: netpixel.hh:103
TString sel("slag[1]:slag[2]")
size_t cpf(const netcluster &, bool=false, int=0)
Definition: netcluster.cc:117
TH1 * t0
double mchirp(int ID, double=2.5, double=1.e20, double=0)
Definition: netcluster.cc:1424
double F
size_t time
Definition: netpixel.hh:110
size_t loadTDampSSE(network &net, char c, size_t BATCH=10000, size_t LOUD=0)
Definition: netcluster.cc:3317
virtual size_t delink()
Definition: netcluster.cc:373
double * entry
Definition: cwb_setcuts.C:224
double e
void setLevel(size_t n)
Definition: wseries.hh:112
void removeDuplicates(std::vector< T > &vec)
Definition: netcluster.cc:47
TFile * froot
int npix
double dt
void PlotClusters()
Definition: netcluster.cc:2186
regression r
Definition: Regression_H1.C:44
double GravitationalConstant()
Definition: constants.hh:131
double flow
#define RATE
int nifo
unsigned long nWWS
pointer to wavelet work space
Definition: WaveDWT.hh:142
char title[256]
Definition: SSeriesExample.C:1
float ellipticity
Definition: netpixel.hh:118
double T
Definition: testWDM_4.C:11
netcluster & operator=(const netcluster &)
Definition: netcluster.cc:236
ifstream in
std::vector< int > sCuts
Definition: netcluster.hh:392
std::vector< float > cTime
Definition: netcluster.hh:399
int LOUD
double nSUB
Definition: netcluster.hh:388
WSeries< double > * getTFmap()
param: no parameters
Definition: detector.hh:179
wavearray< int > index
int compare_PIX(const void *x, const void *y)
Definition: netcluster.cc:54
virtual void stop(double s)
Definition: wavearray.hh:139
double fabs(const Complex &x)
Definition: numpy.cc:55
virtual size_t cleanhalo(bool=false)
param: if false - de-cluster pixels return size of the list
Definition: netcluster.cc:561
bool read(const FILE *)
Definition: netpixel.cc:147
void Forward(int n=-1)
param: wavelet - n is number of steps (-1 means full decomposition)
Definition: wseries.cc:246
int cnt
void print()
Definition: netcluster.cc:3737
Meyer< double > S(1024, 2)
double df
sprintf(tfres,"(1/%g)x(%g) (sec)x(Hz)", 2 *df, df)
std::vector< clusterdata > cData
Definition: netcluster.hh:391
double asnr
double mmax
virtual wavearray< double > select(char *, double)
Definition: netcluster.cc:263
void chirpDraw(int id)
Definition: netcluster.cc:2177
DataType_t * data
Definition: wavearray.hh:319
const int nRES
Definition: revMonster.cc:7
Long_t id
double rTDF
Definition: network.hh:576
double bpp
Definition: netcluster.hh:381
WaveDWT< DataType_t > * pWavelet
Definition: wseries.hh:456
double dT
Definition: testWDM_5.C:12
SSeries< double > * getSTFmap(size_t n)
Definition: detector.hh:187
bool save
double ctime
fclose(ftrig)
float rate
Definition: netpixel.hh:113
size_t read(const char *)
Definition: netcluster.cc:3115
double getdata(char type='R', size_t n=0)
Definition: netpixel.hh:74
size_t addhalo(int=0)
param: packet pattern mode return size of the list
Definition: netcluster.cc:631
double shift[NIFO_MAX]
virtual void resize(unsigned int)
Definition: wavearray.cc:463
static double pr
Definition: geodesics.cc:26
wavearray< double > y
Definition: Test10.C:31
size_t nPIX
Definition: netcluster.hh:385
int getSTFind(double r)
Definition: detector.hh:182
size_t loadTDamp(network &net, char c, size_t BATCH=10000, size_t LOUD=0)
Definition: netcluster.cc:3214
int nsel
Definition: cwb_setcuts.C:237
int maxLayer()
Definition: wseries.hh:139
static double Delta
Definition: geodesics.cc:26
int m_H
Definition: Wavelet.hh:121
exit(0)
void clean()
Definition: netpixel.hh:99
double SpeedOfLightInVacuo()
Definition: constants.hh:114
char os[1024]
void clear()
Definition: netcluster.hh:427