piegy 1.0.0__py3-none-any.whl → 1.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.
piegy/__version__.py CHANGED
@@ -13,5 +13,7 @@ version history:
13
13
  0.1.9: first round of full debugging
14
14
 
15
15
  1.0.0: first version in PyPI
16
+ 1.1.0: debugging. Updated a range of functions, in the following modules: figures, videos, test_var, model, figure_tools
17
+ 1.1.1: minor debugging in model module.
16
18
 
17
19
  '''
piegy/data_tools.py CHANGED
@@ -118,12 +118,14 @@ def read_data(dirs):
118
118
 
119
119
  # outputs
120
120
  try:
121
- sim.set_data(False, data[2][0], data[2][1], data[2][2], data[2][3], data[2][4], data[2][5])
121
+ sim.set_data(data_empty = False, max_record = data[2][0], compress_itv = data[2][1],
122
+ U = data[2][2], V = data[2][3], U_pi = data[2][4], V_pi = data[2][5])
122
123
  except:
123
124
  raise ValueError('Invalid simulation results saved in data')
124
125
 
125
126
  return sim
126
-
127
+
128
+
127
129
 
128
130
 
129
131
 
piegy/figures.py CHANGED
@@ -37,20 +37,20 @@ import matplotlib.pyplot as plt
37
37
  import numpy as np
38
38
 
39
39
 
40
-
41
40
  # curve type in plot
42
41
  # used by UV_dyna, UV_std, and pi_dyna
43
42
  CURVE_TYPE = '-'
44
43
 
45
44
 
46
45
 
47
- def UV_heatmap(sim, U_color = 'Purples', V_color = 'Greens', start = 0.95, end = 1.0, annot = False, fmt = '.3g'):
46
+ def UV_heatmap(sim, ax_U = None, ax_V = None, U_color = 'Purples', V_color = 'Greens', start = 0.95, end = 1.0, annot = False, fmt = '.3g'):
48
47
  '''
49
48
  Makes two heatmaps for U, V average distribution over a time interval, respectively. Works best for 2D space.
50
49
  1D works as well, but figures look bad.
51
50
 
52
51
  Inputs:
53
52
  sim: A model.simulation object.
53
+ ax_U, ax_V: matplotlib axes to plot on. New axes will be created if None is given.
54
54
  U_color: Color for U's heatmap, uses matplotlib color maps.
55
55
  V_color: Color for V's heatmap.
56
56
  start: (0,1) float, where the interval should start from. Intended as a 'percentage'.
@@ -60,7 +60,7 @@ def UV_heatmap(sim, U_color = 'Purples', V_color = 'Greens', start = 0.95, end =
60
60
  fmt: Number format for annotations. How many digits you want to keep. Please set annot = True first and then use fmt.
61
61
 
62
62
  Returns:
63
- fig1, fig2: Two heatmaps of U, V distribution.
63
+ ax_U, ax_V: matplotlib axes with heatmaps of U, V distribution plotted upon.
64
64
  '''
65
65
 
66
66
  start_index = int(start * sim.max_record)
@@ -77,20 +77,21 @@ def UV_heatmap(sim, U_color = 'Purples', V_color = 'Greens', start = 0.95, end =
77
77
  V_title = figure_t.gen_title('V', start, end)
78
78
  V_text = figure_t.gen_text(np.mean(V_ave), np.std(V_ave))
79
79
 
80
- fig1 = figure_t.heatmap(U_ave, U_color, annot, fmt, U_title, U_text)
81
- fig2 = figure_t.heatmap(V_ave, V_color, annot, fmt, V_title, V_text)
80
+ ax_U = figure_t.heatmap(U_ave, ax_U, U_color, annot, fmt, U_title, U_text)
81
+ ax_V = figure_t.heatmap(V_ave, ax_V, V_color, annot, fmt, V_title, V_text)
82
82
 
83
- return fig1, fig2
83
+ return ax_U, ax_V
84
84
 
85
85
 
86
86
 
87
- def UV_bar(sim, U_color = 'purple', V_color = 'green', start = 0.95, end = 1.0):
87
+ def UV_bar(sim, ax_U = None, ax_V = None, U_color = 'purple', V_color = 'green', start = 0.95, end = 1.0):
88
88
  '''
89
89
  Makes two barplots for U, V average distribution over a time interval. Works best for 1D space.
90
90
  2D works as well, but figures look bad.
91
91
 
92
92
  Inputs:
93
93
  sim: A model.simulation object.
94
+ ax_U, ax_V: matplotlib axes to plot on. New axes will be created if None is given.
94
95
  U_color: Color of U's barplot. Uses Matplotlib colors.
95
96
  See available colors at: https://matplotlib.org/stable/gallery/color/named_colors.html
96
97
  V_color: Color of V's barplot. Uses Matplotlib colors.
@@ -98,7 +99,7 @@ def UV_bar(sim, U_color = 'purple', V_color = 'green', start = 0.95, end = 1.0):
98
99
  end: (0,1) float. Where you want the interval to end.
99
100
 
100
101
  Returns:
101
- fig1, fig2: Two Matplotlib bar plots, for U and V, respectively.
102
+ ax_U, ax_V: matplotlib axes with bar plots for U and V plotted upon.
102
103
  '''
103
104
 
104
105
  start_index = int(start * sim.max_record)
@@ -114,15 +115,15 @@ def UV_bar(sim, U_color = 'purple', V_color = 'green', start = 0.95, end = 1.0):
114
115
  V_title = figure_t.gen_title('V', start, end)
115
116
  V_text = figure_t.gen_text(np.mean(V_ave), np.std(V_ave))
116
117
 
117
- fig1 = figure_t.bar(U_ave, color = U_color, xlabel = 'patches', ylabel = 'U', title = U_title, text = U_text)
118
- fig2 = figure_t.bar(V_ave, color = V_color, xlabel = 'patches', ylabel = 'V', title = V_title, text = V_text)
118
+ ax_U = figure_t.bar(U_ave, ax = ax_U, color = U_color, xlabel = 'patches', ylabel = 'U', title = U_title, text = U_text)
119
+ ax_V = figure_t.bar(V_ave, ax = ax_V, color = V_color, xlabel = 'patches', ylabel = 'V', title = V_title, text = V_text)
119
120
 
120
- return fig1, fig2
121
+ return ax_U, ax_V
121
122
 
122
123
 
123
124
 
124
125
 
125
- def UV_dyna(sim, interval = 20, grid = True):
126
+ def UV_dyna(sim, ax = None, interval = 20, grid = True):
126
127
  '''
127
128
  Plots how total U, V change overtime.
128
129
  The curves are not directly based on every single data point.
@@ -132,13 +133,14 @@ def UV_dyna(sim, interval = 20, grid = True):
132
133
 
133
134
  Inputs:
134
135
  sim: A model.simulation object.
136
+ ax: matplotlib ax to plot on. New ax will be created if None is given.
135
137
  interval: How many data points to take average over. Larger value makes curves smoother, but also loses local fluctuations.
136
138
  NOTE: this interval doesn't overlap with sim.compress_itv.
137
139
  e.g. you already took average over every 20 data points, then using interval <= 20 here has no smoothing effect.
138
140
  grid: Whether to add grid lines to plot.
139
141
 
140
142
  Returns:
141
- fig: A Matplotlib figure, contains U's, V's, and U+V population.
143
+ ax: matplotlib ax, contains U's, V's, and sum of U & V population.
142
144
  '''
143
145
 
144
146
  # store the average values in lists
@@ -160,26 +162,29 @@ def UV_dyna(sim, interval = 20, grid = True):
160
162
  #### plot ####
161
163
  xaxis = np.linspace(0, sim.maxtime, len(U_curve))
162
164
 
163
- fig, ax = plt.subplots()
165
+ if ax == None:
166
+ _, ax = plt.subplots()
164
167
  ax.grid(grid)
165
168
  ax.plot(xaxis, U_curve, CURVE_TYPE, label = 'U')
166
169
  ax.plot(xaxis, V_curve, CURVE_TYPE, label = 'V')
167
170
  ax.plot(xaxis, total_curve, CURVE_TYPE, label = 'total')
168
- ax.title.set_text('U & V over time')
171
+ ax.set_xlabel('Time')
172
+ ax.set_ylabel('Population')
173
+ ax.set_title('Population U & V Over Time')
169
174
  ax.legend()
170
175
 
171
- return fig
176
+ return ax
172
177
 
173
178
 
174
179
 
175
180
 
176
- def UV_hist(sim, U_color = 'purple', V_color = 'green', start = 0.95, end = 1.0):
181
+ def UV_hist(sim, ax_U = None, ax_V = None, U_color = 'purple', V_color = 'green', start = 0.95, end = 1.0):
177
182
  '''
178
183
  Makes density histograms for U, V's average distribution over an interval.
179
184
  Sometimes it may not be shown in density plots due to matplotlib features.
180
185
 
181
186
  Returns:
182
- fig1, fig2: Two Matplotlib histograms, for U and V, respectively.
187
+ ax_U, ax_V: matplotlib axes with heatmaps of U, V population density plotted upon.
183
188
  '''
184
189
 
185
190
  start_index = int(start * sim.max_record)
@@ -190,30 +195,32 @@ def UV_hist(sim, U_color = 'purple', V_color = 'green', start = 0.95, end = 1.0)
190
195
 
191
196
  #### plot ####
192
197
 
193
- fig1, ax1 = plt.subplots()
194
- ax1.set_xlabel('U')
195
- ax1.set_ylabel('density')
196
- ax1.hist(U_ave, color = U_color, density = True)
197
- ax1.title.set_text(figure_t.gen_title('U hist', start, end))
198
+ if ax_U == None:
199
+ _, ax_U = plt.subplots()
200
+ ax_U.set_xlabel('Population U')
201
+ ax_U.set_ylabel('Density')
202
+ ax_U.hist(U_ave, color = U_color, density = True)
203
+ ax_U.set_title(figure_t.gen_title('U Hist', start, end))
198
204
 
199
- fig2, ax2 = plt.subplots()
200
- ax2.set_xlabel('V')
201
- ax2.set_ylabel('density')
202
- ax2.hist(V_ave, color = V_color, density = True)
203
- ax2.title.set_text(figure_t.gen_title('V hist', start, end))
205
+ if ax_V == None:
206
+ _, ax_V = plt.subplots()
207
+ ax_V.set_xlabel('Population V')
208
+ ax_V.set_ylabel('Density')
209
+ ax_V.hist(V_ave, color = V_color, density = True)
210
+ ax_V.set_title(figure_t.gen_title('V Hist', start, end))
204
211
 
205
- return fig1, fig2
212
+ return ax_U, ax_V
206
213
 
207
214
 
208
215
 
209
216
 
210
- def UV_std(sim, interval = 20, grid = True):
217
+ def UV_std(sim, ax = None, interval = 20, grid = True):
211
218
  '''
212
219
  Plots how standard deviation of U, V change over time.
213
220
  Takes average over many small interval to smooth out local fluctuations.
214
221
 
215
222
  Returns:
216
- fig: A Matplotlib figure, contains U's and V's std curves.
223
+ ax: matplotlib ax, contains U's and V's std curves.
217
224
  '''
218
225
 
219
226
  interval = figure_t.scale_interval(interval, sim.compress_itv)
@@ -232,15 +239,17 @@ def UV_std(sim, interval = 20, grid = True):
232
239
  #### plot ####
233
240
  xaxis = np.linspace(0, sim.maxtime, len(U_std))
234
241
 
235
- fig, ax = plt.subplots()
242
+ if ax == None:
243
+ _, ax = plt.subplots()
236
244
  ax.grid(grid)
237
245
  ax.plot(xaxis, U_std, CURVE_TYPE, label = 'U std')
238
246
  ax.plot(xaxis, V_std, CURVE_TYPE, label = 'V std')
239
247
  ax.legend()
240
- ax.set_xlabel('time (records)', fontsize = 11)
241
- ax.title.set_text('std_dev over time')
242
-
243
- return fig
248
+ ax.set_xlabel('Time')
249
+ ax.set_ylabel('Std Dev')
250
+ ax.set_title('Population Std-Dev Dynamics')
251
+
252
+ return ax
244
253
 
245
254
 
246
255
 
@@ -270,7 +279,7 @@ def UV_expected_val(sim):
270
279
 
271
280
 
272
281
 
273
- def UV_expected(sim, U_color = 'Purples', V_color = 'Greens', annot = False, fmt = '.3g'):
282
+ def UV_expected(sim, ax_U = None, ax_V = None, U_color = 'Purples', V_color = 'Greens', annot = False, fmt = '.3g'):
274
283
  '''
275
284
  Calculate expected population distribution based on matrices, assuming no migration.
276
285
  For the formulas, see stochastic_mode.expected_UV
@@ -279,8 +288,8 @@ def UV_expected(sim, U_color = 'Purples', V_color = 'Greens', annot = False, fmt
279
288
  Note the colors are color maps.
280
289
 
281
290
  Returns:
282
- fig1, fig2: If 2D (N and M both > 1), then fig1 and fig2 are heatmaps.
283
- If 1D (N or M == 1), then fig1 and fig2 are barplots.
291
+ ax_U, ax_V: If 2D (N and M both > 1), then ax_U and ax_V are heatmaps.
292
+ If 1D (N or M == 1), then ax_U and ax_V are barplots.
284
293
  '''
285
294
 
286
295
  U_expected, V_expected = UV_expected_val(sim)
@@ -292,20 +301,20 @@ def UV_expected(sim, U_color = 'Purples', V_color = 'Greens', annot = False, fmt
292
301
 
293
302
  if (sim.N != 1) and (sim.M != 1):
294
303
  # 2D
295
- fig1 = figure_t.heatmap(U_expected, U_color, annot, fmt, title = 'Expected U', text = U_text)
296
- fig2 = figure_t.heatmap(V_expected, V_color, annot, fmt, title = 'Expected V', text = V_text)
304
+ ax_U = figure_t.heatmap(U_expected, ax_U, U_color, annot, fmt, title = 'Expected U', text = U_text)
305
+ ax_V = figure_t.heatmap(V_expected, ax_V, V_color, annot, fmt, title = 'Expected V', text = V_text)
297
306
 
298
307
  else:
299
308
  # 1D
300
- fig1 = figure_t.bar(U_expected.flatten(), color = U_color, xlabel = 'patches', ylabel = 'popu', title = 'Expected U', text = U_text)
301
- fig2 = figure_t.bar(V_expected.flatten(), color = V_color, xlabel = 'patches', ylabel = 'popu', title = 'Expected V', text = V_text)
309
+ ax_U = figure_t.bar(U_expected.flatten(), ax_U, color = U_color, xlabel = 'patches', ylabel = 'popu', title = 'Expected Population U', text = U_text)
310
+ ax_V = figure_t.bar(V_expected.flatten(), ax_V, color = V_color, xlabel = 'patches', ylabel = 'popu', title = 'Expected Population V', text = V_text)
302
311
 
303
- return fig1, fig2
312
+ return ax_U, ax_V
304
313
 
305
314
 
306
315
 
307
316
 
308
- def pi_heatmap(sim, U_color = 'BuPu', V_color = 'YlGn', start = 0.95, end = 1.0, annot = False, fmt = '.3g'):
317
+ def pi_heatmap(sim, ax_U = None, ax_V = None, U_color = 'BuPu', V_color = 'YlGn', start = 0.95, end = 1.0, annot = False, fmt = '.3g'):
309
318
  '''
310
319
  Make heatmaps for payoff in a specified interval.
311
320
  Works best for 2D. 1D works as well, but figures look bad.
@@ -314,7 +323,7 @@ def pi_heatmap(sim, U_color = 'BuPu', V_color = 'YlGn', start = 0.95, end = 1.0,
314
323
  Note the colors are matplotlib color maps.
315
324
 
316
325
  Returns:
317
- fig1, fig2: Seaborn heatmaps, for U's & V's payoff distribution, respectively.
326
+ ax_U, ax_V: Seaborn heatmaps, for U's & V's payoff distribution, respectively.
318
327
  '''
319
328
 
320
329
  start_index = int(sim.max_record * start)
@@ -323,26 +332,26 @@ def pi_heatmap(sim, U_color = 'BuPu', V_color = 'YlGn', start = 0.95, end = 1.0,
323
332
  U_pi_ave = figure_t.ave_interval(sim.U_pi, start_index, end_index)
324
333
  V_pi_ave = figure_t.ave_interval(sim.V_pi, start_index, end_index)
325
334
 
326
- U_title = figure_t.gen_title('U_pi', start, end)
335
+ U_title = figure_t.gen_title('Payoff ' + r'$p_U$', start, end)
327
336
  U_text = figure_t.gen_text(np.mean(U_pi_ave), np.std(U_pi_ave))
328
- V_title = figure_t.gen_title('V_pi', start, end)
337
+ V_title = figure_t.gen_title('Payoff ' + r'$p_V$', start, end)
329
338
  V_text = figure_t.gen_text(np.mean(V_pi_ave), np.std(V_pi_ave))
330
339
 
331
- fig1 = figure_t.heatmap(U_pi_ave, U_color, annot, fmt, U_title, U_text)
332
- fig2 = figure_t.heatmap(V_pi_ave, V_color, annot, fmt, V_title, V_text)
340
+ ax_U = figure_t.heatmap(U_pi_ave, ax_U, U_color, annot, fmt, U_title, U_text)
341
+ ax_V = figure_t.heatmap(V_pi_ave, ax_V, V_color, annot, fmt, V_title, V_text)
333
342
 
334
- return fig1, fig2
343
+ return ax_U, ax_V
335
344
 
336
345
 
337
346
 
338
347
 
339
- def pi_bar(sim, U_color = 'violet', V_color = 'yellowgreen', start = 0.95, end = 1.0):
348
+ def pi_bar(sim, ax_U = None, ax_V = None, U_color = 'violet', V_color = 'yellowgreen', start = 0.95, end = 1.0):
340
349
  '''
341
350
  Make barplot for payoff in a specified interval.
342
351
  Works best for 1D. 2D works as well, but figures look bad.
343
352
 
344
353
  Returns:
345
- fig1, fig2: Matplotlib barplots, for U's and V's payoff distribution, respectively.
354
+ ax_U, ax_V: matplotlib axes with barplots of U and V payoff distribution plotted upon.
346
355
  '''
347
356
 
348
357
  start_index = int(sim.max_record * start)
@@ -351,25 +360,25 @@ def pi_bar(sim, U_color = 'violet', V_color = 'yellowgreen', start = 0.95, end =
351
360
  U_pi_ave = figure_t.ave_interval_1D(sim.U_pi, start_index, end_index)
352
361
  V_pi_ave = figure_t.ave_interval_1D(sim.V_pi, start_index, end_index)
353
362
 
354
- U_title = figure_t.gen_title('U_pi', start, end)
363
+ U_title = figure_t.gen_title(r'$p_U$', start, end)
355
364
  U_text = figure_t.gen_text(np.mean(U_pi_ave), np.std(U_pi_ave))
356
- V_title = figure_t.gen_title('V_pi', start, end)
365
+ V_title = figure_t.gen_title(r'$p_V$', start, end)
357
366
  V_text = figure_t.gen_text(np.mean(V_pi_ave), np.std(V_pi_ave))
358
367
 
359
- fig1 = figure_t.bar(U_pi_ave, U_color, 'patches', 'pi', U_title, U_text)
360
- fig2 = figure_t.bar(V_pi_ave, V_color, 'patches', 'pi', V_title, V_text)
368
+ ax_U = figure_t.bar(U_pi_ave, ax_U, U_color, 'Patches', 'Payoff ' + r'$p_U$', U_title, U_text)
369
+ ax_V = figure_t.bar(V_pi_ave, ax_V, V_color, 'Patches', 'Payoff ' + r'$p_V$', V_title, V_text)
361
370
 
362
- return fig1, fig2
371
+ return ax_U, ax_V
363
372
 
364
373
 
365
374
 
366
375
 
367
- def pi_dyna(sim, interval = 20, grid = True):
376
+ def pi_dyna(sim, ax = None, interval = 20, grid = True):
368
377
  '''
369
378
  Plot how payoffs change over time.
370
379
 
371
380
  Returns:
372
- fig: Matplotlib figure of U's, V's, and U+V payoff, either total or not.
381
+ ax: matplotlib ax of U's, V's, and sum of U & V payoff.
373
382
  '''
374
383
 
375
384
  U_curve = []
@@ -390,27 +399,30 @@ def pi_dyna(sim, interval = 20, grid = True):
390
399
  #### plot ####
391
400
  xaxis = np.linspace(0, sim.maxtime, len(U_curve))
392
401
 
393
- fig, ax = plt.subplots()
402
+ if ax == None:
403
+ _, ax = plt.subplots()
394
404
  ax.grid(grid)
395
- ax.plot(xaxis, U_curve, CURVE_TYPE, label = 'U_pi')
396
- ax.plot(xaxis, V_curve, CURVE_TYPE, label = 'V_pi')
405
+ ax.plot(xaxis, U_curve, CURVE_TYPE, label = r'$p_U$')
406
+ ax.plot(xaxis, V_curve, CURVE_TYPE, label = r'$p_V$')
397
407
  ax.plot(xaxis, total_curve, CURVE_TYPE, label = 'total')
398
408
  ax.set_xlim(0, sim.maxtime)
399
- ax.title.set_text('U&V _pi over time')
409
+ ax.set_xlabel('Time')
410
+ ax.set_ylabel('Payoff')
411
+ ax.set_title('Payoff ' + r'$p_U$' + ' & ' + r'$p_V$' + ' over time')
400
412
  ax.legend()
401
413
 
402
- return fig
414
+ return ax
403
415
 
404
416
 
405
417
 
406
418
 
407
- def pi_hist(sim, U_color = 'violet', V_color = 'yellowgreen', start = 0.95, end = 1.0):
419
+ def pi_hist(sim, ax_U = None, ax_V = None, U_color = 'violet', V_color = 'yellowgreen', start = 0.95, end = 1.0):
408
420
  '''
409
421
  Makes deensity histograms of U's and V's payoffs in a sepcified interval.
410
422
  Sometimes it may not be shown in density plots due to matplotlib features.
411
423
 
412
424
  Returns:
413
- fig1, fig2: histogram of U's and V's payoff.
425
+ ax_U, ax_V: histogram of U's and V's payoff.
414
426
  '''
415
427
 
416
428
  start_index = int(start * sim.max_record)
@@ -421,29 +433,31 @@ def pi_hist(sim, U_color = 'violet', V_color = 'yellowgreen', start = 0.95, end
421
433
 
422
434
  #### plot ####
423
435
 
424
- fig1, ax1 = plt.subplots()
425
- ax1.set_xlabel('U_pi')
426
- ax1.set_ylabel('density')
427
- ax1.hist(U_pi_ave, color = U_color, density = True)
428
- ax1.title.set_text(figure_t.gen_title('U_pi hist', start, end))
436
+ if ax_U == None:
437
+ _, ax_U = plt.subplots()
438
+ ax_U.set_xlabel('Payoff ' + r'$p_U$')
439
+ ax_U.set_ylabel('Density')
440
+ ax_U.hist(U_pi_ave, color = U_color, density = True)
441
+ ax_U.set_title(figure_t.gen_title('Payoff ' + r'$p_U$' + ' Hist', start, end))
429
442
 
430
- fig2, ax2 = plt.subplots()
431
- ax2.set_xlabel('V_pi')
432
- ax2.set_ylabel('density')
433
- ax2.hist(V_pi_ave, color = V_color, density = True)
434
- ax2.title.set_text(figure_t.gen_title('V_pi hist', start, end))
443
+ if ax_V == None:
444
+ _, ax_V = plt.subplots()
445
+ ax_V.set_xlabel('Payoff ' + r'$p_V$')
446
+ ax_V.set_ylabel('Density')
447
+ ax_V.hist(V_pi_ave, color = V_color, density = True)
448
+ ax_V.set_title(figure_t.gen_title('Payoff ' + r'$p_V$' + ' Hist', start, end))
435
449
 
436
- return fig1, fig2
450
+ return ax_U, ax_V
437
451
 
438
452
 
439
453
 
440
454
 
441
- def pi_std(sim, interval = 20, grid = True):
455
+ def pi_std(sim, ax = None, interval = 20, grid = True):
442
456
  '''
443
457
  Plots how standard deviation of payoff change over time.
444
458
 
445
459
  Returns:
446
- fig: Matplotlib figure of the std of payoffs.
460
+ ax: matplotlib ax of the std of payoffs.
447
461
  '''
448
462
 
449
463
 
@@ -463,26 +477,28 @@ def pi_std(sim, interval = 20, grid = True):
463
477
  #### plot ####
464
478
  xaxis = np.linspace(0, sim.maxtime, len(U_pi_std))
465
479
 
466
- fig, ax = plt.subplots()
480
+ if ax == None:
481
+ _, ax = plt.subplots()
467
482
  ax.grid(grid)
468
- ax.plot(xaxis, U_pi_std, CURVE_TYPE, label = 'U_pi std')
469
- ax.plot(xaxis, V_pi_std, CURVE_TYPE, label = 'V_pi std')
483
+ ax.plot(xaxis, U_pi_std, CURVE_TYPE, label = r'$p_U$' + ' std')
484
+ ax.plot(xaxis, V_pi_std, CURVE_TYPE, label = r'$p_V$' + ' std')
470
485
  ax.legend()
471
- ax.set_xlabel('time (records)', fontsize = 11)
472
- ax.title.set_text('std over time')
486
+ ax.set_xlabel('Time')
487
+ ax.set_ylabel('Std Dev')
488
+ ax.set_title('Payoff Std-Dev Dynamics')
473
489
 
474
- return fig
490
+ return ax
475
491
 
476
492
 
477
493
 
478
494
 
479
- def UV_pi(sim, U_color = 'violet', V_color = 'yellowgreen', alpha = 0.25, start = 0.95, end = 1.0):
495
+ def UV_pi(sim, ax_U = None, ax_V = None, U_color = 'violet', V_color = 'yellowgreen', alpha = 0.4, start = 0.95, end = 1.0):
480
496
  '''
481
497
  Make two scatter plots: x-axes are population and y-axes are payoff in a specified time interval.
482
498
  Reveals relationship between population and payoff.
483
499
 
484
500
  Returns:
485
- fig1, fig2: U's and V's population-payoff scatter plots.
501
+ ax_U, ax_V: matplotlib axes with U and V population-payoff scatter plots.
486
502
  '''
487
503
 
488
504
  start_index = int(start * sim.max_record)
@@ -495,9 +511,9 @@ def UV_pi(sim, U_color = 'violet', V_color = 'yellowgreen', alpha = 0.25, start
495
511
  V_pi_ave = figure_t.ave_interval(sim.V_pi, start_index, end_index)
496
512
 
497
513
 
498
- fig1 = figure_t.scatter(U_ave, U_pi_ave, U_color, alpha, xlabel = 'U', ylabel = 'U_pi', title = 'U - U_pi')
499
- fig2 = figure_t.scatter(V_ave, V_pi_ave, V_color, alpha, xlabel = 'V', ylabel = 'V_pi', title = 'V - V_pi')
514
+ ax_U = figure_t.scatter(U_ave, U_pi_ave, ax_U, U_color, alpha, xlabel = 'U', ylabel = 'Payoff ' + r'$p_U$', title = 'U - ' + r'$p_U$')
515
+ ax_V = figure_t.scatter(V_ave, V_pi_ave, ax_V, V_color, alpha, xlabel = 'V', ylabel = 'Payoff ' + r'$p_V$', title = 'V - ' + r'$p_V$')
500
516
 
501
- return fig1, fig2
517
+ return ax_U, ax_V
502
518
 
503
519
 
piegy/model.py CHANGED
@@ -41,9 +41,6 @@ PI_DTYPE = 'float64'
41
41
  # data type for storing rates in single_test an single_init
42
42
  RATES_DTYPE = 'float64'
43
43
 
44
- # store e locally, slightly increases speed
45
- MATH_E = math.e
46
-
47
44
 
48
45
  class patch:
49
46
  '''
@@ -176,8 +173,8 @@ class patch:
176
173
 
177
174
  for i in range(4):
178
175
  if self.nb[i] != None:
179
- U_weight[i] = 1 + pow(MATH_E, self.w1 * self.nb[i].U_pi) # use your own functions!
180
- V_weight[i] = 1 + pow(MATH_E, self.w2 * self.nb[i].V_pi)
176
+ U_weight[i] = 1 + pow(math.e, self.w1 * self.nb[i].U_pi)
177
+ V_weight[i] = 1 + pow(math.e, self.w2 * self.nb[i].V_pi)
181
178
 
182
179
  mu1_U = self.mu1 * self.U
183
180
  mu2_V = self.mu2 * self.V
@@ -358,14 +355,11 @@ class simulation:
358
355
  if print_pct <= 0:
359
356
  raise ValueError('Please use an int > 0 for print_pct or None for not printing progress.')
360
357
 
361
- if type(seed) != int:
362
- raise TypeError('Please use an int as seed')
363
- if seed < 0:
364
- raise ValueError('Please use a non-negative int as seed.')
358
+ # seed is checked by number
365
359
 
366
360
 
367
361
  def check_valid_data(self, data_empty, max_record, compress_itv, U, V, U_pi, V_pi):
368
- # check whether a set of data is valid
362
+ # check whether a set of data is valid, used when reading a saved model
369
363
  if type(data_empty) != bool:
370
364
  raise TypeError('data_empty not a bool')
371
365
 
piegy/test_var.py CHANGED
@@ -48,6 +48,10 @@ DOTTED_CURVE_TYPE = 'o-'
48
48
  # map patch_var name to index in the patch class (in stochastic_model.py)
49
49
  PATCH_VAR_DICT = {'mu1': 0, 'mu2': 1, 'w1': 2, 'w2': 3, 'kappa1': 4, 'kappa2': 5}
50
50
 
51
+ # display name (in latex)
52
+ PATCH_VAR_DISP = {'mu1': r'$\mu_U$', 'mu2': r'$\mu_V$', 'w1': r'$w_U$', 'w2': r'$w_V$',
53
+ 'kappa1': r'$\kappa_U$', 'kappa2': r'$\kappa_V$'}
54
+
51
55
 
52
56
 
53
57
  def test_var1(sim, var, values, dirs, compress_itv = None, predict_runtime = False):
@@ -144,7 +148,7 @@ def test_var2(sim, var1, var2, values1, values2, dirs, compress_itv = None, pred
144
148
 
145
149
 
146
150
 
147
- def var_UV1(var, values, var_dirs, start = 0.95, end = 1.0, U_color = 'purple', V_color = 'green'):
151
+ def var_UV1(var, values, var_dirs, ax_U = None, ax_V = None, start = 0.95, end = 1.0, U_color = 'purple', V_color = 'green'):
148
152
  '''
149
153
  Plot function for test_var1, plot how var influences U, V population.
150
154
  Make U, V - var curve in two figures, with y-axis being total population at the end of simulations, x-axis being var's values.
@@ -153,12 +157,13 @@ def var_UV1(var, values, var_dirs, start = 0.95, end = 1.0, U_color = 'purple',
153
157
  - var: str, which variable was tested.
154
158
  - values: 1D list or np.array, which values were tested.
155
159
  - var_dirs: return value of test_var1, a 1D list of directories where all data are stored.
160
+ - ax_U, ax_V: matplotlib axes to plot on.
156
161
  - start, end: floats, give an interval of time over which to take average and make plot.
157
162
  For example, start = 0.95, end = 1.0 are to take average over the last 5% time of results;
158
163
  essentially plots how var influences equilibrium population.
159
164
 
160
165
  Returns:
161
- - fig1, fig2: two figures for U, V, respectively.
166
+ - ax_U, ax_V: axes for U, V, respectively.
162
167
  '''
163
168
 
164
169
  # average value of U, V over the interval. One entry for one value of var
@@ -181,25 +186,28 @@ def var_UV1(var, values, var_dirs, start = 0.95, end = 1.0, U_color = 'purple',
181
186
  V_ave.append(sum(figure_t.ave_interval_1D(simk.V, start_index, end_index)) / NM)
182
187
 
183
188
  #### plot ####
189
+ if ax_U == None:
190
+ _, ax_U = plt.subplots()
191
+ if ax_V == None:
192
+ _, ax_V = plt.subplots()
193
+ var_disp = PATCH_VAR_DISP[var]
184
194
 
185
- fig1, ax1 = plt.subplots()
186
- ax1.set_xlabel(var)
187
- ax1.set_ylabel('U')
188
- ax1.plot(values, U_ave, DOTTED_CURVE_TYPE, color = U_color)
189
- ax1.title.set_text(figure_t.gen_title(var + ' - U', start, end))
195
+ ax_U.set_xlabel(var_disp)
196
+ ax_U.set_ylabel(r'$U$')
197
+ ax_U.plot(values, U_ave, DOTTED_CURVE_TYPE, color = U_color)
198
+ ax_U.set_title(figure_t.gen_title(var_disp + r'$\,-\,U$', start, end))
190
199
 
191
- fig2, ax2 = plt.subplots()
192
- ax2.set_xlabel(var)
193
- ax2.set_ylabel('V')
194
- ax2.plot(values, V_ave, DOTTED_CURVE_TYPE, color = V_color)
195
- ax2.title.set_text(figure_t.gen_title(var + ' - V', start, end))
200
+ ax_V.set_xlabel(var_disp)
201
+ ax_V.set_ylabel(r'$V$')
202
+ ax_V.plot(values, V_ave, DOTTED_CURVE_TYPE, color = V_color)
203
+ ax_V.set_title(figure_t.gen_title(var_disp + r'$\,-\,V$', start, end))
196
204
 
197
- return fig1, fig2
205
+ return ax_U, ax_V
198
206
 
199
207
 
200
208
 
201
209
 
202
- def var_UV2(var1, var2, values1, values2, var_dirs, start = 0.95, end = 1.0, U_color = 'viridis', V_color = 'viridis', rgb_alpha = 1):
210
+ def var_UV2(var1, var2, values1, values2, var_dirs, ax_U = None, ax_V = None, var1_on_xaxis = True, start = 0.95, end = 1.0, U_color = 'viridis', V_color = 'viridis', rgb_alpha = 1):
203
211
  '''
204
212
  Plot function for test_var2, plot how two variables influence U, V population.
205
213
  Make U, V - var1, var2 curves. y-axis is population, x-axis is var2's values,
@@ -211,6 +219,8 @@ def var_UV2(var1, var2, values1, values2, var_dirs, start = 0.95, end = 1.0, U_c
211
219
  - values1: 1D list or np.array, values for var1.
212
220
  - values2: 1D list or np.array, values for var2.
213
221
  - var_dirs: return value of test_var2, a 2D list of directories where all data are stored.
222
+ - ax_U, ax_V: matplotlib axes to plot on.
223
+ - var1_on_xaxis: whether to put var1 on x-axis. Set to False if not.
214
224
  - start, end: floats, give an interval of time over which to take average and make plot.
215
225
  For example, start = 0.95, end = 1.0 plots the near-end population (equilibrium, if converged).
216
226
  - color: str, what colors to use for different value of var1. Uses Matplotlib color maps.
@@ -218,7 +228,7 @@ def var_UV2(var1, var2, values1, values2, var_dirs, start = 0.95, end = 1.0, U_c
218
228
  - rgb_alpha: the alpha value for color. Thr curves might have overlaps, recommend set a small alpha value if so.
219
229
 
220
230
  Returns:
221
- - fig1, fig2: figures for U, V, respectively.
231
+ - ax_U, ax_V: axes for U, V, respectively.
222
232
  '''
223
233
 
224
234
  # average value of U, V over the interval. One entry for one values of var1, var2
@@ -240,38 +250,59 @@ def var_UV2(var1, var2, values1, values2, var_dirs, start = 0.95, end = 1.0, U_c
240
250
 
241
251
  U_ave[k1].append(sum(figure_t.ave_interval_1D(simk.U, start_index, end_index)) / NM)
242
252
  V_ave[k1].append(sum(figure_t.ave_interval_1D(simk.V, start_index, end_index)) / NM)
243
-
244
- #### plot ####
253
+
254
+ U_ave = np.array(U_ave)
255
+ V_ave = np.array(V_ave)
245
256
 
246
- fig1, ax1 = plt.subplots()
247
- ax1.set_xlabel(var2)
248
- ax1.set_ylabel('U')
249
- cmap1 = plt.get_cmap(U_color)
257
+ #### plot ####
258
+ if ax_U == None:
259
+ _, ax_U = plt.subplots()
260
+ if ax_V == None:
261
+ _, ax_V = plt.subplots()
250
262
 
251
- for k1 in range(len(values1)):
252
- label = var1 + '=' + str(values1[k1])
253
- color_k1 = cmap1(k1 / len(values1))[:3] + (rgb_alpha,)
254
- ax1.plot(values2, U_ave[k1], DOTTED_CURVE_TYPE, label = label, color = color_k1)
255
- ax1.title.set_text(figure_t.gen_title(var1 + '&' + var2 + ' - U', start, end))
256
- ax1.legend(bbox_to_anchor = (1, 1))
263
+ var1_disp = PATCH_VAR_DISP[var1]
264
+ var2_disp = PATCH_VAR_DISP[var2]
257
265
 
258
- fig2, ax2 = plt.subplots()
259
- ax2.set_xlabel(var2)
260
- ax2.set_ylabel('V')
261
- cmap2 = plt.get_cmap(V_color)
262
266
 
263
- for k1 in range(len(values1)):
264
- label = var1 + '=' + str(values1[k1])
265
- color_k1 = cmap2(k1 / len(values1))[:3] + (rgb_alpha,)
266
- ax2.plot(values2, V_ave[k1], DOTTED_CURVE_TYPE, label = label, color = color_k1)
267
- ax2.title.set_text(figure_t.gen_title(var1 + '&' + var2 + ' - V', start, end))
268
- ax2.legend(bbox_to_anchor = (1.2, 1))
267
+ cmap_U = plt.get_cmap(U_color)
268
+ if var1_on_xaxis:
269
+ for k in range(len(values2)):
270
+ label = var2_disp + '=' + str(values2[k])
271
+ color_k = cmap_U(k / len(values2))[:3] + (rgb_alpha,)
272
+ ax_U.plot(values1, U_ave[:, k], DOTTED_CURVE_TYPE, label = label, color = color_k)
273
+ ax_U.set_xlabel(var1_disp)
274
+ else:
275
+ for k in range(len(values1)):
276
+ label = var1_disp + '=' + str(values1[k])
277
+ color_k = cmap_U(k / len(values1))[:3] + (rgb_alpha,)
278
+ ax_U.plot(values2, U_ave[k], DOTTED_CURVE_TYPE, label = label, color = color_k)
279
+ ax_U.set_xlabel(var2_disp)
280
+ ax_U.set_ylabel(r'$U$')
281
+ ax_U.set_title(figure_t.gen_title(var1_disp + ',' + var2_disp + r'$\,-\,U$', start, end))
282
+ ax_U.legend()
269
283
 
270
- return fig1, fig2
284
+ cmap_V = plt.get_cmap(V_color)
285
+ if var1_on_xaxis:
286
+ for k in range(len(values2)):
287
+ label = var2_disp + '=' + str(values2[k])
288
+ color_k = cmap_V(k / len(values2))[:3] + (rgb_alpha,)
289
+ ax_V.plot(values1, V_ave[:, k], DOTTED_CURVE_TYPE, label = label, color = color_k)
290
+ ax_V.set_xlabel(var1_disp)
291
+ else:
292
+ for k in range(len(values1)):
293
+ label = var1_disp + '=' + str(values1[k])
294
+ color_k = cmap_V(k / len(values1))[:3] + (rgb_alpha,)
295
+ ax_V.plot(values2, V_ave[k], DOTTED_CURVE_TYPE, label = label, color = color_k)
296
+ ax_V.set_xlabel(var2_disp)
297
+ ax_V.set_ylabel(r'$V$')
298
+ ax_V.set_title(figure_t.gen_title(var1_disp + ',' + var2_disp + r'$\,-\,V$', start, end))
299
+ ax_V.legend()
300
+
301
+ return ax_U, ax_V
271
302
 
272
303
 
273
304
 
274
- def var_pi1(var, values, var_dirs, start = 0.95, end = 1.0, U_color = 'violet', V_color = 'yellowgreen'):
305
+ def var_pi1(var, values, var_dirs, ax_U = None, ax_V = None, start = 0.95, end = 1.0, U_color = 'violet', V_color = 'yellowgreen'):
275
306
  '''
276
307
  Plot function for test_var1. Plot influence of var on U, V's payoff.
277
308
  Make U_pi, V_pi - var curves. y-axis is payoff, x-axis is values of var.
@@ -280,10 +311,11 @@ def var_pi1(var, values, var_dirs, start = 0.95, end = 1.0, U_color = 'violet',
280
311
  - var_dirs: return value of test_var1. A 1D list of directories where all data are stored.
281
312
  - var: str, which variable as tested.
282
313
  - values: 1D list or np.array, what values were used.
314
+ - ax_U, ax_V: matplotlib axes to plot on.
283
315
  - start, end: floats, define an interval of time over which to calculate average payoff and make plots.
284
316
 
285
317
  Returns:
286
- - fig1, fig2: figures for U, V's payoff, respectively.
318
+ - ax_U, ax_V: axes for U, V, respectively.
287
319
  '''
288
320
 
289
321
  # take average value of payoff over an interval of time
@@ -308,24 +340,28 @@ def var_pi1(var, values, var_dirs, start = 0.95, end = 1.0, U_color = 'violet',
308
340
  del simk
309
341
 
310
342
  #### plot ####
343
+ if ax_U == None:
344
+ _, ax_U = plt.subplots()
345
+ if ax_V == None:
346
+ _, ax_V = plt.subplots()
347
+ var_disp = PATCH_VAR_DISP[var]
311
348
 
312
- fig1, ax1 = plt.subplots()
313
- ax1.set_xlabel(var)
314
- ax1.set_ylabel('U_pi')
315
- ax1.plot(values, U_ave, DOTTED_CURVE_TYPE, color = U_color)
316
- ax1.title.set_text(figure_t.gen_title(var + ' - U_pi', start, end))
349
+ ax_U.set_xlabel(var_disp)
350
+ ax_U.set_ylabel(r'$\pi_U$')
351
+ ax_U.plot(values, U_ave, DOTTED_CURVE_TYPE, color = U_color)
352
+ ax_U.set_title(figure_t.gen_title(var_disp + r'$\,-\,\pi_U$', start, end))
317
353
 
318
- fig2, ax2 = plt.subplots()
319
- ax2.set_xlabel(var)
320
- ax2.set_ylabel('V_pi')
321
- ax2.plot(values, V_ave, DOTTED_CURVE_TYPE, color = V_color)
322
- ax2.title.set_text(figure_t.gen_title(var + ' - V_pi', start, end))
354
+ ax_V.set_xlabel(var_disp)
355
+ ax_V.set_ylabel(r'$\pi_V$')
356
+ ax_V.plot(values, V_ave, DOTTED_CURVE_TYPE, color = V_color)
357
+ ax_V.set_title(figure_t.gen_title(var_disp + r'$\,-\,\pi_V$', start, end))
358
+
359
+ return ax_U, ax_V
323
360
 
324
- return fig1, fig2
325
361
 
326
362
 
327
363
 
328
- def var_pi2(var1, var2, values1, values2, var_dirs, start = 0.95, end = 1.0, U_color = 'viridis', V_color = 'viridis', rgb_alpha = 1):
364
+ def var_pi2(var1, var2, values1, values2, var_dirs, ax_U = None, ax_V = None, var1_on_xaxis = True, start = 0.95, end = 1.0, U_color = 'viridis', V_color = 'viridis', rgb_alpha = 1):
329
365
  '''
330
366
  Plot function for test_var2. Plot how var1 and var2 influence payoff.
331
367
  Make U_pi, V_pi - var2 curves. y-axis is payoff, x-axis is values of var2,
@@ -335,12 +371,14 @@ def var_pi2(var1, var2, values1, values2, var_dirs, start = 0.95, end = 1.0, U_c
335
371
  - var_dirs: return value of test_var2. A 2D list of directories where all data are stored.
336
372
  - var1, var2: str, what variables were tested.
337
373
  - values1, values2: 1D lists or np.array, what values were tested.
374
+ - ax_U, ax_V: matplotlib axes to plot on.
375
+ - var1_on_xaxis: whether to put var1 on x-axis. Set to False if not.
338
376
  - start, end: floats, define a time inteval over which to make average and make plots.
339
377
  - color: str, Matplotlib color maps.
340
378
  - rgb_alpha: set alpha value for curves.
341
379
 
342
380
  Returns:
343
- - fig1, fig2: U, V's payoff figures, respectively.
381
+ - ax_U, ax_V: U, V's payoff figures, respectively.
344
382
  '''
345
383
 
346
384
  # take average value of payoff over an interval of time
@@ -364,34 +402,54 @@ def var_pi2(var1, var2, values1, values2, var_dirs, start = 0.95, end = 1.0, U_c
364
402
  V_ave[k1].append(np.sum(figure_t.ave_interval(simk.V_pi, start_index, end_index)) / NM)
365
403
 
366
404
  del simk # manually delete this large object
367
-
368
- #### plot ####
369
-
370
- fig1, ax1 = plt.subplots()
371
- ax1.set_xlabel(var2)
372
- ax1.set_ylabel('U_pi')
373
- cmap1 = plt.get_cmap(U_color)
374
405
 
375
- for k1 in range(len(var_dirs)):
376
- label = var1 + '=' + str(values1[k1])
377
- color_k1 = cmap1(k1 / len(values1))[:3] + (rgb_alpha,)
378
- ax1.plot(values2, U_ave[k1], DOTTED_CURVE_TYPE, label = label, color = color_k1)
379
- ax1.title.set_text(figure_t.gen_title(var1 + '&' + var2 + ' - U_pi', start, end))
380
- ax1.legend(bbox_to_anchor = (1, 1))
406
+ U_ave = np.array(U_ave)
407
+ V_ave = np.array(V_ave)
381
408
 
382
- fig2, ax2 = plt.subplots()
383
- ax2.set_xlabel(var2)
384
- ax1.set_ylabel('V_pi')
385
- cmap2 = plt.get_cmap(V_color)
409
+ #### plot ####
410
+ if ax_U == None:
411
+ _, ax_U = plt.subplots()
412
+ if ax_V == None:
413
+ _, ax_V = plt.subplots()
386
414
 
387
- for k1 in range(len(var_dirs)):
388
- label = var1 + '=' + str(values1[k1])
389
- color_k1 = cmap2(k1 / len(values1))[:3] + (rgb_alpha,)
390
- ax2.plot(values2, V_ave[k1], DOTTED_CURVE_TYPE, label = label, color = color_k1)
391
- ax2.title.set_text(figure_t.gen_title(var1 + '&' + var2 + ' - V_pi', start, end))
392
- ax2.legend(bbox_to_anchor = (1.2, 1))
415
+ var1_disp = PATCH_VAR_DISP[var1]
416
+ var2_disp = PATCH_VAR_DISP[var2]
417
+
418
+ cmap_U = plt.get_cmap(U_color)
419
+ if var1_on_xaxis:
420
+ for k in range(len(values2)):
421
+ label = var2_disp + '=' + str(values2[k])
422
+ color_k = cmap_U(k / len(values2))[:3] + (rgb_alpha,)
423
+ ax_U.plot(values1, U_ave[:, k], DOTTED_CURVE_TYPE, label = label, color = color_k)
424
+ ax_U.set_xlabel(var1_disp)
425
+ else:
426
+ for k in range(len(values1)):
427
+ label = var1_disp + '=' + str(values1[k])
428
+ color_k = cmap_U(k / len(values1))[:3] + (rgb_alpha,)
429
+ ax_U.plot(values2, U_ave[k], DOTTED_CURVE_TYPE, label = label, color = color_k)
430
+ ax_U.set_xlabel(var2_disp)
431
+ ax_U.set_ylabel(r'$\pi_{V}$')
432
+ ax_U.set_title(figure_t.gen_title(var1_disp + ',' + var2_disp + r'$\,-\,\pi_U$', start, end))
433
+ ax_U.legend()
434
+
435
+ cmap_V = plt.get_cmap(V_color)
436
+ if var1_on_xaxis:
437
+ for k in range(len(values2)):
438
+ label = var2_disp + '=' + str(values2[k])
439
+ color_k = cmap_V(k / len(values2))[:3] + (rgb_alpha,)
440
+ ax_V.plot(values1, V_ave[:, k], DOTTED_CURVE_TYPE, label = label, color = color_k)
441
+ ax_V.set_xlabel(var1_disp)
442
+ else:
443
+ for k in range(len(values1)):
444
+ label = var1_disp + '=' + str(values1[k])
445
+ color_k = cmap_V(k / len(values1))[:3] + (rgb_alpha,)
446
+ ax_V.plot(values2, V_ave[k], DOTTED_CURVE_TYPE, label = label, color = color_k)
447
+ ax_V.set_xlabel(var2_disp)
448
+ ax_V.set_ylabel(r'$\pi_{U}$')
449
+ ax_V.set_title(figure_t.gen_title(var1_disp + ',' + var2_disp + r'$\,-\,\pi_V$', start, end))
450
+ ax_V.legend()
393
451
 
394
- return fig1, fig2
452
+ return ax_U, ax_V
395
453
 
396
454
 
397
455
 
@@ -10,6 +10,7 @@ Functions:
10
10
  - scale_interval: scale interval if sim's data was already reduced.
11
11
  - ave_interval: Calculates average value of data over a time interval.
12
12
  - ave_interval_1D: Return in a 1D format.
13
+ - config_mpl: Configure Matplotlib parameters in a nice format
13
14
  '''
14
15
 
15
16
 
@@ -21,12 +22,13 @@ import seaborn as sns
21
22
  # default value is [0.125, 0.11, 0.9, 0.88]
22
23
 
23
24
 
24
- def heatmap(data, cmap = "Greens", annot = False, fmt = '.3g', title = None, text = None):
25
+ def heatmap(data, ax = None, cmap = "Greens", annot = False, fmt = '.3g', title = None, text = None):
25
26
  '''
26
27
  Helper function for making heatmaps.
27
28
 
28
29
  Inputs:
29
30
  data: 1D data for which you want to make a heatmap.
31
+ ax: matplotlib ax to plot on.
30
32
  cmap: Color of heatmap. Uses matplotlib color maps
31
33
  annot: Whether to show numbers of every block.
32
34
  fmt: Number format for annotations. How many digits you want to keep.
@@ -37,23 +39,26 @@ def heatmap(data, cmap = "Greens", annot = False, fmt = '.3g', title = None, tex
37
39
  fig: Seaborn heatmap.
38
40
  '''
39
41
 
40
- fig, ax = plt.subplots()
42
+ if ax == None:
43
+ _, ax = plt.subplots()
44
+
41
45
  if text != None:
42
- ax.text(0.63, 0.9, text, size = 10, linespacing = 1.5, transform = plt.gcf().transFigure)
46
+ ax.text(0.66, 0.9, text, size = 10, linespacing = 1.5, transform = plt.gcf().transFigure)
43
47
 
44
- ax = sns.heatmap(data, cmap = cmap, annot = annot, fmt = fmt)
45
- ax.title.set_text(title)
48
+ ax = sns.heatmap(data, ax = ax, cmap = cmap, annot = annot, fmt = fmt)
49
+ ax.set_title(title)
46
50
 
47
- return fig
51
+ return ax
48
52
 
49
53
 
50
54
 
51
- def bar(data, color = "green", xlabel = None, ylabel = None, title = None, text = None):
55
+ def bar(data, ax = None, color = "green", xlabel = None, ylabel = None, title = None, text = None):
52
56
  '''
53
57
  Helper Function for making barplots.
54
58
 
55
59
  Inputs:
56
60
  data: 2D data to make barplot.
61
+ ax: matplotlib ax to plot on.
57
62
  color: Uses Matplotlib colors.
58
63
  xlabel, y_label:
59
64
  Label for axes.
@@ -67,44 +72,48 @@ def bar(data, color = "green", xlabel = None, ylabel = None, title = None, text
67
72
  N = np.array(data).size
68
73
  xaxis = np.array([i for i in range(N)])
69
74
 
70
- # make figure larger if has more data points
71
- fig, ax = plt.subplots()
72
- if N > 60:
73
- fig.set_size_inches(min(N * 0.12, 9.6), 4.8)
75
+ if ax == None:
76
+ if N > 60:
77
+ # make figure larger if has more data points
78
+ _, ax = plt.subplots(figsize = (min(N * 0.107, 6.4), 4.8))
79
+ else:
80
+ _, ax = plt.subplots()
74
81
 
75
82
  if text != None:
76
- ax.text(0.63, 0.9, text, size = 10, linespacing = 1.5, transform = plt.gcf().transFigure)
83
+ ax.text(0.66, 0.9, text, size = 10, linespacing = 1.5, transform = plt.gcf().transFigure)
77
84
 
78
85
  ax.bar(x = xaxis, height = data, color = color)
79
86
  ax.set_xlabel(xlabel)
80
87
  ax.set_ylabel(ylabel)
81
- ax.title.set_text(title)
88
+ ax.set_title(title)
82
89
 
83
- return fig
90
+ return ax
84
91
 
85
92
 
86
93
 
87
- def scatter(X, Y, color = "orange", alpha = 0.25, xlabel = "x", ylabel = "y", title = None):
94
+ def scatter(X, Y, ax = None, color = "orange", alpha = 0.25, xlabel = "x", ylabel = "y", title = None):
88
95
  '''
89
96
  Helper function for makeing scatter plots.
90
97
 
91
98
  Inputs:
92
99
  X: x-coordinates of points.
93
100
  Y: y-coordinates of points.
101
+ ax: matplotlib ax to plot on.
94
102
  Note color is Matplotlib colors.
95
103
 
96
104
  Returns:
97
105
  fig: A Matplotlib scatter plot.
98
106
  '''
99
107
 
100
- fig, ax = plt.subplots()
108
+ if ax == None:
109
+ _, ax = plt.subplots(figsize = (7.2, 5.4))
101
110
  ax.scatter(X, Y, color = color, alpha = alpha)
102
111
 
103
112
  ax.set_xlabel(xlabel)
104
113
  ax.set_ylabel(ylabel)
105
- ax.title.set_text(title)
114
+ ax.set_title(title)
106
115
 
107
- return fig
116
+ return ax
108
117
 
109
118
 
110
119
 
@@ -121,7 +130,7 @@ def gen_text(ave, std):
121
130
  '''
122
131
  Generate text about standard deviation info.
123
132
  '''
124
- text = "ave: " + str(round(ave, 3)) + ", std: " + str(round(std, 3))
133
+ text = "ave=" + str(round(ave, 2)) + ", std=" + str(round(std, 2))
125
134
  return text
126
135
 
127
136
 
@@ -204,3 +213,26 @@ def scale_interval(interval, compress_itv):
204
213
  return interval
205
214
 
206
215
 
216
+
217
+ def config_mpl(mpl):
218
+ '''
219
+ Configure Matplotlib figures
220
+ '''
221
+ mpl.rcParams['savefig.dpi'] = 300
222
+
223
+ mpl.rcParams['font.family'] = 'serif'
224
+ mpl.rcParams['font.serif'] = plt.rcParams['font.serif']
225
+ mpl.rcParams['lines.linewidth'] = 1.75
226
+ mpl.rcParams['font.size'] = 11
227
+ mpl.rcParams['axes.labelsize'] = 12
228
+ mpl.rcParams['xtick.major.size'] = 10
229
+ mpl.rcParams['ytick.major.size'] = 9
230
+ mpl.rcParams['xtick.minor.size'] = 4
231
+ mpl.rcParams['ytick.minor.size'] = 4
232
+
233
+ mpl.rcParams['xtick.major.width'] = 1.5
234
+ mpl.rcParams['ytick.major.width'] = 1.5
235
+ mpl.rcParams['xtick.minor.width'] = 1.5
236
+ mpl.rcParams['ytick.minor.width'] = 1.5
237
+
238
+
piegy/videos.py CHANGED
@@ -11,22 +11,21 @@ Private Functions
11
11
  - get_max_lim: Get the max lim (interval) over many lims, and then expand it a bit for better accommodation.
12
12
  Essentially takes union of those intervals.
13
13
  - video_lim: Find a large enough xlim and ylim for video.
14
- - sort_frames: Put frames in order.
15
- other not documented here.
14
+ - make_mp4: Put frames together into a mp4.
15
+ others not documented here.
16
16
 
17
17
  '''
18
18
 
19
19
 
20
20
  from . import figures
21
21
  from .tools import file_tools as file_t
22
+ from .tools import figure_tools as figure_t
22
23
 
23
-
24
+ import matplotlib as mpl
24
25
  import matplotlib.pyplot as plt
25
26
  import numpy as np
26
27
  import os
27
- import imageio.v2 as imageio
28
- import re
29
- from moviepy import VideoFileClip
28
+ from moviepy import ImageSequenceClip
30
29
 
31
30
 
32
31
  # a list of supported figures
@@ -163,15 +162,15 @@ def frame_heatmap_lim(sim, func, frames):
163
162
  V_list = []
164
163
 
165
164
  for i in range(10):
166
- U_fig, V_fig = func(sim, start = i / 10, end = (i / 10 + 1 / frames))
165
+ fig_U, ax_U = plt.subplots()
166
+ fig_V, ax_V = plt.subplots()
167
+ ax_U, ax_V = func(sim, ax_U = ax_U, ax_V = ax_V, start = i / 10, end = (i / 10 + 1 / frames))
167
168
 
168
- U_ax = U_fig.get_axes()[0]
169
- U_list.append(U_ax.collections[0].get_clim())
170
- V_ax = V_fig.get_axes()[0]
171
- V_list.append(V_ax.collections[0].get_clim())
169
+ U_list.append(ax_U.collections[0].get_clim())
170
+ V_list.append(ax_V.collections[0].get_clim())
172
171
 
173
- plt.close(U_fig)
174
- plt.close(V_fig)
172
+ plt.close(fig_U)
173
+ plt.close(fig_V)
175
174
 
176
175
  U_clim = get_max_lim(U_list)
177
176
  V_clim = get_max_lim(V_list)
@@ -180,49 +179,29 @@ def frame_heatmap_lim(sim, func, frames):
180
179
 
181
180
 
182
181
 
183
- def sort_frames(images):
184
- '''
185
- Put frames in order.
186
-
187
- Inputs:
188
- images: A list of dirs (frame names)
189
- '''
190
- numeric_part, non_numeric_part = re.match(r'(\d+) (\D+)', images).groups()
191
- return (int(numeric_part), non_numeric_part)
192
-
193
-
194
182
 
195
- def make_mp4(dirs, frame_dirs, duration, video_name):
183
+ def make_mp4(video_dir, frame_dir, fps):
196
184
  '''
197
- Convert frames into a mp4 video.
198
-
185
+ Read .png from the frames folder and make into a mp4
199
186
  Inputs:
200
- dirs: where to store the video.
201
- frame_dirs: where to find frames.
202
- duration: how long the video should be.
203
- video_name: name of the video.
187
+ video_dir: where to save the video
188
+ frame_dirs: where to read frames from
189
+ fps: frames per second
204
190
  '''
205
191
 
206
- # png to gif
207
- images = [img for img in os.listdir(frame_dirs) if img.endswith('.png')]
208
- images.sort(key = sort_frames)
192
+ frame_paths_incomplete = os.listdir(frame_dir)
193
+ frame_paths_incomplete.sort(key=lambda f: int(''.join(filter(str.isdigit, f))))
194
+ frame_paths = []
195
+ for path in frame_paths_incomplete:
196
+ if (path[-4:] == '.png') and ('frame' in path):
197
+ frame_paths.append(frame_dir + '/' + path)
198
+ clip = ImageSequenceClip(frame_paths, fps = fps)
199
+ clip.write_videofile(video_dir, logger = None)
209
200
 
210
- image_list = []
211
- for img in images:
212
- img_path = os.path.join(frame_dirs, img)
213
- image_list.append(imageio.imread(img_path))
214
- gif_dirs = dirs + '/temp.gif'
215
- imageio.mimsave(gif_dirs, image_list, format = 'gif', duration = duration)
216
-
217
- # gif to mp4
218
- clip = VideoFileClip(gif_dirs)
219
- clip.write_videofile(video_name, logger = None)
220
- # delete gif
221
- os.remove(gif_dirs)
222
201
 
223
202
 
224
203
 
225
- def make_video(sim, func_name = 'UV_heatmap', frames = 100, speed = 1.25, dpi = 120, U_color = 'Greens', V_color = 'Purples', annot = False, fmt = '.3g', del_frames = False, dirs = 'videos'):
204
+ def make_video(sim, func_name = 'UV_heatmap', frames = 100, fps = 30, U_color = 'Greens', V_color = 'Purples', annot = False, fmt = '.3g', del_frames = False, dirs = 'videos'):
226
205
  '''
227
206
  Make a mp4 video based on simulation results.
228
207
 
@@ -230,8 +209,7 @@ def make_video(sim, func_name = 'UV_heatmap', frames = 100, speed = 1.25, dpi =
230
209
  - sim: a stochastic_model.simulation object, the simulation results.
231
210
  - func_name: what function to use to make the frames. Should be one of the functions in figures.py
232
211
  - frames: how many frames to make. Use more frames for more smooth evolutions.
233
- - speed: how long every frame should last. Use larger number for slower video.
234
- - dpi: dpi of frames
212
+ - fps: frames per second.
235
213
  - U_color: color for U's videos. Color maps or regular colors, based on what function you use.
236
214
  - V_color: color for V's videos.
237
215
  - annot: used by heatmaps. Whether to show numbers.
@@ -268,7 +246,6 @@ def make_video(sim, func_name = 'UV_heatmap', frames = 100, speed = 1.25, dpi =
268
246
  if os.path.exists(V_frame_dirs):
269
247
  file_t.del_dirs(V_frame_dirs)
270
248
  os.makedirs(V_frame_dirs)
271
-
272
249
 
273
250
  #### for loop ####
274
251
 
@@ -277,30 +254,31 @@ def make_video(sim, func_name = 'UV_heatmap', frames = 100, speed = 1.25, dpi =
277
254
  print('making frames', round(i / frames * 100), '%', end = '\r')
278
255
  current_progress += one_progress
279
256
 
257
+ fig_U, ax_U = plt.subplots(figsize = (6.4, 4.8))#, constrained_layout = True)
258
+ fig_V, ax_V = plt.subplots(figsize = (6.4, 4.8))#, constrained_layout = True)
259
+
280
260
  if 'heatmap' in func_name:
281
- U_fig, V_fig = func(sim, U_color, V_color, start = i / frames, end = (i + 1) / frames, annot = annot, fmt = fmt)
261
+ ax_U, ax_V = func(sim, ax_U = ax_U, ax_V = ax_V, U_color = U_color, V_color = V_color, start = i / frames, end = (i + 1) / frames, annot = annot, fmt = fmt)
282
262
  else:
283
- U_fig, V_fig = func(sim, U_color, V_color, start = i / frames, end = (i + 1) / frames)
284
- U_ax = U_fig.get_axes()[0]
285
- V_ax = V_fig.get_axes()[0]
263
+ ax_U, ax_V = func(sim, ax_U = ax_U, ax_V = ax_V, U_color = U_color, V_color = V_color, start = i / frames, end = (i + 1) / frames)
286
264
 
287
265
  if 'heatmap' in func_name:
288
- U_ax.collections[0].set_clim(U_clim)
289
- V_ax.collections[0].set_clim(V_clim)
266
+ ax_U.collections[0].set_clim(U_clim)
267
+ ax_V.collections[0].set_clim(V_clim)
290
268
  else:
291
269
  # make sure y axis not changing if not heatmap and not UV_pi
292
- U_ax.set_ylim(U_ylim)
293
- V_ax.set_ylim(V_ylim)
270
+ ax_U.set_ylim(U_ylim)
271
+ ax_V.set_ylim(V_ylim)
294
272
  if ('hist' in func_name) or (func_name == 'UV_pi'):
295
273
  # need to set xlim as well for UV_pi and histograms
296
- U_ax.set_xlim(U_xlim)
297
- V_ax.set_xlim(V_xlim)
274
+ ax_V.set_xlim(U_xlim)
275
+ ax_V.set_xlim(V_xlim)
298
276
 
299
- U_fig.savefig(U_frame_dirs + '/' + str(i) + ' U' + '.png', dpi = dpi)
300
- V_fig.savefig(V_frame_dirs + '/' + str(i) + ' V' + '.png', dpi = dpi)
277
+ fig_U.savefig(U_frame_dirs + '/' + 'U_frame_' + str(i) + '.png', pad_inches = 0.25)
278
+ fig_V.savefig(V_frame_dirs + '/' + 'V_frame_' + str(i) + '.png', pad_inches = 0.25)
301
279
 
302
- plt.close(U_fig)
303
- plt.close(V_fig)
280
+ plt.close(fig_U)
281
+ plt.close(fig_V)
304
282
 
305
283
  #### for loop ends ####
306
284
 
@@ -308,8 +286,8 @@ def make_video(sim, func_name = 'UV_heatmap', frames = 100, speed = 1.25, dpi =
308
286
  print('making mp4... ', end = '\r')
309
287
 
310
288
  # make videos based on frames
311
- make_mp4(dirs, U_frame_dirs, frames * speed, dirs + '/U-' + func_name + '.mp4')
312
- make_mp4(dirs, V_frame_dirs, frames * speed, dirs + '/V-' + func_name + '.mp4')
289
+ make_mp4(dirs + '/U-' + func_name + '.mp4', U_frame_dirs, fps)
290
+ make_mp4(dirs + '/V-' + func_name + '.mp4', V_frame_dirs, fps)
313
291
 
314
292
  if del_frames:
315
293
  file_t.del_dirs(U_frame_dirs)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: piegy
3
- Version: 1.0.0
3
+ Version: 1.1.1
4
4
  Summary: Payoff-Driven Stochastic Spatial Model for Evolutionary Game Theory
5
5
  Author-email: Chenning Xu <cxu7@caltech.edu>
6
6
  License: BSD 3-Clause License
@@ -49,7 +49,6 @@ Description-Content-Type: text/markdown
49
49
  License-File: LICENSE.txt
50
50
  Requires-Dist: numpy
51
51
  Requires-Dist: matplotlib
52
- Requires-Dist: imageio>=2.37.0
53
52
  Requires-Dist: moviepy>=2.1.1
54
53
  Requires-Dist: seaborn>=0.13.2
55
54
  Dynamic: license-file
@@ -62,20 +61,22 @@ Provides a stochastic spatial model for simulating the interaction and evolution
62
61
 
63
62
  ## Installation
64
63
 
64
+ To install *piegy*, run the following in terminal:
65
+
65
66
  ```bash
66
67
  pip install piegy
67
68
  ```
68
69
 
69
70
  ## Documentation and Source
70
71
 
71
- See source code at: [GitHub-piegy repo](https://github.com/Chenning04/piegy.git).
72
- The *piegy* documentation at: [piegy docs](https://piegy.readthedocs.io/en/).
72
+ See source code at: [piegy GitHub repository](https://github.com/Chenning04/piegy.git).
73
+ The *piegy* documentation at: [piegy Documentation](https://piegy.readthedocs.io/en/).
73
74
 
74
75
  ## How the Model Works
75
76
 
76
- Our model can be summarized as "classical game theory endowed with a spatial structure and payoff-driven migration rules". Consider two species, predators and preys (denote by *U* and *V*), in a rectangular region. We divide the region into N by M patches and simulate their interaction within a patch by classical game theory (i.e., payoff matrices and carrying capacity). Interactions across patches are simulated by payoff-driven migration rules. An individual migrates to a neighboring patch with probability weighted by payoff in the neighbors.
77
+ Our model can be summarized as "classical evolutionary game theory endowed with spatial structure and payoff-driven migration rules". Consider two species, predators and preys (denoted by *U* and *V*), in a rectangular region. We divide the region into N by M patches and simulate their interaction within a patch by classical game theory (i.e., payoff matrices and carrying capacity). Interactions across patches are simulated by payoff-driven migration rules. An individual migrates to a neighboring patch with probability weighted by payoff in the neighbors.
77
78
 
78
- We use the Gillepie algorithm as the fundamental event-selection algorithm. At each time step, one event is selected and let happen; and step sizes are continuous, dependent on the current state in the space. Data are recorded every some specified time interval.
79
+ We use the Gillepie algorithm as the fundamental event-selection algorithm. At each time step, one event is selected and let happen; and the step size is continuous, dependent on the current state in the space. Data are recorded every some specified time interval.
79
80
 
80
81
  ## Analytic Tools
81
82
 
@@ -95,10 +96,11 @@ dynamics = figures.UV_dyna(sim)
95
96
  U_hmap, V_hmap = figures.UV_heatmap(sim)
96
97
  ```
97
98
 
98
- The figures reveal the population dynamics and steady state distribution.
99
+ The figures reveal the population dynamics and steady state population distribution.
99
100
 
100
101
 
101
102
  ## Acknowledgments
102
103
 
103
104
  - Thanks Professor Daniel Cooney at University of Illinois Urbana-Champaign. This package is developed alongside a project with Prof. Cooney and received enormous help from him.
104
105
  - Special thanks to the open-source community for making this package possible.
106
+
@@ -0,0 +1,16 @@
1
+ piegy/__init__.py,sha256=Lrh6NegSvo6LOCXg_tBTu804eicnHpQY2zmE0FchjKE,3241
2
+ piegy/__version__.py,sha256=8IfclnXlmVE5p-odcoFI_9v7RIOmz2Cxd8Dvx1dMjNc,526
3
+ piegy/analysis.py,sha256=1cF06igQMGJGVjLiyhtgepGk8fYhzvL0orI48tOK1qY,8713
4
+ piegy/data_tools.py,sha256=lNFOX4H0o_WfRSNQoC9QGCK66-IdrZ0zCnz12N-Ael4,3599
5
+ piegy/figures.py,sha256=xR4NKuHc-7E3ld6NjyAAVcJG8CtIoKoM4mqd8qPOXsg,19063
6
+ piegy/model.py,sha256=NkP_Apnun3MhATSihR4_irnA-8p4FW879xQjCXVEPMA,45502
7
+ piegy/test_var.py,sha256=PDtCCou-kFXumEe2EdAQNKJohwHH58ifLSsp5xQraVI,23532
8
+ piegy/videos.py,sha256=vPl1aTIOaWxIUsxX5yL3JPiuf-Um0bPo7qYIHZP0bo0,10143
9
+ piegy/tools/__init__.py,sha256=eYOl_HJHDonYexfrmKh3koOlxvtSo46vH6jHvCEEB4k,300
10
+ piegy/tools/figure_tools.py,sha256=tAI5sBMsxN_1BN5_G_3UoMcDeYTj2DXr8l4HpPl9FSs,6961
11
+ piegy/tools/file_tools.py,sha256=ncxFWeHfIE-GYLQlOrahFlhBgqPyuY3R5_93fpQeCEs,630
12
+ piegy-1.1.1.dist-info/licenses/LICENSE.txt,sha256=wfzEht_CxOcfGGmg3f3at4mWJb9rTBjA51mXLl_3O3g,1498
13
+ piegy-1.1.1.dist-info/METADATA,sha256=qawzMEDrKZITzujlqMf_9WJoEklAGFYcOw3I2u8plbQ,5097
14
+ piegy-1.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
15
+ piegy-1.1.1.dist-info/top_level.txt,sha256=k4QLYL8PqdqDuy95-4NZD_FVLqJDsmq67tpKkBn4vMw,6
16
+ piegy-1.1.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.4.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,16 +0,0 @@
1
- piegy/__init__.py,sha256=Lrh6NegSvo6LOCXg_tBTu804eicnHpQY2zmE0FchjKE,3241
2
- piegy/__version__.py,sha256=H58EUm6wBWYw2Q4gXk5PznfRrEry4c4zk7c--daUx_8,365
3
- piegy/analysis.py,sha256=1cF06igQMGJGVjLiyhtgepGk8fYhzvL0orI48tOK1qY,8713
4
- piegy/data_tools.py,sha256=dXESWglAXN4q79ZG8wtpZftJoiiaOJFU7NSaip1ZTq0,3518
5
- piegy/figures.py,sha256=46Vg6AsWswF-juGbyndaRaChrdVuzPbpRQQd9grTWfk,17842
6
- piegy/model.py,sha256=2Y49NDzdtog9effo9Lr_-psu5NMBF3iH9BeE8zhCHZ8,45700
7
- piegy/test_var.py,sha256=fk_e0Hko6zNfsOx-SMnnEcsgeu6fx0rQcdfuXGceY7U,20892
8
- piegy/videos.py,sha256=vW0F9WYDvPVJM0fHM_0Vi9Y8ZSVfJBcuCLJ2lLXeZ2U,10410
9
- piegy/tools/__init__.py,sha256=eYOl_HJHDonYexfrmKh3koOlxvtSo46vH6jHvCEEB4k,300
10
- piegy/tools/figure_tools.py,sha256=qhuMPZn2krEzjhjmAd6ac9QVBeCWUkSdCGOz7RASAhA,5931
11
- piegy/tools/file_tools.py,sha256=ncxFWeHfIE-GYLQlOrahFlhBgqPyuY3R5_93fpQeCEs,630
12
- piegy-1.0.0.dist-info/licenses/LICENSE.txt,sha256=wfzEht_CxOcfGGmg3f3at4mWJb9rTBjA51mXLl_3O3g,1498
13
- piegy-1.0.0.dist-info/METADATA,sha256=hn5JGkA5jBMN2toZ0xPdJ-0munvYBE-BzcOMKWb-d-g,5035
14
- piegy-1.0.0.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
15
- piegy-1.0.0.dist-info/top_level.txt,sha256=k4QLYL8PqdqDuy95-4NZD_FVLqJDsmq67tpKkBn4vMw,6
16
- piegy-1.0.0.dist-info/RECORD,,