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), )
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
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}")