Title: Creating Matlab files
Question: Matlab is a versatil tool to analyse and plot / display data of all kind of measurements. In our lab we use Delphi console applications to batch preprocess the raw measurement data and Delphi vcl application to control Matlab as a data analysis and plotting engine. After preprocessing the data is written in Matlab
readable files for further analysis. The core routines to produce such Matlab files are presented here as a unit uMat.
As an example - to give you an idea of how to use the routines - I present you a MatLab file structure we currently use, and the Delphi type's and var's and code necessary to create such a file.
Answer:
{---------------------------------------------------------------------------
u M a t
a library of basic procedures necessary to create Matlab files
For a complete description of the Matlab 5 format see
http://www.mathworks.com/access/helpdesk/help/pdf_doc/matlab/matfile_format.pdf
---------------------------------------------------------------------------
Author: F. Honegger
Balance International Innovations GmbH Switzerland
Edit History:
Who When What
--------------------------------------------------------------------------
FHO 08.12.2001 Creation
Dependencies on other units: see uses clause
Important:
compile with $N+
--------------------------------------------------------------------------}
unit uMat;
interface
uses
Classes, Sysutils;
const
miInt8 = 01;
miUInt8 = 02;
miInt16 = 03;
miUInt16 = 04;
miInt32 = 05;
miUInt32 = 06;
miSingle = 07;
miDouble = 09;
miInt64 = 12;
miuInt64 = 13;
miMatrix = 14;
mxCellC = 1;
mxStructC = 2;
mxObjectC = 3;
mxCharC = 4;
mxSparseC = 5;
mxDoubleC = 6;
mxSingleC = 7;
mxInt8C = 8;
mxUInt8C = 9;
mxInt16C = 10;
mxUInt16C = 11;
mxInt32C = 12;
mxUInt32C = 13;
type
TMtlIntegerVector=array of Integer;
TMtlSmallIntVector=array of SmallInt;
TMtlWordVector=array of Word;
TMtlByteVector = array of byte;
TMtlDoubleVector =array of double;
TMtlSingleVector =array of Single;
TMtlIntegerMatrix=array of TMtlIntegerVector;
TMtlSmallIntMatrix=array of TMtlSmallIntVector;
TMtlWordMatrix=array of TMtlWordVector;
TMtlByteMatrix = array of TMtlByteVector;
TMtlDoubleMatrix =array of TMtlDoubleVector;
TMtlSingleMatrix =array of TMtlSingleVector;
EMtlHeaderError = class(Exception) end;
procedure WriteMTLFileHeader(TargetStream:TStream);
procedure WriteMtlTag(TargetStream:TStream;aDataType,aSize:Cardinal);
procedure PrimeMtlTag(TargetStream:TStream;aDataType:Cardinal);
procedure CompleteMtlTag;
procedure WriteMtlArrayFlags(TargetStream:TStream;aClass,aFlags:byte);
procedure WriteMtlDimmensions(TargetStream:TStream;aDim:Array of Integer);
procedure WriteMtlStrucNames(TargetStream:TStream;const aNam:array of string);
function GetVecDim(asRow:boolean;size:integer):TMtlIntegerVector;
function GetMatDim(rows,colums:integer):TMtlIntegerVector;
procedure WriteMtlName(TargetStream:TStream;const aName:String);
procedure WriteMtlVarDouble(TargetStream:TStream; const name: String;const a:double);
procedure WriteMtlVecVarDouble(asRow:boolean;TargetStream:TStream; const name: String;const a:array of double);
procedure WriteMtlMatVarDouble(TargetStream:TStream; const name: String;const a:array of TMtlDoubleVector);
procedure WriteMtlVarSingle(TargetStream:TStream; const name: String;const a:Single);
procedure WriteMtlVecVarSingle(asRow:boolean;TargetStream:TStream; const name: String;const a:array of Single);
procedure WriteMtlMatVarSingle(TargetStream:TStream; const name: String;const a:array of TMtlSingleVector);
procedure WriteMtlVarInteger(TargetStream:TStream; const name: String;const a:Integer);
procedure WriteMtlVecVarInteger(asRow:boolean;TargetStream:TStream; const name: String;const a:array of Integer);
procedure WriteMtlMatVarInteger(TargetStream:TStream; const name: String;const a:array of TMtlIntegerVector);
procedure WriteMtlVarSmallInt(TargetStream:TStream; const name: String;const a:SmallInt);
procedure WriteMtlVecVarSmallInt(asRow:boolean;TargetStream:TStream; const name: String;const a:array of SmallInt);
procedure WriteMtlMatVarSmallInt(TargetStream:TStream; const name: String;const a:array of TMtlSmallIntVector);
procedure WriteMtlVarWord(TargetStream:TStream; const name: String;const a:Word);
procedure WriteMtlVecVarWord(asRow:boolean;TargetStream:TStream; const name: String;const a:array of Word);
procedure WriteMtlMatVarWord(TargetStream:TStream; const name: String;const a:array of TMtlWordVector);
procedure WriteMtlVarByte(TargetStream:TStream; const name: String;const a:Byte);
procedure WriteMtlVecVarByte(asRow:boolean;TargetStream:TStream; const name: String;const a:array of Byte);
procedure WriteMtlMatVarByte(TargetStream:TStream; const name: String;const a:array of TMtlByteVector);
procedure WriteMtlVarString(TargetStream:TStream; const name: String;const a:String);
procedure WriteMtlVecVarString(TargetStream:TStream; const name: String;const a:array of String);
implementation
Uses
Windows, Math;
function PadCh(const s : string; Ch : Char; Len: Integer) : string;
{-Return a string right-padded to length len with ch}
var
Slen: Integer;
begin
Result:=s;
SLen:=Length(s);
if SLen SetLength(Result,Len);
FillChar(Result[Succ(Slen)], Len-Slen, Ch);
end;
end;
function Pad(const s : string; Len: Integer) : string;
{-Return a string right-padded to length len with blanks}
begin
Pad := PadCh(s, ' ', Len);
end;
procedure WriteMTLFileHeader(TargetStream:TStream);
const
cHeaderText='MATLAB 5.0 MAT-file, Platform: PCWIN, Created on: %s %s by %s';
cID=$4d490100;
var
s:string;
i:dword;
dnow:TDateTime;
begin
dnow:=Now;
s:=pad(format(cHeaderText,[TimeToStr(dnow),DateToStr(dnow),ExtractFileName(paramstr(0))]),124);
TargetStream.Write(s[1],length(s));
i:=cId;
TargetStream.Write(i,SizeOf(i));
end;
Type
TMtlTag=packed record
DataType,
Size:cardinal;
end;
TMtlArrayFlags=packed record
mxClass:Byte;
Flags:Byte;
Undef:Word;
Undefined:cardinal;
end;
procedure WriteMtlTag(TargetStream:TStream;aDataType,aSize:Cardinal);
var
MtlTag:TMtlTag;
begin
with MtlTag do begin
DataType :=aDataType;
Size :=aSize;
end;
TargetStream.Write(MtlTag,SizeOf(MtlTag));
end;
type
TTagState=record
FilPos:integer;
DatTyp:integer;
TrgtStream:Tstream;
end;
var
MtlTagStateStack:array of TTagState;
procedure PrimeMtlTag(TargetStream:TStream;aDataType:Cardinal);
var
slen:integer;
begin
slen:=length(MtlTagStateStack);
SetLength(MtlTagStateStack,slen+1);
with MtlTagStateStack[slen] do begin
FilPos:=TargetStream.Position;
DatTyp:=aDataType;
TrgtStream:=TargetStream;
end;
WriteMtlTag(TargetStream,aDataType,0);
end;
procedure CompleteMtlTag;
var
nFilePos:integer;
slen:integer;
begin
if Length(MtlTagStateStack)=0 then
raise EMtlHeaderError.Create('PrimeMtlTag must be called before CompleteMtlTag');
slen:=Length(MtlTagStateStack)-1;
with MtlTagStateStack[slen] do begin
nFilePos:=TrgtStream.Position;
TrgtStream.Seek(FilPos,soFromBeginning);
WriteMtlTag(TrgtStream,DatTyp,nFilePos-FilPos-8);
TrgtStream.Seek(nFilePos,soFromBeginning);
TrgtStream:=nil;
end;
SetLength(MtlTagStateStack,slen);
end;
procedure WriteMtlCompressedTag(TargetStream:TStream;aDataType,aSize:cardinal; const aData);
var
MtlTag:TMtlTag;
begin
with MtlTag do begin
DataType :=asize shl 16 + aDataType;
Fillchar(Size,SizeOf(Size),0);
move(aData,Size,aSize);
end;
TargetStream.Write(MtlTag,SizeOf(MtlTag));
end;
procedure WriteMtlArrayFlags(TargetStream:TStream;aClass,aFlags:byte);
var
AMtlFlags:TMtlArrayFlags;
MtlTag:TMtlTag;
begin
with MtlTag do begin
DataType :=miUint32;
Size :=8;
end;
TargetStream.Write(MtlTag,SizeOf(MtlTag));
FillChar(AMtlFlags,SizeOf(AMtlFlags),0);
with AMtlFlags do begin
Flags :=aFlags;
mxClass:=aClass;
end;
TargetStream.Write(AMtlFlags,SizeOf(AMtlFlags));
end;
procedure WriteMtlPadding(TargetStream:TStream;aStrucSize:cardinal);
var
Padding:array of byte;
padSize:integer;
begin
//pad to mod 8
padSize:=aStrucSize mod 8;
if padSize=0 then exit;
SetLength(Padding,8-padSize);
FillChar(Padding[0],length(Padding),0);
TargetStream.Write(Padding[0],length(Padding));
end;
procedure WriteMtlDimmensions(TargetStream:TStream;aDim:Array of Integer);
var
MtlTag:TMtlTag;
begin
with MtlTag do begin
DataType :=miInt32;
Size :=SizeOf(Integer)*length(aDim);
end;
TargetStream.Write(MtlTag,SizeOf(MtlTag));
TargetStream.Write(aDim[0],MtlTag.Size);
WriteMtlPadding(TargetStream,MtlTag.Size);
end;
procedure WriteMtlStrucNames(TargetStream:TStream;const aNam:array of string);
var
MtlTag:TMtlTag;
s:string;
i:integer;
begin
with MtlTag do begin
DataType :=4 shl 16 + miInt32;
Size :=32;
end;
//strucname size
TargetStream.Write(MtlTag,SizeOf(MtlTag));
with MtlTag do begin
DataType :=miInt8;
Size :=length(anam)*32;
end;
//size of name block
TargetStream.Write(MtlTag,SizeOf(MtlTag));
SetLength(s,32);
//names
for i:=0 to length(anam)-1 do begin
fillchar(s[1],length(s),0);
move(anam[i][1],s[1],min(length(anam[i]),32));
TargetStream.Write(s[1],length(s));
end;
end;
procedure WriteMtlName(TargetStream:TStream;const aName:String);
var
MtlTag:TMtlTag;
begin
with MtlTag do begin
if length(aName) WriteMtlCompressedTag(TargetStream,miInt8,length(aName),aName[1]);
Exit;
end else begin
DataType :=miInt8;
Size :=SizeOf(Byte)*Length(aName);
end;
end;
TargetStream.Write(MtlTag,SizeOf(MtlTag));
TargetStream.Write(aName[1],MtlTag.Size);
WriteMtlPadding(TargetStream,MtlTag.Size);
end;
procedure WriteMtlVecDouble(TargetStream:TStream; a:array of double);
var
Size:cardinal;
begin
Size:=length(a)*SizeOf(Double);
WriteMtlTag(TargetStream,miDouble,Size);
TargetStream.Write(a[0],Size);
end;
procedure WriteMtlMatDouble(TargetStream:TStream; a:array of TMtlDoubleVector);
var
Size:cardinal;
i:integer;
begin
Size:=length(a[0])*length(a)*SizeOf(Double);
WriteMtlTag(TargetStream,miDouble,Size);
Size:=length(a[0])*SizeOf(Double);
for i:=0 to length(a)-1 do
TargetStream.Write(a[i][0],Size);
end;
procedure WriteMtlVecSingle(TargetStream:TStream; a:array of single);
var
Size:cardinal;
begin
Size:=length(a);
if Size WriteMtlCompressedTag(TargetStream,miSingle,Size*SizeOf(a[0]),a[0]);
exit;
end;
Size:=Size*SizeOf(Single);
WriteMtlTag(TargetStream,miSingle,Size);
TargetStream.Write(a[0],Size);
WriteMtlPadding(TargetStream,Size);
end;
procedure WriteMtlMatSingle(TargetStream:TStream; a:array of TMtlSingleVector);
var
TotSize,VecSize:cardinal;
i:integer;
begin
TotSize:=length(a[0])*length(a)*SizeOf(Single);
WriteMtlTag(TargetStream,miSingle,TotSize);
VecSize:=length(a[0])*SizeOf(Single);
for i:=0 to length(a)-1 do
TargetStream.Write(a[i][0],VecSize);
WriteMtlPadding(TargetStream,TotSize);
end;
procedure WriteMtlVecInteger(TargetStream:TStream; a:array of integer);
var
Size:cardinal;
begin
Size:=length(a);
if Size WriteMtlCompressedTag(TargetStream,miInt32,Size*SizeOf(a[0]),a[0]);
exit;
end;
Size:=Size*SizeOf(Integer);
WriteMtlTag(TargetStream,miInt32,Size);
TargetStream.Write(a[0],Size);
WriteMtlPadding(TargetStream,Size);
end;
procedure WriteMtlMatInteger(TargetStream:TStream; a:array of TMtlIntegerVector);
var
TotSize,VecSize:cardinal;
i:integer;
begin
TotSize:=length(a[0])*length(a)*SizeOf(Integer);
WriteMtlTag(TargetStream,miInt32,TotSize);
VecSize:=length(a[0])*SizeOf(Integer);
for i:=0 to length(a)-1 do
TargetStream.Write(a[i][0],VecSize);
WriteMtlPadding(TargetStream,TotSize);
end;
procedure WriteMtlVecSmallInt(TargetStream:TStream; a:array of Smallint);
var
Size:cardinal;
begin
Size:=length(a);
if Size WriteMtlCompressedTag(TargetStream,miInt16,Size*SizeOf(a[0]),a[0]);
exit;
end;
Size:=Size*SizeOf(SmallInt);
WriteMtlTag(TargetStream,miInt16,Size);
TargetStream.Write(a[0],Size);
WriteMtlPadding(TargetStream,Size);
end;
procedure WriteMtlMatSmallInt(TargetStream:TStream; a:array of TMtlSmallIntVector);
var
TotSize,VecSize:cardinal;
i:integer;
begin
TotSize:=length(a[0])*length(a)*SizeOf(SmallInt);
WriteMtlTag(TargetStream,miInt16,TotSize);
VecSize:=length(a[0])*SizeOf(SmallInt);
for i:=0 to length(a)-1 do
TargetStream.Write(a[i][0],VecSize);
WriteMtlPadding(TargetStream,TotSize);
end;
procedure WriteMtlVecWord(TargetStream:TStream; a:array of Word);
var
Size:cardinal;
begin
Size:=length(a);
if Size WriteMtlCompressedTag(TargetStream,miUInt16,Size*SizeOf(a[0]),a[0]);
exit;
end;
Size:=Size*SizeOf(SmallInt);
WriteMtlTag(TargetStream,miUInt16,Size);
TargetStream.Write(a[0],Size);
WriteMtlPadding(TargetStream,Size);
end;
procedure WriteMtlMatWord(TargetStream:TStream; a:array of TMtlWordVector);
var
TotSize,VecSize:cardinal;
i:integer;
begin
TotSize:=length(a[0])*length(a)*SizeOf(Word);
WriteMtlTag(TargetStream,miUInt16,TotSize);
VecSize:=length(a[0])*SizeOf(Word);
for i:=0 to length(a)-1 do
TargetStream.Write(a[i][0],VecSize);
WriteMtlPadding(TargetStream,TotSize);
end;
procedure WriteMtlVecByte(TargetStream:TStream; a:array of byte);
var
Size:cardinal;
begin
Size:=length(a)*SizeOf(a[0]);
if Size WriteMtlCompressedTag(TargetStream,miUInt8,Size*SizeOf(a[0]),a[0]);
exit;
end;
Size:=Size*SizeOf(Byte);
WriteMtlTag(TargetStream,miUInt8,Size);
TargetStream.Write(a[0],Size);
WriteMtlPadding(TargetStream,Size);
end;
procedure WriteMtlMatByte(TargetStream:TStream; a:array of TMtlByteVector);
var
TotSize,VecSize:cardinal;
i:integer;
begin
TotSize:=length(a[0])*length(a)*SizeOf(Byte);
WriteMtlTag(TargetStream,miUInt8,TotSize);
VecSize:=length(a[0])*SizeOf(Byte);
for i:=0 to length(a)-1 do
TargetStream.Write(a[i][0],VecSize);
WriteMtlPadding(TargetStream,TotSize);
end;
procedure WriteMtlVecString(TargetStream:TStream; a:string);
var
Size:cardinal;
i:integer;
wa:array of word;
begin
SetLength(wa,length(a));
for i:=0 to length(wa)-1 do wa[i]:=ord(a[i+1]);
Size:=length(a)*SizeOf(word);
if Size WriteMtlCompressedTag(TargetStream,miUInt16,Size,wa[0]);
exit;
end;
WriteMtlTag(TargetStream,miUInt16,Size);
TargetStream.Write(wa[0],Size);
WriteMtlPadding(TargetStream,Size);
end;
function GetVecDim(asRow:boolean;size:integer):TMtlIntegerVector;
begin
SetLength(Result,2);
if asRow then begin
Result[0]:=1;
Result[1]:=size;
end else begin
Result[0]:=size;
Result[1]:=1;
end;
end;
function GetMatDim(rows,colums:integer):TMtlIntegerVector;
begin
SetLength(Result,2);
Result[0]:=Colums;
Result[1]:=Rows;
end;
procedure WriteMtlVarDouble(TargetStream:TStream; const name: String;const a:double);
begin
WriteMtlVecVarDouble(True,TargetStream,name,a);
end;
procedure WriteMtlVecVarDouble(asRow:boolean;TargetStream:TStream; const name: String;const a:array of double);
begin
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxDoubleC,0);
WriteMtlDimmensions(TargetStream,GetVecDim(asRow,length(a)));
WriteMtlName(TargetStream,name);
WriteMtlVecDouble(TargetStream,a);
CompleteMtlTag;
end;
procedure WriteMtlMatVarDouble(TargetStream:TStream; const name: String;const a:array of TMtlDoubleVector);
begin
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxDoubleC,0);
WriteMtlDimmensions(TargetStream,GetMatDim(length(a),length(a[0])));
WriteMtlName(TargetStream,name);
WriteMtlMatDouble(TargetStream,a);
CompleteMtlTag;
end;
procedure WriteMtlVarSingle(TargetStream:TStream; const name: String;const a:Single);
begin
WriteMtlVecVarSingle(True,TargetStream,name,a);
end;
procedure WriteMtlVecVarSingle(asRow:boolean;TargetStream:TStream; const name: String;const a:array of Single);
begin
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxSingleC,0);
WriteMtlDimmensions(TargetStream,GetVecDim(asRow,length(a)));
WriteMtlName(TargetStream,name);
WriteMtlVecSingle(TargetStream,a);
CompleteMtlTag;
end;
procedure WriteMtlMatVarSingle(TargetStream:TStream; const name: String;const a:array of TMtlSingleVector);
begin
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxSingleC,0);
WriteMtlDimmensions(TargetStream,GetMatDim(length(a),length(a[0])));
WriteMtlName(TargetStream,name);
WriteMtlMatSingle(TargetStream,a);
CompleteMtlTag;
end;
procedure WriteMtlVarInteger(TargetStream:TStream; const name: String;const a:integer);
begin
WriteMtlVecVarInteger(True,TargetStream,name,a);
end;
procedure WriteMtlVecVarInteger(asRow:boolean;TargetStream:TStream; const name: String;const a:array of Integer);
begin
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxInt32C,0);
WriteMtlDimmensions(TargetStream,GetVecDim(asRow,length(a)));
WriteMtlName(TargetStream,name);
WriteMtlVecInteger(TargetStream,a);
CompleteMtlTag;
end;
procedure WriteMtlMatVarInteger(TargetStream:TStream; const name: String;const a:array of TMtlIntegerVector);
begin
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxInt32C,0);
WriteMtlDimmensions(TargetStream,GetMatDim(length(a),length(a[0])));
WriteMtlName(TargetStream,name);
WriteMtlMatInteger(TargetStream,a);
CompleteMtlTag;
end;
procedure WriteMtlVarSmallInt(TargetStream:TStream; const name: String;const a:Smallint);
begin
WriteMtlVecVarSmallInt(True,TargetStream,name,a);
end;
procedure WriteMtlVecVarSmallInt(asRow:boolean;TargetStream:TStream; const name: String;const a:array of SmallInt);
begin
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxInt16C,0);
WriteMtlDimmensions(TargetStream,GetVecDim(asRow,length(a)));
WriteMtlName(TargetStream,name);
WriteMtlVecSmallInt(TargetStream,a);
CompleteMtlTag;
end;
procedure WriteMtlMatVarSmallInt(TargetStream:TStream; const name: String;const a:array of TMtlSmallIntVector);
begin
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxInt16C,0);
WriteMtlDimmensions(TargetStream,GetMatDim(length(a),length(a[0])));
WriteMtlName(TargetStream,name);
WriteMtlMatSmallInt(TargetStream,a);
CompleteMtlTag;
end;
procedure WriteMtlVarWord(TargetStream:TStream; const name: String;const a:Word);
begin
WriteMtlVecVarWord(True,TargetStream,name,a);
end;
procedure WriteMtlVecVarWord(asRow:boolean;TargetStream:TStream; const name: String;const a:array of Word);
begin
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxUInt16C,0);
WriteMtlDimmensions(TargetStream,GetVecDim(asRow,length(a)));
WriteMtlName(TargetStream,name);
WriteMtlVecWord(TargetStream,a);
CompleteMtlTag;
end;
procedure WriteMtlMatVarWord(TargetStream:TStream; const name: String;const a:array of TMtlWordVector);
begin
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxUInt16C,0);
WriteMtlDimmensions(TargetStream,GetMatDim(length(a),length(a[0])));
WriteMtlName(TargetStream,name);
WriteMtlMatWord(TargetStream,a);
CompleteMtlTag;
end;
procedure WriteMtlVarByte(TargetStream:TStream; const name: String;const a:Byte);
begin
WriteMtlVecVarByte(True,TargetStream,name,a);
end;
procedure WriteMtlVecVarByte(asRow:boolean;TargetStream:TStream; const name: String;const a:array of Byte);
begin
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxUInt8C,0);
WriteMtlDimmensions(TargetStream,GetVecDim(asRow,length(a)));
WriteMtlName(TargetStream,name);
WriteMtlVecByte(TargetStream,a);
CompleteMtlTag;
end;
procedure WriteMtlMatVarByte(TargetStream:TStream; const name: String;const a:array of TMtlByteVector);
begin
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxUInt8C,0);
WriteMtlDimmensions(TargetStream,GetMatDim(length(a),length(a[0])));
WriteMtlName(TargetStream,name);
WriteMtlMatByte(TargetStream,a);
CompleteMtlTag;
end;
procedure WriteMtlVarString(TargetStream:TStream; const name: String;const a:String);
begin
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxCharC,0);
WriteMtlDimmensions(TargetStream,GetVecDim(True,length(a)));
WriteMtlName(TargetStream,name);
WriteMtlVecString(TargetStream,a);
CompleteMtlTag;
end;
procedure WriteMtlVecVarString(TargetStream:TStream; const name: String;const a:array of String);
var
i:integer;
begin
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxCellC,0);
WriteMtlDimmensions(TargetStream,GetVecDim(False,length(a)));
WriteMtlName(TargetStream,name);
for i:=0 to length(a)-1 do begin
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxCharC,0);
WriteMtlDimmensions(TargetStream,GetVecDim(True,length(a[i])));
WriteMtlName(TargetStream,'');
WriteMtlVecString(TargetStream,a[i]);
CompleteMtlTag;
end;
CompleteMtlTag;
end;
end.
//----------- end of unit, cut here ------------------------------------------
Example
=======
Matlab View of the file to be produced
======================================
1. Variable enumeration:
The following variables are hold within the file
adc mrk stat trials
exclude samprate stim ws
2. Variable descriptions:
2.1. adc: ADC Channel descriptions
adc has the structure of an array of channel description.
A channel description is a record consisting of
n: the channel name
u: the channel unit of measure
sf: a scaling factor to scale to u
access the items as follows (i,k,10 being channel indices)
adc(1).n
adc(k).u
adc(10).sf etc.
2.2. mrk: Marker description
mrk is a structure consisting of a string array and unit of measure string channel description.
n: array with the marker names name
u: string with the unit of measure
access the items as follows (1,i being marker indices)
mrk.n(1)
mrk.n(i)
mrk.u etc.
2.3. samprate: Frequency descriptions
samprate is structure consisting of the following items
adc, a structure describing the adc sampling rates
mrk, a structure describing the marker sampling rates
numtrials, the number of trials of the experiment
adc and mrk have the same substructur that consists of to numbers
frame, the sampling frequency
scan, the inter channel/marker collection frequency
access the items as follows
samprate.numtrials
samprate.adc.frame
samprate.mrk.scan etc.
2.4. trials: Original data
trials is an array of the following trial structure
adc, a matrix with the adc channel values, each row is a channel
dig, a integer row vector with the digital output information
of the ODAU
mrk, an array of the following structure for each marker
x,y,z, row vectors with the 3 space components of the marker
Nan, a integer row vector with indices of missing data points
of the marker
Spike, a integer row vector with indices of the data points
identified as being part of a spike
adcfname, a string with the corresponding ODAU source file name
mrkfname, a string with the corresponding OptoTrak source file name
adcdattim, date and time as within the ODAU source file
mrkdattim, date and time as within the OptpTrak source file
access the items as follows (i,k being trial indices, m,n being marker/channel indices and h,j being point indices)
trials(i).mrkdattim
trials(k).adc(m,j)
trials(i).mrk(m).x
trials(i).mrk(m).y(j)
trials(k).mrk.Nan etc.
2.5. exclude: Data to be excluded
exclude is structured in three parts
trial, is an integer array of the trials to be excluded completely
adc, is an array of the following structure
no, is the index of the channel
trial, is a integer array of the trials to be excluded for the
corresponding channel.
mrk, is an array of the same structure as adc
no, is the index of the marker
trial, is a integer array of the trials to be excluded for the
corresponding marker.
2.6. stat: Average data
stat is a structure with the following structures
adc, average ODAU data
adc itself is a array of structure, where
mean, is a matrix containing the average channels as rows
std, is a matrix containing the corresponding std, and
count, an integer array holds the number of trials within the
means
mrk, averaged OptoTrak data
mrk itself is a matrix of structure, where the markers are aligned
in a row for each trial.
mean, is a structure of three row vectors x,y,z. The same structure has
std, the corresponding stds.
count, is the number of trials within the mean
access the items as follows (i,k being stimulus indices, m,n being marker/channel indices and h,j being point indices)
stat.adc(i).mean(m,j)
stat.adc(i).std(m,j)
stat.adc(i).std(m,j)
stat.adc(i).count(m)
stat.mrk(i,m).mean.x(j)
stat.mrk(k.n).std.z(h)
stat.mrk(k.n).count etc.
2.7. stim: The description of the stimuli
stim is an array of the following structure that holds for each stimulus the following information.
name, a string holding, then name of the stimulus
trials,an array of integer holding the numbers of the trials that
correspond to the stimulus
access the items as follows (i,k being stimulus indices)
stim(j).name
stim(k).trials(:), etc.
2.8. ws: Average built information
ws is a structure with the following string information
name, the name of the workstation the averaging was done
user, the user who was logged in while averaging
datim, date and time when average was done
description, the description string from the .ndo file (subject name)
Delphi view
===========
Sample code to produce a matlab .mat file of the above structure that can be loaded with
the standard matlab load command
Type declaration necessary to build corresponding delphi data memory structures.
type
TADCDesc= record
n:String;
u:String;
sf:double;
end;
TStimDesc= record
Name:string;
Trials:array of integer;
end;
TMarkerChannel=record
x:TMtlSingleVector;
y:TMtlSingleVector;
z:TMtlSingleVector;
Nan:TMtlIntegerVector;
Spike:TMtlIntegerVector;
end;
TMarkerTrial=array of TMarkerChannel;
TTrial= record
adc:TMtlSingleMatrix;
mrk:TMarkerTrial;
dig:TMtlWordVector;
voltageFilNam:String;
markerFilNam:String;
adcDateTime:String;
mrkDateTime:String;
end;
TAdcTrialStat= record
mean: TMtlDoubleMatrix;
std: TMtlDoubleMatrix;
count: TMtlIntegerVector;
end;
TMarkerPos = record
x:TMtlDoubleVector;
y:TMtlDoubleVector;
z:TMtlDoubleVector;
end;
TMarkerStat= record
mean:TMarkerPos;
std:TMarkerPos;
count: Integer;
end;
TMarkerTrialStat= Array of TMarkerStat;
TSampRate=record
frame: integer;
scan: integer;
end;
TSampRates=record
chan:TSampRate;
mrk:TSampRate;
NumTrials:integer;
end;
TMrkDesc=record
n:Array Of String;
u:string;
end;
The variables that are used to hold the data.
var
//odau
ADCDesc: array of TADCDesc;
StimDesc: array of TStimDesc;
AdcTrialStat: array of TAdcTrialStat;
MrkTrialStat: array of TMarkerTrialStat;
TrialArray: array of Ttrial;
SampRate: TsampRates;
Description: String;
//opto
MrkDesc: TMrkDesc;
//both
ExcludeList: TExtendedExcludeList;
procedure CreateMatlabFile(const fname:string;EstMinimalSize:integer);
var
ErrMes:String;
k,i,iErr:Integer;
TargetStream:TMemoryStream;
StrucNames:array of string;
begin
TargetStream:=TMemoryStream.Create;
TargetStream.SetSize(EstMinimalSize);
try
WriteMTLFileHeader(TargetStream);
//ws info
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxStructC,0);
WriteMtlDimmensions(TargetStream,GetMatDim(1,1));
WriteMtlName(TargetStream,'ws');
SetLength(StrucNames,4);
StrucNames[0]:='name';
StrucNames[1]:='user';
StrucNames[2]:='datim';
StrucNames[3]:='description';
WriteMtlStrucNames(TargetStream,StrucNames);
WriteMtlVarString(TargetStream,'',ComputerName);
WriteMtlVarString(TargetStream,'',UserName);
WriteMtlVarString(TargetStream,'',DateTimeToStr(now));
WriteMtlVarString(TargetStream,'',Description);
CompleteMtlTag;
//AdcDesc Structure
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxStructC,0);
WriteMtlDimmensions(TargetStream,GetMatDim(1,length(AdcDesc)));
WriteMtlName(TargetStream,'adc');
SetLength(StrucNames,3);
StrucNames[0]:='n';
StrucNames[1]:='u';
StrucNames[2]:='sf';
WriteMtlStrucNames(TargetStream,StrucNames);
for i:=0 to length(AdcDesc)-1 do begin
WriteMtlVarString(TargetStream,'',AdcDesc[i].n);
WriteMtlVarString(TargetStream,'',AdcDesc[i].u);
WriteMtlVarDouble(TargetStream,'',AdcDesc[i].sf);
end;
CompleteMtlTag;
//MrkDesc Structure
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxStructC,0);
WriteMtlDimmensions(TargetStream,GetMatDim(1,1));
WriteMtlName(TargetStream,'mrk');
SetLength(StrucNames,2);
StrucNames[0]:='n';
StrucNames[1]:='u';
WriteMtlStrucNames(TargetStream,StrucNames);
WriteMtlVecVarString(TargetStream,'',MrkDesc.n);
WriteMtlVarString(TargetStream,'',MrkDesc.u);
CompleteMtlTag;
//StimDesc Structure
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxStructC,0);
WriteMtlDimmensions(TargetStream,GetMatDim(1,length(StimDesc)));
WriteMtlName(TargetStream,'stim');
SetLength(StrucNames,2);
StrucNames[0]:='name';
StrucNames[1]:='trials';
WriteMtlStrucNames(TargetStream,StrucNames);
for i:=0 to length(StimDesc)-1 do begin
WriteMtlVarString(TargetStream,'',StimDesc[i].Name);
WriteMtlVecVarInteger(True,TargetStream,'',StimDesc[i].Trials);
end;
CompleteMtlTag;
//SampRate Structure;
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxStructC,0);
WriteMtlDimmensions(TargetStream,GetMatDim(1,1));
WriteMtlName(TargetStream,'samprate');
SetLength(StrucNames,3);
StrucNames[0]:='adc';
StrucNames[1]:='mrk';
StrucNames[2]:='numtrials';
WriteMtlStrucNames(TargetStream,StrucNames);
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxStructC,0);
WriteMtlDimmensions(TargetStream,GetMatDim(1,1));
WriteMtlName(TargetStream,'');
SetLength(StrucNames,2);
StrucNames[0]:='frame';
StrucNames[1]:='scan';
WriteMtlStrucNames(TargetStream,StrucNames);
WriteMtlVarInteger(TargetStream,'',SampRate.chan.frame);
WriteMtlVarInteger(TargetStream,'',SampRate.chan.scan);
CompleteMtlTag;
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxStructC,0);
WriteMtlDimmensions(TargetStream,GetMatDim(1,1));
WriteMtlName(TargetStream,'');
SetLength(StrucNames,2);
StrucNames[0]:='frame';
StrucNames[1]:='scan';
WriteMtlStrucNames(TargetStream,StrucNames);
WriteMtlVarInteger(TargetStream,'',SampRate.mrk.frame);
WriteMtlVarInteger(TargetStream,'',SampRate.mrk.scan);
CompleteMtlTag;
WriteMtlVarInteger(TargetStream,'',SampRate.NumTrials);
CompleteMtlTag;
//Exclude lists
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxStructC,0);
WriteMtlDimmensions(TargetStream,GetMatDim(1,1));
WriteMtlName(TargetStream,'exclude');
SetLength(StrucNames,3);
StrucNames[0]:='trial';
StrucNames[1]:='adc';
StrucNames[2]:='mrk';
WriteMtlStrucNames(TargetStream,StrucNames);
WriteMtlVecVarInteger(true,TargetStream,'',ExcludeList.TrialExclude);
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxStructC,0);
WriteMtlDimmensions(TargetStream,GetMatDim(1,length(ExcludeList.ChannelExclude)));
WriteMtlName(TargetStream,'');
SetLength(StrucNames,2);
StrucNames[0]:='no';
StrucNames[1]:='trial';
WriteMtlStrucNames(TargetStream,StrucNames);
for i:=0 to length(ExcludeList.ChannelExclude)-1 do begin
WriteMtlVarInteger(TargetStream,'',ExcludeList.ChannelExclude[i].ChNo);
WriteMtlVecVarInteger(true,TargetStream,'',ExcludeList.ChannelExclude[i].Exclude);
end;
CompleteMtlTag;
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxStructC,0);
WriteMtlDimmensions(TargetStream,GetMatDim(1,length(ExcludeList.MarkerExclude)));
WriteMtlName(TargetStream,'');
SetLength(StrucNames,2);
StrucNames[0]:='no';
StrucNames[1]:='trial';
WriteMtlStrucNames(TargetStream,StrucNames);
for i:=0 to length(ExcludeList.MarkerExclude)-1 do begin
WriteMtlVarInteger(TargetStream,'',ExcludeList.MarkerExclude[i].ChNo);
WriteMtlVecVarInteger(true,TargetStream,'',ExcludeList.MarkerExclude[i].Exclude);
end;
CompleteMtlTag;
CompleteMtlTag;
//Stat Structure
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxStructC,0);
WriteMtlDimmensions(TargetStream,GetMatDim(1,1));
WriteMtlName(TargetStream,'stat');
SetLength(StrucNames,2);
StrucNames[0]:='adc';
StrucNames[1]:='mrk';
WriteMtlStrucNames(TargetStream,StrucNames);
//adc
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxStructC,0);
WriteMtlDimmensions(TargetStream,GetMatDim(1,length(AdcTrialStat)));
WriteMtlName(TargetStream,'');
SetLength(StrucNames,3);
StrucNames[0]:='mean';
StrucNames[1]:='std';
StrucNames[2]:='count';
WriteMtlStrucNames(TargetStream,StrucNames);
for i:=0 to length(AdcTrialStat)-1 do begin
WriteMtlMatVarDouble(TargetStream,'',AdcTrialStat[i].mean);
WriteMtlMatVarDouble(TargetStream,'',AdcTrialStat[i].std);
WriteMtlVecVarInteger(false,TargetStream,'',AdcTrialStat[i].count);
end;
CompleteMtlTag;
//mrk
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxStructC,0);
WriteMtlDimmensions(TargetStream,GetMatDim(Length(MrkDesc.N),length(MrkTrialStat)));
WriteMtlName(TargetStream,'');
SetLength(StrucNames,3);
StrucNames[0]:='mean';
StrucNames[1]:='std';
StrucNames[2]:='count';
WriteMtlStrucNames(TargetStream,StrucNames);
for k:=0 to Length(MrkDesc.N)-1 do begin
for i:=0 to length(MrkTrialStat)-1 do begin
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxStructC,0);
WriteMtlDimmensions(TargetStream,GetMatDim(1,1));
WriteMtlName(TargetStream,'');
SetLength(StrucNames,3);
StrucNames[0]:='x';
StrucNames[1]:='y';
StrucNames[2]:='z';
WriteMtlStrucNames(TargetStream,StrucNames);
WriteMtlVecVarDouble(true,TargetStream,'',MrkTrialStat[i][k].mean.x);
WriteMtlVecVarDouble(true,TargetStream,'',MrkTrialStat[i][k].mean.y);
WriteMtlVecVarDouble(true,TargetStream,'',MrkTrialStat[i][k].mean.z);
CompleteMtlTag;
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxStructC,0);
WriteMtlDimmensions(TargetStream,GetMatDim(1,1));
WriteMtlName(TargetStream,'');
SetLength(StrucNames,3);
StrucNames[0]:='x';
StrucNames[1]:='y';
StrucNames[2]:='z';
WriteMtlStrucNames(TargetStream,StrucNames);
WriteMtlVecVarDouble(true,TargetStream,'',MrkTrialStat[i][k].std.x);
WriteMtlVecVarDouble(true,TargetStream,'',MrkTrialStat[i][k].std.y);
WriteMtlVecVarDouble(true,TargetStream,'',MrkTrialStat[i][k].std.z);
CompleteMtlTag;
WriteMtlVarInteger(TargetStream,'',MrkTrialStat[i][k].count);
end;
end;
CompleteMtlTag;
CompleteMtlTag;
//trials
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxStructC,0);
WriteMtlDimmensions(TargetStream,GetMatDim(1,length(TrialArray)));
WriteMtlName(TargetStream,'trials');
SetLength(StrucNames,7);
StrucNames[0]:='adc';
StrucNames[1]:='dig';
StrucNames[2]:='mrk';
StrucNames[3]:='adcfname';
StrucNames[4]:='mrkfname';
StrucNames[5]:='adcdattim';
StrucNames[6]:='mrkdattim';
WriteMtlStrucNames(TargetStream,StrucNames);
for i:=0 to length(TrialArray)-1 do begin
WriteMtlMatVarSingle(TargetStream,'',TrialArray[i].ADC);
WriteMtlVecVarWord(True,TargetStream,'',TrialArray[i].Dig);
PrimeMtlTag(TargetStream,miMatrix);
WriteMtlArrayFlags(TargetStream,mxStructC,0);
WriteMtlDimmensions(TargetStream,GetMatDim(1,length(TrialArray[i].mrk)));
WriteMtlName(TargetStream,'');
SetLength(StrucNames,5);
StrucNames[0]:='x';
StrucNames[1]:='y';
StrucNames[2]:='z';
StrucNames[3]:='Nan';
StrucNames[4]:='Spike';
WriteMtlStrucNames(TargetStream,StrucNames);
for k:=0 to length(TrialArray[i].mrk)-1 do begin
WriteMtlVecVarSingle(True,TargetStream,'',TrialArray[i].mrk[k].x);
WriteMtlVecVarSingle(True,TargetStream,'',TrialArray[i].mrk[k].y);
WriteMtlVecVarSingle(True,TargetStream,'',TrialArray[i].mrk[k].z);
WriteMtlVecVarInteger(True,TargetStream,'',TrialArray[i].mrk[k].Nan);
WriteMtlVecVarInteger(True,TargetStream,'',TrialArray[i].mrk[k].Spike);
end;
CompleteMtlTag;
WriteMtlVarString(TargetStream,'',TrialArray[i].voltageFilNam);
WriteMtlVarString(TargetStream,'',TrialArray[i].markerFilNam);
WriteMtlVarString(TargetStream,'',TrialArray[i].adcDateTime);
WriteMtlVarString(TargetStream,'',TrialArray[i].mrkDateTime);
end;
CompleteMtlTag;
TargetStream.SetSize(TargetStream.Position);
try
TargetStream.SaveToFile(fname);
except
on e:EWriteError do begin
CleanUpFile(fname);
e.Message:=fname+' ['+e.message+']';
raise;
end;
on e:EFCreateError do begin
e.Message:=fname+' ['+e.message+']';
raise;
end;
end;
finally
TargetStream.Free;
end;
end;