-
Notifications
You must be signed in to change notification settings - Fork 274
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
BUG: Projection of periodic boxes with specified width smaller than boxsize. #3916
Comments
Triaging as "viz: 2D" because this bug manifests itself in a ProjectionPlot, though it seems likely that this is really a particle selection bug. |
@benopp99 Could you please share more of the script you're using to produce this buggy image ? Also, can you confirm that you're dealing with a particle field ? |
Yes, this is a particle field (AREPO). (Same with EAGLE, Simba). Here's a script that you can adapt another simulation to. If you need this simulation snapshot, it can be made available. One more thing-- I use trident, but this is not an issue with trident, so you can do an oxygen map with the ProjectionPlot routine and avoid loading/installing trident. import trident
import sys
import astropy
import numpy as np
import h5py
import os.path
sim = sys.argv[1]
run = sys.argv[2]
snap = sys.argv[3]
axis = "z"
npix = 4000
nslices = 6
snapshot_filename = "/mnt/ceph/users/camels/Sims/" + sim + "/" + run + "/snap_" + snap + ".hdf5"
output_basename = sim + "." + run + ".snap_" + snap
ds = yt.load(snapshot_filename)
print("ds= ",ds.domain_left_edge,ds.domain_right_edge,ds.domain_right_edge[1],ds.domain_right_edge[2])
for i in range(nslices):
slice_frac_low = i*1./nslices
slice_frac_high = (i+1)*1./nslices
print("slice_frac_low, slice_frac_high= ",slice_frac_low, slice_frac_high)
left_edge = [ds.domain_left_edge[0],ds.domain_left_edge[1],slice_frac_low*ds.domain_right_edge[2]]
right_edge = [ds.domain_right_edge[0],ds.domain_right_edge[1],slice_frac_high*ds.domain_right_edge[2]]
my_slice = ds.box(left_edge, right_edge)
trident.add_ion_fields(ds, ions=['O VII'])
Pos = [22000,22000,22000]
Width = 23000
# Width = (32686, 'kpc')
proj = yt.ProjectionPlot(ds, "z", ("gas","O_number_density"), data_source=my_slice,center=Pos,width=Width,buff_size=[npix,npix])
proj.save(name=output_basename + '.trident_O.slice%dof%d.png'%(i+1,nslices))
proj_fits_slice = yt.FITSProjection(ds, "z", ("gas","O_p6_number_density"), data_source=my_slice, image_res=npix,center=Pos,width=Width)
proj_fits_slice.writeto(output_basename + '.trident_OVII.slice%dof%d.fits'%(i+1,nslices),overwrite=True) |
yes I think having the exact dataset could help as a first step |
Let's see if this works. It's 3 GB. via the wormhole app. |
Thanks for sharing the dataset! Your script is still a little far from a minimal reproducer however, and it is proving quite difficult for me to reproduce your problem so far. In particular, I don't know how you're able to use yt 4.1dev with trident. To my knowledge, the latest version is not compatible with yt 4.1 (trident-project/trident#180).
Your script also necessitates some adjustments to be usable on another machine, it'd be good to simplify this too so we can focus on actually inquiring the problem. |
trident is not necessary as this is a problem with projection plots. Let me simplify the script. |
import yt
import sys
sim = sys.argv[1]
run = sys.argv[2]
snap = sys.argv[3]
axis = "z"
npix = 4000
nslices = 6
#snapshot_filename = sim + "/" + run + "/snap_" + snap + ".hdf5"
snapshot_filename = "snap_" + snap + ".hdf5"
output_basename = sim + "." + run + ".snap_" + snap
ds = yt.load(snapshot_filename)
print("ds= ",ds.domain_left_edge,ds.domain_right_edge,ds.domain_right_edge[1],ds.domain_right_edge[2])
for i in range(nslices):
slice_frac_low = i*1./nslices
slice_frac_high = (i+1)*1./nslices
print("slice_frac_low, slice_frac_high= ",slice_frac_low, slice_frac_high)
left_edge = [ds.domain_left_edge[0],ds.domain_left_edge[1],slice_frac_low*ds.domain_right_edge[2]]
right_edge = [ds.domain_right_edge[0],ds.domain_right_edge[1],slice_frac_high*ds.domain_right_edge[2]]
my_slice = ds.box(left_edge, right_edge)
Pos = [22000,22000,22000]
Width = 23000
proj = yt.ProjectionPlot(ds, "z", ("gas","O_number_density"), data_source=my_slice,center=Pos,width=Width,buff_size=[npix,npix])
proj.save(name=output_basename + '.O.slice%dof%d.png'%(i+1,nslices)) |
Hmmm... that color scale does seem strange as it goes from 10^18 to 0, so it wouldn't distinguish that gap. Can you set the scale bar manually in your case? I'm trying to see if the structures are aligned, and I don't think they are. edit: I reran it myself without trident, and attached below, so you can grab that if you want. |
I reran the simpler script (below), without trident. I still get the gap. import yt
import sys
snap = sys.argv[1]
axis = "z"
npix = 4000
nslices = 6
snapshot_filename = "snap_" + snap + ".hdf5"
output_basename = "snap_" + snap
ds = yt.load(snapshot_filename)
print("ds= ",ds.domain_left_edge,ds.domain_right_edge,ds.domain_right_edge[1],ds.domain_right_edge[2])
for i in range(nslices):
slice_frac_low = i*1./nslices
slice_frac_high = (i+1)*1./nslices
print("slice_frac_low, slice_frac_high= ",slice_frac_low, slice_frac_high)
left_edge = [ds.domain_left_edge[0],ds.domain_left_edge[1],slice_frac_low*ds.domain_right_edge[2]]
right_edge = [ds.domain_right_edge[0],ds.domain_right_edge[1],slice_frac_high*ds.domain_right_edge[2]]
my_slice = ds.box(left_edge, right_edge)
Pos = [22000,22000,22000]
Width = 23000
proj = yt.ProjectionPlot(ds, "z", ("gas","O_number_density"), data_source=my_slice,center=Pos,width=Width,buff_size=[npix,npix])
proj.save(name=output_basename + '.O.slice%dof%d.png'%(i+1,nslices)) |
I've been making a lot of changes related to color scaling lately. For reference, I'm running your script with yt 4.0.3, which should behave as the current 4.1dev regarding color scaling. Anyway here's a further simplified version of your script import yt
ds = yt.load("snap_032.hdf5")
left_edge = [ds.domain_left_edge[0],ds.domain_left_edge[1],0*ds.domain_left_edge[0]]
right_edge = [ds.domain_right_edge[0],ds.domain_right_edge[1],0.5*ds.domain_right_edge[2]]
my_slice = ds.box(left_edge, right_edge)
Pos = [22000,22000,22000]
Width = 23000
proj = yt.ProjectionPlot(ds, "z", ("gas","O_number_density"), data_source=my_slice,center=Pos,width=Width,buff_size=(50,50))
proj.set_log(("gas","O_number_density"), True, linthresh=1e-8)
proj.save("test.png") |
Nice, that's the issue with the colorbar not being scaled. I like that you did it with fewer pixels, so that it runs faster. I would guess that in the loss gap, the particles are being mapped twice, once positive and once negative, and cancelling each other out. But that's just an uneducated guess and I haven't looked at the code. |
I think an important hint is that we're setting |
So no that's in code units, and that is 23000/h (h=0.6711). I spent a lot of time checking if this is a units issue, and as far as I can tell, it's not, because I changed everything (ds.domain_edges, etc.) to physical kpc, and other similar tests. It can be explored, but I feel like I exhausted those avenues. |
Oh I see, I incorrectly assumed that the length unit was kpc. Nevermind. |
I think I found a reproducer that doesn't require your 3Gb dataset: import numpy as np
import yt
def fake_ds(hsml_factor):
npart = 3**3
x = np.empty(npart)
y = np.empty(npart)
z = np.empty(npart)
tot = 0
for i in range(0, 3):
for j in range(0, 3):
for k in range(0, 3):
x[tot] = i + 0.5
y[tot] = j + 0.5
z[tot] = k + 0.5
tot += 1
data = {
"particle_position_x": (x, "cm"),
"particle_position_y": (y, "cm"),
"particle_position_z": (z, "cm"),
"particle_mass": (np.ones(npart), "g"),
"particle_velocity_x": (np.zeros(npart), "cm/s"),
"particle_velocity_y": (np.zeros(npart), "cm/s"),
"particle_velocity_z": (np.zeros(npart), "cm/s"),
"smoothing_length": (0.05 * np.ones(npart) * hsml_factor, "cm"),
"density": (np.ones(npart), "g/cm**3"),
"temperature": (np.ones(npart), "K"),
}
bbox = np.array([[0, 3], [0, 3], [0, 3]])
return yt.load_particles(data=data, length_unit=1.0, bbox=bbox)
ds = fake_ds(10)
for w in (3, 2, 1.5):
proj = yt.ProjectionPlot(
ds, "z", ("gas", "density"), center=(2.8, 2.8, 2.8), width=w,
)
proj.save(f"/tmp/test_{w=}.png") outputs So we can see that the further we zoom in, the more data we miss. one last note for today: this issue seems specific to projections indeed. I don't see any problem with the |
Interesting to see this. And yes, I see that as well- the more you zoom in, the more that is missed (which is the other image I showed above from the progression from 23000-26000). I can make more of those from the 3GB dataset to show you the progression more clearly, because it is revealing. Let me get back to you on this in a little bit. |
This is the behavior I see. The gap opens up at the periodic boundary and grows at double the rate of the inverse of the width (when it is smaller than the boxsize) away from the boundary. e.g. width=25 Mpc/h- no gap, 24 Mpc/h- gap from 25-27 Mpc/h, 23 Mpc/h- gap 25-29 Mpc/h, etc. Or so it seems. |
So I've tried tracking this down but for now my results are limited. I know that the following region of the code is hit at pixelisation time (at least in my minimal example)
but so far I haven't been able to find where the actual particle selection is performed. At this point I don't think it's my best shot to just try and find this myself so let's ask for help. @matthewturk, any pointers ? |
So taking a smaller width than the whole box behaves like the bounding box issue in #2639? And the box periodicity is turned off in such a case now? @matthewturk's comment from that thread suggests that regions are prevented from spanning periodic boundaries: "We don't currently allow bbox selections to run off the edge of a domain (i.e., like we do with ds.region), so this shouldn't block anything that works. Is that right?" I believe this issue happens when I don't explicitly set data_source to be a ds.box region, but I can recheck this if necessary. I am using ds.box to have limited depth in the box (or what I call a slice). |
Sorry about the confusion, indeed these problems are not directly related. What I meant to point out is that they both are caused by how particle selection works with periodicity. |
Making progress ! I investigated a bit further and I'm almost certain that the problematic selection happens here: yt/yt/geometry/coordinates/cartesian_coordinates.py Lines 360 to 369 in 2684921
For context:
AFAICT, all these objects are correctly initialised, regarding bounds and periodicity. The only problem seems to be with chunking. |
@neutrinoceros This is sounding somewhat familiar. I have not been able to be checked-in to this as much as I would like, so I will ask a few leading questions -- what happens if you change |
taking my example from #3916 (comment), I obtain and taking my example from #3916 (comment), I obtain So no errors in sight here ! So if I'm reading this right, it confirms my hunch that the IO selection is where the bug is, would you agree ? |
Happy to test this out on my system. Is this the line that needs to be changed?
to something like:
? |
The simplest change is override |
Okay, I'm trying this override. It does solve the problem of the gaps, but I think it is selecting everything, e.g. if I use a region like a box to limit the depth of the projection, I believe it is not using that region to limit the particle selection. But I'll check to make sure. Though you probably can answer that this is the case when using all_data(). Update: Yes, it looks to take the entire depth. |
Hi @neutrinoceros and @matthewturk So the simple override is not a longterm solution. Is there a fix that can be made so one can take regions of limited depth? |
@benopp99 @matthewturk @neutrinoceros I am also seeing this creep up in another situation so I am going to take a whack at it. The main issue here is that when you specify a smaller rectangular region across a periodic boundary, it does not select all of the particles. It actually doesn't have anything to do with projections per se Frankly, this is quite a major bug so I am surprised it's not getting reported more often or isn't getting caught in a test. |
Thanks for pulling this up again. I apologize that it fell off my radar.
Can we check that it is not related to the bitmap indexing somehow?
…On Wed, Aug 3, 2022 at 1:49 PM John ZuHone ***@***.***> wrote:
@benopp99 <https://github.com/benopp99> @matthewturk
<https://github.com/matthewturk> @neutrinoceros
<https://github.com/neutrinoceros> I am also seeing this creep up in
another situation so I am going to take a whack at it. The main issue here
is that when you specify a smaller rectangular region across a periodic
boundary, it does not select all of the particles. It actually doesn't have
anything to do with projections per se
Frankly, this is quite a major bug so I am surprised it's not getting
reported more often or isn't getting caught in a test.
—
Reply to this email directly, view it on GitHub
<#3916 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAVXO2NZJKUUPKCCCYQWV3VXK5NHANCNFSM5VOPJATA>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
@matthewturk I am worried that something is going wrong here: yt/yt/geometry/_selection_routines/region_selector.pxi Lines 139 to 157 in 02d0332
|
right edge shift has always confused me. What happens if you manually
translate the sphere across the six faces and additional corners?
…On Wed, Aug 3, 2022 at 1:56 PM John ZuHone ***@***.***> wrote:
@matthewturk <https://github.com/matthewturk> I am worried that something
is going wrong here:
https://github.com/yt-project/yt/blob/02d03320697a4e3f9c75e6415788b39dff4bfc1a/yt/geometry/_selection_routines/region_selector.pxi#L139-L157
—
Reply to this email directly, view it on GitHub
<#3916 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAVXO6HVUS2ZBGU4UPRAV3VXK6HNANCNFSM5VOPJATA>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
Sorry I haven't been able to follow this. Thank you John for picking it up, I agree this is a major bug. |
Hi @benopp99 can you re-post the file that was originally here: https://wormhole.app/Nmvv4#7VKmczrb6lwxME-ZAje0fQ It's not available anymore. |
This bit of logic at 0e206f0 |
Let me get to this in the morning. I may have to access it differently due
to my Flatirons account expiring.
Glad you all are making headway on this.
-Ben
|
I think if we can figure out the simple example we should be in good shape |
Okay, ping me if you need it. I got sidetracked this morning, but am
available to help.
…On Thu, Aug 4, 2022 at 7:29 AM John ZuHone ***@***.***> wrote:
I think if we can figure out the simple example we should be in good shape
—
Reply to this email directly, view it on GitHub
<#3916 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AMEF72MSRUVKADVGE5SRTDDVXPATPANCNFSM5VOPJATA>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
@benopp99 it would be good to have it just to make sure it's fixed for your case. PR incoming |
Fixed with #4050 |
Yup, the fix was the main motivation for 4.0.5 |
Awesome! |
I've seemingly found an issue with periodic box wrapping in ProjectionPlot. Below is a 25 Mpc/h IllustrisTNG periodic volume, and I kept getting maps zoomed into halos cut off at the periodic boundary. This was seemingly confounding because when I run a whole box, the wrapper works perfectly. After a lot of tinkering, I think it has to do with the width argument being not equal to the domain. I made images of 23000, 24000, 25000, and 26000 kpc/h centered at (22000, 22000, 22000), which I think serves as a good diagnostic of the problem. A loss gap opens up at the periodic boundary (i.e. 25000) and grows as the width becomes smaller (23000 is upper left, 24000 upper right, and so on). Therefore for a ProjectionPlot zoomed on a specific halo near the periodic boundary, you often incorrectly miss the halo. Here's the code snippet (I used FITSProjection which is a wrapper for ProjectionPlot, which has same issue):
Note this is in all types of periodic simulations- EAGLE, Simba too. Maybe I'm doing something wrong, and if there is a quick fix, let me know.
I've added a ProjectionPlot of oxygen (instead of O^6+) to more clearly show the 23000 case.
Version Information
python 3.9.5
yt 4.1.dev0
Note that this issue has been seen in earlier version of yt going back a couple years. i.e. before yt 4.0
The text was updated successfully, but these errors were encountered: