Skip to content

Commit

Permalink
Adding experimental buttons for getting sampled donor/acceptor subtre…
Browse files Browse the repository at this point in the history
…es for viewing on usherbio
  • Loading branch information
mrkylesmith committed Feb 28, 2024
1 parent 8c3e129 commit c5984b8
Show file tree
Hide file tree
Showing 6 changed files with 1,718 additions and 1,767 deletions.
30 changes: 25 additions & 5 deletions backend/backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,21 +76,31 @@ def get_gene_annotations(features):

return gene_region_data

def get_sampled_desc(results_file, node_id):
def get_sampled_desc(results_file, node_id, _type):
"""
"""
NODE_ID_COL = 0
SAMPLED_DESC_COL = -3
if _type == "Donor":
NODE_ID_COL = 1
SAMPLED_DESC_COL = -2
elif _type == "Acceptor":
NODE_ID_COL = 2
SAMPLED_DESC_COL = -1
BUF_SIZE = 1048576 # Read 1MB at a time
f = open(results_file, 'r', buffering=BUF_SIZE)
d = {}
# Skip over column headers (assuming one)
header = f.readline()

# Check to make sure results file contains sampled descendants field
if header.strip().split('\t')[-1] != "Sampled Descendants":
if header.strip().split('\t')[-3] != "Sampled Descendants":
return None

for line in f:
splitline = line.strip().split('\t')
sampled_desc_list = list(filter(None,splitline[-1].split(',')))
if node_id == splitline[0]:
sampled_desc_list = list(filter(None,splitline[SAMPLED_DESC_COL].split(',')))
if node_id == splitline[NODE_ID_COL]:
return sampled_desc_list
# Error, node_id not found in results file
return None
Expand Down Expand Up @@ -258,7 +268,7 @@ def build_counts_histogram(results_file, month_seq_counts_filename):
joined_date = "_".join([year, month])
if joined_date not in month_bins.keys():
#TODO: Temporary fix, update data statistics data past 2023-02
if year == "2023" and int(month) > 2:
if year == "2023" and int(month) > 2 or year == "2024":
continue
print("[ERROR] CHECK Formatting: {}".format(joined_date))
print("Recomb Node id: {}, with date: {}, in this file: {} is producing this error".format(recomb_id, recomb_date, results_file))
Expand Down Expand Up @@ -1086,3 +1096,13 @@ def search_by_sample(recomb_node_set, desc_file, desc_lookup_table, substr):
if pattern in desc_string.lower():
recomb_nodes.add(node_id)
return list(recomb_nodes)

def get_aa_mutations(db_file, table, node_id):
"""
"""
import duckdb
con = duckdb.connect(database=db_file, read_only=True)
mutations = con.sql("select * from {} where column0 = '{}'".format(table, node_id)).fetchall()
con.close()
# Return aa_mutations list and and nt_mutations list for the given node_id
return [x[2] for x in mutations], [x[1] for x in mutations]
36 changes: 11 additions & 25 deletions rivet-frontend.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,12 @@ def get_usher_link():
#TODO: Handle for local version
# return jsonify(None)
node_id = content["node"]
_type = content["type"]
else:
# Initialize default values from input TSV
node_id = init_data["recomb_id"]

samples = backend.get_sampled_desc(results_file, node_id)
samples = backend.get_sampled_desc(results_file, node_id, _type)
if not samples:
print("[Error] {} not found in results file.".format(node_id))
samples = ["England/PHEP-YYGTYSK/2023|2023-03-18",
Expand Down Expand Up @@ -238,14 +239,12 @@ def get_aa_mutations():
content = request.get_json()
recomb_node_id = content["recomb_node_id"]
tree = content["tree"]
db_file = app.config.get('db_file')
aa_tables = app.config.get('aa_tables')
if tree == "public":
translation_data = app.config.get('translation_data')
aa_mutations = translation_data[recomb_node_id]["aa_mutations"]
nt_mutations = translation_data[recomb_node_id]["nt_mutations"]
aa_mutations, nt_mutations = backend.get_aa_mutations(db_file, aa_tables[0], recomb_node_id)
else:
translation_data = app.config.get('full_tree_translation_data')
aa_mutations = translation_data[recomb_node_id]["aa_mutations"]
nt_mutations = translation_data[recomb_node_id]["nt_mutations"]
aa_mutations, nt_mutations = backend.get_aa_mutations(db_file, aa_tables[1], recomb_node_id)
return jsonify({"aa": aa_mutations, "nt": nt_mutations})

@app.route("/get_all_descendants", methods=["POST", "GET"])
Expand Down Expand Up @@ -488,14 +487,13 @@ def table():
parser.add_argument("-r", "--recombinant_results", required=True, type=str, help="Give input recombination results file")
parser.add_argument("-d", "--descendants_file", required=False, type=str, help="File containing descendants (up to 10k) for each node in VCF")
parser.add_argument("-c", "--config", required=True, type=str, help="Configuration file for defining custom color schema for visualizations.")
parser.add_argument("-t", "--translate", required=False, type=str, help="matUtils translate file for visualizing amino acid information.")
parser.add_argument("-a", "--analysis", required=False, type=str, help="Extra data files with counts of new genomes sequenced per month. Not for general use.")
args = parser.parse_args()

# Load and parse config file
config = backend.parse_config(args.config)
print("Loading RIVET for MAT date: ", config["date"])

color_schema = config
#color_schema = None
#if args.config != None:
Expand All @@ -504,7 +502,7 @@ def table():
# print("Config file not provided, using default RIVET settings.")
# color_schema = backend.default_color_schema()
#TODO: Check extensions for input files for correct file format (ie. genbank file)

# Load recombination results file and get initial data
results_files = args.recombinant_results.split(",")
recomb_results = results_files[0]
Expand Down Expand Up @@ -563,7 +561,6 @@ def table():
app.config['month_seq_counts'] = month_seq_counts
app.config['recomb_counts'] = recomb_counts
app.config['relative_recombinants'] = relative_recombinants


full_tree_month_case_counts,full_tree_month_seq_counts,full_tree_recomb_counts,full_tree_relative_recombinants, = None,None,None,None
if len(results_files) > 1:
Expand Down Expand Up @@ -598,20 +595,6 @@ def table():
full_tree_recomb_node_set = set([cell[1] for cell in full_tree_table])
full_tree_desc_position_table, full_tree_sample_counts = backend.preprocess_desc_file(full_tree_desc_file, full_tree_recomb_node_set)

# Amino acid translation (if provided)
translation_data, full_tree_translation_data = None, None
if args.translate:
translation_files = args.translate.split(",")
translation_file = translation_files[0]
print("Loading provided amino acid translation file/s: ", translation_file)
translation_data = backend.parse_translation_files(translation_file, recomb_node_set)
if len(translation_files) > 1:
full_tree_translation_file = translation_files[1]
print("Loading provided amino acid translation file/s: ", full_tree_translation_file)
full_tree_translation_data = backend.parse_translation_files(full_tree_translation_file, full_tree_recomb_node_set)

app.config['translation_data'] = translation_data
app.config['full_tree_translation_data'] = full_tree_translation_data

# App parameter for public tree recombination results
app.config['info_sites'] = info_sites
Expand Down Expand Up @@ -653,6 +636,9 @@ def table():
app.config['genome_size'] = genome_size
app.config['genomic_range'] = genomic_range
app.config['gene_region_data'] = gene_region_data
# Name of persistent database file
app.config['db_file'] = config['db_file']
app.config['aa_tables'] = (config['aa_public'], config['aa_full'])

tock = time.perf_counter()
print(f"Time elapsed: {tock-tick:.2f} seconds")
Expand Down
18 changes: 15 additions & 3 deletions static/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -77,19 +77,31 @@ div#off_canvas_right_body {

#view_usher {
position:absolute;
bottom: 165;
bottom: 200;
left: 10;
}

#view_usher_donor {
position:absolute;
bottom: 155;
left: 10;
}

#view_usher_acceptor {
position:absolute;
bottom: 110;
left: 10;
}

#show_mutations {
position:absolute;
bottom: 115;
bottom: 65;
left: 10;
}

#view_tree {
position:absolute;
bottom: 65;
bottom: 20;
left: 10;
}

Expand Down
4 changes: 2 additions & 2 deletions static/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ function usher_button_info_display(tooltip) {
'px');
}

function view_usher_tree(d) {
function view_usher_tree(d, node_type) {
let tree_selected = 'public';
let full_table_select = document.getElementById('full_table');
// Check if public or full table is selected
Expand All @@ -98,7 +98,7 @@ function view_usher_tree(d) {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify(
{node: d['NODE_IDS']['Recomb'], tree: tree_selected})
{node: d['NODE_IDS'][node_type], tree: tree_selected, type: node_type })
}).then(res => {
res.json().then(data => {
// Open usher.bio link in new tab
Expand Down
Loading

0 comments on commit c5984b8

Please sign in to comment.