def get_protocol(self):
        p = stepwise.Protocol()
        s = ul()

        if self.names:
            p += pl(
                f"Purify {','.join(self.names)} by ethanol precipitation [1,2]:",
                s)
        else:
            p += pl("Perform an ethanol precipitation [1,2]:", s)

        s += f"""\
                Add {self.cation_name} to {self.cation_conc}."""
        s += f"""\
                Add {self.carrier_name} to {self.carrier_conc}."""
        s += f"""\
                Add {plural(self.solvent_volume):# volume/s} 
                {self.solvent_name} and mix well."""
        s += f"""\
                If necessary, divide the sample between microfuge tubes
                such that none holds more than 400 µL."""

        if self.incubation and (t := self.incubation_time):
            incubation_time = "overnight" if t == 'overnight' else f"for {t}"
            s += f"""\
    def get_protocol(self):
        transfer = self.volume * (f := self.inv_factor) / (1 - f)
        initial_volume = self.volume + transfer

        conc_high_str = format_quantity(self.conc_high, self.conc_unit, 'g')
        material_str = f'{conc_high_str} {self.material}'.lstrip()
        conc_table = [[i, format_quantity(conc, self.conc_unit, 'e')]
                      for i, conc in enumerate(self.concentrations, 1)]

        num_tubes = self.steps if self.include_zero else self.steps - 1
        each_tube = 'each tube *except the last*' if self.include_zero else 'each tube'

        protocol = stepwise.Protocol()
        protocol += pl(
            "Perform a serial dilution [1]:",
            ul(
                f"Put {initial_volume:.2f} μL {material_str} in a tube.",
                f"Put {self.volume:.2f} μL {self.diluent} in {plural(num_tubes):# adjacent tube/s}.",
                f"Transfer {transfer:.2f} μL between {each_tube} to make {self.steps} {self.factor:.2g}-fold dilutions.",
            ),
        )

        protocol.footnotes[1] = pl(
            "The final concentrations will be:",
            pre(stepwise.tabulate(conc_table, align='>>')),
            br='\n',
        )
        return protocol
Ejemplo n.º 3
0
    def get_protocol(self):
        phrases = []
        n = plural(self.product_tags)

        if self.show_product_tags:
            phrases.append(f"Concentrate the following {n:sample/s}")
        elif self.product_tags:
            phrases.append(f"Concentrate the {n:sample/s}")
        else:
            phrases.append("Concentrate the sample(s)")

        if self.volume and self.conc:
            err = UsageError(volume=self.volume, conc=self.conc)
            err.brief = "cannot specify volume and concentration"
            err.info += "volume: {volume}"
            err.info += "conc: {conc}"
            raise err
        elif self.volume:
            phrases.append(f"to {self.volume}")
        elif self.conc:
            phrases.append(f"to {self.conc}")
        else:
            pass

        if self.show_product_tags:
            phrases.append(
                f"by lyophilization: {', '.join(map(str, self.product_tags))}")
        else:
            phrases.append("by lyophilization.")

        return stepwise.Protocol(steps=[' '.join(phrases)], )
Ejemplo n.º 4
0
    def get_gel_electrophoresis_steps(self):
        p = stepwise.Protocol()
        n = plural(self.samples)
        gel = Gel(self.gel_preset)

        mix = gel.sample_mix
        k = mix.volume / mix['sample'].volume

        for sample in self.samples:
            sample.stock_conc
            sample.sample_volume_per_lane_uL = min(
                    sample.volume_uL,
                    sample.volume_uL / ceil(sample.mass_ug / '20 µg'),
                    mix['sample'].volume.value or inf,
            )
            sample.load_volume_per_lane_uL = k * sample.sample_volume_per_lane_uL
            sample.num_lanes = int(ceil(sample.volume_uL / sample.sample_volume_per_lane_uL))

        conc_vol_groups = group_by_identity(
                self.samples,
                key=lambda x: (x.stock_conc, x.volume_uL),
        )
        for (conc, volume_uL), group in conc_vol_groups:
            prep_gel = Gel(self.gel_preset)
            prep_gel.num_samples = len(group)
            mix = prep_gel.sample_mix

            mix.hold_ratios.volume = k * volume_uL, 'µL'
            mix['sample'].name = ','.join(str(x.name) for x in group)
            mix['sample'].stock_conc = conc

            p += prep_gel.prep_step

        if x := self.gel_percent:
            gel.gel_percent = x
Ejemplo n.º 5
0
    def get_protocol(self):
        p = stepwise.Protocol()

        ## Clean your bench
        p += stepwise.load('rnasezap')

        ## In vitro transcription
        rxn = self.reaction
        n = plural(rxn.num_reactions)
        f = self.footnotes.get('reaction', [])
        p += paragraph_list(
            f"Setup {n:# in vitro transcription reaction/s}{p.add_footnotes(*f)}:",
            rxn,
            unordered_list(*self.instructions),
        )

        f = self.footnotes.get('incubation', [])
        if self.short and affected_by_short(self.incubation_times_min):
            f += [
                f"Reaction time is different than usual because the template is short (<{self.template_length_threshold} bp)."
            ]
        p += f"Incubate at {self.incubation_temp_C}°C for {format_min(pick_by_short(self.incubation_times_min, self.short))}{p.add_footnotes(*f)}."

        ## DNase treatment
        if self.dnase:
            f = self.footnotes.get('dnase', [])
            p += paragraph_list(
                f"Setup {n:# DNase reaction/s}{p.add_footnotes(*f)}:",
                self.dnase_reaction,
            )
            p += f"Incubate at {self.dnase_incubation_temp_C}°C for {format_min(self.dnase_incubation_time_min)}."

        return p
Ejemplo n.º 6
0
    def get_gel_extraction_steps(self):
        p = stepwise.Protocol()
        names = self._cluster_names_by_molecule()

        desired = oxford_comma(x) if (x := self.desired_bands) else 'desired'
        n = plural(max(len(self.desired_bands), len(self.samples)))
        f = "Based on Fitzy's DNA PAGE purification protocol, [Nilson2013], and [Petrov2013]."

        p += pl(f"Cut the {desired} {n:band/s} out of the gel{p.add_footnotes(f)}.", ul(
            "Place the gel over a TLC plate.",
            "Use a UV light to visualize the RNA (dark spot).",
            "Consider visualizing remaining gel to ensure that all desired RNA was excised.",
        ))
        p += pl(f"Crush the gel {n:slice/s}.", ul(
            "Poke a hole in the bottom of a 0.65 mL tube with a 27 g needle.",
            "Place gel slice inside the 0.65 mL tube.",
            "Place the 0.65 mL tube inside a 1.5 mL tube.",
            "Spin at max speed for 5 min.",
        ))

        eb = elution_buffer()
        eb.hold_ratios.volume = 500 * len(self.samples), 'µL'
        p += pl(
                "Resuspend gel in 400 µL PAGE elution buffer:",
                eb,
        )

        if names['RNA']:
            p += f"Incubate {join_if(names['RNA'], names['DNA'])}at 4°C overnight with end-over-end mixing."

        if names['DNA']:
            p += f"Incubate {join_if(names['DNA'], names['RNA'])}at 55°C overnight with 800 rpm mixing."

        return p
Ejemplo n.º 7
0
    def get_stub_protocol(self):
        tags = [x.tag for x in self.stocks]
        in_diluent = f' in {self.diluent}' if self.diluent else ''

        p = stepwise.Protocol()
        p += f"Dilute {oxford_comma(tags)} to {self.target_conc}{in_diluent}."
        return p
Ejemplo n.º 8
0
    def get_protocol(self):
        protocol = stepwise.Protocol()
        pcr, primer_mix = self.reaction
        thermocycler = self.thermocycler_protocol
        footnotes = []

        # Primer mix (if applicable):

        example_uM = min(x.stock_uM for x in flatten(self.primer_pairs))
        footnotes.append(pl(
                f"For resuspending lyophilized primers:",
                f"{example_uM} µM = {1e3 / example_uM:g} µL/nmol",
                br='\n',
        ))

        if primer_mix:
            protocol += pl(
                    f"Prepare 10x primer mix{protocol.add_footnotes(*footnotes)}:",
                    primer_mix,
            )
            footnotes = []

        # PCR reaction setup:

        if self.footnote:
            # Before the footnote on resuspending the primers, if it hasn't 
            # been added to the protocol already.
            footnotes.insert(0, self.footnote)

        if x := pcr['template DNA'].stock_conc:
            footnotes.append(pl(
                    f"For diluting template DNA to {x}:",
                    f"Dilute 1 µL twice into {sqrt(1000/x.value):.1g}*sqrt([DNA]) µL",
                    br='\n',
            ))
Ejemplo n.º 9
0
    def __init__(self, product):
        args = product.maker_args

        self.products = [product]
        self.dependencies = args.get('deps', [])

        if isinstance(self.dependencies, str):
            self.dependencies = self.dependencies.split(',')

        if 'protocol' in args:
            self.protocol = stepwise.Protocol(steps=args['protocol'])

        # Maker attributes:
        if 'conc' in args:
            self.product_conc = stepwise.Quantity.from_string(args['conc'])

        if 'volume' in args:
            self.product_volume = stepwise.Quantity.from_string(args['volume'])

        # Synthesis attributes:
        if 'seq' in args:
            self.product_seqs = [args['seq']]

        if 'molecule' in args:
            self.product_molecule = args['molecule']

        if 'circular' in args:
            self.is_product_circular = freezerbox.parse_bool(args['circular'])
Ejemplo n.º 10
0
    def get_protocol(self):
        # Maybe this should be the getter function for the assembly param...

        p = stepwise.Protocol()
        rxn = self.reaction
        n = rxn.num_reactions
        n_frags = self.num_fragments

        f = 'https://tinyurl.com/yaa5mqz5'
        p += pl(
            f"Setup {plural(n):# Golden Gate assembl/y/ies}{p.add_footnotes(f)}:",
            rxn,
        )
        if n_frags <= 2:
            p += pl(
                "Run the following thermocycler protocol:",
                ul("37°C for 5 min", ),
                "Or, to maximize the number of transformants:",
                ul(
                    "37°C for 60 min",
                    "60°C for 5 min",
                ),
            )

        elif n_frags <= 4:
            p += pl(
                "Run the following thermocycler protocol:",
                ul(
                    "37°C for 60 min",
                    "60°C for 5 min",
                ),
            )

        elif n_frags <= 10:
            p += pl(
                "Run the following thermocycler protocol:",
                ul(
                    "Repeat 30 times:",
                    ul(
                        "37°C for 1 min",
                        "16°C for 1 min",
                    ),
                    "60°C for 5 min",
                ),
            )

        else:
            p += pl(
                "Run the following thermocycler protocol:",
                ul(
                    "Repeat 30 times:",
                    ul(
                        "37°C for 5 min",
                        "16°C for 5 min",
                    ),
                    "60°C for 5 min",
                ),
            )

        return p
Ejemplo n.º 11
0
    def get_protocol(self):
        anneal = AnnealMrnaLinker(self.mrnas, self.linkers)
        anneal.num_reactions = self.num_reactions
        anneal.linker_ratio = 0.6  # See expt #1

        # Scale the reactions such that we'll end up with enough mRNA:
        anneal_rxn = anneal.reaction

        mrna_pmol = (
                self.expected_dead_volume_uL * self.target_conc_uM /
                self.expected_yield
        )
        mrna_conc_uM = anneal_rxn['mRNA'].stock_conc.value

        anneal.mrna_volume_uL = max(
                mrna_pmol / mrna_conc_uM,
                self.mrna_volume_uL,
        )

        ligate = LigateMrnaLinker(anneal)
        wash = WashBarendt()
        wash.mwco_kDa = self.mwco_kDa

        p = stepwise.Protocol()
        p += anneal.protocol
        p += ligate.protocol

        if self.label:
            p += f"Label the product: {self.label}"
        if self.wash:
            p += wash.protocol
        if self.aliquot:
            p += stepwise.load('aliquot "4 µL" "1 µM"')

        return p
Ejemplo n.º 12
0
    def get_protocol(self):
        self._bind_samples()

        p = stepwise.Protocol()
        p += self.gel_electrophoresis_steps
        p += self.gel_extraction_steps
        p += self.product_recovery_steps
        return p
Ejemplo n.º 13
0
 def get_protocol(self):
     p = stepwise.Protocol()
     p += pl(
         f"Setup {plural(self.num_reactions):# ligation reaction/s}:",
         self.reaction,
     )
     p += "Incubate at room temperature for 1h."
     return p
Ejemplo n.º 14
0
def test_to_stdout(capsysbinary):
    unpickleable_protocol = stepwise.Protocol(steps=[lambda: None])
    io = stepwise.ProtocolIO(unpickleable_protocol)
    io.to_stdout()

    cap = capsysbinary.readouterr()
    io_out = pickle.loads(cap.out)
    assert io_out.protocol == ''
    assert io_out.errors == 1
    assert "AttributeError: Can't pickle local object" in cap.err.decode()
Ejemplo n.º 15
0
    def __init__(self, products):
        from more_itertools import flatten

        steps = list(
            flatten(x.maker_args.get('protocol', []) for x in products))
        deps = list(flatten(x.maker_args.get('deps', []) for x in products))

        self.products = products
        self.protocol = stepwise.Protocol(steps=steps)
        self.dependencies = deps
Ejemplo n.º 16
0
    def get_protocol(self):
        p = stepwise.Protocol()

        if self.sample_mix:
            p += self.prep_step

        p += self.run_step

        if self.stain:
            p += stepwise.load(self.stain)

        return p
Ejemplo n.º 17
0
    def get_protocol(self):
        optics = [self.parse_optics(x) for x in self.optics]
        lasers = [f"{plural(optics):laser/s}:"
                  ] + [f"{x['laser']} nm" for x in optics]
        filters = [f"{plural(optics):filter/s}:"
                   ] + [x['filter'] for x in optics]

        p = stepwise.Protocol()
        p += pl(
            "Image with a laser scanner:",
            table([lasers, filters], align='<>>'),
        )
        return p
Ejemplo n.º 18
0
    def get_protocol(self):
        p = stepwise.Protocol()
        rxn = self.reaction

        p += pl(
                f"Setup {plural(self.num_reactions):# {self.title} reaction/s}{p.add_footnotes(self.setup_footnote)}:",
                rxn,
                ul(*self.setup_instructions),
        )
        if self.incubation_time != '0':
            p += f"Incubate at {self.incubation_temp_C:g}°C for {self.incubation_time}{p.add_footnotes(self.incubation_footnote)}."

        return p
Ejemplo n.º 19
0
    def get_protocol(self):
        p = stepwise.Protocol()
        rxn = self.reaction
        n = rxn.num_reactions

        f = "https://tinyurl.com/ychbvkra"
        p += pl(
                f"Setup {plural(n):# Gibson assembl/y/ies}{p.add_footnotes(f)}:",
                rxn,
        )

        incubation_time = '15 min' if self.num_fragments <= 3 else '1h'
        p += f"Incubate at 50°C for {incubation_time}."
        return p
Ejemplo n.º 20
0
    def get_protocol(self):
        p = stepwise.Protocol()
        pl = stepwise.paragraph_list()
        ul = stepwise.unordered_list()

        def break_if_too_long(pl, ul, n=4):
            if len(ul) > n:
                ul = stepwise.unordered_list()
                pl += ul
            return ul

        footnotes = []
        if self.protocol_link:
            footnotes.append(self.protocol_link)
        if self.column_capacity_ug:
            footnotes.append(f"Column capacity: {self.column_capacity_ug} µg")

        if self.product_tags and self.show_product_tags:
            product_tags = oxford_comma(self.product_tags) + ' '
        else:
            product_tags = ''

        p += pl
        pl += f"Purify {product_tags}using {self.protocol_name}{p.add_footnotes(*footnotes)}:"
        pl += ul

        if self.spin_speed_g:
            ul += f"Perform all spin steps at {self.spin_speed_g}g."

        ## Dilute
        if x := self.target_sample_volume_uL:
            v = self.sample_volume_uL

            if not isinstance(x, dict):
                target = f'{x} µL'
                skip = v and v == x
                self.sample_volume_uL = x
            elif 'min' in x and 'max' in x:
                target = f"between {x['min']}–{x['max']} µL"
                skip = v and x['min'] <= v <= x['max']
            elif 'min' in x:
                target = f"at least {x['min']} µL"
                skip = v and x['min'] <= v
            elif 'max' in x:
                target = f"at most {x['max']} µL"
                skip = v and v <= x['max']

            if not skip:
                ul += f"Ensure that the sample is {target}."
Ejemplo n.º 21
0
 def get_protocol(self):
     p = stepwise.Protocol()
     p += pl(
             "Remove unligated linker by ultrafiltration:",
             s := ul(
                 "Bring reaction to 500 µL with 8M urea.",
                 f"Load onto a {self.mwco_kDa} kDa MWCO spin-filter [1].",
                 "Spin 14000g, 15 min.",
                 "Wash with 500 µL 8M urea.",
                 "Wash with 500 µL nuclease-free water.",
                 "Wash with water again.",
                 "Wash with water again, but spin for 30 min.",
                 "Invert the filter into a clean tube and spin 1000g, 2 min to collect ligated product in a volume of ≈15 µL.",
             ),
     )
Ejemplo n.º 22
0
    def get_protocol(self):
        Q = Quantity.from_string

        if self.conc:
            aliquot_info = f'{Q(self.volume)}, {Q(self.conc)}'
        else:
            aliquot_info = f'{Q(self.volume)}'

        if self.product_tags and self.show_product_tags:
            product_tags = f" of: {', '.join(self.product_tags)}"
        else:
            product_tags = "."

        return stepwise.Protocol(
            steps=[f"Make {aliquot_info} aliquots{product_tags}"], )
Ejemplo n.º 23
0
    def get_protocol(self):
        p = stepwise.Protocol()
        rxn = self.reaction

        p += pl(
            f"Setup {plural(rxn.num_reactions):# ligation reaction/s}{p.add_footnotes('https://tinyurl.com/y7gxfv5m')}:",
            rxn,
        )
        p += pl(
            "Incubate at the following temperatures:",
            ul(
                "25°C for 15 min",
                "65°C for 10 min",
            ),
        )
        return p
Ejemplo n.º 24
0
    def get_protocol(self):
        protocol = stepwise.Protocol()
        n = self.num_reactions

        protocol += f"""\
Setup {plural(n):# annealing reaction/s}:

{self.reaction}
"""
        protocol += f"""\
Perform the {plural(n):annealing reaction/s}:

- Incubate at 95°C for 2 min.
- Cool at room temperature.
"""
        return protocol
Ejemplo n.º 25
0
    def get_protocol(self):
        p = stepwise.Protocol()
        rxn = self.reaction
        rxn_name = 'ligation' if self.use_ligase else 'negative control'
        n = rxn.num_reactions

        p += stepwise.pl(
                f"Setup {plural(n):# {rxn_name} reaction/s}:",
                rxn,
        )
        if self.incubate:
            p += pl(
                    f"Incubate the {plural(n):ligation reaction/s} as follows:",
                    s := ul(
                        f"{self.incubate_temp} for {self.incubate_time}."
                    ),
            )
            if self.quench:
Ejemplo n.º 26
0
    def get_product_recovery_steps(self):
        p = stepwise.Protocol()
        names = self._cluster_names_by_molecule()

        # Filter material:
        # - Corning has a good guide on which material to select:
        #   https://www.corning.com/catalog/cls/documents/selection-guides/t_filterselectionguide.pdf
        #
        # - I want 0.22 µm, because that's the standard size for filter 
        #   sterilizing biological buffers (that's not my application here, but 
        #   I can see myself wanting to do that).
        #
        # - I want cellulose acetate filters.  Nylon and cellulose nitrate have 
        #   high DNA binding, which will cause me to lose material.  The 
        #   downside to cellulose acetate is that it has a wetting agent that 
        #   will end up in the sample.  However, this will be removed by the 
        #   Zymo column in the subsequent step.
        #
        # - Product number: 8161 (non sterile)
        #
        # Centrifugation speed:
        # - Fitzy's DNA PAGE purification protocol calls for 4 min at 7000 rpm
        # - The Corning guide (see above) includes an agarose gel purification 
        #   protocol, which calls for 13,000g for 5-20 min.  But this protocol 
        #   has no incubation step, so I gather that the spin is supposed to 
        #   pull the solvent out of the gel.  I probably don't need to go so 
        #   fast, but why not go as fast as the columns can tolerate?
        f = "Nylon and cellulose nitrate have high DNA-binding: https://tinyurl.com/3pkyc8dr"
        p += pl(
                "Remove gel debris by spin filtration:",
                ul(
                    f"Load samples onto a 0.22 µm cellose-acetate Spin-X column{p.add_footnotes(f)}.",
                    "Spin at 13,000g for 5 min."
                ),
        )

        if self.cleanup:
            if names['RNA']:
                p += cleanup(self.rna_cleanup_preset, names['RNA'], names['DNA'])

            if names['DNA']:
                p += cleanup(self.dna_cleanup_preset, names['DNA'], names['RNA'])

        return p
Ejemplo n.º 27
0
 def get_run_step(self):
     p = stepwise.Protocol()
     additive = f" with {x}" if (x := self.gel_additive) else ""
     percent = x.replace('-', '–') if isinstance(x := self.gel_percent,
                                                 str) else x
     p += pl(
         f"Run a gel{p.add_footnotes(self.protocol_link)}:",
         dl(
             ("gel", f"{percent}% {self.gel_type}{additive}"),
             ("buffer", f"{self.gel_buffer}"),
             ("ladder", self.ladder_name
              and f"{self.ladder_volume_uL:g} µL {self.ladder_name}"),
             ("samples", self.load_volume_uL
              and f"{self.load_volume_uL:.3g} µL/lane"),
             ("prerun", self.prerun_time_min and
              f"{self.prerun_volts:g}V for {self.prerun_time_min:g} min"),
             ("run", f"{self.run_volts:g}V for {self.run_time_min:g} min"),
         ))
     return p
Ejemplo n.º 28
0
    def get_protocol(self):
        protocol = stepwise.Protocol()
        targets = iter_targets(
                self.db, self.tags,
                include_deps=self.include_deps,
        )

        for key, group in group_by_synthesis(targets):
            for maker in iter_makers(self.db, key, group):
                protocol += maker.protocol
                if getattr(maker, 'label_products', True):
                    protocol += label_products(maker.products)

            parents = [x.parent for x in group]
            for key, subgroup in group_by_cleanup(parents):
                for maker in iter_makers(self.db, key, subgroup):
                    protocol += maker.protocol

        return protocol
Ejemplo n.º 29
0
    def get_protocol(self):
        p = stepwise.Protocol()
        rxn = self.reaction

        p += f"""\
Setup {plural(self.num_reactions):# NEBExpress reaction/s} [1]:

{rxn}

- Thaw all components on ice.
- Mix the S30 extract and protein synthesis buffer 
  by gently vortexing.
"""

        p += f"""\
Incubate at {self.incubation_temp_C}°C for {self.incubation_time} [4].
"""

        p.footnotes[1] = """\
During the experimental setup, it is recommended 
to add the linear DNA template in the last step to 
allow GamS to bind and inhibit RecBCD exonuclease 
before RecBCD has a chance to act on the DNA. 
"""

        p.footnotes[2] = """\
Aliquot to avoid multiple freeze/thaw cycles.
"""

        p.footnotes[3] = """\
Optimal concentration must be determined 
empirically for each template.
"""

        p.footnotes[4] = """\
Additional incubation time (maximum 10 hours) at 
37°C may increase yield.
"""

        return p
Ejemplo n.º 30
0
    def get_protocol(self):
        p = stepwise.Protocol()
        rxn = self.reaction
        n = rxn.num_reactions

        p += pl(
            f"Setup {plural(n):# annealing reaction/s} [1]:",
            rxn,
        )

        p.footnotes[1] = """\
                Using 0.6x linker reduces the amount of unligated 
                linker, see expt #1."""

        p += pl(
            f"Perform the {plural(n):annealing reaction/s}:",
            ul(
                "Incubate at 95°C for 2 min.",
                "Cool at room temperature.",
            ),
        )

        return p