/// <summary> /// Cloning constructor. /// </summary> /// <param name="source">The source object from which to clone.</param> /// <param name="context">The cloning context object.</param> protected FusionPresentationImage(FusionPresentationImage source, ICloningContext context) : base(source, context) { context.CloneFields(source, this); _baseFrameReference = source._baseFrameReference.Clone(); _overlayFrameDataReference = source._overlayFrameDataReference.Clone(); }
public override List <IDisplaySet> CreateDisplaySets(Series series) { List <IDisplaySet> displaySets = new List <IDisplaySet>(); if (IsValidPETFusionSeries(series)) { var fuseableBaseSeries = new List <Series>(FindFuseableBaseSeries(series)); if (fuseableBaseSeries.Count > 0) { string error; if (!CheckPETFusionSeries(series, out error)) { // if there is an error with the PET series, avoid trying to generate the volume entirely // instead, generate a placeholder series for each base series foreach (var baseSeries in fuseableBaseSeries) { displaySets.Add(CreateFusionErrorDisplaySet(baseSeries, series, error)); } return(displaySets); } var overlayFrames = GetFrames(series.Sops); using (var fusionOverlayData = new FusionOverlayData(overlayFrames)) { foreach (var baseSeries in fuseableBaseSeries) { if (!CheckBaseSeries(baseSeries, out error)) { // if there is an error with a single base series, generate a placeholder series displaySets.Add(CreateFusionErrorDisplaySet(baseSeries, series, error)); continue; } var descriptor = new PETFusionDisplaySetDescriptor(baseSeries.GetIdentifier(), series.GetIdentifier(), IsAttenuationCorrected(series.Sops[0])); var displaySet = new DisplaySet(descriptor); using (var sops = new DisposableList <Sop>(baseSeries.Sops.OfType <ImageSop>().Select(s => new ImageSop(new FusionSopDataSource(s.DataSource, _fusionType, overlayFrames))))) { foreach (var baseFrame in GetFrames(sops)) { using (var fusionOverlaySlice = fusionOverlayData.CreateOverlaySlice(baseFrame)) { var fus = new FusionPresentationImage(baseFrame, fusionOverlaySlice); displaySet.PresentationImages.Add(fus); } } } displaySet.PresentationImages.Sort(); displaySets.Add(displaySet); } } } } return(displaySets); }
/// <summary> /// Attempts to install an appropriate equivalent of the specified <paramref name="sourceVoiLut"/> to a fusion image. If the LUT is not linear, computes a dummy LUT. /// </summary> private static void InstallVoiLut(FusionPresentationImage fusionImage, IVoiLut sourceVoiLut, Frame sourceFrame, bool applyToOverlay) { IVoiLut newVoiLut; if (sourceVoiLut is MinMaxPixelCalculatedLinearLut) { if (applyToOverlay) { // if the overlay source image is using a min/max calculated LUT, install a custom calculated LUT that delay-computes min/max from the fusion data // we need to delay-compute this because the fusion image graphic is delay-generated, and thus not necessarily available until just before rendering! var skipModalityLut = sourceFrame.ParentImageSop.Modality == @"PT" && sourceFrame.IsSubnormalRescale; newVoiLut = new FusionOverlayMinMaxVoiLutLinear(fusionImage, !skipModalityLut); } else { // if the base source image is using a min/max calculated LUT, install a similarly min/max calculated LUT for the base of the fusion image newVoiLut = new MinMaxPixelCalculatedLinearLut(fusionImage.ImageGraphic.PixelData); } } else if (sourceVoiLut is IVoiLutLinear) { var voiLutLinear = (IVoiLutLinear)sourceVoiLut; var normalizedVoiSlope = 1.0; var normalizedVoiIntercept = 0.0; if (applyToOverlay && sourceFrame.ParentImageSop.Modality == @"PT" && sourceFrame.IsSubnormalRescale) { // for subnormal PET rescale slope cases, the original VOI windows must be transformed through the same process as what MPR did to the pixel data normalizedVoiSlope = sourceFrame.RescaleSlope / fusionImage.OverlayFrameData.OverlayRescaleSlope; normalizedVoiIntercept = (sourceFrame.RescaleIntercept - fusionImage.OverlayFrameData.OverlayRescaleIntercept) / fusionImage.OverlayFrameData.OverlayRescaleSlope; } newVoiLut = new BasicVoiLutLinear(voiLutLinear.WindowWidth * normalizedVoiSlope, voiLutLinear.WindowCenter * normalizedVoiSlope + normalizedVoiIntercept); } else { // if the source image is using some non-linear LUT, just install a default pass-through LUT newVoiLut = new IdentityVoiLinearLut(); } if (applyToOverlay) { fusionImage.OverlayVoiLutManager.InstallVoiLut(newVoiLut); } else { fusionImage.BaseVoiLutManager.InstallVoiLut(newVoiLut); } }
public FusionOverlayMinMaxVoiLutLinear(FusionPresentationImage fusionPresentationImage, bool useModalityLut) { Platform.CheckForNullReference(fusionPresentationImage, "fusionPresentationImage"); _fusionPresentationImage = fusionPresentationImage; _useModalityLut = useModalityLut; }
public override List<IDisplaySet> CreateDisplaySets(Series series) { List<IDisplaySet> displaySets = new List<IDisplaySet>(); if (IsValidPETFusionSeries(series)) { var fuseableBaseSeries = new List<Series>(FindFuseableBaseSeries(series)); if (fuseableBaseSeries.Count > 0) { string error; if (!CheckPETFusionSeries(series, out error)) { // if there is an error with the PET series, avoid trying to generate the volume entirely // instead, generate a placeholder series for each base series foreach (var baseSeries in fuseableBaseSeries) displaySets.Add(CreateFusionErrorDisplaySet(baseSeries, series, error)); return displaySets; } using (var fusionOverlayData = new FusionOverlayData(GetFrames(series.Sops))) { foreach (var baseSeries in fuseableBaseSeries) { if (!CheckBaseSeries(baseSeries, out error)) { // if there is an error with a single base series, generate a placeholder series displaySets.Add(CreateFusionErrorDisplaySet(baseSeries, series, error)); continue; } var descriptor = new PETFusionDisplaySetDescriptor(baseSeries.GetIdentifier(), series.GetIdentifier(), IsAttenuationCorrected(series.Sops[0])); var displaySet = new DisplaySet(descriptor); foreach (var baseFrame in GetFrames(baseSeries.Sops)) { using (var fusionOverlaySlice = fusionOverlayData.CreateOverlaySlice(baseFrame)) { var fus = new FusionPresentationImage(baseFrame, fusionOverlaySlice); displaySet.PresentationImages.Add(fus); } } displaySet.PresentationImages.Sort(); displaySets.Add(displaySet); } } } } return displaySets; }
/// <summary> /// Attempts to install an appropriate equivalent of the specified <paramref name="sourceVoiLut"/> to a fusion image. If the LUT is not linear, computes a dummy LUT. /// </summary> private static void InstallVoiLut(FusionPresentationImage fusionImage, IVoiLut sourceVoiLut, Frame sourceFrame, bool applyToOverlay) { IVoiLut newVoiLut; if (sourceVoiLut is MinMaxPixelCalculatedLinearLut) { if (applyToOverlay) { // if the overlay source image is using a min/max calculated LUT, install a custom calculated LUT that delay-computes min/max from the fusion data // we need to delay-compute this because the fusion image graphic is delay-generated, and thus not necessarily available until just before rendering! var skipModalityLut = sourceFrame.ParentImageSop.Modality == @"PT" && sourceFrame.IsSubnormalRescale; newVoiLut = new FusionOverlayMinMaxVoiLutLinear(fusionImage, !skipModalityLut); } else { // if the base source image is using a min/max calculated LUT, install a similarly min/max calculated LUT for the base of the fusion image newVoiLut = new MinMaxPixelCalculatedLinearLut(fusionImage.ImageGraphic.PixelData); } } else if (sourceVoiLut is IVoiLutLinear) { var voiLutLinear = (IVoiLutLinear) sourceVoiLut; var normalizedVoiSlope = 1.0; var normalizedVoiIntercept = 0.0; if (applyToOverlay && sourceFrame.ParentImageSop.Modality == @"PT" && sourceFrame.IsSubnormalRescale) { // for subnormal PET rescale slope cases, the original VOI windows must be transformed through the same process as what MPR did to the pixel data normalizedVoiSlope = sourceFrame.RescaleSlope/fusionImage.OverlayFrameData.OverlayRescaleSlope; normalizedVoiIntercept = (sourceFrame.RescaleIntercept - fusionImage.OverlayFrameData.OverlayRescaleIntercept)/fusionImage.OverlayFrameData.OverlayRescaleSlope; } newVoiLut = new BasicVoiLutLinear(voiLutLinear.WindowWidth*normalizedVoiSlope, voiLutLinear.WindowCenter*normalizedVoiSlope + normalizedVoiIntercept); } else { // if the source image is using some non-linear LUT, just install a default pass-through LUT newVoiLut = new IdentityVoiLinearLut(); } if (applyToOverlay) fusionImage.OverlayVoiLutManager.InstallVoiLut(newVoiLut); else fusionImage.BaseVoiLutManager.InstallVoiLut(newVoiLut); }