-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathplot_potential.py
More file actions
182 lines (120 loc) · 4.74 KB
/
plot_potential.py
File metadata and controls
182 lines (120 loc) · 4.74 KB
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
import numpy as np
import h5py
import os
import datetime as dt
import matplotlib.pyplot as plt
import nvector as nv
import pandas as pd
import pvlib
import nc_utils
from ppigrf import igrf
import scipy.interpolate
def main(
stime=dt.datetime(2019, 3, 4, 1),
etime=dt.datetime(2019, 3, 5),
timestep=dt.timedelta(minutes=60),
mlat_cutoff=60.,
pot_fname_fmt='/Users/chartat1/Downloads/pymix_2019Mar04/ampere_mix_%04d-%02d-%02dT%02d-%02d-%02dZ.nc',
plot_fname_fmt='./plots/ampere_mix_%04d-%02d-%02dT%02d-%02d-%02dZ.png',
):
"""
Validate potential maps using DMSP cross-track drift data
"""
""" Get the North Magnetic Pole location in geographic coordinates """
pot_fname = pot_fname_fmt % (stime.year, stime.month, stime.day, stime.hour, stime.minute, stime.second)
pot = nc_utils.ncread_vars(pot_fname)
np_idx = pot['MLAT (AACGM)'] == 90
assert np.sum(np_idx) > 0, 'pole not found'
np_latlon = [pot['Geographic Latitude'][np_idx][0], pot['Geographic Longitude'][np_idx][0]]
""" Run through and process """
time = stime
while time < etime:
""" load poetntial at time """
pot_fname = pot_fname_fmt % (time.year, time.month, time.day, time.hour, time.minute, time.second)
pot = nc_utils.ncread_vars(pot_fname)
""" plot """
plot_fname = plot_fname_fmt % (time.year, time.month, time.day, time.hour, time.minute, time.second)
fig, ax = plt.subplots(1, 1,subplot_kw={'projection': 'polar'})
lats, lons = pot['MLAT (AACGM)'][:, 0], pot['MLON (AACGM)'][0, :]
rad, theta = get_rad_theta(lats, lons)
""" contour data over the map. """
latlim = 55.
#theta = np.concatenate([theta, [np.abs(theta[0]),]])
poten = pot['Potential'] # [::-1, :]
si = np.argsort(theta)
im = ax.contourf(theta[si], rad, poten[:, si])
yticks = 90 - np.rad2deg(ax.get_yticks())
ax.set_yticklabels(['%1.0f' % y for y in yticks])
cb = plt.colorbar(im, ax=ax)
""" Plot local noon dot """
noon_glon = local_noon(time)
noon_mlon = glon_to_mlon(
pot['Geographic Longitude'][-1, :],
pot['MLON (AACGM)'][-1, :], noon_glon,
)
noon_rad, noon_theta = get_rad_theta(latlim + 0.5, noon_mlon)
ax.plot(noon_theta, noon_rad, '.r', markersize=20)
ax.set_rmax(np.deg2rad(90 - latlim))
plt.savefig(plot_fname)
print('***** Saved to %s' % plot_fname)
plt.close()
time += timestep
def load_ampere(fname, dati=None):
"""
load AMPERE data
if no date/time requested assume that we're doing the whole
AMPERE netcdf file
otherwise, do just the requested time
"""
dset = ncread_vars(fname)
blocks = np.arange(dset['Jr'].shape[0])
nlon = dset['nlon'][0] + 0
nlat = dset['nlat'][0] + 0
vars = {}
for vn in ['dBnorth2', 'dBeast1', 'Jr']:
vars[vn] = []
for block in blocks:
tmp = np.reshape(dset[vn][block], (nlon, nlat))
# add pole:
tmp = np.hstack((np.ones((tmp.shape[0], 1)) * tmp[:, 0].mean(), tmp))
vars[vn].append(tmp.T)
return vars
def zero_360(vals):
""" set values between 0 - 360 degrees """
if isinstance(vals, float):
vals = np.array(vals)
vals[vals >= 360] -= 360
vals[vals < 0] += 360
return vals
def wrap(dictarr):
"""
Wrap grid in longitude and above pole/below lowest lat for gradient calculation
"""
d2 = {}
for k, arr in dictarr.items():
# add opposite longitude ring above the pole
half_lon = int(arr.shape[1] / 2)
lon_idx = np.concatenate([np.arange(half_lon, arr.shape[1]), np.arange(half_lon)])
arr2 = np.concatenate([arr[1, [lon_idx,]], arr], axis=0)
# add duplicate ring below the lowest latitude
arr3 = np.concatenate([arr2, arr2[[-1,], :]], axis=0)
# Add another longitude wrap before the first one
arr4 = np.concatenate([arr3[:, [-2,]], arr3], axis=1)
d2[k] = arr4
return d2
def local_noon(time):
""" Calculate local noon longitude from UTC time """
noon_lon = zero_360(-(time.hour / 24 + time.minute / 1440) * 360 + 180)
return noon_lon
def glon_to_mlon(glon, mlon, glon_i):
""" interpolate geographic longitude to AACGM lon """
intf = scipy.interpolate.interp1d(zero_360(glon), zero_360(mlon), fill_value='extrapolate')
noon_mlon = intf(zero_360(glon_i))
return noon_mlon
def get_rad_theta(lat, lon):
""" convert lat, lon (deg) to r/theta for polar plotting """
rad = np.deg2rad(90) - np.abs(np.deg2rad(lat))
theta = np.deg2rad(lon)
return rad, theta
if __name__ == '__main__':
main()