Esempio n. 1
0
    def corners(self, gmt_format=False):
        """
        Retrieve corners of simulation domain.
        gmt_format: if True, also returns corners in GMT string format
        """
        # compared with model_params format:
        # c1 =   x0   y0
        # c2 = xmax   y0
        # c3 = xmax ymax
        # c4 =   x0 ymax
        # cannot just use self.ll_map as xmax, ymax for simulation domain
        # may have been decimated. sim nx 1400 (xmax 1399) with dxts 5 = 1395
        gp_cnrs = np.array(
            [
                [0, 0],
                [self.nx_sim - 1, 0],
                [self.nx_sim - 1, self.ny_sim - 1],
                [0, self.ny_sim - 1],
            ]
        )
        amat = geo.gen_mat(self.mrot, self.mlon, self.mlat)[0]
        ll_cnrs = geo.xy2ll(geo.gp2xy(gp_cnrs, self.nx_sim, self.ny_sim, self.hh), amat)
        if np.min(ll_cnrs[:, 0]) < -90 and np.max(ll_cnrs[:, 0]) > 90:
            # assume crossing over 180 -> -180, extend past 180
            ll_cnrs[ll_cnrs[:, 0] < 0, 0] += 360

        if not gmt_format:
            return ll_cnrs.tolist()

        gmt_cnrs = "\n".join([" ".join(map(str, cnr)) for cnr in ll_cnrs])
        return ll_cnrs.tolist(), gmt_cnrs
Esempio n. 2
0
    def __init__(self, xyts_path, meta_only=False):
        """
        Load metadata and optionally prepare gridpoint datum locations.
        xyts_path: path to the xyts.e3d file
        meta_only: don't prepare gridpoint datum locations (slower)
                can't use timeslice (lon, lat, value) capability
        """

        xytf = open(xyts_path, "rb")

        # determine endianness, an x-y timeslice has 1 z value
        nz = np.fromfile(xytf, dtype=">i4", count=7)[-1]
        if nz == 0x00000001:
            endian = ">"
        elif nz == 0x01000000:
            endian = "<"
        else:
            xytf.close()
            raise ValueError("File is not an XY timeslice file: %s" % (xyts_path))
        xytf.seek(0)

        # read header
        self.x0, self.y0, self.z0, self.t0, self.nx, self.ny, self.nz, self.nt = np.fromfile(
            xytf, dtype="%si4" % (endian), count=8
        )
        self.dx, self.dy, self.hh, dt, self.mrot, self.mlat, self.mlon = np.fromfile(
            xytf, dtype="%sf4" % (endian), count=7
        )
        xytf.close()
        # dt is sensitive to float error eg 0.2 stores as 0.199999 (dangerous)
        self.dt = np.around(dt, decimals=4)

        # determine original sim parameters
        self.dxts = int(round(self.dx / self.hh))
        self.dyts = int(round(self.dy / self.hh))
        self.nx_sim = self.nx * self.dxts
        self.ny_sim = self.ny * self.dyts

        # orientation of components
        self.dip = 0
        self.comps = {
            "X": radians(90 + self.mrot),
            "Y": radians(self.mrot),
            "Z": radians(90 - self.dip),
        }
        # rotation of components so Y is true north
        self.cosR = cos(self.comps["X"])
        self.sinR = sin(self.comps["X"])
        # simulation plane always flat, dip = 0
        self.cosP = 0  # cos(self.comps['Z'])
        self.sinP = 1  # sin(self.comps['Z'])
        # xy dual component rotation matrix
        # must also flip vertical axis
        theta = radians(self.mrot)
        self.rot_matrix = np.array(
            [[cos(theta), -sin(theta), 0], [-sin(theta), -cos(theta), 0], [0, 0, -1]]
        )

        # save speed when only loaded to read metadata section
        if meta_only:
            return

        # memory map for data section
        self.data = np.memmap(
            xyts_path,
            dtype="%sf4" % (endian),
            mode="r",
            offset=60,
            shape=(self.nt, len(self.comps), self.ny, self.nx),
        )

        # create longitude, latitude map for data
        grid_points = (
            np.mgrid[0 : self.nx_sim : self.dxts, 0 : self.ny_sim : self.dyts]
            .reshape(2, -1, order="F")
            .T
        )
        amat = geo.gen_mat(self.mrot, self.mlon, self.mlat)[0]
        ll_map = geo.xy2ll(
            geo.gp2xy(grid_points, self.nx_sim, self.ny_sim, self.hh), amat
        ).reshape(self.ny, self.nx, 2)
        if np.min(ll_map[:, :, 0]) < -90 and np.max(ll_map[:, :, 0]) > 90:
            # assume crossing over 180 -> -180, extend past 180
            ll_map[ll_map[:, :, 0] < 0, 0] += 360
        self.ll_map = ll_map
Esempio n. 3
0
def test_gp2xy(gp, nx, ny, hh, expected):
    assert np.allclose(geo.gp2xy(gp, nx, ny, hh), expected, atol=1e-5)