Logo coherent WaveBurst  
Library Reference Guide
Logo
cwb_pereport.C
Go to the documentation of this file.
1 /*
2 # Copyright (C) 2019 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 // This macro is used to for the post-processing analysis of simulations
20 // done with PE posteriors samples
21 // Author : Gabriele Vedovato
22 
23 #define XIFO 4
24 
25 #pragma GCC system_header
26 
27 #define _USE_LAL
28 
29 #include "cwb.hh"
30 #include "config.hh"
31 #include "wavearray.hh"
32 #include "TString.h"
33 #include "TObjArray.h"
34 #include "TObjString.h"
35 #include "TRandom.h"
36 #include "TComplex.h"
37 #include "TGraphAsymmErrors.h"
38 #include "TPaveStats.h"
39 #include "TMath.h"
40 #include "mdc.hh"
41 #include "cwb2G.hh"
42 #include "watplot.hh"
43 #include "gwavearray.hh"
44 #include "network.hh"
45 #include "gnetwork.hh"
46 #include "constants.hh"
47 #include <fstream>
48 #include <vector>
49 #include "TKDE.h"
50 #include "TSpline.h"
51 
52 // ---------------------------------------------------------------------------------
53 // INFOS
54 // ---------------------------------------------------------------------------------
55 
56 // the injected PE posteriors source parameters are defined in the xml file obtained
57 // from the conversion of the posterior_samples.dat to posterior_samples.xml
58 // The simulation with posteriors must be done using the plugin CWB_Plugin_WF.C which is
59 // used to save the inj/rec/nul waveforms into the output root file
60 
61 // NOTE: the wave_dir (see input options) must include a symbolic link
62 // to the output root file of the onsource rec event
63 // the name of the symbolic link must contains the string defined in data_label
64 
65 // NOTE: to permit the selection of the events based on IFAR the root files
66 // in the output dir must be merged and the cwb_setifar must be applied
67 
68 // ---------------------------------------------------------------------------------
69 // HOW RUN THIS MACRO (EXAMPLE)
70 // ---------------------------------------------------------------------------------
71 
72 /*
73 root -b -l 'cwb_pereport.C+("--data_label=O2_K19_C02c_LH_BBH_SIM_tst1 \
74  --gps_event=1185389807.333 --inj_time_step=150 --off_event=0 --wave_dir=merge \
75  --nifo=2 --ifar_thr=50 --plot_type=time --plot_efraction=0.9")'
76 
77 root -b -l 'cwb_pereport.C+("--data_label=O2_K21_C02c_LH_BBH_SIM_tst1 --gps_event=1187008879.45 \
78  --inj_time_step=150 --off_event=3 --wave_dir=output --nifo=2 --ifar_thr=0 --plot_type=phase \
79  --nevents=100 --sync_phase=true")'
80 */
81 
82 // ---------------------------------------------------------------------------------
83 // DEFINES : Default values used to initialize the user options input parameters
84 // ---------------------------------------------------------------------------------
85 
86 #define PE_MAX_EVENTS 15000
87 
88 #define PE_GW_NAME "GWXXYYZZ"
89 #define PE_DATA_LABEL "wave_"
90 #define PE_WAVE_DIR "output"
91 #define PE_NIFO 2
92 #define PE_NCYCLES 800
93 #define PE_IFAR_THR 0
94 #define PE_GPS_EVENT 0
95 #define PE_TCOA_SHIFT 0.
96 #define PE_GPS_ERROR 0.01
97 #define PE_OFF_EVENT 0
98 #define PE_INJ_TIME_STEP 150
99 #define PE_INJ_ONSRC false
100 
101 #define PE_CCUT ""
102 #define PE_RCUT ""
103 
104 #define PE_LOGL ""
105 
106 #define PE_RSTAT ""
107 
108 #define PE_DUMP_CR true
109 #define PE_USE_ONSRC ""
110 
111 #define PE_PLOT_ONSRC false
112 
113 #define PE_SYNC_PHASE false
114 #define PE_SYNC_TIME false
115 
116 #define PE_SENSITIVITY false
117 #define PE_RESIDUALS false
118 #define PE_STATISTICS false
119 #define PE_EFRACTION 0.01
120 
121 #define PE_SIDE "full"
122 #define PE_COVERAGE "local"
123 
124 #define PE_PLOT_CR true
125 #define PE_PLOT_TYPE "time"
126 #define PE_PLOT_FNAME "pewave"
127 #define PE_PLOT_ODIR ""
128 #define PE_PLOT_EFRACTION 0.999
129 #define PE_PLOT_ZOOM 1.0
130 #define PE_PLOT_99PERC false
131 
132 #define PE_MAKE_FF true
133 #define PE_MAKE_OF false
134 #define PE_MAKE_RE true
135 #define PE_MAKE_NE false
136 #define PE_MAKE_ONSRC false
137 
138 // ---------------------------------------------------------------------------------
139 // INPUT USER OPTIONS
140 // ---------------------------------------------------------------------------------
141 
142 // rec event : is the real detected event reconstructed by cWB
143 // rec posterior : is the injected posterior reconstructed by cWB
144 
145 struct uoptions {
146  TString gw_name; // GW event name
147  TString data_label; // data label of output root files (used to select files)
148  TString wave_dir; // wave root files directory : ex -> (output/merge)
149 
150  int nifo; // number of detectors
151  int nevents; // max number of events read from root files (must be <= PE_MAX_EVENTS)
152  int ncycles; // phase cycles display in plot_phase; xaxis [0:ncycles]
153 
154  double ifar_thr; // ifar threshold (years) used to to select the detected events (0: -> select all)
155 
156  double gps_event; // gps time of rec event (first ifo)
157  double tcoa_shift; // user tcoa time shift (default = 0 sec)
158  double gps_error; // errors gps time of rec event used to identify event in root file
159  int off_event; // time offset of rec_gps_time and merger time of posteriors (integer)
160  int inj_time_step; // injection time step of posteriors (integer)
161  bool inj_onsrc; // def=false. true -> injection are maded in at on-source time. It is setup to true when inj_time_step==0
162 
163  bool dump_cr; // true/false: if enabled rec & confidence regions are dumped to ascii file
164  TString use_onsrc; // if enabled (!="") the onsource vFF,vOF,vRE is replaced with
165  // the sample associated with median xFF.xOF,xRE onsource distribution, allowed values:
166  // mleft/mfull -> median of matching values left/full
167  // eleft/efull -> median of residual energy values left/full
168 
169  bool sync_phase; // true/false: if enabled the rec posteriors are
170  // syncronized in phase respect to the rec event
171  bool sync_time; // true/false: if enabled the rec posteriors are
172  // syncronized in time respect to the rec event
173  // if sync_phase=true & sync_time=true the sync is made in both time and phase
174 
175  bool sensitivity; // true/false: if enabled the computation of sensitivity
176  bool residuals; // true/false: if enabled the residuals (null) are produced instead of waveforms
177  bool statistics; // true/false: if enabled the matching factors of reconstructed vs injected posteriors samples are computed
178  double efraction; // used to select the time range for FF/OF/RE computation
179 
180  TString side; // full/left/right/chirp, if left/right then FF/OF/RE are computed before/after the coalescence time
181  // if chirp then the ccut is applied according to the ccut parameters
182 
183  TString coverage; // local/full - if 'full' then if coverage is computed over the time range of median waveform within the plot_efraction of energy (def=0.999)
184 
185  TString plot_fname; // label used for the output plot name
186  // ex: plot_name=pewave -> L1_pewave_ifar_0_efrac_0d999_Time_A33.png
187  TString plot_odir; // output plot directory
188  TString plot_type; // plot type used for plot_cr: available options are: time/phase/envelope/frequency/spectrum
189  double plot_efraction; // used in time plot, select the time range based on the
190  // signal energy fraction respect to the maximum amplitude
191  double plot_zoom; // used to zooming the time CR plots
192  bool plot_cr; // true(def)/false -> plot waveform cr
193  bool plot_99perc; // true/false(false) -> plot 99 percentage belt
194 
195  bool make_ff; // true(def)/false -> make fitting factor
196  bool make_of; // true/false(def) -> make overlap factor
197  bool make_re; // true(def)/false -> make residual energy factor
198  bool make_ne; // true/false(def) -> make null energy factor
199  bool make_onsrc; // true/false(def) -> make onsource disctribution (green): cWB onsource vs inj-offsource
200 
201  TString ccut; // Is used to select TF area using chirp TF cut. If="" then it is not applied.
202  // The selected TF region is defined by the parameters declared in the ccut string.
203  // format: wdm_fres:mc_lower_factor:mc_upper_factor:left_time:right_time
204  // default: 16:1.35:1.65:0.5:0.0
205 
206  // the following parameters are setup parsing the user ccut parameter. Are initialized with the default values
207  int ccut_wdm_fres;
208  double ccut_bchirp;
209  double ccut_uchirp;
210  double ccut_ltime;
211  double ccut_rtime;
212  double ccut_fmax;
213 
214  TString rcut; // Is used to select TF area using pixels above the rcut_thr threshold. If="" then it is not applied.
215  // The selected TF region is defined by the parameters declared in the rcut string.
216  // format: wdm_fres:thr
217  // default: 64:0.95
218 
219  // the following parameters are setup parsing the user rcut parameter. Are initialized with the default values
220  int rcut_wdm_fres;
221  double rcut_thr;
222 
223  TString logl; // used to define the parameters to compute logl (EXPERIMENTAL OPTION)
224  // format: enable:flow:fhigh:arthr:ifo_mask:resample
225  // default: false:0:4096:0.001:0x11111111:1
226 
227  // the following parameters are setup parsing the user logl parameter. Are initialized with the default values
228  bool logl_enabled;
229  float logl_flow;
230  float logl_fhigh;
231  float logl_arthr;
232  int logl_ifo_mask;
233  int logl_resample;
234 
235  TString rstat; // used to define the parameters to compute rstat (EXPERIMENTAL OPTION)
236 
237  // the following parameters are setup parsing the user rstat parameter. Are initialized with the default values
238 
239  bool rstat_enabled;
240  TString rstat_type;
241  int rstat_rtrials;
242  int rstat_jtrials;
243 
244 };
245 
246 // ---------------------------------------------------------------------------------
247 // Global Variables
248 // ---------------------------------------------------------------------------------
249 
250 uoptions gOPT; // global User Options
251 int gEVENTS; // number of read events
252 static TString gIFO[3] = {"L1","H1","V1"}; // network ifos. WARNING: this setup is hard coded !!!
253 WDM<double>* gWDM; // wdm used for chirp TF cut
254 
255 // chirp tf cut default parameters
256 
257 #define CCUT_WDM_FRES 16 // the WDM frequency resolution (Hz) used to decompose the signal in TF domain
258 #define CCUT_BCHIRP 1.35 // mchirp factor used to select the bottom region boundary
259 #define CCUT_UCHIRP 1.65 // mchirp factor used to select the upper region boundary
260 #define CCUT_LTIME 0.5 // left time from tcoa (sec) used to select the the time region: [tcoa-left_time:tcoa-right_time]
261 #define CCUT_RTIME 0.0 // right time from tcoa (sec) used to select the the time region: [tcoa-left_time:tcoa-right_time]
262 #define CCUT_FMAX 512.0 // hard coded init value for freq max used by the tchirp and fchirp functions
263 
264 #define RCUT_WDM_FRES 8 // the WDM frequency resolution (Hz) used to decompose the signal in TF domain
265 #define RCUT_THR 0.95 // normalized residual energy threshold [0,1]
266 
267 // logl default parameters (EXPERIMENTAL OPTION)
268 
269 #define LOGL_ENABLED false // true/false -> enable/disable logl computation
270 #define LOGL_FLOW 0 // logl low frequency start
271 #define LOGL_FHIGH 8192 // logl high frequency stop
272 #define LOGL_ARTHR 0.001 // logl amplitude ratio threshold -> min_freq_amp vREC > max_freq_amp vREC
273 #define LOGL_IFO_MASK 0x1111111 // logl ifo mask used to select ifos for logl computation
274 #define LOGL_RESAMPLE 1 // logl resample, used to speedup logl computation. logl is computed every 'resample' samples
275 
276 //#define LOGL_USE_KDE // select the probability distribution type: KDE or binning Histogram for logl computation
277 //#define LOGL_TEST_KDE 1000 // used to check comparison KDE vs binning Histogram
278 
279 // rstat defaul parameters _. rstat is the statistic based on symmetric null hyphotesis distribution
280 
281 #define RSTAT_ENABLED false // true/false -> enable/disable rstat computation
282 #define RSTAT_TYPE "median" // rstat1/median
283 #define RSTAT_RTRIALS 0 // number of entries in the null hyphotesis distribution. If 0 then rtrials=gEVENTS
284 #define RSTAT_JTRIALS 0 // number of injections used to build the 'green' distribution. If 0 then jtrials=gEVENTS
285 
286 // ---------------------------------------------------------------------------------
287 // WAVEFORMS (vectors index is ifos)
288 // ---------------------------------------------------------------------------------
289 
290 std::vector<wavearray<double> > vNUL; // null reconstructed by wave packet
291 std::vector<wavearray<double> > vREC; // signal reconstructed by wave packet
292 std::vector<wavearray<double> > vINJ; // whitened injected waveform
293 std::vector<wavearray<double> > vAUX; // auxiliary whitened injected waveform
294 std::vector<wavearray<double> > vMED; // median reconstructed amplitude
295 std::vector<wavearray<double> > vL50; // = vMED - 50% Lower Bound
296 std::vector<wavearray<double> > vU50; // = vMED - 50% Upper Bound
297 std::vector<wavearray<double> > vL90; // = 90% Lower Bound - vMED
298 std::vector<wavearray<double> > vU90; // = 90% Upper Bound - vMED
299 std::vector<wavearray<double> > vL99; // = 99% Lower Bound - vMED
300 std::vector<wavearray<double> > vU99; // = 99% Upper Bound - vMED
301 
302 std::vector<wavearray<double> > pSNR; // = on-source SNR evolution of vREC computed with cWB::Toolbos::GetPhase
303 std::vector<wavearray<double> > pFRQ; // = on-source Freq evolution of vREC computed with cWB::Toolbos::GetPhase
304 std::vector<wavearray<double> > pTIM; // = on-source Time evolution of vREC computed with cWB::Toolbos::GetPhase
305 
306 std::vector<double> vTREC; // absolute tstart of vREC. The value stored into wavearray start is module inj_time_step.
307 
308 double vTCOA; // tcoa OnSource sample
309 double vFACTOR; // factor OnSource sample
310 float vTHETA; // theta OnSource sample
311 float vPHI; // phi OnSource sample
312 float vM1; // mass1 OnSource sample
313 float vM2; // mass2 OnSource sample
314 float vS1; // spin1 OnSource sample
315 float vS2; // spin2 OnSource sample
316 float vDOF; // Degrees of Freedom OnSource sample
317 float vSNR[NIFO_MAX]; // reconstructed SNR OnSource sample
318 
319 double vTSYNC[NIFO_MAX]; // time shift OnSource sample after time sync
320 double vPSYNC[NIFO_MAX]; // phase shift OnSource sample after phase sync
321 
322 std::vector<wavearray<double> > wREC[PE_MAX_EVENTS]; // reconstructed OffSource signals
323 std::vector<wavearray<double> > wNUL[PE_MAX_EVENTS]; // reconstructed null OffSource signal sdata
324 std::vector<wavearray<double> > wINJ[PE_MAX_EVENTS]; // OffSource iwhitened injected posteriors
325 std::vector<wavearray<double> > wAUX[PE_MAX_EVENTS]; // OffSource auxiliary iwhitened injected posteriors
326 
327 double wTCOA[PE_MAX_EVENTS]; // tcoa OffSource injected posteriors
328 double wFACTOR[PE_MAX_EVENTS]; // factor OffSource injected posteriors
329 float wTHETA[PE_MAX_EVENTS]; // theta OffSource injected posteriors
330 float wPHI[PE_MAX_EVENTS]; // phi OffSource injected posteriors
331 float wM1[PE_MAX_EVENTS]; // mass1 OffSource injected posteriors
332 float wM2[PE_MAX_EVENTS]; // mass2 OffSource injected posteriors
333 float wS1[PE_MAX_EVENTS]; // spin1 OffSource injected posteriors
334 float wS2[PE_MAX_EVENTS]; // spin2 OffSource injected posteriors
335 float wDOF[PE_MAX_EVENTS]; // Degrees of Freedom OffSource injected posteriors
336 float wSNR[PE_MAX_EVENTS][NIFO_MAX]; // reconstructed SNR OffSource injected posteriors
337 
338 std::vector<double> vFF,vOF,vRE,vNE; // Fitting/Overlap/ResidualEnergy/NullEnergy Factors of reconstructed vs injected Posterior Samples
339  // the first element is the
340  // cWB point estimate Fitting/Overlap/ResidualEnergy Factor respect to Map Posterior Sample
341 
342 std::vector<double> xFF,xOF,xRE,xNE; // Matching factors onsource reconstructed vs offsource injected
343 
344 
345 // ---------------------------------------------------------------------------------
346 // FUNCTIONS
347 // ---------------------------------------------------------------------------------
348 
349 void ResetUserOptions();
351 void PrintUserOptions(TString ofname="");
352 
353 void LoadOutputRootFiles(int nIFO, TString data_label, TString output_dir, int max_events=PE_MAX_EVENTS, double ifar_thr=0);
354 int SyncWaveforms(int nIFO, TString type);
355 
357 
359 int ComputeCCutStatistics(int nIFO);
360 double GetCCut(wavearray<double>* ts, double tcoa, double m1, double m2, double s1z, double s2z);
361 
364 
366 
368 
369 int ComputeStatistics(int nIFO);
370 int GetOnSourceStatistic(int nIFO, double &mFF, double &mOF, double &mRE);
371 void GetOffSourceStatistic(int nIFO, int recId, vector<int> injId,
372  vector<double>& oFF, vector<double>& oOF, vector<double>& oRE);
373 void MakeDistributions(TString type="FF");
374 void MakePvalueDistribution(TString type="FF");
375 void DumpStatistics(TString ofname, TString params, bool app);
376 
377 float TestStatistic(int nIFO, int id, float ref); // Used for tests
378 
379 int ComputeWaveformCR(int nIFO);
380 void DumpWaveformCR(int nIFO);
381 void PlotWaveformsCR(int nIFO);
382 
383 int ComputeWaveformFCR(int nIFO);
384 void ComputeWaveformCR(int nIFO, int selected, double* cov50, double* cov90, double* cov99);
385 void GetFullCoverage(int nIFO, int selected, double* fcov50, double* fcov90, double* fcov99);
386 
387 void PlotWaveforms(int nIFO, int id, bool residual=false);
392  TString pdir, double P, double Q, double tref, double tcoa, int ifoid);
393 
394 double GetInjTcoa(double geocentric_tcoa, network* NET, TString ifo, double theta, double phi);
395 double GetDelay(network* NET, TString ifo, double theta, double phi);
396 double GetSyncTcoa(wavearray<double> wf, double sync_time, double sync_phase, double tcoa);
397 
398 void ComputePhaseSensitivity(TString match, double lower, double upper, double& dmatch, double& dphase);
399 void ComputeTimeSensitivity(TString match, double lower, double upper, double& dmatch, double& dtime);
400 void ComputeAmpSensitivity(TString match, double lower, double upper, double& dmatch, double& damp);
401 
403 
404  // Read Input Options
406  ReadUserOptions(options);
408  PrintUserOptions("pereport_config.txt");
409 
410  if(gOPT.nifo>3) {
411  cout << "cwb_pereport - Error : max nifo is 3" << endl;
412  gSystem->Exit(1);
413  }
414  if((gOPT.plot_type!="time")&&(gOPT.plot_type!="phase")&&(gOPT.plot_type!="envelope")&&(gOPT.plot_type!="frequency")&&(gOPT.plot_type!="spectrum")) {
415  cout << "cwb_pereport - Error : plot_type option (" << gOPT.plot_type << ") not allowed. Available options are: time/phase/envelope/frequency/spectrum" << endl;
416  gSystem->Exit(1);
417  }
418  if((gOPT.coverage!="local")&&(gOPT.coverage!="full")) {
419  cout << "cwb_pereport - Error : coverage option (" << gOPT.coverage << ") not allowed. Available options are: local/full" << endl;
420  gSystem->Exit(1);
421  }
422 
423  gEVENTS=0; // init the read events
424 
425  // init vTSYNC, vPSYNC
426  for(int n=0;n<NIFO_MAX;n++) vTSYNC[n]=0;
427  for(int n=0;n<NIFO_MAX;n++) vPSYNC[n]=0;
428 
429  // read reconstructed posteriors from output root files
430  LoadOutputRootFiles(gOPT.nifo, gOPT.data_label, gOPT.wave_dir, gOPT.nevents, gOPT.ifar_thr);
431 
432  // init WDM transform
433  if(gOPT.side=="ccut") { // WDM transform for ccut
434  int ccut_wdm_levels = int(vREC[0].rate()/gOPT.ccut_wdm_fres/2);
435  cout << endl << "RATE " << vREC[0].rate() << " WDM levels " << ccut_wdm_levels << endl << endl;
436  gWDM = new WDM<double>(ccut_wdm_levels, ccut_wdm_levels, 6, 10);
437  }
438  if(gOPT.side=="rcut") { // WDM transform for rcut
439  int rcut_wdm_levels = int(vREC[0].rate()/gOPT.rcut_wdm_fres/2);
440  cout << endl << "RATE " << vREC[0].rate() << " WDM levels " << rcut_wdm_levels << endl << endl;
441  gWDM = new WDM<double>(rcut_wdm_levels, rcut_wdm_levels, 6, 10);
442  }
443 
444  gStyle->SetTitleW(0.95); // fix weird title display offset
445 
446  // compute Sample Statistics (Fitting Factors, Overlap Factors, Residual Energy)
447  if(gOPT.statistics) {
448 
449  if(gOPT.side=="ccut") {
450  int selected = ComputeCCutStatistics(gOPT.nifo);
451  if(selected==0) exit(0);
452 
453  gOPT.sensitivity=false;
454  gOPT.make_onsrc=false;
455  MakeDistributions("RE"); // plot Residual Energy Factor
456 
457  } else {
458  int selected = ComputeStatistics(gOPT.nifo);
459  if(selected==0) exit(0);
460 
461  if(!gOPT.rstat_enabled) PlotWaveforms(gOPT.nifo, -1, true); // plot onsource residuals
462  if(!gOPT.rstat_enabled) PlotWaveforms(gOPT.nifo, -1, false); // plot onsource waveforms
463  //PlotWaveforms(gOPT.nifo, 10, true); // plot offsource residuals
464  //PlotWaveforms(gOPT.nifo, 10, false); // plot offsource waveforms
465 
466  // plot Fitting Factor
467  if(gOPT.make_ff) MakeDistributions("FF");
468  if(gOPT.make_ff && gOPT.make_onsrc) MakePvalueDistribution("FF");
469  // plot Overlap Factor
470  if(gOPT.make_of) MakeDistributions("OF");
471  if(gOPT.make_of && gOPT.make_onsrc) MakePvalueDistribution("OF");
472  // plot Residual Energy Factor
473  if(gOPT.make_re) MakeDistributions("RE");
474  if(gOPT.make_re && gOPT.make_onsrc) MakePvalueDistribution("RE");
475  // plot Null Energy Factor
476  if(gOPT.make_ne && (gOPT.residuals)) MakeDistributions("NE");
477  }
478  } else { // compute waveform CR
479 
480  // compute Posterior CR
481  int selected = (gOPT.coverage=="local") ? ComputeWaveformCR(gOPT.nifo) : ComputeWaveformFCR(gOPT.nifo);
482  if(selected==0) exit(0);
483 
484  // plot cWB rec and posterior confidence regions
485  if(gOPT.plot_cr) PlotWaveformsCR(gOPT.nifo);
486 
487  // rec & confidence regions are dumped to acii file (only for time domain plots)
488  if(gOPT.dump_cr && gOPT.plot_type!="phase") DumpWaveformCR(gOPT.nifo);
489  }
490 
491  delete gWDM;
492 
493  exit(0);
494 }
495 
497 
498  while(!vFF.empty()) vFF.pop_back(); vFF.clear(); std::vector<double>().swap(vFF); // reset off-source vector vFF
499  while(!vOF.empty()) vOF.pop_back(); vOF.clear(); std::vector<double>().swap(vOF); // reset off-source vector vOF
500  while(!vRE.empty()) vRE.pop_back(); vRE.clear(); std::vector<double>().swap(vRE); // reset off-source vector vRE
501 
502  while(!xFF.empty()) xFF.pop_back(); xFF.clear(); std::vector<double>().swap(xFF); // reset on-source vector xFF
503  while(!xOF.empty()) xOF.pop_back(); xOF.clear(); std::vector<double>().swap(xOF); // reset on-source vector xOF
504  while(!xRE.empty()) xRE.pop_back(); xRE.clear(); std::vector<double>().swap(xRE); // reset on-source vector xRE
505  while(!xNE.empty()) xNE.pop_back(); xNE.clear(); std::vector<double>().swap(xNE); // reset on-source vector xNE
506 
507  if(gOPT.rstat_enabled==false) { // compute standard statistic
508 
509  gnetwork* NET = new gnetwork(nIFO,gIFO);
510 
511  // The waveforms are aligned and, if requested, sync in phase and time
512  // the reference waveforms are INJ, this choice is necessary to fix the original onsource waveform
513  int selected=SyncWaveforms(nIFO, "statistics");
514  cout << endl << "ComputeStatistics - selected events : " << selected << endl << endl;
515  if(selected==0) return 0;
516 
517  // cWB point estimate OnSource Matching Factors
518 
519  vector<double> tstart;
520  if(gOPT.side=="right") {
521  tstart.resize(nIFO);
522  for(int n=0;n<nIFO;n++) {
523  double inj_tcoa = gOPT.inj_time_step+fmod(vTCOA,1);
524  tstart[n] = GetInjTcoa(inj_tcoa, NET, gIFO[n], vTHETA, vPHI);
525  }
526  }
527 
528  vector<double> tstop;
529  if(gOPT.side=="left") {
530  tstop.resize(nIFO);
531  for(int n=0;n<nIFO;n++) {
532  double inj_tcoa = gOPT.inj_time_step+fmod(vTCOA,1);
533  tstop[n] = GetInjTcoa(inj_tcoa, NET, gIFO[n], vTHETA, vPHI);
534  }
535  }
536 
537  double FF = CWB::mdc::GetMatchFactor("ff",vREC,vINJ,tstart,tstop);
538  double OF = CWB::mdc::GetMatchFactor("of",vREC,vINJ,tstart,tstop);
539  double RE = CWB::mdc::GetMatchFactor("re",vREC,vINJ,tstart,tstop);
540 
541  vFF.push_back(FF);
542  vOF.push_back(OF);
543  vRE.push_back(RE);
544 
545  if(gOPT.residuals) { // injection null energy
546  vector<wavearray<double> > vDAT = vNUL; for(int n=0;n<nIFO;n++) vDAT[n]+=vREC[n];
547  double NE = CWB::mdc::GetMatchFactor("re",vDAT,vINJ,tstart,tstop);
548  vNE.push_back(NE);
549  }
550 
551  // cWB point estimate OffSource Matching Factors
552 
553  for(int i=0;i<gEVENTS;i++) {
554 
555  if(wREC[i].size()==0) continue;
556 
557  vector<double> tstart;
558  if(gOPT.side=="right") {
559  tstart.resize(nIFO);
560  for(int n=0;n<nIFO;n++) {
561  double inj_tcoa = gOPT.inj_time_step+fmod(wTCOA[i],1);
562  tstart[n] = GetInjTcoa(inj_tcoa, NET, gIFO[n], wTHETA[i], wPHI[i]);
563  }
564  }
565 
566  vector<double> tstop;
567  if(gOPT.side=="left") {
568  tstop.resize(nIFO);
569  for(int n=0;n<nIFO;n++) {
570  double inj_tcoa = gOPT.inj_time_step+fmod(wTCOA[i],1);
571  tstop[n] = GetInjTcoa(inj_tcoa, NET, gIFO[n], wTHETA[i], wPHI[i]);
572  }
573  }
574 
575  double FF = CWB::mdc::GetMatchFactor("ff",wREC[i],wINJ[i],tstart,tstop);
576  double OF = CWB::mdc::GetMatchFactor("of",wREC[i],wINJ[i],tstart,tstop);
577  double RE = CWB::mdc::GetMatchFactor("re",wREC[i],wINJ[i],tstart,tstop);
578 
579  vFF.push_back(FF);
580  vOF.push_back(OF);
581  vRE.push_back(RE);
582 
583  //float pvalue = TestStatistic(nIFO, i, RE);
584  //cout << i << "\tpvalue " << pvalue << "\tref " << RE << endl;
585 
586  if(gOPT.residuals) { // injection null energy
587  vector<wavearray<double> > vDAT = wNUL[i]; for(int n=0;n<nIFO;n++) vDAT[n]+=wREC[i][n];
588  double NE = CWB::mdc::GetMatchFactor("re",vDAT,wINJ[i],tstart,tstop);
589  vNE.push_back(NE);
590  }
591  }
592 
593  // dump match factors
594  TString pdir=gOPT.plot_odir;
595  char ofname[256] = "match_factors.txt";
596  TString fName = pdir!="" ? TString(pdir)+TString("/")+ofname : ofname;
597  cout << "write : " << fName << endl;
598  ofstream out;
599  out.open(fName.Data(),ios::out);
600  if (!out.good()) {cout << "Error Opening Output File : " << fName << endl;exit(1);}
601  out.precision(14);
602  double iSNR=0;
603  double oSNR=0;
604  for(int n=0;n<vINJ.size();n++) for(int i=0;i<vINJ[n].size();i++) iSNR+=pow(vINJ[n][i],2); // inj onsource SNR
605  for(int n=0;n<vREC.size();n++) for(int i=0;i<vREC[n].size();i++) oSNR+=pow(vREC[n][i],2); // rec onsource SNR
606  if(gOPT.residuals) {
607  out << "tcoa " << vTCOA << "\tiSNR " << sqrt(iSNR) << "\toSNR " << sqrt(oSNR) << "\tfactor " << vFACTOR
608  << "\tff " << vFF[0] << "\tof " << vOF[0] << "\tre " << vRE[0] << "\tne " << vNE[0] << endl;
609  } else {
610  out << "tcoa " << vTCOA << "\tiSNR " << sqrt(iSNR) << "\toSNR " << sqrt(oSNR)
611  << "\tff " << vFF[0] << "\tof " << vOF[0] << "\tre " << vRE[0] << endl;
612  }
613  for(int j=0;j<gEVENTS;j++) {
614  iSNR=oSNR=0;
615  for(int n=0;n<wINJ[j].size();n++) for(int i=0;i<wINJ[j][n].size();i++) iSNR+=pow(wINJ[j][n][i],2); // inj offsource SNR
616  for(int n=0;n<wREC[j].size();n++) for(int i=0;i<wREC[j][n].size();i++) oSNR+=pow(wREC[j][n][i],2); // rec offsource SNR
617  if(gOPT.residuals) {
618  out << "tcoa " << wTCOA[j] << "\tiSNR " << sqrt(iSNR) << "\toSNR " << sqrt(oSNR) << "\tfactor " << wFACTOR[j]
619  << "\tff " << vFF[j+1] << "\tof " << vOF[j+1] << "\tre " << vRE[j+1] << "\tne " << vNE[j+1] << endl;
620  } else {
621  out << "tcoa " << wTCOA[j] << "\tiSNR " << sqrt(iSNR) << "\toSNR " << sqrt(oSNR)
622  << "\tff " << vFF[j+1] << "\tof " << vOF[j+1] << "\tre " << vRE[j+1] << endl;
623  }
624  }
625  out.close();
626 
627  if(gOPT.make_onsrc || gOPT.use_onsrc!="") {
628 
629  double mFF,mOF,mRE;
630  int imed=GetOnSourceStatistic(nIFO,mFF,mOF,mRE); // fill xFF,xOF,xRE and compute median xFF,xOF,xRE
631 
632  // the onsource vFF,vOF,vRE,vINJ are replaced with the sample associated with median xFF onsource distribution
633  if(gOPT.use_onsrc!="") {
634  cout << endl << "GetOnSourceStatistic : " << "\tmFF = " << mFF << "\tmOF = " << mOF << "\tmRE = " << mRE << endl << endl;
635  vFF[0]=mFF;
636  vOF[0]=mOF;
637  vRE[0]=mRE;
638 
639  for(int n=0;n<nIFO;n++) vINJ[n]=wINJ[imed][n];
640  }
641  }
642 
643  delete NET;
644  return selected;
645 
646  } else { // compute rstatistic
647 
648  // init
649  if(gOPT.rstat_rtrials==0) {gOPT.rstat_rtrials=gEVENTS;cout<<endl << "---> Set rstat_rtrials = " << gOPT.rstat_rtrials << endl<<endl;}
650  if(gOPT.rstat_jtrials==0) {gOPT.rstat_jtrials=gEVENTS;cout<<endl << "---> Set rstat_jtrials = " << gOPT.rstat_jtrials << endl<<endl;}
651  if(gOPT.rstat_rtrials>gEVENTS) gOPT.rstat_rtrials=gEVENTS;
652  if(gOPT.rstat_jtrials>gEVENTS) gOPT.rstat_jtrials=gEVENTS;
653 
654  // fill recId with random reconstructed off-source events
655  vector<int> recId;
656  std::map<int,bool> runique;
657  while(recId.size()<gOPT.rstat_rtrials) {
658  int k = int(gRandom->Uniform(0,gEVENTS));
659  if(runique[k]==false) {runique[k]=true;recId.push_back(k);}
660  }
661 
662  // fill injId with random reconstructed off-source events
663  vector<int> injId;
664  std::map<int,bool> junique;
665  while(injId.size()<gOPT.rstat_jtrials) {
666  int k = int(gRandom->Uniform(0,gEVENTS));
667  if(junique[k]==false) {junique[k]=true;injId.push_back(k);}
668  }
669 
670  // get match reconstructed offsource vs injected offsource
671  int kEVENTS = gOPT.rstat_rtrials;
672  int pc = 0; int npc= 0;
673  int ipc = double(kEVENTS)/10.; if(ipc==0) ipc=1;
674  cout << endl << "Compute offsource distribution : be patient, it takes a while ..." << endl << endl;
675  vector<vector<double> > voFF,voOF,voRE;
676  for(int k=0;k<kEVENTS;k++) {
677  if((npc++)%ipc==0) {if(kEVENTS>10) {cout << pc<<"%";if (pc<100) cout << " - ";pc+=10;cout.flush();}}
678  vector<double> oFF,oOF,oRE;
679  GetOffSourceStatistic(nIFO,recId[k],injId,oFF,oOF,oRE); // fill oFF,oOF,oRE
680  voFF.push_back(oFF);
681  voOF.push_back(oOF);
682  voRE.push_back(oRE);
683  }
684  if(pc==100) cout << pc<<"%";;
685  cout << endl << endl;
686 
687  // compute null hypothesis r-distribution
688 
689  vFF.push_back(0); // reserve place on-source FF r-statistic
690  vOF.push_back(0); // reserve place on-source OF r-statistic
691  vRE.push_back(0); // reserve place on-source RE r-statistic
692 
693  if(gOPT.rstat_type=="rstat1") {
694  for(int k=0;k<kEVENTS;k++) {
695  int nTOT=0; int nFF=0; int nOF=0; int nRE=0;
696  for(int i=0;i<kEVENTS;i++) {
697  for(int j=0;j<gOPT.rstat_jtrials;j++) {
698  nTOT++;
699  if(voFF[k][j]>voFF[i][j]) nFF++;
700  if(voOF[k][j]>voOF[i][j]) nOF++;
701  if(voRE[k][j]>voRE[i][j]) nRE++;
702  }
703  }
704  // save off-source r-statistic
705  vFF.push_back(double(nFF)/double(nTOT));
706  vOF.push_back(double(nOF)/double(nTOT));
707  vRE.push_back(double(nRE)/double(nTOT));
708  }
709  }
710 
711  if(gOPT.rstat_type=="median") {
712  int nentries = gOPT.rstat_jtrials;
713  int *index = new int[nentries];
714  double *value = new double[nentries];
715  int imed = (nentries*50.)/100.; if(imed>=nentries) imed=nentries-1;
716 
717  for(int k=0;k<kEVENTS;k++) {
718  for(int i=0;i<nentries;i++) value[i]=voFF[k][i];
719  TMath::Sort(nentries,value,index,false);
720  vFF.push_back(value[index[imed]]); // save off-source FF r-statistic
721 
722  for(int i=0;i<nentries;i++) value[i]=voOF[k][i];
723  TMath::Sort(nentries,value,index,false);
724  vOF.push_back(value[index[imed]]); // save off-source OF r-statistic
725 
726  for(int i=0;i<nentries;i++) value[i]=voRE[k][i];
727  TMath::Sort(nentries,value,index,false);
728  vRE.push_back(value[index[imed]]); // save off-source RE r-statistic
729  }
730 
731  delete [] index;
732  delete [] value;
733  }
734 
735  // get match reconstructed onsource vs injected offsource
736  GetOffSourceStatistic(nIFO,-1,injId,xFF,xOF,xRE); // fill xFF,xOF,xRE (green distribution)
737 
738  // compute on-source r-statistic value
739 
740  if(gOPT.rstat_type=="rstat1") {
741  int nTOT=0; int nFF=0; int nOF=0; int nRE=0;
742  for(int i=0;i<kEVENTS;i++) {
743  for(int j=0;j<gOPT.rstat_jtrials;j++) {
744  nTOT++;
745  if(xFF[j]>voFF[i][j]) nFF++;
746  if(xOF[j]>voOF[i][j]) nOF++;
747  if(xRE[j]>voRE[i][j]) nRE++;
748  }
749  }
750  // save on-source r-statistic
751  vFF[0]=double(nFF)/double(nTOT);
752  vOF[0]=double(nOF)/double(nTOT);
753  vRE[0]=double(nRE)/double(nTOT);
754 
755  gOPT.make_onsrc=false; // disable plot on-source distribution
756  }
757 
758  if(gOPT.rstat_type=="median") {
759  int nentries = gOPT.rstat_jtrials;
760  int *index = new int[nentries];
761  double *value = new double[nentries];
762  int imed = (nentries*50.)/100.; if(imed>=nentries) imed=nentries-1;
763 
764  for(int i=0;i<nentries;i++) value[i]=xFF[i];
765  TMath::Sort(nentries,value,index,false);
766  vFF[0]=value[index[imed]]; // save on-source FF r-statistic
767 
768  for(int i=0;i<nentries;i++) value[i]=xOF[i];
769  TMath::Sort(nentries,value,index,false);
770  vOF[0]=value[index[imed]]; // save on-source OF r-statistic
771 
772  for(int i=0;i<nentries;i++) value[i]=xRE[i];
773  TMath::Sort(nentries,value,index,false);
774  vRE[0]=value[index[imed]]; // save on-source RE r-statistic
775 
776  delete [] index;
777  delete [] value;
778  }
779 
780  return kEVENTS;
781  }
782 
783  return 0;
784 }
785 
787 
788  if(gOPT.side!="ccut") {cout << "ComputeCCutStatistics Error: enabled only with gOPT.side=ccut" << endl;exit(1);}
789 
790  // The waveforms are aligned and, if requested, sync in phase and time
791  // the reference waveforms are INJ, this choice is necessary to fix the original onsource waveform
792  int selected=SyncWaveforms(nIFO, "statistics");
793  cout << endl << "ComputeCCutStatistics - selected events : " << selected << endl << endl;
794  if(selected==0) return 0;
795 
796  cout << endl << "Apply CCut : be patient, it takes a while ..." << endl << endl;
797  gnetwork NET(nIFO,gIFO);
798  int pc = 0;
799  int npc= 0;
800  int ipc = double(nIFO*gEVENTS)/10.; if(ipc==0) ipc=1;
801 
802  double RE=0;
803  for(int n=0;n<nIFO;n++) {
804  double inj_tcoa = gOPT.inj_time_step+fmod(vTCOA,1)-vINJ[n].start();
805  inj_tcoa = GetInjTcoa(inj_tcoa, &NET, gIFO[n], vTHETA, vPHI);
806  wavearray<double> vDif = CWB::mdc::GetDiff(&vREC[n], &vINJ[n]);
807  RE += GetCCut(&vDif, inj_tcoa, vM1, vM2, vS1, vS2);
808  }
809  vFF.push_back(0); // dummy value
810  vOF.push_back(0); // dummy value
811  vRE.push_back(RE);
812 
813  for(int i=0;i<gEVENTS;i++) {
814  RE=0;
815  for(int n=0;n<nIFO;n++) {
816  if((npc++)%ipc==0) {if(gEVENTS>100) {cout << pc<<"%";if (pc<100) cout << " - ";pc+=10;cout.flush();}}
817  double inj_tcoa = gOPT.inj_time_step+fmod(wTCOA[i],1)-wINJ[i][n].start();
818  inj_tcoa = GetInjTcoa(inj_tcoa, &NET, gIFO[n], wTHETA[i], wPHI[i]);
819  wavearray<double> wDif = CWB::mdc::GetDiff(&wREC[i][n], &wINJ[i][n]);
820  RE += GetCCut(&wDif, inj_tcoa, wM1[i], wM2[i], wS1[i], wS2[i]);
821  }
822  vFF.push_back(0); // dummy value
823  vOF.push_back(0); // dummy value
824  vRE.push_back(RE);
825  }
826 
827  if(pc==100) cout << pc<<"%";;
828  cout << endl << endl;
829 
830  return selected;
831 }
832 
833 void
834 PlotWaveforms(int nIFO, int id, bool residual) {
835 
836  if(id>=gEVENTS) {
837  cout << "PlotWaveforms - Error : sample id exceed max number " << gEVENTS << endl;
838  gSystem->Exit(1);
839  }
840 
841  wavearray<double> wrec,winj;
842  gnetwork* NET = new gnetwork(nIFO,gIFO);
843 
844  // plots rec vs inj
845  for(int n=0;n<nIFO;n++) {
846 
847  TString tagid="";
848 
849  if(id<0) {wrec=vREC[n];winj=vINJ[n];tagid="onsource";} // onsource posterior sample
850  else {wrec=wREC[id][n];winj=wINJ[id][n];tagid=TString::Format("sample %d",id);} // offsource posterior sample
851 
852  // restore original time/phase
853  if(gOPT.sync_phase || gOPT.sync_time) {
855  CWB::mdc::TimePhaseSync(winj,-vTSYNC[n],-vPSYNC[n]);
856  }
857 
858  // resample data to increase the plot resolution
859  wrec.Resample(16384);
860  winj.Resample(16384);
861 
862  gwavearray<double> gw(&wrec);
863  gw.Draw(GWAT_TIME);
864  if(residual) {
865  wavearray<double> wres=wrec;
866  for(int i=0;i<wres.size();i++) wres[i]-=winj[i];
867  gw.Draw(&wres,GWAT_TIME,"SAME",kRed);
868  } else {
869  gw.Draw(&winj,GWAT_TIME,"SAME",kRed);
870  }
871 
872  watplot* plot = gw.GetWATPLOT(); // get pointer to watplot object
873 
874  // set x,y axis titles and plot title
875  char gtitle[256];
876  if(residual) {
877  sprintf(gtitle,"%s - %s - Residual(Red) - Reconstructed(Black) - Tcoa(Green) - (%s)",gOPT.gw_name.Data(),gIFO[n].Data(),tagid.Data());
878  } else {
879  sprintf(gtitle,"%s - %s - Injected(Red) - Reconstructed(Black) - Tcoa(Green) - (%s)",gOPT.gw_name.Data(),gIFO[n].Data(),tagid.Data());
880  }
881  plot->gtitle(gtitle,"time(sec)","amplitude");
882 
883  // set the time range to be displayed
884  double bT, eT;
885  double P=0.999;
886  double tmax; double amax=0; // get time of max abs(amp) waveform envelope
887  wavearray<double> W=wrec; W+=winj; // wrec+winj is used to compute the boundaries
889  for(int i=0;i<wenv.size();i++) if(fabs(wenv[i])>amax) {amax=fabs(wenv[i]);tmax=wenv.start()+i/wenv.rate();}
890  CWB::mdc::GetTimeBoundaries(W, P, bT, eT, tmax, P);
891  bT-=W.start(); eT-=W.start();
892  plot->graph[0]->GetHistogram()->GetXaxis()->SetRangeUser(bT,eT);
893 
894  // set x title
895  TString xtitle = TString::Format("Time (sec) : GPS OFFSET = %d",int(vTREC[n]));
896  plot->graph[0]->GetHistogram()->GetXaxis()->SetTitle(xtitle.Data());
897 
898  bool is_tcoa_defined=false;
899  double inj_tcoa;
900  if(id<0) { // onsource posterior sample
901  if(vTCOA>=0) is_tcoa_defined=true;
902  inj_tcoa = gOPT.inj_time_step+fmod(vTCOA,1);
903  inj_tcoa = GetInjTcoa(inj_tcoa, NET, gIFO[n], vTHETA, vPHI);
904  if(gOPT.sync_phase || gOPT.sync_time) { // inj_tcoa of vINJ[n] after time/phase sync
905  inj_tcoa = GetSyncTcoa(vINJ[n], -vTSYNC[n], -vPSYNC[n], inj_tcoa);
906  }
907  } else { // offsource posterior sample
908  if(wTCOA[id]>=0) is_tcoa_defined=true;
909  inj_tcoa = gOPT.inj_time_step+fmod(wTCOA[id],1);
910  inj_tcoa = GetInjTcoa(inj_tcoa, NET, gIFO[n], wTHETA[id], wPHI[id]);
911  if(gOPT.sync_phase || gOPT.sync_time) { // inj_tcoa of wINJ[id][n] after time/phase sync
912  inj_tcoa = GetSyncTcoa(wINJ[id][n], -vTSYNC[n], -vPSYNC[n], inj_tcoa);
913  }
914  }
915 
916  // add vertical green line at tcoa time
917  wavearray<double> wline = wrec;
918  double dt=1./wline.rate();
919  for(int i=0;i<wline.size();i++) {
920  double time=i*dt+wline.start();
921  if(fabs(time-inj_tcoa)<dt) wline[i]=-1.0; else wline[i]=-1000.;
922  }
923  if(is_tcoa_defined) gw.Draw(&wline,GWAT_TIME,"SAME",kGreen);
924 
925  TString gfile;
926  if(residual) {
927  gfile="x"+gIFO[n]+"_rec_vs_res_"+tagid+".png";
928  } else {
929  gfile="x"+gIFO[n]+"_rec_vs_inj_"+tagid+".png";
930  }
931 
932  (*plot) >> gfile;
933 
934  if(residual) {
935  gfile="x"+gIFO[n]+"_rec_vs_res_"+tagid+".root";
936  } else {
937  gfile="x"+gIFO[n]+"_rec_vs_inj_"+tagid+".root";
938  }
939 
940  (*plot) >> gfile;
941 
942  cout << "created plot file name : " << gfile << endl;
943  }
944 }
945 
947 
948  // The waveforms are aligned and, if requested, sync in phase and time
949  // the reference waveform is REC, this choice is necessary to fix the original onsource waveform
950  int selected=SyncWaveforms(nIFO, "waveform");
951  cout << endl << "ComputeWaveformCR - selected events : " << selected << endl << endl;
952  if(selected==0) return 0;
953 
954  if(gOPT.logl_enabled && gOPT.plot_type=="spectrum") {
955  cout << endl << "Compute log-likelihood : be patient, it takes a while ..." << endl << endl;
956  }
957  double fmin=1e20;
958  double fmax=0;
959  double logl; // Log_e Likelihood (used to compute the Bayes Factor)
960  int nlogl=0; // number of samples used in logl
961  int pc = 0;
962  int ipc = double(nIFO*wREC[0][0].size())/10.; if(ipc==0) ipc=1;
963 
964  float l90_dof,u90_dof;
965  if(gOPT.logl_enabled && gOPT.plot_type=="spectrum") {
966  int *index = new int[gEVENTS];
967  TMath::Sort(gEVENTS,wDOF,index,false);
968  int il90 = (gEVENTS*5.)/100.; if(il90>=gEVENTS) il90=gEVENTS-1;
969  int iu90 = (gEVENTS*95.)/100.; if(iu90>=gEVENTS) iu90=gEVENTS-1;
970  l90_dof = wDOF[index[il90]];
971  u90_dof = wDOF[index[iu90]];
972  }
973 
974  // compute vMED, vL50, vU50, vL90, vU90, vL99, vU99
982  for(int n=0;n<nIFO;n++) {
983  wmed[n] = wREC[0][n]; wmed[n] = 0;
984  wl50[n] = wREC[0][n]; wl50[n] = 0;
985  wu50[n] = wREC[0][n]; wu50[n] = 0;
986  wl90[n] = wREC[0][n]; wl90[n] = 0;
987  wu90[n] = wREC[0][n]; wu90[n] = 0;
988  wl99[n] = wREC[0][n]; wl99[n] = 0;
989  wu99[n] = wREC[0][n]; wu99[n] = 0;
990 
991  int nentries = selected; // number of detected events in the offsource
992  int *index = new int[nentries];
993  double *value = new double[nentries];
994  for(int j=0;j<wREC[0][n].size();j++) {
995  if(gOPT.residuals) {
996  int k=0; for(int i=0;i<gEVENTS;i++) if(wNUL[i][n].size()) value[k++] = wNUL[i][n][j]; // select detected events
997  } else {
998  int k=0; for(int i=0;i<gEVENTS;i++) if(wREC[i][n].size()) value[k++] = wREC[i][n][j]; // select detected events
999  }
1000  TMath::Sort(nentries,value,index,false);
1001 
1002  int imed = (nentries*50.)/100.; if(imed>=nentries) imed=nentries-1;
1003  wmed[n][j] = value[index[imed]];
1004 
1005  int il50 = (nentries*25.)/100.; if(il50>=nentries) il50=nentries-1;
1006  int iu50 = (nentries*75.)/100.; if(iu50>=nentries) iu50=nentries-1;
1007  int il90 = (nentries*5.)/100.; if(il90>=nentries) il90=nentries-1;
1008  int iu90 = (nentries*95.)/100.; if(iu90>=nentries) iu90=nentries-1;
1009  int il99 = (nentries*0.5)/100.; if(il99>=nentries) il99=nentries-1;
1010  int iu99 = (nentries*99.5)/100.; if(iu99>=nentries) iu99=nentries-1;
1011 
1012  double med = wmed[n][j];
1013  double l50 = value[index[il50]];
1014  double u50 = value[index[iu50]];
1015  double l90 = value[index[il90]];
1016  double u90 = value[index[iu90]];
1017  double l99 = value[index[il99]];
1018  double u99 = value[index[iu99]];
1019 
1020  bool check=true;
1021  if(!(l50<=u50)) check=false;
1022  if(!(l90<=u90)) check=false;
1023  if(!(l99<=u99)) check=false;
1024  if(!(med>=l50 && med<=u50)) check=false;
1025  if(!(med>=l90 && med<=u90)) check=false;
1026  if(!(med>=l99 && med<=u99)) check=false;
1027  if(!check) {cout << "ComputeWaveformCR : standard wrong median, lower, upper bound !!! " << l50 << " " << med << " " << u50 << endl;}
1028  if(!(med>=l50 && med<=u50)) med=l50;
1029  wmed[n][j]=med;
1030 
1031  wl50[n][j] = fabs(med-l50);
1032  wu50[n][j] = fabs(u50-med);
1033  wl90[n][j] = fabs(med-l90);
1034  wu90[n][j] = fabs(u90-med);
1035  wl99[n][j] = fabs(med-l99);
1036  wu99[n][j] = fabs(u99-med);
1037 
1038  // compute log likelihood used for the the computation of bayes factor
1039  if(gOPT.logl_enabled && gOPT.plot_type=="spectrum") {
1040  int ifo_mask=1<<4*n;
1041  if(!(gOPT.logl_ifo_mask&ifo_mask)) continue; // select ifos
1042  double freq = j/vREC[n].rate();
1043  if((n*wREC[0][n].size()+j)%ipc==0) {cout << pc<<"%";if (pc<100) cout << " - ";pc+=10;cout.flush();}
1044  if(vREC[n][j]/vREC[n].max() < gOPT.logl_arthr) continue; // skip frequency bin if too small
1045  if(freq>gOPT.logl_flow && freq<gOPT.logl_fhigh && j%gOPT.logl_resample==0) {
1046  double xmin=value[index[0]];
1047  double xmax=value[index[nentries-1]];
1048 #ifdef LOGL_TEST_KDE
1049  cout << j << " freq = " << freq << " vREC = " << vREC[n][j] << " vREC[n][j]/vREC[n].max() = " << vREC[n][j]/vREC[n].max() << endl;
1050  TCanvas* clogl = NULL;
1051  TH1D* hprob = NULL;
1052  if(j==LOGL_TEST_KDE) {
1053  clogl = new TCanvas();
1054  double dbin = (u90-l90)/(nentries/40.);
1055  int nbins = (xmax-xmin)/dbin;
1056  hprob = new TH1D("hprob","",nbins,xmin,xmax);
1057  for(int i=0;i<nentries;i++) hprob->Fill(value[i]); // fill histogram
1058  hprob->SetLineColor(kBlue);
1059  hprob->Draw();
1060  hprob->Scale(1./hprob->Integral(),"width" );
1061  }
1062  // smooth probability distribution with kernel density estimation
1063  double rho = 1.0; //default value
1064  TKDE * kde = new TKDE(nentries, value, xmin, xmax, "", rho);
1065  if(j==LOGL_TEST_KDE) {
1066  //kde->Draw("ConfidenceInterval@0.95 Same");
1067  kde->GetFunction()->SetLineColor(kRed);
1068  kde->Draw("SAME");
1069  clogl->SetLogx();
1070  clogl->SetLogy();
1071  clogl->Print("prob_distr_for_logl.png");
1072  exit(0);
1073  }
1074  // get the probability of the on-source reconstructed event
1075  double prob = kde->GetValue(vREC[n][j]);
1076  delete kde;
1077  if(hprob!=NULL) delete hprob;
1078  if(clogl!=NULL) delete clogl;
1079 #else
1080 #ifdef LOGL_USE_KDE
1081  // smooth probability distribution with kernel density estimation
1082  double rho = 1.0; //default value
1083  TKDE * kde = new TKDE(nentries, value, xmin, xmax, "", rho);
1084  // get the probability of the on-source reconstructed event
1085 /*
1086  double x = vREC[n][j];
1087  if(x<l90) x=l90;
1088  if(x>u90) x=u90;
1089  double prob = kde->GetValue(x);
1090 */
1091  double prob = kde->GetValue(vREC[n][j]);
1092  delete kde;
1093 #else
1094  double dbin = (u90-l90)/(nentries/40.);
1095  int nbins = (xmax-xmin)/dbin;
1096  TH1D* hprob = new TH1D("hprob","",nbins,xmin,xmax);
1097  for(int i=0;i<nentries;i++) hprob->Fill(value[i]); // fill histogram
1098  hprob->Draw();
1099  hprob->Scale(1./hprob->Integral(),"width" );
1100  int bin = hprob->FindBin(vREC[n][j]);
1101  double prob = hprob->GetBinContent(bin);
1102  delete hprob;
1103 #endif
1104 #endif
1105  if(prob<(1./nentries)) continue; // skip frequency bin if prob is less than available inverse entries
1106  //cout << "logl -> " << j << "/" << n << " freq = " << freq
1107  // << " onsrc/l90 = " << vREC[n][j] << "/" << l90 << " logl = " << log(prob) << endl;
1108  nlogl++;
1109  logl+=log(prob);
1110  if(freq<fmin) fmin=freq;
1111  if(freq>fmax) fmax=freq;
1112  }
1113  }
1114  }
1115  delete [] index;
1116  delete [] value;
1117 
1118  vMED.push_back(wmed[n]);
1119  vL50.push_back(wl50[n]);
1120  vU50.push_back(wu50[n]);
1121  vL90.push_back(wl90[n]);
1122  vU90.push_back(wu90[n]);
1123  vL99.push_back(wl99[n]);
1124  vU99.push_back(wu99[n]);
1125  }
1126 
1127  if(gOPT.logl_enabled && gOPT.plot_type=="spectrum") {
1128  if(pc==100) cout << pc<<"%";
1129  cout << endl << endl;
1130  // dump log likelihood
1131  logl = nlogl>0 ? logl/nlogl : 0; // normalized logl
1132  logl*= vDOF; // multiplied by the on-source degrees of freedom
1133  float l90_logl = l90_dof*logl/vDOF;
1134  float u90_logl = u90_dof*logl/vDOF;
1135  TString parm = TString::Format("log likelihood = %g [%g,%g] ( frequency bins = %d - DoF = %g [%g:%g]) fmin:fmax = %g:%g (Hz)",
1136  logl,l90_logl,u90_logl,vDOF,l90_dof,u90_dof,nlogl,fmin,fmax);
1137  DumpStatistics("spectrum_logl.txt", parm, false);
1138  cout << parm << endl;
1139  }
1140 
1141  // Compute time boundaries which contain the P energy fraction of median
1142 
1143  double P = gOPT.plot_efraction;
1144  double estart, estop;
1145  for(int n=0;n<nIFO;n++) {
1146  double bT, eT;
1147  CWB::mdc::GetTimeBoundaries(vMED[n], P, bT, eT);
1148  if(n==0) {
1149  estart=bT;estop=eT;
1150  } else {
1151  if(bT<estart) estart=bT;
1152  if(eT>estop) estop=eT;
1153  }
1154  }
1155  cout << endl;
1156  cout << "estart=" << estart << "\testop=" << estop << endl;
1157  cout << endl;
1158 
1159  int nstart = (estart-vREC[0].start())*vREC[0].rate();
1160  int nstop = (estop -vREC[0].start())*vREC[0].rate();
1161 
1162  // Compute the effective coverages
1163 
1164  for(int n=0;n<nIFO;n++) {
1165  int n50=0;
1166  int n90=0;
1167  int n99=0;
1168  for(int i=0;i<gEVENTS;i++) {
1169  if(!wREC[i][n].size()) continue; // select detected events
1170  bool b50=false;
1171  bool b90=false;
1172  bool b99=false;
1173  for(int j=nstart;j<nstop;j++) {
1174  double vl50 = vMED[n][j]-fabs(vL50[n][j]);
1175  double vu50 = vMED[n][j]+fabs(vU50[n][j]);
1176  double vl90 = vMED[n][j]-fabs(vL90[n][j]);
1177  double vu90 = vMED[n][j]+fabs(vU90[n][j]);
1178  double vl99 = vMED[n][j]-fabs(vL99[n][j]);
1179  double vu99 = vMED[n][j]+fabs(vU99[n][j]);
1180 
1181  double value = wREC[i][n][j];
1182  if(value<vl50 || value>vu50) b50=true;
1183  if(value<vl90 || value>vu90) b90=true;
1184  if(value<vl99 || value>vu99) b99=true;
1185  }
1186  if(b50) n50++;
1187  if(b90) n90++;
1188  if(b99) n99++;
1189  }
1190  cout << endl;
1191  cout << "IFO " << gIFO[n] << "\tEffective Coverage at 50% = " << int(100.-100.*n50/(double)selected) << endl;
1192  cout << "IFO " << gIFO[n] << "\tEffective Coverage at 90% = " << int(100.-100.*n90/(double)selected) << endl;
1193  cout << "IFO " << gIFO[n] << "\tEffective Coverage at 99% = " << int(100.-100.*n99/(double)selected) << endl;
1194  cout << endl;
1195  }
1196 
1197  return selected;
1198 }
1199 
1200 void LoadOutputRootFiles(int nIFO, TString data_label, TString output_dir, int max_events, double ifar_thr) {
1201 
1202  if(ifar_thr<=0) ifar_thr=-1e-10; // force all events which do not pass the PP cuts to be removed
1203 
1204  gEVENTS=0;
1205 
1206  char beginString[1024];
1207  sprintf(beginString,"wave_");
1208  char endString[1024];
1209  sprintf(endString,".root");
1210  char containString[1024];
1211  sprintf(containString,"%s",data_label.Data());
1212 
1213  vector<TString> fileList = CWB::Toolbox::getFileListFromDir(output_dir, endString, beginString, containString);
1214 
1215  wavearray<double>* sample_wREC[NIFO_MAX];
1216  for(int i=0;i<nIFO;i++) sample_wREC[i] = new wavearray<double>;
1217  wavearray<double>* sample_wNUL[NIFO_MAX];
1218  if(gOPT.residuals) for(int i=0;i<nIFO;i++) sample_wNUL[i] = new wavearray<double>;
1219  wavearray<double>* sample_wINJ[NIFO_MAX];
1220  for(int i=0;i<nIFO;i++) sample_wINJ[i] = new wavearray<double>;
1221  wavearray<double>* sample_wAUX[NIFO_MAX];
1222  if(gOPT.side=="rcut") for(int i=0;i<nIFO;i++) sample_wAUX[i] = new wavearray<double>;
1223  int ndim;
1224  double* time = new double[2*nIFO];
1225  float* sSNR = new float[nIFO];
1226  int* size = new int[nIFO];
1227  float norm;
1228  float theta[4];
1229  float phi[4];
1230  float ifar=0;
1231  float likelihood;
1232  float factor;
1233  double tcoa=-1; // geocentric tcoa
1234  string* log = new string; // injection log
1235 
1236  TBranch* branch;
1237  bool ifar_exists=false;
1238  bool tcoa_exists=false;
1239  bool vnul_exists=false;
1240  bool vaux_exists=false;
1241 
1242  bool efound=false;
1243  char command[1024];
1244  int nfile = fileList.size();
1245  int nevt=0;
1246  for(int n=0;n<nfile;n++) {
1247  cout << n << " " << fileList[n].Data() << endl;
1248 
1249  TFile* froot = new TFile(fileList[n].Data(),"READ");
1250  if(froot==NULL) {
1251  cout << "LoadOutputRootFiles - Error : Failed to open file : " << fileList[n].Data() << endl;
1252  gSystem->Exit(1);
1253  }
1254  TTree* itree = (TTree*)froot->Get("waveburst");
1255  if(itree==NULL) {
1256  cout << "LoadOutputRootFiles - Error : Failed to open tree waveburst from file : " << fileList[n].Data() << endl;
1257  //continue;
1258  gSystem->Exit(1);
1259  }
1260 
1261  ifar_exists=false;
1262  TIter ifar_next(itree->GetListOfBranches());
1263  while ((branch=(TBranch*)ifar_next())) {
1264  if(TString("ifar").CompareTo(branch->GetName())==0) ifar_exists=true;
1265  }
1266  ifar_next.Reset();
1267 
1268  tcoa_exists=false;
1269  TIter tcoa_next(itree->GetListOfBranches());
1270  while ((branch=(TBranch*)tcoa_next())) {
1271  if(TString("wf_tcoa").CompareTo(branch->GetName())==0) tcoa_exists=true;
1272  }
1273  tcoa_next.Reset();
1274 
1275  vnul_exists=false;
1276  vaux_exists=false;
1277  TIter vnul_next(itree->GetListOfBranches());
1278  while ((branch=(TBranch*)vnul_next())) {
1279  if(TString("wNUL_0").CompareTo(branch->GetName())==0) vnul_exists=true;
1280  if(TString("wAUX_0").CompareTo(branch->GetName())==0) vaux_exists=true;
1281  }
1282  if(!vnul_exists) gOPT.residuals=false; // disable residuals
1283  vnul_next.Reset();
1284  if(gOPT.side=="rcut" && !vaux_exists) {
1285  cout << "LoadOutputRootFiles - Error : auxiliary injection do not exist!" << endl;
1286  cout << " with option side=rcut must be provided the auxiliary injections" << endl;
1287  gSystem->Exit(1);
1288  }
1289 
1290  for(int k=0;k<itree->GetEntries();k++) {
1291 
1292  if(k%100==0) cout << "ENTRY = " << k << " / " << itree->GetEntries() << endl;
1293  if(!(nevt<max_events || fileList[n].Contains("job0.root"))) continue;
1294 
1295  // check if user input nIFO is consistent with the ndim read from the root file
1296  itree->SetBranchAddress("ndim",&ndim);
1297  itree->GetEntry(k);
1298  if(ndim!=nIFO) {
1299  cout << "LoadOutputRootFiles - Error : number of ifos=" << ndim
1300  << " declared in the output root files is different from the user declared value " << nIFO << endl;
1301  cout << endl << "Use NIFO=" << ndim << " or check file; " << endl << endl << fileList[n] << endl << endl;
1302  gSystem->Exit(1);
1303  }
1304 
1305  for(int i=0;i<nIFO;i++) itree->SetBranchAddress(TString::Format("wREC_%d",i).Data(),&sample_wREC[i]);
1306  if(gOPT.residuals) {
1307  for(int i=0;i<nIFO;i++) itree->SetBranchAddress(TString::Format("wNUL_%d",i).Data(),&sample_wNUL[i]);
1308  }
1309  for(int i=0;i<nIFO;i++) itree->SetBranchAddress(TString::Format("wINJ_%d",i).Data(),&sample_wINJ[i]);
1310  if(gOPT.side=="rcut") {
1311  for(int i=0;i<nIFO;i++) itree->SetBranchAddress(TString::Format("wAUX_%d",i).Data(),&sample_wAUX[i]);
1312  }
1313  itree->SetBranchAddress("time",time);
1314  itree->SetBranchAddress("sSNR",sSNR);
1315  itree->SetBranchAddress("size",size);
1316  itree->SetBranchAddress("norm",&norm);
1317  itree->SetBranchAddress("theta",theta);
1318  itree->SetBranchAddress("phi",phi);
1319  itree->SetBranchAddress("likelihood",&likelihood);
1320  itree->SetBranchAddress("factor",&factor);
1321  itree->SetBranchAddress("log",&log);
1322  if(ifar_exists) itree->SetBranchAddress("ifar",&ifar);
1323  if(tcoa_exists) itree->SetBranchAddress("wf_tcoa",&tcoa);
1324  else if(gOPT.side!="full") {
1325  cout << endl << "LoadOutputRootFiles - Error : wf_tcoa not found, side!=full requires tcoa" << endl << endl;
1326  gSystem->Exit(1);
1327  }
1328 
1329  itree->GetEntry(k); // read wREC,skyprob objects
1330 
1331  ifar/=(24.*3600.*365.); // sec -> year
1332 
1333  bool onsource=false;
1334  if(fabs(gOPT.gps_event-time[0])<gOPT.gps_error) onsource=true;
1335  if(!onsource && ifar<ifar_thr) continue; // skip offsource events below the ifar threshold
1336 
1337  bool fail=false;
1338 
1339  // check if objects are not null
1340  for(int i=0;i<nIFO;i++) {
1341  if(sample_wREC[i]==NULL) {
1342  cout << "LoadOutputRootFiles - Error : Object wavearray not exist !!! " << endl;
1343  //gSystem->Exit(1);
1344  fail=true;
1345  }
1346  }
1347  if(fail) continue;
1348 
1349  tcoa+=gOPT.tcoa_shift; // apply time shift to tcoa
1350 
1351  // fill object vectors
1352  cout.precision(14);
1353  if(fabs(gOPT.gps_event-time[0])<gOPT.gps_error && fileList[n].Contains("_job0.root")) { // OnSource
1354  vTCOA=tcoa; // store OnSource sample geoacentric tcoa
1355  vFACTOR=factor; // store OnSource factor
1356  vTHETA=theta[1]; // store OnSource sample theta
1357  vPHI=phi[1]; // store OnSource sample phi
1358  vDOF= norm>0?size[0]/norm:0.; // store OnSource degrees of freedom
1359  TString m1 = GetParameterFromInjLog(log->c_str(), "mass1"); // get mass1 from injection parameters
1360  TString m2 = GetParameterFromInjLog(log->c_str(), "mass2"); // get mass2 from injection parameters
1361  vM1=m1.Atof(); // store OnSource sample m1
1362  vM2=m2.Atof(); // store OnSource sample m2
1363  TString s1 = GetParameterFromInjLog(log->c_str(), "spin1"); // get spin1z from injection parameters
1364  TString s2 = GetParameterFromInjLog(log->c_str(), "spin2"); // get spin2z from injection parameters
1365  vS1=s1.Atof(); // store OnSource sample s1
1366  vS2=s2.Atof(); // store OnSource sample s2
1367  for(int i=0;i<nIFO;i++) vSNR[i]=sqrt(sSNR[i]); // store OnSource SNR
1368  efound=true;
1369  vTREC.resize(nIFO);
1370  for(int i=0;i<nIFO;i++) {
1371  if(gOPT.side=="rcut") {
1372  CWB::mdc::Align(*sample_wAUX[i], *sample_wREC[i]); // align onsource aux wrt rec
1373  sample_wAUX[i]->start(fmod(sample_wAUX[i]->start(),gOPT.inj_time_step));
1374  vAUX.push_back(*sample_wAUX[i]); // store reconstructed null event waveform
1375  }
1376  CWB::mdc::Align(*sample_wINJ[i], *sample_wREC[i]); // align onsource inj wrt rec
1377  sample_wINJ[i]->start(fmod(sample_wINJ[i]->start(),gOPT.inj_time_step));
1378  vINJ.push_back(*sample_wINJ[i]); // store whitened injected waveform
1379  vTREC[i]=sample_wREC[i]->start(); // save absolute start time
1380  sample_wREC[i]->start(fmod(sample_wREC[i]->start(),gOPT.inj_time_step));
1381  vREC.push_back(*sample_wREC[i]); // store reconstructed event waveform
1382  if(gOPT.residuals) {
1383  sample_wNUL[i]->start(fmod(sample_wNUL[i]->start(),gOPT.inj_time_step));
1384  vNUL.push_back(*sample_wNUL[i]); // store reconstructed null event waveform
1385  }
1386  }
1387  double toff = gOPT.inj_time_step-int(fmod(gOPT.gps_event,gOPT.inj_time_step))-gOPT.off_event;
1388  cout << "EVENT FOUND @ GPS time -> " << time[0] << "\tSNR -> " << sqrt(likelihood) << "\tIFAR -> " << ifar << " yrs" << " toff -> " << toff << endl;
1389  cout << endl;
1390  cout << " File -> " << fileList[n] << endl << endl;
1391  for(int i=0;i<nIFO;i++) vREC[i].start(int(vREC[i].start()+toff)%gOPT.inj_time_step);
1392  for(int i=0;i<nIFO;i++) vINJ[i].start(int(vINJ[i].start()+toff)%gOPT.inj_time_step);
1393  if(gOPT.residuals) {
1394  for(int i=0;i<nIFO;i++) vNUL[i].start(int(vNUL[i].start()+toff)%gOPT.inj_time_step);
1395  }
1396  if(gOPT.side=="rcut") {
1397  for(int i=0;i<nIFO;i++) vAUX[i].start(int(vAUX[i].start()+toff)%gOPT.inj_time_step);
1398  }
1399 
1400  // read ifo names from the tree user list and updated gIFO global array according to the input data network setup
1401  TList* ifoList = itree->GetUserInfo();
1402  detectorParams dParams[NIFO_MAX];
1403  for (int i=0;i<ifoList->GetSize();i++) {
1404  detector* pDetector = (detector*)ifoList->At(i);
1405  dParams[i] = pDetector->getDetectorParams();
1406  gIFO[i] = dParams[i].name;
1407  }
1408 
1409  } else { // OffSource
1410  wTCOA[gEVENTS]=tcoa; // store injected geocentric tcoa
1411  wFACTOR[gEVENTS]=factor; // store injected factor
1412  wTHETA[gEVENTS]=theta[1]; // store injected theta
1413  wPHI[gEVENTS]=phi[1]; // store injected phi
1414  wDOF[gEVENTS]= norm>0?size[0]/norm:0.; // store injected degrees of freedom
1415  TString m1 = GetParameterFromInjLog(log->c_str(), "mass1");
1416  TString m2 = GetParameterFromInjLog(log->c_str(), "mass2");
1417  wM1[gEVENTS]=m1.Atof(); // store injected m1
1418  wM2[gEVENTS]=m2.Atof(); // store injected m2
1419  TString s1 = GetParameterFromInjLog(log->c_str(), "spin1");
1420  TString s2 = GetParameterFromInjLog(log->c_str(), "spin2");
1421  wS1[gEVENTS]=s1.Atof(); // store injected s1
1422  wS2[gEVENTS]=s2.Atof(); // store injected s2
1423  for(int i=0;i<nIFO;i++) wSNR[gEVENTS][i]=sqrt(sSNR[i]); // store reconstructed SNR
1424  for(int i=0;i<nIFO;i++) {
1425  double toff=0;
1426  if(gOPT.inj_onsrc) {
1427  toff = gOPT.inj_time_step-int(fmod(gOPT.gps_event,gOPT.inj_time_step))-gOPT.off_event;
1428  }
1429  sample_wREC[i]->start(fmod(sample_wREC[i]->start()+toff,gOPT.inj_time_step));
1430  wREC[gEVENTS].push_back(*sample_wREC[i]); // store reconstructed posterior sample waveform
1431  sample_wINJ[i]->start(fmod(sample_wINJ[i]->start()+toff,gOPT.inj_time_step));
1432  wINJ[gEVENTS].push_back(*sample_wINJ[i]); // store whitened posterior sample waveform
1433  if(gOPT.residuals) {
1434  sample_wNUL[i]->start(fmod(sample_wNUL[i]->start()+toff,gOPT.inj_time_step));
1435  wNUL[gEVENTS].push_back(*sample_wNUL[i]); // store reconstructed null posterior sample waveform
1436  }
1437  if(gOPT.side=="rcut") {
1438  sample_wAUX[i]->start(fmod(sample_wAUX[i]->start()+toff,gOPT.inj_time_step));
1439  wAUX[gEVENTS].push_back(*sample_wAUX[i]); // store reconstructed null posterior sample waveform
1440  }
1441  }
1442  gEVENTS++;
1443  }
1444 
1445  if(gEVENTS>=PE_MAX_EVENTS) {
1446  cout << "LoadOutputRootFiles - Warning : Number of events > PE_MAX_EVENTS !!! " << PE_MAX_EVENTS << endl;
1447  break;
1448  }
1449 
1450  nevt++;
1451  }
1452 
1453  froot->Close();
1454  }
1455 
1456  if(vREC.size()!=nIFO || vINJ.size()!=nIFO) {
1457  cout << "LoadOutputRootFiles - Error : Number of OnSource Events = " << vREC.size()/nIFO << " -> must be 1" << endl;
1458  cout << " check the onsrc links in the ofsrc merge directory " << endl;
1459  cout << " check the onsrc event time " << endl;
1460  exit(1);
1461  }
1462 
1463  if(gEVENTS==0) {
1464  cout << "LoadOutputRootFiles - Error : Found 0 OffSource Events !!! " << endl;
1465  exit(1);
1466  }
1467 
1468 
1469  if(!efound) {
1470  cout << "LoadOutputRootFiles - Error : GPS EVENT NOT FOUND !!! " << endl;
1471  cout << endl;
1472  cout << "Possible reasons:" << endl;
1473  cout << endl;
1474  cout << "1) The root file with EVENT has not been included" << endl;
1475  cout << "2) gps_error is too rectrictive, current value is " << gOPT.gps_error << " , try a new value with option --gps_error=... " << endl;
1476  cout << endl;
1477  gSystem->Exit(1);
1478  }
1479 
1480  double toffset = wREC[0][0].start()-vREC[0].start();
1481  if(toffset!=0) {
1482  cout << endl;
1483  cout << "LoadOutputRootFiles - Warning : detected event and posterios have a possible inconsistent GPS time" << endl;
1484  cout << " check the detected event root file" << endl;
1485  cout << " try --off_event=" << gOPT.off_event-toffset << endl;
1486  cout << endl;
1487 // gSystem->Exit(1);
1488  }
1489 
1490  for(int i=0;i<nIFO;i++) delete sample_wREC[i];
1491  if(gOPT.residuals) for(int i=0;i<nIFO;i++) delete sample_wNUL[i];
1492  if(gOPT.side=="rcut") for(int i=0;i<nIFO;i++) delete sample_wAUX[i];
1493  if(gOPT.statistics) for(int i=0;i<nIFO;i++) delete sample_wINJ[i];
1494  delete [] time;
1495  delete log;
1496 }
1497 
1499 
1500  gnetwork* NET = new gnetwork(nIFO,gIFO);
1501 
1502  TString ifar_thr_label = TString::Format("%g",gOPT.ifar_thr).ReplaceAll(".","d");
1503  TString ncycles_label = TString::Format("%d",gOPT.ncycles);
1504 
1505  TString type_label = "";
1506  type_label += "ifar_"+ifar_thr_label;
1507  if(gOPT.plot_type=="phase") type_label+="_Phase";
1508  if(gOPT.plot_type=="time") type_label+="_Time";
1509  if(gOPT.plot_type=="envelope") type_label+="_Envelope";
1510  if(gOPT.plot_type=="frequency") type_label+="_Frequency";
1511  if(gOPT.plot_type=="spectrum") type_label+="_Spectrum";
1512 
1513  TString pdir=gOPT.plot_odir;
1514  char title[256]; char ofname[256];
1515  for(int n=0; n<nIFO; n++) {
1516  if(gOPT.plot_99perc) {
1517  sprintf(title,"%s (ifar=%sy) : cWB REC (red) - Errors (entries=%d) : med (black) : 50% (dark_grey) : 90% (medium gray) : 99% (light_gray)",
1518  gIFO[n].Data(),ifar_thr_label.Data(),gEVENTS);
1519  } else {
1520  sprintf(title,"%s (ifar=%sy) : cWB REC (red) - Errors (entries=%d) : med (black) : 50% (dark_grey) : 90% (light gray)",
1521  gIFO[n].Data(),ifar_thr_label.Data(),gEVENTS);
1522  }
1523 
1524  int K = (gOPT.plot_type=="spectrum" || gOPT.plot_type=="phase") ? 1 : 3;
1525  for(int k=0;k<K;k++) { // plot at 3 different time zooms
1526  // get tcoa of vINJ[n] after time/phase sync
1527  double tcoa = GetInjTcoa(vTCOA, NET, gIFO[n], vTHETA, vPHI);
1528  tcoa = tcoa-vTREC[n]+vREC[n].start();
1529  if(gOPT.sync_phase || gOPT.sync_time) {
1530  tcoa = GetSyncTcoa(vINJ[n], vTSYNC[n], vPSYNC[n], tcoa);
1531  }
1532  // get time of max abs(amp) waveform envelope
1533  double tmax=tcoa;
1534  if(gOPT.plot_type=="time" || gOPT.plot_type=="envelope" || gOPT.plot_type=="frequency") {
1535  wavearray<double> wenv = CWB::mdc::GetEnvelope(&vMED[n]);
1536  double amax=0;
1537  for(int i=0;i<wenv.size();i++) if(fabs(wenv[i])>amax) {amax=fabs(wenv[i]);tmax=wenv.start()+i/wenv.rate();}
1538  }
1539  double tref = (tcoa>tmax) ? tcoa : tmax; // time used as reference to zoom the waveform
1540  double P=1;
1541  TString zoom; // the A/B/C characters are use to sort the plots when cwb_mkhtml is used
1542  if(k==0) {P=0.65/gOPT.plot_zoom; if(P>1) P=1; zoom = TString::Format("C%d",int(P*100));}
1543  if(k==1) {P=0.85/gOPT.plot_zoom; if(P>1) P=1; zoom = TString::Format("B%d",int(P*100));}
1544  if(k==2) {P=0.99/gOPT.plot_zoom; if(P>1) P=1; zoom = TString::Format("A%d",int(P*100));}
1545  double Q=P+0.5*(1-P); // increases the time range on the right side
1546  if(gOPT.plot_type=="spectrum" || gOPT.plot_type=="phase") zoom="A";
1547  sprintf(ofname,"%s_%s_%s_%s.%s",gIFO[n].Data(),gOPT.plot_fname.Data(), type_label.Data(), zoom.Data(), "png");
1548  if(gOPT.residuals) {
1549  PlotWaveformAsymmErrors(ofname, title, vNUL[n], vMED[n], vL50[n], vU50[n], vL90[n], vU90[n], vL99[n], vU99[n], vNUL[n], pdir, P, Q, tref, tcoa, n);
1550  } else {
1551  PlotWaveformAsymmErrors(ofname, title, vREC[n], vMED[n], vL50[n], vU50[n], vL90[n], vU90[n], vL99[n], vU99[n], vREC[n], pdir, P, Q, tref, tcoa, n);
1552  }
1553  }
1554  }
1555 }
1556 
1561  TString pdir, double P, double Q, double tref, double tcoa, int ifoid) {
1562 
1563  // resample data to increase the plot resolution
1564  if(gOPT.plot_type=="time") {
1565  wrec.Resample(16384);
1566  wmed.Resample(16384);
1567  wl50.Resample(16384);
1568  wu50.Resample(16384);
1569  wl90.Resample(16384);
1570  wu90.Resample(16384);
1571  wl99.Resample(16384);
1572  wu99.Resample(16384);
1573  wref.Resample(16384);
1574  }
1575 
1576  int size = wrec.size();
1577 
1578  wavearray<double> x(size);
1579  wavearray<double> ex(size); ex=0;
1580  if(gOPT.plot_type=="spectrum") {
1581  for (int i=0; i<size; i++) x[i] = i/wrec.rate();
1582  } else if(gOPT.plot_type=="phase") {
1583  for (int i=0; i<size; i++) x[i] = i;
1584  } else {
1585  for (int i=0; i<size; i++) x[i] = i/wrec.rate()+(wref.start());
1586  }
1587 
1588  TString xtitle;
1589  if(gOPT.plot_type=="phase") xtitle = "Phase (cycles)";
1590  if(gOPT.plot_type=="envelope") xtitle = TString::Format("Time Envelope (sec) : GPS OFFSET = %d",int(gOPT.gps_event-gOPT.inj_time_step));
1591  if(gOPT.plot_type=="time") xtitle = TString::Format("Time (sec) : GPS OFFSET = %d",int(gOPT.gps_event-gOPT.inj_time_step));
1592  if(gOPT.plot_type=="frequency") xtitle = TString::Format("Time Frequency (sec) : GPS OFFSET = %d",int(gOPT.gps_event-gOPT.inj_time_step));
1593  if(gOPT.plot_type=="spectrum") xtitle = "Frequency (Hz)";
1594 
1595  TGraphAsymmErrors* egr99 = new TGraphAsymmErrors(size,x.data,wmed.data,ex.data,ex.data,wl99.data,wu99.data);
1596  egr99->SetLineColor(18);
1597  egr99->SetFillStyle(1001);
1598  egr99->SetFillColor(18);
1599  egr99->GetXaxis()->SetTitle(xtitle);
1600  if(gOPT.plot_type=="phase") egr99->GetYaxis()->SetTitle("degrees");
1601  if(gOPT.plot_type=="envelope") egr99->GetYaxis()->SetTitle("magnitude");
1602  if(gOPT.plot_type=="time") egr99->GetYaxis()->SetTitle("magnitude");
1603  if(gOPT.plot_type=="frequency") egr99->GetYaxis()->SetTitle("Hz");
1604  if(gOPT.plot_type=="spectrum") egr99->GetYaxis()->SetTitle("magnitude");
1605  egr99->SetTitle(title);
1606  egr99->GetXaxis()->SetTitleFont(42);
1607  egr99->GetXaxis()->SetLabelFont(42);
1608  egr99->GetXaxis()->SetLabelOffset(0.012);
1609  egr99->GetXaxis()->SetTitleOffset(1.5);
1610  egr99->GetYaxis()->SetTitleFont(42);
1611  egr99->GetYaxis()->SetLabelFont(42);
1612  egr99->GetYaxis()->SetLabelOffset(0.01);
1613  egr99->GetYaxis()->SetTitleOffset(1.4);
1614 
1615  TGraphAsymmErrors* egr90 = new TGraphAsymmErrors(size,x.data,wmed.data,ex.data,ex.data,wl90.data,wu90.data);
1616  egr90->SetLineColor(17);
1617  egr90->SetFillStyle(1001);
1618  egr90->SetFillColor(17);
1619  egr90->GetXaxis()->SetTitle(xtitle);
1620  if(gOPT.plot_type=="phase") egr90->GetYaxis()->SetTitle("degrees");
1621  if(gOPT.plot_type=="envelope") egr90->GetYaxis()->SetTitle("magnitude");
1622  if(gOPT.plot_type=="time") egr90->GetYaxis()->SetTitle("magnitude");
1623  if(gOPT.plot_type=="frequency") egr90->GetYaxis()->SetTitle("Hz");
1624  if(gOPT.plot_type=="spectrum") egr90->GetYaxis()->SetTitle("magnitude");
1625  egr90->SetTitle(title);
1626  egr90->GetXaxis()->SetTitleFont(42);
1627  egr90->GetXaxis()->SetLabelFont(42);
1628  egr90->GetXaxis()->SetLabelOffset(0.012);
1629  egr90->GetXaxis()->SetTitleOffset(1.5);
1630  egr90->GetYaxis()->SetTitleFont(42);
1631  egr90->GetYaxis()->SetLabelFont(42);
1632  egr90->GetYaxis()->SetLabelOffset(0.01);
1633  egr90->GetYaxis()->SetTitleOffset(1.4);
1634 
1635  TGraphAsymmErrors* egr50 = new TGraphAsymmErrors(size,x.data,wmed.data,ex.data,ex.data,wl50.data,wu50.data);
1636  egr50->SetLineColor(15);
1637  egr50->SetFillStyle(1001);
1638  egr50->SetFillColor(15);
1639 
1640  TGraph* agr = new TGraph(size,x.data,wmed.data);
1641  agr->SetLineWidth(1);
1642  agr->SetLineColor(kBlack);
1643  agr->SetLineStyle(1);
1644 
1645  TGraph* gr = new TGraph(size,x.data,wrec.data);
1646  gr->SetLineWidth(1);
1647  gr->SetLineColor(2);
1648 
1649  TCanvas* canvas = new TCanvas("wave_pe_cwb","wave_pe_cwb",200,20,800,500);
1650  canvas->cd();
1651  canvas->SetGridx();
1652  canvas->SetGridy();
1653  if(gOPT.plot_type=="spectrum") {
1654  canvas->SetLogx();
1655  canvas->SetLogy();
1656  }
1657 
1658  if(gOPT.plot_type=="time" || gOPT.plot_type=="envelope" || gOPT.plot_type=="frequency") {
1659  double bT, eT;
1660  wavearray<double> W=wmed; W+=wu99; W+=wref; // the 99% belt + wref is used to compute the boundaries
1661  CWB::mdc::GetTimeBoundaries(W, P, bT, eT, tref, Q);
1662  if(gOPT.plot_99perc) egr99->GetXaxis()->SetRangeUser(bT, eT);
1663  else egr90->GetXaxis()->SetRangeUser(bT, eT);
1664  }
1665  if(gOPT.plot_type=="spectrum") {
1666  if(gOPT.plot_99perc) egr99->GetYaxis()->SetRangeUser(1e-3, 1.5 * egr99->GetHistogram()->GetMaximum());
1667  else egr90->GetYaxis()->SetRangeUser(1e-3, 1.5 * egr90->GetHistogram()->GetMaximum());
1668  if(gOPT.plot_99perc) egr99->GetXaxis()->SetRangeUser(20, wrec.size()/wrec.rate());
1669  else egr90->GetXaxis()->SetRangeUser(20, wrec.size()/wrec.rate());
1670  }
1671 
1672  if(gOPT.plot_99perc) {
1673  egr99->Draw("A3");
1674  egr90->Draw("3same");
1675  } else {
1676  egr90->Draw("A3");
1677  }
1678  egr50->Draw("3same");
1679  agr->Draw("Lsame");
1680  gr->Draw("Lsame");
1681 
1682  // add vertical green line at tcoa time
1683  TGraph* grline = NULL;
1684  if(gOPT.plot_type=="time" || gOPT.plot_type=="envelope" || gOPT.plot_type=="frequency") {
1685  wavearray<double> wline = wrec;
1686  double dt=1./wline.rate();
1687  bool bline=false;
1688  for(int i=0;i<wline.size();i++) {
1689  double time=i*dt+wline.start();
1690  if(fabs(time-tcoa)<dt && !bline) {
1691  if(gOPT.plot_type=="time") wline[i]=-1.0;
1692  if(gOPT.plot_type=="envelope") wline[i]= 0.0;
1693  if(gOPT.plot_type=="frequency") wline[i]= 0.0;
1694  bline=true;
1695  } else wline[i]=-1000.;
1696  }
1697  grline = new TGraph(size,x.data,wline.data);
1698  grline->SetLineWidth(1);
1699  grline->SetLineColor(kGreen);
1700  grline->Draw("Lsame");
1701  }
1702 
1703  TGraph* grpfrq = NULL;
1704  TGraph* grpsnr = NULL;
1705  if(gOPT.plot_type=="phase") {
1706 
1707  grpsnr = new TGraph(x.size(),x.data,pSNR[ifoid].data);
1708  grpsnr->SetLineWidth(1);
1709  grpsnr->SetLineColor(kBlue);
1710  grpsnr->Draw("Lsame");
1711 
1712  grpfrq = new TGraph(x.size(),x.data,pFRQ[ifoid].data);
1713  grpfrq->SetLineWidth(1);
1714  grpfrq->SetLineColor(kGreen);
1715  grpfrq->Draw("Lsame");
1716 
1717  if(gOPT.plot_99perc) egr99->GetXaxis()->SetRangeUser(0, gOPT.ncycles);
1718  else egr90->GetXaxis()->SetRangeUser(0, gOPT.ncycles);
1719  if(gOPT.plot_99perc) egr99->GetYaxis()->SetRangeUser(-180, 180);
1720  else egr90->GetYaxis()->SetRangeUser(-180, 180);
1721  }
1722 
1723  if(ofname!="") {
1724  TString pfname = pdir!="" ? TString(pdir)+TString("/")+ofname : ofname;
1725  canvas->Print(pfname);
1726  cout << "write : " << pfname << endl;
1727  pfname.ReplaceAll(".png",".root");
1728  canvas->Print(pfname);
1729  cout << "write : " << pfname << endl;
1730  }
1731 
1732  delete canvas;
1733  delete egr50;
1734  delete egr90;
1735  if(gOPT.plot_99perc) delete egr99;
1736  delete agr;
1737  delete gr;
1738  if(grline!=NULL) delete grline;
1739  if(grpfrq!=NULL) delete grpfrq;
1740  if(grpsnr!=NULL) delete grpsnr;
1741 }
1742 
1744 
1745  // get plugin options
1746 
1747  if(TString(options)!="") {
1748 
1749  //cout << "WF options : " << options << endl;
1750  TObjArray* token = TString(options).Tokenize(TString(' '));
1751  for(int j=0;j<token->GetEntries();j++) {
1752 
1753  TObjString* tok = (TObjString*)token->At(j);
1754  TString stok = tok->GetString();
1755  stok.ReplaceAll(" ",""); // remove white spaces
1756  stok.ReplaceAll(" ",""); // remove tabs
1757 
1758  if(stok.Contains("dump_cr=")) {
1759  TString pe_dump_cr=stok;
1760  pe_dump_cr.Remove(0,pe_dump_cr.Last('=')+1);
1761  if(pe_dump_cr=="true") gOPT.dump_cr=true;
1762  if(pe_dump_cr=="false") gOPT.dump_cr=false;
1763  }
1764 
1765  if(stok.Contains("use_onsrc=")) {
1766  TString pe_use_onsrc=stok;
1767  pe_use_onsrc.Remove(0,pe_use_onsrc.Last('=')+1);
1768  if(pe_use_onsrc!="mfull" && pe_use_onsrc!="mleft" && pe_use_onsrc!="efull" && pe_use_onsrc!="eleft") pe_use_onsrc="";
1769  gOPT.use_onsrc=pe_use_onsrc;
1770  }
1771 
1772  if(stok.Contains("sync_phase=")) {
1773  TString pe_sync_phase=stok;
1774  pe_sync_phase.Remove(0,pe_sync_phase.Last('=')+1);
1775  if(pe_sync_phase=="true") gOPT.sync_phase=true;
1776  if(pe_sync_phase=="false") gOPT.sync_phase=false;
1777  }
1778 
1779  if(stok.Contains("sync_time=")) {
1780  TString pe_sync_time=stok;
1781  pe_sync_time.Remove(0,pe_sync_time.Last('=')+1);
1782  if(pe_sync_time=="true") gOPT.sync_time=true;
1783  if(pe_sync_time=="false") gOPT.sync_time=false;
1784  }
1785 
1786  if(stok.Contains("sensitivity=")) {
1787  TString pe_sensitivity=stok;
1788  pe_sensitivity.Remove(0,pe_sensitivity.Last('=')+1);
1789  if(pe_sensitivity=="true") gOPT.sensitivity=true;
1790  if(pe_sensitivity=="false") gOPT.sensitivity=false;
1791  }
1792 
1793  if(stok.Contains("residuals=")) {
1794  TString pe_residuals=stok;
1795  pe_residuals.Remove(0,pe_residuals.Last('=')+1);
1796  if(pe_residuals=="true") gOPT.residuals=true;
1797  if(pe_residuals=="false") gOPT.residuals=false;
1798  }
1799 
1800  if(stok.Contains("statistics=")) {
1801  TString pe_statistics=stok;
1802  pe_statistics.Remove(0,pe_statistics.Last('=')+1);
1803  if(pe_statistics=="true") gOPT.statistics=true;
1804  if(pe_statistics=="false") gOPT.statistics=false;
1805  }
1806 
1807  if(stok.Contains("plot_cr=")) {
1808  TString pe_plot_cr=stok;
1809  pe_plot_cr.Remove(0,pe_plot_cr.Last('=')+1);
1810  if(pe_plot_cr=="true") gOPT.plot_cr=true;
1811  if(pe_plot_cr=="false") gOPT.plot_cr=false;
1812  }
1813 
1814  if(stok.Contains("plot_99perc=")) {
1815  TString pe_plot_99perc=stok;
1816  pe_plot_99perc.Remove(0,pe_plot_99perc.Last('=')+1);
1817  if(pe_plot_99perc=="true") gOPT.plot_99perc=true;
1818  if(pe_plot_99perc=="false") gOPT.plot_99perc=false;
1819  }
1820 
1821  if(stok.Contains("make_ff=")) {
1822  TString pe_make_ff=stok;
1823  pe_make_ff.Remove(0,pe_make_ff.Last('=')+1);
1824  if(pe_make_ff=="true") gOPT.make_ff=true;
1825  if(pe_make_ff=="false") gOPT.make_ff=false;
1826  }
1827 
1828  if(stok.Contains("efraction=")) {
1829  TString pe_efraction=stok;
1830  pe_efraction.Remove(0,pe_efraction.Last('=')+1);
1831  if(pe_efraction.IsFloat()) gOPT.efraction=pe_efraction.Atof();
1832  }
1833 
1834  if(stok.Contains("side=")) {
1835  TString pe_side=stok;
1836  pe_side.Remove(0,pe_side.Last('=')+1);
1837  gOPT.side=pe_side;
1838  }
1839 
1840  if(stok.Contains("coverage=")) {
1841  TString pe_coverage=stok;
1842  pe_coverage.Remove(0,pe_coverage.Last('=')+1);
1843  gOPT.coverage=pe_coverage;
1844  }
1845 
1846  if(stok.Contains("make_of=")) {
1847  TString pe_make_of=stok;
1848  pe_make_of.Remove(0,pe_make_of.Last('=')+1);
1849  if(pe_make_of=="true") gOPT.make_of=true;
1850  if(pe_make_of=="false") gOPT.make_of=false;
1851  }
1852 
1853  if(stok.Contains("make_re=")) {
1854  TString pe_make_re=stok;
1855  pe_make_re.Remove(0,pe_make_re.Last('=')+1);
1856  if(pe_make_re=="true") gOPT.make_re=true;
1857  if(pe_make_re=="false") gOPT.make_re=false;
1858  }
1859 
1860  if(stok.Contains("make_ne=")) {
1861  TString pe_make_ne=stok;
1862  pe_make_ne.Remove(0,pe_make_ne.Last('=')+1);
1863  if(pe_make_ne=="true") gOPT.make_ne=true;
1864  if(pe_make_ne=="false") gOPT.make_ne=false;
1865  }
1866 
1867  if(stok.Contains("make_onsrc=")) {
1868  TString pe_make_onsrc=stok;
1869  pe_make_onsrc.Remove(0,pe_make_onsrc.Last('=')+1);
1870  if(pe_make_onsrc=="true") gOPT.make_onsrc=true;
1871  if(pe_make_onsrc=="false") gOPT.make_onsrc=false;
1872  }
1873 
1874  if(stok.Contains("gw_name=")) {
1875  TString pe_gw_name=stok;
1876  pe_gw_name.Remove(0,pe_gw_name.Last('=')+1);
1877  gOPT.gw_name=pe_gw_name;
1878  }
1879 
1880  if(stok.Contains("data_label=")) {
1881  TString pe_data_label=stok;
1882  pe_data_label.Remove(0,pe_data_label.Last('=')+1);
1883  gOPT.data_label=pe_data_label;
1884  }
1885 
1886  if(stok.Contains("wave_dir=")) {
1887  TString pe_wave_dir=stok;
1888  pe_wave_dir.Remove(0,pe_wave_dir.Last('=')+1);
1889  gOPT.wave_dir=pe_wave_dir;
1890  }
1891 
1892  if(stok.Contains("nifo=")) {
1893  TString pe_nifo=stok;
1894  pe_nifo.Remove(0,pe_nifo.Last('=')+1);
1895  if(pe_nifo.IsDigit()) gOPT.nifo=pe_nifo.Atoi();
1896  }
1897 
1898  if(stok.Contains("nevents=")) {
1899  TString pe_nevents=stok;
1900  pe_nevents.Remove(0,pe_nevents.Last('=')+1);
1901  if(pe_nevents.IsDigit()) gOPT.nevents=pe_nevents.Atoi();
1902  }
1903 
1904  if(stok.Contains("ncycles=")) {
1905  TString pe_ncycles=stok;
1906  pe_ncycles.Remove(0,pe_ncycles.Last('=')+1);
1907  if(pe_ncycles.IsDigit()) gOPT.ncycles=pe_ncycles.Atoi();
1908  }
1909 
1910  if(stok.Contains("ifar_thr=")) {
1911  TString pe_ifar_thr=stok;
1912  pe_ifar_thr.Remove(0,pe_ifar_thr.Last('=')+1);
1913  if(pe_ifar_thr.IsFloat()) gOPT.ifar_thr=pe_ifar_thr.Atof();
1914  }
1915 
1916  if(stok.Contains("gps_event=")) {
1917  TString pe_gps_event=stok;
1918  pe_gps_event.Remove(0,pe_gps_event.Last('=')+1);
1919  if(pe_gps_event.IsFloat()) gOPT.gps_event=pe_gps_event.Atof();
1920  }
1921 
1922  if(stok.Contains("tcoa_shift=")) {
1923  TString pe_tcoa_shift=stok;
1924  pe_tcoa_shift.Remove(0,pe_tcoa_shift.Last('=')+1);
1925  if(pe_tcoa_shift.IsFloat()) gOPT.tcoa_shift=pe_tcoa_shift.Atof();
1926  }
1927 
1928  if(stok.Contains("gps_error=")) {
1929  TString pe_gps_error=stok;
1930  pe_gps_error.Remove(0,pe_gps_error.Last('=')+1);
1931  if(pe_gps_error.IsFloat()) gOPT.gps_error=pe_gps_error.Atof();
1932  }
1933 
1934  if(stok.Contains("off_event=")) {
1935  TString pe_off_event=stok;
1936  pe_off_event.Remove(0,pe_off_event.Last('=')+1);
1937  if(pe_off_event.IsFloat()) gOPT.off_event=pe_off_event.Atoi();
1938  }
1939 
1940  if(stok.Contains("inj_time_step=")) {
1941  TString pe_inj_time_step=stok;
1942  pe_inj_time_step.Remove(0,pe_inj_time_step.Last('=')+1);
1943  if(pe_inj_time_step.IsDigit()) {
1944  gOPT.inj_time_step=pe_inj_time_step.Atoi();
1945  if(gOPT.inj_time_step<=0) {
1946  gOPT.inj_time_step=PE_INJ_TIME_STEP;
1947  gOPT.inj_onsrc=true;
1948  }
1949  } else {
1950  cout << endl;
1951  cout << "cwb_report - Error : input parameter inj_time_step=" << pe_inj_time_step << " is not an integer !!! " << endl;
1952  cout << endl;
1953  exit(1);
1954  }
1955  }
1956 
1957  if(stok.Contains("ccut=")) {
1958  TString pe_ccut=stok;
1959  pe_ccut.Remove(0,pe_ccut.Last('=')+1);
1960  gOPT.ccut=pe_ccut;
1961  GetCCutParms(gOPT.ccut);
1962  }
1963 
1964  if(stok.Contains("rcut=")) {
1965  TString pe_rcut=stok;
1966  pe_rcut.Remove(0,pe_rcut.Last('=')+1);
1967  gOPT.rcut=pe_rcut;
1968  GetRCutParms(gOPT.rcut);
1969  }
1970 
1971  if(stok.Contains("logl=")) {
1972  TString pe_logl=stok;
1973  pe_logl.Remove(0,pe_logl.Last('=')+1);
1974  gOPT.logl=pe_logl;
1975  GetLoglParms(gOPT.logl);
1976  }
1977 
1978  if(stok.Contains("rstat=")) {
1979  TString pe_rstat=stok;
1980  pe_rstat.Remove(0,pe_rstat.Last('=')+1);
1981  gOPT.rstat=pe_rstat;
1982  GetRstatParms(gOPT.rstat);
1983  }
1984 
1985  if(stok.Contains("plot_fname=")) {
1986  TString pe_plot_fname=stok;
1987  pe_plot_fname.Remove(0,pe_plot_fname.Last('=')+1);
1988  gOPT.plot_fname=pe_plot_fname;
1989  }
1990 
1991  if(stok.Contains("plot_odir=")) {
1992  TString pe_plot_odir=stok;
1993  pe_plot_odir.Remove(0,pe_plot_odir.Last('=')+1);
1994  gOPT.plot_odir=pe_plot_odir;
1995  }
1996 
1997  if(stok.Contains("plot_type=")) {
1998  TString pe_plot_type=stok;
1999  pe_plot_type.Remove(0,pe_plot_type.Last('=')+1);
2000  gOPT.plot_type=pe_plot_type;
2001  }
2002 
2003  if(stok.Contains("plot_efraction=")) {
2004  TString pe_plot_efraction=stok;
2005  pe_plot_efraction.Remove(0,pe_plot_efraction.Last('=')+1);
2006  if(pe_plot_efraction.IsFloat()) gOPT.plot_efraction=pe_plot_efraction.Atof();
2007  }
2008 
2009  if(stok.Contains("plot_zoom=")) {
2010  TString pe_plot_zoom=stok;
2011  pe_plot_zoom.Remove(0,pe_plot_zoom.Last('=')+1);
2012  if(pe_plot_zoom.IsFloat()) gOPT.plot_zoom=pe_plot_zoom.Atof();
2013  if(gOPT.plot_zoom<=0) gOPT.plot_zoom=1.;
2014  }
2015  }
2016  }
2017 }
2018 
2020 
2021  gOPT.gw_name = PE_GW_NAME;
2022  gOPT.data_label = PE_DATA_LABEL;
2023  gOPT.wave_dir = PE_WAVE_DIR;
2024  gOPT.nifo = PE_NIFO;
2025  gOPT.nevents = PE_MAX_EVENTS;
2026  gOPT.ncycles = PE_NCYCLES;
2027  gOPT.ifar_thr = PE_IFAR_THR;
2028  gOPT.gps_event = PE_GPS_EVENT;
2029  gOPT.tcoa_shift = PE_TCOA_SHIFT;
2030  gOPT.gps_error = PE_GPS_ERROR;
2031  gOPT.off_event = PE_OFF_EVENT;
2032  gOPT.inj_time_step = PE_INJ_TIME_STEP;
2033  gOPT.inj_onsrc = PE_INJ_ONSRC;
2034  gOPT.ccut = PE_CCUT;
2035  gOPT.rcut = PE_RCUT;
2036  gOPT.logl = PE_LOGL;
2037  gOPT.rstat = PE_RSTAT;
2038  gOPT.dump_cr = PE_DUMP_CR;
2039  gOPT.use_onsrc = PE_USE_ONSRC;
2040  gOPT.sync_phase = PE_SYNC_PHASE;
2041  gOPT.sync_time = PE_SYNC_TIME;
2042  gOPT.sensitivity = PE_SENSITIVITY;
2043  gOPT.residuals = PE_RESIDUALS;
2044  gOPT.statistics = PE_STATISTICS;
2045  gOPT.efraction = PE_EFRACTION;
2046  gOPT.side = PE_SIDE;
2047  gOPT.coverage = PE_COVERAGE;
2048  gOPT.plot_fname = PE_PLOT_FNAME;
2049  gOPT.plot_odir = PE_PLOT_ODIR;
2050  gOPT.plot_type = PE_PLOT_TYPE;
2051  gOPT.plot_efraction = PE_PLOT_EFRACTION;
2052  gOPT.plot_zoom = PE_PLOT_ZOOM;
2053  gOPT.plot_cr = PE_PLOT_CR;
2054  gOPT.plot_99perc = PE_PLOT_99PERC;
2055  gOPT.make_ff = PE_MAKE_FF;
2056  gOPT.make_of = PE_MAKE_OF;
2057  gOPT.make_re = PE_MAKE_RE;
2058  gOPT.make_ne = PE_MAKE_NE;
2059  gOPT.make_onsrc = PE_MAKE_ONSRC;
2060 }
2061 
2063 
2064  // redirect cout to buffer and return contents
2065  std::streambuf *old = NULL;
2066  std::stringstream buffer;
2067  if(ofname!="") {
2068  old = std::cout.rdbuf(buffer.rdbuf());
2069  }
2070 
2071  cout.precision(6);
2072 
2073  TString sync_phase = gOPT.sync_phase ?"true":"false";
2074  TString sync_time = gOPT.sync_time ?"true":"false";
2075  TString sensitivity = gOPT.sensitivity ?"true":"false";
2076  TString residuals = gOPT.residuals ?"true":"false";
2077  TString statistics = gOPT.statistics ?"true":"false";
2078  TString plot_cr = gOPT.plot_cr ?"true":"false";
2079  TString plot_99perc = gOPT.plot_99perc ?"true":"false";
2080  TString make_ff = gOPT.make_ff ?"true":"false";
2081  TString make_of = gOPT.make_of ?"true":"false";
2082  TString make_re = gOPT.make_re ?"true":"false";
2083  TString make_ne = gOPT.make_ne ?"true":"false";
2084  TString make_onsrc = gOPT.make_onsrc ?"true":"false";
2085  TString logl_enabled = gOPT.logl_enabled ?"true":"false";
2086  TString rstat_enabled = gOPT.rstat_enabled ?"true":"false";
2087 
2088  cout << endl;
2089 
2090  cout << "-----------------------------------------" << endl;
2091  cout << "cwb_pereport config options " << endl;
2092  cout << endl;
2093  cout << "UTC - "; cout.flush();
2094  wat::Time date("now"); cout << date.GetDateString() << endl;
2095  cout << "-----------------------------------------" << endl << endl;
2096 
2097  cout << "PE_GW_NAME " << gOPT.gw_name << endl;
2098  cout << "PE_DATA_LABEL " << gOPT.data_label << endl;
2099  cout << "PE_WAVE_DIR " << gOPT.wave_dir << endl;
2100  cout << "PE_NIFO " << gOPT.nifo << endl;
2101  cout << "PE_NEVENTS " << gOPT.nevents << endl;
2102  cout << "PE_NCYCLES " << gOPT.ncycles << endl;
2103  cout << "PE_IFAR_THR " << gOPT.ifar_thr << endl;
2104  cout << "PE_GPS_EVENT " << std::setprecision(14) << gOPT.gps_event << std::setprecision(6) << endl;
2105  cout << "PE_TCOA_SHIFT " << gOPT.tcoa_shift << endl;
2106  cout << "PE_GPS_ERROR " << gOPT.gps_error << endl;
2107  cout << "PE_OFF_EVENT " << gOPT.off_event << endl;
2108  cout << "PE_INJ_TIME_STEP " << gOPT.inj_time_step << endl;
2109  cout << "PE_INJ_ONSRC " << gOPT.inj_onsrc << endl;
2110  cout << "PE_CCUT " << gOPT.ccut << endl;
2111  cout << "PE_RCUT " << gOPT.rcut << endl;
2112  cout << "PE_LOGL " << gOPT.logl << endl;
2113  cout << "PE_RSTAT " << gOPT.rstat << endl;
2114  cout << "PE_DUMP_CR " << gOPT.dump_cr << endl;
2115  cout << "PE_USE_ONSRC " << gOPT.use_onsrc << endl;
2116  cout << "PE_SYNC_PHASE " << sync_phase << endl;
2117  cout << "PE_SYNC_TIME " << sync_time << endl;
2118  cout << "PE_SENSITIVITY " << sensitivity << endl;
2119  cout << "PE_RESIDUALS " << residuals << endl;
2120  cout << "PE_STATISTICS " << statistics << endl;
2121  cout << "PE_EFRACTION " << gOPT.efraction << endl;
2122  cout << "PE_SIDE " << gOPT.side << endl;
2123  cout << "PE_COVERAGE " << gOPT.coverage << endl;
2124  cout << "PE_PLOT_FNAME " << gOPT.plot_fname << endl;
2125  cout << "PE_PLOT_ODIR " << gOPT.plot_odir << endl;
2126  cout << "PE_PLOT_TYPE " << gOPT.plot_type << endl;
2127  cout << "PE_PLOT_EFRACTION " << gOPT.plot_efraction << endl;
2128  cout << "PE_PLOT_ZOOM " << gOPT.plot_zoom << endl;
2129  cout << "PE_PLOT_CR " << plot_cr << endl;
2130  cout << "PE_PLOT_99PERC " << plot_99perc << endl;
2131  cout << "PE_MAKE_FF " << make_ff << endl;
2132  cout << "PE_MAKE_OF " << make_of << endl;
2133  cout << "PE_MAKE_RE " << make_re << endl;
2134  cout << "PE_MAKE_NE " << make_ne << endl;
2135  cout << "PE_MAKE_ONSRC " << make_onsrc << endl;
2136 
2137  cout << endl;
2138 
2139  cout << "CCUT_WDM_FRES " << gOPT.ccut_wdm_fres << endl;
2140  cout << "CCUT_BCHIRP " << gOPT.ccut_bchirp << endl;
2141  cout << "CCUT_UCHIRP " << gOPT.ccut_uchirp << endl;
2142  cout << "CCUT_LTIME " << gOPT.ccut_ltime << endl;
2143  cout << "CCUT_RTIME " << gOPT.ccut_rtime << endl;
2144  cout << "CCUT_FMAX " << gOPT.ccut_fmax << endl;
2145 
2146  cout << endl;
2147 
2148  cout << "RCUT_WDM_FRES " << gOPT.rcut_wdm_fres << endl;
2149  cout << "RCUT_THR " << gOPT.rcut_thr << endl;
2150 
2151  cout << endl;
2152 
2153  cout << "LOGL_ENABLED " << logl_enabled << endl;
2154  cout << "LOGL_FLOW " << gOPT.logl_flow << endl;
2155  cout << "LOGL_FHIGH " << gOPT.logl_fhigh << endl;
2156  cout << "LOGL_ARTHR " << gOPT.logl_arthr << endl;
2157  cout << "LOGL_IFO_MASK " << "0x" << std::hex << gOPT.logl_ifo_mask << std::dec << endl;
2158  cout << "LOGL_RESAMPLE " << gOPT.logl_resample << endl;
2159 
2160  cout << endl;
2161 
2162  cout << "RSTAT_ENABLED " << rstat_enabled << endl;
2163  cout << "RSTAT_TYPE " << gOPT.rstat_type << endl;
2164  cout << "RSTAT_RTRIALS " << gOPT.rstat_rtrials << endl;
2165  cout << "RSTAT_JTRIALS " << gOPT.rstat_jtrials << endl;
2166 
2167  cout << endl;
2168 
2169  if(ofname!="") {
2170  // restore cout
2171  std::cout.rdbuf(old);
2172  // dump config to ofname file
2173  ofstream out;
2174  out.open(ofname.Data(),ios::out);
2175  out.precision(14);
2176  out << buffer.str() << endl;
2177  out.close();
2178  }
2179 }
2180 
2181 // Dumps reconstructed waveform: time rec posterior med and CR in ASCII & ROOT format
2183 
2184  // save rec/med/cr to output ascii file
2185  char ofname[1024];
2186  for(int n=0; n<nIFO; n++) {
2187 
2188  sprintf(ofname,"%s_%s_cr.txt",gIFO[n].Data(),gOPT.plot_fname.Data());
2189 
2190  ofstream out;
2191  out.open(ofname,ios::out);
2192  if (!out.good()) {cout << "Error Opening Output File : " << ofname << endl;exit(1);}
2193  cout << "Create Output File : " << ofname << endl;
2194  out.precision(19);
2195 
2196  // write header
2197  if(gOPT.plot_type=="time" || gOPT.plot_type=="envelope") {
2198  out << "#whitened data : time, amp_cwb_rec, "
2199  << "amp_post_median, amp_post_lower_50_cr, amp_post_lower_90_cr, amp_post_upper_50_cr, amp_post_upper_90_cr" << endl;
2200  } else if(gOPT.plot_type=="spectrum") {
2201  out << "#whitened data : frequency, amp_cwb_rec, "
2202  << "amp_post_median, amp_post_lower_50_cr, amp_post_lower_90_cr, amp_post_upper_50_cr, amp_post_upper_90_cr" << endl;
2203  } else if(gOPT.plot_type=="phase") {
2204  out << "#whitened data : cycles, amp_cwb_rec, "
2205  << "amp_post_median, amp_post_lower_50_cr, amp_post_lower_90_cr, amp_post_upper_50_cr, amp_post_upper_90_cr" << endl;
2206  }
2207 
2208  // write data
2209  int size = vREC[n].size();
2210  double dx=1./vREC[n].rate();
2211  for (int i=0; i<size; i++) {
2212  double x = i*dx;
2213  if(gOPT.plot_type=="time" || gOPT.plot_type=="envelope") x+=vTREC[n];
2214  double vl50 = vMED[n][i]-fabs(vL50[n][i]);
2215  double vu50 = vMED[n][i]+fabs(vU50[n][i]);
2216  double vl90 = vMED[n][i]-fabs(vL90[n][i]);
2217  double vu90 = vMED[n][i]+fabs(vU90[n][i]);
2218 
2219  out << x
2220  << " " << vREC[n][i] << " " << vMED[n][i]
2221  << " " << vl50 << " " << vl90 << " " << vu50 << " " << vu90
2222  << endl;
2223  }
2224 
2225  out.close();
2226  }
2227 
2228  // open output root file to store rec,med,cr
2229  sprintf(ofname,"%s_cr.root",gOPT.plot_fname.Data());
2230  TFile *froot = new TFile(ofname, "RECREATE");
2231  if(froot==NULL) {
2232  cout << "Failed to create file !!! " << ofname << endl;
2233  gSystem->Exit(1);
2234  }
2235  for(int n=0; n<nIFO; n++) {
2236  // save start times
2237  double tREC = vREC[n].start();
2238  double tMED = vMED[n].start();
2239  double tL50 = vL50[n].start();
2240  double tL90 = vL90[n].start();
2241  double tL99 = vL99[n].start();
2242  double tU50 = vU50[n].start();
2243  double tU90 = vU90[n].start();
2244  double tU99 = vU99[n].start();
2245 
2246  if(gOPT.plot_type=="time" || gOPT.plot_type=="envelope") {
2247  // set the start GPS time
2248  vREC[n].start(vTREC[n]);
2249  vMED[n].start(vTREC[n]);
2250  vL50[n].start(vTREC[n]);
2251  vL90[n].start(vTREC[n]);
2252  vL99[n].start(vTREC[n]);
2253  vU50[n].start(vTREC[n]);
2254  vU90[n].start(vTREC[n]);
2255  vU99[n].start(vTREC[n]);
2256  }
2257 
2258  // write data to output root file
2259  vREC[n].Write(TString::Format("REC_%s",gIFO[n].Data()));
2260  vMED[n].Write(TString::Format("MED_%s",gIFO[n].Data()));
2261  vL50[n].Write(TString::Format("L50_%s",gIFO[n].Data()));
2262  vL90[n].Write(TString::Format("L90_%s",gIFO[n].Data()));
2263  vL99[n].Write(TString::Format("L99_%s",gIFO[n].Data()));
2264  vU50[n].Write(TString::Format("U50_%s",gIFO[n].Data()));
2265  vU90[n].Write(TString::Format("U90_%s",gIFO[n].Data()));
2266  vU99[n].Write(TString::Format("U99_%s",gIFO[n].Data()));
2267 
2268  // restore start times
2269  vREC[n].start(tREC);
2270  vMED[n].start(tMED);
2271  vL50[n].start(tL50);
2272  vL90[n].start(tL90);
2273  vL99[n].start(tL99);
2274  vU50[n].start(tU50);
2275  vU90[n].start(tU90);
2276  vU99[n].start(tU99);
2277  }
2278  froot->Close();
2279 }
2280 
2282 
2283  if(type!="FF" && type!="OF" && type!="RE" && type!="NE") {
2284  cout << "MakeDistributions - Error : plot type not available, must be FF/OF/RE/NE" << endl;
2285  gSystem->Exit(1);
2286  }
2287 
2288  TCanvas* cmf = new TCanvas("MatchingFactor", "MatchingFactor", 200, 20, 1000, 600);
2289  cmf->SetLogx(false);
2290  cmf->SetLogy(true);
2291  cmf->SetGridx(true);
2292  cmf->SetGridy(true);
2293 
2294  gStyle->SetOptStat("emrou");
2295  gStyle->SetStatFont(63);
2296  gStyle->SetStatFontSize(12);
2297  gStyle->SetStatW(0.15);
2298  gStyle->SetStatH(0.12);
2299 
2300  double xmin=1e20;
2301  double xmax=-1e-20;
2302  if(type=="FF") {
2303  for(int i=0;i<vFF.size();i++) {
2304  if(vFF[i]<xmin) xmin=vFF[i];
2305  if(vFF[i]>xmax) xmax=vFF[i];
2306  }
2307  //xmin=-1.0;
2308  //xmin=0.0;
2309  xmax=1.0;
2310  }
2311  if(type=="OF") {
2312  for(int i=0;i<vOF.size();i++) {
2313  if(vOF[i]<xmin) xmin=vOF[i];
2314  if(vOF[i]>xmax) xmax=vOF[i];
2315  }
2316  }
2317  if(type=="RE") {
2318  double xmean=0.;
2319  for(int i=0;i<vRE.size();i++) {
2320  if(vRE[i]<xmin) xmin=vRE[i];
2321  if(vRE[i]>xmax) xmax=vRE[i]+0.1*xmax;
2322  xmean+=vRE[i];
2323  }
2324  // limit the xmax when big outliers are present
2325  xmean/=vRE.size();
2326  if(xmax>6*xmean) xmax=6*xmean;
2327  if(xmax<vRE[0]) xmax=2*vRE[0];
2328  }
2329  if(type=="NE") {
2330  for(int i=0;i<vNE.size();i++) {
2331  if(vNE[i]<xmin) xmin=vNE[i];
2332  if(vNE[i]>xmax) xmax=vNE[i]+0.1*xmax;
2333  }
2334  }
2335 
2336  // histogram of matching factor onsource reconstructed vs offsource injected
2337  TH1F* xhist = new TH1F("xhist","xhist",100,xmin,xmax);
2338  //xhist->SetStats(kFALSE);
2339  xhist->SetLineWidth(2);
2340  xhist->SetLineColor(kGreen+2);
2341  for(int i=1;i<xFF.size();i++) {
2342  if(type=="FF") xhist->Fill(xFF[i]);
2343  if(type=="OF") xhist->Fill(xOF[i]);
2344  if(type=="RE") xhist->Fill(xRE[i]);
2345  if(type=="NE") xhist->Fill(xNE[i]);
2346  }
2347 
2348  int nFF=0;
2349  int nOF=0;
2350  int nRE=0;
2351  int nNE=0;
2352  // histogram of matching factor onsource/offsource reconstructed vs onsource/offsource injected
2353  TH1F* hist = new TH1F("hist","hist",100,xmin,xmax);
2354  //hist->SetStats(kFALSE);
2355  if(type=="FF") for(int i=1;i<vFF.size();i++) hist->Fill(vFF[i]);
2356  if(type=="OF") for(int i=1;i<vOF.size();i++) hist->Fill(vOF[i]);
2357  if(type=="RE") for(int i=1;i<vRE.size();i++) hist->Fill(vRE[i]);
2358  if(type=="NE") for(int i=1;i<vNE.size();i++) hist->Fill(vNE[i]);
2359 
2360  int nTOT=0;
2361  for(int i=1;i<vFF.size();i++) {
2362  if(type=="FF") {nTOT++;if(vFF[i]<vFF[0]) nFF++;}
2363  if(type=="OF") {nTOT++;if(vOF[i]<vOF[0]) nOF++;}
2364  if(type=="RE") {nTOT++;if(vRE[i]>vRE[0]) nRE++;}
2365  if(type=="NE") {nTOT++;if(vNE[i]>vNE[0]) nNE++;}
2366  }
2367 
2368  double pvalueFF = double(nFF)/double(nTOT);
2369  double pvalueOF = double(nOF)/double(nTOT);
2370  double pvalueRE = double(nRE)/double(nTOT);
2371  double pvalueNE = double(nNE)/double(nTOT);
2372 
2373  cout << endl;
2374  if(type=="FF") cout << "pvalue FF=" << pvalueFF << endl;
2375  if(type=="OF") cout << "pvalue OF=" << pvalueOF << endl;
2376  if(type=="RE") cout << "pvalue RE=" << pvalueRE << endl;
2377  if(type=="NE") cout << "pvalue NE=" << pvalueNE << endl;
2378  cout << endl;
2379 
2380  hist->SetLineWidth(2);
2381 
2382  hist->Draw("HIST");
2383  cmf->Modified(); cmf->Update();
2384  TPaveStats *sthist = (TPaveStats*)hist->FindObject("stats");
2385  sthist->SetTextColor(kBlack);
2386  sthist->SetLineColor(kBlack);
2387  if(gOPT.make_onsrc) {
2388  sthist->SetTextColor(kBlue);
2389  xhist->Draw("SAMES");
2390  cmf->Modified(); cmf->Update();
2391  TPaveStats *stxhist = (TPaveStats*)xhist->FindObject("stats");
2392  stxhist->SetTextColor(kGreen+2);
2393  stxhist->SetLineColor(kBlack);
2394  stxhist->SetY2NDC(.68);
2395  stxhist->SetOptStat(1110);
2396  }
2397  float yhmax = hist->GetMaximum()>xhist->GetMaximum() ? hist->GetMaximum() : xhist->GetMaximum();
2398  hist->GetYaxis()->SetRangeUser(0.9,1.1*yhmax);
2399  hist->GetYaxis()->SetNdivisions(3);
2400 
2401  double mean = hist->GetMean();
2402  double rms = hist->GetRMS();
2403 
2404  // compute offsource median. 50%, 90%, 99%
2405  int nentries=vFF.size()-1; // index=0 contains onsource
2406  int *index = new int[nentries];
2407  float *value = new float[nentries];
2408  for(int i=0;i<nentries;i++) {
2409  if(type=="FF") value[i]=vFF[i+1];
2410  if(type=="OF") value[i]=vOF[i+1];
2411  if(type=="RE") value[i]=vRE[i+1];
2412  if(type=="NE") value[i]=vNE[i+1];
2413  }
2414  TMath::Sort(nentries,value,index,false);
2415 
2416  int imed = (nentries*50.)/100.; if(imed>=nentries) imed=nentries-1;
2417  int il50 = (nentries*25.)/100.; if(il50>=nentries) il50=nentries-1;
2418  int iu50 = (nentries*75.)/100.; if(iu50>=nentries) iu50=nentries-1;
2419  int il90 = (nentries*5.)/100.; if(il90>=nentries) il90=nentries-1;
2420  int iu90 = (nentries*95.)/100.; if(iu90>=nentries) iu90=nentries-1;
2421  int il99 = (nentries*0.5)/100.; if(il99>=nentries) il99=nentries-1;
2422  int iu99 = (nentries*99.5)/100.; if(iu99>=nentries) iu99=nentries-1;
2423  int il100 = 0;
2424  int iu100 = nentries-1;
2425 
2426  double med = value[index[imed]];
2427  double l50 = value[index[il50]];
2428  double u50 = value[index[iu50]];
2429  double l90 = value[index[il90]];
2430  double u90 = value[index[iu90]];
2431  double l99 = value[index[il99]];
2432  double u99 = value[index[iu99]];
2433  double l100 = value[index[il100]];
2434  double u100 = value[index[iu100]];
2435 
2436  double match=-1;
2437  if(type=="FF") match=vFF[0];
2438  if(type=="OF") match=vOF[0];
2439  if(type=="RE") match=vRE[0];
2440  if(type=="NE") match=vNE[0];
2441 
2442  double pvalue=0;
2443  if(type=="FF") pvalue=pvalueFF;
2444  if(type=="OF") pvalue=pvalueOF;
2445  if(type=="RE") pvalue=pvalueRE;
2446  if(type=="NE") pvalue=pvalueNE;
2447 
2448  TString xtitle="";
2449  if(type=="FF") xtitle="Fitting Factor";
2450  if(type=="OF") xtitle="Overlap Factor";
2451  if(type=="RE") xtitle="Residual Energy";
2452  if(type=="NE") xtitle="Null Energy";
2453 
2454  hist->GetXaxis()->SetTitle(xtitle);
2455  hist->GetXaxis()->SetTitleOffset(1.4);
2456  hist->GetXaxis()->SetLabelOffset(0.02);
2457  hist->GetXaxis()->SetNoExponent();
2458 
2459  hist->GetYaxis()->SetTitle("counts");
2460  hist->GetYaxis()->SetTitleOffset(1.6);
2461  hist->GetYaxis()->SetLabelOffset(0.02);
2462  hist->GetYaxis()->SetNoExponent();
2463  if(gOPT.rstat_enabled) hist->GetXaxis()->SetTitle("R statistic");
2464  char htitle[1024];
2465  if(gOPT.rstat_enabled) {
2466  sprintf(htitle,"%s %s (%s) - on-source (red - R-stat=%0.4f, pvalue=%0.4f) vs off-source (blue)",
2467  gOPT.gw_name.Data(),xtitle.Data(),gOPT.side.Data(),match,pvalue);
2468  } else {
2469  sprintf(htitle,"%s %s (%s) - cWB (red - %s=%0.4f, pvalue=%0.4f) vs off-source (blue)",
2470  gOPT.gw_name.Data(),xtitle.Data(),gOPT.side.Data(),type.Data(),match,pvalue);
2471  }
2472  hist->SetTitle(htitle);
2473  hist->SetName("Statistic");
2474 
2475  // draw vertical line at the cWB point estimate FF/OF/RE/NE value
2476  float ymax = hist->GetMaximum();
2477  float xval = 0;
2478  if(type=="FF") xval=vFF[0];
2479  if(type=="OF") xval=vOF[0];
2480  if(type=="RE") xval=vRE[0];
2481  if(type=="NE") xval=vNE[0];
2482  TLine *line = new TLine(xval,0,xval,ymax);
2483  line->SetLineWidth(2);
2484  line->SetLineColor(kRed);
2485  line->Draw();
2486 
2487  // set stats box line color black
2488 // cmf->Update();
2489 // TPaveStats *ptstats = (TPaveStats*)cmf->GetPrimitive("stats");
2490 // ptstats->SetLineColor(kBlack);
2491 // cmf->Modified();
2492 
2493  TString pdir=gOPT.plot_odir;
2494  xtitle.ReplaceAll(" ","");
2495  char ofname[256];
2496  sprintf(ofname,"%s_%s.png",gOPT.plot_fname.Data(),xtitle.Data());
2497  TString fName = pdir!="" ? TString(pdir)+TString("/")+ofname : ofname;
2498  cmf->Print(fName);
2499  cout << "write : " << fName << endl;
2500  fName.ReplaceAll(".png",".root");
2501  cmf->Print(fName);
2502  cout << "write : " << fName << endl;
2503 
2504  //if(type=="RE") {xtitle="ResidualSNR"; match=sqrt(match);}
2505  // dump summary statistic
2506  fName.ReplaceAll(".root",".txt");
2507  TString params = TString::Format("%s : %s %0.4f pvalue %0.4f median %0.4f l99 %0.4f l90 %0.4f l50 %0.4f u50 %0.4f u90 %0.4f u99 %0.4f",
2508  gOPT.gw_name.Data(),xtitle.Data(),match,pvalue,med,l99,l90,l50,u50,u90,u99);
2509  DumpStatistics(fName, params, false);
2510 
2511  if(gOPT.side=="ccut") { // dump ccut parameters & match & pvalue
2512  params = TString::Format("%s : %s %0.4f pvalue %0.4f ccut_wdm_fres %d ccut_bchirp %0.4f ccut_uchirp %0.4f ccut_ltime %0.4f ccut_rtime %0.4f",
2513  gOPT.gw_name.Data(),xtitle.Data(),match,pvalue,gOPT.ccut_wdm_fres,gOPT.ccut_bchirp,gOPT.ccut_uchirp,gOPT.ccut_ltime,gOPT.ccut_rtime);
2514  DumpStatistics("pestat_ccut.txt", params, false);
2515  }
2516 
2517  if(gOPT.side=="ccut") { // dump ccut parameters & match & pvalue
2518  DumpStatistics("pestat_ccut.lst", "id\tpvalue\tresidual", false);
2519  for(int n=0;n<vFF.size();n++) {
2520  int nRE=0; for(int i=1;i<vFF.size();i++) if(vRE[i]>vRE[n]) nRE++;
2521  double pvalueRE = nRE/(double)(vRE.size()-1);
2522  TString parm = TString::Format("%d\t%.6f\t%.6f",n,pvalueRE,vRE[n]);
2523  DumpStatistics("pestat_ccut.lst", parm, true);
2524  }
2525  }
2526 
2527  TString sfName = fName; // save output file name, used as template for the following auxiliary output files
2528 
2529  // dump sorted statistic
2530  fName=sfName;fName.ReplaceAll(".txt","_statistic.txt");
2531  for(int i=0;i<nentries;i++) {
2532  TString parm = TString::Format("%f",value[index[i]]);
2533  if(i==0) DumpStatistics(fName, parm, false);
2534  else DumpStatistics(fName, parm, true);
2535  }
2536 
2537  // dump factors, used with ONSPE multi injections
2538  if(type=="NE") {
2539  int fmed = wFACTOR[index[imed]];
2540  int fl50 = wFACTOR[index[il50]];
2541  int fu50 = wFACTOR[index[iu50]];
2542  int fl90 = wFACTOR[index[il90]];
2543  int fu90 = wFACTOR[index[iu90]];
2544  int fl99 = wFACTOR[index[il99]];
2545  int fu99 = wFACTOR[index[iu99]];
2546  int fl100 = wFACTOR[index[il100]];
2547  int fu100 = wFACTOR[index[iu100]];
2548  fName=sfName;fName.ReplaceAll(".txt","_factor.txt");
2549  TString params = TString::Format("%s : %s %0.4f pvalue %0.4f median %d l100 %d l99 %d l90 %d l50 %d u50 %d u90 %d u99 %d u100 %d",
2550  gOPT.gw_name.Data(),xtitle.Data(),match,pvalue,fmed,fl100,fl99,fl90,fl50,fu50,fu90,fu99,fu100);
2551  DumpStatistics(fName, params, false);
2552  }
2553 
2554  if(gOPT.sensitivity) {
2555 
2556  double dphase50,dtime50,damp50;
2557  double dphase90,dtime90,damp90;
2558  if(type=="FF") {
2559  double dff_phase,dff_time,dff_amp;
2560  ComputePhaseSensitivity("ff",l90,u90,dff_phase,dphase90);
2561  ComputePhaseSensitivity("ff",l50,u50,dff_phase,dphase50);
2562  printf("\n\n------> FF Phase Sensitivity (l50=%.2f - u50=%.2f) = %.4f\n\n",l50,u50,dff_phase);
2563  ComputeTimeSensitivity("ff",l90,u90,dff_time,dtime90);
2564  ComputeTimeSensitivity("ff",l50,u50,dff_time,dtime50);
2565  printf("\n\n------> FF Time Sensitivity (l50=%.2f - u50=%.2f) = %.4f\n\n",l50,u50,dff_time);
2566  ComputeAmpSensitivity("ff",l90,u90,dff_amp,damp90);
2567  ComputeAmpSensitivity("ff",l50,u50,dff_amp,damp50);
2568  printf("\n\n------> FF Amp Sensitivity (l50=%.2f - u50=%.2f) = %.4f\n\n",l50,u50,dff_amp);
2569  params = TString::Format("%s : %s\tdff_phase\t%0.4f\tdff_time\t%0.4f\tdff_amp\t%0.4f\tdphase50\t%0.4f\tdtime50\t%0.5f\tdamp50\t%0.4f\tdphase90\t%0.4f\tdtime90\t%0.5f\tdamp90\t%0.4f",
2570  gOPT.gw_name.Data(),xtitle.Data(),dff_phase,dff_time,dff_amp,dphase50,dtime50,damp50,dphase90,dtime90,damp90);
2571  }
2572  if(type=="OF") {
2573  double dof_phase,dof_time,dof_amp;
2574  ComputePhaseSensitivity("of",l90,u90,dof_phase,dphase90);
2575  ComputePhaseSensitivity("of",l50,u50,dof_phase,dphase50);
2576  printf("\n\n------> OF Phase Sensitivity (l50=%.2f - u50=%.2f) = %.4f\n\n",l50,u50,dof_phase);
2577  ComputeTimeSensitivity("of",l90,u90,dof_time,dtime90);
2578  ComputeTimeSensitivity("of",l50,u50,dof_time,dtime50);
2579  printf("\n\n------> OF Time Sensitivity (l50=%.2f - u50=%.2f) = %.4f\n\n",l50,u50,dof_time);
2580  ComputeAmpSensitivity("of",l90,u90,dof_amp,damp90);
2581  ComputeAmpSensitivity("of",l50,u50,dof_amp,damp50);
2582  printf("\n\n------> OF Amp Sensitivity (l50=%.2f - u50=%.2f) = %.4f\n\n",l50,u50,dof_amp);
2583  params = TString::Format("%s : %s\tdof_phase\t%0.4f\tdof_time\t%0.4f\tdof_amp\t%0.4f\tdphase50\t%0.4f\tdtime50\t%0.5f\tdamp50\t%0.4f\tdphase90\t%0.4f\tdtime90\t%0.5f\tdamp90\t%0.4f",
2584  gOPT.gw_name.Data(),xtitle.Data(),dof_phase,dof_time,dof_amp,dphase50,dtime50,damp50,dphase90,dtime90,damp90);
2585  }
2586  if(type=="RE") {
2587  double dre_phase,dre_time,dre_amp;
2588  ComputePhaseSensitivity("re",l90,u90,dre_phase,dphase90);
2589  ComputePhaseSensitivity("re",l50,u50,dre_phase,dphase50);
2590  printf("\n\n------> RE Phase Sensitivity (l50=%.2f - u50=%.2f) = %.4f\n\n",l50,u50,dre_phase);
2591  ComputeTimeSensitivity("re",l90,u90,dre_time,dtime90);
2592  ComputeTimeSensitivity("re",l50,u50,dre_time,dtime50);
2593  printf("\n\n------> RE Time Sensitivity (l50=%.2f - u50=%.2f) = %.4f\n\n",l50,u50,dre_time);
2594  ComputeAmpSensitivity("re",l90,u90,dre_amp,damp90);
2595  ComputeAmpSensitivity("re",l50,u50,dre_amp,damp50);
2596  printf("\n\n------> RE Amp Sensitivity (l50=%.2f - u50=%.2f) = %.4f\n\n",l50,u50,dre_amp);
2597  params = TString::Format("%s : %s\tdre_phase\t%0.4f\tdre_time\t%0.4f\tdre_amp\t%0.4f\tdphase50\t%0.4f\tdtime50\t%0.5f\tdamp50\t%0.4f\tdphase90\t%0.4f\tdtime90\t%0.5f\tdamp90\t%0.4f",
2598  gOPT.gw_name.Data(),xtitle.Data(),dre_phase,dre_time,dre_amp,dphase50,dtime50,damp50,dphase90,dtime90,damp90);
2599  }
2600 
2601  if(type!="NE") {
2602  fName=sfName;fName.ReplaceAll(".txt","_sensitivity.txt");
2603  DumpStatistics(fName, params, false);
2604  }
2605  }
2606 
2607  // compute 90% percentile bounds of the on-source distribution
2608  if(gOPT.make_onsrc) {
2609  int xnentries=xFF.size();
2610  int* xindex = new int[xnentries];
2611  float* xvalue = new float[xnentries];
2612  for(int i=0;i<xnentries;i++) {
2613  if(type=="FF") xvalue[i]=xFF[i];
2614  if(type=="OF") xvalue[i]=xOF[i];
2615  if(type=="RE") xvalue[i]=xRE[i];
2616  if(type=="NE") xvalue[i]=xNE[i];
2617  }
2618  TMath::Sort(xnentries,xvalue,xindex,false);
2619  int ixl50 = (xnentries*25.)/100.; if(ixl50>=xnentries) ixl50=xnentries-1;
2620  int ixu50 = (xnentries*75.)/100.; if(ixu50>=xnentries) ixu50=xnentries-1;
2621  int ixl90 = (xnentries*5.)/100.; if(ixl90>=xnentries) ixl90=xnentries-1;
2622  int ixu90 = (xnentries*95.)/100.; if(ixu90>=xnentries) ixu90=xnentries-1;
2623  int ixl99 = (xnentries*0.5)/100.; if(ixl99>=xnentries) ixl99=xnentries-1;
2624  int ixu99 = (xnentries*99.5)/100.; if(ixu99>=xnentries) ixu99=xnentries-1;
2625  double xl50 = xvalue[xindex[ixl50]];
2626  double xu50 = xvalue[xindex[ixu50]];
2627  double xl90 = xvalue[xindex[ixl90]];
2628  double xu90 = xvalue[xindex[ixu90]];
2629  double xl99 = xvalue[xindex[il99]];
2630  double xu99 = xvalue[xindex[ixu99]];
2631  // compute on-source distribution probability @ 50%,90%,99%
2632  int bxl50 = hist->FindBin(xl50); // lower 50% xhist bound bin
2633  int bxu50 = hist->FindBin(xu50); // upper 50% xhist bound bin
2634  int bxl90 = hist->FindBin(xl90); // lower 90% xhist bound bin
2635  int bxu90 = hist->FindBin(xu90); // upper 90% xhist bound bin
2636  int bxl99 = hist->FindBin(xl99); // lower 99% xhist bound bin
2637  int bxu99 = hist->FindBin(xu99); // upper 99% xhist bound bin
2638  hist->Scale(1./hist->Integral()); // distribution is normalized to 1
2639  double prob50=0;
2640  for(int i=bxl50;i<=bxu50;i++) prob50+=hist->GetBinContent(i); // get probability of xhist distr @ 50%
2641  double prob90=0;
2642  for(int i=bxl90;i<=bxu90;i++) prob90+=hist->GetBinContent(i); // get probability of xhist distr @ 90%
2643  double prob99=0;
2644  for(int i=bxl99;i<=bxu99;i++) prob99+=hist->GetBinContent(i); // get probability of xhist distr @ 99%
2645  // dump to file on-source distribution probability @ 50%,90%,99%
2646  fName=sfName;fName.ReplaceAll(".txt","_onsource_prob.txt");
2647  params = TString::Format("%s : prob50 %0.4f prob90 %0.4f prob99 %0.4f",
2648  gOPT.gw_name.Data(),prob50,prob90,prob99);
2649  DumpStatistics(fName, params, false);
2650  cout << endl << xtitle << " on-source probability -> " << params << endl << endl;
2651 
2652  // dump sorted statistic
2653  fName=sfName;fName.ReplaceAll(".txt","_onsource_statistic.txt");
2654  for(int i=0;i<xnentries;i++) {
2655  TString parm = TString::Format("%f",xvalue[xindex[i]]);
2656  if(i==0) DumpStatistics(fName, parm, false);
2657  else DumpStatistics(fName, parm, true);
2658  }
2659 
2660  delete [] xindex;
2661  delete [] xvalue;
2662 /*
2663  // dump on-source marginal likelihood used for bayes factor
2664  double prob=0;
2665  for(int i=0;i<=hist->GetNbinsX();i++) {
2666  prob += hist->GetBinContent(i)*xhist->GetBinContent(i);
2667  }
2668  if(hist->Integral()*xhist->Integral()>0) prob /= hist->Integral()*xhist->Integral();
2669  else prob=0.;
2670  TString parm = TString::Format("on-source marginal likelihood = %g", prob);
2671  fName=sfName;fName.ReplaceAll(".txt","_mlike.txt");
2672  DumpStatistics(fName, parm, false);
2673  cout << endl << sfName.ReplaceAll(".txt"," -> ") << parm << endl << endl;
2674 */
2675  }
2676 
2677  delete hist;
2678  delete xhist;
2679  delete cmf;
2680  delete [] index;
2681  delete [] value;
2682 }
2683 
2684 double
2685 GetInjTcoa(double geocentric_tcoa, network* NET, TString ifo, double theta, double phi) {
2686 // compute coalescence time
2687 
2688  // Add Time Delay respect to geocenter
2689  CWB::mdc MDC(NET);
2690  double tdelay = MDC.GetDelay(ifo,"",phi,theta);
2691  double ifo_tcoa = geocentric_tcoa+tdelay;
2692 
2693  return ifo_tcoa;
2694 }
2695 
2696 double
2697 GetDelay(network* NET, TString ifo, double theta, double phi) {
2698 
2699  // Add Time Delay respect to geocenter
2700  CWB::mdc MDC(NET);
2701  double tdelay = MDC.GetDelay(ifo,"",phi,theta);
2702 
2703  return tdelay;
2704 }
2705 
2706 void
2707 DumpStatistics(TString ofname, TString params, bool app) {
2708 
2709  ofstream out;
2710  if(app) out.open(ofname.Data(),ios::app);
2711  else out.open(ofname.Data(),ios::out);
2712  out.precision(14);
2713  out << params.Data() << endl;
2714  out.close();
2715 }
2716 
2717 void
2718 ComputePhaseSensitivity(TString match, double lower, double upper, double& dmatch, double& dphase) {
2719 
2720  if((match!="ff")&&(match!="of")&&(match!="re")) {dmatch=dphase=0.;return;}
2721 
2722  vector<wavearray<double> > xINJ = vINJ;
2723 
2724  bool lfound,ufound;
2725  lfound=ufound=false;
2726  double lphase,uphase;
2727  lphase=uphase=0.;
2728  cout.precision(4);
2729  for(int i=0;i<180;i++) {
2730  if(lfound&&ufound) continue;
2731  for(int n=0;n<xINJ.size();n++) CWB::mdc::PhaseShift(xINJ[n],1.);
2732  double value = CWB::mdc::GetMatchFactor(match,xINJ,vINJ);
2733  if(match=="ff" || match=="of") {
2734  if((!ufound)&&(value>upper)) uphase=i+1; else ufound=true;
2735  if((!lfound)&&(value>lower)) lphase=i+1; else lfound=true;
2736  } else {
2737  if((!ufound)&&(value<upper)) uphase=i+1; else ufound=true;
2738  if((!lfound)&&(value<lower)) lphase=i+1; else lfound=true;
2739  }
2740  //cout << match.ToUpper() << "\tComputePhaseSensitivity " << i+1 << "\t" << value << "\t" << lower << "\t" << upper << endl;
2741  }
2742  dmatch = (uphase!=lphase) ? (upper-lower)/(uphase-lphase) : 0;
2743  dmatch/=(upper+lower)/2.;
2744  dmatch=fabs(dmatch);
2745  dphase=fabs(uphase-lphase);
2746 }
2747 
2748 void
2749 ComputeTimeSensitivity(TString match, double lower, double upper, double& dmatch, double& dtime) {
2750 
2751  if((match!="ff")&&(match!="of")&&(match!="re")) {dmatch=dtime=0.;return;}
2752 
2753  vector<wavearray<double> > xINJ = vINJ;
2754 
2755  double dt=0.00001;
2756 
2757  bool lfound,ufound;
2758  lfound=ufound=false;
2759  double ltime,utime;
2760  ltime=utime=0.;
2761  cout.precision(4);
2762  for(int i=0;i<10000;i++) {
2763  if(lfound&&ufound) continue;
2764  double t=(i+1)*dt;
2765  for(int n=0;n<xINJ.size();n++) CWB::mdc::TimeShift(xINJ[n],dt);
2766  double value = CWB::mdc::GetMatchFactor(match,xINJ,vINJ);
2767  if(match=="ff" || match=="of") {
2768  if((!ufound)&&(value>upper)) utime=t; else ufound=true;
2769  if((!lfound)&&(value>lower)) ltime=t; else lfound=true;
2770  } else {
2771  if((!ufound)&&(value<upper)) utime=t; else ufound=true;
2772  if((!lfound)&&(value<lower)) ltime=t; else lfound=true;
2773  }
2774  //cout << match.ToUpper() << "\tComputeTimeSensitivity " << t << "\t" << value << "\t" << lower << "\t" << upper << endl;
2775  }
2776  dmatch = (utime!=ltime) ? (upper-lower)/(utime-ltime) : 0;
2777  dmatch/=(upper+lower)/2.;
2778  dmatch=fabs(dmatch);
2779  dtime=fabs(utime-ltime);
2780 }
2781 
2782 void
2783 ComputeAmpSensitivity(TString match, double lower, double upper, double& dmatch, double& damp) {
2784 
2785  if((match!="of")&&(match!="re")) {dmatch=damp=0.;return;}
2786 
2787  double da=0.99;
2788 
2789  bool lfound,ufound;
2790  double lamp,uamp;
2791  cout.precision(4);
2792  if(match=="of") {
2793  lamp=uamp=0.;
2794  lfound=ufound=false;
2795  vector<wavearray<double> > xINJ = vINJ;
2796  for(int n=0;n<xINJ.size();n++) xINJ[n]*=pow(da,-200);
2797  for(int i=0;i<401;i++) {
2798  if(lfound&&ufound) continue;
2799  double a = pow(da,(i-200));
2800  double value = CWB::mdc::GetMatchFactor(match,xINJ,vINJ);
2801  if((!ufound)&&(value>upper)) uamp=a; else ufound=true;
2802  if((!lfound)&&(value>lower)) lamp=a; else lfound=true;
2803  //cout << i-200 << " " << "\tComputeAmpSensitivity " << a << "\t" << value << "\t" << lower << "\t" << upper << endl;
2804  for(int n=0;n<xINJ.size();n++) xINJ[n]*=da;
2805  }
2806  dmatch = (uamp!=lamp) ? (upper-lower)/(uamp-lamp) : 0;
2807  dmatch/=(upper+lower)/2.;
2808  dmatch=fabs(dmatch);
2809  damp=fabs(uamp-lamp);
2810  return;
2811  }
2812  if(match=="re") {
2813  // amplitude factor <=1
2814  lamp=uamp=0.;
2815  lfound=ufound=false;
2816  vector<wavearray<double> > xINJ = vINJ;
2817  for(int i=0;i>-200;i--) {
2818  if(lfound&&ufound) continue;
2819  double a = pow(da,i);
2820  double value = CWB::mdc::GetMatchFactor(match,xINJ,vINJ);
2821  if((!ufound)&&(value<upper)) uamp=a; else ufound=true;
2822  if((!lfound)&&(value<lower)) lamp=a; else lfound=true;
2823  //cout << i << " " << "\tComputeAmpSensitivity " << a << "\t" << value << "\t" << lower << "\t" << upper << endl;
2824  for(int n=0;n<xINJ.size();n++) xINJ[n]*=1./da;
2825  }
2826  double damp1=fabs(uamp-lamp);
2827  double dmatch1 = (uamp!=lamp) ? (upper-lower)/(uamp-lamp) : 0;
2828  dmatch1/=(upper+lower)/2.;
2829 
2830  // amplitude factor >=1
2831  lamp=uamp=0.;
2832  lfound=ufound=false;
2833  xINJ = vINJ;
2834  for(int i=0;i<200;i++) {
2835  if(lfound&&ufound) continue;
2836  double a = pow(da,i);
2837  double value = CWB::mdc::GetMatchFactor(match,xINJ,vINJ);
2838  if((!ufound)&&(value<upper)) uamp=a; else ufound=true;
2839  if((!lfound)&&(value<lower)) lamp=a; else lfound=true;
2840  //cout << i << " " << "\tComputeAmpSensitivity " << a << "\t" << value << "\t" << lower << "\t" << upper << endl;
2841  for(int n=0;n<xINJ.size();n++) xINJ[n]*=da;
2842  }
2843  double damp2=fabs(uamp-lamp);
2844  double dmatch2 = (uamp!=lamp) ? (upper-lower)/(uamp-lamp) : 0;
2845  dmatch2/=(upper+lower)/2.;
2846 
2847  dmatch=(fabs(dmatch1)+fabs(dmatch2))/2.;
2848  damp=(damp1+damp2)/2.;
2849  return;
2850  }
2851 }
2852 
2853 double
2854 GetSyncTcoa(wavearray<double> wf, double sync_time, double sync_phase, double tcoa) {
2855 
2856 // this function return the time shift of the tcoa after the time/phase sync
2857 //
2858 // wf is the wINJ after time/phase sync
2859 // sync_time, sync_phase are the time/phase sync
2860 // tcoa is the coalescence time of wINJ
2861 
2862  CWB::mdc::TimePhaseSync(wf, -sync_time, -sync_phase); // return to the original wf before time/phase sync
2863 
2864  wavearray<double> fwf = CWB::Toolbox::getHilbertIFrequency(wf); // get frequency vs time
2865 
2866  double dt = 1./wf.rate();
2867  int n = int((tcoa-wf.start())/dt);
2868  float inj_fcoa = fwf[n]; // get frequency at the coalescence time
2869 
2870  double tshift = inj_fcoa>0 ? sync_time+(1./inj_fcoa)*(sync_phase/360.) : sync_time; // get time shift after time/phase sync
2871 
2872  return tcoa+tshift;
2873 }
2874 
2875 float
2876 TestStatistic(int nIFO, int id, float ref) {
2877 // Used for tests
2878 
2879  if(wREC[id].size()==0) return -1.;
2880 
2881  int nTRY = 100;
2882 
2883  gRandom->SetSeed(150914+id);
2884 
2885  // select nTRY random onsource samples
2886  vector<int> irnd(nTRY);
2887  for(int i=0;i<nTRY;i++) irnd[i] = int(gRandom->Uniform(0,gEVENTS));
2888 
2889  gnetwork* NET = new gnetwork(nIFO,gIFO);
2890 
2891  int N=0;
2892  int M=0;
2893  float min=1e20;
2894  std::vector<wavearray<double> > wrec(nIFO);
2895  for(int j=0;j<nTRY;j++) {
2896  int i=irnd[j];
2897  if(wINJ[i].size()==0) continue;
2898  // phase time,sync the wREC sample waveforms respect to wINJ
2899  for(int n=0;n<nIFO;n++) {
2900  // align wINJ wrt wREC
2901  wrec[n] = CWB::mdc::GetAligned(id<0 ? &vREC[n] : &wREC[id][n], &wINJ[i][n]);
2902  char sout[1024];
2903  double sync_phase, sync_time, sync_xcor;
2904  if(gOPT.sync_time && !gOPT.sync_phase) {
2905  sync_xcor = CWB::mdc::TimeSync(wrec[n], wINJ[i][n], sync_time);
2906  sprintf(sout,"wINJ Time Sync -> ifo = %*s - evtId = %*d / %*d - sync_time = %*.4f sec - sync_xcor = %*.3f",
2907  2, gIFO[n].Data(), 5, i, 5 , nTRY, 7, sync_time, 6, sync_xcor);
2908  //cout << sout << endl;
2909  }
2910  if(gOPT.sync_phase && !gOPT.sync_time) {
2911  sync_xcor = CWB::mdc::PhaseSync(wrec[n], wINJ[i][n], sync_phase);
2912  sprintf(sout,"wINJ Phase Sync -> ifo = %*s - evtId = %*d / %*d - sync_phase = %*.1f deg - sync_xcor = %*.3f",
2913  2, gIFO[n].Data(), 5, i, 5 , nTRY, 6, sync_phase, 6, sync_xcor);
2914  //cout << sout << endl;
2915  }
2916  if(gOPT.sync_phase && gOPT.sync_time) {
2917  sync_xcor = CWB::mdc::TimePhaseSync(wrec[n], wINJ[i][n], sync_time, sync_phase);
2918  sprintf(sout,"wINJ TimePhase Sync -> ifo = %*s - evtId = %*d / %*d - sync_time = %*.4f sec - sync_phase = %*.1f deg - sync_xcor = %*.3f",
2919  2, gIFO[n].Data(), 5, i, 5 , nTRY, 7, sync_time, 6, sync_phase, 6, sync_xcor);
2920  //cout << sout << endl;
2921  }
2922  }
2923 
2924  vector<double> tstart;
2925  vector<double> tstop(nIFO);
2926  // select the left side of the waveform
2927  for(int n=0;n<nIFO;n++) {
2928  double inj_tcoa = gOPT.inj_time_step+fmod(wTCOA[i],1);
2929  tstop[n] = GetInjTcoa(inj_tcoa, NET, gIFO[n], wTHETA[i], wPHI[i]);
2930  }
2931 
2932  //float ET=0; for(int n=0;n<nIFO;n++) for(int j=0;j<wINJ[i][n].size();j++) ET+=pow(wINJ[i][n][j],2);
2933  double re = CWB::mdc::GetMatchFactor("re",wrec, wINJ[i],tstart,tstop);
2934  if(re>ref) M++;
2935  if(re<min) min=re;
2936  N++;
2937  }
2938  delete NET;
2939 
2940  float pvalue=(float)M/(float)N;
2941  return pvalue;
2942 }
2943 
2944 int
2945 GetOnSourceStatistic(int nIFO, double &mFF, double &mOF, double &mRE) {
2946 
2947  // compute statistics onsource/offsource reconstructed vs onsource/offsource injected
2948  // results are stored in xFF,xOF,xRE,xNE
2949  // WARNING!!! the offsource whitened waveforms are aligned in time to the onsource reconstructed waveform
2950  // -> from this point the offsource whitened waveforms can not be used for the standard comparison
2951 
2952  cout << endl << "Compute onsource distribution : be patient, it takes a while ..." << endl << endl;
2953 
2954  gnetwork* NET = new gnetwork(nIFO,gIFO);
2955 
2956  // align the injected sample waveforms respect to the point estimated
2957  for(int n=0;n<nIFO;n++) {
2958  for(int i=0;i<gEVENTS;i++) {
2959  if(wREC[i].size()) { // event detected
2960  wINJ[i][n] = CWB::mdc::GetAligned(&wINJ[i][n], &vREC[n]);
2961  } else { // event rejected (set to 0)
2962  wREC[i][n] = wINJ[i][n]; wREC[i][n]=0;
2963  }
2964  }
2965  }
2966 
2967  // phase time,sync the injected waveforms respect to the point estimated waveforms
2968  // NOTE: by default the time sync is applied, if requested also the phase sync is applied
2969  int pc = 0;
2970  int ipc = double(gEVENTS)/10.; if(ipc==0) ipc=1;
2971  for(int i=0;i<gEVENTS;i++) {
2972  if(i%ipc==0) {if(gEVENTS>100) {cout << pc<<"%";if (pc<100) cout << " - ";pc+=10;cout.flush();}}
2973  for(int n=0;n<nIFO;n++) {
2974  char sout[1024];
2975  double sync_phase, sync_time, sync_xcor;
2976  if(!gOPT.sync_phase) {
2977  sync_xcor = CWB::mdc::TimeSync(wINJ[i][n], vREC[n], sync_time);
2978  sprintf(sout,"Time Sync -> ifo = %*s - evtId = %*d / %*d - sync_time = %*.4f sec - sync_xcor = %*.3f",
2979  2, gIFO[n].Data(), 5, i+1, 5 , gEVENTS, 7, sync_time, 6, sync_xcor);
2980  //cout << sout << endl;
2981  }
2982  if(gOPT.sync_phase && gOPT.sync_time) {
2983  sync_xcor = CWB::mdc::TimePhaseSync(wINJ[i][n], vREC[n], sync_time, sync_phase);
2984  sprintf(sout,"TimePhase Sync -> ifo = %*s - evtId = %*d / %*d - sync_time = %*.4f sec - sync_phase = %*.1f deg - sync_xcor = %*.3f",
2985  2, gIFO[n].Data(), 5, i+1, 5 , gEVENTS, 7, sync_time, 6, sync_phase, 6, sync_xcor);
2986  //cout << sout << endl;
2987  }
2988  }
2989  }
2990  if(pc==100) cout << pc<<"%";;
2991  cout << endl << endl;
2992 
2993  // cWB point estimate Matching Factors respect to Posterior Samples Median
2994  std::vector<double> zFF,zRE;
2995  for(int i=0;i<gEVENTS;i++) {
2996 
2997  if(wREC[i].size()==0) continue;
2998 
2999  vector<double> tstart;
3000  if(gOPT.side=="right") {
3001  tstart.resize(nIFO);
3002  for(int n=0;n<nIFO;n++) {
3003  double inj_tcoa = gOPT.inj_time_step+fmod(vTCOA,1);
3004  tstart[n] = GetInjTcoa(inj_tcoa, NET, gIFO[n], vTHETA, vPHI);
3005  }
3006  }
3007 
3008  vector<double> tstop;
3009  if(gOPT.side=="left") {
3010  tstop.resize(nIFO);
3011  for(int n=0;n<nIFO;n++) {
3012  double inj_tcoa = gOPT.inj_time_step+fmod(vTCOA,1);
3013  tstop[n] = GetInjTcoa(inj_tcoa, NET, gIFO[n], vTHETA, vPHI);
3014  }
3015  }
3016 
3017  double FF = CWB::mdc::GetMatchFactor("ff",vREC,wINJ[i],tstart,tstop);
3018  double OF = CWB::mdc::GetMatchFactor("of",vREC,wINJ[i],tstart,tstop);
3019  double RE = CWB::mdc::GetMatchFactor("re",vREC,wINJ[i],tstart,tstop);
3020 
3021  xFF.push_back(FF);
3022  xOF.push_back(OF);
3023  xRE.push_back(RE);
3024 
3025  if(gOPT.residuals) { // null energy
3026  vector<wavearray<double> > vDAT = vNUL; for(int n=0;n<nIFO;n++) vDAT[n]+=vREC[n];
3027  double NE = CWB::mdc::GetMatchFactor("re",vDAT,wINJ[i],tstart,tstop);
3028  xNE.push_back(NE);
3029  }
3030 
3031  // compute FF/RE full/left side, used to get median sample for onsource comparision
3032  if(gOPT.use_onsrc=="mfull" || gOPT.use_onsrc=="mleft") {
3033  tstart.resize(0);
3034  if(gOPT.use_onsrc=="mfull") {
3035  tstop.resize(0);
3036  } else {
3037  tstop.resize(nIFO);
3038  for(int n=0;n<nIFO;n++) {
3039  double inj_tcoa = gOPT.inj_time_step+fmod(vTCOA,1);
3040  tstop[n] = GetInjTcoa(inj_tcoa, NET, gIFO[n], vTHETA, vPHI);
3041  }
3042  }
3043  FF = CWB::mdc::GetMatchFactor("ff",vREC,wINJ[i],tstart,tstop);
3044  zFF.push_back(FF);
3045  } else { // efull/eleft
3046  tstart.resize(0);
3047  if(gOPT.use_onsrc=="efull") {
3048  tstop.resize(0);
3049  } else {
3050  tstop.resize(nIFO);
3051  for(int n=0;n<nIFO;n++) {
3052  double inj_tcoa = gOPT.inj_time_step+fmod(vTCOA,1);
3053  tstop[n] = GetInjTcoa(inj_tcoa, NET, gIFO[n], vTHETA, vPHI);
3054  }
3055  }
3056  RE = CWB::mdc::GetMatchFactor("re",vREC,wINJ[i],tstart,tstop);
3057  zRE.push_back(RE);
3058  }
3059  }
3060 
3061  int imed=-1;
3062  if(gOPT.use_onsrc!="") {
3063  // compute onsource median
3064  int nentries = (gOPT.use_onsrc=="mfull" || gOPT.use_onsrc=="mleft") ? zFF.size() : zRE.size();
3065  int *index = new int[nentries];
3066  float *value = new float[nentries];
3067 
3068  // compute median FF/RE full/left side onsource distribution
3069  for(int i=0;i<nentries;i++) value[i] = (gOPT.use_onsrc=="mfull" || gOPT.use_onsrc=="mleft") ? zFF[i] : zRE[i];
3070  TMath::Sort(nentries,value,index,false);
3071 
3072  imed = int((nentries*50.)/100.);
3073 
3074  // get medians
3075  mFF = xFF[index[imed]];
3076  mOF = xOF[index[imed]];
3077  mRE = xRE[index[imed]];
3078 
3079  delete [] index;
3080  delete [] value;
3081  }
3082 
3083  delete NET;
3084 
3085  return imed;
3086 }
3087 
3088 void
3089 GetOffSourceStatistic(int nIFO, int recId, vector<int> injId,
3090  vector<double>& oFF, vector<double>& oOF, vector<double>& oRE) {
3091 
3092  // compute statistics offsource reconstructed vs offsource injected
3093  // results are stored in oFF,oOF,oRE
3094  // WARNING!!! the offsource whitened waveforms are aligned in time to the onsource reconstructed waveform
3095  // -> from this point the offsource whitened waveforms can not be used for the standard comparison
3096 
3097  if(recId>=gEVENTS) return;
3098 
3099  gnetwork* NET = new gnetwork(nIFO,gIFO);
3100 
3101  int kEVENTS = gOPT.rstat_jtrials;
3102 
3103  // set reconstructed off-source event
3104  std::vector<wavearray<double> > oREC = recId>=0 ? wREC[recId] : vREC;
3105 
3106  std::vector<wavearray<double> > oINJ[PE_MAX_EVENTS]; // OffSource iwhitened injected posteriors
3107 
3108  // align the injected sample waveforms respect to the point estimated
3109  for(int k=0;k<kEVENTS;k++) {
3110  int i=injId[k];
3111  for(int n=0;n<nIFO;n++) oINJ[i].push_back(CWB::mdc::GetAligned(&wINJ[i][n], &oREC[n]));
3112  }
3113 
3114  // phase time,sync the injected waveforms respect to the point estimated waveforms
3115  // NOTE: by default the time sync is applied, if requested also the phase sync is applied
3116  for(int k=0;k<kEVENTS;k++) {
3117  int i=injId[k];
3118 
3119  // compute optimal phase/time shifts for each detector
3120  char sout[1024];
3121  double sync_phase[NIFO_MAX], sync_time[NIFO_MAX], sync_xcor[NIFO_MAX];
3122  for(int n=0;n<nIFO;n++) {
3123  if(gOPT.sync_phase) { // apply time/phase sync
3124  sync_xcor[n] = CWB::mdc::TimePhaseSync(oINJ[i][n], oREC[n], sync_time[n], sync_phase[n]);
3125  sprintf(sout,"TimePhase Sync -> ifo = %*s - evtId = %*d / %*d - sync_time = %*.4f sec - sync_phase = %*.1f deg - sync_xcor = %*.3f",
3126  2, gIFO[n].Data(), 5, i+1, 5 , gEVENTS, 7, sync_time[n], 6, sync_phase[n], 6, sync_xcor[n]);
3127  } else { // apply time sync
3128  sync_xcor[n] = CWB::mdc::TimeSync(oINJ[i][n], oREC[n], sync_time[n]);
3129  sprintf(sout,"Time Sync -> ifo = %*s - evtId = %*d / %*d - sync_time = %*.4f sec - sync_xcor = %*.3f",
3130  2, gIFO[n].Data(), 5, i+1, 5 , gEVENTS, 7, sync_time[n], 6, sync_xcor[n]);
3131  }
3132  //cout << sout << endl;
3133  }
3134 /*
3135  // computed weighted average sync phase/time
3136  double wsnr2=0.;
3137  double wsync_phase=0.;
3138  double wsync_time=0.;
3139  for(int n=0;n<nIFO;n++) {
3140  wsync_phase+=pow(wSNR[k][n],2)*sync_phase[n];
3141  wsync_time+=pow(wSNR[k][n],2)*sync_time[n];
3142  wsnr2+=pow(wSNR[k][n],2);
3143  }
3144  wsync_phase/=wsnr2;
3145  wsync_time /=wsnr2;
3146 
3147  // restore original time/phase and apply global weighted average sync phese/time
3148  for(int n=0;n<nIFO;n++) {
3149  if(!gOPT.sync_phase) {
3150  CWB::mdc::TimeSync(oINJ[i][n], wsync_time-sync_time[n]);
3151  if(n==0) sprintf(sout,"Time Sync -> - evtId = %*d / %*d - sync_time = %*.4f sec",
3152  5, k+1, 5 , gEVENTS, 7, wsync_time);
3153  }
3154  if(gOPT.sync_phase && gOPT.sync_time) {
3155  CWB::mdc::TimePhaseSync(oINJ[i][n], wsync_time-sync_time[n], wsync_phase-sync_phase[n]);
3156  if(n==0) sprintf(sout,"TimePhase Sync -> - evtId = %*d / %*d - sync_time = %*.4f sec - sync_phase = %*.1f deg",
3157  5, k+1, 5 , gEVENTS, 7, wsync_time, 6, wsync_phase);
3158  }
3159  }
3160 */
3161  //cout << sout << endl;
3162  }
3163 
3164  // cWB point estimate Matching Factors respect to Posterior Samples Median
3165  for(int k=0;k<kEVENTS;k++) {
3166  int i=injId[k];
3167 
3168  if(wREC[i].size()==0) continue;
3169 
3170  vector<double> tstart;
3171  if(gOPT.side=="right") {
3172  tstart.resize(nIFO);
3173  for(int n=0;n<nIFO;n++) {
3174  double inj_tcoa = gOPT.inj_time_step+fmod(vTCOA,1);
3175  tstart[n] = GetInjTcoa(inj_tcoa, NET, gIFO[n], vTHETA, vPHI);
3176  }
3177  }
3178 
3179  vector<double> tstop;
3180  if(gOPT.side=="left") {
3181  tstop.resize(nIFO);
3182  for(int n=0;n<nIFO;n++) {
3183  double inj_tcoa = gOPT.inj_time_step+fmod(vTCOA,1);
3184  tstop[n] = GetInjTcoa(inj_tcoa, NET, gIFO[n], vTHETA, vPHI);
3185  }
3186  }
3187 
3188  if(oINJ[i].size()!=oREC.size()) {
3189  cout << "GetOffSourceStatistic - Error: the elements of input injId vector are not unique !!!" << endl;
3190  gSystem->Exit(1);
3191  }
3192 
3193  double FF = CWB::mdc::GetMatchFactor("ff",oREC,oINJ[i],tstart,tstop);
3194  double OF = CWB::mdc::GetMatchFactor("of",oREC,oINJ[i],tstart,tstop);
3195  double RE = CWB::mdc::GetMatchFactor("re",oREC,oINJ[i],tstart,tstop);
3196 
3197  oFF.push_back(FF);
3198  oOF.push_back(OF);
3199  oRE.push_back(RE);
3200  }
3201 
3202  delete NET;
3203 
3204  return;
3205 }
3206 
3208 
3209  if(type!="FF" && type!="OF" && type!="RE") {
3210  cout << "MakePvalueDistribution - Error : plot type not available, must be FF/OF/REE" << endl;
3211  gSystem->Exit(1);
3212  }
3213 
3214  TCanvas* cpd = new TCanvas("PvalueDistribution", "PvalueDistribution", 200, 20, 1000, 600);
3215  cpd->SetLogx(false);
3216  cpd->SetLogy(true);
3217  cpd->SetGridx(true);
3218  cpd->SetGridy(true);
3219 
3220  gStyle->SetOptStat("emr");
3221 
3222  // histogram of matching factor onsource reconstructed vs offsource injected
3223  TH1F* hist = new TH1F("hpvalue","hpvalue",100,0,1);
3224  //hist->SetStats(kFALSE);
3225  hist->SetLineWidth(2);
3226  hist->SetLineColor(kGreen+2);
3227 
3228  // sort null hyphotesis values
3229  int nentries=vFF.size()-1; // index=0 contains onsource
3230  int *index = new int[nentries];
3231  float *value = new float[nentries];
3232  for(int i=0;i<nentries;i++) {
3233  if(type=="FF") value[i]=vFF[i+1];
3234  if(type=="OF") value[i]=vOF[i+1];
3235  if(type=="RE") value[i]=vRE[i+1];
3236  }
3237  TMath::Sort(nentries,value,index,false);
3238 
3239  int onsize=xFF.size();
3240  float *pvalue = new float[onsize];
3241  for(int i=0;i<onsize;i++) {
3242  double x;
3243  if(type=="FF") x=xFF[i];
3244  if(type=="OF") x=xOF[i];
3245  if(type=="RE") x=xRE[i];
3246  bool loop=true;
3247  // find pvalue of x using dichotomic search
3248  int imed=0;
3249  int imin=0;
3250  int imax=nentries-1;
3251  while(loop) {
3252  imed = imin+int((imax-imin)*50./100.);
3253  if(imed>=imax) imed=imax;
3254  double xmed=value[index[imed]];
3255  imin = (x<xmed) ? imin : imed;
3256  imax = (x<xmed) ? imed : imax;
3257  if(imax==imin+1) loop=false;
3258  }
3259  if(type=="FF") pvalue[i]=double(imed)/double(nentries);
3260  if(type=="OF") pvalue[i]=double(imed)/double(nentries);
3261  if(type=="RE") pvalue[i]=double(nentries-imed)/double(nentries);
3262  hist->Fill(pvalue[i]);
3263  }
3264  delete [] index;
3265  delete [] value;
3266 
3267  // compute pvalue median and 90% lower/upper limits
3268  int *pindex = new int[onsize];
3269  TMath::Sort(onsize,pvalue,pindex,false);
3270  float pvalue_med = pvalue[pindex[int(onsize*50./100.)]];
3271  float pvalue_l90 = pvalue[pindex[int(onsize* 5./100.)]];
3272  float pvalue_u90 = pvalue[pindex[int(onsize*95./100.)]];
3273 
3274  hist->GetXaxis()->SetTitle("pvalue");
3275  hist->GetXaxis()->SetTitleOffset(1.4);
3276  hist->GetXaxis()->SetLabelOffset(0.02);
3277  hist->GetXaxis()->SetNoExponent();
3278 
3279  hist->GetYaxis()->SetTitle("counts");
3280  hist->GetYaxis()->SetTitleOffset(1.6);
3281  hist->GetYaxis()->SetLabelOffset(0.02);
3282  hist->GetYaxis()->SetNoExponent();
3283  hist->GetYaxis()->SetNdivisions(3);
3284 
3285  TString xtitle="";
3286  if(type=="FF") xtitle="Fitting Factor";
3287  if(type=="OF") xtitle="Overlap Factor";
3288  if(type=="RE") xtitle="Residual Energy";
3289 
3290  char htitle[256];
3291  sprintf(htitle,"%s %s (%s) - %s on-source p-value distribution (l90=%f, med=%f, u90=%f)",
3292  gOPT.gw_name.Data(),xtitle.Data(),gOPT.side.Data(),type.Data(),pvalue_l90,pvalue_med,pvalue_u90);
3293  hist->SetTitle(htitle);
3294  hist->SetName("Statistic");
3295  hist->Draw("HIST");
3296 
3297  // draw vertical lines at the pvalue med/l90/u90
3298  float ymax = hist->GetMaximum();
3299  TLine *line_med = new TLine(pvalue_med,0,pvalue_med,ymax);
3300  line_med->SetLineWidth(2);
3301  line_med->SetLineColor(kRed);
3302  line_med->Draw();
3303  TLine *line_l90 = new TLine(pvalue_l90,0,pvalue_l90,ymax);
3304  line_l90->SetLineWidth(2);
3305  line_l90->SetLineColor(kBlue);
3306  line_l90->Draw();
3307  TLine *line_u90 = new TLine(pvalue_u90,0,pvalue_u90,ymax);
3308  line_u90->SetLineWidth(2);
3309  line_u90->SetLineColor(kBlue);
3310  line_u90->Draw();
3311 
3312  // set stats box line color black
3313  cpd->Update();
3314  TPaveStats *ptstats = (TPaveStats*)cpd->GetPrimitive("stats");
3315  ptstats->SetLineColor(kBlack);
3316  cpd->Modified();
3317 
3318  TString pdir=gOPT.plot_odir;
3319  xtitle.ReplaceAll(" ","");
3320  char ofname[256];
3321  sprintf(ofname,"%s_%s_%s.png",gOPT.plot_fname.Data(),"onsource_pvalue_distribution",xtitle.Data());
3322  TString fName = pdir!="" ? TString(pdir)+TString("/")+ofname : ofname;
3323  cpd->Print(fName);
3324  cout << "write : " << fName << endl;
3325  fName.ReplaceAll(".png",".root");
3326  cpd->Print(fName);
3327  cout << "write : " << fName << endl;
3328 
3329  // dump sorted pvalue onsource statistic
3330  sprintf(ofname,"%s_%s_%s.txt",gOPT.plot_fname.Data(),xtitle.Data(),"onsource_pvalue_statistic");
3331  fName = pdir!="" ? TString(pdir)+TString("/")+ofname : ofname;
3332  for(int i=0;i<onsize;i++) {
3333  TString parm = TString::Format("%f",pvalue[pindex[i]]);
3334  if(i==0) DumpStatistics(fName, parm, false);
3335  else DumpStatistics(fName, parm, true);
3336  }
3337 
3338  delete [] pindex;
3339  delete [] pvalue;
3340 
3341  delete line_med;
3342  delete line_l90;
3343  delete line_u90;
3344  delete hist;
3345  delete cpd;
3346 }
3347 
3348 int SyncWaveforms(int nIFO, TString type) {
3349 
3350 // for type=statistics the reference is INJ, this choice permits to fix the tcoa
3351 // for type=waveform the reference is REC, this choice is necessary to fix the original onsource waveform
3352 
3353  if(type!="statistics" && type!="waveform") return 0;
3354 
3355  int selected=0;
3356  if(type=="statistics" || gOPT.plot_type=="phase") {
3357  // align onsource/offsource sample waveforms respect to the reconstructed
3358  for(int n=0;n<nIFO;n++) {
3359  selected=0;
3360  CWB::mdc::Align(vINJ[n], vREC[n]); // onsource waveform
3361  if(gOPT.residuals) vNUL[n]=CWB::mdc::GetAligned(&vNUL[n], &vREC[n]); // onsource null
3362  for(int i=0;i<gEVENTS;i++) {
3363  if(wREC[i].size()) { // event detected
3364  CWB::mdc::Align(wINJ[i][n], wREC[i][n]); // offsource waveform
3365  if(gOPT.residuals) wNUL[i][n]=CWB::mdc::GetAligned(&wNUL[i][n], &wREC[i][n]); // offsource null
3366  if(gOPT.side=="rcut") wAUX[i][n]=CWB::mdc::GetAligned(&wAUX[i][n], &wREC[i][n]); // offsource auxiliary
3367  selected++;
3368  }
3369  }
3370  if(selected==0) return 0; // return if no events are detects
3371  }
3372  } else {
3373  // align the reconstructed waveforms respect to the point estimated
3374  for(int n=0;n<nIFO;n++) {
3375  selected=0;
3376  for(int i=0;i<gEVENTS;i++) {
3377  if(wREC[i].size()) { // event detected
3378  wREC[i][n] = CWB::mdc::GetAligned(&wREC[i][n], &vREC[n]);
3379  if(gOPT.residuals) wNUL[i][n] = CWB::mdc::GetAligned(&wNUL[i][n], &vNUL[n]);
3380  if(gOPT.side=="rcut") wAUX[i][n] = CWB::mdc::GetAligned(&wAUX[i][n], &vAUX[n]);
3381  selected++;
3382  } else { // event rejected (set to 0)
3383  wREC[i][n] = vREC[n]; wREC[i][n]=0;
3384  if(gOPT.residuals) wNUL[i][n] = vNUL[n]; wNUL[i][n]=0;
3385  if(gOPT.side=="rcut") wAUX[i][n] = vAUX[n]; wAUX[i][n]=0;
3386  }
3387  }
3388  if(selected==0) return 0; // return if no events are detects
3389  }
3390  }
3391 
3392  if(gOPT.sync_phase || gOPT.sync_time) {
3393 
3394  // OnSource - phase time,sync the reconstructed waveforms respect to the injected waveforms
3395  for(int n=0;n<nIFO;n++) {
3396 
3397  wavearray<double>* wref = type=="statistics" || gOPT.plot_type=="phase" ? &vINJ[n] : &vREC[n];
3398  wavearray<double>* wsht = type=="statistics" || gOPT.plot_type=="phase" ? &vREC[n] : &vREC[n];
3399 
3400  char sout[1024];
3401  double sync_phase, sync_time, sync_xcor;
3402  if(gOPT.sync_time && !gOPT.sync_phase) {
3403  sync_xcor = CWB::mdc::TimeSync(*wsht, *wref, sync_time);
3404  vTSYNC[n]+=sync_time;
3405  sprintf(sout,"Time Sync -> ifo = %*s - sync_time = %*.4f sec - sync_xcor = %*.3f",
3406  2, gIFO[n].Data(), 7, sync_time, 6, sync_xcor);
3407  cout << sout << endl;
3408  if(gOPT.side=="rcut") CWB::mdc::TimeSync(vAUX[n], sync_time);
3409  }
3410  if(gOPT.sync_phase && !gOPT.sync_time) {
3411  sync_xcor = CWB::mdc::PhaseSync(*wsht, *wref, sync_phase);
3412  vPSYNC[n]+=sync_phase;
3413  sprintf(sout,"Phase Sync -> ifo = %*s - sync_phase = %*.1f deg - sync_xcor = %*.3f",
3414  2, gIFO[n].Data(), 6, sync_phase, 6, sync_xcor);
3415  cout << sout << endl;
3416  if(gOPT.side=="rcut") CWB::mdc::PhaseSync(vAUX[n], sync_phase);
3417  }
3418  if(gOPT.sync_phase && gOPT.sync_time) {
3419  sync_xcor = CWB::mdc::TimePhaseSync(*wsht, *wref, sync_time, sync_phase);
3420  vTSYNC[n]+=sync_time;
3421  vPSYNC[n]+=sync_phase;
3422  sprintf(sout,"TimePhase Sync -> ifo = %*s - sync_time = %*.4f sec - sync_phase = %*.1f deg - sync_xcor = %*.3f",
3423  2, gIFO[n].Data(), 7, sync_time, 6, sync_phase, 6, sync_xcor);
3424  cout << sout << endl;
3425  if(gOPT.side=="rcut") CWB::mdc::TimePhaseSync(vAUX[n], sync_time, sync_phase);
3426  }
3427  }
3428 
3429  // OffSource - phase time,sync the reconstructed waveforms respect to the injected waveforms
3430  for(int i=0;i<gEVENTS;i++) {
3431  for(int n=0;n<nIFO;n++) {
3432 
3433  wavearray<double>* wref = type=="statistics" || gOPT.plot_type=="phase" ? &wINJ[i][n] : &vREC[n];
3434  wavearray<double>* wsht = type=="statistics" || gOPT.plot_type=="phase" ? &wREC[i][n] : &wREC[i][n];
3435 
3436  char sout[1024];
3437  double sync_phase, sync_time, sync_xcor;
3438  if(gOPT.sync_time && !gOPT.sync_phase) {
3439  sync_xcor = CWB::mdc::TimeSync(*wsht, *wref, sync_time);
3440  sprintf(sout,"Time Sync -> ifo = %*s - evtId = %*d / %*d - sync_time = %*.4f sec - sync_xcor = %*.3f",
3441  2, gIFO[n].Data(), 5, i+1, 5 , gEVENTS, 7, sync_time, 6, sync_xcor);
3442  cout << sout << endl;
3443  if(gOPT.side=="rcut") CWB::mdc::TimeSync(wAUX[i][n], sync_time);
3444  }
3445  if(gOPT.sync_phase && !gOPT.sync_time) {
3446  sync_xcor = CWB::mdc::PhaseSync(*wsht, *wref, sync_phase);
3447  sprintf(sout,"Phase Sync -> ifo = %*s - evtId = %*d / %*d - sync_phase = %*.1f deg - sync_xcor = %*.3f",
3448  2, gIFO[n].Data(), 5, i+1, 5 , gEVENTS, 6, sync_phase, 6, sync_xcor);
3449  cout << sout << endl;
3450  if(gOPT.side=="rcut") CWB::mdc::PhaseSync(wAUX[i][n], sync_phase);
3451  }
3452  if(gOPT.sync_phase && gOPT.sync_time) {
3453  sync_xcor = CWB::mdc::TimePhaseSync(*wsht, *wref, sync_time, sync_phase);
3454  sprintf(sout,"TimePhase Sync -> ifo = %*s - evtId = %*d / %*d - sync_time = %*.4f sec - sync_phase = %*.1f deg - sync_xcor = %*.3f",
3455  2, gIFO[n].Data(), 5, i+1, 5 , gEVENTS, 7, sync_time, 6, sync_phase, 6, sync_xcor);
3456  cout << sout << endl;
3457  if(gOPT.side=="rcut") CWB::mdc::TimePhaseSync(wAUX[i][n], sync_time, sync_phase);
3458  }
3459  }
3460  }
3461  }
3462 
3463  if(gOPT.side=="rcut") {
3464  cout << endl << "Apply RCut : be patient, it takes a while ..." << endl << endl;
3465  int pc = 0;
3466  int ipc = double(gEVENTS)/10.; if(ipc==0) ipc=1;
3467  for(int n=0;n<nIFO;n++) {
3468  for(int i=0;i<gEVENTS;i++) {
3469  if(n==nIFO-1 && i%ipc==0) {if(gEVENTS>100) {cout << pc<<"%";if (pc<100) cout << " - ";pc+=10;cout.flush();}}
3470  wINJ[i][n] = GetRCut(&wINJ[i][n],&wAUX[i][n]);
3471  wREC[i][n] = GetRCut(&wREC[i][n],&wAUX[i][n]);
3472  }
3473  vINJ[n] = GetRCut(&vINJ[n],&vAUX[n]);
3474  vREC[n] = GetRCut(&vREC[n],&vAUX[n]);
3475  }
3476  if(pc==100) cout << pc<<"%";;
3477  cout << endl << endl;
3478  }
3479 
3480  // convert time wavearray into envelope/frequency/spectrum
3481  if(type=="waveform") {
3482  for(int n=0;n<nIFO;n++) {
3483  for(int i=0;i<gEVENTS;i++) {
3484  // convert wREC[i][n] time into envelope
3485  if(gOPT.plot_type=="envelope") wREC[i][n] = CWB::Toolbox::getHilbertEnvelope(wREC[i][n]);
3486  // convert wREC[i][n] time into frequency
3487  if(gOPT.plot_type=="frequency") wREC[i][n] = CWB::Toolbox::getHilbertIFrequency(wREC[i][n]);
3488  // convert wREC[i][n] time into spectrum oneside
3489  if(gOPT.plot_type=="spectrum") wREC[i][n] = CWB::mdc::GetSpectrum(&wREC[i][n],true);
3490  }
3491  // convert vREC[n] time into envelope
3492  if(gOPT.plot_type=="envelope") vREC[n] = CWB::Toolbox::getHilbertEnvelope(vREC[n]);
3493  // convert vREC[n] time into frequency
3494  if(gOPT.plot_type=="frequency") vREC[n] = CWB::Toolbox::getHilbertIFrequency(vREC[n]);
3495  // convert vREC[n] time into spectrum oneside
3496  if(gOPT.plot_type=="spectrum") vREC[n] = CWB::mdc::GetSpectrum(&vREC[n],true);
3497  }
3498 
3499  // convert vREC[n] time into phase
3500  wavearray<double> fi,fr,s,t;
3501  if(gOPT.plot_type=="phase") {
3502  for(int n=0;n<nIFO;n++) {
3503  for(int i=0;i<gEVENTS;i++) {
3504  wREC[i][n] = CWB::Toolbox::GetPhase(wINJ[i][n], wREC[i][n], fi, fr, s, t);
3505  wREC[i][n].resize(gOPT.ncycles);
3506  wREC[i][n]*=180.;
3507  }
3508  }
3509  for(int n=0;n<nIFO;n++) {
3510  pSNR.push_back(s); // cumulative SNR of vINJ[n]+vREC[n]
3511  pFRQ.push_back(fi); // vINJ[n] frequency
3512  pTIM.push_back(t); // vINJ[n] time
3513  vREC[n] = CWB::Toolbox::GetPhase(vINJ[n], vREC[n], pFRQ[n], fr, pSNR[n], pTIM[n]);
3514  vREC[n].resize(gOPT.ncycles);
3515  vREC[n]*=180.;
3516  // set max pFRQ and max pSNR to 180
3517  pFRQ[n]*=180./pFRQ[n].max();
3518  pSNR[n]*=180./pSNR[n].max();
3519  }
3520  }
3521  }
3522 
3523  return selected;
3524 }
3525 
3527 // get params from log string
3528 
3529  TObjArray* token = log.Tokenize(TString(" "));
3530  for(int i=0;i<token->GetEntries();i++) {
3531  TObjString* otoken = (TObjString*)token->At(i);
3532  TString stoken = otoken->GetString();
3533  // exctract value
3534  if(stoken==param) {
3535  if(i<token->GetEntries()-1) {
3536  if(stoken=="spin1" || stoken=="spin2") {
3537  otoken = (TObjString*)token->At(i+3); // get spinz
3538  return otoken->GetString();
3539  } else {
3540  otoken = (TObjString*)token->At(i+1);
3541  return otoken->GetString();
3542  }
3543  }
3544  }
3545  }
3546  if(token) delete token;
3547 
3548  return "";
3549 }
3550 
3551 double GetCCut(wavearray<double>* ts, double tcoa, double m1, double m2, double s1z, double s2z) {
3552 // apply chirp TF cuts and compute total energy inside the chirp cut region
3553 
3554  // NOTE: the current inmplementation works only with SEOBNRv4ROM model
3555 
3556  const auto& fchirp = static_cast<double(*)(double,double,double,double,double)>(CWB::mdc::SimIMRSEOBNRv4ROMFrequencyOfTime);
3557  const auto& tchirp = static_cast<double(*)(double,double,double,double,double)>(CWB::mdc::SimIMRSEOBNRv4ROMTimeOfFrequency);
3558 
3559  // produce the TF map:
3560  WSeries<double> W; // TF map container
3561  W.Forward(*ts, *gWDM); // apply the WDM to the time series
3562 
3563  double fmin=16;
3564  // set the initial value of fmax using the global variable gOPT.ccut_fmax
3565  // the LAL functions XLALSimIMRSEOBNRv4ROMFrequencyOfTime/XLALSimIMRSEOBNRv4ROMTimeOfFrequency use spline and works only
3566  // for a given frequency interval which depends on masses and spins of the binary system
3567  double fmax= ts->rate()/2.>gOPT.ccut_fmax ? gOPT.ccut_fmax : ts->rate()/2.;
3568 
3569  int nPx=30; // number of points (nPx) used to compute the up/bottom chirp lines
3570  double T[nPx],Fb[nPx],Fu[nPx];
3571  double dF = (fmax-fmin)/nPx;
3572  for(int i=0;i<nPx;i++) {
3573  double F = fmin+i*dF;
3574  Fb[i] = gOPT.ccut_bchirp*F; // alpha bottom
3575  Fu[i] = gOPT.ccut_uchirp*F; // alpha up
3576  double t=tchirp(F,m1,m2,s1z,s2z);
3577  if(t<0) { // the LAL function return error because frequency is not in the available frequency range
3578  cout << "cwb_pereport:GetCCut - update gOPT.ccut_fmax frequency to " << F
3579  << " Hz in order to avoid errors in LAL functions XLALSimIMRSEOBNRv4ROMFrequencyOfTime/XLALSimIMRSEOBNRv4ROMTimeOfFrequency" << endl;
3580  gOPT.ccut_fmax=fmin+(i-1)*dF; // update gOPT.ccut_fmax frequency
3581  nPx=i; // update the number of points (nPx) used to compute the up/bottom chirp lines
3582  } else {
3583  T[i] = tcoa-t;
3584  }
3585  }
3586  TSpline3 tbchirp("tbchirp",Fb,T,nPx); // bottom chirp line (time vs freq)
3587  TSpline3 tuchirp("tuchirp",Fu,T,nPx); // up chirp line (time vs freq)
3588  TSpline3 fbchirp("fbchirp",T,Fb,nPx); // bottom chirp line (freq vs time)
3589  TSpline3 fuchirp("fuchirp",T,Fu,nPx); // up chirp line (freq vs time)
3590 
3591  double df = W.resolution(); // frequency pixel resolution (hz)
3592  double dt = 1./(2*df); // time pixel resolution (sec)
3593 
3594  int layers = W.maxLayer()+1; // numbers of frequency bins (first & last bins have df/2)
3595  int slices = W.sizeZero(); // number of time bins
3596 
3597  double tl = tcoa-gOPT.ccut_ltime; // left time cut
3598  double tr = tcoa-gOPT.ccut_rtime; // right time cut
3599 
3600  // rescale the phase 00/90 pixel amplitudes
3601 
3602  for(int i=1;i<slices;i++) { // loop over time bins, skip first slice
3603 
3604  double time = i*dt; // pixel central time
3605 
3606  double tm = time-dt/2; // pixel minimum time
3607  double tM = time+dt/2; // pixel maximum time
3608 
3609  if(tm<tl-dt || tM>tr+dt) { // remove pixels outside the time interval [tl-dt:tr+dt]
3610  for(int j=1;j<layers;j++) { // loop over frequency bins
3611  W.putSample(0,i,j+0.01); // zero a00 pixel amplitude
3612  W.putSample(0,i,-(j+0.01)); // zero a90 pixel amplitude
3613  }
3614  continue;
3615  }
3616 
3617  double fb = fbchirp.Eval(time); // fbchirp frequency at pixel central time
3618  double fu = fuchirp.Eval(time); // fuchirp frequency at pixel central time
3619 
3620  if(TMath::IsNaN(fb)) fb = ts->rate()/2.; // check if fb is NaN
3621  if(TMath::IsNaN(fu)) fu = ts->rate()/2.; // check if fu is NaN
3622 
3623  double f1 = fbchirp.Eval(tm); // fbchirp frequency at pixel minimum time
3624  double f2 = fbchirp.Eval(tM); // fbchirp frequency at pixel maximum time
3625  double f3 = fuchirp.Eval(tm); // fuchirp frequency at pixel minimum time
3626  double f4 = fuchirp.Eval(tM); // fuchirp frequency at pixel maximum time
3627 
3628  for(int j=1;j<layers;j++) { // loop over frequency bins, skip first layer
3629 
3630  double freq = j*df; // pixel central frequency
3631 
3632  double fm = freq-df/2; // pixel minimum frequency
3633  double fM = freq+df/2; // pixel maximum frequency
3634 
3635  if(fm<fmin || fM>fmax) {
3636  W.putSample(0,i,j+0.01); // zero a00 pixel amplitude
3637  W.putSample(0,i,-(j+0.01)); // zero a90 pixel amplitude
3638  continue;
3639  }
3640 
3641  double t1 = tbchirp.Eval(fm); // fbchirp time at pixel minimum frequency
3642  double t2 = tbchirp.Eval(fM); // fbchirp time at pixel maximum frequency
3643  double t3 = tuchirp.Eval(fm); // fuchirp time at pixel minimum frequency
3644  double t4 = tuchirp.Eval(fM); // fuchirp time at pixel maximum frequency
3645 
3646  // check if pixel is inside the time cut range tl,tr
3647  bool ctime = (tM>tl && tm<tr) ? true : false;
3648 
3649  // check if pixel is inside the frequency cut range fb,fu
3650  bool cfreq = (fM>fb && fm<fu) ? true : false;
3651 
3652  double x1=t1,x2=t2,x3=t3,x4=t4,xm=tm,xM=tM; // assign x* = t*
3653  double y1=f1,y2=f2,y3=f3,y4=f4,ym=fm,yM=fM; // assign y* = f*
3654 
3655  // for pixels crossed by the cut times tl,tr assign new time pixel boundaries xm,xM and new f*
3656  if(tl>tm && tl<tM) {xm=tl; f1 = fbchirp.Eval(xm); f3 = fuchirp.Eval(xm);}
3657  if(tr>tm && tr<tM) {xM=tr; f2 = fbchirp.Eval(xM); f4 = fuchirp.Eval(xM);}
3658 
3659  y1=f1,y2=f2,y3=f3,y4=f4; // update y*
3660 
3661  // check if pixel is crossed by fbchirp,fuchirp lines
3662  // a pixel is crossed by the chirp lines if at least one of t*,f* points are inside the time/freq pixel ranges
3663 
3664  bool cline=false; // false/true = not-crossed/crossed
3665 
3666  if(t1>xm && t1<xM) cline=true;
3667  if(t2>xm && t2<xM) cline=true;
3668  if(t3>xm && t3<xM) cline=true;
3669  if(t4>xm && t4<xM) cline=true;
3670 
3671  if(f1>ym && f1<yM) cline=true;
3672  if(f2>ym && f2<yM) cline=true;
3673  if(f3>ym && f3<yM) cline=true;
3674  if(f4>ym && f4<yM) cline=true;
3675 
3676  double Ap=(xM-xm)*(yM-ym); // area pixel (is <=0.5 = total pixel area)
3677 
3678  if(ctime&&cline) { // pixels crossed by fbchirp,fuchirp lines and inside the time cut range tl,tr
3679 
3680  // for pixels with frequency outside the frequency pixel range assign ym,yM
3681  if(y1<ym) y1=ym; if(y1>yM) y1=yM;
3682  if(y2<ym) y2=ym; if(y2>yM) y2=yM;
3683  if(y3<ym) y3=ym; if(y3>yM) y3=yM;
3684  if(y4<ym) y4=ym; if(y4>yM) y4=yM;
3685 
3686  // compute area Ab for pixels crossed by fbchirp line
3687 
3688  double Ab=0; // area pixel above the fbchirp line
3689 
3690  // for pixels with times t1,t2 outside the time pixel range assign xm,xM and compute the corresponding new frequencies y1,y2
3691  if(t1<xm) {x1=xm; y1 = fbchirp.Eval(x1);}
3692  if(t1>xM) {x1=xM; y1 = fbchirp.Eval(x1);}
3693  if(t2<xm) {x2=xm; y2 = fbchirp.Eval(x2);}
3694  if(t2>xM) {x2=xM; y2 = fbchirp.Eval(x2);}
3695 
3696  // for pixels with frequency outside the frequency pixel range assign ym,yM
3697  if(y1<ym) y1=ym; if(y1>yM) y1=yM;
3698  if(y2<ym) y2=ym; if(y2>yM) y2=yM;
3699 
3700  // compute area pixel above the fbchirp line
3701  if(y1 >ym && y2==yM) Ab = (x2-xm)*(yM-y1)/2;
3702  if(y1 >ym && y2 <yM) Ab = (xM-xm)*(yM-y2)+(xM-xm)*(y2-y1)/2;
3703  if(y1==ym && y2==yM) Ab = (x1-xm)*(yM-ym)+(x2-x1)*(yM-ym)/2;
3704  if(y1==ym && y2 <yM) Ab = Ap-(xM-x1)*(y2-ym)/2;
3705 
3706  // compute area Au for pixels crossed by fuchirp line
3707 
3708  double Au=0; // area pixel below the fuchirp line
3709 
3710  // for pixels with times t3,t4 outside the time pixel range assign xm,xM and compute the corresponding new frequencies y3,y4
3711  if(t3<xm) {x3=xm; y3 = fuchirp.Eval(x3);}
3712  if(t3>xM) {x3=xM; y3 = fuchirp.Eval(x3);}
3713  if(t4<xm) {x4=xm; y4 = fuchirp.Eval(x4);}
3714  if(t4>xM) {x4=xM; y4 = fuchirp.Eval(x4);}
3715 
3716  // for pixels with frequency outside the frequency pixel range assign ym,yM
3717  if(y3<ym) y3=ym; if(y3>yM) y3=yM;
3718  if(y4<ym) y4=ym; if(y4>yM) y4=yM;
3719 
3720  // compute area pixel below the fuchirp line
3721  if(y3 >ym && y4==yM) Au = Ap-(x4-xm)*(yM-y3)/2;
3722  if(y3 >ym && y4 <yM) Au = (xM-xm)*(y3-ym)+(xM-xm)*(y4-y3)/2;
3723  if(y3==ym && y4==yM) Au = (xM-x4)*(yM-ym)+(x4-x3)*(yM-ym)/2;
3724  if(y3==ym && y4 <yM) Au = (xM-x3)*(y4-ym)/2;
3725 
3726  if(Ab<0) Ab=0; if(Ab>Ap) Ab=Ap; // fix area inconsistency due to precision errors
3727  if(Au<0) Au=0; if(Au>Au) Au=Au; // fix area inconsistency due to precision errors
3728  double A = Ab+Au; A-=Ap; // combine Ab and Au when pixel is crossed by fbchirp fuchirp lines
3729 
3730  if(A<0) {cout << "GetCCut Warning: pixel area < 0 " << endl; A=0;}
3731  if(A>Ap) {cout << "GetCCut Warning: pixel area > Ap " << endl; A=Ap;}
3732  double R=sqrt(A/0.5); // compute the rescaling amplitude factor (0.5 is the total pixel area)
3733 /*
3734  TString tag = R==0 ? "*" : "";
3735  TString sR = TString::Format("GetCCut Rescaling Factor: Ap %0.3f \ttime %0.3f \tfreq %0.3f \tR %0.3f \t%s",Ap,time,freq,R,tag.Data());
3736  cout << sR << endl;
3737 */
3738  double a00 = W.getSample(i,j+0.01); W.putSample(a00*R,i,j+0.01); // rescaling a00 pixel amplitude
3739  double a90 = W.getSample(i,-(j+0.01));W.putSample(a90*R,i,-(j+0.01)); // rescaling a90 pixel amplitude
3740  }
3741 
3742  if((ctime && cfreq) && !cline) { // pixels inside/outside the chirp cut area not belonging to the cline pixels
3743 
3744  double R = (x4<=tl || x1>=tr) ? 0 : sqrt(Ap/0.5); // compute the rescaling amplitude factor (0.5 is the total pixel area)
3745  // remove pixels outside the time interval [tl,tr]
3746 /*
3747  TString tag = "+";
3748  TString sR = TString::Format("GetCCut Rescaling Factor: Ap %0.3f \ttime %0.3f \tfreq %0.3f \tR %0.3f \t%s",Ap,time,freq,R,tag.Data());
3749  cout << sR << endl;
3750 */
3751  double a00 = W.getSample(i,j+0.01); W.putSample(a00*R,i,j+0.01); // rescaling a00 pixel amplitude
3752  double a90 = W.getSample(i,-(j+0.01));W.putSample(a90*R,i,-(j+0.01)); // rescaling a90 pixel amplitude
3753  }
3754 
3755  //if(ctime && cfreq) {
3756  //if(ctime && cline) {
3757  //if((ctime && cfreq) && !cline) {
3758  if((ctime && cline)||(ctime && cfreq)) {
3759  } else {
3760  W.putSample(0,i,j+0.01);
3761  W.putSample(0,i,-(j+0.01));
3762  }
3763  }
3764  }
3765 
3766  double Et=0; // Energy in time-frequency chirp cut region
3767  for(int i=1;i<slices;i++) { // loop over time bins
3768  for(int j=1;j<layers;j++) { // loop over frequency bins
3769  double a00 = W.getSample(i,j+0.01); // read a00 pixel amplitude
3770  double a90 = W.getSample(i,-(j+0.01)); // read a90 pixel amplitude
3771  Et+=(a00*a00+a90*a90)/2;
3772  }
3773  }
3774 
3775  return Et;
3776 }
3777 
3779 
3780  // initialize with the default values
3781  gOPT.ccut_wdm_fres = CCUT_WDM_FRES;
3782  gOPT.ccut_bchirp = CCUT_BCHIRP;
3783  gOPT.ccut_uchirp = CCUT_UCHIRP;
3784  gOPT.ccut_ltime = CCUT_LTIME;
3785  gOPT.ccut_rtime = CCUT_RTIME;
3786  gOPT.ccut_fmax = CCUT_FMAX;
3787 
3788  // read the user parameter ccut
3789  TObjArray* token = TString(options).Tokenize(TString(':'));
3790  if(token->GetEntries()!=5) {
3791  cout << endl;
3792  cout << "cwb_pereport - Error : ccut format - must be: wdm_fres:bchirp:uchirp:ltime:rtime" << endl;
3793  cout << " Default setup is: 16:1.35:1.65:0.5:0.0" << endl;
3794  cout << " To setup a default value use *" << endl;
3795  cout << " Example: *:1.25:1.75:*:*" << endl;
3796  cout << endl;
3797  exit(1);
3798  }
3799  for(int j=0;j<token->GetEntries();j++) {
3800  TObjString* tok = (TObjString*)token->At(j);
3801  TString stok = tok->GetString();
3802 
3803  if(stok=="*") continue;
3804 
3805  if(j==0) {
3806  TString wdm_fres=stok;
3807  if(wdm_fres.IsDigit()) gOPT.ccut_wdm_fres=wdm_fres.Atoi();
3808  else {cout<<"cwb_pereport - Error : wdm_fres is not integer"<<endl;exit(1);}
3809  }
3810  if(j==1) {
3811  TString mc_lower_factor=stok;
3812  if(mc_lower_factor.IsFloat()) gOPT.ccut_bchirp=mc_lower_factor.Atof();
3813  else {cout<<"cwb_pereport - Error : mc_lower_factor is not float"<<endl;exit(1);}
3814  }
3815  if(j==2) {
3816  TString mc_upper_factor=stok;
3817  if(mc_upper_factor.IsFloat()) gOPT.ccut_uchirp=mc_upper_factor.Atof();
3818  else {cout<<"cwb_pereport - Error : mc_upper_factor is not float"<<endl;exit(1);}
3819  }
3820  if(j==3) {
3821  TString left_time=stok;
3822  if(left_time.IsFloat()) gOPT.ccut_ltime=left_time.Atof();
3823  else {cout<<"cwb_pereport - Error : left_time is not float"<<endl;exit(1);}
3824  }
3825  if(j==4) {
3826  TString right_time=stok;
3827  if(right_time.IsFloat()) gOPT.ccut_rtime=right_time.Atof();
3828  else {cout<<"cwb_pereport - Error : right_time is not float"<<endl;exit(1);}
3829  }
3830  }
3831 
3832  int x=gOPT.ccut_wdm_fres; // must be power of 2
3833  if(!((x != 0) && ((x & (~x + 1)) == x)) || gOPT.ccut_wdm_fres<=0) {
3834  cout<<"cwb_pereport : upTDF parameter non valid : must be power of 2 : "<<gOPT.ccut_wdm_fres<<endl;
3835  exit(1);
3836  }
3837  if(gOPT.ccut_bchirp < 0) {
3838  cout<<"cwb_pereport - Error :.ccut_bchirp must be >= 0"<<endl;
3839  exit(1);
3840  }
3841  if(gOPT.ccut_bchirp > gOPT.ccut_uchirp) {
3842  cout<<"cwb_pereport - Error :.ccut_bchirp must be < ccut_uchirp"<<endl;
3843  exit(1);
3844  }
3845  if(gOPT.ccut_rtime < 0) {
3846  cout<<"cwb_pereport - Error :.ccut_rtime >=0"<<endl;
3847  exit(1);
3848  }
3849  if(gOPT.ccut_ltime < gOPT.ccut_rtime) {
3850  cout<<"cwb_pereport - Error :.ccut_ltime must be >.ccut_rtime"<<endl;
3851  exit(1);
3852  }
3853 }
3854 
3856 // apply residual cut
3857 
3858  // produce the TF aux map:
3859  WSeries<double> WAUX; // TF map container
3860  WAUX.Forward(*aux, *gWDM); // apply the WDM to the auxiliary time series
3861 
3862  int layers = WAUX.maxLayer()+1; // numbers of frequency bins (first & last bins have df/2)
3863  int slices = WAUX.sizeZero(); // number of time bins
3864 
3865  int esize = slices*layers;
3866  float* energy = new float[esize];
3867 
3868  // set to 0 the phase 00/90 amplitudes outside the chirp band
3869  float etot=0;
3870  for(int i=0;i<slices;i++) { // loop over time bins
3871  for(int j=0;j<layers;j++) { // loop over frequency bins
3872  float A00 = WAUX.getSample(i,j+0.01); // get phase 00 amplitude
3873  float A90 = WAUX.getSample(i,-(j+0.01)); // get phase 90 amplitude
3874  energy[j+i*layers] = A00*A00+A90*A90;
3875  etot+=energy[j+i*layers];
3876  }
3877  }
3878 
3879  // produce the TF ts map:
3880  WSeries<double> WTS; // TF map container
3881  WTS.Forward(*ts, *gWDM); // apply the WDM to the time series
3882 
3883  int *index = new int[esize];
3884  TMath::Sort(esize,energy,index,true);
3885  float ecum=0;
3886  for(int k=0;k<esize;k++) {
3887  int m = index[k];
3888  ecum+=energy[m];
3889  if(ecum <= etot*gOPT.rcut_thr) {
3890  //cout << k << "/" << esize << " " << energy[m] << endl;
3891  } else {
3892  int j = m%layers;
3893  int i = (m-j)/layers;
3894  WTS.putSample(0,i,j+0.01);
3895  WTS.putSample(0,i,-(j+0.01));
3896  }
3897  }
3898 
3899  // return to time domain
3900  WSeries<double> xWTS = WTS;
3901  WTS.Inverse();
3902  xWTS.Inverse(-2);
3903  WTS += xWTS;
3904  WTS *= 0.5;
3905 
3906  return WTS;
3907 }
3908 
3910 
3911  // initialize with the default values
3912  gOPT.rcut_wdm_fres = RCUT_WDM_FRES;
3913  gOPT.rcut_thr = RCUT_THR;
3914 
3915  // read the user parameter rcut
3916  TObjArray* token = TString(options).Tokenize(TString(':'));
3917  if(token->GetEntries()!=2) {
3918  cout << endl;
3919  cout << "cwb_pereport - Error : rcut format - must be: wdm_fres:thr" << endl;
3920  cout << " Default setup is: 64:1.0" << endl;
3921  cout << " To setup a default value use *" << endl;
3922  cout << " Example: *:0.9" << endl;
3923  cout << endl;
3924  exit(1);
3925  }
3926  for(int j=0;j<token->GetEntries();j++) {
3927  TObjString* tok = (TObjString*)token->At(j);
3928  TString stok = tok->GetString();
3929 
3930  if(stok=="*") continue;
3931 
3932  if(j==0) {
3933  TString wdm_fres=stok;
3934  if(wdm_fres.IsDigit()) gOPT.rcut_wdm_fres=wdm_fres.Atoi();
3935  else {cout<<"cwb_pereport - Error : wdm_fres is not integer"<<endl;exit(1);}
3936  }
3937  if(j==1) {
3938  TString thr=stok;
3939  if(thr.IsFloat()) gOPT.rcut_thr=thr.Atof();
3940  else {cout<<"cwb_pereport - Error : thr is not float"<<endl;exit(1);}
3941  }
3942  }
3943 
3944  int x=gOPT.rcut_wdm_fres; // must be power of 2
3945  if(!((x != 0) && ((x & (~x + 1)) == x)) || gOPT.rcut_wdm_fres<=0) {
3946  cout<<"cwb_pereport : upTDF parameter non valid : must be power of 2 : "<<gOPT.rcut_wdm_fres<<endl;
3947  exit(1);
3948  }
3949  if(gOPT.rcut_thr < 0 || gOPT.rcut_thr > 1) {
3950  cout<<"cwb_pereport - Error :rcut_thr must be >= 0 && <=1"<<endl;
3951  exit(1);
3952  }
3953 }
3954 
3956 
3957  // initialize with the default values
3958  gOPT.logl_enabled = LOGL_ENABLED;
3959  gOPT.logl_flow = LOGL_FLOW;
3960  gOPT.logl_fhigh = LOGL_FHIGH;
3961  gOPT.logl_arthr = LOGL_ARTHR;
3962  gOPT.logl_ifo_mask = LOGL_IFO_MASK;
3963  gOPT.logl_resample = LOGL_RESAMPLE;
3964 
3965  // read the user parameter logl
3966  TObjArray* token = TString(options).Tokenize(TString(':'));
3967  if(token->GetEntries()!=6) {
3968  cout << endl;
3969  cout << "cwb_pereport - Error : logl format - must be: enabled:flow:fhigh:arthr:ifo_mask:resample" << endl;
3970  cout << " Default setup is: false:0:8192:0.001:0x11111111:1" << endl;
3971  cout << " Example: true:20:100:*:0x100:* (select only the third ifo)" << endl;
3972  cout << endl;
3973  exit(1);
3974  }
3975  for(int j=0;j<token->GetEntries();j++) {
3976  TObjString* tok = (TObjString*)token->At(j);
3977  TString stok = tok->GetString();
3978 
3979  if(stok=="*") continue;
3980 
3981  if(j==0) {
3982  TString enabled=stok;
3983  enabled.Remove(0,enabled.Last('=')+1);
3984  if(enabled=="true") gOPT.logl_enabled=true;
3985  if(enabled=="false") gOPT.logl_enabled=false;
3986  }
3987  if(j==1) {
3988  TString flow=stok;
3989  if(flow.IsFloat()) gOPT.logl_flow=flow.Atof();
3990  else {cout<<"cwb_pereport - Error : logl flow is not float"<<endl;exit(1);}
3991  }
3992  if(j==2) {
3993  TString fhigh=stok;
3994  if(fhigh.IsFloat()) gOPT.logl_fhigh=fhigh.Atof();
3995  else {cout<<"cwb_pereport - Error : logl fhigh is not float"<<endl;exit(1);}
3996  }
3997  if(j==3) {
3998  TString arthr=stok;
3999  if(arthr.IsFloat()) gOPT.logl_arthr=arthr.Atof();
4000  else {cout<<"cwb_pereport - Error : logl arthr is not float"<<endl;exit(1);}
4001  }
4002  if(j==4) {
4003  TString ifo_mask=stok;
4004  if(ifo_mask.IsHex()) {
4005  std::string sifo_mask = ifo_mask.Data();
4006  gOPT.logl_ifo_mask=std::stoi(sifo_mask, 0, 16);
4007  } else {cout<<"cwb_pereport - Error : logl ifo_mask is not hex"<<endl;exit(1);}
4008  }
4009  if(j==5) {
4010  TString resample=stok;
4011  if(resample.IsDigit()) gOPT.logl_resample=resample.Atoi();
4012  else {cout<<"cwb_pereport - Error : logl resample is not integer"<<endl;exit(1);}
4013  }
4014  }
4015 
4016  if(gOPT.logl_flow > gOPT.logl_fhigh) {
4017  cout<<"cwb_pereport - Error : logl_flow must be < logl_fhigh "<<endl;
4018  exit(1);
4019  }
4020  if(gOPT.logl_arthr>=1) {
4021  cout<<"cwb_pereport - Error : logl_arthr must be < 1"<<endl;
4022  exit(1);
4023  }
4024 }
4025 
4027 
4028  // initialize with the default values
4029  gOPT.rstat_enabled = RSTAT_ENABLED;
4030  gOPT.rstat_type = RSTAT_TYPE;
4031  gOPT.rstat_rtrials = RSTAT_RTRIALS;
4032  gOPT.rstat_jtrials = RSTAT_JTRIALS;
4033 
4034  // read the user parameter rstat
4035  TObjArray* token = TString(options).Tokenize(TString(':'));
4036  if(token->GetEntries()!=4) {
4037  cout << endl;
4038  cout << "cwb_pereport - Error : rstat format - must be: true:median:rtrials:jtrials" << endl;
4039  cout << " Default setup is: false:median:0:0" << endl;
4040  cout << " Example: true:median:1000:100 " << endl;
4041  cout << endl;
4042  exit(1);
4043  }
4044  for(int j=0;j<token->GetEntries();j++) {
4045  TObjString* tok = (TObjString*)token->At(j);
4046  TString stok = tok->GetString();
4047 
4048  if(stok=="*") continue;
4049 
4050  if(j==0) {
4051  TString enabled=stok;
4052  enabled.Remove(0,enabled.Last('=')+1);
4053  if(enabled=="true") gOPT.rstat_enabled=true;
4054  if(enabled=="false") gOPT.rstat_enabled=false;
4055  }
4056  if(j==1) {
4057  TString type=stok;
4058  type.Remove(0,type.Last('=')+1);
4059  if((type!="rstat1")&&(type!="median")) {
4060  cout<<"cwb_pereport - Error : available options for rstat_type are: rstat1/median "<<endl;
4061  exit(1);
4062  } else gOPT.rstat_type=type;
4063  }
4064  if(j==2) {
4065  TString rtrials=stok;
4066  if(rtrials.IsDigit()) gOPT.rstat_rtrials=rtrials.Atoi();
4067  else {cout<<"cwb_pereport - Error : rstat rtrials is not integer"<<endl;exit(1);}
4068  }
4069  if(j==3) {
4070  TString jtrials=stok;
4071  if(jtrials.IsDigit()) gOPT.rstat_jtrials=jtrials.Atoi();
4072  else {cout<<"cwb_pereport - Error : rstat jtrials is not integer"<<endl;exit(1);}
4073  }
4074  }
4075 
4076  if(gOPT.rstat_enabled==false) { // when rstat is disabled set default
4077  gOPT.rstat_rtrials=RSTAT_RTRIALS;
4078  gOPT.rstat_jtrials=RSTAT_JTRIALS;
4079  } else {
4080  if(gOPT.rstat_rtrials < 0) {
4081  cout<<"cwb_pereport - Error : rstat_rtrials must be >=0 "<<endl;
4082  exit(1);
4083  }
4084  if(gOPT.rstat_jtrials < 0) {
4085  cout<<"cwb_pereport - Error : rstat_jtrials must be >=0 "<<endl;
4086  exit(1);
4087  }
4088  }
4089 }
4090 
4092 
4093 #define MAX_TRIALS 30
4094 #define MAX_ECOV 1.0
4095 
4096  // The waveforms are aligned and, if requested, sync in phase and time
4097  // the reference waveform is REC, this choice is necessary to fix the original onsource waveform
4098  int selected=SyncWaveforms(nIFO, "waveform");
4099  cout << endl << "ComputeWaveformFCR - selected events : " << selected << endl << endl;
4100  if(selected==0) return 0;
4101 
4102  double cov50[NIFO_MAX],cov90[NIFO_MAX],cov99[NIFO_MAX]; // local coverage
4103 
4104  double fcov50[NIFO_MAX],fcov90[NIFO_MAX],fcov99[NIFO_MAX]; // full coverage
4105  double bcov50[NIFO_MAX],bcov90[NIFO_MAX],bcov99[NIFO_MAX]; // bottom coverage
4106  double ucov50[NIFO_MAX],ucov90[NIFO_MAX],ucov99[NIFO_MAX]; // up coverage
4107 
4108  for(int n=0;n<nIFO;n++) {bcov50[n]=0.; bcov90[n]=0.; bcov99[n]=0.; }
4109  for(int n=0;n<nIFO;n++) { cov50[n]=50.; cov90[n]=90.; cov99[n]=99.; }
4110  for(int n=0;n<nIFO;n++) {ucov50[n]=100.; ucov90[n]=100.; ucov99[n]=100.;}
4111 
4112  int trials=0;
4113  bool done=false;
4114  while(!done && trials<MAX_TRIALS) { // dichotomic search
4115 
4116  trials++;
4117 
4118  ComputeWaveformCR(nIFO, selected, cov50, cov90, cov99);
4119 
4120  GetFullCoverage(nIFO, selected, fcov50, fcov90, fcov99);
4121  for(int n=0;n<nIFO;n++) {
4122  cout.precision(6);
4123  cout << endl;
4124  cout << "Trials = " << trials << "\tIFO " << gIFO[n] << "\tFull/Local Coverage at 50% = " << (int)fcov50[n] << " / " << cov50[n] << endl;
4125  cout << "Trials = " << trials << "\tIFO " << gIFO[n] << "\tFull/Local Coverage at 90% = " << (int)fcov90[n] << " / " << cov90[n] << endl;
4126  cout << "Trials = " << trials << "\tIFO " << gIFO[n] << "\tFull/Local Coverage at 99% = " << (int)fcov99[n] << " / " << cov99[n] << endl;
4127  cout << endl;
4128  }
4129 
4130  done=true;
4131  for(int n=0;n<nIFO;n++) {
4132  if(fabs(fcov50[n]-50.)>MAX_ECOV) {
4133  if(fcov50[n]<50.) {bcov50[n]=cov50[n]; cov50[n] += (ucov50[n]- cov50[n])/2.;}
4134  else {ucov50[n]=cov50[n]; cov50[n] -= ( cov50[n]-bcov50[n])/2.;}
4135  done=false;
4136  }
4137  if(fabs(fcov90[n]-90.)>MAX_ECOV) {
4138  if(fcov90[n]<90.) {bcov90[n]=cov90[n]; cov90[n] += (ucov90[n]- cov90[n])/2.;}
4139  else {ucov90[n]=cov90[n]; cov90[n] -= ( cov90[n]-bcov90[n])/2.;}
4140  done=false;
4141  }
4142  if(fabs(fcov99[n]-99.)>MAX_ECOV) {
4143  if(fcov99[n]<99.) {bcov99[n]=cov99[n]; cov99[n] += (ucov99[n]- cov99[n])/2.;}
4144  else {ucov99[n]=cov99[n]; cov99[n] -= ( cov99[n]-bcov99[n])/2.;}
4145  done=false;
4146  }
4147  }
4148  }
4149 
4150  // dump coverage
4151  TString parm="";
4152  DumpStatistics("full_coverage.txt", "", false);
4153  for(int n=0;n<nIFO;n++) {
4154  parm = TString::Format("%s : Trials = %d/%d \tIFO %s \tFull/Local Coverage at 50% = %.4f / %.4f",
4155  gOPT.gw_name.Data(), trials, MAX_TRIALS, gIFO[n].Data(), fcov50[n], cov50[n]);
4156  DumpStatistics("full_coverage.txt", parm, true);
4157  parm = TString::Format("%s : Trials = %d/%d \tIFO %s \tFull/Local Coverage at 90% = %.4f / %.4f",
4158  gOPT.gw_name.Data(), trials, MAX_TRIALS, gIFO[n].Data(), fcov90[n], cov90[n]);
4159  DumpStatistics("full_coverage.txt", parm, true);
4160  parm = TString::Format("%s : Trials = %d/%d \tIFO %s \tFull/Local Coverage at 99% = %.4f / %.4f",
4161  gOPT.gw_name.Data(), trials, MAX_TRIALS, gIFO[n].Data(), fcov99[n], cov99[n]);
4162  DumpStatistics("full_coverage.txt", parm, true);
4163  DumpStatistics("full_coverage.txt", "", true);
4164  }
4165 
4166  return selected;
4167 }
4168 
4169 void ComputeWaveformCR(int nIFO, int selected, double* cov50, double* cov90, double* cov99) {
4170 
4171  // clean vectors
4172  while(!vMED.empty()) vMED.pop_back();
4173  vMED.clear(); std::vector<wavearray<double> >().swap(vMED);
4174  while(!vL50.empty()) vL50.pop_back();
4175  vL50.clear(); std::vector<wavearray<double> >().swap(vL50);
4176  while(!vU50.empty()) vU50.pop_back();
4177  vU50.clear(); std::vector<wavearray<double> >().swap(vU50);
4178  while(!vL90.empty()) vL90.pop_back();
4179  vL90.clear(); std::vector<wavearray<double> >().swap(vL90);
4180  while(!vU90.empty()) vU90.pop_back();
4181  vU90.clear(); std::vector<wavearray<double> >().swap(vU90);
4182  while(!vL99.empty()) vL99.pop_back();
4183  vL99.clear(); std::vector<wavearray<double> >().swap(vL99);
4184  while(!vU99.empty()) vU99.pop_back();
4185  vU99.clear(); std::vector<wavearray<double> >().swap(vU99);
4186 
4187  // compute vMED, vL50, vU50, vL90, vU90, vL99, vU99
4188  wavearray<double> wmed[NIFO_MAX];
4189  wavearray<double> wl50[NIFO_MAX];
4190  wavearray<double> wu50[NIFO_MAX];
4191  wavearray<double> wl90[NIFO_MAX];
4192  wavearray<double> wu90[NIFO_MAX];
4193  wavearray<double> wl99[NIFO_MAX];
4194  wavearray<double> wu99[NIFO_MAX];
4195  for(int n=0;n<nIFO;n++) {
4196  wmed[n] = wREC[0][n]; wmed[n] = 0;
4197  wl50[n] = wREC[0][n]; wl50[n] = 0;
4198  wu50[n] = wREC[0][n]; wu50[n] = 0;
4199  wl90[n] = wREC[0][n]; wl90[n] = 0;
4200  wu90[n] = wREC[0][n]; wu90[n] = 0;
4201  wl99[n] = wREC[0][n]; wl99[n] = 0;
4202  wu99[n] = wREC[0][n]; wu99[n] = 0;
4203 
4204  int nentries = selected; // number of detected events in the offsource
4205  int *index = new int[nentries];
4206  double *value = new double[nentries];
4207  for(int j=0;j<wREC[0][n].size();j++) {
4208  if(gOPT.residuals) {
4209  int k=0; for(int i=0;i<gEVENTS;i++) if(wNUL[i][n].size()) value[k++] = wNUL[i][n][j]; // select detected events
4210  } else {
4211  int k=0; for(int i=0;i<gEVENTS;i++) if(wREC[i][n].size()) value[k++] = wREC[i][n][j]; // select detected events
4212  }
4213  TMath::Sort(nentries,value,index,false);
4214 
4215  int imed = (nentries*50.)/100.; if(imed>=nentries) imed=nentries-1;
4216  wmed[n][j] = value[index[imed]];
4217 
4218  int il50 = (nentries*(50.-cov50[n]/2.))/100.; if(il50>=nentries) il50=nentries-1;
4219  int iu50 = (nentries*(50.+cov50[n]/2.))/100.; if(iu50>=nentries) iu50=nentries-1;
4220  int il90 = (nentries*(50.-cov90[n]/2.))/100.; if(il90>=nentries) il90=nentries-1;
4221  int iu90 = (nentries*(50.+cov90[n]/2.))/100.; if(iu90>=nentries) iu90=nentries-1;
4222  int il99 = (nentries*(50.-cov99[n]/2.))/100.; if(il99>=nentries) il99=nentries-1;
4223  int iu99 = (nentries*(50.+cov99[n]/2.))/100.; if(iu99>=nentries) iu99=nentries-1;
4224 
4225  double med = wmed[n][j];
4226  double l50 = value[index[il50]];
4227  double u50 = value[index[iu50]];
4228  double l90 = value[index[il90]];
4229  double u90 = value[index[iu90]];
4230  double l99 = value[index[il99]];
4231  double u99 = value[index[iu99]];
4232 
4233  bool check=true;
4234  if(!(l50<=u50)) check=false;
4235  if(!(l90<=u90)) check=false;
4236  if(!(l99<=u99)) check=false;
4237  if(!(med>=l50 && med<=u50)) check=false;
4238  if(!(med>=l90 && med<=u90)) check=false;
4239  if(!(med>=l99 && med<=u99)) check=false;
4240  if(!check) {cout << "ComputeWaveformFCR : standard wrong median, lower, upper bound !!! " << l50 << " " << med << " " << u50 << endl;}
4241  if(!(med>=l50 && med<=u50)) med=l50;
4242  wmed[n][j]=med;
4243 
4244  wl50[n][j] = fabs(med-l50);
4245  wu50[n][j] = fabs(u50-med);
4246  wl90[n][j] = fabs(med-l90);
4247  wu90[n][j] = fabs(u90-med);
4248  wl99[n][j] = fabs(med-l99);
4249  wu99[n][j] = fabs(u99-med);
4250  }
4251  delete [] index;
4252  delete [] value;
4253 
4254  vMED.push_back(wmed[n]);
4255  vL50.push_back(wl50[n]);
4256  vU50.push_back(wu50[n]);
4257  vL90.push_back(wl90[n]);
4258  vU90.push_back(wu90[n]);
4259  vL99.push_back(wl99[n]);
4260  vU99.push_back(wu99[n]);
4261  }
4262 }
4263 
4264 void GetFullCoverage(int nIFO, int selected, double* fcov50, double* fcov90, double* fcov99) {
4265 
4266  // Compute time boundaries which contain the P energy fraction of median
4267 
4268  double P = gOPT.plot_efraction;
4269  double estart, estop;
4270  for(int n=0;n<nIFO;n++) {
4271  double bT, eT;
4272  CWB::mdc::GetTimeBoundaries(vMED[n], P, bT, eT);
4273  if(n==0) {
4274  estart=bT;estop=eT;
4275  } else {
4276  if(bT<estart) estart=bT;
4277  if(eT>estop) estop=eT;
4278  }
4279  }
4280  cout << endl;
4281  cout << "estart=" << estart << "\testop=" << estop << endl;
4282  cout << endl;
4283 
4284  int nstart = (estart-vREC[0].start())*vREC[0].rate();
4285  int nstop = (estop -vREC[0].start())*vREC[0].rate();
4286 
4287  // Compute the full coverages
4288 
4289  for(int n=0;n<nIFO;n++) {
4290  int n50=0;
4291  int n90=0;
4292  int n99=0;
4293  for(int i=0;i<gEVENTS;i++) {
4294  if(!wREC[i][n].size()) continue; // select detected events
4295  bool b50=false;
4296  bool b90=false;
4297  bool b99=false;
4298  for(int j=nstart;j<nstop;j++) {
4299  double vl50 = vMED[n][j]-fabs(vL50[n][j]);
4300  double vu50 = vMED[n][j]+fabs(vU50[n][j]);
4301  double vl90 = vMED[n][j]-fabs(vL90[n][j]);
4302  double vu90 = vMED[n][j]+fabs(vU90[n][j]);
4303  double vl99 = vMED[n][j]-fabs(vL99[n][j]);
4304  double vu99 = vMED[n][j]+fabs(vU99[n][j]);
4305 
4306  double value = wREC[i][n][j];
4307  if(value<vl50 || value>vu50) b50=true;
4308  if(value<vl90 || value>vu90) b90=true;
4309  if(value<vl99 || value>vu99) b99=true;
4310  }
4311  if(b50) n50++;
4312  if(b90) n90++;
4313  if(b99) n99++;
4314  }
4315  fcov50[n] = (100.-100.*n50/(double)selected);
4316  fcov90[n] = (100.-100.*n90/(double)selected);
4317  fcov99[n] = (100.-100.*n99/(double)selected);
4318  }
4319 }
4320 
wavearray< double > t(hp.size())
TF1 * fuchirp
Definition: DrawCCutxPE.C:83
float wS1[PE_MAX_EVENTS]
Definition: cwb_pereport.C:333
double vTSYNC[NIFO_MAX]
Definition: cwb_pereport.C:319
std::vector< wavearray< double > > pSNR
Definition: cwb_pereport.C:302
double pc
Definition: DrawEBHH.C:15
double rho
detectorParams getDetectorParams()
Definition: detector.cc:218
std::vector< wavearray< double > > vU50
Definition: cwb_pereport.C:296
double vFACTOR
Definition: cwb_pereport.C:309
double aux
Definition: testWDM_5.C:14
std::vector< double > xOF
Definition: cwb_pereport.C:342
void GetRstatParms(TString options)
#define PE_MAKE_ONSRC
Definition: cwb_pereport.C:136
float vM1
Definition: cwb_pereport.C:312
void gtitle(TString title="", TString xtitle="", TString ytitle="")
Definition: watplot.cc:1256
void ComputeTimeSensitivity(TString match, double lower, double upper, double &dmatch, double &dtime)
char xtitle[1024]
int slices
static vector< TString > getFileListFromDir(TString dir_name, TString endString="", TString beginString="", TString containString="", bool fast=false)
Definition: Toolbox.cc:5108
TString GetDateString()
Definition: time.cc:461
TH1 * t1
double M
Definition: DrawEBHH.C:13
#define PE_SENSITIVITY
Definition: cwb_pereport.C:116
void DumpWaveformCR(int nIFO)
par [0] value
void GetOffSourceStatistic(int nIFO, int recId, vector< int > injId, vector< double > &oFF, vector< double > &oOF, vector< double > &oRE)
void MakeDistributions(TString type="FF")
float wS2[PE_MAX_EVENTS]
Definition: cwb_pereport.C:334
std::vector< wavearray< double > > wNUL[PE_MAX_EVENTS]
Definition: cwb_pereport.C:323
double min(double x, double y)
Definition: eBBH.cc:31
virtual void rate(double r)
Definition: wavearray.hh:141
#define PE_PLOT_ODIR
Definition: cwb_pereport.C:127
#define MAX_TRIALS
#define PE_EFRACTION
Definition: cwb_pereport.C:119
float factor
float vS2
Definition: cwb_pereport.C:315
char name[32]
Definition: detector.hh:50
#define CCUT_UCHIRP
Definition: cwb_pereport.C:259
double m1
Int_t nentries
Definition: TimeSortTree.C:24
#define RSTAT_JTRIALS
Definition: cwb_pereport.C:284
#define LOGL_RESAMPLE
Definition: cwb_pereport.C:274
wavearray< double > a(hp.size())
std::vector< double > vTREC
Definition: cwb_pereport.C:306
#define PE_CCUT
Definition: cwb_pereport.C:101
std::vector< wavearray< double > > vDAT
#define PE_IFAR_THR
Definition: cwb_pereport.C:93
#define LOGL_IFO_MASK
Definition: cwb_pereport.C:273
int n
Definition: cwb_net.C:28
#define PE_GPS_ERROR
Definition: cwb_pereport.C:96
uoptions gOPT
Definition: cwb_pereport.C:250
#define PE_PLOT_99PERC
Definition: cwb_pereport.C:130
TString("c")
std::vector< double > vRE
Definition: cwb_pereport.C:338
#define PE_MAKE_OF
Definition: cwb_pereport.C:133
int ComputeStatistics(int nIFO)
Definition: cwb_pereport.C:496
double GetSyncTcoa(wavearray< double > wf, double sync_time, double sync_phase, double tcoa)
#define CCUT_FMAX
Definition: cwb_pereport.C:262
std::vector< wavearray< double > > vU99
Definition: cwb_pereport.C:300
#define PE_RESIDUALS
Definition: cwb_pereport.C:117
void putSample(DataType_t a, int n, double m)
Definition: wseries.hh:195
ofstream out
Definition: cwb_merge.C:214
static void PhaseShift(wavearray< double > &x, double pShift=0.)
Definition: mdc.cc:2955
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
#define LOGL_FHIGH
Definition: cwb_pereport.C:271
std::vector< wavearray< double > > vAUX
Definition: cwb_pereport.C:293
float theta
double GetInjTcoa(double geocentric_tcoa, network *NET, TString ifo, double theta, double phi)
CWB::frame fr(FRLIST_NAME)
void GetRCutParms(TString options)
std::vector< TGraph * > graph
Definition: watplot.hh:194
return wmap canvas
plot gtitle(gtitle,"frequency (Hz)","strain/#sqrt{Hz}")
float wM1[PE_MAX_EVENTS]
Definition: cwb_pereport.C:331
void MakePvalueDistribution(TString type="FF")
#define PE_USE_ONSRC
Definition: cwb_pereport.C:109
float vM2
Definition: cwb_pereport.C:313
int layers
CWB::mdc * MDC
#define PE_PLOT_ZOOM
Definition: cwb_pereport.C:129
double vPSYNC[NIFO_MAX]
Definition: cwb_pereport.C:320
static wavearray< double > getHilbertIFrequency(wavearray< double > x)
Definition: Toolbox.cc:6935
waveform wf
std::vector< wavearray< double > > wINJ[PE_MAX_EVENTS]
Definition: cwb_pereport.C:324
Long_t size
int GetOnSourceStatistic(int nIFO, double &mFF, double &mOF, double &mRE)
double wFACTOR[PE_MAX_EVENTS]
Definition: cwb_pereport.C:328
int nevt
#define PE_STATISTICS
Definition: cwb_pereport.C:118
int m
Definition: cwb_net.C:28
std::vector< double > oSNR[NIFO_MAX]
std::vector< wavearray< double > > pTIM
Definition: cwb_pereport.C:304
char command[1024]
Definition: cwb_compile.C:44
virtual void start(double s)
Definition: wavearray.hh:137
int j
Definition: cwb_net.C:28
i drho i
#define PE_WAVE_DIR
Definition: cwb_pereport.C:90
#define PE_SYNC_TIME
Definition: cwb_pereport.C:114
double GetDelay(TString ifo1, TString ifo2, double phi, double theta)
Definition: mdc.cc:4523
#define N
char ifo[NIFO_MAX][8]
std::vector< double > xFF
Definition: cwb_pereport.C:342
iseg push_back(seg)
int ComputeWaveformCR(int nIFO)
Definition: cwb_pereport.C:946
float vDOF
Definition: cwb_pereport.C:316
#define PE_OFF_EVENT
Definition: cwb_pereport.C:97
#define PE_COVERAGE
Definition: cwb_pereport.C:122
#define nIFO
double tstart
virtual size_t size() const
Definition: wavearray.hh:145
char data_label[512]
Definition: test_config1.C:160
float phi
gWSeries< double > gw(w)
#define PE_RCUT
Definition: cwb_pereport.C:102
static TString gIFO[3]
Definition: cwb_pereport.C:252
#define PE_GPS_EVENT
Definition: cwb_pereport.C:94
wavearray< double > freq
Definition: Regression_H1.C:79
void GetLoglParms(TString options)
x plot
std::vector< wavearray< double > > vL99
Definition: cwb_pereport.C:299
std::vector< wavearray< double > > vINJ
Definition: cwb_pereport.C:292
std::vector< double > vOF
Definition: cwb_pereport.C:338
void GetCCutParms(TString options)
Definition: mdc.hh:248
static double GetMatchFactor(TString match, vector< wavearray< double > > &w1, vector< wavearray< double > > &w2, vector< double > tstart=DEFAULT_VECtOR_DOUBLE, vector< double > tstop=DEFAULT_VECtOR_DOUBLE)
Definition: mdc.cc:7737
TGraph * gr
#define MAX_ECOV
float wPHI[PE_MAX_EVENTS]
Definition: cwb_pereport.C:330
TF1 * f2
#define PE_MAKE_FF
Definition: cwb_pereport.C:132
static wavearray< double > GetEnvelope(wavearray< double > *x)
Definition: mdc.cc:7828
watplot * WTS
Definition: ChirpMass.C:119
double GetCCut(wavearray< double > *ts, double tcoa, double m1, double m2, double s1z, double s2z)
i() int(T_cor *100))
#define PE_TCOA_SHIFT
Definition: cwb_pereport.C:95
network NET
Definition: cwb_dump_inj.C:30
static wavearray< double > GetAligned(wavearray< double > *w1, wavearray< double > *w2)
Definition: mdc.cc:7302
TString GetParameterFromInjLog(TString log, TString param)
const int NIFO_MAX
Definition: wat.hh:22
bool log
Definition: WaveMDC.C:41
void Resample(const wavearray< DataType_t > &, double, int=6)
Definition: wavearray.cc:640
double fhigh
#define PE_PLOT_EFRACTION
Definition: cwb_pereport.C:128
#define CCUT_BCHIRP
Definition: cwb_pereport.C:258
printf("total live time: non-zero lags = %10.1f \, liveTot)
#define PE_GW_NAME
Definition: cwb_pereport.C:88
std::vector< wavearray< double > > vL50
Definition: cwb_pereport.C:295
#define CCUT_LTIME
Definition: cwb_pereport.C:260
std::vector< double > iSNR[NIFO_MAX]
#define PE_PLOT_CR
Definition: cwb_pereport.C:124
int k
double tstop
#define CCUT_WDM_FRES
Definition: cwb_pereport.C:257
std::vector< wavearray< double > > wREC[PE_MAX_EVENTS]
Definition: cwb_pereport.C:322
static double A
Definition: geodesics.cc:26
TObjArray * token
#define RSTAT_RTRIALS
Definition: cwb_pereport.C:283
x *double Et
Definition: ComputeSNR.C:40
#define LOGL_ENABLED
Definition: cwb_pereport.C:269
double F
#define PE_MAKE_RE
Definition: cwb_pereport.C:134
#define PE_DATA_LABEL
Definition: cwb_pereport.C:89
void DumpStatistics(TString ofname, TString params, bool app)
void PrintUserOptions(TString ofname="")
std::vector< wavearray< double > > vMED
Definition: cwb_pereport.C:294
void cwb_pereport(TString options)
Definition: cwb_pereport.C:402
double e
#define nPx
void ComputeAmpSensitivity(TString match, double lower, double upper, double &dmatch, double &damp)
std::vector< wavearray< double > > vREC
Definition: cwb_pereport.C:291
float wDOF[PE_MAX_EVENTS]
Definition: cwb_pereport.C:335
#define PE_LOGL
Definition: cwb_pereport.C:104
void PlotWaveformAsymmErrors(TString ofname, TString title, wavearray< double > wrec, wavearray< double > wmed, wavearray< double > wl50, wavearray< double > wu50, wavearray< double > wl90, wavearray< double > wu90, wavearray< double > wl99, wavearray< double > wu99, wavearray< double > wref, TString pdir, double P, double Q, double tref, double tcoa, int ifoid)
static double TimeSync(wavearray< double > &w1, wavearray< double > &w2, double &sync_time)
Definition: mdc.cc:7562
static double GetTimeBoundaries(wavearray< double > x, double P, double &bT, double &eT, double T=-1., double Q=-1.)
Definition: mdc.cc:7419
TFile * froot
int nevents
std::vector< wavearray< double > > wAUX[PE_MAX_EVENTS]
Definition: cwb_pereport.C:325
#define LOGL_ARTHR
Definition: cwb_pereport.C:272
#define PE_INJ_TIME_STEP
Definition: cwb_pereport.C:98
double dt
double vTCOA
Definition: cwb_pereport.C:308
void LoadOutputRootFiles(int nIFO, TString data_label, TString output_dir, int max_events=PE_MAX_EVENTS, double ifar_thr=0)
static void TimeShift(wavearray< double > &x, double tShift=0.)
Definition: mdc.cc:2903
s s
Definition: cwb_net.C:155
double flow
char options[256]
#define PE_MAX_EVENTS
Definition: cwb_pereport.C:86
std::vector< double > xRE
Definition: cwb_pereport.C:342
int nifo
#define RCUT_THR
Definition: cwb_pereport.C:265
void PlotWaveformsCR(int nIFO)
char title[256]
Definition: SSeriesExample.C:1
std::vector< wavearray< double > > vL90
Definition: cwb_pereport.C:297
int SyncWaveforms(int nIFO, TString type)
double T
Definition: testWDM_4.C:11
float TestStatistic(int nIFO, int id, float ref)
static wavearray< double > GetDiff(wavearray< double > *w1, wavearray< double > *w2)
Definition: mdc.cc:7374
#define PE_INJ_ONSRC
Definition: cwb_pereport.C:99
#define PE_PLOT_TYPE
Definition: cwb_pereport.C:125
wavearray< double > ts(N)
cout<< "Starting reading output directory ..."<< endl;vector< TString > fileList
static double PhaseSync(wavearray< double > &w1, wavearray< double > &w2, double &sync_phase)
Definition: mdc.cc:7507
wavearray< int > index
int ComputeCCutStatistics(int nIFO)
Definition: cwb_pereport.C:786
static int Align(wavearray< double > &w1, wavearray< double > &w2)
Definition: mdc.cc:7679
#define PE_MAKE_NE
Definition: cwb_pereport.C:135
double fabs(const Complex &x)
Definition: numpy.cc:55
#define PE_SIDE
Definition: cwb_pereport.C:121
TF1 * fchirp
Definition: ChirpMass.C:122
double resolution(int=0)
Definition: wseries.hh:155
double m2
TBranch * branch
int gps_event
Definition: cwb_inet.C:188
double Q
#define CCUT_RTIME
Definition: cwb_pereport.C:261
#define RCUT_WDM_FRES
Definition: cwb_pereport.C:264
#define PE_NCYCLES
Definition: cwb_pereport.C:92
void Forward(int n=-1)
param: wavelet - n is number of steps (-1 means full decomposition)
Definition: wseries.cc:246
#define PE_RSTAT
Definition: cwb_pereport.C:106
void ResetUserOptions()
double df
#define PE_NIFO
Definition: cwb_pereport.C:91
sprintf(tfres,"(1/%g)x(%g) (sec)x(Hz)", 2 *df, df)
std::vector< wavearray< double > > vU90
Definition: cwb_pereport.C:298
TTree * itree
TString gfile
std::vector< wavearray< double > > vNUL
Definition: cwb_pereport.C:290
double wTCOA[PE_MAX_EVENTS]
Definition: cwb_pereport.C:327
watplot * GetWATPLOT()
Definition: gwavearray.hh:88
DataType_t * data
Definition: wavearray.hh:319
std::vector< wavearray< double > > pFRQ
Definition: cwb_pereport.C:303
#define RSTAT_TYPE
Definition: cwb_pereport.C:282
static double TimePhaseSync(wavearray< double > &w1, wavearray< double > &w2, double &sync_time, double &sync_phase)
Definition: mdc.cc:7610
Long_t id
#define PE_DUMP_CR
Definition: cwb_pereport.C:108
float vPHI
Definition: cwb_pereport.C:311
DataType_t getSample(int n, double m)
Definition: wseries.hh:185
void ComputePhaseSensitivity(TString match, double lower, double upper, double &dmatch, double &dphase)
static wavearray< double > getHilbertEnvelope(wavearray< double > x)
Definition: Toolbox.cc:6915
double GetDelay(network *NET, TString ifo, double theta, double phi)
float wTHETA[PE_MAX_EVENTS]
Definition: cwb_pereport.C:329
void PlotWaveforms(int nIFO, int id, bool residual=false)
Definition: cwb_pereport.C:834
TF1 * fbchirp
Definition: DrawCCutxPE.C:82
double ctime
char line[1024]
static wavearray< double > GetPhase(wavearray< double > hi, wavearray< double > hr, wavearray< double > &fi, wavearray< double > &fr, wavearray< double > &s, wavearray< double > &tt)
Definition: Toolbox.cc:7162
#define RSTAT_ENABLED
Definition: cwb_pereport.C:281
float vTHETA
Definition: cwb_pereport.C:310
std::vector< double > vFF
Definition: cwb_pereport.C:338
WDM< double > * gWDM
Definition: cwb_pereport.C:253
void ReadUserOptions(TString options)
float wM2[PE_MAX_EVENTS]
Definition: cwb_pereport.C:332
int gEVENTS
Definition: cwb_pereport.C:251
char fName[256]
void GetFullCoverage(int nIFO, int selected, double *fcov50, double *fcov90, double *fcov99)
int check
char output_dir[512]
Definition: test_config1.C:146
void Inverse(int n=-1)
param: n - number of steps (-1 means full reconstruction)
Definition: wseries.cc:291
size_t sizeZero()
Definition: wseries.hh:144
wavearray< double > GetRCut(wavearray< double > *ts, wavearray< double > *aux)
std::vector< double > vNE
Definition: cwb_pereport.C:338
#define LOGL_FLOW
Definition: cwb_pereport.C:270
int maxLayer()
Definition: wseries.hh:139
float wSNR[PE_MAX_EVENTS][NIFO_MAX]
Definition: cwb_pereport.C:336
void Draw(GWAT_DRAW type=GWAT_TIME, TString options="ALP", Color_t color=kBlack)
Definition: gwavearray.cc:89
#define PE_PLOT_FNAME
Definition: cwb_pereport.C:126
static wavearray< double > GetSpectrum(wavearray< double > *x, bool oneside=false)
Definition: mdc.cc:7855
int ComputeWaveformFCR(int nIFO)
#define PE_SYNC_PHASE
Definition: cwb_pereport.C:113
exit(0)
float vS1
Definition: cwb_pereport.C:314
std::vector< double > xNE
Definition: cwb_pereport.C:342
float vSNR[NIFO_MAX]
Definition: cwb_pereport.C:317