├── .ipynb_checkpoints └── Parcellation_visualization-checkpoint.ipynb ├── Parcellation_visualization.html ├── Parcellation_visualization.ipynb ├── Parcellations ├── Maj_Card.nii ├── Maj_Eyes.nii ├── Maj_Movies.nii ├── Maj_N-back.nii ├── Maj_Rest1.nii ├── Maj_Rest2.nii ├── Maj_SST.nii ├── Maj_allTasks_4D_N8.nii └── Maj_gradCPT.nii ├── README.md ├── bis_individualizeconnectivity.tcl ├── images └── node_parcellation_alg.png ├── vtkbisIndividualizeParcellation.cpp └── vtkbisIndividualizeParcellation.h /Parcellations/Maj_Card.nii: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YaleMRRC/Node-Parcellation/1240d7decf674c72210f56e9776dfe9ed2ec7e83/Parcellations/Maj_Card.nii -------------------------------------------------------------------------------- /Parcellations/Maj_Eyes.nii: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YaleMRRC/Node-Parcellation/1240d7decf674c72210f56e9776dfe9ed2ec7e83/Parcellations/Maj_Eyes.nii -------------------------------------------------------------------------------- /Parcellations/Maj_Movies.nii: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YaleMRRC/Node-Parcellation/1240d7decf674c72210f56e9776dfe9ed2ec7e83/Parcellations/Maj_Movies.nii -------------------------------------------------------------------------------- /Parcellations/Maj_N-back.nii: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YaleMRRC/Node-Parcellation/1240d7decf674c72210f56e9776dfe9ed2ec7e83/Parcellations/Maj_N-back.nii -------------------------------------------------------------------------------- /Parcellations/Maj_Rest1.nii: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YaleMRRC/Node-Parcellation/1240d7decf674c72210f56e9776dfe9ed2ec7e83/Parcellations/Maj_Rest1.nii -------------------------------------------------------------------------------- /Parcellations/Maj_Rest2.nii: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YaleMRRC/Node-Parcellation/1240d7decf674c72210f56e9776dfe9ed2ec7e83/Parcellations/Maj_Rest2.nii -------------------------------------------------------------------------------- /Parcellations/Maj_SST.nii: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YaleMRRC/Node-Parcellation/1240d7decf674c72210f56e9776dfe9ed2ec7e83/Parcellations/Maj_SST.nii -------------------------------------------------------------------------------- /Parcellations/Maj_allTasks_4D_N8.nii: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YaleMRRC/Node-Parcellation/1240d7decf674c72210f56e9776dfe9ed2ec7e83/Parcellations/Maj_allTasks_4D_N8.nii -------------------------------------------------------------------------------- /Parcellations/Maj_gradCPT.nii: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YaleMRRC/Node-Parcellation/1240d7decf674c72210f56e9776dfe9ed2ec7e83/Parcellations/Maj_gradCPT.nii -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Node-Parcellation 2 | 3 |

4 | 5 |

6 | 7 | 8 | 9 | This is the documentation file for **spatially-constrained exemplar-based node parcellation** of the human brain at the individual- and state-specific level. For more details, please see Salehi et al., 2017 [1] and Salehi et al., 2018 [2]. 10 | 11 | The parcellation algorithm is implemented in C++, and is part of the open-source BioImage Suite Project. To run these files, you need to download BioImageSuite source code from [here](https://www.nitrc.org/projects/bioimagesuite). After downloading BioImage Suite source code (under the name "bioimagesuite32_0b1_src"), you can run the individualized parcellation algorithm via the following: 12 | 13 | 1. Move the file 'vtkbisIndividualizeParcellation.cpp' to '/bioimagesuite32_0b1_src/Connectivity/' 14 | 15 | 2. Move the file 'bis_individualizeconnectivity.tcl' to '/bioimagesuite32_0b1_src/bioimagesuite/bis_algorithm/' 16 | 17 | 3. Build the package following the steps in the BioImageSuite mannual (see [here](http://bioimagesuite.yale.edu/manual/index.aspx)) 18 | 19 | 4. Make sure you set the environment path, by running the following command: 20 | ```bash 21 | source bioimagesuite32_0b1_src/build/setpaths.csh 22 | ``` 23 | 5. Execute the the individualzied parcellation algorithm using the following command: 24 | ``` bash 25 | bis_individualizeconnectivity.tcl -inp $input -inp2 $parc -indiv_group 1 -blursigma $BW -num_exemplar $K 26 | ``` 27 | 28 | - **$input** is the .nii file containing the voxel-level time series. 29 | 30 | - **$parc** is the initial group-level parcellation that the algorihtm starts from. Please refer to the manuscript for more details. 31 | 32 | - **indiv_group** option should be set to **1** to generate individualized parcellations, as well as the functional connectivity matrices using the individualize partcellations. If set to **0**, it will only output the functional connectivity matrices, using initial group-level parcellation. 33 | 34 | - **$BW** is the smoothing kernel's bandwidth. In the original work, we set **BW=4**. 35 | 36 | - **$K** is the number of nodes in the parcellation. **K** should match the group-level parcellation. Here we used the parcelation by Shen et al. [3], where **K=268** for whole brain analysis, and **K=188** for cortical analysis. 37 | 38 | For further questions please raise an issue [here](https://github.com/YaleMRRC/Node-Parcellation/issues). 39 | 40 | 41 | ### References 42 | 43 | [1] Salehi, M., Karbasi, A., Scheinost, D., & Constable, R. T. (2017, September). A submodular approach to create individualized parcellations of the human brain. In International Conference on Medical Image Computing and Computer-Assisted Intervention (pp. 478-485). Springer, Cham. 44 | 45 | [2] Salehi, M., Greene, A. S., Karbasi, A., Shen, X., Scheinost, D., & Constable, R. T. (2018). There is no single functional atlas even for a single individual: Parcellation of the human brain is state dependent. bioRxiv, 431833. 46 | 47 | [3] Shen, X., Tokoglu, F., Papademetris, X., & Constable, R. T. (2013). Groupwise whole-brain parcellation from resting-state fMRI data for network node identification. Neuroimage, 82, 403-415. 48 | 49 | -------------------------------------------------------------------------------- /bis_individualizeconnectivity.tcl: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # the next line restarts using wish \ 3 | exec vtk "$0" -- "$@" 4 | 5 | #BIOIMAGESUITE_LICENSE --------------------------------------------------------------------------------- 6 | #BIOIMAGESUITE_LICENSE This file is part of the BioImage Suite Software Package. 7 | #BIOIMAGESUITE_LICENSE 8 | #BIOIMAGESUITE_LICENSE X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H 9 | #BIOIMAGESUITE_LICENSE Staib. BioImage Suite: An integrated medical image analysis suite, Section 10 | #BIOIMAGESUITE_LICENSE of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of 11 | #BIOIMAGESUITE_LICENSE Medicine, http:#www.bioimagesuite.org. 12 | #BIOIMAGESUITE_LICENSE 13 | #BIOIMAGESUITE_LICENSE This program is free software; you can redistribute it and/or 14 | #BIOIMAGESUITE_LICENSE modify it under the terms of the GNU General Public License version 2 15 | #BIOIMAGESUITE_LICENSE as published by the Free Software Foundation. 16 | #BIOIMAGESUITE_LICENSE 17 | #BIOIMAGESUITE_LICENSE This program is distributed in the hope that it will be useful, 18 | #BIOIMAGESUITE_LICENSE but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | #BIOIMAGESUITE_LICENSE MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 | #BIOIMAGESUITE_LICENSE GNU General Public License for more details. 21 | #BIOIMAGESUITE_LICENSE 22 | #BIOIMAGESUITE_LICENSE You should have received a copy of the GNU General Public License 23 | #BIOIMAGESUITE_LICENSE along with this program; if not, write to the Free Software 24 | #BIOIMAGESUITE_LICENSE Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 25 | #BIOIMAGESUITE_LICENSE See also http:#www.gnu.org/licenses/gpl.html 26 | #BIOIMAGESUITE_LICENSE 27 | #BIOIMAGESUITE_LICENSE If this software is modified please retain this statement and add a notice 28 | #BIOIMAGESUITE_LICENSE that it had been modified (and by whom). 29 | #BIOIMAGESUITE_LICENSE 30 | #BIOIMAGESUITE_LICENSE ----------------------------------------------------------------------------------- 31 | 32 | lappend auto_path [ file dirname [ info script ]] 33 | lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] base] 34 | lappend auto_path [file join [file join [ file dirname [ info script ]] ".." ] apps] 35 | 36 | package require bis_dualimagetransformationalgorithm 1.0 37 | package require bis_smoothimage 1.0 38 | package provide bis_individualizeconnectivity 1.0 39 | package require bis_matrixcorrelation 1.0 40 | package require bis_roimean 1.0 41 | 42 | itcl::class bis_individualizeconnectivity { 43 | 44 | inherit bis_dualimagetransformationalgorithm 45 | 46 | constructor { } { 47 | $this Initialize 48 | } 49 | 50 | public method Initialize { } 51 | public method Execute { } 52 | 53 | public method GetGUIName { } { return "Individualize"} 54 | } 55 | 56 | # ----------------------------------------------------------------------------------------- 57 | # Initialize 58 | # ---------------------------------------------------------------------------------------- 59 | 60 | itcl::body bis_individualizeconnectivity::Initialize { } { 61 | 62 | PrintDebug "bis_individualizeconnectivity::Initialize" 63 | 64 | set options { 65 | { num_exemplar "Number of exemplars" "Start T" { integer default } 268 { 1 1000000 } 9 } 66 | { blursigma "kernel size [mm/voxel] of FWHM filter size" "Filter Size" { real triplescale 100 } 6.0 { 0.0 20.0 } 0 } 67 | { indiv_group "Individualized 1 or group 0 parcellation" "Do Indiv" boolean 1 {0 1} 0 } 68 | { hemisphere "Whether to do each hemisphere separately 1 or the whole brain together 0" "do single hemi" boolean 1 {0 1} 0 } 69 | { lambda "The relative importance of functional and spatial distances (dist = lambda*fxn + (1-lambda)*xyz)" "lambda" { real triplescale 100 } 1 { 0 1 } 0 } 70 | } 71 | 72 | set defaultsuffix { "_individ" } 73 | set scriptname bis_individualizeconnectivity 74 | 75 | set description "Calculate individualized parcellations." 76 | set description2 "Calculate individualized parcellations starting from a group-level parcellation." 77 | set backwardcompatibility "" 78 | set authors "mehraveh.salehi@yale.edu" 79 | 80 | set category "Functional Imaging" 81 | 82 | 83 | $this InitializeDualImageTransformationAlgorithm 84 | } 85 | 86 | # ---------------------------------------------------------------------------------------- 87 | # Execute 88 | # ---------------------------------------------------------------------------------------- 89 | 90 | itcl::body bis_individualizeconnectivity::Execute { } { 91 | 92 | set ok [ pxtclvtkpxcontrib::ConditionalLoadLibrary vtkbisConnectivityTCL vtkbisROICorrelation 0 ] 93 | if { $ok == 0 } { 94 | set errormessage "Failed to load library vtkbisConnectivityTCL" 95 | return 0 96 | } 97 | 98 | set num_exemplar [ $OptionsArray(num_exemplar) GetValue ] 99 | set image_in [ $InputsArray(input_image) GetObject ] 100 | set blursigma [ $OptionsArray(blursigma) GetValue ] 101 | set hemisphere [ $OptionsArray(hemisphere) GetValue ] 102 | set lambda [ $OptionsArray(lambda) GetValue ] 103 | set indiv_group [ $OptionsArray(indiv_group) GetValue ] 104 | set indiv [ $this GetOutput ] 105 | set group [ $this GetSecondInput ] 106 | 107 | 108 | set tmpname0 [ $InputsArray(input_image) GetFileName ] 109 | # puts stderr "extension = [file extension $tmpname0]" 110 | if { [ file extension $tmpname0 ] == ".gz" } { set tmpname0 [ file rootname $tmpname0 ] } 111 | if { [ file extension $tmpname0 ] == ".nii" } { set tmpname0 [ file rootname $tmpname0 ] } 112 | # puts stderr "extension = [file extension $tmpname0]" 113 | 114 | 115 | set tmpname ${tmpname0}_WHOLEBRAIN 116 | if { $num_exemplar == 188 } { set tmpname ${tmpname0}_CORTICAL } 117 | 118 | if { $indiv_group == 1 } { set ig "indiv" } 119 | if { $indiv_group == 0 } { set ig "group" } 120 | 121 | if { $hemisphere == 1 } { set hem "" } 122 | if { $hemisphere == 0 } { set hem "WBtogether" } 123 | 124 | ############################## From here gets commented to generate group parcellation connectivities ################################## 125 | 126 | if { $indiv_group == 1 } { 127 | # Step 1 ... Invoke bis_smoothimage ----- 128 | set smooth_alg [bis_smoothimage [pxvtable::vnewobj]] 129 | $smooth_alg InitializeFromContainer $this 130 | $smooth_alg SetInput $image_in 131 | $smooth_alg SetOptionValue blursigma $blursigma 132 | $smooth_alg SetOptionValue unit "mm" 133 | $smooth_alg Execute 134 | 135 | if { $blursigma > 0 } { 136 | set smimage [ [ $smooth_alg GetOutput ] GetImage ] 137 | } 138 | set individualize [ vtkbisIndividualizeParcellation [ pxvtable::vnewobj ]] 139 | if { $blursigma > 0 } { 140 | $individualize SetFMRIImage $smimage 141 | } 142 | if { $blursigma == 0 } { 143 | puts stdout "No smoothing!" 144 | $individualize SetFMRIImage [$image_in GetImage] 145 | } 146 | $individualize SetInput [ $group GetObject ] 147 | $individualize SetNumberOfExemplars $num_exemplar 148 | $individualize SetHemisphere $hemisphere 149 | $individualize SetIndivGroup $indiv_group 150 | $individualize SetLambda $lambda 151 | $individualize Update 152 | 153 | $indiv ShallowCopyImage [ $individualize GetOutput ] 154 | $indiv CopyImageHeader [ $image_in GetImageHeader ] 155 | 156 | set comment [ format " [ $this GetCommandLine full ]" ] 157 | [ $indiv GetImageHeader ] AddComment "$comment $Log" 0 158 | 159 | $indiv SetFileName ${tmpname}_parcellation_${ig}_Priority_AllNorm1_lambda${lambda}.nii.gz 160 | puts stderr "Indiv Description = [ $indiv GetDescription ]" 161 | 162 | $individualize Delete 163 | itcl::delete object $smooth_alg 164 | } 165 | ############################### Until here gets commented to generate group parcellation connectivities ############################## 166 | 167 | set roimean_alg [ bis_roimean \#auto ] 168 | $roimean_alg InitializeFromContainer 0 $this 169 | $roimean_alg SetInput $image_in 170 | if { $indiv_group == 1 } { $roimean_alg SetSecondInput $indiv } 171 | if { $indiv_group == 0 } { $roimean_alg SetSecondInput $group } 172 | $roimean_alg SetOptionValue dotextfile 1 173 | $roimean_alg SetOptionValue filename ${tmpname}_roimean_Priority_AllNorm1_lambda${lambda}.txt 174 | $roimean_alg SetOptionValue filename2 ${tmpname}_xyzCoordinate_Priority_AllNorm1_lambda${lambda}.txt 175 | $roimean_alg Execute 176 | 177 | # if { $dosave == 1 } { 178 | set tmpname1 ${tmpname}_roimean_Priority_AllNorm1_lambda${lambda}.nii.gz 179 | [ $roimean_alg GetOutput ] Save $tmpname1 180 | puts stdout "ROI Mean saved in $tmpname1" 181 | # } 182 | 183 | 184 | set corr [ bis_matrixcorrelation \#auto ] 185 | $corr InitializeFromContainer 0 $this 186 | $corr SetInput [ $roimean_alg GetOutput ] 187 | $corr SetOptionValue dotextfile 1 188 | $corr SetOptionValue filename ${tmpname}_matrix_Priority_AllNorm1_lambda${lambda}.txt 189 | $corr SetOptionValue filename2 ${tmpname}_outputForConnectivityViewer_Priority_AllNorm1_lambda${lambda}.txt 190 | $corr Execute 191 | 192 | 193 | 194 | return 1 195 | } 196 | 197 | 198 | # ----------------------------------------------------------------------------------------- 199 | # This checks if executable is called (in this case bis_individualizeconnectivity.tcl) if it is execute 200 | # ---------------------------------------------------------------------------------------- 201 | 202 | if { [ file rootname $argv0 ] == [ file rootname [ info script ] ] } { 203 | # this is essentially the main function 204 | 205 | 206 | set alg [bis_individualizeconnectivity [pxvtable::vnewobj]] 207 | $alg MainFunction 208 | } 209 | 210 | -------------------------------------------------------------------------------- /images/node_parcellation_alg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/YaleMRRC/Node-Parcellation/1240d7decf674c72210f56e9776dfe9ed2ec7e83/images/node_parcellation_alg.png -------------------------------------------------------------------------------- /vtkbisIndividualizeParcellation.cpp: -------------------------------------------------------------------------------- 1 | //BIOIMAGESUITE_LICENSE --------------------------------------------------------------------------------- 2 | //BIOIMAGESUITE_LICENSE This file is part of the BioImage Suite Software Package. 3 | //BIOIMAGESUITE_LICENSE 4 | //BIOIMAGESUITE_LICENSE X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H 5 | //BIOIMAGESUITE_LICENSE Staib. BioImage Suite: An integrated medical image analysis suite, Section 6 | //BIOIMAGESUITE_LICENSE of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of 7 | //BIOIMAGESUITE_LICENSE Medicine, http://www.bioimagesuite.org. 8 | //BIOIMAGESUITE_LICENSE 9 | //BIOIMAGESUITE_LICENSE This program is free software; you can redistribute it and/or 10 | //BIOIMAGESUITE_LICENSE modify it under the terms of the GNU General Public License version 2 11 | //BIOIMAGESUITE_LICENSE as published by the Free Software Foundation. 12 | //BIOIMAGESUITE_LICENSE 13 | //BIOIMAGESUITE_LICENSE This program is distributed in the hope that it will be useful, 14 | //BIOIMAGESUITE_LICENSE but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | //BIOIMAGESUITE_LICENSE MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | //BIOIMAGESUITE_LICENSE GNU General Public License for more details. 17 | //BIOIMAGESUITE_LICENSE 18 | //BIOIMAGESUITE_LICENSE You should have received a copy of the GNU General Public License 19 | //BIOIMAGESUITE_LICENSE along with this program; if not, write to the Free Software 20 | //BIOIMAGESUITE_LICENSE Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | //BIOIMAGESUITE_LICENSE See also http://www.gnu.org/licenses/gpl.html 22 | //BIOIMAGESUITE_LICENSE 23 | //BIOIMAGESUITE_LICENSE If this software is modified please retain this statement and add a notice 24 | //BIOIMAGESUITE_LICENSE that it had been modified (and by whom). 25 | //BIOIMAGESUITE_LICENSE 26 | //BIOIMAGESUITE_LICENSE ----------------------------------------------------------------------------------- 27 | 28 | 29 | 30 | #include "vtkbisIndividualizeParcellation.h" 31 | #include "vtkObjectFactory.h" 32 | #include "vtkImageData.h" 33 | #include "vtkPointData.h" 34 | #include "vtkDataArray.h" 35 | #include "pxisinf.h" 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | 43 | #include "Eigen/Dense" 44 | #include "Eigen/Sparse" 45 | using Eigen::MatrixXd; 46 | using Eigen::VectorXd; 47 | using Eigen::VectorXi; 48 | using Eigen::Map; 49 | #include "igl/slice.h" 50 | #include "igl/colon.h" 51 | #include "igl/mat_min.h" 52 | #include "igl/mat_max.h" 53 | #include "igl/find.h" 54 | using igl::slice; 55 | using igl::colon; 56 | using igl::mat_min; 57 | using igl::mat_max; 58 | using igl::find; 59 | 60 | 61 | // This creates the "New" Function 62 | vtkStandardNewMacro(vtkbisIndividualizeParcellation); 63 | 64 | // Construct object to extract all of the input data. 65 | vtkbisIndividualizeParcellation::vtkbisIndividualizeParcellation() 66 | { 67 | this->NumberOfExemplars=268; 68 | this->FMRIImage=NULL; 69 | this->Hemisphere=1; 70 | this->Lambda=1; 71 | } 72 | vtkbisIndividualizeParcellation::~vtkbisIndividualizeParcellation() 73 | { 74 | this->FMRIImage=NULL; 75 | } 76 | 77 | // --------------------------------------------------------------------------- 78 | //input=group level parcellation 79 | //output=individualize parcellation 80 | 81 | bool isAnyFalse(std::vector &v) 82 | { 83 | for (int i=0; iGetDimensions(dim); 93 | int slicesize=dim[0]*dim[1]; 94 | int index=0; 95 | double d[3]; 96 | 97 | for (int ic=-1;ic<=1;ic++) 98 | { 99 | for (int ib=-1;ib<=1;ib++) 100 | { 101 | for (int ia=-1;ia<=1;ia++) 102 | { 103 | if ((ia+ib+ic==1 || ia+ib+ic==-1) && (ia==0 || ib==0 || ic==0)) 104 | { 105 | // fprintf(stderr,"(%d, %d, %d)\n", ia, ib, ic); 106 | incr[index]=ia+ib*dim[0]+ic*slicesize; 107 | ++index; 108 | } 109 | } 110 | } 111 | } 112 | 113 | 114 | return 1; 115 | } 116 | 117 | bool vtkbisIndividualizeParcellation::ismember(VectorXi V, int p) 118 | { 119 | for (int i=0;iFMRIImage!=NULL) 135 | { 136 | this->FMRIImage->GetDimensions(dim); 137 | input->GetDimensions(dim2); 138 | fprintf(stderr,"fMRI Image dim = %dx%dx%d\n",dim[0],dim[1],dim[2]); 139 | fprintf(stderr,"input Image dim = %dx%dx%d\n",dim2[0],dim2[1],dim2[2]); 140 | int sum=0; 141 | for (int ia=0;ia<=2;ia++) 142 | sum+=abs(dim[ia]-dim2[ia]); 143 | if (sum>0) 144 | { 145 | fprintf(stderr,"Bad FMRI Input to vtkbisIndividualizeParcellation SimpleExecute - sum = %d\n",sum); 146 | return; 147 | } 148 | } 149 | else 150 | { 151 | fprintf(stderr,"Bad FMRI Input to vtkbisIndividualizeParcellation SimpleExecute - Null image\n"); 152 | return; 153 | } 154 | 155 | 156 | vtkDataArray* group=input->GetPointData()->GetScalars(); 157 | int N=group->GetNumberOfTuples(); //nt 158 | 159 | vtkDataArray* indiv=output->GetPointData()->GetScalars(); 160 | indiv->FillComponent(0,0.0); 161 | 162 | vtkDataArray* fmri=this->FMRIImage->GetPointData()->GetScalars(); 163 | const int t=this->FMRIImage->GetNumberOfScalarComponents(); //nc 164 | 165 | double range[2]; 166 | group->GetRange(range); 167 | 168 | int Pmax = this->NumberOfExemplars; // Whole brain = 268, Cortical = 188 169 | double lambda = this->Lambda; 170 | 171 | if (Pmax != range[1]){ 172 | fprintf(stderr,"Bad Group Parcellation Input to vtkbisIndividualizeParcellation SimpleExecute - pmax = %d, range[1] = %d\n",Pmax,range[1]); 173 | return; 174 | } 175 | 176 | fprintf(stderr,"number of frames is %d\n",t); 177 | fprintf(stderr,"number of voxels is %d x %d x %d = %d\n",dim[0],dim[1],dim[2],N); 178 | fprintf(stderr,"number of exemplars is %d\n",Pmax); 179 | fprintf(stderr,"lambda is %f\n",lambda); 180 | 181 | fprintf(stderr,"START: the elapsed time is = %f s \n",float(clock()-begin_time)/CLOCKS_PER_SEC); 182 | 183 | 184 | 185 | // Copying data to matrixXd and VectorXd 186 | 187 | const clock_t timebegin1 = clock(); 188 | int count=0; 189 | 190 | for (int voxel=0;voxelGetComponent(voxel,0)>0) 192 | count++; 193 | 194 | MatrixXd X(t,count); 195 | count=0; 196 | double position[3]; 197 | 198 | for (int voxel=0;voxelGetComponent(voxel,0)>0) 202 | { 203 | input->GetPoint(voxel,position); 204 | for (int frame=0;frameGetComponent(voxel,frame); 206 | count++; 207 | } 208 | } 209 | 210 | 211 | 212 | VectorXd parcel(count); 213 | std::unordered_map ntoNvoxel; 214 | std::unordered_map Ntonvoxel; 215 | count=0; 216 | for (int voxel=0;voxelGetComponent(voxel,0)>0) 218 | { 219 | parcel(count) = group->GetComponent(voxel,0); // this is the group label for all the nonzero voxels 220 | ntoNvoxel.insert( std::make_pair(count,voxel) ); 221 | Ntonvoxel.insert( std::make_pair(voxel,count) ); 222 | count++; 223 | } 224 | 225 | int n = count; 226 | 227 | fprintf(stderr,"COPYING DATA TO EIGEN MATRIX & VECTOR: the elapsed time is = %f s \n",float(clock()-timebegin1)/CLOCKS_PER_SEC); 228 | fprintf(stderr,"number of non-zero voxels n = %d\n",n); 229 | 230 | 231 | 232 | const clock_t timebegin11 = clock(); 233 | 234 | VectorXd mean_subtract(t); 235 | mean_subtract = (X.rowwise().sum())/double(n); 236 | 237 | 238 | // Normalizing data points to 0 mean 239 | double newValue; 240 | MatrixXd V = MatrixXd(t,n); 241 | V = X.colwise()-mean_subtract; // mean of V is all 0 [VERIFIED] 242 | 243 | 244 | 245 | // Calculating the l2-norm 246 | VectorXd twoNorm(n); 247 | twoNorm =V.colwise().norm(); 248 | VectorXd inverse_twoNorm(n); 249 | inverse_twoNorm = twoNorm.array().inverse(); 250 | 251 | //////////////////////////////////////////////// 1- Dividing with the maximum norm 252 | //// finding the maximum value in the array 253 | // double maxValue = twoNorm.maxCoeff(); 254 | //// Normalizing data points to a unit ball sphere 255 | // MatrixXd v = V/maxValue; 256 | // fprintf(stderr,"NORMALIZATION INTO UNIT SPHERE (DIVIDE BY MAX NORM): the elapsed time is = %f s \n",float(clock()-timebegin11)/CLOCKS_PER_SEC); 257 | 258 | //////////////////////////////////////////////// 2- Normalizing to the unit norm (all vectors norm = 1) 259 | MatrixXd v = V.array().rowwise()* inverse_twoNorm.transpose().array(); 260 | twoNorm = v.colwise().norm(); // twoNorm is all 1 [VERIFIED] 261 | 262 | // VectorXd test_ii(t); 263 | // test_ii = (V.rowwise().sum())/double(n); 264 | // for (int ii=0; ii > indice_p; 275 | std::vector p_vector; 276 | for (int p=0;p sqrDist; 295 | MatrixXd D; 296 | VectorXi R(t); 297 | 298 | colon(0,1,t-1,R); 299 | 300 | 301 | for (int p=0;p C(ptr,psize); 307 | MatrixXd vP(t,psize); 308 | slice(v,R,C,vP); 309 | sqrMatrix = ((vP.transpose()*vP*-2).colwise() + vP.colwise().squaredNorm().transpose()).rowwise() + vP.colwise().squaredNorm(); 310 | 311 | 312 | sqrDist.push_back( sqrMatrix ); 313 | } 314 | 315 | fprintf(stderr,"SQUARED DISTANCES: the elapsed time is = %f s \n",float(clock()-timebegin3)/CLOCKS_PER_SEC); 316 | 317 | 318 | // Calculating the distance between auxiliary exemplar and the rest of the voxels 319 | const clock_t timebegin4 = clock(); 320 | 321 | std::vector e0sqrDist; 322 | VectorXd e0 = VectorXd::Zero(t); 323 | e0(0) = 3; 324 | 325 | 326 | 327 | for (int p=0;p C(ptr,psize); 333 | MatrixXd vP(t,psize); 334 | slice(v,R,C,vP); 335 | sqrArray = ((vP.transpose()*e0*-2).colwise() + vP.colwise().squaredNorm().transpose()).rowwise() + e0.colwise().squaredNorm(); 336 | 337 | 338 | e0sqrDist.push_back( sqrArray ); 339 | 340 | 341 | // delete [] sqrArray; 342 | } 343 | // for (int pp1=0;pp1::const_iterator voxelN = ntoNvoxel.find (Sopt(p)); 368 | if (voxelN != ntoNvoxel.end()) 369 | SoptN(p) = voxelN->second; 370 | } 371 | 372 | fprintf(stderr,"EXEMPLAR IDENTIFICATION: the elapsed time is = %f s \n",float(clock()-timebegin5)/CLOCKS_PER_SEC); 373 | 374 | // for (int p=0; pGetComponent(SoptN(p),0),SoptN(p)); 376 | 377 | // Assigning each voxel to the closest exemplar using the priority queue algorithm 378 | 379 | 380 | 381 | 382 | 383 | 384 | const clock_t timebegin6 = clock(); 385 | std::vector label(n,-1); 386 | 387 | // minDistIndexR and minDistIndexL need to be double, otherwise the result differs from MATLAB. It is perhaps because of the SetComponent() command. 388 | 389 | MatrixXd vSopt(t,Pmax); 390 | slice(v,R,Sopt,vSopt); 391 | 392 | MatrixXd distvSopt(n,Pmax); 393 | 394 | distvSopt = ((v.transpose()*vSopt*-2).colwise() + v.colwise().squaredNorm().transpose()).rowwise() + vSopt.colwise().squaredNorm(); 395 | 396 | dim[3]; input->GetDimensions(dim); 397 | const unsigned int neighbors = 6; 398 | int incr[neighbors]; this->ComputeMRFIncrements(input,incr); 399 | 400 | int sumVisited = 0; 401 | std::vector VISITED(n,0); 402 | 403 | 404 | // Assigning labels to exemplars and marking them as visited 405 | for (int p=0; p , std::vector >, std::greater > > > exemplar_min_heaps (Pmax); 412 | for (int p=0; pGetComponent(currVoxN,0)>0) 420 | { 421 | std::unordered_map::const_iterator voxeln = Ntonvoxel.find (currVoxN); 422 | if (voxeln != Ntonvoxel.end()) 423 | { 424 | int currVox = voxeln->second; 425 | exemplar_min_heaps[p].push(std::make_pair(distvSopt(currVox,p),currVox)); 426 | } 427 | } 428 | } 429 | } 430 | 431 | 432 | while (sumVisited < n) 433 | { 434 | int min_idx = -1; 435 | double min_val = 10000000; 436 | for (int p=0; p curNode = exemplar_min_heaps[p].top(); 441 | if (curNode.first < min_val) 442 | { 443 | min_val = curNode.first; // all distances <=4 [VERIFIED] 444 | min_idx = p; 445 | } 446 | } 447 | 448 | } 449 | // selected exemplar queue (min_idx) is correct [VERIFIED] 450 | // fprintf(stderr,"\n(selected queue,min_val)=(%d,%f)\n",min_idx,min_val); 451 | 452 | if (min_idx >=0) 453 | { 454 | std::pair chosenNode = exemplar_min_heaps[min_idx].top(); 455 | exemplar_min_heaps[min_idx].pop(); 456 | int chosenVoxel = chosenNode.second; 457 | if (VISITED[chosenVoxel] == 0) 458 | { 459 | label[chosenVoxel] = min_idx; 460 | VISITED[chosenVoxel] = 1; 461 | sumVisited ++; 462 | // fprintf(stderr,"number of visited = %d\n", sumVisited); 463 | std::unordered_map::const_iterator voxelN = ntoNvoxel.find (chosenVoxel); 464 | if (voxelN != ntoNvoxel.end()) 465 | { 466 | int chosenVoxelN = voxelN->second; 467 | // if(NONBOUNDARY[chosenVoxelN] == 1) 468 | for (int ia=0;iaGetComponent(currVoxN,0)>0) 472 | { 473 | std::unordered_map::const_iterator voxeln = Ntonvoxel.find (currVoxN); 474 | if (voxeln != Ntonvoxel.end()) 475 | { 476 | int currVox = voxeln->second; 477 | if (VISITED[currVox] == 0){ 478 | exemplar_min_heaps[min_idx].push(std::make_pair(distvSopt(currVox,min_idx),currVox)); 479 | } 480 | } 481 | } 482 | } 483 | } 484 | } 485 | 486 | } 487 | /* testing the order of elements in the priority queue is from smallest dist to largest dist [VERIFIED] 488 | std::queue > tteesstt; 489 | for (int ii=0;ii testNode = exemplar_min_heaps[min_idx].top(); 492 | tteesstt.push(testNode); 493 | exemplar_min_heaps[min_idx].pop(); 494 | fprintf(stderr,"(%d,%f), ",testNode.second,testNode.first); 495 | } 496 | fprintf(stderr,"next...\n"); 497 | */ 498 | 499 | if (min_idx < 0) 500 | break; 501 | } 502 | 503 | fprintf(stderr,"ASSIGNING VOXELS TO EXEMPLARS: the elapsed time is = %f s \n",float(clock()-timebegin6)/CLOCKS_PER_SEC); 504 | 505 | const clock_t timebegin7 = clock(); 506 | int Voxel_indices[N]; 507 | count = 0; 508 | 509 | for (int voxel=0;voxelGetComponent(voxel,0)>0) 512 | { 513 | std::unordered_map::const_iterator voxeln = Ntonvoxel.find (voxel); 514 | if (voxeln != Ntonvoxel.end()) 515 | { 516 | int finalvoxeln = voxeln->second; 517 | indiv->SetComponent(voxel,0,label[finalvoxeln]+1); 518 | } 519 | } 520 | else 521 | { 522 | indiv->SetComponent(voxel,0,0); 523 | } 524 | 525 | } 526 | fprintf(stderr,"WRITING IMAGE: the elapsed time is = %f s \n",float(clock()-timebegin7)/CLOCKS_PER_SEC); 527 | 528 | 529 | } 530 | -------------------------------------------------------------------------------- /vtkbisIndividualizeParcellation.h: -------------------------------------------------------------------------------- 1 | //BIOIMAGESUITE_LICENSE --------------------------------------------------------------------------------- 2 | //BIOIMAGESUITE_LICENSE This file is part of the BioImage Suite Software Package. 3 | //BIOIMAGESUITE_LICENSE 4 | //BIOIMAGESUITE_LICENSE X. Papademetris, M. Jackowski, N. Rajeevan, H. Okuda, R.T. Constable, and L.H 5 | //BIOIMAGESUITE_LICENSE Staib. BioImage Suite: An integrated medical image analysis suite, Section 6 | //BIOIMAGESUITE_LICENSE of Bioimaging Sciences, Dept. of Diagnostic Radiology, Yale School of 7 | //BIOIMAGESUITE_LICENSE Medicine, http://www.bioimagesuite.org. 8 | //BIOIMAGESUITE_LICENSE 9 | //BIOIMAGESUITE_LICENSE This program is free software; you can redistribute it and/or 10 | //BIOIMAGESUITE_LICENSE modify it under the terms of the GNU General Public License version 2 11 | //BIOIMAGESUITE_LICENSE as published by the Free Software Foundation. 12 | //BIOIMAGESUITE_LICENSE 13 | //BIOIMAGESUITE_LICENSE This program is distributed in the hope that it will be useful, 14 | //BIOIMAGESUITE_LICENSE but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | //BIOIMAGESUITE_LICENSE MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | //BIOIMAGESUITE_LICENSE GNU General Public License for more details. 17 | //BIOIMAGESUITE_LICENSE 18 | //BIOIMAGESUITE_LICENSE You should have received a copy of the GNU General Public License 19 | //BIOIMAGESUITE_LICENSE along with this program; if not, write to the Free Software 20 | //BIOIMAGESUITE_LICENSE Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 21 | //BIOIMAGESUITE_LICENSE See also http://www.gnu.org/licenses/gpl.html 22 | //BIOIMAGESUITE_LICENSE 23 | //BIOIMAGESUITE_LICENSE If this software is modified please retain this statement and add a notice 24 | //BIOIMAGESUITE_LICENSE that it had been modified (and by whom). 25 | //BIOIMAGESUITE_LICENSE 26 | //BIOIMAGESUITE_LICENSE ----------------------------------------------------------------------------------- 27 | 28 | 29 | #ifndef __vtkbisIndividualizeParcellation_h 30 | #define __vtkbisIndividualizeParcellation_h 31 | 32 | #include "vtkSimpleImageToImageFilter.h" 33 | #include "vtkDataArray.h" 34 | #include "vtkImageData.h" 35 | #include "vtkIdList.h" 36 | 37 | 38 | 39 | 40 | 41 | #include "Eigen/Dense" 42 | using Eigen::VectorXi; 43 | using Eigen::MatrixXd; 44 | 45 | 46 | 47 | class vtkbisIndividualizeParcellation : public vtkSimpleImageToImageFilter 48 | { 49 | public: 50 | vtkTypeMacro(vtkbisIndividualizeParcellation,vtkSimpleImageToImageFilter); 51 | static vtkbisIndividualizeParcellation *New(); 52 | 53 | // Mask Image 54 | vtkSetObjectMacro(FMRIImage,vtkImageData); 55 | vtkGetObjectMacro(FMRIImage,vtkImageData); 56 | 57 | // Number of Exemplars 58 | vtkSetClampMacro(NumberOfExemplars,int,1,1000000); 59 | vtkGetMacro(NumberOfExemplars,int); 60 | 61 | // Do Hemisphere? 62 | vtkSetClampMacro(Hemisphere,int,0,1); 63 | vtkGetMacro(Hemisphere,int); 64 | 65 | // Do Individualzied? 66 | vtkSetClampMacro(IndivGroup,int,0,1); 67 | vtkGetMacro(IndivGroup,int); 68 | 69 | // Lambda 70 | vtkSetClampMacro(Lambda,float,0,1); 71 | vtkGetMacro(Lambda,float); 72 | 73 | protected: 74 | 75 | vtkbisIndividualizeParcellation(); 76 | virtual ~vtkbisIndividualizeParcellation(); 77 | 78 | // Execute Function -- main function 79 | virtual void SimpleExecute(vtkImageData* input, vtkImageData* output); 80 | virtual int ComputeMRFIncrements(vtkImageData* img,int incr[]); 81 | // virtual int ComputeMRFIncrements_Diag(vtkImageData* img,int incr[]); 82 | void ClusterAssignment(vtkImageData* input,vtkImageData* output, int* Voxel_indices, MatrixXd& distvSoptR, MatrixXd& distvSoptL); 83 | bool ismember(VectorXi V, int p); 84 | private: 85 | vtkbisIndividualizeParcellation(const vtkbisIndividualizeParcellation& src) {}; 86 | vtkbisIndividualizeParcellation& operator=(const vtkbisIndividualizeParcellation& rhs) {}; 87 | int NumberOfExemplars; 88 | int Hemisphere; 89 | int IndivGroup; 90 | vtkImageData* FMRIImage; 91 | float Lambda; 92 | }; 93 | 94 | #endif 95 | 96 | 97 | 98 | --------------------------------------------------------------------------------