def hrs_spectral_properties(plane_id: int, arm: types.HRSArm,
                            hrs_mode: types.HRSMode) -> Optional[types.Energy]:
    """
     Method to calculate an spectral properties of HRS instrument

    Parameter
    ----------
    plane_id: int
        Plane id of of this file
    arm: HRSArm
        HRS arm either red or blue
    hrs_mode: HRSMode
        HRS resolution (Low, Medium, ...) Resolution

    Return
    ------
    Energy
        HRS spectral properties.
    """

    interval = hrs_wavelength_interval(arm=arm)
    resolving_power = hrs_resolving_power(arm=arm, hrs_mode=hrs_mode)
    if resolving_power is None:
        return None
    return types.Energy(
        dimension=1,
        max_wavelength=max(interval),
        min_wavelength=min(interval),
        plane_id=plane_id,
        resolving_power=resolving_power,
        sample_size=interval[1] - interval[0],
    )
def imaging_spectral_properties(plane_id: int, filter_name: str,
                                instrument: types.Instrument) -> types.Energy:
    """
    Spectral properties of a imaging setup.

    Parameter
    ----------
    plane_id: int
        Plane id
    filter_name: str
        Filter name
    instrument: Instrument
        Instrument
    Return
    ------
    Energy
        Calculated spectral properties
    """
    lambda_min, lambda_max = filter_wavelength_interval(
        filter_name, instrument)
    resolving_power = 0.5 * (lambda_min + lambda_max) / (lambda_max -
                                                         lambda_min)
    return types.Energy(
        dimension=1,
        max_wavelength=lambda_max,
        min_wavelength=lambda_min,
        plane_id=plane_id,
        resolving_power=resolving_power.to_value(u.dimensionless_unscaled),
        sample_size=abs(lambda_max - lambda_min),
    )
예제 #3
0
 def energy(self, plane_id: int) -> types.Energy:
     return types.Energy(
         dimension=512,
         max_wavelength=7000 * u.nanometer,
         min_wavelength=6500 * u.nanometer,
         plane_id=plane_id,
         resolving_power=915,
         sample_size=2.74 * u.nanometer,
     )
def test_energy(mocker):
    with mocker.patch.object(
            rss_obs,
            "energy",
            return_value=types.Energy(
                dimension=1,
                max_wavelength=Quantity(value=2, unit=u.meter),
                min_wavelength=Quantity(value=1, unit=u.meter),
                plane_id=1,
                resolving_power=1.0,
                sample_size=Quantity(value=1, unit=u.meter),
            ),
    ):
        energy = rss_obs.energy(1)
        assert energy.dimension == 1
        assert energy.max_wavelength.value == 2
        assert energy.min_wavelength.value == 1
        assert energy.resolving_power == 1.0
예제 #5
0
    def energy(self, plane_id: int) -> Optional[types.Energy]:
        if random.random() < 0.05:
            return None

        def wavelengths() -> Tuple[Quantity, Quantity]:
            wavelength_interval = 5000 * random.random()
            min_wavelength = (
                3000 + ((9000 - wavelength_interval) - 3000) * random.random())
            max_wavelength = min_wavelength + wavelength_interval
            return min_wavelength, max_wavelength

        wavelength_values = wavelengths()

        return types.Energy(
            dimension=random.randint(1, 1024),
            max_wavelength=wavelength_values[1] * u.angstrom,
            min_wavelength=wavelength_values[0] * u.angstrom,
            plane_id=plane_id,
            resolving_power=8000 * random.random(),
            sample_size=100 * random.random() * u.angstrom,
        )
def rss_spectral_properties(header_value: Any,
                            plane_id: int) -> Optional[types.Energy]:
    """
     Spectral properties for an RSS setup.

    Parameter
    ----------
    header_value: Function
        Method to get FITS header value for a keyword
    plane_id: int
        Plane id of this file
    Return
    ------
    Energy
        RSS Spectral properties
    """
    filter = header_value("FILTER")
    if (not filter or filter.upper() == "EMPTY" or filter
            in ["PC00000", "PC03200", "PC03400", "PC03850", "PC04600"]):
        return None
    observation_mode = header_value("OBSMODE").upper()
    if observation_mode.upper() == "IMAGING":
        return imaging_spectral_properties(
            plane_id=plane_id,
            filter_name=header_value("FILTER"),
            instrument=types.Instrument.RSS,
        )

    if observation_mode.upper() == "SPECTROSCOPY":
        grating_angle = float(header_value("GR-ANGLE")) * u.deg
        camera_angle = float(header_value("AR-ANGLE")) * u.deg
        slit_barcode = header_value("MASKID")
        spectral_binning = int(header_value("CCDSUM").split()[0])
        grating_frequency = get_grating_frequency(header_value("GRATING"))
        wavelength_interval = (
            rss_ccd_wavelength(-3162,
                               grating_angle,
                               camera_angle,
                               grating_frequency=grating_frequency),
            rss_ccd_wavelength(3162,
                               grating_angle,
                               camera_angle,
                               grating_frequency=grating_frequency),
        )
        dimension = 6096 // spectral_binning
        sample_size = rss_ccd_wavelength(
            spectral_binning, grating_angle,
            camera_angle, grating_frequency) - rss_ccd_wavelength(
                0, grating_angle, camera_angle, grating_frequency)
        return types.Energy(
            dimension=dimension,
            max_wavelength=max(wavelength_interval),
            min_wavelength=min(wavelength_interval),
            plane_id=plane_id,
            resolving_power=rss_resolution(
                grating_angle,
                camera_angle,
                grating_frequency=grating_frequency,
                slit_width=rss_slit_width_from_barcode(slit_barcode),
            ),
            sample_size=abs(sample_size),
        )

    if observation_mode == "FABRY-PEROT":
        etalon_state = header_value("ET-STATE")
        if etalon_state.lower() == "s1 - etalon open":
            return None

        if etalon_state.lower() == "s3 - etalon 2":
            _lambda = float(header_value("ET2WAVE0")) * u.angstrom
        elif (etalon_state.lower() == "s2 - etalon 1"
              or etalon_state.lower() == "s4 - etalon 1 & 2"):
            _lambda = (float(header_value("ET1WAVE0")) * u.angstrom
                       )  # Todo what are this units?
        else:
            raise ValueError("Unknown etalon state")

        wavelength_interval_length = fabry_perot_fwhm(
            rss_fp_mode=find_fabry_perot_mode(header_value),
            wavelength=_lambda)
        if wavelength_interval_length is None:
            return None

        wavelength_interval = (
            _lambda - wavelength_interval_length / 2,
            _lambda + wavelength_interval_length / 2,
        )
        return types.Energy(
            dimension=1,
            max_wavelength=wavelength_interval[1],
            min_wavelength=wavelength_interval[0],
            plane_id=plane_id,
            resolving_power=(_lambda / wavelength_interval_length).to_value(
                u.dimensionless_unscaled),
            sample_size=wavelength_interval_length,
        )

    raise ValueError(f"Unsupported observation mode: {observation_mode}")