Loading .gitignore +3 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ # Docs docs/doxyxml/ docs/build/* docs/xml/* # Byte-compiled / optimized / DLL files __pycache__/ Loading Loading @@ -224,3 +225,5 @@ dmypy.json *.img *.IMG print.prt tests/ctests/default.profraw default.profraw CHANGELOG.md +1 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ release. ### Changed - Enabled Hayabusa2 drivers [#596](https://github.com/DOI-USGS/ale/pull/596) - Enabled Juno drivers [#597](https://github.com/DOI-USGS/ale/pull/597) - Enabled Odyssey drivers [#582](https://github.com/DOI-USGS/ale/pull/582) ### Added - Apollo Metric drivers, tests, and data [#533](https://github.com/DOI-USGS/ale/pull/533) Loading ale/base/type_distortion.py +12 −0 Original line number Diff line number Diff line Loading @@ -193,3 +193,15 @@ class LoDistortion(): "center_point_y" : center_point_y } } class ThemisIrDistortion(): @property def usgscsm_distortion_model(self): return { "themisir":{ "p_alpha1" : 0.00447623, "p_alpha2" : 0.00107556, "p_k" : 0.996005 } } No newline at end of file ale/drivers/__init__.py +2 −2 Original line number Diff line number Diff line Loading @@ -23,8 +23,8 @@ from ale.base.data_naif import NaifSpice from abc import ABC # Explicit list of disabled drivers __disabled_drivers__ = ["ody_drivers", "tgo_drivers"] __disabled_drivers__ = ["tgo_drivers"] # dynamically load drivers __all__ = [os.path.splitext(os.path.basename(d))[0] for d in glob(os.path.join(os.path.dirname(__file__), '*_drivers.py'))] Loading ale/drivers/ody_drivers.py +370 −30 Original line number Diff line number Diff line import spiceypy as spice import ale import math from ale.base.base import Driver from ale.base.type_distortion import NoDistortion from ale.base.type_distortion import ThemisIrDistortion, NoDistortion from ale.base.data_naif import NaifSpice from ale.base.label_isis import IsisLabel from ale.base.type_sensor import LineScanner from ale.base.type_sensor import LineScanner, PushFrame import pvl class OdyThemisIrIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, NoDistortion, Driver): class OdyThemisIrIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, ThemisIrDistortion, Driver): """ Driver for Themis IR ISIS cube """ @property def instrument_id(self): """ Returns the short name of the instrument Returns ------- : str instrument id """ inst_id = super().instrument_id if inst_id not in ["THEMIS_IR"]: raise Exception(f"{inst_id} is not a valid THEMIS IR instrument name. Expecting THEMIS_IR") return inst_id @property def sensor_model_version(self): """ Returns ------- : int version of the sensor model """ return 1 @property def spacecraft_name(self): """ Returns the name of the spacecraft Returns ------- : str Full name of the spacecraft """ name = super().spacecraft_name.replace('_', ' ') if name != "MARS ODYSSEY": raise Exception("{name} for label is not a valid Mars Odyssey spacecraft name") Loading @@ -35,8 +56,34 @@ class OdyThemisIrIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, NoD @property def ikid(self): """ Returns the Naif ID code for the instrument Returns ------- : int Naif ID used to for identifying the instrument in Spice kernels """ return self.label['IsisCube']['Kernels']['NaifFrameCode'] @property def sampling_factor(self): """ Returns the summing factor from the ISIS label. For example a return value of 2 indicates that 2 lines and 2 samples (4 pixels) were summed and divided by 4 to produce the output pixel value. Returns ------- : int Number of samples and lines combined from the original data to produce a single pixel in this image """ try: summing = self.label['IsisCube']['Instrument']['SpatialSumming'] except: summing = 1 return summing @property def line_exposure_duration(self): """ Loading @@ -47,7 +94,17 @@ class OdyThemisIrIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, NoD return (33.2871/1000 * self.line_summing) @property def ephemeris_start_time(self): def start_time(self): """ The starting ephemeris time, in seconds Formula derived from ISIS3's ThemisIr Camera model Returns ------- : double Starting ephemeris time in seconds """ og_start_time = super().ephemeris_start_time offset = self.label["IsisCube"]["Instrument"]["SpacecraftClockOffset"] if isinstance(offset, pvl.collections.Quantity): Loading @@ -60,30 +117,145 @@ class OdyThemisIrIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, NoD return og_start_time + offset @property def ephemeris_start_time(self): """ Returns the ephemeris start time of the image. Expects spacecraft_id to be defined. This should be the integer Naif ID code for the spacecraft. Returns ------- : float ephemeris start time of the image """ return self.band_times[0] @property def ephemeris_stop_time(self): """ Returns the sum of the starting ephemeris time and the number of lines times the exposure duration. Expects ephemeris start time, exposure duration and image lines to be defined. These should be double precision numbers containing the ephemeris start, exposure duration and number of lines of the image. Returns ------- : double Center ephemeris time for an image """ return self.band_times[-1] + (self.image_lines * self.line_exposure_duration) @property def focal_length(self): return 202.059 """ The focal length of the instrument Returns ------- float : The focal length in millimeters """ return 203.9213 @property def detector_center_sample(self): """ Returns the center detector sample. Returns ------- : float Detector sample of the principal point """ return 160.0 @property def detector_center_line(self): """ Returns the center detector line. Returns ------- : float Detector line of the principal point """ return 0 @property def detector_center_sample(self): return 0 def tdi_mode(self): return self.label['IsisCube']['Instrument']["TimeDelayIntegration"] @property def sensor_name(self): """ Returns the name of the sensor Returns ------- : str Name of the sensor """ return self.label['IsisCube']['Instrument']['SpacecraftName'] @property def band_times(self): """ Computes the band offset and adds to each band's start time Returns ------- : list Adjusted start times for each band """ self._num_bands = self.label["IsisCube"]["Core"]["Dimensions"]["Bands"] times = [] org_bands = self.label["IsisCube"]["BandBin"]["FilterNumber"] for vband in range(self._num_bands): if 'ReferenceBand' in self.label['IsisCube']['Instrument']: band = self.label['IsisCube']['Instrument']['ReferenceBand'] else: if isinstance(org_bands, (list, tuple)): band = org_bands[vband] else: band = org_bands if (self.tdi_mode == "ENABLED"): band_tdi = [8.5, 24.5, 50.5, 76.5, 102.5, 128.5, 154.5, 180.5, 205.5, 231.5] detector_line = band_tdi[band-1] else: band_no_tdi = [9, 24, 52, 77, 102, 129, 155, 181, 206, 232] detector_line = band_no_tdi[band-1] class OdyThemisVisIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, NoDistortion, Driver): band_offset = (detector_line - 0.5) * self.line_exposure_duration band_offset /= self.sampling_factor time = self.start_time + band_offset times.append(time) return times class OdyThemisVisIsisLabelNaifSpiceDriver(PushFrame, IsisLabel, NaifSpice, NoDistortion, Driver): """" Driver for Themis VIS ISIS cube """ @property def instrument_id(self): """ Returns the short name of the instrument Returns ------- : str instrument id """ inst_id = super().instrument_id if inst_id not in ["THEMIS_VIS"]: Loading @@ -93,10 +265,23 @@ class OdyThemisVisIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, No @property def sensor_model_version(self): """ Returns ------- : int version of the sensor model """ return 1 @property def spacecraft_name(self): """ Returns the name of the spacecraft Returns ------- : str Full name of the spacecraft """ name = super().spacecraft_name.replace('_', ' ') if name != "MARS ODYSSEY": raise Exception("{name} for label is not a valid Mars Odyssey spacecraft name") Loading @@ -104,10 +289,18 @@ class OdyThemisVisIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, No @property def ikid(self): """ Returns the Naif ID code for the instrument Returns ------- : int Naif ID used to for identifying the instrument in Spice kernels """ return self.label['IsisCube']['Kernels']['NaifFrameCode'] @property def ephemeris_start_time(self): def start_time(self): """ The starting ephemeris time, in seconds Loading @@ -118,7 +311,10 @@ class OdyThemisVisIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, No : double Starting ephemeris time in seconds """ og_start_time = super().ephemeris_start_time clock_start_count = self.label['IsisCube']['Instrument']['SpacecraftClockCount'] # ran into weird quirk that if clock count ends with a zero, str() will drop the last zero causing scs2e to return a different et. og_start_time = spice.scs2e(self.spacecraft_id, f'{clock_start_count:.3f}') offset = self.label["IsisCube"]["Instrument"]["SpacecraftClockOffset"] if isinstance(offset, pvl.collections.Quantity): Loading @@ -129,43 +325,187 @@ class OdyThemisVisIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, No # if not milliseconds, the units are probably seconds offset = offset.value return og_start_time + offset - (self.line_exposure_duration/2) return og_start_time + offset - (self.exposure_duration / 2) @property def line_exposure_duration(self): def ephemeris_start_time(self): """ The line exposure duration of the image, in seconds Returns the ephemeris start time of the image. Expects spacecraft_id to be defined. This should be the integer Naif ID code for the spacecraft. Returns ------- : float Line exposure duration in seconds ephemeris start time of the image """ line_exposure_duration = self.label['IsisCube']['Instrument']['ExposureDuration'] if isinstance(line_exposure_duration, pvl.collections.Quantity): units = line_exposure_duration.units if "ms" in units.lower(): line_exposure_duration = line_exposure_duration.value * 0.001 else: # if not milliseconds, the units are probably seconds line_exposure_duration = line_exposure_duration.value else: # if no units are available, assume the exposure duration is given in milliseconds line_exposure_duration = line_exposure_duration * 0.001 return line_exposure_duration return self.band_times[0] @property def center_ephemeris_time(self): """ Returns the center ephemeris times based off the last band start time. Expects spacecraft_id to be defined. This should be the integer Naif ID code for the spacecraft. Returns ------- : double Center ephemeris time for an image """ center_frame = math.floor(self.num_frames / 2) return (self.band_times[-1] + center_frame * self.interframe_delay) + self.exposure_duration @property def ephemeris_stop_time(self): """ Returns the ephemeris stop time of the image. Expects spacecraft_id to be defined. This should be the integer Naif ID code for the spacecraft. Returns ------- : float ephemeris stop time of the image """ return (max(self.band_times) + self.num_frames * self.interframe_delay) + self.exposure_duration @property def focal_length(self): """ The focal length of the instrument Returns ------- float : The focal length in millimeters """ return 202.059 @property def detector_center_line(self): return 0 """ Returns the center detector line. Returns ------- : float Detector line of the principal point """ return 512.0 @property def detector_center_sample(self): return 0 """ Returns the center detector sample. Returns ------- : float Detector sample of the principal point """ return 512.0 @property def sensor_name(self): """ Returns the name of the sensor Returns ------- : str Name of the sensor """ return self.label['IsisCube']['Instrument']['SpacecraftName'] @property def num_frames(self): """ Number of frames in the image Returns ------- : int Number of frames in the image """ return self.label['IsisCube']['Instrument']['NumFramelets'] @property def framelet_height(self): """ Computes the framelet height based on number lines, number of frames and sampling factor Returns ------- : float height of framelet """ return self.image_lines / (self.num_frames / self.sampling_factor) @property def sampling_factor(self): """ Returns the summing factor from the PDS3 label that is defined by the SpatialSumming Returns ------- : int Number of samples and lines combined from the original data to produce a single pixel in this image """ return self.label['IsisCube']['Instrument']['SpatialSumming'] @property def interframe_delay(self): """ The interframe delay in seconds Returns ------- : float interframe delay in seconds """ return self.label['IsisCube']['Instrument']['InterframeDelay'] @property def band_times(self): """ Computes the band offset and adds to each band's start time Returns ------- : list Adjusted start times for each band """ self._num_bands = self.label["IsisCube"]["Core"]["Dimensions"]["Bands"] times = [] org_bands = self.label["IsisCube"]["BandBin"]["FilterNumber"] for vband in range(self._num_bands): if isinstance(org_bands, (list, tuple)): timeband = org_bands[vband] else: timeband = org_bands if 'ReferenceBand' in self.label['IsisCube']['Instrument']: ref_band = self.label['IsisCube']['Instrument']['ReferenceBand'] wavelength_to_timeband = [2, 5, 3, 4, 1] timeband = wavelength_to_timeband[ref_band - 1] band_offset = ((timeband - 1) * self.interframe_delay) - (self.exposure_duration / 2.0) time = self.start_time + band_offset times.append(time) return times @property def framelets_flipped(self): """ Checks if framelets are flipped Returns ------- : bool """ return True No newline at end of file Loading
.gitignore +3 −0 Original line number Diff line number Diff line Loading @@ -4,6 +4,7 @@ # Docs docs/doxyxml/ docs/build/* docs/xml/* # Byte-compiled / optimized / DLL files __pycache__/ Loading Loading @@ -224,3 +225,5 @@ dmypy.json *.img *.IMG print.prt tests/ctests/default.profraw default.profraw
CHANGELOG.md +1 −0 Original line number Diff line number Diff line Loading @@ -37,6 +37,7 @@ release. ### Changed - Enabled Hayabusa2 drivers [#596](https://github.com/DOI-USGS/ale/pull/596) - Enabled Juno drivers [#597](https://github.com/DOI-USGS/ale/pull/597) - Enabled Odyssey drivers [#582](https://github.com/DOI-USGS/ale/pull/582) ### Added - Apollo Metric drivers, tests, and data [#533](https://github.com/DOI-USGS/ale/pull/533) Loading
ale/base/type_distortion.py +12 −0 Original line number Diff line number Diff line Loading @@ -193,3 +193,15 @@ class LoDistortion(): "center_point_y" : center_point_y } } class ThemisIrDistortion(): @property def usgscsm_distortion_model(self): return { "themisir":{ "p_alpha1" : 0.00447623, "p_alpha2" : 0.00107556, "p_k" : 0.996005 } } No newline at end of file
ale/drivers/__init__.py +2 −2 Original line number Diff line number Diff line Loading @@ -23,8 +23,8 @@ from ale.base.data_naif import NaifSpice from abc import ABC # Explicit list of disabled drivers __disabled_drivers__ = ["ody_drivers", "tgo_drivers"] __disabled_drivers__ = ["tgo_drivers"] # dynamically load drivers __all__ = [os.path.splitext(os.path.basename(d))[0] for d in glob(os.path.join(os.path.dirname(__file__), '*_drivers.py'))] Loading
ale/drivers/ody_drivers.py +370 −30 Original line number Diff line number Diff line import spiceypy as spice import ale import math from ale.base.base import Driver from ale.base.type_distortion import NoDistortion from ale.base.type_distortion import ThemisIrDistortion, NoDistortion from ale.base.data_naif import NaifSpice from ale.base.label_isis import IsisLabel from ale.base.type_sensor import LineScanner from ale.base.type_sensor import LineScanner, PushFrame import pvl class OdyThemisIrIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, NoDistortion, Driver): class OdyThemisIrIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, ThemisIrDistortion, Driver): """ Driver for Themis IR ISIS cube """ @property def instrument_id(self): """ Returns the short name of the instrument Returns ------- : str instrument id """ inst_id = super().instrument_id if inst_id not in ["THEMIS_IR"]: raise Exception(f"{inst_id} is not a valid THEMIS IR instrument name. Expecting THEMIS_IR") return inst_id @property def sensor_model_version(self): """ Returns ------- : int version of the sensor model """ return 1 @property def spacecraft_name(self): """ Returns the name of the spacecraft Returns ------- : str Full name of the spacecraft """ name = super().spacecraft_name.replace('_', ' ') if name != "MARS ODYSSEY": raise Exception("{name} for label is not a valid Mars Odyssey spacecraft name") Loading @@ -35,8 +56,34 @@ class OdyThemisIrIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, NoD @property def ikid(self): """ Returns the Naif ID code for the instrument Returns ------- : int Naif ID used to for identifying the instrument in Spice kernels """ return self.label['IsisCube']['Kernels']['NaifFrameCode'] @property def sampling_factor(self): """ Returns the summing factor from the ISIS label. For example a return value of 2 indicates that 2 lines and 2 samples (4 pixels) were summed and divided by 4 to produce the output pixel value. Returns ------- : int Number of samples and lines combined from the original data to produce a single pixel in this image """ try: summing = self.label['IsisCube']['Instrument']['SpatialSumming'] except: summing = 1 return summing @property def line_exposure_duration(self): """ Loading @@ -47,7 +94,17 @@ class OdyThemisIrIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, NoD return (33.2871/1000 * self.line_summing) @property def ephemeris_start_time(self): def start_time(self): """ The starting ephemeris time, in seconds Formula derived from ISIS3's ThemisIr Camera model Returns ------- : double Starting ephemeris time in seconds """ og_start_time = super().ephemeris_start_time offset = self.label["IsisCube"]["Instrument"]["SpacecraftClockOffset"] if isinstance(offset, pvl.collections.Quantity): Loading @@ -60,30 +117,145 @@ class OdyThemisIrIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, NoD return og_start_time + offset @property def ephemeris_start_time(self): """ Returns the ephemeris start time of the image. Expects spacecraft_id to be defined. This should be the integer Naif ID code for the spacecraft. Returns ------- : float ephemeris start time of the image """ return self.band_times[0] @property def ephemeris_stop_time(self): """ Returns the sum of the starting ephemeris time and the number of lines times the exposure duration. Expects ephemeris start time, exposure duration and image lines to be defined. These should be double precision numbers containing the ephemeris start, exposure duration and number of lines of the image. Returns ------- : double Center ephemeris time for an image """ return self.band_times[-1] + (self.image_lines * self.line_exposure_duration) @property def focal_length(self): return 202.059 """ The focal length of the instrument Returns ------- float : The focal length in millimeters """ return 203.9213 @property def detector_center_sample(self): """ Returns the center detector sample. Returns ------- : float Detector sample of the principal point """ return 160.0 @property def detector_center_line(self): """ Returns the center detector line. Returns ------- : float Detector line of the principal point """ return 0 @property def detector_center_sample(self): return 0 def tdi_mode(self): return self.label['IsisCube']['Instrument']["TimeDelayIntegration"] @property def sensor_name(self): """ Returns the name of the sensor Returns ------- : str Name of the sensor """ return self.label['IsisCube']['Instrument']['SpacecraftName'] @property def band_times(self): """ Computes the band offset and adds to each band's start time Returns ------- : list Adjusted start times for each band """ self._num_bands = self.label["IsisCube"]["Core"]["Dimensions"]["Bands"] times = [] org_bands = self.label["IsisCube"]["BandBin"]["FilterNumber"] for vband in range(self._num_bands): if 'ReferenceBand' in self.label['IsisCube']['Instrument']: band = self.label['IsisCube']['Instrument']['ReferenceBand'] else: if isinstance(org_bands, (list, tuple)): band = org_bands[vband] else: band = org_bands if (self.tdi_mode == "ENABLED"): band_tdi = [8.5, 24.5, 50.5, 76.5, 102.5, 128.5, 154.5, 180.5, 205.5, 231.5] detector_line = band_tdi[band-1] else: band_no_tdi = [9, 24, 52, 77, 102, 129, 155, 181, 206, 232] detector_line = band_no_tdi[band-1] class OdyThemisVisIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, NoDistortion, Driver): band_offset = (detector_line - 0.5) * self.line_exposure_duration band_offset /= self.sampling_factor time = self.start_time + band_offset times.append(time) return times class OdyThemisVisIsisLabelNaifSpiceDriver(PushFrame, IsisLabel, NaifSpice, NoDistortion, Driver): """" Driver for Themis VIS ISIS cube """ @property def instrument_id(self): """ Returns the short name of the instrument Returns ------- : str instrument id """ inst_id = super().instrument_id if inst_id not in ["THEMIS_VIS"]: Loading @@ -93,10 +265,23 @@ class OdyThemisVisIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, No @property def sensor_model_version(self): """ Returns ------- : int version of the sensor model """ return 1 @property def spacecraft_name(self): """ Returns the name of the spacecraft Returns ------- : str Full name of the spacecraft """ name = super().spacecraft_name.replace('_', ' ') if name != "MARS ODYSSEY": raise Exception("{name} for label is not a valid Mars Odyssey spacecraft name") Loading @@ -104,10 +289,18 @@ class OdyThemisVisIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, No @property def ikid(self): """ Returns the Naif ID code for the instrument Returns ------- : int Naif ID used to for identifying the instrument in Spice kernels """ return self.label['IsisCube']['Kernels']['NaifFrameCode'] @property def ephemeris_start_time(self): def start_time(self): """ The starting ephemeris time, in seconds Loading @@ -118,7 +311,10 @@ class OdyThemisVisIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, No : double Starting ephemeris time in seconds """ og_start_time = super().ephemeris_start_time clock_start_count = self.label['IsisCube']['Instrument']['SpacecraftClockCount'] # ran into weird quirk that if clock count ends with a zero, str() will drop the last zero causing scs2e to return a different et. og_start_time = spice.scs2e(self.spacecraft_id, f'{clock_start_count:.3f}') offset = self.label["IsisCube"]["Instrument"]["SpacecraftClockOffset"] if isinstance(offset, pvl.collections.Quantity): Loading @@ -129,43 +325,187 @@ class OdyThemisVisIsisLabelNaifSpiceDriver(LineScanner, IsisLabel, NaifSpice, No # if not milliseconds, the units are probably seconds offset = offset.value return og_start_time + offset - (self.line_exposure_duration/2) return og_start_time + offset - (self.exposure_duration / 2) @property def line_exposure_duration(self): def ephemeris_start_time(self): """ The line exposure duration of the image, in seconds Returns the ephemeris start time of the image. Expects spacecraft_id to be defined. This should be the integer Naif ID code for the spacecraft. Returns ------- : float Line exposure duration in seconds ephemeris start time of the image """ line_exposure_duration = self.label['IsisCube']['Instrument']['ExposureDuration'] if isinstance(line_exposure_duration, pvl.collections.Quantity): units = line_exposure_duration.units if "ms" in units.lower(): line_exposure_duration = line_exposure_duration.value * 0.001 else: # if not milliseconds, the units are probably seconds line_exposure_duration = line_exposure_duration.value else: # if no units are available, assume the exposure duration is given in milliseconds line_exposure_duration = line_exposure_duration * 0.001 return line_exposure_duration return self.band_times[0] @property def center_ephemeris_time(self): """ Returns the center ephemeris times based off the last band start time. Expects spacecraft_id to be defined. This should be the integer Naif ID code for the spacecraft. Returns ------- : double Center ephemeris time for an image """ center_frame = math.floor(self.num_frames / 2) return (self.band_times[-1] + center_frame * self.interframe_delay) + self.exposure_duration @property def ephemeris_stop_time(self): """ Returns the ephemeris stop time of the image. Expects spacecraft_id to be defined. This should be the integer Naif ID code for the spacecraft. Returns ------- : float ephemeris stop time of the image """ return (max(self.band_times) + self.num_frames * self.interframe_delay) + self.exposure_duration @property def focal_length(self): """ The focal length of the instrument Returns ------- float : The focal length in millimeters """ return 202.059 @property def detector_center_line(self): return 0 """ Returns the center detector line. Returns ------- : float Detector line of the principal point """ return 512.0 @property def detector_center_sample(self): return 0 """ Returns the center detector sample. Returns ------- : float Detector sample of the principal point """ return 512.0 @property def sensor_name(self): """ Returns the name of the sensor Returns ------- : str Name of the sensor """ return self.label['IsisCube']['Instrument']['SpacecraftName'] @property def num_frames(self): """ Number of frames in the image Returns ------- : int Number of frames in the image """ return self.label['IsisCube']['Instrument']['NumFramelets'] @property def framelet_height(self): """ Computes the framelet height based on number lines, number of frames and sampling factor Returns ------- : float height of framelet """ return self.image_lines / (self.num_frames / self.sampling_factor) @property def sampling_factor(self): """ Returns the summing factor from the PDS3 label that is defined by the SpatialSumming Returns ------- : int Number of samples and lines combined from the original data to produce a single pixel in this image """ return self.label['IsisCube']['Instrument']['SpatialSumming'] @property def interframe_delay(self): """ The interframe delay in seconds Returns ------- : float interframe delay in seconds """ return self.label['IsisCube']['Instrument']['InterframeDelay'] @property def band_times(self): """ Computes the band offset and adds to each band's start time Returns ------- : list Adjusted start times for each band """ self._num_bands = self.label["IsisCube"]["Core"]["Dimensions"]["Bands"] times = [] org_bands = self.label["IsisCube"]["BandBin"]["FilterNumber"] for vband in range(self._num_bands): if isinstance(org_bands, (list, tuple)): timeband = org_bands[vband] else: timeband = org_bands if 'ReferenceBand' in self.label['IsisCube']['Instrument']: ref_band = self.label['IsisCube']['Instrument']['ReferenceBand'] wavelength_to_timeband = [2, 5, 3, 4, 1] timeband = wavelength_to_timeband[ref_band - 1] band_offset = ((timeband - 1) * self.interframe_delay) - (self.exposure_duration / 2.0) time = self.start_time + band_offset times.append(time) return times @property def framelets_flipped(self): """ Checks if framelets are flipped Returns ------- : bool """ return True No newline at end of file