Skip to content

Commit cfeae4d

Browse files
authored
Update pipetting loss calculations to use ceiling (#318)
1 parent e973664 commit cfeae4d

2 files changed

Lines changed: 15 additions & 10 deletions

File tree

src/MasterMix/pipettingLossTableColumn.test.tsx

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,17 +27,17 @@ describe('pipettingLossTableColumn', () => {
2727
render(<>{column.render(null, { volume: 10, title: '', key: 1 }, 1)}</>);
2828
render(<>{column.title}</>);
2929

30-
expect(screen.getByText('22.0 µl')).toBeInTheDocument();
30+
expect(screen.getByText('30.0 µl')).toBeInTheDocument();
3131
expect(screen.getByText('2x Ansätze + 10% (PV)')).toBeInTheDocument();
3232
});
3333
});
3434

3535
describe('with "factorWithMinimum" pipetting loss type', () => {
3636
it('should use minimum positions when factor loss is slightly below minimum positions', () => {
3737
// 19 ansätze × 10µl = 190µl
38-
// factor loss: 190µl × 10% = 19µl
38+
// factor loss: ceil(19 × 10%) = ceil(1.9) = 2 positions × 10µl = 20µl
3939
// min positions loss: 2 × 10µl = 20µl
40-
// result: 190µl + max(19µl, 20µl) = 210µl
40+
// result: 190µl + max(20µl, 20µl) = 210µl
4141
const column = pipettingLossTableColumn({
4242
count: 19,
4343
pipettingLoss: {
@@ -55,9 +55,9 @@ describe('pipettingLossTableColumn', () => {
5555

5656
it('should use factor loss when it is slightly above minimum positions', () => {
5757
// 21 ansätze × 10µl = 210µl
58-
// factor loss: 210µl × 10% = 21µl
58+
// factor loss: ceil(21 × 10%) = ceil(2.1) = 3 positions × 10µl = 30µl
5959
// min positions loss: 2 × 10µl = 20µl
60-
// result: 210µl + max(21µl, 20µl) = 231µl
60+
// result: 210µl + max(30µl, 20µl) = 240µl
6161
const column = pipettingLossTableColumn({
6262
count: 21,
6363
pipettingLoss: {
@@ -69,7 +69,7 @@ describe('pipettingLossTableColumn', () => {
6969
render(<>{column.title}</>);
7070
render(<>{column.render(null, { volume: 10, title: '', key: 1 }, 1)}</>);
7171

72-
expect(screen.getByText('231.0 µl')).toBeInTheDocument();
72+
expect(screen.getByText('240.0 µl')).toBeInTheDocument();
7373
expect(screen.getByText('21x Ansätze + 10% (PV)')).toBeInTheDocument();
7474
});
7575
});

src/MasterMix/pipettingLossTableColumn.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,18 @@ type PipettingLosses = {
1515
minPositionsLoss: number;
1616
};
1717

18+
function calculateAdditionalSamples(count: number, factor: number): number {
19+
return Math.ceil(count * factor);
20+
}
21+
1822
function calculatePipettingLosses(
1923
count: number,
2024
pipettingLoss: PipettingLossFactorWithMinimum,
2125
volume = 1,
2226
): PipettingLosses {
23-
const baseVolume = volume * count;
2427
return {
25-
factorLoss: baseVolume * pipettingLoss.factor,
28+
factorLoss:
29+
volume * calculateAdditionalSamples(count, pipettingLoss.factor),
2630
minPositionsLoss: volume * pipettingLoss.minPositions,
2731
};
2832
}
@@ -59,8 +63,9 @@ function totalVolume(
5963
);
6064
case 'factor':
6165
return (
62-
record.volume * args.count +
63-
record.volume * args.count * args.pipettingLoss.factor
66+
record.volume *
67+
(args.count +
68+
calculateAdditionalSamples(args.count, args.pipettingLoss.factor))
6469
).toFixed(1);
6570
case 'factorWithMinimum': {
6671
const baseVolume = record.volume * args.count;

0 commit comments

Comments
 (0)