/// <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); }
public INifti <float> Classify(INifti <float> prior, INifti <float> current) { var output = MSCompare.CompareMSLesionIncrease(prior, current); return(output); }