CellCounter


Counting results

To determine the effectiveness of the Cell Counter, I compared it to two different other counting methods. One of them was manual counting using the Neubauer counting chamber, the other was counting the cells with a Coulter Counter. For that i took a cell suspension with ~1.35 * 10^7 cells and set up a serial dilution by always halving the amount up to 1:16. I took 3 measurements for each timepoint. One measurement for both, the Cell Counter and the manual counting, consists of three seperate images.

Here you can see the result of those measurements:
























The Y-error bar represents the standard deviation of the 3 measurements taken at each dilution step.

As you can see in this little test, all three methods give comparable results regarding the amount of cells/ml. While the manual counting of cells is a tedious approach, the Cell Counter has it's merits in efficiency compared to the Coulter Counter. All it needs are pictures taken under a microscope, which is easily done, even more so if it is done for more than one culture at once since it is only swapping of objectives then. It is also usefull for the cell counting in bioreactors. Bioreactors have to be monitored constantly for possible infections under the microscope with picture documentation, so one can use those pictures as input for the Cell Counter at the same time.

Experiment Data

For those of you, who want to replicate the experiment, here are the parameters used in the functions and the picture data:

Camera and microscope

  • Pixel Size : 6.45x6.45 microns
  • Binning : 2x2
  • Camera Mount : 2x
  • Magnification : 20x

Cells

  • Diameter: 9.5 microns

Here are the pictures for the program to analyze.

The corresponding code looks like this:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
let dimension = Filter.squareCalculator 6.45 2. 20. 2.

let wvRadius = Filter.cellRadiusCalculator 9.5 6.45 2. 20. 2.

let processFolders folderPath height width radius multiplier = 
    let subfolders  = Directory.GetDirectories folderPath
    let result      = subfolders
                      |> Array.mapi (fun i folder ->
                            printfn "processing folder %i of %i" (i+1) subfolders.Length
                            Pipeline.processImages folder height width radius multiplier) 
    result

let processAll = processFolders @"...\Dilution\CoulterCounter"
                    dimension dimension wvRadius 0.2

The data for the manual counting can be found here, and the Coulter Counter data is here.

A more in depth explanation how to adapt the functions for your use can be found here

Multiple items
namespace FSharp

--------------------
namespace Microsoft.FSharp
namespace FSharp.Plotly
namespace CounterFunctions
namespace System
namespace System.IO
val cellCounter : float []
val cellCounterStabw : float []
val manual : float []
val manualStabw : float []
val coulterCounter : float []
val coulterCounterStabw : float []
val increments : string []
val xAxis : title:'a -> Axis.LinearAxis
val title : 'a
module Axis

from FSharp.Plotly
Multiple items
type LinearAxis =
  inherit DynamicObj
  new : unit -> LinearAxis
  static member init : ?AxisType:AxisType * ?Title:'a * ?Titlefont:Font * ?Autorange:AutoRange * ?Rangemode:RangeMode * ?Range:Range * ?Fixedrange:'b * ?Tickmode:TickMode * ?nTicks:'c * ?Tick0:'d * ?dTick:'e * ?Tickvals:'f * ?Ticktext:'g * ?Ticks:TickOptions * ?Mirror:Mirror * ?Ticklen:'h * ?Tickwidth:'i * ?Tickcolor:'j * ?Showticklabels:'k * ?Tickfont:Font * ?Tickangle:'l * ?Tickprefix:'m * ?Showtickprefix:ShowTickOption * ?Ticksuffix:'q * ?Showticksuffix:ShowTickOption * ?Showexponent:ShowExponent * ?Exponentformat:ExponentFormat * ?Tickformat:'r * ?Hoverformat:'s * ?Showline:'t * ?Linecolor:'a1 * ?Linewidth:'a2 * ?Showgrid:'a3 * ?Gridcolor:'a4 * ?Gridwidth:'a5 * ?Zeroline:'a6 * ?Zerolinecolor:'a7 * ?Zerolinewidth:'a8 * ?Anchor:AxisAnchorId * ?Side:Side * ?Overlaying:AxisAnchorId * ?Domain:Range * ?Position:float * ?IsSubplotObj:'a9 * ?Tickvalssrc:'a10 * ?Ticktextsrc:'a11 * ?Showspikes:'a12 * ?Spikesides:'a13 * ?Spikethickness:'a14 * ?Spikecolor:'a15 * ?Showbackground:'a16 * ?Backgroundcolor:'a17 * ?Showaxeslabels:'a18 -> LinearAxis
  static member style : ?AxisType:AxisType * ?Title:'b * ?Titlefont:Font * ?Autorange:AutoRange * ?Rangemode:RangeMode * ?Range:Range * ?Fixedrange:'c * ?Tickmode:TickMode * ?nTicks:'d * ?Tick0:'e * ?dTick:'f * ?Tickvals:'g * ?Ticktext:'h * ?Ticks:TickOptions * ?Mirror:Mirror * ?Ticklen:'i * ?Tickwidth:'j * ?Tickcolor:'k * ?Showticklabels:'l * ?Tickfont:Font * ?Tickangle:'m * ?Tickprefix:'n * ?Showtickprefix:ShowTickOption * ?Ticksuffix:'o * ?Showticksuffix:ShowTickOption * ?Showexponent:ShowExponent * ?Exponentformat:ExponentFormat * ?Tickformat:'p * ?Hoverformat:'q * ?Showline:'r * ?Linecolor:'s * ?Linewidth:'t * ?Showgrid:'a1 * ?Gridcolor:'a2 * ?Gridwidth:'a3 * ?Zeroline:'a4 * ?Zerolinecolor:'a5 * ?Zerolinewidth:'a6 * ?Anchor:AxisAnchorId * ?Side:Side * ?Overlaying:AxisAnchorId * ?Domain:Range * ?Position:float * ?IsSubplotObj:'a7 * ?Tickvalssrc:'a8 * ?Ticktextsrc:'a9 * ?Showspikes:'a10 * ?Spikesides:'a11 * ?Spikethickness:'a12 * ?Spikecolor:'a13 * ?Showbackground:'a14 * ?Backgroundcolor:'a15 * ?Showaxeslabels:'a16 -> (LinearAxis -> LinearAxis)

--------------------
new : unit -> Axis.LinearAxis
static member Axis.LinearAxis.init : ?AxisType:StyleParam.AxisType * ?Title:'a * ?Titlefont:Font * ?Autorange:StyleParam.AutoRange * ?Rangemode:StyleParam.RangeMode * ?Range:StyleParam.Range * ?Fixedrange:'b * ?Tickmode:StyleParam.TickMode * ?nTicks:'c * ?Tick0:'d * ?dTick:'e * ?Tickvals:'f * ?Ticktext:'g * ?Ticks:StyleParam.TickOptions * ?Mirror:StyleParam.Mirror * ?Ticklen:'h * ?Tickwidth:'i * ?Tickcolor:'j * ?Showticklabels:'k * ?Tickfont:Font * ?Tickangle:'l * ?Tickprefix:'m * ?Showtickprefix:StyleParam.ShowTickOption * ?Ticksuffix:'q * ?Showticksuffix:StyleParam.ShowTickOption * ?Showexponent:StyleParam.ShowExponent * ?Exponentformat:StyleParam.ExponentFormat * ?Tickformat:'r * ?Hoverformat:'s * ?Showline:'t * ?Linecolor:'a1 * ?Linewidth:'a2 * ?Showgrid:'a3 * ?Gridcolor:'a4 * ?Gridwidth:'a5 * ?Zeroline:'a6 * ?Zerolinecolor:'a7 * ?Zerolinewidth:'a8 * ?Anchor:StyleParam.AxisAnchorId * ?Side:StyleParam.Side * ?Overlaying:StyleParam.AxisAnchorId * ?Domain:StyleParam.Range * ?Position:float * ?IsSubplotObj:'a9 * ?Tickvalssrc:'a10 * ?Ticktextsrc:'a11 * ?Showspikes:'a12 * ?Spikesides:'a13 * ?Spikethickness:'a14 * ?Spikecolor:'a15 * ?Showbackground:'a16 * ?Backgroundcolor:'a17 * ?Showaxeslabels:'a18 -> Axis.LinearAxis
module StyleParam

from FSharp.Plotly
type Mirror =
  | True
  | Ticks
  | False
  | All
  | AllTicks
    static member convert : (Mirror -> obj)
    static member toString : (Mirror -> string)
union case StyleParam.Mirror.All: StyleParam.Mirror
type TickMode =
  | Auto
  | Linear
  | Array
    static member convert : (TickMode -> obj)
    static member toString : (TickMode -> string)
union case StyleParam.TickMode.Auto: StyleParam.TickMode
type TickOptions =
  | Outside
  | Inside
  | Empty
    static member convert : (TickOptions -> obj)
    static member toString : (TickOptions -> string)
union case StyleParam.TickOptions.Inside: StyleParam.TickOptions
Multiple items
type Font =
  inherit DynamicObj
  new : unit -> Font
  static member init : ?Family:FontFamily * ?Size:'b * ?Color:'c * ?Familysrc:'d * ?Sizesrc:'e * ?Colorsrc:'f -> Font
  static member style : ?Family:FontFamily * ?Size:'a0 * ?Color:'a1 * ?Familysrc:'a2 * ?Sizesrc:'a3 * ?Colorsrc:'a4 -> (Font -> Font)

--------------------
new : unit -> Font
static member Font.init : ?Family:StyleParam.FontFamily * ?Size:'b * ?Color:'c * ?Familysrc:'d * ?Sizesrc:'e * ?Colorsrc:'f -> Font
type FontFamily =
  | Arial
  | Balto
  | Courier_New
  | Droid_Sans
  | Droid_Serif
  | Droid_Sans_Mono
  | Gravitas_One
  | Old_Standard_TT
  | Open_Sans
  | Overpass
  ...
    static member convert : (FontFamily -> obj)
    static member toString : (FontFamily -> string)
union case StyleParam.FontFamily.Arial: StyleParam.FontFamily
val yAxis : title:'a -> Axis.LinearAxis
val chartCellCounter : GenericChart.GenericChart
type Chart =
  static member Area : xy:seq<#IConvertible * #IConvertible> * ?Name:string * ?ShowMarkers:bool * ?Showlegend:bool * ?MarkerSymbol:Symbol * ?Color:'a2 * ?Opacity:float * ?Labels:seq<#IConvertible> * ?TextPosition:TextPosition * ?TextFont:Font * ?Dash:DrawingStyle * ?Width:'a4 -> GenericChart
  static member Area : x:seq<#IConvertible> * y:seq<#IConvertible> * ?Name:string * ?ShowMarkers:bool * ?Showlegend:bool * ?MarkerSymbol:Symbol * ?Color:'a2 * ?Opacity:float * ?Labels:seq<#IConvertible> * ?TextPosition:TextPosition * ?TextFont:Font * ?Dash:DrawingStyle * ?Width:'a4 -> GenericChart
  static member Bar : keysvalues:seq<#IConvertible * #IConvertible> * ?Name:string * ?Showlegend:bool * ?Color:'a2 * ?Opacity:float * ?Labels:seq<#IConvertible> * ?TextPosition:TextPosition * ?TextFont:Font * ?Marker:Marker -> GenericChart
  static member Bar : keys:seq<#IConvertible> * values:seq<#IConvertible> * ?Name:string * ?Showlegend:bool * ?Color:'a2 * ?Opacity:float * ?Labels:seq<#IConvertible> * ?TextPosition:TextPosition * ?TextFont:Font * ?Marker:Marker -> GenericChart
  static member BoxPlot : xy:seq<'a0 * 'a1> * ?Name:string * ?Showlegend:bool * ?Color:'a2 * ?Fillcolor:'a3 * ?Opacity:float * ?Whiskerwidth:'a4 * ?Boxpoints:Boxpoints * ?Boxmean:BoxMean * ?Jitter:'a5 * ?Pointpos:'a6 * ?Orientation:Orientation -> GenericChart
  static member BoxPlot : ?x:'a0 * ?y:'a1 * ?Name:string * ?Showlegend:bool * ?Color:'a2 * ?Fillcolor:'a3 * ?Opacity:float * ?Whiskerwidth:'a4 * ?Boxpoints:Boxpoints * ?Boxmean:BoxMean * ?Jitter:'a5 * ?Pointpos:'a6 * ?Orientation:Orientation -> GenericChart
  static member Bubble : xysizes:seq<#IConvertible * #IConvertible * #IConvertible> * ?Name:string * ?Showlegend:bool * ?MarkerSymbol:Symbol * ?Color:'a3 * ?Opacity:float * ?Labels:seq<#IConvertible> * ?TextPosition:TextPosition * ?TextFont:Font -> GenericChart
  static member Bubble : x:seq<#IConvertible> * y:seq<#IConvertible> * sizes:seq<#IConvertible> * ?Name:string * ?Showlegend:bool * ?MarkerSymbol:Symbol * ?Color:'a3 * ?Opacity:float * ?Labels:seq<#IConvertible> * ?TextPosition:TextPosition * ?TextFont:Font -> GenericChart
  static member ChoroplethMap : locations:seq<string> * z:seq<#IConvertible> * ?Text:seq<#IConvertible> * ?Locationmode:LocationFormat * ?Autocolorscale:bool * ?Colorscale:Colorscale * ?Colorbar:'a2 * ?Marker:Marker * ?Zmin:'a3 * ?Zmax:'a4 -> GenericChart
  static member Column : keysvalues:seq<#IConvertible * #IConvertible> * ?Name:string * ?Showlegend:bool * ?Color:'a2 * ?Opacity:float * ?Labels:seq<#IConvertible> * ?TextPosition:TextPosition * ?TextFont:Font * ?Marker:Marker -> GenericChart
  ...
static member Chart.Line : xy:seq<#System.IConvertible * #System.IConvertible> * ?Name:string * ?ShowMarkers:bool * ?Showlegend:bool * ?MarkerSymbol:StyleParam.Symbol * ?Color:'a2 * ?Opacity:float * ?Labels:seq<#System.IConvertible> * ?TextPosition:StyleParam.TextPosition * ?TextFont:Font * ?Dash:'a4 * ?Width:'a5 -> GenericChart.GenericChart
static member Chart.Line : x:seq<#System.IConvertible> * y:seq<#System.IConvertible> * ?Name:string * ?ShowMarkers:bool * ?Showlegend:bool * ?MarkerSymbol:StyleParam.Symbol * ?Color:'c * ?Opacity:float * ?Labels:seq<#System.IConvertible> * ?TextPosition:StyleParam.TextPosition * ?TextFont:Font * ?Dash:'e * ?Width:'f -> GenericChart.GenericChart
static member Chart.withYErrorStyle : ?Array:'a * ?Arrayminus:'b * ?Symmetric:'c * ?Color:'d * ?Thickness:'e * ?Width:'f -> (GenericChart.GenericChart -> GenericChart.GenericChart)
static member Chart.withTraceName : ?Name:string * ?Showlegend:bool * ?Legendgroup:string * ?Visible:StyleParam.Visible -> (GenericChart.GenericChart -> GenericChart.GenericChart)
val chartManual : GenericChart.GenericChart
val chartCoulterCounter : GenericChart.GenericChart
val combinedChart : GenericChart.GenericChart
static member Chart.Combine : gCharts:seq<GenericChart.GenericChart> -> GenericChart.GenericChart
static member Chart.withX_Axis : xAxis:Axis.LinearAxis * ?Id:int -> (GenericChart.GenericChart -> GenericChart.GenericChart)
static member Chart.withY_Axis : yAxis:Axis.LinearAxis * ?Id:int -> (GenericChart.GenericChart -> GenericChart.GenericChart)
static member Chart.withSize : width:float * heigth:float -> (GenericChart.GenericChart -> GenericChart.GenericChart)
val dimension : int
module Filter

from CounterFunctions
val squareCalculator : cameraPixelSize:float -> binning:float -> magnification:float -> cameraMount:float -> int
val wvRadius : float
val cellRadiusCalculator : cellDiameter:float -> cameraPixelSize:float -> binning:float -> magnification:float -> cameraMount:float -> float
val processFolders : folderPath:string -> height:int -> width:int -> radius:float -> multiplier:float -> (int * GenericChart.GenericChart) [] []
val folderPath : string
val height : int
val width : int
val radius : float
val multiplier : float
val subfolders : string []
type Directory =
  static member CreateDirectory : path:string -> DirectoryInfo
  static member Delete : path:string -> unit + 1 overload
  static member EnumerateDirectories : path:string -> IEnumerable<string> + 2 overloads
  static member EnumerateFileSystemEntries : path:string -> IEnumerable<string> + 2 overloads
  static member EnumerateFiles : path:string -> IEnumerable<string> + 2 overloads
  static member Exists : path:string -> bool
  static member GetCreationTime : path:string -> DateTime
  static member GetCreationTimeUtc : path:string -> DateTime
  static member GetCurrentDirectory : unit -> string
  static member GetDirectories : path:string -> string[] + 2 overloads
  ...
Multiple items
Directory.GetDirectories(path: string) : string []
Directory.GetDirectories(path: string, searchPattern: string) : string []
Directory.GetDirectories(path: string, searchPattern: string, searchOption: SearchOption) : string []

--------------------
Directory.GetDirectories(path: string) : string []
Directory.GetDirectories(path: string, searchPattern: string) : string []
Directory.GetDirectories(path: string, searchPattern: string, searchOption: SearchOption) : string []
val result : (int * GenericChart.GenericChart) [] []
module Array

from Microsoft.FSharp.Collections
val mapi : mapping:(int -> 'T -> 'U) -> array:'T [] -> 'U []
val i : int
val folder : string
val printfn : format:Printf.TextWriterFormat<'T> -> 'T
property System.Array.Length: int
module Pipeline

from CounterFunctions
val processImages : folderPath:string -> height:int -> width:int -> radius:float -> multiplier:float -> (int * GenericChart.GenericChart) []
val processAll : (int * GenericChart.GenericChart) [] []
Fork me on GitHub