Exemple #1
0
    def __init__(self,
                 target: str,
                 time_unit: str = "min",
                 angular_unit: str = "deg"):
        """ Creates a JanusMosaicGenerator

        :param target: target body, e.g. "CALLISTO"
        :param time_unit: Unit for temporal values - "sec", "min" or "hour"
        :param angular_unit: Unit for angular values - "deg", "rad", "arcMin" or "arcSec"
        """
        if not target or not isinstance(target, str):
            raise TypeError(
                f"target must be a non-empty string, not '{target}'")
        self.target = target
        if time_unit not in time_units:
            raise ValueError(
                f"Time unit must be one of following: {time_units}")
        self.time_unit = time_unit
        if angular_unit not in angular_units:
            raise ValueError(
                f"Angular unit must be one of following: {angular_units}")
        self.angular_unit = angular_unit

        # Convert JANUS FOV size from radians to required angular unit
        self.fov_size: Tuple[float, float] = tuple(
            convertAngleFromTo(v_deg, "deg", self.angular_unit)
            for v_deg in self.JANUS_FOV_SIZE_DEG)
        # the time unit arguments are in opposite order because slew rate has time in denominator
        self.slew_rate_in_required_units = convertTimeFromTo(
            convertAngleFromTo(self.JUICE_SLEW_RATE_DEG_PER_SEC, "deg",
                               self.angular_unit), self.time_unit, "sec")
Exemple #2
0
    def plot(self, query_spice: bool = True):
        """ Shows generated scan diagram. """
        plt.figure()
        # plot rectangles
        for r in self.rectangles:
            r.plot_to_ax(plt.gca(), 'b')
        # plot slew trajectory
        traj_points = []
        x_delta, y_delta = self.delta
        for i, cp in enumerate(self.center_points):
            tps = [(cp[0], cp[1] - y_delta / 2), (cp[0], cp[1] + y_delta / 2)]
            if i % 2:
                tps = list(reversed(tps))
            traj_points += tps
        plt.gca().plot(*zip(*traj_points),
                       'k',
                       linewidth=2,
                       linestyle='dashed')
        plt.gca().plot(*zip(*traj_points), 'rx')
        if query_spice:
            radius_start = convertAngleFromTo(
                get_body_angular_diameter_rad("JUICE", self.target,
                                              self.start_time) / 2, "rad",
                self.angular_unit)
            circle_start = plt.Circle((0, 0),
                                      radius=radius_start,
                                      color='#FF0000',
                                      fill=False,
                                      linewidth=2)
            plt.gca().add_artist(circle_start)

            radius_end = convertAngleFromTo(
                get_body_angular_diameter_rad("JUICE", self.target,
                                              self.end_time) / 2, "rad",
                self.angular_unit)
            circle_end = plt.Circle((0, 0),
                                    radius=radius_end,
                                    color='#A00000',
                                    fill=False,
                                    linewidth=2,
                                    linestyle='-.')
            plt.gca().add_artist(circle_end)

            illuminated_shape_start = get_illuminated_shape(
                "JUICE", self.target, self.start_time, self.angular_unit)
            plt.gca().plot(*illuminated_shape_start.exterior.xy, '#CCCC00')

            illuminated_shape_end = get_illuminated_shape(
                "JUICE", self.target, self.end_time, self.angular_unit)
            plt.gca().plot(*illuminated_shape_end.exterior.xy,
                           color='#999900',
                           linestyle='-.')
        plt.axis('equal')
        plt.grid()
        plt.xlabel(f'X coordinate [{self.angular_unit}]')
        plt.ylabel(f'Y coordinate [{self.angular_unit}]')
        plt.title(f'Scan of {self.target} at {self.start_time.isoformat()}')
        plt.show()
Exemple #3
0
 def test_input(self):
     with self.assertRaises(ValueError, msg="Invalid unit request"):
         convertAngleFromTo(1.3, " min", "sec")
     with self.assertRaises(ValueError, msg="Invalid unit request"):
         convertAngleFromTo(1.3, "deg", "sec")
     with self.assertRaises(ValueError, msg="Invalid unit request"):
         convertAngleFromTo(1.3, "deg", "ArcSec")
     with self.assertRaises(ValueError, msg="Invalid unit request"):
         convertAngleFromTo(1.3, None, "arcSec")
     with self.assertRaises(ValueError, msg="Invalid unit request"):
         convertAngleFromTo(1.3, "deg", "")
Exemple #4
0
    def plot(self, query_spice: bool = True):
        """ Shows generated mosaic diagram. """
        plt.figure()
        for r in self.rectangles:
            r.plot_to_ax(plt.gca(), 'b')
        plt.gca().plot(*zip(*self.center_points), 'k')
        plt.gca().plot(*zip(*self.center_points), 'rx')
        if query_spice:
            radius_start = convertAngleFromTo(
                get_body_angular_diameter_rad("JUICE", self.target,
                                              self.start_time) / 2, "rad",
                self.angular_unit)
            circle_start = plt.Circle((0, 0),
                                      radius=radius_start,
                                      color='#FF0000',
                                      fill=False,
                                      linewidth=2)
            plt.gca().add_artist(circle_start)

            radius_end = convertAngleFromTo(
                get_body_angular_diameter_rad("JUICE", self.target,
                                              self.end_time) / 2, "rad",
                self.angular_unit)
            circle_end = plt.Circle((0, 0),
                                    radius=radius_end,
                                    color='#A00000',
                                    fill=False,
                                    linewidth=2,
                                    linestyle='-.')
            plt.gca().add_artist(circle_end)

            illuminated_shape_start = get_illuminated_shape(
                "JUICE", self.target, self.start_time, self.angular_unit)
            plt.gca().plot(*illuminated_shape_start.exterior.xy, '#CCCC00')

            illuminated_shape_end = get_illuminated_shape(
                "JUICE", self.target, self.end_time, self.angular_unit)
            plt.gca().plot(*illuminated_shape_end.exterior.xy,
                           color='#999900',
                           linestyle='-.')
        plt.axis('equal')
        plt.grid()
        plt.xlabel(f'X coordinate [{self.angular_unit}]')
        plt.ylabel(f'Y coordinate [{self.angular_unit}]')
        plt.title(f'Mosaic of {self.target} at {self.start_time.isoformat()}')
        plt.show()
Exemple #5
0
 def test_conversions(self):
     self.assertEquals(convertAngleFromTo(0.0, "deg", "rad"), 0.0)
     self.assertEquals(convertAngleFromTo(0, "deg", "deg"), 0.0)
     self.assertEquals(
         convertAngleFromTo(0.23184984351384843, "deg", "deg"),
         0.23184984351384843)
     self.assertEquals(convertAngleFromTo(-3.1689, "deg", "deg"), -3.1689)
     self.assertEquals(convertAngleFromTo(1.0, "deg", "rad"), np.pi / 180)
     self.assertAlmostEquals(convertAngleFromTo(4.36, "arcSec", "rad"),
                             2.114e-5,
                             places=4)
     self.assertAlmostEquals(convertAngleFromTo(14.36, "arcSec", "arcMin"),
                             0.23933,
                             places=4)
     self.assertAlmostEquals(convertAngleFromTo(814.21, "deg", "arcMin"),
                             48842.8,
                             places=0)
Exemple #6
0
    def __init__(self, fov_width: float, probe: str, target: str,
                 start_time: datetime, time_unit: str, angular_unit: str,
                 measurement_slew_rate: float, transfer_slew_rate: float):
        """ Create a ScanGenerator

        :param fov_width: width of FOV along x-axis
        :param probe: SPICE name of probe, e.g. "JUICE"
        :param target: SPICE name of target body, e.g. "CALLISTO"
        :param start_time: Time of beginning of mosaic
        :param time_unit: Unit for temporal values - "sec", "min" or "hour"
        :param angular_unit: Unit for angular values - "deg", "rad", "arcMin" or "arcSec"
        :param measurement_slew_rate: Slew rate during scanning measurement - depends on instrument
        :param transfer_slew_rate: Slew rate for transferring in between scans - as high as possible
        """
        if fov_width <= 0.0:
            raise ValueError(f"FOV width must be positive: {fov_width}")
        self.fov_width = fov_width

        self.probe = probe
        self.target = target

        self.start_time = start_time
        if time_unit not in time_units:
            raise ValueError(
                f"Time unit must be one of following: {time_units}")
        self.time_unit = time_unit
        if angular_unit not in angular_units:
            raise ValueError(
                f"Angular unit must be one of following: {angular_units}")
        self.angular_unit = angular_unit
        if measurement_slew_rate <= 0.0:
            raise ValueError(
                f"Measurement slew rate must be positive: {measurement_slew_rate}"
            )
        self.measurement_slew_rate = measurement_slew_rate
        if transfer_slew_rate <= 0.0:
            raise ValueError(
                f"Transfer slew rate must be positive: {transfer_slew_rate}")
        self.transfer_slew_rate = transfer_slew_rate

        # calculate angular size of target at start time
        self.target_angular_diameter = convertAngleFromTo(
            get_body_angular_diameter_rad(self.probe, self.target, start_time),
            "rad", self.angular_unit)
Exemple #7
0
    def __init__(self, fov_size: Tuple[float, float],
                 probe: str, target: str,
                 start_time: datetime,
                 time_unit: str, angular_unit: str,
                 dwell_time: float,
                 slew_rate: float):
        """ Create a MosaicGenerator

        :param fov_size: 2-tuple (x, y) containing rectangular FOV size
        :param probe: SPICE name of probe, e.g. "JUICE"
        :param target: SPICE name of target body, e.g. "CALLISTO"
        :param start_time: Time of beginning of mosaic
        :param time_unit: Unit for temporal values - "sec", "min" or "hour"
        :param angular_unit: Unit for angular values - "deg", "rad", "arcMin" or "arcSec"
        :param dwell_time: Dwell time at each mosaic point
        :param slew_rate: Rate of slew of spacecraft in units specified
        """
        if any([x < 0.0 for x in fov_size]):
            raise ValueError(f"FOV size values must be non-negative: {fov_size}")
        self.fov_size = fov_size

        self.probe = probe
        self.target = target

        self.start_time = start_time
        if time_unit not in time_units:
            raise ValueError(f"Time unit must be one of following: {time_units}")
        self.time_unit = time_unit
        if angular_unit not in angular_units:
            raise ValueError(f"Angular unit must be one of following: {angular_units}")
        self.angular_unit = angular_unit
        if dwell_time < 0.0:
            raise ValueError(f"Dwell time must be non-negative: {dwell_time}")
        self.dwell_time = dwell_time
        if slew_rate <= 0.0:
            raise ValueError(f"Slew rate must be positive: {slew_rate}")
        self.slew_rate = slew_rate

        # calculate angular size of target at start time
        self.target_angular_diameter = convertAngleFromTo(get_body_angular_diameter_rad(self.probe, self.target, start_time),
                                                          "rad", self.angular_unit)