Skip to content

Commit 382697c

Browse files
Add pyaps3 files
1 parent 92a2c57 commit 382697c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+5773
-0
lines changed

PyAPS.pdf

200 KB
Binary file not shown.

__init__.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
'''
2+
PyAPS module to compute InSAR phase delay maps from weather models.
3+
4+
Written by Romain Jolivet <rjolivet@gps.caltech.edu> and Piyush Agram <piyush@gps.caltech.edu>. The original Fortran package was written by Romain Jolivet and the Python version including support for different models was written by Piyush Agram.
5+
6+
.. note::
7+
Details of the python module can be obtained `here. <http://code.google.com/p/pyaps>`_
8+
'''
9+
10+
__all__ = ['geocoord','rdrcoord','autoget']
11+
12+
from .geocoord import PyAPS_geo
13+
from .rdrcoord import PyAPS_rdr
14+
from .autoget import *
15+
16+
17+
############################################################
18+
# Program is part of PyAPS #
19+
# Copyright 2012, by the California Institute of Technology#
20+
# Contact: earthdef@gps.caltech.edu #
21+
############################################################

autoget.py

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
############################################################
2+
# Program is part of PyAPS #
3+
# Copyright 2012, by the California Institute of Technology#
4+
# Contact: earthdef@gps.caltech.edu #
5+
# Modified by A. Benoit and R. Jolivet 2019 #
6+
# Ecole Normale Superieure, Paris #
7+
# Contact: insar@geologie.ens.fr #
8+
############################################################
9+
10+
import configparser as ConfigParser
11+
import sys
12+
import os.path
13+
import cdsapi
14+
15+
def ECMWFdload(bdate,hr,filedir,model,datatype,humidity='Q'):
16+
'''
17+
ECMWF data downloading.
18+
19+
Args:
20+
* bdate : date to download (str)
21+
* hr : hour to download (str)
22+
* filedir : files directory (str)
23+
* model : weather model ('interim' or 'era5' or 'hres')
24+
* datatype : reanalysis data type (an)
25+
* humidity : humidity
26+
'''
27+
28+
#-------------------------------------------
29+
# Initialize
30+
31+
# Check data
32+
assert model in ('era5','interim','hres'), 'Unknown model for ECMWF'
33+
34+
# Infos for downloading
35+
if model in 'interim':
36+
print('WARNING: you are downloading from the old ECMWF platform. ERA-Interim is deprecated, use ERA-5 instead.')
37+
if model in 'era5':
38+
print('INFO: You are using the latest ECMWF platform for downloading datasets: https://cds.climate.copernicus.eu/api/v2')
39+
40+
#-------------------------------------------
41+
# Define parameters
42+
43+
# Humidity
44+
assert humidity in ('Q','R'), 'Unknown humidity field for ECMWF'
45+
if humidity in 'Q':
46+
if model in 'era5':
47+
humidparam = 'specific_humidity'
48+
else:
49+
humidparam = 133
50+
elif humidity in 'R':
51+
if model in 'era5':
52+
humidparam = 'relative_humidity'
53+
else:
54+
humidparam = 157
55+
56+
# Grid size (only for HRES and ERA-Interim)
57+
if model in 'hres':
58+
gridsize = '0.10/0.10'
59+
elif model in 'interim':
60+
gridsize = '0.75/0.75'
61+
62+
#-------------------------------------------
63+
# Iterate over dates
64+
65+
flist = []
66+
for k in range(len(bdate)):
67+
day = bdate[k]
68+
69+
#-------------------------------------------
70+
# CASE 1: request for CDS API client (new ECMWF platform, for ERA-5)
71+
if model in 'era5':
72+
73+
# Contact the server
74+
c = cdsapi.Client()
75+
76+
# Pressure levels
77+
pressure_lvls = ['1','2','3','5','7','10','20','30','50',
78+
'70','100','125','150','175','200','225',
79+
'250','300','350','400','450','500','550',
80+
'600','650','700','750','775','800','825',
81+
'850','875','900','925','950','975','1000']
82+
83+
# Dictionary
84+
indict = {'product_type':'reanalysis',
85+
'format':'grib',
86+
'variable':['geopotential','temperature','{}'.format(humidparam)],
87+
'pressure_level': pressure_lvls,
88+
'year':'{}'.format(day[0:4]),
89+
'month':'{}'.format(day[4:6]),
90+
'day':'{}'.format(day[6:8]),
91+
'time':'{}:00'.format(hr)}
92+
93+
# Output
94+
fname = '%s/ERA-5_%s_%s_%s.grb'%(filedir,day,hr,datatype)
95+
flist.append(fname)
96+
97+
# Assert grib file not yet downloaded
98+
if not os.path.exists(fname):
99+
print('Downloading %d of %d: %s '%(k+1,len(bdate),fname))
100+
print(indict)
101+
102+
# Make the request
103+
c.retrieve(
104+
'reanalysis-{}-pressure-levels'.format(model),
105+
indict,
106+
fname)
107+
108+
#-------------------------------------------
109+
# CASE 2: request for WEB API client (old ECMWF platform, deprecated, for ERA-Int and HRES)
110+
else:
111+
112+
# Contact the server
113+
from pyaps3.ecmwfapi import ECMWFDataServer
114+
dpath = os.path.dirname(__file__)
115+
config = ConfigParser.RawConfigParser()
116+
config.read(os.path.expanduser('~/.ecmwfcfg'))
117+
url = "https://api.ecmwf.int/v1"
118+
emid = config.get('ECMWF', 'email')
119+
key = config.get('ECMWF', 'key')
120+
server = ECMWFDataServer(url=url, key=key, email=emid)
121+
122+
# Output
123+
if model in 'interim':
124+
fname = '%s/ERA-Int_%s_%s_%s.grb'%(filedir,day,hr,datatype)
125+
elif model in 'hres':
126+
fname = '%s/HRES_%s_%s_%s.grb'%(filedir,day,hr,datatype)
127+
flist.append(fname)
128+
129+
# Dictionary
130+
indict = {'dataset' : '{}'.format(model),
131+
'type' : '{}'.format(datatype),
132+
'date' : '{}'.format(day),
133+
'time' : '{}'.format(hr),
134+
'step' : '0',
135+
'levtype' : "pl",
136+
'levelist' : "all",
137+
'grid' : '{}'.format(gridsize),
138+
'param' : '129/130/{}'.format(humidparam),
139+
'target' : '{}'.format(fname)}
140+
141+
# Assert grib file not yet downloaded
142+
if not os.path.exists(fname):
143+
print('Downloading %d of %d: %s '%(k+1,len(bdate),fname))
144+
print(indict)
145+
146+
# Make the request
147+
server.retrieve(indict)
148+
149+
return flist

delay.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
############################################################
2+
# Program is part of PyAPS #
3+
# Copyright 2012, by the California Institute of Technology#
4+
# Contact: earthdef@gps.caltech.edu #
5+
# Modified by A. Benoit and R. Jolivet 2019 #
6+
# Ecole Normale Superieure, Paris #
7+
# Contact: insar@geologie.ens.fr #
8+
############################################################
9+
import numpy as np
10+
11+
#############Clausius-Clapeyron for ECMWF as used in Jolivet et al 2011#
12+
def cc_eraorig(tmp,cdic):
13+
'''This routine takes temperature profiles and returns Saturation water vapor partial pressure using the Clausius-Clapeyron law applied in Jolivet et al. 2011,GRL, doi:10.1029/2011GL048757. It can be used in case you are using Relative Humidity from ECMWF models
14+
15+
Args:
16+
* tmp (np.array) : Temperature
17+
* cdic (dict) : Dictionnary of constants
18+
19+
Returns:
20+
* esat (np.array) : Saturation water vapor partial pressure.'''
21+
22+
a1w=cdic['a1w']
23+
T3=cdic['T3']
24+
Rv=cdic['Rv']
25+
26+
esat=a1w*np.exp( (2.5e6/Rv) * ( (1/T3) - (1/tmp) ) )
27+
28+
return esat
29+
###############Completed CC_ERAORIG#####################################
30+
31+
##############Read Input text file #####################################
32+
def read_eratxt(fname,cdic):
33+
'''Read ECMWF files from 0.75 degree grid similar to Romain Jolivet's Delay Package.
34+
35+
Args:
36+
* fname (str): Path to the delay file
37+
* cdic (np.float): Dictionary of constants
38+
39+
Kwargs:
40+
* humidity (str): Specific ('Q') or relative humidity ('R').
41+
42+
Returns:
43+
* lvls (np.array): Pressure levels
44+
* latlist(np.array): Latitudes of the stations
45+
* lonlist(np.array): Longitudes of the stations
46+
* gph (np.array): Geopotential height
47+
* tmp (np.array): Temperature
48+
* vpr (np.array): Vapor pressure
49+
50+
.. note::
51+
Uses cc_eraorig by default.
52+
'''
53+
54+
lvls=[]
55+
latlist=[]
56+
lonlist=[]
57+
gpht=[]
58+
tmpt=[]
59+
reht=[]
60+
61+
g=cdic['g']
62+
63+
f=open(fname,'r')
64+
tmp=f.readlines()
65+
i=0
66+
nstn=0
67+
maxloop=np.int(len(tmp))
68+
while i<maxloop:
69+
if (tmp[i][0]=='-'):
70+
nstn=nstn+1
71+
lonlat=tmp[i+3].rsplit(' ')
72+
lonlist.append(np.float(lonlat[3]))
73+
latlist.append(np.float(lonlat[9]))
74+
i=i+5
75+
new='y'
76+
else:
77+
if new in ('y'):
78+
n=1
79+
val=tmp[i].rsplit(' ')
80+
gpht.append(np.float(val[0]))
81+
lvls.append(np.float(val[1]))
82+
tmpt.append(np.float(val[2]))
83+
reht.append(np.float(val[3]))
84+
i=i+1
85+
new='n'
86+
else:
87+
n=n+1
88+
val=tmp[i].rsplit(' ')
89+
gpht.append(np.float(val[0]))
90+
lvls.append(np.float(val[1]))
91+
tmpt.append(np.float(val[2]))
92+
reht.append(np.float(val[3]))
93+
i=i+1
94+
95+
gpht=np.array(gpht)/g
96+
gph=np.flipud(gpht.reshape((n,nstn),order='F'))
97+
del gpht
98+
99+
tmpt=np.array(tmpt)
100+
esat=cc_eraorig(tmpt,cdic)
101+
tmp=np.flipud(tmpt.reshape((n,nstn),order='F'))
102+
del tmpt
103+
104+
vprt=(np.array(reht)/100.)*esat
105+
vpr=np.flipud(vprt.reshape((n,nstn),order='F'))
106+
del vprt
107+
del esat
108+
109+
lvls=np.flipud(np.array(lvls))
110+
lvls=lvls[0:n]
111+
112+
lonlist=np.array(lonlist)
113+
latlist=np.array(latlist)
114+
115+
return lvls,latlist,lonlist,gph,tmp,vpr

ecmwf.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
############################################################
2+
# Program is part of PyAPS #
3+
# Copyright 2012, by the California Institute of Technology#
4+
# Contact: earthdef@gps.caltech.edu #
5+
# Modified by A. Benoit and R. Jolivet 2019 #
6+
# Ecole Normale Superieure, Paris #
7+
# Contact: insar@geologie.ens.fr #
8+
############################################################
9+
import urllib.request
10+
import urllib.parse
11+
import time
12+
import datetime
13+
14+
class ECMWFDataServer:
15+
def __init__(self,portal,token,email):
16+
self.version = '0.3'
17+
self.portal = portal
18+
self.token = token
19+
self.email = email
20+
21+
def _call(self,action,args):
22+
23+
params = {'_token' : self.token,
24+
'_email' : self.email,
25+
'_action' : action,
26+
'_version' : self.version}
27+
params.update(args)
28+
29+
data = urllib.parse.urlencode(params)
30+
req = urllib.request.Request(self.portal, data)
31+
response = urllib.request.urlopen(req)
32+
33+
json = response.read();
34+
35+
undef = None;
36+
json = eval(json)
37+
38+
if json != None:
39+
if 'error' in json:
40+
raise RuntimeError(json['error'])
41+
if 'message' in json:
42+
self.put(json['message'])
43+
44+
return json
45+
46+
def put(self,*args):
47+
print(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')),
48+
for a in args:
49+
print(a),
50+
print()
51+
52+
53+
def retrieve(self,args):
54+
self.put("ECMWF data server batch tool version",self.version);
55+
user = self._call("user_info",{});
56+
self.put("Welcome to",user['name'], "from" , user['organisation']);
57+
58+
r = self._call('retrieve',args)
59+
rid = r['request']
60+
61+
last = ''
62+
sleep = 0
63+
while r['status'] != 'complete' and r['status'] != 'aborted':
64+
text = r['status'] + '.'
65+
if 'info' in r and r['info'] != None:
66+
text = text + ' ' + r['info']
67+
68+
if text != last:
69+
self.put("Request",text)
70+
last = text
71+
72+
time.sleep(sleep)
73+
r = self._call('status',{'request':rid})
74+
if sleep < 60:
75+
sleep = sleep + 1
76+
77+
if r['status'] != last:
78+
self.put("Request",r['status'])
79+
80+
if 'reason' in r:
81+
for m in r['reason']:
82+
self.put(m)
83+
84+
if 'result' in r:
85+
size = long(r['size'])
86+
self.put("Downloading",self._bytename(size))
87+
done = self._transfer(r['result'],args['target'])
88+
self.put("Done")
89+
if done != size:
90+
raise RuntimeError("Size mismatch: " + str(done) + " and " + str(size))
91+
92+
self._call('delete',{'request':rid})
93+
94+
if r['status'] == 'aborted':
95+
raise RuntimeError("Request aborted")
96+
97+
def _transfer(self,url,path):
98+
result = urllib.request.urlretrieve(url,path)
99+
return long(result[1]['content-length'])
100+
101+
def _bytename(self,size):
102+
next = {'':'K','K':'M','M':'G','G':'T','T':'P'}
103+
l = ''
104+
size = size*1.0
105+
while 1024 < size:
106+
l = next[l]
107+
size = size / 1024
108+
return "%g %sbyte%s" % (size,l,'s')
109+

0 commit comments

Comments
 (0)