def mms_pgs_mphigeo(mag_temp, pos_temp): """ Generates the 'mphigeo' transformation matrix """ pos_data = get_data(pos_temp) if pos_data is None: logging.error('Error with position data') return # the following is heisted from the IDL version # transformation to generate other_dim dim for mphigeo from thm_fac_matrix_make # All the conversions to polar and trig simplifies to this. # But the reason the conversion is why this is the conversion that is done, is lost on me. # The conversion swaps the x & y components of position, reflects over x=0,z=0 then projects into the xy plane pos_conv = np.stack( (-pos_data.y[:, 1], pos_data.y[:, 0], np.zeros(len(pos_data.times)))) pos_conv = np.transpose(pos_conv, [1, 0]) store_data(pos_temp, data={'x': pos_data.times, 'y': pos_conv}) # transform into GSE because the particles are in GSE cotrans(name_in=pos_temp, name_out=pos_temp, coord_in='gei', coord_out='gse') # create orthonormal basis set z_basis = tnormalize(mag_temp, return_data=True) x_basis = tcrossp(z_basis, pos_temp, return_data=True) x_basis = tnormalize(x_basis, return_data=True) y_basis = tcrossp(z_basis, x_basis, return_data=True) return (x_basis, y_basis, z_basis)
def mms_pgs_make_fac(times, mag_tvar_in, pos_tvar_in, fac_type='mphigeo'): """ Generate the field aligned coordinate transformation matrix """ if not data_exists(mag_tvar_in): logging.error('Magnetic field variable not found: "' + mag_tvar_in + '"; skipping field-aligned outputs') return if not data_exists(pos_tvar_in): logging.error('Position variable not found: "' + pos_tvar_in + '"; skipping field-aligned outputs') return valid_types = ['mphigeo', 'phigeo', 'xgse'] if fac_type not in valid_types: logging.error( 'Invalid FAC type; valid types: "mphigeo", "phigeo", "xgse"') return cotrans(name_in=pos_tvar_in, name_out=pos_tvar_in, coord_in='gse', coord_out='gei') mag_temp = mag_tvar_in + '_pgs_temp' pos_temp = pos_tvar_in + '_pgs_temp' # first, we need to interpolate the magnetic field and position # variables to the time stamps of the particle data (times) tinterpol(mag_tvar_in, times, newname=mag_temp) tinterpol(pos_tvar_in, times, newname=pos_temp) if fac_type == 'mphigeo': basis = mms_pgs_mphigeo(mag_temp, pos_temp) elif fac_type == 'phigeo': basis = mms_pgs_phigeo(mag_temp, pos_temp) elif fac_type == 'xgse': basis = mms_pgs_xgse(mag_temp, pos_temp) fac_output = np.zeros((len(times), 3, 3)) fac_output[:, 0, :] = basis[0] fac_output[:, 1, :] = basis[1] fac_output[:, 2, :] = basis[2] return fac_output
def test_cotrans_igrf(self): """Test GSE->GSM and IGRF.""" del_data() d = [[245.0, -102.0, 251.0], [775.0, 10.0, -10], [121.0, 545.0, -1.0], [304.65, -205.3, 856.1], [464.34, -561.55, -356.22]] t = [1577112800, 1577308800, 1577598800, 1577608800, 1577998800] name_out = "tname_out" cotrans(name_out=name_out, time_in=t, data_in=d, coord_in="gse", coord_out="gsm") in_len = len(t) dout = get_data(name_out) out_len = len(dout[0]) gsm = dout[1][1] res = [775.0, 11.70325822, -7.93937951] self.assertTrue(out_len == in_len) self.assertTrue(abs(gsm[0] - res[0]) <= 1e-6) self.assertTrue(abs(gsm[1] - res[1]) <= 1e-6) self.assertTrue(abs(gsm[2] - res[2]) <= 1e-6)
def test_cotrans(self): """Test cotrans.py GEI->GEO with Themis data.""" del_data() trange = ['2010-02-25/00:00:00', '2010-02-25/23:59:59'] probe = 'a' name_in = "tha_pos" name_out = "tha_pos_new_geo" pyspedas.themis.state(probe=probe, trange=trange, time_clip=True, varnames=[name_in]) cotrans(name_in=name_in, name_out=name_out, coord_in="gei", coord_out="geo") din = get_data(name_in) in_len = len(din[0]) dout = get_data(name_out) out_len = len(dout[0]) cotrans(name_in=name_in, coord_in="gei", coord_out="geo") self.assertTrue(out_len == in_len)
def test_cotrans_geigsm(self): """Test daisy chain of multiple transofrmations, GEI->GSE->GSM.""" del_data() d = [[245.0, -102.0, 251.0], [775.0, 10.0, -10], [121.0, 545.0, -1.0], [304.65, -205.3, 856.1], [464.34, -561.55, -356.22]] t = [1577112800, 1577308800, 1577598800, 1577608800, 1577998800] name_out = "tname_out" cotrans(name_out=name_out, time_in=t, data_in=d, coord_in="gei", coord_out="gsm") in_len = len(t) dout = get_data(name_out) out_len = len(dout[0]) gsm = dout[1][1] res = [4.59847513e+01, 7.62303493e+02, 1.32679267e+02] self.assertTrue(out_len == in_len) self.assertTrue(abs(gsm[0] - res[0]) <= 1e-6) self.assertTrue(abs(gsm[1] - res[1]) <= 1e-6) self.assertTrue(abs(gsm[2] - res[2]) <= 1e-6)
def test_cotrans_j2000(self): """Test GEI->J2000 and J2000 params.""" del_data() d = [[245.0, -102.0, 251.0], [775.0, 10.0, -10], [121.0, 545.0, -1.0], [304.65, -205.3, 856.1], [464.34, -561.55, -356.22]] t = [1577112800, 1577308800, 1577598800, 1577608800, 1577998800] name_out = "tname_out" cotrans(name_out=name_out, time_in=t, data_in=d, coord_in="gei", coord_out="j2000") in_len = len(t) dout = get_data(name_out) out_len = len(dout[0]) j2000 = dout[1][1] res = [775.01595209, 6.59521058, -11.47942543] self.assertTrue(out_len == in_len) self.assertTrue(abs(j2000[0] - res[0]) <= 1e-6) self.assertTrue(abs(j2000[1] - res[1]) <= 1e-6) self.assertTrue(abs(j2000[2] - res[2]) <= 1e-6)
def mms_cotrans_lmn(name_in, name_out, gsm=False, gse=False, probe=None, data_rate='srvy'): ''' Tranforms MMS vector fields from GSM coordinates to LMN (boundary-normal) coordinates using the Shue et al., 1998 magnetopause model Input ------ name_in: str Name of the input tplot variable name_out: str Name of the output tplot variable Parameters ----------- gsm: bool Flag to indicate the input data are in GSM coordinates gse: bool Flag to indicate the input data are in GSE coordinates; note: the input data will be transformed to GSM prior to transforming to LMN probe: str Spacecraft probe #; if not specified, the routine attempts to extract from the input variable name data_rate: str Data rate of the input data; default is 'srvy' Returns -------- Name of the variable containing the data in LMN coordinates. ''' data_in = get_data(name_in) metadata_in = get_data(name_in, metadata=True) if data_in is None: logging.error('Error reading tplot variable: ' + name_in) return None data_in_coord = cotrans_get_coord(name_in).lower() if data_in_coord != 'gse' and data_in_coord != 'gsm' and not gse and not gsm: logging.error( 'Please specify the coordinate system of the input data.') return # we'll need the probe if it's not specified via keyword if probe is None: sc_id = name_in.split('_')[0] if sc_id != '': probe = sc_id[-1] if probe not in ['1', '2', '3', '4']: logging.error( 'Error, probe not found; please specify the probe via the "probe" keyword.' ) return # load the spacecraft position data mec_vars = mec(trange=[min(data_in.times), max(data_in.times)], probe=probe, data_rate=data_rate) # interpolate the position data to the input data tinterp_vars = tinterpol('mms' + probe + '_mec_r_gsm', name_in, newname='mms' + probe + '_mec_r_gsm_interp') pos_data = get_data('mms' + probe + '_mec_r_gsm_interp') # we'll need the input data in GSM coordinates if data_in_coord != 'gsm': cotrans_out = cotrans(name_in, name_in + '_gsm', coord_out='gsm') data_in = get_data(name_in + '_gsm') swdata = solarwind_load([min(data_in.times), max(data_in.times)]) logging.info( 'Transforming GSM -> LMN; this may take several minutes, depending on the size of the input.' ) Blmn = gsm2lmn(data_in.times, pos_data.y, data_in.y, swdata=swdata) saved = store_data(name_out, data={ 'x': data_in.times, 'y': Blmn }, attr_dict=metadata_in) if saved: options(name_out, 'legend_names', ['L', 'M', 'N']) return name_out else: logging.error('Problem creating tplot variable.')
def dsi2j2000(name_in=None, name_out=None, no_orb=False, J20002DSI=False, noload=False): """ This function transform a time series data between the DSI and J2000 coordinate systems Parameters: name_in : str input tplot variable to be transformed name_out : str Name of the tplot variable in which the transformed data is stored J20002DSI : bool Set to transform data from J2000 to DSI. If not set, it transforms data from DSI to J2000. Returns: None """ if (name_in is None) or (name_in not in tplot_names(quiet=True)): print('Input of Tplot name is undifiend') return if name_out is None: print('Tplot name for output is undifiend') name_out = 'result_of_dsi2j2000' # prepare for transformed Tplot Variable reload = not noload dl_in = get_data(name_in, metadata=True) get_data_array = get_data(name_in) time_array = get_data_array[0] time_length = time_array.shape[0] dat = get_data_array[1] # Get the SGI axis by interpolating the attitude data dsiz_j2000 = erg_interpolate_att(name_in, noload=noload)['sgiz_j2000'] # Sun direction in J2000 sundir = np.array([[1., 0., 0.]]*time_length) if no_orb: store_data('sundir_gse', data={'x': time_array, 'y': sundir}) else: # Calculate the sun directions from the instantaneous satellite locations if reload: tr = get_timespan(name_in) orb(trange=time_string([tr[0] - 60., tr[1] + 60.])) tinterpol('erg_orb_l2_pos_gse', time_array) scpos = get_data('erg_orb_l2_pos_gse-itrp')[1] sunpos = np.array([[1.496e+08, 0., 0.]]*time_length) sundir = sunpos - scpos store_data('sundir_gse', data={'x': time_array, 'y': sundir}) tnormalize('sundir_gse', newname='sundir_gse') # Derive DSI-X and DSI-Y axis vectors in J2000. # The elementary vectors below are the definition of DSI. The detailed relationship # between the spin phase, sun pulse timing, sun direction, and the actual subsolar point # on the spining s/c body should be incorporated into the calculation below. if reload: cotrans(name_in='sundir_gse', name_out='sundir_j2000', coord_in='gse', coord_out='j2000') sun_j2000 = get_data('sundir_j2000') dsiy = tcrossp(dsiz_j2000['y'], sun_j2000[1], return_data=True) dsix = tcrossp(dsiy, dsiz_j2000['y'], return_data=True) dsix_j2000 = {'x': time_array, 'y': dsix} dsiy_j2000 = {'x': time_array, 'y': dsiy} if not J20002DSI: print('DSI --> J2000') mat = cart_trans_matrix_make( dsix_j2000['y'], dsiy_j2000['y'], dsiz_j2000['y']) j2000x_in_dsi = np.dot(mat, np.array([1., 0., 0.])) j2000y_in_dsi = np.dot(mat, np.array([0., 1., 0.])) j2000z_in_dsi = np.dot(mat, np.array([0., 0., 1.])) mat = cart_trans_matrix_make( j2000x_in_dsi, j2000y_in_dsi, j2000z_in_dsi) dat_new = np.einsum("ijk,ik->ij", mat, dat) else: print('J2000 --> DSI') mat = cart_trans_matrix_make( dsix_j2000['y'], dsiy_j2000['y'], dsiz_j2000['y']) dat_new = np.einsum("ijk,ik->ij", mat, dat) store_data(name_out, data={'x': time_array, 'y': dat_new}, attr_dict=dl_in) options(name_out, 'ytitle', '\n'.join(name_out.split('_')))
def test_all_cotrans(self): """Test all cotrans pairs. Apply transformation, then inverse transformation and compare. """ cotrans() all_cotrans = ['gei', 'geo', 'j2000', 'gsm', 'mag', 'gse', 'sm'] d = [[245.0, -102.0, 251.0], [775.0, 10.0, -10], [121.0, 545.0, -1.0], [304.65, -205.3, 856.1], [464.34, -561.55, -356.22]] dd1 = d[1] t = [1577112800, 1577308800, 1577598800, 1577608800, 1577998800] in_len = len(t) name1 = "name1" name2 = "name2" count = 0 # Test non-existent system. cotrans(name_out=name1, time_in=t, data_in=d, coord_in="coord_in", coord_out="coord_out") # Test empty data. cotrans(name_out=name1, time_in=t, data_in=[], coord_in="gei", coord_out="geo") cotrans(time_in=t, data_in=d, coord_in="gse", coord_out="gsm") # Test all combinations. for coord_in in all_cotrans: for coord_out in all_cotrans: count += 1 del_data() cotrans(name_out=name1, time_in=t, data_in=d, coord_in=coord_in, coord_out=coord_out) dout = get_data(name1) out_len1 = len(dout[0]) self.assertTrue(out_len1 == in_len) # Now perform inverse transformation. cotrans(name_in=name1, name_out=name2, coord_in=coord_out, coord_out=coord_in) dout2 = get_data(name2) out_len2 = len(dout2[0]) dd2 = dout2[1][1] print(count, "--- in:", coord_in, "out:", coord_out) # print(dout[1][1]) # print(dd2) self.assertTrue(out_len2 == in_len) self.assertTrue(abs(dd1[0] - dd2[0]) <= 1e-6) self.assertTrue(abs(dd1[1] - dd2[1]) <= 1e-6) self.assertTrue(abs(dd1[2] - dd2[2]) <= 1e-6)