cdxcore 0.1.14__py3-none-any.whl → 0.1.15__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.

Potentially problematic release.


This version of cdxcore might be problematic. Click here for more details.

cdxcore/dynaplot.py CHANGED
@@ -1,17 +1,17 @@
1
1
  """
2
- dynaplot
3
- Dynamic matplotlib in jupyer notebooks
2
+ Overview
3
+ --------
4
4
 
5
- from dynaplot import figure
5
+ Basic utilities for Python such as type management, formatting, some trivial timers.
6
+
7
+ Import
8
+ ------
9
+ .. code-block:: python
10
+
11
+ import cdxcore.util as util
6
12
 
7
- fig = figure()
8
- ax = fig.add_subplot()
9
- ax.plot(x,y)
10
- ax = fig.add_subplot()
11
- ax.plot(x,z)
12
- fig.close()
13
-
14
- Hans Buehler 2022
13
+ Documentation
14
+ -------------
15
15
  """
16
16
  import matplotlib.pyplot as plt
17
17
  from matplotlib.gridspec import GridSpec#NOQA
@@ -22,260 +22,10 @@ from IPython import display
22
22
  import io as io
23
23
  import gc as gc
24
24
  import types as types
25
- import numpy as np
26
- from .deferred import Deferred
27
- from .util import fmt as txtfmt
28
25
  from collections.abc import Collection
29
- import warnings as warnings
30
-
31
- def error( text, *args, exception = RuntimeError, **kwargs ):
32
- raise exception( txtfmt(text, *args, **kwargs) )
33
- def verify( cond, text, *args, exception = RuntimeError, **kwargs ):
34
- if not cond:
35
- error( text, *args, **kwargs, exception=exception )
36
- def warn( text, *args, warning=warnings.RuntimeWarning, stack_level=1, **kwargs ):
37
- warnings.warn( txtfmt(text, *args, **kwargs), warning, stack_level=stack_level )
38
- def warn_if( cond, text, *args, warning=warnings.RuntimeWarning, stack_level=1, **kwargs ):
39
- if cond:
40
- warn( text, *args, warning=warning, stack_level=stack_level, **kwargs )
41
-
42
- class AutoLimits( object ):
43
- """
44
- Max/Min limit manger for dynamic figures.
45
-
46
- limits = MinMaxLimit( 0.05, 0.95 )
47
- ax.add_subplot( x,y ,.. )
48
- limits.update(x, y)
49
- ax.add_subplot( x,z,.. )
50
- limits.update(x, z)
51
- limits.set_lims(ax)
52
- """
53
-
54
- def __init__(self, low_quantile, high_quantile, min_length : int = 10, lookback : int = None ):
55
- """
56
- Initialize MinMaxLimit.
57
-
58
- Parameters
59
- ----------
60
- low_quantile : float
61
- Lower quantile to use for computing a 'min' y value. Set to 0 to use 'min'.
62
- high_quantile : float
63
- Higher quantile to use for computing a 'min' y value. Set to 1 to use 'max'.
64
- min_length : int
65
- Minimum length data must have to use quantile(). If less data is presented,
66
- use min/max, respectively.
67
- lookback : int
68
- How many steps to lookback for any calculation. None to use all steps
69
- """
70
-
71
- verify( low_quantile >=0., "'low_quantile' must not be negative", exception=ValueError )
72
- verify( high_quantile <=1., "'high_quantile' must not exceed 1", exception=ValueError )
73
- verify( low_quantile<=high_quantile, "'low_quantile' not exceed 'high_quantile'", exception=ValueError )
74
- self.lo_q = low_quantile
75
- self.hi_q = high_quantile
76
- self.min_length = int(min_length)
77
- self.lookback = int(lookback) if not lookback is None else None
78
- self.max_y = None
79
- self.min_y = None
80
- self.min_x = None
81
- self.max_x = None
82
-
83
- def update(self, *args, axis=None ):
84
- """
85
- Add a data set to the min/max calc
86
-
87
- If the x axis is ordinal first dimension of 'y':
88
- update(y, axis=axis )
89
- In this case x = np.linspace(1,y.shape[0],y.shape[0])
90
-
91
- Specifcy x axis
92
- update(x, y, axis=axis )
93
-
94
- Parameters
95
- ----------
96
- *args:
97
- Either y or x,y
98
- axis:
99
- along which axis to compute min/max/quantiles
100
- """
101
- assert len(args) in [1,2], ("'args' must be 1 or 2", len(args))
102
-
103
- y = args[-1]
104
- x = args[0] if len(args) > 1 else None
105
-
106
- if len(y) == 0:
107
- return
108
- if axis is None:
109
- axis = None if len(y.shape) <= 1 else tuple(list(y.shape)[1])
110
-
111
- y_len = y.shape[0]
112
- if not self.lookback is None:
113
- y = y[-self.lookback:,...]
114
- x = x[-self.lookback:,...] if not x is None else None
115
-
116
- min_y = np.min( np.quantile( y, self.lo_q, axis=axis ) ) if self.lo_q > 0. and len(y) > self.min_length else np.min( y )
117
- max_y = np.max( np.quantile( y, self.hi_q, axis=axis ) ) if self.hi_q < 1. and len(y) > self.min_length else np.max( y )
118
- assert min_y <= max_y, ("Internal error", min_y, max_y, y)
119
- self.min_y = min_y if self.min_y is None else min( self.min_y, min_y )
120
- self.max_y = max_y if self.max_y is None else max( self.max_y, max_y )
121
-
122
- if x is None:
123
- self.min_x = 1
124
- self.max_x = y_len if self.max_x is None else max( y_len, self.max_x )
125
- else:
126
- min_ = np.min( x )
127
- max_ = np.max( x )
128
- self.min_x = min_ if self.max_x is None else min( self.min_x, min_ )
129
- self.max_x = max_ if self.max_x is None else max( self.max_x, max_ )
130
-
131
- return self
132
-
133
- def set( self, *, min_x = None, max_x = None,
134
- min_y = None, max_y = None ) -> type:
135
- """
136
- Overwrite any of the extrema.
137
- Imposing an extrema also sets the other side if this would violate the requrest eg if min_x is set the function also floors self.max_x at min_x
138
- Returns 'self.'
139
- """
140
- verify( min_x is None or max_x is None or min_x <= max_x, "'min_x' and 'max_'x are in wrong order", min_x, max_x, exception=ValueError )
141
- if not min_x is None:
142
- self.min_x = min_x
143
- self.max_x = min( self.max_x, min_x )
144
- if not max_x is None:
145
- self.min_x = max( self.min_x, max_x )
146
- self.max_x = max_x
147
-
148
- verify( min_y is None or max_y is None or min_y <= max_y, "'min_y' and 'max_'x are in wrong order", min_y, max_y, exception=ValueError )
149
- if not min_y is None:
150
- self.min_y = min_y
151
- self.max_y = min( self.max_y, min_y )
152
- if not max_y is None:
153
- self.min_y = max( self.min_y, max_y )
154
- self.max_y = max_y
155
- return self
156
-
157
- def bound( self, *, min_x_at_least = None, max_x_at_most = None, # <= boundary limits
158
- min_y_at_least = None, max_y_at_most = None,
159
- ):
160
- """
161
- Bound extrema
162
- """
163
- verify( min_x_at_least is None or max_x_at_most is None or min_x_at_least <= max_x_at_most, "'min_x_at_least' and 'max_x_at_most'x are in wrong order", min_x_at_least, max_x_at_most, exception=ValueError )
164
- if not min_x_at_least is None:
165
- self.min_x = max( self.min_x, min_x_at_least )
166
- self.max_x = max( self.max_x, min_x_at_least )
167
- if not max_x_at_most is None:
168
- self.min_x = min( self.min_x, max_x_at_most )
169
- self.max_x = min( self.max_x, max_x_at_most )
170
-
171
- verify( min_y_at_least is None or max_y_at_most is None or min_y_at_least <= max_y_at_most, "'min_y_at_least' and 'max_y_at_most'x are in wrong order", min_y_at_least, max_y_at_most, exception=ValueError )
172
- if not min_y_at_least is None:
173
- self.min_y = max( self.min_y, min_y_at_least )
174
- self.max_y = max( self.max_y, min_y_at_least )
175
- if not max_y_at_most is None:
176
- self.min_y = min( self.min_y, max_y_at_most )
177
- self.max_y = min( self.max_y, max_y_at_most )
178
- return self
179
-
180
- def set_a_lim( self, ax,*, is_x,
181
- min_d,
182
- rspace,
183
- min_set = None,
184
- max_set = None,
185
- min_at_least = None,
186
- max_at_most = None ):
187
- """ Utility function """
188
- min_ = self.min_x if is_x else self.min_y
189
- max_ = self.max_x if is_x else self.max_y
190
- ax_scale = (ax.get_xaxis() if is_x else ax.get_yaxis()).get_scale()
191
- label = "x" if is_x else "y"
192
- f = ax.set_xlim if is_x else ax.set_ylim
193
-
194
- if min_ is None or max_ is None:
195
- warn( "No data recevied yet; ignoring call" )
196
- return
197
- assert min_ <= max_, ("Internal error (1): min and max are not in order", label, min_, max_)
198
-
199
- verify( min_set is None or max_set is None or min_set <= max_set, "'min_set_%s' exceeds 'max_set_%s': found %g and %g, respectively", label, label, min_set, max_set, exception=RuntimeError )
200
- verify( min_at_least is None or max_at_most is None or min_at_least <= max_at_most, "'min_at_least_%s' exceeds 'max_at_most_%s': found %g and %g, respectively", label, label, min_at_least, max_at_most, exception=RuntimeError )
201
-
202
- if not min_set is None:
203
- min_ = min_set
204
- max_ = max(min_set, max_)
205
- if not max_set is None:
206
- min_ = min(min_, max_set)
207
- max_ = max_set
208
- if not min_at_least is None:
209
- min_ = max( min_, min_at_least )
210
- max_ = max( max_, min_at_least )
211
- if not max_at_most is None:
212
- min_ = min( min_, max_at_most )
213
- max_ = min( max_, max_at_most )
214
-
215
- assert min_ <= max_, ("Internal error (2): min and max are not in order", label, min_, max_)
216
-
217
- if isinstance( max_, int ):
218
- verify( ax_scale == "linear", "Only 'linear' %s axis supported for integer based %s coordinates; found '%s'", label, label, ax_scale, exception=AttributeError )
219
- max_ = max(max_, min_+1)
220
- f( min_, max_ )
221
- else:
222
- d = max( max_-min_, min_d ) * rspace
223
- if ax_scale == "linear":
224
- f( min_ - d, max_ + d )
225
- else:
226
- verify( ax_scale == "log", "Only 'linear' and 'log' %s axis scales are supported; found '%s'", label, ax_scale, exception=AttributeError )
227
- verify( min_ > 0., "Minimum for 'log' %s axis must be positive; found %g", label, min_)
228
- rdx = np.exp( d )
229
- f( min_ / rdx, max_ * rdx )
230
- return self
231
-
232
- def set_ylim(self, ax, *, min_dy : float = 1E-4, yrspace : float = 0.001, min_set_y = None, max_set_y = None, min_y_at_least = None, max_y_at_most = None ):
233
- """
234
- Set x limits for 'ax'. See set_lims()
235
- """
236
- return self.set_a_lim( ax, is_x=False, min_d=min_dy, rspace=yrspace, min_set=min_set_y, max_set=max_set_y, min_at_least=min_y_at_least, max_at_most=max_y_at_most )
237
-
238
- def set_xlim(self, ax, *, min_dx : float = 1E-4, xrspace : float = 0.001, min_set_x = None, max_set_x = None, min_x_at_least = None, max_x_at_most = None ):
239
- """
240
- Set x limits for 'ax'. See set_lims()
241
- """
242
- return self.set_a_lim( ax, is_x=True, min_d=min_dx, rspace=xrspace, min_set=min_set_x, max_set=max_set_x, min_at_least=min_x_at_least, max_at_most=max_x_at_most )
243
-
244
- def set_lims( self, ax, *, x : bool = True, y : bool = True,
245
- min_dx : float = 1E-4, min_dy = 1E-4, xrspace = 0.001, yrspace = 0.001,
246
- min_set_x = None, max_set_x = None, min_x_at_least = None, max_x_at_most = None,
247
- min_set_y = None, max_set_y = None, min_y_at_least = None, max_y_at_most = None):
248
- """
249
- Set x and/or y limits for 'ax'.
250
-
251
- For example for the x axis: let
252
- dx := max( max_x - min_x, min_dx )*xrspace
253
-
254
- For linear axes:
255
- set_xlim( min_x - dy, max_x + dx )
256
-
257
- For logarithmic axes
258
- set_xlim( min_x * exp(-dx), max_x * exp(dx) )
259
-
260
- Parameters
261
- ----------
262
- ax :
263
- matplotlib plot
264
- x, y: bool
265
- Whether to apply x and y limits.
266
- min_dx, min_dy:
267
- Minimum distance
268
- xrspace, yspace:
269
- How much of the distance to add to left and right.
270
- The actual distance added to max_x is dx:=max(min_dx,max_x-min_x)*xrspace
271
- min_set_x, max_set_x, min_set_y, max_set_y:
272
- If not None, set the respective min/max accordingly.
273
- min_x_at_least, max_x_at_most, min_y_at_least, max_y_at_most:
274
- If not None, bound the respecitve min/max accordingly.
275
- """
276
- if x: self.set_xlim(ax, min_dx=min_dx, xrspace=xrspace, min_set_x=min_set_x, max_set_x=max_set_x, min_x_at_least=min_x_at_least, max_x_at_most=max_x_at_most)
277
- if y: self.set_ylim(ax, min_dy=min_dy, yrspace=yrspace, min_set_y=min_set_y, max_set_y=max_set_y, min_y_at_least=min_y_at_least, max_y_at_most=max_y_at_most)
278
- return self
26
+ from .deferred import Deferred
27
+ from .util import verify, warn
28
+ from .dynaplotlimits import AutoLimits
279
29
 
280
30
  class DynamicAx(Deferred):
281
31
  """
@@ -0,0 +1,245 @@
1
+ """
2
+ Beta Version Do Not Use
3
+ -----------------------
4
+ """
5
+ from matplotlib.gridspec import GridSpec#NOQA
6
+ import numpy as np
7
+ from .err import verify, warn
8
+
9
+ class AutoLimits( object ):
10
+ """
11
+ Max/Min limit manger for dynamic figures.
12
+
13
+ limits = MinMaxLimit( 0.05, 0.95 )
14
+ ax.add_subplot( x,y ,.. )
15
+ limits.update(x, y)
16
+ ax.add_subplot( x,z,.. )
17
+ limits.update(x, z)
18
+ limits.set_lims(ax)
19
+ """
20
+
21
+ def __init__(self, low_quantile, high_quantile, min_length : int = 10, lookback : int = None ):
22
+ """
23
+ Initialize MinMaxLimit.
24
+
25
+ Parameters
26
+ ----------
27
+ low_quantile : float
28
+ Lower quantile to use for computing a 'min' y value. Set to 0 to use 'min'.
29
+ high_quantile : float
30
+ Higher quantile to use for computing a 'min' y value. Set to 1 to use 'max'.
31
+ min_length : int
32
+ Minimum length data must have to use quantile(). If less data is presented,
33
+ use min/max, respectively.
34
+ lookback : int
35
+ How many steps to lookback for any calculation. None to use all steps
36
+ """
37
+
38
+ verify( low_quantile >=0., "'low_quantile' must not be negative", exception=ValueError )
39
+ verify( high_quantile <=1., "'high_quantile' must not exceed 1", exception=ValueError )
40
+ verify( low_quantile<=high_quantile, "'low_quantile' not exceed 'high_quantile'", exception=ValueError )
41
+ self.lo_q = low_quantile
42
+ self.hi_q = high_quantile
43
+ self.min_length = int(min_length)
44
+ self.lookback = int(lookback) if not lookback is None else None
45
+ self.max_y = None
46
+ self.min_y = None
47
+ self.min_x = None
48
+ self.max_x = None
49
+
50
+ def update(self, *args, axis=None ):
51
+ """
52
+ Add a data set to the min/max calc
53
+
54
+ If the x axis is ordinal first dimension of 'y':
55
+ update(y, axis=axis )
56
+ In this case x = np.linspace(1,y.shape[0],y.shape[0])
57
+
58
+ Specifcy x axis
59
+ update(x, y, axis=axis )
60
+
61
+ Parameters
62
+ ----------
63
+ *args:
64
+ Either y or x,y
65
+ axis:
66
+ along which axis to compute min/max/quantiles
67
+ """
68
+ assert len(args) in [1,2], ("'args' must be 1 or 2", len(args))
69
+
70
+ y = args[-1]
71
+ x = args[0] if len(args) > 1 else None
72
+
73
+ if len(y) == 0:
74
+ return
75
+ if axis is None:
76
+ axis = None if len(y.shape) <= 1 else tuple(list(y.shape)[1])
77
+
78
+ y_len = y.shape[0]
79
+ if not self.lookback is None:
80
+ y = y[-self.lookback:,...]
81
+ x = x[-self.lookback:,...] if not x is None else None
82
+
83
+ min_y = np.min( np.quantile( y, self.lo_q, axis=axis ) ) if self.lo_q > 0. and len(y) > self.min_length else np.min( y )
84
+ max_y = np.max( np.quantile( y, self.hi_q, axis=axis ) ) if self.hi_q < 1. and len(y) > self.min_length else np.max( y )
85
+ assert min_y <= max_y, ("Internal error", min_y, max_y, y)
86
+ self.min_y = min_y if self.min_y is None else min( self.min_y, min_y )
87
+ self.max_y = max_y if self.max_y is None else max( self.max_y, max_y )
88
+
89
+ if x is None:
90
+ self.min_x = 1
91
+ self.max_x = y_len if self.max_x is None else max( y_len, self.max_x )
92
+ else:
93
+ min_ = np.min( x )
94
+ max_ = np.max( x )
95
+ self.min_x = min_ if self.max_x is None else min( self.min_x, min_ )
96
+ self.max_x = max_ if self.max_x is None else max( self.max_x, max_ )
97
+
98
+ return self
99
+
100
+ def set( self, *, min_x = None, max_x = None,
101
+ min_y = None, max_y = None ) -> type:
102
+ """
103
+ Overwrite any of the extrema.
104
+ Imposing an extrema also sets the other side if this would violate the requrest eg if min_x is set the function also floors self.max_x at min_x
105
+ Returns 'self.'
106
+ """
107
+ verify( min_x is None or max_x is None or min_x <= max_x, "'min_x' and 'max_'x are in wrong order", min_x, max_x, exception=ValueError )
108
+ if not min_x is None:
109
+ self.min_x = min_x
110
+ self.max_x = min( self.max_x, min_x )
111
+ if not max_x is None:
112
+ self.min_x = max( self.min_x, max_x )
113
+ self.max_x = max_x
114
+
115
+ verify( min_y is None or max_y is None or min_y <= max_y, "'min_y' and 'max_'x are in wrong order", min_y, max_y, exception=ValueError )
116
+ if not min_y is None:
117
+ self.min_y = min_y
118
+ self.max_y = min( self.max_y, min_y )
119
+ if not max_y is None:
120
+ self.min_y = max( self.min_y, max_y )
121
+ self.max_y = max_y
122
+ return self
123
+
124
+ def bound( self, *, min_x_at_least = None, max_x_at_most = None, # <= boundary limits
125
+ min_y_at_least = None, max_y_at_most = None,
126
+ ):
127
+ """
128
+ Bound extrema
129
+ """
130
+ verify( min_x_at_least is None or max_x_at_most is None or min_x_at_least <= max_x_at_most, "'min_x_at_least' and 'max_x_at_most'x are in wrong order", min_x_at_least, max_x_at_most, exception=ValueError )
131
+ if not min_x_at_least is None:
132
+ self.min_x = max( self.min_x, min_x_at_least )
133
+ self.max_x = max( self.max_x, min_x_at_least )
134
+ if not max_x_at_most is None:
135
+ self.min_x = min( self.min_x, max_x_at_most )
136
+ self.max_x = min( self.max_x, max_x_at_most )
137
+
138
+ verify( min_y_at_least is None or max_y_at_most is None or min_y_at_least <= max_y_at_most, "'min_y_at_least' and 'max_y_at_most'x are in wrong order", min_y_at_least, max_y_at_most, exception=ValueError )
139
+ if not min_y_at_least is None:
140
+ self.min_y = max( self.min_y, min_y_at_least )
141
+ self.max_y = max( self.max_y, min_y_at_least )
142
+ if not max_y_at_most is None:
143
+ self.min_y = min( self.min_y, max_y_at_most )
144
+ self.max_y = min( self.max_y, max_y_at_most )
145
+ return self
146
+
147
+ def set_a_lim( self, ax,*, is_x,
148
+ min_d,
149
+ rspace,
150
+ min_set = None,
151
+ max_set = None,
152
+ min_at_least = None,
153
+ max_at_most = None ):
154
+ """ Utility function """
155
+ min_ = self.min_x if is_x else self.min_y
156
+ max_ = self.max_x if is_x else self.max_y
157
+ ax_scale = (ax.get_xaxis() if is_x else ax.get_yaxis()).get_scale()
158
+ label = "x" if is_x else "y"
159
+ f = ax.set_xlim if is_x else ax.set_ylim
160
+
161
+ if min_ is None or max_ is None:
162
+ warn( "No data recevied yet; ignoring call" )
163
+ return
164
+ assert min_ <= max_, ("Internal error (1): min and max are not in order", label, min_, max_)
165
+
166
+ verify( min_set is None or max_set is None or min_set <= max_set, lambda : f"'min_set_{label}' exceeds 'max_set_{label}': found {min_set:.4g} and {max_set:.4g}, respectively", exception=RuntimeError )
167
+ verify( min_at_least is None or max_at_most is None or min_at_least <= max_at_most, lambda : f"'min_at_least_{label}' exceeds 'max_at_most_{label}': found {min_at_least:.4g} and {max_at_most:.4g}, respectively", exception=RuntimeError )
168
+
169
+ if not min_set is None:
170
+ min_ = min_set
171
+ max_ = max(min_set, max_)
172
+ if not max_set is None:
173
+ min_ = min(min_, max_set)
174
+ max_ = max_set
175
+ if not min_at_least is None:
176
+ min_ = max( min_, min_at_least )
177
+ max_ = max( max_, min_at_least )
178
+ if not max_at_most is None:
179
+ min_ = min( min_, max_at_most )
180
+ max_ = min( max_, max_at_most )
181
+
182
+ assert min_ <= max_, ("Internal error (2): min and max are not in order", label, min_, max_)
183
+
184
+ if isinstance( max_, int ):
185
+ verify( ax_scale == "linear", lambda : f"Only 'linear' {label} axis supported for integer based {label} coordinates; found '{ax_scale}'", exception=AttributeError )
186
+ max_ = max(max_, min_+1)
187
+ f( min_, max_ )
188
+ else:
189
+ d = max( max_-min_, min_d ) * rspace
190
+ if ax_scale == "linear":
191
+ f( min_ - d, max_ + d )
192
+ else:
193
+ verify( ax_scale == "log", lambda : f"Only 'linear' and 'log' {label} axis scales are supported; found '{ax_scale}'", exception=AttributeError )
194
+ verify( min_ > 0., lambda : f"Minimum for 'log' {label} axis must be positive; found {min_:.4g}", exception=ValueError )
195
+ rdx = np.exp( d )
196
+ f( min_ / rdx, max_ * rdx )
197
+ return self
198
+
199
+ def set_ylim(self, ax, *, min_dy : float = 1E-4, yrspace : float = 0.001, min_set_y = None, max_set_y = None, min_y_at_least = None, max_y_at_most = None ):
200
+ """
201
+ Set x limits for 'ax'. See set_lims()
202
+ """
203
+ return self.set_a_lim( ax, is_x=False, min_d=min_dy, rspace=yrspace, min_set=min_set_y, max_set=max_set_y, min_at_least=min_y_at_least, max_at_most=max_y_at_most )
204
+
205
+ def set_xlim(self, ax, *, min_dx : float = 1E-4, xrspace : float = 0.001, min_set_x = None, max_set_x = None, min_x_at_least = None, max_x_at_most = None ):
206
+ """
207
+ Set x limits for 'ax'. See set_lims()
208
+ """
209
+ return self.set_a_lim( ax, is_x=True, min_d=min_dx, rspace=xrspace, min_set=min_set_x, max_set=max_set_x, min_at_least=min_x_at_least, max_at_most=max_x_at_most )
210
+
211
+ def set_lims( self, ax, *, x : bool = True, y : bool = True,
212
+ min_dx : float = 1E-4, min_dy = 1E-4, xrspace = 0.001, yrspace = 0.001,
213
+ min_set_x = None, max_set_x = None, min_x_at_least = None, max_x_at_most = None,
214
+ min_set_y = None, max_set_y = None, min_y_at_least = None, max_y_at_most = None):
215
+ """
216
+ Set x and/or y limits for 'ax'.
217
+
218
+ For example for the x axis: let
219
+ dx := max( max_x - min_x, min_dx )*xrspace
220
+
221
+ For linear axes:
222
+ set_xlim( min_x - dy, max_x + dx )
223
+
224
+ For logarithmic axes
225
+ set_xlim( min_x * exp(-dx), max_x * exp(dx) )
226
+
227
+ Parameters
228
+ ----------
229
+ ax :
230
+ matplotlib plot
231
+ x, y: bool
232
+ Whether to apply x and y limits.
233
+ min_dx, min_dy:
234
+ Minimum distance
235
+ xrspace, yspace:
236
+ How much of the distance to add to left and right.
237
+ The actual distance added to max_x is dx:=max(min_dx,max_x-min_x)*xrspace
238
+ min_set_x, max_set_x, min_set_y, max_set_y:
239
+ If not None, set the respective min/max accordingly.
240
+ min_x_at_least, max_x_at_most, min_y_at_least, max_y_at_most:
241
+ If not None, bound the respecitve min/max accordingly.
242
+ """
243
+ if x: self.set_xlim(ax, min_dx=min_dx, xrspace=xrspace, min_set_x=min_set_x, max_set_x=max_set_x, min_x_at_least=min_x_at_least, max_x_at_most=max_x_at_most)
244
+ if y: self.set_ylim(ax, min_dy=min_dy, yrspace=yrspace, min_set_y=min_set_y, max_set_y=max_set_y, min_y_at_least=min_y_at_least, max_y_at_most=max_y_at_most)
245
+ return self
cdxcore/util.py CHANGED
@@ -935,13 +935,13 @@ class TrackTiming(object):
935
935
  return self._tracked
936
936
 
937
937
  def summary(self, fmat : str = "%(text)s: %(fmt_seconds)s", jn_fmt : str = ", " ) -> str:
938
- """
938
+ r"""
939
939
  Generate summary string by applying some formatting
940
940
 
941
941
  Parameters
942
942
  ----------
943
943
  fmat : str, optional
944
- Format string using ``%()``. Arguments are ```text``, ``seconds`` (as int) and ``fmt_seconds`` (a string).
944
+ Format string using ``%()``. Arguments are ``text``, ``seconds`` (as int) and ``fmt_seconds`` (a string).
945
945
 
946
946
  Default is ``"%(text)s: %(fmt_seconds)s"``.
947
947
 
@@ -997,7 +997,7 @@ class Timer(object):
997
997
 
998
998
  def interval_test( self, interval : float ) -> bool:
999
999
  r"""
1000
- Tests if `interval` seconds have passed.
1000
+ Tests if ``interval`` seconds have passed.
1001
1001
  If yes, reset timer and return True. Otherwise return False.
1002
1002
 
1003
1003
  Usage::
@@ -1006,8 +1006,8 @@ class Timer(object):
1006
1006
  tme = Timer()
1007
1007
  for i in range(n):
1008
1008
  if tme.test_dt_seconds(2.):
1009
- print(f"\r{i+1}/{n} done. Time taken so far {tme}.", end='', flush=True)
1010
- print("\rDone. This took {tme}.")
1009
+ print(f"\\r{i+1}/{n} done. Time taken so far {tme}.", end='', flush=True)
1010
+ print("\\rDone. This took {tme}.")
1011
1011
 
1012
1012
  """
1013
1013
  if interval is None:
cdxcore/version.py CHANGED
@@ -1,4 +1,4 @@
1
- """
1
+ r"""
2
2
  Overview
3
3
  --------
4
4
 
@@ -117,12 +117,12 @@ Decorated Function Information
117
117
  A decorated function or class has a member ``version`` of type :class:`cdxcore.version.Version` which has the following
118
118
  key properties:
119
119
 
120
- * :attr:`cdxcore.version.Version.input`: the input version as defined with :dec:`cdxcore.version.version.
120
+ * :attr:`cdxcore.version.Version.input`: the input version as defined with :dec:`cdxcore.version.version`.
121
121
  * :attr:`cdxcore.version.Version.full`: a fully qualified version with all dependent functions and classes in human readable form.
122
122
  * :attr:`cdxcore.version.Version.unique_id48`,
123
123
  :attr:`cdxcore.version.Version.unique_id64`:
124
124
  unique hashes of :attr:`cdxcore.version.Version.full` of 48 or 64 characters,
125
- respectively. You can use the function :meth:`cdxcore.version.Version.unique_id
125
+ respectively. You can use the function :meth:`cdxcore.version.Version.unique_id`
126
126
  to compute hash IDs of any length.
127
127
  * :attr:`cdxcore.version.Version.dependencies`: a hierarchical list of dependencies for systematic inspection.
128
128
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cdxcore
3
- Version: 0.1.14
3
+ Version: 0.1.15
4
4
  Summary: Basic Python Tools; upgraded cdxbasics
5
5
  Author-email: Hans Buehler <github@buehler.london>
6
6
  License-Expression: MIT
@@ -1,22 +1,23 @@
1
- cdxcore/__init__.py,sha256=R9JQzThLS2EKfQZMbocqPtP7h86zUNQQZXyJvd4OfOg,127
1
+ cdxcore/__init__.py,sha256=DDe92gvSbMoVPmYZeQq5stY46fOBgfwbVmoWCwe1P3M,127
2
2
  cdxcore/config.py,sha256=YnIEJVFtMZ5EHlwzaB2JsSkCPhWPvEw9QSpe6mof_V4,98472
3
- cdxcore/crman.py,sha256=83oKpuzNy98ObpmUeJg2McGRxaLk2AP5lN1yd1F9ueQ,5759
4
- cdxcore/deferred.py,sha256=cPIvd0_CrC7Kn6dtaZXoHjWCA0L_3byPtLv8Op0uRI4,34181
5
- cdxcore/dynaplot.py,sha256=kwrH_WccpJcfS7n_gzdAr4QxQobvIZZrrxgdsKLKfj0,48552
3
+ cdxcore/crman.py,sha256=D2KE_T5nHi0PdLRiNARHPAy-nidr38BD2dRpj0XHvXM,5760
4
+ cdxcore/deferred.py,sha256=zrMGN9FfDi-0ZJ9SdgNB4C2CeUvjFFoWBSQskFubGlc,40486
5
+ cdxcore/dynaplot.py,sha256=IaAhFPPhs_ag3ptA16ZwY0Z8BX-ogv2WEr--czHxYtI,36578
6
+ cdxcore/dynaplotlimits.py,sha256=YEPUELCbqjvfLtH45VzcXmfKH9_jdGGraM_R2I_KXDU,11530
6
7
  cdxcore/err.py,sha256=BwmhilSxofBjN_NSrekCHn8_Oz9U_XbbfTm5qFRUl90,14645
7
8
  cdxcore/jcpool.py,sha256=kurdafk6lerCkv52Wjh9UN7EFMP8Xp07iqB2adE5bfY,27302
8
9
  cdxcore/pretty.py,sha256=iUpgUCwmI8yb5O-WZFJEk3QvNYcj_GIFHUgZ5lK8F2I,17082
9
10
  cdxcore/pretty.py_bak.py,sha256=JgWr5044HzCNGG0wKSAWlWiPRs7-bNzkwiKH0T3n0to,28658
10
11
  cdxcore/subdir.py,sha256=NScdtAG-Wrt0D7_FcpO62qzII4bS9ABXFerkILPg4uE,173864
11
12
  cdxcore/uniquehash.py,sha256=g-D8pqPIppSdRq5QfdE5aP3paZ-NkXWHfnn-uNB7fmg,50648
12
- cdxcore/util.py,sha256=S-eaAlDfELZbOGyHCMO2M3TllOCpf9h8FgZV9pXgwZ4,34197
13
+ cdxcore/util.py,sha256=o4J3IY3q2N87ZaUoljAhZroo7co0P2BiGb6JANKeJX4,34201
13
14
  cdxcore/verbose.py,sha256=66n9v2TduNWlochcV3mixSqyQzznO_H0LPrDgr9_dEo,30240
14
- cdxcore/version.py,sha256=m30oI2Ortg44dKSim-sIoeh9PioD1FWsSfVEP5rubhk,27173
15
- cdxcore-0.1.14.dist-info/licenses/LICENSE,sha256=M-cisgK9kb1bqVRJ7vrCxHcMQQfDxdY3c2YFJJWfNQg,1090
16
- docs/source/conf.py,sha256=Owctibh5XcSpSNcrpOr3ROIDjoklmFVrMhu8cOSe50o,4180
15
+ cdxcore/version.py,sha256=bEAYXKlDuEVB9mazfaGRldVlpOWobKXZfkT8HrQSDZ4,27176
16
+ cdxcore-0.1.15.dist-info/licenses/LICENSE,sha256=M-cisgK9kb1bqVRJ7vrCxHcMQQfDxdY3c2YFJJWfNQg,1090
17
+ docs/source/conf.py,sha256=uYnpLfkcoaIB4IgrneDIfGwwK6_9T6KTS2k6lI-s4Ww,4038
17
18
  tests/test_config.py,sha256=N86mH3y7k3LXEmU8uPLfrmRMZ-80VhlD35nBbpLmebg,15617
18
19
  tests/test_crman.py,sha256=YNNEAIcKvqfy9KifV1p1qzpphHIANrhjjPbccJFmzqk,1378
19
- tests/test_deferred.py,sha256=GKAI9m3vs2RCvRVJUg7E3VqJwlzZehwzZv-7nslRhrU,7355
20
+ tests/test_deferred.py,sha256=I0VNkAzlivefezT8Cgspt_SYb8yfqipJvtQXrNHS0Xs,7930
20
21
  tests/test_err.py,sha256=4Pc7x2I0A_LBuiCMvstKNzN1JAcSPmm78dwLwp-N7s0,3146
21
22
  tests/test_jcpool.py,sha256=bcGC3UcJ7SOHVgzZ-cooEJgncLWmhutBfqH7P5qB-iw,7901
22
23
  tests/test_pretty.py,sha256=pVwTBjm3XqwEf2jq5GdZvT4cDSTGqiQFBMLqmGJYuB0,11644
@@ -25,13 +26,14 @@ tests/test_uniquehash.py,sha256=n6ZCkdBw-iRsyzeAEmrnLK0hJLGH6l_Dtt_KIkSa6KA,2463
25
26
  tests/test_util.py,sha256=MXQMOmGjlBWTEwyW3JBTvZzlpMj5kDzThyhM2JwPZy8,23776
26
27
  tests/test_verbose.py,sha256=zXheIqAVOnwML2zsCjLugjYzB_KNzU_S4Xu2CSb4o10,4723
27
28
  tests/test_version.py,sha256=m_RODPDFlXTC1jAIczm3t1v6tXzqczDiUFFJtGvRG98,4381
29
+ tmp/deferred-hierarchical.py,sha256=JXzvQa3wiM3S685vdTri2uDBS1jFo7KIljxSUFSVEF4,30714
28
30
  tmp/filelock.py,sha256=HqnHZhSCESaOA3ClrdWPW_GZpyo7c3VRSEofAV-khKM,18137
29
31
  tmp/np.py,sha256=2MynhiaTfmx984Gz7TwfZH3t7GCmCAQiyeWzDDCL6_k,47686
30
32
  tmp/npio.py,sha256=4Kwp5H4MgKHkOEhu4UJ5CcwpM7Pm8UFkaoL5FvOEFRI,10310
31
33
  tmp/sharedarray.py,sha256=JuHuSlxA0evD0a-bEZgTFrfdlVPMgzfQNgfSjr1212w,11484
32
34
  up/git_message.py,sha256=EfSH7Pit3ZoCiRqSMwRCUN_QyuwreU4LTIyGSutBlm4,123
33
35
  up/pip_modify_setup.py,sha256=Esaml4yA9tFsqxLhk5bWSwvKCURONjQqfyChgFV2TSY,1584
34
- cdxcore-0.1.14.dist-info/METADATA,sha256=uDJxPG9h8DYY-4xTGQxom-eGhC9k-DT4knV_Wt_Ri-c,754
35
- cdxcore-0.1.14.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
36
- cdxcore-0.1.14.dist-info/top_level.txt,sha256=phNSwCyJFe7UP2YMoi8o6ykhotatlIbJHjTp9EHM51k,26
37
- cdxcore-0.1.14.dist-info/RECORD,,
36
+ cdxcore-0.1.15.dist-info/METADATA,sha256=PoBrfdw__2k-E7vh2E61vsP2XMOARpT9nkUYv0wy-7g,754
37
+ cdxcore-0.1.15.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
38
+ cdxcore-0.1.15.dist-info/top_level.txt,sha256=phNSwCyJFe7UP2YMoi8o6ykhotatlIbJHjTp9EHM51k,26
39
+ cdxcore-0.1.15.dist-info/RECORD,,