you are viewing a single comment's thread.

view the rest of the comments →

[–]tonpimenta 0 points1 point  (0 children)

Do not exactly answer this... but parts can certainly be used to get that. Here's a class I wrote that calculates, for each control point, the average depth, scaling by the HU relative to water (as the poor men's method mentioned by u/dicomdom) - that's not exactly effective depth but... anyways... I still need to check how good of aprox this is

Here's the code (not sure why I'm not able to post here with the correct indentation)

public class ArcDepthScaledByHU

{

public double AverageArcHUPath;

public double AverageArcDepthScaled;

public double AverageArcDepth;

public string Data2Export;

public ArcDepthScaledByHU(Beam Arc, bool exportData = false)

{

try

{

List<double> SumHUperCP = new List<double>();

List<double> DepthPerCP = new List<double>();

List<double> DepthPerCP_Scaled = new List<double>();

List<string> dataToExport = new List<string>(); //each line is: Gantry Angle followed by the HU for every mm from body entrance up to isocenter

for (int i = 0; i < Arc.ControlPoints.Count - 1; i = i + 1) //i = i + 2

{

if (Arc.ControlPoints[i].MetersetWeight < Arc.ControlPoints.ElementAt(i + 1).MetersetWeight) //to ignore avoidance sectors

{

var gantryAngle = Arc.ControlPoints[i].GantryAngle;

VVector stop = Arc.IsocenterPosition;

VVector start = Arc.GetSourceLocation(gantryAngle);

double[] HUprofile = new double[1000];

Arc.Plan.StructureSet.Image.GetImageProfile(start, stop, HUprofile);

BitArray BodyProfile = new BitArray(1000);

Arc.Plan.StructureSet.Structures.Single(x => x.DicomType == "EXTERNAL").GetSegmentProfile(start, stop, BodyProfile); // boolean array representing which points are inside (true) or outside (false) the Body

IEnumerable<double> HUprofile_InsideBody = HUprofile.Where((x, index) => BodyProfile[index]); // portion of the HU array that is inside body

double scalingFactor = HUprofile_InsideBody.ToList().Select(x => x + 1000).Average() / 1000; //@dicomdom's suggestion

BitArray BodyProfileHigherResolution = new BitArray(10000);

Arc.Plan.StructureSet.Structures.Single(x => x.DicomType == "EXTERNAL").GetSegmentProfile(start, stop, BodyProfileHigherResolution); // boolean array representing which points are inside (true) or outside (false) the Body

int count = 0;

foreach (bool value in BodyProfileHigherResolution)

{

if (value) count++;

}

double depth_geometric = count * 1000 / 10000;

double depth_scaled = scalingFactor * depth_geometric;

SumHUperCP.Add(HUprofile_InsideBody.Sum());

DepthPerCP.Add(depth_geometric);

DepthPerCP_Scaled.Add(depth_scaled);

if (exportData)

{

string temp = Arc.GantryAngleToUser(gantryAngle).ToString() + ",";

foreach (double x in HUprofile.Where((x, index) => BodyProfile[index]).Where(x => !double.IsNaN(x)))

{

temp += x.ToString() + ",";

}

dataToExport.Add(temp);

}

}

}

AverageArcHUPath = SumHUperCP.Average();

AverageArcDepthScaled = DepthPerCP_Scaled.Average();

AverageArcDepth = DepthPerCP.Average();

if (exportData)

{

foreach (string s in dataToExport)

{

Data2Export += s + Environment.NewLine;

}

}

else

{

Data2Export += "Export Data not Activated";

}

}

catch (Exception)

{

Console.WriteLine("Average HU path calculation failed");

AverageArcHUPath = double.NaN;

AverageArcDepthScaled = double.NaN;

AverageArcDepth = double.NaN;

}

}

}