def test_liquid_class_volume_calibration(self): assert self.lc._get_calibrated_volume(Unit(1, "ul"), self.tip_type) == Unit( 6, "ul" ) with pytest.raises(KeyError): self.lc._get_calibrated_volume(Unit(1, "ul"), "fake_tip_type")
def test_volume_calibration_calibrates_volume(self): volume = Unit(1.23, "uL") slope = 3.14 intercept = Unit(5, "uL") calibration = VolumeCalibrationBin(slope, intercept) assert (calibration.calibrate_volume(volume) == slope * volume + intercept)
def test_estimate_calibrated_volume_with_tip(self): calibrated_volume = Unit(5, "uL") calibrated_lc = LiquidClass(calibrated_volume=calibrated_volume) estimated_calibrated_volume = self.lhm._estimate_calibrated_volume( volume=Unit(1, "uL"), liquid=calibrated_lc, tip_type="test" ) assert estimated_calibrated_volume == calibrated_volume
class LiquidHandleMethodTester(object): single_shape = LiquidHandle.builders.shape(1, 1, "SBS96") preceding_z = LiquidHandle.builders.position_z( reference="preceding_position") empty_z = LiquidHandle.builders.position_z() well_top_z = LiquidHandle.builders.position_z(reference="well_top") well_top_transport = LiquidHandle.builders.transport( mode_params=LiquidHandle.builders.mode_params(position_z=well_top_z)) surface_z = LiquidHandle.builders.position_z(reference="liquid_surface") surface_transport = LiquidHandle.builders.transport( mode_params=LiquidHandle.builders.mode_params(position_z=surface_z)) surface_tracked_z = LiquidHandle.builders.position_z( reference="liquid_surface", detection_method="tracked") surface_sensing_z = LiquidHandle.builders.position_z( reference="liquid_surface", detection_method="capacitance") asp_transport = LiquidHandle.builders.transport( volume=Unit(1, "uL"), density=None, pump_override_volume=Unit(2, "uL"), flowrate=LiquidHandle.builders.flowrate(target=Unit(10, "uL/s")), delay_time=Unit(0.5, "s"), mode_params=LiquidHandle.builders.mode_params( liquid_class="air", position_z=LiquidHandle.builders.position_z( reference="preceding_position"))) @pytest.fixture(autouse=True) def setup(self): self.lhm = LiquidHandleMethod() self.lhm._shape = self.single_shape
def test_move_rate_builder(self): move_rate = { "target": Unit(50, "mm/s"), "acceleration": Unit(100, "mm/s/s") } assert LiquidHandle.builders.move_rate(**move_rate) == move_rate
class LiquidClassTester(object): tip_type = "generic_1_50" vol_bin_1 = VolumeCalibrationBin(3, "3:uL") vol_bin_5 = VolumeCalibrationBin(1, "1:uL") vol_calibration_curve = VolumeCalibration( (Unit("5:uL"), vol_bin_5), (Unit("1:uL"), vol_bin_1) ) volume_calibration = {tip_type: vol_calibration_curve} flow_bin_5 = LiquidHandle.builders.flowrate(target="3:uL/s") flow_bin_1 = LiquidHandle.builders.flowrate(target="7:uL/s") flowrate_calibration = { tip_type: VolumeCalibration( (Unit("5:uL"), flow_bin_5), (Unit("1:uL"), flow_bin_1) ) } @pytest.fixture(autouse=True) def setup(self): self.lc = LiquidClass() self.lc.volume_calibration_curve = self.volume_calibration self.lc.aspirate_flowrate_calibration_curve = self.flowrate_calibration self.lc.dispense_flowrate_calibration_curve = self.flowrate_calibration
def init_inventory_well(well, headers=TSC_HEADERS, org_name=ORG_NAME): """Initialize well (set volume etc) for Transcriptic""" def _container_url(container_id): return 'https://secure.transcriptic.com/{}/samples/{}.json'.format(org_name, container_id) #only initialize containers that have already been made if not well.container.id: return response = requests.get(_container_url(well.container.id), headers=headers) response.raise_for_status() container = response.json() well_data = list(filter(lambda w: w['well_idx'] == well.index,container['aliquots']))[0] well.name = "{}/{}".format(container["label"], well_data['name']) if well_data['name'] is not None else container["label"] well.properties = well_data['properties'] well.volume = Unit(well_data['volume_ul'], 'microliter') if 'ERROR' in well.properties: raise ValueError("Well {} has ERROR property: {}".format(well, well.properties["ERROR"])) if well.volume < Unit(20, "microliter"): logging.warn("Low volume for well {} : {}".format(well.name, well.volume)) return True
def test_unit_types(self): protocol_info = ProtocolInfo({ "name": "Test Basic Types", "inputs": { "volume": "volume", "time": "time", "temperature": "temperature", }, }) parsed = protocol_info.parse( self.protocol, { "refs": {}, "parameters": { "volume": "3:microliter", "time": "30:second", "temperature": "25:celsius", }, }, ) assert { "volume": Unit.fromstring("3:microliter"), "time": Unit.fromstring("30:second"), "temperature": Unit.fromstring("25:celsius"), } == parsed with pytest.raises(RuntimeError): parsed = protocol_info.parse( self.protocol, { "refs": {}, "parameters": { "volume": 3, "time": "30:second", "temperature": "25:celsius", }, }, ) parsed = protocol_info.parse( self.protocol, { "refs": {}, "parameters": { "volume": "3:microliter", "time": "hello", "temperature": "25:celsius", }, }, ) parsed = protocol_info.parse( self.protocol, { "refs": {}, "parameters": { "volume": "3:microliter", "time": "30:second", "temperature": 25, }, }, )
def test_position_z_builder(self): flat_position_z = { "reference": "liquid_surface", "offset": Unit(-1, "mm"), "move_rate": LiquidHandle.builders.move_rate(target="10:mm/s"), "detection_method": "capacitance", "detection_threshold": Unit(10, "picofarad"), "detection_duration": Unit(1, "millisecond"), "detection_fallback": LiquidHandle.builders.position_z(reference="well_top") } structured_position_z = { "reference": flat_position_z["reference"], "offset": flat_position_z["offset"], "move_rate": flat_position_z["move_rate"], "detection": { "method": flat_position_z["detection_method"], "threshold": flat_position_z["detection_threshold"], "duration": flat_position_z["detection_duration"], "fallback": flat_position_z["detection_fallback"] } } assert (LiquidHandle.builders.position_z(**structured_position_z) == LiquidHandle.builders.position_z(**flat_position_z) == structured_position_z) extra_detection_arguments_positions_z = { "reference": flat_position_z["reference"], "offset": flat_position_z["offset"], "move_rate": flat_position_z["move_rate"], "detection": { "method": flat_position_z["detection_method"], "threshold": flat_position_z["detection_threshold"], "duration": flat_position_z["detection_duration"], "fallback": flat_position_z["detection_fallback"], "sensitivity": 20, "offset": 20 } } assert (LiquidHandle.builders.position_z( **extra_detection_arguments_positions_z) == extra_detection_arguments_positions_z) with pytest.raises(ValueError): LiquidHandle.builders.position_z(reference="well_top", detection_method="capacitance") with pytest.raises(ValueError): LiquidHandle.builders.position_z( detection={"method": flat_position_z["detection_method"]}, **flat_position_z)
def test_get_sorted_tip_types(self): tip_types = [ TipType("generic_1_1000", Unit("1000:ul")), TipType("generic_1_50", Unit("50:ul")) ] self.lhm._get_tip_types = (lambda: tip_types) assert self.lhm._get_sorted_tip_types() == tip_types[::-1]
def test_rec_flowrates(self): assert ( self.lc._get_aspirate_flowrate(Unit(0.5, "ul"), "generic_1_50") == self.flow_bin_1 ) assert ( self.lc._get_dispense_flowrate(Unit(4.5, "ul"), "generic_1_50") == self.flow_bin_5 )
def test_flowrate_builder(self): flowrate = { "target": Unit(40, "uL/s"), "initial": Unit(30, "uL/s"), "cutoff": Unit(20, "uL/s"), "acceleration": Unit(10, "uL/s/s"), "deceleration": Unit(50, "uL/s/s"), } assert LiquidHandle.builders.flowrate(**flowrate) == flowrate
def test_rec_tip_type(self): assert self.transfer._rec_tip_type(Unit(20, "uL")) == "generic_1_50" # 24uL is the largest transfer vol that should use the 50ul tip assert self.transfer._rec_tip_type(Unit(24, "uL")) == "generic_1_50" # 50uL transfer uses larger tip because of overage_volume assert self.transfer._rec_tip_type(Unit(50, "uL")) == "generic_1_1000" with pytest.raises(RuntimeError): self.transfer._rec_tip_type(Unit(2000, "uL"))
def test_convert_string_to_unit(self): self.assertEqual(utils.convert_string_to_unit('100uM'), Unit('100:uM')) self.assertEqual(utils.convert_string_to_unit('100:uM'), Unit('100:uM')) self.assertEqual( utils.convert_string_to_unit('100nanogram/microliter'), Unit('100:nanogram/microliter'))
def test_transport_builder(self): transport = { "volume": Unit(1, "uL"), "density": None, "pump_override_volume": Unit(2, "uL"), "flowrate": LiquidHandle.builders.flowrate(target="2:uL/s"), "delay_time": Unit(5, "s"), "mode_params": LiquidHandle.builders.mode_params(liquid_class="air"), } assert LiquidHandle.builders.transport(**transport) == transport
def test_nozzle_position(self): assert Dispense.builders.nozzle_position() == {} reference = { "position_x": Unit(-3, "mm"), "position_y": Unit(3, "mm"), "position_z": Unit(5, "mm"), } pos = Dispense.builders.nozzle_position("-3:mm", "3:mm", "5:mm") assert pos == reference
def test_transports_with_denisty_builder(self): transport = { "volume": Unit(5, "uL"), "density": Unit(1, "mg/ml"), "pump_override_volume": Unit(2, "uL"), "flowrate": LiquidHandle.builders.flowrate(target="2:uL/s"), "delay_time": Unit(5, "s"), "mode_params": LiquidHandle.builders.mode_params(liquid_class="air"), } density = LiquidHandle.builders.transport(**transport)["density"] assert density == Unit(1, "mg/ml")
def test_shake_after(self): assert Dispense.builders.shake_after("5:second", "10:hertz", "landscape_linear", "1:mm") == { "duration": Unit(5, "second"), "frequency": Unit(10, "hertz"), "path": "landscape_linear", "amplitude": Unit(1, "millimeter"), } with pytest.raises(ValueError): Dispense.builders.shake_after("5:second", path="foo")
def test_unit_types(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { 'volume': 'volume', 'time': 'time', 'temperature': 'temperature' } }) parsed = protocol_info.parse( self.protocol, { 'refs': {}, 'parameters': { 'volume': '3:microliter', 'time': '30:second', 'temperature': '25:celsius' } }) self.assertEqual( { 'volume': Unit.fromstring('3:microliter'), 'time': Unit.fromstring('30:second'), 'temperature': Unit.fromstring('25:celsius') }, parsed) with self.assertRaises(RuntimeError): parsed = protocol_info.parse( self.protocol, { 'refs': {}, 'parameters': { 'volume': 3, 'time': '30:second', 'temperature': '25:celsius' } }) parsed = protocol_info.parse( self.protocol, { 'refs': {}, 'parameters': { 'volume': "3:microliter", 'time': "hello", 'temperature': '25:celsius' } }) parsed = protocol_info.parse( self.protocol, { 'refs': {}, 'parameters': { 'volume': "3:microliter", 'time': "30:second", 'temperature': 25 } })
def test_specified_point_params(self): test_vol = "vol" test_asp_flow = {"test": "asp"} test_dsp_flow = {"test": "dsp"} point_lc = LiquidClass(calibrated_volume=test_vol, aspirate_flowrate=test_asp_flow, dispense_flowrate=test_dsp_flow) assert (point_lc._get_calibrated_volume(Unit(0.5, "ul"), "generic_1_50") == test_vol) assert (point_lc._get_aspirate_flowrate(Unit( 0.5, "ul"), "generic_1_50") == test_asp_flow) assert (point_lc._get_dispense_flowrate(Unit( 0.5, "ul"), "generic_1_50") == test_dsp_flow)
def test_dispense_simple_with_density(self): tip_position = self.asp_transport["mode_params"]["tip_position"] self.lhm._dispense_simple( volume=self.asp_transport["volume"], calibrated_vol=self.asp_transport["pump_override_volume"], initial_z=self.well_top_z, position_x=tip_position["position_x"], position_y=tip_position["position_y"], flowrate=self.asp_transport["flowrate"], delay_time=self.asp_transport["delay_time"], liquid_class=self.asp_transport["mode_params"]["liquid_class"], density=Unit(1, "mg/ml")) assert self.lhm._transports[0] == self.well_top_transport assert self.lhm._transports[1]["density"] == Unit(1, "mg/ml")
def to_unit(item): try: if isinstance(item, str): item = Unit(item) except UnitError: pass return item
def serial_dilute_plus(protocol, params): params = make_dottable_dict(params) dilution_plate = protocol.ref("dilution plate", cont_type="96-flat", storage=params.storage_condition) # total_well_volume is 150 so that a factor of 2 dilution we don't exceed the well volume. total_well_volume = Unit(150, "microliter") num_of_dilutions = 8 wells = dilution_plate.wells_from(0, num_of_dilutions * len(params.samples), columnwise=True) protocol.dispense(dilution_plate, params.diluent, [{ 'column': i, 'volume': total_well_volume - (total_well_volume / params.samples[i]["dilution_factor"]) } for i in xrange(0, len(params.samples))]) for g in params["samples"]: protocol.transfer(g["sample"], dilution_plate.well(params.samples.index(g)), total_well_volume / g["dilution_factor"], mix_after=True) g["column"] = params.samples.index(g) for g in params["samples"]: well = g["column"] * 8 while well < g["column"] * 8 + 7: protocol.transfer(wells[well], wells[well + 1], total_well_volume / g["dilution_factor"], mix_after=True) well += 1
def test_aspirate_simple_with_density(self): tip_position = self.asp_transport["mode_params"]["tip_position"] self.lhm._aspirate_simple( # pylint: disable=invalid-unary-operand-type volume=-self.asp_transport["volume"], # pylint: disable=invalid-unary-operand-type calibrated_vol=-self.asp_transport["pump_override_volume"], initial_z=self.well_top_z, position_x=tip_position["position_x"], position_y=tip_position["position_y"], flowrate=self.asp_transport["flowrate"], delay_time=self.asp_transport["delay_time"], liquid_class=self.asp_transport["mode_params"]["liquid_class"], density=Unit(1, "mg/ml")) assert self.lhm._transports[0] == self.well_top_transport assert self.lhm._transports[1]["density"] == Unit(1, "mg/ml")
def test_aspirate_with_prime(self): prime_vol = Unit(5, "microliter") tip_position = self.asp_transport["mode_params"]["tip_position"] self.lhm._aspirate_with_prime( # pylint: disable=invalid-unary-operand-type volume=-self.asp_transport["volume"], prime_vol=prime_vol, # pylint: disable=invalid-unary-operand-type calibrated_vol=-self.asp_transport["pump_override_volume"], initial_z=self.well_top_z, position_x=tip_position["position_x"], position_y=tip_position["position_y"], asp_flowrate=self.asp_transport["flowrate"], dsp_flowrate=self.asp_transport["flowrate"], delay_time=self.asp_transport["delay_time"], liquid_class=self.asp_transport["mode_params"]["liquid_class"]) assert self.lhm._transports[0] == self.well_top_transport assert self.lhm._transports[2] == self.asp_transport prime_aspirate = self.asp_transport.copy() prime_dispense = self.asp_transport.copy() prime_aspirate["volume"] = -prime_vol prime_aspirate["pump_override_volume"] = -prime_vol prime_dispense["volume"] = prime_vol prime_dispense["pump_override_volume"] = prime_vol assert self.lhm._transports[1] == prime_aspirate assert self.lhm._transports[3] == prime_dispense
def test_estimate_calibrated_volume_without_tip(self): target_volume = Unit(1, "uL") volume_multiplier = LiquidClass()._safe_volume_multiplier estimated_calibrated_volume = self.lhm._estimate_calibrated_volume( volume=target_volume, liquid=LiquidClass(), tip_type=None ) assert estimated_calibrated_volume == target_volume * volume_multiplier
def test_estimate_calibrated_volume_with_tip_but_not_calibration(self): target_volume = Unit(1, "uL") volume_multiplier = LiquidClass()._safe_volume_multiplier estimated_calibrated_volume = self.lhm._estimate_calibrated_volume( volume=target_volume, liquid=LiquidClass(), tip_type="generic_96_180" ) assert estimated_calibrated_volume == target_volume * volume_multiplier
def test_unit_types(self): protocol_info = ProtocolInfo( {"name": "Test Basic Types", "inputs": {"volume": "volume", "time": "time", "temperature": "temperature"}} ) parsed = protocol_info.parse( self.protocol, {"refs": {}, "parameters": {"volume": "3:microliter", "time": "30:second", "temperature": "25:celsius"}}, ) self.assertEqual( { "volume": Unit.fromstring("3:microliter"), "time": Unit.fromstring("30:second"), "temperature": Unit.fromstring("25:celsius"), }, parsed, )
def test_blowout_builder(self): blowout = { "volume": Unit(3, "ul"), "initial_z": LiquidHandle.builders.position_z(offset="2:mm"), "flowrate": LiquidHandle.builders.flowrate(target="1:uL/s") } assert LiquidHandle.builders.blowout(**blowout) == blowout
def test_unit_types(self): protocol_info = ProtocolInfo({ 'name': 'Test Basic Types', 'inputs': { 'volume': 'volume', 'time': 'time', 'temperature': 'temperature' } }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': { 'volume': '3:microliter', 'time': '30:second', 'temperature': '25:celsius' } }) self.assertEqual({ 'volume': Unit.fromstring('3:microliter'), 'time': Unit.fromstring('30:second'), 'temperature': Unit.fromstring('25:celsius') }, parsed) with self.assertRaises(RuntimeError): parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': { 'volume': 3, 'time': '30:second', 'temperature': '25:celsius' } }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': { 'volume': "3:microliter", 'time': "hello", 'temperature': '25:celsius' } }) parsed = protocol_info.parse(self.protocol, { 'refs': {}, 'parameters': { 'volume': "3:microliter", 'time': "30:second", 'temperature': 25 } })
def test_get_mode_params(self): with pytest.raises(ValueError): Evaporate.builders.get_mode_params(mode="vortex", mode_params={"gas": "nitrogen"}) with pytest.raises(ValueError): Evaporate.builders.get_mode_params( mode="vortex", mode_params={"vortex_speed": Unit("200:ml/sec")}) test1 = Evaporate.builders.get_mode_params( mode="blowdown", mode_params={ "gas": "nitrogen", "vortex_speed": Unit("200:rpm"), "blow_rate": "200:uL/sec", }, ) assert test1["gas"] == "nitrogen"
def test_mix_builder(self): mix = { "volume": Unit(5, "ul"), "repetitions": 4, "initial_z": LiquidHandle.builders.position_z(offset="3:mm"), "asp_flowrate": LiquidHandle.builders.flowrate(target="1:uL/s"), "dsp_flowrate": LiquidHandle.builders.flowrate(target="2:uL/s") } assert LiquidHandle.builders.mix(**mix) == mix