#include "MLogManip.h" int callisto(const char *seqfile="seq/2012/01/23/20120123_023.seq", const char *outpath = "output") { // ====================================================== // true: Display correctly mapped pixels in the camera displays // but the value-vs-index plot is in software/spiral indices // false: Display pixels in hardware/linear indices, // but the order is the camera display is distorted bool usemap = true; // map file to use (get that from La Palma!) const char *map = usemap ? "/home/fact/FACT++/FACTmap111030.txt" : NULL; /* Bool_t maximum = kTRUE; const char *lp_template = maximum ? "template-lp-extractor-maximum.root" : "template-lp-extractor-leading-edge.root"; const char *pulse_template = "template-pulse.root"; */ // ------------------------------------------------------ //bool use_delays=false; int spike_removal=3; // The gain as extracted from our dark count spectra double gain = 258; // ------------------------------------------------------ // Extraction range in slices. It will always(!) contain the full range // of integration const int first_slice = 25; // 10ns const int last_slice = 225; // 125ns // Note that rise and fall time mean different things whether you use IntegralFixed or IntegraRel: // // IntegralFixed: // * fRiseTime: Number of slices left from arrival time // * fFallTime: Number of slices right from arrival time // IntegralRel: // * fRiseTime: Number of slices left from maximum time // * fFallTime: Number of slices right from maximum time // /* const int rise_time_cal = maximum ? 40 : 10; // was 13; 5ns const int fall_time_cal = maximum ? 120 : 160; // was 23; 80ns const int rise_time_dat = maximum ? 10 : 2; // was 13; was 10; 1ns const int fall_time_dat = maximum ? 40 : 48; // was 23; was 40; 24ns // Extraction type: Extract integral and half leading edge const int type = maximum ? (MExtralgoSpline::kAmplitudeRel) : (MExtralgoSpline::kIntegralFixed); //const int type = MExtralgoSpline::kIntegralFixed; const double heighttm = 0.5; // IntegralAbs { 1.5pe * 9.6mV/pe } / IntegralRel { 0.5 } */ Long_t max = 0; // All Long_t max0 = max; // Time marker //Long_t max1 = max; // Light pulser //Long_t max2 = 3000; // Calibration ratio //Long_t max3 = max; // Pedestal Rndm //Long_t max4 = max; // Pedestal Ext Long_t max5 = max; // Data // ====================================================== if (map && gSystem->AccessPathName(map, kFileExists)) { gLog << err << "ERROR - Cannot access mapping file '" << map << "'" << endl; return 1; } // The sequence file which defines the files for the analysis MSequence seq(seqfile); if (!seq.IsValid()) { gLog << err << "ERROR - Sequence '" << seqfile << "' invalid!" << endl; return 2; } // -------------------------------------------------------------------------------- gLog.Separator("Callisto"); gLog << all << "Calibrate data of sequence '" << seq.GetFileName() << "'" << endl; gLog << endl; // ------------------------------------------------------ ostringstream drsname; drsname << gSystem->DirName(seqfile) << "/"; drsname << seq.GetNight().GetNightAsInt() << "_"; drsname << Form("%03d", seq.GetDrsSequence()) << ".drs.seq"; MSequence drs(drsname.str().c_str()); if (!drs.IsValid()) { gLog << err << "ERROR - DRS sequence invalid!" << endl; return 3; } gLog << all << "DRS sequence file: " << drsname.str() << '\n' << endl; TString drsfile = seq.GetFileName(0, MSequence::kRawDrs); if (drsfile.IsNull()) { gLog << err << "No DRS file available in sequence." << endl; return 4; } TString timfile = drs.GetFileName(0, MSequence::kFitsDat); TString drs1024 = drs.GetFileName(0, MSequence::kFitsDrs); TString calfile = seq.GetFileName(0, MSequence::kFitsCal); //TString pedfile = seq.GetFileName(0, MSequence::kFitsPed); gLog << all; gLog << "DRS calib 300: " << drsfile << '\n'; gLog << "DRS calib 1024: " << drs1024 << "\n\n"; MDrsCalibration drscalib300; if (!drscalib300.ReadFits(drsfile.Data())) return 5; MDrsCalibration drscalib1024; if (!drscalib1024.ReadFits(drs1024.Data())) return 6; gLog << all; gLog << "Time calibration : " << timfile << '\n'; gLog << "Light Pulser file: " << calfile << '\n' << endl; //gLog << "Pedestal file: " << pedfile << '\n'; // ------------------------------------------------------ MDirIter iter; if (seq.GetRuns(iter, MSequence::kFitsDat)<=0) { gLog << err << "ERROR - Sequence valid but without files." << endl; return 7; } iter.Print(); // ====================================================== MStatusArray arrt, arrp; TFile ft(lp_template); if (arrt.Read()<=0) { gLog << err << "ERROR - Reading LP template from " << lp_template << endl; return 100; } MHCamera *lpref = (MHCamera*)arrt.FindObjectInCanvas("ExtCalSig;avg", "MHCamera", "Cam"); if (!lpref) { gLog << err << "ERROR - LP Template not found in " << lp_template << endl; return 101; } lpref->SetDirectory(0); MHCamera *gain = (MHCamera*)arrt.FindObjectInCanvas("gain", "MHCamera", "Gain"); if (!gain) { gLog << err << "ERROR - Gain not found in " << lp_template << endl; return 101; } gain->SetDirectory(0); TFile fp(pulse_template); if (arrp.Read()<=0) { gLog << err << "ERROR - Reading Pulse template from " << pulse_template << endl; return 102; } TH1F *hpulse = (TH1F*)arrp.FindObjectInCanvas("hPixelEdgeMean0_0", "TH1F", "cgpPixelPulses0"); if (!hpulse) { gLog << err << "ERROR - Pulse Template not found in " << pulse_template << endl; return 103; } hpulse->SetDirectory(0); // ====================================================== MStatusDisplay *d = new MStatusDisplay; MBadPixelsCam badpixels; badpixels.InitSize(1440); badpixels[ 424].SetUnsuitable(MBadPixelsPix::kUnsuitable); badpixels[ 583].SetUnsuitable(MBadPixelsPix::kUnsuitable); badpixels[ 830].SetUnsuitable(MBadPixelsPix::kUnsuitable); badpixels[ 923].SetUnsuitable(MBadPixelsPix::kUnsuitable); badpixels[1208].SetUnsuitable(MBadPixelsPix::kUnsuitable); badpixels[1399].SetUnsuitable(MBadPixelsPix::kUnsuitable); // Twin pixel // 113 // 115 // 354 // 423 // 1195 // 1393 MDrsCalibrationTime timecam; // Plot the trigger pattern rates vs. run-number MH3 hrate("MRawRunHeader.GetFileID", "MRawEvtHeader.GetTriggerID&0xff00"); hrate.SetWeight("1./TMath::Max(MRawRunHeader.GetRunLength,1)"); hrate.SetName("Rate"); hrate.SetTitle("Event rate [Hz];File Id;Trigger Type;"); hrate.InitLabels(MH3::kLabelsXY); hrate.DefineLabelY( 0, "Data"); // What if TriggerID==0 already??? hrate.DefineLabelY(0x100, "Cal"); hrate.DefineLabelY(0x400, "Ped"); // hrate.DefaultLabelY("ERROR"); Bool_t isinteg = (type&MExtralgoSpline::kIntegral) || (type&MExtralgoSpline::kFixedWidth) || (type&MExtralgoSpline::kDynWidth) ? kTRUE : kFALSE; gStyle->SetOptFit(kTRUE); // ====================================================== gLog << endl; gLog.Separator("Processing DRS timing calibration run"); MTaskList tlist0; MParList plist0; plist0.AddToList(&tlist0); plist0.AddToList(&drscalib1024); plist0.AddToList(&badpixels); plist0.AddToList(&timecam); MEvtLoop loop0("DetermineTimeCal"); loop0.SetDisplay(d); loop0.SetParList(&plist0); // ------------------ Setup the tasks --------------- MRawFitsRead read0(timfile); MContinue cont0("MRawEvtHeader.GetTriggerID!=33792", "SelectTim"); MGeomApply apply0; MDrsCalibApply drsapply0; drsapply0.SetRemoveSpikes(spike_removal); MFillH fill0("MHDrsCalibrationTime"); fill0.SetNameTab("DeltaT"); tlist0.AddToList(&read0); tlist0.AddToList(&apply0); tlist0.AddToList(&drsapply0); tlist0.AddToList(&cont0); tlist0.AddToList(&fill0); if (!loop0.Eventloop(max0)) return 8; if (!loop0.GetDisplay()) return 9; /* MHDrsCalibrationT *t = (MHDrsCalibrationT*)plist4.FindObject("MHDrsCalibrationT"); t->SetDisplay(d); t->PlotAll(); */ // ====================================================== /* gLog << endl; gLog.Separator("Processing external light pulser run"); MTaskList tlist1; MParList plist1; plist1.AddToList(&tlist1); plist1.AddToList(&drscalib300); plist1.AddToList(&badpixels); plist1.AddToList(&timecam); MEvtLoop loop1("DetermineCalConst"); loop1.SetDisplay(d); loop1.SetParList(&plist1); // ------------------ Setup the tasks --------------- MRawFitsRead read1; read1.LoadMap(map); read1.AddFile(calfile); MContinue cont1("(MRawEvtHeader.GetTriggerID&0xff00)!=0x100", "SelectCal"); MGeomApply apply1; MDrsCalibApply drsapply1; drsapply1.SetRemoveSpikes(spike_removal); // --- MExtractTimeAndChargeSpline extractor1b("ExtractPulse"); extractor1b.SetRange(first_slice, last_slice); extractor1b.SetRiseTimeHiGain(rise_time_cal); extractor1b.SetFallTimeHiGain(fall_time_cal); extractor1b.SetHeightTm(heighttm); extractor1b.SetChargeType(type); extractor1b.SetSaturationLimit(600000); extractor1b.SetNoiseCalculation(kFALSE); MExtractTimeAndChargeSpline extractor1c("ExtractAmplitude"); extractor1c.SetRange(first_slice, last_slice); extractor1c.SetChargeType(MExtralgoSpline::kAmplitude); extractor1c.SetSaturationLimit(600000); extractor1c.SetNoiseCalculation(kFALSE); extractor1c.SetNameSignalCam("Amplitude"); extractor1c.SetNameTimeCam("AmplitudePos"); // --- MHCamEvent evt1a(5, "CalRatio", "Ratio per slice between integrated signal and amplitude;; r [1/n]"); evt1a.SetNameSub("Amplitude", kTRUE); MFillH fill1a(&evt1a, "MExtractedSignalCam", "FillRatio"); fill1a.SetDrawOption("gaus"); MParameterD ratio1a; ratio1a.SetVal(1./(fall_time_cal+rise_time_cal)); fill1a.SetWeight(&ratio1a); // --- MHCamEvent evt1f(0, "ExtCalSig", "Extracted calibration signal;;S [mV·sl]"); MHCamEvent evt1g(4, "ExtCalTm", "Extracted arrival times;;T [sl]"); MHCamEvent evt1h(6, "CalCalTm", "Calibrated arrival times;;T [sl]"); MHSectorVsTime hist1rmsb("ExtSigVsTm"); MHSectorVsTime hist1tmb("CalTmVsTm"); hist1rmsb.SetTitle("Extracted calibration vs event number;;S [mV·sl]"); hist1rmsb.SetType(0); hist1tmb.SetTitle("Extracted arrival time vs event number;;T [sl]"); //hist1tmb.SetType(4); hist1tmb.SetType(6); MFillH fill1f(&evt1f, "MExtractedSignalCam", "FillExtSig"); MFillH fill1g(&evt1g, "MArrivalTimeCam", "FillExtTm"); MFillH fill1h(&evt1h, "MSignalCam", "FillCalTm"); MFillH fill1r(&hist1rmsb, "MExtractedSignalCam", "FillExtSigVsTm"); //MFillH fill1j(&hist1tmb, "MArrivalTimeCam", "FillExtTmVsTm"); MFillH fill1j(&hist1tmb, "MSignalCam", "FillCalTmVsTm"); fill1f.SetDrawOption("gaus"); fill1h.SetDrawOption("gaus"); // --- MCalibrateDrsTimes calctm1a("CalibrateCalEvents"); calctm1a.SetNameUncalibrated("UncalibratedTimes"); MBadPixelsTreat treat1; treat1.SetProcessPedestalRun(kFALSE); treat1.SetProcessPedestalEvt(kFALSE); // --- MHCamEvent evt1c(6, "ExtCalTmShift", "Relative extracted arrival time of calibration pulse (w.r.t. event-median);;\\Delta T [ns]"); MHCamEvent evt1d(6, "CalCalTmShift", "Relative calibrated arrival time of calibration pulse (w.r.t. event-median);;\\Delta T [ns]"); evt1c.SetMedianShift(); evt1d.SetMedianShift(); MFillH fill1c(&evt1c, "UncalibratedTimes", "FillExtCalTm"); MFillH fill1d(&evt1d, "MSignalCam", "FillCalCalTm"); fill1d.SetDrawOption("gaus"); // ------------------ Setup eventloop and run analysis --------------- tlist1.AddToList(&read1); tlist1.AddToList(&apply1); tlist1.AddToList(&drsapply1); tlist1.AddToList(&cont1); tlist1.AddToList(&extractor1b); if (isinteg) { tlist1.AddToList(&extractor1c); tlist1.AddToList(&fill1a); } tlist1.AddToList(&calctm1a); tlist1.AddToList(&treat1); tlist1.AddToList(&fill1f); tlist1.AddToList(&fill1g); tlist1.AddToList(&fill1h); tlist1.AddToList(&fill1r); tlist1.AddToList(&fill1j); tlist1.AddToList(&fill1c); tlist1.AddToList(&fill1d); if (!loop1.Eventloop(max1)) return 10; if (!loop1.GetDisplay()) return 11; if (use_delays) timecam.SetDelays(*evt1h.GetHist()); // ========================= Result ================================== Double_t avgS = evt1f.GetHist()->GetMean(); Double_t medS = evt1f.GetHist()->GetMedian(); Double_t rmsS = evt1f.GetHist()->GetRMS(); Double_t maxS = evt1f.GetHist()->GetMaximum(); MArrayF der1(hpulse->GetNbinsX()); MArrayF der2(hpulse->GetNbinsX()); MExtralgoSpline spline(hpulse->GetArray()+1, hpulse->GetNbinsX(), der1.GetArray(), der2.GetArray()); spline.SetRiseFallTime(rise_time_dat, fall_time_dat); spline.SetExtractionType(type); spline.SetHeightTm(heighttm); spline.Extract(hpulse->GetMaximumBin()-1); // The pulser signal is most probably around 400mV/9.5mV // IntegraFixed 2/48 corresponds to roughly 215mV*50slices Double_t scale = 1./spline.GetSignal(); MArrayD calib(1440); for (int i=0; i<1440; i++) { Double_t g = gain->GetBinContent(i+1)>0.5 ? gain->GetBinContent(i+1) : 1; if (evt1f.GetHist()->GetBinContent(i+1)>0 && !badpixels[i].IsUnsuitable()) calib[i] = lpref->GetBinContent(i+1) / evt1f.GetHist()->GetBinContent(i+1) / g; } gROOT->SetSelectedPad(0); d->AddTab("PulseTemp"); gPad->SetGrid(); hpulse->SetNameTitle("Pulse", "Single p.e. pulse template"); hpulse->SetDirectory(0); hpulse->SetLineColor(kBlack); hpulse->DrawCopy(); TAxis *ax = hpulse->GetXaxis(); Double_t w = hpulse->GetBinWidth(1); Double_t T = w*(spline.GetTime()+0.5) +ax->GetXmin(); Double_t H = w*(hpulse->GetMaximumBin()+0.5)+ax->GetXmin(); TLine line; line.SetLineColor(kRed); line.DrawLine(T-rise_time_dat*w, spline.GetHeight(), T+fall_time_dat*w, spline.GetHeight()); line.DrawLine(T, spline.GetHeight()/4, T, 3*spline.GetHeight()/4); line.DrawLine(T-rise_time_dat*w, 0, T-rise_time_dat*w, spline.GetHeight()); line.DrawLine(T+fall_time_dat*w, 0, T+fall_time_dat*w, spline.GetHeight()); TGraph gg; for (int ix=1; ix<=hpulse->GetNbinsX(); ix++) for (int i=0; i<10; i++) { Double_t x = hpulse->GetBinLowEdge(ix)+i*hpulse->GetBinWidth(ix)/10.; gg.SetPoint(gg.GetN(), x+w/2, spline.EvalAt(ix-1+i/10.)); } gg.SetLineColor(kBlue); gg.SetMarkerColor(kBlue); gg.SetMarkerStyle(kFullDotMedium); gg.DrawClone("L"); gROOT->SetSelectedPad(0); d->AddTab("CalConst"); MGeomCamFACT fact; MHCamera hcalco(fact); hcalco.SetName("CalConst"); hcalco.SetTitle(Form("Relative calibration constant [%.0f/pe]", 1./scale)); hcalco.SetCamContent(calib); hcalco.SetAllUsed(); //hcalco.Scale(scale); hcalco.DrawCopy(); */ TF1 f("f", "[0]*(1-1/(1+exp(x/[1])))*exp(-x/[2])", -15, 150); f.SetParameter(0, gain*0.05143); f.SetParameter(1, 1.075); f.SetParameter(2, 19.3); f.SetNpx(2*165); //2GHz // Convert to graph TGraph g(&f); // Convert to float MArrayF x(g.GetN()); MArrayF y(g.GetN()); for (int i=0; iSetTitle(title, kFALSE); TString path; path += Form("%s/20%6d_%03d-calibration.root", outpath, seq.GetSequence()/1000, seq.GetSequence()%1000); d->SaveAs(path); return 0; } int callisto(const ULong64_t seqnum, const char *outpath = "output") { UInt_t night = seqnum/1000; UInt_t num = seqnum%1000; TString file = Form("/scratch/fact/sequences/%04d/%02d/%02d/%06d_%03d.seq", night/10000, (night/100)%100, night%100, num); return callisto(file.Data(), outpath); }