-
-
Notifications
You must be signed in to change notification settings - Fork 54
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mivot writer #627
base: main
Are you sure you want to change the base?
Mivot writer #627
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #627 +/- ##
==========================================
+ Coverage 82.30% 82.93% +0.63%
==========================================
Files 72 75 +3
Lines 7430 7658 +228
==========================================
+ Hits 6115 6351 +236
+ Misses 1315 1307 -8 ☔ View full report in Codecov by Sentry. |
Forced pull after having squashed tiny commits dues to CI errors
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comments mostly focusing on documentation and on how the API is exposed.
docs/mivot/index.rst
Outdated
********************* | ||
MIVOT (``pyvo.mivo``) | ||
********************* |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
typo
********************* | |
MIVOT (``pyvo.mivo``) | |
********************* | |
********************** | |
MIVOT (``pyvo.mivot``) | |
********************** |
pyvo/mivot/writer/annotations.py
Outdated
blocks into VOTable files. The MIVOT block, represented as an XML structure, is used for | ||
data model annotations in the IVOA ecosystem. | ||
|
||
Features: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While I see the motivation for including some narrative docs with the source code, this section is not at all included in the rendered documentation as is not being part of any testing. So any information listed here likely need to be repeated and then kept in sync with the narrative docs. So my suggestion would be to remove the details from here and only have the narrative docs, as well as docstrings in any user facing functionality.
MIVOT items put together.
default pyvo.mivot content code stye add license
optional with mandatory keyword
The 3.11 step failed on a Simbad TAP server error |
The simbad failure is unrelated and I see it in This is ready for review for @astropy/pyvo-maintainers |
(on the current SIMBAD list of tables failure, the new table |
docs/mivot/index.rst
Outdated
|
||
This module contains the new feature of annotations in VOTable. | ||
This module contains the new feature handling model annotations in VOTable. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sounds better IMO.
This module contains the new feature handling model annotations in VOTable. | |
This module contains the new feature of handling model annotations in VOTable. |
- MIVOT module: If the MIVOT annotation block contains a valid instance of the | ||
``mango:EpochPosition`` class, the dynamic object describing the mapped | ||
data can generate a valid SkyCoord instance. [#591] | ||
|
||
- RegTAP constraints involving tables other than rr.resource are now |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering what happened here since this is not your change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not understand the issue, this relates to 1.6.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering what happened here since this is not your change.
a rebase or merge conflict resolution went wrong
docs/mivot/viewer.rst
Outdated
------------------ | ||
The ``ModelViewer`` module manages access to data mapped to a model through dynamically | ||
generated objects (``MivotInstance``class). | ||
The example below shows how can be consumed a VOTable resulting from a cone-search query which data are mapped |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The example below shows how can be consumed a VOTable resulting from a cone-search query which data are mapped | |
The example below shows how a VOTable result of a cone-search query can be parsed and data mapped |
docs/mivot/viewer.rst
Outdated
xml_view = mivot_viewer.xml_view | ||
# do whatever you want with this XML element | ||
|
||
It to be noted that ``mivot_viewer.xml_view`` is a shortcut |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It to be noted that ``mivot_viewer.xml_view`` is a shortcut | |
It is to be noted that ``mivot_viewer.xml_view`` is a shortcut |
value="BARYCENTER", | ||
) | ||
space_frame.add_instance(ref_position) | ||
space_sys.add_instance(space_frame) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like this is too low level API for it to gain traction. My idea of this (as I probably mentioned to you in the past) would be to have the supported models part of this library. Users only have to define the mapping to the column names, maybe the units and the global values and a utility generates the corresponding json that goes into the header and the rest of the result content is streamed from the database. The utility can take an optional VOTable header to check if the columns in the mapping exist in the table. But all the other details (dmrole, dmtype, etc) are internal to the Model classes and not exposed to the user.
I would have preferred a simple example of a writer for SkyCoords where a utility requires the mapping of SkyCoords fields to column names but can generate the other details the MIVOT uses. Can that be a goal? Is it possible to implement?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Providing a user-friendly API is the final goal of this work but it requires a low-level API allowing to build annotations step by step which is the object of this PR.
I've another PR on the track allowing to add in one callback time frames, space frames and photometric filters, defined as instances of classes of Coordinates DM and PhotDM respectively.
I propose to first merge this incoming work with #627, but this not enough to build annotations on the fly as you suggest.
I'll add another endpoint(s) allowing to add MANGO objects even if MANGO is not a REC yet. I assume that possible requested changes won't alter too much the code.
I propose to start with the 6 parameters EpochPosition, the Brightness (mag or flux) and the Color.
The API will look like:
votable = parse(votable_path)
annotations = Annotation()
annotations.add_epoch_propagation(sky_position, space_frame, time_frame, correlation, errors)
# something similar for the magnitude/color
annotations.build_mivot_block()
annotations.insert_into_votable(votable)
- the parameters of
add_epoch_propagation
are basically dictionaries containing tuples connecting model leaves with columns identifiers or literal values. - this API could be extended with an automatic column discovery at least for columns having unambiguous UCDs
This work will take a bit of time however.
If you agree, the PR can be frozen meanwhile it is merged with that future code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. It makes sense. Maybe just mention in the documentation that this is intended for developers of DM classes that want them to be annotated to VOTables and not for the end users.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@andamian - I believe all your comments have been addressed. Do you think it's good to go now?
When it gets the green light, I'll go ahead and rebase to get rid of the merge commits and the weirdness in the changelog.
- MIVOT module: If the MIVOT annotation block contains a valid instance of the | ||
``mango:EpochPosition`` class, the dynamic object describing the mapped | ||
data can generate a valid SkyCoord instance. [#591] | ||
|
||
- RegTAP constraints involving tables other than rr.resource are now |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering what happened here since this is not your change.
a rebase or merge conflict resolution went wrong
try: | ||
from astropy.io.votable.tree import MivotBlock | ||
except ImportError: | ||
pass |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe add a comment here that this try/except should go away once we don't need to do check_astropy_version and require astropy >=6.0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry. I've had these comments on Pending - just forgot to submit review. I'm doing it now.
@@ -1,2 +1 @@ | |||
# package entry point | |||
from .viewer.mivot_viewer import MivotViewer |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this because MivotViewer
is not part of the user facing API and just meant for library developers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I now have 2 different features (read and write). I thought it was better to put the default imports at sub-package level (viewer, writer).
I took example on pyvo.io.
Is that not correct?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I let it as it is
pyvo/mivot/writer/annotations.py
Outdated
|
||
Attributes | ||
---------- | ||
_models : dict |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are all private attributes. Document them online when they are declared maybe?
""" | ||
return self._mivot_block | ||
|
||
def _get_report(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't all MIVOT components represented by classes should have _to_xml
methods to get their representations? It might be more consistent and easier to remember. Just a suggestion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This method just returns one component of the MIVOT block: <REPORT...\>
as do the following ones for MODELS/GLOBALS/TEMPLATES.
_to_xml
is used for model components such as <INSTANCE>
These methods are used internally to pack the MIVOT block.
I can add add an _xml
in their names (e.g. _get_xml_report
) if you think it will make the code more clear but in my opinion this not a good option because these methods return strings not XML elements (etree).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I let it as it is.
@@ -0,0 +1,160 @@ | |||
# Licensed under a 3-clause BSD style license - see LICENSE.rst | |||
""" | |||
MivotInstance is a simple API for building MIVOT instances step by step. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you detail in the description what a MIVOT instance is?
pyvo/mivot/writer/instance.py
Outdated
Free identifier of the instance | ||
|
||
""" | ||
def __init__(self, dmtype=None, *, dmrole=None, dmid=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If dmtype
is required it shouldn't have a default.
""" | ||
if not dmtype: | ||
raise MappingError("Cannot build an instance without dmtype") | ||
self._dmtype = dmtype |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I invite the others to chime in but I've started using a rule that we are using in Java. If the ctor argument is required, then the corresponding class attribute is read-only and uses a property to enforce that. If it's optional, then it's a read/write attribute and the attribute should be public. In the case above:
def __init__(self, dmtype, *, dmrole=None, dmid=None):
self._dmtype = dmtype # check dmtype is correct
self.dmrole = droll
self dmid = dmid
@property
def dmtype(self):
return self._dmtype
'''
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm using this pattern for read-only properties (e.g. MivotAnnotation.mivot_block
) but in this case, all the class attributes are set at instantiation time are not meant to changed later or even read from outside (apart of the tests).
Do you think it worth it to add getters for them?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Probably not. Only for those that the caller might need access to.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I let it as it is
API for creating and writing MIVOTY annotation
#. Create individual instances (INSTANCE) using the
MivotInstance
class#. Wrap the annotations with the
MivotAnnotations
class#. Insert the annotations into a VOtable by using the Astropy API (wrapped in the package logic).
The annotation builder does not check whether the XML conforms to any particular model.
It simply validates it against the MIVOT XML Schema if the
xmlvalidator
package if is installed.The documentation has been split in 2 separate sections (reading and writing MIVOT)