makePolycone.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 
3 import os
4 import sys
5 import getopt
6 
7 def usage():
8  print """
9  makePolycone <inner-surface.txt> <outer-surface.txt>
10 
11  Outputs text to the standard output that is suitable to be included
12  into a C++ source file defining the inner and outer surfaces of a
13  G4Polycone.
14 
15  --vector-name <name>
16  The name of a vector to be used in the include file.
17 
18  --step
19  The step size along the Z axis to use while building the
20  polycone. This can be small (but it will make this run slowly),
21  since only the steps where the precision is bad will be saved.
22 
23  --precision
24  Set the maximum distance the wall of the cryostat can be from the
25  interpolated line.
26  """
27 
28 try:
29  options, args = getopt.gnu_getopt(sys.argv[1:],
30  "h",
31  ["vector-name=",
32  "precision=",
33  "step=",
34  "minimum-segment=",
35  "help"])
36 except:
37  usage()
38  print "ERROR: Invalid option."
39  sys.exit(1)
40 
41 if len(args)<2:
42  usage()
43  sys.exit(1)
44 
45 # Define the default values for the options.
46 vectorName = "polyconeShape"
47 boundaryStep = 0.3
48 precision = 0.3
49 minimumSegment = 0.5
50 
51 # Parse the command line options.
52 for o, a in options:
53  if o == "--vector-name":
54  vectorName=a
55  elif o == "--precision":
56  precision=float(a)
57  elif o == "--step":
58  boundaryStep=float(a)
59  elif o == "--minimum-segment":
60  minimumSegment=float(a)
61  else:
62  usage()
63  sys.exit(1)
64 
65 # Read the points from an input file. The file should be defined as
66 # X, Y where the symetry axis is along X, and the radius is along Y.
67 # This only uses the first two numbers on a line.
68 def ReadPoints(fileName):
69  print "// Filename: ", fileName
70  points = []
71  for line in open(fileName):
72  if line[0] == "/":
73  print line.rstrip()
74  continue
75  if len(line) < 5: continue
76  spl = line.split()
77  points.append([float(spl[0]),float(spl[1])])
78  return points
79 
80 # Find the radius of the cryostat at a particular vertical position.
81 # This is called "z" since it's going to be used to buill a G4Polycone
82 # along the Z axis. In the Z axis here is equivalent to the X axis in
83 # the input file.
84 def FindRadius(z,points):
85  radii=[]
86  there=points[-1]
87  for here in points:
88  if ((there[0] <= z and z < here[0])
89  or (here[0] <= z and z < there[0])):
90  r = (here[1]-there[1])/(here[0]-there[0])*(z-there[0]) + there[1]
91  radii.append(r)
92  there = here
93  if len(radii) == 0: return 0.0
94  average = reduce(lambda x, y: x+y, radii)/len(radii)
95  r = 0.0
96  for p in radii:
97  r = r + abs(p-average)
98  return r/len(radii)
99 
100 # Find the total range along the vertical axis of the cryostat that
101 # needs to be used to define the polycone.
102 def FindRange(inner,outer,step):
103  minZ = min(innerPoints[0][0],outerPoints[0][0])
104  maxZ = max(innerPoints[0][0],outerPoints[0][0])
105  for p in inner:
106  minZ = min(p[0], minZ)
107  maxZ = max(p[0], maxZ)
108  for p in outer:
109  minZ = min(p[0], minZ)
110  maxZ = max(p[0], maxZ)
111  return xrange(int(minZ/step)-1, int(maxZ/step)+2)
112 
113 # Check to see if a new polycone segment needs to be started.
114 def SegmentIsOK(p1,p2,middle,thres):
115  if abs(p1[0]-p2[0]) < minimumSegment: return True;
116  maxThres = 0.0
117  for p in middle:
118  r1 = (p[0]-p2[0])*(p1[1]-p2[1])/(p1[0]-p2[0]) + p2[1]
119  r2 = (p[0]-p2[0])*(p1[2]-p2[2])/(p1[0]-p2[0]) + p2[2]
120  maxThres = max(maxThres, abs(r1-p[1]))
121  maxThres = max(maxThres, abs(r2-p[2]))
122  if maxThres > thres: return False;
123  return True
124 
125 print """
126 ////////////////////////////////////////////////////////////////////////
127 // This is an auto-generated built using makePolycone.py. It defines
128 // points to be used to build a G4Polycone. Prior to including this file,
129 // the vector %s must be define in a way equivalent to
130 //
131 // class Point {
132 // public:
133 // Point(double z, double i, double o): fZ(z), fInner(i), fOuter(o) {}
134 // double fZ;
135 // double fInner;
136 // double fOuter;
137 // };
138 //
139 // std::vector<Point> %s;
140 //
141 ////////////////////////////////////////////////////////////////////////
142 """ % (vectorName, vectorName)
143 
144 innerPoints = ReadPoints(args[0])
145 print ""
146 outerPoints = ReadPoints(args[1])
147 print ""
148 
149 # Build up the boundary of the polycone using fixed steps in Z. The digitized
150 # boundaries are interpolated to fill in missing points.
151 boundary = []
152 for iZ in FindRange(innerPoints,outerPoints,boundaryStep):
153  z = boundaryStep*iZ
154  inner = FindRadius(z,innerPoints)
155  outer = FindRadius(z,outerPoints)
156  if outer < inner: inner, outer = outer, inner
157  boundary.append([z,inner,outer])
158 
159 # Figure out which boundary points should be used to define the segments in
160 # G4Polycone. This scans through the boundary points and finds out where
161 # the interpolated line gets to far from the expected line.
162 savedPoints = [boundary[0]]
163 runningPoints = []
164 for p in boundary[1:]:
165  if len(runningPoints) < 1:
166  runningPoints.append(p)
167  continue
168  if SegmentIsOK(savedPoints[-1],p,runningPoints,precision):
169  runningPoints.append(p)
170  continue
171  savedPoints.append(runningPoints[-1])
172  runningPoints = []
173 if savedPoints[-1] != boundary[-1]: savedPoints.append(boundary[-1])
174 
175 # Dump all of the saved points to the output as a line of "c++" code.
176 for p in savedPoints:
177  print "%s.push_back(Point(%f,%f,%f));" % (vectorName,p[0],p[1],p[2])
178 
179 sys.exit(0)
static std::string reduce(const std::string &str, const std::string &fill=" ", const std::string &whitespace=" \t")
Definition: doxyindexer.cpp:63
def FindRange(inner, outer, step)
int open(const char *, int)
Opens a file descriptor.
def FindRadius(z, points)
Definition: makePolycone.py:84
T abs(T value)
def SegmentIsOK(p1, p2, middle, thres)
static int max(int a, int b)
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
def ReadPoints(fileName)
Definition: makePolycone.py:68