Extract and store results from multibody simulations with Altair Compose

MotionSolve plot files (.plt) are produced when running multibody simulations. These files contain results such as displacements, velocities and accelerations (and much more) from the bodies present in the file.


A single PLT file can contain dozens of different datatypes (data like displacement, force, torque, etc.), requests (entities present in the model from which data is to be extracted. E.g., a specific piece in an assembly) and components (e.g., X, Y, Z, magnitude, etc.), so peering into a file manually to look at every produced result can be lengthy.


With Altair Compose and its dedicated libraries for reading and handling CAE files (both from Altair and third-party products) reading and storing (with or without previously post-processing data) all the contents from a PLT file into a CSV can be done in a few steps. Let’s look at how to do it:


First the user is prompted for the PLT file to read and the directory in which to write data using uigetfile and uigetdir. The desired directory is created with mkdir.


close all, clear, clc


% Choose plt file and desired location for outputs

[name, filepath, ~] = uigetfile('*.plt', 'Please select file location');

filename = strcat(filepath, name);


parentDir = uigetdir(cd, 'Please select output directory location');



% Create directory for containing all datatype outputs

outputDir = name(1:end-4);

mkdir(cd, outputDir);


Next, a list of all available data types in the file is created using gettypelist, and the time vector from the simulation is extracted with readcae. squeeze is used to avoid matrices with redundant dimensions, e.g., dimension with just one element, like a 2x2x1 3-dimensional matrix (which would be turned into a 2x2 2-dimensional matrix).


% Get all available datatypes

datatypes = gettypelist(filename);


% Get time

t = squeeze(readcae(filename, 'Time', 'Time', 'Time', [], 1));


Afterwards, a for loop can be used to cycle through all present data types (except “Time” and “Index”, as we don’t care about these in our results). For each data type, a subdirectory is created at the output location and its corresponding requests and components are extracted into lists with the help of getreqlist and getcomplist, respectively.


% Go through each datatype

for i = 1:numel(datatypes)


      % Skip if datatype is "Time" or "Index"

      if strcmp(datatypes{i}, 'Time') || strcmp(datatypes{i}, 'Index')




      % Current datatype

      datatype = datatypes{i};


      % Create directory for containing all requests in this datatype

      mkdir(['./' outputDir], datatype);

      currentOutputDir = ['./' outputDir '/' datatype];


      % Get requests and components for this datatype

      requests = getreqlist(filename, datatype);

      components = getcomplist(filename, datatype);


For each request present in each datatype, a CSV file is created. This file will store the results present in the PLT file that correspond to this request and all its components. The output file’s name is set using strcat for string concatenation (e.g. request1.csv) and fopen created the file and opens it in write mode.


      % Go through each request

      for j = 1:numel(requests)


            % Current request

            request = requests{j};


            % Matrix for storing data from all components

            data = t;


            % Open csv to write data

            outputFile = strcat(currentOutputDir, '/', request(5:end), '.csv');

            [fid msg] = fopen(outputFile, 'w');


Each component in the current request is extracted from the file and stored in a data matrix, in which all components, and the time vector, occupy a column.


            % Go through each component in this request

            for k = 1:numel(components)


                  % Current component

                  component = components{k};

                  % Read data for current request & component

                  data = [data, squeeze(readcae(filename, datatype, request, component, [], 1))];




Having all relevant data from the current request, functions from the Compose FileIO library make it straightforward to put the results in a CSV file. Note that both functions are used because csvwrite cannot write string values into a file, so the headers are written afterwards using xlswrite.


            % First line saved for headers

            headers = NaN(1, numel(components) + 1);


            % Write data & close current csv

            csvwrite(fid, [headers; data]);



            % Write component names as headers (xls functions are required to write strings into files)

            tcell{1} = 'Time';

            headers = [tcell components];


            % Open, write headers & close file

            fid = xlsopen(outputFile, 1);

            xlswrite(fid, headers);







And that’s it! With a simple script, all available results are extracted from a PLT file and stored in an ordered way, in a file format readable by anyone, which can be further used in a CAE workflow.