Calling Chimera from another program
Hi Brian, I talked to Niels Volkmann on Friday about how PyCoan can use Chimera for displaying maps. There are two existing ways for programs to communicate with Chimera. Here are some info about those. Since PyCoan uses Python it would be possible for it to run under the same Python interpreter as Chimera. Current Chimera daily builds use a standard Python 2.5 distribution with a bunch of additional modules (numpy, pil, pytables, ...) included. Although this approach gives the most power for passing data between PyCoan and Chimera, it requires the two programs to use exactly the same versions of third party Python modules and that can cause problems. Also it allows unlimited access to Chimera internals and use of that functionality would likely make PyCoan/Chimera communication break as Chimera code evolves. There are two ways to communicate with Chimera from a separate process. One involves sending Chimera commands (e.g. "open mymap.mrc") to Chimera's stdin. You have to start Chimera with the following option to get it to read stdin "chimera --start ReadStdin". The other method involves sending Python code to Chimera using a socket. The second approach works by running "chimera --send somecode.py" which will connect to an existing Chimera on the local machine or start one if none is running. Both methods require Chimera and the controlling process to run on the same machine. The second method does not require that limitation but we impose it because there is no authentication method -- so if you allow remote connections, anyone could run arbitrary Python code on your machine (unlikely to be abused, but we're not going to distribute that capability). The first approach is limited to Chimera commands and many Chimera capabilities available in the graphical user interface have no equivalent command. All the capabilities are available if Python code is used. Sending Chimera commands returns the text output of the command although this rarely contains useful information. Sending Python code with "chimera --send xxx.py" returns nothing. So the communication is essentially uni-directional. The advantage of these communication methods over just start Chimera with a Python script as an argument is that you can maintain a connection to a single instance of Chimera and update the visualization as needed. Both the stdin and socket methods need map data to be written to a separate file if you want to open that. Niels was interested in avoiding the use of temporary files and suggested using shared memory. Python has some shared memory support but I recommend against that. The performance is unlikely to be dramatically better. If you write a temporary file the operating system is going to cache it in memory rather than writing it to disk and Chimera will then read it from memory. If you delete the temporary file soon it may never be written to disk. You could force this behavior using shared memory but that is just a more complex way to achieve the same optimization that the operating system is already providing. In any case I would not pursue that until you test the performance of using files. I've attached an example Python script that starts Chimera and sends commands to open a volume and set its contour level and color. I tested it with a Chimera daily build (1.2502). I recommend using the daily builds instead of the November 2007 production release since many volume data improvements have been made. Here is Chimera documentation on the ReadStdin and "--send" communication methods. http://www.cgl.ucsf.edu/chimera/docs/ContributedSoftware/readstdin/readstdin... http://www.cgl.ucsf.edu/chimera/docs/UsersGuide/options.html Tom # ----------------------------------------------------------------------------- # Example program that sends commands to Chimera. # class Chimera_IO: def __init__(self): args = ['chimera', '--start', 'ReadStdin'] self.prog = run_program(args) def send_command(self, command): p = self.prog p.stdin.write(command + '\n') p.stdin.flush() # Collect output. lines = [] while True: line = p.stdout.readline() if line == '' or line == 'END\n': break lines.append(line) output = ''.join(lines) return output # ----------------------------------------------------------------------------- # def run_program(args): # Hide console window on Windows. import sys if sys.platform == 'win32': from subprocess import STARTUPINFO, STARTF_USESHOWWINDOW spinfo = STARTUPINFO() spinfo.dwFlags |= STARTF_USESHOWWINDOW else: spinfo = None from subprocess import Popen, PIPE try: p = Popen(args, stdin = PIPE, stdout = PIPE, startupinfo = spinfo) except: print 'Starting "%s" failed.\n' % ' '.join(args) return None return p # ----------------------------------------------------------------------------- # c = Chimera_IO() print c.send_command('open 0 /tmp/sfv.mrc') print c.send_command('volume #0 level 2500 color tan')
participants (1)
-
Tom Goddard