Coverage for python/lsst/meas/extensions/multiprofit/pipetasks_fit.py: 63%

265 statements  

« prev     ^ index     » next       coverage.py v7.15.0, created at 2026-07-08 09:38 +0000

1# This file is part of meas_extensions_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 

22__all__ = ( 

23 "component_names_default", 

24 "model_names_default", 

25 "MultiProFitCoaddPsfFitConfig", 

26 "MultiProFitCoaddPsfFitTask", 

27 "MultiProFitCoaddObjectFitConfig", 

28 "MultiProFitCoaddPointFitConfig", 

29 "MultiProFitCoaddSersicFitConfig", 

30 "MultiProFitCoaddSersicFitTask", 

31 "MultiProFitCoaddGaussFitConfig", 

32 "MultiProFitCoaddGaussFitTask", 

33 "MultiProFitCoaddExpFitConfig", 

34 "MultiProFitCoaddExpFitTask", 

35 "MultiProFitCoaddDeVFitConfig", 

36 "MultiProFitCoaddDeVFitTask", 

37 "MultiProFitCoaddExpDeVFitConfig", 

38 "MultiProFitCoaddExpDeVFitTask", 

39) 

40 

41from abc import abstractmethod 

42import itertools 

43import math 

44from types import SimpleNamespace 

45from typing import Any, Mapping, Sequence 

46 

47from lsst.daf.butler import DeferredDatasetHandle 

48import lsst.gauss2d.fit as g2f 

49from lsst.multiprofit.componentconfig import ( 

50 GaussianComponentConfig, 

51 ParameterConfig, 

52 SersicComponentConfig, 

53 SersicIndexParameterConfig, 

54) 

55from lsst.multiprofit.fitting.fit_source import CatalogExposureSourcesABC, CatalogSourceFitterConfigData 

56from lsst.multiprofit.modelconfig import ModelConfig 

57from lsst.multiprofit.sourceconfig import ComponentGroupConfig, SourceConfig 

58from lsst.pex.config import ConfigDictField, Field 

59from lsst.pipe.tasks.fit_coadd_multiband import ( 

60 CatalogExposureInputs, 

61 CoaddMultibandFitConfig, 

62 CoaddMultibandFitConnections, 

63 CoaddMultibandFitTask, 

64) 

65from lsst.pipe.tasks.fit_coadd_psf import CoaddPsfFitConfig, CoaddPsfFitConnections, CoaddPsfFitTask 

66 

67from .fit_coadd_multiband import ( 

68 CachedBasicModelInitializer, 

69 MagnitudeDependentSizePriorConfig, 

70 MakeBasicInitializerAction, 

71 ModelInitializer, 

72 MultiProFitSourceTask, 

73 PsfComponentsActionBase, 

74 SourceTablePsfComponentsAction, 

75) 

76from .fit_coadd_psf import MultiProFitPsfTask 

77from .input_config import InputConfig 

78 

79component_names_default = SimpleNamespace( 

80 point="point", 

81 gauss="gauss", 

82 exp="exp", 

83 deV="deV", 

84 sersic="sersic", 

85) 

86 

87model_names_default = SimpleNamespace( 

88 point="Point", 

89 gauss="Gauss", 

90 exp="Exp", 

91 deV="DeV", 

92 sersic="Sersic", 

93 fixed_cen="FixedCen", 

94 shapelet_psf="ShapeletPsf", 

95) 

96 

97 

98class MultiProFitCoaddPsfFitConfig( 

99 CoaddPsfFitConfig, 

100 pipelineConnections=CoaddPsfFitConnections, 

101): 

102 """MultiProFit PSF fit task config.""" 

103 

104 def setDefaults(self): 

105 super().setDefaults() 

106 self.fit_coadd_psf.retarget(MultiProFitPsfTask) 

107 self.fit_coadd_psf.config_fit.eval_residual = False 

108 

109 

110class MultiProFitCoaddPsfFitTask(CoaddPsfFitTask): 

111 """MultiProFit PSF fit task.""" 

112 

113 ConfigClass = MultiProFitCoaddPsfFitConfig 

114 _DefaultName = "multiProFitCoaddPsfFit" 

115 

116 

117class MultiProFitCoaddObjectFitConnections(CoaddMultibandFitConnections): 

118 def __init__(self, *, config=None): 

119 super().__init__(config=config) 

120 for name, config_input in config.inputs_init.items(): 

121 if hasattr(self, name): 

122 raise ValueError( 

123 f"{config_input=} {name=} is invalid, due to being an existing attribute" f" of {self=}" 

124 ) 

125 if config_input.is_multipatch or not config_input.is_multiband: 

126 raise ValueError( 

127 f"Single-band and/or multipatch initialization config_input entries ({name})" 

128 f" are not supported yet." 

129 ) 

130 connection = config_input.get_connection(name) 

131 setattr(self, name, connection) 

132 

133 

134class MultiProFitCoaddObjectFitConfig( 

135 CoaddMultibandFitConfig, 

136 pipelineConnections=MultiProFitCoaddObjectFitConnections, 

137): 

138 """Generic MultiProFit source fit task config.""" 

139 

140 inputs_init = ConfigDictField( 

141 doc="Mapping of optional input dataset configs by name, for initialization", 

142 keytype=str, 

143 itemtype=InputConfig, 

144 default={}, 

145 ) 

146 

147 # This needs to be set, ideally in setDefaults of subclasses 

148 name_model = Field[str](doc="The name of the model", default=None) 

149 

150 def _get_source(self): 

151 return next(iter(self.fit_coadd_multiband.config_model.sources.values())) 

152 

153 def _get_component_group(self, source: SourceConfig | None = None): 

154 if source is None: 

155 source = self._get_source() 

156 return next(iter(source.component_groups.values())) 

157 

158 def add_point_source(self, name: str | None = None): 

159 """Add a point source component. 

160 

161 Parameters 

162 ---------- 

163 name 

164 The name of the component. 

165 """ 

166 if name is None: 166 ↛ 168line 166 didn't jump to line 168 because the condition on line 166 was always true

167 name = component_names_default.point 

168 source = self._get_source() 

169 group = self._get_component_group(source=source) 

170 if name in group.components_gauss: 170 ↛ 171line 170 didn't jump to line 171 because the condition on line 170 was never true

171 raise RuntimeError(f"{name=} component already exists in {source=}") 

172 group.components_gauss[name] = self.make_point_source_component() 

173 self.connections.name_table += model_names_default.point 

174 

175 def finalize( 

176 self, 

177 add_point_source: bool = False, 

178 fix_centroid: bool = False, 

179 use_shapelet_psf: bool = False, 

180 prior_axrat_stddev: float | str | None = None, 

181 ): 

182 """Apply runtime configuration changes to this config. 

183 

184 Parameters 

185 ---------- 

186 add_point_source 

187 Whether to add a point source component. 

188 fix_centroid 

189 Whether to fix the centroid. 

190 use_shapelet_psf 

191 Whether to initialize PSF parameters from prior shapelet fits. 

192 prior_axrat_stddev 

193 The standard deviation for the axis ratio prior. Ignored if None, 

194 otherwise it must be convertible to a float. 

195 """ 

196 if add_point_source: 

197 self.add_point_source() 

198 if fix_centroid: 

199 self.fix_centroid() 

200 if use_shapelet_psf: 

201 self.use_shapelet_psf() 

202 if prior_axrat_stddev is not None: 

203 self.set_prior_axrat_stddev(float(prior_axrat_stddev)) 

204 

205 def fix_centroid(self): 

206 """Fix (freeze) the source centroid parameters.""" 

207 group = self._get_component_group() 

208 centroids = group.centroids["default"] 

209 centroids.x.fixed = True 

210 centroids.y.fixed = True 

211 self.connections.name_table += model_names_default.fixed_cen 

212 

213 @classmethod 

214 @abstractmethod 

215 def get_model_name_default(cls) -> str: 

216 """Return the default name for this model in table columns.""" 

217 raise NotImplementedError("Subclasses must implement get_model_name_default") 

218 

219 @classmethod 

220 def get_model_name_full(cls) -> str: 

221 """Return a longer, more descriptive name for the model.""" 

222 return cls.get_model_name_default() 

223 

224 @abstractmethod 

225 def make_default_model_config(self) -> ModelConfig: 

226 """Make a default configuration object for this model.""" 

227 raise NotImplementedError("Subclasses must implement make_default_model_config") 

228 

229 @staticmethod 

230 def make_point_source_component() -> GaussianComponentConfig: 

231 """Make a point source component config (zero-size Gaussian).""" 

232 return GaussianComponentConfig( 

233 size_x=ParameterConfig(value_initial=0.0, fixed=True), 

234 size_y=ParameterConfig(value_initial=0.0, fixed=True), 

235 rho=ParameterConfig(value_initial=0.0, fixed=True), 

236 ) 

237 

238 @staticmethod 

239 def make_sersic_component(**kwargs) -> SersicComponentConfig: 

240 """Make a default Sersic component config. 

241 

242 Parameters 

243 ---------- 

244 **kwargs 

245 Keyword arguments to pass to the SersicIndexParameterConfig. 

246 

247 Returns 

248 ------- 

249 config 

250 The default-initialized config. 

251 """ 

252 return SersicComponentConfig( 

253 prior_axrat_stddev=1.0, 

254 prior_size_stddev=0.2, 

255 sersic_index=SersicIndexParameterConfig(**kwargs), 

256 ) 

257 

258 @staticmethod 

259 def make_single_model_config(group: ComponentGroupConfig) -> ModelConfig: 

260 """Make a default single-source, single component group config. 

261 

262 Parameters 

263 ---------- 

264 group 

265 The component group config for the single source. 

266 

267 Returns 

268 ------- 

269 config 

270 A model config with a single nameless source and component group. 

271 """ 

272 return ModelConfig( 

273 sources={ 

274 "": SourceConfig( 

275 component_groups={ 

276 "": group, 

277 } 

278 ) 

279 } 

280 ) 

281 

282 def set_prior_axrat_stddev(self, stddev: float) -> None: 

283 """Set the standard deviation for all axis ratio priors. 

284 

285 Parameters 

286 ---------- 

287 stddev 

288 The standard deviation. 

289 """ 

290 for source in self.fit_coadd_multiband.config_model.sources.values(): 

291 for group in source.component_groups.values(): 

292 for comp in itertools.chain( 

293 group.components_gauss.values(), 

294 group.components_sersic.values(), 

295 ): 

296 comp.prior_axrat_stddev = stddev 

297 

298 group = self._get_component_group() 

299 centroids = group.centroids["default"] 

300 centroids.x.fixed = True 

301 centroids.y.fixed = True 

302 self.connections.name_table += model_names_default.fixed_cen 

303 

304 def setDefaults(self): 

305 super().setDefaults() 

306 self.fit_coadd_multiband.retarget(MultiProFitSourceTask) 

307 self.fit_coadd_multiband.action_psf = PsfComponentsActionBase() 

308 self.fit_coadd_multiband.bands_fit = ("u", "g", "r", "i", "z", "y") 

309 

310 self.fit_coadd_multiband.config_model = self.make_default_model_config() 

311 self.name_model = self.get_model_name_default() 

312 self.connections.name_table = self.name_model 

313 

314 def use_shapelet_psf(self): 

315 """Reconfigure self to use prior shapelet PSF fit parameters.""" 

316 self.fit_coadd_multiband.action_psf = SourceTablePsfComponentsAction() 

317 self.drop_psf_connection = True 

318 self.connections.name_table += model_names_default.shapelet_psf 

319 

320 

321class MultiProFitCoaddObjectFitTask(CoaddMultibandFitTask): 

322 """MultiProFit coadd object model fitting task.""" 

323 

324 ConfigClass = MultiProFitCoaddObjectFitConfig 

325 _DefaultName = "multiProFitCoaddObjectFit" 

326 

327 def make_kwargs(self, butlerQC, inputRefs, inputs): 

328 inputs_init = {} 

329 for name, config in self.config.inputs_init.items(): 

330 input_ = inputs[name][0] 

331 if isinstance(input_, DeferredDatasetHandle): 

332 parameters = None 

333 if config.needs_metadata: 

334 parameters = {"strip_astropy_meta_yaml": False} 

335 input_ = input_.get(parameters=parameters) 

336 

337 inputs_init[name] = (config, input_) 

338 

339 kwargs = {} 

340 if inputs_init: 

341 kwargs["inputs_init"] = inputs_init 

342 

343 return kwargs 

344 

345 

346class MultiProFitCoaddPointFitConfig( 

347 MultiProFitCoaddObjectFitConfig, 

348 pipelineConnections=MultiProFitCoaddObjectFitConnections, 

349): 

350 """MultiProFit single Sersic model fit task config.""" 

351 

352 @classmethod 

353 def get_model_name_default(cls) -> str: 

354 return model_names_default.point 

355 

356 @classmethod 

357 def get_model_name_full(cls) -> str: 

358 return "Point Source" 

359 

360 def make_default_model_config(self) -> ModelConfig: 

361 config_group = ComponentGroupConfig() 

362 # This is a bit silly but add_point_source will look for the first 

363 # source so it must be added now. Perhaps add_point_source should 

364 # add to a config instance or only self by default 

365 self.fit_coadd_multiband.config_model = self.make_single_model_config(group=config_group) 

366 self.add_point_source() 

367 return self.fit_coadd_multiband.config_model 

368 

369 

370class MultiProFitCoaddSersicFitConfig( 

371 MultiProFitCoaddObjectFitConfig, 

372 pipelineConnections=MultiProFitCoaddObjectFitConnections, 

373): 

374 """MultiProFit single Sersic model fit task config.""" 

375 

376 def _rename_defaults( 

377 self, 

378 name_new: str, 

379 name_model: str | None = None, 

380 name_old: str | None = None, 

381 index_new: float | None = None, 

382 fix_index: bool = False, 

383 ): 

384 """Rename the default Sersic component to something more specific. 

385 

386 This is intended for fixed index models such as exponential and 

387 deVaucouleurs. 

388 

389 Parameters 

390 ---------- 

391 name_new 

392 The new name for the component. 

393 name_model 

394 The new name of the model. Default is to capitalize name_new. 

395 name_old 

396 The old name of the component. Default is to set to 

397 component_names_default.sersic. 

398 index_new 

399 The initial value for the Sersic index. 

400 fix_index 

401 Whether the fix the index to the new value. 

402 """ 

403 if name_old is None: 403 ↛ 405line 403 didn't jump to line 405 because the condition on line 403 was always true

404 name_old = component_names_default.sersic 

405 if name_model is None: 405 ↛ 406line 405 didn't jump to line 406 because the condition on line 405 was never true

406 name_model = name_new.capitalize() 

407 group = self._get_component_group() 

408 comps_sersic = group.components_sersic 

409 

410 if name_new in comps_sersic: 410 ↛ 411line 410 didn't jump to line 411 because the condition on line 410 was never true

411 raise RuntimeError(f"{name_new=} is already in {comps_sersic=}") 

412 

413 comp_sersic = comps_sersic[name_old] 

414 del comps_sersic[name_old] 

415 if index_new is not None: 415 ↛ 417line 415 didn't jump to line 417 because the condition on line 415 was always true

416 comp_sersic.sersic_index.value_initial = index_new 

417 if fix_index: 417 ↛ 419line 417 didn't jump to line 419 because the condition on line 417 was always true

418 comp_sersic.sersic_index.fixed = True 

419 comps_sersic[name_new] = comp_sersic 

420 

421 if prior_old := self.fit_coadd_multiband.size_priors.get(name_old): 421 ↛ 425line 421 didn't jump to line 425 because the condition on line 421 was always true

422 self.fit_coadd_multiband.size_priors[name_new] = prior_old 

423 del self.fit_coadd_multiband.size_priors[name_old] 

424 

425 self.name_model = name_model 

426 self.connections.name_table = name_model 

427 

428 @classmethod 

429 def get_model_name_default(cls) -> str: 

430 return model_names_default.sersic 

431 

432 @classmethod 

433 def get_model_name_full(cls) -> str: 

434 return "Sersic" 

435 

436 def make_default_model_config(self) -> ModelConfig: 

437 config_group = ComponentGroupConfig( 

438 components_sersic={ 

439 component_names_default.sersic: self.make_sersic_component(), 

440 }, 

441 ) 

442 return self.make_single_model_config(group=config_group) 

443 

444 def setDefaults(self): 

445 super().setDefaults() 

446 # This is in pixels and based on DC2. See DM-46498 for details. 

447 self.fit_coadd_multiband.size_priors[component_names_default.sersic] = ( 

448 MagnitudeDependentSizePriorConfig( 

449 intercept_mag=22.6, 

450 slope_median_per_mag=-0.15, 

451 slope_stddev_per_mag=0, 

452 ) 

453 ) 

454 

455 

456class MultiProFitCoaddSersicFitTask(MultiProFitCoaddObjectFitTask): 

457 """MultiProFit single Sersic model fit task.""" 

458 

459 ConfigClass = MultiProFitCoaddSersicFitConfig 

460 _DefaultName = "multiProFitCoaddSersicFit" 

461 

462 

463class MultiProFitCoaddGaussFitConfig( 

464 MultiProFitCoaddSersicFitConfig, 

465 pipelineConnections=MultiProFitCoaddObjectFitConnections, 

466): 

467 """MultiProFit single Gaussian model fit task config.""" 

468 

469 @classmethod 

470 def get_model_name_default(cls) -> str: 

471 return model_names_default.gauss 

472 

473 @classmethod 

474 def get_model_name_full(cls) -> str: 

475 return "Gaussian" 

476 

477 def setDefaults(self): 

478 super().setDefaults() 

479 self._rename_defaults( 

480 name_new=component_names_default.gauss, 

481 name_model=model_names_default.gauss, 

482 index_new=0.5, 

483 fix_index=True, 

484 ) 

485 

486 

487class MultiProFitCoaddGaussFitTask(MultiProFitCoaddObjectFitTask): 

488 """MultiProFit single Gaussian model fit task.""" 

489 

490 ConfigClass = MultiProFitCoaddGaussFitConfig 

491 _DefaultName = "multiProFitCoaddGaussFit" 

492 

493 

494class MultiProFitCoaddExpFitConfig( 

495 MultiProFitCoaddSersicFitConfig, 

496 pipelineConnections=MultiProFitCoaddObjectFitConnections, 

497): 

498 """MultiProFit single exponential model fit task config.""" 

499 

500 @classmethod 

501 def get_model_name_default(cls) -> str: 

502 return model_names_default.exp 

503 

504 @classmethod 

505 def get_model_name_full(cls) -> str: 

506 return "Exponential" 

507 

508 def setDefaults(self): 

509 super().setDefaults() 

510 self._rename_defaults( 

511 name_new=component_names_default.exp, 

512 name_model=model_names_default.exp, 

513 index_new=1.0, 

514 fix_index=True, 

515 ) 

516 # These are typical values from DC2 and could/should be switched to a 

517 # more data-driven prior (from HSC?) 

518 prior_size = self.fit_coadd_multiband.size_priors[component_names_default.exp] 

519 prior_size.intercept_mag = 23.4 

520 prior_size.slope_median_per_mag = -0.14 

521 

522 

523class MultiProFitCoaddExpFitTask(MultiProFitCoaddObjectFitTask): 

524 """MultiProFit single exponential model fit task.""" 

525 

526 ConfigClass = MultiProFitCoaddExpFitConfig 

527 _DefaultName = "multiProFitCoaddExpFit" 

528 

529 

530class MultiProFitCoaddDeVFitConfig( 

531 MultiProFitCoaddSersicFitConfig, 

532 pipelineConnections=MultiProFitCoaddObjectFitConnections, 

533): 

534 """MultiProFit single DeVaucouleurs model fit task config.""" 

535 

536 @classmethod 

537 def get_model_name_default(cls) -> str: 

538 return model_names_default.deV 

539 

540 @classmethod 

541 def get_model_name_full(cls) -> str: 

542 return "de Vaucouleurs" 

543 

544 def setDefaults(self): 

545 super().setDefaults() 

546 self._rename_defaults( 

547 name_new=component_names_default.deV, 

548 name_model=model_names_default.deV, 

549 index_new=4.0, 

550 fix_index=True, 

551 ) 

552 # These are typical values from DC2 and could/should be switched to a 

553 # more data-driven prior (from HSC?). See DM-46498 for details. 

554 prior_size = self.fit_coadd_multiband.size_priors[component_names_default.deV] 

555 prior_size.intercept_mag = 21.2 

556 prior_size.slope_median_per_mag = -0.14 

557 

558 

559class MultiProFitCoaddDeVFitTask(MultiProFitCoaddObjectFitTask): 

560 """MultiProFit single DeVaucouleurs model fit task.""" 

561 

562 ConfigClass = MultiProFitCoaddDeVFitConfig 

563 _DefaultName = "multiProFitCoaddDeVFit" 

564 

565 

566class CachedChainedModelInitializer(CachedBasicModelInitializer): 

567 def get_centroid_and_shape( 

568 self, 

569 source: Mapping[str, Any], 

570 catexps: list[CatalogExposureSourcesABC], 

571 config_data: CatalogSourceFitterConfigData, 

572 values_init: Mapping[g2f.ParameterD, float] | None = None, 

573 ) -> tuple[tuple[float, float], tuple[float, float, float]]: 

574 row_best = None 

575 chisq_red_min = math.inf 

576 for name, input_data in self.inputs.items(): 

577 data = input_data.data 

578 index_row = input_data.id_index.get(source["id"]) 

579 if index_row is not None: 

580 row = data[index_row] 

581 chisq_red = input_data.get_column("chisq_reduced", data=row) 

582 if chisq_red < chisq_red_min: 

583 row_best = (row, input_data) 

584 chisq_red_min = chisq_red 

585 if row_best is None: 

586 return super().get_centroid_and_shape( 

587 source=source, 

588 catexps=catexps, 

589 config_data=config_data, 

590 values_init=values_init, 

591 ) 

592 row_best, input_data = row_best 

593 cen_x, cen_y, reff_x, reff_y, rho = ( 

594 input_data.get_column(column, data=row_best) 

595 for column in ( 

596 input_data.get_column("cen_x").name, 

597 input_data.get_column("cen_y").name, 

598 input_data.get_column(f"{input_data.size_column}_x").name, 

599 input_data.get_column(f"{input_data.size_column}_y").name, 

600 input_data.get_column("rho").name, 

601 ) 

602 ) 

603 return (cen_x, cen_y), (reff_x, reff_y, rho) 

604 

605 

606class MakeCachedChainedInitializerAction(MakeBasicInitializerAction): 

607 def _make_initializer( 

608 self, 

609 catalog_multi: Sequence, 

610 catexps: list[CatalogExposureInputs], 

611 config_data: CatalogSourceFitterConfigData, 

612 ) -> ModelInitializer: 

613 sources, priors = config_data.sources_priors 

614 return CachedChainedModelInitializer(config=self.config, priors=priors, sources=sources) 

615 

616 

617class MultiProFitCoaddExpDeVFitConfig( 

618 MultiProFitCoaddObjectFitConfig, 

619 pipelineConnections=MultiProFitCoaddObjectFitConnections, 

620): 

621 """MultiProFit single Exponential+DeVaucouleurs model fit task config.""" 

622 

623 @classmethod 

624 def get_model_name_default(cls) -> str: 

625 return f"{model_names_default.exp}{model_names_default.deV}" 

626 

627 @classmethod 

628 def get_model_name_full(cls) -> str: 

629 return "Exponential + de Vaucouleurs" 

630 

631 def make_default_model_config(self) -> ModelConfig: 

632 config_group = ComponentGroupConfig( 

633 components_sersic={ 

634 component_names_default.exp: self.make_sersic_component(value_initial=1.0, fixed=True), 

635 component_names_default.deV: self.make_sersic_component(value_initial=4.0, fixed=True), 

636 }, 

637 ) 

638 return self.make_single_model_config(group=config_group) 

639 

640 def setDefaults(self): 

641 super().setDefaults() 

642 self.fit_coadd_multiband.action_initializer = MakeCachedChainedInitializerAction() 

643 self.fit_coadd_multiband.config_model = self.make_default_model_config() 

644 self.name_model = self.get_model_name_default() 

645 self.connections.name_table = self.name_model 

646 

647 size_priors = self.fit_coadd_multiband.size_priors 

648 size_priors[component_names_default.exp] = MagnitudeDependentSizePriorConfig( 

649 intercept_mag=23.3, 

650 slope_median_per_mag=-0.14, 

651 ) 

652 size_priors[component_names_default.deV] = MagnitudeDependentSizePriorConfig( 

653 intercept_mag=21.2, 

654 slope_median_per_mag=-0.14, 

655 ) 

656 

657 

658class MultiProFitCoaddExpDeVFitTask(MultiProFitCoaddObjectFitTask): 

659 """MultiProFit single ExpDeV model fit task.""" 

660 

661 ConfigClass = MultiProFitCoaddExpDeVFitConfig 

662 _DefaultName = "multiProFitCoaddExpDeVFit"