예제 #1
0
    def apply_exposure_time_correction(self, undo=False, force=False):
        # Get exposure time in seconds.
        exposure_time_s = self.exposure_time.to(u.s).value
        # If exposure time is not scalar, change array's shape so that
        # it can be broadcast with data and uncertainty arrays.
        if not np.isscalar(exposure_time_s):
            # Get data axis of exposure time.
            if self._exposure_time_loc == "extra_coords":
                exposure_axis = self.extra_coords[self._exposure_time_name]["axis"]
            else:
                exposure_axis = get_axis_number_from_axis_name(self._exposure_time_name,
                                                               self.world_axis_physical_types)
            # Change array shape for broadcasting
            item = [np.newaxis] * self.data.ndim
            item[exposure_axis] = slice(None)
            exposure_time_s = exposure_time_s[tuple(item)]
        # Based on value on undo kwarg, apply or remove exposure time correction.
        if undo is True:
            new_data, new_uncertainty, new_unit = _uncalculate_exposure_time_correction(
                self.data, self.uncertainty, self.unit, exposure_time_s, force=force)
        else:
            new_data, new_uncertainty, new_unit = _calculate_exposure_time_correction(
                self.data, self.uncertainty, self.unit, exposure_time_s, force=force)
        # Return new instance of SpectrogramCube with correction applied/undone.

        return self.__class__(
            new_data, self.wcs,
            extra_coords=convert_extra_coords_dict_to_input_format(self.extra_coords,
                                                                   self.missing_axes),
            unit=new_unit, uncertainty=new_uncertainty, meta=self.meta, mask=self.mask,
            missing_axes=self.missing_axes)
예제 #2
0
 def __getitem__(self, item):
     result = super().__getitem__(item)
     if result.extra_coords is None:
         extra_coords = None
     else:
         extra_coords = convert_extra_coords_dict_to_input_format(result.extra_coords,
                                                                  result.missing_axes)
     return self.__class__(result.data, result.wcs, extra_coords, result.unit,
                           result.uncertainty, result.meta, mask=result.mask,
                           missing_axes=result.missing_axes)
예제 #3
0
 def __getitem__(self, item):
     result = super(IRISSpectrogramCube, self).__getitem__(item)
     return IRISSpectrogramCube(result.data,
                                result.wcs,
                                result.uncertainty,
                                result.unit,
                                result.meta,
                                convert_extra_coords_dict_to_input_format(
                                    result.extra_coords,
                                    result.missing_axis),
                                mask=result.mask,
                                missing_axis=result.missing_axis)
예제 #4
0
    def apply_exposure_time_correction(self, undo=False, force=False):
        """
        Applies or undoes exposure time correction to data and uncertainty and adjusts unit.

        Correction is only applied (undone) if the object's unit doesn't (does)
        already include inverse time.  This can be overridden so that correction
        is applied (undone) regardless of unit by setting force=True.

        Parameters
        ----------
        undo: `bool`
            If False, exposure time correction is applied.
            If True, exposure time correction is undone.
            Default=False

        force: `bool`
            If not True, applies (undoes) exposure time correction only if unit
            doesn't (does) already include inverse time.
            If True, correction is applied (undone) regardless of unit.  Unit is still
            adjusted accordingly.

        Returns
        -------
        result: `IRISSpectrogramCube`
            New IRISSpectrogramCube in new units.

        """
        # Get exposure time in seconds and change array's shape so that
        # it can be broadcast with data and uncertainty arrays.
        exposure_time_s = self.extra_coords["exposure time"]["value"].to(u.s).value
        if not self.extra_coords["exposure time"]["value"].isscalar:
            if len(self.dimensions) == 1:
                pass
            elif len(self.dimensions) == 2:
                exposure_time_s = exposure_time_s[:, np.newaxis]
            elif len(self.dimensions) == 3:
                exposure_time_s = exposure_time_s[:, np.newaxis, np.newaxis]
            else:
                raise ValueError(
                    "IRISSpectrogramCube dimensions must be 2 or 3. Dimensions={0}".format(
                        len(self.dimensions.shape)))
        # Based on value on undo kwarg, apply or remove exposure time correction.
        if undo is True:
            new_data_arrays, new_unit = iris_tools.uncalculate_exposure_time_correction(
                (self.data, self.uncertainty.array), self.unit, exposure_time_s, force=force)
        else:
            new_data_arrays, new_unit = iris_tools.calculate_exposure_time_correction(
                (self.data, self.uncertainty.array), self.unit, exposure_time_s, force=force)
        # Return new instance of IRISSpectrogramCube with correction applied/undone.
        return IRISSpectrogramCube(
            new_data_arrays[0], self.wcs, new_data_arrays[1], new_unit, self.meta,
            convert_extra_coords_dict_to_input_format(self.extra_coords, self.missing_axis),
            mask=self.mask, missing_axis=self.missing_axis)
예제 #5
0
    def __getitem__(self, item):
        # Slice SpectrogramCube using parent slicing.
        result = super().__getitem__(item)

        # As result is an NDCube, must put extra coord back into input format
        # to create a SpectrogramCube.
        if result.extra_coords is None:
            extra_coords = None
        else:
            extra_coords = convert_extra_coords_dict_to_input_format(
                result.extra_coords, result.missing_axes)

        # Slice instrument_axes if it exists.
        # If item is a slice, cube dimensionality is not reduced
        # so instrument_axes need not be sliced.
        if self.instrument_axes is None or isinstance(item, slice):
            instrument_axes = self.instrument_axes
        else:
            # If item is int, instrument_axes needs slicing.
            if isinstance(item, numbers.Integral):
                instrument_axes = self.instrument_axes[1:]
            # If item is tuple, instrument axes will need to be sliced if tuple contains an int.
            elif isinstance(item, tuple):
                instr_item = [isinstance(i, numbers.Integral) for i in item] + \
                        [False] * (len(self.instrument_axes) - len(item))
                instrument_axes = self.instrument_axes[np.invert(instr_item)]
            else:
                raise TypeError(
                    "Unrecognized slice item. Must be int, slice or tuple.")
            # If slicing causes cube to be a scalar, set instrument_axes to None.
            if len(instrument_axes) == 0:
                instrument_axes = None

        return self.__class__(result.data,
                              wcs=result.wcs,
                              uncertainty=result.uncertainty,
                              mask=result.mask,
                              meta=result.meta,
                              unit=result.unit,
                              extra_coords=extra_coords,
                              missing_axes=result.missing_axes,
                              instrument_axes=instrument_axes)
예제 #6
0
    def convert_to(self, new_unit_type):
        """
        Converts data, unit and uncertainty attributes to new unit type.

        The presence or absence of the exposure time correction is
        preserved in the conversions.

        Parameters
        ----------
        new_unit_type: `str`
           Unit type to convert data to.  Three values are accepted:
           "DN": Relevant IRIS data number based on detector type.
           "photons": photon counts
           "radiance": Perorms radiometric calibration conversion.

        Returns
        -------
        result: `IRISSpectrogramCube`
            New IRISSpectrogramCube in new units.

        """
        detector_type = iris_tools.get_detector_type(self.meta)
        if new_unit_type == "radiance" or self.unit.is_equivalent(
                iris_tools.RADIANCE_UNIT):
            # Get spectral dispersion per pixel.
            spectral_wcs_index = np.where(
                np.array(self.wcs.wcs.ctype) == "WAVE")[0][0]
            spectral_dispersion_per_pixel = self.wcs.wcs.cdelt[spectral_wcs_index] * \
                                            self.wcs.wcs.cunit[spectral_wcs_index]
            # Get solid angle from slit width for a pixel.
            lat_wcs_index = ["HPLT" in c for c in self.wcs.wcs.ctype]
            lat_wcs_index = np.arange(len(self.wcs.wcs.ctype))[lat_wcs_index]
            lat_wcs_index = lat_wcs_index[0]
            solid_angle = self.wcs.wcs.cdelt[lat_wcs_index] * \
                          self.wcs.wcs.cunit[lat_wcs_index] * iris_tools.SLIT_WIDTH
            # Get wavelength for each pixel.
            spectral_data_index = (-1) * (np.arange(len(self.dimensions)) +
                                          1)[spectral_wcs_index]
            obs_wavelength = self.axis_world_coords(2)
        if new_unit_type == "DN" or new_unit_type == "photons":
            if self.unit.is_equivalent(iris_tools.RADIANCE_UNIT):
                # Convert from radiance to counts/s
                new_data_quantities = iris_tools.convert_or_undo_photons_per_sec_to_radiance(
                    (self.data * self.unit,
                     self.uncertainty.array * self.unit),
                    obs_wavelength,
                    detector_type,
                    spectral_dispersion_per_pixel,
                    solid_angle,
                    undo=True)
                new_data = new_data_quantities[0].value
                new_uncertainty = new_data_quantities[1].value
                new_unit = new_data_quantities[0].unit
                self = IRISSpectrogramCube(
                    new_data,
                    self.wcs,
                    new_uncertainty,
                    new_unit,
                    self.meta,
                    convert_extra_coords_dict_to_input_format(
                        self.extra_coords, self.missing_axis),
                    mask=self.mask,
                    missing_axis=self.missing_axis)
            if new_unit_type == "DN":
                new_unit = iris_tools.DN_UNIT[detector_type]
            else:
                new_unit = u.photon
            new_data_arrays, new_unit = iris_tools.convert_between_DN_and_photons(
                (self.data, self.uncertainty.array), self.unit, new_unit)
            new_data = new_data_arrays[0]
            new_uncertainty = new_data_arrays[1]
        elif new_unit_type == "radiance":
            if self.unit.is_equivalent(iris_tools.RADIANCE_UNIT):
                new_data = self.data
                new_uncertainty = self.uncertainty
                new_unit = self.unit
            else:
                # Ensure spectrogram is in units of counts/s.
                cube = self.convert_to("photons")
                try:
                    cube = cube.apply_exposure_time_correction()
                except ValueError(iris_tools.APPLY_EXPOSURE_TIME_ERROR):
                    pass
                # Convert to radiance units.
                new_data_quantities = iris_tools.convert_or_undo_photons_per_sec_to_radiance(
                    (cube.data * cube.unit,
                     cube.uncertainty.array * cube.unit), obs_wavelength,
                    detector_type, spectral_dispersion_per_pixel, solid_angle)
                new_data = new_data_quantities[0].value
                new_uncertainty = new_data_quantities[1].value
                new_unit = new_data_quantities[0].unit
        else:
            raise ValueError("Input unit type not recognized.")
        return IRISSpectrogramCube(new_data,
                                   self.wcs,
                                   new_uncertainty,
                                   new_unit,
                                   self.meta,
                                   convert_extra_coords_dict_to_input_format(
                                       self.extra_coords, self.missing_axis),
                                   mask=self.mask,
                                   missing_axis=self.missing_axis)
예제 #7
0
파일: sji.py 프로젝트: MohamedNedal/irispy
    def apply_exposure_time_correction(self, undo=False, force=False):
        """
        Applies or undoes exposure time correction to data and uncertainty and adjusts unit.

        Correction is only applied (undone) if the object's unit doesn't (does)
        already include inverse time.  This can be overridden so that correction
        is applied (undone) regardless of unit by setting force=True.

        Parameters
        ----------
        undo: `bool`
            If False, exposure time correction is applied.
            If True, exposure time correction is removed.
            Default=False

        force: `bool`
            If not True, applies (undoes) exposure time correction only if unit
            doesn't (does) already include inverse time.
            If True, correction is applied (undone) regardless of unit.  Unit is still
            adjusted accordingly.

        Returns
        -------
        result: `IRISMapCube`
            A new IRISMapCube is returned with the correction applied (undone).

        """
        # Raise an error if this method is called while memmap is used
        if not self.scaled:
            raise ValueError(
                "This method is not available as you are using memmap")
        # Get exposure time in seconds and change array's shape so that
        # it can be broadcast with data and uncertainty arrays.
        exposure_time_s = u.Quantity(
            self.extra_coords["EXPOSURE TIME"]["value"], unit='s').value
        if not np.isscalar(self.extra_coords["EXPOSURE TIME"]["value"]):
            if self.data.ndim == 1:
                pass
            elif self.data.ndim == 2:
                exposure_time_s = exposure_time_s[:, np.newaxis]
            elif self.data.ndim == 3:
                exposure_time_s = exposure_time_s[:, np.newaxis, np.newaxis]
            else:
                raise ValueError(
                    "IRISMapCube dimensions must be 2 or 3. Dimensions={0}".
                    format(self.data.ndim))
        # Based on value on undo kwarg, apply or remove exposure time correction.
        if undo is True:
            new_data_arrays, new_unit = iris_tools.uncalculate_exposure_time_correction(
                (self.data, self.uncertainty.array),
                self.unit,
                exposure_time_s,
                force=force)
        else:
            new_data_arrays, new_unit = iris_tools.calculate_exposure_time_correction(
                (self.data, self.uncertainty.array),
                self.unit,
                exposure_time_s,
                force=force)
        # Return new instance of IRISMapCube with correction applied/undone.
        return IRISMapCube(
            data=new_data_arrays[0],
            wcs=self.wcs,
            uncertainty=new_data_arrays[1],
            unit=new_unit,
            meta=self.meta,
            mask=self.mask,
            missing_axes=self.missing_axes,
            scaled=self.scaled,
            extra_coords=convert_extra_coords_dict_to_input_format(
                self.extra_coords, self.missing_axes))
예제 #8
0
    def convert_to(self, new_unit_type, time_obs=None, response_version=4):
        """
        Converts data, unit and uncertainty attributes to new unit type.

        Takes into consideration also the observation time and response version.

        The presence or absence of the exposure time correction is
        preserved in the conversions.

        Parameters
        ----------
        new_unit_type: `str`
           Unit type to convert data to.  Three values are accepted:
           "DN": Relevant IRIS data number based on detector type.
           "photons": photon counts
           "radiance": Perorms radiometric calibration conversion.

        time_obs: an `astropy.time.Time` object, as a kwarg, valid for version > 2
           Observation times of the datapoints.
           Must be in the format of, e.g.,
           time_obs=Time('2013-09-03', format='utime'),
           which yields 1094169600.0 seconds in value.
           The argument time_obs is ignored for versions 1 and 2.

        response_version: `int`
            Version number of effective area file to be used. Cannot be set
            simultaneously with response_file or pre_launch kwarg. Default=4.

        Returns
        -------
        result: `IRISSpectrogramCube`
            New IRISSpectrogramCube in new units.

        """
        detector_type = iris_tools.get_detector_type(self.meta)
        time_obs = time_obs
        response_version = response_version  # Should default to latest
        if new_unit_type == "radiance" or self.unit.is_equivalent(
                iris_tools.RADIANCE_UNIT):
            # Get spectral dispersion per pixel.
            spectral_wcs_index = np.where(
                np.array(self.wcs.wcs.ctype) == "WAVE")[0][0]
            spectral_dispersion_per_pixel = self.wcs.wcs.cdelt[spectral_wcs_index] * \
                self.wcs.wcs.cunit[spectral_wcs_index]
            # Get solid angle from slit width for a pixel.
            lat_wcs_index = ["HPLT" in c for c in self.wcs.wcs.ctype]
            lat_wcs_index = np.arange(len(self.wcs.wcs.ctype))[lat_wcs_index]
            lat_wcs_index = lat_wcs_index[0]
            solid_angle = self.wcs.wcs.cdelt[lat_wcs_index] * \
                          self.wcs.wcs.cunit[lat_wcs_index] * iris_tools.SLIT_WIDTH
            # Get wavelength for each pixel.
            spectral_data_index = (-1) * (np.arange(len(self.dimensions)) +
                                          1)[spectral_wcs_index]
            obs_wavelength = self.axis_world_coords(2)

        if new_unit_type == "DN" or new_unit_type == "photons":
            if self.unit.is_equivalent(iris_tools.RADIANCE_UNIT):
                # Convert from radiance to counts/s
                new_data_quantities = iris_tools.convert_or_undo_photons_per_sec_to_radiance(
                    (self.data * self.unit,
                     self.uncertainty.array * self.unit),
                    time_obs,
                    response_version,
                    obs_wavelength,
                    detector_type,
                    spectral_dispersion_per_pixel,
                    solid_angle,
                    undo=True)
                new_data = new_data_quantities[0].value
                new_uncertainty = new_data_quantities[1].value
                new_unit = new_data_quantities[0].unit
                self = IRISSpectrogramCube(
                    new_data,
                    self.wcs,
                    new_uncertainty,
                    new_unit,
                    self.meta,
                    convert_extra_coords_dict_to_input_format(
                        self.extra_coords, self.missing_axes),
                    mask=self.mask,
                    missing_axes=self.missing_axes)
            if new_unit_type == "DN":
                new_unit = iris_tools.DN_UNIT[detector_type]
            else:
                new_unit = u.photon
            new_data_arrays, new_unit = iris_tools.convert_between_DN_and_photons(
                (self.data, self.uncertainty.array), self.unit, new_unit)
            new_data = new_data_arrays[0]
            new_uncertainty = new_data_arrays[1]
        elif new_unit_type == "radiance":
            if self.unit.is_equivalent(iris_tools.RADIANCE_UNIT):
                new_data = self.data
                new_uncertainty = self.uncertainty
                new_unit = self.unit
            else:
                # Ensure spectrogram is in units of counts/s.
                cube = self.convert_to("photons")
                try:
                    cube = cube.apply_exposure_time_correction()
                except ValueError(iris_tools.APPLY_EXPOSURE_TIME_ERROR):
                    pass
                # Convert to radiance units.
                new_data_quantities = iris_tools.convert_or_undo_photons_per_sec_to_radiance(
                    (cube.data * cube.unit,
                     cube.uncertainty.array * cube.unit), time_obs,
                    response_version, obs_wavelength, detector_type,
                    spectral_dispersion_per_pixel, solid_angle)
                new_data = new_data_quantities[0].value
                new_uncertainty = new_data_quantities[1].value
                new_unit = new_data_quantities[0].unit
        else:
            raise ValueError("Input unit type not recognized.")
        return IRISSpectrogramCube(new_data,
                                   self.wcs,
                                   new_uncertainty,
                                   new_unit,
                                   self.meta,
                                   convert_extra_coords_dict_to_input_format(
                                       self.extra_coords, self.missing_axes),
                                   mask=self.mask,
                                   missing_axes=self.missing_axes)