-
Notifications
You must be signed in to change notification settings - Fork 279
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
Clean up and added test cases for data_objects.data_containers
#1831
Conversation
Unable to add @Colin as a reviewer. If someone can add him, that would be great! |
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 missing the context to really review the content changes or the effectiveness of the new tests, but I left a few surface-level nitpicks :)
file_row_2 = file.readline() | ||
file_row_2 = np.array(file_row_2.split('\t'), dtype=np.float64) | ||
sorted_keys = sorted(sp.field_data.keys()) | ||
_keys = [str(k) for k in sorted_keys] |
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 don't see the point of signifying these as private with _
.
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
|
||
def test_to_dataframe(): | ||
try: | ||
import pandas as pd |
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.
Does import pandas as _
make flake8 happy?
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.
Rather than wrapping the test logic in a try/except, please use yt.testing.requires_module
, which is a decorator you can apply to a test function to tell nose that the test function requires some optional module (in this case pandas
).
You probably also need to install pandas on travis and appveyor to get this test to actually execute.
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
rho = dd.quantities["WeightedAverageQuantity"]("density", | ||
weight="cell_mass") | ||
dd.extract_isocontours("density", rho, "triangles.obj", True) | ||
dd.calculate_isocontour_flux("density", rho, "x", "y", "z", |
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 formatting choice seems odd (the complete line is shorter than the lines above). Are you using an auto-formatter like yapf or eyeballing 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.
I'd format these two lines like:
dd.calculate_isocontour_flux(
"density", rho, "x", "y", "z", "dx")
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.
fixed
ds = fake_particle_ds() | ||
sp = ds.sphere(ds.domain_center, 0.25) | ||
sp.save_object("my_sphere_1", filename="test_save_obj") | ||
obj = shelve.open("test_save_obj", protocol=-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.
This could be wrapped in a with
statement to prevent the file handler to being left opened if the assertion bellow fail.
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 had done it earlier using with
statement however it was failing in python 2.7 (error: AttributeError: DbfilenameShelf instance has no attribute '__exit__'
).
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, fair enough!
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.
On the whole this is good although I've left a number of comments below.
In addition it looks like you added two empty files (I think from your other PR?) that should be removed.
@@ -922,7 +922,8 @@ def __init__(self, *args, **kwargs): | |||
self._final_start_index = self.global_startindex | |||
|
|||
def _setup_data_source(self, level_state = None): | |||
if level_state is None: return | |||
if level_state is None: | |||
return super(YTSmoothedCoveringGrid, self)._setup_data_source() |
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'd format this as:
if level_state is None:
super(YTSmoothedCoveringGrid, self)._setup_data_source()
return
_setup_data_source
doesn't return anything, and this way of calling it makes it clearer that that's the case.
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
yt/data_objects/data_containers.py
Outdated
if iterable(width): | ||
radius = max(width) | ||
if isinstance(width, tuple): | ||
radius = width[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.
I don't think this change is correct - the original code is correct. We're checking for iterable(width)
because width might be a list or an ndarray or some other kind of iterable. It's easier to just use the iterable
function to test for this rather than using isinstance
and insisting on only accepting a certain number of types.
Also it's a behavior change to pick width[0]
instead of max(width)
. Can you explain why you did that? Choosing max(width)
is arbitrary, but since we already made the decision it's best to not change our minds without a good reason.
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 changed it as I was getting error for the test case:
def test_to_frb():
ds = fake_amr_ds(fields=["density", "cell_mass"], geometry="cylindrical",
particles=16**3)
proj = ds.proj("density", weight_field="cell_mass", axis=1,
data_source=ds.all_data())
proj.to_frb((1.0, 'unitary'), 64)
Error:
line 1668, in to_frb
radius = max(width)
TypeError: '>' not supported between instances of 'str' and 'float'
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.
Width is allowed to be a tuple of tuples, like this:
((1.0, 'unitary'), (0.7, 'unitary'))
this allows constructing images where the width doesn't equal the height.
For the cylindrical FRB the width really represents a radius, and what happens right now is it assumes if you're passing a tuple you're passing two floats and it assumes the radius you really mean is the maximum of the two floats you passed in.
That's not great, so maybe it's ok to change this. Rather than what you've done though I'd suggest if we're passed a tuple, to check if it's a valid (length, unit)
tuple, and if not raise an error. That is, for a cylindrical dataset, it only makes sense to pass in one width to inrepret as the radius, so if someone passes in more than one, we should raise an error.
Basically the code here:
yt/yt/data_objects/data_containers.py
Lines 1691 to 1696 in cc299b0
if iterable(width): | |
w, u = width | |
if isinstance(w, tuple) and isinstance(u, tuple): | |
height = u | |
w, u = w | |
width = self.ds.quan(w, input_units = u) |
But in the if statement raise an error instead of interpreting the tuple as a width and height.
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
with assert_raises(RuntimeError) as err: | ||
YTDataContainer(None, None) | ||
desired = 'Error: ds must be set either through class type or parameter' \ | ||
' to the constructor' |
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.
style nit: If you put the string inside parentheses then you don't need to use the line continuation
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
assert_equal('pz' in proj.keys(), False) | ||
|
||
# Delete the key and check if exits | ||
proj.__delitem__('px') |
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.
Rather than calling __delitem__
directly I'd format this (and similarly below) as del proj['px']
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
assert_equal(str(ex.exception), desired) | ||
|
||
# Test the convert method | ||
assert_equal(proj.convert('HydroMethod'), -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.
This is actually a relic of the old pre yt-3.0 API that should have been removed a long time ago. Can you remove this test and the function calling 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.
done
|
||
def test_to_dataframe(): | ||
try: | ||
import pandas as pd |
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.
Rather than wrapping the test logic in a try/except, please use yt.testing.requires_module
, which is a decorator you can apply to a test function to tell nose that the test function requires some optional module (in this case pandas
).
You probably also need to install pandas on travis and appveyor to get this test to actually execute.
particles=16**3) | ||
proj = ds.proj("density", weight_field="cell_mass", axis=1, | ||
data_source=ds.all_data()) | ||
proj.to_frb((1.0, 'unitary'), 64) |
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 test that the FixedResolutionBuffer
object you get back is correct? (e.g. it produces images with a resolution of (64, 64)
and that the image covers the full domain? For the latter you can just inspect the state of the FixedResolutionBuffer
object (e.g. by checking frb.bounds
) rather than trying to make sure the image is 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.
In case of CylindricalFixedResolutionBuffer
the object does not have bounds
field instead there is buff_size
.
rho = dd.quantities["WeightedAverageQuantity"]("density", | ||
weight="cell_mass") | ||
dd.extract_isocontours("density", rho, "triangles.obj", True) | ||
dd.calculate_isocontour_flux("density", rho, "x", "y", "z", |
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'd format these two lines like:
dd.calculate_isocontour_flux(
"density", rho, "x", "y", "z", "dx")
ds = fake_amr_ds(fields=["density", "cell_mass"], particles=16**3) | ||
dd = ds.all_data() | ||
rho = dd.quantities["WeightedAverageQuantity"]("density", | ||
weight="cell_mass") |
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'd format these lines like:
q = dd.quantities["WeightedAverageQuantity"]
rho = q("density", weight="cell_mass")
Often when you find yourself hitting a line length limit you can get around it by defining an intermediate variable. This has the side benefit of often making the code more understandable.
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
min_val, max_val = data_source[field].min() / 2, data_source[field].max() / 2 | ||
|
||
data_source.extract_connected_sets(field, 3, min_val, max_val, | ||
log_space=True, cumulative=True) |
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 test that the data returned by this function are correct? Also the formatting right here is a little odd, this line should be aligned with field
, not 3
.
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.
Removing this test as it is already present in test_connected_sets.py
.
@@ -922,7 +922,8 @@ def __init__(self, *args, **kwargs): | |||
self._final_start_index = self.global_startindex | |||
|
|||
def _setup_data_source(self, level_state = None): | |||
if level_state is None: return | |||
if level_state is None: | |||
return super(YTSmoothedCoveringGrid, self)._setup_data_source() |
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
with assert_raises(RuntimeError) as err: | ||
YTDataContainer(None, None) | ||
desired = 'Error: ds must be set either through class type or parameter' \ | ||
' to the constructor' |
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
assert_equal('pz' in proj.keys(), False) | ||
|
||
# Delete the key and check if exits | ||
proj.__delitem__('px') |
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
assert_equal(str(ex.exception), desired) | ||
|
||
# Test the convert method | ||
assert_equal(proj.convert('HydroMethod'), -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.
Should I delete convert
and __delitem__
methods only?
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.
Don't delete __delitem__
, that's still needed. I was saying that in the test don't invoke __delitem__
directly, instead use the del
statement to invoke it indirectly.
You should delete convert
since it's a relic function that doesn't do what it says in its own docstring.
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.
Updated as per first review comments. Please review again.
assert_equal(str(ex.exception), desired) | ||
|
||
# Test the convert method | ||
assert_equal(proj.convert('HydroMethod'), -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.
done
file_row_2 = file.readline() | ||
file_row_2 = np.array(file_row_2.split('\t'), dtype=np.float64) | ||
sorted_keys = sorted(sp.field_data.keys()) | ||
_keys = [str(k) for k in sorted_keys] |
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
ds = fake_particle_ds() | ||
sp = ds.sphere(ds.domain_center, 0.25) | ||
sp.save_object("my_sphere_1", filename="test_save_obj") | ||
obj = shelve.open("test_save_obj", protocol=-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.
I had done it earlier using with
statement however it was failing in python 2.7 (error: AttributeError: DbfilenameShelf instance has no attribute '__exit__'
).
obj = shelve.open("test_save_obj", protocol=-1) | ||
loaded_sphere = obj["my_sphere_1"][1] | ||
assert_array_equal(loaded_sphere.center, sp.center) | ||
assert_equal(loaded_sphere.radius, sp.radius) |
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
|
||
def test_to_dataframe(): | ||
try: | ||
import pandas as pd |
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
ds = fake_amr_ds(fields=["density", "cell_mass"], particles=16**3) | ||
dd = ds.all_data() | ||
rho = dd.quantities["WeightedAverageQuantity"]("density", | ||
weight="cell_mass") |
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
min_val, max_val = data_source[field].min() / 2, data_source[field].max() / 2 | ||
|
||
data_source.extract_connected_sets(field, 3, min_val, max_val, | ||
log_space=True, cumulative=True) |
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.
Removing this test as it is already present in test_connected_sets.py
.
yt/data_objects/data_containers.py
Outdated
if iterable(width): | ||
radius = max(width) | ||
if isinstance(width, tuple): | ||
radius = width[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.
done
particles=16**3) | ||
proj = ds.proj("density", weight_field="cell_mass", axis=1, | ||
data_source=ds.all_data()) | ||
proj.to_frb((1.0, 'unitary'), 64) |
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.
In case of CylindricalFixedResolutionBuffer
the object does not have bounds
field instead there is buff_size
.
filename = "sphere.txt" | ||
ds = fake_particle_ds() | ||
sp = ds.sphere(ds.domain_center, 0.25) | ||
sp.write_out(filename) |
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.
Just a few minor comments, other than that this looks good to me now.
.travis.yml
Outdated
@@ -23,6 +23,7 @@ env: | |||
FLAKE8=flake8 | |||
CODECOV=codecov | |||
COVERAGE=coverage | |||
PANDAS=pandas<0.21 |
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 there some problem with the latest version of pandas?
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 was getting Double requirement given: numpy==1.12.1 ... (already in numpy==1.9.3 )
and build was failing at Travis.
Solution: pandas-dev/pandas#20723
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.
Ah, so it's because pandas dropped support for python3.4
- can you only add this version restriction for the python3.4 builder?
To be honest, we should probably drop testing for python3.4, it's going EOL - I'll make a note to bring that up at the team meeting tomorrow.
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.
Our Travis lint stage is executed for python3.4, do you want me to update that too with python3.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.
Yup.
elif center.lower() == "min": | ||
self.center = self.ds.find_min(("gas", "density"))[1] | ||
elif center.startswith("min_"): | ||
self.center = self.ds.find_min(center[4:])[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.
good catch!
for k in loaded_sphere._key_fields: | ||
assert_array_equal(loaded_sphere[k], sp[k]) | ||
|
||
# Object is saved but retrieval is not working |
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 open an issue to track this?
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
yt/data_objects/data_containers.py
Outdated
field_order += [field for field in fields if field not in field_order] | ||
fid = open(filename,"w") | ||
fid.write("\t".join(["#"] + field_order + ["\n"])) | ||
fid = open(filename, "w") |
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'd be happier with a with
statement there, to prevent the file handler from being left opened.
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
@yt-fido test this please |
PR Summary
PR Checklist