using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.ComponentModel.Design; using System.ComponentModel; using static WPFUI.PTAccess; using System.Windows.Threading; using System.Globalization; using System.Runtime.CompilerServices; namespace WPFUI { /// /// Interaction logic for MainWindow.xaml /// /// public enum SpecialFeatures { None, Color, Highlight } public class DoubleRangeRule : ValidationRule { public double Min { get; set; } public double Max { get; set; } public override ValidationResult Validate(object value, CultureInfo cultureInfo) { double parameter = 0; try { if (((string)value).Length > 0) { parameter = Double.Parse((String)value); } } catch (Exception e) { MessageBox.Show("Illegal characters or " + e.Message, "Warning ", MessageBoxButton.OK, MessageBoxImage.Warning); return new ValidationResult(false, "Illegal characters or " + e.Message); } if ((parameter < this.Min) || (parameter > this.Max)) { MessageBox.Show("Invalid Dice Threshold. Enter a number between " + this.Min +" and "+ this.Max, "Warning ", MessageBoxButton.OK, MessageBoxImage.Warning); return new ValidationResult(false, "Please enter value in the range: " + this.Min + " - " + this.Max + "."); } return new ValidationResult(true, null); } } public partial class MainWindow : Window, INotifyPropertyChanged { private double diceThreshold = 0.33; public double DiceThreshold { get { return diceThreshold; } set { diceThreshold = value; OnPropertyChanged("DiceThreshold"); } } public static char[] charsToTrim = { '*', ' ', '\'' }; public static string PatientName { get; set; } = string.Empty; public static List trials { get; set; } = new List(); public static List structures { get; set; } = new List(); public static List ctName { get; set; } = new List(); public static List strucSetNames { get; set; } = new List(); // public static List strucNames { get; set; } = new List(); public static int CTindex { get; set; } = new int(); public static int StrSetIndex { get; set; } = new int(); const double DiceThresholdDefault = 0.33; public List InitList(int count, T initValue) { return Enumerable.Repeat(initValue, count).ToList(); } public class VelocityStructure { public int Num { get; set; } = new int(); public string Name { get; set; } = ""; } public static List strucNames { get; set; } = new List(); public class VelocityDB { public string MyVelocityDB { get; set; } = System.String.Empty; // public string IPadddress { get; set; } = string.Empty; // public int Port { get; set; } = new int(); public string User { get; set; } = string.Empty; public string Passwd { get; set; } = string.Empty; } public List velocityDB { get; set; } = new() { new VelocityDB { User = "codey", Passwd = "Rttqa123", MyVelocityDB = "RTTQA-2" }, new VelocityDB { User = "codey", Passwd = "Rttqa123", MyVelocityDB = "VMS_RESEARCH" }, new VelocityDB { User = "codey", Passwd = "Rttqa123", MyVelocityDB = "RTTQA-1" }, new VelocityDB { User = "codey", Passwd = "Rttqa123", MyVelocityDB = "RTTQA-3" } }; public class EditableStructures : INotifyPropertyChanged { public string StrName { get; set; } public bool IsAccepted { get; set; } public int NamInd { get; set; } private SpecialFeatures _specialFeatures; public SpecialFeatures SpecialFeatures { get { return _specialFeatures; } set { _specialFeatures = value; OnPropertyChanged("SpecialFeatures"); } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string name) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); } } public ObservableCollection AutoNames { get; set; } /*------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*------------------------------------------------------------------------------------------------------------------------------------------------------*/ private void UpdateTrials() { TrialDB.ItemsSource = trials; } public MainWindow() { InitializeComponent(); DataContext = this; AutoNames = new ObservableCollection(); DBAccess db = new DBAccess(); trials = db.GetTrials(); // LOAD AND DISPLAY PROTOCOL TRIAL NAMEs if (trials.Count <= 0) { MessageBox.Show("No trial foud in DataBase", "Error", MessageBoxButton.OK, MessageBoxImage.Error); return; } UpdateTrials(); PTAccess pt = new PTAccess(); pt.InitializeVelocity(); } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string name = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); } private void emptyProtocolListbox() { ProtocolStructures.ItemsSource = null; ProtocolStructures.Items.Clear(); ProtocolStructures.Items.Refresh(); } private void emptyCTnamesListbox() { PTAccess pt = new PTAccess(); CTnames.ItemsSource = null; CTnames.Items.Clear(); CTnames.Items.Refresh(); StructSets.ItemsSource = null; StructSets.Items.Clear(); StructSets.Items.Refresh(); pt.ResetVelocityContext(); } private void emptyStructSetsListbox() { StructSets.ItemsSource = null; StructSets.Items.Clear(); StructSets.Items.Refresh(); } private void emptyVelStructuresListbox() { VelStructures.ItemsSource= null; VelStructures.Items.Clear(); VelStructures.Items.Refresh(); } private void emptyEditableStructsListBox() { AutoNames.Clear(); EditableStructs.ItemsSource = null; EditableStructs.Items.Clear(); EditableStructs.Items.Refresh(); } private void UpdateProtocol() { ProtocolStructures.ItemsSource = (System.Collections.IEnumerable)structures; } private void UpdateCT() { CTnames.ItemsSource = (System.Collections.IEnumerable)ctName; CTnames.Items.Refresh(); } private void UpdateStructSet() { StructSets.ItemsSource = (System.Collections.IEnumerable)strucSetNames; } public void UpdateVelStructures() { VelStructures.ItemsSource = (System.Collections.IEnumerable)strucNames; VelStructures.Items.Refresh(); } public void UpdateAutoStrucNames() { EditableStructs.ItemsSource = (System.Collections.IEnumerable)AutoNames; } /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*------------------------------------------------------- LOAD AND DISPLAY PROTOCOL TRIAL NAMEs ----------------------------------------------------------------------------*/ private void TrialDB_SelectionChanged(object sender, SelectionChangedEventArgs e) { DBAccess db = new DBAccess(); int TrialDBind = TrialDB.SelectedIndex; string trialNam = TrialDB.SelectedItem.ToString(); if (String.IsNullOrEmpty(trialNam)) { MessageBox.Show("No Trial has been selected", "Warning ", MessageBoxButton.OK, MessageBoxImage.Warning); return; } structures = db.GetStructures(trialNam); UpdateProtocol(); emptyEditableStructsListBox(); } /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------- TRIAL-NAME-ERASED EVENT HANDLER -------------------------------------------------------------------------------------*/ private void Trial_TextChanged(object sender, TextChangedEventArgs e) { PTAccess pt = new PTAccess(); emptyProtocolListbox(); structures.Clear(); EditableStructs.ItemsSource = null; EditableStructs.Items.Clear(); EditableStructs.Items.Refresh(); pt.RenamedStructNames.Clear(); } /*-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*------------------------------------------------------- TRIAL-NAME-CHANGED EVENT HANDLER ----------------------------------------------------------------------------*/ /* private void Trial_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e) { DBAccess db = new DBAccess(); structures = db.GetStructures(Trial.Text); UpdateProtocol(); } */ /*--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*------------------------------------------------------- LOAD PATIENT AND DISPLAY PATIENT CT VOLUMEs -----------------------------------------------------------------*/ private void PatientScan_Click(object sender, RoutedEventArgs e) { // if (CTnames.SelectedIndex == -1) // return; string content = Patient.Text; // CHECK IF PATIENT NAME HAS CHANGED content = content.Trim(charsToTrim); // TRIM HEADING AND TRAILING SPACES if(String.IsNullOrEmpty(content)) { MessageBox.Show("Patient has to be loaded before loading any CT !.", "Warning ", MessageBoxButton.OK, MessageBoxImage.Warning); return; } if (content.Equals(PatientName)) return; PatientName = content; int Res = 0; PTAccess pt = new PTAccess(); ctName = pt.GetCTVol(PatientName, ref Res); // GET PATIENT CT VOLUMES if(Res == -1) // PATIENT NOT LOADED { Patient.Clear(); PatientName = System.String.Empty; Patient.Text = " "; } if (ctName == null) { MessageBox.Show("Cannot find any CT for current patient Make another choice!.", "Warning ", MessageBoxButton.OK, MessageBoxImage.Warning); } UpdateCT(); } /*-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*--------------------------------------------------------- PATIENT-TEXT-CHANGE HANDLER --------------------------------------------------------------------------------------------*/ /*------------------------------- Wipe out the CTs list, the Structure-Sets list, the Velocity-Strutures list, the Editabe-Structures list ------------------------------------*/ /* */ private void Patient_TextChanged(object sender, TextChangedEventArgs e) { emptyCTnamesListbox(); emptyStructSetsListbox(); emptyVelStructuresListbox(); emptyEditableStructsListBox(); return; } /*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*-------------------------------------------------- CT-NAME SELECTION EVENT HANDLER ----------------------------------------------------------------------------------------*/ /*---------------- Load and display the Structure-sets of the selected CT volume -----------------------------------------------------------------------------------------------*/ /* */ private void CTnames_SelectionChanged(object sender, SelectionChangedEventArgs e) { if(CTnames.ItemsSource == null) { return; } string CTvalue = CTnames.SelectedItem.ToString(); // BREAK-POINT HERE TO CHECK NAME OF SELECTED CT int Res = 0; CTindex = CTnames.SelectedIndex; emptyStructSetsListbox(); emptyVelStructuresListbox(); emptyEditableStructsListBox(); // DiceThreshold = DiceThresholdDefault; // DiceTol.Text = DiceThresholdDefault.ToString(); PTAccess pt = new PTAccess(); pt.RenamedStructNames.Clear(); strucSetNames = pt.GetStructSet(CTindex, Res); if (strucSetNames != null) { UpdateStructSet(); } else { MessageBox.Show("Cannot find any structure-set for current CT.", "Warning ", MessageBoxButton.OK, MessageBoxImage.Warning); UpdateCT(); // DiceThreshold = DiceThresholdDefault; // DiceTol.Text = DiceThresholdDefault.ToString(); } } /*--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*------------------------------------------------- STRUCTURE-SET-SELECTION EVENT HANDLER ----------------------------------------------------------------------------------*/ /* */ private void StructSets_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (StructSets.SelectedIndex == -1) // IF NO SELECTION UPDATE AGAIN STRUCTURE-SETs LIST return; string structSetValue = StructSets.SelectedItem.ToString(); // BREAK-POINT HERE TO CHECK NAME OF SELECTED STRUCTURE-SET StrSetIndex = StructSets.SelectedIndex; emptyVelStructuresListbox(); emptyEditableStructsListBox(); PTAccess pt = new PTAccess(); List VelNam = pt.GetStructures(StrSetIndex, PatientName); if (VelNam == null) { MessageBox.Show("Cannot find any structure for current structure-set.", "Warning ", MessageBoxButton.OK, MessageBoxImage.Warning); UpdateStructSet(); } strucNames.Clear(); int j = 1; foreach (string str in VelNam) { strucNames.Add(new VelocityStructure { Name = str, Num = j }); j++; } // DiceThreshold = DiceThresholdDefault; // DiceTol.Text = DiceThresholdDefault.ToString(); UpdateVelStructures(); } /*------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*------------------------------------------------------------ CHANGING DICE THRESHOLD EVENT HANDLER-------------------------------------------------------------------------------*/ /* */ private void DiceTol_TextChanged(object sender, TextChangedEventArgs e) { if (0 <= DiceThreshold & DiceThreshold <= 1) { // MessageBox.Show("Invalid Dice Threshold. Enter a number between 0 and 1", "Warning ", MessageBoxButton.OK, MessageBoxImage.Warning); // DiceThreshold = DiceThresholdDefault; // DiceTol.Text = DiceThresholdDefault.ToString(); emptyEditableStructsListBox(); return; } } /*------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*------------------------------------------------------------ DISPLAY AUTO-MATCHED STRUCTUREs EVENT HANDLER-------------------------------------------------------------------------------*/ /* */ private void AutoMatchedStruct_Click(object sender, RoutedEventArgs e) { emptyEditableStructsListBox(); if (DiceThreshold < 0 | DiceThreshold > 1) { MessageBox.Show("DiceThreshold invalid. Enter a number between 0 and 1", "Warning ", MessageBoxButton.OK, MessageBoxImage.Warning); DiceThreshold = DiceThresholdDefault; DiceTol.Text = DiceThresholdDefault.ToString(); return; } if (structures.Count <= 0) // CHECKS PROTOCOL STRUCTUREs HAVE BEEN LOADED { MessageBox.Show("Protocol structures must be loaded Before renaming can start.", "Warning ", MessageBoxButton.OK, MessageBoxImage.Warning); return; } if(strucNames.Count <= 0) { MessageBox.Show("Patient structures must be loaded Before renaming can start.", "Warning ", MessageBoxButton.OK, MessageBoxImage.Warning); return; } PTAccess pt = new PTAccess(); int count = strucNames.Count; List IsGuessed = InitList(count, false); List EditedList = new List(); double DT = DiceThreshold; EditedList = pt.StructuresAutomaticRename(structures, ref IsGuessed, DT); int j = 0; for (j=0; j < EditedList.Count; j++) { if (IsGuessed[j]) AutoNames.Add(new EditableStructures { StrName = EditedList[j], IsAccepted = false, NamInd = j+1, SpecialFeatures = SpecialFeatures.Color }); else if(String.IsNullOrWhiteSpace(EditedList[j])) AutoNames.Add(new EditableStructures { StrName = EditedList[j], IsAccepted = false, NamInd = j+1, SpecialFeatures = SpecialFeatures.None }); else AutoNames.Add(new EditableStructures { StrName = EditedList[j], IsAccepted = true, NamInd = j + 1, SpecialFeatures = SpecialFeatures.None }); } // string DbgList = "" ; // DEBUG PURPOSE // DbgList = String.Join(" , ", AutoNames.Select(x => x.StrName)); // DEBUG PURPOSE // MessageBox.Show($"AUTOMATICALLY RENAMED STRUCTURES: \n {DbgList}"); // DEBUG PURPOSE //............................ Compare Number of Guessed Structure Names With Number Of Structure Names From Velocity DataBase // ............................ Alert User If Less Than 50% Structures Could Not Be Guessed int NumGuessed = 0; int NumOriginal = 0; var Guessed = AutoNames.Where(m => !string.IsNullOrWhiteSpace(m.StrName)).ToList(); NumGuessed = Guessed.Count; NumOriginal = strucNames.Count; MessageBox.Show($" {NumGuessed} structures automatically renamed out of {NumOriginal} patient structures\n", "Is this patient belonging to this trial? ", MessageBoxButton.OK, MessageBoxImage.Information); UpdateAutoStrucNames(); } /*----------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*-------------------------------------------------- CLOSE THIS APPLICATION -----------------------------------------------------------------------*/ private void Cancel_Click(object sender, RoutedEventArgs e) { AppDomain.CurrentDomain.ProcessExit += (source, data) => { PTAccess.engine.logout(); }; // CLEAN UP VELOCITY ENVIRONMENT MessageBox.Show("The application will be closed.", "Cancel Application ", MessageBoxButton.OK, MessageBoxImage.Information); App.Current.Shutdown(); // TERMINATE APPLICATION Application.Current.MainWindow.Close(); } /*--------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*-------------------------------------- COMMIT RENAMED STRUCTURES TO VELOCITY DATABASE ----------------------------------------*/ public void Accept_Click(object sender, RoutedEventArgs e) { if (AutoNames.Count <= 0) { MessageBox.Show($"No structure to save", "Warning ", MessageBoxButton.OK, MessageBoxImage.Warning); return; } Mouse.OverrideCursor = System.Windows.Input.Cursors.Wait; // SET MOUSE TO HOURGLASS var selectedPairs = AutoNames.Where(m => m.IsAccepted && !string.IsNullOrWhiteSpace(m.StrName)); List SavedStruct = selectedPairs.Select(m => m.StrName).ToList(); // EXTRACTS SELECTED STRUCTURES // string DbgList = ""; // DbgList = String.Join(" , ", SavedStruct.Select(x => x)); // DEBUG PURPOSE // MessageBox.Show($"EDITED AND SELECTED STRUCTURES: \n {DbgList}"); // DEBUG PURPOSE PTAccess pt = new PTAccess(); bool res = pt.StoreSavedStructuresToVelocityDB( AutoNames); if(!res) { MessageBox.Show($"No structure set saved to Velocity DB ", "Warning ", MessageBoxButton.OK, MessageBoxImage.Warning); } else { MessageBox.Show($"Structure set Correctly Saved to Velocity DB with name {targetSetName} ", "Success ", MessageBoxButton.OK, MessageBoxImage.Information); } /*.......................................... Clean up all Velocity related ListBoxes ...........................................................................................................................*/ emptyCTnamesListbox(); emptyStructSetsListbox(); emptyVelStructuresListbox(); emptyEditableStructsListBox(); AutoNames.Clear(); PatientName = System.String.Empty; Patient.Text = " "; DiceThreshold = DiceThresholdDefault; DiceTol.Text = DiceThresholdDefault.ToString(); Mouse.OverrideCursor = null; // SHOW DEFAULT MOUSE } /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ /*---------------------------------------------------------- CHOICE OF VELOCITY DATABASE ---------------------------------------------------------------*/ private void VDB_SelectionChanged(object sender, SelectionChangedEventArgs e) { PTAccess pt = new PTAccess(); int VelDBind = VDB.SelectedIndex; VelocityDataBase = ((VelocityDB)VDB.SelectedItem).MyVelocityDB.ToString(); if (String.IsNullOrEmpty(VelocityDataBase )) { MessageBox.Show("No Velocity database has been selected", "Warning ", MessageBoxButton.OK, MessageBoxImage.Warning); return; } Password = velocityDB[VelDBind].Passwd; UserName = velocityDB[VelDBind].User; emptyCTnamesListbox(); emptyStructSetsListbox(); emptyVelStructuresListbox(); emptyEditableStructsListBox(); PatientName = System.String.Empty; Patient.Text = " "; } } }