Skip to content
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

Merged
merged 17 commits into from
Jun 29, 2018

Conversation

git-abhishek
Copy link
Contributor

PR Summary

  1. Removed dead code
  2. Fixed few issues which were identified by adding more test cases
  3. Increased coverage

PR Checklist

  • Code passes flake8 checker
  • New features are documented, with docstrings and narrative docs NA
  • Adds a test for any bugs fixed. Adds tests for new features.

@git-abhishek
Copy link
Contributor Author

Unable to add @Colin as a reviewer. If someone can add him, that would be great!

Copy link

@colinmarc colinmarc left a 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]

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 _.

Copy link
Contributor Author

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

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?

Copy link
Member

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.

Copy link
Contributor Author

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",

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?

Copy link
Member

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")

Copy link
Contributor Author

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)
Copy link
Member

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.

Copy link
Contributor Author

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__').

Copy link
Member

Choose a reason for hiding this comment

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

OK, fair enough!

Copy link
Member

@ngoldbaum ngoldbaum left a 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()
Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

if iterable(width):
radius = max(width)
if isinstance(width, tuple):
radius = width[0]
Copy link
Member

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.

Copy link
Contributor Author

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'

Copy link
Member

@ngoldbaum ngoldbaum Jun 12, 2018

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:

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.

Copy link
Contributor Author

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'
Copy link
Member

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

Copy link
Contributor Author

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')
Copy link
Member

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']

Copy link
Contributor Author

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)
Copy link
Member

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?

Copy link
Contributor Author

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
Copy link
Member

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)
Copy link
Member

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.

Copy link
Contributor Author

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",
Copy link
Member

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")
Copy link
Member

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.

Copy link
Contributor Author

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)
Copy link
Member

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.

Copy link
Contributor Author

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()
Copy link
Contributor Author

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'
Copy link
Contributor Author

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')
Copy link
Contributor Author

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)
Copy link
Contributor Author

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?

Copy link
Member

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.

Copy link
Contributor Author

@git-abhishek git-abhishek left a 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)
Copy link
Contributor Author

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]
Copy link
Contributor Author

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)
Copy link
Contributor Author

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)
Copy link
Contributor Author

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
Copy link
Contributor Author

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")
Copy link
Contributor Author

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)
Copy link
Contributor Author

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.

if iterable(width):
radius = max(width)
if isinstance(width, tuple):
radius = width[0]
Copy link
Contributor Author

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)
Copy link
Contributor Author

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)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Copy link
Member

@ngoldbaum ngoldbaum left a 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
Copy link
Member

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?

Copy link
Contributor Author

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

Copy link
Member

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.

Copy link
Contributor Author

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?

Copy link
Member

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]
Copy link
Member

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
Copy link
Member

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?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

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")
Copy link
Member

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.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@ngoldbaum
Copy link
Member

@yt-fido test this please

@ngoldbaum ngoldbaum merged commit a5db4fc into yt-project:master Jun 29, 2018
@git-abhishek git-abhishek deleted the cc-do-containers branch June 29, 2018 22:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants