aimsalgo 6.0.0
Neuroimaging image processing
discriminantanalysis_d.h
Go to the documentation of this file.
1/* This software and supporting documentation are distributed by
2 * Institut Federatif de Recherche 49
3 * CEA/NeuroSpin, Batiment 145,
4 * 91191 Gif-sur-Yvette cedex
5 * France
6 *
7 * This software is governed by the CeCILL-B license under
8 * French law and abiding by the rules of distribution of free software.
9 * You can use, modify and/or redistribute the software under the
10 * terms of the CeCILL-B license as circulated by CEA, CNRS
11 * and INRIA at the following URL "http://www.cecill.info".
12 *
13 * As a counterpart to the access to the source code and rights to copy,
14 * modify and redistribute granted by the license, users are provided only
15 * with a limited warranty and the software's author, the holder of the
16 * economic rights, and the successive licensors have only limited
17 * liability.
18 *
19 * In this respect, the user's attention is drawn to the risks associated
20 * with loading, using, modifying and/or developing or reproducing the
21 * software by the user in light of its specific status of free software,
22 * that may mean that it is complicated to manipulate, and that also
23 * therefore means that it is reserved for developers and experienced
24 * professionals having in-depth computer knowledge. Users are therefore
25 * encouraged to load and test the software's suitability as regards their
26 * requirements in conditions enabling the security of their systems and/or
27 * data to be ensured and, more generally, to use and operate it in the
28 * same conditions as regards security.
29 *
30 * The fact that you are presently reading this means that you have had
31 * knowledge of the CeCILL-B license and that you accept its terms.
32 */
33
34
35#include <aims/math/svd.h>
36#include <aims/math/mathelem.h>
37#include <aims/math/random.h>
38#include <aims/math/gausslu.h>
40#include <aims/io/writer.h>
41
42namespace aims
43{
44
46 _significantEV(significantEV), _computed(false), _dataScaleFactor(1.),
47 _probaScaleFactor(1.), _PIj(PIj), _detVarCov(1.),
49{
50
51}
52
53template <typename T>
54void
56 const std::list< Point3d >& selectedPoints,
57 const carto::rc_ptr<carto::Volume<T> >& data )
58{
59 carto::VolumeRef<T> individuals( std::max(int(selectedPoints.size()), 1),
60 data->getSizeT(), 1, 1,
61 carto::AllocatorContext::fast() );
62 int i = 0 ;
63 std::list< Point3d >::const_iterator iter( selectedPoints.begin() ), last( selectedPoints.end() ) ;
65
66 _indivPosition = std::vector<Point3d>( selectedPoints.size() ) ;
67 while( iter != last ){
68 _indivPosition[ i ] = *iter ;
69 for(int t = 0 ; t < data->getSizeT() ; ++t )
70 individuals( i, t ) = T(data->at( (*iter)[0], (*iter)[1], (*iter)[2], t ) ) ;
71 ++i ; ++iter ;
72 //cout << "Indiv " << i << " = " << *iter << endl ;
73 mean += Point3df( (*iter)[0], (*iter)[1], (*iter)[2] ) ;
74 }
75 //cout << "Center = " << mean / float( individuals->getSizeX() ) << endl ;
76 doIt( individuals ) ;
77}
78
79template <typename T>
80void
82 const carto::rc_ptr<carto::Volume<T> >& individuals )
83{
84 _computed = true ;
85 int nbFrame = individuals->getSizeY() ;
86
87 carto::VolumeRef<double> centeredIndivMatrix(
88 individuals->getSizeX(), individuals->getSizeY(), 1, 1,
89 carto::AllocatorContext::fast() );
90 _mean = carto::VolumeRef<double>( individuals->getSizeY(), 1, 1, 1,
91 carto::AllocatorContext::fast() );
92 _mean = 0 ;
93 T val ;
94 for( int ind = 0 ; ind < individuals->getSizeX() ; ++ind )
95 for( int t = 0 ; t < individuals->getSizeY() ; ++t ){
96 val = individuals->at( ind, t ) ;
97 _mean(t) += val ;
98 }
99
100 //TEMP
101 double meanMean = 0. ;
102 //END TEMP
103
104 for( int t = 0 ; t < nbFrame ; ++t )
105 {
106 _mean(t) = _mean(t) / centeredIndivMatrix->getSizeX() ;
107 for( int ind = 0 ; ind < centeredIndivMatrix->getSizeX() ; ++ind )
108 {
109 centeredIndivMatrix( ind, t ) = individuals->at( ind, t ) - _mean(t) ;
110 meanMean += centeredIndivMatrix( ind, t ) ;
111 }
112 }
113
114 // Matrice des correlations
115 carto::VolumeRef<double> matVarCov(centeredIndivMatrix->getSizeY(), centeredIndivMatrix->getSizeY() ) ;
116 int x1, y1, dx1 = matVarCov->getSizeX(), dy1 = matVarCov->getSizeY();
117
118 for( y1=0; y1<dy1; ++y1 )
119 for( x1=0; x1<dx1; ++x1 )
120 {
121 for(int k=0; k < centeredIndivMatrix->getSizeX() ;++k)
122 matVarCov(x1, y1) += centeredIndivMatrix(k, x1) * centeredIndivMatrix(k, y1);
123 matVarCov(x1, y1) /= centeredIndivMatrix->getSizeX() - 1 ;
124 }
125
126 //Writer< carto::rc_ptr<carto::Volume<double> > > wriMatVarCov("matVarCov.ima") ;
127 //wriMatVarCov.write( matVarCov ) ;
128
129 carto::VolumeRef< double > u = matVarCov.deepcopy(); // because it is replaced on SVD output
131 matVarCov->getSizeY(), matVarCov->getSizeY(), 1, 1,
132 carto::AllocatorContext::fast() );
133
135 carto::VolumeRef< double > w = svd2.doit( u, &v );
136 //svd2.sort(u, w, &v) ;
137
138 carto::VolumeRef<double> invW( w.getSizeX(), w.getSizeY(), 1, 1,
139 carto::AllocatorContext::fast() ) ;
140
141 // JUST FOR SOCIETY FOR MOLECULAR IMAGING
142// int indMax = 0 ;
143 double sig2 = 0. ;
144// for( int i = 1 ; i < w->getSizeX() ; ++i )
145// if( w(i, i) > w(indMax, indMax) )
146// indMax = i ;
147 for( int i = _significantEV ; i < w.getSizeX() ; ++i ){
148 sig2 += w(i, i) ;
149 }
150 sig2 /= w.getSizeX() - _significantEV ;
151
152 std::cout << "signif EV = " << _significantEV << " sig2 = " << sig2 << std::endl ;
153
154 double lnSig2 = log(sig2) ;
155 double sqrtSig2 = sqrt(sig2) ;
156 int i, n = w.getSizeX();
157 double lnDetVarCov = 0 ;
158 _detVarCov = 1. ;
159 for ( i = 0; i < _significantEV ; i++ )
160 {
161 lnDetVarCov += 0.5 * log( w( i, i ) ) ;
162 _detVarCov *= sqrt(w( i, i )) ;
163 invW( i, i ) = 1.0f / w( i, i );
164 }
165 for ( i = _significantEV ; i<n; i++ )
166 {
167 lnDetVarCov += 0.5 * lnSig2 ;
168 _detVarCov *= sqrtSig2 ;
169 w( i, i ) = sig2 ;
170 invW( i, i ) = 1.0f / sig2 ;
171 }
172
173 // JUST FOR SOCIETY FOR MOLECULAR IMAGING END
174
175 // Set the singular values lower than threshold to zero
176// double ts = s * w.maximum();
177// int i, n = w->getSizeX();
178// _detVarCov = 1. ;
179// for ( i=0; i<n; i++ )
180// {
181// _detVarCov *= w( i, i ) ;
182// if ( w( i, i ) > ts ) w( i, i ) = 1.0f / w( i, i );
183// else w( i, i ) = 0.0f;
184// }
185
186
187 //cout << "Det Var Cov = " << _detVarCov << endl ;
188 if( _detVarCov != 0. )
189 {
190 _invVarCov = carto::matrix_product( carto::transpose( u ),
191 carto::matrix_product( invW, u ) );
192 _normFactor = 1. / _detVarCov ;
193 _lnAddFactor = -lnDetVarCov + log( _PIj * _PIj ) ;
194
195 std::cout << "normFactor = " << _normFactor << "\t_lnAddFactor = " << _lnAddFactor << std::endl ;
196
197 for( y1=0; y1<dy1; ++y1 )
198 for( x1=0; x1<dx1; ++x1 )
199 if( x1 < y1 )
200 {
201 double val = 0.5 * ( _invVarCov(x1, y1) + _invVarCov(y1, x1) ) ;
202 _invVarCov(x1, y1) = _invVarCov(y1, x1) = val ;
203 }
204 }
205 else
206 {
207 std::cerr << "Bad var cov matrix !" << std::endl ;
208 throw std::runtime_error( "Bad var cov matrix !") ;
209 }
210}
211
212double
214 const carto::rc_ptr<carto::Volume<double> >& x, double ) const
215{
216 if( ! _computed ){
217 std::cerr << "You must doIt first, parameter not yet computed !"
218 << std::endl ;
219
220 throw std::runtime_error( "You must doIt first, parameter not yet computed !") ;
221 }
222// carto::VolumeRef<double> xCentered(x->getSizeX()) ;
223// for( int t = 0 ; t < x->getSizeX() ; ++t )
224// xCentered(t) = ( x(t) - _mean(t) ) * _dataScaleFactor ;
225
226
227 double distance = 0. ;
228 for(int i = 0 ; i < x->getSizeX() ; ++i ){
229 double sum = 0. ;
230 for( int j = 0 ; j < x->getSizeX() ; ++j )
231 sum += _invVarCov(i, j) * ( x->at(j) - _mean(j) ) ;
232 //double term = ( x->at(i) - _mean(i) ) * sum ;
233 distance += ( x->at(i) - _mean(i) ) * sum ;
234 }
235
236 return _normFactor * exp( -distance ) ;
237}
238
239double
241 const carto::rc_ptr<carto::Volume<double> >& x ) const
242{
243 if( ! _computed ){
244 std::cerr <<"You must doIt first, parameter not yet computed !"
245 << std::endl ;
246 throw std::runtime_error( "You must doIt first, parameter not yet computed !") ;
247 }
248// cout << "DiscriminantAnalysisElement::distance " << endl ;
249// cout << "inv var cov size = " << _invVarCov->getSizeX() << " , " << _invVarCov->getSizeY() << endl ;
250 double distance = 0. ;
251 for(int i = 0 ; i < x->getSizeX() ; ++i ){
252// cout << "i = " << i << endl ;
253 double sum = 0. ;
254 for( int j = 0 ; j < x->getSizeX() ; ++j ){
255// cout << "\tj = " << j << endl ;
256 sum += _invVarCov(i, j) * ( x->at(j) - _mean(j) ) ;
257 }
258 //double term = ( x->at(i) - _mean(i) ) * sum ;
259 distance += ( x->at(i) - _mean(i) ) * sum ;
260 }
261// cout << "DiscriminantAnalysisElement::distance end " << endl ;
262
263 return distance ;
264}
265
266double
268 const carto::rc_ptr<carto::Volume<double> >& x ) const
269{
270 if( ! _computed ){
271 std::cerr << "You must doIt first, parameter not yet computed !"
272 << std::endl ;
273 throw std::runtime_error( "You must doIt first, parameter not yet computed !") ;
274 }
275 double distance = 0. ;
276 for(int i = 0 ; i < x->getSizeX() ; ++i ){
277 double sum = 0. ;
278 for( int j = 0 ; j < x->getSizeX() ; ++j )
279 sum += _invVarCov(i, j) * ( x->at(j) - _mean(j) ) ;
280 //double term = ( x->at(i) - _mean(i) ) * sum ;
281 distance += ( x->at(i) - _mean(i) ) * sum ;
282 }
283
284// double distanceTest = 0. ;
285// carto::VolumeRef<double> Ux( x->getSizeX() ) ;
286// for(int i = 0 ; i < _U->getSizeX() ; ++i )
287// for( int j = 0 ; j < _U->getSizeY() ; ++j )
288// Ux(i) += _U(j, i) * (x->at(j) - _mean(i) ) ;
289
290// for( int i = 0 ; i < Ux->getSizeX() ; ++i )
291// distanceTest += Ux(i) * Ux(i) * _invEigenValues[i] ;
292
293// double distance = 0. ;
294// for(int i = 0 ; i < x->getSizeX() ; ++i ){
295// double sum = 0. ;
296// for( int j = 0 ; j < x->getSizeX() ; ++j )
297// sum += _invVarCov(i, j) * ( x->at(j) - _mean(j) ) ;
298// distance += ( x->at(i) - _mean(i) ) * sum ;
299// cout << i << "\txi = " << x->at(i) << "\tmean i = " << _mean(i) <<
300// " diff = " << x->at(i) - _mean(i) << " dist = " << distance << endl ;
301// }
302
303 return -distance + _lnAddFactor ;
304}
305
306
309{
310 if( ! _computed ){
311 std::cerr <<"You must doIt first, parameter not yet computed !"
312 << std::endl ;
313 throw std::runtime_error( "You must doIt first, parameter not yet computed !") ;
314 }
315 return _mean ;
316}
317
318template <class T>
320 const carto::rc_ptr<carto::Volume<T> >& data,
321 const std::vector< std::list< Point3d > >& classes,
322 int significantEV, const std::vector<double>& PIj )
323 : _significantEV(significantEV <= 0 ? data->getSizeT() : significantEV),
324 _classes(classes), _data(data), _PIj(PIj)
325{
326 if( PIj.size() != 0 )
327 if( PIj.size() == classes.size() )
328 _PIj = PIj ;
329 else{
330 std::cerr << "Inconsistant data : number of classes and number of classes prior probabilities are different !" << std::endl ;
331
332 throw std::runtime_error("Inconsistant data : number of classes and number of classes prior probabilities are different !") ;
333 }
334 else{
335 _PIj.reserve( _classes.size() ) ;
336 for( unsigned int c = 0 ; c < _classes.size() ; ++c )
337 _PIj.push_back( 1./_classes.size() ) ;
338 }
339 //--------------------------------TEMP---------------------------------------------
340/* carto::VolumeRef<double> indiv(12000, 3) ; */
341/* Point3dd mean( 56., 32., 100.) ; */
342/* Point3dd sigma( 20., 2., 10.) ; */
343
344/* for( int ind = 0 ; ind < indiv->getSizeX() ; ++ind ) */
345/* for( int t = 0 ; t < indiv->getSizeY() ; ++t ) */
346/* indiv(ind, t) = GaussianRandom ( mean[t], sigma[t] ) ; */
347
348 //--------------------------------TEMP---------------------------------------------
349 _discrElements.reserve( _classes.size() ) ;
350 for( unsigned int c = 0 ; c < _classes.size() ; ++c ){
351 DiscriminantAnalysisElement el( significantEV, _PIj[c] ) ;
352 el.doIt( _classes[c], _data ) ;
353/* el.doIt( indiv ) ; */
354
355 std::cout << "Class " << c << " done !" << std::endl ;
356
357 _discrElements.push_back( el ) ;
358 }
359 std::cout << "Discriminant analysis initization completed" << std::endl ;
360}
361
362template <class T>
363std::vector<double>
365 const carto::rc_ptr<carto::Volume<double> >& x, double pX )
366{
367 std::vector<double> res( _classes.size() ) ;
368 for( unsigned int c = 0 ; c < _classes.size() ; ++c )
369 res[c] = _discrElements[c].posteriorProbability( x, pX ) ;
370 return res ;
371}
372
373template <class T>
374std::vector<double>
377{
378 std::vector<double> res( _classes.size() ) ;
379 double sum = 0. ;
380 for( unsigned int c = 0 ; c < _classes.size() ; ++c ){
381 res[c] = _discrElements[c].posteriorProbability( x, 1. ) ;
382 sum += res[c] ;
383 }
384
385 for( unsigned int c = 0 ; c < _classes.size() ; ++c )
386 res[c] /= sum ;
387
388 return res ;
389}
390
391template <class T>
392int
395{
396 double lnP ;
397 double lnPMax = _discrElements[0].lnPosteriorProbability( x ) ;
398 int indMax = 0 ;
399 for( unsigned int c = 0 ; c < _classes.size() ; ++c )
400 {
401 lnP = _discrElements[c].lnPosteriorProbability( x ) ;
402 if( lnP > lnPMax ){
403 lnPMax = lnP ;
404 indMax = c ;
405 }
406 }
407
408 return indMax ;
409}
410
411
412template <class T>
413bool
415 const carto::rc_ptr<carto::Volume<T> >& dynamicImage,
418{
419 int x, y, z ;
420 if( dynamicImage->getSizeT() != _data->getSizeT() )
421 return false ;
422 if( segmented->getSizeX() != _data->getSizeX() && segmented->getSizeY() != _data->getSizeY()
423 && segmented->getSizeZ() != _data->getSizeZ() )
424 {
425 segmented = carto::VolumeRef<short> ( _data->getSizeX(), _data->getSizeY(), _data->getSizeZ() );
426 segmented->setVoxelSize( _data->getVoxelSize() );
427 }
428
429 carto::VolumeRef<double> indiv( dynamicImage->getSizeT(), 1, 1, 1,
430 carto::AllocatorContext::fast() ) ;
431
432 int dx = dynamicImage->getSizeX(), dy = dynamicImage->getSizeY(),
433 dz = dynamicImage->getSizeZ();
434
435 for( z=0; z<dz; ++z )
436 for( y=0; y<dy; ++y )
437 for( x=0; x<dx; ++x )
438 {
439 if( mask->at(x, y, z) )
440 {
441 std::cout << "x : " << x << ", y : " << y << ", z : " << z << std::endl ;
442 for( int t = 0 ; t < _data->getSizeT() ; ++t )
443 indiv(t) = dynamicImage->at(x, y, z, t ) ;
444 segmented->at(x, y, z) = affectedTo( indiv ) ;
445 }
446 }
447
448 std::cout << "Discriminant analysis classification completed" << std::endl ;
449
450 return true ;
451}
452
453template <class T>
454bool
456 const carto::rc_ptr<carto::Volume<T> >& dynamicImage,
458 carto::rc_ptr<carto::Volume<float> >& fuzzySegmented,
459 const carto::rc_ptr<carto::Volume<double> > & indivPriorProbabilities )
460{
461 bool noPriorProba
462 = ( indivPriorProbabilities->getSizeX() == 1
463 && indivPriorProbabilities->getSizeY() == 1
464 && indivPriorProbabilities->getSizeZ() == 1 );
465 int count = 0 ;
466 //double uniformPriorProba ;
467
468 int x, y, z ;
469 if( noPriorProba )
470 {
471 int dx = mask->getSizeX(), dy = mask->getSizeY(), dz = mask->getSizeZ();
472
473 for( z=0; z<dz; ++z )
474 for( y=0; y<dy; ++y )
475 for( x=0; x<dx; ++x )
476 if( mask->at( x, y, z ) )
477 ++count ;
478 //uniformPriorProba = 1. / count ;
479 }
480 if( dynamicImage->getSizeT() != _data->getSizeT() )
481 return false ;
482 if( fuzzySegmented->getSizeX() != _data->getSizeX()
483 && fuzzySegmented->getSizeY() != _data->getSizeY()
484 && fuzzySegmented->getSizeZ() != _data->getSizeZ() &&
485 fuzzySegmented->getSizeT() != int(_classes.size() ) )
486 {
487 fuzzySegmented = carto::VolumeRef<float> ( _data->getSizeX(), _data->getSizeY(),
488 _data->getSizeZ(), _classes.size() ) ;
489 fuzzySegmented->setVoxelSize( _data->getVoxelSize() ) ;
490 }
491
492 std::vector<double> probabilityRepartition ;
493 carto::VolumeRef<double> indiv( dynamicImage->getSizeT(), 1, 1, 1,
494 carto::AllocatorContext::fast() ) ;
495
496 int dx = dynamicImage->getSizeX(), dy = dynamicImage->getSizeY(),
497 dz = dynamicImage->getSizeZ();
498
499 for( z=0; z<dz; ++z )
500 for( y=0; y<dy; ++y )
501 for( x=0; x<dx; ++x )
502 {
503 if( mask->at(x, y, z) )
504 {
505 //cout << "x : " << x << ", y : " << y << ", z : " << z << endl ;
506 for( int t = 0 ; t < _data->getSizeT() ; ++t )
507 indiv(t) = dynamicImage->at(x, y, z, t ) ;
508 /* probabilityRepartition = andersonScores( indiv ) ; */
509 probabilityRepartition = posteriorProbabilities( indiv, 1. ) ;
510
511 for( int c = 0 ; c < fuzzySegmented->getSizeT() ; ++c )
512 fuzzySegmented->at(x, y, z, c) = probabilityRepartition[c] ;
513 }
514 }
515
516 std::cout << "Discriminant analysis : fuzzy classification completed"
517 << std::endl ;
518
519 return true ;
520}
521
522}
Definition svd.h:59
carto::VolumeRef< T > doit(carto::VolumeRef< T > &, carto::VolumeRef< T > *v=NULL)
Singular Value Decomposition.
const carto::VolumeRef< double > & mean() const
double posteriorProbability(const carto::rc_ptr< carto::Volume< double > > &individual, double pX) const
double lnPosteriorProbability(const carto::rc_ptr< carto::Volume< double > > &individual) const
void doIt(const carto::rc_ptr< carto::Volume< T > > &individuals)
DiscriminantAnalysisElement(int significantEV=-1, double PIj=1.)
double distance(const carto::rc_ptr< carto::Volume< double > > &x) const
carto::VolumeRef< double > _invVarCov
bool classification(const carto::rc_ptr< carto::Volume< T > > &dynamicImage, const carto::rc_ptr< carto::Volume< byte > > &mask, carto::rc_ptr< carto::Volume< short > > &segmented)
DiscriminantAnalysis(const carto::rc_ptr< carto::Volume< T > > &data, const std::vector< std::list< Point3d > > &classes, int significantEV=-1, const std::vector< double > &PIj=std::vector< double >())
int affectedTo(const carto::rc_ptr< carto::Volume< double > > &x)
std::vector< double > andersonScores(const carto::rc_ptr< carto::Volume< double > > &x)
std::vector< double > posteriorProbabilities(const carto::rc_ptr< carto::Volume< double > > &x, double px)
bool fuzzyClassification(const carto::rc_ptr< carto::Volume< T > > &dynamicImage, const carto::rc_ptr< carto::Volume< byte > > &mask, carto::rc_ptr< carto::Volume< float > > &fuzzySegmented, const carto::rc_ptr< carto::Volume< double > > &indivPriorProbabilities=carto::rc_ptr< carto::Volume< double > >())
const T & at(long x, long y=0, long z=0, long t=0) const
int getSizeY() const
int getSizeX() const
VolumeRef< T > deepcopy() const
BucketMap< Void > * mask(const BucketMap< Void > &src, const BucketMap< Void > &m, bool intersect=true)
DataTypeTraits< T >::LongType sum(const Volume< T > &vol)
AimsVector< float, 3 > Point3df