synth_starfield — ASTROSTACK synth op

• Data kinds: कोई नहीं → image2d (केवल arguments से तय होने वाला op — यह कोई image या data input नहीं लेता)

• Call: import fullseye as fs; fs.ledger.synth_starfield(shape=(128, 128), n_stars=30, flux_min=400.0, flux_max=9000.0, fwhm_px=3.2, psf='gaussian', moffat_beta=2.5, sky=60.0, read_sigma=6.0, shift_row=0.0, shift_col=0.0, n_cosmic=0, cosmic_flux=4000.0, margin_px=6.0, seed=0, field_seed=None, noise=True) (implementation को सीधे call करना हो तो import astrostack; astrostack.synth_starfield(shape=(128, 128), n_stars=30, flux_min=400.0, flux_max=9000.0, fwhm_px=3.2, psf='gaussian', moffat_beta=2.5, sky=60.0, read_sigma=6.0, shift_row=0.0, shift_col=0.0, n_cosmic=0, cosmic_flux=4000.0, margin_px=6.0, seed=0, field_seed=None, noise=True), registry से लेना हो तो opsastrostack.get("synth_starfield"))

• Ledger के ज़रिए return value: fullseye.ledger.synth_starfield(...) केवल घोषित out type image2d का value लौटाता है (मूल function सहायक जानकारी भी लौटाता है)। जो हिस्सा छोड़ दिया गया है उसकी ज़रूरत हो तो fullseye.ledger.synth_starfield.raw(...) का उपयोग करें, या astrostack.synth_starfield को सीधे call करें।

• मूल function का return: (frame, truth) -> image2d

उपयोग

1 ज्ञात star field synthesize करता है — इस family के ground truth का स्रोत।

हर तारा अपना कुल flux (electrons) flux_min–flux_max पर log-uniform distribution से लेता है और image की सीमा से कम से कम margin_px अंदर uniform रूप से रखा जाता है। जब *psf* "gaussian" होता है, तो यह scipy.special.erf के ज़रिए हर pixel पर exact integral होता है, इसलिए 1 तारे का योग दिए गए flux से ठीक मेल खाता है (image के बाहर पड़ने वाले भाग को छोड़कर)। "moffat" Moffat, *A Theoretical Investigation of Focal Stellar Images*, A&A 3, 455 (1969) का (1 + (r/alpha)^2)^(-beta) है, ज़मीन पर स्थित वायुमंडल से प्रभावित तारों की images का standard model (इसका diffraction-limited सहोदर optics.airy_pattern है)।

noise केवल 1 सिद्धांत का पालन करता है —— Poisson(star + sky) (photons_per_unit=1.0 के साथ photoncount.photon_sample को call करके), उसके बाद cosmic rays जोड़ी जाती हैं, और अंत में additive Gaussian read noise read_sigma। यह क्रम physics का पालन करता है:

cosmic rays photons नहीं हैं (वे Poisson sampling से नहीं गुज़रतीं)। cosmic rays की स्थितियाँ defectgen.defect_pits की uniform point process पर छोड़ी गई हैं —— "random स्थितियों पर दुर्लभ, छोटे, तीखे जमाव" की stochastic geometry pitting corrosion जैसी ही है, इसलिए दूसरा model लिखने का कोई कारण नहीं है।

*shift_row* / *shift_col* पूरे star field को subpixel मात्रा से खिसकाते हैं (dithering)। synthesize किए गए ground-truth coordinates भी उतने ही खिसकते हैं, इसलिए इसका उपयोग registration और drizzle की cross-check के लिए किया जा सकता है।

(frame, truth) लौटाता है:

• frame —— (H, W) float64, electrons की इकाई में।

• truth —— dict। rows / cols (N,) सही तारा केंद्र हैं (convention: integer coordinates pixel केंद्र हैं), fluxes (N,) सही कुल flux, fwhm_px / sigma_px / alpha_px / beta PSF, sky / read_sigma noise, cosmic_mask (H, W) bool cosmic-ray pixels, noiseless (H, W) noise जोड़ने से पहले की अपेक्षा (expectation) (cross-checks के लिए)।

2 seeds हैं। field_seed star field (coordinates और fluxes) तय करता है, seed वह विशेष observation (shot noise, read noise, cosmic-ray positions) तय करता है। field_seed=None होने पर यह seed के समान मान लेता है। इन्हें अलग करने का कारण माप से मिली एक दुर्घटना है: पहले version में, जिसमें 1 seed था, synth_frame_series हर frame के लिए seed बदलता था, जिसका परिणाम यह हुआ कि हर frame में star field ही अलग था, registration को केवल 1 correspondence मिला (frame_align ने सही ढंग से fail closed किया), और cross-frame cosmic-ray removal ने "हर pixel एक outlier है" लौटाया। उसी आकाश को दोबारा image करना और अलग आकाश को image करना 1 argument से उलझ सकता है —— इसलिए उन्हें type से नहीं, नाम से अलग किया गया है। दोनों random generators numpy.random.default_rng हैं, इसलिए seeds की समान जोड़ी किसी भी machine पर समान frame देती है।

यह जो ground truth दोहराता है (tests/test_astrostack.py में पक्का किया गया):

noise=False, sky=0, fwhm_px=3.0 (64x64, flux 5000 e-) वाले 1-तारे के frame के लिए, पूरी image पर योग और दिए गए flux के बीच relative error 1.8e-16 है —— 1 float64 rounding जितना: "लगभग संरक्षित" नहीं बल्कि संरक्षित। त्रिज्या (radius) r के circular aperture द्वारा एकत्र अंश 1 - exp(-r^2/(2 sigma^2)) है:

r = 2 sigma के लिए 0.8647, r = 3 sigma के लिए 0.98889।

Raises ValueError: *shape* बहुत छोटा / *n_stars* non-negative integer नहीं / flux_min > flux_max / *psf* PSF_MODELS में नहीं / moffat_beta <= 1 (integral diverge होता है) / margin_px image से बड़ा / *seed* non-negative integer नहीं।

संदर्भ (sample data, साहित्य)

• Sample data catalog (DL URL / license) — 2-D के लिए skimage.data (BSD/public) + synthetic, 3-D के लिए real data sources (Stanford/PDS आदि) के DL URL।

• Operators का स्रोत और संदर्भ — इस op family के मूल research/methods के स्रोत।

• Algorithm का मानक स्रोत (लेखक, वर्ष) और उपयोग ऊपर की family usage guide में दिए गए हैं।

चलाए जा सकने वाले उदाहरण (verified samples जो सच में यह op call करते हैं)

• astro_stacking — py -3.11 examples/astro_stacking.py

• poc_astro_photometry — py -3.11 examples/poc_astro_photometry.py

वे अगले ops जिनसे type जुड़ता है (image2d को input के रूप में लेते हैं)

frame_quality · noise_sigma · cosmic_ray_reject · star_detect · psf_fit · aperture_photometry · frame_align

इसी category के (synth)

synth_frame_series


*Provenance: astrostack.py — ASTROSTACK operator registry. यह per-op note tools/opdocs.py md से अपने-आप generate होता है (हाथ से edit न करें)।*

© 2026 Kazufumi Furuse — Fullseye operator documentation. Licensed under Apache-2.0.