44constexpr uint32_t kSidecarVersionMin = 1;
45constexpr uint32_t kSidecarVersionMax = 3;
48constexpr double kSidecarV1FallbackTolerance = 1.e-6;
50constexpr uint32_t kFlagInnerWall = 1u << 0;
53constexpr uint32_t kFlatCSGVersion = 1;
54constexpr uint64_t kFlatCSGHalfspaceBytes = 100;
55constexpr uint64_t kFlatCSGCellBytes = 64;
72bool parseBSplineEdge(
const std::vector<double>&
params, O2BVHSurfaceSolid::PlanarBoundaryCurve& curve)
77 const int degree =
static_cast<int>(std::lround(
params[0]));
78 const int nPoles =
static_cast<int>(std::lround(
params[1]));
79 if (degree < 1 || nPoles < degree + 1) {
82 const size_t nKnots =
static_cast<size_t>(nPoles) + degree + 1;
83 const size_t expected = 2 + 2 *
static_cast<size_t>(nPoles) +
static_cast<size_t>(nPoles) + nKnots;
87 std::vector<O2BVHSurfaceSolid::Point2D> poles(nPoles);
89 for (
int i = 0;
i < nPoles; ++
i) {
93 std::vector<double>
weights(nPoles);
94 for (
int i = 0;
i < nPoles; ++
i) {
97 std::vector<double> knots(nKnots);
98 for (
size_t i = 0;
i < nKnots; ++
i) {
118bool readValue(std::ifstream& in, T&
value)
120 in.read(
reinterpret_cast<char*
>(&
value),
sizeof(
value));
121 return static_cast<bool>(in);
126void writeValue(std::ofstream& out,
const T&
value)
128 out.write(
reinterpret_cast<const char*
>(&
value),
sizeof(
value));
132uint64_t bytesRemaining(std::ifstream& in, std::streamoff fileSize)
137 const std::streamoff here = in.tellg();
138 return here < 0 || here > fileSize ? 0 :
static_cast<uint64_t>(fileSize - here);
141bool readDoubles(std::ifstream& in, std::vector<double>&
values,
uint32_t n, std::streamoff fileSize)
143 if (
static_cast<uint64_t>(
n) *
sizeof(
double) > bytesRemaining(in, fileSize)) {
147 in.read(
reinterpret_cast<char*
>(
values.data()),
static_cast<std::streamsize
>(
n) *
sizeof(
double));
148 return static_cast<bool>(in);
158 O2BVHSurfaceSolid::PlanarBoundaryCurve& bspline)
160 if (edge.curveType == kLineSegment && edge.params.size() >= 4) {
161 start = {edge.params[0], edge.params[1]};
162 end = {edge.params[2], edge.params[3]};
165 if (edge.curveType == kCircularArc && edge.params.size() >= 5) {
166 const double cu = edge.params[0], cv = edge.params[1],
r = edge.params[2];
167 const double a0 = edge.params[3], a1 = edge.params[3] + edge.params[4];
168 start = {cu +
r * std::cos(a0), cv +
r * std::sin(a0)};
169 end = {cu +
r * std::cos(a1), cv +
r * std::sin(a1)};
172 if (edge.curveType == kBSpline2D) {
173 if (!parseBSplineEdge(edge.params, bspline)) {
178 std::vector<surface::Vec2> poles;
179 poles.reserve(bspline.poles.size());
180 for (
const auto& pole : bspline.poles) {
181 poles.push_back({pole[0], pole[1]});
183 const surface::Curve2D evaluated =
185 const surface::Vec2
first = evaluated.startPoint();
186 const surface::Vec2
last = evaluated.endPoint();
197 const double*
params =
nullptr;
199 static void evaluate(
const void* context,
const surface::Vec2& uv,
double& gUU,
double& gUV,
double& gVV)
201 const auto& record = *
static_cast<const RecordMetric*
>(context);
202 const double* p = record.params;
203 switch (record.surfaceType) {
212 const double slope = (p[10] - p[9]) / (p[12] - p[11]);
231 surface::ParametricMetric metric()
const {
return {&evaluate,
this}; }
236bool wireToCurves(
const std::string&
file,
size_t surfaceIndex,
const SidecarWire& wire,
237 std::vector<O2BVHSurfaceSolid::PlanarBoundaryCurve>& curves,
bool& anyArc,
238 const surface::ParametricMetric& metric,
double joinTolerance,
const char* toleranceOrigin)
240 using Curve = O2BVHSurfaceSolid::PlanarBoundaryCurve;
242 curves.reserve(wire.edges.size());
244 const size_t nEdges = wire.edges.size();
245 std::vector<O2BVHSurfaceSolid::Point2D> starts(nEdges);
246 std::vector<O2BVHSurfaceSolid::Point2D> ends(nEdges);
247 std::vector<Curve> bsplines(nEdges);
248 for (
size_t e = 0;
e < nEdges; ++
e) {
249 if (!edgeEndpoints(wire.edges[
e], starts[
e], ends[
e], bsplines[
e])) {
250 ::Error(
"LoadSurfaceSolid",
"%s: surface %zu: unsupported or malformed wire edge %zu",
file.c_str(),
255 for (
size_t e = 0;
e < nEdges; ++
e) {
256 const auto& edge = wire.edges[
e];
257 const auto&
end = ends[
e];
258 const auto& nextStart = starts[(
e + 1) % nEdges];
259 const double joinGapSq = metric.distanceSq({
end[0],
end[1]}, {nextStart[0], nextStart[1]});
260 if (joinGapSq > joinTolerance * joinTolerance) {
261 ::Error(
"LoadSurfaceSolid",
262 "%s: surface %zu: wire edge %zu end does not join the next edge start (gap %.3g cm, tolerance %.3g cm, "
264 file.c_str(), surfaceIndex,
e, std::sqrt(joinGapSq), joinTolerance, toleranceOrigin);
267 if (edge.curveType == kCircularArc) {
269 curves.push_back(Curve::makeArc({edge.params[0], edge.params[1]}, edge.params[2], edge.params[3],
270 edge.params[3] + edge.params[4]));
271 }
else if (edge.curveType == kBSpline2D) {
273 curves.push_back(std::move(bsplines[
e]));
275 curves.push_back(Curve::makeLine(starts[
e],
end));
286constexpr TrimWording kPlaneWording{
"%s: plane surface %zu has more than one outer wire",
287 "%s: plane surface %zu has no outer wire"};
288constexpr TrimWording kQuadricWording{
"%s: quadric surface %zu has more than one outer trim wire",
289 "%s: quadric surface %zu trim block has no outer wire"};
292bool collectTrim(
const std::string&
file,
size_t surfaceIndex,
const TrimWording& wording,
293 const std::vector<SidecarWire>& wires, std::vector<O2BVHSurfaceSolid::PlanarBoundaryCurve>& outer,
294 std::vector<std::vector<O2BVHSurfaceSolid::PlanarBoundaryCurve>>& inners,
bool& anyArc,
295 const surface::ParametricMetric& metric,
double joinTolerance,
const char* toleranceOrigin)
297 bool haveOuter =
false;
298 for (
const auto& wire : wires) {
299 std::vector<O2BVHSurfaceSolid::PlanarBoundaryCurve> curves;
300 if (!wireToCurves(
file, surfaceIndex, wire, curves, anyArc, metric, joinTolerance, toleranceOrigin)) {
303 if (wire.role == 0) {
305 ::Error(
"LoadSurfaceSolid", wording.moreThanOneOuter,
file.c_str(), surfaceIndex);
308 outer = std::move(curves);
311 inners.push_back(std::move(curves));
315 ::Error(
"LoadSurfaceSolid", wording.noOuter,
file.c_str(), surfaceIndex);
322void reorderEdgeRefsToKernelOrder(
const std::vector<SidecarWire>& wires, std::vector<unsigned int>& edgeIds,
323 std::vector<unsigned char>& edgeFlags)
325 size_t totalEdges = 0;
326 for (
const auto& wire : wires) {
327 totalEdges += wire.edges.size();
329 if (wires.empty() || totalEdges != edgeIds.size()) {
333 std::vector<size_t> kernelOffset(wires.size(), 0);
335 for (
size_t w = 0;
w < wires.size(); ++
w) {
336 if (wires[
w].
role == 0) {
338 running = wires[
w].edges.size();
342 for (
size_t w = 0;
w < wires.size(); ++
w) {
343 if (wires[
w].
role != 0) {
344 kernelOffset[
w] = running;
345 running += wires[
w].edges.size();
349 std::vector<unsigned int> permutedIds(edgeIds.size());
350 std::vector<unsigned char> permutedFlags(edgeFlags.size());
351 size_t sidecarOffset = 0;
352 for (
size_t w = 0;
w < wires.size(); ++
w) {
353 for (
size_t e = 0;
e < wires[
w].edges.size(); ++
e) {
354 permutedIds[kernelOffset[
w] +
e] = edgeIds[sidecarOffset +
e];
355 permutedFlags[kernelOffset[
w] +
e] = edgeFlags[sidecarOffset +
e];
357 sidecarOffset += wires[
w].edges.size();
359 edgeIds.swap(permutedIds);
360 edgeFlags.swap(permutedFlags);
367 std::ifstream in(
file, std::ios::binary);
369 ::Error(
"LoadSurfaceSolid",
"Cannot open surface sidecar file %s",
file.c_str());
373 in.seekg(0, std::ios::end);
374 const std::streamoff fileSize = in.tellg();
375 in.seekg(0, std::ios::beg);
378 in.read(magic,
sizeof(magic));
379 if (!in || std::memcmp(magic,
"O2SS", 4) != 0) {
380 ::Error(
"LoadSurfaceSolid",
"%s is not a surface sidecar file (bad magic)",
file.c_str());
385 if (!readValue(in,
version) || !readValue(in, nSurfaces) || !readValue(in, reserved)) {
386 ::Error(
"LoadSurfaceSolid",
"%s: truncated header",
file.c_str());
389 if (version < kSidecarVersionMin || version > kSidecarVersionMax) {
390 ::Error(
"LoadSurfaceSolid",
"%s: unsupported sidecar version %u (reader supports %u..%u)",
file.c_str(),
version,
391 kSidecarVersionMin, kSidecarVersionMax);
397 double modelTolerance = 0.;
398 if (!readValue(in, modelTolerance)) {
399 ::Error(
"LoadSurfaceSolid",
"%s: truncated version-2 header (no model tolerance)",
file.c_str());
403 if (
version >= 3 && !readValue(in, nModelEdges)) {
404 ::Error(
"LoadSurfaceSolid",
"%s: truncated version-3 header (no edge table size)",
file.c_str());
408 ::Warning(
"LoadSurfaceSolid",
409 "%s is a version-1 sidecar and states no model tolerance; assuming %g cm (the extractor's precision). "
410 "Re-run the converter to record the model's own value.",
411 file.c_str(), kSidecarV1FallbackTolerance);
418 ?
"declared by the model"
419 :
"the extractor-precision fallback";
421 for (
size_t s = 0;
s < nSurfaces; ++
s) {
423 if (!readValue(in,
surfaceType) || !readValue(in,
flags) || !readValue(in, nParams)) {
424 ::Error(
"LoadSurfaceSolid",
"%s: truncated surface record %zu",
file.c_str(),
s);
427 std::vector<double> p;
428 if (!readDoubles(in, p, nParams, fileSize)) {
429 ::Error(
"LoadSurfaceSolid",
"%s: truncated parameters of surface %zu",
file.c_str(),
s);
435 if (!readValue(in, nWires)) {
436 ::Error(
"LoadSurfaceSolid",
"%s: truncated wire count of surface %zu",
file.c_str(),
s);
440 if (
static_cast<uint64_t>(nWires) * 8u > bytesRemaining(in, fileSize)) {
441 ::Error(
"LoadSurfaceSolid",
"%s: surface %zu claims %u wires, more than the file holds",
file.c_str(),
s, nWires);
444 std::vector<SidecarWire> wires(nWires);
445 for (
auto& wire : wires) {
447 if (!readValue(in, wire.role) || !readValue(in, nEdges)) {
448 ::Error(
"LoadSurfaceSolid",
"%s: truncated wire header in surface %zu",
file.c_str(),
s);
451 if (
static_cast<uint64_t>(nEdges) * 8u > bytesRemaining(in, fileSize)) {
452 ::Error(
"LoadSurfaceSolid",
"%s: surface %zu claims %u wire edges, more than the file holds",
file.c_str(),
s,
456 wire.edges.resize(nEdges);
457 for (
auto& edge : wire.edges) {
459 if (!readValue(in, edge.curveType) || !readValue(in, nCurveParams) ||
460 !readDoubles(in, edge.params, nCurveParams, fileSize)) {
461 ::Error(
"LoadSurfaceSolid",
"%s: truncated edge record in surface %zu",
file.c_str(),
s);
468 std::vector<unsigned int> edgeIds;
469 std::vector<unsigned char> edgeFlags;
472 if (!readValue(in, nEdgeRefs)) {
473 ::Error(
"LoadSurfaceSolid",
"%s: truncated edge identity count of surface %zu",
file.c_str(),
s);
476 if (
static_cast<uint64_t>(nEdgeRefs) * 5u > bytesRemaining(in, fileSize)) {
477 ::Error(
"LoadSurfaceSolid",
"%s: surface %zu claims %u edge identities, more than the file holds",
478 file.c_str(),
s, nEdgeRefs);
481 edgeIds.resize(nEdgeRefs);
482 edgeFlags.resize(nEdgeRefs);
486 if (!readValue(in, edgeId) || !readValue(in, edgeFlag)) {
487 ::Error(
"LoadSurfaceSolid",
"%s: truncated edge identity %u of surface %zu",
file.c_str(),
e,
s);
490 if (nModelEdges > 0 && edgeId >= nModelEdges) {
491 ::Error(
"LoadSurfaceSolid",
"%s: surface %zu edge identity %u is %u, outside the model's %u edge(s)",
492 file.c_str(),
s,
e, edgeId, nModelEdges);
496 edgeFlags[
e] = edgeFlag;
500 const bool innerWall = (
flags & kFlagInnerWall) != 0;
501 const RecordMetric recordMetric{
surfaceType, p.data()};
505 const auto addQuadric = [&](
const char*
name,
uint32_t expectedParams,
const auto& addUntrimmed,
506 const auto& addTrimmed) {
507 if (nParams != expectedParams) {
508 ::Error(
"LoadSurfaceSolid",
"%s: %s surface %zu has %u parameters, expected %u",
file.c_str(),
name,
s,
509 nParams, expectedParams);
513 added = addUntrimmed();
516 std::vector<O2BVHSurfaceSolid::PlanarBoundaryCurve> outer;
517 std::vector<std::vector<O2BVHSurfaceSolid::PlanarBoundaryCurve>> inners;
519 if (!collectTrim(
file,
s, kQuadricWording, wires, outer, inners, anyArc, recordMetric.metric(), joinTolerance,
523 added = addTrimmed(outer, inners);
530 ::Error(
"LoadSurfaceSolid",
"%s: plane surface %zu has %u parameters, expected 9",
file.c_str(),
s, nParams);
535 std::vector<O2BVHSurfaceSolid::PlanarBoundaryCurve> outer;
536 std::vector<std::vector<O2BVHSurfaceSolid::PlanarBoundaryCurve>> inners;
538 if (!collectTrim(
file,
s, kPlaneWording, wires, outer, inners, anyArc, recordMetric.metric(), joinTolerance,
545 const auto toPolygon = [](
const std::vector<O2BVHSurfaceSolid::PlanarBoundaryCurve>& curves) {
546 std::vector<O2BVHSurfaceSolid::Point2D> polygon;
547 polygon.reserve(curves.size());
548 for (
const auto&
c : curves) {
549 polygon.push_back(
c.lineStart);
553 std::vector<std::vector<O2BVHSurfaceSolid::Point2D>> innerPolys;
554 innerPolys.reserve(inners.size());
555 for (
const auto& inner : inners) {
556 innerPolys.push_back(toPolygon(inner));
558 added = solid.
AddPlanarSurface(point3(p, 0), point3(p, 3), point3(p, 6), toPolygon(outer), innerPolys);
566 return solid.
AddCylindricalSurface(point3(p, 0), point3(p, 3), point3(p, 6), p[9], p[10], p[11], p[12],
569 [&](
const auto& outer,
const auto& inners) {
570 return solid.
AddCylindricalSurface(point3(p, 0), point3(p, 3), point3(p, 6), p[9], p[10], p[11], p[12],
571 p[13], innerWall, outer, inners);
580 return solid.
AddConicalSurface(point3(p, 0), point3(p, 3), point3(p, 6), p[9], p[10], p[11], p[12],
581 p[13], p[14], innerWall);
583 [&](
const auto& outer,
const auto& inners) {
584 return solid.
AddConicalSurface(point3(p, 0), point3(p, 3), point3(p, 6), p[9], p[10], p[11], p[12],
585 p[13], p[14], innerWall, outer, inners);
594 return solid.
AddSphericalSurface(point3(p, 0), point3(p, 3), point3(p, 6), p[9], p[10], p[11], p[12],
597 [&](
const auto& outer,
const auto& inners) {
598 return solid.
AddSphericalSurface(point3(p, 0), point3(p, 3), point3(p, 6), p[9], p[10], p[11], p[12],
599 p[13], innerWall, outer, inners);
608 return solid.
AddToroidalSurface(point3(p, 0), point3(p, 3), point3(p, 6), p[9], p[10], p[11], p[12],
609 p[13], p[14], innerWall);
611 [&](
const auto& outer,
const auto& inners) {
612 return solid.
AddToroidalSurface(point3(p, 0), point3(p, 3), point3(p, 6), p[9], p[10], p[11], p[12],
613 p[13], p[14], innerWall, outer, inners);
619 ::Error(
"LoadSurfaceSolid",
"%s: surface %zu has unknown surface type %u",
file.c_str(),
s,
surfaceType);
624 ::Error(
"LoadSurfaceSolid",
"%s: surface %zu was rejected by O2BVHSurfaceSolid",
file.c_str(),
s);
627 if (!edgeIds.empty()) {
628 reorderEdgeRefsToKernelOrder(wires, edgeIds, edgeFlags);
638 std::ifstream in(
file, std::ios::binary);
640 ::Error(
"LoadFacetSolid",
"Cannot open facet sidecar file %s",
file.c_str());
644 in.seekg(0, std::ios::end);
645 const std::streamoff fileSize = in.tellg();
646 in.seekg(0, std::ios::beg);
649 if (!readValue(in, nTriangles)) {
650 ::Error(
"LoadFacetSolid",
"%s: truncated header",
file.c_str());
655 const uint64_t recordsBytes =
static_cast<uint64_t>(nTriangles) * 9u *
sizeof(
float);
656 const uint64_t remaining = bytesRemaining(in, fileSize);
657 if (recordsBytes > remaining) {
658 ::Error(
"LoadFacetSolid",
"%s: truncated: %u facet record(s) need %llu byte(s), found %llu",
file.c_str(),
659 nTriangles,
static_cast<unsigned long long>(recordsBytes),
static_cast<unsigned long long>(remaining));
662 std::vector<float>
records(9 *
static_cast<size_t>(nTriangles));
663 in.read(
reinterpret_cast<char*
>(
records.data()),
static_cast<std::streamsize
>(recordsBytes));
665 ::Error(
"LoadFacetSolid",
"%s: truncated facet records",
file.c_str());
671 const float*
v = &
records[9 *
static_cast<size_t>(
i)];
681 if (nDegenerate > 0) {
682 ::Warning(
"LoadFacetSolid",
"%s: skipped %u degenerate facet(s) of %u",
file.c_str(), nDegenerate, nTriangles);
690 std::ifstream in(
file, std::ios::binary);
692 ::Error(
"LoadFlatCSG",
"Cannot open flat-CSG sidecar file %s",
file.c_str());
696 in.seekg(0, std::ios::end);
697 const std::streamoff fileSize = in.tellg();
698 in.seekg(0, std::ios::beg);
701 in.read(magic,
sizeof(magic));
702 if (!in || std::memcmp(magic,
"O2FLTCSG",
sizeof(magic)) != 0) {
703 ::Error(
"LoadFlatCSG",
"%s is not a flat-CSG sidecar file (bad magic)",
file.c_str());
708 if (!readValue(in,
version) || !readValue(in, nHalfspaces) || !readValue(in, nCells)) {
709 ::Error(
"LoadFlatCSG",
"%s: truncated header",
file.c_str());
712 if (
version != kFlatCSGVersion) {
713 ::Error(
"LoadFlatCSG",
"%s: unsupported sidecar version %u (reader supports %u)",
file.c_str(),
version,
720 static_cast<uint64_t>(nHalfspaces) * kFlatCSGHalfspaceBytes +
static_cast<uint64_t>(nCells) * kFlatCSGCellBytes;
721 const uint64_t remaining = bytesRemaining(in, fileSize);
723 ::Error(
"LoadFlatCSG",
724 "%s: file length does not match its header (%u halfspace(s) + %u cell(s) implies %llu more byte(s), "
726 file.c_str(), nHalfspaces, nCells,
static_cast<unsigned long long>(
expected),
727 static_cast<unsigned long long>(remaining));
736 if (!readValue(in,
kind) || !readValue(in, sign)) {
737 ::Error(
"LoadFlatCSG",
"%s: truncated halfspace record %u",
file.c_str(),
h);
742 for (
int i = 0;
i < 11 && ok; ++
i) {
743 ok = readValue(in,
c[
i]);
746 ::Error(
"LoadFlatCSG",
"%s: truncated halfspace record %u",
file.c_str(),
h);
749 bool finite = std::isfinite(sign);
751 finite = finite && std::isfinite(
value);
754 ::Error(
"LoadFlatCSG",
"%s: halfspace %u has a non-finite coefficient",
file.c_str(),
h);
760 const double centre[3] = {
c[0],
c[1],
c[2]};
761 const double axis[3] = {
c[3],
c[4],
c[5]};
762 if (!(axis[0] * axis[0] + axis[1] * axis[1] + axis[2] * axis[2] > 0.)) {
763 ::Error(
"LoadFlatCSG",
"%s: torus halfspace %u has a zero axis",
file.c_str(),
h);
766 solid.
AddTorus(sign, centre, axis,
c[6],
c[7]);
768 ::Error(
"LoadFlatCSG",
"%s: halfspace %u has unknown kind %d",
file.c_str(),
h,
kind);
773 for (
uint32_t cellIdx = 0; cellIdx < nCells; ++cellIdx) {
776 if (!readValue(in,
first) || !readValue(in,
count) || !readValue(in, volume)) {
777 ::Error(
"LoadFlatCSG",
"%s: truncated cell record %u",
file.c_str(), cellIdx);
782 for (
int i = 0;
i < 3 && ok; ++
i) {
783 ok = readValue(in, lo[
i]);
785 for (
int i = 0;
i < 3 && ok; ++
i) {
786 ok = readValue(in, hi[
i]);
789 ::Error(
"LoadFlatCSG",
"%s: truncated cell record %u",
file.c_str(), cellIdx);
793 ::Error(
"LoadFlatCSG",
"%s: cell %u has an invalid range (first=%d, count=%d) into %u halfspace(s)",
798 solid.
SetCellBBox(
static_cast<int>(cellIdx), lo, hi);
808 ::Error(
"WriteFlatCSG",
809 "%s: shape %s is not closed (CloseShape() was never called, or refused); refusing to "
810 "write a sidecar that may encode a degenerate cell box",
811 file.c_str(), solid.GetName());
815 std::ofstream out(
file, std::ios::binary);
817 ::Error(
"WriteFlatCSG",
"Cannot open %s for writing",
file.c_str());
821 out.write(
"O2FLTCSG", 8);
826 writeValue(out, nHalfspaces);
827 writeValue(out, nCells);
833 writeValue(out,
kind);
834 writeValue(out, halfspace.
sign);
835 for (
double value : halfspace.
c) {
836 writeValue(out,
value);
839 for (
uint32_t cellIdx = 0; cellIdx < nCells; ++cellIdx) {
843 writeValue(out,
first);
844 writeValue(out,
count);
845 writeValue(out, cell.
volume);
847 solid.
GetCellBBox(
static_cast<int>(cellIdx), lo, hi);
848 for (
double value : lo) {
849 writeValue(out,
value);
851 for (
double value : hi) {
852 writeValue(out,
value);
857 ::Error(
"WriteFlatCSG",
"%s: write failed",
file.c_str());
std::vector< o2::soa::IndexRecord > records
Private analytic bounded surfaces, trim wires and closure checks behind O2BVHSurfaceSolid.
configStandalone Light OpenGL display display_light Apply smoothing to points Enable Z buffer Highlight links Highlight seeds Highlight sector tracks Highlight final tracks Show individual Show related Highlight grid Show only individual collision Color clusters belonging to track objects Set line Enable drawing TPC data Enable drawing TOF data Enable drawing magnetic field Set field line step count Invert colors configStandalone Heavy OpenGL display display_heavy Show tracks with ITS contribution Show tracks with TOF contribution Enable propagation of loopers Show clusters at nominal x of pad row for early transformed data Split CE tracks when they cross the central Mark clusters Mark adjacent clusters Hide rejected tracks Apply filter on tracks to be displayed Separate increase X h configStandalone Camera window renderer OpenGL display display_camera Orient the camera such that the y axis is always upwards Full Screen MultiSample Anti Downsampling Anti Enable Vertical Sync Target frame or if the backend cannot limit to the refresh Use OpenGL indirect draws to reduce number of draw calls Display h configStandalone Vulkan display display_vulkan Have uniform buffers in host accessible device memory h configStandalone Internal display display_internal Number of updates the Qt GUI may send ahead of the last one the display has before it waits for the display Opacity of the console background Number of console lines the history is shortened to this when it reaches twice the size Time in seconds an info message fades out after setInfoTime h OpenGL display display Font size Do not use Freetype for font Renderer for event Frontend to use for event ROOT macros used as track filter Console script file
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error s
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char Directory with events to Events directory is and not inside events Show standalone event Run event generator maximum time bin of continuous for triggered for automatic continuous for automatic continuous triggered uint64_t
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char e
configStandalone Reconstruction rec_tpc multiplier for the combined cluster track error during track following area in cm for the search of for z only used if decrease removal by when above this local occupancy rowx Shift of TPC revert cluster flag edge bit distance to edge exceeds this ZOffset for secondary multiple of radius max P of electron K BB bands crossing max P of electron p BB bands crossing max P of electron d BB bands crossing max P of electron t BB bands crossing min accepted dEdxMaxTPC of the track Additive extra cluster error for Y2 if edge flag set Additive extra cluster error for Y2 if single set Additive extra cluster error for Y2 if or single set Additive extra cluster error for Z2 if or single set Extra errors to add to track when crossing depending on addErrorsCECrossing Inner portion of y range in sector that is not used in searching for extrapolated track candidates factor2YS for track merging factor2K for track merging Margin in cm of Y position when rejecting edge clusters based on uncorrected track Y Max fraction of shared clusters for tracklet Except pad from cluster finding if total number of charges in a fragment is above this Except pad from cluster finding if number of consecutive charges in a fragment is above this Threshold where a timebin is considered disabling the noisy pad check for that pad Treat signal above this minimum as saturated Smoothing factor for the exponential Highly Ionising Particle tail filter Number of timebins to use for the averaging Add additional custom track errors when crossing relative as fraction of Do N fit passes in final fit of< 0:reject at max -n hits") AddOptionRTC(rejectIFCLowRadiusCluster, uint8_t, 1, "", 0, "Reject clusters that get the IFC mask error during refit") AddOptionRTC(dEdxTruncLow, uint8_t, 2, "", 0, "Low truncation threshold, fraction of 128") AddOptionRTC(dEdxTruncHigh, uint8_t, 77, "", 0, "High truncation threshold, fraction of 128") AddOptionRTC(extrapolationTracking, int8_t, 1, "", 0, "Enable Extrapolation Tracking(prolong tracks to adjacent sectors to find short segments)") AddOptionRTC(disableRefitAttachment, uint8_t, 0, "", 0, "Bitmask to disable certain attachment steps during refit(1:attachment, 2:propagation, 4:loop following, 8:mirroring)") AddOptionRTC(rejectionStrategy, uint8_t, o2::gpu::GPUSettings::RejectionStrategyA, "", 0, "Enable rejection of TPC clusters for compression(0=no, 1=strategy A, 2=strategy B)") AddOptionRTC(mergeLoopersAfterburner, uint8_t, 1, "", 0, "Run afterburner for additional looper merging") AddOptionRTC(compressionTypeMask, uint8_t, o2::gpu::GPUSettings::CompressionFull, "", 0, "TPC Compression mode bits(1=truncate charge/width LSB, 2=differences, 4=track-model)") AddOptionRTC(compressionSortOrder, uint8_t, o2::gpu::GPUSettings::SortTime, "", 0, "Sort order of TPC compression(0=time, 1=pad, 2=Z-time-pad, 3=Z-pad-time, 4=no sorting(use incoming order))") AddOptionRTC(sigBitsCharge, uint8_t, 4, "", 0, "Number of significant bits for TPC cluster charge in compression mode 1") AddOptionRTC(sigBitsWidth, uint8_t, 3, "", 0, "Number of significant bits for TPC cluster width in compression mode 1") AddOptionRTC(dropLoopers, uint8_t, 0, "", 0, "Drop looping tracks starting from second loop") AddOptionRTC(mergerInterpolateErrors, uint8_t, 1, "", 0, "Use interpolation instead of extrapolation for chi2 based cluster rejection") AddOptionRTC(mergerInterpolateRejectAlsoOnCurrentPosition, uint8_t, 1, "", 0, "When using mergerInterpolateErrors, reject based on chi2 twice computed with interpolated and current track position starting from NDF > mergerNonInterpolateRejectMinNDF Merge tracks accross the central electrode Enable PID response Add sub threshold clusters in TPC dEdx computation OR mask of TPC flags that will reject the cluster in alternative dEdx Reject edge clusters based on uncorrected track Y during track fit Increase decrease removal by when on this number of pads from the edge h configStandalone Reconstruction rec_trd Max chi2 for TRD tracklets to be matched to a track Chi2 cut for strict matching mode Number of sigmas for ITS TPC track time error estimate Addition to search road around track prolongation along Y in cm Optimal tracklet rphi resolution in maximum chi2 per attached tracklet for TRD tracks take into account the full likelihood of the slope including exponential tails Tracks with less attached tracklets are discarded after the tracking Post trigger Pile up integration time in BCs fits all iterations but the last one in projections Use material lookup table for TPC refit Apply workarounds to avoid cyclic merge should not be needed tpc dyn configStandalone Processing proc_rtc Replace constant variables static by constexpr expressions Compile RTC in deterministic with NO_FAST_MATH flags and GPUCA_DETERMINISTIC_MODE define Use RTC to optimize GPU code h configStandalone Processing proc_rtctech Use a file lock to serialize access to the cache folder int32_t
constexpr int p1()
constexpr to accelerate the coordinates changing
std::vector< SidecarEdge > edges
const char * moreThanOneOuter
Class for time synchronization of RawReader instances.
bool AddFacet(const Vertex_t &pt0, const Vertex_t &pt1, const Vertex_t &pt2)
Adding a triangular facet from vertex positions in absolute coordinates.
Tessellated::Vertex_t Vertex_t
bool AddCylindricalSurface(const Point3D ¢erPoint, const Point3D &axis, const Point3D &referenceAxisU, double radius, double heightMin, double heightMax, double phiStart=0., double phiSweep=6.283185307179586, bool innerWall=false)
Add a cylindrical wall of radius around axis over a height range and a phi sweep; innerWall points th...
double GetModelTolerance() const
std::array< double, 3 > Point3D
std::array< double, 2 > Point2D
bool AddCurvedPlanarSurface(const Point3D &origin, const Point3D &axisU, const Point3D &axisV, const std::vector< PlanarBoundaryCurve > &outerWire, const std::vector< std::vector< PlanarBoundaryCurve > > &innerWires={})
Add an exact planar surface bounded by line/arc wires; axisU and axisV are orthonormal and axisU x ax...
bool AddConicalSurface(const Point3D ¢erPoint, const Point3D &axis, const Point3D &referenceAxisU, double radiusAtMin, double radiusAtMax, double heightMin, double heightMax, double phiStart=0., double phiSweep=6.283185307179586, bool innerWall=false)
Add a conical wall whose radius runs linearly from radiusAtMin to radiusAtMax; one radius may be zero...
void SetModelTolerance(double toleranceCm)
bool SetSurfaceBoundaryEdges(int surfaceIndex, const std::vector< unsigned int > &edgeIds, const std::vector< unsigned char > &edgeFlags)
Attach surface surfaceIndex's edge identities in trim-curve order; false on a bad index or mismatched...
bool AddSphericalSurface(const Point3D ¢er, const Point3D &polarAxis, const Point3D &referenceAxisU, double radius, double thetaMin=0., double thetaMax=3.141592653589793, double phiStart=0., double phiSweep=6.283185307179586, bool innerWall=false)
Add a spherical surface of radius trimmed to a theta range and a phi sweep; the defaults give a full ...
bool AddToroidalSurface(const Point3D ¢erPoint, const Point3D &axis, const Point3D &referenceAxisU, double majorRadius, double minorRadius, double phiStart=0., double phiSweep=6.283185307179586, double tubeStart=0., double tubeSweep=6.283185307179586, bool innerWall=false)
Add a toroidal surface trimmed to a phiRing x phiTube rectangle; the defaults give a full torus,...
bool AddPlanarSurface(const Point3D &origin, const Point3D &axisU, const Point3D &axisV, const std::vector< Point2D > &outerWire, const std::vector< std::vector< Point2D > > &innerWires={})
int AddCell(int first, int count, double volume)
Append a cell over [first, first + count) of the halfspace array; returns its index.
int AddQuadric(double sign, const double coeff[10])
Append a quadric halfspace; returns its index. sign is +1 or -1, inside is sign*Q <= 0.
int GetNhalfspaces() const
const FlatCSGCell & GetCell(int index) const
int AddTorus(double sign, const double *centre, const double *axis, double major, double minor)
Append a torus halfspace, inside sign * (sqrt((rho - major)^2 + z^2) - minor) <= 0 about unit axis; r...
void GetCellBBox(int cell, double *lo, double *hi) const
const FlatCSGHalfspace & GetHalfspace(int index) const
void SetCellBBox(int cell, const double *lo, const double *hi)
GLsizei const GLuint const GLfloat * weights
GLuint const GLchar * name
GLsizei const GLfloat * value
GLenum const GLfloat * params
GLenum GLsizei GLsizei GLint * values
GLubyte GLubyte GLubyte GLubyte w
constexpr double wireJoinToleranceFor(double modelTolerance)
The wire-join band for a model with a declared tolerance: that tolerance when looser than kWireJoinTo...
void coneParametricMetric(double radiusAtHeight, double slope, double &gUU, double &gUV, double &gVV)
void planeParametricMetric(const Vec3 &axisU, const Vec3 &axisV, double &gUU, double &gUV, double &gVV)
constexpr double kWireJoinTolerance
Wire-closure tolerance, a 3D length in cm through the surface metric: the CAD extractor's endpoint pr...
void torusParametricMetric(double majorRadius, double minorRadius, double phiTube, double &gUU, double &gUV, double &gVV)
Torus, (u, v) = (phiRing[rad], phiTube[rad]). The ring scale runs from R - r to R + r.
void cylinderParametricMetric(double radius, double &gUU, double &gUV, double &gVV)
Cylinder, (u, v) = (phi[rad], h[cm]).
void sphereParametricMetric(double radius, double theta, double &gUU, double &gUV, double &gVV)
bool LoadFlatCSG(const std::string &file, O2FlatCSG &solid)
Load a flat-CSG sidecar (flatcsg_*.bin, version 1) into solid; call CloseShape() after....
bool LoadFacetSolid(const std::string &file, o2::base::O2Tessellated &solid)
bool WriteFlatCSG(const std::string &file, const O2FlatCSG &solid)
bool LoadSurfaceSolid(const std::string &file, O2BVHSurfaceSolid &solid)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
One DNF cell: [first, first + count) of the halfspace array, intersected; volume is its own volume.
static PlanarBoundaryCurve makeBSpline(int splineDegree, std::vector< Point2D > splinePoles, std::vector< double > splineWeights, std::vector< double > splineKnots)
static Curve2D makeBSpline(int splineDegree, std::vector< Vec2 > splinePoles, std::vector< double > splineWeights, std::vector< double > splineKnots)
std::map< std::string, ID > expected