v2.0.0
Loading...
Searching...
No Matches
fs_annotation.cpp
Go to the documentation of this file.
1//=============================================================================================================
36
37//=============================================================================================================
38// INCLUDES
39//=============================================================================================================
40
41#include "fs_annotation.h"
42#include "fs_label.h"
43#include "fs_surface.h"
44
45#include <iostream>
46
47//=============================================================================================================
48// QT INCLUDES
49//=============================================================================================================
50
51#include <QDebug>
52#include <QFile>
53#include <QDataStream>
54#include <QFileInfo>
55
56//=============================================================================================================
57// USED NAMESPACES
58//=============================================================================================================
59
60using namespace FSLIB;
61using namespace Eigen;
62
63//=============================================================================================================
64// DEFINE MEMBER METHODS
65//=============================================================================================================
66
68: m_iHemi(-1)
69{
70}
71
72//=============================================================================================================
73
74FsAnnotation::FsAnnotation(const QString& p_sFileName)
75: m_sFileName(p_sFileName)
76{
77 FsAnnotation t_Annotation;
78 FsAnnotation::read(m_sFileName, t_Annotation);
79 *this = t_Annotation;
80}
81
82//=============================================================================================================
83
84FsAnnotation::FsAnnotation(const QString &subject_id, qint32 hemi, const QString &atlas, const QString &subjects_dir)
85: m_iHemi(-1)
86{
87 FsAnnotation::read(subject_id, hemi, atlas, subjects_dir, *this);
88}
89
90//=============================================================================================================
91
92FsAnnotation::FsAnnotation(const QString &path, qint32 hemi, const QString &atlas)
93: m_iHemi(-1)
94{
95 FsAnnotation::read(path, hemi, atlas, *this);
96}
97
98//=============================================================================================================
99
103
104//=============================================================================================================
105
107{
108 m_sFileName = QString("");
109 m_Vertices = VectorXi::Zero(0);
110 m_LabelIds = VectorXi::Zero(0);
111 m_Colortable.clear();
112}
113
114//=============================================================================================================
115
116bool FsAnnotation::read(const QString &subject_id, qint32 hemi, const QString &atlas, const QString &subjects_dir, FsAnnotation &p_Annotation)
117{
118 if(hemi != 0 && hemi != 1)
119 return false;
120
121 QString p_sFile = QString("%1/%2/label/%3.%4.annot").arg(subjects_dir).arg(subject_id).arg(hemi == 0 ? "lh" : "rh").arg(atlas);
122
123 return read(p_sFile, p_Annotation);
124}
125
126//=============================================================================================================
127
128bool FsAnnotation::read(const QString &path, qint32 hemi, const QString &atlas, FsAnnotation &p_Annotation)
129{
130 if(hemi != 0 && hemi != 1)
131 return false;
132
133 QString p_sFile = QString("%1/%2.%3.annot").arg(path).arg(hemi == 0 ? "lh" : "rh").arg(atlas);
134
135 return read(p_sFile, p_Annotation);
136}
137
138//=============================================================================================================
139
140bool FsAnnotation::read(const QString& p_sFileName, FsAnnotation &p_Annotation)
141{
142 p_Annotation.clear();
143
144 qInfo("Reading annotation...\n");
145 QFile t_File(p_sFileName);
146 QFileInfo fileInfo(t_File.fileName());
147
148 p_Annotation.m_sFileName = fileInfo.fileName();
149 p_Annotation.m_sFilePath = fileInfo.filePath();
150
151 if (!t_File.open(QIODevice::ReadOnly))
152 {
153 qWarning("\tError: Couldn't open the file");
154 return false;
155 }
156
157 QDataStream t_Stream(&t_File);
158 t_Stream.setByteOrder(QDataStream::BigEndian);
159
160 qint32 numEl;
161 t_Stream >> numEl;
162
163 p_Annotation.m_Vertices = VectorXi(numEl);
164 p_Annotation.m_LabelIds = VectorXi(numEl);
165
166 for(qint32 i = 0; i < numEl; ++i)
167 {
168 t_Stream >> p_Annotation.m_Vertices[i];
169 t_Stream >> p_Annotation.m_LabelIds[i];
170 }
171
172 qint32 hasColortable;
173 t_Stream >> hasColortable;
174 if (hasColortable)
175 {
176 p_Annotation.m_Colortable.clear();
177
178 //Read colortable
179 qint32 numEntries;
180 t_Stream >> numEntries;
181 qint32 len;
182 if(numEntries > 0)
183 {
184
185 qInfo("\tReading from Original Version\n");
186 p_Annotation.m_Colortable.numEntries = numEntries;
187 t_Stream >> len;
188 QByteArray tmp;
189 tmp.resize(len);
190 t_Stream.readRawData(tmp.data(),len);
191 // FreeSurfer includes null terminator in stored length – strip it
192 if (tmp.endsWith('\0'))
193 tmp.chop(1);
194 p_Annotation.m_Colortable.orig_tab = tmp;
195
196 for(qint32 i = 0; i < numEntries; ++i)
197 p_Annotation.m_Colortable.struct_names.append("");
198
199 p_Annotation.m_Colortable.table = MatrixXi(numEntries,5);
200
201 for(qint32 i = 0; i < numEntries; ++i)
202 {
203 t_Stream >> len;
204 tmp.resize(len);
205 t_Stream.readRawData(tmp.data(),len);
206 if (tmp.endsWith('\0'))
207 tmp.chop(1);
208
209 p_Annotation.m_Colortable.struct_names[i]= tmp;
210
211 for(qint32 j = 0; j < 4; ++j)
212 t_Stream >> p_Annotation.m_Colortable.table(i,j);
213
214 p_Annotation.m_Colortable.table(i,4) = p_Annotation.m_Colortable.table(i,0)
215 + p_Annotation.m_Colortable.table(i,1) * 256 //(2^8)
216 + p_Annotation.m_Colortable.table(i,2) * 65536 //(2^16)
217 + p_Annotation.m_Colortable.table(i,3) * 16777216; //(2^24);
218 }
219 }
220 else
221 {
222 qint32 version = -numEntries;
223 if(version != 2)
224 qWarning("\tError! Does not handle version %d", version);
225 else
226 qInfo("\tReading from version %d\n", version);
227
228 t_Stream >> numEntries;
229 p_Annotation.m_Colortable.numEntries = numEntries;
230
231 t_Stream >> len;
232 QByteArray tmp;
233 tmp.resize(len);
234 t_Stream.readRawData(tmp.data(),len);
235 // FreeSurfer includes null terminator in stored length – strip it
236 if (tmp.endsWith('\0'))
237 tmp.chop(1);
238 p_Annotation.m_Colortable.orig_tab = tmp;
239
240 for(qint32 i = 0; i < numEntries; ++i)
241 p_Annotation.m_Colortable.struct_names.append("");
242
243 p_Annotation.m_Colortable.table = MatrixXi(numEntries,5);
244
245 qint32 numEntriesToRead;
246 t_Stream >> numEntriesToRead;
247
248 qint32 structure;
249 for(qint32 i = 0; i < numEntriesToRead; ++i)
250 {
251
252 t_Stream >> structure;
253 if (structure < 0)
254 qWarning("\tError! Read entry, index %d", structure);
255
256 if(!p_Annotation.m_Colortable.struct_names[structure].isEmpty())
257 qWarning("Error! Duplicate Structure %d", structure);
258
259 t_Stream >> len;
260 tmp.resize(len);
261 t_Stream.readRawData(tmp.data(),len);
262 if (tmp.endsWith('\0'))
263 tmp.chop(1);
264
265 p_Annotation.m_Colortable.struct_names[structure]= tmp;
266
267 for(qint32 j = 0; j < 4; ++j)
268 t_Stream >> p_Annotation.m_Colortable.table(structure,j);
269
270 p_Annotation.m_Colortable.table(structure,4) = p_Annotation.m_Colortable.table(structure,0)
271 + p_Annotation.m_Colortable.table(structure,1) * 256 //(2^8)
272 + p_Annotation.m_Colortable.table(structure,2) * 65536 //(2^16)
273 + p_Annotation.m_Colortable.table(structure,3) * 16777216; //(2^24);
274 }
275 }
276 qInfo("\tcolortable with %d entries read\n\t(originally %s)\n", p_Annotation.m_Colortable.numEntries, p_Annotation.m_Colortable.orig_tab.toUtf8().constData());
277 }
278 else
279 {
280 qWarning("\tError! No colortable stored");
281 }
282
283 // hemi info
284 if(t_File.fileName().contains("lh."))
285 p_Annotation.m_iHemi = 0;
286 else
287 p_Annotation.m_iHemi = 1;
288
289 qInfo("[done]\n");
290
291 t_File.close();
292
293 return true;
294}
295
296//=============================================================================================================
297
299 QList<FsLabel> &p_qListLabels,
300 QList<RowVector4i> &p_qListLabelRGBAs,
301 const QStringList& lLabelPicks) const
302{
303 if(this->m_iHemi != p_surf.hemi())
304 {
305 qWarning("FsAnnotation and surface hemisphere (annot = %d; surf = %d) do not match!\n", this->m_iHemi, p_surf.hemi());
306 return false;
307 }
308
309 if(m_LabelIds.size() == 0)
310 {
311 qWarning("FsAnnotation doesn't' contain data!\n");
312 return false;
313 }
314
315 qInfo("Converting labels from annotation...");
316
317//n_read = 0
318//labels = list()
319//label_colors = list()
320
321 VectorXi label_ids = m_Colortable.getLabelIds();
322 QStringList label_names = m_Colortable.getNames();
323 MatrixX4i label_rgbas = m_Colortable.getRGBAs();
324
325 // load the vertex positions from surface
326 MatrixX3f vert_pos = p_surf.rr();
327
328// qDebug() << label_rgbas.rows() << label_ids.size() << label_names.size();
329
330// std::cout << label_ids;
331
332 qint32 label_id, count;
333 RowVector4i label_rgba;
334 VectorXi vertices;
335 VectorXd values;
336 MatrixX3f pos;
337 QString name;
338 for(qint32 i = 0; i < label_rgbas.rows(); ++i)
339 {
340 label_id = label_ids[i];
341 label_rgba = label_rgbas.row(i);
342 count = 0;
343 vertices.resize(m_LabelIds.size());
344 //Where
345 for(qint32 j = 0; j < m_LabelIds.size(); ++j)
346 {
347 if(m_LabelIds[j] == label_id)
348 {
349 vertices[count] = j;
350 ++count;
351 }
352 }
353 // check if label is part of cortical surface
354 if(count == 0)
355 continue;
356 vertices.conservativeResize(count);
357
358 pos.resize(count, 3);
359 for(qint32 j = 0; j < count; ++j)
360 pos.row(j) = vert_pos.row(vertices[j]);
361
362 values = VectorXd::Zero(count);
363 name = QString("%1-%2").arg(label_names[i]).arg(this->m_iHemi == 0 ? "lh" : "rh");
364
365 // put it all together
366 if(lLabelPicks.isEmpty()) {
367 //t_tris
368 p_qListLabels.append(FsLabel(vertices, pos, values, this->m_iHemi, name, label_id));
369 // store the color
370 p_qListLabelRGBAs.append(label_rgba);
371 } else if (lLabelPicks.indexOf(name) != -1) {
372 //t_tris
373 p_qListLabels.append(FsLabel(vertices, pos, values, this->m_iHemi, name, label_id));
374 // store the color
375 p_qListLabelRGBAs.append(label_rgba);
376 }
377 }
378
379// for label_id, label_name, label_rgba in
380// zip(label_ids, label_names, label_rgbas):
381// vertices = np.where(annot == label_id)[0]
382// if len(vertices) == 0:
383// # label is not part of cortical surface
384// continue
385// pos = vert_pos[vertices, :]
386// values = np.zeros(len(vertices))
387// name = label_name + '-' + hemi
388// label = FsLabel(vertices, pos, values, hemi, name=name)
389// labels.append(label)
390
391// # store the color
392// label_rgba = tuple(label_rgba / 255.)
393// label_colors.append(label_rgba)
394
395// n_read = len(labels) - n_read
396// logger.info(' read %d labels from %s' % (n_read, fname))
397
398//# sort the labels and colors by label name
399//names = [label.name for label in labels]
400//labels, label_colors = zip(*((label, color) for (name, label, color)
401// in sorted(zip(names, labels, label_colors))))
402//# convert tuples to lists
403//labels = list(labels)
404//label_colors = list(label_colors)
405
406 qInfo("[done]\n");
407
408 return true;
409}
FsLabel class declaration.
FsSurface class declaration.
FsAnnotation class declaration.
FreeSurfer surface and annotation I/O.
qint32 hemi() const
static bool read(const QString &subject_id, qint32 hemi, const QString &atlas, const QString &subjects_dir, FsAnnotation &p_Annotation)
bool toLabels(const FsSurface &p_surf, QList< FsLabel > &p_qListLabels, QList< Eigen::RowVector4i > &p_qListLabelRGBAs, const QStringList &lLabelPicks=QStringList()) const
QStringList struct_names
Eigen::MatrixXi table
Freesurfer/MNE label.
Definition fs_label.h:81
FreeSurfer surface mesh.
Definition fs_surface.h:83
qint32 hemi() const
Definition fs_surface.h:346
const Eigen::MatrixX3f & rr() const
Definition fs_surface.h:367