Skip to content

Commit

Permalink
Merge tag 'v0.5.0.0' into maintenance
Browse files Browse the repository at this point in the history
  • Loading branch information
nlambriICH committed Apr 29, 2024
2 parents 2fd1d7e + addddb0 commit 7acac49
Show file tree
Hide file tree
Showing 71 changed files with 3,544 additions and 874 deletions.
12 changes: 12 additions & 0 deletions .github/workflows/reusable_build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ jobs:
steps:
- name: Check out repository
uses: actions/checkout@v2
- name: Install Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Setup env
run: |
cd TMIAutomation\Server
pip install . -r requirements.txt
- name: Build server app
run: |
cd TMIAutomation\Server
pyinstaller --clean --noconfirm --add-data "models;models" --add-data "config.yml;." --collect-submodules=pydicom src/app.py
- name: Add nuget to PATH
uses: nuget/setup-nuget@v1
- name: Add msbuild to PATH
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -366,4 +366,5 @@ FodyWeavers.xsd
TMIAutomation.Tests/Configuration/SensitiveData.txt
TMIAutomation/Library/
Docs/*
!Docs/*.pdf
!Docs/*.pdf
TMIAutomation.Tests/Dicoms/
Binary file modified Docs/TMIAutomation.pdf
Binary file not shown.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@

Plug-in script for the Eclipse Treatment Planning System to automate Total Marrow (Lymph-node) Irradiation (TMI/TMLI).

The script was introduced and validated in [this paper](https://doi.org/10.1007/s00066-022-02014-0).
The script was introduced and validated in [this paper](https://doi.org/10.1007/s00066-022-02014-0) on Strahlentherapie und Onkologie.

The generation of the field geometry of TMI/TMLI with deep-learning was introduced in [this paper](https://aapm.onlinelibrary.wiley.com/doi/10.1002/mp.17089) on Medical Physics.

If you liked/used this project, don't forget to give it a star! :star:

## Key features

* Field geometry for the TMI/TMLI upper-body generated with deep-learning models
* Automatic planning of the lower-extremities for TMI/TMLI
* Extendible to VMAT-TBI (Total Body Irradiation delivered with Volumetric Modulated Arc Therapy)

Expand Down Expand Up @@ -37,9 +40,6 @@ If you are on a research workstation (_TBox_), you can immediately run the scrip
by setting the database in research mode from the RT Administration module of Eclipse.
Otherwise, the plug-in script `TMIAutomation.esapi.dll` needs to be **approved** in the Eclipse application.

The `Configuration` folder contains config files with objectives and parameters to optimize the lower-extremities plan.
Example values are provided in order for the script to execute properly.

## Contributing

Any contribution/feedback is **greatly appreciated**!
Expand Down
6 changes: 6 additions & 0 deletions TMIAutomation.Runner/TMIAutomation.Runner.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,12 @@
IF %25ERRORLEVEL%25 GEQ 8 exit 1
IF $(ConfigurationName) == Debug-15.6 robocopy $(SolutionDir)$(SolutionName)\Configuration\ESAPI15 $(TargetDir)Configuration /mir
IF %25ERRORLEVEL%25 GEQ 8 exit 1
robocopy $(SolutionDir)$(SolutionName)\Configuration $(TargetDir)Configuration OARNames.txt
IF %25ERRORLEVEL%25 GEQ 8 exit 1
robocopy $(SolutionDir)$(SolutionName)\Configuration $(TargetDir)Configuration DCMExport.txt
IF %25ERRORLEVEL%25 GEQ 8 exit 1
robocopy $(SolutionDir)$(SolutionName)\Server\dist $(TargetDir)dist /mir /ns /nc /nfl /ndl
IF %25ERRORLEVEL%25 GEQ 8 exit 1
exit 0</PostBuildEvent>
</PropertyGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Values must be tab separated
# Lines starting with a hash sign '#' are ignored
# Empty lines are ignored
OptimizationAlgorithm DoseAlgorithm MLCID DosePerFraction NumberOfFractions
PO_15.6.06 AAA 15.06.06 MLC0010 2 1
OptimizationAlgorithm PO_15.6.06
DoseAlgorithm AAA 15.06.06
MLCID MLC0010
DosePerFraction 2
NumberOfFractions 1
TreatmentMachine TrueBeamSN1015
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Values must be tab separated
# Lines starting with a hash sign '#' are ignored
# Empty lines are ignored
OptimizationAlgorithm DoseAlgorithm MLCID DosePerFraction NumberOfFractions
PO 16.1.0 AAA 15.06.06 MLC0010 2 1
OptimizationAlgorithm PO 16.1.0
DoseAlgorithm AAA 15.06.06
MLCID MLC0010
DosePerFraction 2
NumberOfFractions 1
TreatmentMachine TrueBeamSN1015
12 changes: 12 additions & 0 deletions TMIAutomation.Tests/Configuration/OARNames.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Lines starting with a hash sign '#' are ignored
# Empty lines are ignored
brain
encefalo
lung
polmone
liver
fegato
bowel
intestino
bladder
vescica
38 changes: 24 additions & 14 deletions TMIAutomation.Tests/EntryPoint.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,28 @@ internal class EntryPoint
[STAThread]
public static void Main(string[] args)
{
ConfigOptOptions.Init();

using (EclipseApp = Application.CreateApplication())
{
string patientID = testData["PatientID"];
Patient patient = EclipseApp.OpenPatientById(patientID);
Course course = patient.Courses.FirstOrDefault(c => c.Id == testData["CourseID"]);
PlanSetup planSetup = course.PlanSetups.FirstOrDefault(ps => ps.Id == testData["PlanID"]);
PluginScriptContext scriptContext = new PluginScriptContext
{
Patient = patient,
Course = course,
PlanSetup = planSetup,
StructureSet = planSetup.StructureSet
};
EsapiWorker esapiWorker = new EsapiWorker(scriptContext);
PlanSetup planSetupLower = course.PlanSetups.FirstOrDefault(ps => ps.Id == testData["PlanIDLower"]);
PlanSetup planSetupUpper = course.PlanSetups.FirstOrDefault(ps => ps.Id == testData["PlanIDUpper"]);

SetUpContext(patient, course, planSetupLower, out PluginScriptContext scriptContextLower, out EsapiWorker esapiWorkerLower);

patient.BeginModifications();
try
{
TestBuilder.Create()
.Add<ModelBaseTests>(new ModelBase(esapiWorker), scriptContext)
.Add<ObjectiveSetupTests>(scriptContext.PlanSetup.OptimizationSetup, scriptContext.PlanSetup)
.Add<CalculationTests>(scriptContext.PlanSetup, scriptContext)
.Add<IsocenterTests>(scriptContext.PlanSetup, scriptContext)
.Add<StructureHelperTests>(scriptContext.StructureSet);
.Add<ModelBaseTests>(new ModelBase(esapiWorkerLower), scriptContextLower)
.Add<ObjectiveSetupTests>(scriptContextLower.PlanSetup.OptimizationSetup, scriptContextLower.PlanSetup)
.Add<CalculationTests>(scriptContextLower.PlanSetup, scriptContextLower)
.Add<IsocenterTests>(scriptContextLower.PlanSetup, planSetupUpper, scriptContextLower)
.Add<StructureHelperTests>(scriptContextLower.StructureSet)
.AddStatic<ClientTests>(patientID);
TestBase.RunTests();
}
catch (Exception e)
Expand All @@ -54,6 +52,18 @@ public static void Main(string[] args)
}
}

private static void SetUpContext(Patient patient, Course course, PlanSetup planSetupLower, out PluginScriptContext scriptContextLower, out EsapiWorker esapiWorkerLower)
{
scriptContextLower = new PluginScriptContext
{
Patient = patient,
Course = course,
PlanSetup = planSetupLower,
StructureSet = planSetupLower.StructureSet
};
esapiWorkerLower = new EsapiWorker(scriptContextLower);
}

private static Dictionary<string, string> InitializeTestData()
{
Dictionary<string, string> dict = new Dictionary<string, string>();
Expand Down
8 changes: 7 additions & 1 deletion TMIAutomation.Tests/TMIAutomation.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
<Compile Include="Attributes\TheoryAttribute.cs" />
<Compile Include="EntryPoint.cs" />
<Compile Include="Tests\CalculationTests.cs" />
<Compile Include="Tests\ClientTests.cs" />
<Compile Include="Tests\IsocenterTests.cs" />
<Compile Include="Tests\ObjectiveSetupTests.cs" />
<Compile Include="TestRunner\ITestBase.cs" />
Expand Down Expand Up @@ -105,6 +106,7 @@
<Content Include="Configuration\EUDOptimizationObjectives.txt" />
<Content Include="Configuration\ESAPI15\OptimizationOptions.txt" />
<Content Include="Configuration\ESAPI16\OptimizationOptions.txt" />
<Resource Include="Configuration\OARNames.txt" />
<Content Include="Configuration\PointOptimizationObjectives.txt" />
<Content Include="Configuration\SensitiveData.txt">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
Expand All @@ -121,7 +123,11 @@
<PostBuildEvent>IF $(ConfigurationName) == Debug-16.1 robocopy $(ProjectDir)Configuration\ESAPI16 $(TargetDir)Configuration /mir
IF %25ERRORLEVEL%25 GEQ 8 exit 1
IF $(ConfigurationName) == Debug-15.6 robocopy $(ProjectDir)Configuration\ESAPI15 $(TargetDir)Configuration /mir
robocopy $(ProjectDir)Configuration $(TargetDir)Configuration PointOptimizationObjectives.txt EUDOptimizationObjectives.txt SensitiveData.txt
robocopy $(ProjectDir)Configuration $(TargetDir)Configuration PointOptimizationObjectives.txt EUDOptimizationObjectives.txt SensitiveData.txt OARNames.txt
IF %25ERRORLEVEL%25 GEQ 8 exit 1
robocopy $(SolutionDir)$(SolutionName)\Server\dist $(TargetDir)dist /mir /ns /nc /nfl /ndl
IF %25ERRORLEVEL%25 GEQ 8 exit 1
robocopy $(ProjectDir)Dicoms $(TargetDir)Dicoms /mir /ns /nc /nfl /ndl
IF %25ERRORLEVEL%25 GEQ 8 exit 1
exit 0</PostBuildEvent>
</PropertyGroup>
Expand Down
7 changes: 7 additions & 0 deletions TMIAutomation.Tests/TestBuilder/TestBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,12 @@ public static TestBuilder Create()
throw new ArgumentException($"Could not find a private testObject of type {testObject.GetType()} in {testBase.GetType()}");
}
}

public TestBuilder AddStatic<T>(params object[] optParams) where T : ITestBase, new()
{
T testBase = new T();
testBase.Init(null, optParams).DiscoverTests();
return testBuilderInstance;
}
}
}
6 changes: 3 additions & 3 deletions TMIAutomation.Tests/Tests/CalculationTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ public override ITestBase Init(object testObject, params object[] optParams)

[Theory]
[InlineData("LowerBase")]
[InlineData("LowerBase1")]
private void AddBaseDosePlan(string expectedPlanId)
[InlineData("LowerBase")]
private void GetOrCreateBaseDosePlan(string expectedPlanId)
{
Course targetCourse = externalPlanSetup.Course;
ExternalPlanSetup newPlan = targetCourse.AddBaseDosePlan(externalPlanSetup.StructureSet);
ExternalPlanSetup newPlan = targetCourse.GetOrCreateBaseDosePlan(externalPlanSetup.StructureSet);
try
{
Assert.Equal(expectedPlanId, newPlan.Id);
Expand Down
Loading

0 comments on commit 7acac49

Please sign in to comment.