-module State
+module Parasitemia.GUI.State
+open System
open System.Collections.Generic
+open System.Windows
open Emgu.CV
open Emgu.CV.Structure
-type ImageSource = {
- cells: List<Types.Cell>
- img: Image<Bgr, byte> }
+open Types
type State () =
- let imagesSource = List<ImageSource>()
+ let sourceImages = List<SourceImage>()
+ let mutable alteredSinceLastSave = false
+ let mutable patientID = ""
+ member this.AlteredSinceLastSave = alteredSinceLastSave
+ member val CurrentImage: SourceImage option = None with get, set
member val FilePath: string = "" with get, set
- member val PatientID: string = "" with get, set
+
+ member this.PatientID
+ with get () : string = patientID
+ and set id =
+ if id <> patientID
+ then
+ alteredSinceLastSave <- true
+ patientID <- id
+
+ member this.ImageParasitemia (srcImg: SourceImage) : int * int =
+ List.length srcImg.rbcs,
+ srcImg.rbcs |> List.fold (fun nbInfected rbc -> if rbc.infected then nbInfected + 1 else nbInfected) 0
+
+ member this.GlobalParasitemia : int * int =
+ sourceImages
+ |> Seq.fold (fun (nbTotal, nbTotalInfected) srcImg ->
+ let nb, nbInfected = this.ImageParasitemia srcImg
+ nbTotal + nb, nbTotalInfected + nbInfected) (0, 0)
+
+
+ member this.SetAsInfected (rbc: RBC) (infected: bool) =
+ if infected <> rbc.infected
+ then
+ alteredSinceLastSave <- true
+ rbc.infected <- infected
+ rbc.setManually <- not rbc.setManually
member this.Save () =
- let data = { Pia.sources = []; Pia.patientID = this.PatientID }
- Pia.save this.FilePath data
+ let data = { PiaZ.FileData.patientID = this.PatientID; PiaZ.FileData.images = List.ofSeq sourceImages }
+ PiaZ.save this.FilePath data
+ alteredSinceLastSave <- false
member this.Load () =
- let data = Pia.load this.FilePath
+ let data = PiaZ.load this.FilePath
this.PatientID <- data.patientID
+ sourceImages.Clear()
+ sourceImages.InsertRange(0, data.images)
+ if sourceImages.Count > 0
+ then this.CurrentImage <- Some sourceImages.[0]
+ alteredSinceLastSave <- false
+
+ member this.AddSourceImage (filePath: string) (defaultConfig: Config.Config) : SourceImage =
+ let srcImg = { num = sourceImages.Count + 1; config = defaultConfig.Copy(); dateLastAnalysis = DateTime(0L); rbcs = []; img = new Image<Bgr, byte>(filePath) }
+ sourceImages.Add(srcImg)
+ if sourceImages.Count = 1
+ then this.CurrentImage <- Some sourceImages.[0]
+ alteredSinceLastSave <- true
+ srcImg
+
+ member this.RemoveSourceImage (srcImg: SourceImage) =
+ let isCurrent =
+ match this.CurrentImage with
+ | Some srcImg' -> srcImg = srcImg'
+ | _ -> false
+
+ if sourceImages.Remove(srcImg)
+ then
+ alteredSinceLastSave <- true
+ if isCurrent
+ then
+ this.CurrentImage <- if sourceImages.Count > 0 then Some sourceImages.[0] else None
+ // Re-numbered the images.
+ sourceImages |> Seq.iteri (fun i srcImg -> srcImg.num <- i + 1)
+
+ member this.SetResult (imgNum: int) (cells: Cell list) =
+ let sourceImage = sourceImages.Find(fun srcImg -> srcImg.num = imgNum)
+
+ let w = sourceImage.img.Width
+ let h = sourceImage.img.Height
+
+ sourceImage.dateLastAnalysis <- DateTime.UtcNow
+
+ // To match with previously manually altered RBC.
+ let manuallyAlteredPreviousRBCS = sourceImage.rbcs |> List.filter (fun rbc -> rbc.setManually)
+ let tolerance = (float sourceImage.config.RBCRadius.Pixel) * 0.5 // +/-.
+ let getPreviousRBC (center: Point) : RBC option =
+ manuallyAlteredPreviousRBCS |> List.tryFind (fun rbc -> rbc.center.X > center.X - tolerance && rbc.center.X < center.X + tolerance &&
+ rbc.center.Y > center.Y - tolerance && rbc.center.Y < center.Y + tolerance)
+
+ sourceImage.rbcs <- cells
+ |> List.filter (fun cell -> match cell.cellClass with HealthyRBC | InfectedRBC -> true | _ -> false )
+ |> List.sortByDescending (fun cell -> cell.infectedArea, (w - cell.center.X) + (h - cell.center.Y))
+ |> List.mapi (fun i cell ->
+ let center = Point(float cell.center.X, float cell.center.Y)
+ let infected, setManually =
+ match getPreviousRBC center with
+ | Some rbc -> rbc.infected, true
+ | _ -> cell.cellClass = InfectedRBC, false
+
+ { num = i + 1
+ infected = infected
+ setManually = setManually
+ center = center
+ size = Size(float cell.elements.Width, float cell.elements.Height)
+ infectedArea = cell.infectedArea })
- member this.AddSourceImage (filePath: string) =
- imagesSource.Add({ cells = List<Types.Cell>(); img = new Image<Bgr, byte>(filePath) })
+ alteredSinceLastSave <- true
- member x.ImagesSource : ImageSource seq =
- imagesSource :> ImageSource seq
+ member this.SourceImages : SourceImage seq =
+ sourceImages :> SourceImage seq
member this.Reset () =
this.PatientID <- ""
- imagesSource.Clear()
\ No newline at end of file
+ this.FilePath <- ""
+ this.CurrentImage <- None
+ sourceImages.Clear()
+ alteredSinceLastSave <- false
\ No newline at end of file