/// <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); }
private AutoReconcilerResult ApplyHistories(DicomFile file, IList <StudyHistory> histories) { Platform.CheckForNullReference(file, "file"); Platform.CheckForNullReference(histories, "histories"); AutoReconcilerResult preProcessingResult = null; StudyHistory lastHistory = histories[0]; var 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); }
private AutoReconcilerResult ProcessImageAsIs(DicomFile file, StudyHistory lastHistory) { StudyStorage destinationStudy = StudyStorage.Load(lastHistory.DestStudyStorageKey); StudyStorageLocation destStudy; var 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); var importContext = new SopInstanceImporterContext( _contextID, file.SourceApplicationEntityTitle, destStudy.ServerPartition); var importer = new SopInstanceImporter(importContext); DicomProcessingResult result = importer.Import(file); if (!result.Successful) { throw new ApplicationException("Unable to import image to destination study"); } } return(preProcessingResult); }
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; 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. StudyStorageLocation destStudy; FilesystemMonitor.Instance.GetWritableStudyStorageLocation(destinationStudy.ServerPartitionKey, destinationStudy.StudyInstanceUid, StudyRestore.True, StudyCache.True, out destStudy); EnsureStudyCanBeUpdated(destStudy); bool belongsToAnotherStudy = !destStudy.Equals(StorageLocation); var 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)) { var 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) { var importContext = new SopInstanceImporterContext(_contextID, file.SourceApplicationEntityTitle, destStudy.ServerPartition); var importer = new SopInstanceImporter(importContext); DicomProcessingResult result = importer.Import(file); if (!result.Successful) { throw new ApplicationException(result.ErrorMessage); } } } return(preProcessingResult); }