From 6f4167a9775918ae7f1fa995a81a6f22dbbdf315 Mon Sep 17 00:00:00 2001 From: William Stonewall Monroe <wsmonroe@login001.cm.cluster> Date: Mon, 9 Jul 2018 14:08:55 -0500 Subject: [PATCH] adding the official NODDI toolbox version 1.0.1, a gitignore file, and some additional sample scripts --- .gitignore | 3 + NODDI_toolbox_v1.01/.DS_Store | Bin 0 -> 6148 bytes NODDI_toolbox_v1.01/LICENSE.txt | 14 + .../ParforProgMonv2/ParforProgMon.m | 63 + NODDI_toolbox_v1.01/ParforProgMonv2/example.m | 27 + .../java/ParforProgressMonitor$1.class | Bin 0 -> 214 bytes .../ParforProgressMonitor$ProgServer$1.class | Bin 0 -> 1499 bytes .../ParforProgressMonitor$ProgServer.class | Bin 0 -> 3542 bytes .../ParforProgressMonitor$ProgThing.class | Bin 0 -> 244 bytes .../ParforProgressMonitor$ProgWorker.class | Bin 0 -> 908 bytes .../java/ParforProgressMonitor.class | Bin 0 -> 921 bytes .../java/ParforProgressMonitor.java | 198 + .../ParforProgMonv2/license.txt | 28 + NODDI_toolbox_v1.01/VERSION | 2 + NODDI_toolbox_v1.01/fitting/CreateROI.m | 83 + NODDI_toolbox_v1.01/fitting/DT_DesignMatrix.m | 77 + NODDI_toolbox_v1.01/fitting/EstimateSigma.m | 27 + NODDI_toolbox_v1.01/fitting/FSL2Protocol.m | 95 + NODDI_toolbox_v1.01/fitting/FitLinearDT.m | 55 + NODDI_toolbox_v1.01/fitting/GetSearchGrid.m | 654 + NODDI_toolbox_v1.01/fitting/GradDescDecode.m | 37 + NODDI_toolbox_v1.01/fitting/GradDescEncode.m | 41 + NODDI_toolbox_v1.01/fitting/GradDescLimits.m | 69 + .../fitting/GridSearchRician.m | 134 + NODDI_toolbox_v1.01/fitting/PlotFittedModel.m | 58 + NODDI_toolbox_v1.01/fitting/QualityOfFit.m | 31 + NODDI_toolbox_v1.01/fitting/RemoveNegMeas.m | 78 + NODDI_toolbox_v1.01/fitting/SaveAsNIfTI.m | 35 + .../fitting/SaveParamsAsNIfTI.m | 153 + .../fitting/SchemeToProtocol.m | 34 + .../fitting/ThreeStageFittingVoxel.m | 219 + NODDI_toolbox_v1.01/fitting/VoxelDataViewer.m | 70 + NODDI_toolbox_v1.01/fitting/batch_fitting.m | 130 + .../fitting/batch_fitting_single.m | 95 + NODDI_toolbox_v1.01/fitting/fmincon_fix.m | 23 + NODDI_toolbox_v1.01/fitting/fobj_rician.m | 43 + NODDI_toolbox_v1.01/fitting/fobj_rician_fix.m | 36 + NODDI_toolbox_v1.01/fitting/fobj_rician_st.m | 69 + NODDI_toolbox_v1.01/models/BesselJ_RootsCyl.m | 31 + .../models/CylNeumanLePar_PGSE.m | 42 + .../models/CylNeumanLePerp_PGSE.m | 137 + NODDI_toolbox_v1.01/models/GetB0.m | 16 + NODDI_toolbox_v1.01/models/GetB_Values.m | 25 + .../models/GetFibreOrientation.m | 14 + .../models/GetParameterIndex.m | 20 + .../models/GetParameterStrings.m | 34 + .../models/GetScalingFactors.m | 44 + NODDI_toolbox_v1.01/models/MakeDT_Matrix.m | 14 + NODDI_toolbox_v1.01/models/MakeModel.m | 89 + NODDI_toolbox_v1.01/models/NumFreeParams.m | 11 + NODDI_toolbox_v1.01/models/RicianLogLik.m | 22 + NODDI_toolbox_v1.01/models/SynthMeas.m | 212 + .../models/SynthMeasHinderedDiffusion_PGSE.m | 61 + NODDI_toolbox_v1.01/models/SynthMeasIsoGPD.m | 73 + NODDI_toolbox_v1.01/models/logbesseli0.m | 25 + .../models/watson/LegendreGaussianIntegral.m | 155 + .../models/watson/NODDI_erfi.m | 21 + .../SynthMeasWatsonHinderedDiffusion_PGSE.m | 56 + .../watson/SynthMeasWatsonSHCylNeuman_PGSE.m | 138 + .../watson/SynthMeasWatsonSHCylSingleRadGPD.m | 45 + .../SynthMeasWatsonSHCylSingleRadGPD_PGSE.m | 90 + ...thMeasWatsonSHCylSingleRadIsoVIsoDot_GPD.m | 54 + ...easWatsonSHCylSingleRadIsoVIsoDot_GPD_B0.m | 52 + .../SynthMeasWatsonSHCylSingleRadIsoV_GPD.m | 58 + ...SynthMeasWatsonSHCylSingleRadIsoV_GPD_B0.m | 51 + .../SynthMeasWatsonSHCylSingleRadTortGPD.m | 53 + ...asWatsonSHCylSingleRadTortIsoVIsoDot_GPD.m | 56 + ...atsonSHCylSingleRadTortIsoVIsoDot_GPD_B0.m | 54 + ...ynthMeasWatsonSHCylSingleRadTortIsoV_GPD.m | 60 + ...hMeasWatsonSHCylSingleRadTortIsoV_GPD_B0.m | 53 + .../SynthMeasWatsonSHStickIsoVIsoDot_B0.m | 52 + .../watson/SynthMeasWatsonSHStickIsoV_B0.m | 49 + .../SynthMeasWatsonSHStickTortIsoVIsoDot_B0.m | 53 + .../SynthMeasWatsonSHStickTortIsoV_B0.m | 49 + .../watson/WatsonHinderedDiffusionCoeff.m | 51 + .../models/watson/WatsonSHCoeff.m | 191 + .../niftimatlib-1.2/README.txt | 237 + .../niftimatlib-1.2/niftimatlib-1.2/gpl.txt | 340 + .../niftimatlib-1.2/license.txt | 96 + .../matlab/@file_array/Contents.m | 55 + .../niftimatlib-1.2/matlab/@file_array/cat.m | 44 + .../matlab/@file_array/ctranspose.m | 14 + .../niftimatlib-1.2/matlab/@file_array/disp.m | 39 + .../matlab/@file_array/display.m | 19 + .../matlab/@file_array/double.m | 17 + .../niftimatlib-1.2/matlab/@file_array/end.m | 22 + .../matlab/@file_array/fieldnames.m | 21 + .../matlab/@file_array/file_array.m | 47 + .../matlab/@file_array/horzcat.m | 16 + .../matlab/@file_array/isnan.m | 26 + .../matlab/@file_array/length.m | 16 + .../matlab/@file_array/loadobj.m | 19 + .../matlab/@file_array/ndims.m | 17 + .../matlab/@file_array/numel.m | 19 + .../matlab/@file_array/numeric.m | 19 + .../matlab/@file_array/permute.m | 15 + .../matlab/@file_array/private/datatypes.m | 61 + .../matlab/@file_array/private/dim.m | 42 + .../matlab/@file_array/private/dtype.m | 91 + .../matlab/@file_array/private/file2mat.m | 21 + .../@file_array/private/file2mat.mexa64 | Bin 0 -> 20614 bytes .../@file_array/private/file2mat.mexglx | Bin 0 -> 18298 bytes .../@file_array/private/file2mat.mexmaci | Bin 0 -> 34360 bytes .../@file_array/private/file2mat.mexmaci64 | Bin 0 -> 18376 bytes .../@file_array/private/file2mat.mexw32 | Bin 0 -> 50688 bytes .../@file_array/private/file2mat.mexw64 | Bin 0 -> 17920 bytes .../matlab/@file_array/private/fname.m | 40 + .../matlab/@file_array/private/mat2file.m | 21 + .../@file_array/private/mat2file.mexa64 | Bin 0 -> 20110 bytes .../@file_array/private/mat2file.mexglx | Bin 0 -> 13773 bytes .../@file_array/private/mat2file.mexmaci | Bin 0 -> 17668 bytes .../@file_array/private/mat2file.mexmaci64 | Bin 0 -> 13928 bytes .../@file_array/private/mat2file.mexw32 | Bin 0 -> 12800 bytes .../@file_array/private/mat2file.mexw64 | Bin 0 -> 13312 bytes .../matlab/@file_array/private/mystruct.m | 21 + .../matlab/@file_array/private/offset.m | 40 + .../matlab/@file_array/private/permission.m | 48 + .../@file_array/private/resize_scales.m | 29 + .../matlab/@file_array/private/scl_inter.m | 41 + .../matlab/@file_array/private/scl_slope.m | 40 + .../matlab/@file_array/private/src/README | 12 + .../matlab/@file_array/private/src/file2mat.c | 644 + .../matlab/@file_array/private/src/mat2file.c | 385 + .../matlab/@file_array/reshape.m | 26 + .../niftimatlib-1.2/matlab/@file_array/size.m | 49 + .../matlab/@file_array/subsasgn.m | 158 + .../matlab/@file_array/subsref.m | 186 + .../matlab/@file_array/transpose.m | 15 + .../matlab/@file_array/vertcat.m | 16 + .../niftimatlib-1.2/matlab/@nifti/Contents.m | 84 + .../niftimatlib-1.2/matlab/@nifti/create.m | 78 + .../niftimatlib-1.2/matlab/@nifti/disp.m | 27 + .../niftimatlib-1.2/matlab/@nifti/display.m | 18 + .../matlab/@nifti/fieldnames.m | 30 + .../niftimatlib-1.2/matlab/@nifti/nifti.m | 95 + .../matlab/@nifti/private/M2Q.m | 38 + .../matlab/@nifti/private/Q2M.m | 36 + .../matlab/@nifti/private/decode_qform0.m | 65 + .../matlab/@nifti/private/empty_hdr.m | 20 + .../matlab/@nifti/private/encode_qform0.m | 50 + .../matlab/@nifti/private/findindict.m | 42 + .../matlab/@nifti/private/getdict.m | 158 + .../matlab/@nifti/private/mayo2nifti1.m | 72 + .../matlab/@nifti/private/mayostruc.m | 85 + .../matlab/@nifti/private/nifti_stats.m | 46 + .../matlab/@nifti/private/niftistruc.m | 86 + .../matlab/@nifti/private/read_extras.m | 32 + .../matlab/@nifti/private/read_hdr.m | 90 + .../matlab/@nifti/private/read_hdr_raw.m | 98 + .../matlab/@nifti/private/spm_existfile.m | 33 + .../matlab/@nifti/private/spm_fileparts.m | 26 + .../matlab/@nifti/private/src/README | 17 + .../matlab/@nifti/private/src/nifti1.h | 1227 ++ .../matlab/@nifti/private/src/nifti_stats.c | 11282 ++++++++++++++++ .../@nifti/private/src/nifti_stats_mex.c | 129 + .../matlab/@nifti/private/write_extras.m | 41 + .../matlab/@nifti/private/write_hdr_raw.m | 82 + .../niftimatlib-1.2/matlab/@nifti/structn.m | 24 + .../niftimatlib-1.2/matlab/@nifti/subsasgn.m | 404 + .../niftimatlib-1.2/matlab/@nifti/subsref.m | 245 + .../niftimatlib-1.2/matlab/Makefile | 85 + .../niftimatlib-1.2/matlab/make.m | 41 + .../matlab/spm_flip_analyze_images.m | 19 + PPMI_NODDI.m | 51 + importPPMIlist.m | 45 + rotateone.txt | 151 + 166 files changed, 23228 insertions(+) create mode 100644 .gitignore create mode 100644 NODDI_toolbox_v1.01/.DS_Store create mode 100644 NODDI_toolbox_v1.01/LICENSE.txt create mode 100644 NODDI_toolbox_v1.01/ParforProgMonv2/ParforProgMon.m create mode 100644 NODDI_toolbox_v1.01/ParforProgMonv2/example.m create mode 100644 NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$1.class create mode 100644 NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgServer$1.class create mode 100644 NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgServer.class create mode 100644 NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgThing.class create mode 100644 NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgWorker.class create mode 100644 NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor.class create mode 100644 NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor.java create mode 100644 NODDI_toolbox_v1.01/ParforProgMonv2/license.txt create mode 100644 NODDI_toolbox_v1.01/VERSION create mode 100644 NODDI_toolbox_v1.01/fitting/CreateROI.m create mode 100644 NODDI_toolbox_v1.01/fitting/DT_DesignMatrix.m create mode 100644 NODDI_toolbox_v1.01/fitting/EstimateSigma.m create mode 100644 NODDI_toolbox_v1.01/fitting/FSL2Protocol.m create mode 100644 NODDI_toolbox_v1.01/fitting/FitLinearDT.m create mode 100644 NODDI_toolbox_v1.01/fitting/GetSearchGrid.m create mode 100644 NODDI_toolbox_v1.01/fitting/GradDescDecode.m create mode 100644 NODDI_toolbox_v1.01/fitting/GradDescEncode.m create mode 100644 NODDI_toolbox_v1.01/fitting/GradDescLimits.m create mode 100644 NODDI_toolbox_v1.01/fitting/GridSearchRician.m create mode 100644 NODDI_toolbox_v1.01/fitting/PlotFittedModel.m create mode 100644 NODDI_toolbox_v1.01/fitting/QualityOfFit.m create mode 100644 NODDI_toolbox_v1.01/fitting/RemoveNegMeas.m create mode 100644 NODDI_toolbox_v1.01/fitting/SaveAsNIfTI.m create mode 100644 NODDI_toolbox_v1.01/fitting/SaveParamsAsNIfTI.m create mode 100644 NODDI_toolbox_v1.01/fitting/SchemeToProtocol.m create mode 100644 NODDI_toolbox_v1.01/fitting/ThreeStageFittingVoxel.m create mode 100644 NODDI_toolbox_v1.01/fitting/VoxelDataViewer.m create mode 100644 NODDI_toolbox_v1.01/fitting/batch_fitting.m create mode 100644 NODDI_toolbox_v1.01/fitting/batch_fitting_single.m create mode 100644 NODDI_toolbox_v1.01/fitting/fmincon_fix.m create mode 100644 NODDI_toolbox_v1.01/fitting/fobj_rician.m create mode 100644 NODDI_toolbox_v1.01/fitting/fobj_rician_fix.m create mode 100644 NODDI_toolbox_v1.01/fitting/fobj_rician_st.m create mode 100644 NODDI_toolbox_v1.01/models/BesselJ_RootsCyl.m create mode 100644 NODDI_toolbox_v1.01/models/CylNeumanLePar_PGSE.m create mode 100644 NODDI_toolbox_v1.01/models/CylNeumanLePerp_PGSE.m create mode 100644 NODDI_toolbox_v1.01/models/GetB0.m create mode 100644 NODDI_toolbox_v1.01/models/GetB_Values.m create mode 100644 NODDI_toolbox_v1.01/models/GetFibreOrientation.m create mode 100644 NODDI_toolbox_v1.01/models/GetParameterIndex.m create mode 100644 NODDI_toolbox_v1.01/models/GetParameterStrings.m create mode 100644 NODDI_toolbox_v1.01/models/GetScalingFactors.m create mode 100644 NODDI_toolbox_v1.01/models/MakeDT_Matrix.m create mode 100644 NODDI_toolbox_v1.01/models/MakeModel.m create mode 100644 NODDI_toolbox_v1.01/models/NumFreeParams.m create mode 100644 NODDI_toolbox_v1.01/models/RicianLogLik.m create mode 100644 NODDI_toolbox_v1.01/models/SynthMeas.m create mode 100644 NODDI_toolbox_v1.01/models/SynthMeasHinderedDiffusion_PGSE.m create mode 100644 NODDI_toolbox_v1.01/models/SynthMeasIsoGPD.m create mode 100644 NODDI_toolbox_v1.01/models/logbesseli0.m create mode 100644 NODDI_toolbox_v1.01/models/watson/LegendreGaussianIntegral.m create mode 100644 NODDI_toolbox_v1.01/models/watson/NODDI_erfi.m create mode 100644 NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonHinderedDiffusion_PGSE.m create mode 100644 NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylNeuman_PGSE.m create mode 100644 NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadGPD.m create mode 100644 NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadGPD_PGSE.m create mode 100644 NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD.m create mode 100644 NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD_B0.m create mode 100644 NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoV_GPD.m create mode 100644 NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoV_GPD_B0.m create mode 100644 NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortGPD.m create mode 100644 NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD.m create mode 100644 NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD_B0.m create mode 100644 NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoV_GPD.m create mode 100644 NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoV_GPD_B0.m create mode 100644 NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickIsoVIsoDot_B0.m create mode 100644 NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickIsoV_B0.m create mode 100644 NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickTortIsoVIsoDot_B0.m create mode 100644 NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickTortIsoV_B0.m create mode 100644 NODDI_toolbox_v1.01/models/watson/WatsonHinderedDiffusionCoeff.m create mode 100644 NODDI_toolbox_v1.01/models/watson/WatsonSHCoeff.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/README.txt create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/gpl.txt create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/license.txt create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/Contents.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/cat.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/ctranspose.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/disp.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/display.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/double.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/end.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/fieldnames.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/file_array.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/horzcat.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/isnan.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/length.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/loadobj.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/ndims.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/numel.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/numeric.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/permute.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/datatypes.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/dim.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/dtype.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexa64 create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexglx create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexmaci create mode 100755 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexmaci64 create mode 100755 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexw32 create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexw64 create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/fname.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexa64 create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexglx create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexmaci create mode 100755 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexmaci64 create mode 100755 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexw32 create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexw64 create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mystruct.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/offset.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/permission.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/resize_scales.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/scl_inter.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/scl_slope.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/src/README create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/src/file2mat.c create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/src/mat2file.c create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/reshape.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/size.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/subsasgn.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/subsref.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/transpose.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/vertcat.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/Contents.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/create.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/disp.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/display.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/fieldnames.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/nifti.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/M2Q.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/Q2M.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/decode_qform0.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/empty_hdr.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/encode_qform0.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/findindict.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/getdict.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/mayo2nifti1.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/mayostruc.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/nifti_stats.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/niftistruc.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/read_extras.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/read_hdr.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/read_hdr_raw.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/spm_existfile.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/spm_fileparts.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/README create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/nifti1.h create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/nifti_stats.c create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/nifti_stats_mex.c create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/write_extras.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/write_hdr_raw.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/structn.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/subsasgn.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/subsref.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/Makefile create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/make.m create mode 100644 NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/spm_flip_analyze_images.m create mode 100644 PPMI_NODDI.m create mode 100644 importPPMIlist.m create mode 100644 rotateone.txt diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f8fb9f3 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.nii +*.BRIK +*.HEAD diff --git a/NODDI_toolbox_v1.01/.DS_Store b/NODDI_toolbox_v1.01/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..6b31e7fe961b6f9db30bb31b0b1c2449b3896fe3 GIT binary patch literal 6148 zcmeHKONzok5Uo-{!Hr9oeTBI}BYFZa;6e<7L>Qb|XXUv(ny)^HlFVknjl2p~ue(yO zL*62l5)obf?7u`7A~J&;%GE;O?7n%=Mww9{9A_M*mF9Q*-JZ_9>fwZOr*Z)Eg6oOj zHgW1Ojae!{1*iZOpaN9jp9)y-h0W%Hj8uRMP=SX6_I)UD!<yIy`lkcIM*!diX*aBW zmH-w@0Bd3whzv}F3Jj{|h@nA8zGPiZ>;i)>n!|_YlQkz4^{3<f;^m?>kdX>dfma2_ zv0YgI-@yNv|6fVmQ2{FOQ3~i}y<M;HO4(a`FK4~Bz;|$~xxvk_b_#;GW1zQVY^)tG cy(sF6t#Q95c7aYu-swR8445u7D)4Rv?jOn(rT_o{ literal 0 HcmV?d00001 diff --git a/NODDI_toolbox_v1.01/LICENSE.txt b/NODDI_toolbox_v1.01/LICENSE.txt new file mode 100644 index 0000000..0961e7b --- /dev/null +++ b/NODDI_toolbox_v1.01/LICENSE.txt @@ -0,0 +1,14 @@ +LICENSE for NODDI matlab toolbox: + +The Software is made available for use under the Open Source-approved Artistic Licence 2.0. The Owner draws your attention to the fact that the Software has been developed for and is intended for use in a research environment only. No endorsement can be given for other use including, but not limited to, use in a clinical environment. + +External tools included in NODDI matlab toolbox: + +1. erfi matlab function + * By Per Sundqvist, No license specified + * Downloaded from http://www.mathworks.com/matlabcentral/fileexchange/18238-erfi-function + +2. PARFOR Progress Monitor v2 + * BSD license + * Downloaded from http://www.mathworks.com/matlabcentral/fileexchange/31673-parfor-progress-monitor-v2 + diff --git a/NODDI_toolbox_v1.01/ParforProgMonv2/ParforProgMon.m b/NODDI_toolbox_v1.01/ParforProgMonv2/ParforProgMon.m new file mode 100644 index 0000000..a1848d2 --- /dev/null +++ b/NODDI_toolbox_v1.01/ParforProgMonv2/ParforProgMon.m @@ -0,0 +1,63 @@ +% Copyright 2009 The MathWorks, Inc. + +classdef ParforProgMon < handle + + properties ( GetAccess = private, SetAccess = private ) + Port + HostName + end + + properties (Transient, GetAccess = private, SetAccess = private) + JavaBit + end + + methods ( Static ) + function o = loadobj( X ) + % Once we've been loaded, we need to reconstruct ourselves correctly as a + % worker-side object. + o = ParforProgMon( {X.HostName, X.Port} ); + end + end + + methods + function o = ParforProgMon( s, N, progressStepSize, width, height ) + % ParforProgMon Build a Parfor Progress Monitor + % Use the syntax: ParforProgMon( 'Window Title', N, progressStepSize, width, height ) + % where N is the number of iterations in the PARFOR loop + % progressStepSize indicates after how many iterations progress is shown + % width indicates the width of the progress window + % height indicates the width of the progress window + + if nargin == 1 && iscell( s ) + % "Private" constructor used on the workers + o.JavaBit = ParforProgressMonitor.createWorker( s{1}, s{2} ); + o.Port = []; + elseif nargin == 5 + % Normal construction + o.JavaBit = ParforProgressMonitor.createServer( s, N, progressStepSize, width, height ); + o.Port = double( o.JavaBit.getPort() ); + % Get the client host name from pctconfig + cfg = pctconfig; + o.HostName = cfg.hostname; + else + error( 'Public constructor is: ParforProgressMonitor( ''Text'', N, progressStepSize, width, height )' ); + end + end + + function X = saveobj( o ) + % Only keep the Port and HostName + X.Port = o.Port; + X.HostName = o.HostName; + end + + function increment( o ) + % Update the UI + o.JavaBit.increment(); + end + + function delete( o ) + % Close the UI + o.JavaBit.done(); + end + end +end diff --git a/NODDI_toolbox_v1.01/ParforProgMonv2/example.m b/NODDI_toolbox_v1.01/ParforProgMonv2/example.m new file mode 100644 index 0000000..93c348f --- /dev/null +++ b/NODDI_toolbox_v1.01/ParforProgMonv2/example.m @@ -0,0 +1,27 @@ +% ParforProgMon - M object to make ParforProgressMonitor objects easier to +% use. Create one of these on the client outside your PARFOR loop with a +% name for the window. Pass it in to the PARFOR loop, and have the workers +% call "increment" at the end of each iteration. This sends notification +% back to the client which then updates the UI. + +% ParforProgMon Build a Parfor Progress Monitor +% Use the syntax: ParforProgMon( 'Window Title', N, progressStepSize, width, height ) +% where N is the number of iterations in the PARFOR loop +% progressStepSize indicates after how many iterations progress is shown +% width indicates the width of the progress window +% height indicates the width of the progress window + +tic +N = 500000; +progressStepSize = 100; +ppm = ParforProgMon('Example: ', N, progressStepSize, 300, 80); + +parfor ii=1:N + rand(100,100); + if mod(ii,progressStepSize)==0 + ppm.increment(); + end +end + +ppm.delete() +toc \ No newline at end of file diff --git a/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$1.class b/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$1.class new file mode 100644 index 0000000000000000000000000000000000000000..abc01f9e56564e2bfb9e468e1bddbb8e2751f3f5 GIT binary patch literal 214 zcmZvWK?=e^3`KvmI$8^MBZ4azt}S{6QE*WdJi%DU+A_>Qrg}IR9>7D1>Av|S;lqC+ z-{1QKV2eaSDa3^M;-6fYLuCzNan^kId}d#=2_g5cYCNxN{nCW#-WAq|%9Xik9{#2< zA<R38)rJ5<a&*q{&gu|MAf)Y`%xYI=r)zDBhA`{I)1|;Y`LnIQ2;w3PWJegv981TN Iq1L6NKb5sLg#Z8m literal 0 HcmV?d00001 diff --git a/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgServer$1.class b/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgServer$1.class new file mode 100644 index 0000000000000000000000000000000000000000..78e99d373bec1f53a4a42594be3fbb6d0c1a0f0a GIT binary patch literal 1499 zcma)6+fEZv6kVsS9T*0|%1uB)9iSAU+(kh|5Cm)iDWa$^LwkgQcBYw`0)N1pKVVdh zk3N}5F`D=Rev>ioGt&wL3{29!&%Uj*yD#V0pYJ~b^x{=1su2;SLq-j5$!I{QAYC$| z=njspkQ;qM)gwr+ggzN%o@c)}4G1z=g4==*$+&~NB6e7Kk4U&D;l6}126;<Ms|Md* z*3t}Yh9T&z>$ci0VVsN$mbsST))u!Ilo`X|)<jyfZEiE%h%IQ=Yts@g7PsxVY3Pn= zsfQuM1U90Rc9fwte75^c`!Yjd!c1|7ikNQjxm;$ITT9w%nlyeZXAlhwr}BiOB{$<* zwqTPJX3k3TDP1_$pPE<KhPI^<?xc}So3?JO#ksR?rW8!zp@Mo`Q&5L13YwrQn8cKV zN0^o{qhMAzJjS$w7~%}I0w|i+jJ0UOu?T29r>9fgQZR>k1q*m0$RgFNr8#M4vT5${ zRF{GTmLxn?u#9I4o?}J93#e4aQ?or%MYV?k43&r1&aZCpq{9$8R4wKVLzGFvONQpN zAQ?(?*_7t+agF*K2)l)swPcdosP=VtGmM_2UF|V(|4!82rXoaVi*rDj)c7J=uRv=# z4;qbL-Twd?N^I`Xh~}ujMd*G3T@(g|Fm#@Kj%Ph(X&HVb-vNO$cy64db0EfD%VxQe zV(1LJ*Bmo@^*X95Ob!J$QV&i<9GXiU)0;Jhs_;oi0&r*HUoYH$<rQs7cf?XupOz49 zlDx*9xVEEbav68Is0)FVX^4nZrwGmTDAmwB*1}g=DOLs`PWwa8k&k{&<iT*APHiOn ziC08A_Q4{J`|w2$;QvA@8hfHa;=o&?H=!1SJ|o};*^#ec-w^QF1!BJSJc3n_3Yy(b zp>rwumF}9;o<aVBvXuiUo>ZR4#kMzjRD>$&l*gq!LL$zy2J*PP2U!StREflVZesP6 z8t{((=X-jLKhUD?VG|!=;S*ZC#DBx`Q=+YIOdG<)1N5@C<0_p(gwucrXru?anq>O^ E0-1P$3;+NC literal 0 HcmV?d00001 diff --git a/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgServer.class b/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgServer.class new file mode 100644 index 0000000000000000000000000000000000000000..82801f09c3c4f26ca94e16ecd1849feb1f02c561 GIT binary patch literal 3542 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 Rwfr9B8Vqy~=`TAH{{_g2Lq7lj literal 0 HcmV?d00001 diff --git a/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgThing.class b/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgThing.class new file mode 100644 index 0000000000000000000000000000000000000000..593257c01ca4552b5bdcfc447df3180c874db735 GIT binary patch literal 244 zcmZvW%?`mp6ot>N>S&eN*x1-uu+hXTNF)}b39%nFs!h!#Gv(ndJb;H1w^kN5_q#tQ z=bqR5@dU6yUmz5S31Oi#tFB7dgw}L+AowSv6(QQ0o6Xd!sCXEq(w>b?t;wx&Zew&& z8#^!MT?+IF<G=Swqu*Z&o%5fcK3;3B?6Q*1DMuJIHc2IQo@|e$$~ejJuU|kQc$^>b Ye2xnrV743bKKNFFE;C{!p@S$0KdOE_kpKVy literal 0 HcmV?d00001 diff --git a/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgWorker.class b/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor$ProgWorker.class new file mode 100644 index 0000000000000000000000000000000000000000..0f2fdff6b99c4575419736c4c265ad7da5aa7b78 GIT binary patch literal 908 zcmZ`%U2hUW6g|V&0^JIwmbQdiR8$JJ2tFybFI8g`sw5B_Urd(m6t~bFGP^bYBcGeJ zl4#-&@JAWXkVZ_3*<|jW`*H5MXXn@N?>_-F(M%(aQW^`mo1%Bm9QQ4h(}<gJ91ko! zOe2X$7Pc(ZENlzJPdZA60^-2<Z&W}(*FJSVJN1#{59-}ed;Xv$kl6KnFWeKzS8k>c zw%!ZG_SLZz$h19QzCAzdOWkw&BSuo5?`nA_ePTx|rgX6zI_~h$8BZ%ni`~b{mlk#e zAYdQ(zSR38CkSL9P@gxl-Es7Z(jBb^S_Z+PB0Z(cjg}dZ?y7U`%GaKmUzl6DW0thB zgq%6@HZsWCSi~)^Fx}smVZE!|p$u)*kr!B=$@1!pE61Uyd>c=Yx6lwM&7D#<{En0! zN=;V(Ua~W^cl}f8Qk>2IL-aoJH&9B0aP6<ouO^kaJ5qu96=VLqaH@4rJ1!$Db9+$Y zQ&}*&Bf^gw@Igh4Aha=h6p7ho-k$OnrOi|)h*WD=h*pbNh+QxwaGPh24WM2z3X?*E zP)%l5kiQ1_I0XbYejxs#dddDv#3o3zYu{jfMbg;R1&cwrRle596t;i_BhSd_Iqxr+ zX<-e!C}NL3U?Fm3VJ*hS^}n;$nJ_?NMlUf9yyRj_*r0EA+T=!tv{kJYCpU|?N#PFD Z5f&C{3oI|70%Vhvt%52~oAz-c^#{bdxd8wG literal 0 HcmV?d00001 diff --git a/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor.class b/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor.class new file mode 100644 index 0000000000000000000000000000000000000000..94e4a8acfad0961d9a0da817ffb61eb1a4254b49 GIT binary patch literal 921 zcmaJ=&rcIU6#k~&-Jwf`3RY;L@~cYQgAH6X)OaD9G^s*TqVc$`Ls=|4WOgC`S$dH~ z5^rAoqm19U2tBNw!@QaIzVCf+-rN24`}+?7yJ$(Q`Vgqu?UBTq4+rZ$X0Rc#DX}F{ z7htT|jUr|C$3YycSinCtdem3uQkk2}du=``Bk@?EV1q{|VKgFdXjG7>f6%=~?=-j! z+T$P^wfl)7rqktW_6`Gctc_(F6~}LM6eil#?_@dx&c6Pr1m=5Tq~2bf4U{<w24i~s zSD%OKJPCCaOFX$1O-mAZmL)n(F(p#bdl9mZmjd}l^Br~i`oav=>(Gi;Gb?^-pC_=M z8Ju`d5zE*vqJhd(a9W84H|<7nIWx0B>8`H_gHtt31eP+P^&Nq=?8wC27XPLTb-R0T z+gyR&tWI)#|C!!S$9Bz)lfbZ?b{2UG6C05H5besNfD-N_hXvlA)9cYLUqgIot*q9{ zj<`Z@&#k!MkgvF37!z3JK1U|VwA?be4|sDJD>L6iEZyYWg3A*ydku&Am}?@1M>tTO zpyuo#=(VNPXl>kWUBUaxL#msSelly7z8qFCOS?(!0^fwv3~>@g*uPEU9_<|MyjS=G D%75W4 literal 0 HcmV?d00001 diff --git a/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor.java b/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor.java new file mode 100644 index 0000000..fa7b565 --- /dev/null +++ b/NODDI_toolbox_v1.01/ParforProgMonv2/java/ParforProgressMonitor.java @@ -0,0 +1,198 @@ +import javax.swing.*; +import java.io.*; +import java.net.*; +import java.util.concurrent.atomic.AtomicBoolean; + +// Copyright 2009 The MathWorks, Inc. + +public class ParforProgressMonitor { + + /** + * Create a "server" progress monitor - this runs on the desktop client and + * pops up the progress monitor UI. + */ + public static ProgServer createServer( String s, int N, int progressStepSize, int width, int height ) + throws IOException { + ProgServer ret = new ProgServer( s, N, progressStepSize, width, height ); + ret.start(); + return ret; + } + + /** + * Create a "worker" progress monitor - runs on the remote lab and sends updates + */ + public static ProgWorker createWorker( String host, int port ) + throws IOException { + return new ProgWorker( host, port ); + } + + /** + * Common interface exposed by both objects + */ + public interface ProgThing { + public void increment(); + public void done(); + } + + /** + * The worker-side object. Simply connects to the server to indicate that a + * quantum of progress has been made. This is a very basic implementation - + * a more sophisticated implementation would use a persistent connection, + * and a SocketChannel on the client with a thread doing a select loop and + * accepting connections etc. + */ + private static class ProgWorker implements ProgThing { + private int fPort; + private String fHost; + private ProgWorker( String host, int port ) { + fHost = host; + fPort = port; + } + + /** + * Connect and disconnect immediately to indicate progress + */ + public void increment() { + try { + Socket s = new Socket( fHost, fPort ); + s.close(); + } catch( Exception e ) { + e.printStackTrace(); + } + } + + /** + * Nothing for us to do here + */ + public void done() { + } + } + + /** + * The client-side object which pops up a window with a + * JProgressBar. Accepts connections from the workers, and then disconnects + * them immediately. Beware, the connection backlog of the ServerSocket + * might be insufficient. + */ + private static class ProgServer implements Runnable, ProgThing { + private JFrame fFrame; + private JProgressBar fBar; + private ServerSocket fSocket; + private int fValue, fN, fStep; + private String title; + private Thread fThread; + private AtomicBoolean fKeepGoing; + + private ProgServer( String s, int N, int progressStepSize, int width, int height ) throws IOException { + // The UI + fFrame = new JFrame( s ); + fBar = new JProgressBar( 0, N ); + fFrame.getContentPane().add( fBar ); + fFrame.pack(); + fFrame.setSize(width,height); + fFrame.setLocationRelativeTo( null ); + fFrame.setVisible( true ); + + // How far we are through - requires synchronized access + fValue = 0; + fN = N; + fStep = progressStepSize; + title = s; + + // Get an anonymous port + fSocket = new ServerSocket( 0 ); + // Set SO_TIMEOUT so that we don't block forever + fSocket.setSoTimeout( 100 ); + + // Our background thread + fThread = new Thread( this ); + fThread.setDaemon( true ); + + // Used to indicate to fThread when it's time to go + fKeepGoing = new AtomicBoolean( true ); + } + + /** + * Don't start the Thread in the constructor + */ + public void start() { fThread.start(); } + + /** + * Loop over accepting connections and updating + */ + public void run() { + while( fKeepGoing.get() ) { + try { + acceptAndIncrement(); + } catch( Exception e ) { + if( fKeepGoing.get() ) { + e.printStackTrace(); + } + } + } + } + + /** + * If there's a connection - accept and then disconnect; increment our count. + */ + private void acceptAndIncrement() throws IOException { + Socket worker; + try { + worker = fSocket.accept(); + } catch( SocketTimeoutException timeout ) { + // don't care about timeouts + return; + } + worker.close(); + increment(); + } + + + /** + * On the EDT, update the progress bar + */ + private void updateBar( final int newVal ) { + SwingUtilities.invokeLater( new Runnable() { + public void run() { + fBar.setValue( fStep*newVal ); + double percentage = 100.0*fStep*newVal/fN; + fFrame.setTitle(title + (int)percentage + "% completed."); + if ( newVal == fBar.getMaximum() ) { + done(); + } + } + } ); + } + + /** + * M-code needs to know which port we got + */ + public int getPort() { + return ((InetSocketAddress)fSocket.getLocalSocketAddress()).getPort(); + } + + /** + * Provide public access to this for pool-close PARFORs + */ + public synchronized void increment() { + fValue++; + updateBar( fValue ); + } + + /** + * Shut it all down + */ + public void done() { + fKeepGoing.set( false ); + try { + fSocket.close(); + } catch( Exception e ) { + e.printStackTrace(); + } + fFrame.dispose(); + } + } + + /** This class isn't useful - use the static methods */ + private ParforProgressMonitor() {} +} \ No newline at end of file diff --git a/NODDI_toolbox_v1.01/ParforProgMonv2/license.txt b/NODDI_toolbox_v1.01/ParforProgMonv2/license.txt new file mode 100644 index 0000000..27fd717 --- /dev/null +++ b/NODDI_toolbox_v1.01/ParforProgMonv2/license.txt @@ -0,0 +1,28 @@ +Copyright (c) 2011, Willem-Jan de Goeij +Copyright (c) 2009, The MathWorks, Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the distribution + * Neither the name of the The MathWorks, Inc. nor the names + of its contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/NODDI_toolbox_v1.01/VERSION b/NODDI_toolbox_v1.01/VERSION new file mode 100644 index 0000000..eff3164 --- /dev/null +++ b/NODDI_toolbox_v1.01/VERSION @@ -0,0 +1,2 @@ +This version of the toolbox is extracted from WUZI r1020. + diff --git a/NODDI_toolbox_v1.01/fitting/CreateROI.m b/NODDI_toolbox_v1.01/fitting/CreateROI.m new file mode 100644 index 0000000..ee75648 --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/CreateROI.m @@ -0,0 +1,83 @@ +function CreateROI(dwifile, maskfile, outputfile) +% +% function CreateROI(dwifile, maskfile) +% +% This function converts 4-D DWI volume into the data format suitable +% for subsequent NODDI fitting. +% +% Inputs: +% +% dwifile: the 4-D DWI volume in NIfTI or Analyze format +% +% maskfile: the brain mask volume in NIfTI or Analyze format which +% specifies the voxels to include for fitting +% +% outputfile: the mat file to store the resulting data for subsequent +% fitting +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +% first check if niftimatlib is available +if (exist('nifti') ~= 2) + error('niftimatlib does not appear to be installed or included in the search path'); + return; +end + +% load the DWI volume +fprintf('loading the DWI volume : %s\n', dwifile); +dwi = nifti(dwifile); +xsize = dwi.dat.dim(1); +ysize = dwi.dat.dim(2); +zsize = dwi.dat.dim(3); +ndirs = dwi.dat.dim(4); + +% convert the data from scanner order to voxel order +dwi = dwi.dat(:,:,:,:); +dwi = permute(dwi,[4 1 2 3]); + +% load the brain mask volume +fprintf('loading the brain mask : %s\n', maskfile); +mask = nifti(maskfile); +mask = mask.dat(:,:,:); + +% create an ROI that is in voxel order and contains just the voxels in the +% brain mask +fprintf('creating the output ROI ...\n'); + +% first get the number of voxels first +% to more efficiently allocate the memory +count=0; +for i=1:xsize + for j=1:ysize + for k=1:zsize + if mask(i,j,k) > 0 + count = count + 1; + mask(i,j,k) = count; + end + end + end +end +roi = zeros(count,ndirs); +idx = zeros(count,3); + +% next construct the ROI +count=0; +for i=1:xsize + for j=1:ysize + for k=1:zsize + if mask(i,j,k) > 0 + count = count + 1; + roi(count,:) = dwi(:,i,j,k); + idx(count,:) = [i j k]; + end + end + end +end + +% save the ROI +fprintf('saving the output ROI as %s\n', outputfile); +save(outputfile, 'roi', 'mask', 'idx'); + +disp('done'); + diff --git a/NODDI_toolbox_v1.01/fitting/DT_DesignMatrix.m b/NODDI_toolbox_v1.01/fitting/DT_DesignMatrix.m new file mode 100644 index 0000000..f27307f --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/DT_DesignMatrix.m @@ -0,0 +1,77 @@ +function X=DT_DesignMatrix(protocol) +% Computes the design matrix for DT fitting using linear least squares. +% +% function X=DT_DesignMatrix(protocol) +% +% protocol is the acquisition protocol. +% +% author: Daniel C Alexander (d.alexander@ucl.ac.uk) +% + + +GAMMA = 2.675987E8; + +if(strcmp(protocol.pulseseq, 'PGSE') || strcmp(protocol.pulseseq, 'STEAM')) + modQ = GAMMA*protocol.smalldel'.*protocol.G'; + q = repmat(modQ, [1,3]).*protocol.grad_dirs; + diffTime = (protocol.delta' - protocol.smalldel'/3); + + % Compute the design matrix + X = [ones(1, length(q)); -diffTime'.*q(:,1)'.*q(:,1)'; -2*diffTime'.*q(:,1)'.*q(:,2)'; -2*diffTime'.*q(:,1)'.*q(:,3)'; -diffTime'.*q(:,2)'.*q(:,2)'; -2*diffTime'.*q(:,2)'.*q(:,3)'; -diffTime'.*q(:,3)'.*q(:,3)']'; + +elseif(strcmp(protocol.pulseseq, 'OGSE')) + q = protocol.grad_dirs; + b = GetB_Values(protocol); + + % Compute the design matrix + X = [ones(1, length(q)); -b.*q(:,1)'.*q(:,1)'; -2*b.*q(:,1)'.*q(:,2)'; -2*b.*q(:,1)'.*q(:,3)'; -b.*q(:,2)'.*q(:,2)'; -2*b.*q(:,2)'.*q(:,3)'; -b.*q(:,3)'.*q(:,3)']'; + +elseif(strcmp(protocol.pulseseq, 'DSE')) + + bValue = GetB_ValuesDSE(protocol.G, protocol.delta1, protocol.delta2, protocol.delta3, protocol.t1, protocol.t2, protocol.t3); + + % Compute the design matrix + X = [ones(1, length(protocol.G)); -bValue.*protocol.grad_dirs(:,1)'.*protocol.grad_dirs(:,1)'; -2*bValue.*protocol.grad_dirs(:,1)'.*protocol.grad_dirs(:,2)'; -2*bValue.*protocol.grad_dirs(:,1)'.*protocol.grad_dirs(:,3)'; -bValue.*protocol.grad_dirs(:,2)'.*protocol.grad_dirs(:,2)'; -2*bValue.*protocol.grad_dirs(:,2)'.*protocol.grad_dirs(:,3)'; -bValue.*protocol.grad_dirs(:,3)'.*protocol.grad_dirs(:,3)']'; + +elseif(strcmp(protocol.pulseseq, 'FullSTEAM')) + + tdd = protocol.gap1 + protocol.gap2 + protocol.TM + 2*protocol.sdelc + 2*protocol.smalldel/3 + 2*protocol.sdelr; + tcc = protocol.TM + 2*protocol.sdelc/3 + 2*protocol.sdelr; + trr = protocol.TM + 2*protocol.sdelr/3; + tdc = protocol.TM + protocol.sdelc + 2*protocol.sdelr; + tdr = protocol.TM + protocol.sdelr; + tcr = protocol.TM + protocol.sdelr; + + qdx = protocol.grad_dirs(:,1)'.*protocol.G.*protocol.smalldel; + qdy = protocol.grad_dirs(:,2)'.*protocol.G.*protocol.smalldel; + qdz = protocol.grad_dirs(:,3)'.*protocol.G.*protocol.smalldel; + qcx = protocol.cG(:,1)'.*protocol.sdelc; + qcy = protocol.cG(:,2)'.*protocol.sdelc; + qcz = protocol.cG(:,3)'.*protocol.sdelc; + qrx = protocol.rG(:,1)'.*protocol.sdelr; + qry = protocol.rG(:,2)'.*protocol.sdelr; + qrz = protocol.rG(:,3)'.*protocol.sdelr; + + Fxx = -GAMMA^2*(qdx.^2.*tdd + qcx.^2.*tcc + qrx.^2.*trr + 2*qdx.*qcx.*tdc + 2*qdx.*qrx.*tdr + 2*qcx.*qrx.*tcr); + Fyy = -GAMMA^2*(qdy.^2.*tdd + qcy.^2.*tcc + qry.^2.*trr + 2*qdy.*qcy.*tdc + 2*qdy.*qry.*tdr + 2*qcy.*qry.*tcr); + Fzz = -GAMMA^2*(qdz.^2.*tdd + qcz.^2.*tcc + qrz.^2.*trr + 2*qdz.*qcz.*tdc + 2*qdz.*qrz.*tdr + 2*qcz.*qrz.*tcr); + Fxy = -GAMMA^2*(qdx.*qdy.*tdd + qcx.*qcy.*tcc + qrx.*qry.*trr + (qdx.*qcy+qdy.*qcx).*tdc + (qdx.*qry+qdy.*qrx).*tdr + (qcx.*qry+qcy.*qrx).*tcr)*2; + Fxz = -GAMMA^2*(qdx.*qdz.*tdd + qcx.*qcz.*tcc + qrx.*qrz.*trr + (qdx.*qcz+qdz.*qcx).*tdc + (qdx.*qrz+qdz.*qrx).*tdr + (qcx.*qrz+qcz.*qrx).*tcr)*2; + Fyz = -GAMMA^2*(qdy.*qdz.*tdd + qcy.*qcz.*tcc + qry.*qrz.*trr + (qdy.*qcz+qdz.*qcy).*tdc + (qdy.*qrz+qdz.*qry).*tdr + (qcy.*qrz+qcz.*qry).*tcr)*2; + + % Compute the design matrix + X = [ones(1, length(protocol.G)); Fxx; Fxy; Fxz; Fyy; Fyz; Fzz]'; +save /tmp/FS_X.mat X; + +elseif(strcmp(protocol.pulseseq, 'GEN')) + + bValue = GENGetB_Values(protocol); + % Compute the design matrix + bValue=bValue'; + X = [ones(1, length(protocol.delta)); -bValue.*protocol.grad_dirs(:,1)'.*protocol.grad_dirs(:,1)'; -2*bValue.*protocol.grad_dirs(:,1)'.*protocol.grad_dirs(:,2)'; -2*bValue.*protocol.grad_dirs(:,1)'.*protocol.grad_dirs(:,3)'; -bValue.*protocol.grad_dirs(:,2)'.*protocol.grad_dirs(:,2)'; -2*bValue.*protocol.grad_dirs(:,2)'.*protocol.grad_dirs(:,3)'; -bValue.*protocol.grad_dirs(:,3)'.*protocol.grad_dirs(:,3)']'; + +else + + error('Not implemented for pulse sequence: %s', protocol.pulseseq); +end + diff --git a/NODDI_toolbox_v1.01/fitting/EstimateSigma.m b/NODDI_toolbox_v1.01/fitting/EstimateSigma.m new file mode 100644 index 0000000..93ddd42 --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/EstimateSigma.m @@ -0,0 +1,27 @@ +function sigma = EstimateSigma(signal, protocol, model) +% +% function sigma = EstimateSigma(signal, protocol, model) +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +if model.sigma.perVoxel == 1 + sigma = std(signal(protocol.b0_Indices), 1); + % if lower than the minimum SNR + sigmaMin = model.sigma.minSNR*mean(signal(protocol.b0_Indices)); + if sigma < sigmaMin + sigma = sigmaMin; + end +else + if isfield(model.sigma, 'globalSigma') + sigma = model.sigma.globalSigma; + elseif isfield(model.sigma, 'globalSNR') + sigma = model.sigma.globalSNR*mean(signal(protocol.b0_Indices)); + else + disp('You have chosen not to use per voxel sigma estimate'); + error('You need to specify either sigma.globalSigma or sigma.globalSNR for your model'); + end +end + +% apply the scaling parameter that may improve fitting +sigma = sigma/model.sigma.scaling; diff --git a/NODDI_toolbox_v1.01/fitting/FSL2Protocol.m b/NODDI_toolbox_v1.01/fitting/FSL2Protocol.m new file mode 100644 index 0000000..be1c271 --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/FSL2Protocol.m @@ -0,0 +1,95 @@ +function protocol = FSL2Protocol(bvalfile, bvecfile, b0threshold) +% +% function protocol = FSL2Protocol(bvalfile, bvecfile, b0threshold) +% +% Note: for NODDI, the exact sequence timing is not important. +% this function reverse-engineerings one possible sequence timing +% given the b-values. +% +% b0threshold: optional argument to specify a non-zero value for your b=0 +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +if nargin == 2 + b0threshold = 0; +end + +protocol.pulseseq = 'PGSE'; +protocol.schemetype = 'multishellfixedG'; +protocol.teststrategy = 'fixed'; + +% load bval +bval = load(bvalfile); +bval = bval'; + +% set total number of measurements +protocol.totalmeas = length(bval); + +% set the b=0 indices +protocol.b0_Indices = find(bval<=b0threshold); +protocol.numZeros = length(protocol.b0_Indices); + +% find the unique non-zero b-values +B = unique(bval(bval>b0threshold)); + +% set the number of shells +protocol.M = length(B); +for i=1:length(B) + protocol.N(i) = length(find(bval==B(i))); +end + +% maximum b-value in the s/mm^2 unit +maxB = max(B); + +% set maximum G = 40 mT/m +Gmax = 0.04; + +% set smalldel and delta and G +GAMMA = 2.675987E8; +tmp = nthroot(3*maxB*10^6/(2*GAMMA^2*Gmax^2),3); +for i=1:length(B) + protocol.udelta(i) = tmp; + protocol.usmalldel(i) = tmp; + protocol.uG(i) = sqrt(B(i)/maxB)*Gmax; +end + +protocol.delta = zeros(size(bval))'; +protocol.smalldel = zeros(size(bval))'; +protocol.G = zeros(size(bval))'; + +for i=1:length(B) + tmp = find(bval==B(i)); + for j=1:length(tmp) + protocol.delta(tmp(j)) = protocol.udelta(i); + protocol.smalldel(tmp(j)) = protocol.usmalldel(i); + protocol.G(tmp(j)) = protocol.uG(i); + end +end + +% load bvec +bvec = load(bvecfile); +protocol.grad_dirs = bvec'; + +% some systems set vector to zeros for b=0 +% the codes below try to account for this +if isempty(protocol.b0_Indices) + for i=1:protocol.totalmeas + if norm(protocol.grad_dirs(i,:)) == 0 + protocol.G(i) = 0.0; + protocol.b0_Indices = [protocol.b0_Indices i]; + end + end + protocol.numZeros = length(protocol.b0_Indices); +end + +% make the gradient directions for b=0's [1 0 0] +for i=1:length(protocol.b0_Indices) + protocol.grad_dirs(protocol.b0_Indices(i),:) = [1 0 0]; +end + +% make sure the gradient directions are unit vectors +for i=1:protocol.totalmeas + protocol.grad_dirs(i,:) = protocol.grad_dirs(i,:)/norm(protocol.grad_dirs(i,:)); +end + diff --git a/NODDI_toolbox_v1.01/fitting/FitLinearDT.m b/NODDI_toolbox_v1.01/fitting/FitLinearDT.m new file mode 100644 index 0000000..411e90e --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/FitLinearDT.m @@ -0,0 +1,55 @@ +function [D, Ep] = FitLinearDT(E, protocol, fitS0) +% Fits the DT model using linear least squares. +% +% D=FitLinearDT(E, protocol, fitS0) +% returns [logS(0) Dxx Dxy Dxz Dyy Dyz Dzz]. +% +% E is the set of measurements. +% +% protocol is the acquisition protocol. +% +% +% fitS0 is a flag for enabling the fitting of S0 +% +% author: Daniel C Alexander (d.alexander@ucl.ac.uk) +% Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +if (nargin < 3) + fitS0 = 0; +end + +if (isfield(protocol, 'dti_subset')) + E = E(protocol.dti_subset); + protocol.delta = protocol.delta(protocol.dti_subset); + protocol.smalldel = protocol.smalldel(protocol.dti_subset); + protocol.G = protocol.G(protocol.dti_subset); + protocol.grad_dirs = protocol.grad_dirs(protocol.dti_subset,:); + protocol.b0_Indices = intersect(protocol.b0_Indices, protocol.dti_subset); +end + +X = DT_DesignMatrix(protocol); +if fitS0 == 0 + X = X(:,2:end); +end +Xi = pinv(X); + +% We assume that E are all positives +% If not, first filter out the nonpositive values with RemoveNegMeas + +if (fitS0) + D = Xi*log(E); + if (nargout > 1) + Ep = exp(X*D); + end +else + S0 = squeeze(mean(E(protocol.b0_Indices))); + E = E/S0; + D = zeros(7,1); + D(1) = log(S0); + D(2:end) = Xi*log(E); + if (nargout > 1) + Ep = S0*exp(X*D(2:end)); + end +end + diff --git a/NODDI_toolbox_v1.01/fitting/GetSearchGrid.m b/NODDI_toolbox_v1.01/fitting/GetSearchGrid.m new file mode 100644 index 0000000..502c48a --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/GetSearchGrid.m @@ -0,0 +1,654 @@ +function grid = GetSearchGrid(model, material, fix, fixedvals) +% Returns a list of parameter combinations for the specified model +% for the GridSearch function to use in search for the combination +% that best fits a set of measurements. +% +% grid=GetSearchGrid(model, material, fix, fixedvals) +% returns a list of parameter combinations for the model that +% are realistic for a particular material type. +% +% model is a string specifying the model. +% +% material is a string specifying the type of material, which +% determines the range of each parameter in the grid. +% Options are: +% invivo +% invivopreterm +% invivowhitematter +% fixedwhitematter +% +% fix is a list of binary numbers specifying which +% model parameters have fixed values. By default the +% list is all zeros so no parameters are fixed. +% +% fixedvals is an array the same size as fix that specifies +% the fixed values of any fixed parameters. Entries in +% fixedvals in locations where fix has value zero are not +% used. +% +% author: Daniel C Alexander (d.alexander@ucl.ac.uk) +% Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +if(nargin<3) + fix=zeros(6); + fixedvals = zeros(6); +end + +if(strcmp(material, 'invivo')) + fs = [0.0 0.25 0.5 0.75 1.0]; + dpars = [13.0 17.0 21.0]*1E-10; + disos = [10.0 20.0 30.0 50.0]*1E-10; + Rs=[0.5 1 2 4]*1E-6; + irfracs=[0 0.1 0.2 0.3]; + fisos=[0.0 0.25 0.5 0.75 1.0]; + kappas = [0.5 1 2 4 8]; + fic = [0.3 0.5 0.7]; +elseif(strcmp(material, 'exvivo')) + fs = [0.0 0.25 0.5 0.75 1.0]; + dpars = [3.0 4.5 6.0 7.5]*1E-10; + disos = [5.0 10.0 15.0]*1E-10; + Rs=[1 2 4 8]*1E-6; + irfracs=[0 0.1 0.2 0.3]; + fisos=[0.0 0.25 0.5 0.75 1.0]; + kappas = [0.5 1 2 4 8]; + fic = [0.3 0.5 0.7]; +elseif(strcmp(material, 'invivopreterm')) + fs = [0.0 0.1 0.2 0.3]; + dpars = [13.0 17.0 21.0]*1E-10; + disos = [10.0 20.0 30.0 50.0]*1E-10; + Rs=[1 2 4 8]*1E-6; + irfracs=[0 0.1 0.2 0.3]; + fisos=[0.0 0.25 0.5 0.75 1.0]; + kappas = [0.5 1 2 4 8]; + fic = [0.3 0.5 0.7]; +elseif(strcmp(material, 'invivowhitematter')) + fs = [0.5 0.7 0.9]; + dpars = [10.0 13.0 15.0 17.0 19.0 21.0 23.0 25.0]*1E-10; + disos = [10.0 20.0 30.0 50.0]*1E-10; + Rs=[1 2 4 8]*1E-6; + irfracs=[0 0.1 0.2 0.3]; + fisos=[0 0.2 0.4]; + kappas = [4 8 16 32 64 128]; + fic = [0.3 0.5 0.7]; +elseif(strcmp(material, 'postmortemwhitematter')) + fs = [0.5 0.7 0.9]; + dpars = [2.0 3.0 4.0 5.0 6.0]*1E-10; + disos = [5.0 10.0 15.0]*1E-10; + Rs=[1 2 4 8]*1E-6; + irfracs=[0 0.1 0.2 0.3]; + fisos=[0 0.2 0.4]; + kappas = [4 8 16 32 64 128]; + fic = [0.3 0.5 0.7]; +else + error(['Unknown material: ', tissue]); +end + +% Adjust for fixed parameters. The first two parameters are the same for +% all models. +if(fix(1)) + fs = [fixedvals(1)]; +end +if(fix(2)) + dpars = [fixedvals(2)]; +end + +if(strcmp(model, 'CylSingleRadTortGPD')) + if(fix(3)) + Rs = [fixedvals(3)]; + end + + numCombs = length(Rs)*length(fs)*length(dpars); + grid = zeros(3, numCombs); + ind = 1; + for i=1:length(Rs) + for j=1:length(fs) + for k=1:length(dpars) + pars = [fs(j) dpars(k) Rs(i)]; + grid(:,ind) = pars; + ind = ind + 1; + end + end + end +elseif(strcmp(model, 'CylSingleRadGPD')) + if(fix(4)) + Rs = [fixedvals(4)]; + end + + numCombs = length(Rs)*length(fs)*length(dpars); + grid = zeros(4, numCombs); + ind = 1; + for i=1:length(Rs) + for j=1:length(fs) + for k=1:length(dpars) + % Set dperp using the standard tortuosity model for + % randomly placed cylinders unless fixed. + dperp = dpars(k)*(1-fs(j)); + if(fix(3)) + dperp = fixedvals(3); + end + pars = [fs(j) dpars(k) dperp Rs(i)]; + grid(:,ind) = pars; + ind = ind + 1; + end + end + end +elseif(strcmp(model, 'CylSingleRadTortIsoGPD')) + if(fix(3)) + Rs = [fixedvals(3)]; + end + if(fix(4)) + fisos = [fixedvals(4)]; + end + + numCombs = length(Rs)*length(fs)*length(dpars)*length(fisos); + grid = zeros(4, numCombs); + ind = 1; + for i=1:length(Rs) + for j=1:length(fs) + for k=1:length(dpars) + for l=1:length(fisos) + pars = [fs(j) dpars(k) Rs(i) fisos(l)]; + grid(:,ind) = pars; + ind = ind + 1; + end + end + end + end +elseif(strcmp(model, 'CylSingleRadIsoV_GPD') || strcmp(model, 'CylSingleRadIsoV_GPD_B0')) + if(fix(4)) + Rs = [fixedvals(4)]; + end + if(fix(5)) + fisos = [fixedvals(5)]; + end + if(fix(6)) + disos = [fixedvals(6)]; + end + + numCombs = length(Rs)*length(fs)*length(dpars)*length(fisos)*length(disos); + grid = zeros(6, numCombs); + ind = 1; + for i=1:length(Rs) + for j=1:length(fs) + for k=1:length(dpars) + for l=1:length(fisos) + for m=1:length(disos) + % Set dperp using the standard tortuosity model for + % randomly placed cylinders unless fixed. + dperp = dpars(k)*(1-fs(j)); + if(fix(3)) + dperp = fixedvals(3); + end + pars = [fs(j) dpars(k) dperp Rs(i) fisos(l) disos(m)]; + grid(:,ind) = pars; + ind = ind + 1; + end + end + end + end + end +elseif(strcmp(model, 'CylSingleRadTortIsoV_GPD') || strcmp(model, 'CylSingleRadTortIsoV_GPD_B0')) + if(fix(3)) + Rs = [fixedvals(3)]; + end + if(fix(4)) + fisos = [fixedvals(4)]; + end + if(fix(5)) + disos = [fixedvals(5)]; + end + + numCombs = length(Rs)*length(fs)*length(dpars)*length(fisos)*length(disos); + grid = zeros(5, numCombs); + ind = 1; + for i=1:length(Rs) + for j=1:length(fs) + for k=1:length(dpars) + for l=1:length(fisos) + for m=1:length(disos) + pars = [fs(j) dpars(k) Rs(i) fisos(l) disos(m)]; + grid(:,ind) = pars; + ind = ind + 1; + end + end + end + end + end +elseif(strcmp(model, 'CylSingleRadIsoDotGPD')) + if(fix(4)) + Rs = [fixedvals(4)]; + end + if(fix(5)) + irfracs = [fixedvals(5)]; + end + numCombs = length(Rs)*length(fs)*length(dpars)*length(irfracs); + grid = zeros(5, numCombs); + ind = 1; + for i=1:length(Rs) + for j=1:length(fs) + for k=1:length(dpars) + for l=1:length(irfracs) + dperp = dpars(k)*(1-fs(j)); + pars = [fs(j) dpars(k) dperp Rs(i) irfracs(l)]; + grid(:,ind) = pars; + ind = ind + 1; + end + end + end + end +elseif(strcmp(model, 'CylSingleRadIsoResTortIsoV_GPD') || strcmp(model, 'CylSingleRadIsoResTortIsoV_GPD_B0')... + || strcmp(model, 'CylSingleRadIsoStickTortIsoV_GPD') || strcmp(model, 'CylSingleRadIsoStickTortIsoV_GPD_B0')... + || strcmp(model, 'CylSingleRadIsoSphereTortIsoV_GPD') || strcmp(model, 'CylSingleRadIsoSphereTortIsoV_GPD_B0')... + || strcmp(model, 'CylSingleRadIsoDotTortIsoV_GPD') || strcmp(model, 'CylSingleRadIsoDotTortIsoV_GPD_B0')) + if(fix(3)) + Rs = [fixedvals(3)]; + end + if(fix(4)) + irfracs = [fixedvals(4)]; + end + if(fix(5)) + fisos = [fixedvals(5)]; + end + if(fix(6)) + disos = [fixedvals(6)]; + end + + numCombs = length(Rs)*length(fs)*length(dpars)*length(fisos)*length(disos); + grid = zeros(6, numCombs); + ind = 1; + for i=1:length(Rs) + for j=1:length(fs) + for k=1:length(dpars) + for l=1:length(fisos) + for m=1:length(disos) + for n=1:length(irfracs) + pars = [fs(j) dpars(k) Rs(i) irfracs(n) fisos(l) disos(m)]; + grid(:,ind) = pars; + ind = ind + 1; + end + end + end + end + end + end +elseif(strcmp(model, 'Stick')) + numCombs = length(fs)*length(dpars); + grid = zeros(3, numCombs); + ind = 1; + for i=1:length(fs) + for j=1:length(dpars) + % Set dperp using the standard tortuosity model for + % randomly placed cylinders unless fixed. + dperp = dpars(j)*(1-fs(i)); + if(fix(3)) + dperp = fixedvals(3); + end + pars = [fs(i) dpars(j) dperp]; + grid(:,ind) = pars; + ind = ind + 1; + end + end +elseif(strcmp(model, 'StickIsoV_B0')) + if(fix(4)) + fisos = [fixedvals(4)]; + end + if(fix(5)) + disos = [fixedvals(5)]; + end + + numCombs = length(fs)*length(dpars)*length(fisos)*length(disos); + grid = zeros(5, numCombs); + ind = 1; + for i=1:length(fs) + for j=1:length(dpars) + for k=1:length(fisos) + for l=1:length(disos) + % Set dperp using the standard tortuosity model for + % randomly placed cylinders unless fixed + dperp = dpars(j)*(1-fs(i)); + if(fix(3)) + dperp = fixedvals(3); + end + pars = [fs(i) dpars(j) dperp fisos(k) disos(l)]; + grid(:,ind) = pars; + ind = ind + 1; + end + end + end + end +elseif(strcmp(model, 'StickTortIsoV_B0')) + if(fix(3)) + fisos = [fixedvals(3)]; + end + if(fix(4)) + disos = [fixedvals(4)]; + end + + numCombs = length(fs)*length(dpars)*length(fisos)*length(disos); + grid = zeros(4, numCombs); + ind = 1; + for i=1:length(fs) + for j=1:length(dpars) + for k=1:length(fisos) + for l=1:length(disos) + pars = [fs(i) dpars(j) fisos(k) disos(l)]; + grid(:,ind) = pars; + ind = ind + 1; + end + end + end + end +elseif(strcmp(model, 'WatsonStick') || strcmp(model, 'WatsonSHStick')) + numCombs = length(fs)*length(dpars)*length(kappas); + grid = zeros(4, numCombs); + ind = 1; + for i=1:length(fs) + for j=1:length(dpars) + for k=1:length(kappas) + % Set dperp using the standard tortuosity model for + % randomly placed cylinders unless fixed. + dperp = dpars(j)*(1-fs(i)); + if(fix(3)) + dperp = fixedvals(3); + end + pars = [fs(i) dpars(j) dperp kappas(k)]; + grid(:,ind) = pars; + ind = ind + 1; + end + end + end +elseif(strcmp(model, 'WatsonSHStickIsoV_B0')) + if(fix(4)) + kappas = [fixedvals(4)]; + end + if(fix(5)) + fisos = [fixedvals(5)]; + end + if(fix(6)) + disos = [fixedvals(6)]; + end + + numCombs = length(fs)*length(dpars)*length(fisos)*length(disos)*length(kappas); + grid = zeros(6, numCombs); + ind = 1; + for i=1:length(fs) + for j=1:length(dpars) + for k=1:length(fisos) + for l=1:length(disos) + for m=1:length(kappas) + dperp = dpars(j)*(1-fs(i)); + if(fix(3)) + dperp = fixedvals(3); + end + pars = [fs(i) dpars(j) dperp kappas(m) fisos(k) disos(l)]; + grid(:,ind) = pars; + ind = ind + 1; + end + end + end + end + end +elseif(strcmp(model, 'WatsonSHStickIsoVIsoDot_B0')) + if(fix(5)) + fisos = [fixedvals(5)]; + end + if(fix(6)) + disos = [fixedvals(6)]; + end + if(fix(7)) + irfracs = [fixedvals(7)]; + end + + numCombs = length(fs)*length(dpars)*length(fisos)*length(disos)*length(kappas)*length(irfracs); + grid = zeros(7, numCombs); + ind = 1; + for i=1:length(fs) + for j=1:length(dpars) + for k=1:length(fisos) + for l=1:length(disos) + for m=1:length(kappas) + for n=1:length(irfracs) + dperp = dpars(j)*(1-fs(i)); + if(fix(3)) + dperp = fixedvals(3); + end + pars = [fs(i) dpars(j) dperp kappas(m) fisos(k) disos(l) irfracs(n)]; + grid(:,ind) = pars; + ind = ind + 1; + end + end + end + end + end + end +elseif(strcmp(model, 'WatsonStickTort') || strcmp(model, 'WatsonSHStickTort')) + numCombs = length(fs)*length(dpars)*length(kappas); + grid = zeros(3, numCombs); + ind = 1; + for i=1:length(fs) + for j=1:length(dpars) + for k=1:length(kappas) + pars = [fs(i) dpars(j) kappas(k)]; + grid(:,ind) = pars; + ind = ind + 1; + end + end + end +elseif(strcmp(model, 'WatsonSHStickTortIsoV_B0')) + if(fix(4)) + fisos = [fixedvals(4)]; + end + if(fix(5)) + disos = [fixedvals(5)]; + end + + numCombs = length(fs)*length(dpars)*length(fisos)*length(disos)*length(kappas); + grid = zeros(5, numCombs); + ind = 1; + for i=1:length(fs) + for j=1:length(dpars) + for k=1:length(fisos) + for l=1:length(disos) + for m=1:length(kappas) + pars = [fs(i) dpars(j) kappas(m) fisos(k) disos(l)]; + grid(:,ind) = pars; + ind = ind + 1; + end + end + end + end + end +elseif(strcmp(model, 'WatsonSHStickTortIsoVIsoDot_B0')) + if(fix(4)) + fisos = [fixedvals(4)]; + end + if(fix(5)) + disos = [fixedvals(5)]; + end + if(fix(6)) + irfracs = [fixedvals(6)]; + end + + numCombs = length(fs)*length(dpars)*length(fisos)*length(disos)*length(kappas)*length(irfracs); + grid = zeros(6, numCombs); + ind = 1; + for i=1:length(fs) + for j=1:length(dpars) + for k=1:length(fisos) + for l=1:length(disos) + for m=1:length(kappas) + for n=1:length(irfracs) + pars = [fs(i) dpars(j) kappas(m) fisos(k) disos(l) irfracs(n)]; + grid(:,ind) = pars; + ind = ind + 1; + end + end + end + end + end + end +elseif(strcmp(model, 'WatsonSHCylSingleRadTortIsoV_GPD') || strcmp(model, 'WatsonSHCylSingleRadTortIsoV_GPD_B0')) + if(fix(3)) + Rs = [fixedvals(3)]; + end + if(fix(5)) + fisos = [fixedvals(5)]; + end + if(fix(6)) + disos = [fixedvals(6)]; + end + + numCombs = length(Rs)*length(fs)*length(dpars)*length(fisos)*length(disos)*length(kappas); + grid = zeros(6, numCombs); + ind = 1; + for i=1:length(Rs) + for j=1:length(fs) + for k=1:length(dpars) + for l=1:length(fisos) + for m=1:length(disos) + for n=1:length(kappas) + pars = [fs(j) dpars(k) Rs(i) kappas(n) fisos(l) disos(m)]; + grid(:,ind) = pars; + ind = ind + 1; + end + end + end + end + end + end +elseif(strcmp(model, 'BinghamCylSingleRadTortIsoV_GPD_B0')) + if(fix(3)) + Rs = [fixedvals(3)]; + end + if(fix(7)) + fisos = [fixedvals(7)]; + end + if(fix(8)) + disos = [fixedvals(8)]; + end + + numCombs = length(Rs)*length(fs)*length(dpars)*length(fisos)*length(disos)*length(kappas); + grid = zeros(8, numCombs); + ind = 1; + for i=1:length(Rs) + for j=1:length(fs) + for k=1:length(dpars) + for l=1:length(fisos) + for m=1:length(disos) + for n=1:length(kappas) + pars = [fs(j) dpars(k) Rs(i) kappas(n) 0 0 fisos(l) disos(m)]; + grid(:,ind) = pars; + ind = ind + 1; + end + end + end + end + end + end +elseif(strcmp(model, 'BinghamStickTortIsoV_B0')) + if(fix(6)) + fisos = [fixedvals(6)]; + end + if(fix(7)) + disos = [fixedvals(7)]; + end + + numCombs = length(fs)*length(dpars)*length(fisos)*length(disos)*length(kappas); + grid = zeros(7, numCombs); + ind = 1; + for i=1:length(fs) + for j=1:length(dpars) + for k=1:length(fisos) + for l=1:length(disos) + for m=1:length(kappas) + pars = [fs(i) dpars(j) kappas(m) 0 0 fisos(k) disos(l)]; + grid(:,ind) = pars; + ind = ind + 1; + end + end + end + end + end +elseif(strcmp(model, 'ExCrossingCylSingleRadGPD')) + R1s = Rs; + R2s = Rs; + if(fix(4)) + R1s = [fixedvals(4)]; + end + + if(fix(5)) + R2s = [fixedvals(5)]; + end + + numCombs = length(R1s)*length(R2s)*length(fs)*length(dpars)*length(fic); + grid = zeros(6, numCombs); + ind = 1; + for i=1:length(R1s) + for j=1:length(R2s) + for k=1:length(fs) + for l=1:length(dpars) + for m=1:length(fic) + % Set dperp using the standard tortuosity model for + % randomly placed cylinders unless fixed. + dperp = dpars(l)*(1-fs(k)); + if(fix(3)) + dperp = fixedvals(3); + end + pars = [fs(k) dpars(l) dperp R1s(i) R2s(j) fic(m)]; + grid(:,ind) = pars; + ind = ind + 1; + end + end + end + end + end +elseif(strcmp(model, 'ExCrossingCylSingleRadIsoDotTortIsoV_GPD_B0')) + R1s = Rs; + R2s = Rs; + if(fix(3)) + R1s = [fixedvals(3)]; + end + + if(fix(4)) + R2s = [fixedvals(4)]; + end + + if(fix(6)) + irfracs = [fixedvals(6)]; + end + + if(fix(7)) + fisos = [fixedvals(7)]; + end + + if(fix(8)) + disos = [fixedvals(8)]; + end + + numCombs = length(R1s)*length(R2s)*length(fs)*length(dpars)*length(fic)*length(irfracs)*length(fisos)*length(disos); + grid = zeros(8, numCombs); + ind = 1; + for i=1:length(R1s) + for j=1:length(R2s) + for k=1:length(fs) + for l=1:length(dpars) + for m=1:length(fic) + for n=1:length(irfracs) + for p=1:length(fisos) + for q=1:length(disos) + pars = [fs(k) dpars(l) R1s(i) R2s(j) fic(m) irfracs(n) fisos(p) disos(q)]; + grid(:,ind) = pars; + ind = ind + 1; + end + end + end + end + end + end + end + end +else + error(['Starting combinations not implemented for model: ', model]); +end + diff --git a/NODDI_toolbox_v1.01/fitting/GradDescDecode.m b/NODDI_toolbox_v1.01/fitting/GradDescDecode.m new file mode 100644 index 0000000..44e66e2 --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/GradDescDecode.m @@ -0,0 +1,37 @@ +function params = GradDescDecode(modelname, optoutput) +% +% function params = GradDescDecode(modelname, optoutput) +% +% Encodes raw parameter values to enforce simple constraints during direct fitting. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +parameterStrings = GetParameterStrings(modelname); +params = zeros(1, length(parameterStrings)); + +for i=1:length(parameterStrings) + if (strcmp(parameterStrings(i), 'ficvf') ||... + strcmp(parameterStrings(i), 'fiso') ||... + strcmp(parameterStrings(i), 'irfrac')) + params(i) = sin(optoutput(i))^2; + elseif (strcmp(parameterStrings(i), 'di') ||... + strcmp(parameterStrings(i), 'diso') ||... + strcmp(parameterStrings(i), 'rad') ||... + strcmp(parameterStrings(i), 'kappa') ||... + strcmp(parameterStrings(i), 'b0') ||... + strcmp(parameterStrings(i), 't1')) + params(i) = optoutput(i)^2; + elseif (strcmp(parameterStrings(i), 'dh')) + diIdx = GetParameterIndex(modelname, 'di'); + params(i) = params(diIdx)*sin(optoutput(i))^2; + elseif (strcmp(parameterStrings(i), 'beta')) + kappaIdx = GetParameterIndex(modelname, 'kappa'); + params(i) = params(kappaIdx)*sin(optoutput(i))^2; + elseif (strcmp(parameterStrings(i), 'theta') ||... + strcmp(parameterStrings(i), 'phi') ||... + strcmp(parameterStrings(i), 'psi')) + params(i) = optoutput(i); + end +end + diff --git a/NODDI_toolbox_v1.01/fitting/GradDescEncode.m b/NODDI_toolbox_v1.01/fitting/GradDescEncode.m new file mode 100644 index 0000000..24a6a58 --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/GradDescEncode.m @@ -0,0 +1,41 @@ +function optarray = GradDescEncode(modelname, x) +% +% function optarray = GradDescEncode(modelname, x) +% +% Encodes raw parameter values to enforce simple constraints during direct fitting. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +parameterStrings = GetParameterStrings(modelname); +optarray = zeros(1, length(parameterStrings)); + +for i=1:length(parameterStrings) + if (strcmp(parameterStrings(i), 'ficvf') ||... + strcmp(parameterStrings(i), 'fiso') ||... + strcmp(parameterStrings(i), 'irfrac')) + optarray(i) = asin(sqrt(x(i))); + elseif (strcmp(parameterStrings(i), 'di') ||... + strcmp(parameterStrings(i), 'diso') ||... + strcmp(parameterStrings(i), 'rad') ||... + strcmp(parameterStrings(i), 'kappa') ||... + strcmp(parameterStrings(i), 'b0') ||... + strcmp(parameterStrings(i), 't1')) + optarray(i) = sqrt(x(i)); + elseif (strcmp(parameterStrings(i), 'dh')) + diIdx = GetParameterIndex(modelname, 'di'); + optarray(i) = asin(sqrt(x(i)/x(diIdx))); + elseif (strcmp(parameterStrings(i), 'beta')) + kappaIdx = GetParameterIndex(modelname, 'kappa'); + if (x(kappaIdx) == 0) + optarray(i) = 0; + else + optarray(i) = asin(sqrt(x(i)/x(kappaIdx))); + end + elseif (strcmp(parameterStrings(i), 'theta') ||... + strcmp(parameterStrings(i), 'phi') ||... + strcmp(parameterStrings(i), 'psi')) + optarray(i) = x(i); + end +end + diff --git a/NODDI_toolbox_v1.01/fitting/GradDescLimits.m b/NODDI_toolbox_v1.01/fitting/GradDescLimits.m new file mode 100644 index 0000000..a9eb11c --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/GradDescLimits.m @@ -0,0 +1,69 @@ +function [min_val max_val] = GradDescLimits(modelname) +% +% function [min_val max_val] = GradDescLimits(modelname) +% +% Returns maximum and minimum settings for the parameters of different +% models to use during direct fitting. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +LARGE = 100000; + +D_MIN = 0.001; +D_MAX = 3; +D_PERP_MIN = 0.001; + +ANGLEMAX=100; + +R_MIN = 0.1; +R_MAX = 5; + +% the values need to account for scaling defined +% in GetScalingFactors.m +K_MIN = 0; +K_MAX = 6.4; + +B_MIN = 0; +B_MAX = 3.2; + +parameterStrings = GetParameterStrings(modelname); +min_val = zeros(1, length(parameterStrings)); +max_val = zeros(1, length(parameterStrings)); + +for i=1:length(parameterStrings) + if (strcmp(parameterStrings(i), 'ficvf') ||... + strcmp(parameterStrings(i), 'fiso') ||... + strcmp(parameterStrings(i), 'irfrac')) + min_val(i) = 0; + max_val(i) = LARGE; + elseif (strcmp(parameterStrings(i), 'di') ||... + strcmp(parameterStrings(i), 'diso')) + min_val(i) = sqrt(D_MIN); + max_val(i) = sqrt(D_MAX); + elseif (strcmp(parameterStrings(i), 'dh')) + min_val(i) = sqrt(D_PERP_MIN); + max_val(i) = LARGE; + elseif (strcmp(parameterStrings(i), 'rad')) + min_val(i) = sqrt(R_MIN); + max_val(i) = sqrt(R_MAX); + elseif (strcmp(parameterStrings(i), 'kappa')) + min_val(i) = sqrt(K_MIN); + max_val(i) = sqrt(K_MAX); + elseif (strcmp(parameterStrings(i), 'beta')) + min_val(i) = sqrt(B_MIN); + max_val(i) = sqrt(B_MAX); + elseif (strcmp(parameterStrings(i), 'theta') ||... + strcmp(parameterStrings(i), 'phi') ||... + strcmp(parameterStrings(i), 'psi')) + min_val(i) = -ANGLEMAX; + max_val(i) = ANGLEMAX; + elseif (strcmp(parameterStrings(i), 'b0')) + min_val(i) = 0.001; + max_val(i) = LARGE; + elseif (strcmp(parameterStrings(i), 't1')) + min_val(i) = 0.1; + max_val(i) = 1; + end +end + diff --git a/NODDI_toolbox_v1.01/fitting/GridSearchRician.m b/NODDI_toolbox_v1.01/fitting/GridSearchRician.m new file mode 100644 index 0000000..0a739a9 --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/GridSearchRician.m @@ -0,0 +1,134 @@ +function [x0, liks] = GridSearchRician(Epn, model, grid, protocol, constants, initSig, fixT1, fibredir) +% Performs a discrete grid search for the combination of parameters +% that best fits a set of measurements for the specified model using a +% Rician noise model. +% +% [x0, liks] = GridSearchRician(Epn, model, grid, protocol, constants, initSig, fibredir) +% returns the parameter combination x0 with the lowest fitting error and a list +% liks of the values of the objective function for each parameter combination in the grid. +% +% model is a string specifying the model. +% +% Epn is the array of measurements. +% +% model is a string specifying the model +% +% grid is the list of parameter combinations to check; typically +% this comes from GetSearchGrid. +% +% protocol contains the protocol for obtaining the measurements. +% +% constants contains values required for the model signal computations. +% +% initSig is the standard deviation of the noise underlying the Rician +% noise model. +% +% fibredir can be specified, but if left out is estimated by fitting the +% diffusion tensor model to the measurements and using the principal +% eigenvalue. +% +% fixT1 is a fixed value for T1 that can be specified. If not +% specified and the model is one that contains T1 as a parameter, +% then T1 is estimated via a linear fit at the same time as the +% diffusion tensor. Note: this may not work particularly well. +% If the DT is a bad fit for the data, this can easily result +% in negative diffusivities etc. +% +% author: Daniel C Alexander (d.alexander@ucl.ac.uk) +% Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +[junk numCombs] = size(grid); + +% Find the fiber direction and S0 from the best fit DT +if(nargin<8) + if(strcmp(model, 'CylSingleRadIsoDotTortIsoV_GPD_B0T1')) + if(nargin<7) + D = FitLinearDT_T1(Epn, protocol); + % Linear estimate of T1 can occasionally go negative + % from noise. + T1 = max([0 D(8)]); + else + % Correct for the known T1 and fit DT in the normal way. + D = FitLinearDT(Epn.*exp(-fixT1./protocol.TM), protocol); + T1 = fixT1; + end + else + D = FitLinearDT(Epn, protocol); + end + dt = MakeDT_Matrix(D(2), D(3), D(4), D(5), D(6), D(7)); + [evec, eval] = eig(dt); + % try to deal with non-positive definite tensors + [eigs, ind] = sort(abs([eval(1, 1) eval(2, 2) eval(3, 3)])); + fibredir = evec(:,ind(3)); + if(strncmp(model, 'Bingham', 7)) + beta_to_kappa = eigs(2)/eigs(3); + fanningdir = evec(:,ind(2)); + end + S0 = exp(D(1)); +end + +initTheta = acos(fibredir(3)); +initPhi = atan2(fibredir(2), fibredir(1)); + +if(strncmp(model, 'Bingham', 7)) + if abs(fibredir(3)) > 0.1 + mat = [-sin(initPhi) -cos(initTheta)*cos(initPhi); cos(initPhi) -cos(initTheta)*sin(initPhi)]; + tmp = mat\[fanningdir(1) fanningdir(2)]'; + initPsi = atan2(tmp(2), tmp(1)); + elseif abs(sin(initPhi)) > 0.1 + mat = [-sin(initPhi) -cos(initTheta)*cos(initPhi); 0 sin(initTheta)]; + tmp = mat\[fanningdir(1) fanningdir(3)]'; + initPsi = atan2(tmp(2), tmp(1)); + else + mat = [cos(initPhi) -cos(initTheta)*sin(initPhi); 0 sin(initTheta)]; + tmp = mat\[fanningdir(2) fanningdir(3)]'; + initPsi = atan2(tmp(2), tmp(1)); + end + if(strcmp(model, 'BinghamStickTortIsoV_B0')) + grid(4,:) = grid(3,:)*beta_to_kappa; + grid(5,:) = initPsi; + elseif(strcmp(model, 'BinghamCylSingleRadTortIsoV_GPD_B0')) + grid(5,:) = grid(4,:)*beta_to_kappa; + grid(6,:) = initPsi; + else + error('ERROR: Bingham initialization not implemented for this model'); + end +end + +% Add the b=0 measurement to the test combinations for models that need it. +if(strcmp(model, 'CylSingleRadIsoV_GPD_B0') ||... + strcmp(model, 'CylSingleRadTortIsoV_GPD_B0') ||... + strcmp(model, 'CylSingleRadIsoDotTortIsoV_GPD_B0') ||... + strcmp(model, 'WatsonSHCylSingleRadTortIsoV_GPD_B0') ||... + strcmp(model, 'WatsonSHStickIsoV_B0') ||... + strcmp(model, 'WatsonSHStickIsoVIsoDot_B0') ||... + strcmp(model, 'WatsonSHStickTortIsoV_B0') ||... + strcmp(model, 'WatsonSHStickTortIsoVIsoDot_B0') ||... + strcmp(model, 'BinghamStickTortIsoV_B0') ||... + strcmp(model, 'BinghamCylSingleRadTortIsoV_GPD_B0') ||... + strcmp(model, 'StickIsoV_B0') ||... + strcmp(model, 'StickTortIsoV_B0')) + grid = [grid' ones(size(grid,2), 1)*S0]'; +end + +% Add T1 and the b=0 measurement to the test combinations for models +% that need it. +if(strcmp(model, 'CylSingleRadIsoDotTortIsoV_GPD_B0T1')) + grid = [grid' ones(size(grid,2), 1)*S0 ones(size(grid,2), 1)*T1]'; +end + +% Test each combination +liks = zeros(numCombs, 1); +for j=1:numCombs + Eest = SynthMeas(model, grid(:,j), protocol, fibredir, constants); + liks(j) = RicianLogLik(Epn, Eest, initSig); +end +[a ind] = max(liks); +mlPars = grid(:,ind); + +% Rescale and construct the final result. +scale = GetScalingFactors(model); +psc = [mlPars' initSig].*scale; +x0 = [psc(1:(end-1)) initTheta initPhi initSig]; + diff --git a/NODDI_toolbox_v1.01/fitting/PlotFittedModel.m b/NODDI_toolbox_v1.01/fitting/PlotFittedModel.m new file mode 100644 index 0000000..21e78d9 --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/PlotFittedModel.m @@ -0,0 +1,58 @@ +function PlotFittedModel(protocol, MODELNAME, fittedpars, constants, h, style) +% Plots the normalized measurements predicted by the model with +% the fitted parameters against the absolute dot product of the +% gradient and fibre directions. +% +% PlotFittedModel(protocol, MODELNAME, fittedpars, h) +% adds the plot to figure handle h. +% +% protocol is the imaging protocol. +% +% MODELNAME is the name identifying the model. +% +% fittedpars and the model parameter values. +% +% constants is a structure containing fixed values required for the model. +% +% h is a figure handle to add the plot to. If not specified, a new figure +% appears. +% +% author: Daniel C Alexander (d.alexander@ucl.ac.uk) +% Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +if(nargin<5) + h = figure; +end + +% Get estimated fibre direction and b=0 signal. +fibredir = GetFibreOrientation(MODELNAME, fittedpars); +b0est = GetB0(MODELNAME, fittedpars); + +if(nargin<6) + style = '-'; +end + +linedef{1} = ['r', style]; +linedef{2} = ['b', style]; +linedef{3} = ['g', style]; +linedef{4} = ['m', style]; +linedef{5} = ['c', style]; +linedef{6} = ['k', style]; +linedef{7} = ['y', style]; + +hold on; + +scale = GetScalingFactors(MODELNAME); +xsc = fittedpars(1:(length(scale)-1))./scale(1:(end-1)); +S_Meas = SynthMeas(MODELNAME, xsc, protocol, fibredir, constants); +Snormdw = S_Meas./b0est; +for j=1:length(protocol.uG) + inds = find(protocol.G == protocol.uG(j) & protocol.delta == protocol.udelta(j) & protocol.smalldel == protocol.usmalldel(j)); + dps = abs(protocol.grad_dirs(inds,:)*fibredir); + [t tinds] = sort(dps); + plot(dps(tinds), Snormdw(inds(tinds)), linedef{j}, 'LineWidth', 2); +end +xlabel('|n.G|/|G|_{max}'); +ylabel('S/S_0'); + diff --git a/NODDI_toolbox_v1.01/fitting/QualityOfFit.m b/NODDI_toolbox_v1.01/fitting/QualityOfFit.m new file mode 100644 index 0000000..08a920f --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/QualityOfFit.m @@ -0,0 +1,31 @@ +function [h] = QualityOfFit(signal, fittedpars, model, protocol) +% Assess the quality of fit +% [h] = QualityOfFit(signal, fittedpars, model, protocol); +% +% Typical usage as follows: +% +% 1) First fit the signal +% [gs fgs ml fml] = ThreeStageFittingVoxel(signal, protocol, model); +% +% 2) Now check the quality of fit +% QualityOfFit(signal, ml, model, protocol); +% +% Author: Gary Hui Zhang, PhD +% + +b0 = GetB0(model.name, fittedpars); +fibredir = GetFibreOrientation(model.name, fittedpars); + +h = figure; + +% the data plot +VoxelDataViewer(protocol, signal, fibredir, b0, h); + +% the predicted data plot +% constants is set to zero for NODDI but should be different for +% ActiveAx models +constants = 0; +PlotFittedModel(protocol, model.name, fittedpars, constants, h); + +end + diff --git a/NODDI_toolbox_v1.01/fitting/RemoveNegMeas.m b/NODDI_toolbox_v1.01/fitting/RemoveNegMeas.m new file mode 100644 index 0000000..93da4b4 --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/RemoveNegMeas.m @@ -0,0 +1,78 @@ +function [E tempprot] = RemoveNegMeas(Epn, protocol) +% Removes negative or zero measurements from a set and returns a protocol +% with the corresponding elements removed to exclude the negative +% measurements from the fitting. +% +% Epn is the full set of measurements; E is that with the negative ones +% removed. +% +% protocol is the full protocol; tempprot is that with the entries +% corresponding to negative measurements removed. +% +% author: Daniel C Alexander (d.alexander@ucl.ac.uk) +% Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +tempprot = protocol; +E = Epn; +if(min(Epn)<=0) + posonly = find(Epn>0); + E = Epn(posonly); + nonposonly = setdiff([1:size(Epn,1)], posonly); + tempprot.totalmeas = length(posonly); + + if (isfield(tempprot, 'b0_Indices')) + tempprot.b0_Indices = []; + end + if (isfield(tempprot, 'dti_subset')) + tempprot.dti_subset = []; + end + + for i=1:tempprot.totalmeas + if(isfield(tempprot, 'b0_Indices')) + if ismember(posonly(i), protocol.b0_Indices) + tempprot.b0_Indices = [tempprot.b0_Indices i]; + end + end + if(isfield(tempprot, 'dti_subset')) + if ismember(posonly(i), protocol.dti_subset) + tempprot.dti_subset = [tempprot.dti_subset i]; + end + end + end + if(isfield(tempprot, 'b0_Indices')) + tempprot.numZeros = length(tempprot.b0_Indices); + if length(tempprot.b0_Indices) == 0 + error('All b=0 measurements are negative'); + end + end + + if tempprot.totalmeas - length(tempprot.b0_Indices) < 6 + error('Not enough DWI measurements'); + end + + if(isfield(tempprot, 'dti_subset')) + if length(tempprot.dti_subset) - length(tempprot.b0_Indices) < 6 + error('Not enough DWI measurements'); + end + end + + if(strcmp(tempprot.pulseseq, 'PGSE') || strcmp(tempprot.pulseseq, 'STEAM')) + tempprot.G = tempprot.G(posonly); + tempprot.delta = tempprot.delta(posonly); + tempprot.smalldel = tempprot.smalldel(posonly); + tempprot.grad_dirs = tempprot.grad_dirs(posonly, :); + if(strcmp(tempprot.pulseseq, 'STEAM')) + tempprot.TM = tempprot.TM(posonly); + tempprot.TR = tempprot.TR(posonly); + tempprot.TE = tempprot.TE(posonly); + end + if(isfield(tempprot, 'TE')) + tempprot.TE = tempprot.TE(posonly); + end + else + error('Need to adapt for other pulse sequences.'); + end +end + + diff --git a/NODDI_toolbox_v1.01/fitting/SaveAsNIfTI.m b/NODDI_toolbox_v1.01/fitting/SaveAsNIfTI.m new file mode 100644 index 0000000..7b272eb --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/SaveAsNIfTI.m @@ -0,0 +1,35 @@ +function SaveAsNIfTI(data, target, output) + +% function SaveAsNIfTI(data, nifti) +% +% Input: +% +% data: the data array to be saved to disk +% +% target: the NIfTI object specifying the target volume specification +% +% output: the filename for the output NIfTI file +% + +% following the example in +% http://niftilib.sourceforge.net/mat_api_html/README.txt +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +dat = file_array; +dat.fname = output; +dat.dim = target.dim; +dat.dtype = 'FLOAT64-LE'; +dat.offset = ceil(348/8)*8; + +N = nifti; +N.dat = dat; +N.mat = target.mat; +N.mat_intent = target.mat_intent; +N.mat0 = target.mat0; +N.mat0_intent = target.mat0_intent; + +create(N); + +N.dat(:,:,:,:) = data; diff --git a/NODDI_toolbox_v1.01/fitting/SaveParamsAsNIfTI.m b/NODDI_toolbox_v1.01/fitting/SaveParamsAsNIfTI.m new file mode 100644 index 0000000..afac589 --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/SaveParamsAsNIfTI.m @@ -0,0 +1,153 @@ +function SaveParamsAsNIfTI(paramsfile, roifile, targetfile, outputpref) +% +% function SaveParamsAsNIfTI(paramsfile, roifile, targetfile, outputpref) +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +% load the fitting results +fprintf('loading the fitted parameters from : %s\n', paramsfile); +load(paramsfile); + +% load the roi file +fprintf('loading the roi from : %s\n', roifile); +load(roifile); + +% load the target volume +fprintf('loading the target volume : %s\n', targetfile); +target = nifti(targetfile); +xsize = target.dat.dim(1); +ysize = target.dat.dim(2); +if length(target.dat.dim) == 2 + zsize = 1; +else + zsize = target.dat.dim(3); +end +total = xsize*ysize*zsize; + +% determine the volumes to be saved +% the number of fitted parameters minus the two fibre orientation +% parameters. +idxOfFitted = find(model.GD.fixed(1:end-2)==0); +noOfVols = length(idxOfFitted); +vols = zeros(total,noOfVols); +% the volume for the objective function values +fobj_ml_vol = zeros(total,1); +% the volume for the error code +error_code_vol = zeros(total,1); +% some special cases +if (strfind(model.name, 'Watson')) + idxOfKappa = find(ismember(model.paramsStr, 'kappa')==1); + odi_vol = zeros(total,1); +end + +% the volumes for the fibre orientations +fibredirs_x_vol = zeros(total,1); +fibredirs_y_vol = zeros(total,1); +fibredirs_z_vol = zeros(total,1); +% compute the fibre orientations from the estimated theta and phi. +fibredirs = GetFibreOrientation(model.name, mlps); + +% determine the volumes with MCMC fitting to be saved +if (model.noOfStages==3) + idxOfFittedMCMC = find(model.MCMC.fixed(1:end-2)==0); + noOfVolsMCMC = length(idxOfFittedMCMC); + volsMCMC = zeros(total,noOfVolsMCMC); + + if (strfind(model.name, 'Watson')) + idxOfKappa = find(ismember(model.paramsStr, 'kappa')==1); + if (model.MCMC.fixed(idxOfKappa)==0) + odi_volMCMC = zeros(total,1); + end + end +end + +% convert to volumetric maps +fprintf('converting the fitted parameters into volumetric maps ...\n'); +for i=1:size(mlps,1) + % compute the index to 3D + volume_index = (idx(i,3)-1)*ysize*xsize + (idx(i,2)-1)*xsize + idx(i,1); + + % fitted parameters other than the fiber orientations + for j=1:length(idxOfFitted) + vols(volume_index,j) = mlps(i, idxOfFitted(j)); + end + + % objective function values + fobj_ml_vol(volume_index) = fobj_ml(i); + + % error codes + error_code_vol(volume_index) = error_code(i); + + % fiber orientations + fibredirs_x_vol(volume_index) = fibredirs(1,i); + fibredirs_y_vol(volume_index) = fibredirs(2,i); + fibredirs_z_vol(volume_index) = fibredirs(3,i); + + % special cases + if (strfind(model.name, 'Watson')) + odi_vol(volume_index) = atan2(1, mlps(i,idxOfKappa)*10)*2/pi; + end + + % MCMC fitted parameters + if (model.noOfStages==3) + for j=1:length(idxOfFittedMCMC) + volsMCMC(volume_index,j) = mean(squeeze(mcmcps(i,:,j))); + end + if (strfind(model.name, 'Watson')) + % Warning: Here we hard-coded the index to kappa!!! + odi_volMCMC(volume_index) = atan2(1, mean(squeeze(mcmcps(i,:,3)))*10)*2/pi; + end + end + +end + +% save as NIfTI +fprintf('Saving the volumetric maps of the fitted parameters ...\n'); + +niftiSpecs.dim = [xsize ysize zsize]; +niftiSpecs.mat = target.mat; +niftiSpecs.mat_intent = target.mat_intent; +niftiSpecs.mat0 = target.mat0; +niftiSpecs.mat0_intent = target.mat0_intent; + +% the fitted parameters other than the fiber orientations +for i=1:length(idxOfFitted) + output = [outputpref '_' cell2mat(model.paramsStr(idxOfFitted(i))) '.nii']; + SaveAsNIfTI(reshape(squeeze(vols(:,i)), [xsize ysize zsize]), niftiSpecs, output); +end + +% the special cases +if (strfind(model.name, 'Watson')) + output = [outputpref '_' 'odi.nii']; + SaveAsNIfTI(reshape(odi_vol, [xsize ysize zsize]), niftiSpecs, output); +end + +% the objective function values +output = [outputpref '_' 'fmin.nii']; +SaveAsNIfTI(reshape(fobj_ml_vol, [xsize ysize zsize]), niftiSpecs, output); + +% the error codes +output = [outputpref '_' 'error_code.nii']; +SaveAsNIfTI(reshape(error_code_vol, [xsize ysize zsize]), niftiSpecs, output); + +% the fibre orientations +output = [outputpref '_' 'fibredirs_xvec.nii']; +SaveAsNIfTI(reshape(fibredirs_x_vol, [xsize ysize zsize]), niftiSpecs, output); +output = [outputpref '_' 'fibredirs_yvec.nii']; +SaveAsNIfTI(reshape(fibredirs_y_vol, [xsize ysize zsize]), niftiSpecs, output); +output = [outputpref '_' 'fibredirs_zvec.nii']; +SaveAsNIfTI(reshape(fibredirs_z_vol, [xsize ysize zsize]), niftiSpecs, output); + +% the MCMC fitted parameters +if (model.noOfStages==3) + for i=1:length(idxOfFittedMCMC) + output = [outputpref '_' cell2mat(model.paramsStr(idxOfFittedMCMC(i))) '_MCMC.nii']; + SaveAsNIfTI(reshape(squeeze(volsMCMC(:,i)), [xsize ysize zsize]), niftiSpecs, output); + end + if (strfind(model.name, 'Watson')) + output = [outputpref '_' 'odi_MCMC.nii']; + SaveAsNIfTI(reshape(odi_volMCMC, [xsize ysize zsize]), niftiSpecs, output); + end +end + diff --git a/NODDI_toolbox_v1.01/fitting/SchemeToProtocol.m b/NODDI_toolbox_v1.01/fitting/SchemeToProtocol.m new file mode 100644 index 0000000..45a1c36 --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/SchemeToProtocol.m @@ -0,0 +1,34 @@ +function protocol = SchemeToProtocol(schemefile) +% +% Reads a Camino Version 1 schemefile into a protocol object +% +% function protocol = SchemeToProtocol(schemefile) +% +% author: Daniel C Alexander (d.alexander@ucl.ac.uk) +% Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +fid = fopen(schemefile, 'r', 'b'); + +% Read in the header (assumes one line) +%A = fscanf(fid, '%c', 10); +A = fgetl(fid); + +% Read in the data +A = fscanf(fid, '%f', [7, inf]); + +fclose(fid); + +% Create the protocol +protocol.pulseseq = 'PGSE'; +protocol.grad_dirs = A(1:3,:)'; +protocol.G = A(4,:); +protocol.delta = A(5,:); +protocol.smalldel = A(6,:); +protocol.TE = A(7,:); +protocol.totalmeas = length(A); + +% Find the B0's +bVals = GetB_Values(protocol); +protocol.b0_Indices = find(bVals==0); + diff --git a/NODDI_toolbox_v1.01/fitting/ThreeStageFittingVoxel.m b/NODDI_toolbox_v1.01/fitting/ThreeStageFittingVoxel.m new file mode 100644 index 0000000..890594e --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/ThreeStageFittingVoxel.m @@ -0,0 +1,219 @@ +function [gsps, fobj_gs, mlps, fobj_ml, error_code, ps] = ThreeStageFittingVoxel(Epn, protocol, model, verbose) +% Performs the three stage fitting routine used for the human data in +% Alexander et al NeuroImage 2000. The three stages are grid search, +% maximum likelihood gradient descent and MCMC with a Rician noise model. +% +% function [gsps, fobj_gs, mlps, fobj_ml, error_code, ps] = ThreeStageFittingVoxel(Epn, protocol, model, verbose) +% +% protocol is the measurement protocol. +% +% model is the model structure created with MakeModel +% +% verbose: optional, 1 for printing verbose messages, 0 for quiet (default) +% +% author: Daniel C Alexander (d.alexander@ucl.ac.uk) +% Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +if nargin < 4 + verbose = 0; +end + +%% Initialization + +warning off all + +% Get the required variables +modelname = model.name; +noOfStages = model.noOfStages; +tissuetype = model.tissuetype; +GS = model.GS; +GD = model.GD; +MCMC = model.MCMC; + +% Initialize the output +error_code = 0; +gsps = zeros(1, model.numParams); +mlps = gsps; +fobj_gs = 0; +fobj_ml = 0; + +% Constants used during grid search and gradient descent +constantsGD.roots_cyl = BesselJ_RootsCyl(30); + +%% First remove non-positive measurements +try + [Epn, protocol] = RemoveNegMeas(Epn, protocol); +catch err + error_code = 1; + disp(err); + return; +end + +%% Determine the sigma +sig = EstimateSigma(Epn, protocol, model); + +%% Grid Search stage + +if verbose + fprintf('Grid Search fitting with %s\n', modelname); +end + +% Set up the search grid +grid = GetSearchGrid(modelname, tissuetype, GS.fixed, GS.fixedvals); + +% Run the grid search +[x0 liks] = GridSearchRician(Epn, modelname, grid, protocol, constantsGD, sig); +gsps = x0(1:(end-1)); +fobj_gs = max(liks); +if verbose + if (strcmp(modelname, 'StickIsoV_B0')) + fprintf('gsps: %5.4f %2.1f %2.1f %5.4f %2.1f %5.1f %5.4f %5.4f : %e\n', gsps, fobj_gs) + elseif (strcmp(modelname, 'StickTortIsoV_B0')) + fprintf('gsps: %5.4f %2.1f %5.4f %2.1f %5.1f %5.4f %5.4f : %e\n', gsps, fobj_gs) + elseif (strcmp(modelname, 'WatsonSHStickTortIsoV_B0')) + fprintf('gsps: %5.4f %2.1f %5.4f %5.4f %2.1f %5.1f %5.4f %5.4f : %e\n', gsps, fobj_gs) + elseif (strcmp(modelname, 'WatsonSHStickTortIsoVIsoDot_B0')) + fprintf('gsps: %5.4f %2.1f %5.4f %5.4f %2.1f %5.4f %5.1f %5.4f %5.4f : %e\n', gsps, fobj_gs) + elseif (strcmp(modelname, 'BinghamStickTortIsoV_B0')) + fprintf('gsps: %5.4f %2.1f %5.4f %5.4f %5.4f %5.4f %2.1f %5.1f %5.4f %5.4f : %e\n', gsps, fobj_gs) + else + disp(fobj_gs); + disp(gsps); + end +end + +if noOfStages == 1 + return; +end + +%% Gradient Descent stage + +if verbose + fprintf('Gradient Descent fitting with %s\n', modelname); +end + +h=optimset('Algorithm', 'active-set', 'Display', 'iter', 'MaxIter',100,... + 'MaxFunEvals',20000,'TolX',1e-6,... + 'TolFun',1e-6,'GradObj','off', 'Hessian', 'off', 'FunValCheck',... + 'on', 'Display', 'off');%,'DerivativeCheck','on'); + +% Convert from actual parameters to optimized quantities that enforce +% constraints. +startx = GradDescEncode(modelname, gsps); +fobj_ml = fobj_gs; +mlps = gsps; +if (strcmp(GD.type, 'multistart')) + noOfIterations = GD.multistart.noOfRuns; + perturbation = GD.multistart.perturbation; + if isempty(find(perturbation~=0, 1)) + error('multistart mode: at least one perturbation should be nonzero'); + else + perturbation(GD.fixed==1) = 0; + end + if verbose + fprintf('Multistart fitting with %i trials\n', noOfIterations); + fprintf('Parameter perturbation adjusted for fixed variables'); + end +else + noOfIterations = 1; +end + +% Get limits and constraints for gradient descent +[MinValGD MaxValGD] = GradDescLimits(modelname); + +% Get orientation dispersion index, if applicable +kappaIdx = GetParameterIndex(modelname, 'kappa'); + +for i=1:noOfIterations + if i==1 + parameter_input = startx; + else + parameter_input = startx.*(1 + perturbation.*randn(1,length(perturbation))); + end + + try + % optimize with orientation fixed + fixedGD = GD.fixed; + fixedGD(end-1:end) = 1; + % if kappa is a parameter, fix it first as well + if (kappaIdx ~= -1) + fixedGD(kappaIdx) = 1; + end + % Account for any fixed parameters + fittedMinValGD = MinValGD(fixedGD==0); + fittedMaxValGD = MaxValGD(fixedGD==0); + [parameter_hat,RESNORM,EXITFLAG,OUTPUT]=fmincon_fix(fixedGD, 'fobj_rician_fix',... + parameter_input,[],[],[],[],fittedMinValGD,fittedMaxValGD,[],h,Epn,protocol, modelname, sig, constantsGD); + parameter_input = parameter_hat; + + % now optimize all free variables + % Account for any fixed parameters + fittedMinValGD = MinValGD(GD.fixed==0); + fittedMaxValGD = MaxValGD(GD.fixed==0); + [parameter_hat,RESNORM,EXITFLAG,OUTPUT]=fmincon_fix(GD.fixed, 'fobj_rician_fix',... + parameter_input,[],[],[],[],fittedMinValGD,fittedMaxValGD,[],h,Epn,protocol, modelname, sig, constantsGD); + + if (-RESNORM > fobj_ml) + fobj_ml = -RESNORM; + mlps = GradDescDecode(modelname, parameter_hat); + end + if (verbose) + disp(fobj_ml); + end + catch err + error_code = 2; + disp(err); + return; + end + +end + +if verbose + if (strcmp(modelname, 'StickIsoV_B0')) + fprintf('mlps: %5.4f %2.1f %2.1f %5.4f %2.1f %5.1f %5.4f %5.4f : %e\n', mlps, fobj_ml) + elseif (strcmp(modelname, 'StickTortIsoV_B0')) + fprintf('mlps: %5.4f %2.1f %5.4f %2.1f %5.1f %5.4f %5.4f : %e\n', mlps, fobj_ml) + elseif (strcmp(modelname, 'WatsonSHStickTortIsoV_B0')) + fprintf('mlps: %5.4f %2.1f %5.4f %5.4f %2.1f %5.1f %5.4f %5.4f : %e\n', mlps, fobj_ml) + elseif (strcmp(modelname, 'WatsonSHStickTortIsoVIsoDot_B0')) + fprintf('mlps: %5.4f %2.1f %5.4f %5.4f %2.1f %5.4f %5.1f %5.4f %5.4f : %e\n', mlps, fobj_ml) + elseif (strcmp(modelname, 'BinghamStickTortIsoV_B0')) + fprintf('mlps: %5.4f %2.1f %5.4f %5.4f %5.4f %5.4f %2.1f %5.1f %5.4f %5.4f : %e\n', mlps, fobj_ml) + else + disp(fobj_ml); + disp(mlps); + end +end + +if noOfStages == 2 + return; +end + +%% MCMC stage + +if verbose + fprintf('MCMC fitting with %s\n', modelname); +end + +% Get limits and constraints for MCMC +[MinValMCMC MaxValMCMC] = MCMC_Limits(modelname); + +% MCMC parameters +steplengths = MCMC.steplengths; +burnin = MCMC.burnin; +interval = MCMC.interval; +samples = MCMC.samples; + +% Constants used during MCMC +constantsMCMC.roots_cyl = BesselJ_RootsCyl(20); + +% Run the MCMC procedure +x0t = [mlps sig]; + +ps(:,:) = RicianMCMC(Epn, x0t, modelname, protocol, MinValMCMC, MaxValMCMC, constantsMCMC, MCMC.fixed, steplengths, burnin, samples, interval); +mcmcps = squeeze(mean(ps,1)); + +if verbose + disp(mcmcps); +end diff --git a/NODDI_toolbox_v1.01/fitting/VoxelDataViewer.m b/NODDI_toolbox_v1.01/fitting/VoxelDataViewer.m new file mode 100644 index 0000000..0cc24fa --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/VoxelDataViewer.m @@ -0,0 +1,70 @@ +function VoxelDataViewer(protocol, data, fibredir, b0, h, style) +% Plots the normalized measurements in one image voxel against the +% absolute dot product of the gradient and fibre directions. +% +% VoxelDataViewer(protocol, data, fibredir, b0, h) +% brings up a window containing the plot. +% +% protocol is the imaging protocol. +% +% data is the set of measurements in the voxel. +% +% fibredir is an estimate of the fibre direction in that voxel. By default +% this is set to the z-axis +% +% b0 is an estimate of the b=0 signal. By default, this is set to one. +% +% h is a figure handle to add the plot to. If not specified, a new figure +% appears. +% +% author: Daniel C Alexander (d.alexander@ucl.ac.uk) +% Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +if(nargin<3) + fibredir = [0 0 1]'; +end +if(nargin<4) + b0=1; +end +if(nargin<5) + h = figure; +end + +% Compute b-values +GAMMA = 2.675987E8; +modQ = GAMMA*protocol.usmalldel.*protocol.uG; +diffTime = (protocol.udelta - protocol.usmalldel/3); +bvals = diffTime.*modQ.^2; + +% Create normalized data set. +normdw = data/b0; + +if(nargin<6) + style = 'x'; +end + +linedef{1} = ['r', style]; +linedef{2} = ['b', style]; +linedef{3} = ['g', style]; +linedef{4} = ['m', style]; +linedef{5} = ['c', style]; +linedef{6} = ['k', style]; +linedef{7} = ['y', style]; + +hold on; +set(gca, 'FontName', 'Times'); +set(gca, 'FontSize', 17); +for j=1:length(protocol.uG) + inds = find(protocol.G == protocol.uG(j) & protocol.delta == protocol.udelta(j) & protocol.smalldel == protocol.usmalldel(j)); + scatter(abs(protocol.grad_dirs(inds,:)*fibredir), normdw(inds), linedef{j}); +end +xlabel('|n.G|/|G|_{max}'); +ylabel('S/S_0'); +%ylim([0,b0*1.1]); + +% Add b=0 measurements +b0_meas = data(protocol.b0_Indices); +for b=1:length(b0_meas) + h(1) = plot([0 1], [b0_meas(b)/b0 b0_meas(b)/b0], ':k'); +end diff --git a/NODDI_toolbox_v1.01/fitting/batch_fitting.m b/NODDI_toolbox_v1.01/fitting/batch_fitting.m new file mode 100644 index 0000000..5806ea9 --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/batch_fitting.m @@ -0,0 +1,130 @@ +function batch_fitting(roifile, protocol, model, outputfile, poolsize) + +% +% function batch_fitting(roifile, protocol, model, outputfile, poolsize) +% +% This function does batch fitting to the voxels in an entire ROI created with +% CreateROI function. +% +% Input: +% +% roifile: the ROI file created with CreateROI +% +% protocol: the protocol object created with FSL2Protocol +% +% model: the model object created with MakeModel +% +% outputfile: the name of the mat file to store the fitted parameters +% +% poolsize (optional): the number of parallel processes to run +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +% first check if there is a file there to resume +if exist(outputfile, 'file') + load(outputfile); + if exist('split_end', 'var') + % previously run and need to be restarted + current_split_start = split_end + 1; + fprintf('Resume an interrupted run from %i\n', current_split_start); + else + % completed + fprintf('An output file of the same name detected.\n'); + fprintf('Choose a different output file name.\n'); + return; + end +else + % if this is the first run + current_split_start = 1; +end + +% initiate the parallel environment if necessary +pool = gcp('nocreate'); +if isempty(pool) + if (nargin < 5) + pool = parpool('local'); + else + pool = parpool('local', poolsize); + end +end + +% load the roi file +load(roifile); +numOfVoxels = size(roi,1); + +% set up the fitting parameter variables if it is the first run +if current_split_start == 1 + gsps = zeros(numOfVoxels, model.numParams); + mlps = zeros(numOfVoxels, model.numParams); + fobj_gs = zeros(numOfVoxels, 1); + fobj_ml = zeros(numOfVoxels, 1); + error_code = zeros(numOfVoxels, 1); + if model.noOfStages == 3 + mcmcps = zeros(numOfVoxels, model.MCMC.samples, model.numParams + 1); + end +end + +% set up the PARFOR Progress Monitor +[mypath myname myext] = fileparts(mfilename('fullpath')); +mypath = [mypath '/../ParforProgMonv2/java']; +pctRunOnAll(['javaaddpath ' mypath]); +progressStepSize = 100; +ppm = ParforProgMon(['Fitting ' roifile, ' : '], numOfVoxels-current_split_start+1,... + progressStepSize, 400, 80); + +tic + +fprintf('%i of voxels to fit\n', numOfVoxels-current_split_start+1); + +% start the parallel fitting +for split_start=current_split_start:progressStepSize:numOfVoxels + % set up the split end + split_end = split_start + progressStepSize - 1; + if split_end > numOfVoxels + split_end = numOfVoxels; + end + + % fit the split + parfor i=split_start:split_end + + % get the MR signals for the voxel i + voxel = roi(i,:)'; + + % fit the voxel + if model.noOfStages == 2 + [gsps(i,:), fobj_gs(i), mlps(i,:), fobj_ml(i), error_code(i)] = ThreeStageFittingVoxel(voxel, protocol, model); + else + [gsps(i,:), fobj_gs(i), mlps(i,:), fobj_ml(i), error_code(i), mcmcps(i,:,:)] = ThreeStageFittingVoxel(voxel, protocol, model); + end + + % report to the progress monitor + if mod(i, progressStepSize)==0 + ppm.increment(); + end + + end + + % save the temporary results of the split + if model.noOfStages == 2 + save(outputfile, 'split_end', 'model', 'gsps', 'fobj_gs', 'mlps', 'fobj_ml', 'error_code'); + else + save(outputfile, 'split_end', 'model', 'gsps', 'fobj_gs', 'mlps', 'fobj_ml', 'mcmcps', 'error_code'); + end + +end + +toc + +ppm.delete(); + +% save the fitted parameters +if model.noOfStages == 2 + save(outputfile, 'model', 'gsps', 'fobj_gs', 'mlps', 'fobj_ml', 'error_code'); +else + save(outputfile, 'model', 'gsps', 'fobj_gs', 'mlps', 'fobj_ml', 'mcmcps', 'error_code'); +end + +% close the parallel pool +delete pool; + diff --git a/NODDI_toolbox_v1.01/fitting/batch_fitting_single.m b/NODDI_toolbox_v1.01/fitting/batch_fitting_single.m new file mode 100644 index 0000000..9b7c92e --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/batch_fitting_single.m @@ -0,0 +1,95 @@ +function batch_fitting_single(roifile, protocol, model, outputfile) + +% +% function batch_fitting_single(roifile, protocol, model, outputfile) +% +% This function does batch fitting to the voxels in an entire ROI created with +% CreateROI function. +% +% Input: +% +% roifile: the ROI file created with CreateROI +% +% protocol: the protocol object created with FSL2Protocol +% +% model: the model object created with MakeModel +% +% outputfile: the name of the mat file to store the fitted parameters +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + + +% first check if there is a file there to resume +if exist(outputfile, 'file') + load(outputfile); + if exist('current_index', 'var') + % previously run and need to be restarted + current_index = current_index + 1; + fprintf('Resume an interrupted run from voxel %i\n', current_index); + else + % completed + fprintf('An output file of the same name detected.\n'); + fprintf('Choose a different output file name.\n'); + return; + end +else + % if this is the first run + current_index = 1; +end + +% load the roi file +load(roifile); +numOfVoxels = size(roi,1); + +% set up the fitting parameter variables if it is the first run +if current_index == 1 + gsps = zeros(numOfVoxels, model.numParams); + mlps = zeros(numOfVoxels, model.numParams); + fobj_gs = zeros(numOfVoxels, 1); + fobj_ml = zeros(numOfVoxels, 1); + error_code = zeros(numOfVoxels, 1); + if model.noOfStages == 3 + mcmcps = zeros(numOfVoxels, model.MCMC.samples, model.numParams + 1); + end +end + +tic + +fprintf('%i of voxels to fit\n', numOfVoxels-current_index+1); + +% start the parallel fitting +for i=current_index:numOfVoxels + + fprintf('Fitting voxel %i\n', i); + + % get the MR signals for the voxel i + voxel = roi(i,:)'; + + % fit the voxel + if model.noOfStages == 2 + [gsps(i,:), fobj_gs(i), mlps(i,:), fobj_ml(i), error_code(i)] = ThreeStageFittingVoxel(voxel, protocol, model); + else + [gsps(i,:), fobj_gs(i), mlps(i,:), fobj_ml(i), error_code(i), mcmcps(i,:,:)] = ThreeStageFittingVoxel(voxel, protocol, model); + end + + % save the temporary results + if mod(i, 100)==0 + current_index = i; + if model.noOfStages == 2 + save(outputfile, 'current_index', 'model', 'gsps', 'fobj_gs', 'mlps', 'fobj_ml', 'error_code'); + else + save(outputfile, 'current_index', 'model', 'gsps', 'fobj_gs', 'mlps', 'fobj_ml', 'mcmcps', 'error_code'); + end + end + +end + +toc + +% save the fitted parameters +if model.noOfStages == 2 + save(outputfile, 'model', 'gsps', 'fobj_gs', 'mlps', 'fobj_ml', 'error_code'); +else + save(outputfile, 'model', 'gsps', 'fobj_gs', 'mlps', 'fobj_ml', 'mcmcps', 'error_code'); +end diff --git a/NODDI_toolbox_v1.01/fitting/fmincon_fix.m b/NODDI_toolbox_v1.01/fitting/fmincon_fix.m new file mode 100644 index 0000000..3ed93ba --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/fmincon_fix.m @@ -0,0 +1,23 @@ +function [x,fval,exitflag,output,lambda,grad,hessian] = fmincon_fix(fix,fun,x0,A,b,Aeq,beq,lb,ub,nonlcon,options,varargin) +% Wrapper for fmincon that allows the user to specify a number of model +% parameters that remain fixed to the initial settings. +% +% fix is a binary array. Zero indicates that the parameter in the +% corresponding position in x0 varies during fitting; one indicates that +% the value remains fixed at the alue in x0. +% +% The other parameters are all as for fmincon. +% +% author: Daniel C Alexander (d.alexander@ucl.ac.uk) +% + +% Construct the parameter vector with fixed values removed. +x0f = x0(find(fix==0)); + +% Run the opt. +[x,fval,exitflag,output,lambda,grad,hessian] = fmincon(fun,x0f,A,b,Aeq,beq,lb,ub,nonlcon,options,varargin{:}, fix, x0); + +% Reconstruct the full fitted parameter list including the fixed values. +xf = fix.*x0; +xf(find(fix==0)) = x; +x = xf; diff --git a/NODDI_toolbox_v1.01/fitting/fobj_rician.m b/NODDI_toolbox_v1.01/fitting/fobj_rician.m new file mode 100644 index 0000000..7acb8c7 --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/fobj_rician.m @@ -0,0 +1,43 @@ +function [sumRes, resJ, H]=fobj_rician(x, meas, protocol, model, sig, constants) +% Objective function for fitting models using a Rician noise model. +% +% x is the encoded model parameter values +% +% meas is the measurements +% +% protocol is the measurement protocol +% +% model is a string encoding the model +% +% sig is the standard deviation of the Gaussian distributions underlying +% the Rician noise +% +% constants contains values required to compute the model signals. +% +% author: Daniel C Alexander (d.alexander@ucl.ac.uk) +% + +% Need to transform to actual parameter values from optimized quantities. +xdec = GradDescDecode(model, x); + +scale = GetScalingFactors(model); +if (strcmp(model, 'ExCrossingCylSingleRadGPD') ||... + strcmp(model, 'ExCrossingCylSingleRadIsoDotTortIsoV_GPD_B0')) + xsc = xdec(1:(end-4))./scale(1:(end-1)); + theta = [xdec(end-3) xdec(end-1)]'; + phi = [xdec(end-2) xdec(end)]'; + fibredir = [cos(phi).*sin(theta) sin(phi).*sin(theta) cos(theta)]'; +else + xsc = xdec(1:(end-2))./scale(1:(end-1)); + theta = xdec(end-1); + phi = xdec(end); + fibredir = [cos(phi)*sin(theta) sin(phi)*sin(theta) cos(theta)]'; +end + +if(nargout == 1) + sumRes = fobj_rician_st(xsc, meas, protocol, model, sig, fibredir, constants); +elseif(nargout == 2) + [sumRes resJ] = fobj_rician_st(xsc, meas, protocol, model, sig, fibredir, constants); +else + [sumRes, resJ, H] = fobj_rician_st(xsc, meas, protocol, model, sig, fibredir, constants); +end diff --git a/NODDI_toolbox_v1.01/fitting/fobj_rician_fix.m b/NODDI_toolbox_v1.01/fitting/fobj_rician_fix.m new file mode 100644 index 0000000..2d9231d --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/fobj_rician_fix.m @@ -0,0 +1,36 @@ +function [sumRes, resJ, H]=fobj_rician_fix(x, meas, protocol, model, sig, constants, fix, x0) +% Wrapper for fobj_rician for use with fmincon_fix. +% +% x is the encoded model parameter values +% +% meas is the measurements +% +% protocol is the measurement protocol +% +% model is a string encoding the model +% +% sig is the standard deviation of the Gaussian distributions underlying +% the Rician noise +% +% constants contains values required to compute the model signals. +% +% fix is a binary array specifying which parameters are fixed and which +% vary. +% +% x0 is the full starting point including the fixed parameters. +% +% author: Daniel C Alexander (d.alexander@ucl.ac.uk) +% + +% Construct the full parameter list including fixed values. +xf = fix.*x0; +xf(find(fix==0)) = x; + +% Now call the full objective function. +if(nargout == 1) + sumRes = fobj_rician(xf, meas, protocol, model, sig, constants); +elseif(nargout == 2) + [sumRes resJ] = fobj_rician(xf, meas, protocol, model, sig, constants); +else + [sumRes, resJ, H] = fobj_rician(xf, meas, protocol, model, sig, constants); +end diff --git a/NODDI_toolbox_v1.01/fitting/fobj_rician_st.m b/NODDI_toolbox_v1.01/fitting/fobj_rician_st.m new file mode 100644 index 0000000..8206c3c --- /dev/null +++ b/NODDI_toolbox_v1.01/fitting/fobj_rician_st.m @@ -0,0 +1,69 @@ +function [sumRes, resJ, H] = fobj_rician_st(xsc, meas, protocol, model, sig, fibredir, constants) +% General function called by variants of fobj_rician once fibre direction +% has been extracted and other parameters scaled appropriately. +% +% xsc is the decoded model parameter values +% +% meas is the measurements +% +% protocol is the measurement protocol +% +% model is a string encoding the model +% +% sig is the standard deviation of the Gaussian distributions underlying +% the Rician noise +% +% fibredir is the fibre direction extracted from the full parameter list. +% +% constants contains values required to compute the model signals. +% +% author: Daniel C Alexander (d.alexander@ucl.ac.uk) +% + +E = SynthMeas(model, xsc, protocol, fibredir, constants); + +% Find the fitting error (log probabilities of the data given the parameter +% settings). +sumRes = -RicianLogLik(meas, E, sig); + +if(nargout>1) + % Construct the Jacobian of the probabilities from the Jacobian of the + % measurement estimates. + scp = meas.*signals./(sig.^2); + ysc = besseli1d0(scp); + sc = (E - meas.*ysc)./(sig.^2); + J = zeros(length(E), length(x)); + for i=1:(length(x)-1) + J(:,i) = sc.*Jnn(:,i); + end + + % Need to rescale the derivates to the scale of x + J = J./repmat(scale(1:(end-1)),[length(E),1]); + + % Now sum over the measurements + resJ = sum(J); +end + +% Finally create the Hessian matrix. Here in fact we use the Fisher +% information matrix instead to reduce computation and increase stability +% and convergence. Code is the same as FishMatRician.m. +% if(nargout>2) +% global RicCorX RicCorY; +% +% C = zeros(length(E),1); +% Esc = E/sig; +% out = find(Esc>=max(RicCorX)); +% in = find(Esc<max(RicCorX)); +% C(in) = interp1(RicCorX, RicCorY, Esc(in))*sig^2; +% C(out) = sig^2; +% JCor = Jnn.*repmat(C, [1,length(x)-1]); +% +% H = Jnn'*JCor/(sig^4); +% +% % Now compute the elements that depend on sigma. +% Jsig = Jnn.*repmat(sig^2*E + E.^3 + 2*E.*C, [1,length(x)-1]); +% H(length(x), 1:(length(x)-1)) = -2*sum(Jsig)/(sig^5); +% H(1:(length(x)-1), length(x)) = squeeze(H(length(x), 1:(length(x)-1))'); +% +% H(length(x), length(x)) = -4*sum(-sig^4 + sig^2*E.^2 - E.^2.*C)/(sig^6); +% end diff --git a/NODDI_toolbox_v1.01/models/BesselJ_RootsCyl.m b/NODDI_toolbox_v1.01/models/BesselJ_RootsCyl.m new file mode 100644 index 0000000..4ca982b --- /dev/null +++ b/NODDI_toolbox_v1.01/models/BesselJ_RootsCyl.m @@ -0,0 +1,31 @@ +function root = BesselJ_RootsCyl(starts) +% BesselJ_RootsCyl(starts) finds the roots of the equation J'_1(x) = 0 +% where J_1 is the first order Bessel function of the first kind. +% +% starts is the number of starting points in the search for +% roots. The larger it is, the more roots are returned in the root array. +% The default is 20, which returns 6 roots. starts = 100 returns 32 roots. +% Generally the number of roots is just under 1/3 the number of starting +% points. +% +% author: Daniel C Alexander (d.alexander@ucl.ac.uk) +% + +if(nargin==0) + starts = 20; +end + +f = @(x)(0.5*(besselj(0,x) - besselj(2,x))); + +% Get a good list of starting points +y = 0:0.1:starts; +dj1 = f(y); +starts = (find(dj1(1:end-1).*dj1(2:end)<0)+1)*0.1; + +for s=1:length(starts) + root(s) = fzero(f,starts(s)); +end + + + + diff --git a/NODDI_toolbox_v1.01/models/CylNeumanLePar_PGSE.m b/NODDI_toolbox_v1.01/models/CylNeumanLePar_PGSE.m new file mode 100644 index 0000000..2db0dd6 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/CylNeumanLePar_PGSE.m @@ -0,0 +1,42 @@ +function [LE,J]=CylNeumanLePar_PGSE(x, G, delta, smalldel) +% Substrate: Parallel, impermeable cylinders with one radius in an empty +% background. +% Pulse sequence: Pulsed gradient spin echo +% Signal approximation: Gaussian phase distribution. +% +% [LE,J]=CylNeumanLePar_PGSE(x, G, delta, smalldel) +% returns the log signal attenuation in parallel direction (LePar) according +% to the Neuman model and the Jacobian J of LePar with respect to the +% parameters. The Jacobian does not include derivates with respect to the +% fibre direction. +% +% x is the list of model parameters in SI units: +% x(1) is the diffusivity of the material inside the cylinders. +% +% G, delta and smalldel are the gradient strength, pulse separation and +% pulse length of each measurement in the protocol. Each has +% size [N 1]. +% +% author: Daniel C Alexander (d.alexander@ucl.ac.uk) +% Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +d=x(1); + +% Radial wavenumbers +GAMMA = 2.675987E8; +modQ = GAMMA*smalldel.*G; +modQ_Sq = modQ.^2; + +% diffusion time for PGSE, in a matrix for the computation below. +difftime = (delta-smalldel/3); + +% Parallel component +LE =-modQ_Sq.*difftime*d; + +% Compute the Jacobian matrix +if(nargout>1) + % dLE/d + J = -modQ_Sq.*difftime; +end + diff --git a/NODDI_toolbox_v1.01/models/CylNeumanLePerp_PGSE.m b/NODDI_toolbox_v1.01/models/CylNeumanLePerp_PGSE.m new file mode 100644 index 0000000..466cdc7 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/CylNeumanLePerp_PGSE.m @@ -0,0 +1,137 @@ +function [LE,J]=CylNeumanLePerp_PGSE(d, R, G, delta, smalldel, roots) +% Substrate: Parallel, impermeable cylinders with one radius in an empty +% background. +% Pulse sequence: Pulsed gradient spin echo +% Signal approximation: Gaussian phase distribution. +% +% [LE,J] = CylNeumanLePerp_PGSE(d, R, G, delta, smalldel, roots) +% +% returns the log signal attenuation in perpendicular direction (LePerp) for +% EACH RADIUS specified in R according to the Neuman model and the Jacobian J +% of LePerp with respect to the parameters. +% +% The Jacobian DOES NOT include derivates with respect to the fibre direction. +% +% d is the diffusivity of the material inside the cylinders. +% +% R is the list of the radii of the cylinders. It has size [1 m] where m is the +% number of radii. +% +% G, delta and smalldel are the gradient strength, pulse separation and +% pulse length of each measurement in the protocol. Each has +% size [N 1]. +% +% roots contains solutions to the Bessel function equation from function +% BesselJ_RootsCyl. +% +% author: Daniel C Alexander (d.alexander@ucl.ac.uk) +% Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +% When R=0, no need to do any calculation +if (R == 0.00) + LE = zeros(size(G,1), size(R,2)); + J = zeros([size(LE), 2]); + J(:,:,:) = 0; + return; +end + +% Check the roots array is correct +if(abs(roots(1) - 1.8412)>0.0001) + error('Looks like the roots array is wrong. First value should be 1.8412, but is %f', roots(1)); +end + +% Radial wavenumbers +GAMMA = 2.675987E8; + +% number of gradient directions, i.e. number of measurements +l_q=size(G,1); +l_a=numel(R); +k_max=numel(roots); + +R_mat=repmat(R,[l_q 1]); +R_mat=R_mat(:); +R_mat=repmat(R_mat,[1 1 k_max]); +R_matSq=R_mat.^2; + +root_m=reshape(roots,[1 1 k_max]); +alpha_mat=repmat(root_m,[l_q*l_a 1 1])./R_mat; +amSq=alpha_mat.^2; +amP6=amSq.^3; + +deltamx=repmat(delta,[1,l_a]); +deltamx_rep = deltamx(:); +deltamx_rep = repmat(deltamx_rep,[1 1 k_max]); + +smalldelmx=repmat(smalldel,[1,l_a]); +smalldelmx_rep = smalldelmx(:); +smalldelmx_rep = repmat(smalldelmx_rep,[1 1 k_max]); + +Gmx=repmat(G,[1,l_a]); +GmxSq = Gmx.^2; + +% Perpendicular component (Neuman model) +sda2 = smalldelmx_rep.*amSq; +bda2 = deltamx_rep.*amSq; +emdsda2 = exp(-d*sda2); +emdbda2 = exp(-d*bda2); +emdbdmsda2 = exp(-d*(bda2 - sda2)); +emdbdpsda2 = exp(-d*(bda2 + sda2)); + +sumnum1 = 2*d*sda2; +% the rest can be reused in dE/dR +sumnum2 = - 2 + 2*emdsda2 + 2*emdbda2; +sumnum2 = sumnum2 - emdbdmsda2 - emdbdpsda2; +sumnum = sumnum1 + sumnum2; + +sumdenom = d^2*amP6.*(R_matSq.*amSq - 1); + +% Check for zeros on top and bottom +%sumdenom(find(sumnum) == 0) = 1; +sumterms = sumnum./sumdenom; + +testinds = find(sumterms(:,:,end)>0); +test = sumterms(testinds,1)./sumterms(testinds,end); +if(min(test)<1E4) + warning('Ratio of largest to smallest terms in Neuman model sum is <1E4. May need more terms.'); +end + +s = sum(sumterms,3); +s = reshape(s,[l_q,l_a]); +if(min(s)<0) + warning('Negative sums found in Neuman sum. Setting to zero.'); + s(find(s<0))=0; +end + +LE = -2*GAMMA^2*GmxSq.*s; + +% Compute the Jacobian matrix +if(nargout>1) + + % dLE/dd + sumnumD = 2*sda2; + sumnumD = sumnumD - 2*sda2.*emdsda2; + sumnumD = sumnumD - 2*bda2.*emdbda2; + sumnumD = sumnumD + (bda2 - sda2).*emdbdmsda2; + sumnumD = sumnumD + (bda2 + sda2).*emdbdpsda2; + sumtermsD = sumnumD./sumdenom; + + sD = sum(sumtermsD,3); + sD = reshape(sD,[l_q,l_a]); + + dLEdd = -2*GAMMA^2*GmxSq.*(sD - 2*s/d); + + % dLE/dR + sumtermsR = (6*sumterms - 2*d*sumtermsD)./R_mat; + + sR = sum(sumtermsR,3); + sR = reshape(sR,[l_q,l_a]); + + dLEdr = -2*GAMMA^2*GmxSq.*sR; + + % Construct the jacobian matrix. + J = zeros([size(LE), 2]); + J(:,:,1) = dLEdd; + J(:,:,2) = dLEdr; +end + diff --git a/NODDI_toolbox_v1.01/models/GetB0.m b/NODDI_toolbox_v1.01/models/GetB0.m new file mode 100644 index 0000000..6569659 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/GetB0.m @@ -0,0 +1,16 @@ +function b0 = GetB0(modelname, fittedpars) +% +% function b0 = GetB0(modelname, fittedpars) +% +% Returns the b=0 signal estimate. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +b0Idx = GetParameterIndex(modelname, 'b0'); +if b0Idx > 0 + b0 = fittedpars(b0Idx); +else + b0 = 1; +end + diff --git a/NODDI_toolbox_v1.01/models/GetB_Values.m b/NODDI_toolbox_v1.01/models/GetB_Values.m new file mode 100644 index 0000000..660aff3 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/GetB_Values.m @@ -0,0 +1,25 @@ +function b = GetB_Values(protocol) +% Computes the b value for each measurement in the protocol +% +% b = GetB_Values(protocol) +% returns an array of b values, one for each measurement defined +% in the list of measurements in the protocol. +% +% author: Daniel C Alexander (d.alexander@ucl.ac.uk) +% + +GAMMA = 2.675987E8; +if(strcmp(protocol.pulseseq, 'PGSE') || strcmp(protocol.pulseseq, 'STEAM')) + modQ = GAMMA*protocol.smalldel.*protocol.G; + diffTime = protocol.delta - protocol.smalldel/3; + b = diffTime.*modQ.^2; + +elseif(strcmp(protocol.pulseseq, 'DSE')) + b = getB_ValuesDSE(protocol.G, protocol.delta1, protocol.delta2, protocol.delta3, protocol.t1, protocol.t2, protocol.t3); + +elseif(strcmp(protocol.pulseseq, 'OGSE')) + b = GetB_ValuesOGSE(protocol.G, protocol.delta, protocol.smalldel, protocol.omega); +end + + + diff --git a/NODDI_toolbox_v1.01/models/GetFibreOrientation.m b/NODDI_toolbox_v1.01/models/GetFibreOrientation.m new file mode 100644 index 0000000..3053520 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/GetFibreOrientation.m @@ -0,0 +1,14 @@ +function fibredir = GetFibreOrientation(modelname, fittedpars) +% +% function fibredir = GetFibreOrientation(modelname, fittedpars) +% +% Returns the fibre orientation as a unit vector from fitted parameters. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +theta = fittedpars(:, GetParameterIndex(modelname, 'theta')); +phi = fittedpars(:, GetParameterIndex(modelname, 'phi')); + +fibredir = [cos(phi).*sin(theta) sin(phi).*sin(theta) cos(theta)]'; + diff --git a/NODDI_toolbox_v1.01/models/GetParameterIndex.m b/NODDI_toolbox_v1.01/models/GetParameterIndex.m new file mode 100644 index 0000000..2cac511 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/GetParameterIndex.m @@ -0,0 +1,20 @@ +function idx = GetParameterIndex(modelname, parametername) +% +% function idx = GetParameterIndex(modelname, parametername) +% +% Given an input modelname and parametername, this function returns the index +% of the parameter within the model. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +strings = GetParameterStrings(modelname); + +for i=1:length(strings) + if (strcmp(strings(i), parametername)) + idx = i; + return; + end +end + +idx = -1; diff --git a/NODDI_toolbox_v1.01/models/GetParameterStrings.m b/NODDI_toolbox_v1.01/models/GetParameterStrings.m new file mode 100644 index 0000000..ef3c4b2 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/GetParameterStrings.m @@ -0,0 +1,34 @@ +function strings = GetParameterStrings(modelname) +% +% function strings = GetParameterStrings(modelname) +% +% Given an input modelname, this function returns the names of the model +% parameters +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +if (strcmp(modelname, 'StickIsoV_B0')) + strings = {'ficvf', 'di', 'dh', 'fiso', 'diso', 'b0', 'theta', 'phi'}; +elseif (strcmp(modelname, 'StickTortIsoV_B0')) + strings = {'ficvf', 'di', 'fiso', 'diso', 'b0', 'theta', 'phi'}; +elseif (strcmp(modelname, 'WatsonSHStick')) + strings = {'ficvf', 'di', 'dh', 'kappa', 'theta', 'phi'}; +elseif (strcmp(modelname, 'WatsonSHStickIsoV_B0')) + strings = {'ficvf', 'di', 'dh', 'kappa', 'fiso', 'diso', 'b0', 'theta', 'phi'}; +elseif (strcmp(modelname, 'WatsonSHStickIsoVIsoDot_B0')) + strings = {'ficvf', 'di', 'dh', 'kappa', 'fiso', 'diso', 'irfrac', 'b0', 'theta', 'phi'}; +elseif (strcmp(modelname, 'WatsonSHStickTortIsoV_B0')) + strings = {'ficvf', 'di', 'kappa', 'fiso', 'diso', 'b0', 'theta', 'phi'}; +elseif (strcmp(modelname, 'WatsonSHStickTortIsoVIsoDot_B0')) + strings = {'ficvf', 'di', 'kappa', 'fiso', 'diso', 'irfrac', 'b0', 'theta', 'phi'}; +elseif (strcmp(modelname, 'BinghamStickTortIsoV_B0')) + strings = {'ficvf', 'di', 'kappa', 'beta', 'psi', 'fiso', 'diso', 'b0', 'theta', 'phi'}; +elseif (strcmp(modelname, 'WatsonSHCylSingleRadTortIsoV_GPD_B0')) + strings = {'ficvf', 'di', 'rad', 'kappa', 'fiso', 'diso', 'b0', 'theta', 'phi'}; +elseif (strcmp(modelname, 'CylSingleRadIsoDotTortIsoV_GPD_B0')) + strings = {'ficvf', 'di', 'rad', 'irfrac', 'fiso', 'diso', 'b0', 'theta', 'phi'}; +else + error(['Parameter strings yet to be defined for this model:', modelname]); +end + diff --git a/NODDI_toolbox_v1.01/models/GetScalingFactors.m b/NODDI_toolbox_v1.01/models/GetScalingFactors.m new file mode 100644 index 0000000..d40f1dc --- /dev/null +++ b/NODDI_toolbox_v1.01/models/GetScalingFactors.m @@ -0,0 +1,44 @@ +function scale = GetScalingFactors(modelname) +% +% function scale = GetScalingFactors(modelname) +% +% Returns an array of scaling factors for the parameters of the model +% intended to rescale so that they all have value close to 1. +% +% Note that including the scaling factor for sigma increases the number +% of model variables by 1. +% +% Note that the scaling factor not set for theta and phi +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +parameterStrings = GetParameterStrings(modelname); + +% here the scaling factors do not include the ones for theta and phi +% but include one for the sigma +scale = zeros(1, length(parameterStrings) - 1); + +% the scaling factor for sigma is set to 1 +scale(end) = 1; + +for i=1:length(parameterStrings) + if (strcmp(parameterStrings(i), 'di') ||... + strcmp(parameterStrings(i), 'dh') ||... + strcmp(parameterStrings(i), 'diso')) + scale(i) = 1E9; + elseif (strcmp(parameterStrings(i), 'rad')) + scale(i) = 1E6; + elseif (strcmp(parameterStrings(i), 'ficvf') ||... + strcmp(parameterStrings(i), 'fiso') ||... + strcmp(parameterStrings(i), 'irfrac') ||... + strcmp(parameterStrings(i), 'psi') ||... + strcmp(parameterStrings(i), 'b0') ||... + strcmp(parameterStrings(i), 't1')) + scale(i) = 1; + elseif (strcmp(parameterStrings(i), 'kappa') ||... + strcmp(parameterStrings(i), 'beta')) + scale(i) = 0.1; + end +end + diff --git a/NODDI_toolbox_v1.01/models/MakeDT_Matrix.m b/NODDI_toolbox_v1.01/models/MakeDT_Matrix.m new file mode 100644 index 0000000..3d9633a --- /dev/null +++ b/NODDI_toolbox_v1.01/models/MakeDT_Matrix.m @@ -0,0 +1,14 @@ +function dt = MakeDT_Matrix(d11, d12, d13, d22, d23, d33) +% Makes a diffusion tensor matrix out of the six elements. +% +% dt = MakeDT_Matrix(d11, d12, d13, d22, d23, d33) +% returns the matrix +% [d11 d12 d13] +% [d12 d22 d23] +% [d13 d23 d33] +% +% author: Daniel C Alexander (d.alexander@ucl.ac.uk) +% + +dt = [d11 d12 d13; d12 d22 d23; d13 d23 d33]; + diff --git a/NODDI_toolbox_v1.01/models/MakeModel.m b/NODDI_toolbox_v1.01/models/MakeModel.m new file mode 100644 index 0000000..6bd4864 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/MakeModel.m @@ -0,0 +1,89 @@ +function model = MakeModel(modelname) + +% function model = MakeModel(modelname) +% +% Set up the model specification for fitting +% +% model.name: model name +% +% model.numParams: number of parameters +% +% model.paramsStr: parameter strings +% +% model.tissuetype: type of tissue +% +% model.noOfStages: how many stages to run +% +% model.fixGD: fixed variables during gradient descent +% model.fixedvalsGD: values for the fixed variables during gradient descent +% +% model.fixMCMC: fixed variables during MCMC +% model.MCMC.steplengths: MCMC step lengths +% model.MCMC.burnin: MCMC burn-in +% model.MCMC.interval: MCMC interval +% model.MCMC.samples: MCMC samples +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +model.name = modelname; +model.numParams = NumFreeParams(modelname); +model.paramsStr = GetParameterStrings(modelname); +model.tissuetype = 'invivo'; +model.GS.fixed = zeros(1, model.numParams); +model.GS.fixedvals = zeros(1, model.numParams); +model.GD.fixed = zeros(1, model.numParams); +model.GD.fixedvals = zeros(1, model.numParams); +model.GD.type = 'single'; % 'multistart' +model.GD.multistart.perturbation = zeros(1, model.numParams); +model.GD.multistart.noOfRuns = 10; +model.MCMC.fixed = ones(1, model.numParams + 1); +model.MCMC.steplengths = 0.05*ones(1, model.numParams+1); +model.MCMC.burnin = 2000; +model.MCMC.interval = 200; +model.MCMC.samples = 40; +model.noOfStages = 2; +model.sigma.perVoxel = 1; +model.sigma.minSNR = 0.02; +model.sigma.scaling = 100; + +% use exvivo setting if isotropic restriction is included +irfracIdx = GetParameterIndex(modelname, 'irfrac'); +if irfracIdx > 0 + model.tissuetype = 'exvivo'; +end + +% fix intrinsic diffusivity +diIdx = GetParameterIndex(modelname, 'di'); +model.GS.fixed(diIdx) = 1; +model.GD.fixed(diIdx) = 1; +if strcmp(model.tissuetype, 'invivo') + model.GS.fixedvals(diIdx) = 1.7E-9; + model.GD.fixedvals(diIdx) = 1.7E-9; +else + model.GS.fixedvals(diIdx) = 0.6E-9; + model.GD.fixedvals(diIdx) = 0.6E-9; +end + +% fix isotropic diffusivity +disoIdx = GetParameterIndex(modelname, 'diso'); +if disoIdx > 0 + model.GS.fixed(disoIdx) = 1; + model.GD.fixed(disoIdx) = 1; + if strcmp(model.tissuetype, 'invivo') + model.GS.fixedvals(disoIdx) = 3.0E-9; + model.GD.fixedvals(disoIdx) = 3.0E-9; + else + model.GS.fixedvals(disoIdx) = 2.0E-9; + model.GD.fixedvals(disoIdx) = 2.0E-9; + end +end + +% fix B0 +% fixed value is estimated from the b0 images voxel-wise +b0Idx = GetParameterIndex(modelname, 'b0'); +if b0Idx > 0 + model.GS.fixed(b0Idx) = 1; + model.GD.fixed(b0Idx) = 1; +end + diff --git a/NODDI_toolbox_v1.01/models/NumFreeParams.m b/NODDI_toolbox_v1.01/models/NumFreeParams.m new file mode 100644 index 0000000..6905509 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/NumFreeParams.m @@ -0,0 +1,11 @@ +function numParams = NumFreeParams(modelname) +% +% function numParams = NumFreeParams(modelname) +% +% Given an input modelname, returns the number of free parameters of the model. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +numParams = length(GetParameterStrings(modelname)); + diff --git a/NODDI_toolbox_v1.01/models/RicianLogLik.m b/NODDI_toolbox_v1.01/models/RicianLogLik.m new file mode 100644 index 0000000..2d504e7 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/RicianLogLik.m @@ -0,0 +1,22 @@ +function loglik = RicianLogLik(meas, signals, sig) +% Computes the log likelihood of the measurements given the model signals +% for the Rician noise model. +% +% loglik = RicianLogLik(meas, signals, sig) returns the likelihood of +% measuring meas given the signals and the noise standard deviation sig. +% +% meas are the measurements +% +% signals are computed from a model +% +% sig is the standard deviation of the Gaussian distributions underlying +% the Rician distribution. +% +% author: Daniel C Alexander (d.alexander@ucl.ac.uk) +% + +sumsqsc = (signals.^2 + meas.^2)./(2*sig.^2); +scp = meas.*signals./(sig.^2); +lb0 = logbesseli0(scp); +logliks = - 2*log(sig) - sumsqsc + log(signals) + lb0; +loglik = sum(logliks); diff --git a/NODDI_toolbox_v1.01/models/SynthMeas.m b/NODDI_toolbox_v1.01/models/SynthMeas.m new file mode 100644 index 0000000..3d91046 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/SynthMeas.m @@ -0,0 +1,212 @@ +function [E J] = SynthMeas(model, xsc, protocol, fibredir, constants) +% +% function [E J] = SynthMeas(model, xsc, protocol, fibredir, constants) +% +% General method for generating synthetic data from a model. +% +% author: Daniel C Alexander (d.alexander@ucl.ac.uk) +% Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +if(nargout == 1) + if(strcmp(model, 'IsoGPD')) + [E] = SynthMeasIsoGPD(xsc, protocol); + elseif(strcmp(model, 'CylSingleRadGPD')) + [E] = SynthMeasCylSingleRadGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'CylSingleRadGPD_B0')) + [E] = SynthMeasCylSingleRadGPD_B0(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'CylSingleRadIsoV_GPD')) + [E] = SynthMeasCylSingleRadIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'CylSingleRadIsoV_GPD_B0')) + [E] = SynthMeasCylSingleRadIsoV_GPD_B0(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'CylSingleRadTortGPD')) + [E] = SynthMeasCylSingleRadTortGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'CylSingleRadTortIsoGPD')) + [E] = SynthMeasCylSingleRadTortIsoGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'CylSingleRadTortIsoV_GPD')) + [E] = SynthMeasCylSingleRadTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'CylSingleRadTortIsoV_GPD_B0')) + [E] = SynthMeasCylSingleRadTortIsoV_GPD_B0(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'CylSingleRadIsoCylTortIsoV_GPD')) + [E] = SynthMeasCylSingleRadIsoCylTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'CylSingleRadIsoStickTortIsoV_GPD')) + [E] = SynthMeasCylSingleRadIsoStickTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'CylSingleRadIsoSphereTortIsoV_GPD')) + [E] = SynthMeasCylSingleRadIsoSphereTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl, constants.roots_sph); + elseif(strcmp(model, 'CylSingleRadIsoDotGPD')) + [E] = SynthMeasCylSingleRadIsoDotGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'CylSingleRadIsoDotTortIsoV_GPD')) + [E] = SynthMeasCylSingleRadIsoDotTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'CylSingleRadIsoDotTortIsoV_GPD_B0')) + [E] = SynthMeasCylSingleRadIsoDotTortIsoV_GPD_B0(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'CylSingleRadIsoDotTortIsoV_GPD_B0T1')) + [E] = SynthMeasCylSingleRadIsoDotTortIsoV_GPD_B0T1(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'CylSingleRadIsoSphereTortIsoV_GPD')) + [E] = SynthMeasCylSingleRadIsoSphereTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'CylGammaRadGPD')) + [E] = SynthMeasCylGammaRadGPD_PGSE(xsc, protocol.grad_dirs, protocol.G', protocol.delta', protocol.smalldel', fibredir, constants.roots_cyl, 0); + elseif(strcmp(model, 'CylGammaRadTortGPD')) + [E] = SynthMeasCylGammaRadTortGPD(xsc, protocol, fibredir, constants.roots_cyl, 0); + elseif(strcmp(model, 'CylGammaRadTortIsoGPD')) + [E] = SynthMeasCylGammaRadTortIsoGPD(xsc, protocol, fibredir, constants.roots_cyl, 0); + elseif(strcmp(model, 'CylGammaRadTortIsoV_GPD')) + [E] = SynthMeasCylGammaRadTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl, 0); + elseif(strcmp(model, 'CylGammaRadByVolGPD')) + [E] = SynthMeasCylGammaRadByVolGPD_PGSE(xsc, protocol.grad_dirs, protocol.G', protocol.delta', protocol.smalldel', fibredir, constants.roots_cyl, 0); + elseif(strcmp(model, 'CylGammaRadByVolTortGPD')) + [E] = SynthMeasCylGammaRadByVolTortGPD(xsc, protocol, fibredir, constants.roots_cyl, 0); + elseif(strcmp(model, 'CylGammaRadByVolTortIsoGPD')) + [E] = SynthMeasCylGammaRadByVolTortIsoGPD(xsc, protocol, fibredir, constants.roots_cyl, 0); + elseif(strcmp(model, 'CylGammaRadByVolTortIsoV_GPD')) + [E] = SynthMeasCylGammaRadByVolTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl, 0); + elseif(strcmp(model, 'SphereSingleRadGPD')) + [E] = SynthMeasSphereSingleRadGPD(xsc, protocol, constants.roots_sph); + elseif(strcmp(model, 'Stick')) + [E] = SynthMeasStick(xsc, protocol, fibredir); + elseif(strcmp(model, 'StickTort')) + [E] = SynthMeasStickTort(xsc, protocol, fibredir); + elseif(strcmp(model, 'StickIsoV_B0')) + [E] = SynthMeasStickIsoV_B0(xsc, protocol, fibredir); + elseif(strcmp(model, 'StickTortIsoV_B0')) + [E] = SynthMeasStickTortIsoV_B0(xsc, protocol, fibredir); + elseif(strcmp(model, 'WatsonCylSingleRadGPD')) + [E] = SynthMeasWatsonCylSingleRadGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'WatsonCylSingleRadTortGPD')) + [E] = SynthMeasWatsonCylSingleRadTortGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'WatsonCylSingleRadTortIsoV_GPD')) + [E] = SynthMeasWatsonCylSingleRadTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'WatsonCylSingleRadTortIsoV_GPD_B0')) + [E] = SynthMeasWatsonCylSingleRadTortIsoV_GPD_B0(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'WatsonStick')) + [E] = SynthMeasWatsonStick(xsc, protocol, fibredir); + elseif(strcmp(model, 'WatsonStickTort')) + [E] = SynthMeasWatsonStickTort(xsc, protocol, fibredir); + elseif(strcmp(model, 'WatsonSHCylSingleRadGPD')) + [E] = SynthMeasWatsonSHCylSingleRadGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'WatsonSHCylSingleRadTortGPD')) + [E] = SynthMeasWatsonSHCylSingleRadTortGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'WatsonSHCylSingleRadTortIsoV_GPD')) + [E] = SynthMeasWatsonSHCylSingleRadTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'WatsonSHCylSingleRadTortIsoV_GPD_B0')) + [E] = SynthMeasWatsonSHCylSingleRadTortIsoV_GPD_B0(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'WatsonSHStick')) + [E] = SynthMeasWatsonSHStick(xsc, protocol, fibredir); + elseif(strcmp(model, 'WatsonSHStickIsoV_B0')) + [E] = SynthMeasWatsonSHStickIsoV_B0(xsc, protocol, fibredir); + elseif(strcmp(model, 'WatsonSHStickIsoVIsoDot_B0')) + [E] = SynthMeasWatsonSHStickIsoVIsoDot_B0(xsc, protocol, fibredir); + elseif(strcmp(model, 'WatsonSHStickTort')) + [E] = SynthMeasWatsonSHStickTort(xsc, protocol, fibredir); + elseif(strcmp(model, 'WatsonSHStickTortIsoV_B0')) + [E] = SynthMeasWatsonSHStickTortIsoV_B0(xsc, protocol, fibredir); + elseif(strcmp(model, 'WatsonSHStickTortIsoVIsoDot_B0')) + [E] = SynthMeasWatsonSHStickTortIsoVIsoDot_B0(xsc, protocol, fibredir); + elseif(strcmp(model, 'BinghamCylSingleRadGPD')) + [E] = SynthMeasBinghamCylSingleRadGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'BinghamCylSingleRadTortGPD')) + [E] = SynthMeasBinghamCylSingleRadTortGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'BinghamCylSingleRadTortIsoV_GPD')) + [E] = SynthMeasBinghamCylSingleRadTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'BinghamCylSingleRadTortIsoV_GPD_B0')) + [E] = SynthMeasBinghamCylSingleRadTortIsoV_GPD_B0(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'BinghamStickTortIsoV_B0')) + [E] = SynthMeasBinghamStickTortIsoV_B0(xsc, protocol, fibredir); + elseif(strcmp(model, 'ExCrossingCylSingleRadGPD')) + [E] = SynthMeasExCrossingCylSingleRadGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'ExCrossingCylSingleRadGPD')) + [E] = SynthMeasExCrossingCylSingleRadTortGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'ExCrossingCylSingleRadIsoDotGPD')) + [E] = SynthMeasExCrossingCylSingleRadIsoDotGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'ExCrossingCylSingleRadIsoDotTortGPD')) + [E] = SynthMeasExCrossingCylSingleRadIsoDotTortGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'ExCrossingCylSingleRadIsoDotTortIsoV_GPD')) + [E] = SynthMeasExCrossingCylSingleRadIsoDotTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'ExCrossingCylSingleRadIsoDotTortIsoV_GPD_B0')) + [E] = SynthMeasExCrossingCylSingleRadIsoDotTortIsoV_GPD_B0(xsc, protocol, fibredir, constants.roots_cyl); + else + error(['Undefined model: ', model]); + end +else + if(strcmp(model, 'IsoGPD')) + [E J] = SynthMeasIsoGPD(xsc, protocol); + elseif(strcmp(model, 'CylSingleRadGPD')) + [E J] = SynthMeasCylSingleRadGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'CylSingleRadIsoV_GPD')) + [E J] = SynthMeasCylSingleRadIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'CylSingleRadIsoV_GPD_B0')) + [E J] = SynthMeasCylSingleRadIsoV_GPD_B0(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'CylSingleRadTortGPD')) + [E J] = SynthMeasCylSingleRadTortGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'CylSingleRadTortIsoGPD')) + [E J] = SynthMeasCylSingleRadTortIsoGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'CylSingleRadTortIsoV_GPD')) + [E J] = SynthMeasCylSingleRadTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'CylSingleRadTortIsoV_GPD_B0')) + [E J] = SynthMeasCylSingleRadTortIsoV_GPD_B0(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'CylGammaRadGPD')) + [E J] = SynthMeasCylGammaRadGPD_PGSE(xsc, protocol.grad_dirs, protocol.G', protocol.delta', protocol.smalldel', fibredir, constants.roots_cyl, 0); + elseif(strcmp(model, 'CylGammaRadTortGPD')) + [E J] = SynthMeasCylGammaRadTortGPD(xsc, protocol, fibredir, constants.roots_cyl, 0); + elseif(strcmp(model, 'CylGammaRadTortIsoGPD')) + [E J] = SynthMeasCylGammaRadTortIsoGPD(xsc, protocol, fibredir, constants.roots_cyl, 0); + elseif(strcmp(model, 'CylGammaRadTortIsoV_GPD')) + [E J] = SynthMeasCylGammaRadTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl, 0); + elseif(strcmp(model, 'CylGammaRadByVolGPD')) + [E J] = SynthMeasCylGammaRadByVolGPD_PGSE(xsc, protocol.grad_dirs, protocol.G', protocol.delta', protocol.smalldel', fibredir, constants.roots_cyl, 0); + elseif(strcmp(model, 'CylGammaRadByVolTortGPD')) + [E J] = SynthMeasCylGammaRadByVolTortGPD(xsc, protocol, fibredir, constants.roots_cyl, 0); + elseif(strcmp(model, 'CylGammaRadByVolTortIsoGPD')) + [E J] = SynthMeasCylGammaRadByVolTortIsoGPD(xsc, protocol, fibredir, constants.roots_cyl, 0); + elseif(strcmp(model, 'CylGammaRadByVolTortIsoV_GPD')) + [E J] = SynthMeasCylGammaRadByVolTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl, 0); + elseif(strcmp(model, 'SphereSingleRadGPD')) + [E J] = SynthMeasSphereSingleRadGPD(xsc, protocol, constants.roots_sph); + elseif(strcmp(model, 'CylSingleRadGPD_B0')) + [E J] = SynthMeasCylSingleRadGPD_B0(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'Stick')) + [E J] = SynthMeasStick(xsc, protocol, fibredir); + elseif(strcmp(model, 'StickTort')) + [E J] = SynthMeasStickTort(xsc, protocol, fibredir); + elseif(strcmp(model, 'WatsonStick')) + [E J] = SynthMeasWatsonStick(xsc, protocol, fibredir); + elseif(strcmp(model, 'WatsonStickTort')) + [E J] = SynthMeasWatsonStickTort(xsc, protocol, fibredir); + elseif(strcmp(model, 'WatsonSHStick')) + [E J] = SynthMeasWatsonSHStick(xsc, protocol, fibredir); + elseif(strcmp(model, 'WatsonSHStickIsoV_B0')) + [E J] = SynthMeasWatsonSHStickIsoV_B0(xsc, protocol, fibredir); + elseif(strcmp(model, 'WatsonSHStickIsoVIsoDot_B0')) + [E J] = SynthMeasWatsonSHStickIsoVIsoDot_B0(xsc, protocol, fibredir); + elseif(strcmp(model, 'WatsonSHStickTort')) + [E J] = SynthMeasWatsonSHStickTort(xsc, protocol, fibredir); + elseif(strcmp(model, 'WatsonSHStickTortIsoV_B0')) + [E J] = SynthMeasWatsonSHStickTortIsoV_B0(xsc, protocol, fibredir); + elseif(strcmp(model, 'WatsonSHStickTortIsoVIsoDot_B0')) + [E J] = SynthMeasWatsonSHStickTortIsoVIsoDot_B0(xsc, protocol, fibredir); + elseif(strcmp(model, 'WatsonCylSingleRadGPD')) + [E J] = SynthMeasWatsonCylSingleRadGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'WatsonSHCylSingleRadGPD')) + [E J] = SynthMeasWatsonSHCylSingleRadGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'WatsonSHCylSingleRadTortGPD')) + [E J] = SynthMeasWatsonSHCylSingleRadTortGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'WatsonSHCylSingleRadTortIsoV_GPD')) + [E J] = SynthMeasWatsonSHCylSingleRadTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'BinghamCylSingleRadGPD')) + [E J] = SynthMeasBinghamCylSingleRadGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'ExCrossingCylSingleRadGPD')) + [E J] = SynthMeasExCrossingCylSingleRadGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'ExCrossingCylSingleRadTortGPD')) + [E J] = SynthMeasExCrossingCylSingleRadTortGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'ExCrossingCylSingleRadIsoDotGPD')) + [E J] = SynthMeasExCrossingCylSingleRadIsoDotGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'ExCrossingCylSingleRadIsoDotTortGPD')) + [E J] = SynthMeasExCrossingCylSingleRadIsoDotTortGPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'ExCrossingCylSingleRadIsoDotTortIsoV_GPD')) + [E J] = SynthMeasExCrossingCylSingleRadIsoDotTortIsoV_GPD(xsc, protocol, fibredir, constants.roots_cyl); + elseif(strcmp(model, 'ExCrossingCylSingleRadIsoDotTortIsoV_GPD_B0')) + [E J] = SynthMeasExCrossingCylSingleRadIsoDotTortIsoV_GPD_B0(xsc, protocol, fibredir, constants.roots_cyl); + else + error(['Undefined model: ', model]); + end +end + diff --git a/NODDI_toolbox_v1.01/models/SynthMeasHinderedDiffusion_PGSE.m b/NODDI_toolbox_v1.01/models/SynthMeasHinderedDiffusion_PGSE.m new file mode 100644 index 0000000..f384052 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/SynthMeasHinderedDiffusion_PGSE.m @@ -0,0 +1,61 @@ +function [E,J]=SynthMeasHinderedDiffusion_PGSE(x, grad_dirs, G, delta, smalldel, fibredir) +% Substrate: Anisotropic hindered diffusion compartment +% Pulse sequence: Pulsed gradient spin echo +% Signal approximation: N/A +% +% [E,J]=SynthMeasHinderedDiffusion_PGSE(x, grad_dirs, G, delta, smalldel, fibredir) +% returns the measurements E according to the model and the Jacobian J of the +% measurements with respect to the parameters. The Jacobian does not +% include derivates with respect to the fibre direction. +% +% x is the list of model parameters in SI units: +% x(1) is the free diffusivity of the material inside and outside the cylinders. +% x(2) is the hindered diffusivity outside the cylinders in perpendicular directions. +% +% grad_dirs is the gradient direction for each measurement. It has size [N +% 3] where N is the number of measurements. +% +% G, delta and smalldel are the gradient strength, pulse separation and +% pulse length of each measurement in the protocol. Each has +% size [N 1]. +% +% fibredir is a unit vector along the cylinder axis. It must be in +% Cartesian coordinates [x y z]' with size [3 1]. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +dPar=x(1); +dPerp=x(2); + +% Radial wavenumbers +GAMMA = 2.675987E8; +modQ = GAMMA*smalldel.*G; +modQ_Sq = modQ.^2; + +% Angles between gradient directions and fibre direction. +cosTheta = grad_dirs*fibredir; +cosThetaSq = cosTheta.^2; +sinThetaSq = 1-cosThetaSq; + +% b-value +bval = (delta-smalldel/3).*modQ_Sq; + +% Find hindered signals +E=exp(-bval.*((dPar - dPerp)*cosThetaSq + dPerp)); + +% Compute the Jacobian matrix +if(nargout>1) + bvalE = bval.*E; + % dE/ddPar + dEddPar = -bvalE.*cosThetaSq; + + % dE/ddPerp + dEddPerp = -bvalE.*sinThetaSq; + + % Construct the jacobian matrix. + J = zeros(size(E, 1), 2); + J(:,1) = dEddPar; + J(:,2) = dEddPerp; +end + diff --git a/NODDI_toolbox_v1.01/models/SynthMeasIsoGPD.m b/NODDI_toolbox_v1.01/models/SynthMeasIsoGPD.m new file mode 100644 index 0000000..71f506a --- /dev/null +++ b/NODDI_toolbox_v1.01/models/SynthMeasIsoGPD.m @@ -0,0 +1,73 @@ +function [E,J]=SynthMeasIsoGPD(d, protocol) +% Computes signals and their derivatives for isotropic free diffusion with +% diffusivity d for the protocol. +% +% [E,J]=SynthMeasIsoGPD(d, protocol) +% returns the measurements E according to the model and the Jacobian J of the +% measurements with respect to the parameter d. +% +% d is the diffusivity. +% +% protocol is the object containing the acquisition protocol. +% +% author: Daniel C Alexander (d.alexander@ucl.ac.uk) +% + +if(strcmp(protocol.pulseseq, 'PGSE') || strcmp(protocol.pulseseq, 'STEAM')) + + GAMMA = 2.675987E8; + modQ = GAMMA*protocol.smalldel'.*protocol.G'; + modQ_Sq = modQ.^2; + difftime = (protocol.delta'-protocol.smalldel'/3); + + E = exp(-difftime.*modQ_Sq*d); + if(nargout>1) + J = -difftime.*modQ_Sq.*E; + end +elseif(strcmp(protocol.pulseseq, 'FullSTEAM')) + + GAMMA = 2.675987E8; + + FullG = protocol.grad_dirs.*repmat(protocol.G', [1 3]); + GdGd = sum(FullG.*FullG,2)'; + GcGc = sum(protocol.cG.*protocol.cG,2)'; + GrGr = sum(protocol.rG.*protocol.rG,2)'; + GdGc = sum(FullG.*protocol.cG,2)'; + GdGr = sum(FullG.*protocol.rG,2)'; + GcGr = sum(protocol.cG.*protocol.rG,2)'; + + tdd = protocol.gap1 + protocol.gap2 + protocol.TM + 2*protocol.sdelc + 2*protocol.smalldel/3 + 2*protocol.sdelr; + tcc = protocol.TM + 2*protocol.sdelc/3 + 2*protocol.sdelr; + trr = protocol.TM + 2*protocol.sdelr/3; + tdc = protocol.TM + protocol.sdelc + 2*protocol.sdelr; + tdr = protocol.TM + protocol.sdelr; + tcr = protocol.TM + protocol.sdelr; + + gqt = GAMMA^2*(GdGd.*protocol.smalldel.^2.*tdd + ... + GcGc.*protocol.sdelc.^2.*tcc + ... + GrGr.*protocol.sdelr.^2.*trr + ... + 2*GdGc.*protocol.smalldel.*protocol.sdelc.*tdc + ... + 2*GdGr.*protocol.smalldel.*protocol.sdelr.*tdr + ... + 2*GcGr.*protocol.sdelc.*protocol.sdelr.*tcr); + + E=exp(-gqt'*d); + + if(nargout>1) + J = -gqt.*E; + end +elseif(strcmp(protocol.pulseseq, 'DSE')) + bValue = GetB_ValuesDSE(protocol.G', protocol.delta1', protocol.delta2', protocol.delta3', protocol.t1', protocol.t2', protocol.t3'); + E = exp(-bValue*d); + if(nargout>1) + J = -bValue.*E; + end +elseif(strcmp(protocol.pulseseq, 'OGSE')) + bValue = GetB_Values(protocol)'; + E = exp(-bValue*d); + if(nargout>1) + J = -bValue.*E; + end +else + error('Not implemented for pulse sequence: %s', protocol.pulseseq); +end + diff --git a/NODDI_toolbox_v1.01/models/logbesseli0.m b/NODDI_toolbox_v1.01/models/logbesseli0.m new file mode 100644 index 0000000..5134559 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/logbesseli0.m @@ -0,0 +1,25 @@ +% Computes log(besseli(0,x)) robustly. Computing it directly causes +% numerical problems at high x, but the function has asymptotic linear +% behaviour, which we approximate here for high x. +% +% author: Daniel C Alexander (d.alexander@ucl.ac.uk) +% + +function lb0 = logbesseli0(x) + +% For very large arguments to besseli, we approximate log besseli using a +% linear model of the asymptotic behaviour. +% The linear parameters come from this command: +% app=regress(log(besseli(0,500:700))',[ones(201,1) (500:700)']); +app = [-3.61178295877576 0.99916157999904]; + +lb0 = zeros(length(x), 1); +exact = find(x<700); +approx = find(x>=700); +lb0(exact) = log(besseli(0, x(exact))); +%lb0(approx) = x(approx)*app(2) + app(1); + +% This is a more standard approximation. For large x, I_0(x) -> exp(x)/sqrt(2 pi x). +lb0(approx) = x(approx) - log(2*pi*x(approx))/2; + + diff --git a/NODDI_toolbox_v1.01/models/watson/LegendreGaussianIntegral.m b/NODDI_toolbox_v1.01/models/watson/LegendreGaussianIntegral.m new file mode 100644 index 0000000..dd4a342 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/watson/LegendreGaussianIntegral.m @@ -0,0 +1,155 @@ +function [L, D] = legendreGaussianIntegral(x, n) +% function [L, D] = legendreGaussianIntegral(x, n) +% Computes legendre gaussian integrals up to the order specified and the +% derivatives if requested +% +% The integral takes the following form, in Mathematica syntax, +% +% L[x, n] = Integrate[Exp[-x \mu^2] Legendre[2*n, \mu], {\mu, -1, 1}] +% D[x, n] = Integrate[Exp[-x \mu^2] (-\mu^2) Legendre[2*n, \mu], {\mu, -1, 1}] +% +% INPUTS: +% +% x should be a column vector of positive numbers, specifying the +% parameters of the gaussian +% +% n should be a non-negative integer, such that 2n specifies the maximum order +% of legendre polynomial +% +% The maximum value for n is 6. +% +% OUTPUTS: +% +% L will be a two-dimensional array with each row containing the +% legendre gaussian integrals of the orders 0, 2, 4, ..., to 2n for the +% parameter value at the corresponding row in x +% +% Note that the legendre gaussian integrals of the odd orders are zero. +% +% D will be the 1st order derivative of L +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +% Make sure n is not larger than 6 +if n > 6 + error('The maximum value for n is 6, which correspondes to the 12th order Legendre polynomial'); +end + +% +% Computing the related exponent gaussian integrals +% I[x, n] = Integrate[Exp[-x \mu^2] \mu^(2*n), {\mu, -1, 1}] +% with the following recursion: +% 1) I[x, 0] = Sqrt[\pi]Erf[x]/Sqrt[x] +% 2) I[x, n+1] = -Exp[-x]/x + (2n+1)/(2x) I[x, n] +% +% This does not work well when x is small + +exact = find(x>0.05); +approx = find(x<=0.05); +% Necessary to make matlab happy when x is a single value +exact = exact(:); +approx = approx(:); + +if nargout > 1 + mn = n + 2; +else + mn = n + 1; +end +I = zeros(length(x),mn); +sqrtx = sqrt(x(exact)); +I(exact,1) = sqrt(pi)*erf(sqrtx)./sqrtx; +dx = 1.0./x(exact); +emx = -exp(-x(exact)); +for i = 2:mn + I(exact,i) = emx + (i-1.5)*I(exact,i-1); + I(exact,i) = I(exact,i).*dx; +end + +% Computing the legendre gaussian integrals for large enough x +L = zeros(length(x),n+1); +for i = 1:n+1 + if i == 1 + L(exact,1) = I(exact,1); + elseif i == 2 + L(exact,2) = -0.5*I(exact,1) + 1.5*I(exact,2); + elseif i == 3 + L(exact,3) = 0.375*I(exact,1) - 3.75*I(exact,2) + 4.375*I(exact,3); + elseif i == 4 + L(exact,4) = -0.3125*I(exact,1) + 6.5625*I(exact,2) - 19.6875*I(exact,3) + 14.4375*I(exact,4); + elseif i == 5 + L(exact,5) = 0.2734375*I(exact,1) - 9.84375*I(exact,2) + 54.140625*I(exact,3) - 93.84375*I(exact,4) + 50.2734375*I(exact,5); + elseif i == 6 + L(exact,6) = -(63/256)*I(exact,1) + (3465/256)*I(exact,2) - (30030/256)*I(exact,3) + (90090/256)*I(exact,4) - (109395/256)*I(exact,5) + (46189/256)*I(exact,6); + elseif i == 7 + L(exact,7) = (231/1024)*I(exact,1) - (18018/1024)*I(exact,2) + (225225/1024)*I(exact,3) - (1021020/1024)*I(exact,4) + (2078505/1024)*I(exact,5) - (1939938/1024)*I(exact,6) + (676039/1024)*I(exact,7); + end +end + +% Computing the legendre gaussian integrals for small x +x2=x(approx,1).^2; +x3=x2.*x(approx,1); +x4=x3.*x(approx,1); +x5=x4.*x(approx,1); +x6=x5.*x(approx,1); +for i = 1:n+1 + if i == 1 + L(approx,1) = 2 - 2*x(approx,1)/3 + x2/5 - x3/21 + x4/108; + elseif i == 2 + L(approx,2) = -4*x(approx,1)/15 + 4*x2/35 - 2*x3/63 + 2*x4/297; + elseif i == 3 + L(approx,3) = 8*x2/315 - 8*x3/693 + 4*x4/1287; + elseif i == 4 + L(approx,4) = -16*x3/9009 + 16*x4/19305; + elseif i == 5 + L(approx,5) = 32*x4/328185; + elseif i == 6 + L(approx,6) = -64*x5/14549535; + elseif i == 7 + L(approx,7) = 128*x6/760543875; + end +end + +if nargout == 1 + return; +end + +% Computing the derivatives for large enough x +D = zeros(length(x),n+1); +for i = 1:n+1 + if i == 1 + D(exact,1) = -I(exact,2); + elseif i == 2 + D(exact,2) = 0.5*I(exact,2) - 1.5*I(exact,3); + elseif i == 3 + D(exact,3) = -0.375*I(exact,2) + 3.75*I(exact,3) - 4.375*I(exact,4); + elseif i == 4 + D(exact,4) = 0.3125*I(exact,2) - 6.5625*I(exact,3) + 19.6875*I(exact,4) - 14.4375*I(exact,5); + elseif i == 5 + D(exact,5) = -0.2734375*I(exact,2) + 9.84375*I(exact,3) - 54.140625*I(exact,4) + 93.84375*I(exact,5) - 50.2734375*I(exact,6); + elseif i == 6 + D(exact,6) = (63/256)*I(exact,2) - (3465/256)*I(exact,3) + (30030/256)*I(exact,4) - (90090/256)*I(exact,5) + (109395/256)*I(exact,6) - (46189/256)*I(exact,7); + elseif i == 7 + D(exact,7) = -(231/1024)*I(exact,2) + (18018/1024)*I(exact,3) - (225225/1024)*I(exact,4) + (1021020/1024)*I(exact,5) - (2078505/1024)*I(exact,6) + (1939938/1024)*I(exact,7) - (676039/1024)*I(exact,8); + end +end + +% Computing the derivatives for small x +for i = 1:n+1 + if i == 1 + D(approx,1) = -2/3 + 2*x(approx,1)/5 - x2/7 + x3/27 - x4/132; + elseif i == 2 + D(approx,2) = -4/15 + 8*x(approx,1)/35 - 2*x2/21 + 8*x3/297 - 5*x4/858; + elseif i == 3 + D(approx,3) = 16*x(approx,1)/315 - 8*x2/231 + 16*x3/1287 - 4*x4/1287; + elseif i == 4 + D(approx,4) = -16*x2/3003 + 64*x3/19305 - 8*x4/7293; + elseif i == 5 + D(approx,5) = 128*x3/328185 - 32*x4/138567; + elseif i == 6 + D(approx,6) = -64*x4/2909907 + 128*x5/10140585; + elseif i == 7 + D(approx,7) = 256*x5/253514625; + end +end + diff --git a/NODDI_toolbox_v1.01/models/watson/NODDI_erfi.m b/NODDI_toolbox_v1.01/models/watson/NODDI_erfi.m new file mode 100644 index 0000000..8db27db --- /dev/null +++ b/NODDI_toolbox_v1.01/models/watson/NODDI_erfi.m @@ -0,0 +1,21 @@ +function ans=NODDI_erfi(x) +% %erfi(x). The Imaginary error function, as it is defined in Mathematica +% %erfi(z)==erf(iz)/i (z could be complex) using +% %the incomplete gamma function in matlab: gammainc +% %Using "@": erfi = @(x) real(-sqrt(-1).*sign(x).*gammainc(-x.^2,1/2)) +% %Note: limit(x->0) erfi(x)/x -> 2/sqrt(pi) +% +% %Example 1: +% x=linspace(0.001,6,100); +% y=exp(-x.^2).*erfi(x)./2./x; +% figure(1), clf;plot(x,y*sqrt(pi)) +% +% %Example 2: +% [x,y]=meshgrid(linspace(-3,3,180),linspace(-3,3,180)); +% z=x+i*y; +% figure(1), clf;contourf(x,y,log(erfi(z))) +% axis equal;axis off +xc=5.7;%cut for asymptotic approximation (when x is real) +ans=~isreal(x).*(-(sqrt(-x.^2)./(x+isreal(x))).*gammainc(-x.^2,1/2))+... + isreal(x).*real(-sqrt(-1).*sign(x).*((x<xc).*gammainc(-x.^2,1/2))+... + (x>=xc).*exp(x.^2)./x/sqrt(pi)); diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonHinderedDiffusion_PGSE.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonHinderedDiffusion_PGSE.m new file mode 100644 index 0000000..3852935 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonHinderedDiffusion_PGSE.m @@ -0,0 +1,56 @@ +function [E,J]=SynthMeasWatsonHinderedDiffusion_PGSE(x, grad_dirs, G, delta, smalldel, fibredir) +% Substrate: Anisotropic hindered diffusion compartment +% Orientation distribution: Watson's distribution +% Pulse sequence: Pulsed gradient spin echo +% Signal approximation: N/A +% +% [E,J]=SynthMeasWatsonHinderedDiffusion_PGSE(x, grad_dirs, G, delta, smalldel, fibredir) +% returns the measurements E according to the model and the Jacobian J of the +% measurements with respect to the parameters. The Jacobian does not +% include derivates with respect to the fibre direction. +% +% x is the list of model parameters in SI units: +% x(1) is the free diffusivity of the material inside and outside the cylinders. +% x(2) is the hindered diffusivity outside the cylinders in perpendicular directions. +% x(3) is the concentration parameter of the Watson's distribution +% +% grad_dirs is the gradient direction for each measurement. It has size [N +% 3] where N is the number of measurements. +% +% G, delta and smalldel are the gradient strength, pulse separation and +% pulse length of each measurement in the protocol. Each has +% size [N 1]. +% +% fibredir is a unit vector along the symmetry axis of the Watson's +% distribution. It must be in Cartesian coordinates [x y z]' with size [3 1]. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +dPar = x(1); +dPerp = x(2); +kappa = x(3); + +% get the equivalent diffusivities +if (nargout == 1) + dw = WatsonHinderedDiffusionCoeff(dPar, dPerp, kappa); +else + [dw, Jdw] = WatsonHinderedDiffusionCoeff(dPar, dPerp, kappa); +end + +xh = [dw(1) dw(2)]; +if (nargout == 1) + E = SynthMeasHinderedDiffusion_PGSE(xh, grad_dirs, G, delta, smalldel, fibredir); +else + [E, Jh] = SynthMeasHinderedDiffusion_PGSE(xh, grad_dirs, G, delta, smalldel, fibredir); +end + +% Compute the Jacobian matrix +if(nargout>1) + % Construct the jacobian matrix. + J = zeros(size(E, 1), 3); + J(:,1) = Jh(:,1)*Jdw(1,1) + Jh(:,2)*Jdw(2,1); + J(:,2) = Jh(:,1)*Jdw(1,2) + Jh(:,2)*Jdw(2,2); + J(:,3) = Jh(:,1)*Jdw(1,3) + Jh(:,2)*Jdw(2,3); +end + diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylNeuman_PGSE.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylNeuman_PGSE.m new file mode 100644 index 0000000..93838bb --- /dev/null +++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylNeuman_PGSE.m @@ -0,0 +1,138 @@ +function [E,J]=SynthMeasWatsonSHCylNeuman_PGSE(x, grad_dirs, G, delta, smalldel, fibredir, roots) +% Substrate: Impermeable cylinders with one radius in an empty background. +% Orientation distribution: Watson's distribution with SH approximation +% Pulse sequence: Pulsed gradient spin echo +% Signal approximation: Gaussian phase distribution. +% +% [E,J]=SynthMeasWatsonSHCylNeuman_PGSE(x, grad_dirs, G, delta, smalldel, fibredir, roots) +% returns the measurements E according to the model and the Jacobian J of the +% measurements with respect to the parameters. The Jacobian does not +% include derivates with respect to the fibre direction. +% +% x is the list of model parameters in SI units: +% x(1) is the diffusivity of the material inside the cylinders. +% x(2) is the radius of the cylinders. +% x(3) is the concentration parameter of the Watson's distribution +% +% grad_dirs is the gradient direction for each measurement. It has size [N +% 3] where N is the number of measurements. +% +% G, delta and smalldel are the gradient strength, pulse separation and +% pulse length of each measurement in the protocol. Each has +% size [N 1]. +% +% fibredir is a unit vector along the symmetry axis of the Watson's +% distribution. It must be in Cartesian coordinates [x y z]' with size [3 1]. +% +% roots contains solutions to the Bessel function equation from function +% BesselJ_RootsCyl. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +if length(x) ~= 3 + error('the first argument should have exactly three parameters'); +end + +d=x(1); +R=x(2); +kappa=x(3); + +l_q = size(grad_dirs,1); + +% Parallel component +if nargout > 1 + [LePar, J_LePar] = CylNeumanLePar_PGSE(d, G, delta, smalldel); +else + LePar = CylNeumanLePar_PGSE(d, G, delta, smalldel); +end + +% Perpendicular component +if nargout > 1 + [LePerp, J_LePerp] = CylNeumanLePerp_PGSE(d, R, G, delta, smalldel, roots); +else + LePerp = CylNeumanLePerp_PGSE(d, R, G, delta, smalldel, roots); +end +ePerp = exp(LePerp); + +% Compute the Legendre weighted signal +Lpmp = LePerp - LePar; +if nargout > 1 + [lgi, J_lgi] = LegendreGaussianIntegral(Lpmp, 6); +else + lgi = LegendreGaussianIntegral(Lpmp, 6); +end + +% Compute the spherical harmonic coefficients of the Watson's distribution +if nargout > 1 + [coeff, J_coeff] = WatsonSHCoeff(kappa); +else + coeff = WatsonSHCoeff(kappa); +end +coeffMatrix = repmat(coeff, [l_q, 1]); + +% Compute the dot product between the symmetry axis of the Watson's distribution +% and the gradient direction +% +% For numerical reasons, cosTheta might not always be between -1 and 1 +% Due to round off errors, individual gradient vectors in grad_dirs and the +% fibredir are never exactly normal. When a gradient vector and fibredir are +% essentially parallel, their dot product can fall outside of -1 and 1. +% +% BUT we need make sure it does, otherwise the legendre function call below +% will FAIL and abort the calculation!!! +% +cosTheta = grad_dirs*fibredir; +badCosTheta = find(abs(cosTheta)>1); +cosTheta(badCosTheta) = cosTheta(badCosTheta)./abs(cosTheta(badCosTheta)); + +% Compute the SH values at cosTheta +sh = zeros(size(coeff)); +shMatrix = repmat(sh, [l_q, 1]); +for i = 1:7 + shMatrix(:,i) = sqrt((i - .75)/pi); + % legendre function returns coefficients of all m from 0 to l + % we only need the coefficient corresponding to m = 0 + % WARNING: make sure to input ROW vector as variables!!! + % cosTheta is expected to be a COLUMN vector. + tmp = legendre(2*i - 2, cosTheta'); + tmp = tmp'; + shMatrix(:,i) = shMatrix(:,i) .* tmp(:,1); +end + +E = sum(lgi.*coeffMatrix.*shMatrix, 2); +% with the SH approximation, there will be no guarantee that E will be positive +% but we need to make sure it does!!! replace the negative values with 10% of +% the smallest positive values +E(find(E<=0)) = min(E(find(E>0)))*0.1; +E = 0.5*E.*ePerp; + +% Compute the Jacobian matrix +if(nargout>1) + % dePerp/dd + dePerpdd = E.*J_LePerp(1); + % dePar/dd + dElgi = sum(J_lgi.*coeffMatrix.*shMatrix, 2); + dePardd = 0.5*dElgi.*(J_LePerp(:,:,1) - J_LePar).*ePerp; + % dE/dd + dEdd = dePardd + dePerpdd; + + % dePerp/dR + dePerpdR = E.*J_LePerp(2); + % dePar/dR + dePardR = 0.5*dElgi.*J_LePerp(:,:,2).*ePerp; + % dE/dR + dEdR = dePardR + dePerpdR; + + % dE/dK + J_coeffMatrix = repmat(J_coeff, [l_q, 1]); + dEdk = sum(lgi.*J_coeffMatrix.*shMatrix,2); + dEdk = 0.5*dEdk.*ePerp; + + % Construct the jacobian matrix. + J = zeros(length(E), 3); + J(:,1) = dEdd; + J(:,2) = dEdR; + J(:,3) = dEdk; +end + diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadGPD.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadGPD.m new file mode 100644 index 0000000..5dc387d --- /dev/null +++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadGPD.m @@ -0,0 +1,45 @@ +function [E,J]=SynthMeasWatsonSHCylSingleRadGPD(x, protocol, fibredir, roots) +% Substrate: Impermeable cylinders with one radius in a homogeneous background. +% Orientation distribution: Watson's distribution with SH approximation +% Pulse sequence: Any +% Signal approximation: Gaussian phase distribution. +% +% [E,J]=SynthMeasWatsonSHCylSingleRadGPD(x, protocol, fibredir, roots) +% returns the measurements E according to the model and the Jacobian J of the +% measurements with respect to the parameters. The Jacobian does not +% include derivates with respect to the fibre direction. +% +% x is the list of model parameters in SI units: +% x(1) is the volume fraction of the intracellular space. +% x(2) is the free diffusivity of the material inside and outside the cylinders. +% x(3) is the hindered diffusivity outside the cylinders in perpendicular directions. +% x(4) is the radius of the cylinders. +% x(5) is the concentration parameter of the Watson's distribution +% +% protocol is the object containing the acquisition protocol. +% +% fibredir is a unit vector along the symmetry axis of the Watson's +% distribution. It must be in Cartesian coordinates [x y z]' with size [3 1]. +% +% roots contains solutions to the Bessel function equation from function +% BesselJ_RootsCyl. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +if(strcmp(protocol.pulseseq, 'PGSE') || strcmp(protocol.pulseseq, 'STEAM')) + if(nargout == 1) + [E] = SynthMeasWatsonSHCylSingleRadGPD_PGSE(x, protocol.grad_dirs, protocol.G', protocol.delta', protocol.smalldel', fibredir, roots); + else + [E J] = SynthMeasWatsonSHCylSingleRadGPD_PGSE(x, protocol.grad_dirs, protocol.G', protocol.delta', protocol.smalldel', fibredir, roots); + end +elseif(strcmp(protocol.pulseseq, 'DSE')) + if(nargout == 1) + [E] = SynthMeasWatsonSHCylSingleRadGPD_DSE(x, protocol.grad_dirs, protocol.G', protocol.TE, protocol.delta1', protocol.delta2', protocol.delta3', protocol.t1', protocol.t2', protocol.t3', fibredir, roots); + else + [E J] = SynthMeasWatsonSHCylSingleRadGPD_DSE(x, protocol.grad_dirs, protocol.G', protocol.TE, protocol.delta1', protocol.delta2', protocol.delta3', protocol.t1', protocol.t2', protocol.t3', fibredir, roots); + end +else + error(['Unknown pulse sequence: ' protocol.pulseseq]); +end + diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadGPD_PGSE.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadGPD_PGSE.m new file mode 100644 index 0000000..8d57d73 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadGPD_PGSE.m @@ -0,0 +1,90 @@ +function [E,J]=SynthMeasWatsonSHCylSingleRadGPD_PGSE(x, grad_dirs, G, delta, smalldel, fibredir, roots) +% Substrate: Impermeable cylinders with one radius in a homogeneous background. +% Orientation distribution: Watson's distribution with SH approximation +% Pulse sequence: Pulsed gradient spin echo +% Signal approximation: Gaussian phase distribution. +% +% [E,J]=SynthMeasWatsonSHCylSingleRadGPD_PGSE(x, grad_dirs, G, delta, smalldel, fibredir, roots) +% returns the measurements E according to the model and the Jacobian J of the +% measurements with respect to the parameters. The Jacobian does not +% include derivates with respect to the fibre direction. +% +% x is the list of model parameters in SI units: +% x(1) is the volume fraction of the intracellular space. +% x(2) is the free diffusivity of the material inside and outside the cylinders. +% x(3) is the hindered diffusivity outside the cylinders in perpendicular directions. +% x(4) is the radius of the cylinders. +% x(5) is the concentration parameter of the Watson's distribution +% +% grad_dirs is the gradient direction for each measurement. It has size [N +% 3] where N is the number of measurements. +% +% G, delta and smalldel are the gradient strength, pulse separation and +% pulse length of each measurement in the protocol. Each has +% size [N 1]. +% +% fibredir is a unit vector along the symmetry axis of the Watson's +% distribution. It must be in Cartesian coordinates [x y z]' with size [3 1]. +% +% roots contains solutions to the Bessel function equation from function +% BesselJ_RootsCyl. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + + +% Duplication with SynthMeasDistributedRadVG remains, because of the +% derivative computation. + +f=x(1); +dPar=x(2); +dPerp=x(3); +R=x(4); +kappa=x(5); + +% build the input x vector for hindered compartment +x_h = [dPar dPerp kappa]; + +% build the input x vector for restricted diffusion in Neuman cylinder model +% set diffusion coeff in restricted compartment same as parallel one in +% hindered. +x_r = [dPar R kappa]; + +% Synthesize measurements from model +if (nargout>1) + [E_h, J_h] = SynthMeasWatsonHinderedDiffusion_PGSE(x_h, grad_dirs, G, delta, smalldel, fibredir); + [E_r, J_r] = SynthMeasWatsonSHCylNeuman_PGSE(x_r, grad_dirs, G, delta, smalldel, fibredir, roots); +else + E_h = SynthMeasWatsonHinderedDiffusion_PGSE(x_h, grad_dirs, G, delta, smalldel, fibredir); + E_r = SynthMeasWatsonSHCylNeuman_PGSE(x_r, grad_dirs, G, delta, smalldel, fibredir, roots); +end + +E=(1-f)*E_h+f*E_r; + +% Compute the Jacobian matrix +if(nargout>1) + + % dE_tot/df = E_r - E_h + dEtdf = E_r - E_h; + + % dE_tot/ddPar + dEtddPar = (1-f)*J_h(:,1) + f*J_r(:,1); + + % dE_tot/ddPerp + dEtddPerp = (1-f)*J_h(:,2); + + % dE_tot/dR + dEtdr = f*J_r(:,2); + + % dE_tot/dk + dEtdk = (1-f)*J_h(:,3) + f*J_r(:,3); + + % Construct the jacobian matrix. + J = zeros(length(E), 5); + J(:,1) = dEtdf; + J(:,2) = dEtddPar; + J(:,3) = dEtddPerp; + J(:,4) = dEtdr; + J(:,5) = dEtdk; +end + diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD.m new file mode 100644 index 0000000..da5be9f --- /dev/null +++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD.m @@ -0,0 +1,54 @@ +function [E,J]=SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD(x, protocol, fibredir, roots) +% Substrate: Impermeable cylinders with one radius in a homogeneous background. +% Orientation distribution: Watson's distribution with SH approximation +% Signal approximation: Gaussian phase distribution. +% Notes: This version includes an isotropic diffusion compartment with its own +% diffusivity. +% This version includes a stationary water compartment. +% +% [E,J]=SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD(x, protocol, fibredir, roots) +% returns the measurements E according to the model and the Jacobian J of the +% measurements with respect to the parameters. The Jacobian does not +% include derivates with respect to the fibre direction. +% +% x is the list of model parameters in SI units: +% x(1) is the volume fraction of the intracellular space. +% x(2) is the free diffusivity of the material inside and outside the cylinders. +% x(3) is the hindered diffusivity outside the cylinders in perpendicular directions. +% x(4) is the radius of the cylinders. +% x(5) is the concentration parameter of the Watson's distribution. +% x(6) is the volume fraction of the isotropic compartment. +% x(7) is the diffusivity of the isotropic compartment. +% x(8) is the volume fraction of the isotropic restriction. +% +% protocol is the object containing the acquisition protocol. +% +% fibredir is a unit vector along the symmetry axis of the Watson's +% distribution. It must be in Cartesian coordinates [x y z]' with size [3 1]. +% +% roots contains solutions to the Bessel function equation from function +% BesselJ_RootsCyl. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +irFrac = x(8); + +% Call the model w/o the isotropic restriction +if(nargout == 1) + Ewo=SynthMeasWatsonSHCylSingleRadIsoV_GPD(x, protocol, fibredir, roots); +else + [Ewo,Jwo]=SynthMeasWatsonSHCylSingleRadIsoV_GPD(x, protocol, fibredir, roots); +end + +E = (1-irFrac)*Ewo + irFrac*1.0; + +if(nargout>1) + + % Update the component w/o isotropic restriction. + J = Jwo*(1-irFrac); + + % Add derivatives wrt isotropic restriction. + J(:,8) = 1.0 - Ewo; +end + diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD_B0.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD_B0.m new file mode 100644 index 0000000..846e883 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD_B0.m @@ -0,0 +1,52 @@ +function [E,J]=SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD_B0(x, protocol, fibredir, roots) +% Substrate: Impermeable cylinders with one radius in a homogeneous background. +% Orientation distribution: Watson's distribution with SH approximation +% Signal approximation: Gaussian phase distribution. +% Notes: This version includes an isotropic diffusion compartment with its own +% diffusivity. +% This version includes a stationary water compartment. +% Includes a free parameter for the measurement at b=0. +% +% [E,J]=SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD_B0(x, protocol, fibredir, roots) +% returns the measurements E according to the model and the Jacobian J of the +% measurements with respect to the parameters. The Jacobian does not +% include derivates with respect to the fibre direction. +% +% x is the list of model parameters in SI units: +% x(1) is the volume fraction of the intracellular space. +% x(2) is the free diffusivity of the material inside and outside the cylinders. +% x(3) is the hindered diffusivity outside the cylinders in perpendicular directions. +% x(4) is the radius of the cylinders. +% x(5) is the concentration parameter of the Watson's distribution. +% x(6) is the volume fraction of the isotropic compartment. +% x(7) is the diffusivity of the isotropic compartment. +% x(8) is the volume fraction of the isotropic restriction. +% x(9) is the measurement at b=0. +% +% protocol is the object containing the acquisition protocol. +% +% fibredir is a unit vector along the symmetry axis of the Watson's +% distribution. It must be in Cartesian coordinates [x y z]' with size [3 1]. +% +% roots contains solutions to the Bessel function equation from function +% BesselJ_RootsCyl. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +S0 = x(9); + +% Call the other function to get normalized measurements. +if(nargout == 1) + Enorm=SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD(x, protocol, fibredir, roots); +else + [Enorm,Jnorm]=SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD(x, protocol, fibredir, roots); +end + +E = Enorm*S0; + +if(nargout>1) + J = Jnorm*S0; + J(:,9) = Enorm; +end + diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoV_GPD.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoV_GPD.m new file mode 100644 index 0000000..5799d60 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoV_GPD.m @@ -0,0 +1,58 @@ +function [E,J]=SynthMeasWatsonSHCylSingleRadIsoV_GPD(x, protocol, fibredir, roots) +% Substrate: Impermeable cylinders with one radius in a homogeneous background. +% Orientation distribution: Watson's distribution with SH approximation +% Signal approximation: Gaussian phase distribution. +% Notes: This version includes an isotropic diffusion compartment with its own +% diffusivity. +% +% [E,J]=SynthMeasWatsonSHCylSingleRadIsoV_GPD(x, protocol, fibredir, roots) +% returns the measurements E according to the model and the Jacobian J of the +% measurements with respect to the parameters. The Jacobian does not +% include derivates with respect to the fibre direction. +% +% x is the list of model parameters in SI units: +% x(1) is the volume fraction of the intracellular space. +% x(2) is the free diffusivity of the material inside and outside the cylinders. +% x(3) is the hindered diffusivity outside the cylinders in perpendicular directions. +% x(4) is the radius of the cylinders. +% x(5) is the concentration parameter of the Watson's distribution. +% x(6) is the volume fraction of the isotropic compartment. +% x(7) is the diffusivity of the isotropic compartment. +% +% protocol is the object containing the acquisition protocol. +% +% fibredir is a unit vector along the symmetry axis of the Watson's +% distribution. It must be in Cartesian coordinates [x y z]' with size [3 1]. +% +% roots contains solutions to the Bessel function equation from function +% BesselJ_RootsCyl. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +fiso = x(6); +dIso = x(7); + +% Call the model with no isotropic component to get the anisotropic component. +if(nargout == 1) + Eaniso=SynthMeasWatsonSHCylSingleRadGPD(x, protocol, fibredir, roots); + Eiso = SynthMeasIsoGPD(dIso, protocol); +else + [Eaniso,Janiso]=SynthMeasWatsonSHCylSingleRadGPD(x, protocol, fibredir, roots); + [Eiso, Jiso] = SynthMeasIsoGPD(dIso, protocol); +end + +E = (1-fiso)*Eaniso + fiso*Eiso; + +if(nargout>1) + + % Update with anisotropic component. + J = Janiso*(1-fiso); + + % Add derivatives wrt isotropic fraction. + J(:,6) = Eiso - Eaniso; + + % Add entry for dIso + J(:,7) = fiso*Jiso; +end + diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoV_GPD_B0.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoV_GPD_B0.m new file mode 100644 index 0000000..c4d19cc --- /dev/null +++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadIsoV_GPD_B0.m @@ -0,0 +1,51 @@ +function [E,J]=SynthMeasWatsonSHCylSingleRadIsoV_GPD_B0(x, protocol, fibredir, roots) +% Substrate: Impermeable cylinders with one radius in a homogeneous background. +% Orientation distribution: Watson's distribution with SH approximation +% Signal approximation: Gaussian phase distribution. +% Notes: This version includes an isotropic diffusion compartment with its own +% diffusivity. +% Includes a free parameter for the measurement at b=0. +% +% [E,J]=SynthMeasWatsonSHCylSingleRadIsoV_GPD_B0(x, protocol, fibredir, roots) +% returns the measurements E according to the model and the Jacobian J of the +% measurements with respect to the parameters. The Jacobian does not +% include derivates with respect to the fibre direction. +% +% x is the list of model parameters in SI units: +% x(1) is the volume fraction of the intracellular space. +% x(2) is the free diffusivity of the material inside and outside the cylinders. +% x(3) is the hindered diffusivity outside the cylinders in perpendicular directions. +% x(4) is the radius of the cylinders. +% x(5) is the concentration parameter of the Watson's distribution. +% x(6) is the volume fraction of the isotropic compartment. +% x(7) is the diffusivity of the isotropic compartment. +% x(8) is the measurement at b=0. +% +% protocol is the object containing the acquisition protocol. +% +% fibredir is a unit vector along the symmetry axis of the Watson's +% distribution. It must be in Cartesian coordinates [x y z]' with size [3 1]. +% +% roots contains solutions to the Bessel function equation from function +% BesselJ_RootsCyl. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +S0 = x(8); + +% Call the other function to get normalized measurements. +if(nargout == 1) + Enorm=SynthMeasWatsonSHCylSingleRadIsoV_GPD(x, protocol, fibredir, roots); +else + [Enorm,Jnorm]=SynthMeasWatsonSHCylSingleRadIsoV_GPD(x, protocol, fibredir, roots); +end + +E = Enorm*S0; + +if(nargout>1) + J = Jnorm*S0; + [meas, params] = size(J); + J(:,params+1) = Enorm; +end + diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortGPD.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortGPD.m new file mode 100644 index 0000000..5002883 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortGPD.m @@ -0,0 +1,53 @@ +function [E,J]=SynthMeasWatsonSHCylSingleRadTortGPD(x, protocol, fibredir, roots) +% Substrate: Impermeable cylinders with one radius in a homogeneous background. +% Orientation distribution: Watson's distribution with SH approximation +% Pulse sequence: Any +% Signal approximation: Gaussian phase distribution. +% Notes: This version estimates the hindered diffusivity from the free diffusivity +% and packing density using Szafer et al's tortuosity model for randomly +% packed cylinders. +% +% [E,J]=SynthMeasWatsonSHCylSingleRadTortGPD(x, protocol, fibredir, roots) +% returns the measurements E according to the model and the Jacobian J of the +% measurements with respect to the parameters. The Jacobian does not +% include derivates with respect to the fibre direction. +% +% x is the list of model parameters in SI units: +% x(1) is the volume fraction of the intracellular space. +% x(2) is the free diffusivity of the material inside and outside the cylinders. +% x(3) is the radius of the cylinders. +% x(4) is the concentration parameter of the Watson's distribution. +% +% protocol is the object containing the acquisition protocol. +% +% fibredir is a unit vector along the symmetry axis of the Watson's +% distribution. It must be in Cartesian coordinates [x y z]' with size [3 1]. +% +% roots contains solutions to the Bessel function equation from function +% BesselJ_RootsCyl. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + + +f=x(1); +dPar=x(2); +% This version is for cylinders with regular packing. +%dPerp = dPar/((1 + f^(3/2))^2); +% This one is for randomly packed cylinders +dPerp = dPar*(1-f); +R=[x(3)]; +kappa=x(4); + +x_full = [f dPar dPerp R kappa]; + +% Call the model with no isotropic component to get the anisotropic component. +if(nargout == 1) + E=SynthMeasWatsonSHCylSingleRadGPD(x_full, protocol, fibredir, roots); +else + [E,J_full]=SynthMeasWatsonSHCylSingleRadGPD(x_full, protocol, fibredir, roots); + J(:,1) = J_full(:,1) - J_full(:,3)*dPar; + J(:,2) = J_full(:,2) + J_full(:,3)*(1-f); + J(:,3) = J_full(:,4); + J(:,4) = J_full(:,5); +end diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD.m new file mode 100644 index 0000000..a42e129 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD.m @@ -0,0 +1,56 @@ +function [E,J]=SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD(x, protocol, fibredir, roots) +% Substrate: Impermeable cylinders with one radius in a homogeneous background. +% Orientation distribution: Watson's distribution with SH approximation +% Signal approximation: Gaussian phase distribution. +% Notes: This version estimates the hindered diffusivity from the free diffusivity +% and packing density using Szafer et al's tortuosity model for randomly +% packed cylinders. +% This version includes an isotropic diffusion compartment with its own +% diffusivity. +% This version includes a stationary water compartment. +% +% [E,J]=SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD(x, protocol, fibredir, roots) +% returns the measurements E according to the model and the Jacobian J of the +% measurements with respect to the parameters. The Jacobian does not +% include derivates with respect to the fibre direction. +% +% x is the list of model parameters in SI units: +% x(1) is the volume fraction of the intracellular space. +% x(2) is the free diffusivity of the material inside and outside the cylinders. +% x(3) is the radius of the cylinders. +% x(4) is the concentration parameter of the Watson's distribution. +% x(5) is the volume fraction of the isotropic compartment. +% x(6) is the diffusivity of the isotropic compartment. +% x(7) is the volume fraction of the isotropic restriction. +% +% protocol is the object containing the acquisition protocol. +% +% fibredir is a unit vector along the symmetry axis of the Watson's +% distribution. It must be in Cartesian coordinates [x y z]' with size [3 1]. +% +% roots contains solutions to the Bessel function equation from function +% BesselJ_RootsCyl. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +irFrac = x(7); + +% Call the model w/o the isotropic restriction. +if(nargout == 1) + Ewo=SynthMeasWatsonSHCylSingleRadTortIsoV_GPD(x, protocol, fibredir, roots); +else + [Ewo,Jwo]=SynthMeasWatsonSHCylSingleRadTortIsoV_GPD(x, protocol, fibredir, roots); +end + +E = (1-irFrac)*Ewo + irFrac*1.0; + +if(nargout>1) + + % Update the component w/o isotropic restriction. + J = Jwo*(1-irFrac); + + % Add derivatives wrt isotropic restriction. + J(:,7) = 1.0 - Ewo; +end + diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD_B0.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD_B0.m new file mode 100644 index 0000000..8f2c15c --- /dev/null +++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD_B0.m @@ -0,0 +1,54 @@ +function [E,J]=SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD_B0(x, protocol, fibredir, roots) +% Substrate: Impermeable cylinders with one radius in a homogeneous background. +% Orientation distribution: Watson's distribution with SH approximation +% Signal approximation: Gaussian phase distribution. +% Notes: This version estimates the hindered diffusivity from the free diffusivity +% and packing density using Szafer et al's tortuosity model for randomly +% packed cylinders. +% This version includes an isotropic diffusion compartment with its own +% diffusivity. +% This version includes a stationary water compartment. +% Includes a free parameter for the measurement at b=0. +% +% [E,J]=SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD_B0(x, protocol, fibredir, roots) +% returns the measurements E according to the model and the Jacobian J of the +% measurements with respect to the parameters. The Jacobian does not +% include derivates with respect to the fibre direction. +% +% x is the list of model parameters in SI units: +% x(1) is the volume fraction of the intracellular space. +% x(2) is the free diffusivity of the material inside and outside the cylinders. +% x(3) is the radius of the cylinders. +% x(4) is the concentration parameter of the Watson's distribution. +% x(5) is the volume fraction of the isotropic compartment. +% x(6) is the diffusivity of the isotropic compartment. +% x(7) is the volume fraction of the isotropic restriction. +% x(8) is the measurement at b=0. +% +% protocol is the object containing the acquisition protocol. +% +% fibredir is a unit vector along the symmetry axis of the Watson's +% distribution. It must be in Cartesian coordinates [x y z]' with size [3 1]. +% +% roots contains solutions to the Bessel function equation from function +% BesselJ_RootsCyl. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +S0 = x(8); + +% Call the other function to get normalized measurements. +if(nargout == 1) + Enorm=SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD(x, protocol, fibredir, roots); +else + [Enorm,Jnorm]=SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD(x, protocol, fibredir, roots); +end + +E = Enorm*S0; + +if(nargout>1) + J = Jnorm*S0; + J(:,8) = Enorm; +end + diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoV_GPD.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoV_GPD.m new file mode 100644 index 0000000..b935e4f --- /dev/null +++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoV_GPD.m @@ -0,0 +1,60 @@ +function [E,J]=SynthMeasWatsonSHCylSingleRadTortIsoV_GPD(x, protocol, fibredir, roots) +% Substrate: Impermeable cylinders with one radius in a homogeneous background. +% Orientation distribution: Watson's distribution with SH approximation +% Signal approximation: Gaussian phase distribution. +% Notes: This version estimates the hindered diffusivity from the free diffusivity +% and packing density using Szafer et al's tortuosity model for randomly +% packed cylinders. +% This version includes an isotropic diffusion compartment with its own +% diffusivity. +% +% [E,J]=SynthMeasWatsonSHCylSingleRadTortIsoV_GPD(x, protocol, fibredir, roots) +% returns the measurements E according to the model and the Jacobian J of the +% measurements with respect to the parameters. The Jacobian does not +% include derivates with respect to the fibre direction. +% +% x is the list of model parameters in SI units: +% x(1) is the volume fraction of the intracellular space. +% x(2) is the free diffusivity of the material inside and outside the cylinders. +% x(3) is the radius of the cylinders. +% x(4) is the concentration parameter of the Watson's distribution. +% x(5) is the volume fraction of the isotropic compartment. +% x(6) is the diffusivity of the isotropic compartment. +% +% protocol is the object containing the acquisition protocol. +% +% fibredir is a unit vector along the symmetry axis of the Watson's +% distribution. It must be in Cartesian coordinates [x y z]' with size [3 1]. +% +% roots contains solutions to the Bessel function equation from function +% BesselJ_RootsCyl. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + + +fiso = x(5); +dIso = x(6); + +% Call the model with no isotropic component to get the anisotropic component. +if(nargout == 1) + Eaniso=SynthMeasWatsonSHCylSingleRadTortGPD(x, protocol, fibredir, roots); + Eiso = SynthMeasIsoGPD(dIso, protocol); +else + [Eaniso,Janiso]=SynthMeasWatsonSHCylSingleRadTortGPD(x, protocol, fibredir, roots); + [Eiso, Jiso] = SynthMeasIsoGPD(dIso, protocol); +end + +E = (1-fiso)*Eaniso + fiso*Eiso; + +if(nargout>1) + + % Update with anisotropic component. + J = Janiso*(1-fiso); + + % Add derivatives wrt isotropic fraction. + J(:,5) = Eiso - Eaniso; + + % Add entry for dIso + J(:,6) = fiso*Jiso; +end diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoV_GPD_B0.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoV_GPD_B0.m new file mode 100644 index 0000000..2a287ef --- /dev/null +++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHCylSingleRadTortIsoV_GPD_B0.m @@ -0,0 +1,53 @@ +function [E,J]=SynthMeasWatsonSHCylSingleRadTortIsoV_GPD_B0(x, protocol, fibredir, roots) +% Substrate: Impermeable cylinders with one radius in a homogeneous background. +% Orientation distribution: Watson's distribution with SH approximation +% Signal approximation: Gaussian phase distribution. +% Notes: This version estimates the hindered diffusivity from the free diffusivity +% and packing density using Szafer et al's tortuosity model for randomly +% packed cylinders. +% This version includes an isotropic diffusion compartment with its own +% diffusivity. +% Includes a free parameter for the measurement at b=0. +% +% [E,J]=SynthMeasWatsonSHCylSingleRadTortIsoV_GPD_B0(x, protocol, fibredir, roots) +% returns the measurements E according to the model and the Jacobian J of the +% measurements with respect to the parameters. The Jacobian does not +% include derivates with respect to the fibre direction. +% +% x is the list of model parameters in SI units: +% x(1) is the volume fraction of the intracellular space. +% x(2) is the free diffusivity of the material inside and outside the cylinders. +% x(3) is the radius of the cylinders. +% x(4) is the concentration parameter of the Watson's distribution. +% x(5) is the volume fraction of the isotropic compartment. +% x(6) is the diffusivity of the isotropic compartment. +% x(7) is the measurement at b=0. +% +% protocol is the object containing the acquisition protocol. +% +% fibredir is a unit vector along the symmetry axis of the Watson's +% distribution. It must be in Cartesian coordinates [x y z]' with size [3 1]. +% +% roots contains solutions to the Bessel function equation from function +% BesselJ_RootsCyl. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +S0 = x(7); + +% Call the other function to get normalized measurements. +if(nargout == 1) + Enorm=SynthMeasWatsonSHCylSingleRadTortIsoV_GPD(x, protocol, fibredir, roots); +else + [Enorm,Jnorm]=SynthMeasWatsonSHCylSingleRadTortIsoV_GPD(x, protocol, fibredir, roots); +end + +E = Enorm*S0; + +if(nargout>1) + J = Jnorm*S0; + [meas, params] = size(J); + J(:,params+1) = Enorm; +end + diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickIsoVIsoDot_B0.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickIsoVIsoDot_B0.m new file mode 100644 index 0000000..ce1b0d1 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickIsoVIsoDot_B0.m @@ -0,0 +1,52 @@ +function [E,J]=SynthMeasWatsonSHStickIsoVIsoDot_B0(x, protocol, fibredir) +% Substrate: Impermeable sticks (cylinders with zero radius) in a homogeneous +% background. +% Orientation distribution: Watson's distribution with SH approximation +% Signal approximation: Not applicable +% This version includes an isotropic diffusion compartment with its own +% diffusivity. +% This version includes a stationary water compartment. +% Includes a free parameter for the measurement at b=0. +% +% [E,J]=SynthMeasWatsonSHStickTortIsoV_B0(x, protocol, fibredir) +% returns the measurements E according to the model and the Jacobian J of the +% measurements with respect to the parameters. The Jacobian does not +% include derivates with respect to the fibre direction. +% +% x is the list of model parameters in SI units: +% x(1) is the volume fraction of the intracellular space. +% x(2) is the free diffusivity of the material inside and outside the cylinders. +% x(3) is the hindered diffusivity outside the cylinders in perpendicular directions. +% x(4) is the concentration parameter of the Watson's distribution. +% x(5) is the volume fraction of the isotropic compartment. +% x(6) is the diffusivity of the isotropic compartment. +% x(7) is the volume fraction of the isotropic restriction. +% x(8) is the measurement at b=0. +% +% protocol is the object containing the acquisition protocol. +% +% fibredir is a unit vector along the symmetry axis of the Watson's +% distribution. It must be in Cartesian coordinates [x y z]' with size [3 1]. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +xcyl=[x(1) x(2) x(3) 0 x(4) x(5) x(6) x(7) x(8)]; + +if(nargout == 1) + E=SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD_B0(xcyl, protocol, fibredir, 0); +else + [E,Jcyl]=SynthMeasWatsonSHCylSingleRadIsoVIsoDot_GPD_B0(xcyl, protocol, fibredir, 0); +end + +if(nargout>1) + J(:,1) = Jcyl(:,1); + J(:,2) = Jcyl(:,2); + J(:,3) = Jcyl(:,3); + J(:,4) = Jcyl(:,5); + J(:,5) = Jcyl(:,6); + J(:,6) = Jcyl(:,7); + J(:,7) = Jcyl(:,8); + J(:,8) = Jcyl(:,9); +end + diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickIsoV_B0.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickIsoV_B0.m new file mode 100644 index 0000000..7a62870 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickIsoV_B0.m @@ -0,0 +1,49 @@ +function [E,J]=SynthMeasWatsonSHStickIsoV_B0(x, protocol, fibredir) +% Substrate: Impermeable sticks (cylinders with zero radius) in a homogeneous +% background. +% Orientation distribution: Watson's distribution with SH approximation +% Pulse sequence: Any +% Signal approximation: Not applicable +% Notes: This version includes an isotropic diffusion compartment with its own +% Includes a free parameter for the measurement at b=0. +% +% [E,J]=SynthMeasWatsonSHStickIsoV_B0(x, protocol, fibredir) +% returns the measurements E according to the model and the Jacobian J of the +% measurements with respect to the parameters. The Jacobian does not +% include derivates with respect to the fibre direction. +% +% x is the list of model parameters in SI units: +% x(1) is the volume fraction of the intracellular space. +% x(2) is the free diffusivity of the material inside and outside the cylinders. +% x(3) is the hindered diffusivity outside the cylinders in perpendicular directions. +% x(4) is the concentration parameter of the Watson's distribution. +% x(5) is the volume fraction of the isotropic compartment. +% x(6) is the diffusivity of the isotropic compartment. +% x(7) is the measurement at b=0. +% +% protocol is the object containing the acquisition protocol. +% +% fibredir is a unit vector along the symmetry axis of the Watson's +% distribution. It must be in Cartesian coordinates [x y z]' with size [3 1]. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +xcyl=[x(1) x(2) x(3) 0 x(4) x(5) x(6) x(7)]; + +if(nargout == 1) + [E] = SynthMeasWatsonSHCylSingleRadIsoV_GPD_B0(xcyl, protocol, fibredir, 0); +else + [E Jcyl] = SynthMeasWatsonSHCylSingleRadIsoV_GPD_B0(xcyl, protocol, fibredir, 0); +end + +if (nargout == 2) + J(:,1) = Jcyl(:,1); + J(:,2) = Jcyl(:,2); + J(:,3) = Jcyl(:,3); + J(:,4) = Jcyl(:,5); + J(:,5) = Jcyl(:,6); + J(:,6) = Jcyl(:,7); + J(:,7) = Jcyl(:,8); +end + diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickTortIsoVIsoDot_B0.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickTortIsoVIsoDot_B0.m new file mode 100644 index 0000000..2d00f44 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickTortIsoVIsoDot_B0.m @@ -0,0 +1,53 @@ +function [E,J]=SynthMeasWatsonSHStickTortIsoVIsoDot_B0(x, protocol, fibredir) +% Substrate: Impermeable sticks (cylinders with zero radius) in a homogeneous +% background. +% Orientation distribution: Watson's distribution with SH approximation +% Signal approximation: Not applicable +% Notes: This version estimates the hindered diffusivity from the free diffusivity +% and packing density using Szafer et al's tortuosity model for randomly +% packed cylinders. +% This version includes an isotropic diffusion compartment with its own +% diffusivity. +% This version includes a stationary water compartment. +% Includes a free parameter for the measurement at b=0. +% +% [E,J]=SynthMeasWatsonSHStickTortIsoV_B0(x, protocol, fibredir) +% returns the measurements E according to the model and the Jacobian J of the +% measurements with respect to the parameters. The Jacobian does not +% include derivates with respect to the fibre direction. +% +% x is the list of model parameters in SI units: +% x(1) is the volume fraction of the intracellular space. +% x(2) is the free diffusivity of the material inside and outside the cylinders. +% x(3) is the concentration parameter of the Watson's distribution. +% x(4) is the volume fraction of the isotropic compartment. +% x(5) is the diffusivity of the isotropic compartment. +% x(6) is the volume fraction of the isotropic restriction. +% x(7) is the measurement at b=0. +% +% protocol is the object containing the acquisition protocol. +% +% fibredir is a unit vector along the symmetry axis of the Watson's +% distribution. It must be in Cartesian coordinates [x y z]' with size [3 1]. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +xcyl=[x(1) x(2) 0 x(3) x(4) x(5) x(6) x(7)]; + +if(nargout == 1) + E=SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD_B0(xcyl, protocol, fibredir, 0); +else + [E,Jcyl]=SynthMeasWatsonSHCylSingleRadTortIsoVIsoDot_GPD_B0(xcyl, protocol, fibredir, 0); +end + +if(nargout>1) + J(:,1) = Jcyl(:,1); + J(:,2) = Jcyl(:,2); + J(:,3) = Jcyl(:,4); + J(:,4) = Jcyl(:,5); + J(:,5) = Jcyl(:,6); + J(:,6) = Jcyl(:,7); + J(:,7) = Jcyl(:,8); +end + diff --git a/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickTortIsoV_B0.m b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickTortIsoV_B0.m new file mode 100644 index 0000000..15e2b09 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/watson/SynthMeasWatsonSHStickTortIsoV_B0.m @@ -0,0 +1,49 @@ +function [E,J]=SynthMeasWatsonSHStickTortIsoV_B0(x, protocol, fibredir) +% Substrate: Impermeable sticks (cylinders with zero radius) in a homogeneous +% background. +% Orientation distribution: Watson's distribution with SH approximation +% Signal approximation: Not applicable +% Notes: This version estimates the hindered diffusivity from the free diffusivity +% and packing density using Szafer et al's tortuosity model for randomly +% packed cylinders. +% This version includes an isotropic diffusion compartment with its own +% diffusivity. +% Includes a free parameter for the measurement at b=0. +% +% [E,J]=SynthMeasWatsonSHStickTortIsoV_B0(x, protocol, fibredir) +% returns the measurements E according to the model and the Jacobian J of the +% measurements with respect to the parameters. The Jacobian does not +% include derivates with respect to the fibre direction. +% +% x is the list of model parameters in SI units: +% x(1) is the volume fraction of the intracellular space. +% x(2) is the free diffusivity of the material inside and outside the cylinders. +% x(3) is the concentration parameter of the Watson's distribution. +% x(4) is the volume fraction of the isotropic compartment. +% x(5) is the diffusivity of the isotropic compartment. +% x(6) is the measurement at b=0. +% +% protocol is the object containing the acquisition protocol. +% +% fibredir is a unit vector along the symmetry axis of the Watson's +% distribution. It must be in Cartesian coordinates [x y z]' with size [3 1]. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +xcyl=[x(1) x(2) 0 x(3) x(4) x(5) x(6)]; + +if(nargout == 1) + E=SynthMeasWatsonSHCylSingleRadTortIsoV_GPD_B0(xcyl, protocol, fibredir, 0); +else + [E,Jcyl]=SynthMeasWatsonSHCylSingleRadTortIsoV_GPD_B0(xcyl, protocol, fibredir, 0); +end + +if(nargout>1) + J(:,1) = Jcyl(:,1); + J(:,2) = Jcyl(:,2); + J(:,3) = Jcyl(:,4); + J(:,4) = Jcyl(:,5); + J(:,5) = Jcyl(:,6); + J(:,6) = Jcyl(:,7); +end diff --git a/NODDI_toolbox_v1.01/models/watson/WatsonHinderedDiffusionCoeff.m b/NODDI_toolbox_v1.01/models/watson/WatsonHinderedDiffusionCoeff.m new file mode 100644 index 0000000..aabecde --- /dev/null +++ b/NODDI_toolbox_v1.01/models/watson/WatsonHinderedDiffusionCoeff.m @@ -0,0 +1,51 @@ +function [dw, Jdw]=WatsonHinderedDiffusionCoeff(dPar, dPerp, kappa) +% Substrate: Anisotropic hindered diffusion compartment +% Orientation distribution: Watson's distribution +% +% [dw, Jdw]=WatsonHinderedDiffusionCoeff(dPar, dPerp, kappa) +% returns the equivalent parallel and perpendicular diffusion coefficients +% for hindered compartment with impermeable cylinder's oriented with a +% Watson's distribution with a cocentration parameter of kappa +% +% dPar is the free diffusivity of the material inside and outside the cylinders. +% dPerp is the hindered diffusivity outside the cylinders in perpendicular directions. +% kappa is the concentration parameter of the Watson's distribution +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +% compute the equivalent diffusion coefficient after integrating +% for all possible orientations +dw = zeros(2,1); +dParMdPerp = dPar - dPerp; + +if kappa < 1e-5 + dParP2dPerp = dPar + 2*dPerp; + k2 = kappa*kappa; + dw(1) = dParP2dPerp/3 + 4*dParMdPerp*kappa/45 + 8*dParMdPerp*k2/945; + dw(2) = dParP2dPerp/3 - 2*dParMdPerp*kappa/45 - 4*dParMdPerp*k2/945; + if (nargout==2) + Jdw(1,1) = 1/3 + 4/45*kappa + 8/945*k2; + Jdw(1,2) = 2/3 - 4/45*kappa - 8/945*k2; + Jdw(1,3) = 4/45*dParMdPerp + 16/945*dParMdPerp*kappa; + Jdw(2,1) = 1/3 - 2/45*kappa - 4/945*k2; + Jdw(2,2) = 2/3 + 2/45*kappa + 4/945*k2; + Jdw(2,3) = -2/45*dParMdPerp - 8/945*dParMdPerp*kappa; + end +else + sk = sqrt(kappa); + dawsonf = 0.5*exp(-kappa)*sqrt(pi)*NODDI_erfi(sk); + factor = sk/dawsonf; + dw(1) = (-dParMdPerp+2*dPerp*kappa+dParMdPerp*factor)/(2*kappa); + dw(2) = (dParMdPerp+2*(dPar+dPerp)*kappa-dParMdPerp*factor)/(4*kappa); + if (nargout==2) + % D[DawsonF(x),x] = 1 - 2xDawsonF(x) + dfactordk = ((1+2*kappa)*dawsonf - sk)/(2*sk*dawsonf*dawsonf); + Jdw(1,1) = (-1 + factor)/(2*kappa); + Jdw(1,2) = (1 + 2*kappa - factor)/(2*kappa); + Jdw(1,3) = (-2*dw(1) + 2*dPerp + dParMdPerp*dfactordk)/(2*kappa); + Jdw(2,1) = (1 + 2*kappa - factor)/(4*kappa); + Jdw(2,2) = (-1 + 2*kappa + factor)/(4*kappa); + Jdw(2,3) = (-4*dw(2) + 2*(dPar+dPerp) - dParMdPerp*dfactordk)/(4*kappa); + end +end diff --git a/NODDI_toolbox_v1.01/models/watson/WatsonSHCoeff.m b/NODDI_toolbox_v1.01/models/watson/WatsonSHCoeff.m new file mode 100644 index 0000000..ee26b76 --- /dev/null +++ b/NODDI_toolbox_v1.01/models/watson/WatsonSHCoeff.m @@ -0,0 +1,191 @@ +function [C, D] = WatsonSHCoeff(k) +% function [C, D] = WatsonSHCoeff(k) +% Computes the spherical harmonic (SH) coefficients of the Watson's +% distribution with the concentration parameter k (kappa) up to the 12th order +% and the derivatives if requested. +% +% Truncating at the 12th order gives good approximation for kappa up to 64. +% +% INPUTS: +% +% k should be an array of positive numbers, specifying a set of +% concentration parameters for the Watson's distribution. +% +% OUTPUTS: +% +% C will be a 2-D array and each row contains the SH coefficients of the +% orders 0, 2, 4, ..., to 2n for the parameter in the corresponding row in +% k. +% +% Note that the SH coefficients of the odd orders are always zero. +% +% D will be the 1st order derivative of C. +% +% author: Gary Hui Zhang (gary.zhang@ucl.ac.uk) +% + +large = find(k>30); +exact = find(k>0.1); +approx = find(k<=0.1); +% Necessary to make matlab happy when k is a single value +exact = exact(:); +approx = approx(:); +large = large(:); + +% The maximum order of SH coefficients (2n) +n = 6; + +% Computing the SH coefficients +C = zeros(length(k),n+1); + +% 0th order is a constant +C(:,1) = 2*sqrt(pi); + +% Precompute the special function values +sk = sqrt(k(exact)); +sk2 = sk.*k(exact); +sk3 = sk2.*k(exact); +sk4 = sk3.*k(exact); +sk5 = sk4.*k(exact); +sk6 = sk5.*k(exact); +sk7 = sk6.*k(exact); +k2 = k.^2; +k3 = k2.*k; +k4 = k3.*k; +k5 = k4.*k; +k6 = k5.*k; +k7 = k6.*k; + +erfik = NODDI_erfi(sk); +ierfik = 1./erfik; +ek = exp(k(exact)); +dawsonk = 0.5*sqrt(pi)*erfik./ek; + +% for large enough kappa +C(exact,2) = 3*sk - (3 + 2*k(exact)).*dawsonk; +C(exact,2) = sqrt(5)*C(exact,2).*ek; +C(exact,2) = C(exact,2).*ierfik./k(exact); + +C(exact,3) = (105 + 60*k(exact) + 12*k2(exact)).*dawsonk; +C(exact,3) = C(exact,3) -105*sk + 10*sk2; +C(exact,3) = .375*C(exact,3).*ek./k2(exact); +C(exact,3) = C(exact,3).*ierfik; + +C(exact,4) = -3465 - 1890*k(exact) - 420*k2(exact) - 40*k3(exact); +C(exact,4) = C(exact,4).*dawsonk; +C(exact,4) = C(exact,4) + 3465*sk - 420*sk2 + 84*sk3; +C(exact,4) = C(exact,4)*sqrt(13*pi)/64./k3(exact); +C(exact,4) = C(exact,4)./dawsonk; + +C(exact,5) = 675675 + 360360*k(exact) + 83160*k2(exact) + 10080*k3(exact) + 560*k4(exact); +C(exact,5) = C(exact,5).*dawsonk; +C(exact,5) = C(exact,5) - 675675*sk + 90090*sk2 - 23100*sk3 + 744*sk4; +C(exact,5) = sqrt(17)*C(exact,5).*ek; +C(exact,5) = C(exact,5)/512./k4(exact); +C(exact,5) = C(exact,5).*ierfik; + +C(exact,6) = -43648605 - 22972950*k(exact) - 5405400*k2(exact) - 720720*k3(exact) - 55440*k4(exact) - 2016*k5(exact); +C(exact,6) = C(exact,6).*dawsonk; +C(exact,6) = C(exact,6) + 43648605*sk - 6126120*sk2 + 1729728*sk3 - 82368*sk4 + 5104*sk5; +C(exact,6) = sqrt(21*pi)*C(exact,6)/4096./k5(exact); +C(exact,6) = C(exact,6)./dawsonk; + +C(exact,7) = 7027425405 + 3666482820*k(exact) + 872972100*k2(exact) + 122522400*k3(exact) + 10810800*k4(exact) + 576576*k5(exact) + 14784*k6(exact); +C(exact,7) = C(exact,7).*dawsonk; +C(exact,7) = C(exact,7) - 7027425405*sk + 1018467450*sk2 - 302630328*sk3 + 17153136*sk4 - 1553552*sk5 + 25376*sk6; +C(exact,7) = 5*C(exact,7).*ek; +C(exact,7) = C(exact,7)/16384./k6(exact); +C(exact,7) = C(exact,7).*ierfik; + +% for very large kappa +if size(large,1) > 0 + lnkd = log(k(large)) - log(30); + lnkd2 = lnkd.*lnkd; + lnkd3 = lnkd2.*lnkd; + lnkd4 = lnkd3.*lnkd; + lnkd5 = lnkd4.*lnkd; + lnkd6 = lnkd5.*lnkd; + C(large,2) = 7.52308 + 0.411538*lnkd - 0.214588*lnkd2 + 0.0784091*lnkd3 - 0.023981*lnkd4 + 0.00731537*lnkd5 - 0.0026467*lnkd6; + C(large,3) = 8.93718 + 1.62147*lnkd - 0.733421*lnkd2 + 0.191568*lnkd3 - 0.0202906*lnkd4 - 0.00779095*lnkd5 + 0.00574847*lnkd6; + C(large,4) = 8.87905 + 3.35689*lnkd - 1.15935*lnkd2 + 0.0673053*lnkd3 + 0.121857*lnkd4 - 0.066642*lnkd5 + 0.0180215*lnkd6; + C(large,5) = 7.84352 + 5.03178*lnkd - 1.0193*lnkd2 - 0.426362*lnkd3 + 0.328816*lnkd4 - 0.0688176*lnkd5 - 0.0229398*lnkd6; + C(large,6) = 6.30113 + 6.09914*lnkd - 0.16088*lnkd2 - 1.05578*lnkd3 + 0.338069*lnkd4 + 0.0937157*lnkd5 - 0.106935*lnkd6; + C(large,7) = 4.65678 + 6.30069*lnkd + 1.13754*lnkd2 - 1.38393*lnkd3 - 0.0134758*lnkd4 + 0.331686*lnkd5 - 0.105954*lnkd6; +end + +% for small kappa +C(approx,2) = 4/3*k(approx) + 8/63*k2(approx); +C(approx,2) = C(approx,2)*sqrt(pi/5); + +C(approx,3) = 8/21*k2(approx) + 32/693*k3(approx); +C(approx,3) = C(approx,3)*(sqrt(pi)*0.2); + +C(approx,4) = 16/693*k3(approx) + 32/10395*k4(approx); +C(approx,4) = C(approx,4)*sqrt(pi/13); + +C(approx,5) = 32/19305*k4(approx); +C(approx,5) = C(approx,5)*sqrt(pi/17); + +C(approx,6) = 64*sqrt(pi/21)*k5(approx)/692835; + +C(approx,7) = 128*sqrt(pi)*k6(approx)/152108775; + +if nargout == 1 + return; +end + +% Computing the derivatives +dawsonk2 = dawsonk.^2; +idawsonk2 = 1./dawsonk2; + +D = zeros(length(k),n+1); +D(:,1) = 0.0; + +% exact +D(exact,2) = -k(exact) + (2*sk2 -sk).*dawsonk + 2*dawsonk2; +D(exact,2) = (.75*sqrt(5*pi))*D(exact,2)./k2(exact).*idawsonk2; + +D(exact,3) = 21*k(exact) - 2*k2(exact); +D(exact,3) = D(exact,3) + (63*sk -44*sk2 + 4*sk3).*dawsonk; +D(exact,3) = D(exact,3) - (84 + 24*k(exact)).*dawsonk2; +D(exact,3) = D(exact,3)*(15*sqrt(pi)/32)./k3(exact).*idawsonk2; + +D(exact,4) = -165*k(exact) + 20*k2(exact) - 4*k3(exact); +D(exact,4) = D(exact,4) + (-825*sk + 390*sk2 - 44*sk3 + 8*sk4).*dawsonk; +D(exact,4) = D(exact,4) + (990 + 360*k(exact) + 40*k2(exact)).*dawsonk2; +D(exact,4) = D(exact,4)*(21*sqrt(13*pi)/128)./k4(exact).*idawsonk2; + +D(exact,5) = 225225*k(exact) - 30030*k2(exact) + 7700*k3(exact) - 248*k4(exact); +D(exact,5) = D(exact,5) + (1576575*sk - 600600*sk2 + 83160*sk3 - 15648*sk4 + 496*sk5).*dawsonk; +D(exact,5) = D(exact,5) - (1801800 + 720720*k(exact) + 110880*k2(exact) + 6720*k3(exact)).*dawsonk2; +D(exact,5) = D(exact,5)*(3*sqrt(17*pi)/2048)./k5(exact).*idawsonk2; + +D(exact,6) = -3968055*k(exact) + 556920*k2(exact) - 157248*k3(exact) + 7488*k4(exact) - 464*k5(exact); +D(exact,6) = D(exact,6) + (-35712495*sk + 11834550*sk2 - 1900090*sk3 + 336960*sk4 - 15440*sk5 + 928*sk6).*dawsonk; +D(exact,6) = D(exact,6) + (39680550 + 16707600*k(exact) + 2948400*k2(exact) + 262080*k3(exact) + 10080*k4(exact)).*dawsonk2; +D(exact,6) = D(exact,6)*(11*sqrt(21*pi)/8192)./k6(exact).*idawsonk2; + +D(exact,7) = 540571185*k(exact) - 78343650*k2(exact) + 23279256*k3(exact) - 1319472*k4(exact) + 119504*k5(exact) - 1952*k6(exact); +D(exact,7) = D(exact,7) + (5946283035*sk - 1786235220*sk2 + 319642092*sk3 - 53155872*sk4 + 2997456*sk5 - 240960*sk6 + 3904*sk7).*dawsonk; +D(exact,7) = D(exact,7) - (6486854220 + 2820371400*k(exact) + 537213600*k2(exact) + 56548800*k3(exact) + 3326400*k4(exact) + 88704*k5(exact)).*dawsonk2; +D(exact,7) = D(exact,7)*(65*sqrt(pi)/65536)./k7(exact).*idawsonk2; + +% approximation +D(approx,2) = 4/3 + 16/63*k(approx) - 16/315*k2(approx) - 128/6237*k3(approx); +D(approx,2) = D(approx,2)*sqrt(pi/5); + +D(approx,3) = 16/105*k(approx) + 32/1155*k2(approx) - 3712/675675*k3(approx) - 5888/2837835*k4(approx); +D(approx,3) = D(approx,3)*sqrt(pi); + +D(approx,4) = 16/231*k2(approx) + 128/10395*k3(approx) - 256/106029*k4(approx); +D(approx,4) = D(approx,4)*sqrt(pi/13); + +D(approx,5) = 128/19305*k3(approx) + 256/220077*k4(approx); +D(approx,5) = D(approx,5)*sqrt(pi/17); + +D(approx,6) = 64/138567*k4(approx); +D(approx,6) = D(approx,6)*sqrt(pi/21); + +D(approx,7) = 256/50702925*k5(approx); +D(approx,7) = D(approx,7)*sqrt(pi); + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/README.txt b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/README.txt new file mode 100644 index 0000000..1577d22 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/README.txt @@ -0,0 +1,237 @@ + +1. Overview + +The nifti1 matlab i/o code is written using matlab object oriented +data structures (in matlab, see help datatypes). The two +main structures are the nifti object, that primarily manages the +metadata (header information) and the file_array object, that manages +the data array and disk files. + +The nifti1 matlab code was provided by John Ashburner, Functional +Imaging Laboratory, Wellcome Department of Imaging Neuroscience, London. +This code is released under the GNU public license, see the license.txt +and gpl.txt files in the distribution. +This niftimatlib release was pulled in March 2012 from the spm8 +release: "Version 4667 (SPM8) 27-Feb-12" + + +2. Install/Build + +The nifti1 matlab i/o code was written to run under MATLAB version 6.5 or higher. +To install, just make sure that the niftimatlib/matlab directory is in your MATLAB +path. For example. in matlab you can run the addpath command: +addpath('/usr/local/pkg/niftimatlib/matlab') +Or, you can copy the contents of the niftimatlib/matlab directory to your <home>/matlab directory. + +There are two C program files included in the distribution: file2mat.c and mat2file.c +to handle file i/o. These need to be compiled into MATLAB mex files. +Precompiled mex files, taken from the spm8 distribution courtesy of the FIL, are included in +this distribution for the following platforms: +mexglx glnx86 Linux on x86 +mexa64 glnxa64 Linux on x86_64 +mexmaci maci Apple Mac OS X on x86 +mexmaci64 maci64 Apple Mac OS X on x86_64 +mexw32 win32 Microsoft Windows on x86 +mexw64 win64 Microsoft Windows on x64 +So, you may not need to do the mex compile. If you do compile, +a Makefile is in the matlab directory. Instructions are in the Makefile, a simple +"make all" should work. Note that you must have a MATLAB version 6.5 or higher mex compiler. +Alternately, a make.m file for calling mex from matlab was contributed by Alle Meije Wink. +Optional C code for a mex interface to Robert Cox's (NIH) nifti_stats.c code is provided +in the @nifti/private/src directory. + + +3. Tiny Example + +Short example for those who want to see something in a hurry (longer example below): +For access to the avg152T1_LR_nifti.nii image see +http://nifti.nimh.nih.gov/nifti-1/data + + +To open an existing nifti1 file: + +>> % be sure to rmpath any paths that point to any spm version +>> % after removing spm paths, clear all, then add niftimatlib path +>> % eg: +>> rmpath(genpath('/usr/local/pkg/spm8')) +>> clear all +>> addpath /usr/local/pkg/niftimatlib-1.2/matlab + + +>> f = nifti('avg152T1_LR_nifti.nii'); +>> disp(f) +NIFTI object: 1-by-1 + dat: [91x109x91 file_array] + mat: [4x4 double] + mat_intent: 'MNI152' + mat0: [4x4 double] + timing: [1x1 struct] + descrip: 'FSL3.2beta' + cal: [0 255] + aux_file: 'none' + + + +>> size(f.dat) + +ans = + + 91 109 91 + + +3. nifti1 i/o Class Structures + + + NIFTI Object + ------------ + + Constructor: + + a = nifti(filename); + a - nifti object + filename - filename for nifti1 dataset. Optional parameter, + if omitted and empty nifti object is returned. + + + Methods: + + create - Create a NIFTI-1 file + disp - Disp a NIFTI-1 object + display - Display a NIFTI-1 object + fieldnames - Fieldnames of a NIFTI-1 object + nifti - Create a NIFTI-1 object + subsasgn - Subscript assignment + subsref - Subscript referencing + + Fields: + + aux_file + cal + dat + descrip + diminfo + intent + mat + mat0 + mat0_intent + mat_intent + timing + + + + FILE_ARRAY Object + ----------------- + + Constructor: + + a = file_array(fname,dim,dtype,offset,scl_slope,scl_inter) + a - file_array object + fname - filename + dim - dimensions (default = [0 0] ) + dtype - datatype (default = 'uint8-le') + offset - offset into file (default = 0) + scl_slope - scalefactor (default = 1) + scl_inter - DC offset, such that dat = raw*scale + inter (default = 0) + + + Methods: + + cat - Concatenate file_array objects. + disp - Display a file_array object + display - Display a file_array object + double - Convert to double precision + end - Overloaded end function for file_array objects + fieldnames - Fieldnames of a file-array object + horzcat - Horizontal concatenation of file_array objects + length - Overloaded length function for file_array objects + ndims - Number of dimensions + numel - Number of simple file arrays involved + numeric - Convert to numeric form + reshape - Overloaded reshape function for file_array objects + size - Overloaded size function for file_array objects + subsasgn - Overloaded subsasgn function for file_array objects + subsref - Subscripted reference. + vertcat - Vertical concatenation of file_array objects + + Disallowed file_array methods: + ctranspose - Complex conjugate transposing is not allowed + permute - Permuting is not allowed + transpose - Transposing is not allowed + + Fields: + + fname + dim + dtype + offset + scl_inter + scl_slope + + + +4. Examples + + % Example of creating a simulated .nii file. + dat = file_array; + dat.fname = 'junk.nii'; + dat.dim = [64 64 32]; + dat.dtype = 'FLOAT64-LE'; + dat.offset = ceil(348/8)*8; + + % alternatively: + % dat = file_array( 'junk.nii',dim,dtype,off,scale,inter) + + disp(dat) + + % Create an empty NIFTI structure + N = nifti; + + fieldnames(N) % Dump fieldnames + + % Creating all the NIFTI header stuff + N.dat = dat; + N.mat = [2 0 0 -110 ; 0 2 0 -110; 0 0 -2 92; 0 0 0 1]; + N.mat_intent = 'xxx'; % dump possibilities + N.mat_intent = 'Scanner'; + N.mat0 = N.mat; + N.mat0_intent = 'Aligned'; + + N.diminfo.slice = 3; + N.diminfo.phase = 2; + N.diminfo.frequency = 2; + N.diminfo.slice_time.code='xxx'; % dump possibilities + N.diminfo.slice_time.code = 'sequential_increasing'; + N.diminfo.slice_time.start = 1; + N.diminfo.slice_time.end = 32; + N.diminfo.slice_time.duration = 3/32; + + N.intent.code='xxx' ; % dump possibilities + N.intent.code='FTEST'; % or N.intent.code=4; + N.intent.param = [4 8]; + + N.timing.toffset = 28800; + N.timing.tspace=3; + N.descrip = 'This is a NIFTI-1 file'; + N.aux_file='aux-file-name.txt'; + N.cal = [0 1]; + + create(N); % Writes hdr info + + %% Note that this call writes the data to the disk file + dat(:,:,:)=0; % Write out the data as all zeros + + [i,j,k] = ndgrid(1:64,1:64,1:32); + dat(find((i-32).^2+(j-32).^2+(k*2-32).^2 < 30^2))=1; % Write some ones in the file + dat(find((i-32).^2+(j-32).^2+(k*2-32).^2 < 15^2))=2; + + + % displaying a slice + imagesc(dat(:,:,12));colorbar + + % get a handle to 'junk.nii'; + M=nifti('junk.nii'); + + imagesc(M.dat(:,:,12)); + + + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/gpl.txt b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/gpl.txt new file mode 100644 index 0000000..6d45519 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/gpl.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/license.txt b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/license.txt new file mode 100644 index 0000000..c224bbb --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/license.txt @@ -0,0 +1,96 @@ +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation; either version 2 +of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + +=================================================================== +The GNU General Public License (gpl.txt) is available from: + http://www.gnu.org/copyleft/gpl.html + +Note: The niftilib matlab files are taken, with permission, from the + SPM8 software package (http://www.fil.ion.ucl.ac.uk/spm/). + Please note that this license pertains only to the files listed below, + dealing with nifti1 i/o methods, and has no bearing at all on the SPM + software package. +=================================================================== +matlab/Makefile +matlab/@file_array/numel.m +matlab/@file_array/permute.m +matlab/@file_array/reshape.m +matlab/@file_array/subsasgn.m +matlab/@file_array/subsref.m +matlab/@file_array/vertcat.m +matlab/@file_array/private/src/README +matlab/@file_array/private/src/file2mat.c +matlab/@file_array/private/src/mat2file.c +matlab/@file_array/private/datatypes.m +matlab/@file_array/private/dim.m +matlab/@file_array/private/dtype.m +matlab/@file_array/private/file2mat.m +matlab/@file_array/private/fname.m +matlab/@file_array/private/mat2file.m +matlab/@file_array/private/mystruct.m +matlab/@file_array/private/offset.m +matlab/@file_array/private/permission.m +matlab/@file_array/private/resize_scales.m +matlab/@file_array/private/scl_inter.m +matlab/@file_array/private/scl_slope.m +matlab/@file_array/cat.m +matlab/@file_array/Contents.m +matlab/@file_array/ctranspose.m +matlab/@file_array/display.m +matlab/@file_array/disp.m +matlab/@file_array/double.m +matlab/@file_array/end.m +matlab/@file_array/fieldnames.m +matlab/@file_array/file_array.m +matlab/@file_array/horzcat.m +matlab/@file_array/isnan.m +matlab/@file_array/length.m +matlab/@file_array/loadobj.m +matlab/@file_array/ndims.m +matlab/@file_array/numeric.m +matlab/@file_array/size.m +matlab/@file_array/transpose.m +matlab/@nifti/private/spm_fileparts.m +matlab/@nifti/private/decode_qform0.m +matlab/@nifti/private/empty_hdr.m +matlab/@nifti/private/encode_qform0.m +matlab/@nifti/private/findindict.m +matlab/@nifti/private/getdict.m +matlab/@nifti/private/M2Q.m +matlab/@nifti/private/mayo2nifti1.m +matlab/@nifti/private/mayostruc.m +matlab/@nifti/private/nifti_stats.m +matlab/@nifti/private/niftistruc.m +matlab/@nifti/private/Q2M.m +matlab/@nifti/private/read_extras.m +matlab/@nifti/private/read_hdr.m +matlab/@nifti/private/read_hdr_raw.m +matlab/@nifti/private/write_extras.m +matlab/@nifti/private/write_hdr_raw.m +matlab/@nifti/private/src/nifti_stats.c +matlab/@nifti/private/src/nifti_stats_mex.c +matlab/@nifti/private/src/nifti1.h +matlab/@nifti/private/src/README +matlab/@nifti/private/spm_existfile.m +matlab/@nifti/Contents.m +matlab/@nifti/create.m +matlab/@nifti/display.m +matlab/@nifti/disp.m +matlab/@nifti/fieldnames.m +matlab/@nifti/nifti.m +matlab/@nifti/structn.m +matlab/@nifti/subsasgn.m +matlab/@nifti/subsref.m +matlab/spm_flip_analyze_images.m + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/Contents.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/Contents.m new file mode 100644 index 0000000..0180f20 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/Contents.m @@ -0,0 +1,55 @@ +% File Array Object +% +% file_array - create a file_array +% horzcat - horizontal concatenation +% vertcat - vertical concatenation +% size - size of array +% length - length of longest dimension +% subsref - subscripted reference +% end - last index in an indexing expression +% resize - resize (but only of simple file_array structures) +% +% other operations are unlikely to work. +% +% Example usage. +% +% % Create a file array object by mapping test_le.img +% % to a 256x256x100 array, of datatype float32, stored +% % in a little-endian way starting at byte 0. +% fa0 = file_array('test_le.img',[256 256 100], 'FLOAT32-LE',0) +% +% % Creating an object from test_be.img, but skipping +% % the first plane of data. Data stored as big-endian +% fa1 = file_array('test_be.img',[256 256 99], 'FLOAT32-BE',4*256*256) +% +% % Reshape procedure +% fa2 = reshape(fa1,[128 2 256 99]) +% +% % Concatenation +% fa3 = [[fa0 fa0]; [fa0 fa0]] +% fa4 = cat(3,fa0,fa1) +% +% % Note that reshape will not work on the above +% % concatenated objects +% +% % Accessing values from the objects +% img = fa1(:,:,40); +% pixval = fa4(50,50,:); +% small = fa1(1:2:end,1:2:end,40); +% +% % Determining dimensions +% size(fa4) +% size(fa2) +% length(fa0) +% _________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: Contents.m 2696 2009-02-05 20:29:48Z guillaume + +% +% niftilib $Id: Contents.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/cat.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/cat.m new file mode 100644 index 0000000..bc3c37e --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/cat.m @@ -0,0 +1,44 @@ +function o = cat(dr,varargin) +% Concatenate file_array objects. The result is a non-simple object +% that can no longer be reshaped. +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: cat.m 4136 2010-12-09 22:22:28Z guillaume + +% +% niftilib $Id: cat.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + +if dr>32 || dr<0, error('Unknown command option.'); end; +dr = max(round(dr),1); +d = ones(nargin-1,16); +tmp = {}; +dpos = 0; +for i=1:nargin-1, + vi = varargin{i}; + if strcmp(class(vi),'file_array') + sz = size(vi); + d(i,1:length(sz)) = sz; + svi = struct(vi); + svi = svi(:); + for j=1:length(svi(:)), + if length(svi(j).pos)<dr + svi(j).pos((length(svi(j).pos)+1):dr) = 1; + end + svi(j).pos(dr)= svi(j).pos(dr) + dpos; + end; + dpos = dpos + d(i,dr); + tmp{i} = svi; + else + error(['Conversion to file_array from ' class(vi) ' is not possible.']); + end; +end; +if any(diff(d(:,[1:(dr-1) (dr+1):end]),1,1)) + error('All matrices on a row in the bracketed expression must have the same number of rows.'); +else + o = vertcat(tmp{:}); + o = file_array(o); +end; diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/ctranspose.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/ctranspose.m new file mode 100644 index 0000000..6cc3090 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/ctranspose.m @@ -0,0 +1,14 @@ +function varargout = ctranspose(varargin) +% Transposing not allowed +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: ctranspose.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: ctranspose.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + +error('file_array objects can not be transposed.'); diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/disp.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/disp.m new file mode 100644 index 0000000..f33b2fc --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/disp.m @@ -0,0 +1,39 @@ +function disp(obj) +% Display a file_array object +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: disp.m 4136 2010-12-09 22:22:28Z guillaume + +% +% niftilib $Id: disp.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +if numel(struct(obj))>1, + fprintf(' %s object: ', class(obj)); + sz = size(obj); + if length(sz)>4, + fprintf('%d-D\n',length(sz)); + else + for i=1:(length(sz)-1), + fprintf('%d-by-',sz(i)); + end; + fprintf('%d\n',sz(end)); + end; +else + disp(mystruct(obj)) +end; +return; +%======================================================================= + +%======================================================================= +function t = mystruct(obj) +fn = fieldnames(obj); +for i=1:length(fn) + t.(fn{i}) = subsref(obj,struct('type','.','subs',fn{i})); +end; +return; +%======================================================================= diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/display.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/display.m new file mode 100644 index 0000000..f36a8fd --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/display.m @@ -0,0 +1,19 @@ +function display(obj) +% Display a file_array object +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: display.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: display.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +disp(' '); +disp([inputname(1),' = ']) +disp(' '); +disp(obj) +disp(' ') diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/double.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/double.m new file mode 100644 index 0000000..dcee922 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/double.m @@ -0,0 +1,17 @@ +function out = double(fa) +% Convert to double precision +% FORMAT double(fa) +% fa - a file_array +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: double.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: double.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + +out = double(numeric(fa)); + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/end.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/end.m new file mode 100644 index 0000000..39f2bb8 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/end.m @@ -0,0 +1,22 @@ +function en = end(a,k,n) +% Overloaded end function for file_array objects. +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: end.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: end.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + +dim = size(a); +if k>length(dim) + en = 1; +else + if n<length(dim), + dim = [dim(1:(n-1)) prod(dim(n:end))]; + end; + en = dim(k); +end; diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/fieldnames.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/fieldnames.m new file mode 100644 index 0000000..7ef162b --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/fieldnames.m @@ -0,0 +1,21 @@ +function t = fieldnames(obj) +% Fieldnames of a file-array object +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: fieldnames.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: fieldnames.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + +t = {... + 'fname' + 'dim' + 'dtype' + 'offset' + 'scl_slope' + 'scl_inter' +}; diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/file_array.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/file_array.m new file mode 100644 index 0000000..44fbe2f --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/file_array.m @@ -0,0 +1,47 @@ +function a = file_array(varargin) +% Function for creating file_array objects. +% FORMAT a = file_array(fname,dim,dtype,offset,scl_slope,scl_inter,permission) +% a - file_array object +% fname - filename +% dim - dimensions (default = [0 0] ) +% dtype - datatype (default = 'uint8-le') +% offset - offset into file (default = 0) +% scl_slope - scalefactor (default = 1) +% scl_inter - DC offset, such that dat = raw*scale + inter (default = 0) +% permission - Write permission, either 'rw' or 'ro' (default = 'rw') +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: file_array.m 4136 2010-12-09 22:22:28Z guillaume + +% +% niftilib $Id: file_array.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +if nargin==1 + if isstruct(varargin{1}), + a = class(varargin{1},'file_array'); + return; + elseif isa(varargin{1},'file_array'), + a = varargin{1}; + return; + end; +end; +a = struct('fname','','dim',[0 0],'dtype',2,... + 'be',0,'offset',0,'pos',[],'scl_slope',[],'scl_inter',[], 'permission','rw'); +%a = class(a,'file_array'); + +if nargin>=1, a = fname(a,varargin{1}); end; +if nargin>=2, a = dim(a,varargin{2}); end; +if nargin>=3, a = dtype(a,varargin{3}); end; +if nargin>=4, a = offset(a,varargin{4}); end; +if nargin>=5, a = scl_slope(a,varargin{5}); end; +if nargin>=6, a = scl_inter(a,varargin{6}); end; +if nargin>=7, a = permission(a,varargin{7}); end; + +a.pos = ones(size(a.dim)); +a = file_array(a); + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/horzcat.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/horzcat.m new file mode 100644 index 0000000..46b997c --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/horzcat.m @@ -0,0 +1,16 @@ +function o = horzcat(varargin) +% Horizontal concatenation of file_array objects +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: horzcat.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: horzcat.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + +o = cat(2,varargin{:}); +return; + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/isnan.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/isnan.m new file mode 100644 index 0000000..986846b --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/isnan.m @@ -0,0 +1,26 @@ +function out = isnan(fa) +% Convert to numeric form +% FORMAT isnan(fa) +% fa - a file_array +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: isnan.m 1301 2008-04-03 13:21:44Z john + +% +% niftilib $Id: isnan.m,v 1.1 2012/03/22 18:36:33 fissell Exp $ +% + + +bs = 10240; +m = size(fa); +fa = reshape(fa,prod(m),1); +n = prod(m); +out = false(m); +for i=1:ceil(n/bs), + ii = ((((i-1)*bs)+1):min((i*bs),n))'; + tmp = subsref(fa,struct('type','()','subs',{{ii}})); + out(ii) = isnan(tmp); +end + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/length.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/length.m new file mode 100644 index 0000000..a375b3c --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/length.m @@ -0,0 +1,16 @@ +function l = length(x) +% Overloaded length function for file_array objects +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: length.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: length.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +l = max(size(x)); + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/loadobj.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/loadobj.m new file mode 100644 index 0000000..dafc535 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/loadobj.m @@ -0,0 +1,19 @@ +function b = loadobj(a) +% loadobj for file_array class +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: loadobj.m 1544 2008-05-06 10:34:36Z guillaume + +% +% niftilib $Id: loadobj.m,v 1.1 2012/03/22 18:36:33 fissell Exp $ +% + + +if isa(a,'file_array') + b = a; +else + a = permission(a, 'rw'); + b = file_array(a); +end diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/ndims.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/ndims.m new file mode 100644 index 0000000..c76163b --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/ndims.m @@ -0,0 +1,17 @@ +function out = ndims(fa) +% Number of dimensions +%_______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: ndims.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: ndims.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +out = size(fa); +out = length(out); + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/numel.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/numel.m new file mode 100644 index 0000000..d7931ab --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/numel.m @@ -0,0 +1,19 @@ +function t = numel(obj) +% Number of simple file arrays involved. +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: numel.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: numel.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +% Should be this, but it causes problems when accessing +% obj as a structure. +%t = prod(size(obj)); + +t = numel(struct(obj)); diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/numeric.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/numeric.m new file mode 100644 index 0000000..3e68720 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/numeric.m @@ -0,0 +1,19 @@ +function out = numeric(fa) +% Convert to numeric form +% FORMAT numeric(fa) +% fa - a file_array +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: numeric.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: numeric.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +[vo{1:ndims(fa)}] = deal(':'); +out = subsref(fa,struct('type','()','subs',{vo})); + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/permute.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/permute.m new file mode 100644 index 0000000..dd119d0 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/permute.m @@ -0,0 +1,15 @@ +function varargout = permute(varargin) +% Can not be permuted. +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: permute.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: permute.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +error('file_array objects can not be permuted.'); diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/datatypes.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/datatypes.m new file mode 100644 index 0000000..d8ee22d --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/datatypes.m @@ -0,0 +1,61 @@ +function dt = datatypes +% Datatype +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: datatypes.m 4136 2010-12-09 22:22:28Z guillaume + + +% +% niftilib $Id: datatypes.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + +persistent dtype +if isempty(dtype), + t = true; + f = false; + table = {... + 0 ,'UNKNOWN' ,'uint8' ,@uint8 ,1,1 ,t,t,f + 1 ,'BINARY' ,'uint1' ,@logical,1,1/8,t,t,f + 256 ,'INT8' ,'int8' ,@int8 ,1,1 ,t,f,t + 2 ,'UINT8' ,'uint8' ,@uint8 ,1,1 ,t,t,t + 4 ,'INT16' ,'int16' ,@int16 ,1,2 ,t,f,t + 512 ,'UINT16' ,'uint16' ,@uint16 ,1,2 ,t,t,t + 8 ,'INT32' ,'int32' ,@int32 ,1,4 ,t,f,t + 768 ,'UINT32' ,'uint32' ,@uint32 ,1,4 ,t,t,t + 1024,'INT64' ,'int64' ,@int64 ,1,8 ,t,f,f + 1280,'UINT64' ,'uint64' ,@uint64 ,1,8 ,t,t,f + 16 ,'FLOAT32' ,'float32' ,@single ,1,4 ,f,f,t + 64 ,'FLOAT64' ,'double' ,@double ,1,8 ,f,f,t + 1536,'FLOAT128' ,'float128',@error ,1,16 ,f,f,f + 32 ,'COMPLEX64' ,'float32' ,@single ,2,4 ,f,f,f + 1792,'COMPLEX128','double' ,@double ,2,8 ,f,f,f + 2048,'COMPLEX256','float128',@error ,2,16 ,f,f,f + 128 ,'RGB24' ,'uint8' ,@uint8 ,3,1 ,t,t,f}; + dtype = struct(... + 'code' ,table(:,1),... + 'label' ,table(:,2),... + 'prec' ,table(:,3),... + 'conv' ,table(:,4),... + 'nelem' ,table(:,5),... + 'size' ,table(:,6),... + 'isint' ,table(:,7),... + 'unsigned' ,table(:,8),... + 'min',-Inf,'max',Inf',... + 'supported',table(:,9)); + for i=1:length(dtype), + if dtype(i).isint + if dtype(i).unsigned + dtype(i).min = 0; + dtype(i).max = 2^(8*dtype(i).size)-1; + else + dtype(i).min = -2^(8*dtype(i).size-1); + dtype(i).max = 2^(8*dtype(i).size-1)-1; + end; + end; + end; +end; + +dt = dtype; diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/dim.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/dim.m new file mode 100644 index 0000000..e4a1438 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/dim.m @@ -0,0 +1,42 @@ +function varargout = dim(varargin) +% Format +% For getting the value +% dat = dim(obj) +% +% For setting the value +% obj = dim(obj,dat) +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: dim.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: dim.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +if nargin==2, + varargout{1} = asgn(varargin{:}); +elseif nargin==1, + varargout{1} = ref(varargin{:}); +else + error('Wrong number of arguments.'); +end; +return; + +function dat = ref(obj) +dat = obj.dim; +return; + +function obj = asgn(obj,dat) +if isnumeric(dat) && all(dat>=0) && all(rem(dat,1)==0), + dat = [double(dat(:)') 1 1]; + lim = max([2 find(dat~=1)]); + dat = dat(1:lim); + obj.dim = dat; +else + error('"dim" must be a vector of positive integers.'); +end; +return; diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/dtype.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/dtype.m new file mode 100644 index 0000000..dca0a23 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/dtype.m @@ -0,0 +1,91 @@ +function varargout = dtype(varargin) +% Format +% For getting the value +% dat = dtype(obj) +% +% For setting the value +% obj = dtype(obj,dat) +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: dtype.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: dtype.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + + +if nargin==2, + varargout{1} = asgn(varargin{:}); +elseif nargin==1, + varargout{1} = ref(varargin{:}); +else + error('Wring number of arguments.'); +end; +return; + +function t = ref(obj) +d = datatypes; +mch = find(cat(1,d.code)==obj.dtype); +if isempty(mch), t = 'UNKNOWN'; else t = d(mch).label; end; +if obj.be, t = [t '-BE']; else t = [t '-LE']; end; +return; + +function obj = asgn(obj,dat) +d = datatypes; +if isnumeric(dat) + if numel(dat)>=1, + mch = find(cat(1,d.code)==dat(1)); + if isempty(mch) || mch==0, + fprintf('Invalid datatype (%d).', dat(1)); + disp('First part of datatype should be of one of the following'); + disp(sortrows([num2str(cat(1,d.code)) ... + repmat(' ',numel(d),2) strvcat(d.label)])); + %error(['Invalid datatype (' num2str(dat(1)) ').']); + return; + end; + obj.dtype = double(dat(1)); + end; + if numel(dat)>=2, + obj.be = double(dat(2)~=0); + end; + if numel(dat)>2, + error('Too many elements in numeric datatype.'); + end; +elseif ischar(dat), + dat1 = lower(dat); + sep = find(dat1=='-' | dat1=='/'); + sep = sep(sep~=1); + if ~isempty(sep), + c1 = dat1(1:(sep(1)-1)); + c2 = dat1((sep(1)+1):end); + else + c1 = dat1; + c2 = ''; + end; + mch = find(strcmpi(c1,lower({d.label}))); + if isempty(mch), + disp('First part of datatype should be of one of the following'); + disp(sortrows([num2str(cat(1,d.code)) ... + repmat(' ',numel(d),2) strvcat(d.label)])); + %error(['Invalid datatype (' c1 ').']); + return; + else + obj.dtype = double(d(mch(1)).code); + end; + if any(c2=='b'), + if any(c2=='l'), + error('Cannot be both big and little endian.'); + end; + obj.be = 1; + elseif any(c2=='l'), + obj.be = 0; + end; +else + error('Invalid datatype.'); +end; +return; + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.m new file mode 100644 index 0000000..8199468 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.m @@ -0,0 +1,21 @@ +function val = file2mat(a,varargin) +% Function for reading from file_array objects. +% FORMAT val = file2mat(a,ind1,ind2,ind3,...) +% a - file_array object +% indx - indices for dimension x (int32) +% val - the read values +% +% This function is normally called by file_array/subsref +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% John Ashburner +% Id: file2mat.m 1530 2008-04-30 19:28:22Z guillaume + +% +% niftilib $Id: file2mat.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + +%-This is merely the help file for the compiled routine +error('file2mat.c not compiled - see Makefile'); diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexa64 b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexa64 new file mode 100644 index 0000000000000000000000000000000000000000..e0f76658c7a7e87b895864d43b19ba06af2946ea GIT binary patch literal 20614 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 E1tf_IM*si- literal 0 HcmV?d00001 diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexglx b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexglx new file mode 100644 index 0000000000000000000000000000000000000000..745b68660baaf9c0dccc97a116fa006c54497345 GIT binary patch literal 18298 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 literal 0 HcmV?d00001 diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexmaci b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexmaci new file mode 100644 index 0000000000000000000000000000000000000000..b932e4f334a808e12e28dd27a8bf1d24ab0e3e0c GIT binary patch literal 34360 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 EA39DFBLDyZ literal 0 HcmV?d00001 diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexmaci64 b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexmaci64 new file mode 100755 index 0000000000000000000000000000000000000000..d5a41f9db23b8d54e56afb6fe4ba26047766c8ca GIT binary patch literal 18376 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 literal 0 HcmV?d00001 diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexw32 b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexw32 new file mode 100755 index 0000000000000000000000000000000000000000..1eb71ec9216aef2d33bc4b25fd14b7d3d294dd77 GIT binary patch literal 50688 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 DS?&PT literal 0 HcmV?d00001 diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexw64 b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/file2mat.mexw64 new file mode 100644 index 0000000000000000000000000000000000000000..9f06847197ed239024918faf2aa3b39ce735a1f5 GIT binary patch literal 17920 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 WZLQr}w{^?bmaQQF^7=1ofqw&kN4u#2 literal 0 HcmV?d00001 diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/fname.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/fname.m new file mode 100644 index 0000000..42ea712 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/fname.m @@ -0,0 +1,40 @@ +function varargout = fname(varargin) +% Format +% For getting the value +% dat = fname(obj) +% +% For setting the value +% obj = fname(obj,dat) +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: fname.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: fname.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + + +if nargin==2, + varargout{1} = asgn(varargin{:}); +elseif nargin==1, + varargout{1} = ref(varargin{:}); +else + error('Wrong number of arguments.'); +end; +return; + +function dat = ref(obj) +dat = obj.fname; +return; + +function obj = asgn(obj,dat) +if ischar(dat) + obj.fname = deblank(dat(:)'); +else + error('"fname" must be a character string.'); +end; +return; diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.m new file mode 100644 index 0000000..12f140c --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.m @@ -0,0 +1,21 @@ +function mat2file(a,val,varargin) +% Function for writing to file_array objects. +% FORMAT mat2file(a,val,ind1,ind2,ind3,...) +% a - file_array object +% val - values to write +% indx - indices for dimension x (int32) +% +% This function is normally called by file_array/subsasgn +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% John Ashburner +% Id: mat2file.m 1530 2008-04-30 19:28:22Z guillaume + +% +% niftilib $Id: mat2file.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + +%-This is merely the help file for the compiled routine +error('mat2file.c not compiled - see Makefile'); diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexa64 b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexa64 new file mode 100644 index 0000000000000000000000000000000000000000..4b264678e6136c7085d9281e5c2e616b87238ac0 GIT binary patch literal 20110 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 literal 0 HcmV?d00001 diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexglx b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexglx new file mode 100644 index 0000000000000000000000000000000000000000..3f277ed0ec84038e43efa73429ba9b77f58aef9a GIT binary patch literal 13773 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 literal 0 HcmV?d00001 diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexmaci b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexmaci new file mode 100644 index 0000000000000000000000000000000000000000..56a9a2f3f2dd1328171202d058c0e8762f77a6b1 GIT binary patch literal 17668 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 aIV9}R!9k}1Z5-4?yt?u0B4!6tg8eUU2)5Ax literal 0 HcmV?d00001 diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexmaci64 b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexmaci64 new file mode 100755 index 0000000000000000000000000000000000000000..6c7da4370ea201514ca6a5527b38dd2f5d49c705 GIT binary patch literal 13928 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 PVIflZ{K@D>9Z~xqFY)|2 literal 0 HcmV?d00001 diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexw32 b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexw32 new file mode 100755 index 0000000000000000000000000000000000000000..783d6fb855cac0e53be08c0acb2c7291ba53e9e2 GIT binary patch literal 12800 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 literal 0 HcmV?d00001 diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexw64 b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mat2file.mexw64 new file mode 100644 index 0000000000000000000000000000000000000000..2ba10482c90dae85d8b375aa47c5d5b85517c2ea GIT binary patch literal 13312 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 aw{_dry<63-_J_(Ik{$y6@7Ldy2mTWZuU!iO literal 0 HcmV?d00001 diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mystruct.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mystruct.m new file mode 100644 index 0000000..124b802 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/mystruct.m @@ -0,0 +1,21 @@ +function t = mystruct(obj) +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: mystruct.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: mystruct.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +if numel(obj)~=1, + error('Too many elements to convert'); +end; +fn = fieldnames(obj); +for i=1:length(fn) + t.(fn{i}) = subsref(obj,struct('type','.','subs',fn{i})); +end; +return; diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/offset.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/offset.m new file mode 100644 index 0000000..258487b --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/offset.m @@ -0,0 +1,40 @@ +function varargout = offset(varargin) +% Format +% For getting the value +% dat = offset(obj) +% +% For setting the value +% obj = offset(obj,dat) +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: offset.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: offset.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + + +if nargin==2, + varargout{1} = asgn(varargin{:}); +elseif nargin==1, + varargout{1} = ref(varargin{:}); +else + error('Wrong number of arguments.'); +end; +return; + +function dat = ref(obj) +dat = obj.offset; +return; + +function obj = asgn(obj,dat) +if isnumeric(dat) && numel(dat)==1 && dat>=0 && rem(dat,1)==0, + obj.offset = double(dat); +else + error('"offset" must be a positive integer.'); +end; +return; diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/permission.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/permission.m new file mode 100644 index 0000000..2701871 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/permission.m @@ -0,0 +1,48 @@ +function varargout = permission(varargin) +% Format +% For getting the value +% dat = permission(obj) +% +% For setting the value +% obj = permission(obj,dat) +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: permission.m 1340 2008-04-09 17:11:23Z john + +% +% niftilib $Id: permission.m,v 1.1 2012/03/22 18:36:33 fissell Exp $ +% + + + + +if nargin==2, + varargout{1} = asgn(varargin{:}); +elseif nargin==1, + varargout{1} = ref(varargin{:}); +else + error('Wrong number of arguments.'); +end; +return; + +function dat = ref(obj) +dat = obj.permission; +return; + +function obj = asgn(obj,dat) +if ischar(dat) + tmp = lower(deblank(dat(:)')); + switch tmp, + case 'ro', + case 'rw', + otherwise, + error('Permission must be either "ro" or "rw"'); + end + obj.permission = tmp; +else + error('"permission" must be a character string.'); +end; +return; + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/resize_scales.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/resize_scales.m new file mode 100644 index 0000000..99f6fe8 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/resize_scales.m @@ -0,0 +1,29 @@ +function s1 = resize_scales(s0,dim,args) +% Resize scalefactors +% _________________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: resize_scales.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: resize_scales.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + +dim = [dim ones(1,max(numel(args)-numel(dim),0))]; +args1 = cell(1,numel(args)); +for i=1:numel(args), + if max(args{i})>dim(i) || min(args{i})<1, + error('Index exceeds matrix dimensions (1).'); + end; + + if size(s0,i)==1, + args1{i} = ones(size(args{i})); + else + args1{i} = args{i}; + end; +end; + +s1 = s0(args1{:}); + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/scl_inter.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/scl_inter.m new file mode 100644 index 0000000..2fad537 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/scl_inter.m @@ -0,0 +1,41 @@ +function varargout = scl_inter(varargin) +% Format +% For getting the value +% dat = scl_inter(obj) +% +% For setting the value +% obj = scl_inter(obj,dat) +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: scl_inter.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: scl_inter.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + + +if nargin==2, + varargout{1} = asgn(varargin{:}); +elseif nargin==1, + varargout{1} = ref(varargin{:}); +else + error('Wrong number of arguments.'); +end; +return; + +function dat = ref(obj) +dat = obj.scl_inter; +return; + +function obj = asgn(obj,dat) +if isnumeric(dat), % && numel(dat)<=1, + obj.scl_inter = double(dat); +else + error('"scl_inter" must be numeric.'); +end; +return; + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/scl_slope.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/scl_slope.m new file mode 100644 index 0000000..75d6617 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/scl_slope.m @@ -0,0 +1,40 @@ +function varargout = scl_slope(varargin) +% Format +% For getting the value +% dat = scl_slope(obj) +% +% For setting the value +% obj = scl_slope(obj,dat) +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: scl_slope.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: scl_slope.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + + +if nargin==2, + varargout{1} = asgn(varargin{:}); +elseif nargin==1, + varargout{1} = ref(varargin{:}); +else + error('Wrong number of arguments.'); +end; +return; + +function dat = ref(obj) +dat = obj.scl_slope; +return; + +function obj = asgn(obj,dat) +if isnumeric(dat), % && numel(dat)<=1, + obj.scl_slope = double(dat); +else + error('"scl_slope" must be numeric.'); +end; +return; diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/src/README b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/src/README new file mode 100644 index 0000000..6e5df62 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/src/README @@ -0,0 +1,12 @@ +To compile on a big-endian machine + mex -O -DBIGENDIAN file2mat.c + mex -O -DBIGENDIAN mat2file.c + +On a little-endian machine + mex -O file2mat.c + mex -O mat2file.c + +On a Windows machine + mex -O -DSPM_WIN32 file2mat.c + mex -O -DSPM_WIN32 mat2file.c + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/src/file2mat.c b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/src/file2mat.c new file mode 100644 index 0000000..6e96cf2 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/src/file2mat.c @@ -0,0 +1,644 @@ +/* + * Id: file2mat.c 4136 2010-12-09 22:22:28Z guillaume + * John Ashburner + */ + +/* + * niftilib $Id: file2mat.c,v 1.3 2012/03/22 18:36:33 fissell Exp $ + */ + +/* +Memory mapping is used by this module. For more information on this, see: +http://www.mathworks.com/company/newsletters/digest/mar04/memory_map.html +*/ + +#define _FILE_OFFSET_BITS 64 + +#include <math.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <stdlib.h> +#include <sys/types.h> +#include <string.h> +#include <stdio.h> +#include "mex.h" + +#ifdef SPM_WIN32 +#include <windows.h> +#include <memory.h> +#include <io.h> +HANDLE hFile, hMapping; +typedef char *caddr_t; +#if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS == 64 +#define stat _stati64 +#define fstat _fstati64 +#define open _open +#define close _close +#if defined _MSC_VER +#define size_t __int64 +#else +#define size_t unsigned long long +#endif +#endif +#else +#include <sys/mman.h> +#include <unistd.h> +#include <errno.h> +#define size_t unsigned long long +#endif + +/* +http://en.wikipedia.org/wiki/Page_(computing)#Determining_the_page_size_in_a_program +http://msdn.microsoft.com/en-us/library/aa366763(VS.85).aspx +*/ +int page_size() +{ +int size = 0; + +#if defined (_WIN32) || defined (_WIN64) + SYSTEM_INFO info; + GetSystemInfo (&info); + size = (int)info.dwAllocationGranularity; +#else + size = sysconf(_SC_PAGESIZE); +#endif + +return size; +} + + +#define MXDIMS 256 + +static long long icumprod[MXDIMS], ocumprod[MXDIMS]; + +static void get_1_sat(int ndim, int idim[], int *iptr[], unsigned char idat[], int odim[], unsigned char odat[], int indi, int indo) +{ + int i; + if (ndim == 0) + { + for(i=0; i<odim[0]; i++) + { + int tmp = indi+iptr[0][i]-1; + odat[indo++] = (idat[tmp>>3]>>(tmp&7))&1; + } + } + else + { + for(i=0; i<odim[ndim]; i++) + get_1_sat(ndim-1, idim, iptr, idat, odim, odat, + indi+icumprod[ndim]*(iptr[ndim][i]-1), indo+ocumprod[ndim]*i); + } +} + +void get_1(int ndim, int idim[], int *iptr[], unsigned char idat[], int odim[], unsigned char odat[]) +{ + get_1_sat(ndim, idim, iptr, idat, odim, odat, 0, 0); +} + +void get_8(int ndim, int idim[], int *iptr[], unsigned char idat[], int odim[], unsigned char odat[]) +{ + int i; + if (!ndim) + { + for(i=0; i<odim[0]; i++) + odat[i] = idat[iptr[0][i]-1]; + } + else + { + for(i=0; i<odim[ndim]; i++) + get_8(ndim-1, idim, iptr, idat+icumprod[ndim]*(iptr[ndim][i]-1), + odim, odat+ocumprod[ndim]*i); + } +} + +void get_16(int ndim, int idim[], int *iptr[], unsigned short idat[], int odim[], unsigned short odat[]) +{ + int i; + if (!ndim) + { + for(i=0; i<odim[0]; i++) + odat[i] = idat[iptr[0][i]-1]; + } + else + { + for(i=0; i<odim[ndim]; i++) + get_16(ndim-1, idim, iptr, idat+icumprod[ndim]*(iptr[ndim][i]-1), + odim, odat+ocumprod[ndim]*i); + } +} + +void get_32(int ndim, int idim[], int *iptr[], unsigned int idat[], int odim[], unsigned int odat[]) +{ + int i; + if (!ndim) + { + for(i=0; i<odim[0]; i++) + odat[i] = idat[iptr[0][i]-1]; + } + else + { + for(i=0; i<odim[ndim]; i++) + get_32(ndim-1, idim, iptr, idat+icumprod[ndim]*(iptr[ndim][i]-1), + odim, odat+ocumprod[ndim]*i); + } +} + +void get_64(int ndim, int idim[], int *iptr[], unsigned long long idat[], int odim[], unsigned long long odat[]) +{ + int i; + if (ndim == 0) + { + for(i=0; i<odim[0]; i++) + odat[i] = idat[iptr[0][i]-1]; + } + else + { + for(i=0; i<odim[ndim]; i++) + get_64(ndim-1, idim, iptr, idat+icumprod[ndim]*(iptr[ndim][i]-1), + odim, odat+ocumprod[ndim]*i); + } +} + +void get_w8(int ndim, int idim[], int *iptr[], unsigned char idat[], + int odim[], unsigned char odat_r[], unsigned char odat_i[]) +{ + int i; + if (ndim == 0) + { + int off; + for(i=0; i<odim[0]; i++) + { + off = 2*(iptr[0][i]-1); + odat_r[i] = idat[off ]; + odat_i[i] = idat[off+1]; + } + } + else + { + for(i=0; i<odim[ndim]; i++) + get_w8(ndim-1, idim, iptr, idat+icumprod[ndim]*(iptr[ndim][i]-1), + odim, odat_r+ocumprod[ndim]*i,odat_i+ocumprod[ndim]*i); + } +} + +void get_w16(int ndim, int idim[], int *iptr[], unsigned short idat[], + int odim[], unsigned short odat_r[], unsigned short odat_i[]) +{ + int i; + if (ndim == 0) + { + int off; + for(i=0; i<odim[0]; i++) + { + off = 2*(iptr[0][i]-1); + odat_r[i] = idat[off ]; + odat_i[i] = idat[off+1]; + } + } + else + { + for(i=0; i<odim[ndim]; i++) + get_w16(ndim-1, idim, iptr, idat+icumprod[ndim]*(iptr[ndim][i]-1), + odim, odat_r+ocumprod[ndim]*i,odat_i+ocumprod[ndim]*i); + } +} + +void get_w32(int ndim, int idim[], int *iptr[], unsigned int idat[], + int odim[], unsigned int odat_r[], unsigned int odat_i[]) +{ + int i; + if (ndim == 0) + { + int off; + for(i=0; i<odim[0]; i++) + { + off = 2*(iptr[0][i]-1); + odat_r[i] = idat[off ]; + odat_i[i] = idat[off+1]; + } + } + else + { + for(i=0; i<odim[ndim]; i++) + get_w32(ndim-1, idim, iptr, idat+icumprod[ndim]*(iptr[ndim][i]-1), + odim, odat_r+ocumprod[ndim]*i,odat_i+ocumprod[ndim]*i); + } +} + +void get_w64(int ndim, int idim[], int *iptr[], unsigned long long idat[], + int odim[], unsigned long long odat_r[], unsigned long long odat_i[]) +{ + int i; + if (ndim == 0) + { + int off; + for(i=0; i<odim[0]; i++) + { + off = 2*(iptr[0][i]-1); + odat_r[i] = idat[off ]; + odat_i[i] = idat[off+1]; + } + } + else + { + for(i=0; i<odim[ndim]; i++) + get_w64(ndim-1, idim, iptr, idat+icumprod[ndim]*(iptr[ndim][i]-1), + odim, odat_r+ocumprod[ndim]*i, odat_i+ocumprod[ndim]*i); + } +} + +void swap8(long long n, unsigned char d[]) +{ /* DO NOTHING */} + +void swap16(long long n, unsigned char d[]) +{ + unsigned char tmp, *de; + for(de=d+2*n; d<de; d+=2) + { + tmp = d[0]; d[0] = d[1]; d[1] = tmp; + } +} + +void swap32(long long n, unsigned char d[]) +{ + unsigned char tmp, *de; + for(de=d+4*n; d<de; d+=4) + { + tmp = d[0]; d[0] = d[3]; d[3] = tmp; + tmp = d[1]; d[1] = d[2]; d[2] = tmp; + } +} + +void swap64(long long n, unsigned char d[]) +{ + unsigned char tmp, *de; + for(de=d+8*n; d<de; d+=8) + { + tmp = d[0]; d[0] = d[7]; d[7] = tmp; + tmp = d[1]; d[1] = d[6]; d[6] = tmp; + tmp = d[2]; d[2] = d[5]; d[5] = tmp; + tmp = d[3]; d[3] = d[4]; d[4] = tmp; + } +} + +typedef struct dtype { + int code; + void (*func)(); + void (*swap)(); + int clss; + int bytes; + int channels; +} Dtype; + +Dtype table[] = { +{ 1,get_1 , swap8 , mxLOGICAL_CLASS, 1,1}, +{ 2,get_8 , swap8 , mxUINT8_CLASS , 8,1}, +{ 4,get_16 , swap16, mxINT16_CLASS ,16,1}, +{ 8,get_32 , swap32, mxINT32_CLASS ,32,1}, +{ 16,get_32 , swap32, mxSINGLE_CLASS ,32,1}, +{ 32,get_w32, swap32, mxSINGLE_CLASS ,32,2}, +{ 64,get_64 , swap64, mxDOUBLE_CLASS ,64,1}, +{ 256,get_8 , swap8 , mxINT8_CLASS , 8,1}, +{ 512,get_16 , swap16, mxUINT16_CLASS ,16,1}, +{ 768,get_32 , swap32, mxUINT32_CLASS ,32,1}, +{1792,get_w64, swap64, mxDOUBLE_CLASS ,64,2} +}; + +typedef struct mtype { + int ndim; + int dim[MXDIMS]; + Dtype *dtype; + int swap; + caddr_t addr; + size_t len; +#ifdef SPM_WIN32 + ULONGLONG off; +#else + off_t off; +#endif + void *data; +} MTYPE; + +#ifdef SPM_WIN32 +void werror(char *where, DWORD last_error) +{ + char buf[512]; + char s[1024]; + int i; + i = FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, + NULL, + last_error, + 0, + buf, + 512/sizeof(TCHAR), + NULL ); + buf[i-2] = '\0'; /* remove \r\n */ + (void)sprintf(s,"%s: %s", where, buf); + mexErrMsgTxt(s); + return; +} +#else +void werror(char *where, int last_error) +{ + char s[1024]; + + (void)sprintf(s,"%s: %s", where, strerror(last_error)); + mexErrMsgTxt(s); + return; +} +#endif + +void do_unmap_file(MTYPE *map) +{ + int sts; + if (map->addr) + { +#ifdef SPM_WIN32 + sts = UnmapViewOfFile((LPVOID)(map->addr)); + if (sts == 0) + werror("Memory Map (UnmapViewOfFile)",GetLastError()); +#else + sts = munmap(map->addr, map->len); + if (sts == -1) + werror("Memory Map (munmap)",errno); +#endif + map->addr = NULL; + } +} + +const double *getpr(const mxArray *ptr, const char nam[], int len, int *n) +{ + char s[128]; + mxArray *arr; + + arr = mxGetField(ptr,0,nam); + if (arr == (mxArray *)0) + { + (void)sprintf(s,"'%s' field is missing.", nam); + mexErrMsgTxt(s); + } + if (!mxIsNumeric(arr) && !mxIsLogical(arr)) + { + (void)sprintf(s,"'%s' field is non-numeric.", nam); + mexErrMsgTxt(s); + } + if (!mxIsDouble(arr)) + { + (void)sprintf(s,"'%s' field is not double precision.", nam); + mexErrMsgTxt(s); + } + if (len>=0) + { + *n = mxGetM(arr)*mxGetN(arr); + if (*n != len) + { + (void)sprintf(s,"'%s' field should have %d elements (has %d).", nam, len, *n); + mexErrMsgTxt(s); + } + } + else + { + *n = mxGetM(arr)*mxGetN(arr); + if (*n > -len) + { + (void)sprintf(s,"'%s' field should have a maximum of %d elements (has %d).", nam, -len, *n); + mexErrMsgTxt(s); + } + } + return (double *)mxGetData(arr); +} + +void do_map_file(const mxArray *ptr, MTYPE *map) +{ + int n; + int i, dtype; +#ifdef SPM_WIN32 + ULONGLONG offset = 0; +#else + off_t offset = 0; +#endif + const double *pr; + mxArray *arr; + size_t siz; + if (!mxIsStruct(ptr)) mexErrMsgTxt("Not a structure."); + + dtype = (int)(getpr(ptr, "dtype", 1, &n)[0]); + for(i=0; i<sizeof(table)/sizeof(Dtype); i++) + { + if (table[i].code == dtype) + { + map->dtype = &table[i]; + break; + } + } + if (map->dtype == NULL) mexErrMsgTxt("Unrecognised 'dtype' value."); + pr = getpr(ptr, "dim", -MXDIMS, &n); + map->ndim = n; + siz = 1; + for(i=0; i<map->ndim; i++) + { + map->dim[i] = (int)fabs(pr[i]); + siz = siz*map->dim[i]; + } + + /* Avoid overflow if possible */ + if (map->dtype->bytes % 8) + siz = (map->dtype->bytes*siz+7)/8; + else + siz = siz*(map->dtype->bytes/8); + + /* On 32bit platforms, cannot map more than 2^31-1 bytes */ + if ((sizeof(map->data) == 4) && (siz > 2147483647ULL)) + mexErrMsgTxt("The total number of bytes mapped is too large."); + + pr = getpr(ptr, "be",1, &n); +#ifdef SPM_BIGENDIAN + map->swap = (int)pr[0]==0; +#else + map->swap = (int)pr[0]!=0; +#endif + pr = getpr(ptr, "offset",1, &n); +#ifdef SPM_WIN32 + map->off = (ULONGLONG)pr[0]; +#else + map->off = (off_t)pr[0]; +#endif + if (map->off < 0) map->off = 0; + + arr = mxGetField(ptr,0,"fname"); + if (arr == (mxArray *)0) mexErrMsgTxt("Cant find fname."); + if (mxIsChar(arr)) + { + int buflen; + char *buf; + int fd; + struct stat stbuf; + buflen = mxGetN(arr)*mxGetM(arr)+1; + buf = mxCalloc(buflen,sizeof(char)); + if (mxGetString(arr,buf,buflen)) + { + mxFree(buf); + mexErrMsgTxt("Cant get filename."); + } + if ((fd = open(buf, O_RDONLY)) == -1) + { + mxFree(buf); + mexErrMsgTxt("Cant open file."); + } + if (fstat(fd, &stbuf) == -1) + { + (void)close(fd); + mxFree(buf); + mexErrMsgTxt("Cant get file size."); + } + if (stbuf.st_size < siz + map->off) + { + (void)close(fd); + mxFree(buf); + mexErrMsgTxt("File is smaller than the dimensions say it should be."); + } + offset = map->off % page_size(); + map->len = siz + (size_t)offset; + map->off = map->off - offset; +#ifdef SPM_WIN32 + (void)close(fd); + + /* http://msdn.microsoft.com/library/default.asp? + url=/library/en-us/fileio/base/createfile.asp */ + hFile = CreateFile( + buf, + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL | FILE_FLAG_RANDOM_ACCESS, + NULL); + mxFree(buf); + if (hFile == NULL) + werror("Memory Map (CreateFile)",GetLastError()); + + /* http://msdn.microsoft.com/library/default.asp? + url=/library/en-us/fileio/base/createfilemapping.asp */ + hMapping = CreateFileMapping( + hFile, + NULL, + PAGE_READONLY, + 0, + 0, + NULL); + (void)CloseHandle(hFile); + if (hMapping == NULL) + werror("Memory Map (CreateFileMapping)",GetLastError()); + + /* http://msdn.microsoft.com/library/default.asp? + url=/library/en-us/fileio/base/mapviewoffile.asp */ + map->addr = (caddr_t)MapViewOfFile( + hMapping, + FILE_MAP_READ, + (DWORD)(map->off >> 32), + (DWORD)(map->off), + map->len); + (void)CloseHandle(hMapping); + if (map->addr == NULL) + werror("Memory Map (MapViewOfFile)",GetLastError()); +#else + map->addr = mmap( + (caddr_t)0, + map->len, + PROT_READ, + MAP_SHARED, + fd, + map->off); + (void)close(fd); + mxFree(buf); + if (map->addr == (void *)-1) + werror("Memory Map (mmap)",errno); +#endif + } + map->data = (void *)((caddr_t)map->addr + offset); +} + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +{ + MTYPE map; + void *idat; + int i; + int *iptr[MXDIMS], odim[MXDIMS], *idim, ndim; + int one[1]; + one[0] = 1; + + if (nrhs<2 || nlhs>1) mexErrMsgTxt("Incorrect usage."); + + do_map_file(prhs[0], &map); + + ndim = map.ndim; + idim = map.dim; + idat = map.data; + + if (ndim >= MXDIMS) mexErrMsgTxt("Too many dimensions."); + + /* if (nrhs > ndim+1) mexErrMsgTxt("Index exceeds matrix dimensions (1)."); */ + + for(i=0;i<nrhs-1; i++) + { + int j; + if (!mxIsNumeric(prhs[i+1]) || !mxIsInt32(prhs[i+1]) || mxIsComplex(prhs[i+1])) + { + do_unmap_file(&map); + mexErrMsgTxt("Indices must be int32."); + } + odim[i] = mxGetM(prhs[i+1])*mxGetN(prhs[i+1]); + iptr[i] = (int *)mxGetData(prhs[i+1]); + for(j=0; j<odim[i]; j++) + if (iptr[i][j]<1 || iptr[i][j]>((i<ndim)?idim[i]:1)) + { + do_unmap_file(&map); + mexErrMsgTxt("Index exceeds matrix dimensions (1)."); + } + } + + for(i=nrhs-1; i<ndim; i++) + { + odim[i] = 1; + iptr[i] = one; + } + if (ndim<nrhs-1) + { + for(i=ndim; i<nrhs-1; i++) + idim[i] = 1; + ndim = nrhs-1; + } + + icumprod[0] = map.dtype->channels; + ocumprod[0] = 1; + for(i=0; i<ndim; i++) + { + icumprod[i+1] = icumprod[i]*(long long)idim[i]; + ocumprod[i+1] = ocumprod[i]*(long long)odim[i]; + + /* Fix for each plane of 1 bit Analyze images being + padded out to a whole number of bytes */ + if (map.dtype->bytes==1 && i==1) + icumprod[i+1] = ((icumprod[i+1]+7)/8)*8; + } + + if (map.dtype->channels == 1) + { + plhs[0] = mxCreateNumericArray(ndim,odim,map.dtype->clss,mxREAL); + map.dtype->func(ndim-1, idim, iptr, idat, odim, mxGetData(plhs[0])); + if (map.swap) + map.dtype->swap(ocumprod[ndim],mxGetData(plhs[0])); + } + else if (map.dtype->channels == 2) + { + plhs[0] = mxCreateNumericArray(ndim,odim,map.dtype->clss,mxCOMPLEX); + (map.dtype->func)(ndim-1, idim, iptr, idat, odim, mxGetData(plhs[0]),mxGetImagData(plhs[0])); + if (map.swap) + { + map.dtype->swap(ocumprod[ndim],mxGetData(plhs[0])); + map.dtype->swap(ocumprod[ndim],mxGetImagData(plhs[0])); + } + } + + do_unmap_file(&map); +} diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/src/mat2file.c b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/src/mat2file.c new file mode 100644 index 0000000..09ae795 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/private/src/mat2file.c @@ -0,0 +1,385 @@ +/* + * Id: mat2file.c 2896 2009-03-18 20:43:48Z guillaume + * John Ashburner + */ + +/* + * niftilib $Id: mat2file.c,v 1.3 2012/03/22 18:36:33 fissell Exp $ + */ + + +#define _LARGEFILE_SOURCE +#define _LARGEFILE64_SOURCE +#define _FILE_OFFSET_BITS 64 + +#include <math.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <stdlib.h> +#include <stdio.h> +#include "mex.h" +#ifdef SPM_WIN32 +#include <windows.h> +#include <memory.h> +#include <io.h> +#if defined _FILE_OFFSET_BITS && _FILE_OFFSET_BITS == 64 +#if defined _MSC_VER +#define off_t __int64 +#define fseeko _fseeki64 +#else +#define off_t off64_t +#define fseeko fseeko64 +#endif +#endif +#endif + +#define MXDIMS 256 + +typedef struct dtype { + int code; + void (*swap)(); + mxClassID clss; + int bits; + int channels; +} Dtype; + +#define copy swap8 + +void swap8(int n, unsigned char id[], unsigned char od[]) +{ + unsigned char *de; + for(de=id+n; id<de; id++, od++) + { + *od = *id; + } +} + +void swap16(int n, unsigned char id[], unsigned char od[]) +{ + unsigned char tmp, *de; + for(de=id+n; id<de; id+=2, od+=2) + { + tmp = id[0]; od[0] = id[1]; od[1] = tmp; + } +} + +void swap32(int n, unsigned char id[], unsigned char od[]) +{ + unsigned char tmp, *de; + for(de=id+n; id<de; id+=4, od+=4) + { + tmp = id[0]; od[0] = id[3]; od[3] = tmp; + tmp = id[1]; od[1] = id[2]; od[2] = tmp; + } +} + +void swap64(int n, unsigned char id[], unsigned char od[]) +{ + unsigned char tmp, *de; + for(de=id+n; id<de; id+=8, od+=8) + { + tmp = id[0]; od[0] = id[7]; od[7] = tmp; + tmp = id[1]; od[1] = id[6]; od[6] = tmp; + tmp = id[2]; od[2] = id[5]; od[5] = tmp; + tmp = id[3]; od[3] = id[4]; od[4] = tmp; + } +} + + +Dtype table[] = { +{ 1, swap8 , mxLOGICAL_CLASS, 1,1}, +{ 2, swap8 , mxUINT8_CLASS , 8,1}, +{ 4, swap16, mxINT16_CLASS ,16,1}, +{ 8, swap32, mxINT32_CLASS ,32,1}, +{ 16, swap32, mxSINGLE_CLASS ,32,1}, +{ 32, swap32, mxSINGLE_CLASS ,32,2}, +{ 64, swap64, mxDOUBLE_CLASS ,64,1}, +{ 256, swap8 , mxINT8_CLASS , 8,1}, +{ 512, swap16, mxUINT16_CLASS ,16,1}, +{ 768, swap32, mxUINT32_CLASS ,32,1}, +{1792, swap64, mxDOUBLE_CLASS ,64,2} +}; + +typedef struct ftype { + int ndim; + int dim[MXDIMS]; + Dtype *dtype; + int swap; + FILE *fp; + off_t off; +} FTYPE; + +off_t icumprod[MXDIMS], ocumprod[MXDIMS]; +off_t poff; +long len; +#define BLEN 131072 +unsigned char wbuf[BLEN], *dptr; + +void put_bytes(int ndim, FILE *fp, int *ptr[], int idim[], unsigned char idat[], off_t indo, off_t indi, void (*swap)()) +{ + int i; + off_t nb = ocumprod[ndim]; + + if (ndim == 0) + { + off_t off; + for(i=0; i<idim[ndim]; i++) + { + off = indo+(ptr[ndim][i]-1)*nb; + if (((off-poff)!=nb) || (len == BLEN)) + { + swap(len,dptr,wbuf); + if (len && (fwrite(wbuf,1,len,fp) != len)) + { + /* Problem */ + (void)fclose(fp); + (void)mexErrMsgTxt("Problem writing data (1)."); + } + if (fseeko(fp, off, SEEK_SET) == -1) + { + /* Problem */ + (void)fclose(fp); + (void)mexErrMsgTxt("Problem writing data (2)."); + } + dptr = idat+indi+i*nb; + len = 0; + } + len += nb; + poff = off; + } + } + else + { + for(i=0; i<idim[ndim]; i++) + { + put_bytes(ndim-1, fp, ptr, idim, + idat, indo+nb*(ptr[ndim][i]-1), indi+icumprod[ndim]*i, swap); + } + } +} + +void put(FTYPE map, int *ptr[], int idim[], void *idat) +{ + int i, nbytes; + void (*swap)(); + + dptr = idat; + nbytes = map.dtype->bits/8; + len = 0; + poff = -999999; + ocumprod[0] = nbytes*map.dtype->channels; + icumprod[0] = nbytes*1; + for(i=0; i<map.ndim; i++) + { + icumprod[i+1] = icumprod[i]*idim[i]; + ocumprod[i+1] = ocumprod[i]*map.dim[i]; + } + + if (map.swap) + swap = map.dtype->swap; + else + swap = copy; + + put_bytes(map.ndim-1, map.fp, ptr, idim, (unsigned char *)idat, map.off, 0,swap); + + swap(len,dptr,wbuf); + if (fwrite(wbuf,1,len,map.fp) != len) + { + /* Problem */ + (void)fclose(map.fp); + (void)mexErrMsgTxt("Problem writing data (3)."); + } +} + +const double *getpr(const mxArray *ptr, const char nam[], int len, int *n) +{ + char s[256]; + mxArray *arr; + + arr = mxGetField(ptr,0,nam); + if (arr == (mxArray *)0) + { + (void)sprintf(s,"'%s' field is missing.", nam); + mexErrMsgTxt(s); + } + if (!mxIsNumeric(arr)) + { + (void)sprintf(s,"'%s' field is non-numeric.", nam); + mexErrMsgTxt(s); + } + if (!mxIsDouble(arr)) + { + (void)sprintf(s,"'%s' field is not double precision.", nam); + mexErrMsgTxt(s); + } + if (len>=0) + { + *n = mxGetM(arr)*mxGetN(arr); + if (*n != len) + { + (void)sprintf(s,"'%s' field should have %d elements (has %d).", nam, len, *n); + mexErrMsgTxt(s); + } + } + else + { + *n = mxGetNumberOfElements(arr); + if (*n > -len) + { + (void)sprintf(s,"'%s' field should have a maximum of %d elements (has %d).", nam, -len, *n); + mexErrMsgTxt(s); + } + } + return (double *)mxGetData(arr); +} + + +void open_file(const mxArray *ptr, FTYPE *map) +{ + int n; + int i, dtype; + const double *pr; + mxArray *arr; + + if (!mxIsStruct(ptr)) mexErrMsgTxt("Not a structure."); + + dtype = (int)(getpr(ptr, "dtype", 1, &n)[0]); + map->dtype = NULL; + for(i=0; i<sizeof(table)/sizeof(Dtype); i++) + { + if (table[i].code == dtype) + { + map->dtype = &table[i]; + break; + } + } + if (map->dtype == NULL) mexErrMsgTxt("Unrecognised 'dtype' value."); + if (map->dtype->bits % 8) mexErrMsgTxt("Can not yet write logical data."); + if (map->dtype->channels != 1) mexErrMsgTxt("Can not yet write complex data."); + pr = getpr(ptr, "dim", -MXDIMS, &n); + map->ndim = n; + for(i=0; i<map->ndim; i++) + { + map->dim[i] = (int)fabs(pr[i]); + } + pr = getpr(ptr, "be",1, &n); +#ifdef SPM_BIGENDIAN + map->swap = (int)pr[0]==0; +#else + map->swap = (int)pr[0]!=0; +#endif + pr = getpr(ptr, "offset",1, &n); + map->off = (off_t)pr[0]; + /* if (map->off < 0) map->off = 0; Unsigned, so not necessary */ + + arr = mxGetField(ptr,0,"fname"); + if (arr == (mxArray *)0) mexErrMsgTxt("Cant find 'fname' field."); + + if (mxIsChar(arr)) + { + int buflen; + char *buf; + buflen = mxGetNumberOfElements(arr)+1; + buf = mxCalloc(buflen+1,sizeof(char)); + if (mxGetString(arr,buf,buflen)) + { + mxFree(buf); + mexErrMsgTxt("Cant get 'fname'."); + } + map->fp = fopen(buf,"rb+"); + if (map->fp == (FILE *)0) + { + map->fp = fopen(buf,"wb"); + if (map->fp == (FILE *)0) + { + mxFree(buf); + mexErrMsgTxt("Cant open file."); + } + } + + mxFree(buf); + } + else + mexErrMsgTxt("Wrong type of 'fname' field."); +} + + +void close_file(FTYPE map) +{ + (void)fclose(map.fp); +} + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +{ + FTYPE map; + void *idat; + int i; + int *ptr[MXDIMS], *odim, ndim, idim[MXDIMS]; + int one[1]; + const mxArray *curr; + one[0] = 1; + + if (nrhs<3 || nlhs>0) mexErrMsgTxt("Incorrect usage."); + + curr = prhs[0]; + open_file(curr, &map); + + ndim = map.ndim; + odim = map.dim; + + if (ndim >= MXDIMS) + { + close_file(map); + mexErrMsgTxt("Too many dimensions."); + } + curr = prhs[1]; + if (mxGetClassID(curr) != map.dtype->clss) + { + close_file(map); + mexErrMsgTxt("Incompatible class types."); + } + idat = mxGetData(curr); + + for(i=0;i<nrhs-2; i++) + { + int j; + curr = prhs[i+2]; + if (!mxIsInt32(curr)) + { + close_file(map); + mexErrMsgTxt("Indices must be int32."); + } + if (i< mxGetNumberOfDimensions(prhs[1])) + idim[i] = mxGetDimensions(prhs[1])[i]; + else + idim[i] = 1; + + if (mxGetNumberOfElements(curr) != idim[i]) + { + close_file(map); + mexErrMsgTxt("Subscripted assignment dimension mismatch (2)."); + } + + ptr[i] = (int *)mxGetData(curr); + for(j=0; j<idim[i]; j++) + if (ptr[i][j]<1 || ptr[i][j]> ((i<ndim)?odim[i]:1)) + { + close_file(map); + mexErrMsgTxt("Index exceeds matrix dimensions (2)."); + } + } + + for(i=nrhs-2; i<ndim; i++) + { + idim[i] = 1; + ptr[i] = one; + } + if (ndim<nrhs-2) + { + for(i=ndim; i<nrhs-2; i++) + map.dim[i] = 1; + map.ndim = nrhs-2; + } + put(map, ptr, idim, idat); + close_file(map); +} diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/reshape.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/reshape.m new file mode 100644 index 0000000..c2d7a56 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/reshape.m @@ -0,0 +1,26 @@ +function a = reshape(b,varargin) +% Overloaded reshape function for file_array objects +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: reshape.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: reshape.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +if length(struct(b))~=1, error('Can only reshape simple file_array objects.'); end; + +args = []; +for i=1:length(varargin), + args = [args varargin{i}(:)']; +end; +if prod(args)~=prod(b.dim), + error('To RESHAPE the number of elements must not change.'); +end; +a = b; +a.dim = args; + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/size.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/size.m new file mode 100644 index 0000000..e1dfdeb --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/size.m @@ -0,0 +1,49 @@ +function d = size(a,varargin) +% overloaded size function for file_array objects. +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: size.m 3730 2010-02-17 13:24:26Z john + +% +% niftilib $Id: size.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +sa = struct(a); +nd = 0; +for i=1:numel(sa), + nd = max(nd,numel(sa(i).dim)); + nd = max(nd,max(find(sa(i).pos==1))); +end +nd = nd+1; + +dim = ones(length(sa),nd); +pos = ones(length(sa),nd); + +for i=1:length(sa) + sz = sa(i).dim; + dim(i,1:length(sz)) = sz; + ps = sa(i).pos; + pos(i,1:length(ps)) = ps; +end + +tmp = pos==1; +d = zeros(1,nd); +for i=1:nd, + ind = all(tmp(:,[1:(i-1) (i+1):nd]),2); + d(i) = sum(dim(ind,i)); +end; +lim = max(max(find(d~=1)),2); +d = d(1:lim); + +if nargin>1, + if varargin{1}<=length(d), + d = d(varargin{1}); + else + d = 1; + end; +end; + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/subsasgn.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/subsasgn.m new file mode 100644 index 0000000..a8eb1f3 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/subsasgn.m @@ -0,0 +1,158 @@ +function obj = subsasgn(obj,subs,dat) +% Overloaded subsasgn function for file_array objects. +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: subsasgn.m 4136 2010-12-09 22:22:28Z guillaume + +% +% niftilib $Id: subsasgn.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +if isempty(subs) + return; +end; +if ~strcmp(subs(1).type,'()'), + if strcmp(subs(1).type,'.'), + %error('Attempt to reference field of non-structure array.'); + if numel(struct(obj))~=1, + error('Can only change the fields of simple file_array objects.'); + end; + switch(subs(1).subs) + case 'fname', obj = asgn(obj,@fname, subs(2:end),dat); %fname(obj,dat); + case 'dtype', obj = asgn(obj,@dtype, subs(2:end),dat); %dtype(obj,dat); + case 'offset', obj = asgn(obj,@offset, subs(2:end),dat); %offset(obj,dat); + case 'dim', obj = asgn(obj,@dim, subs(2:end),dat); %obj = dim(obj,dat); + case 'scl_slope', obj = asgn(obj,@scl_slope, subs(2:end),dat); %scl_slope(obj,dat); + case 'scl_inter', obj = asgn(obj,@scl_inter, subs(2:end),dat); %scl_inter(obj,dat); + case 'permission', obj = asgn(obj,@permission,subs(2:end),dat); %permission(obj,dat); + otherwise, error(['Reference to non-existent field "' subs.subs '".']); + end; + return; + end; + if strcmp(subs(1).type,'{}'), error('Cell contents reference from a non-cell array object.'); end; +end; + +if numel(subs)~=1, error('Expression too complicated');end; +dm = size(obj); +sobj = struct(obj); + +if length(subs.subs) < length(dm), + l = length(subs.subs); + dm = [dm(1:(l-1)) prod(dm(l:end))]; + if numel(sobj) ~= 1, + error('Can only reshape simple file_array objects.'); + end; + if numel(sobj.scl_slope)>1 || numel(sobj.scl_inter)>1, + error('Can not reshape file_array objects with multiple slopes and intercepts.'); + end; +end; + +dm = [dm ones(1,16)]; +di = ones(1,16); +args = {}; +for i=1:length(subs.subs), + if ischar(subs.subs{i}), + if ~strcmp(subs.subs{i},':'), error('This shouldn''t happen....'); end; + args{i} = int32(1:dm(i)); + else + args{i} = int32(subs.subs{i}); + end; + di(i) = length(args{i}); +end; +for j=1:length(sobj), + if strcmp(sobj(j).permission,'ro'), + error('Array is read-only.'); + end +end + +if length(sobj)==1 + sobj.dim = dm; + if numel(dat)~=1, + subfun(sobj,double(dat),args{:}); + else + dat1 = double(dat) + zeros(di); + subfun(sobj,dat1,args{:}); + end; +else + for j=1:length(sobj), + ps = [sobj(j).pos ones(1,length(args))]; + dm = [sobj(j).dim ones(1,length(args))]; + siz = ones(1,16); + for i=1:length(args), + msk = args{i}>=ps(i) & args{i}<(ps(i)+dm(i)); + args2{i} = find(msk); + args3{i} = int32(double(args{i}(msk))-ps(i)+1); + siz(i) = numel(args2{i}); + end; + if numel(dat)~=1, + dat1 = double(subsref(dat,struct('type','()','subs',{args2}))); + else + dat1 = double(dat) + zeros(siz); + end; + subfun(sobj(j),dat1,args3{:}); + end +end +return + +function sobj = subfun(sobj,dat,varargin) +va = varargin; + +dt = datatypes; +ind = find(cat(1,dt.code)==sobj.dtype); +if isempty(ind), error('Unknown datatype'); end; +if dt(ind).isint, dat(~isfinite(dat)) = 0; end; + +if ~isempty(sobj.scl_inter), + inter = sobj.scl_inter; + if numel(inter)>1, + inter = resize_scales(inter,sobj.dim,varargin); + end; + dat = double(dat) - inter; +end; + +if ~isempty(sobj.scl_slope), + slope = sobj.scl_slope; + if numel(slope)>1, + slope = resize_scales(slope,sobj.dim,varargin); + dat = double(dat)./slope; + else + dat = double(dat)/slope; + end; +end; + +if dt(ind).isint, dat = round(dat); end; + +% Avoid warning messages in R14 SP3 +wrn = warning; +warning('off'); +dat = feval(dt(ind).conv,dat); +warning(wrn); + +nelem = dt(ind).nelem; +if nelem==1, + mat2file(sobj,dat,va{:}); +elseif nelem==2, + sobj1 = sobj; + sobj1.dim = [2 sobj.dim]; + sobj1.dtype = dt(find(strcmp(dt(ind).prec,{dt.prec}) & (cat(2,dt.nelem)==1))).code; + dat = reshape(dat,[1 size(dat)]); + dat = [real(dat) ; imag(dat)]; + mat2file(sobj1,dat,int32([1 2]),va{:}); +else + error('Inappropriate number of elements per voxel.'); +end; +return + +function obj = asgn(obj,fun,subs,dat) +if ~isempty(subs), + tmp = feval(fun,obj); + tmp = subsasgn(tmp,subs,dat); + obj = feval(fun,obj,tmp); +else + obj = feval(fun,obj,dat); +end; + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/subsref.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/subsref.m new file mode 100644 index 0000000..7e1df13 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/subsref.m @@ -0,0 +1,186 @@ +function varargout=subsref(obj,subs) +% SUBSREF Subscripted reference +% An overloaded function... +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: subsref.m 4136 2010-12-09 22:22:28Z guillaume + +% +% niftilib $Id: subsref.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +if isempty(subs), return; end + +switch subs(1).type + case '{}' + error('Cell contents reference from a non-cell array object.'); + case '.' + varargout = access_fields(obj,subs); + return; +end + +if numel(subs)~=1, error('Expression too complicated'); end; + +dim = [size(obj) ones(1,16)]; +nd = find(dim>1,1,'last')-1; +sobj = struct(obj); + +if ~numel(subs.subs) + [subs.subs{1:nd+1}] = deal(':'); +elseif length(subs.subs) < nd + l = length(subs.subs); + dim = [dim(1:(l-1)) prod(dim(l:end))]; + if numel(sobj) ~= 1 + error('Can only reshape simple file_array objects.'); + else + if numel(sobj.scl_slope)>1 || numel(sobj.scl_inter)>1 + error('Can not reshape file_array objects with multiple slopes and intercepts.'); + end + sobj.dim = dim; + end +end + +di = ones(16,1); +args = cell(1,length(subs.subs)); +for i=1:length(subs.subs) + if ischar(subs.subs{i}) + if ~strcmp(subs.subs{i},':'), error('This shouldn''t happen....'); end + if length(subs.subs) == 1 + args{i} = 1:prod(dim); % possible overflow when int32() + k = 0; + for j=1:length(sobj) + sobj(j).dim = [prod(sobj(j).dim) 1]; + sobj(j).pos = [k+1 1]; + k = k + sobj(j).dim(1); + end + else + args{i} = 1:dim(i); + end + else + args{i} = subs.subs{i}; + end + di(i) = length(args{i}); +end + +if length(sobj)==1 + t = subfun(sobj,args{:}); +else + dt = datatypes; + dt = dt([dt.code]==sobj(1).dtype); % assuming identical datatypes + t = zeros(di',func2str(dt.conv)); + for j=1:length(sobj) + ps = [sobj(j).pos ones(1,length(args))]; + dm = [sobj(j).dim ones(1,length(args))]; + for i=1:length(args) + msk = find(args{i}>=ps(i) & args{i}<(ps(i)+dm(i))); + args2{i} = msk; + args3{i} = double(args{i}(msk))-ps(i)+1; + end + + t = subsasgn(t,struct('type','()','subs',{args2}),subfun(sobj(j),args3{:})); + end +end +varargout = {t}; + + +%========================================================================== +% function t = subfun(sobj,varargin) +%========================================================================== +function t = subfun(sobj,varargin) + +%sobj.dim = [sobj.dim ones(1,16)]; +try + args = cell(size(varargin)); + for i=1:length(varargin) + args{i} = int32(varargin{i}); + end + t = file2mat(sobj,args{:}); +catch + t = multifile2mat(sobj,varargin{:}); +end +if ~isempty(sobj.scl_slope) || ~isempty(sobj.scl_inter) + slope = 1; + inter = 0; + if ~isempty(sobj.scl_slope), slope = sobj.scl_slope; end + if ~isempty(sobj.scl_inter), inter = sobj.scl_inter; end + if numel(slope)>1 + slope = resize_scales(slope,sobj.dim,varargin); + t = double(t).*slope; + else + t = double(t)*slope; + end + if numel(inter)>1 + inter = resize_scales(inter,sobj.dim,varargin); + end; + t = t + inter; +end + + +%========================================================================== +% function c = access_fields(obj,subs) +%========================================================================== +function c = access_fields(obj,subs) + +sobj = struct(obj); +c = cell(1,numel(sobj)); +for i=1:numel(sobj) + %obj = class(sobj(i),'file_array'); + obj = sobj(i); + switch(subs(1).subs) + case 'fname', t = fname(obj); + case 'dtype', t = dtype(obj); + case 'offset', t = offset(obj); + case 'dim', t = dim(obj); + case 'scl_slope', t = scl_slope(obj); + case 'scl_inter', t = scl_inter(obj); + case 'permission', t = permission(obj); + otherwise + error(['Reference to non-existent field "' subs(1).subs '".']); + end + if numel(subs)>1 + t = subsref(t,subs(2:end)); + end + c{i} = t; +end + + +%========================================================================== +% function val = multifile2mat(sobj,varargin) +%========================================================================== +function val = multifile2mat(sobj,varargin) + +% Convert subscripts into linear index +[indx2{1:length(varargin)}] = ndgrid(varargin{:},1); +ind = sub2ind(sobj.dim,indx2{:}); + +% Work out the partition +dt = datatypes; +dt = dt([dt.code]==sobj.dtype); +sz = dt.size; +try + mem = spm('Memory'); % in bytes, has to be a multiple of 16 (max([dt.size])) +catch + mem = 200 * 1024 * 1024; +end +s = ceil(prod(sobj.dim) * sz / mem); + +% Assign indices to partitions +[x,y] = ind2sub([mem/sz s],ind(:)); +c = histc(y,1:s); +cc = [0 reshape(cumsum(c),1,[])]; + +% Read data in relevant partitions +obj = sobj; +val = zeros(length(x),1,func2str(dt.conv)); +for i=reshape(find(c),1,[]) + obj.offset = sobj.offset + mem*(i-1); + obj.dim = [1 min(mem/sz, prod(sobj.dim)-(i-1)*mem/sz)]; + val(cc(i)+1:cc(i+1)) = file2mat(obj,int32(1),int32(x(y==i))); +end +r = cellfun('length',varargin); +if numel(r) == 1, r = [r 1]; end +val = reshape(val,r); diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/transpose.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/transpose.m new file mode 100644 index 0000000..6451efe --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/transpose.m @@ -0,0 +1,15 @@ +function varargout = transpose(varargin) +% Transposing is not allowed. +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: transpose.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: transpose.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +error('file_array objects can not be transposed.'); diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/vertcat.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/vertcat.m new file mode 100644 index 0000000..28b6ed1 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@file_array/vertcat.m @@ -0,0 +1,16 @@ +function o = vertcat(varargin) +% Vertical concatenation of file_array objects. +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: vertcat.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: vertcat.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +o = cat(1,varargin{:}); +return; diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/Contents.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/Contents.m new file mode 100644 index 0000000..b1a0903 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/Contents.m @@ -0,0 +1,84 @@ +% NIFTI Object +% +% create - Create a NIFTI-1 file +% disp - Disp a NIFTI-1 object +% display - Display a NIFTI-1 object +% fieldnames - Fieldnames of a NIFTI-1 object +% nifti - Create a NIFTI-1 object +% subsasgn - Subscript assignment +% subsref - Subscript referencing +% +% other operations are unlikely to work. +% +% Example usage. +% +% % Example of creating a simulated .nii file. +% dat = file_array; +% dat.fname = 'junk.nii'; +% dat.dim = [64 64 32]; +% dat.dtype = 'FLOAT64-BE'; +% dat.offset = ceil(348/8)*8; +% +% % alternatively: +% % dat = file_array( 'junk.nii',dim,dtype,off,scale,inter) +% +% disp(dat) +% +% % Create an empty NIFTI structure +% N = nifti; +% +% fieldnames(N) % Dump fieldnames +% +% % Creating all the NIFTI header stuff +% N.dat = dat; +% N.mat = [2 0 0 -110 ; 0 2 0 -110; 0 0 -2 92; 0 0 0 1]; +% N.mat_intent = 'xxx'; % dump possibilities +% N.mat_intent = 'Scanner'; +% N.mat0 = N.mat; +% N.mat0_intent = 'Aligned'; +% +% N.diminfo.slice = 3; +% N.diminfo.phase = 2; +% N.diminfo.frequency = 2; +% N.diminfo.slice_time.code='xxx'; % dump possibilities +% N.diminfo.slice_time.code = 'sequential_increasing'; +% N.diminfo.slice_time.start = 1; +% N.diminfo.slice_time.end = 32; +% N.diminfo.slice_time.duration = 3/32; +% +% N.intent.code='xxx' ; % dump possibilities +% N.intent.code='FTEST'; % or N.intent.code=4; +% N.intent.param = [4 8]; +% +% N.timing.toffset = 28800; +% N.timing.tspace=3; +% N.descrip = 'This is a NIFTI-1 file'; +% N.aux_file='aux-file-name.txt'; +% N.cal = [0 1]; +% +% create(N); % Writes hdr info +% +% dat(:,:,:)=0; % Write out the data as all zeros +% +% [i,j,k] = ndgrid(1:64,1:64,1:32); +% dat(find((i-32).^2+(j-32).^2+(k*2-32).^2 < 30^2))=1; % Write some ones in the file +% dat(find((i-32).^2+(j-32).^2+(k*2-32).^2 < 15^2))=2; +% +% +% % displaying a slice +% imagesc(dat(:,:,12));colorbar +% +% % get a handle to 'junk.nii'; +% M=nifti('junk.nii'); +% +% imagesc(M.dat(:,:,12)); +% +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: Contents.m 2696 2009-02-05 20:29:48Z guillaume + +% +% niftilib $Id: Contents.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/create.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/create.m new file mode 100644 index 0000000..1d9099f --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/create.m @@ -0,0 +1,78 @@ +function create(obj,wrt) +% Create a NIFTI-1 file +% FORMAT create(obj) +% This writes out the header information for the nifti object +% +% create(obj,wrt) +% This also writes out an empty image volume if wrt==1 +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: create.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: create.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + +for i=1:numel(obj) + create_each(obj(i)); +end; + +function create_each(obj) +if ~isa(obj.dat,'file_array'), + error('Data must be a file-array'); +end; +fname = obj.dat.fname; +if isempty(fname), + error('No filename to write to.'); +end; +dt = obj.dat.dtype; +ok = write_hdr_raw(fname,obj.hdr,dt(end-1)=='B'); +if ~ok, + error(['Unable to write header for "' fname '".']); +end; + +write_extras(fname,obj.extras); + +if nargin>2 && any(wrt==1), + % Create an empty image file if necessary + d = findindict(obj.hdr.datatype, 'dtype'); + dim = double(obj.hdr.dim(2:end)); + dim((double(obj.hdr.dim(1))+1):end) = 1; + nbytes = ceil(d.size*d.nelem*prod(dim(1:2)))*prod(dim(3:end))+double(obj.hdr.vox_offset); + [pth,nam,ext] = fileparts(obj.dat.fname); + + if any(strcmp(deblank(obj.hdr.magic),{'n+1','nx1'})), + ext = '.nii'; + else + ext = '.img'; + end; + iname = fullfile(pth,[nam ext]); + fp = fopen(iname,'a+'); + if fp==-1, + error(['Unable to create image for "' fname '".']); + end; + + fseek(fp,0,'eof'); + pos = ftell(fp); + if pos<nbytes, + bs = 2048; % Buffer-size + nbytes = nbytes - pos; + buf = uint8(0); + buf(bs) = 0; + while(nbytes>0) + if nbytes<bs, buf = buf(1:nbytes); end; + nw = fwrite(fp,buf,'uint8'); + if nw<min(bs,nbytes), + fclose(fp); + error(['Problem while creating image for "' fname '".']); + end; + nbytes = nbytes - nw; + end; + end; + fclose(fp); +end; + +return; + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/disp.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/disp.m new file mode 100644 index 0000000..09563f2 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/disp.m @@ -0,0 +1,27 @@ +function disp(obj) +% Disp a NIFTI-1 object +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: disp.m 4136 2010-12-09 22:22:28Z guillaume + +% +% niftilib $Id: disp.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + +sz = size(obj); +fprintf('NIFTI object: '); +if length(sz)>4, + fprintf('%d-D\n',length(sz)); +else + for i=1:(length(sz)-1), + fprintf('%d-by-',sz(i)); + end; + fprintf('%d\n',sz(end)); +end; +if prod(sz)==1, + disp(structn(obj)) +end; +return; diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/display.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/display.m new file mode 100644 index 0000000..38383ab --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/display.m @@ -0,0 +1,18 @@ +function display(obj) +% Display a NIFTI-1 object +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: display.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: display.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + +disp(' '); +disp([inputname(1),' = ']) +disp(' '); +disp(obj) +disp(' ') diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/fieldnames.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/fieldnames.m new file mode 100644 index 0000000..2573925 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/fieldnames.m @@ -0,0 +1,30 @@ +function t = fieldnames(obj) +% Fieldnames of a NIFTI-1 object +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: fieldnames.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: fieldnames.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + +if isfield(obj.hdr,'magic') + t = {... + 'dat' + 'mat' + 'mat_intent' + 'mat0' + 'mat0_intent' + 'intent' + 'diminfo' + 'timing' + 'descrip' + 'cal' + 'aux_file' + }; +else + error('This should not happen.'); +end; diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/nifti.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/nifti.m new file mode 100644 index 0000000..6bd71b1 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/nifti.m @@ -0,0 +1,95 @@ +function h = nifti(varargin) +% Create a NIFTI-1 object +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: nifti.m 4270 2011-03-29 16:26:26Z john + +% +% niftilib $Id: nifti.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + +switch nargin +case 0, + org = niftistruc; + hdr = []; + for i=1:length(org), + hdr.(org(i).label) = feval(org(i).dtype.conv,org(i).def); + end; + h = struct('hdr',hdr,'dat',[],'extras',struct); + h = class(h,'nifti'); + +case 1 + if ischar(varargin{1}) + if size(varargin{1},1)>1, + h = nifti(cellstr(varargin{1})); + return; + end; + fname = deblank(varargin{1}); + vol = read_hdr(fname); + extras = read_extras(fname); + + if ~isfield(vol.hdr,'magic'), + vol.hdr = mayo2nifti1(vol.hdr); + + % For SPM99 compatibility + if isfield(extras,'M') && ~isfield(extras,'mat'), + extras.mat = extras.M; + if spm_flip_analyze_images, + extras.mat = diag([-1 1 1 1])*extras.mat; + end; + end; + + % Over-ride sform if a .mat file exists + if isfield(extras,'mat') && size(extras.mat,3)>=1, + mat = extras.mat(:,:,1); + mat1 = mat*[eye(4,3) [1 1 1 1]']; + vol.hdr.srow_x = mat1(1,:); + vol.hdr.srow_y = mat1(2,:); + vol.hdr.srow_z = mat1(3,:); + vol.hdr.sform_code = 2; + vol.hdr.qform_code = 2; + vol.hdr = encode_qform0(mat,vol.hdr); + end; + end; + + if isfield(extras,'M'), extras = rmfield(extras,'M'); end; + if isfield(extras,'mat') && size(extras.mat,3)<=1, + extras = rmfield(extras,'mat'); + end; + + dim = double(vol.hdr.dim); + dim = dim(2:(dim(1)+1)); + dt = double(vol.hdr.datatype); + offs = max(double(vol.hdr.vox_offset),0); + + if ~vol.hdr.scl_slope && ~vol.hdr.scl_inter, + vol.hdr.scl_slope = 1; + end; + slope = double(vol.hdr.scl_slope); + inter = double(vol.hdr.scl_inter); + + dat = file_array(vol.iname,dim,[dt,vol.be],offs,slope,inter); + h = struct('hdr',vol.hdr,'dat',dat,'extras',extras); + h = class(h,'nifti'); + + elseif isstruct(varargin{1}) + h = class(varargin{1},'nifti'); + + elseif iscell(varargin{1}) + fnames = varargin{1}; + h(numel(fnames)) = struct('hdr',[],'dat',[],'extras',struct); + h = class(h,'nifti'); + for i=1:numel(fnames), + h(i) = nifti(fnames{i}); + end; + + else + error('Dont know what to do yet.'); + end; +otherwise + error('Dont know what to do yet'); +end; +return; diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/M2Q.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/M2Q.m new file mode 100644 index 0000000..1b453d6 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/M2Q.m @@ -0,0 +1,38 @@ +function Q = M2Q(M) +% Convert from rotation matrix to quaternion form +% See: http://skal.planet-d.net/demo/matrixfaq.htm +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: M2Q.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: M2Q.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +d = diag(M(1:3,1:3)); +t = sum(d) + 1; +if t>0.5, + s = sqrt(t)*2; + Q = [(M(3,2)-M(2,3))/s (M(1,3)-M(3,1))/s (M(2,1)-M(1,2))/s 0.25*s]'; +else + t = find(d==max(d)); + t = t(1); + switch(t), + case 1, + s = 2*sqrt(1 + M(1,1) - M(2,2) - M(3,3)); + Q = [0.25*s (M(1,2)+M(2,1))/s (M(3,1)+M(1,3))/s (M(3,2)-M(2,3))/s]'; + case 2, + s = 2*sqrt(1 + M(2,2) - M(1,1) - M(3,3)); + Q = [(M(1,2)+M(2,1))/s 0.25*s (M(2,3)+M(3,2))/s (M(1,3)-M(3,1))/s ]'; + case 3, + s = 2*sqrt(1 + M(3,3) - M(1,1) - M(2,2)); + Q = [(M(3,1)+M(1,3))/s (M(2,3)+M(3,2))/s 0.25*s (M(2,1)-M(1,2))/s]'; + end; +end; +if Q(4)<0, Q = -Q; end; % w must be +ve +return; + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/Q2M.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/Q2M.m new file mode 100644 index 0000000..4d4caf1 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/Q2M.m @@ -0,0 +1,36 @@ +function M = Q2M(Q) +% Generate a rotation matrix from a quaternion xi+yj+zk+w, +% where Q = [x y z], and w = 1-x^2-y^2-z^2. +% See: http://skal.planet-d.net/demo/matrixfaq.htm +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: Q2M.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: Q2M.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +Q = Q(1:3); % Assume rigid body +w = sqrt(1 - sum(Q.^2)); +x = Q(1); y = Q(2); z = Q(3); +if w<1e-7, + w = 1/sqrt(x*x+y*y+z*z); + x = x*w; + y = y*w; + z = z*w; + w = 0; +end; +xx = x*x; yy = y*y; zz = z*z; ww = w*w; +xy = x*y; xz = x*z; xw = x*w; +yz = y*z; yw = y*w; zw = z*w; +M = [... +(xx-yy-zz+ww) 2*(xy-zw) 2*(xz+yw) 0 + 2*(xy+zw) (-xx+yy-zz+ww) 2*(yz-xw) 0 + 2*(xz-yw) 2*(yz+xw) (-xx-yy+zz+ww) 0 + 0 0 0 1]; +return; + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/decode_qform0.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/decode_qform0.m new file mode 100644 index 0000000..08ba046 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/decode_qform0.m @@ -0,0 +1,65 @@ +function M = decode_qform0(hdr) +% Decode qform info from NIFTI-1 headers. +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: decode_qform0.m 3131 2009-05-18 15:54:10Z guillaume + +% +% niftilib $Id: decode_qform0.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + +dim = double(hdr.dim); +pixdim = double(hdr.pixdim); +if ~isfield(hdr,'magic') || hdr.qform_code <= 0, + flp = spm_flip_analyze_images; + %disp('------------------------------------------------------'); + %disp('The images are in a form whereby it is not possible to'); + %disp('tell the left and right sides of the brain apart.'); + %if flp, + % disp('They are assumed to be stored left-handed.'); + %else + % disp('They are assumed to be stored right-handed.'); + %end; + %disp('------------------------------------------------------'); + + %R = eye(4); + n = min(dim(1),3); + vox = [pixdim(2:(n+1)) ones(1,3-n)]; + + if ~isfield(hdr,'origin') || ~any(hdr.origin(1:3)), + origin = (dim(2:4)+1)/2; + else + origin = double(hdr.origin(1:3)); + end; + off = -vox.*origin; + M = [vox(1) 0 0 off(1) ; 0 vox(2) 0 off(2) ; 0 0 vox(3) off(3) ; 0 0 0 1]; + + % Stuff for default orientations + if flp, M = diag([-1 1 1 1])*M; end; +else + + % Rotations from quaternions + R = Q2M(double([hdr.quatern_b hdr.quatern_c hdr.quatern_d])); + + % Translations + T = [eye(4,3) double([hdr.qoffset_x hdr.qoffset_y hdr.qoffset_z 1]')]; + + % Zooms. Note that flips are derived from the first + % element of pixdim, which is normally unused. + n = min(dim(1),3); + Z = [pixdim(2:(n+1)) ones(1,4-n)]; + Z(Z<0) = 1; + if pixdim(1)<0, Z(3) = -Z(3); end; + Z = diag(Z); + + M = T*R*Z; + + % Convert from first voxel at [1,1,1] + % to first voxel at [0,0,0] + M = M * [eye(4,3) [-1 -1 -1 1]']; +end; +return; + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/empty_hdr.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/empty_hdr.m new file mode 100644 index 0000000..db26933 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/empty_hdr.m @@ -0,0 +1,20 @@ +function hdr = empty_hdr +% Create an empty NIFTI-1 header +% FORMAT hdr = empty_hdr +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: empty_hdr.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: empty_hdr.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +org = niftistruc; +for i=1:length(org), + hdr.(org(i).label) = org(i).def; +end; + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/encode_qform0.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/encode_qform0.m new file mode 100644 index 0000000..7649ed6 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/encode_qform0.m @@ -0,0 +1,50 @@ +function hdr = encode_qform0(M,hdr) +% Encode an affine transform into qform +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: encode_qform0.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: encode_qform0.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +% Convert from first voxel at [1,1,1] to first voxel at [0,0,0] +M = M * [eye(4,3) [1 1 1 1]']; + +% Translations +hdr.qoffset_x = M(1,4); +hdr.qoffset_y = M(2,4); +hdr.qoffset_z = M(3,4); + +% Rotations and zooms +R = M(1:3,1:3); +vx = sqrt(sum(M(1:3,1:3).^2)); +vx(vx==0) = 1; +R = R * diag(1./vx); + +% Ensure that R is O(3) +[U,S,V] = svd(R); +R = U*V'; +if any(abs(diag(S)-1)>1e-3), warning('QFORM0 representation has been rounded.'); end; + +% Ensure that R is SO(3) +if det(R)>0 + hdr.pixdim(1:4) = [ 1 vx]; +else + R = R*diag([1 1 -1]); + hdr.pixdim(1:4) = [-1 vx]; +end; + +% Convert to quaternions +Q = M2Q(R); +hdr.quatern_b = Q(1); +hdr.quatern_c = Q(2); +hdr.quatern_d = Q(3); + +if hdr.qform_code == 0, hdr.qform_code = 2; end; +return; + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/findindict.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/findindict.m new file mode 100644 index 0000000..7fd41d9 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/findindict.m @@ -0,0 +1,42 @@ +function entry = findindict(c,dcode) +% Look up an entry in the dictionary +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: findindict.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: findindict.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +entry = []; +d = getdict; +d = d.(dcode); +if ischar(c) + for i=1:length(d), + if strcmpi(d(i).label,c), + entry = d(i); + break; + end; + end; +elseif isnumeric(c) && numel(c)==1 + for i=1:length(d), + if d(i).code==c, + entry = d(i); + break; + end; + end; +else + error(['Inappropriate code for ' dcode '.']); +end; +if isempty(entry) + fprintf('\nThis is not an option. Try one of these:\n'); + for i=1:length(d) + fprintf('%5d) %s\n', d(i).code, d(i).label); + end; + %fprintf('\nNO CHANGES MADE\n'); +end; + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/getdict.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/getdict.m new file mode 100644 index 0000000..acdfa4d --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/getdict.m @@ -0,0 +1,158 @@ +function d = getdict +% Dictionary of NIFTI stuff +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: getdict.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: getdict.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +persistent dict; +if ~isempty(dict), + d = dict; + return; +end; + +% Datatype +t = true; +f = false; +table = {... + 0 ,'UNKNOWN' ,'uint8' ,@uint8 ,1,1 ,t,t,f + 1 ,'BINARY' ,'uint1' ,@logical,1,1/8,t,t,f + 256 ,'INT8' ,'int8' ,@int8 ,1,1 ,t,f,t + 2 ,'UINT8' ,'uint8' ,@uint8 ,1,1 ,t,t,t + 4 ,'INT16' ,'int16' ,@int16 ,1,2 ,t,f,t + 512 ,'UINT16' ,'uint16' ,@uint16 ,1,2 ,t,t,t + 8 ,'INT32' ,'int32' ,@int32 ,1,4 ,t,f,t + 768 ,'UINT32' ,'uint32' ,@uint32 ,1,4 ,t,t,t + 1024,'INT64' ,'int64' ,@int64 ,1,8 ,t,f,f + 1280,'UINT64' ,'uint64' ,@uint64 ,1,8 ,t,t,f + 16 ,'FLOAT32' ,'float32' ,@single ,1,4 ,f,f,t + 64 ,'FLOAT64' ,'double' ,@double ,1,8 ,f,f,t + 1536,'FLOAT128' ,'float128',@crash ,1,16 ,f,f,f + 32 ,'COMPLEX64' ,'float32' ,@single ,2,4 ,f,f,f + 1792,'COMPLEX128','double' ,@double ,2,8 ,f,f,f + 2048,'COMPLEX256','float128',@crash ,2,16 ,f,f,f + 128 ,'RGB24' ,'uint8' ,@uint8 ,3,1 ,t,t,f}; + +dtype = struct(... + 'code' ,table(:,1),... + 'label' ,table(:,2),... + 'prec' ,table(:,3),... + 'conv' ,table(:,4),... + 'nelem' ,table(:,5),... + 'size' ,table(:,6),... + 'isint' ,table(:,7),... + 'unsigned' ,table(:,8),... + 'min',-Inf,'max',Inf',... + 'supported',table(:,9)); +for i=1:length(dtype), + if dtype(i).isint + if dtype(i).unsigned + dtype(i).min = 0; + dtype(i).max = 2^(8*dtype(i).size)-1; + else + dtype(i).min = -2^(8*dtype(i).size-1); + dtype(i).max = 2^(8*dtype(i).size-1)-1; + end; + end; +end; +% Intent +table = {... + 0 ,'NONE' ,'None',{} + 2 ,'CORREL' ,'Correlation statistic',{'DOF'} + 3 ,'TTEST' ,'T-statistic',{'DOF'} + 4 ,'FTEST' ,'F-statistic',{'numerator DOF','denominator DOF'} + 5 ,'ZSCORE' ,'Z-score',{} + 6 ,'CHISQ' ,'Chi-squared distribution',{'DOF'} + 7 ,'BETA' ,'Beta distribution',{'a','b'} + 8 ,'BINOM' ,'Binomial distribution',... + {'number of trials','probability per trial'} + 9 ,'GAMMA' ,'Gamma distribution',{'shape','scale'} + 10 ,'POISSON' ,'Poisson distribution',{'mean'} + 11 ,'NORMAL' ,'Normal distribution',{'mean','standard deviation'} + 12 ,'FTEST_NONC' ,'F-statistic noncentral',... + {'numerator DOF','denominator DOF','numerator noncentrality parameter'} + 13 ,'CHISQ_NONC' ,'Chi-squared noncentral',{'DOF','noncentrality parameter'} + 14 ,'LOGISTIC' ,'Logistic distribution',{'location','scale'} + 15 ,'LAPLACE' ,'Laplace distribution',{'location','scale'} + 16 ,'UNIFORM' ,'Uniform distribition',{'lower end','upper end'} + 17 ,'TTEST_NONC' ,'T-statistic noncentral',{'DOF','noncentrality parameter'} + 18 ,'WEIBULL' ,'Weibull distribution',{'location','scale','power'} + 19 ,'CHI' ,'Chi distribution',{'DOF'} + 20 ,'INVGAUSS' ,'Inverse Gaussian distribution',{'mu','lambda'} + 21 ,'EXTVAL' ,'Extreme Value distribution',{'location','scale'} + 22 ,'PVAL' ,'P-value',{} + 23 ,'LOGPVAL' ,'Log P-value',{} + 24 ,'LOG10PVAL' ,'Log_10 P-value',{} + 1001,'ESTIMATE' ,'Estimate',{} + 1002,'LABEL' ,'Label index',{} + 1003,'NEURONAMES' ,'NeuroNames index',{} + 1004,'MATRIX' ,'General matrix',{'M','N'} + 1005,'MATRIX_SYM' ,'Symmetric matrix',{} + 1006,'DISPLACEMENT' ,'Displacement vector',{} + 1007,'VECTOR' ,'Vector',{} + 1008,'POINTS' ,'Pointset',{} + 1009,'TRIANGLE' ,'Triangle',{} + 1010,'QUATERNION' ,'Quaternion',{} + 1011,'DIMLESS' ,'Dimensionless',{} +}; +intent = struct('code',table(:,1),'label',table(:,2),... + 'fullname',table(:,3),'param',table(:,4)); + +% Units +table = {... + 0, 1,'UNKNOWN' + 1,1000,'m' + 2, 1,'mm' + 3,1e-3,'um' + 8, 1,'s' + 16,1e-3,'ms' + 24,1e-6,'us' + 32, 1,'Hz' + 40, 1,'ppm' + 48, 1,'rads'}; +units = struct('code',table(:,1),'label',table(:,3),'rescale',table(:,2)); + +% Reference space +% code = {0,1,2,3,4}; +table = {... + 0,'UNKNOWN' + 1,'Scanner Anat' + 2,'Aligned Anat' + 3,'Talairach' + 4,'MNI_152'}; +anat = struct('code',table(:,1),'label',table(:,2)); + +% Slice Ordering +table = {... + 0,'UNKNOWN' + 1,'sequential_increasing' + 2,'sequential_decreasing' + 3,'alternating_increasing' + 4,'alternating_decreasing'}; +sliceorder = struct('code',table(:,1),'label',table(:,2)); + +% Q/S Form Interpretation +table = {... + 0,'UNKNOWN' + 1,'Scanner' + 2,'Aligned' + 3,'Talairach' + 4,'MNI152'}; +xform = struct('code',table(:,1),'label',table(:,2)); + +dict = struct('dtype',dtype,'intent',intent,'units',units,... + 'space',anat,'sliceorder',sliceorder,'xform',xform); + +d = dict; +return; + +function varargout = crash(varargin) +error('There is a NIFTI-1 data format problem (an invalid datatype).'); + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/mayo2nifti1.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/mayo2nifti1.m new file mode 100644 index 0000000..6c18e8e --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/mayo2nifti1.m @@ -0,0 +1,72 @@ +function hdr = mayo2nifti1(ohdr,mat) +% Convert from an ANALYZE to a NIFTI-1 header +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: mayo2nifti1.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: mayo2nifti1.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +if isfield(ohdr,'magic'), + hdr = ohdr; + return; +end; +hdr = empty_hdr; +hdr.dim = ohdr.dim; +hdr.datatype = ohdr.datatype; +hdr.bitpix = ohdr.bitpix; +hdr.pixdim = ohdr.pixdim; +hdr.vox_offset = ohdr.vox_offset; +hdr.scl_slope = ohdr.roi_scale; +hdr.scl_inter = ohdr.funused1; +hdr.descrip = ohdr.descrip; +hdr.aux_file = ohdr.aux_file; +hdr.glmax = ohdr.glmax; +hdr.glmin = ohdr.glmin; +hdr.cal_max = ohdr.cal_max; +hdr.cal_min = ohdr.cal_min; +hdr.magic = 'ni1'; + +switch hdr.datatype, +case 130, hdr.datatype = 256; % int8 +case 132, hdr.datatype = 512; % uint16 +case 136, hdr.datatype = 768; % uint32 +end; + +if nargin<2, + % No mat, so create the equivalent from the hdr... + if any(ohdr.origin(1:3)), origin = double(ohdr.origin(1:3)); + else origin = (double(ohdr.dim(2:4))+1)/2; end; + vox = double(ohdr.pixdim(2:4)); + if vox(1)<0, + % Assume FSL orientation + flp = 0; + else + % Assume SPM or proper Analyze + flp = spm_flip_analyze_images; + end; + if all(vox == 0), vox = [1 1 1]; end; + off = -vox.*origin; + mat = [vox(1) 0 0 off(1) ; 0 vox(2) 0 off(2) ; 0 0 vox(3) off(3) ; 0 0 0 1]; + if flp, + %disp(['Assuming that image is stored left-handed']); + mat = diag([-1 1 1 1])*mat; + else + %disp(['Assuming that image is stored right-handed']); + end; +end; + +hdr = encode_qform0(mat,hdr); +mat = mat*[eye(4,3) [1 1 1 1]']; +hdr.srow_x = mat(1,:); +hdr.srow_y = mat(2,:); +hdr.srow_z = mat(3,:); +hdr.qform_code = 2; +hdr.sform_code = 2; +return; + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/mayostruc.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/mayostruc.m new file mode 100644 index 0000000..e18578d --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/mayostruc.m @@ -0,0 +1,85 @@ +function o = mayostruc +% Create a data structure describing Analyze headers +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: mayostruc.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: mayostruc.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +persistent org; +if ~isempty(org), + o = org; + return; +end; +t = struct('conv',{ @char, @int16, @int32, @single },... + 'prec',{'uint8','int16','int32','single'},... + 'size',{ 1, 2, 4, 4}); +c = t(1); +s = t(2); +i = t(3); +f = t(4); +table = {... + i, 1,'sizeof_hdr',348 + c,10,'data_type',[] + c,18,'db_name',[] + i, 1,'extents',[] + s, 1,'session_error',[] + c, 1,'regular','r' + c, 1,'hkey_un0',[] + s, 8,'dim',[3 1 1 1 1 1 1 1 1] + c, 4,'vox_units',[] + c, 8,'cal_units',[] + s, 1,'unused1',[] + s, 1,'datatype',[] + s, 1,'bitpix',[] + s, 1,'dim_un0',[] + f, 8,'pixdim',[] + f, 1,'vox_offset',0 + f, 1,'roi_scale',1 + f, 1,'funused1',0 + f, 1,'funused2',[] + f, 1,'cal_max',[] + f, 1,'cal_min',[] + i, 1,'compressed',[] + i, 1,'verified',[] + i, 1,'glmax',[] + i, 1,'glmin',[] + c,80,'descrip','Analyze Image' + c,24,'aux_file','' + c, 1,'orient',[] +% c,10,'originator',[] + s, 5,'origin',[] % SPM version + c,10,'generated',[] + c,10,'scannum',[] + c,10,'patient_id',[] + c,10,'exp_date',[] + c,10,'exp_time',[] + c, 3,'hist_un0',[] + i, 1,'views',[] + i, 1,'vols_added',[] + i, 1,'start_field',[] + i, 1,'field_skip',[] + i, 1,'omax',[] + i, 1,'omin',[] + i, 1,'smax',[] + i, 1,'smin',[]}; +org = struct('label',table(:,3),'dtype',table(:,1),'len',table(:,2),... + 'offset',0,'def',table(:,4)); +os = 0; +for j=1:length(org) + os = os + org(j).dtype.size*ceil(os/org(j).dtype.size); + fun = org(j).dtype.conv; + def = [org(j).def zeros(1,org(j).len-length(org(j).def))]; + org(j).def = feval(fun,def); + org(j).offset = os; + os = os + org(j).len*org(j).dtype.size; +end; +o = org; +return; + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/nifti_stats.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/nifti_stats.m new file mode 100644 index 0000000..975f1af --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/nifti_stats.m @@ -0,0 +1,46 @@ +function varargout = nifti_stats(varargin) +% Conversion among various statistics +% FORMAT P = nifti_stats(VAL,CODE,OPT,PARAM) +% CODE can be one of +% 'CORREL' 'TTEST' 'FTEST' 'ZSCORE' +% 'CHISQ' 'BETA' 'BINOM' 'GAMMA' +% 'POISSON' 'NORMAL' 'FTEST_NONC' 'CHISQ_NONC' +% 'LOGISTIC' 'LAPLACE' 'UNIFORM' 'TTEST_NONC' +% 'WEIBULL' 'CHI' 'INVGAUSS' 'EXTVAL' +% 'PVAL' +% With only one input argument, CODE defaults to 'ZSCORE' +% +% OPT can be one of +% '-p' ==> output P = Prob(statistic < VAL). +% '-q' ==> output is 1-p. +% '-d' ==> output is probability density. +% '-1' ==> output is X such that Prob(statistic < x) = VAL. +% '-z' ==> output is Z such that Normal cdf(Z) = p(VAL). +% '-h' ==> output is Z such that 1/2-Normal cdf(Z) = p(VAL). +% With less than three input arguments, OPT defaults to '-p'. +% +% PARAM are up to three distribution parameters. +% These default to zero if unspecified. +% +% P is an array with the same dimensions as VAL. +% +%_______________________________________________________________________ +% 99.99% of the work by RW Cox - SSCC/NIMH/NIH/DHHS/USA/EARTH - March 2004 +% 0.01% of the work (the mex wrapper) by John Ashburner - FIL/ION/UCL +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: nifti_stats.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: nifti_stats.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +fprintf('******************************************\n'); +fprintf('Compile the nifti_stats function with\n'); +fprintf(' mex nifti_stats.c nifti_stats_mex.c -O\n'); +fprintf('******************************************\n'); + +error('nifti_stats is not compiled.'); diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/niftistruc.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/niftistruc.m new file mode 100644 index 0000000..38dd127 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/niftistruc.m @@ -0,0 +1,86 @@ +function o = niftistruc +% Create a data structure describing NIFTI headers +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: niftistruc.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: niftistruc.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +persistent org; +if ~isempty(org), + o = org; + return; +end; +t = struct('conv',{ @char , @uint8 , @int16 , @int32 , @single },... + 'prec',{'uint8', 'uint8', 'int16', 'int32', 'single'},... + 'size',{ 1, 1, 2, 4, 4 }); +c = t(1); +b = t(2); +s = t(3); +i = t(4); +f = t(5); + +table = {... + i, 1,'sizeof_hdr',348 + c,10,'data_type',[] + c,18,'db_name',[] + i, 1,'extents',[] + s, 1,'session_error',[] + c, 1,'regular','r' + b, 1,'dim_info',[] + s, 8,'dim',[3 0 0 0 1 1 1 1 1] + f, 1,'intent_p1',0 + f, 1,'intent_p2',0 + f, 1,'intent_p3',0 + s, 1,'intent_code',0 + s, 1,'datatype',2 + s, 1,'bitpix',8 + s, 1,'slice_start',[] + f, 8,'pixdim',[0 1 1 1] + f, 1,'vox_offset',0 + f, 1,'scl_slope',1 + f, 1,'scl_inter',0 + s, 1,'slice_end',[] + b, 1,'slice_code',[] + b, 1,'xyzt_units',10 + f, 1,'cal_max',[] + f, 1,'cal_min',[] + f, 1,'slice_duration',[] + f, 1,'toffset',[] + i, 1,'glmax',[] + i, 1,'glmin',[] + c,80,'descrip','NIFTI-1 Image' + c,24,'aux_file','' + s, 1,'qform_code',0 + s, 1,'sform_code',0 + f, 1,'quatern_b',0 + f, 1,'quatern_c',0 + f, 1,'quatern_d',0 + f, 1,'qoffset_x',0 + f, 1,'qoffset_y',0 + f, 1,'qoffset_z',0 + f, 4,'srow_x',[1 0 0 0] + f, 4,'srow_y',[0 1 0 0] + f, 4,'srow_z',[0 0 1 0] + c,16,'intent_name','' + c, 4,'magic','ni1'}; +org = struct('label',table(:,3),'dtype',table(:,1),'len',table(:,2),... + 'offset',0,'def',table(:,4)); +os = 0; +for j=1:length(org) + os = os + org(j).dtype.size*ceil(os/org(j).dtype.size); + fun = org(j).dtype.conv; + def = [org(j).def zeros(1,org(j).len-length(org(j).def))]; + org(j).def = feval(fun,def); + org(j).offset = os; + os = os + org(j).len*org(j).dtype.size; +end; +o = org; +return; + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/read_extras.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/read_extras.m new file mode 100644 index 0000000..5047979 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/read_extras.m @@ -0,0 +1,32 @@ +function extras = read_extras(fname) +% Read extra bits of information +%_______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: read_extras.m 2237 2008-09-29 17:39:53Z guillaume + +% +% niftilib $Id: read_extras.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +extras = struct; +[pth,nam,ext] = fileparts(fname); +switch ext +case {'.hdr','.img','.nii'} + mname = fullfile(pth,[nam '.mat']); +case {'.HDR','.IMG','.NII'} + mname = fullfile(pth,[nam '.MAT']); +otherwise + mname = fullfile(pth,[nam '.mat']); +end + +if spm_existfile(mname), + try, + extras = load(mname); + catch, + warning('Can not load "%s" as a binary MAT file.\n', mname); + end; +end; diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/read_hdr.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/read_hdr.m new file mode 100644 index 0000000..e25c949 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/read_hdr.m @@ -0,0 +1,90 @@ +function vol = read_hdr(fname) +% Get a variety of information from a NIFTI-1 header. +% FORMAT vol = read_hdr(fname) +% fname - filename of image +% vol - various bits of information +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: read_hdr.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: read_hdr.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +persistent d +if isempty(d), d = getdict; end; + +[pth,nam,ext,num] = spm_fileparts(fname); +switch ext +case '.hdr' + hname = fullfile(pth,[nam '.hdr']); +case '.HDR' + hname = fullfile(pth,[nam '.HDR']); +case '.img' + hname = fullfile(pth,[nam '.hdr']); +case '.IMG' + hname = fullfile(pth,[nam '.HDR']); +case '.nii' + hname = fullfile(pth,[nam '.nii']); +case '.NII' + hname = fullfile(pth,[nam '.NII']); +otherwise + hname = fullfile(pth,[nam ext]); +end +[hdr,be] = read_hdr_raw(hname); +if isempty(hdr) + error(['Error reading header file "' hname '"']); +end; + +if ~isfield(hdr,'magic'), + % A patch for some possible SPM2 datatypes + switch hdr.datatype, + case 130, hdr.datatype = 256; % int8 + case 132, hdr.datatype = 512; % uint16 + case 136, hdr.datatype = 768; % uint32 + end; +end; + +dt = []; +for i=1:length(d.dtype) + if hdr.datatype == d.dtype(i).code + dt = d.dtype(i); + break; + end; +end; +if isempty(dt) + error(['Unrecognised datatype (' num2str(double(hdr.datatype)) ') for "' fname '.'] ); +end +if isfield(hdr,'magic') + switch deblank(hdr.magic) + case {'n+1'} + iname = hname; + if hdr.vox_offset < hdr.sizeof_hdr + error(['Bad vox_offset (' num2str(double(hdr.vox_offset)) ') for "' fname '.'] ); + end + case {'ni1'} + if strcmp(ext,lower(ext)), + iname = fullfile(pth,[nam '.img']); + else + iname = fullfile(pth,[nam '.IMG']); + end; + otherwise + error(['Bad magic (' hdr.magic ') for "' fname '.'] ); + end +else + if strcmp(ext,lower(ext)), + iname = fullfile(pth,[nam '.img']); + else + iname = fullfile(pth,[nam '.IMG']); + end; +end +if rem(double(hdr.vox_offset),dt.size) + error(['Bad alignment of voxels (' num2str(double(hdr.vox_offset)) '/' num2str(double(dt.size)) ') for "' fname '.'] ); +end; + +vol = struct('hdr',hdr,'be',be,'hname',hname,'iname',iname); +return diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/read_hdr_raw.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/read_hdr_raw.m new file mode 100644 index 0000000..ff0d501 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/read_hdr_raw.m @@ -0,0 +1,98 @@ +function [hdr,be] = read_hdr_raw(fname) +% Read a NIFTI-1 hdr file +% FORMAT [hdr,be] = read_hdr_raw(fname) +% fname - filename of image +% hdr - a structure containing hdr info +% be - whether big-endian or not +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: read_hdr_raw.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: read_hdr_raw.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +hdr = []; +be = []; +ok = true; + +% Name of header file +[pth,nam,ext] = fileparts(fname); +switch ext +case {'.img','.hdr'} + hname = fullfile(pth,[nam '.hdr']); +case {'.nii'} + hname = fullfile(pth,[nam '.nii']); +otherwise + hname = fullfile(pth,[nam '.hdr']); +end; + +% Open it if possible +fp = fopen(hname,'r','native'); +if fp==-1 + hdr = []; + return; +end; + +% Sort out endian issues of header +[unused,unused,mach] = fopen(fp); +if strcmp(mach,'ieee-be') || strcmp(mach,'ieee-be.l64') + be = true; +else + be = false; +end; +fseek(fp,0,'bof'); +fseek(fp,40,'bof'); +nd = fread(fp,1,'int16')'; +if isempty(nd), + fclose(fp); + hdr = []; + return; +elseif nd<1 || nd>7 + be = ~be; + fclose(fp); + if be, mach = 'ieee-be'; + else mach = 'ieee-le'; + end; + fp = fopen(hname,'r',mach); + if fp==-1 + hdr = []; + return; + end; +end; + +% Is it NIFTI or not +fseek(fp,0,'bof'); +fseek(fp,344,'bof'); +mgc = deblank(char(fread(fp,4,'uint8')')); +switch mgc +case {'ni1','n+1'} + org = niftistruc; +otherwise + org = mayostruc; +end; +fseek(fp,0,'bof'); +% Read the fields +for i=1:length(org) + tmp = fread(fp,org(i).len,['*' org(i).dtype.prec])'; + if length(tmp) ~= org(i).len +disp([length(tmp) org(i).len]); + tmp = org(i).def; + ok = false; + end; + tmp = feval(org(i).dtype.conv,tmp); + hdr.(org(i).label) = tmp; +end; + +fclose(fp); +if ~ok, + fprintf('There was a problem reading the header of\n'); + fprintf('"%s".\n', fname); + fprintf('It may be corrupted in some way.'); +end; +return; + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/spm_existfile.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/spm_existfile.m new file mode 100644 index 0000000..c3008e1 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/spm_existfile.m @@ -0,0 +1,33 @@ +function s = spm_existfile(filename) +% Check if a file exists on disk - a compiled routine +% FORMAT S = SPM_EXISTFILE(FILENAME) +% FILENAME - filename (can also be a relative or full pathname to a file) +% S - logical scalar, true if the file exists and false otherwise +%_______________________________________________________________________ +% +% This compiled routine is equivalent to: +% >> s = exist(filename,'file') == 2; +% and was written for speed purposes. The differences in behaviour are: +% * spm_existfile returns true for directory names +% * spm_existfile does not look in MATLAB's search path +% * spm_existfile returns false for an existing file that does not have +% read permission +%_______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% Guillaume Flandin +% $Id: spm_existfile.m,v 1.1 2012/03/22 18:36:33 fissell Exp $ + + +%-This is merely the help file for the compiled routine +%error('spm_existfile.c not compiled - see Makefile') +%persistent runonce +%if isempty(runonce) +% warning('spm_existfile is not compiled for your platform.'); +% runonce = 1; +%end + +%s = exist(filename,'file') > 0; + +% KF replace compiled version with almost equivalent matlab call +s = exist(filename,'file') == 2; diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/spm_fileparts.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/spm_fileparts.m new file mode 100644 index 0000000..26029f1 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/spm_fileparts.m @@ -0,0 +1,26 @@ +function [pth,nam,ext,num] = spm_fileparts(fname) +% Like fileparts, but separates off a comma separated list at the end +% FORMAT [pth,nam,ext,num] = spm_fileparts(fname) +% fname - original filename +% pth - path +% nam - filename +% ext - extension +% num - comma separated list of values +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% John Ashburner +% Id: spm_fileparts.m 4205 2011-02-21 15:39:08Z guillaume + +% +% niftilib $Id: spm_fileparts.m,v 1.1 2012/03/22 18:36:33 fissell Exp $ +% + + +num = ''; +[pth,nam,ext] = fileparts(fname); +ind = find(ext==','); +if ~isempty(ind) + num = ext(ind(1):end); + ext = ext(1:(ind(1)-1)); +end diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/README b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/README new file mode 100644 index 0000000..155b63d --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/README @@ -0,0 +1,17 @@ +/* + * This is a Matlab mex interface for Bob Cox's extensive nifti_stats.c + * functionality. See nifti_stats.m for documentation. + */ + + +To compile on a big-endian machine + mex -DBIGENDIAN nifti_stats.c nifti_stats_mex.c -O + +On a little-endian machine + mex nifti_stats.c nifti_stats_mex.c -O + +On a Windows machine + mex -O -DSPM_WIN32 nifti_stats.c nifti_stats_mex.c + + +mv the .mex* file up one level to the private dir diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/nifti1.h b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/nifti1.h new file mode 100644 index 0000000..4e30c0c --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/nifti1.h @@ -0,0 +1,1227 @@ +#ifndef _NIFTI_HEADER_ +#define _NIFTI_HEADER_ + +/***************************************************************************** + ** This file defines the "NIFTI-1" header format. ** + ** It is derived from 2 meetings at the NIH (31 Mar 2003 and ** + ** 02 Sep 2003) of the Data Format Working Group (DFWG), ** + ** chartered by the NIfTI (Neuroimaging Informatics Technology ** + ** Initiative) at the National Institutes of Health (NIH). ** + **--------------------------------------------------------------** + ** Neither the National Institutes of Health (NIH), the DFWG, ** + ** nor any of the members or employees of these institutions ** + ** imply any warranty of usefulness of this material for any ** + ** purpose, and do not assume any liability for damages, ** + ** incidental or otherwise, caused by any use of this document. ** + ** If these conditions are not acceptable, do not use this! ** + **--------------------------------------------------------------** + ** Author: Robert W Cox (NIMH, Bethesda) ** + ** Advisors: John Ashburner (FIL, London), ** + ** Stephen Smith (FMRIB, Oxford), ** + ** Mark Jenkinson (FMRIB, Oxford) ** +******************************************************************************/ + + +/* + * niftilib $Id: nifti1.h,v 1.1 2012/03/22 18:36:33 fissell Exp $ + */ + +/*---------------------------------------------------------------------------*/ +/* Note that the ANALYZE 7.5 file header (dbh.h) is + (c) Copyright 1986-1995 + Biomedical Imaging Resource + Mayo Foundation + Incorporation of components of dbh.h are by permission of the + Mayo Foundation. + + Changes from the ANALYZE 7.5 file header in this file are released to the + public domain, including the functional comments and any amusing asides. +-----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/*! INTRODUCTION TO NIFTI-1: + ------------------------ + The twin (and somewhat conflicting) goals of this modified ANALYZE 7.5 + format are: + (a) To add information to the header that will be useful for functional + neuroimaging data analysis and display. These additions include: + - More basic data types. + - Two affine transformations to specify voxel coordinates. + - "Intent" codes and parameters to describe the meaning of the data. + - Affine scaling of the stored data values to their "true" values. + - Optional storage of the header and image data in one file (.nii). + (b) To maintain compatibility with non-NIFTI-aware ANALYZE 7.5 compatible + software (i.e., such a program should be able to do something useful + with a NIFTI-1 dataset -- at least, with one stored in a traditional + .img/.hdr file pair). + + Most of the unused fields in the ANALYZE 7.5 header have been taken, + and some of the lesser-used fields have been co-opted for other purposes. + Notably, most of the data_history substructure has been co-opted for + other purposes, since the ANALYZE 7.5 format describes this substructure + as "not required". + + NIFTI-1 FLAG (MAGIC STRINGS): + ---------------------------- + To flag such a struct as being conformant to the NIFTI-1 spec, the last 4 + bytes of the header must be either the C String "ni1" or "n+1"; + in hexadecimal, the 4 bytes + 6E 69 31 00 or 6E 2B 31 00 + (in any future version of this format, the '1' will be upgraded to '2', + etc.). Normally, such a "magic number" or flag goes at the start of the + file, but trying to avoid clobbering widely-used ANALYZE 7.5 fields led to + putting this marker last. However, recall that "the last shall be first" + (Matthew 20:16). + + If a NIFTI-aware program reads a header file that is NOT marked with a + NIFTI magic string, then it should treat the header as an ANALYZE 7.5 + structure. + + NIFTI-1 FILE STORAGE: + -------------------- + "ni1" means that the image data is stored in the ".img" file corresponding + to the header file (starting at file offset 0). + + "n+1" means that the image data is stored in the same file as the header + information. We recommend that the combined header+data filename suffix + be ".nii". When the dataset is stored in one file, the first byte of image + data is stored at byte location (int)vox_offset in this combined file. + + GRACE UNDER FIRE: + ---------------- + Most NIFTI-aware programs will only be able to handle a subset of the full + range of datasets possible with this format. All NIFTI-aware programs + should take care to check if an input dataset conforms to the program's + needs and expectations (e.g., check datatype, intent_code, etc.). If the + input dataset can't be handled by the program, the program should fail + gracefully (e.g., print a useful warning; not crash). + + SAMPLE CODES: + ------------ + The associated files nifti1_io.h and nifti1_io.c provide a sample + implementation in C of a set of functions to read, write, and manipulate + NIFTI-1 files. The file nifti1_test.c is a sample program that uses + the nifti1_io.c functions. +-----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* HEADER STRUCT DECLARATION: + ------------------------- + In the comments below for each field, only NIFTI-1 specific requirements + or changes from the ANALYZE 7.5 format are described. For convenience, + the 348 byte header is described as a single struct, rather than as the + ANALYZE 7.5 group of 3 substructs. + + Further comments about the interpretation of various elements of this + header are after the data type definition itself. Fields that are + marked as ++UNUSED++ have no particular interpretation in this standard. + (Also see the UNUSED FIELDS comment section, far below.) + + The presumption below is that the various C types have particular sizes: + sizeof(int) = sizeof(float) = 4 ; sizeof(short) = 2 +-----------------------------------------------------------------------------*/ + +/*=================*/ +#ifdef __cplusplus +extern "C" { +#endif +/*=================*/ + /*************************/ /************************/ +struct nifti_1_header { /* NIFTI-1 usage */ /* ANALYZE 7.5 field(s) */ + /*************************/ /************************/ + + /*--- was header_key substruct ---*/ + int sizeof_hdr; /*!< MUST be 348 */ /* int sizeof_hdr; */ + char data_type[10]; /*!< ++UNUSED++ */ /* char data_type[10]; */ + char db_name[18]; /*!< ++UNUSED++ */ /* char db_name[18]; */ + int extents; /*!< ++UNUSED++ */ /* int extents; */ + short session_error; /*!< ++UNUSED++ */ /* short session_error; */ + char regular; /*!< ++UNUSED++ */ /* char regular; */ + char dim_info; /*!< MRI slice ordering. */ /* char hkey_un0; */ + + /*--- was image_dimension substruct ---*/ + short dim[8]; /*!< Data array dimensions.*/ /* short dim[8]; */ + float intent_p1 ; /*!< 1st intent parameter. */ /* short unused8; */ + /* short unused9; */ + float intent_p2 ; /*!< 2nd intent parameter. */ /* short unused10; */ + /* short unused11; */ + float intent_p3 ; /*!< 3rd intent parameter. */ /* short unused12; */ + /* short unused13; */ + short intent_code ; /*!< NIFTI_INTENT_* code. */ /* short unused14; */ + short datatype; /*!< Defines data type! */ /* short datatype; */ + short bitpix; /*!< Number bits/voxel. */ /* short bitpix; */ + short slice_start; /*!< First slice index. */ /* short dim_un0; */ + float pixdim[8]; /*!< Grid spacings. */ /* float pixdim[8]; */ + float vox_offset; /*!< Offset into .nii file */ /* float vox_offset; */ + float scl_slope ; /*!< Data scaling: slope. */ /* float funused1; */ + float scl_inter ; /*!< Data scaling: offset. */ /* float funused2; */ + short slice_end; /*!< Last slice index. */ /* float funused3; */ + char slice_code ; /*!< Slice timing order. */ + char xyzt_units ; /*!< Units of pixdim[1..4] */ + float cal_max; /*!< Max display intensity */ /* float cal_max; */ + float cal_min; /*!< Min display intensity */ /* float cal_min; */ + float slice_duration;/*!< Time for 1 slice. */ /* float compressed; */ + float toffset; /*!< Time axis shift. */ /* float verified; */ + int glmax; /*!< ++UNUSED++ */ /* int glmax; */ + int glmin; /*!< ++UNUSED++ */ /* int glmin; */ + + /*--- was data_history substruct ---*/ + char descrip[80]; /*!< any text you like. */ /* char descrip[80]; */ + char aux_file[24]; /*!< auxiliary filename. */ /* char aux_file[24]; */ + + short qform_code ; /*!< NIFTI_XFORM_* code. */ /*-- all ANALYZE 7.5 ---*/ + short sform_code ; /*!< NIFTI_XFORM_* code. */ /* fields below here */ + /* are replaced */ + float quatern_b ; /*!< Quaternion b param. */ + float quatern_c ; /*!< Quaternion c param. */ + float quatern_d ; /*!< Quaternion d param. */ + float qoffset_x ; /*!< Quaternion x shift. */ + float qoffset_y ; /*!< Quaternion y shift. */ + float qoffset_z ; /*!< Quaternion z shift. */ + + float srow_x[4] ; /*!< 1st row affine transform. */ + float srow_y[4] ; /*!< 2nd row affine transform. */ + float srow_z[4] ; /*!< 3rd row affine transform. */ + + char intent_name[16];/*!< 'name' or meaning of data. */ + + char magic[4] ; /*!< MUST be "ni1\0" or "n+1\0". */ + +} ; /**** 348 bytes total ****/ + +typedef struct nifti_1_header nifti_1_header ; + +/*---------------------------------------------------------------------------*/ +/* DATA DIMENSIONALITY (as in ANALYZE 7.5): + --------------------------------------- + dim[0] = number of dimensions; + - if dim[0] is outside range 1..7, then the header information + needs to be byte swapped appropriately + - ANALYZE supports dim[0] up to 7, but NIFTI-1 reserves + dimensions 1,2,3 for space (x,y,z), 4 for time (t), and + 5,6,7 for anything else needed. + + dim[i] = length of dimension #i, for i=1..dim[0] (must be positive) + - also see the discussion of intent_code, far below + + pixdim[i] = voxel width along dimension #i, i=1..dim[0] (positive) + - cf. ORIENTATION section below for use of pixdim[0] + - the units of pixdim can be specified with the xyzt_units + field (also described far below). + + Number of bits per voxel value is in bitpix, which MUST correspond with + the datatype field. The total number of bytes in the image data is + dim[1] * ... * dim[dim[0]] * bitpix / 8 + + In NIFTI-1 files, dimensions 1,2,3 are for space, dimension 4 is for time, + and dimension 5 is for storing multiple values at each spatiotemporal + voxel. Some examples: + - A typical whole-brain FMRI experiment's time series: + - dim[0] = 4 + - dim[1] = 64 pixdim[1] = 3.75 xyzt_units = NIFTI_UNITS_MM + - dim[2] = 64 pixdim[2] = 3.75 | NIFTI_UNITS_SEC + - dim[3] = 20 pixdim[3] = 5.0 + - dim[4] = 120 pixdim[4] = 2.0 + - A typical T1-weighted anatomical volume: + - dim[0] = 3 + - dim[1] = 256 pixdim[1] = 1.0 xyzt_units = NIFTI_UNITS_MM + - dim[2] = 256 pixdim[2] = 1.0 + - dim[3] = 128 pixdim[3] = 1.1 + - A single slice EPI time series: + - dim[0] = 4 + - dim[1] = 64 pixdim[1] = 3.75 xyzt_units = NIFTI_UNITS_MM + - dim[2] = 64 pixdim[2] = 3.75 | NIFTI_UNITS_SEC + - dim[3] = 1 pixdim[3] = 5.0 + - dim[4] = 1200 pixdim[4] = 0.2 + - A 3-vector stored at each point in a 3D volume: + - dim[0] = 5 + - dim[1] = 256 pixdim[1] = 1.0 xyzt_units = NIFTI_UNITS_MM + - dim[2] = 256 pixdim[2] = 1.0 + - dim[3] = 128 pixdim[3] = 1.1 + - dim[4] = 1 pixdim[4] = 0.0 + - dim[5] = 3 intent_code = NIFTI_INTENT_VECTOR + - A single time series with a 3x3 matrix at each point: + - dim[0] = 5 + - dim[1] = 1 xyzt_units = NIFTI_UNITS_SEC + - dim[2] = 1 + - dim[3] = 1 + - dim[4] = 1200 pixdim[4] = 0.2 + - dim[5] = 9 intent_code = NIFTI_INTENT_GENMATRIX + - intent_p1 = intent_p2 = 3.0 (indicates matrix dimensions) +-----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* DATA STORAGE: + ------------ + If the magic field is "n+1", then the voxel data is stored in the + same file as the header. In this case, the voxel data starts at offset + (int)vox_offset into the header file. Thus, vox_offset=348.0 means that + the data starts immediately after the NIFTI-1 header. If vox_offset is + greater than 348, the NIFTI-1 format does not say anything about the + contents of the dataset file between the end of the header and the + start of the data. + + FILES: + ----- + If the magic field is "ni1", then the voxel data is stored in the + associated ".img" file, starting at offset 0 (i.e., vox_offset is not + used in this case, and should be set to 0.0). + + When storing NIFTI-1 datasets in pairs of files, it is customary to name + the files in the pattern "name.hdr" and "name.img", as in ANALYZE 7.5. + When storing in a single file ("n+1"), the file name should be in + the form "name.nii" (the ".nft" and ".nif" suffixes are already taken; + cf. http://www.icdatamaster.com/n.html ). + + BYTE ORDERING: + ------------- + The byte order of the data arrays is presumed to be the same as the byte + order of the header (which is determined by examining dim[0]). + + Floating point types are presumed to be stored in IEEE-754 format. +-----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* DATA SCALING: + ------------ + If the scl_slope field is nonzero, then each voxel value in the dataset + should be scaled as + y = scl_slope * x + scl_inter + where x = voxel value stored + y = "true" voxel value + Normally, we would expect this scaling to be used to store "true" floating + values in a smaller integer datatype, but that is not required. That is, + it is legal to use scaling even if the datatype is a float type (crazy, + perhaps, but legal). + - However, the scaling is to be ignored if datatype is DT_RGB24. + - If datatype is a complex type, then the scaling is to be + applied to both the real and imaginary parts. + + The cal_min and cal_max fields (if nonzero) are used for mapping (possibly + scaled) dataset values to display colors: + - Minimum display intensity (black) corresponds to dataset value cal_min. + - Maximum display intensity (white) corresponds to dataset value cal_max. + - Dataset values below cal_min should display as black also, and values + above cal_max as white. + - Colors "black" and "white", of course, may refer to any scalar display + scheme (e.g., a color lookup table specified via aux_file). + - cal_min and cal_max only make sense when applied to scalar-valued + datasets (i.e., dim[0] < 5 or dim[5] = 1). +-----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* TYPE OF DATA (acceptable values for datatype field): + --------------------------------------------------- + Values of datatype smaller than 256 are ANALYZE 7.5 compatible. + Larger values are NIFTI-1 additions. These are all multiples of 256, so + that no bits below position 8 are set in datatype. But there is no need + to use only powers-of-2, as the original ANALYZE 7.5 datatype codes do. + + The additional codes are intended to include a complete list of basic + scalar types, including signed and unsigned integers from 8 to 64 bits, + floats from 32 to 128 bits, and complex (float pairs) from 64 to 256 bits. + + Note that most programs will support only a few of these datatypes! + A NIFTI-1 program should fail gracefully (e.g., print a warning message) + when it encounters a dataset with a type it doesn't like. +-----------------------------------------------------------------------------*/ + +#undef DT_UNKNOWN /* defined in dirent.h on some Unix systems */ + + /*--- the original ANALYZE 7.5 type codes ---*/ +#define DT_NONE 0 +#define DT_UNKNOWN 0 /* what it says, dude */ +#define DT_BINARY 1 /* binary (1 bit/voxel) */ +#define DT_UNSIGNED_CHAR 2 /* unsigned char (8 bits/voxel) */ +#define DT_SIGNED_SHORT 4 /* signed short (16 bits/voxel) */ +#define DT_SIGNED_INT 8 /* signed int (32 bits/voxel) */ +#define DT_FLOAT 16 /* float (32 bits/voxel) */ +#define DT_COMPLEX 32 /* complex (64 bits/voxel) */ +#define DT_DOUBLE 64 /* double (64 bits/voxel) */ +#define DT_RGB 128 /* RGB triple (24 bits/voxel) */ +#define DT_ALL 255 /* not very useful (?) */ + + /*----- another set of names for the same ---*/ +#define DT_UINT8 2 +#define DT_INT16 4 +#define DT_INT32 8 +#define DT_FLOAT32 16 +#define DT_COMPLEX64 32 +#define DT_FLOAT64 64 +#define DT_RGB24 128 + + /*------------------- new codes for NIFTI ---*/ +#define DT_INT8 256 /* signed char (8 bits) */ +#define DT_UINT16 512 /* unsigned short (16 bits) */ +#define DT_UINT32 768 /* unsigned int (32 bits) */ +#define DT_INT64 1024 /* long long (64 bits) */ +#define DT_UINT64 1280 /* unsigned long long (64 bits) */ +#define DT_FLOAT128 1536 /* long double (128 bits) */ +#define DT_COMPLEX128 1792 /* double pair (128 bits) */ +#define DT_COMPLEX256 2048 /* long double pair (256 bits) */ + + /*------- aliases for all the above codes ---*/ + + /*! unsigned char. */ +#define NIFTI_TYPE_UINT8 2 + /*! signed short. */ +#define NIFTI_TYPE_INT16 4 + /*! signed int. */ +#define NIFTI_TYPE_INT32 8 + /*! 32 bit float. */ +#define NIFTI_TYPE_FLOAT32 16 + /*! 64 bit complex = 2 32 bit floats. */ +#define NIFTI_TYPE_COMPLEX64 32 + /*! 64 bit float = double. */ +#define NIFTI_TYPE_FLOAT64 64 + /*! 3 8 bit bytes. */ +#define NIFTI_TYPE_RGB24 128 + /*! signed char. */ +#define NIFTI_TYPE_INT8 256 + /*! unsigned short. */ +#define NIFTI_TYPE_UINT16 512 + /*! unsigned int. */ +#define NIFTI_TYPE_UINT32 768 + /*! signed long long. */ +#define NIFTI_TYPE_INT64 1024 + /*! unsigned long long. */ +#define NIFTI_TYPE_UINT64 1280 + /*! 128 bit float = long double. */ +#define NIFTI_TYPE_FLOAT128 1536 + /*! 128 bit complex = 2 64 bit floats. */ +#define NIFTI_TYPE_COMPLEX128 1792 + /*! 256 bit complex = 2 128 bit floats */ +#define NIFTI_TYPE_COMPLEX256 2048 + + /*-------- sample typedefs for complicated types ---*/ +#if 0 +typedef struct { float r,i; } complex_float ; +typedef struct { double r,i; } complex_double ; +typedef struct { long double r,i; } complex_longdouble ; +typedef struct { unsigned char r,g,b; } rgb_byte ; +#endif + +/*---------------------------------------------------------------------------*/ +/* INTERPRETATION OF VOXEL DATA: + ---------------------------- + The intent_code field can be used to indicate that the voxel data has + some particular meaning. In particular, a large number of codes is + given to indicate that the the voxel data should be interpreted as + being drawn from a given probability distribution. + + VECTOR-VALUED DATASETS: + ---------------------- + The 5th dimension of the dataset, if present (i.e., dim[0]=5 and + dim[5] > 1), contains multiple values (e.g., a vector) to be stored + at each spatiotemporal location. For example, the header values + - dim[0] = 5 + - dim[1] = 64 + - dim[2] = 64 + - dim[3] = 20 + - dim[4] = 1 (indicates no time axis) + - dim[5] = 3 + - datatype = DT_FLOAT + - intent_code = NIFTI_INTENT_VECTOR + mean that this dataset should be interpreted as a 3D volume (64x64x20), + with a 3-vector of floats defined at each point in the 3D grid. + + A program reading a dataset with a 5th dimension may want to reformat + the image data to store each voxels' set of values together in a struct + or array. This programming detail, however, is beyond the scope of the + NIFTI-1 file specification! Uses of dimensions 6 and 7 are also not + specified here. + + STATISTICAL PARAMETRIC DATASETS (i.e., SPMs): + -------------------------------------------- + Values of intent_code from NIFTI_FIRST_STATCODE to NIFTI_LAST_STATCODE + (inclusive) indicate that the numbers in the dataset should be interpreted + as being drawn from a given distribution. Most such distributions have + auxiliary parameters (e.g., NIFTI_INTENT_TTEST has 1 DOF parameter). + + If the dataset DOES NOT have a 5th dimension, then the auxiliary parameters + are the same for each voxel, and are given in header fields intent_p1, + intent_p2, and intent_p3. + + If the dataset DOES have a 5th dimension, then the auxiliary parameters + are different for each voxel. For example, the header values + - dim[0] = 5 + - dim[1] = 128 + - dim[2] = 128 + - dim[3] = 1 (indicates a single slice) + - dim[4] = 1 (indicates no time axis) + - dim[5] = 2 + - datatype = DT_FLOAT + - intent_code = NIFTI_INTENT_TTEST + mean that this is a 2D dataset (128x128) of t-statistics, with the + t-statistic being in the first "plane" of data and the degrees-of-freedom + parameter being in the second "plane" of data. + + If the dataset 5th dimension is used to store the voxel-wise statistical + parameters, then dim[5] must be 1 plus the number of parameters required + by that distribution (e.g., intent_code=NIFTI_INTENT_TTEST implies dim[5] + must be 2, as in the example just above). + + Note: intent_code values 2..10 are compatible with AFNI 1.5x (which is + why there is no code with value=1, which is obsolescent in AFNI). + + OTHER INTENTIONS: + ---------------- + The purpose of the intent_* fields is to help interpret the values + stored in the dataset. Some non-statistical values for intent_code + and conventions are provided for storing other complex data types. + + The intent_name field provides space for a 15 character (plus 0 byte) + 'name' string for the type of data stored. Examples: + - intent_code = NIFTI_INTENT_ESTIMATE; intent_name = "T1"; + could be used to signify that the voxel values are estimates of the + NMR parameter T1. + - intent_code = NIFTI_INTENT_TTEST; intent_name = "House"; + could be used to signify that the voxel values are t-statistics + for the significance of 'activation' response to a House stimulus. + - intent_code = NIFTI_INTENT_DISPVECT; intent_name = "ToMNI152"; + could be used to signify that the voxel values are a displacement + vector that transforms each voxel (x,y,z) location to the + corresponding location in the MNI152 standard brain. + - intent_code = NIFTI_INTENT_SYMMATRIX; intent_name = "DTI"; + could be used to signify that the voxel values comprise a diffusion + tensor image. + + If no data name is implied or needed, intent_name[0] should be set to 0. +-----------------------------------------------------------------------------*/ + + /*! default: no intention is indicated in the header. */ + +#define NIFTI_INTENT_NONE 0 + + /*-------- These codes are for probability distributions ---------------*/ + /* Most distributions have a number of parameters, + below denoted by p1, p2, and p3, and stored in + - intent_p1, intent_p2, intent_p3 if dataset doesn't have 5th dimension + - image data array if dataset does have 5th dimension + + Functions to compute with many of the distributions below can be found + in the CDF library from U Texas. + + Formulas for and discussions of these distributions can be found in the + following books: + + [U] Univariate Discrete Distributions, + NL Johnson, S Kotz, AW Kemp. + + [C1] Continuous Univariate Distributions, vol. 1, + NL Johnson, S Kotz, N Balakrishnan. + + [C2] Continuous Univariate Distributions, vol. 2, + NL Johnson, S Kotz, N Balakrishnan. */ + /*----------------------------------------------------------------------*/ + + /*! [C2, chap 32] Correlation coefficient R (1 param): + p1 = degrees of freedom + R/sqrt(1-R*R) is t-distributed with p1 DOF. */ + +#define NIFTI_INTENT_CORREL 2 + + /*! [C2, chap 28] Student t statistic (1 param): p1 = DOF. */ + +#define NIFTI_INTENT_TTEST 3 + + /*! [C2, chap 27] Fisher F statistic (2 params): + p1 = numerator DOF, p2 = denominator DOF. */ + +#define NIFTI_INTENT_FTEST 4 + + /*! [C1, chap 13] Standard normal (0 params): Density = N(0,1). */ + +#define NIFTI_INTENT_ZSCORE 5 + + /*! [C1, chap 18] Chi-squared (1 param): p1 = DOF. + Density(x) proportional to exp(-x/2) * x^(p1/2-1). */ + +#define NIFTI_INTENT_CHISQ 6 + + /*! [C2, chap 25] Beta distribution (2 params): p1=a, p2=b. + Density(x) proportional to x^(a-1) * (1-x)^(b-1). */ + +#define NIFTI_INTENT_BETA 7 + + /*! [U, chap 3] Binomial distribution (2 params): + p1 = number of trials, p2 = probability per trial. + Prob(x) = (p1 choose x) * p2^x * (1-p2)^(p1-x), for x=0,1,...,p1. */ + +#define NIFTI_INTENT_BINOM 8 + + /*! [C1, chap 17] Gamma distribution (2 params): + p1 = shape, p2 = scale. + Density(x) proportional to x^(p1-1) * exp(-p2*x). */ + +#define NIFTI_INTENT_GAMMA 9 + + /*! [U, chap 4] Poisson distribution (1 param): p1 = mean. + Prob(x) = exp(-p1) * p1^x / x! , for x=0,1,2,.... */ + +#define NIFTI_INTENT_POISSON 10 + + /*! [C1, chap 13] Normal distribution (2 params): + p1 = mean, p2 = standard deviation. */ + +#define NIFTI_INTENT_NORMAL 11 + + /*! [C2, chap 30] Noncentral F statistic (3 params): + p1 = numerator DOF, p2 = denominator DOF, + p3 = numerator noncentrality parameter. */ + +#define NIFTI_INTENT_FTEST_NONC 12 + + /*! [C2, chap 29] Noncentral chi-squared statistic (2 params): + p1 = DOF, p2 = noncentrality parameter. */ + +#define NIFTI_INTENT_CHISQ_NONC 13 + + /*! [C2, chap 23] Logistic distribution (2 params): + p1 = location, p2 = scale. + Density(x) proportional to sech^2((x-p1)/(2*p2)). */ + +#define NIFTI_INTENT_LOGISTIC 14 + + /*! [C2, chap 24] Laplace distribution (2 params): + p1 = location, p2 = scale. + Density(x) proportional to exp(-abs(x-p1)/p2). */ + +#define NIFTI_INTENT_LAPLACE 15 + + /*! [C2, chap 26] Uniform distribution: p1 = lower end, p2 = upper end. */ + +#define NIFTI_INTENT_UNIFORM 16 + + /*! [C2, chap 31] Noncentral t statistic (2 params): + p1 = DOF, p2 = noncentrality parameter. */ + +#define NIFTI_INTENT_TTEST_NONC 17 + + /*! [C1, chap 21] Weibull distribution (3 params): + p1 = location, p2 = scale, p3 = power. + Density(x) proportional to + ((x-p1)/p2)^(p3-1) * exp(-((x-p1)/p2)^p3) for x > p1. */ + +#define NIFTI_INTENT_WEIBULL 18 + + /*! [C1, chap 18] Chi distribution (1 param): p1 = DOF. + Density(x) proportional to x^(p1-1) * exp(-x^2/2) for x > 0. + p1 = 1 = 'half normal' distribution + p1 = 2 = Rayleigh distribution + p1 = 3 = Maxwell-Boltzmann distribution. */ + +#define NIFTI_INTENT_CHI 19 + + /*! [C1, chap 15] Inverse Gaussian (2 params): + p1 = mu, p2 = lambda + Density(x) proportional to + exp(-p2*(x-p1)^2/(2*p1^2*x)) / x^3 for x > 0. */ + +#define NIFTI_INTENT_INVGAUSS 20 + + /*! [C2, chap 22] Extreme value type I (2 params): + p1 = location, p2 = scale + cdf(x) = exp(-exp(-(x-p1)/p2)). */ + +#define NIFTI_INTENT_EXTVAL 21 + + /*! Data is a 'p-value' (no params). */ + +#define NIFTI_INTENT_PVAL 22 + + /*! Smallest intent_code that indicates a statistic. */ + +#define NIFTI_FIRST_STATCODE 2 + + /*! Largest intent_code that indicates a statistic. */ + +#define NIFTI_LAST_STATCODE 22 + + /*---------- these values for intent_code aren't for statistics ----------*/ + + /*! To signify that the value at each voxel is an estimate + of some parameter, set intent_code = NIFTI_INTENT_ESTIMATE. + The name of the parameter may be stored in intent_name. */ + +#define NIFTI_INTENT_ESTIMATE 1001 + + /*! To signify that the value at each voxel is an index into + some set of labels, set intent_code = NIFTI_INTENT_LABEL. + The filename with the labels may stored in aux_file. */ + +#define NIFTI_INTENT_LABEL 1002 + + /*! To signify that the value at each voxel is an index into the + NeuroNames labels set, set intent_code = NIFTI_INTENT_NEURONAME. */ + +#define NIFTI_INTENT_NEURONAME 1003 + + /*! To store an M x N matrix at each voxel: + - dataset must have a 5th dimension (dim[0]=5 and dim[5]>1) + - intent_code must be NIFTI_INTENT_GENMATRIX + - dim[5] must be M*N + - intent_p1 must be M (in float format) + - intent_p2 must be N (ditto) + - the matrix values A[i][[j] are stored in row-order: + - A[0][0] A[0][1] ... A[0][N-1] + - A[1][0] A[1][1] ... A[1][N-1] + - etc., until + - A[M-1][0] A[M-1][1] ... A[M-1][N-1] */ + +#define NIFTI_INTENT_GENMATRIX 1004 + + /*! To store an NxN symmetric matrix at each voxel: + - dataset must have a 5th dimension + - intent_code must be NIFTI_INTENT_SYMMATRIX + - dim[5] must be N*(N+1)/2 + - intent_p1 must be N (in float format) + - the matrix values A[i][[j] are stored in row-order: + - A[0][0] + - A[1][0] A[1][1] + - A[2][0] A[2][1] A[2][2] + - etc.: row-by-row */ + +#define NIFTI_INTENT_SYMMATRIX 1005 + + /*! To signify that the vector value at each voxel is to be taken + as a displacement field or vector: + - dataset must have a 5th dimension + - intent_code must be NIFTI_INTENT_DISPVECT + - dim[5] must be the dimensionality of the displacment + vector (e.g., 3 for spatial displacement, 2 for in-plane) */ + +#define NIFTI_INTENT_DISPVECT 1006 /* specifically for displacements */ +#define NIFTI_INTENT_VECTOR 1007 /* for any other type of vector */ + + /*! To signify that the vector value at each voxel is really a + spatial coordinate (e.g., the vertices or nodes of a surface mesh): + - dataset must have a 5th dimension + - intent_code must be NIFTI_INTENT_POINTSET + - dim[0] = 5 + - dim[1] = number of points + - dim[2] = dim[3] = dim[4] = 1 + - dim[5] must be the dimensionality of space (e.g., 3 => 3D space). + - intent_name may describe the object these points come from + (e.g., "pial", "gray/white" , "EEG", "MEG"). */ + +#define NIFTI_INTENT_POINTSET 1008 + + /*! To signify that the vector value at each voxel is really a triple + of indexes (e.g., forming a triangle) from a pointset dataset: + - dataset must have a 5th dimension + - intent_code must be NIFTI_INTENT_TRIANGLE + - dim[0] = 5 + - dim[1] = number of triangles + - dim[2] = dim[3] = dim[4] = 1 + - dim[5] = 3 + - datatype should be an integer type (preferably DT_INT32) + - the data values are indexes (0,1,...) into a pointset dataset. */ + +#define NIFTI_INTENT_TRIANGLE 1009 + + /*! To signify that the vector value at each voxel is a quaternion: + - dataset must have a 5th dimension + - intent_code must be NIFTI_INTENT_QUATERNION + - dim[0] = 5 + - dim[5] = 4 + - datatype should be a floating point type */ + +#define NIFTI_INTENT_QUATERNION 1010 + +/*---------------------------------------------------------------------------*/ +/* 3D IMAGE (VOLUME) ORIENTATION AND LOCATION IN SPACE: + --------------------------------------------------- + There are 3 different methods by which continuous coordinates can + attached to voxels. The discussion below emphasizes 3D volumes, and + the continuous coordinates are referred to as (x,y,z). The voxel + index coordinates (i.e., the array indexes) are referred to as (i,j,k), + with valid ranges: + i = 0 .. dim[1]-1 + j = 0 .. dim[2]-1 (if dim[0] >= 2) + k = 0 .. dim[3]-1 (if dim[0] >= 3) + The (x,y,z) coordinates refer to the CENTER of a voxel. In methods + 2 and 3, the (x,y,z) axes refer to a subject-based coordinate system, + with + +x = Right +y = Anterior +z = Superior. + This is a right-handed coordinate system. However, the exact direction + these axes point with respect to the subject depends on qform_code + (Method 2) and sform_code (Method 3). + + N.B.: The i index varies most rapidly, j index next, k index slowest. + Thus, voxel (i,j,k) is stored starting at location + (i + j*dim[1] + k*dim[1]*dim[2]) * (bitpix/8) + into the dataset array. + + N.B.: The ANALYZE 7.5 coordinate system is + +x = Left +y = Anterior +z = Superior + which is a left-handed coordinate system. This backwardness is + too difficult to tolerate, so this NIFTI-1 standard specifies the + coordinate order which is most common in functional neuroimaging. + + N.B.: The 3 methods below all give the locations of the voxel centers + in the (x,y,z) coordinate system. In many cases, programs will wish + to display image data on some other grid. In such a case, the program + will need to convert its desired (x,y,z) values into (i,j,k) values + in order to extract (or interpolate) the image data. This operation + would be done with the inverse transformation to those described below. + + N.B.: Method 2 uses a factor 'qfac' which is either -1 or 1; qfac is + stored in the otherwise unused pixdim[0]. If pixdim[0]=0.0 (which + should not occur), we take qfac=1. Of course, pixdim[0] is only used + when reading a NIFTI-1 header, not when reading an ANALYZE 7.5 header. + + N.B.: The units of (x,y,z) can be specified using the xyzt_units field. + + METHOD 1 (the "old" way, used only when qform_code = 0): + ------------------------------------------------------- + The coordinate mapping from (i,j,k) to (x,y,z) is the ANALYZE + 7.5 way. This is a simple scaling relationship: + + x = pixdim[1] * i + y = pixdim[2] * j + z = pixdim[3] * k + + No particular spatial orientation is attached to these (x,y,z) + coordinates. (NIFTI-1 does not have the ANALYZE 7.5 orient field, + which is not general and is often not set properly.) This method + is not recommended, and is present mainly for compatibility with + ANALYZE 7.5 files. + + METHOD 2 (used when qform_code > 0, which should be the "normal case): + --------------------------------------------------------------------- + The (x,y,z) coordinates are given by the pixdim[] scales, a rotation + matrix, and a shift. This method is intended to represent + "scanner-anatomical" coordinates, which are often embedded in the + image header (e.g., DICOM fields (0020,0032), (0020,0037), (0028,0030), + and (0018,0050)), and represent the nominal orientation and location of + the data. This method can also be used to represent "aligned" + coordinates, which would typically result from some post-acquisition + alignment of the volume to a standard orientation (e.g., the same + subject on another day, or a rigid rotation to true anatomical + orientation from the tilted position of the subject in the scanner). + The formula for (x,y,z) in terms of header parameters and (i,j,k) is: + + [ x ] [ R11 R12 R13 ] [ pixdim[1] * i ] [ qoffset_x ] + [ y ] = [ R21 R22 R23 ] [ pixdim[2] * j ] + [ qoffset_y ] + [ z ] [ R31 R32 R33 ] [ qfac * pixdim[3] * k ] [ qoffset_z ] + + The qoffset_* shifts are in the NIFTI-1 header. Note that the center + of the (i,j,k)=(0,0,0) voxel (first value in the dataset array) is + just (x,y,z)=(qoffset_x,qoffset_y,qoffset_z). + + The rotation matrix R is calculated from the quatern_* parameters. + This calculation is described below. + + The scaling factor qfac is either 1 or -1. The rotation matrix R + defined by the quaternion parameters is "proper" (has determinant 1). + This may not fit the needs of the data; for example, if the image + grid is + i increases from Left-to-Right + j increases from Anterior-to-Posterior + k increases from Inferior-to-Superior + Then (i,j,k) is a left-handed triple. In this example, if qfac=1, + the R matrix would have to be + + [ 1 0 0 ] + [ 0 -1 0 ] which is "improper" (determinant = -1). + [ 0 0 1 ] + + If we set qfac=-1, then the R matrix would be + + [ 1 0 0 ] + [ 0 -1 0 ] which is proper. + [ 0 0 -1 ] + + This R matrix is represented by quaternion [a,b,c,d] = [0,1,0,0] + (which encodes a 180 degree rotation about the x-axis). + + METHOD 3 (used when sform_code > 0): + ----------------------------------- + The (x,y,z) coordinates are given by a general affine transformation + of the (i,j,k) indexes: + + x = srow_x[0] * i + srow_x[1] * j + srow_x[2] * k + srow_x[3] + y = srow_y[0] * i + srow_y[1] * j + srow_y[2] * k + srow_y[3] + z = srow_z[0] * i + srow_z[1] * j + srow_z[2] * k + srow_z[3] + + The srow_* vectors are in the NIFTI_1 header. Note that no use is + made of pixdim[] in this method. + + WHY 3 METHODS? + -------------- + Method 1 is provided only for backwards compatibility. The intention + is that Method 2 (qform_code > 0) represents the nominal voxel locations + as reported by the scanner, or as rotated to some fiducial orientation and + location. Method 3, if present (sform_code > 0), is to be used to give + the location of the voxels in some standard space. The sform_code + indicates which standard space is present. Both methods 2 and 3 can be + present, and be useful in different contexts (method 2 for displaying the + data on its original grid; method 3 for displaying it on a standard grid). + + In this scheme, a dataset would originally be set up so that the + Method 2 coordinates represent what the scanner reported. Later, + a registration to some standard space can be computed and inserted + in the header. Image display software can use either transform, + depending on its purposes and needs. + + In Method 2, the origin of coordinates would generally be whatever + the scanner origin is; for example, in MRI, (0,0,0) is the center + of the gradient coil. + + In Method 3, the origin of coordinates would depend on the value + of sform_code; for example, for the Talairach coordinate system, + (0,0,0) corresponds to the Anterior Commissure. + + QUATERNION REPRESENTATION OF ROTATION MATRIX (METHOD 2) + ------------------------------------------------------- + The orientation of the (x,y,z) axes relative to the (i,j,k) axes + in 3D space is specified using a unit quaternion [a,b,c,d], where + a*a+b*b+c*c+d*d=1. The (b,c,d) values are all that is needed, since + we require that a = sqrt(1.0-b*b+c*c+d*d) be nonnegative. The (b,c,d) + values are stored in the (quatern_b,quatern_c,quatern_d) fields. + + The quaternion representation is chosen for its compactness in + representing rotations. The (proper) 3x3 rotation matrix that + corresponds to [a,b,c,d] is + + [ a*a+b*b-c*c-d*d 2*b*c-2*a*d 2*b*d+2*a*c ] + R = [ 2*b*c+2*a*d a*a+c*c-b*b-d*d 2*c*d-2*a*b ] + [ 2*b*d-2*a*c 2*c*d+2*a*b a*a+d*d-c*c-b*b ] + + [ R11 R12 R13 ] + = [ R21 R22 R23 ] + [ R31 R32 R33 ] + + If (p,q,r) is a unit 3-vector, then rotation of angle h about that + direction is represented by the quaternion + + [a,b,c,d] = [cos(h/2), p*sin(h/2), q*sin(h/2), r*sin(h/2)]. + + Requiring a >= 0 is equivalent to requiring -Pi <= h <= Pi. (Note that + [-a,-b,-c,-d] represents the same rotation as [a,b,c,d]; there are 2 + quaternions that can be used to represent a given rotation matrix R.) + To rotate a 3-vector (x,y,z) using quaternions, we compute the + quaternion product + + [0,x',y',z'] = [a,b,c,d] * [0,x,y,z] * [a,-b,-c,-d] + + which is equivalent to the matrix-vector multiply + + [ x' ] [ x ] + [ y' ] = R [ y ] (equivalence depends on a*a+b*b+c*c+d*d=1) + [ z' ] [ z ] + + Multiplication of 2 quaternions is defined by the following: + + [a,b,c,d] = a*1 + b*I + c*J + d*K + where + I*I = J*J = K*K = -1 (I,J,K are square roots of -1) + I*J = K J*K = I K*I = J + J*I = -K K*J = -I I*K = -J (not commutative!) + For example + [a,b,0,0] * [0,0,0,1] = [0,-b,0,a] + since this expands to + (a+b*I)*(K) = (a*K+b*I*K) = (a*K-b*J). + + The above formula shows how to go from quaternion (b,c,d) to + rotation matrix and direction cosines. Conversely, given R, + we can compute the fields for the NIFTI-1 header by + + a = 0.5 * sqrt(1+R11+R22+R33) (not stored) + b = 0.25 * (R32-R23) / a => quatern_b + c = 0.25 * (R13-R31) / a => quatern_c + d = 0.25 * (R21-R12) / a => quatern_d + + If a=0 (a 180 degree rotation), alternative formulas are needed. + See the nifti1_io.c function mat44_to_quatern() for an implementation + of the various cases in converting R to [a,b,c,d]. + + Note that R-transpose (= R-inverse) would lead to the quaternion + [a,-b,-c,-d]. + + The choice to specify the qoffset_x (etc.) values in the final + coordinate system is partly to make it easy to convert DICOM images to + this format. The DICOM attribute "Image Position (Patient)" (0020,0032) + stores the (Xd,Yd,Zd) coordinates of the center of the first voxel. + Here, (Xd,Yd,Zd) refer to DICOM coordinates, and Xd=-x, Yd=-y, Zd=z, + where (x,y,z) refers to the NIFTI coordinate system discussed above. + (i.e., DICOM +Xd is Left, +Yd is Posterior, +Zd is Superior, + whereas +x is Right, +y is Anterior , +z is Superior. ) + Thus, if the (0020,0032) DICOM attribute is extracted into (px,py,pz), then + qoffset_x = -px qoffset_y = -py qoffset_z = pz + is a reasonable setting when qform_code=NIFTI_XFORM_SCANNER_ANAT. + + That is, DICOM's coordinate system is 180 degrees rotated about the z-axis + from the neuroscience/NIFTI coordinate system. To transform between DICOM + and NIFTI, you just have to negate the x- and y-coordinates. + + The DICOM attribute (0020,0037) "Image Orientation (Patient)" gives the + orientation of the x- and y-axes of the image data in terms of 2 3-vectors. + The first vector is a unit vector along the x-axis, and the second is + along the y-axis. If the (0020,0037) attribute is extracted into the + value (xa,xb,xc,ya,yb,yc), then the first two columns of the R matrix + would be + [ -xa -ya ] + [ -xb -yb ] + [ xc yc ] + The negations are because DICOM's x- and y-axes are reversed relative + to NIFTI's. The third column of the R matrix gives the direction of + displacement (relative to the subject) along the slice-wise direction. + This orientation is not encoded in the DICOM standard in a simple way; + DICOM is mostly concerned with 2D images. The third column of R will be + either the cross-product of the first 2 columns or its negative. It is + possible to infer the sign of the 3rd column by examining the coordinates + in DICOM attribute (0020,0032) "Image Position (Patient)" for successive + slices. However, this method occasionally fails for reasons that I + (RW Cox) do not understand. +-----------------------------------------------------------------------------*/ + + /* [qs]form_code value: */ /* x,y,z coordinate system refers to: */ + /*-----------------------*/ /*---------------------------------------*/ + + /*! Arbitrary coordinates (Method 1). */ + +#define NIFTI_XFORM_UNKNOWN 0 + + /*! Scanner-based anatomical coordinates */ + +#define NIFTI_XFORM_SCANNER_ANAT 1 + + /*! Coordinates aligned to another file's, + or to anatomical "truth". */ + +#define NIFTI_XFORM_ALIGNED_ANAT 2 + + /*! Coordinates aligned to Talairach- + Tournoux Atlas; (0,0,0)=AC, etc. */ + +#define NIFTI_XFORM_TALAIRACH 3 + + /*! MNI 152 normalized coordinates. */ + +#define NIFTI_XFORM_MNI_152 4 + +/*---------------------------------------------------------------------------*/ +/* UNITS OF SPATIAL AND TEMPORAL DIMENSIONS: + ---------------------------------------- + The codes below can be used in xyzt_units to indicate the units of pixdim. + As noted earlier, dimensions 1,2,3 are for x,y,z; dimension 4 is for + time (t). + - If dim[4]=1 or dim[0] < 4, there is no time axis. + - A single time series (no space) would be specified with + - dim[0] = 4 (for scalar data) or dim[0] = 5 (for vector data) + - dim[1] = dim[2] = dim[3] = 1 + - dim[4] = number of time points + - pixdim[4] = time step + - xyzt_units indicates units of pixdim[4] + - dim[5] = number of values stored at each time point + + Bits 0..2 of xyzt_units specify the units of pixdim[1..3] + (e.g., spatial units are values 1..7). + Bits 3..5 of xyzt_units specify the units of pixdim[4] + (e.g., temporal units are multiples of 8). + + This compression of 2 distinct concepts into 1 byte is due to the + limited space available in the 348 byte ANALYZE 7.5 header. The + macros XYZT_TO_SPACE and XYZT_TO_TIME can be used to mask off the + undesired bits from the xyzt_units fields, leaving "pure" space + and time codes. Inversely, the macro SPACE_TIME_TO_XYZT can be + used to assemble a space code (0,1,2,...,7) with a time code + (0,8,16,32,...,56) into the combined value for xyzt_units. + + Note that codes are provided to indicate the "time" axis units are + actually frequency in Hertz (_HZ) or in part-per-million (_PPM). + + The toffset field can be used to indicate a nonzero start point for + the time axis. That is, time point #m is at t=toffset+m*pixdim[4] + for m=0..dim[4]-1. +-----------------------------------------------------------------------------*/ + + /*! NIFTI code for unspecified units. */ +#define NIFTI_UNITS_UNKNOWN 0 + + /** Space codes are multiples of 1. **/ + /*! NIFTI code for meters. */ +#define NIFTI_UNITS_METER 1 + /*! NIFTI code for millimeters. */ +#define NIFTI_UNITS_MM 2 + /*! NIFTI code for micrometers. */ +#define NIFTI_UNITS_MICRON 3 + + /** Time codes are multiples of 8. **/ + /*! NIFTI code for seconds. */ +#define NIFTI_UNITS_SEC 8 + /*! NIFTI code for milliseconds. */ +#define NIFTI_UNITS_MSEC 16 + /*! NIFTI code for microseconds. */ +#define NIFTI_UNITS_USEC 24 + + /*** These units are for spectral data: ***/ + /*! NIFTI code for Hertz. */ +#define NIFTI_UNITS_HZ 32 + /*! NIFTI code for ppm. */ +#define NIFTI_UNITS_PPM 40 + +#undef XYZT_TO_SPACE +#undef XYZT_TO_TIME +#define XYZT_TO_SPACE(xyzt) ( (xyzt) & 0x07 ) +#define XYZT_TO_TIME(xyzt) ( (xyzt) & 0x38 ) + +#undef SPACE_TIME_TO_XYZT +#define SPACE_TIME_TO_XYZT(ss,tt) ( (((char)(ss)) & 0x07) \ + | (((char)(tt)) & 0x38) ) + +/*---------------------------------------------------------------------------*/ +/* MRI-SPECIFIC SPATIAL AND TEMPORAL INFORMATION: + --------------------------------------------- + A few fields are provided to store some extra information + that is sometimes important when storing the image data + from an FMRI time series experiment. (After processing such + data into statistical images, these fields are not likely + to be useful.) + + { freq_dim } = These fields encode which spatial dimension (1,2, or 3) + { phase_dim } = corresponds to which acquisition dimension for MRI data. + { slice_dim } = + Examples: + Rectangular scan multi-slice EPI: + freq_dim = 1 phase_dim = 2 slice_dim = 3 (or some permutation) + Spiral scan multi-slice EPI: + freq_dim = phase_dim = 0 slice_dim = 3 + since the concepts of frequency- and phase-encoding directions + don't apply to spiral scan + + slice_duration = If this is positive, AND if slice_dim is nonzero, + indicates the amount of time used to acquire 1 slice. + slice_duration*dim[slice_dim] can be less than pixdim[4] + with a clustered acquisition method, for example. + + slice_code = If this is nonzero, AND if slice_dim is nonzero, AND + if slice_duration is positive, indicates the timing + pattern of the slice acquisition. The following codes + are defined: + NIFTI_SLICE_SEQ_INC + NIFTI_SLICE_SEQ_DEC + NIFTI_SLICE_ALT_INC + NIFTI_SLICE_ALT_DEC + { slice_start } = Indicates the start and end of the slice acquisition + { slice_end } = pattern, when slice_code is nonzero. These values + are present to allow for the possible addition of + "padded" slices at either end of the volume, which + don't fit into the slice timing pattern. If there + are no padding slices, then slice_start=0 and + slice_end=dim[slice_dim]-1 are the correct values. + For these values to be meaningful, slice_start must + be non-negative and slice_end must be greater than + slice_start. + + The following table indicates the slice timing pattern, relative to + time=0 for the first slice acquired, for some sample cases. Here, + dim[slice_dim]=7 (there are 7 slices, labeled 0..6), slice_duration=0.1, + and slice_start=1, slice_end=5 (1 padded slice on each end). + + slice + index SEQ_INC SEQ_DEC ALT_INC ALT_DEC + 6 -- n/a n/a n/a n/a n/a = not applicable + 5 -- 0.4 0.0 0.2 0.0 (slice time offset + 4 -- 0.3 0.1 0.4 0.3 doesn't apply to + 3 -- 0.2 0.2 0.1 0.1 slices outside range + 2 -- 0.1 0.3 0.3 0.4 slice_start..slice_end) + 1 -- 0.0 0.4 0.0 0.2 + 0 -- n/a n/a n/a n/a + + The fields freq_dim, phase_dim, slice_dim are all squished into the single + byte field dim_info (2 bits each, since the values for each field are + limited to the range 0..3). This unpleasantness is due to lack of space + in the 348 byte allowance. + + The macros DIM_INFO_TO_FREQ_DIM, DIM_INFO_TO_PHASE_DIM, and + DIM_INFO_TO_SLICE_DIM can be used to extract these values from the + dim_info byte. + + The macro FPS_INTO_DIM_INFO can be used to put these 3 values + into the dim_info byte. +-----------------------------------------------------------------------------*/ + +#undef DIM_INFO_TO_FREQ_DIM +#undef DIM_INFO_TO_PHASE_DIM +#undef DIM_INFO_TO_SLICE_DIM + +#define DIM_INFO_TO_FREQ_DIM(di) ( ((di) ) & 0x03 ) +#define DIM_INFO_TO_PHASE_DIM(di) ( ((di) >> 2) & 0x03 ) +#define DIM_INFO_TO_SLICE_DIM(di) ( ((di) >> 4) & 0x03 ) + +#undef FPS_INTO_DIM_INFO +#define FPS_INTO_DIM_INFO(fd,pd,sd) ( ( ( ((char)(fd)) & 0x03) ) | \ + ( ( ((char)(pd)) & 0x03) << 2 ) | \ + ( ( ((char)(sd)) & 0x03) << 4 ) ) + +#define NIFTI_SLICE_SEQ_INC 1 +#define NIFTI_SLICE_SEQ_DEC 2 +#define NIFTI_SLICE_ALT_INC 3 +#define NIFTI_SLICE_ALT_DEC 4 + +/*---------------------------------------------------------------------------*/ +/* UNUSED FIELDS: + ------------- + Some of the ANALYZE 7.5 fields marked as ++UNUSED++ may need to be set + to particular values for compatibility with other programs. The issue + of interoperability of ANALYZE 7.5 files is a murky one -- not all + programs require exactly the same set of fields. (Unobscuring this + murkiness is a principal motivation behind NIFTI-1.) + + Some of the fields that may need to be set for other (non-NIFTI aware) + software to be happy are: + + extents dbh.h says this should be 16384 + regular dbh.h says this should be the character 'r' + glmin, } dbh.h says these values should be the min and max voxel + glmax } values for the entire dataset + + It is best to initialize ALL fields in the NIFTI-1 header to 0 + (e.g., with calloc()), then fill in what is needed. +-----------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------*/ +/* MISCELLANEOUS C MACROS +-----------------------------------------------------------------------------*/ + +/*.................*/ +/*! Given a nifti_1_header struct, check if it has a good magic number. + Returns NIFTI version number (1..9) if magic is good, 0 if it is not. */ + +#define NIFTI_VERSION(h) \ + ( ( (h).magic[0]=='n' && (h).magic[3]=='\0' && \ + ( (h).magic[1]=='i' || (h).magic[1]=='+' ) && \ + ( (h).magic[2]>='1' && (h).magic[2]<='9' ) ) \ + ? (h).magic[2]-'0' : 0 ) + +/*.................*/ +/*! Check if a nifti_1_header struct says if the data is stored in the + same file or in a separate file. Returns 1 if the data is in the same + file as the header, 0 if it is not. */ + +#define NIFTI_ONEFILE(h) ( (h).magic[1] == '+' ) + +/*.................*/ +/*! Check if a nifti_1_header struct needs to be byte swapped. + Returns 1 if it needs to be swapped, 0 if it does not. */ + +#define NIFTI_NEEDS_SWAP(h) ( (h).dim[0] < 0 || (h).dim[0] > 7 ) + +/*.................*/ +/*! Check if a nifti_1_header struct contains a 5th (vector) dimension. + Returns size of 5th dimension if > 1, returns 0 otherwise. */ + +#define NIFTI_5TH_DIM(h) ( ((h).dim[0]>4 && (h).dim[5]>1) ? (h).dim[5] : 0 ) + +/*****************************************************************************/ + +/*=================*/ +#ifdef __cplusplus +} +#endif +/*=================*/ + +#endif /* _NIFTI_HEADER_ */ diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/nifti_stats.c b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/nifti_stats.c new file mode 100644 index 0000000..e1c276a --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/nifti_stats.c @@ -0,0 +1,11282 @@ +#ifndef lint +static char sccsid[] = "%W% R.W. Cox %E%"; +#endif + /************************************************************************/ + /** Functions to compute cumulative distributions and their inverses **/ + /** for the NIfTI-1 statistical types. Much of this code is taken **/ + /** from other sources. In particular, the cdflib functions by **/ + /** Brown and Lovato make up the bulk of this file. That code **/ + /** was placed in the public domain. The code by K. Krishnamoorthy **/ + /** is also released for unrestricted use. Finally, the other parts **/ + /** of this file (by RW Cox) are released to the public domain. **/ + /** **/ + /** Most of this file comprises a set of "static" functions, to be **/ + /** called by the user-level functions at the very end of the file. **/ + /** At the end of the file is a simple main program to drive these **/ + /** functions. **/ + /** **/ + /** To find the user-level functions, search forward for the string **/ + /** "nifti_", which will be at about line 11000. **/ + /************************************************************************/ + /*****==============================================================*****/ + /***** Neither the National Institutes of Health (NIH), the DFWG, *****/ + /***** nor any of the members or employees of these institutions *****/ + /***** imply any warranty of usefulness of this material for any *****/ + /***** purpose, and do not assume any liability for damages, *****/ + /***** incidental or otherwise, caused by any use of this document. *****/ + /***** If these conditions are not acceptable, do not use this! *****/ + /*****==============================================================*****/ + /************************************************************************/ + + /*....................................................................... + To compile with gcc, for example: + + gcc -O3 -ffast-math -o nifti_stats nifti_stats.c -lm + ........................................................................*/ + + +/* + * niftilib $Id: nifti_stats.c,v 1.1 2012/03/22 18:36:33 fissell Exp $ + */ + +#include "nifti1.h" /* for the NIFTI_INTENT_* constants */ +#include <stdio.h> +#include <stdlib.h> +#include <math.h> + + /************************************************************************/ + /************ Include all the cdflib functions here and now *************/ + /************ [about 9900 lines of code below here] *************/ + /************************************************************************/ + +/** Prototypes for cdflib functions **/ + +static double algdiv(double*,double*); +static double alngam(double*); +static double alnrel(double*); +static double apser(double*,double*,double*,double*); +static double basym(double*,double*,double*,double*); +static double bcorr(double*,double*); +static double betaln(double*,double*); +static double bfrac(double*,double*,double*,double*,double*,double*); +static void bgrat(double*,double*,double*,double*,double*,double*,int*i); +static double bpser(double*,double*,double*,double*); +static void bratio(double*,double*,double*,double*,double*,double*,int*); +static double brcmp1(int*,double*,double*,double*,double*); +static double brcomp(double*,double*,double*,double*); +static double bup(double*,double*,double*,double*,int*,double*); +static void cdfbet(int*,double*,double*,double*,double*,double*,double*, + int*,double*); +static void cdfbin(int*,double*,double*,double*,double*,double*,double*, + int*,double*); +static void cdfchi(int*,double*,double*,double*,double*,int*,double*); +static void cdfchn(int*,double*,double*,double*,double*,double*,int*,double*); +static void cdff(int*,double*,double*,double*,double*,double*,int*,double*); +static void cdffnc(int*,double*,double*,double*,double*,double*,double*, + int*s,double*); +static void cdfgam(int*,double*,double*,double*,double*,double*,int*,double*); +static void cdfnbn(int*,double*,double*,double*,double*,double*,double*, + int*,double*); +static void cdfnor(int*,double*,double*,double*,double*,double*,int*,double*); +static void cdfpoi(int*,double*,double*,double*,double*,int*,double*); +static void cdft(int*,double*,double*,double*,double*,int*,double*); +static void cumbet(double*,double*,double*,double*,double*,double*); +static void cumbin(double*,double*,double*,double*,double*,double*); +static void cumchi(double*,double*,double*,double*); +static void cumchn(double*,double*,double*,double*,double*); +static void cumf(double*,double*,double*,double*,double*); +static void cumfnc(double*,double*,double*,double*,double*,double*); +static void cumgam(double*,double*,double*,double*); +static void cumnbn(double*,double*,double*,double*,double*,double*); +static void cumnor(double*,double*,double*); +static void cumpoi(double*,double*,double*,double*); +static void cumt(double*,double*,double*,double*); +static double dbetrm(double*,double*); +static double devlpl(double [],int*,double*); +static double dexpm1(double*); +static double dinvnr(double *p,double *q); +static void E0000(int,int*,double*,double*,unsigned long*, + unsigned long*,double*,double*,double*, + double*,double*,double*,double*); +static void dinvr(int*,double*,double*,unsigned long*,unsigned long*); +static void dstinv(double*,double*,double*,double*,double*,double*, + double*); +static double dlanor(double*); +static double dln1mx(double*); +static double dln1px(double*); +static double dlnbet(double*,double*); +static double dlngam(double*); +static double dstrem(double*); +static double dt1(double*,double*,double*); +static void E0001(int,int*,double*,double*,double*,double*, + unsigned long*,unsigned long*,double*,double*, + double*,double*); +static void dzror(int*,double*,double*,double*,double *, + unsigned long*,unsigned long*); +static void dstzr(double *zxlo,double *zxhi,double *zabstl,double *zreltl); +static double erf1(double*); +static double erfc1(int*,double*); +static double esum(int*,double*); +static double exparg(int*); +static double fpser(double*,double*,double*,double*); +static double gam1(double*); +static void gaminv(double*,double*,double*,double*,double*,int*); +static double gamln(double*); +static double gamln1(double*); +static double Xgamm(double*); +static void grat1(double*,double*,double*,double*,double*,double*); +static void gratio(double*,double*,double*,double*,int*); +static double gsumln(double*,double*); +static double psi(double*); +static double rcomp(double*,double*); +static double rexp(double*); +static double rlog(double*); +static double rlog1(double*); +static double spmpar(int*); +static double stvaln(double*); +static double fifdint(double); +static double fifdmax1(double,double); +static double fifdmin1(double,double); +static double fifdsign(double,double); +static long fifidint(double); +static long fifmod(long,long); +static void ftnstop(char*); +static int ipmpar(int*); + +/***=====================================================================***/ +static double algdiv(double *a,double *b) +/* +----------------------------------------------------------------------- + + COMPUTATION OF LN(GAMMA(B)/GAMMA(A+B)) WHEN B .GE. 8 + + -------- + + IN THIS ALGORITHM, DEL(X) IS THE FUNCTION DEFINED BY + LN(GAMMA(X)) = (X - 0.5)*LN(X) - X + 0.5*LN(2*PI) + DEL(X). + +----------------------------------------------------------------------- +*/ +{ +static double c0 = .833333333333333e-01; +static double c1 = -.277777777760991e-02; +static double c2 = .793650666825390e-03; +static double c3 = -.595202931351870e-03; +static double c4 = .837308034031215e-03; +static double c5 = -.165322962780713e-02; +static double algdiv,c,d,h,s11,s3,s5,s7,s9,t,u,v,w,x,x2,T1; +/* + .. + .. Executable Statements .. +*/ + if(*a <= *b) goto S10; + h = *b/ *a; + c = 1.0e0/(1.0e0+h); + x = h/(1.0e0+h); + d = *a+(*b-0.5e0); + goto S20; +S10: + h = *a/ *b; + c = h/(1.0e0+h); + x = 1.0e0/(1.0e0+h); + d = *b+(*a-0.5e0); +S20: +/* + SET SN = (1 - X**N)/(1 - X) +*/ + x2 = x*x; + s3 = 1.0e0+(x+x2); + s5 = 1.0e0+(x+x2*s3); + s7 = 1.0e0+(x+x2*s5); + s9 = 1.0e0+(x+x2*s7); + s11 = 1.0e0+(x+x2*s9); +/* + SET W = DEL(B) - DEL(A + B) +*/ + t = pow(1.0e0/ *b,2.0); + w = ((((c5*s11*t+c4*s9)*t+c3*s7)*t+c2*s5)*t+c1*s3)*t+c0; + w *= (c/ *b); +/* + COMBINE THE RESULTS +*/ + T1 = *a/ *b; + u = d*alnrel(&T1); + v = *a*(log(*b)-1.0e0); + if(u <= v) goto S30; + algdiv = w-v-u; + return algdiv; +S30: + algdiv = w-u-v; + return algdiv; +} /* END */ + +/***=====================================================================***/ +static double alngam(double *x) +/* +********************************************************************** + + double alngam(double *x) + double precision LN of the GAMma function + + + Function + + + Returns the natural logarithm of GAMMA(X). + + + Arguments + + + X --> value at which scaled log gamma is to be returned + X is DOUBLE PRECISION + + + Method + + + If X .le. 6.0, then use recursion to get X below 3 + then apply rational approximation number 5236 of + Hart et al, Computer Approximations, John Wiley and + Sons, NY, 1968. + + If X .gt. 6.0, then use recursion to get X to at least 12 and + then use formula 5423 of the same source. + +********************************************************************** +*/ +{ +#define hln2pi 0.91893853320467274178e0 +static double coef[5] = { + 0.83333333333333023564e-1,-0.27777777768818808e-2,0.79365006754279e-3, + -0.594997310889e-3,0.8065880899e-3 +}; +static double scoefd[4] = { + 0.62003838007126989331e2,0.9822521104713994894e1,-0.8906016659497461257e1, + 0.1000000000000000000e1 +}; +static double scoefn[9] = { + 0.62003838007127258804e2,0.36036772530024836321e2,0.20782472531792126786e2, + 0.6338067999387272343e1,0.215994312846059073e1,0.3980671310203570498e0, + 0.1093115956710439502e0,0.92381945590275995e-2,0.29737866448101651e-2 +}; +static int K1 = 9; +static int K3 = 4; +static int K5 = 5; +static double alngam,offset,prod,xx; +static int i,n; +static double T2,T4,T6; +/* + .. + .. Executable Statements .. +*/ + if(!(*x <= 6.0e0)) goto S70; + prod = 1.0e0; + xx = *x; + if(!(*x > 3.0e0)) goto S30; +S10: + if(!(xx > 3.0e0)) goto S20; + xx -= 1.0e0; + prod *= xx; + goto S10; +S30: +S20: + if(!(*x < 2.0e0)) goto S60; +S40: + if(!(xx < 2.0e0)) goto S50; + prod /= xx; + xx += 1.0e0; + goto S40; +S60: +S50: + T2 = xx-2.0e0; + T4 = xx-2.0e0; + alngam = devlpl(scoefn,&K1,&T2)/devlpl(scoefd,&K3,&T4); +/* + COMPUTE RATIONAL APPROXIMATION TO GAMMA(X) +*/ + alngam *= prod; + alngam = log(alngam); + goto S110; +S70: + offset = hln2pi; +/* + IF NECESSARY MAKE X AT LEAST 12 AND CARRY CORRECTION IN OFFSET +*/ + n = fifidint(12.0e0-*x); + if(!(n > 0)) goto S90; + prod = 1.0e0; + for(i=1; i<=n; i++) prod *= (*x+(double)(i-1)); + offset -= log(prod); + xx = *x+(double)n; + goto S100; +S90: + xx = *x; +S100: +/* + COMPUTE POWER SERIES +*/ + T6 = 1.0e0/pow(xx,2.0); + alngam = devlpl(coef,&K5,&T6)/xx; + alngam += (offset+(xx-0.5e0)*log(xx)-xx); +S110: + return alngam; +#undef hln2pi +} /* END */ + +/***=====================================================================***/ +static double alnrel(double *a) +/* +----------------------------------------------------------------------- + EVALUATION OF THE FUNCTION LN(1 + A) +----------------------------------------------------------------------- +*/ +{ +static double p1 = -.129418923021993e+01; +static double p2 = .405303492862024e+00; +static double p3 = -.178874546012214e-01; +static double q1 = -.162752256355323e+01; +static double q2 = .747811014037616e+00; +static double q3 = -.845104217945565e-01; +static double alnrel,t,t2,w,x; +/* + .. + .. Executable Statements .. +*/ + if(fabs(*a) > 0.375e0) goto S10; + t = *a/(*a+2.0e0); + t2 = t*t; + w = (((p3*t2+p2)*t2+p1)*t2+1.0e0)/(((q3*t2+q2)*t2+q1)*t2+1.0e0); + alnrel = 2.0e0*t*w; + return alnrel; +S10: + x = 1.e0+*a; + alnrel = log(x); + return alnrel; +} /* END */ + +/***=====================================================================***/ +static double apser(double *a,double *b,double *x,double *eps) +/* +----------------------------------------------------------------------- + APSER YIELDS THE INCOMPLETE BETA RATIO I(SUB(1-X))(B,A) FOR + A .LE. MIN(EPS,EPS*B), B*X .LE. 1, AND X .LE. 0.5. USED WHEN + A IS VERY SMALL. USE ONLY IF ABOVE INEQUALITIES ARE SATISFIED. +----------------------------------------------------------------------- +*/ +{ +static double g = .577215664901533e0; +static double apser,aj,bx,c,j,s,t,tol; +/* + .. + .. Executable Statements .. +*/ + bx = *b**x; + t = *x-bx; + if(*b**eps > 2.e-2) goto S10; + c = log(*x)+psi(b)+g+t; + goto S20; +S10: + c = log(bx)+g+t; +S20: + tol = 5.0e0**eps*fabs(c); + j = 1.0e0; + s = 0.0e0; +S30: + j += 1.0e0; + t *= (*x-bx/j); + aj = t/j; + s += aj; + if(fabs(aj) > tol) goto S30; + apser = -(*a*(c+s)); + return apser; +} /* END */ + +/***=====================================================================***/ +static double basym(double *a,double *b,double *lambda,double *eps) +/* +----------------------------------------------------------------------- + ASYMPTOTIC EXPANSION FOR IX(A,B) FOR LARGE A AND B. + LAMBDA = (A + B)*Y - B AND EPS IS THE TOLERANCE USED. + IT IS ASSUMED THAT LAMBDA IS NONNEGATIVE AND THAT + A AND B ARE GREATER THAN OR EQUAL TO 15. +----------------------------------------------------------------------- +*/ +{ +static double e0 = 1.12837916709551e0; +static double e1 = .353553390593274e0; +static int num = 20; +/* +------------------------ + ****** NUM IS THE MAXIMUM VALUE THAT N CAN TAKE IN THE DO LOOP + ENDING AT STATEMENT 50. IT IS REQUIRED THAT NUM BE EVEN. + THE ARRAYS A0, B0, C, D HAVE DIMENSION NUM + 1. +------------------------ + E0 = 2/SQRT(PI) + E1 = 2**(-3/2) +------------------------ +*/ +static int K3 = 1; +static double basym,bsum,dsum,f,h,h2,hn,j0,j1,r,r0,r1,s,sum,t,t0,t1,u,w,w0,z,z0, + z2,zn,znm1; +static int i,im1,imj,j,m,mm1,mmj,n,np1; +static double a0[21],b0[21],c[21],d[21],T1,T2; +/* + .. + .. Executable Statements .. +*/ + basym = 0.0e0; + if(*a >= *b) goto S10; + h = *a/ *b; + r0 = 1.0e0/(1.0e0+h); + r1 = (*b-*a)/ *b; + w0 = 1.0e0/sqrt(*a*(1.0e0+h)); + goto S20; +S10: + h = *b/ *a; + r0 = 1.0e0/(1.0e0+h); + r1 = (*b-*a)/ *a; + w0 = 1.0e0/sqrt(*b*(1.0e0+h)); +S20: + T1 = -(*lambda/ *a); + T2 = *lambda/ *b; + f = *a*rlog1(&T1)+*b*rlog1(&T2); + t = exp(-f); + if(t == 0.0e0) return basym; + z0 = sqrt(f); + z = 0.5e0*(z0/e1); + z2 = f+f; + a0[0] = 2.0e0/3.0e0*r1; + c[0] = -(0.5e0*a0[0]); + d[0] = -c[0]; + j0 = 0.5e0/e0*erfc1(&K3,&z0); + j1 = e1; + sum = j0+d[0]*w0*j1; + s = 1.0e0; + h2 = h*h; + hn = 1.0e0; + w = w0; + znm1 = z; + zn = z2; + for(n=2; n<=num; n+=2) { + hn = h2*hn; + a0[n-1] = 2.0e0*r0*(1.0e0+h*hn)/((double)n+2.0e0); + np1 = n+1; + s += hn; + a0[np1-1] = 2.0e0*r1*s/((double)n+3.0e0); + for(i=n; i<=np1; i++) { + r = -(0.5e0*((double)i+1.0e0)); + b0[0] = r*a0[0]; + for(m=2; m<=i; m++) { + bsum = 0.0e0; + mm1 = m-1; + for(j=1; j<=mm1; j++) { + mmj = m-j; + bsum += (((double)j*r-(double)mmj)*a0[j-1]*b0[mmj-1]); + } + b0[m-1] = r*a0[m-1]+bsum/(double)m; + } + c[i-1] = b0[i-1]/((double)i+1.0e0); + dsum = 0.0e0; + im1 = i-1; + for(j=1; j<=im1; j++) { + imj = i-j; + dsum += (d[imj-1]*c[j-1]); + } + d[i-1] = -(dsum+c[i-1]); + } + j0 = e1*znm1+((double)n-1.0e0)*j0; + j1 = e1*zn+(double)n*j1; + znm1 = z2*znm1; + zn = z2*zn; + w = w0*w; + t0 = d[n-1]*w*j0; + w = w0*w; + t1 = d[np1-1]*w*j1; + sum += (t0+t1); + if(fabs(t0)+fabs(t1) <= *eps*sum) goto S80; + } +S80: + u = exp(-bcorr(a,b)); + basym = e0*t*u*sum; + return basym; +} /* END */ + +/***=====================================================================***/ +static double bcorr(double *a0,double *b0) +/* +----------------------------------------------------------------------- + + EVALUATION OF DEL(A0) + DEL(B0) - DEL(A0 + B0) WHERE + LN(GAMMA(A)) = (A - 0.5)*LN(A) - A + 0.5*LN(2*PI) + DEL(A). + IT IS ASSUMED THAT A0 .GE. 8 AND B0 .GE. 8. + +----------------------------------------------------------------------- +*/ +{ +static double c0 = .833333333333333e-01; +static double c1 = -.277777777760991e-02; +static double c2 = .793650666825390e-03; +static double c3 = -.595202931351870e-03; +static double c4 = .837308034031215e-03; +static double c5 = -.165322962780713e-02; +static double bcorr,a,b,c,h,s11,s3,s5,s7,s9,t,w,x,x2; +/* + .. + .. Executable Statements .. +*/ + a = fifdmin1(*a0,*b0); + b = fifdmax1(*a0,*b0); + h = a/b; + c = h/(1.0e0+h); + x = 1.0e0/(1.0e0+h); + x2 = x*x; +/* + SET SN = (1 - X**N)/(1 - X) +*/ + s3 = 1.0e0+(x+x2); + s5 = 1.0e0+(x+x2*s3); + s7 = 1.0e0+(x+x2*s5); + s9 = 1.0e0+(x+x2*s7); + s11 = 1.0e0+(x+x2*s9); +/* + SET W = DEL(B) - DEL(A + B) +*/ + t = pow(1.0e0/b,2.0); + w = ((((c5*s11*t+c4*s9)*t+c3*s7)*t+c2*s5)*t+c1*s3)*t+c0; + w *= (c/b); +/* + COMPUTE DEL(A) + W +*/ + t = pow(1.0e0/a,2.0); + bcorr = (((((c5*t+c4)*t+c3)*t+c2)*t+c1)*t+c0)/a+w; + return bcorr; +} /* END */ + +/***=====================================================================***/ +static double betaln(double *a0,double *b0) +/* +----------------------------------------------------------------------- + EVALUATION OF THE LOGARITHM OF THE BETA FUNCTION +----------------------------------------------------------------------- + E = 0.5*LN(2*PI) +-------------------------- +*/ +{ +static double e = .918938533204673e0; +static double betaln,a,b,c,h,u,v,w,z; +static int i,n; +static double T1; +/* + .. + .. Executable Statements .. +*/ + a = fifdmin1(*a0,*b0); + b = fifdmax1(*a0,*b0); + if(a >= 8.0e0) goto S100; + if(a >= 1.0e0) goto S20; +/* +----------------------------------------------------------------------- + PROCEDURE WHEN A .LT. 1 +----------------------------------------------------------------------- +*/ + if(b >= 8.0e0) goto S10; + T1 = a+b; + betaln = gamln(&a)+(gamln(&b)-gamln(&T1)); + return betaln; +S10: + betaln = gamln(&a)+algdiv(&a,&b); + return betaln; +S20: +/* +----------------------------------------------------------------------- + PROCEDURE WHEN 1 .LE. A .LT. 8 +----------------------------------------------------------------------- +*/ + if(a > 2.0e0) goto S40; + if(b > 2.0e0) goto S30; + betaln = gamln(&a)+gamln(&b)-gsumln(&a,&b); + return betaln; +S30: + w = 0.0e0; + if(b < 8.0e0) goto S60; + betaln = gamln(&a)+algdiv(&a,&b); + return betaln; +S40: +/* + REDUCTION OF A WHEN B .LE. 1000 +*/ + if(b > 1000.0e0) goto S80; + n = a-1.0e0; + w = 1.0e0; + for(i=1; i<=n; i++) { + a -= 1.0e0; + h = a/b; + w *= (h/(1.0e0+h)); + } + w = log(w); + if(b < 8.0e0) goto S60; + betaln = w+gamln(&a)+algdiv(&a,&b); + return betaln; +S60: +/* + REDUCTION OF B WHEN B .LT. 8 +*/ + n = b-1.0e0; + z = 1.0e0; + for(i=1; i<=n; i++) { + b -= 1.0e0; + z *= (b/(a+b)); + } + betaln = w+log(z)+(gamln(&a)+(gamln(&b)-gsumln(&a,&b))); + return betaln; +S80: +/* + REDUCTION OF A WHEN B .GT. 1000 +*/ + n = a-1.0e0; + w = 1.0e0; + for(i=1; i<=n; i++) { + a -= 1.0e0; + w *= (a/(1.0e0+a/b)); + } + betaln = log(w)-(double)n*log(b)+(gamln(&a)+algdiv(&a,&b)); + return betaln; +S100: +/* +----------------------------------------------------------------------- + PROCEDURE WHEN A .GE. 8 +----------------------------------------------------------------------- +*/ + w = bcorr(&a,&b); + h = a/b; + c = h/(1.0e0+h); + u = -((a-0.5e0)*log(c)); + v = b*alnrel(&h); + if(u <= v) goto S110; + betaln = -(0.5e0*log(b))+e+w-v-u; + return betaln; +S110: + betaln = -(0.5e0*log(b))+e+w-u-v; + return betaln; +} /* END */ + +/***=====================================================================***/ +static double bfrac(double *a,double *b,double *x,double *y,double *lambda, + double *eps) +/* +----------------------------------------------------------------------- + CONTINUED FRACTION EXPANSION FOR IX(A,B) WHEN A,B .GT. 1. + IT IS ASSUMED THAT LAMBDA = (A + B)*Y - B. +----------------------------------------------------------------------- +*/ +{ +static double bfrac,alpha,an,anp1,beta,bn,bnp1,c,c0,c1,e,n,p,r,r0,s,t,w,yp1; +/* + .. + .. Executable Statements .. +*/ + bfrac = brcomp(a,b,x,y); + if(bfrac == 0.0e0) return bfrac; + c = 1.0e0+*lambda; + c0 = *b/ *a; + c1 = 1.0e0+1.0e0/ *a; + yp1 = *y+1.0e0; + n = 0.0e0; + p = 1.0e0; + s = *a+1.0e0; + an = 0.0e0; + bn = anp1 = 1.0e0; + bnp1 = c/c1; + r = c1/c; +S10: +/* + CONTINUED FRACTION CALCULATION +*/ + n += 1.0e0; + t = n/ *a; + w = n*(*b-n)**x; + e = *a/s; + alpha = p*(p+c0)*e*e*(w**x); + e = (1.0e0+t)/(c1+t+t); + beta = n+w/s+e*(c+n*yp1); + p = 1.0e0+t; + s += 2.0e0; +/* + UPDATE AN, BN, ANP1, AND BNP1 +*/ + t = alpha*an+beta*anp1; + an = anp1; + anp1 = t; + t = alpha*bn+beta*bnp1; + bn = bnp1; + bnp1 = t; + r0 = r; + r = anp1/bnp1; + if(fabs(r-r0) <= *eps*r) goto S20; +/* + RESCALE AN, BN, ANP1, AND BNP1 +*/ + an /= bnp1; + bn /= bnp1; + anp1 = r; + bnp1 = 1.0e0; + goto S10; +S20: +/* + TERMINATION +*/ + bfrac *= r; + return bfrac; +} /* END */ + +/***=====================================================================***/ +static void bgrat(double *a,double *b,double *x,double *y,double *w, + double *eps,int *ierr) +/* +----------------------------------------------------------------------- + ASYMPTOTIC EXPANSION FOR IX(A,B) WHEN A IS LARGER THAN B. + THE RESULT OF THE EXPANSION IS ADDED TO W. IT IS ASSUMED + THAT A .GE. 15 AND B .LE. 1. EPS IS THE TOLERANCE USED. + IERR IS A VARIABLE THAT REPORTS THE STATUS OF THE RESULTS. +----------------------------------------------------------------------- +*/ +{ +static double bm1,bp2n,cn,coef,dj,j,l,lnx,n2,nu,p,q,r,s,sum,t,t2,u,v,z; +static int i,n,nm1; +static double c[30],d[30],T1; +/* + .. + .. Executable Statements .. +*/ + bm1 = *b-0.5e0-0.5e0; + nu = *a+0.5e0*bm1; + if(*y > 0.375e0) goto S10; + T1 = -*y; + lnx = alnrel(&T1); + goto S20; +S10: + lnx = log(*x); +S20: + z = -(nu*lnx); + if(*b*z == 0.0e0) goto S70; +/* + COMPUTATION OF THE EXPANSION + SET R = EXP(-Z)*Z**B/GAMMA(B) +*/ + r = *b*(1.0e0+gam1(b))*exp(*b*log(z)); + r *= (exp(*a*lnx)*exp(0.5e0*bm1*lnx)); + u = algdiv(b,a)+*b*log(nu); + u = r*exp(-u); + if(u == 0.0e0) goto S70; + grat1(b,&z,&r,&p,&q,eps); + v = 0.25e0*pow(1.0e0/nu,2.0); + t2 = 0.25e0*lnx*lnx; + l = *w/u; + j = q/r; + sum = j; + t = cn = 1.0e0; + n2 = 0.0e0; + for(n=1; n<=30; n++) { + bp2n = *b+n2; + j = (bp2n*(bp2n+1.0e0)*j+(z+bp2n+1.0e0)*t)*v; + n2 += 2.0e0; + t *= t2; + cn /= (n2*(n2+1.0e0)); + c[n-1] = cn; + s = 0.0e0; + if(n == 1) goto S40; + nm1 = n-1; + coef = *b-(double)n; + for(i=1; i<=nm1; i++) { + s += (coef*c[i-1]*d[n-i-1]); + coef += *b; + } +S40: + d[n-1] = bm1*cn+s/(double)n; + dj = d[n-1]*j; + sum += dj; + if(sum <= 0.0e0) goto S70; + if(fabs(dj) <= *eps*(sum+l)) goto S60; + } +S60: +/* + ADD THE RESULTS TO W +*/ + *ierr = 0; + *w += (u*sum); + return; +S70: +/* + THE EXPANSION CANNOT BE COMPUTED +*/ + *ierr = 1; + return; +} /* END */ + +/***=====================================================================***/ +static double bpser(double *a,double *b,double *x,double *eps) +/* +----------------------------------------------------------------------- + POWER SERIES EXPANSION FOR EVALUATING IX(A,B) WHEN B .LE. 1 + OR B*X .LE. 0.7. EPS IS THE TOLERANCE USED. +----------------------------------------------------------------------- +*/ +{ +static double bpser,a0,apb,b0,c,n,sum,t,tol,u,w,z; +static int i,m; +/* + .. + .. Executable Statements .. +*/ + bpser = 0.0e0; + if(*x == 0.0e0) return bpser; +/* +----------------------------------------------------------------------- + COMPUTE THE FACTOR X**A/(A*BETA(A,B)) +----------------------------------------------------------------------- +*/ + a0 = fifdmin1(*a,*b); + if(a0 < 1.0e0) goto S10; + z = *a*log(*x)-betaln(a,b); + bpser = exp(z)/ *a; + goto S100; +S10: + b0 = fifdmax1(*a,*b); + if(b0 >= 8.0e0) goto S90; + if(b0 > 1.0e0) goto S40; +/* + PROCEDURE FOR A0 .LT. 1 AND B0 .LE. 1 +*/ + bpser = pow(*x,*a); + if(bpser == 0.0e0) return bpser; + apb = *a+*b; + if(apb > 1.0e0) goto S20; + z = 1.0e0+gam1(&apb); + goto S30; +S20: + u = *a+*b-1.e0; + z = (1.0e0+gam1(&u))/apb; +S30: + c = (1.0e0+gam1(a))*(1.0e0+gam1(b))/z; + bpser *= (c*(*b/apb)); + goto S100; +S40: +/* + PROCEDURE FOR A0 .LT. 1 AND 1 .LT. B0 .LT. 8 +*/ + u = gamln1(&a0); + m = b0-1.0e0; + if(m < 1) goto S60; + c = 1.0e0; + for(i=1; i<=m; i++) { + b0 -= 1.0e0; + c *= (b0/(a0+b0)); + } + u = log(c)+u; +S60: + z = *a*log(*x)-u; + b0 -= 1.0e0; + apb = a0+b0; + if(apb > 1.0e0) goto S70; + t = 1.0e0+gam1(&apb); + goto S80; +S70: + u = a0+b0-1.e0; + t = (1.0e0+gam1(&u))/apb; +S80: + bpser = exp(z)*(a0/ *a)*(1.0e0+gam1(&b0))/t; + goto S100; +S90: +/* + PROCEDURE FOR A0 .LT. 1 AND B0 .GE. 8 +*/ + u = gamln1(&a0)+algdiv(&a0,&b0); + z = *a*log(*x)-u; + bpser = a0/ *a*exp(z); +S100: + if(bpser == 0.0e0 || *a <= 0.1e0**eps) return bpser; +/* +----------------------------------------------------------------------- + COMPUTE THE SERIES +----------------------------------------------------------------------- +*/ + sum = n = 0.0e0; + c = 1.0e0; + tol = *eps/ *a; +S110: + n += 1.0e0; + c *= ((0.5e0+(0.5e0-*b/n))**x); + w = c/(*a+n); + sum += w; + if(fabs(w) > tol) goto S110; + bpser *= (1.0e0+*a*sum); + return bpser; +} /* END */ + +/***=====================================================================***/ +static void bratio(double *a,double *b,double *x,double *y,double *w, + double *w1,int *ierr) +/* +----------------------------------------------------------------------- + + EVALUATION OF THE INCOMPLETE BETA FUNCTION IX(A,B) + + -------------------- + + IT IS ASSUMED THAT A AND B ARE NONNEGATIVE, AND THAT X .LE. 1 + AND Y = 1 - X. BRATIO ASSIGNS W AND W1 THE VALUES + + W = IX(A,B) + W1 = 1 - IX(A,B) + + IERR IS A VARIABLE THAT REPORTS THE STATUS OF THE RESULTS. + IF NO INPUT ERRORS ARE DETECTED THEN IERR IS SET TO 0 AND + W AND W1 ARE COMPUTED. OTHERWISE, IF AN ERROR IS DETECTED, + THEN W AND W1 ARE ASSIGNED THE VALUE 0 AND IERR IS SET TO + ONE OF THE FOLLOWING VALUES ... + + IERR = 1 IF A OR B IS NEGATIVE + IERR = 2 IF A = B = 0 + IERR = 3 IF X .LT. 0 OR X .GT. 1 + IERR = 4 IF Y .LT. 0 OR Y .GT. 1 + IERR = 5 IF X + Y .NE. 1 + IERR = 6 IF X = A = 0 + IERR = 7 IF Y = B = 0 + +-------------------- + WRITTEN BY ALFRED H. MORRIS, JR. + NAVAL SURFACE WARFARE CENTER + DAHLGREN, VIRGINIA + REVISED ... NOV 1991 +----------------------------------------------------------------------- +*/ +{ +static int K1 = 1; +static double a0,b0,eps,lambda,t,x0,y0,z; +static int ierr1,ind,n; +static double T2,T3,T4,T5; +/* + .. + .. Executable Statements .. +*/ +/* + ****** EPS IS A MACHINE DEPENDENT CONSTANT. EPS IS THE SMALLEST + FLOATING POINT NUMBER FOR WHICH 1.0 + EPS .GT. 1.0 +*/ + eps = spmpar(&K1); + *w = *w1 = 0.0e0; + if(*a < 0.0e0 || *b < 0.0e0) goto S270; + if(*a == 0.0e0 && *b == 0.0e0) goto S280; + if(*x < 0.0e0 || *x > 1.0e0) goto S290; + if(*y < 0.0e0 || *y > 1.0e0) goto S300; + z = *x+*y-0.5e0-0.5e0; + if(fabs(z) > 3.0e0*eps) goto S310; + *ierr = 0; + if(*x == 0.0e0) goto S210; + if(*y == 0.0e0) goto S230; + if(*a == 0.0e0) goto S240; + if(*b == 0.0e0) goto S220; + eps = fifdmax1(eps,1.e-15); + if(fifdmax1(*a,*b) < 1.e-3*eps) goto S260; + ind = 0; + a0 = *a; + b0 = *b; + x0 = *x; + y0 = *y; + if(fifdmin1(a0,b0) > 1.0e0) goto S40; +/* + PROCEDURE FOR A0 .LE. 1 OR B0 .LE. 1 +*/ + if(*x <= 0.5e0) goto S10; + ind = 1; + a0 = *b; + b0 = *a; + x0 = *y; + y0 = *x; +S10: + if(b0 < fifdmin1(eps,eps*a0)) goto S90; + if(a0 < fifdmin1(eps,eps*b0) && b0*x0 <= 1.0e0) goto S100; + if(fifdmax1(a0,b0) > 1.0e0) goto S20; + if(a0 >= fifdmin1(0.2e0,b0)) goto S110; + if(pow(x0,a0) <= 0.9e0) goto S110; + if(x0 >= 0.3e0) goto S120; + n = 20; + goto S140; +S20: + if(b0 <= 1.0e0) goto S110; + if(x0 >= 0.3e0) goto S120; + if(x0 >= 0.1e0) goto S30; + if(pow(x0*b0,a0) <= 0.7e0) goto S110; +S30: + if(b0 > 15.0e0) goto S150; + n = 20; + goto S140; +S40: +/* + PROCEDURE FOR A0 .GT. 1 AND B0 .GT. 1 +*/ + if(*a > *b) goto S50; + lambda = *a-(*a+*b)**x; + goto S60; +S50: + lambda = (*a+*b)**y-*b; +S60: + if(lambda >= 0.0e0) goto S70; + ind = 1; + a0 = *b; + b0 = *a; + x0 = *y; + y0 = *x; + lambda = fabs(lambda); +S70: + if(b0 < 40.0e0 && b0*x0 <= 0.7e0) goto S110; + if(b0 < 40.0e0) goto S160; + if(a0 > b0) goto S80; + if(a0 <= 100.0e0) goto S130; + if(lambda > 0.03e0*a0) goto S130; + goto S200; +S80: + if(b0 <= 100.0e0) goto S130; + if(lambda > 0.03e0*b0) goto S130; + goto S200; +S90: +/* + EVALUATION OF THE APPROPRIATE ALGORITHM +*/ + *w = fpser(&a0,&b0,&x0,&eps); + *w1 = 0.5e0+(0.5e0-*w); + goto S250; +S100: + *w1 = apser(&a0,&b0,&x0,&eps); + *w = 0.5e0+(0.5e0-*w1); + goto S250; +S110: + *w = bpser(&a0,&b0,&x0,&eps); + *w1 = 0.5e0+(0.5e0-*w); + goto S250; +S120: + *w1 = bpser(&b0,&a0,&y0,&eps); + *w = 0.5e0+(0.5e0-*w1); + goto S250; +S130: + T2 = 15.0e0*eps; + *w = bfrac(&a0,&b0,&x0,&y0,&lambda,&T2); + *w1 = 0.5e0+(0.5e0-*w); + goto S250; +S140: + *w1 = bup(&b0,&a0,&y0,&x0,&n,&eps); + b0 += (double)n; +S150: + T3 = 15.0e0*eps; + bgrat(&b0,&a0,&y0,&x0,w1,&T3,&ierr1); + *w = 0.5e0+(0.5e0-*w1); + goto S250; +S160: + n = b0; + b0 -= (double)n; + if(b0 != 0.0e0) goto S170; + n -= 1; + b0 = 1.0e0; +S170: + *w = bup(&b0,&a0,&y0,&x0,&n,&eps); + if(x0 > 0.7e0) goto S180; + *w += bpser(&a0,&b0,&x0,&eps); + *w1 = 0.5e0+(0.5e0-*w); + goto S250; +S180: + if(a0 > 15.0e0) goto S190; + n = 20; + *w += bup(&a0,&b0,&x0,&y0,&n,&eps); + a0 += (double)n; +S190: + T4 = 15.0e0*eps; + bgrat(&a0,&b0,&x0,&y0,w,&T4,&ierr1); + *w1 = 0.5e0+(0.5e0-*w); + goto S250; +S200: + T5 = 100.0e0*eps; + *w = basym(&a0,&b0,&lambda,&T5); + *w1 = 0.5e0+(0.5e0-*w); + goto S250; +S210: +/* + TERMINATION OF THE PROCEDURE +*/ + if(*a == 0.0e0) goto S320; +S220: + *w = 0.0e0; + *w1 = 1.0e0; + return; +S230: + if(*b == 0.0e0) goto S330; +S240: + *w = 1.0e0; + *w1 = 0.0e0; + return; +S250: + if(ind == 0) return; + t = *w; + *w = *w1; + *w1 = t; + return; +S260: +/* + PROCEDURE FOR A AND B .LT. 1.E-3*EPS +*/ + *w = *b/(*a+*b); + *w1 = *a/(*a+*b); + return; +S270: +/* + ERROR RETURN +*/ + *ierr = 1; + return; +S280: + *ierr = 2; + return; +S290: + *ierr = 3; + return; +S300: + *ierr = 4; + return; +S310: + *ierr = 5; + return; +S320: + *ierr = 6; + return; +S330: + *ierr = 7; + return; +} /* END */ + +/***=====================================================================***/ +static double brcmp1(int *mu,double *a,double *b,double *x,double *y) +/* +----------------------------------------------------------------------- + EVALUATION OF EXP(MU) * (X**A*Y**B/BETA(A,B)) +----------------------------------------------------------------------- +*/ +{ +static double Const = .398942280401433e0; +static double brcmp1,a0,apb,b0,c,e,h,lambda,lnx,lny,t,u,v,x0,y0,z; +static int i,n; +/* +----------------- + CONST = 1/SQRT(2*PI) +----------------- +*/ +static double T1,T2,T3,T4; +/* + .. + .. Executable Statements .. +*/ + a0 = fifdmin1(*a,*b); + if(a0 >= 8.0e0) goto S130; + if(*x > 0.375e0) goto S10; + lnx = log(*x); + T1 = -*x; + lny = alnrel(&T1); + goto S30; +S10: + if(*y > 0.375e0) goto S20; + T2 = -*y; + lnx = alnrel(&T2); + lny = log(*y); + goto S30; +S20: + lnx = log(*x); + lny = log(*y); +S30: + z = *a*lnx+*b*lny; + if(a0 < 1.0e0) goto S40; + z -= betaln(a,b); + brcmp1 = esum(mu,&z); + return brcmp1; +S40: +/* +----------------------------------------------------------------------- + PROCEDURE FOR A .LT. 1 OR B .LT. 1 +----------------------------------------------------------------------- +*/ + b0 = fifdmax1(*a,*b); + if(b0 >= 8.0e0) goto S120; + if(b0 > 1.0e0) goto S70; +/* + ALGORITHM FOR B0 .LE. 1 +*/ + brcmp1 = esum(mu,&z); + if(brcmp1 == 0.0e0) return brcmp1; + apb = *a+*b; + if(apb > 1.0e0) goto S50; + z = 1.0e0+gam1(&apb); + goto S60; +S50: + u = *a+*b-1.e0; + z = (1.0e0+gam1(&u))/apb; +S60: + c = (1.0e0+gam1(a))*(1.0e0+gam1(b))/z; + brcmp1 = brcmp1*(a0*c)/(1.0e0+a0/b0); + return brcmp1; +S70: +/* + ALGORITHM FOR 1 .LT. B0 .LT. 8 +*/ + u = gamln1(&a0); + n = b0-1.0e0; + if(n < 1) goto S90; + c = 1.0e0; + for(i=1; i<=n; i++) { + b0 -= 1.0e0; + c *= (b0/(a0+b0)); + } + u = log(c)+u; +S90: + z -= u; + b0 -= 1.0e0; + apb = a0+b0; + if(apb > 1.0e0) goto S100; + t = 1.0e0+gam1(&apb); + goto S110; +S100: + u = a0+b0-1.e0; + t = (1.0e0+gam1(&u))/apb; +S110: + brcmp1 = a0*esum(mu,&z)*(1.0e0+gam1(&b0))/t; + return brcmp1; +S120: +/* + ALGORITHM FOR B0 .GE. 8 +*/ + u = gamln1(&a0)+algdiv(&a0,&b0); + T3 = z-u; + brcmp1 = a0*esum(mu,&T3); + return brcmp1; +S130: +/* +----------------------------------------------------------------------- + PROCEDURE FOR A .GE. 8 AND B .GE. 8 +----------------------------------------------------------------------- +*/ + if(*a > *b) goto S140; + h = *a/ *b; + x0 = h/(1.0e0+h); + y0 = 1.0e0/(1.0e0+h); + lambda = *a-(*a+*b)**x; + goto S150; +S140: + h = *b/ *a; + x0 = 1.0e0/(1.0e0+h); + y0 = h/(1.0e0+h); + lambda = (*a+*b)**y-*b; +S150: + e = -(lambda/ *a); + if(fabs(e) > 0.6e0) goto S160; + u = rlog1(&e); + goto S170; +S160: + u = e-log(*x/x0); +S170: + e = lambda/ *b; + if(fabs(e) > 0.6e0) goto S180; + v = rlog1(&e); + goto S190; +S180: + v = e-log(*y/y0); +S190: + T4 = -(*a*u+*b*v); + z = esum(mu,&T4); + brcmp1 = Const*sqrt(*b*x0)*z*exp(-bcorr(a,b)); + return brcmp1; +} /* END */ + +/***=====================================================================***/ +static double brcomp(double *a,double *b,double *x,double *y) +/* +----------------------------------------------------------------------- + EVALUATION OF X**A*Y**B/BETA(A,B) +----------------------------------------------------------------------- +*/ +{ +static double Const = .398942280401433e0; +static double brcomp,a0,apb,b0,c,e,h,lambda,lnx,lny,t,u,v,x0,y0,z; +static int i,n; +/* +----------------- + CONST = 1/SQRT(2*PI) +----------------- +*/ +static double T1,T2; +/* + .. + .. Executable Statements .. +*/ + brcomp = 0.0e0; + if(*x == 0.0e0 || *y == 0.0e0) return brcomp; + a0 = fifdmin1(*a,*b); + if(a0 >= 8.0e0) goto S130; + if(*x > 0.375e0) goto S10; + lnx = log(*x); + T1 = -*x; + lny = alnrel(&T1); + goto S30; +S10: + if(*y > 0.375e0) goto S20; + T2 = -*y; + lnx = alnrel(&T2); + lny = log(*y); + goto S30; +S20: + lnx = log(*x); + lny = log(*y); +S30: + z = *a*lnx+*b*lny; + if(a0 < 1.0e0) goto S40; + z -= betaln(a,b); + brcomp = exp(z); + return brcomp; +S40: +/* +----------------------------------------------------------------------- + PROCEDURE FOR A .LT. 1 OR B .LT. 1 +----------------------------------------------------------------------- +*/ + b0 = fifdmax1(*a,*b); + if(b0 >= 8.0e0) goto S120; + if(b0 > 1.0e0) goto S70; +/* + ALGORITHM FOR B0 .LE. 1 +*/ + brcomp = exp(z); + if(brcomp == 0.0e0) return brcomp; + apb = *a+*b; + if(apb > 1.0e0) goto S50; + z = 1.0e0+gam1(&apb); + goto S60; +S50: + u = *a+*b-1.e0; + z = (1.0e0+gam1(&u))/apb; +S60: + c = (1.0e0+gam1(a))*(1.0e0+gam1(b))/z; + brcomp = brcomp*(a0*c)/(1.0e0+a0/b0); + return brcomp; +S70: +/* + ALGORITHM FOR 1 .LT. B0 .LT. 8 +*/ + u = gamln1(&a0); + n = b0-1.0e0; + if(n < 1) goto S90; + c = 1.0e0; + for(i=1; i<=n; i++) { + b0 -= 1.0e0; + c *= (b0/(a0+b0)); + } + u = log(c)+u; +S90: + z -= u; + b0 -= 1.0e0; + apb = a0+b0; + if(apb > 1.0e0) goto S100; + t = 1.0e0+gam1(&apb); + goto S110; +S100: + u = a0+b0-1.e0; + t = (1.0e0+gam1(&u))/apb; +S110: + brcomp = a0*exp(z)*(1.0e0+gam1(&b0))/t; + return brcomp; +S120: +/* + ALGORITHM FOR B0 .GE. 8 +*/ + u = gamln1(&a0)+algdiv(&a0,&b0); + brcomp = a0*exp(z-u); + return brcomp; +S130: +/* +----------------------------------------------------------------------- + PROCEDURE FOR A .GE. 8 AND B .GE. 8 +----------------------------------------------------------------------- +*/ + if(*a > *b) goto S140; + h = *a/ *b; + x0 = h/(1.0e0+h); + y0 = 1.0e0/(1.0e0+h); + lambda = *a-(*a+*b)**x; + goto S150; +S140: + h = *b/ *a; + x0 = 1.0e0/(1.0e0+h); + y0 = h/(1.0e0+h); + lambda = (*a+*b)**y-*b; +S150: + e = -(lambda/ *a); + if(fabs(e) > 0.6e0) goto S160; + u = rlog1(&e); + goto S170; +S160: + u = e-log(*x/x0); +S170: + e = lambda/ *b; + if(fabs(e) > 0.6e0) goto S180; + v = rlog1(&e); + goto S190; +S180: + v = e-log(*y/y0); +S190: + z = exp(-(*a*u+*b*v)); + brcomp = Const*sqrt(*b*x0)*z*exp(-bcorr(a,b)); + return brcomp; +} /* END */ + +/***=====================================================================***/ +static double bup(double *a,double *b,double *x,double *y,int *n,double *eps) +/* +----------------------------------------------------------------------- + EVALUATION OF IX(A,B) - IX(A+N,B) WHERE N IS A POSITIVE INTEGER. + EPS IS THE TOLERANCE USED. +----------------------------------------------------------------------- +*/ +{ +static int K1 = 1; +static int K2 = 0; +static double bup,ap1,apb,d,l,r,t,w; +static int i,k,kp1,mu,nm1; +/* + .. + .. Executable Statements .. +*/ +/* + OBTAIN THE SCALING FACTOR EXP(-MU) AND + EXP(MU)*(X**A*Y**B/BETA(A,B))/A +*/ + apb = *a+*b; + ap1 = *a+1.0e0; + mu = 0; + d = 1.0e0; + if(*n == 1 || *a < 1.0e0) goto S10; + if(apb < 1.1e0*ap1) goto S10; + mu = fabs(exparg(&K1)); + k = exparg(&K2); + if(k < mu) mu = k; + t = mu; + d = exp(-t); +S10: + bup = brcmp1(&mu,a,b,x,y)/ *a; + if(*n == 1 || bup == 0.0e0) return bup; + nm1 = *n-1; + w = d; +/* + LET K BE THE INDEX OF THE MAXIMUM TERM +*/ + k = 0; + if(*b <= 1.0e0) goto S50; + if(*y > 1.e-4) goto S20; + k = nm1; + goto S30; +S20: + r = (*b-1.0e0)**x/ *y-*a; + if(r < 1.0e0) goto S50; + k = t = nm1; + if(r < t) k = r; +S30: +/* + ADD THE INCREASING TERMS OF THE SERIES +*/ + for(i=1; i<=k; i++) { + l = i-1; + d = (apb+l)/(ap1+l)**x*d; + w += d; + } + if(k == nm1) goto S70; +S50: +/* + ADD THE REMAINING TERMS OF THE SERIES +*/ + kp1 = k+1; + for(i=kp1; i<=nm1; i++) { + l = i-1; + d = (apb+l)/(ap1+l)**x*d; + w += d; + if(d <= *eps*w) goto S70; + } +S70: +/* + TERMINATE THE PROCEDURE +*/ + bup *= w; + return bup; +} /* END */ + +/***=====================================================================***/ +static void cdfbet(int *which,double *p,double *q,double *x,double *y, + double *a,double *b,int *status,double *bound) +/********************************************************************** + + void cdfbet(int *which,double *p,double *q,double *x,double *y, + double *a,double *b,int *status,double *bound) + + Cumulative Distribution Function + BETa Distribution + + + Function + + + Calculates any one parameter of the beta distribution given + values for the others. + + + Arguments + + + WHICH --> Integer indicating which of the next four argument + values is to be calculated from the others. + Legal range: 1..4 + iwhich = 1 : Calculate P and Q from X,Y,A and B + iwhich = 2 : Calculate X and Y from P,Q,A and B + iwhich = 3 : Calculate A from P,Q,X,Y and B + iwhich = 4 : Calculate B from P,Q,X,Y and A + + P <--> The integral from 0 to X of the chi-square + distribution. + Input range: [0, 1]. + + Q <--> 1-P. + Input range: [0, 1]. + P + Q = 1.0. + + X <--> Upper limit of integration of beta density. + Input range: [0,1]. + Search range: [0,1] + + Y <--> 1-X. + Input range: [0,1]. + Search range: [0,1] + X + Y = 1.0. + + A <--> The first parameter of the beta density. + Input range: (0, +infinity). + Search range: [1D-300,1D300] + + B <--> The second parameter of the beta density. + Input range: (0, +infinity). + Search range: [1D-300,1D300] + + STATUS <-- 0 if calculation completed correctly + -I if input parameter number I is out of range + 1 if answer appears to be lower than lowest + search bound + 2 if answer appears to be higher than greatest + search bound + 3 if P + Q .ne. 1 + 4 if X + Y .ne. 1 + + BOUND <-- Undefined if STATUS is 0 + + Bound exceeded by parameter number I if STATUS + is negative. + + Lower search bound if STATUS is 1. + + Upper search bound if STATUS is 2. + + + Method + + + Cumulative distribution function (P) is calculated directly by + code associated with the following reference. + + DiDinato, A. R. and Morris, A. H. Algorithm 708: Significant + Digit Computation of the Incomplete Beta Function Ratios. ACM + Trans. Math. Softw. 18 (1993), 360-373. + + Computation of other parameters involve a seach for a value that + produces the desired value of P. The search relies on the + monotinicity of P with the other parameter. + + + Note + + + The beta density is proportional to + t^(A-1) * (1-t)^(B-1) + +**********************************************************************/ +{ +#define tol (1.0e-8) +#define atol (1.0e-50) +#define zero (1.0e-300) +#define inf 1.0e300 +#define one 1.0e0 +static int K1 = 1; +static double K2 = 0.0e0; +static double K3 = 1.0e0; +static double K8 = 0.5e0; +static double K9 = 5.0e0; +static double fx,xhi,xlo,cum,ccum,xy,pq; +static unsigned long qhi,qleft,qporq; +static double T4,T5,T6,T7,T10,T11,T12,T13,T14,T15; +/* + .. + .. Executable Statements .. +*/ +/* + Check arguments +*/ + if(!(*which < 1 || *which > 4)) goto S30; + if(!(*which < 1)) goto S10; + *bound = 1.0e0; + goto S20; +S10: + *bound = 4.0e0; +S20: + *status = -1; + return; +S30: + if(*which == 1) goto S70; +/* + P +*/ + if(!(*p < 0.0e0 || *p > 1.0e0)) goto S60; + if(!(*p < 0.0e0)) goto S40; + *bound = 0.0e0; + goto S50; +S40: + *bound = 1.0e0; +S50: + *status = -2; + return; +S70: +S60: + if(*which == 1) goto S110; +/* + Q +*/ + if(!(*q < 0.0e0 || *q > 1.0e0)) goto S100; + if(!(*q < 0.0e0)) goto S80; + *bound = 0.0e0; + goto S90; +S80: + *bound = 1.0e0; +S90: + *status = -3; + return; +S110: +S100: + if(*which == 2) goto S150; +/* + X +*/ + if(!(*x < 0.0e0 || *x > 1.0e0)) goto S140; + if(!(*x < 0.0e0)) goto S120; + *bound = 0.0e0; + goto S130; +S120: + *bound = 1.0e0; +S130: + *status = -4; + return; +S150: +S140: + if(*which == 2) goto S190; +/* + Y +*/ + if(!(*y < 0.0e0 || *y > 1.0e0)) goto S180; + if(!(*y < 0.0e0)) goto S160; + *bound = 0.0e0; + goto S170; +S160: + *bound = 1.0e0; +S170: + *status = -5; + return; +S190: +S180: + if(*which == 3) goto S210; +/* + A +*/ + if(!(*a <= 0.0e0)) goto S200; + *bound = 0.0e0; + *status = -6; + return; +S210: +S200: + if(*which == 4) goto S230; +/* + B +*/ + if(!(*b <= 0.0e0)) goto S220; + *bound = 0.0e0; + *status = -7; + return; +S230: +S220: + if(*which == 1) goto S270; +/* + P + Q +*/ + pq = *p+*q; + if(!(fabs(pq-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S260; + if(!(pq < 0.0e0)) goto S240; + *bound = 0.0e0; + goto S250; +S240: + *bound = 1.0e0; +S250: + *status = 3; + return; +S270: +S260: + if(*which == 2) goto S310; +/* + X + Y +*/ + xy = *x+*y; + if(!(fabs(xy-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S300; + if(!(xy < 0.0e0)) goto S280; + *bound = 0.0e0; + goto S290; +S280: + *bound = 1.0e0; +S290: + *status = 4; + return; +S310: +S300: + if(!(*which == 1)) qporq = *p <= *q; +/* + Select the minimum of P or Q + Calculate ANSWERS +*/ + if(1 == *which) { +/* + Calculating P and Q +*/ + cumbet(x,y,a,b,p,q); + *status = 0; + } + else if(2 == *which) { +/* + Calculating X and Y +*/ + T4 = atol; + T5 = tol; + dstzr(&K2,&K3,&T4,&T5); + if(!qporq) goto S340; + *status = 0; + dzror(status,x,&fx,&xlo,&xhi,&qleft,&qhi); + *y = one-*x; +S320: + if(!(*status == 1)) goto S330; + cumbet(x,y,a,b,&cum,&ccum); + fx = cum-*p; + dzror(status,x,&fx,&xlo,&xhi,&qleft,&qhi); + *y = one-*x; + goto S320; +S330: + goto S370; +S340: + *status = 0; + dzror(status,y,&fx,&xlo,&xhi,&qleft,&qhi); + *x = one-*y; +S350: + if(!(*status == 1)) goto S360; + cumbet(x,y,a,b,&cum,&ccum); + fx = ccum-*q; + dzror(status,y,&fx,&xlo,&xhi,&qleft,&qhi); + *x = one-*y; + goto S350; +S370: +S360: + if(!(*status == -1)) goto S400; + if(!qleft) goto S380; + *status = 1; + *bound = 0.0e0; + goto S390; +S380: + *status = 2; + *bound = 1.0e0; +S400: +S390: + ; + } + else if(3 == *which) { +/* + Computing A +*/ + *a = 5.0e0; + T6 = zero; + T7 = inf; + T10 = atol; + T11 = tol; + dstinv(&T6,&T7,&K8,&K8,&K9,&T10,&T11); + *status = 0; + dinvr(status,a,&fx,&qleft,&qhi); +S410: + if(!(*status == 1)) goto S440; + cumbet(x,y,a,b,&cum,&ccum); + if(!qporq) goto S420; + fx = cum-*p; + goto S430; +S420: + fx = ccum-*q; +S430: + dinvr(status,a,&fx,&qleft,&qhi); + goto S410; +S440: + if(!(*status == -1)) goto S470; + if(!qleft) goto S450; + *status = 1; + *bound = zero; + goto S460; +S450: + *status = 2; + *bound = inf; +S470: +S460: + ; + } + else if(4 == *which) { +/* + Computing B +*/ + *b = 5.0e0; + T12 = zero; + T13 = inf; + T14 = atol; + T15 = tol; + dstinv(&T12,&T13,&K8,&K8,&K9,&T14,&T15); + *status = 0; + dinvr(status,b,&fx,&qleft,&qhi); +S480: + if(!(*status == 1)) goto S510; + cumbet(x,y,a,b,&cum,&ccum); + if(!qporq) goto S490; + fx = cum-*p; + goto S500; +S490: + fx = ccum-*q; +S500: + dinvr(status,b,&fx,&qleft,&qhi); + goto S480; +S510: + if(!(*status == -1)) goto S540; + if(!qleft) goto S520; + *status = 1; + *bound = zero; + goto S530; +S520: + *status = 2; + *bound = inf; +S530: + ; + } +S540: + return; +#undef tol +#undef atol +#undef zero +#undef inf +#undef one +} /* END */ + +/***=====================================================================***/ +static void cdfbin(int *which,double *p,double *q,double *s,double *xn, + double *pr,double *ompr,int *status,double *bound) +/********************************************************************** + + void cdfbin(int *which,double *p,double *q,double *s,double *xn, + double *pr,double *ompr,int *status,double *bound) + + Cumulative Distribution Function + BINomial distribution + + + Function + + + Calculates any one parameter of the binomial + distribution given values for the others. + + + Arguments + + + WHICH --> Integer indicating which of the next four argument + values is to be calculated from the others. + Legal range: 1..4 + iwhich = 1 : Calculate P and Q from S,XN,PR and OMPR + iwhich = 2 : Calculate S from P,Q,XN,PR and OMPR + iwhich = 3 : Calculate XN from P,Q,S,PR and OMPR + iwhich = 4 : Calculate PR and OMPR from P,Q,S and XN + + P <--> The cumulation from 0 to S of the binomial distribution. + (Probablility of S or fewer successes in XN trials each + with probability of success PR.) + Input range: [0,1]. + + Q <--> 1-P. + Input range: [0, 1]. + P + Q = 1.0. + + S <--> The number of successes observed. + Input range: [0, XN] + Search range: [0, XN] + + XN <--> The number of binomial trials. + Input range: (0, +infinity). + Search range: [1E-300, 1E300] + + PR <--> The probability of success in each binomial trial. + Input range: [0,1]. + Search range: [0,1] + + OMPR <--> 1-PR + Input range: [0,1]. + Search range: [0,1] + PR + OMPR = 1.0 + + STATUS <-- 0 if calculation completed correctly + -I if input parameter number I is out of range + 1 if answer appears to be lower than lowest + search bound + 2 if answer appears to be higher than greatest + search bound + 3 if P + Q .ne. 1 + 4 if PR + OMPR .ne. 1 + + BOUND <-- Undefined if STATUS is 0 + + Bound exceeded by parameter number I if STATUS + is negative. + + Lower search bound if STATUS is 1. + + Upper search bound if STATUS is 2. + + + Method + + + Formula 26.5.24 of Abramowitz and Stegun, Handbook of + Mathematical Functions (1966) is used to reduce the binomial + distribution to the cumulative incomplete beta distribution. + + Computation of other parameters involve a seach for a value that + produces the desired value of P. The search relies on the + monotinicity of P with the other parameter. + + +**********************************************************************/ +{ +#define atol (1.0e-50) +#define tol (1.0e-8) +#define zero (1.0e-300) +#define inf 1.0e300 +#define one 1.0e0 +static int K1 = 1; +static double K2 = 0.0e0; +static double K3 = 0.5e0; +static double K4 = 5.0e0; +static double K11 = 1.0e0; +static double fx,xhi,xlo,cum,ccum,pq,prompr; +static unsigned long qhi,qleft,qporq; +static double T5,T6,T7,T8,T9,T10,T12,T13; +/* + .. + .. Executable Statements .. +*/ +/* + Check arguments +*/ + if(!(*which < 1 && *which > 4)) goto S30; + if(!(*which < 1)) goto S10; + *bound = 1.0e0; + goto S20; +S10: + *bound = 4.0e0; +S20: + *status = -1; + return; +S30: + if(*which == 1) goto S70; +/* + P +*/ + if(!(*p < 0.0e0 || *p > 1.0e0)) goto S60; + if(!(*p < 0.0e0)) goto S40; + *bound = 0.0e0; + goto S50; +S40: + *bound = 1.0e0; +S50: + *status = -2; + return; +S70: +S60: + if(*which == 1) goto S110; +/* + Q +*/ + if(!(*q < 0.0e0 || *q > 1.0e0)) goto S100; + if(!(*q < 0.0e0)) goto S80; + *bound = 0.0e0; + goto S90; +S80: + *bound = 1.0e0; +S90: + *status = -3; + return; +S110: +S100: + if(*which == 3) goto S130; +/* + XN +*/ + if(!(*xn <= 0.0e0)) goto S120; + *bound = 0.0e0; + *status = -5; + return; +S130: +S120: + if(*which == 2) goto S170; +/* + S +*/ + if(!(*s < 0.0e0 || *which != 3 && *s > *xn)) goto S160; + if(!(*s < 0.0e0)) goto S140; + *bound = 0.0e0; + goto S150; +S140: + *bound = *xn; +S150: + *status = -4; + return; +S170: +S160: + if(*which == 4) goto S210; +/* + PR +*/ + if(!(*pr < 0.0e0 || *pr > 1.0e0)) goto S200; + if(!(*pr < 0.0e0)) goto S180; + *bound = 0.0e0; + goto S190; +S180: + *bound = 1.0e0; +S190: + *status = -6; + return; +S210: +S200: + if(*which == 4) goto S250; +/* + OMPR +*/ + if(!(*ompr < 0.0e0 || *ompr > 1.0e0)) goto S240; + if(!(*ompr < 0.0e0)) goto S220; + *bound = 0.0e0; + goto S230; +S220: + *bound = 1.0e0; +S230: + *status = -7; + return; +S250: +S240: + if(*which == 1) goto S290; +/* + P + Q +*/ + pq = *p+*q; + if(!(fabs(pq-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S280; + if(!(pq < 0.0e0)) goto S260; + *bound = 0.0e0; + goto S270; +S260: + *bound = 1.0e0; +S270: + *status = 3; + return; +S290: +S280: + if(*which == 4) goto S330; +/* + PR + OMPR +*/ + prompr = *pr+*ompr; + if(!(fabs(prompr-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S320; + if(!(prompr < 0.0e0)) goto S300; + *bound = 0.0e0; + goto S310; +S300: + *bound = 1.0e0; +S310: + *status = 4; + return; +S330: +S320: + if(!(*which == 1)) qporq = *p <= *q; +/* + Select the minimum of P or Q + Calculate ANSWERS +*/ + if(1 == *which) { +/* + Calculating P +*/ + cumbin(s,xn,pr,ompr,p,q); + *status = 0; + } + else if(2 == *which) { +/* + Calculating S +*/ + *s = 5.0e0; + T5 = atol; + T6 = tol; + dstinv(&K2,xn,&K3,&K3,&K4,&T5,&T6); + *status = 0; + dinvr(status,s,&fx,&qleft,&qhi); +S340: + if(!(*status == 1)) goto S370; + cumbin(s,xn,pr,ompr,&cum,&ccum); + if(!qporq) goto S350; + fx = cum-*p; + goto S360; +S350: + fx = ccum-*q; +S360: + dinvr(status,s,&fx,&qleft,&qhi); + goto S340; +S370: + if(!(*status == -1)) goto S400; + if(!qleft) goto S380; + *status = 1; + *bound = 0.0e0; + goto S390; +S380: + *status = 2; + *bound = *xn; +S400: +S390: + ; + } + else if(3 == *which) { +/* + Calculating XN +*/ + *xn = 5.0e0; + T7 = zero; + T8 = inf; + T9 = atol; + T10 = tol; + dstinv(&T7,&T8,&K3,&K3,&K4,&T9,&T10); + *status = 0; + dinvr(status,xn,&fx,&qleft,&qhi); +S410: + if(!(*status == 1)) goto S440; + cumbin(s,xn,pr,ompr,&cum,&ccum); + if(!qporq) goto S420; + fx = cum-*p; + goto S430; +S420: + fx = ccum-*q; +S430: + dinvr(status,xn,&fx,&qleft,&qhi); + goto S410; +S440: + if(!(*status == -1)) goto S470; + if(!qleft) goto S450; + *status = 1; + *bound = zero; + goto S460; +S450: + *status = 2; + *bound = inf; +S470: +S460: + ; + } + else if(4 == *which) { +/* + Calculating PR and OMPR +*/ + T12 = atol; + T13 = tol; + dstzr(&K2,&K11,&T12,&T13); + if(!qporq) goto S500; + *status = 0; + dzror(status,pr,&fx,&xlo,&xhi,&qleft,&qhi); + *ompr = one-*pr; +S480: + if(!(*status == 1)) goto S490; + cumbin(s,xn,pr,ompr,&cum,&ccum); + fx = cum-*p; + dzror(status,pr,&fx,&xlo,&xhi,&qleft,&qhi); + *ompr = one-*pr; + goto S480; +S490: + goto S530; +S500: + *status = 0; + dzror(status,ompr,&fx,&xlo,&xhi,&qleft,&qhi); + *pr = one-*ompr; +S510: + if(!(*status == 1)) goto S520; + cumbin(s,xn,pr,ompr,&cum,&ccum); + fx = ccum-*q; + dzror(status,ompr,&fx,&xlo,&xhi,&qleft,&qhi); + *pr = one-*ompr; + goto S510; +S530: +S520: + if(!(*status == -1)) goto S560; + if(!qleft) goto S540; + *status = 1; + *bound = 0.0e0; + goto S550; +S540: + *status = 2; + *bound = 1.0e0; +S550: + ; + } +S560: + return; +#undef atol +#undef tol +#undef zero +#undef inf +#undef one +} /* END */ + +/***=====================================================================***/ +static void cdfchi(int *which,double *p,double *q,double *x,double *df, + int *status,double *bound) +/********************************************************************** + + void cdfchi(int *which,double *p,double *q,double *x,double *df, + int *status,double *bound) + + Cumulative Distribution Function + CHI-Square distribution + + + Function + + + Calculates any one parameter of the chi-square + distribution given values for the others. + + + Arguments + + + WHICH --> Integer indicating which of the next three argument + values is to be calculated from the others. + Legal range: 1..3 + iwhich = 1 : Calculate P and Q from X and DF + iwhich = 2 : Calculate X from P,Q and DF + iwhich = 3 : Calculate DF from P,Q and X + + P <--> The integral from 0 to X of the chi-square + distribution. + Input range: [0, 1]. + + Q <--> 1-P. + Input range: (0, 1]. + P + Q = 1.0. + + X <--> Upper limit of integration of the non-central + chi-square distribution. + Input range: [0, +infinity). + Search range: [0,1E300] + + DF <--> Degrees of freedom of the + chi-square distribution. + Input range: (0, +infinity). + Search range: [ 1E-300, 1E300] + + STATUS <-- 0 if calculation completed correctly + -I if input parameter number I is out of range + 1 if answer appears to be lower than lowest + search bound + 2 if answer appears to be higher than greatest + search bound + 3 if P + Q .ne. 1 + 10 indicates error returned from cumgam. See + references in cdfgam + + BOUND <-- Undefined if STATUS is 0 + + Bound exceeded by parameter number I if STATUS + is negative. + + Lower search bound if STATUS is 1. + + Upper search bound if STATUS is 2. + + + Method + + + Formula 26.4.19 of Abramowitz and Stegun, Handbook of + Mathematical Functions (1966) is used to reduce the chisqure + distribution to the incomplete distribution. + + Computation of other parameters involve a seach for a value that + produces the desired value of P. The search relies on the + monotinicity of P with the other parameter. + +**********************************************************************/ +{ +#define tol (1.0e-8) +#define atol (1.0e-50) +#define zero (1.0e-300) +#define inf 1.0e300 +static int K1 = 1; +static double K2 = 0.0e0; +static double K4 = 0.5e0; +static double K5 = 5.0e0; +static double fx,cum,ccum,pq,porq; +static unsigned long qhi,qleft,qporq; +static double T3,T6,T7,T8,T9,T10,T11; +/* + .. + .. Executable Statements .. +*/ +/* + Check arguments +*/ + if(!(*which < 1 || *which > 3)) goto S30; + if(!(*which < 1)) goto S10; + *bound = 1.0e0; + goto S20; +S10: + *bound = 3.0e0; +S20: + *status = -1; + return; +S30: + if(*which == 1) goto S70; +/* + P +*/ + if(!(*p < 0.0e0 || *p > 1.0e0)) goto S60; + if(!(*p < 0.0e0)) goto S40; + *bound = 0.0e0; + goto S50; +S40: + *bound = 1.0e0; +S50: + *status = -2; + return; +S70: +S60: + if(*which == 1) goto S110; +/* + Q +*/ + if(!(*q <= 0.0e0 || *q > 1.0e0)) goto S100; + if(!(*q <= 0.0e0)) goto S80; + *bound = 0.0e0; + goto S90; +S80: + *bound = 1.0e0; +S90: + *status = -3; + return; +S110: +S100: + if(*which == 2) goto S130; +/* + X +*/ + if(!(*x < 0.0e0)) goto S120; + *bound = 0.0e0; + *status = -4; + return; +S130: +S120: + if(*which == 3) goto S150; +/* + DF +*/ + if(!(*df <= 0.0e0)) goto S140; + *bound = 0.0e0; + *status = -5; + return; +S150: +S140: + if(*which == 1) goto S190; +/* + P + Q +*/ + pq = *p+*q; + if(!(fabs(pq-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S180; + if(!(pq < 0.0e0)) goto S160; + *bound = 0.0e0; + goto S170; +S160: + *bound = 1.0e0; +S170: + *status = 3; + return; +S190: +S180: + if(*which == 1) goto S220; +/* + Select the minimum of P or Q +*/ + qporq = *p <= *q; + if(!qporq) goto S200; + porq = *p; + goto S210; +S200: + porq = *q; +S220: +S210: +/* + Calculate ANSWERS +*/ + if(1 == *which) { +/* + Calculating P and Q +*/ + *status = 0; + cumchi(x,df,p,q); + if(porq > 1.5e0) { + *status = 10; + return; + } + } + else if(2 == *which) { +/* + Calculating X +*/ + *x = 5.0e0; + T3 = inf; + T6 = atol; + T7 = tol; + dstinv(&K2,&T3,&K4,&K4,&K5,&T6,&T7); + *status = 0; + dinvr(status,x,&fx,&qleft,&qhi); +S230: + if(!(*status == 1)) goto S270; + cumchi(x,df,&cum,&ccum); + if(!qporq) goto S240; + fx = cum-*p; + goto S250; +S240: + fx = ccum-*q; +S250: + if(!(fx+porq > 1.5e0)) goto S260; + *status = 10; + return; +S260: + dinvr(status,x,&fx,&qleft,&qhi); + goto S230; +S270: + if(!(*status == -1)) goto S300; + if(!qleft) goto S280; + *status = 1; + *bound = 0.0e0; + goto S290; +S280: + *status = 2; + *bound = inf; +S300: +S290: + ; + } + else if(3 == *which) { +/* + Calculating DF +*/ + *df = 5.0e0; + T8 = zero; + T9 = inf; + T10 = atol; + T11 = tol; + dstinv(&T8,&T9,&K4,&K4,&K5,&T10,&T11); + *status = 0; + dinvr(status,df,&fx,&qleft,&qhi); +S310: + if(!(*status == 1)) goto S350; + cumchi(x,df,&cum,&ccum); + if(!qporq) goto S320; + fx = cum-*p; + goto S330; +S320: + fx = ccum-*q; +S330: + if(!(fx+porq > 1.5e0)) goto S340; + *status = 10; + return; +S340: + dinvr(status,df,&fx,&qleft,&qhi); + goto S310; +S350: + if(!(*status == -1)) goto S380; + if(!qleft) goto S360; + *status = 1; + *bound = zero; + goto S370; +S360: + *status = 2; + *bound = inf; +S370: + ; + } +S380: + return; +#undef tol +#undef atol +#undef zero +#undef inf +} /* END */ + +/***=====================================================================***/ +static void cdfchn(int *which,double *p,double *q,double *x,double *df, + double *pnonc,int *status,double *bound) +/********************************************************************** + + void cdfchn(int *which,double *p,double *q,double *x,double *df, + double *pnonc,int *status,double *bound) + + Cumulative Distribution Function + Non-central Chi-Square + + + Function + + + Calculates any one parameter of the non-central chi-square + distribution given values for the others. + + + Arguments + + + WHICH --> Integer indicating which of the next three argument + values is to be calculated from the others. + Input range: 1..4 + iwhich = 1 : Calculate P and Q from X and DF + iwhich = 2 : Calculate X from P,DF and PNONC + iwhich = 3 : Calculate DF from P,X and PNONC + iwhich = 3 : Calculate PNONC from P,X and DF + + P <--> The integral from 0 to X of the non-central chi-square + distribution. + Input range: [0, 1-1E-16). + + Q <--> 1-P. + Q is not used by this subroutine and is only included + for similarity with other cdf* routines. + + X <--> Upper limit of integration of the non-central + chi-square distribution. + Input range: [0, +infinity). + Search range: [0,1E300] + + DF <--> Degrees of freedom of the non-central + chi-square distribution. + Input range: (0, +infinity). + Search range: [ 1E-300, 1E300] + + PNONC <--> Non-centrality parameter of the non-central + chi-square distribution. + Input range: [0, +infinity). + Search range: [0,1E4] + + STATUS <-- 0 if calculation completed correctly + -I if input parameter number I is out of range + 1 if answer appears to be lower than lowest + search bound + 2 if answer appears to be higher than greatest + search bound + + BOUND <-- Undefined if STATUS is 0 + + Bound exceeded by parameter number I if STATUS + is negative. + + Lower search bound if STATUS is 1. + + Upper search bound if STATUS is 2. + + + Method + + + Formula 26.4.25 of Abramowitz and Stegun, Handbook of + Mathematical Functions (1966) is used to compute the cumulative + distribution function. + + Computation of other parameters involve a seach for a value that + produces the desired value of P. The search relies on the + monotinicity of P with the other parameter. + + + WARNING + + The computation time required for this routine is proportional + to the noncentrality parameter (PNONC). Very large values of + this parameter can consume immense computer resources. This is + why the search range is bounded by 10,000. + +**********************************************************************/ +{ +#define tent4 1.0e4 +#define tol (1.0e-8) +#define atol (1.0e-50) +#define zero (1.0e-300) +#define one (1.0e0-1.0e-16) +#define inf 1.0e300 +static double K1 = 0.0e0; +static double K3 = 0.5e0; +static double K4 = 5.0e0; +static double fx,cum,ccum; +static unsigned long qhi,qleft; +static double T2,T5,T6,T7,T8,T9,T10,T11,T12,T13; +/* + .. + .. Executable Statements .. +*/ +/* + Check arguments +*/ + if(!(*which < 1 || *which > 4)) goto S30; + if(!(*which < 1)) goto S10; + *bound = 1.0e0; + goto S20; +S10: + *bound = 4.0e0; +S20: + *status = -1; + return; +S30: + if(*which == 1) goto S70; +/* + P +*/ + if(!(*p < 0.0e0 || *p > one)) goto S60; + if(!(*p < 0.0e0)) goto S40; + *bound = 0.0e0; + goto S50; +S40: + *bound = one; +S50: + *status = -2; + return; +S70: +S60: + if(*which == 2) goto S90; +/* + X +*/ + if(!(*x < 0.0e0)) goto S80; + *bound = 0.0e0; + *status = -4; + return; +S90: +S80: + if(*which == 3) goto S110; +/* + DF +*/ + if(!(*df <= 0.0e0)) goto S100; + *bound = 0.0e0; + *status = -5; + return; +S110: +S100: + if(*which == 4) goto S130; +/* + PNONC +*/ + if(!(*pnonc < 0.0e0)) goto S120; + *bound = 0.0e0; + *status = -6; + return; +S130: +S120: +/* + Calculate ANSWERS +*/ + if(1 == *which) { +/* + Calculating P and Q +*/ + cumchn(x,df,pnonc,p,q); + *status = 0; + } + else if(2 == *which) { +/* + Calculating X +*/ + *x = 5.0e0; + T2 = inf; + T5 = atol; + T6 = tol; + dstinv(&K1,&T2,&K3,&K3,&K4,&T5,&T6); + *status = 0; + dinvr(status,x,&fx,&qleft,&qhi); +S140: + if(!(*status == 1)) goto S150; + cumchn(x,df,pnonc,&cum,&ccum); + fx = cum-*p; + dinvr(status,x,&fx,&qleft,&qhi); + goto S140; +S150: + if(!(*status == -1)) goto S180; + if(!qleft) goto S160; + *status = 1; + *bound = 0.0e0; + goto S170; +S160: + *status = 2; + *bound = inf; +S180: +S170: + ; + } + else if(3 == *which) { +/* + Calculating DF +*/ + *df = 5.0e0; + T7 = zero; + T8 = inf; + T9 = atol; + T10 = tol; + dstinv(&T7,&T8,&K3,&K3,&K4,&T9,&T10); + *status = 0; + dinvr(status,df,&fx,&qleft,&qhi); +S190: + if(!(*status == 1)) goto S200; + cumchn(x,df,pnonc,&cum,&ccum); + fx = cum-*p; + dinvr(status,df,&fx,&qleft,&qhi); + goto S190; +S200: + if(!(*status == -1)) goto S230; + if(!qleft) goto S210; + *status = 1; + *bound = zero; + goto S220; +S210: + *status = 2; + *bound = inf; +S230: +S220: + ; + } + else if(4 == *which) { +/* + Calculating PNONC +*/ + *pnonc = 5.0e0; + T11 = tent4; + T12 = atol; + T13 = tol; + dstinv(&K1,&T11,&K3,&K3,&K4,&T12,&T13); + *status = 0; + dinvr(status,pnonc,&fx,&qleft,&qhi); +S240: + if(!(*status == 1)) goto S250; + cumchn(x,df,pnonc,&cum,&ccum); + fx = cum-*p; + dinvr(status,pnonc,&fx,&qleft,&qhi); + goto S240; +S250: + if(!(*status == -1)) goto S280; + if(!qleft) goto S260; + *status = 1; + *bound = zero; + goto S270; +S260: + *status = 2; + *bound = tent4; +S270: + ; + } +S280: + return; +#undef tent4 +#undef tol +#undef atol +#undef zero +#undef one +#undef inf +} /* END */ + +/***=====================================================================***/ +static void cdff(int *which,double *p,double *q,double *f,double *dfn, + double *dfd,int *status,double *bound) +/********************************************************************** + + void cdff(int *which,double *p,double *q,double *f,double *dfn, + double *dfd,int *status,double *bound) + + Cumulative Distribution Function + F distribution + + + Function + + + Calculates any one parameter of the F distribution + given values for the others. + + + Arguments + + + WHICH --> Integer indicating which of the next four argument + values is to be calculated from the others. + Legal range: 1..4 + iwhich = 1 : Calculate P and Q from F,DFN and DFD + iwhich = 2 : Calculate F from P,Q,DFN and DFD + iwhich = 3 : Calculate DFN from P,Q,F and DFD + iwhich = 4 : Calculate DFD from P,Q,F and DFN + + P <--> The integral from 0 to F of the f-density. + Input range: [0,1]. + + Q <--> 1-P. + Input range: (0, 1]. + P + Q = 1.0. + + F <--> Upper limit of integration of the f-density. + Input range: [0, +infinity). + Search range: [0,1E300] + + DFN < --> Degrees of freedom of the numerator sum of squares. + Input range: (0, +infinity). + Search range: [ 1E-300, 1E300] + + DFD < --> Degrees of freedom of the denominator sum of squares. + Input range: (0, +infinity). + Search range: [ 1E-300, 1E300] + + STATUS <-- 0 if calculation completed correctly + -I if input parameter number I is out of range + 1 if answer appears to be lower than lowest + search bound + 2 if answer appears to be higher than greatest + search bound + 3 if P + Q .ne. 1 + + BOUND <-- Undefined if STATUS is 0 + + Bound exceeded by parameter number I if STATUS + is negative. + + Lower search bound if STATUS is 1. + + Upper search bound if STATUS is 2. + + + Method + + + Formula 26.6.2 of Abramowitz and Stegun, Handbook of + Mathematical Functions (1966) is used to reduce the computation + of the cumulative distribution function for the F variate to + that of an incomplete beta. + + Computation of other parameters involve a seach for a value that + produces the desired value of P. The search relies on the + monotinicity of P with the other parameter. + + WARNING + + The value of the cumulative F distribution is not necessarily + monotone in either degrees of freedom. There thus may be two + values that provide a given CDF value. This routine assumes + monotonicity and will find an arbitrary one of the two values. + +**********************************************************************/ +{ +#define tol (1.0e-8) +#define atol (1.0e-50) +#define zero (1.0e-300) +#define inf 1.0e300 +static int K1 = 1; +static double K2 = 0.0e0; +static double K4 = 0.5e0; +static double K5 = 5.0e0; +static double pq,fx,cum,ccum; +static unsigned long qhi,qleft,qporq; +static double T3,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15; +/* + .. + .. Executable Statements .. +*/ +/* + Check arguments +*/ + if(!(*which < 1 || *which > 4)) goto S30; + if(!(*which < 1)) goto S10; + *bound = 1.0e0; + goto S20; +S10: + *bound = 4.0e0; +S20: + *status = -1; + return; +S30: + if(*which == 1) goto S70; +/* + P +*/ + if(!(*p < 0.0e0 || *p > 1.0e0)) goto S60; + if(!(*p < 0.0e0)) goto S40; + *bound = 0.0e0; + goto S50; +S40: + *bound = 1.0e0; +S50: + *status = -2; + return; +S70: +S60: + if(*which == 1) goto S110; +/* + Q +*/ + if(!(*q <= 0.0e0 || *q > 1.0e0)) goto S100; + if(!(*q <= 0.0e0)) goto S80; + *bound = 0.0e0; + goto S90; +S80: + *bound = 1.0e0; +S90: + *status = -3; + return; +S110: +S100: + if(*which == 2) goto S130; +/* + F +*/ + if(!(*f < 0.0e0)) goto S120; + *bound = 0.0e0; + *status = -4; + return; +S130: +S120: + if(*which == 3) goto S150; +/* + DFN +*/ + if(!(*dfn <= 0.0e0)) goto S140; + *bound = 0.0e0; + *status = -5; + return; +S150: +S140: + if(*which == 4) goto S170; +/* + DFD +*/ + if(!(*dfd <= 0.0e0)) goto S160; + *bound = 0.0e0; + *status = -6; + return; +S170: +S160: + if(*which == 1) goto S210; +/* + P + Q +*/ + pq = *p+*q; + if(!(fabs(pq-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S200; + if(!(pq < 0.0e0)) goto S180; + *bound = 0.0e0; + goto S190; +S180: + *bound = 1.0e0; +S190: + *status = 3; + return; +S210: +S200: + if(!(*which == 1)) qporq = *p <= *q; +/* + Select the minimum of P or Q + Calculate ANSWERS +*/ + if(1 == *which) { +/* + Calculating P +*/ + cumf(f,dfn,dfd,p,q); + *status = 0; + } + else if(2 == *which) { +/* + Calculating F +*/ + *f = 5.0e0; + T3 = inf; + T6 = atol; + T7 = tol; + dstinv(&K2,&T3,&K4,&K4,&K5,&T6,&T7); + *status = 0; + dinvr(status,f,&fx,&qleft,&qhi); +S220: + if(!(*status == 1)) goto S250; + cumf(f,dfn,dfd,&cum,&ccum); + if(!qporq) goto S230; + fx = cum-*p; + goto S240; +S230: + fx = ccum-*q; +S240: + dinvr(status,f,&fx,&qleft,&qhi); + goto S220; +S250: + if(!(*status == -1)) goto S280; + if(!qleft) goto S260; + *status = 1; + *bound = 0.0e0; + goto S270; +S260: + *status = 2; + *bound = inf; +S280: +S270: + ; + } + else if(3 == *which) { +/* + Calculating DFN +*/ + *dfn = 5.0e0; + T8 = zero; + T9 = inf; + T10 = atol; + T11 = tol; + dstinv(&T8,&T9,&K4,&K4,&K5,&T10,&T11); + *status = 0; + dinvr(status,dfn,&fx,&qleft,&qhi); +S290: + if(!(*status == 1)) goto S320; + cumf(f,dfn,dfd,&cum,&ccum); + if(!qporq) goto S300; + fx = cum-*p; + goto S310; +S300: + fx = ccum-*q; +S310: + dinvr(status,dfn,&fx,&qleft,&qhi); + goto S290; +S320: + if(!(*status == -1)) goto S350; + if(!qleft) goto S330; + *status = 1; + *bound = zero; + goto S340; +S330: + *status = 2; + *bound = inf; +S350: +S340: + ; + } + else if(4 == *which) { +/* + Calculating DFD +*/ + *dfd = 5.0e0; + T12 = zero; + T13 = inf; + T14 = atol; + T15 = tol; + dstinv(&T12,&T13,&K4,&K4,&K5,&T14,&T15); + *status = 0; + dinvr(status,dfd,&fx,&qleft,&qhi); +S360: + if(!(*status == 1)) goto S390; + cumf(f,dfn,dfd,&cum,&ccum); + if(!qporq) goto S370; + fx = cum-*p; + goto S380; +S370: + fx = ccum-*q; +S380: + dinvr(status,dfd,&fx,&qleft,&qhi); + goto S360; +S390: + if(!(*status == -1)) goto S420; + if(!qleft) goto S400; + *status = 1; + *bound = zero; + goto S410; +S400: + *status = 2; + *bound = inf; +S410: + ; + } +S420: + return; +#undef tol +#undef atol +#undef zero +#undef inf +} /* END */ + +/***=====================================================================***/ +static void cdffnc(int *which,double *p,double *q,double *f,double *dfn, + double *dfd,double *phonc,int *status,double *bound) +/********************************************************************** + + void cdffnc(int *which,double *p,double *q,double *f,double *dfn, + double *dfd,double *phonc,int *status,double *bound) + + Cumulative Distribution Function + Non-central F distribution + + + Function + + + Calculates any one parameter of the Non-central F + distribution given values for the others. + + + Arguments + + + WHICH --> Integer indicating which of the next five argument + values is to be calculated from the others. + Legal range: 1..5 + iwhich = 1 : Calculate P and Q from F,DFN,DFD and PNONC + iwhich = 2 : Calculate F from P,Q,DFN,DFD and PNONC + iwhich = 3 : Calculate DFN from P,Q,F,DFD and PNONC + iwhich = 4 : Calculate DFD from P,Q,F,DFN and PNONC + iwhich = 5 : Calculate PNONC from P,Q,F,DFN and DFD + + P <--> The integral from 0 to F of the non-central f-density. + Input range: [0,1-1E-16). + + Q <--> 1-P. + Q is not used by this subroutine and is only included + for similarity with other cdf* routines. + + F <--> Upper limit of integration of the non-central f-density. + Input range: [0, +infinity). + Search range: [0,1E300] + + DFN < --> Degrees of freedom of the numerator sum of squares. + Input range: (0, +infinity). + Search range: [ 1E-300, 1E300] + + DFD < --> Degrees of freedom of the denominator sum of squares. + Must be in range: (0, +infinity). + Input range: (0, +infinity). + Search range: [ 1E-300, 1E300] + + PNONC <-> The non-centrality parameter + Input range: [0,infinity) + Search range: [0,1E4] + + STATUS <-- 0 if calculation completed correctly + -I if input parameter number I is out of range + 1 if answer appears to be lower than lowest + search bound + 2 if answer appears to be higher than greatest + search bound + 3 if P + Q .ne. 1 + + BOUND <-- Undefined if STATUS is 0 + + Bound exceeded by parameter number I if STATUS + is negative. + + Lower search bound if STATUS is 1. + + Upper search bound if STATUS is 2. + + + Method + + + Formula 26.6.20 of Abramowitz and Stegun, Handbook of + Mathematical Functions (1966) is used to compute the cumulative + distribution function. + + Computation of other parameters involve a seach for a value that + produces the desired value of P. The search relies on the + monotinicity of P with the other parameter. + + WARNING + + The computation time required for this routine is proportional + to the noncentrality parameter (PNONC). Very large values of + this parameter can consume immense computer resources. This is + why the search range is bounded by 10,000. + + WARNING + + The value of the cumulative noncentral F distribution is not + necessarily monotone in either degrees of freedom. There thus + may be two values that provide a given CDF value. This routine + assumes monotonicity and will find an arbitrary one of the two + values. + +**********************************************************************/ +{ +#define tent4 1.0e4 +#define tol (1.0e-8) +#define atol (1.0e-50) +#define zero (1.0e-300) +#define one (1.0e0-1.0e-16) +#define inf 1.0e300 +static double K1 = 0.0e0; +static double K3 = 0.5e0; +static double K4 = 5.0e0; +static double fx,cum,ccum; +static unsigned long qhi,qleft; +static double T2,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17; +/* + .. + .. Executable Statements .. +*/ +/* + Check arguments +*/ + if(!(*which < 1 || *which > 5)) goto S30; + if(!(*which < 1)) goto S10; + *bound = 1.0e0; + goto S20; +S10: + *bound = 5.0e0; +S20: + *status = -1; + return; +S30: + if(*which == 1) goto S70; +/* + P +*/ + if(!(*p < 0.0e0 || *p > one)) goto S60; + if(!(*p < 0.0e0)) goto S40; + *bound = 0.0e0; + goto S50; +S40: + *bound = one; +S50: + *status = -2; + return; +S70: +S60: + if(*which == 2) goto S90; +/* + F +*/ + if(!(*f < 0.0e0)) goto S80; + *bound = 0.0e0; + *status = -4; + return; +S90: +S80: + if(*which == 3) goto S110; +/* + DFN +*/ + if(!(*dfn <= 0.0e0)) goto S100; + *bound = 0.0e0; + *status = -5; + return; +S110: +S100: + if(*which == 4) goto S130; +/* + DFD +*/ + if(!(*dfd <= 0.0e0)) goto S120; + *bound = 0.0e0; + *status = -6; + return; +S130: +S120: + if(*which == 5) goto S150; +/* + PHONC +*/ + if(!(*phonc < 0.0e0)) goto S140; + *bound = 0.0e0; + *status = -7; + return; +S150: +S140: +/* + Calculate ANSWERS +*/ + if(1 == *which) { +/* + Calculating P +*/ + cumfnc(f,dfn,dfd,phonc,p,q); + *status = 0; + } + else if(2 == *which) { +/* + Calculating F +*/ + *f = 5.0e0; + T2 = inf; + T5 = atol; + T6 = tol; + dstinv(&K1,&T2,&K3,&K3,&K4,&T5,&T6); + *status = 0; + dinvr(status,f,&fx,&qleft,&qhi); +S160: + if(!(*status == 1)) goto S170; + cumfnc(f,dfn,dfd,phonc,&cum,&ccum); + fx = cum-*p; + dinvr(status,f,&fx,&qleft,&qhi); + goto S160; +S170: + if(!(*status == -1)) goto S200; + if(!qleft) goto S180; + *status = 1; + *bound = 0.0e0; + goto S190; +S180: + *status = 2; + *bound = inf; +S200: +S190: + ; + } + else if(3 == *which) { +/* + Calculating DFN +*/ + *dfn = 5.0e0; + T7 = zero; + T8 = inf; + T9 = atol; + T10 = tol; + dstinv(&T7,&T8,&K3,&K3,&K4,&T9,&T10); + *status = 0; + dinvr(status,dfn,&fx,&qleft,&qhi); +S210: + if(!(*status == 1)) goto S220; + cumfnc(f,dfn,dfd,phonc,&cum,&ccum); + fx = cum-*p; + dinvr(status,dfn,&fx,&qleft,&qhi); + goto S210; +S220: + if(!(*status == -1)) goto S250; + if(!qleft) goto S230; + *status = 1; + *bound = zero; + goto S240; +S230: + *status = 2; + *bound = inf; +S250: +S240: + ; + } + else if(4 == *which) { +/* + Calculating DFD +*/ + *dfd = 5.0e0; + T11 = zero; + T12 = inf; + T13 = atol; + T14 = tol; + dstinv(&T11,&T12,&K3,&K3,&K4,&T13,&T14); + *status = 0; + dinvr(status,dfd,&fx,&qleft,&qhi); +S260: + if(!(*status == 1)) goto S270; + cumfnc(f,dfn,dfd,phonc,&cum,&ccum); + fx = cum-*p; + dinvr(status,dfd,&fx,&qleft,&qhi); + goto S260; +S270: + if(!(*status == -1)) goto S300; + if(!qleft) goto S280; + *status = 1; + *bound = zero; + goto S290; +S280: + *status = 2; + *bound = inf; +S300: +S290: + ; + } + else if(5 == *which) { +/* + Calculating PHONC +*/ + *phonc = 5.0e0; + T15 = tent4; + T16 = atol; + T17 = tol; + dstinv(&K1,&T15,&K3,&K3,&K4,&T16,&T17); + *status = 0; + dinvr(status,phonc,&fx,&qleft,&qhi); +S310: + if(!(*status == 1)) goto S320; + cumfnc(f,dfn,dfd,phonc,&cum,&ccum); + fx = cum-*p; + dinvr(status,phonc,&fx,&qleft,&qhi); + goto S310; +S320: + if(!(*status == -1)) goto S350; + if(!qleft) goto S330; + *status = 1; + *bound = 0.0e0; + goto S340; +S330: + *status = 2; + *bound = tent4; +S340: + ; + } +S350: + return; +#undef tent4 +#undef tol +#undef atol +#undef zero +#undef one +#undef inf +} /* END */ + +/***=====================================================================***/ +static void cdfgam(int *which,double *p,double *q,double *x,double *shape, + double *scale,int *status,double *bound) +/********************************************************************** + + void cdfgam(int *which,double *p,double *q,double *x,double *shape, + double *scale,int *status,double *bound) + + Cumulative Distribution Function + GAMma Distribution + + + Function + + + Calculates any one parameter of the gamma + distribution given values for the others. + + + Arguments + + + WHICH --> Integer indicating which of the next four argument + values is to be calculated from the others. + Legal range: 1..4 + iwhich = 1 : Calculate P and Q from X,SHAPE and SCALE + iwhich = 2 : Calculate X from P,Q,SHAPE and SCALE + iwhich = 3 : Calculate SHAPE from P,Q,X and SCALE + iwhich = 4 : Calculate SCALE from P,Q,X and SHAPE + + P <--> The integral from 0 to X of the gamma density. + Input range: [0,1]. + + Q <--> 1-P. + Input range: (0, 1]. + P + Q = 1.0. + + X <--> The upper limit of integration of the gamma density. + Input range: [0, +infinity). + Search range: [0,1E300] + + SHAPE <--> The shape parameter of the gamma density. + Input range: (0, +infinity). + Search range: [1E-300,1E300] + + SCALE <--> The scale parameter of the gamma density. + Input range: (0, +infinity). + Search range: (1E-300,1E300] + + STATUS <-- 0 if calculation completed correctly + -I if input parameter number I is out of range + 1 if answer appears to be lower than lowest + search bound + 2 if answer appears to be higher than greatest + search bound + 3 if P + Q .ne. 1 + 10 if the gamma or inverse gamma routine cannot + compute the answer. Usually happens only for + X and SHAPE very large (gt 1E10 or more) + + BOUND <-- Undefined if STATUS is 0 + + Bound exceeded by parameter number I if STATUS + is negative. + + Lower search bound if STATUS is 1. + + Upper search bound if STATUS is 2. + + + Method + + + Cumulative distribution function (P) is calculated directly by + the code associated with: + + DiDinato, A. R. and Morris, A. H. Computation of the incomplete + gamma function ratios and their inverse. ACM Trans. Math. + Softw. 12 (1986), 377-393. + + Computation of other parameters involve a seach for a value that + produces the desired value of P. The search relies on the + monotinicity of P with the other parameter. + + + Note + + + + The gamma density is proportional to + T**(SHAPE - 1) * EXP(- SCALE * T) + +**********************************************************************/ +{ +#define tol (1.0e-8) +#define atol (1.0e-50) +#define zero (1.0e-300) +#define inf 1.0e300 +static int K1 = 1; +static double K5 = 0.5e0; +static double K6 = 5.0e0; +static double xx,fx,xscale,cum,ccum,pq,porq; +static int ierr; +static unsigned long qhi,qleft,qporq; +static double T2,T3,T4,T7,T8,T9; +/* + .. + .. Executable Statements .. +*/ +/* + Check arguments +*/ + if(!(*which < 1 || *which > 4)) goto S30; + if(!(*which < 1)) goto S10; + *bound = 1.0e0; + goto S20; +S10: + *bound = 4.0e0; +S20: + *status = -1; + return; +S30: + if(*which == 1) goto S70; +/* + P +*/ + if(!(*p < 0.0e0 || *p > 1.0e0)) goto S60; + if(!(*p < 0.0e0)) goto S40; + *bound = 0.0e0; + goto S50; +S40: + *bound = 1.0e0; +S50: + *status = -2; + return; +S70: +S60: + if(*which == 1) goto S110; +/* + Q +*/ + if(!(*q <= 0.0e0 || *q > 1.0e0)) goto S100; + if(!(*q <= 0.0e0)) goto S80; + *bound = 0.0e0; + goto S90; +S80: + *bound = 1.0e0; +S90: + *status = -3; + return; +S110: +S100: + if(*which == 2) goto S130; +/* + X +*/ + if(!(*x < 0.0e0)) goto S120; + *bound = 0.0e0; + *status = -4; + return; +S130: +S120: + if(*which == 3) goto S150; +/* + SHAPE +*/ + if(!(*shape <= 0.0e0)) goto S140; + *bound = 0.0e0; + *status = -5; + return; +S150: +S140: + if(*which == 4) goto S170; +/* + SCALE +*/ + if(!(*scale <= 0.0e0)) goto S160; + *bound = 0.0e0; + *status = -6; + return; +S170: +S160: + if(*which == 1) goto S210; +/* + P + Q +*/ + pq = *p+*q; + if(!(fabs(pq-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S200; + if(!(pq < 0.0e0)) goto S180; + *bound = 0.0e0; + goto S190; +S180: + *bound = 1.0e0; +S190: + *status = 3; + return; +S210: +S200: + if(*which == 1) goto S240; +/* + Select the minimum of P or Q +*/ + qporq = *p <= *q; + if(!qporq) goto S220; + porq = *p; + goto S230; +S220: + porq = *q; +S240: +S230: +/* + Calculate ANSWERS +*/ + if(1 == *which) { +/* + Calculating P +*/ + *status = 0; + xscale = *x**scale; + cumgam(&xscale,shape,p,q); + if(porq > 1.5e0) *status = 10; + } + else if(2 == *which) { +/* + Computing X +*/ + T2 = -1.0e0; + gaminv(shape,&xx,&T2,p,q,&ierr); + if(ierr < 0.0e0) { + *status = 10; + return; + } + else { + *x = xx/ *scale; + *status = 0; + } + } + else if(3 == *which) { +/* + Computing SHAPE +*/ + *shape = 5.0e0; + xscale = *x**scale; + T3 = zero; + T4 = inf; + T7 = atol; + T8 = tol; + dstinv(&T3,&T4,&K5,&K5,&K6,&T7,&T8); + *status = 0; + dinvr(status,shape,&fx,&qleft,&qhi); +S250: + if(!(*status == 1)) goto S290; + cumgam(&xscale,shape,&cum,&ccum); + if(!qporq) goto S260; + fx = cum-*p; + goto S270; +S260: + fx = ccum-*q; +S270: + if(!(qporq && cum > 1.5e0 || !qporq && ccum > 1.5e0)) goto S280; + *status = 10; + return; +S280: + dinvr(status,shape,&fx,&qleft,&qhi); + goto S250; +S290: + if(!(*status == -1)) goto S320; + if(!qleft) goto S300; + *status = 1; + *bound = zero; + goto S310; +S300: + *status = 2; + *bound = inf; +S320: +S310: + ; + } + else if(4 == *which) { +/* + Computing SCALE +*/ + T9 = -1.0e0; + gaminv(shape,&xx,&T9,p,q,&ierr); + if(ierr < 0.0e0) { + *status = 10; + return; + } + else { + *scale = xx/ *x; + *status = 0; + } + } + return; +#undef tol +#undef atol +#undef zero +#undef inf +} /* END */ + +/***=====================================================================***/ +static void cdfnbn(int *which,double *p,double *q,double *s,double *xn, + double *pr,double *ompr,int *status,double *bound) +/********************************************************************** + + void cdfnbn(int *which,double *p,double *q,double *s,double *xn, + double *pr,double *ompr,int *status,double *bound) + + Cumulative Distribution Function + Negative BiNomial distribution + + + Function + + + Calculates any one parameter of the negative binomial + distribution given values for the others. + + The cumulative negative binomial distribution returns the + probability that there will be F or fewer failures before the + XNth success in binomial trials each of which has probability of + success PR. + + The individual term of the negative binomial is the probability of + S failures before XN successes and is + Choose( S, XN+S-1 ) * PR^(XN) * (1-PR)^S + + + Arguments + + + WHICH --> Integer indicating which of the next four argument + values is to be calculated from the others. + Legal range: 1..4 + iwhich = 1 : Calculate P and Q from S,XN,PR and OMPR + iwhich = 2 : Calculate S from P,Q,XN,PR and OMPR + iwhich = 3 : Calculate XN from P,Q,S,PR and OMPR + iwhich = 4 : Calculate PR and OMPR from P,Q,S and XN + + P <--> The cumulation from 0 to S of the negative + binomial distribution. + Input range: [0,1]. + + Q <--> 1-P. + Input range: (0, 1]. + P + Q = 1.0. + + S <--> The upper limit of cumulation of the binomial distribution. + There are F or fewer failures before the XNth success. + Input range: [0, +infinity). + Search range: [0, 1E300] + + XN <--> The number of successes. + Input range: [0, +infinity). + Search range: [0, 1E300] + + PR <--> The probability of success in each binomial trial. + Input range: [0,1]. + Search range: [0,1]. + + OMPR <--> 1-PR + Input range: [0,1]. + Search range: [0,1] + PR + OMPR = 1.0 + + STATUS <-- 0 if calculation completed correctly + -I if input parameter number I is out of range + 1 if answer appears to be lower than lowest + search bound + 2 if answer appears to be higher than greatest + search bound + 3 if P + Q .ne. 1 + 4 if PR + OMPR .ne. 1 + + BOUND <-- Undefined if STATUS is 0 + + Bound exceeded by parameter number I if STATUS + is negative. + + Lower search bound if STATUS is 1. + + Upper search bound if STATUS is 2. + + + Method + + + Formula 26.5.26 of Abramowitz and Stegun, Handbook of + Mathematical Functions (1966) is used to reduce calculation of + the cumulative distribution function to that of an incomplete + beta. + + Computation of other parameters involve a seach for a value that + produces the desired value of P. The search relies on the + monotinicity of P with the other parameter. + +**********************************************************************/ +{ +#define tol (1.0e-8) +#define atol (1.0e-50) +#define inf 1.0e300 +#define one 1.0e0 +static int K1 = 1; +static double K2 = 0.0e0; +static double K4 = 0.5e0; +static double K5 = 5.0e0; +static double K11 = 1.0e0; +static double fx,xhi,xlo,pq,prompr,cum,ccum; +static unsigned long qhi,qleft,qporq; +static double T3,T6,T7,T8,T9,T10,T12,T13; +/* + .. + .. Executable Statements .. +*/ +/* + Check arguments +*/ + if(!(*which < 1 || *which > 4)) goto S30; + if(!(*which < 1)) goto S10; + *bound = 1.0e0; + goto S20; +S10: + *bound = 4.0e0; +S20: + *status = -1; + return; +S30: + if(*which == 1) goto S70; +/* + P +*/ + if(!(*p < 0.0e0 || *p > 1.0e0)) goto S60; + if(!(*p < 0.0e0)) goto S40; + *bound = 0.0e0; + goto S50; +S40: + *bound = 1.0e0; +S50: + *status = -2; + return; +S70: +S60: + if(*which == 1) goto S110; +/* + Q +*/ + if(!(*q <= 0.0e0 || *q > 1.0e0)) goto S100; + if(!(*q <= 0.0e0)) goto S80; + *bound = 0.0e0; + goto S90; +S80: + *bound = 1.0e0; +S90: + *status = -3; + return; +S110: +S100: + if(*which == 2) goto S130; +/* + S +*/ + if(!(*s < 0.0e0)) goto S120; + *bound = 0.0e0; + *status = -4; + return; +S130: +S120: + if(*which == 3) goto S150; +/* + XN +*/ + if(!(*xn < 0.0e0)) goto S140; + *bound = 0.0e0; + *status = -5; + return; +S150: +S140: + if(*which == 4) goto S190; +/* + PR +*/ + if(!(*pr < 0.0e0 || *pr > 1.0e0)) goto S180; + if(!(*pr < 0.0e0)) goto S160; + *bound = 0.0e0; + goto S170; +S160: + *bound = 1.0e0; +S170: + *status = -6; + return; +S190: +S180: + if(*which == 4) goto S230; +/* + OMPR +*/ + if(!(*ompr < 0.0e0 || *ompr > 1.0e0)) goto S220; + if(!(*ompr < 0.0e0)) goto S200; + *bound = 0.0e0; + goto S210; +S200: + *bound = 1.0e0; +S210: + *status = -7; + return; +S230: +S220: + if(*which == 1) goto S270; +/* + P + Q +*/ + pq = *p+*q; + if(!(fabs(pq-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S260; + if(!(pq < 0.0e0)) goto S240; + *bound = 0.0e0; + goto S250; +S240: + *bound = 1.0e0; +S250: + *status = 3; + return; +S270: +S260: + if(*which == 4) goto S310; +/* + PR + OMPR +*/ + prompr = *pr+*ompr; + if(!(fabs(prompr-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S300; + if(!(prompr < 0.0e0)) goto S280; + *bound = 0.0e0; + goto S290; +S280: + *bound = 1.0e0; +S290: + *status = 4; + return; +S310: +S300: + if(!(*which == 1)) qporq = *p <= *q; +/* + Select the minimum of P or Q + Calculate ANSWERS +*/ + if(1 == *which) { +/* + Calculating P +*/ + cumnbn(s,xn,pr,ompr,p,q); + *status = 0; + } + else if(2 == *which) { +/* + Calculating S +*/ + *s = 5.0e0; + T3 = inf; + T6 = atol; + T7 = tol; + dstinv(&K2,&T3,&K4,&K4,&K5,&T6,&T7); + *status = 0; + dinvr(status,s,&fx,&qleft,&qhi); +S320: + if(!(*status == 1)) goto S350; + cumnbn(s,xn,pr,ompr,&cum,&ccum); + if(!qporq) goto S330; + fx = cum-*p; + goto S340; +S330: + fx = ccum-*q; +S340: + dinvr(status,s,&fx,&qleft,&qhi); + goto S320; +S350: + if(!(*status == -1)) goto S380; + if(!qleft) goto S360; + *status = 1; + *bound = 0.0e0; + goto S370; +S360: + *status = 2; + *bound = inf; +S380: +S370: + ; + } + else if(3 == *which) { +/* + Calculating XN +*/ + *xn = 5.0e0; + T8 = inf; + T9 = atol; + T10 = tol; + dstinv(&K2,&T8,&K4,&K4,&K5,&T9,&T10); + *status = 0; + dinvr(status,xn,&fx,&qleft,&qhi); +S390: + if(!(*status == 1)) goto S420; + cumnbn(s,xn,pr,ompr,&cum,&ccum); + if(!qporq) goto S400; + fx = cum-*p; + goto S410; +S400: + fx = ccum-*q; +S410: + dinvr(status,xn,&fx,&qleft,&qhi); + goto S390; +S420: + if(!(*status == -1)) goto S450; + if(!qleft) goto S430; + *status = 1; + *bound = 0.0e0; + goto S440; +S430: + *status = 2; + *bound = inf; +S450: +S440: + ; + } + else if(4 == *which) { +/* + Calculating PR and OMPR +*/ + T12 = atol; + T13 = tol; + dstzr(&K2,&K11,&T12,&T13); + if(!qporq) goto S480; + *status = 0; + dzror(status,pr,&fx,&xlo,&xhi,&qleft,&qhi); + *ompr = one-*pr; +S460: + if(!(*status == 1)) goto S470; + cumnbn(s,xn,pr,ompr,&cum,&ccum); + fx = cum-*p; + dzror(status,pr,&fx,&xlo,&xhi,&qleft,&qhi); + *ompr = one-*pr; + goto S460; +S470: + goto S510; +S480: + *status = 0; + dzror(status,ompr,&fx,&xlo,&xhi,&qleft,&qhi); + *pr = one-*ompr; +S490: + if(!(*status == 1)) goto S500; + cumnbn(s,xn,pr,ompr,&cum,&ccum); + fx = ccum-*q; + dzror(status,ompr,&fx,&xlo,&xhi,&qleft,&qhi); + *pr = one-*ompr; + goto S490; +S510: +S500: + if(!(*status == -1)) goto S540; + if(!qleft) goto S520; + *status = 1; + *bound = 0.0e0; + goto S530; +S520: + *status = 2; + *bound = 1.0e0; +S530: + ; + } +S540: + return; +#undef tol +#undef atol +#undef inf +#undef one +} /* END */ + +/***=====================================================================***/ +static void cdfnor(int *which,double *p,double *q,double *x,double *mean, + double *sd,int *status,double *bound) +/********************************************************************** + + void cdfnor(int *which,double *p,double *q,double *x,double *mean, + double *sd,int *status,double *bound) + + Cumulative Distribution Function + NORmal distribution + + + Function + + + Calculates any one parameter of the normal + distribution given values for the others. + + + Arguments + + + WHICH --> Integer indicating which of the next parameter + values is to be calculated using values of the others. + Legal range: 1..4 + iwhich = 1 : Calculate P and Q from X,MEAN and SD + iwhich = 2 : Calculate X from P,Q,MEAN and SD + iwhich = 3 : Calculate MEAN from P,Q,X and SD + iwhich = 4 : Calculate SD from P,Q,X and MEAN + + P <--> The integral from -infinity to X of the normal density. + Input range: (0,1]. + + Q <--> 1-P. + Input range: (0, 1]. + P + Q = 1.0. + + X < --> Upper limit of integration of the normal-density. + Input range: ( -infinity, +infinity) + + MEAN <--> The mean of the normal density. + Input range: (-infinity, +infinity) + + SD <--> Standard Deviation of the normal density. + Input range: (0, +infinity). + + STATUS <-- 0 if calculation completed correctly + -I if input parameter number I is out of range + 1 if answer appears to be lower than lowest + search bound + 2 if answer appears to be higher than greatest + search bound + 3 if P + Q .ne. 1 + + BOUND <-- Undefined if STATUS is 0 + + Bound exceeded by parameter number I if STATUS + is negative. + + Lower search bound if STATUS is 1. + + Upper search bound if STATUS is 2. + + + Method + + + + + A slightly modified version of ANORM from + + Cody, W.D. (1993). "ALGORITHM 715: SPECFUN - A Portabel FORTRAN + Package of Special Function Routines and Test Drivers" + acm Transactions on Mathematical Software. 19, 22-32. + + is used to calulate the cumulative standard normal distribution. + + The rational functions from pages 90-95 of Kennedy and Gentle, + Statistical Computing, Marcel Dekker, NY, 1980 are used as + starting values to Newton's Iterations which compute the inverse + standard normal. Therefore no searches are necessary for any + parameter. + + For X < -15, the asymptotic expansion for the normal is used as + the starting value in finding the inverse standard normal. + This is formula 26.2.12 of Abramowitz and Stegun. + + + Note + + + The normal density is proportional to + exp( - 0.5 * (( X - MEAN)/SD)**2) + +**********************************************************************/ +{ +static int K1 = 1; +static double z,pq; +/* + .. + .. Executable Statements .. +*/ +/* + Check arguments +*/ + *status = 0; + if(!(*which < 1 || *which > 4)) goto S30; + if(!(*which < 1)) goto S10; + *bound = 1.0e0; + goto S20; +S10: + *bound = 4.0e0; +S20: + *status = -1; + return; +S30: + if(*which == 1) goto S70; +/* + P +*/ + if(!(*p <= 0.0e0 || *p > 1.0e0)) goto S60; + if(!(*p <= 0.0e0)) goto S40; + *bound = 0.0e0; + goto S50; +S40: + *bound = 1.0e0; +S50: + *status = -2; + return; +S70: +S60: + if(*which == 1) goto S110; +/* + Q +*/ + if(!(*q <= 0.0e0 || *q > 1.0e0)) goto S100; + if(!(*q <= 0.0e0)) goto S80; + *bound = 0.0e0; + goto S90; +S80: + *bound = 1.0e0; +S90: + *status = -3; + return; +S110: +S100: + if(*which == 1) goto S150; +/* + P + Q +*/ + pq = *p+*q; + if(!(fabs(pq-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S140; + if(!(pq < 0.0e0)) goto S120; + *bound = 0.0e0; + goto S130; +S120: + *bound = 1.0e0; +S130: + *status = 3; + return; +S150: +S140: + if(*which == 4) goto S170; +/* + SD +*/ + if(!(*sd <= 0.0e0)) goto S160; + *bound = 0.0e0; + *status = -6; + return; +S170: +S160: +/* + Calculate ANSWERS +*/ + if(1 == *which) { +/* + Computing P +*/ + z = (*x-*mean)/ *sd; + cumnor(&z,p,q); + } + else if(2 == *which) { +/* + Computing X +*/ + z = dinvnr(p,q); + *x = *sd*z+*mean; + } + else if(3 == *which) { +/* + Computing the MEAN +*/ + z = dinvnr(p,q); + *mean = *x-*sd*z; + } + else if(4 == *which) { +/* + Computing SD +*/ + z = dinvnr(p,q); + *sd = (*x-*mean)/z; + } + return; +} /* END */ + +/***=====================================================================***/ +static void cdfpoi(int *which,double *p,double *q,double *s,double *xlam, + int *status,double *bound) +/********************************************************************** + + void cdfpoi(int *which,double *p,double *q,double *s,double *xlam, + int *status,double *bound) + + Cumulative Distribution Function + POIsson distribution + + + Function + + + Calculates any one parameter of the Poisson + distribution given values for the others. + + + Arguments + + + WHICH --> Integer indicating which argument + value is to be calculated from the others. + Legal range: 1..3 + iwhich = 1 : Calculate P and Q from S and XLAM + iwhich = 2 : Calculate A from P,Q and XLAM + iwhich = 3 : Calculate XLAM from P,Q and S + + P <--> The cumulation from 0 to S of the poisson density. + Input range: [0,1]. + + Q <--> 1-P. + Input range: (0, 1]. + P + Q = 1.0. + + S <--> Upper limit of cumulation of the Poisson. + Input range: [0, +infinity). + Search range: [0,1E300] + + XLAM <--> Mean of the Poisson distribution. + Input range: [0, +infinity). + Search range: [0,1E300] + + STATUS <-- 0 if calculation completed correctly + -I if input parameter number I is out of range + 1 if answer appears to be lower than lowest + search bound + 2 if answer appears to be higher than greatest + search bound + 3 if P + Q .ne. 1 + + BOUND <-- Undefined if STATUS is 0 + + Bound exceeded by parameter number I if STATUS + is negative. + + Lower search bound if STATUS is 1. + + Upper search bound if STATUS is 2. + + + Method + + + Formula 26.4.21 of Abramowitz and Stegun, Handbook of + Mathematical Functions (1966) is used to reduce the computation + of the cumulative distribution function to that of computing a + chi-square, hence an incomplete gamma function. + + Cumulative distribution function (P) is calculated directly. + Computation of other parameters involve a seach for a value that + produces the desired value of P. The search relies on the + monotinicity of P with the other parameter. + +**********************************************************************/ +{ +#define tol (1.0e-8) +#define atol (1.0e-50) +#define inf 1.0e300 +static int K1 = 1; +static double K2 = 0.0e0; +static double K4 = 0.5e0; +static double K5 = 5.0e0; +static double fx,cum,ccum,pq; +static unsigned long qhi,qleft,qporq; +static double T3,T6,T7,T8,T9,T10; +/* + .. + .. Executable Statements .. +*/ +/* + Check arguments +*/ + if(!(*which < 1 || *which > 3)) goto S30; + if(!(*which < 1)) goto S10; + *bound = 1.0e0; + goto S20; +S10: + *bound = 3.0e0; +S20: + *status = -1; + return; +S30: + if(*which == 1) goto S70; +/* + P +*/ + if(!(*p < 0.0e0 || *p > 1.0e0)) goto S60; + if(!(*p < 0.0e0)) goto S40; + *bound = 0.0e0; + goto S50; +S40: + *bound = 1.0e0; +S50: + *status = -2; + return; +S70: +S60: + if(*which == 1) goto S110; +/* + Q +*/ + if(!(*q <= 0.0e0 || *q > 1.0e0)) goto S100; + if(!(*q <= 0.0e0)) goto S80; + *bound = 0.0e0; + goto S90; +S80: + *bound = 1.0e0; +S90: + *status = -3; + return; +S110: +S100: + if(*which == 2) goto S130; +/* + S +*/ + if(!(*s < 0.0e0)) goto S120; + *bound = 0.0e0; + *status = -4; + return; +S130: +S120: + if(*which == 3) goto S150; +/* + XLAM +*/ + if(!(*xlam < 0.0e0)) goto S140; + *bound = 0.0e0; + *status = -5; + return; +S150: +S140: + if(*which == 1) goto S190; +/* + P + Q +*/ + pq = *p+*q; + if(!(fabs(pq-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S180; + if(!(pq < 0.0e0)) goto S160; + *bound = 0.0e0; + goto S170; +S160: + *bound = 1.0e0; +S170: + *status = 3; + return; +S190: +S180: + if(!(*which == 1)) qporq = *p <= *q; +/* + Select the minimum of P or Q + Calculate ANSWERS +*/ + if(1 == *which) { +/* + Calculating P +*/ + cumpoi(s,xlam,p,q); + *status = 0; + } + else if(2 == *which) { +/* + Calculating S +*/ + *s = 5.0e0; + T3 = inf; + T6 = atol; + T7 = tol; + dstinv(&K2,&T3,&K4,&K4,&K5,&T6,&T7); + *status = 0; + dinvr(status,s,&fx,&qleft,&qhi); +S200: + if(!(*status == 1)) goto S230; + cumpoi(s,xlam,&cum,&ccum); + if(!qporq) goto S210; + fx = cum-*p; + goto S220; +S210: + fx = ccum-*q; +S220: + dinvr(status,s,&fx,&qleft,&qhi); + goto S200; +S230: + if(!(*status == -1)) goto S260; + if(!qleft) goto S240; + *status = 1; + *bound = 0.0e0; + goto S250; +S240: + *status = 2; + *bound = inf; +S260: +S250: + ; + } + else if(3 == *which) { +/* + Calculating XLAM +*/ + *xlam = 5.0e0; + T8 = inf; + T9 = atol; + T10 = tol; + dstinv(&K2,&T8,&K4,&K4,&K5,&T9,&T10); + *status = 0; + dinvr(status,xlam,&fx,&qleft,&qhi); +S270: + if(!(*status == 1)) goto S300; + cumpoi(s,xlam,&cum,&ccum); + if(!qporq) goto S280; + fx = cum-*p; + goto S290; +S280: + fx = ccum-*q; +S290: + dinvr(status,xlam,&fx,&qleft,&qhi); + goto S270; +S300: + if(!(*status == -1)) goto S330; + if(!qleft) goto S310; + *status = 1; + *bound = 0.0e0; + goto S320; +S310: + *status = 2; + *bound = inf; +S320: + ; + } +S330: + return; +#undef tol +#undef atol +#undef inf +} /* END */ + +/***=====================================================================***/ +static void cdft(int *which,double *p,double *q,double *t,double *df, + int *status,double *bound) +/********************************************************************** + + void cdft(int *which,double *p,double *q,double *t,double *df, + int *status,double *bound) + + Cumulative Distribution Function + T distribution + + + Function + + + Calculates any one parameter of the t distribution given + values for the others. + + + Arguments + + + WHICH --> Integer indicating which argument + values is to be calculated from the others. + Legal range: 1..3 + iwhich = 1 : Calculate P and Q from T and DF + iwhich = 2 : Calculate T from P,Q and DF + iwhich = 3 : Calculate DF from P,Q and T + + P <--> The integral from -infinity to t of the t-density. + Input range: (0,1]. + + Q <--> 1-P. + Input range: (0, 1]. + P + Q = 1.0. + + T <--> Upper limit of integration of the t-density. + Input range: ( -infinity, +infinity). + Search range: [ -1E300, 1E300 ] + + DF <--> Degrees of freedom of the t-distribution. + Input range: (0 , +infinity). + Search range: [1e-300, 1E10] + + STATUS <-- 0 if calculation completed correctly + -I if input parameter number I is out of range + 1 if answer appears to be lower than lowest + search bound + 2 if answer appears to be higher than greatest + search bound + 3 if P + Q .ne. 1 + + BOUND <-- Undefined if STATUS is 0 + + Bound exceeded by parameter number I if STATUS + is negative. + + Lower search bound if STATUS is 1. + + Upper search bound if STATUS is 2. + + + Method + + + Formula 26.5.27 of Abramowitz and Stegun, Handbook of + Mathematical Functions (1966) is used to reduce the computation + of the cumulative distribution function to that of an incomplete + beta. + + Computation of other parameters involve a seach for a value that + produces the desired value of P. The search relies on the + monotinicity of P with the other parameter. + +**********************************************************************/ +{ +#define tol (1.0e-8) +#define atol (1.0e-50) +#define zero (1.0e-300) +#define inf 1.0e300 +#define maxdf 1.0e10 +static int K1 = 1; +static double K4 = 0.5e0; +static double K5 = 5.0e0; +static double fx,cum,ccum,pq; +static unsigned long qhi,qleft,qporq; +static double T2,T3,T6,T7,T8,T9,T10,T11; +/* + .. + .. Executable Statements .. +*/ +/* + Check arguments +*/ + if(!(*which < 1 || *which > 3)) goto S30; + if(!(*which < 1)) goto S10; + *bound = 1.0e0; + goto S20; +S10: + *bound = 3.0e0; +S20: + *status = -1; + return; +S30: + if(*which == 1) goto S70; +/* + P +*/ + if(!(*p <= 0.0e0 || *p > 1.0e0)) goto S60; + if(!(*p <= 0.0e0)) goto S40; + *bound = 0.0e0; + goto S50; +S40: + *bound = 1.0e0; +S50: + *status = -2; + return; +S70: +S60: + if(*which == 1) goto S110; +/* + Q +*/ + if(!(*q <= 0.0e0 || *q > 1.0e0)) goto S100; + if(!(*q <= 0.0e0)) goto S80; + *bound = 0.0e0; + goto S90; +S80: + *bound = 1.0e0; +S90: + *status = -3; + return; +S110: +S100: + if(*which == 3) goto S130; +/* + DF +*/ + if(!(*df <= 0.0e0)) goto S120; + *bound = 0.0e0; + *status = -5; + return; +S130: +S120: + if(*which == 1) goto S170; +/* + P + Q +*/ + pq = *p+*q; + if(!(fabs(pq-0.5e0-0.5e0) > 3.0e0*spmpar(&K1))) goto S160; + if(!(pq < 0.0e0)) goto S140; + *bound = 0.0e0; + goto S150; +S140: + *bound = 1.0e0; +S150: + *status = 3; + return; +S170: +S160: + if(!(*which == 1)) qporq = *p <= *q; +/* + Select the minimum of P or Q + Calculate ANSWERS +*/ + if(1 == *which) { +/* + Computing P and Q +*/ + cumt(t,df,p,q); + *status = 0; + } + else if(2 == *which) { +/* + Computing T + .. Get initial approximation for T +*/ + *t = dt1(p,q,df); + T2 = -inf; + T3 = inf; + T6 = atol; + T7 = tol; + dstinv(&T2,&T3,&K4,&K4,&K5,&T6,&T7); + *status = 0; + dinvr(status,t,&fx,&qleft,&qhi); +S180: + if(!(*status == 1)) goto S210; + cumt(t,df,&cum,&ccum); + if(!qporq) goto S190; + fx = cum-*p; + goto S200; +S190: + fx = ccum-*q; +S200: + dinvr(status,t,&fx,&qleft,&qhi); + goto S180; +S210: + if(!(*status == -1)) goto S240; + if(!qleft) goto S220; + *status = 1; + *bound = -inf; + goto S230; +S220: + *status = 2; + *bound = inf; +S240: +S230: + ; + } + else if(3 == *which) { +/* + Computing DF +*/ + *df = 5.0e0; + T8 = zero; + T9 = maxdf; + T10 = atol; + T11 = tol; + dstinv(&T8,&T9,&K4,&K4,&K5,&T10,&T11); + *status = 0; + dinvr(status,df,&fx,&qleft,&qhi); +S250: + if(!(*status == 1)) goto S280; + cumt(t,df,&cum,&ccum); + if(!qporq) goto S260; + fx = cum-*p; + goto S270; +S260: + fx = ccum-*q; +S270: + dinvr(status,df,&fx,&qleft,&qhi); + goto S250; +S280: + if(!(*status == -1)) goto S310; + if(!qleft) goto S290; + *status = 1; + *bound = zero; + goto S300; +S290: + *status = 2; + *bound = maxdf; +S300: + ; + } +S310: + return; +#undef tol +#undef atol +#undef zero +#undef inf +#undef maxdf +} /* END */ + +/***=====================================================================***/ +static void cumbet(double *x,double *y,double *a,double *b,double *cum, + double *ccum) +/* +********************************************************************** + + void cumbet(double *x,double *y,double *a,double *b,double *cum, + double *ccum) + + Double precision cUMulative incomplete BETa distribution + + + Function + + + Calculates the cdf to X of the incomplete beta distribution + with parameters a and b. This is the integral from 0 to x + of (1/B(a,b))*f(t)) where f(t) = t**(a-1) * (1-t)**(b-1) + + + Arguments + + + X --> Upper limit of integration. + X is DOUBLE PRECISION + + Y --> 1 - X. + Y is DOUBLE PRECISION + + A --> First parameter of the beta distribution. + A is DOUBLE PRECISION + + B --> Second parameter of the beta distribution. + B is DOUBLE PRECISION + + CUM <-- Cumulative incomplete beta distribution. + CUM is DOUBLE PRECISION + + CCUM <-- Compliment of Cumulative incomplete beta distribution. + CCUM is DOUBLE PRECISION + + + Method + + + Calls the routine BRATIO. + + References + + Didonato, Armido R. and Morris, Alfred H. Jr. (1992) Algorithim + 708 Significant Digit Computation of the Incomplete Beta Function + Ratios. ACM ToMS, Vol.18, No. 3, Sept. 1992, 360-373. + +********************************************************************** +*/ +{ +static int ierr; +/* + .. + .. Executable Statements .. +*/ + if(!(*x <= 0.0e0)) goto S10; + *cum = 0.0e0; + *ccum = 1.0e0; + return; +S10: + if(!(*y <= 0.0e0)) goto S20; + *cum = 1.0e0; + *ccum = 0.0e0; + return; +S20: + bratio(a,b,x,y,cum,ccum,&ierr); +/* + Call bratio routine +*/ + return; +} /* END */ + +/***=====================================================================***/ +static void cumbin(double *s,double *xn,double *pr,double *ompr, + double *cum,double *ccum) +/* +********************************************************************** + + void cumbin(double *s,double *xn,double *pr,double *ompr, + double *cum,double *ccum) + + CUmulative BINomial distribution + + + Function + + + Returns the probability of 0 to S successes in XN binomial + trials, each of which has a probability of success, PBIN. + + + Arguments + + + S --> The upper limit of cumulation of the binomial distribution. + S is DOUBLE PRECISION + + XN --> The number of binomial trials. + XN is DOUBLE PRECISIO + + PBIN --> The probability of success in each binomial trial. + PBIN is DOUBLE PRECIS + + OMPR --> 1 - PBIN + OMPR is DOUBLE PRECIS + + CUM <-- Cumulative binomial distribution. + CUM is DOUBLE PRECISI + + CCUM <-- Compliment of Cumulative binomial distribution. + CCUM is DOUBLE PRECIS + + + Method + + + Formula 26.5.24 of Abramowitz and Stegun, Handbook of + Mathematical Functions (1966) is used to reduce the binomial + distribution to the cumulative beta distribution. + +********************************************************************** +*/ +{ +static double T1,T2; +/* + .. + .. Executable Statements .. +*/ + if(!(*s < *xn)) goto S10; + T1 = *s+1.0e0; + T2 = *xn-*s; + cumbet(pr,ompr,&T1,&T2,ccum,cum); + goto S20; +S10: + *cum = 1.0e0; + *ccum = 0.0e0; +S20: + return; +} /* END */ + +/***=====================================================================***/ +static void cumchi(double *x,double *df,double *cum,double *ccum) +/* +********************************************************************** + + void cumchi(double *x,double *df,double *cum,double *ccum) + CUMulative of the CHi-square distribution + + + Function + + + Calculates the cumulative chi-square distribution. + + + Arguments + + + X --> Upper limit of integration of the + chi-square distribution. + X is DOUBLE PRECISION + + DF --> Degrees of freedom of the + chi-square distribution. + DF is DOUBLE PRECISION + + CUM <-- Cumulative chi-square distribution. + CUM is DOUBLE PRECISIO + + CCUM <-- Compliment of Cumulative chi-square distribution. + CCUM is DOUBLE PRECISI + + + Method + + + Calls incomplete gamma function (CUMGAM) + +********************************************************************** +*/ +{ +static double a,xx; +/* + .. + .. Executable Statements .. +*/ + a = *df*0.5e0; + xx = *x*0.5e0; + cumgam(&xx,&a,cum,ccum); + return; +} /* END */ + +/***=====================================================================***/ +static void cumchn(double *x,double *df,double *pnonc,double *cum, + double *ccum) +/* +********************************************************************** + + void cumchn(double *x,double *df,double *pnonc,double *cum, + double *ccum) + + CUMulative of the Non-central CHi-square distribution + + + Function + + + Calculates the cumulative non-central chi-square + distribution, i.e., the probability that a random variable + which follows the non-central chi-square distribution, with + non-centrality parameter PNONC and continuous degrees of + freedom DF, is less than or equal to X. + + + Arguments + + + X --> Upper limit of integration of the non-central + chi-square distribution. + X is DOUBLE PRECISION + + DF --> Degrees of freedom of the non-central + chi-square distribution. + DF is DOUBLE PRECISION + + PNONC --> Non-centrality parameter of the non-central + chi-square distribution. + PNONC is DOUBLE PRECIS + + CUM <-- Cumulative non-central chi-square distribution. + CUM is DOUBLE PRECISIO + + CCUM <-- Compliment of Cumulative non-central chi-square distribut + CCUM is DOUBLE PRECISI + + + Method + + + Uses formula 26.4.25 of Abramowitz and Stegun, Handbook of + Mathematical Functions, US NBS (1966) to calculate the + non-central chi-square. + + + Variables + + + EPS --- Convergence criterion. The sum stops when a + term is less than EPS*SUM. + EPS is DOUBLE PRECISIO + + NTIRED --- Maximum number of terms to be evaluated + in each sum. + NTIRED is INTEGER + + QCONV --- .TRUE. if convergence achieved - + i.e., program did not stop on NTIRED criterion. + QCONV is LOGICAL + + CCUM <-- Compliment of Cumulative non-central + chi-square distribution. + CCUM is DOUBLE PRECISI + +********************************************************************** +*/ +{ +#define dg(i) (*df+2.0e0*(double)(i)) +#define qsmall(xx) (int)(sum < 1.0e-20 || (xx) < eps*sum) +#define qtired(i) (int)((i) > ntired) +static double eps = 1.0e-5; +static int ntired = 1000; +static double adj,centaj,centwt,chid2,dfd2,lcntaj,lcntwt,lfact,pcent,pterm,sum, + sumadj,term,wt,xnonc; +static int i,icent,iterb,iterf; +static double T1,T2,T3; +/* + .. + .. Executable Statements .. +*/ + if(!(*x <= 0.0e0)) goto S10; + *cum = 0.0e0; + *ccum = 1.0e0; + return; +S10: + if(!(*pnonc <= 1.0e-10)) goto S20; +/* + When non-centrality parameter is (essentially) zero, + use cumulative chi-square distribution +*/ + cumchi(x,df,cum,ccum); + return; +S20: + xnonc = *pnonc/2.0e0; +/* +********************************************************************** + The following code calcualtes the weight, chi-square, and + adjustment term for the central term in the infinite series. + The central term is the one in which the poisson weight is + greatest. The adjustment term is the amount that must + be subtracted from the chi-square to move up two degrees + of freedom. +********************************************************************** +*/ + icent = fifidint(xnonc); + if(icent == 0) icent = 1; + chid2 = *x/2.0e0; +/* + Calculate central weight term +*/ + T1 = (double)(icent+1); + lfact = alngam(&T1); + lcntwt = -xnonc+(double)icent*log(xnonc)-lfact; + centwt = exp(lcntwt); +/* + Calculate central chi-square +*/ + T2 = dg(icent); + cumchi(x,&T2,&pcent,ccum); +/* + Calculate central adjustment term +*/ + dfd2 = dg(icent)/2.0e0; + T3 = 1.0e0+dfd2; + lfact = alngam(&T3); + lcntaj = dfd2*log(chid2)-chid2-lfact; + centaj = exp(lcntaj); + sum = centwt*pcent; +/* +********************************************************************** + Sum backwards from the central term towards zero. + Quit whenever either + (1) the zero term is reached, or + (2) the term gets small relative to the sum, or + (3) More than NTIRED terms are totaled. +********************************************************************** +*/ + iterb = 0; + sumadj = 0.0e0; + adj = centaj; + wt = centwt; + i = icent; + goto S40; +S30: + if(qtired(iterb) || qsmall(term) || i == 0) goto S50; +S40: + dfd2 = dg(i)/2.0e0; +/* + Adjust chi-square for two fewer degrees of freedom. + The adjusted value ends up in PTERM. +*/ + adj = adj*dfd2/chid2; + sumadj += adj; + pterm = pcent+sumadj; +/* + Adjust poisson weight for J decreased by one +*/ + wt *= ((double)i/xnonc); + term = wt*pterm; + sum += term; + i -= 1; + iterb += 1; + goto S30; +S50: + iterf = 0; +/* +********************************************************************** + Now sum forward from the central term towards infinity. + Quit when either + (1) the term gets small relative to the sum, or + (2) More than NTIRED terms are totaled. +********************************************************************** +*/ + sumadj = adj = centaj; + wt = centwt; + i = icent; + goto S70; +S60: + if(qtired(iterf) || qsmall(term)) goto S80; +S70: +/* + Update weights for next higher J +*/ + wt *= (xnonc/(double)(i+1)); +/* + Calculate PTERM and add term to sum +*/ + pterm = pcent-sumadj; + term = wt*pterm; + sum += term; +/* + Update adjustment term for DF for next iteration +*/ + i += 1; + dfd2 = dg(i)/2.0e0; + adj = adj*chid2/dfd2; + sumadj += adj; + iterf += 1; + goto S60; +S80: + *cum = sum; + *ccum = 0.5e0+(0.5e0-*cum); + return; +#undef dg +#undef qsmall +#undef qtired +} /* END */ + +/***=====================================================================***/ +static void cumf(double *f,double *dfn,double *dfd,double *cum,double *ccum) +/* +********************************************************************** + + void cumf(double *f,double *dfn,double *dfd,double *cum,double *ccum) + CUMulative F distribution + + + Function + + + Computes the integral from 0 to F of the f-density with DFN + and DFD degrees of freedom. + + + Arguments + + + F --> Upper limit of integration of the f-density. + F is DOUBLE PRECISION + + DFN --> Degrees of freedom of the numerator sum of squares. + DFN is DOUBLE PRECISI + + DFD --> Degrees of freedom of the denominator sum of squares. + DFD is DOUBLE PRECISI + + CUM <-- Cumulative f distribution. + CUM is DOUBLE PRECISI + + CCUM <-- Compliment of Cumulative f distribution. + CCUM is DOUBLE PRECIS + + + Method + + + Formula 26.5.28 of Abramowitz and Stegun is used to reduce + the cumulative F to a cumulative beta distribution. + + + Note + + + If F is less than or equal to 0, 0 is returned. + +********************************************************************** +*/ +{ +#define half 0.5e0 +#define done 1.0e0 +static double dsum,prod,xx,yy; +static int ierr; +static double T1,T2; +/* + .. + .. Executable Statements .. +*/ + if(!(*f <= 0.0e0)) goto S10; + *cum = 0.0e0; + *ccum = 1.0e0; + return; +S10: + prod = *dfn**f; +/* + XX is such that the incomplete beta with parameters + DFD/2 and DFN/2 evaluated at XX is 1 - CUM or CCUM + YY is 1 - XX + Calculate the smaller of XX and YY accurately +*/ + dsum = *dfd+prod; + xx = *dfd/dsum; + if(xx > half) { + yy = prod/dsum; + xx = done-yy; + } + else yy = done-xx; + T1 = *dfd*half; + T2 = *dfn*half; + bratio(&T1,&T2,&xx,&yy,ccum,cum,&ierr); + return; +#undef half +#undef done +} /* END */ + +/***=====================================================================***/ +static void cumfnc(double *f,double *dfn,double *dfd,double *pnonc, + double *cum,double *ccum) +/* +********************************************************************** + + F -NON- -C-ENTRAL F DISTRIBUTION + + + + Function + + + COMPUTES NONCENTRAL F DISTRIBUTION WITH DFN AND DFD + DEGREES OF FREEDOM AND NONCENTRALITY PARAMETER PNONC + + + Arguments + + + X --> UPPER LIMIT OF INTEGRATION OF NONCENTRAL F IN EQUATION + + DFN --> DEGREES OF FREEDOM OF NUMERATOR + + DFD --> DEGREES OF FREEDOM OF DENOMINATOR + + PNONC --> NONCENTRALITY PARAMETER. + + CUM <-- CUMULATIVE NONCENTRAL F DISTRIBUTION + + CCUM <-- COMPLIMENT OF CUMMULATIVE + + + Method + + + USES FORMULA 26.6.20 OF REFERENCE FOR INFINITE SERIES. + SERIES IS CALCULATED BACKWARD AND FORWARD FROM J = LAMBDA/2 + (THIS IS THE TERM WITH THE LARGEST POISSON WEIGHT) UNTIL + THE CONVERGENCE CRITERION IS MET. + + FOR SPEED, THE INCOMPLETE BETA FUNCTIONS ARE EVALUATED + BY FORMULA 26.5.16. + + + REFERENCE + + + HANDBOOD OF MATHEMATICAL FUNCTIONS + EDITED BY MILTON ABRAMOWITZ AND IRENE A. STEGUN + NATIONAL BUREAU OF STANDARDS APPLIED MATEMATICS SERIES - 55 + MARCH 1965 + P 947, EQUATIONS 26.6.17, 26.6.18 + + + Note + + + THE SUM CONTINUES UNTIL A SUCCEEDING TERM IS LESS THAN EPS + TIMES THE SUM (OR THE SUM IS LESS THAN 1.0E-20). EPS IS + SET TO 1.0E-4 IN A DATA STATEMENT WHICH CAN BE CHANGED. + +********************************************************************** +*/ +{ +#define qsmall(x) (int)(sum < 1.0e-20 || (x) < eps*sum) +#define half 0.5e0 +#define done 1.0e0 +static double eps = 1.0e-4; +static double dsum,dummy,prod,xx,yy,adn,aup,b,betdn,betup,centwt,dnterm,sum, + upterm,xmult,xnonc; +static int i,icent,ierr; +static double T1,T2,T3,T4,T5,T6; +/* + .. + .. Executable Statements .. +*/ + if(!(*f <= 0.0e0)) goto S10; + *cum = 0.0e0; + *ccum = 1.0e0; + return; +S10: + if(!(*pnonc < 1.0e-10)) goto S20; +/* + Handle case in which the non-centrality parameter is + (essentially) zero. +*/ + cumf(f,dfn,dfd,cum,ccum); + return; +S20: + xnonc = *pnonc/2.0e0; +/* + Calculate the central term of the poisson weighting factor. +*/ + icent = xnonc; + if(icent == 0) icent = 1; +/* + Compute central weight term +*/ + T1 = (double)(icent+1); + centwt = exp(-xnonc+(double)icent*log(xnonc)-alngam(&T1)); +/* + Compute central incomplete beta term + Assure that minimum of arg to beta and 1 - arg is computed + accurately. +*/ + prod = *dfn**f; + dsum = *dfd+prod; + yy = *dfd/dsum; + if(yy > half) { + xx = prod/dsum; + yy = done-xx; + } + else xx = done-yy; + T2 = *dfn*half+(double)icent; + T3 = *dfd*half; + bratio(&T2,&T3,&xx,&yy,&betdn,&dummy,&ierr); + adn = *dfn/2.0e0+(double)icent; + aup = adn; + b = *dfd/2.0e0; + betup = betdn; + sum = centwt*betdn; +/* + Now sum terms backward from icent until convergence or all done +*/ + xmult = centwt; + i = icent; + T4 = adn+b; + T5 = adn+1.0e0; + dnterm = exp(alngam(&T4)-alngam(&T5)-alngam(&b)+adn*log(xx)+b*log(yy)); +S30: + if(qsmall(xmult*betdn) || i <= 0) goto S40; + xmult *= ((double)i/xnonc); + i -= 1; + adn -= 1.0; + dnterm = (adn+1.0)/((adn+b)*xx)*dnterm; + betdn += dnterm; + sum += (xmult*betdn); + goto S30; +S40: + i = icent+1; +/* + Now sum forwards until convergence +*/ + xmult = centwt; + if(aup-1.0+b == 0) upterm = exp(-alngam(&aup)-alngam(&b)+(aup-1.0)*log(xx)+ + b*log(yy)); + else { + T6 = aup-1.0+b; + upterm = exp(alngam(&T6)-alngam(&aup)-alngam(&b)+(aup-1.0)*log(xx)+b* + log(yy)); + } + goto S60; +S50: + if(qsmall(xmult*betup)) goto S70; +S60: + xmult *= (xnonc/(double)i); + i += 1; + aup += 1.0; + upterm = (aup+b-2.0e0)*xx/(aup-1.0)*upterm; + betup -= upterm; + sum += (xmult*betup); + goto S50; +S70: + *cum = sum; + *ccum = 0.5e0+(0.5e0-*cum); + return; +#undef qsmall +#undef half +#undef done +} /* END */ + +/***=====================================================================***/ +static void cumgam(double *x,double *a,double *cum,double *ccum) +/* +********************************************************************** + + void cumgam(double *x,double *a,double *cum,double *ccum) + Double precision cUMulative incomplete GAMma distribution + + + Function + + + Computes the cumulative of the incomplete gamma + distribution, i.e., the integral from 0 to X of + (1/GAM(A))*EXP(-T)*T**(A-1) DT + where GAM(A) is the complete gamma function of A, i.e., + GAM(A) = integral from 0 to infinity of + EXP(-T)*T**(A-1) DT + + + Arguments + + + X --> The upper limit of integration of the incomplete gamma. + X is DOUBLE PRECISION + + A --> The shape parameter of the incomplete gamma. + A is DOUBLE PRECISION + + CUM <-- Cumulative incomplete gamma distribution. + CUM is DOUBLE PRECISION + + CCUM <-- Compliment of Cumulative incomplete gamma distribution. + CCUM is DOUBLE PRECISIO + + + Method + + + Calls the routine GRATIO. + +********************************************************************** +*/ +{ +static int K1 = 0; +/* + .. + .. Executable Statements .. +*/ + if(!(*x <= 0.0e0)) goto S10; + *cum = 0.0e0; + *ccum = 1.0e0; + return; +S10: + gratio(a,x,cum,ccum,&K1); +/* + Call gratio routine +*/ + return; +} /* END */ + +/***=====================================================================***/ +static void cumnbn(double *s,double *xn,double *pr,double *ompr, + double *cum,double *ccum) +/* +********************************************************************** + + void cumnbn(double *s,double *xn,double *pr,double *ompr, + double *cum,double *ccum) + + CUmulative Negative BINomial distribution + + + Function + + + Returns the probability that it there will be S or fewer failures + before there are XN successes, with each binomial trial having + a probability of success PR. + + Prob(# failures = S | XN successes, PR) = + ( XN + S - 1 ) + ( ) * PR^XN * (1-PR)^S + ( S ) + + + Arguments + + + S --> The number of failures + S is DOUBLE PRECISION + + XN --> The number of successes + XN is DOUBLE PRECISIO + + PR --> The probability of success in each binomial trial. + PR is DOUBLE PRECISIO + + OMPR --> 1 - PR + OMPR is DOUBLE PRECIS + + CUM <-- Cumulative negative binomial distribution. + CUM is DOUBLE PRECISI + + CCUM <-- Compliment of Cumulative negative binomial distribution. + CCUM is DOUBLE PRECIS + + + Method + + + Formula 26.5.26 of Abramowitz and Stegun, Handbook of + Mathematical Functions (1966) is used to reduce the negative + binomial distribution to the cumulative beta distribution. + +********************************************************************** +*/ +{ +static double T1; +/* + .. + .. Executable Statements .. +*/ + T1 = *s+1.e0; + cumbet(pr,ompr,xn,&T1,cum,ccum); + return; +} /* END */ + +/***=====================================================================***/ +static void cumnor(double *arg,double *result,double *ccum) +/* +********************************************************************** + + void cumnor(double *arg,double *result,double *ccum) + + + Function + + + Computes the cumulative of the normal distribution, i.e., + the integral from -infinity to x of + (1/sqrt(2*pi)) exp(-u*u/2) du + + X --> Upper limit of integration. + X is DOUBLE PRECISION + + RESULT <-- Cumulative normal distribution. + RESULT is DOUBLE PRECISION + + CCUM <-- Compliment of Cumulative normal distribution. + CCUM is DOUBLE PRECISION + + Renaming of function ANORM from: + + Cody, W.D. (1993). "ALGORITHM 715: SPECFUN - A Portabel FORTRAN + Package of Special Function Routines and Test Drivers" + acm Transactions on Mathematical Software. 19, 22-32. + + with slight modifications to return ccum and to deal with + machine constants. + +********************************************************************** + Original Comments: +------------------------------------------------------------------ + + This function evaluates the normal distribution function: + + / x + 1 | -t*t/2 + P(x) = ----------- | e dt + sqrt(2 pi) | + /-oo + + The main computation evaluates near-minimax approximations + derived from those in "Rational Chebyshev approximations for + the error function" by W. J. Cody, Math. Comp., 1969, 631-637. + This transportable program uses rational functions that + theoretically approximate the normal distribution function to + at least 18 significant decimal digits. The accuracy achieved + depends on the arithmetic system, the compiler, the intrinsic + functions, and proper selection of the machine-dependent + constants. + +******************************************************************* +******************************************************************* + + Explanation of machine-dependent constants. + + MIN = smallest machine representable number. + + EPS = argument below which anorm(x) may be represented by + 0.5 and above which x*x will not underflow. + A conservative value is the largest machine number X + such that 1.0 + X = 1.0 to machine precision. +******************************************************************* +******************************************************************* + + Error returns + + The program returns ANORM = 0 for ARG .LE. XLOW. + + + Intrinsic functions required are: + + ABS, AINT, EXP + + + Author: W. J. Cody + Mathematics and Computer Science Division + Argonne National Laboratory + Argonne, IL 60439 + + Latest modification: March 15, 1992 + +------------------------------------------------------------------ +*/ +{ +static double a[5] = { + 2.2352520354606839287e00,1.6102823106855587881e02,1.0676894854603709582e03, + 1.8154981253343561249e04,6.5682337918207449113e-2 +}; +static double b[4] = { + 4.7202581904688241870e01,9.7609855173777669322e02,1.0260932208618978205e04, + 4.5507789335026729956e04 +}; +static double c[9] = { + 3.9894151208813466764e-1,8.8831497943883759412e00,9.3506656132177855979e01, + 5.9727027639480026226e02,2.4945375852903726711e03,6.8481904505362823326e03, + 1.1602651437647350124e04,9.8427148383839780218e03,1.0765576773720192317e-8 +}; +static double d[8] = { + 2.2266688044328115691e01,2.3538790178262499861e02,1.5193775994075548050e03, + 6.4855582982667607550e03,1.8615571640885098091e04,3.4900952721145977266e04, + 3.8912003286093271411e04,1.9685429676859990727e04 +}; +static double half = 0.5e0; +static double p[6] = { + 2.1589853405795699e-1,1.274011611602473639e-1,2.2235277870649807e-2, + 1.421619193227893466e-3,2.9112874951168792e-5,2.307344176494017303e-2 +}; +static double one = 1.0e0; +static double q[5] = { + 1.28426009614491121e00,4.68238212480865118e-1,6.59881378689285515e-2, + 3.78239633202758244e-3,7.29751555083966205e-5 +}; +static double sixten = 1.60e0; +static double sqrpi = 3.9894228040143267794e-1; +static double thrsh = 0.66291e0; +static double root32 = 5.656854248e0; +static double zero = 0.0e0; +static int K1 = 1; +static int K2 = 2; +static int i; +static double del,eps,temp,x,xden,xnum,y,xsq,min; +/* +------------------------------------------------------------------ + Machine dependent constants +------------------------------------------------------------------ +*/ + eps = spmpar(&K1)*0.5e0; + min = spmpar(&K2); + x = *arg; + y = fabs(x); + if(y <= thrsh) { +/* +------------------------------------------------------------------ + Evaluate anorm for |X| <= 0.66291 +------------------------------------------------------------------ +*/ + xsq = zero; + if(y > eps) xsq = x*x; + xnum = a[4]*xsq; + xden = xsq; + for(i=0; i<3; i++) { + xnum = (xnum+a[i])*xsq; + xden = (xden+b[i])*xsq; + } + *result = x*(xnum+a[3])/(xden+b[3]); + temp = *result; + *result = half+temp; + *ccum = half-temp; + } +/* +------------------------------------------------------------------ + Evaluate anorm for 0.66291 <= |X| <= sqrt(32) +------------------------------------------------------------------ +*/ + else if(y <= root32) { + xnum = c[8]*y; + xden = y; + for(i=0; i<7; i++) { + xnum = (xnum+c[i])*y; + xden = (xden+d[i])*y; + } + *result = (xnum+c[7])/(xden+d[7]); + xsq = fifdint(y*sixten)/sixten; + del = (y-xsq)*(y+xsq); + *result = exp(-(xsq*xsq*half))*exp(-(del*half))**result; + *ccum = one-*result; + if(x > zero) { + temp = *result; + *result = *ccum; + *ccum = temp; + } + } +/* +------------------------------------------------------------------ + Evaluate anorm for |X| > sqrt(32) +------------------------------------------------------------------ +*/ + else { + *result = zero; + xsq = one/(x*x); + xnum = p[5]*xsq; + xden = xsq; + for(i=0; i<4; i++) { + xnum = (xnum+p[i])*xsq; + xden = (xden+q[i])*xsq; + } + *result = xsq*(xnum+p[4])/(xden+q[4]); + *result = (sqrpi-*result)/y; + xsq = fifdint(x*sixten)/sixten; + del = (x-xsq)*(x+xsq); + *result = exp(-(xsq*xsq*half))*exp(-(del*half))**result; + *ccum = one-*result; + if(x > zero) { + temp = *result; + *result = *ccum; + *ccum = temp; + } + } + if(*result < min) *result = 0.0e0; +/* +------------------------------------------------------------------ + Fix up for negative argument, erf, etc. +------------------------------------------------------------------ +----------Last card of ANORM ---------- +*/ + if(*ccum < min) *ccum = 0.0e0; +} /* END */ + +/***=====================================================================***/ +static void cumpoi(double *s,double *xlam,double *cum,double *ccum) +/* +********************************************************************** + + void cumpoi(double *s,double *xlam,double *cum,double *ccum) + CUMulative POIsson distribution + + + Function + + + Returns the probability of S or fewer events in a Poisson + distribution with mean XLAM. + + + Arguments + + + S --> Upper limit of cumulation of the Poisson. + S is DOUBLE PRECISION + + XLAM --> Mean of the Poisson distribution. + XLAM is DOUBLE PRECIS + + CUM <-- Cumulative poisson distribution. + CUM is DOUBLE PRECISION + + CCUM <-- Compliment of Cumulative poisson distribution. + CCUM is DOUBLE PRECIS + + + Method + + + Uses formula 26.4.21 of Abramowitz and Stegun, Handbook of + Mathematical Functions to reduce the cumulative Poisson to + the cumulative chi-square distribution. + +********************************************************************** +*/ +{ +static double chi,df; +/* + .. + .. Executable Statements .. +*/ + df = 2.0e0*(*s+1.0e0); + chi = 2.0e0**xlam; + cumchi(&chi,&df,ccum,cum); + return; +} /* END */ + +/***=====================================================================***/ +static void cumt(double *t,double *df,double *cum,double *ccum) +/* +********************************************************************** + + void cumt(double *t,double *df,double *cum,double *ccum) + CUMulative T-distribution + + + Function + + + Computes the integral from -infinity to T of the t-density. + + + Arguments + + + T --> Upper limit of integration of the t-density. + T is DOUBLE PRECISION + + DF --> Degrees of freedom of the t-distribution. + DF is DOUBLE PRECISIO + + CUM <-- Cumulative t-distribution. + CCUM is DOUBLE PRECIS + + CCUM <-- Compliment of Cumulative t-distribution. + CCUM is DOUBLE PRECIS + + + Method + + + Formula 26.5.27 of Abramowitz and Stegun, Handbook of + Mathematical Functions is used to reduce the t-distribution + to an incomplete beta. + +********************************************************************** +*/ +{ +static double K2 = 0.5e0; +static double xx,a,oma,tt,yy,dfptt,T1; +/* + .. + .. Executable Statements .. +*/ + tt = *t**t; + dfptt = *df+tt; + xx = *df/dfptt; + yy = tt/dfptt; + T1 = 0.5e0**df; + cumbet(&xx,&yy,&T1,&K2,&a,&oma); + if(!(*t <= 0.0e0)) goto S10; + *cum = 0.5e0*a; + *ccum = oma+*cum; + goto S20; +S10: + *ccum = 0.5e0*a; + *cum = oma+*ccum; +S20: + return; +} /* END */ + +/***=====================================================================***/ +static double dbetrm(double *a,double *b) +/* +********************************************************************** + + double dbetrm(double *a,double *b) + Double Precision Sterling Remainder for Complete + Beta Function + + + Function + + + Log(Beta(A,B)) = Lgamma(A) + Lgamma(B) - Lgamma(A+B) + where Lgamma is the log of the (complete) gamma function + + Let ZZ be approximation obtained if each log gamma is approximated + by Sterling's formula, i.e., + Sterling(Z) = LOG( SQRT( 2*PI ) ) + ( Z-0.5 ) * LOG( Z ) - Z + + Returns Log(Beta(A,B)) - ZZ + + + Arguments + + + A --> One argument of the Beta + DOUBLE PRECISION A + + B --> The other argument of the Beta + DOUBLE PRECISION B + +********************************************************************** +*/ +{ +static double dbetrm,T1,T2,T3; +/* + .. + .. Executable Statements .. +*/ +/* + Try to sum from smallest to largest +*/ + T1 = *a+*b; + dbetrm = -dstrem(&T1); + T2 = fifdmax1(*a,*b); + dbetrm += dstrem(&T2); + T3 = fifdmin1(*a,*b); + dbetrm += dstrem(&T3); + return dbetrm; +} /* END */ + +/***=====================================================================***/ +static double devlpl(double a[],int *n,double *x) +/* +********************************************************************** + + double devlpl(double a[],int *n,double *x) + Double precision EVALuate a PoLynomial at X + + + Function + + + returns + A(1) + A(2)*X + ... + A(N)*X**(N-1) + + + Arguments + + + A --> Array of coefficients of the polynomial. + A is DOUBLE PRECISION(N) + + N --> Length of A, also degree of polynomial - 1. + N is INTEGER + + X --> Point at which the polynomial is to be evaluated. + X is DOUBLE PRECISION + +********************************************************************** +*/ +{ +static double devlpl,term; +static int i; +/* + .. + .. Executable Statements .. +*/ + term = a[*n-1]; + for(i= *n-1-1; i>=0; i--) term = a[i]+term**x; + devlpl = term; + return devlpl; +} /* END */ + +/***=====================================================================***/ +static double dexpm1(double *x) +/* +********************************************************************** + + double dexpm1(double *x) + Evaluation of the function EXP(X) - 1 + + + Arguments + + + X --> Argument at which exp(x)-1 desired + DOUBLE PRECISION X + + + Method + + + Renaming of function rexp from code of: + + DiDinato, A. R. and Morris, A. H. Algorithm 708: Significant + Digit Computation of the Incomplete Beta Function Ratios. ACM + Trans. Math. Softw. 18 (1993), 360-373. + +********************************************************************** +*/ +{ +static double p1 = .914041914819518e-09; +static double p2 = .238082361044469e-01; +static double q1 = -.499999999085958e+00; +static double q2 = .107141568980644e+00; +static double q3 = -.119041179760821e-01; +static double q4 = .595130811860248e-03; +static double dexpm1,w; +/* + .. + .. Executable Statements .. +*/ + if(fabs(*x) > 0.15e0) goto S10; + dexpm1 = *x*(((p2**x+p1)**x+1.0e0)/((((q4**x+q3)**x+q2)**x+q1)**x+1.0e0)); + return dexpm1; +S10: + w = exp(*x); + if(*x > 0.0e0) goto S20; + dexpm1 = w-0.5e0-0.5e0; + return dexpm1; +S20: + dexpm1 = w*(0.5e0+(0.5e0-1.0e0/w)); + return dexpm1; +} /* END */ + +/***=====================================================================***/ +static double dinvnr(double *p,double *q) +/* +********************************************************************** + + double dinvnr(double *p,double *q) + Double precision NoRmal distribution INVerse + + + Function + + + Returns X such that CUMNOR(X) = P, i.e., the integral from - + infinity to X of (1/SQRT(2*PI)) EXP(-U*U/2) dU is P + + + Arguments + + + P --> The probability whose normal deviate is sought. + P is DOUBLE PRECISION + + Q --> 1-P + P is DOUBLE PRECISION + + + Method + + + The rational function on page 95 of Kennedy and Gentle, + Statistical Computing, Marcel Dekker, NY , 1980 is used as a start + value for the Newton method of finding roots. + + + Note + + + If P or Q .lt. machine EPS returns +/- DINVNR(EPS) + +********************************************************************** +*/ +{ +#define maxit 100 +#define eps (1.0e-13) +#define r2pi 0.3989422804014326e0 +#define nhalf (-0.5e0) +#define dennor(x) (r2pi*exp(nhalf*(x)*(x))) +static double dinvnr,strtx,xcur,cum,ccum,pp,dx; +static int i; +static unsigned long qporq; +/* + .. + .. Executable Statements .. +*/ +/* + FIND MINIMUM OF P AND Q +*/ + qporq = *p <= *q; + if(!qporq) goto S10; + pp = *p; + goto S20; +S10: + pp = *q; +S20: +/* + INITIALIZATION STEP +*/ + strtx = stvaln(&pp); + xcur = strtx; +/* + NEWTON INTERATIONS +*/ + for(i=1; i<=maxit; i++) { + cumnor(&xcur,&cum,&ccum); + dx = (cum-pp)/dennor(xcur); + xcur -= dx; + if(fabs(dx/xcur) < eps) goto S40; + } + dinvnr = strtx; +/* + IF WE GET HERE, NEWTON HAS FAILED +*/ + if(!qporq) dinvnr = -dinvnr; + return dinvnr; +S40: +/* + IF WE GET HERE, NEWTON HAS SUCCEDED +*/ + dinvnr = xcur; + if(!qporq) dinvnr = -dinvnr; + return dinvnr; +#undef maxit +#undef eps +#undef r2pi +#undef nhalf +#undef dennor +} /* END */ + +/***=====================================================================***/ +static void E0000(int IENTRY,int *status,double *x,double *fx, + unsigned long *qleft,unsigned long *qhi,double *zabsst, + double *zabsto,double *zbig,double *zrelst, + double *zrelto,double *zsmall,double *zstpmu) +{ +#define qxmon(zx,zy,zz) (int)((zx) <= (zy) && (zy) <= (zz)) +static double absstp,abstol,big,fbig,fsmall,relstp,reltol,small,step,stpmul,xhi, + xlb,xlo,xsave,xub,yy; +static int i99999; +static unsigned long qbdd,qcond,qdum1,qdum2,qincr,qlim,qok,qup; + switch(IENTRY){case 0: goto DINVR; case 1: goto DSTINV;} +DINVR: + if(*status > 0) goto S310; + qcond = !qxmon(small,*x,big); + if(qcond){ ftnstop("SMALL,X,BIG nonmonotone in E0000"); *status=-1; return;} + xsave = *x; +/* + See that SMALL and BIG bound the zero and set QINCR +*/ + *x = small; +/* + GET-FUNCTION-VALUE +*/ + i99999 = 1; + goto S300; +S10: + fsmall = *fx; + *x = big; +/* + GET-FUNCTION-VALUE +*/ + i99999 = 2; + goto S300; +S20: + fbig = *fx; + qincr = fbig > fsmall; + if(!qincr) goto S50; + if(fsmall <= 0.0e0) goto S30; + *status = -1; + *qleft = *qhi = 1; + return; +S30: + if(fbig >= 0.0e0) goto S40; + *status = -1; + *qleft = *qhi = 0; + return; +S40: + goto S80; +S50: + if(fsmall >= 0.0e0) goto S60; + *status = -1; + *qleft = 1; + *qhi = 0; + return; +S60: + if(fbig <= 0.0e0) goto S70; + *status = -1; + *qleft = 0; + *qhi = 1; + return; +S80: +S70: + *x = xsave; + step = fifdmax1(absstp,relstp*fabs(*x)); +/* + YY = F(X) - Y + GET-FUNCTION-VALUE +*/ + i99999 = 3; + goto S300; +S90: + yy = *fx; + if(!(yy == 0.0e0)) goto S100; + *status = 0; + qok = 1; + return; +S100: + qup = qincr && yy < 0.0e0 || !qincr && yy > 0.0e0; +/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + HANDLE CASE IN WHICH WE MUST STEP HIGHER +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +*/ + if(!qup) goto S170; + xlb = xsave; + xub = fifdmin1(xlb+step,big); + goto S120; +S110: + if(qcond) goto S150; +S120: +/* + YY = F(XUB) - Y +*/ + *x = xub; +/* + GET-FUNCTION-VALUE +*/ + i99999 = 4; + goto S300; +S130: + yy = *fx; + qbdd = qincr && yy >= 0.0e0 || !qincr && yy <= 0.0e0; + qlim = xub >= big; + qcond = qbdd || qlim; + if(qcond) goto S140; + step = stpmul*step; + xlb = xub; + xub = fifdmin1(xlb+step,big); +S140: + goto S110; +S150: + if(!(qlim && !qbdd)) goto S160; + *status = -1; + *qleft = 0; + *qhi = !qincr; + *x = big; + return; +S160: + goto S240; +S170: +/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + HANDLE CASE IN WHICH WE MUST STEP LOWER +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +*/ + xub = xsave; + xlb = fifdmax1(xub-step,small); + goto S190; +S180: + if(qcond) goto S220; +S190: +/* + YY = F(XLB) - Y +*/ + *x = xlb; +/* + GET-FUNCTION-VALUE +*/ + i99999 = 5; + goto S300; +S200: + yy = *fx; + qbdd = qincr && yy <= 0.0e0 || !qincr && yy >= 0.0e0; + qlim = xlb <= small; + qcond = qbdd || qlim; + if(qcond) goto S210; + step = stpmul*step; + xub = xlb; + xlb = fifdmax1(xub-step,small); +S210: + goto S180; +S220: + if(!(qlim && !qbdd)) goto S230; + *status = -1; + *qleft = 1; + *qhi = qincr; + *x = small; + return; +S240: +S230: + dstzr(&xlb,&xub,&abstol,&reltol); +/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + IF WE REACH HERE, XLB AND XUB BOUND THE ZERO OF F. +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ +*/ + *status = 0; + goto S260; +S250: + if(!(*status == 1)) goto S290; +S260: + dzror(status,x,fx,&xlo,&xhi,&qdum1,&qdum2); + if(!(*status == 1)) goto S280; +/* + GET-FUNCTION-VALUE +*/ + i99999 = 6; + goto S300; +S280: +S270: + goto S250; +S290: + *x = xlo; + *status = 0; + return; +DSTINV: + small = *zsmall; + big = *zbig; + absstp = *zabsst; + relstp = *zrelst; + stpmul = *zstpmu; + abstol = *zabsto; + reltol = *zrelto; + return; +S300: +/* + TO GET-FUNCTION-VALUE +*/ + *status = 1; + return; +S310: + switch((int)i99999){case 1: goto S10;case 2: goto S20;case 3: goto S90;case + 4: goto S130;case 5: goto S200;case 6: goto S270;default: break;} +#undef qxmon +} /* END */ + +/***=====================================================================***/ +static void dinvr(int *status,double *x,double *fx, + unsigned long *qleft,unsigned long *qhi) +/* +********************************************************************** + + void dinvr(int *status,double *x,double *fx, + unsigned long *qleft,unsigned long *qhi) + + Double precision + bounds the zero of the function and invokes zror + Reverse Communication + + + Function + + + Bounds the function and invokes ZROR to perform the zero + finding. STINVR must have been called before this routine + in order to set its parameters. + + + Arguments + + + STATUS <--> At the beginning of a zero finding problem, STATUS + should be set to 0 and INVR invoked. (The value + of parameters other than X will be ignored on this cal + + When INVR needs the function evaluated, it will set + STATUS to 1 and return. The value of the function + should be set in FX and INVR again called without + changing any of its other parameters. + + When INVR has finished without error, it will return + with STATUS 0. In that case X is approximately a root + of F(X). + + If INVR cannot bound the function, it returns status + -1 and sets QLEFT and QHI. + INTEGER STATUS + + X <-- The value of X at which F(X) is to be evaluated. + DOUBLE PRECISION X + + FX --> The value of F(X) calculated when INVR returns with + STATUS = 1. + DOUBLE PRECISION FX + + QLEFT <-- Defined only if QMFINV returns .FALSE. In that + case it is .TRUE. If the stepping search terminated + unsucessfully at SMALL. If it is .FALSE. the search + terminated unsucessfully at BIG. + QLEFT is LOGICAL + + QHI <-- Defined only if QMFINV returns .FALSE. In that + case it is .TRUE. if F(X) .GT. Y at the termination + of the search and .FALSE. if F(X) .LT. Y at the + termination of the search. + QHI is LOGICAL + +********************************************************************** +*/ +{ + E0000(0,status,x,fx,qleft,qhi,NULL,NULL,NULL,NULL,NULL,NULL,NULL); +} /* END */ + +/***=====================================================================***/ +static void dstinv(double *zsmall,double *zbig,double *zabsst, + double *zrelst,double *zstpmu,double *zabsto, + double *zrelto) +/* +********************************************************************** + void dstinv(double *zsmall,double *zbig,double *zabsst, + double *zrelst,double *zstpmu,double *zabsto, + double *zrelto) + + Double Precision - SeT INverse finder - Reverse Communication + Function + Concise Description - Given a monotone function F finds X + such that F(X) = Y. Uses Reverse communication -- see invr. + This routine sets quantities needed by INVR. + More Precise Description of INVR - + F must be a monotone function, the results of QMFINV are + otherwise undefined. QINCR must be .TRUE. if F is non- + decreasing and .FALSE. if F is non-increasing. + QMFINV will return .TRUE. if and only if F(SMALL) and + F(BIG) bracket Y, i. e., + QINCR is .TRUE. and F(SMALL).LE.Y.LE.F(BIG) or + QINCR is .FALSE. and F(BIG).LE.Y.LE.F(SMALL) + if QMFINV returns .TRUE., then the X returned satisfies + the following condition. let + TOL(X) = MAX(ABSTOL,RELTOL*ABS(X)) + then if QINCR is .TRUE., + F(X-TOL(X)) .LE. Y .LE. F(X+TOL(X)) + and if QINCR is .FALSE. + F(X-TOL(X)) .GE. Y .GE. F(X+TOL(X)) + Arguments + SMALL --> The left endpoint of the interval to be + searched for a solution. + SMALL is DOUBLE PRECISION + BIG --> The right endpoint of the interval to be + searched for a solution. + BIG is DOUBLE PRECISION + ABSSTP, RELSTP --> The initial step size in the search + is MAX(ABSSTP,RELSTP*ABS(X)). See algorithm. + ABSSTP is DOUBLE PRECISION + RELSTP is DOUBLE PRECISION + STPMUL --> When a step doesn't bound the zero, the step + size is multiplied by STPMUL and another step + taken. A popular value is 2.0 + DOUBLE PRECISION STPMUL + ABSTOL, RELTOL --> Two numbers that determine the accuracy + of the solution. See function for a precise definition. + ABSTOL is DOUBLE PRECISION + RELTOL is DOUBLE PRECISION + Method + Compares F(X) with Y for the input value of X then uses QINCR + to determine whether to step left or right to bound the + desired x. the initial step size is + MAX(ABSSTP,RELSTP*ABS(S)) for the input value of X. + Iteratively steps right or left until it bounds X. + At each step which doesn't bound X, the step size is doubled. + The routine is careful never to step beyond SMALL or BIG. If + it hasn't bounded X at SMALL or BIG, QMFINV returns .FALSE. + after setting QLEFT and QHI. + If X is successfully bounded then Algorithm R of the paper + 'Two Efficient Algorithms with Guaranteed Convergence for + Finding a Zero of a Function' by J. C. P. Bus and + T. J. Dekker in ACM Transactions on Mathematical + Software, Volume 1, No. 4 page 330 (DEC. '75) is employed + to find the zero of the function F(X)-Y. This is routine + QRZERO. +********************************************************************** +*/ +{ + E0000(1,NULL,NULL,NULL,NULL,NULL,zabsst,zabsto,zbig,zrelst,zrelto,zsmall, + zstpmu); +} /* END */ + +/***=====================================================================***/ +static double dlanor(double *x) +/* +********************************************************************** + + double dlanor(double *x) + Double precision Logarith of the Asymptotic Normal + + + Function + + + Computes the logarithm of the cumulative normal distribution + from abs( x ) to infinity for abs( x ) >= 5. + + + Arguments + + + X --> Value at which cumulative normal to be evaluated + DOUBLE PRECISION X + + + Method + + + 23 term expansion of formula 26.2.12 of Abramowitz and Stegun. + The relative error at X = 5 is about 0.5E-5. + + + Note + + + ABS(X) must be >= 5 else there is an error stop. + +********************************************************************** +*/ +{ +#define dlsqpi 0.91893853320467274177e0 +static double coef[12] = { + -1.0e0,3.0e0,-15.0e0,105.0e0,-945.0e0,10395.0e0,-135135.0e0,2027025.0e0, + -34459425.0e0,654729075.0e0,-13749310575.e0,316234143225.0e0 +}; +static int K1 = 12; +static double dlanor,approx,correc,xx,xx2,T2; +/* + .. + .. Executable Statements .. +*/ + xx = fabs(*x); + if(xx < 5.0e0){ ftnstop("Argument too small in DLANOR"); return 66.6; } + approx = -dlsqpi-0.5e0*xx*xx-log(xx); + xx2 = xx*xx; + T2 = 1.0e0/xx2; + correc = devlpl(coef,&K1,&T2)/xx2; + correc = dln1px(&correc); + dlanor = approx+correc; + return dlanor; +#undef dlsqpi +} /* END */ + +/***=====================================================================***/ +static double dln1mx(double *x) +/* +********************************************************************** + + double dln1mx(double *x) + Double precision LN(1-X) + + + Function + + + Returns ln(1-x) for small x (good accuracy if x .le. 0.1). + Note that the obvious code of + LOG(1.0-X) + won't work for small X because 1.0-X loses accuracy + + + Arguments + + + X --> Value for which ln(1-x) is desired. + X is DOUBLE PRECISION + + + Method + + + If X > 0.1, the obvious code above is used ELSE + The Taylor series for 1-x is expanded to 20 terms. + +********************************************************************** +*/ +{ +static double dln1mx,T1; +/* + .. + .. Executable Statements .. +*/ + T1 = -*x; + dln1mx = dln1px(&T1); + return dln1mx; +} /* END */ + +/***=====================================================================***/ +static double dln1px(double *a) +/* +********************************************************************** + + double dln1px(double *a) + Double precision LN(1+X) + + + Function + + + Returns ln(1+x) + Note that the obvious code of + LOG(1.0+X) + won't work for small X because 1.0+X loses accuracy + + + Arguments + + + X --> Value for which ln(1-x) is desired. + X is DOUBLE PRECISION + + + Method + + + Renames ALNREL from: + DiDinato, A. R. and Morris, A. H. Algorithm 708: Significant + Digit Computation of the Incomplete Beta Function Ratios. ACM + Trans. Math. Softw. 18 (1993), 360-373. + +********************************************************************** +----------------------------------------------------------------------- + EVALUATION OF THE FUNCTION LN(1 + A) +----------------------------------------------------------------------- +*/ +{ +static double p1 = -.129418923021993e+01; +static double p2 = .405303492862024e+00; +static double p3 = -.178874546012214e-01; +static double q1 = -.162752256355323e+01; +static double q2 = .747811014037616e+00; +static double q3 = -.845104217945565e-01; +static double dln1px,t,t2,w,x; +/* + .. + .. Executable Statements .. +*/ + if(fabs(*a) > 0.375e0) goto S10; + t = *a/(*a+2.0e0); + t2 = t*t; + w = (((p3*t2+p2)*t2+p1)*t2+1.0e0)/(((q3*t2+q2)*t2+q1)*t2+1.0e0); + dln1px = 2.0e0*t*w; + return dln1px; +S10: + x = 1.e0+*a; + dln1px = log(x); + return dln1px; +} /* END */ + +/***=====================================================================***/ +static double dlnbet(double *a0,double *b0) +/* +********************************************************************** + + double dlnbet(a0,b0) + Double precision LN of the complete BETa + + + Function + + + Returns the natural log of the complete beta function, + i.e., + + ln( Gamma(a)*Gamma(b) / Gamma(a+b) + + + Arguments + + + A,B --> The (symmetric) arguments to the complete beta + DOUBLE PRECISION A, B + + + Method + + + Renames BETALN from: + DiDinato, A. R. and Morris, A. H. Algorithm 708: Significant + Digit Computation of the Incomplete Beta Function Ratios. ACM + Trans. Math. Softw. 18 (1993), 360-373. + +********************************************************************** +----------------------------------------------------------------------- + EVALUATION OF THE LOGARITHM OF THE BETA FUNCTION +----------------------------------------------------------------------- + E = 0.5*LN(2*PI) +-------------------------- +*/ +{ +static double e = .918938533204673e0; +static double dlnbet,a,b,c,h,u,v,w,z; +static int i,n; +static double T1; +/* + .. + .. Executable Statements .. +*/ + a = fifdmin1(*a0,*b0); + b = fifdmax1(*a0,*b0); + if(a >= 8.0e0) goto S100; + if(a >= 1.0e0) goto S20; +/* +----------------------------------------------------------------------- + PROCEDURE WHEN A .LT. 1 +----------------------------------------------------------------------- +*/ + if(b >= 8.0e0) goto S10; + T1 = a+b; + dlnbet = gamln(&a)+(gamln(&b)-gamln(&T1)); + return dlnbet; +S10: + dlnbet = gamln(&a)+algdiv(&a,&b); + return dlnbet; +S20: +/* +----------------------------------------------------------------------- + PROCEDURE WHEN 1 .LE. A .LT. 8 +----------------------------------------------------------------------- +*/ + if(a > 2.0e0) goto S40; + if(b > 2.0e0) goto S30; + dlnbet = gamln(&a)+gamln(&b)-gsumln(&a,&b); + return dlnbet; +S30: + w = 0.0e0; + if(b < 8.0e0) goto S60; + dlnbet = gamln(&a)+algdiv(&a,&b); + return dlnbet; +S40: +/* + REDUCTION OF A WHEN B .LE. 1000 +*/ + if(b > 1000.0e0) goto S80; + n = a-1.0e0; + w = 1.0e0; + for(i=1; i<=n; i++) { + a -= 1.0e0; + h = a/b; + w *= (h/(1.0e0+h)); + } + w = log(w); + if(b < 8.0e0) goto S60; + dlnbet = w+gamln(&a)+algdiv(&a,&b); + return dlnbet; +S60: +/* + REDUCTION OF B WHEN B .LT. 8 +*/ + n = b-1.0e0; + z = 1.0e0; + for(i=1; i<=n; i++) { + b -= 1.0e0; + z *= (b/(a+b)); + } + dlnbet = w+log(z)+(gamln(&a)+(gamln(&b)-gsumln(&a,&b))); + return dlnbet; +S80: +/* + REDUCTION OF A WHEN B .GT. 1000 +*/ + n = a-1.0e0; + w = 1.0e0; + for(i=1; i<=n; i++) { + a -= 1.0e0; + w *= (a/(1.0e0+a/b)); + } + dlnbet = log(w)-(double)n*log(b)+(gamln(&a)+algdiv(&a,&b)); + return dlnbet; +S100: +/* +----------------------------------------------------------------------- + PROCEDURE WHEN A .GE. 8 +----------------------------------------------------------------------- +*/ + w = bcorr(&a,&b); + h = a/b; + c = h/(1.0e0+h); + u = -((a-0.5e0)*log(c)); + v = b*alnrel(&h); + if(u <= v) goto S110; + dlnbet = -(0.5e0*log(b))+e+w-v-u; + return dlnbet; +S110: + dlnbet = -(0.5e0*log(b))+e+w-u-v; + return dlnbet; +} /* END */ + +/***=====================================================================***/ +static double dlngam(double *a) +/* +********************************************************************** + + double dlngam(double *a) + Double precision LN of the GAMma function + + + Function + + + Returns the natural logarithm of GAMMA(X). + + + Arguments + + + X --> value at which scaled log gamma is to be returned + X is DOUBLE PRECISION + + + Method + + + Renames GAMLN from: + DiDinato, A. R. and Morris, A. H. Algorithm 708: Significant + Digit Computation of the Incomplete Beta Function Ratios. ACM + Trans. Math. Softw. 18 (1993), 360-373. + +********************************************************************** +----------------------------------------------------------------------- + EVALUATION OF LN(GAMMA(A)) FOR POSITIVE A +----------------------------------------------------------------------- + WRITTEN BY ALFRED H. MORRIS + NAVAL SURFACE WARFARE CENTER + DAHLGREN, VIRGINIA +-------------------------- + D = 0.5*(LN(2*PI) - 1) +-------------------------- +*/ +{ +static double c0 = .833333333333333e-01; +static double c1 = -.277777777760991e-02; +static double c2 = .793650666825390e-03; +static double c3 = -.595202931351870e-03; +static double c4 = .837308034031215e-03; +static double c5 = -.165322962780713e-02; +static double d = .418938533204673e0; +static double dlngam,t,w; +static int i,n; +static double T1; +/* + .. + .. Executable Statements .. +*/ + if(*a > 0.8e0) goto S10; + dlngam = gamln1(a)-log(*a); + return dlngam; +S10: + if(*a > 2.25e0) goto S20; + t = *a-0.5e0-0.5e0; + dlngam = gamln1(&t); + return dlngam; +S20: + if(*a >= 10.0e0) goto S40; + n = *a-1.25e0; + t = *a; + w = 1.0e0; + for(i=1; i<=n; i++) { + t -= 1.0e0; + w = t*w; + } + T1 = t-1.0e0; + dlngam = gamln1(&T1)+log(w); + return dlngam; +S40: + t = pow(1.0e0/ *a,2.0); + w = (((((c5*t+c4)*t+c3)*t+c2)*t+c1)*t+c0)/ *a; + dlngam = d+w+(*a-0.5e0)*(log(*a)-1.0e0); + return dlngam; +} /* END */ + +/***=====================================================================***/ +static double dstrem(double *z) +{ +/* +********************************************************************** + double dstrem(double *z) + Double precision Sterling Remainder + Function + Returns Log(Gamma(Z)) - Sterling(Z) where Sterling(Z) is + Sterling's Approximation to Log(Gamma(Z)) + Sterling(Z) = LOG( SQRT( 2*PI ) ) + ( Z-0.5 ) * LOG( Z ) - Z + Arguments + Z --> Value at which Sterling remainder calculated + Must be positive. + DOUBLE PRECISION Z + Method + If Z >= 6 uses 9 terms of series in Bernoulli numbers + (Values calculated using Maple) + Otherwise computes difference explicitly +********************************************************************** +*/ +#define hln2pi 0.91893853320467274178e0 +#define ncoef 10 +static double coef[ncoef] = { + 0.0e0,0.0833333333333333333333333333333e0, + -0.00277777777777777777777777777778e0,0.000793650793650793650793650793651e0, + -0.000595238095238095238095238095238e0, + 0.000841750841750841750841750841751e0,-0.00191752691752691752691752691753e0, + 0.00641025641025641025641025641026e0,-0.0295506535947712418300653594771e0, + 0.179644372368830573164938490016e0 +}; +static int K1 = 10; +static double dstrem,sterl,T2; +/* + .. + .. Executable Statements .. +*/ +/* + For information, here are the next 11 coefficients of the + remainder term in Sterling's formula + -1.39243221690590111642743221691 + 13.4028640441683919944789510007 + -156.848284626002017306365132452 + 2193.10333333333333333333333333 + -36108.7712537249893571732652192 + 691472.268851313067108395250776 + -0.152382215394074161922833649589D8 + 0.382900751391414141414141414141D9 + -0.108822660357843910890151491655D11 + 0.347320283765002252252252252252D12 + -0.123696021422692744542517103493D14 +*/ + if(*z <= 0.0e0){ ftnstop("nonpositive argument in DSTREM"); return 66.6; } + if(!(*z > 6.0e0)) goto S10; + T2 = 1.0e0/pow(*z,2.0); + dstrem = devlpl(coef,&K1,&T2)**z; + goto S20; +S10: + sterl = hln2pi+(*z-0.5e0)*log(*z)-*z; + dstrem = dlngam(z)-sterl; +S20: + return dstrem; +#undef hln2pi +#undef ncoef +} /* END */ + +/***=====================================================================***/ +static double dt1(double *p,double *q,double *df) +/* +********************************************************************** + + double dt1(double *p,double *q,double *df) + Double precision Initalize Approximation to + INVerse of the cumulative T distribution + + + Function + + + Returns the inverse of the T distribution function, i.e., + the integral from 0 to INVT of the T density is P. This is an + initial approximation + + + Arguments + + + P --> The p-value whose inverse from the T distribution is + desired. + P is DOUBLE PRECISION + + Q --> 1-P. + Q is DOUBLE PRECISION + + DF --> Degrees of freedom of the T distribution. + DF is DOUBLE PRECISION + +********************************************************************** +*/ +{ +static double coef[4][5] = { + 1.0e0,1.0e0,0.0e0,0.0e0,0.0e0,3.0e0,16.0e0,5.0e0,0.0e0,0.0e0,-15.0e0,17.0e0, + 19.0e0,3.0e0,0.0e0,-945.0e0,-1920.0e0,1482.0e0,776.0e0,79.0e0 +}; +static double denom[4] = { + 4.0e0,96.0e0,384.0e0,92160.0e0 +}; +static int ideg[4] = { + 2,3,4,5 +}; +static double dt1,denpow,sum,term,x,xp,xx; +static int i; +/* + .. + .. Executable Statements .. +*/ + x = fabs(dinvnr(p,q)); + xx = x*x; + sum = x; + denpow = 1.0e0; + for(i=0; i<4; i++) { + term = devlpl(&coef[i][0],&ideg[i],&xx)*x; + denpow *= *df; + sum += (term/(denpow*denom[i])); + } + if(!(*p >= 0.5e0)) goto S20; + xp = sum; + goto S30; +S20: + xp = -sum; +S30: + dt1 = xp; + return dt1; +} /* END */ + +/***=====================================================================***/ +static void E0001(int IENTRY,int *status,double *x,double *fx, + double *xlo,double *xhi,unsigned long *qleft, + unsigned long *qhi,double *zabstl,double *zreltl, + double *zxhi,double *zxlo) +{ +#define ftol(zx) (0.5e0*fifdmax1(abstol,reltol*fabs((zx)))) +static double a,abstol,b,c,d,fa,fb,fc,fd,fda,fdb,m,mb,p,q,reltol,tol,w,xxhi,xxlo; +static int ext,i99999; +static unsigned long first,qrzero; + switch(IENTRY){case 0: goto DZROR; case 1: goto DSTZR;} +DZROR: + if(*status > 0) goto S280; + *xlo = xxlo; + *xhi = xxhi; + b = *x = *xlo; +/* + GET-FUNCTION-VALUE +*/ + i99999 = 1; + goto S270; +S10: + fb = *fx; + *xlo = *xhi; + a = *x = *xlo; +/* + GET-FUNCTION-VALUE +*/ + i99999 = 2; + goto S270; +S20: +/* + Check that F(ZXLO) < 0 < F(ZXHI) or + F(ZXLO) > 0 > F(ZXHI) +*/ + if(!(fb < 0.0e0)) goto S40; + if(!(*fx < 0.0e0)) goto S30; + *status = -1; + *qleft = *fx < fb; + *qhi = 0; + return; +S40: +S30: + if(!(fb > 0.0e0)) goto S60; + if(!(*fx > 0.0e0)) goto S50; + *status = -1; + *qleft = *fx > fb; + *qhi = 1; + return; +S60: +S50: + fa = *fx; + first = 1; +S70: + c = a; + fc = fa; + ext = 0; +S80: + if(!(fabs(fc) < fabs(fb))) goto S100; + if(!(c != a)) goto S90; + d = a; + fd = fa; +S90: + a = b; + fa = fb; + *xlo = c; + b = *xlo; + fb = fc; + c = a; + fc = fa; +S100: + tol = ftol(*xlo); + m = (c+b)*.5e0; + mb = m-b; + if(!(fabs(mb) > tol)) goto S240; + if(!(ext > 3)) goto S110; + w = mb; + goto S190; +S110: + tol = fifdsign(tol,mb); + p = (b-a)*fb; + if(!first) goto S120; + q = fa-fb; + first = 0; + goto S130; +S120: + fdb = (fd-fb)/(d-b); + fda = (fd-fa)/(d-a); + p = fda*p; + q = fdb*fa-fda*fb; +S130: + if(!(p < 0.0e0)) goto S140; + p = -p; + q = -q; +S140: + if(ext == 3) p *= 2.0e0; + if(!(p*1.0e0 == 0.0e0 || p <= q*tol)) goto S150; + w = tol; + goto S180; +S150: + if(!(p < mb*q)) goto S160; + w = p/q; + goto S170; +S160: + w = mb; +S190: +S180: +S170: + d = a; + fd = fa; + a = b; + fa = fb; + b += w; + *xlo = b; + *x = *xlo; +/* + GET-FUNCTION-VALUE +*/ + i99999 = 3; + goto S270; +S200: + fb = *fx; + if(!(fc*fb >= 0.0e0)) goto S210; + goto S70; +S210: + if(!(w == mb)) goto S220; + ext = 0; + goto S230; +S220: + ext += 1; +S230: + goto S80; +S240: + *xhi = c; + qrzero = fc >= 0.0e0 && fb <= 0.0e0 || fc < 0.0e0 && fb >= 0.0e0; + if(!qrzero) goto S250; + *status = 0; + goto S260; +S250: + *status = -1; +S260: + return; +DSTZR: + xxlo = *zxlo; + xxhi = *zxhi; + abstol = *zabstl; + reltol = *zreltl; + return; +S270: +/* + TO GET-FUNCTION-VALUE +*/ + *status = 1; + return; +S280: + switch((int)i99999){case 1: goto S10;case 2: goto S20;case 3: goto S200; + default: break;} +#undef ftol +} /* END */ + +/***=====================================================================***/ +static void dzror(int *status,double *x,double *fx,double *xlo, + double *xhi,unsigned long *qleft,unsigned long *qhi) +/* +********************************************************************** + + void dzror(int *status,double *x,double *fx,double *xlo, + double *xhi,unsigned long *qleft,unsigned long *qhi) + + Double precision ZeRo of a function -- Reverse Communication + + + Function + + + Performs the zero finding. STZROR must have been called before + this routine in order to set its parameters. + + + Arguments + + + STATUS <--> At the beginning of a zero finding problem, STATUS + should be set to 0 and ZROR invoked. (The value + of other parameters will be ignored on this call.) + + When ZROR needs the function evaluated, it will set + STATUS to 1 and return. The value of the function + should be set in FX and ZROR again called without + changing any of its other parameters. + + When ZROR has finished without error, it will return + with STATUS 0. In that case (XLO,XHI) bound the answe + + If ZROR finds an error (which implies that F(XLO)-Y an + F(XHI)-Y have the same sign, it returns STATUS -1. In + this case, XLO and XHI are undefined. + INTEGER STATUS + + X <-- The value of X at which F(X) is to be evaluated. + DOUBLE PRECISION X + + FX --> The value of F(X) calculated when ZROR returns with + STATUS = 1. + DOUBLE PRECISION FX + + XLO <-- When ZROR returns with STATUS = 0, XLO bounds the + inverval in X containing the solution below. + DOUBLE PRECISION XLO + + XHI <-- When ZROR returns with STATUS = 0, XHI bounds the + inverval in X containing the solution above. + DOUBLE PRECISION XHI + + QLEFT <-- .TRUE. if the stepping search terminated unsucessfully + at XLO. If it is .FALSE. the search terminated + unsucessfully at XHI. + QLEFT is LOGICAL + + QHI <-- .TRUE. if F(X) .GT. Y at the termination of the + search and .FALSE. if F(X) .LT. Y at the + termination of the search. + QHI is LOGICAL + +********************************************************************** +*/ +{ + E0001(0,status,x,fx,xlo,xhi,qleft,qhi,NULL,NULL,NULL,NULL); +} /* END */ + +/***=====================================================================***/ +static void dstzr(double *zxlo,double *zxhi,double *zabstl,double *zreltl) +/* +********************************************************************** + void dstzr(double *zxlo,double *zxhi,double *zabstl,double *zreltl) + Double precision SeT ZeRo finder - Reverse communication version + Function + Sets quantities needed by ZROR. The function of ZROR + and the quantities set is given here. + Concise Description - Given a function F + find XLO such that F(XLO) = 0. + More Precise Description - + Input condition. F is a double precision function of a single + double precision argument and XLO and XHI are such that + F(XLO)*F(XHI) .LE. 0.0 + If the input condition is met, QRZERO returns .TRUE. + and output values of XLO and XHI satisfy the following + F(XLO)*F(XHI) .LE. 0. + ABS(F(XLO) .LE. ABS(F(XHI) + ABS(XLO-XHI) .LE. TOL(X) + where + TOL(X) = MAX(ABSTOL,RELTOL*ABS(X)) + If this algorithm does not find XLO and XHI satisfying + these conditions then QRZERO returns .FALSE. This + implies that the input condition was not met. + Arguments + XLO --> The left endpoint of the interval to be + searched for a solution. + XLO is DOUBLE PRECISION + XHI --> The right endpoint of the interval to be + for a solution. + XHI is DOUBLE PRECISION + ABSTOL, RELTOL --> Two numbers that determine the accuracy + of the solution. See function for a + precise definition. + ABSTOL is DOUBLE PRECISION + RELTOL is DOUBLE PRECISION + Method + Algorithm R of the paper 'Two Efficient Algorithms with + Guaranteed Convergence for Finding a Zero of a Function' + by J. C. P. Bus and T. J. Dekker in ACM Transactions on + Mathematical Software, Volume 1, no. 4 page 330 + (Dec. '75) is employed to find the zero of F(X)-Y. +********************************************************************** +*/ +{ + E0001(1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,zabstl,zreltl,zxhi,zxlo); +} /* END */ + +/***=====================================================================***/ +static double erf1(double *x) +/* +----------------------------------------------------------------------- + EVALUATION OF THE REAL ERROR FUNCTION +----------------------------------------------------------------------- +*/ +{ +static double c = .564189583547756e0; +static double a[5] = { + .771058495001320e-04,-.133733772997339e-02,.323076579225834e-01, + .479137145607681e-01,.128379167095513e+00 +}; +static double b[3] = { + .301048631703895e-02,.538971687740286e-01,.375795757275549e+00 +}; +static double p[8] = { + -1.36864857382717e-07,5.64195517478974e-01,7.21175825088309e+00, + 4.31622272220567e+01,1.52989285046940e+02,3.39320816734344e+02, + 4.51918953711873e+02,3.00459261020162e+02 +}; +static double q[8] = { + 1.00000000000000e+00,1.27827273196294e+01,7.70001529352295e+01, + 2.77585444743988e+02,6.38980264465631e+02,9.31354094850610e+02, + 7.90950925327898e+02,3.00459260956983e+02 +}; +static double r[5] = { + 2.10144126479064e+00,2.62370141675169e+01,2.13688200555087e+01, + 4.65807828718470e+00,2.82094791773523e-01 +}; +static double s[4] = { + 9.41537750555460e+01,1.87114811799590e+02,9.90191814623914e+01, + 1.80124575948747e+01 +}; +static double erf1,ax,bot,t,top,x2; +/* + .. + .. Executable Statements .. +*/ + ax = fabs(*x); + if(ax > 0.5e0) goto S10; + t = *x**x; + top = (((a[0]*t+a[1])*t+a[2])*t+a[3])*t+a[4]+1.0e0; + bot = ((b[0]*t+b[1])*t+b[2])*t+1.0e0; + erf1 = *x*(top/bot); + return erf1; +S10: + if(ax > 4.0e0) goto S20; + top = ((((((p[0]*ax+p[1])*ax+p[2])*ax+p[3])*ax+p[4])*ax+p[5])*ax+p[6])*ax+p[ + 7]; + bot = ((((((q[0]*ax+q[1])*ax+q[2])*ax+q[3])*ax+q[4])*ax+q[5])*ax+q[6])*ax+q[ + 7]; + erf1 = 0.5e0+(0.5e0-exp(-(*x**x))*top/bot); + if(*x < 0.0e0) erf1 = -erf1; + return erf1; +S20: + if(ax >= 5.8e0) goto S30; + x2 = *x**x; + t = 1.0e0/x2; + top = (((r[0]*t+r[1])*t+r[2])*t+r[3])*t+r[4]; + bot = (((s[0]*t+s[1])*t+s[2])*t+s[3])*t+1.0e0; + erf1 = (c-top/(x2*bot))/ax; + erf1 = 0.5e0+(0.5e0-exp(-x2)*erf1); + if(*x < 0.0e0) erf1 = -erf1; + return erf1; +S30: + erf1 = fifdsign(1.0e0,*x); + return erf1; +} /* END */ + +/***=====================================================================***/ +static double erfc1(int *ind,double *x) +/* +----------------------------------------------------------------------- + EVALUATION OF THE COMPLEMENTARY ERROR FUNCTION + + ERFC1(IND,X) = ERFC(X) IF IND = 0 + ERFC1(IND,X) = EXP(X*X)*ERFC(X) OTHERWISE +----------------------------------------------------------------------- +*/ +{ +static double c = .564189583547756e0; +static double a[5] = { + .771058495001320e-04,-.133733772997339e-02,.323076579225834e-01, + .479137145607681e-01,.128379167095513e+00 +}; +static double b[3] = { + .301048631703895e-02,.538971687740286e-01,.375795757275549e+00 +}; +static double p[8] = { + -1.36864857382717e-07,5.64195517478974e-01,7.21175825088309e+00, + 4.31622272220567e+01,1.52989285046940e+02,3.39320816734344e+02, + 4.51918953711873e+02,3.00459261020162e+02 +}; +static double q[8] = { + 1.00000000000000e+00,1.27827273196294e+01,7.70001529352295e+01, + 2.77585444743988e+02,6.38980264465631e+02,9.31354094850610e+02, + 7.90950925327898e+02,3.00459260956983e+02 +}; +static double r[5] = { + 2.10144126479064e+00,2.62370141675169e+01,2.13688200555087e+01, + 4.65807828718470e+00,2.82094791773523e-01 +}; +static double s[4] = { + 9.41537750555460e+01,1.87114811799590e+02,9.90191814623914e+01, + 1.80124575948747e+01 +}; +static int K1 = 1; +static double erfc1,ax,bot,e,t,top,w; +/* + .. + .. Executable Statements .. +*/ +/* + ABS(X) .LE. 0.5 +*/ + ax = fabs(*x); + if(ax > 0.5e0) goto S10; + t = *x**x; + top = (((a[0]*t+a[1])*t+a[2])*t+a[3])*t+a[4]+1.0e0; + bot = ((b[0]*t+b[1])*t+b[2])*t+1.0e0; + erfc1 = 0.5e0+(0.5e0-*x*(top/bot)); + if(*ind != 0) erfc1 = exp(t)*erfc1; + return erfc1; +S10: +/* + 0.5 .LT. ABS(X) .LE. 4 +*/ + if(ax > 4.0e0) goto S20; + top = ((((((p[0]*ax+p[1])*ax+p[2])*ax+p[3])*ax+p[4])*ax+p[5])*ax+p[6])*ax+p[ + 7]; + bot = ((((((q[0]*ax+q[1])*ax+q[2])*ax+q[3])*ax+q[4])*ax+q[5])*ax+q[6])*ax+q[ + 7]; + erfc1 = top/bot; + goto S40; +S20: +/* + ABS(X) .GT. 4 +*/ + if(*x <= -5.6e0) goto S60; + if(*ind != 0) goto S30; + if(*x > 100.0e0) goto S70; + if(*x**x > -exparg(&K1)) goto S70; +S30: + t = pow(1.0e0/ *x,2.0); + top = (((r[0]*t+r[1])*t+r[2])*t+r[3])*t+r[4]; + bot = (((s[0]*t+s[1])*t+s[2])*t+s[3])*t+1.0e0; + erfc1 = (c-t*top/bot)/ax; +S40: +/* + FINAL ASSEMBLY +*/ + if(*ind == 0) goto S50; + if(*x < 0.0e0) erfc1 = 2.0e0*exp(*x**x)-erfc1; + return erfc1; +S50: + w = *x**x; + t = w; + e = w-t; + erfc1 = (0.5e0+(0.5e0-e))*exp(-t)*erfc1; + if(*x < 0.0e0) erfc1 = 2.0e0-erfc1; + return erfc1; +S60: +/* + LIMIT VALUE FOR LARGE NEGATIVE X +*/ + erfc1 = 2.0e0; + if(*ind != 0) erfc1 = 2.0e0*exp(*x**x); + return erfc1; +S70: +/* + LIMIT VALUE FOR LARGE POSITIVE X + WHEN IND = 0 +*/ + erfc1 = 0.0e0; + return erfc1; +} /* END */ + +/***=====================================================================***/ +static double esum(int *mu,double *x) +/* +----------------------------------------------------------------------- + EVALUATION OF EXP(MU + X) +----------------------------------------------------------------------- +*/ +{ +static double esum,w; +/* + .. + .. Executable Statements .. +*/ + if(*x > 0.0e0) goto S10; + if(*mu < 0) goto S20; + w = (double)*mu+*x; + if(w > 0.0e0) goto S20; + esum = exp(w); + return esum; +S10: + if(*mu > 0) goto S20; + w = (double)*mu+*x; + if(w < 0.0e0) goto S20; + esum = exp(w); + return esum; +S20: + w = *mu; + esum = exp(w)*exp(*x); + return esum; +} /* END */ + +/***=====================================================================***/ +static double exparg(int *l) +/* +-------------------------------------------------------------------- + IF L = 0 THEN EXPARG(L) = THE LARGEST POSITIVE W FOR WHICH + EXP(W) CAN BE COMPUTED. + + IF L IS NONZERO THEN EXPARG(L) = THE LARGEST NEGATIVE W FOR + WHICH THE COMPUTED VALUE OF EXP(W) IS NONZERO. + + NOTE... ONLY AN APPROXIMATE VALUE FOR EXPARG(L) IS NEEDED. +-------------------------------------------------------------------- +*/ +{ +static int K1 = 4; +static int K2 = 9; +static int K3 = 10; +static double exparg,lnb; +static int b,m; +/* + .. + .. Executable Statements .. +*/ + b = ipmpar(&K1); + if(b != 2) goto S10; + lnb = .69314718055995e0; + goto S40; +S10: + if(b != 8) goto S20; + lnb = 2.0794415416798e0; + goto S40; +S20: + if(b != 16) goto S30; + lnb = 2.7725887222398e0; + goto S40; +S30: + lnb = log((double)b); +S40: + if(*l == 0) goto S50; + m = ipmpar(&K2)-1; + exparg = 0.99999e0*((double)m*lnb); + return exparg; +S50: + m = ipmpar(&K3); + exparg = 0.99999e0*((double)m*lnb); + return exparg; +} /* END */ + +/***=====================================================================***/ +static double fpser(double *a,double *b,double *x,double *eps) +/* +----------------------------------------------------------------------- + + EVALUATION OF I (A,B) + X + + FOR B .LT. MIN(EPS,EPS*A) AND X .LE. 0.5. + +----------------------------------------------------------------------- + + SET FPSER = X**A +*/ +{ +static int K1 = 1; +static double fpser,an,c,s,t,tol; +/* + .. + .. Executable Statements .. +*/ + fpser = 1.0e0; + if(*a <= 1.e-3**eps) goto S10; + fpser = 0.0e0; + t = *a*log(*x); + if(t < exparg(&K1)) return fpser; + fpser = exp(t); +S10: +/* + NOTE THAT 1/B(A,B) = B +*/ + fpser = *b/ *a*fpser; + tol = *eps/ *a; + an = *a+1.0e0; + t = *x; + s = t/an; +S20: + an += 1.0e0; + t = *x*t; + c = t/an; + s += c; + if(fabs(c) > tol) goto S20; + fpser *= (1.0e0+*a*s); + return fpser; +} /* END */ + +/***=====================================================================***/ +static double gam1(double *a) +/* + ------------------------------------------------------------------ + COMPUTATION OF 1/GAMMA(A+1) - 1 FOR -0.5 .LE. A .LE. 1.5 + ------------------------------------------------------------------ +*/ +{ +static double s1 = .273076135303957e+00; +static double s2 = .559398236957378e-01; +static double p[7] = { + .577215664901533e+00,-.409078193005776e+00,-.230975380857675e+00, + .597275330452234e-01,.766968181649490e-02,-.514889771323592e-02, + .589597428611429e-03 +}; +static double q[5] = { + .100000000000000e+01,.427569613095214e+00,.158451672430138e+00, + .261132021441447e-01,.423244297896961e-02 +}; +static double r[9] = { + -.422784335098468e+00,-.771330383816272e+00,-.244757765222226e+00, + .118378989872749e+00,.930357293360349e-03,-.118290993445146e-01, + .223047661158249e-02,.266505979058923e-03,-.132674909766242e-03 +}; +static double gam1,bot,d,t,top,w,T1; +/* + .. + .. Executable Statements .. +*/ + t = *a; + d = *a-0.5e0; + if(d > 0.0e0) t = d-0.5e0; + T1 = t; + if(T1 < 0) goto S40; + else if(T1 == 0) goto S10; + else goto S20; +S10: + gam1 = 0.0e0; + return gam1; +S20: + top = (((((p[6]*t+p[5])*t+p[4])*t+p[3])*t+p[2])*t+p[1])*t+p[0]; + bot = (((q[4]*t+q[3])*t+q[2])*t+q[1])*t+1.0e0; + w = top/bot; + if(d > 0.0e0) goto S30; + gam1 = *a*w; + return gam1; +S30: + gam1 = t/ *a*(w-0.5e0-0.5e0); + return gam1; +S40: + top = (((((((r[8]*t+r[7])*t+r[6])*t+r[5])*t+r[4])*t+r[3])*t+r[2])*t+r[1])*t+ + r[0]; + bot = (s2*t+s1)*t+1.0e0; + w = top/bot; + if(d > 0.0e0) goto S50; + gam1 = *a*(w+0.5e0+0.5e0); + return gam1; +S50: + gam1 = t*w/ *a; + return gam1; +} /* END */ + +/***=====================================================================***/ +static void gaminv(double *a,double *x,double *x0,double *p,double *q, + int *ierr) +/* + ---------------------------------------------------------------------- + INVERSE INCOMPLETE GAMMA RATIO FUNCTION + + GIVEN POSITIVE A, AND NONEGATIVE P AND Q WHERE P + Q = 1. + THEN X IS COMPUTED WHERE P(A,X) = P AND Q(A,X) = Q. SCHRODER + ITERATION IS EMPLOYED. THE ROUTINE ATTEMPTS TO COMPUTE X + TO 10 SIGNIFICANT DIGITS IF THIS IS POSSIBLE FOR THE + PARTICULAR COMPUTER ARITHMETIC BEING USED. + + ------------ + + X IS A VARIABLE. IF P = 0 THEN X IS ASSIGNED THE VALUE 0, + AND IF Q = 0 THEN X IS SET TO THE LARGEST FLOATING POINT + NUMBER AVAILABLE. OTHERWISE, GAMINV ATTEMPTS TO OBTAIN + A SOLUTION FOR P(A,X) = P AND Q(A,X) = Q. IF THE ROUTINE + IS SUCCESSFUL THEN THE SOLUTION IS STORED IN X. + + X0 IS AN OPTIONAL INITIAL APPROXIMATION FOR X. IF THE USER + DOES NOT WISH TO SUPPLY AN INITIAL APPROXIMATION, THEN SET + X0 .LE. 0. + + IERR IS A VARIABLE THAT REPORTS THE STATUS OF THE RESULTS. + WHEN THE ROUTINE TERMINATES, IERR HAS ONE OF THE FOLLOWING + VALUES ... + + IERR = 0 THE SOLUTION WAS OBTAINED. ITERATION WAS + NOT USED. + IERR.GT.0 THE SOLUTION WAS OBTAINED. IERR ITERATIONS + WERE PERFORMED. + IERR = -2 (INPUT ERROR) A .LE. 0 + IERR = -3 NO SOLUTION WAS OBTAINED. THE RATIO Q/A + IS TOO LARGE. + IERR = -4 (INPUT ERROR) P + Q .NE. 1 + IERR = -6 20 ITERATIONS WERE PERFORMED. THE MOST + RECENT VALUE OBTAINED FOR X IS GIVEN. + THIS CANNOT OCCUR IF X0 .LE. 0. + IERR = -7 ITERATION FAILED. NO VALUE IS GIVEN FOR X. + THIS MAY OCCUR WHEN X IS APPROXIMATELY 0. + IERR = -8 A VALUE FOR X HAS BEEN OBTAINED, BUT THE + ROUTINE IS NOT CERTAIN OF ITS ACCURACY. + ITERATION CANNOT BE PERFORMED IN THIS + CASE. IF X0 .LE. 0, THIS CAN OCCUR ONLY + WHEN P OR Q IS APPROXIMATELY 0. IF X0 IS + POSITIVE THEN THIS CAN OCCUR WHEN A IS + EXCEEDINGLY CLOSE TO X AND A IS EXTREMELY + LARGE (SAY A .GE. 1.E20). + ---------------------------------------------------------------------- + WRITTEN BY ALFRED H. MORRIS, JR. + NAVAL SURFACE WEAPONS CENTER + DAHLGREN, VIRGINIA + ------------------- +*/ +{ +static double a0 = 3.31125922108741e0; +static double a1 = 11.6616720288968e0; +static double a2 = 4.28342155967104e0; +static double a3 = .213623493715853e0; +static double b1 = 6.61053765625462e0; +static double b2 = 6.40691597760039e0; +static double b3 = 1.27364489782223e0; +static double b4 = .036117081018842e0; +static double c = .577215664901533e0; +static double ln10 = 2.302585e0; +static double tol = 1.e-5; +static double amin[2] = { + 500.0e0,100.0e0 +}; +static double bmin[2] = { + 1.e-28,1.e-13 +}; +static double dmin[2] = { + 1.e-06,1.e-04 +}; +static double emin[2] = { + 2.e-03,6.e-03 +}; +static double eps0[2] = { + 1.e-10,1.e-08 +}; +static int K1 = 1; +static int K2 = 2; +static int K3 = 3; +static int K8 = 0; +static double am1,amax,ap1,ap2,ap3,apn,b,c1,c2,c3,c4,c5,d,e,e2,eps,g,h,pn,qg,qn, + r,rta,s,s2,sum,t,u,w,xmax,xmin,xn,y,z; +static int iop; +static double T4,T5,T6,T7,T9; +/* + .. + .. Executable Statements .. +*/ +/* + ****** E, XMIN, AND XMAX ARE MACHINE DEPENDENT CONSTANTS. + E IS THE SMALLEST NUMBER FOR WHICH 1.0 + E .GT. 1.0. + XMIN IS THE SMALLEST POSITIVE NUMBER AND XMAX IS THE + LARGEST POSITIVE NUMBER. +*/ + e = spmpar(&K1); + xmin = spmpar(&K2); + xmax = spmpar(&K3); + *x = 0.0e0; + if(*a <= 0.0e0) goto S300; + t = *p+*q-1.e0; + if(fabs(t) > e) goto S320; + *ierr = 0; + if(*p == 0.0e0) return; + if(*q == 0.0e0) goto S270; + if(*a == 1.0e0) goto S280; + e2 = 2.0e0*e; + amax = 0.4e-10/(e*e); + iop = 1; + if(e > 1.e-10) iop = 2; + eps = eps0[iop-1]; + xn = *x0; + if(*x0 > 0.0e0) goto S160; +/* + SELECTION OF THE INITIAL APPROXIMATION XN OF X + WHEN A .LT. 1 +*/ + if(*a > 1.0e0) goto S80; + T4 = *a+1.0e0; + g = Xgamm(&T4); + qg = *q*g; + if(qg == 0.0e0) goto S360; + b = qg/ *a; + if(qg > 0.6e0**a) goto S40; + if(*a >= 0.30e0 || b < 0.35e0) goto S10; + t = exp(-(b+c)); + u = t*exp(t); + xn = t*exp(u); + goto S160; +S10: + if(b >= 0.45e0) goto S40; + if(b == 0.0e0) goto S360; + y = -log(b); + s = 0.5e0+(0.5e0-*a); + z = log(y); + t = y-s*z; + if(b < 0.15e0) goto S20; + xn = y-s*log(t)-log(1.0e0+s/(t+1.0e0)); + goto S220; +S20: + if(b <= 0.01e0) goto S30; + u = ((t+2.0e0*(3.0e0-*a))*t+(2.0e0-*a)*(3.0e0-*a))/((t+(5.0e0-*a))*t+2.0e0); + xn = y-s*log(t)-log(u); + goto S220; +S30: + c1 = -(s*z); + c2 = -(s*(1.0e0+c1)); + c3 = s*((0.5e0*c1+(2.0e0-*a))*c1+(2.5e0-1.5e0**a)); + c4 = -(s*(((c1/3.0e0+(2.5e0-1.5e0**a))*c1+((*a-6.0e0)**a+7.0e0))*c1+( + (11.0e0**a-46.0)**a+47.0e0)/6.0e0)); + c5 = -(s*((((-(c1/4.0e0)+(11.0e0**a-17.0e0)/6.0e0)*c1+((-(3.0e0**a)+13.0e0)* + *a-13.0e0))*c1+0.5e0*(((2.0e0**a-25.0e0)**a+72.0e0)**a-61.0e0))*c1+(( + (25.0e0**a-195.0e0)**a+477.0e0)**a-379.0e0)/12.0e0)); + xn = (((c5/y+c4)/y+c3)/y+c2)/y+c1+y; + if(*a > 1.0e0) goto S220; + if(b > bmin[iop-1]) goto S220; + *x = xn; + return; +S40: + if(b**q > 1.e-8) goto S50; + xn = exp(-(*q/ *a+c)); + goto S70; +S50: + if(*p <= 0.9e0) goto S60; + T5 = -*q; + xn = exp((alnrel(&T5)+gamln1(a))/ *a); + goto S70; +S60: + xn = exp(log(*p*g)/ *a); +S70: + if(xn == 0.0e0) goto S310; + t = 0.5e0+(0.5e0-xn/(*a+1.0e0)); + xn /= t; + goto S160; +S80: +/* + SELECTION OF THE INITIAL APPROXIMATION XN OF X + WHEN A .GT. 1 +*/ + if(*q <= 0.5e0) goto S90; + w = log(*p); + goto S100; +S90: + w = log(*q); +S100: + t = sqrt(-(2.0e0*w)); + s = t-(((a3*t+a2)*t+a1)*t+a0)/((((b4*t+b3)*t+b2)*t+b1)*t+1.0e0); + if(*q > 0.5e0) s = -s; + rta = sqrt(*a); + s2 = s*s; + xn = *a+s*rta+(s2-1.0e0)/3.0e0+s*(s2-7.0e0)/(36.0e0*rta)-((3.0e0*s2+7.0e0)* + s2-16.0e0)/(810.0e0**a)+s*((9.0e0*s2+256.0e0)*s2-433.0e0)/(38880.0e0**a* + rta); + xn = fifdmax1(xn,0.0e0); + if(*a < amin[iop-1]) goto S110; + *x = xn; + d = 0.5e0+(0.5e0-*x/ *a); + if(fabs(d) <= dmin[iop-1]) return; +S110: + if(*p <= 0.5e0) goto S130; + if(xn < 3.0e0**a) goto S220; + y = -(w+gamln(a)); + d = fifdmax1(2.0e0,*a*(*a-1.0e0)); + if(y < ln10*d) goto S120; + s = 1.0e0-*a; + z = log(y); + goto S30; +S120: + t = *a-1.0e0; + T6 = -(t/(xn+1.0e0)); + xn = y+t*log(xn)-alnrel(&T6); + T7 = -(t/(xn+1.0e0)); + xn = y+t*log(xn)-alnrel(&T7); + goto S220; +S130: + ap1 = *a+1.0e0; + if(xn > 0.70e0*ap1) goto S170; + w += gamln(&ap1); + if(xn > 0.15e0*ap1) goto S140; + ap2 = *a+2.0e0; + ap3 = *a+3.0e0; + *x = exp((w+*x)/ *a); + *x = exp((w+*x-log(1.0e0+*x/ap1*(1.0e0+*x/ap2)))/ *a); + *x = exp((w+*x-log(1.0e0+*x/ap1*(1.0e0+*x/ap2)))/ *a); + *x = exp((w+*x-log(1.0e0+*x/ap1*(1.0e0+*x/ap2*(1.0e0+*x/ap3))))/ *a); + xn = *x; + if(xn > 1.e-2*ap1) goto S140; + if(xn <= emin[iop-1]*ap1) return; + goto S170; +S140: + apn = ap1; + t = xn/apn; + sum = 1.0e0+t; +S150: + apn += 1.0e0; + t *= (xn/apn); + sum += t; + if(t > 1.e-4) goto S150; + t = w-log(sum); + xn = exp((xn+t)/ *a); + xn *= (1.0e0-(*a*log(xn)-xn-t)/(*a-xn)); + goto S170; +S160: +/* + SCHRODER ITERATION USING P +*/ + if(*p > 0.5e0) goto S220; +S170: + if(*p <= 1.e10*xmin) goto S350; + am1 = *a-0.5e0-0.5e0; +S180: + if(*a <= amax) goto S190; + d = 0.5e0+(0.5e0-xn/ *a); + if(fabs(d) <= e2) goto S350; +S190: + if(*ierr >= 20) goto S330; + *ierr += 1; + gratio(a,&xn,&pn,&qn,&K8); + if(pn == 0.0e0 || qn == 0.0e0) goto S350; + r = rcomp(a,&xn); + if(r == 0.0e0) goto S350; + t = (pn-*p)/r; + w = 0.5e0*(am1-xn); + if(fabs(t) <= 0.1e0 && fabs(w*t) <= 0.1e0) goto S200; + *x = xn*(1.0e0-t); + if(*x <= 0.0e0) goto S340; + d = fabs(t); + goto S210; +S200: + h = t*(1.0e0+w*t); + *x = xn*(1.0e0-h); + if(*x <= 0.0e0) goto S340; + if(fabs(w) >= 1.0e0 && fabs(w)*t*t <= eps) return; + d = fabs(h); +S210: + xn = *x; + if(d > tol) goto S180; + if(d <= eps) return; + if(fabs(*p-pn) <= tol**p) return; + goto S180; +S220: +/* + SCHRODER ITERATION USING Q +*/ + if(*q <= 1.e10*xmin) goto S350; + am1 = *a-0.5e0-0.5e0; +S230: + if(*a <= amax) goto S240; + d = 0.5e0+(0.5e0-xn/ *a); + if(fabs(d) <= e2) goto S350; +S240: + if(*ierr >= 20) goto S330; + *ierr += 1; + gratio(a,&xn,&pn,&qn,&K8); + if(pn == 0.0e0 || qn == 0.0e0) goto S350; + r = rcomp(a,&xn); + if(r == 0.0e0) goto S350; + t = (*q-qn)/r; + w = 0.5e0*(am1-xn); + if(fabs(t) <= 0.1e0 && fabs(w*t) <= 0.1e0) goto S250; + *x = xn*(1.0e0-t); + if(*x <= 0.0e0) goto S340; + d = fabs(t); + goto S260; +S250: + h = t*(1.0e0+w*t); + *x = xn*(1.0e0-h); + if(*x <= 0.0e0) goto S340; + if(fabs(w) >= 1.0e0 && fabs(w)*t*t <= eps) return; + d = fabs(h); +S260: + xn = *x; + if(d > tol) goto S230; + if(d <= eps) return; + if(fabs(*q-qn) <= tol**q) return; + goto S230; +S270: +/* + SPECIAL CASES +*/ + *x = xmax; + return; +S280: + if(*q < 0.9e0) goto S290; + T9 = -*p; + *x = -alnrel(&T9); + return; +S290: + *x = -log(*q); + return; +S300: +/* + ERROR RETURN +*/ + *ierr = -2; + return; +S310: + *ierr = -3; + return; +S320: + *ierr = -4; + return; +S330: + *ierr = -6; + return; +S340: + *ierr = -7; + return; +S350: + *x = xn; + *ierr = -8; + return; +S360: + *x = xmax; + *ierr = -8; + return; +} /* END */ + +/***=====================================================================***/ +static double gamln(double *a) +/* +----------------------------------------------------------------------- + EVALUATION OF LN(GAMMA(A)) FOR POSITIVE A +----------------------------------------------------------------------- + WRITTEN BY ALFRED H. MORRIS + NAVAL SURFACE WARFARE CENTER + DAHLGREN, VIRGINIA +-------------------------- + D = 0.5*(LN(2*PI) - 1) +-------------------------- +*/ +{ +static double c0 = .833333333333333e-01; +static double c1 = -.277777777760991e-02; +static double c2 = .793650666825390e-03; +static double c3 = -.595202931351870e-03; +static double c4 = .837308034031215e-03; +static double c5 = -.165322962780713e-02; +static double d = .418938533204673e0; +static double gamln,t,w; +static int i,n; +static double T1; +/* + .. + .. Executable Statements .. +*/ + if(*a > 0.8e0) goto S10; + gamln = gamln1(a)-log(*a); + return gamln; +S10: + if(*a > 2.25e0) goto S20; + t = *a-0.5e0-0.5e0; + gamln = gamln1(&t); + return gamln; +S20: + if(*a >= 10.0e0) goto S40; + n = *a-1.25e0; + t = *a; + w = 1.0e0; + for(i=1; i<=n; i++) { + t -= 1.0e0; + w = t*w; + } + T1 = t-1.0e0; + gamln = gamln1(&T1)+log(w); + return gamln; +S40: + t = pow(1.0e0/ *a,2.0); + w = (((((c5*t+c4)*t+c3)*t+c2)*t+c1)*t+c0)/ *a; + gamln = d+w+(*a-0.5e0)*(log(*a)-1.0e0); + return gamln; +} /* END */ + +/***=====================================================================***/ +static double gamln1(double *a) +/* +----------------------------------------------------------------------- + EVALUATION OF LN(GAMMA(1 + A)) FOR -0.2 .LE. A .LE. 1.25 +----------------------------------------------------------------------- +*/ +{ +static double p0 = .577215664901533e+00; +static double p1 = .844203922187225e+00; +static double p2 = -.168860593646662e+00; +static double p3 = -.780427615533591e+00; +static double p4 = -.402055799310489e+00; +static double p5 = -.673562214325671e-01; +static double p6 = -.271935708322958e-02; +static double q1 = .288743195473681e+01; +static double q2 = .312755088914843e+01; +static double q3 = .156875193295039e+01; +static double q4 = .361951990101499e+00; +static double q5 = .325038868253937e-01; +static double q6 = .667465618796164e-03; +static double r0 = .422784335098467e+00; +static double r1 = .848044614534529e+00; +static double r2 = .565221050691933e+00; +static double r3 = .156513060486551e+00; +static double r4 = .170502484022650e-01; +static double r5 = .497958207639485e-03; +static double s1 = .124313399877507e+01; +static double s2 = .548042109832463e+00; +static double s3 = .101552187439830e+00; +static double s4 = .713309612391000e-02; +static double s5 = .116165475989616e-03; +static double gamln1,w,x; +/* + .. + .. Executable Statements .. +*/ + if(*a >= 0.6e0) goto S10; + w = ((((((p6**a+p5)**a+p4)**a+p3)**a+p2)**a+p1)**a+p0)/((((((q6**a+q5)**a+ + q4)**a+q3)**a+q2)**a+q1)**a+1.0e0); + gamln1 = -(*a*w); + return gamln1; +S10: + x = *a-0.5e0-0.5e0; + w = (((((r5*x+r4)*x+r3)*x+r2)*x+r1)*x+r0)/(((((s5*x+s4)*x+s3)*x+s2)*x+s1)*x + +1.0e0); + gamln1 = x*w; + return gamln1; +} /* END */ + +/***=====================================================================***/ +static double Xgamm(double *a) +/* +----------------------------------------------------------------------- + + EVALUATION OF THE GAMMA FUNCTION FOR REAL ARGUMENTS + + ----------- + + GAMMA(A) IS ASSIGNED THE VALUE 0 WHEN THE GAMMA FUNCTION CANNOT + BE COMPUTED. + +----------------------------------------------------------------------- + WRITTEN BY ALFRED H. MORRIS, JR. + NAVAL SURFACE WEAPONS CENTER + DAHLGREN, VIRGINIA +----------------------------------------------------------------------- +*/ +{ +static double d = .41893853320467274178e0; +static double pi = 3.1415926535898e0; +static double r1 = .820756370353826e-03; +static double r2 = -.595156336428591e-03; +static double r3 = .793650663183693e-03; +static double r4 = -.277777777770481e-02; +static double r5 = .833333333333333e-01; +static double p[7] = { + .539637273585445e-03,.261939260042690e-02,.204493667594920e-01, + .730981088720487e-01,.279648642639792e+00,.553413866010467e+00,1.0e0 +}; +static double q[7] = { + -.832979206704073e-03,.470059485860584e-02,.225211131035340e-01, + -.170458969313360e+00,-.567902761974940e-01,.113062953091122e+01,1.0e0 +}; +static int K2 = 3; +static int K3 = 0; +static double Xgamm,bot,g,lnx,s,t,top,w,x,z; +static int i,j,m,n,T1; +/* + .. + .. Executable Statements .. +*/ + Xgamm = 0.0e0; + x = *a; + if(fabs(*a) >= 15.0e0) goto S110; +/* +----------------------------------------------------------------------- + EVALUATION OF GAMMA(A) FOR ABS(A) .LT. 15 +----------------------------------------------------------------------- +*/ + t = 1.0e0; + m = fifidint(*a)-1; +/* + LET T BE THE PRODUCT OF A-J WHEN A .GE. 2 +*/ + T1 = m; + if(T1 < 0) goto S40; + else if(T1 == 0) goto S30; + else goto S10; +S10: + for(j=1; j<=m; j++) { + x -= 1.0e0; + t = x*t; + } +S30: + x -= 1.0e0; + goto S80; +S40: +/* + LET T BE THE PRODUCT OF A+J WHEN A .LT. 1 +*/ + t = *a; + if(*a > 0.0e0) goto S70; + m = -m-1; + if(m == 0) goto S60; + for(j=1; j<=m; j++) { + x += 1.0e0; + t = x*t; + } +S60: + x += (0.5e0+0.5e0); + t = x*t; + if(t == 0.0e0) return Xgamm; +S70: +/* + THE FOLLOWING CODE CHECKS IF 1/T CAN OVERFLOW. THIS + CODE MAY BE OMITTED IF DESIRED. +*/ + if(fabs(t) >= 1.e-30) goto S80; + if(fabs(t)*spmpar(&K2) <= 1.0001e0) return Xgamm; + Xgamm = 1.0e0/t; + return Xgamm; +S80: +/* + COMPUTE GAMMA(1 + X) FOR 0 .LE. X .LT. 1 +*/ + top = p[0]; + bot = q[0]; + for(i=1; i<7; i++) { + top = p[i]+x*top; + bot = q[i]+x*bot; + } + Xgamm = top/bot; +/* + TERMINATION +*/ + if(*a < 1.0e0) goto S100; + Xgamm *= t; + return Xgamm; +S100: + Xgamm /= t; + return Xgamm; +S110: +/* +----------------------------------------------------------------------- + EVALUATION OF GAMMA(A) FOR ABS(A) .GE. 15 +----------------------------------------------------------------------- +*/ + if(fabs(*a) >= 1.e3) return Xgamm; + if(*a > 0.0e0) goto S120; + x = -*a; + n = x; + t = x-(double)n; + if(t > 0.9e0) t = 1.0e0-t; + s = sin(pi*t)/pi; + if(fifmod(n,2) == 0) s = -s; + if(s == 0.0e0) return Xgamm; +S120: +/* + COMPUTE THE MODIFIED ASYMPTOTIC SUM +*/ + t = 1.0e0/(x*x); + g = ((((r1*t+r2)*t+r3)*t+r4)*t+r5)/x; +/* + ONE MAY REPLACE THE NEXT STATEMENT WITH LNX = ALOG(X) + BUT LESS ACCURACY WILL NORMALLY BE OBTAINED. +*/ + lnx = log(x); +/* + FINAL ASSEMBLY +*/ + z = x; + g = d+g+(z-0.5e0)*(lnx-1.e0); + w = g; + t = g-w; + if(w > 0.99999e0*exparg(&K3)) return Xgamm; + Xgamm = exp(w)*(1.0e0+t); + if(*a < 0.0e0) Xgamm = 1.0e0/(Xgamm*s)/x; + return Xgamm; +} /* END */ + +/***=====================================================================***/ +static void grat1(double *a,double *x,double *r,double *p,double *q, + double *eps) +{ +static int K2 = 0; +static double a2n,a2nm1,am0,an,an0,b2n,b2nm1,c,cma,g,h,j,l,sum,t,tol,w,z,T1,T3; +/* + .. + .. Executable Statements .. +*/ +/* +----------------------------------------------------------------------- + EVALUATION OF THE INCOMPLETE GAMMA RATIO FUNCTIONS + P(A,X) AND Q(A,X) + IT IS ASSUMED THAT A .LE. 1. EPS IS THE TOLERANCE TO BE USED. + THE INPUT ARGUMENT R HAS THE VALUE E**(-X)*X**A/GAMMA(A). +----------------------------------------------------------------------- +*/ + if(*a**x == 0.0e0) goto S120; + if(*a == 0.5e0) goto S100; + if(*x < 1.1e0) goto S10; + goto S60; +S10: +/* + TAYLOR SERIES FOR P(A,X)/X**A +*/ + an = 3.0e0; + c = *x; + sum = *x/(*a+3.0e0); + tol = 0.1e0**eps/(*a+1.0e0); +S20: + an += 1.0e0; + c = -(c*(*x/an)); + t = c/(*a+an); + sum += t; + if(fabs(t) > tol) goto S20; + j = *a**x*((sum/6.0e0-0.5e0/(*a+2.0e0))**x+1.0e0/(*a+1.0e0)); + z = *a*log(*x); + h = gam1(a); + g = 1.0e0+h; + if(*x < 0.25e0) goto S30; + if(*a < *x/2.59e0) goto S50; + goto S40; +S30: + if(z > -.13394e0) goto S50; +S40: + w = exp(z); + *p = w*g*(0.5e0+(0.5e0-j)); + *q = 0.5e0+(0.5e0-*p); + return; +S50: + l = rexp(&z); + w = 0.5e0+(0.5e0+l); + *q = (w*j-l)*g-h; + if(*q < 0.0e0) goto S90; + *p = 0.5e0+(0.5e0-*q); + return; +S60: +/* + CONTINUED FRACTION EXPANSION +*/ + a2nm1 = a2n = 1.0e0; + b2nm1 = *x; + b2n = *x+(1.0e0-*a); + c = 1.0e0; +S70: + a2nm1 = *x*a2n+c*a2nm1; + b2nm1 = *x*b2n+c*b2nm1; + am0 = a2nm1/b2nm1; + c += 1.0e0; + cma = c-*a; + a2n = a2nm1+cma*a2n; + b2n = b2nm1+cma*b2n; + an0 = a2n/b2n; + if(fabs(an0-am0) >= *eps*an0) goto S70; + *q = *r*an0; + *p = 0.5e0+(0.5e0-*q); + return; +S80: +/* + SPECIAL CASES +*/ + *p = 0.0e0; + *q = 1.0e0; + return; +S90: + *p = 1.0e0; + *q = 0.0e0; + return; +S100: + if(*x >= 0.25e0) goto S110; + T1 = sqrt(*x); + *p = erf1(&T1); + *q = 0.5e0+(0.5e0-*p); + return; +S110: + T3 = sqrt(*x); + *q = erfc1(&K2,&T3); + *p = 0.5e0+(0.5e0-*q); + return; +S120: + if(*x <= *a) goto S80; + goto S90; +} /* END */ + +/***=====================================================================***/ +static void gratio(double *a,double *x,double *ans,double *qans,int *ind) +/* + ---------------------------------------------------------------------- + EVALUATION OF THE INCOMPLETE GAMMA RATIO FUNCTIONS + P(A,X) AND Q(A,X) + + ---------- + + IT IS ASSUMED THAT A AND X ARE NONNEGATIVE, WHERE A AND X + ARE NOT BOTH 0. + + ANS AND QANS ARE VARIABLES. GRATIO ASSIGNS ANS THE VALUE + P(A,X) AND QANS THE VALUE Q(A,X). IND MAY BE ANY INTEGER. + IF IND = 0 THEN THE USER IS REQUESTING AS MUCH ACCURACY AS + POSSIBLE (UP TO 14 SIGNIFICANT DIGITS). OTHERWISE, IF + IND = 1 THEN ACCURACY IS REQUESTED TO WITHIN 1 UNIT OF THE + 6-TH SIGNIFICANT DIGIT, AND IF IND .NE. 0,1 THEN ACCURACY + IS REQUESTED TO WITHIN 1 UNIT OF THE 3RD SIGNIFICANT DIGIT. + + ERROR RETURN ... + ANS IS ASSIGNED THE VALUE 2 WHEN A OR X IS NEGATIVE, + WHEN A*X = 0, OR WHEN P(A,X) AND Q(A,X) ARE INDETERMINANT. + P(A,X) AND Q(A,X) ARE COMPUTATIONALLY INDETERMINANT WHEN + X IS EXCEEDINGLY CLOSE TO A AND A IS EXTREMELY LARGE. + ---------------------------------------------------------------------- + WRITTEN BY ALFRED H. MORRIS, JR. + NAVAL SURFACE WEAPONS CENTER + DAHLGREN, VIRGINIA + -------------------- +*/ +{ +static double alog10 = 2.30258509299405e0; +static double d10 = -.185185185185185e-02; +static double d20 = .413359788359788e-02; +static double d30 = .649434156378601e-03; +static double d40 = -.861888290916712e-03; +static double d50 = -.336798553366358e-03; +static double d60 = .531307936463992e-03; +static double d70 = .344367606892378e-03; +static double rt2pin = .398942280401433e0; +static double rtpi = 1.77245385090552e0; +static double third = .333333333333333e0; +static double acc0[3] = { + 5.e-15,5.e-7,5.e-4 +}; +static double big[3] = { + 20.0e0,14.0e0,10.0e0 +}; +static double d0[13] = { + .833333333333333e-01,-.148148148148148e-01,.115740740740741e-02, + .352733686067019e-03,-.178755144032922e-03,.391926317852244e-04, + -.218544851067999e-05,-.185406221071516e-05,.829671134095309e-06, + -.176659527368261e-06,.670785354340150e-08,.102618097842403e-07, + -.438203601845335e-08 +}; +static double d1[12] = { + -.347222222222222e-02,.264550264550265e-02,-.990226337448560e-03, + .205761316872428e-03,-.401877572016461e-06,-.180985503344900e-04, + .764916091608111e-05,-.161209008945634e-05,.464712780280743e-08, + .137863344691572e-06,-.575254560351770e-07,.119516285997781e-07 +}; +static double d2[10] = { + -.268132716049383e-02,.771604938271605e-03,.200938786008230e-05, + -.107366532263652e-03,.529234488291201e-04,-.127606351886187e-04, + .342357873409614e-07,.137219573090629e-05,-.629899213838006e-06, + .142806142060642e-06 +}; +static double d3[8] = { + .229472093621399e-03,-.469189494395256e-03,.267720632062839e-03, + -.756180167188398e-04,-.239650511386730e-06,.110826541153473e-04, + -.567495282699160e-05,.142309007324359e-05 +}; +static double d4[6] = { + .784039221720067e-03,-.299072480303190e-03,-.146384525788434e-05, + .664149821546512e-04,-.396836504717943e-04,.113757269706784e-04 +}; +static double d5[4] = { + -.697281375836586e-04,.277275324495939e-03,-.199325705161888e-03, + .679778047793721e-04 +}; +static double d6[2] = { + -.592166437353694e-03,.270878209671804e-03 +}; +static double e00[3] = { + .25e-3,.25e-1,.14e0 +}; +static double x00[3] = { + 31.0e0,17.0e0,9.7e0 +}; +static int K1 = 1; +static int K2 = 0; +static double a2n,a2nm1,acc,am0,amn,an,an0,apn,b2n,b2nm1,c,c0,c1,c2,c3,c4,c5,c6, + cma,e,e0,g,h,j,l,r,rta,rtx,s,sum,t,t1,tol,twoa,u,w,x0,y,z; +static int i,iop,m,max,n; +static double wk[20],T3; +static int T4,T5; +static double T6,T7; +/* + .. + .. Executable Statements .. +*/ +/* + -------------------- + ****** E IS A MACHINE DEPENDENT CONSTANT. E IS THE SMALLEST + FLOATING POINT NUMBER FOR WHICH 1.0 + E .GT. 1.0 . +*/ + e = spmpar(&K1); + if(*a < 0.0e0 || *x < 0.0e0) goto S430; + if(*a == 0.0e0 && *x == 0.0e0) goto S430; + if(*a**x == 0.0e0) goto S420; + iop = *ind+1; + if(iop != 1 && iop != 2) iop = 3; + acc = fifdmax1(acc0[iop-1],e); + e0 = e00[iop-1]; + x0 = x00[iop-1]; +/* + SELECT THE APPROPRIATE ALGORITHM +*/ + if(*a >= 1.0e0) goto S10; + if(*a == 0.5e0) goto S390; + if(*x < 1.1e0) goto S160; + t1 = *a*log(*x)-*x; + u = *a*exp(t1); + if(u == 0.0e0) goto S380; + r = u*(1.0e0+gam1(a)); + goto S250; +S10: + if(*a >= big[iop-1]) goto S30; + if(*a > *x || *x >= x0) goto S20; + twoa = *a+*a; + m = fifidint(twoa); + if(twoa != (double)m) goto S20; + i = m/2; + if(*a == (double)i) goto S210; + goto S220; +S20: + t1 = *a*log(*x)-*x; + r = exp(t1)/Xgamm(a); + goto S40; +S30: + l = *x/ *a; + if(l == 0.0e0) goto S370; + s = 0.5e0+(0.5e0-l); + z = rlog(&l); + if(z >= 700.0e0/ *a) goto S410; + y = *a*z; + rta = sqrt(*a); + if(fabs(s) <= e0/rta) goto S330; + if(fabs(s) <= 0.4e0) goto S270; + t = pow(1.0e0/ *a,2.0); + t1 = (((0.75e0*t-1.0e0)*t+3.5e0)*t-105.0e0)/(*a*1260.0e0); + t1 -= y; + r = rt2pin*rta*exp(t1); +S40: + if(r == 0.0e0) goto S420; + if(*x <= fifdmax1(*a,alog10)) goto S50; + if(*x < x0) goto S250; + goto S100; +S50: +/* + TAYLOR SERIES FOR P/R +*/ + apn = *a+1.0e0; + t = *x/apn; + wk[0] = t; + for(n=2; n<=20; n++) { + apn += 1.0e0; + t *= (*x/apn); + if(t <= 1.e-3) goto S70; + wk[n-1] = t; + } + n = 20; +S70: + sum = t; + tol = 0.5e0*acc; +S80: + apn += 1.0e0; + t *= (*x/apn); + sum += t; + if(t > tol) goto S80; + max = n-1; + for(m=1; m<=max; m++) { + n -= 1; + sum += wk[n-1]; + } + *ans = r/ *a*(1.0e0+sum); + *qans = 0.5e0+(0.5e0-*ans); + return; +S100: +/* + ASYMPTOTIC EXPANSION +*/ + amn = *a-1.0e0; + t = amn/ *x; + wk[0] = t; + for(n=2; n<=20; n++) { + amn -= 1.0e0; + t *= (amn/ *x); + if(fabs(t) <= 1.e-3) goto S120; + wk[n-1] = t; + } + n = 20; +S120: + sum = t; +S130: + if(fabs(t) <= acc) goto S140; + amn -= 1.0e0; + t *= (amn/ *x); + sum += t; + goto S130; +S140: + max = n-1; + for(m=1; m<=max; m++) { + n -= 1; + sum += wk[n-1]; + } + *qans = r/ *x*(1.0e0+sum); + *ans = 0.5e0+(0.5e0-*qans); + return; +S160: +/* + TAYLOR SERIES FOR P(A,X)/X**A +*/ + an = 3.0e0; + c = *x; + sum = *x/(*a+3.0e0); + tol = 3.0e0*acc/(*a+1.0e0); +S170: + an += 1.0e0; + c = -(c*(*x/an)); + t = c/(*a+an); + sum += t; + if(fabs(t) > tol) goto S170; + j = *a**x*((sum/6.0e0-0.5e0/(*a+2.0e0))**x+1.0e0/(*a+1.0e0)); + z = *a*log(*x); + h = gam1(a); + g = 1.0e0+h; + if(*x < 0.25e0) goto S180; + if(*a < *x/2.59e0) goto S200; + goto S190; +S180: + if(z > -.13394e0) goto S200; +S190: + w = exp(z); + *ans = w*g*(0.5e0+(0.5e0-j)); + *qans = 0.5e0+(0.5e0-*ans); + return; +S200: + l = rexp(&z); + w = 0.5e0+(0.5e0+l); + *qans = (w*j-l)*g-h; + if(*qans < 0.0e0) goto S380; + *ans = 0.5e0+(0.5e0-*qans); + return; +S210: +/* + FINITE SUMS FOR Q WHEN A .GE. 1 + AND 2*A IS AN INTEGER +*/ + sum = exp(-*x); + t = sum; + n = 1; + c = 0.0e0; + goto S230; +S220: + rtx = sqrt(*x); + sum = erfc1(&K2,&rtx); + t = exp(-*x)/(rtpi*rtx); + n = 0; + c = -0.5e0; +S230: + if(n == i) goto S240; + n += 1; + c += 1.0e0; + t = *x*t/c; + sum += t; + goto S230; +S240: + *qans = sum; + *ans = 0.5e0+(0.5e0-*qans); + return; +S250: +/* + CONTINUED FRACTION EXPANSION +*/ + tol = fifdmax1(5.0e0*e,acc); + a2nm1 = a2n = 1.0e0; + b2nm1 = *x; + b2n = *x+(1.0e0-*a); + c = 1.0e0; +S260: + a2nm1 = *x*a2n+c*a2nm1; + b2nm1 = *x*b2n+c*b2nm1; + am0 = a2nm1/b2nm1; + c += 1.0e0; + cma = c-*a; + a2n = a2nm1+cma*a2n; + b2n = b2nm1+cma*b2n; + an0 = a2n/b2n; + if(fabs(an0-am0) >= tol*an0) goto S260; + *qans = r*an0; + *ans = 0.5e0+(0.5e0-*qans); + return; +S270: +/* + GENERAL TEMME EXPANSION +*/ + if(fabs(s) <= 2.0e0*e && *a*e*e > 3.28e-3) goto S430; + c = exp(-y); + T3 = sqrt(y); + w = 0.5e0*erfc1(&K1,&T3); + u = 1.0e0/ *a; + z = sqrt(z+z); + if(l < 1.0e0) z = -z; + T4 = iop-2; + if(T4 < 0) goto S280; + else if(T4 == 0) goto S290; + else goto S300; +S280: + if(fabs(s) <= 1.e-3) goto S340; + c0 = ((((((((((((d0[12]*z+d0[11])*z+d0[10])*z+d0[9])*z+d0[8])*z+d0[7])*z+d0[ + 6])*z+d0[5])*z+d0[4])*z+d0[3])*z+d0[2])*z+d0[1])*z+d0[0])*z-third; + c1 = (((((((((((d1[11]*z+d1[10])*z+d1[9])*z+d1[8])*z+d1[7])*z+d1[6])*z+d1[5] + )*z+d1[4])*z+d1[3])*z+d1[2])*z+d1[1])*z+d1[0])*z+d10; + c2 = (((((((((d2[9]*z+d2[8])*z+d2[7])*z+d2[6])*z+d2[5])*z+d2[4])*z+d2[3])*z+ + d2[2])*z+d2[1])*z+d2[0])*z+d20; + c3 = (((((((d3[7]*z+d3[6])*z+d3[5])*z+d3[4])*z+d3[3])*z+d3[2])*z+d3[1])*z+ + d3[0])*z+d30; + c4 = (((((d4[5]*z+d4[4])*z+d4[3])*z+d4[2])*z+d4[1])*z+d4[0])*z+d40; + c5 = (((d5[3]*z+d5[2])*z+d5[1])*z+d5[0])*z+d50; + c6 = (d6[1]*z+d6[0])*z+d60; + t = ((((((d70*u+c6)*u+c5)*u+c4)*u+c3)*u+c2)*u+c1)*u+c0; + goto S310; +S290: + c0 = (((((d0[5]*z+d0[4])*z+d0[3])*z+d0[2])*z+d0[1])*z+d0[0])*z-third; + c1 = (((d1[3]*z+d1[2])*z+d1[1])*z+d1[0])*z+d10; + c2 = d2[0]*z+d20; + t = (c2*u+c1)*u+c0; + goto S310; +S300: + t = ((d0[2]*z+d0[1])*z+d0[0])*z-third; +S310: + if(l < 1.0e0) goto S320; + *qans = c*(w+rt2pin*t/rta); + *ans = 0.5e0+(0.5e0-*qans); + return; +S320: + *ans = c*(w-rt2pin*t/rta); + *qans = 0.5e0+(0.5e0-*ans); + return; +S330: +/* + TEMME EXPANSION FOR L = 1 +*/ + if(*a*e*e > 3.28e-3) goto S430; + c = 0.5e0+(0.5e0-y); + w = (0.5e0-sqrt(y)*(0.5e0+(0.5e0-y/3.0e0))/rtpi)/c; + u = 1.0e0/ *a; + z = sqrt(z+z); + if(l < 1.0e0) z = -z; + T5 = iop-2; + if(T5 < 0) goto S340; + else if(T5 == 0) goto S350; + else goto S360; +S340: + c0 = ((((((d0[6]*z+d0[5])*z+d0[4])*z+d0[3])*z+d0[2])*z+d0[1])*z+d0[0])*z- + third; + c1 = (((((d1[5]*z+d1[4])*z+d1[3])*z+d1[2])*z+d1[1])*z+d1[0])*z+d10; + c2 = ((((d2[4]*z+d2[3])*z+d2[2])*z+d2[1])*z+d2[0])*z+d20; + c3 = (((d3[3]*z+d3[2])*z+d3[1])*z+d3[0])*z+d30; + c4 = (d4[1]*z+d4[0])*z+d40; + c5 = (d5[1]*z+d5[0])*z+d50; + c6 = d6[0]*z+d60; + t = ((((((d70*u+c6)*u+c5)*u+c4)*u+c3)*u+c2)*u+c1)*u+c0; + goto S310; +S350: + c0 = (d0[1]*z+d0[0])*z-third; + c1 = d1[0]*z+d10; + t = (d20*u+c1)*u+c0; + goto S310; +S360: + t = d0[0]*z-third; + goto S310; +S370: +/* + SPECIAL CASES +*/ + *ans = 0.0e0; + *qans = 1.0e0; + return; +S380: + *ans = 1.0e0; + *qans = 0.0e0; + return; +S390: + if(*x >= 0.25e0) goto S400; + T6 = sqrt(*x); + *ans = erf1(&T6); + *qans = 0.5e0+(0.5e0-*ans); + return; +S400: + T7 = sqrt(*x); + *qans = erfc1(&K2,&T7); + *ans = 0.5e0+(0.5e0-*qans); + return; +S410: + if(fabs(s) <= 2.0e0*e) goto S430; +S420: + if(*x <= *a) goto S370; + goto S380; +S430: +/* + ERROR RETURN +*/ + *ans = 2.0e0; + return; +} /* END */ + +/***=====================================================================***/ +static double gsumln(double *a,double *b) +/* +----------------------------------------------------------------------- + EVALUATION OF THE FUNCTION LN(GAMMA(A + B)) + FOR 1 .LE. A .LE. 2 AND 1 .LE. B .LE. 2 +----------------------------------------------------------------------- +*/ +{ +static double gsumln,x,T1,T2; +/* + .. + .. Executable Statements .. +*/ + x = *a+*b-2.e0; + if(x > 0.25e0) goto S10; + T1 = 1.0e0+x; + gsumln = gamln1(&T1); + return gsumln; +S10: + if(x > 1.25e0) goto S20; + gsumln = gamln1(&x)+alnrel(&x); + return gsumln; +S20: + T2 = x-1.0e0; + gsumln = gamln1(&T2)+log(x*(1.0e0+x)); + return gsumln; +} /* END */ + +/***=====================================================================***/ +static double psi(double *xx) +/* +--------------------------------------------------------------------- + + EVALUATION OF THE DIGAMMA FUNCTION + + ----------- + + PSI(XX) IS ASSIGNED THE VALUE 0 WHEN THE DIGAMMA FUNCTION CANNOT + BE COMPUTED. + + THE MAIN COMPUTATION INVOLVES EVALUATION OF RATIONAL CHEBYSHEV + APPROXIMATIONS PUBLISHED IN MATH. COMP. 27, 123-127(1973) BY + CODY, STRECOK AND THACHER. + +--------------------------------------------------------------------- + PSI WAS WRITTEN AT ARGONNE NATIONAL LABORATORY FOR THE FUNPACK + PACKAGE OF SPECIAL FUNCTION SUBROUTINES. PSI WAS MODIFIED BY + A.H. MORRIS (NSWC). +--------------------------------------------------------------------- +*/ +{ +static double dx0 = 1.461632144968362341262659542325721325e0; +static double piov4 = .785398163397448e0; +static double p1[7] = { + .895385022981970e-02,.477762828042627e+01,.142441585084029e+03, + .118645200713425e+04,.363351846806499e+04,.413810161269013e+04, + .130560269827897e+04 +}; +static double p2[4] = { + -.212940445131011e+01,-.701677227766759e+01,-.448616543918019e+01, + -.648157123766197e+00 +}; +static double q1[6] = { + .448452573429826e+02,.520752771467162e+03,.221000799247830e+04, + .364127349079381e+04,.190831076596300e+04,.691091682714533e-05 +}; +static double q2[4] = { + .322703493791143e+02,.892920700481861e+02,.546117738103215e+02, + .777788548522962e+01 +}; +static int K1 = 3; +static int K2 = 1; +static double psi,aug,den,sgn,upper,w,x,xmax1,xmx0,xsmall,z; +static int i,m,n,nq; +/* + .. + .. Executable Statements .. +*/ +/* +--------------------------------------------------------------------- + MACHINE DEPENDENT CONSTANTS ... + XMAX1 = THE SMALLEST POSITIVE FLOATING POINT CONSTANT + WITH ENTIRELY INTEGER REPRESENTATION. ALSO USED + AS NEGATIVE OF LOWER BOUND ON ACCEPTABLE NEGATIVE + ARGUMENTS AND AS THE POSITIVE ARGUMENT BEYOND WHICH + PSI MAY BE REPRESENTED AS ALOG(X). + XSMALL = ABSOLUTE ARGUMENT BELOW WHICH PI*COTAN(PI*X) + MAY BE REPRESENTED BY 1/X. +--------------------------------------------------------------------- +*/ + xmax1 = ipmpar(&K1); + xmax1 = fifdmin1(xmax1,1.0e0/spmpar(&K2)); + xsmall = 1.e-9; + x = *xx; + aug = 0.0e0; + if(x >= 0.5e0) goto S50; +/* +--------------------------------------------------------------------- + X .LT. 0.5, USE REFLECTION FORMULA + PSI(1-X) = PSI(X) + PI * COTAN(PI*X) +--------------------------------------------------------------------- +*/ + if(fabs(x) > xsmall) goto S10; + if(x == 0.0e0) goto S100; +/* +--------------------------------------------------------------------- + 0 .LT. ABS(X) .LE. XSMALL. USE 1/X AS A SUBSTITUTE + FOR PI*COTAN(PI*X) +--------------------------------------------------------------------- +*/ + aug = -(1.0e0/x); + goto S40; +S10: +/* +--------------------------------------------------------------------- + REDUCTION OF ARGUMENT FOR COTAN +--------------------------------------------------------------------- +*/ + w = -x; + sgn = piov4; + if(w > 0.0e0) goto S20; + w = -w; + sgn = -sgn; +S20: +/* +--------------------------------------------------------------------- + MAKE AN ERROR EXIT IF X .LE. -XMAX1 +--------------------------------------------------------------------- +*/ + if(w >= xmax1) goto S100; + nq = fifidint(w); + w -= (double)nq; + nq = fifidint(w*4.0e0); + w = 4.0e0*(w-(double)nq*.25e0); +/* +--------------------------------------------------------------------- + W IS NOW RELATED TO THE FRACTIONAL PART OF 4.0 * X. + ADJUST ARGUMENT TO CORRESPOND TO VALUES IN FIRST + QUADRANT AND DETERMINE SIGN +--------------------------------------------------------------------- +*/ + n = nq/2; + if(n+n != nq) w = 1.0e0-w; + z = piov4*w; + m = n/2; + if(m+m != n) sgn = -sgn; +/* +--------------------------------------------------------------------- + DETERMINE FINAL VALUE FOR -PI*COTAN(PI*X) +--------------------------------------------------------------------- +*/ + n = (nq+1)/2; + m = n/2; + m += m; + if(m != n) goto S30; +/* +--------------------------------------------------------------------- + CHECK FOR SINGULARITY +--------------------------------------------------------------------- +*/ + if(z == 0.0e0) goto S100; +/* +--------------------------------------------------------------------- + USE COS/SIN AS A SUBSTITUTE FOR COTAN, AND + SIN/COS AS A SUBSTITUTE FOR TAN +--------------------------------------------------------------------- +*/ + aug = sgn*(cos(z)/sin(z)*4.0e0); + goto S40; +S30: + aug = sgn*(sin(z)/cos(z)*4.0e0); +S40: + x = 1.0e0-x; +S50: + if(x > 3.0e0) goto S70; +/* +--------------------------------------------------------------------- + 0.5 .LE. X .LE. 3.0 +--------------------------------------------------------------------- +*/ + den = x; + upper = p1[0]*x; + for(i=1; i<=5; i++) { + den = (den+q1[i-1])*x; + upper = (upper+p1[i+1-1])*x; + } + den = (upper+p1[6])/(den+q1[5]); + xmx0 = x-dx0; + psi = den*xmx0+aug; + return psi; +S70: +/* +--------------------------------------------------------------------- + IF X .GE. XMAX1, PSI = LN(X) +--------------------------------------------------------------------- +*/ + if(x >= xmax1) goto S90; +/* +--------------------------------------------------------------------- + 3.0 .LT. X .LT. XMAX1 +--------------------------------------------------------------------- +*/ + w = 1.0e0/(x*x); + den = w; + upper = p2[0]*w; + for(i=1; i<=3; i++) { + den = (den+q2[i-1])*w; + upper = (upper+p2[i+1-1])*w; + } + aug = upper/(den+q2[3])-0.5e0/x+aug; +S90: + psi = aug+log(x); + return psi; +S100: +/* +--------------------------------------------------------------------- + ERROR RETURN +--------------------------------------------------------------------- +*/ + psi = 0.0e0; + return psi; +} /* END */ + +/***=====================================================================***/ +static double rcomp(double *a,double *x) +/* + ------------------- + EVALUATION OF EXP(-X)*X**A/GAMMA(A) + ------------------- + RT2PIN = 1/SQRT(2*PI) + ------------------- +*/ +{ +static double rt2pin = .398942280401433e0; +static double rcomp,t,t1,u; +/* + .. + .. Executable Statements .. +*/ + rcomp = 0.0e0; + if(*a >= 20.0e0) goto S20; + t = *a*log(*x)-*x; + if(*a >= 1.0e0) goto S10; + rcomp = *a*exp(t)*(1.0e0+gam1(a)); + return rcomp; +S10: + rcomp = exp(t)/Xgamm(a); + return rcomp; +S20: + u = *x/ *a; + if(u == 0.0e0) return rcomp; + t = pow(1.0e0/ *a,2.0); + t1 = (((0.75e0*t-1.0e0)*t+3.5e0)*t-105.0e0)/(*a*1260.0e0); + t1 -= (*a*rlog(&u)); + rcomp = rt2pin*sqrt(*a)*exp(t1); + return rcomp; +} /* END */ + +/***=====================================================================***/ +static double rexp(double *x) +/* +----------------------------------------------------------------------- + EVALUATION OF THE FUNCTION EXP(X) - 1 +----------------------------------------------------------------------- +*/ +{ +static double p1 = .914041914819518e-09; +static double p2 = .238082361044469e-01; +static double q1 = -.499999999085958e+00; +static double q2 = .107141568980644e+00; +static double q3 = -.119041179760821e-01; +static double q4 = .595130811860248e-03; +static double rexp,w; +/* + .. + .. Executable Statements .. +*/ + if(fabs(*x) > 0.15e0) goto S10; + rexp = *x*(((p2**x+p1)**x+1.0e0)/((((q4**x+q3)**x+q2)**x+q1)**x+1.0e0)); + return rexp; +S10: + w = exp(*x); + if(*x > 0.0e0) goto S20; + rexp = w-0.5e0-0.5e0; + return rexp; +S20: + rexp = w*(0.5e0+(0.5e0-1.0e0/w)); + return rexp; +} /* END */ + +/***=====================================================================***/ +static double rlog(double *x) +/* + ------------------- + COMPUTATION OF X - 1 - LN(X) + ------------------- +*/ +{ +static double a = .566749439387324e-01; +static double b = .456512608815524e-01; +static double p0 = .333333333333333e+00; +static double p1 = -.224696413112536e+00; +static double p2 = .620886815375787e-02; +static double q1 = -.127408923933623e+01; +static double q2 = .354508718369557e+00; +static double rlog,r,t,u,w,w1; +/* + .. + .. Executable Statements .. +*/ + if(*x < 0.61e0 || *x > 1.57e0) goto S40; + if(*x < 0.82e0) goto S10; + if(*x > 1.18e0) goto S20; +/* + ARGUMENT REDUCTION +*/ + u = *x-0.5e0-0.5e0; + w1 = 0.0e0; + goto S30; +S10: + u = *x-0.7e0; + u /= 0.7e0; + w1 = a-u*0.3e0; + goto S30; +S20: + u = 0.75e0**x-1.e0; + w1 = b+u/3.0e0; +S30: +/* + SERIES EXPANSION +*/ + r = u/(u+2.0e0); + t = r*r; + w = ((p2*t+p1)*t+p0)/((q2*t+q1)*t+1.0e0); + rlog = 2.0e0*t*(1.0e0/(1.0e0-r)-r*w)+w1; + return rlog; +S40: + r = *x-0.5e0-0.5e0; + rlog = r-log(*x); + return rlog; +} /* END */ + +/***=====================================================================***/ +static double rlog1(double *x) +/* +----------------------------------------------------------------------- + EVALUATION OF THE FUNCTION X - LN(1 + X) +----------------------------------------------------------------------- +*/ +{ +static double a = .566749439387324e-01; +static double b = .456512608815524e-01; +static double p0 = .333333333333333e+00; +static double p1 = -.224696413112536e+00; +static double p2 = .620886815375787e-02; +static double q1 = -.127408923933623e+01; +static double q2 = .354508718369557e+00; +static double rlog1,h,r,t,w,w1; +/* + .. + .. Executable Statements .. +*/ + if(*x < -0.39e0 || *x > 0.57e0) goto S40; + if(*x < -0.18e0) goto S10; + if(*x > 0.18e0) goto S20; +/* + ARGUMENT REDUCTION +*/ + h = *x; + w1 = 0.0e0; + goto S30; +S10: + h = *x+0.3e0; + h /= 0.7e0; + w1 = a-h*0.3e0; + goto S30; +S20: + h = 0.75e0**x-0.25e0; + w1 = b+h/3.0e0; +S30: +/* + SERIES EXPANSION +*/ + r = h/(h+2.0e0); + t = r*r; + w = ((p2*t+p1)*t+p0)/((q2*t+q1)*t+1.0e0); + rlog1 = 2.0e0*t*(1.0e0/(1.0e0-r)-r*w)+w1; + return rlog1; +S40: + w = *x+0.5e0+0.5e0; + rlog1 = *x-log(w); + return rlog1; +} /* END */ + +/***=====================================================================***/ +static double spmpar(int *i) +/* +----------------------------------------------------------------------- + + SPMPAR PROVIDES THE SINGLE PRECISION MACHINE CONSTANTS FOR + THE COMPUTER BEING USED. IT IS ASSUMED THAT THE ARGUMENT + I IS AN INTEGER HAVING ONE OF THE VALUES 1, 2, OR 3. IF THE + SINGLE PRECISION ARITHMETIC BEING USED HAS M BASE B DIGITS AND + ITS SMALLEST AND LARGEST EXPONENTS ARE EMIN AND EMAX, THEN + + SPMPAR(1) = B**(1 - M), THE MACHINE PRECISION, + + SPMPAR(2) = B**(EMIN - 1), THE SMALLEST MAGNITUDE, + + SPMPAR(3) = B**EMAX*(1 - B**(-M)), THE LARGEST MAGNITUDE. + +----------------------------------------------------------------------- + WRITTEN BY + ALFRED H. MORRIS, JR. + NAVAL SURFACE WARFARE CENTER + DAHLGREN VIRGINIA +----------------------------------------------------------------------- +----------------------------------------------------------------------- + MODIFIED BY BARRY W. BROWN TO RETURN DOUBLE PRECISION MACHINE + CONSTANTS FOR THE COMPUTER BEING USED. THIS MODIFICATION WAS + MADE AS PART OF CONVERTING BRATIO TO DOUBLE PRECISION +----------------------------------------------------------------------- +*/ +{ +static int K1 = 4; +static int K2 = 8; +static int K3 = 9; +static int K4 = 10; +static double spmpar,b,binv,bm1,one,w,z; +static int emax,emin,ibeta,m; +/* + .. + .. Executable Statements .. +*/ + if(*i > 1) goto S10; + b = ipmpar(&K1); + m = ipmpar(&K2); + spmpar = pow(b,(double)(1-m)); + return spmpar; +S10: + if(*i > 2) goto S20; + b = ipmpar(&K1); + emin = ipmpar(&K3); + one = 1.0; + binv = one/b; + w = pow(b,(double)(emin+2)); + spmpar = w*binv*binv*binv; + return spmpar; +S20: + ibeta = ipmpar(&K1); + m = ipmpar(&K2); + emax = ipmpar(&K4); + b = ibeta; + bm1 = ibeta-1; + one = 1.0; + z = pow(b,(double)(m-1)); + w = ((z-one)*b+bm1)/(b*z); + z = pow(b,(double)(emax-2)); + spmpar = w*z*b*b; + return spmpar; +} /* END */ + +/***=====================================================================***/ +static double stvaln(double *p) +/* +********************************************************************** + + double stvaln(double *p) + STarting VALue for Neton-Raphon + calculation of Normal distribution Inverse + + + Function + + + Returns X such that CUMNOR(X) = P, i.e., the integral from - + infinity to X of (1/SQRT(2*PI)) EXP(-U*U/2) dU is P + + + Arguments + + + P --> The probability whose normal deviate is sought. + P is DOUBLE PRECISION + + + Method + + + The rational function on page 95 of Kennedy and Gentle, + Statistical Computing, Marcel Dekker, NY , 1980. + +********************************************************************** +*/ +{ +static double xden[5] = { + 0.993484626060e-1,0.588581570495e0,0.531103462366e0,0.103537752850e0, + 0.38560700634e-2 +}; +static double xnum[5] = { + -0.322232431088e0,-1.000000000000e0,-0.342242088547e0,-0.204231210245e-1, + -0.453642210148e-4 +}; +static int K1 = 5; +static double stvaln,sign,y,z; +/* + .. + .. Executable Statements .. +*/ + if(!(*p <= 0.5e0)) goto S10; + sign = -1.0e0; + z = *p; + goto S20; +S10: + sign = 1.0e0; + z = 1.0e0-*p; +S20: + y = sqrt(-(2.0e0*log(z))); + stvaln = y+devlpl(xnum,&K1,&y)/devlpl(xden,&K1,&y); + stvaln = sign*stvaln; + return stvaln; +} /* END */ + +/***=====================================================================***/ +static double fifdint(double a) +/************************************************************************ +FIFDINT: +Truncates a double precision number to an integer and returns the +value in a double. +************************************************************************/ +/* a - number to be truncated */ +{ + return (double) ((int) a); +} /* END */ + +/***=====================================================================***/ +static double fifdmax1(double a,double b) +/************************************************************************ +FIFDMAX1: +returns the maximum of two numbers a and b +************************************************************************/ +/* a - first number */ +/* b - second number */ +{ + if (a < b) return b; + else return a; +} /* END */ + +/***=====================================================================***/ +static double fifdmin1(double a,double b) +/************************************************************************ +FIFDMIN1: +returns the minimum of two numbers a and b +************************************************************************/ +/* a - first number */ +/* b - second number */ +{ + if (a < b) return a; + else return b; +} /* END */ + +/***=====================================================================***/ +static double fifdsign(double mag,double sign) +/************************************************************************ +FIFDSIGN: +transfers the sign of the variable "sign" to the variable "mag" +************************************************************************/ +/* mag - magnitude */ +/* sign - sign to be transfered */ +{ + if (mag < 0) mag = -mag; + if (sign < 0) mag = -mag; + return mag; + +} /* END */ + +/***=====================================================================***/ +static long fifidint(double a) +/************************************************************************ +FIFIDINT: +Truncates a double precision number to a long integer +************************************************************************/ +/* a - number to be truncated */ +{ + if (a < 1.0) return (long) 0; + else return (long) a; +} /* END */ + +/***=====================================================================***/ +static long fifmod(long a,long b) +/************************************************************************ +FIFMOD: +returns the modulo of a and b +************************************************************************/ +/* a - numerator */ +/* b - denominator */ +{ + return a % b; +} /* END */ + +/***=====================================================================***/ +static void ftnstop(char* msg) +/************************************************************************ +FTNSTOP: +Prints msg to standard error and then exits +************************************************************************/ +/* msg - error message */ +{ + if (msg != NULL) fprintf(stderr,"*** CDFLIB ERROR: %s\n",msg); + /** exit(1); **/ /** RWCox - DON'T EXIT */ +} /* END */ + +/***=====================================================================***/ +static int ipmpar(int *i) +/* +----------------------------------------------------------------------- + + IPMPAR PROVIDES THE INTEGER MACHINE CONSTANTS FOR THE COMPUTER + THAT IS USED. IT IS ASSUMED THAT THE ARGUMENT I IS AN INTEGER + HAVING ONE OF THE VALUES 1-10. IPMPAR(I) HAS THE VALUE ... + + INTEGERS. + + ASSUME INTEGERS ARE REPRESENTED IN THE N-DIGIT, BASE-A FORM + + SIGN ( X(N-1)*A**(N-1) + ... + X(1)*A + X(0) ) + + WHERE 0 .LE. X(I) .LT. A FOR I=0,...,N-1. + + IPMPAR(1) = A, THE BASE. + + IPMPAR(2) = N, THE NUMBER OF BASE-A DIGITS. + + IPMPAR(3) = A**N - 1, THE LARGEST MAGNITUDE. + + FLOATING-POINT NUMBERS. + + IT IS ASSUMED THAT THE SINGLE AND DOUBLE PRECISION FLOATING + POINT ARITHMETICS HAVE THE SAME BASE, SAY B, AND THAT THE + NONZERO NUMBERS ARE REPRESENTED IN THE FORM + + SIGN (B**E) * (X(1)/B + ... + X(M)/B**M) + + WHERE X(I) = 0,1,...,B-1 FOR I=1,...,M, + X(1) .GE. 1, AND EMIN .LE. E .LE. EMAX. + + IPMPAR(4) = B, THE BASE. + + SINGLE-PRECISION + + IPMPAR(5) = M, THE NUMBER OF BASE-B DIGITS. + + IPMPAR(6) = EMIN, THE SMALLEST EXPONENT E. + + IPMPAR(7) = EMAX, THE LARGEST EXPONENT E. + + DOUBLE-PRECISION + + IPMPAR(8) = M, THE NUMBER OF BASE-B DIGITS. + + IPMPAR(9) = EMIN, THE SMALLEST EXPONENT E. + + IPMPAR(10) = EMAX, THE LARGEST EXPONENT E. + +----------------------------------------------------------------------- + + TO DEFINE THIS FUNCTION FOR THE COMPUTER BEING USED REMOVE + THE COMMENT DELIMITORS FROM THE DEFINITIONS DIRECTLY BELOW THE NAME + OF THE MACHINE + +*** RWCox: at this time, the IEEE parameters are enabled. + +----------------------------------------------------------------------- + + IPMPAR IS AN ADAPTATION OF THE FUNCTION I1MACH, WRITTEN BY + P.A. FOX, A.D. HALL, AND N.L. SCHRYER (BELL LABORATORIES). + IPMPAR WAS FORMED BY A.H. MORRIS (NSWC). THE CONSTANTS ARE + FROM BELL LABORATORIES, NSWC, AND OTHER SOURCES. + +----------------------------------------------------------------------- + .. Scalar Arguments .. +*/ +{ +static int imach[11]; +static int outval ; +/* MACHINE CONSTANTS FOR AMDAHL MACHINES. */ +/* + imach[1] = 2; + imach[2] = 31; + imach[3] = 2147483647; + imach[4] = 16; + imach[5] = 6; + imach[6] = -64; + imach[7] = 63; + imach[8] = 14; + imach[9] = -64; + imach[10] = 63; +*/ +/* MACHINE CONSTANTS FOR THE AT&T 3B SERIES, AT&T + PC 7300, AND AT&T 6300. */ +/* + imach[1] = 2; + imach[2] = 31; + imach[3] = 2147483647; + imach[4] = 2; + imach[5] = 24; + imach[6] = -125; + imach[7] = 128; + imach[8] = 53; + imach[9] = -1021; + imach[10] = 1024; +*/ +/* MACHINE CONSTANTS FOR THE BURROUGHS 1700 SYSTEM. */ +/* + imach[1] = 2; + imach[2] = 33; + imach[3] = 8589934591; + imach[4] = 2; + imach[5] = 24; + imach[6] = -256; + imach[7] = 255; + imach[8] = 60; + imach[9] = -256; + imach[10] = 255; +*/ +/* MACHINE CONSTANTS FOR THE BURROUGHS 5700 SYSTEM. */ +/* + imach[1] = 2; + imach[2] = 39; + imach[3] = 549755813887; + imach[4] = 8; + imach[5] = 13; + imach[6] = -50; + imach[7] = 76; + imach[8] = 26; + imach[9] = -50; + imach[10] = 76; +*/ +/* MACHINE CONSTANTS FOR THE BURROUGHS 6700/7700 SYSTEMS. */ +/* + imach[1] = 2; + imach[2] = 39; + imach[3] = 549755813887; + imach[4] = 8; + imach[5] = 13; + imach[6] = -50; + imach[7] = 76; + imach[8] = 26; + imach[9] = -32754; + imach[10] = 32780; +*/ +/* MACHINE CONSTANTS FOR THE CDC 6000/7000 SERIES + 60 BIT ARITHMETIC, AND THE CDC CYBER 995 64 BIT + ARITHMETIC (NOS OPERATING SYSTEM). */ +/* + imach[1] = 2; + imach[2] = 48; + imach[3] = 281474976710655; + imach[4] = 2; + imach[5] = 48; + imach[6] = -974; + imach[7] = 1070; + imach[8] = 95; + imach[9] = -926; + imach[10] = 1070; +*/ +/* MACHINE CONSTANTS FOR THE CDC CYBER 995 64 BIT + ARITHMETIC (NOS/VE OPERATING SYSTEM). */ +/* + imach[1] = 2; + imach[2] = 63; + imach[3] = 9223372036854775807; + imach[4] = 2; + imach[5] = 48; + imach[6] = -4096; + imach[7] = 4095; + imach[8] = 96; + imach[9] = -4096; + imach[10] = 4095; +*/ +/* MACHINE CONSTANTS FOR THE CRAY 1, XMP, 2, AND 3. */ +/* + imach[1] = 2; + imach[2] = 63; + imach[3] = 9223372036854775807; + imach[4] = 2; + imach[5] = 47; + imach[6] = -8189; + imach[7] = 8190; + imach[8] = 94; + imach[9] = -8099; + imach[10] = 8190; +*/ +/* MACHINE CONSTANTS FOR THE DATA GENERAL ECLIPSE S/200. */ +/* + imach[1] = 2; + imach[2] = 15; + imach[3] = 32767; + imach[4] = 16; + imach[5] = 6; + imach[6] = -64; + imach[7] = 63; + imach[8] = 14; + imach[9] = -64; + imach[10] = 63; +*/ +/* MACHINE CONSTANTS FOR THE HARRIS 220. */ +/* + imach[1] = 2; + imach[2] = 23; + imach[3] = 8388607; + imach[4] = 2; + imach[5] = 23; + imach[6] = -127; + imach[7] = 127; + imach[8] = 38; + imach[9] = -127; + imach[10] = 127; +*/ +/* MACHINE CONSTANTS FOR THE HONEYWELL 600/6000 + AND DPS 8/70 SERIES. */ +/* + imach[1] = 2; + imach[2] = 35; + imach[3] = 34359738367; + imach[4] = 2; + imach[5] = 27; + imach[6] = -127; + imach[7] = 127; + imach[8] = 63; + imach[9] = -127; + imach[10] = 127; +*/ +/* MACHINE CONSTANTS FOR THE HP 2100 + 3 WORD DOUBLE PRECISION OPTION WITH FTN4 */ +/* + imach[1] = 2; + imach[2] = 15; + imach[3] = 32767; + imach[4] = 2; + imach[5] = 23; + imach[6] = -128; + imach[7] = 127; + imach[8] = 39; + imach[9] = -128; + imach[10] = 127; +*/ +/* MACHINE CONSTANTS FOR THE HP 2100 + 4 WORD DOUBLE PRECISION OPTION WITH FTN4 */ +/* + imach[1] = 2; + imach[2] = 15; + imach[3] = 32767; + imach[4] = 2; + imach[5] = 23; + imach[6] = -128; + imach[7] = 127; + imach[8] = 55; + imach[9] = -128; + imach[10] = 127; +*/ +/* MACHINE CONSTANTS FOR THE HP 9000. */ +/* + imach[1] = 2; + imach[2] = 31; + imach[3] = 2147483647; + imach[4] = 2; + imach[5] = 24; + imach[6] = -126; + imach[7] = 128; + imach[8] = 53; + imach[9] = -1021; + imach[10] = 1024; +*/ +/* MACHINE CONSTANTS FOR THE IBM 360/370 SERIES, + THE ICL 2900, THE ITEL AS/6, THE XEROX SIGMA + 5/7/9 AND THE SEL SYSTEMS 85/86. */ +/* + imach[1] = 2; + imach[2] = 31; + imach[3] = 2147483647; + imach[4] = 16; + imach[5] = 6; + imach[6] = -64; + imach[7] = 63; + imach[8] = 14; + imach[9] = -64; + imach[10] = 63; +*/ +/* MACHINE CONSTANTS FOR THE IBM PC. */ +/* + imach[1] = 2; + imach[2] = 31; + imach[3] = 2147483647; + imach[4] = 2; + imach[5] = 24; + imach[6] = -125; + imach[7] = 128; + imach[8] = 53; + imach[9] = -1021; + imach[10] = 1024; +*/ +/* MACHINE CONSTANTS FOR THE MACINTOSH II - ABSOFT + MACFORTRAN II. */ +/* + imach[1] = 2; + imach[2] = 31; + imach[3] = 2147483647; + imach[4] = 2; + imach[5] = 24; + imach[6] = -125; + imach[7] = 128; + imach[8] = 53; + imach[9] = -1021; + imach[10] = 1024; +*/ +/* MACHINE CONSTANTS FOR THE MICROVAX - VMS FORTRAN. */ +/* + imach[1] = 2; + imach[2] = 31; + imach[3] = 2147483647; + imach[4] = 2; + imach[5] = 24; + imach[6] = -127; + imach[7] = 127; + imach[8] = 56; + imach[9] = -127; + imach[10] = 127; +*/ +/* MACHINE CONSTANTS FOR THE PDP-10 (KA PROCESSOR). */ +/* + imach[1] = 2; + imach[2] = 35; + imach[3] = 34359738367; + imach[4] = 2; + imach[5] = 27; + imach[6] = -128; + imach[7] = 127; + imach[8] = 54; + imach[9] = -101; + imach[10] = 127; +*/ +/* MACHINE CONSTANTS FOR THE PDP-10 (KI PROCESSOR). */ +/* + imach[1] = 2; + imach[2] = 35; + imach[3] = 34359738367; + imach[4] = 2; + imach[5] = 27; + imach[6] = -128; + imach[7] = 127; + imach[8] = 62; + imach[9] = -128; + imach[10] = 127; +*/ +/* MACHINE CONSTANTS FOR THE PDP-11 FORTRAN SUPPORTING + 32-BIT INTEGER ARITHMETIC. */ +/* + imach[1] = 2; + imach[2] = 31; + imach[3] = 2147483647; + imach[4] = 2; + imach[5] = 24; + imach[6] = -127; + imach[7] = 127; + imach[8] = 56; + imach[9] = -127; + imach[10] = 127; +*/ +/* MACHINE CONSTANTS FOR THE SEQUENT BALANCE 8000. */ +/* + imach[1] = 2; + imach[2] = 31; + imach[3] = 2147483647; + imach[4] = 2; + imach[5] = 24; + imach[6] = -125; + imach[7] = 128; + imach[8] = 53; + imach[9] = -1021; + imach[10] = 1024; +*/ +/* MACHINE CONSTANTS FOR THE SILICON GRAPHICS IRIS-4D + SERIES (MIPS R3000 PROCESSOR). */ +/* + imach[1] = 2; + imach[2] = 31; + imach[3] = 2147483647; + imach[4] = 2; + imach[5] = 24; + imach[6] = -125; + imach[7] = 128; + imach[8] = 53; + imach[9] = -1021; + imach[10] = 1024; +*/ +/* MACHINE CONSTANTS FOR IEEE ARITHMETIC MACHINES, SUCH AS THE AT&T + 3B SERIES, MOTOROLA 68000 BASED MACHINES (E.G. SUN 3 AND AT&T + PC 7300), AND 8087 BASED MICROS (E.G. IBM PC AND AT&T 6300). */ + + imach[1] = 2; + imach[2] = 31; + imach[3] = 2147483647; + imach[4] = 2; + imach[5] = 24; + imach[6] = -125; + imach[7] = 128; + imach[8] = 53; + imach[9] = -1021; + imach[10] = 1024; + +/* MACHINE CONSTANTS FOR THE UNIVAC 1100 SERIES. */ +/* + imach[1] = 2; + imach[2] = 35; + imach[3] = 34359738367; + imach[4] = 2; + imach[5] = 27; + imach[6] = -128; + imach[7] = 127; + imach[8] = 60; + imach[9] = -1024; + imach[10] = 1023; +*/ +/* MACHINE CONSTANTS FOR THE VAX 11/780. */ +/* + imach[1] = 2; + imach[2] = 31; + imach[3] = 2147483647; + imach[4] = 2; + imach[5] = 24; + imach[6] = -127; + imach[7] = 127; + imach[8] = 56; + imach[9] = -127; + imach[10] = 127; +*/ + outval = imach[*i]; + return outval ; +} + +/*************************************************************************/ +/*************************************************************************/ +/************************ End of cdflib inclusion ************************/ +/*************************************************************************/ +/*************************************************************************/ + +/*-----------------------------------------------------------------------*/ +typedef struct { double p,q ; } pqpair ; /* for returning p=cdf q=1-cdf */ +/*-----------------------------------------------------------------------*/ +#undef BIGG +#define BIGG 9.99e+37 /* a really big number (duh) */ +/*-----------------------------------------------------------------------*/ + +/*************************************************************************/ +/******** Internal functions for various statistical computations ********/ +/*************************************************************************/ + +/*--------------------------------------------------------------- + F statistic +-----------------------------------------------------------------*/ + +static double fstat_pq2s( pqpair pq , double dofnum , double dofden ) +{ + int which , status ; + double p , q , f , dfn , dfd , bound ; + + which = 2 ; + p = pq.p ; if( p <= 0.0 ) return 0.0 ; + q = pq.q ; if( q <= 0.0 ) return BIGG ; + f = 0.0 ; + dfn = dofnum ; + dfd = dofden ; + + cdff( &which , &p , &q , &f , &dfn , &dfd , &status , &bound ) ; + return f ; +} + +/*------------------------------*/ + +static pqpair fstat_s2pq( double ff , double dofnum , double dofden ) +{ + int which , status ; + double p , q , f , dfn , dfd , bound ; + pqpair pq={0.0,1.0} ; + + which = 1 ; + p = 0.0 ; + q = 1.0 ; + f = ff ; if( f <= 0.0 ) return pq; + dfn = dofnum ; if( dfn <= 0.0 ) return pq ; + dfd = dofden ; if( dfd <= 0.0 ) return pq ; + + cdff( &which , &p , &q , &f , &dfn , &dfd , &status , &bound ) ; + pq.p = p ; pq.q = q ; return pq ; +} + +/*--------------------------------------------------------------- + noncentral F statistic +-----------------------------------------------------------------*/ + +static double fnonc_pq2s( pqpair pq , double dofnum , double dofden , double nonc ) +{ + int which , status ; + double p , q , f , dfn , dfd , bound , pnonc ; + + which = 2 ; + p = pq.p ; if( p <= 0.0 ) return 0.0 ; + q = pq.q ; if( q <= 0.0 ) return BIGG ; + f = 0.0 ; + dfn = dofnum ; + dfd = dofden ; + pnonc = nonc ; + + cdffnc( &which , &p , &q , &f , &dfn , &dfd , &pnonc , &status , &bound ) ; + return f ; +} + +/*------------------------------*/ + +static pqpair fnonc_s2pq( double ff , double dofnum , double dofden , double nonc ) +{ + int which , status ; + double p , q , f , dfn , dfd , bound , pnonc ; + pqpair pq={0.0,1.0} ; + + which = 1 ; + p = 0.0 ; + q = 1.0 ; + f = ff ; if( f <= 0.0 ) return pq ; + dfn = dofnum ; if( dfn <= 0.0 ) return pq ; + dfd = dofden ; if( dfd <= 0.0 ) return pq ; + pnonc = nonc ; if( pnonc < 0.0 ) return pq ; + + cdffnc( &which , &p , &q , &f , &dfn , &dfd , &pnonc , &status , &bound ) ; + pq.p = p ; pq.q = q ; return pq ; +} + +/*--------------------------------------------------------------- + Standard Normal distribution +-----------------------------------------------------------------*/ + +static pqpair normal_s2pq( double zz ) +{ + double p , q , x=zz ; + pqpair pq ; + + cumnor( &x, &p, &q ) ; + pq.p = p ; pq.q = q ; return pq ; +} + +/*------------------------------*/ + +static double normal_pq2s( pqpair pq ) +{ + double p=pq.p , q=pq.q ; + + if( p <= 0.0 ) return -BIGG ; + if( q <= 0.0 ) return BIGG ; + return dinvnr( &p,&q ) ; +} + +/*---------------------------------------------------------------- + Chi-square +------------------------------------------------------------------*/ + +static pqpair chisq_s2pq( double xx , double dof ) +{ + int which , status ; + double p,q,x,df,bound ; + pqpair pq={0.0,1.0} ; + + which = 1 ; + p = 0.0 ; + q = 1.0 ; + x = xx ; if( x <= 0.0 ) return pq ; + df = dof ; if( dof <= 0.0 ) return pq ; + + cdfchi( &which , &p , &q , &x , &df , &status , &bound ) ; + pq.p = p ; pq.q = q ; return pq ; +} + +/*------------------------------*/ + +static double chisq_pq2s( pqpair pq , double dof ) +{ + int which , status ; + double p,q,x,df,bound ; + + which = 2 ; + p = pq.p ; if( p <= 0.0 ) return 0.0 ; + q = pq.q ; if( q <= 0.0 ) return BIGG ; + x = 0.0 ; + df = dof ; + + cdfchi( &which , &p , &q , &x , &df , &status , &bound ) ; + return x ; +} + +/*---------------------------------------------------------------- + noncentral Chi-square +------------------------------------------------------------------*/ + +static pqpair chsqnonc_s2pq( double xx , double dof , double nonc ) +{ + int which , status ; + double p,q,x,df,bound , pnonc ; + pqpair pq={0.0,1.0} ; + + which = 1 ; + p = 0.0 ; + q = 1.0 ; + x = xx ; if( x <= 0.0 ) return pq ; + df = dof ; if( df <= 0.0 ) return pq ; + pnonc = nonc ; if( pnonc < 0.0 ) return pq ; + + cdfchn( &which , &p , &q , &x , &df , &pnonc , &status , &bound ) ; + pq.p = p ; pq.q = q ; return pq ; +} + +/*------------------------------*/ + +static double chsqnonc_pq2s( pqpair pq , double dof , double nonc ) +{ + int which , status ; + double p,q,x,df,bound , pnonc ; + + which = 2 ; + p = pq.p ; if( p <= 0.0 ) return 0.0 ; + q = pq.q ; if( q <= 0.0 ) return BIGG ; + x = 0.0 ; + df = dof ; + pnonc = nonc ; + + cdfchn( &which , &p , &q , &x , &df , &pnonc , &status , &bound ) ; + return x ; +} + +/*---------------------------------------------------------------- + Beta distribution +------------------------------------------------------------------*/ + +static pqpair beta_s2pq( double xx , double aa , double bb ) +{ + int which , status ; + double p,q,x,y,a,b,bound ; + pqpair pq={0.0,1.0} ; + + which = 1 ; + p = 0.0 ; + q = 1.0 ; + x = xx ; if( x <= 0.0 ) return pq ; + y = 1.0 - xx ; if( y <= 0.0 ){ pq.p=1.0; pq.q=0.0; return pq; } + a = aa ; if( a < 0.0 ) return pq ; + b = bb ; if( b < 0.0 ) return pq ; + + cdfbet( &which , &p , &q , &x , &y , &a , &b , &status , &bound ) ; + pq.p = p ; pq.q = q ; return pq ; +} + +/*------------------------------*/ + +static double beta_pq2s( pqpair pq , double aa , double bb ) +{ + int which , status ; + double p,q,x,y,a,b,bound ; + + which = 2 ; + p = pq.p ; if( p <= 0.0 ) return 0.0 ; + q = pq.q ; if( q <= 0.0 ) return 1.0 ; + x = 0.0 ; + y = 1.0 ; + a = aa ; + b = bb ; + + cdfbet( &which , &p , &q , &x , &y , &a , &b , &status , &bound ) ; + return x ; +} + +/*---------------------------------------------------------------- + Binomial distribution + (that is, the probability that more than ss out of ntrial + trials were successful). +------------------------------------------------------------------*/ + +static pqpair binomial_s2pq( double ss , double ntrial , double ptrial ) +{ + int which , status ; + double p,q, s,xn,pr,ompr,bound ; + pqpair pq={0.0,1.0} ; + + which = 1 ; + p = 0.0 ; + q = 1.0 ; + s = ss ; if( s < 0.0 ) return pq ; + xn = ntrial ; if( xn <= 0.0 ) return pq ; + pr = ptrial ; if( pr < 0.0 ) return pq ; + ompr = 1.0 - ptrial ; + + cdfbin( &which , &p , &q , &s , &xn , &pr , &ompr , &status , &bound ) ; + pq.p = p ; pq.q = q ; return pq ; +} + +/*------------------------------*/ + +static double binomial_pq2s( pqpair pq , double ntrial , double ptrial ) +{ + int which , status ; + double p,q, s,xn,pr,ompr,bound ; + + which = 2 ; + p = pq.p ; + q = pq.q ; + s = 0.0 ; + xn = ntrial ; + pr = ptrial ; + ompr = 1.0 - ptrial ; + + cdfbin( &which , &p , &q , &s , &xn , &pr , &ompr , &status , &bound ) ; + return s ; +} + +/*---------------------------------------------------------------- + Gamma distribution. +------------------------------------------------------------------*/ + +static pqpair gamma_s2pq( double xx , double sh , double sc ) +{ + int which , status ; + double p,q, x,shape,scale,bound ; + pqpair pq={0.0,1.0} ; + + which = 1 ; + p = 0.0 ; + q = 1.0 ; + x = xx ; if( x <= 0.0 ) return pq ; + shape = sh ; if( shape <= 0.0 ) return pq ; + scale = sc ; if( scale <= 0.0 ) return pq ; + + cdfgam( &which , &p , &q , &x , &shape , &scale , &status , &bound ) ; + pq.p = p ; pq.q = q ; return pq ; +} + +/*------------------------------*/ + +static double gamma_pq2s( pqpair pq , double sh , double sc ) +{ + int which , status ; + double p,q, x,shape,scale,bound ; + + which = 2 ; + p = pq.p ; if( p <= 0.0 ) return 0.0 ; + q = pq.q ; if( q <= 0.0 ) return BIGG ; + x = 0.0 ; + shape = sh ; + scale = sc ; + + cdfgam( &which , &p , &q , &x , &shape , &scale , &status , &bound ) ; + return x ; +} + +/*---------------------------------------------------------------- + Poisson distribution +------------------------------------------------------------------*/ + +static pqpair poisson_s2pq( double xx , double lambda ) +{ + int which , status ; + double p,q, s,xlam,bound ; + pqpair pq={0.0,1.0} ; + + which = 1 ; + p = 0.0 ; + q = 1.0 ; + s = xx ; if( s < 0.0 ) return pq ; + xlam = lambda ; if( xlam < 0.0 ) return pq ; + + cdfpoi( &which , &p , &q , &s , &xlam , &status , &bound ) ; + pq.p = p ; pq.q = q ; return pq ; +} + +/*------------------------------*/ + +static double poisson_pq2s( pqpair pq , double lambda ) +{ + int which , status ; + double p,q, s,xlam,bound ; + + which = 2 ; + p = pq.p ; + q = pq.q ; + s = 0.0 ; + xlam = lambda ; + + cdfpoi( &which , &p , &q , &s , &xlam , &status , &bound ) ; + return s ; +} + +/*---------------------------------------------------------------- + T distribution. +------------------------------------------------------------------*/ + +static pqpair student_s2pq( double xx , double dof ) +{ + int which , status ; + double p,q, s,xlam,bound ; + pqpair pq={0.0,1.0} ; + + which = 1 ; + p = 0.0 ; + q = 1.0 ; + s = xx ; + xlam = dof ; if( xlam <= 0.0 ) return pq ; + + cdft( &which , &p , &q , &s , &xlam , &status , &bound ) ; + pq.p = p ; pq.q = q ; return pq ; +} + +/*------------------------------*/ + +double student_pq2s( pqpair pq , double dof ) +{ + int which , status ; + double p,q, s,xlam,bound ; + + which = 2 ; + p = pq.p ; + q = pq.q ; + s = 0.0 ; + xlam = dof ; + + cdft( &which , &p , &q , &s , &xlam , &status , &bound ) ; + return s ; +} + +/****************************************************************************/ +/* For the distributions below here, cdflib can't do what we want directly. */ +/****************************************************************************/ + +/*---------------------------------------------------------------- + Null correlation distribution. + Let x = (rr+1)/2; then x is Beta(dof/2,dof/2). +------------------------------------------------------------------*/ + +static pqpair correl_s2pq( double rr , double dof ) /* fake it with cdflib */ +{ + return beta_s2pq( 0.5*(rr+1.0) , 0.5*dof , 0.5*dof ) ; +} + +/*------------------------------*/ + +static double correl_pq2s( pqpair pq , double dof ) +{ + double xx = beta_pq2s( pq , 0.5*dof , 0.5*dof ) ; + return (2.0*xx-1.0) ; +} + +/*---------------------------------------------------------------- + Uniform U(0,1) distribution. +------------------------------------------------------------------*/ + +static pqpair uniform_s2pq( double xx ) /* this isn't too hard */ +{ + pqpair pq ; + if( xx <= 0.0 ) pq.p = 0.0 ; + else if( xx >= 1.0 ) pq.p = 1.0 ; + else pq.p = xx ; + pq.q = 1.0-xx ; return pq ; +} + +/*------------------------------*/ + +static double uniform_pq2s( pqpair pq ) +{ + return pq.p ; /* that was easy */ +} + +/*---------------------------------------------------------------- + standard Logistic distribution. +------------------------------------------------------------------*/ + +static pqpair logistic_s2pq( double xx ) /* this isn't hard, either */ +{ + pqpair pq ; + if( xx >= 0.0 ){ pq.q = 1.0/(1.0+exp( xx)); pq.p = 1.0-pq.q; } + else { pq.p = 1.0/(1.0+exp(-xx)); pq.q = 1.0-pq.p; } + return pq ; +} + +/*------------------------------*/ + +static double logistic_pq2s( pqpair pq ) +{ + if( pq.p <= 0.0 ) return -BIGG ; + else if( pq.q <= 0.0 ) return BIGG ; + + if( pq.p < pq.q ) return -log(1.0/pq.p-1.0) ; + else return log(1.0/pq.q-1.0) ; +} + +/*---------------------------------------------------------------- + standard Laplace distribution. +------------------------------------------------------------------*/ + +static pqpair laplace_s2pq( double xx ) /* easy */ +{ + pqpair pq ; + + if( xx >= 0.0 ){ pq.q = 0.5*exp(-xx) ; pq.p = 1.0-pq.q ; } + else { pq.p = 0.5*exp( xx) ; pq.q = 1.0-pq.p ; } + return pq ; +} + +/*------------------------------*/ + +static double laplace_pq2s( pqpair pq ) +{ + if( pq.p <= 0.0 ) return -BIGG ; + else if( pq.q <= 0.0 ) return BIGG ; + + if( pq.p < pq.q ) return log(2.0*pq.p) ; + else return -log(2.0*pq.q) ; +} + +/*---------------------------------------------------------------- + noncentral T distribution = hard calculation +------------------------------------------------------------------*/ + +/**************************************************************************** + Noncentral t distribution function by + Professor K. Krishnamoorthy + Department of Mathematics + University of Louisiana at Lafayette + Manually translated from Fortran by RWC. +*****************************************************************************/ + +#if 0 +static double alng( double x ) /* log(Gamma(x)) from K */ +{ + int indx ; + double xx,fterm,sum,valg ; + double b[9] = { 0.0 , + 8.33333333333333e-2, 3.33333333333333e-2, + 2.52380952380952e-1, 5.25606469002695e-1, + 1.01152306812684e0, 1.51747364915329e0, + 2.26948897420496e0, 3.00991738325940e0 } ; + + if( x < 8.0 ){ xx = x + 8.0 ; indx = 1 ; } + else { xx = x ; indx = 0 ; } + + fterm = (xx-0.5)*log(xx) - xx + 9.1893853320467e-1 ; + sum = b[1]/(xx+b[2]/(xx+b[3]/(xx+b[4]/(xx+b[5]/(xx+b[6]/ + (xx+b[7]/(xx+b[8]))))))) ; + valg = sum + fterm ; + if(indx) + valg = valg-log(x+7.0)-log(x+6.0)-log(x+5.0) + -log(x+4.0)-log(x+3.0)-log(x+2.0)-log(x+1.0)-log(x) ; + return valg ; +} +#else +static double alng( double x ) /*-- replace with cdflib function --*/ +{ + double xx=x ; return alngam( &xx ) ; +} +#endif + +/*---------------------------------------------------------------------------*/ + +#if 0 +static double gaudf( double x ) /* N(0,1) cdf from K */ +{ + static double p0=913.16744211475570 , p1=1024.60809538333800, + p2=580.109897562908800, p3=202.102090717023000, + p4=46.0649519338751400, p5=6.81311678753268400, + p6=6.047379926867041e-1,p7=2.493381293151434e-2 ; + static double q0=1826.33488422951125, q1=3506.420597749092, + q2=3044.77121163622200, q3=1566.104625828454, + q4=523.596091947383490, q5=116.9795245776655, + q6=17.1406995062577800, q7=1.515843318555982, + q8=6.25e-2 ; + static double sqr2pi=2.506628274631001 ; + int check ; + double reslt,z , first,phi ; + + if(x > 0.0){ z = x ; check = 1 ; } + else { z =-x ; check = 0 ; } + + if( z > 32.0 ) return (x > 0.0) ? 1.0 : 0.0 ; + + first = exp(-0.5*z*z) ; + phi = first/sqr2pi ; + + if (z < 7.0) + reslt = first* (((((((p7*z+p6)*z+p5)*z+p4)*z+p3)*z+p2)*z+p1)*z+p0) + /((((((((q8*z+q7)*z+q6)*z+q5)*z+q4)*z+q3)*z+q2)*z+q1)*z+q0); + else + reslt = phi/(z+1.0/(z+2.0/(z+3.0/(z+4.0/(z+6.0/(z+7.0)))))) ; + + if(check) reslt = 1.0 - reslt ; + return reslt ; +} +#else +static double gaudf( double x ) /*-- replace with cdflib func --*/ +{ + double xx=x , p,q ; + cumnor( &xx, &p, &q ); return p; +} +#endif + +/*---------------------------------------------------------------------------*/ + +#if 0 +static double betadf( double x , double p , double q ) /* Beta cdf from K */ +{ + int check , ns ; + double result,betf,psq,xx,cx,pp,qq ; + double term,ai,rx,temp ; + + if( x >= 1.0 ) return 1.0 ; + if( x <= 0.0 ) return 0.0 ; + + betf = alng(p)+alng(q)-alng(p+q) ; + result=x ; + psq=p+q ; + cx=1.0-x ; + if(p < psq*x){ xx=cx ; cx=x ; pp=q ; qq=p ; check=1 ; } + else { xx=x ; pp=p ; qq=q ; check=0 ; } + + term=1.0 ; + ai=1.0 ; + result=1.0 ; + ns=(int)(qq+cx*psq) ; + rx=xx/cx ; +L3: + temp=qq-ai ; + if(ns == 0) rx=xx ; +L4: + term=term*temp*rx/(pp+ai) ; + result=result+term ; + temp=fabs(term) ; + if(temp <= 1.e-14 && temp <= 1.e-14*result) goto L5 ; + ai=ai+1.0 ; + ns=ns-1 ; + if(ns >= 0) goto L3 ; + temp=psq ; + psq=psq+1.0 ; + goto L4 ; + +L5: + result=result*exp(pp*log(xx)+(qq-1.0)*log(cx)-betf)/pp ; + if(check) result=1.0-result ; + return result ; +} +#else +static double betadf( double x , double p , double q ) /*-- cdflib func --*/ +{ + double xx=x,yy=1.0-x , aa=p,bb=q , pp,qq ; + cumbet( &xx,&yy , &aa,&bb , &pp,&qq ) ; return pp ; +} +#endif + +/*---------------------------------------------------------------------------*/ +/* Krishnamoorthy's function for cdf of noncentral t, for df > 0, + translated into C by RW Cox [Mar 2004]. + Note the original fails for delta=0, so we call the cdflib func for this. + A couple of other minor fixes are also included. +-----------------------------------------------------------------------------*/ + +static pqpair tnonc_s2pq( double t , double df , double delta ) +{ + int indx , k , i ; + double x,del,tnd,ans,y,dels,a,b,c ; + double pkf,pkb,qkf,qkb , pgamf,pgamb,qgamf,qgamb ; + double pbetaf,pbetab,qbetaf,qbetab ; + double ptermf,qtermf,ptermb,qtermb,term ; + double rempois,delosq2,sum,cons,error ; + + pqpair pq={0.0,1.0} ; /* will be return value */ + double ab1 ; + + /*-- stupid user? --*/ + + if( df <= 0.0 ) return pq ; + + /*-- non-centrality = 0? --*/ + + if( fabs(delta) < 1.e-8 ) return student_s2pq(t,df) ; + + /*-- start K's code here --*/ + + if( t < 0.0 ){ x = -t ; del = -delta ; indx = 1 ; } /* x will be */ + else { x = t ; del = delta ; indx = 0 ; } /* positive */ + + ans = gaudf(-del) ; /* prob that x <= 0 = Normal cdf */ + + /*-- the nearly trivial case of x=0 --*/ + + if( x == 0.0 ){ pq.p = ans; pq.q = 1.0-ans; return pq; } + + if( df == 1.0 ) df = 1.0000001 ; /** df=1 is BAD **/ + + y = x*x/(df+x*x) ; /* between 0 and 1 */ + dels = 0.5*del*del ; /* will be positive */ + k = (int)dels ; /* 0, 1, 2, ... */ + a = k+0.5 ; /* might be as small as 0.5 */ + c = k+1.0 ; + b = 0.5*df ; /* might be as small as 0.0 */ + + pkf = exp(-dels+k*log(dels)-alng(k+1.0)) ; + pkb = pkf ; + qkf = exp(-dels+k*log(dels)-alng(k+1.0+0.5)) ; + qkb = qkf ; + + pbetaf = betadf(y, a, b) ; + pbetab = pbetaf ; + qbetaf = betadf(y, c, b) ; + qbetab = qbetaf ; + + ab1 = a+b-1.0 ; /* might be as small as -0.5 */ + + /*-- RWCox: if a+b-1 < 0, log(Gamma(a+b-1)) won't work; + instead, use Gamma(a+b-1)=Gamma(a+b)/(a+b-1) --*/ + + if( ab1 > 0.0 ) + pgamf = exp(alng(ab1)-alng(a)-alng(b)+(a-1.0)*log(y)+b*log(1.0-y)) ; + else + pgamf = exp(alng(a+b)-alng(a)-alng(b)+(a-1.0)*log(y)+b*log(1.0-y))/ab1 ; + + pgamb = pgamf*y*(ab1)/a ; + + /*-- we can't have c+b-1 < 0, so the above patchup isn't needed --*/ + + qgamf = exp(alng(c+b-1.0)-alng(c)-alng(b)+(c-1.0)*log(y) + b*log(1.0-y)) ; + qgamb = qgamf*y*(c+b-1.0)/c ; + + rempois = 1.0 - pkf ; + delosq2 = del/1.4142135623731 ; + sum = pkf*pbetaf+delosq2*qkf*qbetaf ; + cons = 0.5*(1.0 + 0.5*fabs(delta)) ; + i = 0 ; +L1: + i = i + 1 ; + pgamf = pgamf*y*(a+b+i-2.0)/(a+i-1.0) ; + pbetaf = pbetaf - pgamf ; + pkf = pkf*dels/(k+i) ; + ptermf = pkf*pbetaf ; + qgamf = qgamf*y*(c+b+i-2.0)/(c+i-1.0) ; + qbetaf = qbetaf - qgamf ; + qkf = qkf*dels/(k+i-1.0+1.5) ; + qtermf = qkf*qbetaf ; + term = ptermf + delosq2*qtermf ; + sum = sum + term ; + error = rempois*cons*pbetaf ; + rempois = rempois - pkf ; + + if( i > k ){ + if( error <= 1.e-12 || i >= 9999 ) goto L2 ; + goto L1 ; + } else { + pgamb = pgamb*(a-i+1.0)/(y*(a+b-i)) ; + pbetab = pbetab + pgamb ; + pkb = (k-i+1.0)*pkb/dels ; + ptermb = pkb*pbetab ; + qgamb = qgamb*(c-i+1.0)/(y*(c+b-i)) ; + qbetab = qbetab + qgamb ; + qkb = (k-i+1.0+0.5)*qkb/dels ; + qtermb = qkb*qbetab ; + term = ptermb + delosq2*qtermb ; + sum = sum + term ; + rempois = rempois - pkb ; + if (rempois <= 1.e-12 || i >= 9999) goto L2 ; + goto L1 ; + } +L2: + tnd = 0.5*sum + ans ; + + /*-- return a pqpair, not just the cdf --*/ + + if( indx ){ pq.p = 1.0-tnd; pq.q = tnd ; } + else { pq.p = tnd ; pq.q = 1.0-tnd; } + return pq ; +} + +/*------------------------------*/ +/* Inverse to above function; + uses cdflib dstinv()/dinvr() + to solve the equation. +--------------------------------*/ + +static double tnonc_pq2s( pqpair pq , double dof , double nonc ) +{ + double t ; /* will be result */ + double tbot,ttop , dt ; + double T6=1.e-50,T7=1.e-8 ; + double K4=0.5,K5=5.0 ; + double fx ; + unsigned long qhi,qleft ; + int status , qporq , ite ; + pqpair tpq ; + + if( dof <= 0.0 ) return BIGG ; /* bad user */ + if( pq.p <= 0.0 ) return -BIGG ; + if( pq.q <= 0.0 ) return BIGG ; + + t = student_pq2s(pq,dof) ; /* initial guess */ + + if( fabs(nonc) < 1.e-8 ) return t ; + + t += 0.5*nonc ; /* adjust up or down */ + + dt = 0.1 * fabs(t) ; if( dt < 1.0 ) dt = 1.0 ; /* stepsize */ + + /* scan down for lower bound, below which cdf is < p */ + + tbot = t ; + for( ite=0 ; ite < 1000 ; ite++ ){ + tpq = tnonc_s2pq( tbot , dof , nonc ) ; + if( tpq.p <= pq.p ) break ; + tbot -= dt ; + } + if( ite >= 1000 ) return -BIGG ; + + /* scan up for upper bound, above which cdf is > p */ + + ttop = tbot+0.5*dt ; + for( ite=0 ; ite < 1000 ; ite++ ){ + tpq = tnonc_s2pq( ttop , dof , nonc ) ; + if( tpq.p >= pq.p ) break ; + ttop += dt ; + } + if( ite >= 1000 ) return BIGG ; + + t = 0.5*(tbot+ttop) ; /* initial guess in middle */ + + /* initialize searching parameters */ + + dstinv(&tbot,&ttop,&K4,&K4,&K5,&T6,&T7); + + status = 0 ; qporq = (pq.p <= pq.q) ; + + while(1){ + + dinvr(&status,&t,&fx,&qleft,&qhi) ; + + if( status != 1 ) return t ; /* done! */ + + tpq = tnonc_s2pq( t , dof , nonc ) ; /* get cdf */ + + /* goal of dinvr is to drive fx to zero */ + + fx = (qporq) ? pq.p-tpq.p : pq.q-tpq.q ; + } + + return BIGG ; /* unreachable */ +} + +/*---------------------------------------------------------------- + Chi distribution (sqrt of chi-squared, duh). +------------------------------------------------------------------*/ + +static pqpair chi_s2pq( double xx , double dof ) +{ + pqpair pq={0.0,1.0} ; + + if( xx <= 0.0 || dof <= 0.0 ) return pq ; + return chisq_s2pq( xx*xx , dof ) ; +} + +/*------------------------------*/ + +static double chi_pq2s( pqpair pq , double dof ) +{ + if( pq.p <= 0.0 ) return 0.0 ; + if( pq.q <= 0.0 ) return BIGG ; + return sqrt(chisq_pq2s(pq,dof)) ; +} + +/*---------------------------------------------------------------- + Extreme value type I: cdf(x) = exp(-exp(-x)). +------------------------------------------------------------------*/ + +static pqpair extval1_s2pq( double x ) +{ + double p,q,y ; pqpair pq ; + + if( x > -5.0 ){ y = exp(-x) ; p = exp(-y) ; } + else { y = 1.0 ; p = 0.0 ; } + + if( y >= 1.e-4 ) q = 1.0-p ; + else q = y*(1.0+y*(-0.5+y*(1.0/6.0-y/24.0))) ; + pq.p = p ; pq.q = q ; return pq ; +} + +/*------------------------------*/ + +static double extval1_pq2s( pqpair pq ) +{ + if( pq.p <= 0.0 ) return -BIGG ; + else if( pq.p >= 1.0 ) return BIGG ; + return -log(-log(pq.p)) ; +} + +/*---------------------------------------------------------------- + Weibull distribution: cdf(x) = 1 - exp( -x^c ) for x>0 and c>0. +------------------------------------------------------------------*/ + +static pqpair weibull_s2pq( double x , double c ) +{ + double y ; + pqpair pq={0.0,1.0} ; + + if( x <= 0.0 || c <= 0.0 ) return pq ; + + y = pow(x,c) ; pq.q = exp(-y) ; + if( y >= 1.e-4 ) pq.p = 1.0-pq.q ; + else pq.p = y*(1.0+y*(-0.5+y*(1.0/6.0-y/24.0))) ; + return pq ; +} + +/*------------------------------*/ + +static double weibull_pq2s( pqpair pq , double c ) +{ + if( pq.p <= 0.0 || c <= 0.0 ) return 0.0 ; + else if( pq.q <= 0.0 ) return BIGG ; + return pow( -log(pq.q) , 1.0/c ) ; +} + +/*---------------------------------------------------------------- + Inverse Gaussian: + density proportional to exp(-0.5*c(x+1/x))/x^1.5 (x,c >0). +------------------------------------------------------------------*/ + +static pqpair invgauss_s2pq( double x, double c ) +{ + double y , p1,q1 , p2,q2 , v ; + pqpair pq={0.0,1.0} ; + + if( x <= 0.0 || c <= 0.0 ) return pq ; + + y = sqrt(c/x) ; + v = y*(x-1.0) ; cumnor( &v , &p1,&q1 ) ; + v = -y*(x+1.0) ; cumnor( &v , &p2,&q2 ) ; + pq.p = p1 ; + if( p2 > 0.0 ) pq.p += exp(2.0*c+log(p2)) ; + pq.q = 1.0-pq.p ; return pq ; +} + +/*------------------------------*/ +/* Inverse to above function; + uses cdflib dstinv()/dinvr() + to solve the equation. +--------------------------------*/ + +static double invgauss_pq2s( pqpair pq , double c ) +{ + double t ; /* will be result */ + double tbot,ttop , dt ; + double T6=1.e-50,T7=1.e-8 ; + double K4=0.5,K5=5.0 ; + double fx ; + unsigned long qhi,qleft ; + int status , qporq , ite ; + pqpair tpq ; + + if( c <= 0.0 ) return BIGG ; /* bad user */ + if( pq.p <= 0.0 ) return 0.0 ; + if( pq.q <= 0.0 ) return BIGG ; + + /* initial guess is t=1; scan down for lower bound */ + + tbot = 1.01 ; dt = 0.9 ; + for( ite=0 ; ite < 1000 ; ite++ ){ + tpq = invgauss_s2pq( tbot , c ) ; + if( tpq.p <= pq.p ) break ; + tbot *= dt ; + } + if( ite >= 1000 ) return 0.0 ; + + /* scan up for upper bound */ + + dt = 1.1 ; ttop = tbot*dt ; + for( ite=0 ; ite < 1000 ; ite++ ){ + tpq = invgauss_s2pq( ttop , c ) ; + if( tpq.p >= pq.p ) break ; + ttop *= dt ; + } + if( ite >= 1000 ) return BIGG ; + + t = sqrt(tbot*ttop) ; /* start at geometric mean */ + + /* initialize searching parameters */ + + dstinv(&tbot,&ttop,&K4,&K4,&K5,&T6,&T7); + + status = 0 ; qporq = (pq.p <= pq.q) ; + + while(1){ + + dinvr(&status,&t,&fx,&qleft,&qhi) ; + + if( status != 1 ) return t ; /* done! */ + + tpq = invgauss_s2pq( t , c ) ; + + /* goal is to drive fx to zero */ + + fx = (qporq) ? pq.p-tpq.p : pq.q-tpq.q ; + } + + return BIGG ; /* unreachable */ +} + +/*--------------------------------------------------------------------------*/ +/*! Given a value, calculate both its cdf and reversed cdf (1.0-cdf). + If an error occurs, you'll probably get back {0.0,1.0}. + All the actual work is done in utility functions for each distribution. +----------------------------------------------------------------------------*/ + +static pqpair stat2pq( double val, int code, double p1,double p2,double p3 ) +{ + pqpair pq={0.0,1.0} ; + + switch( code ){ + + case NIFTI_INTENT_CORREL: pq = correl_s2pq ( val, p1 ) ; break; + case NIFTI_INTENT_TTEST: pq = student_s2pq ( val, p1 ) ; break; + case NIFTI_INTENT_FTEST: pq = fstat_s2pq ( val, p1,p2 ) ; break; + case NIFTI_INTENT_ZSCORE: pq = normal_s2pq ( val ) ; break; + case NIFTI_INTENT_CHISQ: pq = chisq_s2pq ( val, p1 ) ; break; + case NIFTI_INTENT_BETA: pq = beta_s2pq ( val, p1,p2 ) ; break; + case NIFTI_INTENT_BINOM: pq = binomial_s2pq( val, p1,p2 ) ; break; + case NIFTI_INTENT_GAMMA: pq = gamma_s2pq ( val, p1,p2 ) ; break; + case NIFTI_INTENT_POISSON: pq = poisson_s2pq ( val, p1 ) ; break; + case NIFTI_INTENT_FTEST_NONC: pq = fnonc_s2pq ( val, p1,p2,p3 ); break; + case NIFTI_INTENT_CHISQ_NONC: pq = chsqnonc_s2pq( val, p1,p2 ); break; + case NIFTI_INTENT_TTEST_NONC: pq = tnonc_s2pq ( val, p1,p2 ) ; break; + case NIFTI_INTENT_CHI: pq = chi_s2pq ( val, p1 ) ; break; + + /* these distributions are shifted and scaled copies of a standard case */ + + case NIFTI_INTENT_INVGAUSS: + if( p1 > 0.0 && p2 > 0.0 ) pq = invgauss_s2pq( val/p1,p2/p1 ) ; break; + + case NIFTI_INTENT_WEIBULL: + if( p2 > 0.0 && p3 > 0.0 ) pq = weibull_s2pq ((val-p1)/p2,p3) ; break; + + case NIFTI_INTENT_EXTVAL: + if( p2 > 0.0 ) pq = extval1_s2pq ( (val-p1)/p2 ) ; break; + + case NIFTI_INTENT_NORMAL: + if( p2 > 0.0 ) pq = normal_s2pq ( (val-p1)/p2 ) ; break; + + case NIFTI_INTENT_LOGISTIC: + if( p2 > 0.0 ) pq = logistic_s2pq( (val-p1)/p2 ) ; break; + + case NIFTI_INTENT_LAPLACE: + if( p2 > 0.0 ) pq = laplace_s2pq ( (val-p1)/p2 ) ; break; + + case NIFTI_INTENT_UNIFORM: + if( p2 > p1 ) pq = uniform_s2pq((val-p1)/(p2-p1)); break; + + /* this case is trivial */ + + case NIFTI_INTENT_PVAL: pq.p = 1.0-val ; pq.q = val ; break; + } + + return pq ; +} + +/*--------------------------------------------------------------------------*/ +/*! Given a pq value (cdf and 1-cdf), compute the value that gives this. + If an error occurs, you'll probably get back a BIGG number. + All the actual work is done in utility functions for each distribution. +----------------------------------------------------------------------------*/ + +static double pq2stat( pqpair pq, int code, double p1,double p2,double p3 ) +{ + double val=BIGG ; + + if( pq.p < 0.0 || pq.q < 0.0 || pq.p > 1.0 || pq.q > 1.0 ) return val ; + + switch( code ){ + + case NIFTI_INTENT_CORREL: val = correl_pq2s ( pq , p1 ) ; break; + case NIFTI_INTENT_TTEST: val = student_pq2s ( pq , p1 ) ; break; + case NIFTI_INTENT_FTEST: val = fstat_pq2s ( pq , p1,p2 ) ; break; + case NIFTI_INTENT_ZSCORE: val = normal_pq2s ( pq ) ; break; + case NIFTI_INTENT_CHISQ: val = chisq_pq2s ( pq , p1 ) ; break; + case NIFTI_INTENT_BETA: val = beta_pq2s ( pq , p1,p2 ) ; break; + case NIFTI_INTENT_BINOM: val = binomial_pq2s( pq , p1,p2 ) ; break; + case NIFTI_INTENT_GAMMA: val = gamma_pq2s ( pq , p1,p2 ) ; break; + case NIFTI_INTENT_POISSON: val = poisson_pq2s ( pq , p1 ) ; break; + case NIFTI_INTENT_FTEST_NONC: val = fnonc_pq2s ( pq , p1,p2,p3 ); break; + case NIFTI_INTENT_CHISQ_NONC: val = chsqnonc_pq2s( pq , p1,p2 ); break; + case NIFTI_INTENT_TTEST_NONC: val = tnonc_pq2s ( pq , p1,p2 ) ; break; + case NIFTI_INTENT_CHI: val = chi_pq2s ( pq , p1 ) ; break; + + /* these distributions are shifted and scaled copies of a standard case */ + + case NIFTI_INTENT_INVGAUSS: + if( p1 > 0.0 && p2 > 0.0 ) val = p1*invgauss_pq2s ( pq,p2/p1); break; + + case NIFTI_INTENT_WEIBULL: + if( p2 > 0.0 && p3 > 0.0 ) val = p1+p2*weibull_pq2s ( pq, p3 ) ; break; + + case NIFTI_INTENT_EXTVAL: + if( p2 > 0.0 ) val = p1+p2*extval1_pq2s ( pq ) ; break; + + case NIFTI_INTENT_NORMAL: + if( p2 > 0.0 ) val = p1+p2*normal_pq2s ( pq ) ; break; + + case NIFTI_INTENT_LOGISTIC: + if( p2 > 0.0 ) val = p1+p2*logistic_pq2s( pq ) ; break; + + case NIFTI_INTENT_LAPLACE: + if( p2 > 0.0 ) val = p1+p2*laplace_pq2s ( pq ) ; break; + + case NIFTI_INTENT_UNIFORM: + if( p2 > p1 ) val = p1+(p2-p1)*uniform_pq2s(pq) ; break; + + /* this case is trivial */ + + case NIFTI_INTENT_PVAL: val = pq.q ; break; + } + + return val ; +} + +/****************************************************************************/ +/*[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]*/ +/*..........................................................................*/ +/*............. AT LAST! Functions to be called by the user! ..............*/ +/*..........................................................................*/ +/*[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]*/ +/****************************************************************************/ + +/**************************************************************************** + Statistical codes implemented here: + + NIFTI_INTENT_CORREL = correlation statistic + NIFTI_INTENT_TTEST = t statistic (central) + NIFTI_INTENT_FTEST = F statistic (central) + NIFTI_INTENT_ZSCORE = N(0,1) statistic + NIFTI_INTENT_CHISQ = Chi-squared (central) + NIFTI_INTENT_BETA = Beta variable (central) + NIFTI_INTENT_BINOM = Binomial variable + NIFTI_INTENT_GAMMA = Gamma distribution + NIFTI_INTENT_POISSON = Poisson distribution + NIFTI_INTENT_FTEST_NONC = noncentral F statistic + NIFTI_INTENT_CHISQ_NONC = noncentral chi-squared + NIFTI_INTENT_TTEST_NONC = noncentral t statistic + NIFTI_INTENT_CHI = Chi statistic (central) + NIFTI_INTENT_INVGAUSS = inverse Gaussian variable + NIFTI_INTENT_WEIBULL = Weibull distribution + NIFTI_INTENT_EXTVAL = Extreme value type I + NIFTI_INTENT_NORMAL = N(mu,variance) normal + NIFTI_INTENT_LOGISTIC = Logistic distribution + NIFTI_INTENT_LAPLACE = Laplace distribution + NIFTI_INTENT_UNIFORM = Uniform distribution + NIFTI_INTENT_PVAL = "p-value" +*****************************************************************************/ + +static char *inam[]={ NULL , NULL , + "CORREL" , "TTEST" , "FTEST" , "ZSCORE" , + "CHISQ" , "BETA" , "BINOM" , "GAMMA" , + "POISSON" , "NORMAL" , "FTEST_NONC" , "CHISQ_NONC" , + "LOGISTIC" , "LAPLACE" , "UNIFORM" , "TTEST_NONC" , + "WEIBULL" , "CHI" , "INVGAUSS" , "EXTVAL" , + "PVAL" , + NULL } ; + +#include <ctype.h> +#include <string.h> + +/*--------------------------------------------------------------------------*/ +/*! Given a string name for a statistic, return its integer code. + Returns -1 if not found. +----------------------------------------------------------------------------*/ + +int nifti_intent_code( char *name ) +{ + char *unam , *upt ; + int ii ; + + if( name == NULL || *name == '\0' ) return -1 ; + + unam = strdup(name) ; + for( upt=unam ; *upt != '\0' ; upt++ ) *upt = (char)toupper(*upt) ; + + for( ii=NIFTI_FIRST_STATCODE ; ii <= NIFTI_LAST_STATCODE ; ii++ ) + if( strcmp(inam[ii],unam) == 0 ) break ; + + free(unam) ; + return (ii <= NIFTI_LAST_STATCODE) ? ii : -1 ; +} + +/*--------------------------------------------------------------------------*/ +/*! Given a value, return its cumulative distribution function (cdf): + - val = statistic + - code = NIFTI_INTENT_* statistical code + - p1,p2,p3 = parameters of the distribution + + If an error occurs, you'll probably get back 0.0. +----------------------------------------------------------------------------*/ + +double nifti_stat2cdf( double val, int code, double p1,double p2,double p3 ) +{ + pqpair pq ; + pq = stat2pq( val, code, p1,p2,p3 ) ; + return pq.p ; +} + +/*--------------------------------------------------------------------------*/ +/*! Given a value, return its reversed cumulative distribution function + (1-cdf): + - val = statistic + - code = NIFTI_INTENT_* statistical code + - p1,p2,p3 = parameters of the distribution + + If an error transpires, you'll probably get back 1.0. +----------------------------------------------------------------------------*/ + +double nifti_stat2rcdf( double val, int code, double p1,double p2,double p3 ) +{ + pqpair pq ; + pq = stat2pq( val, code, p1,p2,p3 ) ; + return pq.q ; +} + +/*--------------------------------------------------------------------------*/ +/*! Given a cdf probability, find the value that gave rise to it. + - p = cdf; 0 < p < 1 + - code = NIFTI_INTENT_* statistical code + - p1,p2,p3 = parameters of the distribution + + If an error transpires, you'll probably get back a BIGG number. +----------------------------------------------------------------------------*/ + +double nifti_cdf2stat( double p , int code, double p1,double p2,double p3 ) +{ + pqpair pq ; + pq.p = p ; pq.q = 1.0-p ; + return pq2stat(pq,code,p1,p2,p3) ; +} + +/*--------------------------------------------------------------------------*/ +/*! Given a reversed cdf probability, find the value that gave rise to it. + - q = 1-cdf; 0 < q < 1 + - code = NIFTI_INTENT_* statistical code + - p1,p2,p3 = parameters of the distribution + + If an error transpires, you'll probably get back a BIGG number. +----------------------------------------------------------------------------*/ + +double nifti_rcdf2stat( double q , int code, double p1,double p2,double p3 ) +{ + pqpair pq ; + pq.p = 1.0-q ; pq.q = q ; + return pq2stat(pq,code,p1,p2,p3) ; +} + +/*--------------------------------------------------------------------------*/ +/*! Given a statistic, compute a z-score from it. That is, the output + is z such that cdf(z) of a N(0,1) variable is the same as the cdf + of the given distribution at val. +----------------------------------------------------------------------------*/ + +double nifti_stat2zscore( double val , int code, double p1,double p2,double p3 ) +{ + pqpair pq ; + + if( code == NIFTI_INTENT_ZSCORE ) return val ; /* trivial */ + if( code == NIFTI_INTENT_NORMAL ) return (val-p1)/p2 ; /* almost so */ + + pq = stat2pq( val, code, p1,p2,p3 ) ; /* find cdf */ + return normal_pq2s( pq ) ; /* find z */ +} + +/*--------------------------------------------------------------------------*/ +/*! Given a statistic, compute a half-z-score from it. That is, the output + is z such that cdf(z) of a half-N(0,1) variable is the same as the cdf + of the given distribution at val. A half-N(0,1) variable has density + zero for z < 0 and twice the usual N(0,1) density for z > 0. +----------------------------------------------------------------------------*/ + +double nifti_stat2hzscore( double val, int code, double p1,double p2,double p3 ) +{ + pqpair pq ; + + pq = stat2pq( val, code, p1,p2,p3 ) ; /* find cdf */ + pq.q = 0.5*(1.0-pq.p) ; pq.p = 0.5*(1.0+pq.p) ; /* mangle it */ + return normal_pq2s( pq ) ; /* find z */ +} + +/****************************************************************************/ +/*[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]*/ +/****************************************************************************/ + +/*--------------------------------------------------------------------------*/ +/* Sample program to test the above functions. Otherwise unimportant. +----------------------------------------------------------------------------*/ + +int main( int argc , char *argv[] ) +{ + double val , p , q , p1=0.0,p2=0.0,p3=0.0 ; + double vbot,vtop,vdel ; + int code , iarg=1 , doq=0 , dod=0 , doi=0 , doz=0 , doh=0 ; + + /*-- print some help for the pitiful user --*/ + + if( argc < 3 || strstr(argv[1],"help") != NULL ){ + int ii ; + printf("\n") ; + printf("Demo program for computing NIfTI statistical functions.\n") ; + printf("Usage: nifti_stats [-q|-d|-1|-z] val CODE [p1 p2 p3]\n") ; + printf(" val can be a single number or in the form bot:top:step.\n") ; + printf(" default ==> output p = Prob(statistic < val).\n") ; + printf(" -q ==> output is 1-p.\n") ; + printf(" -d ==> output is density.\n") ; + printf(" -1 ==> output is x such that Prob(statistic < x) = val.\n") ; + printf(" -z ==> output is z such that Normal cdf(z) = p(val).\n") ; + printf(" -h ==> output is z such that 1/2-Normal cdf(z) = p(val).\n"); + printf(" Allowable CODEs:\n") ; + for( ii=NIFTI_FIRST_STATCODE ; ii <= NIFTI_LAST_STATCODE ; ii++ ){ + printf(" %-10s",inam[ii]); if((ii-NIFTI_FIRST_STATCODE)%6==5)printf("\n"); + } + printf("\n") ; + printf(" Following CODE are distributional parameters, as needed.\n"); + printf("\n") ; + printf("Results are written to stdout, 1 number per output line.\n") ; + printf("Example (piping output into AFNI program 1dplot):\n") ; + printf(" nifti_stats -d 0:4:.001 INVGAUSS 1 3 | 1dplot -dx 0.001 -stdin\n"); + printf("\n") ; + printf("Author - RW Cox - SSCC/NIMH/NIH/DHHS/USA/EARTH - March 2004\n") ; + printf("\n") ; + exit(0) ; + } + + /*-- check first arg to see if it is an output option; + if so, set the appropriate output flag to determine what to compute --*/ + + if( strcmp(argv[iarg],"-q") == 0 ){ doq = 1 ; iarg++ ; } + else if( strcmp(argv[iarg],"-d") == 0 ){ dod = 1 ; iarg++ ; } + else if( strcmp(argv[iarg],"-1") == 0 ){ doi = 1 ; iarg++ ; } + else if( strcmp(argv[iarg],"-z") == 0 ){ doz = 1 ; iarg++ ; } + else if( strcmp(argv[iarg],"-h") == 0 ){ doh = 1 ; iarg++ ; } + + /*-- get the value(s) to process --*/ + + vbot=vtop=vdel = 0.0 ; + sscanf( argv[iarg++] , "%lf:%lf:%lf" , &vbot,&vtop,&vdel ) ; + if( vbot >= vtop ) vdel = 0.0 ; + if( vdel <= 0.0 ) vtop = vbot ; + + /*-- decode the CODE into the integer signifying the distribution --*/ + + code = nifti_intent_code(argv[iarg++]) ; + if( code < 0 ){ fprintf(stderr,"illegal code=%s\n",argv[iarg-1]); exit(1); } + + /*-- get the parameters, if present (defaults are 0) --*/ + + if( argc > iarg ) p1 = strtod(argv[iarg++],NULL) ; + if( argc > iarg ) p2 = strtod(argv[iarg++],NULL) ; + if( argc > iarg ) p3 = strtod(argv[iarg++],NULL) ; + + /*-- loop over input value(s), compute output, write to stdout --*/ + + for( val=vbot ; val <= vtop ; val += vdel ){ + if( doq ) /* output = 1-cdf */ + p = nifti_stat2rcdf( val , code,p1,p2,p3 ) ; + else if( dod ) /* output = density */ + p = 1000.0*( nifti_stat2cdf(val+.001,code,p1,p2,p3) + -nifti_stat2cdf(val ,code,p1,p2,p3)) ; + else if( doi ) /* output = inverse */ + p = nifti_cdf2stat( val , code,p1,p2,p3 ) ; + else if( doz ) /* output = z score */ + p = nifti_stat2zscore( val , code,p1,p2,p3 ) ; + else if( doh ) /* output = halfz score */ + p = nifti_stat2hzscore( val , code,p1,p2,p3 ) ; + else /* output = cdf */ + p = nifti_stat2cdf( val , code,p1,p2,p3 ) ; + + printf("%.9g\n",p) ; + if( vdel <= 0.0 ) break ; /* the case of just 1 value */ + } + + /*-- terminus est --*/ + + exit(0) ; +} + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/nifti_stats_mex.c b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/nifti_stats_mex.c new file mode 100644 index 0000000..6c61724 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/src/nifti_stats_mex.c @@ -0,0 +1,129 @@ +#ifndef lint +static char svnid[] = "Id: nifti_stats_mex.c 253 2005-10-13 15:31:34Z guillaume "; +#endif +/* + * This is a Matlab mex interface for Bob Cox's extensive nifti_stats.c + * functionality. See nifti_stats.m for documentation. + */ + + +/* + * niftilib $Id: nifti_stats_mex.c,v 1.1 2012/03/22 18:36:33 fissell Exp $ + */ + +#include <stdio.h> +#include <stdlib.h> +#include <math.h> +#include "mex.h" + +#include "nifti1.h" +extern int nifti_intent_code( char *name ); +extern double nifti_stat2cdf( double val, int code, double p1,double p2,double p3 ); +extern double nifti_stat2rcdf( double val, int code, double p1,double p2,double p3 ); +extern double nifti_stat2cdf( double val, int code, double p1,double p2,double p3 ); +extern double nifti_cdf2stat( double val, int code, double p1,double p2,double p3 ); +extern double nifti_stat2zscore( double val, int code, double p1,double p2,double p3 ); +extern double nifti_stat2hzscore( double val, int code, double p1,double p2,double p3 ); + +void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) +{ + double *val, *p, p1=0.0,p2=0.0,p3=0.0 ; + int code=5, dop=1, doq=0, dod=0, doi=0, doz=0, doh=0 ; + int ndim, i, n; + const int *dim; + + if (nlhs>1) mexErrMsgTxt("Too many output arguments."); + if (nrhs<1) mexErrMsgTxt("Not enough input arguments."); + if (nrhs>4) mexErrMsgTxt("Too many input arguments."); + + /* VAL */ + if (!mxIsNumeric(prhs[0]) || !mxIsDouble(prhs[0]) || mxIsComplex(prhs[0])) + mexErrMsgTxt("Wrong datatype for 1st argument."); + ndim = mxGetNumberOfDimensions(prhs[0]); + dim = mxGetDimensions(prhs[0]); + n = 1; + for(i=0,n=1; i<ndim; i++) + n = n*dim[i]; + val = mxGetPr(prhs[0]); + + /* CODE */ + if (nrhs>=2) + { + if (mxIsChar(prhs[1])) + { + int buflen; + char *buf; + buflen = mxGetN(prhs[1])*mxGetM(prhs[1])+1; + buf = (char *)mxCalloc(buflen,sizeof(char)); + mxGetString(prhs[1],buf,buflen); + code = nifti_intent_code(buf); + mxFree(buf); + } + else if (mxIsNumeric(prhs[1]) && mxIsDouble(prhs[1]) && !mxIsComplex(prhs[1])) + { + if (mxGetM(prhs[1])*mxGetN(prhs[1]) != 1) + mexErrMsgTxt("Wrong sized 2nd argument."); + code = (int)mxGetPr(prhs[1])[0]; + } + else mexErrMsgTxt("Wrong datatype for 2nd argument."); + if (code<NIFTI_FIRST_STATCODE || code>NIFTI_LAST_STATCODE) + mexErrMsgTxt("Illegal Stat-Code."); + } + + /* OPT */ + if (nrhs>=3) + { + int buflen; + char *buf; + dop = 0; + if (!mxIsChar(prhs[2])) + mexErrMsgTxt("Wrong datatype for3rd argument."); + buflen = mxGetN(prhs[2])*mxGetM(prhs[2])+1; + buf = (char *)mxCalloc(buflen,sizeof(char)); + mxGetString(prhs[2],buf,buflen); + if ( strcmp(buf,"-p") == 0 ) dop = 1; + else if ( strcmp(buf,"-q") == 0 ) doq = 1; + else if ( strcmp(buf,"-d") == 0 ) dod = 1; + else if ( strcmp(buf,"-1") == 0 ) doi = 1; + else if ( strcmp(buf,"-z") == 0 ) doz = 1; + else if ( strcmp(buf,"-h") == 0 ) doh = 1; + else { mxFree(buf); mexErrMsgTxt("Unrecognised option."); } + mxFree(buf); + } + + /* PARAM */ + if (nrhs>=4) + { + int np; + if (!mxIsNumeric(prhs[3]) || !mxIsDouble(prhs[3]) || mxIsComplex(prhs[3])) + mexErrMsgTxt("Wrong datatype for 4th argument."); + np = mxGetM(prhs[3])*mxGetN(prhs[3]); + if (np>3) mexErrMsgTxt("Wrong sized 4th argument."); + if (np>=1) p1 = mxGetPr(prhs[3])[0]; + if (np>=2) p2 = mxGetPr(prhs[3])[1]; + if (np>=3) p3 = mxGetPr(prhs[3])[2]; + } + + /* P */ + plhs[0] = mxCreateNumericArray(ndim,dim,mxDOUBLE_CLASS,mxREAL); + p = mxGetData(plhs[0]); + + /* Call Bob's code */ + for(i=0; i<n; i++) + { + if ( dop ) + p[i] = nifti_stat2cdf(val[i], code,p1,p2,p3 ) ; + else if ( doq ) + p[i] = nifti_stat2rcdf(val[i], code,p1,p2,p3 ) ; + else if ( dod ) + p[i] = 1000.0*( nifti_stat2cdf(val[i]+.001,code,p1,p2,p3) + -nifti_stat2cdf(val[i] ,code,p1,p2,p3)) ; + else if ( doi ) + p[i] = nifti_cdf2stat(val[i], code,p1,p2,p3 ) ; + else if ( doz ) + p[i] = nifti_stat2zscore(val[i], code,p1,p2,p3 ) ; + else if ( doh ) + p[i] = nifti_stat2hzscore(val[i], code,p1,p2,p3 ) ; + } +} + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/write_extras.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/write_extras.m new file mode 100644 index 0000000..49c4cc5 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/write_extras.m @@ -0,0 +1,41 @@ +function extras = write_extras(fname,extras) +% Write extra bits of information +%_______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: write_extras.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: write_extras.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +[pth,nam,ext] = fileparts(fname); +switch ext +case {'.hdr','.img','.nii'} + mname = fullfile(pth,[nam '.mat']); +case {'.HDR','.IMG','.NII'} + mname = fullfile(pth,[nam '.MAT']); +otherwise + mname = fullfile(pth,[nam '.mat']); +end +if isstruct(extras) && ~isempty(fieldnames(extras)), + savefields(mname,extras); +end; + +function savefields(fnam,p) +if length(p)>1, error('Can''t save fields.'); end; +fn = fieldnames(p); +for i_=1:length(fn), + eval([fn{i_} '= p.' fn{i_} ';']); +end; +if str2num(version('-release'))>=14, + fn = {'-V6',fn{:}}; +end; +if numel(fn)>0, + save(fnam,fn{:}); +end; +return; + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/write_hdr_raw.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/write_hdr_raw.m new file mode 100644 index 0000000..01b65e5 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/private/write_hdr_raw.m @@ -0,0 +1,82 @@ +function ok = write_hdr_raw(fname,hdr,be) +% Write a NIFTI-1 .hdr file. +% FORMAT ok = write_hdr_raw(fname,hdr,be) +% fname - filename of image +% hdr - a structure containing hdr info +% be - whether big-endian or not +% ok - status (1=good, 0=bad) +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: write_hdr_raw.m 2237 2008-09-29 17:39:53Z guillaume + +% +% niftilib $Id: write_hdr_raw.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + + +[pth,nam,ext] = fileparts(fname); +if isempty(pth), pth = pwd; end + +if isfield(hdr,'magic') + org = niftistruc; + switch deblank(hdr.magic) + case {'ni1'} + hname = fullfile(pth,[nam '.hdr']); + case {'n+1'} + hname = fullfile(pth,[nam '.nii']); + otherwise + error('Bad header.'); + end; +else + org = mayostruc; + hname = fullfile(pth,[nam '.hdr']); +end; + +if nargin >=3 + if be, mach = 'ieee-be'; + else mach = 'ieee-le'; + end; +else mach = 'native'; +end; + +ok = true; +if spm_existfile(hname), + fp = fopen(hname,'r+',mach); +else + fp = fopen(hname,'w+',mach); +end +if fp == -1, + ok = false; + return; +end + +for i=1:length(org) + if isfield(hdr,org(i).label), + dat = hdr.(org(i).label); + if length(dat) ~= org(i).len, + if length(dat)< org(i).len, + dat = [dat(:) ; zeros(org(i).len-length(dat),1)]; + else + dat = dat(1:org(i).len); + end; + end; + else + dat = org(i).def; + end; + % fprintf('%s=\n',org(i).label) + % disp(dat) + len = fwrite(fp,dat,org(i).dtype.prec); + if len ~= org(i).len, + ok = false; + end; +end; +fclose(fp); +if ~ok, + fprintf('There was a problem writing to the header of\n'); + fprintf('"%s"\n', fname); +end; +return; + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/structn.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/structn.m new file mode 100644 index 0000000..074ab04 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/structn.m @@ -0,0 +1,24 @@ +function t = structn(obj) +% Convert a NIFTI-1 object into a form of struct +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: structn.m 1143 2008-02-07 19:33:33Z spm + +% +% niftilib $Id: structn.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + +if numel(obj)~=1, + error('Too many elements to convert'); +end; +fn = fieldnames(obj); +for i=1:length(fn) + tmp = subsref(obj,struct('type','.','subs',fn{i})); + if ~isempty(tmp) + t.(fn{i}) = tmp; + end; +end; +return; diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/subsasgn.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/subsasgn.m new file mode 100644 index 0000000..5335be1 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/subsasgn.m @@ -0,0 +1,404 @@ +function obj = subsasgn(obj,subs,varargin) +% Subscript assignment +% See subsref for meaning of fields. +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: subsasgn.m 4136 2010-12-09 22:22:28Z guillaume + +% +% niftilib $Id: subsasgn.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + +switch subs(1).type, +case {'.'}, + if numel(obj)~=nargin-2, + error('The number of outputs should match the number of inputs.'); + end; + objs = struct(obj); + for i=1:length(varargin), + val = varargin{i}; + obji = nifti(objs(i)); + obji = fun(obji,subs,val); + objs(i) = struct(obji); + end; + obj = nifti(objs); + +case {'()'}, + objs = struct(obj); + if length(subs)>1, + t = subsref(objs,subs(1)); + % A lot of this stuff is a little flakey, and may cause Matlab to bomb. + % + %if numel(t) ~= nargin-2, + % error('The number of outputs should match the number of inputs.'); + %end; + for i=1:numel(t), + val = varargin{1}; + obji = nifti(t(i)); + obji = subsasgn(obji,subs(2:end),val); + t(i) = struct(obji); + end; + objs = subsasgn(objs,subs(1),t); + else + if numel(varargin)>1, + error('Illegal right hand side in assignment. Too many elements.'); + end; + val = varargin{1}; + if isa(val,'nifti'), + objs = subsasgn(objs,subs,struct(val)); + elseif isempty(val), + objs = subsasgn(objs,subs,[]); + else + error('Assignment between unlike types is not allowed.'); + end; + end; + obj = nifti(objs); + +otherwise + error('Cell contents reference from a non-cell array object.'); +end; +return; +%======================================================================= + +%======================================================================= +function obj = fun(obj,subs,val) +% Subscript referencing + +switch subs(1).type, +case {'.'}, + objs = struct(obj); + for ii=1:numel(objs) + obj = objs(ii); + + if any(strcmpi(subs(1).subs,{'dat'})), + if length(subs)>1, + val = subsasgn(obj.dat,subs(2:end),val); + end; + obj = assigndat(obj,val); + objs(ii) = obj; + continue; + end; + + if isempty(obj.hdr), obj.hdr = empty_hdr; end; + if ~isfield(obj.hdr,'magic'), error('Not a NIFTI-1 header'); end; + + if length(subs)>1, % && ~strcmpi(subs(1).subs,{'raw','dat'}), + val0 = subsref(nifti(obj),subs(1)); + val1 = subsasgn(val0,subs(2:end),val); + else + val1 = val; + end; + + switch(subs(1).subs) + case {'extras'} + if length(subs)>1, + obj.extras = subsasgn(obj.extras,subs(2:end),val); + else + obj.extras = val; + end; + + case {'mat0'} + if ~isnumeric(val1) || ndims(val1)~=2 || any(size(val1)~=[4 4]) || sum((val1(4,:)-[0 0 0 1]).^2)>1e-8, + error('"mat0" should be a 4x4 matrix, with a last row of 0,0,0,1.'); + end; + if obj.hdr.qform_code==0, obj.hdr.qform_code=2; end; + s = double(bitand(obj.hdr.xyzt_units,7)); + if s + d = findindict(s,'units'); + val1 = diag([[1 1 1]/d.rescale 1])*val1; + end; + obj.hdr = encode_qform0(double(val1), obj.hdr); + + case {'mat0_intent'} + if isempty(val1), + obj.hdr.qform_code = 0; + else + if ~ischar(val1) && ~(isnumeric(val1) && numel(val1)==1), + error('"mat0_intent" should be a string or a scalar.'); + end; + d = findindict(val1,'xform'); + if ~isempty(d) + obj.hdr.qform_code = d.code; + end; + end; + + case {'mat'} + if ~isnumeric(val1) || ndims(val1)~=2 || any(size(val1)~=[4 4]) || sum((val1(4,:)-[0 0 0 1]).^2)>1e-8 + error('"mat" should be a 4x4 matrix, with a last row of 0,0,0,1.'); + end; + if obj.hdr.sform_code==0, obj.hdr.sform_code=2; end; + s = double(bitand(obj.hdr.xyzt_units,7)); + if s + d = findindict(s,'units'); + val1 = diag([[1 1 1]/d.rescale 1])*val1; + end; + val1 = val1 * [eye(4,3) [1 1 1 1]']; + obj.hdr.srow_x = val1(1,:); + obj.hdr.srow_y = val1(2,:); + obj.hdr.srow_z = val1(3,:); + + case {'mat_intent'} + if isempty(val1), + obj.hdr.sform_code = 0; + else + if ~ischar(val1) && ~(isnumeric(val1) && numel(val1)==1), + error('"mat_intent" should be a string or a scalar.'); + end; + d = findindict(val1,'xform'); + if ~isempty(d), + obj.hdr.sform_code = d.code; + end; + end; + + case {'intent'} + if ~valid_fields(val1,{'code','param','name'}) + obj.hdr.intent_code = 0; + obj.hdr.intent_p1 = 0; + obj.hdr.intent_p2 = 0; + obj.hdr.intent_p3 = 0; + obj.hdr.intent_name = ''; + else + if ~isfield(val1,'code'), + val1.code = obj.hdr.intent_code; + end; + d = findindict(val1.code,'intent'); + if ~isempty(d), + obj.hdr.intent_code = d.code; + if isfield(val1,'param'), + prm = [double(val1.param(:)) ; 0 ; 0; 0]; + prm = [prm(1:length(d.param)) ; 0 ; 0; 0]; + obj.hdr.intent_p1 = prm(1); + obj.hdr.intent_p2 = prm(2); + obj.hdr.intent_p3 = prm(3); + end; + if isfield(val1,'name'), + obj.hdr.intent_name = val1.name; + end; + end; + end; + + case {'diminfo'} + if ~valid_fields(val1,{'frequency','phase','slice','slice_time'}) + tmp = obj.hdr.dim_info; + for bit=1:6, + tmp = bitset(tmp,bit,0); + end; + obj.hdr.dim_info = tmp; + obj.hdr.slice_start = 0; + obj.hdr.slice_end = 0; + obj.hdr.slice_duration = 0; + obj.hdr.slice_code = 0; + else + if isfield(val1,'frequency'), + tmp = val1.frequency; + if ~isnumeric(tmp) || numel(tmp)~=1 || tmp<0 || tmp>3, + error('Invalid frequency direction'); + end; + obj.hdr.dim_info = bitset(obj.hdr.dim_info,1,bitget(tmp,1)); + obj.hdr.dim_info = bitset(obj.hdr.dim_info,2,bitget(tmp,2)); + end; + + if isfield(val1,'phase'), + tmp = val1.phase; + if ~isnumeric(tmp) || numel(tmp)~=1 || tmp<0 || tmp>3, + error('Invalid phase direction'); + end; + obj.hdr.dim_info = bitset(obj.hdr.dim_info,3,bitget(tmp,1)); + obj.hdr.dim_info = bitset(obj.hdr.dim_info,4,bitget(tmp,2)); + end; + + if isfield(val1,'slice'), + tmp = val1.slice; + if ~isnumeric(tmp) || numel(tmp)~=1 || tmp<0 || tmp>3, + error('Invalid slice direction'); + end; + obj.hdr.dim_info = bitset(obj.hdr.dim_info,5,bitget(tmp,1)); + obj.hdr.dim_info = bitset(obj.hdr.dim_info,6,bitget(tmp,2)); + end; + + if isfield(val1,'slice_time') + tim = val1.slice_time; + if ~valid_fields(tim,{'start','end','duration','code'}), + obj.hdr.slice_code = 0; + obj.hdr.slice_start = 0; + obj.hdr.end_slice = 0; + obj.hdr.slice_duration = 0; + else + % sld = double(bitget(obj.hdr.dim_info,5)) + 2*double(bitget(obj.hdr.dim_info,6)); + + if isfield(tim,'start'), + ss = double(tim.start); + if isnumeric(ss) && numel(ss)==1 && ~rem(ss,1), % && ss>=1 && ss<=obj.hdr.dim(sld+1) + obj.hdr.slice_start = ss-1; + else + error('Inappropriate "slice_time.start".'); + end; + end; + + if isfield(tim,'end'), + ss = double(tim.end); + if isnumeric(ss) && numel(ss)==1 && ~rem(ss,1), % && ss>=1 && ss<=obj.hdr.dim(sld+1) + obj.hdr.slice_end = ss-1; + else + error('Inappropriate "slice_time.end".'); + end; + end; + + if isfield(tim,'duration') + sd = double(tim.duration); + if isnumeric(sd) && numel(sd)==1, + s = double(bitand(obj.hdr.xyzt_units,24)); + d = findindict(s,'units'); + if ~isempty(d) && d.rescale, sd = sd/d.rescale; end; + obj.hdr.slice_duration = sd; + else + error('Inappropriate "slice_time.duration".'); + end; + end; + + if isfield(tim,'code'), + d = findindict(tim.code,'sliceorder'); + if ~isempty(d), + obj.hdr.slice_code = d.code; + end; + end; + end; + end; + end; + + case {'timing'} + if ~valid_fields(val1,{'toffset','tspace'}), + obj.hdr.pixdim(5) = 0; + obj.hdr.toffset = 0; + else + s = double(bitand(obj.hdr.xyzt_units,24)); + d = findindict(s,'units'); + if isfield(val1,'toffset'), + if isnumeric(val1.toffset) && numel(val1.toffset)==1, + if d.rescale, + val1.toffset = val1.toffset/d.rescale; + end; + obj.hdr.toffset = val1.toffset; + else + error('"timing.toffset" needs to be numeric with 1 element'); + end; + end; + if isfield(val1,'tspace'), + if isnumeric(val1.tspace) && numel(val1.tspace)==1, + if d.rescale, + val1.tspace = val1.tspace/d.rescale; + end; + obj.hdr.pixdim(5) = val1.tspace; + else + error('"timing.tspace" needs to be numeric with 1 element'); + end; + end; + end; + + case {'descrip'} + if isempty(val1), val1 = char(val1); end; + if ischar(val1), + obj.hdr.descrip = val1; + else + error('"descrip" must be a string.'); + end; + + case {'cal'} + if isempty(val1), + obj.hdr.cal_min = 0; + obj.hdr.cal_max = 0; + else + if isnumeric(val1) && numel(val1)==2, + obj.hdr.cal_min = val1(1); + obj.hdr.cal_max = val1(2); + else + error('"cal" should contain two elements.'); + end; + end; + + case {'aux_file'} + if isempty(val1), val1 = char(val1); end; + if ischar(val1), + obj.hdr.aux_file = val1; + else + error('"aux_file" must be a string.'); + end; + + case {'hdr'} + error('hdr is a read-only field.'); + obj.hdr = val1; + + otherwise + error(['Reference to non-existent field ''' subs(1).subs '''.']); + end; + + objs(ii) = obj; + end + obj = nifti(objs); + +otherwise + error('This should not happen.'); +end; +return; +%======================================================================= + +%======================================================================= +function obj = assigndat(obj,val) +if isa(val,'file_array'), + sz = size(val); + if numel(sz)>7, + error('Too many dimensions in data.'); + end; + sz = [sz 1 1 1 1 1 1 1]; + sz = sz(1:7); + sval = struct(val); + d = findindict(sval.dtype,'dtype'); + if isempty(d) + error(['Unknown datatype (' num2str(double(sval.datatype)) ').']); + end; + + [pth,nam,suf] = fileparts(sval.fname); + if any(strcmp(suf,{'.img','.IMG'})) + val.offset = max(sval.offset,0); + obj.hdr.magic = ['ni1' char(0)]; + elseif any(strcmp(suf,{'.nii','.NII'})) + val.offset = max(sval.offset,352); + obj.hdr.magic = ['n+1' char(0)]; + else + error(['Unknown filename extension (' suf ').']); + end; + val.offset = (ceil(val.offset/16))*16; + obj.hdr.vox_offset = val.offset; + + obj.hdr.dim(2:(numel(sz)+1)) = sz; + nd = max(find(obj.hdr.dim(2:end)>1)); + if isempty(nd), nd = 3; end; + obj.hdr.dim(1) = nd; + obj.hdr.datatype = sval.dtype; + obj.hdr.bitpix = d.size*8; + if ~isempty(sval.scl_slope), obj.hdr.scl_slope = sval.scl_slope; end; + if ~isempty(sval.scl_inter), obj.hdr.scl_inter = sval.scl_inter; end; + obj.dat = val; +else + error('"raw" must be of class "file_array"'); +end; +return; + +function ok = valid_fields(val,allowed) +if isempty(val), ok = false; return; end; +if ~isstruct(val), + error(['Expecting a structure, not a ' class(val) '.']); +end; +fn = fieldnames(val); +for ii=1:length(fn), + if ~any(strcmpi(fn{ii},allowed)), + fprintf('Allowed fieldnames are:\n'); + for i=1:length(allowed), fprintf(' %s\n', allowed{i}); end; + error(['"' fn{ii} '" is not a valid fieldname.']); + end +end +ok = true; +return; diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/subsref.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/subsref.m new file mode 100644 index 0000000..dcedc97 --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/@nifti/subsref.m @@ -0,0 +1,245 @@ +function varargout = subsref(opt,subs) +% Subscript referencing +% +% Fields are: +% dat - a file-array representing the image data +% mat0 - a 9-parameter affine transform (from qform0) +% Note that the mapping is from voxels (where the first +% is considered to be at [1,1,1], to millimetres. See +% mat0_interp for the meaning of the transform. +% mat - a 12-parameter affine transform (from sform0) +% Note that the mapping is from voxels (where the first +% is considered to be at [1,1,1], to millimetres. See +% mat1_interp for the meaning of the transform. +% mat_intent - intention of mat. This field may be missing/empty. +% mat0_intent - intention of mat0. This field may be missing/empty. +% intent - interpretation of image. When present, this structure +% contains the fields +% code - name of interpretation +% params - parameters needed to interpret the image +% diminfo - MR encoding of different dimensions. This structure may +% contain some or all of the following fields +% frequency - a value of 1-3 indicating frequency direction +% phase - a value of 1-3 indicating phase direction +% slice - a value of 1-3 indicating slice direction +% slice_time - only present when "slice" field is present. +% Contains the following fields +% code - ascending/descending etc +% start - starting slice number +% end - ending slice number +% duration - duration of each slice acquisition +% Setting frequency, phase or slice to 0 will remove it. +% timing - timing information. When present, contains the fields +% toffset - acquisition time of first volume (seconds) +% tspace - time between sucessive volumes (seconds) +% descrip - a brief description of the image +% cal - a two-element vector containing cal_min and cal_max +% aux_file - name of an auxiliary file +% _______________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% +% Id: subsref.m 4136 2010-12-09 22:22:28Z guillaume + +% +% niftilib $Id: subsref.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + + +varargout = rec(opt,subs); +return; + +function c = rec(opt,subs) +switch subs(1).type, +case {'.'}, + c = {}; + opts = struct(opt); + for ii=1:numel(opts) + opt = nifti(opts(ii)); + %if ~isstruct(opt) + % error('Attempt to reference field of non-structure array.'); + %end; + + h = opt.hdr; + if isempty(h), + %error('No header.'); + h = empty_hdr; + end; + + % NIFTI-1 FORMAT + switch(subs(1).subs) + case 'extras', + t = opt.extras; + + case 'raw', % A hidden field + if isa(opt.dat,'file_array'), + tmp = struct(opt.dat); + tmp.scl_slope = []; + tmp.scl_inter = []; + t = file_array(tmp); + else + t = opt.dat; + end; + + case 'dat', + t = opt.dat; + + case 'mat0', + t = decode_qform0(h); + s = double(bitand(h.xyzt_units,7)); + if s + d = findindict(s,'units'); + if ~isempty(d) + t = diag([d.rescale*[1 1 1] 1])*t; + end; + end; + + case 'mat0_intent', + d = findindict(h.qform_code,'xform'); + if isempty(d) || d.code==0, + t = ''; + else + t = d.label; + end; + + case 'mat', + if h.sform_code > 0 + t = double([h.srow_x ; h.srow_y ; h.srow_z ; 0 0 0 1]); + t = t * [eye(4,3) [-1 -1 -1 1]']; + else + t = decode_qform0(h); + end + s = double(bitand(h.xyzt_units,7)); + if s + d = findindict(s,'units'); + t = diag([d.rescale*[1 1 1] 1])*t; + end; + + case 'mat_intent', + if h.sform_code>0, + t = h.sform_code; + else + t = h.qform_code; + end; + d = findindict(t,'xform'); + if isempty(d) || d.code==0, + t = ''; + else + t = d.label; + end; + + case 'intent', + d = findindict(h.intent_code,'intent'); + if isempty(d) || d.code == 0, + %t = struct('code','UNKNOWN','param',[]); + t = []; + else + t = struct('code',d.label,'param',... + double([h.intent_p1 h.intent_p2 h.intent_p3]), 'name',deblank(h.intent_name)); + t.param = t.param(1:length(d.param)); + end + + case 'diminfo', + t = []; + tmp = bitand( h.dim_info ,3); if tmp, t.frequency = double(tmp); end; + tmp = bitand(bitshift(h.dim_info,-2),3); if tmp, t.phase = double(tmp); end; + tmp = bitand(bitshift(h.dim_info,-4),3); if tmp, t.slice = double(tmp); end; + % t = struct('frequency',bitand( h.dim_info ,3),... + % 'phase',bitand(bitshift(h.dim_info,-2),3),... + % 'slice',bitand(bitshift(h.dim_info,-4),3)) + if isfield(t,'slice') + sc = double(h.slice_code); + ss = double(h.slice_start)+1; + se = double(h.slice_end)+1; + ss = max(ss,1); + se = min(se,double(h.dim(t.slice+1))); + + sd = double(h.slice_duration); + s = double(bitand(h.xyzt_units,24)); + d = findindict(s,'units'); + if d.rescale, sd = sd*d.rescale; end; + + ns = (se-ss+1); + d = findindict(sc,'sliceorder'); + if isempty(d) + label = 'UNKNOWN'; + else + label = d.label; + end; + t.slice_time = struct('code',label,'start',ss,'end',se,'duration',sd); + if 0, % Never + t.times = zeros(1,double(h.dim(t.slice+1)))+NaN; + switch sc, + case 0, % Unknown + t.times(ss:se) = zeros(1,ns); + case 1, % sequential increasing + t.times(ss:se) = (0:(ns-1))*sd; + case 2, % sequential decreasing + t.times(ss:se) = ((ns-1):-1:0)*sd; + case 3, % alternating increasing + t.times(ss:2:se) = (0:floor((ns+1)/2-1))*sd; + t.times((ss+1):2:se) = (floor((ns+1)/2):(ns-1))*sd; + case 4, % alternating decreasing + t.times(se:-2:ss) = (0:floor((ns+1)/2-1))*sd; + t.times(se:-2:(ss+1)) = (floor((ns+1)/2):(ns-1))*sd; + end; + end; + end; + + case 'timing', + to = double(h.toffset); + dt = double(h.pixdim(5)); + if to==0 && dt==0, + t = []; + else + s = double(bitand(h.xyzt_units,24)); + d = findindict(s,'units'); + if d.rescale, + to = to*d.rescale; + dt = dt*d.rescale; + end; + t = struct('toffset',to,'tspace',dt); + end; + + case 'descrip', + t = deblank(h.descrip); + msk = find(t==0); + if any(msk), t=t(1:(msk(1)-1)); end; + + case 'cal', + t = [double(h.cal_min) double(h.cal_max)]; + if all(t==0), t = []; end; + + case 'aux_file', + t = deblank(h.aux_file); + + case 'hdr', % Hidden field + t = h; + + otherwise + error(['Reference to non-existent field ''' subs(1).subs '''.']); + end; + if numel(subs)>1, + t = subsref(t,subs(2:end)); + end; + c{ii} = t; + end; +case {'{}'}, + error('Cell contents reference from a non-cell array object.'); +case {'()'}, + opt = struct(opt); + t = subsref(opt,subs(1)); + if length(subs)>1 + c = {}; + for i=1:numel(t), + ti = nifti(t(i)); + ti = rec(ti,subs(2:end)); + c = {c{:}, ti{:}}; + end; + else + c = {nifti(t)}; + end; + +otherwise + error('This should not happen.'); +end; diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/Makefile b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/Makefile new file mode 100644 index 0000000..03e71fc --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/Makefile @@ -0,0 +1,85 @@ +#!make -f +# +# The tardist file for the nifti1 matlab code contains precompiled +# mex files for the PCWIN, MAC, SOL2, LNX86, GLNXA64 platforms, so +# you do not need to do this build if you have one of those platforms. +# Run "uname" at your shell prompt to see your platform code. +# +# +# Two files need to be compiled with the MATLAB mex compiler: +# file2mat.c +# mat2file.c +# These files are in the @file_array/private/src directory. +# A successful compile will leave two "mex" files in the @file_array/private directory: +# file2mat.mex<platform suffix> +# mat2file.mex<platform suffix> +# +# To make the mex files, in this matlab directory type: +# make all +# +# +# Problems ? +# If you need to make platform specific tweaks to the mex call, you +# may want to look at the SPM8 (http://www.fil.ion.ucl.ac.uk/spm/) +# distribution src/Makefile and src/Makefile.var that has more detailed flag settings. +# +# For Windows you need the CygWin environment (http://sourceware.org/cygwin/). +# Install the Default configuration, along with the gcc C compiler, and make +# from the "Devel" options. +# You may want to refer to Matthew Brett's web page on mex files for Windows: +# (http://gnumex.sourceforge.net/) +# + + +## Defines +MEX = mex -O +CC = cc +DIR = @file_array/private/src + + + +## Default targets +unknown: + @ make `uname` + +all: + @ make `uname` + +help: + @echo "make all to compile the file2mat and mat2file mex libraries" + @echo "" + + +## Platforms +SunOS: big_endian +IRIX: big_endian +IRIX64: big_endian +HP-UX: big_endian +AIX: big_endian +OSF1: big_endian + +# for MAC power pc reset to big_endian +Darwin: little_endian + +Linux: little_endian +Linux.A64: little_endian + +CYGWIN_NT-4.0: windows +CYGWIN_NT-5.0: windows +CYGWIN_NT-5.1: windows + + + +## Compiles +big_endian: + (cd $(DIR); $(MEX) -DBIGENDIAN file2mat.c; mv *mex* ..) + (cd $(DIR); $(MEX) -DBIGENDIAN mat2file.c; mv *mex* ..) + +little_endian: + (cd $(DIR); $(MEX) file2mat.c; mv *mex* ..) + (cd $(DIR); $(MEX) mat2file.c; mv *mex* ..) + +windows: + (cd $(DIR); $(MEX) -DSPM_WIN32 file2mat.c; mv *.dll ..) + (cd $(DIR); $(MEX) -DSPM_WIN32 mat2file.c; mv *.dll ..) + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/make.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/make.m new file mode 100644 index 0000000..8ffdd4c --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/make.m @@ -0,0 +1,41 @@ +% +% Makefile equivalent for use in MatLab +% requires availability of MEX +% +% calling 'make' from the matlab prompt: +% 1. compiles the c-sources in @file_array/private/src +% 2. moves the compiled files to @file_array/private +% +% Alle Meije Wink 27/03/2012 +% a.wink@vumc.nl +% + +% +% niftilib $Id: make.m,v 1.1 2012/03/30 15:25:41 fissell Exp $ +% + +% check for existence of MEX compiler +if (exist('mex') ~=2) + error('MEX not installed on your system. Exiting.'); +end + +% go to the directory where the c sources are +cd(['@file_array' filesep 'private' filesep 'src']) + +% compile the 2 sources +if(mex('file2mat.c') | mex('mat2file.c')) + error('something went wrong during compilation'); +else + % move them to the parent directory + if(~movefile('*.mex*','..')) + error('compiled files could not be moved') + end +end + +% go bake to the directory of make.m +cd(['..' filesep '..' filesep '..']); + +% report the good news +disp ('files successfully compiled and moved') + + diff --git a/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/spm_flip_analyze_images.m b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/spm_flip_analyze_images.m new file mode 100644 index 0000000..1f56afa --- /dev/null +++ b/NODDI_toolbox_v1.01/niftimatlib-1.2/niftimatlib-1.2/matlab/spm_flip_analyze_images.m @@ -0,0 +1,19 @@ +function flip = spm_flip_analyze_images +% Do Analyze format images need to be left-right flipped? The default +% behaviour is to have the indices of the voxels stored as left-handed and +% interpret the mm coordinates within a right-handed coordinate system. +% +% Note: the behaviour used to be set in spm_defaults.m, but this has now +% been changed. +%__________________________________________________________________________ +% Copyright (C) 2008 Wellcome Trust Centre for Neuroimaging + +% John Ashburner +% Id: spm_flip_analyze_images.m 1418 2008-04-15 19:15:16Z john + +% +% niftilib $Id: spm_flip_analyze_images.m,v 1.3 2012/03/22 18:36:33 fissell Exp $ +% + +flip = 1; + diff --git a/PPMI_NODDI.m b/PPMI_NODDI.m new file mode 100644 index 0000000..4b62d03 --- /dev/null +++ b/PPMI_NODDI.m @@ -0,0 +1,51 @@ +function PPMI_NODDI(i) +addpath(genpath('NODDI_toolbox_v1.0.1')); +importPPMIlist +PatientNumber=VarName1; +%for i=1:floor(length(PatientNumber)/3) +% +% [bVal, bGradX, bGradY, bGradZ] = textread(strcat('/data/project/dti/For_William/rotateDWIv2/BMTXT/',int2str(PatientNumber(i)),'.rotatetwo.BVEC.txt'),'%f %f %f %f'); +% lengthB = length(bGradX); +% +% fileID = fopen(strcat('/data/project/dti/For_William/rotateDWIv2/BMTXT/',int2str(PatientNumber(i)),'.rotatetwo.bval'),'w'); +% +% formatSpec = '%f '; +% +% for j=1:lengthB +% fprintf(fileID,formatSpec,bVal(j)); +% end +% fclose(fileID); +% +% clear fileID +% +% fileID = fopen(strcat('/data/project/dti/For_William/rotateDWIv2/BMTXT/',int2str(PatientNumber(i)),'.rotatetwo.bvec'),'w'); +% +% formatSpec = '%f '; +% +% for j=1:lengthB +% fprintf(fileID,formatSpec,bGradX(j)); +% end +% +% fprintf(fileID,'\n'); +% +% for j=1:lengthB +% fprintf(fileID,formatSpec,bGradY(j)); +% end +% +% fprintf(fileID,'\n'); +% +% for j=1:lengthB +% fprintf(fileID,formatSpec,bGradZ(j)); +% end +% fclose(fileID); +% +% clear fileID + +CreateROI(strcat('/data/project/dti/For_William/rotateDWIv2/finalrotatedDWIv2/',int2str(PatientNumber(i)),'.DWI.rotat.med.nii'),strcat('/data/project/dti/For_William/rotateDWIv2/brainMasks/',int2str(PatientNumber(i)),'.brainmask.nii'),strcat('/data/project/dti/For_William/rotateDWIv2/FreeWaterResults_WB/',int2str(PatientNumber(i)),'.NODDIroi.mat')); +%CreateROI('/data/project/dti/For_William/rotateDWIv2/finalrotatedDWIv2/3111.DWI.rotat.med.nii','/data/project/dti/For_William/rotateDWIv2/brainMasks/3111.brainmask.nii','NODDIroi1.mat') +protocol = FSL2Protocol(strcat('/data/project/dti/For_William/rotateDWIv2/BMTXT/',int2str(PatientNumber(i)),'.rotatetwo.bval'),strcat('/data/project/dti/For_William/rotateDWIv2/BMTXT/',int2str(PatientNumber(i)),'.rotatetwo.bvec')) +noddi = MakeModel('WatsonSHStickTortIsoV_B0'); +batch_fitting(strcat('/data/project/dti/For_William/rotateDWIv2/FreeWaterResults_WB/',int2str(PatientNumber(i)),'.NODDIroi.mat'),protocol,noddi,strcat('/data/project/dti/For_William/rotateDWIv2/FreeWaterResults_WB/',int2str(PatientNumber(i)),'.FittedParams.mat'),8); +SaveParamsAsNIfTI(strcat('/data/project/dti/For_William/rotateDWIv2/FreeWaterResults_WB/',int2str(PatientNumber(i)),'.FittedParams.mat'),strcat('/data/project/dti/For_William/rotateDWIv2/FreeWaterResults_WB/',int2str(PatientNumber(i)),'.NODDIroi.mat'),strcat('/data/project/dti/For_William/rotateDWIv2/brainMasks/',int2str(PatientNumber(i)),'.brainmask.nii'),strcat('/data/project/dti/For_William/rotateDWIv2/FreeWaterResults_WB/',int2str(PatientNumber(i)),'.noddi')) + +end diff --git a/importPPMIlist.m b/importPPMIlist.m new file mode 100644 index 0000000..0a381a8 --- /dev/null +++ b/importPPMIlist.m @@ -0,0 +1,45 @@ +%% Import data from text file. +% Script for importing data from the following text file: +% +% /data/project/dti/For_William/matlab/NODDI_toolbox_v1.0/rotateone.txt +% +% To extend the code to different selected data or a different text file, +% generate a function instead of a script. + +% Auto-generated by MATLAB on 2018/05/01 11:40:45 + +%% Initialize variables. +filename = 'rotateone.txt'; +delimiter = ','; + +%% Format for each line of text: +% column1: double (%f) +% column2: text (%s) +% For more information, see the TEXTSCAN documentation. +formatSpec = '%f%s%[^\n\r]'; + +%% Open the text file. +fileID = fopen(filename,'r'); + +%% Read columns of data according to the format. +% This call is based on the structure of the file used to generate this +% code. If an error occurs for a different file, try regenerating the code +% from the Import Tool. +dataArray = textscan(fileID, formatSpec, 'Delimiter', delimiter, 'TextType', 'string', 'ReturnOnError', false); + +%% Close the text file. +fclose(fileID); + +%% Post processing for unimportable data. +% No unimportable data rules were applied during the import, so no post +% processing code is included. To generate code which works for +% unimportable data, select unimportable cells in a file and regenerate the +% script. + +%% Allocate imported array to column variable names +VarName1 = dataArray{:, 1}; +rotate000I000R000Aashift4100S500L700P = cellstr(dataArray{:, 2}); + + +%% Clear temporary variables +clearvars filename delimiter formatSpec fileID dataArray ans; diff --git a/rotateone.txt b/rotateone.txt new file mode 100644 index 0000000..91bd27b --- /dev/null +++ b/rotateone.txt @@ -0,0 +1,151 @@ +3775, -rotate 0.00I 0.00R 0.00A -ashift 41.00S 5.00L -7.00P +3325, -rotate 2.00I -0.14R -4.00A -ashift 31.19S 8.35L -14.80P +3866, -rotate 3.00I 0.00R 0.00A -ashift 42.00S 11.98L -11.63P +3584, -rotate 10.00I 0.00R 0.00A -ashift 33.00S 8.24L -7.72P +3816, -rotate -3.00I 8.00R 0.00A -ashift 49.27S 3.99L -19.43P +3814, -rotate -4.00I 0.00R 0.00A -ashift 42.00S 6.40L -7.57P +3181, -rotate 0.00I 12.00R -2.00A -ashift 8.10S -2.72L 9.00P +3151, -rotate 0.00I 16.00R 0.00A -ashift 4.78S -2.00L 4.67P +3852, -rotate 0.00I 16.00R 0.00A -ashift 6.00S 2.50L 14.00P +3355, -rotate 0.00I 27.00R 0.00A -ashift 5.00S 0.00L 13.00P +3157, -rotate 0.00I 28.00R 0.00A -ashift 5.43S 0.00L 14.36P +3390, -rotate 0.00I 8.00R 0.00A -ashift 6.00S -2.50L 20.00P +3788, -rotate 0.00I 8.00R 0.00A -ashift 11.00S 2.00L 7.00P +3830, -rotate 0.17I 12.04R 3.88A -ashift 9.78S -0.05L -2.92P +3350, -rotate -0.22I 26.07R 4.59A -ashift 7.14S -2.61L 11.32P +3358, -rotate 0.25I 26.04R 2.25A -ashift 11.59S -0.76L 12.57P +3368, -rotate -0.31I 22.26R 6.69A -ashift 7.86S -1.99L 8.14P +3178, -rotate 0.35I 9.99R -2.03A -ashift 4S -2L 13P +3321, -rotate 0.35I 9.99R -2.03A -ashift 1.97S 1.00L 12.99P +3191, -rotate -0.42I 7.99R 4.03A -ashift 4.01S 0.43L 14.00P +3800, -rotate -0.46I 20.07R -1.03A -ashift 7S -1.74L -5.10P +3377, -rotate 0.47I 16.02R 1.79A -ashift 5.90S -3.24L 15.02P +3327, -rotate 0.47I 18.10R 4.68A -ashift 9.50S 1.00L 13.97P +3172, -rotate -0.55I 30.36R 5.45A -ashift 4.90S -2.98L 8.31P +3316, -rotate -0.68I 18.00R -0.05A -ashift 7.58S -2.13L 11.25P +4082, -rotate -0.77I 27.04R 1.23A -ashift 5.06S 3.45L 12.92P +4067, -rotate -0.81I 14.12R -4.65A -ashift 8.00S 0.00L 2.00P +3789, -rotate 0.81I 25.06R 2.38A -ashift 4.00S 2.42L 11.92P +3770, -rotate 0.82I 5.03R 2.01A -ashift 7.04S -3.00L 16.44P +3352, -rotate -0.94I 22.07R -4.43A -ashift 6.10S -1.27L 13.96P +3824, -rotate -0.95I 18.00R -0.32A -ashift 9.00S -1.96L 2.03P +3166, -rotate 0.96I 15.10R 3.87A -ashift 8S 1.19L 11.98P +3307, -rotate 0I 10R 0A -ashift 9S 0L 20P +3161, -rotate 0I 12R 0A -ashift 12.24S -4L 14.30P +3311, -rotate 0I 14R 0A -ashift 6.65S -4L 10.13P +3762, -rotate 0I 16R 0A -ashift 12S -5L 22P +3376, -rotate 0I 18R 0A -ashift 8.14S -1L 9.53P +3107, -rotate 0I 20R 0A -ashift 5S -4L 10P +3373, -rotate 0I 22R 0A -ashift 6S 0L 9P +3807, -rotate 0I 22R 0A -ashift 5S -2L 0P +3105, -rotate 0I 26R 0A -ashift 1.03S 2L 7.58P +3563, -rotate 0I 26R 0A -ashift -3S -3L 2P +3570, -rotate 0I 26R 0A -ashift -3S -3L 2P +3855, -rotate 0I 26R 1A -ashift 0S -0.50L 0P +3556, -rotate 0I 27R 0A -ashift 9.67S -0.56L 6.46P +3369, -rotate 0I 28R 0A -ashift 0S -2L 7P +3802, -rotate 0I 28R 0A -ashift -1S -2L -4P +3767, -rotate 0I 9R 0A -ashift 12.21S -0.5L 11.77P +3309, -rotate 1.00I 14.00R 1.00A -ashift 6.06S 2.50L 19.95P +3108, -rotate 1.03I 14R -0.25A -ashift 7.58S -1.79L 12.30P +3853, -rotate -1.04I 15.93R 3.29A -ashift -4.96S -2.59L -0.03P +3826, -rotate 1.08I 22R -0.4A -ashift 10S -2.48L 1.03P +3554, -rotate 1.10I 26R -0.34A -ashift 11.75S -1.50L 12.36P +3808, -rotate 1.11I 23.98R 0.19A -ashift 9.08S -3.18L 5P +3753, -rotate 1.25I 14.09R 3.09A -ashift 8.04S -1L 16.53P +3765, -rotate -1.25I 17.94R -1.75A -ashift 4.00S -1.58L 14.01P +3758, -rotate 1.27I 19.99R 2.13A -ashift 12.67S -2L 16.81P +3571, -rotate 1.29I 21.17R 4.20A -ashift 11S -1.5L 11.08P +3838, -rotate -1.76I 23.02R 1.75A -ashift 7.00S 0.98L -1.02P +3190, -rotate -1.90I 17.99R 1.35A -ashift 7.92S -3.79L 13.83P +3778, -rotate 1.92I 16.13R -3.43A -ashift 9.07S -1L 1.97P +3756, -rotate 10.06I 15.21R 3.06A -ashift 10S -0.5L 15.03P +3332, -rotate -10.12I 33.87R -2.13A -ashift 0.06S -2.99L 3.83P +3173, -rotate 13.42I 9.38R 8.65A -ashift 6.93S 2.78L 12.83P +3760, -rotate 1I 25R 0A -ashift 10.98S -3L 8.05P +3112, -rotate 2.00I 16.00R 0.00A -ashift 8.03S 0.00L -0.72P +3828, -rotate -2.00I 5.00R 0.00A -ashift 9.27S -3.00L 13.30P +3850, -rotate -2.03I 9.99R -1.65A -ashift 2.05S -1.93L 2.95P +3768, -rotate 2.04I 11.99R -0.43A -ashift 11S -0.58L 11.99P +3837, -rotate -2.07I 24.98R -2.21A -ashift 8.95S 2.00L 3.94P +3759, -rotate 2.08I 15.99R 1.43A -ashift 9.38S -2.83L 14.33P +3832, -rotate 2.14I 21.13R 4.23A -ashift 9.00S 0.00L 0.00P +3806, -rotate -2.31I 18R 1.05A -ashift 10S -3L 5P +3763, -rotate 2.44I 14.06R -1.63A -ashift 10.44S -2L 16.23P +3831, -rotate 2.45I 27.17R 2.45A -ashift 10.25S 3.99L 3.85P +3310, -rotate -2.47I 35.97R 1.45A -ashift 7.36S -3.90L -3.07P +3169, -rotate -2.49I 16.05R 2.51A -ashift -0.05S -2.58L 12.03P +3823, -rotate -2.50I 14.94R -0.80A -ashift 4.76S -4.71L 7.16P +3805, -rotate 2.53I 14.03R 1.81A -ashift 10.00S 0.00L 4.00P +3184, -rotate -2.60I 12.03R -2.83A -ashift 1.22S -3.27L 16.84P +4080, -rotate 2.74I 22.16R 4.39A -ashift 7.32S 1.00L 9.54P +3833, -rotate 2.91I 11.10R -2.56A -ashift 4.03S -1.00L -0.02P +3375, -rotate 2.93I 26.10R 4.79A -ashift 4.08S -4.50L 13P +4004, -rotate -2.98I 11R -1.19A -ashift -2.17S 6.06L 5.65P +4083, -rotate 2.98I 23.04R 2.09A -ashift 5.66S 1.37L 9.12P +3320, -rotate 2I 16R 0A -ashift 8.54S -1.00L 12.64P +3308, -rotate 2I 24R 0A -ashift 13.53S -3.5L 12.59P +3354, -rotate 2I 26R 2A -ashift 9.84S -3.34L 14.09P +3392, -rotate 3.00I 16.00R 1.00A -ashift 6.02S 1.00L 10.00P +3769, -rotate -3.00I 17.00R 0.00A -ashift 2.70S -1.00L 18.07P +3118, -rotate 3.02I 25.98R 4.22A -ashift 4.22S -2.15L 11.30P +3835, -rotate -3.09I 19.87R 3.19A -ashift 7.97S 2.00L 0.34P +3389, -rotate 3.15I 29.86R -4.04A -ashift 11.00S -0.69L 12.99P +3365, -rotate 3.22I 28.07R 3.52A -ashift 2.45S -1L 14.13P +3558, -rotate -3.25I 16.01R 1.75A -ashift -1.03S -0.88L 6.01P +3555, -rotate -3.28I 23.97R -1.33A -ashift 7S 0L 18.95P +3559, -rotate -3.36I 20R 1.06A -ashift 0.72S -4L 8.03P +3551, -rotate 3.37I 26.69R 0.47A -ashift -2.01S -0.14L -3.99P +3366, -rotate 3.46I 29.85R 1.74A -ashift 2.14S 1.99L 10.83P +3779, -rotate 3.56I 10.98R -0.62A -ashift 9.60S -0.6L 23.10P +3776, -rotate 3.73I 15.00R 1.04A -ashift 10.95S -2.50L 5.99P +3587, -rotate 3.79I 23.88R -1.74A -ashift 0.00S 2.00L 12.03P +3168, -rotate -3.84I 3R -3A -ashift 5.47S -2L 12.20P +3165, -rotate 3I 14.10R 4.12A -ashift 1S 0L 12P +3125, -rotate 3I 18R 0A -ashift 7.44S 2L 16.27P +3361, -rotate 3I 19R 0A -ashift 5.42S 0L 13.82P +3593, -rotate 4.00I 22.00R 1.00A -ashift 5.82S -1.60L 8.14P +3174, -rotate 4.15I 13.16R 3.41A -ashift 7.05S -0.54L 18.32P +3305, -rotate 4.19I 12.01R -0.81A -ashift 6.58S 0.80L 11.32P +3757, -rotate 4.19I 24.05R 1.11A -ashift 6.39S -1.36L 8.36P +3834, -rotate 4.24I 27.07R 5.42A -ashift 8.09S -0.07L 4.87P +3817, -rotate 4.36I 11.98R 3.07A -ashift 11.03S 0.50L 4.01P +3811, -rotate -4.41I 24.93R -2.14A -ashift 4.14S -1.99L 3.86P +3592, -rotate 4.43I 22.07R 1.98A -ashift 4.71S -0.78L 17.08P +3119, -rotate -4.45I 24R 1.09A -ashift 13S -0.5L 4P +3818, -rotate -4.57I 15.99R 2.08A -ashift 1.93S -3L 1.98P +3104, -rotate 4.66I 27.17R 1.47A -ashift -0.33S 0.22L 8.45P +3764, -rotate 4.72I 22R 1.75A -ashift 11S -1.33L 10.02P +4010, -rotate 4.74I 8.06R 1.74A -ashift 2.29S 6.61L 3.43P +3825, -rotate 4.86I 16.19R -3.12A -ashift 10.93S -2L 3.21P +3809, -rotate -4I 10R 0A -ashift 3.75S -2L 7.14P +3120, -rotate -4I 14R 0A -ashift 5.16S 1L 24.09P +3829, -rotate 4I 18R 0A -ashift 12.85S 0L 4.42P +3812, -rotate 4I 22R 0A -ashift 4S -1.5L 0.14P +3815, -rotate 5.00I 24.00R 0.00A -ashift 2.99S -2.50L 4.03P +3557, -rotate 5.02I 14.38R 3.86A -ashift 5S 0.71L 11.99P +3175, -rotate 5.26I 6.96R 6.04A -ashift 3.16S 0L 8.93P +3777, -rotate 5.41I 23.07R 3.90A -ashift 6.00S 0.00L 18.00P +4024, -rotate -5.43I 15.99R -2.08A -ashift -1.38S -9.94L 13.09P +3771, -rotate 5.53I 22.05R 1.35A -ashift 6.50S 0.52L 15.99P +3102, -rotate 5.64I 31.98R 3.25A -ashift 2.96S 3.45L 11.72P +3575, -rotate 5I 34R 0A -ashift -2.88S -5L 2.03P +3591, -rotate 6.08I 15.99R -0.57A -ashift 3.00S -1.27L 21.02P +3380, -rotate 6.33I 23.18R 6.27A -ashift 4.86S -2.17L 9P +3154, -rotate 6.41I 16.73R 5.20A -ashift 2.47S -3.99L 15.30P +3116, -rotate 6.55I 18.05R -1.45A -ashift 2.93S 2.58L 12.04P +3367, -rotate 6.59I 24.18R 6.59A -ashift 8.56S -4.60L 12.28P +3171, -rotate 6.5I 19R 0A -ashift 7.79S -3.5L 12.14P +3353, -rotate -6.62I 17.93R 5.26A -ashift 5.29S -4.00L 11.41P +3819, -rotate -6.65I 17.99R 2.10A -ashift 7.29S -2L 6.28P +3318, -rotate -6.67I 20.08R -3.53A -ashift 11.70S -3.38L 11.1P +3574, -rotate 6I 12R 0A -ashift 2S 4L 7P +4029, -rotate -6I 19R 0A -ashift 2.69S -7L 18.05P +3787, -rotate 7.03I 14.00R -0.25A -ashift 4.00S -0.95L 3.00P +3123, -rotate -7.19I 27.40R -9.36A -ashift 0.64S -3.58L 8.34P +3780, -rotate 7.25I 16.01R -0.75A -ashift 13.97S 1.70L 17.02P +3372, -rotate 7.27I 25.04R 1.27A -ashift 4S 0.28L 8P +3111, -rotate 8.06I 20.28R 5.07A -ashift 13.89S -3.98L 20.58P +3552, -rotate 8.15I 18.11R 5.66A -ashift 7.00S 0.52L 15.99P +3359, -rotate 9.44I 25.09R 5.01A -ashift 8.89S -3.10L 17.15P +3585, -rotate 9.78I 17.99R 0.40A -ashift 5.86S 6.02L 15.94P -- GitLab