public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // Load the JSON for the Result into a JObject var jo = JObject.Load(reader); var unitJO = (JValue)jo[nameof(DoseProfile.Unit)]; var unit = serializer.Deserialize <DoseUnit>(unitJO.CreateReader()); // Load the JSON for the Result into a JObject var ja = JArray.Load(jo["Points"].CreateReader()); var points = ja .Select(j => serializer.Deserialize <ProfilePoint>(((JObject)j).CreateReader())) .ToList(); var first = points[0]; var second = points[1]; var values = points.Select(p => p.Value).ToList(); // Construct the Result object using the non-default constructor var dp = new DoseProfile(first.Position, second.Position - first.Position, values.ToArray(), unit); // Return the result return(dp); }
public static DoseValue CalculateMeanDose(PlanSetup plan, Structure structure) { Dose dose = plan.Dose; if (dose == null) { return(new DoseValue(Double.NaN, DoseValue.DoseUnit.Unknown)); } plan.DoseValuePresentation = DoseValuePresentation.Absolute; double sum = 0.0; int count = 0; double xres = 2.5; double yres = 2.5; double zres = 2.5; int xcount = (int)((dose.XRes * dose.XSize) / xres); System.Collections.BitArray segmentStride = new System.Collections.BitArray(xcount); double[] doseArray = new double[xcount]; DoseValue.DoseUnit doseUnit = dose.DoseMax3D.Unit; for (double z = 0; z < dose.ZSize * dose.ZRes; z += zres) { for (double y = 0; y < dose.YSize * dose.YRes; y += yres) { VVector start = dose.Origin + dose.YDirection * y + dose.ZDirection * z; VVector end = start + dose.XDirection * dose.XRes * dose.XSize; SegmentProfile segmentProfile = structure.GetSegmentProfile(start, end, segmentStride); DoseProfile doseProfile = null; for (int i = 0; i < segmentProfile.Count; i++) { if (segmentStride[i]) { if (doseProfile == null) { doseProfile = dose.GetDoseProfile(start, end, doseArray); } double doseValue = doseProfile[i].Value; if (!Double.IsNaN(doseValue)) { sum += doseProfile[i].Value; count++; } } } doseProfile = null; } } double mean = sum / ((double)count); return(new DoseValue(mean, doseUnit)); }
public void SerializeDeserializeDoseProfile() { var v1 = new VVector(1, 2, 3); var v2 = new VVector(4, 5, 6); var dp = new DoseProfile(v1, v2, new double[] { 0.1, 0.2 }, DoseValue.DoseUnit.Percent); var serialized = FacadeSerializer.Serialize(dp); var deserialized = FacadeSerializer.Deserialize <DoseProfile>(serialized); Assert.AreEqual(deserialized.Count, 2); Assert.AreEqual(dp[0], deserialized[0]); Assert.AreEqual(dp[1], deserialized[1]); Assert.AreEqual(dp.Unit, deserialized.Unit); }
/// <summary> /// Calculate a total volume for the loaded patient plan on given percent level of prescitoion dose /// and display the result in message box. /// </summary> /// <param name="curPlan"> the current loaded patient plan</param> /// <param name="percentVal"> the percent level of prescition dose</param> /// <returns></returns> public double CalculateVolAtPercentPresDose(PlanSetup curPlan, double percentVal) { double totalVol = 0.0; int totalNum = 0; // get total prescribed dose, only consider on single plan for this excercise var presDose = curPlan.TotalDose.Dose; curPlan.DoseValuePresentation = DoseValuePresentation.Absolute; var curPlanDose = curPlan.Dose; int xDoseCount = curPlanDose.XSize; // allocated buffer for dose array in x direction double[] xDoseVals = new double[xDoseCount]; var percentDose = presDose * percentVal / 100; // search through 3D dose matrix for (double z = 0.0; z < curPlanDose.ZSize * curPlanDose.ZRes; z += curPlanDose.ZRes) { for (double y = 0.0; y < curPlanDose.YSize * curPlanDose.YRes; y += curPlanDose.YRes) { // get first and last point to extract dose profile with given z and y VVector start = curPlanDose.Origin + curPlanDose.YDirection * y + curPlanDose.ZDirection * z; VVector stop = start + curPlanDose.XDirection * curPlanDose.XRes * (curPlanDose.XSize - 1); DoseProfile profile = null; profile = curPlanDose.GetDoseProfile(start, stop, xDoseVals); // compare doses in x direction foreach (var profilePoint in profile) { if (profilePoint.Value >= percentDose) { totalNum++; } } } } // calculate total Volume in cm totalVol = curPlanDose.XRes * curPlanDose.YRes * curPlanDose.ZRes * totalNum / 1000.0; return(Math.Round(totalVol, 2)); }
private double Get_Gamma(DoseProfile dp, Tuple <double, double> tdd, double v1, double v2, ProfilePoint pp, string axisDir, double norm_factor) { //throw new NotImplementedException(); List <double> gamma_values = new List <double>(); double dd = 0.02 * norm_factor; //2% double dta = 2; //2mm int loc = dp.ToList().IndexOf(pp); //search backward 10* the dta int start = loc - 10 * dta < 0 ? 0 : loc - Convert.ToInt16(10 * dta); int end = loc + 10 * dta > dp.Count() ? dp.Count() : loc + Convert.ToInt16(10 * dta); for (double i = start; i < end - 1; i += 0.1) { int r0 = (int)Math.Floor(i); int r1 = (int)Math.Ceiling(i); //find the position in the doseprofile. double x0 = axisDir == "X" ? dp[r0].Position.x : dp[r0].Position.y + 200; double x1 = axisDir == "X" ? dp[r1].Position.x : dp[r1].Position.y + 200; //find the value in the dose profeil. double y0 = dp[r0].Value; double y1 = dp[r1].Value; double dos = 0; double pos = 0; if (r0 == r1) { //cannot linearly interpolate between the same number pos = x0; dos = y0; } else { pos = x0 + (i - r0) * (x1 - x0) / (r1 - r0); dos = y0 + (i - r0) * (y1 - y0) / (r1 - r0); } double gamma = Math.Sqrt(Math.Pow((pos - tdd.Item1) / dta, 2) + Math.Pow((dos / norm_factor * 100 - tdd.Item2) / dd, 2)); gamma_values.Add(gamma); } //return the minumum gamma value. return(gamma_values.Min()); }
private void CalculateDoseProfiles() { if (SelectedPlan != null) { planSetup = course.PlanSetups.FirstOrDefault(x => x.Id == SelectedPlan); double[] depths = new double[] { 15, 50, 100, 200, 300 };//mm List <DoseProfile> profiles = new List <DoseProfile>(); foreach (Beam b in planSetup.Beams) { foreach (double d in depths) { double x1 = b.ControlPoints.First().JawPositions.X1; double x2 = b.ControlPoints.First().JawPositions.X2; VVector start = new VVector(x1 - 50, d - 200, 0); VVector end = new VVector(x2 + 50, d - 200, 0); DoseProfile prof = b.Dose.GetDoseProfile( start, end, new double[Convert.ToInt16(end.x - start.x + 1)]); DoseProfileData += $"Profile - d {d}mm - FS {(x2 - x1) / 10}cm\n"; profiles.Add(prof); } } _eventAggregator.GetEvent <UpdatePlotEvent>().Publish(profiles); } }
public void Execute(ScriptContext context /*, System.Windows.Window window, ScriptEnvironment environment*/) { // TODO : Add here the code that is called when the script is launched from Eclipse. //get access to the plan. PlanSetup ps = context.PlanSetup; Dose d = ps.Dose; //create a vector where the dose profile will start. VVector start = new VVector(); start.x = -100; //mm start.y = -100; //location from the dicom origin. start.z = 0; VVector end = new VVector(); end.x = 100; end.y = start.y; end.z = start.z; //size of the doseprofile. double[] size = new double[201]; DoseProfile dp = d.GetDoseProfile(start, end, size); //write this doseprofile to a csv file. string filename = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\profile.csv"; using (StreamWriter sw = new StreamWriter(filename)) { sw.WriteLine("Position,Dose"); foreach (ProfilePoint pp in dp) { sw.WriteLine(String.Format("{0},{1}", pp.Position.x, pp.Value)); } } }
/// <summary> /// Return collapsed 1D dose profile /// </summary> /// <param name="profile"> DoseProfile to collapse</param> /// <returns>Array of double[2] of location and doseValue. /// Location at profile start is set to 0 with subsequent values set at distance from start. /// </returns> public static double[][] flattenProfile(DoseProfile profile) { var start = profile.ElementAt(0).Position; return(profile.Select(pp => new double[] { (pp.Position - start).Length, pp.Value }).ToArray()); }
public void Execute(ScriptContext context /*, System.Windows.Window window*/) { PlanSetup plan = context.PlanSetup; StructureSet ss = context.StructureSet; if (plan == null) { MessageBox.Show("Load a plan!"); return; } if (plan.IsDoseValid == false) { MessageBox.Show("plan has no dose calculated!"); return; } //User places point called "TopLeft" in top left corner where scan will start before running script Structure refMarker = (from s in ss.Structures where s.Id == "TopLeft" select s).FirstOrDefault(); if (refMarker == null) { MessageBox.Show("No marker point called TopLeft found."); return; } VVector topLeft = refMarker.CenterPoint; //User places point called "BottomRight" in bottom right corner where scan will stop before running script Structure refMarker2 = (from s in ss.Structures where s.Id == "BottomRight" select s).FirstOrDefault(); if (refMarker == null) { MessageBox.Show("No marker point called BottomRight found."); return; } VVector bottomRight = refMarker2.CenterPoint; VVector topRight = new VVector(bottomRight.x, topLeft.y, topLeft.z); VVector bottomLeft = new VVector(topLeft.x, topLeft.y, bottomRight.z); int column = 255; // arbitrarily make 255x255 (since that's what Excel can handle) int row = 255; double[] buffer = new double[column]; double xDist = (VVector.Distance(topLeft, topRight)) / (double)column; string filename = string.Format(@"c:\temp\doseplane.csv"); using (System.IO.StreamWriter sw = new System.IO.StreamWriter(filename, false, Encoding.ASCII)) { sw.Write("Y[cm]...X[cm],"); for (int i = 0; i < column; i++) { sw.Write("{0},", MMtoCM(Math.Round(topLeft.x + (xDist * i), 3))); } sw.WriteLine(""); double zDist = (VVector.Distance(topLeft, bottomLeft)) / (double)row; for (int j = 0; j < row; j++) { // figure out new start and stop points for the row we are scanning, then get the dose profile (scan it) double newZ = topLeft.z - (zDist * j); VVector newRowStart = topLeft; VVector newRowEnd = topRight; newRowStart.z = newZ; newRowEnd.z = newZ; // scan the row DoseProfile dp = plan.Dose.GetDoseProfile(newRowStart, newRowEnd, buffer); sw.Write("{0},", MMtoCM(Math.Round(newZ, 3))); foreach (var profilePt in dp) { sw.Write("{0},", Math.Round(profilePt.Value, 6)); } sw.WriteLine(""); } sw.Flush(); sw.Close(); MessageBox.Show(string.Format(@"File written to '{0}'", filename), "Varian Developer"); } // 'Start' generated CSV file to launch Excel window System.Diagnostics.Process.Start(filename); // Sleep for a few seconds to let Excel to start System.Threading.Thread.Sleep(TimeSpan.FromSeconds(2)); }
private void OnCompareScan() { //prevScans_sp.Children.Clear();//we will refill this stackpanel with results later. PlanSetup ps = SelectedPlan; foreach (DataScan ds in ds_list) { //find a beam with the same field size as the scan. string s_output = ""; Beam b_keep = null; foreach (Beam b in ps.Beams) { double x1 = b.ControlPoints.First().JawPositions.X1; double x2 = b.ControlPoints.First().JawPositions.X2; double y1 = b.ControlPoints.First().JawPositions.Y1; double y2 = b.ControlPoints.First().JawPositions.Y2; if (Math.Abs(x2 - x1 - ds.FieldX) < 0.1 && Math.Abs(y2 - y1 - ds.FieldY) < 0.1) { b_keep = b;//found a winner! break; } } if (b_keep == null) { s_output = "No Scan"; } //could not find the similar field. else { //analyze the field. //start by gettig the dose profile. VVector start = new VVector(); start.x = ds.axisDir == "X" ? ds.scan_data.First().Item1 : 0; start.y = ds.axisDir == "X" ? ds.depth - 200 : ds.scan_data.First().Item1 - 200; //-200 because of the conversion from depth to dicom coordinate. start.z = 0; //crossline profiles only! VVector end = new VVector(); end.x = ds.axisDir == "X" ? ds.scan_data.Last().Item1 : start.x; end.y = ds.axisDir == "X" ? start.y : ds.scan_data.Last().Item1 - 200; end.z = start.z; double[] size = new double[ds.scanLength];//make data arrays the same size. DoseProfile dp = b_keep.Dose.GetDoseProfile(start, end, size); //normalization factor (eclipse calcs not normalized) double norm_factor = ds.axisDir == "X" ? //if this is a profile dp.Where(x => x.Position.x >= 0).First().Value : //norm to central axis. dp.Max(x => x.Value); //for PDD normalizeto max dose. //write the data to the desktop using (StreamWriter sw = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\Scan" + ds.FieldX.ToString() + "X" + ds.FieldY.ToString() + "_" + ds.depth.ToString() + ".csv")) { sw.WriteLine("Scan Pos, Scan Dose, Calc Pos, Calc Dose, Gamma"); foreach (Tuple <double, double> tdd in ds.scan_data) { //check the profile point to make sure a point exists in the doseprofile. IEnumerable <ProfilePoint> pp_check = ds.axisDir == "X" ? dp.Where(x => x.Position.x >= tdd.Item1) : dp.Where(x => x.Position.y + 200 >= tdd.Item1); ProfilePoint pp; //if there is not profile point, then you cannot do that gamma analysis. if (pp_check.Count() == 0) { break; } else { pp = pp_check.First(); } //but if there is a profile point, take the first. //get calculated position and dose (from eclipse profile) string calc_pos = ds.axisDir == "X" ? pp.Position.x.ToString() : Convert.ToString(pp.Position.y + 200); string calcdos = Convert.ToString(pp.Value / norm_factor * 100); double gam = Get_Gamma(dp, tdd, Convert.ToDouble(calc_pos), Convert.ToDouble(calcdos), pp, ds.axisDir, norm_factor); //write data to csv sw.WriteLine(String.Format("{0},{1},{2},{3},{4}", tdd.Item1, tdd.Item2, calc_pos, calcdos, gam)); } sw.Flush(); s_output = "Success"; } } } }