source: flex_extract.git/source/python/mods/checks.py @ d4696e0

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

bugfix retrievement with basetime parameter

  • Property mode set to 100644
File size: 23.8 KB
RevLine 
[97f4f4c]1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
[6f951ca]3#*******************************************************************************
[97f4f4c]4# @Author: Anne Philipp (University of Vienna)
5#
6# @Date: November 2018
7#
8# @Change History:
9#
10# @License:
[6f951ca]11#    (C) Copyright 2014-2019.
12#    Anne Philipp, Leopold Haimberger
[97f4f4c]13#
[6f951ca]14#    This work is licensed under the Creative Commons Attribution 4.0
15#    International License. To view a copy of this license, visit
16#    http://creativecommons.org/licenses/by/4.0/ or send a letter to
17#    Creative Commons, PO Box 1866, Mountain View, CA 94042, USA.
[97f4f4c]18#*******************************************************************************
[6f951ca]19'''This module contains check methods for the CONTROL paramaters.
20'''
[97f4f4c]21
22# ------------------------------------------------------------------------------
23# MODULES
24# ------------------------------------------------------------------------------
25
[45fc9b4]26import os
[6f951ca]27import sys
[3f36e42]28import _config
[45fc9b4]29import exceptions
30from tools import my_error, silent_remove
31from datetime import datetime
[97f4f4c]32# ------------------------------------------------------------------------------
33# FUNCTIONS
34# ------------------------------------------------------------------------------
35
[45fc9b4]36def check_logicals_type(c, logicals):
37    '''Check that the logical variables have correct type integer.
38
39    Parameters
40    ----------
[6f951ca]41    c : ControlFile
[45fc9b4]42        Contains all the parameters of CONTROL file and
43        command line.
44
[6f951ca]45    logicals : list of (str or int)
[45fc9b4]46        Names of the switches that are used to control the flow of the
47        program.
48
49    Return
50    ------
51
52    '''
53
54    for var in logicals:
55        if not isinstance(getattr(c, var), int):
56            setattr(c, var, int(getattr(c, var)))
57
58    return
[97f4f4c]59
[3f36e42]60def check_grid(grid):
[a55ac71]61    '''Convert grid into correct Lat/Lon format. E.g. '0.5/0.5'
62
63    Checks on format of original grid. Wether it is in the order of 1000 or 1.
64    Convert to correct grid format and substitute into "Lat/Lon" format string.
65
66    Parameters
67    ----------
[6f951ca]68    grid : str
[a55ac71]69        Contains grid information
70
71    Return
72    ------
[6f951ca]73    grid : str
[a55ac71]74        Contains grid in format Lat/lon. E.g. 0.1/0.1
75    '''
[97f4f4c]76
[3f36e42]77    if 'N' in grid:
78        return grid
[97f4f4c]79    if '/' in grid:
80        gridx, gridy = grid.split('/')
81        if gridx == gridy:
82            grid = gridx
83        else:
84            raise ValueError('GRID parameter contains two values '
85                             'which are unequal %s' (grid))
86    # determine grid format
87    if float(grid) / 100. >= 0.5:
88        # grid is defined in 1/1000 degrees; old format
89        grid = '{}/{}'.format(float(grid) / 1000.,
90                              float(grid) / 1000.)
91    elif float(grid) / 100. < 0.5:
92        # grid is defined in normal degree; new format
93        grid = '{}/{}'.format(float(grid), float(grid))
94
[3f36e42]95    return grid
96
97def check_area(grid, area, upper, lower, left , right):
[a55ac71]98    '''Defines the correct area string.
99
100    Checks on the format of the four area components. Wether it is of
101    the order of 1000 or 1. Also checks wether area was already set by command
102    line, then the four components are overwritten.
103    Convert to correct format of the order of magnitude "1" and sets the
104    area parameter (North/West/South/East).
105    E.g.: -5./20./10./10.
[3f36e42]106
[a55ac71]107    Parameters
108    ----------
[6f951ca]109    grid : str
[45fc9b4]110        Contains grid information.
111
[6f951ca]112    area : str
[45fc9b4]113        Contains area informtion.
114
[6f951ca]115    upper : str
[45fc9b4]116        The northern most latitude.
117
[6f951ca]118    lower : str
[45fc9b4]119        The souther most latitude.
120
[6f951ca]121    left : str
[45fc9b4]122        The western most longitude.
123
[6f951ca]124    right : str
[45fc9b4]125        The eastern most longiude.
[3f36e42]126
[a55ac71]127    Return
128    ------
[6f951ca]129    grid : str
[a55ac71]130        Contains grid in format Lat/lon. E.g. 0.1/0.1
[3f36e42]131    '''
132    if 'N' in grid:  # Gaussian output grid
133        area = 'G'
134        return area
135
136    # if area was provided decompose area into its 4 components
137    if area:
138        components = area.split('/')
139        upper, left, lower, right = components
140
[97f4f4c]141    # determine area format
[45fc9b4]142    if ((abs(float(upper) / 10000.) >= 0.01 or float(upper) / 1000. == 0. ) and
143        (abs(float(lower) / 10000.) >= 0.01 or float(lower) / 1000. == 0. ) and
144        (abs(float(left) / 10000.) >= 0.01 or float(left) / 1000. == 0. ) and
145        (abs(float(right) / 10000.) >= 0.01 or float(right) / 1000. == 0.)):
[97f4f4c]146        # area is defined in 1/1000 degrees; old format
147        area = '{}/{}/{}/{}'.format(float(upper) / 1000.,
148                                    float(left) / 1000.,
149                                    float(lower) / 1000.,
150                                    float(right) / 1000.)
[45fc9b4]151    elif (abs(float(upper) / 10000.) < 0.05 and
152          abs(float(lower) / 10000.) < 0.05 and
153          abs(float(left) / 10000.) < 0.05 and
154          abs(float(right) / 10000.) < 0.05):
[97f4f4c]155        # area is already in new format
156        area = '{}/{}/{}/{}'.format(float(upper),
157                                    float(left),
158                                    float(lower),
159                                    float(right))
160    else:
161        raise ValueError('The area components have different '
[d2febd4]162                         'formats (upper, lower, left, right): '
163                         '{}/{}/{}/{}'.format(str(upper), str(lower),
164                                              str(left) , str(right)))
[97f4f4c]165
[3f36e42]166    return area
167
168def check_levels(levelist, level):
[a55ac71]169    '''Defines correct level list and guarantees that the maximum level is
170    one of the available maximum levels.
[3f36e42]171
172    Parameters
173    ----------
[6f951ca]174    levelist : str
[a55ac71]175        Specifies the level list.
176        Examples: model level: 1/to/137, pressure levels: 500/to/1000
177
[6f951ca]178    level : str
[a55ac71]179        Specifies the maximum level.
[3f36e42]180
181    Return
182    ------
[6f951ca]183    levelist : str
[a55ac71]184        Specifies the required levels. It has to have a valid
185        correspondence to the selected levtype.
186        Examples: model level: 1/to/137, pressure levels: 500/to/1000
187
[6f951ca]188    level : str
[a55ac71]189        Specifies the maximum level. It has to be one of the
190        available maximum level number as contained in the variable
191        MAX_LEVEL_LIST in "_config". E.g. [16, 19, 31, 40, 50, 60, 62, 91, 137]
[3f36e42]192
193    '''
194    # assure consistency of levelist and level
195    if not levelist and not level:
196        raise ValueError('ERROR: neither levelist nor level '
197                         'specified in CONTROL file')
198    elif not levelist and level:
199        levelist = '1/to/' + level
200    elif (levelist and not level) or \
201         (levelist[-1] != level[-1]):
202        level = levelist.split('/')[-1]
203    else:
204        pass
205
206    # check if max level is a valid level
207    if int(level) not in _config.MAX_LEVEL_LIST:
208        raise ValueError('ERROR: \n'
209                         'LEVEL must be the maximum level of a specified '
210                         'level list from ECMWF, e.g. {} \n'
211                         'Check parameter "LEVEL" or the max level of '
212                         '"LEVELIST"!'.format(str(_config.MAX_LEVEL_LIST)))
213
214    return levelist, level
215
216
217def check_ppid(c, ppid):
218    '''Sets the current PPID.
219
220    Parameters
221    ----------
[6f951ca]222    c : ControlFile
[3f36e42]223            Contains all the parameters of CONTROL file and
224            command line.
225
[6f951ca]226    ppid : int or None
[3f36e42]227        Contains the ppid number provided by the command line parameter
228        of is None otherwise.
229
230    Return
231    ------
232
233    '''
234
235    if not ppid:
236        c.ppid = str(os.getppid())
237    else:
238        c.ppid = ppid
239
240    return
241
[4d3b052]242
[45fc9b4]243def check_purefc(ftype):
[4d3b052]244    '''Check for a pure forecast mode.
245
246    Parameters
247    ----------
[6f951ca]248    ftype : list of str
[4d3b052]249        List of field types.
250
251    Return
252    ------
253    True or False:
254        True if pure forecasts are to be retrieved. False if there are
255        analysis fields in between.
256    '''
257
[45fc9b4]258    if 'AN' not in ftype and '4V' not in ftype:
[4d3b052]259        # pure forecast
[45fc9b4]260        return 1
261
262    return 0
263
264
265def check_step(step, mailfail):
266    '''Checks on step format and convert into a list of steps.
267
268    If the steps were defined with "to" and "by" they are converted into
269    a list of steps. If the steps were set in a string, it is
270    converted into a list.
271
272    Parameters
273    ----------
[6f951ca]274    step : list of str or str
[45fc9b4]275        Specifies the forecast time step from forecast base time.
276        Valid values are hours (HH) from forecast base time.
277
[6f951ca]278    mailfail : list of str
[45fc9b4]279        Contains all email addresses which should be notified.
280        It might also contain just the ecmwf user name which will trigger
281        mailing to the associated email address for this user.
282
283    Return
284    ------
[6f951ca]285    step : list of str
[45fc9b4]286        List of forecast steps in format e.g. [001, 002, ...]
287    '''
288
289    if '/' in step:
290        steps = step.split('/')
291        if 'to' in step.lower() and 'by' in step.lower():
292            ilist = np.arange(int(steps[0]),
293                              int(steps[2]) + 1,
294                              int(steps[4]))
295            step = ['{:0>3}'.format(i) for i in ilist]
296        elif 'to' in step.lower() and 'by' not in step.lower():
297            my_error(mailfail, step + ':\n' +
298                     'if "to" is used in steps parameter, '
299                     'please use "by" as well')
300        else:
301            step = steps
302
303    if not isinstance(step, list):
304        step = [step]
305
306    return step
307
308def check_type(ftype, steps):
309    '''Check if type variable is of type list and if analysis field has
310    forecast step 0.
311
312    Parameters
313    ----------
[6f951ca]314    ftype : list of str or str
[45fc9b4]315        List of field types.
316
[6f951ca]317    steps : str
[45fc9b4]318        Specifies the forecast time step from forecast base time.
319        Valid values are hours (HH) from forecast base time.
320
321    Return
322    ------
[6f951ca]323    ftype : list of str
[45fc9b4]324        List of field types.
325    '''
326    if not isinstance(ftype, list):
327        ftype = [ftype]
328
329    for i, val in enumerate(ftype):
330        if ftype[i] == 'AN' and int(steps[i]) != 0:
331            print('Analysis retrievals must have STEP = 0 (now set to 0)')
332            ftype[i] = 0
333
334    return ftype
335
336def check_time(ftime):
337    '''Check if time variable is of type list. Otherwise convert to list.
338
339    Parameters
340    ----------
[6f951ca]341    ftime : list of str or str
[45fc9b4]342        The time in hours of the field.
343
344    Return
345    ------
[6f951ca]346    ftime : list of str
[45fc9b4]347        The time in hours of the field.
348    '''
349    if not isinstance(ftime, list):
350        ftime = [ftime]
351
352    return ftime
353
354def check_len_type_time_step(ftype, ftime, steps, maxstep, purefc):
355    '''Check if
356
357    Parameters
358    ----------
[6f951ca]359    ftype : list of str
[45fc9b4]360        List of field types.
361
[6f951ca]362    ftime : list of str or str
[45fc9b4]363        The time in hours of the field.
364
[6f951ca]365    steps : str
[45fc9b4]366        Specifies the forecast time step from forecast base time.
367        Valid values are hours (HH) from forecast base time.
368
[6f951ca]369    maxstep : int
[45fc9b4]370        The maximum forecast time step in hours from the forecast base time.
371        This is the maximum step for non flux (accumulated) forecast data.
372
[6f951ca]373    purefc : int
[45fc9b4]374        Switch for definition of pure forecast mode or not.
375
376    Return
377    ------
[6f951ca]378    ftype : list of str
[45fc9b4]379        List of field types.
380
[6f951ca]381    ftime : list of str
[45fc9b4]382        The time in hours of the field.
383
[6f951ca]384    steps : str
[45fc9b4]385        Specifies the forecast time step from forecast base time.
386        Valid values are hours (HH) from forecast base time.
387    '''
388    if not (len(ftype) == len(ftime) == len(steps)):
389        raise ValueError('ERROR: The number of field types, times and steps '
390                         'are not the same! Please check the setting in the '
391                         'CONTROL file!')
392
393    # if pure forecast is selected and only one field type/time is set
394    # prepare a complete list of type/time/step combination upto maxstep
395    if len(ftype) == 1 and purefc:
396        ftype = []
397        steps = []
398        ftime = []
399        for i in range(0, maxstep + 1):
400            ftype.append(ftype[0])
401            steps.append('{:0>3}'.format(i))
402            ftime.append(ftime[0])
403
404    return ftype, ftime, steps
405
406def check_mail(mail):
407    '''Check the string of mail addresses, seperate them and convert to a list.
408
409    Parameters
410    ----------
[6f951ca]411    mail : list of str or str
[45fc9b4]412        Contains email addresses for notifications.
413        It might also contain just the ecmwf user name which will trigger
414        mailing to the associated email address for this user.
415
416    Return
417    ------
[6f951ca]418    mail : list of str
[45fc9b4]419        Contains email addresses for notifications.
420        It might also contain just the ecmwf user name which will trigger
421        mailing to the associated email address for this user.
422
423    '''
424    if not isinstance(mail, list):
425        if ',' in mail:
426            mail = mail.split(',')
427        elif ' ' in mail:
428            mail = mail.split()
429        else:
430            mail = [mail]
431
432    return mail
433
434def check_queue(queue, gateway, destination, ecuid, ecgid):
435    '''Check if the necessary ECMWF parameters are set if the queue is
436    one of the QUEUES_LIST (in _config).
437
438    Parameters
439    ----------
[6f951ca]440    queue : str
[45fc9b4]441        Name of the queue if submitted to the ECMWF servers.
442        Used to check if ecuid, ecgid, gateway and destination
443        are set correctly and are not empty.
444
[6f951ca]445    gateway : str
[45fc9b4]446        The address of the gateway server.
447
[6f951ca]448    destination : str
[45fc9b4]449        The name of the destination of the gateway server for data
450        transfer through ectrans. E.g. name@genericSftp
451
[6f951ca]452    ecuid : str
[45fc9b4]453        ECMWF user id.
454
[6f951ca]455    ecgid : str
[45fc9b4]456        ECMWF group id.
457
458    Return
459    ------
460
461    '''
462    if queue in _config.QUEUES_LIST and \
463        not gateway or not destination or \
464        not ecuid or not ecgid:
465        raise ValueError('\nEnvironment variables GATEWAY, DESTINATION, ECUID '
466                         'and ECGID were not set properly! \n '
467                         'Please check for existence of file "ECMWF_ENV" '
468                         'in the run directory!')
469    return
470
471def check_pathes(idir, odir, fpdir, fedir):
472    '''Check if output and flexpart pathes are set.
473
474    Parameters
475    ----------
[6f951ca]476    idir : str
[45fc9b4]477        Path to the temporary directory for MARS retrieval data.
478
[6f951ca]479    odir : str
[45fc9b4]480        Path to the final output directory where the FLEXPART input files
481        will be stored.
[4d3b052]482
[6f951ca]483    fpdir : str
[45fc9b4]484        Path to FLEXPART root directory.
[4d3b052]485
[6f951ca]486    fedir : str
[45fc9b4]487        Path to flex_extract root directory.
488
489    Return
490    ------
[6f951ca]491    odir : str
[45fc9b4]492        Path to the final output directory where the FLEXPART input files
493        will be stored.
494
[6f951ca]495    fpdir : str
[45fc9b4]496        Path to FLEXPART root directory.
497
498    '''
499    if not fpdir:
500        fpdir = fedir
501
502    if not odir:
503        odir = idir
504
505    return odir, fpdir
506
507def check_dates(start, end):
508    '''Checks if there is at least a start date for a one day retrieval.
509
510    Checks if end date lies after start date and end date is set.
511
512    Parameters
513    ----------
[6f951ca]514    start : str
[45fc9b4]515        The start date of the retrieval job.
516
[6f951ca]517    end : str
[45fc9b4]518        The end date of the retrieval job.
519
520    Return
521    ------
[6f951ca]522    start : str
[45fc9b4]523        The start date of the retrieval job.
524
[6f951ca]525    end : str
[45fc9b4]526        The end date of the retrieval job.
[4d3b052]527
[3f36e42]528    '''
[45fc9b4]529    # check for having at least a starting date
530    # otherwise program is not allowed to run
531    if not start:
532        raise ValueError('start_date was neither specified in command line nor '
533                         'in CONTROL file.\n'
534                         'Try "{} -h" to print usage information'
535                         .format(sys.argv[0].split('/')[-1]) )
536
537    # retrieve just one day if end_date isn't set
538    if not end:
539        end = start
540
541    dstart = datetime.strptime(start, '%Y%m%d')
542    dend = datetime.strptime(end, '%Y%m%d')
543    if dstart > dend:
544        raise ValueError('ERROR: Start date is after end date! \n'
545                         'Please adapt the dates in CONTROL file or '
546                         'command line! (start={}; end={})'.format(start, end))
547
548    return start, end
549
550def check_maxstep(maxstep, steps):
551    '''Convert maxstep into integer if it is already given. Otherwise, select
552    maxstep by going through the steps list.
553
554    Parameters
555    ----------
[6f951ca]556    maxstep : str
[45fc9b4]557        The maximum forecast time step in hours from the forecast base time.
558        This is the maximum step for non flux (accumulated) forecast data.
559
[6f951ca]560    steps : str
[45fc9b4]561        Specifies the forecast time step from forecast base time.
562        Valid values are hours (HH) from forecast base time.
563
564    Return
565    ------
[6f951ca]566    maxstep : int
[45fc9b4]567        The maximum forecast time step in hours from the forecast base time.
568        This is the maximum step for non flux (accumulated) forecast data.
569
570    '''
571    # if maxstep wasn't provided
572    # search for it in the "step" parameter
573    if not maxstep:
574        maxstep = 0
575        for s in steps:
576            if int(s) > maxstep:
577                maxstep = int(s)
578    else:
579        maxstep = int(maxstep)
580
581    return maxstep
582
583def check_basetime(basetime):
584    '''Check if basetime is set and contains one of the two
585    possible values (0, 12).
586
587    Parameters
588    ----------
[d4696e0]589    basetime : int or str or None
[45fc9b4]590        The time for a half day retrieval. The 12 hours upfront are to be
591        retrieved.
592
593    Return
594    ------
[d4696e0]595    basetime : int or None
596        The time for a half day retrieval. The 12 hours upfront are to be
597        retrieved.
[45fc9b4]598    '''
[d4696e0]599    if basetime is not None:
600        basetime = int(basetime)
601        if basetime != 0 and basetime != 12:
[45fc9b4]602            raise ValueError('ERROR: Basetime has an invalid value '
603                             '-> {}'.format(str(basetime)))
[d4696e0]604    return basetime
[45fc9b4]605
606def check_request(request, marsfile):
607    '''Check if there is an old mars request file and remove it.
608
609    Parameters
610    ----------
[6f951ca]611    request : int
[45fc9b4]612        Selects the mode of retrieval.
613        0: Retrieves the data from ECMWF.
614        1: Prints the mars requests to an output file.
615        2: Retrieves the data and prints the mars request.
616
[6f951ca]617    marsfile : str
[45fc9b4]618        Path to the mars request file.
619
620    Return
621    ------
622
623    '''
624    if request != 0:
625        if os.path.isfile(marsfile):
626            silent_remove(marsfile)
627    return
628
629def check_public(public, dataset):
630    '''Check wether the dataset parameter is set for a
631    public data set retrieval.
[3f36e42]632
633    Parameters
634    ----------
[6f951ca]635    public : int
[45fc9b4]636        Specifies if public data are to be retrieved or not.
637
[6f951ca]638    dataset : str
[45fc9b4]639        Specific name which identifies the public dataset.
[3f36e42]640
641    Return
642    ------
643
644    '''
[45fc9b4]645    if public and not dataset:
646        raise ValueError('ERROR: If public mars data wants to be retrieved, '
647                         'the "dataset"-parameter has to be set too!')
[3f36e42]648    return
[45fc9b4]649
650def check_acctype(acctype, ftype):
651    '''Guarantees that the accumulation field type is set.
652
653    If not set, it is derivated as in the old method (TYPE[1]).
654
655    Parameters
656    ----------
[6f951ca]657    acctype : str
[45fc9b4]658        The field type for the accumulated forecast fields.
659
[6f951ca]660    ftype : list of str
[45fc9b4]661        List of field types.
662
663    Return
664    ------
[6f951ca]665    acctype : str
[45fc9b4]666        The field type for the accumulated forecast fields.
667    '''
668    if not acctype:
669        print('... Control parameter ACCTYPE was not defined.')
670        try:
671            if len(ftype) == 1 and ftype[0] != 'AN':
[d4696e0]672                print('... Use same field type as for the non-flux fields.')
[45fc9b4]673                acctype = ftype[0]
674            elif len(ftype) > 1 and ftype[1] != 'AN':
[d4696e0]675                print('... Use old setting by using TYPE[1] for flux forecast!')
[45fc9b4]676                acctype = ftype[1]
677        except:
678            raise ValueError('ERROR: Accumulation field type could not be set!')
679    else:
680        if acctype.upper() == 'AN':
681            raise ValueError('ERROR: Accumulation forecast fields can not be '
682                             'of type "analysis"!')
683    return acctype
684
685
[d4696e0]686def check_acctime(acctime, marsclass, purefc):
[45fc9b4]687    '''Guarantees that the accumulation forecast times were set.
688
[d4696e0]689    If it is not set, it tries to set the value for some of the
[45fc9b4]690    most commonly used data sets. Otherwise it raises an error.
691
692    Parameters
693    ----------
[6f951ca]694    acctime : str
[45fc9b4]695        The starting time from the accumulated forecasts.
696
[d4696e0]697    marsclass : str
698        ECMWF data classification identifier.
[45fc9b4]699
[6f951ca]700    purefc : int
[45fc9b4]701        Switch for definition of pure forecast mode or not.
702
703    Return
704    ------
[6f951ca]705    acctime : str
[45fc9b4]706        The starting time from the accumulated forecasts.
707    '''
[d4696e0]708
[45fc9b4]709    if not acctime:
710        print('... Control parameter ACCTIME was not defined.')
[6f951ca]711        print('... Value will be set depending on field type:\n '
[d4696e0]712              '\t\t EA=06/18\n\t\t EI/OD=00/12\n\t\t EP=18')
713        if marsclass.upper() == 'EA': # Era 5
[45fc9b4]714            acctime = '06/18'
[d4696e0]715        elif marsclass.upper() == 'EI': # Era-Interim
[45fc9b4]716            acctime = '00/12'
[d4696e0]717        elif marsclass.upper() == 'EP': # CERA
[45fc9b4]718            acctime = '18'
[d4696e0]719        elif marsclass.upper() == 'OD' and not purefc: # On-demand
[45fc9b4]720            acctime = '00/12'
721        else:
722            raise ValueError('ERROR: Accumulation forecast time can not '
723                             'automatically be derived!')
724    return acctime
725
[d4696e0]726def check_accmaxstep(accmaxstep, marsclass, purefc, maxstep):
[45fc9b4]727    '''Guarantees that the accumulation forecast step were set.
728
729    Parameters
730    ----------
[6f951ca]731    accmaxstep : str
[45fc9b4]732        The maximum forecast step for the accumulated forecast fields.
733
[d4696e0]734    marsclass : str
735        ECMWF data classification identifier.
[45fc9b4]736
[6f951ca]737    purefc : int
[45fc9b4]738        Switch for definition of pure forecast mode or not.
739
[6f951ca]740    maxstep : str
[45fc9b4]741        The maximum forecast time step in hours from the forecast base time.
742        This is the maximum step for non flux (accumulated) forecast data.
743
744    Return
745    ------
[6f951ca]746    accmaxstep : str
[45fc9b4]747        The maximum forecast step for the accumulated forecast fields.
748    '''
749    if not accmaxstep:
750        print('... Control parameter ACCMAXSTEP was not defined.')
751        print('... Value will be set depending on field type/time: '
[d4696e0]752              '\n\t\t EA/EI/OD=12\n\t\t EP=24')
753        if marsclass.upper() in ['EA', 'EI', 'OD'] and not purefc:
[45fc9b4]754            # Era 5, Era-Interim, On-demand operational
755            accmaxstep = '12'
[d4696e0]756        elif marsclass.upper() == 'EP': # CERA
[45fc9b4]757            accmaxstep = '18'
758        elif purefc and accmaxstep != maxstep:
759            accmaxstep = maxstep
760            print('... For pure forecast mode, the accumulated forecast must '
761                  'have the same maxstep as the normal forecast fields!\n'
762                  '\t\t Accmaxstep was set to maxstep!')
763        else:
764            raise ValueError('ERROR: Accumulation forecast step can not '
765                             'automatically be derived!')
766    else:
767        if purefc and int(accmaxstep) != int(maxstep):
768            accmaxstep = maxstep
769            print('... For pure forecast mode, the accumulated forecast must '
770                          'have the same maxstep as the normal forecast fields!\n'
771                          '\t\t Accmaxstep was set to maxstep!')
772    return accmaxstep
773
774def check_addpar(addpar):
775    '''Check that addpar has correct format of additional parameters in
776    a single string, so that it can be easily appended to the hard coded
777    parameters that are retrieved in any case.
778
779    Parameters
780    ----------
[6f951ca]781    addpar : str or list of str
[45fc9b4]782        List of additional parameters to be retrieved.
783
784    Return
785    ------
[6f951ca]786    addpar : str
[45fc9b4]787        List of additional parameters to be retrieved.
788    '''
789
790    if addpar and isinstance(addpar, str):
791        if '/' in addpar:
792            parlist = addpar.split('/')
793            parlist = [p for p in parlist if p is not '']
794        else:
795            parlist = [addpar]
796
797        addpar = '/' + '/'.join(parlist)
798
799    return addpar
800
[f2616a3]801
802def check_job_chunk(job_chunk):
[6f951ca]803    '''Checks that if job chunk is set, the number is positive and non zero.
[f2616a3]804
805    Parameters
806    ----------
[6f951ca]807    job_chunk : int
[f2616a3]808        The number of days for a single job script.
809
810    Return
811    ------
[6f951ca]812    job_chunk : int
[f2616a3]813        The number of days for a single job script.
814    '''
[6f951ca]815    if not job_chunk:
816        return job_chunk
817
[f2616a3]818    if job_chunk < 0:
819        raise ValueError('ERROR: The number of job chunk is negative!\n'
820                         'It has to be a positive number!')
821    elif job_chunk == 0:
822        job_chunk = None
823    else:
824        pass
825
826    return job_chunk
Note: See TracBrowser for help on using the repository browser.
hosted by ZAMG