diff --git a/.gitignore b/.gitignore index 9233dd9..cc80c1a 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ *.sqlite3 *.sqlite last_sync +trees/ # Byte-compiled / optimized / DLL files __pycache__/ diff --git a/app/app.py b/app/app.py index 3be3ae6..41ce1a8 100644 --- a/app/app.py +++ b/app/app.py @@ -1,5 +1,6 @@ import csv import os +from typing import Optional from app import __version__, get_db_last_sync from flask import ( Flask, @@ -39,6 +40,14 @@ app.secret_key = os.urandom(12) IS_DEV_SITE = os.environ.get("MARC_DEV", "").lower() == "true" +MARC_TREE_FP = os.environ.get("MARC_TREE_FP") + + +def treefile_for_species(species_name: str) -> Optional[str]: + if not species_name: + return None + slug = "_".join(species_name.lower().split()) + return f"{slug}.treefile" @app.context_processor @@ -380,6 +389,36 @@ def show_antimicrobial(antimicrobial_id: int): ) +@app.route("/species/") +def show_species(species_name: str): + assignment_count = ( + db.session.query(func.count(TaxonomicAssignment.id)) + .filter(TaxonomicAssignment.classification == species_name) + .scalar() + ) + treefile_name = treefile_for_species(species_name) + tree_content = None + tree_path = None + tree_error = None + if MARC_TREE_FP and treefile_name: + candidate = Path(MARC_TREE_FP) / treefile_name + tree_path = str(candidate) + if candidate.is_file(): + try: + tree_content = candidate.read_text() + except Exception as exc: + tree_error = str(exc) + return render_template( + "show_species.html", + species_name=species_name, + assignment_count=assignment_count, + tree_path=tree_path, + tree_content=tree_content, + tree_error=tree_error, + tree_root=MARC_TREE_FP, + ) + + @app.route("/assembly/") def show_assembly(assembly_id: int): assemblies = get_assemblies(db.session, id=assembly_id) diff --git a/app/templates/browse_isolates.html b/app/templates/browse_isolates.html index 5b550c3..028cb62 100644 --- a/app/templates/browse_isolates.html +++ b/app/templates/browse_isolates.html @@ -27,6 +27,7 @@

Isolates

$(document).ready(function () { /* Initialize the DataTable with server-side processing */ const isolateUrl = "{{ url_for('show_isolate', isolate_id='') }}"; + const speciesUrl = "{{ url_for('show_species', species_name='') }}"; const renderCollectionYear = (value, type) => { if (!value) { return type === 'sort' || type === 'type' ? null : ''; @@ -59,7 +60,15 @@

Isolates

{ data: 'received_date', render: function(value, type) { return renderCollectionYear(value, type); } }, { data: 'subject_id' }, { data: 'specimen_id' }, - { data: 'suspected_organism' } + { data: 'suspected_organism', render: function(value, type) { + if (type !== 'display') { + return value; + } + if (!value) { + return ''; + } + return '' + value + ''; + } } ]); /* Move search box to bottom of summary area */ diff --git a/app/templates/browse_taxonomic_assignments.html b/app/templates/browse_taxonomic_assignments.html index f41626c..d686b80 100644 --- a/app/templates/browse_taxonomic_assignments.html +++ b/app/templates/browse_taxonomic_assignments.html @@ -25,11 +25,20 @@

Taxonomic Assignments

+ + + + + {% elif tree_root %} +

No treefile found for this species.

+ {% else %} +

Set the MARC_TREE_FP environment variable to load treefiles.

+ {% endif %} + + + +{% endblock %} diff --git a/app/templates/show_taxonomic_assignment.html b/app/templates/show_taxonomic_assignment.html index 2bbd305..d4f1814 100644 --- a/app/templates/show_taxonomic_assignment.html +++ b/app/templates/show_taxonomic_assignment.html @@ -22,7 +22,15 @@

Taxonomic Assignment for Assembly {{ assembly_id }}

{{ assignment.tool or '—' }}
Classification
-
{{ assignment.classification or '—' }}
+
+ {% if assignment.classification %} + + {{ assignment.classification }} + + {% else %} + — + {% endif %} +
Comment
{{ assignment.comment or '—' }}