v2.0.0
Loading...
Searching...
No Matches
mri_vol_data.cpp
Go to the documentation of this file.
1//=============================================================================================================
34
35//=============================================================================================================
36// INCLUDES
37//=============================================================================================================
38
39#include "mri_vol_data.h"
40#include "mri_mgh_io.h"
41
42#include <fiff/fiff_file.h>
43
44//=============================================================================================================
45// USED NAMESPACES
46//=============================================================================================================
47
48using namespace MRILIB;
49using namespace Eigen;
50
51//=============================================================================================================
52// DEFINE MEMBER METHODS
53//=============================================================================================================
54
56: version(0)
57, width(0)
58, height(0)
59, depth(0)
60, nframes(0)
62, dof(0)
63, rasGood(false)
64, xsize(1.0f)
65, ysize(1.0f)
66, zsize(1.0f)
67, x_ras(-1.0f, 0.0f, 0.0f) // FreeSurfer defaults when goodRASflag is false
68, y_ras( 0.0f, 0.0f, -1.0f) // See: https://surfer.nmr.mgh.harvard.edu/fswiki/FsTutorial/MghFormat
69, z_ras( 0.0f, 1.0f, 0.0f)
70, c_ras( 0.0f, 0.0f, 0.0f)
71, TR(0.0f)
72, flipAngle(0.0f)
73, TE(0.0f)
74, TI(0.0f)
75, FoV(0.0f)
76{
77}
78
79//=============================================================================================================
80
82{
83 return (version == MRI_MGH_VERSION && width > 0 && height > 0 && depth > 0);
84}
85
86//=============================================================================================================
87
88bool MriVolData::read(const QString& path)
89{
90 QVector<FIFFLIB::FiffCoordTrans> additionalTrans;
91 return MriMghIO::read(path, *this, additionalTrans);
92}
93
94//=============================================================================================================
95
96QVector<float> MriVolData::voxelDataAsFloat() const
97{
98 if (slices.isEmpty() || width <= 0 || height <= 0 || depth <= 0)
99 return {};
100
101 const int nPixels = width * height;
102 QVector<float> result(width * height * depth, 0.0f);
103
104 for (int k = 0; k < depth && k < slices.size(); ++k) {
105 const MriSlice& slice = slices[k];
106 int offset = k * nPixels;
107
108 switch (slice.pixelFormat) {
110 for (int p = 0; p < qMin(nPixels, slice.pixels.size()); ++p)
111 result[offset + p] = static_cast<float>(slice.pixels[p]);
112 break;
114 for (int p = 0; p < qMin(nPixels, slice.pixelsWord.size()); ++p)
115 result[offset + p] = static_cast<float>(slice.pixelsWord[p]);
116 break;
118 for (int p = 0; p < qMin(nPixels, slice.pixelsFloat.size()); ++p)
119 result[offset + p] = slice.pixelsFloat[p];
120 break;
121 }
122 }
123
124 return result;
125}
126
127//=============================================================================================================
128
130{
131 //
132 // Build voxel-to-surface-RAS transform (FreeSurfer convention).
133 //
134 // The direction cosine matrix Mdc stores the orientation of each voxel axis
135 // (columns are x, y, z directions). Scaling by voxel size gives the actual
136 // spacing matrix M:
137 //
138 // M = Mdc * diag(xsize, ysize, zsize)
139 //
140 // The origin P0 in RAS coordinates is:
141 //
142 // P0 = c_ras - M * (dim/2)
143 //
144 // The full 4x4 vox2ras matrix is:
145 //
146 // | M P0 | (in mm, then converted to meters for FIFF)
147 // | 0 1 |
148 //
149 // Reference: https://surfer.nmr.mgh.harvard.edu/fswiki/FsTutorial/MghFormat
150 //
151
152 // Construct M = Mdc * D (scale direction cosines by voxel sizes)
153 Matrix3f M;
154 M.col(0) = x_ras * xsize;
155 M.col(1) = y_ras * ysize;
156 M.col(2) = z_ras * zsize;
157
158 // Compute center voxel
159 Vector3f center(static_cast<float>(width) / 2.0f,
160 static_cast<float>(height) / 2.0f,
161 static_cast<float>(depth) / 2.0f);
162
163 // Compute P0 = c_ras - M * center
164 Vector3f P0 = c_ras - M * center;
165
166 // Build 4x4 matrix in meters (FreeSurfer uses mm, FIFF uses meters)
167 Matrix4f vox2ras = Matrix4f::Identity();
168 vox2ras.block<3, 3>(0, 0) = M / 1000.0f;
169 vox2ras.block<3, 1>(0, 3) = P0 / 1000.0f;
170
171 return vox2ras;
172}
MriMghIO class declaration.
MriVolData class declaration.
Header file describing the numerical values used in fif files.
#define FIFFV_MRI_PIXEL_BYTE
Definition fiff_file.h:702
#define FIFFV_MRI_PIXEL_FLOAT
Definition fiff_file.h:705
#define FIFFV_MRI_PIXEL_WORD
Definition fiff_file.h:703
MRI volume and coordinate-system I/O (volumes, voxel geometry, transforms).
constexpr int MRI_MGH_VERSION
Definition mri_types.h:57
constexpr int MRI_UCHAR
Definition mri_types.h:75
static bool read(const QString &mgzFile, MriVolData &volData, QVector< FIFFLIB::FiffCoordTrans > &additionalTrans, const QString &subjectMriDir=QString(), bool verbose=false)
Single MRI slice data.
QVector< unsigned char > pixels
QVector< unsigned short > pixelsWord
QVector< float > pixelsFloat
Eigen::Vector3f y_ras
bool read(const QString &path)
bool isValid() const
Eigen::Vector3f x_ras
QVector< MriSlice > slices
Eigen::Matrix4f computeVox2Ras() const
Eigen::Vector3f z_ras
Eigen::Vector3f c_ras
QVector< float > voxelDataAsFloat() const