How to read time domain signals from CI Data Files in C#, Python, and Matlab

Introduction
The CI Data File Reader API consists of two DLL files that can be integrated with custom software to directly read and extract data from an ATFX file. This article will demonstrate how to read time domain signals in C#, Python and Matlab. There will be similarities to reading frequency domain signals as the only difference is passing in the spectrum type parameter.

For a simple way to import the C# dll files and open an ATFX file in Python & Matlab, please refer to the How to Read CI Data Files in Python and/or How to Read CI Data Files in Matlab article.

For more detailed information on how to implement the following code sections and properties in a class, please refer to the CI Data File Reader manual and the provided C#, Python & Matlab Demo code. The package can be downloaded from our Programming Corner.

The following Python script uses two packages, numpy and matplotlib, that can be installed by the following commands in the operating system command prompt or integrated development environment software terminal.

pip install numpy

pip install matplotlib

Obtaining Frequency Domain Signal Frame Data in C#
The following is a very short code example of obtaining a time signal frame data in C#. The ISignal.GetFrame(int index, _SpectrumScalingType spectrum, string engineeringUnit) method is used to obtain a signal frame from an ATFX file.

The index specifies the starting index of the frame. The data will convert to a scaling spectrum type and is identical for the engineeringUnit string. Since this is reading a time domain signal, the spectrum is not required, thus _SpectrumScalingType.Unknown can be passed in. If any other spectrum types are passed in, it would not affect the returned data.

The engineering unit string can be left blank, “”, to obtain the default engineering unit that the signal was saved as.

To obtain the exact engineering unit string that the CI Data File Reader API can read in, it is recommended to use the Utility.GetSignalQuantityEngiUnitStrings(ISignal) to return a string array that contains the engineering unit strings.

string recordingPath = "C:\Sig001.atfx";
RecordingManager.Manager.OpenRecording(recordingPath, out IRecording rec)

ISignal timeSig = rec.Signals[10];

string[] engiUnits = Utility.GetSignalQuantityEngiUnitStrings(timeSig);

double[][] frame = timeSig.GetFrame(0, _SpectrumScalingType.Unknown, engiUnits[3]);

Obtaining Time Domain Signal Frame Data in Python
The following python script can be found in Reading_TimeDomain_Data.py.

The following are the import modules for the script.

#---Pythonnet clr import
import clr
# Change file path here to whereever the DLL files are
parentPath = "C:\\MyStuff\\DevelopmentalVer\\bin\\AnyCPU\\Debug\\Utility\\CIATFXReader\\"

clr.AddReference(parentPath + "CI.ATFX.Reader.dll")
clr.AddReference(parentPath + "Common.dll")
clr.AddReference('System.Linq')
clr.AddReference('System.Collections')

import numpy as np
import matplotlib.pyplot as plt

#---C# .NET imports & dll imports
from EDM.Recording import *
from EDM.RecordingInterface import *
from ASAM.ODS.NVH import *
from EDM.Utils import *
from Common import *
from Common import _SpectrumScalingType
from Common.Spider import *
from System import *
from System.Diagnostics import *
from System.Reflection import *
from System.Text import *
from System.IO import *

The following is the open recording method for the ATFX file.

# Change file path here to whereever signal or recording files are
recordingPath = "C:\\Users\\KevinCheng\\Downloads\\gps test example\\"
# ATFX file path, change contain the file name and correctly reference it in RecordingManager.Manager.OpenRecording
recordingPathRegular = recordingPath + "SIG0000.atfx"

#OpenRecording(string, out IRecording)
# openRecordSucceed is required for the OpenRecording as it is the returned boolean
# Make sure to reference the correct file string

openRecordSucceed, recording = RecordingManager.Manager.OpenRecording(recordingPathRegular, None)

Then from the extracted IRecording object, the script will obtain the list of signals, obtain a specific time domain signal, and obtain signal frame.

# Get a list of signals
signalList = Utility.GetListOfAllSignals(recording)

# Get the frame of a time signal depending on where it is in the list
# The Convert.ToInt32 is necessary for the the enum AccelerationUnitType to be read as a int instead of a string

signal = signalList[1]
frame = signal.GetFrame(0, _SpectrumScalingType.Unknown, AccelerationUnitEnumString.ArrayString[Convert.ToInt32(AccelerationUnitType.g)])

The signal GetFrame will return as a System.Double[], which can be used as is, but sometimes it may be better to convert to a more readable Python object such as a numpy array.

print("X: ", frame[0][0])
print("Y: ", frame[1][0])
print("X: ", frame[0][1])
print("Y: ", frame[1][1])
print("X: ", frame[0][2])
print("Y: ", frame[1][2])

# Convert System.Double[] to numpy array
frameX = np.fromiter(frame[0], float)
frameY = np.fromiter(frame[1], float)
    
# Plot the signal frames
plt.plot(frameX,frameY,'r', label=signal.Name)
plt.xlabel(signal.Properties.xQuantity + " (" + signal.Properties.xUnit + ")")
plt.ylabel(signal.Properties.yQuantity + " (" + signal.Properties.yUnit + ")")
plt.title("Plot of the " + signal.Name)
plt.legend()
plt.show()

Obtaining Time Domain Signal Frame Data in Matlab
The following python script can be found in Reading_TimeDomain_Data.m.

The following is the script import the C# DLL files use for the Matlab built-in NET.addAssembly() method. After that, the script will create the IRecording object and then obtain a time domain signal.

% Load common and reader dll
NET.addAssembly('C:\MyStuff\DevelopmentalVer\bin\AnyCPU\Debug\Utility\CIATFXReader\Common.dll');
NET.addAssembly('C:\MyStuff\DevelopmentalVer\bin\AnyCPU\Debug\Utility\CIATFXReader\CI.ATFX.Reader.dll');

% Create a atfx recording instance
atfxFilePath = 'C:\Users\KevinCheng\Documents\EDM\test\Random69\Run3 Jul 01, 2022 11-20-16\SIG0004.atfx';
% array to contain boolean return and the actual out IRecording parameter
[openRecordSucceed, recording] = EDM.Recording.RecordingManager.Manager.OpenRecording(atfxFilePath);

% Use item function to get a time signal instance
sig = Item(recording.Signals,9);

Then the script will proceed in displaying certain signal properties and obtaining the signal frame data.

% Display signal properties
disp(System.String.Format("Name:",sig.Name));
disp(System.String.Format("X Unit:",sig.Properties.xUnit));
disp(System.String.Format("Y Unit:",sig.Properties.yUnit));

disp("display signal frame data");
% Get signal frame
frame = sig.GetFrame(0);

Then it will convert the frame .Net double[][] object to matlab cell to start plotting the signal frame data.

% Convert .Net double[][] array to matlab cell
matFrame = cell(frame);
% Long format, showing more decimal places
format long;
% Display the cell(frame) content
%celldisp(matFrame);
% Convert back to mat array

xVals = cell2mat(matFrame(1));
yValues = cell2mat(matFrame(2));

%plot the signal
plot(xVals,yValues,'r');
xlabel(string(sig.Properties.xQuantity)+" ("+string(sig.Properties.xUnit)+")");
ylabel(string(sig.Properties.yQuantity)+" ("+string(sig.Properties.yUnit)+")");
title("Plot of the "+string(sig.Name));
legend(string(sig.Name));