Exemplo n.º 1
0
    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)
Exemplo n.º 5
0
    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'
            )
Exemplo n.º 6
0
    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')
Exemplo n.º 7
0
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)
Exemplo n.º 10
0
    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()
Exemplo n.º 11
0
 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)
Exemplo n.º 12
0
    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}'
     )
Exemplo n.º 14
0
    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
Exemplo n.º 15
0
    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')
Exemplo n.º 16
0
    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()
Exemplo n.º 17
0
    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')