source: flex_extract.git/source/python/mods/get_mars_data.py @ 6f951ca

ctbtodev
Last change on this file since 6f951ca was 6f951ca, checked in by Anne Philipp <anne.philipp@…>, 5 years ago

new style of docstring params and updates in docstrings

  • Property mode set to 100755
File size: 10.1 KB
RevLine 
[d69b677]1#!/usr/bin/env python
[efdb01a]2# -*- coding: utf-8 -*-
[991df6a]3#*******************************************************************************
4# @Author: Anne Fouilloux (University of Oslo)
5#
6# @Date: October 2014
7#
8# @Change History:
9#
10#    November 2015 - Leopold Haimberger (University of Vienna):
[ff99eae]11#        - moved the getEIdata program into a function "get_mars_data"
[991df6a]12#        - moved the AgurmentParser into a seperate function
13#        - adatpted the function for the use in flex_extract
[ff99eae]14#        - renamed file to get_mars_data
[991df6a]15#
16#    February 2018 - Anne Philipp (University of Vienna):
17#        - applied PEP8 style guide
18#        - added structured documentation
19#        - minor changes in programming style for consistence
20#        - added function main and moved function calls vom __main__ there
21#          (necessary for better documentation with docstrings for later
22#          online documentation)
23#        - use of UIFiles class for file selection and deletion
[6f951ca]24#        - seperated get_mars_data function into several smaller pieces:
25#          write_reqheader, mk_server, mk_dates, remove_old, do_retrievment
[991df6a]26#
27# @License:
[6f951ca]28#    (C) Copyright 2014-2019.
29#    Anne Philipp, Leopold Haimberger
[991df6a]30#
[6f951ca]31#    This work is licensed under the Creative Commons Attribution 4.0
32#    International License. To view a copy of this license, visit
33#    http://creativecommons.org/licenses/by/4.0/ or send a letter to
34#    Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
[991df6a]35#*******************************************************************************
[6f951ca]36'''This script extracts MARS data from ECMWF servers.
[96e1533]37
[6f951ca]38At first, the necessary parameters from command line and CONTROL files are
39extracted. They define the data set to be extracted from MARS.
[96e1533]40
41This file can also be imported as a module and contains the following
42functions:
43
44    * main - the main function of the script
[6f951ca]45    * get_mars_data - overall control of ECMWF data retrievment
46    * write_reqheader - writes the header into the mars_request file
47    * mk_server - creates the server connection to ECMWF servers
48    * mk_dates - defines the start and end date
49    * remove_old - deletes old retrieved grib files
50    * do_retrievement - creates individual retrievals
51
52Type: get_mars_data.py --help
53to get information about command line parameters.
54Read the documentation for usage instructions.
55'''
[efdb01a]56# ------------------------------------------------------------------------------
57# MODULES
58# ------------------------------------------------------------------------------
[991df6a]59import os
60import sys
61import inspect
[ca867de]62from datetime import datetime, timedelta
[ff99eae]63
64# software specific classes and modules from flex_extract
[6f951ca]65# add path to local main python path for flex_extract to get full access
[70fee58]66sys.path.append(os.path.dirname(os.path.abspath(
67    inspect.getfile(inspect.currentframe()))) + '/../')
[2fb99de]68import _config
[9aefaad]69from tools import (my_error, normal_exit, get_cmdline_args,
[5bad6ec]70                   read_ecenv, make_dir)
[25b14be]71from classes.EcFlexpart import EcFlexpart
72from classes.UioFiles import UioFiles
[403cbf1]73from classes.MarsRetrieval import MarsRetrieval
[ca867de]74
75try:
76    ecapi = True
77    import ecmwfapi
78except ImportError:
79    ecapi = False
[efdb01a]80# ------------------------------------------------------------------------------
81# FUNCTION
82# ------------------------------------------------------------------------------
[991df6a]83def main():
[274f9ef]84    '''Controls the program to get data out of mars.
85
86    This is done if it is called directly from command line.
87    Then it also takes program call arguments and control file input.
[295ff45]88
[274f9ef]89    Parameters
90    ----------
[991df6a]91
[274f9ef]92    Return
93    ------
[991df6a]94
95    '''
[54a8a01]96
[9aefaad]97    args = get_cmdline_args()
[4971f63]98    c = ControlFile(args.controlfile)
[54a8a01]99
[2fb99de]100    env_parameter = read_ecenv(_config.PATH_ECMWF_ENV)
[295ff45]101    c.assign_args_to_control(args)
[54a8a01]102    c.assign_envs_to_control(env_parameter)
[2fb99de]103    c.check_conditions(args.queue)
[54a8a01]104
[ff99eae]105    get_mars_data(c)
[96e1533]106    normal_exit(c.mailops, c.queue, 'Done!')
[d69b677]107
[991df6a]108    return
109
[ff99eae]110def get_mars_data(c):
[274f9ef]111    '''Retrieves the EC data needed for a FLEXPART simulation.
112
113    Start and end dates for retrieval period is set. Retrievals
114    are divided into smaller periods if necessary and datechunk parameter
115    is set.
116
117    Parameters
118    ----------
[6f951ca]119    c : ControlFile
[274f9ef]120        Contains all the parameters of CONTROL file and
121        command line.
122
123    Return
124    ------
125
[991df6a]126    '''
[631ba13]127    c.ecapi = ecapi
[d69b677]128
129    if not os.path.exists(c.inputdir):
[5bad6ec]130        make_dir(c.inputdir)
[991df6a]131
[403cbf1]132    if c.request == 0:
[2fb99de]133        print("Retrieving EC data!")
[403cbf1]134    else:
135        if c.request == 1:
136            print("Printing mars requests!")
137        elif c.request == 2:
138            print("Retrieving EC data and printing mars request!")
[631ba13]139        write_reqheader(os.path.join(c.inputdir, _config.FILE_MARS_REQUESTS))
[2fb99de]140
141    print("start date %s " % (c.start_date))
142    print("end date %s " % (c.end_date))
[d69b677]143
[631ba13]144    server = mk_server(c)
145
146    # if data are to be retrieved, clean up any old grib files
147    if c.request == 0 or c.request == 2:
[1d15e27]148        remove_old('*grb', c.inputdir)
[631ba13]149
150    # --------------  flux data ------------------------------------------------
[45c6337]151    start, end, datechunk = mk_dates(c, fluxes=True)
[631ba13]152    do_retrievement(c, server, start, end, datechunk, fluxes=True)
153
154    # --------------  non flux data --------------------------------------------
[45c6337]155    start, end, datechunk = mk_dates(c, fluxes=False)
[631ba13]156    do_retrievement(c, server, start, end, datechunk, fluxes=False)
157
158    return
159
160def write_reqheader(marsfile):
161    '''Writes header with column names into mars request file.
162
163    Parameters
164    ----------
[6f951ca]165    marsfile : str
[631ba13]166        Path to the mars request file.
167
168    Return
169    ------
170
171    '''
172    MR = MarsRetrieval(None, None)
173    attrs = vars(MR).copy()
174    del attrs['server']
175    del attrs['public']
176    with open(marsfile, 'w') as f:
177        f.write('request_number' + ', ')
178        f.write(', '.join(str(key) for key in sorted(attrs.iterkeys())))
179        f.write('\n')
180
181    return
182
183def mk_server(c):
184    '''Creates server connection if ECMWF WebAPI is available.
185
186    Parameters
187    ----------
[6f951ca]188    c : ControlFile
[631ba13]189        Contains all the parameters of CONTROL file and
190        command line.
191
192    Return
193    ------
[6f951ca]194    server : ECMWFDataServer or ECMWFService
[631ba13]195        Connection to ECMWF server via python interface ECMWF WebAPI.
196
197    '''
198    if c.ecapi:
[5bad6ec]199        if c.public:
200            server = ecmwfapi.ECMWFDataServer()
201        else:
202            server = ecmwfapi.ECMWFService("mars")
[d69b677]203    else:
204        server = False
205
[2fb99de]206    print('Using ECMWF WebAPI: ' + str(c.ecapi))
[991df6a]207
[631ba13]208    return server
[54a8a01]209
210
[631ba13]211def mk_dates(c, fluxes):
212    '''Prepares start and end date depending on flux or non flux data.
[54a8a01]213
[631ba13]214    If forecast for maximum one day (upto 24h) are to be retrieved, then
215    collect accumulation data (flux data) with additional days in the
216    beginning and at the end (used for complete disaggregation of
217    original period)
[54a8a01]218
[631ba13]219    If forecast data longer than 24h are to be retrieved, then
220    collect accumulation data (flux data) with the exact start and end date
221    (disaggregation will be done for the exact time period with
222    boundary conditions)
223
224    Since for basetime the extraction contains the 12 hours upfront,
225    if basetime is 0, the starting date has to be the day before and
226
227    Parameters
228    ----------
[6f951ca]229    c : ControlFile
[631ba13]230        Contains all the parameters of CONTROL file and
231        command line.
232
[6f951ca]233    fluxes : boolean, optional
[631ba13]234        Decides if the flux parameter settings are stored or
235        the rest of the parameter list.
236        Default value is False.
237
238    Return
239    ------
[6f951ca]240    start : datetime
[631ba13]241        The start date of the retrieving data set.
242
[6f951ca]243    end : datetime
[631ba13]244        The end date of the retrieving data set.
245
[6f951ca]246    chunk : datetime
[631ba13]247        Time period in days for one single mars retrieval.
248
249    '''
[ca867de]250    start = datetime.strptime(c.start_date, '%Y%m%d')
251    end = datetime.strptime(c.end_date, '%Y%m%d')
[631ba13]252    chunk = timedelta(days=int(c.date_chunk))
253
254    if c.basetime:
255        if c.basetime == '00':
256            start = start - timedelta(days=1)
[efdb01a]257
[dbf9d89]258    if not c.purefc and fluxes:
[ca867de]259        start = start - timedelta(days=1)
[631ba13]260        end = end + timedelta(days=1)
[ca867de]261
[631ba13]262    return start, end, chunk
[54a8a01]263
[1d15e27]264def remove_old(pattern, inputdir):
[3f36e42]265    '''Deletes old retrieval files from current input directory
266    matching the pattern.
[54a8a01]267
[631ba13]268    Parameters
269    ----------
[6f951ca]270    pattern : str
[631ba13]271        The sub string pattern which identifies the files to be deleted.
[991df6a]272
[6f951ca]273    inputdir : str, optional
[1d15e27]274        Path to the directory where the retrieved data is stored.
275
[631ba13]276    Return
277    ------
[991df6a]278
[631ba13]279    '''
[1d15e27]280    print('... removing old content of ' + inputdir)
[631ba13]281
[1d15e27]282    tobecleaned = UioFiles(inputdir, pattern)
[631ba13]283    tobecleaned.delete_files()
[54a8a01]284
285    return
286
[631ba13]287
[54a8a01]288def do_retrievement(c, server, start, end, delta_t, fluxes=False):
[274f9ef]289    '''Divides the complete retrieval period in smaller chunks and
290    retrieves the data from MARS.
291
292    Parameters
293    ----------
[6f951ca]294    c : ControlFile
[274f9ef]295        Contains all the parameters of CONTROL file and
296        command line.
[54a8a01]297
[6f951ca]298    server : ECMWFService or ECMWFDataServer
[274f9ef]299            The server connection to ECMWF.
[54a8a01]300
[6f951ca]301    start : datetime
[274f9ef]302        The start date of the retrieval.
[54a8a01]303
[6f951ca]304    end : datetime
[274f9ef]305        The end date of the retrieval.
[54a8a01]306
[6f951ca]307    delta_t : datetime
[274f9ef]308        Delta_t + 1 is the maximal time period of a single
309        retrieval.
[54a8a01]310
[6f951ca]311    fluxes : boolean, optional
[274f9ef]312        Decides if the flux parameters are to be retrieved or
313        the rest of the parameter list.
314        Default value is False.
[54a8a01]315
[274f9ef]316    Return
317    ------
[54a8a01]318
319    '''
320
321    # since actual day also counts as one day,
322    # we only need to add datechunk - 1 days to retrieval
323    # for a period
[ca867de]324    delta_t_m1 = delta_t - timedelta(days=1)
[54a8a01]325
[efdb01a]326    day = start
327    while day <= end:
[54a8a01]328        flexpart = EcFlexpart(c, fluxes)
329        tmpday = day + delta_t_m1
[ff99eae]330        if tmpday < end:
331            dates = day.strftime("%Y%m%d") + "/to/" + \
332                    tmpday.strftime("%Y%m%d")
333        else:
334            dates = day.strftime("%Y%m%d") + "/to/" + \
335                    end.strftime("%Y%m%d")
[efdb01a]336
[2fb99de]337        print("... retrieve " + dates + " in dir " + c.inputdir)
[64cf353]338
[ff99eae]339        try:
[5bad6ec]340            flexpart.retrieve(server, dates, c.public, c.request, c.inputdir)
[ff99eae]341        except IOError:
[54a8a01]342            my_error(c.mailfail, 'MARS request failed')
[efdb01a]343
[54a8a01]344        day += delta_t
[64cf353]345
[efdb01a]346    return
[d69b677]347
348if __name__ == "__main__":
[991df6a]349    main()
Note: See TracBrowser for help on using the repository browser.
hosted by ZAMG