├── .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 |
--------------------------------------------------------------------------------