def test_compound_units(self): u1 = Unit(20, 'microliter/second') u2 = Unit(30, 'microliter/second') assert (u1 < u2) assert (u2 > u1) assert (u1 + u2 == Unit(50, 'microliter/second')) assert (u1 - u2 == Unit(-10, 'microliter/second'))
def test_compound_units(self): u1 = Unit(20, "microliter/second") u2 = Unit(30, "microliter/second") assert u1 < u2 assert u2 > u1 assert u1 + u2 == Unit(50, "microliter/second") assert u1 - u2 == Unit(-10, "microliter/second")
def test_compound_units(self): u1 = Unit(20, 'microliter/second') u2 = Unit(30, 'microliter/second') self.assertTrue(u1 < u2) self.assertTrue(u2 > u1) self.assertEqual(u1 + u2, Unit(50, 'microliter/second')) self.assertEqual(u1 - u2, Unit(-10, 'microliter/second'))
def test_set_volume_unit_conv(self): self.c.well(0).set_volume("200:nanoliter") assert (self.c.well(0).volume == Unit(0.2, "microliter")) self.c.well(1).set_volume(".1:milliliter") assert (self.c.well(1).volume == Unit(100, "microliter")) with pytest.raises(ValueError): self.c.well(2).set_volume("1:milliliter")
def test_input_types(self): u1 = Unit("20.1:microliter") u2 = Unit(20.1, "microliter") u3 = Unit(Decimal("20.1"), "microliter") assert u1 == u2 == u3 assert isinstance(u1.magnitude, Decimal) with pytest.raises(UnitValueError): Unit(1j, "microliter")
def test_string_rounding(self): # Ensure that string representation is rounded assert ( str(Unit(0.1, "microliter") + Unit(0.2, "microliter")) == "0.3:microliter" ) # Currently we round to 12 decimal places by default assert str(Unit(0.1234567890123, "microliter")) == "0.123456789012:microliter" assert str(Unit(0.1234567890126, "microliter")) == "0.123456789013:microliter"
def test_generates_liquid_handle_with_density(self): self.p.transfer(self.flat.well(0), self.flat.well(0), "1:uL", density=Unit(1.1, "mg/ml")) inst = self.p.instructions[-1] assert inst.op == "liquid_handle" assert inst.data["locations"][0]["transports"][4]["density"] == Unit( 1.1, "mg/ml")
def test_updates_well_volume(self): source = self.flat.well(0) destination = self.flat.well(1) source_volume = Unit(30, "uL") volume = Unit(20, "uL") self.p.transfer(source.set_volume(source_volume), destination, volume) assert source.volume == source_volume - volume assert destination.volume == volume
def test_split_volume_transfer(self): self.p.transfer(self.deep.well(0), self.deep.well(1), "2000:uL") assert len(self.p.instructions) == 3 volumes = [ _.locations[1]["transports"][4]["volume"] for _ in self.p.instructions ] expected_volumes = [Unit(895, "uL"), Unit(895, "uL"), Unit(210, "uL")] assert volumes == expected_volumes
def test_comparison(self): u1 = Unit(20, 'microliter') u2 = Unit(30, 'microliter') self.assertFalse(u1 == u2) self.assertTrue(u1 == Unit(20, 'microliter')) self.assertTrue(u1 != u2) self.assertTrue(u1 < u2) self.assertTrue(u1 <= u2) self.assertFalse(u1 > u2) self.assertTrue(u2 > u1)
def test_arithmetic(self): u1 = Unit(20, "microliter") u2 = Unit(30, "microliter") assert Unit(50, "microliter") == u1 + u2 assert Unit(50, "microliter") == u2 + u1 assert Unit(-10, "microliter") == u1 - u2 assert Unit(10, "microliter") == u2 - u1 assert Unit(600, "microliter") == u2 * u1.magnitude assert Unit(600, "microliter") == u2.magnitude * u1 assert Unit(1.5, "microliter") == u2 / u1.magnitude assert Unit(1, "dimensionless") == u2 // u1
def test_dimensional_arithmetic(self): u1 = Unit(200, "microliter") u2 = Unit(3, "milliliter") assert Unit(3200, "microliter") == u1 + u2 assert Unit(3.2, "milliliter") == u2 + u1 assert Unit(-2800, "microliter") == u1 - u2 assert Unit(2.8, "milliliter") == u2 - u1 assert Unit(0.6, "milliliter**2") == u2 * u1 assert Unit(600000, "microliter**2") == u1 * u2 assert Unit(15, "dimensionless") == u2 / u1 assert Unit(0.066666667, "dimensionless") == (u1 / u2).round(9)
def test_arithmetic(self): u1 = Unit(20, 'microliter') u2 = Unit(30, 'microliter') assert (Unit(50, 'microliter') == u1 + u2) assert (Unit(50, 'microliter') == u2 + u1) assert (Unit(-10, 'microliter') == u1 - u2) assert (Unit(10, 'microliter') == u2 - u1) assert (Unit(600, 'microliter') == u2 * u1._magnitude) assert (Unit(600, 'microliter') == u2._magnitude * u1) assert (Unit(1.5, 'microliter') == u2 / u1._magnitude) assert (Unit(1, 'dimensionless') == u2 // u1)
def test_dimensional_arithmetic(self): u1 = Unit(200, 'microliter') u2 = Unit(3, 'milliliter') assert Unit(3200, 'microliter') == u1 + u2 assert Unit(3.2, 'milliliter') == u2 + u1 assert Unit(-2800, 'microliter') == u1 - u2 assert Unit(2.8, 'milliliter') == u2 - u1 assert Unit(0.6, 'milliliter**2') == u2 * u1 assert Unit(600000, 'microliter**2') == u1 * u2 assert Unit(15, 'dimensionless') == u2 / u1 assert Unit(0.066666667, 'dimensionless') == (u1 / u2).round(9)
def test_arithmetic(self): u1 = Unit(20, 'microliter') u2 = Unit(30, 'microliter') self.assertEqual(Unit(50, 'microliter'), u1 + u2) self.assertEqual(Unit(50, 'microliter'), u2 + u1) self.assertEqual(Unit(-10, 'microliter'), u1 - u2) self.assertEqual(Unit(10, 'microliter'), u2 - u1) self.assertEqual(Unit(600, 'microliter'), u2 * u1.value) self.assertEqual(Unit(1.5, 'microliter'), u2 / u1.value) self.assertEqual(Unit(1, 'microliter'), u2 // u1)
def __init__(self, shortname, description): """ Parameters ---------- shortname : str A short name for the solution. (e.g. 'buffer') description: A descriptive name for the solution (e.g. '20 mM Tris 50 mM NaCl') """ self.shortname = shortname self.description = description self.species = None self.concentration = Unit(0.0, 'moles/liter') self.uncertainty = Unit(0.0, 'moles/liter')
def test_comparison(self): u1 = Unit(20, "microliter") u2 = Unit(30, "microliter") u3 = Unit(1, "milliliter") assert u1 != u2 assert u1 == Unit(20, "microliter") assert u1 != u2 assert u1 < u2 assert u1 <= u2 assert u1 <= u2 assert u2 > u1 assert u1 < u2 assert u2 >= u1 assert u3 > u1 assert u2 < u3
def test_comparison(self): u1 = Unit(20, 'microliter') u2 = Unit(30, 'microliter') u3 = Unit(1, 'milliliter') assert (u1 != u2) assert (u1 == Unit(20, 'microliter')) assert (u1 != u2) assert (u1 < u2) assert (u1 <= u2) assert (u1 <= u2) assert (u2 > u1) assert (u1 < u2) assert (u2 >= u1) assert (u3 > u1) assert (u2 < u3)
def __init__(self, dmso_stock): """ Parameters ---------- dmso_stock : dict The dictionary containing 'id', 'compound_name', 'compound mass (mg)', 'molecular weight', 'purity', 'solvent_mass' """ self.shortname = dmso_stock['id'] self.species = dmso_stock['compound name'] self.description = '10 mM ' + dmso_stock['compound name'] + ' DMSO stock' dmso_density = Unit(1.1004, 'grams/milliliter') mass_uncertainty = 0.01 # TODO: Calculate from balance precision concentration = Unit(dmso_stock['compound mass (mg)'], 'milligrams') * dmso_stock['purity'] / Unit(dmso_stock['molecular weight'], 'grams/mole') / (Unit(dmso_stock['solvent mass (g)'], 'grams') / dmso_density) # mol/liter self.concentration = concentration.to('moles/liter') self.uncertainty = mass_uncertainty * self.concentration self.buffer = DMSO
def sample_protocol(protocol, params): dest_plate = params["destination_plate"] wells_to_measure = [] for location in params["dye_locations"]: protocol.transfer(params["dye"], dest_plate.well(location["well_index"]), location["volume"]) if location["volume"] != Unit(100, "microliter"): protocol.transfer(params["water"], dest_plate.well(location["well_index"]), Unit(100, "microliter") - location["volume"], mix_after=True) wells_to_measure.append(location["well_index"]) protocol.absorbance(dest_plate, wells_to_measure, "475:nanometer", "test")
def provision_assay_plate(name, plate_type='4titude 4ti-0223', id=None): """ Provision a new assay plate. Parameters ---------- name : str The name of the container plate_type : str, optional, default='4titude 4ti-0223' The name of the plate type used to retrieve the `container_type` from library id : str, optional, default=None Unless `id` is specified, a unique container ID will be autogenerated. """ if id == None: id = generate_uuid # Define the container container_type = container_types[plate_type] container = Container(name="assay-plate", id=id, container_type=container_type) # Initialize well properties for this container for well in container.all_wells(): well.set_volume(Unit(0.0, 'microliters')) # well starts empty return container
def measure_absorbance(self, record: paml.ActivityNodeExecution): results = {} call = record.call.lookup() parameter_value_map = call.parameter_value_map() wl = parameter_value_map["wavelength"]["value"] wl_units = tyto.OM.get_term_by_uri(wl.unit) samples = parameter_value_map["samples"]["value"] wells = self.var_to_entity[samples] measurements = parameter_value_map["measurements"]["value"] # HACK extract contrainer from well group since we do not have it as input container = wells[0].container l.debug(f"measure_absorbance:") l.debug(f" container: {container}") l.debug(f" samples: {samples}") l.debug(f" wavelength: {wl.value} {wl_units}") self.protocol.spectrophotometry( dataref=measurements, obj=container, groups=Spectrophotometry.builders.groups([ Spectrophotometry.builders.group( "absorbance", Spectrophotometry.builders.absorbance_mode_params( wells=wells, wavelength=Unit(wl.value, wl_units), num_flashes=None, settle_time=None, read_position=None, position_z=None)) ])) return results
def test_single_transfer(self): p = Protocol() c = p.ref("test", None, "96-flat", discard=True) p.transfer(c.well(0), c.well(1), "20:microliter") self.assertEqual(Unit(20, "microliter"), c.well(1).volume) self.assertEqual(None, c.well(0).volume) self.assertTrue("transfer" in p.instructions[-1].groups[-1])
def test_one_source(self): p = Protocol() c = p.ref("test", None, "96-flat", discard=True) with self.assertRaises(RuntimeError): p.transfer(c.wells_from(0, 2), c.wells_from(2, 2), "40:microliter", one_source=True) with self.assertRaises(RuntimeError): p.transfer(c.wells_from(0, 2).set_volume("1:microliter"), c.wells_from(1, 5), "10:microliter", one_source=True) p.transfer(c.wells_from(0, 2).set_volume("50:microliter"), c.wells_from(2, 2), "40:microliter", one_source=True) self.assertEqual(2, len(p.instructions[0].groups)) self.assertFalse(p.instructions[0].groups[0]["transfer"][0]["from"] == p.instructions[0].groups[1]["transfer"][0]["from"]) p.transfer(c.wells_from(0, 2).set_volume("100:microliter"), c.wells_from(2, 4), "40:microliter", one_source=True) self.assertEqual(7, len(p.instructions[0].groups)) self.assertTrue(p.instructions[0].groups[2]["transfer"][0]["from"] == p.instructions[0].groups[4]["transfer"][0]["from"]) self.assertTrue(p.instructions[0].groups[4]["transfer"][0]["volume"] == Unit.fromstring("20:microliter")) p.transfer(c.wells_from(0, 2).set_volume("100:microliter"), c.wells_from(2, 4), ["20:microliter", "40:microliter", "60:microliter", "80:microliter"], one_source=True) self.assertEqual(12, len(p.instructions[0].groups)) self.assertTrue(p.instructions[0].groups[7]["transfer"][0]["from"] == p.instructions[0].groups[9]["transfer"][0]["from"]) self.assertFalse(p.instructions[0].groups[9]["transfer"][0]["from"] == p.instructions[0].groups[10]["transfer"][0]["from"]) self.assertEqual(Unit.fromstring("20:microliter"), p.instructions[0].groups[10]["transfer"][0]["volume"]) p.transfer(c.wells_from(0, 2).set_volume("50:microliter"), c.wells(2), "100:microliter", one_source=True) c.well(0).set_volume("50:microliter") c.well(1).set_volume("200:microliter") p.transfer(c.wells_from(0, 2), c.well(1), "100:microliter", one_source=True) self.assertFalse(p.instructions[0].groups[14]["transfer"][0]["from"] == p.instructions[0].groups[15]["transfer"][0]["from"]) c.well(0).set_volume("100:microliter") c.well(1).set_volume("0:microliter") c.well(2).set_volume("100:microliter") p.transfer(c.wells_from(0, 3), c.wells_from(3, 2), "100:microliter", one_source=True) p = Protocol() c = p.ref("test", None, "96-flat", discard=True) c.well(0).set_volume("100.0000000000005:microliter") c.well(1).set_volume("100:microliter") p.transfer(c.wells_from(0, 2), c.wells_from(3, 3), "50:microliter", one_source=True) self.assertEqual(3, len(p.instructions[0].groups)) p = Protocol() c = p.ref("test", None, "96-flat", discard=True) c.well(0).set_volume("50:microliter") c.well(1).set_volume("101:microliter") p.transfer(c.wells_from(0, 2), c.wells_from(3, 3), "50.0000000000005:microliter", one_source=True) self.assertEqual(3, len(p.instructions[0].groups))
def test_echo_max_vol(self): from autoprotocol.protocol import Protocol p = Protocol() echo_w = p.ref("echo", None, "384-echo", discard=True).well(0) echo_w.set_volume("135:microliter") assert echo_w.volume == Unit(135, "microliter") with pytest.raises(ValueError): echo_w.set_volume("136:microliter")
def dummy_type(): return ContainerType( name="dummy", well_count=15, well_depth_mm=None, well_volume_ul=Unit(200, "microliter"), well_coating=None, sterile=False, is_tube=False, cover_types=[], seal_types=None, capabilities=[], shortname="dummy", col_count=5, dead_volume_ul=Unit(15, "microliter"), safe_min_volume_ul=Unit(30, "microliter") )
def _create_extinction_coefficients_model(self): """ Determine all spectroscopic wavelengths in use and create model of extinction coefficients Populates the following fields: * parameter_names['extinction coefficients'] : all extinction coefficients * all_wavelengths : list of all wavelengths in use * absorbance : True if absorbance in use * fluorescence : True if fluorescence in use """ # # Spectroscopic measurements # # TODO: Switch to log extinction coefficients and uniform prior in log extinction coefficients MIN_EXTINCTION_COEFFICIENT = Unit(0.1, '1/(moles/liter)/centimeter') # maximum physically reasonable extinction coefficient MAX_EXTINCTION_COEFFICIENT = Unit(100e3, '1/(moles/liter)/centimeter') # maximum physically reasonable extinction coefficient EXTINCTION_COEFFICIENT_GUESS = Unit(1.0, '1/(moles/liter)/centimeter') # maximum physically reasonable extinction coefficient # Determine all wavelengths and detection technologies in use self.all_wavelengths = set() for well in self.wells: measurements = well.properties['measurements'] if 'absorbance' in measurements: for wavelength in measurements['absorbance'].keys(): self.all_wavelengths.add(wavelength) if 'fluorescence' in measurements: for (excitation_wavelength, emission_wavelength, geometry) in measurements['fluorescence'].keys(): self.all_wavelengths.add(excitation_wavelength) self.all_wavelengths.add(emission_wavelength) print("all wavelengths in use:") print(self.all_wavelengths) if (len(self.all_wavelengths) > 0): # Priors for spectroscopic parameters of each component self.parameter_names['extinction coefficients'] = list() for species in self.all_species: for wavelength in self.all_wavelengths: name = 'log extinction coefficient of %s at wavelength %s' % (species, wavelength) log_extinction_coefficient = pymc.Uniform(name, lower=np.log(MIN_EXTINCTION_COEFFICIENT.to_base_units().m), upper=np.log(MAX_EXTINCTION_COEFFICIENT.to_base_units().m), value=np.log(EXTINCTION_COEFFICIENT_GUESS.to_base_units().m)) # extinction coefficient or molar absorptivity for ligand, units of 1/M/cm self.model[name] = log_extinction_coefficient self.parameter_names['extinction coefficients'].append(name)
def test_conversion(self): assert (Unit(200, 'centimeter').to('meter') == Unit(2, 'meter')) assert (Unit(20, 'microliter/second').to('liter/hour') == Unit( 0.072, 'liter / hour')) # Due to floating point imprecision, use AlmostEqual as the test # condition assert almost_equal( Unit(1000, 'microliter').to('milliliter'), Unit(1, 'milliliter'), Unit(10**-12, 'milliliter'))
def test_multiple_sources(self): p = Protocol() c = p.ref("test", None, "96-flat", discard=True) with self.assertRaises(AssertionError): p.consolidate(c.wells_from(0, 3), c.wells_from(2, 3), "10:microliter") p.consolidate(c.wells_from(0, 3), c.well(4), ["10:microliter"]) p.consolidate(c.wells_from(0, 3), c.well(4), "10:microliter") self.assertEqual(Unit(30, "microliter"), c.well(4).volume) self.assertEqual( 3, len(p.instructions[0].groups[0]["consolidate"]["from"]))
def test_updates_well_volume(self): source_volume = Unit(30, "uL") volume = Unit(20, "uL") row_count = self.flat.container_type.row_count() source_origin = self.flat.well(0) source_wells = self.flat.wells_from( source_origin, row_count, columnwise=True).set_volume(source_volume) destination_origin = self.flat.well(1) destination_wells = self.flat.wells_from(destination_origin, row_count, columnwise=True) self.p.transfer(source_origin, destination_origin, volume, rows=row_count) assert all(_.volume == source_volume - volume for _ in source_wells) assert all(_.volume == volume for _ in destination_wells)
def dummy_echo(): return Container( None, ContainerType( name="dummy", well_count=384, well_depth_mm=None, well_volume_ul=Unit(65, "microliter"), well_coating=None, sterile=False, is_tube=False, cover_types=[], seal_types=None, capabilities=[], shortname="dummy", col_count=96, dead_volume_ul=Unit(15, "microliter"), safe_min_volume_ul=Unit(15, "microliter"), true_max_vol_ul=Unit(135, "microliter"), vendor="Labcyte" ) )
def define_container_types(): # # Define assay plate container # container_types = dict() # Define the container type for 4titude 4ti-0223. # info: http://4ti.co.uk/microplates/black-clear-bottom/96-well/ # drawing: http://4ti.co.uk/files/1614/0542/7662/4ti-0223_Marketing_Drawing.pdf # All arguments to ContainerType are required! capabilities = [ 'pipette', 'spin', 'absorbance', 'fluorescence', 'luminescence', 'incubate', 'gel_separate', 'cover', 'seal', 'stamp', 'dispense' ] container_type = ContainerType(name='4titude 4ti-0223', is_tube=False, well_count=96, well_depth_mm=Unit(11.15, 'millimeter'), well_volume_ul=Unit(300, 'microliter'), well_coating='polystyrene', sterile=False, cover_types=[], seal_types=[], capabilities=capabilities, shortname='4ti-0223', col_count=12, dead_volume_ul=Unit(20, 'microliter'), safe_min_volume_ul=Unit(50, 'microliter')) # Attach well area. well_diameter = Unit(6.30, "millimeters") well_area = np.pi * (well_diameter / 2)**2 setattr(container_type, 'well_area', well_area) container_types[container_type.name] = container_type return container_types
def test_units_match(self): with pytest.raises(ValueError): Unit(20, 'microliter') + Unit(30, 'second') with pytest.raises(ValueError): Unit(20, 'microliter') - Unit(30, 'second') with pytest.raises(ValueError): Unit(20, 'microliter') < Unit(30, 'second')
def thermocycle_ramp(start_temp, end_temp, total_duration, step_duration): ''' Create a ramp instruction for the thermocyler. Used in annealing protocols. ''' assert Unit.fromstring(total_duration).unit == Unit.fromstring(step_duration).unit, ("Thermocycle_ramp durations" " must be specified using the" " same unit of time.") thermocycle_steps = [] start_temp = Unit.fromstring(start_temp).value num_steps = int(Unit.fromstring(total_duration).value // Unit.fromstring(step_duration).value) step_size = (Unit.fromstring(end_temp).value - start_temp) // num_steps for i in xrange(0, num_steps): thermocycle_steps.append({ "temperature": "%d:celsius" % (start_temp + i * step_size), "duration": step_duration }) return thermocycle_steps
def test_fromstring(self): self.assertEqual(Unit.fromstring("20:microliter"), Unit(20,'microliter'))
def volume_check(well, usage_volume=0, use_safe_vol=False, use_safe_dead_diff=False): """Basic Volume check Checks to see if the designated well has usage_volume above the well's dead volume. In other words, this method checks if usage_volume can be pipetted out of well. Example Usage: .. code-block:: python from autoprotocol import Protocol from autoprotocol_utilities.container_helpers import volume_check p = Protocol() example_container = p.ref(name="exampleplate", id=None, cont_type="96-pcr", storage="warm_37") p.dispense(ref=example_container, reagent="water", columns=[{"column": 0, "volume": "10:microliters"}]) #Checks if there are 5 microliters above the dead volume #available in well 0 assert (volume_check(well=example_container.well(0), usage_volume=5)) is None #Checks if the volume in well 0 is at least the safe minimum volume assert (volume_check(well=example_container.well(0), usage_volume=0, use_safe_vol=True) is None Parameters ---------- well : Well, WellGroup, list Well(s) to test usage_volume : Unit, str, int, float, optional Volume to test for. If 0 the aliquot will be tested against the container dead volume. If int or float is used, microliter will be assumed. use_safe_vol : bool, optional Use safe minimum volume instead of dead volume use_safe_dead_diff : bool, optional Use the safe_minimum_volume - dead_volume as the required amount. Useful if `set_pipettable_volume()` was used before to correct the well_volume to not include the dead_volume anymore Returns ------- str string of errors if volume check failed OR None If no errors are detected Raises ------ ValueError If well is not of type Well, list or WellGroup ValueError If elements of well are not of type Well """ assert isinstance(well, (Well, WellGroup, list)) if isinstance(well, Well): well = [well] error_message = [] # noinspection PyTypeChecker for aliquot in well: assert isinstance(aliquot, Well) if isinstance(usage_volume, (int, float)): usage_volume = Unit(usage_volume, "microliter") if isinstance(usage_volume, string_type): usage_volume = int(usage_volume.split(":microliter")[0]) if not aliquot.volume: error_message.append( "Your aliquot does not have a volume. (%s) We assume 0 uL " "for this test." % aliquot) correction_vol = aliquot.container.container_type.dead_volume_ul message_string = "dead volume" volume = Unit(0, "microliter") if aliquot.volume: volume = aliquot.volume if use_safe_vol: correction_vol = \ aliquot.container.container_type.safe_min_volume_ul message_string = "safe minimum volume" elif use_safe_dead_diff: correction_vol = \ aliquot.container.container_type.safe_min_volume_ul - \ aliquot.container.container_type.dead_volume_ul message_string = "safe minimum volume" volume = volume + aliquot.container.container_type.dead_volume_ul test_vol = correction_vol + usage_volume if test_vol > volume: if usage_volume == 0: error_message.append( "You want to pipette from a container with {:~P} {!s}. " "However, your aliquot: {!s}, only has {:~P}.".format( correction_vol, message_string, well_name(aliquot), volume)) else: error_message.append( "You want to pipette {:~P} from a container with {:~P} " "{!s} ({:~P} total). However, your aliquot: {!s}, only has" " {:~P}.".format( usage_volume, correction_vol, message_string, usage_volume + correction_vol, well_name(aliquot), volume)) if error_message: error_message = str(len(error_message)) + " volume errors: " + \ ", ".join(error_message) else: error_message = None return error_message
def thermocycle_ramp(start_temp, end_temp, total_duration, step_duration): """Create a ramp instruction for the thermocyler. Create a multi-temperature thermocycling program commonly used in annealing protocols. Based on total time and the step duration this function computes the temperature increment required for each step within the start and the end temperature. Parameters ---------- start_temp: string, int, float, Unit Start of the thermocycle protocol, in the format "37:celsius" end_temp: string, int, float, Unit End of the thermocycle protocol, in the format "37:celsius" total_duration: string, Unit Total duration of the thermocycle protocol, in the format "1:hour" step_duration: string, Unit Time that each temperature should be held, in the format "1:minute" Example ------- .. code-block:: python therm = thermocycle_ramp(65, 95, "30:minute", "1:minute") protocol.thermocycle(dest_plate, therm, volume="15:microliter") Returns ------- dict containing thermocycling steps that can be used in the thermocycle instruction Raises ------ ValueError If either temperature is not of type `int`, `float`, `string` or `Unit` and if either duration is not of type `string` or `Unit` """ assert isinstance(start_temp, (int, float, string_type, Unit)) assert isinstance(end_temp, (int, float, string_type, Unit)) assert isinstance(total_duration, (string_type, Unit)) assert isinstance(step_duration, (string_type, Unit)) if isinstance(start_temp, string_type): start_temp = Unit.fromstring(start_temp) elif isinstance(start_temp, (int, float)): start_temp = Unit(start_temp, 'degC') if isinstance(end_temp, string_type): end_temp = Unit.fromstring(end_temp) elif isinstance(end_temp, (int, float)): end_temp = Unit(end_temp, 'degC') if isinstance(total_duration, string_type): total_duration = Unit.fromstring(total_duration) if isinstance(step_duration, string_type): step_duration = Unit.fromstring(step_duration) start_temp.ito('degC') end_temp.ito('degC') total_duration.ito_base_units() step_duration.ito_base_units() num_steps = int(total_duration // step_duration) step_size = (end_temp - start_temp).magnitude // num_steps thermocycle_steps = [] for i in range(num_steps + 1): thermocycle_steps.append({ "temperature": "%s:celsius" % ( start_temp.magnitude + i * step_size), "duration": str(step_duration) }) return thermocycle_steps
def molar_to_mass_conc(length, molar, ds=True): """ For the DNA molarity given, return the mass concentration of DNA Example Usage: .. code-block:: python from autoprotocol_utilities import molar_to_mass_conc from autoprotocol_utilities import dna_mole_to_mass from autoprotocol.unit import Unit dna_length = 5000 dna_molarity = Unit(10, 'uM') molar_to_mass_conc(dna_length, dna_molarity) Returns: .. code-block:: python Unit(33000.0, 'nanogram / microliter') Parameters ---------- length: int Length of DNA in bp molar: str, Unit Molarity of DNA in prefix-M ds: bool, optional True for dsDNA, False for ssDNA Returns ------- mass_conc: Unit Mass concentration of DNA in ng/uL Raises ------ ValueError If inputs are not of specified types """ if not isinstance(length, int): raise ValueError( "Length of DNA is of type %s, must be of type " "integer" % type(length)) if isinstance(molar, str): molar = Unit.fromstring(molar) if not (isinstance(molar, Unit) and str(molar.dimensionality) == '[substance] / [length] ** 3'): raise ValueError( "Molar concentration of DNA must be of type string or Unit") if not isinstance(ds, bool): raise ValueError( "ds is of type %s, must be of type bool: True for dsDNA, " "False for ssDNA" % type(ds)) dna_umole = Unit((molar / Unit(1, "M")).magnitude, "umol") dna_ug = dna_mole_to_mass(length, dna_umole, ds) mass_conc = Unit(dna_ug.magnitude * 1000, "ng/uL") return mass_conc
def mass_conc_to_molar(length, mass_conc, ds=True): """ For the DNA mass concentration given, return the molarity of DNA Example Usage: .. code-block:: python from autoprotocol_utilities import mass_conc_to_molar from autoprotocol_utilities import dna_mass_to_mole from autoprotocol.unit import Unit dna_length = 5000 dna_mass_conc = Unit(33, 'ng/uL') mass_conc_to_molar(dna_length, dna_mass_conc) Returns: .. code-block:: python Unit(0.01, 'micromolar') Parameters ---------- length: int Length of DNA in bp mass_conc: str, Unit Mass concentration of DNA ds: bool, optional True for dsDNA, False for ssDNA Returns ------- molar: Unit Molarity of DNA in uM Raises ------ ValueError If inputs are not of specified types """ if not isinstance(length, int): raise ValueError( "Length of DNA is of type %s, must be of type " "integer" % type(length)) if isinstance(mass_conc, str): mass_conc = Unit.fromstring(mass_conc) if not isinstance(mass_conc, Unit) or \ str(mass_conc.dimensionality) != '[mass] / [length] ** 3': raise ValueError("Mass concentration of DNA must be of type Unit") if not isinstance(ds, bool): raise ValueError( "ds is of type %s, must be of type bool: True for dsDNA, " "False for ssDNA" % type(ds)) dna_ng = Unit((mass_conc / Unit(1, "ng/uL")).magnitude, "ng") dna_pmol = dna_mass_to_mole(length, dna_ng, ds) dna_molar = Unit(round(dna_pmol.magnitude, 9), "uM") return dna_molar
def ligation_insert_ng(plasmid_size, plasmid_mass, insert_size, molar_ratio=1): """ For the plasmid size, plasmid amount, insert size, and molar ratio given, return the mass of insert needed for ligation Different from ligation_insert_volume: no insert concentration is given -> returns mass of insert needed Example Usage: .. code-block:: python from autoprotocol_utilities import ligation_insert_ng from autoprotocol.unit import Unit plasmid_size = 3000 plasmid_mass = Unit(100, 'ng') insert_size = 48 ligation_insert_ng(plasmid_size, plasmid_mass, insert_size) Returns: .. code-block:: python Unit(1.6, 'nanogram') Parameters ---------- plasmid_size : int Length of plasmid in bp. insert_size: int Length of insert in bp plasmid_mass : str, Unit Mass of plasmid in prefix-g molar_ratio : int, float, string, optional Ligation molar ratio of insert : vector. By default it is 1 : 1. Generally ligations are tested at 1:3, 1:1, and 3:1 Returns ------- insert_amount: Unit Amount of insert solution needed in ng Raises ------ ValueError If wells are not of type list, WellGroup or Container """ # Check input types if not isinstance(plasmid_size, int): raise ValueError("Plasmid_size: must be an integer") if not isinstance(insert_size, int): raise ValueError("insert_size: must be an integer") if type(molar_ratio) == str: molar_ratio = float( molar_ratio.split(":")[0]) / float(molar_ratio.split(":")[1]) if type(molar_ratio) not in (int, float): raise ValueError( "molar_ratio: must be an int, float, or string in the form " "of int:int") if isinstance(plasmid_mass, str): plasmid_mass = Unit.fromstring(plasmid_mass) if not (isinstance(plasmid_mass, Unit) and str(plasmid_mass.dimensionality) == "[mass]"): raise ValueError( "Plasmid amount must be of type str or Unit in prefix-g") length_ratio = float(insert_size) / float(plasmid_size) plasmid_ng = plasmid_mass.to("ng") insert_ng = plasmid_ng * length_ratio * molar_ratio return insert_ng
def dna_mass_to_mole(length, mass, ds=True): """ For the DNA Length and mass given, return the mole amount of DNA Example Usage: .. code-block:: python from autoprotocol_utilities import dna_mass_to_mole from autoprotocol.unit import Unit dna_length = 100 dna_mass = Unit(33, 'ng') dna_mass_to_mole(dna_length, dna_mass) Returns: .. code-block:: python Unit(0.5, 'picomole') Parameters ---------- length: int Length of DNA in bp mass: str, Unit Weight of DNA in prefix-g ds: bool, optional True for dsDNA, False for ssDNA Returns ------- pmole_dna: Unit Mole amount of DNA in pmol Raises ------ ValueError If inputs are not of specified types """ if isinstance(mass, str): mass = Unit.fromstring(mass) if not isinstance(mass, Unit) or str(mass.dimensionality) != "[mass]": raise ValueError("Mass of DNA must be of type Unit in prefix-gram") if not isinstance(length, int): raise ValueError( "Length of DNA is of type %s, must be of type " "integer" % type(length)) if not isinstance(ds, bool): raise ValueError( "ds is of type %s, must be of type bool: True for dsDNA, " "False for ssDNA" % type(ds)) dna_pg = mass.to("pg") if ds: dna_pmol = dna_pg / (Unit(660, "pg/pmol") * length) else: dna_pmol = dna_pg / (Unit(330, "pg/pmol") * length) return dna_pmol
def ligation_insert_volume(plasmid_size, plasmid_mass, insert_size, insert_conc, ds=True, molar_ratio=1): """ For the plasmid size, plasmid amount, insert size, insert concentration, and molar ratio given, return the volume of insert solution needed for ligation Different from ligation_insert_ng: insert concentration is given -> returns volume of insert solution needed Example Usage: .. code-block:: python from autoprotocol_utilities import ligation_insert_volume from autoprotocol_utilities import molar_to_mass_conc from autoprotocol.unit import Unit plasmid_size = 3000 plasmid_mass = Unit(100, 'ng') insert_size = 48 insert_conc = Unit(25, 'ng/uL') ligation_insert_volume(plasmid_size, plasmid_mass, insert_size, insert_conc) Returns: .. code-block:: python Unit(0.064, 'microliter') Parameters ---------- plasmid_size : int Length of plasmid in bp. plasmid_mass : str, Unit Mass of plasmid in prefix-g insert_size: int Length of insert in bp insert_conc: str, Unit Molar or mass concentration of insert ds: bool, optional True for dsDNA, False for ssDNA molar_ratio : int, float, string, optional Ligation molar ratio of insert : vector. Common ratios are 1:3, 1:1, and 3:1. 1:1 by default Returns ------- insert_amount: Unit Volume of insert solution needed in uL Raises ------ ValueError If wells are not of type list, WellGroup or Container """ conc_dimension = ["[substance] / [length] ** 3", '[mass] / [length] ** 3'] # Check input types if not isinstance(plasmid_size, int): raise ValueError("Plasmid_size: must be an integer") if isinstance(plasmid_mass, str): plasmid_mass = Unit.fromstring(plasmid_mass) if not isinstance(plasmid_mass, Unit) and \ str(plasmid_mass.dimensionality) == "[mass]": raise ValueError( "Plasmid mass must be of type str or Unit in prefix-g") if not isinstance(insert_size, int): raise ValueError("insert_size: must be an integer") if isinstance(insert_conc, str): insert_conc = Unit.fromstring(insert_conc) if not (isinstance(insert_conc, Unit) and str(insert_conc.dimensionality) in conc_dimension): raise ValueError( "Plasmid concentration must be of type Unit in prefix-M or " "prefix-g / prefix-L ") if not isinstance(ds, bool): raise ValueError( "ds is of type %s, must be of type bool: True for dsDNA, " "False for ssDNA" % type(ds)) if type(molar_ratio) == str: molar_ratio = float( molar_ratio.split(":")[0]) / float(molar_ratio.split(":")[1]) if type(molar_ratio) not in (int, float): raise ValueError( "molar_ratio: must be an int, float, or string in the " "form of int:int") len_ratio = float(insert_size) / float(plasmid_size) plasmid_ng = plasmid_mass.to("ng") insert_ng = plasmid_ng * len_ratio * molar_ratio # Convert concentration to ng/uL if str(insert_conc.dimensionality) == conc_dimension[0]: insert_conc = molar_to_mass_conc(insert_size, insert_conc, ds) else: insert_conc = insert_conc.to("ng/uL") insert_vol = insert_ng / insert_conc return insert_vol
def ligation_insert_amount(plasmid_size, plasmid_conc, plasmid_volume, insert_size, insert_conc, ds=True, molar_ratio=1): """ For the plasmid size, plasmid concentration, insert size, insert concentration, and molar ratio given, return the volume of insert solution needed for ligation Different form ligation_insert_volume: plasmid concentration and volume are given instead of plasmid mass Example Usage: .. code-block:: python from autoprotocol_utilities import ligation_insert_amount from autoprotocol_utilities import molar_to_mass_conc from autoprotocol.unit import Unit plasmid_size = 2000 plasmid_conc = '1.5:uM' plasmid_volume = Unit(10, 'uL') insert_size = 25 insert_conc = Unit(10, 'ng/uL') ligation_insert_amount(plasmid_size, plasmid_conc, plasmid_volume, insert_size, insert_conc) Returns: .. code-block:: python Unit(24.75, 'microliter') Parameters ---------- plasmid_size : int Length of plasmid in bp. plasmid_conc : str, Unit Molar or mass concentration of plasmid solution plasmid_volume: str, Unit Volume of plasmid solution in prefix-L insert_size: int Length of insert in bp insert_conc : str, Unit Molar or mass concentration of insert solution ds: bool, optional True for dsDNA, False for ssDNA molar_ratio : int, float, string, optional Ligation molar ratio of insert : vector. Common ratios are 1:3, 1:1, and 3:1. 1:1 by default Returns ------- insert_amount: Unit Volume of insert solution in uL Raises ------ ValueError If wells are not of type list, WellGroup or Container """ # Check input types if not isinstance(plasmid_size, int): raise ValueError("Plasmid_size: must be an integer") if not isinstance(insert_size, int): raise ValueError("insert_size: must be an integer") if isinstance(plasmid_volume, str): plasmid_volume = Unit.fromstring(plasmid_volume) if not isinstance(plasmid_volume, Unit) or \ str(plasmid_volume.dimensionality) != "[length] ** 3": raise ValueError( "Volume of plasmid solution must be of type str or Unit") conc_dimension = ["[substance] / [length] ** 3", '[mass] / [length] ** 3'] conc = [plasmid_conc, insert_conc] size = [plasmid_size, insert_size] for i in range(0, 2): if isinstance(conc[i], str): conc[i] = Unit.fromstring(conc[i]) if (isinstance(conc[i], Unit) and str(conc[i].dimensionality) in conc_dimension): # Convert all concentrations to ng/uL if str(conc[i].dimensionality) == conc_dimension[0]: conc[i] = molar_to_mass_conc(size[i], conc[i], ds) else: conc[i] = conc[i].to("ng/uL") else: raise ValueError( "Concentration must be of type string or Unit ") if not isinstance(ds, bool): raise ValueError( "ds is of type %s, must be of type bool: True for dsDNA, " "False for ssDNA" % type(ds)) if type(molar_ratio) == str: molar_ratio = float( molar_ratio.split(":")[0]) / float(molar_ratio.split(":")[1]) if type(molar_ratio) not in (int, float): raise ValueError( "molar_ratio: must be an int, float, or string in the " "form of int:int") plasmid_conc = conc[0] insert_conc = conc[1] # Convert input volume to uL plasmid_uL = Unit((plasmid_volume / Unit(1, "uL")).magnitude, "uL") len_ratio = float(insert_size) / float(plasmid_size) plasmid_ng = plasmid_conc * plasmid_uL insert_ng = plasmid_ng * len_ratio * molar_ratio insert_amount = insert_ng / insert_conc return insert_amount
def dna_mole_to_mass(length, mole, ds=True): """ For the DNA Length and mole amount given, return the mass of DNA Example Usage: .. code-block:: python from autoprotocol_utilities import dna_mole_to_mass from autoprotocol.unit import Unit dna_length = 5000 dna_mole = "10:pmol" dna_mole_to_mass(dna_length, dna_mole) Returns: .. code-block:: python Unit(33.0, 'microgram') Parameters ---------- length: int Length of DNA in bp mole: str, Unit Mole amount of DNA in prefix-mol ds: bool, optional True for dsDNA, False for ssDNA Returns ------- dna_ug: Unit Weight of DNA in ug Raises ------ ValueError If inputs are not of specified types """ if isinstance(mole, str): mole = Unit.fromstring(mole) if not isinstance(mole, Unit) or str(mole.dimensionality) != "[substance]": raise ValueError( "Mole amount of DNA must be of type Unit in prefix-mol") if not isinstance(length, int): raise ValueError( "Length of DNA is of type %s, must be of type " "integer" % type(length)) if not isinstance(ds, bool): raise ValueError( "ds is of type %s, must be of type bool: True for dsDNA, " "False for ssDNA" % type(ds)) dna_pmol = mole.to("pmol") if ds: dna_ug = ( Unit(660, "pg/pmol") * dna_pmol * Unit(10**(-6), "ug/pg") * length) else: dna_ug = ( Unit(330, "pg/pmol") * dna_pmol * Unit(10**(-6), "ug/pg") * length) return dna_ug