---
title: "Schuck_animal_microbiome"
author: "Laura Schuck"
date: "`r Sys.Date()`"
output: html_document
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```

###Bioinformatics
We received filtered data from the sequencing facility. The filtering thresholds are described in the methods section.

Amplicon sequence data is available under NCBI (PRJNA1354894), isolates sequences are available in the AmphiBac database (https://github.com/AmphiBac). All data is also openly available at request to the correspondent author (laurakauerschuck@gmail.com)

```{bash bionformatics}
module load anaconda
conda activate qiime2-amplicon-2023.9


cd /storage/work/lxk5406/masters2
#gzip -d Rwads/*.gz

qiime tools import --type 'SampleData[SequencesWithQuality]'     --input-path sample_list.tsv     --output-path samples.qza     --input-format SingleEndFastqManifestPhred33V2

qiime dada2 denoise-single \
  --i-demultiplexed-seqs samples.qza \
   --p-trunc-len 0 \
   --p-n-threads 8 \
   --p-n-reads-learn 50000 \
   --output-dir dada2_output

#visualize dada2 table
qiime metadata tabulate \
  --m-input-file dada2_output/denoising_stats.qza \
  --o-visualization stats-dada2.qzv

qiime tools export --input-path dada2_output/denoising_stats.qza --output-path dada2_output
qiime tools export --input-path dada2_output/table.qza --output-path dada2_output_exported
qiime tools export --input-path dada2_output/representative_sequences.qza --output-path dada2_output_exported
biom convert -i dada2_output_exported/feature-table.biom -o dada2_output_exported/feature-table.txt --to-tsv


#change file names to match later script
mv /storage/work/lxk5406/masters2/dada2_output/representative_sequences.qza rep-seqs.qza
mv /storage/work/lxk5406/masters2/dada2_output/table.qza table.qza

#summarize the feature table
qiime feature-table summarize \
  --i-table table.qza \
  --m-sample-metadata-file metadata2.tsv \
  --o-visualization table.qzv
qiime feature-table tabulate-seqs \
  --i-data rep-seqs.qza \
  --o-visualization rep-seqs.qzv

#align sequences
qiime alignment mafft \
  --i-sequences ./rep-seqs.qza \
  --o-alignment seq_dada2_aligned.qza

#filter alignment
qiime alignment mask \
  --i-alignment ./seq_dada2_aligned.qza \
  --o-masked-alignment seq_dada2_aligned_filtered.qza

#create phylogenetic tree
qiime phylogeny fasttree \
  --i-alignment ./seq_dada2_aligned_filtered.qza \
  --o-tree tree_unrooted.qza

#root the phylogenetic tree
qiime phylogeny midpoint-root \
  --i-tree ./tree_unrooted.qza \
  --o-rooted-tree tree_rooted.qza

##tree completed

#download trained Bayesian classifier
#wget -O "gg_2022_10_backbone_full_length.nb.qza" https://data.qiime2.org/classifiers/greengenes/gg_2022_10_backbone_full_length.nb.qza

#assign taxonomy using classifier
qiime feature-classifier classify-sklearn \
  --i-classifier gg_2022_10_backbone_full_length.nb.qza \
  --i-reads ./rep-seqs.qza \
  --o-classification dada2_taxonomy.qza

#export taxonomy to get .tsv file with taxonomy for each feature
qiime tools export \
  --input-path ./dada2_taxonomy.qza \
  --output-path dada2_taxonomy

#filter OTU table based on taxonomy to remove mitochondria and chloroplasts
qiime taxa filter-table \
  --i-table ./table.qza \
  --i-taxonomy ./dada2_taxonomy.qza \
  --p-exclude mitochondria,chloroplast,Unassigned \
  --p-mode contains \
  --o-filtered-table table_filt2.qza

#filtered OTU table
qiime feature-table summarize \
  --i-table ./table_filt2.qza \
  --m-sample-metadata-file metadata2.tsv \
  --o-visualization table_filt2.qzv

#view rarefaction curves
qiime diversity alpha-rarefaction \
  --i-table ./table_filt2.qza \
  --p-max-depth 5620 \
  --p-metrics observed_features \
  --o-visualization alpha_rarefaction_r5620.qzv \
  --m-metadata-file ./metadata2.tsv 
  
  
#rarefy to 5620
qiime feature-table rarefy \
  --i-table ./table_filt2.qza \
  --p-sampling-depth 5620 \
  --o-rarefied-table table_filt_r5620.qza

qiime feature-table summarize \
  --i-table ./table_filt_r5620.qza \
  --m-sample-metadata-file ./metadata2.tsv \
  --o-visualization table_filt_r5620.qzv
  
  
  #get taxa barplots
qiime taxa barplot \
  --i-table ./table_filt_r5620.qza \
  --i-taxonomy ./dada2_taxonomy.qza \
  --m-metadata-file ./metadata2.tsv \
  --output-dir taxonomy_plots_r5620
  
#alpha diversity
qiime diversity core-metrics-phylogenetic \
  --i-phylogeny ./tree_rooted.qza \
  --i-table ./table_filt_r5620.qza \
  --p-sampling-depth 5620 \
  --m-metadata-file ./metadata2.tsv \
  --output-dir core_metrics_r5620
qiime tools export \
  --input-path ./core_metrics_r5620/observed_features_vector.qza \
  --output-path observed_features_r5620
qiime tools export \
  --input-path ./core_metrics_r5620/faith_pd_vector.qza \
  --output-path faith_pd_r5620
qiime tools export \
  --input-path ./core_metrics_r5620/evenness_vector.qza \
  --output-path evenness_r5620
qiime tools export \
  --input-path ./core_metrics_r5620/shannon_vector.qza \
  --output-path shannon_r5620

#Beta Diversity
qiime tools export \
  --input-path ./core_metrics_r5620/bray_curtis_distance_matrix.qza \
  --output-path bray_curtis_dm_r5620
qiime tools export \
  --input-path ./core_metrics_r5620/bray_curtis_pcoa_results.qza \
  --output-path bray_curtis_pcoa_r5620
qiime tools export \
  --input-path ./core_metrics_r5620/jaccard_distance_matrix.qza \
  --output-path jaccard_dm_r5620
qiime tools export \
  --input-path ./core_metrics_r5620/jaccard_pcoa_results.qza \
  --output-path jaccard_pcoa_r5620
qiime tools export \
  --input-path ./core_metrics_r5620/unweighted_unifrac_distance_matrix.qza \
  --output-path unweighted_unifrac_dm_r5620
qiime tools export \
  --input-path ./core_metrics_r5620/unweighted_unifrac_pcoa_results.qza \
  --output-path unweighted_unifrac_pcoa_r5620
qiime tools export \
  --input-path ./core_metrics_r5620/weighted_unifrac_distance_matrix.qza \
  --output-path weighted_unifrac_dm_r5620
qiime tools export \
  --input-path ./core_metrics_r5620/weighted_unifrac_pcoa_results.qza \
  --output-path weighted_unifrac_pcoa_r5620

#filter by host species
qiime feature-table filter-samples \
  --i-table ./table_filt_r5620.qza \
  --m-metadata-file ./metadata2.tsv \
  --p-where "condition='Haddadus binotatus'" \
  --o-filtered-table table_filt_r5620_had.qza \
  --p-no-exclude-ids

qiime feature-table filter-samples \
  --i-table ./table_filt_r5620.qza \
  --m-metadata-file ./metadata2.tsv \
  --p-where "condition='Ischnocnema henselii'" \
  --o-filtered-table table_filt_r5620_hen.qza \
  --p-no-exclude-ids


#calculate core microbiome
qiime feature-table core-features \
  --i-table ./table_filt_r5620_had.qza \
  --p-min-fraction 0.90 \
  --output-dir ./core_microbiome_r5620_had
qiime feature-table core-features \
  --i-table ./table_filt_r5620_hen.qza \
  --p-min-fraction 0.90 \
  --output-dir ./core_microbiome_r5620_hen

#NOTHING FOUND 


#core diversity
qiime diversity core-metrics-phylogenetic \
  --i-phylogeny ./tree_rooted.qza \
  --i-table ./table_filt_r5620_had.qza \
  --p-sampling-depth 5620 \
  --m-metadata-file ./metadata2.tsv \
  --output-dir core_metrics_r5620_had

qiime diversity core-metrics-phylogenetic \
  --i-phylogeny ./tree_rooted.qza \
  --i-table ./table_filt_r5620_hen.qza \
  --p-sampling-depth 5620 \
  --m-metadata-file ./metadata2.tsv \
  --output-dir core_metrics_r5620_hen


#Beta Diversity Haddadus
qiime tools export \
  --input-path ./core_metrics_r5620_had/bray_curtis_distance_matrix.qza \
  --output-path bray_curtis_dm_r5620_had
qiime tools export \
  --input-path ./core_metrics_r5620_had/bray_curtis_pcoa_results.qza \
  --output-path bray_curtis_pcoa_r5620_had
qiime tools export \
  --input-path ./core_metrics_r5620_had/jaccard_distance_matrix.qza \
  --output-path jaccard_dm_r5620_had
qiime tools export \
  --input-path ./core_metrics_r5620_had/jaccard_pcoa_results.qza \
  --output-path jaccard_pcoa_r5620_had
qiime tools export \
  --input-path ./core_metrics_r5620_had/unweighted_unifrac_distance_matrix.qza \
  --output-path unweighted_unifrac_dm_r5620_had
qiime tools export \
  --input-path ./core_metrics_r5620_had/unweighted_unifrac_pcoa_results.qza \
  --output-path unweighted_unifrac_pcoa_r5620_had
qiime tools export \
  --input-path ./core_metrics_r5620_had/weighted_unifrac_distance_matrix.qza \
  --output-path weighted_unifrac_dm_r5620_had
  
  --input-path ./core_metrics_r5620_had/weighted_unifrac_pcoa_results.qza \
  --output-path weighted_unifrac_pcoa_r5620_had

#Beta Diversity henselii
qiime tools export \
  --input-path ./core_metrics_r5620_hen/bray_curtis_distance_matrix.qza \
  --output-path bray_curtis_dm_r5620_hen
qiime tools export \
  --input-path ./core_metrics_r5620_hen/bray_curtis_pcoa_results.qza \
  --output-path bray_curtis_pcoa_r5620_hen
qiime tools export \
  --input-path ./core_metrics_r5620_hen/jaccard_distance_matrix.qza \
  --output-path jaccard_dm_r5620_hen
qiime tools export \
  --input-path ./core_metrics_r5620_hen/jaccard_pcoa_results.qza \
  --output-path jaccard_pcoa_r5620_hen
qiime tools export \
  --input-path ./core_metrics_r5620_hen/unweighted_unifrac_distance_matrix.qza \
  --output-path unweighted_unifrac_dm_r5620_hen
qiime tools export \
  --input-path ./core_metrics_r5620_hen/unweighted_unifrac_pcoa_results.qza \
  --output-path unweighted_unifrac_pcoa_r5620_hen
qiime tools export \
  --input-path ./core_metrics_r5620_hen/weighted_unifrac_distance_matrix.qza \
  --output-path weighted_unifrac_dm_r5620_hen
qiime tools export \
  --input-path ./core_metrics_r5620_hen/weighted_unifrac_pcoa_results.qza \
  --output-path weighted_unifrac_pcoa_r5620_hen
  
  
  
#filter by host species
#qiime feature-table filter-samples \
#  --i-table ./table_filt_r5620.qza \
#  --m-metadata-file ./metadata2.tsv \
#  --p-where "condition='Haddadus binotatus'" \
#  --o-filtered-table table_filt_r5620_had.qza \
#  --p-no-exclude-ids


#filter by host species and time
qiime feature-table filter-samples \
  --i-table ./table_filt_r5620_had.qza \
  --m-metadata-file ./metadata2.tsv \
  --p-where "time='field'" \
  --o-filtered-table table_filt_r5620_had_field.qza \
  --p-no-exclude-ids
 qiime feature-table filter-samples \
  --i-table ./table_filt_r5620_had.qza \
  --m-metadata-file ./metadata2.tsv \
  --p-where "time='post_ant'" \
  --o-filtered-table table_filt_r5620_had_pant.qza \
  --p-no-exclude-ids
qiime feature-table filter-samples \
  --i-table ./table_filt_r5620_had.qza \
  --m-metadata-file ./metadata2.tsv \
  --p-where "time='post_bd'" \
  --o-filtered-table table_filt_r5620_had_pbd.qza \
  --p-no-exclude-ids
qiime feature-table filter-samples \
  --i-table ./table_filt_r5620_had.qza \
  --m-metadata-file ./metadata2.tsv \
  --p-where "time='final'" \
  --o-filtered-table table_filt_r5620_had_final.qza \
  --p-no-exclude-ids
qiime feature-table filter-samples \
  --i-table ./table_filt_r5620_had.qza \
  --m-metadata-file ./metadata2.tsv \
  --p-where "time='post_mortem'" \
  --o-filtered-table table_filt_r5620_had_pmortem.qza \
  --p-no-exclude-ids

qiime diversity core-metrics-phylogenetic \
  --i-phylogeny ./tree_rooted.qza \
  --i-table ./table_filt_r5620_had_field.qza \
  --p-sampling-depth 5620 \
  --m-metadata-file ./metadata2.tsv \
  --output-dir core_metrics_r5620_had_field
qiime diversity core-metrics-phylogenetic \
  --i-phylogeny ./tree_rooted.qza \
  --i-table ./table_filt_r5620_had_pant.qza \
  --p-sampling-depth 5620 \
  --m-metadata-file ./metadata2.tsv \
  --output-dir core_metrics_r5620_had_pant
qiime diversity core-metrics-phylogenetic \
  --i-phylogeny ./tree_rooted.qza \
  --i-table ./table_filt_r5620_had_pbd.qza \
  --p-sampling-depth 5620 \
  --m-metadata-file ./metadata2.tsv \
  --output-dir core_metrics_r5620_had_pbd
qiime diversity core-metrics-phylogenetic \
  --i-phylogeny ./tree_rooted.qza \
  --i-table ./table_filt_r5620_had_final.qza \
  --p-sampling-depth 5620 \
  --m-metadata-file ./metadata2.tsv \
  --output-dir core_metrics_r5620_had_final
 qiime diversity core-metrics-phylogenetic \
  --i-phylogeny ./tree_rooted.qza \
  --i-table ./table_filt_r5620_had_pmortem.qza \
  --p-sampling-depth 5620 \
  --m-metadata-file ./metadata2.tsv \
  --output-dir core_metrics_r5620_had_pmortem


qiime tools export \
  --input-path ./core_metrics_r5620_had_field/unweighted_unifrac_pcoa_results.qza \
  --output-path unweighted_unifrac_pcoa_r5620_had_field
qiime tools export \
  --input-path ./core_metrics_r5620_had_pant/unweighted_unifrac_pcoa_results.qza \
  --output-path unweighted_unifrac_pcoa_r5620_had_pant
qiime tools export \
  --input-path ./core_metrics_r5620_had_pbd/unweighted_unifrac_pcoa_results.qza \
  --output-path unweighted_unifrac_pcoa_r5620_had_pbd
qiime tools export \
  --input-path ./core_metrics_r5620_had_final/unweighted_unifrac_pcoa_results.qza \
  --output-path unweighted_unifrac_pcoa_r5620_had_final
qiime tools export \
  --input-path ./core_metrics_r5620_had_pmortem/unweighted_unifrac_pcoa_results.qza \
  --output-path unweighted_unifrac_pcoa_r5620_had_pmortem


qiime feature-table filter-samples \
  --i-table ./table_filt_r5620.qza \
  --m-metadata-file ./metadata2.tsv \
  --p-where "condition='Ischnocnema henselii'" \
  --o-filtered-table table_filt_r5620_hen.qza \
  --p-no-exclude-ids


#filter by host species and time
qiime feature-table filter-samples \
  --i-table ./table_filt_r5620_hen.qza \
  --m-metadata-file ./metadata2.tsv \
  --p-where "time='field'" \
  --o-filtered-table table_filt_r5620_hen_field.qza \
  --p-no-exclude-ids
 qiime feature-table filter-samples \
  --i-table ./table_filt_r5620_hen.qza \
  --m-metadata-file ./metadata2.tsv \
  --p-where "time='post_ant'" \
  --o-filtered-table table_filt_r5620_hen_pant.qza \
  --p-no-exclude-ids
qiime feature-table filter-samples \
  --i-table ./table_filt_r5620_hen.qza \
  --m-metadata-file ./metadata2.tsv \
  --p-where "time='post_bd'" \
  --o-filtered-table table_filt_r5620_hen_pbd.qza \
  --p-no-exclude-ids
qiime feature-table filter-samples \
  --i-table ./table_filt_r5620_hen.qza \
  --m-metadata-file ./metadata2.tsv \
  --p-where "time='final'" \
  --o-filtered-table table_filt_r5620_hen_final.qza \
  --p-no-exclude-ids
qiime feature-table filter-samples \
  --i-table ./table_filt_r5620_hen.qza \
  --m-metadata-file ./metadata2.tsv \
  --p-where "time='post_mortem'" \
  --o-filtered-table table_filt_r5620_hen_pmortem.qza \
  --p-no-exclude-ids

qiime diversity core-metrics-phylogenetic \
  --i-phylogeny ./tree_rooted.qza \
  --i-table ./table_filt_r5620_hen_field.qza \
  --p-sampling-depth 5620 \
  --m-metadata-file ./metadata2.tsv \
  --output-dir core_metrics_r5620_hen_field
qiime diversity core-metrics-phylogenetic \
  --i-phylogeny ./tree_rooted.qza \
  --i-table ./table_filt_r5620_hen_pant.qza \
  --p-sampling-depth 5620 \
  --m-metadata-file ./metadata2.tsv \
  --output-dir core_metrics_r5620_hen_pant
qiime diversity core-metrics-phylogenetic \
  --i-phylogeny ./tree_rooted.qza \
  --i-table ./table_filt_r5620_hen_pbd.qza \
  --p-sampling-depth 5620 \
  --m-metadata-file ./metadata2.tsv \
  --output-dir core_metrics_r5620_hen_pbd
qiime diversity core-metrics-phylogenetic \
  --i-phylogeny ./tree_rooted.qza \
  --i-table ./table_filt_r5620_hen_final.qza \
  --p-sampling-depth 5620 \
  --m-metadata-file ./metadata2.tsv \
  --output-dir core_metrics_r5620_hen_final
 qiime diversity core-metrics-phylogenetic \
  --i-phylogeny ./tree_rooted.qza \
  --i-table ./table_filt_r5620_hen_pmortem.qza \
  --p-sampling-depth 5620 \
  --m-metadata-file ./metadata2.tsv \
  --output-dir core_metrics_r5620_hen_pmortem


qiime tools export \
  --input-path ./core_metrics_r5620_hen_field/unweighted_unifrac_pcoa_results.qza \
  --output-path unweighted_unifrac_pcoa_r5620_hen_field
qiime tools export \
  --input-path ./core_metrics_r5620_hen_pant/unweighted_unifrac_pcoa_results.qza \
  --output-path unweighted_unifrac_pcoa_r5620_hen_pant
qiime tools export \
  --input-path ./core_metrics_r5620_hen_pbd/unweighted_unifrac_pcoa_results.qza \
  --output-path unweighted_unifrac_pcoa_r5620_hen_pbd
qiime tools export \
  --input-path ./core_metrics_r5620_hen_final/unweighted_unifrac_pcoa_results.qza \
  --output-path unweighted_unifrac_pcoa_r5620_hen_final
qiime tools export \
  --input-path ./core_metrics_r5620_hen_pmortem/unweighted_unifrac_pcoa_results.qza \
  --output-path unweighted_unifrac_pcoa_r5620_hen_pmortem
```

I merged the diversity results with the metadata. Decidaded to use unweighted unifrac for more representativity of rare OTUs and to consider phylogeny.

##Isolate sequences

First I used this script to define which isolates I would consider Bd-inhibitory"

```{r inhibition}
setwd("/Users/lauraschuck/Desktop/Bioassays")

data <- read.csv("testeR.csv", header = TRUE)
data$Plate <- as.factor(data$Plate)
data$Day <- as.factor(data$Day)


library(dplyr)

# Calculate the mean absorbance for each triplicate of a given Sample, Plate, and Day
mean_data <- data %>%
  group_by(Plate, Day, Sample) %>%
  summarize(across(starts_with("Absorbance"), mean, na.rm = TRUE)) %>%
  ungroup()

# Write the result to a new CSV file
write.csv(mean_data, "mean_absorbance_data.csv", row.names = FALSE)


# Define the output directory and file path
output_dir <- "/Users/lauraschuck/Desktop/Bioassays/mnt/data"  # Modify this path as needed
output_file <- file.path(output_dir, "mean_absorbance_data.csv")





# Load necessary library
library(dplyr)

# Read the CSV file
data <- mean_data

# Calculate the mean absorbance of the negative control (Heat killed Bd) for each plate
HK_mean <- data %>%
  filter(Sample == "HK-Bd0001") %>%
  group_by(Plate) %>%
  summarize(mean_absorbance = mean(Absorbance))

# Correct the absorbance values by subtracting the mean HK absorbance for each plate
data_corrected <- data %>%
  left_join(HK_mean, by = "Plate") %>%
  mutate(Corrected_Absorbance = Absorbance - mean_absorbance) %>%
  select(-mean_absorbance)

# Separate data into day "zero" and "final"
day_zero <- data_corrected %>%
  filter(Day == "zero") %>%
  select(Plate, Sample, Corrected_Absorbance) %>%
  rename(Absorbance_zero = Corrected_Absorbance)

day_final <- data_corrected %>%
  filter(Day == "final") %>%
  select(Plate, Sample, Corrected_Absorbance) %>%
  rename(Absorbance_final = Corrected_Absorbance)

# Merge the data to align day "zero" and "final" samples
merged_data <- merge(day_final, day_zero, by = c("Plate", "Sample"))

# Calculate the corrected absorbance for the final day by subtracting the zero day absorbance
corrected_data <- merged_data %>%
  mutate(Corrected_Absorbance = Absorbance_final - Absorbance_zero)

# Calculate the corrected Positive0001 value for each plate
positive_values <- corrected_data %>%
  filter(Sample == "Positive0001") %>%
  select(Plate, Corrected_Absorbance) %>%
  rename(Positive_Corrected_Absorbance = Corrected_Absorbance)

# Merge the positive values with the corrected data
corrected_data <- corrected_data %>%
  left_join(positive_values, by = "Plate")

# Calculate the Proportion and Inhibition
corrected_data <- corrected_data %>%
  mutate(
    Proportion = Corrected_Absorbance / Positive_Corrected_Absorbance,
    Inhibition = 1 - Proportion
  )

# Create the result column
corrected_data <- corrected_data %>%
  mutate(
    result = ifelse(Inhibition > 0.50, "Inhibitor", "Non-inhibitor")
  )

# Exclude Positive0001 and select relevant columns, then order by Sample
final_data <- corrected_data %>%
  filter(Sample != "Positive0001") %>%
  select(Plate, Sample, Inhibition, result) %>%
  arrange(Sample)

# Save the final table
write.csv(final_data, "inhibition_results.csv", row.names = FALSE)

# Display the final data
print(final_data)




#Merge with metadata

# Load necessary libraries
library(dplyr)

# Load the datasets
isolates_metadata <- read.csv("/Users/lauraschuck/Desktop/Isolates/isolates_metadata.csv")
inhibition_results <- read.csv("/Users/lauraschuck/Desktop/Bioassays/inhibition_results.csv")

# Merge the datasets by "Sample" and "SampleID" columns
merged_data <- merge(isolates_metadata, inhibition_results, by.x = "SampleID", by.y = "Sample")

# Save the merged data to a new CSV file
write.csv(merged_data, "/Users/lauraschuck/Desktop/Isolates/merged_data.csv", row.names = FALSE)
```


I've used the IsolateR package to filter the isolate sequences and create the inhibitory-only and the full libraries:


```{r isolate_filtering}
library(isolateR)
folder_list <- c("/path/to/folder_containing_ab1_files1",
                 "/path/to/folder_containing_ab1_files2",
                 "/path/to/folder_containing_ab1_files3")

isoALL.S4 <- isoALL(input=folder_list, merge=TRUE)
```

This provided me with Fasta files for each library.
Here I describe the matching process:

##Isolate matching
#VSearch modification
We used VSearch to match our amplicon and isolate libraries.

VSEARCH is a sequence search tool used in bioinformatics to compare DNA sequences quickly and efficiently. By default, vsearch limits the number of returned matches for each query (--maxaccepts, default = 1) and stops searching once a set number of non-matches are encountered (-maxrejects, default = 32). These defaults boost speed but may miss valid hits, especially in exhaustive search protocols. 

Parameter Changes
We changed the following:
•	—maxaccepts 0
Setting this to zero removes the limit on the number of acceptable hits per query. This ensures that all database sequences matching the query at or above the identity threshold (e.g. 100% match) are reported. Use this for comprehensive matching.
•	-maxrejects 0
Setting this to zero disables the early cutoff of rejected sequences. VSEARCH will continue searching the full database for each query, regardless of how many candidates are rejected. This prevents missing matches after a string of non-matches.

Reason for Changes
These settings are recommended for exhaustive, conservative analysis—such as matching short 16S V4 amplicon reads to longer bacterial reference sequences with strict identity requirements.
•	All true matches are reported.
•	No matches are missed due to default shortcut limits.
•	More computational resources may be required due to full database searches for every query.

Example code (changed within the _cluster_features.py file in q2-vsearch folder):

def cluster_features_de_novo(sequences: DNAFASTAFormat, table: biom.Table,
                             perc_identity: float, threads: int = 1
                             ) -> (biom.Table, DNAFASTAFormat):
    clustered_sequences = DNAFASTAFormat()
    with tempfile.NamedTemporaryFile() as fasta_with_sizes:
        with tempfile.NamedTemporaryFile() as out_uc:
            _fasta_with_sizes(str(sequences), fasta_with_sizes.name, table)
            cmd = ['vsearch',
                   '--cluster_size', fasta_with_sizes.name,
                   '--id', str(perc_identity),
                   '--centroids', str(clustered_sequences),
                   '--uc', out_uc.name,
                   '--qmask', 'none',  # ensures no lowercase DNA chars
                   '--xsize',
                   '--threads', str(threads),
                   '--minseqlength', '1',
                   '--maxrejects', '0', #changed
                   '--maxaccepts', '0', #changed
                   '--fasta_width', '0']
            run_command(cmd)
            out_uc.seek(0)

            conn = _uc_to_sqlite(out_uc)
            collapse_f = _collapse_f_from_sqlite(conn)

    table = table.collapse(collapse_f, norm=False, min_group_size=1,
                           axis='observation',
                           include_collapsed_metadata=False)

    return table, clustered_sequences

#Running VSearch
When done changing, I ran this code using my strict_inhibitory and full libraries:

``` {bash vsearch}
module load anaconda
conda activate qiime2-amplicon-2023.9

cd /storage/work/lxk5406/matching

#ANTI-BD DATABASE MATCHING
#table with just rare ASVs filtered
#filter sequences to just retained ASVs
qiime feature-table filter-seqs \
--i-table table_filt_r5620.qza \
--i-data rep-seqs.qza \
--p-no-exclude-ids \
--o-filtered-data OTUtable-filtered_Repset.qza



#match to STRICT INHIBITORY database at 100% similarity 
qiime vsearch cluster-features-closed-reference \
--i-sequences OTUtable-filtered_Repset.qza \
--i-table table_filt_r5620.qza \
--i-reference-sequences inhibitor_only_lks.qza \
--p-perc-identity 1 \
--p-strand both \
--output-dir Antifungal_Matches_100

qiime feature-table presence-absence \
--i-table Antifungal_Matches_100/clustered_table.qza \
--o-presence-absence-table PresAbs_clustered_table_lks.qza

#match to FULL database at 100% similarity
qiime vsearch cluster-features-closed-reference \
--i-sequences OTUtable-filtered_Repset.qza \
--i-table table_filt_r5620.qza \
--i-reference-sequences full_db_lks.qza \
--p-perc-identity 1 \
--p-strand both \
--output-dir Cultured_Matches_100

qiime tools export \
  --input-path Antifungal_Matches_100/clustered_table.qza \
  --output-path clustered_table_exported
```

#Calculating proportion of Bd-inhibitory reads:

```{R matching_proportions}
setwd("/Users/lauraschuck/Desktop/submissions/antifungal_predictions/")


if (!require("readr")) {
  install.packages("readr", repos="http://cran.rstudio.com/") 
  library("readr")
}

if (!require("magrittr")) {
  install.packages("magrittr", repos="http://cran.rstudio.com/") 
  library("magrittr")
}


if (!require("dplyr")) {
  install.packages("dplyr", repos="http://cran.rstudio.com/") 
  library("dplyr")
}

if (!require("purrr")) {
  install.packages("purrr", repos="http://cran.rstudio.com/") 
  library("purrr")
}

if (!require("stringr")) {
  install.packages("stringr", repos="http://cran.rstudio.com/") 
  library("stringr")
}

if (!require("devtools")) {
  install.packages("devtools", repos="http://cran.rstudio.com/") 
  library("devtools")
}

if (!require("qiime2R")) {
  install_github("jbisanz/qiime2R") 
  library("qiime2R")
}

library(tidyr)

Antifungal_table = qiime2R::read_qza("Antifungal_Matches_100/clustered_table.qza")

#import the clustered table from above (contains the number of reads matching the inhibitory database for each sample before rarefaction)
#include full pathname
Antifungal_table = qiime2R::read_qza("Antifungal_Matches_100/clustered_table.qza")

Antifungal_table = as.data.frame(Antifungal_table$data)

TotalAntiFungal = Antifungal_table %>%
  select_if(is.numeric) %>%
  map_dbl(sum)

TotalAntiFungal = as.data.frame(TotalAntiFungal)

TotalAntiFungal = cbind(id = rownames(TotalAntiFungal), TotalAntiFungal)

rownames(TotalAntiFungal) <- NULL

#import the clustered table from above (contains the number of reads matching the full database for each sample before rarefaction)
Cultured_table = qiime2R::read_qza("Cultured_Matches_100/clustered_table.qza")

Cultured_table = as.data.frame(Cultured_table$data)

TotalCultured = Cultured_table %>%
  select_if(is.numeric) %>%
  map_dbl(sum)

TotalCultured = as.data.frame(TotalCultured)

TotalCultured = cbind(id = rownames(TotalCultured), TotalCultured)

rownames(TotalCultured) <- NULL

#join the results into one dataframe
Antifungal_Cultured_Reads <- left_join(TotalCultured, TotalAntiFungal, by = "id")


Antifungal_Cultured_Reads3 <- Antifungal_Cultured_Reads %>%
  mutate(RatioAF_Full_PR = TotalAntiFungal/TotalCultured) %>% #calculate the ratio of inhibitory/all matching reads
  mutate(Representation = TotalCultured/5620) %>% #calculate proportion of total reads matching full DB
  rename(TotalAntiFungal_PR = TotalAntiFungal) %>% #rename the columns so that they are labeled as PR (pre-rarefaction)
  rename(TotalCultured_PR = TotalCultured) %>%
  replace_na(list(RatioAF_Full_PR = 0)) #replace NAs with 0s

Antifungal_Cultured_Reads3$id <- gsub("-", "\\.", Antifungal_Cultured_Reads3$id) #this just fixes the IDs so they match my metadata
  
write.csv(Antifungal_Cultured_Reads3, "Antifungal_Cultured_Reads3.csv", row.names = F) #write this dataframe so you can merge it with your dataframe

Metadata = read.csv("metadata_final.csv")
#Metadata$id <- gsub("\\.", "-", Metadata$id)

Antifungal_tablePA = qiime2R::read_qza("Antifungal_Matches_100/PresAbs_clustered_table.qza")

Antifungal_tablePA = as.data.frame(Antifungal_tablePA$data)

AntiFungal_Richness = Antifungal_tablePA %>%
  select_if(is.numeric) %>%
  map_dbl(sum)

AntiFungal_Richness = as.data.frame(AntiFungal_Richness)

AntiFungal_Richness$id <- AntiFungal_Richness$SampleID

AntiFungal_Richness = cbind(id = rownames(AntiFungal_Richness), AntiFungal_Richness)



rownames(AntiFungal_Richness) <- NULL

Metadata_Antifungal_Richness = Metadata %>%
  left_join(AntiFungal_Richness, by = "id")

Metadata_AB = Metadata_Antifungal_Richness %>%
  left_join(Antifungal_Cultured_Reads3, by = "id")

Metadata_AB$metric <- Metadata_AB$TotalAntiFungal_PR * Metadata_AB$Representation

write.csv(Metadata_AB, "Metadata_AB.csv", row.names = F)
```
I used the ratio between antifungal matching reads and total cultured reads times the representation of cultured isolates in the sample to have a weighted measure of Bd-inhibitory function, limited by my culturing. 

I'm confident on my culturing efforts since some samples have over 80% reads represented in my cultured database.

This is my data processing. Now the analysis:

###Analysis
##Survival
To perform the survival analysis and run the proportional hazards model, I need to have the table organized by frog ID instead of sample. So I did this:

```{r byfrogdata}
library(tidyverse)

# Load metadata_ab
ab <- read.csv("/Users/lauraschuck/Desktop/submissions/antifungal_predictions/Metadata_AB.csv")   

# Columns to reshape (UPDATED)
cols <- c(
  "Load",
  "AntiFungal_Richness",
  "TotalCultured_PR",
  "TotalAntiFungal_PR",
  "RatioAF_Full_PR",
  "Representation",
  "metric"
)

# Confirm colnames
names(ab)

# Pivot to wide format
ab_wide <- ab %>%
  select(frog_id, time, all_of(cols)) %>%
  pivot_wider(
    id_cols = frog_id,
    names_from = time,
    values_from = all_of(cols),
    names_sep = "_"
  )

# Primeiro, garantir que todas as colunas de load sejam numéricas
ab_wide <- ab_wide %>%
  mutate(across(starts_with("Load_"), ~ as.numeric(.)))

# Função para pegar o último valor não-NA
last_non_na <- function(x) {
  rev(x)[which.max(!is.na(rev(x)))]
}

# Identificar automaticamente todas as colunas de Load_* na ordem correta
load_cols <- c(
  "Load_field",
  "Load_post_ant",
  "Load_post_bd",
  "Load_final",
  "Load_post_mortem"
)

# Selecionar apenas as colunas que realmente existem na sua tabela
load_cols <- load_cols[load_cols %in% names(ab_wide)]

# Criar load_last
ab_wide$load_last <- apply(ab_wide[, load_cols], 1, last_non_na)

# Criar shift
ab_wide$Load_Shift <- ab_wide$load_last - ab_wide$Load_field
ab_wide$Load_Shift_log <- log10(ab_wide$Load_Shift+1)

last_info <- ab %>%
  group_by(frog_id) %>%
  filter(day == max(day, na.rm = TRUE)) %>%   # pega o maior dia
  slice(1) %>%                                # garante uma linha
  ungroup() %>%
  select(frog_id, day_last = day, status_last = status, species, treatment, ant, bd)

ab_wide <- ab_wide %>%
  left_join(last_info, by = "frog_id")

# View result
ab_wide

write.csv(ab_wide, "metadata_frogid.csv", row.names = FALSE)


```
I created survival curves on JMP:

```{text JMP_survival_script}

Local Here(
	table1 = New Table("metadata_frogid",
		Add Rows(79),
		New Script("Source",
			Open(
				"$DESKTOP/submissions/metadata_frogid.csv",
				columns(
					New Column("frog_id", Numeric, "Continuous", Format("Best", 12)),
					New Column("Load_post_ant", Numeric, "Continuous", Format("Best", 12)),
					New Column("Load_post_bd", Numeric, "Continuous", Format("Best", 12)),
					New Column("Load_final", Numeric, "Continuous", Format("Best", 12)),
					New Column("Load_post_mortem", Numeric, "Continuous", Format("Best", 12)),
					New Column("Load_field", Numeric, "Continuous", Format("Best", 12)),
					... your remaining columns here ...
				),
				Import Settings(
					End Of Line(CRLF, CR, LF),
					End Of Field(Comma, CSV(1)),
					...
				)
			)
		),
		... more New Column() statements ...
	) << Run Formulas;

	New Window(
		"metadata_frogid - Survival",
		table1 << Survival(
			Y(:day_last),
			Censor(:status_last),
			Grouping(:treatment),
			Censor Code(0),
			Failure Plot(0),
			By(:condition)
		)
	) << Move Window(203, 0)
	 << Set Content Size(573, 973)
	 << Set Window Icon("Survival")
);
```

Now the Proportional Hazards Model, also on JMP:

``` {text JMP_hazard}
	Set Window Icon( "Model" );
	New Window( "metadata_frogid - Fit Proportional Hazards 5",
		table1 << Fit Model(
			Y( :day_last ),
			Effects(
				:ant, :Load_Shift_log, :Load_Shift_log * :ant,
				:RatioAF_Full_PR_field
			),
			Personality( "Proportional Hazard" ),
			Censor( :status_last ),
			Censor Code( "0" ),
			Run( Likelihood Confidence Intervals( 1 ), Likelihood Ratio Tests( 1 ) ),
			By( :species )
		)
```
		
##Infection intensity and dispersion overtime


``` {r loads_dispersion}

library(nlme)
ab <- read.csv("/Users/lauraschuck/Desktop/submissions/antifungal_predictions/Metadata_AB.csv") 
metadata <- ab
metadata$UU_disp <- metadata$UU_dispersion
# Make sure 'group' is a factor
metadata$group <- as.factor(metadata$frog_id)

model1 <- lme(
  Load_log ~ ant + RatioAF_Full_PR,
  random = ~ 1 | group,
  correlation = corCAR1(form = ~ day | group),
  data = metadata,
  na.action = na.exclude,
  method = "REML"
)



##species:

metadata_hb <- filter(metadata, species=="Haddadus binotatus")
metadata_ih <- filter(metadata, species=="Ischnocnema henselii")

model_hb <- lme(
  Load_log ~ ant + RatioAF_Full_PR,
  random = ~ 1 | group,
  correlation = corCAR1(form = ~ day | group),
  data = metadata_hb,
  na.action = na.exclude,
  method = "REML"
)


model_ih <- lme(
  Load_log ~ ant + RatioAF_Full_PR,
  random = ~ 1 | group,
  correlation = corCAR1(form = ~ day | group),
  data = metadata_ih,
  na.action = na.exclude,
  method = "REML"
)

#check duplicates
dups <- metadata[duplicated(metadata[c("frog_id", "day")]), ]
print(dups)


##geral
model_disp <- lme(
  UU_disp ~ species + ant + Load_log + ant*Load_log,
  random = ~ 1 | group,
  correlation = corCAR1(form = ~ day | group),
    data = metadata,
  na.action = na.exclude,
  method = "REML"
)

model_disp_hb <- lme(
  UU_disp ~ ant + Load_log + ant*Load_log,
  random = ~ 1 | group,
  correlation = corCAR1(form = ~ day | group),
    data = metadata_hb,
  na.action = na.exclude,
  method = "REML"
)

model_disp_ih <- lme(
  UU_disp ~ ant + Load_log + ant*Load_log,
  random = ~ 1 | group,
  correlation = corCAR1(form = ~ day | group),
    data = metadata_ih,
  na.action = na.exclude,
  method = "REML"
)

summary(model_hb)
summary(model_ih)
summary(model_disp_hb)
summary(model_disp_ihsum)

  
```
##Lefse

```{r lefse}
## =============================================================
## LOAD PACKAGES
## =============================================================
library(phyloseq)
library(dplyr)
library(readr)
library(qiime2R)
library(ggplot2)
library(Biostrings)
library(forcats)

## =============================================================
## IMPORT PHYLOSEQ OBJECT + METADATA
## =============================================================
SVs <- read_qza("table_filt_r5620.qza")
taxonomy_qza <- read_qza("dada2_taxonomy.qza")
tree <- read_qza("tree_rooted.qza")
repseqs <- read_qza("rep-seqs.qza")        # <- NOW INCLUDED

metadata <- read.csv("Metadata_AB.csv")
write.table(metadata, "metadata_final.tsv", sep = "\t",
            row.names = FALSE, quote = FALSE)

physeq <- qza_to_phyloseq(
  features = "table_filt_r5620.qza",
  tree = "tree_rooted.qza",
  taxonomy = "dada2_taxonomy.qza",
  metadata = "metadata_final.tsv"
)

## =============================================================
## RUN LEFSE
## =============================================================
lefse <- run_lefse(
  physeq,
  group = "species",
  taxa_rank = "none",
  kw_cutoff = 0.01,
  wilcoxon_cutoff = 0.01,
  lda_cutoff = 3
)

## =============================================================
## EXTRACT LEFSE MARKER TABLE CORRECTLY
## =============================================================
mt <- lefse@marker_table@.Data
mm_species <- as.data.frame(mt, stringsAsFactors = FALSE)
colnames(mm_species) <- lefse@marker_table@names
mm_species$Feature.ID <- mm_species$feature

## =============================================================
## IMPORT TAXONOMY AND MERGE
## =============================================================
tax <- as.data.frame(taxonomy_qza$data)
colnames(tax)[1] <- "Feature.ID"

lefse_tax <- mm_species %>%
  left_join(tax, by = "Feature.ID") %>%
  mutate(
    last_tax = sapply(
      strsplit(Taxon, ";"),
      function(x) trimws(tail(x, 1))
    )
  )

## =============================================================
## LOAD ASV SEQUENCES
## =============================================================
# ASV sequences from rep-seqs.qza
asv_seqs <- DNAStringSet(repseqs$data$Sequence)
names(asv_seqs) <- repseqs$data$Feature.ID

# Subset only ASVs that appear in LEfSe results
asv_lefse <- asv_seqs[names(asv_seqs) %in% lefse_tax$Feature.ID]

## =============================================================
## LOAD INHIBITOR SEQUENCES
## =============================================================
inhib_qza <- read_qza("inhibitor_only_lks.qza")$data
inhib_seqs <- DNAStringSet(inhib_qza$Sequence)
names(inhib_seqs) <- rownames(inhib_qza)

## =============================================================
## FUNCTION TO COMPUTE % IDENTITY
## =============================================================
seq_identity <- function(seq1, seq2) {
  aln <- pairwiseAlignment(seq1, seq2, type = "local")   # LOCAL alignment
  pid(aln) / 100
}


## =============================================================
## MATCH LEFSE ASVS TO INHIBITOR ASVS AT ≥97% IDENTITY
## =============================================================
identity_results <- sapply(names(asv_lefse), function(asv_id) {
  seq1 <- asv_lefse[[asv_id]]
  max(sapply(inhib_seqs, function(seq2) seq_identity(seq1, seq2)))
})

# Add match to LEfSe table
lefse_tax$inhib_match97 <- lefse_tax$Feature.ID %in%
  names(identity_results[identity_results >= 0.95])

## =============================================================
## BEAUTIFUL LEFSE PLOT WITH STARS FOR INHIBITOR MATCHES
## =============================================================
lefse_tax$label_clean <- fct_reorder(lefse_tax$last_tax, lefse_tax$ef_lda)

ggplot(lefse_tax,
       aes(x = label_clean, y = ef_lda, fill = enrich_group)) +
  
  geom_col(width = 0.7, color = "black", linewidth = 0.2) +
  
  # STAR FOR INHIBITOR MATCH
  geom_point(
    data = subset(lefse_tax, inhib_match97),
    aes(x = label_clean, y = ef_lda),
    shape = 8, size = 4, color = "black"
  ) +
  
  coord_flip() +
  
  scale_fill_manual(
    values = c("Haddadus binotatus" = "#F8766D",
               "Ischnocnema henselii" = "#00BFC4"),
    name = "Enriched in:"
  ) +
  
  labs(
    x = "",
    y = "LDA Effect Size",
    title = "LEfSe-Enriched ASVs (Stars = ≥97% Similar to Inhibitor Isolates)"
  ) +
  
  theme_minimal(base_size = 14) +
  theme(
    plot.title = element_text(face = "bold", size = 18, hjust = 0.5),
    axis.text.y = element_text(size = 11),
    axis.text.x = element_text(size = 12),
    axis.title.x = element_text(size = 14),
    legend.position = "right",
    panel.grid.major.y = element_blank(),
    panel.grid.minor = element_blank()
  )
```

## review

``` {r review}

#setwd("C:/Users/laura/iCloudDrive/Desktop/submissions/Animal_microbiome")
setwd("/Users/lauraschuck/Desktop/submissions/Animal_microbiome")
# ============================================================
# FINAL SURVIVAL ANALYSIS + VISUALIZATION
# ============================================================

library(dplyr)
library(readr)
library(survival)
library(survminer)

# -----------------------------
# 1) Load and prepare data
# -----------------------------

metadata <- read_tsv("metadata_final.tsv", show_col_types = FALSE)

metadata_clean <- metadata %>%
  mutate(
    frog_id = as.factor(frog_id),
    species = as.factor(species),
    ant = as.factor(ant),
    bd = as.factor(bd),
    time = as.factor(time),
    day = as.numeric(day),
    status = as.numeric(status),
    Load_log = as.numeric(Load_log),
    RatioAF_Full_PR = as.numeric(RatioAF_Full_PR)
  )

# -----------------------------
# 2) One row per frog
# -----------------------------

surv_simple <- metadata_clean %>%
  arrange(frog_id, day) %>%
  group_by(frog_id) %>%
  summarise(
    day_last = max(day, na.rm = TRUE),
    status_last = max(status, na.rm = TRUE),
    species = first(species),
    ant = first(ant),
    bd = first(bd),
    RatioAF_Full_PR_field = RatioAF_Full_PR[time == "field"][1],
    .groups = "drop"
  ) %>%
  filter(!is.na(RatioAF_Full_PR_field))

# Relevel for interpretation
surv_simple <- surv_simple %>%
  mutate(
    species = relevel(species, ref = "Haddadus binotatus"),
    ant = relevel(ant, ref = "control_a"),
    bd = relevel(bd, ref = "control_bd")
  )

# -----------------------------
# 3) GLOBAL MODEL (main result)
# -----------------------------

cox_global <- coxph(
  Surv(day_last, status_last) ~
    species +
    ant * bd +
    RatioAF_Full_PR_field,
  data = surv_simple
)

summary(cox_global)

# -----------------------------
# 4) Kaplan–Meier visualization
# -----------------------------

surv_simple$treat <- interaction(
  surv_simple$species,
  surv_simple$ant,
  surv_simple$bd
)

fit <- survfit(Surv(day_last, status_last) ~ treat, data = surv_simple)

ggsurvplot(
  fit,
  data = surv_simple,
  risk.table = TRUE,
  pval = TRUE,
  ggtheme = theme_minimal()
)

# -----------------------------
# 5) TIME-VARYING MODEL (mechanism)
# -----------------------------

surv_long <- metadata_clean %>%
  arrange(frog_id, day) %>%
  group_by(frog_id) %>%
  mutate(
    start = day,
    stop = lead(day),
    event = lead(status)
  ) %>%
  filter(!is.na(stop), stop > start) %>%
  ungroup()

cox_tv <- coxph(
  Surv(start, stop, event) ~
    Load_log +
    ant +
    species +
    cluster(frog_id),
  data = surv_long
)

summary(cox_tv)

# H. binotatus: Bd alone vs Bd + antibiotics
survdiff(Surv(day_last, status_last) ~ group,
         data = surv_simple %>% filter(species == "Haddadus binotatus",
                                       group %in% c("control_a_bd", "ant_bd")))

# I. henselii: Bd alone vs Bd + antibiotics
survdiff(Surv(day_last, status_last) ~ group,
         data = surv_simple %>% filter(species == "Ischnocnema henselii",
                                       group %in% c("control_a_bd", "ant_bd")))

```




##ancom

``` {r ancom}
# ============================================================
# ANCOM-BC2 at GENUS level — treatment comparison
# ============================================================

library(phyloseq)
library(ANCOMBC)
library(dplyr)
library(tibble)

ps <- physeq  # your object

# ------------------------------------------------------------
# 1) Agglomerate to GENUS level
# ------------------------------------------------------------

ps_genus <- tax_glom(ps, taxrank = "Genus")

# Clean taxa names (optional but helps)
tax_table(ps_genus)[, "Genus"] <- make.names(tax_table(ps_genus)[, "Genus"])

# ------------------------------------------------------------
# 2) Use experimental samples (NOT field)
# ------------------------------------------------------------

ps_exp <- subset_samples(ps_genus, time != "field")
ps_exp <- prune_taxa(taxa_sums(ps_exp) > 0, ps_exp)

# Ensure treatment is a factor
sample_data(ps_exp)$treatment <- as.factor(sample_data(ps_exp)$treatment)

# Check levels (IMPORTANT)
levels(sample_data(ps_exp)$treatment)

# Set reference level (control)
sample_data(ps_exp)$treatment <- relevel(
  sample_data(ps_exp)$treatment,
  ref = "control"
)

# ------------------------------------------------------------
# 3) Run ANCOM-BC2
# ------------------------------------------------------------

ancom_treat <- ancombc2(
  data = ps_exp,
  taxa_are_rows = TRUE,
  assay_name = "counts",
  tax_level = "Genus",
  fix_formula = "treatment",
  group = "treatment",
  p_adj_method = "holm",
  prv_cut = 0.10,
  lib_cut = 1000,
  struc_zero = TRUE,
  neg_lb = TRUE,
  alpha = 0.05,
  verbose = TRUE
)

# ------------------------------------------------------------
# 4) Extract results
# ------------------------------------------------------------

res <- ancom_treat$res

# Find columns automatically
lfc_cols  <- grep("^lfc_treatment", colnames(res), value = TRUE)
p_cols    <- grep("^p_treatment", colnames(res), value = TRUE)
q_cols    <- grep("^q_treatment", colnames(res), value = TRUE)
diff_cols <- grep("^diff_treatment", colnames(res), value = TRUE)

ancom_results <- res %>%
  as.data.frame() %>%
  rownames_to_column("Genus")

# View top results
print(ancom_results, n = 20)

# Save
write.csv(ancom_results,
          "ANCOMBC2_treatment_genus.csv",
          row.names = FALSE)
```