Coverage for C: \ Users \ peaco \ OneDrive \ Documents \ GitHub \ mth5 \ mth5 \ timeseries \ xarray_helpers.py: 100%

39 statements  

« prev     ^ index     » next       coverage.py v7.13.1, created at 2026-01-10 00:01 -0800

1""" 

2Module containing helper functions for working with xarray objects. 

3""" 

4 

5from typing import Optional, Union 

6 

7import numpy as np 

8import xarray as xr 

9 

10 

11def covariance_xr( 

12 X: xr.DataArray, 

13 aweights: Optional[Union[np.ndarray, None]] = None, 

14 bias: Optional[bool] = False, 

15 rowvar: Optional[bool] = False, 

16) -> xr.DataArray: 

17 """ 

18 Compute the covariance matrix with numpy.cov. 

19 

20 Parameters 

21 ---------- 

22 X: xarray.core.dataarray.DataArray 

23 Multivariate time series as an xarray 

24 aweights: array_like, optional 

25 Passthrough param for np.cov. 

26 1-D array of observation vector weights. These relative weights are 

27 typically large for observations considered "important" and smaller for 

28 observations considered less "important". If ``ddof=0`` the array of 

29 weights can be used to assign probabilities to observation vectors. 

30 bias: bool 

31 Passthrough param for np.cov. 

32 Default normalization (False) is by ``(N - 1)``, where ``N`` is the 

33 number of observations given (unbiased estimate). If `bias` is True, 

34 then normalization is by ``N``. These values can be overridden by using 

35 the keyword ``ddof`` in numpy versions >= 1.5. 

36 rowvar: bool 

37 Passthrough param for np.cov. 

38 If `rowvar` is True (default), then each row represents a 

39 variable, with observations in the columns. Otherwise, the relationship 

40 is transposed: each column represents a variable, while the rows 

41 contain observations. 

42 

43 Returns 

44 ------- 

45 S: xarray.DataArray 

46 The covariance matrix of the data in xarray form. 

47 

48 Development Notes: 

49 In case of ValueError: conflicting sizes for dimension 'channel_1', this likely means the bool for rowvar 

50 should be flipped. 

51 """ 

52 

53 channels = list(X.coords["variable"].values) 

54 

55 cov_result = np.cov(X.values, rowvar=rowvar, aweights=aweights, bias=bias) 

56 

57 # Handle scalar result for single variable 

58 if cov_result.ndim == 0: 

59 cov_result = np.array([[cov_result]]) 

60 

61 S = xr.DataArray( 

62 cov_result, 

63 dims=["channel_1", "channel_2"], 

64 coords={"channel_1": channels, "channel_2": channels}, 

65 ) 

66 return S 

67 

68 

69def initialize_xrda_1d( 

70 channels: list, 

71 dtype: Optional[type] = None, 

72 value: Optional[Union[complex, float, bool]] = 0.0, 

73) -> xr.DataArray: 

74 """ 

75 Returns a 1D xr.DataArray with variable "channel", having values channels named by the input list. 

76 

77 Parameters 

78 ---------- 

79 channels: list 

80 The channels in the multivariate array 

81 dtype: type, optional 

82 The datatype to initialize the array. 

83 Common cases are complex, float, and bool 

84 value: Union[complex, float, bool], optional 

85 The default value to assign the array 

86 

87 Returns 

88 ------- 

89 xrda: xarray.core.dataarray.DataArray 

90 An xarray container for the channels, initialized to zeros. 

91 """ 

92 k = len(channels) 

93 xrda = xr.DataArray( 

94 np.zeros(k, dtype=dtype), 

95 dims=[ 

96 "variable", 

97 ], 

98 coords={ 

99 "variable": channels, 

100 }, 

101 ) 

102 if value != 0: 

103 data = value * np.ones(k, dtype=dtype) 

104 xrda.data = data 

105 return xrda 

106 

107 

108def initialize_xrds_2d( 

109 variables: list, 

110 coords: dict, 

111 dtype: Optional[type] = complex, 

112 value: Optional[Union[complex, float, bool]] = 0, 

113) -> xr.Dataset: 

114 """ 

115 Returns a 2D xr.Dataset with the given variables and coordinates. 

116 

117 Parameters 

118 ---------- 

119 variables: list 

120 List of variable names to create in the dataset 

121 coords: dict 

122 Dictionary of coordinates for the dataset dimensions 

123 dtype: type, optional 

124 The datatype to initialize the arrays. 

125 Common cases are complex, float, and bool 

126 value: Union[complex, float, bool], optional 

127 The default value to assign the arrays 

128 

129 Returns 

130 ------- 

131 xrds: xr.Dataset 

132 A 2D xarray Dataset with dimensions from coords 

133 """ 

134 # Get dimensions from coords 

135 dims = list(coords.keys()) 

136 shape = tuple(len(v) for v in coords.values()) 

137 

138 # Initialize empty dataset 

139 xrds = xr.Dataset(coords=coords) 

140 

141 # Add each variable 

142 for var in variables: 

143 if value == 0: 

144 data = np.zeros(shape, dtype=dtype) 

145 else: 

146 data = value * np.ones(shape, dtype=dtype) 

147 

148 xrds[var] = xr.DataArray(data, dims=dims, coords=coords) 

149 

150 return xrds 

151 

152 

153def initialize_xrda_2d( 

154 variables: list, coords: dict, dtype: type = complex, value: Union[int, float] = 0.0 

155) -> xr.Dataset: 

156 """Initialize a 3D xarray DataArray with dimensions from coords plus 'variable'. 

157 

158 Parameters 

159 ---------- 

160 variables : list 

161 List of variable names for the additional dimension. 

162 coords : dict 

163 Dictionary of coordinates for the dataset dimensions. 

164 dtype : type, optional 

165 Data type for the array, by default complex. 

166 value : int or float, optional 

167 Value to initialize the array with, by default 0. 

168 

169 Returns 

170 ------- 

171 xr.DataArray 

172 A 3D DataArray with dimensions from coords plus 'variable'. 

173 """ 

174 # Create Dataset first 

175 ds = initialize_xrds_2d(variables, coords, dtype, value) 

176 

177 # Convert to DataArray with original dimension order plus 'variable' 

178 dims = list(coords.keys()) 

179 da = ds.to_array(dim="variable").transpose(*dims, "variable") 

180 

181 return da 

182 

183 

184def initialize_xrda_2d_cov( 

185 channels, dtype=complex, value: Optional[Union[complex, float, bool]] = 0 

186): 

187 """ 

188 TODO: consider changing nomenclature from dims=["channel_1", "channel_2"], 

189 to dims=["variable_1", "variable_2"], to be consistent with initialize_xrda_1d 

190 

191 Parameters 

192 ---------- 

193 channels: list 

194 The channels in the multivariate array. The covariance matrix will be square 

195 with dimensions len(channels) x len(channels). 

196 dtype: type 

197 The datatype to initialize the array. 

198 Common cases are complex, float, and bool 

199 value: Union[complex, float, bool] 

200 The default value to assign the array 

201 

202 Returns 

203 ------- 

204 xrda: xarray.core.dataarray.DataArray 

205 An xarray container for the channel covariances, initialized to zeros. 

206 The matrix is square with dimensions len(channels) x len(channels). 

207 """ 

208 K = len(channels) 

209 xrda = xr.DataArray( 

210 np.zeros((K, K), dtype=dtype), 

211 dims=["channel_1", "channel_2"], 

212 coords={"channel_1": channels, "channel_2": channels}, 

213 ) 

214 if value != 0: 

215 data = value * np.ones(xrda.shape, dtype=dtype) 

216 xrda.data = data 

217 

218 return xrda