resistics.time module¶
Classes and methods for storing and manipulating time data, including:
The TimeMetadata model for defining metadata for TimeData
The TimeData class for storing TimeData
Implementations of time data readers for numpy and ascii formatted TimeData
TimeData processors
- pydantic model resistics.time.ChanMetadata[source]¶
Bases:
resistics.common.Metadata
Channel metadata
Show JSON schema
{ "title": "ChanMetadata", "description": "Channel metadata", "type": "object", "properties": { "name": { "title": "Name", "type": "string" }, "data_files": { "title": "Data Files", "type": "array", "items": { "type": "string" } }, "chan_type": { "title": "Chan Type", "type": "string" }, "chan_source": { "title": "Chan Source", "type": "string" }, "sensor": { "title": "Sensor", "default": "", "type": "string" }, "serial": { "title": "Serial", "default": "", "type": "string" }, "gain1": { "title": "Gain1", "default": 1, "type": "number" }, "gain2": { "title": "Gain2", "default": 1, "type": "number" }, "scaling": { "title": "Scaling", "default": 1, "type": "number" }, "chopper": { "title": "Chopper", "default": false, "type": "boolean" }, "dipole_dist": { "title": "Dipole Dist", "default": 1, "type": "number" }, "sensor_calibration_file": { "title": "Sensor Calibration File", "default": "", "type": "string" }, "instrument_calibration_file": { "title": "Instrument Calibration File", "default": "", "type": "string" } }, "required": [ "name" ] }
- field name: str [Required]¶
The name of the channel
- field data_files: Optional[List[str]] = None¶
The data files
- Validated by
validate_data_files
- field chan_type: Optional[str] = None¶
The channel type, electric, magnetic or unknown
- Validated by
validate_chan_type
- field chan_source: Optional[str] = None¶
The name of channel in the data source, can be ignored if not required
- field sensor: str = ''¶
The name of the sensor
- field serial: str = ''¶
The serial number of the sensor
- field gain1: float = 1¶
Primary channel gain
- field gain2: float = 1¶
Secondary channel gain
- field scaling: float = 1¶
Scaling to apply to the data. May include the gains and other scaling
- field chopper: bool = False¶
Boolean flag for chopper on
- field dipole_dist: float = 1¶
Dipole spacing for the channel
- field sensor_calibration_file: str = ''¶
Explicit name of sensor calibration file
- field instrument_calibration_file: str = ''¶
Explicit name of instrument calibration file
- pydantic model resistics.time.TimeMetadata[source]¶
Bases:
resistics.common.WriteableMetadata
Time metadata
Show JSON schema
{ "title": "TimeMetadata", "description": "Time metadata", "type": "object", "properties": { "file_info": { "$ref": "#/definitions/ResisticsFile" }, "fs": { "title": "Fs", "type": "number" }, "chans": { "title": "Chans", "type": "array", "items": { "type": "string" } }, "n_chans": { "title": "N Chans", "type": "integer" }, "n_samples": { "title": "N Samples", "type": "integer" }, "first_time": { "title": "First Time", "pattern": "%Y-%m-%d %H:%M:%S.%f_%o_%q_%v", "examples": [ "2021-01-01 00:00:00.000061_035156_250000_000000" ] }, "last_time": { "title": "Last Time", "pattern": "%Y-%m-%d %H:%M:%S.%f_%o_%q_%v", "examples": [ "2021-01-01 00:00:00.000061_035156_250000_000000" ] }, "system": { "title": "System", "default": "", "type": "string" }, "serial": { "title": "Serial", "default": "", "type": "string" }, "wgs84_latitude": { "title": "Wgs84 Latitude", "default": -999.0, "type": "number" }, "wgs84_longitude": { "title": "Wgs84 Longitude", "default": -999.0, "type": "number" }, "easting": { "title": "Easting", "default": -999.0, "type": "number" }, "northing": { "title": "Northing", "default": -999.0, "type": "number" }, "elevation": { "title": "Elevation", "default": -999.0, "type": "number" }, "chans_metadata": { "title": "Chans Metadata", "type": "object", "additionalProperties": { "$ref": "#/definitions/ChanMetadata" } }, "history": { "title": "History", "default": { "records": [] }, "allOf": [ { "$ref": "#/definitions/History" } ] } }, "required": [ "fs", "chans", "n_samples", "first_time", "last_time", "chans_metadata" ], "definitions": { "ResisticsFile": { "title": "ResisticsFile", "description": "Required information for writing out a resistics file", "type": "object", "properties": { "created_on_local": { "title": "Created On Local", "type": "string", "format": "date-time" }, "created_on_utc": { "title": "Created On Utc", "type": "string", "format": "date-time" }, "version": { "title": "Version", "type": "string" } } }, "ChanMetadata": { "title": "ChanMetadata", "description": "Channel metadata", "type": "object", "properties": { "name": { "title": "Name", "type": "string" }, "data_files": { "title": "Data Files", "type": "array", "items": { "type": "string" } }, "chan_type": { "title": "Chan Type", "type": "string" }, "chan_source": { "title": "Chan Source", "type": "string" }, "sensor": { "title": "Sensor", "default": "", "type": "string" }, "serial": { "title": "Serial", "default": "", "type": "string" }, "gain1": { "title": "Gain1", "default": 1, "type": "number" }, "gain2": { "title": "Gain2", "default": 1, "type": "number" }, "scaling": { "title": "Scaling", "default": 1, "type": "number" }, "chopper": { "title": "Chopper", "default": false, "type": "boolean" }, "dipole_dist": { "title": "Dipole Dist", "default": 1, "type": "number" }, "sensor_calibration_file": { "title": "Sensor Calibration File", "default": "", "type": "string" }, "instrument_calibration_file": { "title": "Instrument Calibration File", "default": "", "type": "string" } }, "required": [ "name" ] }, "Record": { "title": "Record", "description": "Class to hold a record\n\nA record holds information about a process that was run. It is intended to\ntrack processes applied to data, allowing a process history to be saved\nalong with any datasets.\n\nExamples\n--------\nA simple example of creating a process record\n\n>>> from resistics.common import Record\n>>> messages = [\"message 1\", \"message 2\"]\n>>> record = Record(\n... creator={\"name\": \"example\", \"parameter1\": 15},\n... messages=messages,\n... record_type=\"example\"\n... )\n>>> record.summary()\n{\n 'time_local': '...',\n 'time_utc': '...',\n 'creator': {'name': 'example', 'parameter1': 15},\n 'messages': ['message 1', 'message 2'],\n 'record_type': 'example'\n}", "type": "object", "properties": { "time_local": { "title": "Time Local", "type": "string", "format": "date-time" }, "time_utc": { "title": "Time Utc", "type": "string", "format": "date-time" }, "creator": { "title": "Creator", "type": "object" }, "messages": { "title": "Messages", "type": "array", "items": { "type": "string" } }, "record_type": { "title": "Record Type", "type": "string" } }, "required": [ "creator", "messages", "record_type" ] }, "History": { "title": "History", "description": "Class for storing processing history\n\nParameters\n----------\nrecords : List[Record], optional\n List of records, by default []\n\nExamples\n--------\n>>> from resistics.testing import record_example1, record_example2\n>>> from resistics.common import History\n>>> record1 = record_example1()\n>>> record2 = record_example2()\n>>> history = History(records=[record1, record2])\n>>> history.summary()\n{\n 'records': [\n {\n 'time_local': '...',\n 'time_utc': '...',\n 'creator': {\n 'name': 'example1',\n 'a': 5,\n 'b': -7.0\n },\n 'messages': ['Message 1', 'Message 2'],\n 'record_type': 'process'\n },\n {\n 'time_local': '...',\n 'time_utc': '...',\n 'creator': {\n 'name': 'example2',\n 'a': 'parzen',\n 'b': -21\n },\n 'messages': ['Message 5', 'Message 6'],\n 'record_type': 'process'\n }\n ]\n}", "type": "object", "properties": { "records": { "title": "Records", "default": [], "type": "array", "items": { "$ref": "#/definitions/Record" } } } } } }
- field fs: float [Required]¶
The sampling frequency
- field chans: List[str] [Required]¶
List of channels
- field n_chans: Optional[int] = None¶
The number of channels
- Validated by
validate_n_chans
- field n_samples: int [Required]¶
The number of samples
- field first_time: resistics.sampling.HighResDateTime [Required]¶
The datetime of the first sample
- Constraints
pattern = %Y-%m-%d %H:%M:%S.%f_%o_%q_%v
examples = [‘2021-01-01 00:00:00.000061_035156_250000_000000’]
- field last_time: resistics.sampling.HighResDateTime [Required]¶
The datetime of the last sample
- Constraints
pattern = %Y-%m-%d %H:%M:%S.%f_%o_%q_%v
examples = [‘2021-01-01 00:00:00.000061_035156_250000_000000’]
- field system: str = ''¶
The system used for recording
- field serial: str = ''¶
Serial number of the system
- field wgs84_latitude: float = -999.0¶
Latitude in WGS84
- field wgs84_longitude: float = -999.0¶
Longitude in WGS84
- field easting: float = -999.0¶
The easting of the site in local cartersian coordinates
- field northing: float = -999.0¶
The northing of the site in local cartersian coordinates
- field elevation: float = -999.0¶
The elevation of the site
- field chans_metadata: Dict[str, resistics.time.ChanMetadata] [Required]¶
List of channel metadata
- field history: resistics.common.History = History(records=[])¶
Processing history
- property dt: float¶
Get the sampling frequency
- property duration: attotime.objects.attotimedelta.attotimedelta¶
Get the duration of the recording
- property nyquist: float¶
Get the nyquist frequency
- get_chan_types() List[str] [source]¶
Get all the different channel types
- Returns
A list of different channel types
- Return type
List[str]
Examples
>>> from resistics.testing import time_metadata_mt >>> metadata = time_metadata_mt() >>> metadata.get_chan_types() ['electric', 'magnetic']
- get_chans_with_type(chan_type: str) List[str] [source]¶
Get channels with the given type
- Parameters
chan_type (str) – The channel type
- Returns
A list of channels with the given channel type
- Return type
List[str]
Examples
>>> from resistics.testing import time_metadata_mt >>> metadata = time_metadata_mt() >>> metadata.get_chans_with_type("magnetic") ['Hx', 'Hy']
- get_electric_chans() List[str] [source]¶
Get list of electric channels
- Returns
List of electric channels
- Return type
List[str]
Examples
>>> from resistics.testing import time_metadata_mt >>> metadata = time_metadata_mt() >>> metadata.get_electric_chans() ['Ex', 'Ey']
- resistics.time.get_time_metadata(time_dict: Dict[str, Any], chans_dict: Dict[str, Dict[str, Any]]) resistics.time.TimeMetadata [source]¶
Get metadata for TimeData
The time and channel dictionaries must have the TimeMetadata required fields. For more information about the required fields, see
TimeMetadata
- Parameters
time_dict (Dict[str, Any]) – Dictionary with metadata for the whole dataset
chans_dict (Dict[str, Dict[str, Any]]) – Dictionary of dictionaries with metadata for each channel
- Returns
Metadata for TimeData
- Return type
See also
TimeMetadata
The TimeMetadata class which is returned
Examples
>>> from resistics.time import get_time_metadata >>> time_dict = { ... "fs": 10, ... "n_samples": 100, ... "chans": ["Ex", "Hy"], ... "n_chans": 2, ... "first_time": "2021-01-01 00:00:00", ... "last_time": "2021-01-01 00:01:00" ... } >>> chans_dict = { ... "Ex": {"name": "Ex", "data_files": "example.ascii"}, ... "Hy": {"name": "Hy", "data_files": "example2.ascii", "sensor": "MFS"} ... } >>> metadata = get_time_metadata(time_dict, chans_dict) >>> metadata.summary() { 'file_info': None, 'fs': 10.0, 'chans': ['Ex', 'Hy'], 'n_chans': 2, 'n_samples': 100, 'first_time': '2021-01-01 00:00:00.000000_000000_000000_000000', 'last_time': '2021-01-01 00:01:00.000000_000000_000000_000000', 'system': '', 'serial': '', 'wgs84_latitude': -999.0, 'wgs84_longitude': -999.0, 'easting': -999.0, 'northing': -999.0, 'elevation': -999.0, 'chans_metadata': { 'Ex': { 'name': 'Ex', 'data_files': ['example.ascii'], 'chan_type': 'electric', 'chan_source': None, 'sensor': '', 'serial': '', 'gain1': 1, 'gain2': 1, 'scaling': 1, 'chopper': False, 'dipole_dist': 1, 'sensor_calibration_file': '', 'instrument_calibration_file': '' }, 'Hy': { 'name': 'Hy', 'data_files': ['example2.ascii'], 'chan_type': 'magnetic', 'chan_source': None, 'sensor': 'MFS', 'serial': '', 'gain1': 1, 'gain2': 1, 'scaling': 1, 'chopper': False, 'dipole_dist': 1, 'sensor_calibration_file': '', 'instrument_calibration_file': '' } }, 'history': {'records': []} }
- resistics.time.adjust_time_metadata(metadata: resistics.time.TimeMetadata, fs: float, first_time: attotime.objects.attodatetime.attodatetime, n_samples: int) resistics.time.TimeMetadata [source]¶
Adjust time data metadata
This is required if changes have been made to the sampling frequency, the time of the first sample of the number of samples. This might occur in processes such as resampling or decimating.
Warning
The metadata passed in will be changed in place. If the original metadata should be retained, pass through a deepcopy
- Parameters
metadata (TimeMetadata) – Metadata to adjust
fs (float) – The sampling frequency
first_time (RSDateTime) – The first time of the data
n_samples (int) – The number of samples
- Returns
Adjusted metadata
- Return type
Examples
>>> from resistics.sampling import to_datetime >>> from resistics.time import adjust_time_metadata >>> from resistics.testing import time_metadata_2chan >>> metadata = time_metadata_2chan(fs=10, first_time="2021-01-01 00:00:00", n_samples=101) >>> metadata.fs 10.0 >>> metadata.n_samples 101 >>> metadata.first_time attotime.objects.attodatetime(2021, 1, 1, 0, 0, 0, 0, 0) >>> metadata.last_time attotime.objects.attodatetime(2021, 1, 1, 0, 0, 10, 0, 0) >>> metadata = adjust_time_metadata(metadata, 20, to_datetime("2021-03-01 00:01:00"), 50) >>> metadata.fs 20.0 >>> metadata.n_samples 50 >>> metadata.first_time attotime.objects.attodatetime(2021, 3, 1, 0, 1, 0, 0, 0) >>> metadata.last_time attotime.objects.attodatetime(2021, 3, 1, 0, 1, 2, 450000, 0)
- class resistics.time.TimeData(metadata: resistics.time.TimeMetadata, data: numpy.ndarray)[source]¶
Bases:
resistics.common.ResisticsData
Class for holding time data
The data values are stored in an numpy array attribute named data. This has shape:
n_chans x n_samples
- Parameters
metadata (TimeMetadata) – Metadata for the TimeData
data (np.ndarray) – Numpy array of the data
Examples
>>> import numpy as np >>> from resistics.testing import time_metadata_2chan >>> from resistics.time import TimeData >>> data = [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]] >>> time_data = TimeData(time_metadata_2chan(), np.array(data)) >>> time_data.metadata.chans ['chan1', 'chan2'] >>> time_data.get_chan("chan1") array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) >>> time_data["chan1"] array([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
- get_chan_index(chan: str) int [source]¶
Get the channel index in the data
- Parameters
chan (str) – The channel
- Returns
The index
- Return type
int
- get_chan(chan: str) numpy.ndarray [source]¶
Get the time data for a channel
- Parameters
chan (str) – The channel for which to get the time data
- Returns
pandas Series with channel data and datetime index
- Return type
np.ndarray
- set_chan(chan: str, chan_data: numpy.ndarray) None [source]¶
Set channel time data
- Parameters
chan (str) – The channel to set the data for
chan_data (np.ndarray) – The new channel data
- Raises
ValueError – If the data has incorrect size
ValueError – If the data has incorrect dtype
- get_timestamps(samples: Optional[numpy.ndarray] = None, estimate: bool = True) Union[numpy.ndarray, pandas.core.indexes.datetimes.DatetimeIndex] [source]¶
Get an array of timestamps
- Parameters
samples (Optional[np.ndarray], optional) – If provided, timestamps are only returned for the specified samples, by default None
estimate (bool, optional) – Flag for using estimates instead of high precision datetimes, by default True
- Returns
The return dates. This will be a numpy array of RSDateTime objects if estimate is False, else it will be a pandas DatetimeIndex
- Return type
Union[np.ndarray, pd.DatetimeIndex]
- subsection(from_time: Union[str, pandas._libs.tslibs.timestamps.Timestamp, datetime.datetime], to_time: Union[str, pandas._libs.tslibs.timestamps.Timestamp, datetime.datetime]) resistics.time.TimeData [source]¶
Get a subsection of the TimeData
Returns a new TimeData object
- Parameters
from_time (DateTimeLike) – Start of subsection
to_time (DateTimeLike) – End of subsection
- Returns
Subsection as new TimeData
- Return type
- copy() resistics.time.TimeData [source]¶
Get a deepcopy of the time data object
- plot(fig: Optional[plotly.graph_objs._figure.Figure] = None, chans: Optional[List[str]] = None, color: str = 'blue', legend: str = 'TimeData', max_pts: Optional[int] = 10000) plotly.graph_objs._figure.Figure [source]¶
Plot time series data
- Parameters
fig (Optional[go.Figure], optional) – A figure if appending the data to an existing plot, by default None
chans (Optional[List[str]], optional) – Explicit definition of channels to plot, by default None
color (str, optional) – The color for the data, by default “blue”
legend (str, optional) – The legend group to use, by default “TimeData”. This is more useful when plotting multiple TimeData
max_pts (Optional[int], optional) – The maximum number of points for any channel plot before applying lttbc downsampling, by default 10_000. If set to None, no downsampling will be applied.
- Returns
Plotly Figure
- Return type
go.Figure
- Raises
ValueError – If a figure is provided and channels have not been explicitly defined
- pydantic model resistics.time.TimeReader[source]¶
Bases:
resistics.common.ResisticsProcess
Show JSON schema
{ "title": "TimeReader", "description": "Base class for resistics processes\n\nResistics processes perform operations on data (including read and write\noperations). Each time a ResisticsProcess child class is run, it should add\na process record to the dataset", "type": "object", "properties": { "name": { "title": "Name", "type": "string" }, "apply_scalings": { "title": "Apply Scalings", "default": true, "type": "boolean" }, "extension": { "title": "Extension", "type": "string" } } }
- field apply_scalings: bool = True¶
- field extension: Optional[str] = None¶
- run(dir_path: pathlib.Path, metadata_only: Optional[bool] = False, metadata: Optional[resistics.time.TimeMetadata] = None, from_time: Optional[Union[str, pandas._libs.tslibs.timestamps.Timestamp, datetime.datetime]] = None, to_time: Optional[Union[str, pandas._libs.tslibs.timestamps.Timestamp, datetime.datetime]] = None, from_sample: Optional[int] = None, to_sample: Optional[int] = None) Union[resistics.time.TimeMetadata, resistics.time.TimeData] [source]¶
Read time series data
- Parameters
dir_path (Path) – The directory path
metadata_only (Optional[bool], optional) – Read only the metadata, by default False
metadata (Optional[TimeMetadata], optional) – Pass the metadata if its already been read in, by default None.
from_time (Union[DateTimeLike, None], optional) – Timestamp to read from, by default None
to_time (Union[DateTimeLike, None], optional) – Timestamp to read to, by default None
from_sample (Union[int, None], optional) – Sample to read from, by default None
to_sample (Union[int, None], optional) – Sample to read to, by default None
- Returns
A TimeData instance
- Return type
- read_metadata(dir_path: pathlib.Path) resistics.time.TimeMetadata [source]¶
Read time series data metadata
- Parameters
dir_path (Path) – The directory path of the time series data
- Raises
NotImplementedError – To be implemented in child classes
- read_data(dir_path: pathlib.Path, metadata: resistics.time.TimeMetadata, read_from: int, read_to: int) resistics.time.TimeData [source]¶
Read raw data with minimal scalings applied
- Parameters
dir_path (path) – The directory path to read from
metadata (TimeMetadata) – Time series data metadata
read_from (int) – Sample to read data from
read_to (int) – Sample to read data to
- Raises
NotImplementedError – To be implemented in child TimeReader classes
- scale_data(time_data: resistics.time.TimeData) resistics.time.TimeData [source]¶
Scale data to physically meaningful units.
For magnetotelluric data, this is assumed to be mV/km for electric channels, mV for magnetic channels (or nT for certain sensors)
The base class assumes the data is already in the correct units and requires no scaling.
- pydantic model resistics.time.TimeReaderJSON[source]¶
Bases:
resistics.time.TimeReader
Base class for TimeReaders that use a resistics JSON header
Show JSON schema
{ "title": "TimeReaderJSON", "description": "Base class for TimeReaders that use a resistics JSON header", "type": "object", "properties": { "name": { "title": "Name", "type": "string" }, "apply_scalings": { "title": "Apply Scalings", "default": true, "type": "boolean" }, "extension": { "title": "Extension", "type": "string" } } }
- read_metadata(dir_path: pathlib.Path) resistics.time.TimeMetadata [source]¶
Read the time series data metadata and return
- Parameters
dir_path (Path) – Path to time series data directory
- Returns
Metadata for time series data
- Return type
- Raises
MetadataReadError – If the headers cannot be parsed
TimeDataReadError – If the data files do not match the expected extension
- field apply_scalings: bool = True¶
- field extension: Optional[str] = None¶
- field name: Optional[str] [Required]¶
- Validated by
validate_name
- pydantic model resistics.time.TimeReaderAscii[source]¶
Bases:
resistics.time.TimeReaderJSON
Class for reading Ascii data
Ascii data expected to be a single file with all the data. The delimiter can be set using the delimiter class attribute as can the number of header lines with the n_header attribute.
Show JSON schema
{ "title": "TimeReaderAscii", "description": "Class for reading Ascii data\n\nAscii data expected to be a single file with all the data. The delimiter can\nbe set using the delimiter class attribute as can the number of header\nlines with the n_header attribute.", "type": "object", "properties": { "name": { "title": "Name", "type": "string" }, "apply_scalings": { "title": "Apply Scalings", "default": true, "type": "boolean" }, "extension": { "title": "Extension", "default": ".txt", "type": "string" }, "delimiter": { "title": "Delimiter", "type": "string" }, "n_header": { "title": "N Header", "default": 0, "type": "integer" } } }
- field extension: str = '.txt'¶
- field delimiter: Optional[str] = None¶
- field n_header: int = 0¶
- read_data(dir_path: pathlib.Path, metadata: resistics.time.TimeMetadata, read_from: int, read_to: int) resistics.time.TimeData [source]¶
Read data from Ascii files
- Parameters
dir_path (path) – The directory path to read from
metadata (TimeMetadata) – Time series data metadata
read_from (int) – Sample to read data from
read_to (int) – Sample to read data to
- Returns
TimeData
- Return type
- Raises
ValueError – If metadata is None
- pydantic model resistics.time.TimeReaderNumpy[source]¶
Bases:
resistics.time.TimeReaderJSON
Class for reading Numpy data
This is expected to be a single data file for all channels. The ordering is assumed to be the same as the channels definition in the metadata.
Show JSON schema
{ "title": "TimeReaderNumpy", "description": "Class for reading Numpy data\n\nThis is expected to be a single data file for all channels. The ordering is\nassumed to be the same as the channels definition in the metadata.", "type": "object", "properties": { "name": { "title": "Name", "type": "string" }, "apply_scalings": { "title": "Apply Scalings", "default": true, "type": "boolean" }, "extension": { "title": "Extension", "default": ".npy", "type": "string" } } }
- field extension: str = '.npy'¶
- read_data(dir_path: pathlib.Path, metadata: resistics.time.TimeMetadata, read_from: int, read_to: int) resistics.time.TimeData [source]¶
Read raw data saved in numpy data
- Parameters
dir_path (path) – The directory path to read from
metadata (TimeMetadata) – Time series data metadata
read_from (int) – Sample to read data from
read_to (int) – Sample to read data to
- Returns
TimeData
- Return type
- Raises
ValueError – If metadata is None
- pydantic model resistics.time.TimeWriterNumpy[source]¶
Bases:
resistics.common.ResisticsWriter
Write out time data in numpy binary format
Data is written out as a single data file including all channels
Show JSON schema
{ "title": "TimeWriterNumpy", "description": "Write out time data in numpy binary format\n\nData is written out as a single data file including all channels", "type": "object", "properties": { "name": { "title": "Name", "type": "string" }, "overwrite": { "title": "Overwrite", "default": true, "type": "boolean" } } }
- run(dir_path: pathlib.Path, time_data: resistics.time.TimeData) None [source]¶
Write out TimeData
- Parameters
dir_path (Path) – The directory path to write to
time_data (TimeData) – TimeData to write out
- Raises
WriteError – If unable to write to the directory
- field overwrite: bool = True¶
- field name: Optional[str] [Required]¶
- Validated by
validate_name
- pydantic model resistics.time.TimeWriterAscii[source]¶
Bases:
resistics.common.ResisticsWriter
Write out time data in ascii format
Show JSON schema
{ "title": "TimeWriterAscii", "description": "Write out time data in ascii format", "type": "object", "properties": { "name": { "title": "Name", "type": "string" }, "overwrite": { "title": "Overwrite", "default": true, "type": "boolean" } } }
- run(dir_path: pathlib.Path, time_data: resistics.time.TimeData) None [source]¶
Write out TimeData
- Parameters
dir_path (Path) – The directory path to write to
time_data (TimeData) – TimeData to write out
- Raises
WriteError – If unable to write to the directory
- field overwrite: bool = True¶
- field name: Optional[str] [Required]¶
- Validated by
validate_name
- resistics.time.new_time_data(time_data: resistics.time.TimeData, metadata: Optional[resistics.time.TimeMetadata] = None, data: Optional[numpy.ndarray] = None, record: Optional[resistics.common.Record] = None) resistics.time.TimeData [source]¶
Get a new TimeData
Values are taken from an existing TimeData where they are not explicitly specified. This is useful in a process where only some aspects of the TimeData have been changed
- Parameters
time_data (TimeData) – The existing TimeData
metadata (Optional[TimeMetadata], optional) – A new TimeMetadata, by default None
data (Optional[np.ndarray], optional) – New data, by default None
record (Optional[Record], optional) – A new record to add, by default None
- Returns
A new TimeData instance
- Return type
- pydantic model resistics.time.TimeProcess[source]¶
Bases:
resistics.common.ResisticsProcess
Parent class for processing time data
Show JSON schema
{ "title": "TimeProcess", "description": "Parent class for processing time data", "type": "object", "properties": { "name": { "title": "Name", "type": "string" } } }
- run(time_data: resistics.time.TimeData) resistics.time.TimeData [source]¶
Run the time processor
- field name: Optional[str] [Required]¶
- Validated by
validate_name
- pydantic model resistics.time.Subsection[source]¶
Bases:
resistics.time.TimeProcess
Get a subsection of time data
- Parameters
from_time (DateTimeLike) – Time to take subsection from
to_time (DateTimeLike) – Time to take subsection to
Examples
>>> import matplotlib.pyplot as plt >>> from resistics.testing import time_data_random >>> from resistics.time import Subsection >>> time_data = time_data_random(n_samples=1000) >>> print(time_data.metadata.first_time, time_data.metadata.last_time) 2020-01-01 00:00:00 2020-01-01 00:01:39.9 >>> process = Subsection(from_time="2020-01-01 00:00:25", to_time="2020-01-01 00:00:50.9") >>> subsection = process.run(time_data) >>> print(subsection.metadata.first_time, subsection.metadata.last_time) 2020-01-01 00:00:25 2020-01-01 00:00:50.9 >>> subsection.metadata.n_samples 260 >>> plt.plot(time_data.get_timestamps(), time_data["Ex"], label="full") >>> plt.plot(subsection.get_timestamps(), subsection["Ex"], label="sub") >>> plt.legend(loc=3) >>> plt.tight_layout() >>> plt.show()
(Source code, png, hires.png, pdf)
Show JSON schema
{ "title": "Subsection", "description": "Get a subsection of time data\n\nParameters\n----------\nfrom_time : DateTimeLike\n Time to take subsection from\nto_time : DateTimeLike\n Time to take subsection to\n\nExamples\n--------\n.. plot::\n :width: 90%\n\n >>> import matplotlib.pyplot as plt\n >>> from resistics.testing import time_data_random\n >>> from resistics.time import Subsection\n >>> time_data = time_data_random(n_samples=1000)\n >>> print(time_data.metadata.first_time, time_data.metadata.last_time)\n 2020-01-01 00:00:00 2020-01-01 00:01:39.9\n >>> process = Subsection(from_time=\"2020-01-01 00:00:25\", to_time=\"2020-01-01 00:00:50.9\")\n >>> subsection = process.run(time_data)\n >>> print(subsection.metadata.first_time, subsection.metadata.last_time)\n 2020-01-01 00:00:25 2020-01-01 00:00:50.9\n >>> subsection.metadata.n_samples\n 260\n >>> plt.plot(time_data.get_timestamps(), time_data[\"Ex\"], label=\"full\") # doctest: +SKIP\n >>> plt.plot(subsection.get_timestamps(), subsection[\"Ex\"], label=\"sub\") # doctest: +SKIP\n >>> plt.legend(loc=3) # doctest: +SKIP\n >>> plt.tight_layout() # doctest: +SKIP\n >>> plt.show() # doctest: +SKIP", "type": "object", "properties": { "name": { "title": "Name", "type": "string" }, "from_time": { "title": "From Time", "anyOf": [ { "type": "string" }, { "type": "string", "format": "date-time" }, { "type": "string", "format": "date-time" } ] }, "to_time": { "title": "To Time", "anyOf": [ { "type": "string" }, { "type": "string", "format": "date-time" }, { "type": "string", "format": "date-time" } ] } }, "required": [ "from_time", "to_time" ] }
- field from_time: Union[str, pandas._libs.tslibs.timestamps.Timestamp, datetime.datetime] [Required]¶
- field to_time: Union[str, pandas._libs.tslibs.timestamps.Timestamp, datetime.datetime] [Required]¶
- run(time_data: resistics.time.TimeData) resistics.time.TimeData [source]¶
Take a subsection from TimeData
- pydantic model resistics.time.InterpolateNans[source]¶
Bases:
resistics.time.TimeProcess
Interpolate nan values in the data
Preserve the data type of the input time data
Examples
>>> from resistics.testing import time_data_with_nans >>> from resistics.time import InterpolateNans >>> time_data = time_data_with_nans() >>> time_data["Hx"] array([nan, 2., 3., 5., 1., 2., 3., 4., 2., 6., 7., nan, nan, 4., 3., 2.], dtype=float32) >>> process = InterpolateNans() >>> time_data_new = process.run(time_data) >>> time_data_new["Hx"] array([2., 2., 3., 5., 1., 2., 3., 4., 2., 6., 7., 6., 5., 4., 3., 2.], dtype=float32)
Show JSON schema
{ "title": "InterpolateNans", "description": "Interpolate nan values in the data\n\nPreserve the data type of the input time data\n\nExamples\n--------\n>>> from resistics.testing import time_data_with_nans\n>>> from resistics.time import InterpolateNans\n>>> time_data = time_data_with_nans()\n>>> time_data[\"Hx\"]\narray([nan, 2., 3., 5., 1., 2., 3., 4., 2., 6., 7., nan, nan,\n 4., 3., 2.], dtype=float32)\n>>> process = InterpolateNans()\n>>> time_data_new = process.run(time_data)\n>>> time_data_new[\"Hx\"]\narray([2., 2., 3., 5., 1., 2., 3., 4., 2., 6., 7., 6., 5., 4., 3., 2.],\n dtype=float32)", "type": "object", "properties": { "name": { "title": "Name", "type": "string" } } }
- run(time_data: resistics.time.TimeData) resistics.time.TimeData [source]¶
Interpolate nan values
- field name: Optional[str] [Required]¶
- Validated by
validate_name
- pydantic model resistics.time.RemoveMean[source]¶
Bases:
resistics.time.TimeProcess
Remove channel mean value from each channel
Preserve the data type of the input time data
Examples
>>> import numpy as np >>> from resistics.testing import time_data_simple >>> from resistics.time import RemoveMean >>> time_data = time_data_simple() >>> process = RemoveMean() >>> time_data_new = process.run(time_data) >>> time_data_new["Hx"] array([-2.5, -1.5, -0.5, 1.5, -2.5, -1.5, -0.5, 0.5, -1.5, 2.5, 3.5, 2.5, 1.5, 0.5, -0.5, -1.5], dtype=float32) >>> hx_test = time_data["Hx"] - np.mean(time_data["Hx"]) >>> hx_test array([-2.5, -1.5, -0.5, 1.5, -2.5, -1.5, -0.5, 0.5, -1.5, 2.5, 3.5, 2.5, 1.5, 0.5, -0.5, -1.5], dtype=float32) >>> np.all(hx_test == time_data_new["Hx"]) True
Show JSON schema
{ "title": "RemoveMean", "description": "Remove channel mean value from each channel\n\nPreserve the data type of the input time data\n\nExamples\n--------\n>>> import numpy as np\n>>> from resistics.testing import time_data_simple\n>>> from resistics.time import RemoveMean\n>>> time_data = time_data_simple()\n>>> process = RemoveMean()\n>>> time_data_new = process.run(time_data)\n>>> time_data_new[\"Hx\"]\narray([-2.5, -1.5, -0.5, 1.5, -2.5, -1.5, -0.5, 0.5, -1.5, 2.5, 3.5,\n 2.5, 1.5, 0.5, -0.5, -1.5], dtype=float32)\n>>> hx_test = time_data[\"Hx\"] - np.mean(time_data[\"Hx\"])\n>>> hx_test\narray([-2.5, -1.5, -0.5, 1.5, -2.5, -1.5, -0.5, 0.5, -1.5, 2.5, 3.5,\n 2.5, 1.5, 0.5, -0.5, -1.5], dtype=float32)\n>>> np.all(hx_test == time_data_new[\"Hx\"])\nTrue", "type": "object", "properties": { "name": { "title": "Name", "type": "string" } } }
- run(time_data: resistics.time.TimeData) resistics.time.TimeData [source]¶
Remove mean from TimeData
- field name: Optional[str] [Required]¶
- Validated by
validate_name
- pydantic model resistics.time.Add[source]¶
Bases:
resistics.time.TimeProcess
Add values to channels
Add can be used to add a constant value to all channels or values for specific channels can be provided.
Add preserves the data type of the original data
- Parameters
add (Union[float, Dict[str, float]]) – Either a scalar to add to all channels or dictionary with values to add to each channel
Examples
Using a constant value for all channels passed as a scalar
>>> from resistics.testing import time_data_ones >>> from resistics.time import Add >>> time_data = time_data_ones() >>> process = Add(add=5) >>> time_data_new = process.run(time_data) >>> time_data_new["Ex"] - time_data["Ex"] array([5., 5., 5., 5., 5., 5., 5., 5., 5., 5.], dtype=float32) >>> time_data_new["Ey"] - time_data["Ey"] array([5., 5., 5., 5., 5., 5., 5., 5., 5., 5.], dtype=float32)
Variable values for the channels provided as a dictionary
>>> time_data = time_data_ones() >>> process = Add(add={"Ex": 3, "Hy": -7}) >>> time_data_new = process.run(time_data) >>> time_data_new["Ex"] - time_data["Ex"] array([3., 3., 3., 3., 3., 3., 3., 3., 3., 3.], dtype=float32) >>> time_data_new["Hy"] - time_data["Hy"] array([-7., -7., -7., -7., -7., -7., -7., -7., -7., -7.], dtype=float32) >>> time_data_new["Ey"] - time_data["Ey"] array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)
Show JSON schema
{ "title": "Add", "description": "Add values to channels\n\nAdd can be used to add a constant value to all channels or values for\nspecific channels can be provided.\n\nAdd preserves the data type of the original data\n\nParameters\n----------\nadd : Union[float, Dict[str, float]]\n Either a scalar to add to all channels or dictionary with values to\n add to each channel\n\nExamples\n--------\nUsing a constant value for all channels passed as a scalar\n\n>>> from resistics.testing import time_data_ones\n>>> from resistics.time import Add\n>>> time_data = time_data_ones()\n>>> process = Add(add=5)\n>>> time_data_new = process.run(time_data)\n>>> time_data_new[\"Ex\"] - time_data[\"Ex\"]\narray([5., 5., 5., 5., 5., 5., 5., 5., 5., 5.], dtype=float32)\n>>> time_data_new[\"Ey\"] - time_data[\"Ey\"]\narray([5., 5., 5., 5., 5., 5., 5., 5., 5., 5.], dtype=float32)\n\nVariable values for the channels provided as a dictionary\n\n>>> time_data = time_data_ones()\n>>> process = Add(add={\"Ex\": 3, \"Hy\": -7})\n>>> time_data_new = process.run(time_data)\n>>> time_data_new[\"Ex\"] - time_data[\"Ex\"]\narray([3., 3., 3., 3., 3., 3., 3., 3., 3., 3.], dtype=float32)\n>>> time_data_new[\"Hy\"] - time_data[\"Hy\"]\narray([-7., -7., -7., -7., -7., -7., -7., -7., -7., -7.], dtype=float32)\n>>> time_data_new[\"Ey\"] - time_data[\"Ey\"]\narray([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.], dtype=float32)", "type": "object", "properties": { "name": { "title": "Name", "type": "string" }, "add": { "title": "Add", "anyOf": [ { "type": "number" }, { "type": "object", "additionalProperties": { "type": "number" } } ] } }, "required": [ "add" ] }
- field add: Union[float, Dict[str, float]] [Required]¶
- run(time_data: resistics.time.TimeData) resistics.time.TimeData [source]¶
Add values to the data
- pydantic model resistics.time.Multiply[source]¶
Bases:
resistics.time.TimeProcess
Multiply channels by values
Multiply can be used to add a constant value to all channels or values for specific channels can be provided.
Multiply preseves the original type of the time data
- Parameters
multiplier (Union[Dict[str, float], float]) – Either a float to multiply all channels with the same value or a dictionary to specify different values for each channel
Examples
Using a constant value for all channels passed as a scalar
>>> from resistics.testing import time_data_ones >>> from resistics.time import Multiply >>> time_data = time_data_ones() >>> process = Multiply(multiplier=5) >>> time_data_new = process.run(time_data) >>> time_data_new["Ex"]/time_data["Ex"] array([5., 5., 5., 5., 5., 5., 5., 5., 5., 5.], dtype=float32) >>> time_data_new["Ey"]/time_data["Ey"] array([5., 5., 5., 5., 5., 5., 5., 5., 5., 5.], dtype=float32)
Variable values for the channels provided as a dictionary
>>> time_data = time_data_ones() >>> process = Multiply(multiplier={"Ex": 3, "Hy": -7}) >>> time_data_new = process.run(time_data) >>> time_data_new["Ex"]/time_data["Ex"] array([3., 3., 3., 3., 3., 3., 3., 3., 3., 3.], dtype=float32) >>> time_data_new["Hy"]/time_data["Hy"] array([-7., -7., -7., -7., -7., -7., -7., -7., -7., -7.], dtype=float32) >>> time_data_new["Ey"]/time_data["Ey"] array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], dtype=float32)
Show JSON schema
{ "title": "Multiply", "description": "Multiply channels by values\n\nMultiply can be used to add a constant value to all channels or values for\nspecific channels can be provided.\n\nMultiply preseves the original type of the time data\n\nParameters\n----------\nmultiplier : Union[Dict[str, float], float]\n Either a float to multiply all channels with the same value or a\n dictionary to specify different values for each channel\n\nExamples\n--------\nUsing a constant value for all channels passed as a scalar\n\n>>> from resistics.testing import time_data_ones\n>>> from resistics.time import Multiply\n>>> time_data = time_data_ones()\n>>> process = Multiply(multiplier=5)\n>>> time_data_new = process.run(time_data)\n>>> time_data_new[\"Ex\"]/time_data[\"Ex\"]\narray([5., 5., 5., 5., 5., 5., 5., 5., 5., 5.], dtype=float32)\n>>> time_data_new[\"Ey\"]/time_data[\"Ey\"]\narray([5., 5., 5., 5., 5., 5., 5., 5., 5., 5.], dtype=float32)\n\nVariable values for the channels provided as a dictionary\n\n>>> time_data = time_data_ones()\n>>> process = Multiply(multiplier={\"Ex\": 3, \"Hy\": -7})\n>>> time_data_new = process.run(time_data)\n>>> time_data_new[\"Ex\"]/time_data[\"Ex\"]\narray([3., 3., 3., 3., 3., 3., 3., 3., 3., 3.], dtype=float32)\n>>> time_data_new[\"Hy\"]/time_data[\"Hy\"]\narray([-7., -7., -7., -7., -7., -7., -7., -7., -7., -7.], dtype=float32)\n>>> time_data_new[\"Ey\"]/time_data[\"Ey\"]\narray([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], dtype=float32)", "type": "object", "properties": { "name": { "title": "Name", "type": "string" }, "multiplier": { "title": "Multiplier", "anyOf": [ { "type": "number" }, { "type": "object", "additionalProperties": { "type": "number" } } ] } }, "required": [ "multiplier" ] }
- field multiplier: Union[float, Dict[str, float]] [Required]¶
- run(time_data: resistics.time.TimeData) resistics.time.TimeData [source]¶
Multiply the channels
- pydantic model resistics.time.LowPass[source]¶
Bases:
resistics.time.TimeProcess
Apply low pass filter
- Parameters
cutoff (float) – The cutoff for the low pass
order (int, optional) – Order of the filter, by default 10
Examples
Low pass to remove 20 Hz from a time series sampled at 50 Hz
import matplotlib.pyplot as plt from resistics.testing import time_data_periodic from resistics.time import LowPass time_data = time_data_periodic([10, 50], fs=250, n_samples=100) process = LowPass(cutoff=30) filtered = process.run(time_data) plt.plot(time_data.get_timestamps(), time_data["chan1"], label="original") plt.plot(filtered.get_timestamps(), filtered["chan1"], label="filtered") plt.legend(loc=3) plt.tight_layout() plt.plot()
(Source code, png, hires.png, pdf)
Show JSON schema
{ "title": "LowPass", "description": "Apply low pass filter\n\nParameters\n----------\ncutoff : float\n The cutoff for the low pass\norder : int, optional\n Order of the filter, by default 10\n\nExamples\n--------\nLow pass to remove 20 Hz from a time series sampled at 50 Hz\n\n.. plot::\n :width: 90%\n\n import matplotlib.pyplot as plt\n from resistics.testing import time_data_periodic\n from resistics.time import LowPass\n time_data = time_data_periodic([10, 50], fs=250, n_samples=100)\n process = LowPass(cutoff=30)\n filtered = process.run(time_data)\n plt.plot(time_data.get_timestamps(), time_data[\"chan1\"], label=\"original\")\n plt.plot(filtered.get_timestamps(), filtered[\"chan1\"], label=\"filtered\")\n plt.legend(loc=3)\n plt.tight_layout()\n plt.plot()", "type": "object", "properties": { "name": { "title": "Name", "type": "string" }, "cutoff": { "title": "Cutoff", "type": "number" }, "order": { "title": "Order", "default": 10, "type": "integer" } }, "required": [ "cutoff" ] }
- field cutoff: float [Required]¶
- field order: int = 10¶
- run(time_data: resistics.time.TimeData) resistics.time.TimeData [source]¶
Apply the low pass filter
- Parameters
time_data (TimeData) – The input TimeData
- Returns
The low pass filtered TimeData
- Return type
- Raises
ProcessRunError – If cutoff > nyquist
- pydantic model resistics.time.HighPass[source]¶
Bases:
resistics.time.TimeProcess
High pass filter time data
- Parameters
cutoff (float) – Cutoff for the high pass filter
order (int, optional) – Order of the filter, by default 10
Examples
High pass to remove 3 Hz from signal sampled at 50 Hz
import matplotlib.pyplot as plt from resistics.testing import time_data_periodic from resistics.time import HighPass time_data = time_data_periodic([10, 50], fs=250, n_samples=100) process = HighPass(cutoff=30) filtered = process.run(time_data) plt.plot(time_data.get_timestamps(), time_data["chan1"], label="original") plt.plot(filtered.get_timestamps(), filtered["chan1"], label="filtered") plt.legend(loc=3) plt.tight_layout() plt.plot()
(Source code, png, hires.png, pdf)
Show JSON schema
{ "title": "HighPass", "description": "High pass filter time data\n\nParameters\n----------\ncutoff : float\n Cutoff for the high pass filter\norder : int, optional\n Order of the filter, by default 10\n\nExamples\n--------\nHigh pass to remove 3 Hz from signal sampled at 50 Hz\n\n.. plot::\n :width: 90%\n\n import matplotlib.pyplot as plt\n from resistics.testing import time_data_periodic\n from resistics.time import HighPass\n time_data = time_data_periodic([10, 50], fs=250, n_samples=100)\n process = HighPass(cutoff=30)\n filtered = process.run(time_data)\n plt.plot(time_data.get_timestamps(), time_data[\"chan1\"], label=\"original\")\n plt.plot(filtered.get_timestamps(), filtered[\"chan1\"], label=\"filtered\")\n plt.legend(loc=3)\n plt.tight_layout()\n plt.plot()", "type": "object", "properties": { "name": { "title": "Name", "type": "string" }, "cutoff": { "title": "Cutoff", "type": "number" }, "order": { "title": "Order", "default": 10, "type": "integer" } }, "required": [ "cutoff" ] }
- field cutoff: float [Required]¶
- field order: int = 10¶
- run(time_data: resistics.time.TimeData) resistics.time.TimeData [source]¶
Apply the high pass filter
- Parameters
time_data (TimeData) – The input TimeData
- Returns
The high pass filtered TimeData
- Return type
- Raises
ProcessRunError – If cutoff > nyquist
- pydantic model resistics.time.BandPass[source]¶
Bases:
resistics.time.TimeProcess
Band pass filter time data
- Parameters
cutoff_low (float) – The low cutoff for the band pass filter
cutoff_high (float) – The high cutoff for the band pass filter
order (int, optional) – The order of the filter, by default 10
Examples
Band pass to isolate 12 Hz signal
import matplotlib.pyplot as plt from resistics.testing import time_data_periodic from resistics.time import BandPass time_data = time_data_periodic([10, 50], fs=250, n_samples=100) process = BandPass(cutoff_low=45, cutoff_high=55) filtered = process.run(time_data) plt.plot(time_data.get_timestamps(), time_data["chan1"], label="original") plt.plot(filtered.get_timestamps(), filtered["chan1"], label="filtered") plt.legend(loc=3) plt.tight_layout() plt.plot()
(Source code, png, hires.png, pdf)
Show JSON schema
{ "title": "BandPass", "description": "Band pass filter time data\n\nParameters\n----------\ncutoff_low : float\n The low cutoff for the band pass filter\ncutoff_high : float\n The high cutoff for the band pass filter\norder : int, optional\n The order of the filter, by default 10\n\nExamples\n--------\nBand pass to isolate 12 Hz signal\n\n.. plot::\n :width: 90%\n\n import matplotlib.pyplot as plt\n from resistics.testing import time_data_periodic\n from resistics.time import BandPass\n time_data = time_data_periodic([10, 50], fs=250, n_samples=100)\n process = BandPass(cutoff_low=45, cutoff_high=55)\n filtered = process.run(time_data)\n plt.plot(time_data.get_timestamps(), time_data[\"chan1\"], label=\"original\")\n plt.plot(filtered.get_timestamps(), filtered[\"chan1\"], label=\"filtered\")\n plt.legend(loc=3)\n plt.tight_layout()\n plt.plot()", "type": "object", "properties": { "name": { "title": "Name", "type": "string" }, "cutoff_low": { "title": "Cutoff Low", "type": "number" }, "cutoff_high": { "title": "Cutoff High", "type": "number" }, "order": { "title": "Order", "default": 10, "type": "integer" } }, "required": [ "cutoff_low", "cutoff_high" ] }
- field cutoff_low: float [Required]¶
- field cutoff_high: float [Required]¶
- field order: int = 10¶
- run(time_data: resistics.time.TimeData) resistics.time.TimeData [source]¶
Apply the band pass filter
- Parameters
time_data (TimeData) – The input TimeData
- Returns
The band pass filtered TimeData
- Return type
- Raises
ProcessRunError – If cutoff_low > cutoff_high
ProcessRunError – If cutoff_high > nyquist
- pydantic model resistics.time.Notch[source]¶
Bases:
resistics.time.TimeProcess
Notch filter time data
- Parameters
notch (float) – The frequency to notch
band (Optional[float], optional) – The bandwidth of the filter, by default None
order (int, optional) – The order of the filter, by default 10
Examples
Notch to remove a 50 Hz signal, for example powerline noise
import matplotlib.pyplot as plt from resistics.testing import time_data_periodic from resistics.time import Notch time_data = time_data_periodic([10, 50], fs=250, n_samples=100) process = Notch(notch=50, band=10) filtered = process.run(time_data) plt.plot(time_data.get_timestamps(), time_data["chan1"], label="original") plt.plot(filtered.get_timestamps(), filtered["chan1"], label="filtered") plt.legend(loc=3) plt.tight_layout() plt.plot()
(Source code, png, hires.png, pdf)
Show JSON schema
{ "title": "Notch", "description": "Notch filter time data\n\nParameters\n----------\nnotch : float\n The frequency to notch\nband : Optional[float], optional\n The bandwidth of the filter, by default None\norder : int, optional\n The order of the filter, by default 10\n\nExamples\n--------\nNotch to remove a 50 Hz signal, for example powerline noise\n\n.. plot::\n :width: 90%\n\n import matplotlib.pyplot as plt\n from resistics.testing import time_data_periodic\n from resistics.time import Notch\n time_data = time_data_periodic([10, 50], fs=250, n_samples=100)\n process = Notch(notch=50, band=10)\n filtered = process.run(time_data)\n plt.plot(time_data.get_timestamps(), time_data[\"chan1\"], label=\"original\")\n plt.plot(filtered.get_timestamps(), filtered[\"chan1\"], label=\"filtered\")\n plt.legend(loc=3)\n plt.tight_layout()\n plt.plot()", "type": "object", "properties": { "name": { "title": "Name", "type": "string" }, "notch": { "title": "Notch", "type": "number" }, "band": { "title": "Band", "type": "number" }, "order": { "title": "Order", "default": 10, "type": "integer" } }, "required": [ "notch" ] }
- field notch: float [Required]¶
- field band: Optional[float] = None¶
- field order: int = 10¶
- run(time_data: resistics.time.TimeData) resistics.time.TimeData [source]¶
Apply notch filter to TimeData
- Parameters
time_data (TimeData) – Input TimeData
- Returns
Filtered TimeData
- Return type
- Raises
ProcessRunError – If notch frequency > nyquist
- pydantic model resistics.time.Resample[source]¶
Bases:
resistics.time.TimeProcess
Resample TimeData
Note that resampling is done on np.float64 data and this will lead to a temporary increase in memory usage. Once resampling is complete, the data is converted back to its original data type.
- Parameters
new_fs (int) – The new sampling frequency
Examples
Resample the data from 250 Hz to 50 Hz
>>> import matplotlib.pyplot as plt >>> from resistics.testing import time_data_periodic >>> from resistics.time import Resample >>> time_data = time_data_periodic([10, 50], fs=250, n_samples=200) >>> print(time_data.metadata.n_samples, time_data.metadata.first_time, time_data.metadata.last_time) 200 2020-01-01 00:00:00 2020-01-01 00:00:00.796 >>> process = Resample(new_fs=50) >>> resampled = process.run(time_data) >>> print(resampled.metadata.n_samples, resampled.metadata.first_time, resampled.metadata.last_time) 40 2020-01-01 00:00:00 2020-01-01 00:00:00.78 >>> plt.plot(time_data.get_timestamps(), time_data["chan1"], label="original") >>> plt.plot(resampled.get_timestamps(), resampled["chan1"], label="resampled") >>> plt.legend(loc=3) >>> plt.tight_layout() >>> plt.show()
(Source code, png, hires.png, pdf)
Show JSON schema
{ "title": "Resample", "description": "Resample TimeData\n\nNote that resampling is done on np.float64 data and this will lead to a\ntemporary increase in memory usage. Once resampling is complete, the data is\nconverted back to its original data type.\n\nParameters\n----------\nnew_fs : int\n The new sampling frequency\n\nExamples\n--------\nResample the data from 250 Hz to 50 Hz\n\n.. plot::\n :width: 90%\n\n >>> import matplotlib.pyplot as plt\n >>> from resistics.testing import time_data_periodic\n >>> from resistics.time import Resample\n >>> time_data = time_data_periodic([10, 50], fs=250, n_samples=200)\n >>> print(time_data.metadata.n_samples, time_data.metadata.first_time, time_data.metadata.last_time)\n 200 2020-01-01 00:00:00 2020-01-01 00:00:00.796\n >>> process = Resample(new_fs=50)\n >>> resampled = process.run(time_data)\n >>> print(resampled.metadata.n_samples, resampled.metadata.first_time, resampled.metadata.last_time)\n 40 2020-01-01 00:00:00 2020-01-01 00:00:00.78\n >>> plt.plot(time_data.get_timestamps(), time_data[\"chan1\"], label=\"original\") # doctest: +SKIP\n >>> plt.plot(resampled.get_timestamps(), resampled[\"chan1\"], label=\"resampled\") # doctest: +SKIP\n >>> plt.legend(loc=3) # doctest: +SKIP\n >>> plt.tight_layout() # doctest: +SKIP\n >>> plt.show() # doctest: +SKIP", "type": "object", "properties": { "name": { "title": "Name", "type": "string" }, "new_fs": { "title": "New Fs", "type": "number" } }, "required": [ "new_fs" ] }
- field new_fs: float [Required]¶
- run(time_data: resistics.time.TimeData) resistics.time.TimeData [source]¶
Resample TimeData
Resampling uses the polyphase method which does not assume periodicity Calculate the upsample rate and the downsampling rate and using polyphase filtering, the final sample rate is:
\[(up / down) * original sample rate\]Therefore, to get a sampling frequency of resampFreq, want:
\[(resampFreq / sampleFreq) * sampleFreq\]Use the fractions library to get up and down as integers which they are required to be.
- pydantic model resistics.time.Decimate[source]¶
Bases:
resistics.time.TimeProcess
Decimate TimeData
Warning
Data is converted to np.float64 prior to decimation. This is going to cause a temporary increase in memory usage, but decimating np.float64 delivers improved results.
The decimated data is converted back to its original data type prior to being returned.
The max_factor for a single decimation step is by default set as 3. When using np.float64 data, it is possible to use a larger decimation factor, up to 13, but this does again have an impact on results.
For more information, see https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.decimate.html
- Parameters
factor (int) – The decimation factor
Examples
>>> import matplotlib.pyplot as plt >>> from resistics.testing import time_data_periodic >>> from resistics.time import Decimate >>> time_data = time_data_periodic([10, 50], fs=250, n_samples=200) >>> print(time_data.metadata.n_samples, time_data.metadata.first_time, time_data.metadata.last_time) 200 2020-01-01 00:00:00 2020-01-01 00:00:00.796 >>> process = Decimate(factor=5) >>> decimated = process.run(time_data) >>> print(decimated.metadata.n_samples, decimated.metadata.first_time, decimated.metadata.last_time) 40 2020-01-01 00:00:00 2020-01-01 00:00:00.78 >>> plt.plot(time_data.get_timestamps(), time_data["chan1"], label="original") >>> plt.plot(decimated.get_timestamps(), decimated["chan1"], label="decimated") >>> plt.legend(loc=3) >>> plt.tight_layout() >>> plt.show()
(Source code, png, hires.png, pdf)
Show JSON schema
{ "title": "Decimate", "description": "Decimate TimeData\n\n.. warning::\n\n Data is converted to np.float64 prior to decimation. This is going to\n cause a temporary increase in memory usage, but decimating np.float64\n delivers improved results.\n\n The decimated data is converted back to its original data type prior\n to being returned.\n\n The max_factor for a single decimation step is by default set as 3.\n When using np.float64 data, it is possible to use a larger decimation\n factor, up to 13, but this does again have an impact on results.\n\n For more information, see\n https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.decimate.html\n\nParameters\n----------\nfactor : int\n The decimation factor\n\nExamples\n--------\n.. plot::\n :width: 90%\n\n >>> import matplotlib.pyplot as plt\n >>> from resistics.testing import time_data_periodic\n >>> from resistics.time import Decimate\n >>> time_data = time_data_periodic([10, 50], fs=250, n_samples=200)\n >>> print(time_data.metadata.n_samples, time_data.metadata.first_time, time_data.metadata.last_time)\n 200 2020-01-01 00:00:00 2020-01-01 00:00:00.796\n >>> process = Decimate(factor=5)\n >>> decimated = process.run(time_data)\n >>> print(decimated.metadata.n_samples, decimated.metadata.first_time, decimated.metadata.last_time)\n 40 2020-01-01 00:00:00 2020-01-01 00:00:00.78\n >>> plt.plot(time_data.get_timestamps(), time_data[\"chan1\"], label=\"original\") # doctest: +SKIP\n >>> plt.plot(decimated.get_timestamps(), decimated[\"chan1\"], label=\"decimated\") # doctest: +SKIP\n >>> plt.legend(loc=3) # doctest: +SKIP\n >>> plt.tight_layout() # doctest: +SKIP\n >>> plt.show() # doctest: +SKIP", "type": "object", "properties": { "name": { "title": "Name", "type": "string" }, "factor": { "title": "Factor", "minimum": 1, "type": "integer" }, "max_single_factor": { "title": "Max Single Factor", "default": 3, "minimum": 2, "type": "integer" } }, "required": [ "factor" ] }
- field factor: resistics.time.ConstrainedIntValue [Required]¶
- Constraints
minimum = 1
- field max_single_factor: resistics.time.ConstrainedIntValue = 3¶
- Constraints
minimum = 2
- run(time_data: resistics.time.TimeData) resistics.time.TimeData [source]¶
Decimate TimeData
- pydantic model resistics.time.ShiftTimestamps[source]¶
Bases:
resistics.time.TimeProcess
Shift timestamps. This method is usually used when there is an offset on the sampling, so that instead of coinciding with a second or an hour, they are offset from this.
The function interpolates the original data onto the shifted timestamps.
- Parameters
shift (float) – The shift in seconds. This must be positive as data is never extrapolated
Examples
An example shifting timestamps for TimeData with a sample period of 20 seconds (fs = 1/20 = 0.05 Hz) but with an offset of 10 seconds on the timestamps
>>> from resistics.testing import time_data_with_offset >>> from resistics.time import ShiftTimestamps >>> time_data = time_data_with_offset(offset=10, fs=1/20, n_samples=5) >>> [x.time().strftime('%H:%M:%S') for x in time_data.get_timestamps()] ['00:00:10', '00:00:30', '00:00:50', '00:01:10', '00:01:30'] >>> process = ShiftTimestamps(shift=10) >>> result = process.run(time_data) >>> [x.time().strftime('%H:%M:%S') for x in result.get_timestamps()] ['00:00:20', '00:00:40', '00:01:00', '00:01:20'] >>> plt.plot(time_data.get_timestamps(), time_data["chan1"], "bo", label="original") >>> plt.plot(result.get_timestamps(), result["chan1"], "rd", label="shifted") >>> plt.legend(loc=4) >>> plt.grid() >>> plt.tight_layout() >>> plt.show()
(Source code, png, hires.png, pdf)
Show JSON schema
{ "title": "ShiftTimestamps", "description": "Shift timestamps. This method is usually used when there is an offset on the\nsampling, so that instead of coinciding with a second or an hour, they are\noffset from this.\n\nThe function interpolates the original data onto the shifted timestamps.\n\nParameters\n----------\nshift : float\n The shift in seconds. This must be positive as data is never\n extrapolated\n\nExamples\n--------\nAn example shifting timestamps for TimeData with a sample period of 20\nseconds (fs = 1/20 = 0.05 Hz) but with an offset of 10 seconds on the\ntimestamps\n\n.. plot::\n :width: 90%\n\n >>> from resistics.testing import time_data_with_offset\n >>> from resistics.time import ShiftTimestamps\n >>> time_data = time_data_with_offset(offset=10, fs=1/20, n_samples=5)\n >>> [x.time().strftime('%H:%M:%S') for x in time_data.get_timestamps()]\n ['00:00:10', '00:00:30', '00:00:50', '00:01:10', '00:01:30']\n >>> process = ShiftTimestamps(shift=10)\n >>> result = process.run(time_data)\n >>> [x.time().strftime('%H:%M:%S') for x in result.get_timestamps()]\n ['00:00:20', '00:00:40', '00:01:00', '00:01:20']\n >>> plt.plot(time_data.get_timestamps(), time_data[\"chan1\"], \"bo\", label=\"original\") # doctest: +SKIP\n >>> plt.plot(result.get_timestamps(), result[\"chan1\"], \"rd\", label=\"shifted\") # doctest: +SKIP\n >>> plt.legend(loc=4) # doctest: +SKIP\n >>> plt.grid() # doctest: +SKIP\n >>> plt.tight_layout() # doctest: +SKIP\n >>> plt.show() # doctest: +SKIP", "type": "object", "properties": { "name": { "title": "Name", "type": "string" }, "shift": { "title": "Shift", "exclusiveMinimum": 0, "type": "number" } }, "required": [ "shift" ] }
- field shift: pydantic.types.PositiveFloat [Required]¶
- Constraints
exclusiveMinimum = 0
- run(time_data: resistics.time.TimeData) resistics.time.TimeData [source]¶
Shift timestamps and interpolate data
- Parameters
time_data (TimeData) – Input TimeData
- Returns
TimeData with shifted timestamps and data interpolated
- Return type
- Raises
ProcessRunError – If the shift is greater than the sampling frequency. This method is not supposed to be used for resampling, but simply for removing an offset from timestamps
- resistics.time.serialize_custom_fnc(fnc: Callable) str [source]¶
Serialize the custom functions
This is not really reversible and recovering parameters from ApplyFunction is not supported
- Parameters
fnc (Callable) – Function to serialize
- Returns
serialized output
- Return type
str
- pydantic model resistics.time.ApplyFunction[source]¶
Bases:
resistics.time.TimeProcess
Apply a generic functions to the time data
To be used with single argument functions that take the channel data array and a perform transformation on the data.
- Parameters
fncs (Dict[str, Callable]) – Dictionary of channel to callable
Examples
>>> import numpy as np >>> from resistics.testing import time_data_ones >>> from resistics.time import ApplyFunction >>> time_data = time_data_ones() >>> process = ApplyFunction(fncs={"Ex": lambda x: 2*x, "Hy": lambda x: 3*x*x - 5*x + 1}) >>> result = process.run(time_data) >>> time_data["Ex"] array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], dtype=float32) >>> result["Ex"] array([2., 2., 2., 2., 2., 2., 2., 2., 2., 2.]) >>> time_data["Hy"] array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], dtype=float32) >>> result["Hy"] array([-1., -1., -1., -1., -1., -1., -1., -1., -1., -1.])
Show JSON schema
{ "title": "ApplyFunction", "description": "Apply a generic functions to the time data\n\nTo be used with single argument functions that take the channel data array\nand a perform transformation on the data.\n\nParameters\n----------\nfncs : Dict[str, Callable]\n Dictionary of channel to callable\n\nExamples\n--------\n>>> import numpy as np\n>>> from resistics.testing import time_data_ones\n>>> from resistics.time import ApplyFunction\n>>> time_data = time_data_ones()\n>>> process = ApplyFunction(fncs={\"Ex\": lambda x: 2*x, \"Hy\": lambda x: 3*x*x - 5*x + 1})\n>>> result = process.run(time_data)\n>>> time_data[\"Ex\"]\narray([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], dtype=float32)\n>>> result[\"Ex\"]\narray([2., 2., 2., 2., 2., 2., 2., 2., 2., 2.])\n>>> time_data[\"Hy\"]\narray([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.], dtype=float32)\n>>> result[\"Hy\"]\narray([-1., -1., -1., -1., -1., -1., -1., -1., -1., -1.])", "type": "object", "properties": { "name": { "title": "Name", "type": "string" } } }
- field fncs: Dict[str, Callable] [Required]¶
- run(time_data: resistics.time.TimeData) resistics.time.TimeData [source]¶
Apply functions to channel data