def test_convert_latlon_arr_failure(self, in_rep, in_irep, msg): in_args = np.array( [self.lat_in, self.lon_in, self.alt_in, self.dtime, "G2A"], dtype=object) in_args[in_irep] = in_rep with pytest.raises(ValueError, match=msg): aacgmv2.convert_latlon_arr(*in_args)
def test_warning_single_loc_in_arr(self): """ Test that user is warned they should be using simpler routine""" self.lwarn = u"for a single location, consider using" aacgmv2.convert_latlon_arr(60, 0, 300, dt.datetime(2015,1,1,0,0,0)) self.lout = self.log_capture.getvalue() if self.lout.find(self.lwarn) < 0: raise AssertionError()
def to_AACGM(self, append_mlt=False, **kwargs): import aacgmv2 as aacgm from geospacelab.cs._aacgm import AACGM method_code = 'G2A' ut_type = type(self.ut) if ut_type is list: uts = np.array(self.ut) elif ut_type is np.ndarray: uts = self.ut lat_shape = self.coords.lat.shape lon_shape = self.coords.lon.shape if issubclass(self.ut.__class__, datetime.datetime): lat, lon, r = aacgm.convert_latlon_arr( in_lat=self.coords.lat.flatten(), in_lon=self.coords.lon.flatten(), height=self.coords.height.flatten(), dtime=self.ut, method_code=method_code) else: if uts.shape[0] != self.coords.lat.shape[0]: mylog.StreamLogger.error( "Datetimes must have the same length as cs!") return lat = np.empty_like(self.coords.lat) lon = np.empty_like(self.coords.lon) r = np.empty_like(self.coords.lat) for ind_dt, dt in enumerate(uts.flatten()): # print(ind_dt, dt, cs.lat[ind_dt, 0]) lat[ind_dt], lon[ind_dt], r[ind_dt] = aacgm.convert_latlon_arr( in_lat=self.coords.lat[ind_dt], in_lon=self.coords.lon[ind_dt], height=self.coords.height[ind_dt], dtime=dt, method_code=method_code) cs_new = AACGM(coords={ 'lat': lat.reshape(lat_shape), 'lon': lon.reshape(lon_shape), 'r': r.reshape(lat_shape), 'r_unit': 'R_E' }, ut=self.ut) if append_mlt: lon = lon.flatten() if issubclass(self.ut.__class__, datetime.datetime): mlt = aacgm.convert_mlt(lon, self.ut) else: lon = cs_new['lon'] mlt = np.empty_like(lon) for ind_dt, dt in enumerate(self.ut.flatten()): mlt[ind_dt] = aacgm.convert_mlt(lon[ind_dt], dt) cs_new['mlt'] = mlt.reshape(lon_shape) return cs_new
def test_convert_latlon_arr_datetime_date(self): """Test array latlon conversion with date and datetime input""" (self.lat_out, self.lon_out, self.r_out) = aacgmv2.convert_latlon_arr([60], [0], [300], self.ddate) lat_2, lon_2, r_2 = aacgmv2.convert_latlon_arr([60], [0], [300], self.dtime) if self.lat_out != lat_2: raise AssertionError() if self.lon_out != lon_2: raise AssertionError() if self.r_out != r_2: raise AssertionError() del lat_2, lon_2, r_2
def test_convert_latlon_arr_arr_mult_and_single_element(self): """Test latlon conversion for arrays with multiple and single vals""" self.out = aacgmv2.convert_latlon_arr(np.array(self.lat_in), np.array([self.lon_in[0]]), np.array(self.alt_in), self.dtime, self.method) self.evaluate_output()
def test_convert_latlon_arr_arr(self): """Test array latlon conversion for array input""" self.out = aacgmv2.convert_latlon_arr(np.array(self.lat_in), np.array(self.lon_in), np.array(self.alt_in), self.dtime, self.method) self.evaluate_output()
def test_convert_latlon_arr_list_single(self): """Test array latlon conversion for list input of single values""" self.out = aacgmv2.convert_latlon_arr([self.lat_in[0]], [self.lon_in[0]], [self.alt_in[0]], self.dtime, self.method) self.evaluate_output(ind=0)
def get_flux_geo(dt): atypes = ['diff', 'mono', 'wave'] jtype = 'electron energy flux' fluxgrid = None # Iterate over types for atype in atypes: print("Generating fluxes for {} type aurora".format(atype), end="\r") # create estimator estimator = ovation_prime.FluxEstimator(atype, jtype) mlatgrid, mltgrid, fg = estimator.get_flux_for_time(dt) # Create fluxgrid in the first iteration if fluxgrid is None: fluxgrid = np.zeros(fg.shape) # Add to flux fluxgrid += fg print("Converting to GEO coordinates", end="\r") # Convert mag local time to magnetic longitude mlongrid = aacgmv2.convert_mlt(mltgrid, dt, m2a=True) # Convert CGM to GEO # altitude of aurora ~ 300 km aur_z = 300 lat_grid, lon_grid, r_grid = aacgmv2.convert_latlon_arr( mlatgrid, mlongrid, #inputs aur_z, dt, u'A2G') # aurora height, datetime, and conversion mode return lat_grid, lon_grid, fluxgrid
def test_convert_latlon_arr_arr(self): """Test array latlon conversion for array input""" (self.lat_out, self.lon_out, self.r_out) = aacgmv2.convert_latlon_arr(np.array([60, 61]), np.array([0, 0]), np.array([300, 300]), self.dtime) if not isinstance(self.lat_out, np.ndarray): raise AssertionError() if not isinstance(self.lon_out, np.ndarray): raise AssertionError() if not isinstance(self.r_out, np.ndarray): raise AssertionError() if not (self.r_out.shape == self.lon_out.shape and self.lat_out.shape == self.r_out.shape and self.r_out.shape == (2,)): raise AssertionError() np.testing.assert_allclose(self.lat_out, [58.22577090, 59.31860933], rtol=1e-4) np.testing.assert_allclose(self.lon_out, [81.16846959, 81.61398933], rtol=1e-4) np.testing.assert_allclose(self.r_out, [1.04566346, 1.04561304], rtol=1e-4)
def test_convert_latlon_arr_mult_arr_unequal(self): """Test array latlon conversion for unequal sized multi-dim array""" (self.lat_out, self.lon_out, self.r_out) = aacgmv2.convert_latlon_arr(np.array([[60, 61, 62], [63, 64, 65]]), np.array([0]), np.array([300]), self.dtime) if not isinstance(self.lat_out, np.ndarray): raise AssertionError() if not isinstance(self.lon_out, np.ndarray): raise AssertionError() if not isinstance(self.r_out, np.ndarray): raise AssertionError() if not (self.r_out.shape == self.lon_out.shape and self.lat_out.shape == self.r_out.shape and self.r_out.shape == (2, 3)): raise AssertionError() np.testing.assert_allclose(self.lat_out, [[58.2257709, 59.3186093, 60.4039740], [61.4819893, 62.5527635, 63.6163840]], rtol=1e-4) np.testing.assert_allclose(self.lon_out, [[81.1684696, 81.6139893, 82.0871880], [82.5909499, 83.1285895, 83.7039272]], rtol=1e-4) np.testing.assert_allclose(self.r_out, [[1.04566346, 1.04561304, 1.04556369], [1.04551548, 1.04546847, 1.04542272]], rtol=1e-4)
def test_convert_latlon_arr_arr_single(self): """Test array latlon conversion for array input of shape (1,)""" self.out = aacgmv2.convert_latlon_arr(np.array([self.lat_in[0]]), np.array([self.lon_in[0]]), np.array([self.alt_in[0]]), self.dtime, self.method) self.evaluate_output(ind=0)
def test_convert_latlon_arr_maxalt_failure(self): """For an array, test failure for an altitude too high for coefficients""" (self.lat_out, self.lon_out, self.r_out) = aacgmv2.convert_latlon_arr([60], [0], [2001], self.dtime) if not np.all([np.isnan(self.lat_out), np.isnan(self.lon_out), np.isnan(self.r_out)]): raise AssertionError()
def test_convert_latlon_arr_clip(self): """Test array latlon conversion with latitude clipping""" self.lat_in = [90.01, -90.01] self.ref = [[83.92352053, -74.98110552], [170.1381271, 17.98164313], [1.04481924, 1.04481924]] self.out = aacgmv2.convert_latlon_arr(self.lat_in, self.lon_in, self.alt_in, self.ddate, self.method) self.evaluate_output()
def test_convert_latlon_arr_badidea(self, method_code, alt, ref): """Test array latlon conversion for BADIDEA""" self.out = aacgmv2.convert_latlon_arr(self.lat_in[0], self.lon_in[0], [alt], self.dtime, method_code) assert len(self.out) == len(ref) assert [isinstance(oo, np.ndarray) and len(oo) == 1 for oo in self.out] for i, oo in enumerate(self.out): np.testing.assert_allclose(oo, [ref[i]], rtol=self.rtol)
def test_convert_latlon_arr_badidea(self): """Test array latlon conversion for BADIDEA""" code = "G2A | BADIDEA" (self.lat_out, self.lon_out, self.r_out) = aacgmv2.convert_latlon_arr([60], [0], [3000], self.dtime, code) np.testing.assert_allclose(self.lat_out, [64.35677791], rtol=1e-4) np.testing.assert_allclose(self.lon_out, [83.30272053], rtol=1e-4) np.testing.assert_allclose(self.r_out, [1.46944431], rtol=1e-4)
def test_convert_latlon_arr_single_val(self): """Test array latlon conversion for a single value""" self.out = aacgmv2.convert_latlon_arr(self.lat_in[0], self.lon_in[0], self.alt_in[0], self.dtime, self.method) assert len(self.out) == len(self.ref) assert [isinstance(oo, np.ndarray) and len(oo) == 1 for oo in self.out] for i, oo in enumerate(self.out): np.testing.assert_allclose(oo, [self.ref[i][0]], rtol=self.rtol)
def solar_conductance(self, dt, mlats, mlts, return_f107=False): """ Estimate the solar conductance using methods from: Cousins, E. D. P., T. Matsuo, and A. D. Richmond (2015), Mapping high-latitude ionospheric electrodynamics with SuperDARN and AMPERE --which cites-- Asgeir Brekke, Joran Moen, Observations of high latitude ionospheric conductances Maybe is not good for SZA for southern hemisphere? Don't know Going to use absolute value of latitude because that's what's done in Cousins IDL code. """ # Find the closest hourly f107 value # to the current time to specifiy the conductance f107 = ovation_utilities.get_daily_f107(dt) if hasattr(self, '_f107'): log.warning( ('Warning: Overriding real F107 {0}'.format(f107) + 'with secret instance property _f107 {0}'.format(self._f107) + 'this is for debugging and will not' + 'produce accurate results for a particular date.')) f107 = self._f107 # print "F10.7 = %f" % (f107) # Convert from magnetic to geocentric using the AACGMv2 python library flatmlats, flatmlts = mlats.flatten(), mlts.flatten() flatmlons = aacgmv2.convert_mlt(flatmlts, dt, m2a=True) try: glats, glons = aacgmv2.convert(flatmlats, flatmlons, 110. * np.ones_like(flatmlats), date=dt, a2g=True, geocentric=False) except AttributeError: # convert method was deprecated glats, glons, r = aacgmv2.convert_latlon_arr(flatmlats, flatmlons, 110., dt, method_code='A2G') sigp, sigh = brekke_moen_solar_conductance(dt, glats, glons, f107) sigp_unflat = sigp.reshape(mlats.shape) sigh_unflat = sigh.reshape(mlats.shape) if return_f107: return sigp_unflat, sigh_unflat, f107 else: return sigp_unflat, sigh_unflat
def test_convert_latlon_arr_datetime_date(self): """Test array latlon conversion with date and datetime input""" self.out = aacgmv2.convert_latlon_arr(self.lat_in, self.lon_in, self.alt_in, self.ddate, self.method) assert len(self.out) == len(self.ref) assert [isinstance(oo, np.ndarray) and len(oo) == len(self.ref[i]) for i, oo in enumerate(self.out)] for i, oo in enumerate(self.out): np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
def test_convert_latlon_arr_arr_mix(self): """Test array latlon conversion for mixed type with an array""" self.out = aacgmv2.convert_latlon_arr(np.array(self.lat_in), self.lon_in[0], self.alt_in[0], self.dtime, self.method) assert len(self.out) == len(self.ref) assert [isinstance(oo, np.ndarray) and len(oo) == len(self.ref[i]) for i, oo in enumerate(self.out)] for i, oo in enumerate(self.out): np.testing.assert_allclose(oo, self.ref[i], rtol=self.rtol)
def test_convert_latlon_arr_location_failure(self): """Test array latlon conversion with a bad location""" with warnings.catch_warnings(): # Causes all warnings to be surpressed warnings.simplefilter("ignore") # Trigger a warning self.out = aacgmv2.convert_latlon_arr([0], [0], [0], self.dtime, "") # Test the output assert len(self.out) == len(self.ref) assert np.any(~np.isfinite(np.array(self.out)))
def test_warning_below_ground_convert_latlon_arr(self): """ Test that a warning is issued if altitude is below zero""" import logbook lwarn = u"conversion not intended for altitudes < 0 km" with logbook.TestHandler() as handler: (self.lat_out, self.lon_out, self.r_out) = aacgmv2.convert_latlon_arr([60], [0], [-1], self.dtime) if not handler.has_warning(lwarn): raise AssertionError() handler.close()
def test_convert_latlon_arr_location_failure(self): """Test array latlon conversion with a bad location""" (self.lat_out, self.lon_out, self.r_out) = aacgmv2.convert_latlon_arr([0], [0], [0], self.dtime) if not isinstance(self.lat_out, np.ndarray): raise AssertionError() if not isinstance(self.lon_out, np.ndarray): raise AssertionError() if not isinstance(self.r_out, np.ndarray): raise AssertionError() if not (self.r_out.shape == self.lon_out.shape and self.lat_out.shape == self.r_out.shape and self.r_out.shape == (1,)): raise AssertionError() if not np.all([np.isnan(self.lat_out), np.isnan(self.lon_out), np.isnan(self.r_out)]): raise AssertionError()
def arr_geo_to_mag(latitudes, longitudes, dtime): """ Convert two arrays of latitudes and longitudes of geodetic coords into geomagnetic coords. Numpy array is returned of lat, lons, e.g. [[lat, lat], [lon, lon]] :param latitudes: ndarray :param longitudes: ndarray :param dtime: datetime :return: array with lat and lon in that order """ dtime = _check_time(dtime) _check_arrays(latitudes, longitudes) converted = aacgmv2.convert_latlon_arr(latitudes, longitudes, 100, dtime, method_code='G2A') return converted[0:2]
def convert_geo_to_aacgm(self): # aalat,aalon, aar = \ # aacgm.wrapper.convert_latlon_arr(lat, lon, alt, dt, code='G2A') lat_in = self.variables['SC_GEO_LAT'] lon_in = self.variables['SC_GEO_LON'] alt_in = self.variables['SC_GEO_ALT'] date0 = self.dates[0] dts = self.variables['SC_DATETIME'] aalat, aalon, aar = \ aacgmv2.convert_latlon_arr(lat_in.flatten(), lon_in.flatten(), alt_in.flatten(), date0, code='G2A') mlt = [] arr = aalon.flatten() for ind, dt in enumerate(dts.flatten()): mlt.append(aacgmv2.convert_mlt(arr[ind], dt, m2a=False)) datashape = dts.shape self.variables['SC_AACGM_LAT'] = aalat.reshape(datashape) self.variables['SC_AACGM_LON'] = aalon.reshape(datashape) self.variables['SC_AACGM_R'] = aar.reshape(datashape) self.variables['SC_AACGM_MLT'] = np.array(mlt).reshape(datashape)
def test_convert_latlon_arr_list_single(self): """Test array latlon conversion for list input of single values""" (self.lat_out, self.lon_out, self.r_out) = aacgmv2.convert_latlon_arr([60], [0], [300], self.dtime) if not isinstance(self.lat_out, np.ndarray): raise AssertionError() if not isinstance(self.lon_out, np.ndarray): raise AssertionError() if not isinstance(self.r_out, np.ndarray): raise AssertionError() if not (self.r_out.shape == self.lon_out.shape and self.lat_out.shape == self.r_out.shape and self.r_out.shape == (1,)): raise AssertionError() np.testing.assert_allclose(self.lat_out, [58.2257709], rtol=1e-4) np.testing.assert_allclose(self.lon_out, [81.16846959], rtol=1e-4) np.testing.assert_allclose(self.r_out, [1.04566346], rtol=1e-4)
def make_aurora_cube_multi(ts,ec,k): ''' make the aurora flux image cuves multiprocessing version - ts is a single datetime object into this function - ec the averaged Newell coupling inout - k the counter for the frames for debugging making one frame use: >> make_aurora_cube_multi(tsm[0],ecm[0],0) ''' print('Frame number and time:', k, ' ',ts) ################# (2a) get fluxes mlatN, mltN, fluxNd=de.get_flux_for_time(ts,ec) mlatN, mltN, fluxNm=me.get_flux_for_time(ts,ec) fluxN=fluxNd+fluxNm #+fluxNw #print(ts), print(ec), print(k), print('....') ################ (2b) coordinate conversion magnetic to geographic #Coordinate conversion MLT to AACGM mlon/lat to geographic coordinates mlonN_1D_small=aacgmv2.convert_mlt(mltN[0],ts,m2a=True) mlonN_1D=np.tile(mlonN_1D_small,mlatN.shape[0]) mlatN_1D=np.squeeze(mlatN.reshape(np.size(mltN),1)) (glatN_1D, glonN_1D, galtN) = aacgmv2.convert_latlon_arr(mlatN_1D,mlonN_1D, 100,ts, method_code="A2G") #**check 100 km ############## (2c) interpolate to world map geo_2D=np.vstack((glatN_1D,glonN_1D)).T #stack 2 (7680,) arrays to a single 7680,2 arrays, .T is needed fluxN_1D=fluxN.reshape(7680,1) #also change flux values to 1D array #make a world map grid in latitude 512 pixels, longitude 1024 pixel like NOAA wx,wy= np.mgrid[-90:90:180/512,-180:180:360/1024] aimg= np.squeeze(scipy.interpolate.griddata(geo_2D, fluxN_1D, (wx, wy), method='linear',fill_value=0)) aimg = scipy.ndimage.gaussian_filter(aimg,sigma=(5,7),mode='wrap') #wrap means wrapping at the 180 degree edge #Array variable to be used by all processes ovation_img_multi[512*1024*k:512*1024*(k+1)]=aimg.reshape(512*1024)
def main(): """Entry point for the script""" desc = 'Converts between geographical coordinates, AACGM-v2, and MLT' parser = argparse.ArgumentParser(description=desc) desc = 'for help, run %(prog)s SUBCOMMAND -h' subparsers = parser.add_subparsers(title='Subcommands', prog='aacgmv2', dest='subcommand', description=desc) subparsers.required = True desc = 'convert to/from geomagnetic coordinates. Input file must have lines' desc += 'of the form "LAT LON ALT".' parser_convert = subparsers.add_parser('convert', help=(desc)) desc = 'convert between magnetic local time (MLT) and AACGM-v2 longitude. ' desc += 'Input file must have a single number on each line.' parser_convert_mlt = subparsers.add_parser('convert_mlt', help=(desc)) desc = 'input file (stdin if none specified)' for pp in [parser_convert, parser_convert_mlt]: pp.add_argument('-i', '--input', dest='file_in', metavar='FILE_IN', type=argparse.FileType('r'), default=STDIN, help=desc) pp.add_argument('-o', '--output', dest='file_out', metavar='FILE_OUT', type=argparse.FileType('wb'), default=STDOUT, help='output file (stdout if none specified)') desc = 'date for magnetic field model (1900-2020, default: today)' parser_convert.add_argument('-d', '--date', dest='date', metavar='YYYYMMDD', help=desc) desc = 'invert - convert AACGM to geographic instead of geographic to AACGM' parser_convert.add_argument('-v', '--a2g', dest='a2g', action='store_true', default=False, help=desc) desc = 'use field-line tracing instead of coefficients' parser_convert.add_argument('-t', '--trace', dest='trace', action='store_true', default=False, help=desc) desc = 'automatically use field-line tracing above 2000 km' parser_convert.add_argument('-a', '--allowtrace', dest='allowtrace', action='store_true', default=False, help=desc) desc = 'allow use of coefficients above 2000 km (bad idea!)' parser_convert.add_argument('-b', '--badidea', dest='badidea', action='store_true', default=False, help=desc) desc = 'assume inputs are geocentric with Earth radius 6371.2 km' parser_convert.add_argument('-g', '--geocentric', dest='geocentric', action='store_true', default=False, help=desc) parser_convert_mlt.add_argument('datetime', metavar='YYYYMMDDHHMMSS', help='date and time for conversion') desc = 'invert - convert MLT to AACGM longitude instead of AACGM longitude' desc += ' to MLT' parser_convert_mlt.add_argument('-v', '--m2a', dest='m2a', action='store_true', default=False, help=desc) args = parser.parse_args() array = np.loadtxt(args.file_in, ndmin=2) if args.subcommand == 'convert': date = dt.date.today() if args.date is None else \ dt.datetime.strptime(args.date, '%Y%m%d') code = aacgmv2.convert_bool_to_bit(a2g=args.a2g, trace=args.trace, allowtrace=args.allowtrace, badidea=args.badidea, geocentric=args.geocentric) lats, lons, alts = aacgmv2.convert_latlon_arr(array[:, 0], array[:, 1], array[:, 2], dtime=date, method_code=code) np.savetxt(args.file_out, np.column_stack((lats, lons, alts)), fmt='%.8f') elif args.subcommand == 'convert_mlt': dtime = dt.datetime.strptime(args.datetime, '%Y%m%d%H%M%S') out = np.array(aacgmv2.convert_mlt(array[:, 0], dtime, m2a=args.m2a)) if len(out.shape) == 0: out = np.array([out]) np.savetxt(args.file_out, out, fmt='%.8f')
def make_aurora_cube(ts, ec, diff, mono): ''' single processor version ''' #this is the array with the final world maps for each timestep ovation_img = np.zeros([512, 1024, np.size(ts)]) #make a world map grid in latitude 512 pixels, longitude 1024 pixel like NOAA wx, wy = np.mgrid[-90:90:180 / 512, -180:180:360 / 1024] #if ts is a single not a list, change to list to make it subscriptable if type(ts) != list: ts = [ts] for k in np.arange(0, np.size(ts)): #go through all times print('Frame number and time:', k, ' ', ts[k]) ######################################### (2a) get solar wind startflux = time.time() #sw=oup.calc_avg_solarwind_predstorm(ts[k],l1wind) #make solarwind with averaging over last 4 hours, only for command line #print('Byz =',sw.by[0],sw.bz[0],' nT V =',int(sw.v[0]), 'km/s') #for the Newell coupling Ec, normalized to cycle average, smoothed for high time resolution #print('Ec to cycle average: ',np.round(swav.ec[k]/coup_cycle,1), ' <Ec> =',int(swav.ec[k])) #get fluxes for northern hemisphere mlatN, mltN, fluxNd = diff.get_flux_for_time(ts[k], ec[k]) mlatN, mltN, fluxNm = mono.get_flux_for_time(ts[k], ec[k]) #mlatN, mltN, fluxNw=we.get_flux_for_time(ts[k],inputfile, hemi='N') #wave flux not correct yet fluxN = fluxNd + fluxNm #+fluxNw #endflux=time.time() #print('OVATION: ', np.round(endflux-startflux,2),' sec') #for debugging #making flux images for comparison to OVATION IDL output #change IDL file in this function for flux comparison #oup.global_ovation_flux(mlatN,mltN,fluxNw,ts[0]) #oup.global_ovation_flux(mlatN,mltN,fluxNd,ts[k]) #sys.exit() #if k==3: sys.exit() ##################################### (2b) coordinate conversion magnetic to geographic #Coordinate conversion MLT to AACGM mlon/lat to geographic coordinates #startcoo=time.time() #magnetic coordinates are mltN mlonN in 2D grids #so we need to convert magnetic local time (MLT) to longitude first #extract from mltN first 96 MLTs for 1 latitude bin convert to magnetic longitude mlonN_1D_small = aacgmv2.convert_mlt(mltN[0], ts[k], m2a=True) #copy result 80 times because MLT is same for all latitudes mlonN_1D = np.tile(mlonN_1D_small, mlatN.shape[0]) #this will make a 1D array for the latitudes compatible with the 1D array created above mlatN_1D = np.squeeze(mlatN.reshape(np.size(mltN), 1)) #magnetic coordinates are now mlatN mlonN, convert to geographic (glatN_1D, glonN_1D, galtN) = aacgmv2.convert_latlon_arr(mlatN_1D, mlonN_1D, 100, ts[k], code="A2G") #endcoo = time.time() #print('Coordinates: ', np.round(endcoo-startcoo,2),' sec') ##################################### (2c) interpolate to world map #geographic coordinates are glatN, glonN, electron flux values are fluxN #change shapes from glatN (80, 96) glonN (80, 96) to a single array with 7680,2 #startworld=time.time() #glatN_1D=glatN.reshape(np.size(fluxN),1) #glonN_1D=glonN.reshape(np.size(fluxN),1) geo_2D = np.vstack( (glatN_1D, glonN_1D) ).T #stack 2 (7680,) arrays to a single 7680,2 arrays, .T is needed #smooth small array first - but strange results! #fluxN=scipy.ndimage.gaussian_filter(fluxN,sigma=(5,5)) fluxN_1D = fluxN.reshape(7680, 1) #also change flux values to 1D array #bottleneck, maybe make own interpolation and accelerate with numba #https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.interpolate.griddata.html #interpolate to world grid, and remove 1 dimension with squeeze aimg = np.squeeze( scipy.interpolate.griddata(geo_2D, fluxN_1D, (wx, wy), method='linear', fill_value=0)) #filter large array aimg = scipy.ndimage.gaussian_filter( aimg, sigma=(5, 7), mode='wrap') #wrap means wrapping at the 180 degree edge ovation_img[:, :, k] = aimg #endworld = time.time() #print('World map: ', np.round(endworld-startworld,2),' sec') return ovation_img
def convert(lat, lon, alt, date=None, a2g=False, trace=False, allowtrace=False, badidea=False, geocentric=False): """Converts between geomagnetic coordinates and AACGM coordinates Parameters ------------ lat : (float) Input latitude in degrees N (code specifies type of latitude) lon : (float) Input longitude in degrees E (code specifies type of longitude) alt : (float) Altitude above the surface of the earth in km date : (datetime) Datetime for magnetic field a2g : (bool) True for AACGM-v2 to geographic (geodetic), False otherwise (default=False) trace : (bool) If True, use field-line tracing, not coefficients (default=False) allowtrace : (bool) If True, use trace only above 2000 km (default=False) badidea : (bool) If True, use coefficients above 2000 km (default=False) geocentric : (bool) True for geodetic, False for geocentric w/RE=6371.2 (default=False) Returns ------- lat_out : (float) Output latitude in degrees N lon_out : (float) Output longitude in degrees E """ import aacgmv2 if (np.array(alt).max() > 2000 and not trace and not allowtrace and not badidea): estr = 'coefficients are not valid for altitudes above 2000 km. You' estr += ' must either use field-line tracing (trace=True ' estr += 'or allowtrace=True) or indicate you know this is a bad idea' estr += ' (badidea=True)' logging.error(estr) raise ValueError(estr) # construct a code from the boolian flags bit_code = aacgmv2.convert_bool_to_bit(a2g=a2g, trace=trace, allowtrace=allowtrace, badidea=badidea, geocentric=geocentric) # convert location lat_out, lon_out, _ = aacgmv2.convert_latlon_arr(lat, lon, alt, date, code=bit_code) return lat_out, lon_out
def test_convert_latlon_arr_lat_failure(self): """Test error return for co-latitudes above 90 for an array""" with pytest.raises(AssertionError): aacgmv2.convert_latlon_arr([91, 60, -91], 0, 300, self.dtime)