MDF

This class acts as a proxy for the MDF3 and MDF4 classes. All attribute access is delegated to the underlying _mdf attribute (MDF2, MDF3 or MDF4 object). See MDF3 and MDF4 for available extra methods (MDF2 and MDF3 share the same implementation).

An empty MDF file is created if the name argument is not provided. If the name argument is provided then the file must exist in the filesystem, otherwise an exception is raised.

Best practice is to use the MDF as a context manager. This way all resources are released correctly in case of exceptions.

with MDF(r'test.mdf') as mdf_file:
    # do something
class asammdf.mdf.MDF(name=None, memory='full', version='4.10')[source]

Unified access to MDF v3 and v4 files.

Parameters:

name : string

mdf file name, if provided it must be a real file name

memory : str

memory option; default full

  • if full the data group binary data block will be loaded in RAM
  • if low the channel data is read from disk on request, and the
    metadata is loaded into RAM
  • if minimum only minimal data is loaded into RAM

version : string

mdf file version from (‘2.00’, ‘2.10’, ‘2.14’, ‘3.00’, ‘3.10’, ‘3.20’, ‘3.30’, ‘4.00’, ‘4.10’, ‘4.11’); default ‘4.10’

convert(to, memory='full')[source]

convert MDF to other versions

Parameters:

to : str

new mdf file version from (‘2.00’, ‘2.10’, ‘2.14’, ‘3.00’, ‘3.10’, ‘3.20’, ‘3.30’, ‘4.00’, ‘4.10’, ‘4.11’); default ‘4.10’

memory : str

memory option; default full

Returns:

out : MDF

new MDF object

cut(start=None, stop=None, whence=0)[source]

convert MDF to other versions

Parameters:

start : float

start time, default None. If None then the start of measurement is used

stop : float

stop time, default . If None then the end of measurement is used

whence : int

how to search for the start and stop values

  • 0 : absolute
  • 1 : relative to first timestamp
Returns:

out : MDF

new MDF object

export(fmt, filename=None)[source]

export MDF to other formats. The MDF file name is used is available, else the filename aragument must be provided.

Parameters:

fmt : string

can be one of the following:

  • csv : CSV export that uses the “;” delimiter. This option

    will generate a new csv file for each data group (<MDFNAME>_DataGroup_<cntr>.csv)

  • hdf5 : HDF5 file output; each MDF data group is mapped to

    a HDF5 group with the name ‘DataGroup_<cntr>’ (where <cntr> is the index)

  • excel : Excel file output (very slow). This option will

    generate a new excel file for each data group (<MDFNAME>_DataGroup_<cntr>.xlsx)

  • mat : Matlab .mat version 5 export, for Matlab >= 7.6. In

    the mat file the channels will be renamed to ‘DataGroup_<cntr>_<channel name>’. The channel group master will be renamed to ‘DataGroup_<cntr>_<channel name>_master’ ( <cntr> is the data group index starting from 0)

filename : string

export file name

filter(channels, memory=None)[source]

return new MDF object that contains only the channels listed in channels argument

Parameters:

channels : list

list of items to be filtered; each item can be :

  • a channel name string
  • (channel_name, group index, channel index) list or tuple
  • (channel name, group index) list or tuple
  • (None, group index, channel index) lsit or tuple

memory : str

memory option for filtered mdf; default None in which case the original file’s memory option is used

Returns:

mdf : MDF

new MDF file

Examples

>>> from asammdf import MDF, Signal
>>> import numpy as np
>>> t = np.arange(5)
>>> s = np.ones(5)
>>> mdf = MDF()
>>> for i in range(4):
...     sigs = [Signal(s*(i*10+j), t, name='SIG') for j in range(1,4)]
...     mdf.append(sigs)
...
>>> filtered = mdf.filter(['SIG', ('SIG', 3, 1), ['SIG', 2], (None, 1, 2)])
>>> for gp_nr, ch_nr in filtered.channels_db['SIG']:
...     print(filtered.get(group=gp_nr, index=ch_nr))
...
<Signal SIG:
        samples=[ 1.  1.  1.  1.  1.]
        timestamps=[0 1 2 3 4]
        unit=""
        info=None
        comment="">
<Signal SIG:
        samples=[ 31.  31.  31.  31.  31.]
        timestamps=[0 1 2 3 4]
        unit=""
        info=None
        comment="">
<Signal SIG:
        samples=[ 21.  21.  21.  21.  21.]
        timestamps=[0 1 2 3 4]
        unit=""
        info=None
        comment="">
<Signal SIG:
        samples=[ 12.  12.  12.  12.  12.]
        timestamps=[0 1 2 3 4]
        unit=""
        info=None
        comment="">
iter_channels(skip_master=True)[source]

generator that yields a Signal for each non-master channel

Parameters:

skip_master : bool

do not yield master channels; default True

iter_groups()[source]

generator that yields channel groups as pandas DataFrames

static merge(files, outversion='4.10', memory='full')[source]

merge several files and return the merged MDF object. The files must have the same internal structure (same number of groups, and same channels in each group)

Parameters:

files : list | tuple

list of MDF file names or MDF instances

outversion : str

merged file version

memory : str

memory option; default full

Returns:

merged : MDF

new MDF object with merged channels

Raises:

MdfException : if there are inconsistencies between the files

merged MDF object

resample(raster, memory=None)[source]

resample all channels to given raster

Parameters:

raster : float

time raster is seconds

memory : str

memory option; default None

Returns:

mdf : MDF

new MDF with resampled channels

select(channels, dataframe=False)[source]

return the channels listed in channels argument

Parameters:

channels : list

list of items to be filtered; each item can be :

  • a channel name string
  • (channel_name, group index, channel index) list or tuple
  • (channel name, group index) list or tuple
  • (None, group index, channel index) lsit or tuple

dataframe: bool

return a pandas DataFrame instead of a list of Signals; in this case the signals will be interpolated using the union of all timestamps

Returns:

signals : list

list of Signal objects based on the input channel list

Examples

>>> from asammdf import MDF, Signal
>>> import numpy as np
>>> t = np.arange(5)
>>> s = np.ones(5)
>>> mdf = MDF()
>>> for i in range(4):
...     sigs = [Signal(s*(i*10+j), t, name='SIG') for j in range(1,4)]
...     mdf.append(sigs)
...
>>> # select SIG group 0 default index 1 default, SIG group 3 index 1, SIG group 2 index 1 default and channel index 2 from group 1
...
>>> mdf.select(['SIG', ('SIG', 3, 1), ['SIG', 2],  (None, 1, 2)])
[<Signal SIG:
        samples=[ 1.  1.  1.  1.  1.]
        timestamps=[0 1 2 3 4]
        unit=""
        info=None
        comment="">
, <Signal SIG:
        samples=[ 31.  31.  31.  31.  31.]
        timestamps=[0 1 2 3 4]
        unit=""
        info=None
        comment="">
, <Signal SIG:
        samples=[ 21.  21.  21.  21.  21.]
        timestamps=[0 1 2 3 4]
        unit=""
        info=None
        comment="">
, <Signal SIG:
        samples=[ 12.  12.  12.  12.  12.]
        timestamps=[0 1 2 3 4]
        unit=""
        info=None
        comment="">
]
whereis(channel)[source]

get ocurrences of channel name in the file

Parameters:

channel : str

channel name string

Returns:

ocurrences : tuple

Examples

>>> mdf = MDF(file_name)
>>> mdf.whereis('VehicleSpeed') # "VehicleSpeed" exists in the file
((1, 2), (2, 4))
>>> mdf.whereis('VehicleSPD') # "VehicleSPD" doesn't exist in the file
()

MDF3 and MDF4 classes

Notes about memory argument

By default when the MDF object is created all data is loaded into RAM (memory=full). This will give you the best performance from asammdf.

However if you reach the physical memory limit asammdf gives you two options:

  • memory=low : only the metadata is loaded into RAM, the raw channel data is loaded when needed
  • memory=minimum : only minimal data is loaded into RAM.

MDF created with memory=’full’

Advantages

  • best performance

Disadvantages

  • higher RAM usage, there is the chance the file will exceed available RAM

Use case

  • when data fits inside the system RAM

MDF created with memory=’low’

Advantages

  • lower RAM usage than memory=full
  • can handle files that do not fit in the available physical memory

Disadvantages

  • slow performance for getting channel data
  • must call close method to release the temporary file used in case of appending.

Note

it is advised to use the MDF context manager in this case

Use case

  • when default data exceeds available RAM
  • it is advised to avoid getting individual channels when using this ioption.

Instead you can get performance close to memory=`full` if you use the select method with the list of target channels.

Note

See benchmarks for the effects of using the flag

MDF created with memory=’minimum’

Advantages

  • lowest RAM usage
  • can handle files that do not fit in the available physical memory
  • handle big files on 32 bit Python

Disadvantages

  • slightly slower performance compared to momeory=low
  • must call close method to release the temporary file used in case of appending.

Note

See benchmarks for the effects of using the flag