This repository has been archived by the owner on Jul 1, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
7 changed files
with
311 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -29,4 +29,6 @@ todo.txt | |
.rspec_status | ||
*.lock | ||
|
||
.idea | ||
.idea | ||
|
||
exe/key_cols2 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,206 @@ | ||
#!/usr/bin/env ruby | ||
|
||
Signal.trap("PIPE", "EXIT") | ||
|
||
require "tree_clusters" | ||
require "trollop" | ||
require "parse_fasta" | ||
require "fileutils" | ||
|
||
TreeClusters.extend TreeClusters | ||
|
||
GREETING = "The '#{__FILE__}' program" | ||
UNDERLINE = "=" * GREETING.length | ||
|
||
opts = Trollop.options do | ||
version TreeClusters::VERSION | ||
|
||
# banner <<-EOS | ||
|
||
|
||
# Checking IDs | ||
# ------------ | ||
|
||
# IDs for the sequences must match between the three input files. | ||
|
||
# The tree file is allowed to have quoted taxa names, but the | ||
# mapping file and alignment file are not. | ||
|
||
# If your alignment file has spaces in the name, the ID part of the | ||
# header (i.e., the part up until the space) must match with the | ||
# sequence IDs in the tree and the mapping file. | ||
|
||
# Example: This would be okay. | ||
|
||
# tree file: | ||
# ('genome_A', 'genome_B'); | ||
|
||
# aln file: | ||
# >genome_A apple pie | ||
# AAAAA | ||
# >genome_B brown sugar | ||
# AATTA | ||
|
||
# Options: | ||
# EOS | ||
|
||
banner <<-EOS | ||
#{GREETING} | ||
#{UNDERLINE} | ||
Hi. My name is #{__FILE__}. If you give me a Newick tree file and | ||
an alignment file (fasta format), I will tell you key columns for | ||
all clades/clusters that have them. | ||
Overview | ||
-------- | ||
A clade has key columns if you can use the residue/nucleotide at | ||
those columns to tell sequences in the clade from sequences outside | ||
of the clade. | ||
Here's an example.... | ||
After you run me (#{__FILE__} is my name), you'll get an output file | ||
with the extension, '*.tree_clusters.key_cols.txt'. It may look | ||
something like this: | ||
cluster_A 4 1-A 2-A 3-A 5-G | ||
cluster_B 4 1-C 2-C 3-C 5-A | ||
This file has the clade name, the number of key columns for that | ||
clade, and then the rest of the columns tell you the position | ||
(1-based) and the nucleotide or residue in that column in all | ||
sequences of that clade. | ||
In this case we have only two clades. The key columns for both are | ||
1, 2, 3, and 5. So you can use columns 1, 2, 3, and 5 to classify a | ||
sequence as belonging to one of these clades. If it has A, A, A, | ||
and G in those positions, it'll be in cluster_A, and if it has C, C, | ||
C, and A in those positions, it'll be in cluster_B. If it has any | ||
other combination in those 4 columns of the alignment, it won't be | ||
in either clade. | ||
This is just a silly example and most of the time you'll get | ||
different key columns for different clades. Note that every clade | ||
may not have key columns listed depending on your data and the | ||
options you select. | ||
Notes & Gotchas | ||
-------------- | ||
- I ignore columns with gap chars (currently just '-') regardless of | ||
column entropy. | ||
Option info | ||
----------- | ||
--entropy-cutoff: A cutoff of 0 means that you allow no variation at | ||
any column. | ||
--clade-size-cutoff: Use this option to ignore tiny clades. | ||
Options: | ||
EOS | ||
|
||
opt(:tree, | ||
"Newick tree file", | ||
type: :string) | ||
opt(:aln, | ||
"Alignment file", | ||
type: :string) | ||
|
||
opt(:entropy_cutoff, | ||
"Cutoff to consider a column low entropy", | ||
default: 0.0) | ||
opt(:clade_size_cutoff, | ||
"Consider only clades with at least this many leaves", | ||
default: 1) | ||
|
||
opt(:outdir, | ||
"Output directory", | ||
default: ".") | ||
opt(:base, | ||
"Basename for output", | ||
default: "snazzy_clades") | ||
end | ||
|
||
abort_if opts[:tree].nil?, | ||
"--tree is a required arg. Try running: #{__FILE__} --help" | ||
abort_if opts[:aln].nil?, | ||
"--aln is a required arg. Try running: #{__FILE__} --help" | ||
|
||
abort_unless_file_exists opts[:tree] | ||
abort_unless_file_exists opts[:aln] | ||
|
||
# TreeClusters.check_ids opts[:tree], opts[:mapping], opts[:aln] | ||
|
||
abort_unless opts[:entropy_cutoff] >= 0, | ||
"--entropy-cutoff must be >= 0" | ||
abort_unless opts[:clade_size_cutoff] >= 1, | ||
"--clade-size-cutoff must be >= 1" | ||
|
||
FileUtils.mkdir_p opts[:outdir] | ||
|
||
tree = NewickTree.fromFile opts[:tree] | ||
leaf2attrs = TreeClusters.read_alignment opts[:aln] | ||
|
||
members_fname = | ||
File.join opts[:outdir], | ||
"#{opts[:base]}.tree_clusters.clade_members.txt" | ||
key_cols_fname = | ||
File.join opts[:outdir], | ||
"#{opts[:base]}.tree_clusters.key_cols.txt" | ||
annotated_tree_fname = | ||
File.join opts[:outdir], | ||
"#{opts[:base]}.tree_clusters.annotated_tree.txt" | ||
|
||
clade_members_f = | ||
File.open(members_fname, "w") | ||
key_cols_f = | ||
File.open(key_cols_fname, "w") | ||
annotated_tree_f = | ||
File.open(annotated_tree_fname, "w") | ||
|
||
key_col_sets = {} | ||
|
||
begin | ||
TreeClusters.all_clades(tree).sort_by {|cl| cl.all_leaves.count}.reverse.each_with_index do |clade, idx| | ||
clade_id = "clade_#{idx + 1}___#{clade.name.tr("'", "_")}" | ||
|
||
clade_members_f.puts [clade_id, | ||
clade.all_leaves.count, | ||
clade.all_leaves].join "\t" | ||
|
||
key_cols_all_leaves = | ||
TreeClusters.low_ent_cols_with_bases clade.all_leaves, | ||
leaf2attrs, | ||
opts[:entropy_cutoff] | ||
|
||
unless key_col_sets.has_key? key_cols_all_leaves | ||
key_col_sets[key_cols_all_leaves] = Set.new [clade_id] | ||
end | ||
key_col_sets[key_cols_all_leaves] << clade_id | ||
|
||
# This will change the node in the original NewickTree | ||
clade.node.name = "'#{clade_id}'" | ||
|
||
end | ||
|
||
# We only want key column sets that are unique to a single clade. | ||
key_col_sets.select { |_, clades| clades.count == 1 }.each do |kc_set, clades| | ||
clade_id = clades.first | ||
key_cols_f.puts [ | ||
clade_id, | ||
kc_set.count, | ||
kc_set.map { |pos, bases| "#{pos}-#{bases.join}" } | ||
].join "\t" | ||
end | ||
|
||
annotated_tree_f.puts tree.to_s.sub(/;+$/, ";") | ||
ensure | ||
clade_members_f.close | ||
key_cols_f.close | ||
annotated_tree_f.close | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
module TreeClusters | ||
VERSION = "0.7.0" | ||
VERSION = "0.8.0" | ||
end |
Oops, something went wrong.