Update coding style.
authorGreg Burri <greg.burri@gmail.com>
Sat, 1 Jul 2017 15:36:26 +0000 (17:36 +0200)
committerGreg Burri <greg.burri@gmail.com>
Sat, 1 Jul 2017 15:36:26 +0000 (17:36 +0200)
44 files changed:
Parasitemia/Logger/AssemblyInfo.fs
Parasitemia/Logger/Logger.fs
Parasitemia/Parasitemia.sln
Parasitemia/ParasitemiaCore/Analysis.fs
Parasitemia/ParasitemiaCore/AssemblyInfo.fs
Parasitemia/ParasitemiaCore/Classifier.fs
Parasitemia/ParasitemiaCore/Config.fs
Parasitemia/ParasitemiaCore/EEOver.fs
Parasitemia/ParasitemiaCore/Ellipse.fs
Parasitemia/ParasitemiaCore/Granulometry.fs
Parasitemia/ParasitemiaCore/Heap.fs
Parasitemia/ParasitemiaCore/ImgTools/Drawing.fs
Parasitemia/ParasitemiaCore/ImgTools/Edges.fs
Parasitemia/ParasitemiaCore/ImgTools/Histogram.fs
Parasitemia/ParasitemiaCore/ImgTools/IO.fs
Parasitemia/ParasitemiaCore/ImgTools/ImgTools.fs
Parasitemia/ParasitemiaCore/ImgTools/Morpho.fs
Parasitemia/ParasitemiaCore/KMeans.fs
Parasitemia/ParasitemiaCore/KMedians.fs
Parasitemia/ParasitemiaCore/KdTree.fs
Parasitemia/ParasitemiaCore/MatchingEllipses.fs
Parasitemia/ParasitemiaCore/ParasitemiaCore.fsproj
Parasitemia/ParasitemiaCore/ParasitesMarker.fs
Parasitemia/ParasitemiaCore/Types.fs
Parasitemia/ParasitemiaCore/UnitsOfMeasure.fs
Parasitemia/ParasitemiaCore/Utils.fs
Parasitemia/ParasitemiaCore/packages.config
Parasitemia/ParasitemiaUI/About.fs
Parasitemia/ParasitemiaUI/Analysis.fs
Parasitemia/ParasitemiaUI/AssemblyInfo.fs
Parasitemia/ParasitemiaUI/DPICalculator.fs
Parasitemia/ParasitemiaUI/Export.fs
Parasitemia/ParasitemiaUI/GUI.fs
Parasitemia/ParasitemiaUI/ParasitemiaUI.fsproj
Parasitemia/ParasitemiaUI/PiaZ.fs
Parasitemia/ParasitemiaUI/Program.fs
Parasitemia/ParasitemiaUI/State.fs
Parasitemia/ParasitemiaUI/Types.fs
Parasitemia/ParasitemiaUI/Utils.fs
Parasitemia/ParasitemiaUI/packages.config
Parasitemia/Tests/ParasitemiaCore.Tests/AssemblyInfo.fs
Parasitemia/Tests/ParasitemiaCore.Tests/KdTree.fs
Parasitemia/Tests/ParasitemiaCore.Tests/ParasitemiaCore.Tests.fsproj
Parasitemia/Tests/ParasitemiaCore.Tests/packages.config

index c810d05..106b6af 100644 (file)
@@ -7,22 +7,22 @@ open System.Runtime.InteropServices
 // General Information about an assembly is controlled through the following 
 // set of attributes. Change these attribute values to modify the information
 // associated with an assembly.
-[<assembly: AssemblyTitle("Logger")>]
-[<assembly: AssemblyDescription("")>]
-[<assembly: AssemblyConfiguration("")>]
-[<assembly: AssemblyCompany("")>]
-[<assembly: AssemblyProduct("Logger")>]
-[<assembly: AssemblyCopyright("Copyright ©  2016")>]
-[<assembly: AssemblyTrademark("")>]
-[<assembly: AssemblyCulture("")>]
+[<assembly: AssemblyTitle "Logger">]
+[<assembly: AssemblyDescription "">]
+[<assembly: AssemblyConfiguration "">]
+[<assembly: AssemblyCompany "">]
+[<assembly: AssemblyProduct "Logger">]
+[<assembly: AssemblyCopyright "Copyright ©  2016">]
+[<assembly: AssemblyTrademark "">]
+[<assembly: AssemblyCulture "">]
 
 // Setting ComVisible to false makes the types in this assembly not visible 
 // to COM components.  If you need to access a type in this assembly from 
 // COM, set the ComVisible attribute to true on that type.
-[<assembly: ComVisible(false)>]
+[<assembly: ComVisible false>]
 
 // The following GUID is for the ID of the typelib if this project is exposed to COM
-[<assembly: Guid("a4f183ae-562a-4bad-88e6-658b4ce15dc3")>]
+[<assembly: Guid "a4f183ae-562a-4bad-88e6-658b4ce15dc3">]
 
 // Version information for an assembly consists of the following four values:
 // 
@@ -33,9 +33,9 @@ open System.Runtime.InteropServices
 // 
 // You can specify all the values or you can default the Build and Revision Numbers 
 // by using the '*' as shown below:
-// [<assembly: AssemblyVersion("1.0.*")>]
-[<assembly: AssemblyVersion("1.0.0.0")>]
-[<assembly: AssemblyFileVersion("1.0.0.0")>]
+// [<assembly: AssemblyVersion "1.0.*">]
+[<assembly: AssemblyVersion "1.0.0.0">]
+[<assembly: AssemblyFileVersion "1.0.0.0">]
 
 do
     ()
\ No newline at end of file
index df2144f..4fc1736 100644 (file)
@@ -33,9 +33,9 @@ type Log () =
         if isNull path then
             None
         else
-            let filename = path.Substring(path.LastIndexOf(Path.DirectorySeparatorChar) + 1)
-            let filenameWithoutExtension = filename.Remove(filename.IndexOf('.'))
-            match Int32.TryParse(filenameWithoutExtension) with
+            let filename = path.Substring (path.LastIndexOf Path.DirectorySeparatorChar + 1)
+            let filenameWithoutExtension = filename.Remove (filename.IndexOf '.')
+            match Int32.TryParse filenameWithoutExtension with
             | (true, n) -> Some n
             | _ -> None
 
@@ -44,13 +44,13 @@ type Log () =
     let [<Literal>] COMPRESS_ARCHIVED_FILES = true
     let [<Literal>] FILENAME_FORMAT = "{0:D4}.log"
     let [<Literal>] COMPRESSED_FILE_POSTFIX = ".gzip"
-    let encoding = Encoding.GetEncoding("UTF-8")
+    let encoding = Encoding.GetEncoding "UTF-8"
 
     let compress (filename : string) =
-        use inputStream = new FileStream(filename, FileMode.Open, FileAccess.Read)
+        use inputStream = new FileStream (filename, FileMode.Open, FileAccess.Read)
         let filenameCompressed = filename + COMPRESSED_FILE_POSTFIX
-        use compressedStream = new GZipStream(new FileStream(filenameCompressed, FileMode.Create, FileAccess.Write), CompressionLevel.Optimal)
-        inputStream.CopyTo(compressedStream)
+        use compressedStream = new GZipStream (new FileStream (filenameCompressed, FileMode.Create, FileAccess.Write), CompressionLevel.Optimal)
+        inputStream.CopyTo compressedStream
 
     let moduleName = System.Diagnostics.StackFrame(1).GetMethod().Module.Name
 
@@ -59,9 +59,9 @@ type Log () =
 
     let mutable logDir : string = null
 
-    let monitor = Object()
+    let monitor = Object ()
 
-    let listeners = List<IListener>()
+    let listeners = List<IListener> ()
 
     let debug =
 #if DEBUG
@@ -70,7 +70,7 @@ type Log () =
         false
 #endif
 
-    static let instance = new Log()
+    static let instance = new Log ()
 
     let openLogFile (entryNumber : int64) =
         if not (isNull logDir) then
@@ -79,40 +79,40 @@ type Log () =
                 then
                     if not (isNull stream)
                     then
-                        stream.Close()
+                        stream.Close ()
                         if COMPRESS_ARCHIVED_FILES then
                             compress filename
-                            File.Delete(filename)
+                            File.Delete filename
 
                     // Search the last id among the log files.
                     let mutable n = 1
-                    for existingFile in Directory.GetFiles(logDir) do
+                    for existingFile in Directory.GetFiles logDir do
                         match extractNumberFromLogfilepath existingFile with
                         | Some n' when n' > n -> n <- n'
                         | _ -> ()
 
-                    filename <- Path.Combine(logDir, String.Format(FILENAME_FORMAT, n))
+                    filename <- Path.Combine (logDir, String.Format (FILENAME_FORMAT, n))
                     try
-                        if File.Exists(filename + COMPRESSED_FILE_POSTFIX) || FileInfo(filename).Length > MAX_SIZE_FILE
+                        if File.Exists (filename + COMPRESSED_FILE_POSTFIX) || FileInfo(filename).Length > MAX_SIZE_FILE
                         then
-                            filename <- Path.Combine(logDir, String.Format(FILENAME_FORMAT, n + 1))
+                            filename <- Path.Combine (logDir, String.Format (FILENAME_FORMAT, n + 1))
                     with
                     | :? FileNotFoundException -> () // The file may not exist.
 
-                    stream <- new StreamWriter(filename, true, encoding)
+                    stream <- new StreamWriter (filename, true, encoding)
             with
-            | ex -> Console.Error.WriteLine("Can't open the file log: {0}", ex)
+            | ex -> Console.Error.WriteLine ("Can't open the file log: {0}", ex)
 
     let write (msg : Message) (entryNumber : int64) =
         openLogFile entryNumber
 
         let header =
-            String.Format(
+            String.Format (
                 "{0:yyyy-MM-dd HH:mm:ss.fff} [{1}] {{{2}}} ({3})",
-                TimeZone.CurrentTimeZone.ToLocalTime(DateTime.UtcNow),
+                TimeZone.CurrentTimeZone.ToLocalTime DateTime.UtcNow,
                 string msg.Severity,
                 msg.ModuleCaller,
-                (if String.IsNullOrEmpty(msg.ThreadName) then string msg.ThreadId else sprintf "%s-%i" msg.ThreadName msg.ThreadId)
+                (if String.IsNullOrEmpty msg.ThreadName then string msg.ThreadId else sprintf "%s-%i" msg.ThreadName msg.ThreadId)
             )
 
         for listener in listeners do
@@ -121,17 +121,17 @@ type Log () =
         if not (isNull stream)
         then
             try
-                stream.WriteLine("{0} : {1}", header, msg.Message)
-                stream.Flush()
+                stream.WriteLine ("{0} : {1}", header, msg.Message)
+                stream.Flush ()
             with
-            | :? IOException as ex -> Console.Error.WriteLine("Unable to write to the log file: {0}", ex)
+            | :? IOException as ex -> Console.Error.WriteLine ("Unable to write to the log file: {0}", ex)
 
     let writeAgent =
-        new MailboxProcessor<Command>(
+        new MailboxProcessor<Command> (
             fun inbox ->
                 let rec loop (nbEntries : int64) =
                     async {
-                        let! command = inbox.Receive()
+                        let! command = inbox.Receive ()
                         match command with
                         | Write message ->
                             write message nbEntries
@@ -143,29 +143,31 @@ type Log () =
         )
 
     do
-        writeAgent.Start()
+        writeAgent.Start ()
 
     let setLogDirectory (dir : string) =
-        lock monitor (fun () ->
-            logDir <- dir
+        lock monitor (
+            fun () ->
+                logDir <- dir
 
-            if not <| isNull stream then
-                stream.Close()
-                stream <- null
+                if not <| isNull stream then
+                    stream.Close ()
+                    stream <- null
 
-            try
-                if not <| Directory.Exists(logDir)
-                then
-                    Directory.CreateDirectory(logDir) |> ignore
-            with
-            | _ -> Console.Error.WriteLine("Unable to create the log directory: {0}", logDir))
+                try
+                    if not <| Directory.Exists logDir
+                    then
+                        Directory.CreateDirectory logDir |> ignore
+                with
+                | _ -> Console.Error.WriteLine ("Unable to create the log directory: {0}", logDir)
+       )
 
     interface IDisposable with
         member this.Dispose () =
             if not (isNull stream)
             then
-                stream.Dispose()
-            (writeAgent :> IDisposable).Dispose()
+                stream.Dispose ()
+            (writeAgent :> IDisposable).Dispose ()
 
     member private this.Write (message : string) (severity : Severity) =
         let moduleNameCaller =
@@ -190,7 +192,7 @@ type Log () =
     /// Will stop and wait a reply. Used to flush the remaining messages.
     /// </summary>
     member private this.Stop () =
-        writeAgent.PostAndReply(
+        writeAgent.PostAndReply (
             fun replyChannel ->
                 Stop replyChannel
         )
@@ -203,23 +205,24 @@ type Log () =
         instance.LogDirectory <- dir
 
     member this.AddListener (listener : IListener) =
-        lock monitor (fun () ->
-            if not <| listeners.Contains(listener)
-            then
-                listeners.Add(listener))
+        lock monitor (
+            fun () ->
+                if not <| listeners.Contains listener
+                then
+                    listeners.Add listener
+        )
 
     member this.RmListener (listener : IListener) =
-        lock monitor (fun () ->
-            listeners.Remove(listener) |> ignore)
+        lock monitor (fun () -> listeners.Remove listener |> ignore)
 
-    static member AddListener (listener : IListener) = instance.AddListener(listener)
-    static member RmListener (listener : IListener) = instance.RmListener(listener)
+    static member AddListener (listener : IListener) = instance.AddListener listener
+    static member RmListener (listener : IListener) = instance.RmListener listener
 
     static member LogWithTime (severity : Severity) (f : unit -> 'a) (format : Printf.StringFormat<'b, 'a>) : 'b =
-        let sw = Stopwatch()
-        sw.Start()
+        let sw = Stopwatch ()
+        sw.Start ()
         let res = f ()
-        sw.Stop()
+        sw.Stop ()
         Printf.kprintf (fun s -> instance.Write (s + sprintf " (time: %d ms)" sw.ElapsedMilliseconds) severity; res) format
 
     static member Debug format =
@@ -242,4 +245,4 @@ type Log () =
         Printf.kprintf (fun s -> instance.Write s Severity.FATAL) format
 
     static member Shutdown () =
-        instance.Stop()
+        instance.Stop ()
index ba7560b..42e8f4e 100644 (file)
@@ -1,7 +1,7 @@
 
 Microsoft Visual Studio Solution File, Format Version 12.00
 # Visual Studio 15
-VisualStudioVersion = 15.0.26403.7
+VisualStudioVersion = 15.0.26430.6
 MinimumVisualStudioVersion = 10.0.40219.1
 Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "ParasitemiaUI", "ParasitemiaUI\ParasitemiaUI.fsproj", "{70838E65-F211-44FC-B28F-0ED1CA6E850F}"
 EndProject
@@ -68,4 +68,7 @@ Global
        GlobalSection(Performance) = preSolution
                HasPerformanceSessions = true
        EndGlobalSection
+       GlobalSection(Performance) = preSolution
+               HasPerformanceSessions = true
+       EndGlobalSection
 EndGlobal
index f607760..8b16c45 100644 (file)
@@ -49,7 +49,7 @@ let doAnalysis (img : Image<Bgr, byte>) (name : string) (config : Config) (repor
 
         logWithName "Starting analysis ..."
 
-        use img_float = img.Convert<Bgr, float32>()
+        use img_float = img.Convert<Bgr, float32> ()
 
         use img_RBC = img_float.[1] // Green.
         use img_RBC_filtered = gaussianFilter img_RBC config.LPFStandardDeviationRBC
@@ -66,8 +66,8 @@ let doAnalysis (img : Image<Bgr, byte>) (name : string) (config : Config) (repor
             let delta = config.Parameters.granulometryRange * config.RBCRadiusByResolution.Pixel
             int <| config.RBCRadiusByResolution.Pixel - delta, int <| config.RBCRadiusByResolution.Pixel + delta
 
-        let! radius = logTimeWithName "Granulometry (area)" (fun() -> reportWithVal 10 (Granulometry.findRadiusByAreaClosing img_RBC_filtered range |> float32))
-        //let! radius = logTimeWithName "Granulometry (morpho)" (fun() -> reportWithVal 10 (Granulometry.findRadiusByClosing img_RBC_filtered range 1. true |> float32))
+        let! radius = logTimeWithName "Granulometry (area)" (fun () -> reportWithVal 10 (Granulometry.findRadiusByAreaClosing img_RBC_filtered range |> float32))
+        //let! radius = logTimeWithName "Granulometry (morpho)" (fun () -> reportWithVal 10 (Granulometry.findRadiusByClosing img_RBC_filtered range 1. true |> float32))
         config.SetRBCRadius <| radius
 
         logWithName (sprintf "Found erythrocyte diameter: %O" config.RBCRadius)
@@ -90,10 +90,13 @@ let doAnalysis (img : Image<Bgr, byte>) (name : string) (config : Config) (repor
         let! parasites, imgWhitoutParasite, imgWithoutNucleus =
             logTimeWithName "Parasites segmentation" (fun () -> reportWithVal 40 (ParasitesMarker.find img_parasites_filtered config))
 
-        let! edges, xGradient, yGradient = logTimeWithName "Finding edges" (fun () ->
-            let edges, xGradient, yGradient = Edges.find img_RBC_filtered
-            removeArea edges (config.RBCRadius.Pixel ** 2.f / 50.f |> int)
-            reportWithVal 50 (edges, xGradient, yGradient))
+        let! edges, xGradient, yGradient =
+            logTimeWithName "Finding edges" (
+                fun () ->
+                    let edges, xGradient, yGradient = Edges.find img_RBC_filtered
+                    removeArea edges (config.RBCRadius.Pixel ** 2.f / 50.f |> int)
+                    reportWithVal 50 (edges, xGradient, yGradient)
+            )
 
         let! matchingEllipses = logTimeWithName "Finding ellipses" (fun () -> reportWithVal 60 (Ellipse.find edges xGradient yGradient config))
 
@@ -107,10 +110,10 @@ let doAnalysis (img : Image<Bgr, byte>) (name : string) (config : Config) (repor
             // Output pictures if debug flag is set.
             match config.Debug with
             | DebugOn output ->
-                let dirPath = System.IO.Path.Combine(output, name)
+                let dirPath = System.IO.Path.Combine (output, name)
                 System.IO.Directory.CreateDirectory dirPath |> ignore
 
-                let buildFileName postfix = System.IO.Path.Combine(dirPath, name + postfix)
+                let buildFileName postfix = System.IO.Path.Combine (dirPath, name + postfix)
 
                 IO.saveMat (edges * 255.0) (buildFileName " - edges.png")
 
@@ -118,19 +121,19 @@ let doAnalysis (img : Image<Bgr, byte>) (name : string) (config : Config) (repor
                 IO.saveImg parasites.parasite (buildFileName " - parasites - stain.png")
                 IO.saveImg parasites.nucleus (buildFileName " - parasites - infection.png")
 
-                let imgAllEllipses = img_RBC_filtered.Copy()
-                Drawing.drawEllipses imgAllEllipses matchingEllipses.Ellipses (Gray(200.0)) 0.04
+                let imgAllEllipses = img_RBC_filtered.Copy ()
+                Drawing.drawEllipses imgAllEllipses matchingEllipses.Ellipses (Gray 200.0) 0.04
                 IO.saveImg imgAllEllipses (buildFileName " - ellipses - all.png")
 
-                let imgEllipses = img_RBC_filtered.Convert<Bgr, byte>()
-                Drawing.drawEllipses imgEllipses prunedEllipses (Bgr(0.0, 240.0, 240.0)) 1.0
+                let imgEllipses = img_RBC_filtered.Convert<Bgr, byte> ()
+                Drawing.drawEllipses imgEllipses prunedEllipses (Bgr (0.0, 240.0, 240.0)) 1.0
                 IO.saveImg imgEllipses (buildFileName " - ellipses.png")
 
-                let imgCells = img.Copy()
+                let imgCells = img.Copy ()
                 Drawing.drawCells imgCells false cells
                 IO.saveImg imgCells (buildFileName " - cells.png")
 
-                let imgCells' = img.Copy()
+                let imgCells' = img.Copy ()
                 Drawing.drawCells imgCells' true cells
                 IO.saveImg imgCells' (buildFileName " - cells - full.png")
 
@@ -167,12 +170,12 @@ let doMultipleAnalysis (imgs : (string * Config * Image<Bgr, byte>) list) (repor
         | Some f -> f percent
         | _ -> true
 
-    let progressPerAnalysis = System.Collections.Concurrent.ConcurrentDictionary<string, int>()
+    let progressPerAnalysis = System.Collections.Concurrent.ConcurrentDictionary<string, int> ()
     let nbImgs = List.length imgs
 
     let reportProgressImg (id : string) (progress : int) =
-        progressPerAnalysis.AddOrUpdate(id, progress, (fun _ _ -> progress)) |> ignore
-        report (progressPerAnalysis.Values.Sum() / nbImgs)
+        progressPerAnalysis.AddOrUpdate (id, progress, (fun _ _ -> progress)) |> ignore
+        report (progressPerAnalysis.Values.Sum () / nbImgs)
 
     let n = Environment.ProcessorCount
 
index 665d7d7..9e190e0 100644 (file)
@@ -7,22 +7,22 @@ open System.Runtime.InteropServices
 // General Information about an assembly is controlled through the following
 // set of attributes. Change these attribute values to modify the information
 // associated with an assembly.
-[<assembly: AssemblyTitle("ParasitemiaCore")>]
-[<assembly: AssemblyDescription("")>]
-[<assembly: AssemblyConfiguration("")>]
-[<assembly: AssemblyCompany("HES-SO / CHUV / Grégory Burri")>]
-[<assembly: AssemblyProduct("ParasitemiaCore")>]
-[<assembly: AssemblyCopyright("Copyright © 2015-2016")>]
-[<assembly: AssemblyTrademark("")>]
-[<assembly: AssemblyCulture("")>]
+[<assembly: AssemblyTitle "ParasitemiaCore">]
+[<assembly: AssemblyDescription "">]
+[<assembly: AssemblyConfiguration "">]
+[<assembly: AssemblyCompany "HES-SO / CHUV / Grégory Burri">]
+[<assembly: AssemblyProduct "ParasitemiaCore">]
+[<assembly: AssemblyCopyright "Copyright © 2015-2016">]
+[<assembly: AssemblyTrademark "">]
+[<assembly: AssemblyCulture "">]
 
 // Setting ComVisible to false makes the types in this assembly not visible
 // to COM components.  If you need to access a type in this assembly from
 // COM, set the ComVisible attribute to true on that type.
-[<assembly: ComVisible(false)>]
+[<assembly: ComVisible false>]
 
 // The following GUID is for the ID of the typelib if this project is exposed to COM
-[<assembly: Guid("0f8a85f4-9328-40c3-b8ff-44fb39ceb01f")>]
+[<assembly: Guid "0f8a85f4-9328-40c3-b8ff-44fb39ceb01f">]
 
 // Version information for an assembly consists of the following four values:
 //
@@ -33,9 +33,9 @@ open System.Runtime.InteropServices
 //
 // You can specify all the values or you can default the Build and Revision Numbers
 // by using the '*' as shown below:
-// [<assembly: AssemblyVersion("1.0.*")>]
-[<assembly: AssemblyVersion("1.0.0.10")>]
-[<assembly: AssemblyFileVersion("1.0.0.10")>]
+// [<assembly: AssemblyVersion "1.0.*">]
+[<assembly: AssemblyVersion "1.0.0.10">]
+[<assembly: AssemblyFileVersion "1.0.0.10">]
 
 do
     ()
\ No newline at end of file
index 36e2851..9b247f4 100644 (file)
@@ -45,7 +45,7 @@ let findCells (ellipses : Ellipse list) (parasites : ParasitesMarker.Result) (wi
         let pixelOwnedByE (p : PointF) (e : EllipseFlaggedKd) (neighbors : (EllipseFlaggedKd * PointF * PointF) list) =
             e.Contains p.X p.Y &&
             seq {
-                let c = PointF(e.Cx, e.Cy)
+                let c = PointF (e.Cx, e.Cy)
 
                 for e', d1 in
                     (neighbors
@@ -58,7 +58,7 @@ let findCells (ellipses : Ellipse list) (parasites : ParasitesMarker.Result) (wi
                     )) do
                     if e'.State = e.State then // Peculiar vs peculiar or RBC vs RBC.
                         let d2 = lineFromTwoPoints c p
-                        let c' = PointF(e'.Cx, e'.Cy)
+                        let c' = PointF (e'.Cx, e'.Cy)
                         let v = pointFromTwoLines d1 (lineFromTwoPoints c c')
                         let case1 = sign (v.X - c.X) <> sign (v.X - c'.X) || Utils.squaredDistanceTwoPoints v c > Utils.squaredDistanceTwoPoints v c'
                         if not (Single.IsInfinity d2.A) then
@@ -91,18 +91,19 @@ let findCells (ellipses : Ellipse list) (parasites : ParasitesMarker.Result) (wi
             if e.State <> CellState.Removed then
                 tree.Search (searchRegion e)
                     // We only keep the ellipses touching 'e'.
-                    |> List.choose (fun otherE ->
-                        if e <> otherE then
-                            match EEOver.EEOverlapArea e otherE with
-                            | Some (_, px, _) when px.Length > 2 ->
-                                otherE.State <- CellState.Removed
-                                None
-                            | Some (area, px, py) when area > 0.f && px.Length = 2 ->
-                                Some (otherE, PointF(px.[0], py.[0]), PointF(px.[1], py.[1]))
-                            | _ ->
+                    |> List.choose (
+                        fun otherE ->
+                            if e <> otherE then
+                                match EEOver.EEOverlapArea e otherE with
+                                | Some (_, px, _) when px.Length > 2 ->
+                                    otherE.State <- CellState.Removed
+                                    None
+                                | Some (area, px, py) when area > 0.f && px.Length = 2 ->
+                                    Some (otherE, PointF (px.[0], py.[0]), PointF (px.[1], py.[1]))
+                                | _ ->
+                                    None
+                            else
                                 None
-                        else
-                            None
                     )
             else
                 []
@@ -117,7 +118,7 @@ let findCells (ellipses : Ellipse list) (parasites : ParasitesMarker.Result) (wi
         // 3) Remove ellipses with a high standard deviation (high contrast).
         // Obsolete. It was useful when the ellipses result quality wasn't good.
         (* let imgData = img.Data
-        let globalStdDeviation = MathNet.Numerics.Statistics.Statistics.PopulationStandardDeviation(seq {
+        let globalStdDeviation = MathNet.Numerics.Statistics.Statistics.PopulationStandardDeviation (seq {
             for y in 0 .. h - 1 do
                 for x in 0 .. w - 1 do
                     yield float imgData.[y, x, 0] })
@@ -145,7 +146,7 @@ let findCells (ellipses : Ellipse list) (parasites : ParasitesMarker.Result) (wi
                 let mutable area = 0
                 for y = (if minY < 0 then 0 else minY) to (if maxY >= height then height - 1 else maxY) do
                     for x = (if minX < 0 then 0 else minX) to (if maxX >= width then width - 1 else maxX) do
-                        let p = PointF(float32 x, float32 y)
+                        let p = PointF (float32 x, float32 y)
                         if pixelOwnedByE p e neighbors then
                             area <- area + 1
 
@@ -155,22 +156,24 @@ let findCells (ellipses : Ellipse list) (parasites : ParasitesMarker.Result) (wi
         // 5) Define non-rbc (peculiar) cells.
         let darkStainData = parasites.darkStain.Data
         ellipsesWithNeigbors
-        |> List.choose (fun (e, neighbors) ->
-            if e.State = CellState.Removed then
-                None
-            else
-                let mutable darkStainPixels = 0
-                let mutable nbElement = 0
-                let minX, minY, maxX, maxY = ellipseWindow e
-                for y = minY to maxY do
-                    for x = minX to maxX do
-                        let p = PointF(float32 x, float32 y)
-                        if pixelOwnedByE p e neighbors then
-                            nbElement <- nbElement + 1
-                            if darkStainData.[y, x, 0] > 0uy then
-                                darkStainPixels <- darkStainPixels + 1
+        |> List.choose (
+            fun (e, neighbors) ->
+                if e.State = CellState.Removed then
+                    None
+                else
+                    let mutable darkStainPixels = 0
+                    let mutable nbElement = 0
+                    let minX, minY, maxX, maxY = ellipseWindow e
+                    for y = minY to maxY do
+                        for x = minX to maxX do
+                            let p = PointF (float32 x, float32 y)
+                            if pixelOwnedByE p e neighbors then
+                                nbElement <- nbElement + 1
+                                if darkStainData.[y, x, 0] > 0uy then
+                                    darkStainPixels <- darkStainPixels + 1
 
-                if float darkStainPixels > config.Parameters.maxDarkStainRatio * (float nbElement) then Some e else None)
+                    if float darkStainPixels > config.Parameters.maxDarkStainRatio * (float nbElement) then Some e else None
+        )
 
         // We do not change the state during the process to avoid to have peculiar neighbors which change the behavior of 'pixelOwnedByE'.
         |> List.iter (fun e -> e.State <- CellState.Peculiar)
@@ -191,30 +194,30 @@ let findCells (ellipses : Ellipse list) (parasites : ParasitesMarker.Result) (wi
                 else
                     let minX, minY, maxX, maxY = ellipseWindow e
 
-                    let nucleusPixels = List<Point>()
-                    let parasitePixels = List<Point>()
+                    let nucleusPixels = List<Point> ()
+                    let parasitePixels = List<Point> ()
 
                     let mutable nbElement = 0
 
-                    let elements = new Matrix<byte>(maxY - minY + 1, maxX - minX + 1)
+                    let elements = new Matrix<byte> (maxY - minY + 1, maxX - minX + 1)
                     for y = minY to maxY do
                         for x = minX to maxX do
-                            let p = PointF(float32 x, float32 y)
+                            let p = PointF (float32 x, float32 y)
                             if pixelOwnedByE p e neighbors then
                                 elements.[y - minY, x - minX] <- 1uy
                                 nbElement <- nbElement + 1
 
                                 if nucleusData.[y, x, 0] > 0uy then
-                                    nucleusPixels.Add(Point(x, y))
+                                    nucleusPixels.Add (Point (x, y))
 
                                 if parasiteData.[y, x, 0] > 0uy then
-                                    parasitePixels.Add(Point(x, y))
+                                    parasitePixels.Add (Point (x, y))
 
                     let parasiteArea =
                         if nucleusPixels.Count > 0 then
                             seq {
                                 for parasitePixel in parasitePixels do
-                                    if nucleusPixels.Exists(fun p -> pown (p.X - parasitePixel.X) 2 + pown (p.Y - parasitePixel.Y) 2 <= diameterParasiteSquared) then
+                                    if nucleusPixels.Exists (fun p -> pown (p.X - parasitePixel.X) 2 + pown (p.Y - parasitePixel.Y) 2 <= diameterParasiteSquared) then
                                         yield 1
                             } |> Seq.sum
                         else
@@ -236,7 +239,7 @@ let findCells (ellipses : Ellipse list) (parasites : ParasitesMarker.Result) (wi
                     Some
                         {
                             cellClass = cellClass
-                            center = Point(roundInt e.Cx, roundInt e.Cy)
+                            center = Point (roundInt e.Cx, roundInt e.Cy)
                             nucleusArea = if cellClass = InfectedRBC then nucleusPixels.Count else 0
                             parasiteArea = parasiteArea
                             elements = elements
index fdeed8f..e000d65 100644 (file)
@@ -98,7 +98,7 @@ type RBCRadius (radius : float32, parameters : Parameters) =
     member this.NucleusArea = parameters.nucleusAreaRatio * this.Area
     member this.MinimumParasiteArea = parameters.minimumParasiteAreaRatio * this.Area
 
-    override this.ToString() =
+    override this.ToString () =
         sprintf "%d px (%.1f μm)" (Utils.roundInt <| 2.f * radius) (2. * this.μm)
 
 type Config (param : Parameters) =
@@ -108,17 +108,17 @@ type Config (param : Parameters) =
         float32 rbcRadiusPx
 
     let mutable parameters : Parameters = param
-    let mutable rbcRadiusByResolution = RBCRadius(RBCadiusInPixels parameters.rbcDiameter parameters.resolution, parameters)
-    let mutable rbcRadius = RBCRadius(0.f, parameters)
+    let mutable rbcRadiusByResolution = RBCRadius (RBCadiusInPixels parameters.rbcDiameter parameters.resolution, parameters)
+    let mutable rbcRadius = RBCRadius (0.f, parameters)
 
-    new () = Config(defaultParameters)
+    new () = Config defaultParameters
 
     member this.Parameters
-        with get() = parameters
-        and set(param) =
+        with get () = parameters
+        and set param =
             parameters <- param
-            rbcRadiusByResolution <- RBCRadius(RBCadiusInPixels parameters.rbcDiameter parameters.resolution, param)
-            rbcRadius <- RBCRadius(rbcRadius.Pixel, param)
+            rbcRadiusByResolution <- RBCRadius (RBCadiusInPixels parameters.rbcDiameter parameters.resolution, param)
+            rbcRadius <- RBCRadius (rbcRadius.Pixel, param)
 
     member val Debug = DebugOff with get, set
 
@@ -134,8 +134,8 @@ type Config (param : Parameters) =
     member this.RBCRadius = rbcRadius
 
     member this.SetRBCRadius (radiusPixel : float32) =
-        rbcRadius <- RBCRadius(radiusPixel, parameters)
+        rbcRadius <- RBCRadius (radiusPixel, parameters)
 
     member this.Copy () =
-        this.MemberwiseClone() :?> Config
+        this.MemberwiseClone () :?> Config
 
index 0824e98..422e86f 100644 (file)
@@ -356,7 +356,7 @@ let private cubicroots (p : float[]) (r : float[,]) =
             else
                 b <- d
             c <- t / b
-        d <- sqrt(0.75) * (b - c)
+        d <- sqrt 0.75 * (b - c)
         r.[2, 2] <- d
         b <- b + c
         c <- -0.5 * b - s
@@ -609,8 +609,8 @@ let EEOverlapArea (e1 : Types.Ellipse) (e2 : Types.Ellipse) : (float32 * float32
                 let x2 = -x1
 
 #if DEBUG_LOG
-                printf "\n\tx1=%f, y1=%f, A=%f. B=%f ---> ellipse2tr(x1)= %f\n" x1 ychk.[i] a1 b1 (ellipse2tr x1 ychk.[i] aa bb cc dd ee ff)
-                printf "\tx2=%f, y1=%f, A=%f. B=%f ---> ellipse2tr(x2)= %f\n" x2 ychk.[i] a1 b1 (ellipse2tr x2 ychk.[i] aa bb cc dd ee ff)
+                printf "\n\tx1=%f, y1=%f, A=%f. B=%f ---> ellipse2tr (x1)= %f\n" x1 ychk.[i] a1 b1 (ellipse2tr x1 ychk.[i] aa bb cc dd ee ff)
+                printf "\tx2=%f, y1=%f, A=%f. B=%f ---> ellipse2tr (x2)= %f\n" x2 ychk.[i] a1 b1 (ellipse2tr x2 ychk.[i] aa bb cc dd ee ff)
 #endif
 
                 if abs (ellipse2tr x1 ychk.[i] aa bb cc dd ee ff) < EPS then
index 174dd68..d0dea6e 100644 (file)
@@ -23,7 +23,7 @@ let minimumDistanceBetweenDrawnPoints = 0.6
 /// 'Ellipse.Alpha' is between 0 and Pi.
 /// </summary>
 let ellipse (p1x : float) (p1y : float) (m1 : float) (p2x : float) (p2y : float) (m2 : float) (p3x : float) (p3y : float) : Types.Ellipse option =
-    let p0 = pointFromTwoLines (Types.Line(float32 m1, float32 (p1y - m1 * p1x))) (Types.Line(float32 m2, float32(p2y - m2 * p2x)))
+    let p0 = pointFromTwoLines (Types.Line (float32 m1, float32 (p1y - m1 * p1x))) (Types.Line (float32 m2, float32(p2y - m2 * p2x)))
     let p0x, p0y = float p0.X, float p0.Y
 
     let s =
@@ -39,8 +39,8 @@ let ellipse (p1x : float) (p1y : float) (m1 : float) (p2x : float) (p2y : float)
     let v2 = matrix [[ 1.; p2x; p2y ]]
     let v3 = matrix [[ 1.; p3x; p3y ]]
 
-    let p = (v3.Stack(v1).Stack(v2).Determinant() * v0).Stack(v0.Stack(v3).Stack(v2).Determinant() * v1).Stack(v0.Stack(v1).Stack(v3).Determinant() * v2).Transpose()
-    let conicMat = p * s.Inverse() * p.Transpose()
+    let p = (v3.Stack(v1).Stack(v2).Determinant () * v0).Stack(v0.Stack(v3).Stack(v2).Determinant () * v1).Stack(v0.Stack(v1).Stack(v3).Determinant () * v2).Transpose ()
+    let conicMat = p * s.Inverse () * p.Transpose ()
     let a = conicMat.[0, 0]
     let b = conicMat.[0, 1]
     let c = conicMat.[1, 1]
@@ -57,7 +57,7 @@ let ellipse (p1x : float) (p1y : float) (m1 : float) (p2x : float) (p2y : float)
         None
     else
         let q = (-1. / at) * (matrix [[ a * f - d ** 2.0; b * d - a * e ]; [ b * d - a * e; a * c - b ** 2.0 ]])
-        let eigen = q.Evd()
+        let eigen = q.Evd ()
         let eigenValues = eigen.EigenValues
         let lambda = eigenValues.[1].Real
         let mu = eigenValues.[0].Real
@@ -77,7 +77,7 @@ let ellipse (p1x : float) (p1y : float) (m1 : float) (p2x : float) (p2y : float)
             let phi' = if phi < 0. then phi + Math.PI else phi
             let majorAxis, minorAxis = if r1 > r2 then r1, r2 else r2, r1
 
-            Some (Types.Ellipse(float32 cx, float32 cy, float32 majorAxis, float32 minorAxis, float32 phi'))
+            Some (Types.Ellipse (float32 cx, float32 cy, float32 majorAxis, float32 minorAxis, float32 phi'))
 
 let inline private vectorRotation (px : float32) (py : float32) (vx : float32) (vy : float32) (p0x : float32) (p0y : float32) : float32 =
     if py > p0y then
@@ -150,15 +150,15 @@ let find (edges : Matrix<byte>)
 
     let mutable last_i, last_j = Int32.MaxValue, Int32.MaxValue
 
-    let currentElements = List<Point>()
+    let currentElements = List<Point> ()
 
     let edgesData = edges.Data
     let xDirData = xGradient.Data
     let yDirData = yGradient.Data
 
-    let rng = Random(42)
+    let rng = Random 42
 
-    let ellipses = MatchingEllipses(config.RBCRadius.Pixel)
+    let ellipses = MatchingEllipses config.RBCRadius.Pixel
 
     for window_i in -windowSize + increment .. increment .. h - increment do
         for window_j in -windowSize + increment .. increment .. w - increment do
@@ -169,9 +169,9 @@ let find (edges : Matrix<byte>)
             let window_j_end = if window_j + windowSize - 1 >= w then w - 1 else window_j + windowSize - 1
 
             // Remove old elements.
-            let indexFirstElement = currentElements.FindIndex(fun p -> p.X >= window_j_begin)
+            let indexFirstElement = currentElements.FindIndex (fun p -> p.X >= window_j_begin)
             if indexFirstElement > 0 then
-                currentElements.RemoveRange(0, indexFirstElement)
+                currentElements.RemoveRange (0, indexFirstElement)
 
             // Add the new elements.
             let newElemsBegin_j = window_j + windowSize - increment
@@ -179,15 +179,15 @@ let find (edges : Matrix<byte>)
             for j = (if newElemsBegin_j < 0 then 0 else newElemsBegin_j) to (if newElemsEnd_j >= w then w - 1 else newElemsEnd_j) do
                 for i = window_i_begin to window_i_end do
                     if edgesData.[i, j] = 1uy then
-                        currentElements.Add(Point(j, i))
+                        currentElements.Add (Point (j, i))
 
             if currentElements.Count >= nbPickElementsMin then
                 let mutable nbOfPicks = (float currentElements.Count) * factorNbMaxPick |> int
                 let mutable nbOfValidPicks = (float currentElements.Count) * factorNbValidPick |> int
                 while nbOfPicks > 0 && nbOfValidPicks > 0 do
-                    let p1 = currentElements.[rng.Next(currentElements.Count)]
-                    let p2 = currentElements.[rng.Next(currentElements.Count)]
-                    let p3 = currentElements.[rng.Next(currentElements.Count)]
+                    let p1 = currentElements.[rng.Next currentElements.Count]
+                    let p2 = currentElements.[rng.Next currentElements.Count]
+                    let p3 = currentElements.[rng.Next currentElements.Count]
                     if p1 <> p2 && p1 <> p3 && p2 <> p3 then
                         nbOfPicks <- nbOfPicks - 1
                         let p1yf, p1xf = float p1.Y, float p1.X
@@ -207,7 +207,7 @@ let find (edges : Matrix<byte>)
                                 | _ -> ()
                             | _ -> ()
 
-        currentElements.Clear()
+        currentElements.Clear ()
 
     ellipses
 
index bbb6d66..287cd3e 100644 (file)
@@ -16,7 +16,7 @@ open Utils
 /// <param name="range">Minimum radius * maximum radius</param>
 /// <param name="scale">le 1.0, to speed up the process.</param>
 let findRadiusByClosing (img : Image<Gray, 'TDepth>) (range : int * int) (scale : float) (useOctagon : bool) : int =
-    use scaledImg = if scale = 1. then img else img.Resize(scale, CvEnum.Inter.Area)
+    use scaledImg = if scale = 1. then img else img.Resize (scale, CvEnum.Inter.Area)
 
     let r1, r2 = range
     let r1', r2' = roundInt (float r1 * scale), roundInt (float r2 * scale)
@@ -27,7 +27,7 @@ let findRadiusByClosing (img : Image<Gray, 'TDepth>) (range : int * int) (scale
     // 's' must be odd.
     let octagon (s : int) : Matrix<byte> =
         if s % 2 = 0 then failwith "s must be odd"
-        let m = new Matrix<byte>(Array2D.create s s 1uy)
+        let m = new Matrix<byte> (Array2D.create s s 1uy)
         let r = (float s) / (Math.Sqrt 2. + 2.) |> roundInt
         for i = 0 to r - 1 do
             for j = 0 to r - 1 do
@@ -44,9 +44,9 @@ let findRadiusByClosing (img : Image<Gray, 'TDepth>) (range : int * int) (scale
             if useOctagon then
                 (octagon (2 * r - 1)).Mat // It doesn't speed up the process.
             else
-                CvInvoke.GetStructuringElement(CvEnum.ElementShape.Ellipse, Size(2 * r, 2 * r), Point(-1, -1))
+                CvInvoke.GetStructuringElement (CvEnum.ElementShape.Ellipse, Size (2 * r, 2 * r), Point (-1, -1))
 
-        use closed = scaledImg.MorphologyEx(CvEnum.MorphOp.Close, se, Point(-1, -1), 1, CvEnum.BorderType.Replicate, MCvScalar(0.0))
+        use closed = scaledImg.MorphologyEx (CvEnum.MorphOp.Close, se, Point (-1, -1), 1, CvEnum.BorderType.Replicate, MCvScalar (0.0))
 
         let n = closed.GetSum().Intensity
 
@@ -67,14 +67,17 @@ let findRadiusByAreaClosing (img : Image<Gray, float32>) (radiusRange : int * in
     if r1 > r2 then
         failwithf "'radiusRange' invalid : %O" radiusRange
 
-    use imgCopy = img.Copy()
+    use imgCopy = img.Copy ()
 
     let mutable maxDiff = 0.f
     let mutable max_r = r1
 
-    Morpho.areaCloseFWithFun imgCopy [ for r in r1 .. r2 -> Math.PI * float r ** 2. |> roundInt, r ] (fun r diff ->
-        if r <> r1 && diff > maxDiff then
-            maxDiff <- diff
-            max_r <- r - 1)
+    Morpho.areaCloseFWithFun imgCopy [ for r in r1 .. r2 -> Math.PI * float r ** 2. |> roundInt, r ] (
+        fun r diff ->
+            if r <> r1 && diff > maxDiff then
+                maxDiff <- diff
+                max_r <- r - 1
+    )
+
     max_r
 
index 350164b..356ea06 100644 (file)
@@ -18,16 +18,16 @@ type private Node<'k, 'v> =
 /// The goal is to have a set of data and be able to get the value associated with the min (or max) key value.
 /// </summary>
 type Heap<'k, 'v> (kComparer : IComparer<'k>) =
-    let a = List<Node<'k, 'v>>()
+    let a = List<Node<'k, 'v>> ()
 
     let rec heapUp (i : int) =
         let l, r = left i, right i
 
         // Is the left child greater than the parent?
-        let mutable max = if l < a.Count && kComparer.Compare(a.[l].key, a.[i].key) > 0 then l else i
+        let mutable max = if l < a.Count && kComparer.Compare (a.[l].key, a.[i].key) > 0 then l else i
 
         // Is the right child greater than the parent and the left child?
-        if r < a.Count && kComparer.Compare(a.[r].key, a.[max].key) > 0 then
+        if r < a.Count && kComparer.Compare (a.[r].key, a.[max].key) > 0 then
             max <- r
 
         // If a child is greater than the parent.
@@ -42,41 +42,41 @@ type Heap<'k, 'v> (kComparer : IComparer<'k>) =
         let l, r = left i, right i
         let leftIntegrity =
             if l < a.Count then
-                if kComparer.Compare(a.[l].key, a.[i].key) > 0 then false else checkIntegrity l
+                if kComparer.Compare (a.[l].key, a.[i].key) > 0 then false else checkIntegrity l
             else
                 true
         let rightIntegrity =
             if r < a.Count then
-                if kComparer.Compare(a.[r].key, a.[i].key) > 0 then false else checkIntegrity r
+                if kComparer.Compare (a.[r].key, a.[i].key) > 0 then false else checkIntegrity r
             else
                 true
         leftIntegrity && rightIntegrity
 
     interface IEnumerable<'k * 'v> with
         member this.GetEnumerator () : IEnumerator<'k * 'v> =
-            (seq { for e in a -> e.key, e.value }).GetEnumerator()
+            (seq { for e in a -> e.key, e.value }).GetEnumerator ()
 
     interface System.Collections.IEnumerable with
         member this.GetEnumerator () : System.Collections.IEnumerator =
-            (this :> IEnumerable<'k * 'v>).GetEnumerator() :> System.Collections.IEnumerator
+            (this :> IEnumerable<'k * 'v>).GetEnumerator () :> System.Collections.IEnumerator
 
     member this.Next () : 'k * 'v =
         let node = a.[0]
         a.[0] <- a.[a.Count - 1]
-        a.RemoveAt(a.Count - 1)
+        a.RemoveAt (a.Count - 1)
         heapUp 0
         node.key, node.value
 
     member this.RemoveNext () =
         a.[0] <- a.[a.Count - 1]
-        a.RemoveAt(a.Count - 1)
+        a.RemoveAt (a.Count - 1)
         heapUp 0
 
     member this.Add (key : 'k) (value : 'v) =
-        a.Add(Node(key, value))
+        a.Add (Node (key, value))
 
         let mutable i = a.Count - 1
-        while i > 0 && kComparer.Compare(a.[parent i].key, a.[i].key) < 0 do
+        while i > 0 && kComparer.Compare (a.[parent i].key, a.[i].key) < 0 do
             let tmp = a.[parent i]
             a.[parent i] <- a.[i]
             a.[i] <- tmp
@@ -89,4 +89,4 @@ type Heap<'k, 'v> (kComparer : IComparer<'k>) =
         let max = a.[0]
         max.key, max.value
 
-    member this.Clear () = a.Clear()
+    member this.Clear () = a.Clear ()
index 9662049..2882f4b 100644 (file)
@@ -14,14 +14,14 @@ let drawPoints (img : Image<Gray, 'TDepth>) (points : Points) (intensity : 'TDep
         img.Data.[p.Y, p.X, 0] <- intensity
 
 let drawLine (img : Image<'TColor, 'TDepth>) (color : 'TColor) (x0 : int) (y0 : int) (x1 : int) (y1 : int) (thickness : int) =
-    img.Draw(LineSegment2D(Point(x0, y0), Point(x1, y1)), color, thickness);
+    img.Draw (LineSegment2D (Point (x0, y0), Point (x1, y1)), color, thickness);
 
 let drawLineF (img : Image<'TColor, 'TDepth>) (color : 'TColor) (x0 : float) (y0 : float) (x1 : float) (y1 : float) (thickness : int) =
-    img.Draw(LineSegment2DF(PointF(float32 x0, float32 y0), PointF(float32 x1, float32 y1)), color, thickness, CvEnum.LineType.AntiAlias);
+    img.Draw (LineSegment2DF (PointF (float32 x0, float32 y0), PointF  (float32 x1, float32 y1)), color, thickness, CvEnum.LineType.AntiAlias);
 
 let drawEllipse (img : Image<'TColor, 'TDepth>) (e : Ellipse) (color : 'TColor) (alpha : float) =
     if alpha >= 1.0 then
-        img.Draw(Emgu.CV.Structure.Ellipse(PointF(e.Cx, e.Cy), SizeF(2.f * e.B, 2.f * e.A), e.Alpha / PI * 180.f), color, 1, CvEnum.LineType.AntiAlias)
+        img.Draw (Emgu.CV.Structure.Ellipse (PointF (e.Cx, e.Cy), SizeF (2.f * e.B, 2.f * e.A), e.Alpha / PI * 180.f), color, 1, CvEnum.LineType.AntiAlias)
     else
         let windowPosX = e.Cx - e.A - 5.f
         let gapX = windowPosX - (float32 (int windowPosX))
@@ -29,24 +29,24 @@ let drawEllipse (img : Image<'TColor, 'TDepth>) (e : Ellipse) (color : 'TColor)
         let windowPosY = e.Cy - e.A - 5.f
         let gapY = windowPosY - (float32 (int windowPosY))
 
-        let roi = Rectangle(int windowPosX, int windowPosY, 2.f * (e.A + 5.f) |> int, 2.f * (e.A + 5.f) |> int)
+        let roi = Rectangle (int windowPosX, int windowPosY, 2.f * (e.A + 5.f) |> int, 2.f * (e.A + 5.f) |> int)
 
         img.ROI <- roi
         if roi = img.ROI then // We do not display ellipses touching the edges (FIXME)
-            use i = new Image<'TColor, 'TDepth>(img.ROI.Size)
-            i.Draw(Emgu.CV.Structure.Ellipse(PointF(e.A + 5.f + gapX, e.A + 5.f + gapY), SizeF(2.f * e.B, 2.f * e.A), e.Alpha / PI * 180.f), color, 1, CvEnum.LineType.AntiAlias)
-            CvInvoke.AddWeighted(img, 1.0, i, alpha, 0.0, img)
+            use i = new Image<'TColor, 'TDepth> (img.ROI.Size)
+            i.Draw (Emgu.CV.Structure.Ellipse(PointF(e.A + 5.f + gapX, e.A + 5.f + gapY), SizeF(2.f * e.B, 2.f * e.A), e.Alpha / PI * 180.f), color, 1, CvEnum.LineType.AntiAlias)
+            CvInvoke.AddWeighted (img, 1.0, i, alpha, 0.0, img)
         img.ROI <- Rectangle.Empty
 
 let drawEllipses (img : Image<'TColor, 'TDepth>) (ellipses : Ellipse list) (color : 'TColor) (alpha : float) =
     List.iter (fun e -> drawEllipse img e color alpha) ellipses
 
-let rngCell =  System.Random()
+let rngCell =  System.Random ()
 let drawCell (img : Image<Bgr, byte>) (drawCellContent : bool) (c : Cell) =
     if drawCellContent then
-        let colorB = rngCell.Next(20, 70)
-        let colorG = rngCell.Next(20, 70)
-        let colorR = rngCell.Next(20, 70)
+        let colorB = rngCell.Next (20, 70)
+        let colorG = rngCell.Next (20, 70)
+        let colorR = rngCell.Next (20, 70)
 
         for y = 0 to c.elements.Height - 1 do
             for x = 0 to c.elements.Width - 1 do
@@ -61,9 +61,9 @@ let drawCell (img : Image<Bgr, byte>) (drawCellContent : bool) (c : Cell) =
 
     let crossColor, crossColor2 =
         match c.cellClass with
-        | HealthyRBC -> Bgr(255., 0., 0.), Bgr(255., 255., 255.)
-        | InfectedRBC -> Bgr(0., 0., 255.), Bgr(120., 120., 255.)
-        | Peculiar -> Bgr(0., 0., 0.), Bgr(80., 80., 80.)
+        | HealthyRBC -> Bgr (255., 0., 0.), Bgr (255., 255., 255.)
+        | InfectedRBC -> Bgr (0., 0., 255.), Bgr (120., 120., 255.)
+        | Peculiar -> Bgr (0., 0., 0.), Bgr (80., 80., 80.)
 
     drawLine img crossColor2 (c.center.X - 3) c.center.Y (c.center.X + 3) c.center.Y 2
     drawLine img crossColor2 c.center.X (c.center.Y - 3) c.center.X (c.center.Y + 3) 2
index 63ec80a..7c3e6d3 100644 (file)
@@ -25,27 +25,27 @@ let find (img : Image<Gray, float32>) : Matrix<byte> * Matrix<float32> * Matrix<
     let h = img.Height
 
     use sobelKernel =
-        new Matrix<float32>(
+        new Matrix<float32> (
             array2D [[ -1.0f; 0.0f; 1.0f ]
                      [ -2.0f; 0.0f; 2.0f ]
                      [ -1.0f; 0.0f; 1.0f ]]
         )
 
-    let xGradient = new Matrix<float32>(img.Size)
-    let yGradient = new Matrix<float32>(img.Size)
-    CvInvoke.Filter2D(img, xGradient, sobelKernel, Point(1, 1))
-    CvInvoke.Filter2D(img, yGradient, sobelKernel.Transpose(), Point(1, 1))
+    let xGradient = new Matrix<float32> (img.Size)
+    let yGradient = new Matrix<float32> (img.Size)
+    CvInvoke.Filter2D (img, xGradient, sobelKernel, Point (1, 1))
+    CvInvoke.Filter2D (img, yGradient, sobelKernel.Transpose (), Point (1, 1))
 
-    use magnitudes = new Matrix<float32>(xGradient.Size)
-    use angles = new Matrix<float32>(xGradient.Size)
-    CvInvoke.CartToPolar(xGradient, yGradient, magnitudes, angles) // Compute the magnitudes and angles. The angles are between 0 and 2 * pi.
+    use magnitudes = new Matrix<float32> (xGradient.Size)
+    use angles = new Matrix<float32> (xGradient.Size)
+    CvInvoke.CartToPolar (xGradient, yGradient, magnitudes, angles) // Compute the magnitudes and angles. The angles are between 0 and 2 * pi.
 
     let thresholdHigh, thresholdLow =
         let threshold, _, _ = otsu (histogramMat magnitudes 300)
         threshold + (sensibilityHigh * threshold), threshold - (sensibilityLow * threshold)
 
     // Non-maximum suppression.
-    use nms = new Matrix<byte>(xGradient.Size)
+    use nms = new Matrix<byte> (xGradient.Size)
 
     let nmsData = nms.Data
     let anglesData = angles.Data
@@ -88,18 +88,18 @@ let find (img : Image<Gray, float32>) : Matrix<byte> * Matrix<float32> * Matrix<
 
     // suppressMConnections nms // It's not helpful for the rest of the process (ellipse detection).
 
-    let edges = new Matrix<byte>(xGradient.Size)
+    let edges = new Matrix<byte> (xGradient.Size)
     let edgesData = edges.Data
 
     // Hysteresis thresholding.
-    let toVisit = Stack<Point>()
+    let toVisit = Stack<Point> ()
     for i = 0 to h - 1 do
         for j = 0 to w - 1 do
             if nmsData.[i, j] = 1uy && magnitudesData.[i, j] >= thresholdHigh then
                 nmsData.[i, j] <- 0uy
-                toVisit.Push(Point(j, i))
+                toVisit.Push (Point (j, i))
                 while toVisit.Count > 0 do
-                    let p = toVisit.Pop()
+                    let p = toVisit.Pop ()
                     edgesData.[p.Y, p.X] <- 1uy
                     for i' = -1 to 1  do
                         for j' = -1 to 1 do
@@ -108,6 +108,6 @@ let find (img : Image<Gray, float32>) : Matrix<byte> * Matrix<float32> * Matrix<
                                 let nj = p.X + j'
                                 if ni >= 0 && ni < h && nj >= 0 && nj < w && nmsData.[ni, nj] = 1uy then
                                     nmsData.[ni, nj] <- 0uy
-                                    toVisit.Push(Point(nj, ni))
+                                    toVisit.Push (Point (nj, ni))
 
     edges, xGradient, yGradient
\ No newline at end of file
index df1ecb6..718a9de 100644 (file)
@@ -20,10 +20,10 @@ let histogramImg (img : Image<Gray, float32>) (nbSamples : int) : Histogram =
 
     let min, max =
         let min = ref [| 0.0 |]
-        let minLocation = ref <| [| Point() |]
+        let minLocation = ref <| [| Point () |]
         let max = ref [| 0.0 |]
-        let maxLocation = ref <| [| Point() |]
-        img.MinMax(min, max, minLocation, maxLocation)
+        let maxLocation = ref <| [| Point () |]
+        img.MinMax (min, max, minLocation, maxLocation)
         float32 (!min).[0], float32 (!max).[0]
 
     let inline bin (x : float32) : int =
@@ -44,10 +44,10 @@ let histogramMat (mat : Matrix<float32>) (nbSamples : int) : Histogram =
 
     let min, max =
         let min = ref 0.0
-        let minLocation = ref <| Point()
+        let minLocation = ref <| Point ()
         let max = ref 0.0
-        let maxLocation = ref <| Point()
-        mat.MinMax(min, max, minLocation, maxLocation)
+        let maxLocation = ref <| Point ()
+        mat.MinMax (min, max, minLocation, maxLocation)
         float32 !min, float32 !max
 
     let inline bin (x : float32) : int =
index 1a663c7..08adfb0 100644 (file)
@@ -7,9 +7,9 @@ open Emgu.CV
 open Emgu.CV.Structure
 
 let saveImg (img : Image<'TColor, 'TDepth>) (filepath : string) =
-    img.Save(filepath)
+    img.Save filepath
 
 let saveMat (mat : Matrix<'TDepth>) (filepath : string) =
-    use img = new Image<Gray, 'TDeph>(mat.Size)
-    mat.CopyTo(img)
+    use img = new Image<Gray, 'TDeph> (mat.Size)
+    mat.CopyTo img
     saveImg img filepath
index 5a404e3..fc89047 100644 (file)
@@ -14,10 +14,10 @@ open Emgu.CV.Structure
 /// <param name="upperLimit"></param>
 let normalize (img : Image<Gray, float32>) (upperLimit : float) : Image<Gray, float32> =
     let min = ref [| 0.0 |]
-    let minLocation = ref <| [| Point() |]
+    let minLocation = ref <| [| Point () |]
     let max = ref [| 0.0 |]
-    let maxLocation = ref <| [| Point() |]
-    img.MinMax(min, max, minLocation, maxLocation)
+    let maxLocation = ref <| [| Point () |]
+    img.MinMax (min, max, minLocation, maxLocation)
     let normalized = (img - (!min).[0]) / ((!max).[0] - (!min).[0])
     if upperLimit = 1.0 then
         normalized
@@ -30,17 +30,17 @@ let mergeChannels (img : Image<Bgr, float32>) (rgbWeights : float * float * floa
     | 0., 1., 0. -> img.[1]
     | 0., 0., 1. -> img.[0]
     | redFactor, greenFactor, blueFactor ->
-        let result = new Image<Gray, float32>(img.Size)
-        CvInvoke.AddWeighted(result, 1., img.[2], redFactor, 0., result)
-        CvInvoke.AddWeighted(result, 1., img.[1], greenFactor, 0., result)
-        CvInvoke.AddWeighted(result, 1., img.[0], blueFactor, 0., result)
+        let result = new Image<Gray, float32> (img.Size)
+        CvInvoke.AddWeighted (result, 1., img.[2], redFactor, 0., result)
+        CvInvoke.AddWeighted (result, 1., img.[1], greenFactor, 0., result)
+        CvInvoke.AddWeighted (result, 1., img.[0], blueFactor, 0., result)
         result
 
 let mergeChannelsWithProjection (img : Image<Bgr, float32>) (v1r : float32, v1g : float32, v1b : float32) (v2r : float32, v2g : float32, v2b : float32) (upperLimit : float)  : Image<Gray, float32> =
     let vr, vg, vb = v2r - v1r, v2g - v1g, v2b - v1b
     let vMagnitude = sqrt (vr ** 2.f + vg ** 2.f + vb ** 2.f)
     let project (r : float32) (g : float32) (b : float32) = ((r - v1r) * vr + (g - v1g) * vg + (b - v1b) * vb) / vMagnitude
-    let result = new Image<Gray, float32>(img.Size)
+    let result = new Image<Gray, float32> (img.Size)
     // TODO: Essayer en bindant Data pour gagner du temps
     for i = 0 to img.Height - 1 do
         for j = 0 to img.Width - 1 do
@@ -49,8 +49,8 @@ let mergeChannelsWithProjection (img : Image<Bgr, float32>) (v1r : float32, v1g
 
 // Normalize image values between 0uy and 255uy.
 let normalizeAndConvert (img : Image<Gray, 'TDepth>) : Image<Gray, byte> =
-    (normalize (img.Convert<Gray, float32>()) 255.).Convert<Gray, byte>()
+    (normalize (img.Convert<Gray, float32> ()) 255.).Convert<Gray, byte> ()
 
 let gaussianFilter (img : Image<'TColor, 'TDepth>) (standardDeviation : float) : Image<'TColor, 'TDepth> =
     let size = 2 * int (ceil (4.0 * standardDeviation)) + 1
-    img.SmoothGaussian(size, size, standardDeviation, standardDeviation)
+    img.SmoothGaussian (size, size, standardDeviation, standardDeviation)
index 6c8d7a0..d2826bf 100644 (file)
@@ -37,28 +37,28 @@ let inline findExtremum (img : Image<Gray, 'TDepth>) (extremumType : ExtremumTyp
     let imgData = img.Data
     let suppress : bool[,] = Array2D.zeroCreate h w
 
-    let result = List<List<Point>>()
+    let result = List<List<Point>> ()
 
     let flood (start : Point) : List<List<Point>> =
-        let sameLevelToCheck = Stack<Point>()
-        let betterLevelToCheck = Stack<Point>()
-        betterLevelToCheck.Push(start)
+        let sameLevelToCheck = Stack<Point> ()
+        let betterLevelToCheck = Stack<Point> ()
+        betterLevelToCheck.Push start
 
-        let result' = List<List<Point>>()
+        let result' = List<List<Point>> ()
 
         while betterLevelToCheck.Count > 0 do
-            let p = betterLevelToCheck.Pop()
+            let p = betterLevelToCheck.Pop ()
             if not suppress.[p.Y, p.X] then
                 suppress.[p.Y, p.X] <- true
-                sameLevelToCheck.Push(p)
-                let current = List<Point>()
+                sameLevelToCheck.Push p
+                let current = List<Point> ()
 
                 let mutable betterExists = false
 
                 while sameLevelToCheck.Count > 0 do
-                    let p' = sameLevelToCheck.Pop()
+                    let p' = sameLevelToCheck.Pop ()
                     let currentLevel = imgData.[p'.Y, p'.X, 0]
-                    current.Add(p') |> ignore
+                    current.Add p' |> ignore
                     for i, j in se do
                         let ni = i + p'.Y
                         let nj = j + p'.X
@@ -68,23 +68,23 @@ let inline findExtremum (img : Image<Gray, 'TDepth>) (extremumType : ExtremumTyp
 
                             if notSuppressed && level = currentLevel then
                                 suppress.[ni, nj] <- true
-                                sameLevelToCheck.Push(Point(nj, ni))
+                                sameLevelToCheck.Push (Point (nj, ni))
                             elif (if extremumType = ExtremumType.Maxima then level > currentLevel else level < currentLevel) then
                                 betterExists <- true
                                 if notSuppressed then
-                                    betterLevelToCheck.Push(Point(nj, ni))
+                                    betterLevelToCheck.Push (Point (nj, ni))
 
                 if not betterExists then
-                    result'.Add(current)
+                    result'.Add current
         result'
 
     for i = 0 to h - 1 do
         for j = 0 to w - 1 do
-            let maxima = flood (Point(j, i))
+            let maxima = flood (Point (j, i))
             if maxima.Count > 0 then
-                result.AddRange(maxima)
+                result.AddRange maxima
 
-    result.Select(fun l -> Points(l))
+    result.Select (fun l -> Points l)
 
 let inline findMaxima (img : Image<Gray, 'TDepth>) : IEnumerable<Points> when 'TDepth : unmanaged =
     findExtremum img ExtremumType.Maxima
@@ -94,7 +94,7 @@ let inline findMinima (img : Image<Gray, 'TDepth>) : IEnumerable<Points> when 'T
 
 type PriorityQueue () =
     let size = 256
-    let q : Points[] = Array.init size (fun i -> Points())
+    let q : Points[] = Array.init size (fun i -> Points ())
     let mutable highest = -1 // Value of the first elements of 'q'.
     let mutable lowest = size
 
@@ -103,8 +103,8 @@ type PriorityQueue () =
             invalidOp "Queue is empty"
         else
             let l = q.[highest]
-            let next = l.First()
-            l.Remove(next) |> ignore
+            let next = l.First ()
+            l.Remove next |> ignore
             let value = byte highest
 
             if l.Count = 0 then
@@ -122,8 +122,8 @@ type PriorityQueue () =
             invalidOp "Queue is empty"
         else
             let l = q.[lowest + 1]
-            let next = l.First()
-            l.Remove(next) |> ignore
+            let next = l.First ()
+            l.Remove next |> ignore
             let value = byte (lowest + 1)
 
             if l.Count = 0 then
@@ -150,11 +150,11 @@ type PriorityQueue () =
         if vi <= lowest then
             lowest <- vi - 1
 
-        q.[vi].Add(p) |> ignore
+        q.[vi].Add p |> ignore
 
     member this.Remove (value : byte) (p : Point) =
         let vi = int value
-        if q.[vi].Remove(p) && q.[vi].Count = 0 then
+        if q.[vi].Remove p && q.[vi].Count = 0 then
             if vi = highest then
                 highest <- highest - 1
                 while highest > lowest && q.[highest].Count = 0 do
@@ -173,7 +173,7 @@ type PriorityQueue () =
 
     member this.Clear () =
         while highest > lowest  do
-            q.[highest].Clear()
+            q.[highest].Clear ()
             highest <- highest - 1
         highest <- -1
         lowest <- size
@@ -199,33 +199,33 @@ let private areaOperation (img : Image<Gray, byte>) (area : int) (op : AreaOpera
     let imgData = img.Data
     let se = [| -1, 0; 0, -1; 1, 0; 0, 1 |]
 
-    let areas = List<Area>((if op = AreaOperation.Opening then findMaxima img else findMinima img) |> Seq.map Area)
+    let areas = List<Area> ((if op = AreaOperation.Opening then findMaxima img else findMinima img) |> Seq.map Area)
 
     let pixels : Area[,] = Array2D.create h w null
     for m in areas do
         for e in m.Elements do
             pixels.[e.Y, e.X] <- m
 
-    let queue = PriorityQueue()
+    let queue = PriorityQueue ()
 
     let addEdgeToQueue (elements : Points) =
         for p in elements do
             for i, j in se do
                 let ni = i + p.Y
                 let nj = j + p.X
-                let p' = Point(nj, ni)
-                if ni >= 0 && ni < h && nj >= 0 && nj < w && not (elements.Contains(p')) then
+                let p' = Point (nj, ni)
+                if ni >= 0 && ni < h && nj >= 0 && nj < w && not (elements.Contains p') then
                     queue.Add (imgData.[ni, nj, 0]) p'
 
     // Reverse order is quicker.
     for i = areas.Count - 1 downto 0 do
         let m = areas.[i]
         if m.Elements.Count <= area && m.State <> AreaState.Removed then
-            queue.Clear()
+            queue.Clear ()
             addEdgeToQueue m.Elements
 
             let mutable intensity = if op = AreaOperation.Opening then queue.Max else queue.Min
-            let nextElements = Points()
+            let nextElements = Points ()
 
             let mutable stop = false
             while not stop do
@@ -238,10 +238,10 @@ let private areaOperation (img : Image<Gray, byte>) (area : int) (op : AreaOpera
                         m.Intensity <- Some intensity
                         stop <- true
                     else
-                        nextElements.Add(p) |> ignore
+                        nextElements.Add p |> ignore
 
                 elif (if op = AreaOperation.Opening then intensity' < intensity else intensity' > intensity) then
-                    m.Elements.UnionWith(nextElements)
+                    m.Elements.UnionWith nextElements
                     for e in nextElements do
                         pixels.[e.Y, e.X] <- m
 
@@ -251,8 +251,8 @@ let private areaOperation (img : Image<Gray, byte>) (area : int) (op : AreaOpera
                         stop <- true
                     else
                         intensity <- intensity'
-                        nextElements.Clear()
-                        nextElements.Add(p) |> ignore
+                        nextElements.Clear ()
+                        nextElements.Add p |> ignore
 
                 else
                     match pixels.[p.Y, p.X] with
@@ -264,11 +264,11 @@ let private areaOperation (img : Image<Gray, byte>) (area : int) (op : AreaOpera
                                 pixels.[e.Y, e.X] <- m
                                 queue.Remove imgData.[e.Y, e.X, 0] e
                             addEdgeToQueue m'.Elements
-                            m.Elements.UnionWith(m'.Elements)
+                            m.Elements.UnionWith m'.Elements
                             let intensityMax = if op = AreaOperation.Opening then queue.Max else queue.Min
                             if intensityMax <> intensity then
                                 intensity <- intensityMax
-                                nextElements.Clear()
+                                nextElements.Clear ()
                             merged <- true
 
                     if not merged then
@@ -280,19 +280,19 @@ let private areaOperation (img : Image<Gray, byte>) (area : int) (op : AreaOpera
                     for i, j in se do
                         let ni = i + p.Y
                         let nj = j + p.X
-                        let p' = Point(nj, ni)
+                        let p' = Point (nj, ni)
                         if ni < 0 || ni >= h || nj < 0 || nj >= w then
                             m.State <- AreaState.Validated
                             m.Intensity <- Some (intensity)
                             stop <- true
-                        elif not (m.Elements.Contains(p')) && not (nextElements.Contains(p')) then
+                        elif not (m.Elements.Contains p') && not (nextElements.Contains p') then
                             queue.Add (imgData.[ni, nj, 0]) p'
 
                 if queue.IsEmpty then
                     if m.Elements.Count + nextElements.Count <= area then
                         m.State <- AreaState.Validated
                         m.Intensity <- Some intensity'
-                        m.Elements.UnionWith(nextElements)
+                        m.Elements.UnionWith nextElements
                     stop <- true
 
     for m in areas do
@@ -331,8 +331,8 @@ let areaOpen2 (img : Image<Gray, byte>) (area : int) =
 
     let flooded : bool[,] = Array2D.zeroCreate h w
 
-    let pointsChecked = HashSet<Point>()
-    let pointsToCheck = Stack<Point>()
+    let pointsChecked = HashSet<Point> ()
+    let pointsToCheck = Stack<Point> ()
 
     for level = 255 downto 0 do
         let mutable n = histogram.[level]
@@ -341,22 +341,22 @@ let areaOpen2 (img : Image<Gray, byte>) (area : int) =
                 for j = 0 to w - 1 do
                     if not flooded.[i, j] && imgData.[i, j, 0] = byte level then
                         let mutable maxNeighborValue = 0uy
-                        pointsChecked.Clear()
-                        pointsToCheck.Clear()
-                        pointsToCheck.Push(Point(j, i))
+                        pointsChecked.Clear ()
+                        pointsToCheck.Clear ()
+                        pointsToCheck.Push (Point (j, i))
 
                         while pointsToCheck.Count > 0 do
-                            let next = pointsToCheck.Pop()
-                            pointsChecked.Add(next) |> ignore
+                            let next = pointsToCheck.Pop ()
+                            pointsChecked.Add next |> ignore
                             flooded.[next.Y, next.X] <- true
 
                             for nx, ny in se do
-                                let p = Point(next.X + nx, next.Y + ny)
+                                let p = Point (next.X + nx, next.Y + ny)
                                 if p.X >= 0 && p.X < w && p.Y >= 0 && p.Y < h then
                                     let v = imgData.[p.Y, p.X, 0]
                                     if v = byte level then
-                                        if not (pointsChecked.Contains(p)) then
-                                            pointsToCheck.Push(p)
+                                        if not (pointsChecked.Contains p) then
+                                            pointsToCheck.Push p
                                     elif v > maxNeighborValue then
                                         maxNeighborValue <- v
 
@@ -366,7 +366,7 @@ let areaOpen2 (img : Image<Gray, byte>) (area : int) =
 
 [<AllowNullLiteral>]
 type Island (cmp : IComparer<float32>) =
-    member val Shore = Heap.Heap<float32, Point>(cmp) with get
+    member val Shore = Heap.Heap<float32, Point> cmp with get
     member val Level = 0.f with get, set
     member val Surface = 0 with get, set
     member this.IsInfinite = this.Surface = Int32.MaxValue
@@ -379,29 +379,29 @@ let private areaOperationF (img : Image<Gray, float32>) (areas : (int * 'a) list
 
     let comparer =
         if op = AreaOperation.Opening then
-            { new IComparer<float32> with member this.Compare(v1, v2) = v1.CompareTo(v2) }
+            { new IComparer<float32> with member this.Compare (v1, v2) = v1.CompareTo v2 }
         else
-            { new IComparer<float32> with member this.Compare(v1, v2) = v2.CompareTo(v1) }
+            { new IComparer<float32> with member this.Compare (v1, v2) = v2.CompareTo v1 }
 
     let ownership : Island[,] = Array2D.create h w null
 
     // Initialize islands with their shore.
-    let islands = List<Island>()
+    let islands = List<Island> ()
     let extremum = img |> if op = AreaOperation.Opening then findMaxima else findMinima
     for e in extremum do
         let island =
-            let p = e.First()
-            Island(comparer, Level = earth.[p.Y, p.X, 0], Surface = e.Count)
-        islands.Add(island)
-        let shorePoints = Points()
+            let p = e.First ()
+            Island (comparer, Level = earth.[p.Y, p.X, 0], Surface = e.Count)
+        islands.Add island
+        let shorePoints = Points ()
         for p in e do
             ownership.[p.Y, p.X] <- island
             for i, j in se do
                 let ni = i + p.Y
                 let nj = j + p.X
-                let neighbor = Point(nj, ni)
-                if ni >= 0 && ni < h && nj >= 0 && nj < w && Object.ReferenceEquals(ownership.[ni, nj], null) && not (shorePoints.Contains(neighbor)) then
-                    shorePoints.Add(neighbor) |> ignore
+                let neighbor = Point (nj, ni)
+                if ni >= 0 && ni < h && nj >= 0 && nj < w && Object.ReferenceEquals (ownership.[ni, nj], null) && not (shorePoints.Contains neighbor) then
+                    shorePoints.Add neighbor |> ignore
                     island.Shore.Add earth.[ni, nj, 0] neighbor
 
     for area, obj in areas do
@@ -422,23 +422,22 @@ let private areaOperationF (img : Image<Gray, float32>) (areas : (int * 'a) list
                 if other = island then // During merging, some points on the shore may be owned by the island itself -> ignored.
                     island.Shore.RemoveNext ()
                 else
-                    if not <| Object.ReferenceEquals(other, null) then
+                    if not <| Object.ReferenceEquals (other, null) then
                         // We touching another island.
-                        if island.IsInfinite || other.IsInfinite || island.Surface + other.Surface >= area || comparer.Compare(island.Level, other.Level) < 0 then
+                        if island.IsInfinite || other.IsInfinite || island.Surface + other.Surface >= area || comparer.Compare (island.Level, other.Level) < 0 then
                             stop <- true
                         else // We can merge 'other' into 'surface'.
                             island.Surface <- island.Surface + other.Surface
                             island.Level <- other.Level
-                            // island.Level <- if comparer.Compare(island.Level, other.Level) > 0 then other.Level else island.Level
                             for l, p in other.Shore do
                                 let mutable currentY = p.Y + 1
                                 while currentY < h && ownership.[currentY, p.X] = other do
                                     ownership.[currentY, p.X] <- island
                                     currentY <- currentY + 1
                                 island.Shore.Add l p
-                            other.Shore.Clear()
+                            other.Shore.Clear ()
 
-                    elif comparer.Compare(level, island.Level) > 0 then
+                    elif comparer.Compare (level, island.Level) > 0 then
                         stop <- true
                     else
                         island.Shore.RemoveNext ()
@@ -449,7 +448,7 @@ let private areaOperationF (img : Image<Gray, float32>) (areas : (int * 'a) list
                                 island.Surface <- Int32.MaxValue
                                 stop <- true
                             else
-                                let neighbor = Point(nj, ni)
+                                let neighbor = Point (nj, ni)
                                 if not <| ownedOrAdjacent neighbor then
                                     island.Shore.Add earth.[ni, nj, 0] neighbor
                         if not stop then
@@ -566,10 +565,10 @@ let removeArea (mat : Matrix<byte>) (areaSize : int) =
         ( 0, -1) // p8
         (-1, -1) |] // p9
 
-    use mat' = new Matrix<byte>(mat.Size)
+    use mat' = new Matrix<byte> (mat.Size)
     let w = mat'.Width
     let h = mat'.Height
-    mat.CopyTo(mat')
+    mat.CopyTo mat'
 
     let data = mat.Data
     let data' = mat'.Data
@@ -577,19 +576,19 @@ let removeArea (mat : Matrix<byte>) (areaSize : int) =
     for i = 0 to h - 1 do
         for j = 0 to w - 1 do
             if data'.[i, j] = 1uy then
-                let neighborhood = List<Point>()
-                let neighborsToCheck = Stack<Point>()
-                neighborsToCheck.Push(Point(j, i))
+                let neighborhood = List<Point> ()
+                let neighborsToCheck = Stack<Point> ()
+                neighborsToCheck.Push (Point (j, i))
                 data'.[i, j] <- 0uy
 
                 while neighborsToCheck.Count > 0 do
-                    let n = neighborsToCheck.Pop()
-                    neighborhood.Add(n)
+                    let n = neighborsToCheck.Pop ()
+                    neighborhood.Add n
                     for (ni, nj) in neighbors do
                         let pi = n.Y + ni
                         let pj = n.X + nj
                         if pi >= 0 && pi < h && pj >= 0 && pj < w && data'.[pi, pj] = 1uy then
-                            neighborsToCheck.Push(Point(pj, pi))
+                            neighborsToCheck.Push (Point (pj, pi))
                             data'.[pi, pj] <- 0uy
                 if neighborhood.Count <= areaSize then
                     for n in neighborhood do
@@ -599,19 +598,19 @@ let connectedComponents (img : Image<Gray, byte>) (startPoints : List<Point>) :
     let w = img.Width
     let h = img.Height
 
-    let pointChecked = Points()
-    let pointToCheck = Stack<Point>(startPoints);
+    let pointChecked = Points ()
+    let pointToCheck = Stack<Point> startPoints;
 
     let data = img.Data
 
     while pointToCheck.Count > 0 do
-        let next = pointToCheck.Pop()
-        pointChecked.Add(next) |> ignore
+        let next = pointToCheck.Pop ()
+        pointChecked.Add next |> ignore
         for ny = -1 to 1 do
             for nx = -1 to 1 do
                 if ny <> 0 && nx <> 0 then
-                    let p = Point(next.X + nx, next.Y + ny)
+                    let p = Point (next.X + nx, next.Y + ny)
                     if p.X >= 0 && p.X < w && p.Y >= 0 && p.Y < h && data.[p.Y, p.X, 0] > 0uy && not (pointChecked.Contains p) then
-                        pointToCheck.Push(p)
+                        pointToCheck.Push p
 
     pointChecked
index dfd2593..c0276d9 100644 (file)
@@ -20,10 +20,10 @@ let kmeans (img : Image<Gray, float32>) : Result =
     let h = img.Height
 
     let min = ref [| 0.0 |]
-    let minLocation = ref <| [| Point() |]
+    let minLocation = ref <| [| Point () |]
     let max = ref [| 0.0 |]
-    let maxLocation = ref <| [| Point() |]
-    img.MinMax(min, max, minLocation, maxLocation)
+    let maxLocation = ref <| [| Point () |]
+    img.MinMax (min, max, minLocation, maxLocation)
 
     let minf = float32 (!min).[0]
     let maxf = float32 (!max).[0]
@@ -32,7 +32,7 @@ let kmeans (img : Image<Gray, float32>) : Result =
     let mutable mean_fg = minf + (maxf - minf) / 4.f
     use mutable d_bg : Image<Gray, float32> = null
     let mutable d_fg : Image<Gray, float32> = null
-    let fg = new Image<Gray, byte>(img.Size)
+    let fg = new Image<Gray, byte> (img.Size)
 
     let imgData = img.Data
     let fgData = fg.Data
@@ -41,14 +41,14 @@ let kmeans (img : Image<Gray, float32>) : Result =
         match d_bg with
         | null -> ()
         | _ ->
-            d_bg.Dispose()
-            d_fg.Dispose()
+            d_bg.Dispose ()
+            d_fg.Dispose ()
 
         // EmGu doesn't import the in-place version of 'AbsDiff' so we have to create two images for each iteration.
-        d_bg <- img.AbsDiff(Gray(float mean_bg))
-        d_fg <- img.AbsDiff(Gray(float mean_fg))
+        d_bg <- img.AbsDiff (Gray (float mean_bg))
+        d_fg <- img.AbsDiff (Gray (float mean_fg))
 
-        CvInvoke.Compare(d_fg, d_bg, fg, CvEnum.CmpType.LessThan)
+        CvInvoke.Compare (d_fg, d_bg, fg, CvEnum.CmpType.LessThan)
 
         let mutable bg_total = 0.f
         let mutable bg_nb = 0
index bae7a24..b2ac738 100644 (file)
@@ -20,35 +20,35 @@ let kmedians (img : Image<Gray, float32>) : Result =
     let h = img.Height
 
     let min = ref [| 0.0 |]
-    let minLocation = ref <| [| Point() |]
+    let minLocation = ref <| [| Point () |]
     let max = ref [| 0.0 |]
-    let maxLocation = ref <| [| Point() |]
-    img.MinMax(min, max, minLocation, maxLocation)
+    let maxLocation = ref <| [| Point () |]
+    img.MinMax (min, max, minLocation, maxLocation)
 
     let mutable median_bg = (!max).[0] - ((!max).[0] - (!min).[0]) / 4.0
     let mutable median_fg = (!min).[0] + ((!max).[0] - (!min).[0]) / 4.0
-    use mutable d_bg = new Image<Gray, float32>(img.Size)
-    let mutable d_fg = new Image<Gray, float32>(img.Size)
-    let mutable fg = new Image<Gray, byte>(img.Size)
+    use mutable d_bg = new Image<Gray, float32> (img.Size)
+    let mutable d_fg = new Image<Gray, float32> (img.Size)
+    let mutable fg = new Image<Gray, byte> (img.Size)
 
     for i = 1 to nbIteration do
-        d_bg <- img.AbsDiff(Gray(median_bg))
-        d_fg <- img.AbsDiff(Gray(median_fg))
+        d_bg <- img.AbsDiff (Gray median_bg)
+        d_fg <- img.AbsDiff (Gray median_fg)
 
-        CvInvoke.Compare(d_fg, d_bg, fg, CvEnum.CmpType.LessThan)
+        CvInvoke.Compare (d_fg, d_bg, fg, CvEnum.CmpType.LessThan)
 
-        let bg_values = List<float>()
-        let fg_values = List<float>()
+        let bg_values = List<float> ()
+        let fg_values = List<float> ()
 
         for i = 0 to h - 1 do
             for j = 0 to w - 1 do
                 if fg.Data.[i, j, 0] > 0uy then
-                    fg_values.Add(float img.Data.[i, j, 0])
+                    fg_values.Add (float img.Data.[i, j, 0])
                 else
-                    bg_values.Add(float img.Data.[i, j, 0])
+                    bg_values.Add (float img.Data.[i, j, 0])
 
-        median_bg <- MathNet.Numerics.Statistics.Statistics.Median(bg_values)
-        median_fg <- MathNet.Numerics.Statistics.Statistics.Median(fg_values)
+        median_bg <- MathNet.Numerics.Statistics.Statistics.Median bg_values
+        median_fg <- MathNet.Numerics.Statistics.Statistics.Median fg_values
 
     { fg = fg; median_bg = median_bg; median_fg = median_fg; d_fg = d_fg }
 
index f98cfa2..2525e27 100644 (file)
@@ -8,17 +8,17 @@ type I2DCoords =
 
 // Compare 'e1' and 'e2' by X.
 let cmpX (e1 : I2DCoords) (e2 : I2DCoords) : int =
-    match e1.X.CompareTo(e2.X) with
-    | 0 -> match e1.Y.CompareTo(e2.Y) with
-           | 0 -> e1.GetHashCode().CompareTo(e2.GetHashCode())
+    match e1.X.CompareTo e2.X with
+    | 0 -> match e1.Y.CompareTo e2.Y with
+           | 0 -> e1.GetHashCode().CompareTo (e2.GetHashCode ())
            | v -> v
     | v -> v
 
 // Compare 'e1' and 'e2' by Y.
 let cmpY (e1 : I2DCoords) (e2 : I2DCoords) : int =
-    match e1.Y.CompareTo(e2.Y) with
-    | 0 -> match e1.X.CompareTo(e2.X) with
-           | 0 -> e1.GetHashCode().CompareTo(e2.GetHashCode())
+    match e1.Y.CompareTo e2.Y with
+    | 0 -> match e1.X.CompareTo e2.X with
+           | 0 -> e1.GetHashCode().CompareTo (e2.GetHashCode ())
            | v -> v
     | v -> v
 
index 13fd556..03a3869 100644 (file)
@@ -34,10 +34,10 @@ type private EllipseScoreFlaggedKd (matchingScore : float32, e : Ellipse) =
         member this.Y = this.Ellipse.Cy
 
 type MatchingEllipses (radius : float32) =
-    let ellipses = List<EllipseScoreFlaggedKd>()
+    let ellipses = List<EllipseScoreFlaggedKd> ()
 
     member this.Add (e : Ellipse) =
-        ellipses.Add(EllipseScoreFlaggedKd(0.f, e))
+        ellipses.Add (EllipseScoreFlaggedKd (0.f, e))
 
     member this.Ellipses : Ellipse list =
         List.ofSeq ellipses |> List.map (fun e -> e.Ellipse)
@@ -69,8 +69,8 @@ type MatchingEllipses (radius : float32) =
                             // Because of approximation error, see https://github.com/chraibi/EEOver/issues/4
                             when overlapArea - areaE < 1.f && overlapArea - areaOther < 1.f ->
                                 let matchingScore = (2.f * overlapArea / (areaE + areaOther)) ** matchingScorePower
-                                other.AddMatchingScore(matchingScore)
-                                e.AddMatchingScore(matchingScore)
+                                other.AddMatchingScore matchingScore
+                                e.AddMatchingScore matchingScore
                         | _ -> ()
 
             // 3) Remove ellipses whose center is near the center of another ellipse with a better score.
@@ -89,7 +89,7 @@ type MatchingEllipses (radius : float32) =
                     for other in tree.Search window do
                         if not other.Removed && e.MatchingScore > other.MatchingScore then
                             // Case where ellipses are too close.
-                            if distanceTwoPoints (PointF(e.Ellipse.Cx, e.Ellipse.Cy)) (PointF(other.Ellipse.Cx, other.Ellipse.Cy)) < minimumDistanceFromCenterRadiusFactor * e.Ellipse.B then
+                            if distanceTwoPoints (PointF (e.Ellipse.Cx, e.Ellipse.Cy)) (PointF (other.Ellipse.Cx, other.Ellipse.Cy)) < minimumDistanceFromCenterRadiusFactor * e.Ellipse.B then
                                 other.Removed <- true
                             else
                                 // Case where ellipses are overlapped.
@@ -101,6 +101,6 @@ type MatchingEllipses (radius : float32) =
             ellipses
             |> List.ofSeq
             |> List.filter (fun e -> not e.Removed)
-            |> List.sortWith (fun e1 e2 -> e2.MatchingScore.CompareTo(e1.MatchingScore))
+            |> List.sortWith (fun e1 e2 -> e2.MatchingScore.CompareTo e1.MatchingScore)
             |> List.map (fun e -> e.Ellipse)
 
index 5a14573..c841f71 100644 (file)
@@ -91,7 +91,7 @@
       <Private>True</Private>
     </Reference>
     <Reference Include="FSharp.Core">
-      <HintPath>..\packages\FSharp.Core.4.1.17\lib\net45\FSharp.Core.dll</HintPath>
+      <HintPath>..\packages\FSharp.Core.4.2.1\lib\net45\FSharp.Core.dll</HintPath>
     </Reference>
     <Reference Include="MathNet.Numerics">
       <HintPath>..\packages\MathNet.Numerics.3.19.0\lib\net40\MathNet.Numerics.dll</HintPath>
index 263e35e..b89caa6 100644 (file)
@@ -21,7 +21,7 @@ type Result =
 
 let find (img : Image<Gray, float32>) (config : Config.Config) : Result * Image<Gray, float32> * Image<Gray, float32> =
 
-    let imgWithoutNucleus = img.Copy()
+    let imgWithoutNucleus = img.Copy ()
     areaCloseF imgWithoutNucleus (roundInt config.RBCRadius.NucleusArea)
 
     let darkStain =
@@ -29,30 +29,30 @@ let find (img : Image<Gray, float32>) (config : Config.Config) : Result * Image<
         let _, mean_fg, mean_bg =
             let hist = histogramImg imgWithoutNucleus 300
             otsu hist
-        imgWithoutNucleus.Cmp(float mean_fg - config.Parameters.darkStainLevel * float (mean_bg - mean_fg), CvEnum.CmpType.LessThan)
+        imgWithoutNucleus.Cmp (float mean_fg - config.Parameters.darkStainLevel * float (mean_bg - mean_fg), CvEnum.CmpType.LessThan)
 
     let marker (img : Image<Gray, float32>) (closed : Image<Gray, float32>) (level : float) : Image<Gray, byte> =
-        let diff = img.Copy()
-        diff._Mul(level)
-        CvInvoke.Subtract(closed, diff, diff)
-        diff._ThresholdBinary(Gray(0.0), Gray(255.))
-        diff.Convert<Gray, byte>()
+        let diff = img.Copy ()
+        diff._Mul level
+        CvInvoke.Subtract (closed, diff, diff)
+        diff._ThresholdBinary (Gray 0.0, Gray 255.)
+        diff.Convert<Gray, byte> ()
 
     // Nucleus.
     let nucleusMarker = marker img imgWithoutNucleus (1. / config.Parameters.infectionSensitivity)
 
     // Cytoplasm.
-    let imgWithoutParasite = img.CopyBlank()
+    let imgWithoutParasite = img.CopyBlank ()
     let kernelSize =
         let size = roundInt config.RBCRadius.CytoplasmSize
         if size % 2 = 0 then size + 1 else size
     use kernel =
         if kernelSize <= 3 then
-            CvInvoke.GetStructuringElement(CvEnum.ElementShape.Rectangle, Size(3, 3), Point(-1, -1))
+            CvInvoke.GetStructuringElement (CvEnum.ElementShape.Rectangle, Size (3, 3), Point (-1, -1))
         else
-            CvInvoke.GetStructuringElement(CvEnum.ElementShape.Ellipse, Size(kernelSize, kernelSize), Point(-1, -1))
+            CvInvoke.GetStructuringElement (CvEnum.ElementShape.Ellipse, Size (kernelSize, kernelSize), Point (-1, -1))
 
-    CvInvoke.MorphologyEx(img, imgWithoutParasite, CvEnum.MorphOp.Close, kernel, Point(-1, -1), 1, CvEnum.BorderType.Replicate, MCvScalar())
+    CvInvoke.MorphologyEx (img, imgWithoutParasite, CvEnum.MorphOp.Close, kernel, Point(-1, -1), 1, CvEnum.BorderType.Replicate, MCvScalar())
     let parasiteMarker = marker img imgWithoutParasite (1. / config.Parameters.cytoplasmSensitivity)
 
     {
index c1a635d..8f526f9 100644 (file)
@@ -36,14 +36,14 @@ type Ellipse (cx : float32, cy : float32, a : float32, b : float32, alpha : floa
         this.CutAnHorizontalLine 0.f || this.CutAnHorizontalLine height
 
     member this.Scale (factor : float32) : Ellipse =
-        Ellipse(this.Cx, this.Cy, this.A * factor, this.B * factor, alpha)
+        Ellipse (this.Cx, this.Cy, this.A * factor, this.B * factor, alpha)
 
     // Approximation of Ramanujan.
     member this.Perimeter =
         PI * (3.f * (this.A + this.B) - sqrt ((3.f * this.A + this.B) * (this.A + 3.f * this.B)))
 
     override this.ToString () =
-        sprintf "(cx: %f, cy: %f, a: %f, b: %f, alpha: %f)" this.Cx this.Cy this.A this.B this.Alpha
+        sprintf "{Ellipse: cx = %f, cy = %f, a = %f, b = %f, alpha = %f}" this.Cx this.Cy this.A this.B this.Alpha
 
 type CellClass = HealthyRBC | InfectedRBC | Peculiar
 
@@ -71,16 +71,16 @@ type MaybeBuilder () =
 
     member this.TryFinally (body, compensation) =
         try
-            this.ReturnFrom(body())
+            this.ReturnFrom (body ())
         finally
-            compensation()
+            compensation ()
 
     member this.Using (disposable : 'a when 'a :> IDisposable, body) =
         let body' = fun () -> body disposable
-        this.TryFinally(body', fun () ->
+        this.TryFinally (body', fun () ->
             match disposable with
             | null -> ()
-            | disp -> disp.Dispose())
+            | disp -> disp.Dispose ())
 
     member this.Zero () =
         None
@@ -88,7 +88,7 @@ type MaybeBuilder () =
     member this.Return x =
         Some x
 
-let maybe = MaybeBuilder()
+let maybe = MaybeBuilder ()
 
 type Result<'a> =
     | Success of 'a
@@ -102,4 +102,4 @@ type ResultBuilder () =
 
     member this.ReturnFrom (x) = x
 
-let result = ResultBuilder()
\ No newline at end of file
+let result = ResultBuilder ()
\ No newline at end of file
index 8202b8e..4af1e55 100644 (file)
@@ -9,9 +9,9 @@
 let μmPerInch = 25.4e3<μm/inch>
 let mmPerInch = 25.4<mm/inch>
 
-let μmToInch(x : float<μm>) : float<inch> = x / μmPerInch
-let inchToμm(x : float<inch>) : float<μm> = x * μmPerInch
+let μmToInch (x : float<μm>) : float<inch> = x / μmPerInch
+let inchToμm (x : float<inch>) : float<μm> = x * μmPerInch
 
-let mmToInch(x : float<mm>) : float<inch> = x / mmPerInch
-let inchTomm(x : float<inch>) : float<mm> = x * mmPerInch
+let mmToInch (x : float<mm>) : float<inch> = x / mmPerInch
+let inchTomm (x : float<inch>) : float<mm> = x * mmPerInch
 
index 77e5e6f..6a13337 100644 (file)
@@ -13,12 +13,12 @@ let inline dprintfn fmt =
 let inline lineFromTwoPoints (p1 : PointF) (p2 : PointF) : Line =
     let a = (p1.Y - p2.Y) / (p1.X - p2.X)
     let b = -(p2.X * p1.Y - p1.X * p2.Y) / (p1.X - p2.X)
-    Line(a, b)
+    Line (a, b)
 
 let inline pointFromTwoLines (l1 : Line) (l2 : Line) : PointF =
     let x = -(l1.B - l2.B) / (l1.A - l2.A)
     let y = -(l2.A * l1.B - l1.A * l2.B) / (l1.A - l2.A)
-    PointF(x, y)
+    PointF (x, y)
 
 let inline linePassThroughSegment (l : Line) (p1 : PointF) (p2 : PointF) : bool =
     let p = pointFromTwoLines l (lineFromTwoPoints p1 p2)
index 91a2fc7..d0073d5 100644 (file)
@@ -2,7 +2,7 @@
 <packages>
   <package id="EmguCV" version="3.1.0.1" targetFramework="net452" />
   <package id="FSharp.Collections.ParallelSeq" version="1.0.2" targetFramework="net452" />
-  <package id="FSharp.Core" version="4.1.17" targetFramework="net452" />
+  <package id="FSharp.Core" version="4.2.1" targetFramework="net452" />
   <package id="MathNet.Numerics" version="3.19.0" targetFramework="net452" />
   <package id="MathNet.Numerics.FSharp" version="3.19.0" targetFramework="net452" />
   <package id="OpenTK" version="2.0.0" targetFramework="net452" />
index 452573a..8c643b7 100644 (file)
@@ -2,14 +2,11 @@
 
 open System
 open System.Windows
-open System.Windows.Media
-open System.Windows.Markup
-open System.Windows.Shapes
 open System.Windows.Controls
 open System.Diagnostics
 
 let showWindow (parent : Window) =
-    let win = Views.AboutWindow()
+    let win = Views.AboutWindow ()
     win.Owner <- parent
 
     win.Left <- (if parent.WindowState = WindowState.Maximized then 0. else parent.Left) + parent.ActualWidth / 2. - win.Width / 2.
@@ -17,21 +14,24 @@ let showWindow (parent : Window) =
 
     let version = System.Reflection.Assembly.GetEntryAssembly().GetName().Version
     let txtVersion = sprintf " %d.%d.%d" version.Major version.Minor version.Revision
-    win.txtAbout.Inlines.FirstInline.ElementEnd.InsertTextInRun(txtVersion)
+    win.txtAbout.Inlines.FirstInline.ElementEnd.InsertTextInRun txtVersion
 
-    let navigateTo = Navigation.RequestNavigateEventHandler(fun obj args ->
-        Process.Start(ProcessStartInfo(args.Uri.AbsoluteUri)) |> ignore
-        args.Handled <- true)
+    let navigateTo =
+        Navigation.RequestNavigateEventHandler (
+            fun obj args ->
+                Process.Start (ProcessStartInfo args.Uri.AbsoluteUri) |> ignore
+                args.Handled <- true
+        )
 
-    win.linkHESSO.RequestNavigate.AddHandler(navigateTo);
-    win.linkCHUV.RequestNavigate.AddHandler(navigateTo);
-    win.linkGBurri.RequestNavigate.AddHandler(navigateTo);
+    win.linkHESSO.RequestNavigate.AddHandler navigateTo;
+    win.linkCHUV.RequestNavigate.AddHandler navigateTo;
+    win.linkGBurri.RequestNavigate.AddHandler navigateTo;
 
 #if DEBUG
-    win.txtAbout.Inlines.FirstInline.ElementEnd.InsertTextInRun(" - DEBUG")
+    win.txtAbout.Inlines.FirstInline.ElementEnd.InsertTextInRun " - DEBUG"
 #endif
 
-    win.butClose.Click.AddHandler(fun obj args -> win.Close())
+    win.butClose.Click.AddHandler (fun obj args -> win.Close ())
 
-    win.ShowDialog() |> ignore
+    win.ShowDialog () |> ignore
 
index e276be6..4a75a91 100644 (file)
@@ -19,7 +19,7 @@ open ParasitemiaCore.Config
 open Types
 
 let showWindow (parent : Window) (state : State.State) : bool =
-    let win = Views.AnalysisWindow()
+    let win = Views.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.
@@ -28,62 +28,69 @@ let showWindow (parent : Window) (state : State.State) : bool =
         {
             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 = Views.ImageSourceSelection (Tag = srcImg, Margin = Thickness 3.)
             imageSourceSelection.Tag <- srcImg
 
-            imageSourceSelection.txtImageNumber.Text <- srcImg.num.ToString()
+            imageSourceSelection.txtImageNumber.Text <- string srcImg.num
             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.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).
@@ -98,71 +105,73 @@ let showWindow (parent : Window) (state : State.State) : bool =
                         | Some resolution ->
                             yield 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
+                            MessageBox.Show (sprintf "No resolution defined for the image number %d" srcImg.num, "No resolution defined", MessageBoxButton.OK, MessageBoxImage.Information) |> ignore
                             yield 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
+                                yield string srcImg.num, 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.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 () ->
index 3814371..d0754f8 100644 (file)
@@ -7,22 +7,22 @@ open System.Runtime.InteropServices
 // General Information about an assembly is controlled through the following
 // set of attributes. Change these attribute values to modify the information
 // associated with an assembly.
-[<assembly: AssemblyTitle("ParasitemiaUI")>]
-[<assembly: AssemblyDescription("")>]
-[<assembly: AssemblyConfiguration("")>]
-[<assembly: AssemblyCompany("HES-SO / CHUV / Grégory Burri")>]
-[<assembly: AssemblyProduct("ParasitemiaUI")>]
-[<assembly: AssemblyCopyright("Copyright © 2015-2016")>]
-[<assembly: AssemblyTrademark("")>]
-[<assembly: AssemblyCulture("")>]
+[<assembly: AssemblyTitle "ParasitemiaUI">]
+[<assembly: AssemblyDescription "">]
+[<assembly: AssemblyConfiguration "">]
+[<assembly: AssemblyCompany "HES-SO / CHUV / Grégory Burri">]
+[<assembly: AssemblyProduct "ParasitemiaUI">]
+[<assembly: AssemblyCopyright "Copyright © 2015-2016">]
+[<assembly: AssemblyTrademark "">]
+[<assembly: AssemblyCulture "">]
 
 // Setting ComVisible to false makes the types in this assembly not visible
 // to COM components.  If you need to access a type in this assembly from
 // COM, set the ComVisible attribute to true on that type.
-[<assembly: ComVisible(false)>]
+[<assembly: ComVisible false>]
 
 // The following GUID is for the ID of the typelib if this project is exposed to COM
-[<assembly: Guid("70838e65-f211-44fc-b28f-0ed1ca6e850f")>]
+[<assembly: Guid "70838e65-f211-44fc-b28f-0ed1ca6e850f">]
 
 // Version information for an assembly consists of the following four values:
 //
@@ -33,9 +33,9 @@ open System.Runtime.InteropServices
 //
 // You can specify all the values or you can default the Build and Revision Numbers
 // by using the '*' as shown below:
-// [<assembly: AssemblyVersion("1.0.*")>]
-[<assembly: AssemblyVersion("1.0.0.10")>]
-[<assembly: AssemblyFileVersion("1.0.0.10")>]
+// [<assembly: AssemblyVersion "1.0.*">]
+[<assembly: AssemblyVersion "1.0.0.10">]
+[<assembly: AssemblyFileVersion "1.0.0.10">]
 
 do
     ()
\ No newline at end of file
index c8d25c8..2cdc184 100644 (file)
@@ -14,13 +14,13 @@ open ParasitemiaCore.UnitsOfMeasure
 open Types
 
 let showWindow (parent : Window) : int option =
-    let win = Views.PPICalculatorWindow()
+    let win = Views.PPICalculatorWindow ()
     win.Owner <- parent
     win.Left <- parent.Left + parent.ActualWidth / 2. - win.Width / 2.
     win.Top <- parent.Top + parent.ActualHeight / 2. - win.Height / 2.
 
     for size in Utils.sensorSizes do
-        win.cmbSensorSize.Items.Add(size) |> ignore
+        win.cmbSensorSize.Items.Add (size) |> ignore
     win.cmbSensorSize.SelectedIndex <- 0
 
     let resolution (w_p : float<px>) (w_mm : float<mm>) (zoom : float) : float<ppi> =
@@ -30,7 +30,7 @@ let showWindow (parent : Window) : int option =
         let { w = w; h = h } = win.cmbSensorSize.SelectedValue :?> SensorSize
         let ratio = h / w
 
-        let parseDouble txt errorMess = match Double.TryParse(txt) with true, value -> Success value | _ -> Fail errorMess
+        let parseDouble txt errorMess = match Double.TryParse (txt) with true, value -> Success value | _ -> Fail errorMess
 
         match
             (result {
@@ -39,17 +39,17 @@ let showWindow (parent : Window) : int option =
                 let wPixel = 1.<px> * sqrt (sensorResolution * 1e6 / ratio)
                 return! Success (float <| resolution wPixel w zoom)
             }) with
-        | Success res -> win.txtImageResolution.Text <- (int (res / 1000.) * 1000).ToString()
+        | Success res -> win.txtImageResolution.Text <- int (res / 1000.) * 1000 |> string
         | Fail mess -> win.txtImageResolution.Text <- mess
 
-    win.butCancel.Click.AddHandler(fun obj args -> win.DialogResult <- Nullable<bool>(false); win.Close())
-    win.butOK.Click.AddHandler(fun obj args -> win.DialogResult <- Nullable<bool>(true); win.Close())
+    win.butCancel.Click.AddHandler (fun obj args -> win.DialogResult <- Nullable<bool> (false); win.Close ())
+    win.butOK.Click.AddHandler (fun obj args -> win.DialogResult <- Nullable<bool> (true); win.Close ())
 
-    win.cmbSensorSize.SelectionChanged.AddHandler(fun obj arg -> updateCurrentResolution ())
-    win.txtSensorResolution.TextChanged.AddHandler(fun obj arg -> updateCurrentResolution ())
-    win.txtZoom.TextChanged.AddHandler(fun obj arg -> updateCurrentResolution ())
+    win.cmbSensorSize.SelectionChanged.AddHandler (fun obj arg -> updateCurrentResolution ())
+    win.txtSensorResolution.TextChanged.AddHandler (fun obj arg -> updateCurrentResolution ())
+    win.txtZoom.TextChanged.AddHandler (fun obj arg -> updateCurrentResolution ())
 
-    let result = win.ShowDialog()
+    let result = win.ShowDialog ()
     if result.HasValue && result.Value then
         match Int32.TryParse win.txtImageResolution.Text with
         | true, res -> Some res
index 29fc0a5..52638d3 100644 (file)
@@ -7,7 +7,7 @@ open State
 
 /// <exception cref="System.IOException">If the results cannot be exported</exception>
 let exportResults (state : State) (filePath : string) =
-    use writer = new StreamWriter(new FileStream(filePath, FileMode.Create, FileAccess.Write))
+    use writer = new StreamWriter (new FileStream (filePath, FileMode.Create, FileAccess.Write))
     fprintfn writer "File: %s" state.FilePath
     fprintfn writer "Export date: %O" DateTime.Now
 
index 35bc2ad..46171a7 100644 (file)
@@ -20,10 +20,10 @@ open ParasitemiaCore.Utils
 open Types
 
 let run (defaultConfig : Config) (fileToOpen : string option) =
-    let app = new Application()
-    let win = Views.MainWindow()
+    let app = new Application ()
+    let win = Views.MainWindow ()
 
-    let state = State.State(defaultConfig)
+    let state = State.State defaultConfig
     let mutable currentScale = 1.
     let mutable displayHealthy = false
     let warningBelowNumberOfRBC = 1000
@@ -40,9 +40,12 @@ let run (defaultConfig : Config) (fileToOpen : string option) =
         let y = rbc.center.Y - rbcHeight / 2. |> roundInt
         let w = roundInt rbcWidth
         let h = roundInt rbcHeight
-        img.GetSubRect(System.Drawing.Rectangle(System.Drawing.Point((if x < 0 then 0 else x), (if y < 0 then 0 else y)),
-                                                System.Drawing.Size((if x + w >= img.Width then img.Width - x else w),
-                                                                    (if y + h >= img.Height then img.Height - y else h))))
+        img.GetSubRect (
+            System.Drawing.Rectangle (
+                System.Drawing.Point ((if x < 0 then 0 else x), (if y < 0 then 0 else y)),
+                System.Drawing.Size ((if x + w >= img.Width then img.Width - x else w), (if y + h >= img.Height then img.Height - y else h))
+            )
+        )
 
     let setRBCFrameStyle (srcImg : SourceImage) (rbc : RBC) (frame : Views.RBCFrame) =
         frame.Opacity <- if displayHealthy || rbc.setManually || rbc.infected then 1. else 0.
@@ -58,19 +61,19 @@ let run (defaultConfig : Config) (fileToOpen : string option) =
         frame.Tag <- rbc
         setRBCFrameStyle srcImg rbc frame
         frame.border.StrokeThickness <- 1.
-        frame.txtRBCNumber.Text <- rbc.num.ToString()
+        frame.txtRBCNumber.Text <- string rbc.num
         frame
 
     let updateDocumentStatus () =
         win.txtDocumentStatus.Text <- if state.FilePath = "" then "<New document>" else state.FilePath
 
-    let statusMessageTimer = Threading.DispatcherTimer()
-    statusMessageTimer.Tick.AddHandler(fun obj args -> statusMessageTimer.Stop(); win.txtMessageStatus.Text <- "")
-    statusMessageTimer.Interval <- TimeSpan(0, 0, 2)
+    let statusMessageTimer = Threading.DispatcherTimer ()
+    statusMessageTimer.Tick.AddHandler (fun obj args -> statusMessageTimer.Stop (); win.txtMessageStatus.Text <- "")
+    statusMessageTimer.Interval <- TimeSpan (0, 0, 2)
     let displayStatusMessage (message : string) =
         win.txtMessageStatus.Text <- message
-        statusMessageTimer.Stop()
-        statusMessageTimer.Start()
+        statusMessageTimer.Stop ()
+        statusMessageTimer.Start ()
 
     let highlightRBCFrame (frame : Views.RBCFrame) (highlight : bool) =
         let rbc = frame.Tag :?> RBC
@@ -82,51 +85,51 @@ let run (defaultConfig : Config) (fileToOpen : string option) =
             if not rbc.infected && not rbc.setManually && not displayHealthy then frame.Opacity <- 0.
 
     let zoomToRBC (rbc : RBC) =
-        win.scrollViewCurrentImage.ScrollToHorizontalOffset(rbc.center.X * currentScale - win.scrollViewCurrentImage.ViewportWidth / 2. + win.borderCurrentImage.BorderThickness.Left)
-        win.scrollViewCurrentImage.ScrollToVerticalOffset(rbc.center.Y * currentScale - win.scrollViewCurrentImage.ViewportHeight / 2. + win.borderCurrentImage.BorderThickness.Top)
+        win.scrollViewCurrentImage.ScrollToHorizontalOffset (rbc.center.X * currentScale - win.scrollViewCurrentImage.ViewportWidth / 2. + win.borderCurrentImage.BorderThickness.Left)
+        win.scrollViewCurrentImage.ScrollToVerticalOffset (rbc.center.Y * currentScale - win.scrollViewCurrentImage.ViewportHeight / 2. + win.borderCurrentImage.BorderThickness.Top)
 
 
     let txtImageName_TextChanged =
-        TextChangedEventHandler(fun obj args -> state.CurrentImage |> Option.iter(fun srcImg -> state.SetName srcImg win.txtImageName.Text))
+        TextChangedEventHandler (fun obj args -> state.CurrentImage |> Option.iter (fun srcImg -> state.SetName srcImg win.txtImageName.Text))
 
     let updateCurrentImageInformation () =
-        win.txtImageName.TextChanged.RemoveHandler(txtImageName_TextChanged)
-        win.txtImageInformation1.Inlines.Clear()
-        win.txtImageInformation2.Inlines.Clear()
+        win.txtImageName.TextChanged.RemoveHandler (txtImageName_TextChanged)
+        win.txtImageInformation1.Inlines.Clear ()
+        win.txtImageInformation2.Inlines.Clear ()
         win.txtImageName.Text <- ""
 
         match state.CurrentImage with
         | Some srcImg ->
             win.gridImageInformation.Visibility <- Visibility.Visible
             win.txtImageName.Text <- srcImg.name
-            win.txtImageName.TextChanged.AddHandler(txtImageName_TextChanged)
+            win.txtImageName.TextChanged.AddHandler txtImageName_TextChanged
 
             // The left part.
             let parasitemiaStr = Utils.percentText (state.ImageParasitemia srcImg)
-            win.txtImageInformation1.Inlines.Add(Documents.Run("Parasitemia: ", FontWeight = FontWeights.Bold))
-            win.txtImageInformation1.Inlines.Add(parasitemiaStr)
-            win.txtImageInformation1.Inlines.Add(Documents.LineBreak())
+            win.txtImageInformation1.Inlines.Add (Documents.Run ("Parasitemia: ", FontWeight = FontWeights.Bold))
+            win.txtImageInformation1.Inlines.Add parasitemiaStr
+            win.txtImageInformation1.Inlines.Add (Documents.LineBreak ())
 
-            win.txtImageInformation1.Inlines.Add(Documents.Run("Last analysis: ", FontWeight = FontWeights.Bold))
-            win.txtImageInformation1.Inlines.Add(Documents.Run(if srcImg.dateLastAnalysis.Ticks = 0L then "<Never>" else srcImg.dateLastAnalysis.ToLocalTime().ToString()))
+            win.txtImageInformation1.Inlines.Add (Documents.Run ("Last analysis: ", FontWeight = FontWeights.Bold))
+            win.txtImageInformation1.Inlines.Add (Documents.Run (if srcImg.dateLastAnalysis.Ticks = 0L then "<Never>" else string (srcImg.dateLastAnalysis.ToLocalTime())))
 
             // The right part part.
-            win.txtImageInformation2.Inlines.Add(Documents.Run("Added infected erythrocyte: ", FontWeight = FontWeights.Bold))
-            win.txtImageInformation2.Inlines.Add(Documents.Run((state.ImageNbManuallyChangedRBCStr srcImg true) + " " + (state.ImageManuallyChangedRBCStr srcImg true)))
-            win.txtImageInformation2.Inlines.Add(Documents.LineBreak())
-            win.txtImageInformation2.Inlines.Add(Documents.Run("Removed infected erythrocyte: ", FontWeight = FontWeights.Bold))
-            win.txtImageInformation2.Inlines.Add(Documents.Run((state.ImageNbManuallyChangedRBCStr srcImg false) + " " + (state.ImageManuallyChangedRBCStr srcImg false)))
+            win.txtImageInformation2.Inlines.Add (Documents.Run ("Added infected erythrocyte: ", FontWeight = FontWeights.Bold))
+            win.txtImageInformation2.Inlines.Add (Documents.Run ((state.ImageNbManuallyChangedRBCStr srcImg true) + " " + (state.ImageManuallyChangedRBCStr srcImg true)))
+            win.txtImageInformation2.Inlines.Add (Documents.LineBreak ())
+            win.txtImageInformation2.Inlines.Add (Documents.Run ("Removed infected erythrocyte: ", FontWeight = FontWeights.Bold))
+            win.txtImageInformation2.Inlines.Add (Documents.Run ((state.ImageNbManuallyChangedRBCStr srcImg false) + " " + (state.ImageManuallyChangedRBCStr srcImg false)))
 
         | _ ->
             win.gridImageInformation.Visibility <- Visibility.Hidden
 
     let updateGlobalParasitemia () =
-        win.txtGlobalParasitemia.Inlines.Clear()
+        win.txtGlobalParasitemia.Inlines.Clear ()
         let total, infected = state.GlobalParasitemia
-        win.txtGlobalParasitemia.Inlines.Add(Documents.Run(Utils.percentText (total, infected), FontWeight = FontWeights.Bold))
+        win.txtGlobalParasitemia.Inlines.Add (Documents.Run (Utils.percentText (total, infected), FontWeight = FontWeights.Bold))
         if total > 0 && total < warningBelowNumberOfRBC then
-            win.txtGlobalParasitemia.Inlines.Add(
-                Documents.Run(
+            win.txtGlobalParasitemia.Inlines.Add (
+                Documents.Run (
                     sprintf " Warning: the number of erythrocytes should be above %d" warningBelowNumberOfRBC,
                     FontWeight = FontWeights.Bold,
                     Foreground = Brushes.Red
@@ -150,7 +153,7 @@ let run (defaultConfig : Config) (fileToOpen : string option) =
                 let marginBottom = previewHeight * (canvasHeight - (win.scrollViewCurrentImage.VerticalOffset - win.borderCurrentImage.BorderThickness.Bottom) - win.scrollViewCurrentImage.ViewportHeight) / canvasHeight - 2.
 
                 preview.viewport.Margin <-
-                    Thickness(
+                    Thickness (
                         marginLeft,
                         marginTop,
                         marginRight,
@@ -173,11 +176,11 @@ let run (defaultConfig : Config) (fileToOpen : string option) =
         updateGlobalParasitemia ()
 
     and RBCFrame (srcImg : SourceImage) (rbc : RBC) : Views.RBCFrame =
-        let frame = RBCFrameFromExisting srcImg rbc (Views.RBCFrame())
-        frame.SetValue(Panel.ZIndexProperty, Int32.MaxValue - rbc.num) // To be sure the
-        frame.menuRBCSetAsHealthy.Click.AddHandler(fun obj args -> setAsInfected srcImg (frame.Tag :?> RBC) false)
-        frame.menuRBCSetAsInfected.Click.AddHandler(fun obj args -> setAsInfected srcImg (frame.Tag :?> RBC) true)
-        frame.ContextMenuOpening.AddHandler(
+        let frame = RBCFrameFromExisting srcImg rbc (Views.RBCFrame ())
+        frame.SetValue (Panel.ZIndexProperty, Int32.MaxValue - rbc.num) // To be sure the
+        frame.menuRBCSetAsHealthy.Click.AddHandler (fun obj args -> setAsInfected srcImg (frame.Tag :?> RBC) false)
+        frame.menuRBCSetAsInfected.Click.AddHandler (fun obj args -> setAsInfected srcImg (frame.Tag :?> RBC) true)
+        frame.ContextMenuOpening.AddHandler (
             fun obj args ->
                 if (frame.Tag :?> RBC).infected then
                     frame.menuRBCSetAsHealthy.Visibility <- Visibility.Visible
@@ -186,9 +189,9 @@ let run (defaultConfig : Config) (fileToOpen : string option) =
                     frame.menuRBCSetAsHealthy.Visibility <- Visibility.Collapsed
                     frame.menuRBCSetAsInfected.Visibility <- Visibility.Visible
         )
-        frame.ContextMenuClosing.AddHandler(fun obj args -> if not frame.IsMouseOver then highlightRBCFrame frame false )
-        frame.MouseEnter.AddHandler(fun obj args -> highlightRBCFrame frame true)
-        frame.MouseLeave.AddHandler(fun obj args -> if not frame.grid.ContextMenu.IsOpen then highlightRBCFrame frame false)
+        frame.ContextMenuClosing.AddHandler (fun obj args -> if not frame.IsMouseOver then highlightRBCFrame frame false )
+        frame.MouseEnter.AddHandler (fun obj args -> highlightRBCFrame frame true)
+        frame.MouseLeave.AddHandler (fun obj args -> if not frame.grid.ContextMenu.IsOpen then highlightRBCFrame frame false)
         frame
 
     and updateRBCFramesPreview () =
@@ -201,17 +204,17 @@ let run (defaultConfig : Config) (fileToOpen : string option) =
                         RBCFrameFromExisting srcImg rbc (win.stackRBC.Children.[currentPreview] :?> Views.RBCFrame)
                     else
                         let f = RBCFrame srcImg rbc
-                        f.MouseLeftButtonUp.AddHandler(fun obj args -> zoomToRBC (f.Tag :?> RBC))
-                        win.stackRBC.Children.Add(f) |> ignore
+                        f.MouseLeftButtonUp.AddHandler (fun obj args -> zoomToRBC (f.Tag :?> RBC))
+                        win.stackRBC.Children.Add f |> ignore
                         f
 
                 currentPreview <- currentPreview + 1
 
                 previewInfected.Height <- win.stackRBC.ActualHeight
                 previewInfected.Width <- win.stackRBC.ActualHeight * rbc.size.Width / rbc.size.Height
-                previewInfected.border.Fill <- ImageBrush(BitmapSourceConvert.ToBitmapSource(extractRBCPreview srcImg.img rbc))
+                previewInfected.border.Fill <- ImageBrush (BitmapSourceConvert.ToBitmapSource (extractRBCPreview srcImg.img rbc))
 
-            win.stackRBC.Children.RemoveRange(currentPreview, win.stackRBC.Children.Count - currentPreview)
+            win.stackRBC.Children.RemoveRange (currentPreview, win.stackRBC.Children.Count - currentPreview)
         | _ -> ()
 
         updateViewportPreview ()
@@ -226,27 +229,27 @@ let run (defaultConfig : Config) (fileToOpen : string option) =
                         RBCFrameFromExisting srcImg rbc (win.canvasCurrentImage.Children.[currentCanvas] :?> Views.RBCFrame)
                     else
                         let f = RBCFrame srcImg rbc
-                        win.canvasCurrentImage.Children.Add(f) |> ignore
+                        win.canvasCurrentImage.Children.Add f |> ignore
                         f
 
                 currentCanvas <- currentCanvas + 1
 
-                Canvas.SetLeft(frame, rbc.center.X - rbc.size.Width / 2.)
-                Canvas.SetTop(frame, rbc.center.Y - rbc.size.Height / 2.)
+                Canvas.SetLeft (frame, rbc.center.X - rbc.size.Width / 2.)
+                Canvas.SetTop (frame, rbc.center.Y - rbc.size.Height / 2.)
 
             for i in currentCanvas .. win.canvasCurrentImage.Children.Count - 1 do
                 win.canvasCurrentImage.Children.[i].Visibility <- Visibility.Hidden
         | _ -> ()
 
     let askDocumentPathToSave () : string option =
-        let dialog = SaveFileDialog(AddExtension = true, DefaultExt = PiaZ.extension, Filter = PiaZ.filter)
+        let dialog = SaveFileDialog (AddExtension = true, DefaultExt = PiaZ.extension, Filter = PiaZ.filter)
 
         if state.FilePath <> "" then
             dialog.FileName <- FileInfo(state.FilePath).Name
         elif state.PatientID <> "" then
             dialog.FileName <- state.PatientID + PiaZ.extension
 
-        let res = dialog.ShowDialog()
+        let res = dialog.ShowDialog ()
         if res.HasValue && res.Value then
             Some dialog.FileName
         else
@@ -258,16 +261,16 @@ let run (defaultConfig : Config) (fileToOpen : string option) =
                 match askDocumentPathToSave () with
                 | Some filepath ->
                     state.FilePath <- filepath
-                    state.Save()
+                    state.Save ()
                 | _ -> ()
             else
-                state.Save()
+                state.Save ()
             updateDocumentStatus ()
             displayStatusMessage "Document saved"
         with
         | :? IOException as ex ->
             Log.Error "%O" ex
-            MessageBox.Show(sprintf "The document cannot be save in \"%s\"" state.FilePath, "Error saving the document", MessageBoxButton.OK, MessageBoxImage.Error) |> ignore
+            MessageBox.Show (sprintf "The document cannot be save in \"%s\"" state.FilePath, "Error saving the document", MessageBoxButton.OK, MessageBoxImage.Error) |> ignore
 
     let saveCurrentDocumentAsNewFile () =
         match askDocumentPathToSave () with
@@ -279,7 +282,7 @@ let run (defaultConfig : Config) (fileToOpen : string option) =
     // Ask the use to save the current document if neccessary.
     let askSaveCurrent () =
         if state.AlteredSinceLastSave then
-            match MessageBox.Show("Would you like to save the current document?", "Saving the current document", MessageBoxButton.YesNo, MessageBoxImage.Question) with
+            match MessageBox.Show ("Would you like to save the current document?", "Saving the current document", MessageBoxButton.YesNo, MessageBoxImage.Question) with
             | MessageBoxResult.Yes -> saveCurrentDocument ()
             | _ -> ()
 
@@ -291,11 +294,11 @@ let run (defaultConfig : Config) (fileToOpen : string option) =
             // Highlight the preview.
             win.stackPreviews.Children
             |> Seq.cast<Views.ImageSourcePreview>
-            |> Seq.iter (fun preview -> preview.border.BorderThickness <- Thickness(if preview.Tag = (srcImg :> Object) then 3. else 0.))
+            |> Seq.iter (fun preview -> preview.border.BorderThickness <- Thickness (if preview.Tag = (srcImg :> Object) then 3. else 0.))
 
             win.canvasCurrentImage.Height <- float srcImg.img.Height
             win.canvasCurrentImage.Width <- float srcImg.img.Width
-            win.canvasCurrentImage.Background <- ImageBrush(BitmapSourceConvert.ToBitmapSource(srcImg.img))
+            win.canvasCurrentImage.Background <- ImageBrush (BitmapSourceConvert.ToBitmapSource (srcImg.img))
 
             updateRBCFramesCurrent ()
             updateRBCFramesPreview ()
@@ -303,8 +306,8 @@ let run (defaultConfig : Config) (fileToOpen : string option) =
         | None ->
             win.imgLogos.Visibility <- Visibility.Visible
 
-            win.stackRBC.Children.Clear()
-            win.canvasCurrentImage.Children.Clear()
+            win.stackRBC.Children.Clear ()
+            win.canvasCurrentImage.Children.Clear ()
             win.canvasCurrentImage.Background <- canvasCurrentImageColor
 
         updateCurrentImageInformation ()
@@ -315,27 +318,29 @@ let run (defaultConfig : Config) (fileToOpen : string option) =
             updateCurrentImage ()
 
     let addPreview (srcImg : SourceImage) =
-        let imgCtrl = Views.ImageSourcePreview(Margin = Thickness(3.))
+        let imgCtrl = Views.ImageSourcePreview (Margin = Thickness 3.)
 
-        imgCtrl.menuRemoveImage.Click.AddHandler(fun obj args ->
-            win.stackPreviews.Children.Remove(imgCtrl)
-            let srcImg = imgCtrl.Tag :?> SourceImage
-            let currentRemoved = Some srcImg = state.CurrentImage
-            state.RemoveSourceImage srcImg
-            if currentRemoved then
-                updateCurrentImage()
+        imgCtrl.menuRemoveImage.Click.AddHandler (
+            fun obj args ->
+                win.stackPreviews.Children.Remove (imgCtrl)
+                let srcImg = imgCtrl.Tag :?> SourceImage
+                let currentRemoved = Some srcImg = state.CurrentImage
+                state.RemoveSourceImage srcImg
+                if currentRemoved then
+                    updateCurrentImage ()
 
-            updateGlobalParasitemia()
+                updateGlobalParasitemia ()
 
-            // Update image numbers.
-            win.stackPreviews.Children |> Seq.cast<Views.ImageSourcePreview> |> Seq.iter (fun imgPreview -> imgPreview.txtImageNumber.Text <- (imgPreview.Tag :?> SourceImage).num.ToString()))
+                // Update image numbers.
+                win.stackPreviews.Children |> Seq.cast<Views.ImageSourcePreview> |> Seq.iter (fun imgPreview -> imgPreview.txtImageNumber.Text <- (imgPreview.Tag :?> SourceImage).num.ToString ())
+        )
 
         imgCtrl.Tag <- srcImg
-        imgCtrl.txtImageNumber.Text <- srcImg.num.ToString()
+        imgCtrl.txtImageNumber.Text <- string srcImg.num
         let width = 200
         let height = srcImg.img.Height * width / srcImg.img.Width
-        imgCtrl.imagePreview.Source <- BitmapSourceConvert.ToBitmapSource(srcImg.img.Resize(width, height, Emgu.CV.CvEnum.Inter.Cubic))
-        win.stackPreviews.Children.Add(imgCtrl) |> ignore
+        imgCtrl.imagePreview.Source <- BitmapSourceConvert.ToBitmapSource (srcImg.img.Resize (width, height, Emgu.CV.CvEnum.Inter.Cubic))
+        win.stackPreviews.Children.Add imgCtrl |> ignore
 
         // Zoom to a mouse position into the control 'imgCtrl'.
         let zoomTo (mousePos : Point) =
@@ -343,24 +348,27 @@ let run (defaultConfig : Config) (fileToOpen : string option) =
             let canvasH = win.canvasCurrentImage.ActualHeight * currentScale
             let centerX = (mousePos.X - imgCtrl.BorderThickness.Left) / (imgCtrl.ActualWidth - imgCtrl.BorderThickness.Left) * canvasW
             let centerY = (mousePos.Y - imgCtrl.BorderThickness.Top) / (imgCtrl.ActualHeight - imgCtrl.BorderThickness.Top) * canvasH
-            win.scrollViewCurrentImage.ScrollToHorizontalOffset(centerX - win.scrollViewCurrentImage.ViewportWidth / 2. + win.borderCurrentImage.BorderThickness.Left)
-            win.scrollViewCurrentImage.ScrollToVerticalOffset(centerY - win.scrollViewCurrentImage.ViewportHeight / 2. + win.borderCurrentImage.BorderThickness.Top)
-
-        imgCtrl.MouseLeftButtonDown.AddHandler(fun obj args ->
-            setCurrentImage (state.SourceImages |> Seq.find (fun srcImg -> (srcImg :> Object) = imgCtrl.Tag))
-            imgCtrl.UpdateLayout()
-            zoomTo (args.GetPosition(imgCtrl))
-            imgCtrl.CaptureMouse() |> ignore
+            win.scrollViewCurrentImage.ScrollToHorizontalOffset (centerX - win.scrollViewCurrentImage.ViewportWidth / 2. + win.borderCurrentImage.BorderThickness.Left)
+            win.scrollViewCurrentImage.ScrollToVerticalOffset (centerY - win.scrollViewCurrentImage.ViewportHeight / 2. + win.borderCurrentImage.BorderThickness.Top)
+
+        imgCtrl.MouseLeftButtonDown.AddHandler (
+            fun obj args ->
+                setCurrentImage (state.SourceImages |> Seq.find (fun srcImg -> (srcImg :> Object) = imgCtrl.Tag))
+                imgCtrl.UpdateLayout ()
+                zoomTo (args.GetPosition (imgCtrl))
+                imgCtrl.CaptureMouse () |> ignore
         )
 
-        imgCtrl.MouseMove.AddHandler(fun obj args ->
-            if imgCtrl.IsMouseCaptured then
-                zoomTo (args.GetPosition(imgCtrl))
+        imgCtrl.MouseMove.AddHandler (
+            fun obj args ->
+                if imgCtrl.IsMouseCaptured then
+                    zoomTo (args.GetPosition imgCtrl)
         )
 
-        imgCtrl.MouseLeftButtonUp.AddHandler(fun obj args ->
-            if imgCtrl.IsMouseCaptured then
-                imgCtrl.ReleaseMouseCapture()
+        imgCtrl.MouseLeftButtonUp.AddHandler (
+            fun obj args ->
+                if imgCtrl.IsMouseCaptured then
+                    imgCtrl.ReleaseMouseCapture ()
         )
 
     let updatePreviews () =
@@ -380,48 +388,48 @@ let run (defaultConfig : Config) (fileToOpen : string option) =
         let previousFilePath = state.FilePath
         try
             state.FilePath <- filepath
-            state.Load()
+            state.Load ()
             updateGUI ()
         with
         | :? IOException as ex ->
             Log.Error "%O" ex
             state.FilePath <- previousFilePath
-            MessageBox.Show(sprintf "The document cannot be loaded from \"%s\"" filepath, "Error loading the document", MessageBoxButton.OK, MessageBoxImage.Error) |> ignore
+            MessageBox.Show (sprintf "The document cannot be loaded from \"%s\"" filepath, "Error loading the document", MessageBoxButton.OK, MessageBoxImage.Error) |> ignore
 
     let askLoadFile () =
-        let dialog = OpenFileDialog(Filter = PiaZ.filter)
-        let res = dialog.ShowDialog()
+        let dialog = OpenFileDialog (Filter = PiaZ.filter)
+        let res = dialog.ShowDialog ()
         if res.HasValue && res.Value then
             loadFile dialog.FileName
 
     let newFile () =
         askSaveCurrent ()
-        state.Reset()
-        updateGUI()
+        state.Reset ()
+        updateGUI ()
 
     let exportResults () =
         let extension = ".txt"
-        let dialog = SaveFileDialog(AddExtension = true, DefaultExt = extension)
+        let dialog = SaveFileDialog (AddExtension = true, DefaultExt = extension)
 
         if state.FilePath <> "" then
-            dialog.FileName <- Path.GetFileNameWithoutExtension(state.FilePath) + extension
+            dialog.FileName <- Path.GetFileNameWithoutExtension state.FilePath + extension
         elif state.PatientID <> "" then
             dialog.FileName <- state.PatientID + extension
 
-        let res = dialog.ShowDialog()
+        let res = dialog.ShowDialog ()
         if res.HasValue && res.Value then
             try
                 Export.exportResults state dialog.FileName
             with
             | :? IOException as ex ->
                 Log.Error "%O" ex
-                MessageBox.Show(sprintf "The results cannot be exported in \"%s\"" state.FilePath, "Error exporting the files", MessageBoxButton.OK, MessageBoxImage.Error) |> ignore
+                MessageBox.Show (sprintf "The results cannot be exported in \"%s\"" state.FilePath, "Error exporting the files", MessageBoxButton.OK, MessageBoxImage.Error) |> ignore
 
     let importImage () =
-        let dialog = OpenFileDialog(Filter = "Image Files|*.png;*.jpg;*.tif;*.tiff", Multiselect = true)
-        let res = dialog.ShowDialog()
+        let dialog = OpenFileDialog (Filter = "Image Files|*.png;*.jpg;*.tif;*.tiff", Multiselect = true)
+        let res = dialog.ShowDialog ()
         if res.HasValue && res.Value then
-            let noSourceImage = state.SourceImages.Count() = 0
+            let noSourceImage = state.SourceImages.Count () = 0
 
             for filename in dialog.FileNames do
                 try
@@ -430,7 +438,7 @@ let run (defaultConfig : Config) (fileToOpen : string option) =
                 with
                 | _ as ex ->
                     Log.Error "%O" ex
-                    MessageBox.Show(sprintf "Unable to read the image from \"%s\"" filename, "Error adding an image", MessageBoxButton.OK, MessageBoxImage.Error) |> ignore
+                    MessageBox.Show (sprintf "Unable to read the image from \"%s\"" filename, "Error adding an image", MessageBoxButton.OK, MessageBoxImage.Error) |> ignore
 
             updateGlobalParasitemia ()
 
@@ -447,173 +455,179 @@ let run (defaultConfig : Config) (fileToOpen : string option) =
         updateRBCFramesPreview ()
         updateRBCFramesCurrent ()
 
-    win.txtPatient.TextChanged.AddHandler(fun obj args -> state.PatientID <- win.txtPatient.Text)
+    win.txtPatient.TextChanged.AddHandler (fun obj args -> state.PatientID <- win.txtPatient.Text)
 
-    win.menuExit.Click.AddHandler(fun obj args -> win.Close())
-    win.menuSave.Click.AddHandler(fun obj args -> saveCurrentDocument ())
-    win.menuSaveAs.Click.AddHandler(fun obj args -> saveCurrentDocumentAsNewFile ())
-    win.menuOpen.Click.AddHandler(fun obj args -> askLoadFile ())
-    win.menuNew.Click.AddHandler(fun obj args -> newFile ())
-    win.menuExportResults.Click.AddHandler(fun obj args -> exportResults ())
+    win.menuExit.Click.AddHandler (fun obj args -> win.Close ())
+    win.menuSave.Click.AddHandler (fun obj args -> saveCurrentDocument ())
+    win.menuSaveAs.Click.AddHandler (fun obj args -> saveCurrentDocumentAsNewFile ())
+    win.menuOpen.Click.AddHandler (fun obj args -> askLoadFile ())
+    win.menuNew.Click.AddHandler (fun obj args -> newFile ())
+    win.menuExportResults.Click.AddHandler (fun obj args -> exportResults ())
 
-    win.menuAddSourceImage.Click.AddHandler(fun obj args -> importImage ())
+    win.menuAddSourceImage.Click.AddHandler (fun obj args -> importImage ())
 
-    win.menuAnalysis.SubmenuOpened.AddHandler(fun obj args -> win.menuStartAnalysis.IsEnabled <- state.SourceImages.Count() > 0)
+    win.menuAnalysis.SubmenuOpened.AddHandler (fun obj args -> win.menuStartAnalysis.IsEnabled <- state.SourceImages.Count () > 0)
 
-    win.menuStartAnalysis.Click.AddHandler(fun obj args -> showAnalysisWindow ())
+    win.menuStartAnalysis.Click.AddHandler (fun obj args -> showAnalysisWindow ())
 
-    win.menuHightlightRBC.Click.AddHandler(fun obj args -> setHighlightRBC win.menuHightlightRBC.IsChecked)
+    win.menuHightlightRBC.Click.AddHandler (fun obj args -> setHighlightRBC win.menuHightlightRBC.IsChecked)
 
-    win.menuAbout.Click.AddHandler(fun obj args -> About.showWindow win)
+    win.menuAbout.Click.AddHandler (fun obj args -> About.showWindow win)
 
-    win.Closing.AddHandler(fun obj args -> askSaveCurrent ())
+    win.Closing.AddHandler (fun obj args -> askSaveCurrent ())
 
     // Zoom on the current image.
     let adjustCurrentImageBorders (deltaX : float) (deltaY : float) =
         win.borderCurrentImage.BorderThickness <-
-            Thickness(
+            Thickness (
                 (win.scrollViewCurrentImage.ViewportWidth + deltaX) / 2.,
                 (win.scrollViewCurrentImage.ViewportHeight + deltaY) / 2.,
                 (win.scrollViewCurrentImage.ViewportWidth + deltaX) / 2.,
                 (win.scrollViewCurrentImage.ViewportHeight + deltaY) / 2.
             )
 
-    win.canvasCurrentImage.SizeChanged.AddHandler(fun obj args ->
-        let deltaX = args.NewSize.Width - args.PreviousSize.Width
-        let deltaY = args.NewSize.Height - args.PreviousSize.Height
-        if deltaX > 0.5 || deltaY > 0.5 then
-            adjustCurrentImageBorders 0.0 0.0
-            // Center the view at the center of the image initialy.
-            win.scrollViewCurrentImage.UpdateLayout()
-            win.scrollViewCurrentImage.ScrollToHorizontalOffset(win.borderCurrentImage.ActualWidth / 2. - win.scrollViewCurrentImage.ViewportWidth / 2.)
-            win.scrollViewCurrentImage.ScrollToVerticalOffset(win.borderCurrentImage.ActualHeight / 2. - win.scrollViewCurrentImage.ViewportHeight / 2.)
+    win.canvasCurrentImage.SizeChanged.AddHandler (
+        fun obj args ->
+            let deltaX = args.NewSize.Width - args.PreviousSize.Width
+            let deltaY = args.NewSize.Height - args.PreviousSize.Height
+            if deltaX > 0.5 || deltaY > 0.5 then
+                adjustCurrentImageBorders 0.0 0.0
+                // Center the view at the center of the image initialy.
+                win.scrollViewCurrentImage.UpdateLayout ()
+                win.scrollViewCurrentImage.ScrollToHorizontalOffset (win.borderCurrentImage.ActualWidth / 2. - win.scrollViewCurrentImage.ViewportWidth / 2.)
+                win.scrollViewCurrentImage.ScrollToVerticalOffset (win.borderCurrentImage.ActualHeight / 2. - win.scrollViewCurrentImage.ViewportHeight / 2.)
     )
 
-    win.scrollViewCurrentImage.SizeChanged.AddHandler(fun obj args ->
-        let deltaX = args.NewSize.Width - args.PreviousSize.Width
-        let deltaY = args.NewSize.Height - args.PreviousSize.Height
-        adjustCurrentImageBorders deltaX deltaY
-        win.scrollViewCurrentImage.ScrollToHorizontalOffset(win.scrollViewCurrentImage.HorizontalOffset + deltaX / 8.)
-        win.scrollViewCurrentImage.ScrollToVerticalOffset(win.scrollViewCurrentImage.VerticalOffset + deltaY / 8.)
+    win.scrollViewCurrentImage.SizeChanged.AddHandler (
+        fun obj args ->
+            let deltaX = args.NewSize.Width - args.PreviousSize.Width
+            let deltaY = args.NewSize.Height - args.PreviousSize.Height
+            adjustCurrentImageBorders deltaX deltaY
+            win.scrollViewCurrentImage.ScrollToHorizontalOffset (win.scrollViewCurrentImage.HorizontalOffset + deltaX / 8.)
+            win.scrollViewCurrentImage.ScrollToVerticalOffset (win.scrollViewCurrentImage.VerticalOffset + deltaY / 8.)
     )
 
     let mutable maxScale = 4.
     let mutable minScale = 0.25
-    let currentImageScaleTransform = ScaleTransform()
+    let currentImageScaleTransform = ScaleTransform ()
     win.canvasCurrentImage.LayoutTransform <- currentImageScaleTransform
-    win.borderCurrentImage.PreviewMouseWheel.AddHandler(fun obj args ->
-        let scaleFactor = if args.Delta > 0 then 2.0 else 0.5
-        if scaleFactor > 1. && currentScale < maxScale || scaleFactor < 1. && currentScale > minScale then
-            let previousScale = currentScale
-            currentScale <-
-                let newScale = currentScale * scaleFactor
-                if newScale > maxScale then maxScale elif newScale < minScale then minScale else newScale
-            let realScaleFactor = currentScale / previousScale
+    win.borderCurrentImage.PreviewMouseWheel.AddHandler (
+        fun obj args ->
+            let scaleFactor = if args.Delta > 0 then 2.0 else 0.5
+            if scaleFactor > 1. && currentScale < maxScale || scaleFactor < 1. && currentScale > minScale then
+                let previousScale = currentScale
+                currentScale <-
+                    let newScale = currentScale * scaleFactor
+                    if newScale > maxScale then maxScale elif newScale < minScale then minScale else newScale
+                let realScaleFactor = currentScale / previousScale
 
-            let centerX = win.scrollViewCurrentImage.HorizontalOffset + win.scrollViewCurrentImage.ViewportWidth / 2. - win.borderCurrentImage.BorderThickness.Left
-            let centerY = win.scrollViewCurrentImage.VerticalOffset + win.scrollViewCurrentImage.ViewportHeight / 2. - win.borderCurrentImage.BorderThickness.Top
+                let centerX = win.scrollViewCurrentImage.HorizontalOffset + win.scrollViewCurrentImage.ViewportWidth / 2. - win.borderCurrentImage.BorderThickness.Left
+                let centerY = win.scrollViewCurrentImage.VerticalOffset + win.scrollViewCurrentImage.ViewportHeight / 2. - win.borderCurrentImage.BorderThickness.Top
 
-            currentImageScaleTransform.ScaleX <- currentScale
-            currentImageScaleTransform.ScaleY <- currentScale
+                currentImageScaleTransform.ScaleX <- currentScale
+                currentImageScaleTransform.ScaleY <- currentScale
 
-            win.scrollViewCurrentImage.ScrollToHorizontalOffset(centerX * realScaleFactor - win.scrollViewCurrentImage.ViewportWidth / 2. + win.borderCurrentImage.BorderThickness.Left)
-            win.scrollViewCurrentImage.ScrollToVerticalOffset(centerY * realScaleFactor - win.scrollViewCurrentImage.ViewportHeight / 2. + win.borderCurrentImage.BorderThickness.Top)
+                win.scrollViewCurrentImage.ScrollToHorizontalOffset (centerX * realScaleFactor - win.scrollViewCurrentImage.ViewportWidth / 2. + win.borderCurrentImage.BorderThickness.Left)
+                win.scrollViewCurrentImage.ScrollToVerticalOffset (centerY * realScaleFactor - win.scrollViewCurrentImage.ViewportHeight / 2. + win.borderCurrentImage.BorderThickness.Top)
 
-        args.Handled <- true
+            args.Handled <- true
     )
 
     // Pan on the current image.
-    let mutable scrollStartPosition = Point(0., 0.)
+    let mutable scrollStartPosition = Point (0., 0.)
     let mutable scrollStartOffsetX = 0.
     let mutable scrollStartOffsetY = 0.
-    win.borderCurrentImage.PreviewMouseLeftButtonDown.AddHandler(fun obj args ->
-        scrollStartPosition <- args.GetPosition(win.scrollViewCurrentImage)
-        scrollStartOffsetX <- win.scrollViewCurrentImage.HorizontalOffset
-        scrollStartOffsetY <- win.scrollViewCurrentImage.VerticalOffset
-        win.borderCurrentImage.Cursor <- Input.Cursors.ScrollAll
-        win.borderCurrentImage.CaptureMouse() |> ignore
-        args.Handled <- true
+    win.borderCurrentImage.PreviewMouseLeftButtonDown.AddHandler (
+        fun obj args ->
+            scrollStartPosition <- args.GetPosition win.scrollViewCurrentImage
+            scrollStartOffsetX <- win.scrollViewCurrentImage.HorizontalOffset
+            scrollStartOffsetY <- win.scrollViewCurrentImage.VerticalOffset
+            win.borderCurrentImage.Cursor <- Input.Cursors.ScrollAll
+            win.borderCurrentImage.CaptureMouse () |> ignore
+            args.Handled <- true
     )
 
-    win.borderCurrentImage.PreviewMouseMove.AddHandler(fun obj args ->
-        if win.borderCurrentImage.IsMouseCaptured then
-            let position = args.GetPosition(win.scrollViewCurrentImage)
-            let deltaX = scrollStartPosition.X - position.X
-            let deltaY = scrollStartPosition.Y - position.Y
-            win.scrollViewCurrentImage.ScrollToHorizontalOffset(deltaX + scrollStartOffsetX)
-            win.scrollViewCurrentImage.ScrollToVerticalOffset(deltaY + scrollStartOffsetY)
+    win.borderCurrentImage.PreviewMouseMove.AddHandler (
+        fun obj args ->
+            if win.borderCurrentImage.IsMouseCaptured then
+                let position = args.GetPosition win.scrollViewCurrentImage
+                let deltaX = scrollStartPosition.X - position.X
+                let deltaY = scrollStartPosition.Y - position.Y
+                win.scrollViewCurrentImage.ScrollToHorizontalOffset (deltaX + scrollStartOffsetX)
+                win.scrollViewCurrentImage.ScrollToVerticalOffset (deltaY + scrollStartOffsetY)
 
-            args.Handled <- true
+                args.Handled <- true
     )
 
-    win.borderCurrentImage.PreviewMouseLeftButtonUp.AddHandler(fun obj args ->
-        if win.borderCurrentImage.IsMouseCaptured then
-            win.borderCurrentImage.Cursor <- Input.Cursors.Arrow
-            win.borderCurrentImage.ReleaseMouseCapture()
-            args.Handled <- true
+    win.borderCurrentImage.PreviewMouseLeftButtonUp.AddHandler (
+        fun obj args ->
+            if win.borderCurrentImage.IsMouseCaptured then
+                win.borderCurrentImage.Cursor <- Input.Cursors.Arrow
+                win.borderCurrentImage.ReleaseMouseCapture ()
+                args.Handled <- true
     )
 
     // Shortcuts.
     // Save.
-    win.InputBindings.Add(
-        Input.KeyBinding(
-            ViewModule.FunCommand((fun obj -> saveCurrentDocument ()), (fun obj -> true)),
-            Input.KeyGesture(Input.Key.S, Input.ModifierKeys.Control)
+    win.InputBindings.Add (
+        Input.KeyBinding (
+            ViewModule.FunCommand ((fun obj -> saveCurrentDocument ()), (fun obj -> true)),
+            Input.KeyGesture (Input.Key.S, Input.ModifierKeys.Control)
         )
     ) |> ignore
 
     // Save as.
-    win.InputBindings.Add(
-        Input.KeyBinding(
-            ViewModule.FunCommand((fun obj -> saveCurrentDocumentAsNewFile ()), (fun obj -> true)),
-            Input.KeyGesture(Input.Key.S, Input.ModifierKeys.Control ||| Input.ModifierKeys.Shift)
+    win.InputBindings.Add (
+        Input.KeyBinding (
+            ViewModule.FunCommand ((fun obj -> saveCurrentDocumentAsNewFile ()), (fun obj -> true)),
+            Input.KeyGesture (Input.Key.S, Input.ModifierKeys.Control ||| Input.ModifierKeys.Shift)
         )
     ) |> ignore
 
     // Open.
-    win.InputBindings.Add(
-        Input.KeyBinding(
-            ViewModule.FunCommand((fun obj -> askLoadFile ()), (fun obj -> true)),
-            Input.KeyGesture(Input.Key.O, Input.ModifierKeys.Control)
+    win.InputBindings.Add (
+        Input.KeyBinding (
+            ViewModule.FunCommand ((fun obj -> askLoadFile ()), (fun obj -> true)),
+            Input.KeyGesture (Input.Key.O, Input.ModifierKeys.Control)
         )
     ) |> ignore
 
     // New file.
-    win.InputBindings.Add(
-        Input.KeyBinding(
-            ViewModule.FunCommand((fun obj -> newFile ()), (fun obj -> true)),
-            Input.KeyGesture(Input.Key.N, Input.ModifierKeys.Control)
+    win.InputBindings.Add (
+        Input.KeyBinding (
+            ViewModule.FunCommand ((fun obj -> newFile ()), (fun obj -> true)),
+            Input.KeyGesture (Input.Key.N, Input.ModifierKeys.Control)
         )
     ) |> ignore
 
     // Export results.
-    win.InputBindings.Add(
-        Input.KeyBinding(
-            ViewModule.FunCommand((fun obj -> exportResults ()), (fun obj -> true)),
-            Input.KeyGesture(Input.Key.E, Input.ModifierKeys.Control)
+    win.InputBindings.Add (
+        Input.KeyBinding (
+            ViewModule.FunCommand ((fun obj -> exportResults ()), (fun obj -> true)),
+            Input.KeyGesture (Input.Key.E, Input.ModifierKeys.Control)
         )
     ) |> ignore
 
     // Import an image.
-    win.InputBindings.Add(
-        Input.KeyBinding(
-            ViewModule.FunCommand((fun obj -> importImage ()), (fun obj -> true)),
-            Input.KeyGesture(Input.Key.A, Input.ModifierKeys.Control)
+    win.InputBindings.Add (
+        Input.KeyBinding (
+            ViewModule.FunCommand ((fun obj -> importImage ()), (fun obj -> true)),
+            Input.KeyGesture (Input.Key.A, Input.ModifierKeys.Control)
         )
     ) |> ignore
 
     // Show analysis dialog.
-    win.InputBindings.Add(
-        Input.KeyBinding(
-            ViewModule.FunCommand((fun obj -> showAnalysisWindow ()), (fun obj -> state.SourceImages.Count() > 0)),
-            Input.KeyGesture(Input.Key.Y, Input.ModifierKeys.Control)
+    win.InputBindings.Add (
+        Input.KeyBinding (
+            ViewModule.FunCommand ((fun obj -> showAnalysisWindow ()), (fun obj -> state.SourceImages.Count () > 0)),
+            Input.KeyGesture (Input.Key.Y, Input.ModifierKeys.Control)
         )
     ) |> ignore
 
     // Toggle RBC highlight.
-    win.InputBindings.Add(
-        Input.KeyBinding(
-            ViewModule.FunCommand(
+    win.InputBindings.Add (
+        Input.KeyBinding (
+            ViewModule.FunCommand (
                 (
                     fun obj ->
                         win.menuHightlightRBC.IsChecked <- not win.menuHightlightRBC.IsChecked
@@ -621,20 +635,20 @@ let run (defaultConfig : Config) (fileToOpen : string option) =
                 ),
                 (fun obj -> true)
             ),
-            Input.KeyGesture(Input.Key.H, Input.ModifierKeys.Control)
+            Input.KeyGesture (Input.Key.H, Input.ModifierKeys.Control)
         )
     ) |> ignore
 
     // Viewport preview.
-    win.scrollViewCurrentImage.ScrollChanged.AddHandler(fun obj args -> updateViewportPreview ())
+    win.scrollViewCurrentImage.ScrollChanged.AddHandler (fun obj args -> updateViewportPreview ())
 
     updateDocumentStatus ()
     win.gridImageInformation.Visibility <- Visibility.Hidden
 
-    win.Show()
+    win.Show ()
 
     match fileToOpen with
     | Some filepath -> loadFile filepath
     | None -> ()
 
-    app.Run()
+    app.Run ()
index 200460e..0324219 100644 (file)
       <HintPath>..\packages\EmguCV.3.1.0.1\lib\net30\Emgu.CV.World.dll</HintPath>
     </Reference>
     <Reference Include="FSharp.Core">
-      <HintPath>..\packages\FSharp.Core.4.1.17\lib\net45\FSharp.Core.dll</HintPath>
+      <HintPath>..\packages\FSharp.Core.4.2.1\lib\net45\FSharp.Core.dll</HintPath>
     </Reference>
     <Reference Include="FSharp.ViewModule">
       <HintPath>..\packages\FSharp.ViewModule.Core.1.0.7.0\lib\portable-net45+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1\FSharp.ViewModule.dll</HintPath>
     </Reference>
     <Reference Include="mscorlib" />
     <Reference Include="Newtonsoft.Json">
-      <HintPath>..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
+      <HintPath>..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
     </Reference>
     <Reference Include="OpenTK">
       <HintPath>..\packages\OpenTK.2.0.0\lib\net20\OpenTK.dll</HintPath>
index 0215254..92ebbe0 100644 (file)
@@ -56,26 +56,26 @@ let currentFileVersion = 2
 /// <param name="data"></param>
 /// <exception cref="System.IOException">If the file cannot be written</exception>
 let save (filePath : string) (data : DocumentData) =
-    use file = ZipFile.Open(filePath, ZipArchiveMode.Update)
+    use file = ZipFile.Open (filePath, ZipArchiveMode.Update)
 
     for e in List.ofSeq file.Entries do // 'ofSeq' to not iterate a collection currently modified.
-        e.Delete()
+        e.Delete ()
 
     // Main JSON file.
-    let mainEntry = file.CreateEntry(mainEntryName, CompressionLevel.Fastest)
-    use mainEntryWriter = new StreamWriter(mainEntry.Open())
-    mainEntryWriter.Write(JsonConvert.SerializeObject({ patientID = data.patientID; fileVersion = currentFileVersion }))
+    let mainEntry = file.CreateEntry (mainEntryName, CompressionLevel.Fastest)
+    use mainEntryWriter = new StreamWriter (mainEntry.Open ())
+    mainEntryWriter.Write (JsonConvert.SerializeObject ({ patientID = data.patientID; fileVersion = currentFileVersion }))
 
     // Write each images and the associated information.
     for srcImg in data.images do
         let imgFilename = (string srcImg.num) + imageExtension
-        let imgEntry = file.CreateEntry(imgFilename, CompressionLevel.NoCompression) // FIXME: It seems a compression is applied to this file despite of the 'NoCompression' flag.
-        srcImg.img.ToBitmap().Save(imgEntry.Open(), System.Drawing.Imaging.ImageFormat.Tiff)
+        let imgEntry = file.CreateEntry (imgFilename, CompressionLevel.NoCompression) // FIXME: It seems a compression is applied to this file despite of the 'NoCompression' flag.
+        srcImg.img.ToBitmap().Save (imgEntry.Open (), System.Drawing.Imaging.ImageFormat.Tiff)
 
-        let imgJSONEntry = file.CreateEntry(imgFilename + ".json", CompressionLevel.Fastest)
-        use imgJSONFileWriter = new StreamWriter(imgJSONEntry.Open())
-        imgJSONFileWriter.Write(
-            JsonConvert.SerializeObject(
+        let imgJSONEntry = file.CreateEntry (imgFilename + ".json", CompressionLevel.Fastest)
+        use imgJSONFileWriter = new StreamWriter (imgJSONEntry.Open ())
+        imgJSONFileWriter.Write (
+            JsonConvert.SerializeObject (
                 {
                     num = srcImg.num
                     name = srcImg.name
@@ -103,11 +103,11 @@ let updateDocumentData (fromVersion : int) (toVersion : int) (data : DocumentDat
 /// <param name="filePath"></param>
 /// <exception cref="System.IOException">If the file cannot be read</exception>
 let load (filePath : string) (defaultConfig : ParasitemiaCore.Config.Config) : DocumentData =
-    use file = ZipFile.Open(filePath, ZipArchiveMode.Read)
+    use file = ZipFile.Open (filePath, ZipArchiveMode.Read)
 
-    let mainEntry = file.GetEntry(mainEntryName)
-    use mainEntryReader = new StreamReader(mainEntry.Open())
-    let info = JsonConvert.DeserializeObject<JSONInformation>(mainEntryReader.ReadToEnd())
+    let mainEntry = file.GetEntry (mainEntryName)
+    use mainEntryReader = new StreamReader (mainEntry.Open ())
+    let info = JsonConvert.DeserializeObject<JSONInformation> (mainEntryReader.ReadToEnd ())
 
     updateDocumentData info.fileVersion currentFileVersion
         {
@@ -116,15 +116,15 @@ let load (filePath : string) (defaultConfig : ParasitemiaCore.Config.Config) : D
                 [
                     let mutable imgNum = 0
                     for imgEntry in file.Entries do
-                        if imgEntry.Name.EndsWith(imageExtension) then
-                            use bitmap = new System.Drawing.Bitmap(imgEntry.Open(), false)
-                            let img = new Image<Bgr, byte>(bitmap)
+                        if imgEntry.Name.EndsWith (imageExtension) then
+                            use bitmap = new System.Drawing.Bitmap (imgEntry.Open (), false)
+                            let img = new Image<Bgr, byte> (bitmap)
                             imgNum <- imgNum + 1
-                            let imgJSONEntry = file.GetEntry(imgEntry.Name + ".json")
-                            use imgJSONFileReader = new StreamReader(imgJSONEntry.Open())
-                            let imgInfo = JsonConvert.DeserializeObject<JSONSourceImage>(imgJSONFileReader.ReadToEnd())
+                            let imgJSONEntry = file.GetEntry (imgEntry.Name + ".json")
+                            use imgJSONFileReader = new StreamReader (imgJSONEntry.Open ())
+                            let imgInfo = JsonConvert.DeserializeObject<JSONSourceImage> (imgJSONFileReader.ReadToEnd ())
 
-                            let config = defaultConfig.Copy()
+                            let config = defaultConfig.Copy ()
                             config.Parameters <-
                                 {
                                     ParasitemiaCore.Config.defaultParameters with
index 0f6df12..b7b4202 100644 (file)
@@ -35,7 +35,7 @@ let parseArgs (args : string[]) : Arguments =
             | Some i, Some i_output when i < args.Length - 2 && i_output < args.Length - 2 ->
                 CmdLine ((File args.[i + 1]), args.[i_output + 1])
             |_ ->
-                Window (if args.Length > 0 && not (args.[0].StartsWith("--")) then Some args.[0] else None)
+                Window (if args.Length > 0 && not (args.[0].StartsWith ("--")) then Some args.[0] else None)
 
     runningMode, Array.exists ((=) "--debug") args
 
@@ -53,14 +53,14 @@ let showArgsHelp () =
     printfn "    <document-file> : a PIAZ file to automatically open at startup"
     printfn "    --debug : output information like intermediate images if set in the current directory"
 
-[<System.Runtime.InteropServices.DllImport("kernel32.dll")>]
-extern bool AttachConsole(int dwProcessId)
+[<System.Runtime.InteropServices.DllImport "kernel32.dll">]
+extern bool AttachConsole (int dwProcessId)
 
 [<EntryPoint>]
-[<STAThread()>]
+[<STAThread ()>]
 let main args =
     // To redirect stdout to the attached console.
-    AttachConsole(-1) |> ignore // -1 to attach to the parent process.
+    AttachConsole -1 |> ignore // -1 to attach to the parent process.
 
     if Array.exists (fun e -> e = "--help" || e = "-h") args then
         showArgsHelp ()
@@ -72,7 +72,7 @@ let main args =
             let result =
                 match parseArgs args with
                 | mode, debug ->
-                    let config = Config(defaultParameters)
+                    let config = Config defaultParameters
 
                     match mode with
                     | CmdLine (input, output) ->
@@ -81,9 +81,9 @@ let main args =
 
                         Directory.CreateDirectory output |> ignore
 
-                        use logFile = new StreamWriter(new FileStream(Path.Combine(output, "log.txt"), FileMode.Append, FileAccess.Write))
-                        let listener = { new IListener with member this.NewEntry severity header mess = logFile.WriteLine(header + " : " + mess) }
-                        Log.AddListener(listener)
+                        use logFile = new StreamWriter (new FileStream (Path.Combine(output, "log.txt"), FileMode.Append, FileAccess.Write))
+                        let listener = { new IListener with member this.NewEntry severity header mess = logFile.WriteLine (header + " : " + mess) }
+                        Log.AddListener listener
 
                         Log.Info "=== New run : %O %s ===" DateTime.Now  (if debug then "[DEBUG]" else "[RELEASE]")
 
@@ -91,23 +91,25 @@ let main args =
                                     | File file -> [ file ]
                                     | Dir dir -> Directory.EnumerateFiles dir |> List.ofSeq
 
-                        use resultFile = new StreamWriter(new FileStream(Path.Combine(output, "results.txt"), FileMode.Append, FileAccess.Write))
-
-                        let images = [ for file in files -> Path.GetFileNameWithoutExtension(FileInfo(file).Name), config.Copy(), new Image<Bgr, byte>(file) ]
-
-                        Log.LogWithTime Severity.INFO (fun () ->
-                            match ParasitemiaCore.Analysis.doMultipleAnalysis images None with
-                            | Some results ->
-                                for id, cells in results do
-                                    let config, img = images |> List.pick (fun (id', config', img') -> if id' = id then Some (config', img') else None)
-                                    img.Dispose()
-                                    let total, infected = countCells cells
-                                    fprintf resultFile "File: %s %d %d %.2f (diameter: %O)\n" id total infected (100. * (float infected) / (float total)) config.RBCRadius
-                            | None ->
-                                fprintf resultFile "Analysis aborted"
-                            Some ()) "Whole analyze" |> ignore
-
-                        Log.RmListener(listener)
+                        use resultFile = new StreamWriter (new FileStream (Path.Combine (output, "results.txt"), FileMode.Append, FileAccess.Write))
+
+                        let images = [ for file in files -> Path.GetFileNameWithoutExtension (FileInfo(file).Name), config.Copy(), new Image<Bgr, byte> (file) ]
+
+                        Log.LogWithTime Severity.INFO (
+                            fun () ->
+                                match ParasitemiaCore.Analysis.doMultipleAnalysis images None with
+                                | Some results ->
+                                    for id, cells in results do
+                                        let config, img = images |> List.pick (fun (id', config', img') -> if id' = id then Some (config', img') else None)
+                                        img.Dispose ()
+                                        let total, infected = countCells cells
+                                        fprintf resultFile "File: %s %d %d %.2f (diameter: %O)\n" id total infected (100. * (float infected) / (float total)) config.RBCRadius
+                                | None ->
+                                    fprintf resultFile "Analysis aborted"
+                                Some ()
+                        ) "Whole analyze" |> ignore
+
+                        Log.RmListener (listener)
                         0
 
                     | Window fileToOpen ->
index d09fe23..3355a42 100644 (file)
@@ -10,7 +10,7 @@ open Emgu.CV.Structure
 open Types
 
 type State (defaultConfig : ParasitemiaCore.Config.Config) =
-    let sourceImages = List<SourceImage>()
+    let sourceImages = List<SourceImage> ()
     let mutable alteredSinceLastSave = false
     let mutable patientID = ""
 
@@ -80,8 +80,8 @@ type State (defaultConfig : ParasitemiaCore.Config.Config) =
     member this.Load () =
         let data = PiaZ.load this.FilePath defaultConfig
         this.PatientID <- data.patientID
-        sourceImages.Clear()
-        sourceImages.InsertRange(0, data.images)
+        sourceImages.Clear ()
+        sourceImages.InsertRange (0, data.images)
         this.CurrentImage <- if sourceImages.Count > 0 then Some sourceImages.[0] else None
         alteredSinceLastSave <- false
 
@@ -93,15 +93,15 @@ type State (defaultConfig : ParasitemiaCore.Config.Config) =
             {
                 num = sourceImages.Count + 1
                 name = System.IO.FileInfo(filePath).Name
-                config = defaultConfig.Copy()
-                dateLastAnalysis = DateTime(0L)
+                config = defaultConfig.Copy ()
+                dateLastAnalysis = DateTime (0L)
                 rbcs = []
-                img = new Image<Bgr, byte>(filePath)
+                img = new Image<Bgr, byte> (filePath)
                 healthyRBCBrightness = 1.f
                 infectedRBCBrightness = 1.f
             }
 
-        sourceImages.Add(srcImg)
+        sourceImages.Add srcImg
         if sourceImages.Count = 1 then
             this.CurrentImage <- Some sourceImages.[0]
         alteredSinceLastSave <- true
@@ -113,7 +113,7 @@ type State (defaultConfig : ParasitemiaCore.Config.Config) =
             | Some srcImg' -> srcImg = srcImg'
             | _ -> false
 
-        if sourceImages.Remove(srcImg) then
+        if sourceImages.Remove srcImg then
             alteredSinceLastSave <- true
             if isCurrent then
                 this.CurrentImage <- if sourceImages.Count > 0 then Some sourceImages.[0] else None
@@ -126,7 +126,7 @@ type State (defaultConfig : ParasitemiaCore.Config.Config) =
             alteredSinceLastSave <- true
 
     member this.SetResult (imgNum : int) (cells : ParasitemiaCore.Types.Cell list) =
-        let sourceImage = sourceImages.Find(fun srcImg -> srcImg.num = imgNum)
+        let sourceImage = sourceImages.Find (fun srcImg -> srcImg.num = imgNum)
 
         let w = sourceImage.img.Width
         let h = sourceImage.img.Height
@@ -137,8 +137,14 @@ type State (defaultConfig : ParasitemiaCore.Config.Config) =
         let manuallyAlteredPreviousRBCS = sourceImage.rbcs |> List.filter (fun rbc -> rbc.setManually)
         let tolerance = (float sourceImage.config.RBCRadius.Pixel) * 0.5 // +/-.
         let getPreviousManuallyAlteredRBC (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)
+            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
@@ -146,7 +152,7 @@ type State (defaultConfig : ParasitemiaCore.Config.Config) =
             |> List.sortByDescending (fun cell -> cell.nucleusArea, (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 center = Point (float cell.center.X, float cell.center.Y)
                     let infected, setManually =
                         let infected = cell.cellClass = ParasitemiaCore.Types.InfectedRBC
                         match getPreviousManuallyAlteredRBC center with
@@ -157,7 +163,7 @@ type State (defaultConfig : ParasitemiaCore.Config.Config) =
                         infected = infected
                         setManually = setManually
                         center = center
-                        size = Size(float cell.elements.Width, float cell.elements.Height)
+                        size = Size (float cell.elements.Width, float cell.elements.Height)
                         infectedArea = cell.nucleusArea
                     }
             )
@@ -171,5 +177,5 @@ type State (defaultConfig : ParasitemiaCore.Config.Config) =
         this.PatientID <- ""
         this.FilePath <- ""
         this.CurrentImage <- None
-        sourceImages.Clear()
+        sourceImages.Clear ()
         alteredSinceLastSave <- false
\ No newline at end of file
index eb778d8..ada2a1f 100644 (file)
@@ -11,8 +11,8 @@ open Newtonsoft.Json
 
 open ParasitemiaCore.UnitsOfMeasure
 
-let healthyRBColor = Color.FromRgb(255uy, 255uy, 0uy) // Yellow-green.
-let infectedRBColor = Color.FromRgb(255uy, 0uy, 40uy) // Red with a bit of blue.
+let healthyRBColor = Color.FromRgb (255uy, 255uy, 0uy) // Yellow-green.
+let infectedRBColor = Color.FromRgb (255uy, 0uy, 40uy) // Red with a bit of blue.
 
 type RBC =
     {
@@ -46,12 +46,12 @@ type SourceImage =
         member this.HealthyRBCColor : SolidColorBrush =
             let mutable color = healthyRBColor * this.healthyRBCBrightness
             color.A <- 255uy
-            SolidColorBrush(color)
+            SolidColorBrush (color)
 
         member this.InfectedRBCColor : SolidColorBrush =
             let mutable color = infectedRBColor * this.infectedRBCBrightness
             color.A <- 255uy
-            SolidColorBrush(color)
+            SolidColorBrush (color)
 
 type PredefinedPPI =
     {
@@ -59,7 +59,7 @@ type PredefinedPPI =
         label : string
     }
     with
-        override this.ToString() =
+        override this.ToString () =
             sprintf "%s: %d" this.label this.ppi
 
 type SensorSize =
index fa4af25..384a0d0 100644 (file)
@@ -7,8 +7,8 @@ open Newtonsoft.Json.Converters
 
 open Types
 
-let listAsStr (s : 'a seq) =
-    s |> Seq.fold (fun acc obj -> acc + (if acc = "" then "" else ", ") + obj.ToString()) ""
+let inline listAsStr (s : 'a seq) =
+    s |> Seq.fold (fun acc obj -> acc + (if acc = "" then "" else ", ") + string obj) ""
 
 let percentText (nbTotal : int, nb : int) : string =
     if nbTotal = 0 then
@@ -18,34 +18,34 @@ let percentText (nbTotal : int, nb : int) : string =
         sprintf "%.1f %% (%d / %d)" percent nb nbTotal
 
 let roamingDir =
-    Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.ApplicationData), "Parasitemia")
+    Path.Combine (System.Environment.GetFolderPath (System.Environment.SpecialFolder.ApplicationData), "Parasitemia")
 
 let predefinedPPIFilename = "predefined-ppi.json"
-let predefinedPPIFilepath = Path.Combine(roamingDir, predefinedPPIFilename)
+let predefinedPPIFilepath = Path.Combine (roamingDir, predefinedPPIFilename)
 
 let sensorSizesFilename = "sensor-sizes.json"
-let sensorSizesFilepath = Path.Combine(roamingDir, sensorSizesFilename)
+let sensorSizesFilepath = Path.Combine (roamingDir, sensorSizesFilename)
 
 let private savePredefinedPPIToFile (predefinedPPI : PredefinedPPI list) =
     try
-        use file = new StreamWriter(predefinedPPIFilepath)
-        file.Write(JsonConvert.SerializeObject(predefinedPPI, JsonSerializerSettings(Formatting = Formatting.Indented)))
+        use file = new StreamWriter (predefinedPPIFilepath)
+        file.Write (JsonConvert.SerializeObject (predefinedPPI, JsonSerializerSettings (Formatting = Formatting.Indented)))
     with
         ex ->
             Logger.Log.Error "Unable to save predefined PPI to file \"%s\": %O" predefinedPPIFilepath ex
 
 let private saveSensorSizesToFile (sensorSizes : SensorSize list) =
     try
-        use file = new StreamWriter(sensorSizesFilepath)
-        file.Write(JsonConvert.SerializeObject(sensorSizes, JsonSerializerSettings(Formatting = Formatting.Indented)))
+        use file = new StreamWriter (sensorSizesFilepath)
+        file.Write (JsonConvert.SerializeObject (sensorSizes, JsonSerializerSettings (Formatting = Formatting.Indented)))
     with
         ex ->
             Logger.Log.Error "Unable to save sensor sizes to file \"%s\": %O" sensorSizesFilepath ex
 
 let predefinedPPI : PredefinedPPI list =
     try
-        use file = new StreamReader(predefinedPPIFilepath)
-        JsonConvert.DeserializeObject<PredefinedPPI list>(file.ReadToEnd())
+        use file = new StreamReader (predefinedPPIFilepath)
+        JsonConvert.DeserializeObject<PredefinedPPI list> (file.ReadToEnd ())
     with
     | ex ->
         savePredefinedPPIToFile defaultPredefinedPPI
@@ -53,8 +53,8 @@ let predefinedPPI : PredefinedPPI list =
 
 let sensorSizes : SensorSize list =
     try
-        use file = new StreamReader(sensorSizesFilepath)
-        JsonConvert.DeserializeObject<SensorSize list>(file.ReadToEnd())
+        use file = new StreamReader (sensorSizesFilepath)
+        JsonConvert.DeserializeObject<SensorSize list> (file.ReadToEnd ())
     with
     | ex ->
         saveSensorSizesToFile defaultSensorSizes
index 89d3dcf..30067c6 100644 (file)
@@ -2,10 +2,10 @@
 <packages>
   <package id="EmguCV" version="3.1.0.1" targetFramework="net452" />
   <package id="Expression.Blend.Sdk" version="1.0.2" targetFramework="net46" />
-  <package id="FSharp.Core" version="4.1.17" targetFramework="net452" />
+  <package id="FSharp.Core" version="4.2.1" targetFramework="net452" />
   <package id="FSharp.ViewModule.Core" version="1.0.7.0" targetFramework="net462" />
   <package id="FsXaml.Wpf" version="3.1.6" targetFramework="net462" />
-  <package id="Newtonsoft.Json" version="10.0.2" targetFramework="net452" />
+  <package id="Newtonsoft.Json" version="10.0.3" targetFramework="net452" />
   <package id="OpenTK" version="2.0.0" targetFramework="net452" />
   <package id="OpenTK.GLControl" version="1.1.2349.61993" targetFramework="net452" />
   <package id="System.ValueTuple" version="4.3.1" targetFramework="net452" />
index d448a0d..931f17d 100644 (file)
@@ -7,22 +7,22 @@ open System.Runtime.InteropServices
 // General Information about an assembly is controlled through the following
 // set of attributes. Change these attribute values to modify the information
 // associated with an assembly.
-[<assembly: AssemblyTitle("ParasitemiaCore.Tests")>]
-[<assembly: AssemblyDescription("")>]
-[<assembly: AssemblyConfiguration("")>]
-[<assembly: AssemblyCompany("HES-SO / CHUV / Grégory Burri")>]
-[<assembly: AssemblyProduct("ParasitemiaCore.Tests")>]
-[<assembly: AssemblyCopyright("Copyright © 2015-2016")>]
-[<assembly: AssemblyTrademark("")>]
-[<assembly: AssemblyCulture("")>]
+[<assembly: AssemblyTitle "ParasitemiaCore.Tests">]
+[<assembly: AssemblyDescription "">]
+[<assembly: AssemblyConfiguration "">]
+[<assembly: AssemblyCompany "HES-SO / CHUV / Grégory Burri">]
+[<assembly: AssemblyProduct "ParasitemiaCore.Tests">]
+[<assembly: AssemblyCopyright "Copyright © 2015-2016">]
+[<assembly: AssemblyTrademark "">]
+[<assembly: AssemblyCulture "">]
 
 // Setting ComVisible to false makes the types in this assembly not visible
 // to COM components.  If you need to access a type in this assembly from
 // COM, set the ComVisible attribute to true on that type.
-[<assembly: ComVisible(false)>]
+[<assembly: ComVisible false>]
 
 // The following GUID is for the ID of the typelib if this project is exposed to COM
-[<assembly: Guid("0f8a85f4-9328-40c3-b8ff-44fb39ceb01f")>]
+[<assembly: Guid "0f8a85f4-9328-40c3-b8ff-44fb39ceb01f">]
 
 // Version information for an assembly consists of the following four values:
 //
@@ -33,11 +33,11 @@ open System.Runtime.InteropServices
 //
 // You can specify all the values or you can default the Build and Revision Numbers
 // by using the '*' as shown below:
-// [<assembly: AssemblyVersion("1.0.*")>]
-[<assembly: AssemblyVersion("1.0.0.0")>]
-[<assembly: AssemblyFileVersion("1.0.0.0")>]
+// [<assembly: AssemblyVersion "1.0.*">]
+[<assembly: AssemblyVersion "1.0.0.0">]
+[<assembly: AssemblyFileVersion "1.0.0.0">]
 
-[<assembly: InternalsVisibleTo("ParasitemiaCore.Tests")>]
+[<assembly: InternalsVisibleTo "ParasitemiaCore.Tests">]
 
 do
     ()
\ No newline at end of file
index 9c9d859..9181c26 100644 (file)
@@ -20,13 +20,13 @@ type KdTreeTests (output : ITestOutputHelper) =
     member this.test () =
         let pts =
             [
-                Point(1.0f, 1.0f)
-                Point(2.0f, 2.0f)
-                Point(1.5f, 3.6f)
-                Point(3.0f, 3.2f)
-                Point(4.0f, 4.0f)
-                Point(3.5f, 1.5f)
-                Point(2.5f, 0.5f)
+                Point (1.0f, 1.0f)
+                Point (2.0f, 2.0f)
+                Point (1.5f, 3.6f)
+                Point (3.0f, 3.2f)
+                Point (4.0f, 4.0f)
+                Point (3.5f, 1.5f)
+                Point (2.5f, 0.5f)
             ]
 
         let tree = Tree.BuildTree pts
@@ -45,9 +45,9 @@ type KdTreeTests (output : ITestOutputHelper) =
     member this.test2 () =
         let pts =
             [
-                Point(1.0f, 1.0f)
-                Point(1.0f, 2.0f)
-                Point(1.0f, 3.0f)
+                Point (1.0f, 1.0f)
+                Point (1.0f, 2.0f)
+                Point (1.0f, 3.0f)
             ]
 
         let tree = Tree.BuildTree pts
index dc8cf62..d0cdfa5 100644 (file)
@@ -54,7 +54,7 @@
   </ItemGroup>
   <ItemGroup>
     <Reference Include="FSharp.Core">
-      <HintPath>..\packages\FSharp.Core.4.1.17\lib\net45\FSharp.Core.dll</HintPath>
+      <HintPath>..\..\packages\FSharp.Core.4.2.1\lib\net45\FSharp.Core.dll</HintPath>
     </Reference>
     <Reference Include="System" />
     <Reference Include="System.Core" />
index 63ccec1..6d282b2 100644 (file)
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <packages>
-  <package id="FSharp.Core" version="4.1.17" targetFramework="net452" />
+  <package id="FSharp.Core" version="4.2.1" targetFramework="net452" />
   <package id="System.ValueTuple" version="4.3.1" targetFramework="net452" />
   <package id="xunit" version="2.2.0" targetFramework="net452" />
   <package id="xunit.abstractions" version="2.0.1" targetFramework="net452" />