JuliaNeuroscience / NIfTI.jl

Julia module for reading/writing NIfTI MRI files
Other
71 stars 35 forks source link

Adding support for sform and qform matrices as fields within the loaded nifti file header. #74

Open divital-coder opened 6 months ago

divital-coder commented 6 months ago

Is there a possibility to add support for sform and qform matrices as fields within the NIfTI.NIfTI1Header type?

Tokazama commented 6 months ago

Since the header is a reflection of the actually storage format it won't change to store a literal matrix (although sqform is pretty close already). We could make it easier to interact with it as if it were a matrix though. Similar to how Rotations.jl has array like rotation objects.

divital-coder commented 6 months ago

Okay so similar to a matrix but not the julia matrix itself, wondering if you were referring to the quaterns and srow values for interacting as if theyu were q and s form matrices... is that something that you were trying to entail

Tokazama commented 6 months ago

wondering if you were referring to the quaterns and srow values for interacting as if theyu were q and s form matrices...

Yeah, that's what I was referring to. At the same time, I'm not sure how that interface would really work in terms of the header struct itself. I think it makes more sense to extract those matrices from the header with a function than build them into it though. I'm not totally against it if you have a killer idea though.

divital-coder commented 6 months ago

So originally i asked this question, because i had to forumalte a nifti struct again after loading a nifti file using NIfTi.jl, following the nifti1io.h nifti image structure, cuz they include things like grid dimensions, spacings, ` /! \struct nifti_image \brief High level data structure for open nifti datasets in the nifti1_io API. Note that this structure is not part of the nifti1 format definition; it is used to implement one API for reading/writing formats in the nifti1 format. / typedef struct { /*!< Image storage struct **/

int ndim ; /!< last dimension greater than 1 (1..7) / int nx ; /!< dimensions of grid array / int ny ; /!< dimensions of grid array / int nz ; /!< dimensions of grid array / int nt ; /!< dimensions of grid array / int nu ; /!< dimensions of grid array / int nv ; /!< dimensions of grid array / int nw ; /!< dimensions of grid array / int dim[8] ; /!< dim[0]=ndim, dim[1]=nx, etc. / sizet nvox ; /!< number of voxels = nxnynz...nw / int nbyper ; /!< bytes per voxel, matches datatype / int datatype ; /*!< type of data in voxels: DT code /

float dx ; /!< grid spacings / float dy ; /!< grid spacings / float dz ; /!< grid spacings / float dt ; /!< grid spacings / float du ; /!< grid spacings / float dv ; /!< grid spacings / float dw ; /!< grid spacings / float pixdim[8] ; /!< pixdim[1]=dx, etc. /

float scl_slope ; /!< scaling parameter - slope / float scl_inter ; /!< scaling parameter - intercept /

float cal_min ; /!< calibration parameter, minimum / float cal_max ; /!< calibration parameter, maximum /

int qform_code ; /!< codes for (x,y,z) space meaning / int sform_code ; /!< codes for (x,y,z) space meaning /

int freq_dim ; /!< indexes (1,2,3, or 0) for MRI / int phase_dim ; /!< directions in dim[]/pixdim[] / int slice_dim ; /!< directions in dim[]/pixdim[] /

int slice_code ; /!< code for slice timing pattern / int slice_start ; /!< index for start of slices / int slice_end ; /!< index for end of slices / float slice_duration ; /!< time between individual slices /

/! quaternion transform parameters [when writing a dataset, these are used for qform, NOT qto_xyz] / float quatern_b , quatern_c , quatern_d , qoffset_x , qoffset_y , qoffset_z , qfac ;

mat44 qto_xyz ; /!< qform: transform (i,j,k) to (x,y,z) / mat44 qto_ijk ; /!< qform: transform (x,y,z) to (i,j,k) /

mat44 sto_xyz ; /!< sform: transform (i,j,k) to (x,y,z) / mat44 sto_ijk ; /!< sform: transform (x,y,z) to (i,j,k) /

float toffset ; /!< time coordinate offset /

int xyz_units ; /!< dx,dy,dz units: NIFTIUNITS code / int time_units ; /!< dt units: NIFTIUNITS code /

int nifti_type ; /!< 0==ANALYZE, 1==NIFTI-1 (1 file), 2==NIFTI-1 (2 files), 3==NIFTI-ASCII (1 file) / int intent_code ; /!< statistic type (or something) / float intent_p1 ; /!< intent parameters / float intent_p2 ; /!< intent parameters / float intent_p3 ; /!< intent parameters / char intent_name[16] ; /!< optional description of intent data /

char descrip[80] ; /!< optional text to describe dataset / char aux_file[24] ; /!< auxiliary filename /

char fname ; /!< header filename (.hdr or .nii) / char iname ; /!< image filename (.img or .nii) / int inameoffset ; /!< offset into iname where data starts / int swapsize ; /!< swap unit in image data (might be 0) / int byteorder ; /*!< byte order on disk (MSB or LSB_FIRST) / void data ; /!< pointer to data: nbypernvox bytes */

int num_ext ; /!< number of extensions in ext_list / nifti1_extension ext_list ; /!< array of extension structs (with data) / analyze_75_orient_code analyze75_orient; /!< for old analyze files, orient */

} nifti_image ;`

like the above

divital-coder commented 6 months ago

so if thats some that can be added, do let me know i will figure out how to do that within this package :) would love to contribute

divital-coder commented 6 months ago

also if thats something not ideal, i can figure out other ways to make them interact as a matrix

Tokazama commented 6 months ago

I have code laying around somewhere that can help with that. I have a lot of work I have to do at the present time so it's all dependent on if I can get away doing this sort of stuff during meetings where I'm simply supposed to be looking attentive.

divital-coder commented 6 months ago

ok great, but have you taken a look at the grid spacing and dimensions of grid array those are the ones i wanted to emphasize upon, also i totally understand your indulgences for the time being, i am very much interested in Nifti.jl cuz i have been using it for the past month or so :) thanks for building such functional and operational package, u are awesome