def test_geo2apex_undefined_warning(): A = Apex(date=2000, refh=10000) with warnings.catch_warnings(record=True) as w: ret = A.geo2apex(0, 0, 0) A.geo2apex(0, 0, 0) assert ret[0] == -9999 assert len(w) == 2 assert issubclass(w[-1].category, UserWarning) assert 'set to -9999 where' in str(w[-1].message)
def test_geo2apex_undefined_warning(): A = Apex(date=2000, refh=10000) with warnings.catch_warnings(record=True) as w: ret = A.geo2apex(0, 0, 0) A.geo2apex(0, 0, 0) assert ret[0] == -9999 assert len(w) == 2 assert issubclass(w[-1].category, UserWarning) assert 'set to -9999 where' in str(w[-1].message)
def test_geo2apex_invalid_lat(): A = Apex(date=2000, refh=300) with pytest.raises(ValueError): A.geo2apex(91, 0, 0) with pytest.raises(ValueError): A.geo2apex(-91, 0, 0) A.geo2apex(90, 0, 0) A.geo2apex(-90, 0, 0) assert_allclose(A.geo2apex(90+1e-5, 0, 0), A.geo2apex(90, 0, 0), rtol=0, atol=1e-8)
def test_geo2apex_invalid_lat(): apex_out = Apex(date=2000, refh=300) with pytest.raises(ValueError): apex_out.geo2apex(91, 0, 0) with pytest.raises(ValueError): apex_out.geo2apex(-91, 0, 0) apex_out.geo2apex(90, 0, 0) apex_out.geo2apex(-90, 0, 0) assert_allclose(apex_out.geo2apex(90 + 1e-5, 0, 0), apex_out.geo2apex(90, 0, 0), rtol=0, atol=1e-8)
def test_convert_geo2mlt(): datetime = dt.datetime(2000, 3, 9, 14, 25, 58) A = Apex(date=2000, refh=300) assert_allclose( A.convert(60, 15, 'geo', 'mlt', height=100, ssheight=2e5, datetime=datetime)[1], A.mlon2mlt(A.geo2apex(60, 15, 100)[1], datetime, ssheight=2e5))
def dovels(self): # read data dat1 = self.h5file.readWholeh5file() # output latitude x=np.arange(self.plats[0][0],self.plats[0][1],self.plats[0][3])[:,np.newaxis] PLAT_OUT=np.concatenate((x,x+self.plats[0][2]),axis=1) if len(self.plats[1])>0: x=np.arange(self.plats[1][0],self.plats[1][1],self.plats[1][3])[:,np.newaxis] x=np.concatenate((x,x+self.plats[1][2]),axis=1) PLAT_OUT=np.concatenate((PLAT_OUT,x),axis=0) # beamcodes BeamCodes=dat1['/']['BeamCodes'] # only use beams that we were asked to use, if empty, # use all beams. num_beamcodes = BeamCodes[:,0].size if len(self.beams2use) > 0: bm_inds = list() available_bms = list(BeamCodes[:,0]) for beamcode in self.beams2use: if beamcode in available_bms: bm_inds.append(available_bms.index(beamcode)) bm_inds = np.array(bm_inds) else: bm_inds = np.arange(0,num_beamcodes) BeamCodes = BeamCodes[bm_inds,:] if self.CorrectVap: IupB=np.where(BeamCodes[:,0]==upBcode)[0] InotUpB=np.where(BeamCodes[:,0]!=upBcode)[0] # geographic k vectors and locations from hdf5 file kn=dat1['/Geomag']['kn'][bm_inds,:] ke=dat1['/Geomag']['ke'][bm_inds,:] kz=dat1['/Geomag']['kz'][bm_inds,:] glat=dat1['/Geomag']['Latitude'][bm_inds,:] glon=dat1['/Geomag']['Longitude'][bm_inds,:] alt=dat1['/Geomag']['Altitude'][bm_inds,:] # find array shape and where nans will be removed arr_shape = glat.shape removed_nans = np.argwhere(np.isnan(glat.ravel())).flatten() # remove nans and flatten array glat = glat[np.isfinite(glat)] glon = glon[np.isfinite(glon)] alt = alt[np.isfinite(alt)] # intialize apex coordinates A = Apex(date=2019) # date should be set by some information in data file # find magnetic latitude and longitude plat, plong = A.geo2apex(glat,glon,alt/1000.) # kvec in geodetic coordinates [e n u] kvec = np.array([ke[np.isfinite(ke)], kn[np.isfinite(kn)], kz[np.isfinite(kz)]]) # apex basis vectors in geodetic coordinates [e n u] f1, f2, f3, g1, g2, g3, d1, d2, d3, e1, e2, e3 = A.basevectors_apex(glat,glon,alt) # find components of k for e1, e2, e3 basis vectors (Laundal and Richmond, 2016 eqn. 60) ke1 = np.einsum('ij,ij->j',kvec,d1) ke2 = np.einsum('ij,ij->j',kvec,d2) ke3 = np.einsum('ij,ij->j',kvec,d3) # reintroduce NANs and reshape the array # find indices where nans should be inserted in new arrays replace_nans = np.array([r-i for i,r in enumerate(removed_nans)]) plat = np.insert(plat,replace_nans,np.nan).reshape(arr_shape) plong = np.insert(plong,replace_nans,np.nan).reshape(arr_shape) ke1 = np.insert(ke1,replace_nans,np.nan).reshape(arr_shape) ke2 = np.insert(ke2,replace_nans,np.nan).reshape(arr_shape) ke3 = np.insert(ke3,replace_nans,np.nan).reshape(arr_shape) # DON'T NEED # convert to magnetic NEU (approximately) kpe = ke1 kpn = -ke2 kpar = -ke3 # geomag # if self.byGeo>0: # geographic # kpn=dat1['/Geomag']['kn'][bm_inds,:] # kpe=dat1['/Geomag']['ke'][bm_inds,:] # kpar=dat1['/Geomag']['kz'][bm_inds,:] # if self.byGeo==2: # plat=dat1['/Geomag']['Latitude'][bm_inds,:] # plong=dat1['/Geomag']['Longitude'][bm_inds,:] # else: # plat=dat1['/Geomag']['MagneticLatitude'][bm_inds,:] # plong=dat1['/Geomag']['MagneticLongitude'][bm_inds,:] # else: # geomagnetic # kpn=dat1['/Geomag']['kpn'][bm_inds,:] # kpe=dat1['/Geomag']['kpe'][bm_inds,:] # kpar=dat1['/Geomag']['kpar'][bm_inds,:] # try: # plat=dat1['/Geomag']['MagneticLatitude'][bm_inds,:] # plong=dat1['/Geomag']['MagneticLongitude'][bm_inds,:] # except: # plat=dat1['/Geomag']['plat'] #??? # plong=dat1['/Geomag']['plong'] #??? Bn=dat1['/Geomag']['Bx'][bm_inds,:] Be=dat1['/Geomag']['By'][bm_inds,:] Bz=dat1['/Geomag']['Bz'][bm_inds,:] Babs=dat1['/Geomag']['Babs'][bm_inds,:] Bmed = np.nanmedian(Babs) for i in range(Bmed.ndim): Bmed=np.nanmedian(Bmed) self.pppE=(np.array(self.ppp).copy()).tolist(); self.pppE[0]*=Bmed; self.pppE[2]*=Bmed; self.pppE[3]*=Bmed self.covarE=(np.array(self.covar).copy()).tolist(); self.covarE[0]*=Bmed*Bmed; self.covarE[1]*=Bmed*Bmed; self.covarE[2]*=Bmed*Bmed # fitted params ht=dat1['/FittedParams']['Altitude'][bm_inds,:] vlos1=dat1['/FittedParams']['Fits'][:,bm_inds,:,0,3] + self.chirp vlos1 = np.swapaxes(vlos1,0,1) dvlos1=dat1['/FittedParams']['Errors'][:,bm_inds,:,0,3] dvlos1 = np.swapaxes(dvlos1,0,1) ne1=dat1['/FittedParams']['Ne'][:,bm_inds,:] # time time1=dat1['/Time']['UnixTime'] doy1=dat1['/Time']['doy'] dtime1=dat1['/Time']['dtime']+(doy1-doy1[0,0])*24.0 MLT=dat1['/Time']['MagneticLocalTimeSite'] yr=dat1['/Time']['Year'] mon=dat1['/Time']['Month'] day=dat1['/Time']['Day'] # low densities I=np.where((ne1 < self.neMin)) vlos1[I]=np.nan dvlos1[I]=np.nan # just do a portion of data if len(self.zoomWhole)!=0: I=np.where((dtime1[:,0]>=self.zoomWhole[0]) & (dtime1[:,1]<=self.zoomWhole[1]))[0] vlos1=vlos1[I] dvlos1=dvlos1[I] time1=time1[I] doy1=doy1[I] dtime1=dtime1[I] MLT=MLT[I] yr=yr[I] mon=mon[I] day=day[I] # title str yr=yr[0,0]; mon=mon[0,0]; day=day[0,0] self.titleString=' %d-%d-%d' % (mon, day, yr) (Nbeams,Nhts)=ht.shape if self.CorrectVap: Nbeams=Nbeams-1 # up B vlos1upB=vlos1[:,IupB[0],:] dvlos1upB=dvlos1[:,IupB[0],:] htupB=ht[IupB[0],:] # not vlos1=vlos1[:,InotUpB,:] dvlos1=dvlos1[:,InotUpB,:] ht=ht[InotUpB,:] kpn=kpn[InotUpB,:] kpe=kpe[InotUpB,:] kpar=kpar[InotUpB,:] plat=plat[InotUpB,:] plong=plong[InotUpB,:] for itimeInt in range(len(self.Time2Integrate)): Time2Integrate = self.Time2Integrate[itimeInt] ofname=self.outputFnames[itimeInt] # output arrays timeout=[] dtimeout=[] MLTtime1=[] done=0 # flag to say when we are done Irec=0 # record counter IIrec=0 # record counter while not done: Irecs=np.where((time1[:,0]>=time1[Irec,0]) & (time1[:,0]<=(time1[Irec,0]+Time2Integrate)))[0] tvlos=vlos1[Irecs,:,:] tdvlos=dvlos1[Irecs,:,:] if self.CorrectVap: vUpB=vlos1upB[Irecs] dvUpB=dvlos1upB[Irecs] for i in range(Nbeams): tupB=np.interpolate.interp1d(np.squeeze(htupB),vUpB,bounds_error=0,fill_value=0.0)(ht[i,:]) tvlos[:,i,:]=tvlos[:,i,:]-tupB*kpar[i,:] tdvlos[:,i,:]=np.sqrt(np.power(tdvlos[:,i,:],2.0)+np.power(dvUpB*kpar[i,:],2.0)) # line of sight velocities and errors vlosin=np.reshape(np.squeeze(tvlos),(Nhts*Nbeams*len(Irecs))) dvlosin=np.reshape(np.squeeze(tdvlos),(Nhts*Nbeams*len(Irecs))) # k vector (this is in mag coords) kin=np.zeros((Nbeams,Nhts,3),dtype=kpn.dtype) # kin[:,:,0]=kpn # kin[:,:,1]=kpe # kin[:,:,2]=kpar kin[:,:,0]=ke1 kin[:,:,1]=ke2 kin[:,:,2]=ke3 kin=np.reshape(np.repeat(kin[np.newaxis,:,:,:],len(Irecs),axis=0),(len(Irecs)*Nhts*Nbeams,3)) # # DON'T NEED # ekin=np.zeros((Nbeams,Nhts,3),dtype=kpn.dtype) # ekin[:,:,0]=(-Be*kpar-Bz*kpe)/Babs**2.0 # ekin[:,:,1]=(Bz*kpn+Bn*kpar)/Babs**2.0 # ekin[:,:,2]=(Bn*kpe-Be*kpn)/Babs**2.0 # ekin=np.reshape(np.repeat(ekin[np.newaxis,:,:,:],len(Irecs),axis=0),(len(Irecs)*Nhts*Nbeams,3)) # magnetic field bin=np.reshape(np.repeat(Babs[np.newaxis,:,:],len(Irecs),axis=0),(len(Irecs)*Nhts*Nbeams)) # mag lat and long, altitude platin=np.reshape(np.repeat(plat[np.newaxis,:,:],len(Irecs),axis=0),(len(Irecs)*Nhts*Nbeams)) plongin=np.reshape(np.repeat(plong[np.newaxis,:,:],len(Irecs),axis=0),(len(Irecs)*Nhts*Nbeams)) htin=np.reshape(np.repeat(ht[np.newaxis,:,:],len(Irecs),axis=0),(len(Irecs)*Nhts*Nbeams)) # compute vectors (plat_out1,Vest,dVest,vVestAll,Nmeas,vchi2)=vvels.compute_velvec2(PLAT_OUT,vlosin,dvlosin,kin,platin,plongin,htin,htmin=self.minAlt*1000,htmax=self.maxAlt*1000,covar=self.covar,p=self.ppp) dVest = np.diagonal(vVestAll,axis1=1,axis2=2) # rotate velocity to get the elecric field # assume magnetic longitude of site PFISR MLON = 267.4 plon_out1 = np.full(plat_out1.shape, 267.4) # find Be3 value at each output bin location Be3, __, __, __ = A.bvectors_apex(plat_out1,plon_out1,300.,coords='apex') # Be3 = np.full(plat_out1.shape,1.0) # set Be3 array to 1.0 - useful for debugging linear algebra # form rotation array R_E = np.einsum('i,jk->ijk',Be3,np.array([[0,-1,0],[1,0,0],[0,0,0]])) # Calculate contravarient components of electric field (Ed1, Ed2, Ed2) Eest = np.einsum('ijk,ik->ij',R_E,Vest) # Calculate electric field covariance matrix (SigE = R_E*SigV*R_E.T) vEestAll = np.einsum('ijk,ikl,iml->ijm',R_E,vVestAll,R_E) dEest = np.diagonal(vEestAll,axis1=1,axis2=2) # # DON'T NEED # (plat_out1,Eest,dEest,vEestAll,Nmeas1,echi2)=vvels.compute_velvec2(PLAT_OUT,vlosin,dvlosin,ekin,platin,plongin,htin,htmin=self.minAlt*1000,htmax=self.maxAlt*1000,covar=self.covarE,p=self.ppp) # Eest[:,-1]*=-1 timeout.append([time1[Irecs[0],0],time1[Irecs[-1],1]]) dtimeout.append([dtime1[Irecs[0],0],dtime1[Irecs[-1],1]]) MLTtime1.append([MLT[Irecs[0],0],MLT[Irecs[-1],1]]) if IIrec>0: while MLTtime1[IIrec][0]<MLTtime1[IIrec-1][0]: MLTtime1[IIrec][0]=MLTtime1[IIrec][0]+24.0 MLTtime1[IIrec][1]=MLTtime1[IIrec][1]+24.0 if IIrec==0: vvels1=Vest[np.newaxis,:,:] dvvels1=dVest[np.newaxis,:,:] varvvels1=vVestAll[np.newaxis,:,:,:] Nall1=Nmeas[np.newaxis,:] chi2 = vchi2[np.newaxis,:] evec1=Eest[np.newaxis,:,:] devec1=dEest[np.newaxis,:,:] varevec1=vEestAll[np.newaxis,:,:,:] else: vvels1=np.concatenate((vvels1,Vest[np.newaxis,:,:]),axis=0) dvvels1=np.concatenate((dvvels1,dVest[np.newaxis,:,:]),axis=0) varvvels1=np.concatenate((varvvels1,vVestAll[np.newaxis,:,:,:]),axis=0) Nall1=np.concatenate((Nall1,Nmeas[np.newaxis,:]),axis=0) chi2 = np.concatenate((chi2,vchi2[np.newaxis,:]),axis=0) evec1=np.concatenate((evec1,Eest[np.newaxis,:,:]),axis=0) devec1=np.concatenate((devec1,dEest[np.newaxis,:,:]),axis=0) varevec1=np.concatenate((varevec1,vEestAll[np.newaxis,:,:,:]),axis=0) Irec=Irecs[-1]+1 # increment counters IIrec=IIrec+1 if Irec>=time1.shape[0]: done=1 MLTtime1=np.array(MLTtime1) timeout=np.array(timeout) dtimeout=np.array(dtimeout) # magnitude and direction Vmag = np.sqrt( np.power(vvels1[:,:,0],2.0) + np.power(vvels1[:,:,1],2.0) ).real dVmag = np.sqrt( np.power(dvvels1[:,:,0],2.0)*np.power(vvels1[:,:,0]/Vmag,2.0) + np.power(dvvels1[:,:,1],2.0)*np.power(vvels1[:,:,1]/Vmag,2.0) ).real Vdir = 180.0/np.pi*np.arctan2(vvels1[:,:,1],vvels1[:,:,0]).real dVdir = 180.0/np.pi*((1.0/np.absolute(vvels1[:,:,0]))*(1.0/(1.0+np.power(vvels1[:,:,1]/vvels1[:,:,0],2.0)))*np.sqrt(np.power(dvvels1[:,:,1],2.0)+np.power(vvels1[:,:,1]/vvels1[:,:,0]*dvvels1[:,:,0],2.0))).real Emag = np.sqrt( np.power(evec1[:,:,0],2.0) + np.power(evec1[:,:,1],2.0) ).real dEmag = np.sqrt( np.power(devec1[:,:,0],2.0)*np.power(evec1[:,:,0]/Emag,2.0) + np.power(devec1[:,:,1],2.0)*np.power(evec1[:,:,1]/Emag,2.0) ).real Edir = 180.0/np.pi*np.arctan2(evec1[:,:,1],evec1[:,:,0]).real dEdir = 180.0/np.pi*((1.0/np.absolute(evec1[:,:,0]))*(1.0/(1.0+np.power(evec1[:,:,1]/evec1[:,:,0],2.0)))*np.sqrt(np.power(devec1[:,:,1],2.0)+np.power(evec1[:,:,1]/evec1[:,:,0]*devec1[:,:,0],2.0))).real ### Set up output dicts self.setOutDicts(dat1) self.Params['IntegrationTime']=Time2Integrate # Time self.Time['UnixTime'] = timeout self.Time['dtime'] = dtimeout self.Time['MagneticLocalTime'] = MLTtime1 # Vector Vels if self.byGeo==2: self.VectorVels['Latitude']=PLAT_OUT self.VectorVels['MagneticLatitude']=[] else: self.VectorVels['Latitude']=[] self.VectorVels['MagneticLatitude']=PLAT_OUT self.VectorVels['Nmeas'] = Nall1.astype('int32') self.VectorVels['Chi2'] = chi2 self.VectorVels['Vest'] = vvels1; self.VectorVels['errVest'] = dvvels1 self.VectorVels['varVest'] = varvvels1 self.VectorVels['Vmag'] = Vmag; self.VectorVels['errVmag'] = dVmag self.VectorVels['Vdir'] = Vdir; self.VectorVels['errVdir'] = dVdir self.VectorVels['Eest'] = evec1; self.VectorVels['errEest'] = devec1 self.VectorVels['varEest'] = varevec1 self.VectorVels['Emag'] = Emag; self.VectorVels['errEmag'] = dEmag self.VectorVels['Edir'] = Edir; self.VectorVels['errEdir'] = dEdir self.Output['Velocity'] = vvels1 self.Output['ElectricField'] = evec1 self.Output['SigV'] = varvvels1 self.Output['SigE'] = varevec1 self.Output['MLAT'] = plat_out1 self.Output['MLON'] = plon_out1 ### Output file if self.saveout: self.createOutputFile(ofname) ### Plot output if self.makeplot: if (timeout[-1,-1]-timeout[0,0])/3600.0>36.0: self.createPlots_byTime(ofname,binByDay=1) else: self.createPlots(ofname) self.create_new_output('test_vvels.h5',vvels1,varvvels1,evec1,varevec1) return
def test_geo2apex_vectorization(): A = Apex(date=2000, refh=300) assert A.geo2apex([60, 60], 15, 100)[0].shape == (2,) assert A.geo2apex(60, [15, 15], 100)[0].shape == (2,) assert A.geo2apex(60, 15, [100, 100])[0].shape == (2,)
def test_geo2apex(): A = Apex(date=2000, refh=300) lat, lon = A.geo2apex(60, 15, 100) assert_allclose((lat, lon), A._geo2apex(60, 15, 100)) assert type(lat) != np.ndarray assert type(lon) != np.ndarray
def test_convert_geo2mlt(): datetime = dt.datetime(2000, 3, 9, 14, 25, 58) A = Apex(date=2000, refh=300) assert_allclose(A.convert(60, 15, 'geo', 'mlt', height=100, ssheight=2e5, datetime=datetime)[1], A.mlon2mlt(A.geo2apex(60, 15, 100)[1], datetime, ssheight=2e5))
def test_convert_geo2apex(): A = Apex(date=2000, refh=300) assert_allclose(A.convert(60, 15, 'geo', 'apex', height=100), A.geo2apex(60, 15, 100))
class Field(object): def __init__(self, *args, **kwargs): if len(args) == 1: self.read_config(args[0]) else: self.apex_year = kwargs['apex_year'] self.field_coords = np.array(kwargs['field_coords']) self.field_values = np.array(kwargs['field_values']) # initialize Apex object self.apex = Apex(date=self.apex_year) self.map_velocity_field(self.field_coords, self.field_values) self.convert_to_ECEF() self.create_interpolators() def read_config(self, config_file): config = configparser.ConfigParser() config.read(config_file) self.apex_year = config.getint('FIELD', 'apex_year') self.field_coords = np.array(eval(config.get('FIELD', 'field_coords'))) self.field_values = np.array(eval(config.get('FIELD', 'field_values'))) def map_velocity_field(self, coords, field): # coords - array (N,3) of geodetic lat, lon, alt # field - array (N,3) of geodetic E, N, U components of the velocity field at each position # define output altitudes altitude = np.arange(50., 1000., 50.) # create array in proper shape to be applied to every input coordinate self.altitude = np.repeat(altitude, coords.shape[-1]) # map to diffent altitudes manually - the current expected input/output arrays of apexpy.map_to_height makes this function difficult to use for this purpose alat, alon = self.apex.geo2apex(coords[0], coords[1], coords[2]) # find positions at each altitude self.latitude, self.longitude, __ = self.apex.apex2geo( np.tile(alat, len(altitude)), np.tile(alon, len(altitude)), self.altitude) # map field to each altitude f = np.array([ self.apex.map_V_to_height(alat, alon, coords[2], a, field.T).T for a in altitude ]) self.field = f.reshape(-1, f.shape[-1]) def convert_to_ECEF(self): self.X, self.Y, self.Z = pm.geodetic2ecef(self.latitude, self.longitude, self.altitude * 1000.) self.Vx, self.Vy, self.Vz = pm.enu2uvw(self.field[:, 0], self.field[:, 1], self.field[:, 2], self.latitude, self.longitude) def create_interpolators(self): self.interpVx = interpolate.LinearNDInterpolator( np.array([self.X, self.Y, self.Z]).T, self.Vx) self.interpVy = interpolate.LinearNDInterpolator( np.array([self.X, self.Y, self.Z]).T, self.Vy) self.interpVz = interpolate.LinearNDInterpolator( np.array([self.X, self.Y, self.Z]).T, self.Vz) def plot_ionosphere(self): fig = plt.figure(figsize=(10, 10)) ax = fig.add_subplot(111, projection='3d') for x, y, z, vx, vy, vz in zip(self.X, self.Y, self.Z, self.Vx, self.Vy, self.Vz): ax.quiver(x, y, z, vx, vy, vz, length=0.4 * np.sqrt(vx**2 + vy**2 + vz**2), color='green') plt.show()
def test_geo2apex_vectorization(): apex_out = Apex(date=2000, refh=300) assert apex_out.geo2apex([60, 60], 15, 100)[0].shape == (2, ) assert apex_out.geo2apex(60, [15, 15], 100)[0].shape == (2, ) assert apex_out.geo2apex(60, 15, [100, 100])[0].shape == (2, )
def test_geo2apex(): apex_out = Apex(date=2000, refh=300) lat, lon = apex_out.geo2apex(60, 15, 100) assert_allclose((lat, lon), apex_out._geo2apex(60, 15, 100)) assert type(lat) != np.ndarray assert type(lon) != np.ndarray
def test_convert_geo2apex(): apex_out = Apex(date=2000, refh=300) assert_allclose(apex_out.convert(60, 15, 'geo', 'apex', height=100), apex_out.geo2apex(60, 15, 100))
def test_convert_geo2apex(): A = Apex(date=2000, refh=300) assert_allclose(A.convert(60, 15, 'geo', 'apex', height=100), A.geo2apex(60, 15, 100))