4545opsMeasured = Tissue (chromophoresMeasuredData , scattererMeasuredData , "" , n = 1.4 ).GetOpticalProperties (wavelengths )
4646# Create measurements using Nurbs-based white Monte Carlo forward solver
4747measurementForwardSolver = 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
5153forwardSolverForInversion = 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
7780def 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):
9093scattererInitialGuess = PowerLawScatterer (initialGuess [2 ], initialGuess [3 ])
9194# Compose tissue for initial guess data to obtain OPs
9295opsInitialGuess = 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
95100from scipy .optimize import least_squares
96101fit = least_squares (
@@ -106,24 +111,27 @@ def residual(valuesSought, wavelengths, fxs, measuredROfFx, forwardSolver):
106111scattererFit = PowerLawScatterer (fit .x [2 ], fit .x [3 ])
107112# Compose tissue for fit data to obtain OPs
108113opsFit = 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
111118chart = go .Figure ()
112119xLabel = "wavelength [nm]"
113120yLabel = "R(wavelength)"
114121wvs = [w for w in wavelengths ]
115122# plot measured data first fx first
116123meas = [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
120128ig = [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
124132conv = [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' ))
127135chart .update_layout ( title = "ROfFx (inverse solution for chromophore concentrations, multiple wavelengths, multiple fx)" , xaxis_title = xLabel , yaxis_title = yLabel )
128136
129137chart .show (renderer = "browser" )
0 commit comments