Inspect and Compare Data Programmatically

You can harness the capabilities of the Simulation Data Inspector from the MATLAB® command line using the Simulation Data Inspector API.

The Simulation Data Inspector organizes data in runs and signals, assigning a unique numeric identification to each run and signal. Some Simulation Data Inspector API functions use the run and signal IDs to reference data, rather than accepting the run or signal itself as an input. To access the run IDs in the workspace, you can use Simulink.sdi.getAllRunIDs or Simulink.sdi.getRunIDByIndex. You can access signal IDs through a Simulink.sdi.Run object using the getSignalIDByIndex method.

The Simulink.sdi.Run and Simulink.sdi.Signal classes provide access to your data and allow you to view and modify run and signal metadata. You can modify the Simulation Data Inspector preferences using functions like Simulink.sdi.setSubPlotLayout, Simulink.sdi.setRunNamingRule, and Simulink.sdi.setMarkersOn. To restore the Simulation Data Inspector's default settings, use Simulink.sdi.clearPreferences.

Create a Run and View the Data

This example shows how to create a run, add data to it, and then view the data in the Simulation Data Inspector.

Create Data for the Run

Create timeseries objects to contain data for a sine signal and a cosine signal. Give each timeseries object a descriptive name.

time = linspace(0,20,100);

sine_vals = sin(2*pi/5*time);
sine_ts = timeseries(sine_vals,time);
sine_ts.Name = 'Sine, T=5';

cos_vals = cos(2*pi/8*time);
cos_ts = timeseries(cos_vals,time);
cos_ts.Name = 'Cosine, T=8';

Create a Run and Add Data

Use the Simulink.sdi.view function to open the Simulation Data Inspector.

Simulink.sdi.view

To import data into the Simulation Data Inspector from the workspace, create a Simulink.sdi.Run object using the Simulink.sdi.Run.create function. Add information about the run to its metadata using the Name and Description properties of the Run object.

sinusoidsRun = Simulink.sdi.Run.create;
sinusoidsRun.Name = 'Sinusoids';
sinusoidsRun.Description = 'Sine and cosine signals with different frequencies';

Use the add function to add the data you created in the workspace to the empty run.

add(sinusoidsRun,'vars',sine_ts,cos_ts);

Plot the Data in the Simulation Data Inspector

Use the getSignalByIndex function to access Simulink.sdi.Signal objects that contain the signal data. You can use the Simulink.sdi.Signal object properties to specify the line style and color for the signal and plot it in the Simulation Data Inspector. Specify the LineColor and LineDashed properties for each signal.

sine_sig = getSignalByIndex(sinusoidsRun,1);
sine_sig.LineColor = [0 0 1];
sine_sig.LineDashed = '-.';

cos_sig = sinusoidsRun.getSignalByIndex(2);
cos_sig.LineColor = [0 1 0];
cos_sig.LineDashed = '--';

Use the Simulink.sdi.setSubPlotLayout function to configure a 2-by-1 subplot layout in the Simulation Data Inspector plotting area. Then use the plotOnSubplot function to plot the sine signal on the top subplot and the cosine signal on the lower subplot.

Simulink.sdi.setSubPlotLayout(2,1);

plotOnSubPlot(sine_sig,1,1,true);
plotOnSubPlot(cos_sig,2,1,true);

Close the Simulation Data Inspector and Save Your Data

When you have finished inspecting the plotted signal data, you can close the Simulation Data Inspector and save the session to an MLDATX file.

Simulink.sdi.close('sinusoids.mldatx')

Compare Signals Within a Simulation Run

This example uses the slexAircraftExample model to demonstrate how to compare the input and output signals of the control system.

Configure and Simulate the Model

The slexAircraftExample model does not log data. Load the model and mark the input and output signals for logging.

load_system('slexAircraftExample')
Simulink.sdi.markSignalForStreaming('slexAircraftExample/Pilot',1,'on')
Simulink.sdi.markSignalForStreaming('slexAircraftExample/Aircraft Dynamics Model',4,'on')

Simulate the model. The data for the logged signals logs to the Simulation Data Inspector and to the workspace.

out = sim('slexAircraftExample');

Access Simulation Data

Use the Simulation Data Inspector programmatic interface to access the data. The Simulink.sdi.Run.getLatest function returns the most recently created run in the Simulation Data Inspector repository. Use the getSignalIDByIndex function to access the signal IDs for the logged signals.

aircraftRun = Simulink.sdi.Run.getLatest;

signalID1 = getSignalIDByIndex(aircraftRun,1);
signalID2 = getSignalIDByIndex(aircraftRun,2);

Specify Tolerance Values

You can specify tolerance values to use in the comparison as a property in the logged Simulink.sdi.Signal object. Use the Simulink.sdi.getSignal function to access the Signal object using the signal ID.

signal1 = Simulink.sdi.getSignal(signalID1);
signal1.AbsTol = 0.1;

Compare Signals

Use the Simulink.sdi.compareSignals function to compare the input and output signals. This example uses the isValidSignalID function to verify that both signal IDs are still valid before calling the Simulink.sdi.compareSignals function. A signal ID becomes invalid when the signal is deleted from the Simulation Data Inspector. After the comparison, check the status in the Simulink.sdi.DiffSignalResult object.

if (isValidSignalID(aircraftRun,signalID1) && isValidSignalID(aircraftRun,signalID2))
    sigDiff = Simulink.sdi.compareSignals(signalID1,signalID2);

    match = sigDiff.Status
end
match = 
OutOfTolerance

The comparison result is out of tolerance. You can use the Simulink.sdi.view function to inspect and analyze the comparison results.

Compare and Analyze Simulation Data Programmatically

This example shows how to compare runs of simulation data and then analyze and save the results using the Simulation Data Inspector programmatic interface.

Create Simulation Data

First, create simulation data by simulating a model that logs data. This example uses the ex_sldemo_absbrake model and analyzes the effect of changing the Desired relative slip value.

Load the model. Use the set_param function to specify an initial value for the relative slip and simulate the model.

load_system('ex_sldemo_absbrake')

set_param('ex_sldemo_absbrake/Desired relative slip','Value','0.24')
out_1 = sim('ex_sldemo_absbrake');

Use the set_param function to specify a different value for the relative slip and simulate the model again.

set_param('ex_sldemo_absbrake/Desired relative slip','Value','0.25')
out_2 = sim('ex_sldemo_absbrake');

Compare Runs Using Global Tolerance Values

First, use the Simulink.sdi.getAllRunIDs function to get the run IDs that correspond to the last two simulation runs.

runIDs = Simulink.sdi.getAllRunIDs;
runID1 = runIDs(end - 1);
runID2 = runIDs(end);

Now, use the Simulink.sdi.compareRuns function to compare the runs. Specify a global relative tolerance value of 0.2 and a global time tolerance value of 0.5.

runResult = Simulink.sdi.compareRuns(runID1,runID2,'reltol',0.2,'timetol',0.5);

Check the Summary property of the returned Simulink.sdi.DiffRunResult object.

runResult.Summary
ans = struct with fields:
       OutOfTolerance: 2
      WithinTolerance: 2
            Unaligned: 0
        UnitsMismatch: 0
                Empty: 0
             Canceled: 0
          EmptySynced: 0
     DataTypeMismatch: 0
         TimeMismatch: 0
    StartStopMismatch: 0
          Unsupported: 0

Two signal comparisons within the run were within tolerance, and two were out of tolerance.

Plot Comparison Results

You can use plots to analyze the comparison results. Access the signal result for the Ww signal from the DiffRunResult object that contains the comparison results using the getResultByIndex function. Check the Status property of the Simulink.sdi.DiffSignalResult object.

signalResult_Ww = getResultByIndex(runResult,1)
signalResult_Ww = 
  DiffSignalResult with properties:

             Name: 'yout.Ww'
           Status: OutOfTolerance
          AlignBy: 'Path'
        SignalID1: 127816
        SignalID2: 127862
    MaxDifference: 12.4878
            Sync1: [1x1 timeseries]
            Sync2: [1x1 timeseries]
             Diff: [1x1 timeseries]

signalResult_Ww.Status
ans = 
OutOfTolerance

The Ww signal comparison results are out of tolerance. Plot the difference signal to analyze the result.

figure(1)
plot(signalResult_Ww.Diff)

Save Comparison Results

You can save the comparison results to an MLDATX file to analyze later or to share with a colleague. Use the saveResult function to save the run data and comparison results.

saveResult(runResult,'desiredSlipResults')

The MLDATX file desiredSlipResults is created in the working directory. Use the Simulink.sdi.load function or the open function to view the results in the MLDATX file.

Analyze Simulation Data Using Signal Tolerances

Using the Simulation Data Inspector programmatic interface, you can specify signal tolerance values to use in comparisons. This example uses the slexAircraftExample model and the Simulation Data Inspector to evaluate the effect of changing the time constant for the low-pass filter following the control input.

Configure the Model

Load the model and mark signals of interest for logging. This example logs data for the q and alpha signals.

load_system('slexAircraftExample')

Simulink.sdi.markSignalForStreaming('slexAircraftExample/Aircraft Dynamics Model',3,'on')
Simulink.sdi.markSignalForStreaming('slexAircraftExample/Aircraft Dynamics Model',4,'on')

Run Simulations

Run simulations with different low-pass filter time constants to generate results to compare. The slexAircraftExample model stores variables associated with the model in the model workspace. To modify the time constant value, access the model workspace and use the assignin function.

out1 = sim('slexAircraftExample');

modelWorkspace = get_param('slexAircraftExample','modelworkspace');
assignin(modelWorkspace,'Ts',1)

out2 = sim('slexAircraftExample');

Access and Compare Simulation Results

Access the simulation results using the Simulation Data Inspector programmatic interface. Each simulation creates a run in the Simulation Data Inspector with a unique run ID. You use the run IDs to compare the simulation results.

runIDs = Simulink.sdi.getAllRunIDs;
runIDTs1 = runIDs(end-1);
runIDTs2 = runIDs(end);

Use the Simulink.sdi.compareRuns function to compare the data from the simulations. Then inspect the Status property of the signal result to see whether the signals fell within the default tolerance of 0.

diffRun1 = Simulink.sdi.compareRuns(runIDTs1,runIDTs2);

sig1Result1 = getResultByIndex(diffRun1,1);
sig2Result1 = getResultByIndex(diffRun1,2);

sig1Result1.Status
ans = 
OutOfTolerance
sig2Result1.Status
ans = 
OutOfTolerance

Compare Runs with Signal Tolerances

By default, signals use 0 for all tolerance values, so the comparison returns out-of-tolerance results when the signals are not identical. To further analyze the effect of the time constant change, specify tolerance values for the signals. You can specify tolerances for a programmatic comparison using the properties of the Simulink.sdi.Signal objects in the runs you compare. The comparison uses the tolerances specified for the baseline Signal object. This example specifies a combination of time and absolute tolerances.

To specify tolerances, first access the Simulink.sdi.Signal objects that correspond to each signal in the runs you want to compare.

run1 = Simulink.sdi.getRun(runIDTs1);
sigID1 = getSignalIDByIndex(run1,1);
sigID2 = getSignalIDByIndex(run1,2);

sig1 = Simulink.sdi.getSignal(sigID1);
sig2 = Simulink.sdi.getSignal(sigID2);

Check the Name property to identify each Signal object.

sig1.Name
ans = 
'q, rad/sec'
sig2.Name
ans = 
'alpha, rad'

Specify an absolute tolerance of 0.1 and a time tolerance of 0.6 for the q signal using the AbsTol and TimeTol properties of the q signal object in the baseline run.

sig1.AbsTol = 0.1;
sig1.TimeTol = 0.6;

Specify an absolute tolerance of 0.2 and a time tolerance of 0.8 for the alpha signal using the AbsTol and TimeTol properties of the alpha signal object in the baseline run.

sig2.AbsTol = 0.2;
sig2.TimeTol = 0.8;

Compare the runs again and access the results.

diffRun2 = Simulink.sdi.compareRuns(runIDTs1,runIDTs2);
sig1Result2 = getResultByIndex(diffRun2,1);
sig2Result2 = getResultByIndex(diffRun2,2);

Check the Status property of each signal to determine whether the comparison results fell within the specified tolerances.

sig1Result2.Status
ans = 
WithinTolerance
sig2Result2.Status
ans = 
WithinTolerance

Create a Report for Plotted Signals

Create a report that contains information about and plots of the signals plotted in the Inspect pane of the Simulation Data Inspector. By default, the report contains the metadata displayed for signals in the table on the Inspect pane. This example shows how to specify which metadata to include in the report.

Load the Session File

This example populates the Simulation Data Inspector with data and plotted signals by loading a saved session file. A session file contains the signal data as well as information about plotted signals and plot layout. Load the session file.

Simulink.sdi.load('ex_sldemo_absbrake_slp_Ww.mldatx');

Create a Report for Plotted Signals

The report includes plots and metadata for the plotted signals. By default, the report includes the metadata that corresponds to the columns displayed in the signals table on the Inspect pane. You can include more data in the report by displaying more columns in the Inspect pane. You can also specify the information you want in the report programmatically using the 'ColumnsToReport' name-value pair and the enumeration class Simulink.sdi.SignalMetaData.

signalMetadata = [Simulink.sdi.SignalMetaData.Run, ...
    Simulink.sdi.SignalMetaData.Line, ... 
    Simulink.sdi.SignalMetaData.BlockName, ...
    Simulink.sdi.SignalMetaData.SignalName];

Simulink.sdi.report('ReportType','Inspect', 'ReportOutputFile', ...
    'absbrake_slp_report.html', 'ColumnsToReport', signalMetadata);

The report shows tables of the metadata for plotted signals, organized by run, above a snapshot of the plot.

Save and Restore a Set of Logged Signals

This example shows how to use the Simulink.HMI.InstrumentedSignals object to save a set of logged signals to restore after running a simulation with a different signal logging configuration.

Save the Initial Signal Logging Configuration

This example uses the sldemo_fuelsys model, which is configured to log 10 signals. Open the model and use the get_param function to get a Simulink.HMI.InstrumentedSignals object representing the signal logging configuration.

load_system sldemo_fuelsys

initSigs = get_param('sldemo_fuelsys','InstrumentedSignals');

You can save the initial signal logging configuration in a MAT-file for later use.

save initial_instSigs.mat initSigs

Remove All Logging Badges

To return to a baseline of no logged signals, you can use the set_param function to remove all logging badges from signals in your model. Then, you can easily select a different configuration of signals to log in the Simulink™ Editor or using the Simulink.sdi.markSignalForStreaming function.

set_param('sldemo_fuelsys','InstrumentedSignals',[])

Restore Saved Logging Configuration

After working with a different set of logged signals, you can restore a saved configuration using the Simulink.HMI.InstrumentedSignals object. For example, if you saved the logging configuration to a MAT-file, you can load the MAT-file contents into the workspace and use the set_param function to restore the previously saved logging configuration.

load initial_instSigs.mat

set_param('sldemo_fuelsys','InstrumentedSignals',initSigs)

See Also

Related Topics