Skip to content

Commit a8847bf

Browse files
authored
Merge pull request #21 from openep/develop
Pull request for first release
2 parents 1f314c3 + 3ce1590 commit a8847bf

File tree

130 files changed

+15224
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

130 files changed

+15224
-0
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# OpenEP
2+
3+
OpenEP supports the import and analysis of electroanatomic mapping data in Matlab

batchImport.m

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
% ----------------------------------------------------------------------- %
2+
% OPENEP/batchImport is a template script to automate the import of
3+
% datasets into OpenEP data format. This batchImport script requires a
4+
% number of assumptions to be true in order to function.
5+
%
6+
% 1. Cases should be named using a study number (e.g. 001) and compressed
7+
% into folders named that study number.
8+
% 2. An Excell information spreadsheet should be provided which
9+
% identifies the map to import and should contain two columns where the
10+
% first contains the study number and the second the number of points per
11+
% map.
12+
%
13+
% As currently configured, the script assumes that datasets are stored on
14+
% an external hard drive, but copies dataset zip files to the local machine
15+
% hard drive prior to unzipping, which is usually fastest.
16+
%
17+
% After importing into OpenEP dataformat, intermediate files which can
18+
% number in the 1000s and occupy Gb of space, are removed.
19+
% ----------------------------------------------------------------------- %
20+
21+
% ----------------------------------------------------------------------- %
22+
% Configuration
23+
% testmode copies and unzips files but does not process them
24+
testmode = false;
25+
26+
% Set up working directories and paths
27+
zip_dir = '/Volumes/Extreme SSD/openep/openep_carto_export_zips';
28+
working_dir = '/Users/Steven/Desktop/openep_working_dir';
29+
info_spreadsheet = '/Volumes/Extreme SSD/openep/openep_datasheet.xlsx';
30+
31+
% Cell array of possible start of names of the study XML file
32+
startStrings = {'CARTO' 'PVI' 'Study' '1008' 'PERS' 'AF' 'LA' 'PAF' 'AIAT'};
33+
% ----------------------------------------------------------------------- %
34+
35+
% Load the study dataset Excel file
36+
info = xlsread(info_spreadsheet, 'A:B');
37+
38+
% Get a list of files in zip_dir
39+
disp('Getting list of filenames')
40+
allFiles = nameFiles(zip_dir, 'showhiddenfiles', false);
41+
42+
% Loop through all the zip files
43+
for i = 1:numel(allFiles)
44+
disp(['Processing case: ' allFiles{i}]);
45+
46+
% Copy the zip file to the hard drive
47+
sourceFile = [zip_dir filesep() allFiles{i}];
48+
destinationFile = [working_dir filesep() allFiles{i}];
49+
status = copyfile(sourceFile, destinationFile);
50+
51+
% Get the study number
52+
studyNumber = str2double(allFiles{i}(1:3));
53+
54+
% Unzip the zip file to a folder named studyNumber in working_dir
55+
caseDir = ([working_dir filesep() num2str(studyNumber)]);
56+
unzip(destinationFile, caseDir);
57+
58+
% Locate the carto export xml file
59+
allXmlFiles = nameFiles(caseDir, 'extension', 'xml', 'showhiddenfiles', false);
60+
iF = NaN(size(startStrings));
61+
for j = 1:numel(startStrings)
62+
temp = find(strstartcmpi(startStrings{j}, allXmlFiles));
63+
if ~isempty(temp)
64+
iF(j) = temp;
65+
end
66+
end
67+
68+
if nnz(~isnan(iF)) > 1
69+
% Multiple possible files found so the user has to choose which xml file to load
70+
iF(isnan(iF)) = [];
71+
beep()
72+
disp([num2str(numel(iF)) ' possible XML files found:'])
73+
for j = 1:numel(iF)
74+
disp([ num2str(j) ' ' allXmlFiles{iF(j)}]);
75+
end
76+
result = input('Enter choice: ');
77+
studyXmlFile = [case_dir filesep() allXmlFiles{iF(result)}];
78+
else % Automatically select the relevant xml file
79+
iF(isnan(iF)) = [];
80+
studyXmlFile = [caseDir filesep() allXmlFiles{iF}];
81+
end
82+
83+
% Check that an XML file has been identified
84+
if ~isfile(studyXmlFile)
85+
error(['RUN_PEPR_EXPERIMENT: Specified XML file - ' studyXmlFile ' - does not exist']);
86+
end
87+
88+
% Read the number of points from the spreadsheet
89+
numpts = info(info(:,1)==studyNumber,2);
90+
91+
% Specify the output directory and filename
92+
outputFile = ([working_dir filesep() [num2str(studyNumber) '.mat']]);
93+
94+
% Start a timer
95+
tic();
96+
97+
% Run importcarto_mem from the command line
98+
if ~testmode
99+
userdata = importcarto_mem(studyXmlFile ...
100+
, 'maptoread', numpts ...
101+
, 'refchannel', 'CS9-CS10' ...
102+
, 'ecgchannel', 'V1' ...
103+
, 'savefilename', outputFile ...
104+
);
105+
end
106+
107+
% Stop a timer
108+
elapsedTime = toc();
109+
110+
% Get the size of caseDir and destinationFile
111+
sizeUnZipped = du(['-sh ' caseDir]);
112+
sizeZipped = du(['-sh ' destinationFile]);
113+
114+
% Remove the carto files and zip file
115+
deleteFolder(caseDir);
116+
delete(destinationFile);
117+
118+
% Dump the time and filesizes to a text file
119+
fid = fopen([working_dir filesep() [num2str(studyNumber) '.data']], 'wt');
120+
fprintf(fid, [num2str(elapsedTime) '\n']);
121+
fprintf(fid, [sizeUnZipped '\n']);
122+
fprintf(fid, [sizeZipped '\n']);
123+
fclose(fid);
124+
125+
end

batchProcess.m

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
% ----------------------------------------------------------------------- %
2+
% OPENEP/batchProcess is a template script which can be used to perform
3+
% multiple functions on OpenEP datasets
4+
% ----------------------------------------------------------------------- %
5+
6+
% ----------------------------------------------------------------------- %
7+
% Configuration
8+
% Set up directories and load filenames
9+
working_dir = '/Users/Steven/Desktop/openep_working_dir';
10+
% ----------------------------------------------------------------------- %
11+
12+
13+
% Get a list of files
14+
disp('Getting list of filenames')
15+
allFiles = nameFiles(working_dir, 'showhiddenfiles', false, 'extension', 'mat');
16+
17+
lat.carto = [];
18+
lat.openep = [];
19+
20+
% Iterate through each file and perform some OpenEP functions
21+
for i = 1:numel(allFiles)
22+
disp(['working on file ... ' allFiles{i}])
23+
load([working_dir filesep() allFiles{i}]);
24+
25+
% Geometry
26+
openep_num_pts(i,1) = getNumPts(userdata);
27+
openep_chamber_area(i,1) = getArea(userdata);
28+
openep_chamber_area_closed(i,1) = getArea(userdata, 'method', 'fill');
29+
openep_chamber_volume(i,1) = getVolume(userdata);
30+
31+
% Local activation time
32+
[~, earliestDirc(i,1:3)] = getEarliestActivationSite(userdata, 'method', 'ptbased');
33+
[~, earliestPrct(i,1:3)] = getEarliestActivationSite(userdata, 'method', 'ptbasedprct');
34+
tat.ptbased(i,1) = getTotalActivationTime(userdata, 'method', 'ptbased');
35+
tat.ptbasedprct(i,1) = getTotalActivationTime(userdata, 'method', 'ptbasedprct');
36+
tat.clinmap(i,1) = getTotalActivationTime(userdata, 'method', 'clinmap');
37+
tat.clinmapprct(i,1) = getTotalActivationTime(userdata, 'method', 'clinmapprct');
38+
tat.openepmap(i,1) = getTotalActivationTime(userdata, 'method', 'openepmap');
39+
tat.openepmapprct(i,1) = getTotalActivationTime(userdata, 'method', 'openepmapprct');
40+
lat_carto_temp = userdata.surface.act_bip(:,1);
41+
lat_openep_tmp = generateInterpData(userdata, 'lat-map');
42+
lat.carto = [lat.carto; lat_carto_temp];
43+
lat.openep = [lat.openep; lat_openep_tmp];
44+
45+
% Voltage
46+
meanVoltage.Carto(i,1) = getMeanVoltage(userdata, 'method', 'map');
47+
meanVoltage.OpenEP(i,1) = getMeanVoltage(userdata, 'method', 'egm');
48+
lva.Carto(i,1) = getLowVoltageArea(userdata, 'method', 'map');
49+
lva.OpenEP(i,1) = getLowVoltageArea(userdata, 'method', 'egm');
50+
51+
% Conduction Velocity
52+
end

cartoMesh2VTK.m

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
function tr = cartoMesh2VTK()
2+
% CARTOMESH2VTK Converts a Carto mesh file to VTK file
3+
%
4+
% Usage:
5+
% tr = cartoMesh2VTK('openfile')
6+
% Where:
7+
% tr, - a TriRep object
8+
%
9+
% CARTOMESH2VTK Converts a Carto3 mesh to a VTK file and returns a TriRep
10+
% object
11+
%
12+
% Author: Steven Williams (2015) (Copyright)
13+
% SPDX-License-Identifier: Apache-2.0
14+
%
15+
% Modifications -
16+
%
17+
% Info on Code Testing:
18+
% ---------------------------------------------------------------
19+
% test code
20+
% ---------------------------------------------------------------
21+
%
22+
% ---------------------------------------------------------------
23+
% code
24+
% ---------------------------------------------------------------
25+
26+
% output the mesh to a temporary VTK
27+
[fileName, pathName] = uigetfile('*.mesh', 'Select a Carto3 .mesh file');
28+
tr = read_meshfile([pathName filesep fileName]);
29+
fileName2 = [fileName(1:end-4) 'vtk'];
30+
writeTriRep2VTK(repack(tr), [], 'outputfile', [pathName filesep fileName2]);
31+
32+
end

cemrg2carto.m

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
function cemrg2carto(infile, outfile, vtktitle)
2+
% CEMRG2CARTO Converts a VTK for loading into Carto
3+
% Usage:
4+
% op = cemrg2carto(infile, outfile)
5+
%
6+
% Where:
7+
% infile - a VTK file created by CEMRG
8+
% outfile - a VTK file formatted for Carto
9+
%
10+
% CEMRG2CARTO Converts a VTK file created by CEMRG into a VTK file that can
11+
% be loaded into Carto. The two main functions are to convert cell data to
12+
% point data and to add the correct header based on patient name and ID.
13+
%
14+
% Author: Steven Williams (2016)
15+
% Modifications -
16+
%
17+
% Info on Code Testing:
18+
% ---------------------------------------------------------------
19+
%
20+
% ---------------------------------------------------------------
21+
%
22+
% ---------------------------------------------------------------
23+
% code
24+
% ---------------------------------------------------------------
25+
26+
if strcmpi(infile, 'openfile')
27+
[filename, pathname] = uigetfile('*.vtk', 'Select VTK file to open ...');
28+
infile = [pathname filename];
29+
end
30+
if infile==0
31+
disp('Operation cancelled');
32+
return
33+
end
34+
35+
h = waitbar(0, 'Load VTK file');
36+
hVtk = VTKReader(infile);
37+
38+
waitbar(.2, h, 'Read VTK data');
39+
hVtk.readAllData();
40+
41+
waitbar(.5, h, 'Get anatomy from VTK file');
42+
tr = hVtk.getTriRep();
43+
44+
waitbar(.8, h, 'Convert cell data to point data');
45+
pointdata = trFaceToVertData(tr, hVtk.CellData{1});
46+
close(h);
47+
48+
if exist('vtktitle')==0
49+
answer = inputdlg({'firstname', 'surname', 'ID'});
50+
vtktitle = ['PatientData ' answer{1} ' ' answer{2} ' ' answer{3}];
51+
end
52+
53+
if strcmpi(outfile, 'openfile')
54+
[filename, pathname] = uiputfile('*.vtk', 'Select VTK file to save ...');
55+
outfile = [pathname filename];
56+
end
57+
58+
writeTriRep2VTK(tr, pointdata, 'title', vtktitle, 'outputfile', outfile);

cvHistogram.m

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
function cvHistogram( userdata, varargin )
2+
% CVHISTOGRAM Draws a conduction velocity histogram
3+
%
4+
% Usage:
5+
% cvHistogram( userdata )
6+
% Where:
7+
% userdata - see importcarto_mem
8+
%
9+
% CVHISTOGRAM accepts the following parameter-value pairs
10+
% 'limits' {[0 5]} | array
11+
% 'binwidth' {0.1} | double
12+
%
13+
% CVHISTOGRAM displays a histogram of conduction velocities. Limits are set
14+
% to exclude non-physiological conduction velocities
15+
%
16+
% Author: Steven Williams (2020) (Copyright)
17+
% SPDX-License-Identifier: Apache-2.0
18+
%
19+
% Modifications -
20+
%
21+
% Info on Code Testing:
22+
% ---------------------------------------------------------------
23+
% cvHistogram( userdata )
24+
% ---------------------------------------------------------------
25+
%
26+
% ---------------------------------------------------------------
27+
% code
28+
% ---------------------------------------------------------------
29+
30+
nStandardArgs = 1; % UPDATE VALUE
31+
limits = [0 5];
32+
binwidth = 0.1;
33+
if nargin > nStandardArgs
34+
for i = 1:2:nargin-nStandardArgs
35+
switch varargin{i}
36+
case 'limits'
37+
limits = varargin{i+1};
38+
case 'binwidth'
39+
binwidth = varargin{i+1};
40+
end
41+
end
42+
end
43+
% TODO: check format of input values for each parameter are correct
44+
45+
cvdata = getConductionVelocity(userdata);
46+
cvdata(cvdata<limits(1)) = [];
47+
cvdata(cvdata>limits(2)) = [];
48+
49+
histogram(cvdata ...
50+
, 'normalization', 'probability' ...
51+
, 'binwidth', binwidth ...
52+
, 'facecolor', 'k' ...
53+
, 'facealpha', 1 ...
54+
);
55+
set(gcf, 'color', 'w');
56+
xlabel('Conduction Velocity (m/s)');
57+
ylabel('Frequency')
58+
set(gca, 'fontsize', 16)
59+
end

0 commit comments

Comments
 (0)