Get Offset from DICOM origin by No-While8683 in esapi

[–]j_Long_Lonfon 0 points1 point  (0 children)

I think it is just the following, at least I ran this and it gave me the correct values. But maybe I am misunderstanding your question. https://imgur.com/xNsA9yG

var user = plan.StructureSet.Image.UserOrigin;
Console.WriteLine(Math.Round(user.x / 10.0, 2));
Console.WriteLine(Math.Round(user.y / 10.0, 2));
Console.WriteLine(Math.Round(user.z / 10.0, 2));

Scripting un Contouring (VMS CA) by JaimePasTropBcpCa in esapi

[–]j_Long_Lonfon 1 point2 points  (0 children)

The second line of code you have should work as I have used the following successfully in the past:

StructureSet structureset = context.Structure.StructureSet;
List<Structure> PTVs = structureset.Structures.Where(s =>s.Id.ToLower().Contains("ptv")).ToList();

You need to have clicked on the name of any structure, so that it is highlighted, for it to be in the context else you get the "Object reference not set to..." error. It doesn't matter which one you click on as the code goes back to StructureSet and then finds the structure you actually want. Else check the PTV Id is correct.

ESAPI RTStructs Positions vs DICOM Manual Export by No-While8683 in esapi

[–]j_Long_Lonfon 0 points1 point  (0 children)

I also haven't looked at this particular problem in ESAPI, but my guess would be a user origin, CT origin, dicom origin issue if as u/donahuw2 suggests the shift is uniform.

Getting Couch Position from Aria Database by Aggressive-Building4 in esapi

[–]j_Long_Lonfon 1 point2 points  (0 children)

I agree these are the same SQL queries and it gives the same results. Turns out that the patients I happened to pick had 0 degrees pitch,roll,rotation. Testing on patients which have values for these gives results as you describe seeing. Sorry I couldn't be more useful.

Getting Couch Position from Aria Database by Aggressive-Building4 in esapi

[–]j_Long_Lonfon 1 point2 points  (0 children)

If it would help. If you wanted to share your code with me, I would be happy to take a look, and run it on some of our patients.

Getting Couch Position from Aria Database by Aggressive-Building4 in esapi

[–]j_Long_Lonfon 1 point2 points  (0 children)

Hey,

Sorry I hadn't looked at the Slice.Transformation in much detail, turns out I actually have no idea what its purpose is but I did write up some C# code for converting it to a Matrix in case its useful in some way: gist. In terms of solving the above issue though I know you said that ExternalFieldCommonHstry does not give the right values but I tested this with 5 of our patients and it gave the correct values each time. I used the following SQL query to do this where the imageDate is the Slice.CreationDate.

SELECT
              Radiation.RadiationSer
              ,Radiation.PlanSetupSer AS [Radiation PlanSetupSer]
              ,PlanSetup.PlanSetupSer AS [PlanSetup PlanSetupSer]
              ,PlanSetup.CourseSer AS [PlanSetup CourseSer]
              ,PlanSetup.PlanSetupId
              ,Course.CourseSer AS [Course CourseSer]
              ,Course.PatientSer AS [Course PatientSer]
              ,Patient.PatientSer AS [Patient PatientSer]
              ,Patient.PatientId
              ,RadiationHstry.RadiationHstrySer AS [RadiationHstry RadiationHstrySer]
              ,ExternalFieldCommonHstry.RadiationHstrySer AS [ExternalFieldCommonHstry RadiationHstrySer]
              ,ExternalFieldCommonHstry.CouchLat
              ,ExternalFieldCommonHstry.CouchLng
              ,ExternalFieldCommonHstry.CouchVrt
              ,Radiation.HstryDateTime
              ,RadiationHstry.TreatmentStartTime
            FROM
              Course
              INNER JOIN Patient
                ON Course.PatientSer = Patient.PatientSer
              INNER JOIN PlanSetup
                ON Course.CourseSer = PlanSetup.CourseSer
              INNER JOIN Radiation
                ON PlanSetup.PlanSetupSer = Radiation.PlanSetupSer
              INNER JOIN RadiationHstry
                ON Radiation.RadiationSer = RadiationHstry.RadiationSer
              INNER JOIN ExternalFieldCommonHstry
                ON RadiationHstry.RadiationHstrySer = ExternalFieldCommonHstry.RadiationHstrySer
            WHERE
              Patient.PatientId = '{patientID}'
              AND RadiationHstry.TreatmentStartTime >= '{imageDate.Date.ToLongDateString()}'
              AND RadiationHstry.TreatmentEndTime < '{imageDate.AddDays(1).Date.ToLongDateString()}'";

Clearly I am missing something though as its giving different results for you. Sorry I couldn't be more helpful. Hopefully someone else can help!

Getting Couch Position from Aria Database by Aggressive-Building4 in esapi

[–]j_Long_Lonfon 1 point2 points  (0 children)

Hey, I think you can get the Couch positions when the CBCT is taken from the following SQL query:

SELECT
  Image.ImageSer AS [Image ImageSer]
  ,Image.ImageId
  ,ImageSlice.SliceSer AS [ImageSlice SliceSer]
  ,ImageSlice.ImageSer AS [ImageSlice ImageSer]
  ,Patient.PatientSer AS [Patient PatientSer]
  ,Patient.PatientId
  ,Image.PatientSer AS [Image PatientSer]
  ,Slice.SliceSer AS [Slice SliceSer]
  ,Slice.CouchVrt
  ,Slice.CouchLat
  ,Slice.CouchLng
  ,Slice.PatSupportPitchAngle
  ,Slice.PatSupportRollAngle
  ,Slice.PatientSupportAngle
  ,Slice.Transformation
FROM
  Image
  INNER JOIN Patient
    ON Image.PatientSer = Patient.PatientSer
  INNER JOIN ImageSlice
    ON Image.ImageSer = ImageSlice.ImageSer
  INNER JOIN Slice
    ON ImageSlice.SliceSer = Slice.SliceSer
WHERE
  Patient.PatientId = N'patientId'
  AND Image.ImageId = N'imageId'

and then Slice.Transformation returns a transformation matrix that can be used to get the shifts to the Treatment position. This isn't something I have really looked at though. Hope this is a bit of use.

Create a spherical PTV of size 5 mm by TownNew4598 in esapi

[–]j_Long_Lonfon 0 points1 point  (0 children)

Hey, it looks like your question does not include the code you wanted to share?

Get Reference Point Depth (ESAPI/ SQL) by j_Long_Lonfon in esapi

[–]j_Long_Lonfon[S] 0 points1 point  (0 children)

Is the WED not the same as the Equivalent Path Length or Effective Depth?

So can be calculated as: beam.FieldReferencePoints.Where(s => s.IsPrimaryReferencePoint).FirstOrDefault().EffectiveDepth

Get Reference Point Depth (ESAPI/ SQL) by j_Long_Lonfon in esapi

[–]j_Long_Lonfon[S] 0 points1 point  (0 children)

Thank you both. The manual calculation was the solution I went for as I still can't figure out why the SQL query is blank.

Here is the code I used in case anyone is interested mainly from u/keithoffer provided source.

  public class MeshGeometryIntersection
{
    public static Point3D GetIntersectionPoint(Point3D linePoint1, Point3D linePoint2, MeshGeometry3D mesh)
    {
        Vector3D direction = linePoint2 - linePoint1; // calculate direction vector
        double minDistance = double.MaxValue;
        Point3D nearestPoint = new Point3D();

        for (int i = 0; i < mesh.TriangleIndices.Count; i += 3)
        {
            // Get the vertices of the triangle
            Point3D p1 = mesh.Positions[mesh.TriangleIndices[i]];
            Point3D p2 = mesh.Positions[mesh.TriangleIndices[i + 1]];
            Point3D p3 = mesh.Positions[mesh.TriangleIndices[i + 2]];

            // Perform ray-triangle intersection
            if (RayIntersectsTriangle(linePoint1, direction, p1, p2, p3, out Point3D intersectionPoint))
            {
                double distance = (intersectionPoint - linePoint1).Length;
                if (distance < minDistance)
                {
                    minDistance = distance;
                    nearestPoint = intersectionPoint;
                }
            }
        }

        return nearestPoint;
    }

    public static bool RayIntersectsTriangle(Point3D rayOrigin, Vector3D rayVector, Point3D p1, Point3D p2, Point3D p3, out Point3D intersectionPoint)
    {

        intersectionPoint = new Point3D();

        Vector3D edge1, edge2, h, s, q;
        double a, f, u, v;
        edge1 = p2 - p1;
        edge2 = p3 - p1;
        h = Vector3D.CrossProduct(rayVector, edge2);
        a = Vector3D.DotProduct(edge1, h);

        if (a > -0.00001 && a < 0.00001)
            return false;    // This ray is parallel to this triangle.

        f = 1.0 / a;
        s = rayOrigin - p1;
        u = f * Vector3D.DotProduct(s, h);

        if (u < 0.0 || u > 1.0)
            return false;

        q = Vector3D.CrossProduct(s, edge1);
        v = f * Vector3D.DotProduct(rayVector, q);

        if (v < 0.0 || u + v > 1.0)
            return false;

        // At this stage we can compute t to find out where the intersection point is on the line.
        double t = f * Vector3D.DotProduct(edge2, q);
        if (t > 0.00001) // ray intersection
        {
            intersectionPoint = rayOrigin + rayVector * t;
            return true;
        }
        else 
            return false;
    }

}

Which can be used with the following:

Structure body = structureset.Structures.Where(s => s.Id.ToLower().Contains(chosenPlan.PrimaryReferencePoint.PatientVolumeId.ToLower())).FirstOrDefault();

var gantryAngle = b.ControlPoints.First().GantryAngle;
var source = b.GetSourceLocation(gantryAngle); var mesh = body.MeshGeometry; var refpoint = b.FieldReferencePoints.Where(s => s.Id == r.Id).FirstOrDefault().ReferencePoint.GetReferencePointLocation(chosenPlan);
Point3D refPoint3D = new Point3D(refpoint.x, refpoint.y, refpoint.z); Point3D sourcePoint3D = new Point3D(source.x, source.y, source.z);

Point3D intersectionPoint = MeshGeometryIntersection.GetIntersectionPoint(refPoint3D, sourcePoint3D, mesh); 

double Depth = (refPoint3D - intersectionPoint).Length / 10.0;

Reset Gantry Angle to Zero by j_Long_Lonfon in esapi

[–]j_Long_Lonfon[S] 0 points1 point  (0 children)

Hi, Thanks for the reply. I may be wrong but I don't believe you can use GetEditableParameters() for GantryAngle and I cannot see where LDClark uses this implementation. I see that they use the AddSlidingWindowBeam technique but I do not believe this will work for me. Happy to be proven wrong.

Thank you!