countmut 0.1.2__tar.gz → 0.1.4__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: countmut
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: Unified ultra-fast strand-aware mutation counter (C backend + samtools-style -e/-p filters)
5
5
  Author-email: Ye Chang <yech1990@gmail.com>
6
6
  License-Expression: MIT
@@ -100,7 +100,7 @@ def _build_cmd(
100
100
  "--threads",
101
101
  str(ecfg.threads or min(os.cpu_count() or 1, 8)),
102
102
  "--max-depth",
103
- str(fcfg.max_depth or 8000),
103
+ str(fcfg.max_depth), # 0 = unlimited
104
104
  ]
105
105
  if fcfg.max_unc is not None:
106
106
  cmd += ["--max-unc", str(fcfg.max_unc)]
@@ -137,12 +137,24 @@ def _build_cmd(
137
137
  cmd.append("--vcf")
138
138
  if ecfg.min_depth:
139
139
  cmd += ["--min-depth", str(ecfg.min_depth)]
140
+ if ecfg.verbose:
141
+ cmd.append("--verbose")
140
142
  return cmd
141
143
 
142
144
 
143
145
  # ---------------------------------------------------------------------------
144
146
  # public entry point
145
147
  # ---------------------------------------------------------------------------
148
+ def _forward_stderr(stream) -> None:
149
+ """Forward a child process' stderr lines to our stderr (--verbose)."""
150
+ try:
151
+ for line in stream:
152
+ sys.stderr.write(line)
153
+ sys.stderr.flush()
154
+ except (ValueError, OSError):
155
+ pass
156
+
157
+
146
158
  def run_backend(
147
159
  samfile: str,
148
160
  reference: str,
@@ -190,12 +202,27 @@ def run_backend(
190
202
  ecfg=ecfg,
191
203
  )
192
204
  start = time.time()
193
- proc = subprocess.run(cmd, capture_output=True, text=True)
205
+ stdout = ""
206
+ if ecfg.verbose:
207
+ # stream the C core's stderr (progress) to our stderr in real time
208
+ proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
209
+ import threading
210
+
211
+ fwd = threading.Thread(
212
+ target=_forward_stderr, args=(proc.stderr,), daemon=True
213
+ )
214
+ fwd.start()
215
+ out, _ = proc.communicate()
216
+ fwd.join(timeout=2)
217
+ stdout = out or ""
218
+ else:
219
+ proc = subprocess.run(cmd, capture_output=True, text=True)
220
+ stdout = proc.stdout
194
221
  elapsed = time.time() - start
195
222
 
196
223
  if output is None and proc.returncode == 0:
197
- # stream the TSV from stdout (already printed by the binary)
198
- sys.stdout.write(proc.stdout)
224
+ # stream the TSV from stdout
225
+ sys.stdout.write(stdout)
199
226
  sys.stdout.flush()
200
227
 
201
228
  rows = 0
@@ -203,7 +230,7 @@ def run_backend(
203
230
  with open(output) as fh:
204
231
  rows = sum(1 for _ in fh) - 1
205
232
  else:
206
- rows = len(proc.stdout.splitlines()) - 1
233
+ rows = len(stdout.splitlines()) - 1
207
234
 
208
235
  if proc.returncode != 0:
209
236
  sys.stderr.write(f"[countmut] backend error: {proc.stderr}\n")
@@ -26,7 +26,7 @@ from .model import EngineConfig, FilterConfig, MutationConfig, StrandConfig
26
26
  try:
27
27
  __version__ = importlib_metadata.version("countmut")
28
28
  except importlib_metadata.PackageNotFoundError: # pragma: no cover
29
- __version__ = "0.1.2"
29
+ __version__ = "0.1.4"
30
30
 
31
31
  click.rich_click.TEXT_MARKUP = "rich"
32
32
  click.rich_click.SHOW_ARGUMENTS = True
@@ -144,6 +144,13 @@ console = Console()
144
144
  show_default=True,
145
145
  help="Minimum site depth to report (base/allele mode)",
146
146
  )
147
+ @click.option(
148
+ "--max-depth",
149
+ type=int,
150
+ default=0,
151
+ show_default=True,
152
+ help="Per-position depth cap (pileup engine; 0 = unlimited, counts all reads)",
153
+ )
147
154
  @click.option(
148
155
  "--min-allele-support",
149
156
  type=int,
@@ -166,7 +173,12 @@ console = Console()
166
173
  default=None,
167
174
  help="Lua site filter (e.g. \"ref == 'A' and depth >= 5 and g > 2\")",
168
175
  )
169
- @click.option("--verbose", is_flag=True, default=False, help="Verbose logging")
176
+ @click.option(
177
+ "--verbose",
178
+ is_flag=True,
179
+ default=False,
180
+ help="Real-time per-region progress on stderr (large BAMs)",
181
+ )
170
182
  def main(
171
183
  samfile,
172
184
  reference,
@@ -182,6 +194,7 @@ def main(
182
194
  split_strand,
183
195
  count_indels,
184
196
  min_depth,
197
+ max_depth,
185
198
  min_allele_support,
186
199
  vcf,
187
200
  read_expr,
@@ -202,6 +215,7 @@ def main(
202
215
  min_con=1,
203
216
  trim_start=2,
204
217
  trim_end=2,
218
+ max_depth=max_depth,
205
219
  )
206
220
  mcfg = (
207
221
  MutationConfig(
@@ -223,6 +237,7 @@ def main(
223
237
  vcf=vcf,
224
238
  read_expr=read_expr,
225
239
  pile_expr=pile_expr,
240
+ verbose=verbose,
226
241
  )
227
242
 
228
243
  config_table = Table(box=rich.box.MINIMAL, show_header=False)
@@ -85,5 +85,6 @@ class EngineConfig:
85
85
  vcf: bool = False # allele mode: emit VCF
86
86
  count_indels: bool = False
87
87
  split_strand: bool = True
88
+ verbose: bool = False # real-time per-region progress on stderr
88
89
  report_reference_bases: bool = False # -k flanking window (pbr)
89
90
  flanking: int = 0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: countmut
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: Unified ultra-fast strand-aware mutation counter (C backend + samtools-style -e/-p filters)
5
5
  Author-email: Ye Chang <yech1990@gmail.com>
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "countmut"
7
- version = "0.1.2"
7
+ version = "0.1.4"
8
8
  description = "Unified ultra-fast strand-aware mutation counter (C backend + samtools-style -e/-p filters)"
9
9
  readme = "README.md"
10
10
  license = "MIT"
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