2929from functools import cache
3030from typing import Any
3131
32- import astropy .io .votable
33- import astropy .table
32+ import astropy .io .votable .tree
3433import felis .datamodel
3534import pyarrow
3635import sqlalchemy
@@ -319,15 +318,43 @@ def to_votable(self, limit: int | None = None) -> astropy.io.votable.tree.VOTabl
319318 if doc := getattr (column , "doc" ): # noqa
320319 extra_descriptions [name ] = doc
321320
322- votable = astropy .io .votable .tree .VOTableFile ()
323- resource = astropy .io .votable .tree .Resource ()
321+ # Astropy <= 7.1 has a bug whereby it internally does not know its
322+ # own version and so disallows some options. For now we have to use
323+ # an internal API to assign the internal config. Otherwise certain
324+ # elements can not be specified.
325+ # Being fixed in https://github.com/astropy/astropy/pull/18366
326+ votable = astropy .io .votable .tree .VOTableFile (version = "1.5" )
327+ votable_config = votable ._get_version_checks ()
328+ resource = astropy .io .votable .tree .Resource (config = votable_config )
329+ coosys_id = "coosys"
330+ resource .coordinate_systems .append (
331+ astropy .io .votable .tree .CooSys (
332+ system = "ICRS" , refposition = "TOPOCENTER" , ID = coosys_id , config = votable_config
333+ )
334+ )
335+ timesys_id = "timesys"
336+ resource .time_systems .append (
337+ astropy .io .votable .tree .TimeSys (
338+ timeorigin = "MJD-origin" ,
339+ timescale = "UTC" ,
340+ refposition = "TOPOCENTER" ,
341+ ID = timesys_id ,
342+ config = votable_config ,
343+ )
344+ )
324345 votable .resources .append (resource )
325346
326347 fields = []
327348 for arrow_field in self .schema :
328349 if arrow_field .name in obscore_columns :
329350 ffield = obscore_columns [arrow_field .name ]
330351 votable_datatype = felis .datamodel .FelisType .felis_type (ffield .datatype .value ).votable_name
352+ refargs = {}
353+ if ivoa_ucd := ffield .ivoa_ucd :
354+ if ivoa_ucd .startswith ("pos.eq" ) or ivoa_ucd .startswith ("pos.outline" ):
355+ refargs ["ref" ] = coosys_id
356+ elif ivoa_ucd .startswith ("time.start" ) or ivoa_ucd .startswith ("time.end" ):
357+ refargs ["ref" ] = timesys_id
331358 field = astropy .io .votable .tree .Field (
332359 votable ,
333360 name = ffield .name ,
@@ -336,6 +363,7 @@ def to_votable(self, limit: int | None = None) -> astropy.io.votable.tree.VOTabl
336363 unit = ffield .ivoa_unit ,
337364 ucd = ffield .ivoa_ucd ,
338365 utype = ffield .votable_utype ,
366+ ** refargs ,
339367 )
340368 if ffield .description :
341369 field .description = ffield .description
@@ -377,7 +405,9 @@ def to_votable(self, limit: int | None = None) -> astropy.io.votable.tree.VOTabl
377405 field .description = extra_descriptions [arrow_field .name ]
378406 fields .append (field )
379407
380- table0 = astropy .io .votable .tree .TableElement (votable )
408+ # Config parameter is needed until upstream inherits the config from
409+ # the VOTableFile. Without this BINARY2 will not be allowed if needed.
410+ table0 = astropy .io .votable .tree .TableElement (votable , config = votable_config )
381411 resource .tables .append (table0 )
382412 table0 .fields .extend (fields )
383413
0 commit comments