let state = State.State()
let mutable currentScale = 1.
let mutable displayHealthy = false
+ let warningBelowNumberOfRBC = 1000
let menuExit: MenuItem = ctrl "menuExit"
let menuSaveFile: MenuItem = ctrl "menuSave"
let menuSaveAsFile: MenuItem = ctrl "menuSaveAs"
let menuLoadFile: MenuItem = ctrl "menuOpen"
let menuNewFile: MenuItem = ctrl "menuNew"
+ let menuExportResults: MenuItem = ctrl "menuExportResults"
let menuAddSourceImage: MenuItem = ctrl "menuAddSourceImage"
let menuAnalysis: MenuItem = ctrl "menuAnalysis"
let menuStartAnalysis: MenuItem = ctrl "menuStartAnalysis"
let txtMessageStatus: TextBlock = ctrl "txtMessageStatus"
let txtPatient: TextBox = ctrl "txtPatient"
- let txtGlobalParasitemia: TextBox = ctrl "txtGlobalParasitemia"
+ let txtGlobalParasitemia: TextBlock = ctrl "txtGlobalParasitemia"
let stackPreviews: StackPanel = ctrl "stackPreviews"
let scrollViewCurrentImage: ScrollViewer = ctrl "scrollViewCurrentImage"
let borderCurrentImage: Border = ctrl "borderCurrentImage"
let canvasCurrentImage: Canvas = ctrl "canvasCurrentImage"
+
+ let gridImageInformation: Grid = ctrl "gridImageInformation"
let txtImageInformation1: TextBlock = ctrl "txtImageInformation1"
let txtImageInformation2: TextBlock = ctrl "txtImageInformation2"
+ let txtImageName: TextBox = ctrl "txtImageName"
let scrollRBC: ScrollViewer = ctrl "scrollRBC"
let stackRBC: StackPanel = ctrl "stackRBC"
scrollViewCurrentImage.ScrollToHorizontalOffset(rbc.center.X * currentScale - scrollViewCurrentImage.ViewportWidth / 2. + borderCurrentImage.BorderThickness.Left)
scrollViewCurrentImage.ScrollToVerticalOffset(rbc.center.Y * currentScale - scrollViewCurrentImage.ViewportHeight / 2. + borderCurrentImage.BorderThickness.Top)
- let percentText (nbTotal: int, nb: int) : string =
- if nbTotal = 0
- then
- ""
- else
- let percent = 100. * (float nb) / (float nbTotal)
- sprintf "%.1f %% (%d / %d)" percent nb nbTotal
+
+ let txtImageName_TextChanged =
+ TextChangedEventHandler(fun obj args -> state.CurrentImage |> Option.iter(fun srcImg -> state.SetName srcImg txtImageName.Text))
let updateCurrentImageInformation () =
+ txtImageName.TextChanged.RemoveHandler(txtImageName_TextChanged)
txtImageInformation1.Inlines.Clear()
txtImageInformation2.Inlines.Clear()
+ txtImageName.Text <- ""
match state.CurrentImage with
| Some srcImg ->
- let parasitemiaStr = percentText (state.ImageParasitemia srcImg)
+ gridImageInformation.Visibility <- Visibility.Visible
+ txtImageName.Text <- srcImg.name
+ txtImageName.TextChanged.AddHandler(txtImageName_TextChanged)
+
+ // The left part.
+ let parasitemiaStr = Utils.percentText (state.ImageParasitemia srcImg)
txtImageInformation1.Inlines.Add(Documents.Run("Parasitemia: ", FontWeight = FontWeights.Bold))
txtImageInformation1.Inlines.Add(parasitemiaStr)
txtImageInformation1.Inlines.Add(Documents.LineBreak())
txtImageInformation1.Inlines.Add(Documents.Run("Last analysis: ", FontWeight = FontWeights.Bold))
txtImageInformation1.Inlines.Add(Documents.Run(if srcImg.dateLastAnalysis.Ticks = 0L then "<Never>" else srcImg.dateLastAnalysis.ToLocalTime().ToString()))
- let alteredStr = percentText (state.ImageNbAltered srcImg)
- txtImageInformation2.Inlines.Add(Documents.Run("Number of erytrocytes manually altered: ", FontWeight = FontWeights.Bold))
- txtImageInformation2.Inlines.Add(Documents.Run(alteredStr))
+ // The right part part.
+ txtImageInformation2.Inlines.Add(Documents.Run("Added infected erythrocyte: ", FontWeight = FontWeights.Bold))
+ txtImageInformation2.Inlines.Add(Documents.Run((state.ImageNbManuallyChangedRBCStr srcImg true) + " " + (state.ImageManuallyChangedRBCStr srcImg true)))
txtImageInformation2.Inlines.Add(Documents.LineBreak())
+ txtImageInformation2.Inlines.Add(Documents.Run("Removed infected erythrocyte: ", FontWeight = FontWeights.Bold))
+ txtImageInformation2.Inlines.Add(Documents.Run((state.ImageNbManuallyChangedRBCStr srcImg false) + " " + (state.ImageManuallyChangedRBCStr srcImg false)))
- txtImageInformation2.Inlines.Add(Documents.Run("Average erytrocyte diameter: ", FontWeight = FontWeights.Bold))
- txtImageInformation2.Inlines.Add(Documents.Run(srcImg.config.RBCRadius.ToString()))
- | _ -> ()
+ | _ ->
+ gridImageInformation.Visibility <- Visibility.Hidden
let updateGlobalParasitemia () =
- txtGlobalParasitemia.Text <- percentText state.GlobalParasitemia
+ txtGlobalParasitemia.Inlines.Clear()
+ let total, infected = state.GlobalParasitemia
+ txtGlobalParasitemia.Inlines.Add(Documents.Run(Utils.percentText (total, infected), FontWeight = FontWeights.Bold))
+ if total > 0 && total < warningBelowNumberOfRBC
+ then
+ txtGlobalParasitemia.Inlines.Add(
+ Documents.Run(
+ sprintf " Warning: the number of erytrocytes should be above %d" warningBelowNumberOfRBC,
+ FontWeight = FontWeights.Bold,
+ Foreground = Brushes.Red))
let updateViewportPreview () =
for preview in stackPreviews.Children |> Seq.cast<Views.ImageSourcePreview> do
state.Reset()
updateGUI()
+ let exportResults () =
+ let extension = ".txt"
+ let dialog = SaveFileDialog(AddExtension = true, DefaultExt = extension)
+
+ if state.FilePath <> ""
+ then
+ dialog.FileName <- Path.GetFileNameWithoutExtension(state.FilePath) + extension
+ elif state.PatientID <> ""
+ then
+ dialog.FileName <- state.PatientID + extension
+
+ let res = dialog.ShowDialog()
+ if res.HasValue && res.Value then
+ try
+ Export.exportResults state dialog.FileName
+ with
+ | :? IOException as ex ->
+ Log.Error(ex.ToString())
+ MessageBox.Show(sprintf "The results cannot be exported in '%s'" state.FilePath, "Error exporting the files", MessageBoxButton.OK, MessageBoxImage.Error) |> ignore
+
txtPatient.TextChanged.AddHandler(fun obj args -> state.PatientID <- txtPatient.Text)
menuExit.Click.AddHandler(fun obj args -> mainWindow.Root.Close())
menuSaveAsFile.Click.AddHandler(fun obj args -> saveCurrentDocumentAsNewFile ())
menuLoadFile.Click.AddHandler(fun obj args -> askLoadFile ())
menuNewFile.Click.AddHandler(fun obj args -> newFile ())
+ menuExportResults.Click.AddHandler(fun obj args -> exportResults ())
menuAddSourceImage.Click.AddHandler(fun obj args ->
let dialog = OpenFileDialog(Filter = "Image Files|*.png;*.jpg;*.tif;*.tiff", Multiselect = true)
FSharp.ViewModule.FunCommand((fun obj -> newFile ()), (fun obj -> true)),
Input.KeyGesture(Input.Key.N, Input.ModifierKeys.Control))) |> ignore
+ // Export results.
+ mainWindow.Root.InputBindings.Add(
+ Input.KeyBinding(
+ FSharp.ViewModule.FunCommand((fun obj -> exportResults ()), (fun obj -> true)),
+ Input.KeyGesture(Input.Key.E, Input.ModifierKeys.Control))) |> ignore
+
// Viewport preview.
scrollViewCurrentImage.ScrollChanged.AddHandler(fun obj args -> updateViewportPreview ())
updateDocumentStatus ()
+ gridImageInformation.Visibility <- Visibility.Hidden
mainWindow.Root.Show()