Skip to content

Commit

Permalink
implement review feedback
Browse files Browse the repository at this point in the history
  • Loading branch information
ecormany committed May 3, 2024
1 parent 99f069b commit 8634a83
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 31 deletions.
2 changes: 1 addition & 1 deletion api/docs/v2/parameters/choosing.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,4 @@ Consider our earlier example of parameterizing serial dilution. Each of the thre

What if you wanted to perform a dilution with 20 repetitions? It's possible with two 96-well plates, or with a 384-well plate. You could set the maximum for the number of dilutions to 24 and allow for these possibilities — either switching the plate type or loading an additional plate based on the provided value.

But what if the user wanted to do just 8 repetitions on a 384-well plate? That would require an additional parameter, an additional choice by the user, and additional logic in your protocol code. It's up to you as the protocol author to decide if adding more parameters adds unnecessary complexity. It may well be better to have two or three protocols that each work simply and efficiently.
But what if the user wanted to do just 8 repetitions on a 384-well plate? That would require an additional parameter, an additional choice by the user, and additional logic in your protocol code. It's up to you as the protocol author to decide if adding more parameters will make protocol setup overly difficult. Sometimes it's more efficient to work with two or three simple protocols rather than one that's long and complex.
31 changes: 15 additions & 16 deletions api/docs/v2/parameters/defining.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ Depending on the :ref:`type of parameter <rtp-types>`, you'll need to specify so
- Optional, for numeric parameters only.
- Displays after the number during run setup.
- Does not affect the parameter's value or protocol execution.
- Maximum [10/TK] characters.
- Maximum 10 characters.



Expand Down Expand Up @@ -93,19 +93,20 @@ During run setup, users can toggle between the two values. In the Opentrons App,
Integer Parameters
------------------

Integer parameters either accept a range of numbers or a list of numbers. You must specify one or the other; you can't prompt for any integer.
Integer parameters either accept a range of numbers or a list of numbers. You must specify one or the other; you can't create an open-ended prompt that accepts any integer.

To specify a range, include ``minimum`` and ``maximum``.

.. code-block::
parameters.add_int(
variable_name="sample_count",
display_name="Sample count",
description="How many samples to process.",
default=24,
minimum=8,
maximum=48
variable_name="volume",
display_name="Aspirate volume",
description="How much to aspirate from each sample.",
default=20,
minimum=10,
maximum=100,
unit="µL"
)
During run setup, the user can enter any integer value from the minimum up to the maximum. Entering a value outside of the range will show an error. At that point, they can correct their custom value or restore the default value.
Expand All @@ -123,8 +124,7 @@ To specify a list of numbers, include ``choices``. Each choice is a dictionary w
{"display_name": "Low (10 µL)", "value": 10},
{"display_name": "Medium (20 µL)", "value": 20},
{"display_name": "High (50 µL)", "value": 50},
],
unit="µL"
]
)
During run setup, the user can choose from a menu of the provided choices.
Expand All @@ -134,7 +134,7 @@ During run setup, the user can choose from a menu of the provided choices.
Float Parameters
----------------

Float parameters either accept a range of numbers or a list of numbers. You must specify one or the other; you can't prompt for any floating point number.
Float parameters either accept a range of numbers or a list of numbers. You must specify one or the other; you can't create an open-ended prompt that accepts any floating point number.

Specifying a range or list is done exactly the same as in the integer examples above. The only difference is that all values must be floating point numbers.

Expand All @@ -149,20 +149,19 @@ Specifying a range or list is done exactly the same as in the integer examples a
{"display_name": "Low (2.5 µL)", "value": 2.5},
{"display_name": "Medium (5 µL)", "value": 5.0},
{"display_name": "High (10 µL)", "value": 10.0},
],
unit="µL"
]
)
Remember, you can't mix types in a parameter. So values of ``2.5``, ``5.0``, and ``10.0`` are valid, but ``2.5``, ``5``, and ``10`` will raise an error.

.. versionadded:: 2.18

String Parameters
-----------------

String parameters only accept a list of values. You can't currently prompt for free text entry of a string value.

To specify a list of strings, include ``choices``. Each choice is a dictionary with entries for display name and value. In most cases, the display name and value *will not* match. A common use for string display names is to provide an easy-to-read version of an API load name. You can also use them to briefly explain the effect each choice will have.
To specify a list of strings, include ``choices``. Each choice is a dictionary with entries for display name and value. Only the display name will appear during run setup.

A common use for string display names is to provide an easy-to-read version of an API load name. You can also use them to briefly explain the effect each choice will have.

.. code-block::
Expand Down
6 changes: 3 additions & 3 deletions api/docs/v2/parameters/style.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
Parameter Style Guide
*********************

Defining parameters creates an important part of the user experience for the technicians who run your protocols. They rely on your parameter names and descriptions being clear, consistent, and ultimately easy to use.
It's important to write clear names and descriptions when you :ref:`define parameters <defining-rtp>` in your protocols. Clarity improves the user experience for the technicians who run your protocols. They rely on your parameter names and descriptions to understand how the robot will function when running your protocol.

Adopting the advice of this guide also makes your protocols more consistent with those in the `Opentrons Protocol Library <https://library.opentrons.com>`_, which can help others access and replicate your science.
Adopting the advice of this guide will help make your protocols clear, consistent, and ultimately easy to use. It also aligns them with protocols in the `Opentrons Protocol Library <https://library.opentrons.com>`_, which can help others access and replicate your science.

General Guidance
================
Expand Down Expand Up @@ -129,7 +129,7 @@ Number Choices
Strings
-------

**Don't use string choices when a Boolean will work.** Use a Boolean when your string choices could be rephrased in terms of "true/false" or "on/off". Note that this does not apply to all two-choice situations.
**Avoid strings that are synonymous with "yes" and "no".** When presenting exactly two string choices, consider their meaning. Can they be rephrased in terms of "yes/no", "true/false", or "on/off"? If no, then a string parameter is appropriate. If yes, it's better to use a Boolean, which appears in run setup as a toggle rather than a dropdown menu.

- ✅ Blue, Red
- ✅ Left-to-right, Right-to-left
Expand Down
16 changes: 8 additions & 8 deletions api/docs/v2/parameters/use_case_dry_run.rst
Original file line number Diff line number Diff line change
Expand Up @@ -45,21 +45,21 @@ Many protocols have built-in delays, either for a module to work or to let a rea

To start, let's consider a simple :py:meth:`.delay` command. We can wrap it in an ``if`` statement such that the delay will only execute when the run is *not* a dry run::

if protocol.params.dry_run == False:
if protocol.params.dry_run is False:
protocol.delay(minutes=5)

You can extend this approach to more complex situations, like module interactions. For example, in a protocol that moves a plate to the Thermocycler for an incubation, you'll want to perform all the movement steps — opening and closing the module lid, and moving the plate to and from the block — but skip the heating and cooling time. The simplest way to do this is, like in the delay example above, to wrap each skippable command::

protocol.move_labware(labware=plate, new_location=tc_mod, use_gripper=True)
if protocol.params.dry_run == False:
if protocol.params.dry_run is False:
tc_mod.set_block_temperature(4)
tc_mod.set_lid_temperature(100)
tc_mod.close_lid()
pcr_profile = [
{"temperature": 68, "hold_time_seconds": 180},
{"temperature": 98, "hold_time_seconds": 180},
]
if protocol.params.dry_run == False:
if protocol.params.dry_run is False:
tc_mod.execute_profile(
steps=pcr_profile, repetitions=1, block_max_volume=50
)
Expand All @@ -70,15 +70,15 @@ Shortening Mix Steps

Similar to delays, mix steps can take a long time because they are inherently repetitive actions. Mixing ten times takes ten times as long as mixing once! To save time, set a mix repetitions variable based on the value of ``protocol.params.dry_run`` and pass that to :py:meth:`.mix`::

if protocol.params.dry_run == True:
if protocol.params.dry_run is True:
mix_reps = 1
else:
mix_reps = 10
pipette.mix(repetitions=mix_reps, volume=50, location=plate["A1"].bottom())

Note that this checks whether the dry run parameter is ``True``. If you prefer to set up all your ``if`` statements to check whether it's ``False``, you can reverse the logic::

if protocol.params.dry_run == False:
if protocol.params.dry_run is False:
mix_reps = 10
else:
mix_reps = 1
Expand All @@ -88,15 +88,15 @@ Returning Tips

Tips used in a dry run should be reusable — for another dry run, if nothing else. It doesn't make sense to dispose of them in a trash container, unless you specifically need to test movement to the trash. You can choose whether to use :py:meth:`.drop_tip` or :py:meth:`.return_tip` based on the value of ``protocol.params.dry_run``. If the protocol doesn't have too many tip drop actions, you can use an ``if`` statement each time::

if protocol.params.dry_run == True:
if protocol.params.dry_run is True:
pipette.return_tip()
else:
pipette.drop_tip()

However, repeating this block every time you handle tips could significantly clutter your code. Instead, you could define it as a function::

def return_or_drop(pipette):
if protocol.params.dry_run == True:
if protocol.params.dry_run is True:
pipette.return_tip()
else:
pipette.drop_tip()
Expand All @@ -114,7 +114,7 @@ Additionally, if your protocol uses enough tips that you have to replenish tip r

The API has methods to handle both of these situations. To continue using the same tip rack without physically replace it, call :py:meth:`.reset_tipracks`. In the live run, move the empty tip rack off the deck and move a full one into place::

if protocol.params.dry_run == True:
if protocol.params.dry_run is True:
pipette.reset_tipracks()
else:
protocol.move_labware(
Expand Down
4 changes: 2 additions & 2 deletions api/docs/v2/parameters/use_case_sample_count.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ We want to limit the number of samples to 8, 16, 24, or 32, so we'll use an inte
parameters.add_int(
variable_name="sample_count",
display_name="Sample count",
description="Number of input DNA samples"
description="Number of input DNA samples",
default=24,
choices=[
{"display_name": "8", "value": 8},
Expand Down Expand Up @@ -267,7 +267,7 @@ This will replace the first 200 µL tip rack (in slot A2) with the last 200 µL

However, in the full protocol, sample count is not the only parameter that affects the rate of tip use. It would be unwieldy to calculate in advance all the permutations of when tip replenishment is necessary. Instead, before each stage of the protocol, we could use :py:obj:`.Well.has_tip()` to check whether the first tip rack is empty. If the *last well* of the rack is empty, we can assume that the entire rack is empty and needs to be replaced::

if tip_racks_200[0].wells()[-1].has_tip == False:
if tip_racks_200[0].wells()[-1].has_tip is False:
# same move_labware() steps as above

For a protocol that uses tips at a faster rate than this one — such that it might exhaust a tip rack in a single ``for`` loop of pipetting steps — you may have to perform such checks even more frequently. You can even define a function that counts tips or performs ``has_tip`` checks in combination with picking up a tip, and use that instead of :py:meth:`.pick_up_tip` every time you pipette. The built-in capabilities of Python and the methods of the Python Protocol API give you the flexibility to add this kind of smart behavior to your protocols.
2 changes: 1 addition & 1 deletion api/docs/v2/parameters/using_values.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Then ``params`` will gain three attributes: ``params.dry_run``, ``params.sample_

.. code-block::
if protocol.params.dry_run == False:
if protocol.params.dry_run is False:
pipette.mix(repetitions=10, volume=protocol.params.volume)
You can also save parameter values to variables with names of your choosing.
Expand Down

0 comments on commit 8634a83

Please sign in to comment.