Coverage for tests/test_componentconfig.py: 100%

55 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-09-14 02:16 -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/>. 

21 

22import numpy as np 

23import pytest 

24 

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 

34 

35 

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 

41 

42 

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 

50 

51 

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")} 

56 

57 

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 

64 

65 

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)) 

104 

105 

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