astrocolor 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 (29) hide show
  1. astrocolor-0.1.0/LICENSE.txt +21 -0
  2. astrocolor-0.1.0/PKG-INFO +125 -0
  3. astrocolor-0.1.0/README.md +104 -0
  4. astrocolor-0.1.0/pyproject.toml +41 -0
  5. astrocolor-0.1.0/src/astrocolor/__init__.py +39 -0
  6. astrocolor-0.1.0/src/astrocolor/algebra.py +101 -0
  7. astrocolor-0.1.0/src/astrocolor/auxiliary.py +803 -0
  8. astrocolor-0.1.0/src/astrocolor/color.py +342 -0
  9. astrocolor-0.1.0/src/astrocolor/convolution.py +94 -0
  10. astrocolor-0.1.0/src/astrocolor/core.py +472 -0
  11. astrocolor-0.1.0/src/astrocolor/data/Sun_CALSPEC.npz +0 -0
  12. astrocolor-0.1.0/src/astrocolor/data/Vega_CALSPEC.npz +0 -0
  13. astrocolor-0.1.0/src/astrocolor/data_manager.py +3 -0
  14. astrocolor-0.1.0/src/astrocolor/errors.py +104 -0
  15. astrocolor-0.1.0/src/astrocolor/filter_objects.py +248 -0
  16. astrocolor-0.1.0/src/astrocolor/filters/CIE_1931_2deg.x.txt +95 -0
  17. astrocolor-0.1.0/src/astrocolor/filters/CIE_1931_2deg.y.txt +95 -0
  18. astrocolor-0.1.0/src/astrocolor/filters/CIE_1931_2deg.z.txt +58 -0
  19. astrocolor-0.1.0/src/astrocolor/filters/Generic_Bessell.B.datA +21 -0
  20. astrocolor-0.1.0/src/astrocolor/filters/Generic_Bessell.R.datA +24 -0
  21. astrocolor-0.1.0/src/astrocolor/filters/Generic_Bessell.U.datA +25 -0
  22. astrocolor-0.1.0/src/astrocolor/filters/Generic_Bessell.V.datA +24 -0
  23. astrocolor-0.1.0/src/astrocolor/filters/SLOAN_SDSS.g.datA +89 -0
  24. astrocolor-0.1.0/src/astrocolor/filters/SLOAN_SDSS.r.datA +75 -0
  25. astrocolor-0.1.0/src/astrocolor/photospectral_objects.py +202 -0
  26. astrocolor-0.1.0/src/astrocolor/physical_models.py +73 -0
  27. astrocolor-0.1.0/src/astrocolor/py.typed +0 -0
  28. astrocolor-0.1.0/src/astrocolor/spectral_objects.py +458 -0
  29. astrocolor-0.1.0/src/astrocolor/spectral_reconstruction.py +240 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Askaniy Anpilogov
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,125 @@
1
+ Metadata-Version: 2.4
2
+ Name: astrocolor
3
+ Version: 0.1.0
4
+ Summary: Library to perform spectral reconstruction, calculate synthetic photometry and colors.
5
+ Author: Askaniy Anpilogov
6
+ Author-email: Askaniy Anpilogov <aaskaniy@gmail.com>
7
+ License-Expression: MIT
8
+ License-File: LICENSE.txt
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: Programming Language :: Python :: 3.14
13
+ Requires-Dist: numpy>=2.4.4
14
+ Requires-Dist: scipy>=1.17.1
15
+ Requires-Python: >=3.12
16
+ Project-URL: Homepage, https://github.com/Askaniy/AstroColor
17
+ Project-URL: Repository, https://github.com/Askaniy/AstroColor
18
+ Project-URL: Issues, https://github.com/Askaniy/AstroColor/issues
19
+ Project-URL: Changelog, https://github.com/Askaniy/AstroColor/releases
20
+ Description-Content-Type: text/markdown
21
+
22
+ # AstroColor
23
+
24
+ A Python library for converting between photometric systems, true color calculation, and space image processing.
25
+
26
+ It performs synthetic photometry on low-resolution (5-nm wavelength grid step) spectra as well as spectral reconstruction from measurements in filters based on Tikhonov regularization.
27
+
28
+ **Pre-alpha version! Do not use!**
29
+
30
+
31
+ ## Installation
32
+
33
+ Use AstroColor in a virtual environment:
34
+ ```sh
35
+ python3 -m venv .venv
36
+ .venv/bin/pip install git+https://github.com/Askaniy/AstroColor.git
37
+ ```
38
+
39
+ Or add AstroColor to your [uv](https://github.com/astral-sh/uv) project:
40
+ ```sh
41
+ uv add git+https://github.com/Askaniy/AstroColor.git
42
+ ```
43
+
44
+
45
+ ## Key features
46
+
47
+ - Calculate synthetic photometry
48
+ ```py
49
+ import astrocolor as ac
50
+
51
+ spectrum = ac.Spectrum(
52
+ wavelength_nm=[400, 500, 600, 700],
53
+ spectral_dist=[1, 2, 2, 1]
54
+ )
55
+ v_band = ac.Filter.get('Generic_Bessell.V')
56
+ flux_value, flux_error = ac.observe(spectrum, v_band)
57
+ ```
58
+
59
+ - Create a filter system
60
+ ```py
61
+ johnson_system = ac.FilterSet.get(
62
+ 'Generic_Bessell.B',
63
+ 'Generic_Bessell.V',
64
+ 'Generic_Bessell.R'
65
+ )
66
+ photospectrum_BVR = ac.observe(spectrum, johnson_system)
67
+ ```
68
+
69
+ - Reconstruct photometry measurements into a smooth spectrum
70
+ ```py
71
+ reconstructed = ac.spectral_reconstruction(photospectrum_BVR, requested_wavelengths=[400, 700])
72
+ ```
73
+
74
+ - Convert measurements directly between photometric systems
75
+ ```py
76
+ sloan_system = ac.FilterSet.get('SLOAN_SDSS.g', 'SLOAN_SDSS.r')
77
+ photospectrum_gr = ac.observe(photospectrum_BVR, sloan_system)
78
+ ```
79
+
80
+ - Work on your wavelengths
81
+ ```py
82
+ custom_filter_set = ac.Filter.monochromatic(656.279) | ac.Filter.monochromatic(486.135)
83
+ ```
84
+
85
+ - Calculate true colors
86
+ ```py
87
+ color_xyz = ac.ColorPoint.from_spectral_data(ac.sun_CALSPEC)
88
+ color_system = ac.ColorSystem('sRGB', 'Illuminant E') # recommended
89
+ color_rgb = color_xyz.to_color_system(color_system)
90
+ color_rgb.maximize_brightness = True
91
+ color_html = color_rgb.to_html()
92
+ ```
93
+
94
+ - Model spectra
95
+ ```py
96
+ bb_3000K = ac.BlackBodyModel(3000).determine_at_wavelengths([400, 700])
97
+ ```
98
+
99
+ - Process images via spectral cube reconstruction
100
+ ```py
101
+ # coming soon after debugging
102
+ ```
103
+
104
+ - Error propagation with covariance matrices
105
+ ```py
106
+ # coming soon after debugging
107
+ ```
108
+
109
+
110
+
111
+ ## History
112
+
113
+ [TrueColorTools](https://github.com/Askaniy/TrueColorTools) were created in 2020 to resolve disputes regarding the color of celestial bodies.
114
+ It features a graphical user interface and a user-expandable spectral database.
115
+ Over time, the core of the program became self-contained enough to be spun off into a library.
116
+ The refactoring took place in 2026; it opens up a general astronomical application.
117
+
118
+
119
+ ## For developers
120
+
121
+ Use `uv sync --group dev` to set the environment and build the library.
122
+ Use `uv run pytest` for testing.
123
+ Use `\dev` folder for local experiments.
124
+
125
+ Any changes suggested by AI must be thoroughly reviewed by the person who generated them. The responsibility always lies with the person.
@@ -0,0 +1,104 @@
1
+ # AstroColor
2
+
3
+ A Python library for converting between photometric systems, true color calculation, and space image processing.
4
+
5
+ It performs synthetic photometry on low-resolution (5-nm wavelength grid step) spectra as well as spectral reconstruction from measurements in filters based on Tikhonov regularization.
6
+
7
+ **Pre-alpha version! Do not use!**
8
+
9
+
10
+ ## Installation
11
+
12
+ Use AstroColor in a virtual environment:
13
+ ```sh
14
+ python3 -m venv .venv
15
+ .venv/bin/pip install git+https://github.com/Askaniy/AstroColor.git
16
+ ```
17
+
18
+ Or add AstroColor to your [uv](https://github.com/astral-sh/uv) project:
19
+ ```sh
20
+ uv add git+https://github.com/Askaniy/AstroColor.git
21
+ ```
22
+
23
+
24
+ ## Key features
25
+
26
+ - Calculate synthetic photometry
27
+ ```py
28
+ import astrocolor as ac
29
+
30
+ spectrum = ac.Spectrum(
31
+ wavelength_nm=[400, 500, 600, 700],
32
+ spectral_dist=[1, 2, 2, 1]
33
+ )
34
+ v_band = ac.Filter.get('Generic_Bessell.V')
35
+ flux_value, flux_error = ac.observe(spectrum, v_band)
36
+ ```
37
+
38
+ - Create a filter system
39
+ ```py
40
+ johnson_system = ac.FilterSet.get(
41
+ 'Generic_Bessell.B',
42
+ 'Generic_Bessell.V',
43
+ 'Generic_Bessell.R'
44
+ )
45
+ photospectrum_BVR = ac.observe(spectrum, johnson_system)
46
+ ```
47
+
48
+ - Reconstruct photometry measurements into a smooth spectrum
49
+ ```py
50
+ reconstructed = ac.spectral_reconstruction(photospectrum_BVR, requested_wavelengths=[400, 700])
51
+ ```
52
+
53
+ - Convert measurements directly between photometric systems
54
+ ```py
55
+ sloan_system = ac.FilterSet.get('SLOAN_SDSS.g', 'SLOAN_SDSS.r')
56
+ photospectrum_gr = ac.observe(photospectrum_BVR, sloan_system)
57
+ ```
58
+
59
+ - Work on your wavelengths
60
+ ```py
61
+ custom_filter_set = ac.Filter.monochromatic(656.279) | ac.Filter.monochromatic(486.135)
62
+ ```
63
+
64
+ - Calculate true colors
65
+ ```py
66
+ color_xyz = ac.ColorPoint.from_spectral_data(ac.sun_CALSPEC)
67
+ color_system = ac.ColorSystem('sRGB', 'Illuminant E') # recommended
68
+ color_rgb = color_xyz.to_color_system(color_system)
69
+ color_rgb.maximize_brightness = True
70
+ color_html = color_rgb.to_html()
71
+ ```
72
+
73
+ - Model spectra
74
+ ```py
75
+ bb_3000K = ac.BlackBodyModel(3000).determine_at_wavelengths([400, 700])
76
+ ```
77
+
78
+ - Process images via spectral cube reconstruction
79
+ ```py
80
+ # coming soon after debugging
81
+ ```
82
+
83
+ - Error propagation with covariance matrices
84
+ ```py
85
+ # coming soon after debugging
86
+ ```
87
+
88
+
89
+
90
+ ## History
91
+
92
+ [TrueColorTools](https://github.com/Askaniy/TrueColorTools) were created in 2020 to resolve disputes regarding the color of celestial bodies.
93
+ It features a graphical user interface and a user-expandable spectral database.
94
+ Over time, the core of the program became self-contained enough to be spun off into a library.
95
+ The refactoring took place in 2026; it opens up a general astronomical application.
96
+
97
+
98
+ ## For developers
99
+
100
+ Use `uv sync --group dev` to set the environment and build the library.
101
+ Use `uv run pytest` for testing.
102
+ Use `\dev` folder for local experiments.
103
+
104
+ Any changes suggested by AI must be thoroughly reviewed by the person who generated them. The responsibility always lies with the person.
@@ -0,0 +1,41 @@
1
+ [build-system]
2
+ requires = ["uv_build>=0.11.20,<0.12.0"]
3
+ build-backend = "uv_build"
4
+
5
+ [project]
6
+ name = "astrocolor"
7
+ version = "0.1.0"
8
+ description = "Library to perform spectral reconstruction, calculate synthetic photometry and colors."
9
+ readme = "README.md"
10
+ license = "MIT"
11
+ license-files = ["LICENSE.txt"]
12
+ authors = [
13
+ { name = "Askaniy Anpilogov", email = "aaskaniy@gmail.com" },
14
+ ]
15
+ requires-python = ">=3.12"
16
+
17
+ classifiers = [
18
+ "Development Status :: 3 - Alpha",
19
+ "Programming Language :: Python :: 3.12",
20
+ "Programming Language :: Python :: 3.13",
21
+ "Programming Language :: Python :: 3.14",
22
+ ]
23
+
24
+ dependencies = [
25
+ "numpy>=2.4.4",
26
+ "scipy>=1.17.1",
27
+ ]
28
+
29
+ [project.urls]
30
+ Homepage = "https://github.com/Askaniy/AstroColor"
31
+ Repository = "https://github.com/Askaniy/AstroColor"
32
+ Issues = "https://github.com/Askaniy/AstroColor/issues"
33
+ Changelog = "https://github.com/Askaniy/AstroColor/releases"
34
+
35
+ [dependency-groups]
36
+ dev = [
37
+ "pytest>=9.1.1",
38
+ ]
39
+
40
+ [tool.pytest.ini_options]
41
+ testpaths = ["tests", "src/astrocolor/tests"]
@@ -0,0 +1,39 @@
1
+ from .spectral_objects import Spectrum, SpectralSet, SpectralCube
2
+ from .photospectral_objects import Photospectrum, PhotospectralSet, PhotospectralCube
3
+ from .spectral_reconstruction import (
4
+ ReconstructedSpectrum,
5
+ ReconstructedSpectralSet,
6
+ ReconstructedSpectralCube,
7
+ spectral_reconstruction,
8
+ )
9
+ from .filter_objects import Filter, FilterSet
10
+ from .convolution import observe, scale_spectrum
11
+ from .color import ColorSystem, ColorPoint, ColorLine, ColorImage, visible_range
12
+ from .physical_models import sun_CALSPEC, vega_CALSPEC, BlackBodyModel
13
+
14
+
15
+ # API namespace
16
+ __all__ = (
17
+ 'Spectrum',
18
+ 'SpectralSet',
19
+ 'SpectralCube',
20
+ 'Photospectrum',
21
+ 'PhotospectralSet',
22
+ 'PhotospectralCube',
23
+ 'ReconstructedSpectrum',
24
+ 'ReconstructedSpectralSet',
25
+ 'ReconstructedSpectralCube',
26
+ 'spectral_reconstruction',
27
+ 'Filter',
28
+ 'FilterSet',
29
+ 'observe',
30
+ 'scale_spectrum',
31
+ 'ColorSystem',
32
+ 'ColorPoint',
33
+ 'ColorLine',
34
+ 'ColorImage',
35
+ 'visible_range',
36
+ 'sun_CALSPEC',
37
+ 'vega_CALSPEC',
38
+ 'BlackBodyModel'
39
+ )
@@ -0,0 +1,101 @@
1
+ import numpy as np
2
+ import numpy.typing as npt
3
+
4
+
5
+
6
+ def make_same_ndim(arr1: npt.ArrayLike, arr2: npt.ArrayLike):
7
+ """ Equalizes the arrays dimensions along spatial axes to make it possible to broadcast """
8
+ arr1 = np.asarray(arr1)
9
+ arr2 = np.asarray(arr2)
10
+ if (ndim_delta := arr2.ndim - arr1.ndim) != 0:
11
+ if ndim_delta > 0:
12
+ arr1 = arr1.reshape(arr1.shape + (1,)*ndim_delta)
13
+ else:
14
+ arr2 = arr2.reshape(arr2.shape + (1,)*(-ndim_delta))
15
+ return arr1, arr2
16
+
17
+
18
+ # 1. Addition
19
+
20
+ def add_value(mean_x, mean_y):
21
+ mean_x, mean_y = make_same_ndim(mean_x, mean_y)
22
+ return mean_x + mean_y
23
+
24
+ def add_error(mean_x, cov_x, mean_y, cov_y):
25
+ if cov_x is None:
26
+ return cov_y
27
+ elif cov_y is None:
28
+ return cov_x
29
+ else:
30
+ cov_x, cov_y = make_same_ndim(cov_x, cov_y)
31
+ return cov_x + cov_y
32
+
33
+
34
+ # 2. Subtraction
35
+
36
+ def sub_value(mean_x, mean_y):
37
+ mean_x, mean_y = make_same_ndim(mean_x, mean_y)
38
+ return mean_x - mean_y
39
+
40
+ def sub_error(mean_x, cov_x, mean_y, cov_y):
41
+ return add_error(mean_x, cov_x, mean_y, cov_y)
42
+
43
+
44
+ # 3. Multiplication
45
+
46
+ @staticmethod
47
+ def mul_value(mean_x, mean_y):
48
+ try:
49
+ # Numeric and same-ndim numpy arrays cases
50
+ return mean_x * mean_y
51
+ except ValueError:
52
+ # Different ndim case
53
+ mean_x = np.asarray(mean_x)
54
+ mean_y = np.asarray(mean_y)
55
+ if mean_y.ndim > mean_x.ndim:
56
+ mean_x, mean_y = mean_y, mean_x
57
+ return (mean_x.T * mean_y).T
58
+
59
+ def mul_error(mean_x, cov_x, mean_y, cov_y):
60
+ if cov_x is None and cov_y is None:
61
+ return None
62
+ else:
63
+ n = mean_x.shape[0]
64
+ cov_z = np.zeros((n, n)) # TODO: fix the case of x.ndim != y.ndim
65
+ if cov_x is not None:
66
+ diag_y = np.diag(mean_y)
67
+ cov_z += diag_y @ cov_x @ diag_y
68
+ if cov_y is not None:
69
+ diag_x = np.diag(mean_x)
70
+ cov_z += diag_x @ cov_y @ diag_x
71
+ return cov_z
72
+
73
+
74
+ # 4. Division
75
+
76
+ @staticmethod
77
+ def div_value(mean_x, mean_y):
78
+ try:
79
+ # Numeric and same-ndim numpy arrays cases
80
+ return mean_x / mean_y
81
+ except ValueError:
82
+ # Different ndim case
83
+ mean_x = np.asarray(mean_x)
84
+ mean_y = np.asarray(mean_y)
85
+ if mean_y.ndim > mean_x.ndim:
86
+ mean_x, mean_y = mean_y, mean_x
87
+ return (mean_x.T / mean_y).T
88
+
89
+ def div_error(mean_x, cov_x, mean_y, cov_y):
90
+ if cov_x is None and cov_y is None:
91
+ return None
92
+ else:
93
+ n = mean_x.shape[0]
94
+ cov_z = np.zeros((n, n)) # TODO: fix the case of x.ndim != y.ndim
95
+ if cov_x is not None:
96
+ cov_z += cov_x
97
+ if cov_y is not None:
98
+ diag_z = np.diag(div_value(mean_x, mean_y))
99
+ cov_z += diag_z @ cov_y @ diag_z
100
+ diag_y_inv = np.diag(1 / mean_y)
101
+ return diag_y_inv @ cov_z @ diag_y_inv