fosanalysis
A framework to evaluate distributed fiber optic sensor data
Loading...
Searching...
No Matches
misc.py
Go to the documentation of this file.
2r"""
3Contains miscellaneous standalone functions.
4\author Bertram Richter
5\date 2023
6"""
7
8import datetime
9import numpy as np
10
11def find_closest_value(arr: np.array, v: float) -> tuple:
12 r"""
13 Returns index and value in `arr`, that is closest to the given `v`.
14 In case of equal distance of `v` to both neighbors, the smaller one is chosen.
15 \param arr Array like (1D) of values in ascending order.
16 \param v The target value, to which the distance should be minimized.
17 \return `(<index>, <entry>)`
18 """
19 arr = np.array(arr)
20 i = np.searchsorted(arr, v)
21 if i == 0:
22 # v is smaller than any entry of the array
23 pass
24 elif i == arr.shape[0]:
25 # v is larger than any entry of the array
26 i = i-1
27 else:
28 # v between some array entries
29 dist_l = np.abs(v - arr[i-1])
30 dist_r = np.abs(v - arr[i])
31 i = i if dist_r < dist_l else i-1
32 return i, arr[i]
33
34def last_finite_index(arr: np.array, axis: int = -1) -> np.array:
35 r"""
36 Returns an array with the indices of the most recent finite entry
37 when traversing the `arr` along the specified axis.
38 The returned array has the same shape as `arr`.
39
40 Example:
41
42 ```.py
43 >>> arr = np.array([1.,2.,"nan", "inf", 5], dtype=float)
44 array([1., 2., nan, inf, 5.])
45 >>> last_finite_index(arr)
46 array([0, 1, 1, 1, 4])
47 ```
48
49 The first element is assumed to be a finite value.
50 All indices before the first finite entry will be `0`.
51
52 ```.py
53 >>> arr = np.array(["nan","nan", "inf", 5], dtype=float)
54 array([nan, nan, inf, 5.])
55 >>> last_finite_index(arr)
56 array([0, 0, 0, 3])
57 ```
58
59 \param arr Array like.
60 \param axis Axis along which to apply the indexing.
61 Defaults to the last axis.
62 """
63 arr = np.array(arr)
64 is_finite = np.isfinite(arr)
65 finite_indices = np.argwhere(is_finite)
66 last_finite_array = np.zeros_like(arr, dtype=int)
67 last_finite_array[is_finite] = finite_indices[:,axis]
68 last_finite_array = np.maximum.accumulate(last_finite_array, axis=axis)
69 return last_finite_array
70
71def nan_diff_1d(arr: np.array) -> np.array:
72 r"""
73 Calculate the difference to the previous finite entry.
74 This is similar to `np.diff()`, but skipping `NaN` or `inf` entries.
75
76 Example:
77
78 ```.py
79 >>> arr = np.array([1.,2.,"nan", "inf", 5], dtype=float)
80 array([1., 2., nan, inf, 5.])
81 >>> nan_diff_1d(arr)
82 array([1., nan, -inf, 3.])
83 ```
84
85 \param arr Array like, needs to be 1D.
86 """
87 arr = np.array(arr)
88 last_finite_array = last_finite_index(arr)
89 arr_to_diff = arr[last_finite_array]
90 diff_array = arr[1:] - arr_to_diff[:-1]
91 return diff_array
92
93def nan_diff(arr: np.array, axis: int = -1) -> np.array:
94 r"""
95 Calculate the difference to the previous finite entry.
96 This is similar to `np.diff()`, but skipping `NaN` or `inf` entries.
97 This function is a wrapper around \ref nan_diff_1d().
98
99 Example:
100
101 ```.py
102 >>> arr = np.array([1.,2.,"nan", "inf", 5], dtype=float)
103 array([1., 2., nan, inf, 5.])
104 >>> nan_diff(arr)
105 array([1., nan, -inf, 3.])
106 ```
107
108 \param arr Array like.
109 \param axis Axis along which to calculate the incremental difference.
110 Defaults to the last axis.
111 """
112 return np.apply_along_axis(nan_diff_1d, axis=axis, arr=arr)
113
115 array: np.array,
116 index: int,
117 to_left: bool,
118 recurse: int = 0,
119 ) -> tuple:
120 r"""
121 Find the next finite neighbor of the entry `array[index]`.
122 An entry `<entry>` is finite, if `np.isfinite(<entry>) == True`.
123 \param array Array, on which the search is carried out.
124 \param index Position in the `array`, where the search is started.
125 \param to_left `True`, if a neighbor to the left of the starting index should be found, `False` for a neighbor to the right.
126 \param recurse Number of recursions, that are done. Examples:
127 - `0`: direct neighbors of the starting index
128 - `1`: neighbors of the neighbors
129 - `2`: neighbors of the neighbors' neighbors
130 - and so on.
131 \return Tuple like `(<index>, <entry>)`.
132 If no finite value could be found before reaching the end of `array` `(None, None)` is returned.
133 """
134 i = index
135 result = None
136 result_index = None
137 while True:
138 i = i - 1 if to_left else i + 1
139 if (0 <= i <= len(array) - 1):
140 if np.isfinite(array[i]):
141 result = array[i]
142 result_index = i
143 break
144 else:
145 break
146 if result_index is not None and recurse > 0:
147 result_index, result = next_finite_neighbor(array=array, index=result_index, to_left=to_left, recurse=recurse-1)
148 return result_index, result
149
150def np_to_python(data):
151 r"""
152 Convert the given data to a Python built-in type.
153 This function should be used, when type-checking.
154 Iterables are recursively converted into `list` and instances of
155 `np.scalar` are converted into standard data types using the method
156 [`np.item()`](https://numpy.org/doc/stable/reference/generated/numpy.ndarray.item.html).
157 """
158 try:
159 return [np_to_python(i) for i in data]
160 except TypeError:
161 return data.item() if isinstance(data, np.generic) else data
162
163def datetime_to_timestamp(datetime_array: np.array) -> np.array:
164 r"""
165 Converts an array of datetime entries to an array of Unix timestamps.
166 \param datetime_array Array of datetime objects.
167 \return Returns an array of Unix timestamps.
168 """
169 return np.vectorize(datetime.datetime.timestamp)(datetime_array)
170
171def timestamp_to_datetime(timestamp_array: np.array) -> np.array:
172 r"""
173 Converts an array of Unix timestamps to an array of datetime entries.
174 \param timestamp_array Array of `float`s, representing Unix timestamps.
175 \return Returns an array of `datetime.datetime` objects.
176 """
177 return np.vectorize(datetime.datetime.fromtimestamp)(timestamp_array)
tuple next_finite_neighbor(np.array array, int index, bool to_left, int recurse=0)
Find the next finite neighbor of the entry array[index].
Definition misc.py:119
np.array nan_diff_1d(np.array arr)
Calculate the difference to the previous finite entry.
Definition misc.py:71
np.array timestamp_to_datetime(np.array timestamp_array)
Converts an array of Unix timestamps to an array of datetime entries.
Definition misc.py:171
np_to_python(data)
Convert the given data to a Python built-in type.
Definition misc.py:150
np.array nan_diff(np.array arr, int axis=-1)
Calculate the difference to the previous finite entry.
Definition misc.py:93
np.array datetime_to_timestamp(np.array datetime_array)
Converts an array of datetime entries to an array of Unix timestamps.
Definition misc.py:163
tuple find_closest_value(np.array arr, float v)
Returns index and value in arr, that is closest to the given v.
Definition misc.py:11
np.array last_finite_index(np.array arr, int axis=-1)
Returns an array with the indices of the most recent finite entry when traversing the arr along the s...
Definition misc.py:34