• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

spedas / pyspedas / 25194239086

26 Apr 2026 08:07PM UTC coverage: 61.697% (-28.8%) from 90.54%
25194239086

push

github

jameswilburlewis
Added test for loading Cluster CODIF differential energy flux

0 of 7 new or added lines in 1 file covered. (0.0%)

19460 existing lines in 418 files now uncovered.

30204 of 48955 relevant lines covered (61.7%)

1.44 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

16.85
/pyspedas/cotrans_tools/matrix_array_lib.py
1
import numpy as np
3✔
2

3
# use nansum from bottleneck if it's installed, otherwise use the numpy one
4
try:
3✔
5
    import bottleneck as bn
3✔
6
    nansum = bn.nansum
×
7
except ImportError:
3✔
8
    nansum = np.nansum
3✔
9

10

11
def ctv_err_test(vals, val, err = 1e-5):
3✔
12
    """ used to determine if values are equal within some standard of computational error """
UNCOV
13
    return (vals >= val-err) & (vals <= val+err)
×
14

15

16
def ctv_determ_mats(m):
3✔
17
    """ returns the determinant of a list of 3x3 matrices """
UNCOV
18
    return np.linalg.det(m)
×
19

20

21
def ctv_identity_mats(m):
3✔
22
    """
23
    determines if a list of 3x3 matrices are identity matrices
24
    will return the indexes of the identity matrices in the list of matrices
25
    """
UNCOV
26
    return ctv_err_test(m[:, 0, 0], 1) & ctv_err_test(m[:, 0, 1], 0) & ctv_err_test(m[:, 0, 2], 0) \
×
27
        & ctv_err_test(m[:, 1, 0], 0) & ctv_err_test(m[:, 1, 1], 1) & ctv_err_test(m[:, 1, 2], 0) \
28
        & ctv_err_test(m[:, 2, 0], 0) & ctv_err_test(m[:, 2, 1], 0) & ctv_err_test(m[:, 2, 2], 1)
29

30

31
def ctv_mm_mult(m1, m2):
3✔
32
    """ multiplication of two lists of 3x3 matrices """
UNCOV
33
    out = np.zeros(m1.shape)
×
UNCOV
34
    out[:, 0, 0] = nansum(m1[:, 0, :] * m2[:, :, 0], axis=1)
×
UNCOV
35
    out[:, 1, 0] = nansum(m1[:, 1, :] * m2[:, :, 0], axis=1)
×
UNCOV
36
    out[:, 2, 0] = nansum(m1[:, 2, :] * m2[:, :, 0], axis=1)
×
UNCOV
37
    out[:, 0, 1] = nansum(m1[:, 0, :] * m2[:, :, 1], axis=1)
×
UNCOV
38
    out[:, 1, 1] = nansum(m1[:, 1, :] * m2[:, :, 1], axis=1)
×
UNCOV
39
    out[:, 2, 1] = nansum(m1[:, 2, :] * m2[:, :, 1], axis=1)
×
UNCOV
40
    out[:, 0, 2] = nansum(m1[:, 0, :] * m2[:, :, 2], axis=1)
×
UNCOV
41
    out[:, 1, 2] = nansum(m1[:, 1, :] * m2[:, :, 2], axis=1)
×
UNCOV
42
    out[:, 2, 2] = nansum(m1[:, 2, :] * m2[:, :, 2], axis=1)
×
UNCOV
43
    return out
×
44

45

46
def ctv_verify_mats(m):
3✔
47
    """
48
    verifies whether a list of matrices
49
    contains valid rotation matrices.
50
    This is determined using 2 constraints.
51
    #1 Where determ(matrix) eq 1
52
    #2 Where matrix#transpose(matrix) eq I
53

54
    returns 0 if the matrices use a mixed system
55
    returns 1 if there are no valid mats
56
    returns 2 if the data are all nans
57
    returns 3 if there are some invalid mats
58
    returns 4 if there are some nans
59
    returns 5 win!
60
    """
UNCOV
61
    identity_mats = ctv_identity_mats(ctv_mm_mult(m, np.transpose(m, (0,2,1))))
×
62
    # make sure matrix is self-inverting and the determinate is either 1 in all cases or -1 in all cases
UNCOV
63
    idx = np.argwhere(ctv_err_test(ctv_determ_mats(m),1) & identity_mats)
×
UNCOV
64
    c_right = idx.shape[0]
×
UNCOV
65
    idx = np.argwhere(ctv_err_test(ctv_determ_mats(m),-1) & identity_mats)
×
UNCOV
66
    c_left = idx.shape[0]
×
UNCOV
67
    idx = np.argwhere(~np.isfinite(ctv_determ_mats(m)))
×
UNCOV
68
    c_nan = idx.shape[0]
×
UNCOV
69
    if (c_left != 0) and (c_right != 0): # mixed system
×
70
        return 0
×
UNCOV
71
    elif (c_left == 0) and (c_right == 0): # all matrices fail
×
72
        return 1
×
UNCOV
73
    elif c_nan == m.shape[0]: # all nans
×
74
        return 2
×
UNCOV
75
    elif (c_left+c_right+c_nan < 0): # some matrices fail
×
76
        return 3
×
UNCOV
77
    elif c_nan != 0: # some nans
×
78
        return 4
×
79
    else: # all mats are rotation mats and there is no missing data
UNCOV
80
        return 5
×
81

82

83
def ctv_left_mats(m):
3✔
84
    """
85
    Is this a set of left-handed permutation matrices?
86
    """
UNCOV
87
    idx = np.argwhere(ctv_err_test(ctv_determ_mats(m),-1))
×
UNCOV
88
    c = idx.shape[0]
×
UNCOV
89
    if c > 0:
×
90
        return 1
×
91
    else:
UNCOV
92
        return 0
×
93

94

95
def ctv_swap_hands(m):
3✔
96
    """
97
    Turns a 3x3 matrix with a left-handed basis into a right-handed basis and vice-versa
98
    """
99
    out = m.copy()
×
100
    out[:,0,:] *= -1
×
101
    return out
×
102

103

104
def ctv_norm_vec_rot(v):
3✔
105
    """
106
    Helper function
107
    Calculates the norm of a bunch of vectors simultaneously
108
    """
109
    if v is None:
×
110
        return -1
×
111
    if v.ndim != 2:
×
112
        return -1
×
113
    return np.sqrt(np.sum(v**2, axis=1))
×
114

115

116
def ctv_normalize_vec_rot(v):
3✔
117
    """
118
    Helper function
119
    Normalizes a bunch of vectors simultaneously
120
    """
121
    if v is None:
×
122
        return -1
×
123
    if v.ndim != 2:
×
124
        return -1
×
125
    n_a = ctv_norm_vec_rot(v)
×
126
    if (n_a.ndim == 0) and (n_a == -1):
×
127
        return -1
×
128
    v_s = v.shape
×
129
    # calculation is pretty straight forward
130
    # we turn n_a into an N x D so computation can be done element by element
131
    n_b = np.repeat(n_a, v_s[1]).reshape(v_s)
×
132
    return v/n_b
×
133

134

135
def ctv_mx_vec_rot(m, x):
3✔
136
    """
137
    Helper function
138
    Vectorized fx to multiply n matrices by n vectors
139
    """
140
    # input checks
141
    if m is None:
×
142
        return -1
×
143
    if x is None:
×
144
        return -1
×
145
    m_s = m.shape
×
146
    x_s = x.shape
×
147
    # make sure number of dimensions in input arrays is correct
148
    if len(m_s) != 3:
×
149
        return -1
×
150
    if len(x_s) != 2:
×
151
        return -1
×
152
    # make sure dimensions match
153
    if not np.array_equal(x_s, [m_s[0], m_s[1]]):
×
154
        return -1
×
155
    if not np.array_equal(m_s, [x_s[0], x_s[1], x_s[1]]):
×
156
        return -1
×
157
    # calculation is pretty straight forward
158
    # we turn x into an N x 3 x 3 so computation can be done element by element
159
    y_t = np.repeat(x, x_s[1]*x_s[1]).reshape(x_s[0], x_s[1], x_s[1])
×
160
    # custom multiplication requires rebin to stack vector across rows,
161
    # not columns
162
    y_t = np.transpose(y_t, (0, 2, 1))
×
163
    # 9 multiplications and 3 additions per matrix
164
    y = np.sum(y_t*m, axis=2)
×
165
    return y
×
166

STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc