public async Task StoreImageAsync(string serverIp, int serverPort, string serverAET, string localAET, IEnumerable <CStoreItem> items) { DicomClient client = new DicomClient(serverIp, serverPort, false, localAET, serverAET); client.NegotiateAsyncOps(); foreach (CStoreItem item in items) { DicomCStoreRequest request = new DicomCStoreRequest(item.File) { OnResponseReceived = (req, res) => { if (res.Status != DicomStatus.Success) { Logger.Error("C-STORE send failed. Instance UID - [{0}]", req.SOPInstanceUID); item.Status = CStoreItemStatus.Failed; } else { item.Status = CStoreItemStatus.Success; } } }; await client.AddRequestAsync(request); } await client.SendAsync(); }
/// <summary> /// 测试请求 /// </summary> /// <param name="serverIp">Server IP Addr</param> /// <param name="serverPort">Server Port</param> /// <param name="serverAET">Server AE Title</param> /// <param name="localAET">Client AE Title</param> /// <returns>true if success</returns> public async Task <bool> Echo(string serverIp, int serverPort, string serverAET, string localAET) { bool echoResult = false; DicomClient client = new DicomClient(serverIp, serverPort, false, localAET, serverAET); client.NegotiateAsyncOps(); DicomCEchoRequest request = new DicomCEchoRequest() { OnResponseReceived = (req, res) => { if (res.Status == DicomStatus.Success) { echoResult = true; } } }; await client.AddRequestAsync(request); try { await client.SendAsync(); } catch (System.Exception ex) { loggerService.Error(ex); return(false); } return(echoResult); }
public DicomBaseClient(string serverHost, int serverPort, string serverAeTitle, string clientAeTitle) { CreateClient = () => { var client = new DicomClient(serverHost, serverPort, false, clientAeTitle, serverAeTitle); client.NegotiateAsyncOps(); return(client); }; }
public async Task <List <TempDicomSeries> > GetDicomSeries(TempDicomStudy d) { var result = new List <TempDicomSeries>(); var request = new DicomCFindRequest(DicomQueryRetrieveLevel.Series); #region seriesDataset request.Dataset.AddOrUpdate(DicomTag.Modality, ""); request.Dataset.AddOrUpdate(DicomTag.SeriesNumber, ""); request.Dataset.AddOrUpdate(DicomTag.SeriesInstanceUID, ""); request.Dataset.AddOrUpdate(DicomTag.SeriesDate, ""); request.Dataset.AddOrUpdate(DicomTag.SeriesTime, ""); request.Dataset.AddOrUpdate(DicomTag.SeriesDescription, ""); request.Dataset.AddOrUpdate(DicomTag.StudyInstanceUID, d.StudyInstanceUID); #endregion request.OnResponseReceived += (re, response) => { if ((response as DicomCFindResponse).Status == DicomStatus.Success) { ; } logger.Trace(" C-Find response = " + response); try { if ((response as DicomCFindResponse).HasDataset) { TempDicomSeries s = new TempDicomSeries((response as DicomCFindResponse).Dataset); if (result.Where(x => x.SeriesInstanceUID == s.SeriesInstanceUID).Any() == false) { s.TempDicomStudy = d; d.DicomSeries.Add(s); result.Add(s); //s.Debug(); logger.Trace("Picked up Series Instance UID " + (response as DicomCFindResponse).Dataset.GetString(DicomTag.SeriesInstanceUID)); } } } catch (Exception ex) { logger.Warn(ex, "Exception in getting TempDicomSeries"); } }; foreach (StoredDicomServer s in DicomServers.Where(x => x.Online)) { logger.Trace("Running series query on " + s.AETitle); DicomClient client = new DicomClient(s.IPAddress, s.Port, false, _preferences.AETitle, s.AETitle); client.AssociationRejected += Client_AssociationRejected; client.AssociationAccepted += Client_AssociationAccepted; client.NegotiateAsyncOps(); await client.AddRequestAsync(request); await client.SendAsync(); } return(result); }
public async Task <List <TempDicomStudy> > GetDicomStudies(DateTime studyDate) { logger.Trace("GetDicomStudies(" + studyDate + ")"); var Studies = new List <TempDicomStudy>(); var request = new DicomCFindRequest(DicomQueryRetrieveLevel.Study); #region studyDataset request.Dataset.AddOrUpdate(DicomTag.PatientName, ""); request.Dataset.AddOrUpdate(DicomTag.PatientID, ""); request.Dataset.AddOrUpdate(DicomTag.StudyDate, studyDate.ToString("yyyyMMdd")); request.Dataset.AddOrUpdate(DicomTag.StudyInstanceUID, ""); request.Dataset.AddOrUpdate(DicomTag.AccessionNumber, ""); request.Dataset.AddOrUpdate(DicomTag.StudyDescription, ""); request.Dataset.AddOrUpdate(DicomTag.ModalitiesInStudy, ""); #endregion request.OnResponseReceived += (re, response) => { logger.Trace(" C-Find response = " + response); try { if ((response as DicomCFindResponse).HasDataset) { if (Studies.Where(x => x.StudyInstanceUID == (response as DicomCFindResponse).Dataset.GetString(DicomTag.StudyInstanceUID)).Any() == false) { Studies.Add(new TempDicomStudy((response as DicomCFindResponse).Dataset)); logger.Trace("Picked up Study Instance UID " + (response as DicomCFindResponse).Dataset.GetString(DicomTag.StudyInstanceUID)); } else { logger.Trace("Already picked up Study Instance UID " + (response as DicomCFindResponse).Dataset.GetString(DicomTag.StudyInstanceUID)); } } } catch (Exception ex) { logger.Warn(ex, "Exception in getting studyUID"); } }; foreach (StoredDicomServer s in DicomServers.Where(x => x.Online)) { logger.Trace("Running study level query on " + s.AETitle); DicomClient client = new DicomClient(s.IPAddress, s.Port, false, _preferences.AETitle, s.AETitle); client.AssociationRejected += Client_AssociationRejected; client.AssociationAccepted += Client_AssociationAccepted; client.NegotiateAsyncOps(); await client.AddRequestAsync(request); await client.SendAsync(); //client.Send(s.IPAddress, s.Port, false, LocalAETitle, s.AETitle, 5000); } return(Studies); }
public async Task NewDicomClient_SendEchos() { var client = new Dicom.Network.Client.DicomClient("127.0.0.1", _server.Port, false, "SCU", "ANY-SCP"); client.NegotiateAsyncOps(1, 1); client.AssociationLingerTimeoutInMs = 0; var requests = Enumerable.Range(0, 1000).Select(i => new DicomCEchoRequest()); await client.AddRequestsAsync(requests).ConfigureAwait(false); await client.SendAsync().ConfigureAwait(false); }
private async Task SendCStoreRequest(OutputJob job) { await DownloadFromPayloadsService(job); if (job.PendingDicomFiles.Count > 0) { var countDownEventHandle = new CountdownEvent(job.PendingDicomFiles.Count); DicomClient client = null; try { client = new DicomClient( job.HostIp, job.Port, false, _dicomAdapterConfiguration.Value.Dicom.Scu.AeTitle, job.AeTitle); client.AssociationAccepted += (sender, args) => job.Logger.LogInformation("Association accepted."); client.AssociationRejected += (sender, args) => job.Logger.LogInformation("Association rejected."); client.AssociationReleased += (sender, args) => job.Logger.LogInformation("Association release."); client.Options = new DicomServiceOptions { LogDataPDUs = _dicomAdapterConfiguration.Value.Dicom.Scu.LogDataPdus, LogDimseDatasets = _dicomAdapterConfiguration.Value.Dicom.Scu.LogDimseDatasets }; client.NegotiateAsyncOps(); GenerateRequests(job, client, countDownEventHandle); job.Logger.LogInformation("Sending job to {0}@{1}:{2}", job.AeTitle, job.HostIp, job.Port); await client.SendAsync(_token).ConfigureAwait(false); countDownEventHandle.Wait(_token); job.Logger.LogInformation("Job sent to {0} completed", job.AeTitle); } catch (Exception ex) { HandleCStoreException(ex, job, client); } } job.LogFailedRequests(); job.ReportStatus(_token); }
protected override async Task <OutputJob> ExportDataBlockCallback(OutputJob outputJob, CancellationToken cancellationToken) { using var loggerScope = _logger.BeginScope(new LogginDataDictionary <string, object> { { "JobId", outputJob.JobId }, { "PayloadId", outputJob.PayloadId } }); if (outputJob.PendingDicomFiles.Count > 0) { var countDownEventHandle = new CountdownEvent(outputJob.PendingDicomFiles.Count); DicomClient client = null; try { client = new DicomClient( outputJob.HostIp, outputJob.Port, false, _scuConfiguration.AeTitle, outputJob.AeTitle); client.AssociationAccepted += (sender, args) => _logger.LogInformation("Association accepted."); client.AssociationRejected += (sender, args) => _logger.LogInformation("Association rejected."); client.AssociationReleased += (sender, args) => _logger.LogInformation("Association release."); client.Options = new DicomServiceOptions { LogDataPDUs = _scuConfiguration.LogDataPdus, LogDimseDatasets = _scuConfiguration.LogDimseDatasets }; client.NegotiateAsyncOps(); GenerateRequests(outputJob, client, countDownEventHandle); _logger.LogInformation("Sending job to {0}@{1}:{2}", outputJob.AeTitle, outputJob.HostIp, outputJob.Port); await client.SendAsync(cancellationToken).ConfigureAwait(false); countDownEventHandle.Wait(cancellationToken); _logger.LogInformation("Job sent to {0} completed", outputJob.AeTitle); } catch (Exception ex) { HandleCStoreException(ex, outputJob, client); } } return(outputJob); }
//建立连接并Retrieve async public void DicomCRetrieveRequestFunct(ServerConfig OneServerConfig) { // 建立连接 var client = new DicomClient(OneServerConfig.RemoteIp, OneServerConfig.RemotePort, false, OneServerConfig.LocalAeTitle, OneServerConfig.RemoteAeTitle); client.NegotiateAsyncOps(); // 使用CMOVE抓取信息,发送到本机STORE服务 // using () { OneServerConfig.AddLogStr($"Run C-Store SCP server on port 104"); foreach (var oneResult in Results) { var cMoveRequest = new DicomCMoveRequest("SegAE", oneResult.StudyInstanceUid, oneResult.SeriesInstanceUid); bool?moveSuccessfully = null; cMoveRequest.OnResponseReceived += (DicomCMoveRequest requ, DicomCMoveResponse response) => { if (response.Status.State == DicomState.Pending) { // Console.WriteLine("Sending is in progress. please wait: " + response.Remaining.ToString()); } else if (response.Status.State == DicomState.Success) { OneServerConfig.AddLogStr($"{oneResult.PatientId} " + $"{oneResult.SeriesInstanceUid}"); moveSuccessfully = true; } else if (response.Status.State == DicomState.Failure) { OneServerConfig.AddLogStr($"{response.Status.Description}"); moveSuccessfully = false; } }; await client.AddRequestAsync(cMoveRequest); await client.SendAsync(); } } }
public async Task <List <DicomFile> > GetDicomFiles(string studyInstanceUID, string seriesInstanceUID) { ReceivedFiles.Clear(); DicomCMoveRequest moveRequest = new DicomCMoveRequest(_preferences.AETitle, studyInstanceUID, seriesInstanceUID); moveRequest.OnResponseReceived += (DicomCMoveRequest requ, DicomCMoveResponse response) => { if (response.Status.State == DicomState.Pending) { //logger.Trace("PresentationContext: " + response.PresentationContext.AcceptedTransferSyntax.ToString()); } else if (response.Status.State == DicomState.Success) { logger.Trace("Sending successfully finished"); } else if (response.Status.State == DicomState.Failure) { logger.Error("Error sending datasets: " + response.Status.Description); } }; logger.Debug("Move Request; AE Title: " + _preferences.AETitle + "; Level: " + moveRequest.Level + "; SOP Class UID: " + moveRequest.SOPClassUID); foreach (StoredDicomServer s in DicomServers) { logger.Trace("GetDicomFiles(" + studyInstanceUID + "," + seriesInstanceUID + ") on " + s.AETitle); var pcs = DicomPresentationContext.GetScpRolePresentationContextsFromStorageUids( DicomStorageCategory.Image, DicomTransferSyntax.ExplicitVRLittleEndian, DicomTransferSyntax.ImplicitVRLittleEndian); DicomClient client = new DicomClient(s.IPAddress, s.Port, false, _preferences.AETitle, s.AETitle); client.AdditionalPresentationContexts.AddRange(pcs); client.AssociationRejected += Client_AssociationRejected; client.AssociationAccepted += Client_AssociationAccepted; client.NegotiateAsyncOps(); await client.AddRequestAsync(moveRequest); await client.SendAsync(); } return(ReceivedFiles); }
private async void echoServer_Do() { // var server = new DicomServer<DicomCEchoProvider>(); var client = new DicomClient(TheServerConfig.RemoteIp, TheServerConfig.RemotePort, false, TheServerConfig.LocalAeTitle, TheServerConfig.RemoteAeTitle); client.NegotiateAsyncOps(); var request = new DicomCEchoRequest(); request.OnResponseReceived += (DicomCEchoRequest req, DicomCEchoResponse response) => { // Console.WriteLine("C-Echo Status: " + response.Status); TheServerConfig.LogInfo += ("ECHO: " + response.Status + Environment.NewLine); }; await client.AddRequestAsync(request); await client.SendAsync(); }
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; IEnumerable <string> matchingFiles = Enumerable.Empty <string>(); switch (request.Level) { case DicomQueryRetrieveLevel.Patient: matchingFiles = finderService.FindFilesByUID(request.Dataset.GetSingleValue <string>(DicomTag.PatientID), string.Empty, string.Empty); break; case DicomQueryRetrieveLevel.Study: matchingFiles = finderService.FindFilesByUID(string.Empty, request.Dataset.GetSingleValue <string>(DicomTag.StudyInstanceUID), string.Empty); break; case DicomQueryRetrieveLevel.Series: matchingFiles = finderService.FindFilesByUID(string.Empty, string.Empty, request.Dataset.GetSingleValue <string>(DicomTag.SeriesInstanceUID)); break; case DicomQueryRetrieveLevel.Image: yield return(new DicomCMoveResponse(request, DicomStatus.QueryRetrieveUnableToPerformSuboperations)); yield break; } var client = new DicomClient(destinationIP, destinationPort, false, QRServer.AETitle, request.DestinationAE); 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++; } }; client.AddRequestAsync(storeRequest).Wait(); } var sendTask = client.SendAsync(); 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("..finished"); yield return(new DicomCMoveResponse(request, DicomStatus.Success)); }
private static async Task Main(string[] args) { try { // Initialize log manager. LogManager.SetImplementation(NLogManager.Instance); DicomException.OnException += delegate(object sender, DicomExceptionEventArgs ea) { ConsoleColor old = Console.ForegroundColor; Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine(ea.Exception); Console.ForegroundColor = old; }; var config = new LoggingConfiguration(); var target = new ColoredConsoleTarget { Layout = @"${date:format=HH\:mm\:ss} ${message}" }; config.AddTarget("Console", target); config.LoggingRules.Add(new LoggingRule("*", NLog.LogLevel.Debug, target)); NLog.LogManager.Configuration = config; var client = new DicomClient("127.0.0.1", 11112, false, "SCU", "STORESCP"); client.NegotiateAsyncOps(); for (int i = 0; i < 10; i++) { await client.AddRequestAsync(new DicomCEchoRequest()); } await client.AddRequestAsync(new DicomCStoreRequest(@"test1.dcm")); await client.AddRequestAsync(new DicomCStoreRequest(@"test2.dcm")); await client.SendAsync(); foreach (DicomPresentationContext ctr in client.AdditionalPresentationContexts) { Console.WriteLine("PresentationContext: " + ctr.AbstractSyntax + " Result: " + ctr.Result); } var samplesDir = Path.Combine( Path.GetPathRoot(Environment.CurrentDirectory), "Development", "fo-dicom-samples"); var testDir = Path.Combine(samplesDir, "Test"); if (!Directory.Exists(testDir)) { Directory.CreateDirectory(testDir); } //var img = new DicomImage(samplesDir + @"\ClearCanvas\CRStudy\1.3.51.5145.5142.20010109.1105627.1.0.1.dcm"); //img.RenderImage().Save(testDir + @"\test.jpg"); //var df = DicomFile.Open(samplesDir + @"\User Submitted\overlays.dcm"); //Console.WriteLine(df.FileMetaInfo.Get<DicomTransferSyntax>(DicomTag.TransferSyntaxUID).UID.Name); //Console.WriteLine(df.Dataset.Get<PlanarConfiguration>(DicomTag.PlanarConfiguration)); //var img = new DicomImage(df.Dataset); //img.RenderImage().Save(testDir + @"\test.jpg"); //df = df.ChangeTransferSyntax(DicomTransferSyntax.JPEGLSLossless); //df.Save(testDir + @"\test-jls.dcm"); //df = df.ChangeTransferSyntax(DicomTransferSyntax.JPEG2000Lossless); //df.Save(testDir + @"\test-j2k.dcm"); //df = df.ChangeTransferSyntax(DicomTransferSyntax.JPEGProcess14SV1); //df.Save(testDir + @"\test-jll.dcm"); //df = df.ChangeTransferSyntax(DicomTransferSyntax.RLELossless); //df.Save(testDir + @"\test-rle.dcm"); //df = df.ChangeTransferSyntax(DicomTransferSyntax.ExplicitVRLittleEndian); //df.Save(testDir + @"\test-ele.dcm"); //df = df.ChangeTransferSyntax(DicomTransferSyntax.ExplicitVRBigEndian); //df.Save(testDir + @"\test-ebe.dcm"); //df = df.ChangeTransferSyntax(DicomTransferSyntax.ImplicitVRLittleEndian); //df.Save(testDir + @"\test-ile.dcm"); //Console.WriteLine("End..."); //Console.ReadLine(); //df.WriteToLog(LogManager.GetCurrentClassLogger(), LogLevel.Info); //Console.WriteLine(DicomValueMultiplicity.Parse("1")); //Console.WriteLine(DicomValueMultiplicity.Parse("3")); //Console.WriteLine(DicomValueMultiplicity.Parse("1-3")); //Console.WriteLine(DicomValueMultiplicity.Parse("1-n")); //Console.WriteLine(DicomValueMultiplicity.Parse("2-2n")); //Console.WriteLine(DicomTag.Parse("00200020")); //Console.WriteLine(DicomTag.Parse("0008,0040")); //Console.WriteLine(DicomTag.Parse("(3000,0012)")); //Console.WriteLine(DicomTag.Parse("2000,2000:TEST CREATOR")); //Console.WriteLine(DicomTag.Parse("(4000,4000:TEST_CREATOR:2)")); //Console.WriteLine(DicomMaskedTag.Parse("(30xx,xx90)")); //Console.WriteLine(DicomMaskedTag.Parse("(3000-3021,0016)")); //DicomRange<DateTime> r = new DicomRange<DateTime>(DateTime.Now.AddSeconds(-5), DateTime.Now.AddSeconds(5)); //Console.WriteLine(r.Contains(DateTime.Now)); //Console.WriteLine(r.Contains(DateTime.Today)); //Console.WriteLine(r.Contains(DateTime.Now.AddSeconds(60))); //DicomDictionary dict = new DicomDictionary(); //dict.Load(@"F:\Development\fo-dicom\DICOM\Dictionaries\dictionary.xml", DicomDictionaryFormat.XML); //string output = Dicom.Generators.DicomTagGenerator.Generate("Dicom", "DicomTag", dict); //File.WriteAllText(@"F:\Development\fo-dicom\DICOM\DicomTagGenerated.cs", output); //output = Dicom.Generators.DicomDictionaryGenerator.Generate("Dicom", "DicomDictionary", "LoadInternalDictionary", dict); //File.WriteAllText(@"F:\Development\fo-dicom\DICOM\DicomDictionaryGenerated.cs", output); //string output = Dicom.Generators.DicomUIDGenerator.Process(@"F:\Development\fo-dicom\DICOM\Dictionaries\dictionary.xml"); //File.WriteAllText(@"F:\Development\fo-dicom\DICOM\DicomUIDGenerated.cs", output); } catch (Exception e) { if (!(e is DicomException)) { Console.WriteLine(e.ToString()); } } Console.ReadLine(); }
public IEnumerable <DicomCMoveResponse> OnCMoveRequest(DicomCMoveRequest request) { //var cMoveAETitle = CADServer.DB.CMoveAETitles.Where(a => a.AETitle == request.DestinationAE).ToList(); //// the c-move request contains the DestinationAE. the data of this AE should be configured somewhere. //if (cMoveAETitle.Count == 0) //{ // 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 = cMoveAETitle[0].Port; //var destinationIP = cMoveAETitle[0].IP; var destinationPort = 11112; var destinationIP = "127.0.0.1"; IDbCommand selectCommand = PacsServer.DatabaseService.CreateCommand(); selectCommand.Connection = PacsServer.DatabaseService.CreateConnection(); selectCommand.CommandText = string.Format(@"SELECT * From CMoveIPTable WHERE AEtitle = '{0}'", request.DestinationAE); selectCommand.Connection.Open(); using (var reader = selectCommand.ExecuteReader(CommandBehavior.CloseConnection | CommandBehavior.SingleRow)) { if (reader.Read()) { destinationPort = reader.GetInt32(2); destinationIP = reader.GetString(1); Console.WriteLine("{0} {1} {2} {3}", reader.GetInt64(0), reader.GetString(1), reader.GetInt32(2), reader.GetString(3)); } else { yield return(new DicomCMoveResponse(request, DicomStatus.QueryRetrieveMoveDestinationUnknown)); yield return(new DicomCMoveResponse(request, DicomStatus.ProcessingFailure)); yield break; } } var queryLevel = request.Level; var matchingFiles = new List <IStorageLocation>(); switch (queryLevel) { case DicomQueryRetrieveLevel.Patient: { IEnumerable <DicomDataset> resStudys = PacsServer.QueryService.FindStudies(request.Dataset, new QueryOptions()); foreach (var resStudy in resStudys) { var resSerices = PacsServer.QueryService.FindSeries(resStudy, new QueryOptions()); foreach (var resSerice in resSerices) { AddSearchRequestData(resSerice); var resObjects = PacsServer.QueryService.FindObjectInstances(resSerice, new QueryOptions()); foreach (var resObject in resObjects) { matchingFiles.Add(RetrieveSopInstance(resObject)); } } } } break; case DicomQueryRetrieveLevel.Study: { IEnumerable <DicomDataset> resStudys = PacsServer.QueryService.FindStudies(request.Dataset, new QueryOptions()); foreach (var resStudy in resStudys) { var resSerices = PacsServer.QueryService.FindSeries(resStudy, new QueryOptions()); foreach (var resSerice in resSerices) { AddSearchRequestData(resSerice); var resObjects = PacsServer.QueryService.FindObjectInstances(resSerice, new QueryOptions()); foreach (var resObject in resObjects) { matchingFiles.Add(RetrieveSopInstance(resObject)); } } } } break; case DicomQueryRetrieveLevel.Series: { var resSerices = PacsServer.QueryService.FindSeries(request.Dataset, new QueryOptions()); foreach (var resSerice in resSerices) { AddSearchRequestData(resSerice); var resObjects = PacsServer.QueryService.FindObjectInstances(resSerice, new QueryOptions()); foreach (var resObject in resObjects) { matchingFiles.Add(RetrieveSopInstance(resObject)); } } } break; case DicomQueryRetrieveLevel.Image: { AddSearchRequestData(request.Dataset); var resObjects = PacsServer.QueryService.FindObjectInstances(request.Dataset, new QueryOptions()); foreach (var resObject in resObjects) { matchingFiles.Add(RetrieveSopInstance(resObject)); } } break; } var client = new DicomClient(destinationIP, destinationPort, false, PacsServer.AETitle, request.DestinationAE); 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 (IStorageLocation location in matchingFiles) { var storeRequest = new DicomCStoreRequest(location.ID); // !!! 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++; } }; client.AddRequestAsync(storeRequest).Wait(); } var sendTask = client.SendAsync(); 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("..finished"); yield return(new DicomCMoveResponse(request, DicomStatus.Success)); }
// 建立连接并查询 async public void DicomCFindRequestFunct(ServerConfig OneServerConfig) { // 首先清空原来的查询结果 Results.Clear(); // 建立连接,查找病人下面的所有Study var client = new DicomClient(OneServerConfig.RemoteIp, OneServerConfig.RemotePort, false, OneServerConfig.LocalAeTitle, OneServerConfig.RemoteAeTitle); client.NegotiateAsyncOps(); var patientRequest = DicomCFindRequest.CreateStudyQuery( patientId: ToQueryPatientId, patientName: ToQueryPatientName, studyDateTime: ToQueryStudyDateRange); // ATTENTION // 需要把DicomTag.StudyTime去除才能得到正确的查询结果,可能是fo-dicom程序的Bug // 注意这个StudyTime与查询里面的studyDateTime不是一个意思 patientRequest.Dataset.Remove(DicomTag.StudyTime); var patientRequestResults = new List <ValuableResult>(); patientRequest.OnResponseReceived += (req, response) => { if (response.Status == DicomStatus.Pending) { lock (patientRequestResults) { var patientId = response.Dataset.GetSingleValueOrDefault(DicomTag.PatientID, string.Empty); var studyInstanceUid = response.Dataset.GetSingleValueOrDefault(DicomTag.StudyInstanceUID, string.Empty); if (!string.IsNullOrEmpty(patientId) && !string.IsNullOrEmpty(studyInstanceUid)) { patientRequestResults.Add(new ValuableResult() { PatientId = patientId, StudyInstanceUid = studyInstanceUid }); // 更新主界面显示 // OneServerConfig.AddLogStr($"Found {response.Dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty)} " + // $"{patientId} and the study instance id is {studyInstanceUid} which was created in " + // $"{response.Dataset.GetSingleValueOrDefault(DicomTag.StudyDate, string.Empty)}"); // OneServerConfig.AddLogStr($"Found: {response.Dataset.GetSingleValueOrDefault(DicomTag.PatientName, string.Empty)} "); } } } if (response.Status == DicomStatus.Success) { // Console.WriteLine(response.Status.ToString()); //OneServerConfig.LogInfo += response.Status.ToString() + Environment.NewLine; } }; await client.AddRequestAsync(patientRequest); await client.SendAsync(); // 病人层次的查询结束 // 得到需要的病人ID和Study的ID // 查询对应的序列 var seriesRequestResults = new List <ValuableResult>(); foreach (var patientRequestResult in patientRequestResults) { var seriesRequest = DicomCFindRequest.CreateSeriesQuery(patientRequestResult.StudyInstanceUid); seriesRequest.OnResponseReceived += (req, response) => { if (response.Status == DicomStatus.Pending) { var seriesUid = response.Dataset?.GetSingleValue <string>(DicomTag.SeriesInstanceUID); if (!string.IsNullOrEmpty(seriesUid)) { string modality = response.Dataset?.GetSingleValue <string>(DicomTag.Modality); if ((IsCtSave && modality.ToUpper().Trim() == "CT") || (IsMrSave && modality.ToUpper().Trim() == "MR") || (IsPetSave && modality.ToUpper().Trim() == "PT") || (IsRtsSave && modality.ToUpper().Trim() == "RTSTRUCT") || (IsRtpSave && modality.ToUpper().Trim() == "PTPLAN") || (IsRtDoseSave && modality.ToUpper().Trim() == "RTDOSE")) { seriesRequestResults.Add(new ValuableResult() { PatientId = patientRequestResult.PatientId, StudyInstanceUid = patientRequestResult.StudyInstanceUid, SeriesInstanceUid = seriesUid }); OneServerConfig.AddLogStr($"Found: {patientRequestResult.PatientId} {modality}"); } } } if (response.Status == DicomStatus.Success) { // Console.WriteLine(response.Status.ToString()); //OneServerConfig.LogInfo += response.Status.ToString() + Environment.NewLine; } // serieUids.Add(response.Dataset?.GetSingleValue<string>(DicomTag.SeriesInstanceUID)); }; await client.AddRequestAsync(seriesRequest); await client.SendAsync(); } Results.AddRange(seriesRequestResults); }
static async Task Main(string[] args) { var client = new DicomClient(QRServerHost, QRServerPort, false, CallingAE, CalledAE); client.NegotiateAsyncOps(); //// Find a list of Studies //var request = CreateStudyRequestByPatientName("Traxler^Y*"); //var studyUids = new List<string>(); //request.OnResponseReceived += (req, response) => //{ // DebugStudyResponse(response); // studyUids.Add(response.Dataset?.GetSingleValue<string>(DicomTag.StudyInstanceUID)); //}; //await client.AddRequestAsync(request); //await client.SendAsync(); //// find all series from a study that previous was returned var studyUID = "111"; //var studyUID = studyUids[0]; //request = CreateSeriesRequestByStudyUID(studyUID); //var serieUids = new List<string>(); //request.OnResponseReceived += (req, response) => //{ // DebugSerieResponse(response); // serieUids.Add(response.Dataset?.GetSingleValue<string>(DicomTag.SeriesInstanceUID)); //}; //await client.AddRequestAsync(request); //await client.SendAsync(); // now get all the images of a serie with cGet in the same association client = new DicomClient(QRServerHost, QRServerPort, false, CallingAE, CalledAE); var cGetRequest = CreateCGetBySeriesUID(studyUID, "11"); client.OnCStoreRequest += (DicomCStoreRequest req) => { Console.WriteLine(DateTime.Now.ToString() + " recived"); SaveImage(req.Dataset); return(Task.FromResult(new DicomCStoreResponse(req, DicomStatus.Success))); }; // the client has to accept storage of the images. We know that the requested images are of SOP class Secondary capture, // so we add the Secondary capture to the additional presentation context // a more general approach would be to mace a cfind-request on image level and to read a list of distinct SOP classes of all // the images. these SOP classes shall be added here. var pcs = DicomPresentationContext.GetScpRolePresentationContextsFromStorageUids( DicomStorageCategory.Image, DicomTransferSyntax.ExplicitVRLittleEndian, DicomTransferSyntax.ImplicitVRLittleEndian, DicomTransferSyntax.ImplicitVRBigEndian); client.AdditionalPresentationContexts.AddRange(pcs); await client.AddRequestAsync(cGetRequest); await client.SendAsync(); // if the images shall be sent to an existing storescp and this storescp is configured on the QR SCP then a CMove could be performed: // here we want to see how a error case looks like - because the test QR Server does not know the node FODICOMSCP client = new DicomClient(QRServerHost, QRServerPort, false, CallingAE, CalledAE); var cMoveRequest = CreateCMoveByStudyUID("STORESCP", studyUID); bool?moveSuccessfully = null; cMoveRequest.OnResponseReceived += (DicomCMoveRequest requ, DicomCMoveResponse response) => { if (response.Status.State == DicomState.Pending) { Console.WriteLine("Sending is in progress. please wait: " + response.Remaining.ToString()); } else if (response.Status.State == DicomState.Success) { Console.WriteLine("Sending successfully finished"); moveSuccessfully = true; } else if (response.Status.State == DicomState.Failure) { Console.WriteLine("Error sending datasets: " + response.Status.Description); moveSuccessfully = false; } Console.WriteLine(response.Status); }; await client.AddRequestAsync(cMoveRequest); await client.SendAsync(); if (moveSuccessfully.GetValueOrDefault(false)) { Console.WriteLine("images sent successfully"); // images sent successfully from QR Server to the store scp } Console.ReadLine(); }
static async Task Main(string[] args) { var storeMore = ""; StoreServerHost = GetServerHost(); StoreServerPort = GetServerPort(); Console.WriteLine("***************************************************"); Console.WriteLine("Server AE Title: " + StoreServerAET); Console.WriteLine("Server Host Address: " + StoreServerHost); Console.WriteLine("Server Port: " + StoreServerPort); Console.WriteLine("Client AE Title: " + AET); Console.WriteLine("***************************************************"); var client = new DicomClient(StoreServerHost, StoreServerPort, false, AET, StoreServerAET); client.NegotiateAsyncOps(); do { try { Console.WriteLine(); Console.WriteLine("Enter the path for a DICOM file:"); Console.Write(">>>"); string dicomFile = Console.ReadLine(); while (!File.Exists(dicomFile)) { Console.WriteLine("Invalid file path, enter the path for a DICOM file or press Enter to Exit:"); dicomFile = Console.ReadLine(); if (string.IsNullOrWhiteSpace(dicomFile)) { return; } } var request = new DicomCStoreRequest(dicomFile); request.OnResponseReceived += (req, response) => { Console.WriteLine("C-Store Response Received, Status: " + response.Status); }; await client.AddRequestAsync(request); await client.SendAsync(); } catch (Exception exception) { Console.WriteLine(); Console.WriteLine("----------------------------------------------------"); Console.WriteLine("Error storing file. Exception Details:"); Console.WriteLine(exception.ToString()); Console.WriteLine("----------------------------------------------------"); Console.WriteLine(); } Console.WriteLine("To store another file, enter \"y\"; Othersie, press enter to exit: "); Console.Write(">>>"); storeMore = Console.ReadLine().Trim(); } while (storeMore.Length > 0 && storeMore.ToLower()[0] == 'y'); }
static void Main(string[] args) { Directory.CreateDirectory(Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName) + "\\Log"); var storeMore = ""; int tCnt = _thread; log.Info("***************************************************"); log.Info("Server Host Address: " + _storeServerHost); log.Info("Server Port: " + _storeServerPort); log.Info("Server AE Title: " + _storeServerAET); log.Info("Client AE Title: " + _aet); log.Info("Test count: " + _count); log.Info("Test interval: " + _interval); log.Info("Test thread: " + _thread); log.Info("Test dicom: " + _testDICOMPath); log.Info("***************************************************"); if (_manual == "Y") { tCnt = 1; log.Info("To start test, enter \"y\"; Othersie, press any key to exit: "); storeMore = Console.ReadLine().Trim(); if (storeMore.Length > 0 && storeMore.ToLower()[0] == 'y') { } else { Environment.Exit(0); } } Thread[] workerThreads = new Thread[tCnt]; for (int i = 0; i < workerThreads.Length; i++) { int tNum = i; workerThreads[i] = new Thread(new ThreadStart(async() => { //var client = new DicomClient(_storeServerHost, _storeServerPort, false, _aet, _storeServerAET); //Add a handler to be notified of any association rejections //client.AssociationRejected += (sender, e) => { // log.Warn($"Association was rejected. Rejected Reason:{e.Reason}"); //}; //Add a handler to be notified of any association information on successful connections //client.AssociationAccepted += (sender, e) => //{ // log.Info(($"Association was accepted by:{e.Association.RemoteHost}"); //}; //Add a handler to be notified when association is successfully released - this can be triggered by the remote peer as well //client.AssociationReleased += (sender, e) => { // log.Info("Association was released. BYE BYE!"); //}; //client.RequestTimedOut += (sender, e) => //{ // log.Warn($"Send PACS error exception:{e.Request} {e.Timeout}"); // throw new NotImplementedException(); //}; //client.NegotiateAsyncOps(); int count = 0; while ((_manual == "Y" && storeMore.Length > 0 && storeMore.ToLower()[0] == 'y') || (_manual != "Y" && count < _count)) { try { var client = new DicomClient(_storeServerHost, _storeServerPort, false, _aet, _storeServerAET); client.NegotiateAsyncOps(); string dicomFile = _testDICOMPath; if (_manual == "Y") { while (!File.Exists(dicomFile)) { log.Warn("Invalid file path, enter the path for a DICOM file or press Enter to Exit:"); dicomFile = Console.ReadLine(); if (string.IsNullOrWhiteSpace(dicomFile)) { return; } } } else { if (!File.Exists(dicomFile)) { log.Warn("Invalid file path, check test dicom file: " + _testDICOMPath); return; } } if (_manual != "Y") { log.Info("Test " + tNum + "-[" + (count + 1) + "]"); } var request = new DicomCStoreRequest(dicomFile); request.OnResponseReceived += (req, response) => { if (_manual == "Y") { log.Info("C-Store Response Received, Status: " + response.Status); log.Info("To test again, enter \"y\"; Othersie, press any key to exit: "); storeMore = Console.ReadLine().Trim(); if (storeMore.Length > 0 && storeMore.ToLower()[0] == 'y') { } else { Environment.Exit(0); } } else { log.Info(tNum + "-[" + (count + 1) + "] " + "C-Store Response Received, Status: " + response.Status); if (count < (_count - 1)) { int fortimerinterval = 0; if (_interval == "random") { fortimerinterval = rand.Next(_randomIntervalmin, _randomIntervalmax); } else { fortimerinterval = Int32.Parse(_interval); } log.Info(tNum + "-[" + (count + 1) + "] " + "Time interval " + fortimerinterval / 1000 + " seconds"); count++; Thread.Sleep(fortimerinterval); } else { bool allDone = true; foreach (var workerThread in workerThreads) { if (workerThread.IsAlive) { allDone = false; break; } } if (allDone) { Thread.Sleep(15000); Environment.Exit(0); } } } }; await client.AddRequestAsync(request); await client.SendAsync(); } catch (DicomAssociationRejectedException assoRejectEx) { log.Warn("----------------------------------------------------"); log.Warn(tNum + "-[" + (count + 1) + "] " + assoRejectEx.Message); log.Warn("----------------------------------------------------"); } catch (Exception exception) { log.Error("----------------------------------------------------"); log.Error(tNum + "-[" + (count + 1) + "] " + exception.ToString()); log.Error("----------------------------------------------------"); } } } )) { IsBackground = true, Name = $"SenderThread #{i}", Priority = ThreadPriority.AboveNormal }; workerThreads[i].Start(); } // Await all background threads foreach (var workerThread in workerThreads) { workerThread.Join(600000); // 10 minutes thread timeout } SpinWait.SpinUntil(() => false); }