drep 3.6.2__tar.gz → 3.7.1__tar.gz

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.
Files changed (36) hide show
  1. {drep-3.6.2 → drep-3.7.1}/PKG-INFO +10 -2
  2. drep-3.7.1/drep/VERSION +1 -0
  3. {drep-3.6.2 → drep-3.7.1}/drep/argumentParser.py +3 -3
  4. {drep-3.6.2 → drep-3.7.1}/drep/d_analyze.py +5 -3
  5. {drep-3.6.2 → drep-3.7.1}/drep/d_bonus.py +5 -3
  6. {drep-3.6.2 → drep-3.7.1}/drep/d_cluster/compare_utils.py +17 -2
  7. {drep-3.6.2 → drep-3.7.1}/drep/d_cluster/controller.py +11 -1
  8. {drep-3.6.2 → drep-3.7.1}/drep/d_cluster/external.py +3 -2
  9. {drep-3.6.2 → drep-3.7.1}/drep/d_evaluate.py +21 -0
  10. {drep-3.6.2 → drep-3.7.1}/drep/d_filter.py +1 -1
  11. {drep-3.6.2 → drep-3.7.1}/drep.egg-info/PKG-INFO +10 -2
  12. {drep-3.6.2 → drep-3.7.1}/drep.egg-info/requires.txt +2 -0
  13. {drep-3.6.2 → drep-3.7.1}/setup.py +2 -0
  14. drep-3.6.2/drep/VERSION +0 -1
  15. {drep-3.6.2 → drep-3.7.1}/README.md +0 -0
  16. {drep-3.6.2 → drep-3.7.1}/bin/dRep +0 -0
  17. {drep-3.6.2 → drep-3.7.1}/drep/WorkDirectory.py +0 -0
  18. {drep-3.6.2 → drep-3.7.1}/drep/__init__.py +0 -0
  19. {drep-3.6.2 → drep-3.7.1}/drep/controller.py +0 -0
  20. {drep-3.6.2 → drep-3.7.1}/drep/d_adjust.py +0 -0
  21. {drep-3.6.2 → drep-3.7.1}/drep/d_choose.py +0 -0
  22. {drep-3.6.2 → drep-3.7.1}/drep/d_cluster/__init__.py +0 -0
  23. {drep-3.6.2 → drep-3.7.1}/drep/d_cluster/cluster_utils.py +0 -0
  24. {drep-3.6.2 → drep-3.7.1}/drep/d_cluster/greedy_clustering.py +0 -0
  25. {drep-3.6.2 → drep-3.7.1}/drep/d_cluster/parsers.py +0 -0
  26. {drep-3.6.2 → drep-3.7.1}/drep/d_cluster/utils.py +0 -0
  27. {drep-3.6.2 → drep-3.7.1}/drep/d_workflows.py +0 -0
  28. {drep-3.6.2 → drep-3.7.1}/drep.egg-info/SOURCES.txt +0 -0
  29. {drep-3.6.2 → drep-3.7.1}/drep.egg-info/dependency_links.txt +0 -0
  30. {drep-3.6.2 → drep-3.7.1}/drep.egg-info/not-zip-safe +0 -0
  31. {drep-3.6.2 → drep-3.7.1}/drep.egg-info/top_level.txt +0 -0
  32. {drep-3.6.2 → drep-3.7.1}/helper_scripts/ScaffoldLevel_dRep.py +0 -0
  33. {drep-3.6.2 → drep-3.7.1}/helper_scripts/parse_stb.py +0 -0
  34. {drep-3.6.2 → drep-3.7.1}/pyproject.toml +0 -0
  35. {drep-3.6.2 → drep-3.7.1}/setup.cfg +0 -0
  36. {drep-3.6.2 → drep-3.7.1}/tests/test_suite.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: drep
3
- Version: 3.6.2
3
+ Version: 3.7.1
4
4
  Summary: De-replication of microbial genomes assembled from multiple samples
5
5
  Home-page: https://github.com/MrOlm/drep
6
6
  Author: Matt Olm
@@ -13,4 +13,12 @@ Requires-Dist: matplotlib
13
13
  Requires-Dist: biopython
14
14
  Requires-Dist: scikit-learn
15
15
  Requires-Dist: tqdm
16
+ Requires-Dist: networkx
17
+ Requires-Dist: setuptools
16
18
  Requires-Dist: pytest
19
+ Dynamic: author
20
+ Dynamic: author-email
21
+ Dynamic: home-page
22
+ Dynamic: license
23
+ Dynamic: requires-dist
24
+ Dynamic: summary
@@ -0,0 +1 @@
1
+ 3.7.1
@@ -44,7 +44,7 @@ def printHelp():
44
44
  print(' ...::: dRep v' + VERSION + ' :::...''')
45
45
  print('''\
46
46
 
47
- Matt Olm. MIT License. Banfield Lab, UC Berkeley. 2017 (last updated 2025)
47
+ Matt Olm. MIT License. Banfield Lab, UC Berkeley. 2017 (last updated 2026)
48
48
 
49
49
  See https://drep.readthedocs.io/en/latest/index.html for documentation
50
50
  Choose one of the operations below for more detailed help.
@@ -96,8 +96,8 @@ def parse_args(args):
96
96
  or eukaryotes or things where checkM scoring does not work. Will only \
97
97
  choose genomes based on length and N50", action='store_true')
98
98
  Iflags.add_argument('--genomeInfo', help='location of .csv file containing quality \
99
- information on the genomes. Must contain: ["genome"(basename of .fasta file \
100
- of that genome), "completeness"(0-100 value for completeness of the genome), \
99
+ information on the genomes. Must contain: ["genome"(filename of .fasta file \
100
+ of that genome, including extension e.g. genome.fasta), "completeness"(0-100 value for completeness of the genome), \
101
101
  "contamination"(0-100 value of the contamination of the genome)]')
102
102
  Iflags.add_argument("--checkM_method", help="Either lineage_wf (more accurate) \
103
103
  or taxonomy_wf (faster)", choices={'taxonomy_wf', 'lineage_wf'}, \
@@ -1016,7 +1016,9 @@ def fancy_dendrogram(linkage,names,name2color=False,threshold=False,self_thresh=
1016
1016
  ax = plt.gca()
1017
1017
  xlbls = ax.get_ymajorticklabels()
1018
1018
  for lbl in xlbls:
1019
- lbl.set_color(name2color[lbl.get_text()])
1019
+ color = name2color[lbl.get_text()]
1020
+ lbl.set_color('black')
1021
+ lbl.set_bbox(dict(facecolor=color, alpha=0.7, edgecolor='none', pad=2))
1020
1022
 
1021
1023
  # Add the threshold
1022
1024
  if threshold:
@@ -1062,7 +1064,7 @@ def gen_color_list(names,name2cluster):
1062
1064
  try:
1063
1065
  cluster2color[cluster] = cm(1.*int(cluster)/NUM_COLORS)
1064
1066
  except:
1065
- cluster2color[cluster] = cm(1.*int(str(cluster).split('_')[1])/NUM_COLORS)
1067
+ cluster2color[cluster] = cm(1.*float(str(cluster).split('_')[1])/NUM_COLORS)
1066
1068
 
1067
1069
  #2. generate list of colors
1068
1070
  colors = []
@@ -1095,7 +1097,7 @@ def gen_color_dictionary(names, name2cluster):
1095
1097
  try:
1096
1098
  cluster2color[cluster] = cm(1.*int(cluster)/NUM_COLORS)
1097
1099
  except:
1098
- cluster2color[cluster] = cm(1.*int(str(cluster).split('_')[1])/NUM_COLORS)
1100
+ cluster2color[cluster] = cm(1.*float(str(cluster).split('_')[1])/NUM_COLORS)
1099
1101
 
1100
1102
  #2. name to color
1101
1103
  name2color = {}
@@ -118,9 +118,11 @@ def find_program(dep):
118
118
  works = False
119
119
  if loc != None:
120
120
  try:
121
- o = subprocess.check_output([loc, '-h'],stderr= subprocess.STDOUT)
122
- works = True
123
- except:
121
+ result = subprocess.run([loc, '-h'], capture_output=True)
122
+ # Some tools (e.g. older fastANI) exit with code 1 on -h even when working
123
+ if len(result.stdout) > 0 or len(result.stderr) > 0:
124
+ works = True
125
+ except Exception:
124
126
  pass
125
127
 
126
128
  return loc, works
@@ -41,8 +41,11 @@ class genomeChunk():
41
41
 
42
42
  def gen_paste_cmd(self, mash_exe):
43
43
  all_file = os.path.join(self.chunk_folder, 'chunk_all.msh')
44
- cmd = [mash_exe, 'paste', all_file] \
45
- + glob.glob(os.path.join(self.chunk_folder, '*'))
44
+ list_file = os.path.join(self.chunk_folder, 'sketch_list.txt')
45
+ with open(list_file, 'w') as f:
46
+ for path in glob.glob(os.path.join(self.chunk_folder, '*.msh')):
47
+ f.write(path + '\n')
48
+ cmd = [mash_exe, 'paste', '-l', all_file, list_file]
46
49
  self.all_file = all_file
47
50
  return cmd
48
51
 
@@ -98,6 +101,18 @@ def all_vs_all_MASH(Bdb, data_folder, **kwargs):
98
101
  debug: if True, log all of the commands
99
102
  wd: if you want to log commands, you also need the wd
100
103
  """
104
+ # Warn if sketch size may be too small for the requested P_ani threshold
105
+ MASH_s = kwargs.get('MASH_sketch', 1000)
106
+ P_ani = kwargs.get('P_ani', 0.9)
107
+ if P_ani < 0.90 and MASH_s <= 1000:
108
+ logging.warning(
109
+ f"P_ani is set to {P_ani} but MASH_sketch is only {MASH_s}. "
110
+ "At low ANI thresholds, a small sketch size can cause Mash to underestimate "
111
+ "distances and place related genomes into separate primary clusters, which "
112
+ "means they will never be compared with the secondary algorithm. "
113
+ "Consider increasing -ms (MASH_sketch) to 10000 or higher."
114
+ )
115
+
101
116
  # Set up the mash folder structure
102
117
  logdir, MASH_folder, sketch_folder, mash_exe = prepare_mash(data_folder, **kwargs)
103
118
 
@@ -95,6 +95,11 @@ class GenomeClusterController(object):
95
95
  Cdb = self.wd.get_db('CdbF')
96
96
  logging.info('2. Primary clustering cache loaded')
97
97
 
98
+ elif len(self.Bdb) < 2:
99
+ logging.warning("Fewer than 2 genomes remain after filtering — skipping MASH clustering")
100
+ Cdb = drep.d_cluster.external._gen_nomash_cdb(self.Bdb)
101
+ Mdb = pd.DataFrame({'Blank': []})
102
+
98
103
  else:
99
104
  logging.info("Running pair-wise MASH clustering")
100
105
  Mdb, Cdb, cluster_ret = drep.d_cluster.compare_utils.all_vs_all_MASH(self.Bdb, self.wd.get_dir('MASH'), **self.kwargs)
@@ -125,7 +130,12 @@ class GenomeClusterController(object):
125
130
  # Wipe any old secondary clusters
126
131
  self.wd._wipe_secondary_clusters()
127
132
 
128
- if not self.kwargs.get('SkipSecondary', False):
133
+ if len(self.Bdb) < 2:
134
+ logging.warning("Fewer than 2 genomes remain after filtering — skipping secondary clustering")
135
+ Cdb = drep.d_cluster.utils._gen_nomani_cdb(self.MCdb, data_folder=self.wd.get_dir('data'), **self.kwargs)
136
+ Ndb = pd.DataFrame({'Blank': []})
137
+
138
+ elif not self.kwargs.get('SkipSecondary', False):
129
139
  if cached:
130
140
  logging.info('3. Loading cached secondary clustering')
131
141
  Ndb = self.wd.get_db('Ndb')
@@ -116,6 +116,7 @@ def run_pairwise_fastANI(genome_list, outdir, **kwargs):
116
116
  return pd.DataFrame()
117
117
 
118
118
  def run_pairwise_skani(genome_list, outdir, **kwargs):
119
+ p = kwargs.get('processors',6)
119
120
  code = drep.d_cluster.utils._randomString(stringLength=10)
120
121
  extra_cmd = kwargs.get('skani_extra', "")
121
122
 
@@ -134,7 +135,7 @@ def run_pairwise_skani(genome_list, outdir, **kwargs):
134
135
  exe_loc = drep.get_exe('skani')
135
136
  out_base = os.path.join(outdir, 'skani_out_{0}'.format(code))
136
137
  #cmd = [exe_loc, '--ql', glist, '--rl', glist, '-o', out_base, '--matrix', '-t', str(p), "--minFraction", str(0)]
137
- cmd = [exe_loc, "triangle", "-t", "1", '-o', out_base, '--full-matrix', '-l', glist, '--detailed', '-s', "1", '--min-af', "0"]
138
+ cmd = [exe_loc, "triangle", "-t", str(p), '-o', out_base, '--full-matrix', '-l', glist, '--detailed', '-s', "1", '--min-af', "0"]
138
139
  if extra_cmd != "":
139
140
  cmd += extra_cmd.split(' ')
140
141
 
@@ -219,7 +220,7 @@ def fastani_one_vs_many(one, many, genome_rep_file, outdir, **kwargs):
219
220
  return fdb
220
221
 
221
222
  def load_fastani(file):
222
- fdb = pd.read_csv(file, names=['reference', 'querry', 'ANI', 'j1', 'j2'], delim_whitespace=True)
223
+ fdb = pd.read_csv(file, names=['reference', 'querry', 'ANI', 'j1', 'j2'], sep=r'\s+')
223
224
  for c in ['reference', 'querry']:
224
225
  fdb[c] = [drep.d_cluster.utils._get_genome_name_from_fasta(x) for x in fdb[c]]
225
226
  fdb = fdb.rename(columns={'ANI':'ani'})
@@ -253,6 +253,27 @@ def evaluate_winners(wd, **kwrags):
253
253
  Table['N50'].append(d['N50 (scaffolds)'].tolist()[0])
254
254
  Table['completeness_metric'].append(comp_str(d['Completeness'].tolist()[0]))
255
255
  Table['contamination_metric'].append(con_str(d['Contamination'].tolist()[0]))
256
+ elif wd.hasDb('genomeInfo'):
257
+ Gdb = wd.get_db('genomeInfo')
258
+ d = Gdb[Gdb['genome'] == row['genome']]
259
+ if len(d) > 0:
260
+ comp = d['completeness'].tolist()[0]
261
+ con = d['contamination'].tolist()[0]
262
+ Table['completeness'].append(comp)
263
+ Table['contamination'].append(con)
264
+ Table['strain_heterogeneity'].append(d['strain_heterogeneity'].tolist()[0] if 'strain_heterogeneity' in d.columns else "NA")
265
+ Table['size'].append(d['length'].tolist()[0] if 'length' in d.columns else "NA")
266
+ Table['N50'].append(d['N50'].tolist()[0] if 'N50' in d.columns else "NA")
267
+ Table['completeness_metric'].append(comp_str(comp))
268
+ Table['contamination_metric'].append(con_str(con))
269
+ else:
270
+ Table['completeness'].append("NA")
271
+ Table['contamination'].append("NA")
272
+ Table['strain_heterogeneity'].append("NA")
273
+ Table['size'].append("NA")
274
+ Table['N50'].append("NA")
275
+ Table['completeness_metric'].append("NA")
276
+ Table['contamination_metric'].append("NA")
256
277
  else:
257
278
  Table['completeness'].append("NA")
258
279
  Table['contamination'].append("NA")
@@ -571,7 +571,7 @@ def run_checkM(genome_folder_whole, checkm_outf_whole, **kwargs):
571
571
  else:
572
572
  cmd = [check_exe,checkm_method,genome_folder,checkm_outf,'-f',\
573
573
  checkm_outf + '/results.tsv','--tab_table','-t',str(t),'--pplacer_threads',\
574
- str(t),'-g','-x','faa']
574
+ str(min(64, int(t))),'-g','-x','faa']
575
575
 
576
576
  logging.debug("Running CheckM with command: {0}".format(' '.join(cmd)))
577
577
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: drep
3
- Version: 3.6.2
3
+ Version: 3.7.1
4
4
  Summary: De-replication of microbial genomes assembled from multiple samples
5
5
  Home-page: https://github.com/MrOlm/drep
6
6
  Author: Matt Olm
@@ -13,4 +13,12 @@ Requires-Dist: matplotlib
13
13
  Requires-Dist: biopython
14
14
  Requires-Dist: scikit-learn
15
15
  Requires-Dist: tqdm
16
+ Requires-Dist: networkx
17
+ Requires-Dist: setuptools
16
18
  Requires-Dist: pytest
19
+ Dynamic: author
20
+ Dynamic: author-email
21
+ Dynamic: home-page
22
+ Dynamic: license
23
+ Dynamic: requires-dist
24
+ Dynamic: summary
@@ -5,4 +5,6 @@ matplotlib
5
5
  biopython
6
6
  scikit-learn
7
7
  tqdm
8
+ networkx
9
+ setuptools
8
10
  pytest
@@ -24,6 +24,8 @@ setup(name='drep',
24
24
  'biopython',
25
25
  'scikit-learn',
26
26
  'tqdm',
27
+ 'networkx',
28
+ 'setuptools',
27
29
  'pytest'
28
30
  ],
29
31
  zip_safe=False)
drep-3.6.2/drep/VERSION DELETED
@@ -1 +0,0 @@
1
- 3.6.2
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes