diff --git a/examples/extracted_MDC2025.fcl b/examples/extracted_MDC2025.fcl index e9f54bc..6f69510 100644 --- a/examples/extracted_MDC2025.fcl +++ b/examples/extracted_MDC2025.fcl @@ -44,9 +44,10 @@ physics.analyzers.Mu2eEventDisplay.filler.addCrvClusters : true physics.analyzers.Mu2eEventDisplay.filler.addCrvTrack : true physics.analyzers.Mu2eEventDisplay.filler.addCrvRecoPulse : false physics.analyzers.Mu2eEventDisplay.filler.addCaloDigis : false -physics.analyzers.Mu2eEventDisplay.filler.addClusters : false +physics.analyzers.Mu2eEventDisplay.filler.addClusters : true physics.analyzers.Mu2eEventDisplay.filler.addKalSeeds : true physics.analyzers.Mu2eEventDisplay.filler.addTrackerHist : true +physics.analyzers.Mu2eEventDisplay.filler.addCaloHist : false physics.analyzers.Mu2eEventDisplay.extracted : true physics.analyzers.Mu2eEventDisplay.specifyTag : false diff --git a/fcl/extracted.fcl b/fcl/extracted.fcl index dfd1b86..4792ab2 100644 --- a/fcl/extracted.fcl +++ b/fcl/extracted.fcl @@ -23,6 +23,7 @@ Mu2eEventDisplay.addTrkCaloHits : true Mu2eEventDisplay.filler.addCosmicTrackSeeds : false Mu2eEventDisplay.filler.addMCTraj : true Mu2eEventDisplay.filler.addTrackerHist : true +Mu2eEventDisplay.filler.addCaloHist : true Mu2eEventDisplay.filler.addHelixSeeds : false Mu2eEventDisplay.specifyTag : false diff --git a/fcl/prolog.fcl b/fcl/prolog.fcl index a77570c..a89a209 100644 --- a/fcl/prolog.fcl +++ b/fcl/prolog.fcl @@ -41,16 +41,17 @@ Mu2eEventDisplay : { addHits : false addBkgClusters : false addCrvRecoPulse : false - addCrvClusters : false - addCrvTrack : false - addTimeClusters : false + addCrvClusters : false + addCrvTrack : false + addTimeClusters : false addTrkHits : false //Combo hits? addCaloDigis : false addClusters : true addKalSeeds : true addCosmicTrackSeeds : false - addMCTraj : true - addTrackerHist : false + addMCTraj : true + addTrackerHist : false + addCaloHist : false addSurfSteps : true addSimParts : false addHelixSeeds : false diff --git a/inc/CollectionFiller.hh b/inc/CollectionFiller.hh index 0cf122f..2abdf95 100644 --- a/inc/CollectionFiller.hh +++ b/inc/CollectionFiller.hh @@ -89,6 +89,7 @@ namespace mu2e{ fhicl::Atom addSurfSteps{Name("addSurfSteps"), Comment("set to add SurfaceStep MC"),false}; fhicl::Atom addSimParts{Name("addSimParts"), Comment("set to add SimParticles MC"),false}; fhicl::Atom addTrackerHist{Name("addTrackerHist"), Comment("set to add tracker histogram"),false}; + fhicl::Atom addCaloHist{Name("addCaloHist"), Comment("set to add calorimeter histogram"),false}; // Global flag to attempt retrieval of all collections found in the event fhicl::Atom FillAll{Name("FillAll"), Comment("to see all available products"), false}; @@ -129,7 +130,8 @@ namespace mu2e{ // --- Boolean Control Flags (Copied from FHiCL Config) --- bool addHits_, addBkgClusters_, addCrvRecoPulse_, addCrvClusters_, addCrvTrack_, addTimeClusters_, addTrkHits_, addCaloDigis_, addClusters_, addHelixSeeds_, addKalSeeds_, addCosmicTrackSeeds_, addMCTraj_, - addSurfSteps_, addSimParts_, addTrackerHist_, FillAll_; + addSurfSteps_, addSimParts_, addTrackerHist_, addCaloHist_, FillAll_; + // --- Collection Retrieval Methods --- diff --git a/inc/MainWindow.hh b/inc/MainWindow.hh index 59d7cae..a491811 100644 --- a/inc/MainWindow.hh +++ b/inc/MainWindow.hh @@ -152,14 +152,17 @@ namespace mu2e { bool addMCTrajectories = false; bool addSurfaceSteps = false; bool addSimParts = false; - bool addTrackerHist = false; + bool addTrackerHist = false; + bool addCaloHist = false; + bool addTrkErrBar = true; bool addCrystalDraw = false; bool addCrvBars = true; DrawOptions(){}; - DrawOptions(bool cosmictracks, bool helices, bool tracks, bool calodigis, bool clusters, bool combohits, bool bkgclusters, bool crv, bool crvclu, bool crvtrack, bool timeclusters, bool trkhits, bool mctraj, bool surfsteps, bool simparts, bool trackerhist, bool errbar, bool crys, bool crvbars) - : addCosmicTracks(cosmictracks), addHelices(helices), addTracks(tracks), addCaloDigis(calodigis), addClusters(clusters), addComboHits(combohits), addBkgClusters(bkgclusters), addCrvRecoPulse(crv), addCrvClusters(crvclu), addCrvTrack(crvtrack), addTimeClusters(timeclusters), addTrkHits(trkhits), addMCTrajectories(mctraj), addSurfaceSteps(surfsteps), addSimParts(simparts), addTrackerHist(trackerhist), addTrkErrBar(errbar), addCrystalDraw(crys), addCrvBars(crvbars) {}; + DrawOptions(bool cosmictracks, bool helices, bool tracks, bool calodigis, bool clusters, bool combohits, bool bkgclusters, bool crv, bool crvclu, bool crvtrack, bool timeclusters, bool trkhits, bool mctraj, bool surfsteps, bool simparts, bool trackerhist, bool calohist, bool errbar, bool crys, bool crvbars) + : addCosmicTracks(cosmictracks), addHelices(helices), addTracks(tracks), addCaloDigis(calodigis), addClusters(clusters), addComboHits(combohits), addBkgClusters(bkgclusters), addCrvRecoPulse(crv), addCrvClusters(crvclu), addCrvTrack(crvtrack), addTimeClusters(timeclusters), addTrkHits(trkhits), addMCTrajectories(mctraj), addSurfaceSteps(surfsteps), addSimParts(simparts), addTrackerHist(trackerhist), addCaloHist(calohist), addTrkErrBar(errbar), addCrystalDraw(crys), addCrvBars(crvbars) {}; + }; diff --git a/inc/TrackerCalo2DViews.hh b/inc/TrackerCalo2DViews.hh index 77dd9e4..468ef3f 100644 --- a/inc/TrackerCalo2DViews.hh +++ b/inc/TrackerCalo2DViews.hh @@ -8,6 +8,7 @@ #include #include #include "Offline/RecoDataProducts/inc/KalSeed.hh" +#include namespace REX = ROOT::Experimental; @@ -19,12 +20,17 @@ public: virtual ~TrackerCalo2DViews(); void createHistogramView(); - void drawTrackerStation(const mu2e::KalSeedPtrCollection* seedcol); - void redrawCanvas(const mu2e::KalSeedPtrCollection* seedcol); + void drawTrackerStation(const mu2e::KalSeedPtrCollection* seedcol); //, const CaloDigiCollection* calodigicol); + void drawTrackerXYView(const mu2e::KalSeedPtrCollection* seedcol); + void drawCalorimeterDisk(); + //void redrawCanvas(const mu2e::KalSeedPtrCollection* seedcol); private: REX::REvePointSet* fCanvasHolder{nullptr}; TCanvas* fCanvas{nullptr}; + TCanvas* fCaloCanvas{nullptr}; + TCanvas* fXYCanvas{nullptr}; + std::map fPlaneCanvases; }; } // namespace mu2e diff --git a/src/CLAUDE.md b/src/CLAUDE.md new file mode 100644 index 0000000..e69de29 diff --git a/src/CollectionFiller.cc b/src/CollectionFiller.cc index 759ad1b..27dc015 100644 --- a/src/CollectionFiller.cc +++ b/src/CollectionFiller.cc @@ -37,6 +37,7 @@ namespace mu2e{ addSurfSteps_(conf.addSurfSteps()), addSimParts_(conf.addSimParts()), addTrackerHist_(conf.addTrackerHist()), + addCaloHist_(conf.addCaloHist()), FillAll_(conf.FillAll()) {} diff --git a/src/MainWindow.cc b/src/MainWindow.cc index 323ebf5..2059452 100644 --- a/src/MainWindow.cc +++ b/src/MainWindow.cc @@ -781,15 +781,19 @@ void MainWindow::showEvents(REX::REveManager *eveMng, REX::REveElement* &eventSc std::vector track_list = std::get<1>(data.track_tuple); if(drawOpts.addTracks and track_list.size() !=0) { pass_data->FillKinKalTrajectory(eveMng, firstLoop, eventScene, data.track_tuple, KKOpts.addKalInter, KKOpts.addTrkStrawHits, KKOpts.addTrkCaloHits, t1, t2); - - auto const& track_list = std::get<1>(data.track_tuple); - const mu2e::KalSeedPtrCollection* seedcol = track_list[0]; - if(drawOpts.addTrackerHist) { + //redrawCanvas(seedcol); + if(drawOpts.addTrackerHist and track_list.size() !=0) { fTrackerCalo2DViews = new TrackerCalo2DViews(); + auto const& track_list = std::get<1>(data.track_tuple); + const mu2e::KalSeedPtrCollection* seedcol = track_list[0]; + //std::vector calodigi_list = std::get<1>(data.calodigi_tuple); + //const CaloDigiCollection* calodigicol = calodigi_list[0]; //fTrackerCalo2DViews->createHistogramView(); - fTrackerCalo2DViews->redrawCanvas(seedcol); - } - //redrawCanvas(seedcol); + //fTrackerCalo2DViews->redrawCanvas(seedcol); + //std::cout<<"track list size = "< #include +#include #include #include +#include #include #include #include #include +#include +#include #include #include +#include #include "Offline/Mu2eKinKal/inc/WireHitState.hh" #include "Offline/GeometryService/inc/GeomHandle.hh" #include "Offline/TrackerGeom/inc/Tracker.hh" #include "Offline/TrackerGeom/inc/Plane.hh" #include "Offline/TrackerGeom/inc/Panel.hh" #include "Offline/TrackerGeom/inc/Straw.hh" +#include "Offline/CalorimeterGeom/inc/DiskCalorimeter.hh" +#include "Offline/CalorimeterGeom/inc/Disk.hh" +#include "Offline/CalorimeterGeom/inc/Crystal.hh" namespace mu2e { @@ -31,133 +39,355 @@ void TrackerCalo2DViews::createHistogramView() { canvasViewer->AddScene(histScene); } -void TrackerCalo2DViews::drawTrackerStation(const mu2e::KalSeedPtrCollection* seedcol) { - // Note: We can draw without fCanvas/fCanvasHolder since you want offline viewing - mu2e::GeomHandle tracker; - - std::map hitDataMap; - std::set uniquePlanes; - - if (seedcol != nullptr) { - for (auto const& kseedptr : *seedcol) { - const mu2e::KalSeed& kseed = *kseedptr; - for (auto const& hit : kseed.hits()) { - mu2e::StrawId sid = hit.strawId(); - uniquePlanes.insert(sid.getPlane()); - hitDataMap[sid] = &hit; - } +template +static void drawTrajectory2D(const KTRAJ& trajectory, const mu2e::Plane& plane, std::map& panelPads, const std::set& activePanels) +{ + double t1 = trajectory.range().begin(); + double t2 = trajectory.range().end(); + double step = 0.5; + std::map panelGraphs; + for (int pid : activePanels) { + panelGraphs[pid] = new TGraph(); + } + for(double t = t1; t <= t2; t += step) { + auto pos = trajectory.position3(t); + CLHEP::Hep3Vector global(pos.x(), pos.y(), pos.z()); + for (int pid : activePanels) { + const mu2e::Panel& panel = plane.getPanel(pid); + CLHEP::Hep3Vector local = panel.dsToPanel() * global; + double w = local.z(); + double v = local.y(); + auto* g = panelGraphs[pid]; + g->SetPoint(g->GetN(), w, v); } } + for (auto& [pid, graph] : panelGraphs) { + TPad* pad = panelPads.count(pid) ? panelPads.at(pid) : nullptr; + if (!pad) continue; + pad->cd(); + graph->SetLineColor(kRed); + graph->SetLineWidth(3); + graph->Draw("L SAME"); + } +} + +template +static void drawTrajectoryXY(const KTRAJ& trajectory) +{ + double t1 = trajectory.range().begin(); + double t2 = trajectory.range().end(); + double step = 0.5; - double strawRadius = tracker->strawProperties()._strawOuterRadius; + TGraph* graph = new TGraph(); + for (double t = t1; t <= t2; t += step) { + auto pos = trajectory.position3(t); + graph->SetPoint(graph->GetN(), pos.x(), pos.y()); + } - std::vector planeIdA = {0,3,4,7,8,11,12,15,16,19,20,23,24,27,28,31,32,35}; + graph->SetLineColor(kRed); + graph->SetLineWidth(2); + graph->Draw("L SAME"); +} - for (const auto& planeId : uniquePlanes) { + void TrackerCalo2DViews::drawTrackerStation(const mu2e::KalSeedPtrCollection* seedcol){ //, const CaloDigiCollection* calodigicol) { + // Note: We can draw without fCanvas/fCanvasHolder since you want offline viewing + std::map hitDataMap; + std::set uniquePlanes; + std::map> activePanelsPerPlane; + if (seedcol != nullptr) { + for (auto const& kseedptr : *seedcol) { + const mu2e::KalSeed& kseed = *kseedptr; + for (auto const& hit : kseed.hits()) { + mu2e::StrawId sid = hit.strawId(); + uniquePlanes.insert(sid.getPlane()); + hitDataMap[sid] = &hit; + activePanelsPerPlane[sid.getPlane()].insert(sid.getPanel()); + } + } + } + mu2e::GeomHandle tracker; + + double strawRadius = tracker->strawProperties()._strawOuterRadius; + std::vector planeIdA = {0,3,4,7,8,11,12,15,16,19,20,23,24,27,28,31,32,35}; + for (const auto& planeId : uniquePlanes) { std::cout << "Processing Canvas for Plane " << planeId << std::endl; std::array padMap; if(std::find(planeIdA.begin(), planeIdA.end(), planeId) != planeIdA.end()) padMap = {2, 3, 6, 5, 4, 1}; else padMap = {5, 4, 1, 2, 3, 6}; - // Fix: Proper TCanvas name and title string formatting TString canvasName = Form("Canvas_Plane_%d", planeId); - TString canvasTitle = Form("Mu2e Tracker Plane %d - Y vs Z View", planeId); - + TString canvasTitle = Form("Plane %d - V vs W View", planeId); + auto cit = fPlaneCanvases.find(planeId); + if (cit != fPlaneCanvases.end()) { + delete cit->second; + fPlaneCanvases.erase(cit); + } TCanvas* planeCanvas = new TCanvas(canvasName, canvasTitle, 1000, 800); + fPlaneCanvases[planeId] = planeCanvas; planeCanvas->Divide(2, 3, 0.005, 0.005); - const mu2e::Plane& plane = tracker->getPlane(planeId); - + std::map panelPads; for (int panelId = 0; panelId < 6; ++panelId) { - const mu2e::Panel& panel = plane.getPanel(panelId); - - // 1. Calculate Bounds for this specific panel - double ymin = 1e9, ymax = -1e9, zmin = 1e9, zmax = -1e9; - for (size_t iStraw = 0; iStraw < panel.nStraws(); ++iStraw) { - const mu2e::Straw& straw = panel.getStraw(iStraw); - CLHEP::Hep3Vector pos_l = straw.getMidPoint(); - ymin = std::min(ymin, pos_l.y()); - ymax = std::max(ymax, pos_l.y()); - zmin = std::min(zmin, pos_l.z()); - zmax = std::max(zmax, pos_l.z()); + const mu2e::Panel& panel = plane.getPanel(panelId); + // 1. Calculate Bounds for this specific panel + /*double ymin = 1e9, ymax = -1e9, zmin = 1e9, zmax = -1e9; + for (size_t iStraw = 0; iStraw < panel.nStraws(); ++iStraw) { + const mu2e::Straw& straw = panel.getStraw(iStraw); + CLHEP::Hep3Vector pos_l = plane.dsToPlane()*straw.getMidPoint(); + ymin = std::min(ymin, pos_l.y()); + ymax = std::max(ymax, pos_l.y()); + zmin = std::min(zmin, pos_l.z()); + zmax = std::max(zmax, pos_l.z()); + }*/ + //std::cout<<"Plane = "<SetStats(0); + frame->Draw(); + // 3. Draw Straws and Hits + for (size_t iStraw = 0; iStraw < panel.nStraws(); ++iStraw) { + const mu2e::Straw& straw = panel.getStraw(iStraw); + CLHEP::Hep3Vector pos_l = panel.dsToPanel()*straw.getMidPoint(); + // Base Straw Geometry + TEllipse *circ = new TEllipse(pos_l.z(), pos_l.y(), strawRadius, strawRadius); + circ->SetLineColor(kGray + 1); + circ->SetFillStyle(0); + circ->Draw(); + // Check for Hits + if (hitDataMap.count(straw.id())) { + const auto* hit = hitDataMap[straw.id()]; + // Hit Outline + TEllipse *hitcirc = new TEllipse(pos_l.z(), pos_l.y(), strawRadius, strawRadius); + hitcirc->SetLineColor(kBlack); + hitcirc->SetLineWidth(2); + hitcirc->SetFillStyle(0); + hitcirc->Draw(); + // Drift Circle + double rdrift = hit->driftRadius(); + TEllipse *rcirc = new TEllipse(pos_l.z(), pos_l.y(), rdrift, rdrift); + mu2e::WireHitState whs = hit->wireHitState(); + if (whs.active() && whs.driftConstraint()) { + rcirc->SetFillColor(kAzure - 9); + rcirc->SetFillStyle(1001); + rcirc->SetLineColor(kBlue); + } else { + rcirc->SetFillStyle(0); + rcirc->SetLineColor(kRed); + rcirc->SetLineStyle(2); // Dashed for inactive/unconstrained + } + rcirc->Draw(); + // Tooltip/Data Graph + double sz = pos_l.z(); + double sy = pos_l.y(); + TGraph *g = new TGraph(1, &sz, &sy); + g->SetMarkerStyle(1); + g->SetMarkerColorAlpha(kWhite, 0); + g->SetName(Form("Straw %d: %.2f MeV", straw.id().getStraw(), hit->energyDep())); + g->Draw("P SAME"); + } + } + } + if(seedcol != nullptr) { + for (auto const& kseedptr : *seedcol) { + const mu2e::KalSeed& kseed = *kseedptr; + if(kseed.loopHelixFit()) { + auto traj = kseed.loopHelixFitTrajectory(); + if (!traj) continue; + drawTrajectory2D(*traj, plane, panelPads, activePanelsPerPlane[planeId]); + } else if(kseed.centralHelixFit()) { + auto traj = kseed.centralHelixFitTrajectory(); + if (!traj) continue; + drawTrajectory2D(*traj, plane, panelPads, activePanelsPerPlane[planeId]); + } else if(kseed.kinematicLineFit()) { + auto traj = kseed.kinematicLineFitTrajectory(); + if (!traj) continue; + drawTrajectory2D(*traj, plane, panelPads, activePanelsPerPlane[planeId]); } + } + } + planeCanvas->Update(); + } +} - // 2. Prepare the Pad - planeCanvas->cd(padMap[panelId]); - gPad->SetBottomMargin(0.15); - gPad->SetLeftMargin(0.15); - - TString frameName = Form("h_plane%d_panel%d", planeId, panelId); - TString frameTitle = Form("Plane %d: Panel %d;Z (mm);Y (mm)", planeId, panelId); - - TH2F* frame = new TH2F(frameName, frameTitle, 100, zmin - 20, zmax + 20, 100, ymin - 10, ymax + 10); - frame->SetStats(0); - frame->Draw(); - - // 3. Draw Straws and Hits - for (size_t iStraw = 0; iStraw < panel.nStraws(); ++iStraw) { - const mu2e::Straw& straw = panel.getStraw(iStraw); - CLHEP::Hep3Vector pos_l = straw.getMidPoint(); - - // Base Straw Geometry - TEllipse *circ = new TEllipse(pos_l.z(), pos_l.y(), strawRadius, strawRadius); - circ->SetLineColor(kGray + 1); - circ->SetFillStyle(0); - circ->Draw(); - - // Check for Hits - if (hitDataMap.count(straw.id())) { - const auto* hit = hitDataMap[straw.id()]; - - // Hit Outline - TEllipse *hitcirc = new TEllipse(pos_l.z(), pos_l.y(), strawRadius, strawRadius); - hitcirc->SetLineColor(kBlack); - hitcirc->SetLineWidth(2); - hitcirc->SetFillStyle(0); - hitcirc->Draw(); - - // Drift Circle - double rdrift = hit->driftRadius(); - TEllipse *rcirc = new TEllipse(pos_l.z(), pos_l.y(), rdrift, rdrift); - - mu2e::WireHitState whs = hit->wireHitState(); - if (whs.active() && whs.driftConstraint()) { - rcirc->SetFillColor(kAzure - 9); - rcirc->SetFillStyle(1001); - rcirc->SetLineColor(kBlue); - } else { - rcirc->SetFillStyle(0); - rcirc->SetLineColor(kRed); - rcirc->SetLineStyle(2); // Dashed for inactive/unconstrained - } - rcirc->Draw(); - - // Tooltip/Data Graph - double sz = pos_l.z(); - double sy = pos_l.y(); - TGraph *g = new TGraph(1, &sz, &sy); - g->SetMarkerStyle(1); - g->SetMarkerColorAlpha(kWhite, 0); - g->SetName(Form("Straw %d: %.2f MeV", straw.id().getStraw(), hit->energyDep())); - g->Draw("P SAME"); - } - } +void TrackerCalo2DViews::drawTrackerXYView(const mu2e::KalSeedPtrCollection* seedcol) { + mu2e::GeomHandle tracker; + + double rInner = tracker->g4Tracker()->getInnerTrackerEnvelopeParams().innerRadius(); + double rOuter = tracker->g4Tracker()->getInnerTrackerEnvelopeParams().outerRadius(); + + if (!fXYCanvas) + fXYCanvas = new TCanvas("TrackerXY", "Tracker X-Y View", 800, 800); + fXYCanvas->cd(); + fXYCanvas->Clear(); + gPad->SetFixedAspectRatio(); + + double rMax = rOuter * 1.1; + TH2F* frame = new TH2F("TrackerXY_frame", "Tracker X-Y View;X (mm);Y (mm)", + 100, -rMax, rMax, 100, -rMax, rMax); + frame->SetStats(0); + frame->Draw(); + + TEllipse* innerCircle = new TEllipse(0.0, 0.0, rInner, rInner); + innerCircle->SetLineColor(kBlue + 1); + innerCircle->SetLineWidth(2); + innerCircle->SetFillStyle(0); + innerCircle->Draw(); + + TEllipse* outerCircle = new TEllipse(0.0, 0.0, rOuter, rOuter); + outerCircle->SetLineColor(kBlue + 1); + outerCircle->SetLineWidth(2); + outerCircle->SetFillStyle(0); + outerCircle->Draw(); + + if (seedcol == nullptr) { + fXYCanvas->Modified(); + fXYCanvas->Update(); + return; + } + + // Collect unique hit straws across all seeds (last seed wins for duplicate straws) + std::map hitMap; + for (auto const& kseedptr : *seedcol) { + for (auto const& hit : kseedptr->hits()) { + hitMap[hit.strawId()] = &hit; } - // Update the canvas for offline viewing - planeCanvas->Update(); - // Optional: planeCanvas->SaveAs(Form("Plane_%d.png", planeId)); } + + for (auto const& [sid, hit] : hitMap) { + const mu2e::Straw& straw = tracker->getStraw(sid); + const CLHEP::Hep3Vector& mid = straw.getMidPoint(); + const CLHEP::Hep3Vector& dir = straw.getDirection(); + double hlen = straw.halfLength(); + + // Full straw extent projected to XY, drawn in light grey + TLine* strawLine = new TLine( + mid.x() - hlen * dir.x(), mid.y() - hlen * dir.y(), + mid.x() + hlen * dir.x(), mid.y() + hlen * dir.y()); + strawLine->SetLineColor(kGray); + strawLine->SetLineWidth(1); + strawLine->Draw(); + + // Use the fitted POCA position (refPOCA_Upos) — bounded within the straw. + // wireDist() is the raw TDC measurement and can exceed halfLength(). + CLHEP::Hep3Vector hitPos3D = straw.wirePosition(hit->refPOCA_Upos()); + double hx = hitPos3D.x(); + double hy = hitPos3D.y(); + float werr = hit->wireRes(); + + // Longitudinal error bar: ±werr along wire direction, projected to XY + TLine* errBar = new TLine( + hx - werr * dir.x(), hy - werr * dir.y(), + hx + werr * dir.x(), hy + werr * dir.y()); + errBar->SetLineColor(kBlack); + errBar->SetLineWidth(2); + errBar->Draw(); + + // Hit marker as TGraph so ROOT shows the title in the status bar on hover + double hx_d = hx, hy_d = hy; + TGraph* hitPoint = new TGraph(1, &hx_d, &hy_d); + hitPoint->SetMarkerStyle(20); + hitPoint->SetMarkerSize(0.5); + hitPoint->SetMarkerColor(kRed); + hitPoint->SetName(Form("hit_%d_%d_%d", sid.getPlane(), sid.getPanel(), sid.getStraw())); + hitPoint->SetTitle(Form("Plane %d Panel %d Straw %d rdrift=%.3f mm", + sid.getPlane(), sid.getPanel(), sid.getStraw(), + hit->driftRadius())); + hitPoint->Draw("P SAME"); + } + + // Draw track trajectory in XY for each seed + for (auto const& kseedptr : *seedcol) { + const mu2e::KalSeed& kseed = *kseedptr; + if (kseed.loopHelixFit()) { + auto traj = kseed.loopHelixFitTrajectory(); + if (!traj) continue; + drawTrajectoryXY(*traj); + } else if (kseed.centralHelixFit()) { + auto traj = kseed.centralHelixFitTrajectory(); + if (!traj) continue; + drawTrajectoryXY(*traj); + } else if (kseed.kinematicLineFit()) { + auto traj = kseed.kinematicLineFitTrajectory(); + if (!traj) continue; + drawTrajectoryXY(*traj); + } + } + + fXYCanvas->Modified(); + fXYCanvas->Update(); +} + +void TrackerCalo2DViews::drawCalorimeterDisk() { + mu2e::GeomHandle calo; + const mu2e::Disk& disk = calo->disk(0); + + if (!fCaloCanvas) + fCaloCanvas = new TCanvas("calo_disk", "Calorimeter Disk 0", 1200, 1200); + fCaloCanvas->cd(); + fCaloCanvas->Clear(); + gPad->SetFixedAspectRatio(); + + // Compute crystal bounds to set frame range + double xmin = 1e9, xmax = -1e9; + double ymin = 1e9, ymax = -1e9; + for (size_t icr = 0; icr < disk.nCrystals(); ++icr) { + const mu2e::Crystal& crystal = disk.crystal(icr); + CLHEP::Hep3Vector pos = crystal.localPosition(); + CLHEP::Hep3Vector size = crystal.size(); + double dx = size.x() / 2.0; + double dy = size.y() / 2.0; + xmin = std::min(xmin, pos.x() - dx); + xmax = std::max(xmax, pos.x() + dx); + ymin = std::min(ymin, pos.y() - dy); + ymax = std::max(ymax, pos.y() + dy); + } + double margin = 20.0; + TH2F* frame = new TH2F("calo_disk_frame", "Calorimeter Disk 0;X (mm);Y (mm)", + 100, xmin - margin, xmax + margin, + 100, ymin - margin, ymax + margin); + frame->SetDirectory(0); + frame->SetStats(0); + frame->Draw(); + + for (size_t icr = 0; icr < disk.nCrystals(); ++icr) { + const mu2e::Crystal& crystal = disk.crystal(icr); + CLHEP::Hep3Vector pos = crystal.localPosition(); + CLHEP::Hep3Vector size = crystal.size(); + double x = pos.x(); + double y = pos.y(); + double dx = size.x() / 2.0; + double dy = size.y() / 2.0; + TBox* box = new TBox(x - dx, y - dy, x + dx, y + dy); + box->SetFillStyle(0); + box->SetLineColor(kBlue + 1); + box->SetLineWidth(1); + box->Draw(); + } + + fCaloCanvas->Modified(); + fCaloCanvas->Update(); } - -void TrackerCalo2DViews::redrawCanvas(const mu2e::KalSeedPtrCollection* seedcol) { - //if (!fCanvas || !fCanvasHolder) return; + + /*void TrackerCalo2DViews::redrawCanvas(const mu2e::KalSeedPtrCollection* seedcol) { + if (!fCanvas || !fCanvasHolder) return; drawTrackerStation(seedcol); - /* fCanvas->Modified(); + fCanvas->Modified(); fCanvas->Update(); TString json = TBufferJSON::ToJSON(fCanvas); fCanvasHolder->SetTitle(TBase64::Encode(json).Data()); - fCanvasHolder->StampObjProps();*/ -} + fCanvasHolder->StampObjProps(); + }*/ } // namespace mu2e