def test_cvms4_basic_elevation(self):
        """
        Tests UCVM's query capabilities with CVM-S4 but using elevation. The tests are the same
        as with test_cvms4_basic_depth.

        Returns:
            None
        """
        self._test_start("test for UCVM query by elevation")

        sd_test = [SeismicData(Point(-118, 34, 0, UCVM_ELEVATION))]

        self.assertTrue(
            UCVM.query(sd_test, "cvms4.usgs-noaa.elevation",
                       ["velocity", "elevation"]))

        assert_velocity_properties(
            self, sd_test[0],
            VelocityProperties(2677.1596, 725.390, 2287.7236, None, None,
                               "cvms4", "cvms4", "cvms4", None, None))

        sd_test = [SeismicData(Point(-130, 40, 0, UCVM_ELEVATION))]

        self.assertTrue(
            UCVM.query(sd_test, "cvms4.usgs-noaa.elevation",
                       ["velocity", "elevation"]))

        # This is above sea level so it should be None for everything.
        assert_velocity_properties(
            self, sd_test[0],
            VelocityProperties(None, None, None, None, None, None, None, None,
                               None, None))

        self._test_end()
    def test_cvmh_query_gtl(self):
        """
        Tests the CVM-H query capabilities both with the GTL and without.

        Returns:
            None
        """
        self._test_start("test for CVM-H query using GTL")

        sd_test = [SeismicData(Point(-118, 34, 0))]

        self.assertTrue(UCVM.query(sd_test, "cvmh1510[gtl]"))

        assert_velocity_properties(
            self, sd_test[0],
            VelocityProperties(824.177, 195, 1084.062, None, None, "cvmh1510",
                               "cvmh1510", "cvmh1510", None, None))

        sd_test = [SeismicData(Point(-118, 34, 0))]

        self.assertTrue(UCVM.query(sd_test, "cvmh1510"))

        # No 1D means None for everything.
        assert_velocity_properties(
            self, sd_test[0],
            VelocityProperties(2484.3879, 969.2999, 2088.316, None, None,
                               "cvmh1510", "cvmh1510", "cvmh1510", None, None))

        self._test_end()
    def test_cvmh_query_1d_background(self):
        """
        Tests the CVM-H query capabilities both with the 1D background model and without.

        Returns:
            None
        """
        self._test_start("test for CVM-H query with 1D model")

        sd_test = [SeismicData(Point(-122.0322, 37.3230, 0))]

        self.assertTrue(UCVM.query(sd_test, "cvmh1510[1d]"))

        assert_velocity_properties(
            self, sd_test[0],
            VelocityProperties(5000.0, 2886.7514, 2654.5, None, None,
                               "cvmh1510", "cvmh1510", "cvmh1510", None, None))

        sd_test = [SeismicData(Point(-122.0322, 37.3230, 0))]

        self.assertTrue(UCVM.query(sd_test, "cvmh1510"))

        # No 1D means None for everything.
        assert_velocity_properties(
            self, sd_test[0],
            VelocityProperties(None, None, None, None, None, None, None, None,
                               None, None))

        self._test_end()
Exemple #4
0
    def test_bayarea_basic_elevation(self):
        """
        Tests the Bay Area query capabilities using elevation. This uses the model's DEM, not the
        UCVM DEM.

        Returns:
            None
        """
        self._test_start("test for Bay Area query by elevation")

        sd_test = [SeismicData(Point(-122.0322, 37.3230, 0, UCVM_ELEVATION))]

        self.assertTrue(UCVM.query(sd_test, "bayarea.elevation"))

        assert_velocity_properties(
            self, sd_test[0],
            VelocityProperties(1700.0, 390.0, 1990.0, 44.0, 22.0, "bayarea",
                               "bayarea", "bayarea", "bayarea", "bayarea"))

        sd_test = [SeismicData(Point(-130, 40, 0, UCVM_ELEVATION))]

        self.assertTrue(
            UCVM.query(sd_test, "bayarea.elevation",
                       ["velocity", "elevation"]))

        # This is above sea level so it should be None for everything.
        assert_velocity_properties(
            self, sd_test[0],
            VelocityProperties(None, None, None, None, None, None, None, None,
                               None, None))

        self._test_end()
    def test_cvms4_basic_depth(self):
        """
        Tests UCVM's basic query capabilities with CVM-S4 using depth. This tests that a known
        point within the model returns the correct material properties and also that a known point
        outside of the model returns the SCEC 1D background material properties.

        Returns:
            None
        """
        self._test_start("test for UCVM query by depth")

        sd_test = [SeismicData(Point(-118, 34, 0))]

        self.assertTrue(UCVM.query(sd_test, "cvms4", ["velocity"]))

        assert_velocity_properties(
            self, sd_test[0],
            VelocityProperties(696.491, 213, 1974.976, None, None, "cvms4",
                               "cvms4", "cvms4", None, None))

        sd_test = [SeismicData(Point(-130, 40, 0))]

        self.assertTrue(UCVM.query(sd_test, "cvms4", ["velocity"]))

        assert_velocity_properties(
            self, sd_test[0],
            VelocityProperties(5000, 2886.751, 2654.5, None, None, "cvms4",
                               "cvms4", "cvms4", None, None))

        self._test_end()
Exemple #6
0
    def test_onedimensional_bbp_depth(self) -> None:
        """
        Tests the 1D model for basic depth query.

        Returns:
            Nothing
        """
        self._test_start("1D BBP format test")

        UCVM.query(self.data["depth"], "1d[CyberShake_BBP_LA_Basin]",
                   ["velocity"])

        assert_velocity_properties(
            self, self.data["depth"][0],
            VelocityProperties(
                1700, 450, 2000, 45.0, 22.5,
                "cybershake la basin linearly interpolated with 1km moho (interpolated)",
                "cybershake la basin linearly interpolated with 1km moho (interpolated)",
                "cybershake la basin linearly interpolated with 1km moho (interpolated)",
                "cybershake la basin linearly interpolated with 1km moho (interpolated)",
                "cybershake la basin linearly interpolated with 1km moho (interpolated)"
            ))
        assert_velocity_properties(
            self, self.data["depth"][1],
            VelocityProperties(
                1850, 900, 2100, 90.0, 45,
                "cybershake la basin linearly interpolated with 1km moho (interpolated)",
                "cybershake la basin linearly interpolated with 1km moho (interpolated)",
                "cybershake la basin linearly interpolated with 1km moho (interpolated)",
                "cybershake la basin linearly interpolated with 1km moho (interpolated)",
                "cybershake la basin linearly interpolated with 1km moho (interpolated)"
            ))
        assert_velocity_properties(
            self, self.data["depth"][2],
            VelocityProperties(
                1900, 950, 2100, 95.0, 47.5,
                "cybershake la basin linearly interpolated with 1km moho (interpolated)",
                "cybershake la basin linearly interpolated with 1km moho (interpolated)",
                "cybershake la basin linearly interpolated with 1km moho (interpolated)",
                "cybershake la basin linearly interpolated with 1km moho (interpolated)",
                "cybershake la basin linearly interpolated with 1km moho (interpolated)"
            ))
        assert_velocity_properties(
            self, self.data["depth"][3],
            VelocityProperties(
                7800, 4500, 3200, 450.0, 225.0,
                "cybershake la basin linearly interpolated with 1km moho (interpolated)",
                "cybershake la basin linearly interpolated with 1km moho (interpolated)",
                "cybershake la basin linearly interpolated with 1km moho (interpolated)",
                "cybershake la basin linearly interpolated with 1km moho (interpolated)",
                "cybershake la basin linearly interpolated with 1km moho (interpolated)"
            ))

        self._test_end()
    def test_cvmh_query_by_elevation(self):
        """
        Tests the CVM-H query capabilities using the model's DEM.

        Returns:
            None
        """
        self._test_start("test for CVM-H query using elevation")

        sd_test = [SeismicData(Point(-118, 34, 0, UCVM_ELEVATION))]

        self.assertTrue(UCVM.query(sd_test, "cvmh1510[gt].elevation"))

        assert_velocity_properties(
            self, sd_test[0],
            VelocityProperties(2495.1269, 978.5577, 2091.678, None, None,
                               "cvmh1510", "cvmh1510", "cvmh1510", None, None))

        sd_test = [SeismicData(Point(-118, 34, 0))]

        self.assertTrue(UCVM.query(sd_test, "cvmh1510[gtl]"))

        # Query by depth.
        assert_velocity_properties(
            self, sd_test[0],
            VelocityProperties(824.177, 195, 1084.062, None, None, "cvmh1510",
                               "cvmh1510", "cvmh1510", None, None))

        # Checks to see that the material properties returned at 266.690277 elevation at -118, 34 equal the
        # material properties returned at 0m depth (i.e. that CVM-H is using its own DEM correctly).
        sd_test = [
            SeismicData(Point(-118, 34, 266.690277099609, UCVM_ELEVATION))
        ]

        self.assertTrue(UCVM.query(sd_test, "cvmh1510[gtl].elevation"))

        assert_velocity_properties(
            self, sd_test[0],
            VelocityProperties(824.177, 195, 1084.062, None, None, "cvmh1510",
                               "cvmh1510", "cvmh1510", None, None))

        # Check to see that "air" returns nothing (there's a bug in vx that will return 1000 for density in air).
        sd_test = [SeismicData(Point(-118, 34, 1000, UCVM_ELEVATION))]

        self.assertTrue(UCVM.query(sd_test, "cvmh1510.elevation"))
        assert_velocity_properties(
            self, sd_test[0],
            VelocityProperties(None, None, None, None, None, None, None, None,
                               None, None))

        self._test_end()
 def _set_velocity_properties_none(cls, sd: SeismicData) -> None:
     """
     Helper method to set the SeismicData velocity properties to just be none (i.e. no
     material properties found).
     :param sd: The SeismicData object to set.
     :return: Nothing
     """
     sd.set_velocity_data(
         VelocityProperties(None, None, None, None, None, None, None, None,
                            None, None))
Exemple #9
0
def _mesh_extract_mpi_awp(sd_array: List[SeismicData], information: dict, im: InternalMesh, start_end: tuple) -> bool:
    """
    Extract an AWP mesh using MPI. Internal method.

    Args:

    Returns:
        True, if successful. Raises an error if not successful.
    """
    from mpi4py import MPI

    comm = MPI.COMM_WORLD
    rank = comm.Get_rank()

    file_out = os.path.join(information["out_dir"], information["mesh_name"]) + ".awp"

    im_iter = AWPInternalMeshIterator(im, start_end[0], start_end[1], len(sd_array), sd_array)

    progress = start_end[0]
    sqrt2 = math.sqrt(2)

    fh = MPI.File.Open(MPI.COMM_WORLD, file_out, amode=MPI.MODE_WRONLY | MPI.MODE_CREATE)

    while progress < im_iter.end_point:
        count = next(im_iter)

        UCVM.query(sd_array[0:count], information["cvm_list"], ["velocity"])

        fl_array = []
        for s in sd_array[0:count]:
            if s.velocity_properties is not None and s.velocity_properties.vs is not None and \
               s.velocity_properties.vs < information["minimums"]["vs"]:
                s.set_velocity_data(
                    VelocityProperties(
                        information["minimums"]["vp"], information["minimums"]["vs"],
                        s.velocity_properties.density, s.velocity_properties.qp,
                        s.velocity_properties.qs, s.velocity_properties.vp_source,
                        s.velocity_properties.vs_source, s.velocity_properties.density_source,
                        s.velocity_properties.qp_source, s.velocity_properties.qs_source
                    )
                )

            fl_array.append(s.velocity_properties.vp)
            fl_array.append(s.velocity_properties.vs)
            fl_array.append(s.velocity_properties.density)

            if s.velocity_properties is None or s.velocity_properties.vp is None or \
               s.velocity_properties.vs is None or s.velocity_properties.density is None:
                print("[Node %d] Attention! %.3f, %.3f, %.3f has no material properties." % (
                    rank, s.original_point.x_value, s.original_point.y_value, s.original_point.z_value
                ), flush=True)
            if s.velocity_properties is not None and s.velocity_properties.vp is not None and \
               s.velocity_properties.vs is not None and s.velocity_properties.vp / s.velocity_properties.vs < sqrt2:
                print("[Node %d] Warning: %.3f, %.3f, %.3f has a Vp/Vs ratio of less than sqrt(2)." % (
                    rank, s.original_point.x_value, s.original_point.y_value, s.original_point.z_value
                ), flush=True)
        s = struct.pack('f' * len(fl_array), *fl_array)
        fh.Write_at(progress * 12, s)
        fh.Sync()

        progress += count

        print("[Node %d] %-4.2f" % (rank, ((progress - start_end[0]) / (start_end[1] - start_end[0])) * 100.0) +
              "% complete. Wrote " + humanize.intcomma(count) + " more grid points.", flush=True)

    comm.Barrier()
    fh.Close()

    if rank == 0:
        print("\n[Node " + str(rank) + "] Extraction job fully complete.")

        # print("\n[Node " + str(rank) + "] Expected file size is " + im.get_grid_file_size()["display"] + ". " +
        #       "Actual size is " + humanize.naturalsize(os.path.getsize(os.path.join(file_out)), gnu=False) + ".",
        #       flush=True)

        # if im.get_grid_file_size()["real"] == os.path.getsize(file_out):
        #     print("Generated file size matches the expected file size.")
        # else:
        #     print("ERROR! File sizes DO NOT MATCH!")

    return True
Exemple #10
0
def _mesh_extract_single_rwg(sd_array: List[SeismicData], information: dict, im: InternalMesh) -> bool:
    """
    Takes an InternalMesh object, the mesh information file, and the iterator, and generates, using
    one core only, the mesh in RWG format.

    Args:
        information (dict): The mesh information dictionary (from the XML config file).
        im (InternalMesh): The internal representation of the RWG mesh.

    Returns:
        Nothing
    """
    file_out_vp = information["mesh_name"] + ".rwgvp"
    file_out_vs = information["mesh_name"] + ".rwgvs"
    file_out_dn = information["mesh_name"] + ".rwgdn"

    im_iter = RWGInternalMeshIterator(im, 0, im.total_size, len(sd_array), sd_array)

    progress = 0

    with open(os.path.join(information["out_dir"], file_out_vp), "wb") as fd_vp, \
         open(os.path.join(information["out_dir"], file_out_vs), "wb") as fd_vs, \
         open(os.path.join(information["out_dir"], file_out_dn), "wb") as fd_dn:
        while progress < im_iter.end_point:
            count = next(im_iter)
            progress += count

            UCVM.query(sd_array[0:count], information["cvm_list"], ["velocity"], None)

            vp_array = []
            vs_array = []
            dn_array = []
            for s in sd_array[0:count]:
                if s.velocity_properties is not None and s.velocity_properties.vs is not None and \
                   s.velocity_properties.vs < information["minimums"]["vs"]:
                    s.set_velocity_data(
                        VelocityProperties(
                            information["minimums"]["vp"], information["minimums"]["vs"],
                            s.velocity_properties.density, s.velocity_properties.qp,
                            s.velocity_properties.qs, s.velocity_properties.vp_source,
                            s.velocity_properties.vs_source, s.velocity_properties.density_source,
                            s.velocity_properties.qp_source, s.velocity_properties.qs_source
                        )
                    )

                vp_array.append(s.velocity_properties.vp / 1000)
                vs_array.append(s.velocity_properties.vs / 1000)
                dn_array.append(s.velocity_properties.density / 1000)

                if s.velocity_properties.vp is None:
                    print("Attention! %.3f, %.3f, %.3f has no material properties." % (
                        s.original_point.x_value, s.original_point.y_value, s.original_point.z_value
                    ))
                if s.velocity_properties is not None and s.velocity_properties.vp is not None and \
                   s.velocity_properties.vs is not None and s.velocity_properties.vp / s.velocity_properties.vs < 1.45:
                    print("Warning: %.3f, %.3f, %.3f has a Vp/Vs ratio of less than 1.45." % (
                        s.original_point.x_value, s.original_point.y_value, s.original_point.z_value
                    ))
            s = struct.pack('f' * len(vp_array), *vp_array)
            fd_vp.write(s)
            s = struct.pack('f' * len(vs_array), *vs_array)
            fd_vs.write(s)
            s = struct.pack('f' * len(dn_array), *dn_array)
            fd_dn.write(s)

            print("%-4.2f" % ((progress / im_iter.end_point) * 100.0) +
                  "% complete. Wrote " + humanize.intcomma(count) + " more grid points.")

        print("\nExpected file size is " + im.get_grid_file_size()["display"] + ". " +
              "Actual size is " + humanize.naturalsize(os.path.getsize(
              os.path.join(information["out_dir"], file_out_vp)), gnu=False) + ".")

        if im.get_grid_file_size()["real"] == \
           os.path.getsize(os.path.join(information["out_dir"], file_out_vp)) and \
           im.get_grid_file_size()["real"] == \
           os.path.getsize(os.path.join(information["out_dir"], file_out_vs)) and \
           im.get_grid_file_size()["real"] == \
           os.path.getsize(os.path.join(information["out_dir"], file_out_dn)):
            print("Generated file size matches the expected file size.")
        else:
            print("ERROR! File sizes DO NOT MATCH!")

    return True
Exemple #11
0
def _mesh_extract_single_awp(sd_array: List[SeismicData], information: dict, im: InternalMesh, slices: str=None,
                             interval: str=None) -> bool:
    """
    Takes an InternalMesh object, the mesh information file, and the iterator, and generates, using
    one core only, the mesh in AWP-ODC format.

    Args:
        information (dict): The mesh information dictionary (from the XML config file).
        im (InternalMesh): The internal representation of the AWP mesh.
        im_iter (AWPInternalMeshIterator): The internal mesh iterator that was generated from im.

    Returns:
        Nothing
    """
    file_out = information["mesh_name"] + ".awp"

    start_point = 0
    end_point = im.total_size

    if slices is not None:
        if "-" in slices:
            parts = slices.split("-")
            start_point = (int(parts[0]) - 1) * im.slice_size
            end_point = (int(parts[1])) * im.slice_size
        else:
            start_point = (int(slices) - 1) * im.slice_size
            end_point = int(slices) * im.slice_size
    elif interval is not None:
        if "-" in interval:
            parts = interval.split("-")
            start_point = (int(parts[0]) / 100) * im.full_size
            end_point = (int(parts[1]) / 100) * im.full_size
        else:
            raise ValueError("Interval must be a range (e.g. 0-10 which means generate the first 10% of the mesh).")

    im_iter = AWPInternalMeshIterator(im, start_point, end_point, len(sd_array), sd_array)
    progress = start_point

    progress = 0
    sqrt2 = math.sqrt(2)

    with open(os.path.join(information["out_dir"], file_out), "ab+") as fd:
        while progress < im.total_size:
            count = next(im_iter)

            UCVM.query(sd_array[0:count], information["cvm_list"], ["velocity"])

            fl_array = []
            for s in sd_array[0:count]:
                if s.velocity_properties is not None and s.velocity_properties.vs is not None and \
                   s.velocity_properties.vs < information["minimums"]["vs"]:
                    s.set_velocity_data(
                        VelocityProperties(
                            information["minimums"]["vp"], information["minimums"]["vs"],
                            s.velocity_properties.density, s.velocity_properties.qp,
                            s.velocity_properties.qs, s.velocity_properties.vp_source,
                            s.velocity_properties.vs_source, s.velocity_properties.density_source,
                            s.velocity_properties.qp_source, s.velocity_properties.qs_source
                        )
                    )

                fl_array.append(s.velocity_properties.vp)
                fl_array.append(s.velocity_properties.vs)
                fl_array.append(s.velocity_properties.density)

                if s.velocity_properties is None or s.velocity_properties.vp is None or \
                   s.velocity_properties.vs is None or s.velocity_properties.density is None:
                    print("Attention! %.3f, %.3f, %.3f has no material properties." % (
                        s.original_point.x_value, s.original_point.y_value, s.original_point.z_value
                    ))
                if s.velocity_properties is not None and s.velocity_properties.vp is not None and \
                   s.velocity_properties.vs is not None and s.velocity_properties.vp / s.velocity_properties.vs < sqrt2:
                    print("Warning: %.3f, %.3f, %.3f has a Vp/Vs ratio of less than sqrt(2)." % (
                        s.original_point.x_value, s.original_point.y_value, s.original_point.z_value
                    ))
            s = struct.pack('f' * len(fl_array), *fl_array)
            fd.seek(progress * 12)
            fd.write(s)

            progress += count

            print("%-4.2f" % ((progress / (im_iter.end_point - start_point)) * 100.0) +
                  "% complete. Wrote " + humanize.intcomma(count) + " more grid points.")

        print("\nExpected file size is " + im.get_grid_file_size()["display"] + ". " +
              "Actual size is " + humanize.naturalsize(os.path.getsize(
              os.path.join(information["out_dir"], file_out)), gnu=False) + ".")

        if im.get_grid_file_size()["real"] == \
           os.path.getsize(os.path.join(information["out_dir"], file_out)):
            print("Generated file size matches the expected file size.")
        else:
            print("ERROR! File sizes DO NOT MATCH!")

    return True
Exemple #12
0
    def _query(self, data: List[SeismicData], **kwargs) -> bool:
        """
        This is the method that all models override. It handles retrieving the queried models'
        properties and adjusting the SeismicData structures as need be.

        Args:
            points (:obj:`list` of :obj:`SeismicData`): List of SeismicData objects containing the
                points queried. These are to be adjusted if needed.

        Returns:
            True on success, false if there is an error.
        """
        ely_coefficients = {"a": 1 / 2, "b": 2 / 3, "c": 3 / 2}

        depth = 350
        zmin = 0

        for datum in data:
            if datum.velocity_properties is None or \
               datum.velocity_properties.vs is None or datum.velocity_properties.vs == 0 or \
               datum.velocity_properties.vp is None or datum.velocity_properties.vp == 0 or \
               datum.velocity_properties.density is None or datum.velocity_properties.density == 0 or \
               datum.vs30_properties is None or datum.vs30_properties.vs30 == 0 or datum.vs30_properties.vs30 is None:
                continue

            if datum.converted_point.z_value < zmin:
                new_vs = ely_coefficients["a"] * datum.vs30_properties.vs30
                new_vp = ely_coefficients["a"] * calculate_scaled_vp(new_vs)
                new_dn = calculate_nafe_drake_density(new_vp)

                datum.set_velocity_data(
                    VelocityProperties(new_vp, new_vs, new_dn,
                                       datum.velocity_properties.qp,
                                       datum.velocity_properties.qs,
                                       new_sources["vp"], new_sources["vs"],
                                       new_sources["dn"],
                                       datum.velocity_properties.qp_source,
                                       datum.velocity_properties.qs_source))
            elif datum.converted_point.z_value < depth:
                datum_ely = [
                    SeismicData(
                        Point(datum.converted_point.x_value,
                              datum.converted_point.y_value, depth, UCVM_DEPTH,
                              datum.converted_point.projection))
                ]
                UCVM.query(
                    datum_ely,
                    datum.model_string.replace(".elevation",
                                               "").replace(".elygtl", ""),
                    ["velocity"])

                new_vs = datum_ely[0].velocity_properties.vs
                new_vp = datum_ely[0].velocity_properties.vp
                new_dn = datum_ely[0].velocity_properties.density
                new_sources = {
                    "vp": datum_ely[0].velocity_properties.vp_source,
                    "vs": datum_ely[0].velocity_properties.vs_source,
                    "dn": datum_ely[0].velocity_properties.density_source
                }

                z = (datum.converted_point.z_value - zmin) / (depth - zmin)
                f = z - math.pow(z, 2.0)
                g = math.pow(z, 2.0) + 2 * math.pow(z, 0.5) - (3 * z)
                new_vs = (z + ely_coefficients["b"] * f) * new_vs + \
                         (ely_coefficients["a"] - ely_coefficients["a"] * z +
                          ely_coefficients["c"] * g) * datum.vs30_properties.vs30
                new_vp = (z + ely_coefficients["b"] * f) * new_vp + \
                         (ely_coefficients["a"] - ely_coefficients["a"] * z +
                          ely_coefficients["c"] * g) * \
                         calculate_scaled_vp(datum.vs30_properties.vs30)
                new_dn = calculate_nafe_drake_density(new_vp)

                for key, item in new_sources.items():
                    new_sources[key] = \
                        ", ".join([x.strip() for x in new_sources[key].split(",")]) + ", Ely GTL"

                datum.set_velocity_data(
                    VelocityProperties(new_vp, new_vs, new_dn,
                                       datum.velocity_properties.qp,
                                       datum.velocity_properties.qs,
                                       new_sources["vp"], new_sources["vs"],
                                       new_sources["dn"],
                                       datum.velocity_properties.qp_source,
                                       datum.velocity_properties.qs_source))

        return True
Exemple #13
0
    def _interpolate_properties(cls, data: List[SeismicData], x_percent: float,
                                y_percent: float,
                                z_percent: float) -> VelocityProperties:
        """
        Interpolates the points and sets the new material properties.

        Args:
            data (:obj:`list` of :obj:`SeismicData`): List of SeismicData objects for interpolation.
            x_percent (float): The x percentage to interpolate.
            y_percent (float): The y percentage to interpolate.
            z_percent (float): The z percentage to interpolate.

        Returns:
            The interpolated material properties.
        """
        props = ["vp", "vs", "density", "qp", "qs"]
        vel_return = VelocityProperties(vp=None,
                                        vp_source=None,
                                        vs=None,
                                        vs_source=None,
                                        density=None,
                                        density_source=None,
                                        qp=None,
                                        qs=None)
        for matprop in props:
            if len(data) == 4:
                if getattr(data[0].velocity_properties, matprop) is not None and \
                   getattr(data[1].velocity_properties, matprop) is not None and \
                   getattr(data[2].velocity_properties, matprop) is not None and \
                   getattr(data[3].velocity_properties, matprop) is not None:
                    setattr(
                        vel_return, matprop,
                        UCVMCCommon.bilinear_interpolate(
                            getattr(data[0].velocity_properties, matprop),
                            getattr(data[2].velocity_properties, matprop),
                            getattr(data[1].velocity_properties, matprop),
                            getattr(data[3].velocity_properties, matprop),
                            x_percent, y_percent))
                    setattr(vel_return, matprop + "_source", "interpolated")
            elif len(data) == 8:
                if getattr(data[0].velocity_properties, matprop) is not None and \
                   getattr(data[1].velocity_properties, matprop) is not None and \
                   getattr(data[2].velocity_properties, matprop) is not None and \
                   getattr(data[3].velocity_properties, matprop) is not None and \
                   getattr(data[4].velocity_properties, matprop) is not None and \
                   getattr(data[5].velocity_properties, matprop) is not None and \
                   getattr(data[6].velocity_properties, matprop) is not None and \
                   getattr(data[7].velocity_properties, matprop) is not None:
                    setattr(
                        vel_return, matprop,
                        UCVMCCommon.trilinear_interpolate(
                            getattr(data[0].velocity_properties, matprop),
                            getattr(data[2].velocity_properties, matprop),
                            getattr(data[1].velocity_properties, matprop),
                            getattr(data[3].velocity_properties, matprop),
                            getattr(data[4].velocity_properties, matprop),
                            getattr(data[5].velocity_properties, matprop),
                            getattr(data[6].velocity_properties, matprop),
                            getattr(data[7].velocity_properties, matprop),
                            x_percent, y_percent, z_percent))
                    setattr(vel_return, matprop + "_source", "interpolated")
    def _query(self, points: List[SeismicData], **kwargs) -> bool:
        """
        This is the method that all models override. It handles querying the velocity model
        and filling in the SeismicData structures.

        Args:
            points (:obj:`list` of :obj:`SeismicData`): List of SeismicData objects containing the
                points in depth. These are to be populated with :obj:`VelocityProperties`:

        Returns:
            True on success, false if there is an error.
        """
        temp_proj = {}

        for sd_object in points:
            if sd_object.original_point.projection == UCVM_DEFAULT_PROJECTION:
                x_value, y_value = pyproj.transform(self.in_proj, self.out_proj, sd_object.original_point.x_value,
                                                    sd_object.original_point.y_value)
            else:
                if len(temp_proj) == 0 or temp_proj["string"] != sd_object.original_point.projection:
                    temp_proj["object"] = pyproj.Proj(sd_object.original_point.projection)
                    temp_proj["string"] = sd_object.original_point.projection
                x_value, y_value = pyproj.transform(temp_proj, self.out_proj, sd_object.original_point.x_value,
                                                    sd_object.original_point.y_value)

            temp_utm_e = x_value - self.model_properties["origin"]["e"]
            temp_utm_n = y_value - self.model_properties["origin"]["n"]

            new_point_utm_n = self.model_properties["angles"]["sin"] * temp_utm_e + \
                self.model_properties["angles"]["cos"] * temp_utm_n
            new_point_utm_e = self.model_properties["angles"]["cos"] * temp_utm_e - \
                self.model_properties["angles"]["sin"] * temp_utm_n

            coords, percentages = UCVMCCommon.calculate_grid_point(
                self.model_properties["dimensions"]["width"],
                self.model_properties["dimensions"]["height"],
                self.config_dict["dimensions"]["depth"],
                new_point_utm_e,
                new_point_utm_n,
                sd_object.converted_point.z_value,
                self.config_dict["dimensions"]["x"],
                self.config_dict["dimensions"]["y"],
                self.config_dict["dimensions"]["z_interval"]
            )

            # Check to see if we are outside of the model boundaries.
            if coords["x"] < 0 or coords["y"] < 0 or \
               (coords["z"] > 98 and not (coords["z"] == 99 and percentages["z"] == 0)) or \
               coords["x"] > self.config_dict["dimensions"]["x"] - 2 or \
               coords["y"] > self.config_dict["dimensions"]["y"] - 2 or \
               coords["z"] < 0:
                self._set_velocity_properties_none(sd_object)
                continue

            v = {"vp": None, "vp_source": None, "vs": None, "vs_source": None,
                 "density": None, "density_source": None, "qp": None, "qp_source": None,
                 "qs": None, "qs_source": None}

            if coords["z"] == 99 and percentages["z"] == 0:
                for prop_given in self.model_has:
                    # Interpolate
                    v[prop_given] = UCVMCCommon.bilinear_interpolate(
                        self.mesh[prop_given][coords["z"]][coords["y"]][coords["x"]],
                        self.mesh[prop_given][coords["z"]][coords["y"]][coords["x"] + 1],
                        self.mesh[prop_given][coords["z"]][coords["y"] + 1][coords["x"]],
                        self.mesh[prop_given][coords["z"]][coords["y"] + 1][coords["x"] + 1],
                        percentages["x"], percentages["y"]
                    )
                    v[str(prop_given) + "_source"] = self.get_metadata()["id"]

                if v["density"] is None and v["vp"] is not None:
                    v["density"] = calculate_nafe_drake_density(float(v["vp"]))

                sd_object.set_velocity_data(VelocityProperties(
                    vp=v["vp"], vp_source=v["vp_source"], vs=v["vs"], vs_source=v["vs_source"],
                    density=v["density"], density_source=v["density_source"], qp=v["qp"],
                    qp_source=v["qp_source"], qs=v["qs"], qs_source=v["qs_source"]
                ))
                continue

            for prop_given in self.model_has:
                # Interpolate
                v[prop_given] = UCVMCCommon.trilinear_interpolate(
                    self.mesh[prop_given][coords["z"]][coords["y"]][coords["x"]],
                    self.mesh[prop_given][coords["z"]][coords["y"]][coords["x"] + 1],
                    self.mesh[prop_given][coords["z"]][coords["y"] + 1][coords["x"]],
                    self.mesh[prop_given][coords["z"]][coords["y"] + 1][coords["x"] + 1],
                    self.mesh[prop_given][coords["z"] + 1][coords["y"]][coords["x"]],
                    self.mesh[prop_given][coords["z"] + 1][coords["y"]][coords["x"] + 1],
                    self.mesh[prop_given][coords["z"] + 1][coords["y"] + 1][coords["x"]],
                    self.mesh[prop_given][coords["z"] + 1][coords["y"] + 1][coords["x"] + 1],
                    percentages["x"], percentages["y"], percentages["z"]
                )
                v[str(prop_given) + "_source"] = self.get_metadata()["id"]

            if v["density"] is None and v["vp"] is not None:
                v["density"] = calculate_nafe_drake_density(float(v["vp"]))

            sd_object.set_velocity_data(VelocityProperties(
                vp=v["vp"], vp_source=v["vp_source"], vs=v["vs"], vs_source=v["vs_source"],
                density=v["density"], density_source=v["density_source"], qp=v["qp"],
                qp_source=v["qp_source"], qs=v["qs"], qs_source=v["qs_source"]
            ))

        return True