1+ # This is an example of python code using VTS to Compute fluence for a two-layer
2+ # medium as a function of radial extent and depth at a given set of optical properties
3+ #
4+ # Import PythonNet
5+ from pythonnet import load
6+ load ('coreclr' )
7+ import clr
8+ # Import the Operating System so we can access the files for the VTS library
9+ import os
10+ file = '../libraries/Vts.dll'
11+ clr .AddReference (os .path .abspath (file ))
12+ import numpy as np
13+ import plotly .graph_objects as go
14+ import plotly .express as px
15+ from Vts import *
16+ from Vts .Common import *
17+ from Vts .Extensions import *
18+ from Vts .Modeling .Optimizers import *
19+ from Vts .Modeling .ForwardSolvers import *
20+ from Vts .SpectralMapping import *
21+ from Vts .Factories import *
22+ from Vts .MonteCarlo import *
23+ from Vts .MonteCarlo .Sources import *
24+ from Vts .MonteCarlo .Tissues import *
25+ from Vts .MonteCarlo .Detectors import *
26+ from Vts .MonteCarlo .Factories import *
27+ from Vts .MonteCarlo .PhotonData import *
28+ from Vts .MonteCarlo .PostProcessing import *
29+ from System import Array , Double , Object , Func , Math
30+ clr .AddReference ("System.Core" )
31+ from System .Linq import Enumerable
32+
33+ solver = TwoLayerSDAForwardSolver ()
34+ solver .SourceConfiguration = SourceConfiguration .Distributed
35+
36+ distributedSolver = DistributedPointSourceSDAForwardSolver ()
37+
38+ topLayerThickness = 5
39+ opRegions = Array .CreateInstance (IOpticalPropertyRegion , 2 )
40+ opRegions [0 ] = LayerOpticalPropertyRegion (DoubleRange (0 , topLayerThickness , 2 ), OpticalProperties (0.1 , 1 , 0.8 , 1.4 ))
41+ opRegions [1 ] = LayerOpticalPropertyRegion (DoubleRange (topLayerThickness , Double .PositiveInfinity , 2 ), OpticalProperties (0.01 , 1 , 0.8 , 1.4 ))
42+ # Create the DoubleRange instance
43+ rhos_range = DoubleRange (0.1 , 19.9 , 100 ) # range of s-d separations in mm
44+
45+ # Convert to .NET array
46+ rho_delta = rhos_range .GetDelta ()
47+ print (rho_delta )
48+ # Start at 0.1, increment by 0.2, 100 elements
49+ rhos = 0.1 + rho_delta * np .arange (100 )
50+ print (rhos )
51+
52+ zs_range = DoubleRange (0.1 , 19.9 , 100 ) # range of depths in mm
53+
54+ # Convert to .NET array
55+ zs_delta = zs_range .GetDelta ()
56+ print (zs_delta )
57+ # Start at 0.1, increment by delta, 100 elements
58+ zs = 0.1 + zs_delta * np .arange (100 )
59+ print (zs )
60+
61+ opRegionsArray = Array [Array [IOpticalPropertyRegion ]]([opRegions ])
62+ # predict the tissue's fluence(rho, z) for the given optical properties
63+ fluence = solver .FluenceOfRhoAndZ (opRegionsArray , rhos , zs );
64+ independentAxes = Array .CreateInstance (IndependentVariableAxis , 1 )
65+ independentAxes [0 ] = IndependentVariableAxis .Z
66+ independentValues = Array .CreateInstance (Array [Double ], 2 )
67+ independentValues [0 ] = Array [Double ](rhos .tolist ())
68+ independentValues [1 ] = Array [Double ](zs .tolist ())
69+ fluenceOfRhoAndZ = ComputationFactory .ComputeFluence (distributedSolver , FluenceSolutionDomainType .FluenceOfRhoAndZ , independentAxes , independentValues , opRegions , Array [Double ](rhos .tolist ()))
70+
71+ #PHD
72+ sourceDetectorSeparation = 10
73+ opArray = Array .CreateInstance (OpticalProperties , 2 )
74+ opArray [0 ] = OpticalProperties (0.1 , 1 , 0.8 , 1.4 )
75+ opArray [1 ] = OpticalProperties (0.01 , 1 , 0.8 , 1.4 )
76+
77+ phdOfRhoAndZ = ComputationFactory .GetPHD (ForwardSolverType .TwoLayerSDA , fluence , sourceDetectorSeparation , opArray , Array [Double ](rhos .tolist ()), Array [Double ](zs .tolist ()))
78+
79+ allRhos = np .concatenate ((- rhos [::- 1 ], rhos ))
80+ print ("*********************************** RHOS *****************************************" )
81+ print (allRhos .tolist ())
82+
83+ # log transform
84+ log_phd = [Math .Log (f ) for f in phdOfRhoAndZ ]
85+ log_fluence = [Math .Log (f ) for f in fluenceOfRhoAndZ ]
86+
87+ size = len (zs )
88+ # split into rows
89+ phdRowsToPlot = np .array ([log_phd [i :i + size ] for i in range (0 , len (log_phd ), size )])
90+ fluenceRowsToPlot = np .array ([log_fluence [i :i + size ] for i in range (0 , len (log_fluence ), size )])
91+ # reverse and concatenate
92+ allFluenceRowsToPlot = np .concatenate ((fluenceRowsToPlot [::- 1 ], phdRowsToPlot ))
93+
94+ def heatmap (values , x , y , x_label = "" , y_label = "" , title = "" ):
95+ """Create a heatmap chart."""
96+ # values should be a 2D array-like (list of lists or 2D numpy array)
97+ fig = go .Figure (data = go .Heatmap (
98+ z = values ,
99+ x = x ,
100+ y = y ,
101+ transpose = True ,
102+ colorscale = 'Hot' ,
103+ colorbar = dict (title = title )
104+ ))
105+ fig .update_layout (
106+ title = title ,
107+ xaxis_title = x_label ,
108+ yaxis_title = y_label ,
109+ yaxis_autorange = 'reversed'
110+ )
111+ return fig
112+
113+ fluenceChart = heatmap (allFluenceRowsToPlot .tolist (), allRhos .tolist (), list (zs ), "ρ [mm]" , "z [mm]" , "log(phd(ρ, z) [mm-2])" )
114+ fluenceChart .show (renderer = "browser" )
0 commit comments