Logo coherent WaveBurst  
Library Reference Guide
Logo
detector.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
21 // WAT detector class
22 // ++++++++++++++++++++++++++++++++++++++++++++++
23 
24 #define DETECTOR_CC
25 #include "detector.hh"
26 #include "Meyer.hh"
27 #include "Symlet.hh"
28 
29 #include "TVector3.h"
30 #include "TRotation.h"
31 #include "Math/Rotation3D.h"
32 #include "Math/Vector3Dfwd.h"
33 
34 using namespace ROOT::Math;
35 using namespace std;
36 
37 // All LIGO coordinates are verbatim from LIGO-P000006-D-E:
38 // Rev. Sci. Instrum., Vol. 72, No. 7, July 2001
39 
40 // LIGO Hanford 4k interferometer
41 extern const double _rH1[3] = {-2.161414928e6, -3.834695183e6, 4.600350224e6};
42 extern const double _eH1x[3] = {-0.223891216, 0.799830697, 0.556905359};
43 extern const double _eH1y[3] = {-0.913978490, 0.026095321, -0.404922650};
44 
45 // LIGO Hanford 2k interferometer
46 extern const double _rH2[3] = {-2.161414928e6, -3.834695183e6, 4.600350224e6};
47 extern const double _eH2x[3] = {-0.223891216, 0.799830697, 0.556905359};
48 extern const double _eH2y[3] = {-0.913978490, 0.026095321, -0.404922650};
49 
50 // LIGO Livingston interferometer
51 extern const double _rL1[3] = {-7.427604192e4, -5.496283721e6, 3.224257016e6};
52 extern const double _eL1x[3] = {-0.954574615, -0.141579994, -0.262187738};
53 extern const double _eL1y[3] = { 0.297740169, -0.487910627, -0.820544948};
54 
55 // GEO coordinates on
56 // http://www.geo600.uni-hannover.de/geo600/project/location.html
57 // x any y arms swaped compare to
58 // Anderson, Brady, Creighton, and Flanagan, PRD 63 042003, 2001,
59 
60 // GEO-600 interferometer
61 extern const double _rG1[3] = {3.8563112e6, 6.665978e5, 5.0196406e6};
62 extern const double _eG1x[3] = {-0.445184239, 0.866534205, 0.225675575};
63 extern const double _eG1y[3] = {-0.626000687, -0.552167273, 0.550667271};
64 
65 // Virgo interferometer
66 extern const double _rV1[3] = {4.5463741e6, 8.429897e5, 4.378577e6};
67 extern const double _eV1x[3] = {-0.700458309, 0.208487795, 0.682562083};
68 extern const double _eV1y[3] = {-0.053791331, -0.969082169, 0.240803326};
69 
70 // TAMA interferometer
71 extern const double _rT1[3] = {-3.946409e6, 3.366259e6, 3.6991507e6};
72 extern const double _eT1x[3] = {0.648969405, 0.760814505, 0};
73 extern const double _eT1y[3] = {-0.443713769, 0.378484715, -0.812322234};
74 
75 // KAGRA interferometer
76 extern const double _rK1[3] = {-3.7770908e+06, 3.4846722e+06, 3.7650676e+06};
77 extern const double _eK1x[3] = {-0.3740476967, -0.8378767376, 0.3975561509};
78 extern const double _eK1y[3] = {0.7142972255, 0.01312009275, 0.6997194701};
79 
80 // AIGO interferometer
81 extern const double _rA1[3] = {-2.3567784e6, 4.8970238e6, -3.3173147e6};
82 extern const double _eA1x[3] = {-9.01077021322091554e-01, -4.33659084587544319e-01, 0};
83 extern const double _eA1y[3] = {-2.25940560005277846e-01, 4.69469807139026196e-01, 8.53550797275327455e-01};
84 
85 // AURIGA bar
86 extern const double _rO1[3] = {4.392467e6, 0.9295086e6, 4.515029e6};
87 extern const double _eO1x[3] = {-0.644504130, 0.573655377, 0.50550364};
88 extern const double _eO1y[3] = {0., 0., 0.};
89 
90 // NAUTILUS bar
91 extern const double _rN1[3] = {4.64410999868e6, 1.04425342477e6, 4.23104713307e6};
92 extern const double _eN1x[3] = {-0.62792641437, 0.56480832712, 0.53544371484};
93 extern const double _eN1y[3] = {0., 0., 0.};
94 
95 // EXPLORER bar
96 extern const double _rE1[3] = {4.37645395452e6, 4.75435044067e5, 4.59985274450e6};
97 extern const double _eE1x[3] = {-0.62792641437, 0.56480832712, 0.53544371484};
98 extern const double _eE1y[3] = {0., 0., 0.};
99 
100 
101 // see also detector coordinates used by GravEn
102 // https://gravity.psu.edu/~s4/sims/BurstMDC/Validation/getifo.m
103 
104 ClassImp(detector)
105 
106 // constructors
107 
109 {
110  for(int i=0; i<3; i++){
111  this->Rv[i] = _rL1[i];
112  this->Ex[i] = _eL1x[i];
113  this->Ey[i] = _eL1y[i];
114  }
115  init();
116  this->sHIFt = 0.;
117  this->null = 0.;
118  this->sSNR = 0.;
119  this->xSNR = 0.;
120  this->ekXk = 0.;
121  this->ifoID = 0;
122  this->rate = 16384.;
123  this->TFmap.rate(4096);
124  detectorParams null_dP = {"",0.0,0,0,0,0,0,0};
125  this->dP = null_dP;
126  this->polarization = TENSOR;
127  this->wfSAVE = 0;
128 }
129 
130 detector::detector(char* name, double t)
131 {
132  const double* pRv;
133  const double* pEx;
134  const double* pEy;
135 
136  bool xifo=false;
137 
138  if(strstr(name,"L1")) {pRv=_rL1; pEx=_eL1x; pEy=_eL1y;xifo=true;}
139  if(strstr(name,"H1")) {pRv=_rH1; pEx=_eH1x; pEy=_eH1y;xifo=true;}
140  if(strstr(name,"H2")) {pRv=_rH2; pEx=_eH2x; pEy=_eH2y;xifo=true;}
141  if(strstr(name,"G1")) {pRv=_rG1; pEx=_eG1x; pEy=_eG1y;xifo=true;}
142  if(strstr(name,"T1")) {pRv=_rT1; pEx=_eT1x; pEy=_eT1y;xifo=true;}
143  if(strstr(name,"V1")) {pRv=_rV1; pEx=_eV1x; pEy=_eV1y;xifo=true;}
144  if(strstr(name,"A1")) {pRv=_rA1; pEx=_eA1x; pEy=_eA1y;xifo=true;}
145  if(strstr(name,"A2")) {pRv=_rA1; pEx=_eA1x; pEy=_eA1y;xifo=true;}
146  if(strstr(name,"Virgo")) {pRv=_rV1; pEx=_eV1x; pEy=_eV1y;xifo=true;}
147  if(strstr(name,"VIRGO")) {pRv=_rV1; pEx=_eV1x; pEy=_eV1y;xifo=true;}
148  if(strstr(name,"GEO")) {pRv=_rG1; pEx=_eG1x; pEy=_eG1y;xifo=true;}
149  if(strstr(name,"TAMA")) {pRv=_rT1; pEx=_eT1x; pEy=_eT1y;xifo=true;}
150  if(strstr(name,"K1")) {pRv=_rK1; pEx=_eK1x; pEy=_eK1y;xifo=true;}
151  if(strstr(name,"O1")) {pRv=_rO1; pEx=_eO1x; pEy=_eO1y;xifo=true;}
152  if(strstr(name,"N1")) {pRv=_rN1; pEx=_eN1x; pEy=_eN1y;xifo=true;}
153  if(strstr(name,"E1")) {pRv=_rE1; pEx=_eE1x; pEy=_eE1y;xifo=true;}
154 
155  if(!xifo) {
156  cout << "detector::detector - Error : detector " << name
157  << " is not in present in the builtin list" << endl;
158  exit(1);
159  }
160 
161  sprintf(this->Name,"%s",name);
162  SetName(name);
163  for(int i=0; i<3; i++){
164  this->Rv[i] = pRv[i];
165  this->Ex[i] = pEx[i];
166  this->Ey[i] = pEy[i];
167  }
168  if(strstr(name,"A2")) this->rotate(45); // rotate arms for A2
169  init(); // fill detector tensor.
170  this->sHIFt = t;
171  this->null = 0.;
172  this->sSNR = 0.;
173  this->xSNR = 0.;
174  this->ekXk = 0.;
175  this->ifoID = 0;
176  this->rate = 16384.;
177  this->TFmap.rate(4096);
178  detectorParams null_dP = {"",0.0,0,0,0,0,0,0};
179  this->dP = null_dP;
180  this->polarization = TENSOR;
181  this->wfSAVE = 0;
182 }
183 
185 {
186  double rad2deg = 180./TMath::Pi();
187  double deg2rad = TMath::Pi()/180.;
188 
189  double uRv[3];
190  double uEx[3];
191  double uEy[3];
192 
193  GeodeticToGeocentric(dP.latitude*deg2rad,dP.longitude*deg2rad,dP.elevation,uRv[0],uRv[1],uRv[2]);
194  GetCartesianComponents(uEx,dP.AltX*deg2rad,dP.AzX*deg2rad, dP.latitude*deg2rad,dP.longitude*deg2rad);
195  GetCartesianComponents(uEy,dP.AltY*deg2rad,dP.AzY*deg2rad, dP.latitude*deg2rad,dP.longitude*deg2rad);
196 
197  sprintf(this->Name,"%s",dP.name);
198  SetName(dP.name);
199  for(int i=0; i<3; i++){
200  this->Rv[i] = uRv[i];
201  this->Ex[i] = uEx[i];
202  this->Ey[i] = uEy[i];
203  }
204  init(); // fill detector tensor.
205  this->sHIFt = t;
206  this->null = 0.;
207  this->sSNR = 0.;
208  this->xSNR = 0.;
209  this->ekXk = 0.;
210  this->ifoID = 0;
211  this->rate = 16384.;
212  this->TFmap.rate(4096);
213  this->dP = dP;
214  this->polarization = TENSOR;
215  this->wfSAVE = 0;
216 }
217 
219 {
220  // -----------------------------------------
221  // user define detector
222  // -----------------------------------------
223  if(strlen(this->dP.name)>0) return this->dP;
224 
225  // -----------------------------------------
226  // builtin detector
227  // -----------------------------------------
228  double rad2deg = 180./TMath::Pi();
229  double deg2rad = TMath::Pi()/180.;
230 
231  XYZVector iRv(this->Rv[0],this->Rv[1],this->Rv[2]);
232  TVector3 vRv(iRv.X(),iRv.Y(),iRv.Z());
233 
234  // Ex angle respect to east direction
235  XYZVector iEx(this->Ex[0],this->Ex[1],this->Ex[2]);
236  XYZVector iEy(this->Ey[0],this->Ey[1],this->Ey[2]);
237  XYZVector iEZ(0.,0.,1.); // Zeta cartesian axis
238 
239  TVector3 vEx(iEx.X(),iEx.Y(),iEx.Z());
240  TVector3 vEy(iEy.X(),iEy.Y(),iEy.Z());
241  TVector3 vEZ(iEZ.X(),iEZ.Y(),iEZ.Z());
242 
243  vEx*=1./vEx.Mag();
244  vEy*=1./vEy.Mag();
245  vEZ*=1./vEZ.Mag();
246  vRv*=1./vRv.Mag();
247 
248  TVector3 vEe=vEZ.Cross(vRv); // vEe point to east in the local detector frame
249  vEe*=1./vEe.Mag();
250 
251  double cosExAngle=vEe.Dot(vEx); // ExAngle is the angle of Ex respect to East counter-clockwise
252  if(cosExAngle>1.) cosExAngle=1.;
253  if(cosExAngle<-1.) cosExAngle=-1.;
254  double cosEyAngle=vEe.Dot(vEy); // EyAngle is the angle of Ey respect to Eas counter-clockwiset
255  if(cosEyAngle>1.) cosEyAngle=1.;
256  if(cosEyAngle<-1.) cosEyAngle=-1.;
257 
258  double ExAngle=acos(cosExAngle)*rad2deg;
259  double EyAngle=acos(cosEyAngle)*rad2deg;
260 
261  // fix sign of ExAngle,EyAngle
262  TVector3 vEn;
263  vEn=vEe.Cross(vEx);
264  if(vEn.Dot(vRv)<0) ExAngle*=-1;
265  vEn=vEe.Cross(vEy);
266  if(vEn.Dot(vRv)<0) EyAngle*=-1;
267 
268  // Convert ExAngle to the angle of Ex respect to North clockwise
269  ExAngle=fmod(90-ExAngle,360.);
270  // Convert EyAngle to the angle of Ey respect to North clockwise
271  EyAngle=fmod(90-EyAngle,360.);
272 
273  double latitude,longitude,elevation;
274  GeocentricToGeodetic(iRv.X(),iRv.Y(),iRv.Z(),latitude,longitude,elevation);
275 
276  detectorParams idP;
277 
278  sprintf(idP.name,"%s",this->Name);
279  idP.latitude = latitude*rad2deg;
280  idP.longitude = longitude*rad2deg;
281  idP.elevation = elevation;
282  idP.AltX = 0.;
283  idP.AzX = ExAngle;
284  idP.AltY = 0.;
285  idP.AzY = EyAngle;
286 
287  return idP;
288 }
289 
290 // rotate arms in the detector plane by angle a in degrees counter-clockwise
291 void detector::rotate(double a)
292 {
293  double ax[3];
294  double ay[3];
295  double si = sin(a*PI/180.);
296  double co = cos(a*PI/180.);
297 
298  for(int i=0; i<3; i++) {
299  ax[i] = this->Ex[i];
300  ay[i] = this->Ey[i];
301  }
302 /*
303  for(int i=0; i<3; i++) {
304  this->Ex[i] = ax[i]*co+ay[i]*si;
305  this->Ey[i] = ay[i]*co-ax[i]*si;
306  }
307 */
308  double aww=0.;
309  double aw[3];
310  double axy=0.;
311 
312  for(int i=0; i<3; i++) axy+=ax[i]*ay[i];
313 
314  // compute vector aw in the plane Ex,Ey ortogonal to Ex and rotate Ex
315  aww=0.;
316  for(int i=0; i<3; i++) {aw[i]=-ax[i]*axy+ay[i]; aww+=aw[i]*aw[i];}
317  for(int i=0; i<3; i++) aw[i]/=sqrt(aww);
318  for(int i=0; i<3; i++) this->Ex[i]=ax[i]*co+aw[i]*si; // rotate Ex
319 
320  // compute vector aw in the plane Ex,Ey ortogonal to Ey and rotate Ey
321  aww=0.;
322  for(int i=0; i<3; i++) {aw[i]=-ax[i]+ay[i]*axy; aww+=aw[i]*aw[i];}
323  for(int i=0; i<3; i++) aw[i]/=sqrt(aww);
324  for(int i=0; i<3; i++) this->Ey[i]=ay[i]*co+aw[i]*si; // rotate Ey
325 
326  init(); // fill detector tensor.
327 
328  // update user define detector
329  if(strlen(this->dP.name)>0) {
330  this->dP.AzX = fmod(this->dP.AzX-a,360.);
331  this->dP.AzY = fmod(this->dP.AzY-a,360.);
332  }
333 }
334 
335 
336 detector::detector(const detector& value)
337 {
338  *this = value;
339 }
340 
341 // destructor
342 
344 
345  int n;
346 
347  n = IWFP.size();
348  for (int i=0;i<n;i++) {
350  delete wf;
351  }
352  IWFP.clear();
353  IWFID.clear();
354 
355  n = RWFP.size();
356  for (int i=0;i<n;i++) {
358  delete wf;
359  }
360  RWFP.clear();
361  RWFID.clear();
362 
363 }
364 
365 //: operator =
366 //: !!! not fully implemented
367 
368 detector& detector::operator=(const detector& value)
369 {
370  sprintf(Name,"%s",value.Name);
371  SetName(Name);
372  for(int i=0; i<3; i++){
373  this->Rv[i] = value.Rv[i];
374  this->Ex[i] = value.Ex[i];
375  this->Ey[i] = value.Ey[i];
376  }
377  init();
378 
379  tau = value.tau;
380  mFp = value.mFp;
381  mFx = value.mFx;
382 
383  TFmap = value.TFmap;
384  waveForm = value.waveForm;
385  sHIFt = value.sHIFt;
386  null = value.null;
387  nRMS = value.nRMS;
388  nVAR = value.nVAR;
389 
390  dP = value.dP;
391 
392  polarization = value.polarization;
393 
394  wfSAVE = value.wfSAVE;
395 
396  return *this;
397 }
398 
399 
401 {
402  double tsRate =TFmap.wavearray<double>::rate();
403  TFmap = value;
404  waveForm.resize(size_t(tsRate));
405  waveForm.rate(tsRate);
406  waveForm.setWavelet(*(TFmap.pWavelet));
407  return *this;
408 }
409 
410 // copy 'from' injection stuff
411 detector& detector::operator<<(detector& value)
412 {
413  wfSAVE = value.wfSAVE;
414  HRSS = value.HRSS;
415  ISNR = value.ISNR;
416  FREQ = value.FREQ;
417  BAND = value.BAND;
418  TIME = value.TIME;
419  TDUR = value.TDUR;
420 
421  IWFID = value.IWFID;
422 
423  for (int i=0;i<IWFP.size();i++) {
425  delete wf;
426  }
427  IWFP.clear();
428  for(int i=0;i<value.IWFP.size();i++) {
430  *wf = *value.IWFP[i];
431  IWFP.push_back(wf);
432  }
433 
434  return *this;
435 }
436 
437 // copy 'to' injection stuff
438 detector& detector::operator>>(detector& value)
439 {
440  value.wfSAVE = wfSAVE;
441  value.HRSS = HRSS;
442  value.ISNR = ISNR;
443  value.FREQ = FREQ;
444  value.BAND = BAND;
445  value.TIME = TIME;
446  value.TDUR = TDUR;
447 
448  value.IWFID = IWFID;
449 
450  for (int i=0;i<value.IWFP.size();i++) {
452  delete wf;
453  }
454  value.IWFP.clear();
455  for(int i=0;i<IWFP.size();i++) {
457  *wf = *IWFP[i];
458  value.IWFP.push_back(wf);
459  }
460 
461  return *this;
462 }
463 
464 
465 //**************************************************************************
466 // initialize detector tenzor
467 //**************************************************************************
469 {
470  DT[0] = Ex[0]*Ex[0]-Ey[0]*Ey[0];
471  DT[1] = Ex[0]*Ex[1]-Ey[0]*Ey[1];
472  DT[2] = Ex[0]*Ex[2]-Ey[0]*Ey[2];
473 
474  DT[3] = DT[1];
475  DT[4] = Ex[1]*Ex[1]-Ey[1]*Ey[1];
476  DT[5] = Ex[1]*Ex[2]-Ey[1]*Ey[2];
477 
478  DT[6] = DT[2];
479  DT[7] = DT[5];
480  DT[8] = Ex[2]*Ex[2]-Ey[2]*Ey[2];
481 
482  if (strcmp(Name,"O1")==0) for (int i=0;i<9;i++) DT[i]*=2;
483  if (strcmp(Name,"N1")==0) for (int i=0;i<9;i++) DT[i]*=2;
484  if (strcmp(Name,"E1")==0) for (int i=0;i<9;i++) DT[i]*=2;
485 }
486 
487 //**************************************************************************
488 // return antenna pattern
489 //**************************************************************************
490 wavecomplex detector::antenna(double theta, double phi, double psi)
491 {
492  double a,b;
493 
494  theta *= PI/180.; phi *= PI/180.; psi *= PI/180.;
495 
496  double cT = cos(theta);
497  double sT = sin(theta);
498  double cP = cos(phi);
499  double sP = sin(phi);
500 
501  double d11 = DT[0];
502  double d12 = DT[1];
503  double d13 = DT[2];
504 
505  double d21 = DT[3];
506  double d22 = DT[4];
507  double d23 = DT[5];
508 
509  double d31 = DT[6];
510  double d32 = DT[7];
511  double d33 = DT[8];
512 
513 
514  double fp = 0.;
515  double fx = 0.;
516 
517  if(polarization==TENSOR) {
518 
519  fp = (cT*cP*d11 + cT*sP*d21 - sT*d31)*cT*cP
520  + (cT*cP*d12 + cT*sP*d22 - sT*d32)*cT*sP
521  - (cT*cP*d13 + cT*sP*d23 - sT*d33)*sT
522  + (cP*d21-sP*d11)*sP
523  - (cP*d22-sP*d12)*cP;
524 
525  fx = -(cT*cP*d11 + cT*sP*d21 - sT*d31)*sP
526  + (cT*cP*d12 + cT*sP*d22 - sT*d32)*cP
527  + (cP*d21-sP*d11)*cT*cP
528  + (cP*d22-sP*d12)*cT*sP
529  - (cP*d23-sP*d13)*sT;
530 
531  fp = -fp; // to follow convention in LIGO-T010110 and Anderson et al.
532 
533  if(fabs(psi)>0.) { // rotate in the waveframe A'=exp(-2*i*psi)A
534  a = fp*cos(2*psi)+fx*sin(2*psi);
535  b = -fp*sin(2*psi)+fx*cos(2*psi);
536  fp = a; fx = b;
537  }
538  }
539 
540  if(polarization==SCALAR) {
541 
542  fp = -(cT*cP*d11 + cT*sP*d21 - sT*d31)*cT*cP
543  - (cT*cP*d12 + cT*sP*d22 - sT*d32)*cT*sP
544  + (cT*cP*d13 + cT*sP*d23 - sT*d33)*sT
545  + (cP*d21-sP*d11)*sP
546  - (cP*d22-sP*d12)*cP;
547 
548  fp = 2*fp;
549  fx = 0;
550  }
551 
552  wavecomplex z(fp/2.,fx/2.);
553  return z;
554 }
555 
556 
557 
558 //**************************************************************************
559 // reconstruct wavelet series for a cluster, put it in waveForm
560 //**************************************************************************
561 double detector::getwave(int ID, netcluster& wc, char atype, size_t index)
562 {
563  int i,j,n,m,k,l;
564  double a,b,rms,fl,fh;
565  double R = this->TFmap.rate();
566  int L = int(this->TFmap.maxLayer()+1);
567 
568  waveForm.setWavelet(*(TFmap.pWavelet));
569  waveForm.rate(R);
570  rms = wc.getwave(ID,waveForm,atype,index);
571 
572  if(rms==0.) return rms;
573 
574 // create bandlimited detector output
575 
576  waveBand = waveForm; waveBand = 0.;
577  fh = waveBand.gethigh();
578  fl = waveBand.getlow();
579  l = int(this->TFmap.getLevel()) - int(waveBand.getLevel());
580 
581 // adjust waveBand resolution to match TFmap
582 
583  if(l<0) { waveBand.Inverse(-l); }
584  else { waveBand.Forward(l); }
585 
586  a = waveBand.start()*R;
587  i = int(a + ((a>0) ? 0.1 : -0.1));
588  k = waveBand.size(); j = 0;
589  if(i<0) { k += i; j = -i; i = 0; }
590  if((i/L)*L != i) cout<<"detector::getwave() time mismatch: "<<L<<" "<<i<<"\n";
591 
592  waveBand.cpf(this->TFmap,k,i,j);
593  waveNull = waveBand;
594 
595  n = int(2*L*fl/R+0.1)-1; // first layer
596  m = int(2*L*fh/R+0.1)+1; // last layer
597  if(n<=0) n=0;
598  if(m>=int(L)) m=L;
599  if(m<=n) { n=0; m=L; }
600 
601  WSeries<double> w = waveBand;
603 
604 // cout<<i<<" L="<<L<<" Band start="<<waveBand.start()<<endl;
605 
606  waveBand = 0;
607  for(k=n; k<m; k++) { w.getLayer(x,k); waveBand.putLayer(x,k); }
608 
609  waveBand.Inverse();
610  waveForm.Inverse();
611  waveNull.Inverse();
612  waveForm *= atype=='w' ? 1./sqrt(this->rate/R) : 1.; // rescale waveform
613  w = waveForm;
614 
615 // window the waveforms
616 
617  double sTARt= waveForm.start();
618  size_t I = waveForm.size();
619  size_t M = I/2;
620  double sum = waveForm.data[M]*waveForm.data[M];
621 
622  a = waveForm.rms();
623  double hrss = a*a*I;
624 
625  for(i=1; i<int(M); i++) {
626  a = waveForm.data[M-i];
627  b = waveForm.data[M+i];
628  sum += a*a+b*b;
629  if(sum/hrss > 0.999 && i/R>0.05) break;
630  }
631  n = i+int(0.05*R);
632  if(n < int(M-1)) i = size_t(n);
633  i = M - ((M-i)/L)*L; // sink with wavelet resolution.
634 
635 // cout<<"M="<<M<<" 2i="<<2*i<<" i/R"<<i/R<<endl;
636 
637  waveForm.cpf(w,2*i,M-i);
638  waveForm.resize(2*i);
639  waveForm.start(sTARt+(M-i)/R);
640 
641  w = waveBand;
642  waveBand.cpf(w,2*i,M-i);
643  waveBand.resize(2*i);
644  waveBand.start(sTARt+(M-i)/R);
645 
646  return rms;
647 }
648 
649 
650 //**************************************************************************
651 // set time delays
652 // time delay convention: t_detector-tau - arrival time at the center of Earth
653 //**************************************************************************
654 void detector::setTau(double sms,double t1,double t2,double p1,double p2)
655 {
656  size_t i;
657  skymap SM(sms,t1,t2,p1,p2);
658  size_t n = SM.size();
659  double x,y,z;
660 
661  for(i=0; i<n; i++) {
662  x = SM.getTheta(i)*PI/180.;
663  y = SM.getPhi(i)*PI/180.;
664  z = Rv[0]*sin(x)*cos(y) + Rv[1]*sin(x)*sin(y) + Rv[2]*cos(x);
665  SM.set(i,-z/speedlight);
666  }
667 
668  tau = SM;
669  return;
670 }
671 
672 
673 //**************************************************************************
674 // set time delays
675 // time delay convention: t_detector-tau - arrival time at the center of Earth
676 //**************************************************************************
677 void detector::setTau(int order)
678 {
679  size_t i;
680  skymap SM(order);
681  size_t n = SM.size();
682  double x,y,z;
683 
684  for(i=0; i<n; i++) {
685  x = SM.getTheta(i)*PI/180.;
686  y = SM.getPhi(i)*PI/180.;
687  z = Rv[0]*sin(x)*cos(y) + Rv[1]*sin(x)*sin(y) + Rv[2]*cos(x);
688  SM.set(i,-z/speedlight);
689  }
690 
691  tau = SM;
692  return;
693 }
694 
695 //**************************************************************************
696 // return detector time delay for specified source location
697 //**************************************************************************
698 double detector::getTau(double theta, double phi)
699 {
700  double x = theta*PI/180.;
701  double y = phi*PI/180.;
702  double z = Rv[0]*sin(x)*cos(y) + Rv[1]*sin(x)*sin(y) + Rv[2]*cos(x);
703  return -z/speedlight;
704 }
705 
706 //**************************************************************************
707 // set antenna patterns
708 //**************************************************************************
709 void detector::setFpFx(double sms,double t1,double t2,double p1,double p2)
710 {
711  size_t i;
712  skymap Sp(sms,t1,t2,p1,p2);
713  skymap Sx(sms,t1,t2,p1,p2);
714  size_t n = Sp.size();
715  double x,y;
716  wavecomplex a;
717 
718  for(i=0; i<n; i++) {
719  x = Sp.getTheta(i);
720  y = Sp.getPhi(i);
721  a = antenna(x,y);
722  Sp.set(i,a.real());
723  Sx.set(i,a.imag());
724  }
725 
726  mFp = Sp;
727  mFx = Sx;
728  return;
729 }
730 
731 //**************************************************************************
732 // set antenna patterns
733 //**************************************************************************
734 void detector::setFpFx(int order)
735 {
736  size_t i;
737  skymap Sp(order);
738  skymap Sx(order);
739  size_t n = Sp.size();
740  double x,y;
741  wavecomplex a;
742 
743  for(i=0; i<n; i++) {
744  x = Sp.getTheta(i);
745  y = Sp.getPhi(i);
746  a = antenna(x,y);
747  Sp.set(i,a.real());
748  Sx.set(i,a.imag());
749  }
750 
751  mFp = Sp;
752  mFx = Sx;
753  return;
754 }
755 
756 //: initialize delay filter
757 // delay index n: 0 1 2 3 4 5 6 ... M-3 M-2 M-1 M
758 // sample delay: 0 -1 -2 -3 -4 -5 -6 3 2 1 0
759 size_t detector::setFilter(size_t K, double phase, size_t upL)
760 {
761  if(TFmap.isWDM()) {
762  cout<<"wseries::setFilter(): not applicable to WDM TFmaps\n";
763  return 0;
764  }
765  size_t i,j,k,n,ii,jj;
766  size_t M = TFmap.maxLayer()+1; // number of wavelet layers
767  size_t L = TFmap.getLevel(); // wavelet decomposition depth
768  size_t m = M*TFmap.pWavelet->m_H; // buffer length
769  size_t N = M*(1<<upL); // number of time delays
770 
771 // K - total length of the delay filter
772  std::vector<delayFilter> F; // delay filter buffer
773  delayFilter v; v.index.resize(K); v.value.resize(K);
774  for(i=0; i<K; i++) v.value[i] = 0.;
775  for(i=0; i<M; i++) F.push_back(v);
776  slice S;
777  size_t s;
778  short inDex;
779  float vaLue;
780  int offst;
781 
782 
783 // set wavelet buffer
784 
785  Wavelet* pW = TFmap.pWavelet->Clone(); // wavelet used to calculate delay filter
786  Meyer<double> wM(1024,1); // up-sample wavelet
787  WSeries<double> w(*pW);
788  WSeries<double> W(wM); // up-sampled wavelet series
789 
790  cout<<"w.pWavelet->m_H "<<w.pWavelet->m_H<<" level "<<w.pWavelet->m_Level<<" ";
791 
792  w.resize(1024);
793  while(int(L)>w.getMaxLevel() || w.size()<m) w.resize(w.size()*2);
794  w.setLevel(L);
795  W.resize(w.size()*N/M);
796  W.setLevel(upL);
797 
798  cout<<"wsize: "<<w.size()<<endl;
799 
800  S = w.getSlice(0);
801  j = M*S.size()/2;
802 
803  double* pb = (double * )malloc(m*sizeof(double));
804  double** pp = (double **)malloc(m*sizeof(double*));
805  for(i=0; i<m; i++) pp[i] = w.data + i + (int(j) - int(m/2));
806  double* p0 = pp[0];
807  double* p;
808  double sum;
809  wavecomplex Z(cos(phase*PI/180.),sin(phase*PI/180.)); // phase shift
810  wavecomplex z;
811 
812  filter.clear();
813  this->nDFS = N; // store number of Delay Filter Samples
814  this->nDFL = M; // store number of Delay Filter Layers
815 
816  for(n=0; n<N; n++) { // loop over delays
817 
818  for(i=0; i<M; i++) { // loop over wavelet layers
819 
820  w = 0.;
821  S = w.getSlice(i);
822  p = w.data+S.start()+j;
823  s = S.start();
824  *p = 1.;
825  w.Inverse();
826 
827 // up-sample
828 
829  W = 0.;
830  W.putLayer(w,0);
831  W.Inverse();
832 
833 // phase shift
834  if(phase != 0.) {
835  W.FFTW(1);
836  for(k=2; k<W.size(); k+=2) {
837  z.set(W.data[k],W.data[k+1]); // complex amplitude
838  z *= Z;
839  W.data[k] = z.real();
840  W.data[k+1] = z.imag();
841  }
842  W.FFTW(-1);
843  }
844 
845 // time shift by integer number of samples
846 
847  W.cpf(W,W.size()-n,n);
848 
849 // down-sample
850 
851  W.Forward(upL);
852  W.getLayer(w,0);
853 
854 // get filter coefficients
855 
856  w.Forward(L);
857  if(n >= N/2) p -= M; // positive shift
858 
859  for(k=0; k<m; k++) {
860  *(pb+k) = *(p0+k); // save data in the buffer
861  *(p0+k) *= *(p0+k); // square
862  }
863 
864  w.waveSort(pp,0,m-1);
865 
866  for(k=m-1; k>=0; k--) {
867  offst = pp[k]-p;
868  if(abs(offst) >32767) continue;
869  inDex = short(offst);
870  vaLue = float(pb[pp[k]-p0]);
871  if(fabs(vaLue)<1.e-4) break;
872  offst += s;
873  offst -= (offst/M)*M;
874  if(offst<0) offst += M; // calculate offset
875  ii = pW->convertO2F(L,offst); // convert offset into frequency index
876 
877  if(offst != pW->getOffset(L,pW->convertF2L(L,ii))) cout<<"setFilter error 1\n";
878  offst -= inDex;
879  offst -= (offst/M)*M;
880  if(offst<0) offst += M; // calculate offset
881  if(offst != int(s)) cout<<"setFilter error 2: "<<offst<<" "<<s<<endl;
882 
883  jj = minDFindex(F[ii])-1; // index of least significant element in F[ii]
884 
885  for(size_t kk=0; kk<K; kk++)
886  if(fabs(F[ii].value[jj])>fabs(F[ii].value[kk])) cout<<"setFilter error 3:\n";
887 
888  if(jj>=K) {cout<<jj<<endl; continue;}
889  if(fabs(F[ii].value[jj]) < fabs(vaLue)){
890  F[ii].value[jj] = vaLue;
891  F[ii].index[jj] = -inDex;
892  }
893  }
894 
895  }
896 
897  for(i=0; i<M; i++) {
898  filter.push_back(F[i]);
899 
900 // if(n==3) {
901 // S = w.getSlice(i);
902 // printf("%3d %3d %1d %7.5f %7.5f %7.5f %7.5f %7.5f %7.5f %7.5f %7.5f %7.5f %7.5f\n",
903 // S.start(),i,n,F[i].value[0],F[i].value[1],F[i].value[2],F[i].value[3],F[i].value[4],
904 // F[i].value[5],F[i].value[6],F[i].value[7],F[i].value[8],F[i].value[9]);
905 // printf("%3d %3d %1d %7d %7d %7d %7d %7d %7d %7d %7d %7d %7d\n",
906 // S.start(),i,n,F[i].index[0],F[i].index[1],F[i].index[2],F[i].index[3],F[i].index[4],
907 // F[i].index[5],F[i].index[6],F[i].index[7],F[i].index[8],F[i].index[9]);
908 // }
909 
910  sum = 0;
911  v = filter[n*M+i];
912  for(k=0; k<K; k++) {
913  sum += F[i].value[k]*F[i].value[k];
914  if(n && F[i].value[k] == 0.) printf("%4d %4d %d4 \n",int(n),int(i),int(k));
915  if(v.value[k] != F[i].value[k] ||
916  v.index[k] != F[i].index[k]) cout<<"setFilter error 4\n";
917  F[i].value[k] = 0.;
918  }
919  if(sum<0.97) printf("%4d %4d %8.5f \n",int(n),int(i),sum);
920 
921  }
922 
923  }
924 
925  delete pW;
926  free(pp);
927  free(pb);
928  return filter.size();
929 }
930 
931 
932 //: initialize delay filter from another detector
933 size_t detector::setFilter(detector &d) {
934  size_t K = d.filter.size();
935  filter.clear();
936  std::vector<delayFilter>().swap(filter);
937  filter.reserve(K);
938 
939  for(size_t k=0; k<K; k++) {
940  filter.push_back(d.filter[k]);
941  }
942  return filter.size();
943 }
944 
945 
946 //: Dumps filters to file *fname in binary format.
947 void detector::writeFilter(const char *fname)
948 {
949  size_t i,j,k;
950  FILE *fp;
951 
952  if ( (fp=fopen(fname, "wb")) == NULL ) {
953  cout << " DumpBinary() error : cannot open file " << fname <<". \n";
954  exit(1);
955  }
956 
957  size_t M = size_t(TFmap.maxLayer()+1); // number of wavelet layers
958  size_t K = size_t(filter[0].index.size()); // delay filter length
959  size_t N = this->nDFS; // number of delays
960  size_t n = K * sizeof(float);
961  size_t m = K * sizeof(short);
962 
965 
966  fwrite(&K, sizeof(size_t), 1, fp); // write filter length
967  fwrite(&M, sizeof(size_t), 1, fp); // number of layers
968  fwrite(&N, sizeof(size_t), 1, fp); // number of delays
969 
970  for(i=0; i<N; i++) { // loop over delays
971  for(j=0; j<M; j++) { // loop over wavelet layers
972  for(k=0; k<K; k++) { // loop over filter coefficients
973  value.data[k] = filter[i*M+j].value[k];
974  index.data[k] = filter[i*M+j].index[k];
975  }
976  fwrite(value.data, n, 1, fp);
977  fwrite(index.data, m, 1, fp);
978  }
979  }
980  fclose(fp);
981 }
982 
983 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
984 //: Read filters from file *fname.
985 //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
986 void detector::readFilter(const char *fname)
987 {
988  size_t i,j,k;
989  FILE *fp;
990 
991  if ( (fp=fopen(fname, "rb")) == NULL ) {
992  cout << " DumpBinary() error : cannot open file " << fname <<". \n";
993  exit(1);
994  }
995 
996  size_t M; // number of wavelet layers
997  size_t K; // delay filter length
998  size_t N; // number of delays
999 
1000  fread(&K, sizeof(size_t), 1, fp); // read filter length
1001  fread(&M, sizeof(size_t), 1, fp); // read number of layers
1002  fread(&N, sizeof(size_t), 1, fp); // read number of delays
1003 
1004  size_t n = K * sizeof(float);
1005  size_t m = K * sizeof(short);
1008  delayFilter v;
1009 
1010  v.value.clear(); v.value.reserve(K);
1011  v.index.clear(); v.index.reserve(K);
1012  this->clearFilter(); filter.reserve(N*M);
1013  this->nDFS = N; // set number of delay samples
1014  this->nDFL = M; // set number of delay layers
1015 
1016  for(k=0; k<K; k++) { // loop over filter coefficients
1017  v.value.push_back(0.);
1018  v.index.push_back(0);
1019  }
1020 
1021  for(i=0; i<N; i++) { // loop over delays
1022  for(j=0; j<M; j++) { // loop over wavelet layers
1023  fread(value.data, n, 1, fp);
1024  fread(index.data, m, 1, fp);
1025  for(k=0; k<K; k++) { // loop over filter coefficients
1026  v.value[k] = value.data[k];
1027  v.index[k] = index.data[k];
1028  }
1029 
1030 // if(i<3){
1031 // printf("%6.5f %6.5f %6.5f %6.5f %6.5f %6.5f %6.5f %6.5f %6.5f %6.5f \n",
1032 // v.value[0],v.value[1],v.value[2],v.value[3],v.value[4],
1033 // v.value[5],v.value[6],v.value[7],v.value[8],v.value[9]);
1034 // printf("%4d %4d %4d %4d %4d %4d %4d %4d %4d %4d \n",
1035 // v.index[0],v.index[1],v.index[2],v.index[3],v.index[4],
1036 // v.index[5],v.index[6],v.index[7],v.index[8],v.index[9]);
1037 // }
1038 
1039  filter.push_back(v);
1040  }
1041  }
1042  fclose(fp);
1043 }
1044 
1045 
1046 //: apply delay filter to input WSeries and put result in TFmap
1048 {
1049  int i,j,jb,je;
1050 
1051  register int k;
1052  register double* p;
1053  register double* q;
1054 
1055  if(TFmap.isWDM()) {
1056  cout<<"wseries::delay(): not applicable to WDM TFmaps\n";
1057  return;
1058  }
1059 
1060  slice S;
1061  delayFilter v = filter[0]; // delay filter
1062 
1063  int M = this->nDFL; // number of wavelet layers
1064  int N = this->nDFS; // number of delay samples per pixel
1065  int K = int(v.index.size()); // delay filter length
1066  int n = int(t*TFmap.wavearray<double>::rate());
1067  int m = n>0 ? (n+N/2-1)/N : (n-N/2)/N; // delay in wavelet pixels
1068  int l = TFmap.pWavelet->m_H/4+2;
1069 
1070  n = n - m*N; // n - delay in samples
1071  if(n <= 0) n = -n; // filter index for negative delays
1072  else n = N-n; // filter index for positive delays
1073 
1074  cout<<"delay="<<t<<" m="<<m<<" n="<<n<<" M="<<M<<" K="<<K<<" N="<<N<<endl;
1075 
1076  int mM = m*M;
1077  double* A = (double*)malloc(K*sizeof(double));
1078  int* I = (int*)malloc(K*sizeof(int));
1079 
1080  for(i=0; i<M; i++) {
1081 
1082  S = w.getSlice(i);
1083  v = filter[n*M+i];
1084  jb = m>0 ? S.start()+(l+m)*M : S.start()+l*M;
1085  je = m<0 ? w.size() +(m-l)*M : w.size() -l*M;
1086 
1087  for(k=0; k<K; k++) { A[k]=double(v.value[k]); I[k]=int(v.index[k]); }
1088 
1089  if(K==16){
1090  for(j=jb; j<je; j+=M) {
1091  p = w.data+j-mM;
1092  TFmap.data[j] = A[0]*p[I[0]] + A[1]*p[I[1]] + A[2]*p[I[2]] + A[3]*p[I[3]]
1093  + A[4]*p[I[4]] + A[5]*p[I[5]] + A[6]*p[I[6]] + A[7]*p[I[7]]
1094  + A[8]*p[I[8]] + A[9]*p[I[9]] + A[10]*p[I[10]] + A[11]*p[I[11]]
1095  + A[12]*p[I[12]] + A[13]*p[I[13]] + A[14]*p[I[14]] + A[15]*p[I[15]];
1096  }
1097  }
1098 
1099  else if(K==32){
1100  for(j=jb; j<je; j+=M) {
1101  p = w.data+j-mM;
1102  TFmap.data[j] = A[0]*p[I[0]] + A[1]*p[I[1]] + A[2]*p[I[2]] + A[3]*p[I[3]]
1103  + A[4]*p[I[4]] + A[5]*p[I[5]] + A[6]*p[I[6]] + A[7]*p[I[7]]
1104  + A[8]*p[I[8]] + A[9]*p[I[9]] + A[10]*p[I[10]] + A[11]*p[I[11]]
1105  + A[12]*p[I[12]] + A[13]*p[I[13]] + A[14]*p[I[14]] + A[15]*p[I[15]]
1106  + A[16]*p[I[16]] + A[17]*p[I[17]] + A[18]*p[I[18]] + A[19]*p[I[19]]
1107  + A[20]*p[I[20]] + A[21]*p[I[21]] + A[22]*p[I[22]] + A[23]*p[I[23]]
1108  + A[24]*p[I[24]] + A[25]*p[I[25]] + A[26]*p[I[26]] + A[27]*p[I[27]]
1109  + A[28]*p[I[28]] + A[29]*p[I[29]] + A[30]*p[I[30]] + A[31]*p[I[31]];
1110  }
1111  }
1112 
1113  else {
1114  for(j=jb; j<je; j+=M) {
1115  p = w.data+j-mM;
1116  q = TFmap.data+j;
1117  k = K; *q = 0.;
1118  while(k-- > 0) { *q += *(A++) * p[*(I++)]; }
1119  A -= K; I -= K;
1120  }
1121  }
1122 
1123  }
1124  free(A);
1125  free(I);
1126 }
1127 
1128 //: return noise variance for selected wavelet layer or pixel
1129 double detector::getNoise(size_t I, int J)
1130 {
1131  if(!nRMS.size()) return 0.;
1132  if(int(I)>TFmap.maxLayer()) return 0.;
1133 
1134  size_t l,j;
1135  double x, g;
1136  size_t N = nRMS.maxLayer()+1; // number of layers in nRMS
1137  size_t M = TFmap.maxLayer()+1; // number of layers in TFmap
1138  size_t n = I*N/M; // layer low index in nRMS
1139  size_t m = (I+1)*(N/M); // layer high index in nRMS
1140  double t = TFmap.start();
1141  double T = nRMS.start();
1142  slice S = TFmap.getSlice(I);
1143  double rATe = TFmap.wrate(); // map rate
1144 
1145  double rESn = nRMS.frequency(1)-nRMS.frequency(0); // noise F resolution
1146 
1147  // printf("%4d %4d %16.3f %16.3f\n",M,N,t,T);
1148 
1149  if(M>N || t>T) {
1150  cout<<"detector::getNoise(): invalid noise rms array nRMS\n";
1151  return 0.;
1152  }
1153 
1154  size_t L = size_t(TFmap.getlow()/rESn+0.1); // low F boundary
1155  size_t H = size_t(TFmap.gethigh()/rESn+0.1); // high F boundary
1156  if(n>=H || m<=L) return 0.; // out of boundaries
1157 
1158  // printf("%4d %4d\n",n,m);
1159 
1160  if(n >= m) {
1161  cout<<"detector::getNoise():: invalid noise rms array nRMS\n";
1162  return 0.;
1163  }
1164 
1165  S = nRMS.getSlice(n);
1166  size_t K = S.size(); // size of noise vector in each layer
1167 
1168  if(!K) return 0.;
1169 
1170  if(J < 0) { // get noise rms for specified layer
1171  wavearray<double> rms(K);
1172  rms = 0.;
1173 
1174  for(l=n; l<m; l++) {
1175  S = nRMS.getSlice(l);
1176  g = (n<L || m>H) ? 1.e10 : 1.; // supress layers below HP cut-off frequency
1177  for(j=0; j<rms.size(); j++) {
1178  x = nRMS.data[S.start()+j*S.stride()]*g;
1179  rms.data[j] += 1./x/x;
1180  }
1181  }
1182 
1183  for(j=0; j<rms.size(); j++) {
1184  rms.data[j] = sqrt((double(m)-double(n))/rms.data[j]);
1185  }
1186 
1187  return rms.mean();
1188  }
1189 
1190  else { // get noise rms for specified pixel
1191 
1192  double RMS = 0;
1193 
1194  t += J/rATe; // pixel GPS time
1195 
1196  int inRMS = int((t-nRMS.start())*nRMS.rate());
1197  int inVAR = nVAR.size() ? int((t-nVAR.start())*nVAR.rate()) : 0;
1198 
1199  if(inRMS < 0) inRMS = 0;
1200  else if(size_t(inRMS)>=K && K) inRMS = K-1;
1201 
1202  if(inVAR <= 0) inVAR = 0;
1203  else if(size_t(inVAR)>=nVAR.size()) inVAR = nVAR.size()-1;
1204 
1205  for(l=n; l<m; l++) { // get noise vector for specified fl-fh
1206  S = nRMS.getSlice(l);
1207  g = (n<L || m>H) ? 1.e10 : 1.; // supress layers below HP cut-off
1208  x = nRMS.data[S.start()+inRMS*S.stride()]*g;
1209  RMS += 1./x/x;
1210  }
1211 
1212  RMS /= double(m)-double(n);
1213  RMS = sqrt(1./RMS);
1214 
1215  if(!nVAR.size() || rESn*n<nVAR.getlow() || rESn*m>nVAR.gethigh()) return RMS;
1216 
1217  return RMS*double(nVAR.data[inVAR]);
1218  }
1219 }
1220 
1221 
1222 //**************************************************************************
1223 // set noise rms in pixel data array in cluster structure
1224 //**************************************************************************
1226 {
1227  size_t i,j,n,m;
1228  size_t M = wc->size();
1229 
1230  if(!M) return false;
1231 
1232  if(!nRMS.size()) return false;
1233 
1234  size_t max_layer = nRMS.maxLayer();
1235  netpixel* p = NULL; // pointer to pixel structure
1236  slice S;
1237 
1238  int k;
1239  int K = nRMS.size()/(max_layer+1); // number of RMS measurements per layer
1240  double To = nRMS.start();
1241  double Ro = nRMS.wrate();
1242  double Fo = nRMS.frequency(0); // central frequency of zero layer
1243  double dF = nRMS.frequency(1)-Fo; // nRMS frequency resolution
1244  double fl = wc->getlow()-0.1;
1245  double fh = wc->gethigh()+0.1;
1246 
1247  double x,f,t,r,F,g;
1248  Fo = Fo==0. ? 0.5 : 0.; // WDM : wavelet frequency correction
1249 
1250  for(i=0; i<M; i++){
1251  p = wc->getPixel(0,i);
1252 
1253  if(p->frequency > max_layer ||
1254  int(p->rate/Ro+0.01) < 1 ||
1255  p->frequency == 0) { // never use zero layer
1256  cout<<"detector::setrms() - illegal pixel from zero level\n";
1257  exit(0);
1258  }
1259 
1260  x = p->frequency-Fo; // fractional frequency index for wavelet and WDM
1261  f = x*p->rate/2.;
1262  n = size_t(f/dF+0.6); // first layer in nRMS
1263  F = (x+1)*p->rate/2.;
1264  m = size_t(F/dF+0.6); // last layer in nRMS
1265  if(m>max_layer) m=max_layer+1;
1266  t = p->getdata('I',I)/p->rate/p->layers; // takes into account time lag
1267  t+= wc->start; // gps time
1268  k = int((t-To)*Ro); // time index in the noise array
1269 
1270  if(k>=K) k -= k ? 1 : 0;
1271  if(k<0 || n>=m || k>=K) {
1272  cout<<"detector::setrms() - invalid input: ";
1273  cout<<k<<" "<<n<<" "<<m<<" "<<f<<" "<<F<<" "<<t<<endl;
1274  cout<<p->frequency<<" "<<p->rate/2.<<" "<<dF<<" "<<fl<<endl;
1275  exit(0);
1276  }
1277 
1278 // get noise rms for specified pixel
1279 
1280  r = 0.;
1281  for(j=n; j<m; j++) {
1282  S = nRMS.getSlice(j);
1283  g = (f<fl || F>fh) ? 1.e10 : 1.; // supress layers below HP cut-off
1284  x = nRMS.data[S.start()+k*S.stride()];
1285  r += 1./x/x;
1286  }
1287 
1288  if(nVAR.size()) { // mitigation of PSD variability added on June 2019
1289  double ff,FF; // does not affect analysis if nVAR is not set
1290  ff = f<nVAR.getlow() ? nVAR.getlow() : f;
1291  if(ff>=nVAR.gethigh()) ff=nVAR.gethigh();
1292  FF = F>nVAR.gethigh() ? nVAR.gethigh() : F;
1293  if(FF<=nVAR.getlow()) FF=nVAR.getlow();
1294  ff = 2*(FF-ff)/p->rate; // band fraction affected by variability
1295  FF = nVAR.get(t,0.5/p->rate); // variability
1296  r *= 1-ff+ff*FF*FF; // corrected RMS
1297  }
1298 
1299  r = (m-n)/r;
1300  if(r <= 0) cout<<"detector:setrms() error!\n";
1301  p->setdata(sqrt(r),'N',I);
1302 
1303  }
1304  return true;
1305 }
1306 
1307 //**************************************************************************
1308 // apply band pass filter with cut-offs specified by parameters (used by 1G)
1309 //**************************************************************************
1310 void detector::bandPass1G(double f1, double f2)
1311 {
1312  int i;
1313  double dF = TFmap.frequency(1)-TFmap.frequency(0); // frequency resolution
1314  double fl = fabs(f1)>0. ? fabs(f1) : this->TFmap.getlow();
1315  double fh = fabs(f2)>0. ? fabs(f2) : this->TFmap.gethigh();
1316  size_t n = TFmap.pWavelet->m_WaveType==WDMT ? size_t((fl+dF/2.)/dF+0.1) : size_t(fl/dF+0.1);
1317  size_t m = TFmap.pWavelet->m_WaveType==WDMT ? size_t((fh+dF/2.)/dF+0.1)-1 : size_t(fh/dF+0.1)-1;
1318  size_t M = this->TFmap.maxLayer()+1;
1320 
1321  if(n>m) return;
1322 
1323  for(i=0; i<int(M); i++) { // ......f1......f2......
1324 
1325  if((f1>=0 && i>=n) && (f2>=0 && i<=m)) continue; // zzzzzz..........zzzzzz band pass
1326  if((f1<0 && i<n) || (f2<0 && i>m)) continue; // ......zzzzzzzzzz...... band cut
1327  if((f1<0 && f2>=0 && i<n)) continue; // ......zzzzzzzzzzzzzzzz low pass
1328  if((f1>=0 && f2<0 && i>=m)) continue; // zzzzzzzzzzzzzzzz...... high pass
1329 
1330  this->TFmap.getLayer(w,i+0.01); w=0.; this->TFmap.putLayer(w,i+0.01);
1331  this->TFmap.getLayer(w,-i-0.01); w=0.; this->TFmap.putLayer(w,-i-0.01);
1332  }
1333  return;
1334 }
1335 
1336 //**************************************************************************
1337 // apply band pass filter with cut-offs specified by parameters
1338 //**************************************************************************
1339 /*
1340 void detector::bandPass(double f1, double f2, double a)
1341 {
1342 // assign constant value a to wseries layer coefficients
1343 // 0utside of the band defined by frequencies f1 and f2
1344 // f1>0, f2>0 - zzzzzz..........zzzzzz band pass
1345 // f1<0, f2<0 - ......zzzzzzzzzz...... band cut
1346 // f1<0, f2>0 - ......zzzzzzzzzzzzzzzz low pass
1347 // f1>0, f2<0 - zzzzzzzzzzzzzzzz...... high pass
1348  int i;
1349  double dF = TFmap.frequency(1)-TFmap.frequency(0); // frequency resolution
1350  double fl = fabs(f1)>0. ? fabs(f1) : this->TFmap.getlow();
1351  double fh = fabs(f2)>0. ? fabs(f2) : this->TFmap.gethigh();
1352  size_t n = TFmap.pWavelet->m_WaveType==WDMT ? size_t((fl+dF/2.)/dF+0.1) : size_t(fl/dF+0.1);
1353  size_t m = TFmap.pWavelet->m_WaveType==WDMT ? size_t((fh+dF/2.)/dF+0.1)-1 : size_t(fh/dF+0.1)-1;
1354  size_t M = this->TFmap.maxLayer()+1;
1355  wavearray<double> w;
1356 
1357  if(n>m) return;
1358 
1359  for(i=0; i<int(M); i++) { // ......f1......f2......
1360 
1361  if((f1>=0 && i>=n) && (f2>=0 && i<=m)) continue; // zzzzzz..........zzzzzz band pass
1362  if((f1<0 && i<n) || (f2<0 && i>m)) continue; // ......zzzzzzzzzz...... band cut
1363  if((f1<0 && f2>=0 && i<n)) continue; // ......zzzzzzzzzzzzzzzz low pass
1364  if((f1>=0 && f2<0 && i>=m)) continue; // zzzzzzzzzzzzzzzz...... high pass
1365 
1366  this->TFmap.getLayer(w,i+0.01); w=a; this->TFmap.putLayer(w,i+0.01);
1367  this->TFmap.getLayer(w,-i-0.01); w=a; this->TFmap.putLayer(w,-i-0.01);
1368  }
1369  return;
1370 }
1371 */
1372 //**************************************************************************
1373 // calculate hrss of injected responses
1374 // returns number of eligible injections
1375 // update MDC series with whitened time series
1376 //**************************************************************************
1377 size_t detector::setsim(WSeries<double> &wi, std::vector<double>* pT, double dT, double offset, bool saveWF)
1378 {
1379  int j,nstop,nstrt,n,m,J;
1380  size_t i,k;
1381  double a,b,T,E,D,H,f;
1382  double R = this->rate; // original data rate
1383  size_t K = pT->size();
1384  size_t I = wi.maxLayer()+1;
1385  size_t M = 0;
1386  bool pOUT = dT>0. ? false : true; // printout flag
1387 
1388  dT = fabs(dT);
1389 
1390  if(wi.size() != TFmap.size()) {
1391  cout<<"setsim(): mismatch between MDC size "
1392  <<wi.size()<<" and data size "<<TFmap.size()<<"\n";
1393  exit(1);
1394  }
1395 
1396  if(!K) return K;
1397  if(!this->nRMS.size() || !this->TFmap.size()) return 0;
1398 
1399  if(this->HRSS.size() != K) {
1400  this->HRSS.resize(K);
1401  this->ISNR.resize(K);
1402  this->FREQ.resize(K);
1403  this->BAND.resize(K);
1404  this->TIME.resize(K);
1405  this->TDUR.resize(K);
1406  }
1407  this->HRSS = 0.;
1408  this->ISNR = 0.;
1409  this->FREQ = 0.;
1410  this->BAND = 0.;
1411  this->TIME = 0.;
1412  this->TDUR = 0.;
1413 
1414  WSeries<double> W; W=wi;
1416  WSeries<double> hot; hot=wi; hot.Inverse();
1418  std::slice S;
1419 
1420 // whiten injection if noise array is filled in
1421 
1422  if(W.pWavelet->m_WaveType==WDMT) { // WDM type
1423  if(!W.white(this->nRMS,1)) { // whiten 0 phase WSeries
1424  cout<<"detector::setsim error: invalid noise array\n"; exit(1);
1425  }
1426  if(!W.white(this->nRMS,-1)) { // whiten 90 phase WSeries
1427  cout<<"detector::setsim error: invalid noise array\n"; exit(1);
1428  }
1429  w = W; // whitened WS
1430  WSeries<double> wtmp = w;
1431  w.Inverse();
1432  wtmp.Inverse(-2);
1433  w += wtmp;
1434  w *= 0.5;
1435  } else { // wavelet type
1436  if(!W.white(this->nRMS)) {
1437  cout<<"detector::setsim error: invalid noise array\n"; exit(1);
1438  }
1439  w = W; // whitened WS
1440  w.Inverse(); // whitened TS
1441  }
1442 
1443 
1444 // isolate injections in time series w
1445 
1446  size_t N = w.size(); // MDC size
1447  double rate = w.wavearray<double>::rate(); // simulation rate
1448  double bgps = w.start()+offset+1.; // analysed start time
1449  double sgps = w.start()-offset+N/rate-1.; // analysed stop time
1450 
1451  for(k=0; k<K; k++) {
1452 
1453  T = (*pT)[k] - w.start();
1454 
1455  nstrt = int((T - dT)*rate);
1456  nstop = int((T + dT)*rate);
1457  if(nstrt<=0) nstrt = 0;
1458  if(nstop>=int(N)) nstop = N;
1459  if(nstop<=0) continue; // outside of the segment
1460  if(nstrt>=int(N)) continue; // outside of the segment
1461 
1462  E = T = 0.;
1463  for(j=nstrt; j<nstop; j++) {
1464  a = w.data[j];
1465  T += a*a*j/rate; // central time
1466  E += a*a; // SNR
1467  }
1468  T /= E; // central time for k-th injection
1469 
1470 // zoom in
1471 
1472  nstrt = int((T - dT)*rate);
1473  nstop = int((T + dT)*rate);
1474  if(nstrt<=0) nstrt = 0;
1475  if(nstop>=int(N)) nstop = N;
1476  if(nstop<=0) continue; // outside of the segment
1477  if(nstrt>=int(N)) continue; // outside of the segment
1478 
1479  E = T = D = H = 0.;
1480  for(j=nstrt; j<nstop; j++) {
1481  a = w.data[j];
1482  T += a*a*j/rate; // central time
1483  E += a*a; // SNR
1484  }
1485  T /= E;
1486 
1487  m = int((T - dT)*W.wrate());
1488  n = int((T + dT)*W.wrate());
1489  S = W.getSlice(0); // zero layer
1490  if(m<=0) m = 0; // check left
1491  if(n>=int(S.size())) n = S.size()-1; // check right
1492 
1493  for(j=nstrt; j<nstop; j++) {
1494  a = w.data[j]*(j/rate-T);
1495  D += a*a; // duration
1496  a = hot.data[j];
1497  H += a*a; // hrss
1498  }
1499 
1500  D = sqrt(D/E);
1501  H = sqrt(H/R);
1502  T += w.start();
1503  if(T<bgps || T>sgps) continue; // outside of the segment
1504 
1505  this->ISNR.data[k] = E;
1506  this->TIME.data[k] = T;
1507  this->TDUR.data[k] = D;
1508  this->HRSS.data[k] = H;
1509 
1510  E = 0.;
1511  for(i=0; i<I; i++) {
1512  S = W.getSlice(i+0.001);
1513  J = S.stride();
1514  a = W.rms(slice(S.start()+m*J,n-m,J)); // get rms
1515  f = W.frequency(i); // layer frequency
1516  this->FREQ.data[k] += f*a*a; // central frequency
1517  this->BAND.data[k] += f*f*a*a; // bandwidth
1518  E += a*a;
1519  }
1520 
1521  this->FREQ.data[k] /= E;
1522  a = this->FREQ.data[k];
1523  b = this->BAND.data[k]/E - a*a;
1524  this->BAND.data[k] = b>0. ? sqrt(b) : 0.;
1525 
1526 // save waveform
1527 
1528  double time = this->TIME.data[k];
1529  double tdur = this->TDUR.data[k];
1530  double tDur = 6*tdur;
1531  if (tDur > dT) tDur = dT;
1532  int nStrt = int((time-tDur-w.start())*rate);
1533  int nStop = int((time+tDur-w.start())*rate);
1534  if(nStrt<0) nStrt = 0;
1535  if(nStop>int(N)) nStop = N;
1536 
1537 // window the injected waveforms
1538 
1539  size_t I = int(2.*dT*rate);
1540  int OS = int((time - dT - w.start())*rate);
1541  double ms = 0;
1542 
1543  for (j=0;j<I;j++) ms += ((OS+j>=0)&&(OS+j<N)) ? w.data[OS+j]*w.data[OS+j] : 0.;
1544 
1545  OS += I/2;
1546  double a,b;
1547  double sum = ((OS>=0)&&(OS<N)) ? w.data[OS]*w.data[OS] : 0.;
1548  for(j=1; j<int(I/2); j++) {
1549  a = ((OS-j>=0)&&(OS-j<N)) ? w.data[OS-j] : 0.;
1550  b = ((OS+j>=0)&&(OS+j<N)) ? w.data[OS+j] : 0.;
1551  sum += a*a+b*b;
1552  if(sum/ms > 0.999) break;
1553  }
1554 
1555  nStrt = int((time-w.start())*rate)-j;
1556  nStop = int((time-w.start())*rate)+j;
1557  if(nStrt<0) nStrt = 0;
1558  if(nStop>int(N)) nStop = N;
1559 
1561  wf->rate(rate);
1562  wf->start(w.start()+nStrt/rate);
1563  wf->resize(nStop-nStrt);
1564  for(j=nStrt; j<nStop; j++) {
1565  wf->data[j-nStrt] = w.data[j];
1566  }
1567 
1568 // apply freq cuts
1569 
1570  double f_low = this->TFmap.getlow();
1571  double f_high = this->TFmap.gethigh();
1572  //cout << "f_low : " << f_low << " f_high : " << f_high << endl;
1573  wf->FFTW(1);
1574  double Fs=((double)wf->rate()/(double)wf->size())/2.;
1575  for (j=0;j<wf->size()/2;j+=2) {
1576  double f=j*Fs;
1577  if((f<f_low)||(f>f_high)) {wf->data[j]=0.;wf->data[j+1]=0.;}
1578  }
1579  wf->FFTW(-1);
1580 
1581 // compute SNR,TIME,DUR within the search frequency band
1582 
1583  E = T = D = 0.;
1584  for(j=0;j<wf->size();j++) {
1585  a = wf->data[j];
1586  T += a*a*j/rate; // central time
1587  E += a*a; // SNR
1588  }
1589  T /= E;
1590 
1591  for(j=0;j<wf->size();j++) {
1592  a = wf->data[j]*(j/rate-T);
1593  D += a*a; // duration
1594  }
1595 
1596  D = sqrt(D/E);
1597  T += wf->start();
1598 
1599  this->ISNR.data[k] = E;
1600  this->TIME.data[k] = T;
1601  this->TDUR.data[k] = D;
1602 
1603  if (saveWF) {
1604  wf->resetFFTW();
1605  IWFID.push_back(k);
1606  IWFP.push_back(wf);
1607  } else {
1608  delete wf;
1609  }
1610 
1611  // save strain waveform
1612  if (saveWF) {
1613 
1614  // compute central time
1615  T = E = 0.;
1616  for(j=nstrt; j<nstop; j++) {
1617  a = hot.data[j];
1618  T += a*a*j/rate; // central time
1619  E += a*a; // energy
1620  }
1621  T /= E;
1622 
1623  // compute the time range containing the 0.999 of the total energy
1624  I = int(2.*dT*rate);
1625  OS = int((T - dT)*rate);
1626  ms = 0;
1627 
1628  for (j=0;j<I;j++) ms += ((OS+j>=0)&&(OS+j<N)) ? hot.data[OS+j]*hot.data[OS+j] : 0.;
1629 
1630  OS += I/2;
1631  sum = ((OS>=0)&&(OS<N)) ? hot.data[OS]*hot.data[OS] : 0.;
1632  for(j=1; j<int(I/2); j++) {
1633  a = ((OS-j>=0)&&(OS-j<N)) ? hot.data[OS-j] : 0.;
1634  b = ((OS+j>=0)&&(OS+j<N)) ? hot.data[OS+j] : 0.;
1635  sum += a*a+b*b;
1636  if(sum/ms > 0.999) break;
1637  }
1638 
1639  nStrt = int(T*rate)-j;
1640  nStop = int(T*rate)+j;
1641  if(nStrt<0) nStrt = 0;
1642  if(nStop>int(N)) nStop = N;
1643 
1644  // select strain mdc data
1646  WF->rate(rate);
1647  WF->start(hot.start()+nStrt/rate);
1648  WF->resize(nStop-nStrt);
1649  for(j=nStrt; j<nStop; j++) WF->data[j-nStrt] = hot.data[j];
1650 
1651  // store strain data (use ID=-(k+1))
1652  IWFID.push_back(-(k+1));
1653  IWFP.push_back(WF);
1654  }
1655 
1656  if(pOUT)
1657  printf("%3d T+-dT: %8.3f +-%5.3f, F+-dF: %4.0f +-%4.0f, SNR: %6.1e, hrss: %6.1e\n",
1658  int(M), T-bgps, D, FREQ.data[k], BAND.data[k], E, H);
1659 
1660 // (*pT)[k] = T;
1661  M++;
1662  }
1663  wi = w;
1664  return M;
1665 }
1666 
1667 //**************************************************************************
1668 // modify input signals (wi) at times pT according the factor pF
1669 //**************************************************************************
1670 size_t detector::setsnr(wavearray<double> &wi, std::vector<double>* pT, std::vector<double>* pF, double dT, double offset)
1671 {
1672  int j,nstop,nstrt;
1673  size_t k;
1674  double F,T;
1675  size_t K = pT->size();
1676  size_t N = wi.size();
1677  size_t M = 0;
1678  double rate = wi.rate(); // simulation rate
1679 
1680  dT = fabs(dT);
1681 
1682  wavearray<double> w; w=wi;
1683 // isolate injections
1684 
1685  for(k=0; k<K; k++) {
1686 
1687  F = (*pF)[k];
1688  T = (*pT)[k] - w.start();
1689 
1690  nstrt = int((T - dT)*rate);
1691  nstop = int((T + dT)*rate);
1692  if(nstrt<=0) nstrt = 0;
1693  if(nstop>=int(N)) nstop = N;
1694  if(nstop<=0) continue; // outside of the segment
1695  if(nstrt>=int(N)) continue; // outside of the segment
1696 
1697  for(j=nstrt; j<nstop; j++) {
1698  w.data[j]*=F;
1699  }
1700 
1701  M++;
1702  }
1703  wi = w;
1704  return M;
1705 }
1706 
1707 
1708 //**************************************************************************
1709 // apply sample shift to time series in TFmap
1710 //**************************************************************************
1711 void detector::delay(double theta, double phi)
1712 {
1713  if(!TFmap.size()) return;
1714  double R = this->TFmap.wavearray<double>::rate();
1715  double T = this->getTau(theta,phi); // time delay: +/- increase/decrease gps
1716  size_t n = size_t(fabs(T)*R); // shift in samples
1717  size_t m = this->TFmap.size();
1719  w = this->TFmap;
1720  TFmap = 0.;
1721 
1722  if(T<0) TFmap.cpf(w,m-n,0,n); // shift forward
1723  else TFmap.cpf(w,m-n,n,0); // shift backward
1724  return;
1725 }
1726 
1727 //**************************************************************************
1728 // apply sample shift to input time series
1729 //**************************************************************************
1731 {
1732  if(!x.size()) return;
1733  double R = x.rate();
1734  double T = this->getTau(theta,phi); // time delay: +/- increase/decrease gps
1735  size_t n = size_t(fabs(T)*R); // shift in samples
1736  size_t m = x.size();
1738  w = x;
1739  x = 0.;
1740 
1741  if(T<0) x.cpf(w,m-n,0,n); // shift forward
1742  else x.cpf(w,m-n,n,0); // shift backward
1743  return;
1744 }
1745 
1746 //**************************************************************************
1747 // apply time shift T to input time series
1748 //**************************************************************************
1750 {
1751  if(!x.size()) return;
1752  double R = x.rate();
1753  size_t n = size_t(fabs(T)*R+0.5); // shift in samples
1754  size_t m = x.size();
1756  w = x;
1757  x = 0.;
1758 
1759  if(T<0) x.cpf(w,m-n,0,n); // shift forward
1760  else x.cpf(w,m-n,n,0); // shift backward
1761  return;
1762 }
1763 
1764 double detector::getWFtime(char atype)
1765 {
1766 // returns central time of reconstructed waveform
1767  double e;
1768  double T = 0.;
1769  double E = 0.;
1770  WSeries<double>* wf = atype=='S' ? &this->waveForm : &this->waveBand;
1771  for(size_t i=0; i<wf->size(); i++) {
1772  e = wf->data[i]*wf->data[i];
1773  T += e*i;
1774  E += e;
1775  }
1776  return E>0. ? wf->start()+T/E/wf->rate() : 0.;
1777 }
1778 
1779 double detector::getWFfreq(char atype)
1780 {
1781 // returns central frequency of reconstructed waveform
1782  double e;
1783  double F = 0.;
1784  double E = 0.;
1785  WSeries<double>* wf = atype=='S' ? &this->waveForm : &this->waveBand;
1786  wf->FFTW(1);
1787  for(size_t i=0; i<wf->size(); i+=2) {
1788  e = wf->data[i]*wf->data[i];
1789  e += wf->data[i+1]*wf->data[i+1];
1790  F += e*i;
1791  E += e;
1792  }
1793  return E>0. ? 0.5*F*wf->rate()/E/wf->size() : 0.;
1794 }
1795 
1796 //______________________________________________________________________________
1798 {
1799  detectorParams xdP = getDetectorParams();
1800 
1801  char LAT;
1802  double theta_t=xdP.latitude;
1803  if(theta_t>0) LAT='N'; else {LAT='S';theta_t=-theta_t;}
1804  int theta_d = int(theta_t);
1805  int theta_m = int((theta_t-theta_d)*60);
1806  float theta_s = (theta_t-theta_d-theta_m/60.)*3600.;
1807 
1808  char LON;
1809  double phi_t=xdP.longitude;
1810  if(phi_t>0) LON='E'; else {LON='W';phi_t=-phi_t;}
1811  int phi_d = int(phi_t);
1812  int phi_m = int((phi_t-phi_d)*60);
1813  float phi_s = (phi_t-phi_d-phi_m/60.)*3600.;
1814 
1815  cout << endl;
1816  cout << "----------------------------------------------" << endl;
1817  cout << "IFO : " << xdP.name << " (Geographic Coordinates) " << endl;
1818  cout << "----------------------------------------------" << endl;
1819  cout << endl;
1820  cout << "latitude : " << xdP.latitude << " longitude : " << xdP.longitude << endl;
1821  cout << endl;
1822  cout << "LAT : " << LAT << " " << theta_d << ", " << theta_m << ", " << theta_s << endl;
1823  cout << "LON : " << LON << " " << phi_d << ", " << phi_m << ", " << phi_s << endl;
1824  cout << endl;
1825  int precision=cout.precision(12);
1826  // radius vector to beam splitter
1827  cout << "Rv : " << Rv[0] << " " << Rv[1] << " " << Rv[2] << " " << endl;
1828  // vector along x-arm
1829  cout << "Ex : " << Ex[0] << " " << Ex[1] << " " << Ex[2] << " " << endl;
1830  // vector along y-arm
1831  cout << "Ey : " << Ey[0] << " " << Ey[1] << " " << Ey[2] << " " << endl;
1832  cout << endl;
1833  cout.precision(precision);
1834  cout << "Ex-North Angle Clockwise (deg) : " << xdP.AzX << endl;
1835  cout << "Ey-North Angle Clockwise (deg) : " << xdP.AzY << endl;
1836  cout << endl;
1837  if(polarization==TENSOR) cout << "GW Polarization = TENSOR" << endl;
1838  if(polarization==SCALAR) cout << "GW Polarization = SCALAR" << endl;
1839  cout << endl;
1840 
1841  return;
1842 }
1843 
1844 //______________________________________________________________________________
1845 void detector::Streamer(TBuffer &R__b)
1846 {
1847  // Stream an object of class detector.
1848 
1849  UInt_t R__s, R__c;
1850  if (R__b.IsReading()) {
1851  Version_t R__v = R__b.ReadVersion(&R__s, &R__c); if (R__v) { }
1852  TNamed::Streamer(R__b);
1853  R__b.ReadStaticArray((char*)Name);
1854  R__b.StreamObject(&(dP),typeid(detectorParams));
1855  R__b.ReadStaticArray((double*)Rv);
1856  R__b.ReadStaticArray((double*)Ex);
1857  R__b.ReadStaticArray((double*)Ey);
1858  R__b.ReadStaticArray((double*)DT);
1859  R__b.ReadStaticArray((double*)ED);
1860  if(R__v > 2) R__b >> ifoID;
1861  R__b >> sHIFt;
1862  if(R__v > 1) {
1863  void *ptr_polarization = (void*)&polarization;
1864  R__b >> *reinterpret_cast<Int_t*>(ptr_polarization);
1865  }
1866 
1867  if(R__v > 3) {
1868  R__b >> wfSAVE;
1869  if(wfSAVE) {
1870  HRSS.Streamer(R__b);
1871  ISNR.Streamer(R__b);
1872  FREQ.Streamer(R__b);
1873  BAND.Streamer(R__b);
1874  TIME.Streamer(R__b);
1875  TDUR.Streamer(R__b);
1876  if(wfSAVE==1||wfSAVE==3) {
1877  {
1878  vector<int> &R__stl = IWFID;
1879  R__stl.clear();
1880  int R__i, R__n;
1881  R__b >> R__n;
1882  R__stl.reserve(R__n);
1883  for (R__i = 0; R__i < R__n; R__i++) {
1884  int R__t;
1885  R__b >> R__t;
1886  R__stl.push_back(R__t);
1887  }
1888  }
1889  {
1890  vector<wavearray<double>*> &R__stl = IWFP;
1891  R__stl.clear();
1892  int R__i, R__n;
1893  R__b >> R__n;
1894  R__stl.reserve(R__n);
1895  for (R__i = 0; R__i < R__n; R__i++) {
1897  R__t->Streamer(R__b);
1898  R__stl.push_back(R__t);
1899  }
1900  }
1901  }
1902  if(wfSAVE==2||wfSAVE==3) {
1903  {
1904  vector<int> &R__stl = RWFID;
1905  R__stl.clear();
1906  int R__i, R__n;
1907  R__b >> R__n;
1908  R__stl.reserve(R__n);
1909  for (R__i = 0; R__i < R__n; R__i++) {
1910  int R__t;
1911  R__b >> R__t;
1912  R__stl.push_back(R__t);
1913  }
1914  }
1915  {
1916  vector<wavearray<double>*> &R__stl = RWFP;
1917  R__stl.clear();
1918  int R__i, R__n;
1919  R__b >> R__n;
1920  R__stl.reserve(R__n);
1921  for (R__i = 0; R__i < R__n; R__i++) {
1923  R__t->Streamer(R__b);
1924  R__stl.push_back(R__t);
1925  }
1926  }
1927  }
1928  }
1929  }
1930 
1931  R__b.CheckByteCount(R__s, R__c, detector::IsA());
1932  } else {
1933  R__c = R__b.WriteVersion(detector::IsA(), kTRUE);
1934  TNamed::Streamer(R__b);
1935  R__b.WriteArray(Name, 16);
1936  R__b.StreamObject(&(dP),typeid(detectorParams));
1937  R__b.WriteArray(Rv, 3);
1938  R__b.WriteArray(Ex, 3);
1939  R__b.WriteArray(Ey, 3);
1940  R__b.WriteArray(DT, 9);
1941  R__b.WriteArray(ED, 5);
1942  R__b << ifoID;
1943  R__b << sHIFt;
1944  R__b << (Int_t)polarization;
1945 
1946  R__b << wfSAVE;
1947  if(wfSAVE) {
1948  HRSS.Streamer(R__b);
1949  ISNR.Streamer(R__b);
1950  FREQ.Streamer(R__b);
1951  BAND.Streamer(R__b);
1952  TIME.Streamer(R__b);
1953  TDUR.Streamer(R__b);
1954  if(wfSAVE==1||wfSAVE==3) {
1955  {
1956  vector<int> &R__stl = IWFID;
1957  int R__n=(&R__stl) ? int(R__stl.size()) : 0;
1958  R__b << R__n;
1959  if(R__n) {
1960  vector<int>::iterator R__k;
1961  for (R__k = R__stl.begin(); R__k != R__stl.end(); ++R__k) {
1962  R__b << (*R__k);
1963  }
1964  }
1965  }
1966  {
1967  vector<wavearray<double> > IWF(IWFP.size());
1968  for(int i=0;i<IWFP.size();i++) IWF[i] = *IWFP[i];
1969  vector<wavearray<double> > &R__stl = IWF;
1970  int R__n=(&R__stl) ? int(R__stl.size()) : 0;
1971  R__b << R__n;
1972  if(R__n) {
1973  vector<wavearray<double> >::iterator R__k;
1974  for (R__k = R__stl.begin(); R__k != R__stl.end(); ++R__k) {
1975  ((wavearray<double>&)(*R__k)).Streamer(R__b);
1976  }
1977  }
1978  }
1979  }
1980  if(wfSAVE==2||wfSAVE==3) {
1981  {
1982  vector<int> &R__stl = RWFID;
1983  int R__n=(&R__stl) ? int(R__stl.size()) : 0;
1984  R__b << R__n;
1985  if(R__n) {
1986  vector<int>::iterator R__k;
1987  for (R__k = R__stl.begin(); R__k != R__stl.end(); ++R__k) {
1988  R__b << (*R__k);
1989  }
1990  }
1991  }
1992  {
1993  vector<wavearray<double> > RWF(RWFP.size());
1994  for(int i=0;i<RWFP.size();i++) RWF[i] = *RWFP[i];
1995  vector<wavearray<double> > &R__stl = RWF;
1996  int R__n=(&R__stl) ? int(R__stl.size()) : 0;
1997  R__b << R__n;
1998  if(R__n) {
1999  vector<wavearray<double> >::iterator R__k;
2000  for (R__k = R__stl.begin(); R__k != R__stl.end(); ++R__k) {
2001  ((wavearray<double>&)(*R__k)).Streamer(R__b);
2002  }
2003  }
2004  }
2005  }
2006  }
2007 
2008  R__b.SetByteCount(R__c, kTRUE);
2009  }
2010 }
2011 
wavearray< double > t(hp.size())
detectorParams dP
Definition: detector.hh:329
const double _eT1x[3]
const double _eH1x[3]
void writeFilter(const char *)
param: file name
Definition: detector.cc:947
double sHIFt
Definition: detector.hh:335
const double _rE1[3]
detectorParams getDetectorParams()
Definition: detector.cc:218
virtual void resize(unsigned int)
Definition: wseries.cc:901
double sTARt
int wfSAVE
Definition: detector.hh:344
double getWFfreq(char atype='S')
Definition: detector.cc:1779
const double _eA1y[3]
static double g(double e)
Definition: GNGen.cc:116
TH1 * t1
double M
Definition: DrawEBHH.C:13
par [0] value
const double _eL1x[3]
int getMaxLevel()
Definition: wseries.cc:103
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
size_t setsnr(wavearray< double > &, std::vector< double > *, std::vector< double > *, double=5., double=8.)
Definition: detector.cc:1670
int offset
Definition: TestSTFT_2.C:19
virtual void rate(double r)
Definition: wavearray.hh:141
char name[32]
Definition: detector.hh:50
plot hist2D SetName("WSeries-1")
wavearray< double > a(hp.size())
size_t frequency
Definition: netpixel.hh:111
double Ey[3]
Definition: detector.hh:332
double AzX
Definition: detector.hh:55
WSeries< float > v[nIFO]
Definition: cwb_net.C:80
double getWFtime(char atype='S')
Definition: detector.cc:1764
par [0] name
int n
Definition: cwb_net.C:28
const double _eE1x[3]
wavearray< double > z
Definition: Test10.C:32
const double _eK1y[3]
double imag() const
Definition: wavecomplex.hh:70
int ID
Definition: TestMDC.C:70
const double _rK1[3]
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
double phase
std::vector< delayFilter > filter
Definition: detector.hh:361
wavearray< double > HRSS
Definition: detector.hh:371
float theta
double getlow()
Definition: netcluster.hh:347
STL namespace.
double getTheta(size_t i)
Definition: skymap.hh:224
std::slice getSlice(double n)
Definition: wseries.hh:152
const double _rT1[3]
size_t setFilter(size_t, double=0., size_t=0)
param: filter length param: filter phase delay in degrees param: number of up-sample layers return fi...
Definition: detector.cc:759
virtual Wavelet * Clone() const
return: Wavelet* - duplicate of *this, allocated on heap
Definition: Wavelet.cc:60
double AltX
Definition: detector.hh:54
double AzY
Definition: detector.hh:57
waveform wf
int polarization
bool setrms(netcluster *, size_t=0)
Definition: detector.cc:1225
const double _rH1[3]
size_t layers
Definition: netpixel.hh:112
int m
Definition: cwb_net.C:28
virtual void start(double s)
Definition: wavearray.hh:137
int j
Definition: cwb_net.C:28
size_t minDFindex(delayFilter &F)
Definition: detector.hh:400
void delay(double, double)
param: theta param: phi
Definition: detector.cc:1711
i drho i
double longitude
Definition: detector.hh:52
skymap tau
Definition: detector.hh:346
#define N
cout<< "SNR "<< xsnr<< endl;wavearray< double > f
Definition: ComputeSNR.C:75
void init()
param: Rx,Ry,Rz in ECEF frame
Definition: detector.cc:468
double getNoise(size_t, int=-1)
param: wavelet layer index (frequency) param: wavelet time index if param 2 is specified - return noi...
Definition: detector.cc:1129
#define PI
Definition: watfun.hh:32
const double _rN1[3]
skymap mFx
Definition: detector.hh:348
const double _eO1x[3]
watplot p2(const_cast< char *>("TFMap2"))
virtual double rms()
Definition: wavearray.cc:1206
wavearray< double > w
Definition: Test1.C:27
void wrate(double r)
Definition: wseries.hh:120
virtual size_t size() const
Definition: wavearray.hh:145
void readFilter(const char *)
Definition: detector.cc:986
float phi
const double _eN1y[3]
const double _eV1y[3]
wavecomplex antenna(double, double, double=0.)
param: source theta,phi, polarization angle psi in degrees
Definition: detector.cc:490
double hrss
Definition: TestMDC.C:70
float psi
size_t size() const
Definition: wslice.hh:89
void set(double x, double y)
Definition: wavecomplex.hh:74
const double _eE1y[3]
detector & operator=(const detector &)
Definition: detector.cc:368
void bandPass1G(double f1=0., double f2=0.)
Definition: detector.cc:1310
size_t start() const
Definition: wslice.hh:85
const double _eT1y[3]
double real() const
Definition: wavecomplex.hh:69
wavearray< double > hot[2]
double deg2rad
double getwave(int, WSeries< double > &, char='W', size_t=0)
param: cluster ID param: WSeries where to put the waveform return: noise rms
Definition: netcluster.cc:2762
WSeries< double > nRMS
Definition: detector.hh:358
TF1 * f2
const double _rG1[3]
const double _rL1[3]
static const double SM
Definition: GNGen.cc:26
wavearray< double > TIME
Definition: detector.hh:375
void GeocentricToGeodetic(double X, double Y, double Z, double &latitude, double &longitude, double &elevation)
Definition: skycoord.hh:307
i() int(T_cor *100))
size_t stride() const
Definition: wslice.hh:93
double Pi
watplot p1(const_cast< char *>("TFMap1"))
virtual int convertF2L(int, int)
Definition: Wavelet.cc:93
const double _eG1x[3]
double D[50000]
const double _eO1y[3]
double start
Definition: netcluster.hh:379
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
double elevation
Definition: detector.hh:53
static double tau
Definition: geodesics.cc:26
const double _rV1[3]
char fname[1024]
POLARIZATION polarization
Definition: detector.hh:384
Definition: Wavelet.hh:49
const double _eH2x[3]
double precision
#define speedlight
Definition: watfun.hh:33
detector & operator>>(detector &)
Definition: detector.cc:438
int k
const double _eK1x[3]
virtual void resetFFTW()
Definition: wavearray.cc:977
const double _eN1x[3]
std::vector< wavearray< double > * > IWFP
Definition: detector.hh:379
detector()
Definition: detector.cc:108
const double _rO1[3]
static double A
Definition: geodesics.cc:26
virtual int convertO2F(int, int)
Definition: Wavelet.cc:105
int m_Level
Definition: Wavelet.hh:115
double F
Definition: skymap.hh:63
double latitude
Definition: detector.hh:51
wavearray< double > TDUR
Definition: detector.hh:376
std::vector< int > IWFID
Definition: detector.hh:378
double e
void setLevel(size_t n)
Definition: wseries.hh:112
WSeries< double > wM
Definition: cwb_job_obj.C:41
size_t size()
Definition: netcluster.hh:147
double gethigh()
Definition: netcluster.hh:348
wavearray< double > BAND
Definition: detector.hh:374
netpixel * getPixel(size_t n, size_t i)
Definition: netcluster.hh:413
double Ex[3]
Definition: detector.hh:331
virtual void FFTW(int=1)
Definition: wavearray.cc:896
regression r
Definition: Regression_H1.C:44
double Rv[3]
Definition: detector.hh:330
s s
Definition: cwb_net.C:155
double rad2deg
char filter[1024]
double getPhi(size_t i)
Definition: skymap.hh:164
WSeries< double > TFmap
Definition: detector.hh:354
double T
Definition: testWDM_4.C:11
void GeodeticToGeocentric(double latitude, double longitude, double elevation, double &X, double &Y, double &Z)
Definition: skycoord.hh:215
const double _eV1x[3]
WSeries< double > waveForm
Definition: detector.hh:355
double AltY
Definition: detector.hh:56
const double _eL1y[3]
virtual double mean() const
Definition: wavearray.cc:1071
const double _rH2[3]
wavearray< int > index
Definition: Meyer.hh:36
char Name[16]
Definition: detector.hh:327
skymap mFp
Definition: detector.hh:347
double fabs(const Complex &x)
Definition: numpy.cc:55
void rotate(double)
Definition: detector.cc:291
virtual ~detector()
Definition: detector.cc:343
const double _eG1y[3]
virtual void waveSort(DataType_t **pp, size_t l=0, size_t r=0) const
Definition: wavearray.cc:1421
void print()
Definition: detector.cc:1797
std::vector< short > index
Definition: detector.hh:45
virtual int getOffset(int, int)
Definition: Wavelet.cc:69
void Forward(int n=-1)
param: wavelet - n is number of steps (-1 means full decomposition)
Definition: wseries.cc:246
TString OS
Definition: cwb_rootlogon.C:25
Meyer< double > S(1024, 2)
sprintf(tfres,"(1/%g)x(%g) (sec)x(Hz)", 2 *df, df)
const double _eA1x[3]
double getTau(double, double)
param: source theta,phi angles in degrees
Definition: detector.cc:698
const double _eH2y[3]
void set(size_t i, double a)
param: sky index param: value to set
Definition: skymap.hh:122
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
netcluster wc
wavearray< double > FREQ
Definition: detector.hh:373
enum WAVETYPE m_WaveType
Definition: Wavelet.hh:106
WaveDWT< DataType_t > * pWavelet
Definition: wseries.hh:456
double dT
Definition: testWDM_5.C:12
fclose(ftrig)
void GetCartesianComponents(double u[3], double Alt, double Az, double Lat, double Lon)
Definition: skycoord.hh:387
float rate
Definition: netpixel.hh:113
size_t size()
Definition: skymap.hh:136
double getdata(char type='R', size_t n=0)
Definition: netpixel.hh:74
WSeries< float > nVAR
Definition: detector.hh:359
std::vector< float > value
Definition: detector.hh:46
virtual void resize(unsigned int)
Definition: wavearray.cc:463
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
void putLayer(wavearray< DataType_t > &, double n)
param: n - layer number
Definition: wseries.cc:219
size_t setsim(WSeries< double > &, std::vector< double > *, double=5., double=8., bool saveWF=false)
Definition: detector.cc:1377
const double _eH1y[3]
double frequency(int l)
Definition: wseries.cc:117
const double _rA1[3]
wavearray< double > ISNR
Definition: detector.hh:372
int maxLayer()
Definition: wseries.hh:139
int m_H
Definition: Wavelet.hh:121
detector & operator<<(detector &)
Definition: detector.cc:411
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
init()
Definition: revMonster.cc:12
exit(0)
void cpf(const wavearray< DataType_t > &, int=0, int=0, int=0)
Definition: wavearray.cc:717
virtual WSeries< double > white(double, int, double=0., double=0.)
what it does: each wavelet layer is devided into k intervals.
Definition: wseries.cc:1146
bool setdata(double a, char type='R', size_t n=0)
Definition: netpixel.hh:58