Пример #1
0
    def check_and_convert(self, value):
        """
        Checks type of :code:`value` against the group specification of this
        ARTS property contained in :code:`self.group`.

        The group specification can be a single string in which case this
        function will try to convert the provided value to the given group
        using the :code:`convert` class method of
        :class:`pyarts.workspace.WorkspaceVariable`.

        It is also possible to specify a list of groups for the expected
        value. In this case this function simply checks whether the group
        inferred by :code:`WorkspaceVariable.get_group_id`
        group of the :code:``

        """
        if type(self.group) == str:
            converted = WorkspaceVariable.convert(self.group, value)

            if converted is None:
                raise Exception(
                    "Provided value of type {0} cannot be converted"
                    " to ARTS group {1}".format(type(value), self.group))
            value = converted
        elif type(self.group) == list:
            g_i = WorkspaceVariable.get_group_id(value)
            g = group_names[g_i]
            if not g in self.group:
                raise Exception("Provided value of type {0} is not of any of "
                                " the expected ARTS groups {1}."\
                                .format(type(value), self.group))

        return value
Пример #2
0
    def add_variable(self, var, group=None):
        """
        This will try to copy a given python variable to the ARTS workspace and
        return a WorkspaceVariable object representing this newly created
        variable.

        Types are natively supported by the C API are int, str, [str], [int], and
        numpy.ndarrays. These will be copied directly into the newly created WSV.

        In addition to that all arts types the can be stored to XML can
        be set to a WSV, but in this case the communication will happen through
        the file system (cf. WorkspaceVariable.from_arts).

        The user should not have to call this method explicitly, but instead it
        is used by the WorkspaceMethod call function to transfer python
        variable arguments to the ARTS workspace.

        Args:
            var: Python variable of type int, str, [str], [int] or np.ndarray
            which should be copied to the workspace.
        """
        if type(var) == WorkspaceVariable:
            return var

        # Create WSV in ARTS Workspace
        if group is None:
            group = WorkspaceVariable.get_group_id(var)

        group = group_names[group]
        wsv = self.create_variable(group, None)

        # Set WSV value using the ARTS C API
        self.set_variable(wsv, var)
        self._vars[wsv.name] = wsv
        return wsv
Пример #3
0
    def set_variable(self, wsv, value):
        """
        This will set a WSV to the given value.

        Natively supported types, i.e. any of int, str, [str], [int], numpy.ndarrays,
        and scipy.sparse, will be copied directly into the newly created WSV.

        In addition to that all arts types the can be stored to XML can
        be set to a WSV, but in this case the communication will happen through
        the file system (cf. :code:`WorkspaceVariable.from_arts`).

        Args:
            wsv: The :class:`WorkspaceVariable` to set.
            value: The Python object representing the value to set :code:`wsv` to.
        """
        if is_empty(value):
            err = arts_api.set_variable_value(self.ptr, wsv.ws_id,
                                              wsv.group_id,
                                              VariableValueStruct.empty())
            if not err is None:
                msg = ("The following error occurred when trying to set the"
                       " WSV {}: {}".format(wsv.name, err.decode()))
                raise Exception(msg)
            return None

        group = group_names[WorkspaceVariable.get_group_id(value)]
        if group != wsv.group:
            try:
                converted = WorkspaceVariable.convert(wsv.group, value)
            except:
                converted = None
            if converted is None:
                raise Exception("Cannot set workspace variable of type {} to "
                                " value  '{}'.".format(wsv.group, value))
            value = converted

        s = VariableValueStruct(value)
        if s.ptr:
            err = arts_api.set_variable_value(self.ptr, wsv.ws_id,
                                              wsv.group_id, s)
            if not err is None:
                msg = ("The following error occurred when trying to set the"
                       " WSV {}: {}".format(wsv.name, err.decode()))
                raise Exception(msg)
        # If the type is not supported by the C API try to write the type to XML
        # and read into ARTS workspace.
        else:
            try:
                wsv.from_arts(value)
            except:
                raise Exception("Could not set variable since + " +
                                str(type(value)) +
                                " is neither supported by " +
                                "the C API nor arts XML IO.")
Пример #4
0
    def _parse_output_input_lists(self, ws, args, kwargs):

        ins = [i for i in self.ins if not i in self.outs]
        outs = self.outs[:]
        temps = []

        # Can call function using only positional or named arguments
        if len(args) and len(kwargs.keys()):
            raise SyntaxError("ARTS WSMs can only be called using either " +
                              " positional or named arguments.")

        # Use dict to store named arguments. Generic in- and outputs
        # will be added to this.
        named_args = dict(**kwargs)

        #
        # Parse positional arguments
        #

        for j in range(len(args)):
            # Parse output arguments
            if j < self.n_out:
                if not type(args[j]) == WorkspaceVariable:
                    out_name = WorkspaceVariable.get_variable_name(outs[j])
                    raise TypeError(
                        "Positional argument for output {} is not of type "
                        "WorkspaceVariable.".format(out_name))

                outs[j] = args[j].ws_id
            # Parse generic output arguments and to list of named
            # args.
            elif j < self.n_out + self.n_g_out:
                k = j - self.n_out
                name = self.g_out[k]
                named_args[name] = args[j]

            # Parse input arguments
            elif j < self.n_out + self.n_g_out + len(ins):
                k = j - self.n_g_out - self.n_out
                if type(args[j]) == WorkspaceVariable:
                    ins[k] = args[j].ws_id
                else:
                    temps.append(ws.add_variable(args[j]))
                    ins[k] = temps[-1].ws_id
            # Parse generic input arguments
            elif j < self.n_out + self.n_g_out + len(ins) + self.n_g_in:
                k = j - self.n_g_out - self.n_out - len(ins)
                name = self.g_in[k]
                named_args[name] = args[j]
            else:
                raise Exception(
                    " {} positional arguments given, but this WSM takes at "
                    "most {}.".format(len(args), j))

        # Parse named arguments
        ins_names = [WorkspaceVariable.get_variable_name(i) for i in ins]
        outs_names = [WorkspaceVariable.get_variable_name(i) for i in outs]

        # Raise exception if named argument does not match method arguments.
        for k in kwargs:
            if not (k in ins_names or k in outs_names or k in self.g_in
                    or k in self.g_out):
                raise Exception(
                    "The provided named argument '{0}' does not match "
                    " any of the arguments of WSM {1}.".format(k, self.name))

            if k in ins_names:
                i = ins_names.index(k)
                arg = kwargs[k]
                if type(arg) == WorkspaceVariable:
                    ins[i] = arg.ws_id
                else:
                    temps.append(ws.add_variable(arg))
                    ins[i] = temps[-1].ws_id

            if k in outs_names:
                i = outs_names.index(k)
                arg = kwargs[k]
                if type(arg) == WorkspaceVariable:
                    outs[i] = arg.ws_id
                else:
                    raise Exception(
                        ("Output argument {} must be a workspace " +
                         "variable.").format(k))

        # Check output argument names
        g_output_args = dict()
        for k in self.g_out:
            if not k in named_args:
                raise Exception("WSM " + self.name + " needs generic output " +
                                k)
            else:
                g_output_args[k] = named_args[k]

        # Check input argument names
        g_input_args = dict()
        for k in self.g_in:
            if not k in named_args:
                if k in self.g_in_default:
                    g_input_args[k] = self.g_in_default[k]
                else:
                    raise Exception("WSM " + self.name +
                                    " needs generic input " + k)
            else:
                g_input_args[k] = named_args[k]

        m_id = self.m_ids[0]
        sg_index = 0

        if (len(self.m_ids) > 1):

            #
            # First, try resolving solely based on WSV input since we can
            # easily identify their type.
            #

            candidates = []
            for i, m_id in enumerate(self.m_ids):
                g_in_types = self.g_in_types[i]
                g_out_types = self.g_out_types[i]

                convertable = True

                for k in g_in_types:
                    in_type = group_names[g_in_types[k]]
                    in_arg = g_input_args[k]
                    if isinstance(in_arg, WorkspaceVariable):
                        if not in_arg.group == in_type:
                            convertable = False
                            break

                for k in g_out_types:
                    out_type = group_names[g_out_types[k]]
                    out_arg = g_output_args[k]
                    if isinstance(out_arg, WorkspaceVariable):
                        if not out_arg.group == out_type:
                            convertable = False
                            break

                if convertable:
                    candidates.append((m_id, i))

            if len(candidates) == 1:
                m_id, sg_index = candidates[0]
            else:
                # Resolve overload (if necessary).
                g_out_types = dict([
                    (k, WorkspaceVariable.get_group_id(g_output_args[k]))
                    for k in self.g_out
                ])
                g_in_types = dict([
                    (k, WorkspaceVariable.get_group_id(g_input_args[k]))
                    for k in self.g_in
                ])

                out_indices = [
                    i for i, ts in enumerate(self.g_out_types)
                    if ts == g_out_types
                ]
                in_indices = [
                    i for i, ts in enumerate(self.g_in_types)
                    if ts == g_in_types
                ]
                sg_indices = set(out_indices) & set(in_indices)

                if len(sg_indices) > 1:
                    raise Exception(
                        "Could not uniquely resolve super-generic overload.")

                if len(sg_indices) == 0:
                    raise Exception(
                        "Could not find super-generic overload matching" +
                        " the given groups.")

                sg_index = sg_indices.pop()
                m_id = self.m_ids[sg_index]

        # Combine input and output arguments into lists.
        arts_args_out = []
        for out in outs:
            arts_args_out.append(out)

        for name in self.g_out:
            arg = g_output_args[name]
            if not type(arg) == WorkspaceVariable:
                raise ValueError("Generic Output " + name +
                                 " must be an ARTS WSV.")
            group_id = arg.group_id
            expected = self.g_out_types[sg_index][name]
            if not group_id == expected:
                raise Exception("Generic output " + name +
                                " expected to be of type " +
                                group_names[expected])
            arts_args_out.append(arg.ws_id)

        arts_args_in = []
        for i in ins:
            if not i in outs:
                arts_args_in.append(i)

        for name in self.g_in:
            arg = g_input_args[name]
            if type(arg) == WorkspaceVariable:
                arts_args_in.append(arg.ws_id)
            else:
                gid = self.g_in_types[sg_index][name]
                arg_converted = WorkspaceVariable.convert(
                    group_names[gid], arg)
                if arg_converted is None:
                    raise Exception(
                        "Could not convert input {} to expected group {}".
                        format(arg, group_names[gid]))
                temps.append(ws.add_variable(arg_converted, gid))
                arts_args_in.append(temps[-1].ws_id)
        return (m_id, arts_args_out, arts_args_in, temps)