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) (defaultConfig: Config) : bool =
+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.
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"
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 ->
- butStart.IsEnabled <- false
- butClose.Content <- "Abort"
- async {
- let results =
- ImageAnalysis.doMultipleAnalysis
- (state.SourceImages |> Seq.map (fun srcImg -> string srcImg.num, srcImg.img) |> Seq.toList)
- defaultConfig
- (Some (fun progress -> window.Root.Dispatcher.Invoke(fun () -> progressBar.Value <- float progress)))
-
- lock monitor (
- fun() ->
- if not analysisCancelled
- then
- for id, rbcRadius, cells in results do
- state.SetResult (int id) rbcRadius cells
-
- window.Root.Dispatcher.Invoke(fun () ->
- butStart.IsEnabled <- false
- butClose.Content <- "Close")
-
- Utils.log "Analysis terminated successfully"
- analysisPerformed <- true)
- } |> Async.Start)
+ 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
if not analysisPerformed
then
analysisCancelled <- true
- analysisPerformed)
-
-
- (*let results = ImageAnalysis.doMultipleAnalysis (state.SourceImages |> Seq.map (fun srcImg -> string srcImg.num, srcImg.img) |> Seq.toList) defaultConfig
- for id, rbcRadius, cells in results do
- state.SetResult (int id) rbcRadius cells*)
\ No newline at end of file
+ atLeastOneAnalysisPerformed)
\ No newline at end of file