Garfield++ 4.0
A toolkit for the detailed simulation of particle detectors based on ionisation measurement in gases and semiconductors
Loading...
Searching...
No Matches
Garfield::ViewIsochrons Class Reference

Draw equal time contour lines. More...

#include <ViewIsochrons.hh>

+ Inheritance diagram for Garfield::ViewIsochrons:

Public Member Functions

 ViewIsochrons ()
 Constructor.
 
 ~ViewIsochrons ()=default
 Destructor.
 
void SetSensor (Sensor *s)
 Set the sensor.
 
void SetComponent (Component *c)
 Set the component.
 
void PlotIsochrons (const double tstep, const std::vector< std::array< double, 3 > > &points, const bool rev=false, const bool colour=false, const bool markers=false, const bool plotDriftLines=true)
 
void DriftElectrons (const bool positive=false)
 
void DriftIons (const bool negative=false)
 Request ion drift lines with positive (default) or negative charge.
 
void EnableSorting (const bool on=true)
 Sort (or not) the points on a contour line (default: sorting is done).
 
void CheckCrossings (const bool on=true)
 
void SetAspectRatioSwitch (const double ar)
 
void SetLoopThreshold (const double thr)
 
void SetConnectionThreshold (const double thr)
 
- Public Member Functions inherited from Garfield::ViewBase
 ViewBase ()=delete
 Default constructor.
 
 ViewBase (const std::string &name)
 Constructor.
 
virtual ~ViewBase ()=default
 Destructor.
 
void SetCanvas (TPad *pad)
 Set the canvas to be painted on.
 
void SetCanvas ()
 Unset an external canvas.
 
TPad * GetCanvas ()
 Retrieve the canvas.
 
void SetArea (const double xmin, const double ymin, const double xmax, const double ymax)
 
virtual void SetArea (const double xmin, const double ymin, const double zmin, const double xmax, const double ymax, const double zmax)
 Set a bounding box (if applicable).
 
void SetArea ()
 
virtual void SetPlane (const double fx, const double fy, const double fz, const double x0, const double y0, const double z0)
 
virtual void SetPlane (const double fx, const double fy, const double fz, const double x0, const double y0, const double z0, const double hx, const double hy, const double hz)
 Set the projection plane specifying a hint for the in-plane x axis.
 
void Rotate (const double angle)
 Rotate the viewing plane (angle in radian).
 
void SetPlaneXY ()
 Set the viewing plane to x-y.
 
void SetPlaneXZ ()
 Set the viewing plane to x-z.
 
void SetPlaneYZ ()
 Set the viewing plane to y-z.
 
void EnableDebugging (const bool on=true)
 Switch on/off debugging output.
 

Additional Inherited Members

- Static Public Member Functions inherited from Garfield::ViewBase
static std::string FindUnusedFunctionName (const std::string &s)
 Find an unused function name.
 
static std::string FindUnusedHistogramName (const std::string &s)
 Find an unused histogram name.
 
static std::string FindUnusedCanvasName (const std::string &s)
 Find an unused canvas name.
 
- Protected Member Functions inherited from Garfield::ViewBase
void UpdateProjectionMatrix ()
 
template<typename T >
void ToPlane (const T x, const T y, const T z, T &xp, T &yp) const
 
template<typename T >
bool InBox (const std::array< T, 3 > &x) const
 
void Clip (const std::array< float, 3 > &x0, const std::array< float, 3 > &x1, std::array< float, 3 > &xc) const
 
void DrawLine (const std::vector< std::array< float, 3 > > &xl, const short col, const short lw)
 
std::string LabelX ()
 
std::string LabelY ()
 
std::string PlaneDescription ()
 
bool PlotLimits (Sensor *sensor, double &xmin, double &ymin, double &xmax, double &ymax) const
 
bool PlotLimits (Component *cmp, double &xmin, double &ymin, double &xmax, double &ymax) const
 
bool PlotLimitsFromUserBox (double &xmin, double &ymin, double &xmax, double &ymax) const
 
bool PlotLimits (std::array< double, 3 > &bbmin, std::array< double, 3 > &bbmax, double &xmin, double &ymin, double &xmax, double &ymax) const
 
bool RangeSet (TPad *)
 
void SetRange (TPad *pad, const double x0, const double y0, const double x1, const double y1)
 
- Protected Attributes inherited from Garfield::ViewBase
std::string m_className = "ViewBase"
 
bool m_debug = false
 
bool m_userPlotLimits = false
 
double m_xMinPlot = -1.
 
double m_xMaxPlot = 1.
 
double m_yMinPlot = -1.
 
double m_yMaxPlot = 1.
 
bool m_userBox = false
 
double m_xMinBox = -1.
 
double m_xMaxBox = 1.
 
double m_yMinBox = -1.
 
double m_yMaxBox = 1.
 
double m_zMinBox = -1.
 
double m_zMaxBox = 1.
 
std::array< std::array< double, 3 >, 3 > m_proj
 
std::array< double, 4 > m_plane {{0, 0, 1, 0}}
 
std::array< std::array< double, 3 >, 3 > m_prmat
 

Detailed Description

Draw equal time contour lines.

Definition at line 13 of file ViewIsochrons.hh.

Constructor & Destructor Documentation

◆ ViewIsochrons()

Garfield::ViewIsochrons::ViewIsochrons ( )

Constructor.

Definition at line 135 of file ViewIsochrons.cc.

135: ViewBase("ViewIsochrons") { }
ViewBase()=delete
Default constructor.

◆ ~ViewIsochrons()

Garfield::ViewIsochrons::~ViewIsochrons ( )
default

Destructor.

Member Function Documentation

◆ CheckCrossings()

void Garfield::ViewIsochrons::CheckCrossings ( const bool  on = true)
inline

Check (or not) that drift-lines do not cross isochrons (default: check is done).

Definition at line 55 of file ViewIsochrons.hh.

55{ m_checkCrossings = on; }

◆ DriftElectrons()

void Garfield::ViewIsochrons::DriftElectrons ( const bool  positive = false)
inline

Request electron drift lines with negative (default) or positive charge.

Definition at line 42 of file ViewIsochrons.hh.

42 {
43 m_particle = Particle::Electron;
44 m_positive = positive;
45 }

◆ DriftIons()

void Garfield::ViewIsochrons::DriftIons ( const bool  negative = false)
inline

Request ion drift lines with positive (default) or negative charge.

Definition at line 47 of file ViewIsochrons.hh.

47 {
48 m_particle = Particle::Ion;
49 m_positive = !negative;
50 }

◆ EnableSorting()

void Garfield::ViewIsochrons::EnableSorting ( const bool  on = true)
inline

Sort (or not) the points on a contour line (default: sorting is done).

Definition at line 52 of file ViewIsochrons.hh.

52{ m_sortContours = on; }

◆ PlotIsochrons()

void Garfield::ViewIsochrons::PlotIsochrons ( const double  tstep,
const std::vector< std::array< double, 3 > > &  points,
const bool  rev = false,
const bool  colour = false,
const bool  markers = false,
const bool  plotDriftLines = true 
)

Draw equal time contour lines.

Parameters
tstepTime interval.
pointsList of starting points.
revIf true, the drift time is measured from the end points of the drift lines.
colourDraw contour lines using colours.
markersDraw markers (as opposed to lines).
plotDriftLinesDraw drift lines together with the isochrons.

Definition at line 186 of file ViewIsochrons.cc.

188 {
189
190 if (!m_sensor && !m_component) {
191 std::cerr << m_className << "::PlotIsochrons:\n"
192 << " Neither sensor nor component are defined.\n";
193 return;
194 }
195 if (tstep <= 0.) {
196 std::cerr << m_className << "::PlotIsochrons: Time step must be > 0.\n";
197 return;
198 }
199 if (points.empty()) {
200 std::cerr << m_className << "::PlotIsochrons:\n"
201 << " No starting points provided.\n";
202 return;
203 }
204 if (!SetPlotLimits()) return;
205 auto canvas = GetCanvas();
206 canvas->cd();
207 canvas->SetTitle("Isochrons");
208 auto frame = canvas->DrawFrame(m_xMinPlot, m_yMinPlot,
210 frame->GetXaxis()->SetTitle(LabelX().c_str());
211 frame->GetYaxis()->SetTitle(LabelY().c_str());
212 canvas->Update();
213
214 //-----------------------------------------------------------------------
215 // DRFEQT - The main routine (DRFEQT) accumulates equal drift time data
216 // DRFEQP which is plotted as a set of contours in the entry DRFEQP.
217 //-----------------------------------------------------------------------
218 std::vector<std::vector<std::array<double, 3> > > driftLines;
219 std::vector<std::array<double, 3> > startPoints;
220 std::vector<std::array<double, 3> > endPoints;
221 std::vector<int> statusCodes;
222 // Accumulate drift lines.
223 ComputeDriftLines(tstep, points, driftLines, startPoints, endPoints,
224 statusCodes, rev);
225 const unsigned int nDriftLines = driftLines.size();
226 if (nDriftLines < 2) {
227 std::cerr << m_className << "::PlotIsochrons: Too few drift lines.\n";
228 return;
229 }
230 // Keep track of the largest number of contours.
231 std::size_t nContours = 0;
232 for (const auto& driftLine : driftLines) {
233 nContours = std::max(nContours, driftLine.size());
234 }
235 if (nContours == 0) {
236 std::cerr << m_className << "::PlotIsochrons: No contour lines.\n";
237 return;
238 }
239
240 std::set<int> allStats;
241 for (const auto stat : statusCodes) allStats.insert(stat);
242
243 // DRFEQP
244 if (m_debug) {
245 std::cout << m_className << "::PlotIsochrons:\n"
246 << " Drawing " << nContours << " contours, "
247 << nDriftLines << " drift lines.\n";
248 std::printf(" Connection threshold: %10.3f\n", m_connectionThreshold);
249 std::printf(" Aspect ratio threshold: %10.3f\n", m_aspectRatio);
250 std::printf(" Loop closing threshold: %10.3f\n", m_loopThreshold);
251 if (m_sortContours) {
252 std::cout << " Sort contours.\n";
253 } else {
254 std::cout << " Do not sort contours.\n";
255 }
256 if (m_checkCrossings) {
257 std::cout << " Check for crossings.\n";
258 } else {
259 std::cout << " Do not check for crossings.\n";
260 }
261 if (markers) {
262 std::cout << " Mark isochron points.\n";
263 } else {
264 std::cout << " Draw isochron lines.\n";
265 }
266 }
267
268 // Loop over the equal time contours.
269 TGraph graph;
270 graph.SetLineColor(kGray + 2);
271 graph.SetMarkerColor(kGray + 2);
272 graph.SetLineStyle(m_lineStyle);
273 graph.SetMarkerStyle(m_markerStyle);
274 const double colRange = double(gStyle->GetNumberOfColors()) / nContours;
275 for (unsigned int ic = 0; ic < nContours; ++ic) {
276 if (colour) {
277 const auto col = gStyle->GetColorPalette(int((ic + 0.99) * colRange));
278 graph.SetLineColor(col);
279 graph.SetMarkerColor(col);
280 }
281 for (int stat : allStats) {
282 std::vector<std::pair<std::array<double, 4>, unsigned int> > contour;
283 // Loop over the drift lines, picking up the points when OK.
284 for (unsigned int k = 0; k < nDriftLines; ++k) {
285 const auto& dl = driftLines[k];
286 // Reject any undesirable combinations.
287 if (statusCodes[k] != stat || ic >= dl.size()) continue;
288 // Add the point to the contour line.
289 std::array<double, 4> point = {dl[ic][0], dl[ic][1], dl[ic][2], 0.};
290 contour.push_back(std::make_pair(point, k));
291 }
292 // Skip the plot of this contour if there are no points.
293 if (contour.empty()) continue;
294 bool circle = false;
295 // If requested, sort the points on the contour line.
296 if (m_sortContours && !markers) SortContour(contour, circle);
297 // Plot this contour.
298 if (markers) {
299 // Simply mark the contours if this was requested.
300 std::vector<double> xp;
301 std::vector<double> yp;
302 std::vector<double> zp;
303 for (const auto& point : contour) {
304 const double x = point.first[0];
305 const double y = point.first[1];
306 const double z = point.first[2];
307 xp.push_back(m_proj[0][0] * x + m_proj[1][0] * y + z * m_plane[0]);
308 yp.push_back(m_proj[0][1] * x + m_proj[1][1] * y + z * m_plane[1]);
309 zp.push_back(m_proj[0][2] * x + m_proj[1][2] * y + z * m_plane[2]);
310 }
311 graph.DrawGraph(xp.size(), xp.data(), yp.data(), "Psame");
312 continue;
313 }
314 // Regular plotting.
315 const double tolx = (m_xMaxPlot - m_xMinPlot) * m_connectionThreshold;
316 const double toly = (m_yMaxPlot - m_yMinPlot) * m_connectionThreshold;
317 // Flag to keep track if the segment is interrupted by a drift line
318 // or if it is too long.
319 bool gap = false;
320 // Coordinates to be plotted.
321 std::vector<double> xp;
322 std::vector<double> yp;
323 std::vector<double> zp;
324 const unsigned int nP = contour.size();
325 for (unsigned int i = 0; i < nP; ++i) {
326 gap = false;
327 const auto x0 = contour[i].first[0];
328 const auto y0 = contour[i].first[1];
329 const auto z0 = contour[i].first[2];
330 xp.push_back(m_proj[0][0] * x0 + m_proj[1][0] * y0 + z0 * m_plane[0]);
331 yp.push_back(m_proj[0][1] * x0 + m_proj[1][1] * y0 + z0 * m_plane[1]);
332 zp.push_back(m_proj[0][2] * x0 + m_proj[1][2] * y0 + z0 * m_plane[2]);
333 if (i == nP - 1) break;
334 const auto x1 = contour[i + 1].first[0];
335 const auto y1 = contour[i + 1].first[1];
336 // Reject contour segments which are long compared with AREA.
337 if (fabs(x1 - x0) > tolx || fabs(y1 - y0) > toly) gap = true;
338 // Get the indices of the drift lines corresponding
339 // to these two points on the contour line.
340 const auto i0 = contour[i].second;
341 const auto i1 = contour[i + 1].second;
342 // Set the BREAK flag if it crosses some stored drift line segment.
343 if (m_checkCrossings && !gap) {
344 for (unsigned int k = 0; k < nDriftLines; ++k) {
345 const auto& dl = driftLines[k];
346 for (unsigned int jc = 0; jc < dl.size(); ++jc) {
347 if ((i0 == k || i1 == k) && (jc == ic || jc + 1 == ic)) {
348 continue;
349 }
350 const auto& p0 = dl[jc];
351 const auto& p1 = jc == dl.size() - 1 ? endPoints[k] : dl[jc + 1];
352 if (Crossing(p0[0], p0[1], p1[0], p1[1], x0, y0, x1, y1)) {
353 gap = true;
354 break;
355 }
356 }
357 if (gap) break;
358 if ((i0 == k || i1 == k) && ic == 0) continue;
359 const auto& p0 = startPoints[k];
360 if (Crossing(p0[0], p0[1], dl[0][0], dl[0][1],
361 x0, y0, x1, y1)) {
362 gap = true;
363 break;
364 }
365 }
366 }
367 // If there has been a break, plot what we have already.
368 if (gap) {
369 if (xp.size() > 1) {
370 // Plot line.
371 graph.DrawGraph(xp.size(), xp.data(), yp.data(), "Lsame");
372 } else {
373 // Plot markers.
374 graph.DrawGraph(xp.size(), xp.data(), yp.data(), "Psame");
375 }
376 xp.clear();
377 yp.clear();
378 zp.clear();
379 }
380 }
381 // Plot the remainder.
382 if (xp.size() > 1) {
383 graph.DrawGraph(xp.size(), xp.data(), yp.data(), "Lsame");
384 } else if (!xp.empty()) {
385 graph.DrawGraph(xp.size(), xp.data(), yp.data(), "Psame");
386 }
387 }
388 }
389
390 gPad->Update();
391 if (!plotDriftLines) return;
392
393 graph.SetLineStyle(1);
394 if (m_particle == Particle::Electron) {
395 graph.SetLineColor(kOrange - 3);
396 } else {
397 graph.SetLineColor(kRed + 1);
398 }
399 for (unsigned int i = 0; i < nDriftLines; ++i) {
400 std::vector<double> xp;
401 std::vector<double> yp;
402 const double x0 = startPoints[i][0];
403 const double y0 = startPoints[i][1];
404 const double z0 = startPoints[i][2];
405 xp.push_back(m_proj[0][0] * x0 + m_proj[1][0] * y0 + z0 * m_plane[0]);
406 yp.push_back(m_proj[0][1] * x0 + m_proj[1][1] * y0 + z0 * m_plane[1]);
407 for (const auto& point : driftLines[i]) {
408 const double x = point[0];
409 const double y = point[1];
410 const double z = point[2];
411 xp.push_back(m_proj[0][0] * x + m_proj[1][0] * y + z * m_plane[0]);
412 yp.push_back(m_proj[0][1] * x + m_proj[1][1] * y + z * m_plane[1]);
413 }
414 const double x1 = endPoints[i][0];
415 const double y1 = endPoints[i][1];
416 const double z1 = endPoints[i][2];
417 xp.push_back(m_proj[0][0] * x1 + m_proj[1][0] * y1 + z1 * m_plane[0]);
418 yp.push_back(m_proj[0][1] * x1 + m_proj[1][1] * y1 + z1 * m_plane[1]);
419 graph.DrawGraph(xp.size(), xp.data(), yp.data(), "Lsame");
420 }
421}
std::array< double, 4 > m_plane
Definition: ViewBase.hh:99
std::string LabelY()
Definition: ViewBase.cc:483
std::string LabelX()
Definition: ViewBase.cc:420
std::string m_className
Definition: ViewBase.hh:78
std::array< std::array< double, 3 >, 3 > m_proj
Definition: ViewBase.hh:96
TPad * GetCanvas()
Retrieve the canvas.
Definition: ViewBase.cc:74
DoubleAc fabs(const DoubleAc &f)
Definition: DoubleAc.h:615

◆ SetAspectRatioSwitch()

void Garfield::ViewIsochrons::SetAspectRatioSwitch ( const double  ar)

Set the aspect ratio above which an isochron is considered linear (as opposed to circular).

Definition at line 157 of file ViewIsochrons.cc.

157 {
158
159 if (ar < 0.) {
160 std::cerr << m_className << "::SetAspectRatioSwitch: Value must be > 0.\n";
161 return;
162 }
163 m_aspectRatio = ar;
164}

◆ SetComponent()

void Garfield::ViewIsochrons::SetComponent ( Component c)

Set the component.

Definition at line 147 of file ViewIsochrons.cc.

147 {
148 if (!c) {
149 std::cerr << m_className << "::SetComponent: Null pointer.\n";
150 return;
151 }
152
153 m_component = c;
154 m_sensor = nullptr;
155}

◆ SetConnectionThreshold()

void Garfield::ViewIsochrons::SetConnectionThreshold ( const double  thr)

Fractional distance over which isochron segments are connected (default: 0.2).

Definition at line 176 of file ViewIsochrons.cc.

176 {
177
178 if (thr < 0. || thr > 1.) {
179 std::cerr << m_className << "::SetConnectionThreshold:\n"
180 << " Value must be between 0 and 1.\n";
181 return;
182 }
183 m_connectionThreshold = thr;
184}

◆ SetLoopThreshold()

void Garfield::ViewIsochrons::SetLoopThreshold ( const double  thr)

Fractional distance between two points for closing a circular isochron (default: 0.2).

Definition at line 166 of file ViewIsochrons.cc.

166 {
167
168 if (thr < 0. || thr > 1.) {
169 std::cerr << m_className << "::SetLoopThreshold:\n"
170 << " Value must be between 0 and 1.\n";
171 return;
172 }
173 m_loopThreshold = thr;
174}

◆ SetSensor()

void Garfield::ViewIsochrons::SetSensor ( Sensor s)

Set the sensor.

Definition at line 137 of file ViewIsochrons.cc.

137 {
138 if (!s) {
139 std::cerr << m_className << "::SetSensor: Null pointer.\n";
140 return;
141 }
142
143 m_sensor = s;
144 m_component = nullptr;
145}

The documentation for this class was generated from the following files: