Skip to content

Commit

Permalink
- fix 1 trait -> overview.js simply forwards to trait.js
Browse files Browse the repository at this point in the history
- fix bug: gene popovers if isGeneList, not if isNumeric!
  • Loading branch information
MrTomRod committed May 3, 2022
1 parent 5a7f696 commit e24e5ef
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 61 deletions.
115 changes: 59 additions & 56 deletions scoary/create_final_overview.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,77 +121,80 @@ def create_final_overview(overview_ds: pd.DataFrame, ns: MockNamespace, isolate_
if isolate_info_df is not None:
isolate_info_df.to_csv(f'{ns.outdir}/isolate_info.tsv', sep='\t')

# prepare data, create linkage_matrix
pre_jaccard = ns.traits_df[overview_ds.index].astype('float').T
pre_jaccard = ((pre_jaccard.fillna(0.5) * 2) - 1).astype('int') # False -> -1, NAN -> 0, True -> 1

# whether class=0 and class=1 are arbitrary. Calculate both possibilities, take minimum
d1 = cdist(pre_jaccard, pre_jaccard, metric='jaccard')
d2 = cdist(pre_jaccard, 0 - pre_jaccard, metric='jaccard')
jaccard_distance = np.minimum(d1, d2)

jaccard_df = pd.DataFrame(
jaccard_distance, columns=pre_jaccard.index, index=pre_jaccard.index
)
linkage_matrix = hierarchy.linkage(squareform(jaccard_df), 'single')
overview_ds_index = list(overview_ds.index)
if len(overview_ds) > 1:
# prepare data, create linkage_matrix
pre_jaccard = ns.traits_df[overview_ds.index].astype('float').T
pre_jaccard = ((pre_jaccard.fillna(0.5) * 2) - 1).astype('int') # False -> -1, NAN -> 0, True -> 1

# whether class=0 and class=1 are arbitrary. Calculate both possibilities, take minimum
d1 = cdist(pre_jaccard, pre_jaccard, metric='jaccard')
d2 = cdist(pre_jaccard, 0 - pre_jaccard, metric='jaccard')
jaccard_distance = np.minimum(d1, d2)

jaccard_df = pd.DataFrame(
jaccard_distance, columns=pre_jaccard.index, index=pre_jaccard.index
)
linkage_matrix = hierarchy.linkage(squareform(jaccard_df), 'single')

# calculate plot proportions
content_height = max(3., len(jaccard_df) / 6) # height dependent on number of compounds
whitespace_abs = 0.6 # absolute amount of whitespace
total_height = content_height + whitespace_abs # total plot height
whitespace_rel = whitespace_abs / 3 / total_height # relative amount of whitespace

# create matplotlib figure
plt.close()
fig = plt.figure(figsize=(7, total_height))
gs = fig.add_gridspec(
nrows=1, ncols=2, width_ratios=(7, 1),
left=0.05, right=0.6, bottom=whitespace_rel * 2, top=1 - whitespace_rel,
wspace=0, hspace=0,
# wspace=0.05, hspace=0.05,
)

# calculate plot proportions
content_height = max(3., len(jaccard_df) / 6) # height dependent on number of compounds
whitespace_abs = 0.6 # absolute amount of whitespace
total_height = content_height + whitespace_abs # total plot height
whitespace_rel = whitespace_abs / 3 / total_height # relative amount of whitespace
# get axes objects with shared y-axis
ax_dendrogram = fig.add_subplot(gs[0, 0])
ax_colorbar = fig.add_subplot(gs[0, 1], sharey=ax_dendrogram)

# create matplotlib figure
plt.close()
fig = plt.figure(figsize=(7, total_height))
gs = fig.add_gridspec(
nrows=1, ncols=2, width_ratios=(7, 1),
left=0.05, right=0.6, bottom=whitespace_rel * 2, top=1 - whitespace_rel,
wspace=0, hspace=0,
# wspace=0.05, hspace=0.05,
)
# plot dendrogram
dendrogram_params = plot_dendrogram(linkage_matrix, labels=jaccard_df.columns.values, ax=ax_dendrogram)

# get axes objects with shared y-axis
ax_dendrogram = fig.add_subplot(gs[0, 0])
ax_colorbar = fig.add_subplot(gs[0, 1], sharey=ax_dendrogram)
# reindex overview_ds according to order in dendrogram
overview_ds_index = dendrogram_params['ivl'][::-1]
overview_ds = overview_ds.reindex(overview_ds_index)

# plot dendrogram
dendrogram_params = plot_dendrogram(linkage_matrix, labels=jaccard_df.columns.values, ax=ax_dendrogram)
# plot qvals
cmaps = {
'min_qval': 'Spectral',
'min_pval_empirical': LinearSegmentedColormap.from_list(
name='pval_emp_cbar',
colors=['#590d22', '#800f2f', '#a4133c', '#c9184a', '#ff4d6d',
'#ff758f', '#ff8fa3', '#ffb3c1', '#ffccd5', '#fff0f3'])
}
cols = [col for col in cmaps.keys() if col in overview_ds.columns]
pcms = plot_qvals(overview_ds[cols], fig=fig, ax=ax_colorbar, cmaps=cmaps)

# reindex overview_ds according to order in dendrogram
dendrogram_index = dendrogram_params['ivl'][::-1]
overview_ds = overview_ds.reindex(dendrogram_index)
overview_ds.index.name = 'Trait'
# save plot
plt.savefig(f'{ns.outdir}/overview_plot.svg', format='svg')
plt.close()

# plot qvals
cmaps = {
'min_qval': 'Spectral',
'min_pval_empirical': LinearSegmentedColormap.from_list(
name='pval_emp_cbar',
colors=['#590d22', '#800f2f', '#a4133c', '#c9184a', '#ff4d6d',
'#ff758f', '#ff8fa3', '#ffb3c1', '#ffccd5', '#fff0f3'])
}
cols = [col for col in cmaps.keys() if col in overview_ds.columns]
pcms = plot_qvals(overview_ds[cols], fig=fig, ax=ax_colorbar, cmaps=cmaps)

# save plot
plt.savefig(f'{ns.outdir}/overview_plot.svg', format='svg')
plt.close()
# create color bar, save
save_colorbars(pcms, [c.removeprefix('min_') for c in cols], out=f'{ns.outdir}/overview_colorbar.svg')

# copy files
files = [f'{file_name}.{file_type}' for file_type in ('html', 'css', 'js') for file_name in ('overview', 'trait')]
files.append('config.json')
import os
for file in files:
os.symlink(src=f'{ROOT_DIR}/templates/{file}', dst=f'{ns.outdir}/{file}')
copy(src=f'{ROOT_DIR}/templates/favicon.ico', dst=f'{ns.outdir}/favicon.ico')

# create color bar, save
save_colorbars(pcms, [c.removeprefix('min_') for c in cols], out=f'{ns.outdir}/overview_colorbar.svg')

if ns.trait_info_df is not None:
overview_ds = overview_ds \
.merge(ns.trait_info_df, left_index=True, right_index=True, how='left', copy=False) \
.reindex(dendrogram_index) # merging destroys index order
.reindex(overview_ds_index) # merging destroys index order

# save overview_ds (reversed index, so the order matches the plot)
overview_ds.reindex(dendrogram_index).to_csv(f'{ns.outdir}/overview.tsv', sep='\t')
# save overview_ds, ensure order matches plot
overview_ds.index.name = 'Trait'
overview_ds.to_csv(f'{ns.outdir}/overview.tsv', sep='\t')
11 changes: 8 additions & 3 deletions scoary/load_genes.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,14 @@ def filter_df(df: pd.DataFrame, restrict_to: [str] = None, ignore: [str] = None)
df = df[[c for c in df.columns if c not in ignore]]

if restrict_to is not None:
cols_missing = set(restrict_to).difference(set(df.columns))
assert len(cols_missing) == 0, f'Some strains in restrict_to were not found: {cols_missing}'
cols_dropped = set(restrict_to).difference(set(df.columns))
restrict_to = set(restrict_to)
have_cols = set(df.columns)
cols_missing = restrict_to.difference(have_cols)
assert len(cols_missing) == 0, f'Some strains in restrict_to were not found:' \
f'\n{cols_missing=}' \
f'\n{restrict_to=}' \
f'\n{have_cols=}'
cols_dropped = restrict_to.difference(set(df.columns))
logger.info(f'Cols kept: {list(restrict_to)}')
logger.info(f'Cols dropped: {list(cols_dropped)}')
df = df[[c for c in df.columns if c in restrict_to]]
Expand Down
4 changes: 3 additions & 1 deletion scoary/scoary.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,9 @@ def scoary(
end='\n'
)
overview_ds = create_final_overview_df(traits, res)
if overview_ds is not None and len(overview_ds) >= 2:
if overview_ds is None and len(overview_ds) == 0:
logging.warning(f'no content for overview_ds')
else:
create_final_overview(overview_ds, ns, isolate_info_df)

print(CITATION)
Expand Down
9 changes: 9 additions & 0 deletions scoary/templates/overview.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,15 @@ const overviewPromise = Papa.execPromise('overview.tsv', {
return 'no isolate info'
})

overviewPromise.then((overviewData) => {
if (overviewData.data.length == 1) {
const traitName = overviewData.data[0]['Trait']
const url = `./trait.html?trait=${traitName}`
console.info(`FORWARDING TO: ${url}`)
window.location.href = url
}
})

const loadSvgPromise = fetch('overview_plot.svg', {method: 'GET', headers: {}}).then(function (response) {
return response.text()
}).then((data) => {
Expand Down
2 changes: 1 addition & 1 deletion scoary/templates/trait.js
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ const coverageMatrixTablePromise = Promise.all(
return `${gene} x ${isolate}`
}

if (!cmValues.isNumeric) return cmValues
if (!cmValues.isGeneList) return cmValues

/**
* Make genes clickable depending on config.json.
Expand Down

0 comments on commit e24e5ef

Please sign in to comment.