pynamicalsys 1.2.2__py3-none-any.whl → 1.3.0__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.
@@ -44,7 +44,7 @@ def diffusion_coefficient(
44
44
  parameters : NDArray[np.float64]
45
45
  System parameters passed to mapping function
46
46
  total_time : int
47
- Total evolution time (must be > transient_time)
47
+ Total evolution time
48
48
  mapping : Callable[[NDArray, NDArray], NDArray]
49
49
  System evolution function: u_next = mapping(u, parameters)
50
50
  axis : int, optional
@@ -58,7 +58,6 @@ def diffusion_coefficient(
58
58
  Raises
59
59
  ------
60
60
  ValueError
61
- If total_time ≤ transient_time
62
61
  If axis index is invalid
63
62
 
64
63
  Notes
@@ -93,14 +92,12 @@ def average_vs_time(
93
92
  mapping: Callable[[NDArray[np.float64], NDArray[np.float64]], NDArray[np.float64]],
94
93
  sample_times: Optional[NDArray[np.int32]] = None,
95
94
  axis: int = 1,
96
- transient_time: int = 0,
97
95
  ) -> NDArray[np.float64]:
98
96
  """
99
97
  Compute the time evolution of ensemble averages for a dynamical system.
100
98
 
101
99
  Tracks the average value of a specified coordinate across multiple trajectories,
102
- with options for downsampling and transient removal. Useful for studying
103
- convergence to equilibrium or statistical properties.
100
+ with options for downsampling. Useful for studying convergence to equilibrium or statistical properties.
104
101
 
105
102
  Parameters
106
103
  ----------
@@ -109,15 +106,13 @@ def average_vs_time(
109
106
  parameters : NDArray[np.float64]
110
107
  System parameters passed to mapping function
111
108
  total_time : int
112
- Total number of iterations (must be > transient_time)
109
+ Total number of iterations
113
110
  mapping : Callable[[NDArray, NDArray], NDArray]
114
111
  System evolution function: u_next = mapping(u, parameters)
115
112
  sample_times : Optional[NDArray[np.int64]], optional
116
113
  Specific time steps to record (default: record all steps)
117
114
  axis : int, optional
118
115
  Coordinate index to analyze (default: 1)
119
- transient_time : int, optional
120
- Initial iterations to discard (default: 0)
121
116
 
122
117
  Returns
123
118
  -------
@@ -127,7 +122,6 @@ def average_vs_time(
127
122
  Raises
128
123
  ------
129
124
  ValueError
130
- If total_time ≤ transient_time
131
125
  If sample_times contains values > total_time
132
126
  If axis is invalid
133
127
 
@@ -135,11 +129,9 @@ def average_vs_time(
135
129
  -----
136
130
  - Uses parallel processing over initial conditions
137
131
  - For large ensembles, consider using sample_times to reduce memory
138
- - The output length matches len(sample_times) if provided, else (total_time - transient_time)
132
+ - The output length matches len(sample_times) if provided, else total_time
139
133
  """
140
134
  # Input validation
141
- if total_time <= transient_time:
142
- raise ValueError("total_time must be > transient_time")
143
135
  if axis < 0 or axis >= u.shape[1]:
144
136
  raise ValueError(f"axis must be in [0, {u.shape[1]-1}]")
145
137
  if sample_times is not None:
@@ -148,30 +140,26 @@ def average_vs_time(
148
140
 
149
141
  # Initialize tracking
150
142
  num_ic = u.shape[0]
151
- effective_time = total_time - transient_time
152
143
  u_current = u.copy()
153
144
 
154
- # Handle output array
145
+ # Handle output array and sample times
155
146
  if sample_times is not None:
156
147
  output = np.empty(len(sample_times))
157
148
  else:
158
- output = np.empty(effective_time)
149
+ sample_times = np.arange(total_time) + 1
150
+ output = np.empty(total_time)
159
151
 
160
- output_idx = 0
152
+ sample_idx = 0
161
153
 
162
- # Main evolution loop
163
- for t in range(total_time):
164
- # Parallel evolution
165
- for i in prange(num_ic):
166
- u_current[i] = mapping(u_current[i], parameters)
167
-
168
- # Record if past transient and matches sampling
169
- if t >= transient_time:
170
- output[output_idx] = np.mean(u_current[:, axis])
171
- if sample_times is None:
172
- output_idx += 1
173
- elif t in sample_times:
174
- output_idx += 1
154
+ prev_t = 0
155
+ for st in sample_times:
156
+ steps = st - prev_t
157
+ for _ in range(steps):
158
+ for i in prange(num_ic):
159
+ u_current[i] = mapping(u_current[i], parameters)
160
+ output[sample_idx] = np.mean(u_current[:, axis])
161
+ sample_idx += 1
162
+ prev_t = st
175
163
 
176
164
  return output
177
165
 
@@ -184,7 +172,6 @@ def cumulative_average_vs_time(
184
172
  mapping: Callable[[NDArray[np.float64], NDArray[np.float64]], NDArray[np.float64]],
185
173
  sample_times: Optional[NDArray[np.int32]] = None,
186
174
  axis: int = 1,
187
- transient_time: int = 0,
188
175
  ) -> NDArray[np.float64]:
189
176
  """
190
177
  Compute the time evolution of the cumulative average of a coordinate across trajectories.
@@ -196,15 +183,13 @@ def cumulative_average_vs_time(
196
183
  parameters : NDArray[np.float64]
197
184
  System parameters passed to mapping function
198
185
  total_time : int
199
- Total number of iterations (must be > transient_time)
186
+ Total number of iterations
200
187
  mapping : Callable[[NDArray, NDArray], NDArray]
201
188
  System evolution function: u_next = mapping(u, parameters)
202
189
  sample_times : Optional[NDArray[np.int64]], optional
203
190
  Specific time steps to record (default: record all steps)
204
191
  axis : int, optional
205
192
  Coordinate index to analyze (default: 1)
206
- transient_time : int, optional
207
- Initial iterations to discard (default: 0)
208
193
 
209
194
  Returns
210
195
  -------
@@ -214,7 +199,6 @@ def cumulative_average_vs_time(
214
199
  Raises
215
200
  ------
216
201
  ValueError
217
- If total_time ≤ transient_time
218
202
  If sample_times contains invalid values
219
203
  If axis is invalid
220
204
 
@@ -222,39 +206,33 @@ def cumulative_average_vs_time(
222
206
  -----
223
207
  - Uses parallel processing over initial conditions
224
208
  - For large total_time, use sample_times to reduce memory usage
225
- - The cumulative average is computed over the ensemble after removing transient
209
+ - The output length matches len(sample_times) if provided, else total_time
226
210
  """
227
211
 
228
212
  num_ic = u.shape[0]
229
213
  u_current = u.copy()
230
214
  sum_values = np.zeros(num_ic)
215
+ sample_idx = 0
231
216
 
232
- # Initialize output array
217
+ # Handle output array and sample times
233
218
  if sample_times is not None:
234
- output_size = len(sample_times)
219
+ output = np.empty(len(sample_times))
235
220
  else:
236
- output_size = total_time - transient_time
237
-
238
- cumul_average = np.zeros(output_size)
239
- output_idx = 0
240
-
241
- # Main evolution loop
242
- for t in range(1, total_time + 1):
243
- # Parallel evolution
244
- for i in prange(num_ic):
245
- u_current[i] = mapping(u_current[i], parameters)
246
-
247
- # Record if past transient and matches sampling
248
- if t > transient_time:
249
- # Update running sum of squares
221
+ sample_times = np.arange(total_time, dtype=np.int64) + 1
222
+ output = np.empty(total_time)
223
+
224
+ prev_t = 0
225
+ for st in sample_times:
226
+ steps = st - prev_t
227
+ for _ in range(steps):
228
+ for i in prange(num_ic):
229
+ u_current[i] = mapping(u_current[i], parameters)
250
230
  sum_values += u_current[:, axis]
251
- cumul_average[output_idx] = np.mean(sum_values / t)
252
- if sample_times is None:
253
- output_idx += 1
254
- elif t in sample_times:
255
- output_idx += 1
231
+ output[sample_idx] = np.mean(sum_values / st)
232
+ sample_idx += 1
233
+ prev_t = st
256
234
 
257
- return cumul_average
235
+ return output
258
236
 
259
237
 
260
238
  @njit(cache=True, parallel=True)
@@ -265,7 +243,6 @@ def root_mean_squared(
265
243
  mapping: Callable[[NDArray[np.float64], NDArray[np.float64]], NDArray[np.float64]],
266
244
  sample_times: Optional[NDArray[np.int32]] = None,
267
245
  axis: int = 1,
268
- transient_time: int = 0,
269
246
  ) -> NDArray[np.float64]:
270
247
  """
271
248
  Compute the time evolution of the root mean square (RMS) of a coordinate across trajectories.
@@ -281,15 +258,13 @@ def root_mean_squared(
281
258
  parameters : NDArray[np.float64]
282
259
  System parameters passed to mapping function
283
260
  total_time : int
284
- Total number of iterations (must be > transient_time)
261
+ Total number of iterations
285
262
  mapping : Callable[[NDArray, NDArray], NDArray]
286
263
  System evolution function: u_next = mapping(u, parameters)
287
264
  sample_times : Optional[NDArray[np.int64]], optional
288
265
  Specific time steps to record (default: record all steps)
289
266
  axis : int, optional
290
267
  Coordinate index to analyze (default: 1)
291
- transient_time : int, optional
292
- Initial iterations to discard (default: 0)
293
268
 
294
269
  Returns
295
270
  -------
@@ -299,7 +274,6 @@ def root_mean_squared(
299
274
  Raises
300
275
  ------
301
276
  ValueError
302
- If total_time ≤ transient_time
303
277
  If sample_times contains invalid values
304
278
  If axis is invalid
305
279
 
@@ -307,39 +281,34 @@ def root_mean_squared(
307
281
  -----
308
282
  - Uses parallel processing over initial conditions
309
283
  - For large total_time, use sample_times to reduce memory usage
310
- - The RMS is computed over the ensemble after removing transient
284
+ - The output length matches len(sample_times) if provided, else total_time
311
285
  """
312
286
 
313
287
  num_ic = u.shape[0]
314
288
  u_current = u.copy()
315
289
  sum_squares = np.zeros(num_ic)
316
290
 
317
- # Initialize output array
291
+ # Handle output array and sample times
318
292
  if sample_times is not None:
319
- output_size = len(sample_times)
293
+ output = np.empty(len(sample_times))
320
294
  else:
321
- output_size = total_time - transient_time
295
+ sample_times = np.arange(total_time) + 1
296
+ output = np.empty(total_time)
322
297
 
323
- rms = np.zeros(output_size)
324
- output_idx = 0
298
+ sample_idx = 0
325
299
 
326
- # Main evolution loop
327
- for t in range(1, total_time + 1):
328
- # Parallel evolution
329
- for i in prange(num_ic):
330
- u_current[i] = mapping(u_current[i], parameters)
331
-
332
- # Record if past transient and matches sampling
333
- if t > transient_time:
334
- # Update running sum of squares
300
+ prev_t = 0
301
+ for st in sample_times: # st = sample time
302
+ steps = st - prev_t
303
+ for _ in range(steps):
304
+ for i in prange(num_ic):
305
+ u_current[i] = mapping(u_current[i], parameters)
335
306
  sum_squares += u_current[:, axis] ** 2
336
- rms[output_idx] = np.sqrt(np.mean(sum_squares / t))
337
- if sample_times is None:
338
- output_idx += 1
339
- elif t in sample_times:
340
- output_idx += 1
307
+ output[sample_idx] = np.sqrt(np.mean(sum_squares / st))
308
+ sample_idx += 1
309
+ prev_t = st
341
310
 
342
- return rms
311
+ return output
343
312
 
344
313
 
345
314
  @njit(cache=True, parallel=True)
@@ -350,7 +319,6 @@ def mean_squared_displacement(
350
319
  mapping: Callable[[NDArray[np.float64], NDArray[np.float64]], NDArray[np.float64]],
351
320
  sample_times: Optional[NDArray[np.int32]] = None,
352
321
  axis: int = 1,
353
- transient_time: int = 0,
354
322
  ) -> NDArray[np.float64]:
355
323
  """
356
324
  Compute the mean squared displacement (MSD) of a coordinate across multiple trajectories.
@@ -366,15 +334,13 @@ def mean_squared_displacement(
366
334
  parameters : NDArray[np.float64]
367
335
  System parameters passed to mapping function
368
336
  total_time : int
369
- Total number of iterations (must be > transient_time)
337
+ Total number of iterations
370
338
  mapping : Callable[[NDArray, NDArray], NDArray]
371
339
  System evolution function: u_next = mapping(u, parameters)
372
340
  sample_times : Optional[NDArray[np.int64]], optional
373
341
  Specific time steps to record (default: record all steps)
374
342
  axis : int, optional
375
343
  Coordinate index to analyze (default: 1)
376
- transient_time : int, optional
377
- Initial iterations to discard (default: 0)
378
344
 
379
345
  Returns
380
346
  -------
@@ -384,7 +350,6 @@ def mean_squared_displacement(
384
350
  Raises
385
351
  ------
386
352
  ValueError
387
- If total_time ≤ transient_time
388
353
  If sample_times contains invalid values
389
354
  If axis is invalid
390
355
 
@@ -392,7 +357,8 @@ def mean_squared_displacement(
392
357
  -----
393
358
  - Uses parallel processing over initial conditions
394
359
  - For normal diffusion, MSD grows linearly with time
395
- - The output length matches len(sample_times) if provided, else (total_time - transient_time)
360
+ - The output length matches len(sample_times) if provided, else total_time
361
+ - For large total_time, use sample_times to reduce memory usage
396
362
  """
397
363
  # Input validation
398
364
 
@@ -401,31 +367,27 @@ def mean_squared_displacement(
401
367
  # Store initial values for MSD calculation
402
368
  initial_values = u0[:, axis].copy()
403
369
 
404
- # Initialize output array
370
+ # Handle output array and sample times
405
371
  if sample_times is not None:
406
- output_size = len(sample_times)
372
+ output = np.empty(len(sample_times))
407
373
  else:
408
- output_size = total_time - transient_time
409
-
410
- msd = np.zeros(output_size)
411
- output_idx = 0
412
-
413
- # Main evolution loop
414
- for t in range(1, total_time + 1):
415
- # Parallel evolution
416
- for i in prange(num_ic):
417
- u[i] = mapping(u[i], parameters)
418
-
419
- # Calculate and store MSD if past transient
420
- if t > transient_time:
421
- displacements = u[:, axis] - initial_values
422
- msd[output_idx] = np.mean(displacements**2)
423
- if sample_times is None:
424
- output_idx += 1
425
- elif t in sample_times:
426
- output_idx += 1
427
-
428
- return msd
374
+ sample_times = np.arange(total_time) + 1
375
+ output = np.empty(total_time)
376
+
377
+ sample_idx = 0
378
+
379
+ prev_t = 0
380
+ for st in sample_times:
381
+ steps = st - prev_t
382
+ for _ in range(steps):
383
+ for i in prange(num_ic):
384
+ u[i] = mapping(u[i], parameters)
385
+ displacements = u[:, axis] - initial_values
386
+ output[sample_idx] = np.mean(displacements**2)
387
+ sample_idx += 1
388
+ prev_t = st
389
+
390
+ return output
429
391
 
430
392
 
431
393
  @njit(cache=True)
@@ -278,7 +278,7 @@ def validate_sample_times(sample_times, total_time):
278
278
  return None
279
279
 
280
280
  try:
281
- sample_times_arr = np.asarray(sample_times, dtype=np.int32)
281
+ sample_times_arr = np.asarray(sample_times, dtype=np.int64)
282
282
  if sample_times_arr.ndim != 1:
283
283
  raise ValueError("sample_times must be a 1D array")
284
284
  if np.any(sample_times_arr < 0) or np.any(sample_times_arr > total_time):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pynamicalsys
3
- Version: 1.2.2
3
+ Version: 1.3.0
4
4
  Summary: A Python toolkit for the analysis of dynamical systems
5
5
  Author-email: Matheus Rolim Sales <rolim.sales.m@gmail.com>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -733,7 +733,7 @@ $ pip install pynamicalsys
733
733
  To upgrade your current version of **pynamicalsys** to the latest stable release, run in your command line:
734
734
 
735
735
  ```bash
736
- $ pip install **pynamicalsys** --upgrade
736
+ $ pip install pynamicalsys --upgrade
737
737
  ```
738
738
 
739
739
  ### Install from source
@@ -781,7 +781,7 @@ Currently, our research paper is under review, but in the mean time, if you use
781
781
 
782
782
  ## Contributing
783
783
 
784
- We welcome contributions from the community! To get started, please see our Contributing Guidelines.
784
+ We welcome contributions from the community! To get started, please see our [Contributing Guidelines](https://pynamicalsys.readthedocs.io/en/latest/contributing.html).
785
785
 
786
786
  ## License
787
787
 
@@ -1,28 +1,28 @@
1
1
  pynamicalsys/__init__.py,sha256=IBHDcCD7wX8pULFXLk0yvF3uuNodvDKGirJektm1nR4,1215
2
- pynamicalsys/__version__.py,sha256=o0zEAUXpMoJZCULVYplCdjcZuIQ-3sIIZKyfNu_loQE,511
2
+ pynamicalsys/__version__.py,sha256=0Oc4EBzGTJOvXX0Vym4evglW1NQPpe8RLn8TdxsKzfs,704
3
3
  pynamicalsys/common/__init__.py,sha256=W4OESm7TA-EUTGUOtIgBgvSd1n80Mgl0KA2dCkw8yIw,721
4
4
  pynamicalsys/common/basin_analysis.py,sha256=teGEOMPPOdzKNZsN0_OvkzBlcV-UOANRjcdFyI2-FLM,5473
5
5
  pynamicalsys/common/recurrence_quantification_analysis.py,sha256=neBolgoWrGJYOQta71Jf2ZMwNK1RoaZb_wNHqb1mM7I,14356
6
- pynamicalsys/common/utils.py,sha256=ezNMSGTDVjtHpAa95Dr0r09s5CR_h9AShLU_ZuLMM44,10189
6
+ pynamicalsys/common/utils.py,sha256=-sPpnoC3G8fJmdGZHzyQvbYU3Ym3BUMBlklaTgcz_Ac,10304
7
7
  pynamicalsys/continuous_time/__init__.py,sha256=W4OESm7TA-EUTGUOtIgBgvSd1n80Mgl0KA2dCkw8yIw,721
8
- pynamicalsys/continuous_time/chaotic_indicators.py,sha256=rwstGDMx2ynT7woezVqaOQ10HJpblp0dJvheLjpCnBg,9891
8
+ pynamicalsys/continuous_time/chaotic_indicators.py,sha256=UNZL1yJvUAvFC-RD-Xr3xZIEFCXgdpgw8KzmTh7U9OU,12542
9
9
  pynamicalsys/continuous_time/models.py,sha256=YJtmsVZqSn3GDNqV0IKSQBHWZSCDY_EJ5Sgh4ulDc9I,5339
10
- pynamicalsys/continuous_time/numerical_integrators.py,sha256=pSsDIlxhSntLxfHLRNduqjExdiUEY6yNpQRyvLBraqk,9667
11
- pynamicalsys/continuous_time/trajectory_analysis.py,sha256=1Eh4WEIlLT_fFGfgEorSgN1qGZ9ym0kVEPbWcRRXNKQ,4406
10
+ pynamicalsys/continuous_time/numerical_integrators.py,sha256=CtP8GWNWGE5_2FYnrpbKFZMKklJdZBDWq3FkeXoIG2U,9684
11
+ pynamicalsys/continuous_time/trajectory_analysis.py,sha256=hpoEw0EZLRV3UoWEGM7P7rH6LLY8lRNZXJ2ymQnNNDw,5256
12
12
  pynamicalsys/continuous_time/validators.py,sha256=dvtlcWbn2w5_vNUB68f7ywFPyFrPKe3cUDqGCk52mhw,3834
13
13
  pynamicalsys/core/__init__.py,sha256=W4OESm7TA-EUTGUOtIgBgvSd1n80Mgl0KA2dCkw8yIw,721
14
14
  pynamicalsys/core/basin_metrics.py,sha256=sqSj-UCzBQdRaTvOBtzo8SCgJN90T3GiWy4nlLsbg5c,7604
15
- pynamicalsys/core/continuous_dynamical_systems.py,sha256=nkESGfuxBT_UmoY_2tJv1fMY4hK1J0M74aQpLgNVEyI,30482
16
- pynamicalsys/core/discrete_dynamical_systems.py,sha256=AhxyAOZFnkjf4KnJiaReN5ZRndkFFEG_GOT2_PeLpXs,135874
15
+ pynamicalsys/core/continuous_dynamical_systems.py,sha256=uunVcArRk5JEG0Z1G8KqlmYDxVzPokoeqNSXzXvUZN8,37989
16
+ pynamicalsys/core/discrete_dynamical_systems.py,sha256=JcDL71M3kaQJLnkWOVTG28ylolNmitMg1tlpq3EryQA,145975
17
17
  pynamicalsys/core/plot_styler.py,sha256=sVX_rb1HSt340U3zyPlXojylhma9cKCOgYirMIge18M,5647
18
18
  pynamicalsys/core/time_series_metrics.py,sha256=7fwXO1I6lIjmv_MzYxBn-9k2gjjnhm_y_Tp3diE1z68,5102
19
19
  pynamicalsys/discrete_time/__init__.py,sha256=W4OESm7TA-EUTGUOtIgBgvSd1n80Mgl0KA2dCkw8yIw,721
20
- pynamicalsys/discrete_time/dynamical_indicators.py,sha256=Ck6orYxy09NHsVYnTSmkROq33csiyiePdsqzOAJCKcs,43057
20
+ pynamicalsys/discrete_time/dynamical_indicators.py,sha256=XDZ6e-nFCDO7UgkkBnuqsr70c3LLJ8bvew82pXrV1no,51759
21
21
  pynamicalsys/discrete_time/models.py,sha256=u9MlaCzBzR_OomWRYbEC2sS2qpfDg7qzZjX8YDijVe0,10756
22
22
  pynamicalsys/discrete_time/trajectory_analysis.py,sha256=W3nqLJgqJYMV9DbBbSSOpzNDQ7XlroP3lC0sgSoFztY,48669
23
- pynamicalsys/discrete_time/transport.py,sha256=29leQue2ReRbFzT_riqWXTZDvf2O7jMsMOUnAQPBrBU,15972
24
- pynamicalsys/discrete_time/validators.py,sha256=4eWQAlZgCzFsrmijzVF10CZuoIMiu-jvrrvRokBFTkY,10013
25
- pynamicalsys-1.2.2.dist-info/METADATA,sha256=UQDElv3HVAqJDDUM0251dJVDbQZPhyLTMe-hnHfPK-E,45834
26
- pynamicalsys-1.2.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
- pynamicalsys-1.2.2.dist-info/top_level.txt,sha256=1AqoHXye_hGRkvqu4KY0SdEuNTgqf3xyTlV8xhiJJFU,13
28
- pynamicalsys-1.2.2.dist-info/RECORD,,
23
+ pynamicalsys/discrete_time/transport.py,sha256=mp6jqI8zfqwVrV5ZXqyOaFKzAjuCPXl6pQtzmX-gDok,14429
24
+ pynamicalsys/discrete_time/validators.py,sha256=sk5PuQ6vxNj6ReqIfBTb2iQqlgY0SUkndS56xcp3w_w,10013
25
+ pynamicalsys-1.3.0.dist-info/METADATA,sha256=_A4OpfJ39pd-eGH-HY08lyuq-KcDbDZB6ktdNb-uWwk,45897
26
+ pynamicalsys-1.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
27
+ pynamicalsys-1.3.0.dist-info/top_level.txt,sha256=1AqoHXye_hGRkvqu4KY0SdEuNTgqf3xyTlV8xhiJJFU,13
28
+ pynamicalsys-1.3.0.dist-info/RECORD,,