Exemple #1
0
def test_time_data(fs: float, n_samples: int, first_time: str, time_data: TimeData):
    """Test time data"""
    from resistics.sampling import to_datetime, to_timedelta

    chans = ["Ex", "Ey", "Hx", "Hy"]
    first_rstime = to_datetime(first_time)
    last_rstime = first_rstime + to_timedelta(1 / fs) * (n_samples - 1)

    # check metadata
    assert time_data.metadata.fs == fs
    assert time_data.metadata.chans == chans
    assert time_data.metadata.n_samples == n_samples
    assert time_data.metadata.n_chans == len(chans)
    assert time_data.metadata.first_time == first_rstime
    assert time_data.metadata.last_time == last_rstime
    # check the arrays and chan indexing
    for idx, chan in enumerate(time_data.metadata.chans):
        assert idx == time_data.get_chan_index(chan)
        np.testing.assert_equal(time_data[chan], time_data.data[idx, :])
        np.testing.assert_equal(time_data.get_chan(chan), time_data.data[idx, :])
    # try setting a channel
    time_data["Ex"] = np.ones(shape=(n_samples), dtype=np.float32)
    np.testing.assert_equal(time_data["Ex"], np.ones(shape=(n_samples)))
    # check the timestamps and plotting functions
    timestamps = pd.date_range(
        start=first_time, periods=n_samples, freq=pd.Timedelta(1 / fs, "s")
    )
    pd.testing.assert_index_equal(time_data.get_timestamps(estimate=True), timestamps)
    pd.testing.assert_index_equal(
        time_data.get_timestamps(samples=np.array([1, 5]), estimate=True),
        timestamps[np.array([1, 5])],
    )
    # copy
    time_data_copy = time_data.copy()
    assert time_data_copy.metadata == time_data.metadata
    np.testing.assert_equal(time_data_copy.data, time_data.data)
    # check to make sure getting an unknown chan raises an error
    with pytest.raises(ChannelNotFoundError):
        time_data["unknown"]
    with pytest.raises(ChannelNotFoundError):
        time_data["unknown"] = np.ones(shape=(n_samples), dtype=np.float32)
Exemple #2
0
    def plot(self, max_pts: Optional[int] = 10_000) -> go.Figure:
        """
        Plot the decimated data

        Parameters
        ----------
        max_pts : Optional[int], optional
            The maximum number of points in any individual plot before applying
            lttbc downsampling, by default 10_000. If set to None, no
            downsampling will be applied.

        Returns
        -------
        go.Figure
            Plotly Figure
        """
        from resistics.plot import get_time_fig
        import plotly.express as px

        if len(self.data) == 0:
            logger.error("Data is empty, no decimation levels to plot")

        chans = self.metadata.chans
        y_labels = {x: self.metadata.chans_metadata[x].chan_type for x in chans}
        fig = get_time_fig(chans, y_labels)
        colors = iter(px.colors.qualitative.Plotly)

        for ilevel in range(0, self.metadata.n_levels):
            logger.info(f"Plotting decimation level {ilevel}")
            metadata_dict = self.metadata.levels_metadata[ilevel].dict()
            metadata_dict["chans"] = self.metadata.chans
            metadata_dict["chans_metadata"] = self.metadata.chans_metadata
            time_data = TimeData(TimeMetadata(**metadata_dict), self.data[ilevel])
            legend = f"{ilevel} - {time_data.metadata.fs:.4f} Hz"
            time_data.plot(
                fig=fig, chans=chans, color=next(colors), legend=legend, max_pts=max_pts
            )
        return fig
Exemple #3
0
def time_data_periodic(
    frequencies: List[float],
    fs: float = 50,
    first_time: str = "2020-01-01 00:00:00",
    n_samples: int = 100,
    dtype: Optional[Type] = None,
) -> TimeData:
    """
    Get period TimeData

    Parameters
    ----------
    frequencies : List[float]
        Frequencies to include
    fs : float, optional
        Sampling frequency, by default 50
    first_time : str, optional
        The first time, by default "2020-01-01 00:00:00"
    n_samples : int, optional
        The number of samples, by default 100
    dtype : Optional[Type], optional
        The data type for the values, by default None

    Returns
    -------
    TimeData
        Periodic TimeData
    """
    if dtype is None:
        dtype = DEFAULT_TIME_DATA_DTYPE
    metadata = time_metadata_1chan(fs, first_time, n_samples)
    times = np.arange(0, n_samples) * (1 / fs)
    data = np.zeros(shape=(1, n_samples), dtype=dtype)
    for freq in frequencies:
        data += np.sin(times * 2 * np.pi * freq)
    creator = {
        "name": "time_data_periodic",
        "frequencies": frequencies,
        "fs": fs,
        "first_time": first_time,
        "n_samples": n_samples,
    }
    messages = ["Generated time data with periodic values"]
    record = get_record(creator, messages)
    metadata.history.add_record(record)
    return TimeData(metadata, data)
Exemple #4
0
def time_data_with_offset(
    offset=0.05,
    fs: float = 10,
    first_time: str = "2020-01-01 00:00:00",
    n_samples: int = 11,
    dtype: Optional[Type] = None,
) -> TimeData:
    """
    Get TimeData with an offset on the sampling

    Parameters
    ----------
    offset : float, optional
        The offset on the sampling in seconds, by default 0.05
    fs : float, optional
        The sampling frequency, by default 10
    first_time : str, optional
        The first time of the TimeData, by default "2020-01-01 00:00:00"
    n_samples : int, optional
        The number of samples, by default 11
    dtype : Optional[Type], optional
        The data type for the values, by default None

    Returns
    -------
    TimeData
        The TimeData
    """
    if dtype is None:
        dtype = DEFAULT_TIME_DATA_DTYPE
    first_time = (pd.to_datetime(first_time) +
                  pd.Timedelta(offset, "s")).isoformat()
    metadata = time_metadata_1chan(fs, first_time, n_samples)
    data = np.arange(0, n_samples).reshape(1, n_samples)
    creator = {
        "name": "time_data_with_offset",
        "offset": offset,
        "fs": fs,
        "first_time": first_time,
        "n_samples": n_samples,
    }
    messages = ["Generated time data with an offset"]
    record = get_record(creator, messages)
    metadata.history.add_record(record)
    return TimeData(metadata, data)
Exemple #5
0
def time_data_with_nans(
    fs: float = 10,
    first_time: str = "2020-01-01 00:00:00",
    dtype: Optional[Type] = None,
) -> TimeData:
    """
    TimeData with 16 samples and some nan values

    Parameters
    ----------
    fs : float, optional
        Sampling frequency, by default 10
    first_time : str, optional
        The time of the first sample, by default "2020-01-01 00:00:00"
    dtype : Optional[Type], optional
        The data type for the values, by default None

    Returns
    -------
    TimeData
        The TimeData
    """
    if dtype is None:
        dtype = DEFAULT_TIME_DATA_DTYPE
    data = np.array(
        [
            [1, 1, 1, 0, np.nan, 0, 1, 1, 1, np.nan, 0, 0, 0, 0, 1, 1],
            [1, 2, np.nan, np.nan, 5, 6, np.nan, 8, 9, 1, 2, 3, 4, 5, 6, 7],
            [np.nan, 2, 3, 5, 1, 2, 3, 4, 2, 6, 7, np.nan, np.nan, 4, 3, 2],
            [2, 0, 0, 1, 2, 3, np.nan, np.nan, np.nan, 0, 0, 1, 3, 3, 3, 3],
        ],
        dtype=dtype,
    )
    n_samples = data.shape[1]
    metadata = time_metadata_mt(fs, first_time, n_samples)
    creator = {
        "name": "time_data_with_nans",
        "fs": fs,
        "first_time": first_time
    }
    messages = ["Generated time data with some nan values"]
    record = get_record(creator, messages)
    metadata.history.add_record(record)
    return TimeData(metadata, data)
Exemple #6
0
def time_data_linear(
    fs: float = 10,
    first_time: str = "2020-01-01 00:00:00",
    n_samples: int = 10,
    dtype: Optional[Type] = None,
) -> TimeData:
    """
    Get TimeData with linear data

    Parameters
    ----------
    fs : float, optional
        The sampling frequency, by default 10
    first_time : str, optional
        Time of first sample, by default "2020-01-01 00:00:00"
    n_samples : int, optional
        The number of samples, by default 10
    dtype : Optional[Type], optional
        The data type for the values, by default None

    Returns
    -------
    TimeData
        TimeData with linear values
    """
    if dtype is None:
        dtype = DEFAULT_TIME_DATA_DTYPE
    metadata = time_metadata_mt(fs, first_time, n_samples)
    data = np.empty(shape=(metadata.n_chans, n_samples), dtype=dtype)
    for idx in range(metadata.n_chans):
        data[idx, :] = np.arange(n_samples)
    creator = {
        "name": "time_data_linear",
        "fs": fs,
        "first_time": first_time,
        "n_samples": n_samples,
    }
    messages = ["Generated time data with linear values"]
    record = get_record(creator, messages)
    metadata.history.add_record(record)
    return TimeData(metadata, data)
Exemple #7
0
def time_data_random(
    fs: float = 10,
    first_time: str = "2020-01-01 00:00:00",
    n_samples: int = 10,
    dtype: Optional[Type] = None,
) -> TimeData:
    """
    TimeData with random values and specifiable number of samples

    Parameters
    ----------
    fs : float, optional
        The sampling frequency, by default 10
    first_time : str, optional
        Time of first sample, by default "2020-01-01 00:00:00"
    n_samples : int, optional
        The number of samples, by default 10
    dtype : Optional[Type], optional
        The data type for the values, by default None

    Returns
    -------
    TimeData
        The TimeData
    """
    if dtype is None:
        dtype = DEFAULT_TIME_DATA_DTYPE
    metadata = time_metadata_mt(fs, first_time, n_samples)
    data = np.random.normal(0, 3,
                            size=(metadata.n_chans, n_samples)).astype(dtype)
    creator = {
        "name": "time_data_random",
        "fs": fs,
        "first_time": first_time,
        "n_samples": n_samples,
    }
    messages = ["Generated time data with random values"]
    record = get_record(creator, messages)
    metadata.history.add_record(record)
    return TimeData(metadata, data)
Exemple #8
0
def time_data_ones(
    fs: float = 10,
    first_time: str = "2020-01-01 00:00:00",
    n_samples: int = 10,
    dtype: Optional[Type] = None,
) -> TimeData:
    """
    TimeData with all ones

    Parameters
    ----------
    fs : float, optional
        The sampling frequency, by default 10
    first_time : str, optional
        The time of the first sample, by default "2020-01-01 00:00:00"
    n_samples : int, optional
        The number of samples, by default 10
    dtype : Optional[Type], optional
        The data type for the values, by default None

    Returns
    -------
    TimeData
        The TimeData
    """
    if dtype is None:
        dtype = DEFAULT_TIME_DATA_DTYPE
    metadata = time_metadata_mt(fs, first_time, n_samples)
    data = np.ones(shape=(len(metadata.chans), n_samples), dtype=dtype)
    creator = {
        "name": "time_data_ones",
        "fs": fs,
        "first_time": first_time,
        "n_samples": n_samples,
    }
    messages = ["Generated time data with fixed values"]
    record = get_record(creator, messages)
    metadata.history.add_record(record)
    return TimeData(metadata, data)