/**
* Roboliq: Automation for liquid-handling robots
* @copyright 2017, ETH Zurich, Ellis Whitehead
* @license GPL-3.0
*/
/**
* Centrifuge commands module (see {@tutorial Commands#centrifuge} or [command specification](tutorial-Commands.html#centrifuge)).
*
* THIS SECTION IS FOR TESTING ONLY:
* {@link loadEvowareCarrierData}
* {@link module:commandHelper}
* {@link module:commands/centrifuge}
* END OF SECTION
*
* See {@link roboliq#Protocol}.
* @module commands/centrifuge
* @return {Protocol}
* @version v1
*/
var _ = require('lodash');
var jmespath = require('jmespath');
import yaml from 'yamljs';
var commandHelper = require('../commandHelper.js');
var expect = require('../expect.js');
var misc = require('../misc.js');
/**
* Create predicates for objects of type = "Centrifuge"
* @static
*/
var objectToPredicateConverters = {
"Centrifuge": function(name, object) {
return [{ "isCentrifuge": { "equipment": name } }];
},
};
function centrifuge2(params, parsed, data) {
var llpl = require('../HTN/llpl.js').create();
llpl.initializeDatabase(data.predicates);
//console.log(JSON.stringify(parsed, null, '\t'))
var agent = parsed.objectName.agent || "?agent";
var equipment = parsed.objectName.equipment || "?equipment";
var object1 = parsed.value.object1;
var object2 = parsed.value.object2;
var query0 = {
"centrifuge.canAgentEquipmentModelSite1Site2": {
"agent": "?agent",
"equipment": "?equipment",
"model": "?model",
"site1": "?site1",
"site2": "?site2"
}
};
var query = _.merge({}, query0,
{"centrifuge.canAgentEquipmentModelSite1Site2": {
"agent": parsed.objectName.agent,
"equipment": parsed.objectName.equipment,
"model": object1.model,
"site1": parsed.objectName.site1,
"site2": parsed.objectName.site2
}}
);
var resultList = llpl.query(query);
var alternatives = jmespath.search(resultList, '[]."centrifuge.canAgentEquipmentModelSite1Site2"');
if (_.isEmpty(resultList)) {
var resultList2 = llpl.query(query0);
if (_.isEmpty(resultList2)) {
return {
errors: ["missing equipment data (please add predicates `centrifuge.canAgentEquipmentModelSite1Site`)"]
};
} else {
return {
errors: ["missing equipment configuration for " + JSON.stringify(query)]
};
}
}
// Pick a plan
let chosen = undefined;
if (data.planAlternativeChoosers.hasOwnProperty("centrifuge.canAgentEquipmentModelSite1Site2")) {
chosen = data.planAlternativeChoosers["centrifuge.canAgentEquipmentModelSite1Site2"](alternatives, data);
// console.log({chosen})
}
const params2 = chosen || alternatives[0];
const destination1
= (parsed.value.destinationAfter1 === "stay") ? params2.site1
: _.isUndefined(parsed.objectName.destinationAfter1) ? object1.location
: parsed.objectName.destinationAfter1;
const destination2
= (parsed.value.destinationAfter2 === "stay") ? params2.site2
: _.isUndefined(parsed.objectName.destinationAfter2) ? object2.location
: parsed.objectName.destinationAfter2;
var expansion = [
(object1.location === params2.site1) ? null : [
{
command: "equipment.openSite",
agent: params2.agent,
equipment: params2.equipment,
site: params2.site1
},
{
"command": "transporter.movePlate",
"object": parsed.objectName.object1,
"destination": params2.site1
}
],
(object2.location === params2.site2) ? null : [
{
command: "equipment.openSite",
agent: params2.agent,
equipment: params2.equipment,
site: params2.site2
},
{
"command": "transporter.movePlate",
"object": parsed.objectName.object2,
"destination": params2.site2
}
],
{
command: "equipment.close",
agent: params2.agent,
equipment: params2.equipment
},
{
command: ["equipment.run", params2.agent, params2.equipment].join('|'),
agent: params2.agent,
equipment: params2.equipment,
program: parsed.objectName.program || parsed.value.program
},
// Move object1 back
(destination1 === params2.site1) ? null : [
{
command: "equipment.openSite",
agent: params2.agent,
equipment: params2.equipment,
site: params2.site1
},
{
"command": "transporter.movePlate",
"object": parsed.objectName.object1,
"destination": destination1
}
],
// Move object2 back
(destination2 === params2.site2) ? null : [
{
command: "equipment.openSite",
agent: params2.agent,
equipment: params2.equipment,
site: params2.site2
},
{
"command": "transporter.movePlate",
"object": parsed.objectName.object2,
"destination": destination2
}
],
// Close the centrifuge
(destination1 === params2.site1 && destination2 === params2.site2) ? null : {
command: "equipment.close",
agent: params2.agent,
equipment: params2.equipment
},
];
const warnings = (object1.model != object2.model)
? ["[W#CENT0001] object1 and object2 are of different labware models; this may be problematic for centrifugation."]
: [];
//console.log("centrifuge2 expansion:")
//console.log(JSON.stringify(expansion, null, '\t'))
return {
expansion,
alternatives,
warnings
};
}
function insertPlates2(params, parsed, data) {
// console.log("insertPlates2: "+JSON.stringify(parsed, null, '\t'));
var llpl = require('../HTN/llpl.js').create();
llpl.initializeDatabase(data.predicates);
if (!parsed.value.object1 && !parsed.value.object2) {
// do nothing
return {};
}
var agent = parsed.objectName.agent || "?agent";
var equipment = parsed.objectName.equipment || "?equipment";
var object1 = parsed.value.object1;
var object2 = parsed.value.object2;
const model = (object1) ? object1.model : object2.model;
var query0 = {
"centrifuge.canAgentEquipmentModelSite1Site2": {
"agent": "?agent",
"equipment": "?equipment",
"model": "?model",
"site1": "?site1",
"site2": "?site2"
}
};
var query = _.merge({}, query0,
{"centrifuge.canAgentEquipmentModelSite1Site2": {
"agent": parsed.objectName.agent,
"equipment": parsed.objectName.equipment,
"model": model,
"site1": parsed.objectName.site1,
"site2": parsed.objectName.site2
}}
);
var resultList = llpl.query(query);
var alternatives = jmespath.search(resultList, '[]."centrifuge.canAgentEquipmentModelSite1Site2"');
if (_.isEmpty(resultList)) {
var resultList2 = llpl.query(query0);
if (_.isEmpty(resultList2)) {
return {
errors: ["missing equipment data (please add predicates `centrifuge.canAgentEquipmentModelSite1Site`)"]
};
} else {
return {
errors: ["missing equipment configuration for " + JSON.stringify(query)]
};
}
}
// Pick a plan
let chosen = undefined;
if (data.planAlternativeChoosers.hasOwnProperty("centrifuge.canAgentEquipmentModelSite1Site2")) {
chosen = data.planAlternativeChoosers["centrifuge.canAgentEquipmentModelSite1Site2"](alternatives, data);
// console.log({chosen})
}
const params2 = chosen || alternatives[0];
var expansion = [
(!object1 || object1.location === params2.site1) ? null : [
{
command: "equipment.openSite",
agent: params2.agent,
equipment: params2.equipment,
site: params2.site1
},
{
"command": "transporter.movePlate",
"object": parsed.objectName.object1,
"destination": params2.site1
}
],
(!object2 || object2.location === params2.site2) ? null : [
{
command: "equipment.openSite",
agent: params2.agent,
equipment: params2.equipment,
site: params2.site2
},
{
"command": "transporter.movePlate",
"object": parsed.objectName.object2,
"destination": params2.site2
}
],
];
const warnings = (parsed.input.object1Model && parsed.input.object2Model && parsed.input.object1Model != parsed.input.object2Model)
? ["[W#CENT0001] object1 and object2 are of different labware models; this may be problematic for centrifugation."]
: [];
return { expansion, alternatives, warnings };
}
insertPlates2.inputSpec = {
agent: "?agent",
equipment: "?equipment",
object1: "?object1",
object2: "?object2",
object1Model: "?object1*model",
object2Model: "?object2*model",
site1: "?site1",
site2: "?site2"
};
/**
* Handlers for {@link centrifuge} commands.
* @static
*/
var commandHandlers = {
"centrifuge.centrifuge2": centrifuge2,
"centrifuge.insertPlates2": insertPlates2
};
module.exports = {
roboliq: "v1",
objectToPredicateConverters,
schemas: yaml.load(__dirname+"/../schemas/centrifuge.yaml"),
commandHandlers
};