Skip to content

Support reading and writing multidimensional columns in ECSV format - #11155

Closed
taldcroft wants to merge 10 commits into
astropy:masterfrom
taldcroft:ascii-serialize-nd-cols
Closed

taldcroft wants to merge 10 commits into
astropy:masterfrom
taldcroft:ascii-serialize-nd-cols

Conversation

@taldcroft

@taldcroft taldcroft commented Dec 8, 2020 •

Copy link
Copy Markdown
Member

Description

This pull request is to support reading and writing multidimensional columns in ECSV format.

This also does consistent checking of table column dimensions for all built-in ASCII formats and raises a useful error message for multidimensional columns for formats that cannot support it.

For instance the following will round-trip and give back the same N-d column.

In [6]: t = Table()                                                                                                                                       

In [7]: t['nd'] = np.arange(18).reshape(3, 2, 3)                                                                                                          

In [8]: ascii.write(t, format='ecsv')                                                                                                                     
# %ECSV 0.9
# ---
# datatype:
# - {name: nd.0_0, datatype: int64}
# - {name: nd.0_1, datatype: int64}
# - {name: nd.0_2, datatype: int64}
# - {name: nd.1_0, datatype: int64}
# - {name: nd.1_1, datatype: int64}
# - {name: nd.1_2, datatype: int64}
# meta: !!omap
# - __serialized_columns__:
#     nd:
#       '0_0': !astropy.table.SerializedColumn {name: nd.0_0}
#       '0_1': !astropy.table.SerializedColumn {name: nd.0_1}
#       '0_2': !astropy.table.SerializedColumn {name: nd.0_2}
#       '1_0': !astropy.table.SerializedColumn {name: nd.1_0}
#       '1_1': !astropy.table.SerializedColumn {name: nd.1_1}
#       '1_2': !astropy.table.SerializedColumn {name: nd.1_2}
#       __class__: astropy.table.column.Column
# schema: astropy-2.0
nd.0_0 nd.0_1 nd.0_2 nd.1_0 nd.1_1 nd.1_2
0 1 2 3 4 5
6 7 8 9 10 11
12 13 14 15 16 17

Fixes #11148

@taldcroft

taldcroft commented Dec 8, 2020 •

Copy link
Copy Markdown
Member Author

This doesn't work for N-d Quantity right now.

Comment thread astropy/io/ascii/ecsv.py Resolved
@taldcroft
taldcroft marked this pull request as draft December 10, 2020 15:22

@mhvk mhvk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a quick flyby of the draft: I like the approach! So far only a comment about a mistake in the comments...

Comment thread astropy/table/column.py Resolved
@taldcroft
taldcroft force-pushed the ascii-serialize-nd-cols branch from 4b8c811 to 2710bd3 Compare February 21, 2021 12:00
@taldcroft
taldcroft requested a review from mhvk February 21, 2021 14:04
@taldcroft

Copy link
Copy Markdown
Member Author

@mhvk - I rebased this and did a bit of touchup. I think this is ready for review now.

@taldcroft taldcroft left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mhvk - I made some comments that might help you a bit in review.

Comment thread CHANGES.rst
astropy.time
^^^^^^^^^^^^

- Add new time format ``unix_ptp`` (Precision Time Protocol) which provides

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, something went wrong in the rebase. Will fix.

import pytest
import numpy as np

from astropy.table import Table, Column, QTable, NdarrayMixin

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this file I refactored the serialization testing out to a new table module test_serialize. The goal is to unify such testing for FITS, HDF5 and ECSV. However this proved a little tricky on my first attempt so the refactor only currently applies to ECSV. In the context of this PR that should be OK?

"""
t = Table([np.arange(4).reshape(2, 2), [1, 2]], names=['a', 'b'])
t = Table()
t['a'] = np.arange(24).reshape(2, 3, 4)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Basic testing here, more comprehensive in test_serialize.py.

(for N > 1) by optionally turning it into the required number of 1-d
arrays (e.g. for ECSV or None context).

For instance a Column with shape (2, 2, 20) will turn into four columns

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will fix the (2, 2, 20) here.

ndarrays within a Table. This is a subclass of numpy.ndarray
and has the same initialization options as ndarray().
"""
__module__ = 'astropy.table.table'

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class definition is the same as the original that was taken out of table.py, with the exception of this line and the one below. I don't remember precisely what hacking the __module__ here was doing, but it might have been for the docs.


# Context types for which multidimensional data will be flattened to
# a list of 1-d arrays.
FLATTEN_MULTIDIM = ['ecsv']

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not clear if there will ever be another context that supports N-d serialization by flattening, but this seemed better than hardwiring 'ecsv' in the code.

Comment thread docs/io/ascii/write.rst

Creating a table with a `~astropy.coordinates.SkyCoord` column can be accomplished with a mixin
column, which is supported by `ECSV <https://docs.astropy.org/en/stable/api/astropy.io.ascii.Ecsv.html>`_. To store a mixin column::
Creating a table with a `~astropy.coordinates.SkyCoord` column can be

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a reformat for column width.

if not has_info_class(data, MixinInfo):
col_cls = MaskedColumn if (hasattr(data, 'mask')
and np.any(data.mask)) else Column
# TODO: I think the **info here is not really needed and tests pass

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nominally planning to leave this TODO for another time since the impact is trickier to understand.

else:
new_name = name + '.' + data_attr

# If the data attribute is not a Mixin (aka a Column or ndarray) and

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the core inner change that makes it all work.

class NdarrayMixinInfo(ParentDtypeInfo):
_represent_as_dict_primary_data = 'data'

def _represent_as_dict(self):

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is new.

@taldcroft

Copy link
Copy Markdown
Member Author

Parenthetical to astropy/astropy-APEs#64, I see the section below this change which discusses multidimensional columns. With this PR it might be possible to make that scheme part of the standard, though it does rely on a special column naming convention. This is unique if the serialized metadata are parsed, but that is outside of the standard currently.

@taldcroft

Copy link
Copy Markdown
Member Author

Closing in favor of ideas mentioned in #11368

@taldcroft taldcroft closed this Apr 4, 2021
@taldcroft
taldcroft deleted the ascii-serialize-nd-cols branch April 4, 2021 10:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ascii.write fails with nondescript error on structured (multi-D) columns

3 participants