Beispiel #1
0
        public IEnumerable <DicomCGetResponse> OnCGetRequest(DicomCGetRequest request)
        {
            IDicomImageFinderService finderService = QRServer.CreateFinderService;
            List <string>            matchingFiles = null;

            switch (request.Level)
            {
            case DicomQueryRetrieveLevel.Patient:
                matchingFiles = finderService.FindFilesByUID(request.Dataset.Get <string>(DicomTag.PatientID), string.Empty, string.Empty);
                break;

            case DicomQueryRetrieveLevel.Study:
                matchingFiles = finderService.FindFilesByUID(string.Empty, request.Dataset.Get <string>(DicomTag.StudyInstanceUID), string.Empty);
                break;

            case DicomQueryRetrieveLevel.Series:
                matchingFiles = finderService.FindFilesByUID(string.Empty, string.Empty, request.Dataset.Get <string>(DicomTag.SeriesInstanceUID));
                break;

            case DicomQueryRetrieveLevel.Image:
                yield return(new DicomCGetResponse(request, DicomStatus.QueryRetrieveUnableToPerformSuboperations));

                yield break;
            }

            foreach (var matchingFile in matchingFiles)
            {
                var storeRequest = new DicomCStoreRequest(matchingFile);
                SendRequest(storeRequest);
            }

            yield return(new DicomCGetResponse(request, DicomStatus.Success));
        }
Beispiel #2
0
        public IEnumerable <DicomCMoveResponse> OnCMoveRequest(DicomCMoveRequest request)
        {
            // the c-move request contains the DestinationAE. the data of this AE should be configured somewhere.
            if (request.DestinationAE != "STORESCP")
            {
                yield return(new DicomCMoveResponse(request, DicomStatus.QueryRetrieveMoveDestinationUnknown));

                yield return(new DicomCMoveResponse(request, DicomStatus.ProcessingFailure));

                yield break;
            }

            // this data should come from some data storage!
            var destinationPort = 11112;
            var destinationIP   = "localhost";

            IDicomImageFinderService finderService = QRServer.CreateFinderService;
            List <string>            matchingFiles = null;

            switch (request.Level)
            {
            case DicomQueryRetrieveLevel.Patient:
                matchingFiles = finderService.FindFilesByUID(request.Dataset.Get <string>(DicomTag.PatientID), string.Empty, string.Empty);
                break;

            case DicomQueryRetrieveLevel.Study:
                matchingFiles = finderService.FindFilesByUID(string.Empty, request.Dataset.Get <string>(DicomTag.StudyInstanceUID), string.Empty);
                break;

            case DicomQueryRetrieveLevel.Series:
                matchingFiles = finderService.FindFilesByUID(string.Empty, string.Empty, request.Dataset.Get <string>(DicomTag.SeriesInstanceUID));
                break;

            case DicomQueryRetrieveLevel.Image:
                yield return(new DicomCMoveResponse(request, DicomStatus.QueryRetrieveUnableToPerformSuboperations));

                yield break;
            }

            DicomClient client = new DicomClient();

            client.NegotiateAsyncOps();
            int storeTotal   = matchingFiles.Count;
            int storeDone    = 0; // this variable stores the number of instances that have already been sent
            int storeFailure = 0; // this variable stores the number of faulues returned in a OnResponseReceived

            foreach (string file in matchingFiles)
            {
                var storeRequest = new DicomCStoreRequest(file);
                // !!! there is a Bug in fo-dicom 3.0.2 that the OnResponseReceived handlers are invoked not until the DicomClient has already
                //     sent all the instances. So the counters are not increased image by image sent but only once in a bulk after all storage
                //     has been finished. This bug will be fixed hopefully soon.
                storeRequest.OnResponseReceived += (req, resp) =>
                {
                    if (resp.Status == DicomStatus.Success)
                    {
                        Logger.Info("Storage of image successfull");
                        storeDone++;
                    }
                    else
                    {
                        Logger.Error("Storage of image failed");
                        storeFailure++;
                    }
                    // SendResponse(new DicomCMoveResponse(request, DicomStatus.Pending) { Remaining = storeTotal - storeDone - storeFailure, Completed = storeDone });
                };
                client.AddRequest(storeRequest);
            }

            // client.Send(destinationIP, destinationPort, false, QRServer.AETitle, request.DestinationAE);

            var sendTask = client.SendAsync(destinationIP, destinationPort, false, QRServer.AETitle, request.DestinationAE);

            while (!sendTask.IsCompleted)
            {
                // while the send-task is runnin we inform the QR SCU every 2 seconds about the status and how many instances are remaining to send.
                yield return(new DicomCMoveResponse(request, DicomStatus.Pending)
                {
                    Remaining = storeTotal - storeDone - storeFailure, Completed = storeDone
                });

                Thread.Sleep(TimeSpan.FromSeconds(2));
            }

            Logger.Info("..fertig");
            yield return(new DicomCMoveResponse(request, DicomStatus.Success));
        }
Beispiel #3
0
 /// <summary>
 /// Testing purposes constructor if you want to inject a custom IDicomImageFinderService
 /// in unit tests
 /// </summary>
 /// <param name="dicomImageFinderService"></param>
 public WadoUriController(IDicomImageFinderService dicomImageFinderService)
 {
     _dicomImageFinderService = dicomImageFinderService;
 }
Beispiel #4
0
        public IEnumerable <DicomCFindResponse> OnCFindRequest(DicomCFindRequest request)
        {
            var queryLevel = request.Level;

            var matchingFiles = new List <string>();
            IDicomImageFinderService finderService = QRServer.CreateFinderService;

            // a QR SCP has to define in a DICOM Conformance Statement for which dicom tags it can query
            // depending on the level of the query. Below there are only very few parameters evaluated.

            switch (queryLevel)
            {
            case DicomQueryRetrieveLevel.Patient:
            {
                var patname = request.Dataset.Get(DicomTag.PatientName, string.Empty);
                var patid   = request.Dataset.Get(DicomTag.PatientID, string.Empty);

                matchingFiles = finderService.FindPatientFiles(patname, patid);
            }
            break;

            case DicomQueryRetrieveLevel.Study:
            {
                var patname  = request.Dataset.Get(DicomTag.PatientName, string.Empty);
                var patid    = request.Dataset.Get(DicomTag.PatientID, string.Empty);
                var accNr    = request.Dataset.Get(DicomTag.AccessionNumber, string.Empty);
                var studyUID = request.Dataset.Get(DicomTag.StudyInstanceUID, string.Empty);

                matchingFiles = finderService.FindStudyFiles(patname, patid, accNr, studyUID);
            }
            break;

            case DicomQueryRetrieveLevel.Series:
            {
                var patname   = request.Dataset.Get(DicomTag.PatientName, string.Empty);
                var patid     = request.Dataset.Get(DicomTag.PatientID, string.Empty);
                var accNr     = request.Dataset.Get(DicomTag.AccessionNumber, string.Empty);
                var studyUID  = request.Dataset.Get(DicomTag.StudyInstanceUID, string.Empty);
                var seriesUID = request.Dataset.Get(DicomTag.SeriesInstanceUID, string.Empty);
                var modality  = request.Dataset.Get(DicomTag.Modality, string.Empty);

                matchingFiles = finderService.FindSeriesFiles(patname, patid, accNr, studyUID, seriesUID, modality);
            }
            break;

            case DicomQueryRetrieveLevel.Image:
                yield return(new DicomCFindResponse(request, DicomStatus.QueryRetrieveUnableToProcess));

                yield break;
            }

            // now read the required dicomtags from the matching files and return as results
            foreach (var matchingFile in matchingFiles)
            {
                var dicomFile = DicomFile.Open(matchingFile);
                var result    = new DicomDataset();
                foreach (var requestedTag in request.Dataset)
                {
                    // most of the requested DICOM tags are stored in the DICOM files and therefore saved into a database.
                    // you can fill the responses by selecting the values from the database.
                    // also be aware that there are some requested DicomTags like "ModalitiesInStudy" or "NumberOfStudyRelatedInstances"
                    // or "NumberOfPatientRelatedInstances" and so on which have to be calculated and cannot be read from a DICOM file.
                    if (dicomFile.Dataset.Contains(requestedTag.Tag))
                    {
                        dicomFile.Dataset.CopyTo(result, requestedTag.Tag);
                    }
                    // else if (requestedTag == DicomTag.NumberOfStudyRelatedInstances)
                    // {
                    //    ... somehow calculate how many instances are stored within the study
                    //    result.Add(DicomTag.NumberOfStudyRelatedInstances, number);
                    // } ....
                    else
                    {
                        result.Add(requestedTag);
                    }
                }
                yield return(new DicomCFindResponse(request, DicomStatus.Pending)
                {
                    Dataset = result
                });
            }

            yield return(new DicomCFindResponse(request, DicomStatus.Success));
        }
Beispiel #5
0
 /// <summary>
 /// Initialize a new instance of WadoUriController
 /// </summary>
 public WadoUriController()
 {
     //Put your own IDicomImageFinderService implementation here for real world scenarios
     _dicomImageFinderService = new TestDicomImageFinderService();
 }
Beispiel #6
0
        public IEnumerable <DicomCFindResponse> OnCFindRequest(DicomCFindRequest request)
        {
            var queryLevel = request.Level;

            DataTable resultsDt = null;
            IDicomImageFinderService finderService = QRServer.CreateFinderService;

            // a QR SCP has to define in a DICOM Conformance Statement for which dicom tags it can query
            // depending on the level of the query. Below there are only very few parameters evaluated.

            switch (queryLevel)
            {
            case DicomQueryRetrieveLevel.Patient:
            {
                var patname = request.Dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty);
                var patid   = request.Dataset.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty);

                resultsDt = finderService.FindPatientFiles(patname, patid);
            }
            break;

            case DicomQueryRetrieveLevel.Study:
            {
                var patname   = request.Dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty);
                var patid     = request.Dataset.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty);
                var accNr     = request.Dataset.GetSingleValueOrDefault(DicomTag.AccessionNumber, string.Empty);
                var studyUID  = request.Dataset.GetSingleValueOrDefault(DicomTag.StudyInstanceUID, string.Empty);
                var StudyDate = request.Dataset.GetSingleValueOrDefault(DicomTag.StudyDate, string.Empty);
                var StudyTime = request.Dataset.GetSingleValueOrDefault(DicomTag.StudyTime, string.Empty);

                resultsDt = finderService.FindStudyFiles(patname, patid, accNr, studyUID, StudyDate, StudyTime);
            }
            break;

            case DicomQueryRetrieveLevel.Series:
            {
                var patname   = request.Dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty);
                var patid     = request.Dataset.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty);
                var accNr     = request.Dataset.GetSingleValueOrDefault(DicomTag.AccessionNumber, string.Empty);
                var studyUID  = request.Dataset.GetSingleValueOrDefault(DicomTag.StudyInstanceUID, string.Empty);
                var seriesUID = request.Dataset.GetSingleValueOrDefault(DicomTag.SeriesInstanceUID, string.Empty);
                var modality  = request.Dataset.GetSingleValueOrDefault(DicomTag.Modality, string.Empty);

                resultsDt = finderService.FindSeriesFiles(patname, patid, accNr, studyUID, seriesUID, modality);
            }
            break;

            case DicomQueryRetrieveLevel.Image:
                yield return(new DicomCFindResponse(request, DicomStatus.QueryRetrieveUnableToProcess));

                yield break;
            }

            bool _autoValidateDICOM = Config.GetConfigBoolValueByName(Config.Key_Enable_DICOM_AutoValidate);
            var  columns            = new List <string>();

            foreach (DataColumn column in resultsDt.Columns)
            {
                columns.Add(column.ColumnName);
            }
            // now read the required dicomtags from the matching files and return as results
            foreach (DataRow row in resultsDt.Rows)
            {
                var rtnResult = new DicomDataset();
                rtnResult.AutoValidate = _autoValidateDICOM; //Not sure if we need this so se up as config value
                //rtnResult.Clear(); //Could clear existing rather than create new.
                foreach (var requestedTag in request.Dataset)
                {
                    // most of the requested DICOM tags are stored in the DICOM files and therefore saved into a database.
                    // you can fill the responses by selecting the values from the database.
                    // also be aware that there are some requested DicomTags like "ModalitiesInStudy" or "NumberOfStudyRelatedInstances"
                    // or "NumberOfPatientRelatedInstances" and so on which have to be calculated and cannot be read from a DICOM file.
                    string columnName = requestedTag.Tag.DictionaryEntry.Keyword.ToString();
                    if (columns.Contains(columnName))
                    {
                        rtnResult.Add(requestedTag.Tag, row[columnName].ToString());
                    }
                    else
                    {
                        rtnResult.Add(requestedTag);
                    }
                }
                yield return(new DicomCFindResponse(request, DicomStatus.Pending)
                {
                    Dataset = rtnResult
                });
            }
            resultsDt.Dispose();
            yield return(new DicomCFindResponse(request, DicomStatus.Success));
        }
Beispiel #7
0
        public IEnumerable <DicomCMoveResponse> OnCMoveRequest(DicomCMoveRequest request)
        {
            // The c-move request contains the DestinationAE. The data of this AE should be configured somewhere.
            if (request.DestinationAE != "")
            {
                yield return(new DicomCMoveResponse(request, DicomStatus.QueryRetrieveMoveDestinationUnknown));

                yield return(new DicomCMoveResponse(request, DicomStatus.ProcessingFailure));

                yield break;
            }

            // This data should come from some data storage.
            var destinationPort = 11112;
            var destinationIP   = "localhost";

            IDicomImageFinderService finderService = ServiceLocator.DicomImageFinderService;
            List <string>            matchingFiles = new List <string>();

            switch (request.Level)
            {
            case DicomQueryRetrieveLevel.Patient:
                string patientId = request.Dataset.GetSingleValue <string>(DicomTag.PatientID);
                matchingFiles = finderService.FindFilesByPatient(patientId);
                break;

            case DicomQueryRetrieveLevel.Study:
                string studyUID = request.Dataset.GetSingleValue <string>(DicomTag.StudyInstanceUID);
                matchingFiles = finderService.FindFilesByStudyUID(studyUID);
                break;

            case DicomQueryRetrieveLevel.Series:
                string seriesUID = request.Dataset.GetSingleValue <string>(DicomTag.SeriesInstanceUID);
                matchingFiles = finderService.FindFilesBySeriesUID(seriesUID);
                break;

            case DicomQueryRetrieveLevel.Image:
                yield return(new DicomCMoveResponse(request, DicomStatus.QueryRetrieveUnableToPerformSuboperations));

                yield break;
            }
            // Send to c-store.
            DicomClient client = new DicomClient();

            client.NegotiateAsyncOps();
            int storeTotal   = matchingFiles.Count;
            int storeDone    = 0;
            int storeFailure = 0;

            foreach (var file in matchingFiles)
            {
                var storeRequest = new DicomCStoreRequest(file);
                storeRequest.OnResponseReceived += (req, resp) =>
                {
                    if (resp.Status == DicomStatus.Success)
                    {
                        storeDone++;
                    }
                    else
                    {
                        storeFailure++;
                    }
                    SendResponseAsync(new DicomCMoveResponse(request, DicomStatus.Pending)
                    {
                        Remaining = storeTotal - storeDone - storeFailure, Completed = storeDone
                    }).Wait();
                };
                client.AddRequest(storeRequest);
            }

            var sendTask = client.SendAsync(destinationIP, destinationPort, false, CalledAE, request.DestinationAE);

            sendTask.Wait();

            yield return(new DicomCMoveResponse(request, DicomStatus.Success));
        }
Beispiel #8
0
 /// <summary>
 /// Testing purposes constructor if you want to inject a custom IDicomImageFinderService
 /// in unit tests
 /// </summary>
 /// <param name="dicomImageFinderService"></param>
 public WadoUriController(IDicomImageFinderService dicomImageFinderService)
 {
     _dicomImageFinderService = dicomImageFinderService;
 }
Beispiel #9
0
 /// <summary>
 /// Initialize a new instance of WadoUriController
 /// </summary>
 public WadoUriController()
 {
     //Put your own IDicomImageFinderService implementation here for real world scenarios
     _dicomImageFinderService = new TestDicomImageFinderService();
 }