multipers 2.0.3__tar.gz → 2.0.4__tar.gz
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.
Potentially problematic release.
This version of multipers might be problematic. Click here for more details.
- {multipers-2.0.3/multipers.egg-info → multipers-2.0.4}/PKG-INFO +1 -1
- {multipers-2.0.3 → multipers-2.0.4}/multipers/_signed_measure_meta.py +79 -65
- {multipers-2.0.3 → multipers-2.0.4}/multipers/_slicer_meta.py +1 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/function_rips.cpp +155 -155
- {multipers-2.0.3 → multipers-2.0.4}/multipers/grids.cpp +155 -155
- {multipers-2.0.3 → multipers-2.0.4}/multipers/io.cpp +2387 -2140
- {multipers-2.0.3 → multipers-2.0.4}/multipers/io.pyx +11 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/mma_structures.cpp +155 -155
- {multipers-2.0.3 → multipers-2.0.4}/multipers/multiparameter_module_approximation.cpp +155 -155
- {multipers-2.0.3 → multipers-2.0.4}/multipers/point_measure_integration.cpp +155 -155
- {multipers-2.0.3 → multipers-2.0.4}/multipers/rank_invariant.cpp +712 -861
- multipers-2.0.4/multipers/rank_invariant.pyx +86 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/simplex_tree_multi.cpp +449 -242
- {multipers-2.0.3 → multipers-2.0.4}/multipers/simplex_tree_multi.pyx +1 -1
- {multipers-2.0.3 → multipers-2.0.4}/multipers/slicer.cpp +37869 -35125
- {multipers-2.0.3 → multipers-2.0.4}/multipers/slicer.pyx +313 -109
- {multipers-2.0.3 → multipers-2.0.4}/multipers/tests/__init__.py +9 -6
- multipers-2.0.4/multipers/tests/test_signed_measure.py +86 -0
- {multipers-2.0.3 → multipers-2.0.4/multipers.egg-info}/PKG-INFO +1 -1
- {multipers-2.0.3 → multipers-2.0.4}/multipers.egg-info/SOURCES.txt +1 -0
- {multipers-2.0.3 → multipers-2.0.4}/setup.py +1 -1
- multipers-2.0.3/multipers/rank_invariant.pyx +0 -224
- {multipers-2.0.3 → multipers-2.0.4}/LICENSE +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/MANIFEST.in +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/README.md +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/__init__.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/data/MOL2.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/data/UCR.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/data/__init__.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/data/graphs.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/data/immuno_regions.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/data/minimal_presentation_to_st_bf.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/data/pytorch2simplextree.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/data/shape3d.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/data/synthetic.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/distances.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/euler_characteristic.pyx +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/filtration_conversions.pxd +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/filtrations.pxd +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/function_rips.pyx +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/grids.pyx +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/gudhi/Persistence_slices_interface.h +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/gudhi/Simplex_tree_multi_interface.h +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/gudhi/gudhi/Simplex_tree/multi_filtrations/Box.h +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/gudhi/gudhi/Simplex_tree/multi_filtrations/Finitely_critical_filtrations.h +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/gudhi/gudhi/Simplex_tree/multi_filtrations/Line.h +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/hilbert_function.pyi +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/hilbert_function.pyx +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/__init__.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/accuracies.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/convolutions.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/invariants_with_persistable.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/kernels.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/mma.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/one.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/point_clouds.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/signed_betti.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/signed_measures.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/sliced_wasserstein.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/ml/tools.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/mma_structures.pxd +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/mma_structures.pyx +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/multi_parameter_rank_invariant/euler_characteristic.h +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/multi_parameter_rank_invariant/function_rips.h +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/multi_parameter_rank_invariant/hilbert_function.h +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/multi_parameter_rank_invariant/rank_invariant.h +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/multiparameter_edge_collapse.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/multiparameter_module_approximation/approximation.h +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/multiparameter_module_approximation/utilities.h +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/multiparameter_module_approximation.pyx +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/pickle.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/plots.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/point_measure_integration.pyx +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/simplex_tree_multi.pxd +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/slicer.pxd +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/tensor.pxd +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/test.pyx +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/tests/old_test_rank_invariant.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/tests/test_diff_helper.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/tests/test_hilbert_function.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/tests/test_mma.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/tests/test_point_clouds.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/tests/test_python-cpp_conversion.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/tests/test_signed_betti.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/tests/test_simplextreemulti.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/tests/test_slicer.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/torch/__init__.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/torch/diff_grids.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers/torch/rips_density.py +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers.egg-info/dependency_links.txt +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers.egg-info/requires.txt +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/multipers.egg-info/top_level.txt +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/pyproject.toml +0 -0
- {multipers-2.0.3 → multipers-2.0.4}/setup.cfg +0 -0
|
@@ -2,20 +2,23 @@ from typing import Iterable, Optional, Union
|
|
|
2
2
|
|
|
3
3
|
import numpy as np
|
|
4
4
|
|
|
5
|
+
import multipers as mp
|
|
5
6
|
from multipers.grids import compute_grid, sms_in_grid
|
|
6
7
|
from multipers.plots import plot_signed_measures
|
|
7
8
|
from multipers.point_measure_integration import clean_sms, zero_out_sms
|
|
8
9
|
from multipers.rank_invariant import rank_from_slicer
|
|
9
|
-
from multipers.simplex_tree_multi import (
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
from multipers.simplex_tree_multi import (
|
|
11
|
+
SimplexTreeMulti_type,
|
|
12
|
+
_available_strategies,
|
|
13
|
+
is_simplextree_multi,
|
|
14
|
+
)
|
|
12
15
|
from multipers.slicer import Slicer_type, is_slicer
|
|
13
16
|
|
|
14
17
|
|
|
15
18
|
def signed_measure(
|
|
16
19
|
filtered_complex: Union[SimplexTreeMulti_type, Slicer_type],
|
|
17
20
|
degree: Optional[int] = None,
|
|
18
|
-
degrees: Iterable[int | None] = [
|
|
21
|
+
degrees: Iterable[int | None] = [],
|
|
19
22
|
mass_default=None,
|
|
20
23
|
grid_strategy: _available_strategies = "exact",
|
|
21
24
|
invariant: Optional[str] = None,
|
|
@@ -29,7 +32,7 @@ def signed_measure(
|
|
|
29
32
|
coordinate_measure: bool = False,
|
|
30
33
|
num_collapses: int = 0,
|
|
31
34
|
clean: Optional[bool] = None,
|
|
32
|
-
vineyard:bool=False,
|
|
35
|
+
vineyard: bool = False,
|
|
33
36
|
**infer_grid_kwargs,
|
|
34
37
|
) -> list[tuple[np.ndarray, np.ndarray]]:
|
|
35
38
|
"""
|
|
@@ -50,7 +53,7 @@ def signed_measure(
|
|
|
50
53
|
Defaults to #cpu, but when doing parallel computations of signed measures, we recommend setting this to 1.
|
|
51
54
|
- verbose:bool, prints c++ logs.
|
|
52
55
|
- expand_collapse: when the input is a simplextree, only expands the complex when computing 1-dimensional slices. Meant to reduce memory footprint at some computational expense.
|
|
53
|
-
- backend:str
|
|
56
|
+
- backend:str reduces first the filtered complex using an external library,
|
|
54
57
|
see ``backend`` in :func:`multipers.io.reduce_complex`.
|
|
55
58
|
- grid_conversion: If given, re-evaluates the final signed measure in this grid.
|
|
56
59
|
- coordinate_measure: bool, if True, compute the signed measure as a coordinates given in grid_conversion.
|
|
@@ -64,13 +67,13 @@ def signed_measure(
|
|
|
64
67
|
with `signed_measure_of_degree` of the form `(dirac location, dirac weights)`.
|
|
65
68
|
"""
|
|
66
69
|
|
|
67
|
-
if len(degrees) ==
|
|
68
|
-
degrees = [degree]
|
|
70
|
+
if degree is not None or len(degrees) == 0:
|
|
71
|
+
degrees = list(degrees) + [degree]
|
|
69
72
|
if None in degrees:
|
|
70
|
-
assert
|
|
73
|
+
assert (
|
|
74
|
+
len(degrees) == 1
|
|
75
|
+
), f"Can only compute one invariant at the time. Got {degrees=}, {invariant=}."
|
|
71
76
|
invariant = "euler"
|
|
72
|
-
if len(degrees) == 0:
|
|
73
|
-
return []
|
|
74
77
|
if clean is None:
|
|
75
78
|
clean = True if None in degrees else False
|
|
76
79
|
|
|
@@ -96,20 +99,25 @@ def signed_measure(
|
|
|
96
99
|
|
|
97
100
|
if mass_default is None:
|
|
98
101
|
mass_default = mass_default
|
|
99
|
-
elif mass_default
|
|
100
|
-
mass_default
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
102
|
+
elif isinstance(mass_default, str):
|
|
103
|
+
if mass_default == "auto":
|
|
104
|
+
mass_default = np.array(
|
|
105
|
+
[1.1 * np.max(f) - 0.1 * np.min(f) for f in grid_conversion]
|
|
106
|
+
)
|
|
107
|
+
elif mass_default == "inf":
|
|
108
|
+
mass_default = np.array([np.inf] * filtered_complex.num_parameters)
|
|
109
|
+
else:
|
|
110
|
+
raise NotImplementedError
|
|
105
111
|
else:
|
|
106
112
|
mass_default = np.asarray(mass_default)
|
|
107
113
|
assert (
|
|
108
114
|
mass_default.ndim == 1
|
|
109
115
|
and mass_default.shape[0] == filtered_complex.num_parameters
|
|
110
116
|
)
|
|
111
|
-
|
|
112
|
-
INPUT_ARGS = locals()
|
|
117
|
+
|
|
118
|
+
# INPUT_ARGS = locals()
|
|
119
|
+
# INPUT_ARGS.pop("filtered_complex")
|
|
120
|
+
|
|
113
121
|
if not filtered_complex.is_squeezed:
|
|
114
122
|
filtered_complex_ = filtered_complex.grid_squeeze(
|
|
115
123
|
grid_conversion, coordinates=True
|
|
@@ -122,88 +130,88 @@ def signed_measure(
|
|
|
122
130
|
grid_conversion
|
|
123
131
|
), f"Number of parameter do not coincide. Got (grid_conversion) {len(grid_conversion)} and (filtered complex) {num_parameters}."
|
|
124
132
|
|
|
133
|
+
if is_simplextree_multi(filtered_complex_):
|
|
134
|
+
if num_collapses != 0:
|
|
135
|
+
filtered_complex_.collapse_edges(num_collapses)
|
|
136
|
+
if backend is not None:
|
|
137
|
+
filtered_complex_ = mp.Slicer(filtered_complex_, vineyard=vineyard)
|
|
138
|
+
|
|
125
139
|
fix_mass_default = mass_default is not None
|
|
126
140
|
if is_slicer(filtered_complex_):
|
|
127
|
-
if backend is not None:
|
|
141
|
+
if backend is not None and not filtered_complex_.is_minpres:
|
|
128
142
|
from multipers.slicer import minimal_presentation
|
|
143
|
+
|
|
129
144
|
assert (
|
|
130
145
|
invariant != "euler"
|
|
131
146
|
), "Euler Characteristic cannot be speed up by a backend"
|
|
132
147
|
# This returns a list of reduced complexes
|
|
133
|
-
reduced_complex = minimal_presentation(
|
|
134
|
-
|
|
148
|
+
reduced_complex = minimal_presentation(
|
|
149
|
+
filtered_complex_,
|
|
150
|
+
degrees=degrees,
|
|
151
|
+
backend=backend,
|
|
152
|
+
vineyard=vineyard,
|
|
153
|
+
verbose=verbose,
|
|
154
|
+
)
|
|
155
|
+
if "rank" in invariant:
|
|
135
156
|
sms = [
|
|
136
157
|
rank_from_slicer(
|
|
137
158
|
s,
|
|
138
159
|
degrees=[1],
|
|
139
160
|
n_jobs=n_jobs,
|
|
140
161
|
grid_shape=tuple(len(g) for g in grid_conversion),
|
|
141
|
-
|
|
142
|
-
)
|
|
162
|
+
zero_pad=fix_mass_default,
|
|
163
|
+
)[0]
|
|
143
164
|
for s, d in zip(reduced_complex, degrees)
|
|
144
165
|
]
|
|
166
|
+
fix_mass_default = False
|
|
145
167
|
else:
|
|
146
|
-
sms = [
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
]
|
|
150
|
-
else: # No backend
|
|
151
|
-
if invariant in ("rank", "rank_invariant"): # TODO Hilbert from slicer
|
|
168
|
+
sms = [_signed_measure_from_slicer(s)[0] for s in reduced_complex]
|
|
169
|
+
else: # No backend
|
|
170
|
+
if "rank" in invariant: # TODO Hilbert from slicer
|
|
152
171
|
degrees = np.asarray(degrees, dtype=int)
|
|
153
|
-
|
|
172
|
+
sms = rank_from_slicer(
|
|
154
173
|
filtered_complex_,
|
|
155
174
|
degrees=degrees,
|
|
156
175
|
n_jobs=n_jobs,
|
|
176
|
+
zero_pad=fix_mass_default,
|
|
157
177
|
grid_shape=tuple(len(g) for g in grid_conversion),
|
|
158
|
-
plot=plot,
|
|
159
178
|
)
|
|
160
|
-
|
|
179
|
+
fix_mass_default = False
|
|
180
|
+
elif filtered_complex_.is_minpres:
|
|
181
|
+
sms = _signed_measure_from_slicer(
|
|
182
|
+
filtered_complex_,
|
|
183
|
+
)
|
|
184
|
+
elif (invariant is None or "euler" in invariant) and (
|
|
185
|
+
len(degrees) == 1 and degrees[0] is None
|
|
186
|
+
):
|
|
161
187
|
sms = _signed_measure_from_slicer(
|
|
162
188
|
filtered_complex_,
|
|
163
189
|
)
|
|
164
190
|
else:
|
|
165
|
-
|
|
166
|
-
assert len(degrees) == 1
|
|
167
|
-
sms = _signed_measure_from_slicer(filtered_complex_)
|
|
191
|
+
from multipers.slicer import minimal_presentation
|
|
168
192
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
193
|
+
backend = "mpfree" ## TODO : make a non-mpfree backend
|
|
194
|
+
reduced_complex = minimal_presentation(
|
|
195
|
+
filtered_complex_,
|
|
196
|
+
degrees=degrees,
|
|
197
|
+
backend=backend,
|
|
198
|
+
vineyard=vineyard,
|
|
199
|
+
)
|
|
200
|
+
sms = [_signed_measure_from_slicer(s)[0] for s in reduced_complex]
|
|
176
201
|
|
|
177
202
|
elif is_simplextree_multi(filtered_complex_):
|
|
178
|
-
if num_collapses != 0:
|
|
179
|
-
filtered_complex_.collapse_edges(num_collapses)
|
|
180
|
-
if backend is not None:
|
|
181
|
-
from multipers.slicer import minimal_presentation
|
|
182
|
-
reduced_complex = minimal_presentation(filtered_complex_, degrees=degrees, backend=backend, vineyard=vineyard)
|
|
183
|
-
# this is a list of slicer -> need to go back
|
|
184
|
-
INPUT_ARGS.pop('filtered_complex')
|
|
185
|
-
INPUT_ARGS.pop('degrees')
|
|
186
|
-
INPUT_ARGS.pop('degree')
|
|
187
|
-
INPUT_ARGS.pop('backend')
|
|
188
|
-
plot = INPUT_ARGS.pop('plot') ## plot has to be dealt with later
|
|
189
|
-
output = [_signed_measure_from_slicer(s, degree=d, **INPUT_ARGS)[0] for s,d in zip(reduced_complex, degrees)]
|
|
190
|
-
if plot:
|
|
191
|
-
plot_signed_measures(output)
|
|
192
|
-
return output
|
|
193
203
|
## we still have a simplextree here
|
|
194
204
|
if invariant in ["rank_invariant", "rank"]:
|
|
195
205
|
assert (
|
|
196
|
-
|
|
206
|
+
num_parameters == 2
|
|
197
207
|
), "Rank invariant only implemented for 2-parameter modules."
|
|
198
208
|
assert not coordinate_measure, "Not implemented"
|
|
199
|
-
from multipers.simplex_tree_multi import
|
|
200
|
-
_rank_signed_measure as smri
|
|
209
|
+
from multipers.simplex_tree_multi import _rank_signed_measure as smri
|
|
201
210
|
|
|
202
211
|
sms = smri(
|
|
203
212
|
filtered_complex_,
|
|
204
213
|
mass_default=mass_default,
|
|
205
214
|
degrees=degrees,
|
|
206
|
-
plot=plot,
|
|
207
215
|
expand_collapse=expand_collapse,
|
|
208
216
|
)
|
|
209
217
|
fix_mass_default = False
|
|
@@ -228,8 +236,9 @@ def signed_measure(
|
|
|
228
236
|
"hilbert",
|
|
229
237
|
"hilbert_function",
|
|
230
238
|
], "Found homological degrees for euler computation."
|
|
231
|
-
from multipers.simplex_tree_multi import
|
|
232
|
-
_hilbert_signed_measure as hilbert_signed_measure
|
|
239
|
+
from multipers.simplex_tree_multi import (
|
|
240
|
+
_hilbert_signed_measure as hilbert_signed_measure,
|
|
241
|
+
)
|
|
233
242
|
|
|
234
243
|
sms = hilbert_signed_measure(
|
|
235
244
|
filtered_complex_,
|
|
@@ -246,7 +255,12 @@ def signed_measure(
|
|
|
246
255
|
if clean:
|
|
247
256
|
sms = clean_sms(sms)
|
|
248
257
|
if grid_conversion is not None and not coordinate_measure:
|
|
249
|
-
sms = sms_in_grid(
|
|
258
|
+
sms = sms_in_grid(
|
|
259
|
+
sms,
|
|
260
|
+
grid_conversion=grid_conversion,
|
|
261
|
+
mass_default=mass_default,
|
|
262
|
+
num_parameters=num_parameters,
|
|
263
|
+
)
|
|
250
264
|
|
|
251
265
|
if fix_mass_default:
|
|
252
266
|
# TODO : some methods need to use this, this could be optimized
|
|
@@ -139,6 +139,7 @@ def Slicer(
|
|
|
139
139
|
)
|
|
140
140
|
if st.is_squeezed:
|
|
141
141
|
slicer.filtration_grid = st.filtration_grid
|
|
142
|
+
slicer.minpres_degree = st.minpres_degree
|
|
142
143
|
elif is_simplextree_multi(st) and backend == "graph":
|
|
143
144
|
slicer = _slicer_from_simplextree(st, backend, vineyard)
|
|
144
145
|
if st.is_squeezed:
|