Repository: yt-project/yt

Issue:
yt.ProfilePlot gives different answers on repeated execution
### Bug report
When executing yt.ProfilePlot for multiple times sequentially, the answers, i.e. the plots, change.

**Code for reproduction**

```python
%matplotlib inline
import yt
data_ds = yt.load(<dump>)
my_sphere = data_ds.sphere("max", (5.0, "kpc"))
plot = yt.ProfilePlot(my_sphere, "radius", ["dark_matter_density"])
plot.show()
plot = yt.ProfilePlot(my_sphere, "radius", ["dark_matter_density"])
plot.show()
plot = yt.ProfilePlot(my_sphere, "radius", ["dark_matter_density"])
plot.show()
```

**Actual outcome**
![1](https://cloud.githubusercontent.com/assets/22685568/25622190/a04b182c-2f21-11e7-8621-78d7eb7f6c8d.png)
![2](https://cloud.githubusercontent.com/assets/22685568/25622196/a45ee150-2f21-11e7-9466-e3ebcc6d3579.png)
![3](https://cloud.githubusercontent.com/assets/22685568/25622199/a6ea441e-2f21-11e7-8791-39c810e65707.png)


**Expected outcome**

The exact same plot.

**Version Information**

  * Operating System: SUSE Linux Enterprise Server 11 (x86_64)
  * Python Version: 2.7.13
  * yt version:3.4-dev 634cc55bf066+ (yt) tip
  * Other Libraries (if applicable): 

Installed via install script with packages via conda and yt from source.




Discussion:
This also happens when I execute the script from a terminal and not within a notebook (leading to different answers again).
Moreover, executing the script twice also provides different plots (some).
@pgrete shared his dataset with us on Slack. I've made a runnable version of his test script that doesn't require the notebook:

```
import yt
# from http://use.yt/upload/a9500d42
data_ds = yt.load('DD0012/data0012')
my_sphere = data_ds.sphere("max", (5.0, "kpc"))
plot = yt.ProfilePlot(my_sphere, "radius", ["dark_matter_density"])
plot.save('1')
plot = yt.ProfilePlot(my_sphere, "radius", ["dark_matter_density"])
plot.save('2')
plot = yt.ProfilePlot(my_sphere, "radius", ["dark_matter_density"])
plot.save('3')
```

Unfortunately I'm not able to reproduce the reported issue. When I run this script on 634cc55bf066 I get three identical copies of this image:

![1_1d-profile_radius_dark_matter_density](https://cloud.githubusercontent.com/assets/3126246/25624777/1d0bc3ae-2f20-11e7-9d26-a04e62952627.png)


I asked Philipp about his local modifications to yt and they're not pertinent (just the patch from PR 1351 applied).
It looks to me like it could be related somehow to chunking and masking getting misapplied, or maybe units or something, but that doesn't match with the lack of repeatability by you, @ngoldbaum.
Kacper reproduced it on Python2.
I was able to get identical results on python2 and python3 with the following patch:

```
diff --git a/yt/utilities/io_handler.py b/yt/utilities/io_handler.py
index 9546319..da116a6 100644
--- a/yt/utilities/io_handler.py
+++ b/yt/utilities/io_handler.py
@@ -125,7 +125,7 @@ class BaseIOHandler(object):
         # rewrite a whole bunch of IO handlers all at once, and to allow a
         # better abstraction for grid-based frontends, we're now defining it in
         # the base class.
-        rv = {field: np.empty(size, dtype="=f8") for field in fields}
+        rv = {field: np.zeros(size, dtype="=f8") for field in fields}
         ind = {field: 0 for field in fields}
         for field, obj, data in self.io_iter(chunks, fields):
             if data is None: continue
```

So I guess that means that something at a low level in Enzo's I/O routines aren't masking data correctly. This process is actually happening identically on python2 and python3, the only reason we saw differences in my tests was because `np.empty` was returning different results on py2 and py3 (e.g. on py2 there were data with values like 10^44 whereas on py3 the maximum value was of order unity). This means we've been silently returning uninitialized data.
It looks like @matt added this code relatively recently in 7a0d6eed, it would be great if you could take a look at this when you have a chance.

@pgrete as a workaround I think you will get correct results for this operation if you try running yt using the stable version. Thank you for reporting this issue! It would have been a shame to release yt 3.4 without this being addressed first.
Here's a possibly simpler test. Make the following modification to yt:

```
diff --git a/yt/utilities/io_handler.py b/yt/utilities/io_handler.py
index 9546319..a89f7ea 100644
--- a/yt/utilities/io_handler.py
+++ b/yt/utilities/io_handler.py
@@ -125,7 +125,7 @@ class BaseIOHandler(object):
         # rewrite a whole bunch of IO handlers all at once, and to allow a
         # better abstraction for grid-based frontends, we're now defining it in
         # the base class.
-        rv = {field: np.empty(size, dtype="=f8") for field in fields}
+        rv = {field: np.zeros(size, dtype="=f8")-1e99 for field in fields}
         ind = {field: 0 for field in fields}
         for field, obj, data in self.io_iter(chunks, fields):
             if data is None: continue
```

Then run the following test script:

```
import yt
ds = yt.load('DD0012/data0012')
ad = ds.all_data()
print(ad['enzo', 'Dark_Matter_Density'].min())
```
On my machine this prints `-1e+99 code_mass/code_length**3`. So indeed something isn't being masked correctly. Also interestingly this seems to not happen for every on-disk field (e.g. it doesn't happen for `('enzo', 'Density')`).

It also doesn't happen if I use a smaller enzo dataset, so I think this is triggering some behavior that only happens for relatively big datasets with lots of grids.

Resolving patch:
diff --git a/yt/frontends/enzo/io.py b/yt/frontends/enzo/io.py
--- a/yt/frontends/enzo/io.py
+++ b/yt/frontends/enzo/io.py
@@ -151,7 +151,9 @@ def _read_obj_field(self, obj, field, fid_data = None):
             node = "/Grid%08i/%s" % (obj.id, fname)
             dg = h5py.h5d.open(fid, b(node))
         except KeyError:
-            if fname == "Dark_Matter_Density": return None
+            if fname == "Dark_Matter_Density":
+                data[:] = 0
+                return data.T
             raise
         dg.read(h5py.h5s.ALL, h5py.h5s.ALL, data)
         # I don't know why, but on some installations of h5py this works, but


Test patch: