예제 #1
0
    def value(self):
        """ Return the value of the variable in a given workspace.

        By default this function will check the value in the workspace associated
        with the variable of in the workspace object provided as argument to the function
        call. If the variable has an associated workspace the workspace provided as
        argument will be ignored.

        Returns:
            The value of the workspace variable represented by an object of the corresponding
            python types.

        Raises:
            Exception: If the type of the workspace variable is not supported by the
            interface.

        """
        if (self.ws):
            ws = self.ws
        if not ws:
            raise ValueError("WorkspaceVariable object need Workspace to determine value.")

        v = arts_api.get_variable_value(ws.ptr, self.ws_id, self.group_id)
        if not v.initialized:
            raise Exception("WorkspaceVariable " + self.name + " is uninitialized.")

        # TODO: Use group attribute here istead of lookup in group_names.
        # TODO: Move this to VariableValueStruct class

        if group_names[self.group_id] == "Index":
            return c.cast(v.ptr, c.POINTER(c.c_long))[0]
        if group_names[self.group_id] == "Numeric":
            return c.cast(v.ptr, c.POINTER(c.c_double))[0]
        if group_names[self.group_id] == "String":
            return (c.cast(v.ptr, c.c_char_p)).value.decode("utf8")
        if group_names[self.group_id] == "ArrayOfIndex":
            return [c.cast(v.ptr, c.POINTER(c.c_long))[i] for i in range(v.dimensions[0])]
        if group_names[self.group_id] == "Sparse":
            m    = v.dimensions[0]
            n    = v.dimensions[1]
            nnz  = v.dimensions[2]
            data = np.ctypeslib.as_array(c.cast(v.ptr, c.POINTER(c.c_double)), (nnz,))
            row_indices = np.ctypeslib.as_array(v.inner_ptr, (nnz,))
            col_starts  = np.ctypeslib.as_array(v.outer_ptr, (m + 1,))
            return sp.sparse.csr_matrix((data, row_indices, col_starts), shape=(m,n))
        if group_names[self.group_id] == "Agenda":
            return Agenda(v.ptr)
        try:
            self.update()
            a = np.asarray(self)
            return a
        except:
            raise Exception("Type of workspace variable is not supported by the interface.")
예제 #2
0
def arts_agenda(func):
    """
    Parse python method as ARTS agenda

    This decorator can be used to define ARTS agendas using python function syntax.
    The function should have one arguments which is assumed to be a Workspace instance.
    All expressions inside the function must be calls to ARTS WSMs. The result is an
    Agenda object that can be used to copied into a named ARTS agenda

    Example:

    >>> @arts_agenda
    >>> def inversion_iterate_agenda(ws):
    >>>     ws.x2artsStandard()
    >>>     ws.atmfields_checkedCalc()
    >>>     ws.atmgeom_checkedCalc()
    >>>     ws.yCalc()
    >>>     ws.VectorAddVector(ws.yf, ws.y, ws.y_baseline)
    >>>     ws.jacobianAdjustAfterIteration()
    >>>
    >>> ws.Copy(ws.inversion_iterate_agenda, inversion_iterate_agenda)
    """

    source = getsource(func)
    source = unindent(source)
    ast = parse(source)

    func_ast = ast.body[0]
    if not type(func_ast) == FunctionDef:
        raise Exception("ARTS agenda definition can only decorate function definiitons.")

    args = func_ast.args.args

    try:
        arg_name = func_ast.args.args[0].arg
    except:
        raise Exception("Agenda definition needs workspace arguments.")

    ws = Workspace(0)

    context = copy(func.__globals__)
    context.update({arg_name : ws})
    # Add resolved non-local variables from closure.
    nls, _, _, _ = getclosurevars(func)
    context.update(nls)

    #
    # Helper functions
    #

    callback_body = []
    def callback_make_fun(body):
        """
        Helper function that creates a wrapper function around
        python code to be executed withing an ARTS agenda.
        """
        m = Module(body)

        def callback(ptr):
            try:
                context[arg_name].ptr = ptr
                eval(compile(m , "<unknown>", 'exec'), context)
            except Exception as e:
                logger.error(r"Exception in Python callback:\n", e)
            context[arg_name].ptr = None

        callback_body = []
        return callback

    def eval_argument(expr):
        """
        Evaluate argument of workspace method call.
        """
        if not hasattr(expr, "lineno"):
            setattr(expr, "lineno", 0)
        return eval(compile(Expression(expr), "<unknown>", 'eval'), context)

    # Create agenda
    a_ptr = arts_api.create_agenda(func.__name__.encode())
    agenda = Agenda(a_ptr)

    illegal_statement_exception = Exception(
        "Agenda definitions may only contain calls to WSMs of the"
        "workspace argument " + arg_name + " or INCLUDE statements.")

    #
    # Here the body of the function definition is traversed. Cases
    # that are treated specieal are INCLUDE statements and calls
    # of workspace methods. Remaining statements are accumulated
    # in callback_body and then added to the agenda as a single callback.
    #

    for e in func_ast.body:
        if not isinstance(e, Expr):
            callback_body += [e]
            continue
        else:
            call = e.value

        if not isinstance(call, Call):
            callback_body += [e]
            continue

        # Include statement
        if type(call.func) == Name:
            if not call.func.id == "INCLUDE":
                callback_body += [e]
            else:
                args = []
                for a in call.args:
                    args.append(eval_argument(a))
                    include = Include(*args)

                    if len(callback_body) > 0:
                        agenda.add_callback(callback_make_fun(callback_body))
                        callback_body = []

                    arts_api.agenda_append(agenda.ptr, include.agenda.ptr)
        else:
            att  = call.func.value
            if not att.id == arg_name:
                callback_body += [e]
                continue

            # Extract method name.
            name = call.func.attr

            # m is not a workspace method
            if not name in workspace_methods:
                callback_body += [e]
                continue

            # m is a workspace method.
            m  = workspace_methods[name]

            args = [ws, m]

            for a in call.args:
                # Handle starred expression
                if type(a) == Starred:
                    bs = eval_argument(a.value)
                    for b in bs:
                        args.append(b)
                    continue

                args.append(eval_argument(a))

            # Extract keyword arguments
            kwargs = dict()
            for k in call.keywords:
                kwargs[k.arg] = eval(
                    compile(Expression(k.value), "<unknown>", 'eval'),
                    context)

            # Add function to agenda
            if len(callback_body) > 0:
                agenda.add_callback(callback_make_fun(callback_body))
                callback_body = []

            agenda.add_method(*args, **kwargs)

    # Check if there's callback code left to add to the agenda.
    if len(callback_body) > 0:
        agenda.add_callback(callback_make_fun(callback_body))
        callback_body = []

    return agenda
예제 #3
0
def arts_agenda(func):
    """
    Parse python method as ARTS agenda

    This decorator can be used to define ARTS agendas using python function syntax.
    The function should have one arguments which is assumed to be a Workspace instance.
    All expressions inside the function must be calls to ARTS WSMs. The result is an
    Agenda object that can be used to copied into a named ARTS agenda

    Example:

    >>> @arts_agenda
    >>> def inversion_iterate_agenda(ws):
    >>>     ws.x2artsStandard()
    >>>     ws.atmfields_checkedCalc()
    >>>     ws.atmgeom_checkedCalc()
    >>>     ws.yCalc()
    >>>     ws.VectorAddVector(ws.yf, ws.y, ws.y_baseline)
    >>>     ws.jacobianAdjustAfterIteration()
    >>>
    >>> ws.Copy(ws.inversion_iterate_agenda, inversion_iterate_agenda)
    """
    source = getsource(func)
    ast = parse(source)

    func_ast = ast.body[0]
    if not type(func_ast) == FunctionDef:
        raise Exception(
            "ARTS agenda definition can only decorate function definiitons.")

    args = func_ast.args.args

    try:
        arg_name = func_ast.args.args[0].arg
    except:
        raise Exception("Agenda definition needs workspace arguments.")

    ws = Workspace()

    context = func.__globals__
    context[arg_name] == ws

    # Create agenda
    a_ptr = arts_api.create_agenda(func.__name__.encode())
    agenda = Agenda(a_ptr)

    for e in func_ast.body:
        if not type(e.value) == Call:
            raise Exception("Agendas may only contain call expressions.")

        # Extract workspace object.
        try:
            call = e.value
            att = call.func.value
            if not att.id == arg_name:
                raise (Exception(
                    "Agenda definition may only contain call to WSMs of the " +
                    "workspace argument " + arg_name + "."))
        except:
            raise (Exception(
                "Agenda definition may only contain call to WSMs of the " +
                "workspace argument " + arg_name + "."))

        # Extract method name.
        try:
            name = call.func.attr
            m = workspace_methods[name]
            if not type(m) == WorkspaceMethod:
                raise Exception(name + " is not a known WSM.")
        except:
            raise Exception(name + " is not a known WSM.")

        # Extract positional arguments
        args = [ws, m]
        for a in call.args:
            args.append(
                eval(compile(Expression(a), "<unknown>", 'eval'), context))

        # Extract keyword arguments
        kwargs = dict()
        for k in call.keywords:
            kwargs[k.arg] = eval(
                compile(Expression(k.value), "<unknown>", 'eval'), context)

        # Add function to agenda
        agenda.add_method(*args, **kwargs)
    return agenda
예제 #4
0
    def value(self):
        """ Return the value of the variable in a given workspace.

        By default this function will check the value in the workspace associated
        with the variable of in the workspace object provided as argument to the
        function call. If the variable has an associated workspace the workspace
        provided as argument will be ignored.

        Returns:
            The value of the workspace variable represented by an object of
            the corresponding python types.

        Raises:
            Exception: If the type of the workspace variable is not supported
            by the interface.

        """
        if (self.ws):
            ws = self.ws
        if not ws:
            raise ValueError("WorkspaceVariable object need Workspace to determine value.")

        v = arts_api.get_variable_value(ws.ptr, self.ws_id, self.group_id)
        if not v.initialized:
            raise Exception("WorkspaceVariable " + self.name + " is uninitialized.")

        if self.group == "Index":
            return c.cast(v.ptr, c.POINTER(c.c_long))[0]
        elif self.group == "Numeric":
            return c.cast(v.ptr, c.POINTER(c.c_double))[0]
        elif self.group == "String":
            return (c.cast(v.ptr, c.c_char_p)).value.decode("utf8")
        elif self.group == "ArrayOfIndex":
            return [c.cast(v.ptr, c.POINTER(c.c_long))[i]
                    for i in range(v.dimensions[0])]
        elif self.group == "Sparse":
            m    = v.dimensions[0]
            n    = v.dimensions[1]
            nnz  = v.dimensions[2]
            if nnz == 0:
                return sp.sparse.csr_matrix(0)
            else:
                data = np.ctypeslib.as_array(c.cast(v.ptr,
                                                    c.POINTER(c.c_double)),
                                             (nnz,))
                row_indices = np.ctypeslib.as_array(v.inner_ptr, (nnz,))
                col_starts  = np.ctypeslib.as_array(v.outer_ptr, (m + 1,))
                return sp.sparse.csr_matrix((data, row_indices, col_starts),
                                            shape=(m,n))
        elif self.group == "Agenda":
            return Agenda(v.ptr)
        elif self.ndim:
            shape = []
            size  = 1
            for i in range(self.ndim):
                shape.append(v.dimensions[i])
                size *= v.dimensions[i]
            if size > 0:
                self.__array_interface__ = {"shape"  : tuple(shape),
                                            "typestr" : "|f8",
                                            "data" : (v.ptr, False),
                                            "version" : 3}
                return np.asarray(self)
            else:
                return np.zeros(shape)
        else:
            try:
                return self.to_typhon()
            except:
                raise Exception("Type of workspace variable is not supported "
                                + " by the interface.")
예제 #5
0
def arts_agenda(func):
    """
    Parse python method as ARTS agenda

    This decorator can be used to define ARTS agendas using python function syntax.
    The function should have one arguments which is assumed to be a Workspace instance.
    All expressions inside the function must be calls to ARTS WSMs. The result is an
    Agenda object that can be used to copied into a named ARTS agenda

    Example:

    >>> @arts_agenda
    >>> def inversion_iterate_agenda(ws):
    >>>     ws.x2artsStandard()
    >>>     ws.atmfields_checkedCalc()
    >>>     ws.atmgeom_checkedCalc()
    >>>     ws.yCalc()
    >>>     ws.VectorAddVector(ws.yf, ws.y, ws.y_baseline)
    >>>     ws.jacobianAdjustAfterIteration()
    >>>
    >>> ws.Copy(ws.inversion_iterate_agenda, inversion_iterate_agenda)
    """

    source = getsource(func)
    source = unindent(source)
    ast = parse(source)

    func_ast = ast.body[0]
    if not type(func_ast) == FunctionDef:
        raise Exception(
            "ARTS agenda definition can only decorate function definiitons.")

    args = func_ast.args.args

    try:
        arg_name = func_ast.args.args[0].arg
    except:
        raise Exception("Agenda definition needs workspace arguments.")

    ws = Workspace()

    context = copy(func.__globals__)
    context.update({arg_name: ws})
    # Add resolved non-local variables from closure.
    nls, _, _, _ = getclosurevars(func)
    context.update(nls)

    def eval_argument(expr):
        if not hasattr(expr, "lineno"):
            setattr(expr, "lineno", 0)
        return eval(compile(Expression(expr), "<unknown>", 'eval'), context)

    # Create agenda
    a_ptr = arts_api.create_agenda(func.__name__.encode())
    agenda = Agenda(a_ptr)

    illegal_statement_exception = Exception(
        "Agenda definitions may only contain calls to WSMs of the"
        "workspace argument " + arg_name + " or INCLUDE statements.")

    for e in func_ast.body:
        try:
            call = e.value
        except:
            raise Exception("Agendas may only contain call expressions.")

        # Include statement
        if type(call.func) == Name:
            if not call.func.id == "INCLUDE":
                raise illegal_statement_exception
            else:
                args = []
                for a in call.args:
                    args.append(eval_argument(a))
                    include = Include(*args)
                    arts_api.agenda_append(agenda.ptr, include.agenda.ptr)
        else:
            att = call.func.value
            if not att.id == arg_name:
                raise illegal_statement_exception

            # Extract method name.
            try:
                name = call.func.attr
                m = workspace_methods[name]
                if not type(m) == WorkspaceMethod:
                    raise Exception(name + " is not a known WSM.")
            except:
                raise Exception(name + " is not a known WSM.")

            # Extract positional arguments
            args = [ws, m]

            for a in call.args:

                # Handle starred expression
                if type(a) == Starred:
                    bs = eval_argument(a.value)
                    for b in bs:
                        args.append(b)
                    continue

                args.append(eval_argument(a))

            # Extract keyword arguments
            kwargs = dict()
            for k in call.keywords:
                kwargs[k.arg] = eval(
                    compile(Expression(k.value), "<unknown>", 'eval'), context)

            # Add function to agenda
            agenda.add_method(*args, **kwargs)
    return agenda