X-Git-Url: http://git.euphorik.ch/?p=master-thesis.git;a=blobdiff_plain;f=Parasitemia%2FParasitemiaUI%2FAnalysis.fs;fp=Parasitemia%2FParasitemiaUI%2FAnalysis.fs;h=40fd30342c7d736fa9b83f9ca4198e690301c6d3;hp=0000000000000000000000000000000000000000;hb=4bfa3cbdc6145e6944f02e24829ab2ef3a851ac1;hpb=48ecdfc43001c444eff6ad442986049384674af2 diff --git a/Parasitemia/ParasitemiaUI/Analysis.fs b/Parasitemia/ParasitemiaUI/Analysis.fs new file mode 100644 index 0000000..40fd303 --- /dev/null +++ b/Parasitemia/ParasitemiaUI/Analysis.fs @@ -0,0 +1,144 @@ +module ParasitemiaUI.Analysis + +open System +open System.IO +open System.Linq +open System.Windows +open System.Windows.Media +open System.Windows.Markup +open System.Windows.Shapes +open System.Windows.Controls +open System.Diagnostics +open Microsoft.Win32 // For the common dialogs. + +open Emgu.CV.WPF + +open ParasitemiaCore.UnitsOfMeasure +open ParasitemiaCore.Config + +open Types + +let showWindow (parent: Window) (state: State.State) : bool = + let window = Views.AnalysisWindow() + window.Root.Owner <- parent + window.Root.Left <- parent.Left + parent.ActualWidth / 2. - window.Root.Width / 2. + window.Root.Top <- parent.Top + parent.ActualHeight / 2. - window.Root.Height / 2. + + let ctrl (name: string): 'a = window.Root.FindName(name) :?> 'a + + let butClose: Button = ctrl "butClose" + let butStart: Button = ctrl "butStart" + + let stackImagesSourceSelection: StackPanel = ctrl "stackImagesSourceSelection" + let progressBar: ProgressBar = ctrl "progress" + let textLog: TextBlock = ctrl "textLog" + let scrollLog: ScrollViewer = ctrl "scrollLog" + + let logListener = + { new Logger.IListener with + member this.NewEntry severity mess = + window.Root.Dispatcher.Invoke(fun () -> + textLog.Inlines.Add(Documents.Run(mess)) + textLog.Inlines.Add(Documents.LineBreak()) + scrollLog.ScrollToBottom()) } + + Logger.Log.AddListener(logListener) + + let minPPI = 1. + let maxPPI = 10e6 + let parseAndValidatePPI (input: string) : float option = + let res = ref 0. + if Double.TryParse(input, res) && !res >= minPPI && !res <= maxPPI + then Some !res + else None + + let monitor = Object() + let mutable atLeastOneAnalysisPerformed = false + let mutable analysisPerformed = false + let mutable analysisCancelled = false + + let updateSourceImages () = + stackImagesSourceSelection.Children.Clear() + let width = int stackImagesSourceSelection.ActualWidth + for srcImg in state.SourceImages do + let imageSourceSelection = Views.ImageSourceSelection(Tag = srcImg, Margin = Thickness(3.)) + + let updateResolution () = + match parseAndValidatePPI imageSourceSelection.txtResolution.Text with + | Some resolution -> srcImg.config.Parameters <- { srcImg.config.Parameters with resolution = resolution * 1. } + | None -> () + + imageSourceSelection.txtImageNumber.Text <- srcImg.num.ToString() + let height = srcImg.img.Height * width / srcImg.img.Width + imageSourceSelection.imagePreview.Source <- BitmapSourceConvert.ToBitmapSource(srcImg.img.Resize(width, height, Emgu.CV.CvEnum.Inter.Cubic)) + imageSourceSelection.chkSelection.IsChecked <- Nullable(srcImg.dateLastAnalysis.Ticks = 0L) + imageSourceSelection.lblDateLastAnalysis.Content <- if srcImg.dateLastAnalysis.Ticks = 0L then "" else srcImg.dateLastAnalysis.ToString() + + imageSourceSelection.txtResolution.Text <- srcImg.config.Parameters.resolution.ToString() + imageSourceSelection.menuZoom50X.Click.AddHandler(fun obj args -> imageSourceSelection.txtResolution.Text <- "230000"; updateResolution ()) + imageSourceSelection.menuZoom100X.Click.AddHandler(fun obj args -> imageSourceSelection.txtResolution.Text <- "460000"; updateResolution ()) + + imageSourceSelection.txtResolution.PreviewTextInput.AddHandler(fun obj args -> + let text = imageSourceSelection.txtResolution.Text + args.Text + args.Handled <- match parseAndValidatePPI text with Some _ -> false | None -> true) + + imageSourceSelection.imagePreview.MouseLeftButtonDown.AddHandler(fun obj args -> + let checkbox = imageSourceSelection.chkSelection + checkbox.IsChecked <- Nullable(not (checkbox.IsChecked.HasValue && checkbox.IsChecked.Value))) + + imageSourceSelection.txtResolution.LostFocus.AddHandler(fun obj args -> updateResolution ()) + + stackImagesSourceSelection.Children.Add(imageSourceSelection) |> ignore + + butClose.Click.AddHandler(fun obj args -> window.Root.Close()) + + butStart.Click.AddHandler(fun obj args -> + let imagesToProcess = [ + for imageSelection in stackImagesSourceSelection.Children |> Seq.cast do + let chk = imageSelection.chkSelection.IsChecked + if chk.HasValue && chk.Value + then + let srcImg = imageSelection.Tag :?> SourceImage + yield srcImg.num.ToString(), srcImg.config, srcImg.img ] + + if imagesToProcess.IsEmpty + then + MessageBox.Show("No image selected", "Cannot start analysis", MessageBoxButton.OK, MessageBoxImage.Information) |> ignore + else + analysisPerformed <- false + butStart.IsEnabled <- false + butClose.Content <- "Abort" + async { + let results = + ParasitemiaCore.Analysis.doMultipleAnalysis + imagesToProcess + (Some (fun progress -> window.Root.Dispatcher.Invoke(fun () -> progressBar.Value <- float progress))) + + lock monitor ( + fun() -> + if not analysisCancelled + then + for id, cells in results do + state.SetResult (int id) cells + + window.Root.Dispatcher.Invoke(fun () -> + butStart.IsEnabled <- true + butClose.Content <- "Close" + updateSourceImages ()) + + Logger.Log.User("All analyses terminated successfully") + atLeastOneAnalysisPerformed <- true + analysisPerformed <- true) + } |> Async.Start) + + window.Root.Loaded.AddHandler(fun obj args -> updateSourceImages ()) + + window.Root.ShowDialog() |> ignore + + Logger.Log.RmListener(logListener) + + lock monitor (fun () -> + if not analysisPerformed + then + analysisCancelled <- true + atLeastOneAnalysisPerformed)