Beispiel #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
Beispiel #2
0
    def get_default_input_dict(m_id, g_in):
        """Get dict mapping names of generic input arguments to default values.

        Is None if no default value for a given generic input is given.

        Args:
            m_id(int):   Index of the method.
            g_in([str]): Names of the generic input arguments.
        Return:
            dict: The mapping.
        """
        res = dict()
        for i, t in enumerate(g_in):
            k = arts_api.get_method_g_in(m_id, i).decode("utf8")
            d = arts_api.get_method_g_in_default(m_id,
                                                 i).decode("utf8").strip()
            if d == nodef:
                d = None
            elif d == "Inf":
                res[k] = np.float64("inf")
            else:
                try:
                    d = WorkspaceVariable.convert(group_names[t],
                                                  ast.literal_eval(d))
                    res[k] = d
                except:
                    res[k] = d
        return res
Beispiel #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.")
Beispiel #4
0
    def convert_argument(self, name, value):
        """
        Tries to infer type of argument based on types of input and
        generic input.
        """
        if isinstance(value, WSV):
            return value

        if name in self.wsm_ins:
            v = workspace_variables[name]
            value_converted = WorkspaceVariable.convert(v.group, value)
            if not value_converted is None:
                value = value_converted

        if name in self.wsm_gins:
            if len(self.wsm.g_in_types) == 1:
                g = group_names[self.wsm.g_in_types[0][name]]

                value_converted = WorkspaceVariable.convert(g, value)
                if not value_converted is None:
                    value = value_converted
        return value
Beispiel #5
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)