Repository: yt-project/yt

Issue:
ds.arbitrary_grid fails for FLASH particle data
<!--To help us understand and resolve your issue, please fill out the form to
the best of your ability.-->
<!--You can feel free to delete the sections that do not apply.-->

### Bug report

**Bug summary**

``ds.arbitrary_grid`` fails for FLASH particle data

<!--A short 1-2 sentences that succinctly describes the bug-->

**Code for reproduction**

<!--A minimum code snippet required to reproduce the bug, also minimizing the
number of dependencies required.-->

<!-- If you need to use a data file to trigger the issue you're having, consider
using one of the datasets from the yt data hub (http://yt-project.org/data). If
your issue cannot be triggered using a public dataset, you can use the yt
curldrop (https://docs.hub.yt/services.html#curldrop) to share data
files. Please include a link to the dataset in the issue if you use the
curldrop.-->

```python
import yt

# see https://girder.hub.yt/#item/5910e362b14b470001b887e2
filename = "streamshock_hdf5_part_0100"

dims = [200, 5, 5]
ds = yt.load(filename)
vol = ds.arbitrary_grid(ds.domain_left_edge, ds.domain_right_edge, dims=dims)
print(vol["deposit", "all_density"].max())
```

**Actual outcome**

<!--The output produced by the above code, which may be a screenshot, console
output, etc.-->

```
yt : [INFO     ] 2017-05-08 14:18:25,422 integer runtime parameter checkpointfilenumber overwrites a simulation scalar of the same name
yt : [INFO     ] 2017-05-08 14:18:25,422 integer runtime parameter particlefilenumber overwrites a simulation scalar of the same name
yt : [INFO     ] 2017-05-08 14:18:25,422 integer runtime parameter plotfilenumber overwrites a simulation scalar of the same name
yt : [INFO     ] 2017-05-08 14:18:25,437 Parameters: current_time              = 50.0034519855
yt : [INFO     ] 2017-05-08 14:18:25,437 Parameters: domain_dimensions         = [2 2 2]
yt : [INFO     ] 2017-05-08 14:18:25,438 Parameters: domain_left_edge          = [ 0.  0.  0.]
yt : [INFO     ] 2017-05-08 14:18:25,438 Parameters: domain_right_edge         = [ 20.    0.5   0.5]
yt : [INFO     ] 2017-05-08 14:18:25,438 Parameters: cosmological_simulation   = 0.0
yt : [INFO     ] 2017-05-08 14:18:25,441 Allocating for 9.480e+04 particles (index particle type 'all')
yt : [INFO     ] 2017-05-08 14:18:25,468 Identified 3.969e+03 octs
Traceback (most recent call last):
  File "to_grid.py", line 8, in <module>
    print(vol["deposit", "all_density"].max())
  File "/Applications/anaconda/lib/python2.7/site-packages/yt/data_objects/data_containers.py", line 281, in __getitem__
    self.get_data(f)
  File "/Applications/anaconda/lib/python2.7/site-packages/yt/data_objects/construction_data_containers.py", line 640, in get_data
    if len(gen) > 0: self._generate_fields(gen)
  File "/Applications/anaconda/lib/python2.7/site-packages/yt/data_objects/data_containers.py", line 1353, in _generate_fields
    fd = self._generate_field(field)
  File "/Applications/anaconda/lib/python2.7/site-packages/yt/data_objects/data_containers.py", line 318, in _generate_field
    tr = self._generate_fluid_field(field)
  File "/Applications/anaconda/lib/python2.7/site-packages/yt/data_objects/data_containers.py", line 338, in _generate_fluid_field
    rv = finfo(gen_obj)
  File "/Applications/anaconda/lib/python2.7/site-packages/yt/fields/derived_field.py", line 234, in __call__
    dd = self._function(self, data)
  File "/Applications/anaconda/lib/python2.7/site-packages/yt/fields/particle_fields.py", line 129, in particle_density
    d = data.deposit(pos, [mass], method = "sum")
  File "/Applications/anaconda/lib/python2.7/site-packages/yt/data_objects/construction_data_containers.py", line 733, in deposit
    op.process_grid(self, positions, fields)
  File "yt/geometry/particle_deposit.pyx", line 144, in yt.geometry.particle_deposit.ParticleDepositOperation.process_grid (yt/geometry/particle_deposit.c:5633)
  File "yt/geometry/particle_deposit.pyx", line 271, in yt.geometry.particle_deposit.SumParticleField.process (yt/geometry/particle_deposit.c:7204)
IndexError: Out of bounds on buffer access (axis 2)
```

**Version Information**
<!--Please specify your platform and versions of the relevant libraries you are
using:-->
  * Operating System: MacOS
  * Python Version: 3.6.1
  * yt version: 3a598d3


Discussion:
Any chance you can share the dataset from the test script or trigger it using one of the public test datasets?
Sure -- here is the data set: https://girder.hub.yt/#item/5910e362b14b470001b887e2

Resolving patch:
diff --git a/yt/data_objects/construction_data_containers.py b/yt/data_objects/construction_data_containers.py
--- a/yt/data_objects/construction_data_containers.py
+++ b/yt/data_objects/construction_data_containers.py
@@ -741,12 +741,15 @@ def deposit(self, positions, fields = None, method = None,
         cls = getattr(particle_deposit, "deposit_%s" % method, None)
         if cls is None:
             raise YTParticleDepositionNotImplemented(method)
-        # We allocate number of zones, not number of octs
-        op = cls(self.ActiveDimensions, kernel_name)
+        # We allocate number of zones, not number of octs. Everything inside
+        # this is fortran ordered because of the ordering in the octree deposit
+        # routines, so we reverse it here to match the convention there
+        op = cls(tuple(self.ActiveDimensions)[::-1], kernel_name)
         op.initialize()
         op.process_grid(self, positions, fields)
         vals = op.finalize()
-        return vals.copy(order="C")
+        # Fortran-ordered, so transpose.
+        return vals.transpose()
 
     def write_to_gdf(self, gdf_path, fields, nprocs=1, field_units=None,
                      **kwargs):
diff --git a/yt/data_objects/grid_patch.py b/yt/data_objects/grid_patch.py
--- a/yt/data_objects/grid_patch.py
+++ b/yt/data_objects/grid_patch.py
@@ -351,14 +351,16 @@ def deposit(self, positions, fields = None, method = None,
         cls = getattr(particle_deposit, "deposit_%s" % method, None)
         if cls is None:
             raise YTParticleDepositionNotImplemented(method)
-        # We allocate number of zones, not number of octs
-        # Everything inside this is fortran ordered, so we reverse it here.
-        op = cls(tuple(self.ActiveDimensions)[::-1], kernel_name)
+        # We allocate number of zones, not number of octs. Everything inside
+        # this is Fortran ordered because of the ordering in the octree deposit
+        # routines, so we reverse it here to match the convention there
+        op = cls(tuple(self.ActiveDimensions[::-1]), kernel_name)
         op.initialize()
         op.process_grid(self, positions, fields)
         vals = op.finalize()
         if vals is None: return
-        return vals.transpose() # Fortran-ordered, so transpose.
+        # Fortran-ordered, so transpose.
+        return vals.transpose()
 
     def select_blocks(self, selector):
         mask = self._get_selector_mask(selector)


Test patch:
diff --git a/yt/data_objects/tests/test_covering_grid.py b/yt/data_objects/tests/test_covering_grid.py
--- a/yt/data_objects/tests/test_covering_grid.py
+++ b/yt/data_objects/tests/test_covering_grid.py
@@ -101,28 +101,27 @@ def test_arbitrary_grid():
 
             ds = load_particles(particle_data)
 
-            LE = np.array([0.05, 0.05, 0.05])
-            RE = np.array([0.95, 0.95, 0.95])
-            dims = np.array([ncells, ncells, ncells])
+            for dims in ([ncells]*3, [ncells, ncells/2, ncells/4]):
+                LE = np.array([0.05, 0.05, 0.05])
+                RE = np.array([0.95, 0.95, 0.95])
+                dims = np.array(dims)
 
-            dds = (RE - LE) / dims
-            volume = ds.quan(np.product(dds), 'cm**3')
+                dds = (RE - LE) / dims
+                volume = ds.quan(np.product(dds), 'cm**3')
 
-            obj = ds.arbitrary_grid(LE, RE, dims)
-            deposited_mass = obj["deposit", "all_density"].sum() * volume
+                obj = ds.arbitrary_grid(LE, RE, dims)
+                deposited_mass = obj["deposit", "all_density"].sum() * volume
 
-            assert_equal(deposited_mass, ds.quan(1.0, 'g'))
+                assert_equal(deposited_mass, ds.quan(1.0, 'g'))
 
-            LE = np.array([0.00, 0.00, 0.00])
-            RE = np.array([0.05, 0.05, 0.05])
-            dims = np.array([ncells, ncells, ncells])
+                LE = np.array([0.00, 0.00, 0.00])
+                RE = np.array([0.05, 0.05, 0.05])
 
-            obj = ds.arbitrary_grid(LE, RE, dims)
+                obj = ds.arbitrary_grid(LE, RE, dims)
 
-            deposited_mass = obj["deposit", "all_density"].sum()
-
-            assert_equal(deposited_mass, 0)
+                deposited_mass = obj["deposit", "all_density"].sum()
 
+                assert_equal(deposited_mass, 0)
 
     # Test that we get identical results to the covering grid for unigrid data.
     # Testing AMR data is much harder.
diff --git a/yt/fields/tests/test_fields.py b/yt/fields/tests/test_fields.py
--- a/yt/fields/tests/test_fields.py
+++ b/yt/fields/tests/test_fields.py
@@ -11,6 +11,7 @@
     assert_array_almost_equal_nulp, \
     assert_array_equal, \
     assert_raises, \
+    assert_allclose_units, \
     requires_file
 from yt.utilities.cosmology import \
     Cosmology
@@ -347,3 +348,13 @@ def test_field_inference():
     # If this is not true this means the result of field inference depends
     # on the order we did field detection, which is random in Python3
     assert_equal(ds._last_freq, (None, None))
+
+ISOGAL = 'IsolatedGalaxy/galaxy0030/galaxy0030'
+
+@requires_file(ISOGAL)
+def test_deposit_amr():
+    ds = load(ISOGAL)
+    for i, g in enumerate(ds.index.grids):
+        gpm = g['particle_mass'].sum()
+        dpm = g['deposit', 'all_mass'].sum()
+        assert_allclose_units(gpm, dpm)