dkist-processing-math 2.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,260 @@
1
+ """Affine transforms."""
2
+ from functools import partial
3
+ from typing import Iterable
4
+ from typing import Iterator
5
+ from typing import Tuple
6
+ from typing import Union
7
+
8
+ import numpy as np
9
+ from skimage import transform as skit
10
+
11
+
12
+ def affine_transform_arrays(
13
+ arrays: Union[Iterable[np.ndarray], np.ndarray],
14
+ matrix: np.ndarray = None,
15
+ scale: Union[Tuple[float, float], np.ndarray, float] = None,
16
+ translation: Union[Tuple[float, float], np.ndarray, float] = None,
17
+ rotation: float = None,
18
+ shear: Union[Tuple[float, float], np.ndarray, float] = None,
19
+ **kwargs,
20
+ ) -> Iterator[np.ndarray]:
21
+ """
22
+ Transform an iterable of input arrays using a generalized affine transform operator.
23
+
24
+ A transform matrix may be specified or separate parameters for scale, translation,
25
+ rotation and shear may be specified instead. This method abstracts the use of the
26
+ scikit-image affine transform, which may easily be replaced with one from scipy or
27
+ another origin. If transform parameters are specified, they are applied in this order:
28
+ shear, scale, rotation, translation
29
+
30
+ Parameters
31
+ ----------
32
+ arrays
33
+ The array(s) to be transformed
34
+ matrix
35
+ The transformation matrix to be used for the transform. If specified, none of
36
+ [translation, rotation, or shear] may be used. Optional. If matrix is not specified,
37
+ at least one of the following must be used: scale, translation, rotation, shear
38
+ scale
39
+ The scale factor to be applied in the transform: (Sx, Sy). If a scalar is used, the same
40
+ value is applied to each axis.
41
+ translation
42
+ The translation to be applied in the transform: (Tx, Ty) in pixel units.
43
+ rotation
44
+ The rotation angle, in radians, to be applied to the transformation.
45
+ A positive angle is counter-clockwise in a right handed coordinate system
46
+ shear
47
+ The shear factor to be applied in the transform: (Shx, Shy). If a scalar is used, the same
48
+ value is applied to each axis.
49
+ **kwargs
50
+ Optional arguments to be passed on to skimage.transform.warp() if desired. See
51
+ https://scikit-image.org/docs/stable/api/skimage.transform.html#skimage.transform.warp
52
+ for more details.
53
+
54
+ Returns
55
+ -------
56
+ The transformed array(s)
57
+
58
+ """
59
+ tform = None
60
+ any_param_set = any(param is not None for param in [scale, translation, rotation, shear])
61
+
62
+ # We do our own pre-checks here so that we're not totally tied to use scikit-image in the future
63
+ #
64
+ if not any_param_set and matrix is None:
65
+ raise ValueError(
66
+ "You must specify matrix or at least one of scale, rotate, shear, or shift."
67
+ )
68
+
69
+ elif any_param_set and matrix is not None:
70
+ raise ValueError(
71
+ "You cannot specify both matrix and any of scale, rotate, shear, or shift."
72
+ )
73
+
74
+ elif matrix is not None:
75
+ if matrix.shape != (3, 3):
76
+ raise ValueError(f"Invalid shape of transformation matrix: {matrix.shape}")
77
+ tform = skit.AffineTransform(matrix=matrix)
78
+
79
+ elif any_param_set:
80
+ # Construct the matrix from parameters
81
+ if scale is None:
82
+ scale = (1.0, 1.0)
83
+ elif np.isscalar(scale):
84
+ scale = (scale, scale)
85
+
86
+ if translation is None:
87
+ translation = (0.0, 0.0)
88
+ elif np.isscalar(translation):
89
+ translation = (translation, translation)
90
+
91
+ if rotation is None:
92
+ rotation = 0.0
93
+
94
+ if shear is None:
95
+ shear = (0.0, 0.0)
96
+
97
+ translation = translation[::-1] # Because skimage and numpy have different axes ordering
98
+ shear_mat = shear_matrix(shear)
99
+ temp_tform = skit.AffineTransform(scale=scale, translation=translation, rotation=rotation)
100
+ tform_mat = temp_tform.params @ shear_mat
101
+ tform = skit.AffineTransform(matrix=tform_mat)
102
+
103
+ arrays = [arrays] if isinstance(arrays, np.ndarray) else arrays
104
+ partial_warp = partial(skit.warp, inverse_map=tform.inverse, **kwargs)
105
+ return map(partial_warp, arrays)
106
+
107
+
108
+ def rotate_arrays_about_point(
109
+ arrays: Union[Iterable[np.ndarray], np.ndarray],
110
+ angle: float = 0.0,
111
+ point: Union[Tuple[float, float], np.ndarray] = None,
112
+ **kwargs,
113
+ ) -> Iterator[np.ndarray]:
114
+ """
115
+ Rotate an iterable of arrays about a specified point.
116
+
117
+ Parameters
118
+ ----------
119
+ arrays
120
+ The array(s) to be rotated
121
+
122
+ angle
123
+ The angle, in radians, for the rotation to be applied, optional. Default is zero
124
+ A positive angle is counter-clockwise in a right handed coordinate system and
125
+ clockwise in a left-handed coordinate system
126
+
127
+ point
128
+ The point, in pixel coordinates (x, y) about which to rotate. Optional. Default is None,
129
+ meaning the center of the array will be used. Note that the origin pixel is centered at
130
+ (0, 0) and has extent: [-0.5: 0.5, -0.5: 0.5]
131
+
132
+ kwargs
133
+ Any arguments to be passed to skimage.transform.rotate. See
134
+ https://scikit-image.org/docs/stable/api/skimage.transform.html#skimage.transform.rotate
135
+ for more details.
136
+
137
+ Returns
138
+ -------
139
+ An Iterator yielding the rotated arrays.
140
+
141
+ """
142
+ arrays = [arrays] if isinstance(arrays, np.ndarray) else arrays
143
+ partial_rotate = partial(skit.rotate, angle=np.degrees(angle), center=point, **kwargs)
144
+ return map(partial_rotate, arrays)
145
+
146
+
147
+ def translate_arrays(
148
+ arrays: Union[Iterable[np.ndarray], np.ndarray],
149
+ translation: Union[Tuple[float, float], np.ndarray] = (0.0, 0.0),
150
+ **kwargs,
151
+ ) -> Iterator[np.ndarray]:
152
+ """
153
+ Translate an iterable of arrays by a specified vector.
154
+
155
+ Parameters
156
+ ----------
157
+ arrays
158
+ The array(s) to be translated
159
+
160
+ translation
161
+ The translation to be applied in the transform: (Tx, Ty) in pixel units. Optional.
162
+
163
+ **kwargs
164
+ Optional arguments to be passed on to skimage.transform.warp() if desired. See
165
+ https://scikit-image.org/docs/stable/api/skimage.transform.html#skimage.transform.warp
166
+ for more details.
167
+
168
+ Returns
169
+ -------
170
+ np.ndarray
171
+ The translated array
172
+
173
+ """
174
+ arrays = [arrays] if isinstance(arrays, np.ndarray) else arrays
175
+ return affine_transform_arrays(arrays, translation=translation, **kwargs)
176
+
177
+
178
+ def scale_matrix(scale_factors: Union[Tuple[float, float], float] = (1.0, 1.0)) -> np.ndarray:
179
+ """
180
+ Create an Affine Transform matrix for a scale operation.
181
+
182
+ Parameters
183
+ ----------
184
+ scale_factors
185
+ The scale factors to use in scaling the array. If a scalar is passed, it
186
+ is applied to both axes.
187
+
188
+ Returns
189
+ -------
190
+ A 3x3 homogeneous transform matrix implementing the scaling
191
+
192
+ """
193
+ return skit.AffineTransform(scale=scale_factors).params
194
+
195
+
196
+ def rotation_matrix(angle: float = 0.0) -> np.ndarray:
197
+ """
198
+ Create an Affine Transform matrix for a rotation operation.
199
+
200
+ This assumes the rotation is about (0, 0) and it is up to the user
201
+ to calculate the appropriate translation offset to be applied in the
202
+ skimage.warp() method to achieve rotation about an arbitrary point
203
+
204
+ Parameters
205
+ ----------
206
+ angle
207
+ The angle of rotation in radians. This represents counter-clockwise rotation
208
+ in a right-handed coordinate system and clockwise rotation in a left-handed
209
+ system
210
+
211
+ Returns
212
+ -------
213
+ A 3x3 homogeneous transform matrix implementing the rotation
214
+
215
+ """
216
+ return skit.AffineTransform(rotation=angle).params
217
+
218
+
219
+ def shear_matrix(shear_factors: Union[Tuple[float, float], float] = (1.0, 1.0)) -> np.ndarray:
220
+ """
221
+ Create an Affine Transform matrix for a shear operation.
222
+
223
+ Parameters
224
+ ----------
225
+ shear_factors
226
+ The shear scaling factors.
227
+
228
+ Returns
229
+ -------
230
+ A 3x3 homogeneous transform matrix implementing the shear
231
+
232
+ """
233
+ if isinstance(shear_factors, float):
234
+ shear_factors = shear_factors, shear_factors
235
+ shear_mat = np.eye(3, 3)
236
+ shear_mat[0, 1] = shear_factors[0]
237
+ shear_mat[1, 0] = shear_factors[1]
238
+ return shear_mat
239
+
240
+
241
+ def translation_matrix(offsets: Union[Tuple[float, float], float] = (1.0, 1.0)) -> np.ndarray:
242
+ """
243
+ Create an Affine Transform matrix for a translation operation.
244
+
245
+ Parameters
246
+ ----------
247
+ offsets
248
+ The translation ofsets.
249
+
250
+ Returns
251
+ -------
252
+ A 3x3 homogeneous transform matrix implementing the translation
253
+
254
+ """
255
+ if isinstance(offsets, float):
256
+ offsets = offsets, offsets
257
+ trans_mat = np.eye(3, 3)
258
+ trans_mat[0, 2] = offsets[1]
259
+ trans_mat[1, 2] = offsets[0]
260
+ return trans_mat
@@ -0,0 +1,37 @@
1
+ """Functionality for binary images."""
2
+ import numpy
3
+ import numpy as np
4
+ from skimage import filters as skif
5
+
6
+
7
+ def make_binary(data: numpy.ndarray, numotsu: int = 1) -> np.ndarray:
8
+ """Generate a binary image from an input float or int array.
9
+
10
+ A threshold value is chosen via Otsu's method and all values below the threshold are set to 1 while everything
11
+ else is set to 0. Thus the result is technically an _inverse_ binary image, which is useful for isolating the
12
+ target grid as a feature of interest.
13
+
14
+ Parameters
15
+ ----------
16
+ data
17
+ Data to convert to binary
18
+
19
+ numotsu
20
+ The number of times to perform thresholding using Otsu's method. Numbers larger than 1 are useful if the
21
+ pixel distribution of the data has > 2 modes.
22
+
23
+ Returns
24
+ -------
25
+ An array of 1's and 0's corresponding to the thresholded input data.
26
+
27
+ """
28
+ threshold = np.inf
29
+ for i in range(numotsu):
30
+ tmp = skif.threshold_otsu(data[data < threshold])
31
+ frac = np.sum(data < tmp) / data.size
32
+ # TODO: make this a parameter
33
+ if frac < 1e-3:
34
+ break
35
+ threshold = tmp
36
+ binary = np.array(data < threshold, dtype=int)
37
+ return binary
@@ -0,0 +1,192 @@
1
+ """Binning transforms."""
2
+ from functools import partial
3
+ from typing import Iterable
4
+ from typing import Iterator
5
+ from typing import Literal
6
+ from typing import Tuple
7
+ from typing import Union
8
+
9
+ import numpy as np
10
+ from skimage import transform as skit
11
+
12
+
13
+ def bin_arrays(
14
+ arrays: Union[Iterable[np.ndarray], np.ndarray], bin_factors: (int, int)
15
+ ) -> Iterator[np.ndarray]:
16
+ """
17
+ Bin an iterable of arrays by summation over an integral number of pixels in each dimension.
18
+
19
+ Parameters
20
+ ----------
21
+ arrays
22
+ The arrays to be binned
23
+
24
+ bin_factors
25
+ The bin factors for each axis, which must be integral divisors of each array dimension
26
+
27
+ Returns
28
+ -------
29
+ An Iterator yielding the binned arrays
30
+
31
+ """
32
+ arrays = [arrays] if isinstance(arrays, np.ndarray) else arrays
33
+ partial_bin = partial(_bin_array, bin_factors=bin_factors)
34
+ return map(partial_bin, arrays)
35
+
36
+
37
+ def _bin_array(array: np.ndarray, bin_factors: (int, int)) -> np.ndarray:
38
+ """
39
+ Bin an array by summation over an integral number of pixels in each dimension.
40
+
41
+ Parameters
42
+ ----------
43
+ array
44
+ The array to be binned
45
+
46
+ bin_factors
47
+ The bin factors for each axis, which must be integral divisors of each array dimension
48
+
49
+ Returns
50
+ -------
51
+ The binned array
52
+
53
+ """
54
+ input_shape = array.shape
55
+ if input_shape[0] % bin_factors[0] or input_shape[1] % bin_factors[1]:
56
+ raise ValueError(
57
+ "Array dimensions must be an integral multiple of the binning factor\n"
58
+ f"Shape of array = {input_shape}, binning factors = {bin_factors}"
59
+ )
60
+ return skit.downscale_local_mean(array, bin_factors)
61
+
62
+
63
+ def resize_arrays(
64
+ arrays: Union[Iterable[np.ndarray], np.ndarray],
65
+ output_shape: Tuple[int, ...],
66
+ order: Literal[0, 1, 2, 3, 4, 5] = 0,
67
+ mode: Literal["constant", "edge", "symmetric", "reflect", "wrap"] = "edge",
68
+ ) -> Iterator[np.ndarray]:
69
+ """
70
+ Resize an iterable of arrays using specified interpolation order.
71
+
72
+ This function is more geared towards up-sampling arrays smoothly. For more accurate downsampling see
73
+ `resize_arrays_local_mean`
74
+
75
+ Parameters
76
+ ----------
77
+ arrays
78
+ The arrays to be binned
79
+
80
+ output_shape
81
+ Shape to bin the input arrays to
82
+
83
+ order
84
+ The order of interpolation:
85
+
86
+ 0: Nearest-neighbor
87
+ 1: Bi-linear (default)
88
+ 2: Bi-quadratic
89
+ 3: Bi-cubic
90
+ 4: Bi-quartic
91
+ 5: Bi-quintic
92
+
93
+ mode
94
+ Points outside the boundaries of the input are filled according to the given mode. See `numpy.pad` for explanations.
95
+
96
+ Returns
97
+ -------
98
+ An Iterator yielding the binned arrays
99
+
100
+ """
101
+ arrays = [arrays] if isinstance(arrays, np.ndarray) else arrays
102
+ partial_bin = partial(_resize_array, output_shape=output_shape, order=order, mode=mode)
103
+ return map(partial_bin, arrays)
104
+
105
+
106
+ def _resize_array(
107
+ array: np.ndarray,
108
+ output_shape: Tuple[int, ...],
109
+ order: Literal[0, 1, 2, 3, 4, 5] = 0,
110
+ mode: Literal["constant", "edge", "symmetric", "reflect", "wrap"] = "edge",
111
+ ) -> np.ndarray:
112
+ """
113
+ Resize an array using the given interpolation order.
114
+
115
+ Parameters
116
+ ----------
117
+ array
118
+ The array to be binned
119
+
120
+ output_shape
121
+ Shape to bin the input arrays to
122
+
123
+ order
124
+ The order of interpolation:
125
+
126
+ 0: Nearest-neighbor
127
+ 1: Bi-linear (default)
128
+ 2: Bi-quadratic
129
+ 3: Bi-cubic
130
+ 4: Bi-quartic
131
+ 5: Bi-quintic
132
+
133
+ mode
134
+ Points outside the boundaries of the input are filled according to the given mode. See `numpy.pad` for explanations.
135
+
136
+ Returns
137
+ -------
138
+ The binned array
139
+
140
+ """
141
+ return skit.resize(
142
+ array, output_shape, preserve_range=True, anti_aliasing=False, order=order, mode=mode
143
+ )
144
+
145
+
146
+ def resize_arrays_local_mean(
147
+ arrays: Union[Iterable[np.ndarray], np.ndarray], output_shape: Tuple[int, ...]
148
+ ) -> Iterator[np.ndarray]:
149
+ """
150
+ Bin an iterable of arrays by summation over an integral number of pixels in each dimension.
151
+
152
+ This function is good for downsampling arrays, but acts like nearest-neighbor when upsampling.
153
+ See `resize` for more flexible upsampling options.
154
+
155
+ Note that when downsampling this method is sensitive to extreme outliers.
156
+
157
+ Parameters
158
+ ----------
159
+ arrays
160
+ The arrays to be binned
161
+
162
+ output_shape
163
+ Shape to bin the input arrays to
164
+
165
+ Returns
166
+ -------
167
+ An Iterator yielding the binned arrays
168
+
169
+ """
170
+ arrays = [arrays] if isinstance(arrays, np.ndarray) else arrays
171
+ partial_bin = partial(_resize_array_local_mean, output_shape=output_shape)
172
+ return map(partial_bin, arrays)
173
+
174
+
175
+ def _resize_array_local_mean(array: np.ndarray, output_shape: Tuple[int, ...]) -> np.ndarray:
176
+ """
177
+ Bin an array by summation over an integral number of pixels in each dimension.
178
+
179
+ Parameters
180
+ ----------
181
+ array
182
+ The array to be binned
183
+
184
+ output_shape
185
+ Shape to bin the input arrays to
186
+
187
+ Returns
188
+ -------
189
+ The binned array
190
+
191
+ """
192
+ return skit.resize_local_mean(array, output_shape, preserve_range=True)
@@ -0,0 +1,44 @@
1
+ """Hough transforms."""
2
+ from typing import Tuple
3
+
4
+ import numpy
5
+ import numpy as np
6
+ from skimage import transform as skit
7
+
8
+
9
+ def do_hough(
10
+ binary: numpy.ndarray, theta_min: float, theta_max: float, numtheta: int = 1500
11
+ ) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
12
+ """
13
+ Perform a Hough line transform on input data.
14
+
15
+ Resolution in the angle dimension can be increased via numtheta.
16
+
17
+ Parameters
18
+ ----------
19
+ binary
20
+ An integer array of 1's and 0's
21
+
22
+ theta_min
23
+ The minimum angle to use for the hough transform fitting
24
+
25
+ theta_max
26
+ The maximum angle to use for the hough transform fitting
27
+
28
+ numtheta
29
+ The number of samples in the theta dimension of the Hough transform.
30
+
31
+ Returns
32
+ -------
33
+ A tuple containing:
34
+ - The 2D Hough space (i.e., accumulator) of the input image.
35
+ - A 1D array of the angle values corresponding to the Hough accumulator. Angles will range from -pi/4 to 3/4 pi and the length will be equal to numtheta.
36
+ - A 1D array of the distance values corresponding to the Hough accumulator. This array is entirely determined by skimage.transform.hough_line
37
+
38
+ """
39
+ hough = skit.hough_line(binary, theta=np.linspace(theta_min, theta_max, numtheta))
40
+ hough_accumulator = hough[0]
41
+ theta = hough[1]
42
+ rho = hough[2]
43
+
44
+ return hough_accumulator, theta, rho
@@ -0,0 +1,107 @@
1
+ Metadata-Version: 2.1
2
+ Name: dkist-processing-math
3
+ Version: 2.1.1
4
+ Summary: Common math functionality used in the DKIST calibrations suite
5
+ Author-email: NSO / AURA <dkistdc@nso.edu>
6
+ License: BSD-3-Clause
7
+ Project-URL: Homepage, https://nso.edu/dkist/data-center/
8
+ Project-URL: Repository, https://bitbucket.org/dkistdc/dkist-processing-math/
9
+ Project-URL: Documentation, https://docs.dkist.nso.edu/projects/math
10
+ Project-URL: Help, https://nso.atlassian.net/servicedesk/customer/portal/5
11
+ Classifier: Programming Language :: Python
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Requires-Python: >=3.11
15
+ Description-Content-Type: text/x-rst
16
+ Requires-Dist: dkist-processing-common >=4.0.0
17
+ Requires-Dist: numpy >=1.24.0
18
+ Requires-Dist: scikit-image >=0.21.0
19
+ Requires-Dist: scipy >=1.11.0
20
+ Requires-Dist: peakutils >=1.3.3
21
+ Provides-Extra: docs
22
+ Requires-Dist: sphinx ; extra == 'docs'
23
+ Requires-Dist: sphinx-astropy ; extra == 'docs'
24
+ Requires-Dist: sphinx-changelog ; extra == 'docs'
25
+ Requires-Dist: sphinx-autoapi ; extra == 'docs'
26
+ Requires-Dist: pytest ; extra == 'docs'
27
+ Requires-Dist: towncrier ; extra == 'docs'
28
+ Requires-Dist: dkist-sphinx-theme ; extra == 'docs'
29
+ Provides-Extra: test
30
+ Requires-Dist: pytest ; extra == 'test'
31
+ Requires-Dist: pytest-cov ; extra == 'test'
32
+ Requires-Dist: pytest-mock ; extra == 'test'
33
+ Requires-Dist: hypothesis ; extra == 'test'
34
+ Requires-Dist: towncrier ; extra == 'test'
35
+
36
+ dkist-processing-math
37
+ =====================
38
+
39
+ dkist-processing-math contains the math functions used throughout the DKIST data processing software stack.
40
+
41
+
42
+ Development
43
+ -----------
44
+ .. code-block:: bash
45
+
46
+ git clone git@bitbucket.org:dkistdc/dkist-processing-visp.git
47
+ cd dkist-processing-visp
48
+ pre-commit install
49
+ pip install -e .[test]
50
+ pytest -v --cov dkist_processing_visp
51
+
52
+ Changelog
53
+ #########
54
+
55
+ When you make **any** change to this repository it **MUST** be accompanied by a changelog file.
56
+ The changelog for this repository uses the `towncrier <https://github.com/twisted/towncrier>`__ package.
57
+ Entries in the changelog for the next release are added as individual files (one per change) to the ``changelog/`` directory.
58
+
59
+ Writing a Changelog Entry
60
+ ^^^^^^^^^^^^^^^^^^^^^^^^^
61
+
62
+ A changelog entry accompanying a change should be added to the ``changelog/`` directory.
63
+ The name of a file in this directory follows a specific template::
64
+
65
+ <PULL REQUEST NUMBER>.<TYPE>[.<COUNTER>].rst
66
+
67
+ The fields have the following meanings:
68
+
69
+ * ``<PULL REQUEST NUMBER>``: This is the number of the pull request, so people can jump from the changelog entry to the diff on BitBucket.
70
+ * ``<TYPE>``: This is the type of the change and must be one of the values described below.
71
+ * ``<COUNTER>``: This is an optional field, if you make more than one change of the same type you can append a counter to the subsequent changes, i.e. ``100.bugfix.rst`` and ``100.bugfix.1.rst`` for two bugfix changes in the same PR.
72
+
73
+ The list of possible types is defined the the towncrier section of ``pyproject.toml``, the types are:
74
+
75
+ * ``feature``: This change is a new code feature.
76
+ * ``bugfix``: This is a change which fixes a bug.
77
+ * ``doc``: A documentation change.
78
+ * ``removal``: A deprecation or removal of public API.
79
+ * ``misc``: Any small change which doesn't fit anywhere else, such as a change to the package infrastructure.
80
+
81
+
82
+ Rendering the Changelog at Release Time
83
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
84
+
85
+ When you are about to tag a release first you must run ``towncrier`` to render the changelog.
86
+ The steps for this are as follows:
87
+
88
+ * Run `towncrier build --version vx.y.z` using the version number you want to tag.
89
+ * Agree to have towncrier remove the fragments.
90
+ * Add and commit your changes.
91
+ * Tag the release.
92
+
93
+ **NOTE:** If you forget to add a Changelog entry to a tagged release (either manually or automatically with ``towncrier``)
94
+ then the Bitbucket pipeline will fail. To be able to use the same tag you must delete it locally and on the remote branch:
95
+
96
+ .. code-block:: bash
97
+
98
+ # First, actually update the CHANGELOG and commit the update
99
+ git commit
100
+
101
+ # Delete tags
102
+ git tag -d vWHATEVER.THE.VERSION
103
+ git push --delete origin vWHATEVER.THE.VERSION
104
+
105
+ # Re-tag with the same version
106
+ git tag vWHATEVER.THE.VERSION
107
+ git push --tags origin main
@@ -0,0 +1,29 @@
1
+ changelog/.gitempty,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ dkist_processing_math/__init__.py,sha256=Mf7liCQC9M5YgFrz2NZ0dZ5smvcuw47ww6MC9mijAHw,249
3
+ dkist_processing_math/arithmetic.py,sha256=h8E4DUBGQLDUiNWmZb2kZRrLMmjEpdl1S_mIi3ntZ6w,3694
4
+ dkist_processing_math/feature.py,sha256=vwrkXBlK7wM6-KFaWxhBsMpHiHbpsWOiuGOhf3PRLSY,2003
5
+ dkist_processing_math/linear_algebra.py,sha256=3ycmWklgLI89NjQgwgY81Zv1m_L4jJXHnt70TzQDVWQ,4179
6
+ dkist_processing_math/statistics.py,sha256=Dgt1gSDQDN2XGV38xSQ3ZUmyIeGMZRoBl2vGHcADAYs,1233
7
+ dkist_processing_math/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ dkist_processing_math/tests/conftest.py,sha256=Pg7lDltF_N7SVIjAi0rRADXBftsSzw0o94-SfKW1Zko,1333
9
+ dkist_processing_math/tests/test_arithmetic.py,sha256=18YI4Fr_m0KU0dYR8_ef7CMmnOlb-Zc4I8ERgoYdxdA,5658
10
+ dkist_processing_math/tests/test_feature.py,sha256=ZB8r_IUrAyTAlKbxEXwr8Q2zS7KPmlJhaU1l0guK0Xc,2311
11
+ dkist_processing_math/tests/test_linear_algebra.py,sha256=k-XqIIBPsenNMKqo2nQnDkkN-6T1nvVT8BrJnupAIFU,6495
12
+ dkist_processing_math/tests/test_statistics.py,sha256=0_bFuKxcu6hfimScB5du38qzABq2syX7SQrA9ZjwbuA,2173
13
+ dkist_processing_math/tests/test_transform.py,sha256=M761Yceh3FKV00udvb6_AeKuyBpQrUAG-mLfO-PbHmc,20253
14
+ dkist_processing_math/transform/__init__.py,sha256=gZGyavJgtuquv8vc_VkXraJjz_8MkDTk9UwGQhthHwM,617
15
+ dkist_processing_math/transform/affine.py,sha256=wJvL-R3DMpOmEnCKL8YI8eRUE7enH2Vg-mSLLpfCEoE,8595
16
+ dkist_processing_math/transform/binary.py,sha256=64FhSBScuVCykHYA8Oh99wQodqVUiPdbtpFGIMl5BX8,1206
17
+ dkist_processing_math/transform/binning.py,sha256=1zSX4SIJnc_LiQY-oOCeZhy-zGAp5ALJFXhJ7Pz6uDI,5172
18
+ dkist_processing_math/transform/hough.py,sha256=o0l9YaYgMBqeKACHT8lZ4PbMZVJwjD-cE1kKrFg8mog,1370
19
+ docs/Makefile,sha256=qnlVz6PuBqE39NfHWuUnHhNEA-EFgT2-WJNNNy9ttfk,4598
20
+ docs/changelog.rst,sha256=S2jPASsWlQxSlAPqdvNrYvhk9k3FcFWNXFNDYXBSjl4,120
21
+ docs/conf.py,sha256=wo1DmmqFac7fMpPLXZrY69vCXb3cji4Y7eYWOphUu_w,1835
22
+ docs/index.rst,sha256=qNJUPrbv1dEdn_QLn5pZOhMTNikWVNAeSQnV76hFnis,103
23
+ docs/make.bat,sha256=mBAhtURwhQ7yc95pqwJzlhqBSvRknr1aqZ5s8NKvdKs,4513
24
+ docs/requirements.txt,sha256=Kbl_X4c7RQZw035YTeNB63We6I7pvXFU4T0Uflp2yDY,29
25
+ licenses/LICENSE.rst,sha256=piZaQplkzOMmH1NXg6QIdo9wwo9pPCoHkvm2-DmH76E,1462
26
+ dkist_processing_math-2.1.1.dist-info/METADATA,sha256=GPD3CVAME94Z-utZGhZTZm-jbGtE97P8RlqU5PwSk8Q,4301
27
+ dkist_processing_math-2.1.1.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
28
+ dkist_processing_math-2.1.1.dist-info/top_level.txt,sha256=7NeFrOlR4xhZ3LMT4jN99LQugukjr6l9u3w_s6b-uO4,46
29
+ dkist_processing_math-2.1.1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (75.1.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,4 @@
1
+ changelog
2
+ dkist_processing_math
3
+ docs
4
+ licenses