#include "MLogManip.h" /***************************************************************** CALLISTO -- CALibrate LIght Signals and Time Offsets datafile: A data file written by the fadctrl, e.g. 20170727_006.fits.fz or 00000015.003_D_MonteCarlo019_Events.fits.fz drsfile: Usually the third of the three .drs.fits files from a DRS calibration sequence, e.g. 20170727_004.drs.fits drstime: An input file with the constants for the DRS timing calibration [Not used right now, keep it 0] delays: A file with the delays of the individual channels [Not available right now, keep it 0] outpath: The path to which the output files are written To run the macro from the command line (assuming you are in a directory Mars/build where you have built your Mars environment) you can do root ../hawc/callisto.C\(\"20191002_018.fits.fz\",\"20191002_013.drs.fits\"\) or from within root [0] .x ../hawc/callisto.C("20191002_018.fits.fz", "20191002_013.drs.fits") ******************************************************************/ int callisto(const char *datafile, const char *drsfile, bool ismc, const char *outpath=".") { // ====================================================== const char *drstime = 0; const char *delays = 0; // ====================================================== // 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. // false is assumed automatically for files with the ISMC flag set. bool usemap = true; // mapping file (found in Mars/hawc) const char *mmap = usemap ? "../hawc/FAMOUSmap170719.txt": NULL; //const char *pulse_template = "template-pulse.root"; // Define a list of defect pixels here (software index) // They get interpolated from their neighbors // (if there are at least three valid neighbors) // The bahaviour can be altered in the corresponding task // (MBadPixelsTreat) MBadPixelsCam badpixels; badpixels.InitSize(64); badpixels[61].SetUnsuitable(MBadPixelsPix::kUnsuitable); badpixels[62].SetUnsuitable(MBadPixelsPix::kUnsuitable); badpixels[63].SetUnsuitable(MBadPixelsPix::kUnsuitable); // Range in which the pulse extraction searches for the // pulse (in samples). const int first_slice = 250; const int last_slice = 330; // Calibration constant (for the moment a single constant to // convert the extracted charge to photo-electrons) //double scale = 1./22.553;//0.2; double scale = 1./17.557; // Three pixels have a slightly different gain // so there signal must be attenuated // THIS ONLY HAS TO BE USED FOR DATA WITH THE RESISTORS IN PLACE!! MArrayD calib(64); calib.Reset(1); if (!ismc) { calib[33] = 1./0.82; calib[37] = 1./0.82; calib[43] = 1./0.82; } // ------------------------------------------------------ Long_t max = 0; // All // ====================================================== // Check if the requested mapping file is available if (mmap && gSystem->AccessPathName(mmap, kFileExists)) { gLog << err << "ERROR - Cannot access mapping file '" << mmap << "'" << endl; return 11; } // ------------------------------------------------------- // Check if the requested DRS time calibration constants are available MDrsCalibrationTime timecam; if (drstime && !timecam.ReadFits(drstime)) { gLog << err << "ERROR - Could not get MDrsCalibrationTime from " << drstime << endl; return 21; } if (delays) { TGraph g(delays); if (g.GetN()!=1440) { gLog << err << "Error reading file " << delays << endl; return 22; } timecam.SetDelays(g); } // ------------------------------------------------------ // Check and read the channel delays if (drstime && delays) { TGraph g(delays); if (g.GetN()!=1440) { gLog << err << "Error reading file " << delays << endl; return 41; } timecam.SetDelays(g); } // ------------------------------------------------------- // Check and read the DRS calibration constants MDrsCalibration drscalib300; if (drsfile && !drscalib300.ReadFits(drsfile)) return 31; // ====================================================== gLog.Separator("Callisto"); gLog << all; gLog << "Data file: " << datafile << '\n'; if (drsfile) gLog << "DRS Calib: " << drsfile << '\n'; if (drstime) gLog << "DRS Time: " << drstime << '\n'; if (delays) gLog << "Delays: " << delays << '\n'; gLog << "Outpath: " << outpath << '\n'; gLog << endl; // ------------------------------------------------------ gStyle->SetOptFit(kTRUE); // =================================================================== gLog << endl; gLog.Separator("Calibrating data"); // Instantiate the list of tasks MTaskList tlist5; // Instantiate the list of data containers MParList plist5; plist5.AddToList(&tlist5); plist5.AddToList(&badpixels); if (drsfile) plist5.AddToList(&drscalib300); if (drstime) plist5.AddToList(&timecam); // Instantiate the camera geometry MGeomCamFAMOUS geom; plist5.AddToList(&geom); // Instantiate the status display MStatusDisplay *d = new MStatusDisplay; // Instantiate the event loop MEvtLoop loop5("CalibratingData"); loop5.SetDisplay(d); loop5.SetParList(&plist5); // ------------------ Setup the tasks --------------- MDirIter files(datafile); // Instantiate the reading task // You can use // read5.AddFiles("*.fits.fz") // for example to read more than one file at once MRawFitsRead read5; read5.AddFiles(files); if (mmap) read5.LoadMap(mmap); // Instantiate the histogram to be filled with the rates MH3 hrate("MRawRunHeader.GetFileID", "int(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"); // Instantiate the task to fill therate histogram MFillH fill5a(&hrate); // Instantiate the task to ensure proper sizing of all containers MGeomApply apply5; // Instantiate the task to apply the drs calibration constants MDrsCalibApply drsapply5; drsapply5.SetMaxNumPrevEvents(0); // Switched off step-correction -> crashes due to the requirement of N*9 ch // Instantiate the filter to select only physics events MFDataPhrase filterdat("(int(MRawEvtHeader.GetTriggerID)&0xff00)==0", "SelectDat"); // --- /* MExtractTimeAndChargeSpline extractor5dat; extractor5dat.SetRange(first_slice, last_slice); extractor5dat.SetRiseTimeHiGain(rise_time_dat); extractor5dat.SetFallTimeHiGain(fall_time_dat); extractor5dat.SetHeightTm(heighttm); extractor5dat.SetChargeType(type); extractor5dat.SetSaturationLimit(600000); extractor5dat.SetNoiseCalculation(kFALSE); */ // Instantiate the digital filter (weighted sliding average) to clean the data // Note that the weights are not adapted yet to HAWC's Eye // A better filter might be worth to think about MFilterData filterdata1; // Instatiate task to extract the maximum of the pulse (correspondins to // a weighted integral) and the position of the leading edge between // first_slice and last_slice as charge and arrival time MExtractFACT extractor5dat("ExtractPulse"); extractor5dat.SetRange(first_slice, last_slice); extractor5dat.SetNoiseCalculation(kFALSE); // Instantiate task which applies the calibration constants MCalibrateFact conv5; conv5.SetScale(scale); conv5.SetCalibConst(calib); // Instantiate task which applies the DRS time calibration MCalibrateDrsTimes calctm5; calctm5.SetNameUncalibrated("UncalibratedTimes"); // Instantiate task to interpolate bad pixels MBadPixelsTreat treat5; treat5.SetProcessPedestalRun(kFALSE); treat5.SetProcessPedestalEvt(kFALSE); // Instantiate histograms to display charges MHCamEvent evt5b(0, "ExtSig", "Extracted signal;;S [mV#cdot sl]"); MHCamEvent evt5c(0, "CalSig", "Calibrated and interpolated signal;;S [~phe]"); MHCamEvent evt5d(4, "ExtSigTm", "Extracted time;;T [sl]"); MHCamEvent evt5e(6, "CalSigTm", "Calibrated and interpolated time;;T [ns]"); // Instantiate task to fill those histograms MFillH fill5b(&evt5b, "MExtractedSignalCam", "FillExtSig"); MFillH fill5c(&evt5c, "MSignalCam", "FillCalSig"); MFillH fill5d(&evt5d, "MArrivalTimeCam", "FillExtTm"); MFillH fill5e(&evt5e, "MSignalCam", "FillCalTm"); // Setup those histograms to fit a gaussian to the distribution fill5c.SetDrawOption("gaus"); fill5d.SetDrawOption("gaus"); fill5e.SetDrawOption("gaus"); // Instantiate the task to apply the software trigger MSoftwareTriggerCalc swtrig; // This is an alternative if more than one file should be read in a single loop // In this case the output file name of each file is created with this rule // from the input file name. Note that the filename of the output file // with the status display must then be explicitly given. // //const TString fname(Form("s/([0-9]+_[0-9]+)[.]fits([.][fg]z)?$/%s\\/$1_C.root/", // MJob::Esc(outpath).Data())); //MWriteRootFile write5(2, fname, "RECREATE", "Calibrated Data"); /* // Convert the name of the input file to the name of the output file TString fname = gSystem->ConcatFileName(outpath, gSystem->BaseName(datafile)); fname.ReplaceAll(".fits.gz", ".root"); fname.ReplaceAll(".fits.fz", ".root"); fname.ReplaceAll(".fits", ".root"); fname.ReplaceAll("_D_", "_C_"); gSystem->ExpandPathName(fname); */ const TString rule(Form("s/([0-9]+)([._])([0-9]+)(_[DPC])?([_].*)?([.]fits([.]fz)?)$/%s\\/$1$2$3_Y$5.root/", MJob:: Esc(outpath).Data())); // Instantitate the writing task and setup the writing MWriteRootFile write5(2, rule, "RECREATE", "Calibrated Data"); write5.AddContainer("MSignalCam", "Events"); write5.AddContainer("MRawEvtHeader", "Events"); write5.AddContainer("MSoftwareTrigger","Events"); write5.AddContainer("MRawRunHeader", "RunHeaders"); write5.AddContainer("MGeomCam", "RunHeaders"); write5.AddContainer("MMcCorsikaRunHeader", "RunHeaders", kFALSE); write5.AddContainer("MCorsikaRunHeader", "RunHeaders", kFALSE); write5.AddContainer("MMcRunHeader", "RunHeaders", kFALSE); write5.AddContainer("MCorsikaEvtHeader", "Events", kFALSE); write5.AddContainer("MMcEvt", "Events", kFALSE); write5.AddContainer("IncidentAngle", "Events", kFALSE); write5.AddContainer("MPointingPos", "Events", kFALSE); write5.AddContainer("MSimSourcePos", "Events", kFALSE); write5.AddContainer("MTime", "Events", kFALSE); write5.AddContainer("MRawBoardsFACT", "Events", kFALSE); write5.AddContainer("MSrcPosCam", "Events", kFALSE); // ------------------ Setup histograms and fill tasks ---------------- // Instantitate the task list and setp the list MTaskList tlist5dat; tlist5dat.AddToList(&fill5b); tlist5dat.AddToList(&fill5c); tlist5dat.AddToList(&fill5d); tlist5dat.AddToList(&fill5e); tlist5dat.SetFilter(&filterdat); tlist5.AddToList(&read5); tlist5.AddToList(&apply5); tlist5.AddToList(&drsapply5); tlist5.AddToList(&fill5a); tlist5.AddToList(&swtrig); tlist5.AddToList(&filterdata1); tlist5.AddToList(&extractor5dat); tlist5.AddToList(&calctm5); tlist5.AddToList(&conv5); tlist5.AddToList(&treat5); tlist5.AddToList(&filterdat); tlist5.AddToList(&tlist5dat); tlist5.AddToList(&write5); // run the eventloop if (!loop5.Eventloop(max)) return 18; // Check if the display was closed (deleted) by the user if (!loop5.GetDisplay()) return 19; // ============================================================ TString fname = write5.GetFileName(); fname.ReplaceAll(".root", "-display.root"); // Write the status display to the file TString title = "-- Calibrated signal ["; title += datafile; title += "] --"; d->SetTitle(title, kFALSE); d->SaveAsRoot(fname); return 0; }