piegy 1.1.2__py3-none-any.whl → 1.1.4__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.
piegy/__init__.py CHANGED
@@ -20,7 +20,7 @@ Last update: May 12, 2025
20
20
 
21
21
  from .__version__ import __version__
22
22
 
23
- from .model import simulation, run, demo_model
23
+ from .simulation import model, run, demo_model
24
24
  from .videos import make_video, SUPPORTED_FIGURES
25
25
  from .data_tools import save_data, read_data
26
26
 
@@ -33,13 +33,13 @@ from .test_var import (test_var1, var_UV1, var_pi1, var_convergence1, get_dirs1,
33
33
  test_var2, var_UV2, var_pi2, var_convergence2, get_dirs2)
34
34
 
35
35
 
36
- model_members = ['simulation', 'run', 'get_demo_model']
36
+ simulation_memebers = ['model', 'run', 'demo_model']
37
37
 
38
38
  videos_members = ['make_video', 'SUPPORTED_FIGURES']
39
39
 
40
40
  data_members = ['save_data', 'read_data']
41
41
 
42
- analysis_members = ['expected_rounds', 'scale_maxtime', 'check_convergence', 'combine_sim']
42
+ analysis_members = ['expected_rounds', 'scale_maxtime', 'check_convergence', 'combine_mod']
43
43
 
44
44
  figures_members = ['UV_heatmap', 'UV_bar', 'UV_dyna', 'UV_hist', 'UV_std', 'UV_expected_val', 'UV_expected',
45
45
  'pi_heatmap', 'pi_bar', 'pi_dyna', 'pi_hist', 'pi_std', 'UV_pi']
@@ -48,7 +48,7 @@ test_var_members = ['test_var1', 'var_UV1', 'var_pi1', 'var_convergence1', 'get_
48
48
  'test_var2', 'var_UV2', 'var_pi2', 'var_convergence2', 'get_dirs2']
49
49
 
50
50
 
51
- __all__ = model_members + videos_members + data_members + figures_members + analysis_members + test_var_members
51
+ __all__ = simulation_memebers + videos_members + data_members + figures_members + analysis_members + test_var_members
52
52
 
53
53
 
54
54
 
piegy/__version__.py CHANGED
@@ -12,9 +12,11 @@ version history:
12
12
  0.1.8: updated installation in README
13
13
  0.1.9: first round of full debugging
14
14
 
15
- 1.0.0: first version in PyPI
15
+ 1.0.0: first version in PyPI.
16
16
  1.1.0: debugging. Updated a range of functions, in the following modules: figures, videos, test_var, model, figure_tools
17
17
  1.1.1: minor debugging in model module.
18
18
  1.1.2: fix text bad location in figure_tools, update labeling and titling in figures and test_var. Add dpi param to make_video in videos. Remove reset_data function in model.
19
+ 1.1.3: update README.
20
+ 1.1.4: changed name: ``model`` module to ``simulation``, and ``model.simulation`` class to ``simulation.model``. Bug fix in videos.
19
21
 
20
22
  '''
piegy/analysis.py CHANGED
@@ -3,8 +3,8 @@ This file contains pre-processing, post-processing, and analytical tools for sim
3
3
 
4
4
  Public Funcions:
5
5
  - check_convergence: Check whether a simulation result converges. i.e. whether U, V's fluctuation are very small.
6
- - combine_sim: Combine two simulation objects and return a new one (the first two unchanged).
7
- Intended usage: say you have sim1, sim2 with same parameters except for sim_time, say 10 and 20.
6
+ - combine_sim: Combine two model objects and return a new one (the first two unchanged).
7
+ Intended usage: say you have mod1, mod2 with same parameters except for sim_time, say 10 and 20.
8
8
  Then combine_sim takes a weighted average (with ratio 1:2) of results and return a new sim3.
9
9
  So that you now have sim3 with 30 sim_time.
10
10
 
@@ -17,7 +17,7 @@ Private Functions:
17
17
 
18
18
  '''
19
19
 
20
- from . import model as model
20
+ from . import simulation as simulation
21
21
  from . import figures as figures
22
22
  from .tools import figure_tools as figure_t
23
23
 
@@ -27,17 +27,17 @@ import math
27
27
 
28
28
 
29
29
 
30
- def rounds_expected(sim):
30
+ def rounds_expected(mod):
31
31
  '''
32
32
  NOTE: Not well-developed. Not recommending to use.
33
33
 
34
- Predict how many rounds will run in single_test. i.e., how many for loops from time = 0 to sim.maxtime.
34
+ Predict how many rounds will run in single_test. i.e., how many for loops from time = 0 to mod.maxtime.
35
35
  Calculated based on expected_UV.
36
36
  '''
37
37
 
38
- N = sim.N
39
- M = sim.M
40
- U_expected, V_expected = figures.UV_expected_val(sim)
38
+ N = mod.N
39
+ M = mod.M
40
+ U_expected, V_expected = figures.UV_expected_val(mod)
41
41
 
42
42
  rates = []
43
43
  patch0 = None # simulate patch i, j
@@ -46,19 +46,19 @@ def rounds_expected(sim):
46
46
  # loop through N, M, create a sample patch to calculate rates, store them
47
47
  for i in range(N):
48
48
  for j in range(M):
49
- patch0 = model.patch(U_expected[i][j], V_expected[i][j], sim.X[i][j], sim.P[i][j])
49
+ patch0 = simulation.patch(U_expected[i][j], V_expected[i][j], mod.X[i][j], mod.P[i][j])
50
50
 
51
51
  nb_indices = None
52
- if sim.boundary:
53
- nb_indices = model.find_nb_zero_flux(N, M, i, j)
52
+ if mod.boundary:
53
+ nb_indices = simulation.find_nb_zero_flux(N, M, i, j)
54
54
  else:
55
- nb_indices = model.find_nb_periodical(N, M, i, j)
55
+ nb_indices = simulation.find_nb_periodical(N, M, i, j)
56
56
 
57
57
  for k in range(4):
58
58
  if nb_indices[k] != None:
59
59
  i_nb = nb_indices[k][0]
60
60
  j_nb = nb_indices[k][1]
61
- patch0_nb_k = model.patch(U_expected[i_nb][j_nb], V_expected[i_nb][j_nb], sim.X[i_nb][j_nb], sim.P[i_nb][j_nb])
61
+ patch0_nb_k = simulation.patch(U_expected[i_nb][j_nb], V_expected[i_nb][j_nb], mod.X[i_nb][j_nb], mod.P[i_nb][j_nb])
62
62
  patch0_nb_k.update_pi_k()
63
63
  patch0_nb.append(patch0_nb_k)
64
64
 
@@ -73,40 +73,40 @@ def rounds_expected(sim):
73
73
  rates += patch0.mig_rates
74
74
 
75
75
  delta_t_expected = (1 / sum(rates)) * math.log(1 / 0.5)
76
- r_expected = round(sim.maxtime / delta_t_expected)
76
+ r_expected = round(mod.maxtime / delta_t_expected)
77
77
 
78
78
  return r_expected
79
79
 
80
80
 
81
81
 
82
82
 
83
- def scale_maxtime(sim1, sim2, scale_interval = True):
83
+ def scale_maxtime(mod1, mod2, scale_interval = True):
84
84
  '''
85
85
  NOTE: Not well-developed. Not recommending to use.
86
86
 
87
- Scale sim1's maxtime towards sim2's, so they will run similar number of rounds in single_test, and hence similar runtime.
87
+ Scale mod1's maxtime towards mod2's, so they will run similar number of rounds in single_test, and hence similar runtime.
88
88
  Intended to reduce the effect of changing params on runtime.
89
89
 
90
90
  Input:
91
- - scale_interval decides whether to scale sim1's interval as well, so that the same number of data will be stored.
91
+ - scale_interval decides whether to scale mod1's interval as well, so that the same number of data will be stored.
92
92
  '''
93
93
 
94
- r_expected1 = rounds_expected(sim1)
95
- r_expected2 = rounds_expected(sim2)
94
+ r_expected1 = rounds_expected(mod1)
95
+ r_expected2 = rounds_expected(mod2)
96
96
  ratio = r_expected2 / r_expected1
97
97
 
98
- new_maxtime = sim1.maxtime * ratio
99
- old_max_record = sim1.maxtime / sim1.interval
98
+ new_maxtime = mod1.maxtime * ratio
99
+ old_max_record = mod1.maxtime / mod1.interval
100
100
 
101
101
  if scale_interval:
102
- sim1.interval = new_maxtime / old_max_record
102
+ mod1.interval = new_maxtime / old_max_record
103
103
 
104
- sim1.change_maxtime(new_maxtime)
104
+ mod1.change_maxtime(new_maxtime)
105
105
 
106
106
 
107
107
 
108
108
 
109
- def check_convergence(sim, interval = 20, start = 0.8, fluc = 0.07):
109
+ def check_convergence(mod, interval = 20, start = 0.8, fluc = 0.07):
110
110
  '''
111
111
  Check whether a simulation converges or not.
112
112
  Based on whether the fluctuation of U, V, pi all < 'fluc' in the later 'tail' portion of time.
@@ -114,7 +114,7 @@ def check_convergence(sim, interval = 20, start = 0.8, fluc = 0.07):
114
114
  Essentially find the max and min values (of population) in every small interval, and then check whether their difference > min * fluc.
115
115
 
116
116
  Inputs:
117
- - sim: a simulation object
117
+ - sim: a simulation.model object
118
118
  - interval: int, how many records to take average over,
119
119
  and then compare this "local mean" with "whole-tail mean" and expect the difference to be less than fluc.
120
120
  - start: (0, 1) float, decides where you expect to check convergence from. Smaller start needs earlier convergence.
@@ -128,25 +128,25 @@ def check_convergence(sim, interval = 20, start = 0.8, fluc = 0.07):
128
128
  if (type(interval) != int) or (interval < 1):
129
129
  raise ValueError("interval should be an int >= 1")
130
130
 
131
- interval = figure_t.scale_interval(interval, sim.compress_itv)
131
+ interval = figure_t.scale_interval(interval, mod.compress_itv)
132
132
 
133
- start_index = int(sim.max_record * start) # where the tail starts
134
- num_interval = int((sim.max_record - start_index) / interval) # how many intervals in total
133
+ start_index = int(mod.max_record * start) # where the tail starts
134
+ num_interval = int((mod.max_record - start_index) / interval) # how many intervals in total
135
135
 
136
136
  # find the max and min value of the small intervals
137
137
  # initiate as average of the first interval
138
- min_U = np.mean(sim.U[:, :, start_index : start_index + interval])
139
- max_U = np.mean(sim.U[:, :, start_index : start_index + interval])
140
- min_V = np.mean(sim.V[:, :, start_index : start_index + interval])
141
- max_V = np.mean(sim.V[:, :, start_index : start_index + interval])
138
+ min_U = np.mean(mod.U[:, :, start_index : start_index + interval])
139
+ max_U = np.mean(mod.U[:, :, start_index : start_index + interval])
140
+ min_V = np.mean(mod.V[:, :, start_index : start_index + interval])
141
+ max_V = np.mean(mod.V[:, :, start_index : start_index + interval])
142
142
 
143
143
  for i in range(1, num_interval):
144
144
  # lower and upper bound of current interval
145
145
  lower = start_index + i * interval
146
146
  upper = lower + interval
147
147
 
148
- ave_U = np.mean(sim.U[:, :, lower : upper])
149
- ave_V = np.mean(sim.V[:, :, lower : upper])
148
+ ave_U = np.mean(mod.U[:, :, lower : upper])
149
+ ave_V = np.mean(mod.V[:, :, lower : upper])
150
150
 
151
151
  # Compare with min, max
152
152
  if ave_U > max_U:
@@ -170,51 +170,51 @@ def check_convergence(sim, interval = 20, start = 0.8, fluc = 0.07):
170
170
 
171
171
 
172
172
 
173
- def combine_sim(sim1, sim2):
173
+ def combine_sim(mod1, mod2):
174
174
  '''
175
- Combine data of sim1 and sim2.
176
- Intended usage: assume sim1 and sim2 has the same N, M, maxtime, interval, boundary, max_record, and I, X, P
175
+ Combine data of mod1 and mod2.
176
+ Intended usage: assume mod1 and mod2 has the same N, M, maxtime, interval, boundary, max_record, and I, X, P
177
177
  combine_sim then combines the two results and calculate a new weighted average of the two data, return a new sim object.
178
178
  Essentially allows breaking up many rounds of simulations into several smaller pieces, and then put together.
179
179
 
180
180
  Inputs:
181
- - sim1, sim2: both stochastic_model.simulation object. All input parameters the same except for sim_time, print_pct and seed.
181
+ - mod1, mod2: both simulation.model objects. All input parameters the same except for sim_time, print_pct and seed.
182
182
  Raises error if not.
183
183
 
184
184
  Returns:
185
185
 
186
- - sim3: a new simulation object whose U, V, U_pi, V_pi are weighted averages of sim1 and sim2
186
+ - sim3: a new model object whose U, V, U_pi, V_pi are weighted averages of mod1 and mod2
187
187
  (weighted by sim_time).
188
- sim3.print_pct is set to sim1's, seed set to None, sim_time set to sum of sim1's and sim2's. All other params same as sim1
188
+ sim3.print_pct is set to mod1's, seed set to None, sim_time set to sum of mod1's and mod2's. All other params same as mod1
189
189
  '''
190
- if not (sim1.N == sim2.N and
191
- sim1.M == sim2.M and
192
- sim1.maxtime == sim2.maxtime and
193
- sim1.record_itv == sim2.record_itv and
194
- sim1.boundary == sim2.boundary and
195
- sim1.max_record == sim2.max_record and
196
- np.array_equal(sim1.I, sim2.I) and
197
- np.array_equal(sim1.X, sim2.X) and
198
- np.array_equal(sim1.P, sim2.P)):
190
+ if not (mod1.N == mod2.N and
191
+ mod1.M == mod2.M and
192
+ mod1.maxtime == mod2.maxtime and
193
+ mod1.record_itv == mod2.record_itv and
194
+ mod1.boundary == mod2.boundary and
195
+ mod1.max_record == mod2.max_record and
196
+ np.array_equal(mod1.I, mod2.I) and
197
+ np.array_equal(mod1.X, mod2.X) and
198
+ np.array_equal(mod1.P, mod2.P)):
199
199
 
200
- raise ValueError('sim1 and sim2 have different input parameters (N, M, maxtime, interval, boundary, max_record, or I, X, P).')
200
+ raise ValueError('mod1 and mod2 have different input parameters (N, M, maxtime, interval, boundary, max_record, or I, X, P).')
201
201
 
202
- if sim1.seed == sim2.seed:
202
+ if mod1.seed == mod2.seed:
203
203
  raise ValueError('Cannot combine two simulations with the same seed.')
204
204
 
205
- # copy sim1, except for no data and a different sim_time
206
- combined_sim_time = sim1.sim_time + sim2.sim_time
207
- sim3 = sim1.copy(copy_data = False)
205
+ # copy mod1, except for no data and a different sim_time
206
+ combined_sim_time = mod1.sim_time + mod2.sim_time
207
+ sim3 = mod1.copy(copy_data = False)
208
208
  sim3.sim_time = combined_sim_time
209
209
  sim3.seed = None
210
210
 
211
211
  for i in range(sim3.N):
212
212
  for j in range(sim3.M):
213
213
  for k in range(sim3.max_record):
214
- sim3.U[i][j][k] = (sim1.U[i][j][k] * sim1.sim_time + sim2.U[i][j][k] * sim2.sim_time) / combined_sim_time
215
- sim3.V[i][j][k] = (sim1.V[i][j][k] * sim1.sim_time + sim2.V[i][j][k] * sim2.sim_time) / combined_sim_time
216
- sim3.U_pi[i][j][k] = (sim1.U_pi[i][j][k] * sim1.sim_time + sim2.U_pi[i][j][k] * sim2.sim_time) / combined_sim_time
217
- sim3.V_pi[i][j][k] = (sim1.V_pi[i][j][k] * sim1.sim_time + sim2.V_pi[i][j][k] * sim2.sim_time) / combined_sim_time
214
+ sim3.U[i][j][k] = (mod1.U[i][j][k] * mod1.sim_time + mod2.U[i][j][k] * mod2.sim_time) / combined_sim_time
215
+ sim3.V[i][j][k] = (mod1.V[i][j][k] * mod1.sim_time + mod2.V[i][j][k] * mod2.sim_time) / combined_sim_time
216
+ sim3.U_pi[i][j][k] = (mod1.U_pi[i][j][k] * mod1.sim_time + mod2.U_pi[i][j][k] * mod2.sim_time) / combined_sim_time
217
+ sim3.V_pi[i][j][k] = (mod1.V_pi[i][j][k] * mod1.sim_time + mod2.V_pi[i][j][k] * mod2.sim_time) / combined_sim_time
218
218
 
219
219
  return sim3
220
220
 
piegy/data_tools.py CHANGED
@@ -1,33 +1,33 @@
1
1
  '''
2
- Stores and reads a simulation object.
2
+ Stores and reads a model object.
3
3
 
4
4
  Functions:
5
- - save_data: save a simulation object.
6
- - read_data: read a simulation object.
5
+ - save_data: save a model object.
6
+ - read_data: read a model object.
7
7
  '''
8
8
 
9
9
 
10
- from . import model as model
10
+ from . import simulation
11
11
 
12
12
  import json
13
13
  import gzip
14
14
  import os
15
15
 
16
16
 
17
- def save_data(sim, dirs = '', print_msg = True):
17
+ def save_data(mod, dirs = '', print_msg = True):
18
18
  '''
19
- Saves a simulation object. Data will be stored at dirs/data.json.gz
19
+ Saves a model object. Data will be stored at dirs/data.json.gz
20
20
 
21
21
  Inputs:
22
- - sim: Your simulation object.
22
+ - mod: Your model object.
23
23
  - dirs: Where to save it.
24
24
  - print_msg: Whether to print message after saving.
25
25
  '''
26
26
 
27
27
  try:
28
- _ = sim.N
28
+ _ = mod.N
29
29
  except AttributeError:
30
- raise ValueError('sim is not a simulation object')
30
+ raise ValueError('mod is not a model object')
31
31
 
32
32
  if dirs != '':
33
33
  # add slash '/'
@@ -39,33 +39,33 @@ def save_data(sim, dirs = '', print_msg = True):
39
39
  data = []
40
40
 
41
41
  inputs1 = []
42
- inputs1.append(sim.N)
43
- inputs1.append(sim.M)
44
- inputs1.append(sim.maxtime)
45
- inputs1.append(sim.record_itv)
46
- inputs1.append(sim.sim_time)
47
- inputs1.append(sim.boundary)
48
- inputs1.append(sim.I.tolist())
49
- inputs1.append(sim.X.tolist())
50
- inputs1.append(sim.P.tolist())
42
+ inputs1.append(mod.N)
43
+ inputs1.append(mod.M)
44
+ inputs1.append(mod.maxtime)
45
+ inputs1.append(mod.record_itv)
46
+ inputs1.append(mod.sim_time)
47
+ inputs1.append(mod.boundary)
48
+ inputs1.append(mod.I.tolist())
49
+ inputs1.append(mod.X.tolist())
50
+ inputs1.append(mod.P.tolist())
51
51
  data.append(inputs1)
52
52
 
53
53
  inputs2 = []
54
- inputs2.append(sim.print_pct)
55
- inputs2.append(sim.seed)
56
- inputs2.append(sim.UV_dtype)
57
- inputs2.append(sim.pi_dtype)
54
+ inputs2.append(mod.print_pct)
55
+ inputs2.append(mod.seed)
56
+ inputs2.append(mod.UV_dtype)
57
+ inputs2.append(mod.pi_dtype)
58
58
  data.append(inputs2)
59
59
 
60
60
  # skipped rng
61
61
 
62
62
  outputs = []
63
- outputs.append(sim.max_record)
64
- outputs.append(sim.compress_itv)
65
- outputs.append(sim.U.tolist())
66
- outputs.append(sim.V.tolist())
67
- outputs.append(sim.U_pi.tolist())
68
- outputs.append(sim.V_pi.tolist())
63
+ outputs.append(mod.max_record)
64
+ outputs.append(mod.compress_itv)
65
+ outputs.append(mod.U.tolist())
66
+ outputs.append(mod.V.tolist())
67
+ outputs.append(mod.U_pi.tolist())
68
+ outputs.append(mod.V_pi.tolist())
69
69
  # H&V_pi_total are not saved, will be calculated when reading the data
70
70
  data.append(outputs)
71
71
 
@@ -83,14 +83,14 @@ def save_data(sim, dirs = '', print_msg = True):
83
83
 
84
84
  def read_data(dirs):
85
85
  '''
86
- Reads and returns a simulation object.
86
+ Reads and returns a model object.
87
87
 
88
88
  Inputs:
89
89
  - dirs: where to read from, just provide the folder-subfolder names. Don't include 'data.json.gz'
90
- - print_msg: this function prints a message when the sim.compress_itv != None. Setting print_msg = False will skip ignore this message.
90
+ - print_msg: this function prints a message when the mod.compress_itv != None. Setting print_msg = False will skip ignore this message.
91
91
 
92
92
  Returns:
93
- - sim: a piegy.model.simulation object read from the data.
93
+ - mod: a piegy.model.model object read from the data.
94
94
  '''
95
95
 
96
96
  if dirs != '':
@@ -110,7 +110,7 @@ def read_data(dirs):
110
110
 
111
111
  # inputs
112
112
  try:
113
- sim = model.simulation(N = data[0][0], M = data[0][1], maxtime = data[0][2], record_itv = data[0][3],
113
+ mod = simulation.model(N = data[0][0], M = data[0][1], maxtime = data[0][2], record_itv = data[0][3],
114
114
  sim_time = data[0][4], boundary = data[0][5], I = data[0][6], X = data[0][7], P = data[0][8],
115
115
  print_pct = data[1][0], seed = data[1][1], UV_dtype = data[1][2], pi_dtype = data[1][3])
116
116
  except:
@@ -118,12 +118,12 @@ def read_data(dirs):
118
118
 
119
119
  # outputs
120
120
  try:
121
- sim.set_data(data_empty = False, max_record = data[2][0], compress_itv = data[2][1],
121
+ mod.set_data(data_empty = False, max_record = data[2][0], compress_itv = data[2][1],
122
122
  U = data[2][2], V = data[2][3], U_pi = data[2][4], V_pi = data[2][5])
123
123
  except:
124
- raise ValueError('Invalid simulation results saved in data')
124
+ raise ValueError('Invalid model results saved in data')
125
125
 
126
- return sim
126
+ return mod
127
127
 
128
128
 
129
129