.csv |
Comma Separated Values |
.data |
Data array |
.els |
ELectrodes Setup (complex cases) |
.ep |
Evoked Potentials |
.eph |
Evoked Potentials with Header |
.epsd.epse |
Evoked Potentials Standard Deviation / Standard Error |
.freq |
Frequencies |
.is |
Inverse Solution matrix |
.lf |
Lead Field file |
.lm |
Link Many file |
.mrk |
Marker file |
.mtg |
Montage file |
.ris |
Results of Inverse Solution computation |
.rois |
Regions Of Interest |
.sef |
Simple Eeg Format |
.seg |
Segmentation |
.spi |
Solution Points Irregularly spaced |
.spr |
Solution Points on Regular grid (obsolete) |
.tva |
Trigger VAlidation file |
.vrb |
Verbose file |
.xyz |
Electrodes coordinates (simpler case) |
This is not a format defined by Cartool, but a very handy and well-recognized file format to store an array of values (handled direclty by Excel, Statistica, Cartool...)
Basically, it is a text file with values on each line being separated either by a comma (,) or by a semi-colon (;), according to your language settings (just to make simple things already complicated... but Cartool will gracefully read both). You can open them either with a text editor, or directly as a spreadsheet in Excel, Statistica, etc... (Note that Cartool also works with its equivalent Tab Separated text file format )
If you have problems and/or want to change the way Cartool, Excel or all other programs behave, do the following:
go to the Control Panel, choose "Regional & Language Options"
The content organization done by Cartool is the following:
A first line which gives the names of the variables,
and their sequence.
Just an example to make it clear, a file used to hold the files parameters for the averaging process:
file;session;tva;triggers
E:\Data\Eeg1.eph;1;;1 2 3 4
E:\Data\Eeg1.eph;2;;5 6 7 8
E:\Data\Eeg2.eph;;;1 2 3 4 5 6 7 8
The first line enumerates the 4 variables (file, session etc...), and there are 3 lines of data with some of these variables defined, and some undefined.
The order of the variables does not matter, and it could have be written as, f.ex.:
file;triggers;session;tva
E:\Data\Eeg1.eph;1 2 3 4;1;
E:\Data\Eeg1.eph;5 6 7 8;2;
E:\Data\Eeg2.eph;1 2 3 4 5 6 7 8;;
A text file used to store and display any kind of
informations, used for example in the
segmentation
process
.
It is a variant of the .seg format, please refer
to it for the full explanations.
The only difference is in the header (first two lines) which lacks the number_of_clusters variable:
number_of_files number_of_time_frames
number_of_tracks tracks_name1 tracks_name2 ... tracks_namen
A text file describing a setup of electrodes. It allows separate clusters of electrodes (for example 2 grids, or a few strips, or electrodes on the scalp plus some auxiliaries...), and each one of the clusters can be of a different type. Another (and obsolete) format is the .xyz.
First line, a magic number:
ES01
Next 2 lines:
Total_number_of_electrodes
Number_of_clusters
Now repeat for each cluster (at least 1):
Cluster_name
Cluster_number_of_electrodes
Cluster_type
Cluster_type could be seen as the dimensionality of the cluster:
0 for separated electrodes (like auxiliaries), or "points"
Then the list of coordinates, one per line:
x y z label optional_flag
x, y, z are, of course, the coordinates, and label the name of the electrode. optional_flag can either be missing or be the identifier Bad, in which case it indicates that the electrodes has a non-significative signal (broken electrode, noisy signal, etc...), and though it will be geometrically used with its neighbors in the building of the 3D tesselation, the value of its signal will not appear to avoid spoiling the display.
The idea of clustering electrodes is to isolate the interpolations between electrodes, so that different clusters won't interfere graphically. For example you can disjoin the auxiliaries electrodes, as you don't want to see them interpolated with regular Eeg.
If two, or more, 3D clusters share the very same name, they will be merged into a single, big cluster of the same name. Still in the case some auxiliaries electrodes were recorded in the middle of regular electrodes, there are, say 3 clusters: 3D, auxs, 3D again, so the program understands that both 3D clusters are the same. If you don't want this merging, simply change the names!
ES01
41
1
10-10 System
41
3
1.000000E+0000 0.000000E+0000 -0.000000E+0000 Fpz
8.090170E-0001 5.877853E-0001 -0.000000E+0000 AF7
9.205049E-0001 0.000000E+0000 3.907311E-0001 AFz
8.090170E-0001 -5.877853E-0001 -0.000000E+0000 AF8
6.273924E-0001 7.217324E-0001 2.923717E-0001 F5
6.590572E-0001 5.336940E-0001 5.299193E-0001 F3
6.946584E-0001 0.000000E+0000 7.193398E-0001 Fz
6.590572E-0001 -5.336940E-0001 5.299193E-0001 F4
6.273924E-0001 -7.217324E-0001 2.923717E-0001 F6
3.090170E-0001 9.510565E-0001 -0.000000E+0000 FT7
3.367557E-0001 8.772786E-0001 3.420201E-0001 FC5
3.535534E-0001 3.535534E-0001 8.660254E-0001 FC1
3.583679E-0001 0.000000E+0000 9.335804E-0001 FCz
3.535534E-0001 -3.535534E-0001 8.660254E-0001 FC2
3.367557E-0001 -8.772786E-0001 3.420201E-0001 FC6
3.090170E-0001 -9.510565E-0001 -0.000000E+0000 FT8
-0.000000E+0000 1.000000E+0000 -0.000000E+0000 T3
-0.000000E+0000 6.946584E-0001 7.193398E-0001 C3
-0.000000E+0000 3.583679E-0001 9.335804E-0001 C1
0 0 1 Cz
3.885433E-0020 -3.583679E-0001 9.335804E-0001 C2
7.531501E-0020 -6.946584E-0001 7.193398E-0001 C4
1.084202E-0019 -1.000000E+0000 -0.000000E+0000 T4
-3.090170E-0001 9.510565E-0001 -0.000000E+0000 TP7
-3.367557E-0001 8.772786E-0001 3.420201E-0001 CP5
-3.535534E-0001 3.535534E-0001 8.660254E-0001 CP1
-3.583679E-0001 -0.000000E+0000 9.335804E-0001 CPz
-3.535534E-0001 -3.535534E-0001 8.660254E-0001 CP2
-3.367557E-0001 -8.772786E-0001 3.420201E-0001 CP6
-3.090170E-0001 -9.510565E-0001 -0.000000E+0000 TP8
-6.273924E-0001 7.217324E-0001 2.923717E-0001 P5
-6.590572E-0001 5.336940E-0001 5.299193E-0001 P3
-6.946584E-0001 -0.000000E+0000 7.193398E-0001 Pz
-6.590572E-0001 -5.336940E-0001 5.299193E-0001 P4
-6.273924E-0001 -7.217324E-0001 2.923717E-0001 P6
-8.090170E-0001 5.877853E-0001 -0.000000E+0000 PO7
-8.619499E-0001 4.019339E-0001 3.090170E-0001 PO3
-9.205049E-0001 -0.000000E+0000 3.907311E-0001 POz
-8.619499E-0001 -4.019339E-0001 3.090170E-0001 PO4
-8.090170E-0001 -5.877853E-0001 -0.000000E+0000 PO8
-1.000000E+0000 -0.000000E+0000 -0.000000E+0000 Oz
A very basic text file format to store an ERP, without header. This is a simple matrix of values, each line (with end-of-line) having all the electrodes values for a given time frame:
electrode_1 electrode_2 electrode_3 ... electrode_n
Lines are repeated for each time frames (the number of time frames is therefore the number of lines). Cartool calculates the number of electrodes and the number of time frames by scanning the whole file at opening time. But it can not guess the sampling frequency, until the user specify it.
A very basic text file format to store an ERP, with a small header.
The first line is the header:
number_of_electrodes number_of_time_frames sampling_frequency
It is followed by the same block as in the .ep files. Cartool does not scan the whole file to get the number of electrodes etc... as they are read (and trusted) directly from the first line.
Actually, the format is just the same as the .eph one.
It simply holds the Standard Deviation / Standard Error of an averaged file.
A binary file that contains the results of some frequency analysis , resulting in a 3 dimensional data array (electrodes x frequencies x time).
There are now two file versions, the first one being obsolete, but Cartool can still read it. The difference between the two versions is in the header, the part describing the frequencies.
Anyway, for both versions, there is a header, composed of a fixed size part plus a variable size part, then followed by the data organized as a matrix.
// some strings size
#define NumFreqTypes 6
#define MaxCharFreqType 32
#define MaxCharFrequencyName 16
// type of content in the file, coded as text
char FreqTypesNames[ NumFreqTypes ][ MaxCharFreqType ] = {
"Unknown",
"FFT Norm",
"FFT Norm2",
"FFT Complex",
"FFT Approximation",
"S Transform"
};
struct TFreqHeader
{
int Version; // 'FR01' (obsolete) or 'FR02'
char Type[MaxCharFreqType]; // of the analysis, and also data stored (see the array FreqTypesNames)
int NumChannels; // total number of electrodes
int NumFrequencies; // saved in file
int NumBlocks; // of repeated analysis, or number of resulting "time frames"
double SamplingFrequency; // of the data in the ORIGINAL file (1000 Hz f.ex.)
double BlockFrequency; // frequency of blocks'occurences (if 1 block is 0.5 s long amd don't overlap -> 2 Hz)
short Year; // Date of the recording
short Month; // (can be 00-00-0000 if unknown)
short Day;
short Hour; // Time of the recording
short Minute; // (can be 00:00:00:0000 if unknown)
short Second;
short Millisecond;
};
// Listing of channels'name
// a matrix of NumElectrodes * sizeof ( TFreqChannel ) chars
//
// To allow an easy calculation of the data origin,
// be aware that each name ALWAYS take 8 bytes in the header, even if the string length is smaller than that.
// The remaining part is padded with bytes set to 0, f.ex.:
// binary values 70 112 122 00 00 00 00 00 65 70 55 00 00 00 00 00 ...
// string equivalence F P z \0 A F 7 \0
struct TFreqChannel
{
char ChannelName[8];
};
This is the part that differs between file versions 'FR01' and 'FR02'.
For the old version 'FR01' :
// Listing of the frequencies actually saved
// size: NumFrequencies * sizeof ( TFreqFrequency )
struct TFreqFrequency
{
double Frequency;
};
For the new version 'FR02' :
// Names assigned to each frequencies or bands actually saved (can be anything)
// size: NumFrequencies * sizeof ( TFreqFrequencyName )
struct TFreqFrequencyName
{
char FrequencyName[ MaxCharFrequencyName ];
};
// Starting at file position:
//
// for version 'FR01'
// sizeof ( TFreqHeader ) + NumElectrodes * sizeof ( TFreqChannel ) + NumFrequencies * sizeof ( TFreqFrequency )
//
// for version 'FR02'
// sizeof ( TFreqHeader ) + NumElectrodes * sizeof ( TFreqChannel ) + NumFrequencies * sizeof ( TFreqFrequencyName )
//
// Data are stored as a matrix NumTimeFrames x NumElectrodes x NumFrequencies
// in this order: f0 f1 f2 .. fn for first electrode, f0 f1 f2 .. fn for second electrode ... etc for first time frame
// then f0 f1 f2 .. fn " " " " for second time frame
// ...etc to the last time frame
//
// Data are of either type
// float (Little Endian - PC) for Type == "FFT Norm", "FFT Norm2", "FFT Approximation"
// or complex (classic C/C++ type) for Type == "FFT Complex"
A binary file containing the matrix for an Inverse Solution , which has to be subsequently multiplied by the EEG to obtain the final results.
3 formats are currently supported, specified by the magic number, the first 4 characters in the file:
'IS01' for a float-type matrix,
'IS02' for a double-type matrix (though it is currently converted into float when read by Cartool),
'IS03' for stacking a set of float-type matrices , and specifying regularizations.
struct isheader {
char magic[ 4 ]; // 'IS01' for float-type matrix, 'IS02' for double-type matrix
int32 numelectrodes;
int32 numsolutionpoints;
int32 numregularizations;
char isinversescalar; // 1 if scalar, 0 if vectorial (value, and not text)
} risheader; // size 13
The matrix can contain either scalar or vectorial results, which means for each solution point there is either:
scalar: 1 signed value,
vectorial: a 3 dimensional vector (a dipole).
Number of rows of the matrix, is scalar type:
numrows = numsolutionpoints
Otherwise, if matrix is of vectorial type, each of the 3 components of the vectors are written on 3 successive rows, giving:
numrows = 3 * numsolutionpoints
Number of columns is always:
numcols = numelectrodes;
The matrix is then written row by row:
(matrixtype is either float or double
according to the header field magic)
matrixtype matrix [ numrows ][ numcols ];
Scalar example, for numrows rows:
s0 s1 s2 ... snumcols-1
s0 s1 s2 ... snumcols-1
...
s0 s1 s2 ... snumcols-1
And vectorial example, for numrows rows:
x0 x1 x2 ... xnumcols-1 (for solution point 1, x component)
y0 y1 y2 ... ynumcols-1 (for solution point 1, y component)
z0 z1 z2 ... znumcols-1 (for solution point 1, z component)
x0 x1 x2 ... xnumcols-1 (for solution point 2)
y0 y1 y2 ... ynumcols-1
z0 z1 z2 ... znumcols-1
...
x0 x1 x2 ... xnumcols-1 (for last solution point)
y0 y1 y2 ... ynumcols-1
z0 z1 z2 ... znumcols-1
struct isfixedheader {
char magic[ 4 ]; // 'IS03'
int32 numelectrodes;
int32 numsolutionpoints;
int32 numregularizations;
char isinversescalar; // 1 if scalar, 0 if vectorial (value, and not text)
} risheaderfixed; // size 17
Note: the number of regularizations has to be >= 1.
Following the fixed header part, the variable header provides the following additional informations:
electrodes names,
solution points names,
the actual values used in the Tikhonov regularizations ,
the display names for each Tikhonov regularizations.
typedef char TElectrodeName [ 32 ]; // 1 electrode name
typedef char TSolutionPointName [ 16 ]; // 1 solution point name
typedef char TRegularizationName[ 32 ]; // 1 regularization name
struct isheadervariable {
TElectrodeName ElectrodesNames [ NumElectrodes ];
TSolutionPointName SolutionPointsNames [ NumSolutionPoints ];
double RegularizationValues [ NumRegularizations ];
TRegularizationName RegularizationNames [ NumRegularizations ];
} risheadervariable;
The matrix content is the same as for type 'IS01' (float matrix), simply repeated by the number of regularizations:
float Matrices[ NumRegularizations ][ NumRows ][ NumColumns ];
A simple binary file format to store a vectorial Lead Field , in double precision.
It has a short header:
struct lfheader {
int32 number_of_electrodes;
int32 number_of_solution_points;
} lfheader; // size 8
Then followed by the data, in double precision, with this ordering (multiplexing the (x,y,z) components):
x0 y0 z0 x1 y1 z1 x2 y2 z2 ... xnumcols-1 ynumcols-1 znumcols-1 (for electrode number 1)
x0 y0 z0 x1 y1 z1 x2 y2 z2 ... xnumcols-1 ynumcols-1 znumcols-1 (for electrode number 2)
...
x0 y0 z0 x1 y1 z1 x2 y2 z2 ... xnumcols-1 ynumcols-1 znumcols-1 (for last electrode)
Or represented as a C array:
double LeadField[ number_of_electrodes ][ number_of_solution_points ][ 3 ];
A text file containing a list of many files that have been
linked by the user. The linked files have to be in whatsoever way
related, though this is very versatile and open to new definitions.
Putting together files will allow to share their informations
between them all, for example an Eeg linked with some electrodes
coordinates will give to the Eeg the electrodes names and 3D positions.
The definate advantage from the link is that, depending on the files
linked, new functionnalities are offered to the user through
new type of views. Taking the same
example, it brings a view showing the potential displayed as a map.
See here for more explanations.
The .lm file is simply a list of other files, written with their full path. F.ex.:
D:\Data\avebrain\egi125.xyz
D:\Data\avebrain\myeeg.condition1.eph
D:\Data\avebrain\myeeg.condition2.eph
Contains the markers defined by the user.
There are 2 formats for .mrk file, the first being in binary
form (obsolete format), the second being in textual form, and
the one actually used as it can be easily read and modified by the user.
In any cases, the markers must be written ordered, sorted
first on their starting positions then on their ending positions (if
two markers have equal starting positions).
It is not advised to write duplicate markers with
exactly the same starting and ending positions. Cartool can read
them, can display them as superimposed markers, but you can expect
unpredictable results when it comes to computing (like averaging,
exporting, etc...). So don't.
A first line with this characters as a magic number:
TL02
Then as many text lines as needed, structured this way:
starting position ending position "description text in quote"
Note: the current limit for the description text is 31 chars.
A header followed by a list of markers, all in binary. The file header structure is:
struct mrkheader {
char magic[4]; // always 'TL01'
} mrkheader; // size 4
And the format for a single marker is:
struct onemrk {
long Position; // from this TF
long To; // to this TF
ushort Code; // trigger code
ushort Type; // should always be 0x2 for a marker
ushort Dummy; // not used, for the user
char Name[6]; // name of the tag
} onemrk; // size 20
A text file that defines a montage to be used with the EEG display (it has to be created in any text editor, Cartool does not provide an editor for this task).
Always a first line with these characters as magic number:
MT01
Then, each following lines can independently be any of these three formats:
el
el1 el2
el1 el2 name
In the first case, the value of the electrode el
(the name of the electrode) is taken as is.
In the second case, the value is the result of subtracting el2
to el1.
The last case is the same as the second one, but a name is given to
override the default one (which would be el1-el2).
This name must be written "as is", without quotes nor spaces.
Non-compliant lines (more fields, empty lines, unknown electrode names..) are simply ignored.
You can put whatever you want in this file, repeating electrodes, changing their order, including auxiliaries or computed tracks . The only limit is that the number of lines should not be more than the number of electrodes in the original file.
MT01
1 2
2 3
3 4
4 5
Aux1 Aux2 DiffAux
10
9
8
7
6
5
4
3
2
1
This text file contains the required structural informations to apply regions of interest calculus on data. At the moment, it simply holds groups of indexes (of electrodes / solution points). You may not be interested on the actual file format, but rather on how to create the ROIs in Cartool, or how to make use of them ?
First line, the magic number to indicate that the content is about indexes (as opposite to voxels):
RO01
Next 2 lines:
Dimension_of_original_data
Number_of_rois
What is meant by Dimension_of_original_data is simply the number of electrodes (or solution points) of the original data the rois were made from. This is used only for checking you're not going to apply the .rois file to the wrong data, which usually have different dimensions.
Then follows 2 lines for each roi:
Roi_name
List_of_indexes
The name of the roi could be anything on the line, including spaces. Quotes are not needed.
Within the list of indexes, use a space to separate between each index. The end of line means the end of the list. Simple. And BTW, indexes start from 1 , not 0.
Example made from a setup of 125 electrodes, into 4 rois:
RO01
125
4
Front Left
26 22 33 23 18 27 24 19 44 39 34 28 25 20 49 45 40 35 29 21 12 41 36 30 13 7 46 37 31
Front Right
14 8 15 9 1 10 3 2 4 124 123 122 121 120 5 119 118 117 116 113 112 111 110 115 114 107 106 105 109
Back Left
42 47 48 43 38 32 50 51 52 53 54 56 57 58 59 60 61 67 63 64 65 66 72 70 71 69 75 74
Back Right
81 88 104 80 87 94 99 103 79 86 93 98 102 78 92 97 101 77 85 91 96 108 84 100 83 90 89 95
This binary file is the final result of inverse solution computations, after the matrix has been multiplied by the Eeg. It is made of a header followed by a matrix of floats.
struct risheader {
char magic[4]; // always 'RI01'
int32 numsolutionpoints;
int32 numtimeframes;
float samplingfrequency; // in Herz
char isinversescalar; // 1 if scalar, 0 if vectorial (value, and not text)
} risheader; // size 17
Number of rows:
numrows = numtimeframes;
If the matrix contains scalar results, the number of columns is
numcols = numsolutionpoints;
If the matrix contains vectorial results, a 3-uple (x,y,z) is written, and the number of columns is
numcols = 3 * numsolutionpoints;
The matrix is then written row by row:
float matrix [ numrows ][ numcols ];
Scalar example, for numrows rows:
s0 s1 s2 ... snumcols-1
s0 s1 s2 ... snumcols-1
...
s0 s1 s2 ... snumcols-1
And vectorial example, for numrows rows:
x0 y0 z0 x1 y1 z1 ... xnumcols-1 ynumcols-1 znumcols-1
x0 y0 z0 x1 y1 z1 ... xnumcols-1 ynumcols-1 znumcols-1
...
x0 y0 z0 x1 y1 z1 ... xnumcols-1 ynumcols-1 znumcols-1
Simple (or safe, or stupid) binary format containing the minimal data structure to describe correctly an EEG, either an original recording or an ERP. It has a header, made of a fixed part and a variable part, followed by the calibrated data (in micro-volts).
struct TSefHeader
{
int Version; // magic number filled with the wide char 'SE01'
int NumElectrodes; // total number of electrodes
int NumAuxElectrodes; // out of which are auxiliaries
int NumTimeFrames; // time length
float SamplingFrequency; // frequency in Hertz
short Year; // Date of the recording
short Month; // (set to 00-00-0000 if unknown)
short Day;
short Hour; // Time of the recording
short Minute; // (set to 00:00:00:0000 if unknown)
short Second;
short Millisecond;
};
The names of the channels, as a matrix of NumElectrodes x 8 chars.
typedef char TSefChannelName[8]; // 1 electrode name
To allow an easy calculation of the data origin, be aware that names are always stored on 8 bytes, even if the string length is smaller than that. In this case, the remaining part is padded with bytes set to 0, f.ex. two consecutive names:
binary values 70 112 122 00 00 00 00 00 65 70 55 00 00 00 00 00 ...
string equivalence F P z \0 A F 7 \0
Starting at file position:
sizeof ( TSefHeader ) + 8 * NumElectrodes
data are stored as a float (Little Endian convention - PC) matrix written row by row:
float data [ NumTimeFrames ][ NumElectrodes ];
A text file used to store and display the results of the segmentation process .
First two lines is the header:
number_of_clusters number_of_files number_of_time_frames
number_of_tracks tracks_name1 tracks_name2 ... tracks_namen
where
number_of_clusters is the number of clusters from
the segmentation process
number_of_files is the number of
files that have been segmented together
number_of_time_frames is the number of time frames of each segmented file
number_of_tracks is the number of
informations saved for each file (f.ex. 5 for Gfp Dis Seg GEV EV)
tracks_namei
is the name of the ith track (f.ex. "Gfp")
Then follow the data, one line per time frame (as in .eph file). Each line concatenates the number_of_tracks variables, one file after the other, f.ex.:
File1Gfp File1Dis File1Seg File1GEV File2Gfp File2Dis File2Seg File2GEV ... FilenGfp FilenDis FilenSeg FilenGEV
A text file consisting of a list of 3D points, used as the solution points for the inverse solutions. These points can be irregularly spaced, and don't need to be on any sort of a grid.
There is no header, and each line simply contains the
coordinates
of one point
(floatting points values), and an optional name
(max 15 characters):
x y z optionalname
Same format as .spi, but the points have to be regularly spaced. That is, there has to be the same distance (usually an integer value) between neighbors, and for all coordinates.
A text file that stores if a trigger was right or wrong, f.ex.
the choices a subject replied during an experiment.
There are two slightly different versions of this file, the
difference being rather semantic than on the format itself:
Is a file without header, containing a serie of lines which have the following format:
accepted reaction_time trigger_code
where:
accepted
is either 0 (wrong answer / false) or 1 (correct
answer / true)
reaction_time
is the reaction time of the answer, in milliseconds, 0 otherwise
trigger_code
is the name of the trigger
Is a serie of lines identical to version 1, but the file starts with the header :
TV01
The difference between the two versions consist in which triggers are being listed.
Version 1 is usually the ouput of the stimulation program, all triggers of the experiment are therefore listed. So if there are three triggers A, B, C repeated 100 times each, we will have 300 lines in the file.
Version 2 is rather an output from Cartool itself, usually from the averaging process. It will list only the triggers that were considered during the processing. If only triggers A and B were used, we will have only 200 + 1 lines in the file, the C trigger being ignored. These tva files can be used to re-do the averaging.
1 1765 45
1 977.1 43
1 1191 36
0 0 56
0 0 35
1 1309 55
1 1696 49
1 1211 33
...
TV01
1 0 On
1 0 Off
0 0 On
1 0 Off
1 0 On
0 0 Off
...
A text file generated during the main processings of Cartool. It records all the parameters set for the processings and in some case the user's responses during the procedure. These files are generated just for your convenience, to help you store and recover how you computed that incredible files of yours!
A text file containing a list of electrodes coordinates on a scalp. For more advanced electrodes setup (strips, clusters of electrodes, grids...) see the .els format.
First line (though the radius of the cluster is not used anymore in Cartool):
Number_of_electrodes Radius_of_the_cluster
Then a list of coordinates, one per line:
x y z label
29 1
9.510565E-0001 -3.090170E-0001 -0.000000E+0000 Fp2
6.590572E-0001 -5.336940E-0001 5.299193E-0001 F4
7.531501E-0020 -6.946584E-0001 7.193398E-0001 C4
-6.590572E-0001 -5.336940E-0001 5.299193E-0001 P4
-9.510565E-0001 -3.090170E-0001 -0.000000E+0000 O2
5.877853E-0001 -8.090170E-0001 -0.000000E+0000 F8
1.084202E-0019 -1.000000E+0000 -0.000000E+0000 T4
-5.877853E-0001 -8.090170E-0001 -0.000000E+0000 T6
8.619499E-0001 -4.019339E-0001 3.090170E-0001 AF4
3.367557E-0001 -8.772786E-0001 3.420201E-0001 FC6
3.535534E-0001 -3.535534E-0001 8.660254E-0001 FC2
-3.535534E-0001 -3.535534E-0001 8.660254E-0001 CP2
-3.367557E-0001 -8.772786E-0001 3.420201E-0001 CP6
9.510565E-0001 3.090170E-0001 -0.000000E+0000 Fp1
6.590572E-0001 5.336940E-0001 5.299193E-0001 F3
-0.000000E+0000 6.946584E-0001 7.193398E-0001 C3
-6.590572E-0001 5.336940E-0001 5.299193E-0001 P3
-9.510565E-0001 3.090170E-0001 -0.000000E+0000 O1
5.877853E-0001 8.090170E-0001 -0.000000E+0000 F7
-0.000000E+0000 1.000000E+0000 -0.000000E+0000 T3
-5.877853E-0001 8.090170E-0001 -0.000000E+0000 T5
8.619499E-0001 4.019339E-0001 3.090170E-0001 AF3
3.367557E-0001 8.772786E-0001 3.420201E-0001 FC5
3.535534E-0001 3.535534E-0001 8.660254E-0001 FC1
-3.535534E-0001 3.535534E-0001 8.660254E-0001 CP1
-3.367557E-0001 8.772786E-0001 3.420201E-0001 CP5
6.946584E-0001 0.000000E+0000 7.193398E-0001 Fz
0 0 1 Cz
-6.946584E-0001 -0.000000E+0000 7.193398E-0001 Pz