def calcFieldPnt(tGeoLat, tGeoLon, tAlt, boreSight, boreOffset, slantRange, \ elevation=None, altitude=None, model=None, coords='geo'): """ Calculate coordinates of field point given the radar coordinates and boresight, the pointing direction deviation from boresight and elevation angle, and the field point slant range and altitude. Either the elevation or the altitude must be provided. If none is provided, the altitude is set to 300 km and the elevation evaluated to accomodate altitude and range. **INPUTS**: * **tGeoLat**: transmitter latitude [degree, N] * **tGeoLon**: transmitter longitude [degree, E] * **tAlt**: transmitter altitude [km] * **boreSight**: boresight azimuth [degree, E] * **boreOffset**: offset from boresight [degree] * **slantRange**: slant range [km] * **elevation**: elevation angle [degree] (estimated if None) * **altitude**: altitude [km] (default 300 km) * **model**: * **'IS'**: for ionopsheric scatter projection model * **'GS'**: for ground scatter projection model * **None**: if you are really confident in your elevation or altitude data * ... more to come * **coords**: 'geo' (more to come) """ from math import radians, degrees, sin, cos, asin, atan, sqrt, pi from utils import Re, geoPack # Make sure we have enough input stuff # if (not model) and (not elevation or not altitude): model = 'IS' # Now let's get to work # Classic Ionospheric/Ground scatter projection model if model in ['IS','GS']: # Make sure you have altitude, because these 2 projection models rely on it if not elevation and not altitude: # Set default altitude to 300 km altitude = 300.0 elif elevation and not altitude: # If you have elevation but not altitude, then you calculate altitude, and elevation will be adjusted anyway altitude = sqrt( Re**2 + slantRange**2 + 2. * slantRange * Re * sin( radians(elevation) ) ) - Re # Now you should have altitude (and maybe elevation too, but it won't be used in the rest of the algorithm) # Adjust altitude so that it makes sense with common scatter distribution xAlt = altitude if model == 'IS': if altitude > 150. and slantRange <= 600: xAlt = 115. elif altitude > 150. and slantRange > 600. and slantRange <= 800.: xAlt = 115. + ( slantRange - 600. ) / 200. * ( altitude - 115. ) elif model == 'GS': if altitude > 150. and slantRange <= 300: xAlt = 115. elif altitude > 150. and slantRange > 300. and slantRange <= 500.: xAlt = 115. + ( slantRange - 300. ) / 200. * ( altitude - 115. ) if slantRange < 150.: xAlt = slantRange / 150. * 115. # To start, set Earth radius below field point to Earth radius at radar (lat,lon,tRe) = geoPack.geodToGeoc(tGeoLat, tGeoLon) RePos = tRe # Iterate until the altitude corresponding to the calculated elevation matches the desired altitude n = 0L # safety counter while True: # pointing elevation (spherical Earth value) [degree] tel = degrees( asin( ((RePos+xAlt)**2 - (tRe+tAlt)**2 - slantRange**2) / (2. * (tRe+tAlt) * slantRange) ) ) # estimate off-array-normal azimuth (because it varies slightly with elevation) [degree] bOff = calcAzOffBore(tel, boreOffset) # pointing azimuth taz = boreSight + bOff # calculate position of field point dictOut = geoPack.calcDistPnt(tGeoLat, tGeoLon, tAlt, dist=slantRange, el=tel, az=taz) # Update Earth radius RePos = dictOut['distRe'] # stop if the altitude is what we want it to be (or close enough) n += 1L if abs(xAlt - dictOut['distAlt']) <= 0.5 or n > 2: return dictOut['distLat'], dictOut['distLon'] break # No projection model (i.e., the elevation or altitude is so good that it gives you the proper projection by simple geometric considerations) elif not model: # Using no models simply means tracing based on trustworthy elevation or altitude if not altitude: altitude = sqrt( Re**2 + slantRange**2 + 2. * slantRange * Re * sin( radians(elevation) ) ) - Re if not elevation: if(slantRange < altitude): altitude = slantRange - 10 elevation = degrees( asin( ((Re+altitude)**2 - (Re+tAlt)**2 - slantRange**2) / (2. * (Re+tAlt) * slantRange) ) ) # The tracing is done by calcDistPnt dict = geoPack.calcDistPnt(tGeoLat, tGeoLon, tAlt, dist=slantRange, el=elevation, az=boreSight+boreOffset) return dict['distLat'], dict['distLon']
def calcFieldPnt(tGeoLat, tGeoLon, tAlt, boreSight, boreOffset, slantRange, \ elevation=None, altitude=None, model=None, coords='geo'): """ Calculate coordinates of field point given the radar coordinates and boresight, the pointing direction deviation from boresight and elevation angle, and the field point slant range and altitude. Either the elevation or the altitude must be provided. If none is provided, the altitude is set to 300 km and the elevation evaluated to accomodate altitude and range. **INPUTS**: * **tGeoLat**: transmitter latitude [degree, N] * **tGeoLon**: transmitter longitude [degree, E] * **tAlt**: transmitter altitude [km] * **boreSight**: boresight azimuth [degree, E] * **boreOffset**: offset from boresight [degree] * **slantRange**: slant range [km] * **elevation**: elevation angle [degree] (estimated if None) * **altitude**: altitude [km] (default 300 km) * **model**: * **'IS'**: for ionopsheric scatter projection model * **'GS'**: for ground scatter projection model * **None**: if you are really confident in your elevation or altitude data * ... more to come * **coords**: 'geo' (more to come) """ from math import radians, degrees, sin, cos, asin, atan, sqrt, pi from utils import Re, geoPack # Make sure we have enough input stuff # if (not model) and (not elevation or not altitude): model = 'IS' # Now let's get to work # Classic Ionospheric/Ground scatter projection model if model in ['IS', 'GS']: # Make sure you have altitude, because these 2 projection models rely on it if not elevation and not altitude: # Set default altitude to 300 km altitude = 300.0 elif elevation and not altitude: # If you have elevation but not altitude, then you calculate altitude, and elevation will be adjusted anyway altitude = sqrt(Re**2 + slantRange**2 + 2. * slantRange * Re * sin(radians(elevation))) - Re # Now you should have altitude (and maybe elevation too, but it won't be used in the rest of the algorithm) # Adjust altitude so that it makes sense with common scatter distribution xAlt = altitude if model == 'IS': if altitude > 150. and slantRange <= 600: xAlt = 115. elif altitude > 150. and slantRange > 600. and slantRange <= 800.: xAlt = 115. + (slantRange - 600.) / 200. * (altitude - 115.) elif model == 'GS': if altitude > 150. and slantRange <= 300: xAlt = 115. elif altitude > 150. and slantRange > 300. and slantRange <= 500.: xAlt = 115. + (slantRange - 300.) / 200. * (altitude - 115.) if slantRange < 150.: xAlt = slantRange / 150. * 115. # To start, set Earth radius below field point to Earth radius at radar (lat, lon, tRe) = geoPack.geodToGeoc(tGeoLat, tGeoLon) RePos = tRe # Iterate until the altitude corresponding to the calculated elevation matches the desired altitude n = 0L # safety counter while True: # pointing elevation (spherical Earth value) [degree] tel = degrees( asin(((RePos + xAlt)**2 - (tRe + tAlt)**2 - slantRange**2) / (2. * (tRe + tAlt) * slantRange))) # estimate off-array-normal azimuth (because it varies slightly with elevation) [degree] bOff = calcAzOffBore(tel, boreOffset) # pointing azimuth taz = boreSight + bOff # calculate position of field point dictOut = geoPack.calcDistPnt(tGeoLat, tGeoLon, tAlt, dist=slantRange, el=tel, az=taz) # Update Earth radius RePos = dictOut['distRe'] # stop if the altitude is what we want it to be (or close enough) n += 1L if abs(xAlt - dictOut['distAlt']) <= 0.5 or n > 2: return dictOut['distLat'], dictOut['distLon'] break # No projection model (i.e., the elevation or altitude is so good that it gives you the proper projection by simple geometric considerations) elif not model: # Using no models simply means tracing based on trustworthy elevation or altitude if not altitude: altitude = sqrt(Re**2 + slantRange**2 + 2. * slantRange * Re * sin(radians(elevation))) - Re if not elevation: if (slantRange < altitude): altitude = slantRange - 10 elevation = degrees( asin(((Re + altitude)**2 - (Re + tAlt)**2 - slantRange**2) / (2. * (Re + tAlt) * slantRange))) # The tracing is done by calcDistPnt dict = geoPack.calcDistPnt(tGeoLat, tGeoLon, tAlt, dist=slantRange, el=elevation, az=boreSight + boreOffset) return dict['distLat'], dict['distLon']
def getRadarsByPosition(self, lat, lon, alt, distMax=4000., datetime=None): """Get a list of radars able to see a given point on Earth **Belongs to**: :class:`network` **Args**: * **lat**: latitude of given point in geographic coordinates * **lon**: longitude of given point in geographic coordinates * **alt**: altitude of point above the Earth's surface in km * **[distMax]**: maximum distance of given point from radar * **[datetime]**: python datetime object (defaults to today) **Returns**: * A dictionnary with keys: * 'radars': a list of radar objects (:class:`radar`) * 'dist': a list of distance from radar to given point (1 per radar) * 'beam': a list of beams (1 per radar) seeing the given point **Example**: :: radars = obj.getRadarsByPosition(67., 134., 300.) written by Sebastien, 2012-08 """ from datetime import datetime as dt from utils import geoPack as geo from numpy import sin, cos, arccos, dot, cross, sign from math import radians, degrees if not datetime: datetime = dt.utcnow() found = False out = {'radars': [], 'dist': [], 'beam': []} for iRad in xrange( self.nradar ): site = self.radars[iRad].getSiteByDate(datetime) # Skip if radar inactive at date if (not site) and (self.radars[iRad].status != 1): continue if not (self.radars[iRad].stTime <= datetime <= self.radars[iRad].edTime): continue # Skip if radar in other hemisphere if site.geolat*lat < 0.: continue distPnt = geo.calcDistPnt(site.geolat, site.geolon, site.alt, distLat=lat, distLon=lon, distAlt=300.) # Skip if radar too far if distPnt['dist'] > distMax: continue # minAz = (site.boresite % 360.)-abs(site.bmsep)*site.maxbeam/2 # maxAz = (site.boresite % 360.)+abs(site.bmsep)*site.maxbeam/2 extFov = abs(site.bmsep)*site.maxbeam/2 ptBo = [cos(radians(site.boresite)), sin(radians(site.boresite))] ptAz = [cos(radians(distPnt['az'])), sin(radians(distPnt['az']))] deltAz = degrees( arccos( dot(ptBo, ptAz) ) ) # Skip if out of azimuth range if not abs(deltAz) <= extFov: continue if sign(cross(ptBo, ptAz)) >= 0: beam = int( site.maxbeam/2 + round( deltAz/site.bmsep ) - 1 ) else: beam = int( site.maxbeam/2 - round( deltAz/site.bmsep ) ) # Update output found = True out['radars'].append(self.radars[iRad]) out['dist'].append(distPnt['dist']) out['beam'].append(beam) if found: return out else: return found
def getRadarsByPosition(self, lat, lon, alt, distMax=4000., datetime=None): """Get a list of radars able to see a given point on Earth **Belongs to**: :class:`network` **Args**: * **lat**: latitude of given point in geographic coordinates * **lon**: longitude of given point in geographic coordinates * **alt**: altitude of point above the Earth's surface in km * **[distMax]**: maximum distance of given point from radar * **[datetime]**: python datetime object (defaults to today) **Returns**: * A dictionnary with keys: * 'radars': a list of radar objects (:class:`radar`) * 'dist': a list of distance from radar to given point (1 per radar) * 'beam': a list of beams (1 per radar) seeing the given point **Example**: :: radars = obj.getRadarsByPosition(67., 134., 300.) written by Sebastien, 2012-08 """ from datetime import datetime as dt from utils import geoPack as geo from numpy import sin, cos, arccos, dot, cross, sign from math import radians, degrees if not datetime: datetime = dt.utcnow() found = False out = {'radars': [], 'dist': [], 'beam': []} for iRad in xrange(self.nradar): site = self.radars[iRad].getSiteByDate(datetime) # Skip if radar inactive at date if (not site) and (self.radars[iRad].status != 1): continue if not (self.radars[iRad].stTime <= datetime <= self.radars[iRad].edTime): continue # Skip if radar in other hemisphere if site.geolat * lat < 0.: continue distPnt = geo.calcDistPnt(site.geolat, site.geolon, site.alt, distLat=lat, distLon=lon, distAlt=300.) # Skip if radar too far if distPnt['dist'] > distMax: continue # minAz = (site.boresite % 360.)-abs(site.bmsep)*site.maxbeam/2 # maxAz = (site.boresite % 360.)+abs(site.bmsep)*site.maxbeam/2 extFov = abs(site.bmsep) * site.maxbeam / 2 ptBo = [cos(radians(site.boresite)), sin(radians(site.boresite))] ptAz = [cos(radians(distPnt['az'])), sin(radians(distPnt['az']))] deltAz = degrees(arccos(dot(ptBo, ptAz))) # Skip if out of azimuth range if not abs(deltAz) <= extFov: continue if sign(cross(ptBo, ptAz)) >= 0: beam = int(site.maxbeam / 2 + round(deltAz / site.bmsep) - 1) else: beam = int(site.maxbeam / 2 - round(deltAz / site.bmsep)) # Update output found = True out['radars'].append(self.radars[iRad]) out['dist'].append(distPnt['dist']) out['beam'].append(beam) if found: return out else: return found
def isrFov(myMap, isrName, isrPos, elev, azim=[-180., 180.], misa=None, ax=None): '''Plot ISR field-of-view ''' from utils import geoPack as gp import numpy as np from matplotlib import pylab import matplotlib as mp if not ax: ax = pylab.gca() fovCol = '0' # ISR location x0, y0 = myMap(isrPos[1], isrPos[0], coords='geo') myMap.scatter(x0, y0, s=20, zorder=5, c='k', ax=ax) ax.text(x0 * 1.04, y0 * 0.96, isrName, fontsize=10, variant='small-caps') # MHO fov nazims = 100 azims = np.linspace(azim[0], azim[1], nazims) isrFov = np.zeros((nazims, 3)) isrFov2 = np.zeros((nazims, 3)) Rav = 6370. for iaz, taz in enumerate(azims): dd = gp.calcDistPnt(isrPos[0], isrPos[1], 0., distAlt=450., el=elev, az=taz) isrFov[iaz, 0] = dd['distLat'] isrFov[iaz, 1] = dd['distLon'] isrFov[iaz, 2] = dd['distAlt'] # x, y = myMap(isrFov[:,1], isrFov[:,0], coords='geo') # myMap.plot(x, y, c=fovCol, ax=ax, zorder=10) for iaz, taz in enumerate(azims): dd = gp.calcDistPnt(isrPos[0], isrPos[1], 0., distAlt=250., el=elev, az=taz) isrFov2[iaz, 0] = dd['distLat'] isrFov2[iaz, 1] = dd['distLon'] isrFov2[iaz, 2] = dd['distAlt'] # x2, y2 = myMap(isrFov2[:,1], isrFov2[:,0], coords='geo') # myMap.plot(x2, y2, c=fovCol, ax=ax, zorder=10) contourLat = np.concatenate((isrFov[:, 0], [isrPos[0]])) contourLon = np.concatenate((isrFov[:, 1], [isrPos[1]])) x3, y3 = myMap(contourLon, contourLat, coords='geo') contour = np.transpose(np.vstack((x3, y3))) patch = mp.patches.Polygon(contour, color='k', alpha=.8, zorder=15) pylab.gca().add_patch(patch) # if abs(azim[1] - azim[0]) != 360.: # myMap.plot([x0,x[0]], [y0,y[0]], zorder=10, # c=fovCol, ax=ax, lw=1) # myMap.plot([x0,x[-1]], [y0,y[-1]], zorder=10, # c=fovCol, ax=ax, lw=1) if misa: dd = gp.calcDistPnt(isrPos[0], isrPos[1], 0., distAlt=450., el=elev, az=misa) x, y = myMap(dd['distLon'], dd['distLat'], coords='geo') myMap.plot([x0, x], [y0, y], zorder=10, c=(0, .3, 0), ax=ax) return isrFov
def mhoRead(expDate, dataPath='/home/sebastien/Documents/code/mho/data/', fileExt=None): '''Acces Millstone Hill data. Looks first for local hdf5 file, if nothing is found, try to dowmload from Madrigal. ''' import madrigalWeb.madrigalWeb import os, glob import datetime as dt import h5py as h5 import matplotlib as mp import numpy as np from utils import geoPack as gp fileName = 'mlh{:%y%m%d}'.\ format( expDate ) if not fileExt: dfiles = np.sort(glob.glob(dataPath + fileName + '?.???.hdf5')) if not list(dfiles): fileExt = '' else: fileExt = dfiles[-1][-10:-5] fileName = fileName + fileExt + '.hdf5' filePath = os.path.join(dataPath, fileName) try: with h5.File(filePath, 'r') as f: pass print 'Found local file: ' + filePath except: dl = getFilesFromMad(expDate, expDate + dt.timedelta(days=1), dataPath=dataPath) if dl is None: print 'Nothing for {:%Y-%b-%d}'.format(expDate) return else: fileExt = dl[-1] filePath = dataPath + dl + '.hdf5' try: with h5.File(filePath, 'r') as f: pass except: raise print 'Downloaded remote file: ' + filePath with h5.File(filePath, 'r') as f: data = f['Data']['Array Layout'] data2D = data['2D Parameters'] data1D = data['1D Parameters'] params = f['Metadata']['Experiment Parameters'] nel = data2D['nel'][:].transpose() ne = data2D['ne'][:].transpose() popl = data2D['popl'][:].transpose() ti = data2D['ti'][:].transpose() tr = data2D['tr'][:].transpose() vo = data2D['vo'][:].transpose() te = tr * ti mho_range = data['range'][:] mho_range2 = data2D['range'][:].transpose() mho_time = mp.dates.epoch2num(data['timestamps'][:]) mho_elev = np.array([data1D['el1'][:], data1D['el2'][:]]).T mho_azim = np.array([data1D['az1'][:], data1D['az2'][:]]).T try: mho_scntyp = data1D['scntyp'][:] except: mho_scntyp = np.zeros(mho_time.shape) vinds = np.where(mho_elev[:, 0] >= 85.) if len(vinds[0]) > 0: mho_scntyp[vinds] = 5 telev = data1D['el1'][:].reshape((1, len(data1D['el1']))) telev = np.radians(telev) telev = np.sin(telev) tran = data['range'][:].reshape((len(data['range']), 1)) Re = 6371. mho_alti = np.sqrt(Re**2 + \ tran**2 + \ 2.*Re*tran.dot(telev)) - Re mho_gdalt = data2D['gdalt'][:].transpose() mhoPos = [ float(params[7][1]), float(params[8][1]), float(params[9][1]) ] f.close() mho_lat = np.zeros(np.shape(mho_alti)) mho_lon = np.zeros(np.shape(mho_alti)) for ir, dist in enumerate(mho_range): dd = gp.calcDistPnt(mhoPos[0], mhoPos[1], mhoPos[2], dist=dist, el=mho_elev[:, 0], az=mho_azim[:, 0]) mho_lat[ir, :] = dd['distLat'] mho_lon[ir, :] = dd['distLon'] return { 'nel': nel, 'ne': nel, 'popl': popl, 'ti': ti, 'tr': tr, 'te': te, 'vo': vo, 'range': mho_range, 'range2': mho_range2, 'time': mho_time, 'elev': mho_elev, 'azim': mho_azim, 'scntyp': mho_scntyp, 'alti': mho_alti, 'gdalt': mho_gdalt, 'lat': mho_lat, 'lon': mho_lon, 'pos': mhoPos, 'filename': os.path.split(filePath)[-1] }
def isrFov(myMap, isrName, isrPos, elev, azim=[-180.,180.], misa=None, ax=None): '''Plot ISR field-of-view ''' from utils import geoPack as gp import numpy as np from matplotlib import pylab import matplotlib as mp if not ax: ax = pylab.gca() fovCol = '0' # ISR location x0, y0 = myMap(isrPos[1], isrPos[0], coords='geo') myMap.scatter(x0, y0, s=20, zorder=5, c='k', ax=ax) ax.text(x0*1.04, y0*0.96, isrName, fontsize=10, variant='small-caps') # MHO fov nazims = 100 azims = np.linspace(azim[0], azim[1], nazims) isrFov = np.zeros((nazims, 3)) isrFov2 = np.zeros((nazims, 3)) Rav = 6370. for iaz, taz in enumerate(azims): dd = gp.calcDistPnt(isrPos[0], isrPos[1], 0., distAlt=450., el=elev, az=taz) isrFov[iaz,0] = dd['distLat'] isrFov[iaz,1] = dd['distLon'] isrFov[iaz,2] = dd['distAlt'] # x, y = myMap(isrFov[:,1], isrFov[:,0], coords='geo') # myMap.plot(x, y, c=fovCol, ax=ax, zorder=10) for iaz, taz in enumerate(azims): dd = gp.calcDistPnt(isrPos[0], isrPos[1], 0., distAlt=250., el=elev, az=taz) isrFov2[iaz,0] = dd['distLat'] isrFov2[iaz,1] = dd['distLon'] isrFov2[iaz,2] = dd['distAlt'] # x2, y2 = myMap(isrFov2[:,1], isrFov2[:,0], coords='geo') # myMap.plot(x2, y2, c=fovCol, ax=ax, zorder=10) contourLat = np.concatenate( (isrFov[:,0], [isrPos[0]]) ) contourLon = np.concatenate( (isrFov[:,1], [isrPos[1]]) ) x3, y3 = myMap(contourLon, contourLat, coords='geo') contour = np.transpose( np.vstack((x3,y3)) ) patch = mp.patches.Polygon( contour, color='k', alpha=.8, zorder=15) pylab.gca().add_patch(patch) # if abs(azim[1] - azim[0]) != 360.: # myMap.plot([x0,x[0]], [y0,y[0]], zorder=10, # c=fovCol, ax=ax, lw=1) # myMap.plot([x0,x[-1]], [y0,y[-1]], zorder=10, # c=fovCol, ax=ax, lw=1) if misa: dd = gp.calcDistPnt(isrPos[0], isrPos[1], 0., distAlt=450., el=elev, az=misa) x, y = myMap(dd['distLon'], dd['distLat'],coords='geo') myMap.plot([x0,x], [y0,y], zorder=10, c=(0,.3,0), ax=ax) return isrFov
def mhoRead( expDate, dataPath='/home/sebastien/Documents/code/mho/data/', fileExt=None) : '''Acces Millstone Hill data. Looks first for local hdf5 file, if nothing is found, try to dowmload from Madrigal. ''' import madrigalWeb.madrigalWeb import os, glob import datetime as dt import h5py as h5 import matplotlib as mp import numpy as np from utils import geoPack as gp fileName = 'mlh{:%y%m%d}'.\ format( expDate ) if not fileExt: dfiles = np.sort(glob.glob(dataPath+fileName+'?.???.hdf5')) if not list(dfiles): fileExt = '' else: fileExt = dfiles[-1][-10:-5] fileName = fileName+fileExt+'.hdf5' filePath = os.path.join(dataPath, fileName) try: with h5.File(filePath,'r') as f: pass print 'Found local file: '+filePath except: dl = getFilesFromMad(expDate, expDate+dt.timedelta(days=1), dataPath=dataPath) if dl is None: print 'Nothing for {:%Y-%b-%d}'.format(expDate) return else: fileExt = dl[-1] filePath = dataPath+dl+'.hdf5' try: with h5.File(filePath,'r') as f: pass except: raise print 'Downloaded remote file: '+filePath with h5.File(filePath,'r') as f: data = f['Data']['Array Layout'] data2D = data['2D Parameters'] data1D = data['1D Parameters'] params = f['Metadata']['Experiment Parameters'] nel = data2D['nel'][:].transpose() ne = data2D['ne'][:].transpose() popl = data2D['popl'][:].transpose() ti = data2D['ti'][:].transpose() tr = data2D['tr'][:].transpose() vo = data2D['vo'][:].transpose() te = tr*ti mho_range = data['range'][:] mho_range2 = data2D['range'][:].transpose() mho_time = mp.dates.epoch2num( data['timestamps'][:] ) mho_elev = np.array( [data1D['el1'][:], data1D['el2'][:]] ).T mho_azim = np.array( [data1D['az1'][:], data1D['az2'][:]] ).T try: mho_scntyp = data1D['scntyp'][:] except: mho_scntyp = np.zeros(mho_time.shape) vinds = np.where( mho_elev[:,0] >= 85. ) if len(vinds[0]) > 0: mho_scntyp[vinds] = 5 telev = data1D['el1'][:].reshape((1,len(data1D['el1']))) telev = np.radians(telev) telev = np.sin(telev) tran = data['range'][:].reshape((len(data['range']),1)) Re = 6371. mho_alti = np.sqrt(Re**2 + \ tran**2 + \ 2.*Re*tran.dot(telev)) - Re mho_gdalt = data2D['gdalt'][:].transpose() mhoPos = [float(params[7][1]), float(params[8][1]), float(params[9][1])] f.close() mho_lat = np.zeros(np.shape(mho_alti)) mho_lon = np.zeros(np.shape(mho_alti)) for ir, dist in enumerate(mho_range): dd = gp.calcDistPnt(mhoPos[0],mhoPos[1],mhoPos[2], dist=dist, el=mho_elev[:,0], az=mho_azim[:,0]) mho_lat[ir,:] = dd['distLat'] mho_lon[ir,:] = dd['distLon'] return {'nel': nel, 'ne': nel, 'popl': popl, 'ti': ti, 'tr': tr, 'te': te, 'vo': vo, 'range': mho_range, 'range2': mho_range2, 'time': mho_time, 'elev': mho_elev, 'azim': mho_azim, 'scntyp': mho_scntyp, 'alti': mho_alti, 'gdalt': mho_gdalt, 'lat': mho_lat, 'lon': mho_lon, 'pos': mhoPos, 'filename': os.path.split(filePath)[-1]}