Skip to content

Commit b6de15d

Browse files
committed
The last version flattened data in order [op1fx1 op1fx2 op2fx1 op2fx2...]. This version flattens data in order [op1fx1 op2fx2 op3fx1 ...]. These two version give same results. For both it bothers me that Chi2 converged is larger than initial guess. I thought reordering of flattened data would change something but it didn't. I guess that makes sense.
1 parent 79bc793 commit b6de15d

1 file changed

Lines changed: 27 additions & 19 deletions

File tree

inverse-solutions/r-of-fx-multi-op-prop-inversion.py

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,17 @@
4545
opsMeasured = Tissue(chromophoresMeasuredData, scattererMeasuredData, "", n=1.4).GetOpticalProperties(wavelengths)
4646
# Create measurements using Nurbs-based white Monte Carlo forward solver
4747
measurementForwardSolver = NurbsForwardSolver()
48-
# len(measuredROfFx)=16 (#wavelengths)x(#fxs) organized [op1fx1, op1fx2, op2fx1, op2fx2, ...]
49-
measuredROfFx= measurementForwardSolver.ROfFx(opsMeasured, fxs)
48+
# len(measuredROfFx)=(#fxs)x(#wavelengths) flattened
49+
measuredROfFx=np.concatenate(
50+
[np.array(measurementForwardSolver.ROfFx(opsMeasured, fxs[0]), dtype=float),
51+
np.array(measurementForwardSolver.ROfFx(opsMeasured, fxs[1]), dtype=float)])
5052
# Create a forward solver as a model function for inversion
5153
forwardSolverForInversion = PointSourceSDAForwardSolver()
5254

5355
# Declare local forward reflectance function that computes reflectance
5456
# from chromophores and scatterer values
5557
# valuesSought = [Hb, HbO2, A, b]
56-
def CalculateReflectanceVsWavelengthFromChromophoreConcentration(
58+
def CalculateReflectanceVsWavelengthFromChromophoreConcAndScatterer(
5759
valuesSought, wavelengths, fxs, forwardSolver):
5860
# Create a forward solve model function to solve inverse
5961
forwardSolverForInversion = PointSourceSDAForwardSolver()
@@ -66,19 +68,20 @@ def CalculateReflectanceVsWavelengthFromChromophoreConcentration(
6668
# Compose local tissue to obtain optical properties
6769
opsLocal = Tissue(chromophoresLocal, scattererLocal, "", n=1.4).GetOpticalProperties(wavelengths)
6870
# Compute reflectance for local absorbers
69-
modelDataLocal = Array.CreateInstance(float, len(wavelengths) * len(fxs))
70-
modelDataLocal = forwardSolver.ROfFx(opsLocal, fxs)
71-
modelDataForReturn= Array.CreateInstance(float, len(wavelengths) * len(fxs))
72-
for i in range(0, len(wavelengths) * len(fxs)):
71+
modelDataLocal=np.concatenate(
72+
[np.array(forwardSolver.ROfFx(opsLocal, fxs[0]), dtype=float),
73+
np.array(forwardSolver.ROfFx(opsLocal, fxs[1]), dtype=float)])
74+
modelDataForReturn=Array.CreateInstance(float, len(wavelengths)*len(fxs))
75+
for i in range(0, len(fxs)*len(wavelengths)-1):
7376
modelDataForReturn[i] = modelDataLocal[i]
7477
return modelDataForReturn
7578

7679
# func for residual
7780
def residual(valuesSought, wavelengths, fxs, measuredROfFx, forwardSolver):
78-
predictedROfFx= CalculateReflectanceVsWavelengthFromChromophoreConcentration(
81+
predictedROfFx= CalculateReflectanceVsWavelengthFromChromophoreConcAndScatterer(
7982
valuesSought, wavelengths, fxs, forwardSolver)
80-
difference = Array.CreateInstance(float,len(wavelengths) * len(fxs))
81-
for i in range(0,len(wavelengths) * len(fxs)):
83+
difference = Array.CreateInstance(float,len(wavelengths)*len(fxs))
84+
for i in range(0, len(fxs)*len(wavelengths)-1):
8285
difference[i] = predictedROfFx[i] - measuredROfFx[i]
8386
return difference
8487

@@ -90,7 +93,9 @@ def residual(valuesSought, wavelengths, fxs, measuredROfFx, forwardSolver):
9093
scattererInitialGuess = PowerLawScatterer(initialGuess[2], initialGuess[3])
9194
# Compose tissue for initial guess data to obtain OPs
9295
opsInitialGuess = Tissue(chromophoresInitialGuess, scattererInitialGuess, "", n=1.4).GetOpticalProperties(wavelengths)
93-
initialGuessROfFx = forwardSolverForInversion.ROfFx(opsInitialGuess, fxs)
96+
initialGuessROfFx=np.concatenate(
97+
[np.array(forwardSolverForInversion.ROfFx(opsInitialGuess, fxs[0]), dtype=float),
98+
np.array(forwardSolverForInversion.ROfFx(opsInitialGuess, fxs[1]), dtype=float)])
9499
# Run the levenberg-marquardt inversion
95100
from scipy.optimize import least_squares
96101
fit = least_squares(
@@ -106,24 +111,27 @@ def residual(valuesSought, wavelengths, fxs, measuredROfFx, forwardSolver):
106111
scattererFit = PowerLawScatterer(fit.x[2], fit.x[3])
107112
# Compose tissue for fit data to obtain OPs
108113
opsFit= Tissue(chromophoresFit, scattererFit, "", n=1.4).GetOpticalProperties(wavelengths)
109-
fitROfFx = forwardSolverForInversion.ROfFx(opsFit, fxs)
110-
# plot the results using Plotly data organization [op1fx1, op1fx2, op2fx1, op2,fx2,...]
114+
fitROfFx=np.concatenate(
115+
[np.array(forwardSolverForInversion.ROfFx(opsFit, fxs[0]), dtype=float),
116+
np.array(forwardSolverForInversion.ROfFx(opsFit, fxs[1]), dtype=float)])
117+
# plot the results using Plotly results flattened so have to unflat
111118
chart = go.Figure()
112119
xLabel = "wavelength [nm]"
113120
yLabel = "R(wavelength)"
114121
wvs = [w for w in wavelengths]
115122
# plot measured data first fx first
116123
meas= [m for m in measuredROfFx]
117-
chart.add_trace(go.Scatter(x=wvs, y=meas[::2], mode='markers', name='measured data: fx1'))
118-
chart.add_trace(go.Scatter(x=wvs, y=meas[1:len(meas):2], mode='markers', name='measured data: fx2'))
124+
midpoint=len(meas) // 2
125+
chart.add_trace(go.Scatter(x=wvs, y=meas[:midpoint], mode='markers', name='measured data: fx1'))
126+
chart.add_trace(go.Scatter(x=wvs, y=meas[midpoint:], mode='markers', name='measured data: fx2'))
119127
# plot initial guess data
120128
ig = [i for i in initialGuessROfFx]
121-
chart.add_trace(go.Scatter(x=wvs, y=ig[::2], mode='markers', name='initial guess: fx1'))
122-
chart.add_trace(go.Scatter(x=wvs, y=ig[1:len(ig):2], mode='markers', name='initial guess: fx2'))
129+
chart.add_trace(go.Scatter(x=wvs, y=ig[:midpoint], mode='markers', name='initial guess: fx1'))
130+
chart.add_trace(go.Scatter(x=wvs, y=ig[midpoint:], mode='markers', name='initial guess: fx2'))
123131
# plot fit: need to organize by fx
124132
conv = [f for f in fitROfFx]
125-
chart.add_trace(go.Scatter(x=wvs, y=conv[::2], mode='lines', name='converged: fx1'))
126-
chart.add_trace(go.Scatter(x=wvs, y=conv[1:len(conv):2], mode='lines', name='converged: fx2'))
133+
chart.add_trace(go.Scatter(x=wvs, y=conv[:midpoint], mode='lines', name='converged: fx1'))
134+
chart.add_trace(go.Scatter(x=wvs, y=conv[midpoint:], mode='lines', name='converged: fx2'))
127135
chart.update_layout( title="ROfFx (inverse solution for chromophore concentrations, multiple wavelengths, multiple fx)", xaxis_title=xLabel, yaxis_title=yLabel)
128136

129137
chart.show(renderer="browser")

0 commit comments

Comments
 (0)