1 /*=========================================================================
4 Module: $RCSfile: clitkSignalMeanPositionFilter.cxx,v $
6 Date: $Date: 2010/02/10 14:55:00 $
7 Version: $Revision: 1.4 $
9 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10 l'Image). All rights reserved. See Doc/License.txt or
11 http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
13 This software is distributed WITHOUT ANY WARRANTY; without even
14 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 PURPOSE. See the above copyright notices for more information.
17 =========================================================================*/
19 #include "clitkSignalMeanPositionFilter.h"
21 //---------------------------------------------------------------------
22 void clitk::SignalMeanPositionFilter::SetParameters(args_info_clitkSignalMeanPositionTracking & args) {
25 mOutputFilenameIsSet = false;
26 mOutputResidualFilenameIsSet = false;
27 mInput.Read(args_info.input_arg);
28 mAugmentationDelay = args_info.delay_arg;
29 mIsAdaptiveMethod = false;
31 mValidationWithRealPhase = false;
32 mUseLearnedDeltaPhase = false;
33 if (args_info.eta_given) {
34 mEta = args_info.eta_arg;
37 mMaxIteration = args_info.iter_arg;
38 if (args_info.output_given) {
39 mOutputFilenameIsSet = true;
40 mOutputFilename = args_info.output_arg;
42 if (args_info.residual_given) {
43 mOutputResidualFilenameIsSet = true;
44 mOutputResidualFilename = args_info.residual_arg;
46 if (args_info.augmented_given) {
47 mOutputAugmentedFilenameIsSet = true;
48 mOutputAugmentedFilename = args_info.augmented_arg;
50 mVerbose = args_info.verbose_flag;
51 mVerboseIteration = args_info.verbose_iteration_flag;
52 if (args_info.L_given) {
53 mIsAdaptiveMethod = true;
54 mWindowLength = args_info.L_arg;
56 if (args_info.phase_given) {
57 mValidationWithRealPhase = true;
58 mInputPhaseFilename = args_info.phase_arg;
59 mInputPhase.Read(mInputPhaseFilename);
61 mNumberOfIsoPhase = args_info.nbiso_arg;
62 if (args_info.delta_given) {
63 mUseLearnedDeltaPhase = true;
64 mLearnIsoPhaseDelta.Read(args_info.delta_arg);
65 mNumberOfIsoPhase = mLearnIsoPhaseDelta.size();
69 if (args_info.phase_given) {
70 std::cout << "PLEASE DO NO USE THIS OPTION --phase YET ..." << std::endl;
73 if (args_info.delta_given) {
74 std::cout << "PLEASE DO NO USE THIS OPTION --delta YET ..." << std::endl;
79 //---------------------------------------------------------------------
82 //---------------------------------------------------------------------
83 void clitk::SignalMeanPositionFilter::Update() {
85 // Compute augmented space
87 std::cout << "Computing augmented space with delay = " << mAugmentationDelay
88 << ", number of samples is " << mInput.size()-mAugmentationDelay
91 mInput.ComputeAugmentedSpace(mAugmentedInputX, mAugmentedInputY, mAugmentationDelay);
93 // Output augmented state
94 if (mOutputAugmentedFilenameIsSet) {
96 openFileForWriting(os, mOutputAugmentedFilename);
97 for(unsigned int i=0; i<(unsigned int)mAugmentedInputX.size(); i++) {
98 os << mAugmentedInputX[i] << " " << mAugmentedInputY[i] << std::endl;
103 // Initial starting ellipse
104 Ellipse An; // starting point
105 if (!mEtaIsSet) mEta = -1;
107 if (mWindowLength == -1) {
108 mWindowLength = mAugmentedInputY.size();
110 An.InitialiseEllipseFitting(mEta, mWindowLength, mAugmentedInputX, mAugmentedInputY);
113 std::cout << "Eta is " << mEta << std::endl;
115 Ellipse AnInitial(An);
117 std::cout << "Set initial ellipse to c=" << An.ComputeCenter()
118 << " and axes=" << An.ComputeSemiAxeLengths() << std::endl;
122 if (mIsAdaptiveMethod) {
123 AdaptiveFitEllipse(An);
129 std::cout << "Result is " << An << std::endl;
130 std::cout << "Center is " << An.ComputeCenter() << std::endl;
131 std::cout << "SemiAxis are " << An.ComputeSemiAxeLengths() << std::endl;
132 std::cout << "Angle is " << rad2deg(An.ComputeAngleInRad()) << " deg" << std::endl;
134 if (mOutputFilenameIsSet) {
136 openFileForWriting(os, mOutputFilename);
138 std::vector<double> phase;
139 ComputeIsoPhase(mListOfEllipses, phase, mCycles);
141 //int currentCycle = 0;
142 for (unsigned int i=0; i<mListOfEllipses.size(); i++) {
143 clitk::Ellipse & An = *mListOfEllipses[i];
144 int time = i+mAugmentationDelay+mWindowLength;
145 os << time << " " // current 'time' in input
146 << mInput[time] << " " // current value in input
147 << An.ComputeCenter()[0] << " " << An.ComputeCenter()[1] << " "
148 << An.ComputeSemiAxeLengths()[0] << " " << An.ComputeSemiAxeLengths()[1] << " "
149 << An.ComputeAngleInRad() << " "
150 << rad2deg(An.ComputeAngleInRad()) << " _Phase_ "
151 << mIsoPhaseIndex[i] << " " ;
154 if (mUseLearnedDeltaPhase) {
155 os << mIsoPhaseDelta[mIsoPhaseIndex[i]] << " " << phase[i] << " ";
160 for(int j=0; j<6; j++) os << An[j] << " ";
166 if (mOutputResidualFilenameIsSet) {
168 openFileForWriting(os, mOutputResidualFilename);
169 for(unsigned int i=0; i<mCurrentResidual.size(); i++) {
171 os << mCurrentResidual[i] << std::endl;
176 //---------------------------------------------------------------------
179 //---------------------------------------------------------------------
180 void clitk::SignalMeanPositionFilter::FitEllipse(clitk::Ellipse & An) {
182 mCurrentResidual.clear();
183 while (n<mMaxIteration) {
184 double r = An.EllipseFittingNextIteration();
185 mCurrentResidual.push_back(r);
187 if (mVerboseIteration) {
188 std::cout.precision(3);
189 std::cout << "A(" << n << ")=" << An
190 << " c=" << An.ComputeCenter()
191 << " ax=" << An.ComputeSemiAxeLengths()
192 << " theta=" << rad2deg(An.ComputeAngleInRad());
193 std::cout.precision(10);
194 std::cout << " R=" << r << std::endl;
198 //---------------------------------------------------------------------
201 //---------------------------------------------------------------------
202 void clitk::SignalMeanPositionFilter::AdaptiveFitEllipse(clitk::Ellipse & An) {
203 // Compute the total number of iteration :
204 // = nb of inputs minus the delay, minus the windowL, minus the first one
205 int maxN = std::min((unsigned int)args_info.t_arg,
206 mInput.size()-mWindowLength-mAugmentationDelay);
207 for(int t=0; t<maxN; t++) {
208 An.UpdateSMatrix(t, mWindowLength, mAugmentedInputX, mAugmentedInputY);
210 clitk::Ellipse * B = new clitk::Ellipse(An);
211 mListOfEllipses.push_back(B);
214 //---------------------------------------------------------------------
217 //---------------------------------------------------------------------
218 void clitk::SignalMeanPositionFilter::ComputeIsoPhase(std::vector<clitk::Ellipse*> & l,
219 std::vector<double> & phase,
220 std::vector<int> & cycles) {
221 double refphaseangle=0;
222 double previousangle=0;
223 phase.resize(mListOfEllipses.size());
225 // DD(mListOfEllipses.size());
226 mIsoPhaseIndex.resize(mListOfEllipses.size());
227 // mIsoPhaseDelta.resize(mNumberOfIsoPhase);
228 // mIsoPhaseDeltaNb.resize(mNumberOfIsoPhase);
229 mIsoPhaseRefAngle.resize(mNumberOfIsoPhase);
231 for (unsigned int i=0; i<mListOfEllipses.size(); i++) {
232 clitk::Ellipse & An = *mListOfEllipses[i];
234 // Current time accordint to initial input signal
235 // int time = i+mAugmentationDelay+mWindowLength; // not use yet
237 // Compute current signed angle
238 Vector2d x1(An.ComputeCenter());
239 double a = mListOfEllipses[0]->ComputeSemiAxeLengths()[0];
240 double theta = mListOfEllipses[0]->ComputeAngleInRad();
241 Vector2d x2; x2[0] = x1[0]+a * cos(theta); x2[1] = x1[1]+a * sin(theta);
243 Vector2d x4; x4[0] = mAugmentedInputX[i+mWindowLength]; x4[1] = mAugmentedInputY[i+mWindowLength];
246 double signed_angle = atan2(B[1], B[0]) - atan2(A[1], A[0]);
247 // double signed_angle = atan2(B[1], B[0]) - atan2(0, 1);
248 if (signed_angle<0) signed_angle = 2*M_PI+signed_angle;
249 // http://www.euclideanspace.com/maths/algebra/vectors/angleBetween/index.htm
251 // First time : set the angle
253 refphaseangle = signed_angle;
254 for(int a=0; a<mNumberOfIsoPhase; a++) {
255 if (a==0) mIsoPhaseRefAngle[a] = signed_angle;
256 else mIsoPhaseRefAngle[a] = (signed_angle
257 + (2*M_PI)*a/mNumberOfIsoPhase);
258 if (mIsoPhaseRefAngle[a] > 2*M_PI) mIsoPhaseRefAngle[a] -= 2*M_PI;
259 if (mIsoPhaseRefAngle[a] < 0) mIsoPhaseRefAngle[a] = 2*M_PI-mIsoPhaseRefAngle[a];
260 // DD(rad2deg(mIsoPhaseRefAngle[a]));
261 // mIsoPhaseDelta[a] = 0.0;
262 // mIsoPhaseDeltaNb[a] = 0;
265 // DD(rad2deg(signed_angle));
266 while ((a<mNumberOfIsoPhase) && (signed_angle>=mIsoPhaseRefAngle[a])) { a++; }
268 mIsoPhaseIndex[i] = a-1;
269 // DD(mIsoPhaseIndex[0]);
273 mIsoPhaseIndex[i] = mIsoPhaseIndex[i-1];
275 // Check if angle cross a ref angle
276 for(int a=0; a<mNumberOfIsoPhase; a++) {
277 std::cout << "a=" << rad2deg(signed_angle) << " p=" << rad2deg(previousangle)
278 << " ref=" << rad2deg(mIsoPhaseRefAngle[a]) << std::endl;
280 (((signed_angle > mIsoPhaseRefAngle[a]) && (previousangle < mIsoPhaseRefAngle[a]))) ||
281 ((mIsoPhaseRefAngle[a]==0) && (signed_angle < previousangle)))
283 // if (mValidationWithRealPhase) {
284 // mIsoPhaseDelta[a] += mInputPhase[time];
285 // mIsoPhaseDeltaNb[a]++;
287 mIsoPhaseIndex[i] = a;
292 // DD(mIsoPhaseIndex[i]);
295 previousangle = signed_angle;
299 if (mValidationWithRealPhase) {
300 // Mean of all deltas
301 for(unsigned int a=0; a<mIsoPhaseDelta.size(); a++) {
302 if (mIsoPhaseDelta[a] == 0) {
303 std::cerr << "Error : less than one cyle ?" << std::endl;
306 mIsoPhaseDelta[a] /= mIsoPhaseDeltaNb[a];
307 DD(mIsoPhaseDelta[a]);
310 openFileForWriting(os, "delta.sig");
311 for(unsigned int a=0; a<mIsoPhaseDelta.size(); a++) {
312 os << mIsoPhaseDelta[a] << std::endl;
319 if (mUseLearnedDeltaPhase) {
320 for(unsigned int a=0; a<mIsoPhaseDelta.size(); a++) {
321 mIsoPhaseDelta[a] = mLearnIsoPhaseDelta[a];
322 DD(mIsoPhaseDelta[a]);
330 for (unsigned int i=0; i<cycles.size(); i++) {
334 n=cycles[i]-cycles[i-1];
335 for(int index=0; index<n; index++) {
337 int indexOfPhase1 = mIsoPhaseIndex[cycles[i-1]];
338 int indexOfPhase2 = mIsoPhaseIndex[cycles[i]];
341 double ph1 = mIsoPhaseDelta[indexOfPhase1];
342 double ph2 = mIsoPhaseDelta[indexOfPhase2];
346 phase[j] = (ph1+(double)index*(ph2-ph1)/(double)n);
347 if (phase[j]>1.0) phase[j] = 1.0-phase[j];
355 for (unsigned int i=0; i<cycles.size(); i++) {
360 //---------------------------------------------------------------------