Beispiel #1
0
    def test_get_worms_for_screen_type(self):
        n2, dnc1, glp1, emb8 = self.get_worms()

        enhs = WormStrain.get_worms_for_screen_type('ENH')
        sups = WormStrain.get_worms_for_screen_type('SUP')

        for worms in (enhs, sups):
            self.assertNotIn(n2, worms)
            self.assertIn(emb8, worms)

        self.assertIn(dnc1, enhs)
        self.assertNotIn(dnc1, sups)

        self.assertNotIn(glp1, enhs)
        self.assertIn(glp1, sups)
Beispiel #2
0
    def get_n2_control_filters(self):
        """
        Get the N2 + RNAi controls for this experiment.
        It does this by manually setting the strain as N2 and then applying
        all the other parameters which are shared by the controls.

        To get the actual control experiments from the returned filters,
        simply do Experiment.objects.filter(**filters). Returning
        the filters is more flexible for customization, or for inserting
        into a URL without performing the query.

        N2 controls for this experiment are restricted to those from
        the same date, *closest* temperature, same RNAi clone.
        """
        filters = {
            'is_junk': False,
            'plate__date': self.date(),
            'plate__temperature': self.temperature(),
            'library_stock': self.library_stock,
            'worm_strain': WormStrain.get_n2().pk,
        }

        filters['plate__temperature'] = Experiment.get_closest_temperature(
            self.temperature(), filters)

        return filters
Beispiel #3
0
    def get_n2_l4440_control_filters(self):
        """
        Get the filters for the L4440 controls for this experiment.

        To get the actual control experiments from the returned filters,
        simply do Experiment.objects.filter(**filters). Returning
        the filters is more flexible for customization, or for inserting
        into a URL without performing the query.

        L4440 controls for this experiment are restricted to those from
        the same date, same temperature, same worm.

        If this experiment is itself an L4440 clone, the function works
        the same way, returning all L4440 experiments from the same
        date, same worm, same temperature.
        """
        filters = {
            'is_junk': False,
            'plate__date': self.date(),
            'plate__temperature': self.temperature(),
            'worm_strain': WormStrain.get_n2().pk,
            'library_stock__intended_clone': Clone.get_l4440(),
        }

        return filters
Beispiel #4
0
def clean_mutant_query_and_screen_type(form, cleaned_data):
    """
    Helper to derive worm strain and temperature from cleaned_data.

    If cleaned_data['mutant_query'] and cleaned_data['screen_type']
    are defined, cleaned_data['worm'] and cleaned_data['temperature']
    will be populated.

    Returns the modified cleaned_data.
    """
    mutant_query = cleaned_data.get('mutant_query')
    secondary_mutant_query = cleaned_data.get('secondary_mutant_query')
    screen_type = cleaned_data.get('screen_type')

    if mutant_query and screen_type and secondary_mutant_query:

        worm_and_temp = WormStrain.get_worm_and_temperature_from_search_term(
            mutant_query, screen_type)

        worm_and_temp2 = WormStrain.get_worm_and_temperature_from_search_term(
            secondary_mutant_query, screen_type)
        print worm_and_temp2

        if worm_and_temp and worm_and_temp2:
            cleaned_data['worm'] = worm_and_temp[0]
            cleaned_data['worm2'] = worm_and_temp2[0]
            cleaned_data['temperature'] = worm_and_temp[1]
        else:
            form.add_error('mutant_query', 'No mutant match')

    elif mutant_query and screen_type:
        worm_and_temp = WormStrain.get_worm_and_temperature_from_search_term(
            mutant_query, screen_type)
        if worm_and_temp:
            cleaned_data['worm'] = worm_and_temp[0]
            cleaned_data['worm2'] = secondary_mutant_query
            cleaned_data['temperature'] = worm_and_temp[1]
        else:
            form.add_error('mutant_query', 'No mutant match')

    return cleaned_data
Beispiel #5
0
def rnai_knockdown(request, clones, temperature=None):
    """
    Render the page showing knockdown by RNAi only.

    context['data'] is returned in format:

        {clone: {
            library_stock: [experiments]
        }}
    """
    data = OrderedDict()

    n2 = WormStrain.get_n2()
    clones = Clone.objects.filter(pk__in=clones.split(','))

    for clone in clones:
        filters = {
            'is_junk': False,
            'worm_strain': n2.pk,
            'library_stock__intended_clone': clone,
        }

        if temperature:
            filters['plate__temperature'] = temperature

        # Do not join manual scores, since N2 not manually scored
        experiments = (Experiment.objects.filter(**filters).select_related(
            'library_stock',
            'plate').prefetch_related('devstarscore_set').order_by(
                '-library_stock__plate__screen_stage', 'library_stock',
                '-plate__date', 'id'))

        data_by_well = OrderedDict()

        for experiment in experiments:
            library_stock = experiment.library_stock
            if library_stock not in data_by_well:
                data_by_well[library_stock] = []
            data_by_well[library_stock].append(experiment)

        if data_by_well:
            data[clone] = data_by_well

    context = {
        'n2': n2,
        'clones': clones,
        'temperature': temperature,
        'data': data,
    }

    return render(request, 'rnai_knockdown.html', context)
Beispiel #6
0
def rnai_knockdown(request, clones, temperature=None):
    """
    Render the page showing knockdown by RNAi only.

    context['data'] is returned in format:

        {clone: {
            library_stock: [experiments]
        }}
    """
    data = OrderedDict()

    n2 = WormStrain.get_n2()
    clones = Clone.objects.filter(pk__in=clones.split(','))

    for clone in clones:
        filters = {
            'is_junk': False,
            'worm_strain': n2.pk,
            'library_stock__intended_clone': clone,
        }

        if temperature:
            filters['plate__temperature'] = temperature

        # Do not join manual scores, since N2 not manually scored
        experiments = (Experiment.objects.filter(**filters)
                       .select_related('library_stock', 'plate')
                       .prefetch_related('devstarscore_set')
                       .order_by('-library_stock__plate__screen_stage',
                                 'library_stock', '-plate__date', 'id'))

        data_by_well = OrderedDict()

        for experiment in experiments:
            library_stock = experiment.library_stock
            if library_stock not in data_by_well:
                data_by_well[library_stock] = []
            data_by_well[library_stock].append(experiment)

        if data_by_well:
            data[clone] = data_by_well

    context = {
        'n2': n2,
        'clones': clones,
        'temperature': temperature,
        'data': data,
    }

    return render(request, 'rnai_knockdown.html', context)
Beispiel #7
0
def get_positives_any_worm(screen_type, screen_stage, criteria, **kwargs):
    """
    Get the set of library stocks that are positive for ANY worm.

    A screen is defined by both screen_type ('ENH' or 'SUP')
    and screen_stage (1 for primary, 2 for secondary).
    """
    worms = WormStrain.get_worms_for_screen_type(screen_type)

    all_positives = set()
    for worm in worms:
        positives = worm.get_positives(screen_type, screen_stage, criteria,
                                       **kwargs)
        all_positives = all_positives.union(positives)

    return all_positives
Beispiel #8
0
def get_positives_any_worm(screen_type, screen_stage, criteria, **kwargs):
    """
    Get the set of library stocks that are positive for ANY worm.

    A screen is defined by both screen_type ('ENH' or 'SUP')
    and screen_stage (1 for primary, 2 for secondary).
    """
    worms = WormStrain.get_worms_for_screen_type(screen_type)

    all_positives = set()
    for worm in worms:
        positives = worm.get_positives(screen_type, screen_stage, criteria,
                                       **kwargs)
        all_positives = all_positives.union(positives)

    return all_positives
Beispiel #9
0
def _limit_to_screen_type(experiments, screen_type):
    """
    Post-process experiments QuerySet such that each experiment was done at its
    worm's SUP or ENH temperature. Since N2 does not have a SUP or ENH
    temperature, N2 will not be in this result.

    Question: Why not just get the SUP/ENH temperature for these experiments'
    worm, and then using `.filter()` with that temperature?

    Answer: That is what I do on queries limited to a single worm strain, e.g.
    for most of the public-facing pages. But these experiment filtering forms
    are meant to be flexible (basically a gateway into the database for GI
    team use only), flexible enough to potentially include multiple strains
    with different SUP/ENH temperatures (e.g. maybe Noah wants to see all
    experiments from one date).

    Question: Why not just join between ExperimentPlate.temperature and
    WormStrain.permissive_temperature / .restrictive_temperature?

    This would involve joining WormStrain on a second field. While easy with
    raw SQL, this is not easy with Django, requiring either 1) soon-to-
    be-deprecated `empty()`, 2) overriding low level query processing in ways
    that are subject to syntax changes, or 3) using `raw()` to write raw SQL.
    While I was tempted to do 3), since these filtering forms are meant to be
    generic and applicable (able to take dozens of possible keys to filter on),
    this one case doesn't warrant losing the readability and protections
    against SQL injection attacks that Django QuerySets provide.
    """
    # Create a dictionary
    to_temperature = WormStrain.get_worm_to_temperature_dictionary(screen_type)
    filtered = []

    for experiment in experiments.prefetch_related("worm_strain", "plate"):
        temperature = experiment.plate.temperature

        if temperature == to_temperature[experiment.worm_strain]:
            filtered.append(experiment)

    return filtered
Beispiel #10
0
def clean_mutant_query_and_screen_type(form, cleaned_data):
    """
    Helper to derive worm strain and temperature from cleaned_data.

    If cleaned_data['mutant_query'] and cleaned_data['screen_type']
    are defined, cleaned_data['worm'] and cleaned_data['temperature']
    will be populated.

    Returns the modified cleaned_data.
    """
    mutant_query = cleaned_data.get('mutant_query')
    screen_type = cleaned_data.get('screen_type')

    if mutant_query and screen_type:
        worm_and_temp = WormStrain.get_worm_and_temperature_from_search_term(
            mutant_query, screen_type)
        if worm_and_temp:
            cleaned_data['worm'] = worm_and_temp[0]
            cleaned_data['temperature'] = worm_and_temp[1]
        else:
            form.add_error('mutant_query', 'No mutant match')

    return cleaned_data
Beispiel #11
0
    def get_n2_control_filters(self):
        """
        Get the N2 + RNAi controls for this experiment.

        To get the actual control experiments from the returned filters,
        simply do Experiment.objects.filter(**filters). Returning
        the filters is more flexible for customization, or for inserting
        into a URL without performing the query.

        N2 controls for this experiment are restricted to those from
        the same date, *closest* temperature, same RNAi clone.
        """
        filters = {
            'is_junk': False,
            'plate__date': self.date(),
            'plate__temperature': self.temperature(),
            'library_stock': self.library_stock,
            'worm_strain': WormStrain.get_n2().pk,
        }

        filters['plate__temperature'] = Experiment.get_closest_temperature(
            self.temperature(), filters)

        return filters
Beispiel #12
0
def double_knockdown(request, mutant, clones, temperature):
    """
    Render the page showing knockdown by both mutation and RNAi.

    context['data'] is returned in format:

        {clone: {
            library_stock: {
                date: {
                    'mutant_rnai': {
                        'experiments': [experiments], 'link_to_all': url
                    },
                    'n2_rnai': {
                        'experiments': [experiments], 'link_to_all': url
                    },
                    'mutant_l4440': {
                        'experiments': [experiments], 'link_to_all': url
                    },
                    'n2_l4440': {
                        'experiments': [experiments], 'link_to_all': url
                    },
                }
            }
        }}

    """

    data = OrderedDict()

    n2 = WormStrain.get_n2()
    l4440 = Clone.get_l4440()
    mutant = get_object_or_404(WormStrain, pk=mutant)
    clones = Clone.objects.filter(pk__in=clones.split(','))

    for clone in clones:
        data_per_clone = OrderedDict()

        library_stocks = (LibraryStock.objects.filter(
            intended_clone=clone).order_by('-plate__screen_stage', 'id'))

        for library_stock in library_stocks:
            data_per_well = OrderedDict()

            dates = Experiment.get_distinct_dates({
                'is_junk':
                False,
                'worm_strain':
                mutant,
                'library_stock':
                library_stock,
                'plate__temperature':
                temperature,
            })

            for date in dates:
                # Add double knockdowns
                filters = {
                    'is_junk': False,
                    'plate__date': date,
                    'worm_strain': mutant.pk,
                    'library_stock': library_stock,
                    'plate__temperature': temperature,
                }
                mutant_rnai = _create_inner_dictionary(filters,
                                                       join_manual=True)

                # Add mutant + L4440 controls
                filters = {
                    'is_junk': False,
                    'plate__date': date,
                    'worm_strain': mutant.pk,
                    'library_stock__intended_clone': l4440,
                    'plate__temperature': temperature,
                }
                mutant_l4440 = _create_inner_dictionary(filters)

                # Add N2 + RNAi controls
                filters = {
                    'is_junk': False,
                    'plate__date': date,
                    'worm_strain': n2.pk,
                    'library_stock': library_stock,
                }

                t = Experiment.get_closest_temperature(temperature, filters)
                filters['plate__temperature'] = t

                n2_rnai = _create_inner_dictionary(filters)

                # Add N2 + L4440 controls
                filters = {
                    'is_junk': False,
                    'plate__date': date,
                    'worm_strain': n2.pk,
                    'library_stock__intended_clone': l4440,
                }

                t = Experiment.get_closest_temperature(temperature, filters)
                filters['plate__temperature'] = t

                n2_l4440 = _create_inner_dictionary(filters)

                data_per_well[date] = {
                    'mutant_rnai': mutant_rnai,
                    'mutant_l4440': mutant_l4440,
                    'n2_rnai': n2_rnai,
                    'n2_l4440': n2_l4440,
                }

            if data_per_well:
                data_per_clone[library_stock] = data_per_well

        data[clone] = data_per_clone

    context = {
        'mutant': mutant,
        'clones': clones,
        'temperature': temperature,
        'data': data,
    }

    return render(request, 'double_knockdown.html', context)
Beispiel #13
0
def double_knockdown(request, mutant, clones, temperature):
    """
    Render the page showing knockdown by both mutation and RNAi.

    context['data'] is returned in format:

        {clone: {
            library_stock: {
                date: {
                    'mutant_rnai': {
                        'experiments': [experiments], 'link_to_all': url
                    },
                    'n2_rnai': {
                        'experiments': [experiments], 'link_to_all': url
                    },
                    'mutant_l4440': {
                        'experiments': [experiments], 'link_to_all': url
                    },
                    'n2_l4440': {
                        'experiments': [experiments], 'link_to_all': url
                    },
                }
            }
        }}

    """

    data = OrderedDict()

    n2 = WormStrain.get_n2()
    l4440 = Clone.get_l4440()
    mutant = get_object_or_404(WormStrain, pk=mutant)
    clones = Clone.objects.filter(pk__in=clones.split(','))

    for clone in clones:
        data_per_clone = OrderedDict()

        library_stocks = (LibraryStock.objects.filter(intended_clone=clone)
                          .order_by('-plate__screen_stage', 'id'))

        for library_stock in library_stocks:
            data_per_well = OrderedDict()

            dates = Experiment.get_distinct_dates({
                'is_junk': False,
                'worm_strain': mutant,
                'library_stock': library_stock,
                'plate__temperature': temperature,
            })

            for date in dates:
                # Add double knockdowns
                filters = {
                    'is_junk': False,
                    'plate__date': date,
                    'worm_strain': mutant.pk,
                    'library_stock': library_stock,
                    'plate__temperature': temperature,
                }
                mutant_rnai = _create_inner_dictionary(
                    filters, join_manual=True)

                # Add mutant + L4440 controls
                filters = {
                    'is_junk': False,
                    'plate__date': date,
                    'worm_strain': mutant.pk,
                    'library_stock__intended_clone': l4440,
                    'plate__temperature': temperature,
                }
                mutant_l4440 = _create_inner_dictionary(filters)

                # Add N2 + RNAi controls
                filters = {
                    'is_junk': False,
                    'plate__date': date,
                    'worm_strain': n2.pk,
                    'library_stock': library_stock,
                }

                t = Experiment.get_closest_temperature(temperature, filters)
                filters['plate__temperature'] = t

                n2_rnai = _create_inner_dictionary(filters)

                # Add N2 + L4440 controls
                filters = {
                    'is_junk': False,
                    'plate__date': date,
                    'worm_strain': n2.pk,
                    'library_stock__intended_clone': l4440,
                }

                t = Experiment.get_closest_temperature(temperature, filters)
                filters['plate__temperature'] = t

                n2_l4440 = _create_inner_dictionary(filters)

                data_per_well[date] = {
                    'mutant_rnai': mutant_rnai,
                    'mutant_l4440': mutant_l4440,
                    'n2_rnai': n2_rnai,
                    'n2_l4440': n2_l4440,
                }

            if data_per_well:
                data_per_clone[library_stock] = data_per_well

        data[clone] = data_per_clone

    context = {
        'mutant': mutant,
        'clones': clones,
        'temperature': temperature,
        'data': data,
    }

    return render(request, 'double_knockdown.html', context)
Beispiel #14
0
    def handle(self, **options):
        summary_mode = options['summary']

        candidates_by_worm = {}
        candidates_by_clone = {}
        worms = WormStrain.get_worms_for_screen_type('ENH')

        for worm in worms:
            candidates_by_worm[worm] = []
            singles = worm.get_stocks_tested_by_number_of_replicates(
                'ENH', 1, 1)

            positives = worm.get_positives('ENH',
                                           1,
                                           passes_enh_primary,
                                           singles=singles)

            for library_stock in positives:
                candidates_by_worm[worm].append(library_stock)
                if library_stock not in candidates_by_clone:
                    candidates_by_clone[library_stock] = []
                candidates_by_clone[library_stock].append(worm)

        if summary_mode:
            self.stdout.write('Total clones to cherrypick: {}'.format(
                len(candidates_by_clone)))

            self.stdout.write('\n\nBefore accounting for universals:')
            _print_candidates_by_worm(candidates_by_worm)

        # Move certain clones from individual worm lists to universal
        candidates_by_worm['universal'] = []
        for well in candidates_by_clone:
            worms = (candidates_by_clone[well])
            if len(worms) >= UNIVERSAL_THRESHOLD:
                candidates_by_worm['universal'].append(well)
                for worm in worms:
                    candidates_by_worm[worm].remove(well)

        if summary_mode:
            self.stdout.write('\n\nAfter accounting for universals:')
            _print_candidates_by_worm(candidates_by_worm)
            return

        # Create official cherrypick list, with random empty wells
        cherrypick_list = []
        already_used_empties = set()
        for worm, candidates in candidates_by_worm.iteritems():
            label = worm.allele if hasattr(worm, 'allele') else worm

            if label == 'universal':
                empties_per_plate = 1
                empties_limit = 9
            elif label == 'it57':
                empties_per_plate = 0
                empties_limit = None
            else:
                empties_per_plate = 2
                empties_limit = None

            assigned = assign_to_plates(
                sorted(candidates),
                vertical=True,
                empties_per_plate=empties_per_plate,
                empties_limit=empties_limit,
                already_used_empties=already_used_empties)

            rows = get_plate_assignment_rows(assigned)

            for row in rows:
                if row[2]:
                    source_plate = row[2].plate
                    source_well = row[2].well
                else:  # Empty well
                    source_plate = None
                    source_well = None

                destination_plate = label + '-E' + str(row[0] + 1)
                destination_well = row[1]
                cherrypick_list.append((source_plate, source_well,
                                        destination_plate, destination_well))

        # Sort by (destination_plate, destination_well)
        cherrypick_list.sort(key=lambda x: (x[2].split('-')[
            0], int(x[2].split('E')[1]), int(x[3][1:]), x[3][0]))

        # Print the list
        self.stdout.write('source_plate,source_well,'
                          'destination_plate,destination_well')
        for row in cherrypick_list:
            self.stdout.write(','.join([str(x) for x in row]))

        # Quick fix for empty_wells check up to this point not accounting
        # for not-full plates potentially having the same plate pattern,
        # despite the "chosen" empty wells differing.
        # If the printed list says "TRASH THIS" at the bottom, try again!
        e = {}
        for row in cherrypick_list:
            if row[0] is None:
                if row[2] not in e:
                    e[row[2]] = set()
                e[row[2]].add(row[3])

        seen = set()
        for plate, wells in e.iteritems():
            wells = tuple(sorted(wells))
            if is_symmetric(wells):
                self.stdout.write('TRASH THIS AND TRY AGAIN. '
                                  '{}:{} pattern is symmetric!'.format(
                                      plate, wells))

            if wells in seen:
                self.stdout.write('TRASH THIS AND TRY AGAIN. '
                                  '{}:{} pattern redundant!'.format(
                                      plate, wells))

            seen.add(wells)
Beispiel #15
0
 def test_get_n2(self):
     n2 = WormStrain.get_n2()
     self.assertEquals(n2.id, 'N2')
     self.assertIsNone(n2.permissive_temperature)
     self.assertIsNone(n2.restrictive_temperature)