def evaluate(self, cmds, verbose=True, log=True, logger=None, timeout=None, pre_call='', post_call=''): """Perform the low-level interaction with an Scilab Session """ self.logger = logger if not timeout is None: self.set_timeout(timeout) if not self.proc: raise Scilab2PyError('Session Closed, try a restart()') if self._first: self.write(""" try getd("."); catch end """) if os.path.exists(self.outfile): try: os.remove(self.outfile) except OSError as e: self.logger.debug(e) outfile = self.outfile # use ascii code 2 for start of text, 3 for end of text, and # 24 to signal an error expr = '\n'.join(cmds) # scilab cannot handle "#" commented lines # try and remove them expr = re.sub(r'[\A\n]\s*#', '//', expr) # use ascii code 2 for start of text, 3 for end of text, and # 24 to signal an error output = """ %(pre_call)s clear("ans"); clear("a__"); clear("_ans"); try disp(char(2)); %(expr)s if exists("ans") == 1 then _ans = ans; end catch disp(lasterror()); disp(char(24)); end if exists("_ans") == 1 if type(_ans) == 4 then _ans = double(_ans) end if or(type(_ans) == [1,2,3,5,6,7,8,10]) then if exists("a__") == 0 then try savematfile -v6 %(outfile)s _ans; catch disp(_ans) end end elseif type(_ans) disp(_ans); end end %(post_call)s disp(char(3)) """ % locals() if len(cmds) == 5: main_line = cmds[2].strip() else: main_line = '\n'.join(cmds) self.logger.debug(output) self.write(output + '\n') if self._first: self.expect(chr(2)) else: self.expect(chr(2), timeout=1) self._first = False debug_prompt = ("Type 'resume' or 'abort' to return to " "standard level prompt.") resp = [] while 1: line = self.readline() if chr(3) in line: break elif chr(24) in line: msg = ('Scilab2Py tried to run:\n"""\n{0}\n"""\n' 'Scilab returned:\n{1}'.format(main_line, '\n'.join(resp))) raise Scilab2PyError(msg) elif line.strip() == debug_prompt: self.interact('-1->') if verbose and logger: logger.info(line) elif log and logger: logger.debug(line) if resp or line.strip(): resp.append(line) return '\n'.join(resp).rstrip()
def eval(self, cmds, verbose=True, timeout=None, log=True, plot_dir=None, plot_name='plot', plot_format='png', plot_width=620, plot_height=590, return_both=False): """ Perform Scilab command or commands. Parameters ---------- cmd : str or list Commands(s) to pass directly to Scilab. verbose : bool, optional Log Scilab output at info level. timeout : float Time to wait for response from Scilab (per character). plot_dir: str, optional If specificed, save the session's plot figures to the plot directory instead of displaying the plot window. plot_name : str, optional Saved plots will start with `plot_name` and end with "_%%.xxx' where %% is the plot number and xxx is the `plot_format`. plot_format: str, optional The format in which to save the plot (PNG by default). plot_width: int, optional The plot with in pixels. plot_height: int, optional The plot height in pixels. return_both : bool, optional If True, return an (printed output, value) tuple. If "ans =" is in the printed output, the printed output will have that portion removed. Returns ------- out : str Results printed by Scilab. Raises ------ Scilab2PyError If the command(s) fail. """ if not self._session: raise Scilab2PyError('No Scilab Session') if isinstance(cmds, (str, unicode)): cmds = [cmds] if verbose and log: [self.logger.info(line) for line in cmds] elif log: [self.logger.debug(line) for line in cmds] if timeout is None: timeout = self.timeout pre_call = '' post_call = '' pre_call += ''' h = gdf(); h.figure_position = [0, 0]; h.figure_size = [%(plot_width)s,%(plot_height)s]; h.axes_size = [%(plot_width)s * 0.98, %(plot_height)s * 0.8]; ''' % locals() if not plot_dir is None: plot_dir = plot_dir.replace("\\", "/") spec = '%(plot_dir)s/%(plot_name)s*.%(plot_format)s' % locals() existing = glob.glob(spec) plot_offset = len(existing) pre_call += ''' close all; function handle_all_fig() ids_array=winsid(); for i=1:length(ids_array) id=ids_array(i); outfile = sprintf('%(plot_dir)s/__ipy_sci_fig_%%03d', i + %(plot_offset)s); if '%(plot_format)s' == 'jpg' then xs2jpg(id, outfile + '.jpg'); elseif '%(plot_format)s' == 'jpeg' then xs2jpg(id, outfile + '.jpeg'); elseif '%(plot_format)s' == 'png' then xs2png(id, outfile); else xs2svg(id, outfile); end close(get_figure_handle(id)); end endfunction ''' % locals() post_call += 'handle_all_fig();' try: resp = self._session.evaluate(cmds, verbose, log, self.logger, timeout=timeout, pre_call=pre_call, post_call=post_call) except KeyboardInterrupt: self.restart() raise Scilab2PyError('Session Interrupted, Restarting') outfile = self._reader.out_file data = None if os.path.exists(outfile) and os.stat(outfile).st_size: try: data = self._reader.extract_file() except (TypeError, IOError) as e: self.logger.debug(e) resp = resp.strip() if resp: if verbose: print(resp) self.logger.info(resp) if return_both: return resp, data else: return data
def _call(self, func, *inputs, **kwargs): """ Scilab2Py Parameters ---------- inputs : array_like Variables to pass to the function. nout : int, optional Number of output arguments. This is set automatically based on the number of return values requested. You can override this behavior by passing a different value. verbose : bool, optional Log Scilab output at info level. plot_dir: str, optional If specificed, save the session's plot figures to the plot directory instead of displaying the plot window. plot_name : str, optional Saved plots will start with `plot_name` and end with "_%%.xxx' where %% is the plot number and xxx is the `plot_format`. plot_format: str, optional The format in which to save the plot (PNG by default). kwargs : dictionary, optional Key - value pairs to be passed as prop - value inputs to the function. The values must be strings or numbers. Returns ------- out : value Value returned by the function. Raises ------ Scilab2PyError If the function call is unsucessful. Notes ----- Integer type arguments will be converted to floating point unless `convert_to_float=False`. """ nout = kwargs.pop('nout', get_nout()) argout_list = ['ans'] if '=' in func: nout = 0 # these three lines will form the commands sent to Scilab # load("-v6", "infile", "invar1", ...) # [a, b, c] = foo(A, B, C) # save("-v6", "outfile", "outvar1", ...) load_line = call_line = save_line = '' prop_vals = [] eval_kwargs = {} for (key, value) in kwargs.items(): if key in ['verbose', 'timeout'] or key.startswith('plot_'): eval_kwargs[key] = value continue if isinstance(value, (str, unicode, int, float)): prop_vals.append('"%s", %s' % (key, repr(value))) else: msg = 'Keyword arguments must be a string or number: ' msg += '%s = %s' % (key, value) raise Scilab2PyError(msg) prop_vals = ', '.join(prop_vals) if nout: # create a dummy list of var names ("a", "b", "c", ...) # use ascii char codes so we can increment argout_list, save_line = self._reader.setup(nout) call_line = '[{0}] = '.format(', '.join(argout_list)) call_line += func + '(' if inputs: argin_list, load_line = self._writer.create_file(inputs) call_line += ', '.join(argin_list) if prop_vals: if inputs: call_line += ', ' call_line += prop_vals call_line += ');' # create the command and execute in octave cmd = [load_line, call_line, save_line] data = self.eval(cmd, **eval_kwargs) if isinstance(data, dict) and not isinstance(data, Struct): data = [data.get(v, None) for v in argout_list] if len(data) == 1 and data[0] is None: data = None return data