def CHAOS_phiavg_timeavg(nphi, ntheta, lmax, yearStart, yearEnd, n, radius=3485): model = cp.load_CHAOS_matfile('../data/CHAOS-7.7.mat') time = np.linspace(yearStart, yearEnd, n) time_chaos = np.array([cp.data_utils.dyear_to_mjd(x) for x in time]) # modified Julian date # create grid latC = np.linspace(0.01, 179.99, num=ntheta) # colatitude in degrees lonC = np.linspace(-179.99, 179.99, num=nphi) # longitude in degrees Br_avg = [] for t in time_chaos: print('Loading CHAOS time {:.2f}'.format(t)) # ylm = model.synth_coeffs_tdep(t) # dtglm = model.synth_coeffs_tdep(t, deriv=1) # Secular Variation Br, _, _ = model.synth_values_tdep(t, radius, latC, lonC, nmax=lmax, deriv=0, grid=True) # (nT) BrC = trapz(Br, lonC, axis=1) # phi average Br_avg.append(BrC) Br_out = sum(Br_avg) / n latC = 90 - latC # NOTE: 0<theta<180 to read data but -90<theta<90 to plot return (latC, lonC, Br_out)
def profiler_complete_forward(n_data=300): """ Example: .. code-block:: python %load_ext line_profiler import sys sys.path.insert(0, <tests directory path>) from test_chaosmagpy import profiler_complete_forward as profiler import chaosmagpy as cp %lprun -f cp.coordinate_utils.synth_rotate_gauss profiler(n_data=300) """ t_start = -200.0 t_end = 6000.0 time = np.linspace(t_start, t_end, num=n_data) radius = R_REF * np.ones(time.shape) theta = np.linspace(1, 179, num=n_data) phi = np.linspace(-180, 179, num=n_data) model = load_CHAOS_matfile(CHAOS_PATH) # B_radius, B_theta, B_phi = model(time, radius, theta, phi) B_radius, B_theta, B_phi = model(time, radius, theta, phi) print('Ran "profiler_complete_forward"')
def example1(): # give inputs theta = np.array([55.676, 51.507, 64.133]) # colat in deg phi = np.array([12.568, 0.1275, -21.933]) # longitude in deg radius = np.array([0.0, 0.0, 500.0]) + R_REF # radius from altitude in km time = np.array([3652.0, 5113.0, 5287.5]) # time in mjd2000 # load the CHAOS model model = load_CHAOS_matfile(FILEPATH_CHAOS) print(model) print('Computing core field.') B_core = model.synth_values_tdep(time, radius, theta, phi) print('Computing crustal field up to degree 110.') B_crust = model.synth_values_static(radius, theta, phi, nmax=110) # complete internal contribution B_radius_int = B_core[0] + B_crust[0] B_theta_int = B_core[1] + B_crust[1] B_phi_int = B_core[2] + B_crust[2] print('Computing field due to external sources, incl. induced field: GSM.') B_gsm = model.synth_values_gsm(time, radius, theta, phi, source='all') print('Computing field due to external sources, incl. induced field: SM.') B_sm = model.synth_values_sm(time, radius, theta, phi, source='all') # complete external field contribution B_radius_ext = B_gsm[0] + B_sm[0] B_theta_ext = B_gsm[1] + B_sm[1] B_phi_ext = B_gsm[2] + B_sm[2] # complete forward computation B_radius = B_radius_int + B_radius_ext B_theta = B_theta_int + B_theta_ext B_phi = B_phi_int + B_phi_ext # save to output file data_CHAOS = np.stack([ time, radius, theta, phi, B_radius, B_theta, B_phi, B_radius_int, B_theta_int, B_phi_int, B_radius_ext, B_theta_ext, B_phi_ext ], axis=-1) header = (' t (mjd2000) r (km) theta (deg) phi (deg) B_r ' 'B_theta B_phi B_r B_theta B_phi B_r ' 'B_theta B_phi\n' ' ' 'model total model internal ' 'model external') np.savetxt('example1_output.txt', data_CHAOS, delimiter=' ', header=header, fmt=['%15.8f', '%9.3f', '%11.5f', '%11.5f'] + 9 * ['%9.2f']) print('Saved output to example1_output.txt.')
def test_synth_euler_angles(self): model = cp.load_CHAOS_matfile(CHAOS_PATH) test = load_matfile(MATFILE_PATH, 'test_synth_euler_angles') time = np.squeeze(test['time']) swarm_c = model.synth_euler_angles(time, 'swarm_c') self.assertIsNone(np.testing.assert_allclose(swarm_c, test['swarm_c']))
def example2(): """ Plot difference between modelled and observed field strength using Swarm A data in August 2018 from a cdf-file. """ import cdflib model = load_CHAOS_matfile(FILEPATH_CHAOS) print(model) cdf_file = cdflib.CDF( 'data/SW_OPER_MAGA_LR_1B_' '20180801T000000_20180801T235959' '_PT15S.cdf', 'r') # print(cdf_file.cdf_info()) # print cdf info/contents radius = cdf_file.varget('Radius') / 1000 # km theta = 90. - cdf_file.varget('Latitude') # colat deg phi = cdf_file.varget('Longitude') # deg time = cdf_file.varget('Timestamp') # milli seconds since year 1 time = time / (1e3 * 3600 * 24) - 730485 # time in modified Julian date 2000 F_swarm = cdf_file.varget('F') cdf_file.close() theta_gsm, phi_gsm = transform_points(theta, phi, time=time, reference='gsm') index_day = np.logical_and(phi_gsm < 90, phi_gsm > -90) index_night = np.logical_not(index_day) # complete forward computation: pre-built not customizable (see ex. 1) B_radius, B_theta, B_phi = model(time, radius, theta, phi) # compute field strength and plot together with data F = np.sqrt(B_radius**2 + B_theta**2 + B_phi**2) print('RMSE of F: {:.5f} nT'.format(np.std(F - F_swarm))) plt.scatter(theta_gsm[index_day], F_swarm[index_day] - F[index_day], s=0.5, c='r', label='dayside') plt.scatter(theta_gsm[index_night], F_swarm[index_night] - F[index_night], s=0.5, c='b', label='nightside') plt.xlabel('dipole colatitude ($^\\circ$)') plt.ylabel('$\\mathrm{d} F$ (nT)') plt.legend(loc=2) plt.show()
def example4(): """ Plot maps of static (i.e. small-scale crustal) magnetic field. """ model = load_CHAOS_matfile(FILEPATH_CHAOS) radius = R_REF model.plot_maps_static(radius, nmax=85)
def test_save_matfile(self): seq = np.random.randint(0, 10, size=(5, )) filename = 'CHAOS-tmp_' + ''.join([str(a) for a in seq]) + '.mat' filepath = os.path.join(ROOT, filename) model = cp.load_CHAOS_matfile(CHAOS_PATH) print(' ', end='') # indent line by two withespaces model.save_matfile(filepath) def test(x, y): if isinstance(x, str) or isinstance(y, str): # convert unicode to str np.testing.assert_string_equal(str(x), str(y)) else: np.testing.assert_allclose(x, y, atol=1e-10) chaos = cp.data_utils.load_matfile( CHAOS_PATH, variable_names=['pp', 'model_ext', 'model_Euler', 'g']) chaos_out = cp.data_utils.load_matfile( filepath, variable_names=['pp', 'model_ext', 'model_Euler', 'g']) pp = chaos['pp'] pp_out = chaos_out['pp'] for key in ['order', 'dim', 'pieces', 'form', 'coefs', 'breaks']: test(pp[key], pp_out[key]) test(chaos['g'], chaos_out['g']) model_ext = chaos['model_ext'] model_ext_out = chaos_out['model_ext'] for key in [ 'm_Dst', 'm_gsm', 'm_sm', 'q10', 'qs11', 't_break_q10', 't_break_qs11' ]: test(model_ext[key], model_ext_out[key]) model_Euler = chaos['model_Euler'] model_Euler_out = chaos_out['model_Euler'] for key in ['alpha', 'beta', 'gamma', 't_break_Euler']: var = model_Euler[key] var_out = model_Euler_out[key] test(var.shape, var_out.shape) for value, value_out in zip(np.ravel(var), np.ravel(var_out)): test(value, value_out) print(f" Removing file {filepath}") os.remove(filepath)
def example6(): """ Plot maps of external and internal sources described in SM and GSM reference systems. """ model = load_CHAOS_matfile(FILEPATH_CHAOS) radius = R_REF + 450 time = mjd2000(2015, 9, 1, 12) model.plot_maps_external(time, radius, reference='all', source='all')
def example3(): """ Plot maps of core field and its derivatives for different times and radii. """ model = load_CHAOS_matfile(FILEPATH_CHAOS) radius = 0.53 * R_REF # radial distance in km of core-mantle boundary time = mjd2000(2015, 9, 1) # year, month, day model.plot_maps_tdep(time, radius, nmax=16, deriv=1)
def example5(): """ Plot timeseries of the magnetic field at the ground observatory in MBour MBO (lat: 75.62°, east lon: 343.03°). """ model = load_CHAOS_matfile(FILEPATH_CHAOS) # observatory location radius = 6.376832e+03 theta = 75.69200 phi = 343.05000 model.plot_timeseries_tdep(radius, theta, phi, nmax=16, deriv=1)
def test_synth_gsm_field(self): # load matfile test = load_matfile(MATFILE_PATH, 'test_synth_gsm_field') model = load_CHAOS_matfile(CHAOS_PATH) N = int(1000) time = np.linspace(-1000, 6000, num=N) radius = R_REF theta = np.linspace(1, 179, num=N) phi = np.linspace(-180, 179, num=N) B_radius = np.zeros(time.shape) B_theta = np.zeros(time.shape) B_phi = np.zeros(time.shape) for source in ['internal', 'external']: B_radius_new, B_theta_new, B_phi_new = model.synth_values_gsm( time, radius, theta, phi, source=source) B_radius += B_radius_new B_theta += B_theta_new B_phi += B_phi_new B_radius_mat = np.ravel(test['B_radius']) B_theta_mat = np.ravel(test['B_theta']) B_phi_mat = np.ravel(test['B_phi']) for component in ['B_radius', 'B_theta', 'B_phi']: res = np.abs(eval(component) - eval('_'.join((component, 'mat')))) print(' -------------------') print(f' {component}:') print(' MAE =', np.mean(res), 'nT') print(' RMSE =', np.sqrt(np.mean(res**2)), 'nT') print(' Max Error =', np.amax(res), 'nT') print(' Min Error =', np.amin(res), 'nT') self.assertIsNone(np.testing.assert_allclose( B_radius, B_radius_mat, rtol=1e-2, atol=1e-2)) self.assertIsNone(np.testing.assert_allclose( B_theta, B_theta_mat, rtol=1e-2, atol=1e-2)) self.assertIsNone(np.testing.assert_allclose( B_phi, B_phi_mat, rtol=1e-2, atol=1e-2))
def CHAOS_ground_values(GPS_ResInt): #1. Load the requiered parameters, including a local CHAOS model in mat format. model = load_CHAOS_matfile(r'CHAOS-7.mat') theta = 90 - GPS_ResInt['Latitude'].values phi = GPS_ResInt['Longitude'].values alt = GPS_ResInt['Altitude'].values rad_geoc_ground, theta_geoc_ground, sd_ground, cd_ground = gg_to_geo( alt, theta ) # gg_to_geo, will transfor the coordinates from geocentric values to geodesic values. Altitude must be in km time = mjd2000( pd.DatetimeIndex(GPS_ResInt['DateTime']).year, pd.DatetimeIndex(GPS_ResInt['DateTime']).month, pd.DatetimeIndex(GPS_ResInt['DateTime']).day) #2. Compute the core, crust and magentoshpere contributions at the altitude level. B_r_core, B_t_core, B_phi_core = model.synth_values_tdep( time, rad_geoc_ground, theta_geoc_ground, phi) #Core Contribution B_r_crust, B_t_crust, B_phi_crust = model.synth_values_static( rad_geoc_ground, theta_geoc_ground, phi) #Crust Contribution B_r_magneto, B_t_magneto, B_phi_magneto = model.synth_values_gsm( time, rad_geoc_ground, theta_geoc_ground, phi) #Magnetosphere contribution. #3. Change the direcction of the axis from XYZ to r,theta and phi. B_r_swarm, B_t_swarm, B_phi_swarm = -GPS_ResInt['C_res'], -GPS_ResInt[ 'N_res'], GPS_ResInt['E_res'] #4. Compute the magnetic component (r,theta,phi) at ground level. B_r_ground = B_r_core + B_r_crust + B_r_magneto + B_r_swarm #(-Z) B_t_ground = B_t_core + B_t_crust + B_t_magneto + B_t_swarm #(-X) B_phi_ground = B_phi_core + B_phi_crust + B_phi_magneto + B_phi_swarm #(Y) #5. Convert B_r_, B_t_, and B_phi to XYZ (NEC) Z_chaos = -B_r_ground #Z X_chaos = -B_t_ground #X Y_chaos = B_phi_ground #Y #6. Rotate the X(N) and Z(C) magnetic field values of the chaos models into the geodectic frame using the sd and cd (sine and cosine d from gg_to_geo) X_obs = X_chaos * cd_ground + Z_chaos * sd_ground #New N Z_obs = Z_chaos * cd_ground - X_chaos * sd_ground #New C Y_obs = Y_chaos # New E return X_obs, Y_obs, Z_obs
def test_surface_field(self): model = cp.load_CHAOS_matfile(CHAOS_PATH) time = 2015. radius = R_REF theta = np.linspace(1, 179, num=180) phi = np.linspace(-180, 179, num=360) B_radius, B_theta, B_phi = model.synth_values_tdep(time, radius, theta, phi, nmax=13, grid=True, deriv=0) B_radius = np.ravel(B_radius, order='F') # ravel column-major B_theta = np.ravel(B_theta, order='F') B_phi = np.ravel(B_phi, order='F') # load matfile test = load_matfile(MATFILE_PATH, 'test_surface_field') B_radius_mat = np.ravel(test['B_radius']) B_theta_mat = np.ravel(test['B_theta']) B_phi_mat = np.ravel(test['B_phi']) for component in ['B_radius', 'B_theta', 'B_phi']: res = np.abs(eval(component) - eval('_'.join((component, 'mat')))) print(' -------------------') print(f' {component}:') print(' MAE =', np.mean(res), 'nT') print(' RMSE =', np.sqrt(np.mean(res**2)), 'nT') print(' Max Error =', np.amax(res), 'nT') print(' Min Error =', np.amin(res), 'nT') self.assertIsNone(np.testing.assert_allclose(B_radius, B_radius_mat)) self.assertIsNone(np.testing.assert_allclose(B_theta, B_theta_mat)) self.assertIsNone(np.testing.assert_allclose(B_phi, B_phi_mat))
def test_sv_timeseries(self): # some observatory location radius = R_REF theta = 90 - 14.308 phi = -16.950 model = cp.load_CHAOS_matfile(CHAOS_PATH) time = np.linspace(model.model_tdep.breaks[0], model.model_tdep.breaks[-1], num=1000) B_radius, B_theta, B_phi = model.synth_values_tdep(time, radius, theta, phi, nmax=16, deriv=1) # load matfile test = load_matfile(MATFILE_PATH, 'test_sv_timeseries') B_radius_mat = np.ravel(test['B_radius']) B_theta_mat = np.ravel(test['B_theta']) B_phi_mat = np.ravel(test['B_phi']) for component in ['B_radius', 'B_theta', 'B_phi']: res = np.abs(eval(component) - eval('_'.join((component, 'mat')))) print(' -------------------') print(f' {component}:') print(' MAE =', np.mean(res), 'nT') print(' RMSE =', np.sqrt(np.mean(res**2)), 'nT') print(' Max Error =', np.amax(res), 'nT') print(' Min Error =', np.amin(res), 'nT') self.assertIsNone(np.testing.assert_allclose(B_radius, B_radius_mat)) self.assertIsNone(np.testing.assert_allclose(B_theta, B_theta_mat)) self.assertIsNone(np.testing.assert_allclose(B_phi, B_phi_mat))
def declination(glat, glon, radius, year): """ Calculates the Declination angle of the each data point from the CHAOS model Parameters ---------- glat : numpy.ndarray (degrees) geographic lattitude. glon : numpy.ndarray (degrees) geographic longitude. radius : float, optional the radius from the centre of the earth to the points. year : int year. Returns ------- numpy.ndarray (radians) Declination used to rotate the magnetometer vectors. """ pysymmetry_path = '/Home/siv32/zef014/' if pysymmetry_path not in sys.path: sys.path.append(pysymmetry_path) sys.path.insert(1, '/Home/siv32/zef014/pysymmetry/src/geodesy.py') sys.path.append('/Home/siv32/zef014/pysymmetry/src/') import geodesy colat, radius, _, _ = geodesy.geod2geoc(glat, 0, 0, 0) import numpy as np from chaosmagpy import load_CHAOS_matfile from chaosmagpy.data_utils import mjd2000 time = mjd2000(year, 1, 1) # modified Julian date # load the CHAOS model model = load_CHAOS_matfile(pysymmetry_path + '/pysymmetry/models/' + 'CHAOS-7.mat') B_radius_core, B_theta_core, B_phi_core = model.synth_values_tdep(time, radius, colat, glon) B_radius_crust, B_theta_crust, B_phi_crust = model.synth_values_static(radius, colat, glon) Br, Bth, Beast = B_radius_core + B_radius_crust, B_theta_core + B_theta_crust, B_phi_core + B_phi_crust # convert from gecentric to geodetic: glat, h, Bnorth, B_down = geodesy.geoc2geod(colat, radius, Bth, Br) return np.arctan(Beast/Bnorth)
def test_save_shcfile(self): seq = np.random.randint(0, 10, size=(5,)) filename = 'CHAOS-tmp_' + ''.join([str(a) for a in seq]) + '.shc' filepath = os.path.join(ROOT, filename) model_mat = load_CHAOS_matfile(CHAOS_PATH) print(' On time-dependent part:') print(' ', end='') model_mat.save_shcfile(filepath, model='tdep') coeffs_tdep_mat = model_mat.model_tdep.coeffs model_shc = load_CHAOS_shcfile(filepath) coeffs_tdep_shc = model_shc.model_tdep.coeffs print(' Max Error =', np.amax(np.abs(coeffs_tdep_shc - coeffs_tdep_mat))) np.testing.assert_allclose( coeffs_tdep_shc, coeffs_tdep_mat, rtol=1e-2, atol=1e-3) print(' On static part:') print(' ', end='') model_mat.save_shcfile(filepath, model='static') coeffs_static_mat = model_mat.model_static.coeffs model_shc = load_CHAOS_shcfile(filepath) coeffs_static_shc = model_shc.model_static.coeffs print(' Max Error =', np.amax(np.abs(coeffs_static_shc - coeffs_static_mat))) np.testing.assert_allclose( coeffs_static_shc, coeffs_static_mat, rtol=1e-2, atol=1e-3) print(f" Removing file {filepath}") os.remove(filepath)
def test_complete_forward(self): n_data = int(300) t_start = -200.0 t_end = 6000.0 time = np.linspace(t_start, t_end, num=n_data) radius = R_REF * np.ones(time.shape) theta = np.linspace(1, 179, num=n_data) phi = np.linspace(-180, 179, num=n_data) model = load_CHAOS_matfile(CHAOS_PATH) B_radius, B_theta, B_phi = model(time, radius, theta, phi) # load matfile test = load_matfile(MATFILE_PATH, 'test_complete_forward') B_radius_mat = np.ravel(test['B_radius']) B_theta_mat = np.ravel(test['B_theta']) B_phi_mat = np.ravel(test['B_phi']) for component in ['B_radius', 'B_theta', 'B_phi']: res = np.abs(eval(component) - eval('_'.join((component, 'mat')))) print(' -------------------') print(f' {component}:') print(' MAE =', np.mean(res), 'nT') print(' RMSE =', np.sqrt(np.mean(res**2)), 'nT') print(' Max Error =', np.amax(res), 'nT') print(' Min Error =', np.amin(res), 'nT') self.assertIsNone(np.testing.assert_allclose( B_radius, B_radius_mat, rtol=1e-7, atol=1e-2)) self.assertIsNone(np.testing.assert_allclose( B_theta, B_theta_mat, rtol=1e-7, atol=1e-2)) self.assertIsNone(np.testing.assert_allclose( B_phi, B_phi_mat, rtol=1e-7, atol=1e-2))
def test_load_CHAOS(self): cp.load_CHAOS_matfile(CHAOS_PATH) cp.load_CHAOS_shcfile(CHAOS_PATH_SHC) cp.chaos.BaseModel.from_shc(CHAOS_PATH_SHC)