Source code for ska_pst.lmc.stat.stat_component_manager

# -*- coding: utf-8 -*-
#
# This file is part of the SKA PST project.
#
# Distributed under the terms of the BSD 3-clause new license.
# See LICENSE for more info.
"""This module provides an implementation of the STAT PST component manager."""

from __future__ import annotations

import logging
from typing import Any

from overrides import override
from ska_pst.lmc.component import PstProcessApiSubcomponentManager
from ska_pst.lmc.stat.stat_model import StatMonitorData, StatMonitorDataStore
from ska_pst.lmc.stat.stat_process_api import (
    PstStatProcessApi,
    PstStatProcessApiGrpc,
    PstStatProcessApiSimulator,
)
from ska_pst.lmc.stat.stat_util import calculate_stat_subband_resources

__all__ = ["PstStatComponentManager"]


[docs]class PstStatComponentManager( PstProcessApiSubcomponentManager[ StatMonitorData, StatMonitorData, PstStatProcessApi, StatMonitorDataStore ] ): """Component manager for the STAT component for the PST.LMC subsystem.""" def __init__( self: PstStatComponentManager, *, device_name: str, process_api_endpoint: str, api: PstStatProcessApi | None = None, logger: logging.Logger | None = None, **kwargs: Any, ): """ Initialise instance of the component manager. :param device_interface: an abstract interface of the TANGO device. :type device_interface: PstApiDeviceInterface[StatMonitorData] :param api: an API object used to delegate functionality to. :type api: `PstProcessApi` :param logger: a logger for this object to use :type logger: `logging.Logger` """ logger = logger or logging.getLogger(__name__) logger.debug( f"Setting up STAT component manager with device_name='{device_name}'" + f"and api_endpoint='{process_api_endpoint}'" ) api = api or PstStatProcessApiSimulator( logger=logger, ) super().__init__( device_name=device_name, subcomponent_name="stat", process_api_endpoint=process_api_endpoint, api=api, logger=logger, data_store=StatMonitorDataStore(), **kwargs, ) @property def real_pol_a_mean_freq_avg(self: PstStatComponentManager) -> float: """Get the mean of the real data for pol A, averaged over all channels.""" return self.monitor_data.real_pol_a_mean_freq_avg @property def real_pol_a_variance_freq_avg(self: PstStatComponentManager) -> float: """Get the variance of the real data for pol A, averaged over all channels.""" return self.monitor_data.real_pol_a_variance_freq_avg @property def real_pol_a_num_clipped_samples(self: PstStatComponentManager) -> int: """Get the num of clipped samples of the real data for pol A.""" return self.monitor_data.real_pol_a_num_clipped_samples @property def imag_pol_a_mean_freq_avg(self: PstStatComponentManager) -> float: """Get the mean of the imaginary data for pol A, averaged over all channels.""" return self.monitor_data.imag_pol_a_mean_freq_avg @property def imag_pol_a_variance_freq_avg(self: PstStatComponentManager) -> float: """Get the variance of the imaginary data for pol A, averaged over all channels.""" return self.monitor_data.imag_pol_a_variance_freq_avg @property def imag_pol_a_num_clipped_samples(self: PstStatComponentManager) -> int: """Get the num of clipped samples of the imaginary data for pol A.""" return self.monitor_data.imag_pol_a_num_clipped_samples @property def real_pol_a_mean_freq_avg_rfi_excised(self: PstStatComponentManager) -> float: """Get the mean of the real data for pol A, averaged over channels not flagged for RFI.""" return self.monitor_data.real_pol_a_mean_freq_avg_rfi_excised @property def real_pol_a_variance_freq_avg_rfi_excised(self: PstStatComponentManager) -> float: """Get the variance of the real data for pol A, averaged over channels not flagged for RFI.""" return self.monitor_data.real_pol_a_variance_freq_avg_rfi_excised @property def real_pol_a_num_clipped_samples_rfi_excised(self: PstStatComponentManager) -> int: """Get the num of clipped samples of the real data for pol A in channels not flagged for RFI.""" return self.monitor_data.real_pol_a_num_clipped_samples_rfi_excised @property def imag_pol_a_mean_freq_avg_rfi_excised(self: PstStatComponentManager) -> float: """Get the mean of the imaginary data for pol A, averaged over channels not flagged for RFI.""" return self.monitor_data.imag_pol_a_mean_freq_avg_rfi_excised @property def imag_pol_a_variance_freq_avg_rfi_excised(self: PstStatComponentManager) -> float: """Get the variance of the imaginary data for pol A, averaged over channels not flagged for RFI.""" return self.monitor_data.imag_pol_a_variance_freq_avg_rfi_excised @property def imag_pol_a_num_clipped_samples_rfi_excised(self: PstStatComponentManager) -> int: """Get the num of clipped samples of the imaginary data for pol A in channels not flagged for RFI.""" return self.monitor_data.imag_pol_a_num_clipped_samples_rfi_excised @property def real_pol_b_mean_freq_avg(self: PstStatComponentManager) -> float: """Get the mean of the real data for pol B, averaged over all channels.""" return self.monitor_data.real_pol_b_mean_freq_avg @property def real_pol_b_variance_freq_avg(self: PstStatComponentManager) -> float: """Get the variance of the real data for pol B, averaged over all channels.""" return self.monitor_data.real_pol_b_variance_freq_avg @property def real_pol_b_num_clipped_samples(self: PstStatComponentManager) -> int: """Get the num of clipped samples of the real data for pol B.""" return self.monitor_data.real_pol_b_num_clipped_samples @property def imag_pol_b_mean_freq_avg(self: PstStatComponentManager) -> float: """Get the mean of the imaginary data for pol B, averaged over all channels.""" return self.monitor_data.imag_pol_b_mean_freq_avg @property def imag_pol_b_variance_freq_avg(self: PstStatComponentManager) -> float: """Get the variance of the imaginary data for pol B, averaged over all channels.""" return self.monitor_data.imag_pol_b_variance_freq_avg @property def imag_pol_b_num_clipped_samples(self: PstStatComponentManager) -> int: """Get the num of clipped samples of the imaginary data for pol B.""" return self.monitor_data.imag_pol_b_num_clipped_samples @property def real_pol_b_mean_freq_avg_rfi_excised(self: PstStatComponentManager) -> float: """Get the mean of the real data for pol B, averaged over channels not flagged for RFI.""" return self.monitor_data.real_pol_b_mean_freq_avg_rfi_excised @property def real_pol_b_variance_freq_avg_rfi_excised(self: PstStatComponentManager) -> float: """Get the variance of the real data for pol B, averaged over channels not flagged for RFI.""" return self.monitor_data.real_pol_b_variance_freq_avg_rfi_excised @property def real_pol_b_num_clipped_samples_rfi_excised(self: PstStatComponentManager) -> int: """Get the num of clipped samples of the real data for pol B in channels not flagged for RFI.""" return self.monitor_data.real_pol_b_num_clipped_samples_rfi_excised @property def imag_pol_b_mean_freq_avg_rfi_excised(self: PstStatComponentManager) -> float: """Get the mean of the imaginary data for pol B, averaged over channels not flagged for RFI.""" return self.monitor_data.imag_pol_b_mean_freq_avg_rfi_excised @property def imag_pol_b_variance_freq_avg_rfi_excised(self: PstStatComponentManager) -> float: """Get the variance of the imaginary data for pol B, averaged over channels not flagged for RFI.""" return self.monitor_data.imag_pol_b_variance_freq_avg_rfi_excised @property def imag_pol_b_num_clipped_samples_rfi_excised(self: PstStatComponentManager) -> int: """Get the num of clipped samples of the imaginary data for pol B in channels not flagged for RFI.""" return self.monitor_data.imag_pol_b_num_clipped_samples_rfi_excised @override def _simulator_api(self: PstStatComponentManager) -> PstStatProcessApi: """Get instance of the simulator API.""" self.logger.debug("STAT component manager setting up simulated API") return PstStatProcessApiSimulator( logger=self.logger, ) @override def _grpc_api(self: PstStatComponentManager) -> PstStatProcessApi: """Get instance of a gRPC API.""" self.logger.debug("STAT component manager setting up gRPC API") return PstStatProcessApiGrpc( client_id=self.subcomponent_id, grpc_endpoint=self.process_api_endpoint, logger=self.logger, ) @override def validate_configure_scan(self: PstStatComponentManager, configuration: dict) -> None: """ Validate a ConfigureScan request sent from CSP.LMC to the STAT sub-component. This asserts the request can be converted to STAT resources and then calls the process API to perform the validation. :param configuration: configuration that would be used when the configure_beam and configure_scan methods are called. :type configuration: dict """ stat_resources = calculate_stat_subband_resources(beam_id=self.beam_id, **configuration) self._api.validate_configure_beam(configuration=stat_resources[1]) self._api.validate_configure_scan(configuration=configuration) @override def _configure_beam(self: PstStatComponentManager, configuration: dict) -> None: """ Configure beam resources in the component. :param configuration: configuration for beam :type configuration: dict """ stat_resources = calculate_stat_subband_resources(beam_id=self.beam_id, **configuration) # deal only with subband 1 for now. self.logger.debug(f"Submitting API with stat_resources={stat_resources[1]}") self._api.configure_beam(configuration=stat_resources[1])