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))
Beispiel #2
0
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
Beispiel #3
0
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 test_fromstring(self):
     assert (Unit.fromstring("20:microliter") == Unit(20, 'microliter'))
     assert (Unit.fromstring("20:microliter") == Unit("20:microliter"))
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
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 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 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_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 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 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
Beispiel #13
0
 def test_fromstring(self):
     self.assertEqual(Unit.fromstring("20:microliter"),
                      Unit(20, 'microliter'))
     self.assertEqual(Unit.fromstring("20:microliter"),
                      Unit("20:microliter"))
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