MicroFlex Tutorial & Quick Start

MicroFlex Architecture

Introduction

Researchers in the natural sciences use microplates to carry out experiments or assays on inorganic chemicals, nucleic acids, proteins and live cells. Basic information concerning the life science can be found here. Additional information concerning microplate assays can be found here.

A microplate consists of a rectangular grid of wells. Rows are assigned a letter starting with A and working towards Z. Rows outside this range are identified by adding an additional letter to the row index (A -> ... -> Z -> AA -> AB). Columns are assigned integer values starting at zero working towards infinity. The row and column indices uniquely identify a single well (A1, A2 etc). A plate cannot contain duplicate wells or wells with rows or columns outside the valid range.

MicroFlex plate data is implemented as a set of wells and a set of subgroups. Wells house the well ID and a list of values. Well subsets are used to aggregate data for different experimental conditions or replicates. Descriptive statistics and mathematical operations between plate stacks, plates, well sets and wells are performed using static methods housed within the statistics and math packages respectively. Custom mathematical or statistical calculations can be added by extending the Operation and DescriptiveStatistics classes and overriding the calculate methods.

MicroFlex consists of five modules:
Package
Description
MicroFlex.Microplate
Contains well, well set, well group, plate and stack objects
MicroFlex.Operations
Performs mathematical operations on wells, well sets, plates and stacks
MicroFlex.Statistics
Performs statistical operations on wells, well sets, plates and stacks
MicroFlex.IO
JSON & XML input and output in condensed easy to read format for wells, well groups, well sets, plates and stacks.
MicroFlex.Utilities
Validation and random construction of well, well group, well set, plate and stacks. Hash set and typed hash set helper classes.

Quick Reference Diagram

Class
Fields
Description
Well
Data Array
Row Index
Column Index
The well is the fundamental unit of a microplate. It is defined by a row and column index and holds experimental results for a given experiment.
Well Group
Well Index Hash Set
Label
Well groups contain a list of well indices used for grouping experimental plate data.
WellSet
Well Hash Set
Label
A well set contains a collection of plate wells without enforcing maximum column or row indices.
Plate
Well Hash Set
Well Group Hash Set
Row Number
Column Number
Plate Type
Label
Plates consist of wells arrayed in rows and columns. Plate well groups partition the plate data into subsets for data analysis.
Stack
Plate Hash Set
Row Number
Column Number
Plate Type
Label
A collection of plate objects.

MicroFlex Usage

Importing MicroFlex

var MicroFlex = require('microflex');
var Microplate = MicroFlex.Microplate;
var Well = Microplate.Well;
var WellGroup = Microplate.WellGroup;
var WellSet = Microplate.WellSet;
var Plate = Microplate.Plate;
var Stack = Microplate.Stack;
...
var MicroFlex = require('microflex');
var Operators = MicroFlex.Operators;
var Addition = Operators.Addition;
var LeftShift = Operators.LeftShift;
...
var MicroFlex = require('microflex');
var Statistics = MicroFlex.Statistics;
var Mean = Statistics.Mean;
var Kurtosis = Statistics.Kurtosis;
...
var MicroFlex = require('microflex');
var IO = MicroFlex.IO;
var MicroJSON = IO.MicroJSON;
var MicroXML = IO.MicroXML;
...
var MicroFlex = require('microflex');
var Utilities = MicroFlex.Utilities;
var WellValidation = Utilities.WellValidation;
var TypedHashSet = Utilities.TypedHashSet;
...

Instantiating MicroFlex Objects

The table below contains only a subset of possible constructor arguments. For examples of all constructor function options see the appropriate documentation for the microplate object.

Object
Example
Input
Well
var well1 = new Well('A1', [1,2,3,4]);
var well2 = new Well(1, 2, [5,6,7,8]);
Index, Data
Row, Column, Data
WellGroup
var group1 = new WellGroup("Example Group");
var group2 = new WellGroup(['A1, 'B2, 'C5'], "Example Group");
Label
Label, Well Indices
WellSet
var array = [well1, well2];
var set1 = new WellSet("Example WellSet");
var set2 = new WellSet(array, "Example WellSet");

Label
Label, Well Array
Plate
var plate1 = new Plate(Plate.PLATE_96WELL, set1, "Example Plate");
var plate2 = new Plate(8, 12, set1, "Example Plate");
Plate Type, WellSet, Label
Row Number, Column Number, WellSet, Label
Stack
var array = [plate1, plate2];
var stack1 = new Stack(Stack.PLATE_96WELL, "Example Stack");
var stack2 = new Stack(8, 12);
var stack3 = new Stack(array, "Example Stack");

Plate Type, Label
Row Number, Column Number, Label
Plate Array, Label

Using Well Groups to Aggregate Data

The code below creates the plate seen in the diagram above. Nine wells are initialized and passed to the plate constructor. Well groups for the control and experimental conditions are added to the plate. The data for each group can then be retrieved by group, group name or index.

// Instantiate control wells

var control_1 = new Well('B2', [12, 21, 35, 42, 58]);
var control_2 = new Well('B3', [63, 17, 87, 99, 10]);
var control_3 = new Well('B4', [11, 12, 53, 24, 15]);

// Instantiate experimental group one

var condition1_1 = new Well('C2', [31, 23, 32, 74, 45]);
var condition1_2 = new Well('C3', [86, 71, 32, 44, 16]);
var condition1_3 = new Well('C4', [11, 17, 43, 24, 55]);

// Instantiate experimental group two

var condition2_1 = new Well('D2', [16, 87, 66, 39, 53]);
var condition2_2 = new Well('D3', [25, 75, 28, 69, 19]);
var condition2_3 = new Well('D4', [19, 13, 28, 93, 22]);

var wells = [ control_1,

control_2,
control_3,
condition1_1,
condition1_2,
condition1_3,
condition2_1,
condition2_2,
condition2_3 ];

// Instantiate the plate and add the wells

var plate = new Plate(8, 12, "Example Plate");
plate.add(wells);

// Create and add groups for control and experimental conditions

var controlGroup = new WellGroup(['B2', 'B3', 'B4'], "Control");
var conditionGroup1 = new WellGroup(['C2', 'C3', 'C4'], "Condition 1");
var conditionGroup2 = new WellGroup(['D2', 'D3', 'D4'], "Condition 2");

var array = [controlGroup, conditionGroup1, conditionGroup2];
plate.addGroups(array);

// Wells can then be accessed by group, group name or well index.

var allGroups1 = plate.allGroupsToArray();
var allGroups2 = plate.groupNamesToArray(['Control', 'Condition 1', 'Condition 2']);
var control = plate.get(['B2', 'B3', 'B4']);
var condition1 = plate.get(['C2', 'C3', 'C4']);
var condition2 = plate.get(['D2', 'D3', 'D4']);

// The allGroups1 and allGroups2 variables now contain the following:

[ WellSet {
     name: 'Control',
     wells: TypedHashSet {
          values: {
              B2: Well { base: 26, row: 1, column: 2, data: [ 12, 21, 35, 42, 58 ] },
              B3: Well { base: 26, row: 1, column: 3, data: [ 63, 17, 87, 99, 10 ] },
              B4: Well { base: 26, row: 1, column: 4, data: [ 11, 12, 53, 24, 15 ] }
          },
          type: 'Well'
      }
  },
  WellSet {
      name: 'Condition 1',
      wells: TypedHashSet {
           values: {
               C2: Well { base: 26, row: 2, column: 2, data: [31, 23, 32, 74, 45] },
               C3: Well { base: 26, row: 2, column: 3, data: [86, 71, 32, 44, 16] },
               C4: Well { base: 26, row: 2, column: 4, data: [11, 17, 43, 24, 55] }
           },
           type: 'Well' }
      }
  },
  WellSet {
      name: 'Condition 2',
      wells: TypedHashSet {
           values: {
               D2: Well { base: 26, row: 3, column: 2, data: [16, 87, 66, 39, 53] },
               D3: Well { base: 26, row: 3, column: 3, data: [25, 75, 28, 69, 19] },
               D4: Well { base: 26, row: 3, column: 4, data: [19, 13, 28, 93, 22] } },
           type: 'Well'
      }
  } ]
              

MicroFlex Operations

Standard vs Strict

Mathematical operators extend the unary, binary and shift operation classes. Standard functions treat all values missing from either data set as zeroes and combine all stacks, plates, sets and wells from both input objects. Strict functions omit all values, stacks, plates, wells and sets missing from one of the input objects:

Operation
Output
Standard
Treats missing values as zeroes
Combines stacks, plates, sets, wells and values from both input objects
Strict
Omits all missing values
Combines stacks, plates, sets, wells and values present in both input objects only

Binary Operations

The functions within the MicroFlex library are designed to be flexible and classes extending the math operation binary object support operations using two stacks, plates, sets and well objects as input. In addition, they support operations using a single stack, plate, set or well object and an array or constant. Binary operations can be limited to a subset of data by passing indices into the well data array.

Input 1
Input 2
Beginning
Index
Ending
Index
Operation
Well Well +/- +/- Performs the operation using the values in the two wells
Well Array +/- +/- Performs the operation using the values in the array and the values in the well
Well Constant +/- +/- Performs the operation using the constant value and each value in the well
Set Set +/- +/- Performs the operation on the values in each matching pair of wells in the two sets
Set Array +/- +/- Performs the operation using the values in the array and the values in each well of the set
Set Constant +/- +/- Performs the operation using the constant and each value in each well of the set
Plate Plate +/- +/- Performs the operation on the values in each matching pair of wells in the two plates
Plate Array +/- +/- Performs the operation using the values in the array and the values in each well of the plate
Plate Constant +/- +/- Performs the operation using the constant and each value in each well of the plate
Stack Stack +/- +/- Performs the operation on the values in each matching pair of wells in each matching plate in the stack
Stack Array +/- +/- Performs the operation using the values in the array and the values in each well of each plate in the stack
Stack Constant +/- +/- Performs the operation using the constant and each value in each well of each plate in the stack
Well Binary Operation Example:

var addition = new Addition();
var well1 = new Well('A1', [1,2,3,4]);
var well2 = new Well('B2', [5,6,7,8]);

addition.wells(well1, well2)   =>  
Well {
                               base: 26,
                               row: 0,
                               column: 1,
                               data: [ 6, 8, 10, 12 ]
                            }


Set Binary Operation Example:

var addition = new Addition();
var set1 = new WellSet(wells1, "Example Set 1");
var set2 = new WellSet(wells2, "Example Set 2");

addition.sets(set1, set2);   =>  
WellSet {
                            name: 'Result - Example Set 1, Example Set 2',
                            wells: TypedHashSet {
                               values: {
                                  A1: Well { base: 26, row: 0, column: 1, data: [ 10, 12, 14, 16 ] },
                                  B2: Well { base: 26, row: 1, column: 2, data: [ 18, 20, 22, 24 ] }
                               },
                               type: 'Well'
                            }
                         }


Plate Binary Operation Example:

var addition = new Addition();
var plate1 = new Plate(8, 12, set1, "Example Plate 1");
var plate2 = new Plate(8, 12, set2, "Example Plate 2");

addition.plates(plate1, plate2);   =>  
WellSet {
                                 name: 'Result - Example Plate 1, Example Plate 2',
                                 wells: TypedHashSet {
                                    values: {
                                       A1: Well { base: 26, row: 0, column: 1, data: [ 10, 12, 14, 16 ] },
                                       B2: Well { base: 26, row: 1, column: 2, data: [ 18, 20, 22, 24 ] }
                                    },
                                    type: 'Well'
                                 }
                              }


Stack Binary Operation Example:

var addition = new Addition();
var stack1 = new Stack(plates1, "Example Stack 1");
var stack2 = new Stack(plates2, "Example Stack 2");

addition.stacks(stack1, stack2);   =>  
[ WellSet {
                                    name: 'Result - Example Plate 1',
                                    wells: TypedHashSet {
                                       values: {
                                          A1: Well { base: 26, row: 0, column: 1, data: [ 10, 12, 14, 16 ] },
                                          B2: Well { base: 26, row: 1, column: 2, data: [ 18, 20, 22, 24 ] }
                                       },
                                       type: 'Well'
                                    }
                                 },
                                 WellSet {
                                    name: 'Result - Example Plate 2',
                                    wells: TypedHashSet {
                                       values: {
                                          A1: Well { base: 26, row: 0, column: 1, data: [ 14, 11, 55, 26 ] },
                                          B2: Well { base: 26, row: 1, column: 2, data: [ 44, 91, 42, 24 ] }
                                       },
                                       type: 'Well'
                                    }
                                 },
                               ]


Unary Operations

Unary operations take a single well, well set, plate or stack as input and perform a mathematical operation on each well value or a subset of well values using indices into the data array.

Well Unary Operation Example:

var increment = new Increment();
var well = new Well('A1', [1,2,3,4]);

increment.well(well)   =>  
Well {
                         base: 26,
                         row: 0,
                         column: 1,
                         data: [ 2, 3, 4, 5 ]
                      }


Set Unary Operation Example:

var increment = new Increment();
var set = new WellSet(wells, "Example Set");

increment.set(set);   =>  
WellSet {
                       name: 'Result - Example Set',
                       wells: TypedHashSet {
                          values: {
                             A1: Well { base: 26, row: 0, column: 1, data: [ 2, 3, 4, 5 ] },
                             B2: Well { base: 26, row: 1, column: 2, data: [ 6, 7, 8, 9 ] }
                          },
                          type: 'Well'
                       }
                    }


Plate Unary Operation Example:

var increment = new Increment();
var plate = new Plate(8, 12, set, "Example Plate");

increment.plate(plate);   =>  
WellSet {
                           name: 'Result - Example Plate',
                           wells: TypedHashSet {
                             values: {
                                A1: Well { base: 26, row: 0, column: 1, data: [ 2, 3, 4, 5 ] },
                                B2: Well { base: 26, row: 1, column: 2, data: [ 6, 7, 8, 9 ] }
                             },
                             type: 'Well'
                          }
                       }


Stack Unary Operation Example:

var increment = new Increment();
var stack = new Stack(plates, "Example Stack");

increment.stack(stack);   =>  
[ WellSet {
                             name: 'Result - Example Plate 1',
                             wells: TypedHashSet {
                                values: {
                                   A1: Well { base: 26, row: 0, column: 1, data: [ 2, 3, 4, 5 ] },
                                   B2: Well { base: 26, row: 1, column: 2, data: [ 6, 7, 8, 9 ] }
                                },
                                type: 'Well'
                             }
                          },
                          WellSet {
                             name: 'Result - Example Plate 2',
                             wells: TypedHashSet {
                                values: {
                                   A1: Well { base: 26, row: 0, column: 1, data: [ 2, 3, 4, 5 ] },
                                   B2: Well { base: 26, row: 1, column: 2, data: [ 6, 7, 8, 9 ] }
                                },
                                type: 'Well'
                             }
                          },
                       ]


Shift Operations

Shift operations take a single well, well set, plate or stack and the number of bits to shift as input and perform a mathematical operation on each well value or a subset of well values using indices into the data array.

Well Shift Operation Example:

var leftShift = new LeftShift();
var well = new Well('A1', [1,2,3,4]);
var bits = 2;

leftShift.well(well, bits)   =>  
Well {
                            base: 26,
                            row: 0,
                            column: 1,
                            data: [ 4, 8, 12, 16 ]
                         }


Set Shift Operation Example:

var leftShift = new LeftShift();
var set = new WellSet(wells, "Example Set");
var bits = 2;

leftShift.set(set, bits);   =>  
WellSet {
                          name: 'Result - Example Set',
                          wells: TypedHashSet {
                             values: {
                                A1: Well { base: 26, row: 0, column: 1, data: [ 4, 8, 12, 16 ] },
                                B2: Well { base: 26, row: 1, column: 2, data: [ 18, 20, 22, 24 ] }
                             },
                             type: 'Well'
                          }
                       }


Plate Shift Operation Example:

var leftShift = new LeftShift();
var plate = new Plate(8, 12, set, "Example Plate");
var bits = 2;

leftShift.plate(plate, bits);   =>  
WellSet {
                              name: 'Result - Example Plate',
                              wells: TypedHashSet {
                                 values: {
                                    A1: Well { base: 26, row: 0, column: 1, data: [ 4, 8, 12, 16 ] },
                                    B2: Well { base: 26, row: 1, column: 2, data: [ 18, 20, 22, 24 ] }
                                 },
                                 type: 'Well'
                              }
                           }


Stack Shift Operation Example:

var leftShift = new LeftShift();
var stack = new Stack(plates, "Example Stack");
var bits = 2;

leftShift.stack(stack, bits);   =>  
[ WellSet {
                                name: 'Result - Example Plate 1',
                                wells: TypedHashSet {
                                   values: {
                                      A1: Well { base: 26, row: 0, column: 1, data: [ 4, 8, 12, 16 ] },
                                      B2: Well { base: 26, row: 1, column: 2, data: [ 18, 20, 22, 24 ] }
                                   },
                                   type: 'Well'
                                }
                             },
                             WellSet {
                                name: 'Result - Example Plate 2',
                                wells: TypedHashSet {
                                   values: {
                                      A1: Well { base: 26, row: 0, column: 1, data: [ 41, 82, 12, 16 ] },
                                      B2: Well { base: 26, row: 1, column: 2, data: [ 44, 91, 42, 24 ] }
                                   },
                                   type: 'Well'
                                }
                             },
                           ]


Creating Custom Mathematical Operations

Creating MicroFlex mathematical operations is simple. Extend the appropriate operation class and override the calculation methods with the operation of choice. This example returns the inverse of each data set value:


   // Create the constructor and extend the unary operation class

   function Invert() {
      UnaryOperation.call(this);
   }

   Invert.prototype = new UnaryOperation();
   Invert.prototype.constructor = Invert;

   // For unary operations overwrite the calculate and calculate range functions

   Invert.prototype.calculate = function(array) {

      var result = [];

      for(var i = 0; i < array.length; i++) {
         result.push(1 / array[i]);
      }

      return result;

  }

  Invert.prototype.calculateRange = function(array, begin, end) {

     var result = [];

     for(var i = begin; i < end && i < result.length; i++) {
        result.push(1 / array[i]);
     }

     return result;
  }

MicroFlex Statistics

Standard vs Aggregated

Statistical operations can be performed using standard or aggregated functions. Standard functions calculate the desired statistic for each well in the stack, plate or set. Aggregated functions aggregate the values from all wells in the stack, plate or set and perform the statistical operation on the aggregated values. Both standard and aggregated functions can be performed on a subset of data by passing indices into the well data set as arguments.

The methods within the MicroFlex library are meant to be flexible and the descriptive statistic object supports operations using a single stack, plate, set or well as well as arrays of stacks, plates, sets or wells. In case of the latter a result for each stack, plate, set or well is returned.

Operation
Beginning
Index
Ending
Index
Input/Output
Standard
+/-
+/-
Accepts a single well, set, plate or stack as input
Calculates the statistic for each well in a well, set, plate or stack
Aggregated
+/-
+/-
Accepts a single well/set/plate/stack or an array of wells/sets/plates/stacks as input
Aggregates the data from all the wells in a well/set/plate/stack and calculates the statistic using the aggregated data
Standard Operation Examples:

var well1 = new Well('A1', [1, 2, 3, 4, 5]);
var well2 = new Well('B2', [6, 7, 8, 9, 10]);
var array = [well1, well2];
Mean.wells(array)  => 
[ { well: 'A1', result: 3 }, { well: 'B2', result: 8 } ]


var set = new WellSet(wells, "Example Set");
Mean.sets(set)  => 
[ { set: 'Example Set', result: [ { well: 'A1', result: 3 }, { well: 'B2', result: 8 } ] } ]


var plate = new Plate(rows, columns, wells, "Example Plate");
Mean.plates(plate)  => 
[ { plate: 'Example Plate', result: [ { well: 'A1', result: 3 }, { well: 'B2', result: 8 } ] } ]


var stack = new Stack(rows, columns, plates, "Example Stack");
Mean.stacks(stack)  => 
[ { plate: 'Example Plate 1', result: [ { well: 'A1', result: 33 }, { well: 'B2', result: 18 } ] },
                      { plate: 'Example Plate 2', result: [ { well: 'C3', result: 29 }, { well: 'D4', result: 12 } ] } ]


Aggregated Operation Examples:

var well1 = new Well('A1', [1, 2, 3, 4, 5]);
var well2 = new Well('B2', [6, 7, 8, 9, 10]);
var array = [well1, well2];
Mean.wellsAggregated(array)  => 
{ wells: [ 'A1', 'B2' ], result: 5.5 }


var set1 = new WellSet(wells1, "Example Set 1");
var set2 = new WellSet(wells2, "Example Set 2");
var array = [set1, set2];
Mean.setsAggregated(array)  => 
[ { set: 'Example Set 1', result: 5.5 }, { set: 'Example Set 2', result: 15.5 } ]


var plate1 = new Plate(8, 12, set1, "Example Plate 1");
var plate2 = new Plate(8, 12, set2, "Example Plate 2");
var array = [plate1, plate2];
Mean.platesAggregated(array)  => 
[ { plate: 'Example Plate 1', result: 5.5 }, { plate: 'Example Plate 2', result: 15.5 } ]


var stack = new Stack(rows, columns, plates, "Example Stack");
Mean.stacksAggregated(stack)  => 
[ { stack: 'Example Stack', result: 10.5 } ]


Weighted Statistics

Weighted statistics can apply an array of weights to the data set prior to the statistical calculation.

From wikipedia: a weight function is a mathematical device used when performing a sum, integral, or average to give some elements more "weight" or influence on the result than other elements in the same set. In statistics a weighted function is often used to correct bias. The weighted statistic class implements a weighted function by accepting an array of values as weights. The values in each well of the stack, plate, set or well are multiplied by the values within the weights array prior to the statistical calculation.

Standard Weighted Operation Examples:

var well1 = new Well('A1', [1, 2, 3, 4, 5]);
var well2 = new Well('B2', [6, 7, 8, 9, 10]);
var weights = [0.2, 0.4, 0.6, 0.8, 1.0];
var array = [well1, well2];
Mean.wells(array, weights)  => 
[ { well: 'A1', result: 2.2 }, { well: 'B2', result: 5.2 } ]


var set = new WellSet(wells, "Example Set");
var weights = [0.2, 0.4, 0.6, 0.8, 1.0];
Mean.sets(set, weights)  => 
[ { set: 'Example Set', result: [ { well: 'A1', result: 2.2 }, { well: 'B2', result: 5.2 } ] } ]


var plate = new Plate(rows, columns, wells, "Example Plate");
var weights = [0.2, 0.4, 0.6, 0.8, 1.0];
Mean.plates(plate, weights)  => 
[ { plate: 'Example Plate', result: [ { well: 'A1', result: 2.2 }, { well: 'B2', result: 5.2 } ] } ]


var stack = new Stack(rows, columns, plates, "Example Stack");
var weights = [0.2, 0.4, 0.6, 0.8, 1.0];
Mean.stacks(stack, weights)  => 
[ { plate: 'Example Plate 1', result: [ { well: 'A1', result: 2.2 }, { well: 'B2', result: 5.2 } ] },
                              { plate: 'Example Plate 2', result: [ { well: 'C3', result: 6.9 }, { well: 'D4', result: 7.3 } ] } ]



Aggregated Weighted Operation Examples:

var well1 = new Well('A1', [1, 2, 3, 4, 5]);
var well2 = new Well('B2', [6, 7, 8, 9, 10]);
var weights = [0.2, 0.4, 0.6, 0.8, 1.0];
var array = [well1, well2];
Mean.wellsAggregated(array, weights)  => 
{ wells: [ 'A1', 'B2' ], result: 3.7 }


var set1 = new WellSet(wells1, "Example Set 1");
var set2 = new WellSet(wells2, "Example Set 2");
var weights = [0.2, 0.4, 0.6, 0.8, 1.0];
var array = [set1, set2];
Mean.setsAggregated(array, weights)  => 
[ { set: 'Example Set 1', result: 3.7 }, { set: 'Example Set 2', result: 9.65 } ]


var plate1 = new Plate(8, 12, set1, "Example Plate 1");
var plate2 = new Plate(8, 12, set2, "Example Plate 2");
var weights = [0.2, 0.4, 0.6, 0.8, 1.0];
var array = [plate1, plate2];
Mean.platesAggregated(array, weights)  => 
[ { plate: 'Example Plate 1', result: 3.7 }, { plate: 'Example Plate 2', result: 9.65 } ]


var stack = new Stack(rows, columns, plates, "Example Stack");
var weights = [0.2, 0.4, 0.6, 0.8, 1.0];
Mean.stacksAggregated(stack, weights)  => 
[ { stack: 'Example Stack', result: 10.5 } ]


Quantile Statistics

Quantile statistics accept an additional input parameter.

Standard Quantile Operation Examples:

var well1 = new Well('A1', [1, 2, 3, 4, 5]);
var well2 = new Well('B2', [6, 7, 8, 9, 10]);
var array = [well1, well2];
var p = 0.25;
Quantile.wells(array, p)  => 
[ { well: 'A1', result: 1.25 }, { well: 'B2', result: 5.25 } ]


var set = new WellSet(wells, "Example Set");
var p = 0.25;
Quantile.sets(set, p)  => 
[ { set: 'Example Set', result: [ { well: 'A1', result: 1.25 }, { well: 'B2', result: 5.25 } ] } ]


var plate = new Plate(rows, columns, wells, "Example Plate");
var p = 0.25;
Quantile.plates(plate, p)  => 
[ { plate: 'Example Plate', result: [ { well: 'A1', result: 1.25 }, { well: 'B2', result: 5.25 } ] } ]


var stack = new Stack(rows, columns, plates, "Example Stack");
var p = 0.25;
Quantile.stacks(stack, p)  => 
[ { plate: 'Example Plate 1', result: [ { well: 'A1', result: 33 }, { well: 'B2', result: 18 } ] },
                           { plate: 'Example Plate 2', result: [ { well: 'C3', result: 29 }, { well: 'D4', result: 12 } ] } ]


Aggregated Quantile Operation Examples:

var well1 = new Well('A1', [1, 2, 3, 4, 5]);
var well2 = new Well('B2', [6, 7, 8, 9, 10]);
var array = [well1, well2];
var p = 0.25;
Quantile.wellsAggregated(array, p)  => 
{ wells: [ 'A1', 'B2' ], result: 2.25 }


var set1 = new WellSet(wells1, "Example Set 1");
var set2 = new WellSet(wells2, "Example Set 2");
var array = [set1, set2];
var p = 0.25;
Quantile.setsAggregated(array, p)  => 
[ { set: 'Example Set 1', result: 5.5 }, { set: 'Example Set 2', result: 15.5 } ]


var plate1 = new Plate(8, 12, set1, "Example Plate 1");
var plate2 = new Plate(8, 12, set2, "Example Plate 2");
var array = [plate1, plate2];
var p = 0.25;
Quantile.platesAggregated(array, p)  => 
[ { plate: 'Example Plate 1', result: 5.5 }, { plate: 'Example Plate 2', result: 15.5 } ]


var stack = new Stack(rows, columns, plates, "Example Stack");
var p = 0.25;
Quantile.stacksAggregated(stack, p)  => 
[ { stack: 'Example Stack', result: 10.5 } ]

Creating Custom Statistical Operations

Creating MicroFlex statistical operations is simple. Extend the appropriate statistics class and override the calculate method with the statistical operation of choice. This example returns the inverse of the mean:


   // Create the constructor and extend the descriptive statistic class

   function InverseMean() {
      DescriptiveStatisticWeighted.call(this);
   }

   InverseMean.prototype = new DescriptiveStatisticWeighted();
   InverseMean.prototype.constructor = InverseMean;

   // Overwrite the calculate method

   InverseMean.prototype.calculate = function(data) {

      var sum = 0;

      for(var value of data) {
         sum += value;
      }

      return 1 / (sum / data.length);

   }

MicroFlex IO

JSON IO

The MicroJSON class formats stack, plate, well set and well objects into a condensed and easy to read JSON format. The MicroJSON.stringify and MicroJSON.parse functions mirror JSON.stringify and JSON.parse, accepting replacer/space and reviver arguments. Wells, well groups and plates are housed within typed hash set objects. This class converts the hash sets to simple objects which are easier to read and parse.

Comparison of JSON Output:
Object
Console.log
JSON.stringify
MicroJSON.stringify
Well
Well {
   base: 26,
   row: 0,
   column: 1,
   data: [ 1, 2, 3, 4 ]
}
{
   "base": 26,
   "row": 0,
   "column": 1,
   "data": [ 1, 2, 3, 4]
}
{
   "type": "Well",
   "index": "A1",
   "row": 0,
   "column": 1,
   "data": [ 1, 2, 3, 4]
}
Well Group
WellGroup {
   groupName: 'Example Group',
   wells: TypedHashSet {
      values: {
         A1: 'A1',
         B2: 'B2',
         C5: 'C5',
         D9: 'D9'
      },
      type: 'String'
   }
}
{
   "groupName": "Example Group",
   "wells": {
      "values": {
         "A1": "A1",
         "B2": "B2",
         "C5": "C5",
         "D9": "D9"
      },
      "type": "String"
   }
}
{
   "type": "WellGroup",
   "label": "Example Group",
   "wells": [ "A1", "B2", "C5", "D9" ]
}
Well Set
WellSet {
   name: 'Example Set',
   wells: TypedHashSet {
      values: {
         A1: Well {
            base: 26,
            row: 0,
            column: 1,
            data: [ 1, 2, 3, 4 ] },
         B2: Well {
            base: 26,
            row: 1,
            column: 2,
            data: [ 5, 6, 7, 8 ]
         }
      },
      type: 'Well'
   }
}
{
   "name": "Example Set",
   "wells": {
      "values": {
         "A1": {
            "base": 26,
            "row": 0,
            "column": 1,
            "data": [ 1, 2, 3, 4 ]
         },
         "B2": {
            "base": 26,
            "row": 1,
            "column": 2,
            "data": [ 5, 6, 7, 8 ]
         }
      },
      "type": "Well"
   }
}
{
   "type": "WellSet",
   "label": "Example Set",
   "wells": {
      "A1": {
         "row": 0,
         "column": 1,
         "data": [ 1, 2, 3, 4 ]
      },
      "B2": {
         "row": 1,
         "column": 2,
         "data": [ 5, 6, 7, 8 ]
      }
   }
}
Plate
Plate {
   plateType: 4,
   rows: 8,
   columns: 12,
   groups: TypedHashSet {
      values: {
         group: WellGroup {
            groupName: 'Example Group',
            wells: TypedHashSet {
               values: {
                  A1: 'A1',
                  B2: 'B2'
               },
               type: 'String'
            }
         }
      },
      type: 'WellGroup'
   },
   name: 'Example Plate',
   wells: TypedHashSet {
      values: {
         A1: Well {
            base: 26,
            row: 0,
            column: 1,
            data: [ 1, 2, 3, 4 ]
         },
         B2: Well {
            base: 26,
            row: 1,
            column: 2,
            data: [ 5, 6, 7, 8 ]
         },
         C5: Well {
            base: 26,
            row: 2,
            column: 5,
            data: [ 9, 10, 11, 12 ]
         }
      },
      type: 'Well'
   }
}
{
   "plateType": 4,
   "rows": 8,
   "columns": 12,
   "groups": {
      "values": {
         group: {
            "groupName": "Example Group",
            "wells": {
               "values": {
                  "A1": "A1",
                  "B2": "B2"
               },
               "type": "String"
            }
         }
      },
      "type": "WellGroup"
   },
   "name": "Example Plate",
   "wells": {
      "values": {
         "A1": {
            "base": 26,
            "row": 0,
            "column": 1,
            "data": [ 1, 2, 3, 4 ]
         },
         "B2": {
            "base": 26,
            "row": 1,
            "column": 2,
            "data": [ 5, 6, 7, 8 ]
         },
         "C5": {
            "base": 26,
            "row": 2,
            "column": 5,
            "data": [ 9, 10, 11, 12 ]
         }
      },
      "type": "Well"
   }
}
{
   "type": "Plate",
   "label": "Example Plate",
   "rows": 8,
   "columns": 12,
   "descriptor": "96-Well",
   "groups": {
      "Example Group": [ "A1", "B2" ]
   },
   "wells": {
      "A1": {
         "row": 0,
         "column": 1,
         "data": [ 1, 2, 3, 4 ]
      },
      "B2": {
         "row": 1,
         "column": 2,
         "data": [ 5, 6, 7, 8 ]
      },
      "C5": {
         "row": 2,
         "column": 5,
         "data": [ 9, 10, 11, 12 ]
      }
   }
}
Stack
Stack {
   plateType: 4,
   rows: 8,
   columns: 12,
   name: 'Test Stack',
   plates: TypedHashSet {
      values: {
	    Plate {
	       plateType: 4,
	       rows: 8,
	       columns: 12,
	       groups: TypedHashSet {
	          values: {
		     group: WellGroup {
		        groupName: 'Example Group',
		        wells: TypedHashSet {
		           values: {
		              A1: 'A1',
		              B2: 'B2'
		           },
		           type: 'String'
		        }
		     }
	          },
	          type: 'WellGroup'
	       },
	       name: 'Example Plate 1',
	       wells: TypedHashSet {
	          values: {
		     A1: Well {
		        base: 26,
		        row: 0,
		        column: 1,
		        data: [ 1, 2, 3, 4 ]
		     },
		     B2: Well {
		        base: 26,
		        row: 1,
		        column: 2,
		        data: [ 5, 6, 7, 8 ]
		     },
		     C5: Well {
		        base: 26,
		        row: 2,
		        column: 5,
		        data: [ 9, 10, 11, 12 ]
		     }
	          },
	          type: 'Well'
	       }
	    },
	    Plate {
	       plateType: 4,
	       rows: 8,
	       columns: 12,
	       groups: TypedHashSet {
	          values: {
		     group: WellGroup {
		        groupName: 'Example Group',
		        wells: TypedHashSet {
		           values: {
		              B2: 'B2',
		              C5: 'C5'
		           },
		           type: 'String'
		        }
		     }
	          },
	          type: 'WellGroup'
	       },
	       name: 'Example Plate 1',
	       wells: TypedHashSet {
	          values: {
		     A1: Well {
		        base: 26,
		        row: 0,
		        column: 1,
		        data: [ 13, 14, 15, 16 ]
		     },
		     B2: Well {
		        base: 26,
		        row: 1,
		        column: 2,
		        data: [ 17, 18, 19, 20 ]
		     },
		     C5: Well {
		        base: 26,
		        row: 2,
		        column: 5,
		        data: [ 21, 22, 23, 24 ]
		     }
	          },
	          type: 'Well'
	       }
	    }
      },
      type: 'Plate'
   }
}
{
   "plateType": 4,
   "rows": 8,
   "columns": 12,
   "name": "Test Stack",
   "plates": {
      "values": {
         "plateType": 4,
         "rows": 8,
         "columns": 12,
         "groups": {
            "values": {
               "group": {
                  "groupName": "Example Group",
                  "wells": {
                    "values": {
                        "A1": "A1",
                        "B2": "B2"
                     },
                     "type": "String"
                  }
               }
            },
            "type": "WellGroup"
         },
         "name": "Example Plate 1",
         "wells": {
            "values": {
               "A1": {
                  "base": 26,
                  "row": 0,
                  "column": 1,
                  "data": [ 1, 2, 3, 4 ]
               },
               "B2": {
                  "base": 26,
                  "row": 1,
                  "column": 2,
                  "data": [ 5, 6, 7, 8 ]
               }
            },
            "type": "Well"
         }
      },
      {
         "plateType": 4,
         "rows": 8,
         "columns": 12,
         "groups": {
            "values": {
               "group": {
                  "groupName": "Example Group",
                  "wells": {
                     "values": {
                        "A1": "A1",
                        "B2": "B2"
                     },
                     "type": "String"
                  }
               }
            },
            "type": "WellGroup"
         },
         "name": "Example Plate 1",
         "wells": {
            "values": {
               "A1": {
                  "base": 26,
                  "row": 0,
                  "column": 1,
                  "data": [ 9, 10, 11, 12 ]
               },
               "B2": {
                  "base": 26,
                  "row": 1,
                  "column": 2,
                  "data": [ 13, 14, 15, 16 ]
               }
            },
            "type": "Well"
         }
      },
      "type": "Plate"
   }
}
{
   "type": "Stack",
   "label": "Test Stack",
   "rows": 8,
   "columns": 12,
   "descriptor": "96-Well",
   "plates": {
      "Example Plate 1": {
         "label": "Example Plate 1",
         "groups": {
            "Example Group": [ "A1", "B2" ]
         },
         "wells": {
            "A1": {
               "row": 0,
               "column": 1,
               "data": [ 1, 2, 3, 4 ]
            },
            "B2": {
               "row": 1,
               "column": 2,
               "data": [ 5, 6, 7, 8 ]
            }
         }
      },
      "Example Plate 2": {
         "label": "Example Plate 2",
         "groups": {
            "Example Group": [ "C5", "D9" ]
         },
         "wells": {
            "C5": {
               "row": 2,
               "column": 5,
               "data": [ 9, 10, 11, 12 ]
            },
            "D9": {
               "row": 3,
               "column": 9,
               "data": [ 13, 14, 15, 16 ]
            }
         }
      }
   }
}

XML IO

The MicroXML class formats stack, plate, well set and well objects into a condensed and easy to read XML format. Wells, well groups and plates are housed within typed hash set objects. This class converts the hash sets to simple objects which are easier to read and parse.

Examples of XML Output:
Well
Well Group
Well Set
Plate
Stack
<WELL>
   <INDEX>A1</INDEX>
   <ROW>0</ROW>
   <COLUMN>1</COLUMN>
   <DATA>
      <VALUE>1</VALUE>
      <VALUE>2</VALUE>
      <VALUE>3</VALUE>
      <VALUE>4</VALUE>
   </DATA>
</WELL>
<WELLGROUP>
   <LABEL>Group</LABEL>
   <WELLS>
      <INDEX>A1</INDEX>
      <INDEX>B2</INDEX>
      <INDEX>C5</INDEX>
      <INDEX>D9</INDEX>
   </WELLS>
</WELLGROUP>
<WELLSET>
   <LABEL>Example Set</LABEL>
   <WELLS>
      <WELL>
         <INDEX>A1</INDEX>
         <ROW>0</ROW>
         <COLUMN>1</COLUMN>
         <DATA>
            <VALUE>1</VALUE>
            <VALUE>2</VALUE>
            <VALUE>3</VALUE>
            <VALUE>4</VALUE>
         </DATA>
      </WELL>
      <WELL>
         <INDEX>B2</INDEX>
         <ROW>1</ROW>
         <COLUMN>2</COLUMN>
         <DATA>
            <VALUE>5</VALUE>
            <VALUE>6</VALUE>
            <VALUE>7</VALUE>
            <VALUE>8</VALUE>
         </DATA>
      </WELL>
   </WELLS>
</WELLSET>
<PLATE>
   <LABEL>Example Plate</LABEL>
   <ROWS>8</ROWS>
   <COLUMNS>12</COLUMNS>
   <DESCRIPTOR>96-Well</DESCRIPTOR>
   <WELLGROUPS>
      <WELLGROUP>
         <LABEL>Group</LABEL>
         <WELLS>
            <INDEX>A1</INDEX>
            <INDEX>B2</INDEX>
         </WELLS>
      </WELLGROUP>
   </WELLGROUPS>
   <WELLS>
      <WELL>
         <INDEX>A1</INDEX>
         <ROW>0</ROW>
         <COLUMN>1</COLUMN>
         <DATA>
            <VALUE>1</VALUE>
            <VALUE>2</VALUE>
            <VALUE>3</VALUE>
            <VALUE>4</VALUE>
         </DATA>
      </WELL>
      <WELL>
         <INDEX>B2</INDEX>
         <ROW>1</ROW>
         <COLUMN>2</COLUMN>
         <DATA>
            <VALUE>5</VALUE>
            <VALUE>6</VALUE>
            <VALUE>7</VALUE>
            <VALUE>8</VALUE>
         </DATA>
      </WELL>
   </WELLS>
</PLATE>
<STACK>
   <LABEL>Test Stack</LABEL>
   <ROWS>8</ROWS>
   <COLUMNS>12</COLUMNS>
   <DESCRIPTOR>96-Well</DESCRIPTOR>
   <PLATES>
      <PLATE>
         <LABEL>Example Plate</LABEL>
         <ROWS>8</ROWS>
         <COLUMNS>12</COLUMNS>
         <DESCRIPTOR>96-Well</DESCRIPTOR>
         <WELLGROUPS>
            <WELLGROUP>
               <LABEL>Group</LABEL>
               <WELLS>
                  <INDEX>A1</INDEX>
                  <INDEX>B2</INDEX>
               </WELLS>
            </WELLGROUP>
         </WELLGROUPS>
         <WELLS>
            <WELL>
               <INDEX>A1</INDEX>
               <ROW>0</ROW>
               <COLUMN>1</COLUMN>
               <DATA>
                  <VALUE>1</VALUE>
                  <VALUE>2</VALUE>
                  <VALUE>3</VALUE>
                  <VALUE>4</VALUE>
               </DATA>
            </WELL>
            <WELL>
               <INDEX>B2</INDEX>
               <ROW>1</ROW>
               <COLUMN>2</COLUMN>
               <DATA>
                  <VALUE>5</VALUE>
                  <VALUE>6</VALUE>
                  <VALUE>7</VALUE>
                  <VALUE>8</VALUE>
               </DATA>
            </WELL>
         </WELLS>
      </PLATE>
      <PLATE>
         <LABEL>Example Plate 2</LABEL>
         <ROWS>8</ROWS>
         <COLUMNS>12</COLUMNS>
         <DESCRIPTOR>96-Well</DESCRIPTOR>
         <WELLGROUPS>
            <WELLGROUP>
               <LABEL>Group</LABEL>
               <WELLS>
                  <INDEX>C5</INDEX>
                  <INDEX>D9</INDEX>
               </WELLS>
            </WELLGROUP>
         </WELLGROUPS>
         <WELLS>
            <WELL>
               <INDEX>C5</INDEX>
               <ROW>2</ROW>
               <COLUMN>5</COLUMN>
               <DATA>
                  <VALUE>9</VALUE>
                  <VALUE>10</VALUE>
                  <VALUE>11</VALUE>
                  <VALUE>12</VALUE>
               </DATA>
            </WELL>
            <WELL>
               <INDEX>D9</INDEX>
               <ROW>3</ROW>
               <COLUMN>9</COLUMN>
               <DATA>
                  <VALUE>13</VALUE>
                  <VALUE>14</VALUE>
                  <VALUE>15</VALUE>
                  <VALUE>16</VALUE>
               </DATA>
            </WELL>
         </WELLS>
      </PLATE>
   </PLATES>
</STACK>