-
Notifications
You must be signed in to change notification settings - Fork 13
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
WIP skip over ValueError in _time_reduce #242
Conversation
49861d8
to
1a5594c
Compare
1a5594c
to
cdae831
Compare
cdae831
to
f767c0b
Compare
@spencerahill @spencerkclark Let me know what you guys think about the pr. |
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.
@micahkim23 this looks great so far! It would be great if you could add some tests for this new logic.
I would probably start by creating a variable that was not defined in time in our test object library: https://github.com/spencerahill/aospy/blob/develop/aospy/test/data/objects/examples.py. Then I would write tests to see if the time reductions were skipped when using CalcSuite
and that new variable, and if an error was raised if a standalone Calc
object was created using that variable that included time reductions in dtype_out_time
. The tests would probably be best placed in test_automate.py
and test_calc_basic.py
.
aospy/calc.py
Outdated
msg = ("Var {0} has no time dimension " | ||
"for the given time reduction " | ||
"{1}".format(var.name, reduction)) | ||
logging.info(msg) |
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.
Per #202 (comment), let's raise an exception here instead of just logging a message (probably a ValueError
is appropriate here).
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.
for testing, are the only possible values for dtype_out_time
: None
, some subset of ['av', 'std, 'ts', 'reg.av', 'reg.std', 'reg.ts', 'None']
, or individual strings of: 'av', 'std, 'ts', 'reg.av', 'reg.std', 'reg.ts', '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.
Yes 👍
specs = self._combine_core_aux_specs() | ||
|
||
for spec in specs: | ||
spec['dtype_out_time'] = _prune_invalid_time_reductions(spec) |
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 spec['dtype_out_time']
always a tuple? I'm confused because in here https://github.com/spencerahill/aospy/blob/develop/aospy/calc.py#L153-L156, it's possible for dtype_out_time
to be a string, but then it's changed back to a tuple.
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 think it's reasonably safe to say here that it will be an iterable of some kind; the documentation states that a list is required in the calc_suite_specs
dictionary:
http://aospy.readthedocs.io/en/latest/api.html?highlight=calcsuite#aospy.automate.submit_mult_calcs.
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 @micahkim23 . I think we're most of the way there. A few things though that need fixing or I'm not totally understanding.
aospy/test/data/objects/examples.py
Outdated
@@ -47,6 +47,13 @@ def total_precipitation(convection_rain, condensation_rain): | |||
models=[example_model] | |||
) | |||
|
|||
precip_largescale = Var( |
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.
Why is this new Var
object needed?
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 just needed to test a Var
object with def_time=False
.
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.
OK. Let's rename it to make that explicit; otherwise it's confusing why there are two nearly identical objects. E.g. var_not_time_defined = Var(name='var_no_time_def', def_time=False)
. You can leave alt_names
and description
unspecified.
aospy/test/test_automate.py
Outdated
|
||
|
||
@pytest.mark.parametrize( | ||
('var'), |
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.
Here and elsewhere: parentheses around a single object do nothing: ('var') == 'var'
. So I would omit them, except where they are used to break expressions over multiple lines.
Conversely, if there is a trailing comma, it defines a length-1 tuple: e.g. ('var',)
.
aospy/test/test_automate.py
Outdated
spec = { | ||
'var': var | ||
} | ||
for i in range(1, 8): |
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.
To be more explicit, replace range(1, 8)
with range(1, len(time_options) + 1)
.
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.
You are using the string 'None'
, instead of the built-in None
object. I think we want the latter.
aospy/test/test_calc_basic.py
Outdated
('None'), | ||
([])] | ||
) | ||
def test_calc_object_no_time_options(dtype_out_time): |
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 test doesn't assert anything; it will only fail if the CalcInterface
call fails. So let's add an assertion about the dtype_out_time
in the resulting CalcInterface
object.
aospy/test/test_calc_basic.py
Outdated
CalcInterface(**test_params) | ||
|
||
|
||
@pytest.mark.fixture |
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 fixture decorator shouldn't be used on a test; instead it's used to prepare the data needed for a test. See https://docs.pytest.org/en/latest/fixture.html#fixtures
docs/whats-new.rst
Outdated
@@ -51,6 +51,9 @@ Bug Fixes | |||
writing to netCDF files to avoid bugs when using ``libnetcdf`` | |||
version 4.5.0 (:pull:`235`). By `Spencer Hill | |||
<https://github.com/spencerahill>`_. | |||
- Skip ``Calc`` object calculation that computes time average of |
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.
Expand a bit: note that this refers to when using CalcSuite
(and thus submit_mult_calcs
), and that Calc
now raises a ValueError when instantiated with a non-time-defined variable but with one or more time-defined reductions.
docs/whats-new.rst
Outdated
- Skip ``Calc`` object calculation that computes time average of | ||
a variable with no time dimension. (closes :issue:`202` | ||
via :pull:`242`). By `Micah Kim <https://github.com/micahkim23>`_. | ||
- In ``CalcSuite`` when calling ``submit_mult_calc``, calculations |
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.
CalcSuite
doesn't call submit_mult_calc
; it's the other way around.
aospy/test/test_automate.py
Outdated
@@ -351,3 +354,24 @@ def test_permute_aux_specs(self, calc_suite, calcsuite_specs): | |||
assert len(actual) == len(expected) | |||
for act in actual: | |||
assert act in expected | |||
|
|||
|
|||
@pytest.mark.parametrize( |
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.
Minor style note: splitting across lines like this, with an open parentheses/bracket/curly bracket and then an immediate line break, is usually only needed when either
- The items/expression within the overall parentheses/bracket/curly bracket is long enough that this helps it fit onto fewer lines, or at least look nicer.
- The items aren't themselves too long to fit on one line each, but there are a lot of them, so it makes it easier to read.
In this case, you don't need to split lines at all; it would fit into a single line:
@pytest.mark.parametrize('var', [precip_largescale, condensation_rain])
Also note more meaningless parentheses; please omit.
@@ -160,6 +161,56 @@ def setUp(self): | |||
} | |||
|
|||
|
|||
test_params = { |
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.
nit: indentation is longer than the standard 4 spaces.
(C.f. comment above re: line-splitting: for me this particular case falls into a gray area of intermediate length, where it could work throwing everything onto as few lines as possible, but it's also long enough that what you've done also works.)
aospy/test/test_calc_basic.py
Outdated
} | ||
|
||
|
||
@pytest.mark.parametrize( |
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.
More unneeded parentheses + line breaks
assert calc.dtype_out_time == tuple([dtype_out_time]) | ||
|
||
|
||
@pytest.mark.parametrize( |
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.
More unneeded parentheses
docs/whats-new.rst
Outdated
@@ -51,6 +51,12 @@ Bug Fixes | |||
writing to netCDF files to avoid bugs when using ``libnetcdf`` | |||
version 4.5.0 (:pull:`235`). By `Spencer Hill | |||
<https://github.com/spencerahill>`_. | |||
- In ``CalcSuite`` when calling ``submit_mult_calc``, calculations |
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.
Other way around: submit_mult_calc
calls CalcSuite
. How about "CalcSuite
(and thus submit_mult_calcs
) now skips calculations that involve..."
aospy/test/data/objects/examples.py
Outdated
@@ -47,6 +47,13 @@ def total_precipitation(convection_rain, condensation_rain): | |||
models=[example_model] | |||
) | |||
|
|||
precip_largescale = Var( |
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.
OK. Let's rename it to make that explicit; otherwise it's confusing why there are two nearly identical objects. E.g. var_not_time_defined = Var(name='var_no_time_def', def_time=False)
. You can leave alt_names
and description
unspecified.
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.
Almost there @micahkim23! Just a few more small things from me.
aospy/automate.py
Outdated
@@ -22,6 +22,7 @@ | |||
_REGIONS_STR = 'regions' | |||
_VARIABLES_STR = 'variables' | |||
_TAG_ATTR_MODIFIERS = dict(all='', default='default_') | |||
_TIME_DEFINED_REDUCTIONS = ['av', 'std', 'ts', 'reg.av', 'reg.std', 'reg.ts'] |
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.
For now I think it might be a good idea to keep the definition of these only in calc.py
and import them here. This way we won't need to remember to maintain this list in two places.
from calc import _TIME_DEFINED_REDUCTIONS
aospy/test/test_calc_basic.py
Outdated
|
||
|
||
@pytest.mark.parametrize( | ||
('dtype_out_time'), |
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 think you can remove the parentheses here too.
aospy/test/test_calc_basic.py
Outdated
} | ||
|
||
|
||
@pytest.mark.parametrize(('dtype_out_time'), [None, '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.
I think you can remove the parentheses around 'dtype_out_time'
here. Also, is there a reason we are testing with the value 'None'
?
aospy/test/test_calc_basic.py
Outdated
|
||
|
||
def test_calc_object_time_options(): | ||
time_options = ['av', 'std', 'ts', 'reg.av', 'reg.std', 'reg.ts', '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.
Per @spencerahill's earlier comment, should we use None
rather than 'None'
here?
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.
Line 486 in 67ec619
'None': lambda xarr: xarr, |
'None'
was a possible time reduction.
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.
Good catch @micahkim23! @spencerahill was this intentional? Should we change it?
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.
Woops! Yes, good call @micahkim23 . Sorry if any comments I made previously were confused on this point.
Since 'None'
appears to just be a synonym for 'ts'
, I'd say we just remove it entirely. So there's only ['ts', 'av', 'std', 'reg.ts', 'reg.av', 'reg.std']
.
Since custom reductions are a big priority moving forward (#208), this will get refactored soon-ish anyways.
We tempted the AppVeyor gods too long 😜 I'd say this is good to go. Thanks @spencerkclark for the reviews and esp. @micahkim23 for the PR! And sorry again for my leading you astray on the |
Closes #202