/// <summary> /// Create Duplicate SIQ Entry /// </summary> /// <param name="file"></param> /// <param name="location"></param> /// <param name="sourcePath"></param> /// <param name="queue"></param> /// <param name="uid"></param> /// <param name="data"></param> public static void CreateDuplicateSIQEntry(DicomFile file, StudyStorageLocation location, string sourcePath, WorkQueue queue, WorkQueueUid uid, StudyProcessWorkQueueData data) { Platform.Log(LogLevel.Info, "Creating Work Queue Entry for duplicate..."); String uidGroup = queue.GroupID ?? queue.GetKey().Key.ToString(); using (var commandProcessor = new ServerCommandProcessor("Insert Work Queue entry for duplicate")) { commandProcessor.AddCommand(new FileDeleteCommand(sourcePath, true)); var sopProcessingContext = new SopInstanceProcessorContext(commandProcessor, location, uidGroup); DicomProcessingResult result = Process(sopProcessingContext, file, data); if (!result.Successful) { FailUid(uid, true); return; } commandProcessor.AddCommand(new DeleteWorkQueueUidCommand(uid)); if (!commandProcessor.Execute()) { Platform.Log(LogLevel.Error, "Unexpected error when creating duplicate study integrity queue entry: {0}", commandProcessor.FailureReason); FailUid(uid, true); } } }
public bool CompleteStream(DicomServer server, ServerAssociationParameters assoc, byte presentationId, DicomMessage message) { DicomProcessingResult result; try { if (_fileStream != null) { _fileStream.Flush(true); _fileStream.Close(); _fileStream.Dispose(); _fileStream = null; } ISopInstanceImporter importer = IoC.Get <ISopInstanceImporter>(); importer.Context = _importContext; result = importer.ImportFile(message, _sourceFilename); if (result.Successful) { if (!String.IsNullOrEmpty(result.AccessionNumber)) { Platform.Log(LogLevel.Info, "Received SOP Instance {0} from {1} to {2} (A#:{3} StudyUid:{4})", result.SopInstanceUid, assoc.CallingAE, assoc.CalledAE, result.AccessionNumber, result.StudyInstanceUid); } else { Platform.Log(LogLevel.Info, "Received SOP Instance {0} from {1} to {2} (StudyUid:{3})", result.SopInstanceUid, assoc.CallingAE, assoc.CalledAE, result.StudyInstanceUid); } } } catch (Exception e) { result = new DicomProcessingResult { DicomStatus = DicomStatuses.ProcessingFailure, ErrorMessage = e.Message }; } if (!result.Successful) { Platform.Log(LogLevel.Warn, "Failure importing sop: {0}", result.ErrorMessage); } CleanupDirectory(); server.SendCStoreResponse(presentationId, message.MessageId, message.AffectedSopInstanceUid, result.DicomStatus); return(true); }
public override bool OnReceiveRequest(DicomServer server, ServerAssociationParameters association, byte presentationId, DicomMessage message) { try { SopInstanceImporterContext context = new SopInstanceImporterContext( String.Format("{0}_{1}", association.CallingAE, association.TimeStamp.ToString("yyyyMMddhhmmss")), association.CallingAE, Partition.AeTitle); DicomProcessingResult result = new DicomProcessingResult(); ISopInstanceImporter importer = IoC.Get <ISopInstanceImporter>(); if (importer != null) { importer.Context = context; result = importer.Import(message); } if (result.Successful) { if (!String.IsNullOrEmpty(result.AccessionNumber)) { Log.Logger.Info("Received SOP Instance {0} from {1} to {2} (A#:{3} StudyUid:{4})", result.SopInstanceUid, association.CallingAE, association.CalledAE, result.AccessionNumber, result.StudyInstanceUid); } else { Log.Logger.Info("Received SOP Instance {0} from {1} to {2} (StudyUid:{3})", result.SopInstanceUid, association.CallingAE, association.CalledAE, result.StudyInstanceUid); } } else { Log.Logger.Warn("Failure importing sop: {0}", result.ErrorMessage); } server.SendCStoreResponse(presentationId, message.MessageId, message.AffectedSopInstanceUid, result.DicomStatus); return(true); } catch (DicomDataException ex) { Log.Logger.Error(ex, "Error when import {0}", message.AffectedSopInstanceUid); return(false); // caller will abort the association } catch (Exception ex) { Log.Logger.Error(ex, "Error when import {0}", message.AffectedSopInstanceUid); return(false); // caller will abort the association } }
public override bool OnReceiveRequest(DicomServer server, ServerAssociationParameters association, byte presentationId, DicomMessage message) { try { var context = new SopInstanceImporterContext( String.Format("{0}_{1}", association.CallingAE, association.TimeStamp.ToString("yyyyMMddhhmmss")), association.CallingAE, association.CalledAE); if (Device != null && Device.DeviceTypeEnum.Equals(DeviceTypeEnum.PrimaryPacs)) { context.DuplicateProcessing = DuplicateProcessingEnum.OverwriteSopAndUpdateDatabase; } var importer = new SopInstanceImporter(context); DicomProcessingResult result = importer.Import(message); if (result.Successful) { if (!String.IsNullOrEmpty(result.AccessionNumber)) { Platform.Log(LogLevel.Info, "Received SOP Instance {0} from {1} to {2} (A#:{3} StudyUid:{4})", result.SopInstanceUid, association.CallingAE, association.CalledAE, result.AccessionNumber, result.StudyInstanceUid); } else { Platform.Log(LogLevel.Info, "Received SOP Instance {0} from {1} to {2} (StudyUid:{3})", result.SopInstanceUid, association.CallingAE, association.CalledAE, result.StudyInstanceUid); } } else { Platform.Log(LogLevel.Warn, "Failure importing sop: {0}", result.ErrorMessage); } server.SendCStoreResponse(presentationId, message.MessageId, message.AffectedSopInstanceUid, result.DicomStatus); return(true); } catch (DicomDataException ex) { Platform.Log(LogLevel.Error, ex); return(false); // caller will abort the association } catch (Exception ex) { Platform.Log(LogLevel.Error, ex); return(false); // caller will abort the association } }
private void ImportFile(string file, ImportStudyContext context) { // Note, we're not doing impersonation of the user's identity, so we may have failures here // which would be new in Marmot. try { EnsureMaxUsedSpaceNotExceeded(); var dicomFile = new DicomFile(file); DicomReadOptions readOptions = Request.FileImportBehaviour == FileImportBehaviourEnum.Save ? DicomReadOptions.Default : DicomReadOptions.Default | DicomReadOptions.StorePixelDataReferences; dicomFile.Load(readOptions); var importer = new ImportFilesUtility(context); DicomProcessingResult result = importer.Import(dicomFile, Request.BadFileBehaviour, Request.FileImportBehaviour); if (result.DicomStatus == DicomStatuses.Success) { Progress.NumberOfFilesImported++; } else { Progress.NumberOfImportFailures++; Progress.StatusDetails = result.ErrorMessage; } } catch (NotEnoughStorageException) { Progress.NumberOfImportFailures++; Progress.StatusDetails = SR.ExceptionNotEnoughStorage; context.FatalError = true; } catch (Exception e) { Platform.Log(LogLevel.Warn, "Unable to import DICOM File ({0}): {1}", file, e.Message); Progress.NumberOfImportFailures++; Progress.StatusDetails = string.Format("{0}: {1}", file, e.Message); } }
// Essentially this is a copy of ClearCanvas.ImageViewer.StudyManagement.Core.DicomFilePublisher that allows us to move files // instead of leaving them orphaned in the original folder. // TODO: revisit this when ClearCanvas.ImageViewer.StudyManagement.Core.DicomFilePublisher gets an option for moving files public static void PublishLocal(ICollection <DicomFile> files) { if (files == null || files.Count == 0) { return; } var configuration = ClearCanvas.ImageViewer.Common.DicomServer.DicomServer.GetConfiguration(); var context = new ImportStudyContext(configuration.AETitle, StudyStore.GetConfiguration(), EventSource.CurrentUser); var utility = new ImportFilesUtility(context); try { DicomProcessingResult failureResult = null; foreach (var file in files) { var importResult = utility.Import(file, BadFileBehaviourEnum.Move, FileImportBehaviourEnum.Move); // THIS IS THE CHANGE if (importResult.DicomStatus != DicomStatuses.Success) { Platform.Log(LogLevel.Warn, "Unable to import published file: {0}", importResult.ErrorMessage); failureResult = importResult; } } if (failureResult != null) { throw new ApplicationException(failureResult.ErrorMessage); } } catch (Exception ex) { var message = String.Format("Failed to import files"); throw new Exception(message, ex); } }
/// <summary> /// Inserts the duplicate DICOM file into the <see cref="WorkQueue"/> for processing (if applicable). /// </summary> /// <param name="context">The processing context.</param> /// <param name="file">The duplicate DICOM file being processed.</param> /// <param name="data">Extra data to insert for the WorkQueue item.</param> /// <param name="sourceFilename">Optional source filename already saved to disk to import.</param> /// <returns>A <see cref="DicomProcessingResult"/> that contains the result of the processing.</returns> /// <remarks> /// This method inserts a <see cref="CommandBase"/> into <paramref name="context.CommandProcessor"/>. /// The outcome of the operation depends on the <see cref="DuplicateSopPolicyEnum"/> of the <see cref="ServerPartition"/>. /// If it is set to <see cref="DuplicateSopPolicyEnum.CompareDuplicates"/>, the duplicate file will be /// inserted into the <see cref="WorkQueue"/> for processing. /// </remarks> public static DicomProcessingResult Process(SopInstanceProcessorContext context, DicomMessageBase file, StudyProcessWorkQueueData data, string sourceFilename = null) { Platform.CheckForNullReference(file, "file"); Platform.CheckForNullReference(context, "context"); Platform.CheckMemberIsSet(context.Group, "parameters.Group"); Platform.CheckMemberIsSet(context.CommandProcessor, "parameters.CommandProcessor"); Platform.CheckMemberIsSet(context.StudyLocation, "parameters.StudyLocation"); if (string.IsNullOrEmpty(sourceFilename)) { Platform.CheckForNullReference(file as DicomFile, "file"); } var result = new DicomProcessingResult { DicomStatus = DicomStatuses.Success, Successful = true, StudyInstanceUid = file.DataSet[DicomTags.StudyInstanceUid].GetString(0, string.Empty), SeriesInstanceUid = file.DataSet[DicomTags.SeriesInstanceUid].GetString(0, string.Empty), SopInstanceUid = file.DataSet[DicomTags.SopInstanceUid].GetString(0, string.Empty), SopClassUid = file.DataSet[DicomTags.SopClassUid].GetString(0, string.Empty), AccessionNumber = file.DataSet[DicomTags.AccessionNumber].GetString(0, string.Empty) }; string failureMessage; if (context.DuplicateProcessing.HasValue && context.DuplicateProcessing.Value.Equals(DuplicateProcessingEnum.Reject)) { failureMessage = String.Format("Duplicate SOP Instance received, rejecting {0}", result.SopInstanceUid); Platform.Log(LogLevel.Info, failureMessage); result.SetError(DicomStatuses.DuplicateSOPInstance, failureMessage); return(result); } if (SopClassIsReport(result.SopClassUid) && context.StudyLocation.ServerPartition.AcceptLatestReport) { Platform.Log(LogLevel.Info, "Duplicate Report received, overwriting {0}", result.SopInstanceUid); if (string.IsNullOrEmpty(sourceFilename)) { ProcessStoredDuplicate(context, file as DicomFile, data, DuplicateProcessingEnum.OverwriteReport); } else { ProcessStoredDuplicateFile(context, sourceFilename, file, data, DuplicateProcessingEnum.OverwriteReport); } return(result); } if (DuplicatePolicy.IsParitionDuplicatePolicyOverridden(context.StudyLocation)) { // Note: this is a special case where we need to temporarily override the duplicate policy for a particular study // so that SIQ entry can be processed (#10569). This should only happen once in a blue moon. Platform.Log(LogLevel.Warn, "Duplicate instance received for study {0} on Partition {1}. Duplicate policy overridden in app config. Will overwrite {2}", result.StudyInstanceUid, context.StudyLocation.ServerPartition.AeTitle, result.SopInstanceUid); if (string.IsNullOrEmpty(sourceFilename)) { ProcessStoredDuplicate(context, file as DicomFile, data, DuplicateProcessingEnum.OverwriteSop); } else { ProcessStoredDuplicateFile(context, sourceFilename, file, data, DuplicateProcessingEnum.OverwriteSop); } return(result); } if (context.DuplicateProcessing.HasValue) { Platform.Log(LogLevel.Info, context.DuplicateProcessing.Value.Equals(DuplicateProcessingEnum.Compare) ? "Duplicate SOP Instance received, comparing {0}" : "Duplicate SOP Instance received, overwriting {0}", result.SopInstanceUid); if (string.IsNullOrEmpty(sourceFilename)) { ProcessStoredDuplicate(context, file as DicomFile, data, context.DuplicateProcessing.Value); } else { ProcessStoredDuplicateFile(context, sourceFilename, file, data, context.DuplicateProcessing.Value); } return(result); } if (context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum.Equals(DuplicateSopPolicyEnum.AcceptLatest)) { Platform.Log(LogLevel.Info, "Duplicate SOP Instance received, overwriting {0}", result.SopInstanceUid); if (string.IsNullOrEmpty(sourceFilename)) { ProcessStoredDuplicate(context, file as DicomFile, data, DuplicateProcessingEnum.OverwriteSopAndUpdateDatabase); } else { ProcessStoredDuplicateFile(context, sourceFilename, file, data, DuplicateProcessingEnum.OverwriteSopAndUpdateDatabase); } return(result); } if (context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum.Equals(DuplicateSopPolicyEnum.SendSuccess)) { Platform.Log(LogLevel.Info, "Duplicate SOP Instance received, sending success response {0}", result.SopInstanceUid); return(result); } if (context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum.Equals(DuplicateSopPolicyEnum.RejectDuplicates)) { failureMessage = String.Format("Duplicate SOP Instance received, rejecting {0}", result.SopInstanceUid); Platform.Log(LogLevel.Info, failureMessage); result.SetError(DicomStatuses.DuplicateSOPInstance, failureMessage); return(result); } if (context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum.Equals(DuplicateSopPolicyEnum.CompareDuplicates)) { if (string.IsNullOrEmpty(sourceFilename)) { ProcessStoredDuplicate(context, file as DicomFile, data, DuplicateProcessingEnum.Compare); } else { ProcessStoredDuplicateFile(context, sourceFilename, file, data, DuplicateProcessingEnum.Compare); } } else { failureMessage = String.Format("Duplicate SOP Instance received. Unsupported duplicate policy {0}.", context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum); result.SetError(DicomStatuses.DuplicateSOPInstance, failureMessage); return(result); } return(result); }
public bool CompleteStream(Dicom.Network.DicomServer server, ServerAssociationParameters assoc, byte presentationId, DicomMessage message) { DicomProcessingResult result; var importer = new ImportFilesUtility(_importContext); if (_rejectFile) { result = new DicomProcessingResult(); result.SetError(DicomStatuses.StorageStorageOutOfResources, string.Format("Import failed, disk space usage exceeded")); string studyInstanceUid = message.DataSet[DicomTags.StudyInstanceUid].GetString(0, string.Empty); WorkItem workItem; lock (_importContext.StudyWorkItemsSyncLock) _importContext.StudyWorkItems.TryGetValue(studyInstanceUid, out workItem); importer.InsertFailedWorkItemUid(workItem, message, result); _importContext.FatalError = true; importer.AuditFailure(result); Platform.Log(LogLevel.Warn, "Failure receiving sop, out of disk space: {0}", message.AffectedSopInstanceUid); server.SendCStoreResponse(presentationId, message.MessageId, message.AffectedSopInstanceUid, result.DicomStatus); return(true); } try { if (_fileStream != null) { _fileStream.Flush(true); _fileStream.Close(); _fileStream.Dispose(); _fileStream = null; } // Convert to file to pass in the source filename var theFile = new DicomFile(message, _sourceFilename); result = importer.Import(theFile, BadFileBehaviourEnum.Delete, FileImportBehaviourEnum.Move); if (result.Successful) { if (!String.IsNullOrEmpty(result.AccessionNumber)) { Platform.Log(LogLevel.Info, "Received SOP Instance {0} from {1} to {2} (A#:{3} StudyUid:{4})", result.SopInstanceUid, assoc.CallingAE, assoc.CalledAE, result.AccessionNumber, result.StudyInstanceUid); } else { Platform.Log(LogLevel.Info, "Received SOP Instance {0} from {1} to {2} (StudyUid:{3})", result.SopInstanceUid, assoc.CallingAE, assoc.CalledAE, result.StudyInstanceUid); } } } catch (Exception e) { result = new DicomProcessingResult { DicomStatus = DicomStatuses.ProcessingFailure, ErrorMessage = e.Message }; } if (!result.Successful) { Platform.Log(LogLevel.Warn, "Failure importing sop: {0}", result.ErrorMessage); } CleanupFile(); server.SendCStoreResponse(presentationId, message.MessageId, message.AffectedSopInstanceUid, result.DicomStatus); return(true); }
/// <summary> /// Inserts the duplicate DICOM file into the <see cref="WorkQueue"/> for processing (if applicable). /// </summary> /// <param name="context">The processing context.</param> /// <param name="file">The duplicate DICOM file being processed.</param> /// <param name="data">Extra data to insert for the WorkQueue item.</param> /// <param name="sourceFilename">Optional source filename already saved to disk to import.</param> /// <returns>A <see cref="DicomProcessingResult"/> that contains the result of the processing.</returns> /// <remarks> /// This method inserts a <see cref="CommandBase"/> into <paramref name="context.CommandProcessor"/>. /// The outcome of the operation depends on the <see cref="DuplicateSopPolicyEnum"/> of the <see cref="ServerPartition"/>. /// If it is set to <see cref="DuplicateSopPolicyEnum.CompareDuplicates"/>, the duplicate file will be /// inserted into the <see cref="WorkQueue"/> for processing. /// </remarks> public static DicomProcessingResult Process(SopInstanceProcessorContext context, DicomMessageBase file, StudyProcessWorkQueueData data, string sourceFilename=null) { Platform.CheckForNullReference(file, "file"); Platform.CheckForNullReference(context, "context"); Platform.CheckMemberIsSet(context.Group, "parameters.Group"); Platform.CheckMemberIsSet(context.CommandProcessor, "parameters.CommandProcessor"); Platform.CheckMemberIsSet(context.StudyLocation, "parameters.StudyLocation"); if (string.IsNullOrEmpty(sourceFilename)) Platform.CheckForNullReference(file as DicomFile, "file"); var result = new DicomProcessingResult { DicomStatus = DicomStatuses.Success, Successful = true, StudyInstanceUid = file.DataSet[DicomTags.StudyInstanceUid].GetString(0, string.Empty), SeriesInstanceUid = file.DataSet[DicomTags.SeriesInstanceUid].GetString(0, string.Empty), SopInstanceUid = file.DataSet[DicomTags.SopInstanceUid].GetString(0, string.Empty), SopClassUid = file.DataSet[DicomTags.SopClassUid].GetString(0, string.Empty), AccessionNumber = file.DataSet[DicomTags.AccessionNumber].GetString(0, string.Empty) }; string failureMessage; if (context.DuplicateProcessing.HasValue && context.DuplicateProcessing.Value.Equals(DuplicateProcessingEnum.Reject)) { failureMessage = String.Format("Duplicate SOP Instance received, rejecting {0}", result.SopInstanceUid); Platform.Log(LogLevel.Info, failureMessage); result.SetError(DicomStatuses.DuplicateSOPInstance, failureMessage); return result; } if (SopClassIsReport(result.SopClassUid) && context.StudyLocation.ServerPartition.AcceptLatestReport) { Platform.Log(LogLevel.Info, "Duplicate Report received, overwriting {0}", result.SopInstanceUid); if (string.IsNullOrEmpty(sourceFilename)) ProcessStoredDuplicate(context, file as DicomFile, data, DuplicateProcessingEnum.OverwriteReport); else ProcessStoredDuplicateFile(context, sourceFilename, file, data, DuplicateProcessingEnum.OverwriteReport); return result; } if (DuplicatePolicy.IsParitionDuplicatePolicyOverridden(context.StudyLocation)) { Platform.Log(LogLevel.Warn, "Duplicate instance received for study {0} on Partition {1}. Duplicate policy overridden. Will overwrite {2}", result.StudyInstanceUid, context.StudyLocation.ServerPartition.AeTitle, result.SopInstanceUid); if (string.IsNullOrEmpty(sourceFilename)) ProcessStoredDuplicate(context, file as DicomFile, data, DuplicateProcessingEnum.OverwriteSop); else ProcessStoredDuplicateFile(context, sourceFilename, file, data, DuplicateProcessingEnum.OverwriteSop); return result; } if (context.DuplicateProcessing.HasValue) { Platform.Log(LogLevel.Info, context.DuplicateProcessing.Value.Equals(DuplicateProcessingEnum.Compare) ? "Duplicate SOP Instance received, comparing {0}" : "Duplicate SOP Instance received, overwriting {0}", result.SopInstanceUid); if (string.IsNullOrEmpty(sourceFilename)) ProcessStoredDuplicate(context, file as DicomFile, data, context.DuplicateProcessing.Value); else ProcessStoredDuplicateFile(context, sourceFilename, file, data, context.DuplicateProcessing.Value); return result; } if (context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum.Equals(DuplicateSopPolicyEnum.AcceptLatest)) { Platform.Log(LogLevel.Info, "Duplicate SOP Instance received, overwriting {0}", result.SopInstanceUid); if (string.IsNullOrEmpty(sourceFilename)) ProcessStoredDuplicate(context, file as DicomFile, data, DuplicateProcessingEnum.OverwriteSopAndUpdateDatabase); else ProcessStoredDuplicateFile(context, sourceFilename, file, data, DuplicateProcessingEnum.OverwriteSopAndUpdateDatabase); return result; } if (context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum.Equals(DuplicateSopPolicyEnum.SendSuccess)) { Platform.Log(LogLevel.Info, "Duplicate SOP Instance received, sending success response {0}", result.SopInstanceUid); return result; } if (context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum.Equals(DuplicateSopPolicyEnum.RejectDuplicates)) { failureMessage = String.Format("Duplicate SOP Instance received, rejecting {0}", result.SopInstanceUid); Platform.Log(LogLevel.Info, failureMessage); result.SetError(DicomStatuses.DuplicateSOPInstance, failureMessage); return result; } if (context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum.Equals(DuplicateSopPolicyEnum.CompareDuplicates)) { if (string.IsNullOrEmpty(sourceFilename)) ProcessStoredDuplicate(context, file as DicomFile, data, DuplicateProcessingEnum.Compare); else ProcessStoredDuplicateFile(context,sourceFilename,file,data,DuplicateProcessingEnum.Compare); } else { failureMessage = String.Format("Duplicate SOP Instance received. Unsupported duplicate policy {0}.", context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum); result.SetError(DicomStatuses.DuplicateSOPInstance, failureMessage); return result; } return result; }
private int ProcessFile(string filePath) { int importedSopCount = 0; bool isDicomFile = false; bool skipped = false; FileInfo fileInfo = new FileInfo(filePath); if (fileInfo.Exists) { DicomFile file; try { file = new DicomFile(filePath); file.Load(); isDicomFile = true; string studyInstanceUid; if (file.DataSet[DicomTags.StudyInstanceUid].TryGetString(0, out studyInstanceUid)) { skipped = _skippedStudies.Contains(studyInstanceUid); if (!skipped) { InitializeImporter(); try { DicomProcessingResult result = _importer.Import(file); if (result.Successful) { if (result.Duplicate) { // was imported but is duplicate } else { importedSopCount = 1; Platform.Log(LogLevel.Info, "Imported SOP {0} to {1}", result.SopInstanceUid, _parms.PartitionAE); ProgressChangedEventArgs progress = new ProgressChangedEventArgs(100, result.SopInstanceUid); // Fire the imported event. SopImportedEventArgs args = new SopImportedEventArgs { StudyInstanceUid = result.StudyInstanceUid, SeriesInstanceUid = result.SeriesInstanceUid, SopInstanceUid = result.SopInstanceUid }; EventsHelper.Fire(_sopImportedHandlers, this, args); OnProgressChanged(progress); } } else { if (result.DicomStatus == DicomStatuses.StorageStorageOutOfResources) { if (result.RestoreRequested) { EventsHelper.Fire(_restoreTriggerHandlers, this, null); } Platform.Log(LogLevel.Info, "Images for study {0} cannot be imported at this time because: {1}", result.StudyInstanceUid, result.ErrorMessage); _skippedStudies.Add(result.StudyInstanceUid); skipped = true; } else { Platform.Log(LogLevel.Warn, "Failed to import {0} to {1} : {2}", filePath, _parms.PartitionAE, result.ErrorMessage); } } } catch (DicomDataException ex) { // skip to next file, this file will be deleted Platform.Log(LogLevel.Warn, ex, "Failed to import {0} to {1}: {2}", filePath, _parms.PartitionAE, ex.Message); skipped = true; } } } else { throw new ApplicationException("Sop does not contains Study Instance Uid tag"); } } catch (Exception ex) { Platform.Log(LogLevel.Error, ex); } finally { try { if (importedSopCount > 0) { DeleteFile(fileInfo); } else if (!isDicomFile) { DeleteFile(fileInfo); } else { //is dicom file but could not be imported. if (!skipped) { DeleteFile(fileInfo); } } } catch (IOException ex) { Platform.Log(LogLevel.Error, ex, "Unable to delete file after it has been imported: {0}", fileInfo.FullName); // Raise alert because this file is stuck in the incoming folder and becomes a duplicate when it is imported again later on. // Depending on the duplicate policy, SIQ may be filled with many duplicate entries. ServerPlatform.Alert(AlertCategory.Application, AlertLevel.Critical, "File Importer", -1, null, TimeSpan.Zero, "The following file has been imported but could not be removed : {0}.\nError: {1}", fileInfo.FullName, ex.Message); } } } return(importedSopCount); }
// TODO: Make these values configurable #endregion #region Public Methods /// <summary> /// Inserts the duplicate DICOM file into the <see cref="WorkQueue"/> for processing (if applicable). /// </summary> /// <param name="context">The processing context.</param> /// <param name="file">Thje duplicate DICOM file being processed.</param> /// <returns>A <see cref="DicomProcessingResult"/> that contains the result of the processing.</returns> /// <remarks> /// This method inserts <see cref="ServerCommand"/> into <paramref name="context.CommandProcessor"/>. /// The outcome of the operation depends on the <see cref="DuplicateSopPolicyEnum"/> of the <see cref="ServerPartition"/>. /// If it is set to <see cref="DuplicateSopPolicyEnum.CompareDuplicates"/>, the duplicate file will be /// inserted into the <see cref="WorkQueue"/> for processing. /// </remarks> static public DicomProcessingResult Process(SopProcessingContext context, DicomFile file) { Platform.CheckForNullReference(file, "file"); Platform.CheckForNullReference(context, "context"); Platform.CheckMemberIsSet(context.Group, "parameters.Group"); Platform.CheckMemberIsSet(context.CommandProcessor, "parameters.CommandProcessor"); Platform.CheckMemberIsSet(context.StudyLocation, "parameters.StudyLocation"); var result = new DicomProcessingResult { DicomStatus = DicomStatuses.Success, Successful = true, StudyInstanceUid = file.DataSet[DicomTags.StudyInstanceUid].GetString(0, string.Empty), SeriesInstanceUid = file.DataSet[DicomTags.SeriesInstanceUid].GetString(0, string.Empty), SopInstanceUid = file.DataSet[DicomTags.SopInstanceUid].GetString(0, string.Empty), SopClassUid = file.DataSet[DicomTags.SopClassUid].GetString(0, string.Empty), AccessionNumber = file.DataSet[DicomTags.AccessionNumber].GetString(0, string.Empty) }; string failureMessage; if (SopClassIsReport(result.SopClassUid) && context.StudyLocation.ServerPartition.AcceptLatestReport) { Platform.Log(LogLevel.Info, "Duplicate Report received, overwriting {0}", result.SopInstanceUid); SaveDuplicate(context, file); context.CommandProcessor.AddCommand( new UpdateWorkQueueCommand(file, context.StudyLocation, true, ServerPlatform.DuplicateFileExtension, context.Group)); return(result); } if (DuplicatePolicy.IsParitionDuplicatePolicyOverridden(context.StudyLocation)) { Platform.Log(LogLevel.Warn, "Duplicate instance received for study {0} on Partition {1}. Duplicate policy overridden. Will overwrite {2}", result.StudyInstanceUid, context.StudyLocation.ServerPartition.AeTitle, result.SopInstanceUid); SaveDuplicate(context, file); context.CommandProcessor.AddCommand(new UpdateWorkQueueCommand(file, context.StudyLocation, true, ServerPlatform.DuplicateFileExtension, context.Group)); return(result); } else { if (context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum.Equals(DuplicateSopPolicyEnum.SendSuccess)) { Platform.Log(LogLevel.Info, "Duplicate SOP Instance received, sending success response {0}", result.SopInstanceUid); return(result); } if (context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum.Equals(DuplicateSopPolicyEnum.RejectDuplicates)) { failureMessage = String.Format("Duplicate SOP Instance received, rejecting {0}", result.SopInstanceUid); Platform.Log(LogLevel.Info, failureMessage); result.SetError(DicomStatuses.DuplicateSOPInstance, failureMessage); return(result); } if (context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum.Equals(DuplicateSopPolicyEnum.CompareDuplicates)) { SaveDuplicate(context, file); context.CommandProcessor.AddCommand( new UpdateWorkQueueCommand(file, context.StudyLocation, true, ServerPlatform.DuplicateFileExtension, context.Group)); } else { failureMessage = String.Format("Duplicate SOP Instance received. Unsupported duplicate policy {0}.", context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum); result.SetError(DicomStatuses.DuplicateSOPInstance, failureMessage); return(result); } } return(result); }
// TODO: Make these values configurable #endregion #region Public Methods /// <summary> /// Inserts the duplicate DICOM file into the <see cref="WorkQueue"/> for processing (if applicable). /// </summary> /// <param name="context">The processing context.</param> /// <param name="file">Thje duplicate DICOM file being processed.</param> /// <returns>A <see cref="DicomProcessingResult"/> that contains the result of the processing.</returns> /// <remarks> /// This method inserts <see cref="ServerCommand"/> into <paramref name="context.CommandProcessor"/>. /// The outcome of the operation depends on the <see cref="DuplicateSopPolicyEnum"/> of the <see cref="ServerPartition"/>. /// If it is set to <see cref="DuplicateSopPolicyEnum.CompareDuplicates"/>, the duplicate file will be /// inserted into the <see cref="WorkQueue"/> for processing. /// </remarks> static public DicomProcessingResult Process(SopProcessingContext context, DicomFile file) { Platform.CheckForNullReference(file, "file"); Platform.CheckForNullReference(context, "context"); Platform.CheckMemberIsSet(context.Group, "parameters.Group"); Platform.CheckMemberIsSet(context.CommandProcessor, "parameters.CommandProcessor"); Platform.CheckMemberIsSet(context.StudyLocation, "parameters.StudyLocation"); var result = new DicomProcessingResult { DicomStatus = DicomStatuses.Success, Successful = true, StudyInstanceUid = file.DataSet[DicomTags.StudyInstanceUid].GetString(0, string.Empty), SeriesInstanceUid = file.DataSet[DicomTags.SeriesInstanceUid].GetString(0, string.Empty), SopInstanceUid = file.DataSet[DicomTags.SopInstanceUid].GetString(0, string.Empty), SopClassUid = file.DataSet[DicomTags.SopClassUid].GetString(0, string.Empty), AccessionNumber = file.DataSet[DicomTags.AccessionNumber].GetString(0, string.Empty) }; string failureMessage; if (SopClassIsReport(result.SopClassUid) && context.StudyLocation.ServerPartition.AcceptLatestReport) { Platform.Log(LogLevel.Info, "Duplicate Report received, overwriting {0}", result.SopInstanceUid); SaveDuplicate(context, file); context.CommandProcessor.AddCommand( new UpdateWorkQueueCommand(file, context.StudyLocation, true, ServerPlatform.DuplicateFileExtension, context.Group)); return result; } if (DuplicatePolicy.IsParitionDuplicatePolicyOverridden(context.StudyLocation)) { Platform.Log(LogLevel.Warn, "Duplicate instance received for study {0} on Partition {1}. Duplicate policy overridden. Will overwrite {2}", result.StudyInstanceUid, context.StudyLocation.ServerPartition.AeTitle, result.SopInstanceUid); SaveDuplicate(context, file); context.CommandProcessor.AddCommand(new UpdateWorkQueueCommand(file, context.StudyLocation, true, ServerPlatform.DuplicateFileExtension, context.Group)); return result; } else { if (context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum.Equals(DuplicateSopPolicyEnum.SendSuccess)) { Platform.Log(LogLevel.Info, "Duplicate SOP Instance received, sending success response {0}", result.SopInstanceUid); return result; } if (context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum.Equals(DuplicateSopPolicyEnum.RejectDuplicates)) { failureMessage = String.Format("Duplicate SOP Instance received, rejecting {0}", result.SopInstanceUid); Platform.Log(LogLevel.Info, failureMessage); result.SetError(DicomStatuses.DuplicateSOPInstance, failureMessage); return result; } if (context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum.Equals(DuplicateSopPolicyEnum.CompareDuplicates)) { SaveDuplicate(context, file); context.CommandProcessor.AddCommand( new UpdateWorkQueueCommand(file, context.StudyLocation, true, ServerPlatform.DuplicateFileExtension, context.Group)); } else { failureMessage = String.Format("Duplicate SOP Instance received. Unsupported duplicate policy {0}.", context.StudyLocation.ServerPartition.DuplicateSopPolicyEnum); result.SetError(DicomStatuses.DuplicateSOPInstance, failureMessage); return result; } } return result; }
public override bool OnReceiveRequest(DicomServer server, ServerAssociationParameters association, byte presentationId, DicomMessage message) { Platform.Log(LogLevel.Info, "Received request,the message is {0}!!!", message.CommandField); //The following part is added for some devices won't contain the SpecificCharacterSet DicomTag. //The may introduce troubles when decoding the characters. //If there's SpecificCharacterSet DicomTag in the image, do nothing //If there's no SpecificCharacterSet DicomTag in the image, the configured DefaultSCS for the device will be added. //If there's no SpecificCharacterSet DicomTag in the image and no configured DefaultSCS, ISO_IR 100 will be used. if (string.IsNullOrEmpty(message.DataSet.SpecificCharacterSet)) { if (string.IsNullOrEmpty(Device.DefaultSCS)) { sDefaultSCS = "ISO_IR 100"; } else { sDefaultSCS = Device.DefaultSCS; } message.DataSet[DicomTags.SpecificCharacterSet].SetStringValue(sDefaultSCS); message.DataSet.SpecificCharacterSet = sDefaultSCS; } try { var context = new SopInstanceImporterContext( String.Format("{0}_{1}", association.CallingAE, association.TimeStamp.ToString("yyyyMMddhhmmss")), association.CallingAE, association.CalledAE); if (Device != null && Device.DeviceTypeEnum.Equals(DeviceTypeEnum.PrimaryPacs)) { context.DuplicateProcessing = DuplicateProcessingEnum.OverwriteSopAndUpdateDatabase; } var importer = new SopInstanceImporter(context); DicomProcessingResult result = importer.Import(message); if (result.Successful) { if (!String.IsNullOrEmpty(result.AccessionNumber)) { ///if the accession number is fresh, write the accession number to RIS DB. This is for Dalian Yiwei if (strAcsNbr != result.AccessionNumber) { strAcsNbr = result.AccessionNumber; /// Platform.Log(LogLevel.Info, "The AccessionNumber of this received SOP Instance is:{0}", result.AccessionNumber); // RIS4PACS.RISInterface ri = new RIS4PACS.RISInterface(); // ri.SetImageArrive(result.AccessionNumber); try { Thread thread = new Thread(new ParameterizedThreadStart(UpdateRIS)); thread.Start((object)strAcsNbr); // RIS4PACS.RISInterface ri = new RIS4PACS.RISInterface(); // ri.SetImageArrive(result.AccessionNumber); } catch { Platform.Log(LogLevel.Info, "RIS4PACS database update failure."); } } Platform.Log(LogLevel.Info, "Received SOP Instance {0} from {1} to {2} (A#:{3} StudyUid:{4} )", result.SopInstanceUid, association.CallingAE, association.CalledAE, result.AccessionNumber, result.StudyInstanceUid); } else { Platform.Log(LogLevel.Info, "Received SOP Instance {0} from {1} to {2} (StudyUid:{3})", result.SopInstanceUid, association.CallingAE, association.CalledAE, result.StudyInstanceUid); } } else { Platform.Log(LogLevel.Warn, "Failure importing sop: {0}", result.ErrorMessage); } server.SendCStoreResponse(presentationId, message.MessageId, message.AffectedSopInstanceUid, result.DicomStatus); return(true); } catch (DicomDataException ex) { Platform.Log(LogLevel.Error, ex); return(false); // caller will abort the association } catch (Exception ex) { Platform.Log(LogLevel.Error, ex); return(false); // caller will abort the association } }
public DicomProcessingResult Import(DicomMessage dicomMessage) { var result = new DicomProcessingResult() { Successful = true, }; if (dicomMessage.DataSet == null) { result.Successful = false; } DateTime dt = new DateTime(); var patient = new Patient { PatientId = dicomMessage.DataSet[DicomTags.PatientId].GetString(0, string.Empty), PatientName = dicomMessage.DataSet[DicomTags.PatientsName].GetString(0, string.Empty), PatientBirthDate = dicomMessage.DataSet[DicomTags.PatientsBirthDate].GetDateTime(0, dt), IssuerOfPatientId = dicomMessage.DataSet[DicomTags.IssuerOfPatientId].GetString(0, string.Empty), }; var study = new Study() { StudyId = dicomMessage.DataSet[DicomTags.StudyId].GetString(0, string.Empty), StudyUid = dicomMessage.DataSet[DicomTags.StudyInstanceUid].GetString(0, string.Empty), AccessionNumber = dicomMessage.DataSet[DicomTags.AccessionNumber].GetString(0, string.Empty), StudyDate = dicomMessage.DataSet[DicomTags.StudyDate].GetDateTime(0, dt), StudyTime = dicomMessage.DataSet[DicomTags.StudyTime].GetDateTime(0, dt), RefPhysician = dicomMessage.DataSet[DicomTags.ReferringPhysiciansName].GetString(0, string.Empty), StudyDescription = dicomMessage.DataSet[DicomTags.StudyDescription].GetString(0, string.Empty), PatientId = patient.PatientId, PatientName = patient.PatientName, PatientBirthday = patient.PatientBirthDate, PatientAge = dicomMessage.DataSet[DicomTags.PatientsAge].GetString(0, string.Empty), PatientSize = dicomMessage.DataSet[DicomTags.PatientsSize].GetString(0, string.Empty), PatientWeight = dicomMessage.DataSet[DicomTags.PatientsWeight].GetString(0, string.Empty), PatientSex = dicomMessage.DataSet[DicomTags.PatientsSex].GetString(0, string.Empty) }; var series = new Series() { SeriesUid = dicomMessage.DataSet[DicomTags.SeriesInstanceUid].GetString(0, string.Empty), SeriesNumber = dicomMessage.DataSet[DicomTags.SeriesNumber].GetString(0, string.Empty), Modality = dicomMessage.DataSet[DicomTags.Modality].GetString(0, string.Empty), BodyPart = dicomMessage.DataSet[DicomTags.BodyPartExamined].GetString(0, string.Empty), Institution = dicomMessage.DataSet[DicomTags.InstitutionName].GetString(0, string.Empty), StationName = dicomMessage.DataSet[DicomTags.StationName].GetString(0, string.Empty), Department = dicomMessage.DataSet[DicomTags.InstitutionalDepartmentName].GetString(0, string.Empty), PerfPhysician = dicomMessage.DataSet[DicomTags.PerformingPhysiciansName].GetString(0, string.Empty), SeriesDate = dicomMessage.DataSet[DicomTags.SeriesDate].GetDateTime(0, dt), SeriesTime = dicomMessage.DataSet[DicomTags.SeriesTime].GetDateTime(0, dt), SeriesDescription = dicomMessage.DataSet[DicomTags.SeriesDescription].GetString(0, string.Empty), PerformedProcedureStepStartDate = dicomMessage.DataSet[DicomTags.PerformedProcedureStepStartDate].GetDateTime(0, dt), PerformedProcedureStepStartTime = dicomMessage.DataSet[DicomTags.PerformedProcedureStepStartTime].GetDateTime(0, dt), }; var instance = new Instance() { SopInstanceUid = dicomMessage.DataSet[DicomTags.SopInstanceUid].GetString(0, string.Empty), SopClassUid = dicomMessage.DataSet[DicomTags.SopClassUid].GetString(0, string.Empty), InstanceNumber = dicomMessage.DataSet[DicomTags.InstanceNumber].GetString(0, string.Empty), ContentDate = dicomMessage.DataSet[DicomTags.ContentDate].GetDateTime(0, dt), ContentTime = dicomMessage.DataSet[DicomTags.ContentTime].GetDateTime(0, dt) }; if (string.IsNullOrEmpty(study.StudyUid) || string.IsNullOrEmpty(series.SeriesUid) || string.IsNullOrEmpty(instance.SopInstanceUid)) { result.Successful = false; } // Get Patient Db Object using (var context = new PacsContext()) { Patient dbPatient = null; var dbStudy = InsertStudy(context, study, patient, out dbPatient); // Patient and study is exist in db now var dbSeries = InsertSeries(context, series, dbStudy, dbPatient); // insert instance var dbInstance = InsertImage(context, instance, dbSeries, dbStudy, dbPatient); var dbFile = InsertFile(context, dbInstance, dbSeries, dbStudy, dbPatient); var dicomFile = new DicomFile(dicomMessage, dbFile.FilePath); if (!Directory.Exists(Path.GetDirectoryName(dbFile.FilePath))) { Directory.CreateDirectory(Path.GetDirectoryName(dbFile.FilePath)); } dicomFile.Save(); context.SaveChanges(); result.DicomStatus = DicomStatuses.Success; } return(result); }