Skip to content
30 changes: 26 additions & 4 deletions hexrdgui/hexrd_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -1203,6 +1203,24 @@ def load_materials(self, f):
def save_materials(self, f, path=None):
save_materials_hdf5(f, self.materials, path)

def import_materials(self, file_paths: list[Path | str]):
"""Import materials from a list of files

This accepts cif and HDF5 files. All imported materials will be
added to `self.materials`.
"""
beam_energy = valWUnit('beam', 'energy', self.beam_energy, 'keV')
for path in file_paths:
ext = Path(path).suffix.lower()
if ext == '.cif':
# Import it as a cif file
self.import_material(path)
else:
# Try to import the materials from an HDF5 file
materials = load_materials_hdf5(path, kev=beam_energy)
for name, material in materials.items():
self.add_material(name, material)

def import_material(self, f):
beam_energy = valWUnit('beam', 'energy', self.beam_energy, 'keV')
name = os.path.splitext(os.path.basename(f))[0]
Expand Down Expand Up @@ -1640,10 +1658,14 @@ def add_material(self, name, material):
self.add_materials([name], [material])

def add_materials(self, names, materials):
if any(x in self.materials for x in names):
mats = list(self.materials.keys())
msg = f'Some names {names} are already in materials list {mats}!'
raise Exception(msg)
# Rename any materials that already exist by appending _1
for material in self.materials:
if material in names:
names[names.index(material)] = f'{material}_1'
HexrdConfig().logger.warning(
f'Material {material} already exists, '
f'renaming to {material}_1'
)

if len(names) != len(materials):
msg = f'{len(names)=} does not match {len(materials)=}!'
Expand Down
96 changes: 79 additions & 17 deletions hexrdgui/main_window.py
Original file line number Diff line number Diff line change
Expand Up @@ -314,7 +314,7 @@ def setup_connections(self):
self.ui.image_tab_widget.create_waterfall_plot)

self.ui.action_open_images.triggered.connect(
self.open_image_files)
self.open_image_files_triggered)
HexrdConfig().update_status_bar.connect(
self.ui.status_bar.showMessage)
HexrdConfig().detectors_changed.connect(
Expand Down Expand Up @@ -541,12 +541,22 @@ def open_image_file(self):

return selected_file

def open_image_files(self):
# Get the most recent images dir
images_dir = HexrdConfig().images_dir
def open_image_files_triggered(self):
try:
self.open_image_files()
except Exception as e:
msg = ('Number of files must match number of detectors: ' +
str(len(HexrdConfig().detector_names)))
QMessageBox.warning(self.ui, 'HEXRD', f'{e}')
return

selected_files, selected_filter = QFileDialog.getOpenFileNames(
self.ui, dir=images_dir)
def open_image_files(self, selected_files=None):
if selected_files is None:
# Get the most recent images dir
images_dir = HexrdConfig().images_dir

selected_files, selected_filter = QFileDialog.getOpenFileNames(
self.ui, dir=images_dir)

if selected_files:
# Save the chosen dir
Expand All @@ -560,8 +570,7 @@ def open_image_files(self):
or len(files) < len(HexrdConfig().detector_names)):
msg = ('Number of files must match number of detectors: ' +
str(len(HexrdConfig().detector_names)))
QMessageBox.warning(self.ui, 'HEXRD', msg)
return
raise Exception(msg)

# If it is a hdf5 file allow the user to select the path
ext = os.path.splitext(selected_files[0])[1]
Expand Down Expand Up @@ -1044,15 +1053,19 @@ def update_config_gui(self):
self.config_loaded.emit()

def eventFilter(self, target, event):
if type(target) == QMainWindow and event.type() == QEvent.Close:
if self.confirm_application_close:
msg = 'Are you sure you want to quit?'
response = QMessageBox.question(self.ui, 'HEXRD', msg)
if response == QMessageBox.No:
event.ignore()
return True
# If the main window is closing, save the config settings
HexrdConfig().save_settings()
if type(target) == QMainWindow:
if event.type() == QEvent.Close:
if self.confirm_application_close:
msg = 'Are you sure you want to quit?'
response = QMessageBox.question(self.ui, 'HEXRD', msg)
if response == QMessageBox.No:
event.ignore()
return True
# If the main window is closing, save the config settings
HexrdConfig().save_settings()
elif event.type() in (QEvent.DragEnter, QEvent.Drop):
self.validateDragDropEvent(event)
return True

if not hasattr(self, '_first_paint_occurred'):
if type(target) == QMainWindow and event.type() == QEvent.Paint:
Expand Down Expand Up @@ -1729,3 +1742,52 @@ def action_apply_median_filter_toggled(self, b):
# The dialog should have modified HexrdConfig's median filter options
# already. Just apply it now.
HexrdConfig().apply_median_filter_correction = b

def validateDragDropEvent(self, event):
mime_data = event.mimeData()
if not mime_data.hasUrls():
event.ignore()
return

paths = [url.toLocalFile() for url in mime_data.urls()]
if event.type() == QEvent.Drop:
self.dropEvent(paths)
else:
event.acceptProposedAction()

def dropEvent(self, paths):
ext = Path(paths[0]).suffix.lower()
if len(paths) == 1 and ext in ('.h5', '.hdf5'):
try:
# Try loading it as a state file
self.load_state_file(paths[0])
return
except:
# If that fails, continue on to try a different loader
pass
if len(paths) == 1 and ext in ('.hexrd', '.yml', '.yaml'):
try:
# Try loading it as an instrument config
HexrdConfig().load_instrument_config(paths[0])
return
except:
# If that fails, continue on to try a different loader
pass
if ext in ('.h5', '.hdf5', '.cif'):
try:
# Try loading as materials file(s)
HexrdConfig().import_materials(paths)
return
except:
# If that fails, continue on to try a different loader
pass
try:
# Fall back to trying to load as image if no loader succeeds or
# extension is not in known list
self.open_image_files(selected_files=paths)
except Exception as e:
error_message = (
'Unable to guess file type (state, instrument, materials, or '
'image). Please use File menu to load.'
)
QMessageBox.critical(self.ui, 'Error', error_message)
3 changes: 3 additions & 0 deletions hexrdgui/resources/ui/main_window.ui
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
<height>900</height>
</rect>
</property>
<property name="acceptDrops">
<bool>true</bool>
</property>
<property name="windowTitle">
<string>HEXRD</string>
</property>
Expand Down
Loading