1import copy 2import operator as op 3import pickle 4import warnings 5 6import pytest 7 8from pint import DimensionalityError, OffsetUnitCalculusError, UnitStrippedWarning 9from pint.compat import np 10from pint.testsuite import helpers 11from pint.testsuite.test_umath import TestUFuncs 12 13 14@helpers.requires_numpy 15class TestNumpyMethods: 16 @classmethod 17 def setup_class(cls): 18 from pint import _DEFAULT_REGISTRY 19 20 cls.ureg = _DEFAULT_REGISTRY 21 cls.Q_ = cls.ureg.Quantity 22 23 @classmethod 24 def teardown_class(cls): 25 cls.ureg = None 26 cls.Q_ = None 27 28 @property 29 def q(self): 30 return [[1, 2], [3, 4]] * self.ureg.m 31 32 @property 33 def q_scalar(self): 34 return np.array(5) * self.ureg.m 35 36 @property 37 def q_nan(self): 38 return [[1, 2], [3, np.nan]] * self.ureg.m 39 40 @property 41 def q_zero_or_nan(self): 42 return [[0, 0], [0, np.nan]] * self.ureg.m 43 44 @property 45 def q_temperature(self): 46 return self.Q_([[1, 2], [3, 4]], self.ureg.degC) 47 48 def assertNDArrayEqual(self, actual, desired): 49 # Assert that the given arrays are equal, and are not Quantities 50 np.testing.assert_array_equal(actual, desired) 51 assert not isinstance(actual, self.Q_) 52 assert not isinstance(desired, self.Q_) 53 54 55class TestNumpyArrayCreation(TestNumpyMethods): 56 # https://docs.scipy.org/doc/numpy/reference/routines.array-creation.html 57 58 @helpers.requires_array_function_protocol() 59 def test_ones_like(self): 60 self.assertNDArrayEqual(np.ones_like(self.q), np.array([[1, 1], [1, 1]])) 61 62 @helpers.requires_array_function_protocol() 63 def test_zeros_like(self): 64 self.assertNDArrayEqual(np.zeros_like(self.q), np.array([[0, 0], [0, 0]])) 65 66 @helpers.requires_array_function_protocol() 67 def test_empty_like(self): 68 ret = np.empty_like(self.q) 69 assert ret.shape == (2, 2) 70 assert isinstance(ret, np.ndarray) 71 72 @helpers.requires_array_function_protocol() 73 def test_full_like(self): 74 helpers.assert_quantity_equal( 75 np.full_like(self.q, self.Q_(0, self.ureg.degC)), 76 self.Q_([[0, 0], [0, 0]], self.ureg.degC), 77 ) 78 self.assertNDArrayEqual(np.full_like(self.q, 2), np.array([[2, 2], [2, 2]])) 79 80 81class TestNumpyArrayManipulation(TestNumpyMethods): 82 # TODO 83 # https://www.numpy.org/devdocs/reference/routines.array-manipulation.html 84 # copyto 85 # broadcast , broadcast_arrays 86 # asarray asanyarray asmatrix asfarray asfortranarray ascontiguousarray asarray_chkfinite asscalar require 87 88 # Changing array shape 89 90 def test_flatten(self): 91 helpers.assert_quantity_equal(self.q.flatten(), [1, 2, 3, 4] * self.ureg.m) 92 93 def test_flat(self): 94 for q, v in zip(self.q.flat, [1, 2, 3, 4]): 95 assert q == v * self.ureg.m 96 97 def test_reshape(self): 98 helpers.assert_quantity_equal( 99 self.q.reshape([1, 4]), [[1, 2, 3, 4]] * self.ureg.m 100 ) 101 102 def test_ravel(self): 103 helpers.assert_quantity_equal(self.q.ravel(), [1, 2, 3, 4] * self.ureg.m) 104 105 @helpers.requires_array_function_protocol() 106 def test_ravel_numpy_func(self): 107 helpers.assert_quantity_equal(np.ravel(self.q), [1, 2, 3, 4] * self.ureg.m) 108 109 # Transpose-like operations 110 111 @helpers.requires_array_function_protocol() 112 def test_moveaxis(self): 113 helpers.assert_quantity_equal( 114 np.moveaxis(self.q, 1, 0), np.array([[1, 2], [3, 4]]).T * self.ureg.m 115 ) 116 117 @helpers.requires_array_function_protocol() 118 def test_rollaxis(self): 119 helpers.assert_quantity_equal( 120 np.rollaxis(self.q, 1), np.array([[1, 2], [3, 4]]).T * self.ureg.m 121 ) 122 123 @helpers.requires_array_function_protocol() 124 def test_swapaxes(self): 125 helpers.assert_quantity_equal( 126 np.swapaxes(self.q, 1, 0), np.array([[1, 2], [3, 4]]).T * self.ureg.m 127 ) 128 129 def test_transpose(self): 130 helpers.assert_quantity_equal( 131 self.q.transpose(), [[1, 3], [2, 4]] * self.ureg.m 132 ) 133 134 @helpers.requires_array_function_protocol() 135 def test_transpose_numpy_func(self): 136 helpers.assert_quantity_equal( 137 np.transpose(self.q), [[1, 3], [2, 4]] * self.ureg.m 138 ) 139 140 @helpers.requires_array_function_protocol() 141 def test_flip_numpy_func(self): 142 helpers.assert_quantity_equal( 143 np.flip(self.q, axis=0), [[3, 4], [1, 2]] * self.ureg.m 144 ) 145 146 # Changing number of dimensions 147 148 @helpers.requires_array_function_protocol() 149 def test_atleast_1d(self): 150 actual = np.atleast_1d(self.Q_(0, self.ureg.degC), self.q.flatten()) 151 expected = (self.Q_(np.array([0]), self.ureg.degC), self.q.flatten()) 152 for ind_actual, ind_expected in zip(actual, expected): 153 helpers.assert_quantity_equal(ind_actual, ind_expected) 154 helpers.assert_quantity_equal(np.atleast_1d(self.q), self.q) 155 156 @helpers.requires_array_function_protocol() 157 def test_atleast_2d(self): 158 actual = np.atleast_2d(self.Q_(0, self.ureg.degC), self.q.flatten()) 159 expected = ( 160 self.Q_(np.array([[0]]), self.ureg.degC), 161 np.array([[1, 2, 3, 4]]) * self.ureg.m, 162 ) 163 for ind_actual, ind_expected in zip(actual, expected): 164 helpers.assert_quantity_equal(ind_actual, ind_expected) 165 helpers.assert_quantity_equal(np.atleast_2d(self.q), self.q) 166 167 @helpers.requires_array_function_protocol() 168 def test_atleast_3d(self): 169 actual = np.atleast_3d(self.Q_(0, self.ureg.degC), self.q.flatten()) 170 expected = ( 171 self.Q_(np.array([[[0]]]), self.ureg.degC), 172 np.array([[[1], [2], [3], [4]]]) * self.ureg.m, 173 ) 174 for ind_actual, ind_expected in zip(actual, expected): 175 helpers.assert_quantity_equal(ind_actual, ind_expected) 176 helpers.assert_quantity_equal( 177 np.atleast_3d(self.q), np.array([[[1], [2]], [[3], [4]]]) * self.ureg.m 178 ) 179 180 @helpers.requires_array_function_protocol() 181 def test_broadcast_to(self): 182 helpers.assert_quantity_equal( 183 np.broadcast_to(self.q[:, 1], (2, 2)), 184 np.array([[2, 4], [2, 4]]) * self.ureg.m, 185 ) 186 187 @helpers.requires_array_function_protocol() 188 def test_expand_dims(self): 189 helpers.assert_quantity_equal( 190 np.expand_dims(self.q, 0), np.array([[[1, 2], [3, 4]]]) * self.ureg.m 191 ) 192 193 @helpers.requires_array_function_protocol() 194 def test_squeeze(self): 195 helpers.assert_quantity_equal(np.squeeze(self.q), self.q) 196 helpers.assert_quantity_equal( 197 self.q.reshape([1, 4]).squeeze(), [1, 2, 3, 4] * self.ureg.m 198 ) 199 200 # Changing number of dimensions 201 # Joining arrays 202 @helpers.requires_array_function_protocol() 203 def test_concat_stack(self, subtests): 204 for func in (np.concatenate, np.stack, np.hstack, np.vstack, np.dstack): 205 with subtests.test(func=func): 206 helpers.assert_quantity_equal( 207 func([self.q] * 2), self.Q_(func([self.q.m] * 2), self.ureg.m) 208 ) 209 # One or more of the args is a bare array full of zeros or NaNs 210 helpers.assert_quantity_equal( 211 func([self.q_zero_or_nan.m, self.q]), 212 self.Q_(func([self.q_zero_or_nan.m, self.q.m]), self.ureg.m), 213 ) 214 # One or more of the args is a bare array with at least one non-zero, 215 # non-NaN element 216 nz = self.q_zero_or_nan 217 nz.m[0, 0] = 1 218 with pytest.raises(DimensionalityError): 219 func([nz.m, self.q]) 220 221 @helpers.requires_array_function_protocol() 222 def test_block_column_stack(self, subtests): 223 for func in (np.block, np.column_stack): 224 with subtests.test(func=func): 225 226 helpers.assert_quantity_equal( 227 func([self.q[:, 0], self.q[:, 1]]), 228 self.Q_(func([self.q[:, 0].m, self.q[:, 1].m]), self.ureg.m), 229 ) 230 231 # One or more of the args is a bare array full of zeros or NaNs 232 helpers.assert_quantity_equal( 233 func( 234 [ 235 self.q_zero_or_nan[:, 0].m, 236 self.q[:, 0], 237 self.q_zero_or_nan[:, 1].m, 238 ] 239 ), 240 self.Q_( 241 func( 242 [ 243 self.q_zero_or_nan[:, 0].m, 244 self.q[:, 0].m, 245 self.q_zero_or_nan[:, 1].m, 246 ] 247 ), 248 self.ureg.m, 249 ), 250 ) 251 # One or more of the args is a bare array with at least one non-zero, 252 # non-NaN element 253 nz = self.q_zero_or_nan 254 nz.m[0, 0] = 1 255 with pytest.raises(DimensionalityError): 256 func([nz[:, 0].m, self.q[:, 0]]) 257 258 @helpers.requires_array_function_protocol() 259 def test_append(self): 260 helpers.assert_quantity_equal( 261 np.append(self.q, [[0, 0]] * self.ureg.m, axis=0), 262 [[1, 2], [3, 4], [0, 0]] * self.ureg.m, 263 ) 264 265 def test_astype(self): 266 actual = self.q.astype(np.float32) 267 expected = self.Q_(np.array([[1.0, 2.0], [3.0, 4.0]], dtype=np.float32), "m") 268 helpers.assert_quantity_equal(actual, expected) 269 assert actual.m.dtype == expected.m.dtype 270 271 def test_item(self): 272 helpers.assert_quantity_equal(self.Q_([[0]], "m").item(), 0 * self.ureg.m) 273 274 275class TestNumpyMathematicalFunctions(TestNumpyMethods): 276 # https://www.numpy.org/devdocs/reference/routines.math.html 277 # Trigonometric functions 278 @helpers.requires_array_function_protocol() 279 def test_unwrap(self): 280 helpers.assert_quantity_equal( 281 np.unwrap([0, 3 * np.pi] * self.ureg.radians), [0, np.pi] 282 ) 283 helpers.assert_quantity_equal( 284 np.unwrap([0, 540] * self.ureg.deg), [0, 180] * self.ureg.deg 285 ) 286 287 # Rounding 288 289 @helpers.requires_array_function_protocol() 290 def test_fix(self): 291 helpers.assert_quantity_equal(np.fix(3.14 * self.ureg.m), 3.0 * self.ureg.m) 292 helpers.assert_quantity_equal(np.fix(3.0 * self.ureg.m), 3.0 * self.ureg.m) 293 helpers.assert_quantity_equal( 294 np.fix([2.1, 2.9, -2.1, -2.9] * self.ureg.m), 295 [2.0, 2.0, -2.0, -2.0] * self.ureg.m, 296 ) 297 298 # Sums, products, differences 299 300 @helpers.requires_array_function_protocol() 301 def test_prod(self): 302 axis = 0 303 where = [[True, False], [True, True]] 304 305 helpers.assert_quantity_equal(self.q.prod(), 24 * self.ureg.m ** 4) 306 helpers.assert_quantity_equal(self.q.prod(axis=axis), [3, 8] * self.ureg.m ** 2) 307 helpers.assert_quantity_equal(self.q.prod(where=where), 12 * self.ureg.m ** 3) 308 309 @helpers.requires_array_function_protocol() 310 def test_prod_numpy_func(self): 311 axis = 0 312 where = [[True, False], [True, True]] 313 314 helpers.assert_quantity_equal(np.prod(self.q), 24 * self.ureg.m ** 4) 315 helpers.assert_quantity_equal( 316 np.prod(self.q, axis=axis), [3, 8] * self.ureg.m ** 2 317 ) 318 helpers.assert_quantity_equal( 319 np.prod(self.q, where=where), 12 * self.ureg.m ** 3 320 ) 321 322 with pytest.raises(DimensionalityError): 323 np.prod(self.q, axis=axis, where=where) 324 helpers.assert_quantity_equal( 325 np.prod(self.q, axis=axis, where=[[True, False], [False, True]]), 326 [1, 4] * self.ureg.m, 327 ) 328 helpers.assert_quantity_equal( 329 np.prod(self.q, axis=axis, where=[True, False]), [3, 1] * self.ureg.m ** 2 330 ) 331 332 def test_sum(self): 333 assert self.q.sum() == 10 * self.ureg.m 334 helpers.assert_quantity_equal(self.q.sum(0), [4, 6] * self.ureg.m) 335 helpers.assert_quantity_equal(self.q.sum(1), [3, 7] * self.ureg.m) 336 337 @helpers.requires_array_function_protocol() 338 def test_sum_numpy_func(self): 339 helpers.assert_quantity_equal(np.sum(self.q, axis=0), [4, 6] * self.ureg.m) 340 with pytest.raises(OffsetUnitCalculusError): 341 np.sum(self.q_temperature) 342 343 @helpers.requires_array_function_protocol() 344 def test_nansum_numpy_func(self): 345 helpers.assert_quantity_equal( 346 np.nansum(self.q_nan, axis=0), [4, 2] * self.ureg.m 347 ) 348 349 def test_cumprod(self): 350 with pytest.raises(DimensionalityError): 351 self.q.cumprod() 352 helpers.assert_quantity_equal((self.q / self.ureg.m).cumprod(), [1, 2, 6, 24]) 353 354 @helpers.requires_array_function_protocol() 355 def test_cumprod_numpy_func(self): 356 with pytest.raises(DimensionalityError): 357 np.cumprod(self.q) 358 with pytest.raises(DimensionalityError): 359 np.cumproduct(self.q) 360 helpers.assert_quantity_equal(np.cumprod(self.q / self.ureg.m), [1, 2, 6, 24]) 361 helpers.assert_quantity_equal( 362 np.cumproduct(self.q / self.ureg.m), [1, 2, 6, 24] 363 ) 364 helpers.assert_quantity_equal( 365 np.cumprod(self.q / self.ureg.m, axis=1), [[1, 2], [3, 12]] 366 ) 367 368 @helpers.requires_array_function_protocol() 369 def test_nancumprod_numpy_func(self): 370 with pytest.raises(DimensionalityError): 371 np.nancumprod(self.q_nan) 372 helpers.assert_quantity_equal( 373 np.nancumprod(self.q_nan / self.ureg.m), [1, 2, 6, 6] 374 ) 375 376 @helpers.requires_array_function_protocol() 377 def test_diff(self): 378 helpers.assert_quantity_equal(np.diff(self.q, 1), [[1], [1]] * self.ureg.m) 379 helpers.assert_quantity_equal( 380 np.diff(self.q_temperature, 1), [[1], [1]] * self.ureg.delta_degC 381 ) 382 383 @helpers.requires_array_function_protocol() 384 def test_ediff1d(self): 385 helpers.assert_quantity_equal(np.ediff1d(self.q), [1, 1, 1] * self.ureg.m) 386 helpers.assert_quantity_equal( 387 np.ediff1d(self.q_temperature), [1, 1, 1] * self.ureg.delta_degC 388 ) 389 390 @helpers.requires_array_function_protocol() 391 def test_gradient(self): 392 grad = np.gradient([[1, 1], [3, 4]] * self.ureg.m, 1 * self.ureg.J) 393 helpers.assert_quantity_equal( 394 grad[0], [[2.0, 3.0], [2.0, 3.0]] * self.ureg.m / self.ureg.J 395 ) 396 helpers.assert_quantity_equal( 397 grad[1], [[0.0, 0.0], [1.0, 1.0]] * self.ureg.m / self.ureg.J 398 ) 399 400 grad = np.gradient(self.Q_([[1, 1], [3, 4]], self.ureg.degC), 1 * self.ureg.J) 401 helpers.assert_quantity_equal( 402 grad[0], [[2.0, 3.0], [2.0, 3.0]] * self.ureg.delta_degC / self.ureg.J 403 ) 404 helpers.assert_quantity_equal( 405 grad[1], [[0.0, 0.0], [1.0, 1.0]] * self.ureg.delta_degC / self.ureg.J 406 ) 407 408 @helpers.requires_array_function_protocol() 409 def test_cross(self): 410 a = [[3, -3, 1]] * self.ureg.kPa 411 b = [[4, 9, 2]] * self.ureg.m ** 2 412 helpers.assert_quantity_equal( 413 np.cross(a, b), [[-15, -2, 39]] * self.ureg.kPa * self.ureg.m ** 2 414 ) 415 416 @helpers.requires_array_function_protocol() 417 def test_trapz(self): 418 helpers.assert_quantity_equal( 419 np.trapz([1.0, 2.0, 3.0, 4.0] * self.ureg.J, dx=1 * self.ureg.m), 420 7.5 * self.ureg.J * self.ureg.m, 421 ) 422 423 @helpers.requires_array_function_protocol() 424 def test_dot(self): 425 helpers.assert_quantity_equal( 426 self.q.ravel().dot(np.array([1, 0, 0, 1])), 5 * self.ureg.m 427 ) 428 429 @helpers.requires_array_function_protocol() 430 def test_dot_numpy_func(self): 431 helpers.assert_quantity_equal( 432 np.dot(self.q.ravel(), [0, 0, 1, 0] * self.ureg.dimensionless), 433 3 * self.ureg.m, 434 ) 435 436 @helpers.requires_array_function_protocol() 437 def test_einsum(self): 438 a = np.arange(25).reshape(5, 5) * self.ureg.m 439 b = np.arange(5) * self.ureg.m 440 helpers.assert_quantity_equal(np.einsum("ii", a), 60 * self.ureg.m) 441 helpers.assert_quantity_equal( 442 np.einsum("ii->i", a), np.array([0, 6, 12, 18, 24]) * self.ureg.m 443 ) 444 helpers.assert_quantity_equal(np.einsum("i,i", b, b), 30 * self.ureg.m ** 2) 445 helpers.assert_quantity_equal( 446 np.einsum("ij,j", a, b), 447 np.array([30, 80, 130, 180, 230]) * self.ureg.m ** 2, 448 ) 449 450 @helpers.requires_array_function_protocol() 451 def test_solve(self): 452 A = self.q 453 b = [[3], [7]] * self.ureg.s 454 x = np.linalg.solve(A, b) 455 456 helpers.assert_quantity_almost_equal(x, self.Q_([[1], [1]], "s / m")) 457 458 helpers.assert_quantity_almost_equal(np.dot(A, x), b) 459 460 # Arithmetic operations 461 def test_addition_with_scalar(self): 462 a = np.array([0, 1, 2]) 463 b = 10.0 * self.ureg("gram/kilogram") 464 helpers.assert_quantity_almost_equal( 465 a + b, self.Q_([0.01, 1.01, 2.01], self.ureg.dimensionless) 466 ) 467 helpers.assert_quantity_almost_equal( 468 b + a, self.Q_([0.01, 1.01, 2.01], self.ureg.dimensionless) 469 ) 470 471 def test_addition_with_incompatible_scalar(self): 472 a = np.array([0, 1, 2]) 473 b = 1.0 * self.ureg.m 474 with pytest.raises(DimensionalityError): 475 op.add(a, b) 476 with pytest.raises(DimensionalityError): 477 op.add(b, a) 478 479 def test_power(self): 480 arr = np.array(range(3), dtype=np.float) 481 q = self.Q_(arr, "meter") 482 483 for op_ in [op.pow, op.ipow, np.power]: 484 q_cp = copy.copy(q) 485 with pytest.raises(DimensionalityError): 486 op_(2.0, q_cp) 487 arr_cp = copy.copy(arr) 488 arr_cp = copy.copy(arr) 489 q_cp = copy.copy(q) 490 with pytest.raises(DimensionalityError): 491 op_(q_cp, arr_cp) 492 q_cp = copy.copy(q) 493 q2_cp = copy.copy(q) 494 with pytest.raises(DimensionalityError): 495 op_(q_cp, q2_cp) 496 497 helpers.assert_quantity_equal( 498 np.power(self.q, self.Q_(2)), self.Q_([[1, 4], [9, 16]], "m**2") 499 ) 500 helpers.assert_quantity_equal( 501 self.q ** self.Q_(2), self.Q_([[1, 4], [9, 16]], "m**2") 502 ) 503 self.assertNDArrayEqual(arr ** self.Q_(2), np.array([0, 1, 4])) 504 505 def test_sqrt(self): 506 q = self.Q_(100, "m**2") 507 helpers.assert_quantity_equal(np.sqrt(q), self.Q_(10, "m")) 508 509 def test_cbrt(self): 510 q = self.Q_(1000, "m**3") 511 helpers.assert_quantity_equal(np.cbrt(q), self.Q_(10, "m")) 512 513 @pytest.mark.xfail 514 @helpers.requires_numpy 515 def test_exponentiation_array_exp_2(self): 516 arr = np.array(range(3), dtype=np.float) 517 # q = self.Q_(copy.copy(arr), None) 518 q = self.Q_(copy.copy(arr), "meter") 519 arr_cp = copy.copy(arr) 520 q_cp = copy.copy(q) 521 # this fails as expected since numpy 1.8.0 but... 522 with pytest.raises(DimensionalityError): 523 op.pow(arr_cp, q_cp) 524 # ..not for op.ipow ! 525 # q_cp is treated as if it is an array. The units are ignored. 526 # Quantity.__ipow__ is never called 527 arr_cp = copy.copy(arr) 528 q_cp = copy.copy(q) 529 with pytest.raises(DimensionalityError): 530 op.ipow(arr_cp, q_cp) 531 532 533class TestNumpyUnclassified(TestNumpyMethods): 534 def test_tolist(self): 535 with pytest.raises(AttributeError): 536 (5 * self.ureg.m).tolist() 537 538 assert self.q.tolist() == [ 539 [1 * self.ureg.m, 2 * self.ureg.m], 540 [3 * self.ureg.m, 4 * self.ureg.m], 541 ] 542 543 def test_fill(self): 544 tmp = self.q 545 tmp.fill(6 * self.ureg.ft) 546 helpers.assert_quantity_equal(tmp, [[6, 6], [6, 6]] * self.ureg.ft) 547 tmp.fill(5 * self.ureg.m) 548 helpers.assert_quantity_equal(tmp, [[5, 5], [5, 5]] * self.ureg.m) 549 550 def test_take(self): 551 helpers.assert_quantity_equal(self.q.take([0, 1, 2, 3]), self.q.flatten()) 552 553 def test_put(self): 554 q = [1.0, 2.0, 3.0, 4.0] * self.ureg.m 555 q.put([0, 2], [10.0, 20.0] * self.ureg.m) 556 helpers.assert_quantity_equal(q, [10.0, 2.0, 20.0, 4.0] * self.ureg.m) 557 558 q = [1.0, 2.0, 3.0, 4.0] * self.ureg.m 559 q.put([0, 2], [1.0, 2.0] * self.ureg.mm) 560 helpers.assert_quantity_equal(q, [0.001, 2.0, 0.002, 4.0] * self.ureg.m) 561 562 q = [1.0, 2.0, 3.0, 4.0] * self.ureg.m / self.ureg.mm 563 q.put([0, 2], [1.0, 2.0]) 564 helpers.assert_quantity_equal( 565 q, [0.001, 2.0, 0.002, 4.0] * self.ureg.m / self.ureg.mm 566 ) 567 568 q = [1.0, 2.0, 3.0, 4.0] * self.ureg.m 569 with pytest.raises(DimensionalityError): 570 q.put([0, 2], [4.0, 6.0] * self.ureg.J) 571 with pytest.raises(DimensionalityError): 572 q.put([0, 2], [4.0, 6.0]) 573 574 def test_repeat(self): 575 helpers.assert_quantity_equal( 576 self.q.repeat(2), [1, 1, 2, 2, 3, 3, 4, 4] * self.ureg.m 577 ) 578 579 def test_sort(self): 580 q = [4, 5, 2, 3, 1, 6] * self.ureg.m 581 q.sort() 582 helpers.assert_quantity_equal(q, [1, 2, 3, 4, 5, 6] * self.ureg.m) 583 584 @helpers.requires_array_function_protocol() 585 def test_sort_numpy_func(self): 586 q = [4, 5, 2, 3, 1, 6] * self.ureg.m 587 helpers.assert_quantity_equal(np.sort(q), [1, 2, 3, 4, 5, 6] * self.ureg.m) 588 589 def test_argsort(self): 590 q = [1, 4, 5, 6, 2, 9] * self.ureg.MeV 591 self.assertNDArrayEqual(q.argsort(), [0, 4, 1, 2, 3, 5]) 592 593 @helpers.requires_array_function_protocol() 594 def test_argsort_numpy_func(self): 595 self.assertNDArrayEqual(np.argsort(self.q, axis=0), np.array([[0, 0], [1, 1]])) 596 597 def test_diagonal(self): 598 q = [[1, 2, 3], [1, 2, 3], [1, 2, 3]] * self.ureg.m 599 helpers.assert_quantity_equal(q.diagonal(offset=1), [2, 3] * self.ureg.m) 600 601 @helpers.requires_array_function_protocol() 602 def test_diagonal_numpy_func(self): 603 q = [[1, 2, 3], [1, 2, 3], [1, 2, 3]] * self.ureg.m 604 helpers.assert_quantity_equal(np.diagonal(q, offset=-1), [1, 2] * self.ureg.m) 605 606 def test_compress(self): 607 helpers.assert_quantity_equal( 608 self.q.compress([False, True], axis=0), [[3, 4]] * self.ureg.m 609 ) 610 helpers.assert_quantity_equal( 611 self.q.compress([False, True], axis=1), [[2], [4]] * self.ureg.m 612 ) 613 614 @helpers.requires_array_function_protocol() 615 def test_compress_nep18(self): 616 helpers.assert_quantity_equal( 617 np.compress([False, True], self.q, axis=1), [[2], [4]] * self.ureg.m 618 ) 619 620 def test_searchsorted(self): 621 q = self.q.flatten() 622 self.assertNDArrayEqual(q.searchsorted([1.5, 2.5] * self.ureg.m), [1, 2]) 623 q = self.q.flatten() 624 with pytest.raises(DimensionalityError): 625 q.searchsorted([1.5, 2.5]) 626 627 @helpers.requires_array_function_protocol() 628 def test_searchsorted_numpy_func(self): 629 """Test searchsorted as numpy function.""" 630 q = self.q.flatten() 631 self.assertNDArrayEqual(np.searchsorted(q, [1.5, 2.5] * self.ureg.m), [1, 2]) 632 633 def test_nonzero(self): 634 q = [1, 0, 5, 6, 0, 9] * self.ureg.m 635 self.assertNDArrayEqual(q.nonzero()[0], [0, 2, 3, 5]) 636 637 @helpers.requires_array_function_protocol() 638 def test_nonzero_numpy_func(self): 639 q = [1, 0, 5, 6, 0, 9] * self.ureg.m 640 self.assertNDArrayEqual(np.nonzero(q)[0], [0, 2, 3, 5]) 641 642 @helpers.requires_array_function_protocol() 643 def test_any_numpy_func(self): 644 q = [0, 1] * self.ureg.m 645 assert np.any(q) 646 with pytest.raises(ValueError): 647 np.any(self.q_temperature) 648 649 @helpers.requires_array_function_protocol() 650 def test_all_numpy_func(self): 651 q = [0, 1] * self.ureg.m 652 assert not np.all(q) 653 with pytest.raises(ValueError): 654 np.all(self.q_temperature) 655 656 @helpers.requires_array_function_protocol() 657 def test_count_nonzero_numpy_func(self): 658 q = [1, 0, 5, 6, 0, 9] * self.ureg.m 659 assert np.count_nonzero(q) == 4 660 661 def test_max(self): 662 assert self.q.max() == 4 * self.ureg.m 663 664 def test_max_numpy_func(self): 665 assert np.max(self.q) == 4 * self.ureg.m 666 667 @helpers.requires_array_function_protocol() 668 def test_max_with_axis_arg(self): 669 helpers.assert_quantity_equal(np.max(self.q, axis=1), [2, 4] * self.ureg.m) 670 671 @helpers.requires_array_function_protocol() 672 def test_max_with_initial_arg(self): 673 helpers.assert_quantity_equal( 674 np.max(self.q[..., None], axis=2, initial=3 * self.ureg.m), 675 [[3, 3], [3, 4]] * self.ureg.m, 676 ) 677 678 @helpers.requires_array_function_protocol() 679 def test_nanmax(self): 680 assert np.nanmax(self.q_nan) == 3 * self.ureg.m 681 682 def test_argmax(self): 683 assert self.q.argmax() == 3 684 685 @helpers.requires_array_function_protocol() 686 def test_argmax_numpy_func(self): 687 self.assertNDArrayEqual(np.argmax(self.q, axis=0), np.array([1, 1])) 688 689 @helpers.requires_array_function_protocol() 690 def test_nanargmax_numpy_func(self): 691 self.assertNDArrayEqual(np.nanargmax(self.q_nan, axis=0), np.array([1, 0])) 692 693 def test_maximum(self): 694 helpers.assert_quantity_equal( 695 np.maximum(self.q, self.Q_([0, 5], "m")), self.Q_([[1, 5], [3, 5]], "m") 696 ) 697 698 def test_min(self): 699 assert self.q.min() == 1 * self.ureg.m 700 701 @helpers.requires_array_function_protocol() 702 def test_min_numpy_func(self): 703 assert np.min(self.q) == 1 * self.ureg.m 704 705 @helpers.requires_array_function_protocol() 706 def test_min_with_axis_arg(self): 707 helpers.assert_quantity_equal(np.min(self.q, axis=1), [1, 3] * self.ureg.m) 708 709 @helpers.requires_array_function_protocol() 710 def test_min_with_initial_arg(self): 711 helpers.assert_quantity_equal( 712 np.min(self.q[..., None], axis=2, initial=3 * self.ureg.m), 713 [[1, 2], [3, 3]] * self.ureg.m, 714 ) 715 716 @helpers.requires_array_function_protocol() 717 def test_nanmin(self): 718 assert np.nanmin(self.q_nan) == 1 * self.ureg.m 719 720 def test_argmin(self): 721 assert self.q.argmin() == 0 722 723 @helpers.requires_array_function_protocol() 724 def test_argmin_numpy_func(self): 725 self.assertNDArrayEqual(np.argmin(self.q, axis=0), np.array([0, 0])) 726 727 @helpers.requires_array_function_protocol() 728 def test_nanargmin_numpy_func(self): 729 self.assertNDArrayEqual(np.nanargmin(self.q_nan, axis=0), np.array([0, 0])) 730 731 def test_minimum(self): 732 helpers.assert_quantity_equal( 733 np.minimum(self.q, self.Q_([0, 5], "m")), self.Q_([[0, 2], [0, 4]], "m") 734 ) 735 736 def test_ptp(self): 737 assert self.q.ptp() == 3 * self.ureg.m 738 739 @helpers.requires_array_function_protocol() 740 def test_ptp_numpy_func(self): 741 helpers.assert_quantity_equal(np.ptp(self.q, axis=0), [2, 2] * self.ureg.m) 742 743 def test_clip(self): 744 helpers.assert_quantity_equal( 745 self.q.clip(max=2 * self.ureg.m), [[1, 2], [2, 2]] * self.ureg.m 746 ) 747 helpers.assert_quantity_equal( 748 self.q.clip(min=3 * self.ureg.m), [[3, 3], [3, 4]] * self.ureg.m 749 ) 750 helpers.assert_quantity_equal( 751 self.q.clip(min=2 * self.ureg.m, max=3 * self.ureg.m), 752 [[2, 2], [3, 3]] * self.ureg.m, 753 ) 754 helpers.assert_quantity_equal( 755 self.q.clip(3 * self.ureg.m, None), [[3, 3], [3, 4]] * self.ureg.m 756 ) 757 helpers.assert_quantity_equal( 758 self.q.clip(3 * self.ureg.m), [[3, 3], [3, 4]] * self.ureg.m 759 ) 760 with pytest.raises(DimensionalityError): 761 self.q.clip(self.ureg.J) 762 with pytest.raises(DimensionalityError): 763 self.q.clip(1) 764 765 @helpers.requires_array_function_protocol() 766 def test_clip_numpy_func(self): 767 helpers.assert_quantity_equal( 768 np.clip(self.q, 150 * self.ureg.cm, None), [[1.5, 2], [3, 4]] * self.ureg.m 769 ) 770 771 def test_round(self): 772 q = [1, 1.33, 5.67, 22] * self.ureg.m 773 helpers.assert_quantity_equal(q.round(0), [1, 1, 6, 22] * self.ureg.m) 774 helpers.assert_quantity_equal(q.round(-1), [0, 0, 10, 20] * self.ureg.m) 775 helpers.assert_quantity_equal(q.round(1), [1, 1.3, 5.7, 22] * self.ureg.m) 776 777 @helpers.requires_array_function_protocol() 778 def test_round_numpy_func(self): 779 helpers.assert_quantity_equal( 780 np.around(1.0275 * self.ureg.m, decimals=2), 1.03 * self.ureg.m 781 ) 782 helpers.assert_quantity_equal( 783 np.round_(1.0275 * self.ureg.m, decimals=2), 1.03 * self.ureg.m 784 ) 785 786 def test_trace(self): 787 assert self.q.trace() == (1 + 4) * self.ureg.m 788 789 def test_cumsum(self): 790 helpers.assert_quantity_equal(self.q.cumsum(), [1, 3, 6, 10] * self.ureg.m) 791 792 @helpers.requires_array_function_protocol() 793 def test_cumsum_numpy_func(self): 794 helpers.assert_quantity_equal( 795 np.cumsum(self.q, axis=0), [[1, 2], [4, 6]] * self.ureg.m 796 ) 797 798 @helpers.requires_array_function_protocol() 799 def test_nancumsum_numpy_func(self): 800 helpers.assert_quantity_equal( 801 np.nancumsum(self.q_nan, axis=0), [[1, 2], [4, 2]] * self.ureg.m 802 ) 803 804 def test_mean(self): 805 assert self.q.mean() == 2.5 * self.ureg.m 806 807 @helpers.requires_array_function_protocol() 808 def test_mean_numpy_func(self): 809 assert np.mean(self.q) == 2.5 * self.ureg.m 810 assert np.mean(self.q_temperature) == self.Q_(2.5, self.ureg.degC) 811 812 @helpers.requires_array_function_protocol() 813 def test_nanmean_numpy_func(self): 814 assert np.nanmean(self.q_nan) == 2 * self.ureg.m 815 816 @helpers.requires_array_function_protocol() 817 def test_average_numpy_func(self): 818 helpers.assert_quantity_almost_equal( 819 np.average(self.q, axis=0, weights=[1, 2]), 820 [2.33333, 3.33333] * self.ureg.m, 821 rtol=1e-5, 822 ) 823 824 @helpers.requires_array_function_protocol() 825 def test_median_numpy_func(self): 826 assert np.median(self.q) == 2.5 * self.ureg.m 827 828 @helpers.requires_array_function_protocol() 829 def test_nanmedian_numpy_func(self): 830 assert np.nanmedian(self.q_nan) == 2 * self.ureg.m 831 832 def test_var(self): 833 assert self.q.var() == 1.25 * self.ureg.m ** 2 834 835 @helpers.requires_array_function_protocol() 836 def test_var_numpy_func(self): 837 assert np.var(self.q) == 1.25 * self.ureg.m ** 2 838 839 @helpers.requires_array_function_protocol() 840 def test_nanvar_numpy_func(self): 841 helpers.assert_quantity_almost_equal( 842 np.nanvar(self.q_nan), 0.66667 * self.ureg.m ** 2, rtol=1e-5 843 ) 844 845 def test_std(self): 846 helpers.assert_quantity_almost_equal( 847 self.q.std(), 1.11803 * self.ureg.m, rtol=1e-5 848 ) 849 850 @helpers.requires_array_function_protocol() 851 def test_std_numpy_func(self): 852 helpers.assert_quantity_almost_equal( 853 np.std(self.q), 1.11803 * self.ureg.m, rtol=1e-5 854 ) 855 with pytest.raises(OffsetUnitCalculusError): 856 np.std(self.q_temperature) 857 858 def test_cumprod(self): 859 with pytest.raises(DimensionalityError): 860 self.q.cumprod() 861 helpers.assert_quantity_equal((self.q / self.ureg.m).cumprod(), [1, 2, 6, 24]) 862 863 @helpers.requires_array_function_protocol() 864 def test_nanstd_numpy_func(self): 865 helpers.assert_quantity_almost_equal( 866 np.nanstd(self.q_nan), 0.81650 * self.ureg.m, rtol=1e-5 867 ) 868 869 def test_conj(self): 870 helpers.assert_quantity_equal((self.q * (1 + 1j)).conj(), self.q * (1 - 1j)) 871 helpers.assert_quantity_equal( 872 (self.q * (1 + 1j)).conjugate(), self.q * (1 - 1j) 873 ) 874 875 def test_getitem(self): 876 with pytest.raises(IndexError): 877 self.q.__getitem__((0, 10)) 878 helpers.assert_quantity_equal(self.q[0], [1, 2] * self.ureg.m) 879 assert self.q[1, 1] == 4 * self.ureg.m 880 881 def test_setitem(self): 882 with pytest.raises(TypeError): 883 self.q[0, 0] = 1 884 with pytest.raises(DimensionalityError): 885 self.q[0, 0] = 1 * self.ureg.J 886 with pytest.raises(DimensionalityError): 887 self.q[0] = 1 888 with pytest.raises(DimensionalityError): 889 self.q[0] = np.ndarray([1, 2]) 890 with pytest.raises(DimensionalityError): 891 self.q[0] = 1 * self.ureg.J 892 893 q = self.q.copy() 894 q[0] = 1 * self.ureg.m 895 helpers.assert_quantity_equal(q, [[1, 1], [3, 4]] * self.ureg.m) 896 897 q = self.q.copy() 898 q[...] = 1 * self.ureg.m 899 helpers.assert_quantity_equal(q, [[1, 1], [1, 1]] * self.ureg.m) 900 901 q = self.q.copy() 902 q[:] = 1 * self.ureg.m 903 helpers.assert_quantity_equal(q, [[1, 1], [1, 1]] * self.ureg.m) 904 905 # check and see that dimensionless num bers work correctly 906 q = [0, 1, 2, 3] * self.ureg.dimensionless 907 q[0] = 1 908 helpers.assert_quantity_equal(q, np.asarray([1, 1, 2, 3])) 909 q[0] = self.ureg.m / self.ureg.mm 910 helpers.assert_quantity_equal(q, np.asarray([1000, 1, 2, 3])) 911 912 q = [0.0, 1.0, 2.0, 3.0] * self.ureg.m / self.ureg.mm 913 q[0] = 1.0 914 helpers.assert_quantity_equal(q, [0.001, 1, 2, 3] * self.ureg.m / self.ureg.mm) 915 916 # Check that this properly masks the first item without warning 917 q = self.ureg.Quantity( 918 np.ma.array([0.0, 1.0, 2.0, 3.0], mask=[False, True, False, False]), "m" 919 ) 920 with warnings.catch_warnings(record=True) as w: 921 q[0] = np.ma.masked 922 # Check for no warnings 923 assert not w 924 assert q.mask[0] 925 926 def test_iterator(self): 927 for q, v in zip(self.q.flatten(), [1, 2, 3, 4]): 928 assert q == v * self.ureg.m 929 930 def test_iterable(self): 931 assert np.iterable(self.q) 932 assert not np.iterable(1 * self.ureg.m) 933 934 def test_reversible_op(self): 935 """ """ 936 x = self.q.magnitude 937 u = self.Q_(np.ones(x.shape)) 938 helpers.assert_quantity_equal(x / self.q, u * x / self.q) 939 helpers.assert_quantity_equal(x * self.q, u * x * self.q) 940 helpers.assert_quantity_equal(x + u, u + x) 941 helpers.assert_quantity_equal(x - u, -(u - x)) 942 943 def test_pickle(self, subtests): 944 for protocol in range(pickle.HIGHEST_PROTOCOL + 1): 945 with subtests.test(protocol): 946 q1 = [10, 20] * self.ureg.m 947 q2 = pickle.loads(pickle.dumps(q1, protocol)) 948 self.assertNDArrayEqual(q1.magnitude, q2.magnitude) 949 assert q1.units == q2.units 950 951 def test_equal(self): 952 x = self.q.magnitude 953 u = self.Q_(np.ones(x.shape)) 954 true = np.ones_like(x, dtype=np.bool_) 955 false = np.zeros_like(x, dtype=np.bool_) 956 957 helpers.assert_quantity_equal(u, u) 958 helpers.assert_quantity_equal(u == u, u.magnitude == u.magnitude) 959 helpers.assert_quantity_equal(u == 1, u.magnitude == 1) 960 961 v = self.Q_(np.zeros(x.shape), "m") 962 w = self.Q_(np.ones(x.shape), "m") 963 self.assertNDArrayEqual(v == 1, false) 964 self.assertNDArrayEqual( 965 self.Q_(np.zeros_like(x), "m") == self.Q_(np.zeros_like(x), "s"), 966 false, 967 ) 968 self.assertNDArrayEqual(v == v, true) 969 self.assertNDArrayEqual(v == w, false) 970 self.assertNDArrayEqual(v == w.to("mm"), false) 971 self.assertNDArrayEqual(u == v, false) 972 973 def test_shape(self): 974 u = self.Q_(np.arange(12)) 975 u.shape = 4, 3 976 assert u.magnitude.shape == (4, 3) 977 978 @helpers.requires_array_function_protocol() 979 def test_shape_numpy_func(self): 980 assert np.shape(self.q) == (2, 2) 981 982 @helpers.requires_array_function_protocol() 983 def test_alen_numpy_func(self): 984 assert np.alen(self.q) == 2 985 986 @helpers.requires_array_function_protocol() 987 def test_ndim_numpy_func(self): 988 assert np.ndim(self.q) == 2 989 990 @helpers.requires_array_function_protocol() 991 def test_copy_numpy_func(self): 992 q_copy = np.copy(self.q) 993 helpers.assert_quantity_equal(self.q, q_copy) 994 assert self.q is not q_copy 995 996 @helpers.requires_array_function_protocol() 997 def test_trim_zeros_numpy_func(self): 998 q = [0, 4, 3, 0, 2, 2, 0, 0, 0] * self.ureg.m 999 helpers.assert_quantity_equal(np.trim_zeros(q), [4, 3, 0, 2, 2] * self.ureg.m) 1000 1001 @helpers.requires_array_function_protocol() 1002 def test_result_type_numpy_func(self): 1003 assert np.result_type(self.q) == np.dtype("int") 1004 1005 @helpers.requires_array_function_protocol() 1006 def test_nan_to_num_numpy_func(self): 1007 helpers.assert_quantity_equal( 1008 np.nan_to_num(self.q_nan, nan=-999 * self.ureg.mm), 1009 [[1, 2], [3, -0.999]] * self.ureg.m, 1010 ) 1011 1012 @helpers.requires_array_function_protocol() 1013 def test_meshgrid_numpy_func(self): 1014 x = [1, 2] * self.ureg.m 1015 y = [0, 50, 100] * self.ureg.mm 1016 xx, yy = np.meshgrid(x, y) 1017 helpers.assert_quantity_equal(xx, [[1, 2], [1, 2], [1, 2]] * self.ureg.m) 1018 helpers.assert_quantity_equal(yy, [[0, 0], [50, 50], [100, 100]] * self.ureg.mm) 1019 1020 @helpers.requires_array_function_protocol() 1021 def test_isclose_numpy_func(self): 1022 q2 = [[1000.05, 2000], [3000.00007, 4001]] * self.ureg.mm 1023 self.assertNDArrayEqual( 1024 np.isclose(self.q, q2), np.array([[False, True], [True, False]]) 1025 ) 1026 self.assertNDArrayEqual( 1027 np.isclose(self.q, q2, atol=1e-5, rtol=1e-7), 1028 np.array([[False, True], [True, False]]), 1029 ) 1030 1031 @helpers.requires_array_function_protocol() 1032 def test_interp_numpy_func(self): 1033 x = [1, 4] * self.ureg.m 1034 xp = np.linspace(0, 3, 5) * self.ureg.m 1035 fp = self.Q_([0, 5, 10, 15, 20], self.ureg.degC) 1036 helpers.assert_quantity_almost_equal( 1037 np.interp(x, xp, fp), self.Q_([6.66667, 20.0], self.ureg.degC), rtol=1e-5 1038 ) 1039 1040 x_ = np.array([1, 4]) 1041 xp_ = np.linspace(0, 3, 5) 1042 fp_ = [0, 5, 10, 15, 20] 1043 1044 helpers.assert_quantity_almost_equal( 1045 np.interp(x_, xp_, fp), self.Q_([6.6667, 20.0], self.ureg.degC), rtol=1e-5 1046 ) 1047 helpers.assert_quantity_almost_equal( 1048 np.interp(x, xp, fp_), [6.6667, 20.0], rtol=1e-5 1049 ) 1050 1051 def test_comparisons(self): 1052 self.assertNDArrayEqual( 1053 self.q > 2 * self.ureg.m, np.array([[False, False], [True, True]]) 1054 ) 1055 self.assertNDArrayEqual( 1056 self.q < 2 * self.ureg.m, np.array([[True, False], [False, False]]) 1057 ) 1058 1059 @helpers.requires_array_function_protocol() 1060 def test_where(self): 1061 helpers.assert_quantity_equal( 1062 np.where(self.q >= 2 * self.ureg.m, self.q, 20 * self.ureg.m), 1063 [[20, 2], [3, 4]] * self.ureg.m, 1064 ) 1065 helpers.assert_quantity_equal( 1066 np.where(self.q >= 2 * self.ureg.m, self.q, 0), 1067 [[0, 2], [3, 4]] * self.ureg.m, 1068 ) 1069 helpers.assert_quantity_equal( 1070 np.where(self.q >= 2 * self.ureg.m, self.q, np.nan), 1071 [[np.nan, 2], [3, 4]] * self.ureg.m, 1072 ) 1073 helpers.assert_quantity_equal( 1074 np.where(self.q >= 3 * self.ureg.m, 0, self.q), 1075 [[1, 2], [0, 0]] * self.ureg.m, 1076 ) 1077 helpers.assert_quantity_equal( 1078 np.where(self.q >= 3 * self.ureg.m, np.nan, self.q), 1079 [[1, 2], [np.nan, np.nan]] * self.ureg.m, 1080 ) 1081 helpers.assert_quantity_equal( 1082 np.where(self.q >= 2 * self.ureg.m, self.q, np.array(np.nan)), 1083 [[np.nan, 2], [3, 4]] * self.ureg.m, 1084 ) 1085 helpers.assert_quantity_equal( 1086 np.where(self.q >= 3 * self.ureg.m, np.array(np.nan), self.q), 1087 [[1, 2], [np.nan, np.nan]] * self.ureg.m, 1088 ) 1089 with pytest.raises(DimensionalityError): 1090 np.where( 1091 self.q < 2 * self.ureg.m, 1092 self.q, 1093 0 * self.ureg.J, 1094 ) 1095 1096 @helpers.requires_array_function_protocol() 1097 def test_fabs(self): 1098 helpers.assert_quantity_equal( 1099 np.fabs(self.q - 2 * self.ureg.m), self.Q_([[1, 0], [1, 2]], "m") 1100 ) 1101 1102 @helpers.requires_array_function_protocol() 1103 def test_isin(self): 1104 self.assertNDArrayEqual( 1105 np.isin(self.q, self.Q_([0, 2, 4], "m")), 1106 np.array([[False, True], [False, True]]), 1107 ) 1108 self.assertNDArrayEqual( 1109 np.isin(self.q, self.Q_([0, 2, 4], "J")), 1110 np.array([[False, False], [False, False]]), 1111 ) 1112 self.assertNDArrayEqual( 1113 np.isin(self.q, [self.Q_(2, "m"), self.Q_(4, "J")]), 1114 np.array([[False, True], [False, False]]), 1115 ) 1116 self.assertNDArrayEqual( 1117 np.isin(self.q, self.q.m), np.array([[False, False], [False, False]]) 1118 ) 1119 self.assertNDArrayEqual( 1120 np.isin(self.q / self.ureg.cm, [1, 3]), 1121 np.array([[True, False], [True, False]]), 1122 ) 1123 with pytest.raises(ValueError): 1124 np.isin(self.q.m, self.q) 1125 1126 @helpers.requires_array_function_protocol() 1127 def test_percentile(self): 1128 helpers.assert_quantity_equal(np.percentile(self.q, 25), self.Q_(1.75, "m")) 1129 1130 @helpers.requires_array_function_protocol() 1131 def test_nanpercentile(self): 1132 helpers.assert_quantity_equal( 1133 np.nanpercentile(self.q_nan, 25), self.Q_(1.5, "m") 1134 ) 1135 1136 @helpers.requires_array_function_protocol() 1137 def test_quantile(self): 1138 helpers.assert_quantity_equal(np.quantile(self.q, 0.25), self.Q_(1.75, "m")) 1139 1140 @helpers.requires_array_function_protocol() 1141 def test_nanquantile(self): 1142 helpers.assert_quantity_equal( 1143 np.nanquantile(self.q_nan, 0.25), self.Q_(1.5, "m") 1144 ) 1145 1146 @helpers.requires_array_function_protocol() 1147 def test_copyto(self): 1148 a = self.q.m 1149 q = copy.copy(self.q) 1150 np.copyto(q, 2 * q, where=[True, False]) 1151 helpers.assert_quantity_equal(q, self.Q_([[2, 2], [6, 4]], "m")) 1152 np.copyto(q, 0, where=[[False, False], [True, False]]) 1153 helpers.assert_quantity_equal(q, self.Q_([[2, 2], [0, 4]], "m")) 1154 np.copyto(a, q) 1155 self.assertNDArrayEqual(a, np.array([[2, 2], [0, 4]])) 1156 1157 @helpers.requires_array_function_protocol() 1158 def test_tile(self): 1159 helpers.assert_quantity_equal( 1160 np.tile(self.q, 2), np.array([[1, 2, 1, 2], [3, 4, 3, 4]]) * self.ureg.m 1161 ) 1162 1163 @helpers.requires_numpy_at_least("1.20") 1164 @helpers.requires_array_function_protocol() 1165 def test_sliding_window_view(self): 1166 q = self.Q_([[1, 2, 2, 1], [2, 1, 1, 2], [1, 2, 2, 1]], "m") 1167 actual = np.lib.stride_tricks.sliding_window_view(q, window_shape=(3, 3)) 1168 expected = self.Q_( 1169 [[[[1, 2, 2], [2, 1, 1], [1, 2, 2]], [[2, 2, 1], [1, 1, 2], [2, 2, 1]]]], 1170 "m", 1171 ) 1172 helpers.assert_quantity_equal(actual, expected) 1173 1174 @helpers.requires_array_function_protocol() 1175 def test_rot90(self): 1176 helpers.assert_quantity_equal( 1177 np.rot90(self.q), np.array([[2, 4], [1, 3]]) * self.ureg.m 1178 ) 1179 1180 @helpers.requires_array_function_protocol() 1181 def test_insert(self): 1182 helpers.assert_quantity_equal( 1183 np.insert(self.q, 1, 0 * self.ureg.m, axis=1), 1184 np.array([[1, 0, 2], [3, 0, 4]]) * self.ureg.m, 1185 ) 1186 1187 def test_ndarray_downcast(self): 1188 with pytest.warns(UnitStrippedWarning): 1189 np.asarray(self.q) 1190 1191 def test_ndarray_downcast_with_dtype(self): 1192 with pytest.warns(UnitStrippedWarning): 1193 qarr = np.asarray(self.q, dtype=np.float64) 1194 assert qarr.dtype == np.float64 1195 1196 def test_array_protocol_unavailable(self): 1197 for attr in ("__array_struct__", "__array_interface__"): 1198 with pytest.raises(AttributeError): 1199 getattr(self.q, attr) 1200 1201 @helpers.requires_array_function_protocol() 1202 def test_resize(self): 1203 helpers.assert_quantity_equal( 1204 np.resize(self.q, (2, 4)), [[1, 2, 3, 4], [1, 2, 3, 4]] * self.ureg.m 1205 ) 1206 1207 @helpers.requires_array_function_protocol() 1208 def test_pad(self): 1209 # Tests reproduced with modification from NumPy documentation 1210 a = [1, 2, 3, 4, 5] * self.ureg.m 1211 b = self.Q_([4.0, 6.0, 8.0, 9.0, -3.0], "degC") 1212 1213 helpers.assert_quantity_equal( 1214 np.pad(a, (2, 3), "constant"), [0, 0, 1, 2, 3, 4, 5, 0, 0, 0] * self.ureg.m 1215 ) 1216 helpers.assert_quantity_equal( 1217 np.pad(a, (2, 3), "constant", constant_values=(0, 600 * self.ureg.cm)), 1218 [0, 0, 1, 2, 3, 4, 5, 6, 6, 6] * self.ureg.m, 1219 ) 1220 helpers.assert_quantity_equal( 1221 np.pad( 1222 b, (2, 1), "constant", constant_values=(np.nan, self.Q_(10, "degC")) 1223 ), 1224 self.Q_([np.nan, np.nan, 4, 6, 8, 9, -3, 10], "degC"), 1225 ) 1226 with pytest.raises(DimensionalityError): 1227 np.pad(a, (2, 3), "constant", constant_values=4) 1228 helpers.assert_quantity_equal( 1229 np.pad(a, (2, 3), "edge"), [1, 1, 1, 2, 3, 4, 5, 5, 5, 5] * self.ureg.m 1230 ) 1231 helpers.assert_quantity_equal( 1232 np.pad(a, (2, 3), "linear_ramp"), 1233 [0, 0, 1, 2, 3, 4, 5, 3, 1, 0] * self.ureg.m, 1234 ) 1235 helpers.assert_quantity_equal( 1236 np.pad(a, (2, 3), "linear_ramp", end_values=(5, -4) * self.ureg.m), 1237 [5, 3, 1, 2, 3, 4, 5, 2, -1, -4] * self.ureg.m, 1238 ) 1239 helpers.assert_quantity_equal( 1240 np.pad(a, (2,), "maximum"), [5, 5, 1, 2, 3, 4, 5, 5, 5] * self.ureg.m 1241 ) 1242 helpers.assert_quantity_equal( 1243 np.pad(a, (2,), "mean"), [3, 3, 1, 2, 3, 4, 5, 3, 3] * self.ureg.m 1244 ) 1245 helpers.assert_quantity_equal( 1246 np.pad(a, (2,), "median"), [3, 3, 1, 2, 3, 4, 5, 3, 3] * self.ureg.m 1247 ) 1248 helpers.assert_quantity_equal( 1249 np.pad(self.q, ((3, 2), (2, 3)), "minimum"), 1250 [ 1251 [1, 1, 1, 2, 1, 1, 1], 1252 [1, 1, 1, 2, 1, 1, 1], 1253 [1, 1, 1, 2, 1, 1, 1], 1254 [1, 1, 1, 2, 1, 1, 1], 1255 [3, 3, 3, 4, 3, 3, 3], 1256 [1, 1, 1, 2, 1, 1, 1], 1257 [1, 1, 1, 2, 1, 1, 1], 1258 ] 1259 * self.ureg.m, 1260 ) 1261 helpers.assert_quantity_equal( 1262 np.pad(a, (2, 3), "reflect"), [3, 2, 1, 2, 3, 4, 5, 4, 3, 2] * self.ureg.m 1263 ) 1264 helpers.assert_quantity_equal( 1265 np.pad(a, (2, 3), "reflect", reflect_type="odd"), 1266 [-1, 0, 1, 2, 3, 4, 5, 6, 7, 8] * self.ureg.m, 1267 ) 1268 helpers.assert_quantity_equal( 1269 np.pad(a, (2, 3), "symmetric"), [2, 1, 1, 2, 3, 4, 5, 5, 4, 3] * self.ureg.m 1270 ) 1271 helpers.assert_quantity_equal( 1272 np.pad(a, (2, 3), "symmetric", reflect_type="odd"), 1273 [0, 1, 1, 2, 3, 4, 5, 5, 6, 7] * self.ureg.m, 1274 ) 1275 helpers.assert_quantity_equal( 1276 np.pad(a, (2, 3), "wrap"), [4, 5, 1, 2, 3, 4, 5, 1, 2, 3] * self.ureg.m 1277 ) 1278 1279 def pad_with(vector, pad_width, iaxis, kwargs): 1280 pad_value = kwargs.get("padder", 10) 1281 vector[: pad_width[0]] = pad_value 1282 vector[-pad_width[1] :] = pad_value 1283 1284 b = self.Q_(np.arange(6).reshape((2, 3)), "degC") 1285 helpers.assert_quantity_equal( 1286 np.pad(b, 2, pad_with), 1287 self.Q_( 1288 [ 1289 [10, 10, 10, 10, 10, 10, 10], 1290 [10, 10, 10, 10, 10, 10, 10], 1291 [10, 10, 0, 1, 2, 10, 10], 1292 [10, 10, 3, 4, 5, 10, 10], 1293 [10, 10, 10, 10, 10, 10, 10], 1294 [10, 10, 10, 10, 10, 10, 10], 1295 ], 1296 "degC", 1297 ), 1298 ) 1299 helpers.assert_quantity_equal( 1300 np.pad(b, 2, pad_with, padder=100), 1301 self.Q_( 1302 [ 1303 [100, 100, 100, 100, 100, 100, 100], 1304 [100, 100, 100, 100, 100, 100, 100], 1305 [100, 100, 0, 1, 2, 100, 100], 1306 [100, 100, 3, 4, 5, 100, 100], 1307 [100, 100, 100, 100, 100, 100, 100], 1308 [100, 100, 100, 100, 100, 100, 100], 1309 ], 1310 "degC", 1311 ), 1312 ) # Note: Does not support Quantity pad_with vectorized callable use 1313 1314 @helpers.requires_array_function_protocol() 1315 def test_allclose(self): 1316 assert np.allclose([1e10, 1e-8] * self.ureg.m, [1.00001e10, 1e-9] * self.ureg.m) 1317 assert not np.allclose( 1318 [1e10, 1e-8] * self.ureg.m, [1.00001e10, 1e-9] * self.ureg.mm 1319 ) 1320 1321 @helpers.requires_array_function_protocol() 1322 def test_intersect1d(self): 1323 helpers.assert_quantity_equal( 1324 np.intersect1d([1, 3, 4, 3] * self.ureg.m, [3, 1, 2, 1] * self.ureg.m), 1325 [1, 3] * self.ureg.m, 1326 ) 1327 1328 1329@pytest.mark.skip 1330class TestBitTwiddlingUfuncs(TestUFuncs): 1331 """Universal functions (ufuncs) > Bittwiddling functions 1332 1333 http://docs.scipy.org/doc/numpy/reference/ufuncs.html#bittwiddlingfunctions 1334 1335 bitwise_and(x1, x2[, out]) Compute the bitwise AND of two arrays elementwise. 1336 bitwise_or(x1, x2[, out]) Compute the bitwise OR of two arrays elementwise. 1337 bitwise_xor(x1, x2[, out]) Compute the bitwise XOR of two arrays elementwise. 1338 invert(x[, out]) Compute bitwise inversion, or bitwise NOT, elementwise. 1339 left_shift(x1, x2[, out]) Shift the bits of an integer to the left. 1340 right_shift(x1, x2[, out]) Shift the bits of an integer to the right. 1341 1342 Parameters 1343 ---------- 1344 1345 Returns 1346 ------- 1347 1348 """ 1349 1350 @property 1351 def qless(self): 1352 return np.asarray([1, 2, 3, 4], dtype=np.uint8) * self.ureg.dimensionless 1353 1354 @property 1355 def qs(self): 1356 return 8 * self.ureg.J 1357 1358 @property 1359 def q1(self): 1360 return np.asarray([1, 2, 3, 4], dtype=np.uint8) * self.ureg.J 1361 1362 @property 1363 def q2(self): 1364 return 2 * self.q1 1365 1366 @property 1367 def qm(self): 1368 return np.asarray([1, 2, 3, 4], dtype=np.uint8) * self.ureg.m 1369 1370 def test_bitwise_and(self): 1371 self._test2(np.bitwise_and, self.q1, (self.q2, self.qs), (self.qm,), "same") 1372 1373 def test_bitwise_or(self): 1374 self._test2( 1375 np.bitwise_or, self.q1, (self.q1, self.q2, self.qs), (self.qm,), "same" 1376 ) 1377 1378 def test_bitwise_xor(self): 1379 self._test2( 1380 np.bitwise_xor, self.q1, (self.q1, self.q2, self.qs), (self.qm,), "same" 1381 ) 1382 1383 def test_invert(self): 1384 self._test1(np.invert, (self.q1, self.q2, self.qs), (), "same") 1385 1386 def test_left_shift(self): 1387 self._test2( 1388 np.left_shift, self.q1, (self.qless, 2), (self.q1, self.q2, self.qs), "same" 1389 ) 1390 1391 def test_right_shift(self): 1392 self._test2( 1393 np.right_shift, 1394 self.q1, 1395 (self.qless, 2), 1396 (self.q1, self.q2, self.qs), 1397 "same", 1398 ) 1399