示例#1
0
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']
示例#2
0
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']
示例#3
0
    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
示例#4
0
    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
示例#5
0
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
示例#6
0
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]
    }
示例#7
0
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
示例#8
0
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]}