Esempio n. 1
0
        /// <summary>
        /// Processes the specified <see cref="DicomFile"/> object.
        /// </summary>
        /// <param name="file"></param>
        /// <returns></returns>
        /// <exception cref="TargetStudyInvalidStateException">Thrown when the target study is in invalid state and cannot be updated.</exception>
        public InstancePreProcessingResult Process(DicomFile file)
        {
            Platform.CheckForNullReference(file, "file");

            AutoReconcilerResult preProcessingResult = null;

            // Update the file based on the reconciliation in the past
            IList <StudyHistory> histories = FindReconcileHistories(StorageLocation, file);

            if (histories != null && histories.Count > 0)
            {
                preProcessingResult = ApplyHistories(file, histories);
            }

            if (preProcessingResult != null)
            {
                StringBuilder log = new StringBuilder();
                log.AppendLine(String.Format("AUTO-RECONCILE: {0}. SOP {1}", preProcessingResult.Action, file.MediaStorageSopInstanceUid));
                foreach (UpdateItem change in preProcessingResult.Changes)
                {
                    if (change.NewValue != null && !change.NewValue.Equals(change.OriginalValue))
                    {
                        log.AppendLine(String.Format("\tSet {0}: {1} => {2}", change.Tag, change.OriginalValue, change.NewValue));
                    }
                }
                Platform.Log(LogLevel.Info, log.ToString());
            }
            return(preProcessingResult);
        }
Esempio n. 2
0
        private AutoReconcilerResult ApplyHistories(DicomFile file, IList <StudyHistory> histories)
        {
            Platform.CheckForNullReference(file, "file");
            Platform.CheckForNullReference(histories, "histories");

            AutoReconcilerResult preProcessingResult = null;

            StudyHistory lastHistory = histories[0];
            StudyReconcileDescriptorParser parser    = new StudyReconcileDescriptorParser();
            StudyReconcileDescriptor       changeLog = parser.Parse(lastHistory.ChangeDescription);

            switch (changeLog.Action)
            {
            case StudyReconcileAction.CreateNewStudy:
            case StudyReconcileAction.Merge:
                if (lastHistory.DestStudyStorageKey != null)
                {
                    preProcessingResult = MergeImage(changeLog.Action, file, lastHistory);
                }
                break;

            case StudyReconcileAction.Discard:
                preProcessingResult = new AutoReconcilerResult(StudyReconcileAction.Discard)
                {
                    DiscardImage = true
                };
                break;

            case StudyReconcileAction.ProcessAsIs:
                if (lastHistory.DestStudyStorageKey != null)
                {
                    preProcessingResult = ProcessImageAsIs(file, lastHistory);
                }
                break;

            default:
                throw new NotImplementedException();
            }
            return(preProcessingResult);
        }
Esempio n. 3
0
        private AutoReconcilerResult ProcessImageAsIs(DicomFile file, StudyHistory lastHistory)
        {
            StudyStorage         destinationStudy = StudyStorage.Load(lastHistory.DestStudyStorageKey);
            StudyStorageLocation destStudy;
            AutoReconcilerResult preProcessingResult = new AutoReconcilerResult(StudyReconcileAction.ProcessAsIs);

            //Load the destination.  An exception will be thrown if any issues are encountered.
            FilesystemMonitor.Instance.GetWritableStudyStorageLocation(destinationStudy.ServerPartitionKey,
                                                                       destinationStudy.StudyInstanceUid, StudyRestore.True,
                                                                       StudyCache.True, out destStudy);

            bool belongsToAnotherStudy = !destStudy.Equals(StorageLocation);

            EnsureStudyCanBeUpdated(destStudy);

            if (belongsToAnotherStudy)
            {
                preProcessingResult.Changes = new List <UpdateItem>
                {
                    new UpdateItem(DicomTags.StudyInstanceUid, file.DataSet[DicomTags.StudyInstanceUid].ToString(), destStudy.StudyInstanceUid)
                };

                file.DataSet[DicomTags.StudyInstanceUid].SetStringValue(destStudy.StudyInstanceUid);
                SopInstanceImporterContext importContext = new SopInstanceImporterContext(
                    _contextID,
                    file.SourceApplicationEntityTitle, destStudy.ServerPartition);
                SopInstanceImporter   importer = new SopInstanceImporter(importContext);
                DicomProcessingResult result   = importer.Import(file);

                if (!result.Successful)
                {
                    throw new ApplicationException("Unable to import image to destination study");
                }
            }
            return(preProcessingResult);
        }
Esempio n. 4
0
        private AutoReconcilerResult MergeImage(StudyReconcileAction action, DicomFile file, StudyHistory lastHistory)
        {
            string originalSeriesUid = file.DataSet[DicomTags.SeriesInstanceUid].ToString();
            string originalSopUid = file.DataSet[DicomTags.SopInstanceUid].ToString();
            
            AutoReconcilerResult preProcessingResult = null;
        	StudyStorageLocation destStudy;
            UidMapper uidMapper = null;
        	if (lastHistory.DestStudyStorageKey != null)
            {
                StudyStorage destinationStudy = StudyStorage.Load(lastHistory.DestStudyStorageKey);

				//Load the destination.  An exception will be thrown if any issues are encountered.
				FilesystemMonitor.Instance.GetWritableStudyStorageLocation(destinationStudy.ServerPartitionKey,
																		   destinationStudy.StudyInstanceUid, 
																		   StudyRestore.True, StudyCache.True, 
																		   out destStudy);

                EnsureStudyCanBeUpdated(destStudy);

                bool belongsToAnotherStudy = !destStudy.Equals(StorageLocation);

                ImageUpdateCommandBuilder commandBuilder = new ImageUpdateCommandBuilder();
                IList<BaseImageLevelUpdateCommand> commands = commandBuilder.BuildCommands<StudyMatchingMap>(destStudy);
                if (belongsToAnotherStudy)
                {
                    Platform.Log(LogLevel.Info, "AUTO-RECONCILE: Move SOP {0} to Study {1}, A#: {2}, Patient {3}", originalSopUid, destStudy.StudyInstanceUid, destStudy.Study.AccessionNumber, destStudy.Study.PatientsName);

                    // Load the Uid Map, either from cache or from disk
                    if (!_uidMapCache.TryGetValue(destStudy.Key, out uidMapper))
                    {
                        UidMapXml mapXml = new UidMapXml();
                        mapXml.Load(destStudy);
                        uidMapper = new UidMapper(mapXml);

                        _uidMapCache.Add(destStudy.Key, uidMapper);
                    }

                    try
                    {
                        commands.Add(GetUidMappingCommand(StorageLocation, destStudy, uidMapper, originalSopUid, originalSeriesUid));
                    }
                    catch (InstanceAlreadyExistsException ex)
                    {
                        Platform.Log(LogLevel.Info, "An instance already exists with the SOP Instance Uid {0}", ex.SopInstanceUid);
                        preProcessingResult = new AutoReconcilerResult(StudyReconcileAction.Discard) { DiscardImage = true };

                        return preProcessingResult;
                    }
                }


                preProcessingResult = new AutoReconcilerResult(action) { Changes = GetUpdateList(file, commands) };

                UpdateImage(file, commands);

                // First, must update the map
                if (uidMapper != null && uidMapper.Dirty)
                {
                    UpdateUidMap(destStudy, uidMapper);
                }

                if (belongsToAnotherStudy)
                {
                    SopInstanceImporterContext importContext = new SopInstanceImporterContext(_contextID, file.SourceApplicationEntityTitle, destStudy.ServerPartition);
                    SopInstanceImporter importer = new SopInstanceImporter(importContext);
                    DicomProcessingResult result = importer.Import(file);

                    if (!result.Successful)
                    {
                        throw new ApplicationException(result.ErrorMessage);
                    }
                }


            }
            return preProcessingResult;
        }
Esempio n. 5
0
        private AutoReconcilerResult ProcessImageAsIs(DicomFile file, StudyHistory lastHistory)
        {
            StudyStorage destinationStudy = StudyStorage.Load(lastHistory.DestStudyStorageKey);
        	StudyStorageLocation destStudy;
            AutoReconcilerResult preProcessingResult = new AutoReconcilerResult(StudyReconcileAction.ProcessAsIs);

			//Load the destination.  An exception will be thrown if any issues are encountered.
        	FilesystemMonitor.Instance.GetWritableStudyStorageLocation(destinationStudy.ServerPartitionKey,
        	                                                           destinationStudy.StudyInstanceUid, StudyRestore.True,
        	                                                           StudyCache.True, out destStudy);

            bool belongsToAnotherStudy = !destStudy.Equals(StorageLocation);

            EnsureStudyCanBeUpdated(destStudy);

            if (belongsToAnotherStudy)
            {
                preProcessingResult.Changes = new List<UpdateItem>
                                                  {
                                                      new UpdateItem(DicomTags.StudyInstanceUid, file.DataSet[DicomTags.StudyInstanceUid].ToString(), destStudy.StudyInstanceUid)
                                                  };

                file.DataSet[DicomTags.StudyInstanceUid].SetStringValue(destStudy.StudyInstanceUid);
                SopInstanceImporterContext importContext = new SopInstanceImporterContext(
                    _contextID,
                    file.SourceApplicationEntityTitle, destStudy.ServerPartition);
                SopInstanceImporter importer = new SopInstanceImporter(importContext);
                DicomProcessingResult result = importer.Import(file);

                if (!result.Successful)
                {
                    throw new ApplicationException("Unable to import image to destination study");
                }
            }
            return preProcessingResult;
        }
Esempio n. 6
0
        private AutoReconcilerResult ApplyHistories(DicomFile file, IList<StudyHistory> histories)
        {
            Platform.CheckForNullReference(file, "file");
            Platform.CheckForNullReference(histories, "histories");

            AutoReconcilerResult preProcessingResult = null;

            StudyHistory lastHistory = histories[0];
            StudyReconcileDescriptorParser parser = new StudyReconcileDescriptorParser();
            StudyReconcileDescriptor changeLog = parser.Parse(lastHistory.ChangeDescription);

            switch (changeLog.Action)
            {
                case StudyReconcileAction.CreateNewStudy:
                case StudyReconcileAction.Merge:
                    if (lastHistory.DestStudyStorageKey != null)
                        preProcessingResult = MergeImage(changeLog.Action, file, lastHistory);
                    break;

                case StudyReconcileAction.Discard:
                    preProcessingResult = new AutoReconcilerResult(StudyReconcileAction.Discard) { DiscardImage = true };
                    break;

                case StudyReconcileAction.ProcessAsIs:
                    if (lastHistory.DestStudyStorageKey != null)
                    {
                        preProcessingResult = ProcessImageAsIs(file, lastHistory);
                    }
                    break;

                default:
                    throw new NotImplementedException();
            }
            return preProcessingResult;
        }
Esempio n. 7
0
        private AutoReconcilerResult MergeImage(StudyReconcileAction action, DicomFile file, StudyHistory lastHistory)
        {
            string originalSeriesUid = file.DataSet[DicomTags.SeriesInstanceUid].ToString();
            string originalSopUid    = file.DataSet[DicomTags.SopInstanceUid].ToString();

            AutoReconcilerResult preProcessingResult = null;
            StudyStorageLocation destStudy;
            UidMapper            uidMapper = null;

            if (lastHistory.DestStudyStorageKey != null)
            {
                StudyStorage destinationStudy = StudyStorage.Load(lastHistory.DestStudyStorageKey);

                //Load the destination.  An exception will be thrown if any issues are encountered.
                FilesystemMonitor.Instance.GetWritableStudyStorageLocation(destinationStudy.ServerPartitionKey,
                                                                           destinationStudy.StudyInstanceUid,
                                                                           StudyRestore.True, StudyCache.True,
                                                                           out destStudy);

                EnsureStudyCanBeUpdated(destStudy);

                bool belongsToAnotherStudy = !destStudy.Equals(StorageLocation);

                ImageUpdateCommandBuilder           commandBuilder = new ImageUpdateCommandBuilder();
                IList <BaseImageLevelUpdateCommand> commands       = commandBuilder.BuildCommands <StudyMatchingMap>(destStudy);
                if (belongsToAnotherStudy)
                {
                    Platform.Log(LogLevel.Info, "AUTO-RECONCILE: Move SOP {0} to Study {1}, A#: {2}, Patient {3}", originalSopUid, destStudy.StudyInstanceUid, destStudy.Study.AccessionNumber, destStudy.Study.PatientsName);

                    // Load the Uid Map, either from cache or from disk
                    if (!_uidMapCache.TryGetValue(destStudy.Key, out uidMapper))
                    {
                        UidMapXml mapXml = new UidMapXml();
                        mapXml.Load(destStudy);
                        uidMapper = new UidMapper(mapXml);

                        _uidMapCache.Add(destStudy.Key, uidMapper);
                    }

                    try
                    {
                        commands.Add(GetUidMappingCommand(StorageLocation, destStudy, uidMapper, originalSopUid, originalSeriesUid));
                    }
                    catch (InstanceAlreadyExistsException ex)
                    {
                        Platform.Log(LogLevel.Info, "An instance already exists with the SOP Instance Uid {0}", ex.SopInstanceUid);
                        preProcessingResult = new AutoReconcilerResult(StudyReconcileAction.Discard)
                        {
                            DiscardImage = true
                        };

                        return(preProcessingResult);
                    }
                }


                preProcessingResult = new AutoReconcilerResult(action)
                {
                    Changes = GetUpdateList(file, commands)
                };

                UpdateImage(file, commands);

                // First, must update the map
                if (uidMapper != null && uidMapper.Dirty)
                {
                    UpdateUidMap(destStudy, uidMapper);
                }

                if (belongsToAnotherStudy)
                {
                    SopInstanceImporterContext importContext = new SopInstanceImporterContext(_contextID, file.SourceApplicationEntityTitle, destStudy.ServerPartition);
                    SopInstanceImporter        importer      = new SopInstanceImporter(importContext);
                    DicomProcessingResult      result        = importer.Import(file);

                    if (!result.Successful)
                    {
                        throw new ApplicationException(result.ErrorMessage);
                    }
                }
            }
            return(preProcessingResult);
        }