Ejemplo n.º 1
0
    def apply_transforms(self):
        num_dets = len(HexrdConfig().detector_names)
        trans = []
        if self.ui.update_all.isChecked():
            idx = self.ui.transform_all_menu.currentIndex()
            trans = [idx for x in range(num_dets)]
        else:
            for combo in self.det_cboxes:
                trans.append(combo.currentIndex())

        ilm = ImageLoadManager()
        state = HexrdConfig().load_panel_state
        state['trans'] = trans

        new_state = {
            'trans': trans,
            'agg': state.get('agg', 0),
        }

        if self.ui.subtract_minimum.isChecked():
            new_state['zero-min'] = None
            state['zero-min'] = None

        ilm.set_state(new_state)
        ilm.begin_processing(postprocess=True)
Ejemplo n.º 2
0
    def run_indexer(self):
        config = create_indexing_config()

        # Find orientations
        self.update_progress_text('Running indexer (paintGrid)')
        ncpus = config.multiprocessing
        self.completeness = indexer.paintGrid(
            self.qfib,
            self.ome_maps,
            etaRange=np.radians(config.find_orientations.eta.range),
            omeTol=np.radians(config.find_orientations.omega.tolerance),
            etaTol=np.radians(config.find_orientations.eta.tolerance),
            omePeriod=np.radians(config.find_orientations.omega.period),
            threshold=config.find_orientations.threshold,
            doMultiProc=ncpus > 1,
            nCPUs=ncpus)
        print('paintGrid complete')

        orientations_cfg = HexrdConfig().indexing_config['find_orientations']
        if orientations_cfg.get('_write_scored_orientations'):
            # Write out the scored orientations
            results = {}
            results['scored_orientations'] = {
                'test_quaternions': self.qfib,
                'score': self.completeness
            }
            print(f'Writing scored orientations in {config.working_dir} ...')
            write_scored_orientations(results, config)
Ejemplo n.º 3
0
    def write_instrument_to_hexrd_config(self, instr):
        iconfig = HexrdConfig().instrument_config_none_euler_convention

        # Add this so the calibration crystal gets written
        cal_crystal = iconfig.get('calibration_crystal')
        output_dict = instr.write_config(calibration_dict=cal_crystal)

        # Convert back to whatever convention we were using before
        eac = HexrdConfig().euler_angle_convention
        if eac is not None:
            convert_tilt_convention(output_dict, None, eac)

        # Add the saturation levels, as they seem to be missing
        sl = 'saturation_level'
        for det in output_dict['detectors'].keys():
            output_dict['detectors'][det][sl] = iconfig['detectors'][det][sl]

        # Save the previous iconfig to restore the statuses
        prev_iconfig = HexrdConfig().config['instrument']

        # Update the config
        HexrdConfig().config['instrument'] = output_dict

        # This adds in any missing keys. In particular, it is going to
        # add in any "None" detector distortions
        HexrdConfig().set_detector_defaults_if_missing()

        # Add status values
        HexrdConfig().add_status(output_dict)

        # Set the previous statuses to be the current statuses
        HexrdConfig().set_statuses_from_prev_iconfig(prev_iconfig)
Ejemplo n.º 4
0
def run_powder_calibration():
    # Set up the tilt calibration mapping
    rme = HexrdConfig().rotation_matrix_euler()

    # Set up the instrument
    iconfig = HexrdConfig().instrument_config
    instr = instrument.HEDMInstrument(instrument_config=iconfig,
                                      tilt_calibration_mapping=rme)

    flags = HexrdConfig().get_statuses_instrument_format()

    if len(flags) != len(instr.calibration_flags):
        msg = 'Length of internal flags does not match instr.calibration_flags'
        raise Exception(msg)

    instr.calibration_flags = flags

    # Plane data and images
    plane_data = HexrdConfig().active_material.planeData
    img_dict = HexrdConfig().current_images_dict()

    # tolerances for patches
    tth_tol = HexrdConfig().config['calibration']['powder']['tth_tol']
    eta_tol = HexrdConfig().config['calibration']['powder']['eta_tol']
    pktype = HexrdConfig().config['calibration']['powder']['pk_type']

    # powder calibrator
    pc = PowderCalibrator(instr,
                          plane_data,
                          img_dict,
                          tth_tol=tth_tol,
                          eta_tol=eta_tol,
                          pktype=pktype)

    # make instrument calibrator
    ic = InstrumentCalibrator(pc)

    use_robust_optimization = False
    ic.run_calibration(use_robust_optimization)

    # We might need to use this at some point
    # data_dict = pc._extract_powder_lines()

    # Add this so the calibration crystal gets written
    cal_crystal = iconfig.get('calibration_crystal')
    output_dict = instr.write_config(calibration_dict=cal_crystal)

    # Add the saturation levels, as they seem to be missing
    sl = 'saturation_level'
    for det in output_dict['detectors'].keys():
        output_dict['detectors'][det][sl] = iconfig['detectors'][det][sl]

    # Add status values
    HexrdConfig().add_status(output_dict)

    # Update the config
    HexrdConfig().config['instrument'] = output_dict

    # Set the previous statuses to be the current statuses
    HexrdConfig().set_statuses_from_instrument_format(flags)
Ejemplo n.º 5
0
    def update_gui_from_config(self, config):
        blocked = [QSignalBlocker(x) for x in self.all_widgets()]
        self.ui.npdiv.setValue(config.get('npdiv'))
        self.ui.refit_pixel_scale.setValue(config.get('refit')[0])
        self.ui.refit_ome_step_scale.setValue(config.get('refit')[1])
        self.ui.threshold.setValue(config.get('threshold'))

        tth_max = config.get('tth_max')
        if isinstance(tth_max, bool):
            enabled = tth_max
            instrument = tth_max
            value = 0.0
        else:
            enabled = True
            instrument = False
            value = tth_max

        self.ui.tth_max_enable.setChecked(enabled)

        self.ui.tth_max_instrument.setEnabled(enabled)
        self.ui.tth_max_instrument.setChecked(instrument)

        self.ui.tth_max_specify.setEnabled(enabled)
        self.ui.tth_max_specify.setChecked(not instrument)

        self.ui.tth_max_value.setEnabled(enabled and (not instrument))
        self.ui.tth_max_value.setValue(value)

        tolerances = config.get('tolerance')
        self.tolerances_model.update_from_config(tolerances)

        indexing_config = HexrdConfig().indexing_config
        self.selected_material = indexing_config.get('_selected_material')
        working_dir = indexing_config.get(
            'working_dir', str(Path(HexrdConfig().working_dir).parent))
        analysis_name = indexing_config.get(
            'analysis_name',
            Path(HexrdConfig().working_dir).stem)
        self.spots_path = str(Path(working_dir) / analysis_name)
        write_spots = indexing_config.get('_write_spots', False)
        self.ui.write_out_spots.setChecked(write_spots)

        self.update_num_hkls()
Ejemplo n.º 6
0
    def __init__(self, parent=None):
        super().__init__(parent)

        config = HexrdConfig().indexing_config['fit_grains']
        if config.get('do_fit') is False:
            return

        loader = UiLoader()
        self.ui = loader.load_file('fit_grains_options_dialog.ui', parent)
        flags = self.ui.windowFlags()
        self.ui.setWindowFlags(flags | Qt.Tool)

        self.setup_material_options()

        ok_button = self.ui.button_box.button(QDialogButtonBox.Ok)
        ok_button.setText('Fit Grains')

        self.tolerances_model = FitGrainsToleranceModel(self.ui)
        self.update_gui_from_config(config)
        self.ui.tolerances_view.setModel(self.tolerances_model)

        # Stretch columns to fill the available horizontal space
        num_cols = self.tolerances_model.columnCount()
        for i in range(num_cols):
            self.ui.tolerances_view.horizontalHeader().setSectionResizeMode(
                i, QHeaderView.Stretch)

        # Setup connections
        self.ui.accepted.connect(self.on_accepted)
        self.ui.rejected.connect(self.rejected)
        self.ui.tth_max_enable.toggled.connect(self.on_tth_max_toggled)
        self.ui.tth_max_specify.toggled.connect(self.on_tth_specify_toggled)
        self.ui.tolerances_view.selectionModel().selectionChanged.connect(
            self.on_tolerances_select)
        self.ui.add_row.clicked.connect(self.on_tolerances_add_row)
        self.ui.delete_row.clicked.connect(self.on_tolerances_delete_row)
        self.ui.move_up.clicked.connect(self.on_tolerances_move_up)
        self.ui.move_down.clicked.connect(self.on_tolerances_move_down)

        self.ui.material.currentIndexChanged.connect(
            self.selected_material_changed)
        self.ui.choose_hkls.pressed.connect(self.choose_hkls)

        self.ui.set_spots_directory.clicked.connect(self.set_working_dir)

        HexrdConfig().overlay_config_changed.connect(self.update_num_hkls)
Ejemplo n.º 7
0
    def update_gui(self):
        blockers = [QSignalBlocker(x) for x in self.widgets]  # noqa: F841

        indexing_config = HexrdConfig().indexing_config
        maps_config = indexing_config['find_orientations']['orientation_maps']

        file_name = maps_config['file'] if maps_config['file'] else ''

        self.ui.file_name.setText(file_name)
        self.threshold = maps_config['threshold']
        self.ui.bin_frames.setValue(maps_config['bin_frames'])

        self.selected_material = indexing_config.get('_selected_material')

        self.update_method_tab()

        self.update_num_hkls()
Ejemplo n.º 8
0
    def save_images(self):
        if self.ui.ignore_agg.isChecked():
            ims_dict = HexrdConfig().unagg_images
        else:
            ims_dict = HexrdConfig().imageseries_dict
        dets = HexrdConfig().detector_names
        if self.ui.single_detector.isChecked():
            dets = [self.ui.detectors.currentText()]
        for det in dets:
            selected_format = self.ui.format.currentText().lower()
            filename = f'{self.ui.file_stem.text()}_{det}.{selected_format}'
            path = f'{self.parent_dir}/{filename}'
            if selected_format.startswith('hdf5'):
                selected_format = 'hdf5'
            elif selected_format.startswith('npz'):
                selected_format = 'frame-cache'

            kwargs = {}
            if selected_format == 'hdf5':
                # A path must be specified. Set it ourselves for now.
                kwargs['path'] = 'imageseries'
            elif selected_format == 'frame-cache':
                # Get the user to pick a threshold
                result, ok = QInputDialog.getDouble(self.ui, 'HEXRD',
                                                    'Choose Threshold', 10, 0,
                                                    1e12, 3)
                if not ok:
                    # User canceled...
                    return

                kwargs['threshold'] = result

                # This needs to be specified, but I think it just needs
                # to be the same as the file name...
                kwargs['cache_file'] = path

            worker = AsyncWorker(HexrdConfig().save_imageseries,
                                 ims_dict.get(det), det, path, selected_format,
                                 **kwargs)
            self.thread_pool.start(worker)
            self.progress_dialog.setWindowTitle(f'Saving {filename}')
            self.progress_dialog.setRange(0, 0)
            worker.signals.finished.connect(self.progress_dialog.accept)
            self.progress_dialog.exec_()
Ejemplo n.º 9
0
def create_fit_grains_results_dialog(fit_grains_results, parent=None):
    # Build grains table
    num_grains = len(fit_grains_results)
    shape = (num_grains, 21)
    grains_table = np.empty(shape)
    gw = instrument.GrainDataWriter(array=grains_table)
    for result in fit_grains_results:
        gw.dump_grain(*result)
    gw.close()

    # Use the material to compute stress from strain
    indexing_config = HexrdConfig().indexing_config
    name = indexing_config.get('_selected_material')
    if name not in HexrdConfig().materials:
        name = HexrdConfig().active_material_name
    material = HexrdConfig().material(name)

    # Create the dialog
    dialog = FitGrainsResultsDialog(grains_table, material, parent)
    dialog.ui.resize(1200, 800)

    return dialog
Ejemplo n.º 10
0
    def update_wppf_plot(self):
        self.clear_wppf_plot()

        if not HexrdConfig().display_wppf_plot:
            return

        wppf_data = HexrdConfig().wppf_data
        axis = self.azimuthal_integral_axis
        line = self.azimuthal_line_artist
        if any(x is None for x in (wppf_data, axis, line)):
            return

        style = HexrdConfig().wppf_plot_style

        if style.get('marker', 'o') not in Line2D.filled_markers:
            # Marker is unfilled
            if 'edgecolors' in style:
                # Unfilled markers can't have edge colors.
                # Remove this to avoid a matplotlib warning.
                style = copy.deepcopy(style)
                del style['edgecolors']

        self.wppf_plot = axis.scatter(*wppf_data, **style)
Ejemplo n.º 11
0
class LoadPanel(QObject):

    # Emitted when images are loaded
    images_loaded = Signal()

    def __init__(self, parent=None):
        super(LoadPanel, self).__init__(parent)

        loader = UiLoader()
        self.ui = loader.load_file('load_panel.ui', parent)

        self.ims = HexrdConfig().imageseries_dict
        self.parent_dir = HexrdConfig().images_dir
        self.state = HexrdConfig().load_panel_state

        self.files = []
        self.omega_min = []
        self.omega_max = []
        self.idx = 0
        self.ext = ''
        self.frame_data = None
        self.progress_dialog = None
        self.current_progress_step = 0
        self.progress_macro_steps = 0
        self.update_allowed = False

        self.setup_gui()
        self.detectors_changed()
        self.setup_connections()

    # Setup GUI

    def setup_gui(self):
        self.setup_processing_options()

        self.ui.all_detectors.setChecked(self.state.get('apply_to_all', False))
        self.ui.aggregation.setCurrentIndex(self.state['agg'])
        self.ui.transform.setCurrentIndex(
            self.state['trans'][self.ui.detector.currentIndex()])
        self.ui.darkMode.setCurrentIndex(
            self.state['dark'][self.ui.detector.currentIndex()])
        self.dark_files = self.state['dark_files']

        self.dark_mode_changed()
        if not self.parent_dir:
            self.ui.img_directory.setText('No directory set')
        else:
            directory = self.parent_dir
            if Path(directory).is_file():
                directory = str(Path(directory).parent)
            self.ui.img_directory.setText(directory)

        self.ui.file_options.resizeColumnsToContents()

    def setup_connections(self):
        HexrdConfig().detectors_changed.connect(self.config_changed)
        HexrdConfig().load_panel_state_reset.connect(self.config_changed)

        self.ui.image_folder.clicked.connect(self.select_folder)
        self.ui.image_files.clicked.connect(self.select_images)
        self.ui.selectDark.clicked.connect(self.select_dark_img)
        self.ui.read.clicked.connect(self.read_data)
        self.ui.image_stack.clicked.connect(self.load_image_stacks)

        self.ui.darkMode.currentIndexChanged.connect(self.dark_mode_changed)
        self.ui.detector.currentIndexChanged.connect(self.switch_detector)
        self.ui.aggregation.currentIndexChanged.connect(self.agg_changed)
        self.ui.transform.currentIndexChanged.connect(self.trans_changed)
        self.ui.all_detectors.toggled.connect(self.apply_to_all_changed)

        self.ui.file_options.customContextMenuRequested.connect(
            self.contextMenuEvent)
        self.ui.file_options.cellChanged.connect(self.omega_data_changed)
        self.ui.file_options.cellChanged.connect(self.enable_aggregations)
        self.ui.update_img_data.clicked.connect(self.update_image_data)

    def setup_processing_options(self):
        self.state = HexrdConfig().load_panel_state
        self.num_dets = len(HexrdConfig().detector_names)
        self.state.setdefault('agg', UI_AGG_INDEX_NONE)
        self.state.setdefault(
            'trans', [UI_TRANS_INDEX_NONE for x in range(self.num_dets)])
        self.state.setdefault(
            'dark', [UI_DARK_INDEX_NONE for x in range(self.num_dets)])
        self.state.setdefault(
            'dark_files', [None for x in range(self.num_dets)])

    # Handle GUI changes

    def dark_mode_changed(self):
        self.state['dark'][self.idx] = self.ui.darkMode.currentIndex()

        if self.state['dark'][self.idx] == UI_DARK_INDEX_FILE:
            self.ui.selectDark.setEnabled(True)
            if self.dark_files[self.idx]:
                self.ui.dark_file.setText(self.dark_files[self.idx])
            else:
                self.ui.dark_file.setText('(No File Selected)')
            self.enable_read()
        else:
            self.ui.selectDark.setEnabled(False)
            self.ui.dark_file.setText(
                '(Using ' + str(self.ui.darkMode.currentText()) + ')')
            self.enable_read()
            self.state['dark_files'][self.idx] = None

    def detectors_changed(self):
        self.ui.detector.clear()
        self.dets = HexrdConfig().detector_names
        self.ui.detector.addItems(HexrdConfig().detector_names)

    def agg_changed(self):
        self.state['agg'] = self.ui.aggregation.currentIndex()
        if self.ui.aggregation.currentIndex() == UI_AGG_INDEX_NONE:
            HexrdConfig().reset_unagg_imgs()

    def trans_changed(self):
        self.state['trans'][self.idx] = self.ui.transform.currentIndex()

    def dir_changed(self):
        new_dir = str(Path(self.files[0][0]).parent)
        HexrdConfig().set_images_dir(new_dir)
        self.parent_dir = new_dir
        self.ui.img_directory.setText(str(Path(self.parent_dir).parent))

    def config_changed(self):
        self.setup_gui()
        self.detectors_changed()
        self.ui.file_options.setRowCount(0)
        self.reset_data()
        self.enable_read()

    def switch_detector(self):
        self.idx = self.ui.detector.currentIndex()
        if not self.ui.all_detectors.isChecked():
            self.ui.transform.setCurrentIndex(self.state['trans'][self.idx])
            if self.ui.darkMode.isEnabled():
                self.ui.darkMode.setCurrentIndex(self.state['dark'][self.idx])
        self.dark_mode_changed()
        self.create_table()

    def apply_to_all_changed(self, checked):
        HexrdConfig().load_panel_state['apply_to_all'] = checked
        if not checked:
            self.switch_detector()
        elif self.state['dark'][self.idx] == UI_DARK_INDEX_FILE:
            self.select_dark_img(self.dark_files[self.idx])


    def select_folder(self, new_dir=None):
        # This expects to define the root image folder.
        if not new_dir:
            caption = HexrdConfig().images_dirtion = 'Select directory for images'
            new_dir = QFileDialog.getExistingDirectory(
                self.ui, caption, dir=self.parent_dir)

        # Only update if a new directory is selected
        if new_dir and new_dir != HexrdConfig().images_dir:
            self.ui.image_files.setEnabled(True)
            HexrdConfig().set_images_dir(new_dir)
            self.parent_dir = new_dir
            self.dir_changed()

    def select_dark_img(self, selected_file=False):
        if not selected_file:
            # This takes one image to use for dark subtraction.
            caption = HexrdConfig().images_dirtion = 'Select image file'
            selected_file, selected_filter = QFileDialog.getOpenFileName(
                self.ui, caption, dir=self.parent_dir)

        if selected_file:
            if self.ui.all_detectors.isChecked():
                files = ImageLoadManager().match_files([selected_file])
                if files and all(len(f) for f in files):
                    files.sort()
                    for i, f in enumerate(files):
                        self.dark_files[i] = files[i][0]
                        self.state['dark_files'][i] = files[i][0]
                else:
                    self.dark_files = [selected_file] * self.num_dets
                    self.state['dark_files'] = [selected_file] * self.num_dets
                    msg = (
                        f'Unable to match files - using the same dark file'
                        f'for each detector.\nIf this is incorrect please '
                        f'de-select \"Apply Selections to All Detectors\" and '
                        f'select the dark file manually for each detector.')
                    QMessageBox.warning(self.ui, 'HEXRD', msg)
            else:
                self.dark_files[self.idx] = selected_file
                self.state['dark_files'][self.idx] = selected_file

            self.dark_mode_changed()
            self.enable_read()

    def select_images(self):
        # This takes one or more images for a single detector.
        if self.ui.aps_imageseries.isChecked():
            files = QDir(self.parent_dir).entryInfoList(QDir.Files)
            selected_files = []
            for file in files:
                selected_files.append(file.absoluteFilePath())
        else:
            caption = HexrdConfig().images_dirtion = 'Select image file(s)'
            selected_files, selected_filter = QFileDialog.getOpenFileNames(
                self.ui, caption, dir=self.parent_dir)

        if selected_files:
            self.update_allowed = False
            self.reset_data()
            self.load_image_data(selected_files)
            self.create_table()
            self.setup_gui()
            self.enable_read()

    def reset_data(self):
        self.empty_frames = 0
        self.total_frames = []
        self.omega_min = []
        self.omega_max = []
        self.nsteps = []
        self.files = []
        self.frame_data = None

    def clear_from_stack_dialog(self):
        self.reset_data()
        self.ui.file_options.setRowCount(0)
        self.enable_read()

    def enable_aggregations(self, row, column):
        if not (column == 1 or column == 2):
            return

        enable = True
        total_frames = np.sum(self.total_frames) / len(self.dets)
        if total_frames - self.empty_frames < 2:
            enable = False
        self.ui.aggregation.setEnabled(enable)
        for i in [1, 2, 3]:
            self.ui.darkMode.model().item(i).setEnabled(enable)

        if not enable:
            # Update dark mode settings
            if self.ui.darkMode.currentIndex() != UI_DARK_INDEX_FILE:
                num_dets = len(HexrdConfig().detector_names)
                self.state['dark'] = (
                    [UI_DARK_INDEX_NONE for x in range(num_dets)])
                self.ui.darkMode.setCurrentIndex(UI_DARK_INDEX_NONE)
            # Update aggregation settings
            self.state['agg'] = UI_AGG_INDEX_NONE
            self.ui.aggregation.setCurrentIndex(0)

    def load_image_data(self, selected_files):
        self.ext = Path(selected_files[0]).suffix
        has_omega = False

        # Select the path if the file(s) are HDF5
        if (ImageFileManager().is_hdf(self.ext) and not
                ImageFileManager().path_exists(selected_files[0])):
            if ImageFileManager().path_prompt(selected_files[0]) is None:
                return

        tmp_ims = []
        for img in selected_files:
            if self.ext not in YAML_EXTS:
                tmp_ims.append(ImageFileManager().open_file(img))

        self.find_images(selected_files)

        if not self.files:
            return

        if self.ext in YAML_EXTS:
            for yf in self.yml_files[0]:
                ims = ImageFileManager().open_file(yf)
                self.total_frames.append(len(ims) if len(ims) > 0 else 1)

            for f in self.files[0]:
                with open(f, 'r') as raw_file:
                    data = yaml.safe_load(raw_file)
                if 'ostart' in data['meta'] or 'omega' in data['meta']:
                    self.get_yaml_omega_data(data)
                else:
                    self.omega_min = [0] * len(self.yml_files[0])
                    self.omega_max = [0.25] * len(self.yml_files[0])
                self.nsteps = [self.total_frames[0]] * len(self.yml_files[0])
                options = data.get('options', {})
                self.empty_frames = 0
                if isinstance(options, dict):
                    empty = options.get('empty-frames', 0)
                    self.empty_frames = empty
                    self.total_frames = [f-empty for f in self.total_frames]
        else:
            for ims in tmp_ims:
                has_omega = 'omega' in ims.metadata
                self.total_frames.append(len(ims) if len(ims) > 0 else 1)
                if has_omega:
                    self.get_omega_data(ims)
                else:
                    self.omega_min.append(0)
                    self.omega_max.append(0.25)
                self.nsteps.append(len(ims))

    def get_omega_data(self, ims):
        minimum = ims.metadata['omega'][0][0]
        maximum = ims.metadata['omega'][-1][1]

        self.omega_min.append(minimum)
        self.omega_max.append(maximum)

    def get_yaml_omega_data(self, data):
        if 'ostart' in data['meta']:
            self.omega_min.append(data['meta']['ostart'])
            self.omega_max.append(data['meta']['ostop'])
        else:
            if isinstance(data['meta']['omega'], str):
                words = data['meta']['omega'].split()
                fname = Path(self.parent_dir, words[-1])
                nparray = np.load(fname)
            else:
                nparray = data['meta']['omega']

            for idx, vals in enumerate(nparray):
                self.omega_min.append(vals[0])
                self.omega_max.append(vals[1])

    def find_images(self, fnames):
        self.files, manual = ImageLoadManager().load_images(fnames)

        if len(self.files) % len(HexrdConfig().detector_names) != 0:
            msg = ('Please select at least one file for each detector.')
            QMessageBox.warning(self.ui, 'HEXRD', msg)
            self.files = []
            return

        if manual:
            dialog = LoadImagesDialog(self.files, manual, self.ui.parent())
            if not dialog.exec_():
                self.reset_data()
                return

            detector_names, files = dialog.results()
            image_files = [img for f in self.files for img in f]
            # Make sure files are matched to selected detector
            self.files = [[] for det in HexrdConfig().detector_names]
            for d, f in zip(detector_names, image_files):
                pos = HexrdConfig().detector_names.index(d)
                self.files[pos].append(f)

        self.dir_changed()

        if self.files and self.ext in YAML_EXTS:
            self.get_yml_files()

    def get_yml_files(self):
        self.yml_files = []
        for det in self.files:
            files = []
            for f in det:
                with open(f, 'r') as yml_file:
                    data = yaml.safe_load(yml_file)['image-files']
                raw_images = data['files'].split()
                for raw_image in raw_images:
                    path = Path(self.parent_dir, data['directory'])
                    files.extend([str(p) for p in path.glob(raw_image)])
            self.yml_files.append(files)

    def enable_read(self):
        files = self.yml_files if self.ext in YAML_EXTS else self.files
        enabled = len(files) > 0
        if len(files) and all(len(f) for f in files):
            if (self.state['dark'][self.idx] == UI_DARK_INDEX_FILE
                    and self.dark_files[self.idx] is None):
                enabled = False
        self.ui.read.setEnabled(enabled)

    # Handle table setup and changes

    def create_table(self):
        # Create the table if files have successfully been selected
        if not len(self.files):
            return

        if self.ext in YAML_EXTS:
            table_files = self.yml_files
        else:
            table_files = self.files

        self.ui.file_options.setRowCount(
            len(table_files[self.idx]))

        # Create the rows
        for row in range(self.ui.file_options.rowCount()):
            for column in range(self.ui.file_options.columnCount()):
                item = QTableWidgetItem()
                item.setTextAlignment(Qt.AlignCenter)
                self.ui.file_options.setItem(row, column, item)

        self.ui.file_options.blockSignals(True)
        # Populate the rows
        for i in range(self.ui.file_options.rowCount()):
            curr = table_files[self.idx][i]
            self.ui.file_options.item(i, 0).setText(Path(curr).name)
            self.ui.file_options.item(i, 1).setText(str(self.empty_frames))
            self.ui.file_options.item(i, 2).setText(str(self.total_frames[i]))
            self.ui.file_options.item(i, 3).setText(str(self.omega_min[i]))
            self.ui.file_options.item(i, 4).setText(str(self.omega_max[i]))
            self.ui.file_options.item(i, 5).setText(
                str(self.total_frames[i] - self.empty_frames))

            # Set tooltips
            self.ui.file_options.item(i, 0).setToolTip(Path(curr).name)
            self.ui.file_options.item(i, 3).setToolTip('Start must be set')
            self.ui.file_options.item(i, 4).setToolTip('Stop must be set')
            self.ui.file_options.item(i, 5).setToolTip('Number of steps')

            # Don't allow editing of file name or total frames
            self.ui.file_options.item(i, 0).setFlags(Qt.ItemIsEnabled)
            self.ui.file_options.item(i, 2).setFlags(Qt.ItemIsEnabled)
            self.ui.file_options.item(i, 5).setFlags(Qt.ItemIsEnabled)
            # If raw data offset can only be changed in YAML file
            if self.ext in YAML_EXTS:
                self.ui.file_options.item(i, 1).setFlags(Qt.ItemIsEnabled)

        self.ui.file_options.blockSignals(False)
        self.ui.file_options.resizeColumnsToContents()
        self.ui.file_options.sortByColumn(0, Qt.AscendingOrder)

    def contextMenuEvent(self, event):
        # Allow user to delete selected file(s)
        menu = QMenu(self.ui)
        remove = menu.addAction('Remove Selected Files')
        action = menu.exec_(QCursor.pos())

        # Re-selects the current row if context menu is called on disabled cell
        i = self.ui.file_options.indexAt(event)
        self.ui.file_options.selectRow(i.row())

        indices = []
        if action == remove:
            for index in self.ui.file_options.selectedIndexes():
                indices.append(QPersistentModelIndex(index))

            for idx in indices:
                self.ui.file_options.removeRow(idx.row())

            if self.ui.file_options.rowCount():
                for i in range(len(self.files)):
                    self.files[i] = []
                for row in range(self.ui.file_options.rowCount()):
                    f = self.ui.file_options.item(row, 0).text()
            else:
                self.files = []
        self.enable_read()

    def omega_data_changed(self, row, column):
        # Update the values for equivalent files when the data is changed
        self.ui.file_options.blockSignals(True)

        curr_val = self.ui.file_options.item(row, column).text()
        total_frames = self.total_frames[row] - self.empty_frames
        if curr_val != '':
            if column == 1:
                self.empty_frames = int(curr_val)
                for r in range(self.ui.file_options.rowCount()):
                    self.ui.file_options.item(r, column).setText(str(curr_val))
                    new_total = str(self.total_frames[r] - self.empty_frames)
                    self.nsteps[r] = int(new_total)
                    self.ui.file_options.item(r, 5).setText(new_total)
            elif column == 3:
                self.omega_min[row] = float(curr_val)
            elif column == 4:
                self.omega_max[row] = float(curr_val)
            self.ui.update_img_data.setEnabled(self.update_allowed)
            self.enable_read()

        self.ui.file_options.blockSignals(False)

    def confirm_omega_range(self):
        files = self.yml_files if self.ext in YAML_EXTS else self.files
        omega_range = abs(max(self.omega_max) - min(self.omega_min))
        within_range = omega_range <= MAXIMUM_OMEGA_RANGE
        if not within_range:
            msg = (
                f'All omegas must be set and the '
                f'range must be no greater than 360°.')
            QMessageBox.warning(self.ui, 'HEXRD', msg)
        return within_range

    # Process files
    def read_data(self):
        if not self.confirm_omega_range():
            return
        data = {
            'omega_min': self.omega_min,
            'omega_max': self.omega_max,
            'nsteps': self.nsteps,
            'empty_frames': self.empty_frames,
            'total_frames': self.total_frames,
            }
        if self.ui.all_detectors.isChecked():
            data['idx'] = self.idx
        if self.ext in YAML_EXTS:
            data['yml_files'] = self.yml_files
        if self.frame_data is not None:
            data.update(self.frame_data)
        HexrdConfig().load_panel_state.update(copy.copy(self.state))
        ImageLoadManager().read_data(self.files, data, self.parent())
        self.update_allowed = True

    def load_image_stacks(self):
        if data := ImageStackDialog(self.parent(), self).exec_():
            self.files = data['files']
            self.omega_min = data['omega_min']
            self.omega_max = data['omega_max']
            self.nsteps = data['nsteps']
            self.empty_frames = data['empty_frames']
            self.total_frames = data['total_frames']
            self.frame_data = data['frame_data']
            self.create_table()
            self.enable_read()
            self.update_allowed = False
            self.ui.update_img_data.setEnabled(self.update_allowed)
Ejemplo n.º 12
0
def run_line_picked_calibration(line_data):
    # Set up the tilt calibration mapping
    rme = HexrdConfig().rotation_matrix_euler()

    print('Setting up the instrument...')

    # Set up the instrument
    iconfig = HexrdConfig().instrument_config_none_euler_convention
    instr = instrument.HEDMInstrument(instrument_config=iconfig,
                                      tilt_calibration_mapping=rme)

    flags = HexrdConfig().get_statuses_instrument_format()

    if np.count_nonzero(flags) == 0:
        msg = 'There are no refinable parameters'
        raise Exception(msg)

    if len(flags) != len(instr.calibration_flags):
        msg = 'Length of internal flags does not match instr.calibration_flags'
        raise Exception(msg)

    print('Running optimization...')

    # Run calibration
    opt_result = calibrate_instrument_from_picks(instr,
                                                 line_data,
                                                 param_flags=flags,
                                                 xtol=1e-4,
                                                 ftol=1e-4)

    if not opt_result.success:
        print('Optimization failed!')
        return False

    print('Optimization succeeded!')

    # Add this so the calibration crystal gets written
    cal_crystal = iconfig.get('calibration_crystal')
    output_dict = instr.write_config(calibration_dict=cal_crystal)

    # Convert back to whatever convention we were using before
    eac = HexrdConfig().euler_angle_convention
    if eac is not None:
        convert_tilt_convention(output_dict, None, eac)

    # Add the saturation levels, as they seem to be missing
    sl = 'saturation_level'
    for det in output_dict['detectors'].keys():
        output_dict['detectors'][det][sl] = iconfig['detectors'][det][sl]

    print('Updating the config')

    # Save the previous iconfig to restore the statuses
    prev_iconfig = HexrdConfig().config['instrument']

    # Update the config
    HexrdConfig().config['instrument'] = output_dict

    # This adds in any missing keys. In particular, it is going to
    # add in any "None" detector distortions
    HexrdConfig().set_detector_defaults_if_missing()

    # Add status values
    HexrdConfig().add_status(output_dict)

    # Set the previous statuses to be the current statuses
    HexrdConfig().set_statuses_from_prev_iconfig(prev_iconfig)

    return True
Ejemplo n.º 13
0
 def params(self):
     conf = HexrdConfig().config['calibration']
     return conf.get('wppf', {}).get('params')