Skip to content

feat(api): add absolute flow_rate argument to aspirate() and dispense()#18326

Merged
ddcc4 merged 1 commit intoedgefrom
dc-py-flowrate
May 13, 2025
Merged

feat(api): add absolute flow_rate argument to aspirate() and dispense()#18326
ddcc4 merged 1 commit intoedgefrom
dc-py-flowrate

Conversation

@ddcc4
Copy link
Copy Markdown
Contributor

@ddcc4 ddcc4 commented May 12, 2025

Overview

Previously, aspirate() and dispense() only took a rate, which is a ratio of the pipette's default flow rate. This made it hard to specify an absolute flow rate for a single aspirate and dispense call, because the default flow rate for the pipette is often unknown. As a workaround, we could override the pipette's default flow rate like this:

pipette.flow_rate.aspirate = 123

but that permanently alters the flow rates for the rest of the protocol. For PD code generation, we were using the hack:

pipette.aspirate(rate=123/pipette.flow_rate.aspirate)

which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an absolute flow_rate argument (in uL/s) to aspirate() and dispense(). AUTH-1627

Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for existing code.
Added tests to make sure we error if the user specifies both rate and flow_rate.

Risk assessment

Low-ish.

@ddcc4 ddcc4 requested review from jbleon95 and jerader May 12, 2025 23:07
@ddcc4 ddcc4 requested a review from a team as a code owner May 12, 2025 23:07
@ddcc4 ddcc4 force-pushed the dc-py-flowrate branch from ef9ea79 to c124f99 Compare May 12, 2025 23:14
@ddcc4 ddcc4 force-pushed the dc-py-flowrate branch from c124f99 to 0eba6f7 Compare May 12, 2025 23:19
Copy link
Copy Markdown
Member

@sfoster1 sfoster1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A long time coming!

@ddcc4 ddcc4 merged commit 50e32e2 into edge May 13, 2025
24 checks passed
@ddcc4 ddcc4 deleted the dc-py-flowrate branch May 13, 2025 20:58
ddcc4 added a commit that referenced this pull request May 16, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.
ddcc4 added a commit that referenced this pull request May 16, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.
ddcc4 added a commit that referenced this pull request May 17, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.
ddcc4 added a commit that referenced this pull request May 17, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.
ddcc4 added a commit that referenced this pull request May 17, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.
ddcc4 added a commit that referenced this pull request May 17, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.

(cherry picked from commit 50e32e2)
ddcc4 added a commit that referenced this pull request May 17, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.

(cherry picked from commit 50e32e2)
ddcc4 added a commit that referenced this pull request May 17, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.

(cherry picked from commit 50e32e2)
ddcc4 added a commit that referenced this pull request May 17, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.

(cherry picked from commit 50e32e2)
ddcc4 added a commit that referenced this pull request May 17, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.

(cherry picked from commit 50e32e2)
ddcc4 added a commit that referenced this pull request May 17, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.

(cherry picked from commit 50e32e2)
ddcc4 added a commit that referenced this pull request May 19, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.

(cherry picked from commit 50e32e2)
ddcc4 added a commit that referenced this pull request May 19, 2025
…and `dispense()` (#18391)

# Overview

We added the `flow_rate` argument to `aspirate()` and `dispense()`
(AUTH-1627, PR #18326), so now in PD Python generation, we can just set
the flow rate directly, instead of the hacky ratio we were emitting
before.

This makes the generated code much cleaner and easier to read.

## Test Plan and Hands on Testing

Updated unit tests.
Examined generated code by hand.
I also re-exported Python for a test protocol and confirmed that it
passes `analyze`.

## Risk assessment

Low.
ddcc4 added a commit that referenced this pull request May 19, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.

(cherry picked from commit 50e32e2)
ddcc4 added a commit that referenced this pull request May 19, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.

(cherry picked from commit 50e32e2)
ddcc4 added a commit that referenced this pull request May 20, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.

(cherry picked from commit 50e32e2)
ddcc4 added a commit that referenced this pull request May 20, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.

(cherry picked from commit 50e32e2)
ddcc4 added a commit that referenced this pull request May 22, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.

(cherry picked from commit 50e32e2)
ddcc4 added a commit that referenced this pull request May 23, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.

(cherry picked from commit 50e32e2)
ddcc4 added a commit that referenced this pull request May 24, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.

(cherry picked from commit 50e32e2)
ddcc4 added a commit that referenced this pull request May 24, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.

(cherry picked from commit 50e32e2)
ddcc4 added a commit that referenced this pull request May 29, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.

(cherry picked from commit 50e32e2)
ddcc4 added a commit that referenced this pull request May 29, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.

(cherry picked from commit 50e32e2)
ddcc4 added a commit that referenced this pull request May 29, 2025
…se() (#18326)

# Overview

Previously, `aspirate()` and `dispense()` only took a `rate`, which is a
ratio of the pipette's default flow rate. This made it hard to specify
an absolute flow rate for a single aspirate and dispense call, because
the default flow rate for the pipette is often unknown. As a workaround,
we could override the pipette's default flow rate like this:
```
pipette.flow_rate.aspirate = 123
```
but that permanently alters the flow rates for the rest of the protocol.
For PD code generation, we were using the hack:
```
pipette.aspirate(rate=123/pipette.flow_rate.aspirate)
```
which produces the correct value, but is ugly.

For both PD code generation and our human users, this PR adds an
absolute `flow_rate` argument (in uL/s) to `aspirate()` and
`dispense()`. AUTH-1627

## Test Plan and Hands on Testing

Added unit tests for the new argument.
I relied on existing unit tests to make sure behavior is unchanged for
existing code.
Added tests to make sure we error if the user specifies both `rate` and
`flow_rate`.

## Risk assessment

Low-ish.

(cherry picked from commit 50e32e2)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants