def open_fits(self, filename): fits_file = fits.open(filename) fits_spectrum = FitsSpectrum(fits_file) self.spectrum_name = fits_spectrum.name() self.spectrum = fits_spectrum.spectrum self.undo.set_spectrum(self.spectrum) self.spectrum.normalize_to_max() if self.spectrum.dispersion() <0.4: print("dispersion too high ({}), reducing spectrum resolution".format(self.spectrum.dispersion())) self.spectrum.resample(self.spectrum.dispersion() / 0.4) self.draw()
def __init__(self, fits_file, settings, database, project=None): super(CalibrateSpectrum, self).__init__() self.project=project self.settings = settings self.fits_spectrum = FitsSpectrum(fits_file) self.fits_spectrum.spectrum.normalize_to_max() self.fits_file = fits_file self.ui = Ui_CalibrateSpectrum() self.ui.setupUi(self) self.toolbar = QToolBar('Calibration Toolbar') self.toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.ui.x_axis_pick.setMenu(QMenu()) self.ui.x_axis_pick.menu().addAction("Maximum from range").triggered.connect(lambda: self.pick_from_range('maximum')) self.ui.x_axis_pick.menu().addAction("Minimum from range").triggered.connect(lambda: self.pick_from_range('minimum')) self.ui.x_axis_pick.menu().addAction("Central value from range").triggered.connect(lambda: self.pick_from_range('central')) self.ui.wavelength_pick.clicked.connect(lambda: self.lines_dialog.show()) save_action = self.toolbar.addAction(QIcon(':/save_20'), 'Save', self.save_spectrum) self.spectrum_plot = QtCommons.nestWidget(self.ui.spectrum_plot_widget, QMathPlotWidget()) self.reference_spectra_dialog = ReferenceSpectraDialog(database) self.reference_spectra_dialog.setup_menu(self.toolbar, self.spectrum_plot.axes, settings) self.object_properties = ObjectProperties(self.fits_file, project=project) self.object_properties_dialog = ObjectPropertiesDialog(settings, self.object_properties) self.toolbar.addAction("Object properties", self.object_properties_dialog.show) self.calibration_model = QStandardItemModel() self.calibration_model.setHorizontalHeaderLabels(["x-axis", "wavelength", "error"]) self.ui.calibration_points.setModel(self.calibration_model) self.ui.calibration_points.selectionModel().selectionChanged.connect(lambda selected, deselected: self.ui.remove_calibration_point.setEnabled(len(selected.indexes()) > 0) ) self.ui.add_calibration_point.clicked.connect(self.add_calibration_point) self.ui.remove_calibration_point.setEnabled(False) self.ui.remove_calibration_point.clicked.connect(self.remove_calibration_point) if project and project.avg_dispersion(): self.ui.set_dispersion.setMenu(QMenu()) self.ui.set_dispersion.menu().addAction('From input value', self.calculate_calibration) self.ui.set_dispersion.menu().addAction('From Project', lambda: self.calculate_calibration(project.avg_dispersion())) else: self.ui.set_dispersion.clicked.connect(self.calculate_calibration) self.ui.point_is_star.toggled.connect(lambda checked: self.ui.wavelength_pick.setEnabled(not checked)) self.ui.point_is_star.toggled.connect(lambda checked: self.ui.point_wavelength.setEnabled(not checked)) self.fits_spectrum.plot_to(self.spectrum_plot.axes) self.toolbar.addSeparator() self.toolbar.addAction("Zoom", self.spectrum_plot.select_zoom) self.toolbar.addAction("Reset Zoom", lambda: self.spectrum_plot.reset_zoom(self.fits_spectrum.spectrum.wavelengths, self.fits_spectrum.spectrum.fluxes.min(), self.fits_spectrum.spectrum.fluxes.max())) self.toolbar.addSeparator() self.lines_dialog = LinesDialog(database, settings, self.spectrum_plot, enable_picker = False, selection_mode = 'single') self.lines_dialog.lines.connect(self.picked_line) hdu_calibration_points = [h for h in self.fits_file if h.name == FitsSpectrum.CALIBRATION_DATA] if len(hdu_calibration_points) > 0: for point in hdu_calibration_points[-1].data: self.add_calibration_point_data(point[0], point[1]) self.calculate_calibration()
def instrument_response(self, filename): print("Applying instrument response {}".format(filename)) instrument_response_file = fits.open(filename) instrument_response = FitsSpectrum(instrument_response_file) response = instrument_response.spectrum response.normalize_to_max() range = (max(response.wavelengths[0], self.spectrum.wavelengths[0]), min(response.wavelengths[-1], self.spectrum.wavelengths[-1])) self.spectrum.cut(self.spectrum.wavelength_index(range[0]), self.spectrum.wavelength_index(range[1])) spline = InterpolatedUnivariateSpline(response.wavelengths, response.fluxes) response_data = [spline(x) for x in self.spectrum.wavelengths] self.spectrum.fluxes /= response_data self.spectrum.normalize_to_max() self.draw()
class CalibrateSpectrum(QWidget): def __init__(self, fits_file, settings, database, project=None): super(CalibrateSpectrum, self).__init__() self.project=project self.settings = settings self.fits_spectrum = FitsSpectrum(fits_file) self.fits_spectrum.spectrum.normalize_to_max() self.fits_file = fits_file self.ui = Ui_CalibrateSpectrum() self.ui.setupUi(self) self.toolbar = QToolBar('Calibration Toolbar') self.toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.ui.x_axis_pick.setMenu(QMenu()) self.ui.x_axis_pick.menu().addAction("Maximum from range").triggered.connect(lambda: self.pick_from_range('maximum')) self.ui.x_axis_pick.menu().addAction("Minimum from range").triggered.connect(lambda: self.pick_from_range('minimum')) self.ui.x_axis_pick.menu().addAction("Central value from range").triggered.connect(lambda: self.pick_from_range('central')) self.ui.wavelength_pick.clicked.connect(lambda: self.lines_dialog.show()) save_action = self.toolbar.addAction(QIcon(':/save_20'), 'Save', self.save_spectrum) self.spectrum_plot = QtCommons.nestWidget(self.ui.spectrum_plot_widget, QMathPlotWidget()) self.reference_spectra_dialog = ReferenceSpectraDialog(database) self.reference_spectra_dialog.setup_menu(self.toolbar, self.spectrum_plot.axes, settings) self.object_properties = ObjectProperties(self.fits_file, project=project) self.object_properties_dialog = ObjectPropertiesDialog(settings, self.object_properties) self.toolbar.addAction("Object properties", self.object_properties_dialog.show) self.calibration_model = QStandardItemModel() self.calibration_model.setHorizontalHeaderLabels(["x-axis", "wavelength", "error"]) self.ui.calibration_points.setModel(self.calibration_model) self.ui.calibration_points.selectionModel().selectionChanged.connect(lambda selected, deselected: self.ui.remove_calibration_point.setEnabled(len(selected.indexes()) > 0) ) self.ui.add_calibration_point.clicked.connect(self.add_calibration_point) self.ui.remove_calibration_point.setEnabled(False) self.ui.remove_calibration_point.clicked.connect(self.remove_calibration_point) if project and project.avg_dispersion(): self.ui.set_dispersion.setMenu(QMenu()) self.ui.set_dispersion.menu().addAction('From input value', self.calculate_calibration) self.ui.set_dispersion.menu().addAction('From Project', lambda: self.calculate_calibration(project.avg_dispersion())) else: self.ui.set_dispersion.clicked.connect(self.calculate_calibration) self.ui.point_is_star.toggled.connect(lambda checked: self.ui.wavelength_pick.setEnabled(not checked)) self.ui.point_is_star.toggled.connect(lambda checked: self.ui.point_wavelength.setEnabled(not checked)) self.fits_spectrum.plot_to(self.spectrum_plot.axes) self.toolbar.addSeparator() self.toolbar.addAction("Zoom", self.spectrum_plot.select_zoom) self.toolbar.addAction("Reset Zoom", lambda: self.spectrum_plot.reset_zoom(self.fits_spectrum.spectrum.wavelengths, self.fits_spectrum.spectrum.fluxes.min(), self.fits_spectrum.spectrum.fluxes.max())) self.toolbar.addSeparator() self.lines_dialog = LinesDialog(database, settings, self.spectrum_plot, enable_picker = False, selection_mode = 'single') self.lines_dialog.lines.connect(self.picked_line) hdu_calibration_points = [h for h in self.fits_file if h.name == FitsSpectrum.CALIBRATION_DATA] if len(hdu_calibration_points) > 0: for point in hdu_calibration_points[-1].data: self.add_calibration_point_data(point[0], point[1]) self.calculate_calibration() def picked_from_range(self, type, min, max): min=(self.fits_spectrum.spectrum.wavelength_index(min)) max=(self.fits_spectrum.spectrum.wavelength_index(max)) add_line = lambda x: self.spectrum_plot.add_line("x_axis_pick", self.fits_spectrum.spectrum.wavelengths[x], color='r') set_x_value = lambda x: self.ui.point_x_axis.setValue(x) if type != 'central': subplot = SelectPlottedPoints(self.fits_spectrum.spectrum.fluxes, min, max+1, self.settings, type) subplot.point.connect(add_line) subplot.point.connect(set_x_value) subplot.show() return point = min+(max-min)/2 self.ui.point_x_axis.setValue(point) set_x_value(point) add_line(point) def pick_from_range(self, type): self.spectrum_plot.add_span_selector('pick_x_axis', lambda min,max: self.picked_from_range(type, min, max),direction='horizontal') def remove_calibration_point(self): self.calibration_model.removeRow(self.ui.calibration_points.selectionModel().selectedIndexes()[0].row()) self.calculate_calibration() def add_calibration_point_data(self, x_value, wavelength): x_axis_item = QStandardItem("star" if x_value == 0 else "{}".format(x_value)) x_axis_item.setData(x_value) wavelength_item = QStandardItem("{:.2f}".format(wavelength)) wavelength_item.setData(wavelength) self.calibration_model.appendRow([x_axis_item, wavelength_item, QStandardItem("n/a")]) self.spectrum_plot.rm_element('x_axis_pick') def picked_line(self, lines): self.ui.point_wavelength.setValue(lines[0]['lambda']) def add_calibration_point(self): self.add_calibration_point_data(self.ui.point_x_axis.value(), 0 if self.ui.point_is_star.isChecked() else self.ui.point_wavelength.value()) self.calculate_calibration() def calibration_points(self): return [{'row': row, 'x': self.calibration_model.item(row, 0).data(), 'wavelength': self.calibration_model.item(row, 1).data()} for row in range(self.calibration_model.rowCount())] def calculate_calibration(self, dispersion = None): points_number = self.calibration_model.rowCount() self.ui.set_dispersion.setEnabled(points_number == 1) self.ui.dispersion.setEnabled(points_number == 1) if points_number == 0: self.fits_spectrum.reset() self.lines_dialog.set_picker_enabled(False) else: self.lines_dialog.set_picker_enabled(True) points = sorted(self.calibration_points(), key=lambda point: point['x']) self.fits_spectrum.calibrate(points, dispersion if dispersion else self.ui.dispersion.value() ) for row, value in [(p['row'], "{:.2f}".format( p['wavelength']-self.fits_spectrum.spectrum.wavelengths[p['x']])) for p in points]: self.calibration_model.item(row, 2).setText(value) self.ui.dispersion.setValue(self.fits_spectrum.spectrum.dispersion()) self.fits_spectrum.plot_to(self.spectrum_plot.axes) def save_spectrum(self): if not self.project: save_file_sticky('Save plot...', 'FITS file (.fit)', lambda f: self.save(f[0]), self.settings, CALIBRATED_PROFILE, [RAW_PROFILE]) return self.project.add_file(Project.CALIBRATED_PROFILE, object_properties = self.object_properties, on_added=self.save) def save(self, filename): self.fits_spectrum.save(filename, self.calibration_points())
def __init__(self, fits_file, settings, database, project=None): super(CalibrateSpectrum, self).__init__() self.project = project self.settings = settings self.fits_spectrum = FitsSpectrum(fits_file) self.fits_spectrum.spectrum.normalize_to_max() self.fits_file = fits_file self.ui = Ui_CalibrateSpectrum() self.ui.setupUi(self) self.toolbar = QToolBar('Calibration Toolbar') self.toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.ui.x_axis_pick.setMenu(QMenu()) self.ui.x_axis_pick.menu().addAction( "Maximum from range").triggered.connect( lambda: self.pick_from_range('maximum')) self.ui.x_axis_pick.menu().addAction( "Minimum from range").triggered.connect( lambda: self.pick_from_range('minimum')) self.ui.x_axis_pick.menu().addAction( "Central value from range").triggered.connect( lambda: self.pick_from_range('central')) self.ui.wavelength_pick.clicked.connect( lambda: self.lines_dialog.show()) save_action = self.toolbar.addAction(QIcon(':/save_20'), 'Save', self.save_spectrum) self.spectrum_plot = QtCommons.nestWidget(self.ui.spectrum_plot_widget, QMathPlotWidget()) self.reference_spectra_dialog = ReferenceSpectraDialog(database) self.reference_spectra_dialog.setup_menu(self.toolbar, self.spectrum_plot.axes, settings) self.object_properties = ObjectProperties(self.fits_file, project=project) self.object_properties_dialog = ObjectPropertiesDialog( settings, self.object_properties) self.toolbar.addAction("Object properties", self.object_properties_dialog.show) self.calibration_model = QStandardItemModel() self.calibration_model.setHorizontalHeaderLabels( ["x-axis", "wavelength", "error"]) self.ui.calibration_points.setModel(self.calibration_model) self.ui.calibration_points.selectionModel().selectionChanged.connect( lambda selected, deselected: self.ui.remove_calibration_point. setEnabled(len(selected.indexes()) > 0)) self.ui.add_calibration_point.clicked.connect( self.add_calibration_point) self.ui.remove_calibration_point.setEnabled(False) self.ui.remove_calibration_point.clicked.connect( self.remove_calibration_point) if project and project.avg_dispersion(): self.ui.set_dispersion.setMenu(QMenu()) self.ui.set_dispersion.menu().addAction('From input value', self.calculate_calibration) self.ui.set_dispersion.menu().addAction( 'From Project', lambda: self.calculate_calibration(project.avg_dispersion())) else: self.ui.set_dispersion.clicked.connect(self.calculate_calibration) self.ui.point_is_star.toggled.connect( lambda checked: self.ui.wavelength_pick.setEnabled(not checked)) self.ui.point_is_star.toggled.connect( lambda checked: self.ui.point_wavelength.setEnabled(not checked)) self.fits_spectrum.plot_to(self.spectrum_plot.axes) self.toolbar.addSeparator() self.toolbar.addAction("Zoom", self.spectrum_plot.select_zoom) self.toolbar.addAction( "Reset Zoom", lambda: self.spectrum_plot.reset_zoom( self.fits_spectrum.spectrum.wavelengths, self.fits_spectrum.spectrum.fluxes.min(), self.fits_spectrum.spectrum.fluxes.max())) self.toolbar.addSeparator() self.lines_dialog = LinesDialog(database, settings, self.spectrum_plot, enable_picker=False, selection_mode='single') self.lines_dialog.lines.connect(self.picked_line) hdu_calibration_points = [ h for h in self.fits_file if h.name == FitsSpectrum.CALIBRATION_DATA ] if len(hdu_calibration_points) > 0: for point in hdu_calibration_points[-1].data: self.add_calibration_point_data(point[0], point[1]) self.calculate_calibration()
class CalibrateSpectrum(QWidget): def __init__(self, fits_file, settings, database, project=None): super(CalibrateSpectrum, self).__init__() self.project = project self.settings = settings self.fits_spectrum = FitsSpectrum(fits_file) self.fits_spectrum.spectrum.normalize_to_max() self.fits_file = fits_file self.ui = Ui_CalibrateSpectrum() self.ui.setupUi(self) self.toolbar = QToolBar('Calibration Toolbar') self.toolbar.setToolButtonStyle(Qt.ToolButtonTextBesideIcon) self.ui.x_axis_pick.setMenu(QMenu()) self.ui.x_axis_pick.menu().addAction( "Maximum from range").triggered.connect( lambda: self.pick_from_range('maximum')) self.ui.x_axis_pick.menu().addAction( "Minimum from range").triggered.connect( lambda: self.pick_from_range('minimum')) self.ui.x_axis_pick.menu().addAction( "Central value from range").triggered.connect( lambda: self.pick_from_range('central')) self.ui.wavelength_pick.clicked.connect( lambda: self.lines_dialog.show()) save_action = self.toolbar.addAction(QIcon(':/save_20'), 'Save', self.save_spectrum) self.spectrum_plot = QtCommons.nestWidget(self.ui.spectrum_plot_widget, QMathPlotWidget()) self.reference_spectra_dialog = ReferenceSpectraDialog(database) self.reference_spectra_dialog.setup_menu(self.toolbar, self.spectrum_plot.axes, settings) self.object_properties = ObjectProperties(self.fits_file, project=project) self.object_properties_dialog = ObjectPropertiesDialog( settings, self.object_properties) self.toolbar.addAction("Object properties", self.object_properties_dialog.show) self.calibration_model = QStandardItemModel() self.calibration_model.setHorizontalHeaderLabels( ["x-axis", "wavelength", "error"]) self.ui.calibration_points.setModel(self.calibration_model) self.ui.calibration_points.selectionModel().selectionChanged.connect( lambda selected, deselected: self.ui.remove_calibration_point. setEnabled(len(selected.indexes()) > 0)) self.ui.add_calibration_point.clicked.connect( self.add_calibration_point) self.ui.remove_calibration_point.setEnabled(False) self.ui.remove_calibration_point.clicked.connect( self.remove_calibration_point) if project and project.avg_dispersion(): self.ui.set_dispersion.setMenu(QMenu()) self.ui.set_dispersion.menu().addAction('From input value', self.calculate_calibration) self.ui.set_dispersion.menu().addAction( 'From Project', lambda: self.calculate_calibration(project.avg_dispersion())) else: self.ui.set_dispersion.clicked.connect(self.calculate_calibration) self.ui.point_is_star.toggled.connect( lambda checked: self.ui.wavelength_pick.setEnabled(not checked)) self.ui.point_is_star.toggled.connect( lambda checked: self.ui.point_wavelength.setEnabled(not checked)) self.fits_spectrum.plot_to(self.spectrum_plot.axes) self.toolbar.addSeparator() self.toolbar.addAction("Zoom", self.spectrum_plot.select_zoom) self.toolbar.addAction( "Reset Zoom", lambda: self.spectrum_plot.reset_zoom( self.fits_spectrum.spectrum.wavelengths, self.fits_spectrum.spectrum.fluxes.min(), self.fits_spectrum.spectrum.fluxes.max())) self.toolbar.addSeparator() self.lines_dialog = LinesDialog(database, settings, self.spectrum_plot, enable_picker=False, selection_mode='single') self.lines_dialog.lines.connect(self.picked_line) hdu_calibration_points = [ h for h in self.fits_file if h.name == FitsSpectrum.CALIBRATION_DATA ] if len(hdu_calibration_points) > 0: for point in hdu_calibration_points[-1].data: self.add_calibration_point_data(point[0], point[1]) self.calculate_calibration() def picked_from_range(self, type, min, max): min = (self.fits_spectrum.spectrum.wavelength_index(min)) max = (self.fits_spectrum.spectrum.wavelength_index(max)) add_line = lambda x: self.spectrum_plot.add_line( "x_axis_pick", self.fits_spectrum.spectrum.wavelengths[x], color='r') set_x_value = lambda x: self.ui.point_x_axis.setValue(x) if type != 'central': subplot = SelectPlottedPoints(self.fits_spectrum.spectrum.fluxes, min, max + 1, self.settings, type) subplot.point.connect(add_line) subplot.point.connect(set_x_value) subplot.show() return point = min + (max - min) / 2 self.ui.point_x_axis.setValue(point) set_x_value(point) add_line(point) def pick_from_range(self, type): self.spectrum_plot.add_span_selector( 'pick_x_axis', lambda min, max: self.picked_from_range(type, min, max), direction='horizontal') def remove_calibration_point(self): self.calibration_model.removeRow( self.ui.calibration_points.selectionModel().selectedIndexes() [0].row()) self.calculate_calibration() def add_calibration_point_data(self, x_value, wavelength): x_axis_item = QStandardItem("star" if x_value == 0 else "{}".format(x_value)) x_axis_item.setData(x_value) wavelength_item = QStandardItem("{:.2f}".format(wavelength)) wavelength_item.setData(wavelength) self.calibration_model.appendRow( [x_axis_item, wavelength_item, QStandardItem("n/a")]) self.spectrum_plot.rm_element('x_axis_pick') def picked_line(self, lines): self.ui.point_wavelength.setValue(lines[0]['lambda']) def add_calibration_point(self): self.add_calibration_point_data( self.ui.point_x_axis.value(), 0 if self.ui.point_is_star.isChecked() else self.ui.point_wavelength.value()) self.calculate_calibration() def calibration_points(self): return [{ 'row': row, 'x': self.calibration_model.item(row, 0).data(), 'wavelength': self.calibration_model.item(row, 1).data() } for row in range(self.calibration_model.rowCount())] def calculate_calibration(self, dispersion=None): points_number = self.calibration_model.rowCount() self.ui.set_dispersion.setEnabled(points_number == 1) self.ui.dispersion.setEnabled(points_number == 1) if points_number == 0: self.fits_spectrum.reset() self.lines_dialog.set_picker_enabled(False) else: self.lines_dialog.set_picker_enabled(True) points = sorted(self.calibration_points(), key=lambda point: point['x']) self.fits_spectrum.calibrate( points, dispersion if dispersion else self.ui.dispersion.value()) for row, value in [(p['row'], "{:.2f}".format( p['wavelength'] - self.fits_spectrum.spectrum.wavelengths[p['x']])) for p in points]: self.calibration_model.item(row, 2).setText(value) self.ui.dispersion.setValue(self.fits_spectrum.spectrum.dispersion()) self.fits_spectrum.plot_to(self.spectrum_plot.axes) def save_spectrum(self): if not self.project: save_file_sticky('Save plot...', 'FITS file (.fit)', lambda f: self.save(f[0]), self.settings, CALIBRATED_PROFILE, [RAW_PROFILE]) return self.project.add_file(Project.CALIBRATED_PROFILE, object_properties=self.object_properties, on_added=self.save) def save(self, filename): self.fits_spectrum.save(filename, self.calibration_points())
def __init__(self, fits_file, settings, database, project=None): super(FinishSpectrum, self).__init__() self.settings = settings self.ui = Ui_FinishSpectrum() self.ui.setupUi(self) self.profile_line = None self.project = project self.fits_spectrum = FitsSpectrum(fits_file) self.undo = Undo(self.fits_spectrum.spectrum, self.draw) try: fits_file.index_of('ORIGINAL_DATA') except KeyError: hdu = fits.ImageHDU(data = fits_file[0].data, header = fits_file[0].header, name='ORIGINAL_DATA') fits_file.append(hdu) self.fits_spectrum.spectrum.normalize_to_max() self.spectrum = self.fits_spectrum.spectrum self.spectrum_plot = QtCommons.nestWidget(self.ui.plot, QMathPlotWidget()) self.spectrum_plot.mouse_moved.connect(Instances.MainWindow.print_coordinates) self.split_view() self.toolbar = QToolBar('Finish Spectrum Toolbar') if project: instrument_response_action = QtCommons.addToolbarPopup(self.toolbar, "Instrument Response") instrument_response_action.menu().addAction('From FITS file...', lambda: open_file_sticky('Open Instrument Response Profile', FITS_EXTS, lambda f: self.instrument_response(f[0]), settings, MATH_OPERATION, [RAW_PROFILE])) for instrument_response in project.get_instrument_responses(): print("Adding instrument response {}".format(instrument_response)) instrument_response_action.menu().addAction(os.path.basename(instrument_response[1]), lambda: self.instrument_response(instrument_response[1])) else: self.toolbar.addAction('Instrument Response', lambda: open_file_sticky('Open Instrument Response Profile', FITS_EXTS, lambda f: self.instrument_response(f[0]), settings, MATH_OPERATION, [RAW_PROFILE])) self.toolbar.addAction("Zoom", lambda: self.spectrum_plot.select_zoom(self.profile_plot.axes)) self.toolbar.addAction("Reset Zoom", lambda: self.spectrum_plot.reset_zoom(self.spectrum.wavelengths, self.spectrum.fluxes.min(), self.spectrum.fluxes.max(), self.profile_plot.axes)) remove_action = QtCommons.addToolbarPopup(self.toolbar, "Remove") remove_action.menu().addAction("Before point", lambda: spectrum_trim_dialog(self.spectrum, 'before', self.profile_plot.axes, lambda: self.draw(), self, before_removal=self.undo.save_undo)) remove_action.menu().addAction("After point", lambda: spectrum_trim_dialog(self.spectrum, 'after', self.profile_plot.axes, lambda: self.draw(), self, before_removal=self.undo.save_undo)) self.undo.add_actions(self.toolbar) self.toolbar.addSeparator() self.reference_spectra_dialog = ReferenceSpectraDialog(database, self.fits_spectrum.spectrum) self.reference_spectra_dialog.setup_menu(self.toolbar, self.profile_plot.axes, settings) lines_menu = QtCommons.addToolbarPopup(self.toolbar, "Spectral Lines..") lines_menu.menu().addAction('Lines Database', lambda: self.lines_dialog.show()) lines_menu.menu().addAction('Custom line', self.add_custom_line) labels_action = QtCommons.addToolbarPopup(self.toolbar, "Labels..") self.object_properties = ObjectProperties(fits_file, project=project) labels_action.menu().addAction('Title', self.add_title) if self.object_properties: labels_action.menu().addAction('Information from FITS file', self.add_fits_information_label) labels_action.menu().addAction('Custom', self.add_label) self.object_properties_dialog = ObjectPropertiesDialog(settings, self.object_properties) self.toolbar.addAction("Object properties", self.object_properties_dialog.show) self.labels, self.lines = [], [] for label in self.fits_spectrum.labels(): self.add_label(text=label['text'], coords=label['coords'], type=label['type'], fontsize=label['fontsize']) self.toolbar.addSeparator() if project: self.toolbar.addAction(QIcon(':/image_20'), "Export Image...", lambda: QtCommons.save_file('Export plot to image', 'PNG (*.png);;PDF (*.pdf);;PostScript (*.ps);;SVG (*.svg)', lambda f: self.save_image(f[0]), project.directory_path(Project.EXPORTED_IMAGES))) self.toolbar.addAction(QIcon(':/save_20'), 'Save', self.save_finished_in_project) else: self.toolbar.addAction(QIcon(':/image_20'), "Export Image...", lambda: save_file_sticky('Export plot to image', 'PNG (*.png);;PDF (*.pdf);;PostScript (*.ps);;SVG (*.svg)', lambda f: self.save_image(f[0]), self.settings, EXPORT_IMAGES, [CALIBRATED_PROFILE])) self.toolbar.addAction(QIcon(':/save_20'), 'Save', lambda: save_file_sticky('Save plot...', 'FITS file (.fit)', lambda f: self.__save(f[0]), self.settings, CALIBRATED_PROFILE)) self.lines_dialog = LinesDialog(database, settings, self.spectrum_plot, self.profile_plot.axes) self.lines_dialog.lines.connect(self.add_lines) for line in self.fits_spectrum.lines_labels(): self.lines.append(ReferenceLine(line['text'], line['wavelength'], self.profile_plot.axes, lambda line: self.lines.remove(line), show_wavelength=line['display_wavelength'], fontsize=line['fontsize'], position=line['position']))
class FinishSpectrum(QWidget): def __init__(self, fits_file, settings, database, project=None): super(FinishSpectrum, self).__init__() self.settings = settings self.ui = Ui_FinishSpectrum() self.ui.setupUi(self) self.profile_line = None self.project = project self.fits_spectrum = FitsSpectrum(fits_file) self.undo = Undo(self.fits_spectrum.spectrum, self.draw) try: fits_file.index_of('ORIGINAL_DATA') except KeyError: hdu = fits.ImageHDU(data = fits_file[0].data, header = fits_file[0].header, name='ORIGINAL_DATA') fits_file.append(hdu) self.fits_spectrum.spectrum.normalize_to_max() self.spectrum = self.fits_spectrum.spectrum self.spectrum_plot = QtCommons.nestWidget(self.ui.plot, QMathPlotWidget()) self.spectrum_plot.mouse_moved.connect(Instances.MainWindow.print_coordinates) self.split_view() self.toolbar = QToolBar('Finish Spectrum Toolbar') if project: instrument_response_action = QtCommons.addToolbarPopup(self.toolbar, "Instrument Response") instrument_response_action.menu().addAction('From FITS file...', lambda: open_file_sticky('Open Instrument Response Profile', FITS_EXTS, lambda f: self.instrument_response(f[0]), settings, MATH_OPERATION, [RAW_PROFILE])) for instrument_response in project.get_instrument_responses(): print("Adding instrument response {}".format(instrument_response)) instrument_response_action.menu().addAction(os.path.basename(instrument_response[1]), lambda: self.instrument_response(instrument_response[1])) else: self.toolbar.addAction('Instrument Response', lambda: open_file_sticky('Open Instrument Response Profile', FITS_EXTS, lambda f: self.instrument_response(f[0]), settings, MATH_OPERATION, [RAW_PROFILE])) self.toolbar.addAction("Zoom", lambda: self.spectrum_plot.select_zoom(self.profile_plot.axes)) self.toolbar.addAction("Reset Zoom", lambda: self.spectrum_plot.reset_zoom(self.spectrum.wavelengths, self.spectrum.fluxes.min(), self.spectrum.fluxes.max(), self.profile_plot.axes)) remove_action = QtCommons.addToolbarPopup(self.toolbar, "Remove") remove_action.menu().addAction("Before point", lambda: spectrum_trim_dialog(self.spectrum, 'before', self.profile_plot.axes, lambda: self.draw(), self, before_removal=self.undo.save_undo)) remove_action.menu().addAction("After point", lambda: spectrum_trim_dialog(self.spectrum, 'after', self.profile_plot.axes, lambda: self.draw(), self, before_removal=self.undo.save_undo)) self.undo.add_actions(self.toolbar) self.toolbar.addSeparator() self.reference_spectra_dialog = ReferenceSpectraDialog(database, self.fits_spectrum.spectrum) self.reference_spectra_dialog.setup_menu(self.toolbar, self.profile_plot.axes, settings) lines_menu = QtCommons.addToolbarPopup(self.toolbar, "Spectral Lines..") lines_menu.menu().addAction('Lines Database', lambda: self.lines_dialog.show()) lines_menu.menu().addAction('Custom line', self.add_custom_line) labels_action = QtCommons.addToolbarPopup(self.toolbar, "Labels..") self.object_properties = ObjectProperties(fits_file, project=project) labels_action.menu().addAction('Title', self.add_title) if self.object_properties: labels_action.menu().addAction('Information from FITS file', self.add_fits_information_label) labels_action.menu().addAction('Custom', self.add_label) self.object_properties_dialog = ObjectPropertiesDialog(settings, self.object_properties) self.toolbar.addAction("Object properties", self.object_properties_dialog.show) self.labels, self.lines = [], [] for label in self.fits_spectrum.labels(): self.add_label(text=label['text'], coords=label['coords'], type=label['type'], fontsize=label['fontsize']) self.toolbar.addSeparator() if project: self.toolbar.addAction(QIcon(':/image_20'), "Export Image...", lambda: QtCommons.save_file('Export plot to image', 'PNG (*.png);;PDF (*.pdf);;PostScript (*.ps);;SVG (*.svg)', lambda f: self.save_image(f[0]), project.directory_path(Project.EXPORTED_IMAGES))) self.toolbar.addAction(QIcon(':/save_20'), 'Save', self.save_finished_in_project) else: self.toolbar.addAction(QIcon(':/image_20'), "Export Image...", lambda: save_file_sticky('Export plot to image', 'PNG (*.png);;PDF (*.pdf);;PostScript (*.ps);;SVG (*.svg)', lambda f: self.save_image(f[0]), self.settings, EXPORT_IMAGES, [CALIBRATED_PROFILE])) self.toolbar.addAction(QIcon(':/save_20'), 'Save', lambda: save_file_sticky('Save plot...', 'FITS file (.fit)', lambda f: self.__save(f[0]), self.settings, CALIBRATED_PROFILE)) self.lines_dialog = LinesDialog(database, settings, self.spectrum_plot, self.profile_plot.axes) self.lines_dialog.lines.connect(self.add_lines) for line in self.fits_spectrum.lines_labels(): self.lines.append(ReferenceLine(line['text'], line['wavelength'], self.profile_plot.axes, lambda line: self.lines.remove(line), show_wavelength=line['display_wavelength'], fontsize=line['fontsize'], position=line['position'])) def add_custom_line(self): wl = QInputDialog.getDouble(self, "Custom Line", "Enter line wavelength in Å", self.fits_spectrum.spectrum.wavelengths[0],self.fits_spectrum.spectrum.wavelengths[0],self.fits_spectrum.spectrum.wavelengths[-1],3) if not wl[1]: return self.add_lines([{'name': 'Custom Line', 'lambda': wl[0]}]) def add_lines(self, lines): for line in lines: self.lines.append(ReferenceLine(line['name'], line['lambda'], self.profile_plot.axes, lambda line: self.lines.remove(line))) def synthetize_img(wavelengths, fluxes): f_fluxes = lambda f: math.pow(f, 3/5) colors = [wavelength_to_rgb(w/10., f_fluxes(fluxes[i])) for i,w in enumerate(wavelengths)] im_height = 150 colors = np.array(colors*im_height).reshape(im_height,len(colors),4) return colors, im_height def split_view(self): figure = self.spectrum_plot.figure figure.clear() self.gs = gridspec.GridSpec(40,1) self.profile_plot = figure.add_subplot(self.gs[0:-6]) self.synthetize = figure.add_subplot(self.gs[-3:-1], sharex = self.profile_plot) self.synthetize.yaxis.set_visible(False) self.synthetize.xaxis.set_visible(False) self.draw() def draw(self): # self.profile_plot.clear() if self.profile_line: self.profile_line.remove() self.profile_line = self.profile_plot.plot(self.spectrum.wavelengths, self.spectrum.fluxes, color='blue')[0] self.synthetize.axes.set_axis_bgcolor('black') with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(FinishSpectrum.synthetize_img, self.spectrum.wavelengths, self.spectrum.fluxes) future.add_done_callback(lambda f: self.synthetize.imshow(f.result()[0], extent=[self.spectrum.wavelengths[0], self.spectrum.wavelengths[-1], 0, f.result()[1]]) ) self.profile_plot.axes.set_xlabel('wavelength (Å)') self.profile_plot.axes.set_ylabel('relative flux') self.profile_plot.axes.xaxis.set_major_locator(MaxNLocator(16)) # TODO: settings for customization? self.profile_plot.axes.xaxis.set_minor_locator(MaxNLocator(200)) self.spectrum_plot.figure.canvas.draw() self.gs.tight_layout(self.spectrum_plot.figure) def instrument_response(self, filename): print("Applying instrument response {}".format(filename)) instrument_response_file = fits.open(filename) instrument_response = FitsSpectrum(instrument_response_file) response = instrument_response.spectrum response.normalize_to_max() range = (max(response.wavelengths[0], self.spectrum.wavelengths[0] ), min(response.wavelengths[-1], self.spectrum.wavelengths[-1])) self.spectrum.cut(self.spectrum.wavelength_index(range[0]), self.spectrum.wavelength_index(range[1])) spline = InterpolatedUnivariateSpline(response.wavelengths, response.fluxes) response_data = [spline(x) for x in self.spectrum.wavelengths] self.spectrum.fluxes /= response_data self.spectrum.normalize_to_max() self.draw() def save_image(self, filename): Notification('Image {} saved in {}'.format(os.path.basename(filename), os.path.dirname(filename)), title='File Saved', type='success', timeout=5) self.spectrum_plot.figure.savefig(filename, bbox_inches='tight', dpi=300) def save_finished_in_project(self): self.project.add_file(Project.FINISHED_PROFILES, self.__save, self.object_properties) def __save(self, filename): self.fits_spectrum.save(filename, spectral_lines = self.lines, labels = self.labels) def add_title(self): title = self.object_properties.name if self.object_properties else 'Title - double click to edit' self.add_label(text=title, coords=(self.spectrum.wavelengths[len(self.spectrum.wavelengths)/2-100], 0.95), fontsize=25, type='lineedit') def add_fits_information_label(self): info_text = "Object Name: {}, type: {}, spectral class: {}\nCoordinates: {}\nDate: {}\nObserver: {}\nEquipment: {}\nPosition: {}".format( self.object_properties.name, self.object_properties.type, self.object_properties.sptype, self.object_properties.printable_coordinates(), self.object_properties.date.toString(), self.object_properties.observer, self.object_properties.equipment, self.object_properties.position ) self.add_label(info_text, type='textbox', coords=(self.spectrum.wavelengths[len(self.spectrum.wavelengths)/4*3], 0.80), fontsize=14) self.profile_plot.figure.canvas.draw() def add_label(self, text=None, type='textbox', coords = None, fontsize = 12, color='black'): if not coords: coords = (self.spectrum.wavelengths[len(self.spectrum.wavelengths)/2], 0.5) self.labels.append((type, MoveableLabel(text=text if text else 'Label - double click to edit', on_dblclick=lambda l: self.edit_label(l, type=type), x=coords[0], y=coords[1], fontsize=fontsize, color=color, axes=self.profile_plot.axes))) self.profile_plot.figure.canvas.draw() def edit_label(self, label, type='lineedit'): def remove_label(self, label, dialog): label.remove() self.labels.remove([l for l in self.labels if l[1] == label][0]) self.profile_plot.figure.canvas.draw() dialog.reject() dialog = QDialog() dialog.setWindowTitle("Edit Label") dialog.setLayout(QVBoxLayout()) font_size = QSpinBox() font_size.setValue(label.get_fontsize()) dialog.layout().addWidget(QLabel("Font Size")) dialog.layout().addWidget(font_size) text_edit = None if type == 'lineedit': text_edit = QLineEdit(label.get_text()) else: text_edit = QTextEdit() text_edit.setPlainText(label.get_text()) dialog.layout().addWidget(QLabel("Text")) dialog.layout().addWidget(text_edit) button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) button_box.accepted.connect(dialog.accept) button_box.rejected.connect(dialog.reject) remove_button = QPushButton('Remove') remove_button.clicked.connect(lambda: remove_label(self, label, dialog)) dialog.layout().addWidget(remove_button) dialog.layout().addWidget(button_box) if QDialog.Accepted != dialog.exec(): return label.set_text(text_edit.text() if type=='lineedit' else text_edit.toPlainText()) label.set_fontsize(font_size.value()) label.axes.figure.canvas.draw()
def __init__(self, fits_file, settings, database, project=None): super(FinishSpectrum, self).__init__() self.settings = settings self.ui = Ui_FinishSpectrum() self.ui.setupUi(self) self.profile_line = None self.project = project self.fits_spectrum = FitsSpectrum(fits_file) self.undo = Undo(self.fits_spectrum.spectrum, self.draw) try: fits_file.index_of('ORIGINAL_DATA') except KeyError: hdu = fits.ImageHDU(data=fits_file[0].data, header=fits_file[0].header, name='ORIGINAL_DATA') fits_file.append(hdu) self.fits_spectrum.spectrum.normalize_to_max() self.spectrum = self.fits_spectrum.spectrum self.spectrum_plot = QtCommons.nestWidget(self.ui.plot, QMathPlotWidget()) self.spectrum_plot.mouse_moved.connect( Instances.MainWindow.print_coordinates) self.split_view() self.toolbar = QToolBar('Finish Spectrum Toolbar') if project: instrument_response_action = QtCommons.addToolbarPopup( self.toolbar, "Instrument Response") instrument_response_action.menu().addAction( 'From FITS file...', lambda: open_file_sticky( 'Open Instrument Response Profile', FITS_EXTS, lambda f: self.instrument_response(f[ 0]), settings, MATH_OPERATION, [RAW_PROFILE])) for instrument_response in project.get_instrument_responses(): print("Adding instrument response {}".format( instrument_response)) instrument_response_action.menu().addAction( os.path.basename(instrument_response[1]), lambda: self.instrument_response(instrument_response[1])) else: self.toolbar.addAction( 'Instrument Response', lambda: open_file_sticky( 'Open Instrument Response Profile', FITS_EXTS, lambda f: self.instrument_response(f[ 0]), settings, MATH_OPERATION, [RAW_PROFILE])) self.toolbar.addAction( "Zoom", lambda: self.spectrum_plot.select_zoom(self.profile_plot.axes)) self.toolbar.addAction( "Reset Zoom", lambda: self.spectrum_plot.reset_zoom( self.spectrum.wavelengths, self.spectrum.fluxes.min(), self.spectrum.fluxes.max(), self.profile_plot.axes)) remove_action = QtCommons.addToolbarPopup(self.toolbar, "Remove") remove_action.menu().addAction( "Before point", lambda: spectrum_trim_dialog(self.spectrum, 'before', self.profile_plot.axes, lambda: self.draw(), self, before_removal=self.undo.save_undo)) remove_action.menu().addAction( "After point", lambda: spectrum_trim_dialog(self.spectrum, 'after', self.profile_plot.axes, lambda: self.draw(), self, before_removal=self.undo.save_undo)) self.undo.add_actions(self.toolbar) self.toolbar.addSeparator() self.reference_spectra_dialog = ReferenceSpectraDialog( database, self.fits_spectrum.spectrum) self.reference_spectra_dialog.setup_menu(self.toolbar, self.profile_plot.axes, settings) lines_menu = QtCommons.addToolbarPopup(self.toolbar, "Spectral Lines..") lines_menu.menu().addAction('Lines Database', lambda: self.lines_dialog.show()) lines_menu.menu().addAction('Custom line', self.add_custom_line) labels_action = QtCommons.addToolbarPopup(self.toolbar, "Labels..") self.object_properties = ObjectProperties(fits_file, project=project) labels_action.menu().addAction('Title', self.add_title) if self.object_properties: labels_action.menu().addAction('Information from FITS file', self.add_fits_information_label) labels_action.menu().addAction('Custom', self.add_label) self.object_properties_dialog = ObjectPropertiesDialog( settings, self.object_properties) self.toolbar.addAction("Object properties", self.object_properties_dialog.show) self.labels, self.lines = [], [] for label in self.fits_spectrum.labels(): self.add_label(text=label['text'], coords=label['coords'], type=label['type'], fontsize=label['fontsize']) self.toolbar.addSeparator() if project: self.toolbar.addAction( QIcon(':/image_20'), "Export Image...", lambda: QtCommons.save_file( 'Export plot to image', 'PNG (*.png);;PDF (*.pdf);;PostScript (*.ps);;SVG (*.svg)', lambda f: self.save_image(f[0]), project.directory_path(Project.EXPORTED_IMAGES))) self.toolbar.addAction(QIcon(':/save_20'), 'Save', self.save_finished_in_project) else: self.toolbar.addAction( QIcon(':/image_20'), "Export Image...", lambda: save_file_sticky( 'Export plot to image', 'PNG (*.png);;PDF (*.pdf);;PostScript (*.ps);;SVG (*.svg)', lambda f: self.save_image(f[0]), self.settings, EXPORT_IMAGES, [CALIBRATED_PROFILE])) self.toolbar.addAction( QIcon(':/save_20'), 'Save', lambda: save_file_sticky( 'Save plot...', 'FITS file (.fit)', lambda f: self.__save( f[0]), self.settings, CALIBRATED_PROFILE)) self.lines_dialog = LinesDialog(database, settings, self.spectrum_plot, self.profile_plot.axes) self.lines_dialog.lines.connect(self.add_lines) for line in self.fits_spectrum.lines_labels(): self.lines.append( ReferenceLine(line['text'], line['wavelength'], self.profile_plot.axes, lambda line: self.lines.remove(line), show_wavelength=line['display_wavelength'], fontsize=line['fontsize'], position=line['position']))
class FinishSpectrum(QWidget): def __init__(self, fits_file, settings, database, project=None): super(FinishSpectrum, self).__init__() self.settings = settings self.ui = Ui_FinishSpectrum() self.ui.setupUi(self) self.profile_line = None self.project = project self.fits_spectrum = FitsSpectrum(fits_file) self.undo = Undo(self.fits_spectrum.spectrum, self.draw) try: fits_file.index_of('ORIGINAL_DATA') except KeyError: hdu = fits.ImageHDU(data=fits_file[0].data, header=fits_file[0].header, name='ORIGINAL_DATA') fits_file.append(hdu) self.fits_spectrum.spectrum.normalize_to_max() self.spectrum = self.fits_spectrum.spectrum self.spectrum_plot = QtCommons.nestWidget(self.ui.plot, QMathPlotWidget()) self.spectrum_plot.mouse_moved.connect( Instances.MainWindow.print_coordinates) self.split_view() self.toolbar = QToolBar('Finish Spectrum Toolbar') if project: instrument_response_action = QtCommons.addToolbarPopup( self.toolbar, "Instrument Response") instrument_response_action.menu().addAction( 'From FITS file...', lambda: open_file_sticky( 'Open Instrument Response Profile', FITS_EXTS, lambda f: self.instrument_response(f[ 0]), settings, MATH_OPERATION, [RAW_PROFILE])) for instrument_response in project.get_instrument_responses(): print("Adding instrument response {}".format( instrument_response)) instrument_response_action.menu().addAction( os.path.basename(instrument_response[1]), lambda: self.instrument_response(instrument_response[1])) else: self.toolbar.addAction( 'Instrument Response', lambda: open_file_sticky( 'Open Instrument Response Profile', FITS_EXTS, lambda f: self.instrument_response(f[ 0]), settings, MATH_OPERATION, [RAW_PROFILE])) self.toolbar.addAction( "Zoom", lambda: self.spectrum_plot.select_zoom(self.profile_plot.axes)) self.toolbar.addAction( "Reset Zoom", lambda: self.spectrum_plot.reset_zoom( self.spectrum.wavelengths, self.spectrum.fluxes.min(), self.spectrum.fluxes.max(), self.profile_plot.axes)) remove_action = QtCommons.addToolbarPopup(self.toolbar, "Remove") remove_action.menu().addAction( "Before point", lambda: spectrum_trim_dialog(self.spectrum, 'before', self.profile_plot.axes, lambda: self.draw(), self, before_removal=self.undo.save_undo)) remove_action.menu().addAction( "After point", lambda: spectrum_trim_dialog(self.spectrum, 'after', self.profile_plot.axes, lambda: self.draw(), self, before_removal=self.undo.save_undo)) self.undo.add_actions(self.toolbar) self.toolbar.addSeparator() self.reference_spectra_dialog = ReferenceSpectraDialog( database, self.fits_spectrum.spectrum) self.reference_spectra_dialog.setup_menu(self.toolbar, self.profile_plot.axes, settings) lines_menu = QtCommons.addToolbarPopup(self.toolbar, "Spectral Lines..") lines_menu.menu().addAction('Lines Database', lambda: self.lines_dialog.show()) lines_menu.menu().addAction('Custom line', self.add_custom_line) labels_action = QtCommons.addToolbarPopup(self.toolbar, "Labels..") self.object_properties = ObjectProperties(fits_file, project=project) labels_action.menu().addAction('Title', self.add_title) if self.object_properties: labels_action.menu().addAction('Information from FITS file', self.add_fits_information_label) labels_action.menu().addAction('Custom', self.add_label) self.object_properties_dialog = ObjectPropertiesDialog( settings, self.object_properties) self.toolbar.addAction("Object properties", self.object_properties_dialog.show) self.labels, self.lines = [], [] for label in self.fits_spectrum.labels(): self.add_label(text=label['text'], coords=label['coords'], type=label['type'], fontsize=label['fontsize']) self.toolbar.addSeparator() if project: self.toolbar.addAction( QIcon(':/image_20'), "Export Image...", lambda: QtCommons.save_file( 'Export plot to image', 'PNG (*.png);;PDF (*.pdf);;PostScript (*.ps);;SVG (*.svg)', lambda f: self.save_image(f[0]), project.directory_path(Project.EXPORTED_IMAGES))) self.toolbar.addAction(QIcon(':/save_20'), 'Save', self.save_finished_in_project) else: self.toolbar.addAction( QIcon(':/image_20'), "Export Image...", lambda: save_file_sticky( 'Export plot to image', 'PNG (*.png);;PDF (*.pdf);;PostScript (*.ps);;SVG (*.svg)', lambda f: self.save_image(f[0]), self.settings, EXPORT_IMAGES, [CALIBRATED_PROFILE])) self.toolbar.addAction( QIcon(':/save_20'), 'Save', lambda: save_file_sticky( 'Save plot...', 'FITS file (.fit)', lambda f: self.__save( f[0]), self.settings, CALIBRATED_PROFILE)) self.lines_dialog = LinesDialog(database, settings, self.spectrum_plot, self.profile_plot.axes) self.lines_dialog.lines.connect(self.add_lines) for line in self.fits_spectrum.lines_labels(): self.lines.append( ReferenceLine(line['text'], line['wavelength'], self.profile_plot.axes, lambda line: self.lines.remove(line), show_wavelength=line['display_wavelength'], fontsize=line['fontsize'], position=line['position'])) def add_custom_line(self): wl = QInputDialog.getDouble( self, "Custom Line", "Enter line wavelength in Å", self.fits_spectrum.spectrum.wavelengths[0], self.fits_spectrum.spectrum.wavelengths[0], self.fits_spectrum.spectrum.wavelengths[-1], 3) if not wl[1]: return self.add_lines([{'name': 'Custom Line', 'lambda': wl[0]}]) def add_lines(self, lines): for line in lines: self.lines.append( ReferenceLine(line['name'], line['lambda'], self.profile_plot.axes, lambda line: self.lines.remove(line))) def synthetize_img(wavelengths, fluxes): f_fluxes = lambda f: math.pow(f, 3 / 5) colors = [ wavelength_to_rgb(w / 10., f_fluxes(fluxes[i])) for i, w in enumerate(wavelengths) ] im_height = 150 colors = np.array(colors * im_height).reshape(im_height, len(colors), 4) return colors, im_height def split_view(self): figure = self.spectrum_plot.figure figure.clear() self.gs = gridspec.GridSpec(40, 1) self.profile_plot = figure.add_subplot(self.gs[0:-6]) self.synthetize = figure.add_subplot(self.gs[-3:-1], sharex=self.profile_plot) self.synthetize.yaxis.set_visible(False) self.synthetize.xaxis.set_visible(False) self.draw() def draw(self): # self.profile_plot.clear() if self.profile_line: self.profile_line.remove() self.profile_line = self.profile_plot.plot(self.spectrum.wavelengths, self.spectrum.fluxes, color='blue')[0] self.synthetize.axes.set_facecolor('black') with ThreadPoolExecutor(max_workers=1) as executor: future = executor.submit(FinishSpectrum.synthetize_img, self.spectrum.wavelengths, self.spectrum.fluxes) future.add_done_callback(lambda f: self.synthetize.imshow( f.result()[0], extent=[ self.spectrum.wavelengths[0], self.spectrum.wavelengths[ -1], 0, f.result()[1] ])) self.profile_plot.axes.set_xlabel('wavelength (Å)') self.profile_plot.axes.set_ylabel('relative flux') self.profile_plot.axes.xaxis.set_major_locator( MaxNLocator(16)) # TODO: settings for customization? self.profile_plot.axes.xaxis.set_minor_locator(MaxNLocator(200)) self.spectrum_plot.figure.canvas.draw() self.gs.tight_layout(self.spectrum_plot.figure) def instrument_response(self, filename): print("Applying instrument response {}".format(filename)) instrument_response_file = fits.open(filename) instrument_response = FitsSpectrum(instrument_response_file) response = instrument_response.spectrum response.normalize_to_max() range = (max(response.wavelengths[0], self.spectrum.wavelengths[0]), min(response.wavelengths[-1], self.spectrum.wavelengths[-1])) self.spectrum.cut(self.spectrum.wavelength_index(range[0]), self.spectrum.wavelength_index(range[1])) spline = InterpolatedUnivariateSpline(response.wavelengths, response.fluxes) response_data = [spline(x) for x in self.spectrum.wavelengths] self.spectrum.fluxes /= response_data self.spectrum.normalize_to_max() self.draw() def save_image(self, filename): Notification('Image {} saved in {}'.format(os.path.basename(filename), os.path.dirname(filename)), title='File Saved', type='success', timeout=5) self.spectrum_plot.figure.savefig(filename, bbox_inches='tight', dpi=300) def save_finished_in_project(self): self.project.add_file(Project.FINISHED_PROFILES, self.__save, self.object_properties) def __save(self, filename): self.fits_spectrum.save(filename, spectral_lines=self.lines, labels=self.labels) def add_title(self): title = self.object_properties.name if self.object_properties else 'Title - double click to edit' self.add_label( text=title, coords=( self.spectrum.wavelengths[len(self.spectrum.wavelengths) / 2 - 100], 0.95), fontsize=25, type='lineedit') def add_fits_information_label(self): info_text = "Object Name: {}, type: {}, spectral class: {}\nCoordinates: {}\nDate: {}\nObserver: {}\nEquipment: {}\nPosition: {}".format( self.object_properties.name, self.object_properties.type, self.object_properties.sptype, self.object_properties.printable_coordinates(), self.object_properties.date.toString(), self.object_properties.observer, self.object_properties.equipment, self.object_properties.position) self.add_label( info_text, type='textbox', coords=(self.spectrum.wavelengths[len(self.spectrum.wavelengths) / 4 * 3], 0.80), fontsize=14) self.profile_plot.figure.canvas.draw() def add_label(self, text=None, type='textbox', coords=None, fontsize=12, color='black'): if not coords: coords = ( self.spectrum.wavelengths[len(self.spectrum.wavelengths) / 2], 0.5) self.labels.append( (type, MoveableLabel( text=text if text else 'Label - double click to edit', on_dblclick=lambda l: self.edit_label(l, type=type), x=coords[0], y=coords[1], fontsize=fontsize, color=color, axes=self.profile_plot.axes))) self.profile_plot.figure.canvas.draw() def edit_label(self, label, type='lineedit'): def remove_label(self, label, dialog): label.remove() self.labels.remove([l for l in self.labels if l[1] == label][0]) self.profile_plot.figure.canvas.draw() dialog.reject() dialog = QDialog() dialog.setWindowTitle("Edit Label") dialog.setLayout(QVBoxLayout()) font_size = QSpinBox() font_size.setValue(label.get_fontsize()) dialog.layout().addWidget(QLabel("Font Size")) dialog.layout().addWidget(font_size) text_edit = None if type == 'lineedit': text_edit = QLineEdit(label.get_text()) else: text_edit = QTextEdit() text_edit.setPlainText(label.get_text()) dialog.layout().addWidget(QLabel("Text")) dialog.layout().addWidget(text_edit) button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) button_box.accepted.connect(dialog.accept) button_box.rejected.connect(dialog.reject) remove_button = QPushButton('Remove') remove_button.clicked.connect( lambda: remove_label(self, label, dialog)) dialog.layout().addWidget(remove_button) dialog.layout().addWidget(button_box) if QDialog.Accepted != dialog.exec(): return label.set_text(text_edit.text() if type == 'lineedit' else text_edit.toPlainText()) label.set_fontsize(font_size.value()) label.axes.figure.canvas.draw()
def __open_reference(self, file, axes): fits_spectrum = FitsSpectrum(fits.open(file)) self.__open(fits_spectrum.spectrum, axes)