11 Performs simple checks on ICARUS geometry.
13 __version__ =
"%(prog)s 2.1"
23 def next(self):
raise StopIteration
36 except StopIteration:
pass
46 return " - ".
join(map(
lambda obj: str(obj.ID()), pair))
48 def BoxToString(box):
return "%s -- %s" % (box.Min(), box.Max())
54 except AttributeError:
return default
60 """Returns a list of pairs of overlapping objects (empty if no overlap)."""
61 if objName
is None: objName = objs.__class__.__name__
63 for (iObj1, obj1), (iObj2, obj2)
in itertools.combinations(
enumerate(objs), 2):
64 box1 = obj1
if extractBox
is None else extractBox(obj1)
65 box2 = obj2
if extractBox
is None else extractBox(obj2)
66 if not box2.Overlaps(box1):
continue
67 logging.error(
"%s %s (%s to %s) and %s (%s to %s) overlap!", objName,
68 boxID(box1, iObj1), box1.Min(), box1.Max(),
69 boxID(box2, iObj2), box2.Min(), box2.Max(),
71 overlaps.append( ( obj1, obj2, ) )
79 """Check alignment in y and z position of planes on the same x.
81 Returns triples (distance, first plane, second plane) for each misaligned
84 assert tolerance >= 0.0
86 inconsistentPlanes = {}
87 for planesOnX
in PlanesByX:
88 if len(planesOnX) < 2:
continue
89 planeIter = iter(planesOnX)
90 refPlane = next(planeIter)
91 for nextPlane
in planeIter:
92 refBox = refPlane.BoundingBox()
93 nextBox = nextPlane.BoundingBox()
97 distance = nextBox.MinZ() - refBox.MaxZ()
98 if abs(distance) > tolerance:
100 "Planes on x=%s are misaligned along z: ( %g -- %g ) (%s) vs. ( %g -- %g ) (%s)",
101 refPlane.GetCenter().
X(), refBox.MinZ(), refBox.MaxZ(), refPlane.ID(),
102 nextBox.MinZ(), nextBox.MaxZ(), nextPlane.ID(),
104 inconsistentPlanes.setdefault(
'zalign', []) \
105 .append( ( distance, refPlane, nextPlane, ) )
111 topDistance = nextBox.MaxY() - refBox.MaxY()
112 if abs(topDistance) > tolerance:
114 "Planes on x=%s are misaligned along y: ( %g -- %g ) (%s) vs. ( %g -- %g ) (%s)",
115 refPlane.GetCenter().
X(), refBox.MinY(), refBox.MaxY(), refPlane.ID(),
116 nextBox.MinY(), nextBox.MaxY(), nextPlane.ID(),
118 inconsistentPlanes.setdefault(
'topYalign', []) \
119 .append( ( topDistance, refPlane, nextPlane, ) )
121 bottomDistance = nextBox.MinY() - refBox.MinY()
122 if abs(bottomDistance) > tolerance:
123 inconsistentPlanes.setdefault(
'bottomYalign', []) \
124 .append( ( bottomDistance, refPlane, nextPlane, ) )
126 if 'topYalign' in inconsistentPlanes
or 'bottomYalign' in inconsistentPlanes:
128 "Planes on x=%s are misaligned along y: ( %g -- %g ) (%s) vs. ( %g -- %g ) (%s)",
129 refPlane.GetCenter().
X(), refBox.MinY(), refBox.MaxY(), refPlane.ID(),
130 nextBox.MinY(), nextBox.MaxY(), nextPlane.ID(),
137 if refPlane.View() != nextPlane.View():
138 logging.error(
"Plane %s is on view '%s', %s is on view '%s'.",
139 refPlane.ID(), ROOT.geo.PlaneGeo.ViewName(refPlane.View()),
140 nextPlane.ID(), ROOT.geo.PlaneGeo.ViewName(nextPlane.View()),
142 inconsistentPlanes.setdefault(
'view', []) \
143 .append( ( refPlane, nextPlane, ) )
149 if 1.0 - refPlane.GetIncreasingWireDirection().Dot(nextPlane.GetIncreasingWireDirection()) > tolerance:
150 logging.error(
"Plane %s measures direction %s, %s measures %s.",
151 refPlane.ID(), refPlane.GetIncreasingWireDirection(),
152 nextPlane.ID(), nextPlane.GetIncreasingWireDirection(),
154 inconsistentPlanes.setdefault(
'direction', []) \
155 .append( ( refPlane, nextPlane, ) )
165 min(wire.GetStart().Y(), wire.GetEnd().Y())
166 for wire
in refPlane.IterateWires()
169 max(wire.GetStart().Y(), wire.GetEnd().Y())
170 for wire
in refPlane.IterateWires()
173 max(wire.GetStart().Z(), wire.GetEnd().Z())
174 for wire
in refPlane.IterateWires()
177 min(wire.GetStart().Y(), wire.GetEnd().Y())
178 for wire
in nextPlane.IterateWires()
181 max(wire.GetStart().Y(), wire.GetEnd().Y())
182 for wire
in nextPlane.IterateWires()
185 min(wire.GetStart().Z(), wire.GetEnd().Z())
186 for wire
in nextPlane.IterateWires()
189 if abs(nextWireMinZ - refWireMaxZ) > tolerance:
191 "Wires of planes on x=%s are misaligned along z: %s ends at %g cm, %s restarts at %g cm",
192 refPlane.GetCenter().
X(), refPlane.ID(), refWireMaxZ, nextPlane.ID(), nextWireMinZ,
194 inconsistentPlanes.setdefault(
'wireZalign', []) \
195 .append( ( nextWireMinZ - refWireMaxZ, refPlane, nextPlane, ) )
198 if abs(nextWireMaxY - refWireMaxY) > tolerance:
200 "Wires of planes on x=%s are misaligned along y: %s tops at %g cm, %s at %g cm",
201 refPlane.GetCenter().
X(), refPlane.ID(), refWireMaxY, nextPlane.ID(), nextWireMaxY,
203 inconsistentPlanes.setdefault(
'wireTopYalign', []) \
204 .append( ( nextWireMaxY - refWireMaxY, refPlane, nextPlane, ) )
207 if abs(nextWireMinY - refWireMinY) > tolerance:
209 "Wires of planes on x=%s are misaligned along y: %s floors at %g cm, %s at %g cm",
210 refPlane.GetCenter().
X(), refPlane.ID(), refWireMinY, nextPlane.ID(), nextWireMinY,
212 inconsistentPlanes.setdefault(
'wireBottomYalign', []) \
213 .append( ( nextWireMinY - refWireMinY, refPlane, nextPlane, ) )
220 return inconsistentPlanes
226 """Returns the borders touched by the specified wire end."""
231 for side
in (
'top',
'bottom', ):
232 if abs(end.Y() - borderCoords[side]) <= tolerance: borders.add(side)
233 assert (
'top' not in borders)
or (
'bottom' not in borders)
235 for side
in (
'upstream',
'downstream', ):
236 if abs(end.Z() - borderCoords[side]) <= tolerance: borders.add(side)
237 assert (
'upstream' not in borders)
or (
'downstream' not in borders)
246 """Wires which do not end on any border of the plane are returned.
248 The border is determined by the wires themselves rather than the plane box,
249 which could in principle extend further (but not less).
251 A dictionary is returned with key the ID of the wire not ending on a border,
252 and a list of end labels ('start', 'end') listing which end did not.
255 assert tolerance >= 0.0
262 min(wire.GetStart().Y(), wire.GetEnd().Y())
263 for wire
in plane.IterateWires()
266 max(wire.GetStart().Y(), wire.GetEnd().Y())
267 for wire
in plane.IterateWires()
270 min(wire.GetStart().Z(), wire.GetEnd().Z())
271 for wire
in plane.IterateWires()
274 max(wire.GetStart().Z(), wire.GetEnd().Z())
275 for wire
in plane.IterateWires()
279 shorterWires = dict()
280 for iWire, wire
in enumerate(plane.IterateWires()):
282 wireID = ROOT.geo.WireID(plane.ID(), iWire)
287 start = wire.GetStart()
291 if len(borders) == 0:
293 "Wire %s \"start\" at %s cm does not touch any plane border (%s)",
294 wireID, start,
", ".
join(
"%s: %g" % item
for item
in borderCoords.items()),
296 shorterWires.setdefault(wireID, []).append(
'start')
306 if len(borders) == 0:
308 "Wire %s \"end\" at %s cm does not touch any plane border (%s)",
309 wireID, end,
", ".
join(
"%s: %g" % item
for item
in borderCoords.items()),
311 shorterWires.setdefault(wireID, []).append(
'end')
323 Wires in the plane A are verified to have a continuation in plane B as another
324 wire. Only wires that reach the side (extreme z coordinate) are tested.
326 Wires are assumed to have to go top to bottom on y direction.
328 The list of misaligned wires is returned in the 5-uple form:
330 ( shift, left wire ID, left wire, right wire ID, right wire )
332 if the wire on the left plane was matched to one on the right plane, and
334 ( None, left wire ID, left wire, None, None )
336 if the wire on the left plane was not matched to any wire on the right plane.
343 if planeA.GetCenter().Z() < planeB.GetCenter().Z():
344 leftPlane, rightPlane = planeA, planeB
346 leftPlane, rightPlane = planeB, planeA
349 rightWirePitch = rightPlane.WirePitch()
350 assert abs(rightWirePitch - leftPlane.WirePitch()) < tolerance
356 min(wire.GetStart().Y(), wire.GetEnd().Y())
357 for wire
in leftPlane.IterateWires()
360 max(wire.GetStart().Y(), wire.GetEnd().Y())
361 for wire
in leftPlane.IterateWires()
364 max(wire.GetStart().Z(), wire.GetEnd().Z())
365 for wire
in leftPlane.IterateWires()
374 leftEndPos =
lambda wire: \
375 wire.GetStart()
if wire.GetStart().Z() > wire.GetEnd().Z()
else wire.GetEnd()
376 rightStartPos =
lambda wire: \
377 wire.GetStart()
if wire.GetStart().Z() < wire.GetEnd().Z()
else wire.GetEnd()
381 for leftWireNo, leftWire
in enumerate(leftPlane.IterateWires()):
383 leftEnd = leftEndPos(leftWire)
389 if abs(leftEnd.Z() - leftMaxZ) > 0.01:
continue
390 if abs(leftEnd.Y() - leftMaxY) < 0.01
or abs(leftEnd.Y() - leftMinY) < 0.01:
396 leftWireID = ROOT.geo.WireID(leftPlane.ID(), leftWireNo)
398 rightWireID = rightPlane.NearestWireID(leftEnd)
400 except TypeError
as e:
402 except ROOT.geo.InvalidWireError
as e:
406 "No wire on %s is close enough to %s (closest is %s, but would have been %s)",
407 rightPlane.ID(), leftWireID,
408 (e.suggestedWireID()
if e.hasSuggestedWire()
else "unknown"),
409 (e.badWireID()
if e.hasBadWire()
else "unknown"),
411 rightWireID = e.badWireID()
if e.hasBadWire()
else None
412 rightWireID.markInvalid()
413 misalignedWires.append( (
None, leftWireID, leftWire,
None,
None, ) )
418 if rightWireID
is None:
419 msg +=
"No wire on {} is close enough to {}" \
420 .
format(rightPlane.ID(), leftWireID)
422 msg +=
"No wire on {} is close enough to {} (would have been {})" \
423 .
format(rightPlane.ID(), leftWireID, rightWireID)
426 wireCoord = rightPlane.WireCoordinate(leftEnd)
427 msg +=
"; closest would have been {} W: {}" \
428 .
format(rightPlane.ID(), wireCoord)
430 nearestWireID = ROOT.geo.WireID(rightPlane.ID(), int(0.5 + wireCoord)) \
431 if 0.5 + wireCoord >= 0.0
else None
433 if nearestWireID
and rightPlane.HasWire(nearestWireID):
434 nearestWire = rightPlane.Wire(nearestWireID)
436 msg +=
"; actual {} ends at: {}" \
437 .
format(nearestWireID, rightStartPos(nearestWire))
440 misalignedWires.append( (
None, leftWireID, leftWire,
None,
None, ) )
444 rightWire = rightPlane.Wire(rightWireID)
449 shift = leftWire.DistanceFrom(rightWire)
455 leftWire.Direction().Dot(rightWire.Direction())
456 if 1.0 - leftWire.Direction().Dot(rightWire.Direction()) > tolerance:
458 "Wire %s has direction %s, the matched %s has %s",
459 leftWireID, leftWire.Direction(),
460 rightWireID, rightWire.Direction(),
467 d = (leftEndPos(leftWire) - rightStartPos(rightWire)).Mag()
470 "Distance of wire %s (%s) from the matched wire %s (%s): %g",
471 leftWireID, leftEndPos(leftWire),
472 rightWireID, rightStartPos(rightWire),
476 closestWireID, d_min = rightWireID, d
477 testWireID = rightWireID
478 while testWireID.Wire > 0:
480 testWire = rightPlane.Wire(testWireID)
481 test_d = (leftEndPos(leftWire) - rightStartPos(testWire)).Mag()
482 logging.debug(
"Distance from %s (%s): %g", testWireID, rightStartPos(testWire), test_d)
483 if test_d >= d_min:
break
484 closestWireID, d_min = testWireID, test_d
486 testWireID = rightWireID
487 LastWireNo = rightPlane.Nwires() - 1
488 while testWireID.Wire < LastWireNo:
490 testWire = rightPlane.Wire(testWireID)
491 test_d = (leftEndPos(leftWire) - rightStartPos(testWire)).Mag()
492 logging.debug(
"Distance from %s (%s): %g", testWireID, rightStartPos(testWire), test_d)
493 if test_d >= d_min:
break
494 closestWireID, d_min = testWireID, test_d
498 "Wire %s ends at %s, the matched wire %s starts at %s, %g cm away.",
499 leftWireID, leftEndPos(leftWire),
500 rightWireID, rightStartPos(rightWire),
503 if closestWireID != rightWireID:
505 " => the closest wire is actually %s starting at %s, %g cm away",
506 closestWireID, rightPlane.Wire(closestWireID), d_min
510 misalignedWires.append( ( d_min, leftWireID, leftWire, rightWireID, rightWire ) )
516 if stats.entries() > 0:
517 logging.debug(
"Shift for %d wires between %s and %s: %g +/- %g cm",
518 stats.entries(), leftPlane.ID(), rightPlane.ID(),
519 stats.average(), stats.RMS(),
522 logging.debug(
"No wire shift statistics collected.")
523 return misalignedWires
529 """Check alignment in z position of planes on the same x.
531 Returns triples (distance, first plane, second plane) for each misaligned
534 assert tolerance >= 0.0
537 for planesOnX
in PlanesByX:
538 if len(planesOnX) < 2:
continue
539 misalignedWiresOnPlane = []
540 planeIter = iter(planesOnX)
541 leftPlane = next(planeIter)
542 for rightPlane
in planeIter:
543 misalignedWiresOnPair \
545 if misalignedWiresOnPair:
546 misalignedWiresOnPlane.extend(misalignedWiresOnPair)
547 leftPlane = rightPlane
549 if misalignedWiresOnPlane: misalignedWires.append(misalignedWiresOnPlane)
551 return misalignedWires
557 def __init__(self, keyFunc = None, tolerance = None):
558 self.
keyFunc = (
lambda obj: obj)
if keyFunc
is None else keyFunc
566 withPrevious = refKey
is not None and self.
_compareKeys(key, refKey)
569 groups.append(
list())
570 groups[-1].append(obj)
577 def cluster(objs, keyFunc = None, tolerance = None):
583 xPos =
lambda plane: plane.GetCenter().
X()
585 groupedByX =
cluster(sorted(planes, key=xPos))
587 if sortBy.lower() ==
'x':
589 elif sortBy.lower() ==
'y':
590 sortKey =
lambda plane: plane.GetCenter().Y()
591 elif sortBy.lower() ==
'z':
592 sortKey =
lambda plane: plane.GetCenter().Z()
594 raise RuntimeError(
"Unsupported sorting requested: '%s'" % sortBy)
595 for planes
in groupedByX: planes.sort(key=sortKey)
610 if self.
min_ > value
or self.
min_ is None: self.
min_ = value
611 if self.
max_ < value: self.
max_ = value
613 def min(self):
return self.min_
614 def max(self):
return self.max_
628 def add(self, value, weight = 1.0):
631 self.
wx += weight * value
632 self.
wx2 += weight * value**2
636 def sum(self):
return self.wx
638 def average(self):
return self.wx / self.
w if self.
w else None
651 Parser = argparse.ArgumentParser(description=__doc__)
653 Parser.set_defaults()
655 Parser.add_argument(
"config", help=
"configuration file [FHiCL]")
657 Parser.add_argument(
"--servicetable",
"-T", default=
'services',
658 help=
"name of the FHiCL table where all services are configured ['%(default)s']"
661 Parser.add_argument(
"--debug",
"-d", action=
"count", default=0,
662 help=
"be more verbose")
664 Parser.add_argument(
"--version",
"-V", action=
"version", version=__version__)
670 args = Parser.parse_args(args=argv[1:])
675 logging.basicConfig(level=logging.DEBUG - (args.debug - 1))
677 from ICARUSservices
import ServiceManager
684 cppUtils.SourceCode.loadHeaderFromUPS(
"larcorealg/Geometry/Exceptions.h")
688 ServiceManager.setConfiguration(args.config, args.servicetable)
694 Cryostats =
list(geom.IterateCryostats())
695 TPCs =
list(geom.IterateTPCs())
696 Planes =
list(geom.IteratePlanes())
702 if overlappingCryostats:
703 msg =
"%s cryostat overlaps detected: %s." % (
704 len(overlappingCryostats),
705 ", ".
join(map(GeoPairToString, overlappingCryostats)),
708 FailureSummary.append(msg)
709 else: logging.info(
"No cryostat overlap detected.")
716 msg =
"%s TPC overlaps detected: %s." % (
717 len(overlappingTPCs),
", ".
join(map(GeoPairToString, overlappingTPCs)),
720 FailureSummary.append(msg)
721 else: logging.info(
"No TPC overlap detected.")
726 overlappingActiveVolTPCs = CheckGeoObjOverlaps \
727 (TPCs,
"active TPC volume", extractBox=ROOT.geo.TPCGeo.ActiveBoundingBox)
728 if overlappingActiveVolTPCs:
729 msg =
"%s TPC active volume overlaps detected: %s." % (
730 len(overlappingActiveVolTPCs),
731 ", ".
join(map(GeoPairToString, overlappingActiveVolTPCs)),
734 FailureSummary.append(msg)
735 else: logging.info(
"No TPC active volume overlap detected.")
740 overlappingPlanes = CheckGeoObjOverlaps \
741 (Planes,
"wire planes", extractBox=ROOT.geo.PlaneGeo.BoundingBox)
742 if overlappingPlanes:
743 logging.error(
"%s wire plane overlaps detected: %s.",
744 len(overlappingPlanes),
745 ", ".
join(map(GeoPairToString, overlappingPlanes))
747 FailureSummary.append \
748 (
"%s wire plane overlaps detected." % len(overlappingPlanes))
749 else: logging.info(
"No wire plane overlap detected.")
756 try: planesWithIssues = inconsistentPlanes[
'zalign']
758 logging.info(
"All %d planes are correctly aligned along z.", len(Planes))
760 logging.error(
"%s wire planes present misalignment on z: %s",
761 len(planesWithIssues),
", ".
join(
762 "%s vs. %s (%g mm)" % (planeA.ID(), planeB.ID(), distance)
763 for distance, planeA, planeB
in planesWithIssues
766 FailureSummary.append \
767 (
"%s wire planes present misalignment: " % len(misalignedPlanes))
770 try: planesWithIssues = inconsistentPlanes[
'topYalign']
772 logging.info(
"Top of all %d planes is correctly aligned.", len(Planes))
774 logging.error(
"%s wire planes present misalignment of top side: %s",
775 len(planesWithIssues),
", ".
join(
776 "%s vs. %s (%g mm)" % (planeA.ID(), planeB.ID(), distance)
777 for distance, planeA, planeB
in planesWithIssues
780 FailureSummary.append \
781 (
"%s wire planes present misalignment on top side" % len(planesWithIssues))
784 try: planesWithIssues = inconsistentPlanes[
'bottomYalign']
786 logging.info(
"Bottom of all %d planes is correctly aligned.", len(Planes))
788 logging.error(
"%s wire planes present misalignment of bottom side: %s",
789 len(planesWithIssues),
", ".
join(
790 "%s vs. %s (%g mm)" % (planeA.ID(), planeB.ID(), distance)
791 for distance, planeA, planeB
in planesWithIssues
794 FailureSummary.append \
795 (
"%s wire planes present misalignment on bottom side" % len(planesWithIssues))
798 try: planesWithIssues = inconsistentPlanes[
'wireZalign']
801 "Inter-plane areas covered by wires on all %d planes are correctly aligned.",
805 logging.error(
"%s planes have wires inconsistently covering the touching side: %s",
806 len(planesWithIssues),
", ".
join(
807 "%s vs. %s (%g mm)" % (planeA.ID(), planeB.ID(), distance)
808 for distance, planeA, planeB
in planesWithIssues
811 FailureSummary.append(
812 "%s planes present inconsistent wire coverage on touching side"
813 % len(planesWithIssues)
817 try: planesWithIssues = inconsistentPlanes[
'wireBottomYalign']
820 "Bottom of areas covered by wires on all %d planes is correctly aligned.",
824 logging.error(
"%s planes have wires inconsistently covering bottom side: %s",
825 len(planesWithIssues),
", ".
join(
826 "%s vs. %s (%g mm)" % (planeA.ID(), planeB.ID(), distance)
827 for distance, planeA, planeB
in planesWithIssues
830 FailureSummary.append(
831 "%s planes present inconsistent wire coverage on bottom side: "
832 % len(misalignedPlanes)
836 try: planesWithIssues = inconsistentPlanes[
'wireTopYalign']
839 "Top of areas covered by wires on all %d planes is correctly aligned.",
843 logging.error(
"%s planes have wires inconsistently covering top side: %s",
844 len(planesWithIssues),
", ".
join(
845 "%s vs. %s (%g mm)" % (planeA.ID(), planeB.ID(), distance)
846 for distance, planeA, planeB
in planesWithIssues
849 FailureSummary.append(
850 "%s planes present inconsistent wire coverage on top side: "
851 % len(misalignedPlanes)
857 try: planesWithIssues = inconsistentPlanes[
'view']
859 logging.info(
"All %d planes have matching views.", len(Planes))
861 logging.error(
"%s wire planes present direction inconsistencies:",
862 len(planesWithIssues),
", ".
join(
863 "%s vs. %s" % (planeA.ID(), planeB.ID())
864 for planeA, planeB
in planesWithIssues
867 FailureSummary.append(
868 "%s wire planes present direction inconsistencies." % len(planesWithIssues)
872 try: planesWithIssues = inconsistentPlanes[
'direction']
874 logging.info(
"All %d planes have consistent directions.", len(Planes))
876 logging.error(
"%s wire planes present view inconsistencies:",
877 len(planesWithIssues),
", ".
join(
878 "%s vs. %s" % (planeA.ID(), planeB.ID())
879 for planeA, planeB
in planesWithIssues
882 FailureSummary.append(
883 "%s wire planes present view inconsistencies." % len(planesWithIssues)
894 logging.error(
"Wires not ending on plane frame found (%d):",
897 for wireID, ends
in shorterWires.items():
898 logging.error(
" %s: %s", wireID,
", ".
join(ends))
899 FailureSummary.append \
900 (
"%d wires do not end on plane frame" % len(shorterWires))
906 logging.error(
"Misaligned wires found on %d extended planes:",
907 len(misalignedWires),
909 for misalignedWiresOnPlane
in misalignedWires:
910 logging.error(
" %d on wires on plane around x=%g cm:",
911 len(misalignedWiresOnPlane),
912 misalignedWiresOnPlane[0][2].GetCenter().
X()
914 for shift, wireLid, wireL, wireRid, wireR
in misalignedWiresOnPlane:
916 logging.error(
" %s did not match any wire", wireLid)
918 logging.error(
" %s and %s are misaligned by %g um",
919 wireLid, wireRid, shift * 1.0e4,
923 FailureSummary.append \
924 (
"misaligned wires found on %d extended planes" % len(misalignedWires))
926 logging.info(
"No misaligned wires detected.")
929 logging.info(
"%d failure categories detected:\n - %s",
930 len(FailureSummary),
"\n - ".
join(FailureSummary),
933 return 1
if FailureSummary
else 0
938 if __name__ ==
"__main__":
def performGeometryChecks
static std::string format(PyObject *obj, unsigned int pos, unsigned int indent, unsigned int maxlen, unsigned int depth)
def checkWireEndingsInPlane
Cluster finding and building.
then echo echo For and will not be changed by echo further linking echo echo B echo The symbol is in the uninitialized data multiple common symbols may appear with the echo same name If the symbol is defined the common echo symbols are treated as undefined references For more echo details on common see the discussion of warn common echo in *Note Linker see the discussion of warn common echo in *Note Linker such as a global int variable echo as opposed to a large global array echo echo I echo The symbol is an indirect reference to another symbol This echo is a GNU extension to the a out object file format which is echo rarely used echo echo N echo The symbol is a debugging symbol echo echo R echo The symbol is in a read only data section echo echo S echo The symbol is in an uninitialized data section for small echo objects echo echo T echo The symbol is in the the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo W echo The symbol is a weak symbol that has not been specifically echo tagged as a weak object symbol When a weak defined symbol echo is linked with a normal defined the normal defined echo symbol is used with no error When a weak undefined symbol echo is linked and the symbol is not the value of the echo weak symbol becomes zero with no error echo echo echo The symbol is a stabs symbol in an a out object file In echo this the next values printed are the stabs other echo the stabs desc and the stab type Stabs symbols are echo used to hold debugging information For more echo see *Note or object file format specific echo echo For Mac OS X
auto enumerate(Iterables &&...iterables)
Range-for loop helper tracking the number of iteration.
S join(S const &sep, Coll const &s)
Returns a concatenation of strings in s separated by sep.
def checkPlaneWireAlignment