def load(self, filename): self.geometry = GeometryRefinement( np.zeros((2, 3)), dist=self.start_values['dist'], wavelength=self.start_values['wavelength'], pixel1=self.start_values['pixel_width'], pixel2=self.start_values['pixel_height']) self.geometry.load(filename) self.calibration_name = get_base_name(filename) self.is_calibrated = True
def __init__(self, img_model=None): """ :param img_model: :type img_model: ImgModel """ super(CalibrationModel, self).__init__() self.img_model = img_model self.points = [] self.points_index = [] self.detector = Detector(pixel1=79e-6, pixel2=79e-6) self.detector_mode = DetectorModes.CUSTOM self._original_detector = None # used for saving original state before rotating or flipping self.pattern_geometry = GeometryRefinement( detector=self.detector, wavelength=0.3344e-10, poni1=0, poni2=0) # default params are necessary, otherwise fails... self.pattern_geometry_img_shape = None self.cake_geometry = None self.cake_geometry_img_shape = None self.calibrant = Calibrant() self.orig_pixel1 = self.detector.pixel1 # needs to be extra stored for applying supersampling self.orig_pixel2 = self.detector.pixel2 self.start_values = { 'dist': 200e-3, 'wavelength': 0.3344e-10, 'polarization_factor': 0.99 } self.fit_wavelength = False self.fixed_values = { } # dictionary for fixed parameters during calibration (keys can be e.g. rot1, poni1 etc. # and values are the values to what the respective parameter will be set self.is_calibrated = False self.use_mask = False self.filename = '' self.calibration_name = 'None' self.polarization_factor = 0.99 self.supersampling_factor = 1 self.correct_solid_angle = True self._calibrants_working_dir = calibrants_path self.distortion_spline_filename = None self.tth = np.linspace(0, 25) self.int = np.sin(self.tth) self.num_points = len(self.int) self.cake_img = np.zeros((2048, 2048)) self.cake_tth = None self.cake_azi = None self.peak_search_algorithm = None
def calibrate(self): self.geometry = GeometryRefinement( self.create_point_array(self.points, self.points_index), dist=self.start_values['dist'], wavelength=self.start_values['wavelength'], pixel1=self.start_values['pixel_width'], pixel2=self.start_values['pixel_height'], calibrant=self.calibrant) self.refine() self.integrate() self.is_calibrated = True self.calibration_name = 'current'
def calibrate(self): self.prepare_parameters() self.orig_pixel1 = self.pixel_size self.orig_pixel2 = self.pixel_size self.pattern_geometry = GeometryRefinement(self.point_array, dist=self.distance, wavelength=self.wavelength, pixel1=self.pixel_size, pixel2=self.pixel_size, calibrant=self.calibrant) self.refine() self.create_cake_geometry() self.pattern_geometry.reset()
def __createGeoRefFromPeaks(self, peaks): """ Contains the geometry refinement part specific to Calibration Sets up the initial guess when starting pyFAI-calib """ fixed = pyFAI.utils.FixedParameters() fixed.add("wavelength") scores = [] PARAMETERS = ["dist", "poni1", "poni2", "rot1", "rot2", "rot3", "wavelength"] # First attempt defaults = self.__initGeoRef() geoRef = GeometryRefinement( data=peaks, wavelength=self.__wavelength, detector=self.__detector, calibrant=self.__calibrant, **defaults) geoRef.refine2(1000000, fix=fixed) score = geoRef.chi2() parameters = [getattr(geoRef, p) for p in PARAMETERS] scores.append((score, parameters)) # Second attempt defaults = self.__initGeoRef() geoRef = GeometryRefinement( data=peaks, wavelength=self.__wavelength, detector=self.__detector, calibrant=self.__calibrant, **defaults) geoRef.guess_poni() geoRef.refine2(1000000, fix=fixed) score = geoRef.chi2() parameters = [getattr(geoRef, p) for p in PARAMETERS] scores.append((score, parameters)) # Third attempt # FIXME use the geometry from the computed model # Choose the best scoring method: At this point we might also ask # a user to just type the numbers in? scores.sort() _score, parameters = scores[0] for parval, parname in zip(parameters, PARAMETERS): setattr(geoRef, parname, parval) return geoRef
def test_peakPicking(self): """first test peak-picking then checks the geometry found is OK""" for i in self.ctrlPt: pts = self.pp.massif.find_peaks(self.ctrlPt[i], stdout=open(self.logfile, "a")) logger.info("point %s at ring #%i (tth=%.1f deg) generated %i points", self.ctrlPt[i], i, self.tth[i], len(pts)) if len(pts) > 0: self.pp.points.append(pts, angle=self.tth[i], ring=i) else: logger.error("point %s caused error (%s) ", i, self.ctrlPt[i]) self.pp.points.save(self.nptfile) lstPeak = self.pp.points.getListRing() # print self.pp.points # print lstPeak logger.info("After peak-picking, we have %s points generated from %s groups ", len(lstPeak), len(self.ctrlPt)) gr = GeometryRefinement(lstPeak, dist=0.01, pixel1=1e-4, pixel2=1e-4, wavelength=self.wavelength, calibrant=self.calibrant) gr.guess_poni() logger.info(gr.__repr__()) last = sys.maxint for i in range(self.maxiter): delta2 = gr.refine2() logger.info(gr.__repr__()) if delta2 == last: logger.info("refinement finished after %s iteration" % i) break last = delta2 self.assertEquals(last < 1e-4, True, "residual error is less than 1e-4, got %s" % last) self.assertAlmostEquals(gr.dist, 0.1, 2, "distance is OK, got %s, expected 0.1" % gr.dist) self.assertAlmostEquals(gr.poni1, 3e-2, 2, "PONI1 is OK, got %s, expected 3e-2" % gr.poni1) self.assertAlmostEquals(gr.poni2, 3e-2, 2, "PONI2 is OK, got %s, expected 3e-2" % gr.poni2) self.assertAlmostEquals(gr.rot1, 0, 2, "rot1 is OK, got %s, expected 0" % gr.rot1) self.assertAlmostEquals(gr.rot2, 0, 2, "rot2 is OK, got %s, expected 0" % gr.rot2) self.assertAlmostEquals(gr.rot3, 0, 2, "rot3 is OK, got %s, expected 0" % gr.rot3)
def calibrate(self): self.reset_supersampling() self.pattern_geometry = GeometryRefinement( self.create_point_array(self.points, self.points_index), dist=self.start_values['dist'], wavelength=self.start_values['wavelength'], detector=self.detector, calibrant=self.calibrant, splineFile=self.distortion_spline_filename) self.refine() self.create_cake_geometry() self.is_calibrated = True self.calibration_name = 'current' self.set_supersampling() # reset the integrator (not the geometric parameters) self.pattern_geometry.reset()
def load(self, filename): self.geometry = GeometryRefinement(np.zeros((2, 3)), dist=self.start_values['dist'], wavelength=self.start_values['wavelength'], pixel1=self.start_values['pixel_width'], pixel2=self.start_values['pixel_height']) self.geometry.load(filename) self.calibration_name = get_base_name(filename) self.is_calibrated = True
def calibrate(self): self.geometry = GeometryRefinement(self.create_point_array(self.points, self.points_index), dist=self.start_values['dist'], wavelength=self.start_values['wavelength'], pixel1=self.start_values['pixel_width'], pixel2=self.start_values['pixel_height'], calibrant=self.calibrant) self.refine() self.integrate() self.is_calibrated = True self.calibration_name = 'current'
def __init(self, peaks, method): defaults = self.__initgeoRef() fixed = pyFAI.utils.FixedParameters() fixed.add("wavelength") geoRef = GeometryRefinement(data=peaks, wavelength=self.__wavelength, detector=self.__detector, calibrant=self.__calibrant, **defaults) geoRef.refine2(1000000, fix=fixed) peakPicker = PeakPicker(data=self.__image, calibrant=self.__calibrant, wavelength=self.__wavelength, detector=self.__detector, method=method) self.__peakPicker = peakPicker self.__geoRef = geoRef self.__fixed = fixed
def test_peakPicking(self): """first test peak-picking then checks the geometry found is OK""" for i in self.ctrlPt: pts = self.pp.massif.find_peaks(self.ctrlPt[i], stdout=open(self.logfile, "a")) logger.info("point %s at ring #%i (tth=%.1f deg) generated %i points", self.ctrlPt[i], i, self.tth[i], len(pts)) if len(pts) > 0: self.pp.points.append(pts, angle=self.tth[i], ring=i) else: logger.error("point %s caused error (%s) ", i, self.ctrlPt[i]) self.pp.points.save(self.nptfile) lstPeak = self.pp.points.getListRing() # print self.pp.points # print lstPeak logger.info("After peak-picking, we have %s points generated from %s groups ", len(lstPeak), len(self.ctrlPt)) gr = GeometryRefinement(lstPeak, dist=0.01, pixel1=1e-4, pixel2=1e-4, wavelength=self.wavelength, dSpacing=self.ds) gr.guess_poni() logger.info(gr.__repr__()) last = sys.maxint for i in range(self.maxiter): delta2 = gr.refine2() logger.info(gr.__repr__()) if delta2 == last: logger.info("refinement finished after %s iteration" % i) break last = delta2 self.assertEquals(last < 1e-4, True, "residual error is less than 1e-4, got %s" % last) self.assertAlmostEquals(gr.dist, 0.1, 2, "distance is OK, got %s, expected 0.1" % gr.dist) self.assertAlmostEquals(gr.poni1, 3e-2, 2, "PONI1 is OK, got %s, expected 3e-2" % gr.poni1) self.assertAlmostEquals(gr.poni2, 3e-2, 2, "PONI2 is OK, got %s, expected 3e-2" % gr.poni2) self.assertAlmostEquals(gr.rot1, 0, 2, "rot1 is OK, got %s, expected 0" % gr.rot1) self.assertAlmostEquals(gr.rot2, 0, 2, "rot2 is OK, got %s, expected 0" % gr.rot2) self.assertAlmostEquals(gr.rot3, 0, 2, "rot3 is OK, got %s, expected 0" % gr.rot3)
def __init(self, peaks, method): defaults = self.__initgeoRef() fixed = pyFAI.utils.FixedParameters() fixed.add("wavelength") geoRef = GeometryRefinement(data=peaks, wavelength=self.__wavelength, detector=self.__detector, calibrant=self.__calibrant, **defaults) self.__residual = geoRef.refine2(1000000, fix=fixed) self.__peakResidual = self.__residual self.__previousResidual = None peakPicker = PeakPicker(data=self.__image, calibrant=self.__calibrant, wavelength=self.__wavelength, detector=self.__detector, method=method) self.__peakPicker = peakPicker self.__geoRef = geoRef
def load(self, filename): """ Loads a calibration file and and sets all the calibration parameter. :param filename: filename for a *.poni calibration file """ self.pattern_geometry = GeometryRefinement( wavelength=0.3344e-10, detector=self.detector, poni1=0, poni2=0) # default params are necessary, otherwise fails... self.pattern_geometry.load(filename) self.orig_pixel1 = self.pattern_geometry.pixel1 self.orig_pixel2 = self.pattern_geometry.pixel2 if self.pattern_geometry.pixel1 == self.detector.pixel1 and \ self.pattern_geometry.pixel2 == self.detector.pixel2: self.pattern_geometry.detector = self.detector # necessary since loading a poni file will reset the detector else: self.reset_detector() self.calibration_name = get_base_name(filename) self.filename = filename self.is_calibrated = True self.create_cake_geometry() self.set_supersampling()
def __init__(self, img_data=None): self.img_data = img_data self.points = [] self.points_index = [] self.geometry = AzimuthalIntegrator() self.calibrant = Calibrant() self.start_values = {'dist': 200e-3, 'wavelength': 0.3344e-10, 'pixel_width': 79e-6, 'pixel_height': 79e-6, 'polarization_factor': 0.95} self.fit_wavelength = False self.is_calibrated = False self.use_mask = False self.calibration_name = 'None' self.polarization_factor = 0.95 self._calibrants_working_dir = os.path.dirname(Calibrants.__file__)
def calibrate(self): self.pattern_geometry = GeometryRefinement(self.create_point_array(self.points, self.points_index), dist=self.start_values['dist'], wavelength=self.start_values['wavelength'], pixel1=self.start_values['pixel_width'], pixel2=self.start_values['pixel_height'], calibrant=self.calibrant) self.orig_pixel1 = self.start_values['pixel_width'] self.orig_pixel2 = self.start_values['pixel_height'] self.refine() self.create_cake_geometry() self.is_calibrated = True self.calibration_name = 'current' self.set_supersampling() # reset the integrator (not the geometric parameters) self.pattern_geometry.reset()
def __init__(self, img_data=None): self.img_data = img_data self.points = [] self.points_index = [] self.geometry = AzimuthalIntegrator() self.calibrant = Calibrant() self.start_values = { 'dist': 200e-3, 'wavelength': 0.3344e-10, 'pixel_width': 79e-6, 'pixel_height': 79e-6, 'polarization_factor': 0.95 } self.fit_wavelength = False self.is_calibrated = False self.use_mask = False self.calibration_name = 'None' self.polarization_factor = 0.95 self._calibrants_working_dir = os.path.dirname(Calibrants.__file__)
def test_bug_1378(self): from ..detectors import Detector from ..calibrant import CalibrantFactory from pyFAI.geometryRefinement import GeometryRefinement calibrant_factory = CalibrantFactory() ceo2 = calibrant_factory("CeO2") img_shape = (280, 290) detector = Detector(100e-6, 110e-6) detector.max_shape = detector.shape = img_shape dx = dy = numpy.ones(shape=img_shape) detector.set_dx(dx) detector.set_dy(dy) pattern_geometry = GeometryRefinement([[1, 1, 0], [2, 1, 1]], dist=1, wavelength=0.3344e-10, detector=detector, calibrant=ceo2)
def addFile(self, filename): if filename in self.listFiles: return basename = os.path.splitext(filename)[0] if filename.endswith(".poni") and os.path.isfile(basename + ".py"): poni = filename pointFile = basename + ".py" elif filename.endswith(".py") and os.path.isfile(basename + ".poni"): poni = filename pointFile = basename + ".py" try: points = eval(open(pointFile).read().replace("data=", "")) except: logging.error("error in reading %s" % pointFile) return refinement = GeometryRefinement(points) refinement.load(poni) # print refinement self.listPoints.append(numpy.array(points).astype("float64")) self.listPoni.append(refinement.param) refinement.dist_min = 0.5 * refinement.dist refinement.dist_max = 2 * refinement.dist refinement.poni1_min = min(0.9 * refinement.poni1, 1.1 * refinement.poni1) refinement.poni1_max = max(0.9 * refinement.poni1, 1.1 * refinement.poni1) refinement.poni2_min = min(0.9 * refinement.poni2, 1.1 * refinement.poni2) refinement.poni2_max = max(0.9 * refinement.poni2, 1.1 * refinement.poni2) refinement.rot1_min = min(0.9 * refinement.rot1, 1.1 * refinement.rot1) refinement.rot1_max = max(0.9 * refinement.rot1, 1.1 * refinement.rot1) refinement.rot2_min = min(0.9 * refinement.rot2, 1.1 * refinement.rot2) refinement.rot2_max = max(0.9 * refinement.rot2, 1.1 * refinement.rot2) refinement.rot3_min = min(0.9 * refinement.rot3, 1.1 * refinement.rot3) refinement.rot3_max = max(0.9 * refinement.rot3, 1.1 * refinement.rot3) self.listRefiner.append(refinement) self.listFiles.append(poni) # self.listFiles.append(pointFile) self.param += refinement.param self.bounds += [(refinement.dist_min, refinement.dist_max), (refinement.poni1_min, refinement.poni1_max), (refinement.poni2_min, refinement.poni2_max), (refinement.rot1_min, refinement.rot1_max), (refinement.rot2_min, refinement.rot2_max), (refinement.rot3_min, refinement.rot3_max)]
class CalibrateDialog(BaseDialog): def __init__(self, parent=None): super(CalibrateDialog, self).__init__(parent) self.plotview = None self.data = None self.counts = None self.points = [] self.pattern_geometry = None self.cake_geometry = None self.is_calibrated = False cstr = str(ALL_CALIBRANTS) calibrants = sorted(cstr[cstr.index(':')+2:].split(', ')) self.parameters = GridParameters() self.parameters.add('calibrant', calibrants, 'Calibrant') self.parameters['calibrant'].value = 'CeO2' self.parameters.add('wavelength', 0.5, 'Wavelength (Ang)', False) self.parameters.add('distance', 100.0, 'Detector Distance (mm)', True) self.parameters.add('xc', 512, 'Beam Center - x', True) self.parameters.add('yc', 512, 'Beam Center - y', True) self.parameters.add('yaw', 0.0, 'Yaw (degrees)', True) self.parameters.add('pitch', 0.0, 'Pitch (degrees)', True) self.parameters.add('roll', 0.0, 'Roll (degrees)', True) self.parameters.add('search_size', 10, 'Search Size (pixels)') rings = ['Ring%s' % i for i in range(1,21)] self.rings_box = self.select_box(rings) self.set_layout(self.select_entry(self.choose_entry), self.action_buttons(('Plot Calibration', self.plot_data)), self.parameters.grid(header=False), self.make_layout( self.action_buttons(('Select Points', self.select)), self.rings_box), self.action_buttons(('Calibrate', self.calibrate), ('Plot Cake', self.plot_cake), ('Restore', self.restore_parameters), ('Save', self.save_parameters)), self.close_buttons(close=True)) self.set_title('Calibrating Powder') def choose_entry(self): if 'calibration' not in self.entry['instrument']: raise NeXusError('Please load calibration data to this entry') self.update_parameters() self.plot_data() def update_parameters(self): self.parameters['wavelength'].value = self.entry['instrument/monochromator/wavelength'] detector = self.entry['instrument/detector'] self.parameters['distance'].value = detector['distance'] self.parameters['yaw'].value = detector['yaw'] self.parameters['pitch'].value = detector['pitch'] self.parameters['roll'].value = detector['roll'] if 'beam_center_x' in detector: self.parameters['xc'].value = detector['beam_center_x'] if 'beam_center_y' in detector: self.parameters['yc'].value = detector['beam_center_y'] self.data = self.entry['instrument/calibration'] self.counts = self.data.nxsignal.nxvalue @property def search_size(self): return int(self.parameters['search_size'].value) @property def ring(self): return int(self.rings_box.currentText()[4:]) - 1 @property def ring_color(self): colors = ['r', 'b', 'g', 'c', 'm'] * 4 return colors[self.ring] def plot_data(self): if self.plotview is None: if 'Powder Calibration' in plotviews: self.plotview = plotviews['Powder Calibration'] else: self.plotview = NXPlotView('Powder Calibration') self.plotview.plot(self.data, log=True) self.plotview.aspect='equal' self.plotview.ytab.flipped = True self.clear_peaks() def on_button_press(self, event): self.plotview.make_active() if event.inaxes: self.xp, self.yp = event.x, event.y else: self.xp, self.yp = 0, 0 def on_button_release(self, event): if event.inaxes: if abs(event.x - self.xp) > 5 or abs(event.y - self.yp) > 5: return x, y = self.plotview.inverse_transform(event.xdata, event.ydata) for i, point in enumerate(self.points): circle = point[0] if circle.contains_point(self.plotview.ax.transData.transform((x,y))): circle.remove() for circle in point[2]: circle.remove() del self.points[i] return idx, idy = self.find_peak(x, y) points = [(idy, idx)] circles = [] massif = Massif(self.counts) extra_points = massif.find_peaks((idy, idx)) for point in extra_points: points.append(point) circles.append(self.circle(point[1], point[0], alpha=0.3)) self.points.append([self.circle(idx, idy), points, circles, self.ring]) def circle(self, idx, idy, alpha=1.0): return self.plotview.circle(idx, idy, self.search_size, facecolor=self.ring_color, edgecolor='k', alpha=alpha) def select(self): self.plotview.cidpress = self.plotview.mpl_connect( 'button_press_event', self.on_button_press) self.plotview.cidrelease = self.plotview.mpl_connect( 'button_release_event', self.on_button_release) def find_peak(self, x, y): s = self.search_size left = int(np.round(x - s * 0.5)) if left < 0: left = 0 top = int(np.round(y - s * 0.5)) if top < 0: top = 0 region = self.counts[top:(top+s),left:(left+s)] idy, idx = np.where(region == region.max()) idx = left + idx[0] idy = top + idy[0] return idx, idy def clear_peaks(self): self.points = [] @property def calibrant(self): return ALL_CALIBRANTS[self.parameters['calibrant'].value] @property def point_array(self): points = [] for point in self.points: for p in point[1]: points.append((p[0], p[1], point[3])) return np.array(points) def prepare_parameters(self): self.parameters.set_parameters() self.wavelength = self.parameters['wavelength'].value * 1e-10 self.distance = self.parameters['distance'].value * 1e-3 self.yaw = np.radians(self.parameters['yaw'].value) self.pitch = np.radians(self.parameters['pitch'].value) self.roll = np.radians(self.parameters['roll'].value) self.pixel_size = self.entry['instrument/detector/pixel_size'].nxvalue * 1e-3 self.xc = self.parameters['xc'].value self.yc = self.parameters['yc'].value def calibrate(self): self.prepare_parameters() self.orig_pixel1 = self.pixel_size self.orig_pixel2 = self.pixel_size self.pattern_geometry = GeometryRefinement(self.point_array, dist=self.distance, wavelength=self.wavelength, pixel1=self.pixel_size, pixel2=self.pixel_size, calibrant=self.calibrant) self.refine() self.create_cake_geometry() self.pattern_geometry.reset() def refine(self): self.pattern_geometry.data = self.point_array if self.parameters['wavelength'].vary: self.pattern_geometry.refine2() fix = [] else: fix = ['wavelength'] if not self.parameters['distance'].vary: fix.append('dist') self.pattern_geometry.refine2_wavelength(fix=fix) self.read_parameters() self.is_calibrated = True self.create_cake_geometry() self.pattern_geometry.reset() def create_cake_geometry(self): self.cake_geometry = AzimuthalIntegrator() pyFAI_parameter = self.pattern_geometry.getPyFAI() pyFAI_parameter['wavelength'] = self.pattern_geometry.wavelength self.cake_geometry.setPyFAI(dist=pyFAI_parameter['dist'], poni1=pyFAI_parameter['poni1'], poni2=pyFAI_parameter['poni2'], rot1=pyFAI_parameter['rot1'], rot2=pyFAI_parameter['rot2'], rot3=pyFAI_parameter['rot3'], pixel1=pyFAI_parameter['pixel1'], pixel2=pyFAI_parameter['pixel2']) self.cake_geometry.wavelength = pyFAI_parameter['wavelength'] def plot_cake(self): if 'Cake Plot' in plotviews: plotview = plotviews['Cake Plot'] else: plotview = NXPlotView('Cake Plot') if not self.is_calibrated: raise NeXusError('No refinement performed') res = self.cake_geometry.integrate2d(self.counts, 1024, 1024, method='csr', unit='2th_deg', correctSolidAngle=True) self.cake_data = NXdata(res[0], (NXfield(res[2], name='azimumthal_angle'), NXfield(res[1], name='polar_angle'))) self.cake_data['title'] = self.entry['instrument/calibration/title'] plotview.plot(self.cake_data, log=True) wavelength = self.parameters['wavelength'].value polar_angles = [2 * np.degrees(np.arcsin(wavelength/(2*d))) for d in self.calibrant.dSpacing] plotview.vlines([polar_angle for polar_angle in polar_angles if polar_angle < plotview.xaxis.max], linestyle=':', color='r') def read_parameters(self): pyFAI = self.pattern_geometry.getPyFAI() fit2d = self.pattern_geometry.getFit2D() self.parameters['wavelength'].value = self.pattern_geometry.wavelength * 1e10 self.parameters['distance'].value = pyFAI['dist'] * 1e3 self.parameters['yaw'].value = np.degrees(pyFAI['rot1']) self.parameters['pitch'].value = np.degrees(pyFAI['rot2']) self.parameters['roll'].value = np.degrees(pyFAI['rot3']) self.parameters['xc'].value = fit2d['centerX'] self.parameters['yc'].value = fit2d['centerY'] def restore_parameters(self): self.parameters.restore_parameters() def save_parameters(self): if not self.is_calibrated: raise NeXusError('No refinement performed') elif 'refinement' in self.entry['instrument/calibration']: if confirm_action('Overwrite previous refinement?'): del self.entry['instrument/calibration/refinement'] else: return self.entry['instrument/calibration/calibrant'] = self.parameters['calibrant'].value process = NXprocess() process.program = 'pyFAI' process.version = pyFAI.version process.parameters = NXcollection() process.parameters['Detector'] = self.entry['instrument/detector/description'] pyFAI_parameter = self.pattern_geometry.getPyFAI() process.parameters['PixelSize1'] = pyFAI_parameter['pixel1'] process.parameters['PixelSize2'] = pyFAI_parameter['pixel2'] process.parameters['Distance'] = pyFAI_parameter['dist'] process.parameters['Poni1'] = pyFAI_parameter['poni1'] process.parameters['Poni2'] = pyFAI_parameter['poni2'] process.parameters['Rot1'] = pyFAI_parameter['rot1'] process.parameters['Rot2'] = pyFAI_parameter['rot2'] process.parameters['Rot3'] = pyFAI_parameter['rot3'] process.parameters['Wavelength'] = pyFAI_parameter['wavelength'] self.entry['instrument/calibration/refinement'] = process self.entry['instrument/monochromator/wavelength'] = self.parameters['wavelength'].value self.entry['instrument/monochromator/energy'] = 12.398419739640717 / self.parameters['wavelength'].value detector = self.entry['instrument/detector'] detector['distance'] = self.parameters['distance'].value detector['yaw'] = self.parameters['yaw'].value detector['pitch'] = self.parameters['pitch'].value detector['roll'] = self.parameters['roll'].value detector['beam_center_x'] = self.parameters['xc'].value detector['beam_center_y'] = self.parameters['yc'].value def reject(self): super(CalibrateDialog, self).reject() if 'Powder Calibration' in plotviews: plotviews['Powder Calibration'].close_view() if 'Cake Plot' in plotviews: plotviews['Cake Plot'].close_view()
class CalibrateDialog(NXDialog): def __init__(self, parent=None): super().__init__(parent) self.plotview = None self.data = None self.counts = None self.points = [] self.pattern_geometry = None self.cake_geometry = None self.polarization = None self.is_calibrated = False self.phi_max = -np.pi cstr = str(ALL_CALIBRANTS) calibrants = sorted(cstr[cstr.index(':')+2:].split(', ')) self.parameters = GridParameters() self.parameters.add('calibrant', calibrants, 'Calibrant') self.parameters['calibrant'].value = 'CeO2' self.parameters.add('wavelength', 0.5, 'Wavelength (Ang)', False) self.parameters.add('distance', 100.0, 'Detector Distance (mm)', True) self.parameters.add('xc', 512, 'Beam Center - x', True) self.parameters.add('yc', 512, 'Beam Center - y', True) self.parameters.add('yaw', 0.0, 'Yaw (degrees)', True) self.parameters.add('pitch', 0.0, 'Pitch (degrees)', True) self.parameters.add('roll', 0.0, 'Roll (degrees)', True) self.parameters.add('search_size', 10, 'Search Size (pixels)') self.rings_box = self.select_box([f'Ring{i}' for i in range(1, 21)]) self.set_layout(self.select_entry(self.choose_entry), self.progress_layout(close=True)) self.set_title('Calibrating Powder') def choose_file(self): super().choose_file() powder_file = self.get_filename() if powder_file: self.data = load_image(powder_file) self.counts = self.data.nxsignal.nxvalue self.plot_data() def choose_entry(self): if self.layout.count() == 2: self.insert_layout( 1, self.filebox('Choose Powder Calibration File')) self.insert_layout(2, self.parameters.grid(header=False)) self.insert_layout( 3, self.action_buttons(('Select Points', self.select), ('Autogenerate Rings', self.auto), ('Clear Points', self.clear_points))) self.insert_layout(4, self.make_layout(self.rings_box)) self.insert_layout( 5, self.action_buttons(('Calibrate', self.calibrate), ('Plot Cake', self.plot_cake), ('Restore', self.restore_parameters), ('Save', self.save_parameters))) self.parameters['wavelength'].value = ( self.entry['instrument/monochromator/wavelength']) detector = self.entry['instrument/detector'] self.parameters['distance'].value = detector['distance'] self.parameters['yaw'].value = detector['yaw'] self.parameters['pitch'].value = detector['pitch'] self.parameters['roll'].value = detector['roll'] if 'beam_center_x' in detector: self.parameters['xc'].value = detector['beam_center_x'] if 'beam_center_y' in detector: self.parameters['yc'].value = detector['beam_center_y'] self.pixel_size = ( self.entry['instrument/detector/pixel_size'].nxvalue * 1e-3) self.pixel_mask = self.entry['instrument/detector/pixel_mask'].nxvalue self.ring = self.selected_ring if 'calibration' in self.entry['instrument']: self.data = self.entry['instrument/calibration'] self.counts = self.data.nxsignal.nxvalue self.plot_data() else: self.close_plots() @property def search_size(self): return int(self.parameters['search_size'].value) @property def selected_ring(self): return int(self.rings_box.currentText()[4:]) - 1 @property def ring_color(self): colors = ['r', 'b', 'g', 'c', 'm'] * 4 return colors[self.ring] def plot_data(self): if self.plotview is None: if 'Powder Calibration' in plotviews: self.plotview = plotviews['Powder Calibration'] else: self.plotview = NXPlotView('Powder Calibration') self.plotview.plot(self.data, log=True) self.plotview.aspect = 'equal' self.plotview.ytab.flipped = True self.clear_points() def on_button_press(self, event): self.plotview.make_active() if event.inaxes: self.xp, self.yp = event.x, event.y else: self.xp, self.yp = 0, 0 def on_button_release(self, event): self.ring = self.selected_ring if event.inaxes: if abs(event.x - self.xp) > 5 or abs(event.y - self.yp) > 5: return x, y = self.plotview.inverse_transform(event.xdata, event.ydata) for i, point in enumerate(self.points): circle = point[0] if circle.shape.contains_point( self.plotview.ax.transData.transform((x, y))): circle.remove() for circle in point[2]: circle.remove() del self.points[i] return self.add_points(x, y) def circle(self, idx, idy, alpha=1.0): return self.plotview.circle(idx, idy, self.search_size, facecolor=self.ring_color, edgecolor='k', alpha=alpha) def select(self): self.plotview.cidpress = self.plotview.mpl_connect( 'button_press_event', self.on_button_press) self.plotview.cidrelease = self.plotview.mpl_connect( 'button_release_event', self.on_button_release) def auto(self): xc, yc = self.parameters['xc'].value, self.parameters['yc'].value wavelength = self.parameters['wavelength'].value distance = self.parameters['distance'].value * 1e-3 self.start_progress((0, self.selected_ring+1)) for ring in range(self.selected_ring+1): self.update_progress(ring) if len([p for p in self.points if p[3] == ring]) > 0: continue self.ring = ring theta = 2 * np.arcsin(wavelength / (2*self.calibrant.dSpacing[ring])) r = distance * np.tan(theta) / self.pixel_size phi = self.phi_max = -np.pi while phi < np.pi: x, y = np.int(xc + r*np.cos(phi)), np.int(yc + r*np.sin(phi)) if ((x > 0 and x < self.data.x.max()) and (y > 0 and y < self.data.y.max()) and not self.pixel_mask[y, x]): self.add_points(x, y, phi) phi = self.phi_max + 0.2 else: phi = phi + 0.2 self.stop_progress() def add_points(self, x, y, phi=0.0): xc, yc = self.parameters['xc'].value, self.parameters['yc'].value idx, idy = self.find_peak(x, y) points = [(idy, idx)] circles = [] massif = Massif(self.counts) extra_points = massif.find_peaks((idy, idx)) for point in extra_points: points.append(point) circles.append(self.circle(point[1], point[0], alpha=0.3)) phis = np.array([np.arctan2(p[0]-yc, p[1]-xc) for p in points]) if phi < -0.5*np.pi: phis[np.where(phis > 0.0)] -= 2 * np.pi self.phi_max = max(*phis, self.phi_max) self.points.append([self.circle(idx, idy), points, circles, self.ring]) def find_peak(self, x, y): s = self.search_size left = int(np.round(x - s * 0.5)) if left < 0: left = 0 top = int(np.round(y - s * 0.5)) if top < 0: top = 0 region = self.counts[top:(top+s), left:(left+s)] idy, idx = np.where(region == region.max()) idx = left + idx[0] idy = top + idy[0] return idx, idy def clear_points(self): for i, point in enumerate(self.points): circle = point[0] circle.remove() for circle in point[2]: circle.remove() self.points = [] @property def calibrant(self): return ALL_CALIBRANTS[self.parameters['calibrant'].value] @property def point_array(self): points = [] for point in self.points: for p in point[1]: points.append((p[0], p[1], point[3])) return np.array(points) def prepare_parameters(self): self.parameters.set_parameters() self.wavelength = self.parameters['wavelength'].value * 1e-10 self.distance = self.parameters['distance'].value * 1e-3 self.yaw = np.radians(self.parameters['yaw'].value) self.pitch = np.radians(self.parameters['pitch'].value) self.roll = np.radians(self.parameters['roll'].value) self.xc = self.parameters['xc'].value self.yc = self.parameters['yc'].value def calibrate(self): self.prepare_parameters() self.orig_pixel1 = self.pixel_size self.orig_pixel2 = self.pixel_size self.pattern_geometry = GeometryRefinement(self.point_array, dist=self.distance, wavelength=self.wavelength, pixel1=self.pixel_size, pixel2=self.pixel_size, calibrant=self.calibrant) self.refine() self.create_cake_geometry() self.pattern_geometry.reset() def refine(self): self.pattern_geometry.data = self.point_array if self.parameters['wavelength'].vary: self.pattern_geometry.refine2() fix = [] else: fix = ['wavelength'] if not self.parameters['distance'].vary: fix.append('dist') self.pattern_geometry.refine2_wavelength(fix=fix) self.read_parameters() self.is_calibrated = True self.create_cake_geometry() self.pattern_geometry.reset() def create_cake_geometry(self): self.cake_geometry = AzimuthalIntegrator() pyFAI_parameter = self.pattern_geometry.getPyFAI() pyFAI_parameter['wavelength'] = self.pattern_geometry.wavelength self.cake_geometry.setPyFAI(dist=pyFAI_parameter['dist'], poni1=pyFAI_parameter['poni1'], poni2=pyFAI_parameter['poni2'], rot1=pyFAI_parameter['rot1'], rot2=pyFAI_parameter['rot2'], rot3=pyFAI_parameter['rot3'], pixel1=pyFAI_parameter['pixel1'], pixel2=pyFAI_parameter['pixel2']) self.cake_geometry.wavelength = pyFAI_parameter['wavelength'] def plot_cake(self): if 'Cake Plot' in plotviews: plotview = plotviews['Cake Plot'] else: plotview = NXPlotView('Cake Plot') if not self.is_calibrated: raise NeXusError('No refinement performed') res = self.cake_geometry.integrate2d(self.counts, 1024, 1024, method='csr', unit='2th_deg', correctSolidAngle=True) self.cake_data = NXdata(res[0], (NXfield(res[2], name='azimumthal_angle'), NXfield(res[1], name='polar_angle'))) self.cake_data['title'] = 'Cake Plot' plotview.plot(self.cake_data, log=True) wavelength = self.parameters['wavelength'].value polar_angles = [2 * np.degrees(np.arcsin(wavelength/(2*d))) for d in self.calibrant.dSpacing] plotview.vlines([polar_angle for polar_angle in polar_angles if polar_angle < plotview.xaxis.max], linestyle=':', color='r') def read_parameters(self): pyFAI = self.pattern_geometry.getPyFAI() fit2d = self.pattern_geometry.getFit2D() self.parameters['wavelength'].value = ( self.pattern_geometry.wavelength * 1e10) self.parameters['distance'].value = pyFAI['dist'] * 1e3 self.parameters['yaw'].value = np.degrees(pyFAI['rot1']) self.parameters['pitch'].value = np.degrees(pyFAI['rot2']) self.parameters['roll'].value = np.degrees(pyFAI['rot3']) self.parameters['xc'].value = fit2d['centerX'] self.parameters['yc'].value = fit2d['centerY'] def restore_parameters(self): self.parameters.restore_parameters() def save_parameters(self): if not self.is_calibrated: raise NeXusError('No refinement performed') elif 'calibration' in self.entry['instrument']: if confirm_action( "Do you want to overwrite existing calibration data?"): del self.entry['instrument/calibration'] else: return self.entry['instrument/calibration'] = self.data if 'refinement' in self.entry['instrument/calibration']: if confirm_action('Overwrite previous refinement?'): del self.entry['instrument/calibration/refinement'] else: return self.entry['instrument/calibration/calibrant'] = ( self.parameters['calibrant'].value) process = NXprocess() process.program = 'pyFAI' process.version = pyFAI.version process.parameters = NXcollection() process.parameters['Detector'] = ( self.entry['instrument/detector/description']) pyFAI_parameter = self.pattern_geometry.getPyFAI() process.parameters['PixelSize1'] = pyFAI_parameter['pixel1'] process.parameters['PixelSize2'] = pyFAI_parameter['pixel2'] process.parameters['Distance'] = pyFAI_parameter['dist'] process.parameters['Poni1'] = pyFAI_parameter['poni1'] process.parameters['Poni2'] = pyFAI_parameter['poni2'] process.parameters['Rot1'] = pyFAI_parameter['rot1'] process.parameters['Rot2'] = pyFAI_parameter['rot2'] process.parameters['Rot3'] = pyFAI_parameter['rot3'] process.parameters['Wavelength'] = pyFAI_parameter['wavelength'] self.entry['instrument/calibration/refinement'] = process self.entry['instrument/monochromator/wavelength'] = ( self.parameters['wavelength'].value) self.entry['instrument/monochromator/energy'] = ( 12.398419739640717 / self.parameters['wavelength'].value) detector = self.entry['instrument/detector'] detector['distance'] = self.parameters['distance'].value detector['yaw'] = self.parameters['yaw'].value detector['pitch'] = self.parameters['pitch'].value detector['roll'] = self.parameters['roll'].value detector['beam_center_x'] = self.parameters['xc'].value detector['beam_center_y'] = self.parameters['yc'].value try: detector['polarization'] = self.pattern_geometry.polarization( factor=0.99, shape=detector['mask'].shape) except Exception: pass def close_plots(self): if 'Powder Calibration' in plotviews: plotviews['Powder Calibration'].close() if 'Cake Plot' in plotviews: plotviews['Cake Plot'].close() def closeEvent(self, event): self.close_plots() event.accept() def accept(self): super().accept() self.close_plots() def reject(self): super().reject() self.close_plots()
def test_Spline(self): """tests geometric refinements with spline""" splineFine = os.path.join(os.path.dirname(__file__), "example.sp") data = [ [795, 288, 0.3490658503988659], [890, 260, 0.3490658503988659], [948, 249, 0.3490658503988659], [710, 325, 0.3490658503988659], [601, 392, 0.3490658503988659], [1167, 248, 0.3490658503988659], [1200, 340, 0.3490658503988659], [1319, 285, 0.3490658503988659], [1362, 302, 0.3490658503988659], [1436, 338, 0.3490658503988659], [1526, 397, 0.3490658503988659], [1560, 424, 0.3490658503988659], [1615, 476, 0.3490658503988659], [1662, 529, 0.3490658503988659], [1742, 650, 0.3490658503988659], [1778, 727, 0.3490658503988659], [1824, 891, 0.3490658503988659], [1831, 947, 0.3490658503988659], [1832, 1063, 0.3490658503988659], [1828, 1106, 0.3490658503988659], [1828, 1106, 0.3490658503988659], [1810, 1202, 0.3490658503988659], [1775, 1307, 0.3490658503988659], [1724, 1407, 0.3490658503988659], [1655, 1502, 0.3490658503988659], [1489, 1649, 0.3490658503988659], [1397, 1700, 0.3490658503988659], [1251, 1752, 0.3490658503988659], [1126, 1772, 0.3490658503988659], [984, 1770, 0.3490658503988659], [907, 1758, 0.3490658503988659], [801, 1728, 0.3490658503988659], [696, 1681, 0.3490658503988659], [634, 1644, 0.3490658503988659], [568, 1596, 0.3490658503988659], [520, 1553, 0.3490658503988659], [453, 1479, 0.3490658503988659], [403, 1408, 0.3490658503988659], [403, 1408, 0.3490658503988659], [363, 1337, 0.3490658503988659], [320, 1228, 0.3490658503988659], [303, 1161, 0.3490658503988659], [287, 1023, 0.3490658503988659], [287, 993, 0.3490658503988659], [304, 846, 0.3490658503988659], [329, 758, 0.3490658503988659], [341, 726, 0.3490658503988659], [402, 606, 0.3490658503988659], [437, 555, 0.3490658503988659], [513, 467, 0.3490658503988659] ] # data = numpy.array(data) # let's sheat ... 0.34 as int is 0 tth = data[0][2] # data[:, 2] = ring wl = 2e-10 * numpy.sin(tth / 2.0) ds = [1.0] # print tth, wl, ds, 2 * ds[0] * numpy.sin(tth / 2) r2 = GeometryRefinement(data, dist=0.1, splineFile=splineFine, wavelength=wl, dSpacing=ds) # r2.poni1 = 5e-2 # r2.poni2 = 5e-2 r2.rot1_max = 0 r2.rot1_min = -0 r2.rot2_max = 0 r2.rot2_min = -0 r2.rot3_max = 0.1 r2.rot3_min = -0.1 r2.refine2(10000000) ref2 = numpy.array([0.1, 4.917310e-02, 4.722438e-02, 0, 0., 0.00000]) # print "ref", ref2 # print "obt", r2.param for i, key in enumerate( ("dist", "poni1", "poni2", "rot1", "rot2", "rot3")): self.assertAlmostEqual( ref2[i], r2.__getattribute__(key), 3, "%s is %s, I expected %s%s%s" % (key, r2.__getattribute__(key), ref2[i], os.linesep, r2))
p.append([141, 2676, 4]) p.append([712, 2998, 4]) p.append([2018, 3270, 4]) p.append([112, 3290, 5]) p.append([1010, 3666, 5]) p.append([1843, 3800, 5]) p.append([127, 3666, 6]) p.append([707, 3905, 6]) p.append([1431, 4081, 6]) pts = np.array(p, dtype="float64") geo_ref = GeometryRefinement(data=pts, dist=d, poni1=p1, poni2=p2, rot1=r1, rot2=r2, rot3=r3, detector=det, wavelength=wl, calibrant=cal) geo_ref.refine2() # generate new .poni file with open(poni_file, "w") as poni_f: poni_f.write("# Calibration done " + str(datetime.datetime.now()) + "\n") poni_f.write("PixelSize1: " + str(geo_ref.pixel1) + "\n") poni_f.write("PixelSize2: " + str(geo_ref.pixel2) + "\n") poni_f.write("Distance: " + str(geo_ref.dist) + "\n") poni_f.write("Poni1: " + str(geo_ref.poni1) + "\n") poni_f.write("Poni2: " + str(geo_ref.poni2) + "\n")
class CalibrationData(object): def __init__(self, img_data=None): self.img_data = img_data self.points = [] self.points_index = [] self.geometry = AzimuthalIntegrator() self.geometry.set_wavelength(0.3344e-10) self.calibrant = Calibrant() self.start_values = { 'dist': 200e-3, 'wavelength': 0.3344e-10, 'pixel_width': 79e-6, 'pixel_height': 79e-6, 'polarization_factor': 0.95 } self.fit_wavelength = False self.is_calibrated = False self.use_mask = False self.calibration_name = 'None' self.polarization_factor = 0.95 self._calibrants_working_dir = 'ExampleData/Calibrants' def find_peaks_automatic(self, x, y, peak_ind): massif = Massif(self.img_data.img_data) cur_peak_points = massif.find_peaks([x, y]) if len(cur_peak_points): self.points.append(np.array(cur_peak_points)) self.points_index.append(peak_ind) return np.array(cur_peak_points) def find_peak(self, x, y, search_size, peak_ind): left_ind = np.round(x - search_size * 0.5) top_ind = np.round(y - search_size * 0.5) x_ind, y_ind = np.where(self.img_data.img_data[left_ind:(left_ind + search_size), top_ind:(top_ind + search_size)] == \ self.img_data.img_data[left_ind:(left_ind + search_size), top_ind:(top_ind + search_size)].max()) x_ind = x_ind[0] + left_ind y_ind = y_ind[0] + top_ind self.points.append(np.array([x_ind, y_ind])) self.points_index.append(peak_ind) return np.array([np.array((x_ind, y_ind))]) def clear_peaks(self): self.points = [] self.points_index = [] def search_peaks_on_ring(self, peak_index, delta_tth=0.1, algorithm='Massif', min_mean_factor=1, upper_limit=55000): if not self.is_calibrated: return #transform delta from degree into radians delta_tth = delta_tth / 180.0 * np.pi # get appropiate two theta value for the ring number tth_calibrant_list = self.calibrant.get_2th() tth_calibrant = np.float(tth_calibrant_list[peak_index]) print tth_calibrant # get the calculated two theta values for the whole image if self.geometry._ttha is None: tth_array = self.geometry.twoThetaArray( self.img_data.img_data.shape) else: tth_array = self.geometry._ttha # create mask based on two_theta position mask = abs(tth_array - tth_calibrant) <= delta_tth # init the peak search algorithm if algorithm == 'Massif': peak_search_algorithm = Massif(self.img_data.img_data) elif algorithm == 'Blob': peak_search_algorithm = BlobDetection(self.img_data.img_data * mask) peak_search_algorithm.process() else: return # calculate the mean and standard deviation of this area sub_data = np.array(self.img_data.img_data.ravel()[np.where( mask.ravel())], dtype=np.float64) sub_data[np.where(sub_data > upper_limit)] = np.NaN mean = np.nanmean(sub_data) std = np.nanstd(sub_data) # set the threshold into the mask (don't detect very low intensity peaks) threshold = min_mean_factor * mean + std mask2 = np.logical_and(self.img_data.img_data > threshold, mask) mask2[np.where(self.img_data.img_data > upper_limit)] = False size2 = mask2.sum(dtype=int) keep = int(np.ceil(np.sqrt(size2))) try: res = peak_search_algorithm.peaks_from_area(mask2, Imin=mean - std, keep=keep) except IndexError: res = [] # Store the result if len(res): self.points.append(np.array(res)) self.points_index.append(peak_index) def set_calibrant(self, filename): self.calibrant = Calibrant() self.calibrant.load_file(filename) self.geometry.calibrant = self.calibrant def set_start_values(self, start_values): self.start_values = start_values self.polarization_factor = start_values['polarization_factor'] def calibrate(self): self.geometry = GeometryRefinement( self.create_point_array(self.points, self.points_index), dist=self.start_values['dist'], wavelength=self.start_values['wavelength'], pixel1=self.start_values['pixel_width'], pixel2=self.start_values['pixel_height'], calibrant=self.calibrant) self.refine() self.integrate() self.is_calibrated = True self.calibration_name = 'current' def refine(self): self.geometry.data = self.create_point_array(self.points, self.points_index) self.geometry.refine2() if self.fit_wavelength: self.geometry.refine2_wavelength(fix=[]) def integrate(self): self.integrate_1d() self.integrate_2d() def integrate_1d(self, num_points=1400, mask=None, polarization_factor=None, filename=None, unit='2th_deg'): if polarization_factor is None: polarization_factor = self.polarization_factor if unit is 'd_A': self.tth, self.int = self.geometry.integrate1d( self.img_data.img_data, num_points, method='lut', unit='2th_deg', mask=mask, polarization_factor=polarization_factor, filename=filename) ind = np.where(self.tth > 0) self.tth = self.geometry.wavelength / ( 2 * np.sin(self.tth[ind] / 360 * np.pi)) * 1e10 self.int = self.int[ind] else: self.tth, self.int = self.geometry.integrate1d( self.img_data.img_data, num_points, method='lut', unit=unit, mask=mask, polarization_factor=polarization_factor, filename=filename) return self.tth, self.int def integrate_2d(self, mask=None, polarization_factor=None, unit='2th_deg'): if polarization_factor is None: polarization_factor = self.polarization_factor res = self.geometry.integrate2d( self.img_data.img_data, 2024, 2024, method='lut', mask=mask, unit=unit, polarization_factor=polarization_factor) self.cake_img = res[0] self.cake_tth = res[1] self.cake_azi = res[2] return self.cake_img def create_point_array(self, points, points_ind): res = [] for i, point_list in enumerate(points): if point_list.shape == (2, ): res.append([point_list[0], point_list[1], points_ind[i]]) else: for point in point_list: res.append([point[0], point[1], points_ind[i]]) return np.array(res) def get_point_array(self): return self.create_point_array(self.points, self.points_index) def get_calibration_parameter(self): pyFAI_parameter = self.geometry.getPyFAI() pyFAI_parameter['polarization_factor'] = self.polarization_factor try: fit2d_parameter = self.geometry.getFit2D() fit2d_parameter['polarization_factor'] = self.polarization_factor except TypeError: fit2d_parameter = None try: pyFAI_parameter['wavelength'] = self.geometry.wavelength fit2d_parameter['wavelength'] = self.geometry.wavelength except RuntimeWarning: pyFAI_parameter['wavelength'] = 0 return pyFAI_parameter, fit2d_parameter def load(self, filename): self.geometry = GeometryRefinement( np.zeros((2, 3)), dist=self.start_values['dist'], wavelength=self.start_values['wavelength'], pixel1=self.start_values['pixel_width'], pixel2=self.start_values['pixel_height'], calibrant=self.calibrant) self.geometry.load(filename) self.calibration_name = get_base_name(filename) self.is_calibrated = True def save(self, filename): self.geometry.save(filename) self.calibration_name = get_base_name(filename)
class CalibrationModel(QtCore.QObject): detector_reset = QtCore.Signal() def __init__(self, img_model=None): """ :param img_model: :type img_model: ImgModel """ super(CalibrationModel, self).__init__() self.img_model = img_model self.points = [] self.points_index = [] self.detector = Detector(pixel1=79e-6, pixel2=79e-6) self.detector_mode = DetectorModes.CUSTOM self._original_detector = None # used for saving original state before rotating or flipping self.pattern_geometry = GeometryRefinement( detector=self.detector, wavelength=0.3344e-10, poni1=0, poni2=0) # default params are necessary, otherwise fails... self.pattern_geometry_img_shape = None self.cake_geometry = None self.cake_geometry_img_shape = None self.calibrant = Calibrant() self.orig_pixel1 = self.detector.pixel1 # needs to be extra stored for applying supersampling self.orig_pixel2 = self.detector.pixel2 self.start_values = { 'dist': 200e-3, 'wavelength': 0.3344e-10, 'polarization_factor': 0.99 } self.fit_wavelength = False self.fixed_values = { } # dictionary for fixed parameters during calibration (keys can be e.g. rot1, poni1 etc. # and values are the values to what the respective parameter will be set self.is_calibrated = False self.use_mask = False self.filename = '' self.calibration_name = 'None' self.polarization_factor = 0.99 self.supersampling_factor = 1 self.correct_solid_angle = True self._calibrants_working_dir = calibrants_path self.distortion_spline_filename = None self.tth = np.linspace(0, 25) self.int = np.sin(self.tth) self.num_points = len(self.int) self.cake_img = np.zeros((2048, 2048)) self.cake_tth = None self.cake_azi = None self.peak_search_algorithm = None def find_peaks_automatic(self, x, y, peak_ind): """ Searches peaks by using the Massif algorithm :param float x: x-coordinate in pixel - should be from original image (not supersampled x-coordinate) :param float y: y-coordinate in pixel - should be from original image (not supersampled y-coordinate) :param peak_ind: peak/ring index to which the found points will be added :return: array of points found """ massif = Massif(self.img_model.img_data) cur_peak_points = massif.find_peaks( (int(np.round(x)), int(np.round(y))), stdout=DummyStdOut()) if len(cur_peak_points): self.points.append(np.array(cur_peak_points)) self.points_index.append(peak_ind) return np.array(cur_peak_points) def find_peak(self, x, y, search_size, peak_ind): """ Searches a peak around the x,y position. It just searches for the maximum value in a specific search size. :param int x: x-coordinate in pixel - should be from original image (not supersampled x-coordinate) :param int y: y-coordinate in pixel - should be form original image (not supersampled y-coordinate) :param search_size: the length of the search rectangle in pixels in all direction in which the algorithm searches for the maximum peak :param peak_ind: peak/ring index to which the found points will be added :return: point found (as array) """ left_ind = int(np.round(x - search_size * 0.5)) if left_ind < 0: left_ind = 0 top_ind = int(np.round(y - search_size * 0.5)) if top_ind < 0: top_ind = 0 search_array = self.img_model.img_data[left_ind:(left_ind + search_size), top_ind:(top_ind + search_size)] x_ind, y_ind = np.where(search_array == search_array.max()) x_ind = x_ind[0] + left_ind y_ind = y_ind[0] + top_ind self.points.append(np.array([x_ind, y_ind])) self.points_index.append(peak_ind) return np.array([np.array((x_ind, y_ind))]) def clear_peaks(self): self.points = [] self.points_index = [] def remove_last_peak(self): if self.points: num_points = int( self.points[-1].size / 2) # each peak is x, y so length is twice as number of peaks self.points.pop(-1) self.points_index.pop(-1) return num_points def create_cake_geometry(self): self.cake_geometry = AzimuthalIntegrator( splineFile=self.distortion_spline_filename, detector=self.detector) pyFAI_parameter = self.pattern_geometry.getPyFAI() pyFAI_parameter['wavelength'] = self.pattern_geometry.wavelength self.cake_geometry.setPyFAI(dist=pyFAI_parameter['dist'], poni1=pyFAI_parameter['poni1'], poni2=pyFAI_parameter['poni2'], rot1=pyFAI_parameter['rot1'], rot2=pyFAI_parameter['rot2'], rot3=pyFAI_parameter['rot3'], detector=self.detector) self.cake_geometry.wavelength = pyFAI_parameter['wavelength'] def setup_peak_search_algorithm(self, algorithm, mask=None): """ Initializes the peak search algorithm on the current image :param algorithm: peak search algorithm used. Possible algorithms are 'Massif' and 'Blob' :param mask: if a mask is used during the process this is provided here as a 2d array for the image. """ if algorithm == 'Massif': self.peak_search_algorithm = Massif(self.img_model.img_data) elif algorithm == 'Blob': if mask is not None: self.peak_search_algorithm = BlobDetection( self.img_model.img_data * mask) else: self.peak_search_algorithm = BlobDetection( self.img_model.img_data) self.peak_search_algorithm.process() else: return def search_peaks_on_ring(self, ring_index, delta_tth=0.1, min_mean_factor=1, upper_limit=55000, mask=None): """ This function is searching for peaks on an expected ring. It needs an initial calibration before. Then it will search for the ring within some delta_tth and other parameters to get peaks from the calibrant. :param ring_index: the index of the ring for the search :param delta_tth: search space around the expected position in two theta :param min_mean_factor: a factor determining the minimum peak intensity to be picked up. it is based on the mean value of the search area defined by delta_tth. Pick a large value for larger minimum value and lower for lower minimum value. Therefore, a smaller number is more prone to picking up noise. typical values like between 1 and 3. :param upper_limit: maximum intensity for the peaks to be picked :param mask: in case the image has to be masked from certain areas, it need to be given here. Default is None. The mask should be given as an 2d array with the same dimensions as the image, where 1 denotes a masked pixel and all others should be 0. """ self.reset_supersampling() if not self.is_calibrated: return # transform delta from degree into radians delta_tth = delta_tth / 180.0 * np.pi # get appropriate two theta value for the ring number tth_calibrant_list = self.calibrant.get_2th() if ring_index >= len(tth_calibrant_list): raise NotEnoughSpacingsInCalibrant() tth_calibrant = np.float(tth_calibrant_list[ring_index]) # get the calculated two theta values for the whole image tth_array = self.pattern_geometry.twoThetaArray( self.img_model.img_data.shape) # create mask based on two_theta position ring_mask = abs(tth_array - tth_calibrant) <= delta_tth if mask is not None: mask = np.logical_and(ring_mask, np.logical_not(mask)) else: mask = ring_mask # calculate the mean and standard deviation of this area sub_data = np.array(self.img_model.img_data.ravel()[np.where( mask.ravel())], dtype=np.float64) sub_data[np.where(sub_data > upper_limit)] = np.NaN mean = np.nanmean(sub_data) std = np.nanstd(sub_data) # set the threshold into the mask (don't detect very low intensity peaks) threshold = min_mean_factor * mean + std mask2 = np.logical_and(self.img_model.img_data > threshold, mask) mask2[np.where(self.img_model.img_data > upper_limit)] = False size2 = mask2.sum(dtype=int) keep = int(np.ceil(np.sqrt(size2))) try: sys.stdout = DummyStdOut res = self.peak_search_algorithm.peaks_from_area(mask2, Imin=mean - std, keep=keep) sys.stdout = sys.__stdout__ except IndexError: res = [] # Store the result if len(res): self.points.append(np.array(res)) self.points_index.append(ring_index) self.set_supersampling() self.pattern_geometry.reset() def set_calibrant(self, filename): self.calibrant = Calibrant() self.calibrant.load_file(filename) self.pattern_geometry.calibrant = self.calibrant def set_start_values(self, start_values): self.start_values = start_values self.polarization_factor = start_values['polarization_factor'] def set_pixel_size(self, pixel_size): """ :param pixel_size: tuple with pixel_width and pixel height as element """ self.orig_pixel1 = pixel_size[0] self.orig_pixel2 = pixel_size[1] self.detector.pixel1 = self.orig_pixel1 self.detector.pixel2 = self.orig_pixel2 self.set_supersampling() def set_fixed_values(self, fixed_values): """ Sets the fixed and not fitted values for the geometry refinement :param fixed_values: a dictionary with the fixed parameters as key and their corresponding fixed value, possible keys: 'dist', 'rot1', 'rot2', 'rot3', 'poni1', 'poni2' """ self.fixed_values = fixed_values def calibrate(self): self.reset_supersampling() self.pattern_geometry = GeometryRefinement( self.create_point_array(self.points, self.points_index), dist=self.start_values['dist'], wavelength=self.start_values['wavelength'], detector=self.detector, calibrant=self.calibrant, splineFile=self.distortion_spline_filename) self.refine() self.create_cake_geometry() self.is_calibrated = True self.calibration_name = 'current' self.set_supersampling() # reset the integrator (not the geometric parameters) self.pattern_geometry.reset() def refine(self): self.reset_supersampling() self.pattern_geometry.data = self.create_point_array( self.points, self.points_index) fix = ['wavelength'] if self.fit_wavelength: fix = [] for key, value in self.fixed_values.items(): fix.append(key) setattr(self.pattern_geometry, key, value) if self.fit_wavelength: self.pattern_geometry.refine2(fix=fix) self.pattern_geometry.refine2_wavelength(fix=fix) self.create_cake_geometry() self.set_supersampling() # reset the integrator (not the geometric parameters) self.pattern_geometry.reset() def _check_detector_and_image_shape(self): if self.detector.shape is not None: if self.detector.shape != self.img_model.img_data.shape: self.reset_detector() self.detector_reset.emit() def _prepare_integration_mask(self, mask): if mask is None: return self.detector.mask else: if self.detector.mask is None: return mask else: if mask.shape == self.detector.mask.shape: return np.logical_or(self.detector.mask, mask) def _prepare_integration_super_sampling(self, mask): if self.supersampling_factor > 1: img_data = supersample_image(self.img_model.img_data, self.supersampling_factor) if mask is not None: mask = supersample_image(mask, self.supersampling_factor) else: img_data = self.img_model.img_data return img_data, mask def integrate_1d(self, num_points=None, mask=None, polarization_factor=None, filename=None, unit='2th_deg', method='csr'): if np.sum(mask) == self.img_model.img_data.shape[ 0] * self.img_model.img_data.shape[1]: # do not perform integration if the image is completely masked... return self.tth, self.int if self.pattern_geometry_img_shape != self.img_model.img_data.shape: # if cake geometry was used on differently shaped image before the azimuthal integrator needs to be reset self.pattern_geometry.reset() self.pattern_geometry_img_shape = self.img_model.img_data.shape if polarization_factor is None: polarization_factor = self.polarization_factor self._check_detector_and_image_shape() mask = self._prepare_integration_mask(mask) img_data, mask = self._prepare_integration_super_sampling(mask) if num_points is None: num_points = self.calculate_number_of_pattern_points( img_data.shape, 2) self.num_points = num_points t1 = time.time() if unit is 'd_A': try: self.tth, self.int = self.pattern_geometry.integrate1d( img_data, num_points, method=method, unit='2th_deg', mask=mask, polarization_factor=polarization_factor, correctSolidAngle=self.correct_solid_angle, filename=filename) except NameError: self.tth, self.int = self.pattern_geometry.integrate1d( img_data, num_points, method='csr', unit='2th_deg', mask=mask, polarization_factor=polarization_factor, correctSolidAngle=self.correct_solid_angle, filename=filename) self.tth = self.pattern_geometry.wavelength / ( 2 * np.sin(self.tth / 360 * np.pi)) * 1e10 self.int = self.int else: try: self.tth, self.int = self.pattern_geometry.integrate1d( img_data, num_points, method=method, unit=unit, mask=mask, polarization_factor=polarization_factor, correctSolidAngle=self.correct_solid_angle, filename=filename) except NameError: self.tth, self.int = self.pattern_geometry.integrate1d( img_data, num_points, method='csr', unit=unit, mask=mask, polarization_factor=polarization_factor, correctSolidAngle=self.correct_solid_angle, filename=filename) logger.info('1d integration of {0}: {1}s.'.format( os.path.basename(self.img_model.filename), time.time() - t1)) ind = np.where((self.int > 0) & (~np.isnan(self.int))) self.tth = self.tth[ind] self.int = self.int[ind] return self.tth, self.int def integrate_2d(self, mask=None, polarization_factor=None, unit='2th_deg', method='csr', rad_points=None, azimuth_points=360, azimuth_range=None): if polarization_factor is None: polarization_factor = self.polarization_factor if self.cake_geometry_img_shape != self.img_model.img_data.shape: # if cake geometry was used on differently shaped image before the azimuthal integrator needs to be reset self.cake_geometry.reset() self.cake_geometry_img_shape = self.img_model.img_data.shape self._check_detector_and_image_shape() mask = self._prepare_integration_mask(mask) img_data, mask = self._prepare_integration_super_sampling(mask) if rad_points is None: rad_points = self.calculate_number_of_pattern_points( img_data.shape, 2) self.num_points = rad_points t1 = time.time() res = self.cake_geometry.integrate2d( img_data, rad_points, azimuth_points, azimuth_range=azimuth_range, method=method, mask=mask, unit=unit, polarization_factor=polarization_factor, correctSolidAngle=self.correct_solid_angle) logger.info('2d integration of {0}: {1}s.'.format( os.path.basename(self.img_model.filename), time.time() - t1)) self.cake_img = res[0] self.cake_tth = res[1] self.cake_azi = res[2] return self.cake_img def create_point_array(self, points, points_ind): res = [] for i, point_list in enumerate(points): if point_list.shape == (2, ): res.append([point_list[0], point_list[1], points_ind[i]]) else: for point in point_list: res.append([point[0], point[1], points_ind[i]]) return np.array(res) def get_point_array(self): return self.create_point_array(self.points, self.points_index) def get_calibration_parameter(self): pyFAI_parameter = self.pattern_geometry.getPyFAI() pyFAI_parameter['polarization_factor'] = self.polarization_factor try: fit2d_parameter = self.pattern_geometry.getFit2D() fit2d_parameter['polarization_factor'] = self.polarization_factor except TypeError: fit2d_parameter = None pyFAI_parameter['wavelength'] = self.pattern_geometry.wavelength if fit2d_parameter: fit2d_parameter['wavelength'] = self.pattern_geometry.wavelength return pyFAI_parameter, fit2d_parameter def calculate_number_of_pattern_points(self, img_shape, max_dist_factor=1.5): # calculates the number of points for an integrated pattern, based on the distance of the beam center to the the # image corners. Maximum value is determined by the shape of the image. fit2d_parameter = self.pattern_geometry.getFit2D() center_x = fit2d_parameter['centerX'] center_y = fit2d_parameter['centerY'] width, height = img_shape if width > center_x > 0: side1 = np.max([abs(width - center_x), center_x]) else: side1 = width if center_y < height and center_y > 0: side2 = np.max([abs(height - center_y), center_y]) else: side2 = height max_dist = np.sqrt(side1**2 + side2**2) return int(max_dist * max_dist_factor) def load(self, filename): """ Loads a calibration file and and sets all the calibration parameter. :param filename: filename for a *.poni calibration file """ self.pattern_geometry = GeometryRefinement( wavelength=0.3344e-10, detector=self.detector, poni1=0, poni2=0) # default params are necessary, otherwise fails... self.pattern_geometry.load(filename) self.orig_pixel1 = self.pattern_geometry.pixel1 self.orig_pixel2 = self.pattern_geometry.pixel2 if self.pattern_geometry.pixel1 == self.detector.pixel1 and \ self.pattern_geometry.pixel2 == self.detector.pixel2: self.pattern_geometry.detector = self.detector # necessary since loading a poni file will reset the detector else: self.reset_detector() self.calibration_name = get_base_name(filename) self.filename = filename self.is_calibrated = True self.create_cake_geometry() self.set_supersampling() def save(self, filename): """ Saves the current calibration parameters into a a text file. Default extension is *.poni """ self.cake_geometry.save(filename) self.calibration_name = get_base_name(filename) self.filename = filename def load_detector(self, name): self.detector_mode = DetectorModes.PREDEFINED names, classes = get_available_detectors() detector_ind = names.index(name) self._load_detector(classes[detector_ind]()) def load_detector_from_file(self, filename): self.detector_mode = DetectorModes.NEXUS self._load_detector(NexusDetector(filename)) def _load_detector(self, detector): """ Loads a pyFAI detector :param detector: an instance of pyFAI Detector """ self.detector = detector self.detector.calc_mask() self.orig_pixel1 = self.detector.pixel1 self.orig_pixel2 = self.detector.pixel2 self.pattern_geometry.detector = self.detector if self.cake_geometry: self.cake_geometry.detector = self.detector self.set_supersampling() self._original_detector = None def reset_detector(self): self.detector_mode = DetectorModes.CUSTOM self.detector = Detector(pixel1=self.orig_pixel1, pixel2=self.orig_pixel2) self.pattern_geometry.detector = self.detector if self.cake_geometry: self.cake_geometry.detector = self.detector self.set_supersampling() def create_file_header(self): try: # pyFAI version 0.12.0 return self.pattern_geometry.makeHeaders( polarization_factor=self.polarization_factor) except AttributeError: # pyFAI after version 0.12.0 from pyFAI.io import DefaultAiWriter return DefaultAiWriter(None, self.pattern_geometry).make_headers() def set_fit2d(self, fit2d_parameter): """ Reads in a dictionary with fit2d parameters where the fields of the dictionary are: 'directDist', 'centerX', 'centerY', 'tilt', 'tiltPlanRotation', 'pixelX', pixelY', 'polarization_factor', 'wavelength' """ self.pattern_geometry.setFit2D( directDist=fit2d_parameter['directDist'], centerX=fit2d_parameter['centerX'], centerY=fit2d_parameter['centerY'], tilt=fit2d_parameter['tilt'], tiltPlanRotation=fit2d_parameter['tiltPlanRotation'], pixelX=fit2d_parameter['pixelX'], pixelY=fit2d_parameter['pixelY']) # the detector pixel1 and pixel2 values are updated by setPyFAI self.orig_pixel1 = self.detector.pixel1 self.orig_pixel2 = self.detector.pixel2 self.pattern_geometry.wavelength = fit2d_parameter['wavelength'] self.create_cake_geometry() self.polarization_factor = fit2d_parameter['polarization_factor'] self.orig_pixel1 = fit2d_parameter['pixelX'] * 1e-6 self.orig_pixel2 = fit2d_parameter['pixelY'] * 1e-6 self.is_calibrated = True self.set_supersampling() def set_pyFAI(self, pyFAI_parameter): """ Reads in a dictionary with pyFAI parameters where the fields of dictionary are: 'dist', 'poni1', 'poni2', 'rot1', 'rot2', 'rot3', 'pixel1', 'pixel2', 'wavelength', 'polarization_factor' """ self.pattern_geometry.setPyFAI(dist=pyFAI_parameter['dist'], poni1=pyFAI_parameter['poni1'], poni2=pyFAI_parameter['poni2'], rot1=pyFAI_parameter['rot1'], rot2=pyFAI_parameter['rot2'], rot3=pyFAI_parameter['rot3'], pixel1=pyFAI_parameter['pixel1'], pixel2=pyFAI_parameter['pixel2']) self.detector.pixel1 = pyFAI_parameter['pixel1'] self.detector.pixel2 = pyFAI_parameter['pixel2'] self.orig_pixel1 = self.detector.pixel1 self.orig_pixel2 = self.detector.pixel2 self.pattern_geometry.wavelength = pyFAI_parameter['wavelength'] self.create_cake_geometry() self.polarization_factor = pyFAI_parameter['polarization_factor'] self.is_calibrated = True self.set_supersampling() def load_distortion(self, spline_filename): self.distortion_spline_filename = spline_filename self.pattern_geometry.set_splineFile(spline_filename) if self.cake_geometry: self.cake_geometry.set_splineFile(spline_filename) def reset_distortion_correction(self): self.distortion_spline_filename = None self.detector.set_splineFile(None) self.pattern_geometry.set_splineFile(None) if self.cake_geometry: self.cake_geometry.set_splineFile(None) def set_supersampling(self, factor=None): """ Sets the supersampling to a specific factor. Whereby the factor determines in how many artificial pixel the original pixel is split. (factor^2) factor n_pixel 1 1 2 4 3 9 4 16 """ if factor is None: factor = self.supersampling_factor self.detector.pixel1 = self.orig_pixel1 / float(factor) self.detector.pixel2 = self.orig_pixel2 / float(factor) self.pattern_geometry.pixel1 = self.orig_pixel1 / float(factor) self.pattern_geometry.pixel2 = self.orig_pixel2 / float(factor) if factor != self.supersampling_factor: self.pattern_geometry.reset() self.supersampling_factor = factor def reset_supersampling(self): self.pattern_geometry.pixel1 = self.orig_pixel1 self.pattern_geometry.pixel2 = self.orig_pixel2 self.detector.pixel1 = self.orig_pixel1 self.detector.pixel2 = self.orig_pixel2 def get_two_theta_img(self, x, y): """ Gives the two_theta value for the x,y coordinates on the image. Be aware that this function will be incorrect for pixel indices, since it does not correct for center of the pixel. :param x: x-coordinate in pixel on the image :type x: ndarray :param y: y-coordinate in pixel on the image :type y: ndarray :return : two theta in radians """ x *= self.supersampling_factor y *= self.supersampling_factor return self.pattern_geometry.tth( x - 0.5, y - 0.5)[0] # deletes 0.5 because tth function uses pixel indices def get_azi_img(self, x, y): """ Gives chi for position on image. :param x: x-coordinate in pixel on the image :type x: ndarray :param y: y-coordinate in pixel on the image :type y: ndarray :return : azimuth in radians """ x *= self.supersampling_factor y *= self.supersampling_factor return self.pattern_geometry.chi(x - 0.5, y - 0.5)[0] def get_two_theta_array(self): return self.pattern_geometry.twoThetaArray( self.img_model.img_data.shape)[::self.supersampling_factor, ::self. supersampling_factor] def get_pixel_ind(self, tth, azi): """ Calculates pixel index for a specfic two theta and azimutal value. :param tth: two theta in radians :param azi: azimuth in radians :return: tuple of index 1 and 2 """ tth_ind = find_contours(self.pattern_geometry.ttha, tth) if len(tth_ind) == 0: return [] tth_ind = np.vstack(tth_ind) azi_values = self.pattern_geometry.chi(tth_ind[:, 0], tth_ind[:, 1]) min_index = np.argmin(np.abs(azi_values - azi)) return tth_ind[min_index, 0], tth_ind[min_index, 1] @property def wavelength(self): return self.pattern_geometry.wavelength ########################## ## Detector rotation stuff def swap_detector_shape(self): self._swap_detector_shape() self._swap_pixel_size() self._swap_detector_module_size() def rotate_detector_m90(self): """ Rotates the detector stuff by m90 degree. This includes swapping of shape, pixel size and module sizes, as well as dx and dy """ self._save_original_detector_definition() self.swap_detector_shape() self._reset_detector_mask() self._transform_pixel_corners(rotate_matrix_m90) def rotate_detector_p90(self): """ """ self._save_original_detector_definition() self.swap_detector_shape() self._reset_detector_mask() self._transform_pixel_corners(rotate_matrix_p90) def flip_detector_horizontally(self): self._save_original_detector_definition() self._transform_pixel_corners(np.fliplr) def flip_detector_vertically(self): self._save_original_detector_definition() self._transform_pixel_corners(np.flipud) def reset_transformations(self): """Restores the detector to it's original state""" if self._original_detector is None: # no transformations done so far return self.detector = deepcopy(self._original_detector) self.orig_pixel1, self.orig_pixel2 = self.detector.pixel1, self.detector.pixel2 self.pattern_geometry.detector = self.detector if self.cake_geometry is not None: self.cake_geometry.detector = self.detector self.set_supersampling() self._original_detector = None def load_transformations_string_list(self, transformations): """ Transforms the detector parameters (shape, pixel size and distortion correction) based on a list of transformation actions. :param transformations: list of transformations specified as strings, values are "flipud", "fliplr", "rotate_matrix_m90", "rotate_matrix_p90 """ for transformation in transformations: if transformation == "flipud": self.flip_detector_vertically() elif transformation == "fliplr": self.flip_detector_horizontally() elif transformation == "rotate_matrix_m90": self.rotate_detector_m90() elif transformation == "rotate_matrix_p90": self.rotate_detector_p90() def _save_original_detector_definition(self): """ Saves the state of the detector to _original_detector if not done yet. Used for restoration upon resetting the transfromations. """ if self._original_detector is None: self._original_detector = deepcopy(self.detector) self._original_detector.pixel1 = self.orig_pixel1 self._original_detector.pixel2 = self.orig_pixel2 self._mask = False def _transform_pixel_corners(self, transform_function): """ :param transform_function: function pointer which will affect the dx, dy and pixel corners of the detector """ if self.detector._dx is not None: old_dx, old_dy = self.detector._dx, self.detector._dy self.detector.set_dx(transform_function(old_dx)) self.detector.set_dy(transform_function(old_dy)) if self.detector._pixel_corners is not None: self.detector._pixel_corners = transform_function( self.detector._pixel_corners) def _swap_pixel_size(self): """swaps the pixel sizes""" self.orig_pixel1, self.orig_pixel2 = self.orig_pixel2, self.orig_pixel1 self.set_supersampling() def _swap_detector_shape(self): """Swaps the detector shape and max_shape values""" if self.detector.shape is not None: self.detector.shape = (self.detector.shape[1], self.detector.shape[0]) if self.detector.max_shape is not None: self.detector.max_shape = (self.detector.max_shape[1], self.detector.max_shape[0]) def _swap_detector_module_size(self): """swaps the module size and gap sizes for e.g. Pilatus Detectors""" if hasattr(self.detector, 'module_size'): self.detector.module_size = (self.detector.module_size[1], self.detector.module_size[0]) if hasattr(self.detector, 'MODULE_GAP'): self.detector.MODULE_GAP = (self.detector.MODULE_GAP[1], self.detector.MODULE_GAP[0]) def _reset_detector_mask(self): """resets and recalculates the mask. Transforamtions to shape and module size have to be performed before.""" self.detector._mask = False
class CalibrateDialog(BaseDialog): def __init__(self, parent=None): super(CalibrateDialog, self).__init__(parent) self.plotview = None self.data = None self.counts = None self.points = [] self.pattern_geometry = None self.cake_geometry = None self.is_calibrated = False cstr = str(ALL_CALIBRANTS) calibrants = sorted(cstr[cstr.index(':') + 2:].split(', ')) self.parameters = GridParameters() self.parameters.add('calibrant', calibrants, 'Calibrant') self.parameters['calibrant'].value = 'CeO2' self.parameters.add('wavelength', 0.5, 'Wavelength (Ang)', False) self.parameters.add('distance', 100.0, 'Detector Distance (mm)', True) self.parameters.add('xc', 512, 'Beam Center - x', True) self.parameters.add('yc', 512, 'Beam Center - y', True) self.parameters.add('yaw', 0.0, 'Yaw (degrees)', True) self.parameters.add('pitch', 0.0, 'Pitch (degrees)', True) self.parameters.add('roll', 0.0, 'Roll (degrees)', True) self.parameters.add('search_size', 10, 'Search Size (pixels)') rings = ['Ring1', 'Ring2', 'Ring3', 'Ring4', 'Ring5'] self.rings_box = self.select_box(rings) self.set_layout( self.select_entry(self.choose_entry), self.action_buttons(('Plot Calibration', self.plot_data)), self.parameters.grid(header=False), self.make_layout( self.action_buttons(('Select Points', self.select)), self.rings_box), self.action_buttons(('Calibrate', self.calibrate), ('Plot Cake', self.plot_cake), ('Restore', self.restore_parameters), ('Save', self.save_parameters)), self.close_buttons(close=True)) self.set_title('Calibrating Powder') def choose_entry(self): if 'calibration' not in self.entry['instrument']: raise NeXusError('Please load calibration data to this entry') self.update_parameters() self.plot_data() def update_parameters(self): self.parameters['wavelength'].value = self.entry[ 'instrument/monochromator/wavelength'] detector = self.entry['instrument/detector'] self.parameters['distance'].value = detector['distance'] self.parameters['yaw'].value = detector['yaw'] self.parameters['pitch'].value = detector['pitch'] self.parameters['roll'].value = detector['roll'] if 'beam_center_x' in detector: self.parameters['xc'].value = detector['beam_center_x'] if 'beam_center_y' in detector: self.parameters['yc'].value = detector['beam_center_y'] self.data = self.entry['instrument/calibration'] self.counts = self.data.nxsignal.nxvalue @property def search_size(self): return int(self.parameters['search_size'].value) @property def ring(self): return int(self.rings_box.currentText()[-1]) - 1 @property def ring_color(self): colors = ['r', 'b', 'g', 'c', 'm'] return colors[self.ring] def plot_data(self): if self.plotview is None: if 'Powder Calibration' in plotviews: self.plotview = plotviews['Powder Calibration'] else: self.plotview = NXPlotView('Powder Calibration') self.plotview.plot(self.data, log=True) self.plotview.aspect = 'equal' self.plotview.ytab.flipped = True self.clear_peaks() def on_button_press(self, event): self.plotview.make_active() if event.inaxes: self.xp, self.yp = event.x, event.y else: self.xp, self.yp = 0, 0 def on_button_release(self, event): if event.inaxes: if abs(event.x - self.xp) > 5 or abs(event.y - self.yp) > 5: return x, y = self.plotview.inverse_transform(event.xdata, event.ydata) for i, point in enumerate(self.points): circle = point[0] if circle.contains_point( self.plotview.ax.transData.transform((x, y))): circle.remove() for circle in point[2]: circle.remove() del self.points[i] return idx, idy = self.find_peak(x, y) points = [(idy, idx)] circles = [] massif = Massif(self.counts) extra_points = massif.find_peaks((idy, idx)) for point in extra_points: points.append(point) circles.append(self.circle(point[1], point[0], alpha=0.3)) self.points.append( [self.circle(idx, idy), points, circles, self.ring]) def circle(self, idx, idy, alpha=1.0): return self.plotview.circle(idx, idy, self.search_size, facecolor=self.ring_color, edgecolor='k', alpha=alpha) def select(self): self.plotview.cidpress = self.plotview.mpl_connect( 'button_press_event', self.on_button_press) self.plotview.cidrelease = self.plotview.mpl_connect( 'button_release_event', self.on_button_release) def find_peak(self, x, y): s = self.search_size left = int(np.round(x - s * 0.5)) if left < 0: left = 0 top = int(np.round(y - s * 0.5)) if top < 0: top = 0 region = self.counts[top:(top + s), left:(left + s)] idy, idx = np.where(region == region.max()) idx = left + idx[0] idy = top + idy[0] return idx, idy def clear_peaks(self): self.points = [] @property def calibrant(self): return ALL_CALIBRANTS[self.parameters['calibrant'].value] @property def point_array(self): points = [] for point in self.points: for p in point[1]: points.append((p[0], p[1], point[3])) return np.array(points) def prepare_parameters(self): self.parameters.set_parameters() self.wavelength = self.parameters['wavelength'].value * 1e-10 self.distance = self.parameters['distance'].value * 1e-3 self.yaw = np.radians(self.parameters['yaw'].value) self.pitch = np.radians(self.parameters['pitch'].value) self.roll = np.radians(self.parameters['roll'].value) self.pixel_size = self.entry[ 'instrument/detector/pixel_size'].nxvalue * 1e-3 self.xc = self.parameters['xc'].value self.yc = self.parameters['yc'].value def calibrate(self): self.prepare_parameters() self.orig_pixel1 = self.pixel_size self.orig_pixel2 = self.pixel_size self.pattern_geometry = GeometryRefinement(self.point_array, dist=self.distance, wavelength=self.wavelength, pixel1=self.pixel_size, pixel2=self.pixel_size, calibrant=self.calibrant) self.refine() self.create_cake_geometry() self.pattern_geometry.reset() def refine(self): self.pattern_geometry.data = self.point_array if self.parameters['wavelength'].vary: self.pattern_geometry.refine2() fix = [] else: fix = ['wavelength'] if not self.parameters['distance'].vary: fix.append('dist') self.pattern_geometry.refine2_wavelength(fix=fix) self.read_parameters() self.is_calibrated = True self.create_cake_geometry() self.pattern_geometry.reset() def create_cake_geometry(self): self.cake_geometry = AzimuthalIntegrator() pyFAI_parameter = self.pattern_geometry.getPyFAI() pyFAI_parameter['wavelength'] = self.pattern_geometry.wavelength self.cake_geometry.setPyFAI(dist=pyFAI_parameter['dist'], poni1=pyFAI_parameter['poni1'], poni2=pyFAI_parameter['poni2'], rot1=pyFAI_parameter['rot1'], rot2=pyFAI_parameter['rot2'], rot3=pyFAI_parameter['rot3'], pixel1=pyFAI_parameter['pixel1'], pixel2=pyFAI_parameter['pixel2']) self.cake_geometry.wavelength = pyFAI_parameter['wavelength'] def plot_cake(self): if 'Cake Plot' in plotviews: plotview = plotviews['Cake Plot'] else: plotview = NXPlotView('Cake Plot') if not self.is_calibrated: raise NeXusError('No refinement performed') res = self.cake_geometry.integrate2d(self.counts, 1024, 1024, method='csr', unit='2th_deg', correctSolidAngle=True) self.cake_data = NXdata(res[0], (NXfield(res[2], name='azimumthal_angle'), NXfield(res[1], name='polar_angle'))) self.cake_data['title'] = self.entry['instrument/calibration/title'] plotview.plot(self.cake_data, log=True) wavelength = self.parameters['wavelength'].value polar_angles = [ 2 * np.degrees(np.arcsin(wavelength / (2 * d))) for d in self.calibrant.dSpacing ] plotview.vlines([ polar_angle for polar_angle in polar_angles if polar_angle < plotview.xaxis.max ], linestyle=':', color='r') def read_parameters(self): pyFAI = self.pattern_geometry.getPyFAI() fit2d = self.pattern_geometry.getFit2D() self.parameters[ 'wavelength'].value = self.pattern_geometry.wavelength * 1e10 self.parameters['distance'].value = pyFAI['dist'] * 1e3 self.parameters['yaw'].value = np.degrees(pyFAI['rot1']) self.parameters['pitch'].value = np.degrees(pyFAI['rot2']) self.parameters['roll'].value = np.degrees(pyFAI['rot3']) self.parameters['xc'].value = fit2d['centerX'] self.parameters['yc'].value = fit2d['centerY'] def restore_parameters(self): self.parameters.restore_parameters() def save_parameters(self): if not self.is_calibrated: raise NeXusError('No refinement performed') elif 'refinement' in self.entry['instrument/calibration']: if confirm_action('Overwrite previous refinement?'): del self.entry['instrument/calibration/refinement'] else: return self.entry['instrument/calibration/calibrant'] = self.parameters[ 'calibrant'].value process = NXprocess() process.program = 'pyFAI' process.version = pyFAI.version process.parameters = NXcollection() process.parameters['Detector'] = self.entry[ 'instrument/detector/description'] pyFAI_parameter = self.pattern_geometry.getPyFAI() process.parameters['PixelSize1'] = pyFAI_parameter['pixel1'] process.parameters['PixelSize2'] = pyFAI_parameter['pixel2'] process.parameters['Distance'] = pyFAI_parameter['dist'] process.parameters['Poni1'] = pyFAI_parameter['poni1'] process.parameters['Poni2'] = pyFAI_parameter['poni2'] process.parameters['Rot1'] = pyFAI_parameter['rot1'] process.parameters['Rot2'] = pyFAI_parameter['rot2'] process.parameters['Rot3'] = pyFAI_parameter['rot3'] process.parameters['Wavelength'] = pyFAI_parameter['wavelength'] self.entry['instrument/calibration/refinement'] = process self.entry['instrument/monochromator/wavelength'] = self.parameters[ 'wavelength'].value self.entry[ 'instrument/monochromator/energy'] = 12.398419739640717 / self.parameters[ 'wavelength'].value detector = self.entry['instrument/detector'] detector['distance'] = self.parameters['distance'].value detector['yaw'] = self.parameters['yaw'].value detector['pitch'] = self.parameters['pitch'].value detector['roll'] = self.parameters['roll'].value detector['beam_center_x'] = self.parameters['xc'].value detector['beam_center_y'] = self.parameters['yc'].value def reject(self): super(CalibrateDialog, self).reject() if 'Powder Calibration' in plotviews: plotviews['Powder Calibration'].close_view() if 'Cake Plot' in plotviews: plotviews['Cake Plot'].close_view()
def __createGeoRef(self, peaks, fixed): """ Contains the geometry refinement part specific to Calibration Sets up the initial guess when starting pyFAI-calib """ scores = [] PARAMETERS = [ "dist", "poni1", "poni2", "rot1", "rot2", "rot3", "wavelength" ] # First attempt defaults = self.__initGeoRef() geoRef = GeometryRefinement(data=peaks, wavelength=self.__wavelength, detector=self.__detector, calibrant=self.__calibrant, **defaults) geoRef.refine2(1000000, fix=fixed) score = geoRef.chi2() parameters = [getattr(geoRef, p) for p in PARAMETERS] scores.append((score, parameters)) # Second attempt defaults = self.__initGeoRef() geoRef = GeometryRefinement(data=peaks, wavelength=self.__wavelength, detector=self.__detector, calibrant=self.__calibrant, **defaults) geoRef.guess_poni() geoRef.refine2(1000000, fix=fixed) score = geoRef.chi2() parameters = [getattr(geoRef, p) for p in PARAMETERS] scores.append((score, parameters)) # Third attempt # FIXME use the geometry from the computed model # Choose the best scoring method: At this point we might also ask # a user to just type the numbers in? scores.sort() _score, parameters = scores[0] for parval, parname in zip(parameters, PARAMETERS): setattr(geoRef, parname, parval) return geoRef
class CalibrationData(object): def __init__(self, img_data=None): self.img_data = img_data self.points = [] self.points_index = [] self.geometry = AzimuthalIntegrator() self.calibrant = Calibrant() self.start_values = {'dist': 200e-3, 'wavelength': 0.3344e-10, 'pixel_width': 79e-6, 'pixel_height': 79e-6, 'polarization_factor': 0.95} self.fit_wavelength = False self.is_calibrated = False self.use_mask = False self.calibration_name = 'None' self.polarization_factor = 0.95 self._calibrants_working_dir = os.path.dirname(Calibrants.__file__) def find_peaks_automatic(self, x, y, peak_ind): massif = Massif(self.img_data.img_data) cur_peak_points = massif.find_peaks([x, y]) if len(cur_peak_points): self.points.append(np.array(cur_peak_points)) self.points_index.append(peak_ind) return np.array(cur_peak_points) def find_peak(self, x, y, search_size, peak_ind): left_ind = np.round(x - search_size * 0.5) top_ind = np.round(y - search_size * 0.5) x_ind, y_ind = np.where(self.img_data.img_data[left_ind:(left_ind + search_size), top_ind:(top_ind + search_size)] == \ self.img_data.img_data[left_ind:(left_ind + search_size), top_ind:(top_ind + search_size)].max()) x_ind = x_ind[0] + left_ind y_ind = y_ind[0] + top_ind self.points.append(np.array([x_ind, y_ind])) self.points_index.append(peak_ind) return np.array([np.array((x_ind, y_ind))]) def clear_peaks(self): self.points = [] self.points_index = [] def setup_peak_search_algorithm(self, algorithm, mask=None): # init the peak search algorithm if algorithm == 'Massif': self.peak_search_algorithm = Massif(self.img_data.img_data) elif algorithm == 'Blob': if mask is not None: self.peak_search_algorithm = BlobDetection(self.img_data.img_data * mask) else: self.peak_search_algorithm = BlobDetection(self.img_data.img_data) self.peak_search_algorithm.process() else: return def search_peaks_on_ring(self, peak_index, delta_tth=0.1, min_mean_factor=1, upper_limit=55000, mask=None): if not self.is_calibrated: return #transform delta from degree into radians delta_tth = delta_tth / 180.0 * np.pi # get appropiate two theta value for the ring number tth_calibrant_list = self.calibrant.get_2th() tth_calibrant = np.float(tth_calibrant_list[peak_index]) # get the calculated two theta values for the whole image if self.geometry._ttha is None: tth_array = self.geometry.twoThetaArray(self.img_data.img_data.shape) else: tth_array = self.geometry._ttha # create mask based on two_theta position ring_mask = abs(tth_array - tth_calibrant) <= delta_tth if mask is not None: mask = np.logical_and(ring_mask, np.logical_not(mask)) else: mask = ring_mask # calculate the mean and standard deviation of this area sub_data = np.array(self.img_data.img_data.ravel()[np.where(mask.ravel())], dtype=np.float64) sub_data[np.where(sub_data > upper_limit)] = np.NaN mean = np.nanmean(sub_data) std = np.nanstd(sub_data) # set the threshold into the mask (don't detect very low intensity peaks) threshold = min_mean_factor * mean + std mask2 = np.logical_and(self.img_data.img_data > threshold, mask) mask2[np.where(self.img_data.img_data > upper_limit)] = False size2 = mask2.sum(dtype=int) keep = int(np.ceil(np.sqrt(size2))) try: res = self.peak_search_algorithm.peaks_from_area(mask2, Imin=mean - std, keep=keep) except IndexError: res = [] # Store the result if len(res): self.points.append(np.array(res)) self.points_index.append(peak_index) def set_calibrant(self, filename): self.calibrant = Calibrant() self.calibrant.load_file(filename) self.geometry.calibrant = self.calibrant def set_start_values(self, start_values): self.start_values = start_values self.polarization_factor = start_values['polarization_factor'] def calibrate(self): self.geometry = GeometryRefinement(self.create_point_array(self.points, self.points_index), dist=self.start_values['dist'], wavelength=self.start_values['wavelength'], pixel1=self.start_values['pixel_width'], pixel2=self.start_values['pixel_height'], calibrant=self.calibrant) self.refine() self.integrate() self.is_calibrated = True self.calibration_name = 'current' def refine(self): self.geometry.data = self.create_point_array(self.points, self.points_index) self.geometry.refine2() if self.fit_wavelength: self.geometry.refine2_wavelength(fix=[]) def integrate(self): self.integrate_1d() self.integrate_2d() def integrate_1d(self, num_points=1400, mask=None, polarization_factor=None, filename=None, unit='2th_deg'): if np.sum(mask) == self.img_data.img_data.shape[0] * self.img_data.img_data.shape[1]: #do not perform integration if the image is completelye masked... return self.tth, self.int if polarization_factor is None: polarization_factor = self.polarization_factor if unit is 'd_A': self.tth, self.int = self.geometry.integrate1d(self.img_data.img_data, num_points, method='lut', unit='2th_deg', mask=mask, polarization_factor=polarization_factor, filename=filename) ind = np.where(self.tth > 0) self.tth = self.geometry.wavelength / (2 * np.sin(self.tth[ind] / 360 * np.pi)) * 1e10 self.int = self.int[ind] else: self.tth, self.int = self.geometry.integrate1d(self.img_data.img_data, num_points, method='lut', unit=unit, mask=mask, polarization_factor=polarization_factor, filename=filename) if self.int.max() > 0: ind = np.where(self.int > 0) self.tth = self.tth[ind] self.int = self.int[ind] return self.tth, self.int def integrate_2d(self, mask=None, polarization_factor=None, unit='2th_deg'): if polarization_factor is None: polarization_factor = self.polarization_factor res = self.geometry.integrate2d(self.img_data.img_data, 2048, 2048, method='lut', mask=mask, unit=unit, polarization_factor=polarization_factor) self.cake_img = res[0] self.cake_tth = res[1] self.cake_azi = res[2] return self.cake_img def create_point_array(self, points, points_ind): res = [] for i, point_list in enumerate(points): if point_list.shape == (2,): res.append([point_list[0], point_list[1], points_ind[i]]) else: for point in point_list: res.append([point[0], point[1], points_ind[i]]) return np.array(res) def get_point_array(self): return self.create_point_array(self.points, self.points_index) def get_calibration_parameter(self): pyFAI_parameter = self.geometry.getPyFAI() pyFAI_parameter['polarization_factor'] = self.polarization_factor try: fit2d_parameter = self.geometry.getFit2D() fit2d_parameter['polarization_factor'] = self.polarization_factor except TypeError: fit2d_parameter = None try: pyFAI_parameter['wavelength'] = self.geometry.wavelength fit2d_parameter['wavelength'] = self.geometry.wavelength except RuntimeWarning: pyFAI_parameter['wavelength'] = 0 return pyFAI_parameter, fit2d_parameter def load(self, filename): self.geometry = GeometryRefinement(np.zeros((2, 3)), dist=self.start_values['dist'], wavelength=self.start_values['wavelength'], pixel1=self.start_values['pixel_width'], pixel2=self.start_values['pixel_height']) self.geometry.load(filename) self.calibration_name = get_base_name(filename) self.is_calibrated = True def save(self, filename): self.geometry.save(filename) self.calibration_name = get_base_name(filename)
def test_noSpline(self): """tests geometric refinements without spline""" pixelSize = [1.5e-5, 1.5e-5] data = [ [1585.9999996029055, 2893.9999991192408, 0.53005649383067788], [1853.9999932086102, 2873.0000001637909, 0.53005649383067788], [2163.9999987531855, 2854.9999987738884, 0.53005649383067788], [2699.9999977914931, 2893.9999985831755, 0.53005649383067788], [3186.9999966428777, 3028.9999985930604, 0.53005649383067788], [3595.0000039534661, 3167.0000022967461, 0.53005649383067788], [3835.0000007197755, 3300.0000002536408, 0.53005649383067788], [1252.0000026881371, 2984.0000056421914, 0.53005649383067788], [576.99992486352289, 3220.0000014469815, 0.53005649383067788], [52.999989546760531, 3531.9999975314959, 0.53005649383067788], [520.99999862452842, 2424.0000005943775, 0.65327673902147754], [1108.0000045189499, 2239.9999793751085, 0.65327673902147754], [2022.0000098770186, 2136.9999921020726, 0.65327673902147754], [2436.000002384907, 2137.0000034435734, 0.65327673902147754], [2797.9999973906524, 2169.9999849019205, 0.65327673902147754], [3516.0000041508365, 2354.0000059814265, 0.65327673902147754], [3870.9999995625412, 2464.9999964079757, 0.65327673902147754], [3735.9999952703465, 2417.9999888223151, 0.65327673902147754], [3374.0001428680412, 2289.9999885080188, 0.65327673902147754], [1709.99999872134, 2165.0000006693272, 0.65327673902147754], [2004.0000081015958, 1471.0000012076148, 0.7592182246175333], [2213.0000015244159, 1464.0000243454842, 0.7592182246175333], [2115.9999952456633, 1475.0000015176133, 0.7592182246175333], [2242.0000023736206, 1477.0000046142911, 0.7592182246175333], [2463.9999967564663, 1464.0000011704756, 0.7592182246175333], [2986.000011249705, 1540.9999994523619, 0.7592182246175333], [2760.0000031761901, 1514.0000002442944, 0.7592182246175333], [3372.0000025298395, 1617.9999995345927, 0.7592182246175333], [3187.0000005152106, 1564.9999952212884, 0.7592182246175333], [3952.0000062252166, 1765.0000234029771, 0.7592182246175333], [200.99999875941003, 1190.0000046393075, 0.85451320177642376], [463.00000674257342, 1121.9999956648539, 0.85451320177642376], [1455.0000001416358, 936.99999830341949, 0.85451320177642376], [1673.9999958962637, 927.99999934328309, 0.85451320177642376], [2492.0000021823594, 922.00000383122256, 0.85451320177642376], [2639.9999948599761, 936.00000247819059, 0.85451320177642376], [3476.9999490636446, 1027.9999838362451, 0.85451320177642376], [3638.9999965727247, 1088.0000258143732, 0.85451320177642376], [4002.0000051610787, 1149.9999925115812, 0.85451320177642376], [2296.9999822277705, 908.00000939182382, 0.85451320177642376], [266.00000015817864, 576.00000049157074, 0.94195419730133967], [364.00001493127616, 564.00000136247968, 0.94195419730133967], [752.99999958240187, 496.9999948653093, 0.94195419730133967], [845.99999758606646, 479.00000730401808, 0.94195419730133967], [1152.0000082161678, 421.9999937722655, 0.94195419730133967], [1215.0000019951258, 431.00019867504369, 0.94195419730133967], [1728.0000096657914, 368.00000247754218, 0.94195419730133967], [2095.9999932673395, 365.99999862304219, 0.94195419730133967], [2194.0000006543587, 356.99999967534075, 0.94195419730133967], [2598.0000021676074, 386.99999979901884, 0.94195419730133967], [2959.9998766657627, 410.00000323183838, 0.94195419730133967], ] data = numpy.array(data) # tth = data[:,2] ring = [ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 ] ds = [ 4.15695, 2.93940753, 2.4000162, 2.078475, 1.85904456, 1.69706773, 1.46970377, 1.38565, 1.31454301, 1.25336758, 1.2000081, 1.15293049, 1.11099162, 1.0392375, 1.00820847, 0.97980251, 0.95366973, 0.92952228, 0.90712086, 0.88626472, 0.84853387, 0.83139, 0.81524497, 0.8000054, 0.77192624, 0.75895176, 0.73485188, 0.72363211, 0.71291104, 0.7026528, 0.692825, 0.68339837, 0.67434634, 0.65727151, 0.64920652, 0.64143131, 0.63392893, 0.62668379, 0.61968152, 0.61290884, 0.60000405, 0.59385, 0.58788151, 0.58208943, 0.57646525, 0.571001, 0.56568924, 0.55549581, 0.55060148, 0.54583428, 0.54118879, 0.53224291, 0.52793318, 0.52372647, 0.51961875, 0.51560619, 0.51168517, 0.50785227, 0.50410423, 0.50043797, 0.49685056 ] #LaB6 data[:, 2] = ring r = GeometryRefinement(data, pixel1=pixelSize[0], pixel2=pixelSize[1], wavelength=1.54e-10, dSpacing=ds) r.refine2(10000000) ref = numpy.array( [0.089652, 0.030970, 0.027668, -0.699407, 0.010067, 0.000001]) ref = numpy.array( [0.089750, 0.030897, 0.027172, -0.704730, 0.010649, 3.51e-06]) # print "Réference:" # print Geometry(*ref, pixel1=15e-6, pixel2=15e-6) # print "Obtained:" # print r self.assertAlmostEqual( abs(numpy.array(r.param) - ref).max(), 0.0, 3, "ref=%s obt=%s delta=%s" % (list(ref), r.param, abs(numpy.array(r.param) - ref)))
def test_noSpline(self): """tests geometric refinements without spline""" pixelSize = [1.5e-5, 1.5e-5] data = [ [1585.9999996029055, 2893.9999991192408, 0.53005649383067788], [1853.9999932086102, 2873.0000001637909, 0.53005649383067788], [2163.9999987531855, 2854.9999987738884, 0.53005649383067788], [2699.9999977914931, 2893.9999985831755, 0.53005649383067788], [3186.9999966428777, 3028.9999985930604, 0.53005649383067788], [3595.0000039534661, 3167.0000022967461, 0.53005649383067788], [3835.0000007197755, 3300.0000002536408, 0.53005649383067788], [1252.0000026881371, 2984.0000056421914, 0.53005649383067788], [576.99992486352289, 3220.0000014469815, 0.53005649383067788], [52.999989546760531, 3531.9999975314959, 0.53005649383067788], [520.99999862452842, 2424.0000005943775, 0.65327673902147754], [1108.0000045189499, 2239.9999793751085, 0.65327673902147754], [2022.0000098770186, 2136.9999921020726, 0.65327673902147754], [2436.000002384907, 2137.0000034435734, 0.65327673902147754], [2797.9999973906524, 2169.9999849019205, 0.65327673902147754], [3516.0000041508365, 2354.0000059814265, 0.65327673902147754], [3870.9999995625412, 2464.9999964079757, 0.65327673902147754], [3735.9999952703465, 2417.9999888223151, 0.65327673902147754], [3374.0001428680412, 2289.9999885080188, 0.65327673902147754], [1709.99999872134, 2165.0000006693272, 0.65327673902147754], [2004.0000081015958, 1471.0000012076148, 0.7592182246175333], [2213.0000015244159, 1464.0000243454842, 0.7592182246175333], [2115.9999952456633, 1475.0000015176133, 0.7592182246175333], [2242.0000023736206, 1477.0000046142911, 0.7592182246175333], [2463.9999967564663, 1464.0000011704756, 0.7592182246175333], [2986.000011249705, 1540.9999994523619, 0.7592182246175333], [2760.0000031761901, 1514.0000002442944, 0.7592182246175333], [3372.0000025298395, 1617.9999995345927, 0.7592182246175333], [3187.0000005152106, 1564.9999952212884, 0.7592182246175333], [3952.0000062252166, 1765.0000234029771, 0.7592182246175333], [200.99999875941003, 1190.0000046393075, 0.85451320177642376], [463.00000674257342, 1121.9999956648539, 0.85451320177642376], [1455.0000001416358, 936.99999830341949, 0.85451320177642376], [1673.9999958962637, 927.99999934328309, 0.85451320177642376], [2492.0000021823594, 922.00000383122256, 0.85451320177642376], [2639.9999948599761, 936.00000247819059, 0.85451320177642376], [3476.9999490636446, 1027.9999838362451, 0.85451320177642376], [3638.9999965727247, 1088.0000258143732, 0.85451320177642376], [4002.0000051610787, 1149.9999925115812, 0.85451320177642376], [2296.9999822277705, 908.00000939182382, 0.85451320177642376], [266.00000015817864, 576.00000049157074, 0.94195419730133967], [364.00001493127616, 564.00000136247968, 0.94195419730133967], [752.99999958240187, 496.9999948653093, 0.94195419730133967], [845.99999758606646, 479.00000730401808, 0.94195419730133967], [1152.0000082161678, 421.9999937722655, 0.94195419730133967], [1215.0000019951258, 431.00019867504369, 0.94195419730133967], [1728.0000096657914, 368.00000247754218, 0.94195419730133967], [2095.9999932673395, 365.99999862304219, 0.94195419730133967], [2194.0000006543587, 356.99999967534075, 0.94195419730133967], [2598.0000021676074, 386.99999979901884, 0.94195419730133967], [2959.9998766657627, 410.00000323183838, 0.94195419730133967], ] data = numpy.array(data) # tth = data[:,2] ring = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5] ds = [ 4.15695 , 2.93940753, 2.4000162 , 2.078475 , 1.85904456, 1.69706773, 1.46970377, 1.38565 , 1.31454301, 1.25336758, 1.2000081 , 1.15293049, 1.11099162, 1.0392375 , 1.00820847, 0.97980251, 0.95366973, 0.92952228, 0.90712086, 0.88626472, 0.84853387, 0.83139 , 0.81524497, 0.8000054 , 0.77192624, 0.75895176, 0.73485188, 0.72363211, 0.71291104, 0.7026528 , 0.692825 , 0.68339837, 0.67434634, 0.65727151, 0.64920652, 0.64143131, 0.63392893, 0.62668379, 0.61968152, 0.61290884, 0.60000405, 0.59385 , 0.58788151, 0.58208943, 0.57646525, 0.571001 , 0.56568924, 0.55549581, 0.55060148, 0.54583428, 0.54118879, 0.53224291, 0.52793318, 0.52372647, 0.51961875, 0.51560619, 0.51168517, 0.50785227, 0.50410423, 0.50043797, 0.49685056]#LaB6 data[:, 2] = ring r = GeometryRefinement(data, pixel1=pixelSize[0], pixel2=pixelSize[1], wavelength=1.54e-10, dSpacing=ds) r.refine2(10000000) ref = numpy.array([0.089652, 0.030970, 0.027668, -0.699407, 0.010067, 0.000001]) ref = numpy.array([0.089750, 0.030897, 0.027172, -0.704730, 0.010649, 3.51e-06]) # print "Réference:" # print Geometry(*ref, pixel1=15e-6, pixel2=15e-6) # print "Obtained:" # print r self.assertAlmostEqual(abs(numpy.array(r.param) - ref).max(), 0.0, 3, "ref=%s obt=%s delta=%s" % (list(ref), r.param, abs(numpy.array(r.param) - ref)))
def test_Spline(self): """tests geometric refinements with spline""" splineFine = os.path.join(os.path.dirname(__file__), "example.sp") data = [[795, 288, 0.3490658503988659], [890, 260, 0.3490658503988659], [948, 249, 0.3490658503988659], [710, 325, 0.3490658503988659], [601, 392, 0.3490658503988659], [1167, 248, 0.3490658503988659], [1200, 340, 0.3490658503988659], [1319, 285, 0.3490658503988659], [1362, 302, 0.3490658503988659], [1436, 338, 0.3490658503988659], [1526, 397, 0.3490658503988659], [1560, 424, 0.3490658503988659], [1615, 476, 0.3490658503988659], [1662, 529, 0.3490658503988659], [1742, 650, 0.3490658503988659], [1778, 727, 0.3490658503988659], [1824, 891, 0.3490658503988659], [1831, 947, 0.3490658503988659], [1832, 1063, 0.3490658503988659], [1828, 1106, 0.3490658503988659], [1828, 1106, 0.3490658503988659], [1810, 1202, 0.3490658503988659], [1775, 1307, 0.3490658503988659], [1724, 1407, 0.3490658503988659], [1655, 1502, 0.3490658503988659], [1489, 1649, 0.3490658503988659], [1397, 1700, 0.3490658503988659], [1251, 1752, 0.3490658503988659], [1126, 1772, 0.3490658503988659], [984, 1770, 0.3490658503988659], [907, 1758, 0.3490658503988659], [801, 1728, 0.3490658503988659], [696, 1681, 0.3490658503988659], [634, 1644, 0.3490658503988659], [568, 1596, 0.3490658503988659], [520, 1553, 0.3490658503988659], [453, 1479, 0.3490658503988659], [403, 1408, 0.3490658503988659], [403, 1408, 0.3490658503988659], [363, 1337, 0.3490658503988659], [320, 1228, 0.3490658503988659], [303, 1161, 0.3490658503988659], [287, 1023, 0.3490658503988659], [287, 993, 0.3490658503988659], [304, 846, 0.3490658503988659], [329, 758, 0.3490658503988659], [341, 726, 0.3490658503988659], [402, 606, 0.3490658503988659], [437, 555, 0.3490658503988659], [513, 467, 0.3490658503988659]] # data = numpy.array(data) # let's sheat ... 0.34 as int is 0 tth = data[0][2] # data[:, 2] = ring wl = 2e-10 * numpy.sin(tth / 2.0) ds = [1.0] # print tth, wl, ds, 2 * ds[0] * numpy.sin(tth / 2) r2 = GeometryRefinement(data, dist=0.1, splineFile=splineFine, wavelength=wl, dSpacing=ds) # r2.poni1 = 5e-2 # r2.poni2 = 5e-2 r2.rot1_max = 0 r2.rot1_min = -0 r2.rot2_max = 0 r2.rot2_min = -0 r2.rot3_max = 0.1 r2.rot3_min = -0.1 r2.refine2(10000000) ref2 = numpy.array([0.1, 4.917310e-02, 4.722438e-02, 0 , 0. , 0.00000]) # print "ref", ref2 # print "obt", r2.param for i, key in enumerate(("dist", "poni1", "poni2", "rot1", "rot2", "rot3")): self.assertAlmostEqual(ref2[i], r2.__getattribute__(key), 3, "%s is %s, I expected %s%s%s" % (key, r2.__getattribute__(key) , ref2[i], os.linesep, r2))