Usage¶
Basic¶
One of the challenges in working with TDMS files is finding the properties and
channel data in a file that you didn’t create. In LabVIEW code, this can be a
frustrating experience - nitdms
to the rescue! At an interactive prompt, just use
tab-completion to discover all the objects available at each level of the heirarchy and
access the desired value.
You can also print the file heirarchy showing all the objects:
>>> from nitdms import TdmsFile
>>> tf = TdmsFile(<file>)
>>> print(tf)
<file>
name
<file property>
...
<group>
<group property>
...
<channel>
<channel property>
...
data
LabVIEW doesn’t impose any constraints on the names of groups, channels or properties. But, Python’s attributes must be valid indentifiers - generally ASCII letters, numbers (except first character) and underscore. So, TdmsFile also supports item access like a dict. For example, suppose a group name in the file is ‘1group’ and has channel ‘1channel’. Both names are invalid identifiers and will generate a syntax error when using dot access.
The usage pattern in this case is:
>>> from nitdms import TdmsFile
>>> tf = TdmsFile(<file>)
>>> print(tf)
file_name
1group
1channel
>>> group = tf['1group']
>>> channel = group['1channel']
>>> data = channel.data
Pandas¶
Want a Pandas DataFrame? For example, suppose the TDMS file contains a group ‘group_0’ with two channels ‘ch_0’ and ‘ch_1’ with equal length. This example also illustrates the iteration feature of TdmsFile.
>>> import pandas as pd
>>> from nitdms import TdmsFile
>>> tf = TdmsFile(<file>)
>>> group = tf.group_0
>>> data = dict(zip(group.channels, [ch.data for ch in group]))
>>> df = pd.DataFrame(data)
>>> df
ch_0 ch_1
0 0 10
1 1 11
2 2 12
...
9 9 19
So, why doesn’t TdmsFile just return a DataFrame? The contents of the TDMS file are arbitrary and have no general, direct mapping to a DataFrame. For example, the tdms file channel data is interpreted by the properties, but the DataFrame columns, which are Pandas Series objects, don’t support metadata. In some situations a DataFrame is appropriate, but in general it isn’t.
WaveformDT and Matplotlib¶
If the channel data in the TDMS file originated from LabVIEW’s waveform data type, the returned data will be a WaveformDT that uses Numpy’s dispatch mechanism. This mimics the waveform data type in LabVIEW. In addition to all of the attributes such as t0 and dt, WaveformDT provides a convenience function to_xy() that facilitates plotting data in Matplotlib. For example:
>>> import matplotlib.pyplot as plt
>>> from nitdms import TdmsFile
>>> tf = TdmsFile(<file>)
>>> waveform = tf.<group>.<channel>.data
>>> waveform.t0
datetime.datetime(...)
>>> waveform.dt
<value>
>>> x, y = waveform.to_xy()
>>> plt.plot(x, y)
>>> plt.show()
WaveformDT also supports item access and Matplotlib’s labeled data interface:
>>> import matplotlib.pyplot as plt
>>> from nitdms import TdmsFile
>>> tf = TdmsFile(<file>)
>>> waveform = tf.<group>.<channel>.data
>>> plt.plot('x', 'y', 'r-', data=waveform)
>>> plt.show()
WaveformDT and unyt¶
If the channel data orginated from a DAQmx acquisition, the WaveformDT object will have the attribute unit_string indicating the measurement unit. You can make the data unit-aware using the unyt package.
>>> import matplotlib.pyplot as plt
>>> from nitdms import TdmsFile
>>> from unit_system.predefined_units import *
>>> tf = TdmsFile(<file>)
>>> waveform = tf.<group>.<channel>.data
>>> waveform.unit_string
'Volts'
>>> x, y = waveform.to_xy()
>>> x = x*s
>>> y = y*V
>>> plt.plot(x, y)
>>> plt.show()