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 ()
24 win.Left <- (if parent
.WindowState = WindowState.Maximized then 0. else parent.Left) + parent.ActualWidth / 2. - win.Width / 2.
25 win.Top <- (if parent.WindowState = WindowState.Maximized then 0. else parent.Top) + parent.ActualHeight / 2. - win.Height / 2.
29 new Logger.IListener with
30 member this
.NewEntry severity _header mess
=
31 win.Dispatcher.Invoke (
33 win.textLog
.Inlines.Add (Documents.Run mess
)
34 win.textLog
.Inlines.Add (Documents.LineBreak ())
35 win.scrollLog
.ScrollToBottom ()
39 Logger.Log.AddListener (logListener)
43 let parseAndValidatePPI (input
: string) : float option =
44 match Double.TryParse input with
45 | true, value
when value
>= minPPI && value
<= maxPPI -> Some value
48 let monitor = Object ()
49 let mutable atLeastOneAnalysisPerformed = false
50 let mutable analysisPerformed = false
51 let mutable analysisCancelled = false
53 let updateSourceImages () =
54 win.stackSourceImagesSelection
.Children.Clear ()
55 let width = int win.stackSourceImagesSelection
.ActualWidth
56 for srcImg
in state
.SourceImages do
57 let imageSourceSelection = Views.ImageSourceSelection (Tag = srcImg
, Margin = Thickness 3.)
58 imageSourceSelection.Tag <- srcImg
60 imageSourceSelection.txtImageNumber
.Text <- string srcImg
.RomanNum
61 let height = srcImg
.Img.Height * width / srcImg
.Img.Width
62 imageSourceSelection.imagePreview
.Source <- BitmapSourceConvert.ToBitmapSource (srcImg
.Img.Resize (width, height, Emgu.CV.CvEnum.Inter.Cubic))
63 imageSourceSelection.chkSelection
.IsChecked <- Nullable<bool> (srcImg
.DateLastAnalysis.Ticks = 0L)
64 imageSourceSelection.lblDateLastAnalysis
.Content <- if srcImg
.DateLastAnalysis.Ticks = 0L then "<Never>" else string srcImg
.DateLastAnalysis
66 imageSourceSelection.txtResolution
.Text <- if srcImg
.DateLastAnalysis.Ticks = 0L then "" else string srcImg
.Config.Parameters.resolution
68 for ppi
in Utils.predefinedPPI
do
69 let menu = MenuItem ()
70 menu.Header <- string ppi
71 menu.Click.AddHandler (fun obj args
-> imageSourceSelection.txtResolution
.Text <- string ppi
.ppi
)
72 imageSourceSelection.predefinedValuesMenu
.Items.Add menu |> ignore
74 imageSourceSelection.butPPICalculator
.Click.AddHandler (
76 match PPICalculator.showWindow win with
77 | Some resolution
-> imageSourceSelection.txtResolution
.Text <- string resolution
81 imageSourceSelection.txtResolution
.PreviewTextInput.AddHandler (
83 let text = imageSourceSelection.txtResolution
.Text + args
.Text
84 args
.Handled <- match parseAndValidatePPI text with Some _ -> false | None -> true
87 imageSourceSelection.imagePreview
.MouseLeftButtonDown.AddHandler (
89 let checkbox = imageSourceSelection.chkSelection
90 checkbox.IsChecked <- Nullable<bool> (not
(checkbox.IsChecked.HasValue && checkbox.IsChecked.Value))
93 win.stackSourceImagesSelection
.Children.Add (imageSourceSelection) |> ignore
95 // Get the new parameters for each image. If an error occurs then 'None' is returned and a message box is displayed.
96 // The boolean is 'true' if the image is selected (checked).
97 let getInputImagesParameters () : (SourceImage * bool * Parameters) list
option =
98 let sourceImagesControls = win.stackSourceImagesSelection
.Children |> Seq.cast
<Views.ImageSourceSelection>
101 for srcImgCtrl
in sourceImagesControls do
102 let srcImg = srcImgCtrl
.Tag :?> SourceImage
103 let isChecked = srcImgCtrl
.chkSelection
.IsChecked
104 match parseAndValidatePPI srcImgCtrl
.txtResolution
.Text with
106 yield
Some (srcImg, isChecked.HasValue && isChecked.Value, { srcImg.Config.Parameters with resolution
= resolution
* 1.<ppi
> })
108 MessageBox.Show (sprintf
"No resolution defined for the image number %d" srcImg.Num, "No resolution defined", MessageBoxButton.OK, MessageBoxImage.Information) |> ignore
110 } |> Seq.takeWhile
(fun e
-> e
.IsSome) |> Seq.map
(fun e
-> e
.Value) |> List.ofSeq
112 if parameters.Count () <> sourceImagesControls.Count () then
117 win.butClose
.Click.AddHandler (fun obj args
-> win.Close ())
119 win.butStart
.Click.AddHandler (
121 match getInputImagesParameters () with
122 | Some imagesParameters
->
123 let imagesToProcess =
125 for srcImg, selected, parameters in imagesParameters
do
126 srcImg.Config.Parameters <- parameters // Save parameters.
128 yield
string srcImg.RomanNum, srcImg.Config, srcImg.Img
131 if imagesToProcess.IsEmpty then
132 MessageBox.Show ("No image selected", "Cannot start analysis", MessageBoxButton.OK, MessageBoxImage.Information) |> ignore
134 win.stackSourceImagesSelection
.IsEnabled <- false
135 analysisPerformed <- false
136 win.butStart
.IsEnabled <- false
137 win.textLog
.Text <- ""
138 win.butClose
.Content <- "Abort"
142 ParasitemiaCore.Analysis.doMultipleAnalysis
144 (Some (fun progress
-> win.Dispatcher.Invoke (fun () -> win.progress
.Value <- float progress); not
analysisCancelled))
148 match maybeResults with
150 for id
, cells
in results
do
151 state
.SetResult id cells
152 Logger.Log.Info "All analyses terminated successfully"
153 atLeastOneAnalysisPerformed <- true
154 analysisPerformed <- true
156 Logger.Log.Info "Analysis aborted"
158 win.Dispatcher.Invoke (
160 win.progress.Value <- if maybeResults.IsSome then 100. else 0.
161 win.stackSourceImagesSelection
.IsEnabled <- true
162 win.butStart
.IsEnabled <- true
163 win.butClose
.Content <- "Close"
164 updateSourceImages ()
171 win.Loaded.AddHandler (fun obj args
-> updateSourceImages ())
173 win.ShowDialog () |> ignore
175 Logger.Log.RmListener (logListener)
179 if not
analysisPerformed then
180 // To cancel the current analysis if one is running on the next call to the progress function.
181 analysisCancelled <- true
182 atLeastOneAnalysisPerformed