aimsalgo  5.1.2
Neuroimaging image processing
wlms-estimator.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 #ifndef AIMS_ESTIMATION_WLMS_ESTIMATOR_H
36 #define AIMS_ESTIMATION_WLMS_ESTIMATOR_H
37 
38 #include <cstdlib>
41 #include <aims/estimation/m-func.h>
42 
43 //
44 // Weighted Linear Mean Squared M-estimator
45 //
46 template < int D >
47 class WLMSEstimator : public MEstimator< D >
48 {
49  public:
50  WLMSEstimator( MEstimatorFunc& mfunc, float error,
51  bool verbose = false )
52  : MEstimator<D>(), _mfunc( mfunc ), _error( error ),
53  _verbose( verbose) { }
54  virtual ~WLMSEstimator() { }
55 
56  void doit(
58  const carto::rc_ptr<carto::Volume< float > >& y, float& a,
60 
61  protected:
63  float _error;
64  bool _verbose;
65 
66  float sigma(
68  const carto::rc_ptr<carto::Volume< float > >& y, float a,
69  const AimsVector< float, D >& b,
71 
72  void step(
74  const carto::rc_ptr<carto::Volume< float > >& y, float& a,
76  const carto::rc_ptr<carto::Volume<float> >& error );
77 };
78 
79 
80 template < int D > inline
83  const carto::rc_ptr<carto::Volume< float > >& y, float a,
84  const AimsVector< float, D >& b,
86 {
87  int N = y->getSizeX(), n, k;
88  for ( n = 0; n < N; n++ )
89  {
90  error->at( n ) = y->at( n ) - a;
91  for ( k = 0; k < D; k++ )
92  error->at( n ) -= b.item( k ) * x->at( n ).item( k );
93  error->at( n ) = fabs( error->at( n ) );
94  }
95 
96  carto::VolumeRef<float> errorbis = error->copy();
97  carto::sort( errorbis );
98 
99  return 1.4826 * errorbis( N / 2 );
100 }
101 
102 
103 template < int D >
104 inline
105 void
107  const carto::rc_ptr<carto::Volume< float > >& y, float& a,
109  const carto::rc_ptr<carto::Volume<float> >& error )
110 {
111  int N = y->getSizeX();
112  carto::VolumeRef<float> mat( D + 1, D + 1, 1, 1,
113  carto::AllocatorContext::fast() );
114  carto::VolumeRef<float> vec( D + 1, 1, 1, 1,
115  carto::AllocatorContext::fast() );
116  carto::VolumeRef<float> weight( N, 1, 1, 1,
117  carto::AllocatorContext::fast() );
118 
119  mat = 0.0;
120  vec = 0.0;
121  weight = 0.0;
122 
123  int k, n;
124 
125  for ( n = 0; n < N; n++ )
126  {
127  weight( n ) = _mfunc.weight( error->at( n ) );
128  mat( 0, 0 ) += weight( n );
129  }
130 
131  for ( k = 1; k <= D; k++ )
132  {
133  for ( n = 0; n < N; n++ )
134  mat( k, 0 ) += weight( n ) * x->at( n ).item( k - 1 );
135  mat( 0, k ) = mat( k, 0 );
136  }
137 
138  int k1, k2;
139  for ( k1 = 1; k1 <= D; k1++ )
140  for ( k2 = 1; k2 <= k1; k2++ )
141  {
142  for ( n = 0; n < N; n++ )
143  mat( k1, k2 ) += weight( n ) *
144  x->at( n ).item( k1 - 1 ) * x->at( n ).item( k2 - 1 );
145  mat( k2, k1 ) = mat( k1, k2 );
146  }
147 
148 
149  for ( n = 0; n < N; n++ )
150  {
151  vec( 0 ) += weight( n ) * y->at( n );
152  for ( k = 1; k <= D; k++ )
153  vec( k ) += weight( n ) * y->at( n ) * x->at( n ).item( k - 1 );
154  }
155 
157  a = res( 0 );
158  for ( k = 1; k <= D; k++ )
159  b.item( k - 1 ) = res( k );
160 }
161 
162 
163 template < int D > inline
165  const carto::rc_ptr<carto::Volume< float > >& y, float& a,
167 {
168  ASSERT( x->getSizeY() == 1 && x->getSizeZ() == 1 && x->getSizeT() == 1 );
169  ASSERT( y->getSizeY() == 1 && y->getSizeZ() == 1 && y->getSizeT() == 1 );
170  ASSERT( x->getSizeX() == y->getSizeX() );
171 
172  float obja, objb;
173  float old_a;
175 
176  // estimate starting value with LMS fit
177  LMSEstimator<D> lms;
178  lms.doit( x, y, a, b );
179 
180  carto::VolumeRef<float> error( x->getSizeX() );
181  int count = 0;
182  // perform iteration of robust estimation until convergence
183  do
184  {
185  ASSERT( count != 100 ); // maximum iteration
186  old_a = a;
187  old_b = b;
188  _mfunc.setSigma( sigma( x, y, old_a,old_b, error ) );
189  step( x, y, a, b, error );
190  obja = fabs( a - old_a ) / ( fabs( a ) + fabs( old_a ) );
191  objb = norm( b - old_b ) / ( norm( b ) + norm( old_b ) );
192  if ( _verbose )
193  std::cout
194  << "Obja : " << obja << " "
195  << "Objb : " << objb << " "
196  << "a : " << a << " "
197  << "b : " << b << std::endl;
198  count++;
199  }
200  while ( obja > _error || objb > _error );
201 }
202 
203 
204 #endif
#define ASSERT(EX)
const T & item(int d) const
void doit(const carto::rc_ptr< carto::Volume< AimsVector< float, D > > > &x, const carto::rc_ptr< carto::Volume< float > > &y, float &a, AimsVector< float, D > &b)
Definition: lms-estimator.h:65
virtual ~WLMSEstimator()
float sigma(const carto::rc_ptr< carto::Volume< AimsVector< float, D > > > &x, const carto::rc_ptr< carto::Volume< float > > &y, float a, const AimsVector< float, D > &b, carto::rc_ptr< carto::Volume< float > > &error)
WLMSEstimator(MEstimatorFunc &mfunc, float error, bool verbose=false)
void doit(const carto::rc_ptr< carto::Volume< AimsVector< float, D > > > &x, const carto::rc_ptr< carto::Volume< float > > &y, float &a, AimsVector< float, D > &b)
void step(const carto::rc_ptr< carto::Volume< AimsVector< float, D > > > &x, const carto::rc_ptr< carto::Volume< float > > &y, float &a, AimsVector< float, D > &b, const carto::rc_ptr< carto::Volume< float > > &error)
MEstimatorFunc & _mfunc
const T & at(long x, long y=0, long z=0, long t=0) const
VolumeRef< T > copy() const
carto::VolumeRef< float > AimsLinearResolutionLU(const carto::VolumeRef< float > &matrix, const carto::VolumeRef< float > &b)
int verbose
void sort(Volume< T > &thing, bool ascending=true)
AIMSDATA_API float norm(const Tensor &thing)