/// <summary> /// Constructs a new <see cref="SopInstanceNode"/> using the given <see cref="DicomFile"/> as a template. /// </summary> /// <param name="sourceDicomFile">The <see cref="DicomFile"/> from which to initialize this node.</param> public SopInstanceNode(DicomMessageBase sourceDicomFile) { _dicomFile = new DicomFile("", sourceDicomFile.MetaInfo.Copy(), sourceDicomFile.DataSet.Copy()); _instanceUid = sourceDicomFile.DataSet[DicomTags.SopInstanceUid].GetString(0, ""); if (_instanceUid == "") _instanceUid = StudyBuilder.NewUid(); }
public DicomCompressCommand(DicomMessageBase file, TransferSyntax syntax, IDicomCodec codec, DicomCodecParameters parms) : base("DICOM Compress Command", true) { _file = file; _syntax = syntax; _codec = codec; _parms = parms; }
public DicomCompressCommand(DicomMessageBase file, XmlDocument parms, bool failOnCodecException) : base("DICOM Compress Command", true) { _file = file; _failOnCodecException = failOnCodecException; XmlElement element = parms.DocumentElement; string syntax = element.Attributes["syntax"].Value; _syntax = TransferSyntax.GetTransferSyntax(syntax); if (_syntax == null) { string failureDescription = String.Format("Invalid transfer syntax in compression command: {0}", element.Attributes["syntax"].Value); Platform.Log(LogLevel.Error, "Error with input syntax: {0}", failureDescription); throw new DicomCodecException(failureDescription); } IDicomCodecFactory[] codecs = DicomCodecRegistry.GetCodecFactories(); IDicomCodecFactory theCodecFactory = null; foreach (IDicomCodecFactory codec in codecs) if (codec.CodecTransferSyntax.Equals(_syntax)) { theCodecFactory = codec; break; } if (theCodecFactory == null) { string failureDescription = String.Format("Unable to find codec for compression: {0}", _syntax.Name); Platform.Log(LogLevel.Error, "Error with compression input parameters: {0}", failureDescription); throw new DicomCodecException(failureDescription); } _codec = theCodecFactory.GetDicomCodec(); _parms = theCodecFactory.GetCodecParameters(parms); }
/// <summary> /// Imports the specified <see cref="DicomMessageBase"/> object into the system. /// The object will be inserted into the <see cref="WorkItem"/> for processing /// </summary> /// <param name="message">The DICOM object to be imported.</param> /// <param name="badFileBehavior"> </param> /// <param name="fileImportBehaviour"> </param> /// <returns>An instance of <see cref="DicomProcessingResult"/> that describes the result of the processing.</returns> /// <exception cref="DicomDataException">Thrown when the DICOM object contains invalid data</exception> public DicomProcessingResult Import(DicomMessageBase message, BadFileBehaviourEnum badFileBehavior, FileImportBehaviourEnum fileImportBehaviour) { Platform.CheckForNullReference(message, "message"); String studyInstanceUid = message.DataSet[DicomTags.StudyInstanceUid].GetString(0, string.Empty); String seriesInstanceUid = message.DataSet[DicomTags.SeriesInstanceUid].GetString(0, string.Empty); String sopInstanceUid = message.DataSet[DicomTags.SopInstanceUid].GetString(0, string.Empty); String accessionNumber = message.DataSet[DicomTags.AccessionNumber].GetString(0, string.Empty); String patientsName = message.DataSet[DicomTags.PatientsName].GetString(0, string.Empty); String patientId = message.DataSet[DicomTags.PatientId].GetString(0, string.Empty); var result = new DicomProcessingResult { Successful = true, StudyInstanceUid = studyInstanceUid, SeriesInstanceUid = seriesInstanceUid, SopInstanceUid = sopInstanceUid, AccessionNumber = accessionNumber, PatientsName = patientsName, PatientId = patientId, }; WorkItem workItem; lock (_context.StudyWorkItemsSyncLock) _context.StudyWorkItems.TryGetValue(studyInstanceUid, out workItem); try { Validate(message); } catch (DicomDataException e) { result.SetError(DicomStatuses.ProcessingFailure, e.Message); AuditFailure(result); return result; } if (workItem != null) { if (workItem.Status == WorkItemStatusEnum.Deleted || workItem.Status == WorkItemStatusEnum.DeleteInProgress || workItem.Status == WorkItemStatusEnum.Canceled || workItem.Status == WorkItemStatusEnum.Canceling) { // TODO Marmot (CR June 2012): not DicomStatuses.Cancel? result.SetError(DicomStatuses.StorageStorageOutOfResources, "Canceled by user"); AuditFailure(result); return result; } } if (LocalStorageMonitor.IsMaxUsedSpaceExceeded) { //The input to this method is a VALID DICOM file, and we know we should have stored it if it weren't for //the fact that we're out of disk space. So, we insert the work item UID anyway, knowing that it'll cause //the work item to fail. In fact, that's why we're doing it. result.SetError(DicomStatuses.StorageStorageOutOfResources, string.Format("Import failed, disk space usage exceeded")); InsertFailedWorkItemUid(workItem, message, result); _context.FatalError = true; AuditFailure(result); return result; } Process(message, fileImportBehaviour, workItem, result); if (result.DicomStatus != DicomStatuses.Success) { if (result.RetrySuggested) { Platform.Log(LogLevel.Warn, "Failure importing file with retry suggested, retrying Import of file: {0}", sopInstanceUid); Process(message, fileImportBehaviour, workItem, result); } } if (result.DicomStatus != DicomStatuses.Success) { //The input to this method is a VALID DICOM file, and we know we should have stored it if it weren't for //the fact that we're out of disk space. So, we insert the work item UID anyway, knowing that it'll cause //the work item to fail. In fact, that's why we're doing it. InsertFailedWorkItemUid(workItem, message, result); AuditFailure(result); } return result; }
/// <summary> /// Abstract method for creating a <see cref="ProcessStudyRequest"/> object for the given DICOM message. /// </summary> /// <param name="message"></param> /// <returns></returns> public abstract ProcessStudyRequest CreateRequest(DicomMessageBase message);
public XSopDataSource(DicomMessageBase sourceMessage) : base(sourceMessage) { }
private DicomProcessingResult HandleDuplicateFile(string sopInstanceUid, StudyStorageLocation studyLocation, ServerCommandProcessor commandProcessor, DicomMessageBase message, string sourceFilename, StudyProcessWorkQueueData data) { Study study = studyLocation.Study ?? studyLocation.LoadStudy(ServerExecutionContext.Current.PersistenceContext); if (study != null) { Platform.Log(LogLevel.Info, "Received duplicate SOP {0} (A#:{1} StudyUid:{2} Patient: {3} ID:{4})", sopInstanceUid, study.AccessionNumber, study.StudyInstanceUid, study.PatientsName, study.PatientId); } else { Platform.Log(LogLevel.Info, "Received duplicate SOP {0} (StudyUid:{1}). Existing files haven't been processed.", sopInstanceUid, studyLocation.StudyInstanceUid); } var sopProcessingContext = new SopInstanceProcessorContext(commandProcessor, studyLocation, _context.ContextID, _context.Request) { DuplicateProcessing = _context.DuplicateProcessing }; DicomProcessingResult result = DuplicateSopProcessorHelper.Process(sopProcessingContext, message, data, sourceFilename); return(result); }
private void PopulateStudy(DicomMessageBase response, IEnumerable <DicomTag> tagList, IStudyData row) { DicomDataset dataSet = response.DataSet; dataSet[DicomTags.RetrieveAeTitle].SetStringValue(Partition.AeTitle); dataSet[DicomTags.InstanceAvailability].SetStringValue("ONLINE"); var characterSet = GetPreferredCharacterSet(); if (!string.IsNullOrEmpty(characterSet)) { dataSet[DicomTags.SpecificCharacterSet].SetStringValue(characterSet); dataSet.SpecificCharacterSet = characterSet; } foreach (DicomTag tag in tagList) { try { switch (tag.TagValue) { case DicomTags.StudyInstanceUid: dataSet[DicomTags.StudyInstanceUid].SetStringValue(row.StudyUid); break; case DicomTags.PatientsName: dataSet[DicomTags.PatientsName].SetStringValue(row.PatientName); break; case DicomTags.PatientId: dataSet[DicomTags.PatientId].SetStringValue(row.PatientId); break; case DicomTags.PatientsBirthDate: dataSet[DicomTags.PatientsBirthDate].SetDateTime(0, row.PatientBirthday); break; case DicomTags.PatientsAge: dataSet[DicomTags.PatientsAge].SetStringValue(row.PatientAge); break; case DicomTags.PatientsSex: dataSet[DicomTags.PatientsSex].SetStringValue(row.PatientSex); break; case DicomTags.StudyDate: dataSet[DicomTags.StudyDate].SetDateTime(0, row.StudyDate); break; case DicomTags.StudyTime: dataSet[DicomTags.StudyTime].SetDateTime(0, row.StudyTime); break; case DicomTags.AccessionNumber: dataSet[DicomTags.AccessionNumber].SetStringValue(row.AccessionNumber); break; case DicomTags.StudyId: dataSet[DicomTags.StudyId].SetStringValue(row.StudyId); break; case DicomTags.StudyDescription: dataSet[DicomTags.StudyDescription].SetStringValue(row.StudyDescription); break; case DicomTags.ReferringPhysiciansName: dataSet[DicomTags.ReferringPhysiciansName].SetStringValue(row.RefPhysician); break; case DicomTags.NumberOfStudyRelatedSeries: dataSet[DicomTags.NumberOfStudyRelatedSeries].AppendInt32(row.NumberOfRelatedSeries); break; case DicomTags.NumberOfStudyRelatedInstances: dataSet[DicomTags.NumberOfStudyRelatedInstances].AppendInt32( row.NumberOfRelatedImage); break; case DicomTags.ModalitiesInStudy: //LoadModalitiesInStudy(read, response, row.Key); break; case DicomTags.QueryRetrieveLevel: dataSet[DicomTags.QueryRetrieveLevel].SetStringValue("STUDY"); break; // Meta tags that should have not been in the RQ, but we've already set case DicomTags.RetrieveAeTitle: case DicomTags.InstanceAvailability: case DicomTags.SpecificCharacterSet: break; default: if (!tag.IsPrivate) { dataSet[tag].SetNullValue(); } break; } } catch (Exception e) { Log.Logger.Warn("Unexpected error setting tag {0} in C-FIND-RSP", dataSet[tag].Tag.ToString()); if (!tag.IsPrivate) { dataSet[tag].SetNullValue(); } } } }
public UpdateWorkQueueCommand(DicomMessageBase message, StudyStorageLocation location, bool duplicate) : this(message, location, duplicate, null, null) { }
/// <summary> /// Constructs a new <see cref="DicomMessageSopDataSource"/>. /// </summary> /// <param name="sourceMessage">The source <see cref="DicomMessageBase"/> which provides all the SOP instance data.</param> protected DicomMessageSopDataSource(DicomMessageBase sourceMessage) { _dummy = new DicomAttributeCollection(); SetSourceMessage(sourceMessage); }
public ServerFilesystemInfo SelectFilesystem(DicomMessageBase msg) { return(SelectFilesystem()); }
/// <summary> /// Inserts a <see cref="DicomMessageBase"/> into the set. /// </summary> /// <param name="message"></param> public void InsertFile(DicomMessageBase message) { StudyInfo.Add(message); }
private static ReconcileStudyQueueDescription GetQueueEntryDescription(StudyStorageLocation existingStorage, DicomMessageBase file) { ReconcileStudyQueueDescription desc = new ReconcileStudyQueueDescription { ExistingPatientId = existingStorage.Study.PatientId, ExistingPatientName = existingStorage.Study.PatientsName, ExistingAccessionNumber = existingStorage.Study.AccessionNumber, ConflictingPatientName = file.DataSet[DicomTags.PatientsName].GetString(0, String.Empty), ConflictingPatientId = file.DataSet[DicomTags.PatientId].GetString(0, String.Empty), ConflictingAccessionNumber = file.DataSet[DicomTags.AccessionNumber].GetString(0, String.Empty) }; return(desc); }
private static IList <StudyHistory> FindReconcileHistories(StudyStorageLocation storageLocation, DicomMessageBase file) { ImageSetDescriptor fileDesc = new ImageSetDescriptor(file.DataSet); List <StudyHistory> studyHistoryList = new List <StudyHistory>( ServerHelper.FindStudyHistories(storageLocation.StudyStorage, new[] { StudyHistoryTypeEnum.StudyReconciled })); IList <StudyHistory> reconcileHistories = studyHistoryList.FindAll( delegate(StudyHistory item) { ImageSetDescriptor desc = XmlUtils.Deserialize <ImageSetDescriptor>(item.StudyData.DocumentElement); return(desc.Equals(fileDesc)); }); if (reconcileHistories.Count == 0) { // no history found in cache... reload the list and search again one more time studyHistoryList = new List <StudyHistory>( ServerHelper.FindStudyHistories(storageLocation.StudyStorage, new[] { StudyHistoryTypeEnum.StudyReconciled })); reconcileHistories = studyHistoryList.FindAll( delegate(StudyHistory item) { ImageSetDescriptor desc = XmlUtils.Deserialize <ImageSetDescriptor>(item.StudyData.DocumentElement); return(desc.Equals(fileDesc)); }); } return(reconcileHistories); }
private void Process(DicomMessageBase message, FileImportBehaviourEnum fileImportBehaviour, WorkItem workItem, DicomProcessingResult result) { result.Initialize(); // Use the command processor for rollback capabilities. using (var commandProcessor = new ViewerCommandProcessor(String.Format("Processing Sop Instance {0}", result.SopInstanceUid))) { try { var studyLocation = new StudyLocation(result.StudyInstanceUid); String destinationFile = studyLocation.GetSopInstancePath(result.SeriesInstanceUid, result.SopInstanceUid); DicomFile file = ConvertToDicomFile(message, destinationFile, _context.SourceAE); // Create the Study Folder, if need be commandProcessor.AddCommand(new CreateDirectoryCommand(studyLocation.StudyFolder)); bool duplicateFile = false; string dupName = null; if (File.Exists(destinationFile)) { // TODO (CR Jun 2012): Shouldn't the commands themselves make this decision at the time // the file is being saved? Otherwise, what happens if the same SOP were being saved 2x simultaneously. // I know the odds are low, but just pointing it out. duplicateFile = true; dupName = Guid.NewGuid().ToString() + ".dcm"; destinationFile = Path.Combine(Path.GetDirectoryName(destinationFile), dupName); } if (fileImportBehaviour == FileImportBehaviourEnum.Move) { commandProcessor.AddCommand(new RenameFileCommand(file.Filename, destinationFile, true)); } else if (fileImportBehaviour == FileImportBehaviourEnum.Copy) { commandProcessor.AddCommand(new CopyFileCommand(file.Filename, destinationFile, true)); } else if (fileImportBehaviour == FileImportBehaviourEnum.Save) { commandProcessor.AddCommand(new SaveDicomFileCommand(destinationFile, file, true)); } var insertWorkItemCommand = CreateWorkItemCommand(workItem, result, file, duplicateFile, dupName); commandProcessor.AddCommand(insertWorkItemCommand); if (commandProcessor.Execute()) { result.DicomStatus = DicomStatuses.Success; IncrementTotalFiles(insertWorkItemCommand, result.StudyInstanceUid); } else { if (commandProcessor.FailureException is ChangeConflictException || commandProcessor.FailureException is SqlCeLockTimeoutException) result.RetrySuggested = true; // Change conflict or lock timeout may work if we just retry Platform.Log(LogLevel.Warn, "Failure Importing file: {0}", file.Filename); string failureMessage = String.Format( "Failure processing message: {0}. Sending failure status.", commandProcessor.FailureReason); result.SetError(DicomStatuses.ProcessingFailure, failureMessage); // processor already rolled back } } catch (Exception e) { Platform.Log(LogLevel.Error, e, "Unexpected exception when {0}. Rolling back operation.", commandProcessor.Description); commandProcessor.Rollback(); result.SetError(result.DicomStatus ?? DicomStatuses.ProcessingFailure, e.Message); } } }
private InsertWorkItemCommand CreateWorkItemCommand(WorkItem workItem, DicomProcessingResult result, DicomMessageBase file, bool duplicateFile, string duplicateFileName) { InsertWorkItemCommand insertWorkItemCommand; if (duplicateFile) { insertWorkItemCommand = workItem != null ? new InsertWorkItemCommand(workItem, result.StudyInstanceUid, result.SeriesInstanceUid, result.SopInstanceUid, duplicateFileName) : new InsertWorkItemCommand(_context.CreateRequest(file), _context.CreateProgress(), result.StudyInstanceUid, result.SeriesInstanceUid, result.SopInstanceUid, duplicateFileName); } else { insertWorkItemCommand = workItem != null ? new InsertWorkItemCommand(workItem, result.StudyInstanceUid, result.SeriesInstanceUid, result.SopInstanceUid) : new InsertWorkItemCommand(_context.CreateRequest(file), _context.CreateProgress(), result.StudyInstanceUid, result.SeriesInstanceUid, result.SopInstanceUid); } insertWorkItemCommand.ExpirationDelaySeconds = _context.ExpirationDelaySeconds; return insertWorkItemCommand; }
private void SetSourceMessage(DicomMessageBase sourceMessage) { _sourceMessage = sourceMessage; _loaded = !_sourceMessage.DataSet.IsEmpty(); }
private void PopulatePatient(DicomMessageBase response, IEnumerable <DicomTag> tagList, IPatientData row) { DicomDataset dataSet = response.DataSet; dataSet[DicomTags.RetrieveAeTitle].SetStringValue(Partition.AeTitle); var characterSet = GetPreferredCharacterSet(); if (!string.IsNullOrEmpty(characterSet)) { dataSet[DicomTags.SpecificCharacterSet].SetStringValue(characterSet); dataSet.SpecificCharacterSet = characterSet; } IList <IStudyData> relatedStudies = row.LoadRelatedStudies(); IStudyData studyData = null; if (relatedStudies.Count > 0) { studyData = relatedStudies.First(); } foreach (DicomTag tag in tagList) { try { switch (tag.TagValue) { case DicomTags.PatientsName: dataSet[DicomTags.PatientsName].SetStringValue(row.PatientName); break; case DicomTags.PatientId: dataSet[DicomTags.PatientId].SetStringValue(row.PatientId); break; case DicomTags.IssuerOfPatientId: dataSet[DicomTags.IssuerOfPatientId].SetStringValue(row.IssuerOfPatientId); break; case DicomTags.NumberOfPatientRelatedStudies: dataSet[DicomTags.NumberOfPatientRelatedStudies].AppendInt32(row.NumberOfRelatedStudies); break; case DicomTags.NumberOfPatientRelatedSeries: dataSet[DicomTags.NumberOfPatientRelatedSeries].AppendInt32(row.NumberOfRelatedSeries); break; case DicomTags.NumberOfPatientRelatedInstances: dataSet[DicomTags.NumberOfPatientRelatedInstances].AppendInt32( row.NumberOfRelatedInstances); break; case DicomTags.QueryRetrieveLevel: dataSet[DicomTags.QueryRetrieveLevel].SetStringValue("PATIENT"); break; case DicomTags.PatientsSex: if (studyData == null) { dataSet[DicomTags.PatientsSex].SetNullValue(); } else { dataSet[DicomTags.PatientsSex].SetStringValue(studyData.PatientSex); } break; case DicomTags.PatientsBirthDate: if (studyData == null) { dataSet[DicomTags.PatientsBirthDate].SetNullValue(); } else { dataSet[DicomTags.PatientsBirthDate].SetDateTime(0, studyData.PatientBirthday); } break; // Meta tags that should have not been in the RQ, but we've already set case DicomTags.RetrieveAeTitle: case DicomTags.InstanceAvailability: case DicomTags.SpecificCharacterSet: break; default: if (!tag.IsPrivate) { dataSet[tag].SetNullValue(); } break; } } catch (Exception e) { Log.Logger.Error(e, "Unexpected error setting tag {0} in C-FIND-RSP", dataSet[tag].Tag.ToString()); if (!tag.IsPrivate) { dataSet[tag].SetNullValue(); } } } }
/// <summary> /// Imports the specified <see cref="DicomMessageBase"/> object into the system. /// The object will be inserted into the <see cref="WorkQueue"/> for processing and /// if it's a duplicate, proper checks will be done and depending on the policy, it will be /// ignored, rejected or inserted into the <see cref="StudyIntegrityQueue"/> for manual intervention. /// </summary> /// <param name="message">The DICOM object to be imported.</param> /// <returns>An instance of <see cref="DicomProcessingResult"/> that describes the result of the processing.</returns> /// <exception cref="DicomDataException">Thrown when the DICOM object contains invalid data</exception> public DicomProcessingResult Import(DicomMessageBase message) { Platform.CheckForNullReference(message, "message"); String studyInstanceUid = message.DataSet[DicomTags.StudyInstanceUid].GetString(0, string.Empty); String seriesInstanceUid = message.DataSet[DicomTags.SeriesInstanceUid].GetString(0, string.Empty); String sopInstanceUid = message.DataSet[DicomTags.SopInstanceUid].GetString(0, string.Empty); String accessionNumber = message.DataSet[DicomTags.AccessionNumber].GetString(0, string.Empty); String patientsName = message.DataSet[DicomTags.PatientsName].GetString(0, string.Empty); DicomFile file = null; // Scrub the name for invalid characters. string newName = XmlUtils.XmlCharacterScrub(patientsName); if (!newName.Equals(patientsName)) { message.DataSet[DicomTags.PatientsName].SetStringValue(newName); } var result = new DicomProcessingResult { Successful = true, StudyInstanceUid = studyInstanceUid, SeriesInstanceUid = seriesInstanceUid, SopInstanceUid = sopInstanceUid, AccessionNumber = accessionNumber }; try { Validate(message); } catch (DicomDataException e) { result.SetError(DicomStatuses.ProcessingFailure, e.Message); return(result); } // Use the command processor for rollback capabilities. using (var commandProcessor = new ServerCommandProcessor(String.Format("Processing Sop Instance {0}", sopInstanceUid))) { try { string failureMessage; StudyStorageLocation studyLocation = GetWritableOnlineStorage(message); // GetWritableOnlineStorage should throw an exception if the study location cannot be found. Platform.CheckForNullReference(studyLocation, "studyLocation"); if (!studyLocation.QueueStudyStateEnum.Equals(QueueStudyStateEnum.Idle) && (!studyLocation.QueueStudyStateEnum.Equals(QueueStudyStateEnum.ProcessingScheduled))) { failureMessage = String.Format("Study {0} on partition {1} is being processed: {2}, can't accept new images.", studyLocation.StudyInstanceUid, _context.Partition.Description, studyLocation.QueueStudyStateEnum.Description); result.SetError(DicomStatuses.StorageStorageOutOfResources, failureMessage); return(result); } if (studyLocation.StudyStatusEnum.Equals(StudyStatusEnum.OnlineLossy)) { if (studyLocation.IsLatestArchiveLossless) { result.DicomStatus = DicomStatuses.StorageStorageOutOfResources; failureMessage = String.Format("Study {0} on partition {1} can't accept new images due to lossy compression of the study. Restoring study.", studyLocation.StudyInstanceUid, _context.Partition.Description); Platform.Log(LogLevel.Error, failureMessage); if (ServerHelper.InsertRestoreRequest(studyLocation) == null) { Platform.Log(LogLevel.Warn, "Unable to insert Restore Request for Study"); } result.SetError(DicomStatuses.StorageStorageOutOfResources, failureMessage); result.RestoreRequested = true; return(result); } } String path = studyLocation.FilesystemPath; const string extension = null; String finalDest = studyLocation.GetSopInstancePath(seriesInstanceUid, sopInstanceUid); file = ConvertToDicomFile(message, finalDest, _context.SourceAE); if (HasUnprocessedCopy(studyLocation.Key, seriesInstanceUid, sopInstanceUid)) { var accept = false; // This is a special case: #10569 // Allow user to revive an orphaned study by reprocessing the files found in the filesystem if (File.Exists(finalDest)) { accept = DuplicatePolicy.IsParitionDuplicatePolicyOverridden(studyLocation); } if (!accept) { failureMessage = string.Format("Another copy of the SOP Instance was received but has not been processed: {0}", sopInstanceUid); result.SetError(DicomStatuses.DuplicateSOPInstance, failureMessage); return(result); } } if (File.Exists(finalDest)) { result = HandleDuplicate(sopInstanceUid, studyLocation, commandProcessor, file); if (!result.Successful) { return(result); } } else { HandleNonDuplicate(seriesInstanceUid, sopInstanceUid, studyLocation, commandProcessor, file, path, false, extension); } if (commandProcessor.Execute()) { result.DicomStatus = DicomStatuses.Success; } else { failureMessage = String.Format("Failure processing message: {0}. Sending failure status.", commandProcessor.FailureReason); result.SetError(DicomStatuses.ProcessingFailure, failureMessage); // processor already rolled back return(result); } } catch (NoWritableFilesystemException) { String failureMessage = String.Format("Unable to process image, no writable filesystem found for Study UID {0}.", sopInstanceUid); commandProcessor.Rollback(); result.SetError(DicomStatuses.StorageStorageOutOfResources, failureMessage); } catch (StudyIsNearlineException e) { String failureMessage = e.RestoreRequested ? String.Format("{0}. Restore has been requested.", e.Message) : e.Message; Platform.Log(LogLevel.Error, failureMessage); commandProcessor.Rollback(); result.SetError(DicomStatuses.ProcessingFailure, failureMessage); } catch (FilesystemNotWritableException) { commandProcessor.Rollback(); string folder; if (!FilesystemMonitor.Instance.GetWriteableIncomingFolder(_context.Partition, out folder)) { String failureMessage = String.Format("Unable to process image, study storage location is missing or not writeable: {0}.", sopInstanceUid); result.SetError(DicomStatuses.StorageStorageOutOfResources, failureMessage); return(result); } if (file == null) { file = ConvertToDicomFile(message, string.Empty, _context.SourceAE); } if (!SaveToFolder(folder, sopInstanceUid, studyInstanceUid, file)) { String failureMessage = String.Format("Study storage location not writeable and no writeable incoming folder: {0}.", sopInstanceUid); result.SetError(DicomStatuses.StorageStorageOutOfResources, failureMessage); return(result); } Platform.Log(LogLevel.Info, "Saved existing SOP without writeable storage location to {0} folder: {1}", FilesystemMonitor.ImportDirectorySuffix, sopInstanceUid); result.DicomStatus = DicomStatuses.Success; return(result); } catch (Exception e) { Platform.Log(LogLevel.Error, e, "Unexpected exception when {0}. Rolling back operation.", commandProcessor.Description); commandProcessor.Rollback(); result.SetError(result.DicomStatus ?? DicomStatuses.ProcessingFailure, e.Message); } } return(result); }
private void PopulateSeries(DicomMessageBase request, DicomMessageBase response, IEnumerable <DicomTag> tagList, ISeriesData row) { DicomDataset dataSet = response.DataSet; dataSet[DicomTags.RetrieveAeTitle].SetStringValue(Partition.AeTitle); dataSet[DicomTags.InstanceAvailability].SetStringValue("ONLINE"); var characterSet = GetPreferredCharacterSet(); if (!string.IsNullOrEmpty(characterSet)) { dataSet[DicomTags.SpecificCharacterSet].SetStringValue(characterSet); dataSet.SpecificCharacterSet = characterSet; } foreach (DicomTag tag in tagList) { try { switch (tag.TagValue) { case DicomTags.PatientId: dataSet[DicomTags.PatientId].SetStringValue(request.DataSet[DicomTags.PatientId].ToString()); break; case DicomTags.StudyInstanceUid: dataSet[DicomTags.StudyInstanceUid].SetStringValue( request.DataSet[DicomTags.StudyInstanceUid].ToString()); break; case DicomTags.SeriesInstanceUid: dataSet[DicomTags.SeriesInstanceUid].SetStringValue(row.SeriesUid); break; case DicomTags.Modality: dataSet[DicomTags.Modality].SetStringValue(row.Modality); break; case DicomTags.SeriesNumber: dataSet[DicomTags.SeriesNumber].SetStringValue(row.SeriesNumber); break; case DicomTags.SeriesDescription: dataSet[DicomTags.SeriesDescription].SetStringValue(row.SeriesDescription); break; case DicomTags.PerformedProcedureStepStartDate: dataSet[DicomTags.PerformedProcedureStepStartDate].SetDateTime(0, row.PerformedProcedureStepStartDate); break; case DicomTags.PerformedProcedureStepStartTime: dataSet[DicomTags.PerformedProcedureStepStartTime].SetDateTime(0, row.PerformedProcedureStepStartTime); break; case DicomTags.NumberOfSeriesRelatedInstances: dataSet[DicomTags.NumberOfSeriesRelatedInstances].AppendInt32(row.NumberOfRelatedImage); break; case DicomTags.RequestAttributesSequence: //LoadRequestAttributes(read, response, row); break; case DicomTags.QueryRetrieveLevel: dataSet[DicomTags.QueryRetrieveLevel].SetStringValue("SERIES"); break; // Meta tags that should have not been in the RQ, but we've already set case DicomTags.RetrieveAeTitle: case DicomTags.InstanceAvailability: case DicomTags.SpecificCharacterSet: break; default: if (!tag.IsPrivate) { dataSet[tag].SetNullValue(); } break; } } catch (Exception e) { Log.Logger.Warn("Unexpected error setting tag {0} in C-FIND-RSP", dataSet[tag].Tag.ToString()); if (!tag.IsPrivate) { dataSet[tag].SetNullValue(); } } } }
private static void Validate(DicomMessageBase message) { DicomSopInstanceValidator validator = new DicomSopInstanceValidator(); validator.Validate(message); }
/// <summary> /// Populate the data from a <see cref="Study"/> entity into a DICOM C-FIND-RSP message. /// </summary> /// <param name="read">The connection to use to read the values.</param> /// <param name="response"></param> /// <param name="tagList"></param> /// <param name="row">The <see cref="Study"/> table to populate the response from.</param> /// <param name="availability">Instance availability string.</param> private void PopulateStudy(IPersistenceContext read, DicomMessageBase response, IEnumerable <uint> tagList, Study row, string availability) { DicomAttributeCollection dataSet = response.DataSet; dataSet[DicomTags.RetrieveAeTitle].SetStringValue(ServerPartitionMonitor.Instance.FindPartition(row.ServerPartitionKey).AeTitle); dataSet[DicomTags.InstanceAvailability].SetStringValue(availability); if (false == String.IsNullOrEmpty(row.SpecificCharacterSet)) { dataSet[DicomTags.SpecificCharacterSet].SetStringValue(row.SpecificCharacterSet); dataSet.SpecificCharacterSet = row.SpecificCharacterSet; // this will ensure the data is encoded using the specified character set } foreach (uint tag in tagList) { try { switch (tag) { case DicomTags.StudyInstanceUid: dataSet[DicomTags.StudyInstanceUid].SetStringValue(row.StudyInstanceUid); break; case DicomTags.PatientsName: dataSet[DicomTags.PatientsName].SetStringValue(row.PatientsName); break; case DicomTags.PatientId: dataSet[DicomTags.PatientId].SetStringValue(row.PatientId); break; case DicomTags.PatientsBirthDate: dataSet[DicomTags.PatientsBirthDate].SetStringValue(row.PatientsBirthDate); break; case DicomTags.PatientsAge: dataSet[DicomTags.PatientsAge].SetStringValue(row.PatientsAge); break; case DicomTags.PatientsSex: dataSet[DicomTags.PatientsSex].SetStringValue(row.PatientsSex); break; case DicomTags.StudyDate: dataSet[DicomTags.StudyDate].SetStringValue(row.StudyDate); break; case DicomTags.StudyTime: dataSet[DicomTags.StudyTime].SetStringValue(row.StudyTime); break; case DicomTags.AccessionNumber: dataSet[DicomTags.AccessionNumber].SetStringValue(row.AccessionNumber); break; case DicomTags.StudyId: dataSet[DicomTags.StudyId].SetStringValue(row.StudyId); break; case DicomTags.StudyDescription: dataSet[DicomTags.StudyDescription].SetStringValue(row.StudyDescription); break; case DicomTags.ReferringPhysiciansName: dataSet[DicomTags.ReferringPhysiciansName].SetStringValue(row.ReferringPhysiciansName); break; case DicomTags.NumberOfStudyRelatedSeries: dataSet[DicomTags.NumberOfStudyRelatedSeries].AppendInt32(row.NumberOfStudyRelatedSeries); break; case DicomTags.NumberOfStudyRelatedInstances: dataSet[DicomTags.NumberOfStudyRelatedInstances].AppendInt32( row.NumberOfStudyRelatedInstances); break; case DicomTags.ModalitiesInStudy: LoadModalitiesInStudy(read, response, row.Key); break; case DicomTags.QueryRetrieveLevel: dataSet[DicomTags.QueryRetrieveLevel].SetStringValue("STUDY"); break; default: dataSet[tag].SetNullValue(); break; // Meta tags that should have not been in the RQ, but we've already set case DicomTags.RetrieveAeTitle: case DicomTags.InstanceAvailability: case DicomTags.SpecificCharacterSet: break; } } catch (Exception e) { Platform.Log(LogLevel.Warn, e, "Unexpected error setting tag {0} in C-FIND-RSP", dataSet[tag].Tag.ToString()); dataSet[tag].SetNullValue(); } } }
private void HandleNonDuplicateFile(string seriesInstanceUid, string sopInstanceUid, StudyStorageLocation studyLocation, ServerCommandProcessor commandProcessor, DicomMessageBase message, string sourcePath, string path, bool dupImage, StudyProcessWorkQueueData data) { commandProcessor.AddCommand(new CreateDirectoryCommand(path)); path = Path.Combine(path, studyLocation.PartitionFolder); commandProcessor.AddCommand(new CreateDirectoryCommand(path)); path = Path.Combine(path, studyLocation.StudyFolder); commandProcessor.AddCommand(new CreateDirectoryCommand(path)); path = Path.Combine(path, studyLocation.StudyInstanceUid); commandProcessor.AddCommand(new CreateDirectoryCommand(path)); path = Path.Combine(path, seriesInstanceUid); commandProcessor.AddCommand(new CreateDirectoryCommand(path)); path = Path.Combine(path, sopInstanceUid); path += ServerPlatform.DicomFileExtension; commandProcessor.AddCommand(new RenameFileCommand(sourcePath, path, true)); WorkQueueUidData uidData = null; if (_context.Request != null && !string.IsNullOrEmpty(_context.Request.OperationToken)) { uidData = new WorkQueueUidData { OperationToken = _context.Request.OperationToken }; } commandProcessor.AddCommand( new UpdateWorkQueueCommand(message, studyLocation, dupImage, data, uidData, _context.Request, _context.Priority)); #region SPECIAL CODE FOR TESTING if (Diagnostics.Settings.SimulateFileCorruption) { commandProcessor.AddCommand(new CorruptDicomFileCommand(path)); } #endregion }