lattice-sub 1.5.3__py3-none-any.whl → 1.5.4__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.
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: lattice-sub
3
- Version: 1.5.3
3
+ Version: 1.5.4
4
4
  Summary: Lattice subtraction for cryo-EM micrographs - removes periodic crystal signals to reveal non-periodic features
5
5
  Author-email: George Stephenson <george.stephenson@colorado.edu>, Vignesh Kasinath <vignesh.kasinath@colorado.edu>
6
6
  License: MIT
7
7
  Project-URL: Homepage, https://github.com/gsstephenson/cryoem-lattice-subtraction
8
8
  Project-URL: Documentation, https://github.com/gsstephenson/cryoem-lattice-subtraction#readme
9
9
  Project-URL: Repository, https://github.com/gsstephenson/cryoem-lattice-subtraction
10
- Keywords: cryo-em,electron-microscopy,lattice-subtraction,image-processing,fft
10
+ Keywords: cryo-em,electron-microscopy,lattice-subtraction,image-processing,fft,live-processing,file-watching
11
11
  Classifier: Development Status :: 5 - Production/Stable
12
12
  Classifier: Intended Audience :: Science/Research
13
13
  Classifier: License :: OSI Approved :: MIT License
@@ -57,6 +57,8 @@ Dynamic: license-file
57
57
 
58
58
  **Remove periodic lattice patterns from cryo-EM micrographs to reveal non-periodic features.**
59
59
 
60
+ > **NEW in v1.5.0:** Live watch mode with `--live` flag! Automatically process motion-corrected files as they arrive during data collection.
61
+
60
62
  ![Example Result](https://raw.githubusercontent.com/gsstephenson/cryoem-lattice-subtraction/main/docs/images/example_comparison.png)
61
63
 
62
64
  ---
@@ -89,6 +91,20 @@ lattice-sub process your_image.mrc -o output.mrc --pixel-size 0.56
89
91
  lattice-sub batch input_folder/ output_folder/ --pixel-size 0.56
90
92
  ```
91
93
 
94
+ ### Live Watch Mode (NEW in v1.5.0)
95
+
96
+ Process files as they arrive during data collection:
97
+
98
+ ```bash
99
+ lattice-sub batch input_folder/ output_folder/ --pixel-size 0.56 --live
100
+ ```
101
+
102
+ In live mode:
103
+ - If files already exist: batch processes them first with all GPUs
104
+ - Then switches to watch mode: monitors for new files with single GPU
105
+ - Press Ctrl+C to stop watching
106
+ - Perfect for processing motion-corrected files as they're generated
107
+
92
108
  ### Generate Comparison Images
93
109
 
94
110
  ```bash
@@ -118,6 +134,7 @@ lattice-sub batch input_folder/ output_folder/ -p 0.56 --vis comparisons/ -n 10
118
134
  | `-t, --threshold` | Peak detection sensitivity (default: **auto** - optimized per image) |
119
135
  | `--vis DIR` | Generate 4-panel comparison PNGs in DIR |
120
136
  | `-n, --num-vis N` | Limit visualizations to first N images |
137
+ | `--live` | **Watch mode**: continuously monitor directory for new files (Ctrl+C to stop) |
121
138
  | `--cpu` | Force CPU processing (GPU is used by default) |
122
139
  | `-q, --quiet` | Hide the banner and progress messages |
123
140
  | `-v, --verbose` | Show detailed processing information |
@@ -192,6 +209,9 @@ When processing batches on systems with multiple GPUs, files are automatically d
192
209
  ```bash
193
210
  # Automatically uses all available GPUs
194
211
  lattice-sub batch input_folder/ output_folder/ -p 0.56
212
+
213
+ # Or watch for new files in real-time (live mode)
214
+ lattice-sub batch input_folder/ output_folder/ -p 0.56 --live
195
215
  ```
196
216
 
197
217
  **Example with 2 GPUs and 100 images:**
@@ -220,7 +240,7 @@ lattice-sub batch input/ output/ -p 0.56
220
240
 
221
241
  **Output:**
222
242
  ```
223
- Phase-preserving FFT inpainting for cryo-EM | v1.3.0
243
+ Phase-preserving FFT inpainting for cryo-EM | v1.5.3
224
244
 
225
245
  Configuration
226
246
  -------------
@@ -280,6 +300,23 @@ stats = processor.process_directory("raw/", "processed/")
280
300
  print(f"Processed {stats.successful}/{stats.total} files")
281
301
  ```
282
302
 
303
+ ### Live Watch Mode
304
+
305
+ ```python
306
+ from lattice_subtraction import LiveBatchProcessor, Config
307
+
308
+ config = Config(pixel_ang=0.56)
309
+ processor = LiveBatchProcessor(
310
+ input_dir="raw/",
311
+ output_dir="processed/",
312
+ config=config,
313
+ num_workers=1
314
+ )
315
+
316
+ # Process existing files, then watch for new ones
317
+ processor.watch_and_process() # Runs until Ctrl+C
318
+ ```
319
+
283
320
  ---
284
321
 
285
322
  ## What It Does
@@ -450,6 +487,7 @@ src/lattice_subtraction/
450
487
  ├── cli.py # Command-line interface
451
488
  ├── core.py # LatticeSubtractor main class
452
489
  ├── batch.py # Parallel batch processing
490
+ ├── watch.py # Live watch mode (NEW in v1.5.0)
453
491
  ├── config.py # Configuration dataclass
454
492
  ├── io.py # MRC file I/O
455
493
  ├── masks.py # FFT mask generation
@@ -1,7 +1,7 @@
1
- lattice_sub-1.5.3.dist-info/licenses/LICENSE,sha256=2kPoH0cbEp0cVEGqMpyF2IQX1npxdtQmWJB__HIRSb0,1101
2
- lattice_subtraction/__init__.py,sha256=ampJE0j9aT_ENZ1Sddx041CQL2bhaDyWbkkd3WQeofg,1828
1
+ lattice_sub-1.5.4.dist-info/licenses/LICENSE,sha256=2kPoH0cbEp0cVEGqMpyF2IQX1npxdtQmWJB__HIRSb0,1101
2
+ lattice_subtraction/__init__.py,sha256=1pt-fhNgcIdz-IiQQ4ZAQ_lb4jqgLveUB_T077hmrxU,1828
3
3
  lattice_subtraction/batch.py,sha256=G_-sxtNT46gOr22miDcG69uOnud3x6a9hEqNv4HpfwQ,20984
4
- lattice_subtraction/cli.py,sha256=7SZTIA2RTGFVTIMRE9ymOmKx01y1OfEkw_SNgkhykjA,27294
4
+ lattice_subtraction/cli.py,sha256=SvnZ2fqUqhdHe2_jkdbMlX-NYWDzyfIHkvPXwXXSNwk,28606
5
5
  lattice_subtraction/config.py,sha256=uzwKb5Zi3phHUk2ZgoiLsQdwFdN-rTiY8n02U91SObc,8426
6
6
  lattice_subtraction/core.py,sha256=VzcecSZHRuBuHUc2jHGv8LalINL75RH0aTpABI708y8,16265
7
7
  lattice_subtraction/io.py,sha256=uHku6rJ0jeCph7w-gOIDJx-xpNoF6PZcLfb5TBTOiw0,4594
@@ -11,8 +11,8 @@ lattice_subtraction/threshold_optimizer.py,sha256=yEsGM_zt6YjgEulEZqtRy113xOFB69
11
11
  lattice_subtraction/ui.py,sha256=-PdBSE6yF78ze85aHuGPNCziYsrQRyXQDUjYRdiTJFM,11436
12
12
  lattice_subtraction/visualization.py,sha256=noRhBXi_Xd1b5deBfVo0Bk0f3d2kqlf3_SQwAPJC0E0,12032
13
13
  lattice_subtraction/watch.py,sha256=wIXjdw0ofB71J8OvU1E5piq5BHEQG73R1VVgdzxVIow,17313
14
- lattice_sub-1.5.3.dist-info/METADATA,sha256=XppWofRhaYp6OMqzP862YyIWA5zek9FluCDEOFJjVOU,14930
15
- lattice_sub-1.5.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
16
- lattice_sub-1.5.3.dist-info/entry_points.txt,sha256=o8PzJR8kFnXlKZufoYGBIHpiosM-P4PZeKZXJjtPS6Y,61
17
- lattice_sub-1.5.3.dist-info/top_level.txt,sha256=BOuW-sm4G-fQtsWPRdeLzWn0WS8sDYVNKIMj5I3JXew,20
18
- lattice_sub-1.5.3.dist-info/RECORD,,
14
+ lattice_sub-1.5.4.dist-info/METADATA,sha256=R16yRpGTZEV_JomHmfR-rivmd8RaLctljTXK9WvMGmk,16155
15
+ lattice_sub-1.5.4.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
16
+ lattice_sub-1.5.4.dist-info/entry_points.txt,sha256=o8PzJR8kFnXlKZufoYGBIHpiosM-P4PZeKZXJjtPS6Y,61
17
+ lattice_sub-1.5.4.dist-info/top_level.txt,sha256=BOuW-sm4G-fQtsWPRdeLzWn0WS8sDYVNKIMj5I3JXew,20
18
+ lattice_sub-1.5.4.dist-info/RECORD,,
@@ -19,7 +19,7 @@ Example:
19
19
  >>> result.save("output.mrc")
20
20
  """
21
21
 
22
- __version__ = "1.5.3"
22
+ __version__ = "1.5.4"
23
23
  __author__ = "George Stephenson & Vignesh Kasinath"
24
24
 
25
25
  from .config import Config
@@ -313,9 +313,9 @@ def setup_gpu(yes: bool, force: bool):
313
313
  )
314
314
  @click.option(
315
315
  "--pixel-size", "-p",
316
- type=float,
317
- required=True,
318
- help="Pixel size in Angstroms",
316
+ type=click.FloatRange(min=0.0, min_open=True),
317
+ required=False,
318
+ help="Pixel size in Angstroms (must be positive). Required unless --config provides pixel_ang.",
319
319
  )
320
320
  @click.option(
321
321
  "--threshold", "-t",
@@ -397,7 +397,23 @@ def process(
397
397
  if config:
398
398
  logger.info(f"Loading config from {config}")
399
399
  cfg = Config.from_yaml(config)
400
+ # Override with command-line options if provided
401
+ if pixel_size is not None:
402
+ cfg.pixel_ang = pixel_size
403
+ if threshold is not None:
404
+ cfg.threshold = threshold
405
+ if inside_radius != 90.0: # Non-default value
406
+ cfg.inside_radius_ang = inside_radius
407
+ if outside_radius is not None:
408
+ cfg.outside_radius_ang = outside_radius
409
+ if cpu:
410
+ cfg.backend = "numpy"
400
411
  else:
412
+ # No config file - pixel_size is required
413
+ if pixel_size is None:
414
+ raise click.UsageError(
415
+ "--pixel-size is required when --config is not provided"
416
+ )
401
417
  # Use "auto" threshold if not specified (GPU-optimized per-image)
402
418
  thresh_value = threshold if threshold is not None else "auto"
403
419
  cfg = Config(
@@ -462,9 +478,9 @@ def process(
462
478
  @click.argument("output_dir", type=click.Path(file_okay=False))
463
479
  @click.option(
464
480
  "--pixel-size", "-p",
465
- type=float,
466
- required=True,
467
- help="Pixel size in Angstroms",
481
+ type=click.FloatRange(min=0.0, min_open=True),
482
+ required=False,
483
+ help="Pixel size in Angstroms (must be positive). Required unless --config provides pixel_ang.",
468
484
  )
469
485
  @click.option(
470
486
  "--threshold", "-t",
@@ -571,7 +587,19 @@ def batch(
571
587
  # Load or create config
572
588
  if config:
573
589
  cfg = Config.from_yaml(config)
590
+ # Override with command-line options if provided
591
+ if pixel_size is not None:
592
+ cfg.pixel_ang = pixel_size
593
+ if threshold is not None:
594
+ cfg.threshold = threshold
595
+ if cpu:
596
+ cfg.backend = "numpy"
574
597
  else:
598
+ # No config file - pixel_size is required
599
+ if pixel_size is None:
600
+ raise click.UsageError(
601
+ "--pixel-size is required when --config is not provided"
602
+ )
575
603
  # Use "auto" threshold if not specified (GPU-optimized per-image)
576
604
  thresh_value = threshold if threshold is not None else "auto"
577
605
  cfg = Config(