diff --git a/environments/gut-to-soil-manuscript-figures-qiime2-tiny-2024.5.yml b/environments/gut-to-soil-manuscript-figures-qiime2-tiny-2024.5.yml
index aaad62d..822342e 100644
--- a/environments/gut-to-soil-manuscript-figures-qiime2-tiny-2024.5.yml
+++ b/environments/gut-to-soil-manuscript-figures-qiime2-tiny-2024.5.yml
@@ -1,16 +1,11 @@
channels:
- https://packages.qiime2.org/qiime2/2024.5/tiny/passed
+- https://packages.qiime2.org/qiime2/2024.5/amplicon/passed
- conda-forge
- bioconda
dependencies:
- qiime2-tiny
- # Note 1: Add any additional conda dependencies here.
+ - q2-diversity
- pip
- pip:
- # Note 2: Add any additional pip dependencies here.
- # - # some pip dependency
- # Note 3: If you host your repository on GitHub, and you uncomment and modify
- # the following lines to replace REPO-OWNER with the user or organization
- # name that owns the repository, your installation commands can be updated to
- # install from this file without additional steps.
- # - "gut-to-soil-manuscript-figures @ git+https://github.com/REPO-OWNER/gut-to-soil-manuscript-figures.git"
+ - gut_to_soil_manuscript_figures@git+https://github.com/caporaso-lab/gut-to-soil-manuscript-figures.git
diff --git a/gut_to_soil_manuscript_figures/_methods.py b/gut_to_soil_manuscript_figures/_methods.py
index 65dd42f..96d131b 100644
--- a/gut_to_soil_manuscript_figures/_methods.py
+++ b/gut_to_soil_manuscript_figures/_methods.py
@@ -6,8 +6,80 @@
# The full license is in the file LICENSE, distributed with this software.
# ----------------------------------------------------------------------------
-import pandas as pd
+import os
+import pkg_resources
+import skbio
+import subprocess
+import qiime2
-def duplicate_table(table: pd.DataFrame) -> pd.DataFrame:
- return table
+
+def pcoa_2d(output_dir: str, metadata: qiime2.Metadata,
+ ordination: skbio.OrdinationResults,
+ measure: str = 'Unweighted Unifrac',
+ average: bool = False, week_annotations: bool = False,
+ invert_x: bool = False, invert_y: bool = False,
+ swap_axes: bool = False, himalaya: bool = False,
+ pit_toilet: bool = False, export_legend: bool = False,
+ highlighted_buckets: str = ''):
+
+ md = metadata.to_dataframe()
+
+ metadata_fp = os.path.join(output_dir, 'metadata.tsv')
+ ordination_fp = os.path.join(output_dir, 'ordination.txt')
+
+ md.to_csv(metadata_fp, sep='\t', index_label='sample-id')
+ ordination.write(ordination_fp)
+
+ script_path = \
+ pkg_resources.resource_filename(
+ 'gut_to_soil_manuscript_figures',
+ 'scripts/plot_pcoa_2d.py'
+ )
+
+ average = str(average)
+ week_annotations = str(week_annotations)
+ invert_x = str(invert_x)
+ invert_y = str(invert_y)
+ swap_axes = str(swap_axes)
+ himalaya = str(himalaya)
+ pit_toilet = str(pit_toilet)
+ export_legend = str(export_legend)
+
+ plot_fp = os.path.join(output_dir, 'pcoa_plot.png')
+
+ if export_legend:
+ legend_fp = os.path.join(output_dir, 'legend.png')
+
+ command = [
+ 'python', script_path,
+ metadata_fp,
+ ordination_fp,
+ measure,
+ average,
+ week_annotations,
+ plot_fp,
+ invert_x,
+ invert_y,
+ swap_axes,
+ himalaya,
+ pit_toilet,
+ export_legend,
+ highlighted_buckets,
+ legend_fp
+ ]
+ subprocess.run(command, check=True)
+
+ with open(os.path.join(output_dir, 'index.html'), 'w') as f:
+ f.write('''
+
+
+
+ 2D PCoA Plot
+
+
+ 2D PCoA Plot
+
+
+
+ ''')
diff --git a/gut_to_soil_manuscript_figures/plugin_setup.py b/gut_to_soil_manuscript_figures/plugin_setup.py
index 9eeb431..50fdf8f 100644
--- a/gut_to_soil_manuscript_figures/plugin_setup.py
+++ b/gut_to_soil_manuscript_figures/plugin_setup.py
@@ -6,36 +6,41 @@
# The full license is in the file LICENSE, distributed with this software.
# ----------------------------------------------------------------------------
-from qiime2.plugin import Citations, Plugin
-from q2_types.feature_table import FeatureTable, Frequency
-from gut_to_soil_manuscript_figures import __version__
-from gut_to_soil_manuscript_figures._methods import duplicate_table
+from qiime2.plugin import Plugin, Metadata, Bool, Str
+
+from q2_types.ordination import PCoAResults
-citations = Citations.load("citations.bib", package="gut_to_soil_manuscript_figures")
+from gut_to_soil_manuscript_figures import __version__
+from gut_to_soil_manuscript_figures._methods import pcoa_2d
plugin = Plugin(
- name="gut-to-soil-manuscript-figures",
+ name='gut-to-soil-manuscript-figures',
version=__version__,
- website="https://github.com/caporaso-lab/gut-to-coil-manuscript-figures/",
- package="gut_to_soil_manuscript_figures",
- description="Plugin that contains methods for figure generation used in Jeff Meilander's PhD manuscript",
- short_description="Plugin template.",
- # The plugin-level citation of 'Caporaso-Bolyen-2024' is provided as
- # an example. You can replace this with citations to other references
- # in citations.bib.
- citations=[citations['Caporaso-Bolyen-2024']]
+ website='https://github.com/caporaso-lab/gut-to-coil-manuscript-figures/',
+ package='gut_to_soil_manuscript_figures',
+ description="Plugin that contains methods for figure generation used in"
+ " Jeff Meilander's PhD manuscript.",
+ short_description=''
)
-plugin.methods.register_function(
- function=duplicate_table,
- inputs={'table': FeatureTable[Frequency]},
- parameters={},
- outputs=[('new_table', FeatureTable[Frequency])],
- input_descriptions={'table': 'The feature table to be duplicated.'},
+plugin.visualizers.register_function(
+ function=pcoa_2d,
+ inputs={'ordination': PCoAResults},
+ parameters={
+ 'metadata': Metadata,
+ 'measure': Str,
+ 'average': Bool,
+ 'week_annotations': Bool,
+ 'invert_x': Bool,
+ 'invert_y': Bool,
+ 'swap_axes': Bool,
+ 'himalaya': Bool,
+ 'pit_toilet': Bool,
+ 'export_legend': Bool,
+ 'highlighted_buckets': Str
+ },
+ input_descriptions={},
parameter_descriptions={},
- output_descriptions={'new_table': 'The duplicated feature table.'},
- name='Duplicate table',
- description=("Create a copy of a feature table with a new uuid. "
- "This is for demonstration purposes only. 🧐"),
- citations=[]
+ name='',
+ description=('')
)
diff --git a/gut_to_soil_manuscript_figures/scripts/plot_pcoa_2d.py b/gut_to_soil_manuscript_figures/scripts/plot_pcoa_2d.py
new file mode 100644
index 0000000..a4cb7be
--- /dev/null
+++ b/gut_to_soil_manuscript_figures/scripts/plot_pcoa_2d.py
@@ -0,0 +1,525 @@
+#!/usr/bin/python3
+
+import sys
+import skbio
+import numpy as np
+import pandas as pd
+import matplotlib as mpl
+import matplotlib.pyplot as plt
+
+
+# HELPER METHODS
+# util for converting sample IDs to ordination XY coords & swapping axes
+def _swap_axis(df, sample_type, swap):
+ if swap == 'False':
+ x = df.loc[sample_type][0]
+ y = df.loc[sample_type][1]
+ elif swap == 'True':
+ x = df.loc[sample_type][1]
+ y = df.loc[sample_type][0]
+ else:
+ raise ValueError('Invalid selection for `swap_axes` parameter.'
+ ' Must either be `True` or `False`.')
+
+ return x, y
+
+
+# util for highlighted bucket handling
+def _bucket_util(highlighted_buckets, md, ord_2d):
+ # handles multiple buckets being entered via command line/jupyter notebook
+ # entire input for this command is a string, split on commas
+ if ',' in highlighted_buckets:
+ bucket_list = [int(x) for x in highlighted_buckets.split(',')]
+ else:
+ bucket_list = [int(highlighted_buckets)]
+
+ # empty dicts to be filled with details for each bucket's time series
+ # details & then starting details (i.e. HE & bulking)
+ buckets_dict = {}
+ bucket_starts_dict = {}
+
+ for bucket in bucket_list:
+ # sorting the MD by week for line plot
+ # connecting time series data in order
+ md_bucket_sorted = \
+ md[(md['Bucket'] == bucket) &
+ (md['SampleType2'] == 'Compost Post-Roll')].sort_values('Week')
+
+ # week 1-52 IDs for selected bucket
+ bucket_ids_sorted = \
+ md_bucket_sorted[md_bucket_sorted['Week'] > 0.0].index.values
+
+ # making sure bucket IDs used are only ones that are present in both
+ # the md and ordination results
+ bucket_ids = []
+ for i in bucket_ids_sorted:
+ if i in ord_2d.index.values:
+ bucket_ids.append(i)
+
+ buckets_dict[bucket] = bucket_ids
+
+ # week 0 i.e. inputs for dotted line connecting HE & bulking -> HEC
+ # HE
+ bucket_ids_HE_week0 = \
+ md[(md['Bucket'] == bucket) &
+ (md['SampleType2'] == 'Self Sample') &
+ (md['Week'] == 0.0)].index.values
+
+ ids_HE_week0 = []
+ for i in bucket_ids_HE_week0:
+ if i in ord_2d.index.values:
+ ids_HE_week0.append(i)
+
+ # bulking
+ bucket_ids_bulk_week0 = \
+ md[(md['Bucket'] == bucket) &
+ (md['SampleType2'] == 'Bulking Material') &
+ (md['Week'] == 0.0)].index.values
+
+ ids_bulk_week0 = []
+ for i in bucket_ids_bulk_week0:
+ if i in ord_2d.index.values:
+ ids_bulk_week0.append(i)
+
+ # week 1 i.e. end points for dotted line connecting HE & BM -> HEC
+ bucket_ids_HEC_week1 = \
+ md_bucket_sorted[md_bucket_sorted['Week'] == 1.0].index.values
+
+ ids_HEC_week1 = []
+ for i in bucket_ids_HEC_week1:
+ if i in ord_2d.index.values:
+ ids_HEC_week1.append(i)
+
+ # nested dict for each bucket start info: HE week0, bulking, HEC week1
+ bucket_starts_dict[bucket] = {
+ 'HE_week0': [i for i in ids_HE_week0],
+ 'bulk_week0': [i for i in ids_bulk_week0],
+ 'HEC_week1': [i for i in ids_HEC_week1]
+ }
+
+ selected_buckets_ids = [i for i in buckets_dict.values()]
+ bucket_set = {i for lst in selected_buckets_ids for i in lst}
+
+ return buckets_dict, selected_buckets_ids, bucket_set, bucket_starts_dict
+
+
+# MAIN METHOD #
+def plot_pcoa_2d(metadata_fp, ordination_fp, measure,
+ average, week_annotations, plot_fp,
+ invert_x, invert_y, swap_axes,
+ himalaya, pit_toilet, export_legend,
+ highlighted_buckets=None, legend_fp=None):
+
+ ord_rslts = skbio.OrdinationResults.read(str(ordination_fp))
+ ord_2d = ord_rslts.samples.iloc[:, 0:2]
+
+ metadata_in = pd.read_csv(str(metadata_fp),
+ sep='\t').set_index('sample-id')
+ # filtering metadata to only include samples w/IDs present in ordination
+ metadata = metadata_in.loc[ord_2d.index.values]
+
+ # setting XY labels based on swap axis &
+ # figure aspect based on proportion explained
+ if swap_axes == 'True':
+ fig_aspect = \
+ ord_rslts.proportion_explained[0]/ord_rslts.proportion_explained[1]
+ x_label = 2
+ y_label = 1
+ elif swap_axes == 'False':
+ fig_aspect = \
+ ord_rslts.proportion_explained[1]/ord_rslts.proportion_explained[0]
+ x_label = 1
+ y_label = 2
+ else:
+ raise ValueError('Invalid value for `swap_axes` parameter.'
+ ' Must be either `True` or `False`.')
+
+ # invering XY axis based on x and/or y invert
+ if invert_x == 'True':
+ ord_2d[0] = ord_2d[0].multiply(-1)
+ if invert_y == 'True':
+ ord_2d[1] = ord_2d[1].multiply(-1)
+
+ # allowed sample types to be pulled from the md
+ sample_types = ['EMP-Soils', 'Food-Compost', 'Self Sample',
+ 'Compost Post-Roll', 'Bulking Material', 'Pit Toilet']
+
+ # if using himalaya and/or pit toilet data
+ if himalaya == 'True':
+ sample_types.append('Himalaya')
+ if pit_toilet == 'True':
+ sample_types.append('Pit Toilet')
+
+ # sorting the filtered md (by allowed sample types) by week
+ md = metadata[metadata['SampleType2']
+ .isin(sample_types)].sort_values('Week')
+ md['Bucket'] = md['Bucket'].astype(float)
+ md['Week'] = md['Week'].astype(float)
+
+ buckets_md = md[md['Bucket'].between(1, 16)]
+
+ # ALL SUBJECT FECAL SAMPLES: IDs -> XY ordination points
+ fecal_ids = list(set(buckets_md[buckets_md['Week'] == 0.0].index.values) &
+ set(ord_2d.index.values))
+ x_fecal, y_fecal = _swap_axis(ord_2d, fecal_ids, swap_axes)
+
+ # ALL SUBJECT BULKING MATERIAL: IDs -> XY ordination points
+ bulking_ids = \
+ list(set(md[md['SampleType2'] == 'Bulking Material'].index.values) &
+ set(ord_2d.index.values))
+ x_bulking, y_bulking = _swap_axis(ord_2d, bulking_ids, swap_axes)
+
+ # (OPTIONAL) SELECTED BUCKET(S): IDs -> XY ordination points
+ if highlighted_buckets:
+ buckets_dict, selected_buckets_ids, bucket_set, bucket_starts_dict = \
+ _bucket_util(highlighted_buckets, md, ord_2d)
+
+ # (OPTIONAL) WEEKLY MEAN FOR ALL BUCKETS: IDs -> XY ordination points
+ if average == 'True':
+ weeks_md = md[md['Week'].between(1, 52)]
+ weeks = list(set(weeks_md['Week'].values))
+
+ # dicts for each week's mean x&y values
+ bucket_weekly_avgs_x = {}
+ bucket_weekly_avgs_y = {}
+
+ for week in weeks:
+ x_list = []
+ y_list = []
+
+ # filtering the md to only include post-roll sample types
+ weekly_bucket_ids = \
+ md[(md['Week'] == week) &
+ (md['SampleType2'] == 'Compost Post-Roll')].index.values
+
+ # only use IDs that are present both in the md and ordination
+ included_ids = []
+ for i in weekly_bucket_ids:
+ if i in ord_2d.index.values:
+ included_ids.append(i)
+
+ # grab weeks 1 & 52 separately to annotate 'start' and 'end' points
+ # for selected bucket(s) and weekly mean for all buckets
+ if week == 1.0:
+ x1, y1 = _swap_axis(ord_2d, included_ids, swap_axes)
+ x1_mean = np.mean(x1.values)
+ y1_mean = np.mean(y1.values)
+ elif week == 52.0:
+ x52, y52 = _swap_axis(ord_2d, included_ids, swap_axes)
+ x52_mean = np.mean(x52.values)
+ y52_mean = np.mean(y52.values)
+ else:
+ pass
+
+ # making sure x&y values correspond to correct ordination axis
+ if swap_axes == 'False':
+ x_list.append(ord_2d.loc[included_ids][0].values)
+ y_list.append(ord_2d.loc[included_ids][1].values)
+ elif swap_axes == 'True':
+ x_list.append(ord_2d.loc[included_ids][1].values)
+ y_list.append(ord_2d.loc[included_ids][0].values)
+ else:
+ raise ValueError('Invalid selection for `swap_axes` parameter.'
+ ' Must either be `True` or `False`.')
+
+ x_avg = np.mean(x_list)
+ bucket_weekly_avgs_x[week] = x_avg
+
+ y_avg = np.mean(y_list)
+ bucket_weekly_avgs_y[week] = y_avg
+
+ # only calculate mean for HE & bulking wk 0 if
+ # no highlighted bucket is selected
+ if not highlighted_buckets:
+ # HE wk 0 mean
+ HE_week0 = \
+ md[(md['SampleType2'] == 'Self Sample') &
+ (md['Week'] == 0.0)].index.values
+ ids_HE_week0 = []
+ for i in HE_week0:
+ if i in ord_2d.index.values:
+ ids_HE_week0.append(i)
+ x0_HE, y0_HE = _swap_axis(ord_2d, ids_HE_week0, swap_axes)
+ x0_HE_mean = np.mean(x0_HE)
+ y0_HE_mean = np.mean(y0_HE)
+
+ # bulk wk 0 mean
+ bulk_week0 = \
+ md[(md['SampleType2'] == 'Bulking Material') &
+ (md['Week'] == 0.0)].index.values
+ ids_bulk_week0 = []
+ for i in bulk_week0:
+ if i in ord_2d.index.values:
+ ids_bulk_week0.append(i)
+ x0_bulk, y0_bulk = _swap_axis(ord_2d, ids_bulk_week0, swap_axes)
+ x0_bulk_mean = np.mean(x0_bulk)
+ y0_bulk_mean = np.mean(y0_bulk)
+
+ # ALL BUCKETS (minus highlighted bucket(s))
+ all_bucket_ids_w_fecal = \
+ list(set(md[md['Bucket'].between(1, 16)].index.values) &
+ set(ord_2d.index.values))
+ all_bucket_ids = list(set(all_bucket_ids_w_fecal) - set(fecal_ids))
+
+ if highlighted_buckets:
+ bucket_ids = list(set(all_bucket_ids) - bucket_set)
+ else:
+ bucket_ids = list(set(all_bucket_ids))
+ x_buckets, y_buckets = _swap_axis(ord_2d, bucket_ids, swap_axes)
+
+ # EMP SOILS
+ emp_ids = md.loc[md['Bucket'] == 0.0].index.values
+ x_emp, y_emp = _swap_axis(ord_2d, emp_ids, swap_axes)
+
+ # FOOD COMPOST
+ compost_ids = \
+ list(set(md.loc[md['Bucket'] == 17.0].index.values) &
+ set(ord_2d.index.values))
+ x_compost, y_compost = _swap_axis(ord_2d, compost_ids, swap_axes)
+
+ # (OPTIONAL SAMPLE TYPES) HIMALAYA
+ if himalaya == 'True':
+ hima_ids = md.loc[md['Bucket'] == 18.0].index.values
+ x_hima, y_hima = _swap_axis(ord_2d, hima_ids, swap_axes)
+
+ # (OPTIONAL SAMPLE TYPES) PIT TOILET
+ if pit_toilet == 'True':
+ pt_ids = md.loc[md['Bucket'] == 19.0].index.values
+ x_pt, y_pt = _swap_axis(ord_2d, pt_ids, swap_axes)
+
+ # Setting up the plot & axis
+ fig, ax = plt.subplots(1, 1, figsize=(15, 8))
+ ax.set_aspect(aspect=fig_aspect)
+
+ # DEFINING THE COLORMAP FOR EACH SELECTED BUCKET
+ if highlighted_buckets:
+ color_idx = np.linspace(0, 1, len(buckets_dict))
+ color_dict = dict(zip(buckets_dict.keys(), color_idx))
+ viridis = mpl.colormaps['viridis'].resampled(len(buckets_dict))
+
+ # Fecal - all subjects
+ fecal_scatter = \
+ plt.scatter(x=x_fecal, y=y_fecal, facecolors='none',
+ edgecolors='tab:brown',
+ label='HE (other buckets)')
+
+ # Bulking Material - all subjects
+ bulking_scatter = \
+ plt.scatter(x=x_bulking, y=y_bulking, facecolors='none',
+ edgecolors='g', label='Bulking Material (other buckets)')
+
+ # All buckets (minus highlighted bucket(s))
+ all_sample_buckets = \
+ plt.scatter(x=x_buckets, y=y_buckets, facecolors='none',
+ edgecolors='#C5C9C7', marker='^',
+ label='HEC (other buckets)')
+
+ # (OPTIONAL) Weekly Mean for all Buckets
+ if average == 'True':
+ bucket_avgs_scatter = \
+ plt.scatter(x=bucket_weekly_avgs_x.values(),
+ y=bucket_weekly_avgs_y.values(),
+ marker='*', facecolors='#1f77b4',
+ s=100, label='HEC (Weekly Mean)')
+
+ # adding HE mean if only plotting the weekly mean
+ # (w/o any highlighted bucket(s))
+ if not highlighted_buckets:
+ # HE
+ HE_week0_scatter = \
+ plt.scatter(x=x0_HE_mean, y=y0_HE_mean,
+ marker='*', s=150, zorder=1,
+ facecolors='tab:brown', edgecolors='k',
+ label='HE (Weekly Mean)')
+
+ # bulking
+ bulk_week0_scatter = \
+ plt.scatter(x=x0_bulk_mean, y=y0_bulk_mean,
+ marker='*', s=150, zorder=1,
+ facecolors='g', edgecolors='k',
+ label='Bulking Material (Weekly Mean)')
+
+ # EMP Soil
+ emp_soil_scatter = plt.scatter(x=x_emp, y=y_emp,
+ facecolors='k', label='Soil')
+
+ # Food Compost
+ food_compost_scatter = plt.scatter(x=x_compost, y=y_compost,
+ facecolors='r',
+ label='FLWC')
+
+ # (OPTIONAL SAMPLE TYPES) Himalaya
+ if himalaya == 'True':
+ himalaya_scatter = plt.scatter(x=x_hima, y=y_hima,
+ facecolors='b', label='Himalaya')
+
+ # (OPTIONAL SAMPLE TYPES) Pit Toilet
+ if pit_toilet == 'True':
+ pit_toilet_scatter = plt.scatter(x=x_pt, y=y_pt,
+ facecolors='y', label='Pit Toilet')
+
+ # collecting the handle info to add to the legend
+ bucket_handles = []
+ bucket_nums = []
+
+ # (OPTIONAL) HIGHLIGHTED BUCKET(S)
+ if highlighted_buckets:
+ # adding start info (HE, bulking -> HEC wk1) for highlighted bucket(s)
+ for bucket, ids in bucket_starts_dict.items():
+ if swap_axes == 'False':
+ x0_HE = ord_2d.loc[ids['HE_week0']][0]
+ y0_HE = ord_2d.loc[ids['HE_week0']][1]
+
+ x0_bulk = ord_2d.loc[ids['bulk_week0']][0]
+ y0_bulk = ord_2d.loc[ids['bulk_week0']][1]
+
+ x1_HEC = ord_2d.loc[ids['HEC_week1']][0]
+ y1_HEC = ord_2d.loc[ids['HEC_week1']][1]
+
+ elif swap_axes == 'True':
+ x0_HE = ord_2d.loc[ids['HE_week0']][1]
+ y0_HE = ord_2d.loc[ids['HE_week0']][0]
+
+ x0_bulk = ord_2d.loc[ids['bulk_week0']][1]
+ y0_bulk = ord_2d.loc[ids['bulk_week0']][0]
+
+ x1_HEC = ord_2d.loc[ids['HEC_week1']][1]
+ y1_HEC = ord_2d.loc[ids['HEC_week1']][0]
+
+ for x, y in zip(x0_HE, y0_HE):
+ ax.plot([x, float(x1_HEC.values)],
+ [y, float(y1_HEC.values)],
+ '--', color='#C5C9C7',
+ linewidth=0.75, zorder=1)
+
+ for x, y in zip(x0_bulk, y0_bulk):
+ ax.plot([x, float(x1_HEC.values)],
+ [y, float(y1_HEC.values)],
+ '--', color='#C5C9C7',
+ linewidth=0.75, zorder=1)
+
+ HE_week0_scatter = \
+ plt.scatter(x=x0_HE, y=y0_HE, facecolors='tab:brown',
+ label=f'HE (Bucket #{bucket})')
+ bucket_handles.append(HE_week0_scatter)
+
+ bulk_week0_scatter = \
+ plt.scatter(x=x0_bulk, y=y0_bulk, facecolors='g',
+ label=f'Bulking Material (Bucket #{bucket})')
+ bucket_handles.append(bulk_week0_scatter)
+
+ for bucket, ids in buckets_dict.items():
+ x_bucket, y_bucket = _swap_axis(ord_2d, ids, swap_axes)
+
+ ax.plot(x_bucket, y_bucket, color='k', zorder=1)
+
+ highlighted_bucket_scatter = \
+ plt.scatter(x=x_bucket, y=y_bucket,
+ facecolors=viridis(color_dict[bucket]),
+ edgecolors='k', marker='^',
+ label=f'HEC (Bucket #{bucket})')
+
+ bucket_handles.append(highlighted_bucket_scatter)
+ bucket_nums.append(bucket)
+
+ # adding week annotations for each highlighted bucket
+ if week_annotations == 'True':
+ for week, x, y in zip((md.loc[ids]['Week']),
+ x_bucket, y_bucket):
+ week_int = int(week)
+ ax.annotate(str(week_int), weight='bold', color='purple',
+ xy=(x, y), xytext=((x+0.002), (y+0.002)))
+ elif week_annotations == 'False':
+ # adding start/end notations for each highlighted bucket
+ ax.annotate('Start', weight='bold', color='purple',
+ xy=(x_bucket[0], y_bucket[0]),
+ xytext=((x_bucket[0]+0.002),
+ (y_bucket[0]+0.002)))
+ ax.annotate('End', weight='bold', color='purple',
+ xy=(x_bucket[-1], y_bucket[-1]),
+ xytext=((x_bucket[-1]+0.005),
+ (y_bucket[-1]+0.002)))
+
+ # appending legend info for non-highlighted subject data
+ bucket_handles.append(fecal_scatter)
+ bucket_handles.append(bulking_scatter)
+ bucket_handles.append(all_sample_buckets)
+
+ if average == 'True':
+ if not highlighted_buckets:
+ bucket_handles.append(HE_week0_scatter)
+ bucket_handles.append(bulk_week0_scatter)
+ bucket_handles.append(bucket_avgs_scatter)
+
+ bucket_handles.append(food_compost_scatter)
+ bucket_handles.append(emp_soil_scatter)
+
+ if himalaya == 'True':
+ bucket_handles.append(himalaya_scatter)
+
+ if pit_toilet == 'True':
+ bucket_handles.append(pit_toilet_scatter)
+
+ # (OPTIONAL) Weekly Mean for all Buckets
+ if average == 'True':
+ ax.plot(bucket_weekly_avgs_x.values(),
+ bucket_weekly_avgs_y.values(), color='#1f77b4')
+ ax.annotate('Start', weight='bold', xy=(x1_mean, y1_mean),
+ xytext=((x1_mean+0.002), (y1_mean+0.002)))
+ ax.annotate('End', weight='bold', xy=(x52_mean, y52_mean),
+ xytext=((x52_mean+0.005), (y52_mean+0.002)))
+
+ if not highlighted_buckets:
+ ax.plot([x0_HE_mean, x1_mean], [y0_HE_mean, y1_mean],
+ '--', color='#C5C9C7', linewidth=0.75, zorder=2)
+ ax.plot([x0_bulk_mean, x1_mean], [y0_bulk_mean, y1_mean],
+ '--', color='#C5C9C7', linewidth=0.75, zorder=2)
+
+ # Adding title, labels & legend details
+ plt.gca().set(xlabel=f'PCoA {x_label}', ylabel=f'PCoA {y_label}',
+ title=f'{measure} for Bucket(s) {bucket_nums}',
+ label='Bucket#')
+
+ # Helper method for exporting legend as a separate figure
+ def _export_legend(legend, filename=legend_fp):
+ fig = legend.figure
+ fig.canvas.draw()
+ bbox = legend.get_window_extent().transformed(
+ fig.dpi_scale_trans.inverted())
+ fig.savefig(filename, dpi='figure', bbox_inches=bbox)
+
+ # Create the legend
+ legend = plt.legend(handles=bucket_handles, bbox_to_anchor=(1.1, 1.05))
+
+ if export_legend == 'True':
+ _export_legend(legend, legend_fp)
+ legend.remove()
+ else:
+ legend.set_bbox_to_anchor((1.1, 1.05))
+
+ # Save the main plot
+ plt.tight_layout()
+ plt.savefig(str(plot_fp), bbox_inches='tight')
+
+
+if __name__ == '__main__':
+ metadata_fp = sys.argv[1]
+ ordination_fp = sys.argv[2]
+ measure = sys.argv[3]
+ average = sys.argv[4]
+ week_annotations = sys.argv[5]
+ plot_fp = sys.argv[6]
+ invert_x = sys.argv[7]
+ invert_y = sys.argv[8]
+ swap_axes = sys.argv[9]
+ himalaya = sys.argv[10]
+ pit_toilet = sys.argv[11]
+ export_legend = sys.argv[12]
+ highlighted_buckets = sys.argv[13]
+ legend_fp = sys.argv[14]
+
+ plot_pcoa_2d(metadata_fp, ordination_fp, measure,
+ average, week_annotations, plot_fp,
+ invert_x, invert_y, swap_axes,
+ himalaya, pit_toilet, export_legend,
+ highlighted_buckets, legend_fp)
diff --git a/gut_to_soil_manuscript_figures/tests/test_methods.py b/gut_to_soil_manuscript_figures/tests/test_methods.py
index 6650d72..f9fbf02 100644
--- a/gut_to_soil_manuscript_figures/tests/test_methods.py
+++ b/gut_to_soil_manuscript_figures/tests/test_methods.py
@@ -6,39 +6,11 @@
# The full license is in the file LICENSE, distributed with this software.
# ----------------------------------------------------------------------------
-import pandas as pd
-import pandas.testing as pdt
-
from qiime2.plugin.testing import TestPluginBase
-from qiime2.plugin.util import transform
-from q2_types.feature_table import BIOMV100Format
-
-from gut_to_soil_manuscript_figures._methods import duplicate_table
-class DuplicateTableTests(TestPluginBase):
+class PCoATests(TestPluginBase):
package = 'gut_to_soil_manuscript_figures.tests'
def test_simple1(self):
- in_table = pd.DataFrame(
- [[1, 2, 3, 4, 5], [9, 10, 11, 12, 13]],
- columns=['abc', 'def', 'jkl', 'mno', 'pqr'],
- index=['sample-1', 'sample-2'])
- observed = duplicate_table(in_table)
-
- expected = in_table
-
- pdt.assert_frame_equal(observed, expected)
-
- def test_simple2(self):
- # test table duplication with table loaded from file this time
- # (for demonstration purposes)
- in_table = transform(
- self.get_data_path('table-1.biom'),
- from_type=BIOMV100Format,
- to_type=pd.DataFrame)
- observed = duplicate_table(in_table)
-
- expected = in_table
-
- pdt.assert_frame_equal(observed, expected)
+ pass
diff --git a/setup.py b/setup.py
index 4f05cef..39461b3 100644
--- a/setup.py
+++ b/setup.py
@@ -11,28 +11,31 @@
import versioneer
description = (
- "Plugin template."
+ 'Plugin template.'
)
setup(
- name="gut-to-soil-manuscript-figures",
+ name='gut-to-soil-manuscript-figures',
version=versioneer.get_version(),
cmdclass=versioneer.get_cmdclass(),
- license="BSD-3-Clause",
+ license='BSD-3-Clause',
packages=find_packages(),
- author="Liz Gehret",
- author_email="elizabeth.gehret@nau.edu",
+ author='Liz Gehret',
+ author_email='elizabeth.gehret@nau.edu',
description=description,
- url="https://github.com/caporaso-lab/gut-to-coil-manuscript-figures/",
+ url='https://github.com/caporaso-lab/gut-to-soil-manuscript-figures/',
entry_points={
- "qiime2.plugins": [
- "gut_to_soil_manuscript_figures="
- "gut_to_soil_manuscript_figures"
- ".plugin_setup:plugin"]
+ 'qiime2.plugins': [
+ 'gut-to-soil-manuscript-figures='
+ 'gut_to_soil_manuscript_figures'
+ '.plugin_setup:plugin']
},
package_data={
- "gut_to_soil_manuscript_figures": ["citations.bib"],
- "gut_to_soil_manuscript_figures.tests": ["data/*"],
+ 'gut_to_soil_manuscript_figures': [
+ 'citations.bib',
+ 'scripts/*'
+ ],
+ 'gut_to_soil_manuscript_figures.tests': ['data/*'],
},
zip_safe=False,
)