Example #1
0
    def test_string(self):
        p = Parser()

        assert p.evaluate('"test"') == 'test'
        assert p.evaluate("'test'") == 'test'
        assert p.evaluate('"test" == "test"') == True
        assert p.evaluate('"foo" == "bar"') == False
Example #2
0
    def test_string(self):
        p = Parser()

        assert p.evaluate('"test"') == "test"
        assert p.evaluate("'test'") == "test"
        assert p.evaluate('"test" == "test"') == True
        assert p.evaluate('"foo" == "bar"') == False
Example #3
0
    def evaluate_expression(self, expression, context={}):
        try:
            # Operations against masked arrays are really slow, so take a regular array view, then back to a masked
            # array afterwards. Todo: find a better solution long-term
            expr_context = {
                k: v.view(ndarray) if is_masked(v) else v
                for k, v in context.items()
            }

            result = Parser().evaluate(expression, context=expr_context)

            if is_ndarray(result):
                for value in context.values():
                    if is_masked(value):
                        if is_masked(result) and is_masked(value):
                            result.mask = result.mask | value.mask
                        elif is_masked(value):
                            result = masked_array(result, mask=value.mask)

                        result = Raster(result, value.extent, value.x_dim,
                                        value.y_dim, value.y_increasing)
                        break

            return result

        except (SyntaxError, NameError) as e:
            raise ExecutionError(
                'The expression is invalid ({0}): {1}\nContext: {2}'.format(
                    str(e), expression, str(context)), self)
Example #4
0
    def evaluate_expression(self, expression, context={}):
        try:
            # Operations against masked arrays are really slow, so take a regular array view, then back to a masked
            # array afterwards. Todo: find a better solution long-term
            expr_context = {k: v.view(numpy.ndarray) if is_masked(v) else v for k, v in six.iteritems(context)}

            result = Parser().evaluate(expression, context=expr_context)

            if is_ndarray(result):
                for value in six.itervalues(context):
                    if is_masked(value):
                        if is_masked(result) and is_masked(value):
                            result.mask = result.mask | value.mask
                        elif is_masked(value):
                            result = numpy.ma.masked_array(result, mask=value.mask)

                        result = Raster(result, value.extent, value.x_dim, value.y_dim, value.y_increasing)
                        break

            return result

        except (SyntaxError, NameError) as e:
            raise ExecutionError(
                'The expression is invalid ({0}): {1}\nContext: {2}'.format(str(e), expression, str(context)),
                self
            )
Example #5
0
    def test_ndarray(self):
        p = Parser()
        arr = numpy.array([1, 2, 3])
        context = {"x": arr}

        assert (p.evaluate("x * 2", context=context) == (arr * 2)).all()
        assert (p.evaluate("x <= 2", context=context) == (arr <= 2)).all()
        assert (p.evaluate("x < 2 or x > 2", context=context) == numpy.array([True, False, True])).all()
        assert (p.evaluate("x > 1 and x < 3", context=context) == numpy.array([False, True, False])).all()
Example #6
0
    def test_variables(self):
        p = Parser()
        context = {"x": 5, "y": 2}

        assert p.evaluate("x", context=context) == 5
        assert p.evaluate("y", context=context) == 2
        assert p.evaluate("x + y", context=context) == 7
        assert p.evaluate("x > y", context=context) == True
        assert p.evaluate("(x + 1) * y", context=context) == 12
        assert p.evaluate("x == 5 and y == 2", context=context) == True
Example #7
0
    def test_bool(self):
        p = Parser()

        assert p.evaluate('true') == True
        assert p.evaluate('True') == True
        assert p.evaluate('TRUE') == True
        assert p.evaluate('false') == False
        assert p.evaluate('False') == False
        assert p.evaluate('FALSE') == False
        assert p.evaluate(
            '1 > 2 == False'
        ) == True  # Note: this differs from Python's behavior
        assert p.evaluate('(1 > 2) == False') == True
Example #8
0
    def test_bool(self):
        p = Parser()

        assert p.evaluate("true") == True
        assert p.evaluate("True") == True
        assert p.evaluate("TRUE") == True
        assert p.evaluate("false") == False
        assert p.evaluate("False") == False
        assert p.evaluate("FALSE") == False
        assert p.evaluate("1 > 2 == False") == True  # Note: this differs from Python's behavior
        assert p.evaluate("(1 > 2) == False") == True
Example #9
0
    def test_variables(self):
        p = Parser()
        context = {'x': 5, 'y': 2}

        assert p.evaluate('x', context=context) == 5
        assert p.evaluate('y', context=context) == 2
        assert p.evaluate('x + y', context=context) == 7
        assert p.evaluate('x > y', context=context) == True
        assert p.evaluate('(x + 1) * y', context=context) == 12
        assert p.evaluate('x == 5 and y == 2', context=context) == True
Example #10
0
    def test_ndarray(self):
        p = Parser()
        arr = numpy.array([1, 2, 3])
        context = {'x': arr}

        assert (p.evaluate('x * 2', context=context) == (arr * 2)).all()
        assert (p.evaluate('x <= 2', context=context) == (arr <= 2)).all()
        assert (p.evaluate('x < 2 or x > 2',
                           context=context) == numpy.array([True, False,
                                                            True])).all()
        assert (p.evaluate('x > 1 and x < 3', context=context) == numpy.array(
            [False, True, False])).all()
Example #11
0
    def test_item_index(self):
        p = Parser()
        context = {
            'arr1': [1, 2, 3],
            'arr2': (1, 2, 3),
            'arr3': numpy.array([1, 2, 3]),
            'arr4': [[1, 2, 3]],
            'dict': {
                'one': 1,
                'two': 2
            }
        }

        assert p.evaluate('arr1[0]', context=context) == 1
        assert p.evaluate('arr2[0]', context=context) == 1
        assert p.evaluate('arr3[0]', context=context) == 1
        assert p.evaluate('dict["one"]', context=context) == 1
        assert p.evaluate('arr1[1+1]', context=context) == 3
        assert p.evaluate('arr4[0][1]', context=context) == 2

        with pytest.raises(TypeError):
            p.evaluate('arr1["one"]', context=context)

        with pytest.raises(IndexError):
            p.evaluate('arr1[3]', context=context)

        with pytest.raises(KeyError):
            p.evaluate('dict[1]', context=context)
Example #12
0
    def test_conditionals(self):
        p = Parser()

        assert p.evaluate('1 and 1') == 1
        assert p.evaluate('1 and 0') == 0
        assert p.evaluate('1 or 0') == 1
        assert p.evaluate('0 or 1') == 1
        assert p.evaluate('1 and 1 and 1') == 1
        assert p.evaluate('1 and 1 and 0') == 0
        assert p.evaluate('1 and 1 or 0') == 1
        assert p.evaluate('0 and 1 or 1') == 1
        assert p.evaluate('0 and (1 or 1)') == 0
        assert p.evaluate('1 and 1 and 1 or 0') == 1
        assert p.evaluate('0 and 1 and 1 or 1') == 1
        assert p.evaluate('0 and 1 and 1 or 0') == 0

        assert p.evaluate('1 > 2') == False
        assert p.evaluate('1 < 1') == False
        assert p.evaluate('1 < 2') == True
        assert p.evaluate('1 == 1') == True
        assert p.evaluate('1 <= 1') == True
        assert p.evaluate('1 <= 2') == True
        assert p.evaluate('1 >= 1') == True
        assert p.evaluate('1 >= 2') == False
        assert p.evaluate('1 + 1 >= 2') == True
        assert p.evaluate('1 + 1 > 2 - 1') == True
        assert p.evaluate('1 <= 2 and 1 + 1 >= 2') == True
        assert p.evaluate('1 <= 2 - 1 and 1 >= 2 - 1') == True
Example #13
0
    def test_functions(self):
        p = Parser()
        arr = numpy.concatenate((numpy.arange(25), numpy.arange(100, 150)))
        nd_arr = numpy.reshape(arr, (25, -1))
        context = {"x": arr}
        nd_context = {"x": nd_arr}

        assert p.evaluate("abs(-5)") == 5
        assert p.evaluate("abs(5)") == 5
        assert (p.evaluate("abs(x)", context={"x": numpy.array([-1, -2, 3])}) == numpy.array([1, 2, 3])).all()
        assert p.evaluate("min(x)", context=context) == 0
        assert (p.evaluate("min(x, 0)", context=nd_context) == numpy.nanmin(nd_arr, 0)).all()
        assert (p.evaluate("min(x, 1)", context=nd_context) == numpy.nanmin(nd_arr, 1)).all()
        assert p.evaluate("max(x)", context=context) == 149
        assert (p.evaluate("max(x, 0)", context=nd_context) == numpy.nanmax(nd_arr, 0)).all()
        assert (p.evaluate("max(x, 1)", context=nd_context) == numpy.nanmax(nd_arr, 1)).all()
        assert p.evaluate("median(x)", context=context) == 112
        assert (p.evaluate("median(x, 0)", context=nd_context) == numpy.nanmedian(nd_arr, 0)).all()
        assert (p.evaluate("median(x, 1)", context=nd_context) == numpy.nanmedian(nd_arr, 1)).all()
        assert p.evaluate("mean(x)", context=context) == 87
        assert (p.evaluate("mean(x, 0)", context=nd_context) == numpy.nanmean(nd_arr, 0)).all()
        assert (p.evaluate("mean(x, 1)", context=nd_context) == numpy.nanmean(nd_arr, 1)).all()
        assert round(p.evaluate("std(x)", context=context), 3) == 54.485
        assert (p.evaluate("std(x, 0)", context=nd_context) == numpy.nanstd(nd_arr, 0)).all()
        assert (p.evaluate("std(x, 1)", context=nd_context) == numpy.nanstd(nd_arr, 1)).all()
        assert round(p.evaluate("var(x)", context=context), 3) == 2968.667
        assert (p.evaluate("var(x, 0)", context=nd_context) == numpy.nanvar(nd_arr, 0)).all()
        assert (p.evaluate("var(x, 1)", context=nd_context) == numpy.nanvar(nd_arr, 1)).all()
        assert p.evaluate("floor(1.7)") == 1
        assert p.evaluate("floor(-1.3)") == -2
        assert p.evaluate("ceil(1.3)") == 2
        assert p.evaluate("ceil(-1.3)") == -1
        assert (p.evaluate("floor(x)", context=context) == numpy.floor(arr)).all()
        assert (p.evaluate("ceil(x)", context=context) == numpy.ceil(arr)).all()
        assert p.evaluate("int(1.3)") == 1
        assert p.evaluate("float(1.3)") == 1.3
        assert (p.evaluate("int(x)", context={"x": numpy.array([1.2, 1.3, 1.4])}) == numpy.array([1, 1, 1])).all()
        assert p.evaluate("int(x)", context={"x": numpy.array([1.2, 1.3, 1.4])}).dtype == int
        assert p.evaluate("float(x)", context=context).dtype == float

        assert (p.evaluate("mask(x, x < 10)", context=context) == numpy.ma.masked_where(arr < 10, arr)).all()

        assert p.evaluate("min(x) < max(x)", context=context) == True
        assert p.evaluate("abs(min(x))", context={"x": numpy.array([-1, 2, 3])}) == 1
Example #14
0
    def test_item_index(self):
        p = Parser()
        context = {
            "arr1": [1, 2, 3],
            "arr2": (1, 2, 3),
            "arr3": numpy.array([1, 2, 3]),
            "arr4": [[1, 2, 3]],
            "dict": {"one": 1, "two": 2},
        }

        assert p.evaluate("arr1[0]", context=context) == 1
        assert p.evaluate("arr2[0]", context=context) == 1
        assert p.evaluate("arr3[0]", context=context) == 1
        assert p.evaluate('dict["one"]', context=context) == 1
        assert p.evaluate("arr1[1+1]", context=context) == 3
        assert p.evaluate("arr4[0][1]", context=context) == 2

        with pytest.raises(TypeError):
            p.evaluate('arr1["one"]', context=context)

        with pytest.raises(IndexError):
            p.evaluate("arr1[3]", context=context)

        with pytest.raises(KeyError):
            p.evaluate("dict[1]", context=context)
Example #15
0
    def test_conditionals(self):
        p = Parser()

        assert p.evaluate("1 and 1") == 1
        assert p.evaluate("1 and 0") == 0
        assert p.evaluate("1 or 0") == 1
        assert p.evaluate("0 or 1") == 1
        assert p.evaluate("1 and 1 and 1") == 1
        assert p.evaluate("1 and 1 and 0") == 0
        assert p.evaluate("1 and 1 or 0") == 1
        assert p.evaluate("0 and 1 or 1") == 1
        assert p.evaluate("0 and (1 or 1)") == 0
        assert p.evaluate("1 and 1 and 1 or 0") == 1
        assert p.evaluate("0 and 1 and 1 or 1") == 1
        assert p.evaluate("0 and 1 and 1 or 0") == 0

        assert p.evaluate("1 > 2") == False
        assert p.evaluate("1 < 1") == False
        assert p.evaluate("1 < 2") == True
        assert p.evaluate("1 == 1") == True
        assert p.evaluate("1 <= 1") == True
        assert p.evaluate("1 <= 2") == True
        assert p.evaluate("1 >= 1") == True
        assert p.evaluate("1 >= 2") == False
        assert p.evaluate("1 + 1 >= 2") == True
        assert p.evaluate("1 + 1 > 2 - 1") == True
        assert p.evaluate("1 <= 2 and 1 + 1 >= 2") == True
        assert p.evaluate("1 <= 2 - 1 and 1 >= 2 - 1") == True
Example #16
0
    def test_functions(self):
        p = Parser()
        arr = numpy.concatenate((numpy.arange(25), numpy.arange(100, 150)))
        nd_arr = numpy.reshape(arr, (25, -1))
        context = {'x': arr}
        nd_context = {'x': nd_arr}

        assert p.evaluate('abs(-5)') == 5
        assert p.evaluate('abs(5)') == 5
        assert (p.evaluate('abs(x)', context={'x': numpy.array([-1, -2, 3])
                                              }) == numpy.array([1, 2,
                                                                 3])).all()
        assert p.evaluate('min(x)', context=context) == 0
        assert (p.evaluate('min(x, 0)',
                           context=nd_context) == numpy.nanmin(nd_arr,
                                                               0)).all()
        assert (p.evaluate('min(x, 1)',
                           context=nd_context) == numpy.nanmin(nd_arr,
                                                               1)).all()
        assert p.evaluate('max(x)', context=context) == 149
        assert (p.evaluate('max(x, 0)',
                           context=nd_context) == numpy.nanmax(nd_arr,
                                                               0)).all()
        assert (p.evaluate('max(x, 1)',
                           context=nd_context) == numpy.nanmax(nd_arr,
                                                               1)).all()
        assert p.evaluate('median(x)', context=context) == 112
        assert (p.evaluate('median(x, 0)',
                           context=nd_context) == numpy.nanmedian(nd_arr,
                                                                  0)).all()
        assert (p.evaluate('median(x, 1)',
                           context=nd_context) == numpy.nanmedian(nd_arr,
                                                                  1)).all()
        assert p.evaluate('mean(x)', context=context) == 87
        assert (p.evaluate('mean(x, 0)',
                           context=nd_context) == numpy.nanmean(nd_arr,
                                                                0)).all()
        assert (p.evaluate('mean(x, 1)',
                           context=nd_context) == numpy.nanmean(nd_arr,
                                                                1)).all()
        assert round(p.evaluate('std(x)', context=context), 3) == 54.485
        assert (p.evaluate('std(x, 0)',
                           context=nd_context) == numpy.nanstd(nd_arr,
                                                               0)).all()
        assert (p.evaluate('std(x, 1)',
                           context=nd_context) == numpy.nanstd(nd_arr,
                                                               1)).all()
        assert round(p.evaluate('var(x)', context=context), 3) == 2968.667
        assert (p.evaluate('var(x, 0)',
                           context=nd_context) == numpy.nanvar(nd_arr,
                                                               0)).all()
        assert (p.evaluate('var(x, 1)',
                           context=nd_context) == numpy.nanvar(nd_arr,
                                                               1)).all()
        assert p.evaluate('floor(1.7)') == 1
        assert p.evaluate('floor(-1.3)') == -2
        assert p.evaluate('ceil(1.3)') == 2
        assert p.evaluate('ceil(-1.3)') == -1
        assert (p.evaluate('floor(x)',
                           context=context) == numpy.floor(arr)).all()
        assert (p.evaluate('ceil(x)',
                           context=context) == numpy.ceil(arr)).all()
        assert p.evaluate('int(1.3)') == 1
        assert p.evaluate('float(1.3)') == 1.3
        assert (p.evaluate('int(x)',
                           context={'x': numpy.array([1.2, 1.3, 1.4])
                                    }) == numpy.array([1, 1, 1])).all()
        assert p.evaluate('int(x)',
                          context={
                              'x': numpy.array([1.2, 1.3, 1.4])
                          }).dtype == int
        assert p.evaluate('float(x)', context=context).dtype == float

        assert (p.evaluate('mask(x, x < 10)',
                           context=context) == numpy.ma.masked_where(
                               arr < 10, arr)).all()

        assert p.evaluate('min(x) < max(x)', context=context) == True
        assert p.evaluate('abs(min(x))',
                          context={'x': numpy.array([-1, 2, 3])}) == 1
Example #17
0
    def test_arithmetic(self):
        p = Parser()

        assert p.evaluate('1 + 1') == 2
        assert p.evaluate('1 * 1') == 1
        assert p.evaluate('1 + 2 * 3') == 7
        assert p.evaluate('3 * 2 + 1') == 7
        assert p.evaluate('(1 + 2) * 3') == 9
        assert p.evaluate('3 * (2 + 1)') == 9
        assert p.evaluate('1 + 7 * 6 / 3') == 15
        assert p.evaluate('(1 + 7) * 6 / 3') == 16
        assert p.evaluate(
            '1 / 2') == 0.5  # Uses true division for ints, as in Python 3
        assert p.evaluate('1 + 2 ** 4') == 17
        assert p.evaluate('(1 + 2) ** 4') == 81
        assert p.evaluate('10 % 5') == 0
        assert p.evaluate('1 + 2.4') == 3.4
        assert p.evaluate('0.5') == .5
        assert p.evaluate('.5') == .5
        assert p.evaluate('-1') == -1
        assert p.evaluate('-.124') == -.124
        assert p.evaluate('-(1 + 2)') == -3
        assert p.evaluate('-x[0]', context={'x': [1]}) == -1
        assert p.evaluate('x[-1]', context={'x': [1, 2]}) == 2
        assert p.evaluate('+1') == 1
        assert p.evaluate('+.124') == .124
        assert p.evaluate('+(1 + 2)') == 3
        assert p.evaluate('+x[0]', context={'x': [1]}) == 1
        assert p.evaluate('x[+1]', context={'x': [1, 2]}) == 2
Example #18
0
    def execute(self,
                region,
                year,
                model=None,
                variables=[],
                traits=[],
                constraints=None):
        data = {}
        variable_names = {v['name'] for v in variables}

        for trait in traits:
            fn = trait['fn']
            names = Lexer().get_names(fn)
            context = {
                x: self.load_variable_data(x, region, year, model)
                for x in names
            }
            data[trait['name']] = Parser().evaluate(fn, context)
            data.update(
                {k: v
                 for k, v in context.items() if k in variable_names})

        sum_rasters = None
        sum_masks = None

        for item in variables + traits:
            limit = item['limit']
            limit_min = limit['min']
            limit_max = limit['max']
            half = (limit_max - limit_min) / 2
            midpoint = limit_min + half
            factor = 100 / half
            mid_factor = factor * midpoint

            if item['name'] in data:
                raster = data[item['name']]
                del data[item['name']]
            else:
                raster = self.load_variable_data(item['name'], region, year,
                                                 model)

            raster = self.apply_constraints(raster, constraints, region)
            extent = raster.extent
            mask = raster.mask if is_masked(raster) else numpy.zeros_like(
                raster, 'bool')

            mask |= raster < limit_min
            mask |= raster > limit_max

            if sum_masks is not None:
                sum_masks |= mask
            else:
                sum_masks = mask

            raster = raster.view(numpy.ndarray).astype('float32')
            raster *= factor
            raster -= mid_factor
            raster **= 2
            raster = numpy.floor(raster, raster)

            if sum_rasters is not None:
                sum_rasters += raster
            else:
                sum_rasters = raster

        sum_rasters += 0.4
        sum_rasters **= 0.5

        sum_masks |= sum_rasters > 100
        sum_rasters = numpy.ma.masked_where(sum_masks, sum_rasters)
        sum_rasters = 100 - sum_rasters.astype('int8')
        sum_rasters.fill_value = -128

        return Raster(sum_rasters, extent, 1, 0, Y_INCREASING)
Example #19
0
    def test_arithmetic(self):
        p = Parser()

        assert p.evaluate("1 + 1") == 2
        assert p.evaluate("1 * 1") == 1
        assert p.evaluate("1 + 2 * 3") == 7
        assert p.evaluate("3 * 2 + 1") == 7
        assert p.evaluate("(1 + 2) * 3") == 9
        assert p.evaluate("3 * (2 + 1)") == 9
        assert p.evaluate("1 + 7 * 6 / 3") == 15
        assert p.evaluate("(1 + 7) * 6 / 3") == 16
        assert p.evaluate("1 / 2") == 0.5  # Uses true division for ints, as in Python 3
        assert p.evaluate("1 + 2 ** 4") == 17
        assert p.evaluate("(1 + 2) ** 4") == 81
        assert p.evaluate("10 % 5") == 0
        assert p.evaluate("1 + 2.4") == 3.4
        assert p.evaluate("0.5") == 0.5
        assert p.evaluate(".5") == 0.5
        assert p.evaluate("-1") == -1
        assert p.evaluate("-.124") == -0.124
        assert p.evaluate("-(1 + 2)") == -3
        assert p.evaluate("-x[0]", context={"x": [1]}) == -1
        assert p.evaluate("x[-1]", context={"x": [1, 2]}) == 2
        assert p.evaluate("+1") == 1
        assert p.evaluate("+.124") == 0.124
        assert p.evaluate("+(1 + 2)") == 3
        assert p.evaluate("+x[0]", context={"x": [1]}) == 1
        assert p.evaluate("x[+1]", context={"x": [1, 2]}) == 2