Logo coherent WaveBurst  
Library Reference Guide
Logo
network.cc
Go to the documentation of this file.
1 /*
2 # Copyright (C) 2019 Sergey Klimenko, Gabriele Vedovato
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 // S. Klimenko, University of Florida, Gainesville, FL
21 // G.Vedovato, INFN, Sezione di Padova, Italy
22 // WAT network class
23 // ++++++++++++++++++++++++++++++++++++++++++++++
24 
25 #define NETWORK_CC
26 #include <time.h>
27 #include <iostream>
28 #include <stdexcept>
29 #include <xmmintrin.h>
30 #include <immintrin.h>
31 #include "TRandom3.h"
32 #include "TMath.h"
33 #include <fstream>
34 #include "Meyer.hh"
35 #include "injection.hh"
36 #include "network.hh"
37 #include "watplot.hh" // remove
38 #include "TComplex.h"
39 
40 using namespace std;
41 
42 ClassImp(network)
43 
44 // constructors
45 
47  nRun(0), nLag(1), nSky(0), mIFO(0), rTDF(0), Step(0.), Edge(0.), gNET(0.), aNET(0.), iNET(0),
48  eCOR(0.), norm(1.), e2or(0.), acor(sqrt(2.)), pOUT(false), EFEC(true), local(true), optim(true),
49  delta(0.), gamma(0.), precision(0.02), pSigma(4.), penalty(1.), netCC(-1.), netRHO(0.),
50  eDisbalance(true), MRA(false), wfsave(false), pattern(1), _WDM(false), _LIKE(' ')
51 {
52  this->ifoList.clear();
53  this->ifoName.clear();
54  this->segList.clear();
55  this->mdcList.clear();
56  this->livTime.clear();
57  this->mdcTime.clear();
58  this->mdcType.clear();
59  this->mdc__ID.clear();
60 }
61 
62 
64 {
65  *this = value;
66 }
67 
68 // destructor
69 
71 {
72  return;
73 }
74 
75 //**************************************************************************
76 //:select TF samples by value of the network excess energy: 2-8 detectors
77 //**************************************************************************
78 long network::getNetworkPixels(int LAG, double Eo, double norm, TH1F* hist)
79 {
80 // 2G analysis algorithm for selection of significant network pixles
81 // works with WDM/wavelet energy TF maps
82 // LAG - time shift lag defining how detectors are shifted wrt each other.
83 // Eo - pixel energy threshold
84 // norm - dummy
85 // hist- pointer to a diagnostic histogram showing network pixel energy.
86 
87  size_t nIFO = this->ifoList.size(); // number of detectors
88 
89  if(nIFO>NIFO) {
90  cout<<"network::getNetworkPixels(): "
91  <<"invalid number of detectors or\n";
92  return 0;
93  }
94  if(getifo(0)->getTFmap()->w_mode != 1) {
95  cout<<"network::getNetworkPixels(): invalid whitening mode.\n";
96  return 0;
97  }
98 
99  WSeries<double>* pTF = this->getifo(0)->getTFmap(); // pointer to first TF map
100  WSeries<double> MAP; MAP = *pTF; MAP=0.; // initialize TF map
101  wavearray<double>* hTS = this->getifo(0)->getHoT(); // pointer to first TS data
102 
103  int i,j,k,m,n,NN,jj,nM,jE,jb,je,J,K;
104 
105  double Em = 2*Eo; // maximum (sole pixel) threshold
106  double Eh = Em*Em; // halo energy^2
107  double R = pTF->wrate(); // pixel layer rate
108  double r = hTS->rate(); // TS rate
109  int N = pTF->size(); // size of TF array
110  int M = hTS->size(); // size of TS array
111  int I = pTF->maxLayer()+1; // number of layers
112  int II = pTF->maxLayer()-1; // number of layers - 2
113  int jB = int(this->Edge*R+0.001); // number of samples in the edges
114  if(jB&1) {cout<<"getNetworkPixels(1): WDM parity violation\n"; exit(1);}
115 
116  if(jB < 3) {
117  cout<<"network::getNetworkPixels(): insufficient data edge length.\n";
118  exit(1);
119  }
120 
121  netpixel pix(nIFO);
122  pix.core = true;
123  pix.rate = R;
124  pix.layers = I;
125 
126  int in[NIFO]; // pixel time index
127  int IN[NIFO]; // pixel time index
128  double* PDATA;
129  double* pmap;
130  double* pdata[NIFO]; // pointers to data
131  double* pp[5]; // pointers to sorted F-arrays
132  for(n=0; n<nIFO; n++) { // pointers to data
133  pdata[n] = getifo(n)->getTFmap()->data;
134  }
135 
136  long nPix = 0;
137  size_t count = 0; // live pixel counter
138  double a,b,E,Ct,Cb,Ht,Hb;
139 
140  if(hist) {pixeLHood = *pTF; pixeLHood=-1.;}
141  if(this->veto.size() != M) { // set veto array if it is not set
142  veto.resize(M); veto = 1;
143  }
144  short* pveto = this->veto.data; // pointer to veto
145 
146  this->wc_List[LAG].clear(); // clear netcluster structure
147  this->livTime[LAG] = 0.; // clear live time counters
148  this->wc_List[LAG].setlow(pTF->getlow());
149  this->wc_List[LAG].sethigh(pTF->gethigh());
150 
151  a = 1.e10; nM = 0; // master detector
152  for(n=0; n<nIFO; n++) {
153  b = this->getifo(n)->lagShift.data[LAG]; // shift in seconds
154  if(a>b) { a = b; nM = n; }
155  }
156 
157  for(n=0; n<nIFO; n++) {
158  b = this->getifo(n)->lagShift.data[LAG]; // shift in seconds
159  K = int((b-a)*R+0.001); // time shift wrt reference
160  if(K&1) {cout<<"getNetworkPixels(2): WDM parity violation\n"; exit(1);}
161  in[n] = IN[n] = K+jB; // time index of first pixel in the layer
162  }
163 
164  int ib=1;
165  int ie=I;
166  for(i=0; i<I; i++) { // select bandwidth
167  if(pTF->frequency(i) <= pTF->gethigh()) ie=i;
168  if(pTF->frequency(i) <= pTF->getlow()) ib=i+1;
169  }
170  if(ie>I-1) ie = I-1; // required by catalog
171  if(ib<1) ib = 1; // required by catalog
172 
173  slice S = pTF->getSlice(0);
174  jE = S.size()-jB; // last good sample in the layer
175  NN = jE-jB; // #of good samples in the layer
176  if(jE&1) {cout<<"getNetworkPixels(3): WDM parity violation\n"; exit(1);}
177 
178  //cout<<r<<" "<<R<<" "<<I<<" "<<jB<<" "<<this->veto.size()<<endl;
179  //cout<<ib<<" "<<ie<<" "<<NN<<" "<<jB<<" "<<jE<<endl;
180 
181  for(jj=0; jj<NN; jj++) { // loop over time stamps
182 
183  double VETO = 1.;
184  pmap = MAP.data+(jj+jB)*I; // pointer to 0 F sample in MAP
185  for(n=0; n<nIFO; n++) {
186  if(in[n] >= jE) in[n] -= NN; // go to jB sample
187  jb = int(in[n]*r/R+0.01); // first veto index
188  je = int((in[n]+1)*r/R+0.01); // last veto index
189  while(jb<je) if(!pveto[jb++]) VETO=0.; // set veto value
190  PDATA = &(pdata[n][in[n]*I]); // pointer to 0 F sample
191  for(i=0; i<I; i++) pmap[i]+=*PDATA++; // sum energy
192  in[n]++; // increment index pointer
193  }
194 
195  for(i=0; i<I; i++) {
196  pmap[i] *= VETO;
197  if(pmap[i]<Eo || i<ib) pmap[i]=0.; // zero sub-threshold pixels
198  if(pmap[i]>Em) pmap[i]=Em+0.1; // degrade loud pixels
199  }
200  count += VETO; // count live time
201  }
202 
203  for(jj=0; jj<NN; jj++) { // loop over time stamps
204 
205  pmap = MAP.data+(jj+jB)*I; // pointer to 0 F sample in MAP
206  for(n=0; n<nIFO; n++) {
207  if(IN[n] >= jE) IN[n] -= NN; // go to jB sample
208  }
209  for(n=0; n<5; n++) pp[n]=pmap+(n-2)*I; // initialize set of pointers
210  for(i=ib; i<ie; i++) {
211  if((E=pp[2][i])<Eo) continue; // skip subthreshold pixels
212  Ct = pp[2][i+1]+pp[3][ i ]+pp[3][i+1]; // top core
213  Cb = pp[2][i-1]+pp[1][ i ]+pp[1][i-1]; // bottom core
214  Ht = pp[4][i+1]; // top halo
215  Ht+= i<II? pp[4][i+2]+pp[3][i+2]:0.; // top halo
216  Hb = pp[0][i-1]; // bottom halo
217  Hb+= i>1 ? pp[0][i-2]+pp[1][i-2]:0.; // bottom halo
218 
219  if((Ct+Cb)*E<Eh &&
220  (Ct+Ht)*E<Eh &&
221  (Cb+Hb)*E<Eh &&
222  E<Em) continue;
223 
224  E = 0;
225  for(n=0; n<nIFO; n++) {
226  j = IN[n]*I+i; // sample index
227  pix.data[n].index = j;
228  pix.data[n].asnr = sqrt(pdata[n][j]);
229  E += pdata[n][j];
230  }
231  j = IN[nM]*I+i; // reference sample index
232  if(hist) hist->Fill(E);
233  if(hist) pixeLHood.data[j] = E;
234  pix.time = j;
235  pix.frequency = i;
236  pix.likelihood = E;
237  pix.phi = 1; // set pixel mark 1 (will be owerriden in likelihood)
238  wc_List[LAG].append(pix); // save pixels in wc_List
239  nPix++;
240  }
241  for(n=0; n<nIFO; n++) IN[n]++; // increment IN
242  }
243 
244 // set metadata in wc_List
245  this->wc_List[LAG].start = pTF->start();
246  this->wc_List[LAG].stop = pTF->stop();
247  this->wc_List[LAG].rate = pTF->rate();
248  this->livTime[LAG] = count/R; // live time depends on resolution
249 
250  if(nPix) this->setRMS();
251 
252  return nPix;
253 }
254 
255 
256 void network::test_sse(int n, int m) {
257  wavearray<float> a(n*4);
258  wavearray<float> b(n*4);
259  wavearray<float> x(n*4);
260  float qq[4];
261  float rq[4];
262  float sq[4];
263  float* pa = a.data;
264  float* pb = b.data;
265  float* px = x.data;
266  __m128* _pa = (__m128*) pa;
267  __m128* _pb = (__m128*) pb;
268  __m128* _px = (__m128*) px;
269 
270  for(int i=0; i<n*4; i++) {
271  a.data[i]=i/float(n*4*m);
272  b.data[i]=i/float(n*4*m);
273  x.data[i]=i*float(m)/float(n*4);
274  }
275 
276  for(int i=0; i<n; i++) {
277  *(_pa+i) = _mm_sqrt_ps(*(_px+i));
278  *(_pa+i) = _mm_div_ps(_mm_set1_ps(1.),*(_pa+i));
279  *(_pb+i) = _mm_rsqrt_ps(*(_px+i));
280  _mm_storeu_ps(qq,*(_px+i));
281  _mm_storeu_ps(sq,*(_pa+i));
282  _mm_storeu_ps(rq,*(_pb+i));
283  printf("%d %9.7f %9.7f %9.7f \n",i,qq[0],sq[0],rq[0]);
284  printf("%d %9.7f %9.7f %9.7f \n",i,qq[1],sq[1],rq[1]);
285  printf("%d %9.7f %9.7f %9.7f \n",i,qq[2],sq[2],rq[2]);
286  printf("%d %9.7f %9.7f %9.7f \n",i,qq[3],sq[3],rq[3]);
287  }
288 
289  return;
290 }
291 
292 
293 long network::likelihoodWP(char mode, int lag, int iID, TH2F* hist)
294 {
295 // Likelihood analysis with packets
296 // mode: analysis mode:
297 // OPTRES analyses, if upper case and optim=true
298 // MRA analysis in low case or optim=false
299 // r - un-modeled
300 // i - iota - wave: no,partial dispersion correction
301 // p - Psi - wave (no dispersion correction)
302 // l,s - linear, loose linear
303 // c,g - circular. loose circular
304 // e,b - elliptical (no dispersion correction), b=p for now
305 // iID: cluster ID, if negative - sky error regions are calculated
306 // lag: lag index
307 // hist: chirp histogram: If not needed, TGraphErrors* hist=NULL
308 // shold be used as input
309 // return number of processed pixels
310 // Negative gamma regulator turns on the AP prior for sky localization
311 //
312 
313  if(!this->wc_List[lag].size()) return 0;
314 
315  this->like('2');
316  this->wdm(true);
317  this->tYPe = mode;
318 
319  bool cirwave = mode=='g' || mode=='G' || mode=='c' || mode=='C';
320  bool linwave = mode=='l' || mode=='L' || mode=='s' || mode=='S';
321  bool iotwave = mode=='i' || mode=='l' || mode=='e' || mode=='c' ||
322  mode=='I' || mode=='L' || mode=='E' || mode=='C';
323  bool psiwave = mode=='l' || mode=='e' || mode=='p' ||
324  mode=='L' || mode=='E' || mode=='P';
325  bool mureana = mode=='i' || mode=='e' || mode=='c' ||
326  mode=='r' || mode=='p' || mode=='b' ||
327  mode=='l' || mode=='s' || mode=='g';
328  bool rndwave = mode=='r' || mode=='R';
329 
330  bool prior = this->gamma<0 ? true : false; // gamma<0 : antenna pattern prior is used
331  bool m_chirp = this->optim ? false : mureana;
332 
333  if(!this->optim) mureana = true;
334 
335  size_t nIFO = this->ifoList.size();
336  size_t ID = abs(iID);
337 
338  if(nIFO>NIFO) {
339  cout<<"network::likelihoodAVX(): invalid network.\n";
340  exit(0);
341  }
342 
343  float En = 2*acor*acor*nIFO; // network energy threshold in the sky loop
344  float gama = this->gamma*this->gamma*2./3.; // gamma regulator for x componet
345  float deta = fabs(this->delta); if(deta>1) deta=1; // delta regulator for + component
346  float REG[2]; REG[0] = deta*sqrt(2);
347  float netEC = this->netRHO*this->netRHO*2; // netEC/netRHO threshold
348 
349  static const __m128 _oo = _mm_set1_ps(1.e-16); // nusance parameter
350  static const __m128 _sm = _mm_set1_ps(-0.f); // sign mask: -0.f = 1 << 31
351  static const __m128 _En = _mm_set1_ps(En); // network threshold
352 
353  float aa,AA,Lo,Eo,Co,No,Ep,Lp,Np,Cp,Ec,Dc,To,Fo,Em,Lm,Rc,Mo,Mw,Eh;
354  float STAT,ee,EE,cc,ff,FF,Lw,Ew,Cw,Nw,Gn,rho,norm,ch,CH,Cr,Mp,N;
355 
356  size_t i,j,k,l,m,Vm,lm,V,V4,V44,id,K,M;
357  size_t L = this->index.size(); // total number of source locations
358  wavearray<short> skyMMcc(L);
359  short* mm = this->skyMask.data;
360  short* MM = skyMMcc.data;
361  bool skymaskcc = (skyMaskCC.size()==L);
362  int f_ = NIFO/4;
363 
364  float vvv[8];
365  float* v00[NIFO];
366  float* v90[NIFO];
367  float* pe[NIFO];
368  float* pa[NIFO];
369  float* pA[NIFO];
370  float *pd[NIFO], *pD[NIFO];
371  float *ps[NIFO], *pS[NIFO];
372  float *pn[NIFO], *pN[NIFO];
373  short* ml[NIFO];
374  double* FP[NIFO];
375  double* FX[NIFO];
376  double xx[NIFO];
377 
378  std::vector<float*> _vtd; // vectors of TD amplitudes
379  std::vector<float*> _vTD; // vectors of TD amplitudes
380  std::vector<float*> _eTD; // vectors of TD energies
381  std::vector<float*> _AVX; // vectors for network pixel statistics
382  std::vector<float*> _APN; // vectors for noise and antenna patterns
383  std::vector<float*> _DAT; // vectors for packet amplitudes
384  std::vector<float*> _SIG; // vectors for packet amplitudes
385  std::vector<float*> _NUL; // vectors for packet amplitudes
386  std::vector<float*> _TMP; // temp array for _avx_norm_ps() function
387 
388  for(i=0; i<NIFO; i++) {
389  if(i<nIFO) {
390  ml[i] = getifo(i)->index.data;
391  FP[i] = getifo(i)->fp.data;
392  FX[i] = getifo(i)->fx.data;
393  }
394  else {
395  ml[i] = getifo(0)->index.data;
396  FP[i] = getifo(0)->fp.data;
397  FX[i] = getifo(0)->fx.data;
398  }
399  }
400 
401  // allocate buffers
402  std::vector<int> pI; // buffer for pixel IDs
403  std::vector<int> pJ; // buffer for pixel index
404  wavearray<double> cid; // buffers for cluster ID
405  wavearray<double> cTo; // buffers for cluster time
406  wavearray<float> S_snr(NIFO); // energy SNR of signal
407  wavearray<float> D_snr(NIFO); // energy SNR of data time series
408  wavearray<float> N_snr(NIFO); // energy of null streams
409  netpixel* pix;
410  std::vector<int>* vint;
411  std::vector<int>* vtof;
412  netcluster* pwc = &this->wc_List[lag];
413 
414  size_t count = 0;
415  size_t tsize = 0;
416 
417  std::map<int,float> vLr; // resolution map
418 
419  // initialize parameters to manage big clusters
420  int precision = int(fabs(this->precision));
421  int csize = precision%65536; // get number of pixels threshold per level
422  int healpix = this->nSkyStat.getOrder(); // get healpix order of likelihood skymap
423  int order = (precision-csize)/65536; // get resampled order
424  wavearray<short> BB(L);BB=1; // index array for setting sky mask
425  bool bBB = false;
426  if(healpix && csize && order && order<healpix) {
427  skymap rsm(order); // resampled skymap
428  for(int l=0;l<rsm.size();l++) {
429  int m = this->nSkyStat.getSkyIndex(rsm.getTheta(l),rsm.getPhi(l));
430  BB[m]=0;
431  }
432  for(int l=0;l<L;l++) BB[l] = BB[l] ? 0 : 1;
433  }
434 
435 //+++++++++++++++++++++++++++++++++++++++
436 // loop over clusters
437 //+++++++++++++++++++++++++++++++++++++++
438 
439  cid = pwc->get((char*)"ID", 0,'S',0); // get cluster ID
440  cTo = pwc->get((char*)"time",0,'L',0); // get cluster time
441 
442  K = cid.size();
443  for(k=0; k<K; k++) { // loop over clusters
444  id = size_t(cid.data[k]+0.1);
445 
446  if(pwc->sCuts[id-1] != -2) continue; // skip rejected/processed clusters
447 
448  vint = &(pwc->cList[id-1]); // pixel list
449  vtof = &(pwc->nTofF[id-1]); // TofFlight configurations
450  V = vint->size();
451  if(!V) continue;
452 
453  pI = wdmMRA.getXTalk(pwc, id);
454  V = pI.size();
455  if(!V) continue;
456 
457  bBB = (V>this->wdmMRA.nRes*csize) ? true : false; // check big cluster size condition
458 
459  if(ID==id) {
460  this->nSensitivity = 0.;
461  this->nAlignment = 0.;
462  this->nNetIndex = 0.;
463  this->nDisbalance = 0.;
464  this->nLikelihood = 0.;
465  this->nNullEnergy = 0.;
466  this->nCorrEnergy = 0.;
467  this->nCorrelation = 0.;
468  this->nSkyStat = 0.;
469  this->nEllipticity = 0.;
470  this->nPolarisation = 0.;
471  this->nProbability = 0.;
472  }
473  this->nAntenaPrior = 0.;
474 
475  pix = pwc->getPixel(id,pI[0]);
476  tsize = pix->tdAmp[0].size();
477  if(!tsize || tsize&1) { // tsize%1 = 1/0 = power/amplitude
478  cout<<"network::likelihoodWP() error: wrong pixel TD data\n";
479  exit(1);
480  }
481 
482  tsize /= 2;
483 
484  if(!(V=pI.size())) continue;
485  V4 = V + (V%4 ? 4 - V%4 : 0);
486  V44 = V4 + 4;
487  pJ.clear();
488  for(j=0; j<V4; j++) pJ.push_back(0);
489 
490  float* ptmp; // allocate aligned arrays
491  if(_vtd.size()) _avx_free_ps(_vtd); // array for 00 amplitudes
492  if(_vTD.size()) _avx_free_ps(_vTD); // array for 90 amplitudes
493  if(_eTD.size()) _avx_free_ps(_eTD); // array for pixel energy
494  if(_APN.size()) _avx_free_ps(_APN); // container for noise rms and antenna patterns
495  if(_DAT.size()) _avx_free_ps(_DAT); // container for data packet amplitudes
496  if(_SIG.size()) _avx_free_ps(_SIG); // container for signal packet amplitudes
497  if(_NUL.size()) _avx_free_ps(_NUL); // container for null packet amplitudes
498  for(i=0; i<NIFO; i++) {
499  ptmp = (float*)_mm_malloc(tsize*V4*sizeof(float),32);
500  for(j=0; j<tsize*V4; j++) ptmp[j]=0; _vtd.push_back(ptmp); // array of aligned vectors
501  ptmp = (float*)_mm_malloc(tsize*V4*sizeof(float),32);
502  for(j=0; j<tsize*V4; j++) ptmp[j]=0; _vTD.push_back(ptmp); // array of aligned vectors
503  ptmp = (float*)_mm_malloc(tsize*V4*sizeof(float),32);
504  for(j=0; j<tsize*V4; j++) ptmp[j]=0; _eTD.push_back(ptmp); // array of aligned vectors
505  ptmp = (float*)_mm_malloc((V4*3+16)*sizeof(float),32);
506  for(j=0; j<(V4*3+16); j++) ptmp[j]=0; _APN.push_back(ptmp); // concatenated arrays {f+}{fx}{rms}{a+,A+,ax,AX}
507  ptmp = (float*)_mm_malloc((V4*3+8)*sizeof(float),32);
508  for(j=0; j<(V4*3+8); j++) ptmp[j]=0; _DAT.push_back(ptmp); // concatenated arrays {amp}{AMP}{norm}{n,N,c,s}
509  ptmp = (float*)_mm_malloc((V4*3+8)*sizeof(float),32);
510  for(j=0; j<(V4*3+8); j++) ptmp[j]=0; _SIG.push_back(ptmp); // concatenated arrays {amp}{AMP}{norm}{n,N,c,s}
511  ptmp = (float*)_mm_malloc((V4*3+8)*sizeof(float),32);
512  for(j=0; j<(V4*3+8); j++) ptmp[j]=0; _NUL.push_back(ptmp); // concatenated arrays {amp}{AMP}{norm}{n,N,c,s}
513  }
514 
515  // data arrays for polar coordinates storage : [0,1] = [radius,angle]
516  for(i=0;i<2;i++) {
517  this->p00_POL[i].resize(V4); this->p00_POL[i]=0.;
518  this->p90_POL[i].resize(V4); this->p90_POL[i]=0.;
519  this->r00_POL[i].resize(V4); this->r00_POL[i]=0.;
520  this->r90_POL[i].resize(V4); this->r90_POL[i]=0.;
521  }
522 
523  for(i=0; i<NIFO; i++) { // set up zero delay and packet pointers
524  pa[i] = _vtd[i] + (tsize/2)*V4;
525  pA[i] = _vTD[i] + (tsize/2)*V4;
526  pe[i] = _eTD[i] + (tsize/2)*V4;
527  pd[i] = _DAT[i]; pD[i] = _DAT[i]+V4;
528  ps[i] = _SIG[i]; pS[i] = _SIG[i]+V4;
529  pn[i] = _NUL[i]; pN[i] = _NUL[i]+V4;
530  }
531 
532  this->a_00.resize(NIFO*V44); this->a_00=0.; // array for pixel amplitudes in sky loop
533  this->a_90.resize(NIFO*V44); this->a_90=0.; // array for pixel amplitudes in sky loop
534  this->rNRG.resize(V4); this->rNRG=0.;
535  this->pNRG.resize(V4); this->pNRG=0.;
536 
537  __m128* _aa = (__m128*) this->a_00.data; // set pointer to 00 array
538  __m128* _AA = (__m128*) this->a_90.data; // set pointer to 90 array
539 
540  if(_AVX.size()) _avx_free_ps(_AVX);
541  float* p_et = (float*)_mm_malloc(V4*sizeof(float),32); // 0
542  for(j=0; j<V4; j++) p_et[j]=0; _AVX.push_back(p_et);
543  float* pMSK = (float*)_mm_malloc(V44*sizeof(float),32); // 1 - pixel mask
544  for(j=0; j<V44; j++) pMSK[j]=0; _AVX.push_back(pMSK); pMSK[V4]=nIFO;
545  float* p_fp = (float*)_mm_malloc(V44*sizeof(float),32); // 2- |f+|^2 (0:V4), +norm (V4:V4+4)
546  for(j=0; j<V44; j++) p_fp[j]=0; _AVX.push_back(p_fp);
547  float* p_fx = (float*)_mm_malloc(V44*sizeof(float),32); // 3- |fx|^2 (0:V4), xnorm (V4:V4+4)
548  for(j=0; j<V44; j++) p_fx[j]=0; _AVX.push_back(p_fx);
549  float* p_si = (float*)_mm_malloc(V4*sizeof(float),32); // 4
550  for(j=0; j<V4; j++) p_si[j]=0; _AVX.push_back(p_si);
551  float* p_co = (float*)_mm_malloc(V4*sizeof(float),32); // 5
552  for(j=0; j<V4; j++) p_co[j]=0; _AVX.push_back(p_co);
553  float* p_uu = (float*)_mm_malloc((V4+16)*sizeof(float),32); // 6 - 00+ unit vector(0:V4), norm(V4), cos(V4+4)
554  for(j=0; j<V4+16; j++) p_uu[j]=0; _AVX.push_back(p_uu);
555  float* p_UU = (float*)_mm_malloc((V4+16)*sizeof(float),32); // 7 - 90+ unit vector(0:V4), norm(V4), sin(V4+4)
556  for(j=0; j<V4+16; j++) p_UU[j]=0; _AVX.push_back(p_UU);
557  float* p_vv = (float*)_mm_malloc((V4+16)*sizeof(float),32); // 8- 00x unit vector(0:V4), norm(V4), cos(V4+4)
558  for(j=0; j<V4+16; j++) p_vv[j]=0; _AVX.push_back(p_vv);
559  float* p_VV = (float*)_mm_malloc((V4+16)*sizeof(float),32); // 9- 90x unit vector(0:V4), norm(V4), sin(V4+4)
560  for(j=0; j<V4+16; j++) p_VV[j]=0; _AVX.push_back(p_VV);
561  float* p_au = (float*)_mm_malloc(V4*sizeof(float),32); // 10
562  for(j=0; j<V4; j++) p_au[j]=0; _AVX.push_back(p_au);
563  float* p_AU = (float*)_mm_malloc(V4*sizeof(float),32); // 11
564  for(j=0; j<V4; j++) p_AU[j]=0; _AVX.push_back(p_AU);
565  float* p_av = (float*)_mm_malloc(V4*sizeof(float),32); // 12
566  for(j=0; j<V4; j++) p_av[j]=0; _AVX.push_back(p_av);
567  float* p_AV = (float*)_mm_malloc(V4*sizeof(float),32); // 13
568  for(j=0; j<V4; j++) p_AV[j]=0; _AVX.push_back(p_AV);
569  float* p_uv = (float*)_mm_malloc(V4*4*sizeof(float),32); // 14 special array for GW norm calculation
570  for(j=0; j<V4*4; j++) p_uv[j]=0; _AVX.push_back(p_uv);
571  float* p_ee = (float*)_mm_malloc(V4*sizeof(float),32); // 15 + energy array
572  for(j=0; j<V4; j++) p_ee[j]=0; _AVX.push_back(p_ee);
573  float* p_EE = (float*)_mm_malloc(V4*sizeof(float),32); // 16 x energy array
574  for(j=0; j<V4; j++) p_EE[j]=0; _AVX.push_back(p_EE);
575  float* pTMP=(float*)_mm_malloc(V4*4*NIFO*sizeof(float),32); // 17 temporary array for _avx_norm_ps()
576  for(j=0; j<V4*4*NIFO; j++) pTMP[j]=0; _AVX.push_back(pTMP);
577  float* p_ni = (float*)_mm_malloc(V4*sizeof(float),32); // 18 + network index
578  for(j=0; j<V4; j++) p_ni[j]=0; _AVX.push_back(p_ni);
579  float* p_ec = (float*)_mm_malloc(V4*sizeof(float),32); // 19 + coherent energy
580  for(j=0; j<V4; j++) p_ec[j]=0; _AVX.push_back(p_ec);
581  float* p_gn = (float*)_mm_malloc(V4*sizeof(float),32); // 20 + Gaussian noise correction
582  for(j=0; j<V4; j++) p_gn[j]=0; _AVX.push_back(p_gn);
583  float* p_ed = (float*)_mm_malloc(V4*sizeof(float),32); // 21 + energy disbalance
584  for(j=0; j<V4; j++) p_ed[j]=0; _AVX.push_back(p_ed);
585  float* p_rn = (float*)_mm_malloc(V4*sizeof(float),32); // 22 + sattelite noise in TF domain
586  for(j=0; j<V4; j++) p_rn[j]=0; _AVX.push_back(p_rn);
587 
588 
589  this->pList.clear();
590  for(j=0; j<V; j++) { // loop over selected pixels
591  pix = pwc->getPixel(id,pI[j]);
592  this->pList.push_back(pix); // store pixel pointers for MRA
593 
594  double rms = 0.;
595  for(i=0; i<nIFO; i++) {
596  xx[i] = 1./pix->data[i].noiserms;
597  rms += xx[i]*xx[i]; // total inverse variance
598  }
599 
600  rms = sqrt(rms);
601  for(i=0; i<nIFO; i++) {
602  _APN[i][V4*2+j] =(float)xx[i]/rms; // noise array for AVX processing
603  for(l=0; l<tsize; l++) {
604  aa = pix->tdAmp[i].data[l]; // copy TD 00 data
605  AA = pix->tdAmp[i].data[l+tsize]; // copy TD 90 data
606  _vtd[i][l*V4+j] = aa; // copy 00 data
607  _vTD[i][l*V4+j] = AA; // copy 90 data
608  _eTD[i][l*V4+j] = aa*aa+AA*AA; // copy power
609  }
610  }
611  }
612 
613 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
614 // sky loop
615 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
616 
617  __m256 _CC;
618  size_t lb = 0;
619  size_t le = L-1;
620  double sky = 0.;
621  STAT=-1.e12; lm=0; Em=Lm=ff=FF=0;
622 
623  skyMMcc = 0;
624  for(l=lb; l<=le; l++) { // loop over sky locations
625  if(!mm[l]) continue; // skip delay configurations
626  if(bBB && !BB[l]) continue; // skip delay configurations : big clusters
627 
628  if(skymaskcc) { // transform l into celestial coordinates lc
629  skymap* sm = &(this->nSkyStat);
630  double gT = cTo.data[k]+pwc->start; // trigger gps time
631  double RA = sm->phi2RA(sm->getPhi(l),gT); // phi -> RA
632  int lc=this->getIndex(sm->getTheta(l),RA); // get sky index in celestial coordinates
633  if (!skyMaskCC.data[lc]) continue;
634  }
635  MM[l] = 1; FF += 1; // set final skymap
636  aa = _avx_dpf_ps(FP,FX,l,_APN,_AVX,V4); // calculate DPF f+,fx and their norms
637  if(aa > gama) ff += 1;
638  }
639  REG[1] = (FF*FF/(ff*ff+1.e-9)-1)*En; // setup x regulator
640 
641  optsky:
642 
643  AA = 0.; // initialize sky statistic
644  for(l=lb; l<=le; l++) { // loop over sky locations
645  skyProb.data[l] = -1.e12;
646  if(!MM[l]) continue; // apply sky mask
647  pnt_(v00, pa, ml, (int)l, (int)V4); // pointers to first pixel 00 data
648  pnt_(v90, pA, ml, (int)l, (int)V4); // pointers to first pixel 90 data
649  Eo=_avx_loadata_ps(v00,v90,pd,pD,En,_AVX,V4); // calculate data stats and store in _AVX
650 
651  _avx_dpf_ps(FP,FX,l,_APN,_AVX,V4); // calculate DPF f+,fx and their norms
652  _avx_cpf_ps(v00,v90,ps,pS,V4); // copy data for GW reconstruction
653  Mo = _avx_GW_ps(ps,pS,_APN,REG,_AVX,V4); // gw strain packet, return number of selected pixels
654 
655  if(lb==le) _avx_saveGW_ps(ps,pS,V); // save gw strain packet into a_00,a_90
656 
657  Lo = _avx_ort_ps(ps,pS,_AVX,V4); // othogonalize signal amplitudes
658  _CC = _avx_stat_ps(pd,pD,ps,pS,_AVX,V4); // coherent statistics
659  _mm256_storeu_ps(vvv,_CC); // extract coherent statistics
660  Cr = vvv[0]; // cc statistics
661  Ec = vvv[1]; // signal coherent energy in TF domain
662  Mp = vvv[2]; // signal energy disbalance in TF domain
663  No = vvv[3]; // total noise in TF domain
664  CH = No/(nIFO*Mo+sqrt(Mo)); // chi2 in TF domain
665  cc = CH>1 ? CH : 1; // noise correction factor in TF domain
666  Co = Ec/(Ec+No*cc-Mo*(nIFO-1)); // network correlation coefficient in TF
667 
668  if(Cr<netCC) continue;
669 
670  aa = Eo>0. ? Eo-No : 0.; // likelihood skystat
671  AA = aa*Co; // x-correlation skystat
672  skyProb.data[l] = this->delta<0 ? aa : AA;
673 
674  ff = FF = ee = 0.;
675  for(j=0; j<V; j++) {
676  if(pMSK[j]<=0) continue;
677  ee += p_et[j]; // total energy
678  ff += p_fp[j]*p_et[j]; // |f+|^2
679  FF += p_fx[j]*p_et[j]; // |fx|^2
680  }
681  ff = ee>0. ? ff/ee : 0.;
682  FF = ee>0. ? FF/ee : 0.;
683  this->nAntenaPrior.set(l, sqrt(ff+FF));
684 
685  if(ID==id) {
686  this->nSensitivity.set(l, sqrt(ff+FF));
687  this->nAlignment.set(l, ff>0 ? sqrt(FF/ff):0);
688  this->nLikelihood.set(l, Eo-No);
689  this->nNullEnergy.set(l, No);
690  this->nCorrEnergy.set(l, Ec);
691  this->nCorrelation.set(l,Co);
692  this->nSkyStat.set(l,AA);
693  this->nProbability.set(l, skyProb.data[l]);
694  this->nDisbalance.set(l,CH);
695  this->nNetIndex.set(l,cc);
696  this->nEllipticity.set(l,Cr);
697  this->nPolarisation.set(l,Mp);
698  }
699 
700  if(AA>=STAT) {STAT=AA; lm=l; Em=Eo-Eh;}
701  if(skyProb.data[l]>sky) sky=skyProb.data[l]; // find max of skyloc stat
702 
703  if(lb!=le) continue;
704 
705  Eo = _avx_packet_ps(pd,pD,_AVX,V4); // get data packet
706  Lo = _avx_packet_ps(ps,pS,_AVX,V4); // get signal packet
707  D_snr = _avx_norm_ps(pd,pD,_AVX,V4); // data packet energy snr
708  S_snr = _avx_norm_ps(pS,pD,p_ec,V4); // set signal norms, return signal SNR
709  Ep = D_snr[0];
710  Lp = S_snr[0];
711 
712  _CC = _avx_noise_ps(pS,pD,_AVX,V4); // get G-noise correction
713  _mm256_storeu_ps(vvv,_CC); // extract coherent statistics
714  Gn = vvv[0]; // gaussian noise correction
715  Ec = vvv[1]; // core coherent energy in TF domain
716  Dc = vvv[2]; // signal-core coherent energy in TF domain
717  Rc = vvv[3]; // EC normalization
718  Eh = vvv[4]; // satellite energy in TF domain
719 
720  N = _avx_setAMP_ps(pd,pD,_AVX,V4)-1; // set data packet amplitudes
721 
722  _avx_setAMP_ps(ps,pS,_AVX,V4); // set signal packet amplitudes
723  _avx_loadNULL_ps(pn,pN,pd,pD,ps,pS,V4); // load noise TF domain amplitudes
724  D_snr = _avx_norm_ps(pd,pD,_AVX,-V4); // data packet energy snr
725  N_snr = _avx_norm_ps(pn,pN,_AVX,-V4); // noise packet energy snr
726  Np = N_snr.data[0]; // time-domain NULL
727  Em = D_snr.data[0]; // time domain energy
728  Lm = Em-Np-Gn; // time domain signal energy
729  norm = Em>0 ? (Eo-Eh)/Em : 1.e9; // norm
730  if(norm<1) norm = 1; // corrected norm
731  Ec /= norm; // core coherent energy in time domain
732  Dc /= norm; // signal-core coherent energy in time domain
733  ch = (Np+Gn)/(N*nIFO); // chi2
734  cc = ch>1 ? ch : 1; // rho correction factor
735  rho = Ec>0 ? sqrt(Ec*Rc/2.) : 0.; // cWB detection stat
736 
737  // save projection on network plane in polar coordinates
738  // The Dual Stream Transform (DSP) is applied to v00,v90
739  _avx_pol_ps(v00,v90,p00_POL,p90_POL,_APN,_AVX,V4);
740  // save DSP components in polar coordinates
741  _avx_pol_ps(v00,v90,r00_POL,r90_POL,_APN,_AVX,V4);
742  }
743 
744  if(le-lb) {lb=le=lm; goto optsky;} // process all pixels at opt sky location
745 
746  if(Lm<=0.||(Eo-Eh)<=0.||Ec*Rc/cc<netEC||N<1) {
747  pwc->sCuts[id-1]=1; count=0; // reject cluster
748  pwc->clean(id); continue;
749  }
750 
751 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
752 // detection statistics at selected sky location
753 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
754 
755  vint = &(pwc->cList[id-1]); // pixel list
756  for(j=0; j<vint->size(); j++) { // initialization for all pixels
757  pix = pwc->getPixel(id,j);
758  pix->core = false;
759  pix->likelihood = 0.;
760  pix->null = 0;
761  }
762 
763 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
764 // detection statistics at selected sky location
765 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
766  M = Mw = 0; // add denoised pixels
767  for(j=0; j<V; j++) { // loop over pixels
768  pix = pwc->getPixel(id,pI[j]);
769  if(pMSK[j]>0) { // Mo - EP pixels: stored in size[0]
770  pix->core = true;
771  pix->likelihood = -(p_ee[j]+p_EE[j])/2; // negative total pixel energy
772  }
773 
774  for(i=0; i<nIFO; i++) {
775  pix->setdata(double(pd[i][j]),'W',i); // 00 whitened
776  pix->setdata(double(pD[i][j]),'U',i); // 90 whitened
777  pix->setdata(double(ps[i][j]),'S',i); // 00 reconstructed whitened response
778  pix->setdata(double(pS[i][j]),'P',i); // 90 reconstructed whitened response
779  }
780  }
781 
782  for(j=0; j<V; j++) { // loop over pixels
783  pix = pwc->getPixel(id,pI[j]);
784  if(!pix->core) continue;
785  if(p_gn[j]<=0) continue; // skip satellites
786  Mw += 1.; // event size stored in size[1]
787  for(k=0; k<V; k++) { // loop over xtalk components
788  netpixel* xpix = pwc->getPixel(id,pI[k]);
789  struct xtalk xt = wdmMRA.getXTalk(pix->layers, pix->time, xpix->layers, xpix->time);
790  if(!xpix->core || p_gn[k]<=0 || xt.CC[0]>2) continue;
791  for(i=0; i<nIFO; i++) {
792  pix->null += xt.CC[0]*pn[i][j]*pn[i][k];
793  pix->null += xt.CC[1]*pn[i][j]*pN[i][k];
794  pix->null += xt.CC[2]*pN[i][j]*pn[i][k];
795  pix->null += xt.CC[3]*pN[i][j]*pN[i][k];
796  }
797  }
798 
799  if(p_ec[j]<=0) continue; // skip incoherent pixels
800  M += 1; // M - signal size: stored in volume[1]
801  pix->likelihood = 0; // total pixel energy
802  for(k=0; k<V; k++) { // loop over xtalk components
803  netpixel* xpix = pwc->getPixel(id,pI[k]);
804  struct xtalk xt = wdmMRA.getXTalk(pix->layers, pix->time, xpix->layers, xpix->time);
805  if(!xpix->core || p_ec[k]<=0 || xt.CC[0]>2) continue;
806  for(i=0; i<nIFO; i++) {
807  pix->likelihood += xt.CC[0]*ps[i][j]*ps[i][k];
808  pix->likelihood += xt.CC[1]*ps[i][j]*pS[i][k];
809  pix->likelihood += xt.CC[2]*pS[i][j]*ps[i][k];
810  pix->likelihood += xt.CC[3]*pS[i][j]*pS[i][k];
811  }
812  }
813  }
814 
815  // subnetwork statistic
816  double Emax = 0;
817  double Nmax = 0;
818  for(j=1; j<=nIFO; j++) { // loop over detectors
819  if(S_snr[j]>Emax) Emax=S_snr[j]; // detector with max energy
820  }
821  double Esub = S_snr.data[0]-Emax;
822  Esub = Esub*(1+2*Rc*Esub/Emax);
823  Nmax = Gn+Np-N*(nIFO-1);
824 
825  //if(hist) hist->Fill(pwc->cData[id-1].skycc,pwc->cData[id-1].netcc);
826 
827 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
828 // fill in detection statistics, prepare output data
829 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
830 
831 // fill in backward delay configuration
832 
833  vtof->clear();
834  NETX (vtof->push_back(ml[0][lm]); ,
835  vtof->push_back(ml[1][lm]); ,
836  vtof->push_back(ml[2][lm]); ,
837  vtof->push_back(ml[3][lm]); ,
838  vtof->push_back(ml[4][lm]); ,
839  vtof->push_back(ml[5][lm]); ,
840  vtof->push_back(ml[6][lm]); ,
841  vtof->push_back(ml[7][lm]); )
842 
843  // need to fix a problem below
844  if((wfsave)||(mdcListSize() && !lag)) { // if wfsave=false only simulated wf are saved
845  if(this->getMRAwave(id,lag,'S',0,true)) { // reconstruct whitened shifted pd->waveForm
846  detector* pd;
847  for(i=0; i<nIFO; i++) { // loop over detectors
848  pd = this->getifo(i);
849  pd->RWFID.push_back(id); // save cluster ID
851  *wf = pd->waveForm;
852  wf->start(pwc->start+pd->waveForm.start());
853  pd->RWFP.push_back(wf);
854  }
855  }
856  if(this->getMRAwave(id,lag,'s',0,true)) { // reconstruct strain shifted pd->waveForm
857  detector* pd;
858  for(i=0; i<nIFO; i++) { // loop over detectors
859  pd = this->getifo(i);
860  pd->RWFID.push_back(-id); // save cluster -ID
862  *wf = pd->waveForm;
863  wf->start(pwc->start+pd->waveForm.start());
864  pd->RWFP.push_back(wf);
865  }
866  }
867  }
868 
869  Lw = Ew = To = Fo = Nw = ee = norm = 0.;
870  for(i=0; i<nIFO; i++) {
871  detector* d = this->getifo(i);
872  d->sSNR = d->xSNR = d->null = d->enrg = 0.;
873  }
874 
875  this->getMRAwave(id,lag,'W',0);
876  this->getMRAwave(id,lag,'S',0);
877  for(i=0; i<nIFO; i++) {
878  detector* d = this->getifo(i);
879  d->waveNull = d->waveBand;
880  d->waveNull-= d->waveForm;
881  float sSNR = d->get_SS();
882  float xSNR = d->get_XS();
883  float null = d->get_NN();
884  float enrg = d->get_XX();
885  d->sSNR += sSNR;
886  d->xSNR += xSNR;
887  d->null += null;
888  d->enrg += enrg;
889  To += sSNR*d->getWFtime();
890  Fo += sSNR*d->getWFfreq();
891  Lw += sSNR;
892  Ew += enrg;
893  Nw += null;
894  }
895  To /= Lw; Fo /= Lw;
896  ch = (Nw+Gn)/(N*nIFO); // chi2
897  cc = ch>1 ? 1+(ch-1)*2*(1-Rc) : 1; // Cr correction factor
898  Cr = Ec*Rc/(Ec*Rc+(Dc+Nw+Gn)*cc-N*(nIFO-1)); // reduced network correlation coefficient
899  cc = ch>1 ? ch : 1; // rho correction factor
900  Cp = Ec*Rc/(Ec*Rc+(Dc+Nw+Gn)-N*(nIFO-1)); // network correlation coefficient
901  norm = (Eo-Eh)/Ew;
902 
903  pwc->cData[id-1].norm = norm*2; // packet norm (saved in norm)
904  pwc->cData[id-1].skyStat = 0; //
905  pwc->cData[id-1].skySize = Mw; // event size in the skyloop (size[1])
906  pwc->cData[id-1].netcc = Cp; // network cc (netcc[0])
907  pwc->cData[id-1].skycc = Cr; // reduced network cc (netcc[1])
908  pwc->cData[id-1].subnet = Esub/(Esub+Nmax); // sub-network statistic (netcc[2])
909  pwc->cData[id-1].SUBNET = Co; // sky cc (netcc[3])
910  pwc->cData[id-1].likenet = Lw; // waveform likelihood
911  pwc->cData[id-1].netED = Nw+Gn+Dc-N*nIFO; // residual NULL energy (neted[0])
912  pwc->cData[id-1].netnull = Nw+Gn; // packet NULL (neted[1])
913  pwc->cData[id-1].energy = Ew; // energy in time domain (neted[2])
914  pwc->cData[id-1].likesky = Em; // energy in the loop (neted[3])
915  pwc->cData[id-1].enrgsky = Eo; // TF-domain all-res energy (neted[4])
916  pwc->cData[id-1].netecor = Ec; // packet (signal) coherent energy
917  pwc->cData[id-1].normcor = Ec*Rc; // normalized coherent energy
918  pwc->cData[id-1].netRHO = rho/sqrt(cc); // reguced rho - stored in rho[0]
919  pwc->cData[id-1].netrho = rho; // chirp rho - stored in rho[1]
920  pwc->cData[id-1].cTime = To;
921  pwc->cData[id-1].cFreq = Fo;
922  pwc->cData[id-1].theta = nLikelihood.getTheta(lm);
923  pwc->cData[id-1].phi = nLikelihood.getPhi(lm);
924  pwc->cData[id-1].gNET = sqrt(ff+FF);
925  pwc->cData[id-1].aNET = sqrt(FF/ff);
926  pwc->cData[id-1].iNET = 0; // degrees of freedom
927  pwc->cData[id-1].nDoF = N; // degrees of freedom
928  pwc->cData[id-1].skyChi2 = CH;
929  pwc->cData[id-1].Gnoise = Gn;
930  pwc->cData[id-1].iota = 0;
931  pwc->cData[id-1].psi = 0;
932  pwc->cData[id-1].ellipticity = 0.;
933 
934  cc = pwc->cData[id-1].netcc;
935  if(hist) {
936  printf("rho=%4.2f|%4.2f cc: %5.3f|%5.3f|%5.3f subnet=%4.3f|%4.3f \n",
937  rho,rho*sqrt(Cp),Co,Cp,Cr,pwc->cData[id-1].subnet,pwc->cData[id-1].SUBNET);
938  printf(" L: %5.1f|%5.1f|%5.1f E: %5.1f|%5.1f|%5.1f|%5.1f N: %4.1f|%4.1f|%4.1f|%4.1f|%4.1f \n",
939  Lw,Lp,Lo,Ew,Ep,Eo,Em,Nw,Np,Rc,Eh,No);
940  printf("id|lm %3d|%6d Vm|m=%3d|%3d|%3d|%3d T|F: %6.3f|%4.1f (t,p)=(%4.1f|%4.1f) \n",
941  int(id),int(lm),int(V),int(Mo),int(Mw),int(M),To,Fo,nLikelihood.getTheta(lm),nLikelihood.getPhi(lm));
942  cout<<" L: |"; for(i=1; i<nIFO+1; i++) {printf("%5.1f|",S_snr[i]);}
943  cout<<" E: |"; for(i=1; i<nIFO+1; i++) {printf("%5.1f|",D_snr[i]);}
944  cout<<" N: |"; for(i=1; i<nIFO+1; i++) {printf("%5.1f|",N_snr[i]);}
945  cout<<endl<<" dof|G|G+R "; printf("%5.1f|%5.1f|%5.1f r[1]=%4.1f",N,Gn,Nw+Gn,REG[1]);
946  printf(" norm=%3.1f chi2 %3.2f|%3.2f Rc=%3.2f, Dc=%4.1f\n",norm,ch,CH,Rc,Dc);
947  // cout<<" r1="<<REG[1]<<" norm="<<norm<<" chi2="<<ch<<"|"<<CH<<" Rc="<<Rc<<" Dc="<<Dc<<endl;
948  //hist->Fill(pwc->cData[id-1].subnet,pwc->cData[id-1].SUBNET);
949  }
950  count++;
951 
952 // calculation of error regions
953 
954  pwc->p_Ind[id-1].push_back(Mo);
955  double T = To+pwc->start; // trigger time
956  std::vector<float> sArea;
957  pwc->sArea.push_back(sArea);
958  pwc->p_Map.push_back(sArea);
959 
960  double var = norm*Rc*sqrt(Mo)*(1+fabs(1-CH));
961 
962  if(iID<=0 || ID==id) {
963  getSkyArea(id,lag,T,var); // calculate error regions
964  }
965 // calculation of chirp mass
966 
967  pwc->cData[id-1].mchirp = 0;
968  pwc->cData[id-1].mchirperr = 0;
969  pwc->cData[id-1].tmrgr = 0;
970  pwc->cData[id-1].tmrgrerr = 0;
971  pwc->cData[id-1].chi2chirp = 0;
972 
973  if(m_chirp) { // work only for MRA
974  ee = pwc->mchirp(id);
975  cc = Ec/(fabs(Ec)+ee); // chirp cc
976  printf("mchirp : %d %g %.2e %.3f %.3f %.3f %.3f \n\n",
977  int(id),cc,pwc->cData[id-1].mchirp,
978  pwc->cData[id-1].mchirperr, pwc->cData[id-1].tmrgr,
979  pwc->cData[id-1].tmrgrerr, pwc->cData[id-1].chi2chirp);
980  }
981 
982  if(ID==id && !EFEC) {
983  this->nSensitivity.gps = T;
984  this->nAlignment.gps = T;
985  this->nDisbalance.gps = T;
986  this->nLikelihood.gps = T;
987  this->nNullEnergy.gps = T;
988  this->nCorrEnergy.gps = T;
989  this->nCorrelation.gps = T;
990  this->nSkyStat.gps = T;
991  this->nEllipticity.gps = T;
992  this->nPolarisation.gps= T;
993  this->nNetIndex.gps = T;
994  }
995 
996  pwc->sCuts[id-1] = -1;
997  pwc->clean(id);
998  } // end of loop over clusters
999 
1000  if(_vtd.size()) _avx_free_ps(_vtd);
1001  if(_vTD.size()) _avx_free_ps(_vTD);
1002  if(_eTD.size()) _avx_free_ps(_eTD);
1003  if(_AVX.size()) _avx_free_ps(_AVX);
1004  if(_APN.size()) _avx_free_ps(_APN); // container for antenna patterns and noise RMS
1005  if(_DAT.size()) _avx_free_ps(_DAT); // container for data packet amplitudes
1006  if(_SIG.size()) _avx_free_ps(_SIG); // container for signal packet amplitudes
1007  if(_NUL.size()) _avx_free_ps(_NUL); // container for null packet amplitudes
1008 
1009  return count;
1010 }
1011 
1012 
1013 
1014 long network::subNetCut(int lag, float subnet, float subcut, TH2F* hist)
1015 {
1016 // sub-network cut with dsp regulator
1017 // lag: lag index
1018 // subnet: sub network threshold
1019 // subcut: sub network threshold in the skyloop
1020 // hist: diagnostic histogram
1021 // return number of processed pixels
1022 
1023  if(!this->wc_List[lag].size()) return 0;
1024 
1025  size_t nIFO = this->ifoList.size();
1026 
1027  if(nIFO>NIFO) {
1028  cout<<"network::subNetCut(): invalid network.\n";
1029  exit(0);
1030  }
1031 
1032  float En = 2*acor*acor*nIFO; // network energy threshold in the sky loop
1033  float Es = 2*e2or; // subnet energy threshold in the sky loop
1034 
1035  subnet = fabs(subnet); // sub network threshold
1036  subcut = fabs(subcut); // sub network threshold in the skyloop
1037 
1038  __m128 _En = _mm_set1_ps(En);
1039  __m128 _Es = _mm_set1_ps(Es);
1040  __m128 _oo = _mm_set1_ps(1.e-12);
1041  __m128 _0 = _mm_set1_ps(0.);
1042  __m128 _05 = _mm_set1_ps(0.5);
1043  __m128 _1 = _mm_set1_ps(1.);
1044  __m128* _pe[NIFO];
1045 
1046  int f_ = NIFO/4;
1047  int l,lm,Vm;
1048  float Lm,Em,Am,Lo,Eo,Co,Lr,Er,ee,em,To;
1049  float cc,aa,AA,rHo,stat,Ls,Ln,EE;
1050 
1051  size_t i,j,k,m,V,V4,id,K,M;
1052  int Lsky = int(this->index.size()); // total number of source locations
1053  short* mm = this->skyMask.data;
1054 
1055  float vvv[NIFO] _ALIGNED;
1056  float* v00[NIFO] _ALIGNED;
1057  float* v90[NIFO] _ALIGNED;
1058  float* pe[NIFO] _ALIGNED;
1059  float* pa[NIFO] _ALIGNED;
1060  float* pA[NIFO] _ALIGNED;
1061  short* ml[NIFO] _ALIGNED;
1062  double* FP[NIFO] _ALIGNED;
1063  double* FX[NIFO] _ALIGNED;
1064  double xx[NIFO] _ALIGNED;
1065 
1066  for(i=0; i<NIFO; i++) {
1067  if(i<nIFO) {
1068  ml[i] = getifo(i)->index.data;
1069  FP[i] = getifo(i)->fp.data;
1070  FX[i] = getifo(i)->fx.data;
1071  }
1072  else {
1073  ml[i] = getifo(0)->index.data;
1074  FP[i] = getifo(0)->fp.data;
1075  FX[i] = getifo(0)->fx.data;
1076  }
1077  }
1078 
1079  // allocate buffers
1080  std::vector<int> pI; // buffer for pixel IDs
1081  wavearray<double> cid; // buffers for cluster ID
1082  wavearray<double> cTo; // buffers for cluster time
1083  netpixel* pix;
1084  std::vector<int>* vint;
1085  netcluster* pwc = &this->wc_List[lag];
1086 
1087  size_t count = 0;
1088  size_t tsize = 0;
1089 
1090 //+++++++++++++++++++++++++++++++++++++++
1091 // loop over clusters
1092 //+++++++++++++++++++++++++++++++++++++++
1093 
1094  cid = pwc->get((char*)"ID", 0,'S',0); // get cluster ID
1095  cTo = pwc->get((char*)"time",0,'L',0); // get cluster time
1096 
1097  K = cid.size();
1098  for(k=0; k<K; k++) { // loop over clusters
1099  id = size_t(cid.data[k]+0.1);
1100  if(pwc->sCuts[id-1] != -2) continue; // skip rejected/processed clusters
1101  vint = &(pwc->cList[id-1]); // pixel list
1102  V = vint->size(); // pixel list size
1103  if(!V) continue;
1104 
1105  pI = wdmMRA.getXTalk(pwc, id);
1106 
1107  V = pI.size(); // number of loaded pixels
1108  if(!V) continue;
1109 
1110  pix = pwc->getPixel(id,pI[0]);
1111  tsize = pix->tdAmp[0].size();
1112  if(!tsize || tsize&1) { // tsize%1 = 1/0 = power/amplitude
1113  cout<<"network::subNetCut() error: wrong pixel TD data\n";
1114  exit(1);
1115  }
1116  tsize /= 2;
1117  V4 = V + (V%4 ? 4 - V%4 : 0);
1118 
1119  //cout<<En<<" "<<Es<<" "<<lag<<" "<<id<<" "<<V4<<" "<<" "<<tsize<<endl;
1120 
1121  std::vector<wavearray<float> > vtd; // vectors of TD amplitudes
1122  std::vector<wavearray<float> > vTD; // vectors of TD amplitudes
1123  std::vector<wavearray<float> > eTD; // vectors of TD energies
1124 
1125  wavearray<float> tmp(tsize*V4); tmp=0; // aligned array for TD amplitudes
1126  wavearray<float> fp(NIFO*V4); fp=0; // aligned array for + antenna pattern
1127  wavearray<float> fx(NIFO*V4); fx=0; // aligned array for x antenna pattern
1128  wavearray<float> nr(NIFO*V4); nr=0; // aligned array for inverse rms
1129  wavearray<float> Fp(NIFO*V4); Fp=0; // aligned array for pattern
1130  wavearray<float> Fx(NIFO*V4); Fx=0; // aligned array for patterns
1131  wavearray<float> am(NIFO*V4); am=0; // aligned array for TD amplitudes
1132  wavearray<float> AM(NIFO*V4); AM=0; // aligned array for TD amplitudes
1133  wavearray<float> bb(NIFO*V4); bb=0; // temporary array for MRA amplitudes
1134  wavearray<float> BB(NIFO*V4); BB=0; // temporary array for MRA amplitudes
1135  wavearray<float> xi(NIFO*V4); xi=0; // 00 array for reconctructed responses
1136  wavearray<float> XI(NIFO*V4); XI=0; // 90 array for reconstructed responses
1137  wavearray<float> ww(NIFO*V4); ww=0; // 00 array for phase-shifted data vectors
1138  wavearray<float> WW(NIFO*V4); WW=0; // 90 array for phase-shifted data vectors
1139  wavearray<float> u4(NIFO*4); u4=0; // temp array
1140  wavearray<float> U4(NIFO*4); U4=0; // temp array
1141 
1142  __m128* _Fp = (__m128*) Fp.data;
1143  __m128* _Fx = (__m128*) Fx.data;
1144  __m128* _am = (__m128*) am.data;
1145  __m128* _AM = (__m128*) AM.data;
1146  __m128* _xi = (__m128*) xi.data;
1147  __m128* _XI = (__m128*) XI.data;
1148  __m128* _fp = (__m128*) fp.data;
1149  __m128* _fx = (__m128*) fx.data;
1150  __m128* _nr = (__m128*) nr.data;
1151  __m128* _ww = (__m128*) ww.data;
1152  __m128* _WW = (__m128*) WW.data;
1153  __m128* _bb = (__m128*) bb.data;
1154  __m128* _BB = (__m128*) BB.data;
1155 
1156  for(i=0; i<NIFO; i++) {
1157  vtd.push_back(tmp); // array of aligned energy vectors
1158  vTD.push_back(tmp); // array of aligned energy vectors
1159  eTD.push_back(tmp); // array of aligned energy vectors
1160  }
1161 
1162  for(i=0; i<NIFO; i++) { // set up zero deley pointers
1163  pa[i] = vtd[i].data + (tsize/2)*V4;
1164  pA[i] = vTD[i].data + (tsize/2)*V4;
1165  pe[i] = eTD[i].data + (tsize/2)*V4;
1166  }
1167 
1168  this->a_00.resize(NIFO*V4); this->a_00=0.;
1169  this->a_90.resize(NIFO*V4); this->a_90=0.;
1170  this->rNRG.resize(V4); this->rNRG=0.;
1171  this->pNRG.resize(V4); this->pNRG=0.;
1172 
1173  __m128* _aa = (__m128*) this->a_00.data; // set pointer to 00 array
1174  __m128* _AA = (__m128*) this->a_90.data; // set pointer to 90 array
1175 
1176  this->pList.clear();
1177  for(j=0; j<V; j++) { // loop over selected pixels
1178  pix = pwc->getPixel(id,pI[j]); // get pixel pointer
1179  pList.push_back(pix); // store pixel pointers for MRA
1180 
1181  double rms = 0.;
1182  for(i=0; i<nIFO; i++) {
1183  xx[i] = 1./pix->data[i].noiserms;
1184  rms += xx[i]*xx[i]; // total inverse variance
1185  }
1186 
1187  for(i=0; i<nIFO; i++) {
1188  nr.data[j*NIFO+i]=(float)xx[i]/sqrt(rms); // normalized 1/rms
1189  for(l=0; l<tsize; l++) {
1190  aa = pix->tdAmp[i].data[l]; // copy TD 00 data
1191  AA = pix->tdAmp[i].data[l+tsize]; // copy TD 90 data
1192  vtd[i].data[l*V4+j] = aa; // copy 00 data
1193  vTD[i].data[l*V4+j] = AA; // copy 90 data
1194  eTD[i].data[l*V4+j] = aa*aa+AA*AA; // copy power
1195  }
1196  }
1197  }
1198 
1199 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1200 // first sky loop
1201 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1202 
1203  int lb = 0;
1204  int le = Lsky-1;
1205  bool mra = false;
1206  double suball=0;
1207  double submra=0;
1208  bool skymaskcc = (skyMaskCC.size()==Lsky);
1209 
1210  stat=Lm=Em=Am=EE=0.; lm=Vm= -1;
1211 
1212  skyloop:
1213 
1214  for(l=lb; l<=le; l++) { // loop over sky locations
1215  if(!mm[l] || l<0) continue; // skip delay configurations
1216 
1217  if(skymaskcc) { // transform l into celestial coordinates lc
1218  skymap* sm = &(this->nSkyStat);
1219  double gT = cTo.data[k]+pwc->start; // trigger gps time
1220  double RA = sm->phi2RA(sm->getPhi(l),gT); // phi -> RA
1221  int lc=this->getIndex(sm->getTheta(l),RA); // get sky index in celestial coordinates
1222  if (!skyMaskCC.data[lc]) continue;
1223  }
1224 
1225  _sse_point_ps(_pe, pe, ml, int(l), (int)V4); // point _pe to energy vectors
1226 
1227  __m128 _msk;
1228  __m128 _E_o = _mm_setzero_ps(); // total network energy
1229  __m128 _E_n = _mm_setzero_ps(); // network energy above the threshold
1230  __m128 _E_s = _mm_setzero_ps(); // subnet energy above the threshold
1231  __m128 _M_m = _mm_setzero_ps(); // # of pixels above threshold
1232  __m128* _rE = (__m128*) rNRG.data; // m128 pointer to energy array
1233  __m128* _pE = (__m128*) pNRG.data; // m128 pointer to energy array
1234 
1235  for(j=0; j<V4; j+=4) { // loop over selected pixels
1236  *_rE = _sse_sum_ps(_pe); // get pixel energy
1237  _msk = _mm_and_ps(_1,_mm_cmpge_ps(*_rE,_En)); // E>En 0/1 mask
1238  _M_m = _mm_add_ps(_M_m,_msk); // count pixels above threshold
1239  *_pE = _mm_mul_ps(*_rE,_msk); // zero sub-threshold pixels
1240  _E_o = _mm_add_ps(_E_o,*_pE); // network energy
1241  _sse_minSNE_ps(_rE,_pe,_pE); // subnetwork energy with _pe increment
1242  _E_s = _mm_add_ps(_E_s,*_pE); // subnetwork energy
1243  _msk = _mm_and_ps(_1,_mm_cmpge_ps(*_pE++,_Es)); // subnet energy > Es 0/1 mask
1244  _E_n = _mm_add_ps(_E_n,_mm_mul_ps(*_rE++,_msk)); // network energy
1245  }
1246 
1247  _mm_storeu_ps(vvv,_E_n);
1248  Ln = vvv[0]+vvv[1]+vvv[2]+vvv[3]; // network energy above subnet threshold
1249  _mm_storeu_ps(vvv,_E_o);
1250  Eo = vvv[0]+vvv[1]+vvv[2]+vvv[3]+0.01; // total network energy
1251  _mm_storeu_ps(vvv,_E_s);
1252  Ls = vvv[0]+vvv[1]+vvv[2]+vvv[3]; // subnetwork energy
1253  _mm_storeu_ps(vvv,_M_m);
1254  m = 2*(vvv[0]+vvv[1]+vvv[2]+vvv[3])+0.01; // pixels above threshold
1255 
1256  aa = Ls*Ln/(Eo-Ls);
1257  if((aa-m)/(aa+m)<subcut) continue;
1258 
1259  pnt_(v00, pa, ml, (int)l, (int)V4); // pointers to first pixel 00 data
1260  pnt_(v90, pA, ml, (int)l, (int)V4); // pointers to first pixel 90 data
1261  float* pfp = fp.data; // set pointer to fp
1262  float* pfx = fx.data; // set pointer tp fx
1263  float* p00 = this->a_00.data; // set pointer for 00 array
1264  float* p90 = this->a_90.data; // set pointer for 90 array
1265 
1266  m = 0;
1267  for(j=0; j<V; j++) {
1268  int jf = j*f_; // source sse pointer increment
1269  cpp_(p00,v00); cpp_(p90,v90); // copy amplitudes with target increment
1270  cpf_(pfp,FP,l); cpf_(pfx,FX,l); // copy antenna with target increment
1271  _sse_zero_ps(_xi+jf); // zero MRA amplitudes
1272  _sse_zero_ps(_XI+jf); // zero MRA amplitudes
1273  _sse_cpf_ps(_am+jf,_aa+jf); // duplicate 00
1274  _sse_cpf_ps(_AM+jf,_AA+jf); // duplicate 90
1275  if(rNRG.data[j]>En) m++; // count superthreshold pixels
1276  }
1277 
1278  __m128* _pp = (__m128*) am.data; // point to multi-res amplitudes
1279  __m128* _PP = (__m128*) AM.data; // point to multi-res amplitudes
1280 
1281  if(mra) { // do MRA
1282  _sse_MRA_ps(xi.data,XI.data,En,m); // get principle components
1283  _pp = (__m128*) xi.data; // point to PC amplitudes
1284  _PP = (__m128*) XI.data; // point to PC amplitudes
1285  }
1286 
1287  m = 0; Ls=Ln=Eo=0;
1288  for(j=0; j<V; j++) {
1289  int jf = j*f_; // source sse pointer increment
1290  int mf = m*f_; // target sse pointer increment
1291  _sse_zero_ps(_bb+jf); // reset array for MRA amplitudes
1292  _sse_zero_ps(_BB+jf); // reset array for MRA amplitudes
1293  ee = _sse_abs_ps(_pp+jf,_PP+jf); // total pixel energy
1294  if(ee<En) continue;
1295  _sse_cpf_ps(_bb+mf,_pp+jf); // copy 00 amplitude/PC
1296  _sse_cpf_ps(_BB+mf,_PP+jf); // copy 90 amplitude/PC
1297  _sse_cpf_ps(_Fp+mf,_fp+jf); // copy F+
1298  _sse_cpf_ps(_Fx+mf,_fx+jf); // copy Fx
1299  _sse_mul_ps(_Fp+mf,_nr+jf); // normalize f+ by rms
1300  _sse_mul_ps(_Fx+mf,_nr+jf); // normalize fx by rms
1301  m++;
1302  em = _sse_maxE_ps(_pp+jf,_PP+jf); // dominant pixel energy
1303  Ls += ee-em; Eo += ee; // subnetwork energy, network energy
1304  if(ee-em>Es) Ln += ee; // network energy above subnet threshold
1305  }
1306  if(Eo<=0) continue;
1307 
1308  size_t m4 = m + (m%4 ? 4 - m%4 : 0);
1309  _E_n = _mm_setzero_ps(); // + likelihood
1310 
1311  for(j=0; j<m4; j+=4) {
1312  int jf = j*f_;
1313  _sse_dpf4_ps(_Fp+jf,_Fx+jf,_fp+jf,_fx+jf); // go to DPF
1314  _E_s = _sse_like4_ps(_fp+jf,_fx+jf,_bb+jf,_BB+jf); // std likelihood
1315  _E_n = _mm_add_ps(_E_n,_E_s); // total likelihood
1316  }
1317  _mm_storeu_ps(vvv,_E_n);
1318 
1319  Lo = vvv[0]+vvv[1]+vvv[2]+vvv[3];
1320  AA = aa/(fabs(aa)+fabs(Eo-Lo)+2*m*(Eo-Ln)/Eo); // subnet stat with threshold
1321  ee = Ls*Eo/(Eo-Ls);
1322  em = fabs(Eo-Lo)+2*m; // suball NULL
1323  ee = ee/(ee+em); // subnet stat without threshold
1324  aa = (aa-m)/(aa+m);
1325 
1326  if(AA>stat && !mra) {
1327  stat=AA; Lm=Lo; Em=Eo; Am=aa; lm=l; Vm=m; suball=ee; EE=em;
1328  }
1329  }
1330 
1331  if(!mra && lm>=0) {mra=true; le=lb=lm; goto skyloop;} // get MRA principle components
1332 
1333  pwc->sCuts[id-1] = -1;
1334  pwc->cData[id-1].likenet = Lm;
1335  pwc->cData[id-1].energy = Em;
1336  pwc->cData[id-1].theta = nLikelihood.getTheta(lm);
1337  pwc->cData[id-1].phi = nLikelihood.getPhi(lm);
1338  pwc->cData[id-1].skyIndex = lm;
1339 
1340  rHo = 0.;
1341  if(mra) {
1342  submra = Ls*Eo/(Eo-Ls); // MRA subnet statistic
1343  submra/= fabs(submra)+fabs(Eo-Lo)+2*(m+6); // MRA subnet coefficient
1344  To = 0;
1345  pwc->p_Ind[id-1].push_back(lm);
1346  for(j=0; j<vint->size(); j++) {
1347  pix = pwc->getPixel(id,j);
1348  pix->theta = nLikelihood.getTheta(lm);
1349  pix->phi = nLikelihood.getPhi(lm);
1350  To += pix->time/pix->rate/pix->layers;
1351  if(j==0&&mra) pix->ellipticity = submra; // subnet MRA propagated to L-stage
1352  if(j==0&&mra) pix->polarisation = fabs(Eo-Lo)+2*(m+6); // submra NULL propagated to L-stage
1353  if(j==1&&mra) pix->ellipticity = suball; // subnet all-sky propagated to L-stage
1354  if(j==1&&mra) pix->polarisation = EE; // suball NULL propagated to L-stage
1355  }
1356  To /= vint->size();
1357  rHo = sqrt(Lo*Lo/(Eo+2*m)/2); // estimator of coherent amplitude
1358  }
1359 
1360  if(hist && rHo>this->netRHO)
1361  for(j=0;j<vint->size();j++) hist->Fill(suball,submra);
1362 
1363  if(fmin(suball,submra)>subnet && rHo>this->netRHO) {
1364  count += vint->size();
1365  if(hist) {
1366  printf("lag|id %3d|%3d rho=%5.2f To=%5.1f stat: %5.3f|%5.3f|%5.3f ",
1367  int(lag),int(id),rHo,To,suball,submra,stat);
1368  printf("E: %6.1f|%6.1f L: %6.1f|%6.1f|%6.1f pix: %4d|%4d|%3d|%2d \n",
1369  Em,Eo,Lm,Lo,Ls,int(vint->size()),int(V),Vm,int(m));
1370  }
1371  }
1372  else pwc->sCuts[id-1]=1;
1373 
1374 // clean time delay data
1375 
1376  V = vint->size();
1377  for(j=0; j<V; j++) { // loop over pixels
1378  pix = pwc->getPixel(id,j);
1379  pix->core = true;
1380  if(pix->tdAmp.size()) pix->clean();
1381  }
1382  } // end of loop over clusters
1383  return count;
1384 }
1385 
1386 
1387 long network::likelihood2G(char mode, int lag, int iID, TH2F* hist)
1388 {
1389 // 2G likelihood analysis
1390 // mode: analysis mode:
1391 // OPTRES analyses, if upper case and optim=true
1392 // MRA analysis in low case or optim=false
1393 // r - un-modeled
1394 // i - iota - wave: no,partial dispersion correction
1395 // p - Psi - wave (no dispersion correction)
1396 // l,s - linear, loose linear
1397 // c,g - circular. loose circular
1398 // e,b - elliptical (no dispersion correction), b=p for now
1399 // iID: cluster ID, if negative - sky error regions are calculated
1400 // lag: lag index
1401 // hist: chirp histogram: If not needed, TGraphErrors* hist=NULL
1402 // shold be used as input
1403 // return number of processed pixels
1404 // Negative gamma regulator turns on the AP prior for sky localization
1405 //
1406 // Delta Regulator:
1407 // constraint w(weak) g(circ) h(hard)
1408 // D0 1----------0.5--------0.5 // value of D0 (00-phase) threshold
1409 // |delta|: 0----------0.5---------1 // value of delta regulator
1410 // D9 1-----------1---------0.5 // value of D9 (90-phase) threshold
1411 
1412  if(!this->wc_List[lag].size()) return 0;
1413 
1414  this->like('2');
1415  this->wdm(true);
1416  this->tYPe = mode;
1417 
1418  bool cirwave = mode=='g' || mode=='G' || mode=='c' || mode=='C';
1419  bool linwave = mode=='l' || mode=='L' || mode=='s' || mode=='S';
1420  bool iotwave = mode=='i' || mode=='l' || mode=='e' || mode=='c' ||
1421  mode=='I' || mode=='L' || mode=='E' || mode=='C';
1422  bool psiwave = mode=='l' || mode=='e' || mode=='p' ||
1423  mode=='L' || mode=='E' || mode=='P';
1424  bool mureana = mode=='i' || mode=='e' || mode=='c' ||
1425  mode=='r' || mode=='p' || mode=='b' ||
1426  mode=='l' || mode=='s' || mode=='g';
1427  bool rndwave = mode=='r' || mode=='R';
1428 
1429  bool prior = this->gamma<0 ? true : false; // gamma<0 : antenna pattern prior is used
1430  bool m_chirp = this->optim ? false : mureana;
1431 
1432  if(!this->optim) mureana = true;
1433 
1434  size_t nIFO = this->ifoList.size();
1435  size_t ID = abs(iID);
1436 
1437  if(nIFO>NIFO) {
1438  cout<<"network::likelihood2G(): invalid network.\n";
1439  exit(0);
1440  }
1441 
1442  float En = 2*acor*acor*nIFO; // network energy threshold in the sky loop
1443  float Es = 2*e2or; // subnet energy threshold
1444  float gama = fabs(this->gamma); // gamma regulator - hard/kill
1445  float deta = fabs(this->delta); // delta regulator - weak/circular/hard
1446  if(gama<=0) gama = 1.e-24; // limit gamma
1447  if(gama>=1) gama = 0.999999; // limit gamma
1448 
1449 // delta regulator:
1450 // constraint w(weak) g(circ) h(hard) // w - no constraint
1451 // DI 1----------0.5--------0.5 // value of DI (00-phase) threshold
1452 // |delta|: 0----------0.5---------1 // value of delta regulator
1453 // DQ 1-----------1---------0.5 // value of DQ (90-phase) threshold
1454 
1455  static const __m128 _D0 = _mm_set1_ps(deta<0.5?1-deta:0.5);
1456  static const __m128 _D9 = _mm_set1_ps(deta<0.5?1:1.5-deta);
1457 
1458  static const __m128 _oo = _mm_set1_ps(1.e-16); // nusance parameter
1459  static const __m128 _sm = _mm_set1_ps(-0.f); // sign mask: -0.f = 1 << 31
1460  static const __m128 _En = _mm_set1_ps(En); // network threshold
1461  static const __m128 _rG = _mm_set1_ps(-1./log(gama)); // regulator-gamma threshold
1462  static const __m128 _kG = _mm_set1_ps(gama); // kill-gamma threshold
1463  static const __m128 _PW = _mm_set1_ps(psiwave?0:1); // flag for psiwave option
1464  static const __m128 _01 = _mm_set1_ps(0.1);
1465  static const __m128 _05 = _mm_set1_ps(0.5);
1466  static const __m128 _09 = _mm_set1_ps(0.9);
1467  static const __m128 _1 = _mm_set1_ps(1.0+1.e-16);
1468  static const __m128 _2 = _mm_set1_ps(2.0);
1469  static const __m128 _4 = _mm_set1_ps(4.0);
1470 
1471  __m128* _pe[NIFO];
1472 
1473  int f_ = NIFO/4;
1474  float NRG,Lm,Em,Lo,Eo,No,Nm,cc,Cm,Co,Do,To,Fo,Ln,Ns;
1475  float STAT,CHR,aa,AA,ee,em,EE,ff,FF,Lr,Cr,ss,Ls,Nc,gg;
1476  double eLp, s2p, c2p;
1477  int optR = 0; // optimal resolution (used by SRA)
1478 
1479  size_t i,j,k,l,m,Vm,lm,V,V4,V44,id,K,M;
1480  size_t L = this->index.size(); // total number of source locations
1481  short* mm = this->skyMask.data;
1482  bool skymaskcc = (skyMaskCC.size()==L);
1483 
1484  float vvv[NIFO] _ALIGNED;
1485  float uuu[NIFO] _ALIGNED;
1486  float* v00[NIFO] _ALIGNED;
1487  float* v90[NIFO] _ALIGNED;
1488  float* pe[NIFO] _ALIGNED;
1489  float* pa[NIFO] _ALIGNED;
1490  float* pA[NIFO] _ALIGNED;
1491  short* ml[NIFO] _ALIGNED;
1492  double* FP[NIFO] _ALIGNED;
1493  double* FX[NIFO] _ALIGNED;
1494  double xx[NIFO] _ALIGNED;
1495 
1496  for(i=0; i<NIFO; i++) {
1497  if(i<nIFO) {
1498  ml[i] = getifo(i)->index.data;
1499  FP[i] = getifo(i)->fp.data;
1500  FX[i] = getifo(i)->fx.data;
1501  }
1502  else {
1503  ml[i] = getifo(0)->index.data;
1504  FP[i] = getifo(0)->fp.data;
1505  FX[i] = getifo(0)->fx.data;
1506  }
1507  }
1508 
1509  // allocate buffers
1510  std::vector<int> pI; // buffer for pixel IDs
1511  std::vector<int> pJ; // buffer for pixel index
1512  wavearray<double> cid; // buffers for cluster ID
1513  wavearray<double> cTo; // buffers for cluster time
1514  netpixel* pix;
1515  std::vector<int>* vint;
1516  std::vector<int>* vtof;
1517  std::vector<int> pRate;
1518  netcluster* pwc = &this->wc_List[lag];
1519 
1520  size_t count = 0;
1521  size_t tsize = 0;
1522 
1523  std::map<int,float> vLr; // resolution map
1524 
1525 //+++++++++++++++++++++++++++++++++++++++
1526 // loop over clusters
1527 //+++++++++++++++++++++++++++++++++++++++
1528 
1529  cid = pwc->get((char*)"ID", 0,'S',0); // get cluster ID
1530  cTo = pwc->get((char*)"time",0,'L',0); // get cluster time
1531 
1532  K = cid.size();
1533  for(k=0; k<K; k++) { // loop over clusters
1534  id = size_t(cid.data[k]+0.1);
1535 
1536  if(pwc->sCuts[id-1] != -2) continue; // skip rejected/processed clusters
1537 
1538  vint = &(pwc->cList[id-1]); // pixel list
1539  vtof = &(pwc->nTofF[id-1]); // TofFlight configurations
1540  V = vint->size();
1541  if(!V) continue;
1542 
1543  pI = wdmMRA.getXTalk(pwc, id);
1544  V = pI.size();
1545  if(!V) continue;
1546 
1547  if(ID==id) {
1548  this->nSensitivity = 0.;
1549  this->nAlignment = 0.;
1550  this->nNetIndex = 0.;
1551  this->nDisbalance = 0.;
1552  this->nLikelihood = 0.;
1553  this->nNullEnergy = 0.;
1554  this->nCorrEnergy = 0.;
1555  this->nCorrelation = 0.;
1556  this->nSkyStat = 0.;
1557  this->nEllipticity = 0.;
1558  this->nPolarisation = 0.;
1559  this->nProbability = 0.;
1560  }
1561  this->nAntenaPrior = 0.;
1562 
1563  pix = pwc->getPixel(id,pI[0]);
1564  tsize = pix->tdAmp[0].size();
1565  if(!tsize || tsize&1) { // tsize%1 = 1/0 = power/amplitude
1566  cout<<"network::likelihood2G() error: wrong pixel TD data\n";
1567  exit(1);
1568  }
1569 
1570  tsize /= 2;
1571 
1572  if(!(V=pI.size())) continue;
1573  V4 = V + (V%4 ? 4 - V%4 : 0);
1574  V44 = V4 + 4;
1575  pJ.clear();
1576  for(j=0; j<V4; j++) pJ.push_back(0);
1577 
1578  //cout<<En<<" "<<Es<<" "<<lag<<" "<<id<<" "<<V4<<" "<<" "<<tsize<<endl;
1579 
1580  std::vector<wavearray<float> > vtd; // vectors of TD amplitudes
1581  std::vector<wavearray<float> > vTD; // vectors of TD amplitudes
1582  std::vector<wavearray<float> > eTD; // vectors of TD energies
1583 
1584  wavearray<float> tmp(tsize*V4); tmp=0; // aligned array for TD amplitudes
1585  wavearray<float> nr(NIFO*V44); nr=0; // aligned array for inverse rms
1586  wavearray<float> fp(NIFO*V44); fp=0; // aligned array for + antenna pattern
1587  wavearray<float> fx(NIFO*V44); fx=0; // aligned array for x antenna pattern
1588  wavearray<float> ep(NIFO*V44); ep=0; // aligned array for + unity vector
1589  wavearray<float> ex(NIFO*V44); ex=0; // aligned array for x unity vector
1590  wavearray<float> Fp(NIFO*V44); Fp=0; // aligned array for F+ patterns
1591  wavearray<float> Fx(NIFO*V44); Fx=0; // aligned array for Fx patterns
1592  wavearray<float> am(NIFO*V44); am=0; // aligned array for pixel amplitudes
1593  wavearray<float> AM(NIFO*V44); AM=0; // aligned array for pixel amplitudes
1594  wavearray<float> bb(NIFO*V44); bb=0; // temporary array for MRA amplitudes
1595  wavearray<float> BB(NIFO*V44); BB=0; // temporary array for MRA amplitudes
1596  wavearray<float> xi(NIFO*V44); xi=0; // 00 array for reconctructed responses
1597  wavearray<float> XI(NIFO*V44); XI=0; // 90 array for reconstructed responses
1598  wavearray<float> ww(NIFO*V44); ww=0; // 00 array for phase-shifted data vectors
1599  wavearray<float> WW(NIFO*V44); WW=0; // 90 array for phase-shifted data vectors
1600  wavearray<float> xp(NIFO*V44); xp=0; // 00 array for network projection
1601  wavearray<float> XP(NIFO*V44); XP=0; // 90 array for network projection
1602 
1603  // data arrays for polar coordinates storage : [0,1] = [radius,angle]
1604  for(i=0;i<2;i++) {
1605  this->p00_POL[i].resize(V4); this->p00_POL[i]=0.;
1606  this->p90_POL[i].resize(V4); this->p90_POL[i]=0.;
1607  this->r00_POL[i].resize(V4); this->r00_POL[i]=0.;
1608  this->r90_POL[i].resize(V4); this->r90_POL[i]=0.;
1609  }
1610 
1611  __m128* _Fp = (__m128*) Fp.data;
1612  __m128* _Fx = (__m128*) Fx.data;
1613  __m128* _am = (__m128*) am.data;
1614  __m128* _AM = (__m128*) AM.data;
1615  __m128* _xi = (__m128*) xi.data;
1616  __m128* _XI = (__m128*) XI.data;
1617  __m128* _xp = (__m128*) xp.data;
1618  __m128* _XP = (__m128*) XP.data;
1619  __m128* _ww = (__m128*) ww.data;
1620  __m128* _WW = (__m128*) WW.data;
1621  __m128* _bb = (__m128*) bb.data;
1622  __m128* _BB = (__m128*) BB.data;
1623  __m128* _fp = (__m128*) fp.data;
1624  __m128* _fx = (__m128*) fx.data;
1625  __m128* _nr = (__m128*) nr.data;
1626  __m128* _ep = (__m128*) ep.data; // point to + unity vector
1627  __m128* _ex = (__m128*) ex.data; // point to x unity vector
1628 
1629  __m128* _fp4 = _fp+V4*f_;
1630  __m128* _fx4 = _fx+V4*f_;
1631  __m128* _uu4 = _am+V4*f_;
1632  __m128* _vv4 = _AM+V4*f_;
1633  __m128* _bb4 = _bb+V4*f_;
1634  __m128* _BB4 = _BB+V4*f_;
1635 
1636  for(i=0; i<NIFO; i++) {
1637  vtd.push_back(tmp); // array of aligned energy vectors
1638  vTD.push_back(tmp); // array of aligned energy vectors
1639  eTD.push_back(tmp); // array of aligned energy vectors
1640  }
1641 
1642  for(i=0; i<NIFO; i++) { // set up zero deley pointers
1643  pa[i] = vtd[i].data + (tsize/2)*V4;
1644  pA[i] = vTD[i].data + (tsize/2)*V4;
1645  pe[i] = eTD[i].data + (tsize/2)*V4;
1646  }
1647 
1648  wavearray<float> siDPF(V4); siDPF=0; // temporary array for DPF sin
1649  wavearray<float> coDPF(V4); coDPF=0; // temporary array for DPF cos
1650  wavearray<float> siORT(V4); siORT=0; // temporary array for ort4 sin
1651  wavearray<float> coORT(V4); coORT=0; // temporary array for ort4 cos
1652  wavearray<float> siPHS(V4); siPHS=0; // temporary array for Phase sin
1653  wavearray<float> coPHS(V4); coPHS=0; // temporary array for Phase cos
1654  wavearray<float> chir(V4); chir=0; // chirality array
1655  wavearray<float> q2Q2(V4); q2Q2=0; // energy array q^2+Q^2
1656  wavearray<float> ec00(V4); ec00=0; // 00-phase coherent energy array
1657  wavearray<float> EC90(V4); EC90=0; // 90-phase coherent energy array
1658  wavearray<float> zzz(V4); zzz=0; // temporary array
1659  wavearray<float> yyy(V4); yyy=0; // temporary array
1660  wavearray<float> xxx(V4); xxx=0; // temporary array
1661  wavearray<float> rrr(V4); rrr=0; // regulator flag array
1662 
1663  this->a_00.resize(NIFO*V44); this->a_00=0.; // array for pixel amplitudes in sky loop
1664  this->a_90.resize(NIFO*V44); this->a_90=0.; // array for pixel amplitudes in sky loop
1665  this->rNRG.resize(V4); this->rNRG=0.;
1666  this->pNRG.resize(V4); this->pNRG=0.;
1667 
1668  __m128* _aa = (__m128*) this->a_00.data; // set pointer to 00 array
1669  __m128* _AA = (__m128*) this->a_90.data; // set pointer to 90 array
1670 
1671 
1672  this->pList.clear(); pRate.clear();
1673  for(j=0; j<V; j++) { // loop over selected pixels
1674  pix = pwc->getPixel(id,pI[j]);
1675  this->pList.push_back(pix); // store pixel pointers for MRA
1676  pRate.push_back(int(pix->rate+0.5)); // store pixel rates for MRA
1677 
1678  if(vLr.find(pRate[j]) == vLr.end()) // initialize vLr map
1679  vLr[pRate[j]] = 0.;
1680 
1681  double rms = 0.;
1682  for(i=0; i<nIFO; i++) {
1683  xx[i] = 1./pix->data[i].noiserms;
1684  rms += xx[i]*xx[i]; // total inverse variance
1685  }
1686 
1687  rms = sqrt(rms);
1688  for(i=0; i<nIFO; i++) {
1689  nr.data[j*NIFO+i]=(float)xx[i]/rms; // normalized 1/rms
1690  for(l=0; l<tsize; l++) {
1691  aa = pix->tdAmp[i].data[l]; // copy TD 00 data
1692  AA = pix->tdAmp[i].data[l+tsize]; // copy TD 90 data
1693  vtd[i].data[l*V4+j] = aa; // copy 00 data
1694  vTD[i].data[l*V4+j] = AA; // copy 90 data
1695  eTD[i].data[l*V4+j] = aa*aa+AA*AA; // copy power
1696  }
1697  }
1698  }
1699 
1700 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1701 // sky loop
1702 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1703 
1704  STAT=0.; lm=0; Vm=0;
1705  double skystat = 0.;
1706  size_t lb = 0;
1707  size_t le = L-1;
1708  bool mra = false;
1709 
1710  optsky:
1711 
1712  AA = 0.; // initialize sky statistic
1713  for(l=lb; l<=le; l++) { // loop over sky locations
1714  if(!mra) skyProb.data[l] = 0.;
1715  if(!mm[l]) continue; // skip delay configurations
1716 
1717  if(skymaskcc) { // transform l into celestial coordinates lc
1718  skymap* sm = &(this->nSkyStat);
1719  double gT = cTo.data[k]+pwc->start; // trigger gps time
1720  double RA = sm->phi2RA(sm->getPhi(l),gT); // phi -> RA
1721  int lc=this->getIndex(sm->getTheta(l),RA); // get sky index in celestial coordinates
1722  if (!skyMaskCC.data[lc]) continue;
1723  }
1724 
1725  pnt_(v00, pa, ml, (int)l, (int)V4); // pointers to first pixel 00 data
1726  pnt_(v90, pA, ml, (int)l, (int)V4); // pointers to first pixel 90 data
1727  float* pfp = fp.data; // set pointer to fp
1728  float* pfx = fx.data; // set pointer to fx
1729  float* p00 = this->a_00.data; // set pointer for 00 array
1730  float* p90 = this->a_90.data; // set pointer for 90 array
1731  float mxLr = 0.;
1732  optR = 0;
1733 
1734  for(j=0; j<V; j++) {
1735  cpp_(p00,v00); cpp_(p90,v90); // copy amplitudes with target increment
1736  cpf_(pfp,FP,l); cpf_(pfx,FX,l); // copy antenna with target increment
1737  if(!this->optim || !mra) continue; // skip if not optimal resolution or !mra
1738  if(vLr[pRate[j]] <= mxLr) continue; // skip small Lr
1739  mxLr = vLr[pRate[j]]; // update maximum Lr
1740  optR = pRate[j]; // select optimal rate
1741  }
1742 
1743  m = 0;
1744  for(j=0; j<V; j++) {
1745  int jf = j*f_; // source sse pointer increment
1746  _sse_zero_ps(_xi+jf); // zero MRA amplitudes
1747  _sse_zero_ps(_XI+jf); // zero MRA amplitudes
1748  rNRG.data[j] = 1; // SRA flag
1749  if(optR && optR!=pRate[j]) { // clear non optimal rate amplitudes
1750  _sse_zero_ps(_aa+jf);
1751  _sse_zero_ps(_AA+jf);
1752  rNRG.data[j] = 0; // exclude these resolutions
1753  }
1754  _sse_cpf_ps(_am+jf,_aa+jf); // duplicate 00
1755  _sse_cpf_ps(_AM+jf,_AA+jf); // duplicate 90
1756  ee = _sse_abs_ps(_aa+jf,_AA+jf); // total pixel energy / quadrature
1757  if(ee>En) m++; else ee=0.; // count core pixels
1758  rNRG.data[j]*= ee; // init residual energy array
1759  pNRG.data[j] = rNRG.data[j]; // init residual energy array
1760  }
1761 
1762  __m128* _pp = (__m128*) am.data; // point to multi-res amplitudes
1763  __m128* _PP = (__m128*) AM.data; // point to multi-res amplitudes
1764 
1765  if(mra && mureana) { // do MRA
1766  _sse_mra_ps(xi.data,XI.data,En,m); // get principle components
1767  _pp = (__m128*) xi.data; // point to PC amplitudes
1768  _PP = (__m128*) XI.data; // point to PC amplitudes
1769  }
1770 
1771  m = 0; Em = 0.;
1772  for(j=0; j<V; j++) {
1773  int jf = j*f_; // source sse pointer increment
1774  int mf = m*f_; // target sse pointer increment
1775  pJ[j] = 0;
1776  _sse_zero_ps(_bb+jf); // reset array for MRA amplitudes
1777  _sse_zero_ps(_BB+jf); // reset array for MRA amplitudes
1778  ee = pNRG.data[j]; // total pixel energy
1779  if(ee<En) continue;
1780  _sse_cpf_ps(_bb+mf,_pp+jf); // copy 00 amplitude/PC
1781  _sse_cpf_ps(_BB+mf,_PP+jf); // copy 90 amplitude/PC
1782  _sse_cpf_ps(_Fp+mf,_fp+jf); // copy F+
1783  _sse_cpf_ps(_Fx+mf,_fx+jf); // copy Fx
1784  _sse_mul_ps(_Fp+mf,_nr+jf); // normalize f+ by rms
1785  _sse_mul_ps(_Fx+mf,_nr+jf); // normalize fx by rms
1786  pJ[m++]= j; // store pixel index
1787  }
1788 
1789  size_t m4 = m + (m%4 ? 4 - m%4 : 0);
1790  __m128 _ll,_LL,_ec,_EC,_ee,_EE,_NI,_s2,_c2,_AX,_NN,_FF,_QQ,_ie,_gg;
1791  __m128 _en,_EN,_ed,_ED,_cc,_ss,_ni,_si,_co,_ax,_nn,_ff,_mm,_IE,_GG;
1792 
1793  __m128* _siP = (__m128*) siPHS.data; // phase sin
1794  __m128* _coP = (__m128*) coPHS.data; // phase cos
1795  __m128* _siO = (__m128*) siORT.data; // ort4 sin
1796  __m128* _coO = (__m128*) coORT.data; // ort4 cos
1797  __m128* _siD = (__m128*) siDPF.data; // DPF sin
1798  __m128* _coD = (__m128*) coDPF.data; // DPF cos
1799  __m128* _nrg = (__m128*) q2Q2.data; // energy (1+e^2)*(q^2+Q^2)
1800  __m128* _chr = (__m128*) chir.data; // chirality (sign of e)
1801 
1802  if(mra) {
1803  _pp = (__m128*) xi.data; // point to PC amplitudes
1804  _PP = (__m128*) XI.data; // point to PC amplitudes
1805  }
1806 
1807 // test sky location
1808 
1809  Lo = Ln = Co = Eo = 0.;
1810  for(j=0; j<m4; j+=4) {
1811  int jf = j*f_; // sse index increment
1812 
1813  __m128* _pbb = _bb+jf;
1814  __m128* _pBB = _BB+jf;
1815  __m128* _pxi = _pp+jf;
1816  __m128* _pXI = _PP+jf;
1817  __m128* _pxp = _xp+jf;
1818  __m128* _pXP = _XP+jf;
1819  __m128* _pww = _ww+jf;
1820  __m128* _pWW = _WW+jf;
1821  __m128* _pfp = _fp+jf;
1822  __m128* _pfx = _fx+jf;
1823  __m128* _pFp = _Fp+jf;
1824  __m128* _pFx = _Fx+jf;
1825 
1826 // do transformations
1827 
1828  _sse_ort4_ps(_pFp,_pFx,_siD,_coD); // get DPF sin and cos
1829  _sse_rot4p_ps(_pFp,_coD,_pFx,_siD,_pfp); // get DPF fp=Fp*c+Fx*s
1830  _sse_rot4m_ps(_pFx,_coD,_pFp,_siD,_pfx); // get DPF fx=Fx*c-Fp*s
1831  _sse_pnp4_ps(_pfp,_pfx,_pbb,_pBB,_pxp,_pXP); // projection on network plane
1832  _sse_ort4_ps(_pxp,_pXP,_siO,_coO); // dual-stream phase sin and cos
1833  _sse_rot4p_ps(_pxp,_coO,_pXP,_siO,_pxi); // get 00 standard response
1834  _sse_rot4m_ps(_pXP,_coO,_pxp,_siO,_pXI); // get 90 standard response
1835  _sse_rot4p_ps(_pbb,_coO,_pBB,_siO,_pww); // get 00 phase data vector
1836  _sse_rot4m_ps(_pBB,_coO,_pbb,_siO,_pWW); // get 90 phase data vector
1837  _coO++; _siO++; _coD++; _siD++; // increment to next 4 pixels
1838 
1839 // save projection on network plane and standard response in polar coordinates
1840  if(le==lb && (optR==0)) {
1841  _sse_pol4_ps(_pfp, _pfx, _pxp, p00_POL[0].data+j, p00_POL[1].data+j);
1842  _sse_pol4_ps(_pfp, _pfx, _pXP, p90_POL[0].data+j, p90_POL[1].data+j);
1843  _sse_pol4_ps(_pfp, _pfx, _pxi, r00_POL[0].data+j, r00_POL[1].data+j);
1844  _sse_pol4_ps(_pfp, _pfx, _pXI, r90_POL[0].data+j, r90_POL[1].data+j);
1845  }
1846 
1847 // standard statistics
1848 
1849  _ee = _sse_abs4_ps(_pww); // 00 energy
1850  _ll = _sse_abs4_ps(_pxi); // standard 00 likelihood
1851  _ec = _sse_ecoh4_ps(_pww,_pxi,_ll); // 00 coherent energy
1852  _EE = _sse_abs4_ps(_pWW); // 90 energy
1853  _LL = _sse_abs4_ps(_pXI); // standard 00 likelihood
1854  _EC = _sse_ecoh4_ps(_pWW,_pXI,_LL); // 90 coherent energy
1855  _cc = _mm_and_ps(_mm_cmpge_ps(_ec,_05),_1); // 00-phase denoising
1856  _ss = _mm_and_ps(_mm_cmpgt_ps(_EC,_05),_cc); // 90-phase denoising
1857 
1858  _ec = _sse_rotp_ps(_ec,_cc,_EC,_ss); // total coherent energy
1859  _ll = _sse_rotp_ps(_ll,_cc,_LL,_ss); // total likelihood
1860  _mm = _sse_rotp_ps(_1,_cc,_1,_ss); // Gaussian noise
1861  _nn = _mm_add_ps(_mm_add_ps(_ee,_EE),_2); // total energy
1862  _cc = _mm_add_ps(_ec,_mm_sub_ps(_nn,_ll));
1863  _cc = _mm_div_ps(_ec,_mm_add_ps(_cc,_mm)); // network correlation coefficient
1864 
1865  _mm_storeu_ps(vvv,_mm_add_ps(_ee,_EE));
1866  Eo += vvv[0]+vvv[1]+vvv[2]+vvv[3]; // network null energy
1867  _mm_storeu_ps(vvv,_ll);
1868  Lo += vvv[0]+vvv[1]+vvv[2]+vvv[3]; // network likelihood
1869  _mm_storeu_ps(vvv,_mm_mul_ps(_ll,_cc));
1870  Ln += vvv[0]+vvv[1]+vvv[2]+vvv[3]; // network likelihood
1871  _mm_storeu_ps(vvv,_ec);
1872  Co += vvv[0]+vvv[1]+vvv[2]+vvv[3]; // network coherent energy
1873  _mm_storeu_ps(vvv,_mm_mul_ps(_ec,_ll));
1874  if(le==lb && !mra) { // optimal resolution likelihood
1875  vLr[pRate[pJ[j+0]]] += vvv[0];
1876  vLr[pRate[pJ[j+1]]] += vvv[1];
1877  vLr[pRate[pJ[j+2]]] += vvv[2];
1878  vLr[pRate[pJ[j+3]]] += vvv[3];
1879  }
1880  }
1881  Ln = Eo>0 ? Ln/Eo : 0;
1882  if(Ln<this->netCC) continue; // skip
1883  _IE = _mm_set1_ps(1-Co/Lo); // global event index
1884 
1885 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1886 // reconstruction loop
1887 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1888  __m128* _xx = (__m128*) xxx.data; // store |f+|
1889  __m128* _yy = (__m128*) yyy.data; // store |fx|
1890  __m128* _zz = (__m128*) zzz.data; // store total amplitude
1891  __m128* _rr = (__m128*) rrr.data; // store regulator flag
1892 
1893  for(j=0; j<m4; j+=4) {
1894  int jf = j*f_; // sse index increment
1895  __m128* _pfp = _fp+jf;
1896  __m128* _pfx = _fx+jf;
1897  *_xx = _sse_abs4_ps(_pfp); // |f+|^2
1898  *_yy = _sse_abs4_ps(_pfx); // |fx|^2
1899  _ee = _mm_add_ps(_mm_sqrt_ps(*_xx++),_oo); // |f+| + eps
1900  _EE = _mm_add_ps(_mm_sqrt_ps(*_yy++),_oo); // |fx| + eps
1901  _sse_cpf4_ps(_ep+jf,_pfp,_mm_div_ps(_1,_ee)); // store + unity vector in ep
1902  _sse_cpf4_ps(_ex+jf,_pfx,_mm_div_ps(_1,_EE)); // store x unity vector in ex
1903  }
1904 
1905  _xx = (__m128*) xxx.data; // store 1/|f+|
1906  _yy = (__m128*) yyy.data; // store 1/|fx|
1907  _zz = (__m128*) zzz.data; // store (1-e*e)*(qq+QQ)*|fx|^2
1908  _rr = (__m128*) rrr.data; // regulator flag
1909  _siP = (__m128*) siPHS.data; // phase sin
1910  _coP = (__m128*) coPHS.data; // phase cos
1911  _siD = (__m128*) siDPF.data; // DPF sin
1912  _coD = (__m128*) coDPF.data; // DPF cos
1913  _nrg = (__m128*) q2Q2.data; // energy (1+e^2)*(q^2+Q^2)
1914 
1915  __m128 linw = linwave ? _oo : _1;
1916  __m128 cirw = cirwave ? _oo : _1;
1917  __m128 _ch = _mm_setzero_ps(); // chirality
1918  __m128 _eqQ = _mm_setzero_ps(); // e*(qq+QQ)*|fx|^2
1919  __m128 _qQ2 = _mm_setzero_ps(); // 2*(qq+QQ)*|fx|^2
1920 
1921  _c2 = _mm_setzero_ps(); // cos[-2p] polarization angle
1922  _s2 = _mm_setzero_ps(); // sin[-2p]
1923  _cc = _mm_setzero_ps(); // cos[t] average vector angle
1924  _ss = _mm_setzero_ps(); // sin[t]
1925 
1926  for(j=0; j<m4; j+=4) { // produce NEW pattern
1927  int jf = j*f_; // sse index increment
1928  __m128* _pfp = _fp+jf;
1929  __m128* _pfx = _fx+jf;
1930  __m128* _pep = _ep+jf;
1931  __m128* _pex = _ex+jf;
1932  __m128* _pxp = _xp+jf;
1933  __m128* _pXP = _XP+jf;
1934  __m128* _pxi = _pp+jf;
1935  __m128* _pXI = _PP+jf;
1936 
1937  _ee = _mm_div_ps(_1,_mm_add_ps(*_xx,_oo)); // 1/|f+|^2
1938  _co = _mm_mul_ps(_sse_dot4_ps(_pfp,_pxi),_ee); // (fp,x)/|f+|^2
1939  _si = _mm_mul_ps(_sse_dot4_ps(_pfp,_pXI),_ee); // (fp,X)/|f+|^2
1940  _sse_rot4p_ps(_pxi,&_co,_pXI,&_si,_bb4); // y 00 phase pattern
1941  _sse_rot4m_ps(_pXI,&_co,_pxi,&_si,_BB4); // Y 90 phase pattern
1942  _NN = _sse_rotp_ps(_co,_co,_si,_si); // (xp*xp+XP*XP) - norm^2
1943  _nn = _mm_div_ps(_1,_mm_add_ps(_NN,_oo)); // 1/(xp*xp+XP*XP) - 1/norm^2
1944  *_siP = _mm_mul_ps(_si,_nn); // normalize siP (used later)
1945  *_coP = _mm_mul_ps(_co,_nn); // normalize coP (used later)
1946 
1947  if(le==lb && (optR==0)) { // save polargrams
1948  __m128 _snn = _mm_sqrt_ps(_nn);
1949  _sse_cpf4_ps(_uu4,_bb4,_snn); // normalize bb4
1950  _sse_cpf4_ps(_vv4,_BB4,_snn); // normalize BB4
1951  _sse_pol4_ps(_ep+jf, _ex+jf, _uu4, r00_POL[0].data+j, r00_POL[1].data+j);
1952  _sse_pol4_ps(_ep+jf, _ex+jf, _vv4, r90_POL[0].data+j, r90_POL[1].data+j);
1953  }
1954 
1955  _en = _sse_dot4_ps(_pex,_bb4); // (ex,y)=-(1-e*e)*(qq+QQ)*S[2d-2p]*|fx|/2
1956  _EN = _sse_dot4_ps(_pex,_BB4); // e*(qq+QQ)*|fx|
1957  _ch = _mm_add_ps(_ch,_EN); // total e*(qq+QQ)*|fx|
1958  _ll = _mm_and_ps(_mm_cmpgt_ps(_EN,_oo),_1); // 1 if e positive
1959  *_chr = _mm_sub_ps(_mm_mul_ps(_ll,_2),_1); // +1/-1 e positive/negative
1960 
1961  _ll = _sse_abs4_ps(_pxi); // 00 energy in ORT pattern
1962  _ni = _sse_ind4_ps(_pfp,*_xx); // f+ index
1963  _NI = _sse_ind4_ps(_pfx,*_yy); // fx index
1964  _ie = _sse_ind4_ps(_pxi,_ll); // normalized incoherent energy
1965  _ff = _mm_div_ps(_mm_add_ps(*_xx,*_yy),_ni); // (|f+|^2+|fx|^2)/ni
1966 
1967  _LL = _sse_rotp_ps(_en,_en,_EN,_EN); // (fx,y)^2+(fx,Y)^2
1968  _LL = _mm_mul_ps(_LL,_nn); // {(1+e*e)-(1-e*e)*C[2d-2p]}*|fx|^2*(qq+QQ)/2
1969  _FF = _mm_mul_ps(*_yy,_ee); // FF = |fx|^2/|f+|^2 - alignment factor
1970  _gg = _mm_mul_ps(_01,_ff); // 0.1*ff
1971  _NN = _mm_mul_ps(_NN,*_xx); // {(1+e*e)+(1-e*e)*C[2d-2p]}*|f+|^2*(qq+QQ)/2
1972  _ll = _mm_mul_ps(_NN,_mm_add_ps(_FF,_gg)); // {(1+e*e)+(1-e*e)*C[2d-2p]}*|f+|^2*(qq+QQ)/2 * (FF+0.1*ff)
1973  _co = _mm_sub_ps(_ll,_LL); // C2*(1-e*e)*(qq+QQ)*|fx|^2
1974  _si = _mm_mul_ps(_2,_sse_dot4_ps(_pfx,_bb4)); //-S2*(1-e*e)*(qq+QQ)*|fx|^2
1975  *_zz = _sse_rotp_ps(_co,_co,_si,_si); // [(1-e*e)*(qq+QQ)*|fx|^2]^2
1976  *_zz = _mm_add_ps(_mm_sqrt_ps(*_zz),_oo); // (1-e*e)*(qq+QQ)*|fx|^2
1977  _ll = _mm_mul_ps(_NN,_FF); // {(1+e*e)+(1-e*e)*C[2d-2p]}*|fx|^2*(qq+QQ)/2
1978  _QQ = _mm_add_ps(_mm_add_ps(_ll,_LL),*_zz); // 2*(qq+QQ)*|fx|^2
1979  _ff = _mm_sqrt_ps(_mm_mul_ps(_ff,_05)); // sqrt[(|f+|^2+|fx|^2)/ni/2]
1980  _FF = _mm_sqrt_ps(_FF); // a = FF = |fx|/|f+| - alignment factor
1981  // CHANGE MEANING OF _ll and _LL
1982  _ax = _mm_add_ps(_1,_mm_div_ps(_co,*_zz)); // 2*sin(d-p)^2 (solution for cos[2d-2p] ~ -1)
1983  _ax = _mm_sqrt_ps(_mm_mul_ps(_ax,_05)); // sin(d-p)
1984  _AX = _sse_dot4_ps(_pfx,_BB4); // e*(qq+QQ)*|fx|^2
1985  _qQ2 = _mm_add_ps(_qQ2,_QQ); // store amplitude term
1986  _eqQ = _mm_add_ps(_eqQ,_AX); // store ellipticity term
1987  _AX = _mm_div_ps(_mm_mul_ps(_2,_AX),_QQ); // e
1988  _GG = _mm_sqrt_ps(_sse_rotp_ps(_ax,_ax,_AX,_AX)); // sqrt(e*e + sin(d-p)^2) - gamma regulator
1989  _gg = _mm_mul_ps(_mm_sub_ps(_05,_ni),
1990  _mm_sub_ps(_1,_FF)); // network index correction
1991  _GG = _mm_sub_ps(_mm_sub_ps(_09,_GG),_gg); // 0.9-sqrt(e*e + sin(d-p)^2) - (0.5-ni)*(1-a)
1992  _GG = _mm_mul_ps(_mm_mul_ps(_IE,_rG),_GG); // gamma regulator value
1993  _GG = _mm_mul_ps(_mm_mul_ps(_IE,_4),_GG); // enhanced gamma regulator value
1994 
1995  _gg = _mm_mul_ps(_mm_sub_ps(_IE,_ff),_kG); // AP threshold
1996  _gg = _mm_mul_ps(_ni,_gg); // network index correction
1997  _nn = _mm_and_ps(_mm_cmpgt_ps(_ff,_gg),_1); // AP regulator --> kill flag
1998  _ee = _mm_mul_ps(_sse_dot4_ps(_pep,_bb4),_nn); // regulated + amplitude: DO NOT UPDATE _ee !!!
1999  _sse_cpf4_ps(_pxi,_pep,_ee); // store + projection
2000 
2001  _mm = _mm_and_ps(_mm_cmpgt_ps(_ff,_GG),_nn); // gamma regulator condition
2002 
2003  _gg = _mm_andnot_ps(_sm,_mm_sub_ps(_NI,_ni)); // |NI-ni|
2004  _gg = _mm_sub_ps(_IE,_mm_mul_ps(_gg,_FF)); // IE-|NI-ni| * |fx|/|f+|
2005  _nn = _mm_and_ps(_mm_cmplt_ps(_gg,_D0),_mm); // 00-phase regulator flag
2006  _mm = _mm_and_ps(_mm_cmplt_ps(_gg,_D9),_mm); // 90-phase regulator flag
2007  _nn = _mm_mul_ps(_nn,cirw); // zero nn if circular wave
2008  _mm = _mm_mul_ps(_mm,linw); // zero mm if linear wave
2009  _EE = _mm_mul_ps(_en,_nn); // 00 x-projection regulator: DO NOT UPDATE _EE !!!
2010  _sse_add4_ps(_pxi,_pex,_EE); // updated 00-phase response
2011  _sse_cpf4_ps(_pXI,_BB4,_mm); // updated 90-phase response
2012 
2013  _nn = _mm_mul_ps(_nn,_PW); // kill 1 dof for psiwave
2014  *_rr = _mm_add_ps(_mm_add_ps(_mm,_nn),_1); // store G-noise bias
2015  _coP++;_siP++;_chr++;_xx++;_yy++;_zz++,_rr++; // advance pointers
2016 
2017  _cc = _mm_add_ps(_cc,_ee); // + a*a* cos(t)
2018  _ss = _mm_add_ps(_ss,_EE); // + a*a* sin(t)
2019 
2020  _ll = _sse_rotm_ps(*_coD,*_coD,*_siD,*_siD); // cos(2d)
2021  _LL = _sse_rotp_ps(*_siD,*_coD,*_siD,*_coD); // sin(2d)
2022  _ec = _sse_rotm_ps(_co,_ll,_si,_LL); // C[-2p] term (si -> -si)
2023  _EC = _sse_rotp_ps(_si,_ll,_co,_LL); // S[-2p] term (si -> -si)
2024  _c2 = _mm_add_ps(_c2,_ec); // accumulate C[-2p]
2025  _s2 = _mm_sub_ps(_s2,_EC); // accumulate S[-2p] (si -> -si)
2026  _coD++;_siD++; // advance pointers
2027  }
2028 
2029  _mm_storeu_ps(vvv,_c2);
2030  c2p = vvv[0]+vvv[1]+vvv[2]+vvv[3]; // cos[-2p]
2031  _mm_storeu_ps(vvv,_s2);
2032  s2p = vvv[0]+vvv[1]+vvv[2]+vvv[3]; // sin[-2p]
2033  gg = sqrt(c2p*c2p+s2p*s2p+1.e-16);
2034  _si = _mm_set1_ps(s2p/gg); // sin[-2p]
2035  _co = _mm_set1_ps(c2p/gg); // cos[-2p]
2036 
2037  if(psiwave) { // reconstruct p-wave
2038  _zz = (__m128*) zzz.data; // store z-amplitude
2039  _siD = (__m128*) siDPF.data; // DPF sin
2040  _coD = (__m128*) coDPF.data; // DPF cos
2041 
2042  _mm_storeu_ps(vvv,_cc);
2043  cc = (vvv[0]+vvv[1]+vvv[2]+vvv[3]); // cos[t]
2044  _mm_storeu_ps(vvv,_ss);
2045  ss = (vvv[0]+vvv[1]+vvv[2]+vvv[3]); // sin[t]
2046  gg = sqrt(cc*cc+ss*ss+1.e-16);
2047  _si = _mm_set1_ps(ss/gg); // sin[-2p]
2048  _co = _mm_set1_ps(cc/gg); // cos[-2p]
2049 
2050  for(j=0; j<m4; j+=4) { // fix chirality and average vector
2051  int jf = j*f_; // sse index increment
2052  __m128* _pxi = _pp+jf;
2053  __m128* _pXI = _PP+jf;
2054 
2055  _sse_rot4p_ps(_ep+jf,&_co,_ex+jf,&_si,_bb4); // rotate e+,ex by theta
2056  _sse_cpf4_ps(_pxi,_bb4,_sse_dot4_ps(_pxi,_bb4));// 0 residual: do not enforce sign
2057 
2058 /* dispersion correction code
2059  _cc = _sse_rotm_ps(*_coD,*_coD,*_siD,*_siD); // cos(2d)
2060  _ss = _sse_rotp_ps(*_siD,*_coD,*_siD,*_coD); // sin(2d)
2061  _ss = _sse_rotp_ps(_si,_cc,_ss,_co); // S[2d-2p] term
2062  _sse_cpf4_ps(_pxi,_pep,_sse_dot4_ps(_pep,_pxi)); // store + projection
2063  _sse_sub4_ps(_pxi,_pex,_mm_mul_ps(_ss,*_zz)); // subtract 0-phase x response
2064  _coD++;_siD++;_zz++; // advance pointers
2065 */
2066  }
2067  }
2068 
2069  // orthogonalize responces before calculate sky statistics
2070 
2071  _siO = (__m128*) siORT.data; // ort4 sin
2072  _coO = (__m128*) coORT.data; // ort4 cos
2073  _siP = (__m128*) siPHS.data; // phase sin
2074  _coP = (__m128*) coPHS.data; // phase cos
2075  _chr = (__m128*) chir.data; // chirality (sign of ellipticity)
2076 
2077  _mm_storeu_ps(vvv,_eqQ);
2078  _mm_storeu_ps(uuu,_qQ2);
2079  eLp = 2.*(vvv[0]+vvv[1]+vvv[2]+vvv[3]); // average ellipticity
2080  eLp/= uuu[0]+uuu[1]+uuu[2]+uuu[3]+1.e-16; // average ellipticity
2081  _mm_storeu_ps(vvv,_ch);
2082  CHR = vvv[0]+vvv[1]+vvv[2]+vvv[3]; // average chirality
2083  ff = CHR>0. ? 1. : -1.; // chirality
2084  _ch = _mm_set1_ps(ff);
2085  _gg = rndwave ? _oo : _mm_set1_ps(0.5); // check or not chirality
2086 
2087  for(j=0; j<m4; j+=4) { // Orthogonalize
2088  int jf = j*f_; // sse index increment
2089  __m128* _pbb = _bb+jf;
2090  __m128* _pBB = _BB+jf;
2091  __m128* _pxp = _xp+jf;
2092  __m128* _pXP = _XP+jf;
2093  __m128* _pxi = _pp+jf;
2094  __m128* _pXI = _PP+jf;
2095 
2096  _ee = _mm_sub_ps(_mm_mul_ps(_ch,*_chr),_1); // -1 or 0
2097  _sse_add4_ps(_pXI,_pXI,_mm_mul_ps(_ee,_gg)); // set chirality
2098 
2099  _co = _sse_rotm_ps(*_coO,*_coP,*_siO,*_siP); // cos(ort4+phase)
2100  _si = _sse_rotp_ps(*_siO,*_coP,*_siP,*_coO); // sin(ort4+phase)
2101  _sse_rot4m_ps(_pxi,&_co,_pXI,&_si,_pxp); // get 00 phase response
2102  _sse_rot4p_ps(_pXI,&_co,_pxi,&_si,_pXP); // get 90 phase response
2103  _sse_ort4_ps(_pxp,_pXP,_siO,_coO); // dual-stream phase sin and cos
2104  _sse_rot4p_ps(_pxp,_coO,_pXP,_siO,_pxi); // get 00 standard response
2105  _sse_rot4m_ps(_pXP,_coO,_pxp,_siO,_pXI); // get 90 standard response
2106  _sse_rot4p_ps(_pbb,_coO,_pBB,_siO,_ww+jf); // get 00 phase data vector
2107  _sse_rot4m_ps(_pBB,_coO,_pbb,_siO,_WW+jf); // get 90 phase data vector
2108  _coO++; _siO++; _coP++; _siP++; _chr++; // increment to next 4 pixels
2109  }
2110 
2111 // calculation of likelihood statistics
2112 
2113  Nm = Lo;
2114 
2115  _rr = (__m128*) rrr.data; // regulator flag
2116 
2117  Lo = Co = Eo = Lr = Cr = Do = 0.;
2118  for(j=0; j<m4; j+=4) {
2119  int jf = j*f_; // sse index increment
2120 
2121  __m128* _pbb = _bb+jf;
2122  __m128* _pBB = _BB+jf;
2123  __m128* _pxi = _pp+jf;
2124  __m128* _pXI = _PP+jf;
2125  __m128* _pww = _ww+jf;
2126  __m128* _pWW = _WW+jf;
2127 
2128  _ee = _sse_abs4_ps(_pbb); // 00 total energy
2129  _ll = _mm_add_ps(_sse_abs4_ps(_pxi),_oo); // standard 00 likelihood
2130  _ed = _sse_ed4_ps(_pww,_pxi,_ll); // 00 energy disbalance
2131  _ec = _sse_ecoh4_ps(_pww,_pxi,_ll); // coherent energy
2132 
2133  _EE = _sse_abs4_ps(_pBB); // 90 total energy
2134  _LL = _mm_add_ps(_sse_abs4_ps(_pXI),_oo); // standard 90 likelihood
2135  _ED = _sse_ed4_ps(_pWW,_pXI,_LL); // 90 energy disbalance
2136  _EC = _sse_ecoh4_ps(_pWW,_pXI,_LL); // coherent energy
2137 
2138  _ll = _mm_add_ps(_ll,_LL); // total signal energy
2139  _ec = _mm_add_ps(_ec,_EC); // total coherent energy
2140  _ed = _mm_add_ps(_ed,_ED); // total energy disbalance
2141  _ee = _mm_add_ps(_ee,_EE); // total energy
2142 
2143  _mm_storeu_ps(vvv,_ee);
2144  Eo += vvv[0]+vvv[1]+vvv[2]+vvv[3]; // total network energy
2145  _mm_storeu_ps(vvv,_ec);
2146  Co += vvv[0]+vvv[1]+vvv[2]+vvv[3]; // network coherent energy
2147  _mm_storeu_ps(vvv,_ed);
2148  Do += vvv[0]+vvv[1]+vvv[2]+vvv[3]; // network energy disbalance
2149  _mm_storeu_ps(vvv,_ll);
2150  Lo += vvv[0]+vvv[1]+vvv[2]+vvv[3]; // network likelihood
2151 
2152 // calculate sky statistics
2153 
2154  _en = _mm_andnot_ps(_sm,_mm_sub_ps(_ee,_ll)); // pixel null energy
2155  _en = _mm_add_ps(_en,*_rr); _rr++; // Gaussian bias added
2156  _EC = _mm_andnot_ps(_sm,_ec); // | coherent energy |
2157  _cc = _mm_add_ps(_mm_add_ps(_EC,_ed),_en); // |C|+null+ed
2158  _cc = _mm_div_ps(_mm_sub_ps(_ec,_ed),_cc); // network correlation
2159 
2160  _mm_storeu_ps(vvv,_mm_mul_ps(_ll,_cc));
2161  Lr += vvv[0]+vvv[1]+vvv[2]+vvv[3]; // reduced likelihood
2162  _mm_storeu_ps(vvv,_mm_mul_ps(_ec,_cc));
2163  Cr += vvv[0]+vvv[1]+vvv[2]+vvv[3]; // reduced coherent energy
2164 
2165  // _mm_storeu_ps(vvv,_gg);
2166  // _mm_storeu_ps(uuu,_ff);
2167  // if(hist && (le-lb) && vvv[0]!=0) hist->Fill(vvv[0], uuu[0]);
2168  // if(hist && (le-lb) && vvv[1]!=0) hist->Fill(vvv[1], uuu[1]);
2169  // if(hist && (le-lb) && vvv[2]!=0) hist->Fill(vvv[2], uuu[2]);
2170  // if(hist && (le-lb) && vvv[3]!=0) hist->Fill(vvv[3], uuu[3]);
2171  }
2172 
2173  aa = Eo>0. ? Lo/Eo : 0.; // detection skystat
2174  AA = Eo>0. ? Lr/Eo : 0.; // detection skystat
2175  if(!mra) skyProb.data[l] = this->delta<0 ? aa : AA;
2176 
2177  if(ID==id || mra) { // antenna patterns
2178  float ll,LL,Et;
2179  ff = FF = Et = Nm = 0.;
2180  for(j=0; j<m; j++) {
2181  int jf = j*f_; // sse pointer increment
2182  ee = _sse_abs_ps(_bb+jf,_BB+jf); // total energy
2183  if(ee<En) continue; // skip sub-threshold PC
2184  ff += _sse_abs_ps(_fp+jf)*ee; // |f+|^2
2185  FF += _sse_abs_ps(_fx+jf)*ee; // |fx|^2
2186  ll = _sse_mul_ps(_pp+jf,_pp+jf,_bb4)+1.e-12; // 00 likelihood
2187  LL = _sse_mul_ps(_PP+jf,_PP+jf,_BB4)+1.e-12; // 90 likelihood
2188  Nm+= _sse_abs_ps(_bb4)/ll+_sse_abs_ps(_BB4)/LL; // network index*L
2189  Et+= ll+LL;
2190  }
2191  Nm = Et>0.&&Nm>0 ? Et/Nm : 0.;
2192  ff = Eo>0. ? 2*ff/Eo : 0.;
2193  FF = Eo>0. ? 2*FF/Eo : 0.;
2194  }
2195 
2196  if(ID==id && !mra) { // fill skymaps
2197  Eo += 0.001; Cr += 0.001;
2198  this->nAntenaPrior.set(l, sqrt(ff+FF)); // fill sensitivity
2199  this->nSensitivity.set(l, sqrt(ff+FF));
2200  this->nAlignment.set(l, sqrt(FF/ff));
2201  this->nLikelihood.set(l, Lo/Eo);
2202  this->nNullEnergy.set(l, (Eo-Lo)/Eo);
2203  this->nCorrEnergy.set(l, Cr/Eo);
2204  this->nCorrelation.set(l, Ln);
2205  this->nSkyStat.set(l, AA);
2206  this->nProbability.set(l, skyProb.data[l]);
2207  this->nDisbalance.set(l, 2*Do/Eo);
2208  this->nEllipticity.set(l, eLp);
2209  this->nPolarisation.set(l, -atan2(s2p,c2p)*180./PI/4.);
2210  this->nNetIndex.set(l, Nm);
2211  }
2212 
2213  if(prior && !mra && ID!=id) { // used in getSkyArea with prior
2214  ff = FF = 0.;
2215  for(j=0; j<m; j++) {
2216  int jf = j*f_; // sse pointer increment
2217  ee = _sse_abs_ps(_bb+jf,_BB+jf); // total energy
2218  if(ee<En) continue; // skip sub-threshold PC
2219  ff += _sse_abs_ps(_fp+jf)*ee; // |f+|^2
2220  FF += _sse_abs_ps(_fx+jf)*ee; // |fx|^2
2221  }
2222  ff = Eo>0. ? 2*ff/Eo : 0.;
2223  FF = Eo>0. ? 2*FF/Eo : 0.;
2224  this->nAntenaPrior.set(l, sqrt(ff+FF)); // fill sensitivity
2225  }
2226 
2227  if(AA>STAT && !mra) {STAT=AA; lm=l; Vm=m;}
2228  }
2229 
2230  if(STAT==0. || (mra && AA<=0.)) {
2231  pwc->sCuts[id-1]=1; count=0; // reject cluster
2232  pwc->clean(id); continue;
2233  }
2234 
2235  if(le-lb) {lb=le=lm; goto optsky;} // process all pixels at opt sky location
2236 
2237  double Em_all,Ln_all,Ls_all,Lr_all;
2238  double Eo_all,Lo_all,Co_all,Do_all,cc_all;
2239  float GNoise = 0.;
2240 
2241  if(!mra) { // all resolution pixels
2242  Em_all=Ls_all=Ln_all = 0;
2243  Eo_all = Eo; // multiresolution energy
2244  Lo_all = Lo; // multiresolution likelihood
2245  Lr_all = Lr; // reduced likelihood
2246  Co_all = Co; // multiresolution coherent energy
2247  Do_all = Do*2; // multiresolution ED
2248  pwc->cData[id-1].skySize = m; // event size in the skyloop
2249  pwc->cData[id-1].likesky = Lo; // multires Likelihood - stored in neted[3]
2250  vint = &(pwc->cList[id-1]); // pixel list
2251  for(j=0; j<vint->size(); j++) { // initialization for all pixels
2252  pix = pwc->getPixel(id,j);
2253  pix->core = false;
2254  pix->likelihood = 0.;
2255  }
2256 
2257  for(j=0; j<Vm; j++) { // loop over significant pixels
2258  pix = pwc->getPixel(id,pI[pJ[j]]);
2259  int jf = j*f_; // source sse pointer increment
2260  ee = _sse_abs_ps(_bb+jf,_BB+jf);
2261  pix->likelihood = ee/2; // total pixel energy
2262  em = _sse_maxE_ps(_bb+jf,_BB+jf); // dominant pixel likelihood
2263  Ls_all += ee-em; // subnetwork Energy
2264  Em_all += em; // maximum detector energy
2265  if(ee-em>Es) Ln_all += ee; // reduced network energy
2266  GNoise += rrr.data[j]; // counter for G-noise bias
2267  }
2268 
2269  pwc->cData[id-1].skyStat = Lr/Eo; // all-resolution sky statistic (saved in norm)
2270  cc_all = Lr/Lo; // multiresolution cc
2271 
2272  Ns = Eo_all-Lo_all+Do+GNoise; // NULL stream with G-noise correction
2273  gg = Ls_all*Ln_all/Em_all; // L: all-sky subnet "energy"
2274  pwc->cData[id-1].SUBNET = gg/(fabs(gg)+Ns); // like2G sub-network statistic (saved in netcc[3])
2275 
2276  mra=true; goto optsky; // process mra pixels at opt sky location
2277  }
2278 
2279  if(AA<this->netCC || !m) {
2280  pwc->sCuts[id-1]=1; count=0; // reject cluster
2281  pwc->clean(id); continue;
2282  }
2283 
2284 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2285 // detection statistics at selected sky location
2286 // wavelet domain: netcc, ecor
2287 // time domain: energy, likelihood, xSNR, sSNR, neted
2288 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2289 
2290  double Em_mra,Ln_mra,Ls_mra;
2291  double Eo_mra,Lo_mra,Co_mra;
2292 
2293  M=m; m=0; GNoise=0.;
2294  Em_mra=Ln_mra=Ls_mra = 0;
2295  for(j=0; j<M; j++) { // loop over principle components
2296  pix = pwc->getPixel(id,pI[pJ[j]]);
2297  int jf = j*f_; // source sse pointer increment
2298  float* psi = siORT.data+j;
2299  float* pco = coORT.data+j;
2300  __m128* _pxi = _xi+jf;
2301  __m128* _pXI = _XI+jf;
2302  ee = _sse_abs_ps(_bb+jf,_BB+jf); // total pixel energy
2303  em = _sse_maxE_ps(_bb+jf,_BB+jf); // dominant pixel energy
2304  Em_mra += em; // maximum detector energy
2305  Ls_mra += ee-em; // subnetwork energy
2306  if(ee-em>Es) Ln_mra += ee; // reduced network energy
2307  GNoise += rrr.data[j]; // counter for G-noise bias
2308  if(em>0) m++; // counter for subnet pixels
2309  pix->core = true;
2310 
2311  _sse_rotm_ps(_pxi,pco,_pXI, psi,_bb4); // invDSP 00 response
2312  _sse_rotp_ps(_pXI,pco,_pxi, psi,_BB4); // invDSP 90 response
2313 
2314  for(i=0; i<nIFO; i++) {
2315  pix->setdata(double(bb.data[j*NIFO+i]),'W',i); // store 00 whitened PC
2316  pix->setdata(double(BB.data[j*NIFO+i]),'U',i); // store 90 whitened PC
2317  pix->setdata(double(bb.data[V4*NIFO+i]),'S',i); // 00 reconstructed whitened response
2318  pix->setdata(double(BB.data[V4*NIFO+i]),'P',i); // 90 reconstructed whitened response
2319  }
2320  }
2321 
2322  if(!m) { // zero reconstructed response
2323  pwc->sCuts[id-1]=1; count=0; // reject cluster
2324  pwc->clean(id); continue;
2325  }
2326 
2327  Em=Eo; Lm=Lo; Do*=2; // copy all-pixel statistics
2328  Eo_mra=Eo; Lo_mra=Lo; Co_mra=Co;
2329 
2330  pwc->cData[id-1].netcc = Lr/Eo; // network cc with mres correction (saved in netcc[0])
2331  Nc = Eo-Lo+Do/2+GNoise; // NULL stream with correction
2332  gg = Ls_mra*Ln_mra/Em_mra; // L: MRA subnet "energy"
2333  pwc->cData[id-1].subnet = gg/(fabs(gg)+Nc); // mra/sra sub-energy statistic (saved in netcc[2])
2334  pwc->cData[id-1].skycc = Co/(fabs(Co)+Nc); // classic SRA/MRA cc (saved in netcc[1])
2335 
2336  //if(hist) hist->Fill(pwc->cData[id-1].skycc,pwc->cData[id-1].netcc);
2337 
2338 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2339 // fill in detection statistics, prepare output data
2340 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2341 
2342 // fill in backward delay configuration
2343 
2344  vtof->clear();
2345  NETX (vtof->push_back(ml[0][lm]); ,
2346  vtof->push_back(ml[1][lm]); ,
2347  vtof->push_back(ml[2][lm]); ,
2348  vtof->push_back(ml[3][lm]); ,
2349  vtof->push_back(ml[4][lm]); ,
2350  vtof->push_back(ml[5][lm]); ,
2351  vtof->push_back(ml[6][lm]); ,
2352  vtof->push_back(ml[7][lm]); )
2353 
2354  // need to fix a problem below
2355  if((wfsave)||(mdcListSize() && !lag)) { // if wfsave=false only simulated wf are saved
2356  int m0d = mureana ? 0 : 1;
2357  if(this->getMRAwave(id,lag,'S',m0d,true)) { // reconstruct whitened shifted pd->waveForm
2358  detector* pd;
2359  for(i=0; i<nIFO; i++) { // loop over detectors
2360  pd = this->getifo(i);
2361  pd->RWFID.push_back(id); // save cluster ID
2363  *wf = pd->waveForm;
2364  wf->start(pwc->start+pd->waveForm.start());
2365  pd->RWFP.push_back(wf);
2366  }
2367  }
2368  if(this->getMRAwave(id,lag,'s',m0d,true)) { // reconstruct strain shifted pd->waveForm
2369  detector* pd;
2370  for(i=0; i<nIFO; i++) { // loop over detectors
2371  pd = this->getifo(i);
2372  pd->RWFID.push_back(-id); // save cluster -ID
2374  *wf = pd->waveForm;
2375  wf->start(pwc->start+pd->waveForm.start());
2376  pd->RWFP.push_back(wf);
2377  }
2378  }
2379  }
2380 
2381  Lo = Eo = To = Fo = No = 0.;
2382  for(i=0; i<nIFO; i++) {
2383  detector* d = this->getifo(i);
2384  d->sSNR = d->xSNR = d->null = d->enrg = 0.;
2385  }
2386 
2387  int two = mureana ? 1 : 2;
2388  int m0d = mureana ? 0 : -1;
2389  while(m0d < 2) {
2390  this->getMRAwave(id,lag,'W',m0d);
2391  this->getMRAwave(id,lag,'S',m0d);
2392  for(i=0; i<nIFO; i++) {
2393  detector* d = this->getifo(i);
2394  d->waveNull = d->waveBand;
2395  d->waveNull-= d->waveForm;
2396  float sSNR = d->get_SS()/two;
2397  float xSNR = d->get_XS()/two;
2398  float null = d->get_NN()/two;
2399  float enrg = d->get_XX()/two;
2400  d->sSNR += sSNR;
2401  d->xSNR += xSNR;
2402  d->null += null;
2403  d->enrg += enrg;
2404  To += sSNR*d->getWFtime();
2405  Fo += sSNR*d->getWFfreq();
2406  Lo += sSNR;
2407  Eo += enrg;
2408  No += null;
2409  }
2410  m0d += 2;
2411  }
2412  To /= Lo; Fo /= Lo;
2413 
2414  gg = Lo/Lo_mra;
2415  Co = Co*gg;
2416  Cr = Cr*gg;
2417  Do = Do*gg;
2418  Nc = Nc*gg;
2419 
2420  pwc->cData[id-1].likenet = Lo;
2421  pwc->cData[id-1].energy = Eo; // energy of the event - stored in neted[2]
2422  pwc->cData[id-1].enrgsky = Eo_all; // energy in the skyloop - stored in neted[4]
2423  pwc->cData[id-1].netecor = Co;
2424  pwc->cData[id-1].netnull = No+GNoise/2; // NULL with Gauss correction - stored in neted[1]
2425  pwc->cData[id-1].netED = Do; // network energy disbalance - stored in neted[0]
2426  pwc->cData[id-1].netRHO = sqrt(Co*cc_all/(nIFO-1.)); // signal rho - stored in rho[0]
2427  pwc->cData[id-1].netrho = sqrt(Cr/(nIFO-1.)); // reguced rho - stored in rho[1]
2428  pwc->cData[id-1].cTime = To;
2429  pwc->cData[id-1].cFreq = Fo;
2430  pwc->cData[id-1].theta = nLikelihood.getTheta(lm);
2431  pwc->cData[id-1].phi = nLikelihood.getPhi(lm);
2432  pwc->cData[id-1].gNET = sqrt(ff+FF);
2433  pwc->cData[id-1].aNET = sqrt(FF/ff);
2434  pwc->cData[id-1].iNET = Nm;
2435  pwc->cData[id-1].iota = Ns;
2436  pwc->cData[id-1].psi = -atan2(s2p,c2p)*180./PI/4.;
2437  pwc->cData[id-1].ellipticity = eLp;
2438 
2439  if(this->optim) pwc->cRate[id-1][0] = optR; // update optimal resolution
2440 
2441  if(sqrt(Co/(nIFO-1.))<this->netRHO || pwc->cData[id-1].skycc<this->netCC) {
2442  pwc->sCuts[id-1]=1; count=0; // reject cluster
2443  pwc->clean(id); continue;
2444  }
2445 
2446  cc = pwc->cData[id-1].skycc;
2447  if(hist) {
2448  printf("id|lm %3d|%6d rho=%4.2f cc: %5.3f|%5.3f|%5.3f|%5.3f \n",
2449  int(id),int(lm),sqrt(Co/(nIFO-1)),STAT,cc,pwc->cData[id-1].netcc,AA);
2450  printf(" (t,p)=(%4.1f|%4.1f) T|F: %6.3f|%4.1f L: %5.1f|%5.1f|%5.1f E: %5.1f|%5.1f|%5.1f \n",
2451  nLikelihood.getTheta(l),nLikelihood.getPhi(l),To,Fo,Lo,Lo_mra,Lo_all,Eo,Em,Eo_all);
2452  printf(" D|N: %4.1f|%4.1f|%4.1f Vm|m=%3d|%3d subnet=%4.3f|%4.3f \n",
2453  Do,No,Nc,int(Vm),int(M),pwc->cData[id-1].subnet,pwc->cData[id-1].SUBNET);
2454  hist->Fill(pwc->cData[id-1].subnet,pwc->cData[id-1].SUBNET);
2455  }
2456  count++;
2457 
2458 // calculation of error regions
2459 
2460  pwc->p_Ind[id-1].push_back(m);
2461  double T = To+pwc->start; // trigger time
2462  std::vector<float> sArea;
2463  pwc->sArea.push_back(sArea);
2464  pwc->p_Map.push_back(sArea);
2465 
2466  skyProb *= Lo;
2467  //double rMs = Ns/(nIFO*Vm);
2468  double rMs = this->delta<0 ? 0 : 2;
2469  if(iID<=0 || ID==id) getSkyArea(id,lag,T,rMs); // calculate error regions
2470 
2471 // calculation of chirp mass
2472 
2473  pwc->cData[id-1].mchirp = 0;
2474  pwc->cData[id-1].mchirperr = 0;
2475  pwc->cData[id-1].tmrgr = 0;
2476  pwc->cData[id-1].tmrgrerr = 0;
2477  pwc->cData[id-1].chi2chirp = 0;
2478 
2479  if(m_chirp) { // work only for MRA
2480  ee = pwc->mchirp(id);
2481  cc = Co_all/(fabs(Co_all)+ee); // chirp cc
2482  printf("mchirp : %d %g %.2e %.3f %.3f %.3f %.3f \n\n",
2483  int(id),cc,pwc->cData[id-1].mchirp,
2484  pwc->cData[id-1].mchirperr, pwc->cData[id-1].tmrgr,
2485  pwc->cData[id-1].tmrgrerr, pwc->cData[id-1].chi2chirp);
2486  }
2487 
2488  if(ID==id && !EFEC) {
2489  this->nSensitivity.gps = T;
2490  this->nAlignment.gps = T;
2491  this->nDisbalance.gps = T;
2492  this->nLikelihood.gps = T;
2493  this->nNullEnergy.gps = T;
2494  this->nCorrEnergy.gps = T;
2495  this->nCorrelation.gps = T;
2496  this->nSkyStat.gps = T;
2497  this->nEllipticity.gps = T;
2498  this->nPolarisation.gps= T;
2499  this->nNetIndex.gps = T;
2500  }
2501 
2502  pwc->sCuts[id-1] = -1;
2503  pwc->clean(id);
2504  } // end of loop over clusters
2505 
2506  return count;
2507 }
2508 
2509 //: operator =
2510 
2512 {
2513  this->wfsave = value.wfsave;
2514  this->MRA = value.MRA;
2515  this->nRun = value.nRun;
2516  this->nLag = value.nLag;
2517  this->nSky = value.nSky;
2518  this->mIFO = value.mIFO;
2519  this->Step = value.Step;
2520  this->Edge = value.Edge;
2521  this->gNET = value.gNET;
2522  this->aNET = value.aNET;
2523  this->iNET = value.iNET;
2524  this->eCOR = value.eCOR;
2525  this->e2or = value.e2or;
2526  this->acor = value.acor;
2527  this->norm = value.norm;
2528  this->pOUT = false;
2529  this->local = value.local;
2530  this->EFEC = value.EFEC;
2531  this->optim = value.optim;
2532  this->delta = value.delta;
2533  this->gamma = value.gamma;
2534  this->penalty = value.penalty;
2535  this->netCC = value.netCC;
2536  this->netRHO = value.netRHO;
2537  this->pSigma = value.pSigma;
2538  this->ifoList = value.ifoList;
2539  this->precision=value.precision;
2540 
2541  this->NDM.clear(); this->NDM=value.NDM;
2542  this->ifoList.clear(); this->ifoList=value.ifoList;
2543  this->ifoName.clear(); this->ifoName=value.ifoName;
2544  this->wc_List.clear(); this->wc_List=value.wc_List;
2545  this->segList.clear(); this->segList=value.segList;
2546  this->mdcList.clear(); this->mdcList=value.mdcList;
2547  this->livTime.clear(); this->livTime=value.livTime;
2548  this->mdcTime.clear(); this->mdcTime=value.mdcTime;
2549  this->mdcType.clear(); this->mdcType=value.mdcType;
2550  this->mdc__ID.clear(); this->mdc__ID=value.mdc__ID;
2551 
2552  return *this;
2553 }
2554 
2555 
2556 //**************************************************************************
2557 //: add detector to the network
2558 //**************************************************************************
2560 
2561  if(ifoList.size()==NIFO) {
2562  cout << "network::add - Error : max number of detectors is " << NIFO << endl;
2563  exit(1);
2564  }
2565 
2566  size_t i,n;
2567  vectorD v; v.clear();
2568  this->ifoList.push_back(d);
2569  this->ifoName.push_back(d->Name);
2570 
2571  n = ifoList.size();
2572  d->ifoID = n-1;
2573  for(i=0; i<n; i++) {
2574  v.push_back(0.);
2575  if(i<n-1) this->NDM[i].push_back(0);
2576  else this->NDM.push_back(v);
2577  }
2578 
2579 // cout<<"size="<<NDM.size()<<" size_0="<<NDM[0].size()<<endl;
2580  return ifoList.size();
2581 }
2582 
2583 //**************************************************************************
2584 // calculate WaveBurst pattern threshold for a given black pixel probability
2585 //**************************************************************************
2586 double network::THRESHOLD(double p, double shape) {
2587 // calculate WaveBurst energy threshold for a given black pixel probability p
2588 // and single detector Gamma distribution shape. TF data should contain pixel energy
2589  int N = ifoListSize();
2590  WSeries<double>* pw = &(getifo(0)->TFmap);
2591  size_t M = pw->maxLayer()+1;
2592  size_t nL = size_t(Edge*pw->wrate()*M);
2593  size_t nR = pw->size() - nL - 1;
2594  wavearray<double> w = *pw;
2595  for(int i=1; i<N; i++) w += getifo(i)->TFmap;
2596  double amp, avr, bbb, alp;
2597  avr = bbb = 0.;
2598  int nn = 0;
2599  for(int i=nL; i<nR; i++) { // get Gamma shape & mean
2600  amp = (double)w.data[i];
2601  if(amp>N*100) amp = N*100.;
2602  if(amp>0.001) {avr+=amp; bbb+=log(amp); nn++;}
2603  }
2604  avr = avr/nn; // Gamma mean
2605  alp = log(avr)-bbb/nn;
2606  alp = (3-alp+sqrt((alp-3)*(alp-3)+24*alp))/12./alp; // Gamma shape
2607  bbb = p*alp/shape; // corrected bpp
2608  //cout<<bbb<<" "<<avr<<" "<<alp<<" "<<shape<<" "<<iGamma(alp,bbb)<<endl;
2609  return avr*iGamma(alp,bbb)/alp/2;
2610 }
2611 
2612 //**************************************************************************
2613 // calculate WaveBurst energy threshold for a given black pixel probability
2614 //**************************************************************************
2615 double network::THRESHOLD(double p) {
2616 // calculate WaveBurst energy threshold for a given black pixel probability p
2617 // TF data should contain pixel energy
2618  int N = ifoListSize();
2619  WSeries<double>* pw = &(getifo(0)->TFmap);
2620  size_t M = pw->maxLayer()+1;
2621  size_t nL = size_t(Edge*pw->wrate()*M);
2622  size_t nR = pw->size() - nL;
2623  wavearray<double> w = *pw;
2624  for(int i=1; i<N; i++) w += getifo(i)->TFmap;
2625  double p10 = p*10.;
2626  double p00 = 0.0;
2627  double fff = w.wavecount(0.0001)/double(w.size());
2628  double v10 = w.waveSplit(nL,nR,nR-int(p10*fff*(nR-nL)));
2629  double val = w.waveSplit(nL,nR,nR-int(p*fff*(nR-nL)));
2630  double med = w.waveSplit(nL,nR,nR-int(0.2*fff*(nR-nL)));
2631  double m = 1.;
2632  while(p00<0.2) {p00 = 1-Gamma(N*m,med); m+=0.01;}
2633  if(m>1) m -= 0.01;
2634  printf("\nm\tM\tbpp\t0.2(D)\t0.2(G)\t0.01(D)\t0.01(G)\tbpp(D)\tbpp(G)\tN*log(m)\tfff\n");
2635  printf("%g\t%d\t%g\t%.3f\t%.3f\t%.3f\t%.3f\t%.3f\t%.3f\t%.3f\t\t%.3f\n\n",
2636  m,M,p,med,iGamma(N*m,0.2),v10,iGamma(N*m,p10),val,iGamma(N*m,p),N*log(m),fff);
2637  return (iGamma(N*m,p)+val)*0.3+N*log(m);
2638 }
2639 
2640 
2641 //**************************************************************************
2642 // calculate WaveBurst threshold as a function of resolution and maximum delay (used by 1G)
2643 //**************************************************************************
2644 double network::threshold(double p, double t)
2645 {
2646  size_t I;
2647  size_t K = ifoListSize();
2648  double n = 1.;
2649  if(getifo(0) && t>0. && K) {
2650  I = getifo(0)->TFmap.maxLayer()+1; // number of wavelet layers
2651  n = 2*t*getifo(0)->TFmap.rate()/I + 1;
2652  if(!getifo(0)->TFmap.size()) n = 1.;
2653  }
2654  else if(t < 0.) n = -t; // special case: n=-t
2655  return sqrt(iGamma1G(K/2.,1.-(p/2.)/pow(n,K/2.))/K);
2656 }
2657 
2658 void network::printwc(size_t n) {
2659  netcluster* p = this->getwc(n);
2660  int iTYPE = this->MRA ? 0 : 1;
2661  wavearray<double> cid = p->get((char*)"ID",0,'S',iTYPE);
2662  wavearray<double> vol = p->get((char*)"volume",0,'S',iTYPE);
2663  wavearray<double> siz = p->get((char*)"size",0,'S',iTYPE);
2664  wavearray<double> lik = p->get((char*)"likelihood",0,'S',iTYPE);
2665  wavearray<double> rat = p->get((char*)"rate",0,'S',iTYPE);
2666  wavearray<double> tim = p->get((char*)"time",1,'L',0);
2667  wavearray<double> T_o = p->get((char*)"time",0,'L',0);
2668  wavearray<double> frq = p->get((char*)"frequency",1,'L',0);
2669  wavearray<double> rho = p->get((char*)"subrho",0,'S',0);
2670  wavearray<double> sub = p->get((char*)"subnet",0,'S',0);
2671 
2672  if(cid.size() != rho.size())
2673  cout<<"wrong size "<<cid.size()<<" "<<rho.size()<<endl;
2674 
2675  for(size_t i=0; i<cid.size(); i++){
2676  printf("%2d %5.0f vol=%4.0f size=%4.0f like=%5.1e rho=%5.1f ",
2677  int(n),cid[i],vol[i],siz[i],lik[i],rho[i]);
2678  printf("sub=%3.2f rate=%4.0f time=%8.3f To=%8.3f freq=%5.0f\n",
2679  sub[i],rat[i],tim[i],T_o[i],frq[i]);
2680  }
2681 }
2682 
2683 
2684 //**************************************************************************
2685 //: initialize network sky maps
2686 //**************************************************************************
2687 void network::setSkyMaps(double sms,double t1,double t2,double p1,double p2)
2688 {
2689  size_t i;
2690  detector* d;
2691  skymap temp(sms,t1,t2,p1,p2);
2692  size_t m = temp.size();
2693  size_t n = this->ifoList.size();
2694 
2695  nSensitivity = temp;
2696  nAlignment = temp;
2697  nCorrelation = temp;
2698  nLikelihood = temp;
2699  nNullEnergy = temp;
2700  nPenalty = temp;
2701  nCorrEnergy = temp;
2702  nNetIndex = temp;
2703  nDisbalance = temp;
2704  nSkyStat = temp;
2705  nEllipticity = temp;
2706  nProbability = temp;
2707  nPolarisation= temp;
2708  nAntenaPrior = temp;
2709 
2710  for(i=0; i<n; i++) {
2711  d = ifoList[i];
2712  d->setTau(sms,t1,t2,p1,p2);
2713  d->setFpFx(sms,t1,t2,p1,p2);
2714  }
2715  skyProb.resize(m);
2716  skyENRG.resize(m);
2717  skyMask.resize(m); skyMask = 1;
2718  skyMaskCC.resize(0);
2719  skyHole.resize(m); skyHole = 1.;
2720  index.resize(m);
2721  for(i=0; i<m; i++) index.data[i] = i;
2722 }
2723 
2724 //**************************************************************************
2725 //: initialize network sky maps (healpix)
2726 //**************************************************************************
2727 void network::setSkyMaps(int healpix_order)
2728 {
2729  size_t i;
2730  detector* d;
2731  skymap temp(healpix_order);
2732  size_t m = temp.size();
2733  size_t n = this->ifoList.size();
2734 
2735  nSensitivity = temp;
2736  nAlignment = temp;
2737  nCorrelation = temp;
2738  nLikelihood = temp;
2739  nNullEnergy = temp;
2740  nPenalty = temp;
2741  nCorrEnergy = temp;
2742  nNetIndex = temp;
2743  nDisbalance = temp;
2744  nSkyStat = temp;
2745  nEllipticity = temp;
2746  nProbability = temp;
2747  nPolarisation= temp;
2748  nAntenaPrior = temp;
2749 
2750  for(i=0; i<n; i++) {
2751  d = ifoList[i];
2752  d->setTau(healpix_order);
2753  d->setFpFx(healpix_order);
2754  }
2755  skyProb.resize(m);
2756  skyENRG.resize(m);
2757  skyMask.resize(m); skyMask = 1;
2758  skyMaskCC.resize(0);
2759  skyHole.resize(m); skyHole = 1.;
2760  index.resize(m);
2761  for(i=0; i<m; i++) index.data[i] = i;
2762 }
2763 
2764 //**************************************************************************
2765 // calculate delays in frame or in barycenter (B) or fermat frame (F)
2766 //**************************************************************************
2767 void network::setDelay(const char* frame) {
2768  size_t n,nn,m,mm;
2769  skymap s = ifoList[0]->tau;
2770  size_t N = this->ifoList.size();
2771  double t,tm,gg;
2772 
2773  if(N < 2) return;
2774 
2775  s = 0.;
2776 
2777  if(strstr(frame,"FL") || strstr(frame,"FS")) { // "Fermat" frame
2778  tm = strstr(frame,"FS") ? 1. : 0.;
2779  gg = strstr(frame,"FS") ? 1. : -1.;
2780  nn = 0;
2781  mm = 1;
2782  for(n=0; n<N; n++) {
2783  for(m=n+1; m<N; m++) {
2784  s = ifoList[n]->tau;
2785  s -= ifoList[m]->tau;
2786  t = gg*(s.max()-s.min());
2787  if(t < tm) { tm=t; nn = n; mm = m; }
2788  }
2789  }
2790 
2791  s = ifoList[nn]->tau;
2792  s+= ifoList[mm]->tau;
2793  s*= 0.5;
2794  mIFO = 99;
2795  }
2796 
2797  else if(strstr(frame,"BC")) { // barycenter frame
2798  for(n=1; n<N; n++) s += ifoList[n]->tau;
2799  s *= 1./N;
2800  mIFO = 99;
2801  }
2802 
2803  else { // detector frame
2804  for(n=0; n<N; n++) {
2805  if(strstr(frame,getifo(n)->Name)) this->mIFO = n;
2806  }
2807  s = ifoList[this->mIFO]->tau;
2808  }
2809 
2810 
2811  for(n=0; n<N; n++) ifoList[n]->tau -= s;
2812  return;
2813 }
2814 
2815 //**************************************************************************
2816 // calculate maximum delay between detectors
2817 //**************************************************************************
2818 double network::getDelay(const char* name) {
2819  size_t i;
2820  size_t n = this->ifoList.size();
2821  double maxTau = -1.;
2822  double minTau = 1.;
2823  double tmax, tmin;
2824 
2825  if(n < 2) return 0.;
2826 
2827  tmax = tmin = 0.;
2828  for(i=0; i<n; i++) {
2829  tmax = ifoList[i]->tau.max();
2830  tmin = ifoList[i]->tau.min();
2831  if(tmax > maxTau) maxTau = tmax;
2832  if(tmin < minTau) minTau = tmin;
2833  }
2834  if(strstr(name,"min")) return minTau;
2835  if(strstr(name,"max")) return maxTau;
2836  if(strstr(name,"MAX")) return fabs(maxTau)>fabs(minTau) ? fabs(maxTau) : fabs(minTau);
2837  return (maxTau-minTau)/2.;
2838 }
2839 
2840 
2841 
2842 
2843 //***************************************************************
2844 //:set antenna pattern buffers in input detector
2845 //***************************************************************
2847 {
2848  size_t n = di->mFp.size();
2849  double a, b;
2850 
2851  di->fp.resize(n);
2852  di->fx.resize(n);
2853  di->ffp.resize(n);
2854  di->ffm.resize(n);
2855  di->fpx.resize(n);
2856 
2857  while(n-- >0) {
2858  a = di->mFp.get(n);
2859  b = di->mFx.get(n);
2860  di->fp.data[n] = a;
2861  di->fx.data[n] = b;
2862  di->ffp.data[n] = a*a+b*b;
2863  di->ffm.data[n] = a*a-b*b;
2864  di->fpx.data[n] = 2*a*b;
2865  }
2866 
2867  return;
2868 }
2869 
2870 //***************************************************************
2871 //:set antenna patterns in the DPF
2872 //***************************************************************
2874 {
2875  size_t M = this->ifoList.size(); // number of detectors
2876  if(M > NIFO) return;
2877 
2878  detector* D[NIFO];
2879 
2880  for(size_t m=0; m<M; m++) {
2881  D[m] = this->getifo(m);
2882  if(D[m]->mFp.size() != D[0]->mFp.size()) {
2883  cout<<"network::setIndex(): invalid detector skymaps\n";
2884  return;
2885  }
2886  this->setAntenna(D[m]);
2887  }
2888  return;
2889 }
2890 
2891 //***************************************************************
2892 //:set index array for delayed amplitudes, used with WDM delay filters
2893 // time delay convention: t+tau - arrival time at the center of Earth
2894 // ta1-tau0 - how much det1 should be delayed to be sinchronized with det0
2895 ///***************************************************************
2897 {
2898  double t;
2899  int i,ii;
2900  size_t n,m,l,k;
2901  size_t N = ifoList.size(); // number of detectors
2902 
2903  double tt[NIFO][NIFO];
2904  double TT[NIFO];
2905  int mm[NIFO][NIFO];
2906 
2907  if(N<2) {
2908  cout<<"network::setDelayIndex(): invalid network\n";
2909  return;
2910  }
2911 
2912  detector* dr[NIFO];
2913  for(n=0; n<N; n++) dr[n] = ifoList[n];
2914 
2915  size_t L = dr[0]->tau.size(); // skymap size
2916  this->rTDF = rate; // effective time-delay rate
2917 
2918  // if(pOUT) cout<<"filter size="<<this->filter.size()
2919  // <<" layers="<<I<<" delays="<<K<<" samples="<<dr[0]->nDFS<<endl;
2920 
2921  for(n=0; n<N; n++) {
2922  if(dr[n]->index.size() != L) {
2923  dr[n]->index.resize(L);
2924  }
2925  }
2926 
2927 // calculate time interval the di detector is delayed to be
2928 // sinchronized with dr
2929 // time delay > 0 - shift di right (future)
2930 // time delay < 0 - shift di left (past)
2931 
2932  this->nPenalty = dr[0]->tau;
2933  this->nNetIndex = dr[0]->tau;
2934 
2935  for(l=0; l<L; l++){
2936 
2937 // calculate time delay matrix
2938 // 0 d01 d02
2939 // d10 0 d12
2940 // d20 d21 0
2941 
2942  for(n=0; n<N; n++) {
2943  for(m=0; m<N; m++) {
2944  t = dr[n]->tau.get(l)-dr[m]->tau.get(l);
2945  i = t>0 ? int(t*rTDF+0.5) : int(t*rTDF-0.5);
2946  mm[n][m] = i;
2947  tt[n][m] = t*rTDF;
2948  }
2949  }
2950 
2951  for(n=0; n<N; n++) {
2952  TT[n] = 0.; // max delay for n-th configuration
2953  for(m=0; m<N; m++) {
2954  for(k=0; k<N; k++) {
2955  t = fabs(mm[n][k]-mm[n][m]-tt[m][k]);
2956  if(TT[n] < t) TT[n] = t;
2957  }
2958  }
2959  }
2960 
2961  t = 20.; i = N;
2962  for(m=0; m<N; m++) {
2963  if(t>TT[m]) { t = TT[m]; k = m; } // first best configuration
2964  }
2965  this->nPenalty.set(l,double(t));
2966 
2967  t = dr[k]->tau.get(l);
2968  if(mIFO<9) i = mm[k][this->mIFO];
2969  else i = t>0 ? int(t*rTDF+0.5) : int(t*rTDF-0.5);
2970 
2971 // 0 d01 d02 0 d01 d02
2972 // d10 0 d12 -> 0 d'01 d'02
2973 // d20 d21 0 0 d"01 d"02
2974 
2975  for(m=0; m<N; m++) {
2976  ii = mm[k][m]-i; // convert to time delay with respect to master IFO
2977  dr[m]->index.data[l] = ii;
2978  //if(m!=this->mIFO) this->nNetIndex.set(l,double(ii));
2979  }
2980  }
2981  return;
2982 }
2983 
2984 //**************************************************************************
2985 //:selection of clusters based on:
2986 // 'C' - network correlation coefficient with incoherent energy
2987 // 'c' - network correlation coefficient with null energy
2988 // 'r' - rho(ecor)
2989 // 'X' - correlated energy
2990 // 'x' - correlated energy - null energy (reduced corr energy)
2991 // 'l' - likelihood (biased)
2992 // 'L' - likelihood (unbiased)
2993 // 'A' - snr - null assymetry (double OR)
2994 // 'E' - snr - null energy (double OR)
2995 // 'a' - snr - null assymetry (edon)
2996 // 'e' - snr - null energy (edon)
2997 //**************************************************************************
2998 size_t network::netcut(double CUT, char cut, size_t core_size, int TYPE)
2999 {
3000  size_t M = this->ifoList.size(); // number of detectors
3001  if(!M) return 0;
3002 
3003  size_t i,j,k,n,m,K;
3004  size_t count = 0;
3005  size_t ID;
3006  size_t I = this->ifoList[0]->TFmap.maxLayer()+1;
3007  int R = int(this->ifoList[0]->getTFmap()->rate()/I+0.5);
3008  int type = this->optim ? R : TYPE; // likelihoodI
3009 
3010  wavearray<double> cid; // buffers for cluster ID
3011  wavearray<double> siz; // buffers for cluster size (core)
3012  wavearray<double> SIZ; // buffers for cluster size (core+halo)
3013  vector<wavearray<double> > snr(M); // buffers for total normalized energy
3014  vector<wavearray<double> > nul(M); // biased null stream
3015 
3016  double xcut,xnul,xsnr,amin,emin,like,LIKE;
3017  bool skip=false;
3018 
3019  for(j=0; j<nLag; j++) { // loop on time shifts
3020 
3021  if(!this->wc_List[j].size()) continue;
3022 
3023  cid = this->wc_List[j].get((char*)"ID",0,'S',type); // get cluster ID
3024  K = cid.size();
3025  if(!K) continue; // no clusters
3026 
3027  siz = this->wc_List[j].get((char*)"size",0,'S',type); // get cluster C size
3028  SIZ = this->wc_List[j].get((char*)"SIZE",0,'S',type); // get cluster C+H size
3029 
3030  for(m=0; m<M; m++) { // loop on detectors
3031  snr[m] = this->wc_List[j].get((char*)"energy",m+1,'S',type); // get total energy
3032  nul[m] = this->wc_List[j].get((char*)"null",m+1,'W',type); // get biased null stream
3033  }
3034 
3035  for(k=0; k<K; k++) { // loop on clusters
3036 
3037  if(siz.data[k] < core_size) continue; // skip small clusters
3038  i = ID = size_t(cid.data[k]+0.1);
3039 
3040  if(tYPe=='i' || tYPe=='s' || tYPe=='g' || tYPe=='r' ||
3041  tYPe=='I' || tYPe=='S' || tYPe=='G' || tYPe=='R') {
3042  skip = !this->SETNDM(i,j,true,type); // fill network data matrix
3043  }
3044  else if(tYPe=='b' || tYPe=='B' || tYPe=='E') {
3045  skip = !this->setndm(i,j,true,type); // fill network data matrix
3046  }
3047  else {
3048  skip = true;
3049  }
3050 
3051  if(skip) {
3052  cout<<"network::netcut: - undefined NDM matrix"<<endl;
3053  this->wc_List[j].ignore(ID); // reject cluster
3054  count += size_t(SIZ.data[k]+0.1); // count rejected pixels
3055  continue;
3056  }
3057 
3058  xnul = xsnr = like = LIKE = 0;
3059  emin = amin = 1.e99;
3060  for(n=0; n<M; n++) {
3061  xnul += this->getifo(n)->null;
3062  xsnr += snr[n].data[k];
3063  like += snr[n].data[k]-this->getifo(n)->null;
3064  xcut = snr[n].data[k]-this->getifo(n)->null;
3065  if(xcut < emin) emin = xcut;
3066  xcut = (xcut-this->getifo(n)->null)/snr[n].data[k];
3067  if(xcut < amin) amin = xcut;
3068  for(m=0; m<M; m++) {
3069  LIKE += this->getNDM(n,m);
3070  }
3071  }
3072 
3073  if(cut == 'A' || cut == 'E') { // double OR selection
3074  emin = amin = 1.e99;
3075  for(n=0; n<M; n++) {
3076  xcut = snr[n].data[k] - this->getifo(n)->null;
3077  if(like-xcut < emin) emin = like-xcut;
3078  xcut = 2*(like-xcut)/(xsnr-xcut) - 1.;
3079  if(xcut < amin) amin = xcut;
3080  }
3081  }
3082 
3083  xcut = 0;
3084  if(cut == 'c' || cut == 'C') xcut = this->eCOR/(xnul + fabs(this->eCOR)); // network x-correlation
3085  if(cut == 'x' || cut == 'X') xcut = this->eCOR/sqrt(fabs(this->eCOR)*M); // network correlated amplitude
3086  if(cut == 'l' || cut == 'L') xcut = like;
3087  if(cut == 'a' || cut == 'A') xcut = amin;
3088  if(cut == 'e' || cut == 'E') xcut = emin;
3089  if(cut == 'r' || cut == 'R') xcut = this->eCOR/sqrt((xnul + fabs(this->eCOR))*M);
3090 
3091  if(xcut < CUT) {
3092  this->wc_List[j].ignore(ID); // reject cluster
3093  count += size_t(SIZ.data[k]+0.1); // count rejected pixels
3094  continue;
3095  }
3096  else
3097  if(cut=='X') cout<<xcut<<cut<<": size="<<SIZ.data[k]<<" L="<<LIKE<<" ID="<<ID<<endl;
3098 
3099 
3100  if(pOUT) {
3101  printf("%3d %4d %7.2e %7.2e %7.2e %7.2e %7.2e %7.2e %7.2e\n",
3102  (int)n,(int)i,getNDM(0,0),getNDM(1,1),getNDM(2,2),getNDM(0,1),getNDM(0,2),getNDM(1,2),
3103  getNDM(0,0)+getNDM(1,1)+getNDM(2,2)+2*(getNDM(0,1)+getNDM(0,2)+getNDM(1,2)));
3104  }
3105  }
3106  }
3107  return count;
3108 }
3109 
3110 
3111 
3112 //**************************************************************************
3113 //: set rank statistic for pixels in network netcluster structure
3114 //**************************************************************************
3115 
3116 size_t network::setRank(double T, double F)
3117 {
3118  size_t j,m,n,V;
3119  size_t cOUNt = 0;
3120 
3121  size_t I = this->ifoList[0]->TFmap.maxLayer()+1;
3122  size_t R = size_t(this->ifoList[0]->getTFmap()->rate()/I+0.5);
3123  size_t N = this->ifoList[0]->getTFmap()->size();
3124  size_t M = this->ifoList.size(); // number of detectors
3125 
3126  int window = int(T*R+0.5)*I/2; // rank half-window size
3127  int offset = int(this->Edge*ifoList[0]->getTFmap()->rate()+0.5);
3128 
3129  double amp, rank;
3130  int inD, frst, last, nB, nT;
3131 
3132 // pointers
3133 
3134  double* ppp;
3135  std::vector<detector*> pDet; pDet.clear();
3136  std::vector<double*> pDat; pDat.clear();
3137 
3138  for(m=0; m<M; m++) {
3139  pDet.push_back(ifoList[m]);
3140  pDat.push_back(ifoList[m]->getTFmap()->data);
3141  }
3142 
3143  size_t wmode = pDet[0]->getTFmap()->w_mode;
3144  if(wmode != 1) return 0;
3145 
3146 // get index arrays for delayed amplitudes
3147 
3148  wavearray<double> cid; // buffers for cluster ID
3149  netpixel* pix;
3150 
3151  for(n=0; n<nLag; n++) { // loop over time shifts
3152  V = this->wc_List[n].pList.size();
3153  nB = int(this->wc_List[n].getbpp()*2*window+0.5);
3154 
3155  if(!V) continue;
3156 
3157  for(j=0; j<V; j++) { // loop over pixels
3158 
3159  pix = &(this->wc_List[n].pList[j]);
3160  if(R != size_t(pix->rate+0.5)) continue;
3161 
3162 // printf("lag=%2d pixel=%4d ID=%4d ",n,j,pix->clusterID);
3163 
3164  for(m=0; m<M; m++) { // loop over detectors
3165 
3166  inD = size_t(pix->getdata('I',m)+0.1);
3167  ppp = pDat[m]+inD;
3168  amp = *ppp;
3169 
3170  *ppp = pix->getdata('S',m); // pixel SNR
3171  if(inD-window < offset) { // left boundary
3172  frst = offset;
3173  last = frst + 2*window;
3174  }
3175  else if(inD+window > int(N-offset)) {
3176  last = N-offset;
3177  frst = last - 2*window;
3178  }
3179  else {
3180  frst = inD-window;
3181  last = inD+window;
3182  }
3183 
3184  if( inD>int(N-offset) || inD<offset ||
3185  frst>int(N-offset) || frst<offset ||
3186  last>int(N-offset) || last<offset) {
3187  cout<<"network::setRank() error\n";
3188  *ppp = amp; // restore pixel value in the array
3189  pix->setdata(0.,'R',m);
3190  continue;
3191  }
3192 
3193  rank = pDet[m]->getTFmap()->getSampleRankE(inD,frst,last);
3194  nT = last-frst+1;
3195 
3196  if(rank > nT-nB) rank = log(nB/double(nT+1-rank));
3197  else rank = 0.;
3198 
3199 // printf("%8.1e|%8.1e ",rank,amp);
3200 
3201  *ppp = amp; // restore pixel value in the array
3202  pix->setdata(rank,'R',m);
3203  cOUNt++;
3204 
3205  }
3206 // cout<<endl;
3207  }
3208  }
3209  return cOUNt;
3210 }
3211 
3212 // read earth skyMask coordinates from file (1G)
3213 size_t network::setSkyMask(double f, char* file) {
3214  int i;
3215  size_t L = this->skyHole.size();
3216  size_t n = 0;
3217  size_t l;
3218  char str[1024];
3219  FILE* in;
3220  char* pc;
3221  double a;
3222 
3223  if(!L) {
3224  cout<<endl<<"network::setSkyMask() - skymap size L=0"<<endl<<endl;
3225  exit(1);
3226  } else if(!file) {
3227  cout<<endl<<"network::setSkyMask() - NULL input skymask file"<<endl<<endl;
3228  exit(1);
3229  } else if(!strlen(file)) {
3230  cout<<endl<<"network::setSkyMask() - input skymask file not defined"<<endl<<endl;
3231  exit(1);
3232  } else if( (in=fopen(file,"r"))==NULL ) {
3233  cout << endl << "network::setSkyMask() - input skymask file '"
3234  << file << "' not exist" << endl << endl;;
3235  exit(1);
3236  }
3237 
3238  while(fgets(str,1024,in) != NULL){
3239 
3240  if(str[0] == '#') continue;
3241  if((pc = strtok(str," \t")) == NULL) continue;
3242  if(pc) i = atoi(pc); // sky index
3243  if((pc = strtok(NULL," \t")) == NULL) continue;
3244  if(pc && i>=0 && i<int(L)) {
3245  this->skyHole.data[i] = atof(pc); // skyProb
3246  this->nSkyStat.set(i, atof(pc));
3247  n++;
3248  } else {
3249  cout<<endl<<"network::setSkyMask() - "
3250  <<"skymask file contains index > max L="<<L<<endl<<endl;
3251  exit(1);
3252  }
3253  }
3254  if(n!=L) {
3255  cout<<endl<<"network::setSkyMask() - "
3256  <<"the number of indexes in the skymask file != L="<<L<<endl<<endl;
3257  exit(1);
3258  }
3259  a = skyHole.mean()*skyHole.size();
3260  skyHole *= a>0. ? 1./a : 0.;
3261  if(f==0.) { skyHole = 1.; return n; }
3262 
3263  double* p = this->skyHole.data;
3264  double** pp = (double **)malloc(L*sizeof(double*));
3265  for(l=0; l<L; l++) pp[l] = p + l;
3266 
3267  skyProb.waveSort(pp,0,L-1);
3268 
3269  a = double(L);
3270  for(l=0; l<L; l++) {
3271  a -= 1.;
3272  *pp[l] = a/L<f ? 0. : 1.;
3273  if(*pp[l] == 0.) this->nSkyStat.set(pp[l]-p,*pp[l]);
3274  }
3275  free(pp);
3276  return n;
3277 }
3278 
3279 // read celestial/earth skyMask coordinates from file
3280 size_t network::setSkyMask(char* file, char skycoord) {
3281 
3282  int i;
3283  size_t L = this->skyHole.size();
3284  size_t n = 0;
3285  char str[1024];
3286  FILE* in;
3287  char* pc;
3288  double data=0;
3289 
3290  if(skycoord!='e' && skycoord!='c') {
3291  cout << "network::setSkyMask() - wrong input sky coordinates "
3292  << " must be 'e'/'c' earth/celestial" << endl;;
3293  exit(1);
3294  }
3295 
3296  if(!L) {
3297  cout<<endl<<"network::setSkyMaskCC() - skymap size L=0"<<endl<<endl;
3298  exit(1);
3299  } else if(!file) {
3300  cout<<endl<<"network::setSkyMaskCC() - NULL input skymask file"<<endl<<endl;
3301  exit(1);
3302  } else if(!strlen(file)) {
3303  cout<<endl<<"network::setSkyMaskCC() - input skymask file not defined"<<endl<<endl;
3304  exit(1);
3305  } else if( (in=fopen(file,"r"))==NULL ) {
3306  cout << endl << "network::setSkyMaskCC() - input skymask file '"
3307  << file << "' not exist" << endl << endl;;
3308  exit(1);
3309  }
3310 
3311  if(skycoord=='e') {skyMask.resize(L); skyMask = 1;}
3312  if(skycoord=='c') {skyMaskCC.resize(L); skyMaskCC = 1;}
3313 
3314  while(fgets(str,1024,in) != NULL){
3315 
3316  if(str[0] == '#') continue;
3317  if((pc = strtok(str," \t")) == NULL) continue;
3318  if(pc) i = atoi(pc); // sky index
3319  if((pc = strtok(NULL," \t")) == NULL) continue;
3320  if(pc && i>=0 && i<int(L)){
3321  data = atof(pc);
3322  if(skycoord=='e') this->skyHole.data[i]=data;
3323  if(skycoord=='c') this->skyMaskCC.data[i]=data;
3324  n++;
3325  } else {
3326  cout<<endl<<"network::setSkyMask() - "
3327  <<"skymask file contains index > max L="<<L<<endl<<endl;
3328  exit(1);
3329  }
3330  }
3331  if(n!=L) {
3332  cout<<endl<<"network::setSkyMask() - "
3333  <<"the number of indexes in the skymask file != L="<<L<<endl<<endl;
3334  exit(1);
3335  }
3336 
3337  if(in!=NULL) fclose(in);
3338  return n;
3339 }
3340 
3341 // read celestial/earth skyMask coordinates from skymap
3342 size_t network::setSkyMask(skymap sm, char skycoord) {
3343 
3344  if(skycoord!='e' && skycoord!='c') {
3345  cout << "network::setSkyMask() - wrong input sky coordinates "
3346  << " must be 'e'/'c' earth/celestial" << endl;;
3347  exit(1);
3348  }
3349 
3350  size_t L = this->skyHole.size();
3351  if((int)sm.size()!=L) {
3352  cout << "network::setSkyMask() - wrong input skymap size "
3353  << sm.size() << " instead of " << L << endl;;
3354  exit(1);
3355  }
3356 
3357  if(skycoord=='e') {
3358  skyMask.resize(L);
3359  for(int i=0;i<L;i++) this->skyHole.data[i]=sm.get(i);
3360  }
3361  if(skycoord=='c') {
3362  skyMaskCC.resize(L);
3363  for(int i=0;i<L;i++) this->skyMaskCC.data[i]=sm.get(i);
3364  }
3365 
3366  return L;
3367 }
3368 
3369 // read MDC log file with list of injections
3370 size_t network::readMDClog(char* file, double gps, int nTime, int nName) {
3371  int i;
3372  size_t j;
3373  FILE* in;
3374  char str[1024];
3375  char STR[1024];
3376  char* p;
3377  bool save;
3378  double GPS;
3379 
3380  int imdcMap=0;
3381  std::map <string, int> mdcMap; // used to check uniqueness of mdc types
3382 
3383  if( (in=fopen(file,"r"))==NULL ) {
3384  cout<<"network::readMDClog() - no file is found \n";
3385  exit(1);
3386  }
3387 
3388  while(fgets(str,1024,in) != NULL){
3389 
3390  if(str[0] == '#') continue;
3391  sprintf(STR,"%s",str); // copy string
3392 
3393 // find and save injection gps time
3394 
3395  if((p = strtok(STR," \t")) == NULL) continue;
3396 
3397  for(i=1; i<nTime; i++) {
3398  p = strtok(NULL," \t"); // get gps time
3399  if(!p) break;
3400  }
3401 
3402  if(p) {
3403  GPS = atof(p);
3404  if(gps==0. || fabs(GPS-gps)<7200.) {
3405  this->mdcList.push_back(str);
3406  this->mdcTime.push_back(GPS);
3407  }
3408  }
3409 
3410 // find and save injection type
3411 
3412  if((p = strtok(str," \t")) == NULL) continue;
3413 
3414  for(i=1; i<nName; i++) {
3415  p = strtok(NULL," \t"); // get name
3416  if(!p) break;
3417  }
3418 
3419  if(p) if(mdcMap.find(p)==mdcMap.end()) mdcMap[p]=imdcMap++;
3420  }
3421 
3422  // copy mdc type to mdcType vector
3423  // the data are sorted keeping the back compatibility with the 1G algorithm
3424  this->mdcType.resize(mdcMap.size());
3425  std::map<std::string, int>::iterator iter;
3426  for (iter=mdcMap.begin(); iter!=mdcMap.end(); iter++) {
3427  this->mdcType[iter->second]=iter->first;
3428  }
3429  // print list
3430  for(int j=0;j<this->mdcType.size();j++) {
3431  int step=1;
3432  if(j<100) step=1;
3433  else if(j<10000) step=100;
3434  else step=1000;
3435  if(j%step==0) {
3436  printf("type %3d\t",(int)j);
3437  cout<<" has been assigned to waveform "<<mdcType[j]<<endl;
3438  }
3439  }
3440 
3441  return this->mdcList.size();
3442 }
3443 
3444 
3445 // read file with segment list
3446 size_t network::readSEGlist(char* file, int n) {
3447  int i;
3448  char str[1024];
3449  char* p;
3450  FILE* in;
3451  waveSegment SEG;
3452  SEG.index = 0;
3453 
3454  if( (in=fopen(file,"r"))==NULL ) {
3455  cout<<"network::readSEGlist(): specified segment file "<<file<<" does not exist\n";
3456  exit(1);
3457  }
3458 
3459  while(fgets(str,1024,in) != NULL){
3460 
3461  if(str[0] == '#') continue;
3462 
3463 // find and save segment start time
3464 
3465  if((p = strtok(str," \t")) == NULL) continue;
3466 
3467  for(i=1; i<n; i++) {
3468  p = strtok(NULL," \t"); // get start
3469  if(!p) break;
3470  }
3471 
3472  if(p) {
3473  SEG.index++;
3474  SEG.start = atof(p);
3475  p = strtok(NULL," \t"); // get stop
3476  if(!p) continue;
3477  SEG.stop = atof(p);
3478 // printf("%12.2f %12.2f \n",SEG.start,SEG.stop);
3479  this->segList.push_back(SEG);
3480  }
3481  }
3482  return this->segList.size();
3483 }
3484 
3485 
3486 // set veto array
3487 double network::setVeto(double Tw) {
3488 // set veto array from the input list of DQ segments
3489 // Tw - time window around injections
3490 //
3491 
3492  int j, jb, je, jm;
3493  size_t i,k;
3494  double gps, EE;
3495  double live = 0.;
3497  this->mdc__ID.clear();
3498 
3499  size_t I = this->ifoList.size();
3500  if(Tw<2.) Tw = 2.;
3501  detector* d = this->ifoList[0];
3502 
3503  int N = d->getTFmap()->size(); // TF data size
3504  int M = d->getHoT()->size(); // TS data size
3505  double R = (d->getTFmap()->pWavelet->m_WaveType==WDMT) ? // time series rate
3506  d->getHoT()->rate() : d->getTFmap()->rate();
3507  double S = d->getTFmap()->start(); // segment start time
3508  double E = d->getTFmap()->stop(); // segment end time
3509  size_t K = this->segList.size(); // segment list size
3510  size_t L = this->mdcList.size(); // injection list size
3511  size_t n = size_t(this->Edge*R+0.5); // data offset
3512  int W = int(Tw*R/2.+0.5); // injection window size
3513 
3514  if(M>2) N=M; // use size of TS object
3515  if(!I || !N) return 0.;
3516 
3517  if(this->veto.size() != size_t(N)) { // initialize veto array
3518  this->veto.resize(N);
3519  }
3520  this->veto = 0;
3521  w = this->veto;
3522 
3523  for(k=0; k<K; k++) { // loop over segmets
3524  gps = segList[k].start;
3525  if(gps<S) gps=S;
3526  if(gps>E) gps=E;
3527  j = int((gps-S)*R); // index in data array
3528  jb = j<0 ? 0 : j;
3529  gps = segList[k].stop;
3530  if(gps<S) gps=S;
3531  if(gps>E) gps=E;
3532  j = int((gps-S)*R); // index in data array
3533  je = j>N ? N : j;
3534  for(j=jb; j<je; j++) this->veto.data[j] = 1;
3535  }
3536 
3537  if(!K) this->veto = 1; // no segment list
3538 
3539  for(k=0; k<L; k++) { // loop over injections
3540  gps = mdcTime[k]; // get LOG injection time
3541  if(gps == 0.) continue;
3542 
3543  if(d->HRSS.size()) { // get MDC injection time
3544  gps = EE = 0.;
3545  for(i=0; i<I; i++) {
3546  d = this->ifoList[i];
3547  gps += d->TIME.data[k]*d->ISNR.data[k];
3548  EE += d->ISNR.data[k];
3549  }
3550  gps /= EE;
3551  mdcTime[k] = gps;
3552  }
3553 
3554  jm = int((gps-S)*R); // index in data array
3555  jb = jm-W; je = jm+W;
3556  if(jb < 0) jb = 0;
3557  if(jb >=N) continue;
3558  if(je > N) je = N;
3559  if(je <=0) continue;
3560  if(je-jb < int(R)) continue;
3561  if(jm<jb || jm>je) continue;
3562 
3563  for(j=jb; j<je; j++) w.data[j] = 1;
3564 
3565  if(veto.data[jm]) this->mdc__ID.push_back(k); // save ID of selected injections
3566  }
3567 
3568  if(L) this->veto *= w; // apply injection mask
3569  live = 0.;
3570  for(k=n; k<N-n; k++) live+=this->veto.data[k];
3571 
3572  return live/R;
3573 }
3574 
3575 // get reconstructed detector responses
3576 bool network::getwave(size_t ID, size_t lag, char atype)
3577 {
3578  int n,m;
3579  size_t i,j,k,l;
3580  double R = 0;
3581  size_t M = this->ifoList.size();
3582  bool flag = true;
3583 
3584  netcluster* wc = this->getwc(lag);
3585  detector* pd = this->getifo(0);
3586 
3587  Meyer<double> Me(256,1);
3588  WSeries<double> w(Me);
3589  WSeries<double> W;
3591  wavearray<double> id = wc->get((char*)"ID");
3592  std::vector<int> v;
3593 
3594  flag = false;
3595  for(j=0; j<id.size(); j++) {
3596  if(id.data[j] == ID) { flag=true; break; }
3597  }
3598 
3599  if(!flag) return false;
3600  flag = true;
3601 
3602  v = wc->nTofF[ID-1]; // backward time delay configuration
3603  k = pd->nDFS/pd->nDFL; // up-sample factor
3604  l = size_t(log(k*1.)/log(2.)+0.1); // wavelet level
3605 
3606 // time-of-flight backward correction for reconstructed waveforms
3607 
3608  for(i=0; i<M; i++) {
3609  pd = this->getifo(i);
3610  if(pd->getwave(ID,*wc,atype,i) == 0.) { flag=false; break; }
3611 
3612  R = pd->waveForm.rate();
3613 
3614  w.rate(R*k); x.rate(R);
3615  m = int(pd->waveForm.size());
3616  n = m/int(R+0.1)+4; // integer number of seconds
3617  n *= int(R+0.1); // total number of samples in layer 0
3618  if(n!=int(x.size())) x.resize(n);
3619  x = 0.; x.cpf(pd->waveForm,m,0,n/2);
3620  n *= k; // total number of up samples
3621  if(n!=int(w.size())) w.resize(n);
3622  w.setLevel(l); // set wavelet level
3623  w = 0.; w.putLayer(x,0); // prepare for upsampling
3624  w.Inverse(); // up-sample
3625  W = w; w = 0.;
3626 
3627  if(v[i]>0) { // time-shift waveform
3628  w.cpf(W,w.size()-v[i],0,v[i]); // v[i] - backward time delay
3629  }
3630  else {
3631  w.cpf(W,w.size()+v[i],-v[i]);
3632  }
3633 
3634  n = x.size();
3635  w.Forward(l);
3636  w.getLayer(x,0);
3637  pd->waveForm.cpf(x,m,n/2); // align waveforms
3638 
3639  x = pd->waveForm; // produce null stream
3640  w = pd->waveNull;
3641  x *= -1.;
3642  n = int((x.start()-w.start())*x.rate()+0.1);
3643  w.add(x,m,0,n);
3644  w.Forward(pd->TFmap.getLevel());
3645 
3646  pd->waveNull.resize(4*int(R+0.1)+x.size());
3647  pd->waveNull.setLevel(pd->TFmap.getLevel());
3648  pd->waveNull = 0.;
3649  pd->waveNull.start(x.start()-2.);
3650 
3651  n = int((pd->waveNull.start()-w.start())*w.rate()+0.1);
3652  m = pd->waveNull.size();
3653  if(n>=0) {
3654  if(n+m > (int)w.size()) m = w.size()-n;
3655  pd->waveNull.cpf(w,m,n,0);
3656  }
3657  else {
3658  m += n;
3659  if(m > (int)w.size()) m = w.size();
3660  pd->waveNull.cpf(w,m,0,-n);
3661  }
3662  }
3663  return flag;
3664 }
3665 
3666 bool network::getMRAwave(size_t ID, size_t lag, char atype, int mode, bool tof)
3667 {
3668 // get MRA waveforms of type atype in time domain given lag nomber and cluster ID
3669 // mode: -1/0/1 - return 90/mra/0 phase
3670 // if tof = true, apply time-of-flight corrections
3671 // fill in waveform arrays in the detector class
3672  size_t i,j;
3673  double R = 0;
3674  size_t nIFO = this->ifoList.size();
3675 
3676  netcluster* pwc = this->getwc(lag);
3677  wavearray<double> id = pwc->get((char*)"ID",0,'S',0);
3678 
3679  bool signal = (abs(atype)=='W' || abs(atype)=='w') ? false : true;
3680  bool flag = false;
3681 
3682  for(j=0; j<id.size(); j++) {
3683  if(size_t(id.data[j]+0.1) == ID) flag=true;
3684  }
3685  if(!flag) return false;
3686 
3688  std::vector<int> v;
3689 
3690  v = pwc->nTofF[ID-1]; // backward time delay configuration
3691 
3692  // time-of-flight backward correction for reconstructed waveforms
3693 
3694  for(i=0; i<nIFO; i++) {
3695 
3696  x = pwc->getMRAwave(this,ID,i,atype,mode);
3697  if(x.size() == 0.) {cout<<"zero length\n"; return false;}
3698 
3699 // apply time delay
3700 
3701  if(tof) {
3702  double R = this->rTDF; // effective time-delay rate
3703  double tShift = -v[i]/R;
3704 
3705  x.FFTW(1);
3706  TComplex C;
3707  double df = x.rate()/x.size();
3708  for (int ii=0;ii<(int)x.size()/2;ii++) {
3709  TComplex X(x.data[2*ii],x.data[2*ii+1]);
3710  X=X*C.Exp(TComplex(0.,-2*PI*ii*df*tShift)); // Time Shift
3711  x.data[2*ii]=X.Re();
3712  x.data[2*ii+1]=X.Im();
3713  }
3714  x.FFTW(-1);
3715  }
3716 
3717  if(signal) this->getifo(i)->waveForm = x;
3718  else this->getifo(i)->waveBand = x;
3719 
3720  }
3721  return flag;
3722 }
3723 
3724 //**************************************************************************
3725 // initialize wc_List for a selected TF area
3726 //**************************************************************************
3727 size_t network::initwc(double sTARt, double duration)
3728 {
3729  size_t i,j,m,k;
3730  double a;
3731  size_t npix = 0;
3732  bool save = false;
3733 
3734  size_t I = this->ifoList[0]->TFmap.maxLayer()+1;
3735  size_t R = size_t(this->ifoList[0]->getTFmap()->rate()/I+0.5);
3736  size_t N = this->ifoList[0]->getTFmap()->size();
3737  size_t M = this->ifoList.size(); // number of detectors
3738  size_t jB = size_t(this->Edge*R)*I; // number of samples in the edges
3739 
3740 // pointers
3741 
3742  std::vector<detector*> pDet; pDet.clear();
3743  std::vector<double*> pDat; pDat.clear();
3744  std::vector<int> pLag; pLag.clear();
3745 
3746  netpixel pix(M); // initialize pixel for M detectors
3747  pix.clusterID = 0; // initialize cluster ID
3748  pix.rate = float(R); // pixel rate
3749  pix.core = true; // pixel core
3750  pix.neighbors.push_back(0); // just one neighbor for each pixel
3751 
3752  for(m=0; m<M; m++) {
3753  pDet.push_back(ifoList[m]);
3754  pDat.push_back(ifoList[m]->getTFmap()->data);
3755  pLag.push_back(int(ifoList[m]->sHIFt*R*I+0.5));
3756  }
3757 
3758  size_t il = size_t(2.*pDet[0]->TFmap.getlow()/R); // low frequency boundary index
3759  size_t ih = size_t(2.*pDet[0]->TFmap.gethigh()/R); // high frequency boundary index
3760  if(ih==0 || ih>=I) ih = I;
3761 
3762  size_t J = size_t(sTARt*R+0.1); // start index in the slice
3763  size_t K = size_t(duration*R+0.1); // number of pixels in the slice
3764  slice S;
3765 
3766  this->wc_List[0].clear(); // clear wc_List
3767 
3768 // cout<<"il="<<il<<" ih"<<ih<<" K="<<K<<" J="<<J<<endl;
3769 
3770  for(i=il; i<ih; i++){ // loop over layers
3771  pix.frequency = i;
3772  S = pDet[0]->TFmap.getSlice(i);
3773 
3774  for(j=0; j<K; j++){ // loop over pixels
3775  pix.time = (J+j)*I + S.start(); // LTF pixel index in the map;
3776 
3777  if(pix.time >= N) {
3778  cout<<"network::initwc() error - index out of limit \n";
3779  continue;
3780  }
3781 
3782  pix.likelihood = 0.;
3783  save = true;
3784  for(m=0; m<M; m++) { // loop over detectors
3785  k = pix.time+pLag[m];
3786  if(k>=N) k -= N-jB;
3787  if(!this->veto.data[k]) save = false;
3788  a = pDat[m][k];
3789  pix.likelihood += a*a/2.;
3790  pix.setdata(a,'S',m); // set amplitude
3791  pix.setdata(k,'I',m); // set index
3792  pix.setdata(pDet[m]->getNoise(i,k),'N',m); // set noise RMS
3793  }
3794  pix.neighbors[0] = ++npix;
3795  if(save) this->wc_List[0].append(pix);
3796  }
3797 
3798  }
3799 
3800  wc_List[0].start = pDet[0]->TFmap.start();
3801  wc_List[0].stop = N/R/I;
3802  wc_List[0].rate = pDet[0]->TFmap.rate();
3803 
3804  if(npix) {
3805  this->wc_List[0].pList[npix-1].neighbors[0]=0;
3806  this->wc_List[0].cluster();
3807  }
3808  return npix;
3809 }
3810 
3811 
3812 //**************************************************************************
3813 //:select TF samples by value of the network likelihood: 2-NIFO detectors
3814 //**************************************************************************
3815 long network::coherence(double Eo, double Es, double factor)
3816 {
3817  size_t nIFO = this->ifoList.size(); // number of detectors
3818 
3819  if(nIFO>NIFO || !this->filter.size() || this->filter[0].index.size()!=32) {
3820  cout<<"network::coherence(): \n"
3821  <<"invalid number of detectors or\n"
3822  <<"delay filter is not set\n";
3823  return 0;
3824  }
3825  if(getifo(0)->getTFmap()->w_mode != 1) {
3826  cout<<"network::coherence(): invalid whitening mode.\n";
3827  return 0;
3828  }
3829 
3830  if(factor > 1.) factor = float(nIFO-1)/nIFO;
3831  Eo = nIFO*Eo*Eo; // lognormal threshold on total pixel energy
3832  Es = nIFO*Es*Es; // final threshold on pixel energy
3833 
3834  size_t i,j,k,m,n,l,NN;
3835  size_t jS,jj,nM,jE,LL;
3836 
3837  double R = this->ifoList[0]->getTFmap()->rate();
3838  size_t N = this->ifoList[0]->getTFmap()->size();
3839  size_t I = this->ifoList[0]->TFmap.maxLayer()+1;
3840  size_t M = this->filter.size()/I; // total number of delays
3841  size_t K = this->filter[0].index.size(); // length of delay filter
3842  size_t L = this->index.size(); // total number of source locations
3843  size_t jB = size_t(this->Edge*R/I)*I; // number of samples in the edges
3844  double band = this->ifoList[0]->TFmap.rate()/I/2.;
3845  slice S = getifo(0)->getTFmap()->getSlice(0); // 0 wavelet slice
3846 
3847  delayFilter* pv;
3848  netpixel pix(nIFO);
3849  pix.core = true;
3850  pix.rate = R/I;
3851  pix.layers = I;
3852 
3853 // pointers to data
3854 
3855  wavearray<int> inTF;
3856  wavearray<double> emax[NIFO];
3857  double* pdata[NIFO];
3858  double* pq;
3859  for(n=0; n<NIFO; n++) {
3860  emax[n].resize(S.size()); emax[n] = 0.;
3861  if(n >= nIFO) continue;
3862  pdata[n] = getifo(n)->getTFmap()->data;
3863  }
3864  inTF.resize(S.size()); inTF = 0;
3865 
3866 // allocate buffers
3867  wavearray<double> eD[NIFO]; // array for delayed amplitudes^2
3868  double* pe[NIFO];
3869  int in[NIFO];
3870  for(n=0; n<NIFO; n++) { eD[n].resize(M); eD[n] = 0.; pe[n] = eD[n].data; }
3871 
3872 // get sky index arrays
3873  wavearray<short> inDEx[NIFO];
3874  short* ina;
3875 
3876  LL = 0;
3877  for(l=0; l<L; l++) if(skyMask.data[l]) LL++;
3878  for(n=0; n<NIFO; n++) {
3879  inDEx[n].resize(LL);
3880  if(n>=nIFO) inDEx[n] = 0;
3881  else {
3882  k = 0;
3883  ina = this->getifo(n)->index.data;
3884  for(l=0; l<L; l++) {
3885  if(skyMask.data[l]) inDEx[n].data[k++] = ina[l];
3886  }
3887  }
3888  }
3889 
3890  NETX(
3891  short* m0 = inDEx[0].data; ,
3892  short* m1 = inDEx[1].data; ,
3893  short* m2 = inDEx[2].data; ,
3894  short* m3 = inDEx[3].data; ,
3895  short* m4 = inDEx[4].data; ,
3896  short* m5 = inDEx[5].data; ,
3897  short* m6 = inDEx[6].data; ,
3898  short* m7 = inDEx[7].data; )
3899 
3900 // buffer for wavelet layer delay filter
3901  double* pF = (double*)malloc(K*M*sizeof(double));
3902  int* pJ = (int*)malloc(K*M*sizeof(int));
3903  double* F;
3904  int* J;
3905 
3906 // sky time delays
3907 
3908  size_t M1[NIFO];
3909  size_t M2[NIFO];
3910  double t1,t2;
3911  size_t KK = this->filter.size()/I; // number of time delay samples
3912  for(n=0; n<nIFO; n++) {
3913  t1 = getifo(n)->tau.min()*R*getifo(0)->nDFS/I;
3914  t2 = getifo(n)->tau.max()*R*getifo(0)->nDFS/I;
3915  M1[n] = short(t1+KK/2+0.5)-1;
3916  M2[n] = short(t2+KK/2+0.5)+1;
3917  }
3918 
3919 // time shifts
3920 
3921  long nZero = 0;
3922  bool skip = false;
3923  size_t Io = 0; // counter of number of layers
3924  double a,b,E;
3925 
3926  this->pixeLHood = getifo(0)->TFmap;
3927  this->pixeLHood = 0.;
3928 
3929 // set veto array if it is not set
3930  if(this->veto.size() != N) { veto.resize(N); veto = 1; }
3931 
3932  N -= jB; // correction for left boundary
3933 
3934  for(k=0; k<nLag; k++) {
3935  this->wc_List[k].clear(); // clear netcluster structure
3936  this->livTime[k] = 0.; // clear live time counters
3937  this->wc_List[k].setlow(getifo(0)->TFmap.getlow());
3938  this->wc_List[k].sethigh(getifo(0)->TFmap.gethigh());
3939  }
3940 
3941  for(i=1; i<I; i++) { // loop over wavelet layers
3942 
3943 // select bandwidth
3944  a = i*band;
3945  if(a >= getifo(0)->TFmap.gethigh()) continue;
3946  a = (i+1)*band;
3947  if(a <= getifo(0)->TFmap.getlow()) continue;
3948 
3949  Io++;
3950 
3951 // set filter array for this layer
3952  for(m=0; m<M; m++){
3953  for(k=0; k<K; k++){
3954  pv = &(filter[i*M+m]);
3955  pF[k+m*K] = double(pv->value[k]);
3956  pJ[k+m*K] = int(pv->index[k]);
3957  }
3958  }
3959 
3960  S = getifo(0)->getTFmap()->getSlice(i);
3961 
3962  NN = S.size();
3963  for(n=0; n<NIFO; n++) { // resize arrays for max amplitudes
3964  if(emax[n].size() != NN) emax[n].resize(NN);
3965  emax[n] = 0; in[n] = 0;
3966  }
3967  if(inTF.size() != NN) inTF.resize(NN);
3968 
3969 // apply delay filters to calculate emax[]
3970 
3971  jS = S.start()+jB;
3972  NN = NN - jB/I;
3973  jE = NN - jB/I;
3974 
3975  for(n=0; n<nIFO; n++) {
3976 
3977  jj = jB/I;
3978 
3979  for(j=jS; j<N; j+=I) { // loop over samples in the layer
3980 
3981  emax[n].data[jj] = 0.;
3982  inTF.data[jj] = j; // store index in TF map
3983 
3984  F = pF+M1[n]*K;
3985  J = pJ+M1[n]*K;
3986  pq = pdata[n]+j;
3987 
3988  b = 0.;
3989  for(m=M1[n]; m<M2[n]; m++){
3990  a = dot32(F,pq,J); // delayed amplitude
3991  a *= a;
3992  if(b < a) b = a; // max energy
3993  F+=K; J+=K;
3994  }
3995  emax[n].data[jj++] = b;
3996  }
3997  }
3998 
3999 // select shifted amplitudes
4000 // regular case: jS.......j*********.....N
4001 // left boundary handling: jS***.............j*****N shift becomes negative
4002 
4003  for(k=0; k<nLag; k++) { // over lags
4004 
4005  a = 1.e10;
4006  nM = 0; // master detector
4007 
4008  for(n=0; n<nIFO; n++) {
4009  b = this->getifo(n)->lagShift.data[k]; // shift in seconds
4010  if(a>b) { a = b; nM = n; }
4011  }
4012 
4013  for(n=0; n<nIFO; n++) {
4014  b = this->getifo(n)->lagShift.data[k]; // shift in seconds
4015  in[n] = (int((b-a)*R)+jB)/I - 1; // index of first pixel in emax -1
4016  }
4017 
4018  for(jj=jB/I; jj<NN; jj++) { // loop over samples in the emax
4019 
4020  m = 0; E = 0.;
4021  for(n=0; n<nIFO; n++) {
4022  if((++in[n]) >= int(NN)) in[n] -= jE; // check boundaries
4023  m += this->veto.data[inTF.data[in[n]]]; // check data quality
4024  E += emax[n].data[in[n]];
4025  }
4026  this->livTime[k] += float(m/nIFO); // calculate live time for each lag
4027  if(E<Eo || m<nIFO) continue;
4028 
4029  skip = false;
4030  for(n=0; n<nIFO; n++) {
4031  b = E - emax[n].data[in[n]];
4032  if(b<Eo*factor) skip = true;
4033  }
4034  if(skip) continue;
4035 
4036 // calculate delays again and run skyloop.
4037 
4038  for(n=0; n<nIFO; n++) {
4039  F = pF+M1[n]*K;
4040  J = pJ+M1[n]*K;
4041  pq = pdata[n]+inTF.data[in[n]];
4042 
4043  for(m=M1[n]; m<M2[n]; m++){
4044  a = dot32(F,pq,J); // delayed amplitude
4045  pe[n][m] = a*a; // delayed energy
4046  F+=K; J+=K;
4047  }
4048  }
4049 
4050  skip = true;
4051  for(l=0; l<LL; l++) {
4052  double pet = 0.;
4053  NETX(
4054  pet+=pe[0][m0[l]]; ,
4055  pet+=pe[1][m1[l]]; ,
4056  pet+=pe[2][m2[l]]; ,
4057  pet+=pe[3][m3[l]]; ,
4058  pet+=pe[4][m4[l]]; ,
4059  pet+=pe[5][m5[l]]; ,
4060  pet+=pe[6][m6[l]]; ,
4061  pet+=pe[7][m7[l]]; )
4062  if(pet > Eo)
4063  { skip = false; break; }
4064  }
4065  if(skip) continue;
4066 
4067 // save pixels in wc_List
4068 
4069  j = inTF.data[in[nM]]; // index in TF
4070  pix.rate = float(R/I);
4071  pix.time = j;
4072  pix.core = E>Es ? true : false;
4073  pix.frequency = i;
4074  pix.likelihood = E;
4075 
4076  for(n=0; n<nIFO; n++) {
4077  pix.data[n].index = inTF.data[in[n]];
4078  pix.data[n].asnr = emax[n].data[in[n]];
4079  }
4080 
4081  wc_List[k].append(pix);
4082  if(!k) this->pixeLHood.data[j] = sqrt(E/nIFO);
4083  nZero++;
4084  }
4085  }
4086  }
4087 
4088 // set metadata in wc_List
4089  for(k=0; k<nLag; k++) {
4090  a = getifo(0)->getTFmap()->start();
4091  b = getifo(0)->getTFmap()->size()/R;
4092  this->wc_List[k].start = a;
4093  this->wc_List[k].stop = a+b;
4094  this->wc_List[k].rate = R;
4095  this->livTime[k] *= double(I)/(Io*R);
4096  }
4097 
4098  if(nZero) this->setRMS();
4099 
4100  free(pF); free(pJ);
4101 
4102  return nZero;
4103 }
4104 
4105 // calculate sky error regions
4106 void network::getSkyArea(size_t id, size_t lag, double To, double rMs) {
4107 // calculate sky error regions
4108 // new version designed for 2G analysis
4109 //!param: cluster id
4110 //!param: time lag
4111 //!param: cluster time
4112 //!param: rms correction: noise rms is 1+rMs
4113 
4114  int in,im,IN,IM;
4115  size_t i,j,l,m,k,K;
4116  size_t N = this->wc_List[lag].csize();
4117  size_t M = this->mdc__IDSize();
4118  size_t L = this->skyProb.size();
4119  size_t Lm = L-int(0.9999*L);
4120  size_t nIFO = this->ifoList.size(); // number of detectors
4121  bool prior = this->gamma<0?true:false; // gamma<0 : antenna pattern prior is used
4122  skymap* sm = &(this->nSkyStat);
4123 
4124  if(Lm < 2) return;
4125  if(nSky > long(L-Lm)) nSky = L-Lm;
4126  if(id>N) return;
4127 
4128  double th,ph,a;
4129  double sum = 0.;
4130  double vol = 0.;
4131  double co1 = cos(sm->theta_1*PI/180.);
4132  double co2 = cos(sm->theta_2*PI/180.);
4133  double phi = sm->phi_2-sm->phi_1;
4134  double s = fabs(phi*(co1-co2))*180/PI/sm->size(); // sky solid angle
4135 
4136  std::vector<float>* vf = &(this->wc_List[lag].sArea[id-1]);
4137  size_t v[11];
4138 
4139  double* p = this->skyProb.data;
4140  double** pp = (double **)malloc(L*sizeof(double*));
4141  for(l=0; l<L; l++) pp[l] = p + l;
4142 
4143  skyProb.waveSort(pp,0,L-1);
4144 
4145  double Po = *pp[L-1];
4146  double rms = fabs(rMs); // rms for method 2
4147 
4148  double smax=nAntenaPrior.max(); // max sensitivity
4149 
4150  for(l=0; l<L; l++) {
4151  if(*pp[l] <= 0.) {*pp[l]=0.; continue;}
4152  *pp[l] = exp(-(Po - *pp[l])/2./rms);
4153  if(prior) *pp[l] *= pow(nAntenaPrior.get(int(pp[l]-p))/smax,4);
4154  sum += *pp[l];
4155  }
4156  if(prior) skyProb.waveSort(pp,0,L-1);
4157 
4158  for(l=0; l<L; l++) {
4159  p[l] /= sum; // normalize map
4160  nProbability.set(l,p[l]); // fill in skyProb map
4161  }
4162 
4163  if(pOUT) cout<<rMs<<" "<<*pp[L-1]<<" "<<*pp[L-2]<<" "<<*pp[L-3]<<"\n";
4164 
4165  vf->clear();
4166  for(m=0; m<11; m++) { v[m] = 0; vf->push_back(0.); }
4167 
4168  vol = 0;
4169  for(l=L-1; l>Lm; l--){
4170  vol += *pp[l];
4171  for(m=size_t(vol*10.)+1; m<10; m++) v[m] += 1;
4172  if(vol >= 0.9) break;
4173  }
4174 
4175  for(m=1; m<10; m++) {
4176  (*vf)[m] = sqrt(v[m]*s);
4177  if(pOUT && !M) cout<<m<<" error region: "<<(*vf)[m]<<endl;
4178  }
4179 
4180 
4181 // fill skyProb skymap
4182 
4183  std::vector<float>* vP = &(this->wc_List[lag].p_Map[id-1]);
4184  std::vector<int>* vI = &(this->wc_List[lag].p_Ind[id-1]);
4185 
4186  K = 0;
4187  sum = 0.;
4188  vP->clear();
4189  vI->clear();
4190  double pthr=0;
4191  // if nSky -> nSky is converted into a probability threshold nSky=-XYZ... -> pthr=0.XYZ...
4192  if(nSky<0) {char spthr[1024];sprintf(spthr,"0.%d",int(abs(nSky)));pthr=atof(spthr);}
4193  for(l=L-1; l>Lm; l--){
4194  sum += *pp[l];
4195  if(nSky==0 && (K==1000 || sum > 0.99) && K>0) break;
4196  else if(nSky<0 && sum > pthr && K>0) break;
4197  else if(nSky>0 && K==nSky && K>0) break;
4198  K++;
4199  vI->push_back(int(pp[l]-p));
4200  vP->push_back(float(*pp[l]));
4201  }
4202 
4203 // set injections if there are any
4204 
4205  if(!M) { free(pp); return; }
4206 
4207  double dT = 1.e13;
4208  double injTime = 1.e12;
4209  int injID = -1;
4210  int mdcID = -1;
4211  injection INJ(this->ifoList.size());
4212 
4213  for(m=0; m<M; m++) {
4214  mdcID = this->getmdc__ID(m);
4215  dT = fabs(To - this->getmdcTime(mdcID));
4216  if(dT<injTime && INJ.fill_in(this,mdcID)) {
4217  injTime = dT;
4218  injID = mdcID;
4219  if(pOUT) printf("getSkyArea: %4d %12.4f %7.3f %f \n",int(m),To,dT,s);
4220  }
4221  }
4222 
4223  if(INJ.fill_in(this,injID)) {
4224 
4225  th = INJ.theta[0];
4226  ph = INJ.phi[0];
4227  i = this->getIndex(th,ph);
4228 
4229  vI->push_back(int(i));
4230  vP->push_back(float(p[i]));
4231 
4232  vol = sum = 0.;
4233  for(l=L-1; l>Lm; l--){
4234  vol += s;
4235  sum += *pp[l];
4236  if(pp[l]-p == int(i)) break;
4237  }
4238  (*vf)[0] = sqrt(vol);
4239  (*vf)[10] = sum;
4240  j = pp[L-1]-p; // reference sky index at max
4241 
4242  if(pOUT) {
4243  printf("getSkyArea: %5d %12.4f %6.1f %6.1f %6.1f %6.1f %6.2f %6.2f %6.2f %7.5f, %e %d \n",
4244  int(id),INJ.time[0]-this->getifo(0)->TFmap.start(),INJ.theta[0],INJ.phi[0],
4245  sm->getTheta(j),sm->getPhi(j),(*vf)[0],(*vf)[5],(*vf)[9],(*vf)[10],p[i],int(i));
4246  }
4247  }
4248 
4249  free(pp);
4250  return;
4251 }
4252 
4253 
4254 // calculate sky error regions
4255 void network::getSkyArea(size_t id, size_t lag, double To) {
4256  int in,im,IN,IM;
4257  size_t i,j,l,m,k,K;
4258  size_t N = this->wc_List[lag].csize();
4259  size_t L = this->skyProb.size();
4260  size_t Lm = L-int(0.9999*L);
4261  skymap* sm = &(this->nSkyStat);
4262 
4263  if(Lm < 2) return;
4264  if(nSky > long(L-Lm)) nSky = L-Lm;
4265  if(id>N) return;
4266 
4267  double a,th,ph,st,sp;
4268  double TH,PH,ST,SP,Eo;
4269  double sum = 0.;
4270  double vol = 0.;
4271  double co1 = cos(sm->theta_1*PI/180.);
4272  double co2 = cos(sm->theta_2*PI/180.);
4273  double phi = sm->phi_2-sm->phi_1;
4274  double s = fabs(phi*(co1-co2))*180/PI/sm->size(); // sky solid angle
4275 
4276  std::vector<float>* vf = &(this->wc_List[lag].sArea[id-1]);
4277  size_t v[11];
4278 
4279  double* p = this->skyProb.data;
4280  double** pp = (double **)malloc(L*sizeof(double*));
4281  for(l=0; l<L; l++) pp[l] = p + l;
4282 
4283  skyProb.waveSplit(pp,0,L-1,Lm);
4284  skyProb.waveSort(pp,Lm,L-1);
4285 
4286  Eo = *pp[L-1]; // max L
4287  for(l=L-1; l>=Lm; l--) *pp[l] -= Eo;
4288  for(l=0; l<Lm; l++) *pp[l] = -1.e10;
4289 
4290 // correction for sky segmentation
4291 
4292  if(sm->getOrder()==0) { // is disabled for HEALPix skymap
4293  for(l=Lm; l<L; l++){
4294  j = pp[l]-p; // reference sky index
4295  th = sm->getTheta(j);
4296  ph = sm->getPhi(j);
4297  st = sm->getThetaStep(j);
4298 
4299  for(in=-1; in<2; in++) {
4300  sp = sm->getPhiStep(getIndex(th+in*st,ph));
4301  for(im=-1; im<2; im++) {
4302  i = this->getIndex(th+in*st,ph+im*sp); // neighbour sky index
4303  if(p[i] >= p[j] || p[i] < -1.e9) continue;
4304 
4305  TH = sm->getTheta(i);
4306  PH = sm->getPhi(i);
4307  ST = sm->getThetaStep(i);
4308  m = 0; a = 0.;
4309  for(IN=-1; IN<2; IN++) {
4310  SP = sm->getPhiStep(getIndex(TH+IN*ST,PH));
4311  for(IM=-1; IM<2; IM++) {
4312  k = this->getIndex(TH+IN*ST,PH+IM*SP); // neighbour sky index
4313  if(p[i] >=p[k]) continue;
4314  m++; a += p[k];
4315  }
4316  }
4317  if(m>3) p[i] = a/m;
4318  }
4319  }
4320  }
4321  skyProb.waveSplit(pp,0,L-1,Lm);
4322  skyProb.waveSort(pp,Lm,L-1);
4323  }
4324 
4325  skyENRG = 0.;
4326  Eo = *pp[L-2]*0.9; // max L
4327  sum = vol = 0.;
4328  for(l=L-2; l>=Lm; l--) {
4329  a = (Eo - *pp[l]);
4330  skyENRG.data[L-l-1] = a;
4331  if(a < pSigma || vol<1.) {
4332  sum += a/(L-l-1);
4333  vol += 1;
4334  }
4335  *pp[l] -= Eo;
4336  }
4337 
4338  if(pOUT) cout<<sum/vol<<" "<<*pp[L-2]<<" "<<*pp[L-3]<<" "<<*pp[0]<<"\n";
4339 
4340  Eo = sum/vol/2.;
4341  *pp[0] = exp(-30.);
4342  for(l=L-1; l>0; l--) {
4343  a = l>Lm ? (L-l-1)*Eo : 30.;
4344  if(a > 30.) a = 30.;
4345  *pp[l] = exp(-a); // calculate skyProb map
4346  }
4347 
4348  if(pOUT) cout<<"norm: "<<(skyProb.mean()*L)<<endl;
4349  skyProb *= 1./(skyProb.mean()*L);
4350  for(l=0; l<L; l++) nProbability.set(l,log10(p[l])); // fill in skyProb map
4351 
4352  vf->clear();
4353  for(m=0; m<11; m++) { v[m] = 0; vf->push_back(0.); }
4354 
4355  sum = 0.;
4356  for(l=L-1; l>Lm; l--){
4357  for(m=size_t(sum*10.)+1; m<10; m++) v[m] += 1;
4358  sum += *pp[l];
4359  if(sum >= 0.9) break;
4360  }
4361 
4362  for(m=1; m<10; m++) (*vf)[m] = sqrt(v[m]*s);
4363 
4364 // fill skyProb skymap
4365 
4366  std::vector<float>* vP = &(this->wc_List[lag].p_Map[id-1]);
4367  std::vector<int>* vI = &(this->wc_List[lag].p_Ind[id-1]);
4368 
4369  K = 0;
4370  sum = 0.;
4371  vP->clear();
4372  vI->clear();
4373  double pthr=0;
4374  // if nSky -> nSky is converted into a probability threshold nSky=-XYZ... -> pthr=0.XYZ...
4375  if(nSky<0) {char spthr[1024];sprintf(spthr,"0.%d",int(abs(nSky)));pthr=atof(spthr);}
4376  for(l=L-1; l>Lm; l--){
4377  sum += *pp[l];
4378  if(nSky==0 && (K==1000 || sum > 0.99) && K>0) break;
4379  else if(nSky<0 && sum > pthr && K>0) break;
4380  else if(nSky>0 && K==nSky && K>0) break;
4381  K++;
4382  vI->push_back(int(pp[l]-p));
4383  vP->push_back(float(*pp[l]));
4384  }
4385 
4386 // set injections if there are any
4387 
4388  size_t M = this->mdc__IDSize();
4389 
4390  if(!M) { free(pp); return; }
4391 
4392  double dT = 1.e13;
4393  double injTime = 1.e12;
4394  int injID = -1;
4395  int mdcID = -1;
4396  injection INJ(this->ifoList.size());
4397 
4398  for(m=0; m<M; m++) {
4399  mdcID = this->getmdc__ID(m);
4400  dT = fabs(To - this->getmdcTime(mdcID));
4401  if(dT<injTime && INJ.fill_in(this,mdcID)) {
4402  injTime = dT;
4403  injID = mdcID;
4404  if(pOUT) printf("getSkyArea: %4d %12.4f %7.3f %f \n",int(m),To,dT,s);
4405  }
4406  }
4407 
4408  if(INJ.fill_in(this,injID)) {
4409 
4410  th = INJ.theta[0];
4411  ph = INJ.phi[0];
4412  i = this->getIndex(th,ph);
4413 
4414  vI->push_back(int(i));
4415  vP->push_back(float(p[i]));
4416 
4417  vol = sum = 0.;
4418  for(l=L-1; l>Lm; l--){
4419  vol += s;
4420  sum += *pp[l];
4421  if(pp[l]-p == int(i)) break;
4422  }
4423  (*vf)[0] = sqrt(vol);
4424  (*vf)[10] = sum;
4425  j = pp[L-1]-p; // reference sky index at max
4426 
4427  if(pOUT) {
4428  printf("getSkyArea: %5d %12.4f %6.1f %6.1f %6.1f %6.1f %6.2f %6.2f %6.2f %7.5f, %e %d \n",
4429  int(id),INJ.time[0]-this->getifo(0)->TFmap.start(),INJ.theta[0],INJ.phi[0],
4430  sm->getTheta(j),sm->getPhi(j),(*vf)[0],(*vf)[5],(*vf)[9],(*vf)[10],p[i],int(i));
4431  }
4432  }
4433 
4434  free(pp);
4435  return;
4436 }
4437 
4438 //**************************************************************************
4439 // calculate network likelihood for constructed clusters: 2-NIFO detectors
4440 // It is designed to replace likelihood functions for 2,3,4 and NIFO networks.
4441 // If the network has less then NIFO detectors, all arrays are allocated for NIFO
4442 // detectors anyway. The arrays are initialized so that the dummy detectors
4443 // do not contribute into calculation of the coherent statistics.
4444 // Both general and elliptical constraint can be executed
4445 //**************************************************************************
4446 long network::likelihood(char type, double Ao, int ID, size_t lag, int ind, bool core)
4447 {
4448  size_t nIFO = this->ifoList.size();
4449  this->tYPe = type;
4450  this->acor = Ao;
4451  if(nIFO>NIFO || !this->filter.size() || this->filter[0].index.size()!=32) {
4452  cout<<"network::likelihood(): invalid number of detectors or delay filter is not set.\n";
4453  return false;
4454  }
4455  if(type=='b' || type=='B' || type=='E')
4456  return likelihoodB(type, Ao, ID, lag, ind, core);
4457  else
4458  return likelihoodI(type, Ao, ID, lag, ind, core);
4459 }
4460 
4461 
4462 //**************************************************************************
4463 // calculate network likelihood for constructed clusters: 2-NIFO detectors
4464 // It is a new implementation for likelihood functions for networks of 2,3,4,NIFO
4465 // detectors with improved constraints. If the network has less then NIFO detectors,
4466 // all arrays are allocated for NIFO detectors anyway. The arrays are initialized
4467 // so that the dummy detectors do not contribute into calculation of the coherent
4468 // statistics.
4469 //**************************************************************************
4470 long network::likelihoodB(char type, double Ao, int iID, size_t lag, int ind, bool core)
4471 {
4472  this->like('B');
4473 
4474  size_t nIFO = this->ifoList.size();
4475  size_t ID = abs(iID);
4476  int N_1 = nIFO>2 ? int(nIFO)-1 : 2;
4477  int N_2 = nIFO>2 ? int(nIFO)-2 : 1;
4478  if(nIFO>NIFO || !this->filter.size() || this->filter[0].index.size()!=32) {
4479  cout<<"network::likelihood(): invalid number of detectors or delay filter is not set.\n";
4480  return false;
4481  }
4482 
4483 // regulators hard <- soft <0> weak -> hard
4484 // gamma = -1 <- 0 -> 1
4485 // delta = 0 -> 1
4486 
4487  double Eo = nIFO*Ao*Ao; // energy threshold in the sky loop
4488  double soft = delta>0 ? delta : 0.;
4489  double GAMMA = 1.-gamma*gamma; // network regulator
4490 
4491  int LOCAL = local ? 1 : 0; // ED minimization case
4492  double rho = this->netRHO*this->netRHO*nIFO; // threshold on rho
4493 
4494  double gr,gp,gx,gR,gI,gc,gg,gP,gX,T,rm,Le,E,LPm;
4495  double STAT,P,EE,Et,Lo,Lm,hh,Xp,Xx,XX,Lp,Em,Ep;
4496  double S,co,si,cc,em,um,vm,uc,us,vc,vs,Co,Cp;
4497  NETX(double c0;,double c1;,double c2;,double c3;,double c4;,double c5;,double c6;,double c7;)
4498  double inet;
4499 
4500  if(type=='E' && Eo<nIFO) Eo = double(nIFO);
4501  if(!ID && ind>=0) ind = -1;
4502  this->tYPe = type;
4503  this->acor = Ao;
4504 
4505  int ii,II,IIm;
4506  size_t i,j,k,l,m,n,V,U,K,id;
4507  size_t I = this->ifoList[0]->TFmap.maxLayer()+1;
4508  size_t M = this->filter.size()/I; // total number of delays
4509  size_t L = ind<0 ? this->index.size() : ind+1; // total number of source locations
4510  int R = int(this->ifoList[0]->getTFmap()->rate()/I+0.5);
4511 
4512 // pointers to data
4513  double* pdata[NIFO];
4514  double* qdata[NIFO];
4515  double* pq;
4516  for(n=0; n<nIFO; n++) {
4517  pdata[n] = getifo(n)->getTFmap()->data;
4518  qdata[n] = getifo(n)->getTFmap()->data;
4519  }
4520 
4521 // buffer for wavelet layer delay filter
4522  std::vector<float>* F;
4523  std::vector<short>* J;
4524 
4525 // get antenna patterns and index arrays
4526  double* fp[NIFO]; // f+
4527  double* fx[NIFO]; // fx
4528  double* ffp[NIFO]; // f+f+ + fxfx
4529  double* ffm[NIFO]; // f+f+ - fxfx
4530  double* fpx[NIFO]; // 2*f+fx
4531  wavearray<double> f00(L); f00 = 0.; // dummy zero array
4532 
4533  for(n=0; n<NIFO; n++) {
4534  fp[n] = n<nIFO ? getifo(n)->fp.data : f00.data;
4535  fx[n] = n<nIFO ? getifo(n)->fx.data : f00.data;
4536  ffp[n] = n<nIFO ? getifo(n)->ffp.data : f00.data;
4537  ffm[n] = n<nIFO ? getifo(n)->ffm.data : f00.data;
4538  fpx[n] = n<nIFO ? getifo(n)->fpx.data : f00.data;
4539  }
4540 
4541  short* mm = this->skyMask.data;
4542  NETX(
4543  short* m0 = getifo(0)->index.data; ,
4544  short* m1 = nIFO>1 ? getifo(1)->index.data : getifo(1)->index.data; ,
4545  short* m2 = nIFO>2 ? getifo(2)->index.data : getifo(1)->index.data; ,
4546  short* m3 = nIFO>3 ? getifo(3)->index.data : getifo(1)->index.data; ,
4547  short* m4 = nIFO>4 ? getifo(4)->index.data : getifo(1)->index.data; ,
4548  short* m5 = nIFO>5 ? getifo(5)->index.data : getifo(1)->index.data; ,
4549  short* m6 = nIFO>6 ? getifo(6)->index.data : getifo(1)->index.data; ,
4550  short* m7 = nIFO>7 ? getifo(7)->index.data : getifo(1)->index.data; )
4551 
4552 // allocate buffers
4553  std::vector<size_t> pI;
4554 
4555  wavearray<double> aS[NIFO]; // single whitened amplitude
4556  wavearray<double> eS[NIFO]; // energy SNR
4557  wavearray<double> NV[NIFO]; // noise variance
4558  wavearray<double> NR[NIFO]; // noise rms
4559  wavearray<double> cid; // buffers for cluster ID
4560  wavearray<double> cTo; // buffers for cluster time
4561  wavearray<double> vol; // buffers for cluster volume
4562  wavearray<double> xi(500); // buffers for detector responses
4563  wavearray<short> jU(2500); // buffers for likelihood normalization factor
4564  wavearray<double> Fplus(2500); // buffers for F+
4565  wavearray<double> Fcros(2500); // buffers for Fx
4566 
4567  double* px;
4568  double* nv[NIFO];
4569  double* nr[NIFO];
4570  double* pe[NIFO];
4571  double* pa[NIFO];
4572  double pp[NIFO];
4573  double qq[NIFO];
4574  double am[NIFO];
4575  double Fp[NIFO];
4576  double Fx[NIFO];
4577  double ee[NIFO];
4578  double rr[NIFO];
4579  double e[NIFO];
4580  double u[NIFO];
4581  double v[NIFO];
4582  double r[NIFO];
4583 
4584  U = 500;
4585  for(n=0; n<NIFO; n++) {
4586  NV[n].resize(U); NV[n] = 0.; nv[n] = NV[n].data;
4587  NR[n].resize(U); NR[n] = 0.; nr[n] = NR[n].data;
4588  aS[n].resize(U*M); aS[n] = 0.;
4589  eS[n].resize(U*M); eS[n] = 0.;
4590  rr[n] = 1.;
4591  }
4592 
4593  netpixel* pix;
4594  std::vector<int>* vint;
4595  std::vector<int>* vtof;
4596 
4597  bool skip;
4598  double logbpp;
4599  size_t count = 0;
4600 
4601  S = 0.;
4602  if(ID) {
4603  this->pixeLHood = getifo(0)->TFmap;
4604  this->pixeLHood = 0.;
4605  this->pixeLNull = getifo(0)->TFmap;
4606  this->pixeLNull = 0.;
4607  this->nSensitivity = 0.;
4608  this->nAlignment = 0.;
4609  this->nNetIndex = 0.;
4610  this->nDisbalance = 0.;
4611  this->nLikelihood = 0.;
4612  this->nNullEnergy = 0.;
4613  this->nCorrEnergy = 0.;
4614  this->nCorrelation = 0.;
4615  this->nSkyStat = 0.;
4616  this->nPenalty = 0.;
4617  this->nProbability = 0.;
4618  this->nAntenaPrior = 0.;
4619  }
4620 
4621 //+++++++++++++++++++++++++++++++++++++++
4622 // liklihood calculation for clusters
4623 //+++++++++++++++++++++++++++++++++++++++
4624 
4625  for(n=lag; n<nLag; n++) { // loop over time shifts
4626 
4627  if(!this->wc_List[n].size()) continue;
4628  logbpp = -log(this->wc_List[n].getbpp());
4629 
4630  cid = this->wc_List[n].get((char*)"ID",0,'S',optim ? R : -R); // get cluster ID
4631  cTo = this->wc_List[n].get((char*)"time",0,'L',optim ? R : -R); // get cluster time
4632 
4633  K = cid.size();
4634 
4635  for(k=0; k<K; k++) { // loop over clusters
4636 
4637  id = size_t(cid.data[k]+0.1);
4638 
4639  if(ID && id!=ID) continue;
4640 
4641  vint = &(this->wc_List[n].cList[id-1]); // pixel list
4642  vtof = &(this->wc_List[n].nTofF[id-1]); // TofFlight configurations
4643 
4644  V = vint->size();
4645  if(!V) continue;
4646 
4647  pI.clear();
4648 
4649  for(j=0; j<V; j++) { // loop over pixels
4650 
4651  pix = this->wc_List[n].getPixel(id,j);
4652 
4653  if(!pix) {
4654  cout<<"network::likelihood() error: NULL pointer"<<endl;
4655  exit(1);
4656  }
4657 
4658  if(R != int(pix->rate+0.5)) continue; // check rate
4659  if(!pix->core && core) continue; // check core flag
4660 
4661  pI.push_back(j); // save pixel index
4662 
4663  }
4664 
4665  V = pI.size();
4666  if(!V) continue;
4667 
4668  if(NV[0].size() < V) { // reallocate arrays
4669  U = V+100;
4670  for(i=0; i<NIFO; i++) {
4671  NV[i].resize(U); NV[i] = 0.; nv[i] = NV[i].data;
4672  NR[i].resize(U); NR[i] = 0.; nr[i] = NR[i].data;
4673  eS[i].resize(U*M); eS[i] = 0.;
4674  aS[i].resize(U*M); aS[i] = 0.;
4675  }
4676  jU.resize(U); xi.resize(U*NIFO);
4677  Fplus.resize(U*NIFO); Fcros.resize(U*NIFO);
4678  }
4679 
4680  for(j=0; j<V; j++) { // loop over selected pixels
4681 
4682  pix = this->wc_List[n].getPixel(id,pI[j]);
4683 
4684  cc = 0.;
4685  for(i=0; i<nIFO; i++) {
4686  ee[i] = 1./pix->data[i].noiserms;
4687  cc += ee[i]*ee[i]; // total inverse variance
4688  }
4689 
4690  for(i=0; i<nIFO; i++) {
4691  nv[i][j] = ee[i]*ee[i]; // inverse variance
4692  nr[i][j] = ee[i]/sqrt(cc); // normalized 1/rms
4693  qdata[i] = pdata[i] + pix->data[i].index; // pointer to data
4694  }
4695 
4696 // apply delay filter
4697 
4698  for(i=0; i<nIFO; i++) {
4699  pq = qdata[i];
4700 
4701  for(m=0; m<M; m++){ // loop over delays
4702  F = &(filter[pix->frequency*M+m].value);
4703  J = &(filter[pix->frequency*M+m].index);
4704  l = m*V + j;
4705 
4706  gg = dot32(F,pq,J); // apply filter
4707 
4708  eS[i].data[l] = gg*gg;
4709  aS[i].data[l] = gg;
4710  }
4711  }
4712  }
4713 
4714  STAT = -1.e64; m=IIm=0; Lm=Em=LPm= 0.;
4715 
4716 // Max Energy
4717 
4718  if(type == 'E') {
4719 
4720  skip = true;
4721  l = ind<0 ? 0 : ind; // process selected index
4722  for(; l<L; l++) { // loop over sky locations
4723  if(!mm[l]) continue; // skip identical delay configurations
4724 
4725  NETX(
4726  pe[0] = eS[0].data + m0[l]*V; ,
4727  pe[1] = eS[1].data + m1[l]*V; ,
4728  pe[2] = eS[2].data + m2[l]*V; ,
4729  pe[3] = eS[3].data + m3[l]*V; ,
4730  pe[4] = eS[4].data + m4[l]*V; ,
4731  pe[5] = eS[5].data + m5[l]*V; ,
4732  pe[6] = eS[6].data + m6[l]*V; ,
4733  pe[7] = eS[7].data + m7[l]*V; )
4734 
4735  NETX(c0=0.;,c1=0.;,c2=0.;,c3=0.;,c4=0.;,c5=0.;,c6=0.;,c7=0.;)
4736  i=0;
4737  for(j=0; j<V; j++) { // loop over selected pixels
4738  double pet = 0.;
4739  NETX(
4740  pet+=pe[0][j]; ,
4741  pet+=pe[1][j]; ,
4742  pet+=pe[2][j]; ,
4743  pet+=pe[3][j]; ,
4744  pet+=pe[4][j]; ,
4745  pet+=pe[5][j]; ,
4746  pet+=pe[6][j]; ,
4747  pet+=pe[7][j]; )
4748  if(pet > Eo) {
4749  NETX(
4750  c0 += pe[0][j]; ,
4751  c1 += pe[1][j]; ,
4752  c2 += pe[2][j]; ,
4753  c3 += pe[3][j]; ,
4754  c4 += pe[4][j]; ,
4755  c5 += pe[5][j]; ,
4756  c6 += pe[6][j]; ,
4757  c7 += pe[7][j]; )
4758  i++;
4759  }
4760  }
4761 
4762  E = 0.; NETX(E+=c0;,E+=c1;,E+=c2;,E+=c3;,E+=c4;,E+=c5;,E+=c6;,E+=c7;) E-=i*nIFO; // correction for dummy detectors
4763  if(E>STAT) { m = l; STAT = E; Lm = E; } // maximize energy
4764  E += i;
4765  if(NETX(E-c0>e2or &&,E-c1>e2or &&,E-c2>e2or &&,E-c3>e2or &&,E-c4>e2or &&,E-c5>e2or &&,E-c6>e2or &&,E-c7>e2or &&) true) skip = false;
4766  }
4767  if(skip) { this->wc_List[n].ignore(id); continue; }
4768  }
4769 
4770 // constraint: total (XkSk-ekSkSk)/Ek = 0
4771 
4772  else {
4773 
4774  l = ind<0 ? 0 : ind; // process selected index
4775  for(; l<L; l++) { // loop over sky locations
4776 
4777  skyProb.data[l] = 0.;
4778 
4779  if(skyMaskCC.size()==L) {
4780  // transform l in celestial coordinates cc_l and check the skyMaskCC
4781  skymap* sm = &(this->nSkyStat);
4782  double th = sm->getTheta(l);
4783  double ph = sm->getPhi(l);
4784  double gpsT = cTo.data[k]+getifo(0)->TFmap.start(); // trigger time
4785  double ra = sm->phi2RA(ph, gpsT);
4786  int cc_l = this->getIndex(th,ra);
4787  if (skyMaskCC.data[cc_l]<=0) continue;
4788  }
4789 
4790  if(!mm[l] && ind<0) continue; // skip sky configurations
4791 
4792  NETX(
4793  pa[0] = aS[0].data + m0[l]*V; , // single whitening
4794  pa[1] = aS[1].data + m1[l]*V; ,
4795  pa[2] = aS[2].data + m2[l]*V; ,
4796  pa[3] = aS[3].data + m3[l]*V; ,
4797  pa[4] = aS[4].data + m4[l]*V; ,
4798  pa[5] = aS[5].data + m5[l]*V; ,
4799  pa[6] = aS[6].data + m6[l]*V; ,
4800  pa[7] = aS[7].data + m7[l]*V; )
4801 
4802 // weak constraint
4803 // transformation to PCF,
4804 // u = [X x (f+ x fx)] x (f+ x fx)
4805 // u/(|u|*|X|) is a unity vector along the projection of X
4806 // u = Fp*uc + Fx*us
4807 
4808 
4809  EE=Lo=Co=Ep=Lp=Cp=inet = 0.; II=0;
4810 
4811  for(j=0; j<V; j++) { // loop over selected pixels
4812 
4813  Et = dotx(pa,j,pa,j); // total energy
4814  ii = int(Et>Eo);
4815  EE+= Et*ii;
4816 
4817  mulx(fp,l,nr,j,Fp);
4818  mulx(fx,l,nr,j,Fx);
4819 
4820  gp = dotx(Fp,Fp)+1.e-12; // fp^2
4821  gx = dotx(Fx,Fx)+1.e-12; // fx^2
4822  gI = dotx(Fp,Fx); // fp*fx
4823  Xp = dotx(Fp,pa,j); // (X*f+)
4824  Xx = dotx(Fx,pa,j); // (X*fx)
4825  uc = Xp*gx - Xx*gI; // u cos of rotation to PCF
4826  us = Xx*gp - Xp*gI; // u sin of rotation to PCF
4827  um = rotx(Fp,uc,Fx,us,u); // calculate u and return its norm
4828  hh = dotx(u,pa,j,e); // (u*X) - not normalized
4829  Le = hh*hh/um;
4830  cc = Le-dotx(e,e)/um;
4831  ii*= int(cc>0);
4832 
4833  Lp+= Le*cc*ii/(Et-Le+1+cc); // effective likelihood
4834  Ep+= Et*ii;
4835  Lo+= Le*ii; // baseline Likelihood
4836  Co+= cc*ii; // coherent energy
4837  II+= ii;
4838  mulx(u,hh*ii/um,xi.data+j*NIFO);
4839 
4840  }
4841 
4842  cc = Ep>0 ? Co/(Ep-Lo+II+fabs(Co)) : 0.;
4843  if(type=='B') Lp = Lo*cc;
4844 
4845  skyProb.data[l] = Lp/EE;
4846 
4847  if(Lp>LPm) { LPm=Lp; Em=EE; IIm=II; }
4848 
4849  cc = EE>0 ? Co/(EE-Lo+II+fabs(Co)) : 0.;
4850  if(cc<this->netCC || cc*Co<rho) continue;
4851 
4852 // weak and hard regulators used for estimation of u
4853 // v = u x (f+ x fx) is a vector perpendicular to u
4854 // u = Fp*uc + Fx*us, v = Fx*vc - Fp*vs
4855 
4856  Lo=Co=gP=gX = 0.;
4857 
4858  for(j=0; j<V; j++) { // loop over selected pixels
4859 
4860  NETX(
4861  am[0] = pa[0][j]; ,
4862  am[1] = pa[1][j]; ,
4863  am[2] = pa[2][j]; ,
4864  am[3] = pa[3][j]; ,
4865  am[4] = pa[4][j]; ,
4866  am[5] = pa[5][j]; ,
4867  am[6] = pa[6][j]; ,
4868  am[7] = pa[7][j]; )
4869 
4870  px = xi.data+j*NIFO;
4871  if(dotx(px,px)<=0) continue;
4872  Et = dotx(am,am);
4873 
4874  mulx(fp,l,nr,j,Fp);
4875  mulx(fx,l,nr,j,Fx);
4876 
4877  gp = dotx(Fp,Fp)+1.e-12; // fp^2
4878  gx = dotx(Fx,Fx)+1.e-12; // fx^2
4879  gI = dotx(Fp,Fx); // fp*fx
4880  gr = (gp+gx)/2.; // sensitivity
4881  gR = (gp-gx)/2.; // real part of gc
4882  gc = sqrt(gR*gR+gI*gI); // norm of complex antenna pattern
4883 
4884  Xp = dotx(Fp,am); // (X*f+)
4885  Xx = dotx(Fx,am); // (X*fx)
4886  uc = Xp*gx - Xx*gI; // u cos of rotation to PCF
4887  us = Xx*gp - Xp*gI; // u sin of rotation to PCF
4888  vc = gp*uc + gI*us; // (u*f+)/|u|^2 - 'cos' for v
4889  vs = gx*us + gI*uc; // (u*fx)/|u|^2 - 'sin' for v
4890  um = rotx(Fp,uc,Fx,us,u); // calculate new response vector
4891  vm = rotx(Fx,-vc,Fp,vs,v)+1.e-24; // calculate complementary vector
4892 
4893 // regulator
4894 
4895  ii = netx(u,um,v,vm,GAMMA); // network index
4896  inet += ii*Et;
4897  if(ii<N_2 && gamma<0) continue; // superclean selection cut
4898 
4899  gP+= (gr+gc)*Et; // + sensitivity
4900  gX+= (gr-gc)*Et; // x sensitivity
4901  gg = (gp+gx)*soft;
4902  uc = Xp*(gx+gg) - Xx*gI; // u cos of rotation to PCF
4903  us = Xx*(gp+gg) - Xp*gI; // u sin of rotation to PCF
4904 
4905  if(ii<N_1 && gamma!=0) {
4906  uc = Xp*(gc+gR)+Xx*gI;
4907  us = Xx*(gc-gR)+Xp*gI;
4908  }
4909 
4910  vc = gp*uc + gI*us; // (u*f+)/|u|^2 - 'cos' for v
4911  vs = gx*us + gI*uc; // (u*fx)/|u|^2 - 'sin' for v
4912  um = rotx(Fp,uc,Fx,us,u); // calculate new response vector
4913  vm = rotx(Fx,-vc,Fp,vs,v)+1.e-24; // calculate complementary vector
4914 
4915 // energy disbalance ratio vectors
4916 
4917  NETX (
4918  rr[0] = LOCAL*am[0]/(am[0]*am[0]+2.)+1-LOCAL; ,
4919  rr[1] = LOCAL*am[1]/(am[1]*am[1]+2.)+1-LOCAL; ,
4920  rr[2] = LOCAL*am[2]/(am[2]*am[2]+2.)+1-LOCAL; ,
4921  rr[3] = LOCAL*am[3]/(am[3]*am[3]+2.)+1-LOCAL; ,
4922  rr[4] = LOCAL*am[4]/(am[4]*am[4]+2.)+1-LOCAL; ,
4923  rr[5] = LOCAL*am[5]/(am[5]*am[5]+2.)+1-LOCAL; ,
4924  rr[6] = LOCAL*am[6]/(am[6]*am[6]+2.)+1-LOCAL; ,
4925  rr[7] = LOCAL*am[7]/(am[7]*am[7]+2.)+1-LOCAL; )
4926 
4927  hh = dotx(u,am)/um;
4928  NETX (
4929  pp[0] = rr[0]*(am[0]-hh*u[0])*u[0]; ,
4930  pp[1] = rr[1]*(am[1]-hh*u[1])*u[1]; ,
4931  pp[2] = rr[2]*(am[2]-hh*u[2])*u[2]; ,
4932  pp[3] = rr[3]*(am[3]-hh*u[3])*u[3]; ,
4933  pp[4] = rr[4]*(am[4]-hh*u[4])*u[4]; ,
4934  pp[5] = rr[5]*(am[5]-hh*u[5])*u[5]; ,
4935  pp[6] = rr[6]*(am[6]-hh*u[6])*u[6]; ,
4936  pp[7] = rr[7]*(am[7]-hh*u[7])*u[7]; )
4937 
4938  gg = dotx(v,am)/um;
4939  hh*= 2.;
4940  NETX (
4941  qq[0] = rr[0]*((hh*u[0]-am[0])*v[0]+u[0]*u[0]*gg); ,
4942  qq[1] = rr[1]*((hh*u[1]-am[1])*v[1]+u[1]*u[1]*gg); ,
4943  qq[2] = rr[2]*((hh*u[2]-am[2])*v[2]+u[2]*u[2]*gg); ,
4944  qq[3] = rr[3]*((hh*u[3]-am[3])*v[3]+u[3]*u[3]*gg); ,
4945  qq[4] = rr[4]*((hh*u[4]-am[4])*v[4]+u[4]*u[4]*gg); ,
4946  qq[5] = rr[5]*((hh*u[5]-am[5])*v[5]+u[5]*u[5]*gg); ,
4947  qq[6] = rr[6]*((hh*u[6]-am[6])*v[6]+u[6]*u[6]*gg); ,
4948  qq[7] = rr[7]*((hh*u[7]-am[7])*v[7]+u[7]*u[7]*gg); )
4949 
4950  co = dotx(qq,qq)/vm+dotx(pp,pp)/um+1.e-24; // cos term
4951  si = dotx(pp,qq); // sin term
4952  if(!eDisbalance) {co=1.;si=0.;}
4953  em = rotx(u,co,v,si/vm,e); // calculate rotated vector e
4954 
4955 // second iteration
4956 
4957  rm = rotx(v,co,u,-si/um,r)+1.e-24; // calculate rotated vector v
4958  hh = dotx(e,am)/em;
4959 
4960  NETX (
4961  pp[0] = rr[0]*(am[0]-hh*e[0])*e[0]; ,
4962  pp[1] = rr[1]*(am[1]-hh*e[1])*e[1]; ,
4963  pp[2] = rr[2]*(am[2]-hh*e[2])*e[2]; ,
4964  pp[3] = rr[3]*(am[3]-hh*e[3])*e[3]; ,
4965  pp[4] = rr[4]*(am[4]-hh*e[4])*e[4]; ,
4966  pp[5] = rr[5]*(am[5]-hh*e[5])*e[5]; ,
4967  pp[6] = rr[6]*(am[6]-hh*e[6])*e[6]; ,
4968  pp[7] = rr[7]*(am[7]-hh*e[7])*e[7]; )
4969 
4970  gg = dotx(r,am)/em;
4971  hh*= 2.;
4972  NETX (
4973  qq[0] = rr[0]*((hh*e[0]-am[0])*r[0]+e[0]*e[0]*gg); ,
4974  qq[1] = rr[1]*((hh*e[1]-am[1])*r[1]+e[1]*e[1]*gg); ,
4975  qq[2] = rr[2]*((hh*e[2]-am[2])*r[2]+e[2]*e[2]*gg); ,
4976  qq[3] = rr[3]*((hh*e[3]-am[3])*r[3]+e[3]*e[3]*gg); ,
4977  qq[4] = rr[4]*((hh*e[4]-am[4])*r[4]+e[4]*e[4]*gg); ,
4978  qq[5] = rr[5]*((hh*e[5]-am[5])*r[5]+e[5]*e[5]*gg); ,
4979  qq[6] = rr[6]*((hh*e[6]-am[6])*r[6]+e[6]*e[6]*gg); ,
4980  qq[7] = rr[7]*((hh*e[7]-am[7])*r[7]+e[7]*e[7]*gg); )
4981 
4982  co = dotx(qq,qq)/rm+dotx(pp,pp)/em+1.e-24; // cos term
4983  si = dotx(pp,qq); // sin term
4984  if(!eDisbalance) {co=1.;si=0.;}
4985  em = rotx(e,co,r,si/rm,e); // calculate ED vector
4986  hh = dotx(e,am,ee); // ee[i] = e[i]*am[i]
4987  Lo+= hh*hh/em; // corrected L
4988  Co+= (hh*hh-dotx(ee,ee))/em; // coherent energy
4989 
4990  }
4991 
4992 // <x*xi> penalty factor and asymmetry
4993 
4994  NETX(pp[0]=0.;,pp[1]=0.;,pp[2]=0.;,pp[3]=0.;,pp[4]=0.;,pp[5]=0.;,pp[6]=0.;,pp[7]=0.;)
4995  NETX(qq[0]=0.001;,qq[1]=0.001;,qq[2]=0.001;,qq[3]=0.001;,qq[4]=0.001;,qq[5]=0.001;,qq[6]=0.001;,qq[7]=0.001;)
4996  NETX(ee[0]=0.;,ee[1]=0.;,ee[2]=0.;,ee[3]=0.;,ee[4]=0.;,ee[5]=0.;,ee[6]=0.;,ee[7]=0.;)
4997 
4998  for(j=0; j<V; j++) { // loop over selected pixels
4999  px = xi.data+j*NIFO;
5000  addx(px,px,qq);
5001  addx(px,pa,j,pp);
5002  addx(pa,j,pa,j,ee);
5003  }
5004 
5005  S = 0.;
5006  NETX (
5007  S+= fabs(pp[0]-qq[0]); ,
5008  S+= fabs(pp[1]-qq[1]); ,
5009  S+= fabs(pp[2]-qq[2]); ,
5010  S+= fabs(pp[3]-qq[3]); ,
5011  S+= fabs(pp[4]-qq[4]); ,
5012  S+= fabs(pp[5]-qq[5]); ,
5013  S+= fabs(pp[6]-qq[6]); ,
5014  S+= fabs(pp[7]-qq[7]); )
5015 
5016  NETX (
5017  pp[0] /= sqrt(qq[0]); ,
5018  pp[1] /= sqrt(qq[1]); ,
5019  pp[2] /= sqrt(qq[2]); ,
5020  pp[3] /= sqrt(qq[3]); ,
5021  pp[4] /= sqrt(qq[4]); ,
5022  pp[5] /= sqrt(qq[5]); ,
5023  pp[6] /= sqrt(qq[6]); ,
5024  pp[7] /= sqrt(qq[7]); )
5025 
5026  hh = 0.;
5027  NETX (
5028  hh+= pp[0]; ,
5029  hh+= pp[1]; ,
5030  hh+= pp[2]; ,
5031  hh+= pp[3]; ,
5032  hh+= pp[4]; ,
5033  hh+= pp[5]; ,
5034  hh+= pp[6]; ,
5035  hh+= pp[7]; )
5036  gg = 0.;
5037  NETX (
5038  gg+= sqrt(ee[0]); ,
5039  gg+= sqrt(ee[1]); ,
5040  gg+= sqrt(ee[2]); ,
5041  gg+= sqrt(ee[3]); ,
5042  gg+= sqrt(ee[4]); ,
5043  gg+= sqrt(ee[5]); ,
5044  gg+= sqrt(ee[6]); ,
5045  gg+= sqrt(ee[7]); )
5046 
5047  P = hh/gg; // Pearson's correlation penalty
5048  cc = Co/(EE-Lo+fabs(Co)); // network correlation coefficient
5049  XX = Lo*cc/EE; // sky statistic
5050 
5051  skyProb.data[l] *= P;
5052 
5053  if(XX>=STAT) { m=l; STAT=XX; Lm=Lo; }
5054 
5055  if(ID) { // fill in skymaps
5056  this->nAntenaPrior.set(l, gP/EE);
5057  this->nSensitivity.set(l, gP/EE);
5058  this->nAlignment.set(l, gX/EE);
5059  this->nNetIndex.set(l, inet/EE);
5060  this->nDisbalance.set(l, S);
5061  this->nLikelihood.set(l, Lo);
5062  this->nNullEnergy.set(l, (EE-Lo));
5063  this->nCorrEnergy.set(l, Co);
5064  this->nCorrelation.set(l, cc);
5065  this->nSkyStat.set(l, XX);
5066  this->nPenalty.set(l, P);
5067  this->nProbability.set(l,skyProb.data[l]);
5068  }
5069  }
5070 
5071  if(STAT<=0.001 && ind<0) {
5072  this->wc_List[n].ignore(id); // reject cluster
5073  continue;
5074  }
5075  }
5076 
5077 // final calculation of likelihood for selected sky location
5078 
5079  Lo = E = 0.;
5080  l = ind<0 ? m : ind;
5081 
5082  NETX (
5083  pa[0] = aS[0].data + m0[l]*V; , // single whitening
5084  pa[1] = aS[1].data + m1[l]*V; ,
5085  pa[2] = aS[2].data + m2[l]*V; ,
5086  pa[3] = aS[3].data + m3[l]*V; ,
5087  pa[4] = aS[4].data + m4[l]*V; ,
5088  pa[5] = aS[5].data + m5[l]*V; ,
5089  pa[6] = aS[6].data + m6[l]*V; ,
5090  pa[7] = aS[7].data + m7[l]*V; )
5091 
5092 // initialize detector energy array
5093 
5094  for(j=0; j<V; j++) { // loop over selected pixels
5095 
5096  Et = 0.; U = 1;
5097  for(i=0; i<nIFO; i++) {
5098  am[i] = pa[i][j];
5099  Fp[i] = fp[i][l]*nr[i][j];
5100  Fx[i] = fx[i][l]*nr[i][j];
5101  Et += am[i]*am[i];
5102  if(!j) ee[i] = 0.;
5103  }
5104 
5105  gp = dotx(Fp,Fp)+1.e-12; // (fp^2)
5106  gx = dotx(Fx,Fx)+1.e-12; // (fx^2)
5107  gI = dotx(Fp,Fx); // (fp*fx)
5108  Xp = dotx(Fp,am); // (X*f+)
5109  Xx = dotx(Fx,am); // (X*fx)
5110  gR = (gp-gx)/2.;
5111  gc = sqrt(gR*gR+gI*gI); // norm of complex antenna pattern
5112  uc = Xp*gx - Xx*gI; // u cos
5113  us = Xx*gp - Xp*gI; // u sin
5114  vc = gp*uc + gI*us; // (u*f+)/|u|^2 - 'cos' for v
5115  vs = gx*us + gI*uc; // (u*fx)/|u|^2 - 'sin' for v
5116  um = rotx(Fp,uc,Fx,us,u); // calculate u and return its norm
5117  vm = rotx(Fx,-vc,Fp,vs,v)+1.e-24; // calculate v and return its norm
5118  hh = dotx(u,am,e); // GW amplitude
5119 
5120  if((hh*hh-dotx(e,e))/um<=0.) U=0;
5121 
5122 // regulator
5123 
5124  ii = 0;
5125  for(i=0; i<nIFO; i++) {
5126  if(u[i]*u[i]/um > 1-GAMMA) ii++;
5127  if(u[i]*u[i]/um+v[i]*v[i]/vm > GAMMA) ii--;
5128  }
5129 
5130  if(ii<N_2 && gamma<0.) U = 0;
5131 
5132  gg = (gp+gx)*soft;
5133  uc = Xp*(gx+gg) - Xx*gI; // u cos of rotation to PCF
5134  us = Xx*(gp+gg) - Xp*gI; // u sin of rotation to PCF
5135 
5136  if(ii<N_1 && gamma!=0) {
5137  uc = Xp*(gc+gR)+Xx*gI;
5138  us = Xx*(gc-gR)+Xp*gI;
5139  }
5140 
5141  vc = (gp*uc + gI*us); // (u*f+)/|u|^2 - 'cos' for v
5142  vs = (gx*us + gI*uc); // (u*fx)/|u|^2 - 'sin' for v
5143  um = rotx(Fp,uc,Fx,us,u); // calculate u and return its norm
5144  vm = rotx(Fx,-vc,Fp,vs,v)+1.e-24; // calculate v and return its norm
5145 
5146 // normalize u and v vectors
5147 
5148  um = sqrt(um);
5149  vm = sqrt(vm);
5150 
5151  hh = gg = 0.;
5152  for(i=0; i<nIFO; i++) {
5153  u[i] = u[i]/um;
5154  v[i] = v[i]/vm;
5155  hh += u[i]*am[i]; // (u*X) - solution
5156  gg += v[i]*am[i]; // (v*X) - solution
5157  }
5158 
5159 // calculate energy disbalance vectors
5160 
5161  co=si=0.;
5162  for(i=0; i<nIFO; i++) { // disbalance vectors
5163  cc = local ? am[i]/(am[i]*am[i]+2.) : 1.;
5164  pp[i] = cc*(am[i]-hh*u[i])*u[i];
5165  qq[i] = cc*((2.*hh*u[i]-am[i])*v[i] + u[i]*u[i]*gg);
5166  co += pp[i]*pp[i] + qq[i]*qq[i]; // cos (version 1)
5167  si += pp[i]*qq[i]; // sin
5168  }
5169  cc = sqrt(si*si+co*co)+1.e-24;
5170  co = co/cc;
5171  si = si/cc;
5172  if(!eDisbalance) {co=1.;si=0.;}
5173 
5174 // corrected likelihood
5175 
5176  hh=gg = 0.;
5177  for(i=0; i<nIFO; i++) { // solution for h(t,f)
5178  e[i] = u[i]*co + v[i]*si; // final projection vector
5179  r[i] = v[i]*co - u[i]*si; // orthogonal v vector
5180  hh += e[i]*am[i]; // solution for hu(t,f)
5181  gg += r[i]*am[i]; // solution for hv(t,f)
5182  }
5183 
5184 // second iteration
5185 
5186  co=si=0.;
5187  for(i=0; i<nIFO; i++) { // disbalance vectors
5188  cc = local ? am[i]/(am[i]*am[i]+2.) : 1.;
5189  pp[i] = cc*(am[i]-hh*e[i])*e[i];
5190  qq[i] = cc*((2.*hh*e[i]-am[i])*r[i] + e[i]*e[i]*gg);
5191  co += pp[i]*pp[i] + qq[i]*qq[i]; // cos (version 1)
5192  si += pp[i]*qq[i]; // sin
5193  }
5194  cc = sqrt(si*si+co*co)+1.e-24;
5195  co = co/cc;
5196  si = si/cc;
5197  if(!eDisbalance) {co=1.;si=0.;}
5198 
5199  if(type=='E') U = 0;
5200  hh = 0.;
5201  for(i=0; i<nIFO; i++) { // solution for h(t,f)
5202  e[i] = e[i]*co+r[i]*si; // final projection vector
5203  hh += e[i]*am[i]*U; // solution for h(t,f)
5204  }
5205 
5206 // fill in pix
5207 
5208  Lp = hh*hh; // likelihood
5209 
5210  if(Et>Eo) {
5211  Lo += (type=='E') ? Et-nIFO : Lp; // calculate Lc for x-check
5212  E += Et;
5213  }
5214 
5215  pix = this->wc_List[n].getPixel(id,pI[j]);
5216  pix->likelihood = (type=='E') ? Et-nIFO : Lp;
5217  pix->theta = nLikelihood.getTheta(l);
5218  pix->phi = nLikelihood.getPhi(l);
5219  if(!core) pix->core = Et<Eo ? false : true;
5220 
5221  for(i=0; i<nIFO; i++) {
5222  pix->setdata(am[i],'S',i); // whitened data
5223  pix->setdata(e[i]*hh/sqrt(nv[i][j]),'W',i); // detector response
5224  }
5225 
5226  if(ID) {
5227  this->pixeLHood.data[pix->time] = Lp;
5228  this->pixeLNull.data[pix->time] = Et-Lp+1.;
5229  if(pOUT) {
5230  cout<<j<<" SNR="<<Et<<" ";
5231  for(i=0; i<nIFO; i++) {
5232  cout<<e[i]*e[i]<<":"<<am[i]*am[i]/Et<<" ";
5233  }
5234  cout<<endl;
5235  }
5236  }
5237  count++;
5238  }
5239 
5240 // fill in backward delay configuration
5241 
5242  vtof->clear();
5243  NETX (
5244  vtof->push_back(int(M/2)-int(m0[l])); ,
5245  vtof->push_back(int(M/2)-int(m1[l])); ,
5246  vtof->push_back(int(M/2)-int(m2[l])); ,
5247  vtof->push_back(int(M/2)-int(m3[l])); ,
5248  vtof->push_back(int(M/2)-int(m4[l])); ,
5249  vtof->push_back(int(M/2)-int(m5[l])); ,
5250  vtof->push_back(int(M/2)-int(m6[l])); ,
5251  vtof->push_back(int(M/2)-int(m7[l])); )
5252 
5253  skyProb *= Em/IIm;
5254  T = cTo.data[k]+getifo(0)->TFmap.start(); // trigger time
5255  if(iID<=0 && type!='E') getSkyArea(id,n,T); // calculate error regions
5256 
5257  if(fabs((Lm-Lo)/Lo)>1.e-4)
5258  cout<<"likelihood: incorrect likelihood : "<<Lm<<" "<<Lo<<" "<<Em<<endl;
5259 
5260  if(E>0 && ID) {
5261  cout<<"max value: "<<STAT<<" at (theta,phi) = ("<<nLikelihood.getTheta(l)
5262  <<","<<nLikelihood.getPhi(l)<<") Likelihood: loop: "<<Lm
5263  <<", final: "<<Lo<<", eff: "<<Em<<endl;
5264  break;
5265  }
5266 
5267  if(ID && !EFEC) {
5268  this->nSensitivity.gps = T;
5269  this->nAlignment.gps = T;
5270  this->nNetIndex.gps = T;
5271  this->nDisbalance.gps = T;
5272  this->nLikelihood.gps = T;
5273  this->nNullEnergy.gps = T;
5274  this->nCorrEnergy.gps = T;
5275  this->nCorrelation.gps = T;
5276  this->nSkyStat.gps = T;
5277  this->nPenalty.gps = T;
5278  this->nProbability.gps = T;
5279  }
5280  } // end of loop over clusters
5281  if(ID) break;
5282  } // end of loop over time shifts
5283  return count;
5284 }
5285 
5286 
5287 //*********************************************************************************
5288 // calculate network likelihood for 2-NIFO detectors assuming elliptical polarisation.
5289 // elliptical constraint is used in a combination with the energy disbalance constraint
5290 // It is designed to replace likelihood functions for 2,3,4 and NIFO networks.
5291 // If the network has less then NIFO detectors, all arrays are allocated for NIFO
5292 // detectors anyway. The arrays are initialized so that the dummy detectors
5293 // do not contribute into calculation of the coherent statistics.
5294 //*********************************************************************************
5295 
5296 long network::likelihoodI(char type, double Ao, int iID, size_t lag, int ind, bool core)
5297 {
5298  this->like('I');
5299 
5300  size_t jN = 500;
5301  size_t nIFO = this->ifoList.size();
5302  size_t ID = abs(iID);
5303  int N_1 = nIFO>2 ? int(nIFO)-1 : 2;
5304  int N_2 = nIFO>2 ? int(nIFO)-2 : 1;
5305  if(nIFO>NIFO || !this->filter.size() || this->filter[0].index.size()!=32) {
5306  cout<<"network::likelihoodE(): invalid number of detectors or delay filter is not set.\n";
5307  return false;
5308  }
5309 
5310 // regulators hard <- soft <0> weak -> hard
5311 // gamma = -1 <- 0 -> 1
5312 // delta = 0 -> 1
5313 
5314  double Eo = nIFO*Ao*Ao; // energy threshold in the sky loop
5315  double soft = delta>0 ? delta : 0.;
5316  double GAMMA = 1.-gamma*gamma; // network regulator
5317  int LOCAL = local ? 1 : 0; // ED minimization case
5318 
5319  double rho = this->netRHO*this->netRHO*nIFO; // threshold on rho
5320  double one = (type=='g' || type=='G') ? 0. : 1.; // circular polarization
5321  double En = (type!='i' && type!='I') ? 1.e9 : 1.;
5322  bool ISG = false;
5323  bool isgr = false;
5324 
5325  if(type=='I' || type=='S' || type=='G') ISG = true;
5326  if(type=='i' || type=='s' || type=='g') ISG = true;
5327  if(type=='i' || type=='s' || type=='g' || type=='r') isgr = true;
5328 
5329  if(!ID && ind>=0) ind = -1;
5330  this->tYPe = type;
5331  this->acor = Ao;
5332 
5333  int ii,II,IIm;
5334  double gr,gg,gc,gp,gx,cc,gP,gX,gR,gI,EE,Et,T,Em,LPm,HH;
5335  double em,STAT,Lo,Lm,Lp,Co,E00,E90,L00,C00,AA,CO,SI;
5336  double co,si,stat,XP,XX,L90,C90,sI,cO,aa,bb,as,ac,ap,La;
5337  double xp,xx,hh,um,vm,uc,us,vc,vs,hp,hx,HP,HX,wp,wx,WP,WX;
5338  size_t i,j,k,l,m,n,V,U,K,id,j5;
5339 
5340  size_t I = this->ifoList[0]->TFmap.maxLayer()+1;
5341  size_t M = this->filter.size()/I; // total number of delays
5342  size_t L = ind<0 ? this->index.size() : ind+1; // total number of source locations
5343  int R = int(this->ifoList[0]->getTFmap()->rate()/I+0.5);
5344 
5345 // pointers to data
5346  double* pdata[NIFO];
5347  double* qdata[NIFO];
5348  double* pq;
5349  for(n=0; n<nIFO; n++) {
5350  pdata[n] = getifo(n)->getTFmap()->data;
5351  qdata[n] = getifo(n)->getTFmap()->data;
5352  }
5353 
5354 // buffer for wavelet layer delay filter
5355  std::vector<float>* F00;
5356  std::vector<short>* J00;
5357  std::vector<float>* F90;
5358  std::vector<short>* J90;
5359 
5360 // get antenna patterns and index arrays
5361  double* fp[NIFO]; // f+
5362  double* fx[NIFO]; // fx
5363  double* ffp[NIFO]; // f+f+ + fxfx
5364  double* ffm[NIFO]; // f+f+ - fxfx
5365  double* fpx[NIFO]; // 2*f+fx
5366  wavearray<double> f00(L); f00 = 0.; // dummy zero array
5367 
5368  for(n=0; n<NIFO; n++) {
5369  fp[n] = n<nIFO ? getifo(n)->fp.data : f00.data;
5370  fx[n] = n<nIFO ? getifo(n)->fx.data : f00.data;
5371  ffp[n] = n<nIFO ? getifo(n)->ffp.data : f00.data;
5372  ffm[n] = n<nIFO ? getifo(n)->ffm.data : f00.data;
5373  fpx[n] = n<nIFO ? getifo(n)->fpx.data : f00.data;
5374  }
5375  short* mm = skyMask.data;
5376  NETX (
5377  short* m0 = nIFO>1 ? getifo(0)->index.data : getifo(0)->index.data; ,
5378  short* m1 = nIFO>1 ? getifo(1)->index.data : getifo(1)->index.data; ,
5379  short* m2 = nIFO>2 ? getifo(2)->index.data : getifo(1)->index.data; ,
5380  short* m3 = nIFO>3 ? getifo(3)->index.data : getifo(1)->index.data; ,
5381  short* m4 = nIFO>4 ? getifo(4)->index.data : getifo(1)->index.data; ,
5382  short* m5 = nIFO>5 ? getifo(5)->index.data : getifo(1)->index.data; ,
5383  short* m6 = nIFO>6 ? getifo(6)->index.data : getifo(1)->index.data; ,
5384  short* m7 = nIFO>7 ? getifo(7)->index.data : getifo(1)->index.data; )
5385 
5386 // allocate buffers
5387  std::vector<size_t> pI;
5388 
5389  wavearray<double> LL(jN);
5390  wavearray<double> GG(jN);
5391  wavearray<short> jU(jN);
5392  wavearray<double> am00(jN*NIFO); // buffers for 00 data
5393  wavearray<double> am90(jN*NIFO); // buffers for 90 data
5394  wavearray<double> xi00(jN*NIFO); // buffers for 00 response
5395  wavearray<double> xi90(jN*NIFO); // buffers for 90 response
5396  wavearray<double> Fplus(jN*NIFO); // buffers for F+
5397  wavearray<double> Fcros(jN*NIFO); // buffers for Fx
5398 
5399 //BM wavearray<double> e00[NIFO];
5400 //BM wavearray<double> e90[NIFO];
5401  wavearray<double> a00[NIFO];
5402  wavearray<double> a90[NIFO];
5403  wavearray<double> NV[NIFO]; // noise variance
5404  wavearray<double> NR[NIFO]; // noise rms
5405  wavearray<double> cid; // buffers for cluster ID
5406  wavearray<double> cTo; // buffers for cluster time
5407  wavearray<double> vol; // buffers for cluster volume
5408 
5409  double u[NIFO];
5410  double v[NIFO];
5411  double e[NIFO];
5412  double ee[NIFO];
5413  double rr[NIFO];
5414  double pp[NIFO];
5415  double qq[NIFO];
5416 
5417  double* am;
5418  double* AM;
5419  double* xi;
5420  double* XI;
5421  double* Fp;
5422  double* Fx;
5423  double* nv[NIFO];
5424  double* nr[NIFO];
5425  double* pa00[NIFO];
5426  double* pa90[NIFO];
5427 
5428  for(n=0; n<NIFO; n++) {
5429  NV[n].resize(jN); NV[n] = 0.; nv[n] = NV[n].data;
5430  NR[n].resize(jN); NR[n] = 0.; nr[n] = NR[n].data;
5431  a00[n].resize(jN*M); a00[n] = 0.;
5432 //BM e00[n].resize(jN*M); e00[n] = 0.;
5433  a90[n].resize(jN*M); a90[n] = 0.;
5434 //BM e90[n].resize(jN*M); e90[n] = 0.;
5435  rr[n] = 1.;
5436  }
5437 
5438  netpixel* pix;
5439  std::vector<int>* vint;
5440  std::vector<int>* vtof;
5441 
5442  double logbpp,inet;
5443  size_t count = 0;
5444  ap = ac = as = 0.;
5445 
5446  if(ID) {
5447  this->pixeLHood = getifo(0)->TFmap;
5448  this->pixeLHood = 0.;
5449  this->pixeLNull = getifo(0)->TFmap;
5450  this->pixeLNull = 0.;
5451  this->nSensitivity = 0.;
5452  this->nAlignment = 0.;
5453  this->nNetIndex = 0.;
5454  this->nDisbalance = 0.;
5455  this->nLikelihood = 0.;
5456  this->nNullEnergy = 0.;
5457  this->nCorrEnergy = 0.;
5458  this->nCorrelation = 0.;
5459  this->nSkyStat = 0.;
5460  this->nEllipticity = 0.;
5461  this->nPolarisation = 0.;
5462  this->nProbability = 0.;
5463  this->nAntenaPrior = 0.;
5464  }
5465 
5466 //+++++++++++++++++++++++++++++++++++++++
5467 // liklihood calculation for clusters
5468 //+++++++++++++++++++++++++++++++++++++++
5469 
5470  for(n=lag; n<nLag; n++) { // loop over time shifts
5471 
5472  if(!this->wc_List[n].size()) continue;
5473  logbpp = -log(this->wc_List[n].getbpp());
5474 
5475  cid = this->wc_List[n].get((char*)"ID",0,'S',optim ? R : -R); // get cluster ID
5476  cTo = this->wc_List[n].get((char*)"time",0,'L',optim ? R : -R); // get cluster time
5477 
5478  K = cid.size();
5479 
5480  for(k=0; k<K; k++) { // loop over clusters
5481 
5482  id = size_t(cid.data[k]+0.1);
5483 
5484  if(ID && id!=ID) continue;
5485 
5486  vint = &(this->wc_List[n].cList[id-1]); // pixel list
5487  vtof = &(this->wc_List[n].nTofF[id-1]); // TofFlight configurations
5488 
5489  V = vint->size();
5490  if(!V) continue;
5491 
5492  pI.clear();
5493 
5494  for(j=0; j<V; j++) { // loop over pixels
5495 
5496  pix = this->wc_List[n].getPixel(id,j);
5497 
5498  if(!pix) {
5499  cout<<"network::likelihood() error: NULL pointer"<<endl;
5500  exit(1);
5501  }
5502 
5503  if(R != int(pix->rate+0.5)) continue; // check rate
5504  if(!pix->core && core) continue; // check core flag
5505 
5506  pI.push_back(j); // save pixel index
5507 
5508  }
5509 
5510  V = pI.size();
5511  if(!V) continue;
5512 
5513  if(NV[0].size() < V) { // reallocate arrays
5514  U = V+100;
5515  for(i=0; i<NIFO; i++) {
5516  NV[i].resize(U); NV[i] = 0.; nv[i] = NV[i].data;
5517  NR[i].resize(U); NR[i] = 0.; nr[i] = NR[i].data;
5518 //BM e00[i].resize(U*M); e00[i] = 0.;
5519  a00[i].resize(U*M); a00[i] = 0.;
5520 //BM e90[i].resize(U*M); e90[i] = 0.;
5521  a90[i].resize(U*M); a90[i] = 0.;
5522  }
5523  jU.resize(U); LL.resize(U); GG.resize(U);
5524  am00.resize(U*NIFO); am90.resize(U*NIFO);
5525  xi00.resize(U*NIFO); xi90.resize(U*NIFO);
5526  Fplus.resize(U*NIFO); Fcros.resize(U*NIFO);
5527  }
5528 
5529  for(j=0; j<V; j++) { // loop over selected pixels
5530 
5531  pix = this->wc_List[n].getPixel(id,pI[j]);
5532 
5533  cc = 0.;
5534  for(i=0; i<nIFO; i++) {
5535  ee[i] = 1./pix->data[i].noiserms;
5536  cc += ee[i]*ee[i]; // total inverse variance
5537  }
5538 
5539  GG.data[j] = sqrt(cc);
5540  for(i=0; i<nIFO; i++) {
5541  nv[i][j] = ee[i]*ee[i]; // inverse variance
5542  ee[i] /= sqrt(cc);
5543  nr[i][j] = ee[i]; // normalized 1/rms
5544  qdata[i] = pdata[i] + pix->data[i].index; // pointer to data
5545  }
5546 
5547 // apply delay filter
5548 
5549  for(i=0; i<nIFO; i++) {
5550  pq = qdata[i];
5551 
5552  for(m=0; m<M; m++){ // loop over delays
5553  F00 = &(filter[pix->frequency*M+m].value);
5554  J00 = &(filter[pix->frequency*M+m].index);
5555  F90 = &(filter90[pix->frequency*M+m].value);
5556  J90 = &(filter90[pix->frequency*M+m].index);
5557  l = m*V + j;
5558 
5559  gg = dot32(F00,pq,J00); // apply filter
5560 //BM e00[i].data[l] = gg*ee[i];
5561  a00[i].data[l] = gg;
5562 
5563  gg = dot32(F90,pq,J90); // apply filter
5564 //BM e90[i].data[l] = gg*ee[i];
5565  a90[i].data[l] = gg;
5566  }
5567  }
5568  }
5569 
5570  STAT = -1.e64; m=U=IIm=0; Em=Lm=LPm=AA=SI=CO=0.;
5571 
5572 //============================================================
5573 // weak constraint on 00 data
5574 //============================================================
5575 
5576  l = ind<0 ? 0 : ind; // process selected index
5577  for(; l<L; l++) { // loop over sky locations
5578 
5579  skyProb.data[l] = 0.;
5580 
5581  if(skyMaskCC.size()==L) {
5582  // transform l in celestial coordinates cc_l and check the skyMaskCC
5583  skymap* sm = &(this->nSkyStat);
5584  double th = sm->getTheta(l);
5585  double ph = sm->getPhi(l);
5586  double gpsT = cTo.data[k]+getifo(0)->TFmap.start(); // trigger time
5587  double ra = sm->phi2RA(ph, gpsT);
5588  int cc_l = this->getIndex(th,ra);
5589  if (!skyMaskCC.data[cc_l]) continue;
5590  }
5591 
5592  if(!mm[l] && ind<0) continue; // skip sky configurations
5593 
5594  NETX (
5595  pa00[0] = a00[0].data + m0[l]*V; ,
5596  pa00[1] = a00[1].data + m1[l]*V; ,
5597  pa00[2] = a00[2].data + m2[l]*V; ,
5598  pa00[3] = a00[3].data + m3[l]*V; ,
5599  pa00[4] = a00[4].data + m4[l]*V; ,
5600  pa00[5] = a00[5].data + m5[l]*V; ,
5601  pa00[6] = a00[6].data + m6[l]*V; ,
5602  pa00[7] = a00[7].data + m7[l]*V; )
5603 
5604  EE=E00=L00=C00=Lp=0.; II=0;
5605 
5606  for(j=0; j<V; j++) { // 00 phase
5607 
5608  j5 = j*NIFO;
5609  am = am00.data+j5;
5610  inix(pa00,j,am);
5611  Et = dotx(am,am); // total energy
5612  ii = int(Et>Eo);
5613  E00+= Et*ii;
5614 
5615  Fp = Fplus.data+j5;
5616  Fx = Fcros.data+j5;
5617  mulx(fp,l,nr,j,Fp);
5618  mulx(fx,l,nr,j,Fx);
5619 
5620  gp = dotx(Fp,Fp)+1.e-12; // fp^2
5621  gx = dotx(Fx,Fx)+1.e-12; // fx^2
5622  gI = dotx(Fp,Fx); // fp*fx
5623 
5624  xi = xi00.data+j5;
5625  xp = dotx(Fp,am); // (X*f+)
5626  xx = dotx(Fx,am); // (X*fx)
5627  um = rotx(Fp,xp*gx-xx*gI,
5628  Fx,xx*gp-xp*gI,xi);
5629  hh = dotx(xi,am,e);
5630  La = hh*hh/um;
5631  Co = La - dotx(e,e)/um;
5632  ii*= int(Co>0.);
5633  EE+= Et*ii;
5634  Lp+= La*Co*ii/(Et-La+1+Co);
5635  II+= ii;
5636  LL.data[j] = La*ii;
5637  L00+= La*ii;
5638  C00+= Co*ii;
5639  mulx(xi,hh*ii/um);
5640  }
5641 
5642  cc = E00>0 ? C00/(E00-L00+fabs(C00)) : 0.;
5643  if(cc<this->netCC || cc*C00<rho) continue;
5644 
5645  E90=L90=C90=inet=0.;
5646 
5647  NETX (
5648  pa90[0] = a90[0].data + m0[l]*V; ,
5649  pa90[1] = a90[1].data + m1[l]*V; ,
5650  pa90[2] = a90[2].data + m2[l]*V; ,
5651  pa90[3] = a90[3].data + m3[l]*V; ,
5652  pa90[4] = a90[4].data + m4[l]*V; ,
5653  pa90[5] = a90[5].data + m5[l]*V; ,
5654  pa90[6] = a90[6].data + m6[l]*V; ,
5655  pa90[7] = a90[7].data + m7[l]*V; )
5656 
5657  for(j=0; j<V; j++) { // 90 phase
5658 
5659  j5 = j*NIFO;
5660  AM = am90.data+j5;
5661  inix(pa90,j,AM);
5662  Et = dotx(AM,AM); // total energy
5663  ii = int(Et>Eo);
5664  E90+= Et*ii;
5665 
5666  Fp = Fplus.data+j5;
5667  Fx = Fcros.data+j5;
5668  gp = dotx(Fp,Fp)+1.e-12; // fp^2
5669  gx = dotx(Fx,Fx)+1.e-12; // fx^2
5670  gI = dotx(Fp,Fx); // fp*fx
5671 
5672  XI = xi90.data+j5;
5673  XP = dotx(Fp,AM); // (X(90)*f+)
5674  XX = dotx(Fx,AM); // (X(90)*fx)
5675  vm = rotx(Fp,XP*gx-XX*gI,
5676  Fx,XX*gp-XP*gI,XI);
5677  HH = dotx(XI,AM,e);
5678  La = HH*HH/vm;
5679  Co = La - dotx(e,e)/vm;
5680  ii*= int(Co>0.);
5681  EE+= Et*ii;
5682  Lp+= La*Co*ii/(Et-La+1+Co);
5683  II+= ii;
5684  LL.data[j] += La*ii;
5685  L90+= La*ii;
5686  C90+= Co*ii;
5687  mulx(XI,HH*ii/vm);
5688  }
5689 
5690  cc = E90>0 ? C90/(E90-L90+fabs(C90)) : 0.;
5691  if(cc<this->netCC || cc*C90<rho) continue;
5692 
5693  Co = C00+C90;
5694  Lo = L00+L90;
5695 
5696  sI=cO=aa=bb=0.;
5697 
5698 //++++++++++++++++elliptical case++++++++++++++++++++++
5699 // find solution for polarisation angle and ellipticity
5700 //++++++++++++++++elliptical case++++++++++++++++++++++
5701 
5702  if(ISG) {
5703 
5704  Lo=Lp=Co=0.;
5705 
5706  for(j=0; j<V; j++) { // loop over selected pixels
5707 
5708  j5 = j*NIFO;
5709  Fp = Fplus.data+j5;
5710  Fx = Fcros.data+j5;
5711  gp = dotx(Fp,Fp)+1.e-12; // fp^2
5712  gx = dotx(Fx,Fx)+1.e-12; // fx^2
5713  gI = dotx(Fp,Fx); // fp*fx
5714  gg = gp+gx;
5715 
5716  wp = dotx(Fp,xi00.data+j5); // +00 response
5717  wx = dotx(Fx,xi00.data+j5); // x00 response
5718  WP = dotx(Fp,xi90.data+j5); // +90 response
5719  WX = dotx(Fx,xi90.data+j5); // x90 response
5720 
5721  xp = (wp*wp + WP*WP);
5722  xx = (wx*wx + WX*WX);
5723  La = LL.data[j];
5724 
5725  sI += 2*(wp*wx+WP*WX-La*gI)/gg; // sin(4psi)
5726  cO += (xp-xx - La*(gp-gx))/gg; // cos(4psi)
5727  bb += La - (xp+xx)/gg;
5728  aa += 2*(wp*WX - wx*WP)/gg;
5729  }
5730 
5731  gg = sqrt(cO*cO+sI*sI);
5732  cO = cO/gg; sI = sI/gg;
5733  aa/= bb+gg+V*En; // ellipticity
5734  if(aa> one) aa = 1.;
5735  if(aa<-one) aa =-1.;
5736 
5737  for(j=0; j<V; j++) { // loop over selected pixels
5738 
5739  Fp = Fplus.data+j*NIFO;
5740  Fx = Fcros.data+j*NIFO;
5741  um = rotx(Fp,1+cO,Fx, sI,u); // rotate by 2*polarization angle
5742  vm = rotx(Fx,1+cO,Fp,-sI,v); // rotate by 2*polarization angle
5743  gp = dotx(u,u)+1.e-12; // fp^2
5744  gx = dotx(v,v)+1.e-12; // fx^2
5745  gI = dotx(u,v); // f+fx
5746  gg = gp+aa*aa*gx; // inverse network sensitivity
5747 
5748  am = am00.data+j*NIFO;
5749  xi = xi00.data+j*NIFO;
5750  um = dotx(xi,xi)+1.e-6;
5751  hh = dotx(xi,am,pp);
5752  xp = dotx(u,xi);
5753  xx = dotx(v,xi)*aa;
5754  bb = (xp*xp+xx*xx)/(um*gg*um);
5755  La = hh*hh*bb;
5756  cc = bb*dotx(pp,pp);
5757 
5758  AM = am90.data+j*NIFO;
5759  XI = xi90.data+j*NIFO;
5760  vm = dotx(XI,XI)+1.e-6;
5761  HH = dotx(XI,AM,qq);
5762  XP = dotx(u,XI);
5763  XX = dotx(v,XI)*aa;
5764  bb = (XP*XP+XX*XX)/(vm*gg*vm);
5765  La+= HH*HH*bb;
5766  cc+= bb*dotx(qq,qq);
5767 
5768  bb = 2*(xp*XX-xx*XP)/(um*gg*vm);
5769  La+= hh*HH*bb;
5770  cc+= bb*dotx(pp,qq);
5771  cc = La-cc;
5772  Lo+= La;
5773  Co+= cc;
5774  Et = dotx(am,am) + dotx(AM,AM);
5775  Lp+= La*cc/(Et-La+2+fabs(cc));
5776  }
5777  }
5778 
5779  cc = EE>0 ? Co/(EE-Lo+II+fabs(Co)) : 0.;
5780  EE = E00+E90;
5781  if(!isgr) Lp = Lo*cc;
5782  if(Lp>LPm) {LPm=Lp; Em=EE; IIm=II;} // max likelihood
5783 
5784  skyProb.data[l] = Lp/EE; // probability map
5785 
5786  cc = EE>0 ? Co/(EE-Lo+II+fabs(Co)) : 0.;
5787  if(cc<this->netCC || cc*Co<rho*2) continue;
5788 
5789 //=============================================================
5790 // zero phase data
5791 //=============================================================
5792 
5793  Lp=Lo=Co=gP=gX=0.;
5794 
5795  for(j=0; j<V; j++) { // loop over selected pixels
5796 
5797  xi = xi00.data+j*NIFO;
5798 
5799  if(dotx(xi,xi)<=0.) continue; // skip insignificant pixel
5800 
5801  am = am00.data+j*NIFO;
5802  Et = dotx(am,am);
5803  Fp = Fplus.data+j*NIFO;
5804  Fx = Fcros.data+j*NIFO;
5805  gp = dotx(Fp,Fp)+1.e-12; // fp^2
5806  gx = dotx(Fx,Fx)+1.e-12; // fx^2
5807  gI = dotx(Fp,Fx); // fp*fx
5808  xp = dotx(Fp,am); // (X*f+)
5809  xx = dotx(Fx,am); // (X*fx)
5810  uc = xp*gx - xx*gI; // u cos of rotation to PCF
5811  us = xx*gp - xp*gI; // u sin of rotation to PCF
5812  vc = gp*uc + gI*us; // (u*f+)/|u|^2 - 'cos' for v
5813  vs = gx*us + gI*uc; // (u*fx)/|u|^2 - 'sin' for v
5814  um = rotx(Fp,uc,Fx,us,u); // calculate new response vector
5815  vm = rotx(Fx,-vc,Fp,vs,v)+1.e-24; // calculate complementary vector
5816 
5817 // regulator
5818 
5819  ii = netx(u,um,v,vm,GAMMA);
5820  inet += ii*Et;
5821  if(ii<N_2 && gamma<0.) {inix(xi,0); continue;}
5822 
5823  gg = (gp+gx)*soft;
5824  uc += xp*gg; // u cos of rotation to PCF
5825  us += xx*gg; // u sin of rotation to PCF
5826 
5827  if(ii<N_1 && gamma!=0) {
5828  gR = (gp-gx)/2;
5829  gc = sqrt(gR*gR+gI*gI); // norm of complex antenna pattern
5830  uc = xp*(gc+gR)+xx*gI;
5831  us = xx*(gc-gR)+xp*gI;
5832  }
5833 
5834  vc = gp*uc + gI*us; // (u*f+)/|u|^2 - 'cos' for v
5835  vs = gx*us + gI*uc; // (u*fx)/|u|^2 - 'sin' for v
5836  um = rotx(Fp,uc,Fx,us,u); // calculate new response vector
5837  vm = rotx(Fx,-vc,Fp,vs,v)+1.e-24; // calculate complementary vector
5838 
5839 // energy disbalance vectors
5840 
5841  NETX (
5842  rr[0] = LOCAL*am[0]/(am[0]*am[0]+2.)+1-LOCAL; ,
5843  rr[1] = LOCAL*am[1]/(am[1]*am[1]+2.)+1-LOCAL; ,
5844  rr[2] = LOCAL*am[2]/(am[2]*am[2]+2.)+1-LOCAL; ,
5845  rr[3] = LOCAL*am[3]/(am[3]*am[3]+2.)+1-LOCAL; ,
5846  rr[4] = LOCAL*am[4]/(am[4]*am[4]+2.)+1-LOCAL; ,
5847  rr[5] = LOCAL*am[5]/(am[5]*am[5]+2.)+1-LOCAL; ,
5848  rr[6] = LOCAL*am[6]/(am[6]*am[6]+2.)+1-LOCAL; ,
5849  rr[7] = LOCAL*am[7]/(am[7]*am[7]+2.)+1-LOCAL; )
5850 
5851  hh = dotx(u,am)/um;
5852  NETX (
5853  pp[0] = rr[0]*(am[0]-hh*u[0])*u[0]; ,
5854  pp[1] = rr[1]*(am[1]-hh*u[1])*u[1]; ,
5855  pp[2] = rr[2]*(am[2]-hh*u[2])*u[2]; ,
5856  pp[3] = rr[3]*(am[3]-hh*u[3])*u[3]; ,
5857  pp[4] = rr[4]*(am[4]-hh*u[4])*u[4]; ,
5858  pp[5] = rr[5]*(am[5]-hh*u[5])*u[5]; ,
5859  pp[6] = rr[6]*(am[6]-hh*u[6])*u[6]; ,
5860  pp[7] = rr[7]*(am[7]-hh*u[7])*u[7]; )
5861 
5862  gg = dotx(v,am)/um;
5863  hh*= 2.;
5864  NETX (
5865  qq[0] = rr[0]*((hh*u[0]-am[0])*v[0]+u[0]*u[0]*gg); ,
5866  qq[1] = rr[1]*((hh*u[1]-am[1])*v[1]+u[1]*u[1]*gg); ,
5867  qq[2] = rr[2]*((hh*u[2]-am[2])*v[2]+u[2]*u[2]*gg); ,
5868  qq[3] = rr[3]*((hh*u[3]-am[3])*v[3]+u[3]*u[3]*gg); ,
5869  qq[4] = rr[4]*((hh*u[4]-am[4])*v[4]+u[4]*u[4]*gg); ,
5870  qq[5] = rr[5]*((hh*u[5]-am[5])*v[5]+u[5]*u[5]*gg); ,
5871  qq[6] = rr[6]*((hh*u[6]-am[6])*v[6]+u[6]*u[6]*gg); ,
5872  qq[7] = rr[7]*((hh*u[7]-am[7])*v[7]+u[7]*u[7]*gg); )
5873 
5874  co = dotx(qq,qq)/vm+dotx(pp,pp)/um+1.e-24; // cos term
5875  si = dotx(pp,qq); // sin term
5876  if(!eDisbalance) {co=1.;si=0.;}
5877  em = rotx(u,co,v,si/vm,e); // calculate rotated vector e
5878 
5879 // second iteration
5880 
5881  vm = rotx(v,co,u,-si/um,v)+1.e-24; // calculate rotated vector v
5882  hh = dotx(e,am)/em;
5883 
5884  NETX (
5885  pp[0] = rr[0]*(am[0]-hh*e[0])*e[0]; ,
5886  pp[1] = rr[1]*(am[1]-hh*e[1])*e[1]; ,
5887  pp[2] = rr[2]*(am[2]-hh*e[2])*e[2]; ,
5888  pp[3] = rr[3]*(am[3]-hh*e[3])*e[3]; ,
5889  pp[4] = rr[4]*(am[4]-hh*e[4])*e[4]; ,
5890  pp[5] = rr[5]*(am[5]-hh*e[5])*e[5]; ,
5891  pp[6] = rr[6]*(am[6]-hh*e[6])*e[6]; ,
5892  pp[7] = rr[7]*(am[7]-hh*e[7])*e[7]; )
5893 
5894  gg = dotx(v,am)/em;
5895  hh*= 2.;
5896  NETX (
5897  qq[0] = rr[0]*((hh*e[0]-am[0])*v[0]+e[0]*e[0]*gg); ,
5898  qq[1] = rr[1]*((hh*e[1]-am[1])*v[1]+e[1]*e[1]*gg); ,
5899  qq[2] = rr[2]*((hh*e[2]-am[2])*v[2]+e[2]*e[2]*gg); ,
5900  qq[3] = rr[3]*((hh*e[3]-am[3])*v[3]+e[3]*e[3]*gg); ,
5901  qq[4] = rr[4]*((hh*e[4]-am[4])*v[4]+e[4]*e[4]*gg); ,
5902  qq[5] = rr[5]*((hh*e[5]-am[5])*v[5]+e[5]*e[5]*gg); ,
5903  qq[6] = rr[6]*((hh*e[6]-am[6])*v[6]+e[6]*e[6]*gg); ,
5904  qq[7] = rr[7]*((hh*e[7]-am[7])*v[7]+e[7]*e[7]*gg); )
5905 
5906  co = dotx(qq,qq)/vm+dotx(pp,pp)/em+1.e-24; // cos term
5907  si = dotx(pp,qq); // sin term
5908  if(!eDisbalance) {co=1.;si=0.;}
5909  em = rotx(e,co,v,si/vm,e); // calculate final vector
5910  hh = dotx(e,am,ee); // GW amplitude
5911  La = hh*hh/em;
5912  cc = La-dotx(ee,ee)/em;
5913  Lo+= La;
5914  Co+= cc;
5915  Lp+= La*cc*int(cc>0)/(Et-La+1+cc);
5916  mulx(e,hh/em,xi);
5917  }
5918 
5919 //=============================================================
5920 // 90 degrees phase energy disbalance
5921 //=============================================================
5922 
5923  for(j=0; j<V; j++) { // select pixels and get dot ptoducts
5924 
5925  XI = xi90.data+j*NIFO;
5926 
5927  if(dotx(XI,XI)<=0) continue; // skip insignificant pixel
5928 
5929  AM = am90.data+j*NIFO;
5930  Et = dotx(AM,AM);
5931  Fp = Fplus.data+j*NIFO;
5932  Fx = Fcros.data+j*NIFO;
5933  gp = dotx(Fp,Fp)+1.e-12; // fp^2
5934  gx = dotx(Fx,Fx)+1.e-12; // fx^2
5935  gI = dotx(Fp,Fx); // fp*fx
5936  XP = dotx(Fp,AM); // (X*f+)
5937  XX = dotx(Fx,AM); // (X*fx)
5938  uc = XP*gx - XX*gI; // u cos of rotation to PCF
5939  us = XX*gp - XP*gI; // u sin of rotation to PCF
5940  vc = gp*uc + gI*us; // (u*f+)/|u|^2 - 'cos' for v
5941  vs = gx*us + gI*uc; // (u*fx)/|u|^2 - 'sin' for v
5942  um = rotx(Fp,uc,Fx,us,u); // calculate new response vector
5943  vm = rotx(Fx,-vc,Fp,vs,v)+1.e-24; // calculate complementary vector
5944 
5945 // regulator
5946 
5947  ii = netx(u,um,v,vm,GAMMA);
5948  inet += ii*Et;
5949  if(ii<N_2 && gamma<0.) {inix(XI,0.); continue;}
5950 
5951  gg = (gp+gx)*soft;
5952  uc += XP*gg; // u cos of rotation to PCF
5953  us += XX*gg; // u sin of rotation to PCF
5954 
5955  if(ii<N_1 && gamma!=0) {
5956  gR = (gp-gx)/2;
5957  gc = sqrt(gR*gR+gI*gI); // norm of complex antenna pattern
5958  uc = XP*(gc+gR)+XX*gI;
5959  us = XX*(gc-gR)+XP*gI;
5960  }
5961 
5962  vc = gp*uc + gI*us; // (u*f+)/|u|^2 - 'cos' for v
5963  vs = gx*us + gI*uc; // (u*fx)/|u|^2 - 'sin' for v
5964  um = rotx(Fp,uc,Fx,us,u); // calculate new response vector
5965  vm = rotx(Fx,-vc,Fp,vs,v)+1.e-24; // calculate complementary vector
5966 
5967 // energy disbalance vectors
5968 
5969  NETX (
5970  rr[0] = LOCAL*AM[0]/(AM[0]*AM[0]+2.)+1-LOCAL; ,
5971  rr[1] = LOCAL*AM[1]/(AM[1]*AM[1]+2.)+1-LOCAL; ,
5972  rr[2] = LOCAL*AM[2]/(AM[2]*AM[2]+2.)+1-LOCAL; ,
5973  rr[3] = LOCAL*AM[3]/(AM[3]*AM[3]+2.)+1-LOCAL; ,
5974  rr[4] = LOCAL*AM[4]/(AM[4]*AM[4]+2.)+1-LOCAL; ,
5975  rr[5] = LOCAL*AM[5]/(AM[5]*AM[5]+2.)+1-LOCAL; ,
5976  rr[6] = LOCAL*AM[6]/(AM[6]*AM[6]+2.)+1-LOCAL; ,
5977  rr[7] = LOCAL*AM[7]/(AM[7]*AM[7]+2.)+1-LOCAL; )
5978 
5979  hh = dotx(u,AM)/um;
5980  NETX (
5981  pp[0] = rr[0]*(AM[0]-hh*u[0])*u[0]; ,
5982  pp[1] = rr[1]*(AM[1]-hh*u[1])*u[1]; ,
5983  pp[2] = rr[2]*(AM[2]-hh*u[2])*u[2]; ,
5984  pp[3] = rr[3]*(AM[3]-hh*u[3])*u[3]; ,
5985  pp[4] = rr[4]*(AM[4]-hh*u[4])*u[4]; ,
5986  pp[5] = rr[5]*(AM[5]-hh*u[5])*u[5]; ,
5987  pp[6] = rr[6]*(AM[6]-hh*u[6])*u[6]; ,
5988  pp[7] = rr[7]*(AM[7]-hh*u[7])*u[7]; )
5989 
5990  gg = dotx(v,AM)/um;
5991  hh*= 2.;
5992  NETX (
5993  qq[0] = rr[0]*((hh*u[0]-AM[0])*v[0]+u[0]*u[0]*gg); ,
5994  qq[1] = rr[1]*((hh*u[1]-AM[1])*v[1]+u[1]*u[1]*gg); ,
5995  qq[2] = rr[2]*((hh*u[2]-AM[2])*v[2]+u[2]*u[2]*gg); ,
5996  qq[3] = rr[3]*((hh*u[3]-AM[3])*v[3]+u[3]*u[3]*gg); ,
5997  qq[4] = rr[4]*((hh*u[4]-AM[4])*v[4]+u[4]*u[4]*gg); ,
5998  qq[5] = rr[5]*((hh*u[5]-AM[5])*v[5]+u[5]*u[5]*gg); ,
5999  qq[6] = rr[6]*((hh*u[6]-AM[6])*v[6]+u[6]*u[6]*gg); ,
6000  qq[7] = rr[7]*((hh*u[7]-AM[7])*v[7]+u[7]*u[7]*gg); )
6001 
6002  co = dotx(qq,qq)/vm+dotx(pp,pp)/um+1.e-24; // cos term
6003  si = dotx(pp,qq); // sin term
6004  if(!eDisbalance) {co=1.;si=0.;}
6005  em = rotx(u,co,v,si/vm,e); // calculate rotated vector e
6006 
6007 // second iteration
6008 
6009  vm = rotx(v,co,u,-si/um,v)+1.e-24; // calculate rotated vector v
6010  hh = dotx(e,AM)/em;
6011 
6012  NETX (
6013  pp[0] = rr[0]*(AM[0]-hh*e[0])*e[0]; ,
6014  pp[1] = rr[1]*(AM[1]-hh*e[1])*e[1]; ,
6015  pp[2] = rr[2]*(AM[2]-hh*e[2])*e[2]; ,
6016  pp[3] = rr[3]*(AM[3]-hh*e[3])*e[3]; ,
6017  pp[4] = rr[4]*(AM[4]-hh*e[4])*e[4]; ,
6018  pp[5] = rr[5]*(AM[5]-hh*e[5])*e[5]; ,
6019  pp[6] = rr[6]*(AM[6]-hh*e[6])*e[6]; ,
6020  pp[7] = rr[7]*(AM[7]-hh*e[7])*e[7]; )
6021 
6022  gg = dotx(v,AM)/em;
6023  hh*= 2.;
6024  NETX (
6025  qq[0] = rr[0]*((hh*e[0]-AM[0])*v[0]+e[0]*e[0]*gg); ,
6026  qq[1] = rr[1]*((hh*e[1]-AM[1])*v[1]+e[1]*e[1]*gg); ,
6027  qq[2] = rr[2]*((hh*e[2]-AM[2])*v[2]+e[2]*e[2]*gg); ,
6028  qq[3] = rr[3]*((hh*e[3]-AM[3])*v[3]+e[3]*e[3]*gg); ,
6029  qq[4] = rr[4]*((hh*e[4]-AM[4])*v[4]+e[4]*e[4]*gg); ,
6030  qq[5] = rr[5]*((hh*e[5]-AM[5])*v[5]+e[5]*e[5]*gg); ,
6031  qq[6] = rr[6]*((hh*e[6]-AM[6])*v[6]+e[6]*e[6]*gg); ,
6032  qq[7] = rr[7]*((hh*e[7]-AM[7])*v[7]+e[7]*e[7]*gg); )
6033 
6034  co = dotx(qq,qq)/vm+dotx(pp,pp)/em+1.e-24; // cos term
6035  si = dotx(pp,qq); // sin term
6036  if(!eDisbalance) {co=1.;si=0.;}
6037  em = rotx(e,co,v,si/vm,e); // calculate final vector
6038  hh = dotx(e,AM,ee); // GW amplitude
6039  La = hh*hh/em;
6040  cc = La-dotx(ee,ee)/em;
6041  Lo+= La;
6042  Co+= cc;
6043  Lp+= La*cc*int(cc>0)/(Et-La+1+cc);
6044  mulx(e,hh/em,XI);
6045  }
6046 
6047 //++++++++++++++++elliptical case++++++++++++++++++++++
6048 // calculate elliptical likelihood and coherent energy
6049 //++++++++++++++++elliptical case++++++++++++++++++++++
6050 
6051  if(ISG) {
6052 
6053  Lp=Lo=Co=0.;
6054 
6055  for(j=0; j<V; j++) { // loop over selected pixels
6056 
6057  Fp = Fplus.data+j*NIFO;
6058  Fx = Fcros.data+j*NIFO;
6059  um = rotx(Fp,1+cO,Fx, sI,u); // rotate by 2*polarization angle
6060  vm = rotx(Fx,1+cO,Fp,-sI,v); // rotate by 2*polarization angle
6061  gp = dotx(u,u)+1.e-12; // fp^2
6062  gx = dotx(v,v)+1.e-12; // fx^2
6063  gg = gp + aa*aa*gx; // network sensitivity
6064 
6065  am = am00.data+j*NIFO;
6066  xi = xi00.data+j*NIFO;
6067  um = dotx(xi,xi)+1.e-6;
6068  hh = dotx(xi,am,pp);
6069  xp = dotx(u,xi);
6070  xx = dotx(v,xi)*aa;
6071  bb = (xp*xp+xx*xx)/(um*gg*um);
6072  La = hh*hh*bb;
6073  cc = bb*dotx(pp,pp);
6074 
6075  AM = am90.data+j*NIFO;
6076  XI = xi90.data+j*NIFO;
6077  vm = dotx(XI,XI)+1.e-6;
6078  HH = dotx(XI,AM,qq);
6079  XP = dotx(u,XI);
6080  XX = dotx(v,XI)*aa;
6081  bb = (XP*XP+XX*XX)/(vm*gg*vm);
6082  La+= HH*HH*bb;
6083  cc+= bb*dotx(qq,qq);
6084 
6085  bb = 2*(xp*XX-xx*XP)/(um*gg*vm);
6086  La+= hh*HH*bb;
6087  cc+= bb*dotx(pp,qq);
6088  cc = La-cc;
6089  Co+= cc;
6090  Lo+= La;
6091  Et = dotx(am,am)+dotx(AM,AM);
6092  Lp+= La*cc*int(cc>0)/(Et-La+2+cc);
6093  }
6094  }
6095 
6096 // final detection statistics
6097 
6098  cc = EE>0 ? Co/(EE-Lo+II+fabs(Co)) : 0.;
6099  stat = isgr ? Lp/EE : Lo*cc/EE;
6100  inet/= EE;
6101 
6102 
6103  if(stat>=STAT) { m=l; STAT=stat; AA=aa; CO=cO; SI=sI; Lm=Lo/2.; }
6104 
6105  if(ID) { // fill skymaps
6106  for(j=0; j<V; j++) { // loop over selected pixels
6107  Fp = Fplus.data+j*NIFO;
6108  Fx = Fcros.data+j*NIFO;
6109  Et = dotx(pa00,j,pa00,j);
6110  gp = dotx(Fp,Fp)+1.e-12; // fp^2
6111  gx = dotx(Fx,Fx)+1.e-12; // fx^2
6112  gI = dotx(Fp,Fx); // fp*fx
6113  gr = (gp+gx)/2;
6114  gR = (gp-gx)/2;
6115  gc = sqrt(gR*gR+gI*gI); // norm of complex antenna pattern
6116  gP+= (gr+gc); // average + sensitivity
6117  gX+= (gr-gc); // average x sensitivity
6118  }
6119 
6120  this->nAntenaPrior.set(l, gP/V);
6121  this->nSensitivity.set(l, gP/V);
6122  this->nAlignment.set(l, gX/V);
6123  this->nLikelihood.set(l, Lo/2);
6124  this->nNullEnergy.set(l, (EE-Lo)/2.);
6125  this->nCorrEnergy.set(l, Co/2);
6126  this->nCorrelation.set(l, cc);
6127  this->nSkyStat.set(l, stat);
6128  this->nProbability.set(l, skyProb.data[l]);
6129  this->nDisbalance.set(l, fabs(L00-L90)/fabs(L00+L90));
6130  this->nEllipticity.set(l, aa);
6131  this->nPolarisation.set(l, atan2(sI,cO));
6132  this->nNetIndex.set(l, inet);
6133  }
6134  }
6135 
6136  if(STAT<0.001 && ind<0) {
6137  this->wc_List[n].ignore(id); // reject cluster
6138  continue;
6139  }
6140 
6141 //============================================================
6142 // final calculation of likelihood for selected sky location
6143 //============================================================
6144 
6145  l = ind<0 ? m : ind;
6146 
6147  NETX (
6148  pa00[0] = a00[0].data + m0[l]*V; ,
6149  pa00[1] = a00[1].data + m1[l]*V; ,
6150  pa00[2] = a00[2].data + m2[l]*V; ,
6151  pa00[3] = a00[3].data + m3[l]*V; ,
6152  pa00[4] = a00[4].data + m4[l]*V; ,
6153  pa00[5] = a00[5].data + m5[l]*V; ,
6154  pa00[6] = a00[6].data + m6[l]*V; ,
6155  pa00[7] = a00[7].data + m7[l]*V; )
6156  NETX (
6157  pa90[0] = a90[0].data + m0[l]*V; ,
6158  pa90[1] = a90[1].data + m1[l]*V; ,
6159  pa90[2] = a90[2].data + m2[l]*V; ,
6160  pa90[3] = a90[3].data + m3[l]*V; ,
6161  pa90[4] = a90[4].data + m4[l]*V; ,
6162  pa90[5] = a90[5].data + m5[l]*V; ,
6163  pa90[6] = a90[6].data + m6[l]*V; ,
6164  pa90[7] = a90[7].data + m7[l]*V; )
6165 
6166  Lo=0;
6167 
6168  for(j=0; j<V; j++) { // select pixels and get dot ptoducts
6169 
6170  pix = this->wc_List[n].getPixel(id,pI[j]);
6171  pix->theta = nLikelihood.getTheta(l);
6172  pix->phi = nLikelihood.getPhi(l);
6173  pix->ellipticity = ISG ? AA : 0.;
6174  pix->polarisation = ISG ? atan2(SI,CO)/4. : 0.;
6175 
6176  E00=E90=gp=gx=gI=xp=xx=XP=XX = 0.;
6177  U = 1;
6178 
6179 
6180  Fp = Fplus.data+j*NIFO;
6181  Fx = Fcros.data+j*NIFO;
6182  am = am00.data+j*NIFO;
6183  AM = am90.data+j*NIFO;
6184  for(i=0; i<nIFO; i++) {
6185  Fp[i] = fp[i][l]*nr[i][j];
6186  Fx[i] = fx[i][l]*nr[i][j];
6187  am[i] = pa00[i][j];
6188  AM[i] = pa90[i][j];
6189  E00 += am[i]*am[i];
6190  E90 += AM[i]*AM[i];
6191 
6192  gp += Fp[i]*Fp[i]+1.e-12;
6193  gx += Fx[i]*Fx[i]+1.e-12;
6194  gI += Fp[i]*Fx[i];
6195  xp += Fp[i]*am[i];
6196  xx += Fx[i]*am[i];
6197  XP += Fp[i]*AM[i];
6198  XX += Fx[i]*AM[i];
6199 
6200  pix->setdata(am[i],'S',i);
6201  pix->setdata(AM[i],'P',i);
6202  xi00.data[i] = 0.;
6203  xi90.data[i] = 0.;
6204 
6205  }
6206 
6207  gr = (gp+gx)*soft;
6208  gR = (gp-gx)/2.;
6209  gc = sqrt(gR*gR+gI*gI); // norm of complex antenna pattern
6210 
6211 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6212 // condition 00 phase
6213 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6214 // find weak vector
6215 
6216  uc = (xp*gx - xx*gI); // u cos of rotation to PCF
6217  us = (xx*gp - xp*gI); // u sin of rotation to PCF
6218  vc = gp*uc + gI*us; // (u*f+)/|u|^2 - 'cos' for v
6219  vs = gx*us + gI*uc; // (u*fx)/|u|^2 - 'sin' for v
6220  um = rotx(Fp,uc,Fx,us,u); // calculate new response vector
6221  vm = rotx(Fx,-vc,Fp,vs,v)+1.e-24; // calculate complementary vector
6222  hh = dotx(u,am,e);
6223  cc = dotx(e,e);
6224 
6225  if((hh*hh-cc)/um<=0. || E00<Eo) U=0;
6226 
6227 // regulator
6228 
6229  ii = netx(u,um,v,vm,GAMMA);
6230  if(ii<N_2 && gamma<0.) U=0; // superclean selection cut
6231 
6232  uc += xp*gr; // u cos of rotation to PCF
6233  us += xx*gr; // u sin of rotation to PCF
6234 
6235  if(ii<N_1 && gamma!=0) {
6236  uc = xp*(gc+gR)+xx*gI;
6237  us = xx*(gc-gR)+xp*gI;
6238  }
6239 
6240  vc = gp*uc + gI*us; // (u*f+)/|u|^2 - 'cos' for v
6241  vs = gx*us + gI*uc; // (u*fx)/|u|^2 - 'sin' for v
6242  um = rotx(Fp,uc,Fx,us,u); // calculate new response vector
6243  vm = rotx(Fx,-vc,Fp,vs,v)+1.e-24; // calculate complementary vector
6244 
6245 // normalize u and v vectors
6246 
6247  um = sqrt(um);
6248  vm = sqrt(vm);
6249 
6250  hh = gg = 0.;
6251  for(i=0; i<nIFO; i++) {
6252  u[i] = u[i]/um;
6253  v[i] = v[i]/vm;
6254  hh += u[i]*am[i]; // (u*X) - solution
6255  gg += v[i]*am[i]; // (v*X) - solution
6256  }
6257 
6258 // calculate energy disbalance vectors
6259 
6260  co=si=0.;
6261  for(i=0; i<nIFO; i++) { // disbalance vectors
6262  cc = local ? am[i]/(am[i]*am[i]+2.) : 1.;
6263  pp[i] = cc*(am[i]-hh*u[i])*u[i];
6264  qq[i] = cc*((2.*hh*u[i]-am[i])*v[i] + u[i]*u[i]*gg);
6265  co += pp[i]*pp[i] + qq[i]*qq[i]; // cos (version 1)
6266  si += pp[i]*qq[i]; // sin
6267  }
6268  cc = sqrt(si*si+co*co)+1.e-24;
6269  co = co/cc;
6270  si = si/cc;
6271  if(!eDisbalance) {co=1.;si=0.;}
6272 
6273 // corrected likelihood
6274 
6275  hh = gg = 0.;
6276  for(i=0; i<nIFO; i++) { // solution for h(t,f)
6277  e[i] = u[i]*co + v[i]*si; // final projection vector
6278  v[i] = v[i]*co - u[i]*si; // orthogonal v vector
6279  u[i] = e[i];
6280  hh += u[i]*am[i]; // solution for hu(t,f)
6281  gg += v[i]*am[i]; // solution for hv(t,f)
6282  }
6283 
6284 // second iteration
6285 
6286  co=si=0.;
6287  for(i=0; i<nIFO; i++) { // disbalance vectors
6288  cc = local ? am[i]/(am[i]*am[i]+2.) : 1.;
6289  pp[i] = cc*(am[i]-hh*u[i])*u[i];
6290  qq[i] = cc*((2.*hh*u[i]-am[i])*v[i] + u[i]*u[i]*gg);
6291  co += pp[i]*pp[i] + qq[i]*qq[i]; // cos (version 1)
6292  si += pp[i]*qq[i]; // sin
6293  }
6294  cc = sqrt(si*si+co*co)+1.e-24;
6295  co = co/cc;
6296  si = si/cc;
6297  if(!eDisbalance) {co=1.;si=0.;}
6298 
6299  hh = 0.;
6300  for(i=0; i<nIFO; i++) { // corrected u vector for 00 amplitude
6301  u[i] = u[i]*co + v[i]*si;
6302  e[i] = am[i]*u[i];
6303  hh += e[i]*U;
6304  }
6305 
6306  La = hh*hh;
6307  wp = wx = 0.;
6308  for(i=0; i<nIFO; i++) { // detector response for 00 data
6309  pix->setdata(u[i]*hh/sqrt(nv[i][j]),'W',i);
6310  wp += Fp[i]*u[i]*hh;
6311  wx += Fx[i]*u[i]*hh;
6312  }
6313 
6314 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6315 // condition 90 phase
6316 //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
6317 // find weak vector
6318 
6319  U = 1;
6320  uc = XP*gx - XX*gI; // u cos of rotation to PCF
6321  us = XX*gp - XP*gI; // u sin of rotation to PCF
6322  vc = gp*uc + gI*us; // (u*f+)/|u|^2 - 'cos' for v
6323  vs = gx*us + gI*uc; // (u*fx)/|u|^2 - 'sin' for v
6324  um = rotx(Fp,uc,Fx,us,u); // calculate new response vector
6325  vm = rotx(Fx,-vc,Fp,vs,v)+1.e-24; // calculate complementary vector
6326  hh = dotx(u,AM,e);
6327  cc = dotx(e,e);
6328 
6329  if((hh*hh-cc)/um<=0. || E90<Eo) U=0;
6330 
6331 // sky regulator
6332 
6333  ii = netx(u,um,v,vm,GAMMA);
6334  if(ii<N_2 && gamma<0.) U=0; // superclean selection cut
6335 
6336  uc += XP*gr; // u cos of rotation to PCF
6337  us += XX*gr; // u sin of rotation to PCF
6338 
6339  if(ii<N_1 && gamma!=0) {
6340  uc = XP*(gc+gR)+XX*gI;
6341  us = XX*(gc-gR)+XP*gI;
6342  }
6343 
6344  vc = gp*uc + gI*us; // (u*f+)/|u|^2 - 'cos' for v
6345  vs = gx*us + gI*uc; // (u*fx)/|u|^2 - 'sin' for v
6346  um = rotx(Fp,uc,Fx,us,u); // calculate new response vector
6347  vm = rotx(Fx,-vc,Fp,vs,v)+1.e-24; // calculate complementary vector
6348 
6349 // normalize u and v vectors
6350 
6351  um = sqrt(um);
6352  vm = sqrt(vm);
6353 
6354  hh = gg = 0.;
6355  for(i=0; i<nIFO; i++) {
6356  u[i] = u[i]/um;
6357  v[i] = v[i]/vm;
6358  hh += u[i]*AM[i]; // (u*X) - solution
6359  gg += v[i]*AM[i]; // (v*X) - solution
6360  }
6361 
6362 // calculate energy disbalance vectors
6363 
6364  co=si=0.;
6365  for(i=0; i<nIFO; i++) { // disbalance vectors
6366  cc = local ? AM[i]/(AM[i]*AM[i]+2.) : 1.;
6367  pp[i] = cc*(AM[i]-hh*u[i])*u[i];
6368  qq[i] = cc*((2.*hh*u[i]-AM[i])*v[i] + u[i]*u[i]*gg);
6369  co += pp[i]*pp[i] + qq[i]*qq[i]; // cos (version 1)
6370  si += pp[i]*qq[i]; // sin
6371  }
6372  cc = sqrt(si*si+co*co)+1.e-24;
6373  co = co/cc;
6374  si = si/cc;
6375  if(!eDisbalance) {co=1.;si=0.;}
6376 
6377 // corrected likelihood
6378 
6379  hh = gg = 0.;
6380  for(i=0; i<nIFO; i++) { // solution for h(t,f)
6381  e[i] = u[i]*co + v[i]*si; // final projection vector
6382  v[i] = v[i]*co - u[i]*si; // orthogonal v vector
6383  u[i] = e[i];
6384  hh += u[i]*AM[i]; // solution for hu(t,f)
6385  gg += v[i]*AM[i]; // solution for hv(t,f)
6386  }
6387 
6388 // second iteration
6389 
6390  co=si=0.;
6391  for(i=0; i<nIFO; i++) { // disbalance vectors
6392  cc = local ? AM[i]/(AM[i]*AM[i]+2.) : 1.;
6393  pp[i] = cc*(AM[i]-hh*u[i])*u[i];
6394  qq[i] = cc*((2.*hh*u[i]-AM[i])*v[i] + u[i]*u[i]*gg);
6395  co += pp[i]*pp[i] + qq[i]*qq[i]; // cos (version 1)
6396  si += pp[i]*qq[i]; // sin
6397  }
6398  cc = sqrt(si*si+co*co)+1.e-24;
6399  co = co/cc;
6400  si = si/cc;
6401  if(!eDisbalance) {co=1.;si=0.;}
6402 
6403 
6404  hh = 0.;
6405  for(i=0; i<nIFO; i++) { // corrected u vector for 00 amplitude
6406  u[i] = u[i]*co + v[i]*si;
6407  e[i] = AM[i]*u[i];
6408  hh += e[i]*U;
6409  }
6410 
6411  La+= hh*hh; // 90 likelihood
6412  WP = WX = 0.;
6413  for(i=0; i<nIFO; i++) { // detector response for 90 data
6414  pix->setdata(u[i]*hh/sqrt(nv[i][j]),'U',i);
6415  WP += Fp[i]*u[i]*hh;
6416  WX += Fx[i]*u[i]*hh;
6417  }
6418 
6419  if(ISG) {
6420  ap = (1+AA*AA);
6421  cc = (1-AA*AA);
6422  as = SI*cc;
6423  ac = CO*cc;
6424  gg = (gp+gx)*ap + (gp-gx)*ac + 2*gI*as;
6425  hp = (wp*(ap+ac) + 2*AA*WX + wx*as)/gg;
6426  hx = (wx*(ap-ac) - 2*AA*WP + wp*as)/gg;
6427  HP = (WP*(ap+ac) - 2*AA*wx + WX*as)/gg;
6428  HX = (WX*(ap-ac) + 2*AA*wp + WP*as)/gg;
6429  La = rotx(Fp,hp,Fx,hx,e)+rotx(Fp,HP,Fx,HX,e);
6430 
6431  for(i=0; i<nIFO; i++) {
6432  pix->setdata((hp*fp[i][l]+hx*fx[i][l])/GG.data[j],'W',i); // 00 detector respose
6433  pix->setdata((HP*fp[i][l]+HX*fx[i][l])/GG.data[j],'U',i); // 90 detector respose
6434  }
6435  }
6436 
6437  pix->likelihood = La/2.;
6438  Lo += La/2;
6439 
6440  if(!core) pix->core = (E00<Eo && E90<Eo) ? false : true;
6441  if(ID) {
6442  this->pixeLHood.data[pix->time] = La/2.;
6443  this->pixeLNull.data[pix->time] = (E00+E90-La)/2+1.;
6444  }
6445 
6446  count++;
6447  }
6448 
6449 // fill in backward delay configuration
6450 
6451  vtof->clear();
6452  NETX (
6453  vtof->push_back(int(M/2)-int(m0[l])); ,
6454  vtof->push_back(int(M/2)-int(m1[l])); ,
6455  vtof->push_back(int(M/2)-int(m2[l])); ,
6456  vtof->push_back(int(M/2)-int(m3[l])); ,
6457  vtof->push_back(int(M/2)-int(m4[l])); ,
6458  vtof->push_back(int(M/2)-int(m5[l])); ,
6459  vtof->push_back(int(M/2)-int(m6[l])); ,
6460  vtof->push_back(int(M/2)-int(m7[l])); )
6461 
6462 // calculation of error regions
6463 
6464  skyProb *= Em/IIm;
6465  T = cTo.data[k]+getifo(0)->TFmap.start(); // trigger time
6466  if(iID<=0 && type!='E') getSkyArea(id,n,T); // calculate error regions
6467 
6468  if(fabs(Lm-Lo)/Lo>1.e-4)
6469  cout<<"likelihood warning: "<<Lm<<" "<<Lo<<endl;
6470 
6471  if(Em>0 && ID) {
6472  cout<<"max value: "<<STAT<<" at (theta,phi) = ("<<nLikelihood.getTheta(l)
6473  <<","<<nLikelihood.getPhi(l)<<") Likelihood: loop: "
6474  <<Lm<<", final: "<<Lo<<", sky: "<<LPm/2<<", energy: "<<Em/2<<endl;
6475  break;
6476  }
6477 
6478  if (mdcListSize() && n==0) { // only for lag=0 && simulation mode
6479  if (this->getwave(id, 0, 'W')) {
6480  //if (this->getwave(id, 0, 'S')) {
6481  detector* pd;
6482  size_t M = this->ifoList.size();
6483  for(int i=0; i<(int)M; i++) { // loop over detectors
6484  pd = this->getifo(i);
6485  pd->RWFID.push_back(id); // save cluster ID
6486 
6487  // save reconstructed waveform
6488 
6489  double gps = this->getifo(0)->getTFmap()->start();
6490  double wfStart = gps + pd->waveForm.start();
6491  //double wfRate = pd->waveForm.rate();
6492  //double wfSize = pd->waveForm.size();
6493 
6495  *wf = pd->waveForm;
6496  wf->start(wfStart);
6497  pd->RWFP.push_back(wf);
6498  }
6499  }
6500  }
6501 
6502  if(ID && !EFEC) {
6503  this->nSensitivity.gps = T;
6504  this->nAlignment.gps = T;
6505  this->nDisbalance.gps = T;
6506  this->nLikelihood.gps = T;
6507  this->nNullEnergy.gps = T;
6508  this->nCorrEnergy.gps = T;
6509  this->nCorrelation.gps = T;
6510  this->nSkyStat.gps = T;
6511  this->nEllipticity.gps = T;
6512  this->nPolarisation.gps = T;
6513  this->nNetIndex.gps = T;
6514  }
6515  } // end of loop over clusters
6516  if(ID) break;
6517  } // end of loop over time shifts
6518  return count;
6519 }
6520 
6521 //**************************************************************************
6522 //: initialize network data matrix NDM, works with likelihoodB()
6523 //**************************************************************************
6524 
6525 bool network::setndm(size_t ID, size_t lag, bool core, int type)
6526 {
6527  int ii;
6528  size_t j,n,m,k,K,V,id;
6529  size_t N = this->ifoList.size(); // number of detectors
6530  int N_1 = N>2 ? int(N)-1 : 2;
6531  int N_2 = N>2 ? int(N)-2 : 1;
6532  if(!N) return false;
6533 
6534  wavearray<double> cid; // cluster ID
6535  wavearray<double> rat; // cluster rate
6536  wavearray<double> lik; // likelihood
6537  vector<wavearray<double> > snr(N); // data stream snr
6538  vector<wavearray<double> > nul(N); // biased null stream
6539  netpixel* pix;
6540  wavecomplex gC;
6541  detector* pd;
6542 
6543  std::vector<int>* vi;
6544  std::vector<wavecomplex> A; // antenna patterns
6545  vectorD esnr; esnr.resize(N); // SkSk snr
6546  vectorD xsnr; xsnr.resize(N); // XkSk snr
6547  vectorD am; am.resize(N); // amplitude vector
6548  vectorD pp; pp.resize(N); // energy disbalance vector
6549  vectorD qq; qq.resize(N); // complementary disbalance vector
6550  vectorD ee; ee.resize(N); // temporary
6551  vectorD Fp; Fp.resize(N); // + antenna pattern
6552  vectorD Fx; Fx.resize(N); // x antenna pattern
6553  vectorD u; u.resize(N); // PCF u vector
6554  vectorD v; v.resize(N); // PCF v vector
6555  vectorD e; e.resize(N); // PCF final vector
6556  vectorD r; r.resize(N); // PCF final vector
6557 
6558  double um,vm,cc,hh,gr,gc,gI,Et,E,Xp,Xx,gp,gx;
6559  double gg,co,si,uc,us,vc,vs,gR,a,nr;
6560  double S_NDM = 0.;
6561  double S_NUL = 0.;
6562  double S_NIL = 0.;
6563  double S_SNR = 0.;
6564  double x_SNR = 0.;
6565  double e_SNR = 0.;
6566  double bIAS = 0.;
6567  double response = 0.;
6568  size_t count = 0;
6569 
6570 // regulators hard <- soft <0> weak -> hard
6571 // gamma = -1 <- 0 -> 1
6572 
6573  double soft = delta>0. ? delta : 0.;
6574  double GAMMA = 1.-gamma*gamma; // network regulator
6575  bool status = false;
6576 
6577  this->gNET = this->aNET = this->eCOR = E = 0.;
6578  A.resize(N);
6579 
6580  for(n=0; n<N; n++) {
6581  nul[n] = this->wc_List[lag].get((char*)"null",n+1,'W',type);
6582  snr[n] = this->wc_List[lag].get((char*)"energy",n+1,'S',type);
6583  this->getifo(n)->sSNR = 0.;
6584  this->getifo(n)->xSNR = 0.;
6585  this->getifo(n)->ekXk = 0.;
6586  this->getifo(n)->null = 0.;
6587  for(m=0; m<NIFO; m++) { this->getifo(n)->ED[m] = 0.; }
6588  for(m=0; m<N; m++) { NDM[n][m] = 0.; }
6589  esnr[n] = xsnr[n] = 0.;
6590  }
6591 
6592  if(!this->wc_List[lag].size()) return status;
6593 
6594  cid = this->wc_List[lag].get((char*)"ID",0,'S',type);
6595  rat = this->wc_List[lag].get((char*)"rate",0,'S',type);
6596  lik = this->wc_List[lag].get((char*)"like",0,'S',type);
6597  K = cid.size();
6598 
6599  for(k=0; k<K; k++) { // loop over clusters
6600 
6601  id = size_t(cid[k]+0.1);
6602  if(id != ID) continue;
6603 
6604  vi = &(this->wc_List[lag].cList[ID-1]);
6605  V = vi->size();
6606  if(!V) continue;
6607 
6608 // normalization of antenna patterns
6609 // calculation of the rotation angles
6610 // calculation of the likelihood matrix
6611 
6612  for(j=0; j<V; j++) {
6613 
6614  pix = this->wc_List[lag].getPixel(ID,j);
6615  if(!pix) {
6616  cout<<"network::setndm() error: NULL pointer"<<endl;
6617  exit(1);
6618  }
6619  if(!pix->core && core) continue;
6620  if(pix->rate != rat.data[k]) continue;
6621 
6622  count++;
6623  gr=Et=gg=Xp=Xx = 0.;
6624  gC=0.;
6625 
6626  for(n=0; n<N; n++) { // calculate noise normalization
6627  nr = pix->getdata('N',n); // noise rms
6628  gg += 1./(nr*nr);
6629  }
6630  gg = sqrt(gg);
6631 
6632  for(n=0; n<N; n++) { // calculate patterns
6633  am[n] = pix->getdata('S',n); // snr amplitude
6634  nr = pix->getdata('N',n)*gg; // noise rms
6635  Et += am[n]*am[n];
6636  pd = this->getifo(n);
6637  Fp[n] = pd->mFp.get(pix->theta,pix->phi)/nr;
6638  Fx[n] = pd->mFx.get(pix->theta,pix->phi)/nr;
6639 
6640  A[n].set(Fp[n],Fx[n]);
6641 
6642  gr += A[n].abs()/2.;
6643  gC += A[n]*A[n];
6644  Xp += am[n]*Fp[n];
6645  Xx += am[n]*Fx[n];
6646  }
6647  E += Et;
6648  gc = gC.mod()/2.;
6649  gR = gC.real()/2.;
6650  gI = gC.imag()/2.;
6651  gp = gr+gR+1.e-12;
6652  gx = gr-gR+1.e-12;
6653 
6654  this->gNET += (gr+gc)*Et;
6655  this->aNET += (gr-gc)*Et;
6656 
6657 // find weak vector
6658 
6659  uc = Xp*gx - Xx*gI; // u cos of rotation to PCF
6660  us = Xx*gp - Xp*gI; // u sin of rotation to PCF
6661  vc = gp*uc + gI*us; // cos of rotation to PCF for v
6662  vs = gx*us + gI*uc; // sin of rotation to PCF for v
6663 
6664  um = vm = hh = cc = 0.;
6665  for(n=0; n<N; n++) {
6666  u[n] = Fp[n]*uc + Fx[n]*us; // u - weak vector
6667  v[n] = Fp[n]*vs - Fx[n]*vc; // v - orthogonal to u
6668  um += u[n]*u[n];
6669  vm += v[n]*v[n];
6670  hh += u[n]*am[n];
6671  cc += u[n]*am[n]*u[n]*am[n];
6672  }
6673  vm += 1.e-24; // H1H2 regulator
6674 
6675  if((hh*hh-cc)/um <= 0.) continue; // negative correlated energy
6676 
6677 // regulator
6678 
6679  ii = 0;
6680  for(n=0; n<N; n++) {
6681  if(u[n]*u[n]/um > 1-GAMMA) ii++;
6682  if(u[n]*u[n]/um+v[n]*v[n]/vm > GAMMA) ii--;
6683  }
6684  this->iNET += ii*Et;
6685 
6686  if(ii<N_2 && gamma<0.) continue; // superclean set
6687 
6688  gg = (gp+gx)*soft;
6689  uc = Xp*(gx+gg) - Xx*gI; // u cos of rotation to PCF
6690  us = Xx*(gp+gg) - Xp*gI; // u sin of rotation to PCF
6691 
6692  if(ii<N_1 && gamma!=0) {
6693  uc = Xp*(gc+gR)+Xx*gI;
6694  us = Xx*(gc-gR)+Xp*gI;
6695  }
6696 
6697  vc = gp*uc + gI*us; // (u*f+)/|u|^2 - 'cos' for v
6698  vs = gx*us + gI*uc; // (u*fx)/|u|^2 - 'sin' for v
6699  um = vm = 0.;
6700  for(n=0; n<N; n++) {
6701  u[n] = Fp[n]*uc + Fx[n]*us;
6702  v[n] = Fp[n]*vs - Fx[n]*vc;
6703  um += u[n]*u[n]; // calculate u and return its norm
6704  vm += v[n]*v[n]; // calculate u and return its norm
6705  }
6706  vm += 1.e-24; // H1H2 regulator
6707 
6708 // calculate unity vectors in PCF
6709 
6710  hh = gg = 0.;
6711  for(n=0; n<N; n++) {
6712  u[n] /=sqrt(um);
6713  v[n] /=sqrt(vm); // unity vectors in PCF
6714  hh += u[n]*am[n]; // (u*X) - solution
6715  gg += v[n]*am[n]; // (v*X) - solution
6716  }
6717 
6718 // calculate energy disbalance vectors
6719 
6720  co = si = 0.;
6721  for(n=0; n<N; n++) { // disbalance vectors
6722  cc = local ? am[n]/(am[n]*am[n]+2.) : 1.;
6723  qq[n] = cc*((2*hh*u[n]-am[n])*v[n]+u[n]*u[n]*gg); // complementary energy disbalance
6724  pp[n] = cc*(am[n]-hh*u[n])*u[n]; // energy disbalance
6725  co += pp[n]*pp[n] + qq[n]*qq[n]; // cos
6726  si += pp[n]*qq[n]; // sin
6727  }
6728  cc = atan2(si,co+1.e-24); // rotation angle
6729  co = cos(cc); // cos(psi)
6730  si = sin(cc); // sin(psi)
6731  if(!eDisbalance) {co=1.;si=0.;}
6732 
6733  hh = gg = 0.;
6734  for(n=0; n<N; n++) {
6735  e[n] = u[n]*co+v[n]*si; // final projection vector
6736  r[n] = v[n]*co-u[n]*si;
6737  hh += e[n]*am[n];
6738  gg += r[n]*am[n];
6739  }
6740 
6741 // second iteration
6742 
6743  co = si = 0.;
6744  for(n=0; n<N; n++) { // disbalance vectors
6745  cc = local ? am[n]/(am[n]*am[n]+2.) : 1.;
6746  pp[n] = cc*(am[n]-hh*e[n])*e[n]; // energy disbalance
6747  qq[n] = cc*((2*hh*e[n]-am[n])*r[n]+e[n]*e[n]*gg); // complementary energy disbalance
6748  co += pp[n]*pp[n] + qq[n]*qq[n]; // cos (version 1)
6749  si += pp[n]*qq[n]; // sin
6750  }
6751  cc = atan2(si,co+1.e-24); // rotation angle
6752  co = cos(cc); // cos(psi)
6753  si = sin(cc); // sin(psi)
6754  if(!eDisbalance) {co=1.;si=0.;}
6755 
6756  for(n=0; n<N; n++) {
6757  e[n] = e[n]*co+r[n]*si; // final projection vector
6758  }
6759 
6760 // likelihood matrix
6761 
6762  for(n=0; n<N; n++) { // loop over NDM elements
6763  response = 0.;
6764  this->getifo(n)->null += e[n]*e[n]; // bias
6765 
6766  for(m=0; m<N; m++) {
6767  gg = e[n]*am[n]*e[m]*am[m]; // en*an * em*am
6768  NDM[n][m] += gg;
6769  response += e[n]*e[m]*am[m]; // detector response
6770  if(n!=m) this->eCOR += gg; // correlated energy
6771  status = true;
6772  }
6773 
6774  esnr[n] += response*response; // reconstructed SNR: Sk*Sk
6775  xsnr[n] += am[n]*response; // reconstructed SNR: Xk*Sk
6776  e_SNR += response*response; // total reconstructed SNR: sum Sk*Sk
6777  x_SNR += am[n]*response; // total reconstructed SNR: sum Xk*Sk
6778  this->getifo(n)->ED[3] += fabs(response*(am[n]-response));
6779  this->getifo(n)->ED[4] += fabs(response*(am[n]-response));
6780  }
6781  }
6782 
6783 // check normalization
6784 
6785  this->norm = x_SNR/e_SNR; // norm factor
6786  if(fabs(this->norm-1) > 1.e-4)
6787  cout<<"network::setndm(): incorrect likelihood normalization: "<<this->norm<<endl;
6788 
6789  for(n=0; n<N; n++) {
6790  bIAS += this->getifo(n)->null;
6791  this->getifo(n)->null += nul[n].data[k]; // detector unbiased null stream
6792  this->getifo(n)->sSNR = esnr[n]; // s-energy of the detector response
6793  this->getifo(n)->xSNR = xsnr[n]; // x-energy of the detector response
6794  S_NUL += this->getifo(n)->null; // total unbiased null stream
6795  S_NIL += nul[n].data[k]; // biased null stream
6796  S_SNR += snr[n].data[k]; // total energy
6797 
6798  this->getifo(n)->ED[0] = (esnr[n]-xsnr[n]);
6799  this->getifo(n)->ED[1] = fabs(esnr[n]-xsnr[n]);
6800  this->getifo(n)->ED[2] = fabs(esnr[n]-xsnr[n]);
6801 
6802  for(m=0; m<N; m++) S_NDM += NDM[n][m];
6803 
6804  }
6805 
6806  if(count) { this->gNET /= E; this->aNET /= E; this->iNET /= E;}
6807 
6808  a = S_NDM - lik.data[k];
6809  if(fabs(a)/S_SNR>1.e-6)
6810  cout<<"ndm-likelihood mismatch: "<<a<<" "<<S_NDM<<" "<<lik.data[k]<<" "<<norm<<endl;
6811  a = fabs(1 - (S_NDM+S_NIL)/S_SNR)/count;
6812  if(a>1.e-5)
6813  cout<<"biased energy disbalance: "<<a<<" "<<S_SNR-S_NDM<<" "<<S_NIL<<" size="<<count<<endl;
6814 
6815  if(status) break;
6816  }
6817  return status;
6818 }
6819 
6820 
6821 //**************************************************************************
6822 //: initialize network data matrix (NDM), works with likelihoodI
6823 //**************************************************************************
6824 bool network::SETNDM(size_t ID, size_t lag, bool core, int type)
6825 {
6826  int ii;
6827  size_t j,n,m,k,K,V;
6828  size_t N = this->ifoList.size(); // number of detectors
6829  int N_1 = N>2 ? int(N)-1 : 2;
6830  int N_2 = N>2 ? int(N)-2 : 1;
6831  if(!N) return false;
6832 
6833  wavearray<double> cid; // cluster ID
6834  wavearray<double> rat; // cluster rate
6835  wavearray<double> lik; // likelihood
6836  vector<wavearray<double> > snr(N); // data stream snr
6837  vector<wavearray<double> > nul(N); // biased null stream
6838  vector<wavearray<double> > SNR(N); // data stream snr
6839  vector<wavearray<double> > NUL(N); // biased null stream
6840  netpixel* pix;
6841  wavecomplex gC,Z;
6842  detector* pd;
6843 
6844  std::vector<int>* vint;
6845  std::vector<wavecomplex> A; // patterns in DPF
6846  vectorD esnr; esnr.resize(N); // SkSk snr
6847  vectorD xsnr; xsnr.resize(N); // XkSk snr
6848  vectorD ssnr; ssnr.resize(N); // total energy of non shifted detector output
6849  vectorD SSNR; SSNR.resize(N); // total energy of phase shifted detector output
6850  vectorD h00; h00.resize(N); // unmodeled 00 response vector
6851  vectorD h90; h90.resize(N); // unmodeled 00 response vector
6852  vectorD u00; u00.resize(N); // unmodeled 00 unit response vector
6853  vectorD u90; u90.resize(N); // unmodeled 90 unit response vector
6854  vectorD am; am.resize(N); // 00 phase response
6855  vectorD AM; AM.resize(N); // 90 phase response
6856  vectorD qq; qq.resize(N); // energy disbalance vector
6857  vectorD pp; pp.resize(N); // energy disbalance vector
6858  vectorD ee; pp.resize(N); // temporary
6859  vectorD Fp; Fp.resize(N); // + antenna pattern
6860  vectorD Fx; Fx.resize(N); // x antenna pattern
6861  vectorD u; u.resize(N); // unity vector
6862  vectorD v; v.resize(N); // unity vector
6863  vectorD e; e.resize(N); // unity vector
6864 
6865  double a,b,aa,psi,gg,gr,gc,gI,gR,E90,E00,E,fp,fx,vc,vs;
6866  double xx,xp,XX,XP,uc,us,co,hh,gp,gx,xi00,xi90,o00,o90;
6867  double hgw,HGW,wp,WP,wx,WX,HH,um,vm,si,cc;
6868  double S_NDM = 0.;
6869  double S_NUL = 0.;
6870  double s_snr = 0.;
6871  double S_SNR = 0.;
6872  size_t count = 0;
6873 
6874 // regulator soft <- weak -> hard
6875 // gamma = -1 <- 0 -> 1
6876 
6877  double soft = delta>0. ? delta : 0.;
6878  double GAMMA = 1.-gamma*gamma; // network regulator
6879  double Eo = this->acor*this->acor*N;
6880 
6881  double nC = this->MRA ? 1. : 2.; // NDM normalization Coefficient
6882 
6883  bool status = false;
6884  bool ISG = false;
6885 
6886  if(tYPe=='I' || tYPe=='S' || tYPe=='G') ISG = true;
6887  if(tYPe=='i' || tYPe=='s' || tYPe=='g') ISG = true;
6888 
6889  A.resize(N);
6890 
6891  this->gNET = 0.;
6892  this->aNET = 0.;
6893  this->iNET = 0.;
6894  this->eCOR = 0.;
6895  E = 0.;
6896 
6897  for(n=0; n<N; n++) {
6898  nul[n] = this->wc_List[lag].get((char*)"null",n+1,'W',type);
6899  NUL[n] = this->wc_List[lag].get((char*)"null",n+1,'U',type);
6900  snr[n] = this->wc_List[lag].get((char*)"energy",n+1,'S',type);
6901  SNR[n] = this->wc_List[lag].get((char*)"energy",n+1,'P',type);
6902  this->getifo(n)->sSNR = 0.;
6903  this->getifo(n)->xSNR = 0.;
6904  this->getifo(n)->ekXk = 0.;
6905  this->getifo(n)->null = 0.;
6906  for(m=0; m<5; m++) { this->getifo(n)->ED[m] = 0.; }
6907  for(m=0; m<N; m++) { NDM[n][m] = 0.; }
6908  esnr[n]=xsnr[n]=ssnr[n]=SSNR[n]=0.;
6909  }
6910 
6911  if(!this->wc_List[lag].size()) return false;
6912 
6913  cid = this->wc_List[lag].get((char*)"ID",0,'S',type);
6914  rat = this->wc_List[lag].get((char*)"rate",0,'S',type);
6915  lik = this->wc_List[lag].get((char*)"like",0,'S',type);
6916  K = cid.size();
6917 
6918  for(k=0; k<K; k++) { // loop over clusters
6919 
6920  if(size_t(cid[k]+0.1) != ID) continue;
6921 
6922  vint = &(this->wc_List[lag].cList[ID-1]);
6923  V = vint->size();
6924  if(!V) continue;
6925 
6926  // normalization of antenna patterns
6927  // calculation of the rotation angles
6928  // calculation of the likelihood matrix
6929 
6930  for(j=0; j<V; j++) {
6931 
6932  pix = this->wc_List[lag].getPixel(ID,j);
6933  if(!pix) {
6934  cout<<"network::SETNDM() error: NULL pointer"<<endl;
6935  exit(1);
6936  }
6937  if(!pix->core && core) continue;
6938  if((pix->rate != rat.data[k]) && type) continue;
6939 
6940 
6941  psi = 2*pix->polarisation; // polarisation rotation angle
6942  Z.set(cos(psi),-sin(psi));
6943 
6944  count++;
6945  gr=gg=xp=xx=XP=XX=E00=E90 = 0.;
6946  o00 = o90 = 1.;
6947  gC = 0.;
6948 
6949  for(n=0; n<N; n++) {
6950  b = pix->getdata('N',n); // noise rms
6951  gg += 1./b/b; // noise normalization
6952  }
6953  gg = sqrt(gg);
6954 
6955  for(n=0; n<N; n++) { // calculate patterns
6956  am[n] = pix->getdata('S',n); // snr amplitude
6957  AM[n] = pix->getdata('P',n); // snr 90 degrees amplitude
6958  E00 += am[n]*am[n];
6959  E90 += AM[n]*AM[n];
6960  b = pix->getdata('N',n)*gg; // noise rms
6961  pd = this->getifo(n);
6962  fp = pd->mFp.get(pix->theta,pix->phi);
6963  fx = pd->mFx.get(pix->theta,pix->phi);
6964  A[n].set(fp/b,fx/b);
6965  A[n] *= Z; // rotate patterns
6966  Fp[n] = A[n].real();
6967  Fx[n] = A[n].imag();
6968  gr += A[n].abs()/2.;
6969  gC += A[n]*A[n];
6970  xp += Fp[n]*am[n];
6971  xx += Fx[n]*am[n];
6972  XP += Fp[n]*AM[n];
6973  XX += Fx[n]*AM[n];
6974  }
6975 
6976  E += E00+E90;
6977  gc = gC.mod()/2.;
6978  gR = gC.real()/2.;
6979  gI = gC.imag()/2.;
6980  gp = gr+gR+1.e-12;
6981  gx = gr-gR+1.e-12;
6982  aa = pix->ellipticity;
6983 
6984  this->norm = aa; // save to store in root file as norm
6985  this->gNET += (gr+gc)*(E00+E90);
6986  this->aNET += (gr-gc)*(E00+E90);
6987 
6988 //====================================================
6989 // calculate unity vectors in PCF for 00 degree phase
6990 //====================================================
6991 
6992 // find weak vector
6993 
6994  uc = xp*gx - xx*gI; // u cos of rotation to PCF
6995  us = xx*gp - xp*gI; // u sin of rotation to PCF
6996  vc = gp*uc + gI*us; // cos of rotation to PCF for v
6997  vs = gx*us + gI*uc; // sin of rotation to PCF for v
6998 
6999  um = vm = hh = cc = 0.;
7000  for(n=0; n<N; n++) {
7001  u[n] = Fp[n]*uc + Fx[n]*us;
7002  v[n] = Fp[n]*vs - Fx[n]*vc;
7003  um += u[n]*u[n];
7004  vm += v[n]*v[n];
7005  hh += u[n]*am[n];
7006  cc += u[n]*am[n]*u[n]*am[n];
7007  }
7008  vm += 1.e-24; // H1H2 regulator
7009 
7010  if((hh*hh-cc)/um<=0. || E00<Eo) o00=0.;
7011 
7012 // sky regulator
7013 
7014  ii = 0;
7015  for(n=0; n<N; n++) {
7016  if(u[n]*u[n]/um > 1-GAMMA) ii++;
7017  if(u[n]*u[n]/um+v[n]*v[n]/vm > GAMMA) ii--;
7018  }
7019  this->iNET += ii*E00;
7020  if(ii<N_2 && gamma<0.) o00=0.; // superclean selection cut
7021 
7022  gg = (gp+gx)*soft;
7023  uc = xp*(gx+gg) - xx*gI; // u cos of rotation to PCF
7024  us = xx*(gp+gg) - xp*gI; // u sin of rotation to PCF
7025 
7026  if(ii<N_1 && gamma!=0) {
7027  uc = xp*(gc+gR)+xx*gI;
7028  us = xx*(gc-gR)+xp*gI;
7029  }
7030 
7031  vc = gp*uc + gI*us; // (u*f+)/|u|^2 - 'cos' for v
7032  vs = gx*us + gI*uc; // (u*fx)/|u|^2 - 'sin' for v
7033  um = vm = 0.;
7034  for(n=0; n<N; n++) {
7035  u[n] = Fp[n]*uc + Fx[n]*us;
7036  v[n] = Fp[n]*vs - Fx[n]*vc;
7037  um += u[n]*u[n]; // calculate u and return its norm
7038  vm += v[n]*v[n]; // calculate u and return its norm
7039  }
7040  vm += 1.e-24; // H1H2 regulator
7041 
7042 // calculate unity vectors in PCF
7043 
7044  hh = gg = 0.;
7045  for(n=0; n<N; n++) {
7046  u[n] /=sqrt(um);
7047  v[n] /=sqrt(vm); // unity vectors in PCF
7048  hh += u[n]*am[n]; // (u*X) - solution
7049  gg += v[n]*am[n]; // (v*X) - solution
7050  }
7051 
7052 // calculate energy disbalance vectors
7053 
7054  co=si=0.;
7055  for(n=0; n<N; n++) { // disbalance vectors
7056  cc = local ? am[n]/(am[n]*am[n]+2.) : 1.;
7057  pp[n] = cc*(am[n]-hh*u[n])*u[n];
7058  qq[n] = cc*((2.*hh*u[n]-am[n])*v[n] + u[n]*u[n]*gg);
7059  co += pp[n]*pp[n] + qq[n]*qq[n]; // cos (version 1)
7060  si += pp[n]*qq[n]; // sin
7061  }
7062  cc = sqrt(si*si+co*co)+1.e-24;
7063  co = co/cc;
7064  si = si/cc;
7065  if(!eDisbalance) {co=1.;si=0.;}
7066 
7067 // corrected likelihood
7068 
7069  hh = gg = 0.;
7070  for(n=0; n<N; n++) { // solution for h(t,f)
7071  e[n] = u[n]*co + v[n]*si; // final projection vector
7072  v[n] = v[n]*co - u[n]*si; // orthogonal v vector
7073  u[n] = e[n];
7074  hh += u[n]*am[n]; // solution for hu(t,f)
7075  gg += v[n]*am[n]; // solution for hv(t,f)
7076  }
7077 
7078 // second iteration
7079 
7080  co=si=0.;
7081  for(n=0; n<N; n++) { // disbalance vectors
7082  cc = local ? am[n]/(am[n]*am[n]+2.) : 1.;
7083  pp[n] = cc*(am[n]-hh*u[n])*u[n];
7084  qq[n] = cc*((2.*hh*u[n]-am[n])*v[n] + u[n]*u[n]*gg);
7085  co += pp[n]*pp[n] + qq[n]*qq[n]; // cos (version 1)
7086  si += pp[n]*qq[n]; // sin
7087  }
7088  cc = sqrt(si*si+co*co)+1.e-24;
7089  co = co/cc;
7090  si = si/cc;
7091  if(!eDisbalance) {co=1.;si=0.;}
7092 
7093  hh = wp = wx = 0.;
7094  for(n=0; n<N; n++) {
7095  u[n] = u[n]*co+v[n]*si; // final projection vector
7096  hh += u[n]*am[n];
7097  wp += Fp[n]*u[n];
7098  wx += Fx[n]*u[n]*aa;
7099  }
7100  for(n=0; n<N; n++) {
7101  h00[n] = u[n]*am[n]*o00;
7102  u00[n] = u[n]*o00;
7103  am[n] = hh*u[n]*o00; // 90 detector response
7104  }
7105 
7106 //==============================================
7107 // calculate unity vectors in PCF for 90 phase
7108 //==============================================
7109 
7110 // find weak vector
7111 
7112  uc = XP*gx - XX*gI; // u cos of rotation to PCF
7113  us = XX*gp - XP*gI; // u sin of rotation to PCF
7114  vc = gp*uc + gI*us; // cos of rotation to PCF for v
7115  vs = gx*us + gI*uc; // sin of rotation to PCF for v
7116 
7117  um = vm = hh = cc = 0.;
7118  for(n=0; n<N; n++) {
7119  u[n] = Fp[n]*uc + Fx[n]*us;
7120  v[n] = Fp[n]*vs - Fx[n]*vc;
7121  um += u[n]*u[n];
7122  vm += v[n]*v[n];
7123  hh += u[n]*AM[n];
7124  cc += u[n]*AM[n]*u[n]*AM[n];
7125  }
7126  vm += 1.e-24; // H1H2 regulator
7127 
7128  if((hh*hh-cc)/um<=0. || E90<Eo) o90=0.;
7129 
7130 // sky regulator
7131 
7132  ii = 0;
7133  for(n=0; n<N; n++) {
7134  if(u[n]*u[n]/um > 1-GAMMA) ii++;
7135  if(u[n]*u[n]/um+v[n]*v[n]/vm > GAMMA) ii--;
7136  }
7137  this->iNET += ii*E90;
7138  if(ii<N_2 && gamma<0.) o90=0.; // superclean selection cut
7139 
7140  gg = (gp+gx)*soft;
7141  uc = XP*(gx+gg) - XX*gI; // u cos of rotation to PCF
7142  us = XX*(gp+gg) - XP*gI; // u sin of rotation to PCF
7143 
7144  if(ii<N_1 && gamma!=0) {
7145  uc = XP*(gc+gR)+XX*gI;
7146  us = XX*(gc-gR)+XP*gI;
7147  }
7148 
7149  vc = gp*uc + gI*us; // (u*f+)/|u|^2 - 'cos' for v
7150  vs = gx*us + gI*uc; // (u*fx)/|u|^2 - 'sin' for v
7151  um = vm = 0.;
7152  for(n=0; n<N; n++) {
7153  u[n] = Fp[n]*uc + Fx[n]*us;
7154  v[n] = Fp[n]*vs - Fx[n]*vc;
7155  um += u[n]*u[n]; // calculate u and return its norm
7156  vm += v[n]*v[n]; // calculate u and return its norm
7157  }
7158  vm += 1.e-24; // H1H2 regulator
7159 
7160 // calculate unity vectors in PCF
7161 
7162  hh = gg = 0.;
7163  for(n=0; n<N; n++) {
7164  u[n] /=sqrt(um);
7165  v[n] /=sqrt(vm); // unity vectors in PCF
7166  hh += u[n]*AM[n]; // (u*X) - solution
7167  gg += v[n]*AM[n]; // (v*X) - solution
7168  }
7169 
7170 // calculate energy disbalance vectors
7171 
7172  co=si=0.;
7173  for(n=0; n<N; n++) { // disbalance vectors
7174  cc = local ? AM[n]/(AM[n]*AM[n]+2.) : 1.;
7175  pp[n] = cc*(AM[n]-hh*u[n])*u[n];
7176  qq[n] = cc*((2.*hh*u[n]-AM[n])*v[n] + u[n]*u[n]*gg);
7177  co += pp[n]*pp[n] + qq[n]*qq[n]; // cos (version 1)
7178  si += pp[n]*qq[n]; // sin
7179  }
7180  cc = sqrt(si*si+co*co)+1.e-24;
7181  co = co/cc;
7182  si = si/cc;
7183  if(!eDisbalance) {co=1.;si=0.;}
7184 
7185 // corrected likelihood
7186 
7187  hh=gg = 0.;
7188  for(n=0; n<N; n++) { // solution for h(t,f)
7189  e[n] = u[n]*co + v[n]*si; // final projection vector
7190  v[n] = v[n]*co - u[n]*si; // orthogonal v vector
7191  u[n] = e[n];
7192  hh += u[n]*AM[n]; // solution for hu(t,f)
7193  gg += v[n]*AM[n]; // solution for hv(t,f)
7194  }
7195 
7196 // second iteration
7197 
7198  co=si=0.;
7199  for(n=0; n<N; n++) { // disbalance vectors
7200  cc = local ? AM[n]/(AM[n]*AM[n]+2.) : 1.;
7201  pp[n] = cc*(AM[n]-hh*u[n])*u[n];
7202  qq[n] = cc*((2.*hh*u[n]-AM[n])*v[n] + u[n]*u[n]*gg);
7203  co += pp[n]*pp[n] + qq[n]*qq[n]; // cos (version 1)
7204  si += pp[n]*qq[n]; // sin
7205  }
7206  cc = sqrt(si*si+co*co)+1.e-24;
7207  co = co/cc;
7208  si = si/cc;
7209  if(!eDisbalance) {co=1.;si=0.;}
7210 
7211  HH = WP = WX = 0.;
7212  for(n=0; n<N; n++) {
7213  u[n] = u[n]*co+v[n]*si; // final projection vector
7214  HH += u[n]*AM[n];
7215  WP += Fp[n]*u[n];
7216  WX += Fx[n]*u[n]*aa;
7217  }
7218  for(n=0; n<N; n++) {
7219  h90[n] = u[n]*AM[n]*o90;
7220  u90[n] = u[n]*o90;
7221  AM[n] = HH*u[n]*o90; // 90 detector response
7222  }
7223 
7224  gg = gp + aa*aa*gx; // inverse network sensitivity
7225  cc = ISG ? (wp*WX-wx*WP)/gg : 0.0; // cross term
7226  hh = ISG ? (wp*wp+wx*wx)/gg/nC : 1./nC; // 00 L term
7227  HH = ISG ? (WP*WP+WX*WX)/gg/nC : 1./nC; // 90 L term
7228 
7229 //==============================================
7230 // likelihood matrix
7231 //==============================================
7232 
7233  hgw = HGW = 0.;
7234 
7235  for(n=0; n<N; n++) {
7236  hgw += (am[n]*Fp[n] + aa*AM[n]*Fx[n])/gg; // h(0 deg)
7237  HGW += (AM[n]*Fp[n] - aa*am[n]*Fx[n])/gg; // h(90 deg)
7238  }
7239 
7240  for(n=0; n<N; n++) { // loop over NDM elements
7241  xi00 = 0.;
7242  xi90 = 0.;
7243 
7244  for(m=0; m<N; m++) {
7245 
7246  a = h00[n]*h00[m]*hh
7247  + h90[n]*h90[m]*HH
7248  + h00[n]*h90[m]*cc;
7249 
7250  xi00 += u00[n]*h00[m]; // unmodeled 00 response
7251  xi90 += u90[n]*h90[m]; // unmodeled 90 response
7252 
7253  NDM[n][m] += a;
7254  if(n!=m) this->eCOR += a; // correlated energy
7255 
7256  a = h00[n]*h00[m] - h90[n]*h90[m]; // unmodeled diff
7257  this->getifo(n)->ED[3] += a;
7258  status = true;
7259  }
7260 
7261  a = u00[n]*u00[n]*hh + u90[n]*u90[n]*HH; // bias
7262  this->getifo(n)->null += a;
7263 
7264  xx = pix->getdata('S',n); // 0-phase
7265  if(ISG) xi00 = hgw*Fp[n]-aa*HGW*Fx[n]; // 0-phase response
7266  esnr[n] += xi00*xi00; // reconstructed SNR: Sk*Sk
7267  xsnr[n] += xx*xi00; // reconstructed SNR: Xk*Sk
7268  ssnr[n] += xx*xx; // total energy of non shifted output
7269  this->getifo(n)->ED[1] += xi00*(xx-xi00);
7270  this->getifo(n)->ED[4] += fabs(xi00*(xx-xi00));
7271 
7272  XX = pix->getdata('P',n); // 90-phase
7273  if(ISG) xi90 = HGW*Fp[n]+aa*hgw*Fx[n]; // 90-phase response
7274  esnr[n] += xi90*xi90; // reconstructed SNR: Sk*Sk
7275  xsnr[n] += XX*xi90; // reconstructed SNR: Xk*Sk
7276  SSNR[n] += XX*XX; // total energy of phase shifted output
7277  this->getifo(n)->ED[2] += xi90*(XX-xi90);
7278  this->getifo(n)->ED[4] += fabs(xi90*(XX-xi90));
7279 
7280  }
7281  }
7282 
7283 // take into account norm-factor
7284 
7285  for(n=0; n<N; n++) {
7286 
7287  b = (SSNR[n]+ssnr[n] - esnr[n])/nC;
7288  this->getifo(n)->null += b; // detector biased null stream
7289  this->getifo(n)->sSNR = esnr[n]/nC; // s-energy of the detector response
7290  this->getifo(n)->xSNR = xsnr[n]/nC; // x-energy of the detector response
7291  S_NUL += b; // total biased null stream
7292  s_snr += ssnr[n]; // total energy
7293  S_SNR += SSNR[n]; // total energy of phase shifted stream
7294 
7295  for(m=0; m<N; m++) S_NDM += NDM[n][m];
7296 
7297  if(fabs(ssnr[n]-snr[n].data[k])/ssnr[n] > 1.e-6 || fabs(SSNR[n]-SNR[n].data[k])/SSNR[n]>1.e-6)
7298  cout<<"SETNDM()-likelihoodI() SNR mismatch: "<<n<<" "<<ID<<" "
7299  <<ssnr[n]<<":"<<snr[n].data[k]<<" "<<SSNR[n]<<":"<<SNR[n].data[k]<<endl;
7300  }
7301 
7302  if(count) { this->gNET /= E; this->aNET /= E; this->iNET /= E; }
7303 
7304  a = S_NDM - lik.data[k];
7305  if(fabs(a)/S_NDM>1.e-6)
7306  cout<<"NDM-likelihood mismatch: "<<a<<" "<<S_NDM<<" "<<lik.data[k]<<endl;
7307 
7308  a = fabs(1 - nC*(S_NDM+S_NUL)/(s_snr+S_SNR))/count;
7309  if(a>1.e-5)
7310  cout<<"biased energy disbalance: "<<a<<" "<<S_NDM+S_NUL<<" "<<(s_snr+S_SNR)/nC<<endl;
7311 
7312  if(status) break;
7313  }
7314  return status;
7315 }
7316 
7317 
7318 //**************************************************************************
7319 //: set parameters for time shift analysis
7320 //**************************************************************************
7322  size_t lagOff, size_t lagMax,
7323  const char* fname, const char* fmode, size_t* lagSite) {
7324  netcluster wc;
7325  size_t nIFO = this->ifoList.size();
7326  this->wc_List.clear(); this->livTime.clear();
7327 
7328  if(lagStep<=0.) {
7329  cout << "network::setTimeShifts : lagStep must be positive" << endl;
7330  exit(1);
7331  }
7332 
7333  if(lagSize<1) lagSize=1;
7334 
7335  if(strcmp(fmode,"r") && strcmp(fmode,"w") && strcmp(fmode,"s")) {
7336  cout << "network::setTimeShifts : bad fmode : must be r/w/s" << endl;
7337  exit(1);
7338  }
7339 
7340  if(fname) { if(strlen(fname)<1) fname = NULL; } // check file name
7341 
7342  TRandom3 rnd;
7343  size_t n,m,k;
7344  size_t nList = 0;
7345  size_t maxList;
7346  size_t lagIDS = lagOff;
7347  int* lagList[NIFO];
7348  int lagL[NIFO];
7349  int lagH[NIFO];
7350  int N[NIFO];
7351  int id[NIFO];
7352  int ID[NIFO];
7353  int maxIter = 10000000;
7354  detector* pd = NULL;
7355 
7356  for(n=0;n<NIFO;n++) {
7357  lagL[n] = kMinInt;
7358  lagH[n] = kMaxInt;
7359  N[n] = 0;
7360  id[n] = 0;
7361  ID[n] = 0;
7362  }
7363 
7364 // default lag list
7365 
7366  if(lagMax==0) {
7367 
7368  lagIDS += int(getifo(0)->sHIFt/lagStep);
7369  maxList = lagSize+lagIDS;
7370 
7371  for(n=0; n<nIFO; n++) lagList[n] = new int[maxList];
7372  for(m=0; m<maxList; m++) {
7373  for(n=0; n<nIFO; n++) {
7374  pd = this->getifo(n);
7375  lagList[n][m] = n==0 ? m : int(pd->sHIFt/lagStep);
7376  }
7377  }
7378  nList=maxList;
7379  goto final;
7380  }
7381 
7382 // read list of lags from file fname fmode="r" or from string fname fmode="s"
7383 
7384  if(fname && (!strcmp(fmode,"r") || !strcmp(fmode,"s"))) {
7385  if(!strcmp(fmode,"r")) { // read from file
7386 
7387  ifstream in;
7388  in.open(fname, ios::in);
7389  if(!in.good()) {
7390  cout << "network::setTimeShifts : Error Opening File : " << fname << endl;
7391  exit(1);
7392  }
7393 
7394  char str[1024];
7395  int fpos=0;
7396  maxList=0;
7397  while(true) {
7398  in.getline(str,1024);
7399  if (!in.good()) break;
7400  if(str[0] != '#') maxList++;
7401  }
7402 
7403  for(n=0; n<nIFO; n++) lagList[n] = new int[maxList];
7404  in.clear(ios::goodbit);
7405  in.seekg(0, ios::beg);
7406  while(true) {
7407  fpos=in.tellg();
7408  in.getline(str,1024);
7409  if(str[0] == '#') continue;
7410  in.seekg(fpos, ios::beg);
7411  in >> m;
7412  for(n=0; n<nIFO; n++) in >> lagList[n][m];
7413  if (!in.good()) break;
7414  fpos=in.tellg();
7415  in.seekg(fpos+1, ios::beg);
7416  }
7417 
7418  in.close();
7419  }
7420 
7421  if(!strcmp(fmode,"s")) { // read from string
7422 
7423  stringstream in;
7424  in << fname; // when fmode='s' then fname contains the lag list
7425 
7426  char str[1024];
7427  int fpos=0;
7428  maxList=0;
7429  while(true) {
7430  in.getline(str,1024);
7431  if (!in.good()) break;
7432  if(str[0] != '#') maxList++;
7433  }
7434 
7435  for(n=0; n<nIFO; n++) lagList[n] = new int[maxList];
7436  in.clear(ios::goodbit);
7437  in.seekg(0, ios::beg);
7438  while(true) {
7439  fpos=in.tellg();
7440  in.getline(str,1024);
7441  if(str[0] == '#') continue;
7442  in.seekg(fpos, ios::beg);
7443  in >> m;
7444  for(n=0; n<nIFO; n++) in >> lagList[n][m];
7445  if (!in.good()) break;
7446  fpos=in.tellg();
7447  in.seekg(fpos+1, ios::beg);
7448  }
7449  }
7450 
7451 // check boundaries
7452 
7453  int lagP=0;
7454  for (n=0; n<nIFO; n++) {lagL[n]=0;lagH[n]=lagMax;}
7455  for(m=0; m<maxList; m++){
7456  bool check=true;
7457  for (n=0; n<nIFO; n++) id[n]=lagList[n][m];
7458 
7459 // Lags must be in the range 0:lagMax
7460 
7461  for (n=0; n<nIFO; n++) if(id[n]<0||id[n]>int(lagMax)) check=false;
7462 
7463 // Difference between 2 lags belonging to different detectors must be <= lagMax
7464 
7465  for (int i=nIFO-1;i>=0;i--) {
7466  for (int j=i-1;j>=0;j--) {
7467  if (!(((id[i]-id[j])>=(lagL[i]-lagH[j]))&&
7468  ((id[i]-id[j])<=(lagH[i]-lagL[j])))) check=false;
7469  }
7470  }
7471  if (check) lagP++;
7472  }
7473 
7474  if(lagP==0) {
7475  cout << "network::setTimeShifts : no lags in the list" << endl;
7476  cout << "lagP : " << lagP << " " << lagSize << endl;
7477  exit(1);
7478  }
7479  if(lagP!=int(maxList)) {
7480  cout << "network::setTimeShifts : lags out of lagMax" << endl;
7481  cout << "lagP : " << lagP << " " << lagSize << endl;
7482  exit(1);
7483  }
7484  nList=maxList;
7485  goto final;
7486  }
7487 
7488 // extended lags list
7489 
7490  if(lagSite!=NULL) for(n=0; n<nIFO; n++) {
7491  if(lagSite[n] >= nIFO) {
7492  cout << "network::setTimeShifts : Error lagSite - value out of range " << endl;
7493  exit(-1);
7494  }
7495  }
7496 
7497  for(n=1; n<nIFO; n++) N[n]=lagMax;
7498  for(n=0; n<nIFO; n++) {lagL[n]=0;lagH[n]=lagMax;}
7499 
7500  maxList=lagOff+lagSize;
7501  for(n=0; n<nIFO; n++) lagList[n] = new int[maxList];
7502  for(n=0; n<nIFO; n++) lagList[n][nList]=0;
7503  nList++;
7504 
7505  rnd.SetSeed(13);
7506  for (int k=0;k<maxIter;k++) {
7507  for(n=0; n<nIFO; n++) ID[n] = TMath::Nint(rnd.Uniform(-(N[n]+0.5),N[n]+0.5));
7508  for(n=0; n<nIFO; n++) id[n] = (lagSite==NULL) ? ID[n] : ID[lagSite[n]];
7509  bool check=true;
7510  for(int i=nIFO-1;i>=0;i--) {
7511  for(int j=i-1;j>=0;j--) {
7512  if(!(((id[i]-id[j])>=(lagL[i]-lagH[j]))&&
7513  ((id[i]-id[j])<=(lagH[i]-lagL[j])))) check=false;
7514  if(lagSite!=NULL) {
7515  if(lagSite[i]!=lagSite[j] && id[i]==id[j]) check=false;
7516  } else {
7517  if(id[i]==id[j]) check=false;
7518  }
7519  }
7520  }
7521 // check if lag is already in the list
7522  if(check) {
7523  for(m=0;m<nList;m++) {
7524  bool pass=true;
7525  for(n=0; n<nIFO; n++) if(lagList[n][m]!=id[n]) pass=false;
7526  if(pass) check=false;
7527  }
7528  }
7529  if(check) {
7530  if(NETX(id[0]||,id[1]||,id[2]||,id[3]||,id[4]||,id[5]||,id[6]||,id[7]||) false) { // skip zero lag
7531  for(n=0; n<nIFO; n++) lagList[n][nList]=id[n];
7532  nList++;
7533  }
7534  }
7535  if (nList>=maxList) break;
7536  }
7537 
7538 // shift lags with respect to the first detector
7539 // negative lags are converted into positive
7540 
7541 final: // extract selected lags from the extended lag list
7542 
7543  for(m=0; m<nList; m++) {
7544  int lagMin = kMaxInt;
7545  for(n=0; n<nIFO; n++) if (lagList[n][m]<lagMin) lagMin=lagList[n][m];
7546  for(n=0; n<nIFO; n++) lagList[n][m]-=lagMin;
7547  }
7548 
7549  if(lagIDS+lagSize>nList) {
7550  cout << "network::setTimeShifts : lagOff+lagSize > nList of lags : " << nList << endl;
7551  exit(1);
7552  }
7553 
7554  for(n=0; n<nIFO; n++){
7555  pd = this->getifo(n);
7556  m = pd->lagShift.size();
7557  if(m!=lagSize) pd->lagShift.resize(lagSize);
7558  pd->lagShift = 0.;
7559  }
7560 
7561 // write in the final list those lags which are inside the segment boundaries
7562 // compute segment lenght
7563 
7564  double R = this->getifo(0)->getTFmap()->rate();
7565  double segLen = this->getifo(0)->getTFmap()->size();
7566  double edge = this->Edge;
7567  size_t selSize=0;
7568  size_t lagMaxSeg=0;
7569  double zero = 0.;
7570 
7571 // check boundaries
7572 
7573  segLen = (segLen/R-2*edge)/lagStep;
7574  lagMaxSeg = int(segLen)-1;
7575 
7576  for(n=0; n<nIFO; n++) {
7577  lagL[n] = 0;
7578  lagH[n] = lagMaxSeg;
7579  }
7580 
7581  for(m=0; m<lagSize; m++) {
7582  bool check = true;
7583  for (n=0; n<nIFO; n++) id[n]=lagList[n][m+lagIDS];
7584 
7585 // Lags must be in the range 0:lagMax
7586  for(n=0; n<nIFO; n++) if(id[n]<0||id[n]>int(lagMaxSeg)) check=false;
7587 
7588 // Difference between 2 lags belonging to diffent detectors must be <= lagMax
7589  for(int i=nIFO-1; i>=0; i--) {
7590  for(int j=i-1; j>=0; j--) {
7591  if (!(((id[i]-id[j])>=(lagL[i]-lagH[j]))&&
7592  ((id[i]-id[j])<=(lagH[i]-lagL[j])))) check=false;
7593  }
7594  }
7595 
7596 // lag is within the boundaries -> store in lagShift
7597 
7598  if (check) {
7599  if(lagMax) { // extended lags
7600  for(n=0; n<nIFO; n++) {
7601  k = lagList[n][m+lagIDS];
7602  if(k) check = false; // check if zero lag is present
7603  this->getifo(n)->lagShift.data[selSize] = k*lagStep;
7604  }
7605  }
7606  else {
7607  k = lagList[0][m+lagIDS];
7608  this->getifo(0)->lagShift.data[selSize] = k*lagStep;
7609  zero = 0;
7610  for(n=1; n<nIFO; n++) {
7611  pd = this->getifo(n);
7612  zero += fabs(pd->sHIFt-k*lagStep);
7613  pd->lagShift.data[selSize] = pd->sHIFt;
7614  }
7615  if(zero>0.1) check = false; // check if zero lag is present
7616  }
7617  wc.shift = check ? 0 : m+lagOff;
7618  wc_List.push_back(wc);
7619  livTime.push_back(0.);
7620  selSize++;
7621  }
7622  }
7623 
7624  if(selSize==0) {
7625  cout << "network::setTimeShifts error: no lag was selected" << endl;
7626  exit(0);
7627  }
7628 
7629  for(n=0; n<nIFO; n++) {
7630  m = this->getifo(n)->lagShift.size();
7631  if(m!=selSize) this->getifo(n)->lagShift.resize(selSize);
7632  }
7633 
7634 // dump lags list
7635 
7636  if(fname && !strcmp(fmode,"w") && lagMax) {
7637 
7638  FILE *fP=NULL;
7639  if((fP = fopen(fname, "w")) == NULL) {
7640  cout << "network::setTimeShifts error: cannot open file " << fname << endl;
7641  exit(1);
7642  }
7643 
7644  // write header
7645  fprintf(fP,"#");for (n=0;n<=nIFO;n++) fprintf(fP,"--------------");fprintf(fP,"\n");
7646  fprintf(fP,"#total %10d lags \n",int(nList));
7647  fprintf(fP,"#");for (n=0;n<=nIFO;n++) fprintf(fP,"--------------");fprintf(fP,"\n");
7648  fprintf(fP,"#%13s%14s%14s\n"," nIFO","lagStep"," lagMax");
7649  fprintf(fP,"#%13d%14.3f%14d\n",int(nIFO),lagStep,int(lagMax));
7650  fprintf(fP,"#");for (n=0;n<=nIFO;n++) fprintf(fP,"--------------");fprintf(fP,"\n");
7651  fprintf(fP,"#%13s","lagId");
7652  for(n=0; n<nIFO; n++) fprintf(fP,"%12s-%1d","lagShift",int(n));
7653  fprintf(fP,"\n");
7654  fprintf(fP,"#");for (n=0;n<=nIFO;n++) fprintf(fP,"--------------");fprintf(fP,"\n");
7655 
7656  // write lags
7657  for(m=0; m<nList; m++){
7658  fprintf(fP,"%14d", int(m));
7659  for (n=0; n<nIFO; n++) fprintf(fP,"%14d",lagList[n][m]);
7660  fprintf(fP,"\n");
7661  }
7662 
7663  if(fP!=NULL) fclose(fP);
7664  }
7665 
7666 // free memory
7667 
7668  for(n=0; n<nIFO; n++) delete [] lagList[n];
7669 
7670 // print selected lags
7671 
7672  printf("%8s ","lag");
7673  for(n=0; n<nIFO; n++) printf("%12.12s%2s","ifo",getifo(n)->Name);
7674  printf("\n");
7675  for(m=0; m<selSize; m++){
7676  printf("%8d ",(int)wc_List[m].shift);
7677  for(n=0; n<nIFO; n++) printf("%14.5f",this->getifo(n)->lagShift.data[m]);
7678  printf("\n");
7679  }
7680 
7681  nLag=selSize; Step=lagStep;
7682  return selSize;
7683 }
7684 
7685 //***************************************************************
7686 // set delay filter for a network:
7687 // time delay convention: + - shift TS right
7688 // - - shift TS left
7689 ///***************************************************************
7691 {
7692  this->filter.clear();
7693  std::vector<delayFilter>().swap(this->filter); // release memory
7694 
7695  if(!d) d = this->getifo(0); // reference detector
7696  double rate = d->getTFmap()->rate(); // data rate
7697 
7698  if(ifoList.size()<2 || !d || rate==0.) {
7699  cout<<"network::setFilter() error: incomplete network initialization"<<endl;
7700  return 0;
7701  }
7702 
7703  double T = this->getDelay((char*)"MAX")+0.002; // maximum delay
7704  delayFilter v = d->filter[0]; // delay filter
7705 
7706  int i,j,k,n,m;
7707  int M = int(d->nDFL); // number of wavelet layers
7708  int K = int(v.index.size()); // delay filter length
7709  int N = int(d->nDFS); // number of filter delays
7710  int J = int((fabs(T)*rate*N)/M+0.5); // total delay in samples
7711 
7712  if(N<M) { cout<<"network::setFilter() error"<<endl; return 0; }
7713  if(!K) return 0;
7714 
7715  this->getifo(0)->nDFS = N; // store number of filter delays in ref detector
7716  this->filter.reserve((2*J-1)*M); // allocate memory for filter
7717 
7718  for(i=0; i<M; i++) {
7719  for(j=-(J-1); j<J; j++) { // loop over delays
7720  m = j>0 ? (j+N/2-1)/N : (j-N/2)/N; // delay in wavelet pixels
7721  n = j - m*N; // n - delay in samples
7722  if(n <= 0) n = -n; // filter index for negative delays
7723  else n = N-n; // filter index for positive delays
7724  v = d->filter[n*M+i];
7725  for(k=0; k<K; k++) v.index[k] -= m*M;
7726  this->filter.push_back(v);
7727  }
7728  }
7729 
7730  return 2*J-1;
7731 }
7732 
7733 //***************************************************************
7734 // set 0-phase delay filter for a network from detector:
7735 // used in cWB script with wat-4.7.0 and earlier
7736 // time delay convention: + - shift TS right
7737 // - - shift TS left
7738 ///***************************************************************
7740 {
7741  size_t N = this->ifoList.size();
7742  if(N < 2) return;
7743  if(d) this->getifo(0)->setFilter(*d);
7744  this->setFilter(this->getifo(0));
7745  this->getifo(0)->clearFilter();
7746  return;
7747 }
7748 
7749 //***************************************************************
7750 // set delay filters for a network from detector filter files
7751 // time delay convention: + - shift TS right
7752 // - - shift TS left
7753 ///***************************************************************
7754 void network::setDelayFilters(char* fname, char* gname)
7755 {
7756  size_t N = this->ifoList.size();
7757 
7758  if(N < 2) return;
7759  if(gname) {
7760  this->getifo(0)->readFilter(gname);
7761  this->setFilter(this->getifo(0));
7762  this->filter90.clear();
7763  std::vector<delayFilter>().swap(this->filter90); // release memory
7764  this->filter90 = this->filter;
7765  }
7766  this->getifo(0)->readFilter(fname);
7767  this->setFilter(this->getifo(0));
7768  this->getifo(0)->clearFilter();
7769  return;
7770 }
7771 
7772 //***************************************************************
7773 // set delay filters for a network from a network filter file
7774 // gname defines the phase shifted filter
7775 ///***************************************************************
7776 void network::setFilter(char* fname, char* gname)
7777 {
7778  size_t N = this->ifoList.size();
7779  if(N < 2) return;
7780  if(gname) {
7781  this->readFilter(gname);
7782  this->filter90 = this->filter;
7783  }
7784  this->readFilter(fname);
7785  return;
7786 }
7787 
7788 //***************************************************************
7789 // Dumps network filter to file *fname in binary format.
7790 //***************************************************************
7791 void network::writeFilter(const char *fname)
7792 {
7793  size_t i,j,k;
7794  FILE *fp;
7795 
7796  if ( (fp=fopen(fname, "wb")) == NULL ) {
7797  cout << " network::writeFilter() error : cannot open file " << fname <<". \n";
7798  return ;
7799  }
7800 
7801  size_t M = size_t(getifo(0)->TFmap.maxLayer()+1); // number of wavelet layers
7802  size_t N = size_t(filter.size()/M); // number of delays
7803  size_t K = size_t(filter[0].index.size()); // delay filter length
7804  size_t n = K * sizeof(float);
7805  size_t m = K * sizeof(short);
7806 
7809 
7810  fwrite(&K, sizeof(size_t), 1, fp); // write filter length
7811  fwrite(&M, sizeof(size_t), 1, fp); // number of layers
7812  fwrite(&N, sizeof(size_t), 1, fp); // number of delays
7813 
7814  for(i=0; i<M; i++) { // loop over wavelet layers
7815  for(j=0; j<N; j++) { // loop over delays
7816  for(k=0; k<K; k++) { // loop over filter coefficients
7817  value.data[k] = filter[i*N+j].value[k];
7818  index.data[k] = filter[i*N+j].index[k];
7819  }
7820  fwrite(value.data, n, 1, fp);
7821  fwrite(index.data, m, 1, fp);
7822  }
7823  }
7824  fclose(fp);
7825 }
7826 
7827 //***************************************************************
7828 // Read network filter from file *fname.
7829 //***************************************************************
7830 void network::readFilter(const char *fname)
7831 {
7832  size_t i,j,k;
7833  FILE *fp;
7834 
7835  if ( (fp=fopen(fname, "rb")) == NULL ) {
7836  cout << " network::readFilter() error : cannot open file " << fname <<". \n";
7837  exit(1);
7838  }
7839 
7840  size_t M; // number of wavelet layers
7841  size_t N; // number of delays
7842  size_t K; // delay filter length
7843 
7844  fread(&K, sizeof(size_t), 1, fp); // read filter length
7845  fread(&M, sizeof(size_t), 1, fp); // read number of layers
7846  fread(&N, sizeof(size_t), 1, fp); // read number of delays
7847 
7848  size_t n = K * sizeof(float);
7849  size_t m = K * sizeof(short);
7852  delayFilter v;
7853 
7854  v.value.clear(); v.value.reserve(K);
7855  v.index.clear(); v.index.reserve(K);
7856  filter.clear(); filter.reserve(N*M);
7857 
7858  for(k=0; k<K; k++) { // loop over filter coefficients
7859  v.value.push_back(0.);
7860  v.index.push_back(0);
7861  }
7862 
7863  for(i=0; i<M; i++) { // loop over wavelet layers
7864  for(j=0; j<N; j++) { // loop over delays
7865  fread(value.data, n, 1, fp);
7866  fread(index.data, m, 1, fp);
7867  for(k=0; k<K; k++) { // loop over filter coefficients
7868  v.value[k] = value.data[k];
7869  v.index[k] = index.data[k];
7870  }
7871  filter.push_back(v);
7872  }
7873  }
7874  fclose(fp);
7875 }
7876 
7877 // extract accurate timr delay amplitudes for a given sky location
7878 void network::updateTDamp(int l, float** v00, float** v90) {
7879 // parameter 1 - sky location index
7880 // parameter 2 - 0-phase array for time-delayed amplitudes
7881 // parameter 3 - 90-phase array for time-delayed amplitudes
7882 // Algorithm: for a given pixel set extract TF data from the sparse maps.
7883 // Obtain time domain data for each resolution, time-shift
7884 // detectors for a given sky location l. Reproduce time-shifted TF maps and
7885 // extract time-shifted amplitudes. Update time delay arrays - only one sky
7886 // location is updated
7887 
7888  int nres = this->wdmList.size(); // number of resolutions
7889  int nIFO = this->ifoList.size(); // number of detectors
7890  int V = int(this->pList.size()); // number of pixels
7891  int layers;
7892 
7893  WSeries<double> WW;
7895  netpixel* pix;
7896  detector* pd;
7897 
7898  for(int i=0; i<nres; i++) {
7899  for(int k=0; k<nIFO; k++) {
7900  pd = this->getifo(k);
7901  pd->vSS[i].Expand(false); // expand sparse map
7902 
7903  WW = pd->vSS[i]; // copy TF map
7904  pd->vSS[i].Inverse(); // 0-phase TS
7905  WW.Inverse(-2); // 90-phase TS
7906  pd->vSS[i].getLayer(x,0); // get I time series
7907  WW.getLayer(y,0); // get Q time series
7908  x+=y; x*=0.5; // prepare time series
7909  x.delay(pd->index[l]/this->rTDF); // time shift data in x
7910  pd->vSS[i].Forward(x); // prepare TF map
7911  layers = pd->vSS[i].maxLayer()+1; // number of WDM layers
7912 
7913  for(int j=0; j<V; j++) { // loop over pixels
7914  pix = this->pList[j];
7915  if(pix->layers != layers) continue; // skip wrong resolution
7916  int ind = int(pix->data[k].index); // index in TF array
7917  v00[k][j] = pd->vSS[i].GetMap00(ind); // update 00 amplitude
7918  v90[k][j] = pd->vSS[i].GetMap90(ind); // update 00 amplitude
7919  }
7920 
7921  pd->vSS[i].Shrink(); // shrink TF map
7922  }
7923  }
7924 }
7925 
7926 //***************************************************************
7927 // delay detectors in the network with respect to reference
7928 // to match sky location theta and phi
7929 // index array should be setup
7930 ///***************************************************************
7931 void network::delay(double theta, double phi)
7932 {
7933  size_t m;
7934  size_t N = this->ifoList.size(); // number of detectors
7935  size_t k = this->getIndex(theta,phi); // sky index
7936  detector* d;
7937 
7938  for(size_t n=1; n<N; n++){
7939  d = this->getifo(n);
7940  m = d->index.data[k]; // delay index
7941  this->delay(d,m);
7942  }
7943  return;
7944 }
7945 
7946 //***************************************************************
7947 // delay detector in a network:
7948 // m - is the delay index
7949 ///***************************************************************
7950 void network::delay(detector* d, size_t m)
7951 {
7952  double R = d->getTFmap()->rate();
7953 
7954  size_t i,j,k;
7955  size_t N = d->getTFmap()->size();
7956  size_t I = d->TFmap.maxLayer()+1;
7957  size_t M = this->filter.size()/I; // total number of delays
7958  size_t K = this->filter[0].index.size(); // filter length
7959  size_t jB = size_t(this->Edge*R/I)*I; // number of samples in the edges
7960  size_t jS;
7961 
7962  slice S;
7963  delayFilter* pv;
7964 
7965 // buffer for wavelet layer delay filter
7966  double* F = (double*)malloc(K*sizeof(double));
7967  int* J = (int*)malloc(K*sizeof(int));
7968 
7969  N -= jB; // correction for left boundary
7970 
7971  WSeries<double> temp = d->TFmap;
7972  d->TFmap=0.;
7973 
7974 // cout<<"m="<<m<<" N="<<N<<" R="<<R<<" I="<<I<<" M="<<M<<" K="<<K<<endl;
7975 
7976  double* p1 = temp.data;
7977  double* b0 = temp.data;
7978 
7979  for(i=0; i<I; i++) { // loop over wavelet layers
7980 
7981 // set filter array for this layer and delay index
7982  pv = &(filter[i*M+m]);
7983  for(k=0; k<K; k++){
7984  F[k] = double(pv->value[k]);
7985  J[k] = int(pv->index[k]);
7986  }
7987 
7988  S = d->getTFmap()->getSlice(i);
7989  jS = S.start()+jB;
7990 
7991  for(j=jS; j<N; j+=I) { // loop over samples in the layer
7992  p1=b0+j;
7993  d->TFmap.data[j] = dot32(F,p1,J); // apply delay filter
7994  }
7995  }
7996  free(F);
7997  free(J);
7998 }
7999 
8000 //***************************************************************
8001 //:set index array for delayed amplitudes
8002 // used with wavelet delay filters
8003 // time delay convention: t+tau - arrival time at the center of Earth
8004 // ta1-tau0 - how much det1 should be delayed to be sinchronized with det0
8005 ///***************************************************************
8007 {
8008  double t;
8009  int i,ii;
8010  size_t n,m,l,k;
8011  size_t N = ifoList.size(); // number of detectors
8012 
8013  double tt[NIFO][NIFO];
8014  double TT[NIFO];
8015  int mm[NIFO][NIFO];
8016 
8017  if(N<2) {
8018  cout<<"network::setDelayIndex(): invalid network\n";
8019  return;
8020  }
8021 
8022  detector* dr[NIFO];
8023  for(n=0; n<N; n++) dr[n] = ifoList[n];
8024 
8025  size_t I = dr[0]->nDFL; // number of wavelet layers
8026  size_t K = this->filter.size()/I; // number of delays
8027  size_t L = dr[0]->tau.size(); // skymap size
8028 
8029  double rate = dr[0]->getTFmap()->rate(); // data rate
8030  rate *= dr[0]->nDFS/I; // up-sample rate
8031 
8032  if(pOUT) cout<<"filter size="<<this->filter.size()
8033  <<" layers="<<I<<" delays="<<K<<" samples="<<dr[0]->nDFS<<endl;
8034 
8035  if(!(K&1) || rate == 0.) {
8036  cout<<"network::setDelayIndex(): invalid network\n";
8037  return;
8038  }
8039 
8040  for(n=0; n<N; n++) {
8041  if(dr[n]->index.size() != L) {
8042  dr[n]->index.resize(L);
8043  }
8044  }
8045 
8046 // calculate time interval the di detector is delayed to be
8047 // sinchronized with dr
8048 // time delay > 0 - shift di right (future)
8049 // time delay < 0 - shift di left (past)
8050 
8051  this->nPenalty = dr[0]->tau;
8052 
8053  for(l=0; l<L; l++){
8054 
8055 // calculate time delay matrix
8056 // 0 d01 d02
8057 // d10 0 d12
8058 // d20 d21 0
8059 
8060  for(n=0; n<N; n++) {
8061  for(m=0; m<N; m++) {
8062  t = dr[n]->tau.get(l)-dr[m]->tau.get(l);
8063  i = int(t*rate+2*K+0.5) - 2*K;
8064  mm[n][m] = i;
8065  tt[n][m] = t*rate;
8066  }
8067  }
8068 
8069  for(n=0; n<N; n++) {
8070  TT[n] = 0.; // max delay for n-th configuration
8071  for(m=0; m<N; m++) {
8072  for(k=0; k<N; k++) {
8073  t = fabs(mm[n][k]-mm[n][m]-tt[m][k]);
8074  if(TT[n] < t) TT[n] = t;
8075  }
8076  }
8077  }
8078 
8079  t = 20.; i = N;
8080  for(m=0; m<N; m++) {
8081  if(t>TT[m]) { t = TT[m]; k = m; } // first best configuration
8082  }
8083  this->nPenalty.set(l,double(t));
8084 
8085  t = dr[k]->tau.get(l);
8086  i = mIFO<9 ? mm[k][this->mIFO] : int(t*rate+2*K+0.5)-2*K;
8087 
8088 // 0 d01 d02 0 d01 d02
8089 // d10 0 d12 -> 0 d'01 d'02
8090 // d20 d21 0 0 d"01 d"02
8091 
8092  for(m=0; m<N; m++) {
8093  ii = (K/2+mm[k][m])-i; // convert to time delay with respect to master IFO
8094  dr[m]->index.data[l] = ii;
8095  if(ii < 0) cout<<"network::setDelayIndex error: sky index<0: "<<k<<endl;
8096  }
8097  }
8098  return;
8099 }
8100 
8101 //***************************************************************
8102 //:set theta, phi index array
8103 //:will not work on 32 bit with the option other than 0,2,4
8104 //***************************************************************
8106 {
8107  detector* dr = ifoList[0];
8108 
8109  if(ifoList.size()<2 || !dr->tau.size()) {
8110  cout<<"network::setIndex() - invalid network"<<endl;
8111  return 0;
8112  }
8113 
8114  size_t i,j,n,m;
8115  size_t L = dr->tau.size();
8116  size_t N = ifoList.size();
8117  size_t I = mode ? dr->nDFL : 1; // number of wavelet layers
8118  // TO BE FIXED !!! works only for 1G
8119  // for 2G only mode=0 works !!!
8120  size_t K = this->filter.size()/I; // number of delays
8121  size_t J = 0; // counter for rejected locations
8122  size_t M = mIFO<9 ? mIFO : 0; // reference detector
8123  long long ll;
8124 
8125  if(this->index.size()!=L) this->index.resize(L);
8126  if(this->skyMask.size()!=L) this->skyMask.resize(L);
8127  if(this->skyHole.size()!=L) { this->skyHole.resize(L); this->skyHole = 1.; }
8128  for(j=0; j<L; j++) {
8129  index.data[j] = j;
8130  skyMask.data[j] = size_t(skyHole.data[j]+0.1);
8131  }
8132  if(!mode) return 0;
8133 
8134  if(mode==2 || mode==4) {
8135  dr->tau.downsample(skyMask,mode);
8136  return 0;
8137  }
8138 
8139  wavearray<long long> delay(L);
8140  long long **pp = (long long**)malloc(L*sizeof(long long*));
8141  skymap* sm = &nSkyStat;
8142 
8143  for(n=0; n<N; n++) {
8144  if(!this->getifo(n)->index.size()) {
8145  cout<<"network::setIndex() - invalid network"<<endl;
8146  return 0;
8147  }
8148  }
8149 
8150  for(i=0; i<L; i++){
8151  delay.data[i] = 0;
8152  pp[i] = delay.data+i;
8153  m = 0;
8154  for(n=0; n<N; n++) {
8155  if(n == M) continue;
8156  ll = this->getifo(n)->index.data[i];
8157  if(this->mIFO==99) ll += K/2 - this->getifo(0)->index.data[i];
8158  delay.data[i] += ll<<(m*12);
8159  m++;
8160  }
8161  }
8162 
8163  delay.waveSort(pp,0,L-1);
8164  ll = *(pp[0]);
8165  for(i=1; i<L; i++) {
8166  j = pp[i] - delay.data;
8167  if(ll == *(pp[i])) {
8168  skyMask.data[j] = 0; // remove duplicate delay configurations
8169  J++;
8170  if(pOUT) cout<<" "<<j<<"|"<<sm->getTheta(j)<<"|"<<sm->getPhi(j);
8171  }
8172  else {
8173  ll = *(pp[i]);
8174  if(pOUT) cout<<"\n ll="<<ll<<" "<<j<<"|"<<sm->getTheta(j)<<"|"<<sm->getPhi(j);
8175  }
8176  }
8177 
8178  free(pp);
8179  return J;
8180 }
8181 
8182 void
8184 
8185  // print detector's info
8186  int nIFO = ifoListSize();
8187  for(int n=0; n<nIFO; n++) getifo(n)->print();
8188 
8189  // print MDC log infos
8190 
8191  cout << "----------------------------------------------" << endl;
8192  cout << " INJECTIONS : " << this->mdcListSize() << endl;
8193  cout << "----------------------------------------------" << endl;
8194  for(size_t k=0;k<this->mdcListSize();k++) {
8195  string str(this->getmdcList(k));
8196  cout << endl << str.c_str() << endl;
8197  }
8198 
8199  return;
8200 }
8201 
wavearray< double > t(hp.size())
std::vector< char * > ifoName
Definition: network.hh:609
double sHIFt
Definition: detector.hh:335
static float _sse_abs_ps(__m128 *_a)
Definition: watsse.hh:137
double pc
Definition: DrawEBHH.C:15
double rho
double netCC
Definition: network.hh:596
virtual void resize(unsigned int)
Definition: wseries.cc:901
double sTARt
static const double C
Definition: GNGen.cc:28
#define NIFO
Definition: wat.hh:74
float phi
Definition: netpixel.hh:117
double getWFfreq(char atype='S')
Definition: detector.cc:1779
size_t nLag
Definition: network.hh:573
std::vector< vector_int > cRate
Definition: netcluster.hh:398
double getlow() const
Definition: wseries.hh:129
void printwc(size_t)
Definition: network.cc:2658
double start
Definition: network.hh:55
double lagStep
Definition: test_config1.C:53
TH1 * t1
double M
Definition: DrawEBHH.C:13
gnetwork * gNET
double duration
std::vector< netcluster > wc_List
Definition: network.hh:610
par [0] value
wavearray< double > getMRAwave(network *net, int ID, size_t n, char atype='S', int mode=0)
Definition: netcluster.cc:2899
size_t add(detector *)
param: detector structure return number of detectors in the network
Definition: network.cc:2559
void setFpFx(double, double=0., double=180., double=0., double=360.)
param - step on phi and theta param - theta begin param - theta end param - phi begin param - phi end...
Definition: detector.cc:709
TString live
size_t readMDClog(char *, double=0., int=11, int=12)
param: MDC log file param: approximate gps time
Definition: network.cc:3370
size_t clusterID
Definition: netpixel.hh:109
int offset
Definition: TestSTFT_2.C:19
virtual void rate(double r)
Definition: wavearray.hh:141
double delta
std::vector< wavearray< float > > tdAmp
Definition: netpixel.hh:123
float factor
virtual ~network()
Definition: network.cc:70
static void _avx_pol_ps(float **p, float **q, wavearray< double > *pol00, wavearray< double > *pol90, std::vector< float *> &pAPN, std::vector< float *> &pAVX, int II)
Definition: watavx.hh:431
double sSNR
Definition: detector.hh:338
#define _ALIGNED
Definition: wat.hh:71
TCanvas * c2
bool getwave(size_t, size_t, char='W')
param: cluster ID param: delay index param: time series type return: true if time series are extracte...
Definition: network.cc:3576
double m1
float M2
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
double getWFtime(char atype='S')
Definition: detector.cc:1764
par [0] name
size_t * lagSite
Definition: test_config1.C:58
long getNetworkPixels(int LAG, double Eo, double DD=1., TH1F *hist=NULL)
Definition: network.cc:78
static void _sse_add4_ps(__m128 *_a, __m128 *_b, __m128 _c)
Definition: watsse.hh:262
double Gamma(double r)
Definition: watfun.hh:193
int n
Definition: cwb_net.C:28
static __m128 _sse_abs4_ps(__m128 *_p)
Definition: watsse.hh:157
static void _sse_zero_ps(__m128 *_p)
Definition: watsse.hh:44
static __m128 _sse_ed4_ps(__m128 *_p, __m128 *_q, __m128 _L)
Definition: watsse.hh:873
std::vector< vectorD > NDM
Definition: network.hh:603
void getSkyArea(size_t id, size_t lag, double T)
param: cluster id param: lag param: cluster time
Definition: network.cc:4255
std::vector< int > neighbors
Definition: netpixel.hh:124
double iGamma(double r, double p)
Definition: watfun.hh:205
double imag() const
Definition: wavecomplex.hh:70
static float _avx_dpf_ps(double **Fp, double **Fx, int l, std::vector< float *> &pAPN, std::vector< float *> &pAVX, int I)
Definition: watavx.hh:84
size_t nRun
Definition: network.hh:572
wavearray< double > fx
Definition: detector.hh:364
size_t setIndexMode(size_t=0)
Definition: network.cc:8105
int ID
Definition: TestMDC.C:70
static __m128 _sse_dot4_ps(__m128 *_p, __m128 *_q)
Definition: watsse.hh:223
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
std::vector< delayFilter > filter
Definition: detector.hh:361
wavearray< double > HRSS
Definition: detector.hh:371
std::vector< wavearray< double > * > RWFP
Definition: detector.hh:382
static void _sse_cpf4_ps(__m128 *_aa, __m128 *_pp)
Definition: watsse.hh:317
bool optim
float theta
wavearray< double > rank
Definition: Regression_H1.C:80
size_t nDFS
Definition: detector.hh:342
WDM< double > wdm(nLAYERS, nLAYERS, 6, 10)
void add(const wavearray< DataType_t > &, int=0, int=0, int=0)
Definition: wavearray.cc:746
std::vector< vector_float > sArea
Definition: netcluster.hh:401
netpixel pix(nifo)
UChar_t VETO[100]
netcluster * pwc
Definition: cwb_job_obj.C:38
TH2F * ph
virtual size_t initwc(double, double)
param: cluster start time relative to segment start param: cluster duration return cluster list size ...
Definition: network.cc:3727
double get_SS()
Definition: detector.hh:309
wavearray< short > index
Definition: detector.hh:368
wavearray< int > sI
size_t setSkyMask(double f, char *fname)
Definition: network.cc:3213
double min()
Definition: skymap.cc:459
int layers
std::vector< std::string > mdcType
Definition: network.hh:613
size_t mIFO
Definition: network.hh:575
STL namespace.
static __m256 _avx_stat_ps(float **x, float **X, float **s, float **S, std::vector< float *> &pAVX, int I)
Definition: watavx.hh:1128
double getTheta(size_t i)
Definition: skymap.hh:224
size_t lagOff
Definition: test_config1.C:54
void setAntenna()
Definition: network.cc:2873
std::slice getSlice(double n)
Definition: wseries.hh:152
waveform wf
double getThetaStep(size_t i)
Definition: skymap.hh:242
static void _sse_cpf_ps(float *a, __m128 *_p)
Definition: watsse.hh:307
double theta_1
Definition: skymap.hh:321
Long_t size
NET segList
Definition: cwb_net.C:294
wavearray< double > hp
Definition: DrawInspiral.C:43
WSeries< double > waveBand
Definition: detector.hh:356
void test_sse(int, int)
Definition: network.cc:256
size_t setFilter(detector *=NULL)
param: detector
Definition: network.cc:7690
size_t layers
Definition: netpixel.hh:112
int m
Definition: cwb_net.C:28
double getPhiStep(size_t i)
Definition: skymap.hh:182
std::vector< vector_int > cList
Definition: netcluster.hh:397
virtual void start(double s)
Definition: wavearray.hh:137
double max()
Definition: skymap.cc:438
std::vector< size_t > mdc__ID
Definition: network.hh:615
void downsample(wavearray< short > &, size_t=4)
Definition: skymap.cc:536
int j
Definition: cwb_net.C:28
static void _sse_rotm_ps(__m128 *u, float *c, __m128 *v, float *s, __m128 *a)
Definition: watsse.hh:424
bool getMRAwave(size_t ID, size_t lag, char atype='S', int mode=0, bool tof=false)
Definition: network.cc:3666
i drho i
void updateTDamp(int, float **, float **)
Definition: network.cc:7878
TRandom3 rnd(1)
std::vector< double > mdcTime
Definition: network.hh:614
double gethigh() const
Definition: wseries.hh:136
long subNetCut(int lag, float subnet=0.6, float subcut=0.33, TH2F *hist=NULL)
Definition: network.cc:1014
long coherence(double, double=0., double=0.)
param: threshold on lognormal pixel energy (in units of noise rms) param: threshold on total pixel en...
Definition: network.cc:3815
skymap tau
Definition: detector.hh:346
wavearray< double > hh
Definition: Regression_H1.C:73
std::vector< double > vectorD
Definition: network.hh:51
long likelihood2G(char mode, int lag, int ID, TH2F *hist=NULL)
Definition: network.cc:1387
std::vector< detector * > ifoList
Definition: network.hh:608
double get_XX()
Definition: detector.hh:310
#define N
double netCC
Definition: test_config1.C:33
cout<< "SNR "<< xsnr<< endl;wavearray< double > f
Definition: ComputeSNR.C:75
static float _avx_GW_ps(float **p, float **q, std::vector< float *> &pAPN, float *rr, std::vector< float *> &pAVX, int II)
Definition: watavx.hh:251
bool core
Definition: netpixel.hh:120
std::vector< vector_float > p_Map
Definition: netcluster.hh:402
double Edge
Definition: network.hh:578
double theta_2
Definition: skymap.hh:322
cout<< "Selected Pixels : "<< nPix<< endl;wc.cluster(1, 1);SSeries< double > ss
network()
Definition: network.cc:46
void writeFilter(const char *fname)
Definition: network.cc:7791
fprintf(stdout,"start=%f duration=%f rate=%f\, x.start(), x.size()/x.rate(), x.rate())
#define PI
Definition: watfun.hh:32
skymap mFx
Definition: detector.hh:348
void clean(int cID=0)
Definition: netcluster.hh:451
double aNET
Definition: network.hh:580
bool optim
Definition: network.hh:590
size_t mode
watplot p2(const_cast< char *>("TFMap2"))
virtual void waveSplit(DataType_t **pp, size_t l, size_t r, size_t m) const
Definition: wavearray.cc:1499
wavearray< double > w
Definition: Test1.C:27
#define nIFO
void wrate(double r)
Definition: wseries.hh:120
char val[20]
wavearray< double > ffp
Definition: detector.hh:365
virtual size_t size() const
Definition: wavearray.hh:145
int getLevel()
Definition: wseries.hh:109
float phi
size_t size()
Definition: netpixel.hh:89
double precision
Definition: network.hh:593
double ra
Definition: ConvertGWGC.C:46
char str[1024]
size_t wavecount(double x, int n=0)
Definition: wavearray.hh:304
long likelihoodWP(char mode, int lag, int ID, TH2F *hist=NULL)
Definition: network.cc:293
float psi
size_t size() const
Definition: wslice.hh:89
wavearray< double > xx
Definition: TestFrame1.C:11
double setVeto(double=5.)
param: time window around injections
Definition: network.cc:3487
static float _avx_packet_ps(float **p, float **q, std::vector< float *> &pAVX, int I)
Definition: watavx.hh:754
double shift
Definition: netcluster.hh:382
int _sse_MRA_ps(network *net, float *amp, float *AMP, float Eo, int K)
void set(double x, double y)
Definition: wavecomplex.hh:74
waveSegment SEG
std::vector< double > livTime
Definition: network.hh:611
TGraph * gr
wavearray< double > hx
Definition: DrawInspiral.C:44
size_t start() const
Definition: wslice.hh:85
double real() const
Definition: wavecomplex.hh:69
int pattern
Definition: monster.hh:30
bool local
Definition: network.hh:589
wavearray< double > * px
TCanvas * c1
wavearray< double > TIME
Definition: detector.hh:375
r setFilter(10)
i() int(T_cor *100))
static __m128 _sse_ecoh4_ps(__m128 *_p, __m128 *_q, __m128 _L)
Definition: watsse.hh:778
float polarisation
Definition: netpixel.hh:119
wavearray< double > * getHoT()
param: no parameters
Definition: detector.hh:175
int getOrder()
Definition: skymap.hh:314
gwavearray< double > * gx
watplot p1(const_cast< char *>("TFMap1"))
void setDelayIndex(double rate)
param: MDC log file
Definition: network.cc:2896
std::vector< std::string > mdcList
Definition: network.hh:612
bool log
Definition: WaveMDC.C:41
double * tmp
Definition: testWDM_5.C:31
double getDelay(const char *c="")
Definition: network.cc:2818
double eCOR
Definition: network.hh:582
double D[50000]
static __m128 _sse_ind4_ps(__m128 *_p, __m128 _L)
Definition: watsse.hh:809
bool EFEC
static void _avx_free_ps(std::vector< float *> &v)
Definition: watavx.hh:40
wavearray< double > fpx
Definition: detector.hh:367
WSeries< double > pTF[nRES]
Definition: revMonster.cc:8
char cut[512]
wavearray< double > fp
Definition: detector.hh:363
double get_XS()
Definition: detector.hh:312
double start
Definition: netcluster.hh:379
double gNET
Definition: network.hh:579
int getLayer(wavearray< DataType_t > &w, double n)
param: n - layer number
Definition: wseries.cc:193
printf("total live time: non-zero lags = %10.1f \, liveTot)
int l
std::vector< vector_int > p_Ind
Definition: netcluster.hh:403
static double tau
Definition: geodesics.cc:26
char fname[1024]
segLen
Definition: cwb_eced.C:24
std::vector< int > RWFID
Definition: detector.hh:381
Definition: Wavelet.hh:49
static void _sse_pol4_ps(__m128 *_fp, __m128 *_fx, __m128 *_v, double *r, double *a)
Definition: watsse.hh:1086
double precision
static void _avx_loadNULL_ps(float **n, float **N, float **d, float **D, float **h, float **H, int I)
Definition: watavx.hh:707
double Step
Definition: network.hh:577
double acor
bool eDisbalance
int k
std::vector< waveSegment > segList
Definition: network.hh:616
int _sse_mra_ps(network *NET, float *amp, float *AMP, float Eo, int K)
static void _sse_rot4m_ps(__m128 *_u, __m128 *_c, __m128 *_v, __m128 *_s, __m128 *_a)
Definition: watsse.hh:472
double THRESHOLD(double bpp)
param: selected fraction of LTF pixels assuming Gaussian noise
Definition: network.cc:2615
double mchirp(int ID, double=2.5, double=1.e20, double=0)
Definition: netcluster.cc:1424
static double A
Definition: geodesics.cc:26
void readFilter(const char *)
Definition: network.cc:7830
double acor
Definition: network.hh:585
x *double Et
Definition: ComputeSNR.C:40
double F
size_t time
Definition: netpixel.hh:110
void setDelay(const char *="L1")
Definition: network.cc:2767
Definition: skymap.hh:63
wavearray< double > lagShift
Definition: detector.hh:369
double e2or
Definition: network.hh:584
double e
void setLevel(size_t n)
Definition: wseries.hh:112
double mod() const
Definition: wavecomplex.hh:73
long likelihood(char='E', double=sqrt(2.), int=0, size_t=0, int=-1, bool=false)
Definition: network.cc:4446
static void _avx_cpf_ps(float **p, float **q, float **u, float **v, int I)
Definition: watavx.hh:49
static float _avx_ort_ps(float **p, float **q, std::vector< float *> &pAVX, int I)
Definition: watavx.hh:1035
WSeries< double > ww
Definition: Regression_H1.C:33
long likelihoodI(char='P', double=sqrt(2.), int=0, size_t=0, int=-1, bool=false)
Definition: network.cc:5296
double phi2RA(double ph, double gps)
Definition: skymap.hh:212
#define STAT
Definition: FrDisplay.cc:128
netpixel * getPixel(size_t n, size_t i)
Definition: netcluster.hh:413
int npix
virtual void FFTW(int=1)
Definition: wavearray.cc:896
FILE * fP
regression r
Definition: Regression_H1.C:44
s s
Definition: cwb_net.C:155
int index
Definition: network.hh:54
char filter[1024]
wavearray< double > ffm
Definition: detector.hh:366
double getPhi(size_t i)
Definition: skymap.hh:164
WSeries< double > TFmap
Definition: detector.hh:354
bool wfsave
Definition: network.hh:600
double gps
double pSigma
Definition: network.hh:594
float ellipticity
Definition: netpixel.hh:118
void print()
Definition: network.cc:8183
double T
Definition: testWDM_4.C:11
static float _avx_setAMP_ps(float **p, float **q, std::vector< float *> &pAVX, int I)
Definition: watavx.hh:956
ifstream in
std::vector< int > sCuts
Definition: netcluster.hh:392
WSeries< double > waveForm
Definition: detector.hh:355
WSeries< double > * getTFmap()
param: no parameters
Definition: detector.hh:179
wavearray< int > index
double xSNR
Definition: detector.hh:339
float theta
Definition: netpixel.hh:116
virtual void delay(double T)
Definition: wavearray.cc:596
Definition: Meyer.hh:36
char Name[16]
Definition: detector.hh:327
xsnr * xsnr
Definition: ComputeSNR.C:71
virtual void stop(double s)
Definition: wavearray.hh:139
skymap mFp
Definition: detector.hh:347
double fabs(const Complex &x)
Definition: numpy.cc:55
double norm
Definition: network.hh:583
double m2
virtual void waveSort(DataType_t **pp, size_t l=0, size_t r=0) const
Definition: wavearray.cc:1421
double gamma
Definition: network.hh:592
#define GPS
double get_NN()
Definition: detector.hh:311
std::vector< short > index
Definition: detector.hh:45
float M1
void Forward(int n=-1)
param: wavelet - n is number of steps (-1 means full decomposition)
Definition: wseries.cc:246
Meyer< double > S(1024, 2)
double df
static __m128 _sse_sum_ps(__m128 **_p)
Definition: watsse.hh:515
sprintf(tfres,"(1/%g)x(%g) (sec)x(Hz)", 2 *df, df)
static float _avx_loadata_ps(float **p, float **q, float **u, float **v, float En, std::vector< float *> &pAVX, int I)
Definition: watavx.hh:634
DataType_t get(size_t i)
Definition: wavearray.hh:282
std::vector< clusterdata > cData
Definition: netcluster.hh:391
double netRHO
Definition: test_config1.C:32
static void _sse_point_ps(__m128 **_p, float **p, short **m, int l, int n)
Definition: watsse.hh:502
float CC[4]
Definition: monster.hh:30
void setDelayFilters(detector *=NULL)
Definition: network.cc:7739
double phi_2
Definition: skymap.hh:324
static void _sse_mul_ps(__m128 *_a, float b)
Definition: watsse.hh:56
double getwave(int, netcluster &, char, size_t)
param: no parameters
Definition: detector.cc:561
DataType_t * data
Definition: wavearray.hh:319
double null
Definition: detector.hh:336
long nSky
Definition: network.hh:574
netcluster wc
Long_t id
enum WAVETYPE m_WaveType
Definition: Wavelet.hh:106
double phi_1
Definition: skymap.hh:323
double iGamma1G(double r, double p)
Definition: watfun.hh:246
double get(size_t i)
param: sky index
Definition: skymap.cc:699
WaveDWT< DataType_t > * pWavelet
Definition: wseries.hh:456
double dT
Definition: testWDM_5.C:12
size_t netcut(double, char='L', size_t=0, int=1)
param: threshold param: minimum cluster size processed by the corrcut param: cluster type return: num...
Definition: network.cc:2998
long nSky
void delay(double theta, double phi)
Definition: network.cc:7931
long likelihoodB(char='E', double=sqrt(2.), int=0, size_t=0, int=-1, bool=false)
param: maximized statistic: param: threshold to define core pixels (in units of noise rms) ...
Definition: network.cc:4470
bool save
static float _sse_maxE_ps(__m128 *_a, __m128 *_A)
Definition: watsse.hh:554
cout<< "live time after cat 2 : "<< detSegs_ctime<< endl;if(detSegs_ctime< segTHR) {cout<< "job segment live time after cat2 < "<< segTHR<< " sec, job terminated !!!"<< endl;exit(1);} double Tb=detSegs[0].start;double Te=detSegs[0].stop;double dT=Te-Tb;char file[512], tdf00[512], tdf90[512], buFFer[1024];int rnID=int(gRandom->Rndm(13) *1.e9);if(simulation) { i=NET.readMDClog(injectionList, double(long(Tb)) -mdcShift);printf("GPS: %16.6f saved, injections: %d\", double(long(Tb)), i);frTB[nIFO].shiftBurstMDCLog(NET.mdcList, ifos, mdcShift);for(int i=0;i< NET.mdcTime.size();i++) NET.mdcTime[i]+=mdcShift;vector< waveSegment > mdcSegs(NET.mdcTime.size());for(int k=0;k< NET.mdcTime.size();k++) {mdcSegs[k].start=NET.mdcTime[k]-gap;mdcSegs[k].stop=NET.mdcTime[k]+gap;} vector< waveSegment > mdcSegs_dq2=slagTB.mergeSegLists(detSegs_dq2, mdcSegs);double mdcSegs_ctime=slagTB.getTimeSegList(mdcSegs_dq2);cout<< "live time in zero lag after cat2+inj : "<< mdcSegs_ctime<< endl;if(mdcSegs_ctime==0) {cout<< "job segment with zero cat2+inj live time in zero lag, job terminated !!!"<< endl;exit(1);} } if(dump_infos_and_exit) exit(0);if(mask >0.) NET.setSkyMask(mask, skyMaskFile);for(i=0;i< nIFO;i++) { frTB[i].readFrames(FRF[i], channelNamesRaw[i], x);x.start(x.start()+dataShift[i]);x.start(x.start() -segLen *(segID[i]-segID[0]));if(singleDetector) TB.resampleToPowerOfTwo(x);sprintf(file,"%s/%s_%d_%s_%d_%d.dat", nodedir, ifo[i], int(Tb), data_label, runID, rnID);if(dump_sensitivity_and_exit) { sprintf(file,"%s/sensitivity_%s_%d_%s_job%d.txt", dump_dir, ifo[i], int(Tb), data_label, runID);cout<< endl<< "Dump Sensitivity : "<< file<< endl<< endl;TB.makeSpectrum(file, x);continue;} if(dcCal[i]>0.) x *=dcCal[i];if(fResample >0) { x.FFT(1);x.resize(fResample/x.rate() *x.size());x.FFT(-1);x.rate(fResample);} pTF[i]=pD[i]-> getTFmap()
fclose(ftrig)
float rate
Definition: netpixel.hh:113
std::vector< SSeries< double > > vSS
Definition: detector.hh:352
static void _sse_minSNE_ps(__m128 *_pE, __m128 **_pe, __m128 *_es)
Definition: watsse.hh:540
network & operator=(const network &)
Definition: network.cc:2511
size_t size()
Definition: skymap.hh:136
WSeries< double > waveNull
Definition: detector.hh:357
double getdata(char type='R', size_t n=0)
Definition: netpixel.hh:74
size_t setRank(double, double=0.)
Definition: network.cc:3116
static __m128 _sse_like4_ps(__m128 *_f, __m128 *_a, __m128 *_A)
Definition: watsse.hh:998
static void _sse_rot4p_ps(__m128 *_u, __m128 *_c, __m128 *_v, __m128 *_s, __m128 *_a)
Definition: watsse.hh:442
double shift[NIFO_MAX]
std::vector< float > value
Definition: detector.hh:46
static void _sse_rotp_ps(__m128 *u, float *c, __m128 *v, float *s, __m128 *a)
Definition: watsse.hh:416
virtual void resize(unsigned int)
Definition: wavearray.cc:463
bool MRA
Definition: network.hh:599
int check
size_t readSEGlist(char *, int=1)
param: segment list file param: start time collumn number
Definition: network.cc:3446
int setTimeShifts(size_t=1, double=1., size_t=0, size_t=0, const char *=NULL, const char *="w", size_t *=NULL)
param number of time lags param time shift step in seconds param first lag ID param maximum lag ID pa...
Definition: network.cc:7321
double penalty
Definition: network.hh:595
void Inverse(int n=-1)
param: n - number of steps (-1 means full reconstruction)
Definition: wseries.cc:291
wavearray< double > y
Definition: Test10.C:31
size_t ifoID
Definition: detector.hh:328
double stop
Definition: network.hh:56
double delta
Definition: network.hh:591
void putLayer(wavearray< DataType_t > &, double n)
param: n - layer number
Definition: wseries.cc:219
char c3[8]
double netRHO
Definition: network.hh:597
bool setndm(size_t, size_t, bool=true, int=1)
param: cluster ID param: lag index param: statistic identificator param: resolution idenificator retu...
Definition: network.cc:6525
double frequency(int l)
Definition: wseries.cc:117
static void _sse_dpf4_ps(__m128 *_Fp, __m128 *_Fx, __m128 *_fp, __m128 *_fx)
Definition: watsse.hh:631
#define SNR
Definition: DrawNRI.C:36
bool SETNDM(size_t, size_t, bool=true, int=1)
Definition: network.cc:6824
float null
Definition: netpixel.hh:115
static void _sse_pnp4_ps(__m128 *_fp, __m128 *_fx, __m128 *_am, __m128 *_AM, __m128 *_u, __m128 *_v)
Definition: watsse.hh:641
wavearray< double > ISNR
Definition: detector.hh:372
size_t nDFL
Definition: detector.hh:343
int maxLayer()
Definition: wseries.hh:139
bool EFEC
Definition: network.hh:587
static __m256 _avx_noise_ps(float **p, float **q, std::vector< float *> &pAVX, int I)
Definition: watavx.hh:1276
detector ** pD
double iNET
Definition: network.hh:581
size_t lagMax
Definition: test_config1.C:55
void setTau(double, double=0., double=180., double=0., double=360.)
param - step on phi and theta param - theta begin param - theta end param - phi begin param - phi end...
Definition: detector.cc:654
static void _sse_ort4_ps(__m128 *_u, __m128 *_v, __m128 *_s, __m128 *_c)
Definition: watsse.hh:572
std::vector< vector_int > nTofF
Definition: netcluster.hh:404
void setSkyMaps(double, double=0., double=180., double=0., double=360.)
param: sky map granularity step, degrees param: theta begin, degrees param: theta end...
Definition: network.cc:2687
exit(0)
void cpf(const wavearray< DataType_t > &, int=0, int=0, int=0)
Definition: wavearray.cc:717
void clean()
Definition: netpixel.hh:99
bool setdata(double a, char type='R', size_t n=0)
Definition: netpixel.hh:58
double enrg
Definition: detector.hh:337
#define GAMMA(TYPE)
Definition: xroot.hh:5
double threshold(double, double)
param: selected fraction of LTF pixels assuming Gaussian noise param: maximum time delay between dete...
Definition: network.cc:2644
double avr
size_t healpix
size_t lagSize
Definition: test_config1.C:52