Source code for pangea.contrib.treeoflife.views
import structlog
from django.db import connection
from django.utils.translation import gettext_lazy as _
from django.core.exceptions import ObjectDoesNotExist
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.exceptions import ValidationError
from pangea.core.utils import str2bool
from .models import TaxonName
logger = structlog.get_logger(__name__)
[docs]@api_view(['GET'])
def fuzzy_correct_taxa_names(request):
"""Reply with alternate taxa names."""
logger.info(
f'treeoflife__name_correction_query',
query_params=request.query_params,
)
query = request.query_params.get('query', None)
rank = request.query_params.get('rank', None)
canon = request.query_params.get('canon', 'true').lower() != 'false'
if query is None:
logger.warn('treeoflife__name_correct_no_query_param')
raise ValidationError(_('Must provide URL-encoded `query` query parameter.'))
queries = query.split(',')
results = {'canon': canon, 'rank': rank}
for query in queries:
result = {'query': query, 'names': []}
nodes = {name.tree_node for name in TaxonName.objects.filter(name__icontains=query)}
if canon:
names = {node.canon_name for node in nodes if not rank or node.rank == rank}
else:
names = set()
for node in nodes:
if rank and node.rank != rank:
continue
for name in node.all_names:
names.add(name)
for name in names:
result['names'].append({'name': name.name, 'taxon_id': name.taxon_id})
results[query] = result
return Response(results)
[docs]@api_view(['GET'])
def get_descendants(request):
"""Reply with descendant taxa."""
logger.info(
f'treeoflife__taxonomic_descendants',
query_params=request.query_params,
)
queries = request.query_params.get('query', None).split(',')
depth = int(request.query_params.get('depth', 1))
annotate = request.query_params.get('annotate', 'false').lower() != 'false'
def dfs(parent_node, parent, depth):
if depth == 0:
return
for child in parent.children.all():
child_node = {
'name': child.canon_name.name,
'taxon_id': child.taxon_id,
'children': []
}
if annotate:
child_node['annotation'] = child.annotation
parent_node['children'].append(child_node)
dfs(child_node, child, depth - 1)
result = {'depth': depth}
for query in queries:
try:
ancestor = TaxonName.objects.get(name__iexact=query).tree_node
except ObjectDoesNotExist:
raise ValidationError(_(f'Provided parameter {query} does not match any taxa.'))
ancestor_node = {'name': ancestor.canon_name.name, 'taxon_id': ancestor.taxon_id, 'children': []}
if annotate:
ancestor_node['annotation'] = ancestor.annotation
dfs(ancestor_node, ancestor, depth)
result[query] = ancestor_node
return Response(result)
[docs]@api_view(['GET'])
def get_ancestors(request):
"""Reply with ancestor taxa."""
logger.info(
f'treeoflife__taxonomic_ancestors',
query_params=request.query_params,
)
queries = request.query_params.get('query', None).split(',')
result = {}
for query in queries:
try:
ancestors = TaxonName.objects.get(name__iexact=query).tree_node.ancestors()
except ObjectDoesNotExist:
raise ValidationError(_(f'Provided parameter {query} does not match any taxa.'))
result[query] = [tree_node.canon_name.name for tree_node in ancestors]
return Response(result)
[docs]@api_view(['GET'])
def annotate_taxa(request):
"""Reply with annotations for the taxa."""
logger.info(
f'treeoflife__annotate_taxa',
query_params=request.query_params,
)
queries = request.query_params.get('query', None).split(',')
result = {}
for query in queries:
try:
taxon = TaxonName.objects.get(name__iexact=query).tree_node
except ObjectDoesNotExist:
raise ValidationError(_(f'Provided parameter {query} does not match any taxa.'))
result[query] = taxon.annotation
return Response(result)