diff --git a/macro/mvd/matbudget_ana.C b/macro/mvd/matbudget_ana.C new file mode 100644 index 0000000000000000000000000000000000000000..5d17fc744b76951b31cfafa05c7ef5a0a30650a5 --- /dev/null +++ b/macro/mvd/matbudget_ana.C @@ -0,0 +1,260 @@ +// Philipp Klaus, 30.04.2020 +// +// derived from version created for STS + +#if !defined(__CINT__) || defined(__MAKECINT__) +#include "TCanvas.h" +#include "TClonesArray.h" +#include "TFile.h" +#include "TH1.h" +#include "TProfile2D.h" +#include "TROOT.h" +#include "TString.h" +#include "TStyle.h" +#include "TSystem.h" +#include "TTree.h" +#include "TVector3.h" + +#include "FairRadLenPoint.h" + +#include <iostream> +#include <vector> +using std::cout; +using std::endl; +using std::vector; +#endif + +#include "TCanvas.h" +#include "TGaxis.h" +#include "TH2.h" +#include "TRandom.h" + +int station_num(float pos, float pitch, float first_z, int n_stations) { + float range_from = first_z - pitch / 2; + float range_to = range_from + n_stations * pitch; + if (pos < range_from || pos > range_to) + return -1; + else + return (pos - range_from) / (range_to - range_from) * n_stations; +} + +// Int_t matbudget_ana(Int_t nEvents = 10 , const char* mvdGeo = "v17a_tr") +// Int_t matbudget_ana(Int_t nEvents = 10000 , const char* mvdGeo = "v17a_tr") +Int_t matbudget_ana(Int_t nEvents = 10000000, const char* mvdGeo = "v17a_tr") { + + // Input file (MC) + TString mvdVersion(mvdGeo); + TString inFile = "data/matbudget." + mvdVersion + ".mc.root"; + TFile* input = new TFile(inFile); + if (!input) { + cout << "*** matbudget_ana: Input file " << inFile << " not found!\n" + << "Be sure to run matbudget_mc.C before for the respective MVD " + "geometry!" + << endl; + exit(1); + } + + // Output file (material maps) + TString outFile = "mvd_matbudget_" + mvdVersion + ".root"; + + // Input tree and branch + TTree* tree = (TTree*) input->Get("cbmsim"); + TClonesArray* points = new TClonesArray("FairRadLenPoint"); + tree->SetBranchAddress("RadLen", &points); + + // Create output histograms + TH1D* hisRadLen = new TH1D("hisRadLen", "Radiation Length", 1000, 0, 100); + const int nStations = 4; // number of MVD stations + const int nBins = 1000; // number of bins in histograms (in both x and y) + const int rMax = 21; // maximal radius for histograms (for both x and y) + const float stationPitch = 5.; + const float firstStationZ = 1.; + // % x/X0 the individual plots should have as limit: + // const double zRange = 22.5; // full-scale (including aluminium heatsinks) + const double zRange = + 0.7; // fixed-scale to pin range to values found in acceptance + TProfile2D* hStationRadLen[nStations]; + TProfile2D* hMvdRadLen; + double MvdRadThick = 0; + + TString mvdname = "Material Budget x/X_{0} [%], MVD"; + hMvdRadLen = + new TProfile2D(mvdname, mvdname, nBins, -rMax, rMax, nBins, -rMax, rMax); + + for (int i = 0; i < nStations; ++i) { + TString hisname = "Radiation Thickness [%],"; + hisname += " Station"; + hisname += i; + TString name = "Material Budget x/X_{0} [%],"; + name += " Station "; + name += i; + hStationRadLen[i] = + new TProfile2D(hisname, name, nBins, -rMax, rMax, nBins, -rMax, rMax); + } + + // Auxiliary variables + TVector3 vecs, veco; + std::map<int, int> trackHitMap; + + // Event loop + int firstEvent = 0; + for (Int_t event = firstEvent; + event < (firstEvent + nEvents) && event < tree->GetEntriesFast(); + event++) { + tree->GetEntry(event); + if (0 == event % 10000) cout << "*** Processing event " << event << endl; + + const int nTracks = 1; + std::vector<double> RadLengthOnTrack( + nTracks, 0.0); // trackID, vector with points on track + std::vector<double> TrackLength( + nTracks, 0.0); // trackID, vector with points on track + + double OverallRadThick = 0.0; + vector<double> RadThick(nStations, 0); + Double_t x = 0; + Double_t y = 0; + + // For this implementation to be correct, there should be only one MCTrack + // per event. + + // Point loop + for (Int_t iPoint = 0; iPoint < points->GetEntriesFast(); iPoint++) { + FairRadLenPoint* point = (FairRadLenPoint*) points->At(iPoint); + + if (point->GetDetectorID() != 1) // 1 == MVD + continue; + + // Get track position at entry and exit of material + TVector3 posIn, posOut, posDif; + posIn = point->GetPosition(); + posOut = point->GetPositionOut(); + posDif = posOut - posIn; + + // Midpoint between in and out + const TVector3 middle = (posOut + posIn); + x = middle.X() / 2; + y = middle.Y() / 2; + const double z = middle.Z() / 2; + + // Material budget per unit length + const double radThick = posDif.Mag() / point->GetRadLength(); + RadLengthOnTrack[point->GetTrackID()] += radThick; + TrackLength[point->GetTrackID()] += posDif.Mag(); + + // cout << "detectorID: " << point->GetDetectorID() << " Zin=" + // << posIn.Z() << " Zout=" << posOut.Z() << endl; + // cout << " length (cm): " << posDif.Mag() + // << " radlength (cm): " << point->GetRadLength() + // << " radThick (%):" << radThick * 100 << endl; + // if (event == 20) return -1; + + // Determine station number + int iStation = + station_num(posIn.Z(), stationPitch, firstStationZ, nStations); + int iStationOut = + station_num(posOut.Z(), stationPitch, firstStationZ, nStations); + + // cout << "station in: " << iStation << "station out: " << iStationOut << + // endl; + + if (iStationOut != iStation || (iStation == -1 && iStationOut == -1)) { + // cannot be assigned to a specific station + OverallRadThick += radThick; + continue; + } + // If still around, iStation == iStationOut, <- a proper station ID + RadThick[iStation] += radThick; + } + + MvdRadThick = 0; + // Fill material budget map for each station + for (int i = 0; i < nStations; ++i) { + if (RadThick[i] == 0.0) + // this avoids shadows of other stations in the plots + continue; + hStationRadLen[i]->Fill(x, y, RadThick[i] * 100); + MvdRadThick += RadThick[i]; + } + MvdRadThick += OverallRadThick; + + hMvdRadLen->Fill(x, y, MvdRadThick * 100); + + for (int k = 0; k < RadLengthOnTrack.size(); k++) + if (RadLengthOnTrack[k] > 0) hisRadLen->Fill(RadLengthOnTrack[k]); + + } // event loop + + // Plotting the results + // single TCanvas* can1 = new TCanvas("c","c",800,800); + TCanvas* can1 = new TCanvas("c", "c", 1600, 800); + can1->Divide(nStations / 2, 2); + gStyle->SetPalette(55); + gStyle->SetOptStat(0); + + // Open output file + TFile* output = new TFile(outFile, "RECREATE"); + output->cd(); + + for (int iStation = 0; iStation < nStations; iStation++) { + can1->cd(iStation + 1); + // single int iStation = 7; + hStationRadLen[iStation]->GetXaxis()->SetTitle("x [cm]"); + hStationRadLen[iStation]->GetYaxis()->SetTitle("y [cm]"); + // hStationRadLen[iStation]->GetZaxis()->SetTitle("x/X_{0} [%]"); + // hStationRadLen[i]->GetZaxis()->SetTitle("radiation thickness [%]"); + hStationRadLen[iStation]->SetAxisRange(0, zRange, "Z"); + gStyle->SetPalette(55); + hStationRadLen[iStation]->Draw("colz"); + hStationRadLen[iStation]->Write(); + } + + // Plot file + TString plotFile = "mvd_" + mvdVersion + "_matbudget.pdf"; + can1->SaveAs(plotFile); + plotFile = "mvd_" + mvdVersion + "_matbudget.jpg"; + can1->SaveAs(plotFile); + + //================================================================ + + // Plotting the results + TCanvas* can2 = new TCanvas("c", "c", 800, 800); + gStyle->SetPalette(55); + gStyle->SetOptStat(0); + + can2->cd(); + hMvdRadLen->GetXaxis()->SetTitle("x [cm]"); + hMvdRadLen->GetYaxis()->SetTitle("y [cm]"); + hMvdRadLen->SetAxisRange(0, zRange * nStations, "Z"); + gStyle->SetPalette(55); + hMvdRadLen->Draw("colz"); + + // Plot file + plotFile = "mvd_" + mvdVersion + "_total_matbudget.pdf"; + can2->SaveAs(plotFile); + plotFile = "mvd_" + mvdVersion + "_total_matbudget.jpg"; + can2->SaveAs(plotFile); + + //================================================================ + + TString thisStation(0); + can2->Clear(); + for (int iStation = 0; iStation < nStations; iStation++) { + hStationRadLen[iStation]->Draw("colz"); + // Plot file + thisStation.Form("%d", iStation); + plotFile = + "mvd_" + mvdVersion + "_station_" + thisStation + "_matbudget.pdf"; + can2->SaveAs(plotFile); + plotFile = + "mvd_" + mvdVersion + "_station_" + thisStation + "_matbudget.jpg"; + can2->SaveAs(plotFile); + } + + // Close files + input->Close(); + output->Close(); + cout << "Material budget maps written to " << outFile << endl; + + return 0; +} diff --git a/macro/mvd/matbudget_mc.C b/macro/mvd/matbudget_mc.C new file mode 100644 index 0000000000000000000000000000000000000000..45148b4da08a0a2738b2b6189418d61dbe77256c --- /dev/null +++ b/macro/mvd/matbudget_mc.C @@ -0,0 +1,198 @@ +// -------------------------------------------------------------------------- +// +// Macro for transport simulation with the MVD +// to determine the material budget of the MVD stations. +// ROOTinos parallel to the z axis will be transported, +// using the RadLenRegister functionality of FairRunSim. +// From the output MC file, the material budget can be +// determined with the macro matbudget_ana.C +// +// Philipp Klaus, 30.04.2020 +// +// derived from version created for STS by +// T. Balog, 11.05.2015 +// +// -------------------------------------------------------------------------- + +// void matbudget_mc(Int_t nEvents = 10 , const char* mvdGeo = "v17a_tr") +// void matbudget_mc(Int_t nEvents = 10000 , const char* mvdGeo = "v17a_tr") +void matbudget_mc(Int_t nEvents = 10000000, const char* mvdGeo = "v17a_tr") { + + // ======================================================================== + // Adjust this part according to your requirements + + // ----- Paths and file names -------------------------------------------- + TString mvdVersion(mvdGeo); + TString inDir = gSystem->Getenv("VMCWORKDIR"); + TString inFile = inDir + "/input/urqmd.ftn14"; + TString outDir = "data"; + TString outFile = outDir + "/matbudget." + mvdVersion + ".mc.root"; + TString parFile = outDir + "/matbudget." + mvdVersion + ".params.root"; + + // ----- Geometries ----------------------------------------------------- + TString caveGeom = "cave.geo"; + TString targetGeom = ""; + TString pipeGeom = ""; + TString magnetGeom = ""; + TString mvdGeom = "mvd/mvd_" + mvdVersion + ".geo.root"; + TString stsGeom = ""; + TString richGeom = ""; + TString trdGeom = ""; + TString tofGeom = ""; + + // In general, the following parts need not be touched + // ======================================================================== + + // --- Logger settings ---------------------------------------------------- + TString logLevel = "ERROR"; // "INFO"; + TString logVerbosity = "LOW"; + // ------------------------------------------------------------------------ + + // ---- Debug option ------------------------------------------------- + gDebug = 0; + // ------------------------------------------------------------------------ + + // ----- Timer -------------------------------------------------------- + TStopwatch timer; + timer.Start(); + // ------------------------------------------------------------------------ + + // ----- Create simulation run ---------------------------------------- + FairRunSim* run = new FairRunSim(); + run->SetName("TGeant3"); // Transport engine + run->SetOutputFile(outFile); // Output file + FairRuntimeDb* rtdb = run->GetRuntimeDb(); + // ------------------------------------------------------------------------ + + // ----- Logger settings ---------------------------------------------- + gLogger->SetLogScreenLevel(logLevel.Data()); + gLogger->SetLogVerbosityLevel(logVerbosity.Data()); + // ------------------------------------------------------------------------ + + // ----- Create media ------------------------------------------------- + run->SetMaterials("media.geo"); // Materials + // ------------------------------------------------------------------------ + + // ----- Create detectors and passive volumes ------------------------- + if (caveGeom != "") { + FairModule* cave = new CbmCave("CAVE"); + cave->SetGeometryFileName(caveGeom); + run->AddModule(cave); + } + + if (pipeGeom != "") { + FairModule* pipe = new CbmPipe("PIPE"); + pipe->SetGeometryFileName(pipeGeom); + run->AddModule(pipe); + } + + if (targetGeom != "") { + FairModule* target = new CbmTarget("Target"); + target->SetGeometryFileName(targetGeom); + run->AddModule(target); + } + + if (magnetGeom != "") { + FairModule* magnet = new CbmMagnet("MAGNET"); + magnet->SetGeometryFileName(magnetGeom); + run->AddModule(magnet); + } + + if (mvdGeom != "") { + FairDetector* mvd = new CbmMvd("MVD", kTRUE); + mvd->SetGeometryFileName(mvdGeom); + run->AddModule(mvd); + } + + if (stsGeom != "") { + FairDetector* sts = new CbmStsMC(kTRUE); + sts->SetGeometryFileName(stsGeom); + run->AddModule(sts); + } + + if (richGeom != "") { + FairDetector* rich = new CbmRich("RICH", kTRUE); + rich->SetGeometryFileName(richGeom); + run->AddModule(rich); + } + + if (trdGeom != "") { + FairDetector* trd = new CbmTrd("TRD", kTRUE); + trd->SetGeometryFileName(trdGeom); + run->AddModule(trd); + } + + if (tofGeom != "") { + FairDetector* tof = new CbmTof("TOF", kTRUE); + tof->SetGeometryFileName(tofGeom); + run->AddModule(tof); + } + + // ------------------------------------------------------------------------ + + // ----- Create magnetic field ---------------------------------------- + // Zero field + CbmFieldConst* magField = new CbmFieldConst(); + magField->SetField(0, 0, 0); // values are in kG + magField->SetFieldRegion(-74, -39, -22, 74, 39, 160); + run->SetField(magField); + + // ----- Create PrimaryGenerator -------------------------------------- + FairPrimaryGenerator* primGen = new FairPrimaryGenerator(); + run->SetGenerator(primGen); + + // --- Primary particles + // Generated are ROOTinos (PDG=0) in z direction (one per event), + // starting at z = 0. + // The starting points in x and y are chosen such as to illuminate the + // detector. + Int_t pdgId = 0; // ROOTinos + Int_t multiplicity = 1; // particles per event + FairBoxGenerator* boxGen = new FairBoxGenerator(pdgId, multiplicity); + + boxGen->SetBoxXYZ(-20., -20., 20., 20., -4.); + boxGen->SetPRange(0.1, 0.5); + boxGen->SetThetaRange(0., 0.); + boxGen->SetPhiRange(0., 360.); + + primGen->AddGenerator(boxGen); + + run->SetRadLenRegister(kTRUE); + // ------------------------------------------------------------------------ + + // ----- Run initialisation ------------------------------------------- + run->Init(); + // ------------------------------------------------------------------------ + + // ----- Runtime database --------------------------------------------- + CbmFieldPar* fieldPar = (CbmFieldPar*) rtdb->getContainer("CbmFieldPar"); + fieldPar->SetParameters(magField); + fieldPar->setChanged(); + fieldPar->setInputVersion(run->GetRunId(), 1); + Bool_t kParameterMerged = kTRUE; + FairParRootFileIo* parOut = new FairParRootFileIo(kParameterMerged); + parOut->open(parFile.Data()); + rtdb->setOutput(parOut); + rtdb->saveOutput(); + rtdb->print(); + // ------------------------------------------------------------------------ + + // ----- Start run ---------------------------------------------------- + run->Run(nEvents); + // ------------------------------------------------------------------------ + + // ----- Finish ------------------------------------------------------- + timer.Stop(); + Double_t rtime = timer.RealTime(); + Double_t ctime = timer.CpuTime(); + cout << endl << endl; + cout << "Macro finished succesfully." << endl; + cout << "Output file is " << outFile << endl; + cout << "Parameter file is " << parFile << endl; + cout << "Real time " << rtime << " s, CPU time " << ctime << "s" << endl + << endl; + // ------------------------------------------------------------------------ + + cout << " Test passed" << endl; + cout << " All ok " << endl; +}