# Plate Transformer

# Ideal for rearranging plate-layouts according to liquid handling steps

Are you a scientist performing HTP assays in 96-well-plates (or other sizes), and trying to track the plate-layouts in a spreadsheet to record what is in each well?

Do you then pipette the plate contents into other plates, thus mixing up the spreadsheet records? If so, you might have trouble creating the _new_ plate-layout.

If so, PlateDataTransfer can help you out.

# Code

## Install

```bash
$ npm install plate-data-transfer
```

## Basic Usage

```js
import PlateDataTransfer from "plate-data-transfer";

let transformer = new PlateDataTransfer(
  sourceLayout,
  destinationLayout,
  transferInstructions,
  sourceInfo,
  destinationInfo
);

let newLayout = transformer.transformPlates();
```

## Example Input Parameters

```js
//source plate map (pipetting from)
//Plate and Well keys required
const sourceLayout = [
  { Plate: "plate1", Well: "A1", buffer: "Tris", additive: "DMSO" },
  { Plate: "plate1", Well: "A2", buffer: "Tris", additive: "Water" },
  { Plate: "plate1", Well: "A3", buffer: "Tris", additive: null },
];

//destination plate layout (pipetting into)
//Plate and Well keys required
const destinationLayout = [
  { Plate: "plate2", Well: "A1", optional: 1 },
  { Plate: "plate2", Well: "A2", optional: 3 },
  { Plate: "plate2", Well: "A3", optional: 5 },
];
// If the destination plate is initially empty, its array can contain just one entry [{Plate:"platename", Well:"A1"}]

const transferInstructions = [
  {
    "Source Plate": "plate_1",
    "Source Well": "A1",
    Volume: 1,
    "Destination Plate": "plate2",
    "Destination Well": "A3",
  },
  {
    "Source Plate": "plate_1",
    "Source Well": "A2",
    Volume: 5,
    "Destination Plate": "plate2",
    "Destination Well": "A2",
  },
  {
    "Source Plate": "plate_1",
    "Source Well": "A3",
    Volume: 10,
    "Destination Plate": "plate2",
    "Destination Well": "A1",
  },
];

const sourceInfo = {
  plate_map_id: "plate1",
  plate_instruction_id: "plate_1", //slightly different name
  plate_size: 6,
  plate_suffix: "_6wp",
};

const destinationInfo = {
  plate_map_id: "plate2",
  plate_instruction_id: "plate2",
  plate_size: 96,
  plate_suffix: "_96wp",
};

let transformer = new PlateTransofmer(
  sourceLayout,
  destinationLayout,
  transferInstructions,
  sourceInfo,
  destinationInfo
);

let newLayout = transformer.transformPlates();

// newLayout
// [
//   { Plate: "plate2", Well: "A1", volume_6wp: 10, optional: 1, buffer: "Tris", additive: null },
//   { Plate: "plate2", Well: "A2", volume_6wp: 5, optional: 3, buffer: "Tris", additive: "Water"},
//   { Plate: "plate2", Well: "A3", volume_6wp: 1, optional: 5, buffer: "Tris", additive: "DMSO" },
//   ...
// ];
```

## SourceInfo and DestinationInfo

The source configuration object indicates what the source plate is named in _in the platelayout_ (`plate_map_id`) and _in the instructions_ (`plate_instruction_id`) (in case they are named differently). `Plate_size` attribute indicates the size of the plate (24, 96, etc). The last configuration is the prefered `plate_suffix`, which may or may not be used depending on the platelayouts and transfer instructions. See below for details.

# Clash Options

When the source and destination's well data share a common key (aside from `Plate` and `Well`), then transfering the data from source to the destination creates a clash issue. You can configure `PlateDataTransfer` to accomodate the clash in several ways. You can keep the source value,keep the destination value, or concatenate both together with a chosen separator (eg: ", " or "-"). Additionally, both keys' names can be
changed by adding the suffix.

**Clash strategy options** = `"keepSource" | "keepDestination" | "concatenate" | "suffix"`

If clash strategy is `concatenate`, then the separator option defines what character (if any) separates the two concatenated values.

**Separator options** = `", " | "-" | "_" | " " | " + " | ""`

# Clash on `buffer` key

Default clash strategy is `"suffix"`

```js
import PlateDataTransfer from "plate-data-transfer";
asdfawef3254jnbvcqwe4rbvfvfe;
//source plate map (pipetting from)
const sourceLayout = [
  { Plate: "a", Well: "A1", buffer: "Tris" },
  { Plate: "a", Well: "A2", buffer: "Tris" },
  //...
  { Plate: "a", Well: "B3", buffer: "Tris" },
];

//destination shares 'buffer' key with source plate
const destinationLayout = [
  { Plate: "b", Well: "A1", buffer: "HEPES" },
  { Plate: "b", Well: "A2", buffer: "HEPES" },
  //...
  { Plate: "b", Well: "G12", buffer: "HEPES" },
];

let transformer = new PlateTransofmer(
  sourceLayout,
  destinationLayout,
  transferInstructions,
  sourceInfo,
  destinationInfo
);

//default clash strategy = "suffix"
let newLayout = transformer.transformPlates();
//newLayout contains {..., buffer_6wp: "Tris", buffer_96wp: "HEPES"}]
```

# Change Clash Strategy

```js
//change clash strategy to keep destination values
transformer.setClashStrategy("keepDestination");
let newLayout = transformer.transformPlates();
//newLayout contains {..., buffer: "HEPES"}
```

## `concatenate` clash strategy

```js
//change clash strategy to concatenate
transformer.setClashStrategy("concatenate");
transformer.setClashConcatenationSeparator(" + ");
let newLayout = transformer.transformPlates();}
//newLayout contains {..., buffer: "Tris + HEPES"}

transformer.setClashConcatenationSeparator("");
let newLayout = transformer.transformPlates();
//newLayout contains {..., buffer: "TrisHEPES"}

transformer.setClashConcatenationSeparator(", ");
let newLayout = transformer.transformPlates();
//newLayout contains {..., buffer: "Tris, HEPES"}
```
