コード例 #1
0
        public void TestKeyImages(int numberOfFrames, int numberOfMultiframeKeyImages, int numberOfSingleFrameKeyImages, bool doSplitting)
        {
            Assert.IsTrue(numberOfFrames == 0 || numberOfFrames > 1);
            Assert.IsTrue(numberOfMultiframeKeyImages <= numberOfFrames);

            const int numberOfSeries     = 1;
            int       instancesPerSeries = numberOfSingleFrameKeyImages + ((numberOfFrames > 0) ? 1 : 0);

            Assert.IsTrue(instancesPerSeries > 0);

            List <TestDataSource> dataSources = CreateMRStudyDataSources(numberOfSeries, instancesPerSeries, "1.2.3");

            if (numberOfFrames > 0)
            {
                TestDataSource           multiFrameDataSource = dataSources[0];
                DicomAttributeCollection oldDataSet           = multiFrameDataSource.File.DataSet;
                DicomAttributeCollection newDataSet           = new DicomAttributeCollection();
                DicomFile newFile = new DicomFile("", new DicomAttributeCollection(), newDataSet);
                //Yes this is the world's crappiest hack.
                base.SetupMultiframeXA(newDataSet, 512, 512, (uint)numberOfFrames);
                //because of an exception that gets thrown from the DateTimeParser
                newDataSet[DicomTags.StudyDate].SetNullValue();
                newDataSet[DicomTags.StudyTime].SetNullValue();
                newDataSet[DicomTags.SeriesDate].SetNullValue();
                newDataSet[DicomTags.SeriesTime].SetNullValue();
                newDataSet[DicomTags.ReferencedStudySequence].SetEmptyValue();
                newDataSet[DicomTags.Modality].SetStringValue("MR");
                newDataSet[DicomTags.StudyInstanceUid].SetStringValue(oldDataSet[DicomTags.StudyInstanceUid].ToString());
                newDataSet[DicomTags.SeriesInstanceUid].SetStringValue(oldDataSet[DicomTags.SeriesInstanceUid].ToString());
                dataSources[0] = new TestDataSource(newFile);
            }

            StudyTree          studyTree  = CreateStudyTree(ConvertToSops(dataSources));
            KeyImageSerializer serializer = new KeyImageSerializer();

            Patient patient      = studyTree.Patients[0];
            Study   study        = patient.Studies[0];
            Series  sourceSeries = study.Series[0];

            List <IDisplaySet> allDisplaySets = new List <IDisplaySet>();

            BasicDisplaySetFactory factory = new BasicDisplaySetFactory();

            factory.SetStudyTree(studyTree);

            List <IDisplaySet> displaySets = factory.CreateDisplaySets(sourceSeries);

            allDisplaySets.AddRange(displaySets);

            List <DicomFile> presentationStates    = new List <DicomFile>();
            int numberOfMultiframeKeyImagesCreated = 0;

            foreach (IDisplaySet displaySet in displaySets)
            {
                foreach (IPresentationImage image in displaySet.PresentationImages)
                {
                    Frame frame = ((IImageSopProvider)image).Frame;
                    if (frame.ParentImageSop.NumberOfFrames > 1)
                    {
                        if (numberOfMultiframeKeyImagesCreated >= numberOfMultiframeKeyImages)
                        {
                            continue;
                        }

                        ++numberOfMultiframeKeyImagesCreated;
                    }

                    DicomSoftcopyPresentationState presentationState = DicomSoftcopyPresentationState.Create(image);
                    //because of an exception that gets thrown from the DateTimeParser
                    presentationState.DicomFile.DataSet[DicomTags.StudyDate].SetNullValue();
                    presentationState.DicomFile.DataSet[DicomTags.StudyTime].SetNullValue();
                    presentationState.DicomFile.DataSet[DicomTags.SeriesDate].SetNullValue();
                    presentationState.DicomFile.DataSet[DicomTags.SeriesTime].SetNullValue();

                    presentationStates.Add(presentationState.DicomFile);
                    serializer.AddImage(frame, presentationState);
                }
            }

            List <DicomFile>      files = serializer.Serialize();
            List <TestDataSource> keyImageDataSources = ConvertToDataSources(files);
            List <Sop>            keyImageSops        = ConvertToSops(keyImageDataSources);

            keyImageSops.AddRange(ConvertToSops(ConvertToDataSources(presentationStates)));

            foreach (Sop sop in keyImageSops)
            {
                studyTree.AddSop(sop);
            }

            try
            {
                foreach (Series series in study.Series)
                {
                    if (series.Modality != "KO")
                    {
                        continue;
                    }

                    List <IDisplaySet> keyImageDisplaySets;
                    if (doSplitting)
                    {
                        factory.CreateSingleImageDisplaySets = true;
                        keyImageDisplaySets = factory.CreateDisplaySets(series);
                        if (keyImageDisplaySets.Count == 0)
                        {
                            factory.CreateSingleImageDisplaySets = false;
                            keyImageDisplaySets = factory.CreateDisplaySets(series);
                        }
                    }
                    else
                    {
                        keyImageDisplaySets = factory.CreateDisplaySets(series);
                    }

                    allDisplaySets.AddRange(keyImageDisplaySets);

                    int numberOfKeyImages = numberOfMultiframeKeyImages + numberOfSingleFrameKeyImages;
                    if (!doSplitting)
                    {
                        Assert.AreEqual(1, keyImageDisplaySets.Count, "There should be only one display set");
                        IDisplaySet keyImageDisplaySet = keyImageDisplaySets[0];
                        Assert.AreEqual(numberOfKeyImages, keyImageDisplaySet.PresentationImages.Count, "Expected {0} images", numberOfKeyImages);
                        Assert.AreEqual(typeof(KOSelectionDocumentDisplaySetDescriptor), keyImageDisplaySet.Descriptor.GetType(), "Wrong display set descriptor type");
                    }
                    else
                    {
                        Assert.AreEqual(numberOfKeyImages, keyImageDisplaySets.Count, "Expected {0} display sets", numberOfKeyImages);

                        foreach (IDisplaySet keyImageDisplaySet in keyImageDisplaySets)
                        {
                            Assert.AreEqual(1, keyImageDisplaySet.PresentationImages.Count, "There should be only one presentation image");
                            IPresentationImage keyImage = keyImageDisplaySet.PresentationImages[0];
                            ImageSop           sop      = ((IImageSopProvider)keyImage).ImageSop;

                            Assert.AreEqual(sourceSeries.SeriesInstanceUid, sop.SeriesInstanceUid, "Series Instance Uid is not that of the source series");
                            if (numberOfKeyImages == 1)
                            {
                                Assert.AreEqual(typeof(KOSelectionDocumentDisplaySetDescriptor), keyImageDisplaySet.Descriptor.GetType(), "Wrong display set descriptor type");
                            }
                            else if (sop.NumberOfFrames > 1)
                            {
                                Assert.AreEqual(typeof(KOSelectionSingleFrameDisplaySetDescriptor), keyImageDisplaySet.Descriptor.GetType(), "Wrong display set descriptor type");
                            }
                            else
                            {
                                Assert.AreEqual(typeof(KOSelectionSingleImageDisplaySetDescriptor), keyImageDisplaySet.Descriptor.GetType(), "Wrong display set descriptor type");
                            }
                        }
                    }
                }
            }
            finally
            {
                foreach (IDisplaySet displaySet in allDisplaySets)
                {
                    displaySet.Dispose();
                }

                studyTree.Dispose();
            }
        }
コード例 #2
0
        public static void AddKeyImage(IPresentationImage image)
        {
            Platform.CheckForNullReference(image, "image");
            Platform.CheckForNullReference(image.ImageViewer, "image.ImageViewer");

            // TODO (CR Phoenix5 - Med): Clinical as well
            if (!PermissionsHelper.IsInRole(AuthorityTokens.KeyImages))
            {
                throw new PolicyException(SR.ExceptionCreateKeyImagePermissionDenied);
            }

            var sopProvider = image as IImageSopProvider;

            if (sopProvider == null)
            {
                throw new ArgumentException("The image must be an IImageSopProvider.", "image");
            }

            IDisplaySet displaySet = null;

            foreach (var set in image.ImageViewer.LogicalWorkspace.ImageSets)
            {
                if (set.Descriptor.Equals(image.ParentDisplaySet.ParentImageSet.Descriptor))
                {
                    foreach (var d in set.DisplaySets)
                    {
                        var displaySetDescriptor = d.Descriptor as KeyImageDisplaySetDescriptor;

                        if (displaySetDescriptor != null
                            &&
                            displaySetDescriptor.SourceStudy.StudyInstanceUid.Equals(sopProvider.Sop.StudyInstanceUid))
                        {
                            displaySet = d;
                            break;
                        }
                    }

                    break;
                }
            }

            if (displaySet == null)
            {
                var displaySetDescriptor = new KeyImageDisplaySetDescriptor(new StudyIdentifier(sopProvider.ImageSop));
                displaySet = new DisplaySet(displaySetDescriptor);
                bool displaySetAdded = false;
                foreach (var imageSet in image.ImageViewer.LogicalWorkspace.ImageSets)
                {
                    if (imageSet.Descriptor.Equals(image.ParentDisplaySet.ParentImageSet.Descriptor))
                    {
                        imageSet.DisplaySets.Add(displaySet);
                        displaySetAdded = true;
                        break;
                    }
                }
                if (!displaySetAdded)
                {
                    throw new ApplicationException(SR.MessageCreateKeyImageFailed);
                }
            }

            var presentationImage = image.CreateFreshCopy();

            var presentationState = DicomSoftcopyPresentationState.Create(image);
            var basicImage        = presentationImage as BasicPresentationImage;

            if (basicImage != null)
            {
                basicImage.PresentationState = presentationState;
            }

            displaySet.PresentationImages.Add(presentationImage);

            foreach (var imageBox in image.ImageViewer.PhysicalWorkspace.ImageBoxes)
            {
                if (imageBox.DisplaySet != null && imageBox.DisplaySet.Descriptor.Uid == displaySet.Descriptor.Uid)
                {
                    var physicalImage = presentationImage.CreateFreshCopy();

                    presentationState = DicomSoftcopyPresentationState.Create(image);
                    basicImage        = physicalImage as BasicPresentationImage;
                    if (basicImage != null)
                    {
                        basicImage.PresentationState = presentationState;
                    }

                    imageBox.DisplaySet.PresentationImages.Add(physicalImage);

                    imageBox.Draw();
                }
            }
        }
コード例 #3
0
        /// <summary>
        /// Creates all the SOP instances associated with the key object selection and the content presentation states.
        /// </summary>
        public IDictionary <IStudySource, List <DicomFile> > CreateSopInstances(NextSeriesNumberDelegate nextSeriesNumberDelegate)
        {
            if (!HasChanges || !Items.Any())
            {
                return(new Dictionary <IStudySource, List <DicomFile> >(0));
            }

            // update the author field
            Author = GetUserName();

            // the series index ensures consistent series level data because we only create one KO series and one PR series per study
            var studyIndex = new Dictionary <string, StudyInfo>();

            var secondaryCaptureImageFactory = new SecondaryCaptureImageFactory(nextSeriesNumberDelegate);
            var framePresentationStates      = new List <KeyValuePair <KeyImageReference, PresentationStateReference> >();

            // create presentation states for the images in the clipboard
            var presentationStates = new List <DicomSoftcopyPresentationState>();

            foreach (var item in Items.Where(i => i.Item is IPresentationImage))
            {
                var image = (IPresentationImage)item.Item;

                // if the item is a placeholder image (e.g. because source study wasn't available), simply reserialize the original sop references
                if (image is KeyObjectPlaceholderImage)
                {
                    // because source study wasn't available, we don't have enough information to create the identical KO for that study
                    // and thus an entry in the study index table is not needed
                    var ko = (KeyObjectPlaceholderImage)image;
                    framePresentationStates.Add(new KeyValuePair <KeyImageReference, PresentationStateReference>(ko.KeyImageReference, ko.PresentationStateReference));
                    continue;
                }

                var provider = image as IImageSopProvider;
                if (provider == null)
                {
                    continue;
                }

                StudyInfo studyInfo;
                var       studyInstanceUid = provider.ImageSop.StudyInstanceUid;
                if (!studyIndex.TryGetValue(studyInstanceUid, out studyInfo))
                {
                    studyIndex.Add(studyInstanceUid, studyInfo = new StudyInfo(provider, nextSeriesNumberDelegate));

                    // keep the previous series number if the one we know about is the same study as this new document
                    // otherwise, pre-allocate a series number for the KO now (ensures the number will be lower than any SC and PR series)
                    if (_parentStudyInstanceUid == studyInstanceUid && _seriesNumber.HasValue)
                    {
                        studyInfo.KeyObjectSeriesNumber = _seriesNumber.Value;
                    }
                    else
                    {
                        studyInfo.AllocateKeyObjectSeriesNumber();
                    }
                }

                // if the item doesn't have changes and the presentation state is DICOM, simply reserialize the original sop references
                if (!item.HasChanges() && image is IDicomPresentationImage)
                {
                    var dicomPresentationState = ((IDicomPresentationImage)image).PresentationState as DicomSoftcopyPresentationState;
                    framePresentationStates.Add(new KeyValuePair <KeyImageReference, PresentationStateReference>(provider.Frame, dicomPresentationState));
                    continue;
                }

                // if the image is not a permanent stored instance (i.e. it was dynamically generated), create a secondary capture from it
                if (!provider.Sop.DataSource.IsStored)
                {
                    image    = secondaryCaptureImageFactory.CreateSecondaryCapture(image);
                    provider = (IImageSopProvider)image;
                }

                var presentationState = DicomSoftcopyPresentationState.IsSupported(image)
                                                                ? DicomSoftcopyPresentationState.Create
                                            (image, ps =>
                {
                    ps.PresentationSeriesInstanceUid = studyInfo.PresentationSeriesUid;
                    ps.PresentationSeriesNumber      = studyInfo.PresentationSeriesNumber;
                    ps.PresentationSeriesDateTime    = studyInfo.PresentationSeriesDateTime;
                    ps.PresentationInstanceNumber    = studyInfo.GetNextPresentationInstanceNumber();
                    ps.SourceAETitle = provider.ImageSop.DataSource[DicomTags.SourceApplicationEntityTitle].ToString();
                }) : null;
                if (presentationState != null)
                {
                    presentationStates.Add(presentationState);
                }
                framePresentationStates.Add(new KeyValuePair <KeyImageReference, PresentationStateReference>(provider.Frame, presentationState));
            }

            // serialize the key image document
            var serializer = new KeyImageSerializer();

            serializer.Author            = Author;
            serializer.Description       = Description;
            serializer.DocumentTitle     = DocumentTitle;
            serializer.SeriesDescription = SeriesDescription;
            foreach (var presentationFrame in framePresentationStates)
            {
                serializer.AddImage(presentationFrame.Key, presentationFrame.Value);
            }

            // collect all the SOP instances that were created (SC, PR and KO)
            var documents = new List <DicomFile>();

            documents.AddRange(serializer.Serialize(koSeries =>
            {
                var uid = koSeries.StudyInstanceUid;
                if (studyIndex.ContainsKey(uid))
                {
                    koSeries.SeriesDateTime    = studyIndex[uid].KeyObjectSeriesDateTime;
                    koSeries.SeriesNumber      = studyIndex[uid].KeyObjectSeriesNumber;
                    koSeries.SeriesInstanceUid = studyIndex[uid].KeyObjectSeriesUid;
                    return(studyIndex[uid].DataSource);
                }
                return(null);
            }
                                                    ));
            documents.AddRange(secondaryCaptureImageFactory.Files);
            documents.AddRange(presentationStates.Select(ps => ps.DicomFile));

            // return the created instances grouped by study (and thus study origin/source)
            return(documents.GroupBy(f => (IStudySource)studyIndex[f.DataSet[DicomTags.StudyInstanceUid].ToString()]).ToDictionary(g => g.Key, g => g.ToList()));
        }
コード例 #4
0
        public IPresentationImage CreateSecondaryCapture(IPresentationImage image)
        {
            var imageSopProvider = image as IImageSopProvider;

            if (imageSopProvider == null)
            {
                const string msg = "image must implement IImageSopProvider";
                throw new ArgumentException(msg, "image");
            }

            SeriesInfo seriesInfo;
            var        seriesKey = MakeSeriesKey(imageSopProvider.Frame.StudyInstanceUid, imageSopProvider.Sop.Modality);

            if (!_seriesInfo.TryGetValue(seriesKey, out seriesInfo))
            {
                _seriesInfo[seriesKey] = seriesInfo = new SeriesInfo(_nextSeriesNumberDelegate.Invoke(imageSopProvider.Frame.StudyInstanceUid));
            }

            var dcf = CreatePrototypeFile(imageSopProvider.Sop.DataSource);

            FillGeneralSeriesModule(dcf.DataSet, imageSopProvider.Frame, seriesInfo);
            FillScEquipmentModule(dcf.DataSet, Manufacturer, ManufacturersModelName, SoftwareVersions);
            FillFrameOfReferenceModule(dcf.DataSet, imageSopProvider.Frame);
            FillGeneralImageModule(dcf.DataSet, imageSopProvider.Frame, seriesInfo);
            FillScImageModule(dcf.DataSet, imageSopProvider.Frame);
            FillImagePlaneModule(dcf.DataSet, imageSopProvider.Frame);
            FillSopCommonModule(dcf.DataSet, SopClass.SecondaryCaptureImageStorageUid);
            FillAuxiliaryImageData(dcf.DataSet, imageSopProvider.Frame);

            if (image is GrayscalePresentationImage)
            {
                FillModalityLutModule(dcf.DataSet, imageSopProvider.Frame);
                FillVoiLutModule(dcf.DataSet, imageSopProvider.Frame);

                // create image pixel last - this method may need to override some attributes set previously
                CreateImagePixelModuleGrayscale(dcf.DataSet, imageSopProvider.Frame);
            }
            else if (image is ColorPresentationImage)
            {
                // create image pixel last - this method may need to override some attributes set previously
                CreateImagePixelModuleColor(dcf.DataSet, imageSopProvider.Frame);
            }
            else
            {
                // create image pixel last - this method may need to override some attributes set previously
                CreateImagePixelModuleRasterRgb(dcf.DataSet, image);
            }

            dcf.MediaStorageSopClassUid    = dcf.DataSet[DicomTags.SopClassUid].ToString();
            dcf.MediaStorageSopInstanceUid = dcf.DataSet[DicomTags.SopInstanceUid].ToString();
            _files.Add(dcf);

            using (var sop = new ImageSop(new LocalSopDataSource(dcf)))
            {
                var secondaryCapture = PresentationImageFactory.Create(sop).Single();
                try
                {
                    var presentationState = DicomSoftcopyPresentationState.IsSupported(image) ? DicomSoftcopyPresentationState.Create(image) : null;
                    if (presentationState != null)
                    {
                        presentationState.DeserializeOptions |= DicomSoftcopyPresentationStateDeserializeOptions.IgnoreImageRelationship;
                        presentationState.Deserialize(secondaryCapture);

                        // override the spatial transform of the secondary capture because the presentation state doesn't save exact parameters
                        var sourceTransform = image as ISpatialTransformProvider;
                        var targetTransform = secondaryCapture as ISpatialTransformProvider;
                        if (sourceTransform != null && targetTransform != null)
                        {
                            targetTransform.SpatialTransform.CenterOfRotationXY = sourceTransform.SpatialTransform.CenterOfRotationXY;
                            targetTransform.SpatialTransform.FlipX        = sourceTransform.SpatialTransform.FlipX;
                            targetTransform.SpatialTransform.FlipY        = sourceTransform.SpatialTransform.FlipY;
                            targetTransform.SpatialTransform.RotationXY   = sourceTransform.SpatialTransform.RotationXY;
                            targetTransform.SpatialTransform.Scale        = sourceTransform.SpatialTransform.Scale;
                            targetTransform.SpatialTransform.TranslationX = sourceTransform.SpatialTransform.TranslationX;
                            targetTransform.SpatialTransform.TranslationY = sourceTransform.SpatialTransform.TranslationY;

                            var sourceImageTransform = sourceTransform as IImageSpatialTransform;
                            var targetImageTransform = targetTransform as IImageSpatialTransform;
                            if (sourceImageTransform != null && targetImageTransform != null)
                            {
                                targetImageTransform.ScaleToFit = sourceImageTransform.ScaleToFit;
                            }
                        }
                    }

                    // force a render to update the client rectangle and scaling of the image
                    secondaryCapture.RenderImage(image.ClientRectangle).Dispose();
                }
                catch (Exception ex)
                {
                    Platform.Log(LogLevel.Warn, ex, "An error has occurred while deserializing the image presentation state.");
                }
                return(secondaryCapture);
            }
        }