+++ /dev/null
-module Parasitemia.GUI.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 UnitsOfMeasure
-open 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"
-
- Utils.log <- (fun mess -> window.Root.Dispatcher.Invoke(fun () ->
- textLog.Inlines.Add(Documents.Run(mess))
- textLog.Inlines.Add(Documents.LineBreak())
- scrollLog.ScrollToBottom()))
-
- 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.<ppi> }
- | 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<bool>(srcImg.dateLastAnalysis.Ticks = 0L)
- imageSourceSelection.lblDateLastAnalysis.Content <- if srcImg.dateLastAnalysis.Ticks = 0L then "<Never>" 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<bool>(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<Views.ImageSourceSelection> 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 =
- ImageAnalysis.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 ())
-
- Utils.log "All analyses terminated successfully"
- atLeastOneAnalysisPerformed <- true
- analysisPerformed <- true)
- } |> Async.Start)
-
- window.Root.Loaded.AddHandler(fun obj args -> updateSourceImages ())
-
- window.Root.ShowDialog() |> ignore
-
- lock monitor (fun () ->
- if not analysisPerformed
- then
- analysisCancelled <- true
- atLeastOneAnalysisPerformed)
\ No newline at end of file