def _edit_pile_length_character(request, pile, character, taxa): # There is little point in being heroic and trying to create exactly # one character value for a pair of taxon_ids = {taxon.id for taxon in taxa} taxon_values = {} minmaxes = {taxon.id: [None, None] for taxon in taxa} for tcv in models.TaxonCharacterValue.objects.filter( taxon__in=taxa, character_value__character=character ).select_related('character_value'): v = tcv.character_value taxon_values[tcv.taxon_id] = v minmaxes[tcv.taxon_id] = [v.value_min, v.value_max] # Process a POST. if 'new_values' in request.POST: new_values = request.POST['new_values'] return _save(request, new_values, character=character) # Grabbing one copy of each family once is noticeably faster than # using select_related('family') up in the taxon fetch: family_ids = set(t.family_id for t in taxa) families = models.Family.objects.filter(id__in=family_ids) taxa.sort(key=pluck('family_id')) # always sort() before groupby()! taxa_by_family_id = { family_id: list(group) for family_id, group in groupby(taxa, key=pluck('family_id')) } def grid(): """Iterator across families and their taxa.""" for family in families: yield 'family', family, None for taxon in taxa_by_family_id.get(family.id, ()): name = taxon.scientific_name if taxon.id not in simple_ids: name += ' (fk)' yield 'taxon', name, minmaxes[taxon.id] partner = which_partner(request) simple_ids = set(ps.species_id for ps in models.PartnerSpecies.objects .filter(partner_id=partner.id, simple_key=True)) valued_ids = {id for id, value in minmaxes.items() if value != ['', ''] } coverage_percent_full = len(valued_ids) * 100.0 / len(taxa) coverage_percent_simple = (len(simple_ids.intersection(valued_ids)) * 100.0 / len(simple_ids.intersection(taxon_ids))) return render(request, 'gobotany/edit_pile_length.html', { 'character': character, 'coverage_percent_full': coverage_percent_full, 'coverage_percent_simple': coverage_percent_simple, 'grid': grid(), 'pile': pile, })
def grid(): for family in sorted(families, key=pluck('name')): yield [family.name] family_taxa = taxa_by_family_id[family.id] for taxon in family_taxa: vector = ''.join('1' if (taxon.id, value.id) in value_map else '0' for value in values) name = taxon.scientific_name if taxon.id not in simple_ids: name += ' (fk)' yield [name, vector]
def grid(): for family in sorted(families, key=pluck('name')): yield [family.name] family_taxa = taxa_by_family_id[family.id] for taxon in family_taxa: vector = ''.join( '1' if (taxon.id, value.id) in value_map else '0' for value in values ) name = taxon.scientific_name if taxon.id not in simple_ids: name += ' (fk)' yield [name, vector]
def _edit_pile_string_character(request, pile, character, taxa): values = list(character.character_values.all()) values.sort(key=character_value_key) tcvlist = list(models.TaxonCharacterValue.objects .filter(taxon__in=taxa, character_value__in=values)) value_map = {(tcv.taxon_id, tcv.character_value_id): tcv for tcv in tcvlist} # We now have enough information, and can either handle a POST # update of specific data or a GET that displays the whole pile. if 'new_values' in request.POST: new_values = request.POST['new_values'] return _save(request, new_values, character=character) # Grabbing one copy of each family once is noticeably faster than # using select_related('family') up in the taxon fetch: family_ids = set(t.family_id for t in taxa) families = models.Family.objects.filter(id__in=family_ids) taxa.sort(key=pluck('family_id')) # always sort() before groupby()! taxa_by_family_id = { family_id: list(group) for family_id, group in groupby(taxa, key=pluck('family_id')) } partner = which_partner(request) simple_ids = set(ps.species_id for ps in models.PartnerSpecies.objects .filter(partner_id=partner.id, simple_key=True)) # This view takes far too long to render with slow Django templates, # so we simply deliver JSON data for the front-end to render there. def grid(): for family in sorted(families, key=pluck('name')): yield [family.name] family_taxa = taxa_by_family_id[family.id] for taxon in family_taxa: vector = ''.join( '1' if (taxon.id, value.id) in value_map else '0' for value in values ) name = taxon.scientific_name if taxon.id not in simple_ids: name += ' (fk)' yield [name, vector] taxa_with_values = set(tcv.taxon_id for tcv in tcvlist) taxa_ids = set(taxon.id for taxon in taxa) coverage_percent_full = len(taxa_with_values) * 100.0 / len(taxa) coverage_percent_simple = (len(simple_ids.intersection(taxa_with_values)) * 100.0 / len(simple_ids.intersection(taxa_ids))) return render(request, 'gobotany/edit_pile_character.html', { 'there_are_any_friendly_texts': any(v.friendly_text for v in values), 'character': character, 'coverage_percent_full': coverage_percent_full, 'coverage_percent_simple': coverage_percent_simple, 'grid': json.dumps(list(grid())), 'pile': pile, 'values': values, 'values_json': json.dumps([value.value_str for value in values]), })
def _edit_pile_length_character(request, pile, character, taxa): # There is little point in being heroic and trying to create exactly # one character value for a pair of taxon_ids = {taxon.id for taxon in taxa} taxon_values = {} minmaxes = {taxon.id: [None, None] for taxon in taxa} for tcv in models.TaxonCharacterValue.objects.filter( taxon__in=taxa, character_value__character=character).select_related( 'character_value'): v = tcv.character_value taxon_values[tcv.taxon_id] = v minmaxes[tcv.taxon_id] = [v.value_min, v.value_max] # Process a POST. if 'new_values' in request.POST: new_values = request.POST['new_values'] return _save(request, new_values, character=character) # Grabbing one copy of each family once is noticeably faster than # using select_related('family') up in the taxon fetch: family_ids = set(t.family_id for t in taxa) families = models.Family.objects.filter(id__in=family_ids) taxa.sort(key=pluck('family_id')) # always sort() before groupby()! taxa_by_family_id = { family_id: list(group) for family_id, group in groupby(taxa, key=pluck('family_id')) } def grid(): """Iterator across families and their taxa.""" for family in families: yield 'family', family, None for taxon in taxa_by_family_id.get(family.id, ()): name = taxon.scientific_name if taxon.id not in simple_ids: name += ' (fk)' yield 'taxon', name, minmaxes[taxon.id] partner = which_partner(request) simple_ids = set(ps.species_id for ps in models.PartnerSpecies.objects.filter( partner_id=partner.id, simple_key=True)) valued_ids = { id for id, value in list(minmaxes.items()) if value != ['', ''] } coverage_percent_full = len(valued_ids) * 100.0 / len(taxa) coverage_percent_simple = (len(simple_ids.intersection(valued_ids)) * 100.0 / len(simple_ids.intersection(taxon_ids))) return render( request, 'gobotany/edit_pile_length.html', { 'character': character, 'coverage_percent_full': coverage_percent_full, 'coverage_percent_simple': coverage_percent_simple, 'grid': grid(), 'pile': pile, })
def _edit_pile_string_character(request, pile, character, taxa): values = list(character.character_values.all()) values.sort(key=character_value_key) tcvlist = list( models.TaxonCharacterValue.objects.filter(taxon__in=taxa, character_value__in=values)) value_map = {(tcv.taxon_id, tcv.character_value_id): tcv for tcv in tcvlist} # We now have enough information, and can either handle a POST # update of specific data or a GET that displays the whole pile. if 'new_values' in request.POST: new_values = request.POST['new_values'] return _save(request, new_values, character=character) # Grabbing one copy of each family once is noticeably faster than # using select_related('family') up in the taxon fetch: family_ids = set(t.family_id for t in taxa) families = models.Family.objects.filter(id__in=family_ids) taxa.sort(key=pluck('family_id')) # always sort() before groupby()! taxa_by_family_id = { family_id: list(group) for family_id, group in groupby(taxa, key=pluck('family_id')) } partner = which_partner(request) simple_ids = set(ps.species_id for ps in models.PartnerSpecies.objects.filter( partner_id=partner.id, simple_key=True)) # This view takes far too long to render with slow Django templates, # so we simply deliver JSON data for the front-end to render there. def grid(): for family in sorted(families, key=pluck('name')): yield [family.name] family_taxa = taxa_by_family_id[family.id] for taxon in family_taxa: vector = ''.join('1' if (taxon.id, value.id) in value_map else '0' for value in values) name = taxon.scientific_name if taxon.id not in simple_ids: name += ' (fk)' yield [name, vector] taxa_with_values = set(tcv.taxon_id for tcv in tcvlist) taxa_ids = set(taxon.id for taxon in taxa) coverage_percent_full = len(taxa_with_values) * 100.0 / len(taxa) coverage_percent_simple = (len(simple_ids.intersection(taxa_with_values)) * 100.0 / len(simple_ids.intersection(taxa_ids))) return render( request, 'gobotany/edit_pile_character.html', { 'there_are_any_friendly_texts': any(v.friendly_text for v in values), 'character': character, 'coverage_percent_full': coverage_percent_full, 'coverage_percent_simple': coverage_percent_simple, 'grid': json.dumps(list(grid())), 'pile': pile, 'values': values, 'values_json': json.dumps([value.value_str for value in values]), })