Ejemplo n.º 1
0
Archivo: parse.py Proyecto: cpaulik/cis
def check_valid_min_max_args(min_val, max_val, step, parser, range_axis):
    """
    If a val range was specified, checks that they are valid numbers and the min is less than the max
    """
    from cis.parse_datetime import parse_as_number_or_datetime, parse_as_float_or_time_delta, \
        parse_datetimestr_to_std_time
    from cis.time_util import convert_datetime_to_std_time
    import datetime

    ax_range = {}

    if min_val is not None:
        dt = parse_as_number_or_datetime(min_val, range_axis + "min", parser)
        if isinstance(dt, datetime.datetime):
            ax_range[range_axis + "min"] = convert_datetime_to_std_time(dt)
        else:
            ax_range[range_axis + "min"] = dt

    if max_val is not None:
        dt = parse_as_number_or_datetime(max_val, range_axis + "max", parser)
        if isinstance(dt, datetime.datetime):
            ax_range[range_axis + "max"] = parse_datetimestr_to_std_time(str(datetime.datetime(*dt)))
        else:
            ax_range[range_axis + "max"] = dt
    if step is not None:
        ax_range[range_axis + "step"] = parse_as_float_or_time_delta(step, range_axis + "step", parser)

    return ax_range
Ejemplo n.º 2
0
Archivo: parse.py Proyecto: cpaulik/cis
def get_subset_limits(subsetlimits, parser):
    """
    :param subsetlimits:  List of subset limit strings
    :param parser:        The parser used to report errors
    :return: The parsed datagroups as a list of dictionaries
    """
    from cis.parse_datetime import parse_datetime, parse_as_number_or_datetime
    from cis.subsetting.subset_limits import SubsetLimits

    # Split into the limits for each dimension.
    split_input = split_outside_brackets(subsetlimits)
    if len(split_input) == 0:
        parser.error("Limits for at least one dimension must be specified for subsetting")

    limit_dict = {}
    for seg in split_input:
        # Parse out dimension name and limit value strings; the expected format is:
        # <dim_name>=[<start_value>,<end_value>]
        # or
        # <dim_name>=[<start_value>]
        match = re.match(r'(?P<dim>[^=]+)=\[(?P<start>[^],]+)(?:,(?P<end>[^],]+))?\]$', seg)
        if match is None or match.group('dim') is None or match.group('start') is None:
            parser.error(
                "A dimension for subsetting does not have dimension name, start value and/or end value specified")
        else:
            dim_name = match.group('dim')
            limit1 = match.group('start')
            if match.group('end') is None:
                limit2 = limit1
            else:
                limit2 = match.group('end')

            # If the dimension is specified as x, y, z, or t, assume that the dimension is spatial or temporal in the
            # obvious way. Otherwise, parse what is found as a date/time or number.
            is_time = None
            if dim_name.lower() == 't':
                limit1_parsed = parse_datetime(limit1, 'subset range start date/time', parser)
                limit2_parsed = parse_datetime(limit2, 'subset range end date/time', parser)
                is_time = True
            elif dim_name.lower() in ['x', 'y', 'z']:
                limit1_parsed = parse_float(limit1, 'subset range start coordinate', parser)
                limit2_parsed = parse_float(limit2, 'subset range start coordinate', parser)
                is_time = False
                if dim_name.lower() == 'x':
                    if not limit1_parsed <= limit2_parsed:
                        parser.error("Longitude limits must be monotonically increasing (i.e. for x[A,B] A <= B). For "
                                     "example, x=[90,-90] is invalid but x=[90,270] is valid")
                    if not limit2_parsed - limit1_parsed <= 360:
                        parser.error("Longitude limits should not be more than 360 degrees apart "
                                     "(i.e. for x[A,B] B-A <= 360)")
            else:
                limit1_parsed = parse_as_number_or_datetime(limit1, 'subset range start coordinate', parser)
                limit2_parsed = parse_as_number_or_datetime(limit2, 'subset range start coordinate', parser)
            limit_dict[dim_name] = SubsetLimits(limit1_parsed, limit2_parsed, is_time)
    return limit_dict
Ejemplo n.º 3
0
Archivo: parse.py Proyecto: cedadev/cis
def get_aggregate_grid(aggregategrid, parser):
    """
    :param aggregategrid: List of aggregate grid specifications
    :param parser:        The parser used to report errors
    :return: The parsed datagroups as a list of dictionaries
    """
    from cis.parse_datetime import parse_as_number_or_datetime, parse_as_number_or_datetime_delta

    # Split into the limits for each dimension.
    split_input = split_outside_brackets(aggregategrid)
    if len(split_input) == 0:
        parser.error("Limits for at least one dimension must be specified for aggregation")

    grid_dict = {}
    for seg in split_input:
        # Parse out dimension name and new grid spacing; the expected format is:
        # <dim_name>=[<start_value>,<end_value,<delta>]
        match = re.match(r'(?P<dim>[^=]+)(?:=)?(?:\[(?P<start>[^],]+)?(?:,(?P<end>[^],]+))?(?:,(?P<delta>[^]]+))?\])?',
                         seg)
        if match is None or match.group('dim') is None:
            parser.error("A dimension for aggregation does not have a valid dimension name")
        elif match.group('start') is None and match.group('delta') is None:
            # This is for gridded aggregation where we just have a list of dims with no grid
            grid_dict[match.group('dim')] = None
        elif match.group('end') is None:
            parser.error("A dimension for aggregation has a start point but no end or delta value, an end and a delta "
                         "value must be supplied, for example x=[0,360,30].")
        elif match.group('delta') is None:
            parser.error("A dimension for aggregation has a start point but no delta value, a delta value must be "
                         "supplied, for example x=[0,360,30].")
        else:
            dim_name = match.group('dim')

            start_parsed = parse_as_number_or_datetime(match.group('start'))
            end_parsed = parse_as_number_or_datetime(match.group('end'))
            delta_parsed = parse_as_number_or_datetime_delta(match.group('delta'))

            if dim_name.lower() == 'x':
                if not start_parsed <= end_parsed:
                    parser.error("Longitude grid must be monotonically increasing (i.e. for x[A,B,C] A <= B). For "
                                 "example, x=[90,-90,10] is invalid but x=[90,270,10] is valid")
                if not end_parsed - start_parsed <= 360:
                    parser.error("Longitude grid should not be wider than 360 degrees "
                                 "(i.e. for x[A,B,C] B-A <= 360)")

            grid_dict[dim_name] = slice(start_parsed, end_parsed, delta_parsed)

    return grid_dict
Ejemplo n.º 4
0
def parse_as_number_or_datetime_can_parse_float():
    dt = parse_as_number_or_datetime('12.345')
    assert (dt == 12.345)
Ejemplo n.º 5
0
def parse_as_number_or_datetime_can_parse_integer():
    dt = parse_as_number_or_datetime('2010')
    assert (dt == 2010)
Ejemplo n.º 6
0
def parse_as_number_or_datetime_can_parse_date_as_datetime():
    from datetime import datetime
    dt = parse_as_number_or_datetime('2010-07-01')
    assert (dt == datetime(2010, 7, 1))
Ejemplo n.º 7
0
Archivo: parse.py Proyecto: cpaulik/cis
def get_aggregate_grid(aggregategrid, parser):
    """
    :param aggregategrid: List of aggregate grid specifications
    :param parser:        The parser used to report errors
    :return: The parsed datagroups as a list of dictionaries
    """
    from cis.parse_datetime import parse_datetime, parse_datetime_delta, parse_as_number_or_datetime
    from cis.aggregation.aggregation_grid import AggregationGrid

    # Split into the limits for each dimension.
    split_input = split_outside_brackets(aggregategrid)
    if len(split_input) == 0:
        parser.error("Limits for at least one dimension must be specified for aggregation")

    grid_dict = {}
    for seg in split_input:
        # Parse out dimension name and new grid spacing; the expected format is:
        # <dim_name>=[<start_value>,<end_value,<delta>]
        match = re.match(r'(?P<dim>[^=]+)(?:=)?(?:\[(?P<start>[^],]+)?(?:,(?P<end>[^],]+))?(?:,(?P<delta>[^]]+))?\])?',
                         seg)
        if match is None or match.group('dim') is None:
            parser.error("A dimension for aggregation does not have a valid dimension name")
        elif match.group('start') is None and match.group('delta') is None:
            dim_name = match.group('dim')
            grid_dict[dim_name] = AggregationGrid(float('NaN'), float('NaN'), float('NaN'), None)
        elif match.group('end') is None:
            parser.error("A dimension for aggregation has a start point but no end or delta value, an end and a delta "
                         "value must be supplied, for example x=[0,360,30].")
        elif match.group('delta') is None:
            parser.error("A dimension for aggregation has a start point but no delta value, a delta value must be "
                         "supplied, for example x=[0,360,30].")
        else:
            dim_name = match.group('dim')
            start = match.group('start')
            end = match.group('end')
            delta = match.group('delta')

            # If the dimension is specified as x, y, z, p or t, assume that the dimension is spatial or temporal in the
            # obvious way. Otherwise, parse what is found as a date/time or number.
            is_time = None
            if dim_name.lower() == 't':
                start_parsed = parse_datetime(start, 'aggregation grid start date/time', parser)
                end_parsed = parse_datetime(end, 'aggregation grid end date/time', parser)
                delta_parsed = parse_datetime_delta(delta, 'aggregation grid delta date/time', parser)
                is_time = True
            elif dim_name.lower() in ['x', 'y', 'z', 'p']:
                start_parsed = parse_float(start, 'aggregation grid start coordinate', parser)
                end_parsed = parse_float(end, 'aggregation grid end coordinate', parser)
                delta_parsed = parse_float(delta, 'aggregation grid delta coordinate', parser)
                is_time = False
                if dim_name.lower() == 'x':
                    if not start_parsed <= end_parsed:
                        parser.error("Longitude grid must be monotonically increasing (i.e. for x[A,B,C] A <= B). For "
                                     "example, x=[90,-90,10] is invalid but x=[90,270,10] is valid")
                    if not end_parsed - start_parsed <= 360:
                        parser.error("Longitude grid should not be wider than 360 degrees "
                                     "(i.e. for x[A,B,C] B-A <= 360)")
            else:
                start_parsed = parse_as_number_or_datetime(start, 'aggregation grid start coordinate', parser)
                end_parsed = parse_as_number_or_datetime(end, 'aggregation grid end coordinate', parser)
                delta_parsed = parse_as_number_or_datetime(delta, 'aggregation grid delta coordinate', parser)
            grid_dict[dim_name] = AggregationGrid(start_parsed, end_parsed, delta_parsed, is_time)

    return grid_dict
Ejemplo n.º 8
0
def parse_as_number_or_datetime_can_parse_float():
    dt = parse_as_number_or_datetime('12.345')
    assert (dt == 12.345)
Ejemplo n.º 9
0
def parse_as_number_or_datetime_can_parse_integer():
    dt = parse_as_number_or_datetime('2010')
    assert (dt == 2010)
Ejemplo n.º 10
0
def parse_as_number_or_datetime_can_parse_date_as_datetime():
    from datetime import datetime
    dt = parse_as_number_or_datetime('2010-07-01')
    assert (dt == datetime(2010, 7, 1))
Ejemplo n.º 11
0
def parse_as_number_or_datetime_can_parse_float():
    parser = MockParser()
    dt = parse_as_number_or_datetime('12.345', 'limit arg', parser)
    assert (dt == 12.345)
Ejemplo n.º 12
0
def parse_as_number_or_datetime_can_parse_integer():
    parser = MockParser()
    dt = parse_as_number_or_datetime('2010', 'limit arg', parser)
    assert (dt == 2010)
Ejemplo n.º 13
0
def parse_as_number_or_datetime_can_parse_date_as_datetime():
    from datetime import datetime
    from cis.time_util import cis_standard_time_unit
    parser = MockParser()
    dt = parse_as_number_or_datetime('2010-07-01', 'date/time arg', parser)
    assert (datetime(*dt) == datetime(2010, 7, 1))