[yt-users] Best way to create radial bins

Matthew Turk matthewturk at gmail.com
Mon Apr 28 07:00:55 PDT 2014


Hi Thomas,

Thanks for writing, and welcome to yt.  :)

On Sun, Apr 27, 2014 at 3:17 AM, Thomas Hansen <thansen at princeton.edu> wrote:
> Hi everyone,
>
> I'm kind of new to yt and am currently working on creating a set of graphs
> but am having a bit of difficulty.  My goal is to take a list of central
> points (a set of x,y,z coordinates) and then look at a set of 30 spherical
> "shells" which surround the central points.  So I want to be able to know
> how much mass is between, say 30 and 60 parsecs away from a certain point
> (along with 60-90, 90-120, etc.).  The problem is, the number of points is
> absolutely massive, so I need a fairly quick way of finding these values for
> all the points I'm interested in.

So if I understand correctly, you're basically constructing a set of
1D profiles, where each profile has 30 radial bins, but each profile
is also from a *different* central point?  (Similar, say, to doing
profiling on a set of halos in a cosmological simulation.)

>
> I've tried a few tactics already.  First I tried going to each point,
> creating a sphere with that center and the maximum radius.  Then I used the
> center location to set a field parameter, then created a BinnedProfile1D
> using a "radius" field and the sphere I created, but that seemed to be
> impractically slow.

It might be, but I'm wondering if you created your own radius field?
The radius field defined in yt (which will use the "center" field
parameter, which will be set by the sphere) will drop to cython and
avoid temporary copies, which we found has in the past slowed things
down considerably.

>
> Next, I tried the somewhat hackish method of for each point, creating a
> series of 30 spheres with radii corresponding with the boundaries I wanted
> between the shells.  I then used the boolean("NOT") command to construct a
> series of shells by finding the part of each sphere not in the smaller one.
> I could then sum over the values in each shell.  This seemed to go a bit
> faster, but I feel like this could use an absolutely massive amount of
> computation, if I understand how yt works properly.

So I think we might be able to do this slightly differently.  I am
still thinking it through, but I think the problem might be that the
current way you've described it is going to hit a lot of IO,
particularly if the frontend you're using is not optimized for partial
dataset loading.  So what you could imagine doing is trying to get it
all in a single pass.  This will be somewhat tricky, but feasible, if
you define a *set* of derived fields that look at the radius from a
given point and then bin that.  So you could create a set of derived
fields like this.  Note that this codei s for yt-2.x, and I would
encourage you to check that the results look reasonable to you, as I
may have typo'd.

def create_centerpoint_radius(ci_index):
    def _dfield(field, data):
        old_center = data.get_field_parameter("center")
        center = data.get_field_parameter("centerlist")[ci_index]
        data.set_field_parameter("center", center)
        rv = data["RadiusPc"]
        data.set_field_parameter("center", old_center)
        return rv
    return _dfield

for ci in range(len(my_list_of_centers)):
    func = create_centerpoint_radius(ci)
    add_field("Center%04i" % ci, function = func)

pf = load(...
dd = pf.h.all_data()
dd.set_field_parameter("centerlist", my_list_of_centers)
prof = BinnedProfile1D(...
prof.add_fields(["Center%04i" % ci for ci in
range(len(my_list_of_centers))], weight="CellMassMsun")

This might do what you're looking for, but on the other hand, it might
also be the exact opposite?

-Matt

>
> Is there a better way of doing this?
>
> Thank you so much for your time,
> Thomas
>
> _______________________________________________
> yt-users mailing list
> yt-users at lists.spacepope.org
> http://lists.spacepope.org/listinfo.cgi/yt-users-spacepope.org
>



More information about the yt-users mailing list