microplate
v2.7.1
Published
A module for parsing, reading & writing microtiter plate layouts in XSLX format.
Downloads
23
Maintainers
Readme
Microplate
The microplate
package is built for parsing microtiter plate information from Excel sheets, validating the contents of plate layouts, and saving plate layouts into Excel or CSV files.
Layout formats
A spreadsheet with one or more plate layouts will be formatted like this:
plate-1 1 2 3 ...
A item-1 item-2
B item-3
C
D
.
.
.
plate-2 1 2 3 ...
A
B
.
.
Alternatively, the spreadsheet can be in tabular format, which also allows for providing multiple columns of data:
PLATE POSITION NAME SCORE ...
plate-1 A1 item-1 5
plate-1 A2 item-2 15
plate-1 B3 item-3 10
. .
. .
. .
The plate layout parser will return a list of all layouts it detects.
Installation
You can install this package with NPM:
npm install microplate
Usage
The examples in this section contain ECMAScript 2016 (ES7) code. Use equivalent ECMAScript 5 code where necessary.
Sheets
A sheet object is created from either an Excel sheet, converted CSV file, or other 2D-array sources. They are the intermediary format between files and plate layouts. For different ways to load sheets from Excel files, read Working with Excel files.
Parsing and validating plate layouts
Plate layouts are processed in three stages:
- Reading a workbook and selecting a sheet
- Parsing the sheet into a layout
- Validating the layout's contents
Parsing step
In this example we are parsing a grid-based sheet we've built from an array:
import {Sheet, PlateLayout} from 'microplate';
let sheet = new Sheet([
['platename', 1, 2, 3],
['A', 'item1', 'item2', 'item3'],
['B', 'item1', 'item2', 'item3'],
[]
])
let layouts = PlateLayout.parse(sheet, {
default: 'name',
converters: {
name: 'string'
}
});
PlateLayout.parse()
always returns an array, because both grid and tabular formats support multiple plates. The converters
option is a dictionary for enforcing types on values. default
is only used with grid layouts.
Possible converters are:
name | description ------ | -------------------------------------------- number | numeric value string | string value number[] | array of numbers (comma separated list) string[] | array of strings (comma separated list) string(position) | well position
A list-based plate layout is processed like so:
let sheet = new Sheet([
['plate', 'position', 'name', 'score value'],
['platename', 'A1', 'item1', 5],
['platename', 'A2', 'item2', 9],
['platename', 'A3', 'item3', 11],
['platename', 'B1', 'item1', 7],
['platename', 'B2', 'item2', 9],
['platename', 'B3', 'item3', 15],
[]
])
let layouts = PlateLayout.parse(sheet, {
aliases: {
'score': ['score value']
}
required: ['name', 'score'],
converters: {
name: 'string',
score: 'number'
}
});
The validation here makes use of aliases
and required
option values, for header name aliases and required columns respectively. The full .parse()
function syntax:
PlateLayout.parse(sheet: Sheet, {
default?: string,
aliases?: {[name:string]: string[]},
converters?: {[name:string]: string},
required?: string[]
}): PlateLayout[]
Validation step
To validate each position in a plate layout, use PlateLayout.prototype.validate()
.
// dummy lookup function
function lookupItemByName(name) {
return Promise.resolve({name: name})
}
try {
let validatedLayout = layouts[0].validate({
name: lookupItemByName
});
} except(e) {
// errors grouped by well position.
}
The full .validate()
function syntax:
PlateLayout.prototype.validate(
validators: {[name:string]: (any) => Promise},
parallel: boolean): Promise<PlateLayout>
Parsing and validating tables
In addition to plate layouts, the package contains a Table
class. A table works just like a plate layout, with the difference that there are no well positions, but rows.
let sheet = new Sheet([
['id', 'name'],
[1, 'foo'],
[2, 'bar']
])
let table = Table.parse(sheet);
try { // validation
table = await table.validate({id: lookupByIdFunction});
} except (e) {
console.log('validation errors:', e)
}
for(let row of table) {
console.log(row);
}
If parallel
is false
, the validator functions in Table
functions will receive two arguments. The second argument will be an array with all previously processed rows. This is useful when importing a table where validation depends on values in previous rows.
You can create a Sheet
from a Table
like so:
let sheet = new Table([
{id: 2, name: 'bar'},
{id: 3, name: 'baz'}
]).toSheet();
Working with Excel files
The microplate
package has some features that aid with import and export to Excel using xlsx
. These examples here are for command-line use.
import fs from 'fs';
import {Workbook} from 'microplate';
let file = fs.readFileSync('./example.xlsx');
let workbook = Workbook.fromFile(file);
console.log(workbook.sheetNames()); // ['Sheet 1', 'Sheet 2']
let sheet1 = workbook.sheet('Sheet 1');
console.log(sheet1.name); // 'Sheet 1'
for(let sheet of workbook) { /* iterates through all sheets in a workbook */ }
let workbook2 = new Workbook({foo: new Sheet()}); // initialize a new Workbook.
You can also load a workbook from an <input/>
in the browser. First, add a file input to your page:
<input type="file" accept=".xlsx" />
Now you can load files like so:
let input = document.querySelector('input[type=file]');
input.addEventListener('change', function () {
if(this.files.length) {
let fileReader = new FileReader();
fileReader.onload = (e) => {
let workbook = Workbook.fromFile(e.target.result);
console.log(workbook);
});
fileReader.readAsBinaryString(this.files[0]);
}
});
To save a workbook in the browser, use e.g. filesaver.js
:
import {saveAs} from 'filesaver.js';
let wb = new Workbook({foo: new Sheet()}); // initialize a new Workbook.
saveAs(wb.toBlob(), 'foo.xlsx');
For more information, read Using files from web applications on MDN.