d09fe23a23c4fca8309bbd2bda71398ae002ffe6
[master-thesis.git] / Parasitemia / ParasitemiaUI / State.fs
1 module ParasitemiaUI.State
2
3 open System
4 open System.Collections.Generic
5 open System.Windows
6
7 open Emgu.CV
8 open Emgu.CV.Structure
9
10 open Types
11
12 type State (defaultConfig : ParasitemiaCore.Config.Config) =
13 let sourceImages = List<SourceImage>()
14 let mutable alteredSinceLastSave = false
15 let mutable patientID = ""
16
17 member this.AlteredSinceLastSave = alteredSinceLastSave
18 member val CurrentImage : SourceImage option = None with get, set
19 member val FilePath : string = "" with get, set
20
21 member this.PatientID
22 with get () : string = patientID
23 and set id =
24 if id <> patientID then
25 alteredSinceLastSave <- true
26 patientID <- id
27
28 member this.ImageParasitemia (srcImg : SourceImage) : int * int =
29 List.length srcImg.rbcs,
30 srcImg.rbcs |> List.fold (fun nbInfected rbc -> if rbc.infected then nbInfected + 1 else nbInfected) 0
31
32 member this.ImageNbManuallyChangedRBC (srcImg : SourceImage) (setAsInfected : bool) : int * int =
33 List.length srcImg.rbcs,
34 srcImg.rbcs |> List.fold (fun nb rbc -> if rbc.setManually && rbc.infected = setAsInfected then nb + 1 else nb) 0
35
36 member this.ImageNbManuallyChangedRBCStr (srcImg : SourceImage) (setAsInfected : bool) : string =
37 Utils.percentText (this.ImageNbManuallyChangedRBC srcImg setAsInfected)
38
39 member this.ImageManuallyChangedRBC (srcImg : SourceImage) (setAsInfected : bool) : int seq =
40 query {
41 for rbc in srcImg.rbcs do
42 where (rbc.setManually && rbc.infected = setAsInfected)
43 select rbc.num
44 }
45
46 member this.ImageManuallyChangedRBCStr (srcImg : SourceImage) (setAsInfected : bool) : string =
47 let listStr = Utils.listAsStr <| this.ImageManuallyChangedRBC srcImg setAsInfected
48 if listStr = "" then
49 ""
50 else
51 "[" + listStr + "]"
52
53 member this.GlobalParasitemia : int * int =
54 sourceImages
55 |> Seq.fold (
56 fun (nbTotal, nbTotalInfected) srcImg ->
57 let nb, nbInfected = this.ImageParasitemia srcImg
58 nbTotal + nb, nbTotalInfected + nbInfected
59 ) (0, 0)
60
61 member this.SetAsInfected (rbc : RBC) (infected : bool) =
62 if infected <> rbc.infected then
63 alteredSinceLastSave <- true
64 rbc.infected <- infected
65 rbc.setManually <- not rbc.setManually
66
67 /// <summary>
68 /// Save the current state. 'FilePath' must have been defined.
69 /// </summary>
70 /// <exception cref="System.IOException">If the file cannot be saved</exception>
71 member this.Save () =
72 let data = { PiaZ.DocumentData.patientID = this.PatientID; PiaZ.DocumentData.images = List.ofSeq sourceImages }
73 PiaZ.save this.FilePath data
74 alteredSinceLastSave <- false
75
76 /// <summary>
77 /// Load the current state. 'FilePath' must have been defined.
78 /// </summary>
79 /// <exception cref="System.IOException">If the file cannot be loaded</exception>
80 member this.Load () =
81 let data = PiaZ.load this.FilePath defaultConfig
82 this.PatientID <- data.patientID
83 sourceImages.Clear()
84 sourceImages.InsertRange(0, data.images)
85 this.CurrentImage <- if sourceImages.Count > 0 then Some sourceImages.[0] else None
86 alteredSinceLastSave <- false
87
88 /// <summary>
89 /// </summary>
90 /// <exception cref="System.IOException">If the image cannot be read</exception>
91 member this.AddSourceImage (filePath : string) (defaultConfig : ParasitemiaCore.Config.Config) : SourceImage =
92 let srcImg =
93 {
94 num = sourceImages.Count + 1
95 name = System.IO.FileInfo(filePath).Name
96 config = defaultConfig.Copy()
97 dateLastAnalysis = DateTime(0L)
98 rbcs = []
99 img = new Image<Bgr, byte>(filePath)
100 healthyRBCBrightness = 1.f
101 infectedRBCBrightness = 1.f
102 }
103
104 sourceImages.Add(srcImg)
105 if sourceImages.Count = 1 then
106 this.CurrentImage <- Some sourceImages.[0]
107 alteredSinceLastSave <- true
108 srcImg
109
110 member this.RemoveSourceImage (srcImg : SourceImage) =
111 let isCurrent =
112 match this.CurrentImage with
113 | Some srcImg' -> srcImg = srcImg'
114 | _ -> false
115
116 if sourceImages.Remove(srcImg) then
117 alteredSinceLastSave <- true
118 if isCurrent then
119 this.CurrentImage <- if sourceImages.Count > 0 then Some sourceImages.[0] else None
120 // Re-numbered the images.
121 sourceImages |> Seq.iteri (fun i srcImg -> srcImg.num <- i + 1)
122
123 member this.SetName (srcImg : SourceImage) (name : string) =
124 if name <> srcImg.name then
125 srcImg.name <- name
126 alteredSinceLastSave <- true
127
128 member this.SetResult (imgNum : int) (cells : ParasitemiaCore.Types.Cell list) =
129 let sourceImage = sourceImages.Find(fun srcImg -> srcImg.num = imgNum)
130
131 let w = sourceImage.img.Width
132 let h = sourceImage.img.Height
133
134 sourceImage.dateLastAnalysis <- DateTime.UtcNow
135
136 // To match with previously manually altered RBC.
137 let manuallyAlteredPreviousRBCS = sourceImage.rbcs |> List.filter (fun rbc -> rbc.setManually)
138 let tolerance = (float sourceImage.config.RBCRadius.Pixel) * 0.5 // +/-.
139 let getPreviousManuallyAlteredRBC (center : Point) : RBC option =
140 manuallyAlteredPreviousRBCS |> List.tryFind (fun rbc -> rbc.center.X > center.X - tolerance && rbc.center.X < center.X + tolerance &&
141 rbc.center.Y > center.Y - tolerance && rbc.center.Y < center.Y + tolerance)
142
143 sourceImage.rbcs <-
144 cells
145 |> List.filter (fun cell -> match cell.cellClass with ParasitemiaCore.Types.HealthyRBC | ParasitemiaCore.Types.InfectedRBC -> true | _ -> false )
146 |> List.sortByDescending (fun cell -> cell.nucleusArea, (w - cell.center.X) + (h - cell.center.Y))
147 |> List.mapi (
148 fun i cell ->
149 let center = Point(float cell.center.X, float cell.center.Y)
150 let infected, setManually =
151 let infected = cell.cellClass = ParasitemiaCore.Types.InfectedRBC
152 match getPreviousManuallyAlteredRBC center with
153 | Some rbc when rbc.infected <> infected -> rbc.infected, true // If it has been previously manually changed and now match the result, the manually flag is removed.
154 | _ -> infected, false
155 {
156 num = i + 1
157 infected = infected
158 setManually = setManually
159 center = center
160 size = Size(float cell.elements.Width, float cell.elements.Height)
161 infectedArea = cell.nucleusArea
162 }
163 )
164
165 alteredSinceLastSave <- true
166
167 member this.SourceImages : SourceImage seq =
168 sourceImages :> SourceImage seq
169
170 member this.Reset () =
171 this.PatientID <- ""
172 this.FilePath <- ""
173 this.CurrentImage <- None
174 sourceImages.Clear()
175 alteredSinceLastSave <- false