00001 #include "ProcessedPlotter.hh"
00002 #include "RootGraphix.hh"
00003 #include "PulseFinder.hh"
00004 #include "Differentiator.hh"
00005 #include "SumChannels.hh"
00006 #include "BaselineFinder.hh"
00007 #include "Fitter.hh"
00008 #include "SpeFinder.hh"
00009 #include "ConvertData.hh"
00010 #include "EventHandler.hh"
00011 #include "ConfigHandler.hh"
00012 #include "CommandSwitchFunctions.hh"
00013 #include "V172X_Params.hh"
00014 #include "EvalRois.hh"
00015 #include "Integrator.hh"
00016 #include "S1S2Evaluation.hh"
00017 #include "PadZoomer.hh"
00018
00019 #include <algorithm>
00020 #include <sstream>
00021
00022 #include "TCanvas.h"
00023 #include "TColor.h"
00024 #include "TGraph.h"
00025 #include "TMultiGraph.h"
00026 #include "TH2F.h"
00027 #include "TAxis.h"
00028 #include "TLegend.h"
00029 #include "TList.h"
00030 #include "TMath.h"
00031 #include "TDirectory.h"
00032 #include "TMarker.h"
00033 #include "TEllipse.h"
00034 #include "TPaveLabel.h"
00035
00036 const int colors[] = {kBlack, kRed, kGreen, kCyan, kBlue, kMagenta, kYellow,
00037 kGray+2, kOrange-3, kGreen+3, kCyan+3, kMagenta-5,
00038 kRed-2};
00039 const int ncolors = sizeof(colors)/sizeof(int);
00040
00041
00042 ProcessedPlotter::ProcessedPlotter() :
00043 BaseModule(GetDefaultName(),
00044 "Plot each channel's waveform and selected analysis results"),
00045 _graphix(0), _paused(false)
00046 {
00047
00048 AddDependency<ConvertData>();
00049 AddDependency<RootGraphix>();
00050
00051
00052 RegisterParameter("chans_per_pad", chans_per_pad = 8,
00053 "Maximum number of channels to stack on a single plot");
00054 RegisterParameter("overlay_analysis", overlay_analysis = true,
00055 "Overlay the raw data with analysis module output (if only 1 channel in the pad)?");
00056 RegisterParameter("multi_color", multi_color = true,
00057 "Draw with multiple colors?");
00058 RegisterParameter("draw_legend", draw_legend = true,
00059 "Include a legend with the plot?");
00060 RegisterParameter("draw_title", draw_title = false,
00061 "Draw a separate title on the pulses plot?");
00062 RegisterParameter("autoscalex", autoscalex = true,
00063 "Set the scale of the x axis automatically?");
00064 RegisterParameter("autoscaley",autoscaley = true,
00065 "Set the scale of the y axis automatically?");
00066 RegisterParameter("xmin", xmin = -10, "Minimum range of the x axis");
00067 RegisterParameter("xmax", xmax = 10, "Maximum range of the x axis");
00068 RegisterParameter("ymin", ymin = 0, "Minimum range of the y axis");
00069 RegisterParameter("ymax", ymax = 16383, "Maximum range of the y axis");
00070 RegisterParameter("subtract_baseline", subtract_baseline = false,
00071 "Subtract the baseline before plotting?");
00072 RegisterParameter("downsample",downsample=1,
00073 "Factor by which to downsample graphed waveforms");
00074
00075 RegisterParameter("drawpulses",drawpulses = true,
00076 "Enable drawing of raw pulses?");
00077 RegisterParameter("drawpmtweights",drawpmtweights = false,
00078 "Enable drawing of PMT weights graph?");
00079 RegisterParameter("scale_pmts_sum",scale_pmts_sum = false,
00080 "Scale PMT weights to sum (true) or max (false)");
00081
00082
00083 for(int i=0; i<NCANVASES; ++i)
00084 _canvas[i] = 0;
00085 }
00086
00087 ProcessedPlotter::~ProcessedPlotter()
00088 {
00089 Finalize();
00090 }
00091
00092 int ProcessedPlotter::Initialize()
00093 {
00094 EventHandler* evhandler = EventHandler::GetInstance();
00095 _graphix = evhandler->GetModule<RootGraphix>();
00096 if(!_graphix){
00097
00098 Message(ERROR)<<"ProcessedPlotter called Initialize, but no RootGraphix!\n";
00099 return 1;
00100 }
00101
00102
00103
00104 drawpmtweights = false;
00105
00106 S1S2Evaluation* eval = evhandler->GetModule<S1S2Evaluation>();
00107 if(!eval || !eval->enabled)
00108 drawpmtweights = false;
00109
00110 if(!drawpulses && !drawpmtweights){
00111 Message(ERROR)<<"Processed plotter is enabled, but all draw functions "
00112 <<"are disabled. Aborting\n";
00113 return 2;
00114 }
00115
00116 if(drawpulses){
00117 _canvas[PULSES] = _graphix->GetCanvas();
00118 if(draw_title){
00119
00120 RootGraphix::Lock glock = _graphix->AcquireLock();
00121 _canvas[PULSES]->Divide(1,2);
00122 _canvas[PULSES]->cd(1);
00123 double y=0.95;
00124 gPad->SetPad(0,y,1,1);
00125 TPaveLabel* subtitle = new TPaveLabel(0.08,0,0.92,1,"","NDC");
00126 subtitle->SetBorderSize(0);
00127 subtitle->SetBit(TObject::kCanDelete,true);
00128 subtitle->SetTextColor(kYellow);
00129 subtitle->SetFillColor(kBlue);
00130 subtitle->SetFillStyle(1001);
00131 subtitle->SetTextFont(62);
00132 subtitle->SetTextSize(1.1);
00133 subtitle->Draw();
00134 _canvas[PULSES]->cd(2);
00135 gPad->SetPad(0,0,1,y);
00136 }
00137 }
00138
00139 if(drawpmtweights)
00140 _canvas[PMTWEIGHTS] = _graphix->GetCanvas();
00141
00142 if(downsample < 1) downsample = 1;
00143 return 0;
00144 }
00145
00146 int ProcessedPlotter::Finalize()
00147 {
00148 for(int i=0; i<NCANVASES; ++i)
00149 _canvas[i] = 0;
00150 return 0;
00151 }
00152
00153 int ProcessedPlotter::Process(EventPtr event)
00154 {
00155 if(_paused) return 0;
00156 EventDataPtr data = event->GetEventData();
00157 Message(DEBUG3)<<"ProcessedPlotter: Acquiring graphics lock.\n";
00158 RootGraphix::Lock glock = _graphix->AcquireLock();
00159 Message(DEBUG3)<<"ProcessedPlotter: Successfully acquired graphics lock.\n";
00160 char title[30];
00161 sprintf(title, "Run %d - Event %d", data->run_id, data->event_id);
00162 if(drawpulses && _canvas[PULSES]){
00163 _canvas[PULSES]->SetTitle(title);
00164 TPad* pulsepad = _canvas[PULSES];
00165 if(draw_title){
00166
00167 _canvas[PULSES]->cd(1);
00168 if(gPad->GetListOfPrimitives() &&
00169 gPad->GetListOfPrimitives()->GetEntries() == 1){
00170 TPaveLabel* label = (TPaveLabel*)(gPad->GetListOfPrimitives()->At(0));
00171 if(label){
00172 label->SetLabel(title);
00173 gPad->Modified();
00174 }
00175 }
00176 pulsepad = (TPad*)(_canvas[PULSES]->cd(2));
00177 if(!pulsepad){
00178 Message(ERROR)<<"ProcessedPlotter: Unable to find pulse pad!\n";
00179 return 1;
00180 }
00181 }
00182 pulsepad->Clear();
00183
00184
00185 int nchans = 0;
00186 std::vector<ChannelData*> chans_to_draw;
00187 for( size_t ch = 0; ch < data->channels.size(); ch++){
00188 if( _skip_channels.find(data->channels[ch].channel_id) ==
00189 _skip_channels.end() ){
00190 nchans++;
00191 chans_to_draw.push_back(&(data->channels[ch]));
00192 }
00193
00194 }
00195
00196 int cpp = chans_per_pad;
00197 if(cpp < 1)
00198 cpp = (nchans > 0 ? nchans : 1);
00199 int total_pads = (nchans+cpp-1)/cpp;
00200
00201 if(total_pads == 0)
00202 return 0;
00203 else if(total_pads == 1) {}
00204 else if(total_pads == 2)
00205 pulsepad->Divide(2,1);
00206 else if(total_pads < 5)
00207 pulsepad->Divide(2,2);
00208 else if(total_pads < 7)
00209 pulsepad->Divide(3,2);
00210 else if(total_pads < 10)
00211 pulsepad->Divide(3,3);
00212 else if(total_pads < 13)
00213 pulsepad->Divide(4,3);
00214 else if(total_pads < 17)
00215 pulsepad->Divide(4,4);
00216 else if(total_pads < 21)
00217 pulsepad->Divide(5,4);
00218 else if(total_pads < 26)
00219 pulsepad->Divide(5,5);
00220 else if(total_pads < 31)
00221 pulsepad->Divide(6,5);
00222 else if(total_pads < 37)
00223 pulsepad->Divide(6,6);
00224 else if(total_pads < 43)
00225 pulsepad->Divide(7,6);
00226 else{
00227 int rootpads = (int)(ceil(sqrt(total_pads)));
00228 pulsepad->Divide(rootpads,rootpads);
00229 }
00230 for(int pad=0; pad<total_pads; pad++){
00231 pulsepad->cd( (total_pads == 1 ? 0 : pad+1 ) );
00232
00233 if( overlay_analysis && (cpp == 1 || nchans == 1) ){
00234 chans_to_draw[pad]->Draw(subtract_baseline, downsample,
00235 autoscalex, autoscaley,
00236 xmin, xmax, ymin, ymax);
00237 }
00238 else{
00239 int chans_this_pad = std::min(cpp, nchans-pad*cpp);
00240 TMultiGraph* graphs = new TMultiGraph;
00241 graphs->SetBit(TObject::kCanDelete, true);
00242 TLegend* legend = 0;
00243 if(draw_legend && chans_this_pad > 1){
00244 legend = new TLegend(0,.9,1,1);
00245 legend->SetBit(TObject::kCanDelete, true);
00246 legend->SetNColumns(4);
00247 legend->SetColumnSeparation(-.3);
00248 legend->SetMargin(0.25);
00249 }
00250
00251 for(int i = pad*cpp;
00252 i < (pad+1)*cpp && i < nchans; i++){
00253 TGraph* g = chans_to_draw[i]->GetTGraph(subtract_baseline,downsample);
00254 if(!g) continue;
00255 if(multi_color && chans_this_pad>1){
00256 g->SetLineColor(colors[abs(chans_to_draw[i]->channel_id)%ncolors]);
00257
00258
00259
00260
00261 g->SetMarkerColor(g->GetLineColor());
00262 g->SetFillColor(g->GetLineColor());
00263 }
00264 if(legend)
00265 legend->AddEntry(g, g->GetTitle(), "lpf");
00266 graphs->Add(g);
00267 if(chans_this_pad == 1)
00268 graphs->SetTitle(g->GetTitle());
00269
00270 }
00271
00272 graphs->Draw("alp");
00273 if(!autoscalex)
00274 graphs->GetXaxis()->SetRangeUser(xmin, xmax);
00275 if(!autoscaley)
00276 graphs->GetYaxis()->SetRangeUser(ymin, ymax);
00277
00278
00279
00280
00281
00282
00283
00284
00285 if(legend)
00286 legend->Draw();
00287
00288 }
00289 }
00290
00291 if(!autoscalex || !autoscaley )
00292 gPad->Modified();
00293 _canvas[PULSES]->cd(0);
00294 _canvas[PULSES]->SetSelected(0);
00295
00296 new PadZoomer(pulsepad);
00297 }
00298
00299
00300 return 0;
00301 }
00302
00303
00304 const TCanvas* ProcessedPlotter::GetCanvas(int i) const
00305 {
00306 if (i == 0 || i == 1)
00307 return _canvas[i];
00308 else
00309 {
00310 Message(ERROR)<<"ProcessedPlotter::GetCanvas()"<<std::endl
00311 <<"Attempt to access non-existent canvas"
00312 <<std::endl;
00313 return NULL;
00314 }
00315 }