# stellarphot — Package Overview This page maps every module in the `stellarphot` package and the import relationships between them. The package has no command-line scripts; users interact with it through Jupyter notebooks (launched via `jupyter-app-launcher`), through ipywidgets-based GUI tools, or by importing the library directly. The modules group into these logical components: | Component | Modules | Role | |---|---|---| | **Core data layer** | `core.py`, `catalogs.py`, `table_representations.py` | Validated astropy `QTable` subclasses (`PhotometryData`, `CatalogData`, `SourceListData`) in `core.py`; catalog-fetcher functions (`apass_dr9`, `vsx_vizier`, `refcat2`) in `catalogs.py`; YAML (de)serialization of settings stored in table metadata | | **Settings & configuration** | `settings/` | Pydantic models for all configuration and saved-settings file management — pure Pydantic, no GUI imports | | **Photometry engine** | `photometry/` | Source detection, FWHM measurement, aperture photometry pipeline | | **Differential photometry** | `differential_photometry/` | Relative flux (AIJ-style) and variable-star magnitude calculations | | **Transit fitting** | `transit_fitting/` | Exoplanet transit modeling (batman), TIC/MAST queries (the EXOTIC helper GUI moved to `gui/`) | | **Input/output** | `io/` | AstroImageJ, AAVSO extended format, TESS/TFOP files | | **GUI layer** | `gui/` | All notebook/widget UI, consolidated here so the rest of the package stays headless: the settings-form generator (`views.py`), settings widgets (`custom_widgets.py`), file chooser (`fits_opener.py`), seeing-profile/comparison-star widgets, and the EXOTIC helper. Requires the optional `[gui]` extra | | **Plotting** | `plotting/` | Seeing, transit, and multi-night light-curve plots | | **Utilities** | `utils/` | Magnitude calibration/transforms, comparison-star helpers, version migration | | **Notebooks** | `notebooks/` | Shipped workflow notebooks (the user-facing entry points) | **Legend** — the node types used on this page: ```mermaid flowchart LR classDef data fill:#e1f5fe,stroke:#0277bd,color:#212121 classDef engine fill:#e8f5e9,stroke:#2e7d32,color:#212121 classDef ui fill:#fff3e0,stroke:#ef6c00,color:#212121 classDef output fill:#f3e5f5,stroke:#7b1fa2,color:#212121 classDef nbstyle fill:#fff8e1,stroke:#f9a825,color:#212121 classDef external fill:#eceff1,stroke:#90a4ae,stroke-dasharray: 5 5,color:#212121 l_data["Core data layer"]:::data l_engine["Processing engine"]:::engine l_ui["UI layer"]:::ui l_output["Output
(io, plotting)"]:::output l_nb["Launcher notebook"]:::nbstyle l_ext["Outside the
cluster shown"]:::external l_data ~~~ l_engine ~~~ l_ui ~~~ l_output ~~~ l_nb ~~~ l_ext ``` - **Solid arrows** — an import, pointing from the importing module to the one it imports. - **Dashed arrows** — notebooks driving a UI layer, or other looser links. - Files are grouped into labeled **subgraphs** by subpackage in the cluster diagrams. ## Subpackage dependency map Arrows point from the importing module to the module it imports. The notebooks drive the GUI layers (dashed arrows) and, through them, the rest of the package. *Arrows: **solid** = an import (importer → imported); **dashed** = a notebook driving a UI layer, or a looser link.* ```mermaid flowchart LR classDef data fill:#e1f5fe,stroke:#0277bd,color:#212121 classDef engine fill:#e8f5e9,stroke:#2e7d32,color:#212121 classDef ui fill:#fff3e0,stroke:#ef6c00,color:#212121 classDef output fill:#f3e5f5,stroke:#7b1fa2,color:#212121 nb["notebooks/
(10 launcher notebooks)"]:::ui gui["gui/"]:::ui sett["settings/"]:::ui phot["photometry/"]:::engine diff["differential_photometry/"]:::engine tfit["transit_fitting/"]:::engine uts["utils/"]:::engine plt["plotting/"]:::output iop["io/"]:::output corem["core.py"]:::data catm["catalogs.py"]:::data trep["table_representations.py"]:::data nb -.->|"drives"| gui nb -.->|"drives"| sett gui --> sett gui --> phot gui --> plt gui --> iop gui --> uts gui --> corem gui -->|"transit_fitting_gui uses get_tic_info"| tfit phot --> corem phot --> sett diff --> corem uts --> corem uts -->|"apass_dr9, vsx_vizier, refcat2"| catm uts --> sett plt --> sett iop -.->|"core (lazy, io.tess)"| corem iop --> sett iop -->|"get_tic_info"| tfit corem -->|"io.aavso"| iop corem --> sett corem --> trep catm -->|"CatalogData"| corem catm -->|"PassbandMap"| sett trep --> sett click nb href "../stellarphot/notebooks/" "notebooks/" click gui href "../stellarphot/gui/" "gui/" click sett href "../stellarphot/settings/" "settings/" click phot href "../stellarphot/photometry/" "photometry/" click diff href "../stellarphot/differential_photometry/" "differential_photometry/" click tfit href "../stellarphot/transit_fitting/" "transit_fitting/" click uts href "../stellarphot/utils/" "utils/" click plt href "../stellarphot/plotting/" "plotting/" click iop href "../stellarphot/io/" "io/" click corem href "../stellarphot/core.py" "core.py" click catm href "../stellarphot/catalogs.py" "catalogs.py" click trep href "../stellarphot/table_representations.py" "table_representations.py" ``` *Source: the [stellarphot/](../stellarphot/) package — each box is a subpackage directory or top-level module.* Notes: - The notebooks also import `differential_photometry`, `transit_fitting`, `io`, `plotting`, `utils`, and the top-level `stellarphot` package directly; only the two main dashed edges are drawn to keep the diagram readable. - `core.py` and `io` reference each other, but the import order is one-way at load time. `core.py` imports `io/aavso.py` (for `write_aavso_extended`) at the top of the file, and `io/aavso.py` does **not** import `core.py`. The only `io` module that imports `core.py` is `io/tess.py`, which is exposed lazily by `io/__init__.py` (a module-level `__getattr__`), so it is loaded only on first use — after `core.py` has finished importing. This replaces the previous in-method lazy import that worked around a genuine `core ↔ io` cycle. ## Core + pipeline cluster (file level) The photometry pipeline, differential photometry, and calibration utilities all sit on top of the core data layer. *Arrows: **solid** = an import (importer → imported); **dashed** = a notebook driving a UI layer, or a looser link.* ```mermaid flowchart LR classDef external fill:#eceff1,stroke:#90a4ae,stroke-dasharray: 5 5,color:#212121 subgraph sg_phot["stellarphot.photometry"] direction TB phot_py["photometry.py
AperturePhotometry"] srcdet_py["source_detection.py
source_detection, compute_fwhm"] prof_py["profiles.py
CenterAndProfile, find_center"] end subgraph sg_diff["stellarphot.differential_photometry"] direction TB relflux_py["aij_rel_fluxes.py
calc_aij_relative_flux"] vsxmag_py["vsx_mags.py
calc_vmag, calc_multi_vmag"] end subgraph sg_utils["stellarphot.utils"] direction TB magtrans_py["magnitude_transforms.py"] magsys_py["magnitude_system_transforms.py"] computil_py["comparison_utils.py"] vermig_py["version_migrator.py"] end subgraph sg_core["core data layer"] direction TB core_py["core.py
PhotometryData, CatalogData,
SourceListData"] catalogs_py["catalogs.py
apass_dr9, vsx_vizier, refcat2"] tabrep_py["table_representations.py"] end settings_ext["stellarphot.settings"]:::external phot_py -->|"compute_fwhm,
fast_fwhm_from_image"| srcdet_py prof_py -->|"calculate_noise"| phot_py phot_py --> core_py phot_py --> settings_ext srcdet_py --> core_py srcdet_py --> settings_ext relflux_py --> core_py magtrans_py -->|"apass_dr9, refcat2"| catalogs_py magtrans_py --> magsys_py computil_py -->|"apass_dr9, vsx_vizier"| catalogs_py vermig_py --> core_py vermig_py --> settings_ext core_py --> settings_ext core_py --> tabrep_py catalogs_py -->|"CatalogData"| core_py catalogs_py -->|"PassbandMap"| settings_ext tabrep_py --> settings_ext click phot_py href "../stellarphot/photometry/photometry.py" "photometry.py" click srcdet_py href "../stellarphot/photometry/source_detection.py" "source_detection.py" click prof_py href "../stellarphot/photometry/profiles.py" "profiles.py" click relflux_py href "../stellarphot/differential_photometry/aij_rel_fluxes.py" "aij_rel_fluxes.py" click vsxmag_py href "../stellarphot/differential_photometry/vsx_mags.py" "vsx_mags.py" click magtrans_py href "../stellarphot/utils/magnitude_transforms.py" "magnitude_transforms.py" click magsys_py href "../stellarphot/utils/magnitude_system_transforms.py" "magnitude_system_transforms.py" click computil_py href "../stellarphot/utils/comparison_utils.py" "comparison_utils.py" click vermig_py href "../stellarphot/utils/version_migrator.py" "version_migrator.py" click core_py href "../stellarphot/core.py" "core.py" click catalogs_py href "../stellarphot/catalogs.py" "catalogs.py" click tabrep_py href "../stellarphot/table_representations.py" "table_representations.py" ``` Key contents of each file: - [`core.py`](../stellarphot/core.py) — `BaseEnhancedTable` (validated `QTable`) and its subclasses `PhotometryData`, `CatalogData`, `SourceListData` (table data structures only). - [`catalogs.py`](../stellarphot/catalogs.py) — catalog-fetcher functions `apass_dr9()`, `refcat2()`, `vsx_vizier()` that build a `CatalogData` from Vizier/astroquery. Still importable from `stellarphot.core` via a deprecated shim. - [`table_representations.py`](../stellarphot/table_representations.py) — `generate_table_representers()`, `serialize_models_in_table_meta()`, `deserialize_models_in_table_meta()` (round-trips pydantic settings models stored in table metadata). - [`photometry/photometry.py`](../stellarphot/photometry/photometry.py) — `AperturePhotometry`, `single_image_photometry()`, `multi_image_photometry()`, `find_too_close()`, `clipped_sky_per_pix_stats()`, `calculate_noise()`. - [`photometry/source_detection.py`](../stellarphot/photometry/source_detection.py) — `source_detection()`, `compute_fwhm()`, `fast_fwhm_from_image()`. - [`photometry/profiles.py`](../stellarphot/photometry/profiles.py) — `find_center()`, `CenterAndProfile` (radial profile, curve of growth, SNR). - [`differential_photometry/aij_rel_fluxes.py`](../stellarphot/differential_photometry/aij_rel_fluxes.py) — `calc_aij_relative_flux()`, `add_relative_flux_column()`, `add_in_quadrature()`. - [`differential_photometry/vsx_mags.py`](../stellarphot/differential_photometry/vsx_mags.py) — `calc_vmag()`, `calc_multi_vmag()`. - [`utils/magnitude_transforms.py`](../stellarphot/utils/magnitude_transforms.py) — `transform_to_catalog()`, `calculate_transform_coefficients()`, `transform_magnitudes()`, `filter_transform()`. - [`utils/magnitude_system_transforms.py`](../stellarphot/utils/magnitude_system_transforms.py) — `PanStarrs1ToJohnsonCousins`, `USNOPrimeToSDSSDR7`, `transform_apass_bands()`, `transform_refcat2_bands()`. - [`utils/comparison_utils.py`](../stellarphot/utils/comparison_utils.py) — `set_up()`, `crossmatch_APASS2VSX()`, `mag_scale()`, `in_field()`, `read_file()`. - [`utils/version_migrator.py`](../stellarphot/utils/version_migrator.py) — `VersionMigrator` (stellarphot 1 → 2 data). ## UI cluster (gui + settings, file level) The entire widget layer now lives in `stellarphot.gui`: the auto-generated settings forms (`views.py`, `ui_generator`), the settings widgets (`custom_widgets.py`), the file chooser (`fits_opener.py`), and the seeing-profile/comparison-star widgets. It is built on top of the pure-Pydantic `stellarphot.settings` package (`models.py`, `settings_files.py`). `stellarphot.settings` is **data-only**: importing it (and hence `import stellarphot` and the core data layer) loads only the pydantic models and file handling, never the GUI stack. The GUI libraries (`ipywidgets`/`ipyautoui`/`astrowidgets`/`ginga`) are confined to `stellarphot.gui` and ship only with the optional `[gui]` extra, so a base install stays headless; importing `stellarphot.gui` is what pulls them in. *Arrows: **solid** = an import (importer → imported); **dashed** = a notebook driving a UI layer, or a looser link.* ```mermaid flowchart LR classDef external fill:#eceff1,stroke:#90a4ae,stroke-dasharray: 5 5,color:#212121 classDef nbstyle fill:#fff8e1,stroke:#f9a825,color:#212121 nb["notebooks/
(launcher)"]:::nbstyle subgraph sg_gui["stellarphot.gui (the [gui] extra)"] direction TB pac_py["profile_and_comps.py
ComparisonAndSeeing"] comp_py["comparison_functions.py
ComparisonViewer"] seeing_py["seeing_profile_functions.py
SeeingProfileWidget"] photwidg_py["photometry_widget_functions.py
TessAnalysisInputControls"] cw_py["custom_widgets.py
ReviewSettings, ChooseOrMakeNew,
PhotometryRunner, TessPhotometrySetup"] views_py["views.py
ui_generator"] fo_py["fits_opener.py
FitsOpener"] end subgraph sg_set["stellarphot.settings (pure Pydantic)"] direction TB sf_py["settings_files.py
SavedSettings,
PhotometryWorkingDirSettings"] models_py["models.py
PhotometrySettings, Camera,
Observatory, ..."] ap_py["astropy_pydantic.py"] aavsom_py["aavso_models.py"] aavsos_py["aavso_submission.py"] end core_ext["core.py"]:::external phot_ext["photometry/"]:::external plot_ext["plotting/"]:::external io_ext["io/"]:::external utils_ext["utils/"]:::external nb -.-> pac_py nb -.-> photwidg_py nb -.-> cw_py pac_py --> comp_py pac_py --> seeing_py comp_py -->|"set_keybindings"| seeing_py comp_py --> cw_py comp_py --> fo_py comp_py --> core_ext comp_py --> utils_ext seeing_py --> cw_py seeing_py --> fo_py seeing_py -->|"CenterAndProfile"| phot_ext seeing_py -->|"seeing_plot"| plot_ext seeing_py -->|"TessSubmission"| io_ext photwidg_py --> cw_py photwidg_py --> core_ext cw_py --> models_py cw_py --> sf_py cw_py -->|"ui_generator"| views_py cw_py --> fo_py cw_py -->|"tess_photometry_setup"| io_ext sf_py --> models_py views_py --> models_py models_py --> ap_py models_py --> aavsom_py aavsos_py --> models_py click nb href "../stellarphot/notebooks/" "notebooks/" click pac_py href "../stellarphot/gui/profile_and_comps.py" "profile_and_comps.py" click comp_py href "../stellarphot/gui/comparison_functions.py" "comparison_functions.py" click seeing_py href "../stellarphot/gui/seeing_profile_functions.py" "seeing_profile_functions.py" click photwidg_py href "../stellarphot/gui/photometry_widget_functions.py" "photometry_widget_functions.py" click cw_py href "../stellarphot/gui/custom_widgets.py" "custom_widgets.py" click views_py href "../stellarphot/gui/views.py" "views.py" click sf_py href "../stellarphot/settings/settings_files.py" "settings_files.py" click models_py href "../stellarphot/settings/models.py" "models.py" click fo_py href "../stellarphot/gui/fits_opener.py" "fits_opener.py" click ap_py href "../stellarphot/settings/astropy_pydantic.py" "astropy_pydantic.py" click aavsom_py href "../stellarphot/settings/aavso_models.py" "aavso_models.py" click aavsos_py href "../stellarphot/settings/aavso_submission.py" "aavso_submission.py" ``` Key contents of each file: - [`settings/models.py`](../stellarphot/settings/models.py) — pydantic models: `Camera`, `Observatory`, `PhotometryApertures`, `SourceLocationSettings`, `PhotometryOptionalSettings`, `PassbandMap`/`PassbandMapEntry`, `LoggingSettings`, `PhotometrySettings` (the aggregate), `Exoplanet`, `PhotometryRunSettings`, `PartialPhotometrySettings`. - [`settings/astropy_pydantic.py`](../stellarphot/settings/astropy_pydantic.py) — pydantic validators for astropy types (`UnitType`, `QuantityType`, `EquivalentTo`, `WithPhysicalType`, `AstropyValidator`). - [`settings/settings_files.py`](../stellarphot/settings/settings_files.py) — `SavedSettings` (per-user storage of cameras/observatories/passband maps), `PhotometryWorkingDirSettings` (loads/saves `photometry_settings.json` in the working directory). - [`gui/views.py`](../stellarphot/gui/views.py) — `ui_generator()` (builds an `ipyautoui` widget from any pydantic model). - [`gui/custom_widgets.py`](../stellarphot/gui/custom_widgets.py) — `ChooseOrMakeNew`, `Confirm`, `SettingWithTitle`, `ReviewSettings`, `PhotometryRunner`, `TessPhotometrySetup`, `Spinner`. - [`gui/fits_opener.py`](../stellarphot/gui/fits_opener.py) — `FitsOpener` (file chooser + lazy `CCDData`/header access). - [`gui/seeing_profile_functions.py`](../stellarphot/gui/seeing_profile_functions.py) — `SeeingProfileWidget`, `set_keybindings()`. - [`gui/comparison_functions.py`](../stellarphot/gui/comparison_functions.py) — `ComparisonViewer`, `make_markers()`. - [`gui/photometry_widget_functions.py`](../stellarphot/gui/photometry_widget_functions.py) — `TessAnalysisInputControls`, `filter_by_dates()`. - [`gui/profile_and_comps.py`](../stellarphot/gui/profile_and_comps.py) — `ComparisonAndSeeing` (combines the seeing and comparison widgets). ## Output / IO cluster (file level) *Arrows: **solid** = an import (importer → imported); **dashed** = a notebook driving a UI layer, or a looser link.* ```mermaid flowchart LR classDef external fill:#eceff1,stroke:#90a4ae,stroke-dasharray: 5 5,color:#212121 subgraph sg_io["stellarphot.io"] direction TB aij_py["aij.py
ApertureFileAIJ, parse_aij_table"] aavso_py["aavso.py
write_aavso_extended"] tess_py["tess.py
TOI, TessSubmission,
TessTargetFile"] end subgraph sg_tf["stellarphot.transit_fitting"] direction TB tf_core["core.py
TransitModelFit"] tf_io["io.py
get_tic_info"] tf_plot["plotting.py
plot_predict_ingress_egress"] end tf_gui["gui/transit_fitting_gui.py
exotic_settings_widget
(stellarphot.gui)"]:::external subgraph sg_plot["stellarphot.plotting"] direction TB aijplots_py["aij_plots.py
seeing_plot"] transitplots_py["transit_plots.py
plot_transit_lightcurve"] multinight_py["multi_night_plots.py
multi_night"] end core_ext["core.py"]:::external settings_ext["settings/"]:::external batman_ext["batman
(transit models)"]:::external mast_ext["astroquery MAST"]:::external tess_py -->|"get_tic_info"| tf_io tess_py --> core_ext tess_py --> settings_ext aavso_py -->|"AAVSOFilters,
AAVSOSubmissionHeader"| settings_ext tf_gui --> tf_io tf_io -.-> mast_ext tf_core -.-> batman_ext aijplots_py -->|"PhotometryApertures"| settings_ext click aij_py href "../stellarphot/io/aij.py" "io/aij.py" click aavso_py href "../stellarphot/io/aavso.py" "io/aavso.py" click tess_py href "../stellarphot/io/tess.py" "io/tess.py" click tf_core href "../stellarphot/transit_fitting/core.py" "transit_fitting/core.py" click tf_gui href "../stellarphot/gui/transit_fitting_gui.py" "gui/transit_fitting_gui.py" click tf_io href "../stellarphot/transit_fitting/io.py" "transit_fitting/io.py" click tf_plot href "../stellarphot/transit_fitting/plotting.py" "transit_fitting/plotting.py" click aijplots_py href "../stellarphot/plotting/aij_plots.py" "plotting/aij_plots.py" click transitplots_py href "../stellarphot/plotting/transit_plots.py" "plotting/transit_plots.py" click multinight_py href "../stellarphot/plotting/multi_night_plots.py" "plotting/multi_night_plots.py" ``` Key contents of each file: - [`io/aij.py`](../stellarphot/io/aij.py) — `ApertureAIJ`, `MultiApertureAIJ`, `ApertureFileAIJ`, `Star`, `generate_aij_table()`, `parse_aij_table()` (AstroImageJ compatibility). - [`io/aavso.py`](../stellarphot/io/aavso.py) — `write_aavso_extended()` plus field validators/formatters for the AAVSO extended file format. - [`io/tess.py`](../stellarphot/io/tess.py) — `TessSubmission` (TFOP file naming), `TOI` (transit parameters fetched by TIC ID), `TessTargetFile` (nearby GAIA sources), `tess_photometry_setup()`. - [`transit_fitting/core.py`](../stellarphot/transit_fitting/core.py) — `TransitModelFit`, `TransitModelOptions`, `VariableArgsFitter`. - [`gui/transit_fitting_gui.py`](../stellarphot/gui/transit_fitting_gui.py) — EXOTIC settings widget and TIC/TOI population helpers. - [`transit_fitting/io.py`](../stellarphot/transit_fitting/io.py) — `get_tic_info()` (MAST catalog query). - [`transit_fitting/plotting.py`](../stellarphot/transit_fitting/plotting.py) — `plot_predict_ingress_egress()`. - [`plotting/aij_plots.py`](../stellarphot/plotting/aij_plots.py) — `seeing_plot()`. - [`plotting/transit_plots.py`](../stellarphot/plotting/transit_plots.py) — `plot_transit_lightcurve()`, `plot_many_factors()`, `bin_data()`, `scale_and_shift()`. - [`plotting/multi_night_plots.py`](../stellarphot/plotting/multi_night_plots.py) — `plot_magnitudes()`, `multi_night()`. ## External dependencies (major ones per component) | Component | Major external dependencies | |---|---| | Core data layer | astropy (QTable, SkyCoord, Time, units), astroquery (Vizier, XMatch), pandas, lightkurve — no GUI stack at import time | | Photometry engine | photutils (apertures, DAOStarFinder, centroids, profiles), astropy, ccdproc | | Settings | pydantic only — no GUI dependencies (the widget layer moved to `stellarphot.gui`) | | Transit fitting | batman-package, astropy.modeling, scipy, astroquery (MAST) | | GUI layer | the optional `[gui]` extra: ipywidgets, ipyautoui, ipyfilechooser, astrowidgets, ginga, jupyter-app-launcher, papermill (plus matplotlib from the base install) — not installed by a base `pip install stellarphot` | | Plotting | matplotlib |