00001
00002
00003
00004
00005
00006
00007
00008
00009 """ Processing of optical measurements for XPP-CSPAD (fixed geometry)
00010
00011 @see OpticAlignmentCspadMethods.py
00012
00013 @version $Id: OpticAlignmentCspadV2.py 12520 2016-08-23 17:12:08Z dubrovin@SLAC.STANFORD.EDU $
00014
00015 @author Mikhail S. Dubrovin
00016 """
00017
00018
00019 __version__ = "$Revision: 12520 $"
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 from CalibManager.OpticAlignmentCspadMethods import *
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 class OpticAlignmentCspadV2 (OpticAlignmentCspadMethods) :
00049 """OpticAlignmentCspadV2"""
00050
00051
00052 quad_r090 = [0, 32,29,30,31, 28,25,26,27, 4,1,2,3, 8,5,6,7, 16,13,14,15, 12,9,10,11, 20,17,18,19, 24,21,22,23]
00053 quad_r000 = [0, 1,2,3,4, 5,6,7,8, 9,10,11,12, 13,14,15,16, 17,18,19,20, 21,22,23,24, 25,26,27,28, 29,30,31,32]
00054 quad_r270 = [0, 10,11,12,9, 14,15,16,13, 22,23,24,21, 18,19,20,17, 26,27,28,25, 30,31,32,29, 6,7,8,5, 2,3,4,1]
00055 quad_r180 = [0, 23,24,21,22, 19,20,17,18, 31,32,29,30, 27,28,25,26, 7,8,5,6, 3,4,1,2, 15,16,13,14, 11,12,9,10]
00056
00057
00058 quad_n90_in_det = [1,0,3,2]
00059
00060 def __init__(self, fname=None, path='calib-tmp', save_calib_files=True, print_bits=07777, plot_bits=0377, exp='Any', det='CSPAD-XPP', n90=0):
00061 """Constructor."""
00062
00063 if print_bits & 1 : print 'Start OpticAlignmentCspadV2'
00064
00065 if fname is not None : self.fname = fname
00066 else : self.fname = '/reg/neh/home1/dubrovin/LCLS/CSPadMetrologyProc/metrology_standard.txt'
00067
00068 if not os.path.lexists(self.fname) :
00069 if print_bits & 1 : print 'Non-available input file: ' + self.fname
00070 return
00071
00072 self.path = path
00073 self.save_calib_files = save_calib_files
00074 self.print_bits = print_bits
00075 self.plot_bits = plot_bits
00076 self.exp = exp
00077 self.det = det
00078
00079 self.fname_center_um = os.path.join(self.path, 'center_global_um-0-end.data')
00080 self.fname_center = os.path.join(self.path, 'center_global-0-end.data')
00081 self.fname_tilt = os.path.join(self.path, 'tilt-0-end.data')
00082 self.fname_geometry = os.path.join(self.path, 'geometry-0-end.data')
00083
00084 self.fname_plot_det = os.path.join(self.path, 'metrology_standard_det.png')
00085
00086 self.readOpticalAlignmentFile()
00087 self.changeNumerationToQuadsV1(n90)
00088 self.evaluate_deviation_from_flatness()
00089 self.evaluate_center_coordinates()
00090 self.evaluate_length_width_angle(n90)
00091
00092 self.present_results()
00093
00094
00095
00096
00097 def present_results(self):
00098
00099 if self.print_bits & 2 : print '\n' + self.txt_deviation_from_flatness()
00100 if self.print_bits & 4 : print '\nQuality check in XY plane:\n', self.txt_qc_table_xy()
00101 if self.print_bits & 8 : print '\nQuality check in Z:\n', self.txt_qc_table_z()
00102
00103 center_txt_um = self.txt_center_um_formatted_array (format='%6i ')
00104 center_txt_pix = self.txt_center_pix_formatted_array(format='%7.2f ')
00105 tilt_txt = self.txt_tilt_formatted_array(format='%8.5f ')
00106 geometry_txt = self.txt_geometry()
00107
00108 if self.print_bits & 16 : print 'X, Y, and Z coordinates of the 2x1 center_global (um):\n' + center_txt_um
00109 if self.print_bits & 32 : print '\nCalibration type "center_global" in pixels:\n' + center_txt_pix
00110 if self.print_bits & 64 : print '\nCalibration type "tilt" - degree:\n' + tilt_txt
00111 if self.print_bits & 128 : print '\nCalibration type "geometry"\n%s' % geometry_txt
00112
00113 if self.save_calib_files :
00114 self.create_directory(self.path)
00115 self.save_text_file(self.fname_center_um, center_txt_um)
00116 self.save_text_file(self.fname_center, center_txt_pix)
00117 self.save_text_file(self.fname_tilt, tilt_txt)
00118 self.save_text_file(self.fname_geometry, geometry_txt)
00119
00120 if self.plot_bits & 1 :
00121 self.arr = self.arr_opt
00122 print 'Draw array from metrology file'
00123 self.drawOpticalAlignmentFile()
00124
00125 if self.plot_bits & 2 :
00126 self.arr = self.arr_renum
00127 print 'Draw array with re-numerated points for quads'
00128 self.drawOpticalAlignmentFile()
00129
00130
00131
00132 def readOpticalAlignmentFile(self):
00133 """Reads the metrology.txt file with original optical measurements.
00134 The numereation of points is changed since 2012-02-26.
00135 """
00136 if self.print_bits & 1 : print 'readOpticalAlignmentFile()'
00137
00138
00139
00140
00141 self.arr_opt = numpy.zeros( (self.nquads, self.npoints+1, 4), dtype=numpy.int32 )
00142
00143
00144 file = open(self.fname, 'r')
00145
00146 for linef in file:
00147
00148 line = linef.strip('\n')
00149
00150
00151
00152 if not line : continue
00153
00154 list_of_fields = line.split()
00155
00156 if list_of_fields[0] == 'Quad' :
00157 self.quad = int(list_of_fields[1])
00158 if self.print_bits & 256 : print 'Stuff for quad', self.quad
00159 continue
00160
00161 if list_of_fields[0] in ('Sensor', 'Point') :
00162 if self.print_bits & 256 : print 'Comment line:', line
00163 continue
00164
00165 if len(list_of_fields) != 4 :
00166 if self.print_bits & 256 : print 'len(list_of_fields) =', len(list_of_fields),
00167 if self.print_bits & 256 : print 'RECORD IS IGNORED due to unexpected format of the line:',line
00168 continue
00169
00170 point, X, Y, Z = [int(v) for v in list_of_fields]
00171
00172
00173 if self.print_bits & 256 : print 'ACCEPT RECORD:', point, X, Y, Z
00174
00175 self.arr_opt[self.quad,point,:] = [point, X, Y, Z]
00176
00177 file.close()
00178
00179 if self.print_bits & 256 : print 'Array of alignment info:\n', self.arr_opt
00180
00181
00182
00183
00184 def arrNumTransformationForN90(self, n90=0):
00185
00186 if n90 == 0 : return np.array([self.quad_r090, self.quad_r000, self.quad_r270, self.quad_r180])
00187 elif n90 == 1 : return np.array([self.quad_r000, self.quad_r270, self.quad_r180, self.quad_r090])
00188 elif n90 == 2 : return np.array([self.quad_r270, self.quad_r180, self.quad_r090, self.quad_r000])
00189 elif n90 == 3 : return np.array([self.quad_r180, self.quad_r090, self.quad_r000, self.quad_r270])
00190 else :
00191 print 'arrNumTransformationForN90: WRONG n90=%d, use n90 = 0, 1, 2, or 3' % n90
00192 sys.exit('Exit on warning')
00193
00194
00195
00196
00197 def changeNumerationToQuadsV1(self, n90=0):
00198 """The numereation of points is changed since 2012-02-26.
00199 Bring the numeration of points to old-standard.
00200 """
00201 if self.print_bits & 256 : print 'changeNumerationToQuadsV1()'
00202
00203
00204
00205
00206 self.arr_renum = numpy.zeros( (self.nquads, self.npoints+1, 4), dtype=numpy.int32 )
00207
00208
00209 num_conv = self.arrNumTransformationForN90(n90)
00210
00211 for quad in range(self.nquads) :
00212 for point in range(1,self.npoints+1,1) :
00213
00214 point_optical = num_conv[quad][point]
00215 self.arr_renum[quad,point,...] = self.arr_opt[quad,point_optical,...]
00216 self.arr_renum[quad,point,0] = point
00217
00218 if self.print_bits & 256 : print 'Array with standard (per quad) numeration of points:\n', self.arr_renum
00219
00220 self.arr = self.arr_renum
00221
00222
00223
00224
00225 def txt_geometry_segments(self) :
00226 txt = ''
00227 name_segm = 'SENS2X1:V1'
00228 segm_index = -1
00229 name_parent = 'CSPAD:V2'
00230 name_index = 0
00231 rotXZ, rotYZ = 0,0
00232 for quad in range(self.nquads) :
00233 for segm in range(self.nsegms) :
00234 segm_index += 1
00235 txt += self.str_fmt() % \
00236 (name_parent.ljust(12), name_index, name_segm.ljust(12), segm_index, \
00237 self.arrXmu[quad][segm], \
00238 self.arrYmu[quad][segm], \
00239 self.arrZmu[quad][segm], \
00240 self.rotXYDegree[quad][segm], \
00241 rotXZ, \
00242 rotYZ, \
00243 self.tiltXYDegree[quad][segm], \
00244 self.tiltXZDegree[quad][segm], \
00245 self.tiltYZDegree[quad][segm])
00246 txt += '\n'
00247 return txt
00248
00249
00250
00251 def txt_geometry_det_ip(self) :
00252 txt = ''
00253 name_object = 'CSPAD:V2'
00254 name_parent = 'IP'
00255 num_parent, num_object, x0, y0, z0, rotXY, rotXZ, rotYZ, tiltXY, tiltXZ, tiltYZ = 0,0,0,0,1e6,0,0,0,0,0,0
00256 txt += self.str_fmt() % \
00257 (name_parent.ljust(12), num_parent, name_object.ljust(12), num_object, \
00258 x0, y0, z0, rotXY, rotXZ, rotYZ, tiltXY, tiltXZ, tiltYZ)
00259
00260 return txt + '\n'
00261
00262
00263
00264
00265 def txt_geometry(self) :
00266 return self.txt_geometry_header() + \
00267 self.txt_geometry_segments() + \
00268 self.txt_geometry_det_ip()
00269
00270
00271
00272
00273
00274
00275 def main():
00276
00277
00278
00279
00280
00281 fname = '2013-10-09-CSPAD-XPP-Metrology.txt'
00282
00283 base_dir = '/reg/neh/home1/dubrovin/LCLS/CSPadMetrologyProc/'
00284
00285 (opts, args) = input_option_parser(base_dir, fname)
00286 path_metrol = os.path.join(opts.dir, opts.fname)
00287
00288 OpticAlignmentCspadV2(path_metrol, print_bits=opts.pbits, plot_bits=opts.gbits, n90=0)
00289 sys.exit()
00290
00291 if __name__ == '__main__':
00292 main()
00293
00294