Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pylabrobot/resources/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from .azenta import *
from .biorad import *
from .boekel import *
from .btx import *
from .carrier import (
Carrier,
MFXCarrier,
Expand Down
1 change: 1 addition & 0 deletions pylabrobot/resources/btx/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .plates import *
61 changes: 61 additions & 0 deletions pylabrobot/resources/btx/plates.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
# https://btxonline.com/media/wysiwyg/tab_content/BTX-Electroporation-Multiwell-Plates-25.pdf
# https://support.btxonline.com/hc/en-us/article_attachments/6352046003987

from pylabrobot.resources.plate import Plate
from pylabrobot.resources.utils import create_ordered_items_2d
from pylabrobot.resources.well import (
CrossSectionType,
Well,
WellBottomType,
)


def BTX_96_wellplate_125ul_Fb_2mm(name: str) -> Plate:
"""BTX 96-well disposable electroporation plate, 2 mm gap.
- BTX part no.: 45-0450 / 45-0450-M
- External dimensions: 127.8 x 85.5 x 15.9 mm
- Well pitch: 9.0 mm x 9.0 mm
- Bottom type: flat
- Nominal / manufacturer max-use volume: 125 uL
- Recommended working volume: 50-100 uL
- Approximate physical brim volume: 160 uL
Notes:
- The well free aperture is modeled as approximately 2.0 mm x 8.0 mm based on BTX gap size,
BTX published footprint/pitch, and manual measurements.
- Internal electrode termination is approximately 1 mm above the cavity floor, but that is not
represented as an internal obstacle in the standard PLR Well model.
- dx, dy, dz, well dimensions, and material_z_thickness are partly inferred from BTX published
dimensions plus manual measurements and should be treated as provisional.
"""

well_kwargs = {
"size_x": 2.0, # effective free aperture between electrodes, inferred from BTX gap size
"size_y": 8.0, # measured/inferred from row wall spacing
"size_z": 10.8, # 10.0 mm internal height + 0.8 mm bottom thickness, inferred
"bottom_type": WellBottomType.FLAT,
"material_z_thickness": 0.8, # inferred from side profile measurements
"cross_section_type": CrossSectionType.RECTANGLE,
"max_volume": 160, # measured brim volume; BTX nominal volume is 125 uL
}

return Plate(
name=name,
size_x=127.8, # from BTX spec
size_y=85.5, # from BTX spec
size_z=15.9, # from BTX spec
lid=None,
model=BTX_96_wellplate_125ul_Fb_2mm.__name__,
ordered_items=create_ordered_items_2d(
Well,
num_items_x=12,
num_items_y=8,
dx=13.3, # measured manually
dy=7.0, # measured manually
dz=4.0, # measured manually
item_dx=9.0, # from BTX spec / standard 96-well pitch
item_dy=9.0, # from BTX spec / standard 96-well pitch
**well_kwargs,
),
)
26 changes: 26 additions & 0 deletions pylabrobot/resources/btx/plates_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import unittest

from pylabrobot.resources import BTX_96_wellplate_125ul_Fb_2mm


class TestBTX96Wellplate2mm(unittest.TestCase):
def test_geometry(self):
plate = BTX_96_wellplate_125ul_Fb_2mm(name="btx_plate")

a1 = plate.get_well("A1")
h1 = plate.get_well("H1")
a12 = plate.get_well("A12")

assert a1.location is not None
assert h1.location is not None
assert a12.location is not None

self.assertEqual(plate.get_size_x(), 127.8)
self.assertEqual(plate.get_size_y(), 85.5)
self.assertEqual(plate.get_size_z(), 15.9)

self.assertAlmostEqual(a1.location.x + a1.get_size_x() / 2, 14.3)
self.assertAlmostEqual(a1.location.y + a1.get_size_y() / 2, 74.0)
self.assertAlmostEqual(h1.location.y, 7.0)
self.assertAlmostEqual(a12.location.x + a12.get_size_x(), 114.3)
self.assertEqual(a1.max_volume, 160)
Loading