map2fig 0.7.6

Fast, publication-quality HEALPix sky map visualization in Rust
Documentation
#!/usr/bin/env python3
"""Analyze FITS I/O and downsampling characteristics."""

import subprocess
import json
import re
from pathlib import Path

# Test file info
test_file = "tests/data/combined_map_95GHz_nside8192_ptsrcmasked_50mJy.fits"
file_path = Path(test_file)

print("=" * 80)
print("FITS I/O AND DOWNSAMPLING ANALYSIS")
print("=" * 80)

# File size
file_size_bytes = file_path.stat().st_size
file_size_gb = file_size_bytes / (1024**3)
print(f"\nπŸ“ Test File: {test_file}")
print(f"   Size: {file_size_gb:.2f} GB ({file_size_bytes:,} bytes)")

# Extract NSIDE from fits header
import subprocess
result = subprocess.run(
    ["file", test_file],
    capture_output=True,
    text=True
)
print(f"   File type: {result.stdout.strip()}")

# Calculate HEALPix metrics
nside = 8192
npix = 12 * nside * nside
npix_millions = npix / 1e6
pixels_gb = (npix * 4) / (1024**3)  # f32 = 4 bytes

print(f"\nπŸ—ΊοΈ  HEALPix Metrics (nside={nside}):")
print(f"   Total pixels: {npix:,} ({npix_millions:.1f}M)")
print(f"   Memory @ f32: {pixels_gb:.2f} GB")
print(f"   Memory @ f64: {pixels_gb*2:.2f} GB")

# Downsampling factors at different output widths
print(f"\nπŸ“Š Downsampling Analysis (different output widths):")
print(f"   {'Width':<10} {'Height':<10} {'Target NSIDE':<14} {'Downsample':<12} {'Output Pixels':<15} {'Reduction':<12}")
print(f"   {'-'*10} {'-'*10} {'-'*14} {'-'*12} {'-'*15} {'-'*12}")

for width in [600, 800, 1200, 1600, 2400]:
    height = width // 2  # Mollweide aspect ratio
    pixels = width * height
    
    import math
    # target_nside = power of 2 closest to sqrt(pixels)
    target_res = math.sqrt(pixels)
    target_nside = 1
    while target_nside * 2 <= target_res:
        target_nside *= 2
    
    downsample_factor = nside // target_nside
    output_npix = 12 * target_nside * target_nside
    reduction = 100.0 * (1 - output_npix / npix)
    
    print(f"   {width:<10} {height:<10} {target_nside:<14} {downsample_factor}x{'':<8} {output_npix:,}{'':<9} {reduction:.1f}%")

# I/O bandwidth estimate
print(f"\n⚑ I/O Bandwidth Analysis:")
print(f"   Current L3β†’Memory bandwidth: ~9.1 GB/s (observed)")
print(f"   Full FITS file I/O: {file_size_gb:.2f} GB Γ· 9.1 GB/s = {file_size_gb/9.1:.2f}s minimum")
print(f"   Actual observed: 1.32s (includes overhead, caching, memmap)")
print(f"   Efficiency: {(file_size_gb/9.1)/1.32*100:.1f}% of theoretical max")

print(f"\nπŸ’‘ Key Insights:")
print(f"   1. Current bottleneck: Reading ALL {npix_millions:.1f}M pixels from {file_size_gb:.2f} GB file")
print(f"   2. Downsampling: {nside//512}x reduction (8192β†’512 for 1200px output)")
print(f"   3. 99.75% of loaded data is discarded during downsampling")
print(f"   4. Total I/O bottleneck: {file_size_gb:.2f} GB (FITS) + processing overhead")

print(f"\nπŸ” Opportunities:")
print(f"   A. Selective reading: Can't do per-HEALPix-pixel, but could compress harder")
print(f"   B. Downgrade-during-read: FAILED before (25% slower due to coord conversion cost)")
print(f"   C. Better caching: Memmap is already optimal for sequential reads")
print(f"   D. Column-specific optimization: Already using direct f32 binary read")
print(f"   E. Task: Analyze actual I/O patterns and cache efficiency")

print("\n" + "="*80)