1
module ParasitemiaUI.Analysis
6 open System.Windows.Controls
8 open ParasitemiaUIControls
9 open ParasitemiaCore.UnitsOfMeasure
10 open ParasitemiaCore.Config
14 let showWindow (parent
: Window) (state
: State.State) : bool =
15 let win = AnalysisWindow ()
17 win.Left <- (if parent
.WindowState = WindowState.Maximized then 0. else parent.Left) + parent.ActualWidth / 2. - win.Width / 2.
18 win.Top <- (if parent.WindowState = WindowState.Maximized then 0. else parent.Top) + parent.ActualHeight / 2. - win.Height / 2.
22 new Logger.IListener with
23 member this
.NewEntry severity header mess
=
24 win.Dispatcher.Invoke (
26 win.textLog
.Inlines.Add (Documents.Run mess
)
27 win.textLog
.Inlines.Add (Documents.LineBreak ())
28 win.scrollLog
.ScrollToBottom ()
32 Logger.Log.AddListener (logListener)
36 let parseAndValidatePPI (input
: string) : float option =
37 match Double.TryParse input with
38 | true, value
when value
>= minPPI && value
<= maxPPI -> Some value
41 let monitor = Object ()
42 let mutable atLeastOneAnalysisPerformed = false
43 let mutable analysisPerformed = false
44 let mutable analysisCancelled = false
46 let updateSourceImages () =
47 win.stackSourceImagesSelection
.Children.Clear ()
48 let width = int win.stackSourceImagesSelection
.ActualWidth
49 for srcImg
in state
.SourceImages do
50 let imageSourceSelection = ImageSourceSelection (Tag = srcImg
, Margin = Thickness 3.)
51 imageSourceSelection.Tag <- srcImg
53 imageSourceSelection.txtImageNumber
.Text <- string srcImg
.RomanNum
54 let height = srcImg
.Img.Height * width / srcImg
.Img.Width
55 imageSourceSelection.imagePreview
.Source <- BitmapSourceConvert.ToBitmapSource (srcImg
.Img.Resize (width, height, Emgu.CV.CvEnum.Inter.Cubic))
56 imageSourceSelection.chkSelection
.IsChecked <- Nullable<bool> (srcImg
.DateLastAnalysis.Ticks = 0L)
57 imageSourceSelection.lblDateLastAnalysis
.Content <- if srcImg
.DateLastAnalysis.Ticks = 0L then "<Never>" else string srcImg
.DateLastAnalysis
59 imageSourceSelection.txtResolution
.Text <- if srcImg
.DateLastAnalysis.Ticks = 0L then "" else string srcImg
.Config.Parameters.resolution
61 for ppi
in Utils.predefinedPPI
do
62 let menu = MenuItem ()
63 menu.Header <- string ppi
64 menu.Click.AddHandler (fun obj args
-> imageSourceSelection.txtResolution
.Text <- string ppi
.ppi
)
65 imageSourceSelection.predefinedValuesMenu
.Items.Add menu |> ignore
67 imageSourceSelection.butPPICalculator
.Click.AddHandler (
69 match PPICalculator.showWindow win with
70 | Some resolution
-> imageSourceSelection.txtResolution
.Text <- string resolution
74 imageSourceSelection.txtResolution
.PreviewTextInput.AddHandler (
76 let text = imageSourceSelection.txtResolution
.Text + args
.Text
77 args
.Handled <- match parseAndValidatePPI text with Some _ -> false | None -> true
80 imageSourceSelection.imagePreview
.MouseLeftButtonDown.AddHandler (
82 let checkbox = imageSourceSelection.chkSelection
83 checkbox.IsChecked <- Nullable<bool> (not
(checkbox.IsChecked.HasValue && checkbox.IsChecked.Value))
86 win.stackSourceImagesSelection
.Children.Add (imageSourceSelection) |> ignore
88 // Get the new parameters for each image. If an error occurs then 'None' is returned and a message box is displayed.
89 // The boolean is 'true' if the image is selected (checked).
90 let getInputImagesParameters () : (SourceImage * bool * Parameters) list
option =
91 let sourceImagesControls = win.stackSourceImagesSelection
.Children |> Seq.cast
<ImageSourceSelection>
94 for srcImgCtrl
in sourceImagesControls do
95 let srcImg = srcImgCtrl
.Tag :?> SourceImage
96 let isChecked = srcImgCtrl
.chkSelection
.IsChecked
97 match parseAndValidatePPI srcImgCtrl
.txtResolution
.Text with
99 Some (srcImg, isChecked.HasValue && isChecked.Value, { srcImg.Config.Parameters with resolution
= resolution
* 1.<ppi
> })
101 MessageBox.Show (sprintf
"No resolution defined for the image number %d" srcImg.Num, "No resolution defined", MessageBoxButton.OK, MessageBoxImage.Information) |> ignore
103 } |> Seq.takeWhile
(fun e
-> e
.IsSome) |> Seq.map
(fun e
-> e
.Value) |> List.ofSeq
105 if parameters.Count () <> sourceImagesControls.Count () then
110 win.butSelectAll
.Click.AddHandler (
112 for srcImgCtrl
in win.stackSourceImagesSelection
.Children |> Seq.cast
<ImageSourceSelection> do
113 srcImgCtrl
.chkSelection
.IsChecked <- true
116 win.butUnselectAll
.Click.AddHandler (
118 for srcImgCtrl
in win.stackSourceImagesSelection
.Children |> Seq.cast
<ImageSourceSelection> do
119 srcImgCtrl
.chkSelection
.IsChecked <- false
122 win.butClose
.Click.AddHandler (fun obj args
-> win.Close ())
124 win.butStart
.Click.AddHandler (
126 match getInputImagesParameters () with
127 | Some imagesParameters
->
128 let imagesToProcess =
130 for srcImg, selected, parameters in imagesParameters
do
131 srcImg.Config.Parameters <- parameters // Save parameters.
133 string srcImg.RomanNum, srcImg.Config, srcImg.Img
136 if imagesToProcess.IsEmpty then
137 MessageBox.Show ("No image selected", "Cannot start analysis", MessageBoxButton.OK, MessageBoxImage.Information) |> ignore
139 win.stackSourceImagesSelection
.IsEnabled <- false
140 win.butSelectAll
.IsEnabled <- false
141 win.butUnselectAll
.IsEnabled <- false
142 analysisPerformed <- false
143 win.butStart
.IsEnabled <- false
144 win.textLog
.Text <- ""
145 win.butClose
.Content <- "Abort"
147 let sw = System.Diagnostics.Stopwatch ()
152 ParasitemiaCore.Analysis.doMultipleAnalysis
154 (Some (fun progress
-> win.Dispatcher.Invoke (fun () -> win.progress
.Value <- float progress); not
analysisCancelled))
158 match maybeResults with
160 for id
, cells
in results
do
161 state
.SetResult id cells
162 Logger.Log.Info $
"All analyses terminated successfully (total time: %d{sw.ElapsedMilliseconds} ms)"
163 atLeastOneAnalysisPerformed <- true
164 analysisPerformed <- true
166 Logger.Log.Info "Analysis aborted"
168 win.Dispatcher.Invoke (
170 win.progress.Value <- if maybeResults.IsSome then 100. else 0.
171 win.stackSourceImagesSelection
.IsEnabled <- true
172 win.butSelectAll
.IsEnabled <- true
173 win.butUnselectAll
.IsEnabled <- true
174 win.butStart
.IsEnabled <- true
175 win.butClose
.Content <- "Close"
176 updateSourceImages ()
183 win.Loaded.AddHandler (fun obj args
-> updateSourceImages ())
185 win.ShowDialog () |> ignore
187 Logger.Log.RemoveListener (logListener)
191 if not
analysisPerformed then
192 // To cancel the current analysis if one is running on the next call to the progress function.
193 analysisCancelled <- true
194 atLeastOneAnalysisPerformed