Coverage for src/scores/functions.py: 100%

16 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2024-02-28 12:51 +1100

1from typing import overload 

2 

3import numpy as np 

4import xarray as xr 

5 

6from scores.typing import XarrayLike 

7 

8 

9def apply_weights(values, weights=None): 

10 """ 

11 Returns: 

12 A new array with the elements of values multiplied by the specified weights. 

13 

14 Args: 

15 - weights: The weightings to be used at every location in the values array. If weights contains additional 

16 dimensions, these will be taken to mean that multiple weightings are wanted simultaneoulsy, and these 

17 dimensions will be added to the new array. 

18 - values: The unweighted values to be used as the basis for weighting calculation 

19 

20 

21 Note - this weighting function is different to the .weighted method contained in xarray in that xarray's 

22 method does not allow NaNs to be present in the weights or data. 

23 """ 

24 

25 if weights is not None: 

26 result = values * weights 

27 return result 

28 

29 return values 

30 

31 

32def create_latitude_weights(latitudes): 

33 """ 

34 A common way of weighting errors is to make them proportional to the amount of area 

35 which is contained in a particular region. This is approximated by the cosine 

36 of the latitude on an LLXY grid. Nuances not accounted for include the variation in 

37 latitude across the region, or the irregularity of the surface of the earth. 

38 

39 Returns: 

40 An xarray containing the weight values to be used for area approximation 

41 

42 Args: 

43 An xarray (or castable type) containing latitudes between +90 and -90 degrees 

44 

45 Note - floating point behaviour can vary between systems, precisions and other factors 

46 """ 

47 weights = np.cos(np.deg2rad(latitudes)) 

48 return weights 

49 

50 

51# Dataset input types lead to a Dataset return type 

52@overload 

53def angular_difference(source_a: xr.Dataset, source_b: xr.Dataset) -> xr.Dataset: 

54 ... 

55 

56 

57# DataArray input types lead to a DataArray return type 

58@overload 

59def angular_difference(source_a: xr.DataArray, source_b: xr.DataArray) -> xr.DataArray: 

60 ... 

61 

62 

63def angular_difference(source_a: XarrayLike, source_b: XarrayLike) -> XarrayLike: 

64 """ 

65 Determines, in degrees, the smaller of the two explementary angles between 

66 two sources of directional data (e.g. wind direction). 

67 

68 Args: 

69 source_a: direction data in degrees, first source 

70 source_b: direction data in degrees, second source 

71 

72 Returns: 

73 An array containing angles within the range [0, 180]. 

74 """ 

75 difference = np.abs(source_a - source_b) % 360 

76 difference = difference.where(difference <= 180, 360 - difference) 

77 return difference