-
Notifications
You must be signed in to change notification settings - Fork 179
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore(shared-data): create liquid class schema v1 and fixture #16267
Conversation
This PR introduces the first version of an Opentrons liquid class schema. Single liquid class definitions will adhere to this schema and be keyed by pipette and tip type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm a little concerned with the regexes that you specify for tips and for pipettes. Because these are keys, they're tough to document; and because we want to keep this open for more pipettes and tips, it's tough to make a properly restrictive and self-documenting regex (insofar as regexes can ever be self-documenting).
What about instead having these levels be arrays, something like
"properties: {
"liquidName": ...,
...,
"byPipette": {
"type": "array",
"description": "The settings for each kind of pipette for this liquid",
"items": {
"type": "object",
"description": "The settings for a specific kind of pipette when handling this liquid",
"properties": {
"pipetteModel": {
"type": "string",
"description": "The pipette model this applies to",
// free to have an enum or a pattern or just a string here
},
"byTipClass": {
"description": "Settings for each kind of tip this pipette can use",
"type": "array",
"items": {
"type": "object",
"properties": {
"tipClass": {
// again, free to have different enums or patterns or whatever
},
...
}
}
}
}
}
}
} | ||
}, | ||
"patternProperties": { | ||
"^p[0-9]{2,4}": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see where you're going with the patternProperties here but I think it's going to be tough to come up with an appropriate regex and I'm not sure this is usefully it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's a good callout. I like the idea of nesting the properties in arrays of objects containing the specific pipette/tip properties. Just pushed a commit to that effect and made some other refactors for only requiring certain properties if enable
is true
.
"type": "object", | ||
"description": "Object containing liquid class properties specific to the pipette model", | ||
"patternProperties": { | ||
"^t[0-9]{2,4}$": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same comment as with the pipette type
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## edge #16267 +/- ##
=======================================
Coverage 73.62% 73.62%
=======================================
Files 41 41
Lines 2992 2992
=======================================
Hits 2203 2203
Misses 789 789
Flags with carried forward coverage won't be shown. Click here to find out more. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great to me! Sorry it took me a while to re-review.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is awesome @ncdiehl! Just a couple of nitpicks.
We also need to add volume corrections but we can add those fields later
"touchTip": { | ||
"type": "object", | ||
"description": "Shared properties for the touch-tip function.", | ||
"properties": { | ||
"enable": { | ||
"type": "boolean", | ||
"description": "Whether touch-tip is enabled." | ||
}, | ||
"zOffset": { | ||
"type": "number", | ||
"description": "Offset from the top of the well for touch-tip, in millimeters." | ||
}, | ||
"mmToEdge": { | ||
"type": "number", | ||
"description": "Offset away from the the well edge, in millimeters." | ||
}, | ||
"speed": { | ||
"$ref": "#/definitions/positiveNumber", | ||
"description": "Touch-tip speed, in millimeters per second." | ||
} | ||
}, | ||
"if": { | ||
"properties": { | ||
"enable": { "const": true } | ||
} | ||
}, | ||
"then": { | ||
"required": ["enable", "zOffset", "mmToEdge", "speed"] | ||
}, | ||
"else": { | ||
"required": ["enable"] | ||
} | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This works, but I think a more concise way of writing the required fields would be something like this-
"touchTip": {
"type": "object",
"description": "Shared properties for the touch-tip function.",
"properties": {
"enable": {
"type": "boolean",
"description": "Whether touch-tip is enabled."
},
"zOffset": {
"type": "number",
"description": "Offset from the top of the well for touch-tip, in millimeters."
},
"mmToEdge": {
"type": "number",
"description": "Offset away from the the well edge, in millimeters."
},
"speed": {
"$ref": "#/definitions/positiveNumber",
"description": "Touch-tip speed, in millimeters per second."
}
},
"required": ["enable"],
"if": {
"properties": {
"enable": { "const": true }
}
},
"then": {
"required": ["zOffset", "mmToEdge", "speed"]
}
},
i.e., enable
is required always. And if enable is true, require the additional properties
Same for all the other properties that have gating behind the enable
key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm going to go further than this and ask if there's a reason why we don't just get rid of enable
and make the the availability of a particular liquid class property depend on it being defined for a particular tip type, i.e. if it's there it's enabled and if it's not defined it's not enabled. This would simplify the Python models and we could always use known defaults if a user wishes to enable a default disabled property.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would simplify the Python models and we could always use known defaults if a user wishes to enable a default disabled property.
@jbleon95 while I agree that not having enable/disable makes the python models as well as this schema much more compact, using some known defaults if a user enables a property whose sub-properties aren't defined isn't a great solution. It would lead to confusion and uncertainty about what the defaults are for each of the enable-gated properties.
That said, maybe there's a middle ground. The schema doesn't include whether to enable or disable those properties but you specify it when using the transfer function. So essentially it'll behave the same way you described, except, the liquid class definition will contain definitions of all properties & sub-properties so that when a transfer function wants to use it, it uses the values from liquid class's definition instead of some defaults.
}, | ||
"mix": { | ||
"type": "object", | ||
"description": "Mixing properties.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we add a more elaborate description like you've used for submerge
?
}, | ||
"blowout": { | ||
"type": "object", | ||
"description": "Blowout properties.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same comment as mix
description
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some nitpicks but mainly want to make sure that the 'by volume' properties are as discussed. We want them to be objects where keys are volumes. So something like-
xyzByVolume: {
"default": 123.
"100": 1.2,
.
.
}
"default"
will be required for all.
The schema for it would be something like-
"airGapByVolume": {
"type": "object",
"description": "Settings for air gap keyed by target aspiration volume.",
"items": {
"$comment": "Other keys in here should be volume in uL",
"properties": {
"default": {
"$ref": "#/definitions/positiveNumber"}
},
"required": ["default"],
"additionalProperties": { "$ref": "#/definitions/positiveNumber", }
}
},
You can even assign pattern properties to the additional keys I think. So they'll always be strings of numbers
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changes look good!! Thanks!!
Overview
This PR introduces the first version of an Opentrons liquid class schema. Single liquid class definitions will adhere to this schema and be keyed by pipette and tip type.
Closes AUTH-832
Test Plan and Hands on Testing
Changelog
Review requests
See test plan. Should we leave keys for
patternProperties
pipette and tip type less restrictive strings? Perhaps anysafeString
rather than following more stringent regex?Risk assessment
low