Пример #1
0
        /// <summary>
        /// Main method responsible for calling other methods to Extract Brain from current and prior series, Register the two, BFC and Normalize and then compare using a lookup table
        /// </summary>
        /// <param name="currentNii">current series nifti file path</param>
        /// <param name="priorNii">prior series nifti file path</param>
        /// <param name="referenceNii">reference series nifti file path (If exists, used for universal frame of reference)</param>
        /// <param name="extractBrain">to do skull stripping or not</param>
        /// <param name="register">to register or not</param>
        /// <param name="biasFieldCorrect">to perform bias field correction or not</param>
        /// <param name="resultNiis">end result output nifti files path</param>
        /// <param name="outPriorReslicedNii">resliced prior series nifti file path</param>
        public override MSMetrics Process()
        {
            // We consider this pipeline one-shot.
            if (IsComplete)
            {
                throw new IThinkSomethingWentWrongException("You've already processed this instance. Make a new one or check the metrics.");
            }
            // Quick sanity check that files exist.
            FileSystem.FilesExist(new[] { _currentNii, _priorNii });

            // Setup our things...
            DataReceivedEventHandler dataout = (s, e) => { _log.Debug(e.Data); System.Console.WriteLine(e.Data); };
            var stopwatch1 = new Stopwatch();

            // BiasCorrection
            if (_biasFieldCorrect)
            {
                _log.Info("Starting bias correction...");
                stopwatch1.Start();
                var bias1 = Task.Run(() => { return(BiasCorrect(_currentNii, dataout)); });
                var bias2 = Task.Run(() => { return(BiasCorrect(_priorNii, dataout)); });
                //bias1.Wait();
                //bias2.Wait();
                _currentNii = bias1.Result;
                _priorNii   = bias2.Result;
                _log.Info($@"..done. [{stopwatch1.Elapsed}]");
                stopwatch1.Restart();
            }

            var currentWithSkull = _currentNii;
            var priorWithSkull   = _priorNii;

            // Brain Extraction
            _log.Info("Starting brain extraction...");
            var brain1 = Task.Run(() => { return(SkullStrip(_currentNii, dataout)); });
            var brain2 = Task.Run(() => { return(SkullStrip(_priorNii, dataout)); });
            var brain3 = Task.Run(() => { return(SkullStrip(_referenceNii, dataout)); }); // TODO: This can be null.

            brain1.Wait();
            brain2.Wait();
            brain3.Wait();
            _currentNii   = brain1.Result;
            _priorNii     = brain2.Result;
            _referenceNii = brain3.Result;
            _log.Info($@"..done. [{stopwatch1.Elapsed}]");
            stopwatch1.Restart();

            // Registration
            if (_register)
            {
                var refBrain = string.IsNullOrEmpty(_referenceNii) && File.Exists(_referenceNii) ? _referenceNii : _currentNii;

                // Registration
                _log.Info("Starting registration...");
                _priorNii = Register(_priorNii, refBrain, dataout);
                if (!refBrain.Equals(_currentNii)) // If we're using a third file for registration...
                {
                    _priorNii = Register(_currentNii, refBrain, dataout);
                }
                _log.Info($@"..done. [{stopwatch1.Elapsed}]");
                stopwatch1.Restart();

                //TODO fix this...
                //priorWithSkull = Reslicer(priorWithSkull, refBrain, dataout);
            }

            // Convert files to INifti, now that we're done with pre-processing.
            var currentNifti          = new NiftiFloat32().ReadNifti(_currentNii);
            var priorNifti            = new NiftiFloat32().ReadNifti(_priorNii);
            var currentNiftiWithSkull = new NiftiFloat32().ReadNifti(currentWithSkull);
            var priorNiftiWithSkull   = new NiftiFloat32().ReadNifti(priorWithSkull);

            // Check brain extraction match...
            _log.Info($@"Checking brain extraction...");
            stopwatch1.Restart();
            CheckBrainExtractionMatch(currentNifti, priorNifti, currentNiftiWithSkull, priorNiftiWithSkull, Metrics);
            _log.Info($@"...done [{stopwatch1.Elapsed}]");

            // Normalize
            stopwatch1.Restart();
            _log.Info("Starting normalization...");
            currentNifti = Normalization.ZNormalize(currentNifti, priorNifti);
            _log.Info($@"..done. [{stopwatch1.Elapsed}]");
            stopwatch1.Restart();

            // Compare
            _log.Info("Starting compare...");
            var increaseTask = Task.Run(() => { return(MSCompare.CompareMSLesionIncrease(currentNifti, priorNifti)); });
            var decreaseTask = Task.Run(() => { return(MSCompare.CompareMSLesionDecrease(currentNifti, priorNifti)); });

            increaseTask.Wait();
            decreaseTask.Wait();
            var increaseNifti = increaseTask.Result;
            var decreaseNifti = decreaseTask.Result;

            _log.Info($@"..done. [{stopwatch1.Elapsed}]");
            stopwatch1.Restart();

            // Estimate edge ratio. The edge ratio is the ratio of change which is an edge vs. the change which is bounded.
            // A lower ratio implies that there are larger connected areas of change, which may be more clinically significant.
            // This is an estimate as the check is only over one dimension (to save time).
            _log.Info($@"Estimating edge ratio (lower implies more meaningful change)");
            EstimateEdgeRatio(increaseNifti, decreaseNifti, Metrics);
            _log.Info($@"..done. [{stopwatch1.Elapsed}]");

            stopwatch1.Restart();

            // Write the prior resliced file.
            var priorToExport = _extractBrain ? priorNifti : priorNiftiWithSkull;

            priorToExport.WriteNifti(_outPriorReslicedNii);

            //Overlay increase and decrease values:
            _log.Info("Generating RGB overlays...");
            var currentToExport = _extractBrain ? currentNifti : currentNiftiWithSkull;
            var overlayTask1    = Task.Run(() => { return(currentToExport.AddOverlay(increaseNifti)); });
            var overlayTask2    = Task.Run(() => { return(currentToExport.AddOverlay(decreaseNifti)); });

            overlayTask1.Wait();
            overlayTask2.Wait();
            var increaseNiftiRGB = overlayTask1.Result;
            var decreaseNiftiRGB = overlayTask2.Result;

            // Write files out to disk.
            var writeTask1 = Task.Run(() => { increaseNiftiRGB.WriteNifti(_resultNiis[0]); });
            var writeTask2 = Task.Run(() => { decreaseNiftiRGB.WriteNifti(_resultNiis[1]); });

            writeTask1.Wait();
            writeTask2.Wait();

            _log.Info($@"..done. [{stopwatch1.Elapsed}]");

            Metrics.Histogram = new Histogram
            {
                Current  = currentNifti,
                Prior    = priorNifti,
                Increase = increaseNifti,
                Decrease = decreaseNifti
            };
            Metrics.ResultsSlides = new System.Drawing.Bitmap[] { Metrics.Histogram.GenerateSlide() };

            IsComplete = true;

            return(Metrics);
        }
Пример #2
0
        public INifti <float> Classify(INifti <float> prior, INifti <float> current)
        {
            var output = MSCompare.CompareMSLesionIncrease(prior, current);

            return(output);
        }