/// <summary> /// Load the values for the sequence <see cref="DicomTags.RequestAttributesSequence"/> /// into a response message for a specific series. /// </summary> /// <param name="read">The connection to use to read the values.</param> /// <param name="response">The message to add the values into.</param> /// <param name="row">The <see cref="Series"/> entity to load the related <see cref="RequestAttributes"/> entity for.</param> private static void LoadRequestAttributes(IPersistenceContext read, DicomMessageBase response, Series row) { var select = read.GetBroker<IRequestAttributesEntityBroker>(); var criteria = new RequestAttributesSelectCriteria(); criteria.SeriesKey.EqualTo(row.GetKey()); IList<RequestAttributes> list = select.Find(criteria); if (list.Count == 0) { response.DataSet[DicomTags.RequestAttributesSequence].SetNullValue(); return; } foreach (RequestAttributes request in list) { var item = new DicomSequenceItem(); item[DicomTags.ScheduledProcedureStepId].SetStringValue(request.ScheduledProcedureStepId); item[DicomTags.RequestedProcedureId].SetStringValue(request.RequestedProcedureId); response.DataSet[DicomTags.RequestAttributesSequence].AddSequenceItem(item); } }
/// <summary> /// Validates the contents in the <see cref="DicomMessageBase"/> object. /// </summary> /// <param name="message"></param> /// <exception cref="DicomDataException"/> is thrown if the DICOM object fails the validation. public void Validate(DicomMessageBase 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); if (String.IsNullOrEmpty(studyInstanceUid)) { throw new DicomDataException("Study Instance UID is missing or empty"); } if (studyInstanceUid.Length > 64 || seriesInstanceUid.Length > 64 || sopInstanceUid.Length > 64) { if (studyInstanceUid.Length > 64) throw new DicomDataException(string.Format("Study Instance UID is > 64 bytes in the SOP Instance : {0}", studyInstanceUid)); if (seriesInstanceUid.Length > 64) throw new DicomDataException(string.Format("Series Instance UID is > 64 bytes in the SOP Instance : {0}", seriesInstanceUid)); throw new DicomDataException(string.Format("SOP Instance UID is > 64 bytes in the SOP Instance : {0}", sopInstanceUid)); } if (studyInstanceUid.EndsWith(".")) throw new DicomDataException(string.Format("Study Instance UID ends with period : {0}", studyInstanceUid)); if (seriesInstanceUid.EndsWith(".")) throw new DicomDataException(string.Format("Series Instance UID ends with period : {0}", seriesInstanceUid)); if (sopInstanceUid.EndsWith(".")) throw new DicomDataException(string.Format("SOP Instance UID ends with period : {0}", sopInstanceUid)); }
private IWorkItemProcessor InsertStudyDelete(DicomMessageBase msg, WorkItemPriorityEnum priority, WorkItemStatusEnum status) { var rq = new WorkItemInsertRequest { Request = new DeleteStudyRequest { Patient = new WorkItemPatient(msg.DataSet), Study = new WorkItemStudy(msg.DataSet), Priority = priority } }; var rsp = WorkItemService.Instance.Insert(rq); var updateRequest = new WorkItemUpdateRequest { Status = status, Identifier = rsp.Item.Identifier }; WorkItemService.Instance.Update(updateRequest); using (var context = new DataAccessContext(DataAccessContext.WorkItemMutex)) { var broker = context.GetWorkItemBroker(); var d = new DeleteStudyItemProcessor(); d.Initialize(new WorkItemStatusProxy(broker.GetWorkItem(rsp.Item.Identifier))); return d; } }
public ServerActionContext(DicomMessageBase msg, ServerEntityKey filesystemKey, ServerPartition partition, ServerEntityKey studyLocationKey) { Message = msg; ServerPartitionKey = partition.Key; StudyLocationKey = studyLocationKey; FilesystemKey = filesystemKey; ServerPartition = partition; }
public DicomCompressedPixelData(DicomMessageBase msg, byte[] frameData) : base(msg) { _sq = new DicomFragmentSequence(DicomTags.PixelData); AddFrameFragment(frameData); //ByteBuffer buffer = new ByteBuffer(frameData); //DicomFragment fragment = new DicomFragment(buffer); //_sq.AddFragment(fragment); NumberOfFrames = 1; }
public UpdateWorkQueueCommand(DicomMessageBase message, StudyStorageLocation location, bool duplicate, string extension, string uidGroupId) : base("Update/Insert a WorkQueue Entry") { Platform.CheckForNullReference(message, "Dicom Message object"); Platform.CheckForNullReference(location, "Study Storage Location"); _message = message; _storageLocation = location; _duplicate = duplicate; _extension = extension; _uidGroupId = uidGroupId; }
public UpdateWorkQueueCommand(DicomMessageBase message, StudyStorageLocation location, bool duplicate, WorkQueueData data=null, WorkQueueUidData uidData=null, ExternalRequestQueue request=null, WorkQueuePriorityEnum priority=null) : base("Update/Insert a WorkQueue Entry") { Platform.CheckForNullReference(message, "Dicom Message object"); Platform.CheckForNullReference(location, "Study Storage Location"); _message = message; _storageLocation = location; _duplicate = duplicate; _data = data; _request = request; _uidData = uidData; _priority = priority; }
/// <summary> /// Load the values for the tag <see cref="DicomTags.ModalitiesInStudy"/> into a response /// message for a specific <see cref="Study"/>. /// </summary> /// <param name="read">The connection to use to read the values.</param> /// <param name="response">The message to add the value into.</param> /// <param name="key">The <see cref="ServerEntityKey"/> for the <see cref="Study"/>.</param> private static void LoadModalitiesInStudy(IPersistenceContext read, DicomMessageBase response, ServerEntityKey key) { var select = read.GetBroker<IQueryModalitiesInStudy>(); var parms = new ModalitiesInStudyQueryParameters { StudyKey = key }; IList<Series> list = select.Find(parms); string value = ""; foreach (Series series in list) { value = value.Length == 0 ? series.Modality : String.Format("{0}\\{1}", value, series.Modality); } response.DataSet[DicomTags.ModalitiesInStudy].SetStringValue(value); }
/// <summary> /// Create a list of SOP Instances to move based on a Patient level C-MOVE-RQ. /// </summary> /// <param name="read"></param> /// <param name="msg"></param> /// <param name="errorComment"> </param> /// <returns></returns> private bool GetSopListForPatient(IPersistenceContext read, DicomMessageBase msg, out string errorComment) { errorComment = string.Empty; string patientId = msg.DataSet[DicomTags.PatientId].GetString(0, ""); var select = read.GetBroker<IStudyEntityBroker>(); var criteria = new StudySelectCriteria(); criteria.PatientId.EqualTo(patientId); criteria.ServerPartitionKey.EqualTo(Partition.Key); IList<Study> studyList = select.Find(criteria); bool bOfflineFound = false; foreach (Study study in studyList) { StudyStorageLocation location; try { FilesystemMonitor.Instance.GetReadableStudyStorageLocation(Partition.Key, study.StudyInstanceUid, StudyRestore.True, StudyCache.True, out location); } catch (StudyIsNearlineException e) { errorComment = string.Format(e.RestoreRequested ? "Study is nearline, inserted restore request: {0}" : "Study is nearline: {0}", study.StudyInstanceUid); bOfflineFound = true; continue; } catch (Exception e) { errorComment = string.Format("Exception occurred when determining study location: {0}", e.Message); bOfflineFound = true; continue; } StudyXml theStream = LoadStudyXml(location); _theScu.LoadStudyFromStudyXml(location.GetStudyPath(), theStream); } return !bOfflineFound; }
/// <summary> /// Process the duplicate with the supplied <see cref="DuplicateProcessingEnum"/> /// </summary> /// <param name="context">The processing context</param> /// <param name="message">A subset of the message stored in <paramref name="sourceFilename"/></param> /// <param name="sourceFilename">The location of the filename that is a duplicate</param> /// <param name="data">The data</param> /// <param name="duplicate">How the processor should handle the duplicate</param> public static void ProcessStoredDuplicateFile(SopInstanceProcessorContext context, string sourceFilename, DicomMessageBase message, StudyProcessWorkQueueData data, DuplicateProcessingEnum duplicate) { SaveDuplicateFile(context, message.DataSet[DicomTags.SopInstanceUid].ToString(), sourceFilename); var uidData = new WorkQueueUidData { Extension = ServerPlatform.DuplicateFileExtension, GroupId = context.Group, DuplicateProcessing = duplicate }; if (context.Request != null) uidData.OperationToken = context.Request.OperationToken; context.CommandProcessor.AddCommand( new UpdateWorkQueueCommand(message, context.StudyLocation, true, data, uidData, context.Request)); }
private void SetSourceMessage(DicomMessageBase sourceMessage) { _sourceMessage = sourceMessage; _loaded = !_sourceMessage.DataSet.IsEmpty(); }
/// <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); }
/// <summary> /// Updat ethe pixel data related tags in a DICOM message. /// </summary> /// <param name="message"></param> public abstract void UpdateMessage(DicomMessageBase message);
/// <summary> /// Populate at the IMAGE level a response message. /// </summary> /// <param name="request"></param> /// <param name="response"></param> /// <param name="tagList"></param> /// <param name="theInstanceStream"></param> private void PopulateInstance(DicomMessageBase request, DicomMessageBase response, IEnumerable<DicomTag> tagList, InstanceXml theInstanceStream) { DicomAttributeCollection dataSet = response.DataSet; dataSet[DicomTags.RetrieveAeTitle].SetStringValue(Partition.AeTitle); dataSet[DicomTags.InstanceAvailability].SetStringValue("ONLINE"); DicomAttributeCollection sourceDataSet = theInstanceStream.Collection; var characterSet = GetPreferredCharacterSet(); if (!string.IsNullOrEmpty(characterSet)) { dataSet[DicomTags.SpecificCharacterSet].SetStringValue(characterSet); dataSet.SpecificCharacterSet = characterSet; } else if (sourceDataSet.Contains(DicomTags.SpecificCharacterSet)) { dataSet[DicomTags.SpecificCharacterSet].SetStringValue(sourceDataSet[DicomTags.SpecificCharacterSet].ToString()); dataSet.SpecificCharacterSet = sourceDataSet[DicomTags.SpecificCharacterSet].ToString(); // this will ensure the data is encoded using the specified character set } 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( request.DataSet[DicomTags.SeriesInstanceUid].ToString()); break; case DicomTags.QueryRetrieveLevel: dataSet[DicomTags.QueryRetrieveLevel].SetStringValue("IMAGE"); break; default: if (sourceDataSet.Contains(tag)) dataSet[tag] = sourceDataSet[tag].Copy(); else if (!tag.IsPrivate) 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()); if (!tag.IsPrivate) dataSet[tag].SetNullValue(); } } }
/// <summary> /// Constructor. /// </summary> /// <param name="message"></param> protected DicomPixelData(DicomMessageBase message) : this(message.DataSet) { _transferSyntax = message.TransferSyntax; }
/// <summary> /// Create a Study Directory Record /// </summary> /// <param name="dicomFile">The dicom file.</param> private static DirectoryRecordSequenceItem CreateStudyItem(DicomMessageBase dicomFile) { IDictionary<uint, object> dicomTags = new Dictionary<uint, object>(); dicomTags.Add(DicomTags.StudyInstanceUid, null); dicomTags.Add(DicomTags.StudyId, null); dicomTags.Add(DicomTags.StudyDate, null); dicomTags.Add(DicomTags.StudyTime, null); dicomTags.Add(DicomTags.AccessionNumber, null); dicomTags.Add(DicomTags.StudyDescription, null); return AddSequenceItem(DirectoryRecordType.Study, dicomFile.DataSet, dicomTags); }
/// <summary> /// Traverse at the Patient level to check if a Patient exists or create a Patient if it doesn't exist. /// </summary> /// <param name="patients"></param> /// <param name="file"></param> /// <returns></returns> private static DirectoryRecordSequenceItem GetExistingOrCreateNewPatient(DirectoryRecordSequenceItem patients, DicomMessageBase file) { DirectoryRecordSequenceItem currentPatient = patients; while (currentPatient != null) { if (currentPatient[DicomTags.PatientId].Equals(file.DataSet[DicomTags.PatientId]) && currentPatient[DicomTags.PatientsName].Equals(file.DataSet[DicomTags.PatientsName])) { return currentPatient; } if (currentPatient.NextDirectoryRecord == null) { currentPatient.NextDirectoryRecord = CreatePatientItem(file); return currentPatient.NextDirectoryRecord; } currentPatient = currentPatient.NextDirectoryRecord; } return null; }
/// <summary> /// Update a <see cref="DicomMessageBase"/> with the pixel data contained /// within this object and also update pixel data related tags. /// </summary> /// <param name="message"></param> public override void UpdateMessage(DicomMessageBase message) { UpdateAttributeCollection(message.DataSet); DicomFile file = message as DicomFile; if (file != null) file.TransferSyntax = TransferSyntax; }
/// <summary> /// Returns a value indicating whether the Dicom image must be reconciled. /// </summary> /// <param name="storageLocation"></param> /// <param name="message">The Dicom message</param> /// <returns></returns> private bool ShouldReconcile(StudyStorageLocation storageLocation, DicomMessageBase message) { Platform.CheckForNullReference(_context, "_context"); Platform.CheckForNullReference(message, "message"); if (_context.Study == null) { // the study doesn't exist in the database return false; } StudyComparer comparer = new StudyComparer(); DifferenceCollection list = comparer.Compare(message, storageLocation.Study, storageLocation.ServerPartition.GetComparisonOptions()); if (list != null && list.Count > 0) { LogDifferences(message, list); return true; } return false; }
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; }
/// <summary> /// Traverse at the Series level to check if a Series exists, or create a Series if it doesn't exist. /// </summary> /// <param name="series"></param> /// <param name="file"></param> /// <returns></returns> private static DirectoryRecordSequenceItem GetExistingOrCreateNewSeries(DirectoryRecordSequenceItem series, DicomMessageBase file) { DirectoryRecordSequenceItem currentSeries = series; while (currentSeries != null) { if (currentSeries[DicomTags.SeriesInstanceUid].Equals(file.DataSet[DicomTags.SeriesInstanceUid])) { return currentSeries; } if (currentSeries.NextDirectoryRecord == null) { currentSeries.NextDirectoryRecord = CreateSeriesItem(file); return currentSeries.NextDirectoryRecord; } currentSeries = currentSeries.NextDirectoryRecord; } return null; }
/// <summary> /// Checks the data in the message and generates warning logs/alerts if /// any of them exceeeds the max size allowed in the database /// </summary> /// <param name="file"></param> private void CheckDataLength(DicomMessageBase file) { //TODO: Maybe this should be part of the model? String studyInstanceUid = file.DataSet[DicomTags.StudyInstanceUid].GetString(0, String.Empty); String patientId = file.DataSet[DicomTags.PatientId].GetString(0, String.Empty); String issuerOfPatientId = file.DataSet[DicomTags.IssuerOfPatientId].GetString(0, String.Empty); String patientsName = file.DataSet[DicomTags.PatientsName].GetString(0, String.Empty); String patientsBirthDate = file.DataSet[DicomTags.PatientsBirthDate].GetString(0, String.Empty); String patientsSex = file.DataSet[DicomTags.PatientsSex].GetString(0, String.Empty); String accessionNumber = file.DataSet[DicomTags.AccessionNumber].GetString(0, String.Empty); bool alert = false; if (!string.IsNullOrEmpty(patientId) && patientId.Length>64) { alert = true; Platform.Log(LogLevel.Warn, "Patient ID ({0}) in the dicom message exceeeds 64 characters", patientId); } if (!string.IsNullOrEmpty(issuerOfPatientId) && issuerOfPatientId.Length > 64) { alert = true; Platform.Log(LogLevel.Warn, "Issuer Of Patient ID ({0}) in the dicom message exceeeds 64 characters", issuerOfPatientId); } if (!string.IsNullOrEmpty(patientsName) && patientsName.Length > 64) { alert = true; Platform.Log(LogLevel.Warn, "Patient's Name ({0}) in the dicom message exceeeds 64 characters", patientsName); } if (!string.IsNullOrEmpty(patientsBirthDate) && patientsBirthDate.Length > 8) { alert = true; Platform.Log(LogLevel.Warn, "Patient's Birth Date ({0}) in the dicom message exceeeds 8 characters", patientsBirthDate); } if (!string.IsNullOrEmpty(patientsSex) && patientsSex.Length > 2) { alert = true; Platform.Log(LogLevel.Warn, "Patient's Sex ({0}) in the dicom message exceeeds 2 characters", patientsSex); } if (!string.IsNullOrEmpty(accessionNumber) && accessionNumber.Length > 16) { alert = true; Platform.Log(LogLevel.Warn, "Accession Number ({0}) in the dicom message exceeeds 16 characters", accessionNumber); } if (alert) { StudyAlertGenerator.Generate( new StudyAlert("Study Process", _context.Partition.AeTitle, studyInstanceUid, StudyAlertType.BadDicomData, String.Format("Study {0} contains some bad data which may have been truncated. It may not appear when queried by remote devices.", studyInstanceUid))); } }
/// <summary> /// Initializes a <see cref="DicomUncompressedPixelData"/> from the attributes in a DICOM file/message. /// </summary> /// <param name="dicomMessage">A DICOM file/message from which to initialize the properties of the <see cref="DicomUncompressedPixelData"/>.</param> public DicomUncompressedPixelData(DicomMessageBase dicomMessage) : base(dicomMessage) { _pd = dicomMessage.DataSet[DicomTags.PixelData]; InitializeFrameData(this, _pd); }
private static void LogDifferences(DicomMessageBase message, DifferenceCollection list) { string sopInstanceUid = message.DataSet[DicomTags.SopInstanceUid].GetString(0, String.Empty); StringBuilder sb = new StringBuilder(); sb.AppendFormat("Found {0} issue(s) in SOP {1}\n", list.Count, sopInstanceUid); sb.Append(list.ToString()); Platform.Log(LogLevel.Warn, sb.ToString()); }
static private DicomFile ConvertToDicomFile(DicomMessageBase message, string filename, string sourceAe) { // This routine sets some of the group 0x0002 elements. DicomFile file; if (message is DicomFile) { file = message as DicomFile; } else if (message is DicomMessage) { file = new DicomFile(message as DicomMessage, filename); } else { throw new NotSupportedException(String.Format("Cannot convert {0} to DicomFile", message.GetType())); } file.SourceApplicationEntityTitle = sourceAe; file.TransferSyntax = message.TransferSyntax; return file; }
/// <summary> /// Initializes a <see cref="DicomUncompressedPixelData"/> from the attributes in a DICOM file/message. /// </summary> /// <param name="dicomMessage">A DICOM file/message from which to initialize the properties of the <see cref="DicomUncompressedPixelData"/>.</param> public DicomUncompressedPixelData(DicomMessageBase dicomMessage) : base(dicomMessage) { _pd = dicomMessage.DataSet[DicomTags.PixelData]; InitializeFrameData(this, _pd); }
/// <summary> /// Compare at the IMAGE level if a query matches the data in an <see cref="InstanceXml"/> file. /// </summary> /// <param name="queryMessage"></param> /// <param name="matchTagList"></param> /// <param name="instanceStream"></param> /// <returns></returns> private static bool CompareInstanceMatch(DicomMessageBase queryMessage, IEnumerable<uint> matchTagList, InstanceXml instanceStream) { foreach (uint tag in matchTagList) { if (!instanceStream.Collection.Contains(tag)) continue; DicomAttribute sourceAttrib = queryMessage.DataSet[tag]; DicomAttribute matchAttrib = instanceStream.Collection[tag]; if (sourceAttrib.Tag.VR.Equals(DicomVr.SQvr)) continue; // TODO if (sourceAttrib.IsNull) continue; string sourceString = sourceAttrib.ToString(); if (sourceString.Contains("*") || sourceString.Contains("?")) { sourceString = sourceString.Replace("*", "[\x21-\x7E]"); sourceString = sourceString.Replace("?", "."); if (!Regex.IsMatch(matchAttrib.ToString(), sourceString)) return false; } else if (!sourceAttrib.Equals(matchAttrib)) return false; } return true; }
/// <summary> /// Traverse at the Study level to check if a Study exists or create a Study if it doesn't exist. /// </summary> /// <param name="studies"></param> /// <param name="file"></param> /// <returns></returns> private static DirectoryRecordSequenceItem GetExistingOrCreateNewStudy(DirectoryRecordSequenceItem studies, DicomMessageBase file) { DirectoryRecordSequenceItem currentStudy = studies; while (currentStudy != null) { if (currentStudy[DicomTags.StudyInstanceUid].Equals(file.DataSet[DicomTags.StudyInstanceUid])) { return currentStudy; } if (currentStudy.NextDirectoryRecord == null) { currentStudy.NextDirectoryRecord = CreateStudyItem(file); return currentStudy.NextDirectoryRecord; } currentStudy = currentStudy.NextDirectoryRecord; } return null; }
/// <summary> /// Populate data from a <see cref="Patient"/> entity into a DICOM C-FIND-RSP message. /// </summary> /// <param name="response">The response message to populate with results.</param> /// <param name="tagList">The list of tags to populate.</param> /// <param name="row">The <see cref="Patient"/> table to populate from.</param> private void PopulatePatient(DicomMessageBase response, IEnumerable<DicomTag> tagList, Patient row) { DicomAttributeCollection 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; } else 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 } IList<Study> relatedStudies = row.LoadRelatedStudies(); Study study = null; if (relatedStudies.Count > 0) study = CollectionUtils.FirstElement(relatedStudies); foreach (DicomTag tag in tagList) { try { switch (tag.TagValue) { case DicomTags.PatientsName: dataSet[DicomTags.PatientsName].SetStringValue(row.PatientsName); 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.NumberOfPatientRelatedStudies); break; case DicomTags.NumberOfPatientRelatedSeries: dataSet[DicomTags.NumberOfPatientRelatedSeries].AppendInt32(row.NumberOfPatientRelatedSeries); break; case DicomTags.NumberOfPatientRelatedInstances: dataSet[DicomTags.NumberOfPatientRelatedInstances].AppendInt32( row.NumberOfPatientRelatedInstances); break; case DicomTags.QueryRetrieveLevel: dataSet[DicomTags.QueryRetrieveLevel].SetStringValue("PATIENT"); break; case DicomTags.PatientsSex: if (study == null) dataSet[DicomTags.PatientsSex].SetNullValue(); else dataSet[DicomTags.PatientsSex].SetStringValue(study.PatientsSex); break; case DicomTags.PatientsBirthDate: if (study == null) dataSet[DicomTags.PatientsBirthDate].SetNullValue(); else dataSet[DicomTags.PatientsBirthDate].SetStringValue(study.PatientsBirthDate); 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(); foreach (var q in _queryExtensions) q.PopulatePatient(response, tag, row, study); break; } } catch (Exception e) { Platform.Log(LogLevel.Warn, e, "Unexpected error setting tag {0} in C-FIND-RSP", dataSet[tag].Tag.ToString()); if (!tag.IsPrivate) dataSet[tag].SetNullValue(); } } }
/// <summary> /// Create a Patient Directory Record /// </summary> /// <param name="dicomFile">The dicom file or message.</param> private static DirectoryRecordSequenceItem CreatePatientItem(DicomMessageBase dicomFile) { if (dicomFile == null) throw new ArgumentNullException("dicomFile"); IDictionary<uint, object> dicomTags = new Dictionary<uint, object>(); dicomTags.Add(DicomTags.PatientsName, null); dicomTags.Add(DicomTags.PatientId, null); dicomTags.Add(DicomTags.PatientsBirthDate, null); dicomTags.Add(DicomTags.PatientsSex, null); return AddSequenceItem(DirectoryRecordType.Patient, dicomFile.DataSet, dicomTags); }
/// <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<DicomTag> tagList, Study row, string availability) { DicomAttributeCollection dataSet = response.DataSet; dataSet[DicomTags.RetrieveAeTitle].SetStringValue(Partition.AeTitle); dataSet[DicomTags.InstanceAvailability].SetStringValue(availability); var characterSet = GetPreferredCharacterSet(); if (!string.IsNullOrEmpty(characterSet)) { dataSet[DicomTags.SpecificCharacterSet].SetStringValue(characterSet); dataSet.SpecificCharacterSet = characterSet; } else 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 (DicomTag tag in tagList) { try { switch (tag.TagValue) { 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; // 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(); foreach (var q in _queryExtensions) q.PopulateStudy(response, tag, row); break; } } catch (Exception e) { Platform.Log(LogLevel.Warn, e, "Unexpected error setting tag {0} in C-FIND-RSP", dataSet[tag].Tag.ToString()); if (!tag.IsPrivate) dataSet[tag].SetNullValue(); } } }
/// <summary> /// Create a Series Directory Record /// </summary> /// <param name="dicomFile">The dicom file.</param> private static DirectoryRecordSequenceItem CreateSeriesItem(DicomMessageBase dicomFile) { IDictionary<uint, object> dicomTags = new Dictionary<uint, object>(); dicomTags.Add(DicomTags.SeriesInstanceUid, null); dicomTags.Add(DicomTags.Modality, null); dicomTags.Add(DicomTags.SeriesDate, null); dicomTags.Add(DicomTags.SeriesTime, null); dicomTags.Add(DicomTags.SeriesNumber, null); dicomTags.Add(DicomTags.SeriesDescription, null); //dicomTags.Add(DicomTags.SeriesDescription, dicomFile.DataSet[DicomTags.SeriesDescription].GetString(0, String.Empty)); return AddSequenceItem(DirectoryRecordType.Series, dicomFile.DataSet, dicomTags); }
/// <summary> /// Populate the data from a <see cref="Series"/> entity into a DICOM C-FIND-RSP message. /// </summary> /// <param name="read">The connection to use to read the values.</param> /// <param name="request"></param> /// <param name="response"></param> /// <param name="tagList"></param> /// <param name="row">The <see cref="Series"/> table to populate the row from.</param> private void PopulateSeries(IPersistenceContext read, DicomMessageBase request, DicomMessageBase response, IEnumerable<DicomTag> tagList, Series row) { DicomAttributeCollection dataSet = response.DataSet; Study theStudy = Study.Load(read, row.StudyKey); StudyStorage storage = StudyStorage.Load(read, theStudy.ServerPartitionKey, theStudy.StudyInstanceUid); dataSet[DicomTags.RetrieveAeTitle].SetStringValue(Partition.AeTitle); dataSet[DicomTags.InstanceAvailability].SetStringValue(storage.StudyStatusEnum == StudyStatusEnum.Nearline ? "NEARLINE" : "ONLINE"); var characterSet = GetPreferredCharacterSet(); if (!string.IsNullOrEmpty(characterSet)) { dataSet[DicomTags.SpecificCharacterSet].SetStringValue(characterSet); dataSet.SpecificCharacterSet = characterSet; } else if (false == String.IsNullOrEmpty(theStudy.SpecificCharacterSet)) { dataSet[DicomTags.SpecificCharacterSet].SetStringValue(theStudy.SpecificCharacterSet); dataSet.SpecificCharacterSet = theStudy.SpecificCharacterSet; // this will ensure the data is encoded using the specified character set } 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.SeriesInstanceUid); 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].SetStringValue( row.PerformedProcedureStepStartDate); break; case DicomTags.PerformedProcedureStepStartTime: dataSet[DicomTags.PerformedProcedureStepStartTime].SetStringValue( row.PerformedProcedureStepStartTime); break; case DicomTags.NumberOfSeriesRelatedInstances: dataSet[DicomTags.NumberOfSeriesRelatedInstances].AppendInt32(row.NumberOfSeriesRelatedInstances); 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(); foreach (var q in _queryExtensions) q.PopulateSeries(response, tag, row); break; } } catch (Exception e) { Platform.Log(LogLevel.Warn, e, "Unexpected error setting tag {0} in C-FIND-RSP", dataSet[tag].Tag.ToString()); if (!tag.IsPrivate) dataSet[tag].SetNullValue(); } } }