diff --git a/hexrdgui/llnl_import_tool_dialog.py b/hexrdgui/llnl_import_tool_dialog.py index d1a0bf438..cb7a8cac3 100644 --- a/hexrdgui/llnl_import_tool_dialog.py +++ b/hexrdgui/llnl_import_tool_dialog.py @@ -14,7 +14,7 @@ from hexrd import resources as hexrd_resources from hexrd.instrument import HEDMInstrument from hexrd.rotations import ( - angleAxisOfRotMat, make_rmat_euler, angles_from_rmat_zxz + angleAxisOfRotMat, make_rmat_euler, angles_from_rmat_zxz, rotMatOfExpMap ) import hexrdgui.resources.calibration @@ -39,6 +39,65 @@ from hexrdgui.utils.dialog import add_help_url +class AtlasConfig: + def __init__(self, atlas_coords, instr): + self.coords = atlas_coords + self.instr = instr + + def _get_orientation(self, crds, det): + """vertex in 4x3 matrix of the + 4 vertices. we return the normal + using a cross product + """ + vertex = self._get_vertices(crds) + if det == 'CAMERA-05': + xhat = -vertex[1, :] + vertex[0, :] + yhat = vertex[3, :] - vertex[0, :] + else: + xhat = vertex[3, :] - vertex[0, :] + yhat = vertex[1, :] - vertex[0, :] + + xhat = xhat/np.linalg.norm(xhat) + yhat = yhat/np.linalg.norm(yhat) + + zhat = np.cross(xhat, yhat) + zhat = zhat/np.linalg.norm(zhat) + + xhat = np.cross(yhat, zhat) + xhat = xhat/np.linalg.norm(xhat) + + rmat = np.vstack((-xhat, yhat, -zhat)).T + + RMAT_Z_180 = rotMatOfExpMap(np.pi*zhat) + if det in ['CAMERA-02', 'CAMERA-03']: + return np.dot(RMAT_Z_180, rmat) + return rmat + + def _get_center(self, vertex): + """return center of detector given + the four vertex + """ + return np.mean(vertex, axis=0) + + def _get_vertices(self, crds): + # by default we will look up from TCC, so there is + # flip in the x-component sign + return crds[0:4, :] + + def update_instrument(self, detector): + v = self._get_vertices(self.coords[detector]) + # tvec sample is the position of the sample in NIF + # chamber coordinates. the position of each detector + # is measured from this point, so we need to take this + # off + tvec_sample= np.array([0, 0, 9.8]) + tvec = self._get_center(v) - tvec_sample + rmat = self._get_orientation(self.coords[detector], detector) + ang, ax = angleAxisOfRotMat(rmat) + self.instr.detectors[detector].tvec = tvec + self.instr.detectors[detector].tilt = ang * ax + + class LLNLImportToolDialog(QObject): # Emitted when new config is loaded @@ -76,6 +135,7 @@ def __init__(self, cmap=None, parent=None): self.loaded_images = [] self.canvas = parent.image_tab_widget.active_canvas self.detector_images = {} + self.atlas_coords = None # Disable these by default. # If we disable these in Qt Designer, there are some weird bugs @@ -99,6 +159,8 @@ def __init__(self, cmap=None, parent=None): self.ui.detector_raw_image, self.ui.instr_settings_label, self.ui.instr_settings, + self.ui.load_atlas, + self.ui.atlas_label, visible=False) self.update_config_settings() @@ -137,6 +199,7 @@ def setup_connections(self): self.ui.dark_load.clicked.connect(self.load_detector_images) self.ui.accept_detector.clicked.connect( self.manually_load_detector_images) + self.ui.load_atlas.clicked.connect(self.load_atlas_coords) def enable_widgets(self, *widgets, enabled): for w in widgets: @@ -263,6 +326,8 @@ def instrument_selected(self, idx): self.ui.detector_raw_image, self.ui.instr_settings_label, self.ui.instr_settings, + self.ui.load_atlas, + self.ui.atlas_label, visible=is_fiddle) has_ip = self.ui.instr_settings.currentIndex() == 0 @@ -352,6 +417,16 @@ def update_config_settings(self): if prev: combo.setCurrentText(prev) + def load_atlas_coords(self): + file, filter = QFileDialog.getOpenFileName( + self.ui, 'Select coordinates file', dir=HexrdConfig().working_dir) + if not file: + return + with open(file, 'r') as f: + coords = yaml.safe_load(f) + self.atlas_coords = {d: np.array(c) for d, c in coords.items()} + self.ui.atlas_label.setText(Path(file).name) + def load_instrument_config(self): temp = tempfile.NamedTemporaryFile(delete=False, suffix='.hexrd') self.config_file = temp.name @@ -813,6 +888,7 @@ def reset_panel(self): self.clear_boundry() # Reset internal state self.completed = [] + self.atlas_coords = None self.defaults.clear() self.config_file = None self.import_in_progress = False @@ -831,6 +907,7 @@ def reset_panel(self): self.ui.config_file_label.setText('No File Selected') self.ui.config_file_label.setToolTip( 'Defaults to currently loaded configuration') + self.ui.atlas_label.setText('No File Selected') # Reset widget states - disable/enable/show/hide as appropriate self.enable_widgets( self.ui.image_plate_raw_image, @@ -854,6 +931,8 @@ def reset_panel(self): self.ui.detector_raw_image, self.ui.instr_settings_label, self.ui.instr_settings, + self.ui.load_atlas, + self.ui.atlas_label, visible=False) # We're all reset and ready to re-enable the main UI features HexrdConfig().enable_image_mode_widget.emit(True) @@ -871,6 +950,12 @@ def import_complete(self): instr = HEDMInstrument( instrument_config=self.ip_and_det_defaults['default_config']) + + if self.atlas_coords is not None: + atlas_config = AtlasConfig(self.atlas_coords, instr) + for detector in self.detectors: + atlas_config.update_instrument(detector) + for det in self.completed: panel = instr.detectors[det] # first need the zxz Euler angles from the panel rotation matrix. diff --git a/hexrdgui/resources/ui/llnl_import_tool_dialog.ui b/hexrdgui/resources/ui/llnl_import_tool_dialog.ui index 24943ee1f..d7f04b09c 100644 --- a/hexrdgui/resources/ui/llnl_import_tool_dialog.ui +++ b/hexrdgui/resources/ui/llnl_import_tool_dialog.ui @@ -7,7 +7,7 @@ 0 0 565 - 854 + 883 @@ -24,6 +24,94 @@ Instrument + + + + true + + + QFrame::NoFrame + + + QFrame::Raised + + + + + + Select Configuration + + + + + + + + + + Load ATLAS Coordinates + + + + + + + + Default configuration + + + + + Currently loaded configuration + + + + + Load configuration from file + + + + + + + + false + + + Load Instrument Config + + + + + + + Configuration Settings: + + + + + + + false + + + + + + No File Selected + + + + + + + No File Selected + + + + + + @@ -112,80 +200,6 @@ - - - - true - - - QFrame::NoFrame - - - QFrame::Raised - - - - - - - Default configuration - - - - - Currently loaded configuration - - - - - Load configuration from file - - - - - - - - false - - - Load Instrument Config - - - - - - - Select Configuration - - - - - - - false - - - - - - No File Selected - - - - - - - Configuration Settings: - - - - - - - - -