@@ -355,20 +355,17 @@ CorrectTEFid[fid_, dw_, te_, gyro_, ppmRan_] := Block[{missing},
355
355
(*HenkelFit*)
356
356
357
357
358
- HenkelFit [fid_ ,dw_ , te_ , gyro_ , ppmRan_ ]:= Block [{timeFull , firstTime , timeOr , timeMis , henk , fit },
358
+ HenkelFit [fid_ ,dw_ , te_ , gyro_ , ppmRan_ ]:= Block [{timeOr , timeMis , henk , fit },
359
359
(*get the correct timing of the fid and missing values*)
360
- timeFull = Reverse @ Range [dw (Length [fid ] - 1 ) + te , 0. , - dw ];
361
- firstTime = First [timeFull ];
362
- timeFull = If [Abs [firstTime - dw ] < firstTime , Prepend [timeFull , firstTime - dw ], timeFull ];
363
- timeOr = Select [timeFull , # >= te & ];
364
- timeMis = Select [timeFull , # < te & ];
360
+ timeOr = dw Range [1 , Length [fid ]];
361
+ timeMis = Reverse @ Range [te - dw , If [Mod [te , dw ] > 0.5 dw , - 0.5 dw , 0 ], - dw ];
365
362
366
363
(*get the henkel values*)
367
364
henk = HenkelSVDFid [fid , dw , gyro , ppmRan ];
368
365
fit = (PseudoInverse [HenkelSVDBasisC [timeOr , henk ]].fid );
369
366
370
367
(*missing and full henkle fid*)
371
- {If [timeMis =!= {}, HenkelSVDBasisC [timeMis ,henk ].fit ,{}], HenkelSVDBasisC [timeFull , henk ].fit }
368
+ {If [timeMis =!= {}, HenkelSVDBasisC [timeMis ,henk ].fit ,{}], HenkelSVDBasisC [timeOr , henk ].fit }
372
369
]
373
370
374
371
@@ -871,7 +868,7 @@ FitSpectra[specBasisIn_, specIn_, {st_,end_}, dtime_, {lwvals_?VectorQ, lwamsp_?
871
868
Off [FindMinimum ::cvmit ]; Off [FindMinimum ::lstol ];
872
869
873
870
(*logging*)
874
- log = {}; (*Print[Dynamic[Column[log]]];*)
871
+ log = {}; (*Print[Dynamic[Column[log]]]*) ;
875
872
876
873
(*get options*)
877
874
pad = OptionValue [PaddingFactor ];
@@ -1131,14 +1128,15 @@ FitSpectraError[{ppmFull_, spec_}, {timeFull_, timeBasis_}, {indSt_, indEnd_}, {
1131
1128
1132
1129
(*----------- Perform Fit and calculate errro -------------*)
1133
1130
(*perform Fit of basis spectra*)
1134
- fit = Quiet @ Clip [LeastSquares [Join [Transpose [Re [specBasisF ]],Transpose [Im [specBasisF ]]], Join [Re [specF ],Im [specF ]]],{0 ,Infinity }];
1135
-
1131
+ (*fit = Quiet@Clip[LeastSquares[Join[Transpose[Re[specBasisF]],Transpose[Im[specBasisF]]], Join[Re[specF],Im[specF]]],{0,Infinity}];*)
1132
+
1133
+ fit = Quiet @ NNLeastSquares [Transpose [Re [specBasisF ]], Re [specF ]];
1136
1134
(*define errors fid and spectra*)
1137
1135
errorS = specF - fit .specBasisF ;
1138
1136
errorF = fidF - fit .fidBasisF ;
1139
1137
1140
1138
(*Re and Im error normalized for number of points*)
1141
- err = Mean [Re [errorS ]^ 2 ] + Mean [Re [errorF ]^ 2 ] + Mean [Im [errorS ]^ 2 ] + Mean [Im [errorF ]^ 2 ];
1139
+ err = 2 Mean [Abs [errorS ]^ 2 ] + Mean [Abs [errorF ]^ 2 ] (*+ 2 Mean[Im[errorS]^2] + Mean[Im[errorF]^2]*) ;
1142
1140
1143
1141
If [init === 0 ,
1144
1142
(*constrain f between 0 and 1*)
@@ -1147,7 +1145,6 @@ FitSpectraError[{ppmFull_, spec_}, {timeFull_, timeBasis_}, {indSt_, indEnd_}, {
1147
1145
perr = ConFuncC [phi [[2 ]], - 0.5 , 0.5 , 5 ];
1148
1146
(*constrain gam to be positive*)
1149
1147
gerr = Total [ConFuncC [gam , 1 , 500 , 3 ]];
1150
-
1151
1148
(*no initial values, minimize RMSE with f, gam and phase contraint*)
1152
1149
err + ferr + gerr + perr
1153
1150
,
@@ -1173,7 +1170,8 @@ FitSpectraError[{ppmFull_, spec_}, {timeFull_, timeBasis_}, {indSt_, indEnd_}, {
1173
1170
specBasis = BasisSpectraApply [{ppmFull , timeFull , timeBasis }, {gam , eps , phi , f }, gyro , readout ];
1174
1171
1175
1172
(*perform Fit of basis spectra*)
1176
- fit = Quiet @ Clip [LeastSquares [Join [Transpose [Re [specBasis ]],Transpose [Im [specBasis ]]], Join [Re [spec ],Im [spec ]]],{0 ,Infinity }];
1173
+ (*fit = Quiet@Clip[LeastSquares[Join[Transpose[Re[specBasis]],Transpose[Im[specBasis]]], Join[Re[spec],Im[spec]]],{0,Infinity}];*)
1174
+ fit = Quiet @ NNLeastSquares [Transpose [Re [specBasis ]], Re [spec ]];
1177
1175
specFit = fit .specBasis ;
1178
1176
1179
1177
(*fit a spline through the residuals*)
@@ -1808,9 +1806,9 @@ CSIInterface[file_?StringQ, opts : OptionsPattern[]] := CSIInterface[file, {0, 0
1808
1806
1809
1807
CSIInterface [file_ ? StringQ , {tei_ ? NumberQ , bwi_ ? NumberQ }, OptionsPattern []] := Module [{
1810
1808
f , te , bw , nuc , field , gyro , names , met , metSel , metRef , method , plot , kload , rec , spectraC , dec , line , fine , den , z , y , x ,
1811
- sphase , status , statusP , kspace , noise , header , type , ham , spectra , spectraR , spec , proc , shift , times , fids , ppms , specs ,
1809
+ sphase , status , statusP , kspace , noise , header , type , ham , spectra , spectraR , spec , proc , shift , fids , specs ,
1812
1810
table , fit , basisFit , errorFit , pars , log , plots , specf , fitted , xm , ym , zm , dn , dc , mr , dw , nsamp , filt , teu ,
1813
- fileSave , spectraPlot , lab , fovz , fovy , fovx , coils , ncoils ,
1811
+ fileSave , spectraPlot , lab , fovz , fovy , fovx , coils , ncoils , teE ,
1814
1812
statPart , loadPart , reconPart , plotpart , fitPart , closePart
1815
1813
},
1816
1814
@@ -1961,28 +1959,29 @@ CSIInterface[file_?StringQ, {tei_?NumberQ, bwi_?NumberQ}, OptionsPattern[]] := M
1961
1959
{Button ["Save spar/sdat" ,
1962
1960
(*saving make better!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*)
1963
1961
spectraPlot = Switch [plot ,
1964
- "Raw" , spectraR ,
1965
- "Proc" ,spectra ,
1962
+ "Raw" , teE = te ; spectraR ,
1963
+ "Proc" ,teE = te ; spectra ,
1966
1964
"Cor" ,
1967
1965
If [! sphase ,
1968
1966
status = "Correcting phase of spectra" ; statusP = True ;
1969
1967
spectraC = Map [PhaseCorrectSpectra [ApodizePadSpectra [ShiftSpectra [# , {dw , gyro }, - shift ]], dw , teu , gyro , {10 , - 20 }, True ]& , spectra , {- 2 }];
1970
1968
status = "Done phase correcting spectra!" ; statusP = False ; sphase = True
1971
1969
];
1970
+ teE = 0. ;
1972
1971
spectraC
1973
1972
];
1974
1973
status = "Saving the CSI data" ;
1975
1974
fileSave = SystemDialogInput ["FileSave" ];
1976
1975
lab = mr <> If [plot === "Raw" ,"" ,If [dn , ", denoised" , "" ] <> If [dc , ", deconvolved" , "" ]]<> If [plot === "Cor" ," ,phase corrected" ,"" ];
1977
- If [fileSave =!= $Canceled , ExportSparSdat [fileSave , spectraPlot , {bw , te }, {gyro , nuc },{ "QMRITools Data" , fovx , fovz , 0 , 0 , lab }]];
1976
+ If [fileSave =!= $Canceled , ExportSparSdat [fileSave , spectraPlot , {bw , teE }, {gyro , nuc }, { fovz , fovy , fovx }]];
1978
1977
(*saving make better!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*)
1979
1978
,
1980
1979
Enabled -> Dynamic [rec && fovy > 0 && fovz > 0 && fovx > 0 ], Method -> "Queued" , ImageSize -> 175 ],
1981
1980
Row [{
1982
1981
{fovz , fovy , fovx } = Round [{fovz , fovy , fovx }];
1983
- TextCell [" FOV z " ], InputField [Dynamic [fovz , (fovz = Round [# ]) & ], Number , FieldSize -> 3 , ContinuousAction -> True , Background -> Dynamic [If [fovz > 0 , White , RGBColor [1 , 0.9 , 0.9 ]]]],
1984
- TextCell [" FOV y " ], InputField [Dynamic [fovy , (fovy = Round [# ]) & ], Number , FieldSize -> 3 , ContinuousAction -> True , Background -> Dynamic [If [fovy > 0 , White , RGBColor [1 , 0.9 , 0.9 ]]]],
1985
- TextCell [" FOV x " ], InputField [Dynamic [fovx , (fovx = Round [# ]) & ], Number , FieldSize -> 3 , ContinuousAction -> True , Background -> Dynamic [If [fovx > 0 , White , RGBColor [1 , 0.9 , 0.9 ]]]]
1982
+ TextCell [" vox z [mm] " ], InputField [Dynamic [fovz , (fovz = Round [# ]) & ], Number , FieldSize -> 3 , ContinuousAction -> True , Background -> Dynamic [If [fovz > 0 , White , RGBColor [1 , 0.9 , 0.9 ]]]],
1983
+ TextCell [" vox y [mm] " ], InputField [Dynamic [fovy , (fovy = Round [# ]) & ], Number , FieldSize -> 3 , ContinuousAction -> True , Background -> Dynamic [If [fovy > 0 , White , RGBColor [1 , 0.9 , 0.9 ]]]],
1984
+ TextCell [" vox x [mm] " ], InputField [Dynamic [fovx , (fovx = Round [# ]) & ], Number , FieldSize -> 3 , ContinuousAction -> True , Background -> Dynamic [If [fovx > 0 , White , RGBColor [1 , 0.9 , 0.9 ]]]]
1986
1985
}, " " ]}
1987
1986
};
1988
1987
@@ -1996,7 +1995,7 @@ CSIInterface[file_?StringQ, {tei_?NumberQ, bwi_?NumberQ}, OptionsPattern[]] := M
1996
1995
NotebookClose [plotwindow ];
1997
1996
(*basis spectra*)
1998
1997
status = "Generating basis spectra" ; statusP = True ;
1999
- {names , times , fids , ppms , specs , table } = GetSpectraBasisFunctions [metSel , {"ATP" }, BasisSequence -> {"PulseAcquire" , teu },
1998
+ {names , fids , specs , table } = GetSpectraBasisFunctions [metSel , {"ATP" }, BasisSequence -> {"PulseAcquire" , teu },
2000
1999
SpectraSamples -> nsamp , SpectraBandwith -> bw , SpectraPpmShift -> 0 , SpectraFieldStrength -> field , SpectraNucleus -> nuc ];
2001
2000
status = "Done generating basis spectra!" ; statusP = False ;
2002
2001
@@ -2212,12 +2211,13 @@ FromVaxD=Compile[{{int,_Integer,0}},Block[{bin,sign ,fraction, exponent},
2212
2211
(* ::Subsubsection::Closed:: *)
2213
2212
(*ExportSparSdat*)
2214
2213
2214
+ Options [ExportSparSdat ]= {SparName -> "QMRITools" , SparOrientation -> {0 ,0 },SparID -> "" }
2215
2215
2216
- SyntaxInformation [ExportSparSdat ] = {"ArgumentsPattern" -> {_ , _ , {_ ,_ }, {_ ,_ }}};
2216
+ SyntaxInformation [ExportSparSdat ] = {"ArgumentsPattern" -> {_ , _ , {_ ,_ }, {_ ,_ }, _ ., OptionsPattern [] }};
2217
2217
2218
- ExportSparSdat [file_ ,specs_ ,{bw_ ,te_ },{gyro_ ,nuc_ }] := ExportSparSdat [file ,specs ,{bw ,te },{gyro ,nuc },{ "QMRITools Data" ,1 ,1 , 0 , 0 , "QMRITools Data" } ]
2218
+ ExportSparSdat [file_ , specs_ , {bw_ , te_ }, {gyro_ , nuc_ }, opts : OptionsPattern []] := ExportSparSdat [file , specs , {bw , te }, {gyro , nuc }, { 1 ,1 ,1 }, opts ]
2219
2219
2220
- ExportSparSdat [file_ ,specs_ ,{bw_ ,te_ },{gyro_ ,nuc_ },pars_ ]:= Block [{fidsOut ,numsOut ,fileOut ,datOut ,headOut },
2220
+ ExportSparSdat [file_ , specs_ , {bw_ , te_ }, {gyro_ , nuc_ }, vox_ , opts : OptionsPattern [] ]:= Block [{fidsOut ,numsOut ,fileOut ,datOut ,headOut },
2221
2221
(*export data*)
2222
2222
fidsOut = Map [ShiftedInverseFourier ,specs ,{- 2 }];
2223
2223
numsOut = binO = ToVaxD [Flatten [TransData [{Re @ fidsOut ,Im @ fidsOut },"l" ]]];
@@ -2227,8 +2227,8 @@ ExportSparSdat[file_,specs_,{bw_,te_},{gyro_,nuc_},pars_]:=Block[{fidsOut,numsOu
2227
2227
Close [fileOut ];
2228
2228
2229
2229
(*export header*)
2230
- headOut = MakeSpar [specs ,{bw ,te },{gyro ,nuc },pars ];
2231
- Export [file <> ".SPAR" ,headOut ,"text" ];
2230
+ headOut = MakeSpar [specs , {bw , te }, {gyro , nuc }, vox , opts ];
2231
+ Export [file <> ".SPAR" , headOut , "text" ];
2232
2232
]
2233
2233
2234
2234
@@ -2256,11 +2256,10 @@ ToVaxD=Compile[{{num,_Real,0}},Block[{signBin,numA,exp,expBin,frac,fracBin},
2256
2256
(* ::Subsubsection::Closed:: *)
2257
2257
(*MakeSpar*)
2258
2258
2259
+ Options [MakeSpar ]= Options [ExportSparSdat ];
2259
2260
2260
- MakeSpar [{dimzO_ ,dimyO_ ,dimxO_ ,nsampO_ },{bw_ ,te_ },{gyro_ ,nuc_ }]:= MakeSpar [{dimzO ,dimyO ,dimxO ,nsampO },{bw ,te },{gyro ,nuc },{"QMRITools Data" ,1 ,1 ,0 ,0 ,"QMRITools Data" }];
2261
-
2262
- MakeSpar [specs_ ,{bw_ ,te_ },{gyro_ ,nuc_ },{name_ ,fov1_ ,fov2_ ,tr_ ,teS_ ,proc_ }]:= Block [{
2263
- dimzO ,dimyO ,dimxO ,nsampO ,gyroO ,nucO ,bwO ,teO ,nameO ,fov1O ,fov2O ,trO ,thickO ,processingO ,
2261
+ MakeSpar [specs_ , {bw_ , te_ }, {gyro_ , nuc_ }, vox_ , OptionsPattern []]:= Block [{
2262
+ dimzO ,dimyO ,dimxO ,nsampO ,gyroO ,nucO ,bwO ,teO ,nameO , hf , ps , id ,
2264
2263
text ,lab ,filHeader ,fixedHeader , vals , head ,row ,depth
2265
2264
},
2266
2265
(*swith between data dimensions*)
@@ -2285,12 +2284,13 @@ MakeSpar[specs_,{bw_,te_},{gyro_,nuc_},{name_,fov1_,fov2_,tr_,teS_,proc_}]:=Bloc
2285
2284
];
2286
2285
2287
2286
(*manditory input paramters*)
2288
- {gyroO ,nucO }= {10 ^ 6 gyro ,nuc };
2289
- {bwO ,teO }= {bw ,te };
2287
+ {gyroO ,nucO } = {10 ^ 6 gyro ,nuc };
2288
+ {bwO , teO } = {bw , te };
2289
+
2290
2290
(*optional input parameters*)
2291
- { nameO , fov1O , fov2O , trO } = { name , fov1 , fov2 , tr } ;
2292
- thickO = Round [ fov2 / dimzO ] ;
2293
- processingO = proc ; (*prefer the processing steps*)
2291
+ nameO = OptionValue [ SparName ] ;
2292
+ { hf , ps } = OptionValue [ SparOrientation ] ; (*head or feat first / prone or supine*)
2293
+ id = OptionValue [ SparID ] ; (*prefer the processing steps*)
2294
2294
2295
2295
(*all needed fixed header information orders of text and lab are important*)
2296
2296
text = {
@@ -2318,39 +2318,47 @@ MakeSpar[specs_,{bw_,te_},{gyro_,nuc_},{name_,fov1_,fov2_,tr_,teS_,proc_}]:=Bloc
2318
2318
(*from input*)
2319
2319
filHeader = {
2320
2320
(*general acquistion names*)
2321
- "patient_position" -> " \" head_first \" " , (* "\"head_first\"","\"feet_first \""*)
2322
- "patient_orientation" -> " \" supine \" " , (* "\"supine\"","\"prone\""*)
2321
+ "patient_position" -> Switch [ hf , 0 , "\" head_first\" " , 1 , "\" feat_first \" " ],
2322
+ "patient_orientation" -> Switch [ ps , 0 , "\" supine\" " , 1 , "\" prone\" " ],
2323
2323
(*get from input window*)
2324
- "examination_name" -> nameO ,"patient_name" -> nameO ,
2325
- "phase_encoding_fov" -> fov1O ,(*mm fov in freq*)
2326
- "slice_thickness" -> fov2O ,(*mm fov in phase*)
2327
- "slice_distance" -> If [depth > 2 ,thickO ,0 ],(*mm slice thickness*)
2328
- "repetition_time" -> trO ,(*ms*)
2324
+ "examination_name" -> "Generated by QMRITools" ,
2325
+ "patient_name" -> nameO ,
2326
+ "phase_encoding_fov" -> vox [[2 ]] dimyO ,(*mm fov in freq*)
2327
+ "slice_thickness" -> vox [[1 ]] dimzO ,(*mm fov in phase*)
2328
+ "slice_distance" -> If [depth > 2 , vox [[1 ]], 0 ],(*mm slice thickness*)
2329
+ "repetition_time" -> 0 ,(*ms could be an input parameter but not relevant for now*)
2329
2330
(*save date*)
2330
2331
"scan_date" -> StringRiffle [ToString /@ DateList [Today ][[1 ;; 3 ]],"." ]<> " " <> StringRiffle [ToString /@ Round [DateList [Now ][[- 3 ;; ]]],":" ],
2331
2332
(*get from gui with processing settings*)
2332
- "scan_id" -> processingO ,
2333
+ "scan_id" -> id (*a string describing the data*) ,
2333
2334
2334
2335
(*get from processing tool*)
2335
2336
"synthesizer_frequency" -> gyroO ,(*MHz*)
2336
- "sample_frequency" -> bwO ,(*Hz*)
2337
- "nucleus" -> nucO ,(*string*)
2337
+ "sample_frequency" -> bwO ,(*Hz*)
2338
+ "nucleus" -> nucO ,(*string*)
2338
2339
"echo_time" -> teO ,(*ms*)
2339
- "spectrum_echo_time" -> If [ teS === 0 , teO ,teS ], (*ms, !!! should be 0 after phasing*)
2340
+ "spectrum_echo_time" -> teO ,
2340
2341
2341
2342
(*get from data dimensions*)
2342
2343
"num_dimensions" -> Clip [depth ,{2 ,4 }],
2343
2344
(*dynamics if needed*)
2344
- "rows" -> row ,"spec_row_upper_val" -> row ,"spec_num_row" -> row ,
2345
+ "rows" -> row ,
2346
+ "spec_row_upper_val" -> row ,
2347
+ "spec_num_row" -> row ,
2345
2348
(*fid parameters and time*)
2346
- "samples" -> nsampO ,"spec_num_col" -> nsampO ,"dim1_pnts" -> nsampO ,
2347
- "dim1_step" -> 1. / bwO ,(*s*) "spec_col_upper_val" -> (nsampO - 1 )(1. / bw ),(*s*)
2349
+ "samples" -> nsampO ,
2350
+ "spec_num_col" -> nsampO ,
2351
+ "dim1_pnts" -> nsampO ,
2352
+ "dim1_step" -> 1. / bwO ,(*s*)
2353
+ "spec_col_upper_val" -> (nsampO - 1 )(1. / bw ),(*s*)
2348
2354
(*data dimensions*)
2349
- "dim2_pnts" -> dimxO ,"dim3_pnts" -> dimyO ,
2355
+ "dim2_pnts" -> dimxO ,
2356
+ "dim3_pnts" -> dimyO ,
2350
2357
"nr_of_slices_for_multislice" -> dimzO ,
2351
2358
"nr_phase_encoding_profiles" -> dimxO ,
2352
2359
"nr_of_phase_encoding_profiles_ky" -> dimyO ,
2353
- "phase_encoding_enable" -> If [depth <= 2 ,"\" no\" " ,"\" yes\" " ],"dim4_pnts" -> dimzO
2360
+ "phase_encoding_enable" -> If [depth <= 2 ,"\" no\" " ,"\" yes\" " ],
2361
+ "dim4_pnts" -> dimzO
2354
2362
};
2355
2363
2356
2364
(*fixed parameters that are default*)
@@ -2383,7 +2391,7 @@ MakeSpar[specs_,{bw_,te_},{gyro_,nuc_},{name_,fov1_,fov2_,tr_,teS_,proc_}]:=Bloc
2383
2391
"dim4_ext" -> "[index]" ,"dim4_low_val" -> 1.0 ,"dim4_step" -> 1.0 ,"dim4_direction" -> "slice" ,"dim4_t0_point" -> "-" ,
2384
2392
(*closing values*)
2385
2393
"echo_acquisition" -> "NO" ,"TSI_factor" -> 0 ,"resp_motion_comp_technique" -> "NONE" ,"de_coupling" -> "NO" ,
2386
- "equipment_sw_verions" -> "QMRITools CSIinterface " ,"placeholder1" -> "" ,"placeholder2" -> ""
2394
+ "equipment_sw_verions" -> "QMRITools" ,"placeholder1" -> "" ,"placeholder2" -> ""
2387
2395
};
2388
2396
2389
2397
(*generate the header values*)
0 commit comments