8#include <TPolyLine3D.h>
9#include <TPolyMarker3D.h>
14#include <TVirtualViewer3D.h>
22 m_driftLines.reserve(1000);
23 m_tracks.reserve(100);
40 m_markerSizeCluster = size;
42 std::cerr <<
m_className <<
"::SetClusterMarkerSize: Size must be > 0.\n";
48 m_markerSizeCollision = size;
50 std::cerr <<
m_className <<
"::SetCollisionMarkerSize: Size must be > 0.\n";
55 std::vector<std::array<float, 3> >& driftLine,
56 bool& electron)
const {
58 if (i >= m_driftLines.size())
return;
59 std::copy(m_driftLines[i].first.begin(), m_driftLines[i].first.end(),
60 std::back_inserter(driftLine));
69 const float x0,
const float y0,
const float z0) {
70 std::lock_guard<std::mutex> guard(m_mutex);
72 std::array<float, 3> p = {x0, y0, z0};
73 constexpr size_t minSize = 1;
74 std::vector<std::array<float, 3> > dl(std::max(minSize, np), p);
75 m_driftLines.push_back(std::make_pair(std::move(dl), particle));
77 return m_driftLines.size() - 1;
81 const float x1,
const float y1,
const float z1) {
82 std::lock_guard<std::mutex> guard(m_mutex);
83 std::array<float, 3> p0 = {x0, y0, z0};
84 std::array<float, 3> p1 = {x1, y1, z1};
85 m_photons.push_back({p0, p1});
89 const float x0,
const float y0,
91 std::lock_guard<std::mutex> guard(m_mutex);
93 constexpr size_t minSize = 1;
94 std::vector<std::array<float, 3> > track(std::max(minSize, np));
95 track[0] = {x0, y0, z0};
96 m_tracks.push_back(std::move(track));
98 id = m_tracks.size() - 1;
102 const float x,
const float y,
104 std::lock_guard<std::mutex> guard(m_mutex);
105 if (iL >= m_driftLines.size() || iP >= m_driftLines[iL].first.size()) {
106 std::cerr <<
m_className <<
"::SetDriftLinePoint: Index out of range.\n";
109 m_driftLines[iL].first[iP] = {x, y, z};
113 const float y,
const float z) {
114 std::lock_guard<std::mutex> guard(m_mutex);
115 if (iL >= m_driftLines.size()) {
116 std::cerr <<
m_className <<
"::AddDriftLinePoint: Index out of range.\n";
119 std::array<float, 3> p = {x, y, z};
120 m_driftLines[iL].first.push_back(std::move(p));
124 const float x,
const float y,
const float z) {
125 std::lock_guard<std::mutex> guard(m_mutex);
126 if (iL >= m_tracks.size() || iP >= m_tracks[iL].size()) {
127 std::cerr <<
m_className <<
"::SetTrackPoint: Index out of range.\n";
130 m_tracks[iL][iP] = {x, y, z};
134 const float y,
const float z) {
135 std::lock_guard<std::mutex> guard(m_mutex);
136 if (iL >= m_tracks.size()) {
137 std::cerr <<
m_className <<
"::AddTrackPoint: Index out of range.\n";
140 std::array<float, 3> p = {x, y, z};
141 m_tracks[iL].push_back(std::move(p));
145 std::lock_guard<std::mutex> guard(m_mutex);
146 std::array<float, 3> p = {x, y, z};
147 m_exc.push_back(std::move(p));
151 std::lock_guard<std::mutex> guard(m_mutex);
152 std::array<float, 3> p = {x, y, z};
153 m_ion.push_back(std::move(p));
157 std::lock_guard<std::mutex> guard(m_mutex);
158 std::array<float, 3> p = {x, y, z};
159 m_att.push_back(std::move(p));
166 Plot3d(axis,
false, snapshot);
173 pad->SetTitle(
"Drift lines");
175 const bool rangeSet =
RangeSet(pad);
176 if (axis || !rangeSet) {
178 if (!SetPlotLimits2d()) {
180 <<
" Could not determine the plot limits.\n";
187 frame->GetXaxis()->SetTitle(
LabelX().c_str());
188 frame->GetYaxis()->SetTitle(
LabelY().c_str());
189 }
else if (!rangeSet) {
193 std::vector<std::array<float, 3> > electrons;
194 std::vector<std::array<float, 3> > holes;
195 std::vector<std::array<float, 3> > ions;
196 for (
const auto& driftLine : m_driftLines) {
198 electrons.push_back(driftLine.first.back());
200 holes.push_back(driftLine.first.back());
202 ions.push_back(driftLine.first.back());
205 DrawMarkers2d(electrons, m_colElectron, m_markerSizeCollision);
206 DrawMarkers2d(holes, m_colHole, m_markerSizeCollision);
207 DrawMarkers2d(ions, m_colIon, m_markerSizeCollision);
209 for (
const auto& driftLine : m_driftLines) {
212 DrawLine(driftLine.first, m_colElectron, lw);
214 DrawLine(driftLine.first, m_colHole, lw);
216 DrawLine(driftLine.first, m_colIon, lw);
222 for (
const auto& track : m_tracks) {
224 if (!m_drawClusters)
continue;
225 DrawMarkers2d(track, m_colTrack, m_markerSizeCluster);
229 gr.SetLineColor(m_colPhoton);
231 for (
const auto& photon : m_photons) {
232 float xp0 = 0., yp0 = 0.;
233 float xp1 = 0., yp1 = 0.;
234 ToPlane(photon[0][0], photon[0][1], photon[0][2], xp0, yp0);
235 ToPlane(photon[1][0], photon[1][1], photon[1][2], xp1, yp1);
236 std::vector<float> xgr = {xp0, xp1};
237 std::vector<float> ygr = {yp0, yp1};
238 gr.DrawGraph(2, xgr.data(), ygr.data(),
"Lsame");
241 if (!m_exc.empty()) {
242 DrawMarkers2d(m_exc, m_colExcitation, m_markerSizeCollision);
244 if (!m_ion.empty()) {
245 DrawMarkers2d(m_ion, m_colIonisation, m_markerSizeCollision);
247 if (!m_att.empty()) {
248 DrawMarkers2d(m_att, m_colAttachment, m_markerSizeCollision);
254void ViewDrift::DrawMarkers2d(
255 const std::vector<std::array<float, 3> >& points,
const short col,
257 if (points.empty())
return;
259 gr.SetMarkerColor(col);
260 gr.SetMarkerSize(size);
261 gr.SetMarkerStyle(20);
262 std::vector<float> xgr;
263 std::vector<float> ygr;
264 for (
const auto& p : points) {
265 if (!
InBox(p))
continue;
266 float xp = 0., yp = 0.;
267 ToPlane(p[0], p[1], p[2], xp, yp);
272 gr.DrawGraph(xgr.size(), xgr.data(), ygr.data(),
"Psame");
277 const bool snapshot) {
280 pad->SetTitle(
"Drift lines");
281 if (!pad->GetView()) {
282 if (!SetPlotLimits3d()) {
284 <<
" Could not determine the plot limits.\n";
286 auto view = TView::CreateView(1, 0, 0);
289 if (axis) view->ShowAxis();
291 if (ogl) pad->GetViewer3D(
"ogl");
295 std::vector<std::array<float, 3> > electrons;
296 std::vector<std::array<float, 3> > holes;
297 std::vector<std::array<float, 3> > ions;
298 for (
const auto& driftLine : m_driftLines) {
300 electrons.push_back(driftLine.first.back());
302 holes.push_back(driftLine.first.back());
304 ions.push_back(driftLine.first.back());
307 DrawMarkers3d(electrons, m_colElectron, m_markerSizeCollision);
308 DrawMarkers3d(holes, m_colHole, m_markerSizeCollision);
309 DrawMarkers3d(ions, m_colIon, m_markerSizeCollision);
311 for (
const auto& driftLine : m_driftLines) {
312 std::vector<float> points;
313 for (
const auto& p : driftLine.first) {
314 points.push_back(p[0]);
315 points.push_back(p[1]);
316 points.push_back(p[2]);
318 const int nP = driftLine.first.size();
319 TPolyLine3D pl(nP, points.data());
321 pl.SetLineColor(m_colElectron);
323 pl.SetLineColor(m_colHole);
325 pl.SetLineColor(m_colIon);
328 pl.DrawPolyLine(nP, points.data(),
"same");
331 for (
const auto& track : m_tracks) {
332 std::vector<float> points;
333 for (
const auto& p : track) {
334 points.push_back(p[0]);
335 points.push_back(p[1]);
336 points.push_back(p[2]);
338 const int nP = track.size();
339 TPolyLine3D pl(nP, points.data());
340 pl.SetLineColor(m_colTrack);
342 pl.DrawPolyLine(nP, points.data(),
"same");
343 if (m_drawClusters) {
344 DrawMarkers3d(track, m_colTrack, m_markerSizeCluster);
348 if (!m_exc.empty()) {
349 DrawMarkers3d(m_exc, m_colExcitation, m_markerSizeCollision);
351 if (!m_ion.empty()) {
352 DrawMarkers3d(m_ion, m_colIonisation, m_markerSizeCollision);
354 if (!m_att.empty()) {
355 DrawMarkers3d(m_att, m_colAttachment, m_markerSizeCollision);
361 TAxis3D* ax3d = TAxis3D::GetPadAxis();
363 ax3d->SetLabelColor(kGray + 2);
364 ax3d->SetAxisColor(kGray + 2);
365 ax3d->SetXTitle(
"x");
366 ax3d->SetYTitle(
"y");
367 ax3d->SetZTitle(
"z");
373void ViewDrift::DrawMarkers3d(
374 const std::vector<std::array<float, 3> >& points,
const short col,
377 const size_t nP = points.size();
378 std::vector<float> xyz;
379 for (
size_t i = 0; i < nP; ++i) {
380 xyz.push_back(points[i][0]);
381 xyz.push_back(points[i][1]);
382 xyz.push_back(points[i][2]);
384 TPolyMarker3D pm(nP, xyz.data());
385 pm.SetMarkerColor(col);
386 pm.SetMarkerSize(size);
387 pm.DrawPolyMarker(nP, xyz.data(), 20,
"same");
390bool ViewDrift::SetPlotLimits2d() {
393 double xmin = 0., ymin = 0., xmax = 0., ymax = 0.;
405 std::array<double, 3> bbmin;
406 std::array<double, 3> bbmax;
407 bbmin.fill(std::numeric_limits<double>::max());
408 bbmax.fill(-std::numeric_limits<double>::max());
409 for (
const auto& driftLine : m_driftLines) {
410 for (
const auto& p : driftLine.first) {
411 for (
unsigned int i = 0; i < 3; ++i) {
412 bbmin[i] = std::min(bbmin[i],
double(p[i]));
413 bbmax[i] = std::max(bbmax[i],
double(p[i]));
417 for (
const auto& track : m_tracks) {
418 for (
const auto& p : track) {
419 for (
unsigned int i = 0; i < 3; ++i) {
420 bbmin[i] = std::min(bbmin[i],
double(p[i]));
421 bbmax[i] = std::max(bbmax[i],
double(p[i]));
429bool ViewDrift::SetPlotLimits3d() {
432 if (m_driftLines.empty() && m_tracks.empty())
return false;
434 std::array<double, 3> bbmin;
435 std::array<double, 3> bbmax;
436 bbmin.fill(std::numeric_limits<double>::max());
437 bbmax.fill(-std::numeric_limits<double>::max());
438 for (
const auto& driftLine : m_driftLines) {
439 for (
const auto& p : driftLine.first) {
440 for (
unsigned int i = 0; i < 3; ++i) {
441 bbmin[i] = std::min(bbmin[i],
double(p[i]));
442 bbmax[i] = std::max(bbmax[i],
double(p[i]));
446 for (
const auto& track : m_tracks) {
447 for (
const auto& p : track) {
448 for (
unsigned int i = 0; i < 3; ++i) {
449 bbmin[i] = std::min(bbmin[i],
double(p[i]));
450 bbmax[i] = std::max(bbmax[i],
double(p[i]));
455 for (
size_t i = 0; i < 3; ++i) r +=
fabs(bbmax[i] - bbmin[i]);
static void SetRange(TVirtualPad *pad, const double x0, const double y0, const double x1, const double y1)
bool InBox(const std::array< T, 3 > &x) const
void DrawLine(const std::vector< std::array< float, 3 > > &xl, const short col, const short lw)
TPad * GetCanvas()
Retrieve the canvas.
static bool RangeSet(TVirtualPad *)
bool PlotLimits(Sensor *sensor, double &xmin, double &ymin, double &xmax, double &ymax) const
void ToPlane(const T x, const T y, const T z, T &xp, T &yp) const
bool PlotLimitsFromUserBox(double &xmin, double &ymin, double &xmax, double &ymax) const
ViewBase()=delete
Default constructor.
void AddIonisation(const float x, const float y, const float z)
void Plot2d(const bool axis=true, const bool snapshot=false)
Make a 2D plot of the drift lines in the current viewing plane.
void AddDriftLinePoint(const size_t iL, const float x, const float y, const float z)
void AddTrackPoint(const size_t iL, const float x, const float y, const float z)
void NewChargedParticleTrack(const size_t np, size_t &id, const float x0, const float y0, const float z0)
void SetTrackPoint(const size_t iL, const size_t iP, const float x, const float y, const float z)
void Plot(const bool twod=false, const bool axis=true, const bool snapshot=false)
Draw the drift lines.
void SetClusterMarkerSize(const double size)
Set the size of the cluster markers (see TAttMarker).
void SetDriftLinePoint(const size_t iL, const size_t iP, const float x, const float y, const float z)
void Plot3d(const bool axis=true, const bool ogl=true, const bool snapshot=false)
Make a 3D plot of the drift lines.
void AddAttachment(const float x, const float y, const float z)
void GetDriftLine(const size_t i, std::vector< std::array< float, 3 > > &driftLine, bool &electron) const
Retrieve the coordinates of a given drift line.
void Clear()
Delete existing drift lines, tracks and markers.
void AddPhoton(const float x0, const float y0, const float z0, const float x1, const float y1, const float z1)
size_t NewDriftLine(const Particle particle, const size_t np, const float x0, const float y0, const float z0)
void AddExcitation(const float x, const float y, const float z)
void SetCollisionMarkerSize(const double size)
Set the size of the collision markers (see TAttMarker).
DoubleAc fabs(const DoubleAc &f)