def true_axial_analysis(df_row, traj_def, euler_def, path_fnc, add_axial_rot_fnc):
    traj = df_row[traj_def]
    start_idx = df_row['up_down_analysis'].max_run_up_start_idx
    end_idx = df_row['up_down_analysis'].max_run_up_end_idx
    orient = np.rad2deg(rgetattr(traj, euler_def))
    true_axial = np.rad2deg(getattr(traj, 'true_axial_rot'))
    apparent_orient_diff = orient[end_idx, 2] - orient[start_idx, 2]
    true_axial_diff = true_axial[end_idx] - true_axial[start_idx]
    add_axial_rot = add_axial_rot_fnc(orient, start_idx, end_idx)

    long, lat = path_fnc(orient, start_idx, end_idx)

    # compute the area
    mid_ix = int((start_idx + end_idx) / 2)
    sp = SphericalPolygon.from_lonlat(long, lat, center=(orient[mid_ix, 0], orient[mid_ix, 1]/2))
    area = np.rad2deg(sp.area())

    # if the actual path and the "euler" path cross each other the spherical_geometry polygon incorrectly estimates the
    # area
    while area > 180:
        area -= 180

    return apparent_orient_diff, true_axial_diff, area, add_axial_rot, sp.is_clockwise()
Example #2
0
    def __init__(self, ra, dec, inside=None, max_depth=10):
        ra = ra.to(u.rad).value
        dec = dec.to(u.rad).value
        # Check if the vertices form a closed polygon
        if ra[0] != ra[-1] or dec[0] != dec[-1]:
            # If not, append the first vertex to ``vertices``
            ra = np.append(ra, ra[0])
            dec = np.append(dec, dec[0])
            vertices = SkyCoord(ra=ra, dec=dec, unit="rad", frame="icrs")

        if inside:
            # Convert it to (x, y, z) cartesian coordinates on the sphere
            inside = (inside.icrs.ra.rad, inside.icrs.dec.rad)

        self.polygon = SphericalPolygon.from_lonlat(lon=ra, lat=dec, center=inside, degrees=False)

        start_depth, ipixels = self._get_starting_depth()
        end_depth = max_depth

        # When the start depth returned is > to the depth requested
        # For that specific case, we only do one iteration at start_depth
        # Thus the MOC will contain the partially intersecting cells with the
        # contained ones at start_depth

        # And we degrade the MOC to the max_depth
        self.degrade_to_max_depth = False
        if start_depth > end_depth:
            end_depth = start_depth
            self.degrade_to_max_depth = True

        self.ipix_d = {str(order): [] for order in range(start_depth, end_depth + 1)}

        ## Iterative version of the algorithm: seems a bit faster than the recursive one
        for depth in range(start_depth, end_depth + 1):
            # Define a HEALPix at the current depth
            hp = HEALPix(nside=(1 << depth), order='nested', frame=ICRS())

            # Get the lon and lat of the corners of the pixels
            # intersecting the polygon
            lon, lat = hp.boundaries_lonlat(ipixels, step=1)
            lon = lon.to(u.rad).value
            lat = lat.to(u.rad).value

            # closes the lon and lat array so that their first and last value matches
            lon = self._closes_numpy_2d_array(lon)
            lat = self._closes_numpy_2d_array(lat)

            num_ipix_inter_poly = ipixels.shape[0]

            # Define a 3d numpy array containing the corners coordinates of the intersecting pixels
            # The first dim is the num of ipixels
            # The second is the number of coordinates (5 as it defines the closed polygon of a HEALPix cell)
            # The last is of size 2 (lon and lat)
            shapes = np.vstack((lon.ravel(), lat.ravel())).T.reshape(num_ipix_inter_poly, 5, -1)

            ipix_in_polygon_l = []
            ipix_inter_polygon_l = []

            for i in range(num_ipix_inter_poly):
                shape = shapes[i]
                # Definition of a SphericalPolygon from the border coordinates of a HEALPix cell
                ipix_shape = SphericalPolygon.from_radec(lon=shape[:, 0], lat=shape[:, 1], degrees=False)
                ipix = ipixels[i]

                if self.polygon.intersects_poly(ipix_shape):
                    # If we are at the max depth then we direcly add to the MOC the intersecting ipixels
                    if depth == end_depth:
                        ipix_in_polygon_l.append(ipix)
                    else:
                        # Check whether polygon contains ipix or not
                        if self.polygon_contains_ipix(ipix_shape):
                            ipix_in_polygon_l.append(ipix)
                        else:
                            # The ipix is just intersecting without being contained in the polygon
                            # We split it in its 4 children
                            child_ipix = ipix << 2
                            ipix_inter_polygon_l.extend([child_ipix,
                                                        child_ipix + 1,
                                                        child_ipix + 2,
                                                        child_ipix + 3])

            self.ipix_d.update({str(depth): ipix_in_polygon_l})
            ipixels = np.asarray(ipix_inter_polygon_l)