-
Notifications
You must be signed in to change notification settings - Fork 1
Time Complexity Analysis
The Cetamura Photo Processing System is designed to batch process archaeological photo archives, converting JPG files to TIFF format, pairing them with XML metadata, and packaging them into ZIP archives with validation.
Total System Complexity: O(N × M) where:
- N = number of files in directory tree
- M = average image size (for image processing operations)
Function: find_photo_sets_enhanced()
Operations:
-
Recursive File Search -
find_all_files_recursive()- O(N): Single depth-first traversal of directory tree
- Max depth limit: 5 levels (prevents excessive recursion)
- Filters files by extension (.jpg, .xml, .ini)
-
File Grouping -
group_files_by_directory()- O(N): Single pass through all discovered files
- Uses
defaultdictfor O(1) insertion per file - Groups by parent directory using hash-based lookup
-
Hierarchical Set Detection -
find_hierarchical_sets()- O(K × L) where K = manifest files, L = avg subdirectories
- Typically K << N (few manifest files)
- Finds parent-child relationships between manifests and photos
-
Photo Set Validation -
validate_photo_set()- O(P) per photo set, where P = files in set
- Validates XML-JPG matching by filename
- Checks for orphaned files
- Total: O(N) across all sets (each file validated once)
Optimizations:
- Early termination on validation failure
- Dictionary-based lookups (O(1) average)
- Single-pass algorithms throughout
- Duplicate detection via set membership (O(1))
Function: pre_flight_checks()
Operations:
-
Disk Space Check
-
O(1): Single system call to
shutil.disk_usage() - Estimates required space: P × average_zip_size
-
O(1): Single system call to
-
Orphaned File Detection
- O(N): Scans staging directory for leftover TIFF/XML files
- Hash-based set operations for duplicate detection
-
Photo Set Validation
- O(P × F) where F = average files per set
- Validates each photo set structure
- Checks XML-JPG pairing consistency
Space Complexity: O(P) for storing photo set metadata
Function: batch_process_with_safety_nets()
Per-Item Processing Pipeline:
-
IID Extraction -
extract_iid_from_xml()- O(X) where X = XML file size
- XML parsing with ElementTree (linear parse)
- XPath navigation: O(depth) typically O(log X)
-
Image Loading & EXIF Processing
- O(M) where M = image dimensions (width × height)
- PIL Image.open(): O(M) to read pixel data
- EXIF tag reading: O(E) where E = EXIF data size (typically << M)
- Orientation detection: O(1) tag lookup
-
Image Rotation (if needed)
- O(M): Full pixel array transformation
- Operations: transpose, rotate (90°, 180°, 270°)
- In-place when possible (PIL optimizations)
-
TIFF Conversion -
convert_jpg_to_tiff()- O(M): Read entire image + write TIFF
- Compression: LZW (O(M) with constant factor)
- Color space conversion: O(M) if needed
- TIFF tag writing: O(1)
-
ZIP Archive Creation
- O(T + X + I) where T = TIFF size, X = XML size, I = manifest size
- ZIP compression: O(T) with LZW/Deflate
- Typically T ≈ M (TIFF size proportional to image size)
-
File Cleanup
- O(1) per file deletion
- 2-3 operations: delete JPG, delete temp TIFF
Total Per-Item: O(X + M + T) ≈ O(M) since M ≫ X and T ≈ M
Batch Processing: N items × O(M) = O(N × M)
Function: validate_batch_output()
Operations:
-
ZIP File Discovery
- O(Z): List all .zip files in output directory
-
ZIP Content Validation -
verify_zip_contents()- O(F) per ZIP: Read ZIP directory structure
- Validates: TIFF + XML + manifest.ini present
- Total: O(Z × F) ≈ O(Z) since F is constant (3)
-
CSV Reconciliation
- O(C) where C = CSV rows
- Single-pass CSV parsing
- Count SUCCESS/ERROR rows
-
Discrepancy Detection
- O(Z): Compare counts (input XML vs output ZIPs)
- Set operations for finding orphaned files: O(N)
Total Validation: O(Z + C + N) ≈ O(N) since Z ≤ N and C ≈ N
Persistent Storage:
- O(N): File path metadata for all discovered files
- O(P): Photo set structures (P << N)
- O(Z): ZIP file validation results
Temporary Storage:
- O(M): Single image loaded in memory at a time
- O(T): TIFF buffer during conversion (T ≈ M)
- O(X): XML DOM tree (X << M, typically KB not MB)
Optimizations:
- Sequential processing: Only one image in memory at a time
- Streaming ZIP: Files written directly to ZIP (no full buffering)
- Generator patterns: File discovery uses iterators where possible
Conditions:
- All photos have correct orientation (no rotation needed)
- Clean directory structure (no orphaned files)
- Sufficient disk space
- Fast I/O (SSD storage)
Complexity: O(N × M) with minimal constant factors
Conditions:
- All photos need 90° rotation (full pixel transformation)
- Complex hierarchical directory structure
- Slow I/O (network drive)
- Many validation failures requiring retries
Complexity: Still O(N × M) but with higher constant factors
Based on 76-file test dataset:
- Processing time: ~2-3 seconds per image
- Dominated by:
- Image I/O (reading JPG, writing TIFF): ~60%
- Image processing (rotation, conversion): ~30%
- ZIP compression: ~8%
- Validation: ~2%
Scales linearly with:
- Number of photo sets
- Number of files per set
- Total files in directory tree
Example:
- 76 files: ~3 minutes
- 760 files: ~30 minutes (10× increase)
- 7,600 files: ~5 hours (100× increase)
Scales with image dimensions:
- 4 MP (2048×2048): ~2 seconds/image
- 16 MP (4096×4096): ~8 seconds/image (4× increase)
- 64 MP (8192×8192): ~32 seconds/image (16× increase)
Currently: Sequential processing (one image at a time)
Potential Improvements:
- Thread-based: Limited by Python GIL for CPU-bound operations
-
Process-based: Good parallelization potential
- Independent file processing (no shared state)
- Can achieve near-linear speedup with P processes
- Improved complexity: O((N × M) / P)
Recommended for: N > 1000 files
-
TIFF Conversion (40-50%)
- Image decompression (JPG → RGB)
- Image compression (RGB → TIFF/LZW)
- Mitigation: Use faster compression or RAW TIFF
-
Disk I/O (30-40%)
- Reading JPG files
- Writing TIFF files
- Writing ZIP archives
- Mitigation: SSD storage, disk caching
-
Image Rotation (10-20%) - when needed
- Full pixel array transformation
- Mitigation: Process at reduced resolution for previews
-
ZIP Compression (5-10%)
- Deflate algorithm on TIFF + XML
- Mitigation: Lower compression level
-
Validation (<5%)
- Negligible impact
- Pre-flight checks: O(1) disk operations
- Post-processing: O(N) file listing
✅ Single-pass directory traversal ✅ Hash-based file lookups ✅ Sequential processing (memory-efficient) ✅ Early termination on errors ✅ Streaming ZIP writes ✅ Efficient XML parsing (ElementTree)
Impact: 4-8× speedup on modern CPUs
# Multiprocessing pool
from multiprocessing import Pool
with Pool(processes=8) as pool:
results = pool.map(process_single_item, file_pairs)Complexity: O((N × M) / P) where P = processes
Impact: Resume from checkpoint, avoid reprocessing
# Track processed files in database
if iid in processed_set:
continue # Skip already processedComplexity: Same O(N × M), but reduced N on reruns
Impact: Reduce I/O overhead
# Write multiple TIFFs to single ZIP
with ZipFile('batch.zip', 'w') as zf:
for item in batch:
zf.write(item)Complexity: Same, but reduced I/O operations
Impact: Faster validation on repeated runs
# Cache file metadata (sizes, hashes)
cache[file_path] = {
'size': size,
'mtime': mtime,
'hash': md5
}Complexity: O(1) lookup instead of O(M) reprocessing
- Time: O(N × M)
- Space: O(N + M)
- Pros: Simple, memory-efficient, reliable
- Cons: Slow for large batches
- Time: O((N × M) / P)
- Space: O(N + P×M) - P images in memory
- Pros: 4-8× faster
- Cons: More complex, higher memory usage
- Time: O(N × M) but with better latency
- Space: O(M) - constant memory
- Pros: Start seeing results immediately
- Cons: More complex error handling
At the moment The Cetamura Photo Processing System has O(N × M) time complexity, which is optimal for this type of batch image processing task. Every file must be read, processed, and written, making O(N × M) the theoretical minimum.
- Linear scalability in number of files (N)
- Linear scalability in image size (M)
- Dominated by I/O, not computation
- Memory-efficient design (O(N + M))
- Good optimization potential through parallelization
- Small batches (<100 files): ~5-10 minutes
- Medium batches (100-1000 files): ~30 minutes - 2 hours
- Large batches (>1000 files): Consider parallel processing
- Pre-flight checks: O(N) - negligible
- Post-processing validation: O(N) - negligible
- Total validation: <5% of processing time
Last Updated: October 7, 2025
Version: v2025.10.06