Conversation
…ated by model_type
There was a problem hiding this comment.
Pull request overview
Adds a new polynomial-based pointing residual model to Mapcat and updates persistence/tests to support storing/retrieving this new model type alongside the existing constant model.
Changes:
- Introduces
PolynomialPointingModelwith coefficient fitting, prediction, and basic statistics helpers. - Updates
PointingResidualTable.residual_modelto store either a constant or polynomial model via JSON (TypeAdapter-backed deserialization). - Expands pointing tests to cover constant-model behavior and basic polynomial fitting/prediction.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
tests/test_pointing.py |
Updates unit imports and adds tests for constant and polynomial pointing models. |
mapcat/pointing/poly.py |
New polynomial pointing model implementation (fit + predict + stats). |
mapcat/pointing/const.py |
Adjusts ConstantPointingModel.predict to subtract offsets. |
mapcat/database/pointing_residual.py |
Allows storing either constant or polynomial pointing model in residual_model. |
mapcat/database/json.py |
Switches JSON deserialization to Pydantic TypeAdapter (enables unions). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def predict(self, pos: SkyCoord) -> SkyCoord: | ||
| racoeffs,deccoeffs = self.extract_coefficients() | ||
| ra_offset = self.model_fn(pos.ra, pos.dec, racoeffs)[0] | ||
| dec_offset = self.model_fn(pos.ra, pos.dec, deccoeffs)[0] | ||
| ra = pos.ra - ra_offset |
JBorrow
left a comment
There was a problem hiding this comment.
Some minor comments. It seems kinda overcomplicated for a polynomial model but that's ok. Is there a reason we can't just use https://numpy.org/doc/stable/reference/generated/numpy.polyfit.html
| from .depth_one_map import DepthOneMapTable | ||
| from .json import JSONEncodedPydantic |
There was a problem hiding this comment.
Looks like you need to run ruff check
| from .depth_one_map import DepthOneMapTable | ||
| from .json import JSONEncodedPydantic | ||
|
|
||
| PointingModel = Union[ConstantPointingModel, PolynomialPointingModel] |
There was a problem hiding this comment.
PointingModel = ConstantPointingModel | PolynomialPointingModel is apparently the way to go
| def calculate_model(self, | ||
| measured_positions: SkyCoord, | ||
| expected_positions: SkyCoord, | ||
| position_uncertainty: tuple[u.Quantity, u.Quantity] | u.Quantity | None = None, | ||
| weights: tuple[list[float], list[float]] | list[float] | None = None | ||
| ) -> SkyCoord: |
There was a problem hiding this comment.
This looks like it needs to be formatted lmao
| # Lots of logic to check if weights exist, etc. | ||
| # Resolve weights from uncertainties if not provided | ||
| if ra_weights is None and dec_weights is None: | ||
| if ra_uncerts is not None and dec_uncerts is not None: | ||
| ra_weights = dec_weights = 1 / np.sqrt(ra_uncerts**2 + dec_uncerts**2) | ||
| elif ra_uncerts is not None: | ||
| dec_uncerts = np.ones(n) * np.mean(ra_uncerts) | ||
| ra_weights = dec_weights = 1 / np.sqrt(ra_uncerts**2 + dec_uncerts**2) | ||
| elif dec_uncerts is not None: | ||
| ra_uncerts = np.ones(n) * np.mean(dec_uncerts) | ||
| ra_weights = dec_weights = 1 / np.sqrt(ra_uncerts**2 + dec_uncerts**2) | ||
| else: | ||
| # No uncertainty or weights provided — uniform | ||
| ra_weights = dec_weights = np.ones(n) | ||
| elif ra_weights is None: | ||
| ra_weights = dec_weights | ||
| elif dec_weights is None: | ||
| dec_weights = ra_weights |
| keys.append(f"x^{i}y^{j}") | ||
| return keys | ||
|
|
||
| def calculate_model(self, |
There was a problem hiding this comment.
Is calculate model here more of a... build model? Calculate is kinda ambiguous in train/apply. I'd prefer train_model or build_model or something.
add the polynomial pointing model to mapcat