X-Git-Url: http://git.euphorik.ch/?p=master-thesis.git;a=blobdiff_plain;f=Parasitemia%2FParasitemiaUI%2FAnalysis.fs;h=e276be6232daede51dd7be603af3c5c7823290e0;hp=24f9adbcaa743661dbebb0243cb2f5f80f1c13b0;hb=e8d14548fc5b127970fccb19bad146512f7ac6d9;hpb=3990946e49fe34e9adcf0e04b0418cd16676e6fe diff --git a/Parasitemia/ParasitemiaUI/Analysis.fs b/Parasitemia/ParasitemiaUI/Analysis.fs index 24f9adb..e276be6 100644 --- a/Parasitemia/ParasitemiaUI/Analysis.fs +++ b/Parasitemia/ParasitemiaUI/Analysis.fs @@ -18,39 +18,31 @@ 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 stackSourceImagesSelection: StackPanel = ctrl "stackSourceImagesSelection" - let progressBar: ProgressBar = ctrl "progress" - let textLog: TextBlock = ctrl "textLog" - let scrollLog: ScrollViewer = ctrl "scrollLog" +let showWindow (parent : Window) (state : State.State) : bool = + let win = Views.AnalysisWindow() + win.Owner <- parent + win.Left <- (if parent.WindowState = WindowState.Maximized then 0. else parent.Left) + parent.ActualWidth / 2. - win.Width / 2. + win.Top <- (if parent.WindowState = WindowState.Maximized then 0. else parent.Top) + parent.ActualHeight / 2. - win.Height / 2. 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()) } + { + new Logger.IListener with + member this.NewEntry severity _header mess = + win.Dispatcher.Invoke(fun () -> + win.textLog.Inlines.Add(Documents.Run(mess)) + win.textLog.Inlines.Add(Documents.LineBreak()) + win.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 parseAndValidatePPI (input : string) : float option = + match Double.TryParse(input) with + | true, value when value >= minPPI && value <= maxPPI -> Some value + | _ -> None let monitor = Object() let mutable atLeastOneAnalysisPerformed = false @@ -58,8 +50,8 @@ let showWindow (parent: Window) (state: State.State) : bool = let mutable analysisCancelled = false let updateSourceImages () = - stackSourceImagesSelection.Children.Clear() - let width = int stackSourceImagesSelection.ActualWidth + win.stackSourceImagesSelection.Children.Clear() + let width = int win.stackSourceImagesSelection.ActualWidth for srcImg in state.SourceImages do let imageSourceSelection = Views.ImageSourceSelection(Tag = srcImg, Margin = Thickness(3.)) imageSourceSelection.Tag <- srcImg @@ -71,8 +63,17 @@ let showWindow (parent: Window) (state: State.State) : bool = imageSourceSelection.lblDateLastAnalysis.Content <- if srcImg.dateLastAnalysis.Ticks = 0L then "" else srcImg.dateLastAnalysis.ToString() imageSourceSelection.txtResolution.Text <- if srcImg.dateLastAnalysis.Ticks = 0L then "" else srcImg.config.Parameters.resolution.ToString() - imageSourceSelection.menuZoom50X.Click.AddHandler(fun obj args -> imageSourceSelection.txtResolution.Text <- "230000") - imageSourceSelection.menuZoom100X.Click.AddHandler(fun obj args -> imageSourceSelection.txtResolution.Text <- "460000") + + for ppi in Utils.predefinedPPI do + let menu = MenuItem() + menu.Header <- ppi.ToString() + menu.Click.AddHandler(fun obj args -> imageSourceSelection.txtResolution.Text <- ppi.ppi.ToString()) + imageSourceSelection.predefinedValuesMenu.Items.Add(menu) |> ignore + + imageSourceSelection.butPPICalculator.Click.AddHandler(fun obj args -> + match PPICalculator.showWindow win with + | Some resolution -> imageSourceSelection.txtResolution.Text <- resolution.ToString() + | None -> ()) imageSourceSelection.txtResolution.PreviewTextInput.AddHandler(fun obj args -> let text = imageSourceSelection.txtResolution.Text + args.Text @@ -82,76 +83,91 @@ let showWindow (parent: Window) (state: State.State) : bool = let checkbox = imageSourceSelection.chkSelection checkbox.IsChecked <- Nullable(not (checkbox.IsChecked.HasValue && checkbox.IsChecked.Value))) - stackSourceImagesSelection.Children.Add(imageSourceSelection) |> ignore + win.stackSourceImagesSelection.Children.Add(imageSourceSelection) |> ignore // Get the new parameters for each image. If an error occurs then 'None' is returned and a message box is displayed. // The boolean is 'true' if the image is selected (checked). let getInputImagesParameters () : (SourceImage * bool * Parameters) list option = - let sourceImagesControls = stackSourceImagesSelection.Children |> Seq.cast - let parameters = seq { - for srcImgCtrl in sourceImagesControls do - let srcImg = srcImgCtrl.Tag :?> SourceImage - let isChecked = srcImgCtrl.chkSelection.IsChecked - match parseAndValidatePPI srcImgCtrl.txtResolution.Text with - | Some resolution -> - yield Some (srcImg, isChecked.HasValue && isChecked.Value, { srcImg.config.Parameters with resolution = resolution * 1. }) - | None -> - MessageBox.Show(sprintf "No resolution defined for the image number %d" srcImg.num, "No resolution defined", MessageBoxButton.OK, MessageBoxImage.Information) |> ignore - yield None } |> Seq.takeWhile (fun e -> e.IsSome) |> Seq.map (fun e -> e.Value) |> List.ofSeq - if parameters.Count() <> sourceImagesControls.Count() - then None - else Some parameters - - butClose.Click.AddHandler(fun obj args -> window.Root.Close()) - - butStart.Click.AddHandler(fun obj args -> + let sourceImagesControls = win.stackSourceImagesSelection.Children |> Seq.cast + let parameters = + seq { + for srcImgCtrl in sourceImagesControls do + let srcImg = srcImgCtrl.Tag :?> SourceImage + let isChecked = srcImgCtrl.chkSelection.IsChecked + match parseAndValidatePPI srcImgCtrl.txtResolution.Text with + | Some resolution -> + yield Some (srcImg, isChecked.HasValue && isChecked.Value, { srcImg.config.Parameters with resolution = resolution * 1. }) + | None -> + MessageBox.Show(sprintf "No resolution defined for the image number %d" srcImg.num, "No resolution defined", MessageBoxButton.OK, MessageBoxImage.Information) |> ignore + yield None + } |> Seq.takeWhile (fun e -> e.IsSome) |> Seq.map (fun e -> e.Value) |> List.ofSeq + + if parameters.Count() <> sourceImagesControls.Count() then + None + else + Some parameters + + win.butClose.Click.AddHandler(fun obj args -> win.Close()) + + win.butStart.Click.AddHandler(fun obj args -> match getInputImagesParameters () with | Some imagesParameters -> - let imagesToProcess = [ - for srcImg, selected, parameters in imagesParameters do - srcImg.config.Parameters <- parameters // Save parameters. - if selected - then yield srcImg.num.ToString(), srcImg.config, srcImg.img ] - - if imagesToProcess.IsEmpty - then + let imagesToProcess = + [ + for srcImg, selected, parameters in imagesParameters do + srcImg.config.Parameters <- parameters // Save parameters. + if selected then + 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 + win.stackSourceImagesSelection.IsEnabled <- false analysisPerformed <- false - butStart.IsEnabled <- false - butClose.Content <- "Abort" + win.butStart.IsEnabled <- false + win.butClose.Content <- "Abort" + async { - let results = + let maybeResults = ParasitemiaCore.Analysis.doMultipleAnalysis imagesToProcess - (Some (fun progress -> window.Root.Dispatcher.Invoke(fun () -> progressBar.Value <- float progress))) + (Some (fun progress -> win.Dispatcher.Invoke(fun () -> win.progress.Value <- float progress); not analysisCancelled)) lock monitor ( fun() -> - if not analysisCancelled - then + match maybeResults with + | Some results -> 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") + Logger.Log.Info "All analyses terminated successfully" atLeastOneAnalysisPerformed <- true - analysisPerformed <- true) + analysisPerformed <- true + | None -> + Logger.Log.Info "Analysis aborted" + + win.Dispatcher.Invoke(fun () -> + win.progress.Value <- if maybeResults.IsSome then 100. else 0. + win.stackSourceImagesSelection.IsEnabled <- true + win.butStart.IsEnabled <- true + win.butClose.Content <- "Close" + updateSourceImages () + ) + ) } |> Async.Start - | _ -> ()) + | _ -> () + ) - window.Root.Loaded.AddHandler(fun obj args -> updateSourceImages ()) + win.Loaded.AddHandler(fun obj args -> updateSourceImages ()) - window.Root.ShowDialog() |> ignore + win.ShowDialog() |> ignore Logger.Log.RmListener(logListener) - lock monitor (fun () -> - if not analysisPerformed - then + lock monitor ( + fun () -> + if not analysisPerformed then + // To cancel the current analysis if one is running on the next call to the progress function. analysisCancelled <- true - atLeastOneAnalysisPerformed) + atLeastOneAnalysisPerformed + )