Example #1
0
def flicamera(ctx, cameras, config_path, simulate, simulation_profile, verbose):
    """Command Line Interface for Finger Lakes Instrumentation cameras."""

    if verbose:
        log.set_level(logging.DEBUG)
    else:
        log.set_level(logging.WARNING)

    # We want to allow the actor to minimally work without a configuration
    # file so instead of passing it to the actor using the .from_config
    # classmethod we parse the configuration ourselves.

    config = None

    if not config_path:
        config_path = f"{os.path.dirname(__file__)}/etc/flicamera.yaml"
    config = read_yaml_file(config_path)

    if config:
        if "cameras" in config:
            camera_config = config["cameras"].copy()
        else:
            camera_config = config.copy()  # type: ignore
        log_file = config.get("log_file", None)
        if log_file:
            log_file = log_file.format(hostname=socket.getfqdn())
    else:
        log_file = None
        camera_config = None

    include = cameras or None

    simulate_config: Union[bool, Dict[str, Any]]
    if simulate is True:
        if not config:
            raise RuntimeError("Cannot simulate without a configuration file.")
        elif "simulation" not in config:
            raise RuntimeError("'simulate' section not found in config file.")

        if "profiles" in config["simulation"]:
            simulate_config = config["simulation"]["profiles"][simulation_profile]
        else:
            simulate_config = config["simulation"]
    else:
        simulate_config = False

    ctx.obj["camera_system"] = FLICameraWrapper(
        camera_config=camera_config,
        include=include,
        log_file=log_file,
        verbose=verbose,
        config_path=config_path,
        simulate_config=simulate_config,
    )

    # Store some of the options here for the daemon
    ctx.obj["cameras"] = cameras
    ctx.obj["config"] = config
    ctx.obj["verbose"] = verbose
Example #2
0
File: conftest.py Project: sdss/HAL
async def actor():

    config = read_yaml_file(config_path)

    hal_actor = HALActor.from_config(config)
    hal_actor = await setup_test_actor(hal_actor)  # type: ignore

    yield hal_actor

    # Clear replies in preparation for next test.
    hal_actor.mock_replies.clear()
Example #3
0
    def _parse_config(
        input: Union[Dict[str, Any], pathlib.Path, str],
        loader=yaml.FullLoader,
    ) -> Dict[str, Any]:

        if not isinstance(input, dict):
            input = pathlib.Path(input)
            assert input.exists(), "configuration path does not exist."
            config = read_yaml_file(str(input), loader=loader)
        else:
            config = input

        return cast("Dict[str, Any]", config)
Example #4
0
def flicamera(ctx, cameras, config_path, verbose):
    """Command Line Interface for Finger Lakes Instrumentation cameras."""

    if verbose:
        log.set_level(logging.NOTSET)
    else:
        log.set_level(logging.WARNING)

    # We want to allow the actor to minimally work without a configuration
    # file so instead of passing it to the actor using the .from_config
    # classmethod we parse the configuration ourselves.

    config = None

    if not config_path:
        config_path = f'{os.path.dirname(__file__)}/etc/flicamera.yaml'
    config = read_yaml_file(config_path)

    if config:
        if 'cameras' in config:
            camera_config = config['cameras'].copy()
        else:
            camera_config = config.copy()
        log_file = config.get('log_file', None)
        if log_file:
            log_file = log_file.format(hostname=socket.getfqdn())
    else:
        log_file = None
        camera_config = None

    include = cameras or None

    ctx.obj['camera_system'] = FLICameraWrapper(camera_config=camera_config,
                                                include=include,
                                                log_file=log_file,
                                                verbose=verbose,
                                                config_path=config_path)

    # Store some of the options here for the daemon
    ctx.obj['cameras'] = cameras
    ctx.obj['config'] = config
    ctx.obj['verbose'] = verbose
Example #5
0
async def flicamera(camera_name):
    """Starts an actor and sets CAMERA-NAME as the default camera.

    It is expected that the information for the actor is found in
    $SDSSCORE_DIR/configuration_files/actors/flicamera.yaml under the
    actor section. Any additional flags passed are used to override the
    default configuration values.

    """

    config_file = os.path.join(os.environ['SDSSCORE_DIR'],
                               'configuration_files/actors/flicamera.yaml')

    if not os.path.exists(config_file):
        raise RuntimeError(f'cannot open file {config_file}.')

    actor_config = read_yaml_file(config_file).get('actor')
    if not actor_config:
        raise RuntimeError('cannot find actor section in configuration file.')

    if 'log_dir' in actor_config:
        actor_config['log_dir'] = os.path.join(actor_config['log_dir'],
                                               camera_name)
    else:
        actor_config['log_dir'] = f'/data/logs/actors/{camera_name}'

    camera_system = FLICameraSystem().setup()
    await camera_system.start_camera_poller()

    await asyncio.sleep(0.1)  # Some time to allow camera to connect.

    actor = await FLIActor.from_config(actor_config,
                                       camera_system,
                                       name=camera_name,
                                       default_cameras=[camera_name]).start()
    actor.timer_commands.append(TimerCommand('status', delay=60))

    await actor.run_forever()
Example #6
0
    def __init__(self,
                 fields,
                 output_dir,
                 observatory=None,
                 config_file=None,
                 n_attempts=10):

        self.output_dir = pathlib.Path(output_dir)

        if config_file:
            config_data = read_yaml_file(config_file)
        else:
            config_data = config

        self.config_data = config_data.copy()

        self.observatory = observatory or self.config_data['observatory']
        self.n_attempts = n_attempts

        numpy.random.seed(config_data['seed'])

        if isinstance(fields, int):
            fields = get_uniform_ra_dec(fields).tolist()
            self.fields = {
                fid + 1: list(map(float, fields[fid]))
                for fid in range(len(fields))
            }
        elif isinstance(fields, dict):
            self.fields = fields
        elif isinstance(fields, (tuple, list)):
            self.fields = {
                fid + 1: list(map(float, fields[fid]))
                for fid in range(len(fields))
            }

        self._data = None
Example #7
0
def config():
    """Gets the test configuration."""

    yield read_yaml_file(TEST_DATA)
Example #8
0
def config():
    return read_yaml_file(TEST_CONFIG_FILE)
Example #9
0
    def __init__(self,
                 targeting_plan,
                 config_file=None,
                 schema=None,
                 table_name=None):

        assert self.name, 'carton subclass must override name'
        assert self.category, 'carton subclass must override category'
        assert self.program, 'carton subclass must override program'

        self.plan = targeting_plan
        self.tag = __version__ if self.plan != '0.0.0-test' else None

        if config_file:
            this_config = read_yaml_file(config_file)
        else:
            this_config = config.copy()

        if self.plan not in this_config:
            raise TargetSelectionError(
                f'({self.name}): cannot find plan {self.plan!r} in config.')

        self.config = this_config[self.plan]

        if 'parameters' in self.config:
            self.parameters = self.config['parameters'].get(self.name, None)
        else:
            self.parameters = None

        try:
            self.xmatch_plan = self.config['xmatch_plan']
        except KeyError:
            raise TargetSelectionError(
                f'({self.name}): xmatch_plan not found in config.')

        # Check the signature of build_query
        self._build_query_signature = inspect.signature(self.build_query)
        if 'version_id' not in self._build_query_signature.parameters:
            raise TargetSelectionError(
                'build_query does not accept version_id')

        self.database = tdb.database
        assert self.database.connected, 'database is not connected.'

        self.schema = schema or self.config.get('schema', None) or 'sandbox'
        self.table_name = table_name or f'temp_{self.name}'.replace('-', '_')
        self.RModel = None

        if self.cadence:
            ncad = tdb.Cadence.select().where(
                tdb.Cadence.label == self.cadence).count()
            assert ncad == 1, f'{self.cadence!r} does not exist in targetdb.cadence.'

        self.log = log
        self.has_run = False
        self._disable_query_log = False

        # We cannot set temp_buffers multiple times if there are temporary tables
        # (as in add_optical_magnitudes) so we set it here.
        if ('database_options' in self.config
                and 'temp_buffers' in self.config['database_options']):
            temp_buffers = self.config['database_options'].pop('temp_buffers')
            self.database.execute_sql(f'SET temp_buffers = \'{temp_buffers}\'')
Example #10
0
def test_config():
    """Yield the test configuration as a dictionary."""

    yield read_yaml_file(TEST_CONFIG_FILE)
Example #11
0
    def __init__(
        self,
        fps: FPS,
        trajectories: str | pathlib.Path | TrajectoryDataType,
        dump: bool | str = True,
        extra_dump_data: dict[str, Any] = {},
    ):

        self.fps = fps
        self.trajectories: TrajectoryDataType

        if self.fps.locked:
            raise FPSLockedError(
                f"FPS is locked by {fps.locked_by}. Cannot send trajectories.")

        if self.fps.moving:
            raise TrajectoryError(
                "The FPS is moving. Cannot send new trajectory.",
                self,
            )

        if isinstance(trajectories, (str, pathlib.Path)):
            path = pathlib.Path(trajectories)
            if path.suffix == ".json":
                self.trajectories = json.loads(open(path,
                                                    "r").read())["trajectory"]
            else:
                self.trajectories = cast(dict, read_yaml_file(trajectories))
        elif isinstance(trajectories, dict):
            self.trajectories = trajectories
        else:
            raise TrajectoryError("invalid trajectory data.", self)

        # List of positioners that failed receiving the trajectory and reason.
        self.failed_positioners: dict[int, str] = {}

        self.validate()

        #: Number of points sent to each positioner as a tuple ``(alpha, beta)``.
        self.n_points = {}

        #: The time required to complete the trajectory.
        self.move_time: float | None = None

        #: How long it took to send the trajectory.
        self.data_send_time: float | None = None

        self.failed = False
        self.send_new_trajectory_failed = False

        # Commands that will be sent. Mostly for inspection if the trajectory fails.
        self.data_send_cmd: Command | None = None
        self.end_traj_cmds: Command | None = None

        self.start_time: float | None = None
        self.end_time: float | None = None

        self.use_sync_line: bool = True
        self._ready_to_start = False

        self.dump_data = {
            "start_time": time.time(),
            "success": False,
            "trajectory_send_time": None,
            "trajectory_start_time": None,
            "end_time": None,
            "use_sync_line": True,
            "extra": extra_dump_data,
            "trajectory": self.trajectories,
            "initial_positions": self.fps.get_positions_dict(),
            "final_positions": {},
        }

        if dump is False:
            self.dump_file = None
        elif isinstance(dump, (str, pathlib.Path)):
            self.dump_file = str(dump)
        else:
            dirname = config["positioner"]["trajectory_dump_path"]
            mjd = str(int(Time.now().mjd))
            dirname = os.path.join(dirname, mjd)

            files = list(sorted(glob(os.path.join(dirname, "*.json"))))
            if len(files) == 0:
                seq = 1
            else:
                seq = int(files[-1].split("-")[-1].split(".")[0]) + 1

            self.dump_file = os.path.join(dirname,
                                          f"trajectory-{mjd}-{seq:04d}.json")
Example #12
0
    def __init__(
        self,
        camera_class: Optional[Type[_T_BaseCamera]] = None,
        camera_config: Optional[Union[AnyPath, Dict[str, Any]]] = None,
        include: Optional[List[Any]] = None,
        exclude: Optional[List[Any]] = None,
        logger: Optional[SDSSLogger] = None,
        log_header: Optional[str] = None,
        log_file: Optional[AnyPath] = None,
        verbose: Optional[Union[bool, int]] = False,
    ):

        self.camera_class = camera_class or self.camera_class

        if not self.camera_class or not issubclass(self.camera_class,
                                                   BaseCamera):
            raise ValueError("camera_class must be a subclass of BaseCamera.")

        self.include = self.include or include
        self.exclude = self.exclude or exclude

        logger_name = self.__class__.__name__.upper()
        self.log_header = log_header or f"[{logger_name.upper()}]: "
        self.logger = logger or cast(SDSSLogger, get_logger(logger_name))

        if verbose:
            self.logger.sh.setLevel(int(verbose))
        else:
            self.logger.sh.setLevel(logging.WARNING)

        if log_file:
            self.logger.start_file_logger(str(log_file))
            if self.logger.fh:
                assert self.logger.fh.formatter
                self.logger.fh.formatter.converter = time.gmtime
                self.log(f"logging to {log_file}")

        self.loop = asyncio.get_event_loop()
        self.loop.set_exception_handler(self.logger.asyncio_exception_handler)

        #: list: The list of cameras being handled.
        self.cameras: List[_T_BaseCamera] = []

        self._camera_poller = None

        #: .EventNotifier: Notifies of `.CameraSystemEvent` and `.CameraEvent` events.
        self.notifier = EventNotifier()

        self._config: Optional[Dict[str, Any]] = None

        if camera_config:
            if isinstance(camera_config, dict):
                self._config = camera_config.copy()
            else:
                self._config = cast(Dict[str, Any],
                                    read_yaml_file(str(camera_config)))
                self.log(f"read configuration file from {camera_config}")

        # If the config has a section named "cameras", prefer that.
        if self._config is not None:
            if isinstance(self._config.get("cameras", None), dict):
                self._config = self._config["cameras"]
            assert self._config is not None
            uids = [self._config[camera]["uid"] for camera in self._config]
            if len(uids) != len(set(uids)):
                raise ValueError("repeated UIDs in the configuration data.")

        self.running: bool = False