00001 #include "ChannelData.hh"
00002 #include "Message.hh"
00003 #include "TGraph.h"
00004 #include "TMultiGraph.h"
00005 #include "TAxis.h"
00006 #include "TLine.h"
00007 #include "TBox.h"
00008 #include "TPad.h"
00009 #include "TList.h"
00010 #include "TGaxis.h"
00011 #include "TMarker.h"
00012 #include <algorithm>
00013 #include <cmath>
00014
00015 #include "intarray.hh"
00016 #include "EvalTGraphPoint.C"
00017
00018 class Scale{
00019 double _offset;
00020 double _stretch;
00021 public:
00022 Scale(double offset, double stretch) : _offset(offset), _stretch(stretch) {}
00023 double operator()(double x){ return _stretch*x + _offset; }
00024 };
00025
00026 TGraph* ChannelData::GetTGraph(bool baseline_subtracted, int downsample) const
00027 {
00028 if( nsamps < 2 || waveform.empty())
00029 return 0;
00030 if( baseline_subtracted && subtracted_waveform.empty())
00031 return 0;
00032 if(downsample < 1) downsample = 1;
00033 std::vector<double> x(nsamps/downsample);
00034 std::vector<double> ycpy( downsample>1 ? nsamps/downsample : 0);
00035
00036 const double* y = (baseline_subtracted ? GetBaselineSubtractedWaveform() :
00037 GetWaveform() );
00038 for(int i=0; i<nsamps/downsample; i++){
00039 x[i] = (i*downsample - trigger_index) / sample_rate;
00040 if(downsample > 1)
00041 ycpy[i] = y[i*downsample];
00042 }
00043 TGraph* graph = new TGraph(nsamps/downsample,&x[0],
00044 (downsample > 1 ? &(ycpy[0]) : y) );
00045 char name[30];
00046 if(label != "")
00047 sprintf(name,"%i-%s",channel_id, label.c_str());
00048 else
00049 sprintf(name,"%i",channel_id);
00050 graph->SetName(name);
00051 graph->SetTitle(name);
00052 graph->SetEditable(false);
00053
00054
00055 return graph;
00056 }
00057
00058 void ChannelData::Draw(bool baseline_subtracted, int downsample,
00059 bool autoscalex, bool autoscaley,
00060 double xmin, double xmax, double ymin, double ymax)
00061 {
00062 if(downsample < 1) downsample = 1;
00063 TGraph* chgraph = GetTGraph(baseline_subtracted,downsample);
00064 if(!chgraph)
00065 return;
00066 int ns = chgraph->GetN();
00067 TMultiGraph* graphs = new TMultiGraph;
00068 graphs->SetBit(TObject::kCanDelete, true);
00069 Double_t* x = chgraph->GetX();
00070 graphs->Add(chgraph);
00071 graphs->SetName(chgraph->GetName());
00072 graphs->SetTitle(chgraph->GetTitle());
00073
00074
00075 if((int)derivative.size() == nsamps){
00076 std::vector<double> scaled_derivative(ns);
00077 for(int i=0; i<ns; i++){
00078 scaled_derivative[i] = derivative[i*downsample]*3;
00079 }
00080
00081 TGraph* dergraph = new TGraph(ns, x, &scaled_derivative[0]);
00082
00083
00084 dergraph->SetLineColor(kRed);
00085 dergraph->SetMarkerColor(kRed);
00086 graphs->Add(dergraph);
00087 }
00088
00089
00090 if((int)smoothed_data.size() == nsamps){
00091
00092 TGraph* smoothgraph = 0;
00093 if(downsample > 1 ){
00094 std::vector<double> smoothcp(ns);
00095 for(int i=0; i<ns; i++)
00096 smoothcp[i] = smoothed_data[i*downsample];
00097 smoothgraph = new TGraph(ns,x,&(smoothcp[0]));
00098 }
00099 else
00100 smoothgraph = new TGraph(ns, x, &(smoothed_data[0]));
00101 smoothgraph->SetLineColor(kTeal);
00102 smoothgraph->SetMarkerColor(kTeal);
00103 graphs->Add(smoothgraph);
00104 }
00105
00106
00107
00108 if (baseline.found_baseline &&!baseline_subtracted){
00109 std::vector<double> base(ns);
00110 for (int i=0; i<ns; i++){
00111 base[i] = waveform[i*downsample] - subtracted_waveform[i*downsample];
00112 }
00113 TGraph* basegraph = new TGraph(ns, x, &(base[0]));
00114 basegraph->SetLineColor(kRed);
00115 basegraph->SetMarkerColor(kRed);
00116 graphs->Add(basegraph);
00117 }
00118
00119
00120 graphs->Draw("alp");
00121 if( !autoscalex )
00122 graphs->GetXaxis()->SetRangeUser(xmin, xmax);
00123 if( !autoscaley )
00124 graphs->GetYaxis()->SetRangeUser(ymin, ymax);
00125 if(!autoscalex || !autoscaley)
00126 graphs->Draw("alp");
00127
00128
00129 bool draw_integral = false;
00130 int integral_color = kBlue;
00131 double integral_scale=1, integral_offset=0;
00132 TGraph* integral_graph = 0;
00133 if((int)integral.size() == nsamps){
00134
00135 draw_integral = true;
00136
00137 std::vector<double> shifted_integral(ns);
00138 double x1,x2,y1,y2;
00139 gPad->Update();
00140 gPad->GetRangeAxis(x1,y1,x2,y2);
00141 integral_offset = (baseline_subtracted ? 0 : baseline.mean);
00142 double raw_ratio = (y2 - integral_offset) / (integral_offset - y1);
00143 double integral_ratio = std::abs(integral_max) / std::abs(integral_min);
00144 if (raw_ratio < integral_ratio) {
00145 integral_scale = (y2 - integral_offset) / std::abs(integral_max) * 0.9;
00146 }else{
00147 integral_scale = (integral_offset - y1) / std::abs(integral_min) * 0.9;
00148 }
00149 for(int i=0;i<ns;i++){
00150 shifted_integral[i] = integral_scale*integral[i*downsample]+
00151 integral_offset;
00152 }
00153 integral_graph = new TGraph(ns, x, &shifted_integral[0]);
00154 integral_graph->SetLineColor(integral_color);
00155 integral_graph->SetMarkerColor(integral_color);
00156 graphs->Add(integral_graph);
00157 }
00158
00159
00160 for(size_t i=0; i<pulses.size(); i++){
00161 Pulse& pulse = pulses[i];
00162 double base = (baseline_subtracted ? 0 : baseline.mean);
00163 if(pulse.found_start){
00164 double peaky = 0;
00165 if(pulse.found_peak)
00166 peaky = base - pulse.peak_amplitude;
00167 TBox* pbox = new TBox( x[pulse.start_index], base,
00168 x[pulse.end_index], peaky);
00169 pbox->SetBit(TObject::kCanDelete,true);
00170 pbox->SetLineColor(kGreen);
00171 pbox->Draw();
00172
00173 TLine* pline = new TLine( x[pulse.peak_index], base,
00174 x[pulse.peak_index], peaky);
00175 pline->SetBit(TObject::kCanDelete,true);
00176 pline->SetLineColor(kMagenta);
00177 pline->Draw();
00178 }
00179 if(pulse.fit.fit_done){
00180 bool time_based_fit = false;
00181 if(time_based_fit){
00182 TF1* fitfunc = pulse.fit.GetTF1();
00183 if (pulse.fit.fit_result == 0)
00184 fitfunc->SetLineColor(kGreen);
00185 else
00186 fitfunc->SetLineColor(kRed);
00187 fitfunc->SetBit(TObject::kCanDelete,true);
00188 fitfunc->Draw("same");
00189 }
00190 else{
00191 TF1* fitfunc = pulse.fit.GetTF1();
00192 const int nfitpts = pulse.fit.end_index - pulse.fit.start_index;
00193 if(nfitpts > 2){
00194 double fitx[nfitpts];
00195 double fity[nfitpts];
00196 for(int j=0; j<nfitpts; j++){
00197 fitx[j] = x[pulse.fit.start_index+j];
00198 fity[j] = fitfunc->Eval(pulse.fit.start_index + j);
00199 }
00200 TGraph* fitgraph = new TGraph(nfitpts, fitx, fity);
00201 fitgraph->SetBit(TObject::kCanDelete,true);
00202 if (pulse.fit.fit_result == 0)
00203 fitgraph->SetLineColor(kGreen);
00204 else
00205 fitgraph->SetLineColor(kRed);
00206 fitgraph->Draw("same");
00207 }
00208 delete fitfunc;
00209 }
00210 }
00211 }
00212
00213 for(size_t i=0; i<regions.size(); i++){
00214 Roi& region = regions[i];
00215 double base = (baseline_subtracted ? 0 : baseline.mean);
00216
00217 double peaky = 0;
00218
00219 peaky = base + region.min;
00220 TBox* pbox = new TBox( x[region.start_index], base,
00221 x[region.end_index], peaky);
00222 pbox->SetBit(TObject::kCanDelete,true);
00223 pbox->SetLineColor(kGreen);
00224 pbox->Draw();
00225 if(draw_integral){
00226 TLine* iline = new TLine( x[region.min_index], base,
00227 x[region.min_index], base+region.integral*integral_scale);
00228 iline->SetBit(TObject::kCanDelete,true);
00229 iline->SetLineColor(kBlue);
00230 iline->SetLineWidth(4);
00231 iline->Draw();
00232 }
00233 TLine* pline = new TLine( x[region.min_index], base,
00234 x[region.min_index], peaky);
00235 pline->SetBit(TObject::kCanDelete,true);
00236 pline->SetLineColor(kMagenta);
00237 pline->Draw();
00238
00239
00240
00241 }
00242
00243 for(size_t i = 0; i<single_pe.size(); i++){
00244 const Spe& spe = single_pe[i];
00245 TBox* spebox =
00246 new TBox(spe.start_time, baseline.mean,
00247 spe.start_time + spe.length,
00248 baseline.mean - spe.amplitude);
00249 spebox->SetBit(TObject::kCanDelete, true);
00250 spebox->SetLineColor(kRed);
00251 spebox->Draw();
00252 }
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270 if(draw_integral){
00271
00272
00273
00274 TMarker* max_integral =
00275 new TMarker(integral_max_time,
00276 EvalTGraphPoint(*integral_graph,integral_max_time),3);
00277 max_integral->SetMarkerColor(integral_color);
00278 max_integral->SetBit(TObject::kCanDelete, true);
00279 max_integral->Draw();
00280
00281
00282
00283 TMarker* min_integral =
00284 new TMarker(integral_min_time,
00285 EvalTGraphPoint(*integral_graph,integral_min_time),3);
00286 min_integral->SetMarkerColor(integral_color);
00287 min_integral->SetBit(TObject::kCanDelete, true);
00288 min_integral->Draw();
00289
00290 if(gPad){
00291
00292 double x1,x2,y1,y2;
00293 gPad->GetRangeAxis(x1,y1,x2,y2);
00294 gPad->SetBit(TObject::kCanDelete, true);
00295 TGaxis* gaxis = new TGaxis(x2,y1,x2,y2,
00296 (y1-integral_offset)/integral_scale,
00297 (y2-integral_offset)/integral_scale,
00298 510,"L+");
00299 gaxis->SetName("integral_axis");
00300 if(channel_id == CH_SUM)
00301 gaxis->SetTitle("Integral [photoelectrons]");
00302 else
00303 gaxis->SetTitle("Integral [counts*samples]");
00304 gaxis->SetLineColor(integral_color);
00305 gaxis->SetTextColor(integral_color);
00306 gaxis->SetTitleColor(integral_color);
00307 gaxis->SetLabelColor(integral_color);
00308 gaxis->SetTitleOffset(1.2);
00309 gaxis->Draw();
00310 }
00311
00312 }
00313
00314 graphs->GetXaxis()->SetTitle("sample time [#mus]");
00315 if(channel_id == CH_SUM)
00316 graphs->GetYaxis()->SetTitle("Amplitude [arb]");
00317 else
00318 graphs->GetYaxis()->SetTitle("Amplitude [counts]");
00319
00320
00321
00322 }
00323
00324 void ChannelData::Print(int verbosity)
00325 {
00326 {
00327 Message m(INFO);
00328 m<<"CHANNEL "<<channel_id<<std::endl;
00329 m<<"Timestamp: "<<timestamp<<std::endl;
00330 m<<"Trigger Index: "<<trigger_index<<std::endl;
00331 m<<"Smoothed Min: "<<smoothed_min<<std::endl;
00332 m<<"Smoothed Max: "<<smoothed_max<<std::endl;
00333 m<<"Saturated: "<<saturated<<std::endl;
00334 m<<"Maximum: "<<maximum<<std::endl;
00335 m<<"Minimum: "<<minimum<<std::endl;
00336 m<<"Max Time: "<<max_time<<std::endl;
00337 m<<"Min Time: "<<min_time<<std::endl;
00338 m<<"SPE Mean: "<<spe_mean<<std::endl;
00339 m<<"SPE Sigma: "<<spe_sigma<<std::endl;
00340 m<<"Baseline Found: "<<baseline.found_baseline<<std::endl;
00341 m<<"Baseline Mean: "<<baseline.mean<<std::endl;
00342 m<<"Baseline Variance: "<<baseline.variance<<std::endl;
00343 m<<"Baseline Search Start Index: "<<baseline.search_start_index<<std::endl;
00344 m<<"Baseline Length: "<<baseline.length<<std::endl;
00345 m<<"Baseline Saturated: "<<baseline.saturated<<std::endl;
00346 m<<"Baseline Laser Skip: "<<baseline.laserskip<<std::endl;
00347 m<<"No. of Pulses: "<<npulses<<std::endl;
00348 m<<"Integral Max: "<<integral_max<<std::endl;
00349 m<<"Integral Min: "<<integral_min<<std::endl;
00350 m<<"Integral Max Time: "<<integral_max_time<<std::endl;
00351 m<<"Integral Min Time: "<<integral_min_time<<std::endl;
00352 m<<"Integral Max Index: "<<integral_max_index<<std::endl;
00353 m<<"Integral Min Index: "<<integral_min_index<<std::endl;
00354 m<<"Integral Max Time: "<<integral_max_time<<std::endl;
00355 m<<"S1 Full: "<<s1_full<<std::endl;
00356 m<<"S1 Fixed: "<<s1_fixed<<std::endl;
00357 m<<"S2 Full: "<<s2_full<<std::endl;
00358 m<<"S2 Fixed: "<<s2_fixed<<std::endl;
00359 }
00360 if (verbosity > 1)
00361 {
00362 for (int i = 0; i < npulses; i++)
00363 {
00364 pulses[i].Print(channel_id, i);
00365 }
00366 }
00367 }
00368