Skip to content

Capturing data during protocol execution: Object of type module is not JSON serializable #593

@amulyagarimella

Description

@amulyagarimella

Capturing communication in the io layer of PLR, like in this example, doesn't work. Minimal reproducible example and error below:

import asyncio
from datetime import datetime

from pylabrobot.io import start_capture, stop_capture
from pylabrobot.liquid_handling import LiquidHandler
from pylabrobot.liquid_handling.backends.hamilton import STAR

from pylabrobot.resources.hamilton import STARDeck
from pylabrobot.resources import (
    TIP_CAR_480_A00,
    PLT_CAR_L5PCR,
    PLT_CAR_L5AC_A00,
    HTF,
    Eppendorf_96_wellplate_250ul_Vb_semiskirted,
    nest_12_troughplate_15000uL_Vb,
    set_tip_tracking,
    set_volume_tracking
)
from pylabrobot.resources.coordinate import Coordinate


async def main(lh, tcend, skip_core96_head, verbose=False):
    await lh.setup(skip_core96_head=skip_core96_head)

    reservoir_name = "res_12_00"
    pcr_plate_name = "pcr_plate_0_4"
    pcr_plate = lh.deck.get_resource(pcr_plate_name)
    reservoir = lh.deck.get_resource(reservoir_name)

    reservoir_wells = [reservoir[i] for i in range(12)]

    tip_well_name = "A1"
    well1 = "A1"
    well2 = "A2"
    reservoir.set_well_liquids(liquids=[("Filled", 15000)] * 12)

    tip = tcend[tip_well_name]
    await lh.pick_up_tips(tip)

    await lh.aspirate(reservoir_wells[0], vols=[1000.], offsets=[Coordinate(0, 0, 3)])

    for _ in range(10):
        await lh.dispense(pcr_plate[well1], vols=[100.], offsets=[Coordinate(0, 0, 10)])
        await lh.aspirate(pcr_plate[well1], vols=[100.], offsets=[Coordinate(0, 0, 3)])
        await lh.dispense(pcr_plate[well2], vols=[100.], offsets=[Coordinate(0, 0, 10)])
        await lh.aspirate(pcr_plate[well2], vols=[100.], offsets=[Coordinate(0, 0, 3)])

if __name__ == "__main__":
    # Initialize hardware
    BACKEND = STAR()
    DECK = STARDeck()
    lh = LiquidHandler(backend=BACKEND, deck=DECK)
    SKIP_CORE96_HEAD = True # For broken core96 head
    MAX_ATTEMPTS = 1

    text_log_file = f"hamilton_run_logs/hamilton_full_run_script_{datetime.now().strftime('%Y%m%d_%H%M%S')}.txt"
     # --- TIP SETUP: Only tip_carrier_2_4 (HTF) on rail 31 ---
    TIP_CAR = TIP_CAR_480_A00(name="tip_carrier_2")
    tcend = HTF(name="tip_carrier_2_4")
    TIP_CAR[4] = tcend
    lh.deck.assign_child_resource(TIP_CAR, rails=31)

    # --- RESERVOIR SETUP: plate_carrier_2 with res_12_04 to res_12_00 on rail 37 ---
    RES_NAMES = [f"res_12_0{i}" for i in reversed(range(5))]  # res_12_04 to res_12_00
    RESOURCES = [nest_12_troughplate_15000uL_Vb(name=name) for name in RES_NAMES]

    PLT_CAR_2 = PLT_CAR_L5AC_A00(name="plate_carrier_2")
    for i, res in enumerate(RESOURCES):
        PLT_CAR_2[i] = res
    lh.deck.assign_child_resource(PLT_CAR_2, rails=37)

    # --- Fill each reservoir with dummy contents ---
    for res_name in RES_NAMES:
        lh.deck.get_resource(res_name).set_well_liquids(liquids=[("Filled", 15000)] * 12)

    # --- PCR PLATE SETUP: 7 carriers with 5 plates each at specific rails ---
    PCR_PLATE_RAILS = [1, 7, 13, 19, 25, 43, 49]
    for idx, rail in enumerate(PCR_PLATE_RAILS):
        carrier = PLT_CAR_L5PCR(name=f"plate_carrier_pcr_{idx}")
        for j in range(5):
            plate_name = f"pcr_plate_{idx}_{j}"
            carrier[j] = Eppendorf_96_wellplate_250ul_Vb_semiskirted(name=plate_name)
        lh.deck.assign_child_resource(carrier, rails=rail)

    # --- Setup the system ---
    lh.backend.read_timeout = 30*60

    # --- Enable resource tracking ---
    set_tip_tracking(True)
    set_volume_tracking(True)

    verbose = False

    validation_file = "hamilton_run_logs/minimal_dispense_validation.json"
    start_capture(validation_file)
    asyncio.run(main(lh, tcend, SKIP_CORE96_HEAD, verbose=verbose))
    stop_capture()
Traceback (most recent call last):
  File "/home/labauto2/Downloads/hamilton-tests/capture.py", line 167, in <module>
    stop_capture()
  File "/home/labauto2/Downloads/plrtest_june25/plrtest/plrtest/pylabrobot/pylabrobot/io/capture.py", line 100, in stop_capture
    capturer.stop()
  File "/home/labauto2/Downloads/plrtest_june25/plrtest/plrtest/pylabrobot/pylabrobot/io/capture.py", line 38, in stop
    json.dump(
  File "/usr/lib/python3.12/json/__init__.py", line 179, in dump
    for chunk in iterable:
  File "/usr/lib/python3.12/json/encoder.py", line 432, in _iterencode
    yield from _iterencode_dict(o, _current_indent_level)
  File "/usr/lib/python3.12/json/encoder.py", line 406, in _iterencode_dict
    yield from chunks
  File "/usr/lib/python3.12/json/encoder.py", line 439, in _iterencode
    o = _default(o)
        ^^^^^^^^^^^
  File "/usr/lib/python3.12/json/encoder.py", line 180, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '
TypeError: Object of type module is not JSON serializable

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions