-
Notifications
You must be signed in to change notification settings - Fork 1
/
market_dynamics_visualisations.py
2735 lines (2224 loc) · 115 KB
/
market_dynamics_visualisations.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
import numpy as np
import time
from datetime import datetime
from matplotlib import cm, pyplot as plt
import matplotlib as mpl
mpl.rc('font',family='Times New Roman',size= 14)
import matplotlib.markers as mmarkers
from matplotlib.colors import ListedColormap
import matplotlib.gridspec as gridspec
import seaborn as sns
import scipy
from scipy.ndimage.filters import gaussian_filter
from os.path import dirname, abspath
import os
import sys
import shutil
global dirmain, diroutput # relative directories
dirmain = dirname(abspath(__file__))
diroutput = dirmain + '/visualisations/output/'
dirinput = dirmain + '/data/input/'
class household:
def __init__(self, N, N_min):
"""
__init__ initialises parameters and dictionaries for which characteristics and preferences are sampled from later.
param N: input number of households
param N_min: absolute minimum number of households
"""
self.N = int(N)
self.N_min = int(N)
self.q_bound = {'n_people': np.linspace(1,4,4), 'type I/II': [1]} # bounds for characteristics,
# type I/II is for testing different characteristics of households
self.s_bound = {'s_0': [-1,0], 'classical:modern': [-1, 1], 'large house': [0,1]} # bounds for preferences
class dwelling:
def __init__(self, M, R, u0_max, u0_wid, price_scale, M_max):
"""
__init__ initialises parameters and dictionaries for which characteristics are sampled from later.
param M: input number of dwellings
param R: linear size of model
param u0_max: maximum U0 value
param u0_wid: window size for U0 distribution
param price_scale: self explanatory by name, value to scale model values to; default unity scale
param M_max: max number of dwellings permitted
"""
self.M = int(M)
self.R = R
self.r_coord = np.zeros((1, 2)) # blank coordinate array
self.u0_max = float(u0_max)
self.u0_wid = u0_wid
self.price_scale = price_scale
self.M_max = M_max
""" establish some dictionaries for later (will search by index of element to find same term to compare
utility of specific characteristics of dwelling) """
self.style = {'classical:modern': [-1,1]}
class simulate:
def __init__(self):
self.all_store_pop = []
self.all_store_dwell = []
simulate.model_parameters(self) # instantiate the model parameters for simulation
def model_parameters(self):
"""
model_parameters() instantiates the main parameters in the model.
"""
# General parameters for model
self.R = 25 # size of coordinate space
self.t = 25 # no. years for simulation
self.t_inc = 4 # increments per year; annualized rates will be divided by this
self.chi = 1 # probability of transaction clearance (decimal)
self.sigma = 0.06/self.t_inc # fractional move rate (evaluated t_inc/year)
# Parameters for population and dwelling increase/decrease (evaluated 1/year)
# rates are as per evaluation period i.e. per year/no. steps per year
self.eps = 0.00/self.t_inc # rate of population growth
self.rho = 0.00/self.t_inc # rate of population decline
self.beta = 0.00/self.t_inc # rate of dwelling creation
self.lamb = 0.02/self.t_inc # rate of dwelling destruction
# affinity function G
self.G_0 = 0.2
self.h = 1
# household parameters
self.N = 1000 # number of households
self.N_min = 1000 # absolute minimum number of households
self.N0 = self.N # original number of households -- used in plotting of mean B and mean U
# dwelling parameters
self.M = 3*self.N # number of dwellings
self.u0_max = 5 # general dwelling utility U0
self.u0_wid = 7 # characteristic width of U0 window for preferred area
self.price_scale = 1000 # rough scale of $/quarter for pricing methods of dwellings.
self.M_max = 1.2 # max no. dwellings M permitted (during dwelling creation)
def create(self):
"""
create() instantiates all objects/classes within the model:
households, dwellings, calculations, visualisations.
"""
global calcs, pop, dwell, visu # instantiate all objects within the model
calcs = calculations()
pop = household(self.N, self.N_min)
dwell = dwelling(self.M, self.R, self.u0_max, self.u0_wid, self.price_scale, self.M_max)
visu = visualisation(sim, pop, dwell, calcs)
def load_from_save(self):
"""
load_from_save() loads all saved data from a specified save folder and fills this data
into all profile arrays.
"""
print("Ensure files to load are unique in directory 'data/input/files...'")
# get files in directory
files = sorted([filenames for _,_,filenames in os.walk(dirinput)][0])
files = [x for x in files if 'txt' in x]
pop_files = [x for x in files if 'household' in x]
dwell_files = [x for x in files if 'dwelling' in x]
order = []
for x in pop_files:
w = [pos for pos, char in enumerate(x) if char == '-']
order.append(float(x[w[0]+1:-3]))
files = np.array(sorted(zip(pop_files,dwell_files,order), key=lambda x:x[2]))
pop_files = files[:,0]
dwell_files = files[:,1]
# get simulation ID and create folder for visualisation output
w = [pos for pos, char in enumerate(pop_files[0]) if char == '_']
self.sim_id = pop_files[0][w[0]+1:w[1]]
self.current_folder = '{}-{}-{}'.format(self.sim_id[4:6],self.sim_id[2:4], self.sim_id[:2])
self.sim = 'market_dyn'
# create a directory for simulation output
chk_dir = os.path.isdir(str(diroutput) + self.current_folder)
if chk_dir == False:
os.mkdir(str(diroutput) + self.current_folder)
self.sim_folder = '{}#{}'.format(self.sim, self.sim_id)
chk_dir = os.path.isdir(str(diroutput) + self.current_folder+'/'+self.sim_folder)
if chk_dir == False:
os.mkdir(str(diroutput)+self.current_folder+'/'+self.sim_folder)
self.save_loc = str(diroutput) + str(self.current_folder) + '/' + str(self.sim_folder) + '/' # save directory
# load households & restructure at all timesteps into self.all_store_pop
for x in pop_files:
pop = np.loadtxt(str(dirinput)+x, dtype=float)
struct = pop[0]
# set sim.p/self.p to household data at last timestep
self.p = pop[1:].reshape(int(struct[0]),int(struct[1]), int(struct[2]))
# add to all_store
self.all_store_pop.append(np.array(self.p, dtype=object))
#load dwellings & restructure at all timesteps into self.all_store_dwell
for x in dwell_files:
dwell = np.loadtxt(str(dirinput)+x, dtype=float)
struct = dwell[0]
# set sim.r/self.r to dwelling data at last timestep
self.r = dwell[1:].reshape(int(struct[0]),int(struct[1]), int(struct[2]))
self.all_store_dwell.append(np.array(self.r, dtype=object))
# update the system size
self.R = int(np.max(self.r[:,1,0]))
def visualise_results(self):
"""
visualise_results() takes a user input for the types of models to plot,
i.e. those of the configuration of the model prior to any evaluation (early figures in paper),
OR those of the data output from a previous simulation (results/test cases in paper).
"""
print("loading data from previous simulations")
# load the saved data to begin simulation, only the parameters for length of simulation will remain,
# all parameters generated during instantiation of objects will be overwritten with the saved parameters.
simulate.load_from_save(self)
""" Case A - City formation """
visu.spatial_gaussian()
""" Case B - Effect of U0 """
# visu.densitymap() # figure 9a-f
# visu.densitymap_whole() # figure 8b
# visu.meanB_r_10() # figure 10a
# visu.U_contribution()
# if hasattr(dwell, 'U0_store'):
# visu.U0_dist_3d() # U0 distribution generated (3d plot)
# visu.U0_dist_2d() # U0 distribution generated (2d plot as function of r) - figure in paper
# visu.U0_sample_mean() # mean U0 distribution from sample
# visu.U0_sample() # U0 distribution from sample
""" Case C - Effects of Spatial Localization of Favored Dwelling Characteristics """
# visu.B1_dist()
# visu.C_gaussian_map() # figure 11b,c: gaussian smoothened spatial density of households
# visu.C_heatmap() # greyscale heatmap of spatial density of households
""" Case D - Segregation """
# visu.spatial_types() # figure 12,13 from paper; spatial plot of households by characteristic type q1
# visu.gaussian_types() # gaussian filter of density of households by characteristic type q1
""" Case E - Supply and Demand """
# visu.N_t() # figure 14a: no. households N vs time t
# visu.meanB_t_r() # figure 14b: plot mean B at specific radiuses for all t
# visu.meanB_r_t() # figure 14c: plot of mean B at all radiuses for each t
# visu.mean_density() # figure 14dL plot of mean density at all radius for each t
# visu.M_t() # no. dwellings M vs time t
""" extra visualisation functions """
""" Household related plots """
# visu.spatial_dist() # general scatter plot of households + dwellings or KDE of households
# visu.kdemap() # KDE map of households
# visu.wealthmap() # spatial map of wealth distribution
# visu.U_all() # scatter U of all households by s0 & line of best fit
# visu.plot_U_wealthy() # plot U of top 50 wealthiest households
# visu.U_specific_household() # plot utility of specific household
# visu.U_by_class() # plot utility of households over time
""" Dwelling related plots """
# visu.B0_dwell() # price B0 of specified dwelling over time
# visu.B0_household() # price of B0 for a specified household over time
# visu.scatter_unocc() # blue & red scatter plot of B0 over time for all dwellings
# visu.mean_B0_U() # plot the mean B0 vs t and mean U vs t
# visu.B0_M_animate() # animation - sorted B0 scattered against dwelling no M and s0 on right axis
# plt.savefig(sim.save_loc + '/plot'+ sim.sim_id +'.png', dpi=400) -- sample line for saving plot
# visu.liveplot() # animated plot of the spatial distribution
# visu.interactive_spatial() # interactive plot of spatial distribution of households/dwellings
plt.show()
def saving(self, timestep):
# save all vectors related to the household and the dwelling as separate files within specific datetime folder of iteration.
# save all model parameters also; model parameter file will include runtime also. -- NEED TO ADD THIS IN
# These will be saved in a format such that it can be input as starting data
print('SAVING DATA')
self.save_loc = str(diroutput) + str(self.current_folder) + '/' + str(self.sim_folder) + '/' # save directory
""" compile the household profile array for saving"""
mn = max([len(pop.p[0])+1, len(pop.q[0]), len(pop.s[0])])
self.p = np.zeros((pop.N, 4, mn), dtype=object) # initialise the empty array of the household profile array
p_dim = np.array(np.shape(self.p))
p_dim = np.array([np.pad(p_dim, (0,mn-len(p_dim)), 'constant')])
for n, [p, U, q, s] in enumerate(zip(pop.p[0:], pop.U[0:], pop.q[0:], pop.s[0:])):
self.p[n][0][:len(p)] = np.array(p) # add general household information
self.p[n][0][len(p)] = np.array(U) # add utility of household
self.p[n][1][:len(q)] = np.array(q) # add household characteristics
self.p[n][2][:len(s)] = np.array(s) # add price sensitivity & preference strengths of the household
# ## save household profile vector -- this is just turned off for testing
# with open(self.save_loc +'households_' + self.sim_id + '_timestep-{}.txt'.format(timestep) , 'w') as save:
# save.write('# household profile vector shape (no. households, 4, no. preferences/max length)\n')
# np.savetxt(save, p_dim, fmt='%-7.2f')
# save.write("""# KEY:
# # [[Household ID, on-market flag, dwelling_id, utility, 0...],
# # [characteristics: q_0(p), q_1(p), q_2(p), ..., q_m(p)],
# # [housing preferences: [s_0(p), s'(p)] = [s_0(p), s'_1(p), s'_2(p), ..., s_n(p)] ]\n""")
# for data_slice in self.p:
# save.write('\n# household {} \n'.format(data_slice[0][0]))
# np.savetxt(save, data_slice, fmt='%-7.2f')
""" compile the dwelling profile array for saving """
r_mn = max([len(dwell.style), len(pop.s_bound)]) # max of length of characteristics B or length of household profile array
self.r = np.zeros((dwell.M, 3, r_mn), dtype=object) # initialise the empty array dimensions to save dwelling data
r_dim = np.array(np.shape(self.r))
r_dim = np.array([np.pad(r_dim, (0,r_mn-len(r_dim)), 'constant')])
for n, [r, r_coord, B] in enumerate(zip(dwell.r[0:], dwell.r_coord[0:], dwell.B[0:])):
self.r[n][0][:len(r)] = np.array(r) # assign general information of dwelling
self.r[n][1][:len(r_coord)] = np.array(r_coord) # assign dwelling location
self.r[n][2][:len(B)] = np.array(B) # assign dwelling characteristics
# ## save dwelling profile vector -- this is just turned off for testing
# with open(self.save_loc +'dwellings_' + self.sim_id + '_timestep-{}.txt'.format(timestep) , 'w') as save:
# save.write('# dwellings profile vector shape (no. dwellings, 3, no. characteristics/max length)\n')
# np.savetxt(save, r_dim, fmt='%-7.2f')
# save.write("""# KEY:
# # [[Dwelling ID, on-market flag, U_0(r), 0, ...],
# # [location: r_1(r), r_2(r), 0, 0, 0, 0, ...],
# # [characteristics: B_0(r), B_1(r), ..., B_n(r)]]\n""")
# for data_slice in self.r:
# save.write('\n# dwelling {} \n'.format(data_slice[0][0]))
# np.savetxt(save, data_slice, fmt='%-7.2f')
self.all_store_pop.append(np.array(self.p, dtype=object))
self.all_store_dwell.append(np.array(self.r, dtype=object))
print('HOUSEHOLD & DWELLING PROFILE VECTORS SAVED')
class calculations:
def __init__(self):
self.fees = 0.00 # percentage of price of dwelling which will be charged as fees for transaction
def mse_dist(self, locs):
locs = np.array(locs*10, dtype=int)
centric = np.array(dwell.centric*10, dtype=int)
dists = np.linalg.norm(locs.T - centric.T, axis=0)/10
mse = np.mean(dists**2)
return mse
class visualisation:
def __init__(self, sim_in, pop_in, dwell_in, calcs_in):
self.tit_cnt = 0
self.rad_t = []
global sim, pop, dwell, calcs
sim = sim_in
pop = pop_in
dwell = dwell_in
calcs = calcs_in
def figure_2(self):
"""
figure_2() creates figures 2a and 2b from the paper:
- figure 2a: U(x, p_j) of household p_j vs dwelling position x,
- figure 2b: spatial varisation of B_1(x) vs x
this function is mostly hard set via tinkering; just example of distributions
"""
B = dwell.B
fig, axs = plt.subplots(2,1,figsize=(7, 10), dpi=90)
""" figure 2a """
xs = np.linspace(-2, 2.3, 100)
y2b = -xs
xs_1 = np.linspace(-1.6, -0.96, 20)
xs_2 = np.linspace(1.61, 2.13, 20)
y1 = (xs + np.pi)*np.sin(xs + np.pi)
y1_s = -5*(xs_1 + 1.3)**2 + 2.35
a = np.array([-np.sin(x**2/5) for x in xs if x<0])
b = np.array([np.sin(x**2/2) for x in xs if x>= 0])
y2 = np.concatenate((a, b))
y2_s = -5*(xs_2 - 1.9)**2 + 1.4
y3 = -((xs/0.6 - 2.9)*np.sin(xs/0.6 - 2.9))/4 + 0.17
y1 = y3 + y2b/2
y2 = y3 - y2b/2
axs[0].set_title("(a)", fontname='times', fontsize=20,loc='right')
axs[0].plot(xs, y1, 'black', linestyle='--')
axs[0].plot(xs_1, y1_s, 'black', linestyle='dotted')
axs[0].plot(xs, y2, 'black', linestyle='--')
axs[0].plot(xs_2, y2_s, 'black', linestyle='dotted')
axs[0].plot(xs, y3, 'black')
axs[0].set_xlim([-2, 2.3])
axs[0].set_ylim([-1.5, 2.6])
axs[0].text(-1.9, 1.2, r'$\rm p_{1}$', fontdict={'family':'times','weight': 'bold','size': 16})
axs[0].text(-1.9, -0.8, r'$\rm p_{2}$', fontdict={'family':'times','weight': 'bold','size': 16})
axs[0].set_xlabel(r"$x$", fontsize=18, fontname='times new roman')
axs[0].set_ylabel(r"$U(x, p_j)$", fontsize=18, fontname='times new roman')
axs[0].set_xticks(ticks=[])
axs[0].set_xticklabels(labels=[])
axs[0].set_yticks(ticks=[])
axs[0].set_yticklabels(labels=[])
""" figure 2b """
xs = np.linspace(-2, 2.3, 100)
y2b = -xs
axs[1].set_title("(b)", fontname='times', fontsize=20,loc='right')
axs[1].plot([xs[0], xs[-1]],[0, 0], 'black', linestyle='--' )
axs[1].plot(xs, y2b, 'black')
axs[1].set_xlabel(r"$x$", fontsize=18, fontname='times new roman')
axs[1].set_ylabel(r"$B_1(x)$", fontsize=18, fontname='times')
axs[1].set_xticks(ticks=[])
axs[1].set_xticklabels(labels=[])
axs[1].set_yticks(ticks=[0])
axs[1].set_yticklabels(labels=[0])
for tick in axs[1].get_yticklabels():
tick.set_fontname("times")
tick.set_fontsize(14)
axs[1].set_xlim([-2, 2.3])
axs[1].set_ylim([-2.3, 2])
# plt.savefig(sim.save_loc + '/figure_2-'+ sim.sim_id +'.png', dpi=400)
def figure_3(self):
"""
figure_3() creates figure 3 from the paper, utility function vs 1D position
for varying s0 values of a household.
this function is mostly hard set via tinkering; just example of distribution.
"""
x = np.linspace(0, 2.5, num=1000)
y0 = np.sin(x**2)/5 +1
y1 = np.sin(x**2)/5 +1.2
plt.figure(1, tight_layout=True, figsize=[5.4,3.8])
plt.plot(x, y0, 'black',linestyle='--')
plt.plot(x, y1,'black')
plt.ylim([0.6,1.7])
plt.xlim([0, 2.5])
plt.xticks(ticks=[], labels=[])
plt.yticks(ticks=[], labels=[])
plt.xlabel(r"$x$", fontsize=18, fontname='times new roman')
plt.ylabel(r"$U(x,p_j)$", fontsize=18, fontname='times')
# plt.savefig(sim.save_loc + '/figure_3-'+ sim.sim_id +'.png', dpi=400)
def figure_4abc(self):
"""
figure_4abc() creates figues 4a, 4b and 4c from the paper:
- figure 4a: log(F(m)) vs log(m) from eq. 11, star at knee at m_c.
- figure 4b: log(F(s_0)) vs s0 from eq. 12.
- figure 4c: m vs s0
use figsize 6,13 for same fig size as in paper & save as img
use figsize 5.3,10 for fig that fits screen.
"""
fig, axs = plt.subplots(3,1,figsize=(5.3, 10), dpi=90,tight_layout=True)
""" figure 4a """
axs[0].plot(np.log(calcs.m), np.log(calcs.F_m), c='black')
w = np.where(np.log(calcs.F_m)==np.log(calcs.m_c))
axs[0].scatter([np.log(calcs.m_c)],[-4.75],marker='*',s=100, c='black')
axs[0].scatter([np.min(np.log(calcs.m)), np.max(np.log(calcs.m))],[np.max(np.log(calcs.F_m)), np.min(np.log(calcs.F_m))],s=100, marker='.',c='black')
axs[0].text(9.3, -4.6, r'$ F(m_\mathrm{min})$', fontdict={'family':'times','weight': 'bold','size': 16})
axs[0].text(11.8, -7.4, r'$ F(m_\mathrm{max})$', fontdict={'family':'times','weight': 'bold','size': 16})
axs[0].text(10.95, -4.75, r'$ F(m_{c})$', fontdict={'family':'times','weight': 'bold','size': 16})
axs[0].set_xlabel(r'$ \log_{10} \> m$', fontsize=18)
axs[0].set_ylabel(r'$ \log_{10}\>F(m)$',fontsize=18)
for tick in axs[0].get_xticklabels():
tick.set_fontname("times")
tick.set_fontsize(14)
for tick in axs[0].get_yticklabels():
tick.set_fontname("times")
tick.set_fontsize(14)
axs[0].set_title("(a)", fontname='times', fontsize=20,loc='right')
""" figure 4b """
axs[1].plot(calcs.s_0, np.log(calcs.F_s), c='black')
axs[1].set_xlabel(r'$ s_0$',fontsize=18)
axs[1].set_ylabel(r'$ \log_{10} \>F(s_0)$',fontsize=18)
axs[1].set_title("(b)", fontname='times', fontsize=20,loc='right')
for tick in axs[1].get_xticklabels():
tick.set_fontname("times")
tick.set_fontsize(14)
for tick in axs[1].get_yticklabels():
tick.set_fontname("times")
tick.set_fontsize(14)
axs[1].scatter([np.min(calcs.s_0), np.max(calcs.s_0)],[np.max(np.log(calcs.F_s)), np.min(np.log(calcs.F_s))],s=100, marker='.',c='black')
axs[1].text(-0.97, 10.3, r'$ s_0(m_\mathrm{min})$', fontdict={'family':'times','weight': 'bold','size': 16})
axs[1].text(-0.2, -1.6, r'$ s_0(m_\mathrm{max})$', fontdict={'family':'times','weight': 'bold','size': 16})
""" figure 4c """
axs[2].plot(calcs.s_0, calcs.m, c='black')
axs[2].set_xlabel(r'$ s_0$',fontsize = 18)
axs[2].set_ylabel(r'$ m \>\>(\$10^{4}) $',fontsize=18)
axs[2].set_title("(c)", fontname='times', fontsize=20,loc='right')
axs[2].scatter([np.min(calcs.s_0), np.max(calcs.s_0)],[np.min(calcs.m), np.max(calcs.m)],s=100, marker='.',c='black')
axs[2].set_yticks(ticks=np.linspace(min(calcs.m), max(calcs.m), 6, dtype=int))
axs[2].set_yticklabels(labels=np.linspace(min(calcs.m), max(calcs.m), 6, dtype=int)//10000)
axs[2].text(-0.97, 13000, r'$ m(s_{0 \mathrm{min}})$', fontdict={'family':'times','weight': 'bold','size': 16})
axs[2].text(-0.15, 235000, r'$ m(s_{0 \mathrm{max}})$', fontdict={'family':'times','weight': 'bold','size': 16})
for tick in axs[2].get_xticklabels():
tick.set_fontname("times")
tick.set_fontsize(14)
for tick in axs[2].get_yticklabels():
tick.set_fontname("times")
tick.set_fontsize(14)
# plt.savefig(sim.save_loc + '/figure_4abc-'+ sim.sim_id +'.png', dpi=400)
def figure_4a(self):
"""
*** NOT UPDATED PLOT ****
Figure 4a from paper with dashed line at m_c
"""
m = calcs.m
F_m = calcs.F_m
m_c = calcs.m_c
plt.figure()
plt.plot(np.log(m), np.log(F_m), c='black')
plt.plot([np.log(m_c), np.log(m_c)],[min(np.log(F_m)), max(np.log(F_m))], c='grey',linestyle='--')
plt.xlabel('$m$ (log scale)', fontsize=12)
plt.ylabel('$F(m)$ (log scale)',fontsize=12)
plt.legend(['Income distribution $F(m)$', 'Income drop-off $m_c$'],fontsize=12)
# plt.savefig(sim.save_loc + '/figure_4a-'+ sim.sim_id +'.png', dpi=400)
def figure_4b_normalised(self):
"""
*** NOT UPDATED PLOT ****
!!! NOT USED IN PAPER !!!
figure_4b_normalised() plots normalised version of figure 4b from paper; normalised to 1.
- this is effectively the probability distribution in which the household price sensitivity
is then drawn from.
"""
s_0 = calcs.s_0
F_s_norm = calcs.F_s_norm
plt.figure()
plt.title('Figure 4b (normalized)')
plt.plot(s_0, F_s_norm)
plt.xlabel('$s_0$')
plt.ylabel('Normalized $F(s_0)$')
# plt.savefig(sim.save_loc + '/figure_4b_normalised-'+ sim.sim_id +'.png', dpi=400)
def m_s0_p(self):
"""
*** NOT UPDATED PLOT ****
!!! NOT USED IN PAPER !!!
m_s0_p() plots household income m(p) (left) and price sensitivity s_0(p) vs household p.
"""
m = calcs.m_sampled
s_0 = calcs.s_0_sampled
fig = plt.figure(tight_layout=True)
ax = fig.add_subplot(111)
ax.scatter(np.linspace(1,len(m),len(m)),m,marker='.',s=10)
ax2 = ax.twinx()
# ax2.scatter(np.linspace(1,len(m),len(m)),s_0,marker='.',s=0)
ax2.set_yticks(ticks=np.linspace(0,1,6, dtype=float))
ax2.set_yticklabels(labels=np.round(np.linspace(np.min(s_0),np.max(s_0),6, dtype=float),2), rotation=0)
ax.set_xlabel(r'Household $p$')
ax.set_ylabel(r'Income $m(p)$')
ax2.set_ylabel(r'Price sensitivity $s_0(p)$')
# plt.savefig(sim.save_loc + '/m_s0_p-'+ sim.sim_id +'.png', dpi=400)
def s0_N(self):
"""
*** NOT UPDATED PLOT ****
!!! NOT USED IN PAPER !!!
s0_N() plots price sensitivity s0 vs household N.
"""
draw = calcs.draw
plt.figure(tight_layout=True)
plt.title('Distribution of $s_0$ by household $N$')
plt.scatter(range(len(draw)),sorted(draw), marker='.',s=10)
plt.xlabel('Household $N$')
plt.ylabel('$s_0$')
# plt.savefig(sim.save_loc + '/s0_N-'+ sim.sim_id +'.png', dpi=400)
def figure_5(self):
"""
figure_5() creates figure 5 from the paper, utility function U(x,p_j,t)
and price function P(x,t) over all p at time t.
this function is mostly hard set via tinkering of sine curves;
- just example of distribution.
"""
xs = np.linspace(2.6,3.6, 1001)
u0 = np.array([-(np.sin(xs**2)*np.cos(xs))/10 + 4]).T
u0_max = -(np.sin(3.13**2)*np.cos(3.13))/10 + 4
u1 = np.array([-(1.5*np.sin(xs**2+1.4)*np.cos(2*xs))/5 + 4]).T
u1_min = -(1.5*np.sin(2.81**2+1.4)*np.cos(2*2.81))/5 + 4
u1_max = -(1.5*np.sin(3.6**2+1.4)*np.cos(2*3.6))/5 + 4
u2 = np.array([-(np.sin(xs**2)*np.cos(2*xs))/5 + 4]).T
u2_min = -(np.sin(2.99**2)*np.cos(2*2.99))/5 + 4
u2_max = -(np.sin(3.6**2)*np.cos(2*3.6))/5 + 4
u3 = np.array([-(np.sin(xs**2-1.2)*np.cos(2*xs))/5 + 4]).T
u3_min = -(np.sin(3.2**2-1.2)*np.cos(2*3.2))/5 + 4
u0[np.where(u0==u0_max)[0][0]:] = 0
u1[:np.where(u1==u1_min)[0][0]] = 0
u1[np.where(u1==u1_max)[0][0]:] = 0
u2[:np.where(u2==u2_min)[0][0]] = 0
u2[np.where(u2==u2_max)[0][0]:] = 0
u3[:np.where(u3==u3_min)[0][0]] = 0
price = np.concatenate((u0, u1, u2, u3), axis=1)
price = np.max(price, axis=1)
u0 = u0[np.nonzero(u0)]
x0 = np.linspace(2.6,3.13,len(u0))
u1 = u1[np.nonzero(u1)]
x1 = np.linspace(2.81,3.6,len(u1))
u2 = u2[np.nonzero(u2)]
x2 = np.linspace(2.99,3.6,len(u2))
u3 = u3[np.nonzero(u3)]
x3 = np.linspace(3.2,3.6,len(u3))
plt.figure(tight_layout=True, figsize=[5.4,3.8])
plt.plot(x0, u0, 'grey',linestyle='dotted')
plt.plot(x1, u1, 'grey', linestyle='dotted')
plt.plot(x2, u2, 'grey',linestyle='dotted')
plt.plot(x3, u3, 'grey',linestyle='dotted')
plt.plot(xs, price, 'black')
plt.xticks(ticks=[], labels=[])
plt.yticks(ticks=[], labels=[])
plt.xlabel(r"$x$", fontsize=18)
ylab = r"$U(x,p_j,t), \>\>\> P(x,t)$"
plt.ylabel(str(ylab), fontsize=18)
plt.ylim([3.97, 4.35])
plt.xlim([np.min(x0), np.max(x3)])
# plt.savefig(sim.save_loc + '/figure_5-'+ sim.sim_id +'.png', dpi=400)
def spatial_gaussian(self):
"""
CASE A - figure 7a-h
left column: spatial plots of households & dwellings
right column: gaussian smoothened plots of household distribution
caseA25 gives figures 7a-f
caseA50 gives figures 7g-h & gif creation
"""
yrs = np.array([0, 10, 25])*4
yrs = yrs[yrs<=sim.t*sim.t_inc]
for yr in yrs:
yr = int(yr)
dwell_r = np.array(sim.all_store_dwell[yr][:,0], dtype=float)
dwell_rcoord = np.array(sim.all_store_dwell[yr][:,1,[0,1]], dtype=float)
X_r, Y_r = dwell_rcoord[:,0:2].T
pop_p = np.array(sim.all_store_pop[yr][:,0],dtype=float)
types = [len(pop_p)]
self.types = types
colours = ['Black','crimson','forestgreen'] #'darkorange'
self.edge = ['lightgrey']*len(X_r)
self.c = [0]*len(X_r)
for y, x in enumerate(types):
self.edge.extend([colours[y]]*x)
self.c.extend([y+1]*x)
# cmap = ['lightgrey'] + colours[:len(types)] # dwellings in light grey
cmap = ['crimson'] + colours[:len(types)] # dwellings in light crimson
leg = ['Dwellings', 'Households']
self.cmap = ListedColormap(cmap)
X_p, Y_p = dwell_rcoord[:,0:2][np.array(pop_p[:,2],dtype=int)].T # coordinates of each household
self.loc = dwell_rcoord[:,0:2][np.array(pop_p[:,2],dtype=int)].T
self.X_p, self.Y_p = X_p, Y_p
# household of interest
# houseX, houseY = sim.r[:,1,0:2][np.array(sim.p[np.where(sim.p[:,0,0]==576),0,2],dtype=int)][0][0]
self.X_c = np.concatenate((X_r, X_p), axis=0)
self.Y_c = np.concatenate((Y_r, Y_p), axis=0)
self.s = [10]*len(X_r) + [10]*len(X_p)
self.mark = [str(".")]*len(X_r) + [str(".")]*len(X_p)
if sim.full_case == 'A':
titles = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s']
elif sim.full_case == 'A50':
titles = ['a','b','c','d','g','h','g','h','i','j','k','l','m','n','o','p','q','r','s']
fig, axs = plt.subplots(1,2)
plt.rcParams['mathtext.fontset'] = 'stix'
plt.rcParams['font.family'] = 'STIXGeneral'
axs[0].scatter(X_r, Y_r, s=[10]*len(X_r), c=[0]*len(X_r), edgecolors=['crimson']*len(X_r), cmap=ListedColormap('crimson'), marker='.', alpha=0.2)
axs[0].scatter(X_p, Y_p, s=[10]*len(X_p), c=[1]*len(X_p), edgecolors=['black']*len(X_p), cmap=ListedColormap('Black'), marker='.', alpha=1)
axs[0].set_xlabel("{} (km)".format(r'$x$'), fontsize=18, fontname='times')
axs[0].set_ylabel("{} (km)".format(r'$y$'), fontsize=18, fontname='times')
lims = 0.02*sim.R
axs[0].set_xlim([-lims, sim.R+lims])
axs[0].set_ylim([-lims, sim.R+lims])
axs[0].set_xticks(ticks=np.linspace(0,sim.R,6))
axs[0].set_yticks(ticks=np.linspace(0,sim.R,6))
for tick in axs[0].get_xticklabels():
tick.set_fontname("times")
tick.set_fontsize(14)
for tick in axs[0].get_yticklabels():
tick.set_fontname("times")
tick.set_fontsize(14)
axs[0].set_aspect('equal', adjustable='box')
axs[0].set_title("({})".format(titles[self.tit_cnt]), fontdict={'family':'times','weight': 'bold','size': 24},loc='right')
self.tit_cnt += 1
# GAUSSIAN SMOOTHENING PLOT
inc = 0.25
dim = int(int(sim.R//inc + 1))
locs = np.zeros(shape=(dim,dim))
for x, y in zip(self.X_p, self.Y_p):
locs[int(x*4)][int(y*4)] += 1
sig = 3
ax = 1
locs1 = gaussian_filter(locs, sigma=sig)
C = locs1.T
img = axs[ax].imshow(C, cmap='Greys', interpolation='nearest', vmin=0, vmax=0.5)
axs[ax].set_xlabel("{} (km)".format(r'$x$'), fontsize=18, fontname='times')
axs[ax].set_ylabel("{} (km)".format(r'$y$'), fontsize=18, fontname='times')
for tick in axs[ax].get_xticklabels():
tick.set_fontname("times")
tick.set_fontsize(14)
for tick in axs[ax].get_yticklabels():
tick.set_fontname("times")
tick.set_fontsize(14)
lims = 0.02*sim.R
axs[ax].set_xlim([-lims, sim.R+lims])
axs[ax].set_ylim([-lims, sim.R+lims])
axs[ax].set_xticks(ticks=np.linspace(0,sim.R*4+1,6, dtype=int))
axs[ax].set_xticklabels(labels=np.linspace(0,sim.R,6, dtype=int), rotation=0)
axs[ax].set_yticks(ticks=np.linspace(0,sim.R*4+1,6, dtype=int))
axs[ax].set_yticklabels(labels=np.linspace(0,sim.R,6, dtype=int))
axs[ax].set_aspect('equal', adjustable='box')
axs[ax].set_title("({})".format(titles[self.tit_cnt]), fontdict={'family':'times','weight': 'bold','size': 24},loc='right')
# plt.colorbar(img, ax=axs)
# axs[ax].invert_yaxis()
self.tit_cnt += 1
# # KDE PLOT INSTEAD OF GAUSSIAN
# sns.kdeplot(self.loc, cmap='Greys', shade=True, bw=2, ax=axs[1])
# axs[1].set_xlabel('x (km)',fontsize=16, fontname='times')
# axs[1].set_ylabel('y (km)',fontsize=16, fontname='times')
# for tick in axs[1].get_xticklabels():
# tick.set_fontname("times")
# tick.set_fontsize(12)
# for tick in axs[1].get_yticklabels():
# tick.set_fontname("times")
# tick.set_fontsize(12)
# axs[1].set_xlim([-1, sim.R+1])
# axs[1].set_ylim([-1, sim.R+1])
# axs[1].set_xticks(ticks=np.linspace(0,sim.R,6))
# # axs[0].set_xticklabels(labels=[0,5,10,15,20,25])
# axs[1].set_yticks(ticks=np.linspace(0,sim.R,6))
# # axs[0].set_yticklabels(labels=[0,5,10,15,20,25])
# axs[1].set_aspect('equal', adjustable='box')
# axs[1].set_title("({})".format(titles[self.tit_cnt]), fontdict={'family':'times','weight': 'bold','size': 20},loc='right')
# # plt.title('Year {}'.format(self.tit_cnt), x=-0.5, y=1)
# self.tit_cnt += 1
plt.tight_layout()
plt.savefig(sim.save_loc + '/urbanfig7{}{}'.format(titles[self.tit_cnt-2],titles[self.tit_cnt-1]) +'.png', dpi=400)
def spatial_gaussian_movie(self):
"""
CASE A - figure 7g gif creation
spatial plot of households & dwellings
caseA50 gives figures 7g-h & gif creation
"""
yrs = np.arange(0,101,dtype=int) # this is for movie creation -- save all figures to folder then use
# https://ezgif.com/maker to compile pics into .gif
yrs = yrs[yrs<=sim.t*sim.t_inc]
for yr in yrs:
yr = int(yr)
dwell_r = np.array(sim.all_store_dwell[yr][:,0], dtype=float)
dwell_rcoord = np.array(sim.all_store_dwell[yr][:,1,[0,1]], dtype=float)
X_r, Y_r = dwell_rcoord[:,0:2].T
pop_p = np.array(sim.all_store_pop[yr][:,0],dtype=float)
types = [len(pop_p)]
self.types = types
colours = ['Black','crimson','forestgreen'] #'darkorange'
self.edge = ['lightgrey']*len(X_r)
self.c = [0]*len(X_r)
for y, x in enumerate(types):
self.edge.extend([colours[y]]*x)
self.c.extend([y+1]*x)
# cmap = ['lightgrey'] + colours[:len(types)] # dwellings in light grey
cmap = ['crimson'] + colours[:len(types)] # dwellings in light crimson
leg = ['Dwellings', 'Households']
self.cmap = ListedColormap(cmap)
X_p, Y_p = dwell_rcoord[:,0:2][np.array(pop_p[:,2],dtype=int)].T # coordinates of each household
self.loc = dwell_rcoord[:,0:2][np.array(pop_p[:,2],dtype=int)].T
self.X_p, self.Y_p = X_p, Y_p
# household of interest
# houseX, houseY = sim.r[:,1,0:2][np.array(sim.p[np.where(sim.p[:,0,0]==576),0,2],dtype=int)][0][0]
self.X_c = np.concatenate((X_r, X_p), axis=0)
self.Y_c = np.concatenate((Y_r, Y_p), axis=0)
self.s = [10]*len(X_r) + [10]*len(X_p)
self.mark = [str(".")]*len(X_r) + [str(".")]*len(X_p)
if sim.full_case == 'A':
titles = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s']
elif sim.full_case == 'A50':
titles = ['a','b','c','d','g','h','g','h','i','j','k','l','m','n','o','p','q','r','s']
fig, axs = plt.subplots(1)
plt.rcParams['mathtext.fontset'] = 'stix'
plt.rcParams['font.family'] = 'STIXGeneral'
axs.scatter(X_r, Y_r, s=[10]*len(X_r), c=[0]*len(X_r), edgecolors=['crimson']*len(X_r), cmap=ListedColormap('crimson'), marker='.', alpha=0.2)
axs.scatter(X_p, Y_p, s=[10]*len(X_p), c=[1]*len(X_p), edgecolors=['black']*len(X_p), cmap=ListedColormap('Black'), marker='.', alpha=1)
axs.set_xlabel("{} (km)".format(r'$x$'), fontsize=18, fontname='times')
axs.set_ylabel("{} (km)".format(r'$y$'), fontsize=18, fontname='times')
lims = 0.02*sim.R
axs.set_xlim([-lims, sim.R+lims])
axs.set_ylim([-lims, sim.R+lims])
axs.set_xticks(ticks=np.linspace(0,sim.R,6))
axs.set_yticks(ticks=np.linspace(0,sim.R,6))
for tick in axs.get_xticklabels():
tick.set_fontname("times")
tick.set_fontsize(14)
for tick in axs.get_yticklabels():
tick.set_fontname("times")
tick.set_fontsize(14)
axs.set_aspect('equal', adjustable='box')
# axs[0].set_title("({})".format(titles[self.tit_cnt]), fontdict={'family':'times','weight': 'bold','size': 24},loc='right')
# self.tit_cnt += 1
# GAUSSIAN SMOOTHENING PLOT
# inc = 0.25
# dim = int(int(sim.R//inc + 1))
# locs = np.zeros(shape=(dim,dim))
# for x, y in zip(self.X_p, self.Y_p):
# locs[int(x*4)][int(y*4)] += 1
# sig = 3
# ax = 1
# locs1 = gaussian_filter(locs, sigma=sig)
# C = locs1.T
# img = axs[ax].imshow(C, cmap='Greys', interpolation='nearest', vmin=0, vmax=0.5)
# axs[ax].set_xlabel("{} (km)".format(r'$x$'), fontsize=18, fontname='times')
# axs[ax].set_ylabel("{} (km)".format(r'$y$'), fontsize=18, fontname='times')
# for tick in axs[ax].get_xticklabels():
# tick.set_fontname("times")
# tick.set_fontsize(14)
# for tick in axs[ax].get_yticklabels():
# tick.set_fontname("times")
# tick.set_fontsize(14)
# lims = 0.02*sim.R
# axs[ax].set_xlim([-lims, sim.R+lims])
# axs[ax].set_ylim([-lims, sim.R+lims])
# axs[ax].set_xticks(ticks=np.linspace(0,sim.R*4+1,6, dtype=int))
# axs[ax].set_xticklabels(labels=np.linspace(0,sim.R,6, dtype=int), rotation=0)
# axs[ax].set_yticks(ticks=np.linspace(0,sim.R*4+1,6, dtype=int))
# axs[ax].set_yticklabels(labels=np.linspace(0,sim.R,6, dtype=int))
# axs[ax].set_aspect('equal', adjustable='box')
# axs[ax].set_title("({})".format(titles[self.tit_cnt]), fontdict={'family':'times','weight': 'bold','size': 24},loc='right')
# plt.colorbar(img, ax=axs)
# axs[ax].invert_yaxis()
# self.tit_cnt += 1
# # KDE PLOT INSTEAD OF GAUSSIAN
# sns.kdeplot(self.loc, cmap='Greys', shade=True, bw=2, ax=axs[1])
# axs[1].set_xlabel('x (km)',fontsize=16, fontname='times')
# axs[1].set_ylabel('y (km)',fontsize=16, fontname='times')
# for tick in axs[1].get_xticklabels():
# tick.set_fontname("times")
# tick.set_fontsize(12)
# for tick in axs[1].get_yticklabels():
# tick.set_fontname("times")
# tick.set_fontsize(12)
# axs[1].set_xlim([-1, sim.R+1])
# axs[1].set_ylim([-1, sim.R+1])
# axs[1].set_xticks(ticks=np.linspace(0,sim.R,6))
# # axs[0].set_xticklabels(labels=[0,5,10,15,20,25])
# axs[1].set_yticks(ticks=np.linspace(0,sim.R,6))
# # axs[0].set_yticklabels(labels=[0,5,10,15,20,25])
# axs[1].set_aspect('equal', adjustable='box')
# axs[1].set_title("({})".format(titles[self.tit_cnt]), fontdict={'family':'times','weight': 'bold','size': 20},loc='right')
# # plt.title('Year {}'.format(self.tit_cnt), x=-0.5, y=1)
# self.tit_cnt += 1
plt.tight_layout()
plt.savefig(sim.save_loc + '/A_spatial_50_{}-'.format(yr)+ sim.sim_id +'.png', dpi=200)
plt.close()
def U0_dist_2d(self):
"""
CASE B - figure 8a
U0_dist_2d() plots the distribution of U0 in a 2D plot;
- side-cut from r=0 to r=R of the 3D plot below.
"""
r = dwell.R/2
d = np.sqrt(r**2 + r**2)
x = np.linspace(0,d, 100)
u0 = dwell.u0_max*np.exp(-abs(x**2/(dwell.u0_wid**2)))
u0 = u0/max(u0)
plt.figure(tight_layout=True)
plt.plot(x, u0, 'Black')
plt.xticks(ticks=np.linspace(0,d,6), labels=np.linspace(0,d,6,dtype=int))
plt.xticks(fontsize=16)
plt.yticks(fontsize=16)
plt.yticks(np.round(np.linspace(0,1,6,dtype=float),2))
plt.xlabel(r"$r$" + " (km)", fontsize=20, fontname='times new roman')
plt.ylabel(r"$U_0( r)\>/\>U_{\rm max}$", fontsize=20, fontname='times new roman')
plt.rcParams['mathtext.fontset'] = 'stix'
plt.rcParams['font.family'] = 'STIXGeneral'
plt.title("(a)", fontname='times', fontsize=28, loc='right')
plt.xlim([0, d])
plt.ylim([0, 1])
plt.savefig(sim.save_loc + '/urbanfig8a.png', dpi=400)
def U0_dist_3d(self):
"""
CASE B
U0_dist_3d() plots the distribution of U0 in a 3D plot.
!!! NOT USED IN PAPER !!!
"""
U0_store = dwell.U0_store
incs = dwell.incs
X,Y = np.meshgrid(np.arange(0,incs,1),np.arange(0,incs,1))
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(X, Y,U0_store, cmap='viridis')
c=256
ax.set_facecolor((c/256,c/256,c/256))
ax.w_xaxis.set_pane_color((c/256,c/256,c/256, c/256))
ax.w_yaxis.set_pane_color((c/256,c/256,c/256, c/256))
ax.grid(False)
ax.set_xlim([incs,1])
ax.set_zlim([np.min(U0_store),2.5*np.max(U0_store)])
ax.w_zaxis.line.set_lw(0.)
ax.set_zticks([])
ax.set_ylim([1,incs])
incs = np.linspace(0,np.max(U0_store), 6)
ax.set_xticklabels(np.linspace(0,dwell.R,6,dtype=int))
ax.set_yticklabels(np.linspace(0,dwell.R,6,dtype=int))
ax.set_xlabel("x (km)", fontsize=18, fontname='times new roman', labelpad=10)
ax.set_ylabel("y (km)", fontsize=18, fontname='times new roman', labelpad=10)
for tick in ax.get_xticklabels():
tick.set_fontname("times")
tick.set_fontsize(12)
for tick in ax.get_yticklabels():
tick.set_fontname("times")
tick.set_fontsize(12)
for tick in ax.get_zticklabels():
tick.set_fontname("times")
tick.set_fontsize(12)
plt.title("(a)", fontname='times', fontsize=24, x=1, y=0.8)
cbaxes = fig.add_axes([0.8, 0.08, 0.02, 0.55])
cbar = fig.colorbar(cm.ScalarMappable(cmap='viridis'), ax=ax, shrink=0.2, cax = cbaxes)
cbar.set_ticks(np.linspace(0,1,5))
u0_ = r'$U_0$'
u0_max = r'$U_{max}$'
# cbar.set_ticklabels(np.round(np.linspace(np.min(self.U0_store),np.max(self.U0_store),5),1))
cbar.set_ticklabels(np.round(np.linspace(0,1,5),1))
cbar.set_label('{} / {}'.format(u0_,u0_max), fontsize=16, labelpad=10)
cbar.ax.tick_params(labelsize=12)
fig.subplots_adjust(left=0, right=0.8, wspace=0) # this plus no 'tight_layout=True' allows for adjusting of margins
# plt.savefig(sim.save_loc + '/B_U0_dist_3d-'+ sim.sim_id +'.png', dpi=400)
def U0_sample_mean(self):
"""
CASE B
U0_sample() creates a 3D plot of the >mean< U0 sampled from the generated U0 distribution.
!!! NOT USED IN PAPER !!!
"""