Skip to content
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

cast angle_to_direction to input array type #3444

Closed
raybellwaves opened this issue Mar 18, 2024 · 5 comments
Closed

cast angle_to_direction to input array type #3444

raybellwaves opened this issue Mar 18, 2024 · 5 comments
Labels
Area: Xarray Pertains to xarray integration Type: Feature New functionality
Milestone

Comments

@raybellwaves
Copy link
Contributor

raybellwaves commented Mar 18, 2024

What should we add?

angle_to_direction returns the same dtype as the input arg

Reference

I think other metpy functions do this.

Goal would be to have the code work below

import metpy.calc as mpcalc
from metpy.cbook import example_data

ds = example_data()
ds["wind_direction"] = mpcalc.wind_direction(ds["uwind"], ds["vwind"], convention="from")
ds["wind_direction_categorical"] = mpcalc.angle_to_direction(ds["wind_direction"], level=1)

Currently gives

TypeError                                 Traceback (most recent call last)
Cell In[22], line 6
      4 ds = example_data()
      5 ds["wind_direction"] = mpcalc.wind_direction(ds["uwind"], ds["vwind"], convention="from")
----> 6 ds["wind_direction_categorical"] = mpcalc.angle_to_direction(ds["wind_direction"], level=1)
      7 # wind_direction

File /opt/userenvs/ray.bell/main/lib/python3.10/site-packages/metpy/xarray.py:1329, in preprocess_and_wrap.<locals>.decorator.<locals>.wrapper(*args, **kwargs)
   1326     _mutate_arguments(bound_args, units.Quantity, lambda arg, _: arg.m)
   1328 # Evaluate inner calculation
-> 1329 result = func(*bound_args.args, **bound_args.kwargs)
   1331 # Wrap output based on match and match_unit
   1332 if match is None:

File /opt/userenvs/ray.bell/main/lib/python3.10/site-packages/metpy/calc/tools.py:1885, in angle_to_direction(input_angle, full, level)
   1882 round_angles = (multiplier * BASE_DEGREE_MULTIPLIER.m * nskip)
   1883 round_angles[np.where(np.isnan(round_angles))] = UND_ANGLE
-> 1885 dir_str_arr = itemgetter(*round_angles)(angle_dict)  # for array
   1886 if not full:
   1887     return dir_str_arr

TypeError: unhashable type: 'numpy.ndarray'
@raybellwaves raybellwaves added the Type: Feature New functionality label Mar 18, 2024
@dopplershift dopplershift added the Area: Xarray Pertains to xarray integration label Mar 19, 2024
@raybellwaves
Copy link
Contributor Author

My two cents on how I would like this function to be written if I were to modernize angle_to_direction.

Function can take a single value (str, int, float e.g. "90", 90, 90.), a list, list of lists, numpy array, dask array or xarray dataarray. Internally the input gets cast to an xarray dataarray.

There are functions that are called using a look up of n categorial (4, 8, 16 directions) and short text ("E") or full text ("East").

The function is vectorized and passed to xr.apply_unfunc.

Lastly it returns same dtype as input

I ended up doing something like below for my need:

def wind_dir_to_cat(x, n_categories=4):
    if 45 <= x < 135:
        return "E"
    elif 135 <= x < 225:
        return "S"
    elif 225 <= x < 315:
        return "W"
    else:
        return "N"
wind_dir_to_cat_vec = np.vectorize(wind_dir_to_cat)
ds["wind_direction_categorical"] = xr.apply_ufunc(wind_dir_to_cat_vec, ds["wind_direction"])

@dopplershift
Copy link
Member

How can it return the same dtype as input if it's going from numeric to str?

There's definitely a nice world where lots of MetPy functions work as callables for apply_ufunc. Unfortunately, right now we live in a world where:

  • Not everyone uses xarray
  • Not every dataset is readable into xarray

So right now, we are the opposite, instead of "internally the input gets cast to an xarray dataarray", we take dataarrays and cast them to numpy + units, and translate on the way out. Now, as far as I can tell, that should still accomplish what you're looking for, so I'm curious what problem you saw that made your solution in #3445 unworkable?

@raybellwaves
Copy link
Contributor Author

raybellwaves commented Mar 21, 2024

so I'm curious what problem you saw that made your solution in #3445 unworkable?

Nothing really. I used the code above in my project. Truthfully, i'm not sure how to fix #3445

@raybellwaves
Copy link
Contributor Author

Now at #3448

@dopplershift
Copy link
Member

Fixed by #3448.

@dopplershift dopplershift added this to the 1.7.0 milestone Mar 21, 2024
@dopplershift dopplershift modified the milestones: 1.7.0, 1.6.2 Jun 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: Xarray Pertains to xarray integration Type: Feature New functionality
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants