def __init__(self): super().__init__() self.ui = Ui_filterwheel_settings_widget() self.ui.setupUi(self) #FIXME have CameraControl send signals - dont connect on internal widgets from here! self.ui.filterwheel_setting_setup.pressed.connect(self.filterwheel_setup) self.ui.filterwheel_setting_connect.pressed.connect(self.filterwheel_connect) self.ui.filterwheel_setting_disconnect.pressed.connect(self.filterwheel_disconnect) self.ui.filterwheel_setting_move.pressed.connect(self.filterwheel_move) self.filterwheel_manager = AppContainer.find('/dev/filterwheel') self.settings = AppContainer.find('/program_settings') if self.settings.filterwheel_driver: self.set_device_label() self.set_widget_states() # we store the names from the manager for filters self.names = None # polling camera status self.timer = QtCore.QTimer() self.timer.timeout.connect(self.filterwheel_status_poll) self.timer.start(1000)
def __init__(self): super().__init__() self.ui = Ui_mount_settings_widget() self.ui.setupUi(self) self.ui.mount_setting_setup.pressed.connect(self.mount_setup) self.ui.mount_setting_connect.pressed.connect(self.mount_connect) self.ui.mount_setting_disconnect.pressed.connect(self.mount_disconnect) self.mount_manager = AppContainer.find('/dev/mount') self.settings = AppContainer.find('/program_settings') # for DEBUG - should be None normally #self.mount_driver = 'ASCOM.Simulator.Telescope' #self.mount_driver = if self.settings.mount_driver: self.set_device_label() self.set_widget_states() # polling camera status self.timer = QtCore.QTimer() self.timer.timeout.connect(self.mount_status_poll) self.timer.start(1000)
def __init__(self): self.socket = None self.requests = {} self.request_id = 0 self.connected = False self.guiding = False self.dither_state = DitherState.IDLE self.dither_timeout_timer = None self.signals = PHD2ManagerSignals() AppContainer.register('/dev/phd2', self)
def __init__(self): super().__init__() self.ui = Ui_PHD2ControlUI() self.ui.setupUi(self) #FIXME have CameraControl send signals - dont connect on internal widgets from here! self.ui.phd2_connect.toggled.connect(self.phd2_connect_toggled) self.ui.phd2_pause.toggled.connect(self.phd2_pause_toggled) self.ui.phd2_settings.pressed.connect(self.phd2_settings) self.phd2_manager = PHD2Manager() self.phd2_manager.signals.request.connect(self.request_event) # self.phd2_manager.signals.tcperror.connect(self.tcperror) # self.phd2_manager.signals.connect_close.connect(self.connect_close) self.phd2_manager.signals.disconnected.connect(self.disconnected) self.disconnecting = False #self.settings = settings self.settings = AppContainer.find('/program_settings') self.set_widget_states() # polling phd2 status self.timer = QtCore.QTimer() self.timer.timeout.connect(self.phd2_status_poll) self.timer.start(5000)
def phd2_dither_timeout_event(self): logging.info('phd2_dither_timeout event received') if not self.exposure_ongoing: logging.error( 'phd2_dither_timeout_event: no exposure ongoing ignoring') return program_settings = AppContainer.find('/program_settings') if program_settings is None: logging.error( 'phd2_dither_timeout_event: cannot retrieve program settings!') QtWidgets.QMessageBox.critical( None, 'Error', 'Unknown error reading program settings in ' 'phd2_dither_timeout_event - aborting!', QtWidgets.QMessageBox.Ok) self.end_sequence(abort=True) return if program_settings.sequence_phd2_stop_ditherfail: logging.error( 'phd2_dither_timeout_event: dither timed out - aborting') QtWidgets.QMessageBox.critical( None, 'PHD2 Dither Failed', 'PHD2 dither operation ' 'did not settle in time - aborting sequence!', QtWidgets.QMessageBox.Ok) self.end_sequence(abort=True) return else: logging.error( 'phd2_dither_timeout_event: ignoring based on program settings' )
def phd2_guiding_stop_event(self): logging.error('phd2_guiding_stop_event: lost guiding event') if not self.exposure_ongoing: logging.error( 'phd2_guiding_stop_event: no exposure ongoing ignoring') return program_settings = AppContainer.find('/program_settings') if program_settings is None: logging.error( 'phd2_guiding_stop_event: cannot retrieve program settings!') QtWidgets.QMessageBox.critical( None, 'Error', 'Unknown error reading program settings - aborting!', QtWidgets.QMessageBox.Ok) self.end_sequence(abort=True) return if program_settings.sequence_phd2_stop_loseguiding: logging.error('phd2_guiding_stop_event: lost guiding - aborting') QtWidgets.QMessageBox.critical( None, 'PHD2 Guiding Stopped', 'PHD2 has stopped ' 'guiding - aborting sequence!', QtWidgets.QMessageBox.Ok) self.end_sequence(abort=True) return else: logging.error( 'phd2_guiding_stop_event: ignoring based on program settings')
def device_setup_ui(device, device_class): backend_attr = f'{device_class}_backend' driver_attr = f'{device_class}_driver' manager_attr = f'{device_class}_manager' old_backend = device.settings.get_key(backend_attr) logging.info(f'device_setup_ui: old backend = {old_backend}') new_backend = backend_setup_ui(old_backend) logging.info(f'device_setup_ui: new backend = {new_backend}') if new_backend != old_backend: backend_changed = True device.settings.set_key(backend_attr, new_backend) device_manager = AppContainer.find('/dev') manager_fn = f'set_{device_class}_backend' fn = getattr(device_manager, manager_fn) logging.debug(f'manager_fn = {manager_fn} fn={fn}') if fn is not None: logging.debug(f'calling {fn}') fn(new_backend) else: logging.error(f'unabled to find {manager_fn}') return None device.settings.set_key(f'{device_class}_driver', '') device.settings.write() else: backend_changed = False # if backend changed call to set_<device_class>_backend() above # will change /dev/<device_class>_backend backend = AppContainer.find(f'/dev/{device_class}_backend') logging.debug(f'device_setup_ui: backend = {backend}') # update internal data structures to reflect changes # at device manager level #device.settings.set_key(f'{device_class}_driver', '') #logging.debug('calling update_manager()') #device.update_manager() new_choice = driver_setup_ui(backend, getattr(device, manager_attr), device.settings.get_key(driver_attr), device_class) if new_choice is not None: device.settings.set_key(driver_attr, new_choice) device.settings.write() device.set_device_label()
def __init__(self): super().__init__() self.ui = Ui_PHD2SettingsDialog() self.ui.setupUi(self) self.settings = AppContainer.find('/program_settings') self.update_widgets()
def __init__(self): super().__init__() self.ui = Ui_focuser_settings_widget() self.ui.setupUi(self) # FIXME have CameraControl send signals - dont connect on internal widgets from here! self.ui.focuser_setting_setup.pressed.connect(self.focuser_setup) self.ui.focuser_setting_connect.pressed.connect(self.focuser_connect) self.ui.focuser_setting_disconnect.pressed.connect( self.focuser_disconnect) self.ui.focuser_setting_movein_small.pressed.connect( self.focuser_move_relative) self.ui.focuser_setting_moveout_small.pressed.connect( self.focuser_move_relative) self.ui.focuser_setting_movein_large.pressed.connect( self.focuser_move_relative) self.ui.focuser_setting_moveout_large.pressed.connect( self.focuser_move_relative) self.ui.focuser_setting_moveabs_move.pressed.connect( self.focuser_move_absolute) self.ui.focuser_setting_moveabs_stop.pressed.connect( self.focuser_move_stop) self.update_manager() # for DEBUG - should be None normally #self.focuser_driver = 'ASCOM.Simulator.Focuser' #self.settings = settings self.settings = AppContainer.find('/program_settings') if self.settings.focuser_driver: self.set_device_label() #self.ui.focuser_driver_label.setText(self.settings.focuser_driver) self.set_widget_states() self.small_step = 15 self.large_step = 100 self.ui.focuser_setting_small_spinbox.setValue(self.small_step) self.ui.focuser_setting_large_spinbox.setValue(self.large_step) # FIXME need a signal connection so we can track spinboxes and save # requested small and large step size persistently # polling camera status self.timer = QtCore.QTimer() self.timer.timeout.connect(self.focuser_status_poll) self.timer.start(1000)
def __init__(self): super().__init__() self.ui = Ui_camera_settings_widget() self.ui.setupUi(self) # FIXME have CameraControl send signals - dont connect on internal widgets from here! self.ui.camera_setting_setup.pressed.connect(self.camera_setup) self.ui.camera_setting_connect.pressed.connect(self.camera_connect) self.ui.camera_setting_disconnect.pressed.connect( self.camera_disconnect) self.ui.camera_setting_expose.pressed.connect(self.expose_pressed) self.ui.camera_setting_binning_spinbox.valueChanged.connect( self.binning_changed) self.ui.camera_setting_roi_set.pressed.connect(self.set_roi) self.ui.camera_setting_cooleronoff.toggled.connect( self.cooleronoff_handler) self.ui.camera_setting_coolersetpt.valueChanged.connect( self.cooler_setpt_changed) self.ui.camera_setting_gain_spinbox.setEnabled(False) self.update_manager() self.settings = AppContainer.find('/program_settings') if self.settings.camera_backend and self.settings.camera_driver: self.set_device_label() # some vars we may or may not want here self.xsize = None self.ysize = None self.roi = None self.state = EXPOSURE_STATE_IDLE self.current_exposure = None # under INDI it is expensive to check things like # camera temperature # so make it so we do it less frequently self.temperature_poll_interval = 5 self.temperature_poll_last = None # self.temperature_current_last = None # self.temperature_target_last = None self.set_widget_states()
def update_manager(self): self.camera_manager = AppContainer.find('/dev/camera') self.camera_manager.signals.status.connect(self.camera_status_poll) self.camera_manager.signals.exposure_complete.connect( self.camera_exposure_complete) if self.camera_manager.is_connected(): cooler_state = self.camera_manager.get_cooler_state() self.ui.camera_setting_cooleronoff.setChecked(cooler_state) settemp = self.camera_manager.get_target_temperature() if settemp is not None: self.ui.camera_setting_coolersetpt.setValue(int(settemp)) else: logging.warning('camera_connect: settemp is None!') maxbin = self.camera_managerget_max_binning() # FIXME need better way to handle maxbin being unavailable! if maxbin is None: logging.debug('Forcing max bin to 4') maxbin = 4 self.ui.camera_setting_binning_spinbox.setMaximum(maxbin) else: self.ui.camera_setting_binning_spinbox.setMaximum(1)
def camera_exposure_complete(self, result): # result will contain (bool, FITSImage) # bool will be True if image successful logging.debug(f'ImageSequenceControlUI:cam_exp_comp: result={result}') if self.exposure_ongoing: flag, fitsimage = result if not flag: logging.warning( 'ImageSequenceControlUI:cam_exp_comp - result was False!') return program_settings = AppContainer.find('/program_settings') if program_settings is None: logging.error('ImageSequenceControlUI:cam_exp_comp: cannot ' 'retrieve program settings!') QtWidgets.QMessageBox.critical( None, 'Error', 'Unknown error reading program ' 'settings in cam_exp_comp - exiting!', QtWidgets.QMessageBox.Ok) sys.exit(-1) # FIXME need better object to send with signal for end of sequence exposure? self.handle_new_image(fitsimage) # get start time from FITS if present start_time = fitsimage.get_dateobs() logging.debug(f'start_time = {start_time}') outname = os.path.join( self.sequence.target_dir, self.sequence.get_filename(start_time=start_time)) overwrite_flag = program_settings.sequence_overwritefiles logging.info(f'writing sequence image to {outname}') try: fitsimage.save_to_file(outname, overwrite=overwrite_flag) except Exception as e: # FIXME Doesnt stop current sequence on this error! logging.error('CameraManager:connect() Exception ->', exc_info=True) QtWidgets.QMessageBox.critical( None, 'Error', 'Unable to save sequence image:\n\n' f'{outname}\n\n' f'Error -> {str(e)}\n\n' 'Check if file already exists and ' 'overwrite set to False\n\n' 'Sequence aborted!', QtWidgets.QMessageBox.Ok) logging.error('Sequence ended due to error!') self.end_sequence(abort=True) return self.new_sequence_image.emit((fitsimage, self.sequence.target_dir, self.sequence.get_filename())) stop_idx = self.sequence.start_index + self.sequence.number_frames self.sequence.current_index += 1 logging.warning(f'new cur idx={self.sequence.current_index} ' f'stop at {stop_idx}') if self.sequence.current_index >= stop_idx: logging.info('Sequence Complete') self.end_sequence() QtWidgets.QMessageBox.information( None, 'Sequence Complete!', 'The requested sequence is complete.', QtWidgets.QMessageBox.Ok) return # see if we need to dither # FIXME currently we just use a modulus of the 'n frames' dither param # If the user somehow messes with image indexes to skip frame numbers, etc # then the dithering may not work out correctly but for a sequenentially # numbered sequence of frames it will do what we want and that is almost # always the use case! logging.debug( f'ImageSequenceControlUI:cam_exp_comp -> num_dither = ' f'{self.sequence.num_dither}') if self.sequence.is_light_frames( ) and self.sequence.num_dither > 0: num_frames = self.sequence.current_index - self.sequence.start_index num_left = self.sequence.start_index + self.sequence.number_frames - self.sequence.current_index logging.info(f'num_frames={num_frames} num_left={num_left} ' f'curidx={self.sequence.current_index} ' f'num_dither={self.sequence.num_dither}') if self.sequence.num_dither == 1: dither_now = True elif num_frames > 1 and num_left >= self.sequence.num_dither: dither_now = (self.sequence.current_index % self.sequence.num_dither) == 0 else: dither_now = False if dither_now: logging.info('sequence: time to dither!') logging.debug(f'ImageSequenceControlUI:cam_exp_comp: ' f'dither: {program_settings.phd2_scale} ' f'{program_settings.phd2_threshold}' f'{program_settings.phd2_starttime} ' f'{program_settings.phd2_settledtime} ' f'{program_settings.phd2_settletimeout} ') rc = self.phd2_manager.dither( program_settings.phd2_scale, program_settings.phd2_threshold, program_settings.phd2_starttime, program_settings.phd2_settledtime, program_settings.phd2_settletimeout) if not rc: # failed to get PHD2 to dither - just fall through and # start next frame after notifying user # # FIXME what is best case here? Use the dither fail # checkbox from general settings to guide # # how to handle? logging.error( 'ImageSequenceControlUI:cam_exp_comp: ' 'Could not communicate with PHD2 to start a dither op' ) QtWidgets.QMessageBox.critical( None, 'Error', 'PHD2 failed to respond to ' 'dither request - dither aborted!', QtWidgets.QMessageBox.Ok) else: logging.info( 'ImageSequenceControlUI:cam_exp_comp: ' 'Dither command sent to PHD2 successfully') # now the 'SettleDone' event should come in from PHD2 and it will be handled # and next frame started unless we get a settle timeout event instead return # dither wasnt required or failed(?) and we just start next frame # start next exposure self.device_manager.camera.start_exposure(self.sequence.exposure) else: logging.warning('ImageSequenceControlUI:cam_exp_comp: no ' 'exposure was ongoing!')
def update_manager(self): self.focuser_manager = AppContainer.find('/dev/focuser') logging.debug( f'focuser update_manager(): self.focuser_manager = {self.focuser_manager}' )
def start_sequence(self): # FIXME this sequence would probably be MUCH NICER using a lock/semaphore # which is a context manager so we wouldn't have so many cases of # releasing locks we'd already acquired when we fail out # make sure camera connected if not self.device_manager.camera.is_connected(): logging.error('start_sequence: camera is not connected!') QtWidgets.QMessageBox.critical(None, 'Error', 'Please connect camera first', QtWidgets.QMessageBox.Ok) return # make sure filter wheel is connected if not self.device_manager.filterwheel.is_connected(): logging.error('start_sequence: filter is not connected!') QtWidgets.QMessageBox.critical(None, 'Error', 'Please connect filter first', QtWidgets.QMessageBox.Ok) return # try to lock camera if not self.device_manager.camera.get_lock(): logging.error('start_sequence: unable to get camera lock!') QtWidgets.QMessageBox.critical(None, 'Error', 'Camera is busy', QtWidgets.QMessageBox.Ok) return # try to lock filter wheel if not self.device_manager.filterwheel.get_lock(): logging.error('start_sequence: unable to get filter lock!') QtWidgets.QMessageBox.critical(None, 'Error', 'Filter is busy!', QtWidgets.QMessageBox.Ok) self.device_manager.camera.release_lock() return status = self.device_manager.camera.get_status() if CameraState(status.state) != CameraState.IDLE: logging.error('CameraControlUI: camera_expose : camera not IDLE') self.device_manager.camera.release_lock() self.device_manager.filterwheel.release_lock() return # check if output directory exists! if not os.path.isdir(self.sequence.target_dir): logging.error('start_sequence: target dir doesnt exist!') QtWidgets.QMessageBox.critical( None, 'Error', f'Targer directory ' f'{self.sequence.target_dir} does ' 'not exist!', QtWidgets.QMessageBox.Ok) self.device_manager.camera.release_lock() self.device_manager.filterwheel.release_lock() return is_light_frame = self.sequence.is_light_frames() program_settings = AppContainer.find('/program_settings') if program_settings is None: logging.error('start_sequence: cannot retrieve program settings!') QtWidgets.QMessageBox.critical( None, 'Error', 'Unknown error reading program settings - aborting!', QtWidgets.QMessageBox.Ok) return if is_light_frame and program_settings.sequence_phd2_warn_notconnect: if self.phd2_manager is None or not self.phd2_manager.is_connected( ): logging.error('start_sequence: phd2 not connected') choice = QtWidgets.QMessageBox.question( None, 'PHD2 Not Connected', 'PHD2 is not connected - ' 'proceed with sequence?', QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) if choice == QtWidgets.QMessageBox.No: self.device_manager.camera.release_lock() self.device_manager.filterwheel.release_lock() return else: logging.info( 'start_sequence: User choose to start sequence ' 'without PHD2 connected.') # FIXME if they chose to start without PHD2 then need to ignore PHD2 for this sequence including # losing guiding and star events! if is_light_frame and program_settings.sequence_phd2_stop_loseguiding: if not self.phd2_manager.is_guiding(): logging.error('start_sequence: phd2 not guiding') choice = QtWidgets.QMessageBox.critical( None, 'PHD2 Not Guiding', 'PHD2 is not guiding - ' 'cannot start sequence. Change ' 'settings to avoid this error.', QtWidgets.QMessageBox.Ok) self.device_manager.camera.release_lock() self.device_manager.filterwheel.release_lock() return if is_light_frame and program_settings.sequence_mount_warn_notconnect: if not self.device_manager.mount.is_connected(): logging.error('start_sequence: mount not connected') choice = QtWidgets.QMessageBox.question( None, 'Mount Not Connected', 'Mount is not connected - ' 'proceed with sequence?', QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) if choice == QtWidgets.QMessageBox.No: self.device_manager.camera.release_lock() self.device_manager.filterwheel.release_lock() return else: logging.info( 'start_sequence: User choose to start sequence ' 'without mount connected.') if program_settings.sequence_warn_coolertemp: set_temp = self.device_manager.camera.get_target_temperature() cur_temp = self.device_manager.camera.get_current_temperature() # FIXME Should delta temp be hard coded # FIXME INDI might not have target set unless we've explicitely done it if set_temp is None or abs(set_temp - cur_temp) > 2: logging.info( f'start_sequence: target T = {set_temp} current T = {cur_temp}' ) choice = QtWidgets.QMessageBox.question( None, 'Cooler Temperature', f'The current camera temperature ' f'is {cur_temp} but the ' f'target temperature is {set_temp}.' '\n\nProceed with sequence?', QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No) if choice == QtWidgets.QMessageBox.No: self.device_manager.camera.release_lock() self.device_manager.filterwheel.release_lock() return else: logging.info( 'start_sequence: User choose to start sequence ' 'with cooler temperature not close to target') # we're committed now self.set_startstop_state(False) # setup camera settings = CameraSettings() settings.binning = self.sequence.binning settings.roi = self.sequence.roi settings.camera_gain = self.sequence.camera_gain self.device_manager.camera.set_settings(settings) # move filter wheel if not self.device_manager.filterwheel.set_position_name( self.sequence.filter): logging.error('start_sequence: unable to move filter wheel!') QtWidgets.QMessageBox.critical(None, 'Error', 'Filter wheel not responding', QtWidgets.QMessageBox.Ok) self.device_manager.camera.release_lock() self.device_manager.filterwheel.release_lock() return # wait on filter wheel # FIXME Fix hardcoded timeout! wait_start = time.time() filter_ok = False while time.time() - wait_start < 15: if not self.device_manager.filterwheel.is_moving(): filter_ok = True break if not filter_ok: logging.error('start_sequence: unable to move filter wheel!') QtWidgets.QMessageBox.critical( None, 'Error', 'Filter wheel not responding - kept moving', QtWidgets.QMessageBox.Ok) self.device_manager.camera.release_lock() self.device_manager.filterwheel.release_lock() return self.sequence.current_index = self.sequence.start_index self.device_manager.camera.start_exposure(self.sequence.exposure) # SIMULATE PROGRESS IN CAMERA MANAGER INSTEAD! # if not self.device_manager.camera.supports_progress(): # logging.info(f'starting exposure timer for {self.sequence.exposure} sec') # self.exposure_timer = QtCore.QTimer() # self.exposure_timer.start(self.sequence.exposure) self.exposure_ongoing = True
def __init__(self): # get settings self.settings = AppContainer.find('/program_settings') logging.debug(f'DeviceManager init(): self.settings = {self.settings}') # set proxy backend objects that will never change self.camera_backend = BackendProxy() self.focuser_backend = BackendProxy() self.filterwheel_backend = BackendProxy() self.mount_backend = BackendProxy() # create proxy devices that will never change self.camera = DeviceProxy() self.focuser = DeviceProxy() self.filterwheel = DeviceProxy() self.mount = DeviceProxy() self.set_camera_backend(self.settings.camera_backend) self.set_focuser_backend(self.settings.focuser_backend) self.set_filterwheel_backend(self.settings.filterwheel_backend) self.set_mount_backend(self.settings.mount_backend) AppContainer.register('/dev', self) # publish these public proxy objects # if backend/driver changes it will be hidden by this proxy AppContainer.register('/dev/camera', self.camera) AppContainer.register('/dev/focuser', self.focuser) AppContainer.register('/dev/filterwheel', self.filterwheel) AppContainer.register('/dev/mount', self.mount) AppContainer.register('/dev/camera_backend', self.camera_backend) AppContainer.register('/dev/focuser_backend', self.focuser_backend) AppContainer.register('/dev/filterwheel_backend', self.filterwheel_backend) AppContainer.register('/dev/mount_backend', self.mount_backend) logging.debug('DeviceManager registration complete')
def __init__(self): super().__init__() self.ui = Ui_SequenceSettingsUI() self.ui.setupUi(self) self.ui.sequence_elements_help.toggled.connect(self.help_toggle) self.ui.sequence_select_targetdir.pressed.connect( self.select_targetdir) self.device_manager = AppContainer.find('/dev') self.phd2_manager = AppContainer.find('/dev/phd2') self.phd2_manager.signals.starlost.connect(self.phd2_starlost_event) self.phd2_manager.signals.guiding_stop.connect( self.phd2_guiding_stop_event) self.phd2_manager.signals.dither_settledone.connect( self.phd2_dither_settledone_event) self.phd2_manager.signals.dither_timeout.connect( self.phd2_dither_timeout_event) self.sequence = ImageSequence(self.device_manager) # use an exposure timer if the camera driver doesn't report progress # self.exposure_timer = None # initialize sequence settings from general settings # FIXME do we need a centralized config object/singleton? settings = AppContainer.find('/program_settings') self.sequence.name_elements = settings.sequence_elements self.sequence.target_dir = settings.sequence_targetdir self.reset_roi() self.update_ui() # until camera connects assume no binning allowed self.ui.sequence_binning.setMaximum(1) self.ui.sequence_binning.setMinimum(1) self.ui.sequence_name.textChanged.connect(self.values_changed) self.ui.sequence_elements.textChanged.connect(self.values_changed) self.ui.sequence_exposure.valueChanged.connect(self.values_changed) self.ui.sequence_number.valueChanged.connect(self.values_changed) self.ui.sequence_frametype.currentIndexChanged.connect( self.values_changed) self.ui.sequence_exposure.valueChanged.connect(self.values_changed) self.ui.sequence_dither.valueChanged.connect(self.values_changed) self.ui.sequence_start.valueChanged.connect(self.values_changed) self.ui.sequence_filter.currentIndexChanged.connect( self.values_changed) self.ui.sequence_start_stop.pressed.connect(self.start_sequence) # FIXME Disabling for now since under ASCOM setting gain for ASI cameras # does not seem to work reliably logging.warning('Setting gain not enabled!') #self.ui.sequence_camera_gain.valueChanged.connect(self.values_changed) self.ui.sequence_binning.valueChanged.connect(self.binning_changed) self.ui.sequence_roi_set.pressed.connect(self.set_roi) self.device_manager.camera.signals.status.connect( self.camera_status_poll) self.device_manager.camera.signals.exposure_complete.connect( self.camera_exposure_complete) self.device_manager.camera.signals.lock.connect( self.camera_lock_handler) self.device_manager.camera.signals.connect.connect( self.camera_connect_handler) self.device_manager.filterwheel.signals.lock.connect( self.filterwheel_lock_handler) self.device_manager.filterwheel.signals.connect.connect( self.filterwheel_connect_handler) self.set_widget_states() self.ui.sequence_camera_gain.setEnabled(False) self.title_help = self.HelpWindow() self.filterwheel_ui_initialized = False self.exposure_ongoing = False self.setWindowTitle('Sequence') self.show()
def handle_new_image(self, fits_doc): """Fills in FITS header data for new images""" # FIXME maybe best handled somewhere else - it relies on lots of 'globals' settings = AppContainer.find('/program_settings') if settings is None: logging.error('ImageSequenceControlUI:handle_new_image: unable to ' 'access program settings!') return False fits_doc.set_notes(settings.observer_notes) fits_doc.set_telescope(settings.telescope_description) fits_doc.set_focal_length(settings.telescope_focallen) aper_diam = settings.telescope_aperture aper_obst = settings.telescope_obstruction aper_area = math.pi * (aper_diam / 2.0 * aper_diam / 2.0) \ * (1-aper_obst*aper_obst / 100.0 / 100.0) fits_doc.set_aperture_diameter(aper_diam) fits_doc.set_aperture_area(aper_area) lat_dms = Angle(settings.location_latitude * u.degree).to_string( unit=u.degree, sep=' ', precision=0) lon_dms = Angle(settings.location_longitude * u.degree).to_string( unit=u.degree, sep=' ', precision=0) fits_doc.set_site_location(lat_dms, lon_dms) # these come from camera, filter wheel and telescope drivers if self.device_manager.camera.is_connected(): cam_name = self.device_manager.camera.get_camera_name() fits_doc.set_instrument(cam_name) try: ccd_gain = self.device_manager.camera.get_camera_gain() logging.debug(f'ccd_gain = {ccd_gain}') if ccd_gain is not None: fits_doc.set_header_keyvalue('CCD_GAIN', ccd_gain) except AttributeError: logging.warning( 'camera driver does not support get_camera_gain()') pass if self.device_manager.filterwheel.is_connected(): logging.debug('connected') cur_name = self.device_manager.filterwheel.get_position_name() fits_doc.set_filter(cur_name) if self.device_manager.mount.is_connected(): ra, dec = self.device_manager.mount.get_position_radec() radec = SkyCoord(ra=ra * u.hour, dec=dec * u.degree, frame='fk5') rastr = radec.ra.to_string(u.hour, sep=" ", pad=True) decstr = radec.dec.to_string(alwayssign=True, sep=" ", pad=True) fits_doc.set_object_radec(rastr, decstr) alt, az = self.device_manager.mount.get_position_altaz() if alt is None or az is None: logging.warning('imagesequi: alt/az are None!') else: altaz = AltAz(alt=alt * u.degree, az=az * u.degree) # altstr = altaz.alt.to_string(alwayssign=True, sep=":", pad=True) # azstr = altaz.az.to_string(alwayssign=True, sep=":", pad=True) altstr = f'{altaz.alt.degree}' azstr = f'{altaz.az.degree}' fits_doc.set_object_altaz(altstr, azstr) now = Time.now() local_sidereal = now.sidereal_time( 'apparent', longitude=settings.location_longitude * u.degree) hour_angle = local_sidereal - radec.ra logging.debug(f'locsid = {local_sidereal} HA={hour_angle}') if hour_angle.hour > 12: hour_angle = (hour_angle.hour - 24.0) * u.hourangle # hastr = Angle(hour_angle).to_string(u.hour, sep=":", pad=True) hastr = f'{Angle(hour_angle).hour}' logging.debug(f'HA={hour_angle} HASTR={hastr} {type(hour_angle)}') fits_doc.set_object_hourangle(hastr) # controlled by user selection in camera or sequence config fits_doc.set_image_type(self.sequence.frame_type.pretty_name()) fits_doc.set_object('TEST-OBJECT') # set by application version fits_doc.set_software_info('pyastroimageview TEST')