Repository navigation
Add QDP data file handling - #11256
Conversation
|
Hello @matteobachetti 👋! It looks like you've made some changes in your pull request, so I've checked the code again for style. There are no PEP8 style issues with this pull request - thanks! 🎉 Comment last updated at 2021-04-08 11:55:44 UTC |
embray
left a comment
There was a problem hiding this comment.
This is helpful for understanding how this file format is interpreted and the code is very well formatted. I think it can be simplified though.
| if input_colnames is None or len(input_colnames) == ncol: | ||
| colnames = interpret_err_lines( | ||
| err_specs, ncol, input_colnames=input_colnames | ||
| ) |
There was a problem hiding this comment.
I don't really understand what this is doing. Is it initializing the err_specs data structure?
There was a problem hiding this comment.
It is reading err_specs and understanding if some columns represent the uncertainty of others. Main column are named col1, col2, ... or whatever the user gives (e.g. MJD, Rate). Error column are named col0_err (or MJD_err) for symmetric error, col0_perr and col0_nerr for positive/negative error
There was a problem hiding this comment.
I do this once at the start of the file, assuming that err_specs is empty, for the case where the file does not contain the READ [ST]ERR commands. This gets overwritten when these commands are found.
|
I don't understand what is happening in those failed tests. It looks like the logger got confused, but only in one test case :O |
taldcroft
left a comment
There was a problem hiding this comment.
@matteobachetti - thanks, this will be a nice addition!
One thing that is going to complicate matters is that this should really be made part of io.ascii. The QDP format is very much an ASCII table format so it should live in that subpackage and support the user doing ascii.read('data.qdp', format='qdp', names=['x', 'y', 'z']). The machinery in io.ascii is a bit orthogonal to the way you've written this so far. If you just take the first step of moving it into io.ascii I can help with getting it to fit in.
|
Hi @taldcroft, I started moving things around. Alas, while the |
Yes. The It looks like you moved the code around. Are there other changes you are planning? |
Not until I understand a little more :). I drafted a couple of classes based on the functionality in |
The delimiter |
|
@taldcroft I don't understand how to make |
|
@matteobachetti - I pushed a commit that seems to do the trick. One comment, can you use |
|
Thanks! I'll change the keyword to |
|
There are a few flake8 issues that should be cleaned up: |
| self.input_colnames = input_colnames | ||
|
|
||
| def read(self, qdp_file): | ||
| return read_table_qdp(qdp_file, table_id=self.table_id, |
There was a problem hiding this comment.
Another key point for API consistency is to allow the input to be a filename, a string with the data, a list of strings or a file object. This is normally done using the following:
# Get a list of the lines (rows) in the table
self.lines = self.inputter.get_lines(table, newline=newline)
Then the core table parsing should always expect a list of lines. I see you have support for providing the table data as a string, though this is not obvious from the docstrings.
To go 100% in the style of io.ascii, the standalone routines like read_table_qdp would not be considered part of the public API and then you would rewrite that function and all the downstream ones to accept only a list of lines.
Another option is to adapt get_lines_from_file to support the standard input options.
|
@taldcroft next: I'm trying to supersede the write interface, but I don't understand how to do that. I commented out my definition of write so that tests pass, but at the moment the interface isn't able to write proper QDP files (with SERR/TERR instructions) |
|
@taldcroft, I just noticed that you reviewed the code while I was making the last modifications. I'll work on your comments. Thanks! |
|
More changes (I made these locally for testing): The |
|
@taldcroft thanks a lot for your thorough review until now, I think I addressed all of your comments :) |
|
There is a failure I don't understand. Aren't warnings allowed? |
|
@matteobachetti - uncaught warnings are not allowed in testing, they are converted to errors as you've seen. Using https://docs.pytest.org/en/stable/warnings.html#recwarn you need to catch them and test that the expected warning got emitted. |
|
@taldcroft But I do test it, in test_qdp.py. This error comes from the generic test in test_write.py. I guess this assumes that ascii readers don't emit warnings with default values, but in this case, this reader is made for files that can contain multiple tables, and it has to warn the user if the user does not specify which table to read. |
|
@matteobachetti - you can put in some special-case handling for the |
|
@taldcroft I don't think the failure has to do with my PR, so whenever you want, this is ready for review. |
taldcroft
left a comment
There was a problem hiding this comment.
@matteobachetti - I took another pass and there are just docs and minor test issues to be fixed. One key thing is that you need to rebase on current master and update this to reflect the new change log system. See emails to astropy-dev (ANN: astropy plans to switch to towncrier for changelog management), in particular the one from Simon that talks about how to fix existing PRs. Hopefully the rebase will fix the CI failure as well.
Welcome to astropy development, it's never quite easy! 😄
| assert np.ma.is_masked(t['b'][0]) | ||
| assert np.isnan(t['d'][1]) | ||
|
|
||
| t.values_equal(dat) |
There was a problem hiding this comment.
You need to check that all the values are actually equal:
for col_equal in t.values_equal(dat).itercols():
assert np.all(col_equal)
But it turns out that doesn't work because of the nan, so you need instead:
for col1, col2 in zip(t.itercols(), dat.itercols()):
assert np.isclose(col1, col2, nan_equal=True)
| t.write(test_file, err_specs={'terr': [1], 'serr': [3]}) | ||
| t2 = Table.read(test_file, names=['a', 'b', 'c', 'd'], table_id=0) | ||
|
|
||
| t.values_equal(t2) |
| t.write(test_file, err_specs={'terr': [1], 'serr': [3]}) | ||
| t2 = Table.read(test_file, names=['a', 'b', 'c', 'd'], table_id=0) | ||
|
|
||
| t.values_equal(t2) |
| return lines | ||
|
|
||
|
|
||
| # def _analyze_qdp_file(qdp_file): |
There was a problem hiding this comment.
Remove this commented-out function if it's not needed.
|
|
||
| Parameters | ||
| ---------- | ||
| err_specs : dict, {'serr': [n0, n1, ...], 'terr': [n2, n3, ...]} |
There was a problem hiding this comment.
The top line should just be err_specs : dict (i.e. only specify the type) with the details in the next line.
See https://github.com/astropy/astropy/pull/11118/files for examples of where this is coming from.
|
|
||
| Other parameters | ||
| ---------------- | ||
| names : list of strings |
|
|
||
| Returns | ||
| ------- | ||
| tables : list of `Table` objects |
There was a problem hiding this comment.
list of `~astropy.table.Table`
| Number of the table to be read from the QDP file. This is useful | ||
| when multiple tables present in the file. By default, the first is read. | ||
|
|
||
| names : list of strings |
There was a problem hiding this comment.
Docstring parameters should have the same order as in the function. Also, list of str
|
|
||
| Returns | ||
| ------- | ||
| tables : list of `Table` objects |
There was a problem hiding this comment.
list of `~astropy.table.Table`
|
|
||
|
|
||
| class QDP(basic.Basic): | ||
| """QDP table. |
There was a problem hiding this comment.
This main docstring should be expanded to illustrate the available parameters and usage. This will be the only way people know about the header_id, err_specs etc. For a good example see the following that shows a full example of the file format and how to read. You can also include a write example.
astropy/astropy/io/ascii/daophot.py
Line 315 in 1ed1d94
|
@taldcroft should be done, including the rebase. I'm not sure the CHANGES.rst file is correct after rebase though. |
|
We don't use |
|
@saimn , is squashing necessary here to change the changelog ? |
|
The failures should be unrelated. The failing test is about a config file, and unit tests were passing up until 04db56e (the only failure was from readthedocs, bad formatting of a docstring) |
|
That is weird (the config failure). Luckily, that test is getting removed in #10877 . Unluckily, it failing is blocking the rest of the jobs for you. |
No, just revert the changes in |
|
Update: CI is fixed now. A rebase would help. FYI |
|
@pllim @taldcroft I renamed my fork's |
|
Due to the trial-and-error path I followed and the initial proposed addition to |
|
Yes squashing the commits would be good, maybe even down to just one. |
|
@taldcroft I tried to preserve the main "building blocks" of this PR, while discarding the initial io.misc interface. It's a quite big rebase, hope it works :D |
taldcroft
left a comment
There was a problem hiding this comment.
@matteobachetti - looks great now, thanks for all the hard work and perseverance!
Description
This pull request is to address Issue #8382, adding QDP data handling.
Fixes #8382