public MprVolume(Volumes.Volume volume, IEnumerable<IMprSliceSet> sliceSets) { Platform.CheckForNullReference(volume, "volume"); // MprVolume is the de jure owner of the Volume // Everything else (like the SOPs) just hold transient references _volume = volume; _sliceSets = new ObservableDisposableList<IMprSliceSet>(); if (sliceSets != null) { foreach (IMprSliceSet sliceSet in sliceSets) { if (sliceSet is IInternalMprSliceSet) ((IInternalMprSliceSet) sliceSet).Parent = this; _sliceSets.Add(sliceSet); } } _sliceSets.EnableEvents = true; _sliceSets.ItemAdded += OnItemAdded; _sliceSets.ItemChanged += OnItemAdded; _sliceSets.ItemChanging += OnItemRemoved; _sliceSets.ItemRemoved += OnItemRemoved; // Generate a descriptive name for the volume PersonName patientName = new PersonName(_volume.DataSet[DicomTags.PatientsName].ToString()); string patientId = _volume.DataSet[DicomTags.PatientId].ToString(); string seriesDescription = _volume.DataSet[DicomTags.SeriesDescription].ToString(); if (string.IsNullOrEmpty(seriesDescription)) _description = string.Format(SR.FormatVolumeLabel, patientName.FormattedName, patientId, seriesDescription); else _description = string.Format(SR.FormatVolumeLabelWithSeries, patientName.FormattedName, patientId, seriesDescription); }
public MprStandardSliceSet(Volumes.Volume volume, IVolumeSlicerParams slicerParams) : base(volume) { Platform.CheckForNullReference(slicerParams, "slicerParams"); _slicerParams = slicerParams; base.Description = slicerParams.Description; this.Reslice(); }
private static IEnumerable <IMprSliceSet> CreateStandardSliceSets(Volumes.Volume volume, IEnumerable <IVolumeSlicerParams> slicerParams) { if (volume != null && slicerParams != null) { foreach (IVolumeSlicerParams slicerParam in slicerParams) { yield return(new MprStandardSliceSet(volume, slicerParam)); } } }
protected static void ValidateVolumeSlicePoints(Volumes.Volume volume, IVolumeSlicerParams slicerParams, IList <KnownSample> expectedPoints, double xAxialGantryTilt, double yAxialGantryTilt, bool gantryTiltInDegrees) { if (gantryTiltInDegrees) { xAxialGantryTilt *= Math.PI / 180; yAxialGantryTilt *= Math.PI / 180; } Trace.WriteLine(string.Format("Using slice plane: {0}", slicerParams.Description)); using (VolumeSlicer slicer = new VolumeSlicer(volume, slicerParams)) { foreach (ISopDataSource slice in slicer.CreateSliceSops()) { using (ImageSop imageSop = new ImageSop(slice)) { foreach (IPresentationImage image in PresentationImageFactory.Create(imageSop)) { IImageGraphicProvider imageGraphicProvider = (IImageGraphicProvider)image; DicomImagePlane dip = DicomImagePlane.FromImage(image); foreach (KnownSample sample in expectedPoints) { Vector3D patientPoint = sample.Point; if (xAxialGantryTilt != 0 && yAxialGantryTilt == 0) { float cos = (float)Math.Cos(xAxialGantryTilt); float sin = (float)Math.Sin(xAxialGantryTilt); patientPoint = new Vector3D(patientPoint.X, patientPoint.Y * cos + (xAxialGantryTilt > 0 ? 100 * sin : 0), patientPoint.Z / cos - patientPoint.Y * sin - (xAxialGantryTilt > 0 ? 100 * sin * sin / cos : 0)); } else if (yAxialGantryTilt != 0) { Assert.Fail("Unit test not designed to work with gantry tilts about Y (i.e. slew)"); } Vector3D slicedPoint = dip.ConvertToImagePlane(patientPoint); if (slicedPoint.Z > -0.5 && slicedPoint.Z < 0.5) { int actual = imageGraphicProvider.ImageGraphic.PixelData.GetPixel((int)slicedPoint.X, (int)slicedPoint.Y); Trace.WriteLine(string.Format("Sample {0} @{1} (SLICE: {2}; PATIENT: {3})", actual, FormatVector(sample.Point), FormatVector(slicedPoint), FormatVector(patientPoint))); Assert.AreEqual(sample.Value, actual, "Wrong colour sample @{0}", sample.Point); } } image.Dispose(); } } slice.Dispose(); } } }
protected MprSliceSet(Volumes.Volume volume) { Platform.CheckForNullReference(volume, "volume"); _volume = volume.CreateReference(); _sliceSops = new ObservableDisposableList <MprSliceSop>(); _sliceSops.EnableEvents = true; _sliceSops.ItemAdded += OnItemAdded; _sliceSops.ItemChanged += OnItemChanged; _sliceSops.ItemChanging += OnItemChanging; _sliceSops.ItemRemoved += OnItemRemoved; }
private void LoadVolume(IBackgroundTaskContext context) { try { ProgressTask mainTask = new ProgressTask(); mainTask.AddSubTask("BUILD", 90); mainTask.AddSubTask("LAYOUT", 10); context.ReportProgress(new BackgroundTaskProgress(mainTask.IntPercent, string.Format(SR.MessageInitializingMpr, mainTask.Progress))); BackgroundTaskParams @params = (BackgroundTaskParams)context.UserState; Volumes.Volume volume = Volumes.Volume.Create(@params.Frames, delegate(int i, int count) { if (context.CancelRequested) { throw new BackgroundTaskCancelledException(); } if (i == 0) { mainTask["BUILD"].AddSubTask("", count); } mainTask["BUILD"][""].Increment(); string message = string.Format(SR.MessageBuildingMprVolumeProgress, mainTask.Progress, i + 1, count, mainTask["BUILD"].Progress); context.ReportProgress(new BackgroundTaskProgress(mainTask.IntPercent, message)); }); mainTask["BUILD"].MarkComplete(); context.ReportProgress(new BackgroundTaskProgress(mainTask.IntPercent, string.Format(SR.MessagePerformingMprWorkspaceLayout, mainTask.Progress))); //call layout here b/c it could take a while @params.SynchronizationContext.Send(delegate { _viewer = new MprViewerComponent(volume); _viewer.Layout(); }, null); mainTask["LAYOUT"].MarkComplete(); context.ReportProgress(new BackgroundTaskProgress(mainTask.IntPercent, string.Format(SR.MessageDone, mainTask.Progress))); context.Complete(); } catch (BackgroundTaskCancelledException) { context.Cancel(); } catch (Exception ex) { context.Error(ex); } }
private static IEnumerable <IMprSliceSet> CreateDefaultSliceSets(Volumes.Volume volume) { // The default slice sets consist of a fixed view of the original image plane, // and three mutable slice sets showing the other two planes perpendicular to the original // plus one oblique slice set halfway in between these two perpendicular planes. if (volume != null) { yield return(MprStaticSliceSet.CreateIdentitySliceSet(volume)); yield return(new MprStandardSliceSet(volume, VolumeSlicerParams.OrthogonalX)); yield return(new MprStandardSliceSet(volume, new VolumeSlicerParams(90, 0, 270))); yield return(new MprStandardSliceSet(volume, new VolumeSlicerParams(90, 0, 315))); } }
protected virtual void Dispose(bool disposing) { if (disposing) { if (_sliceSets != null) { _sliceSets.ItemAdded -= OnItemAdded; _sliceSets.ItemChanged -= OnItemAdded; _sliceSets.ItemChanging -= OnItemRemoved; _sliceSets.ItemRemoved -= OnItemRemoved; _sliceSets.Dispose(); _sliceSets = null; } if (_volume != null) { _volume.Dispose(); _volume = null; } } }
public MprVolume(Volumes.Volume volume, IEnumerable <IMprSliceSet> sliceSets) { Platform.CheckForNullReference(volume, "volume"); // MprVolume is the de jure owner of the Volume // Everything else (like the SOPs) just hold transient references _volume = volume; _sliceSets = new ObservableDisposableList <IMprSliceSet>(); if (sliceSets != null) { foreach (IMprSliceSet sliceSet in sliceSets) { if (sliceSet is IInternalMprSliceSet) { ((IInternalMprSliceSet)sliceSet).Parent = this; } _sliceSets.Add(sliceSet); } } _sliceSets.EnableEvents = true; _sliceSets.ItemAdded += OnItemAdded; _sliceSets.ItemChanged += OnItemAdded; _sliceSets.ItemChanging += OnItemRemoved; _sliceSets.ItemRemoved += OnItemRemoved; // Generate a descriptive name for the volume PersonName patientName = new PersonName(_volume.DataSet[DicomTags.PatientsName].ToString()); string patientId = _volume.DataSet[DicomTags.PatientId].ToString(); string seriesDescription = _volume.DataSet[DicomTags.SeriesDescription].ToString(); if (string.IsNullOrEmpty(seriesDescription)) { _description = string.Format(SR.FormatVolumeLabel, patientName.FormattedName, patientId, seriesDescription); } else { _description = string.Format(SR.FormatVolumeLabelWithSeries, patientName.FormattedName, patientId, seriesDescription); } }
protected static void ValidateVolumeSlicePoints(Volumes.Volume volume, IVolumeSlicerParams slicerParams, IList <KnownSample> expectedPoints) { ValidateVolumeSlicePoints(volume, slicerParams, expectedPoints, 0, 0, false); }
public VolumeSlicer(Volumes.Volume volume, IVolumeSlicerParams slicerParams) { _volume = volume.CreateReference(); _slicerParams = slicerParams; }
public static MprStaticSliceSet CreateIdentitySliceSet(Volumes.Volume volume) { return(new MprStaticSliceSet(volume, VolumeSlicerParams.Identity)); }
public MprVolume(Volumes.Volume volume, IEnumerable <IVolumeSlicerParams> slicerParams) : this(volume, CreateStandardSliceSets(volume, slicerParams)) { }
public MprVolume(Volumes.Volume volume) : this(volume, CreateDefaultSliceSets(volume)) { }
public MprViewerComponent(Volumes.Volume volume) : this() { _volumes.Add(new MprVolume(volume)); }
private static void TestVolume(bool signed, VolumeFunction f, IEnumerable <IVolumeSlicerParams> slicerParams, string testName, ImageKernelFunction imageKernel, VolumeKernelFunction volumeKernel) { const int FULL_SCALE = 65535; VolumeFunction normalizedFunction = f.Normalize(100); using (Volumes.Volume volume = normalizedFunction.CreateVolume(100, signed)) { float offset = signed ? -32768 : 0; foreach (IVolumeSlicerParams slicing in slicerParams) { List <double> list = new List <double>(); using (VolumeSlicer slicer = new VolumeSlicer(volume, slicing)) { foreach (ISopDataSource slice in slicer.CreateSliceSops()) { using (ImageSop imageSop = new ImageSop(slice)) { // assert tags inserted by slicer AssertAreEqual("WSD", imageSop.DataSource, DicomTags.ConversionType); AssertAreEqual("ClearCanvas Inc.", imageSop.DataSource, DicomTags.SecondaryCaptureDeviceManufacturer); AssertAreEqual(@"DERIVED\SECONDARY", imageSop.DataSource, DicomTags.ImageType); AssertAreEqual("Multiplanar Reformatting", imageSop.DataSource, DicomTags.DerivationDescription); foreach (IPresentationImage image in PresentationImageFactory.Create(imageSop)) { IImageSopProvider imageSopProvider = (IImageSopProvider)image; IImageGraphicProvider imageGraphicProvider = (IImageGraphicProvider)image; DicomImagePlane dip = DicomImagePlane.FromImage(image); for (int y = 1; y < imageSopProvider.Frame.Rows - 1; y++) { for (int x = 1; x < imageSopProvider.Frame.Columns - 1; x++) { // pixels on the extreme sides of the volume tend to have more interpolation error due to MPR padding values Vector3D vector = dip.ConvertToPatient(new PointF(x, y)); // +new Vector3D(-0.5f, -0.5f, 0); if (Between(vector.X, 1, 98) && Between(vector.Y, 1, 98) && Between(vector.Z, 1, 98)) { float expected = volumeKernel.Invoke(normalizedFunction, vector.X, vector.Y, vector.Z) + offset; float actual = imageKernel.Invoke(imageGraphicProvider.ImageGraphic.PixelData, x, y); list.Add(Math.Abs(expected - actual)); } } } image.Dispose(); } } slice.Dispose(); } } Statistics stats = new Statistics(list); Trace.WriteLine(string.Format("Testing {0}", testName)); Trace.WriteLine(string.Format("\tFunction/Slicing: {0} / {1}", normalizedFunction.Name, slicing.Description)); Trace.WriteLine(string.Format("\t Pixel Rep: {0}", signed ? "signed" : "unsigned")); Trace.WriteLine(string.Format("\t Voxels Compared: {0}", list.Count)); Trace.WriteLine(string.Format("\t Mean Delta: {0:f2} ({1:p2} of full scale)", stats.Mean, stats.Mean / FULL_SCALE)); Trace.WriteLine(string.Format("\t StdDev Delta: {0:f2} ({1:p2} of full scale)", stats.StandardDeviation, stats.StandardDeviation / FULL_SCALE)); Assert.Less(stats.Mean, FULL_SCALE * 0.05, "Mean delta exceeds 5% of full scale ({0})", FULL_SCALE); Assert.Less(stats.StandardDeviation, FULL_SCALE * 0.05, "StdDev delta exceeds 5% of full scale ({0})", FULL_SCALE); } } }