def fit(self, table ) : """TODO: document""" log = get_logger() #- identify ADC setups adc12=(np.array(table['ADC1'])+1000*np.array(table['ADC2'])) uadc12 = np.unique(adc12) nconfig = len(uadc12) self.adc1 = np.zeros(nconfig,dtype=float) self.adc2 = np.zeros(nconfig,dtype=float) self.scale = np.zeros(nconfig,dtype=float) self.rotation = np.zeros(nconfig,dtype=float) self.offset_x = np.zeros(nconfig,dtype=float) self.offset_y = np.zeros(nconfig,dtype=float) self.zbpolids = None self.zbcoeffs = list() for config, adc12v in enumerate(uadc12) : selection = (adc12==adc12v) self.adc1[config]=table['ADC1'][selection][0] self.adc2[config]=table['ADC2'][selection][0] print("Fitting ADC1={} ADC2={}".format(self.adc1[config],self.adc2[config])) #- Get reduced coordinates rxtan, rytan = _reduce_xytan(table['X_TAN'][selection], table['Y_TAN'][selection]) rxfp, ryfp = _reduce_xyfp(table['X_FP'][selection], table['Y_FP'][selection]) ################################################################# ## CHOICE OF POLYNOMIALS IS HERE ## polids = np.array([2, 5, 6, 9, 20, 27, 28, 29, 30],dtype=int) ################################################################# #- Perform fit if 1 : # it's a bit better scale, rotation, offset_x, offset_y, zbpolids, zbcoeffs = fit_scale_rotation_offset(rxtan, rytan, rxfp, ryfp, fitzb=True, polids=polids) self.scale[config] = scale self.rotation[config] = rotation self.offset_x[config] = offset_x self.offset_y[config] = offset_y else : zbpolids, zbcoeffs, dx, dy = fitZhaoBurge(rxtan, rytan, rxfp, ryfp, polids=polids) self.scale[config] = 1 self.rotation[config] = 0. self.offset_x[config] = 0. self.offset_y[config] = 0. if self.zbpolids is None : self.zbpolids = zbpolids else : assert(np.all(self.zbpolids==zbpolids)) self.zbcoeffs.append(zbcoeffs) #- Goodness of fit #xfp_fit, yfp_fit = self.tan2fp(table['X_TAN'][selection], table['Y_TAN'][selection]) #dx = (table['X_FP'][selection] - xfp_fit) #dy = (table['Y_FP'][selection] - yfp_fit) #dr = np.sqrt(dx**2 + dy**2) #log.info('Mean, median, RMS distance = {:.1f}, {:.1f}, {:.1f} um'.format( # 1000*np.mean(dr), 1000*np.median(dr), 1000*np.sqrt(np.mean(dr**2)))) self.zbcoeffs = np.vstack(self.zbcoeffs)
def fit(self, spots, metrology=None, update_spots=False): """TODO: document""" log = get_logger() if metrology is not None: self.metrology = metrology else: filename = resource_filename('desimeter', "data/fp-metrology.csv") if not os.path.isfile(filename): log.error("cannot find {}".format(filename)) raise IOError("cannot find {}".format(filename)) log.info("reading fiducials metrology in {}".format(filename)) self.metrology = Table.read(filename, format="csv") #- Trim spots to just fiducial spots (not posioners, not unmatchs spots) ii = (spots['LOCATION'] > 0) & (spots['PINHOLE_ID'] > 0) fidspots = spots[ii] #- trim metrology to just the ones that have spots fidspots_pinloc = fidspots['LOCATION'] * 10 + fidspots['PINHOLE_ID'] metro_pinloc = self.metrology['LOCATION'] * 10 + self.metrology[ 'PINHOLE_ID'] jj = np.in1d(metro_pinloc, fidspots_pinloc) metrology = self.metrology[jj] #- Sort so that they match each other fidspots.sort(keys=('LOCATION', 'PINHOLE_ID')) metrology.sort(keys=('LOCATION', 'PINHOLE_ID')) assert np.all(fidspots['LOCATION'] == metrology['LOCATION']) assert np.all(fidspots['PINHOLE_ID'] == metrology['PINHOLE_ID']) #- Get reduced coordinates rxpix, rypix = _reduce_xyfvc(fidspots['XPIX'], fidspots['YPIX']) rxfp, ryfp = _reduce_xyfp(metrology['X_FP'], metrology['Y_FP']) #- Perform fit #- Perform fit scale, rotation, offset_x, offset_y, zbpolids, zbcoeffs = \ fit_scale_rotation_offset(rxpix, rypix, rxfp, ryfp, fitzb=True) self.scale = scale self.rotation = rotation self.offset_x = offset_x self.offset_y = offset_y self.zbpolids = zbpolids self.zbcoeffs = zbcoeffs #- Goodness of fit xfp_fidmeas, yfp_fidmeas = self.fvc2fp(fidspots['XPIX'], fidspots['YPIX']) dx = (metrology['X_FP'] - xfp_fidmeas) dy = (metrology['Y_FP'] - yfp_fidmeas) dr = np.sqrt(dx**2 + dy**2) log.info( 'Mean, median, RMS distance = {:.1f}, {:.1f}, {:.1f} um'.format( 1000 * np.mean(dr), 1000 * np.median(dr), 1000 * np.sqrt(np.mean(dr**2)))) if update_spots: xfp_meas, yfp_meas = self.fvc2fp(spots['XPIX'], spots['YPIX']) spots["X_FP"] = xfp_meas spots["Y_FP"] = yfp_meas #- the metrology table is in a different order than the original #- spots table, which is also a superset of the fidicual spots #- matched to the metrology, so find the sorting of the metrology #- that will match the order that they appear in the spots table iifid = (spots['LOCATION'] > 0) & (spots['PINHOLE_ID'] > 0) fidspots_pinloc = (spots['LOCATION'] * 10 + spots['PINHOLE_ID'])[iifid] metro_pinloc = metrology['LOCATION'] * 10 + metrology['PINHOLE_ID'] ii = np.argsort(np.argsort(fidspots_pinloc)) jj = np.argsort(metro_pinloc) kk = jj[ii] #- Check that we got that dizzying array of argsorts right assert np.all( spots['LOCATION'][iifid] == metrology['LOCATION'][kk]) assert np.all( spots['PINHOLE_ID'][iifid] == metrology['PINHOLE_ID'][kk]) #- Update the spots table with metrology columns #- TODO: used masked arrays in addition to default=0 spots["X_FP_METRO"] = np.zeros(len(spots)) spots["Y_FP_METRO"] = np.zeros(len(spots)) spots["Z_FP_METRO"] = np.zeros(len(spots)) spots["X_FP_METRO"][iifid] = metrology['X_FP'][kk] spots["Y_FP_METRO"][iifid] = metrology['Y_FP'][kk] spots["Z_FP_METRO"][iifid] = metrology['Z_FP'][kk]
def fit(self, spots, metrology=None, update_spots=False, zbfit=True, fixed_scale=False, fixed_rotation=False): """ TODO: document """ log = get_logger() if metrology is not None: self.metrology = metrology else: self.metrology = load_metrology() #- Trim spots to just fiducial spots (not posioners, not unmatchs spots) ii = (spots['LOCATION'] >= 0) & (spots['PINHOLE_ID'] > 0) fidspots = spots[ii] #- trim metrology to just the ones that have spots fidspots_pinloc = fidspots['LOCATION'] * 10 + fidspots['PINHOLE_ID'] metro_pinloc = self.metrology['LOCATION'] * 10 + self.metrology[ 'PINHOLE_ID'] jj = np.in1d(metro_pinloc, fidspots_pinloc) metrology = self.metrology[jj] #- Sort so that they match each other fidspots.sort(keys=('LOCATION', 'PINHOLE_ID')) metrology.sort(keys=('LOCATION', 'PINHOLE_ID')) assert np.all(fidspots['LOCATION'] == metrology['LOCATION']) assert np.all(fidspots['PINHOLE_ID'] == metrology['PINHOLE_ID']) #- Get reduced coordinates rxpix, rypix = self._reduce_xyfvc(fidspots['XPIX'], fidspots['YPIX']) rxfp, ryfp = self._reduce_xyfp(metrology['X_FP'], metrology['Y_FP']) if fixed_rotation: fixed_rotation_value = self.rotation log.info( "Use fixed rotation = {:5.4f}".format(fixed_rotation_value)) else: fixed_rotation_value = None if fixed_scale: fixed_scale_value = self.scale log.info("Use fixed scale = {:5.4f}".format(fixed_scale_value)) else: fixed_scale_value = None res = fit_scale_rotation_offset(rxpix, rypix, rxfp, ryfp, fitzb=zbfit, zbpolids=self.zbpolids, zbcoeffs=self.zbcoeffs, fixed_scale=fixed_scale_value, fixed_rotation=fixed_rotation_value) self.scale = res[0] self.rotation = res[1] self.offset_x = res[2] self.offset_y = res[3] if zbfit: self.zbpolids = res[4] self.zbcoeffs = res[5] #- Goodness of fit xfp_fidmeas, yfp_fidmeas = self.fvc2fp(fidspots['XPIX'], fidspots['YPIX']) dx = (metrology['X_FP'] - xfp_fidmeas) dy = (metrology['Y_FP'] - yfp_fidmeas) dr = np.sqrt(dx**2 + dy**2) log.info( 'Mean, median, RMS distance = {:.1f}, {:.1f}, {:.1f} um'.format( 1000 * np.mean(dr), 1000 * np.median(dr), 1000 * np.sqrt(np.mean(dr**2)))) if update_spots: xfp_meas, yfp_meas = self.fvc2fp(spots['XPIX'], spots['YPIX']) spots["X_FP"] = xfp_meas spots["Y_FP"] = yfp_meas #- the metrology table is in a different order than the original #- spots table, which is also a superset of the fidicual spots #- matched to the metrology, so find the sorting of the metrology #- that will match the order that they appear in the spots table iifid = (spots['LOCATION'] > 0) & (spots['PINHOLE_ID'] > 0) fidspots_pinloc = (spots['LOCATION'] * 10 + spots['PINHOLE_ID'])[iifid] metro_pinloc = metrology['LOCATION'] * 10 + metrology['PINHOLE_ID'] ii = np.argsort(np.argsort(fidspots_pinloc)) jj = np.argsort(metro_pinloc) kk = jj[ii] #- Check that we got that dizzying array of argsorts right assert np.all( spots['LOCATION'][iifid] == metrology['LOCATION'][kk]) assert np.all( spots['PINHOLE_ID'][iifid] == metrology['PINHOLE_ID'][kk]) #- Update the spots table with metrology columns #- TODO: used masked arrays in addition to default=0 spots["X_FP_METRO"] = np.zeros(len(spots)) spots["Y_FP_METRO"] = np.zeros(len(spots)) spots["Z_FP_METRO"] = np.zeros(len(spots)) spots["X_FP_METRO"][iifid] = metrology['X_FP'][kk] spots["Y_FP_METRO"][iifid] = metrology['Y_FP'][kk] spots["Z_FP_METRO"][iifid] = metrology['Z_FP'][kk]