def add_method(*args, **kwargs): """ Add a workspace method call to the agenda. Parameters: ws(arts.workspace.Workspace): A (dummy) workspace object. m(arts.workspace.WorkspaceMethod): The method to add to the agenda *args: Positional arguments of the WSM call to add to the agenda. **kwargs: Key-word arguments of the WSM call to add to the agenda. """ from pyarts.workspace.variables import group_names if len(args) < 3: raise Exception("Need at least self, a workspace and the method to" " add as arguments.") self = args[0] ws = args[1] m = args[2] m_id, args_out, args_in, temps = m._parse_output_input_lists( ws, args[3:], kwargs) arg_out_ptr = c.cast((c.c_long * len(args_out))(*args_out), c.POINTER(c.c_long)) arg_in_ptr = c.cast((c.c_long * len(args_in))(*args_in), c.POINTER(c.c_long)) if not m.name[-3:] == "Set" or not m.name[:-3] in group_names: for t in temps: arts_api.agenda_insert_set(ws.ptr, self.ptr, t.ws_id, t.group_id) arts_api.agenda_add_method(c.c_void_p(self.ptr), m_id, len(args_out), arg_out_ptr, len(args_in), arg_in_ptr) else: from pyarts.workspace.variables import WorkspaceVariable name_out = WorkspaceVariable.get_variable_name(args_out[0]) name_in = WorkspaceVariable.get_variable_name(args_in[0]) wsv_out = getattr(ws, name_out) wsv_in = getattr(ws, name_in) ws.Copy(wsv_out, wsv_in) group_id = arts_api.get_variable(args_out[0]).group arts_api.agenda_insert_set(ws.ptr, self.ptr, args_out[0], group_id)
def get_wsm_kwargs(self, wsm): """ Generate a list of arguments to the given ARTS workspace method :code:`wsm` for which the sensor related input parameters are replace by the ones of this sensor. This is done by checking whether the input argument name is in the sensors :code:`_wsv` dictionary and if so replacing the argument. Parameters: wsm(pyarts.workspace.methods.WorkspaceMethod): The ARTS workspace method object for which to generate the input argument list. Returns: The list of input arguments with sensor specific input arguments replaced by the corresponding WSVs of the sensor. """ kwargs = {} for i in wsm.ins: name = WorkspaceVariable.get_variable_name(i) if name in self._wsvs: kwargs[name] = self._wsvs[name] else: kwargs[name] = wsv[name] return kwargs
def call_wsm(self, ws, wsm): """ Call workspace method on the given workspace. This method replaces inputs of the workspace variable with the private WSMs of the object. After execution of the method the results are copied to the private WSMs of the object. Parameters: ws(pyarts.workspace.Workspace): The workspace on which to execute the method. wsm(pyarts.workspace.WorkspaceMethod): The workspace method to execute. """ args = self.get_wsm_kwargs(wsm) wsm.call(ws, **args) # Copy output for i in wsm.outs: name = WorkspaceVariable.get_variable_name(i) if name in self._wsvs and not i in wsm.ins: ws.Copy(self._wsvs[name], wsv[name])
def __init__(self, name, args, kwargs): if not name in workspace_methods: raise Exception("{} is not a known workspace method.".format(name)) self.wsm = workspace_methods[name] self.wsm_outs = [ WorkspaceVariable.get_variable_name(m) for m in self.wsm.outs ] self.wsm_gouts = self.wsm.g_out self.wsm_ins = [WorkspaceVariable.get_variable_name(m) for m in self.wsm.ins \ if not m in self.wsm.outs] self.wsm_gins = self.wsm.g_in self.arg_names = self.wsm_outs + self.wsm_gouts + self.wsm_ins + self.wsm_gins self.name = name self.args = args self.kwargs = kwargs if not kwargs is None: if "in" in kwargs: self.kwargs_to_args()
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)