yt-project / yt

Main yt repository
http://yt-project.org
Other
469 stars 279 forks source link

Threshold by a different field in quivers #4737

Open matthewturk opened 1 year ago

matthewturk commented 1 year ago

It would be useful to apply thresholds to vector plots in yt where the threshold is supplied by another field. For instance, if I am applying a quiver plot to wind velocity, I would like to be able to threshold based on the velocity magnitude. This can currently be implemented with a combination of derived fields, such as:

@yt.derived_field(name=("gas", "uinterp_thresh"), units="m/s", sampling_type="cell")
def uinterp_thresh(field, data):
    windmag = (data["cm1", "uinterp"]**2.0 + data["cm1", "vinterp"]**2.0)**0.5
    rv = data["cm1", "uinterp"].copy()
    rv[windmag < 20 * rv.uq] = np.nan
    return rv

@yt.derived_field(name=("gas", "vinterp_thresh"), units="m/s", sampling_type="cell")
def uinterp_thresh(field, data):
    windmag = (data["cm1", "uinterp"]**2.0 + data["cm1", "vinterp"]**2.0)**0.5
    rv = data["cm1", "vinterp"].copy()
    rv[windmag < 20 * rv.uq] = np.nan
    return rv

But, this is annoying. And, it's not easy to change the threshold value (20 in this case) on-the-fly. It would be good to have an argument to the quiver annotation call that included thresholding information, such as field and value (or expression).

chrishavlin commented 1 year ago

I like this idea!

I initially thought it'd be cool to implement this by adding a data_source kwarg to annotate_quiver -- you could then use a cut_region to apply the thresholding or use any other data source to, e.g., only add the vectors within a spatial region of the plot (distinct from the data source used by the base plot). But then I looked back at the QuiverCallback and I think that'd be a pretty big refactor... and I'm not sure we can even pixelize a cut_region. So ya, your idea of having a specific threshold argument makes more sense :)