WorklistHandler.cs 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. // Copyright (c) 2012-2020 fo-dicom contributors.
  2. // Licensed under the Microsoft Public License (MS-PL).
  3. using Dicom;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Text.RegularExpressions;
  7. namespace Worklist_SCP.Model
  8. {
  9. public class WorklistHandler
  10. {
  11. public static IEnumerable<DicomDataset> FilterWorklistItems(DicomDataset request, List<WorklistItem> allWorklistItems)
  12. {
  13. var exams = allWorklistItems.AsQueryable();
  14. if ( request.TryGetSingleValue(DicomTag.PatientID, out string patientId))
  15. {
  16. exams = exams.Where(x => x.PatientID.Equals(patientId));
  17. }
  18. var patientName = request.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty);
  19. if (!string.IsNullOrEmpty(patientName))
  20. {
  21. exams = AddNameCondition(exams, patientName);
  22. }
  23. DicomDataset procedureStep = null;
  24. if (request.Contains(DicomTag.ScheduledProcedureStepSequence))
  25. {
  26. procedureStep = request.GetSequence(DicomTag.ScheduledProcedureStepSequence).First();
  27. // Required Matching keys
  28. var scheduledStationAET = procedureStep.GetSingleValueOrDefault(DicomTag.ScheduledStationAETitle, string.Empty);
  29. if (!string.IsNullOrEmpty(scheduledStationAET))
  30. {
  31. exams = exams.Where(x => x.ScheduledAET == scheduledStationAET);
  32. }
  33. var performingPhysician = procedureStep.GetSingleValueOrDefault(DicomTag.PerformingPhysicianName, string.Empty);
  34. if (!string.IsNullOrEmpty(performingPhysician))
  35. {
  36. exams = exams.Where(x => x.PerformingPhysician == performingPhysician);
  37. }
  38. var modality = procedureStep.GetSingleValueOrDefault(DicomTag.Modality, string.Empty);
  39. if (!string.IsNullOrEmpty(modality))
  40. {
  41. exams = exams.Where(x => x.Modality == modality);
  42. }
  43. // if only date is specified, then using standard matching
  44. // but if both are specified, then MWL defines a combined match
  45. var scheduledProcedureStepStartDateTime = procedureStep.GetSingleValueOrDefault(DicomTag.ScheduledProcedureStepStartDateTime, string.Empty);
  46. if (!string.IsNullOrEmpty(scheduledProcedureStepStartDateTime))
  47. {
  48. exams = AddDateCondition(exams, scheduledProcedureStepStartDateTime);
  49. }
  50. // Optional (but commonly used) matching keys.
  51. var procedureStepLocation = procedureStep.GetSingleValueOrDefault(DicomTag.ScheduledProcedureStepLocation, string.Empty);
  52. if (!string.IsNullOrEmpty(procedureStepLocation))
  53. {
  54. exams = exams.Where(x => x.ExamRoom.Equals(procedureStepLocation));
  55. }
  56. var procedureDescription = procedureStep.GetSingleValueOrDefault(DicomTag.ScheduledProcedureStepDescription, string.Empty);
  57. if (!string.IsNullOrEmpty(procedureDescription))
  58. {
  59. exams = exams.Where(x => x.ExamDescription.Equals(procedureDescription));
  60. }
  61. }
  62. var results = exams.ToList();
  63. // Parsing result
  64. foreach (var result in results)
  65. {
  66. var resultingSPS = new DicomDataset();
  67. var resultDataset = new DicomDataset();
  68. var resultingSPSSequence = new DicomSequence(DicomTag.ScheduledProcedureStepSequence, resultingSPS);
  69. if (procedureStep != null)
  70. {
  71. resultDataset.Add(resultingSPSSequence);
  72. }
  73. // add results to "main" dataset
  74. AddIfExistsInRequest(resultDataset, request, DicomTag.AccessionNumber, result.AccessionNumber); // T2
  75. AddIfExistsInRequest(resultDataset, request, DicomTag.InstitutionName, result.HospitalName);
  76. AddIfExistsInRequest(resultDataset, request, DicomTag.ReferringPhysicianName, result.ReferringPhysician); // T2
  77. AddIfExistsInRequest(resultDataset, request, DicomTag.PatientName, result.Surname + "^" + result.Forename + "^^" + result.Title); //T1
  78. AddIfExistsInRequest(resultDataset, request, DicomTag.PatientID, result.PatientID); // T1
  79. AddIfExistsInRequest(resultDataset, request, DicomTag.PatientBirthDate, result.DateOfBirth); // T2
  80. AddIfExistsInRequest(resultDataset, request, DicomTag.PatientSex, result.Sex); //T2
  81. AddIfExistsInRequest(resultDataset, request, DicomTag.StudyInstanceUID, result.StudyUID); // T1
  82. AddIfExistsInRequest(resultDataset, request, DicomTag.RequestingPhysician, result.ReferringPhysician); //T2
  83. AddIfExistsInRequest(resultDataset, request, DicomTag.RequestedProcedureDescription, result.ExamDescription); //T1C
  84. AddIfExistsInRequest(resultDataset, request, DicomTag.RequestedProcedureID, result.ProcedureID); // T1
  85. // Scheduled Procedure Step sequence T1
  86. // add results to procedure step dataset
  87. // Return if requested
  88. if (procedureStep != null)
  89. {
  90. AddIfExistsInRequest(resultingSPS, procedureStep, DicomTag.ScheduledStationAETitle, result.ScheduledAET); // T1
  91. AddIfExistsInRequest(resultingSPS, procedureStep, DicomTag.ScheduledProcedureStepStartDate, result.ExamDateAndTime); //T1
  92. AddIfExistsInRequest(resultingSPS, procedureStep, DicomTag.ScheduledProcedureStepStartTime, result.ExamDateAndTime); //T1
  93. AddIfExistsInRequest(resultingSPS, procedureStep, DicomTag.Modality, result.Modality); // T1
  94. AddIfExistsInRequest(resultingSPS, procedureStep, DicomTag.ScheduledPerformingPhysicianName, result.PerformingPhysician); //T2
  95. AddIfExistsInRequest(resultingSPS, procedureStep, DicomTag.ScheduledProcedureStepDescription, result.ExamDescription); // T1C
  96. AddIfExistsInRequest(resultingSPS, procedureStep, DicomTag.ScheduledProcedureStepID, result.ProcedureStepID); // T1
  97. AddIfExistsInRequest(resultingSPS, procedureStep, DicomTag.ScheduledStationName, result.ExamRoom); //T2
  98. AddIfExistsInRequest(resultingSPS, procedureStep, DicomTag.ScheduledProcedureStepLocation, result.ExamRoom); //T2
  99. }
  100. // Put blanks in for unsupported fields which are type 2 (i.e. must have a value even if NULL)
  101. // In a real server, you may wish to support some or all of these, but they are not commonly supported
  102. AddIfExistsInRequest(resultDataset, request, DicomTag.ReferencedStudySequence, new DicomDataset()); // Ref//d Study Sequence
  103. AddIfExistsInRequest(resultDataset, request, DicomTag.Priority, ""); // Priority
  104. AddIfExistsInRequest(resultDataset, request, DicomTag.PatientTransportArrangements, ""); // Transport Arrangements
  105. AddIfExistsInRequest(resultDataset, request, DicomTag.AdmissionID, ""); // Admission ID
  106. AddIfExistsInRequest(resultDataset, request, DicomTag.CurrentPatientLocation, ""); // Patient Location
  107. AddIfExistsInRequest(resultDataset, request, DicomTag.ReferencedPatientSequence, new DicomDataset()); // Ref//d Patient Sequence
  108. AddIfExistsInRequest(resultDataset, request, DicomTag.PatientWeight, ""); // Weight
  109. AddIfExistsInRequest(resultDataset, request, DicomTag.ConfidentialityConstraintOnPatientDataDescription, ""); // Confidentiality Constraint
  110. // Send Reponse Back
  111. yield return resultDataset;
  112. }
  113. }
  114. //Splits patient name into 2 separte strings surname and forename and send then to the addstringcondition subroutine.
  115. internal static IQueryable<WorklistItem> AddNameCondition(IQueryable<WorklistItem> exams, string dicomName)
  116. {
  117. if (string.IsNullOrEmpty(dicomName) || dicomName == "*")
  118. {
  119. return exams;
  120. }
  121. var personName = new DicomPersonName(DicomTag.PatientName, dicomName);
  122. if (dicomName.Contains("*"))
  123. {
  124. var firstNameRegex = new Regex("^" + Regex.Escape(personName.First).Replace("\\*", ".*") + "$");
  125. var lastNameRegex = new Regex("^" + Regex.Escape(personName.Last).Replace("\\*", ".*") + "$");
  126. exams = exams.Where(x => firstNameRegex.IsMatch(x.Forename) || lastNameRegex.IsMatch(x.Surname));
  127. }
  128. else
  129. {
  130. exams = exams.Where(x => (x.Forename.Equals(personName.First) && x.Surname.Equals(personName.Last)));
  131. }
  132. return exams;
  133. }
  134. internal static IQueryable<WorklistItem> AddDateCondition(IQueryable<WorklistItem> exams, string dateCondition)
  135. {
  136. if (!string.IsNullOrEmpty(dateCondition) && dateCondition != "*")
  137. {
  138. var range = new DicomDateTime(DicomTag.ScheduledProcedureStepStartDate, dateCondition).Get<DicomDateRange>();
  139. exams = exams.Where(x => range.Contains(x.ExamDateAndTime));
  140. }
  141. return exams;
  142. }
  143. internal static void AddIfExistsInRequest<T>(DicomDataset result, DicomDataset request, DicomTag tag, T value)
  144. {
  145. // Only send items which have been requested
  146. if (request.Contains(tag))
  147. {
  148. if (value == null)
  149. {
  150. value = default;
  151. }
  152. result.AddOrUpdate(tag, value);
  153. }
  154. }
  155. }
  156. }