Source code for director.matlab

from subprocess import Popen, PIPE, STDOUT

import subprocess
import select
import socket
import os

import director
from director.simpletimer import SimpleTimer

import numpy as np



[docs]def startMatlab(): return subprocess.Popen(['matlab', '-nodisplay', '-nosplash'], stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.STDOUT)
def _readAllSoFar(proc, retVal=''): while proc.poll() is None and (select.select([proc.stdout],[],[],0)[0] != []): retVal += proc.stdout.read(1) return retVal DEFALUT_MATLAB_SERVER_PORT=41576
[docs]class MatlabServer(object): def __init__(self, port=DEFALUT_MATLAB_SERVER_PORT): self.port = port self.proc = None self.sock = None
[docs] def start(self): self.proc = startMatlab() self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.sock.bind(('', self.port)) self.sock.listen(1) while True: print 'waiting for client...' conn, addr = self.sock.accept() print 'client connected.' self.serve(conn)
[docs] def serve(self, sock): sock.settimeout(0.001) while True: data = _readAllSoFar(self.proc, '') if data: sock.send(data) try: inData = sock.recv(1024) if inData: self.proc.stdin.write(inData) else: sock.close() return except socket.timeout as e: pass except socket.error as e: print 'socket error:', e sock.close() return
[docs]class MatlabSocketClient(object): def __init__(self, host='127.0.0.1', port=DEFALUT_MATLAB_SERVER_PORT): self.host = host self.port = port self.sock = None self.connect()
[docs] def connect(self): self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try: self.sock.connect((self.host, self.port)) except socket.error: self.sock = None else: self.sock.settimeout(0.001)
[docs] def send(self, data): self.sock.send(data)
[docs] def receive(self): if not self.isAlive(): return '' try: inData = self.sock.recv(1024) if inData: return inData else: self.sock.close() self.sock = None return '' except socket.timeout as e: return ''
[docs] def isAlive(self): return (self.sock is not None)
[docs]class MatlabPipeClient(object): def __init__(self): self.proc = startMatlab()
[docs] def send(self, data): self.proc.stdin.write(data)
[docs] def receive(self): return _readAllSoFar(self.proc, '')
[docs] def isAlive(self): return (self.proc.poll() is None)
[docs]class MatlabCommunicator(object): def __init__(self, matlabClient): self.client = matlabClient self.prompt = '>> ' self.outputConsole = None self.echoToStdOut = True self.echoCommandsToStdOut = False self.writeCommandsToLogFile = False self.logFile = None self.logFileName = os.path.expanduser('~/.director/matlab_commands.m') self.clearResult()
[docs] def checkForResult(self): self.accumulatedOutput = self.accumulatedOutput + self.client.receive() if self.accumulatedOutput.endswith(self.prompt): self.outputLines = self.accumulatedOutput.split('\n')[:-1] return self.outputLines else: return None
[docs] def getLogFile(self): if self.logFile is None: if not os.path.exists(os.path.dirname(self.logFileName)): os.makedirs(os.path.dirname(self.logFileName)) self.logFile = open(self.logFileName, 'w') return self.logFile
[docs] def isAlive(self): return self.client.isAlive()
[docs] def waitForResult(self, timeout=None): t = SimpleTimer() while self.isAlive(): result = self.checkForResult() if result is not None: return result if timeout is not None and t.elapsed() > timeout: return None
def _colorReplace(self, line): line = line.replace('[\x08', '<font color="orange">') line = line.replace(']\x08', '</font>') line = line.replace('}\x08', '<font color="red">') line = line.replace('{\x08', '</font>') return line def _colorStrip(self, line): line = line.replace('[\x08', '') line = line.replace(']\x08', '') line = line.replace('}\x08', '') line = line.replace('{\x08', '') return line
[docs] def printResult(self): if not self.outputLines: return if self.outputConsole: self.outputConsole.append('<pre>' + '<br/>'.join([self._colorReplace(line) for line in self.outputLines]) + '</pre>') if self.echoToStdOut or not self.outputConsole: print '\n'.join([self._colorStrip(line) for line in self.outputLines]) if self.outputConsole: scrollBar = self.outputConsole.verticalScrollBar() scrollBar.setValue(scrollBar.maximum)
[docs] def clearResult(self): self.accumulatedOutput = '' self.outputLines = []
[docs] def getResult(self): return self.outputLines
[docs] def getResultString(self): return self.accumulatedOutput
[docs] def send(self, command): assert self.isAlive() self.clearResult() self.client.send(command + '\n') if self.echoCommandsToStdOut: print command if self.writeCommandsToLogFile: self.getLogFile().write(command + '\n') self.getLogFile().flush()
[docs] def sendCommands(self, commands, display=True): commands = '\n'.join(commands).split('\n') for command in commands: self.send(command) self.waitForResult() if display: self.printResult()
[docs] def waitForResultAsync(self, timeout=0.0): while self.waitForResult(timeout) is None: yield
[docs] def sendCommandsAsync(self, commands, timeout=0.0, display=True): commands = '\n'.join(commands).split('\n') for command in commands: self.send(command) for _ in self.waitForResultAsync(timeout): yield if display: self.printResult()
[docs] def getFloatArray(self, expression): self.send('disp(%s)' % expression) result = self.waitForResult() if len(result) and not result[-1]: result.pop() def parseRow(rowData): values = rowData.split() if len(values) == 1: return float(values[0]) else: return [float(x) for x in values] try: return [parseRow(x) for x in result] except: raise Exception('Failed to parse output as a float array. Output was:\n%s' % '\n'.join(result))
[docs] def assignFloatArray(self, array, arrayName): def joinFloats(values, sep): maxLength = 180.0 pieces = np.array_split(values, np.ceil(len(values)/maxLength)) pieces = [sep.join([repr(float(x)) for x in piece]) for piece in pieces] return str(sep + '...\n').join(pieces) if np.ndim(array) == 1: arrayStr = '[%s]' % joinFloats(array, ';') else: assert np.ndim(array) == 2 arrayStr = '[%s]' % ';...\n'.join([joinFloats(row, ',') for row in array]) self.send('%s = %s;' % (arrayName, arrayStr)) self.waitForResult()
[docs] def interact(self): self.clearResult() previousEchoMode = self.echoToStdOut self.echoToStdOut = True while self.isAlive(): command = raw_input('>>>') if not command: continue if command == 'break': break self.send(command) self.waitForResult() self.printResult() self.echoToStdOut = previousEchoMode
if __name__ == '__main__': server = MatlabServer() server.start()