1
module ParasitemiaUI.Analysis
7 open System.Windows.Media
8 open System.Windows.Markup
9 open System.Windows.Shapes
10 open System.Windows.Controls
11 open System.Diagnostics
12 open Microsoft.Win32 // For the common dialogs.
16 open ParasitemiaCore.UnitsOfMeasure
17 open ParasitemiaCore.Config
21 let showWindow (parent
: Window) (state
: State.State) : bool =
22 let win = Views.AnalysisWindow()
23 win.Root.Owner <- parent
24 win.Root.Left <- (if parent
.WindowState = WindowState.Maximized then 0. else parent.Left) + parent.ActualWidth / 2. - win.Root.Width / 2.
25 win.Root.Top <- (if parent.WindowState = WindowState.Maximized then 0. else parent.Top) + parent.ActualHeight / 2. - win.Root.Height / 2.
28 { new Logger.IListener with
29 member this
.NewEntry severity mess
=
30 win.Root.Dispatcher.Invoke(fun () ->
31 win.textLog
.Inlines.Add(Documents.Run(mess
))
32 win.textLog
.Inlines.Add(Documents.LineBreak())
33 win.scrollLog
.ScrollToBottom()) }
35 Logger.Log.AddListener(logListener)
39 let parseAndValidatePPI (input
: string) : float option =
40 match Double.TryParse(input
) with
41 | true, value
when value
>= minPPI && value
<= maxPPI -> Some value
44 let monitor = Object()
45 let mutable atLeastOneAnalysisPerformed = false
46 let mutable analysisPerformed = false
47 let mutable analysisCancelled = false
49 let updateSourceImages () =
50 win.stackSourceImagesSelection
.Children.Clear()
51 let width = int win.stackSourceImagesSelection
.ActualWidth
52 for srcImg
in state
.SourceImages do
53 let imageSourceSelection = Views.ImageSourceSelection(Tag = srcImg
, Margin = Thickness(3.))
54 imageSourceSelection.Tag <- srcImg
56 imageSourceSelection.txtImageNumber
.Text <- srcImg
.num
.ToString()
57 let height = srcImg
.img
.Height * width / srcImg
.img
.Width
58 imageSourceSelection.imagePreview
.Source <- BitmapSourceConvert.ToBitmapSource(srcImg
.img
.Resize(width, height, Emgu.CV.CvEnum.Inter.Cubic))
59 imageSourceSelection.chkSelection
.IsChecked <- Nullable<bool>(srcImg
.dateLastAnalysis
.Ticks = 0L)
60 imageSourceSelection.lblDateLastAnalysis
.Content <- if srcImg
.dateLastAnalysis
.Ticks = 0L then "<Never>" else srcImg.dateLastAnalysis
.ToString()
62 imageSourceSelection.txtResolution
.Text <- if srcImg.dateLastAnalysis
.Ticks = 0L then "" else srcImg.config
.Parameters.resolution
.ToString()
64 for ppi
in Utils.predefinedPPI
do
66 menu.Header <- ppi
.ToString()
67 menu.Click.AddHandler(fun obj args
-> imageSourceSelection.txtResolution
.Text <- ppi
.ppi
.ToString())
68 imageSourceSelection.predefinedValuesMenu
.Items.Add(menu) |> ignore
70 imageSourceSelection.butPPICalculator
.Click.AddHandler(fun obj args
->
71 match PPICalculator.showWindow win.Root with
72 | Some resolution
-> imageSourceSelection.txtResolution
.Text <- resolution
.ToString()
75 imageSourceSelection.txtResolution
.PreviewTextInput.AddHandler(fun obj args
->
76 let text = imageSourceSelection.txtResolution
.Text + args
.Text
77 args
.Handled <- match parseAndValidatePPI text with Some _ -> false | None -> true)
79 imageSourceSelection.imagePreview
.MouseLeftButtonDown.AddHandler(fun obj args
->
80 let checkbox = imageSourceSelection.chkSelection
81 checkbox.IsChecked <- Nullable<bool>(not
(checkbox.IsChecked.HasValue && checkbox.IsChecked.Value)))
83 win.stackSourceImagesSelection
.Children.Add(imageSourceSelection) |> ignore
85 // Get the new parameters for each image. If an error occurs then 'None' is returned and a message box is displayed.
86 // The boolean is 'true' if the image is selected (checked).
87 let getInputImagesParameters () : (SourceImage * bool * Parameters) list
option =
88 let sourceImagesControls = win.stackSourceImagesSelection
.Children |> Seq.cast
<Views.ImageSourceSelection>
89 let parameters = seq
{
90 for srcImgCtrl
in sourceImagesControls do
91 let srcImg = srcImgCtrl
.Tag :?> SourceImage
92 let isChecked = srcImgCtrl
.chkSelection
.IsChecked
93 match parseAndValidatePPI srcImgCtrl
.txtResolution
.Text with
95 yield
Some (srcImg, isChecked.HasValue && isChecked.Value, { srcImg.config
.Parameters with resolution
= resolution
* 1.<ppi
> })
97 MessageBox.Show(sprintf
"No resolution defined for the image number %d" srcImg.num
, "No resolution defined", MessageBoxButton.OK, MessageBoxImage.Information) |> ignore
98 yield
None } |> Seq.takeWhile
(fun e
-> e
.IsSome) |> Seq.map
(fun e
-> e
.Value) |> List.ofSeq
99 if parameters.Count() <> sourceImagesControls.Count()
103 win.butClose
.Click.AddHandler(fun obj args
-> win.Root.Close())
105 win.butStart
.Click.AddHandler(fun obj args
->
106 match getInputImagesParameters () with
107 | Some imagesParameters
->
108 let imagesToProcess = [
109 for srcImg, selected, parameters in imagesParameters
do
110 srcImg.config
.Parameters <- parameters // Save parameters.
112 then yield
srcImg.num
.ToString(), srcImg.config
, srcImg.img
]
114 if imagesToProcess.IsEmpty
116 MessageBox.Show("No image selected", "Cannot start analysis", MessageBoxButton.OK, MessageBoxImage.Information) |> ignore
118 win.stackSourceImagesSelection
.IsEnabled <- false
119 analysisPerformed <- false
120 win.butStart
.IsEnabled <- false
121 win.butClose
.Content <- "Abort"
125 ParasitemiaCore.Analysis.doMultipleAnalysis
127 (Some (fun progress
-> win.Root.Dispatcher.Invoke(fun () -> win.progress
.Value <- float progress); not
analysisCancelled))
131 match maybeResults with
133 for id
, cells
in results
do
134 state
.SetResult (int id) cells
135 Logger.Log.User("All analyses terminated successfully")
136 atLeastOneAnalysisPerformed <- true
137 analysisPerformed <- true
139 Logger.Log.User("Analysis aborted")
141 win.Root.Dispatcher.Invoke(fun () ->
142 win.progress.Value <- if maybeResults.IsSome then 100. else 0.
143 win.stackSourceImagesSelection
.IsEnabled <- true
144 win.butStart
.IsEnabled <- true
145 win.butClose
.Content <- "Close"
146 updateSourceImages ()))
150 win.Root.Loaded.AddHandler(fun obj args
-> updateSourceImages ())
152 win.Root.ShowDialog() |> ignore
154 Logger.Log.RmListener(logListener)
156 lock
monitor (fun () ->
157 if not
analysisPerformed
159 // To cancel the current analysis if one is running on the next call to the progress function.
160 analysisCancelled <- true
161 atLeastOneAnalysisPerformed)