1
module ParasitemiaUI.State
4 open System.Collections.Generic
12 type State (defaultConfig
: ParasitemiaCore.Config.Config) =
13 let sourceImages = List<SourceImage>()
14 let mutable alteredSinceLastSave = false
15 let mutable patientID = ""
17 member this
.AlteredSinceLastSave = alteredSinceLastSave
18 member val CurrentImage : SourceImage option = None with get
, set
19 member val FilePath : string = "" with get
, set
22 with get
() : string = patientID
24 if id <> patientID then
25 alteredSinceLastSave <- true
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
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
36 member this
.ImageNbManuallyChangedRBCStr (srcImg
: SourceImage) (setAsInfected
: bool) : string =
37 Utils.percentText
(this
.ImageNbManuallyChangedRBC srcImg setAsInfected
)
39 member this
.ImageManuallyChangedRBC (srcImg
: SourceImage) (setAsInfected
: bool) : int seq =
41 for rbc
in srcImg
.rbcs
do
42 where
(rbc
.setManually
&& rbc
.infected
= setAsInfected
)
46 member this
.ImageManuallyChangedRBCStr (srcImg
: SourceImage) (setAsInfected
: bool) : string =
47 let listStr = Utils.listAsStr
<| this.ImageManuallyChangedRBC srcImg setAsInfected
53 member this.GlobalParasitemia : int * int =
56 fun (nbTotal
, nbTotalInfected
) srcImg
->
57 let nb, nbInfected = this.ImageParasitemia srcImg
58 nbTotal
+ nb, nbTotalInfected
+ nbInfected
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
68 /// Save the current state. 'FilePath' must have been defined.
70 /// <exception cref="System.IOException">If the file cannot be saved</exception>
72 let data = { PiaZ.DocumentData.patientID = this.PatientID; PiaZ.DocumentData.images
= List.ofSeq
sourceImages }
73 PiaZ.save
this.FilePath data
74 alteredSinceLastSave <- false
77 /// Load the current state. 'FilePath' must have been defined.
79 /// <exception cref="System.IOException">If the file cannot be loaded</exception>
81 let data = PiaZ.load
this.FilePath defaultConfig
82 this.PatientID <- data.patientID
84 sourceImages.InsertRange(0, data.images
)
85 this.CurrentImage <- if sourceImages.Count > 0 then Some sourceImages.[0] else None
86 alteredSinceLastSave <- false
90 /// <exception cref="System.IOException">If the image cannot be read</exception>
91 member this.AddSourceImage (filePath
: string) (defaultConfig
: ParasitemiaCore.Config.Config) : SourceImage =
94 num
= sourceImages.Count + 1
95 name
= System.IO.FileInfo(filePath
).Name
96 config
= defaultConfig
.Copy()
97 dateLastAnalysis
= DateTime(0L)
99 img
= new Image<Bgr, byte
>(filePath
)
100 healthyRBCBrightness
= 1.f
101 infectedRBCBrightness
= 1.f
104 sourceImages.Add(srcImg)
105 if sourceImages.Count = 1 then
106 this.CurrentImage <- Some sourceImages.[0]
107 alteredSinceLastSave <- true
110 member this.RemoveSourceImage (srcImg : SourceImage) =
112 match this.CurrentImage with
113 | Some srcImg' -> srcImg = srcImg'
116 if sourceImages.Remove(srcImg) then
117 alteredSinceLastSave <- true
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)
123 member this.SetName (srcImg : SourceImage) (name
: string) =
124 if name
<> srcImg.name
then
126 alteredSinceLastSave <- true
128 member this.SetResult (imgNum
: int) (cells
: ParasitemiaCore.Types.Cell list) =
129 let sourceImage = sourceImages.Find(fun srcImg -> srcImg.num
= imgNum
)
131 let w = sourceImage.img
.Width
132 let h = sourceImage.img
.Height
134 sourceImage.dateLastAnalysis
<- DateTime.UtcNow
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)
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))
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
158 setManually
= setManually
160 size
= Size(float cell.elements
.Width, float cell.elements
.Height)
161 infectedArea
= cell.nucleusArea
165 alteredSinceLastSave <- true
167 member this.SourceImages : SourceImage seq =
168 sourceImages :> SourceImage seq
170 member this.Reset () =
173 this.CurrentImage <- None
175 alteredSinceLastSave <- false