hyper-py-photometry 0.1.0__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.
Files changed (32) hide show
  1. hyper_py_photometry-0.1.0/LICENSE +13 -0
  2. hyper_py_photometry-0.1.0/PKG-INFO +514 -0
  3. hyper_py_photometry-0.1.0/README.md +495 -0
  4. hyper_py_photometry-0.1.0/pyproject.toml +36 -0
  5. hyper_py_photometry-0.1.0/setup.cfg +4 -0
  6. hyper_py_photometry-0.1.0/src/hyper_py/__init__.py +1 -0
  7. hyper_py_photometry-0.1.0/src/hyper_py/bkg_multigauss.py +524 -0
  8. hyper_py_photometry-0.1.0/src/hyper_py/bkg_single.py +477 -0
  9. hyper_py_photometry-0.1.0/src/hyper_py/config.py +43 -0
  10. hyper_py_photometry-0.1.0/src/hyper_py/create_background_slices.py +160 -0
  11. hyper_py_photometry-0.1.0/src/hyper_py/data_output.py +132 -0
  12. hyper_py_photometry-0.1.0/src/hyper_py/detection.py +142 -0
  13. hyper_py_photometry-0.1.0/src/hyper_py/extract_cubes.py +42 -0
  14. hyper_py_photometry-0.1.0/src/hyper_py/fitting.py +562 -0
  15. hyper_py_photometry-0.1.0/src/hyper_py/gaussfit.py +519 -0
  16. hyper_py_photometry-0.1.0/src/hyper_py/groups.py +66 -0
  17. hyper_py_photometry-0.1.0/src/hyper_py/hyper.py +150 -0
  18. hyper_py_photometry-0.1.0/src/hyper_py/logger.py +73 -0
  19. hyper_py_photometry-0.1.0/src/hyper_py/map_io.py +73 -0
  20. hyper_py_photometry-0.1.0/src/hyper_py/paths_io.py +122 -0
  21. hyper_py_photometry-0.1.0/src/hyper_py/photometry.py +114 -0
  22. hyper_py_photometry-0.1.0/src/hyper_py/run_hyper.py +45 -0
  23. hyper_py_photometry-0.1.0/src/hyper_py/single_map.py +716 -0
  24. hyper_py_photometry-0.1.0/src/hyper_py/survey.py +70 -0
  25. hyper_py_photometry-0.1.0/src/hyper_py/visualization.py +150 -0
  26. hyper_py_photometry-0.1.0/src/hyper_py_photometry.egg-info/PKG-INFO +514 -0
  27. hyper_py_photometry-0.1.0/src/hyper_py_photometry.egg-info/SOURCES.txt +30 -0
  28. hyper_py_photometry-0.1.0/src/hyper_py_photometry.egg-info/dependency_links.txt +1 -0
  29. hyper_py_photometry-0.1.0/src/hyper_py_photometry.egg-info/entry_points.txt +4 -0
  30. hyper_py_photometry-0.1.0/src/hyper_py_photometry.egg-info/requires.txt +8 -0
  31. hyper_py_photometry-0.1.0/src/hyper_py_photometry.egg-info/top_level.txt +1 -0
  32. hyper_py_photometry-0.1.0/test/test_hyper.py +175 -0
@@ -0,0 +1,13 @@
1
+ Copyright 2025 Traficante Alessio
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
@@ -0,0 +1,514 @@
1
+ Metadata-Version: 2.4
2
+ Name: hyper-py-photometry
3
+ Version: 0.1.0
4
+ Summary: HYPER: Hybrid Photometry Photometry and Extraction Routine
5
+ Author-email: Alessio Traficante <alessio.traficante@inaf.it>
6
+ Project-URL: Homepage, https://github.com/alessio-traficante/hyper-py
7
+ Requires-Python: >=3.11
8
+ Description-Content-Type: text/markdown
9
+ License-File: LICENSE
10
+ Requires-Dist: pyyaml
11
+ Requires-Dist: astropy
12
+ Requires-Dist: numpy
13
+ Requires-Dist: photutils
14
+ Requires-Dist: scipy
15
+ Requires-Dist: lmfit
16
+ Requires-Dist: matplotlib
17
+ Requires-Dist: scikit-learn<1.6,>=1.4
18
+ Dynamic: license-file
19
+
20
+ # 💫 `Hyper-py`: Hybrid Photometry Photometry and Extraction Routine in Python
21
+
22
+ **Authors:** Alessio Traficante; Fabrizio De Angelis; Alice Nucara; Milena Benedettini
23
+ **Original reference:** Traficante et al. (2015), *MNRAS, 451, 3089*
24
+
25
+ ---
26
+
27
+ ## Overview
28
+ `Hyper-py` is a flexible and modular Python-based pipeline for performing accurate source extraction and elliptical aperture photometry on astronomical maps. It is designed to reproduce and improve the performance of the original IDL-based HYPER algorithm introduced in Traficante et al. (2015).
29
+
30
+ The core objective of `Hyper-py` is to combine Gaussian fitting and polynomial background estimation to extract reliable fluxes for compact sources, especially in the presence of blending and spatially variable backgrounds.
31
+
32
+ ---
33
+
34
+ ## Philosophy
35
+ - Perform **aperture photometry** using source-dependent elliptical apertures derived from Gaussian fits
36
+ - Use a **polynomial background model**, estimated and optionally subtracted either jointly or separately from source fitting
37
+ - Handle both **isolated and blended sources**, using multi-Gaussian fitting for groups
38
+ - **Support 3D datacubes**: estimate polynomial backgrounds per spectral slice (with source masking) and optionally subtract them before fitting.
39
+ - Offer high configurability through a YAML-based configuration file
40
+ - Provide robust visual diagnostics and clean output formats (e.g. IPAC tables, DS9 region files)
41
+
42
+ ---
43
+
44
+ ## Workflow Summary
45
+ 1. **Input maps loading**
46
+ 2. **Source detection** with configurable filters and DAOStarFinder
47
+ 3. **Grouping** of nearby sources for joint fitting
48
+ 4. **Background estimation** (optional, fixed or fitted)
49
+ 5. **2D Gaussian fitting** with background polynomial (multi-source or isolated)
50
+ 6. **Aperture photometry** using elliptical regions derived from fit parameters
51
+ 7. **Output** generation: flux table, region files, diagnostics plots
52
+
53
+ ---
54
+
55
+ ## Parallel Processing
56
+
57
+ Hyper-py now supports **parallel execution** over multiple maps or datacube slices. If a list of FITS files is provided, Hyper-py will automatically:
58
+
59
+ - Launch one independent process per map (up to the number of available CPU cores)
60
+ - Run the full pipeline (detection, fitting, photometry) in parallel across different maps
61
+ - Maintain **individual log files** for each map
62
+ - Merge the final outputs (tables and diagnostics) into a single, combined summary
63
+
64
+ To enable parallelism, set the following parameters in your `config.yaml` file under the `control` section:
65
+
66
+ ```yaml
67
+ control:
68
+ parallel_maps: true # Enable parallel execution across maps
69
+ n_cores: 4 # Number of CPU cores to use
70
+ ```
71
+
72
+ If `parallel_maps` is set to `false`, the pipeline will run in serial mode.
73
+
74
+
75
+
76
+ ## 🚀 Prerequisites
77
+
78
+ Before using `Hyper-py`, make sure you have all the necessary Python dependencies installed. The following core libraries are required:
79
+ • astropy
80
+ • photutils
81
+ • matplotlib
82
+ • lmfit
83
+
84
+ This will install the necessary packages using `pip`:
85
+
86
+ ```bash
87
+ astropy photutils matplotlib lmfit
88
+ ```
89
+
90
+
91
+ ## 🛠️ Installation
92
+ You can install and use `Hyper-py` in two different ways, depending on your needs:
93
+
94
+ ### Option 1: Use the Source Code (for development or integration)
95
+
96
+ If you want to modify, extend, or integrate `Hyper-py` in your own projects:
97
+
98
+ 1. Clone the repository or download the source code.
99
+
100
+ ```bash
101
+ git clone https://github.com/Alessio-Traficante/hyper-py.git
102
+ ```
103
+
104
+ 2. Make sure the `src/` directory is in your `PYTHONPATH`.
105
+ ```bash
106
+ cd hyper_py
107
+ export PYTHONPATH=$(pwd)/src
108
+ ```
109
+ Or from within a Python script or interpreter:
110
+
111
+ ```python
112
+ import sys
113
+ sys.path.insert(0, "/absolute/path/to/hyper_py/src")
114
+ ```
115
+ ### Option 2: Install via `pip` (for direct usage)
116
+ 1. Build or download the .whl package (e.g., dist/hyper_py-X.X.X-py3-none-any.whl).
117
+ 2. Install the wheel file using `pip`:
118
+
119
+ ```bash
120
+ pip install hyper_py-X.X.X-py3-none-any.whl
121
+ ```
122
+ Use the current file version in dist folder.
123
+
124
+
125
+
126
+ ## 🎯 Usage
127
+
128
+ You can use `Hyper-py` either by importing and running it directly from Python, or via command line.
129
+ > [!IMPORTANT]
130
+ > `Hyper-py` needs a configuration file in order to run. If no configuration file path is provided, the default file located in the `src/` folder will be used.
131
+
132
+ ### 1. From Python
133
+
134
+ Import and run the `cli` function, passing the path to your YAML configuration file.
135
+
136
+ ```python
137
+ from hyper_py import run_hyper
138
+
139
+ run_hyper("path/to/config.yaml")
140
+ ```
141
+ This is the recommended approach if you want to integrate `Hyper-py` into a larger Python application or workflow.
142
+
143
+ ### 2. From Command Line Interface (CLI)
144
+
145
+ I) Using the source code:
146
+
147
+ You can execute the tool from the terminal:
148
+ ```bash
149
+ python -m hyper_py path/to/config.yaml
150
+ ```
151
+ This runs the main process using the configuration file specified.
152
+
153
+ II) If installed via pip:
154
+
155
+ Once the .whl package is installed (e.g., via pip install hyper_py-X.X.X-py3-none-any.whl), you can run it directly:
156
+ ```bash
157
+ hyper_py path/to/config.yaml
158
+ ```
159
+
160
+ ## Using the Source Code in Visual Studio Code
161
+ To run or debug the source code using Visual Studio Code:
162
+ ### 1. Open the project
163
+ - Open the project folder in VS Code.
164
+ - Make sure the Python extension is installed.
165
+ - Press Ctrl+Shift+P (or Cmd+Shift+P on macOS) and run Python: Select Interpreter.
166
+ - Choose the Hyper Conda environment (or another where the dependencies are installed).
167
+
168
+ ### 2. Run and debug the code
169
+
170
+ To debug:
171
+ - Open src/hyper_py/hyper.py or cli.py.
172
+ - Set breakpoints as needed.
173
+ - Press F5 or click the "Run and Debug" button in the sidebar.
174
+ - In the launch configuration, set the entry script to src/hyper_py/cli.py.
175
+
176
+ Optional: You can add this to `.vscode/launch.json` for convenience:
177
+
178
+
179
+ ```yaml
180
+ {
181
+ "version": "0.2.0",
182
+ "configurations": [
183
+ {
184
+ "name": "Python Debugger:Run Hyper",
185
+ "type": "debugpy",
186
+ "request": "launch",
187
+ "program": "${workspaceFolder}/src/hyper_py/cli.py",
188
+ "console": "integratedTerminal",
189
+ "args": ["path/to/config.yaml"], // Specify a different config file
190
+ }
191
+ ]
192
+ }
193
+ ```
194
+ ---
195
+ <br/><br/>
196
+
197
+
198
+ ## ⚙️ Configuration File Reference (`config.yaml`)
199
+
200
+ The `config.yaml` file controls all aspects of the Hyper-py pipeline. Below is a detailed explanation of every entry, including its purpose, accepted values, default, and type.
201
+
202
+ ### File Paths
203
+
204
+ | Entry | Description | Default | Type |
205
+ |----------------------|-----------------------------------------------------------------------------|-----------------|-----------|
206
+ | `paths.input.dir_maps` | Directory containing input map files. | `./maps` | REQUIRED |
207
+ | `paths.output.dir_root` | Root directory for output data. | `./output` | REQUIRED |
208
+ | `paths.output.dir_table_out`| Subdirectory of `dir_root` for photometry output tables. | `params` | REQUIRED |
209
+ | `paths.output.dir_region_out`| Subdirectory of `dir_root` for region files (output). | `regions` | REQUIRED |
210
+ | `paths.output.dir_log_out` | Subdirectory of `dir_root` for log files. | `logs` | REQUIRED |
211
+
212
+ ### File Names
213
+
214
+ | Entry | Description | Default | Type |
215
+ |----------------------|-----------------------------------------------------------------------------|-----------------|-----------|
216
+ | `files.file_map_name` | Input FITS map(s) list for analysis (in `dir_maps`). | `maps_list.txt` | REQUIRED |
217
+ | `files.file_table_base` | Base filename for photometry output tables (in `dir_table_out`). | `params` | REQUIRED |
218
+ | `files.file_region_base` | Base filename for output ellipse region files (in `dir_region_out`). | `region_files` | REQUIRED |
219
+ | `files.file_log_name` | Name of the global log file (in `dir_log_out`). | `hyper_py.log` | REQUIRED |
220
+
221
+ ### Pipeline Control
222
+
223
+ | Entry | Description | Default | Type |
224
+ |----------------------|-----------------------------------------------------------------------------|-----------------|-----------|
225
+ | `control.parallel_maps` | Enable parallel execution over multiple maps (`True`/`False`). | `True` | REQUIRED |
226
+ | `control.n_cores` | Number of CPU cores to use for multiprocessing. | `2` | REQUIRED |
227
+ | `control.detection_only` | Only perform source detection without photometry (`True`/`False`). | `False` | REQUIRED |
228
+ | `control.datacube` | Select if the input map is a datacube (`True`/`False`). | `False` | REQUIRED |
229
+ | `control.dir_datacube_slices`| Subdirectory of `dir_root` for datacube slice FITS files. | `maps` | OPTIONAL |
230
+
231
+ ### Units Conversion
232
+
233
+ | Entry | Description | Default | Type |
234
+ |----------------------|-----------------------------------------------------------------------------|-----------------|-----------|
235
+ | `units.convert_mJy` | Convert fluxes to mJy in the final output (`True`/`False`). | `False` (Jy) | REQUIRED |
236
+
237
+ ### Survey Settings
238
+
239
+ | Entry | Description | Default | Type |
240
+ |----------------------|-----------------------------------------------------------------------------|-----------------|-----------|
241
+ | `survey.survey_code` | Numeric identifier for survey parameters (e.g., beam size). | `15 (params from map header)` | REQUIRED |
242
+
243
+ ### Source Detection
244
+
245
+ | Entry | Description | Default | Type |
246
+ |----------------------|-----------------------------------------------------------------------------|-----------------|-----------|
247
+ | `detection.sigma_thres` | Detection threshold in units of RMS (sigma). | `4.0` | REQUIRED |
248
+ | `detection.use_manual_rms` | Use manually provided RMS noise value (`True`/`False`). | `False` | OPTIONAL |
249
+ | `detection.rms_value` | Manual RMS noise value (Jy), used if `use_manual_rms` is `True`. | `1.e-6` | OPTIONAL |
250
+ | `detection.roundlim` | Allowed source roundness range (min, max for DAOFIND). | `[-4.0, 4.0]` | ADVANCED |
251
+ | `detection.sharplim` | Allowed source sharpness range (min, max for DAOFIND). | `[-2.0, 2.0]` | ADVANCED |
252
+ | `detection.use_fixed_source_table`| Use external IPAC table for peak/aperture (`True`/`False`). | `False` | OPTIONAL |
253
+ | `detection.fixed_source_table_path` | Path to an external IPAC table with source information (in `dir_root`). The table must have **6 columns**:
254
+ - **ID**: Source identifier
255
+ - **xcen**: X coordinate (in map units, e.g. degrees or pixels)
256
+ - **ycen**: Y coordinate (in map units, e.g. degrees or pixels)
257
+ - **fwhm_1**: Major axis FWHM (arcsec)
258
+ - **fwhm_2**: Minor axis FWHM (arcsec)
259
+ - **PA**: Position angle (degrees, East of North)
260
+ The code will use only `xcen` and `ycen` if `detection.fixed_peaks = true`, only `fwhm_1`, `fwhm_2`, and `PA` if `photometry.fixed_radius = true`, or both sets of parameters if both options are enabled. | `source_table.txt` | OPTIONAL |
261
+ | `detection.fixed_peaks` | Use fixed peaks instead of automatic (`True`/`False`). | `False` | OPTIONAL |
262
+ | `detection.xcen_fix` | Fixed peak X coordinates (deg; used if `fixed_peaks` is `True`). | `[1.0, 1.0]` | OPTIONAL |
263
+ | `detection.ycen_fix` | Fixed peak Y coordinates (deg; used if `fixed_peaks` is `True`). | `[1.0, 1.0]` | OPTIONAL |
264
+
265
+ ### Photometry Settings
266
+
267
+ | Entry | Description | Default | Type |
268
+ |----------------------|-----------------------------------------------------------------------------|-----------------|-----------|
269
+ | `photometry.aper_inf` | Minimum size factor for Gaussian FWHM (used as minimum radius for aperture photometry). This value multiplies the average beam FWHM to set the minimum allowed aperture size. | `1.0` | OPTIONAL |
270
+ | `photometry.aper_sup` | Maximum size factor for Gaussian FWHM (used as maximum radius for aperture photometry). This value multiplies the average beam FWHM to set the maximum allowed aperture size for photometry. | `2.0` | OPTIONAL |
271
+ | `photometry.fixed_radius` | Use fixed aperture radii (`True`/`False`). | `False` | OPTIONAL |
272
+ | `photometry.fwhm_1` | Fixed FWHM aperture radius major axis (arcsec; if `fixed_radius` is `True`). | `[0.0]` | OPTIONAL |
273
+ | `photometry.fwhm_2` | Fixed FWHM aperture radius minor axis (arcsec; if `fixed_radius` is `True`). | `[0.0]` | OPTIONAL |
274
+ | `photometry.PA_val` | Fixed aperture position angle (deg; if `fixed_radius` is `True`). | `[0.0]` | OPTIONAL |
275
+
276
+ ### Model Fit Settings
277
+
278
+ | Entry | Description | Default | Type |
279
+ |----------------------|-----------------------------------------------------------------------------|-----------------|-----------|
280
+ | `fit_options.fit_method` | Optimization algorithm for Gaussian fitting. | `"least_squares"`| ADVANCED |
281
+ | `fit_options.loss` | Specifies the loss function used during Gaussian fitting optimization.
282
+ - `"linear"`: Standard least-squares loss (minimizes squared residuals; most common for well-behaved data).
283
+ - `"soft_l1"`: Soft L1 loss, less sensitive to outliers than linear; combines properties of L1 and L2 norms.
284
+ - `"huber"`: Huber loss, robust to outliers; behaves like linear for small residuals and like L1 for large residuals.
285
+ - `"cauchy"`: Cauchy loss, strongly suppresses the influence of outliers.
286
+ Choose a robust loss (e.g., `"huber"` or `"cauchy"`) if your data contains significant outliers or non-Gaussian noise. | `"linear"` | ADVANCED |
287
+ | `fit_options.f_scale` | Relevant for `soft_l1`, `huber`, `cauchy` loss functions. | `0.1` | ADVANCED |
288
+ | `fit_options.max_nfev` | Maximum number of function evaluations. | `50000` | ADVANCED |
289
+ | `fit_options.xtol` | Tolerance on parameter change for convergence. | `1e-8` | ADVANCED |
290
+ | `fit_options.ftol` | Tolerance on cost function change for convergence. | `1e-8` | ADVANCED |
291
+ | `fit_options.gtol` | Tolerance on gradient orthogonality. | `1e-8` | ADVANCED |
292
+ | `fit_options.weights` | Specifies the weighting scheme used during Gaussian fitting.
293
+ - `"null"`: No weighting; all pixels are treated equally.
294
+ - `"inverse_rms"`: Weights are set as the inverse of the RMS noise, giving less weight to noisier pixels.
295
+ - `"snr"`: Weights are proportional to the signal-to-noise ratio (SNR) of each pixel.
296
+ - `"power_snr"`: Weights are proportional to the SNR raised to a user-defined power (`fit_options.power_snr`).
297
+ - `"map"`: Weights are set equal to the user-provided input map.
298
+ - `"mask"`: Weights are set to zero for masked pixels and one elsewhere, effectively ignoring masked regions.
299
+ Choose the scheme that best matches your data quality and analysis goals. | `"snr"` | OPTIONAL |
300
+ | `fit_options.power_snr` | SNR exponent for weighting (if `weights` is `"power_snr"`). | `5` | OPTIONAL |
301
+ | `fit_options.calc_covar` | Estimate parameter covariance matrix (`True`/`False`). | `False` | ADVANCED |
302
+ | `fit_options.min_method` | Criterion used to select the best fit among multiple solutions:
303
+ - `"nmse"`: Normalized Mean Squared Error; selects the fit with the lowest mean squared residuals normalized by the data variance.
304
+ - `"redchi"`: Reduced Chi-Squared; selects the fit with the lowest reduced chi-squared statistic, accounting for the number of degrees of freedom.
305
+ - `"bic"`: Bayesian Information Criterion; selects the fit with the lowest BIC value, which penalizes model complexity to avoid overfitting.
306
+ Choose the method that best matches your scientific goals and data characteristics. | `"nmse"` | ADVANCED |
307
+ | `fit_options.verbose` | Print full fit report (`True`/`False`). | `False` | ADVANCED |
308
+ | `fit_options.use_l2_regularization`| Enable L2 regularization on background terms (`True`/`False`). | `True` | ADVANCED |
309
+ | `fit_options.lambda_l2` | Regularization strength. | `1e-4` | ADVANCED |
310
+ | `fit_options.vary` | Allow source peak to vary during Gaussian fit (`True`/`False`). | `False` | ADVANCED |
311
+ | `fit_options.bg_fitters` | Background fitting methods to try (`least_squares`, `huber`, `theilsen`). | `['least_squares']`| ADVANCED |
312
+ | `fit_options.huber_epsilons` | List of epsilon values for HuberRegressor. | `[1.1, 1.35, 1.7, 2.0]`| ADVANCED |
313
+
314
+ ### Background Estimation
315
+
316
+ | Entry | Description | Default | Type |
317
+ |----------------------|-----------------------------------------------------------------------------|-----------------|-----------|
318
+ | `background.fit_gauss_and_bg_separately`| Estimate Gaussian and background separately (`True`/`False`). | `True` | OPTIONAL |
319
+ | `background.pol_orders_separate` | Polynomial orders for separated background subtraction. | `[0, 1, 2]` | OPTIONAL |
320
+ | `background.fix_min_box` | Minimum box size for variable-size background fitting, expressed as a multiple of the source FWHM (half-size increment). **If set to `0`, the background is estimated over the entire map.** | `3` | OPTIONAL |
321
+ | `background.fix_max_box` | Maximum box size (multiple of FWHMs) for background fitting. | `5` | OPTIONAL |
322
+ | `background.fit_gauss_and_bg_together` | If `True`, the code fits Gaussian source components and the polynomial background **simultaneously** in a single optimization step. If `False`, background subtraction and Gaussian fitting are performed separately. Use `True` for joint modeling when the background and sources are strongly coupled. | `False` | REQUIRED |
323
+ | `background.polynomial_orders` | Polynomial background orders for main fitting. | `[0]` | OPTIONAL |
324
+
325
+ ### Fits Output Options
326
+
327
+ | Entry | Description | Default | Type |
328
+ |----------------------|-----------------------------------------------------------------------------|-----------------|-----------|
329
+ | `fits_output.fits_fitting` | Save best fit model group FITS files (`True`/`False`). | `False` | OPTIONAL |
330
+ | `fits_output.fits_deblended` | Save deblended per-source FITS files (`True`/`False`). | `False` | OPTIONAL |
331
+ | `fits_output.fits_bg_separate` | Save best fit background separated model group FITS files (`True`/`False`).| `False` | OPTIONAL |
332
+ | `fits_output.fits_output_dir_fitting`| Subdirectory of `dir_root` for fitting FITS files. | `fits/fitting` | OPTIONAL |
333
+ | `fits_output.fits_output_dir_deblended`| Subdirectory of `dir_root` for deblended FITS files. | `fits/deblended`| OPTIONAL |
334
+ | `fits_output.fits_output_dir_bg_separate`| Subdirectory of `dir_root` for background FITS files. | `fits/bg_separate`| OPTIONAL |
335
+
336
+ ### Visualization Options
337
+
338
+ | Entry | Description | Default | Type |
339
+ |----------------------|-----------------------------------------------------------------------------|-----------------|-----------|
340
+ | `visualization.visualize_fitting` | Visualize final Gaussian+background fit (`True`/`False`). | `False` | OPTIONAL |
341
+ | `visualization.visualize_deblended` | Visualize per-source blended maps (`True`/`False`). | `False` | OPTIONAL |
342
+ | `visualization.visualize_bg_separate` | Visualize background model from masked fit (`True`/`False`). | `False` | OPTIONAL |
343
+ | `visualization.output_dir_fitting` | Subdirectory of `dir_root` for fitting plots. | `plots/fitting` | OPTIONAL |
344
+ | `visualization.output_dir_deblended` | Subdirectory of `dir_root` for deblended plots. | `plots/deblended`| OPTIONAL |
345
+ | `visualization.output_dir_bg_separate` | Subdirectory of `dir_root` for background plots. | `plots/bg_separate`| OPTIONAL |
346
+
347
+ ---
348
+
349
+ **Tip:**
350
+ All entries can be customized in your `config.yaml`. If an entry is omitted, the default value will be used.
351
+
352
+
353
+
354
+ ## 📦 Code Modules
355
+
356
+ | File | Description |
357
+ |-------------------------------|-------------|
358
+ | `cli.py` | Main launcher for multi-map analysis (parallel or serial)
359
+ | `hyper.py` | Core logic for initializing the code run
360
+ | `single_map.py` | Core logic for running detection + photometry on one map
361
+ | `config.py` | YAML parser with access interface
362
+ | `logger.py` | Custom logger supporting log file + screen separation
363
+ | `paths_io.py` | Handles file path construction for input/output files
364
+ | `map_io.py` | FITS input and pre-processing (unit conversion)
365
+ | `survey.py` | Retrieves beam info and reference units
366
+ | `detection.py` | Source detection using high-pass filtering and DAOStarFinder
367
+ | `groups.py` | Identifies source groups (blends vs. isolated)
368
+ | `bkg_single.py` | Estimates and fits the background for single sources in maps or cubes
369
+ | `bck_multigauss.py` | Estimates and fits the background for groups of sources using multi-Gaussian models
370
+ | `gaussfit.py` | Fitting routine for isolated Gaussian sources
371
+ | `fitting.py` | Multi-Gaussian + background fitting engine
372
+ | `photometry.py` | Elliptical aperture photometry
373
+ | `data_output.py` | Output table formatting and writing (IPAC, CSV)
374
+ | `visualization.py` | 2D/3D visual diagnostics of Gaussian/background fits
375
+ | `extract_cubes.py` | Extracts 2D slices from 3D datacubes and saves them as FITS files.
376
+ | `create_background_slices.py` | Creates and saves background slices from 3D datacubes for further analysis.
377
+
378
+ ---
379
+
380
+
381
+ ## 🗺️ Minimal FITS Header Requirements
382
+
383
+ To ensure compatibility with Hyper-py, each input FITS file (2D map or 3D datacube) must include a minimal set of header keywords describing the coordinate system, pixel scale, units, and beam properties.
384
+
385
+ ### Minimal Header for 2D Maps
386
+
387
+ | Keyword | Description / Example Value | Options / Notes |
388
+ |-----------|-------------------------------------------|--------------------------------------------------|
389
+ | SIMPLE | FITS standard compliance | `T` (required) |
390
+ | BITPIX | Data type | `-64` (float64), `-32` (float32) |
391
+ | NAXIS | Number of dimensions | `2` |
392
+ | NAXIS1 | X axis length | Integer |
393
+ | NAXIS2 | Y axis length | Integer |
394
+ | CRPIX1 | Reference pixel X | Float |
395
+ | CRPIX2 | Reference pixel Y | Float |
396
+ | CDELT1 | Pixel scale X | Degrees/pixel (can also be `'CD1_1'`) |
397
+ | CDELT2 | Pixel scale Y | Degrees/pixel (can also be `'CD2_1'`) |
398
+ | CRVAL1 | Reference value X | RA (deg) |
399
+ | CRVAL2 | Reference value Y | Dec (deg) |
400
+ | CTYPE1 | Coordinate type X | `'RA---SIN'`, `'RA---TAN'`, `'GLON--CAR'`, etc. |
401
+ | CTYPE2 | Coordinate type Y | `'DEC--SIN'`, `'DEC--TAN'`, `'GLAT--CAR'`, etc. |
402
+ | CUNIT1 | Unit for X | `'deg'`, `'arcsec'` |
403
+ | CUNIT2 | Unit for Y | `'deg'`, `'arcsec'` |
404
+ | BUNIT | Data unit | `'Jy'`, `'Jy/beam'`, `'beam-1 Jy'`, `'MJy/sr'` |
405
+ | BMAJ | Beam major axis (deg) | Float |
406
+ | BMIN | Beam minor axis (deg) | Float |
407
+ | BPA | Beam position angle (deg) | Float |
408
+ | OBJECT | Map description | String |
409
+
410
+ ### Minimal Header for 3D Datacubes
411
+
412
+ | Keyword | Description / Example Value | Options / Notes |
413
+ |-----------|-------------------------------------------|--------------------------------------------------|
414
+ | SIMPLE | FITS standard compliance | `T` (required) |
415
+ | BITPIX | Data type | `-32` (float32), `-64` (float64) |
416
+ | NAXIS | Number of dimensions | `3` |
417
+ | NAXIS1 | X axis length | Integer |
418
+ | NAXIS2 | Y axis length | Integer |
419
+ | NAXIS3 | Number of slices | Integer |
420
+ | CRPIX1 | Reference pixel X | Float |
421
+ | CRPIX2 | Reference pixel Y | Float |
422
+ | CRPIX3 | Reference pixel Z (slice) | Float |
423
+ | CDELT1 | Pixel scale X | Degrees/pixel (can also be `'CD1_1'`) |
424
+ | CDELT2 | Pixel scale Y | Degrees/pixel (can also be `'CD2_1'`) |
425
+ | CDELT3 | Channel width | Velocity or frequency units |
426
+ | CRVAL1 | Reference value X | RA (deg) |
427
+ | CRVAL2 | Reference value Y | Dec (deg) |
428
+ | CRVAL3 | Reference value Z (slice) | Velocity/frequency (e.g. `0.0`) |
429
+ | CTYPE1 | Coordinate type X | `'RA---SIN'`, `'RA---TAN'`, `'GLON--CAR'`, etc. |
430
+ | CTYPE2 | Coordinate type Y | `'DEC--SIN'`, `'DEC--TAN'`, `'GLAT--CAR'`, etc. |
431
+ | CTYPE3 | Coordinate type Z | `'VRAD'`, `'VELO-LSR'`, `'FREQ'` |
432
+ | CUNIT1 | Unit for X | `'deg'`, `'arcsec'` |
433
+ | CUNIT2 | Unit for Y | `'deg'`, `'arcsec'` |
434
+ | CUNIT3 | Unit for Z | `'km s-1'`, `'Hz'` |
435
+ | WCSAXES | Number of WCS axes | `3` |
436
+ | BUNIT | Data unit | `'Jy'`, `'Jy/beam'`, `'beam-1 Jy'`, `'MJy/sr'` |
437
+ | BMAJ | Beam major axis (deg) | Float |
438
+ | BMIN | Beam minor axis (deg) | Float |
439
+ | BPA | Beam position angle (deg) | Float |
440
+ | OBJECT | Cube description | String |
441
+
442
+ ### Notes & Options
443
+
444
+ - **Coordinate Systems:**
445
+ - Common values for `CTYPE1`/`CTYPE2` are `'RA---SIN'`, `'RA---TAN'`, `'DEC--SIN'`, `'DEC--TAN'`, `'GLON--CAR'`, `'GLAT--CAR'`.
446
+ - For cubes, `CTYPE3` can be `'VRAD'` (velocity), `'VELO-LSR'`, or `'FREQ'` (frequency).
447
+ - **Units:**
448
+ - `CUNIT1`/`CUNIT2`: `'deg'` (degrees), `'arcsec'` (arcseconds)
449
+ - `CUNIT3`: `'km s-1'` (velocity), `'Hz'` (frequency)
450
+ - `BUNIT`: `'Jy'`, `'Jy/beam'`, `'beam-1 Jy'`, `'MJy/sr'` (must match your science case)
451
+ - **Beam Parameters:**
452
+ - `BMAJ`, `BMIN`: Beam size in degrees (convert from arcsec if needed: 1 arcsec = 1/3600 deg)
453
+ - `BPA`: Beam position angle in degrees
454
+ - **Other:**
455
+ - Additional header keywords may be present, but the above are required for Hyper-py to interpret the map/cube correctly.
456
+
457
+ ---
458
+
459
+ **Example: Minimal 2D Map Header**
460
+ ```
461
+ SIMPLE = T
462
+ BITPIX = -64
463
+ NAXIS = 2
464
+ NAXIS1 = 400
465
+ NAXIS2 = 400
466
+ CRPIX1 = 200.0
467
+ CRPIX2 = 200.0
468
+ CDELT1 = -3.000000000000E-03
469
+ CDELT2 = 3.000000000000E-03
470
+ CRVAL1 = 260.0
471
+ CRVAL2 = 15.0
472
+ CTYPE1 = 'RA---SIN'
473
+ CTYPE2 = 'DEC--SIN'
474
+ CUNIT1 = 'deg '
475
+ CUNIT2 = 'deg '
476
+ BUNIT = 'Jy '
477
+ BMAJ = 1.5E-05
478
+ BMIN = 1.5E-05
479
+ BPA = 0.0
480
+ OBJECT = '2D map for Hyper-py test'
481
+ END
482
+ ```
483
+
484
+ **Example: Minimal Datacube Header**
485
+ ```
486
+ SIMPLE = T
487
+ BITPIX = -32
488
+ NAXIS = 3
489
+ NAXIS1 = 400
490
+ NAXIS2 = 400
491
+ NAXIS3 = 4
492
+ CRPIX1 = 200.0
493
+ CRPIX2 = 200.0
494
+ CRPIX3 = 1
495
+ CDELT1 = -2.500000000000E-03
496
+ CDELT2 = 2.500000000000E-03
497
+ CDELT3 = 0.5
498
+ CRVAL1 = 260.0
499
+ CRVAL2 = 15.0
500
+ CRVAL3 = 0.0
501
+ CTYPE1 = 'RA---SIN'
502
+ CTYPE2 = 'DEC--SIN'
503
+ CTYPE3 = 'VRAD '
504
+ CUNIT1 = 'deg '
505
+ CUNIT2 = 'deg '
506
+ CUNIT3 = 'km s-1 '
507
+ WCSAXES = 3
508
+ BUNIT = 'beam-1 Jy'
509
+ BMAJ = 0.00015
510
+ BMIN = 0.00015
511
+ BPA = 0.0
512
+ OBJECT = 'Datacube for Hyper-py test'
513
+ END
514
+ ```