Program.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. // Copyright (c) 2012-2020 fo-dicom contributors.
  2. // Licensed under the Microsoft Public License (MS-PL).
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Threading.Tasks;
  7. using Dicom;
  8. using Dicom.Log;
  9. using Dicom.Network;
  10. using DicomClient = Dicom.Network.Client.DicomClient;
  11. namespace Worklist_SCU
  12. {
  13. public static class Program
  14. {
  15. private const string _performedStationAETitle = "Modality";
  16. private const string _performedStationName = "Modality";
  17. public static async Task Main(string[] args)
  18. {
  19. // Initialize log manager.
  20. LogManager.SetImplementation(ConsoleLogManager.Instance);
  21. // set the connection parameters
  22. var serverIP = "localhost";
  23. var serverPort = 8005;
  24. var serverAET = "QRSCP";
  25. var clientAET = "ModalityAET";
  26. // query all worklist items from worklist server
  27. var worklistItems = await GetAllItemsFromWorklistAsync(serverIP, serverPort, serverAET, clientAET);
  28. Console.WriteLine($"received {worklistItems.Count} worklist items.");
  29. // take the first result and set it to in-progress via mpps
  30. var worklistItem = worklistItems.First();
  31. var (affectedInstanceUid, responseStatus, responseMessage) = await SendMppsInProgressAsync(serverIP, serverPort, serverAET, clientAET, worklistItem);
  32. Console.WriteLine($"in progress sent with response {responseStatus} ({responseMessage})");
  33. // then send the compleded
  34. var responseCompleted = await SendMppsCompletedAsync(serverIP, serverPort, serverAET, clientAET, affectedInstanceUid, worklistItem);
  35. Console.WriteLine($"completed sent with response {responseCompleted.responseStatus} ({responseCompleted.responseMessage})");
  36. Console.ReadLine();
  37. }
  38. private static async Task<(string responseStatus, string responseMessage)> SendMppsCompletedAsync(string serverIP, int serverPort, string serverAET, string clientAET, DicomUID affectedInstanceUid, DicomDataset worklistItem)
  39. {
  40. var client = new DicomClient(serverIP, serverPort, false, clientAET, serverAET);
  41. var dataset = new DicomDataset();
  42. DicomSequence procedureStepSq = worklistItem.GetSequence(DicomTag.ScheduledProcedureStepSequence);
  43. // A worklistitem may have a list of scheduledprocedureSteps.
  44. // For each of them you have to send separate MPPS InProgress- and Completed-messages.
  45. // there in this example we will only send for the first procedure step
  46. var procedureStep = procedureStepSq.First();
  47. // data
  48. dataset.Add(DicomTag.PerformedProcedureStepEndDate, DateTime.Now);
  49. dataset.Add(DicomTag.PerformedProcedureStepEndTime, DateTime.Now);
  50. dataset.Add(DicomTag.PerformedProcedureStepStatus, "COMPLETED");
  51. dataset.Add(DicomTag.PerformedProcedureStepDescription, procedureStep.GetSingleValueOrDefault(DicomTag.ScheduledProcedureStepID, string.Empty));
  52. dataset.Add(DicomTag.PerformedProcedureTypeDescription, string.Empty);
  53. dataset.Add(DicomTag.PerformedProtocolCodeSequence, new DicomDataset());
  54. // dose and reports
  55. dataset.Add(DicomTag.ImageAndFluoroscopyAreaDoseProduct, 0.0m); // if there has bee sone dose while examination
  56. dataset.Add(DicomTag.CommentsOnRadiationDose, string.Empty); // a free text that contains all dose parameters
  57. // images created
  58. var performedSeriesSq = new DicomSequence(DicomTag.PerformedSeriesSequence);
  59. // iterate all Series that have been created while examination
  60. var serie = new DicomDataset
  61. {
  62. { DicomTag.RetrieveAETitle, string.Empty }, // the aetitle of the archive where the images have been sent to
  63. { DicomTag.SeriesDescription, "serie 1" },
  64. { DicomTag.PerformingPhysicianName, string.Empty },
  65. { DicomTag.OperatorsName, string.Empty },
  66. { DicomTag.ProtocolName, string.Empty },
  67. { DicomTag.SeriesInstanceUID, DicomUID.Generate() }
  68. };
  69. var refImagesInSerie = new DicomSequence(DicomTag.ReferencedImageSequence);
  70. // iterate all images in the serie
  71. var image = new DicomDataset
  72. {
  73. { DicomTag.ReferencedSOPClassUID, DicomUID.SecondaryCaptureImageStorage },
  74. { DicomTag.ReferencedSOPInstanceUID, DicomUID.Generate() }
  75. };
  76. refImagesInSerie.Items.Add(image);
  77. serie.Add(refImagesInSerie);
  78. performedSeriesSq.Items.Add(serie);
  79. dataset.Add(performedSeriesSq);
  80. var dicomFinished = new DicomNSetRequest(DicomUID.ModalityPerformedProcedureStepSOPClass, affectedInstanceUid)
  81. {
  82. Dataset = dataset
  83. };
  84. string responseStatus = string.Empty;
  85. string responseMessage = string.Empty;
  86. dicomFinished.OnResponseReceived += (req, response) =>
  87. {
  88. if (response != null)
  89. {
  90. Console.WriteLine(response);
  91. responseStatus = response.Status.ToString();
  92. responseMessage = response.ToString();
  93. }
  94. };
  95. await client.AddRequestAsync(dicomFinished);
  96. await client.SendAsync();
  97. return (responseStatus, responseMessage);
  98. }
  99. private static async Task<(DicomUID affectedInstanceUid, string responseStatus, string responseMessage)> SendMppsInProgressAsync(string serverIP, int serverPort, string serverAET, string clientAET, DicomDataset worklistItem)
  100. {
  101. var client = new DicomClient(serverIP, serverPort, false, clientAET, serverAET);
  102. var dataset = new DicomDataset();
  103. DicomSequence procedureStepSq = worklistItem.GetSequence(DicomTag.ScheduledProcedureStepSequence);
  104. // A worklistitem may have a list of scheduledprocedureSteps.
  105. // For each of them you have to send separate MPPS InProgress- and Completed-messages.
  106. // there in this example we will only send for the first procedure step
  107. var procedureStep = procedureStepSq.First();
  108. var content = new DicomDataset();
  109. // get study instance UID from MWL query resault
  110. string studyInstanceUID = worklistItem.GetSingleValueOrDefault(DicomTag.StudyInstanceUID, DicomUID.Generate().ToString());
  111. // set Attribute Sequence data
  112. content.Add(DicomTag.StudyInstanceUID, studyInstanceUID);
  113. content.Add(DicomTag.ReferencedStudySequence, new DicomDataset());
  114. content.Add(DicomTag.AccessionNumber, worklistItem.GetSingleValueOrDefault(DicomTag.AccessionNumber, string.Empty));
  115. content.Add(DicomTag.RequestedProcedureID, worklistItem.GetSingleValueOrDefault(DicomTag.RequestedProcedureID, string.Empty));
  116. content.Add(DicomTag.RequestedProcedureDescription, worklistItem.GetSingleValueOrDefault(DicomTag.RequestedProcedureDescription, string.Empty));
  117. content.Add(DicomTag.ScheduledProcedureStepID, procedureStep.GetSingleValueOrDefault(DicomTag.ScheduledProcedureStepID, string.Empty));
  118. content.Add(DicomTag.ScheduledProcedureStepDescription, procedureStep.GetSingleValueOrDefault(DicomTag.ScheduledProcedureStepDescription, string.Empty));
  119. content.Add(DicomTag.ScheduledProtocolCodeSequence, new DicomDataset());
  120. var attr_Sequence = new DicomSequence(DicomTag.ScheduledStepAttributesSequence, content);//"Scheduled Step Attribute Sequence"
  121. dataset.Add(attr_Sequence);
  122. dataset.Add(DicomTag.PatientName, worklistItem.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty));
  123. dataset.Add(DicomTag.PatientID, worklistItem.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty));
  124. dataset.Add(DicomTag.PatientBirthDate, worklistItem.GetSingleValueOrDefault(DicomTag.PatientBirthDate, string.Empty));
  125. dataset.Add(DicomTag.PatientSex, worklistItem.GetSingleValueOrDefault(DicomTag.PatientSex, string.Empty));
  126. dataset.Add(DicomTag.ReferencedPatientSequence, new DicomDataset());
  127. dataset.Add(DicomTag.PerformedProcedureStepID, procedureStep.GetSingleValueOrDefault(DicomTag.ScheduledProcedureStepID, string.Empty));
  128. dataset.Add(DicomTag.PerformedStationAETitle, _performedStationAETitle);
  129. dataset.Add(DicomTag.PerformedStationName, _performedStationName);
  130. dataset.Add(DicomTag.PerformedLocation, string.Empty);
  131. dataset.Add(DicomTag.PerformedProcedureStepStartDate, DateTime.Now);
  132. dataset.Add(DicomTag.PerformedProcedureStepStartTime, DateTime.Now);
  133. // set status
  134. dataset.Add(DicomTag.PerformedProcedureStepStatus, "IN PROGRESS");
  135. dataset.Add(DicomTag.PerformedProcedureStepDescription, procedureStep.GetSingleValueOrDefault(DicomTag.ScheduledProcedureStepID, string.Empty));
  136. dataset.Add(DicomTag.PerformedProcedureTypeDescription, string.Empty);
  137. dataset.Add(DicomTag.PerformedProcedureStepEndDate, string.Empty);
  138. dataset.Add(DicomTag.PerformedProcedureStepEndTime, string.Empty);
  139. // get modality from MWL query resault
  140. dataset.Add(DicomTag.Modality, procedureStep.GetSingleValueOrDefault(DicomTag.Modality, string.Empty));
  141. dataset.Add(DicomTag.StudyID, worklistItem.GetSingleValueOrDefault(DicomTag.StudyID, string.Empty));
  142. dataset.Add(DicomTag.PerformedProtocolCodeSequence, new DicomDataset());
  143. // create an unique UID as the effectedinstamceUid, this id will be needed for the N-SET also
  144. var effectedinstamceUid = DicomUID.Generate();
  145. var dicomStartRequest = new DicomNCreateRequest(DicomUID.ModalityPerformedProcedureStepSOPClass, effectedinstamceUid)
  146. {
  147. Dataset = dataset
  148. };
  149. string responseStatus = string.Empty;
  150. string responseMessage = string.Empty;
  151. dicomStartRequest.OnResponseReceived += (req, response) =>
  152. {
  153. if (response != null)
  154. {
  155. Console.WriteLine(response);
  156. responseStatus = response.Status.ToString();
  157. responseMessage = response.ToString();
  158. }
  159. };
  160. await client.AddRequestAsync(dicomStartRequest);
  161. await client.SendAsync();
  162. return (effectedinstamceUid, responseStatus, responseMessage);
  163. }
  164. private static async Task<List<DicomDataset>> GetAllItemsFromWorklistAsync(string serverIP, int serverPort, string serverAET, string clientAET)
  165. {
  166. var worklistItems = new List<DicomDataset>();
  167. var cfind = DicomCFindRequest.CreateWorklistQuery(); // no filter, so query all awailable entries
  168. cfind.OnResponseReceived = (DicomCFindRequest rq, DicomCFindResponse rp) =>
  169. {
  170. if (rp.HasDataset)
  171. {
  172. Console.WriteLine("Study UID: {0}", rp.Dataset.GetSingleValue<string>(DicomTag.StudyInstanceUID));
  173. worklistItems.Add(rp.Dataset);
  174. }
  175. else
  176. {
  177. Console.WriteLine(rp.Status.ToString());
  178. }
  179. };
  180. var client = new DicomClient(serverIP, serverPort, false, clientAET, serverAET);
  181. await client.AddRequestAsync(cfind);
  182. await client.SendAsync();
  183. return worklistItems;
  184. }
  185. }
  186. }