PyamilySeq 0.4.0__py3-none-any.whl → 0.5.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -4,16 +4,16 @@ from collections import OrderedDict,defaultdict
4
4
  import copy
5
5
  import math
6
6
  import sys
7
- import argparse
8
- import os
9
7
  from tempfile import NamedTemporaryFile
10
8
 
11
9
 
12
10
 
13
11
  try:
14
12
  from .Constants import *
13
+ from .utils import *
15
14
  except (ModuleNotFoundError, ImportError, NameError, TypeError) as error:
16
15
  from Constants import *
16
+ from utils import *
17
17
 
18
18
 
19
19
  def custom_sort_key(k, dict1, dict2):
@@ -33,7 +33,7 @@ def select_longest_gene(sequences):
33
33
  return longest_sequences
34
34
 
35
35
 
36
- def run_mafft_on_sequences(sequences, output_file):
36
+ def run_mafft_on_sequences(options, sequences, output_file):
37
37
  """Run mafft on the given sequences and write to output file."""
38
38
  # Create a temporary input file for mafft
39
39
  with NamedTemporaryFile('w', delete=False) as temp_input_file:
@@ -44,17 +44,25 @@ def run_mafft_on_sequences(sequences, output_file):
44
44
  # Run mafft
45
45
  try:
46
46
  with open(output_file, 'w') as output_f:
47
- subprocess.run(
48
- ['mafft', '--auto', temp_input_file_path],
49
- stdout=output_f,
50
- stderr=subprocess.DEVNULL, # Suppress stderr
51
- check=True
52
- )
47
+ if options.verbose == 'True':
48
+ subprocess.run(
49
+ ['mafft', '--auto', temp_input_file_path],
50
+ stdout=output_f,
51
+ stderr=sys.stderr,
52
+ check=True
53
+ )
54
+ else:
55
+ subprocess.run(
56
+ ['mafft', '--auto', temp_input_file_path],
57
+ stdout=output_f,
58
+ stderr=subprocess.DEVNULL, # Suppress stderr
59
+ check=True
60
+ )
53
61
  finally:
54
62
  os.remove(temp_input_file_path) # Clean up the temporary file
55
63
 
56
64
 
57
- def process_gene_families(directory, output_file):
65
+ def process_gene_families(options, directory, output_file):
58
66
  """Process each gene family file to select the longest sequence per genome and concatenate aligned sequences."""
59
67
  concatenated_sequences = {}
60
68
  output_file = directory.replace('Gene_Families_Output',output_file)
@@ -72,7 +80,7 @@ def process_gene_families(directory, output_file):
72
80
 
73
81
  # Run mafft on the longest sequences
74
82
  aligned_file = f"{gene_file}_aligned.fasta"
75
- run_mafft_on_sequences({seq_id: seq for seq_id, seq in longest_sequences.values()}, aligned_file)
83
+ run_mafft_on_sequences(options, {seq_id: seq for seq_id, seq in longest_sequences.values()}, aligned_file)
76
84
 
77
85
  # Read aligned sequences and concatenate them
78
86
  aligned_sequences = read_fasta(aligned_file)
@@ -143,9 +151,9 @@ def read_fasta(fasta_file):
143
151
  for line in file:
144
152
  line = line.strip()
145
153
  if not line:
146
- continue # Skip empty lines
154
+ continue
147
155
  if line.startswith('>'):
148
- current_sequence = line[1:] # Remove '>' character
156
+ current_sequence = line[1:]
149
157
  sequences[current_sequence] = ''
150
158
  else:
151
159
  sequences[current_sequence] += line
@@ -384,9 +392,9 @@ def combined_clustering_CDHIT(options, genome_dict):
384
392
  return combined_pangenome_clusters_First_Second_clustered,not_Second_only_cluster_ids, combined_pangenome_clusters_Second, unique_genomes
385
393
 
386
394
  def combined_clustering_Edge_List(options, genome_dict):
387
- if options.format == 'TSV':
395
+ if options.cluster_format == 'TSV':
388
396
  separator = '\t'
389
- elif options.format == 'CSV':
397
+ elif options.cluster_format == 'CSV':
390
398
  separator = ','
391
399
  unique_genomes = []
392
400
  cluster_id = 0
@@ -463,9 +471,9 @@ def combined_clustering_Edge_List(options, genome_dict):
463
471
 
464
472
 
465
473
  def cluster_EdgeList(options):
466
- if options.format == 'TSV':
474
+ if options.cluster_format == 'TSV':
467
475
  separator = '\t'
468
- elif options.format == 'CSV':
476
+ elif options.cluster_format == 'CSV':
469
477
  separator = ','
470
478
  cluster_id = 0
471
479
  last_rep = ''
@@ -548,9 +556,9 @@ def cluster_CDHIT(options):
548
556
  #@profile
549
557
  def cluster(options):
550
558
 
551
- if options.format == 'CD-HIT':
559
+ if options.cluster_format == 'CD-HIT':
552
560
  genome_dict, pangenome_clusters_First, pangenome_clusters_First_sequences, reps = cluster_CDHIT(options)
553
- elif options.format in ['TSV','CSV']:
561
+ elif options.cluster_format in ['TSV','CSV']:
554
562
  genome_dict, pangenome_clusters_First, pangenome_clusters_First_sequences, reps = cluster_EdgeList(options)
555
563
 
556
564
  ######################################
@@ -558,10 +566,10 @@ def cluster(options):
558
566
  ###
559
567
 
560
568
  if options.reclustered != None:
561
- if options.format == 'CD-HIT':
569
+ if options.cluster_format == 'CD-HIT':
562
570
  combined_pangenome_clusters_First_Second_clustered,not_Second_only_cluster_ids,combined_pangenome_clusters_Second,\
563
571
  unique_genomes = combined_clustering_CDHIT(options, genome_dict)
564
- if options.format == 'TSV':
572
+ if options.cluster_format == 'TSV':
565
573
  combined_pangenome_clusters_First_Second_clustered,not_Second_only_cluster_ids,combined_pangenome_clusters_Second,\
566
574
  unique_genomes = combined_clustering_Edge_List(options, genome_dict)
567
575
  pangenome_clusters_Type = combined_clustering_counting(options, pangenome_clusters_First, reps, combined_pangenome_clusters_First_Second_clustered)
@@ -570,7 +578,7 @@ def cluster(options):
570
578
 
571
579
 
572
580
 
573
- Number_Of_StORF_Extending_But_Same_Genomes = 0
581
+ Number_Of_Second_Extending_But_Same_Genomes = 0
574
582
 
575
583
  sorted_first_keys = sort_keys_by_values(pangenome_clusters_First, pangenome_clusters_First_sequences)
576
584
  pangenome_clusters_First_sorted = reorder_dict_by_keys(pangenome_clusters_First, sorted_first_keys)
@@ -594,7 +602,7 @@ def cluster(options):
594
602
  elif numbers[0] > 1 and numbers[3] >= 1: # If unique Secondss combined multiple Firsts
595
603
  calc_multi_First_extended_Second_only_core(numbers[1], groups, cores, numbers[3])
596
604
  elif numbers[4] >= 1:
597
- Number_Of_StORF_Extending_But_Same_Genomes += 1
605
+ Number_Of_Second_Extending_But_Same_Genomes += 1
598
606
  combined_pangenome_clusters_ONLY_Second_Type = defaultdict(list)
599
607
  combined_pangenome_clusters_Second_Type = defaultdict(list)
600
608
  for cluster, genomes in combined_pangenome_clusters_Second.items():
@@ -643,7 +651,7 @@ def cluster(options):
643
651
  outfile.write(f"{wrapped_sequence}\n")
644
652
 
645
653
  if options.con_core != None and options.fasta != None and options.write_families != None:
646
- process_gene_families(os.path.join(input_dir, 'Gene_Families_Output'), 'concatonated_genes_aligned.fasta')
654
+ process_gene_families(options, os.path.join(input_dir, 'Gene_Families_Output'), 'concatonated_genes_aligned.fasta')
647
655
 
648
656
 
649
657
  # groups_dir = os.path.join(input_dir, 'Gene_Families_Output')
@@ -705,7 +713,7 @@ def cluster(options):
705
713
  # for core_gene_family in core_gene_families:
706
714
  # found_sequences = {genome: False for genome in genomes}
707
715
  #
708
- # for fasta_file in fasta_files:
716
+ # for fasta_file in fasta_files:f
709
717
  # sequences = read_fasta(fasta_file)
710
718
  # for header, sequence in sequences.items():
711
719
  # genome = header.split('|')[0]
@@ -720,93 +728,3 @@ def cluster(options):
720
728
 
721
729
 
722
730
 
723
- def main():
724
-
725
- parser = argparse.ArgumentParser(description='PyamilySeq-Species ' + PyamilySeq_Version + ': PyamilySeq-Species Run Parameters.')
726
- parser._action_groups.pop()
727
-
728
- required = parser.add_argument_group('Required Arguments')
729
- required.add_argument('-c', action='store', dest='clusters', help='Clustering output file from CD-HIT, TSV or CSV Edge List',
730
- required=True)
731
- required.add_argument('-f', action='store', dest='format', choices=['CD-HIT', 'CSV', 'TSV'],
732
- help='Which format to use (CD-HIT or Comma/Tab Separated Edge-List (such as MMseqs2 tsv output))',
733
- required=True)
734
-
735
- output_args = parser.add_argument_group('Output Parameters')
736
- output_args.add_argument('-w', action="store", dest='write_families', default=None,
737
- help='Default - No output: Output sequences of identified families (provide levels at which to output "-w 99,95"'
738
- ' - Must provide FASTA file with -fasta',
739
- required=False)
740
- output_args.add_argument('-con', action="store", dest='con_core', default=None,
741
- help='Default - No output: Output aligned and concatinated sequences of identified families - used for MSA (provide levels at which to output "-w 99,95"'
742
- ' - Must provide FASTA file with -fasta',
743
- required=False)
744
- output_args.add_argument('-fasta', action='store', dest='fasta',
745
- help='FASTA file to use in conjunction with "-w" or "-con"',
746
- required=False)
747
-
748
- optional = parser.add_argument_group('Optional Arguments')
749
- optional.add_argument('-rc', action='store', dest='reclustered', help='Clustering output file from secondary round of clustering',
750
- required=False)
751
- optional.add_argument('-st', action='store', dest='sequence_tag', help='Default - "StORF": Unique identifier to be used to distinguish the second of two rounds of clustered sequences',
752
- required=False)
753
- optional.add_argument('-groups', action="store", dest='core_groups', default="99,95,15",
754
- help='Default - (\'99,95,15\'): Gene family groups to use')
755
- optional.add_argument('-gpa', action='store', dest='gene_presence_absence_out', help='Default - False: If selected, a Roary formatted gene_presence_absence.csv will be created - Required for Coinfinder and other downstream tools',
756
- required=False)
757
-
758
- misc = parser.add_argument_group('Misc')
759
- misc.add_argument('-verbose', action='store', dest='verbose', default=False, type=eval, choices=[True, False],
760
- help='Default - False: Print out runtime messages',
761
- required = False)
762
- misc.add_argument('-v', action='store_true', dest='version',
763
- help='Default - False: Print out version number and exit',
764
- required=False)
765
-
766
-
767
- options = parser.parse_args()
768
- if options.clusters == None or options.format == None:
769
- if options.version:
770
- sys.exit(PyamilySeq_Version)
771
- else:
772
- exit('PyamilySeq: error: the following arguments are required: -c, -f')
773
-
774
- if options.sequence_tag == None:
775
- options.sequence_tag = 'StORF'
776
-
777
- if options.con_core == True:
778
- if is_tool_installed('mafft'):
779
- print("mafft is installed. Proceeding with alignment.")
780
- else:
781
- print("mafft is not installed. Please install mafft to proceed.")
782
-
783
- if options.write_families != None and options.fasta == False:
784
- exit("-fasta must br provided if -w is used")
785
-
786
-
787
- options.clusters = os.path.normpath(options.clusters)
788
- options.clusters = os.path.realpath(options.clusters)
789
- if options.reclustered:
790
- options.reclustered = os.path.normpath(options.reclustered)
791
- options.reclustered = os.path.realpath(options.reclustered)
792
-
793
-
794
- options.core_groups = options.core_groups + ',0'
795
-
796
- cluster(options)
797
-
798
-
799
-
800
-
801
-
802
- print("Thank you for using PyamilySeq -- A detailed user manual can be found at https://github.com/NickJD/PyamilySeq\n"
803
- "Please report any issues to: https://github.com/NickJD/PyamilySeq/issues\n#####")
804
-
805
-
806
-
807
-
808
-
809
- if __name__ == "__main__":
810
- main()
811
- print("Done")
812
-
@@ -0,0 +1,44 @@
1
+ import argparse
2
+
3
+
4
+ try:
5
+ from .Constants import *
6
+ from .utils import *
7
+ except (ModuleNotFoundError, ImportError, NameError, TypeError) as error:
8
+ from Constants import *
9
+ from utils import *
10
+
11
+
12
+
13
+ def main():
14
+ parser = argparse.ArgumentParser(description='Seq-Combiner ' + PyamilySeq_Version + ': Seq-Combiner Run Parameters.')
15
+ ### Required Arguments
16
+ required = parser.add_argument_group('Required Arguments')
17
+ required.add_argument('-input_dir', action='store', dest='input_dir',
18
+ help='Directory location where the files are located.',
19
+ required=True)
20
+ required.add_argument("-input_type", action="store", dest="input_type", choices=['separate', 'combined'],
21
+ help="Type of input files: 'separate' for separate FASTA and GFF files,"
22
+ " 'combined' for GFF files with embedded FASTA sequences.",
23
+ required=True)
24
+ required.add_argument("-name_split", action="store", dest="name_split",
25
+ help="substring used to split the filename and extract the genome name ('_combined.gff3' or '.gff').",
26
+ required=True)
27
+ required.add_argument("-output_dir", action="store", dest="output_dir",
28
+ help="Directory for all output files.",
29
+ required=True)
30
+ required.add_argument("-output_name", action="store", dest="output_file",
31
+ help="Output file name.",
32
+ required=True)
33
+ options = parser.parse_args()
34
+
35
+ output_path = os.path.abspath(options.output_dir)
36
+ combined_out_file = os.path.join(output_path, options.output_file)
37
+
38
+ if options.input_type == 'separate':
39
+ read_separate_files(options.input_dir, options.name_split, )
40
+ else:
41
+ read_combined_files(options.input_dir, options.name_split, combined_out_file)
42
+
43
+ if __name__ == "__main__":
44
+ main()
PyamilySeq/utils.py ADDED
@@ -0,0 +1,136 @@
1
+ import subprocess
2
+ import shutil
3
+ import os
4
+ import glob
5
+ import collections
6
+
7
+
8
+ def is_tool_installed(tool_name):
9
+ """Check if a tool is installed and available in PATH."""
10
+ # Check if the tool is in the system PATH
11
+ if shutil.which(tool_name) is None:
12
+ return False
13
+
14
+ # Try running the tool to ensure it's executable
15
+ try:
16
+ subprocess.run([tool_name, '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True)
17
+ return True
18
+ except subprocess.CalledProcessError:
19
+ return True # The tool is installed and ran, even if it returns an error code
20
+ except FileNotFoundError:
21
+ return False # This shouldn't happen due to the earlier check
22
+
23
+ def reverse_complement(seq):
24
+ complement = {'A': 'T', 'T': 'A', 'G': 'C', 'C': 'G', 'N': 'N'}
25
+ return ''.join(complement[base] for base in reversed(seq))
26
+
27
+ def fix_path(path):
28
+ fixed_path = os.path.normpath(path)
29
+ fixed_path = os.path.realpath(fixed_path)
30
+ return fixed_path
31
+
32
+
33
+
34
+
35
+
36
+
37
+
38
+ def read_separate_files(input_dir, name_split, combined_out):
39
+ with open(combined_out, 'w') as combined_out_file:
40
+ for gff_file in glob.glob(os.path.join(input_dir, '*' + name_split)):
41
+ genome_name = os.path.basename(gff_file).split(name_split)[0]
42
+ corresponding_fasta_file = os.path.splitext(gff_file)[0] + '.fa'
43
+ if not os.path.exists(corresponding_fasta_file):
44
+ continue
45
+
46
+ gff_features = []
47
+ with open(gff_file, 'r') as file:
48
+ lines = file.readlines()
49
+ for line in lines:
50
+ line_data = line.split('\t')
51
+ if len(line_data) == 9:
52
+ if line_data[2] == 'CDS':
53
+ contig = line_data[0]
54
+ feature = line_data[2]
55
+ strand = line_data[6]
56
+ start, end = int(line_data[3]), int(line_data[4])
57
+ seq_id = line_data[8].split('ID=')[1].split(';')[0]
58
+ gff_features.append((contig, start, end, strand, feature, seq_id))
59
+ fasta_dict = collections.defaultdict(str)
60
+ with open(corresponding_fasta_file, 'r') as file:
61
+ lines = file.readlines()
62
+ for line in lines:
63
+ if line.startswith('>'):
64
+ current_contig = line[1:].split()[0]
65
+ fasta_dict[current_contig] = ['', '']
66
+ else:
67
+ fasta_dict[current_contig][0] += line.strip()
68
+
69
+ for contig, fasta in fasta_dict.items():
70
+ reverse_sequence = reverse_complement(fasta[0])
71
+ fasta_dict[contig][1] = reverse_sequence
72
+
73
+ if fasta_dict and gff_features:
74
+ for contig, start, end, strand, feature, seq_id in gff_features:
75
+ if contig in fasta_dict:
76
+ if strand == '+':
77
+ full_sequence = fasta_dict[contig][0]
78
+ cds_sequence = full_sequence[start - 1:end]
79
+ elif strand == '-':
80
+ corrected_start = max(len(fasta_dict[contig][0]) - int(end), 1)
81
+ corrected_stop = max(len(fasta_dict[contig][0]) - int(start - 1), 1)
82
+ full_sequence = fasta_dict[contig][1]
83
+ cds_sequence = full_sequence[corrected_start:corrected_stop]
84
+
85
+ wrapped_sequence = '\n'.join([cds_sequence[i:i + 60] for i in range(0, len(cds_sequence), 60)])
86
+ combined_out_file.write(f">{genome_name}|{seq_id}\n{wrapped_sequence}\n")
87
+
88
+
89
+ def read_combined_files(input_dir, name_split, combined_out):
90
+ with open(combined_out, 'w') as combined_out_file:
91
+ for gff_file in glob.glob(os.path.join(input_dir, '*' + name_split)):
92
+ genome_name = os.path.basename(gff_file).split(name_split)[0]
93
+ fasta_dict = collections.defaultdict(str)
94
+ gff_features = []
95
+ with open(gff_file, 'r') as file:
96
+ lines = file.readlines()
97
+ fasta_section = False
98
+ for line in lines:
99
+ if line.startswith('##FASTA'):
100
+ fasta_section = True
101
+ continue
102
+ if fasta_section:
103
+ if line.startswith('>'):
104
+ current_contig = line[1:].split()[0]
105
+ fasta_dict[current_contig] = ['','']
106
+ else:
107
+ fasta_dict[current_contig][0] +=line.strip()
108
+ else:
109
+ line_data = line.split('\t')
110
+ if len(line_data) == 9:
111
+ if line_data[2] == 'CDS':
112
+ contig = line_data[0]
113
+ feature = line_data[2]
114
+ strand = line_data[6]
115
+ start, end = int(line_data[3]), int(line_data[4])
116
+ seq_id = line_data[8].split('ID=')[1].split(';')[0]
117
+ gff_features.append((contig, start, end, strand, feature, seq_id))
118
+
119
+ for contig, fasta in fasta_dict.items():
120
+ reverse_sequence = reverse_complement(fasta[0])
121
+ fasta_dict[contig][1]=reverse_sequence
122
+
123
+ if fasta_dict and gff_features:
124
+ for contig, start, end, strand, feature, seq_id in gff_features:
125
+ if contig in fasta_dict:
126
+ if strand == '+':
127
+ full_sequence = fasta_dict[contig][0]
128
+ cds_sequence = full_sequence[start - 1:end]
129
+ elif strand == '-':
130
+ corrected_start = max(len(fasta_dict[contig][0]) - int(end), 1)
131
+ corrected_stop = max(len(fasta_dict[contig][0]) - int(start - 1), 1)
132
+ full_sequence = fasta_dict[contig][1]
133
+ cds_sequence = full_sequence[corrected_start:corrected_stop]
134
+
135
+ wrapped_sequence = '\n'.join([cds_sequence[i:i + 60] for i in range(0, len(cds_sequence), 60)])
136
+ combined_out_file.write(f">{genome_name}|{seq_id}\n{wrapped_sequence}\n")
@@ -0,0 +1,163 @@
1
+ Metadata-Version: 2.1
2
+ Name: PyamilySeq
3
+ Version: 0.5.0
4
+ Summary: PyamilySeq - A a tool to look for sequence-based gene families identified by clustering methods such as CD-HIT, DIAMOND, BLAST or MMseqs2.
5
+ Home-page: https://github.com/NickJD/PyamilySeq
6
+ Author: Nicholas Dimonaco
7
+ Author-email: nicholas@dimonaco.co.uk
8
+ Project-URL: Bug Tracker, https://github.com/NickJD/PyamilySeq/issues
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
11
+ Classifier: Operating System :: OS Independent
12
+ Requires-Python: >=3.6
13
+ Description-Content-Type: text/markdown
14
+ License-File: LICENSE
15
+
16
+ # PyamilySeq - !BETA!
17
+ **PyamilySeq** (Family Seek) is a Python tool for clustering gene sequences into families based on sequence similarity identified by tools such as CD-HIT, BLAST, DIAMOND or MMseqs2.
18
+ This work is an extension of the gene family / pangenome tool developed for the StORF-Reporter publication in NAR (https://doi.org/10.1093/nar/gkad814).
19
+
20
+ ## Features
21
+ - **End-to-End**: PyamilySeq can take a directory of GFF+FASTA files, run CD-HIT for clustering and process the results.
22
+ - **Clustering**: Supports input from CD-HIT formatted files as well as CSV and TSV edge lists (-outfmt 6 from BLAST/DIAMOND).
23
+ - **Reclustering**: Allows for the addition of new sequences post-initial clustering.
24
+ - **Output**: Generates a gene 'Roary/Panaroo' formatted presence-absence CSV formatted file for downstream analysis.
25
+ - Align representative sequences using MAFFT.
26
+ - Output concatenated aligned sequences for downstream analysis.
27
+ - Optionally output sequences of identified families.
28
+
29
+
30
+ ### Installation
31
+ PyamilySeq requires Python 3.6 or higher. Install using pip:
32
+
33
+ ```bash
34
+ pip install PyamilySeq
35
+ ```
36
+
37
+ ## Usage - Menu
38
+ ```
39
+ usage: PyamilySeq.py [-h] -run_mode {Full,Partial} -group_mode {Species,Genus}
40
+ -clust_tool {CD-HIT} -output_dir OUTPUT_DIR
41
+ [-input_type {separate,combined}] [-input_dir INPUT_DIR]
42
+ [-name_split NAME_SPLIT] [-pid PIDENT]
43
+ [-len_diff LEN_DIFF] [-cluster_file CLUSTER_FILE]
44
+ [-reclustered RECLUSTERED] [-seq_tag SEQUENCE_TAG]
45
+ [-groups CORE_GROUPS] [-w WRITE_FAMILIES] [-con CON_CORE]
46
+ [-original_fasta ORIGINAL_FASTA]
47
+ [-gpa GENE_PRESENCE_ABSENCE_OUT] [-verbose {True,False}]
48
+ [-v]
49
+
50
+ PyamilySeq v0.5.0: PyamilySeq Run Parameters.
51
+
52
+ options:
53
+ -h, --help show this help message and exit
54
+
55
+ Required Arguments:
56
+ -run_mode {Full,Partial}
57
+ Run Mode: Should PyamilySeq be run in "Full" or
58
+ "Partial" mode?
59
+ -group_mode {Species,Genus}
60
+ Group Mode: Should PyamilySeq be run in "Species" or
61
+ "Genus" mode?
62
+ -clust_tool {CD-HIT} Clustering tool to use: CD-HIT, DIAMOND, BLAST or
63
+ MMseqs2.
64
+ -output_dir OUTPUT_DIR
65
+ Directory for all output files.
66
+
67
+ Full-Mode Arguments - Required when "-run_mode Full" is used:
68
+ -input_type {separate,combined}
69
+ Type of input files: 'separate' for separate FASTA and
70
+ GFF files, 'combined' for GFF files with embedded
71
+ FASTA sequences.
72
+ -input_dir INPUT_DIR Directory containing GFF/FASTA files.
73
+ -name_split NAME_SPLIT
74
+ substring used to split the filename and extract the
75
+ genome name ('_combined.gff3' or '.gff').
76
+ -pid PIDENT Default 0.95: Pident threshold for clustering.
77
+ -len_diff LEN_DIFF Default 0.80: Minimum length difference between
78
+ clustered sequences - (-s) threshold for CD-HIT
79
+ clustering.
80
+
81
+ Partial-Mode Arguments - Required when "-run_mode Partial" is used:
82
+ -cluster_file CLUSTER_FILE
83
+ Clustering output file containing CD-HIT, TSV or CSV
84
+ Edge List
85
+
86
+ Grouping Arguments - Use to fine-tune grouping of genes after clustering:
87
+ -reclustered RECLUSTERED
88
+ Clustering output file from secondary round of
89
+ clustering
90
+ -seq_tag SEQUENCE_TAG
91
+ Default - "StORF": Unique identifier to be used to
92
+ distinguish the second of two rounds of clustered
93
+ sequences
94
+ -groups CORE_GROUPS Default - ('99,95,15'): Gene family groups to use
95
+
96
+ Output Parameters:
97
+ -w WRITE_FAMILIES Default - No output: Output sequences of identified
98
+ families (provide levels at which to output "-w 99,95"
99
+ - Must provide FASTA file with -fasta
100
+ -con CON_CORE Default - No output: Output aligned and concatinated
101
+ sequences of identified families - used for MSA
102
+ (provide levels at which to output "-w 99,95" - Must
103
+ provide FASTA file with -fasta
104
+ -original_fasta ORIGINAL_FASTA
105
+ FASTA file to use in conjunction with "-w" or "-con"
106
+ when running in Partial Mode.
107
+ -gpa GENE_PRESENCE_ABSENCE_OUT
108
+ Default - False: If selected, a Roary formatted
109
+ gene_presence_absence.csv will be created - Required
110
+ for Coinfinder and other downstream tools
111
+
112
+ Misc:
113
+ -verbose {True,False}
114
+ Default - False: Print out runtime messages
115
+ -v Default - False: Print out version number and exit
116
+
117
+ ```
118
+
119
+ ### Examples: Below are two examples of running PyamilySeq in its two main modes.
120
+ #### 'Full Mode': Will conduct clustering of sequences as part of PyamilySeq run
121
+ ```bash
122
+ PyamilySeq -id .../genomes -it combined -ns _combined.gff3 -pid 0.90 -ld 0.60 -co testing_cd-hit -ct CD-HIT -od .../testing
123
+ ```
124
+ #### 'Partial Mode': Will take the output of a sequence clustering
125
+ ```bash
126
+ PyamilySeq -run_mode Partial -group_mode Species -output_dir .../test_data/testing -cluster_file .../test_data/CD-HIT/combined_Ensmbl_pep_CD_90_60.clstr -clust_tool CD-HIT -original_fasta .../test_data/combined_Ensmbl_cds.fasta -gpa True -con True -w 99 -verbose True
127
+ ```
128
+
129
+ ```Calculating Groups
130
+ Calculating Groups
131
+ Gene Groups:
132
+ first_core_99: 3103
133
+ first_core_95: 0
134
+ first_core_15: 3217
135
+ first_core_0: 4808
136
+ Total Number of Gene Groups (Including Singletons): 11128
137
+ ```
138
+
139
+ ## Seq-Combiner: This tool is provided to enable the pre-processing of multiple GFF/FASTA files together ready to be clustered by the user
140
+ ### Example:
141
+ ```bash
142
+ Seq-Combiner -input_dir .../test_data/genomes -name_split _combined.gff3 -output_dir.../test_data -output_name combine_fasta_seqs.fa -input_type combined
143
+ ```
144
+ ## Seq-Combiner Menu:
145
+ ```bash
146
+ usage: Seq_Combiner.py [-h] -input_dir INPUT_DIR -input_type {separate,combined} -name_split NAME_SPLIT -output_dir OUTPUT_DIR -output_name OUTPUT_FILE
147
+
148
+ Seq-Combiner v0.5.0: Seq-Combiner Run Parameters.
149
+
150
+ options:
151
+ -h, --help show this help message and exit
152
+
153
+ Required Arguments:
154
+ -input_dir INPUT_DIR Directory location where the files are located.
155
+ -input_type {separate,combined}
156
+ Type of input files: 'separate' for separate FASTA and GFF files, 'combined' for GFF files with embedded FASTA sequences.
157
+ -name_split NAME_SPLIT
158
+ substring used to split the filename and extract the genome name ('_combined.gff3' or '.gff').
159
+ -output_dir OUTPUT_DIR
160
+ Directory for all output files.
161
+ -output_name OUTPUT_FILE
162
+ Output file name.
163
+ ```
@@ -0,0 +1,14 @@
1
+ PyamilySeq/CD-Hit_StORF-Reporter_Cross-Genera_Builder.py,sha256=UzQ5iOKCNfurxmj1pnkowF11YfWBO5vnBCKxQK6goB8,26538
2
+ PyamilySeq/Constants.py,sha256=H1GMMb0WK68bphZPfzCvdvvSi5BeQc80QL4igt17S94,31
3
+ PyamilySeq/PyamilySeq.py,sha256=ONDjQZoR4YCdAoDq2Ufv8mcY_1ek1LPJF-OtS4gzXDs,11276
4
+ PyamilySeq/PyamilySeq_Genus.py,sha256=JpLLu3QaahUHBe7E80xVHtFORGuyeUMOt9eiLN5uazc,31286
5
+ PyamilySeq/PyamilySeq_Species.py,sha256=6LHEdp6Vndoder8dlVSuyUKHdCbo5Rbxea1rnncrceY,35172
6
+ PyamilySeq/Seq_Combiner.py,sha256=bHEIR-MZODSGm8n69ZIN-XzEoct5WZ1kH5Xa6uKCu4Y,1972
7
+ PyamilySeq/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ PyamilySeq/utils.py,sha256=KhEnwzgVZyUu_Q92ukRPUrVD2505xSg9NY6e75nUmPQ,6487
9
+ PyamilySeq-0.5.0.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
10
+ PyamilySeq-0.5.0.dist-info/METADATA,sha256=II_Elm1hg0nTXjmnEnsct2e4l2KQ1xR2hcXgp1wEiJA,7649
11
+ PyamilySeq-0.5.0.dist-info/WHEEL,sha256=Wyh-_nZ0DJYolHNn1_hMa4lM7uDedD_RGVwbmTjyItk,91
12
+ PyamilySeq-0.5.0.dist-info/entry_points.txt,sha256=QtXD1tmnLvRAkIpGWZgXm1lfLH8GGeCwxmgoHZaTp98,102
13
+ PyamilySeq-0.5.0.dist-info/top_level.txt,sha256=J6JhugUQTq4rq96yibAlQu3o4KCM9WuYfqr3w1r119M,11
14
+ PyamilySeq-0.5.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (71.0.4)
2
+ Generator: setuptools (71.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,2 +1,3 @@
1
1
  [console_scripts]
2
2
  PyamilySeq = PyamilySeq.PyamilySeq:main
3
+ Seq-Combiner = PyamilySeq.Seq_Combiner:main