public async Task <IEnumerable <FhirTransactionRequestEntry> > BuildAsync(FhirTransactionContext context, CancellationToken cancellationToken) { EnsureArg.IsNotNull(context, nameof(context)); EnsureArg.IsNotNull(context.ChangeFeedEntry, nameof(context.ChangeFeedEntry)); Identifier identifier = IdentifierUtility.CreateIdentifier(context.ChangeFeedEntry.StudyInstanceUid); List <Observation> matchingObservations = (await _fhirService.RetrieveObservationsAsync(identifier, cancellationToken)).ToList(); // terminate early if no observation found if (matchingObservations.Count == 0) { return(null); } var requests = new List <FhirTransactionRequestEntry>(); foreach (Observation observation in matchingObservations) { Bundle.RequestComponent request = new Bundle.RequestComponent() { Method = Bundle.HTTPVerb.DELETE, Url = $"{ResourceType.Observation.GetLiteral()}/{observation.Id}" }; requests.Add(new FhirTransactionRequestEntry( FhirTransactionRequestMode.Delete, request, observation.ToServerResourceId(), observation)); } return(requests); }
public void GivenStudyInstanceUid_WhenCreated_ThenCorrectIdentifierShouldBeCreated() { var identifier = IdentifierUtility.CreateIdentifier("123"); Assert.NotNull(identifier); Assert.Equal("urn:dicom:uid", identifier.System); Assert.Equal("urn:oid:123", identifier.Value); }
/// <inheritdoc/> public async Task <FhirTransactionRequestEntry> BuildAsync(FhirTransactionContext context, CancellationToken cancellationToken) { EnsureArg.IsNotNull(context, nameof(context)); EnsureArg.IsNotNull(context.ChangeFeedEntry, nameof(context.ChangeFeedEntry)); ChangeFeedEntry changeFeedEntry = context.ChangeFeedEntry; Identifier imagingStudyIdentifier = IdentifierUtility.CreateIdentifier(changeFeedEntry.StudyInstanceUid); ImagingStudy imagingStudy = await _fhirService.RetrieveImagingStudyAsync(imagingStudyIdentifier, cancellationToken); // Returns null if imagingStudy does not exists for given studyInstanceUid if (imagingStudy == null) { return(null); } string imagingStudySource = imagingStudy.Meta.Source; ImagingStudy.SeriesComponent series = ImagingStudyPipelineHelper.GetSeriesWithinAStudy(changeFeedEntry.SeriesInstanceUid, imagingStudy.Series); ImagingStudy.InstanceComponent instance = ImagingStudyPipelineHelper.GetInstanceWithinASeries(changeFeedEntry.SopInstanceUid, series); // Return null if the given instance is not present in ImagingStudy if (instance == null) { return(null); } // Removes instance from series collection series.Instance.Remove(instance); // Removes series from ImagingStudy if its instance collection is empty if (series.Instance.Count == 0) { imagingStudy.Series.Remove(series); } if (imagingStudy.Series.Count == 0 && _dicomWebEndpoint.Equals(imagingStudySource, System.StringComparison.Ordinal)) { return(new FhirTransactionRequestEntry( FhirTransactionRequestMode.Delete, ImagingStudyPipelineHelper.GenerateDeleteRequest(imagingStudy), imagingStudy.ToServerResourceId(), imagingStudy)); } return(new FhirTransactionRequestEntry( FhirTransactionRequestMode.Update, ImagingStudyPipelineHelper.GenerateUpdateRequest(imagingStudy), imagingStudy.ToServerResourceId(), imagingStudy)); }
public async Task <IEnumerable <FhirTransactionRequestEntry> > BuildAsync(FhirTransactionContext context, CancellationToken cancellationToken) { EnsureArg.IsNotNull(context?.ChangeFeedEntry, nameof(context.ChangeFeedEntry)); EnsureArg.IsNotNull(context.Request, nameof(context.Request)); IResourceId patientId = context.Request.Patient.ResourceId; IResourceId imagingStudyId = context.Request.ImagingStudy.ResourceId; ChangeFeedEntry changeFeedEntry = context.ChangeFeedEntry; Identifier identifier = IdentifierUtility.CreateIdentifier(changeFeedEntry.StudyInstanceUid); IReadOnlyCollection <Observation> observations = _observationParser.Parse(changeFeedEntry.Metadata, patientId.ToResourceReference(), imagingStudyId.ToResourceReference(), identifier); if (observations.Count == 0) { return(Enumerable.Empty <FhirTransactionRequestEntry>()); } Identifier imagingStudyIdentifier = imagingStudyId.ToResourceReference().Identifier; IEnumerable <Observation> existingDoseSummariesAsync = imagingStudyIdentifier != null ? await _fhirService .RetrieveObservationsAsync( imagingStudyId.ToResourceReference().Identifier, cancellationToken) : new List <Observation>(); // TODO: Figure out a way to match existing observations with newly created ones. List <FhirTransactionRequestEntry> fhirRequests = new List <FhirTransactionRequestEntry>(); foreach (var observation in observations) { fhirRequests.Add(new FhirTransactionRequestEntry( FhirTransactionRequestMode.Create, new Bundle.RequestComponent() { Method = Bundle.HTTPVerb.POST, Url = ResourceType.Observation.GetLiteral() }, new ClientResourceId(), observation)); } return(fhirRequests); }
public void RadiationEventWithAllSupportedAttributes() { const string randomIrradiationEventUid = "1.2.3.4.5.6.123123"; const decimal randomDecimalNumber = (decimal)0.10; var randomRadiationMeasurementCodeItem = new DicomCodeItem("mGy", "UCUM", "mGy"); var report = new DicomStructuredReport( ObservationConstants.IrradiationEventXRayData, new DicomContentItem( ObservationConstants.IrradiationEventUid, DicomRelationship.Contains, new DicomUID(randomIrradiationEventUid, "", DicomUidType.Unknown)), new DicomContentItem( ObservationConstants.MeanCtdIvol, DicomRelationship.Contains, new DicomMeasuredValue(randomDecimalNumber, randomRadiationMeasurementCodeItem)), new DicomContentItem( ObservationConstants.Dlp, DicomRelationship.Contains, new DicomMeasuredValue(randomDecimalNumber, randomRadiationMeasurementCodeItem)), new DicomContentItem( ObservationConstants.CtdIwPhantomType, DicomRelationship.Contains, new DicomCodeItem("113691", "DCM", "IEC Body Dosimetry Phantom"))); var observations = _observationParser.Parse( report.Dataset, new ResourceReference(), new ResourceReference(), IdentifierUtility.CreateIdentifier(randomIrradiationEventUid)); Assert.Single(observations); Observation radiationEvent = observations.First(); Assert.Single(radiationEvent.Identifier); Assert.Equal("urn:oid:" + randomIrradiationEventUid, radiationEvent.Identifier[0].Value); Assert.Equal(2, radiationEvent.Component .Count(component => component.Value is Quantity)); Assert.Equal(1, radiationEvent.Component .Count(component => component.Value is CodeableConcept)); }
public static ImagingStudy ValidateImagingStudyUpdate(string studyInstanceUid, string patientResourceId, FhirTransactionRequestEntry entry, bool hasAccessionNumber = true) { Identifier expectedIdentifier = IdentifierUtility.CreateIdentifier(studyInstanceUid); string expectedRequestUrl = $"ImagingStudy/{entry.Resource.Id}"; ValidateRequestEntryMinimumRequirementForWithChange(FhirTransactionRequestMode.Update, expectedRequestUrl, Bundle.HTTPVerb.PUT, actualEntry: entry); ImagingStudy updatedImagingStudy = Assert.IsType <ImagingStudy>(entry.Resource); Assert.Equal(ImagingStudy.ImagingStudyStatus.Available, updatedImagingStudy.Status); ValidateResourceReference(patientResourceId, updatedImagingStudy.Subject); Action <Identifier> studyIdValidaion = identifier => ValidateIdentifier("urn:dicom:uid", $"urn:oid:{studyInstanceUid}", identifier); Action <Identifier> accessionNumberValidation = identifier => ValidateAccessionNumber(null, FhirTransactionContextBuilder.DefaultAccessionNumber, identifier); Assert.Collection( updatedImagingStudy.Identifier, hasAccessionNumber ? new[] { studyIdValidaion, accessionNumberValidation } : new[] { studyIdValidaion }); return(updatedImagingStudy); }
public static ImagingStudy CreateNewImagingStudy(string studyInstanceUid, List <string> seriesInstanceUidList, List <string> sopInstanceUidList, string patientResourceId, string source = "defaultSouce") { // Create a new ImagingStudy ImagingStudy study = new ImagingStudy { Id = "123", Status = ImagingStudy.ImagingStudyStatus.Available, Subject = new ResourceReference(patientResourceId), Meta = new Meta() { VersionId = "1", Source = source, }, }; foreach (string seriesInstanceUid in seriesInstanceUidList) { ImagingStudy.SeriesComponent series = new ImagingStudy.SeriesComponent() { Uid = seriesInstanceUid, }; foreach (string sopInstanceUid in sopInstanceUidList) { ImagingStudy.InstanceComponent instance = new ImagingStudy.InstanceComponent() { Uid = sopInstanceUid, }; series.Instance.Add(instance); } study.Series.Add(series); } study.Identifier.Add(IdentifierUtility.CreateIdentifier(studyInstanceUid)); return(study); }
/// <inheritdoc/> public async Task <FhirTransactionRequestEntry> BuildAsync(FhirTransactionContext context, CancellationToken cancellationToken) { EnsureArg.IsNotNull(context, nameof(context)); EnsureArg.IsNotNull(context.ChangeFeedEntry, nameof(context.ChangeFeedEntry)); EnsureArg.IsNotNull(context.Request, nameof(context.Request)); IResourceId patientId = context.Request.Patient.ResourceId; ChangeFeedEntry changeFeedEntry = context.ChangeFeedEntry; Identifier imagingStudyIdentifier = IdentifierUtility.CreateIdentifier(changeFeedEntry.StudyInstanceUid); ImagingStudy existingImagingStudy = await _fhirService.RetrieveImagingStudyAsync(imagingStudyIdentifier, cancellationToken); ImagingStudy imagingStudy = (ImagingStudy)existingImagingStudy?.DeepCopy(); FhirTransactionRequestMode requestMode = FhirTransactionRequestMode.None; if (existingImagingStudy == null) { imagingStudy = new ImagingStudy() { Status = ImagingStudy.ImagingStudyStatus.Available, Subject = patientId.ToResourceReference(), }; imagingStudy.Identifier.Add(imagingStudyIdentifier); imagingStudy.Meta = new Meta() { Source = _dicomWebEndpoint, }; requestMode = FhirTransactionRequestMode.Create; } await SynchronizeImagingStudyPropertiesAsync(context, imagingStudy, cancellationToken); if (requestMode != FhirTransactionRequestMode.Create && !existingImagingStudy.IsExactly(imagingStudy)) { requestMode = FhirTransactionRequestMode.Update; } Bundle.RequestComponent request = requestMode switch { FhirTransactionRequestMode.Create => ImagingStudyPipelineHelper.GenerateCreateRequest(imagingStudyIdentifier), FhirTransactionRequestMode.Update => ImagingStudyPipelineHelper.GenerateUpdateRequest(imagingStudy), _ => null, }; IResourceId resourceId = requestMode switch { FhirTransactionRequestMode.Create => new ClientResourceId(), _ => existingImagingStudy.ToServerResourceId(), }; return(new FhirTransactionRequestEntry( requestMode, request, resourceId, imagingStudy)); }
public void DoseSummaryWithAllSupportedAttributes() { const string studyInstanceUid = "1.3.12.2.123.5.4.5.123123.123123"; const string accessionNumber = "random-accession"; const decimal randomDecimalNumber = (decimal)0.10; var randomRadiationMeasurementCodeItem = new DicomCodeItem("mGy", "UCUM", "mGy"); var report = new DicomStructuredReport( ObservationConstants.RadiopharmaceuticalRadiationDoseReport, // identifiers new DicomContentItem( ObservationConstants.StudyInstanceUid, DicomRelationship.HasProperties, new DicomUID(studyInstanceUid, "", DicomUidType.Unknown)), new DicomContentItem( ObservationConstants.AccessionNumber, DicomRelationship.HasProperties, DicomValueType.Text, accessionNumber), // attributes new DicomContentItem( ObservationConstants.DoseRpTotal, DicomRelationship.Contains, new DicomMeasuredValue(randomDecimalNumber, randomRadiationMeasurementCodeItem)), new DicomContentItem( ObservationConstants.AccumulatedAverageGlandularDose, DicomRelationship.Contains, new DicomMeasuredValue(randomDecimalNumber, randomRadiationMeasurementCodeItem)), new DicomContentItem( ObservationConstants.DoseAreaProductTotal, DicomRelationship.Contains, new DicomMeasuredValue(randomDecimalNumber, randomRadiationMeasurementCodeItem)), new DicomContentItem( ObservationConstants.FluoroDoseAreaProductTotal, DicomRelationship.Contains, new DicomMeasuredValue(randomDecimalNumber, randomRadiationMeasurementCodeItem)), new DicomContentItem( ObservationConstants.AcquisitionDoseAreaProductTotal, DicomRelationship.Contains, new DicomMeasuredValue(randomDecimalNumber, randomRadiationMeasurementCodeItem)), new DicomContentItem( ObservationConstants.TotalFluoroTime, DicomRelationship.Contains, new DicomMeasuredValue(randomDecimalNumber, randomRadiationMeasurementCodeItem)), new DicomContentItem( ObservationConstants.TotalNumberOfRadiographicFrames, DicomRelationship.Contains, new DicomMeasuredValue(10, new DicomCodeItem("1", "UCUM", "No units"))), new DicomContentItem( ObservationConstants.AdministeredActivity, DicomRelationship.Contains, new DicomMeasuredValue(randomDecimalNumber, randomRadiationMeasurementCodeItem)), new DicomContentItem( ObservationConstants.CtDoseLengthProductTotal, DicomRelationship.Contains, new DicomMeasuredValue(randomDecimalNumber, randomRadiationMeasurementCodeItem)), new DicomContentItem( ObservationConstants.TotalNumberOfIrradiationEvents, DicomRelationship.Contains, new DicomMeasuredValue(10, new DicomCodeItem("1", "UCUM", "No units"))), new DicomContentItem( ObservationConstants.MeanCtdIvol, DicomRelationship.Contains, new DicomMeasuredValue(randomDecimalNumber, randomRadiationMeasurementCodeItem)), new DicomContentItem( ObservationConstants.RadiopharmaceuticalAgent, DicomRelationship.Contains, DicomValueType.Text, "Uranium"), new DicomContentItem( ObservationConstants.Radionuclide, DicomRelationship.Contains, DicomValueType.Text, "Uranium"), new DicomContentItem( ObservationConstants.RadiopharmaceuticalVolume, DicomRelationship.Contains, new DicomMeasuredValue(randomDecimalNumber, randomRadiationMeasurementCodeItem)), new DicomContentItem( ObservationConstants.RouteOfAdministration, DicomRelationship.Contains, new DicomCodeItem("needle", "random-scheme", "this is made up")) ); var observations = _observationParser.Parse( report.Dataset, new ResourceReference(), new ResourceReference(), IdentifierUtility.CreateIdentifier(studyInstanceUid)); Assert.Single(observations); Observation doseSummary = observations.First(); Assert.Equal(2, doseSummary.Identifier.Count); Assert.Equal("urn:oid:" + studyInstanceUid, doseSummary.Identifier[0].Value); Assert.Equal(accessionNumber, doseSummary.Identifier[1].Value); Assert.Equal(10, doseSummary.Component .Count(component => component.Value is Quantity)); Assert.Equal(2, doseSummary.Component .Count(component => component.Value is Integer)); Assert.Equal(2, doseSummary.Component .Count(component => component.Value is FhirString)); Assert.Equal(1, doseSummary.Component .Count(component => component.Value is CodeableConcept)); }