Skip to content

Commit 5c024d8

Browse files
committed
Updated power law fit algorithm
1 parent 349c158 commit 5c024d8

1 file changed

Lines changed: 47 additions & 19 deletions

File tree

src/app/calc/calculate.cpp

Lines changed: 47 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -232,20 +232,29 @@ void Calculate::CalculatePowerLawAutoFitSimple(Parameters *para)
232232
double error, sumError;
233233
double minError = 1e100;
234234
double curB = 0.0;
235-
double x, y;
235+
236+
const unsigned int nWavel = para->nWavel;
237+
const double refWavel = para->refWavel;
238+
const double muspRef = para->muspAtRefWavel[para->refWavelIdx];
239+
240+
//xRatio and y depend only on k, not on bMie
241+
std::vector<double> xRatio(nWavel);
242+
std::vector<double> y(nWavel);
243+
for (unsigned int k = 0; k < nWavel; k++)
244+
{
245+
xRatio[k] = para->wavelArray[k] / refWavel;
246+
y[k] = para->mus[k] * (1.0 - para->g[k]);
247+
}
236248

237249
for (int j=0; j<=400; j++)
238250
{
239251
bMie = j*0.01; //Range: [0, 4]
240252
sumError = 0.0;
241-
for (unsigned int k=0; k<para->nWavel; k++)
253+
for (unsigned int k=0; k<nWavel; k++)
242254
{
243255
//Steve L Jacques,"Optical properties of biological tissues: a review" Phys. Med & Bio. 58(2013) R37-R61.
244-
x = para->wavelArray[k];
245-
yFit = ( para->muspAtRefWavel[para->refWavelIdx]*pow(x/para->refWavel, -bMie));
246-
247-
y = para->mus[k] * (1.0 - para->g[k]);
248-
error = yFit - y;
256+
yFit = muspRef * pow(xRatio[k], -bMie);
257+
error = yFit - y[k];
249258
sumError += error*error;
250259
}
251260
if (sumError < minError)
@@ -264,7 +273,30 @@ void Calculate::CalculatePowerLawAutoFitComplex(Parameters *para)
264273
double error, sumError;
265274
double minError = 1e100;
266275
double curB = 0.0, curF = 0.0;
267-
double x, y;
276+
277+
const unsigned int nWavel = para->nWavel;
278+
const double refWavel = para->refWavel;
279+
const double muspRef = para->muspAtRefWavel[para->refWavelIdx];
280+
281+
//xRatio, rayTerm and y depend only on k
282+
std::vector<double> xRatio(nWavel);
283+
std::vector<double> rayTerm(nWavel); //(x/refWavel)^-4, invariant across fRay and bMie
284+
std::vector<double> y(nWavel);
285+
for (unsigned int k = 0; k < nWavel; k++)
286+
{
287+
xRatio[k] = para->wavelArray[k] / refWavel;
288+
rayTerm[k] = pow(xRatio[k], -4.0);
289+
y[k] = para->mus[k] * (1.0 - para->g[k]);
290+
}
291+
292+
//(x/refWavel)^-bMie depends only on (j, k), not on fRay
293+
std::vector<std::vector<double>> powTerm(401, std::vector<double>(nWavel));
294+
for (int j = 0; j <= 400; j++)
295+
{
296+
double bMieCandidate = j * 0.01;
297+
for (unsigned int k = 0; k < nWavel; k++)
298+
powTerm[j][k] = pow(xRatio[k], -bMieCandidate);
299+
}
268300

269301
for (int i=0; i<=100; i++)
270302
{
@@ -273,14 +305,12 @@ void Calculate::CalculatePowerLawAutoFitComplex(Parameters *para)
273305
{
274306
bMie = j*0.01; //Range: [0, 4]
275307
sumError = 0.0;
276-
for (unsigned int k=0; k<para->nWavel; k++)
308+
const std::vector<double> &powTermJ = powTerm[j];
309+
for (unsigned int k=0; k<nWavel; k++)
277310
{
278311
//Steve L Jacques,"Optical properties of biological tissues: a review" Phys. Med & Bio. 58(2013) R37-R61.
279-
x = para->wavelArray[k];
280-
yFit = ( para->muspAtRefWavel[para->refWavelIdx] *(fRay*pow(x/para->refWavel, -4.0) + (1.0-fRay)*pow(x/para->refWavel, -bMie)));
281-
282-
y = para->mus[k] * (1.0 - para->g[k]);
283-
error = yFit - y;
312+
yFit = muspRef * (fRay*rayTerm[k] + (1.0-fRay)*powTermJ[k]);
313+
error = yFit - y[k];
284314
sumError += error*error;
285315
}
286316
if (sumError < minError)
@@ -350,7 +380,7 @@ double Calculate::CalculateForwardBackward(std::complex<double> *S1,
350380
return sum;
351381
}
352382

353-
//Builds a ThetaGrid internally on every call
383+
//Back-compat wrapper: builds a ThetaGrid internally on every call
354384
double Calculate::CalculateForwardBackward(std::complex<double> *S1,
355385
std::complex<double> *S2,
356386
Parameters *para,
@@ -379,10 +409,8 @@ double Calculate::CalculateG(std::complex<double> *S1, std::complex<double> *S2,
379409
return num/den;
380410
}
381411

382-
//Builds a ThetaGrid internally on every call
383-
double Calculate::CalculateG(std::complex<double> *S1,
384-
std::complex<double> *S2,
385-
Parameters *para)
412+
//Calculate G
413+
double Calculate::CalculateG(std::complex<double> *S1, std::complex<double> *S2, Parameters *para)
386414
{
387415
ThetaGrid grid;
388416
BuildThetaGrid(para, grid);

0 commit comments

Comments
 (0)