예제 #1
0
        /// <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);
                }
            }
        }
예제 #2
0
        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);
        }
예제 #3
0
파일: CStoreScp.cs 프로젝트: 1059444127/XA
        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
            }
        }
예제 #4
0
        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
            }
        }
예제 #5
0
        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);
            }
        }
예제 #7
0
        /// <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);
        }
예제 #8
0
        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;
		}
예제 #10
0
        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;
        }
예제 #13
0
        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
            }
        }
예제 #14
0
        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);
        }