Coverage for tests/test_componentconfig.py: 100%
55 statements
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-23 02:31 -0700
« prev ^ index » next coverage.py v7.16.0, created at 2026-09-23 02:31 -0700
1# This file is part of multiprofit.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
22import numpy as np
23import pytest
25import lsst.gauss2d.fit as g2f
26from lsst.multiprofit.componentconfig import (
27 EllipticalComponentConfig,
28 GaussianComponentConfig,
29 ParameterConfig,
30 SersicComponentConfig,
31 SersicIndexParameterConfig,
32)
33from lsst.multiprofit.utils import get_params_uniq, set_config_from_dict
36@pytest.fixture(scope="module")
37def centroid_limits():
38 """Return trivial limits for centroids."""
39 limits = g2f.LimitsD(min=-np.inf, max=np.inf)
40 return limits
43@pytest.fixture(scope="module")
44def centroid(centroid_limits):
45 """Return centroid parameters with trivial limits."""
46 cenx = g2f.CentroidXParameterD(0, limits=centroid_limits, fixed=True)
47 ceny = g2f.CentroidYParameterD(0, limits=centroid_limits, fixed=True)
48 centroid = g2f.CentroidParameters(cenx, ceny)
49 return centroid
52@pytest.fixture(scope="module")
53def channels():
54 """Return dict of generic RGB channels."""
55 return {band: g2f.Channel.get(band) for band in ("R", "G", "B")}
58def test_EllipticalComponentConfig():
59 """Test set_config_from_dict on a component."""
60 config = EllipticalComponentConfig()
61 config2 = EllipticalComponentConfig()
62 set_config_from_dict(config2, config.toDict())
63 assert config == config2
66def test_GaussianComponentConfig(centroid):
67 """Test GaussianComponentConfig init and funcs."""
68 config = GaussianComponentConfig(
69 rho=ParameterConfig(value_initial=0),
70 size_x=ParameterConfig(value_initial=1.4),
71 size_y=ParameterConfig(value_initial=1.6),
72 )
73 channel = g2f.Channel.NONE
74 component_data1 = config.make_component(
75 centroid=centroid,
76 integral_model=g2f.FractionalIntegralModel(
77 [(channel, g2f.ProperFractionParameterD(0.5, fixed=False))],
78 model=config.make_linear_integral_model({channel: 1.0}),
79 ),
80 )
81 component_data2 = config.make_component(
82 centroid=centroid,
83 integral_model=g2f.FractionalIntegralModel(
84 [(channel, g2f.ProperFractionParameterD(1.0, fixed=True))],
85 model=component_data1.integral_model,
86 is_final=True,
87 ),
88 )
89 components = (component_data1, component_data2)
90 n_components = len(components)
91 for idx, component_data in enumerate(components):
92 component = component_data.component
93 assert component.centroid is centroid
94 assert len(component_data.priors) == 0
95 fluxes = list(get_params_uniq(component, nonlinear=False))
96 assert len(fluxes) == 1
97 assert isinstance(fluxes[0], g2f.IntegralParameterD)
98 fracs = [
99 param
100 for param in get_params_uniq(component, linear=False)
101 if isinstance(param, g2f.ProperFractionParameterD)
102 ]
103 assert len(fracs) == (idx + (idx == 0) - (idx == n_components))
106def test_SersicConfig(centroid, channels):
107 """Test Sersic Component/Index Config init and funcs."""
108 rho, size_x, size_y, sersic_index = -0.3, 1.4, 1.6, 3.2
109 config = SersicComponentConfig(
110 rho=ParameterConfig(value_initial=rho),
111 size_x=ParameterConfig(value_initial=size_x),
112 size_y=ParameterConfig(value_initial=size_y),
113 sersic_index=SersicIndexParameterConfig(value_initial=sersic_index),
114 )
115 fluxes = {channel: 1.0 + idx for idx, channel in enumerate(channels.values())}
116 integral_model = config.make_linear_integral_model(fluxes)
117 component_data = config.make_component(
118 centroid=centroid,
119 integral_model=integral_model,
120 )
121 assert component_data.component is not None
122 # Will be true as long as there's a default Sersic index prior
123 assert len(component_data.priors) == 1
124 params = get_params_uniq(component_data.component)
125 values_init = {
126 g2f.RhoParameterD: rho,
127 g2f.ReffXParameterD: size_x,
128 g2f.ReffYParameterD: size_y,
129 g2f.SersicIndexParameterD: sersic_index,
130 }
131 fluxes_label = {
132 config.format_label(config.get_integral_label_default(), name_channel=channel.name): fluxes[channel]
133 for channel in fluxes.keys()
134 }
135 for param in params:
136 if isinstance(param, g2f.IntegralParameterD):
137 assert fluxes_label[param.label] == param.value
138 elif value_init := values_init.get(param.__class__):
139 assert param.value == value_init