Exemplo n.º 1
0
def rotate_data(NSEMdata, rot_angle):
    """
    Function that rotates clockwise by rotation angle
        (- negative for a counter-clockwise rotation)

    :param SimPEG.electromagnetics.natural_source.Data NSEMdata: NSEM data object to process
    :param float rot_angle: Rotation angel in degrees, positive for clockwise rotation
    """
    recData = NSEMdata.toRecArray("Complex")
    impData = rec_to_ndarr(recData[["zxx", "zxy", "zyx", "zyy"]].copy(), complex)
    # Make the rotation matrix
    # c,s,zxx,zxy,zyx,zyy = sympy.symbols('c,s,zxx,zxy,zyx,zyy')
    # rotM = sympy.Matrix([[c,-s],[s, c]])
    # zM = sympy.Matrix([[zxx,zxy],[zyx,zyy]])
    # rotM*zM*rotM.T
    # [c*(c*zxx - s*zyx) - s*(c*zxy - s*zyy), c*(c*zxy - s*zyy) + s*(c*zxx - s*zyx)],
    # [c*(c*zyx + s*zxx) - s*(c*zyy + s*zxy), c*(c*zyy + s*zxy) + s*(c*zyx + s*zxx)]])
    s = np.sin(-np.deg2rad(rot_angle))
    c = np.cos(-np.deg2rad(rot_angle))
    rotMat = np.array([[c, -s], [s, c]])
    rotData = (
        (rotMat.dot(impData.reshape(-1, 2, 2).dot(rotMat.T)))
        .transpose(1, 0, 2)
        .reshape(-1, 4)
    )
    outRec = recData.copy()
    for nr, comp in enumerate(["zxx", "zxy", "zyx", "zyy"]):
        outRec[comp] = rotData[:, nr]

    return Data.fromRecArray(outRec)
Exemplo n.º 2
0
    def test_from_rec_array(self):
        """test for class instantiation from a record array"""

        data_obj = Data.fromRecArray(recArray=self.rec_array)
        assert data_obj.survey.frequencies == self.freqs
        assert len(data_obj.survey.source_list) == 2
        for src in data_obj.survey.source_list:
            assert len(
                src.receiver_list) == 2  # one real, one imaginary component
            for rx in src.receiver_list:
                np.testing.assert_almost_equal(rx.locations, [self.loc])
        np.testing.assert_almost_equal(data_obj.dobs,
                                       np.array([0.5, 0.0, 0.5, 1.0]))
Exemplo n.º 3
0
def resample_data(NSEMdata, locs="All", freqs="All", rxs="All", verbose=False):
    """
    Function that selects locations from all the receivers in the survey
    (uses the numerator location as a reference). Also gives the option
    of selecting frequencies and receiver.

    :param SimPEG.electromagnetics.natural_source.Data NSEMdata: NSEM data object to process

    :param locs: receiver locations to use (default is 'All' locations)
    :type locs: numpy.ndarray, optional
    :param freqs: frequencies to use (default is 'All' frequencies))
    :type freqs: numpy.ndarray, optional
    :param rxs: list of receiver sting types to use (default is 'All' types).
        Can be any componation of ['zxx','zxy','zyx','zyy','tzx','tzy']
    :type rxs: str, optional

    """

    # Initiate new objects
    new_srcList = []
    data_list = []
    std_list = []
    floor_list = []

    # Sort out input frequencies
    if locs == "All":
        locations = NSEMdata._unique_locations()
    elif isinstance(locs, np.ndarray):
        locations = locs
    else:
        raise IOError("Incorrect input type for locs. \n" + "Can be 'All' or ndarray ")
    # Sort out input frequencies
    if freqs == "All":
        frequencies = NSEMdata.survey.freqs
    elif isinstance(freqs, np.ndarray):
        frequencies = freqs
    elif isinstance(freqs, list):
        frequencies = np.array(freqs)
    else:
        raise IOError(
            "Incorrect input type for freqs. \n" + "Can be 'All'; ndarray or a list"
        )
    # Sort out input rxs
    if rxs == "All":
        rx_comp = True
    elif isinstance(rxs, list):
        rx_comp = []
        for rxT in rxs:
            if "z" in rxT[0]:
                rxtype = Point3DImpedance
            elif "t" in rxT[0]:
                rxtype = Point3DTipper
            else:
                raise IOError("Unknown rx type string")
            orient = rxT[1:3]
            rx_comp.append((rxtype, orient))

    else:
        raise IOError("Incorrect input type for rxs. \n" + "Can be 'All' or a list")

    # Filter the data
    for src in NSEMdata.survey.source_list:
        if src.freq in frequencies:
            new_rxList = []
            for rx in src.receiver_list:
                if rx_comp is True or np.any(
                    [
                        (isinstance(rx, ct) and rx.orientation in co)
                        for (ct, co) in rx_comp
                    ]
                ):
                    if len(rx.locations.shape) == 3:
                        ind_loc = np.sum(
                            np.concatenate(
                                [
                                    (
                                        np.sqrt(
                                            np.sum(
                                                (rx.locations[:, :, 0] - location) ** 2,
                                                axis=1,
                                            )
                                        )
                                        < 0.1
                                    ).reshape(-1, 1)
                                    for location in locations
                                ],
                                axis=1,
                            ),
                            axis=1,
                            dtype=bool,
                        )
                        new_locs = rx.locations[ind_loc, :, :]
                    else:
                        ind_loc = np.sum(
                            np.concatenate(
                                [
                                    (
                                        np.sqrt(
                                            np.sum(
                                                (rx.locations[:, :] - location) ** 2,
                                                axis=1,
                                            )
                                        )
                                        < 0.1
                                    ).reshape(-1, 1)
                                    for location in locations
                                ],
                                axis=1,
                            ),
                            axis=1,
                            dtype=bool,
                        )
                        new_locs = rx.locations[ind_loc, :]
                    new_rx = type(rx)
                    new_rxList.append(new_rx(new_locs, rx.orientation, rx.component))
                    data_list.append(NSEMdata[src, rx][ind_loc])
                    try:
                        std_list.append(NSEMdata.relative_error[src, rx][ind_loc])
                        floor_list.append(NSEMdata.floor[src, rx][ind_loc])
                    except Exception as e:
                        if verbose:
                            print("No standard deviation or floor assigned")

            new_src = type(src)
            new_srcList.append(new_src(new_rxList, src.freq))

    survey = Survey(new_srcList)
    if std_list or floor_list:
        return Data(
            survey,
            np.concatenate(data_list),
            np.concatenate(std_list),
            np.concatenate(floor_list),
        )
    else:
        return Data(survey, np.concatenate(data_list))
Exemplo n.º 4
0
def convert3Dto1Dobject(NSEMdata, rxType3D="yx"):
    """
    Function that converts a 3D NSEMdata of a list of
    1D NSEMdata objects for running 1D inversions for.

    :param SimPEG.electromagnetics.natural_source.Data NSEMdata: NSEM data object to process

    :param rxType3D: component of the NSEMdata to use.
        Can be 'xy', 'yx' or 'det'
    :type rxType3D: str, optional

    """

    # Find the unique locations
    # Need to find the locations
    recDataTemp = NSEMdata.toRecArray().data.flatten()
    # Check if survey.std has been assigned.
    ## NEED TO: write this...
    # Calculte and add the DET of the tensor to the recArray
    if "det" in rxType3D:
        Zon = (recDataTemp["zxxr"] + 1j * recDataTemp["zxxi"]) * (
            recDataTemp["zyyr"] + 1j * recDataTemp["zyyi"]
        )
        Zoff = (recDataTemp["zxyr"] + 1j * recDataTemp["zxyi"]) * (
            recDataTemp["zyxr"] + 1j * recDataTemp["zyxi"]
        )
        det = np.sqrt(Zon - Zoff)
        recData = recFunc.append_fields(
            recDataTemp, ["zdetr", "zdeti"], [det.real, det.imag]
        )
    else:
        recData = recDataTemp

    uniLocs = rec_to_ndarr(np.unique(recData[["x", "y", "z"]].copy()))
    mtData1DList = []
    if "xy" in rxType3D:
        corr = -1
        # Shift the data to comply with the quadtrature of the 1d problem
    else:
        corr = 1
    for loc in uniLocs:
        # Make the receiver list
        rx1DList = []
        rx1DList.append(Point1DImpedance(simpeg.mkvc(loc, 2).T, "real"))
        rx1DList.append(Point1DImpedance(simpeg.mkvc(loc, 2).T, "imag"))
        # Source list
        locrecData = recData[
            np.sqrt(
                np.sum(
                    (rec_to_ndarr(recData[["x", "y", "z"]].copy()) - loc) ** 2, axis=1
                )
            )
            < 1e-5
        ]
        dat1DList = []
        src1DList = []
        for freq in locrecData["freq"]:
            src1DList.append(Planewave_xy_1Dprimary(rx1DList, freq))
            for comp in ["r", "i"]:
                dat1DList.append(
                    corr * locrecData[rxType3D + comp][locrecData["freq"] == freq]
                )

        # Make the survey
        sur1D = Survey(src1DList)

        # Make the data
        dataVec = np.hstack(dat1DList)
        dat1D = Data(sur1D, dataVec)
        sur1D.dobs = dataVec
        # Need to take NSEMdata.survey.std and split it as well.
        std = 0.05
        sur1D.std = np.abs(sur1D.dobs * std)
        mtData1DList.append(dat1D)

    # Return the the list of data.
    return mtData1DList