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
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
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.")
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
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)