module ParasitemiaUI.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 ParasitemiaUIControls
open ParasitemiaCore.UnitsOfMeasure
open ParasitemiaCore.Config
open Types
let showWindow (parent : Window) (state : State.State) : bool =
- let win = Views.AnalysisWindow()
+ let win = AnalysisWindow ()
win.Owner <- parent
win.Left <- (if parent.WindowState = WindowState.Maximized then 0. else parent.Left) + parent.ActualWidth / 2. - win.Width / 2.
win.Top <- (if parent.WindowState = WindowState.Maximized then 0. else parent.Top) + parent.ActualHeight / 2. - win.Height / 2.
{
new Logger.IListener with
member this.NewEntry severity _header mess =
- win.Dispatcher.Invoke(fun () ->
- win.textLog.Inlines.Add(Documents.Run(mess))
- win.textLog.Inlines.Add(Documents.LineBreak())
- win.scrollLog.ScrollToBottom()
+ win.Dispatcher.Invoke (
+ fun () ->
+ win.textLog.Inlines.Add (Documents.Run mess)
+ win.textLog.Inlines.Add (Documents.LineBreak ())
+ win.scrollLog.ScrollToBottom ()
)
}
- Logger.Log.AddListener(logListener)
+ Logger.Log.AddListener (logListener)
let minPPI = 1.
let maxPPI = 10e6
let parseAndValidatePPI (input : string) : float option =
- match Double.TryParse(input) with
+ match Double.TryParse input with
| true, value when value >= minPPI && value <= maxPPI -> Some value
| _ -> None
- let monitor = Object()
+ let monitor = Object ()
let mutable atLeastOneAnalysisPerformed = false
let mutable analysisPerformed = false
let mutable analysisCancelled = false
let updateSourceImages () =
- win.stackSourceImagesSelection.Children.Clear()
+ win.stackSourceImagesSelection.Children.Clear ()
let width = int win.stackSourceImagesSelection.ActualWidth
for srcImg in state.SourceImages do
- let imageSourceSelection = Views.ImageSourceSelection(Tag = srcImg, Margin = Thickness(3.))
+ let imageSourceSelection = ImageSourceSelection (Tag = srcImg, Margin = Thickness 3.)
imageSourceSelection.Tag <- srcImg
- 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.txtImageNumber.Text <- string srcImg.RomanNum
+ 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 string srcImg.DateLastAnalysis
- imageSourceSelection.txtResolution.Text <- if srcImg.dateLastAnalysis.Ticks = 0L then "" else srcImg.config.Parameters.resolution.ToString()
+ imageSourceSelection.txtResolution.Text <- if srcImg.DateLastAnalysis.Ticks = 0L then "" else string srcImg.Config.Parameters.resolution
for ppi in Utils.predefinedPPI do
- let menu = MenuItem()
- menu.Header <- ppi.ToString()
- menu.Click.AddHandler(fun obj args -> imageSourceSelection.txtResolution.Text <- ppi.ppi.ToString())
- imageSourceSelection.predefinedValuesMenu.Items.Add(menu) |> ignore
-
- imageSourceSelection.butPPICalculator.Click.AddHandler(fun obj args ->
- match PPICalculator.showWindow win with
- | Some resolution -> imageSourceSelection.txtResolution.Text <- resolution.ToString()
- | None -> ())
-
- 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)))
-
- win.stackSourceImagesSelection.Children.Add(imageSourceSelection) |> ignore
+ let menu = MenuItem ()
+ menu.Header <- string ppi
+ menu.Click.AddHandler (fun obj args -> imageSourceSelection.txtResolution.Text <- string ppi.ppi)
+ imageSourceSelection.predefinedValuesMenu.Items.Add menu |> ignore
+
+ imageSourceSelection.butPPICalculator.Click.AddHandler (
+ fun obj args ->
+ match PPICalculator.showWindow win with
+ | Some resolution -> imageSourceSelection.txtResolution.Text <- string resolution
+ | None -> ()
+ )
+
+ 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))
+ )
+
+ win.stackSourceImagesSelection.Children.Add (imageSourceSelection) |> ignore
// Get the new parameters for each image. If an error occurs then 'None' is returned and a message box is displayed.
// The boolean is 'true' if the image is selected (checked).
let getInputImagesParameters () : (SourceImage * bool * Parameters) list option =
- let sourceImagesControls = win.stackSourceImagesSelection.Children |> Seq.cast<Views.ImageSourceSelection>
+ let sourceImagesControls = win.stackSourceImagesSelection.Children |> Seq.cast<ImageSourceSelection>
let parameters =
seq {
for srcImgCtrl in sourceImagesControls do
let isChecked = srcImgCtrl.chkSelection.IsChecked
match parseAndValidatePPI srcImgCtrl.txtResolution.Text with
| Some resolution ->
- yield Some (srcImg, isChecked.HasValue && isChecked.Value, { srcImg.config.Parameters with resolution = resolution * 1.<ppi> })
+ Some (srcImg, isChecked.HasValue && isChecked.Value, { srcImg.Config.Parameters with resolution = resolution * 1.<ppi> })
| None ->
- MessageBox.Show(sprintf "No resolution defined for the image number %d" srcImg.num, "No resolution defined", MessageBoxButton.OK, MessageBoxImage.Information) |> ignore
- yield None
+ MessageBox.Show (sprintf "No resolution defined for the image number %d" srcImg.Num, "No resolution defined", MessageBoxButton.OK, MessageBoxImage.Information) |> ignore
+ None
} |> Seq.takeWhile (fun e -> e.IsSome) |> Seq.map (fun e -> e.Value) |> List.ofSeq
- if parameters.Count() <> sourceImagesControls.Count() then
+ if parameters.Count () <> sourceImagesControls.Count () then
None
else
Some parameters
- win.butClose.Click.AddHandler(fun obj args -> win.Close())
-
- win.butStart.Click.AddHandler(fun obj args ->
- match getInputImagesParameters () with
- | Some imagesParameters ->
- let imagesToProcess =
- [
- for srcImg, selected, parameters in imagesParameters do
- srcImg.config.Parameters <- parameters // Save parameters.
- if selected then
- 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
- win.stackSourceImagesSelection.IsEnabled <- false
- analysisPerformed <- false
- win.butStart.IsEnabled <- false
- win.butClose.Content <- "Abort"
-
- async {
- let maybeResults =
- ParasitemiaCore.Analysis.doMultipleAnalysis
- imagesToProcess
- (Some (fun progress -> win.Dispatcher.Invoke(fun () -> win.progress.Value <- float progress); not analysisCancelled))
-
- lock monitor (
- fun() ->
- match maybeResults with
- | Some results ->
- for id, cells in results do
- state.SetResult (int id) cells
- Logger.Log.Info "All analyses terminated successfully"
- atLeastOneAnalysisPerformed <- true
- analysisPerformed <- true
- | None ->
- Logger.Log.Info "Analysis aborted"
-
- win.Dispatcher.Invoke(fun () ->
- win.progress.Value <- if maybeResults.IsSome then 100. else 0.
- win.stackSourceImagesSelection.IsEnabled <- true
- win.butStart.IsEnabled <- true
- win.butClose.Content <- "Close"
- updateSourceImages ()
- )
- )
- } |> Async.Start
- | _ -> ()
+ win.butClose.Click.AddHandler (fun obj args -> win.Close ())
+
+ win.butStart.Click.AddHandler (
+ fun obj args ->
+ match getInputImagesParameters () with
+ | Some imagesParameters ->
+ let imagesToProcess =
+ [
+ for srcImg, selected, parameters in imagesParameters do
+ srcImg.Config.Parameters <- parameters // Save parameters.
+ if selected then
+ string srcImg.RomanNum, srcImg.Config, srcImg.Img
+ ]
+
+ if imagesToProcess.IsEmpty then
+ MessageBox.Show ("No image selected", "Cannot start analysis", MessageBoxButton.OK, MessageBoxImage.Information) |> ignore
+ else
+ win.stackSourceImagesSelection.IsEnabled <- false
+ analysisPerformed <- false
+ win.butStart.IsEnabled <- false
+ win.textLog.Text <- ""
+ win.butClose.Content <- "Abort"
+
+ async {
+ let maybeResults =
+ ParasitemiaCore.Analysis.doMultipleAnalysis
+ imagesToProcess
+ (Some (fun progress -> win.Dispatcher.Invoke (fun () -> win.progress.Value <- float progress); not analysisCancelled))
+
+ lock monitor (
+ fun () ->
+ match maybeResults with
+ | Some results ->
+ for id, cells in results do
+ state.SetResult id cells
+ Logger.Log.Info "All analyses terminated successfully"
+ atLeastOneAnalysisPerformed <- true
+ analysisPerformed <- true
+ | None ->
+ Logger.Log.Info "Analysis aborted"
+
+ win.Dispatcher.Invoke (
+ fun () ->
+ win.progress.Value <- if maybeResults.IsSome then 100. else 0.
+ win.stackSourceImagesSelection.IsEnabled <- true
+ win.butStart.IsEnabled <- true
+ win.butClose.Content <- "Close"
+ updateSourceImages ()
+ )
+ )
+ } |> Async.Start
+ | _ -> ()
)
- win.Loaded.AddHandler(fun obj args -> updateSourceImages ())
+ win.Loaded.AddHandler (fun obj args -> updateSourceImages ())
- win.ShowDialog() |> ignore
+ win.ShowDialog () |> ignore
- Logger.Log.RmListener(logListener)
+ Logger.Log.RmListener (logListener)
lock monitor (
fun () ->