I'd almost forgotten about this:
Two patched protein subtypes and a conserved domain of group I proteins that regulates turnover.
Kawamura S, Hervold K, Ramirez-Weber FA, Kornberg TB.
Biochemistry & Biophysics, University of California, San Francisco, CA 94158.
Patched (Ptc) is a twelve-cross membrane protein that binds the secreted Hedgehog protein. Its regulation of the Hedgehog signaling pathway is critical to normal development and to a number of human diseases. This report analyzes features of sequence similarity and divergence in the Ptc protein family and identifies two subtypes distinguished by novel conserved domains. We used these results to propose a rational basis for classification. We show that one of the conserved sequence regions in the C-terminal domain of Ptc 1 is responsible, at least in part, for rapid turnover. This sequence is absent from the stable Ptc 2 protein.
Monday, September 8, 2008
Wednesday, September 3, 2008
Levenshtein distance
A Levenshtein distance, or "edit distance," is a measure of the similarity of two given strings as embodied in the number of changes--insertions, deletions, or substitutions--required to transform one string into the other.
This is an incredibly useful tool for grouping and ordering strings, and in particular, non-language strings -- we already have a convention for ordering words in English, but if you're staring at 200 protein sequences, alphabetic order doesn't do anything for you.
There's a fast C implementation of the Levenshtein algorithm and though it doesn't seem to have a proper project homepage, it can be found in the Pootle & Translate Toolkit.
I needed to add a wildcard parameter to the Levenshtein algorithm so that the distance between, eg, ABC and AXC is 0, given that 'X' is the specified wildcard character. (Normally, the Levenshtein distance between "ABC" and "AXC" is 1, of course: it takes one substitution to turn one string into the other.)
So I did.
Before I attempted to modify this C version, though, I put together a simple, unoptimized Python version, and the difference in performance was shocking. On my test data set, the C code took 0.3s to run, and the Python version took ... over 3 minutes. It was over 1000x slower.
After adding the couple of if statements and loops necessary for the wildcard code, the C code slowed to 1.2s.
This is an incredibly useful tool for grouping and ordering strings, and in particular, non-language strings -- we already have a convention for ordering words in English, but if you're staring at 200 protein sequences, alphabetic order doesn't do anything for you.
There's a fast C implementation of the Levenshtein algorithm and though it doesn't seem to have a proper project homepage, it can be found in the Pootle & Translate Toolkit.
I needed to add a wildcard parameter to the Levenshtein algorithm so that the distance between, eg, ABC and AXC is 0, given that 'X' is the specified wildcard character. (Normally, the Levenshtein distance between "ABC" and "AXC" is 1, of course: it takes one substitution to turn one string into the other.)
So I did.
Before I attempted to modify this C version, though, I put together a simple, unoptimized Python version, and the difference in performance was shocking. On my test data set, the C code took 0.3s to run, and the Python version took ... over 3 minutes. It was over 1000x slower.
After adding the couple of if statements and loops necessary for the wildcard code, the C code slowed to 1.2s.
Tuesday, August 19, 2008
MochiKit, IE6, and DOM manipulation
I'd recommend MochiKit to anyone who has to write Javascript code -- it lives up to its motto and "makes Javascript suck less." I'd recommend it twice as forcefully to Python coders, as features like the iteration tools are explicitly inspired by Python; and thrice as forcefully to any functional programming -minded Python coders, as it provides handy functions like map and zip, plus short-cuts for partial application and the like.
Bob Ippolito is a smart man.
MochiKit also provides some convenient DOM manipulation tools, such that swapping in a whole table takes only 3 or 4 lines of code:
(assuming you already had a DOM element w/ id='mytable')
A quick caveat, though: Internet Explorer 6 is picky about tables, and requires that a table created via the DOM have a TBODY or nothing will be displayed.
Bob Ippolito is a smart man.
MochiKit also provides some convenient DOM manipulation tools, such that swapping in a whole table takes only 3 or 4 lines of code:
swapDOM( $('mytable'),
TABLE({'id':'mytable'},
TBODY(null, [TR(null, TD(null, "a cell"))] ) );
(assuming you already had a DOM element w/ id='mytable')
A quick caveat, though: Internet Explorer 6 is picky about tables, and requires that a table created via the DOM have a TBODY or nothing will be displayed.
Thursday, July 17, 2008
Python class inconsistencies
Update:
Masklinn's correction is obviously correct -- this isn't primarily a class v. instance variable problem, it's the difference between the operators I'm using on the instance variables.
So, an assignment (k.t = ...) points the attribute at a wholly new object, while accessing one of the attributes' methods actually alters the attributes' state.
(Which is where the confusion over mutability comes into play, but it was still confusion on my part.)
My original posting:
This makes a modicum of sense if you have a basic grasp of the distinction between mutables and immutables in Python, but it still seems like a mess.
Do you see it?
Class K defines two attributes, a tuple t and a list l.
If you instantiate K twice (k and j), then change the t attribute of one and the l attribute of the other, the change to l will be shared between instances, while the change to t will only effect the instance.
Whether an attribute belongs to the class or the instance depends on whether it's type is mutable or not!
There's a fix in one case: you can use __init__ to make mutable data instance-specific:
However, I can't find a way to accomplish the opposite--create a class attribute for an immutable data type--w/out resorting to __get_attribute__ magic.
Masklinn's correction is obviously correct -- this isn't primarily a class v. instance variable problem, it's the difference between the operators I'm using on the instance variables.
So, an assignment (k.t = ...) points the attribute at a wholly new object, while accessing one of the attributes' methods actually alters the attributes' state.
(Which is where the confusion over mutability comes into play, but it was still confusion on my part.)
My original posting:
This makes a modicum of sense if you have a basic grasp of the distinction between mutables and immutables in Python, but it still seems like a mess.
>>> class K(object):
>>> t = (1,2,3)
>>> l = [1,2,3]
>>>
>>> k = K()
>>> j = K()
>>>
>>> k.t = ('a','b','c')
>>> j.l.append( 10 )
>>>
>>> j.t
(1, 2, 3)
>>> k.l
[1, 2, 3, 10]
Do you see it?
Class K defines two attributes, a tuple t and a list l.
If you instantiate K twice (k and j), then change the t attribute of one and the l attribute of the other, the change to l will be shared between instances, while the change to t will only effect the instance.
Whether an attribute belongs to the class or the instance depends on whether it's type is mutable or not!
There's a fix in one case: you can use __init__ to make mutable data instance-specific:
Now changes to k.l won't effect j.l
>>> class K(object):
>>> t = (1,2,3)
>>> l = [1,2,3]
>>> def __init__(self):
>>> self.l = [1,2,3]
However, I can't find a way to accomplish the opposite--create a class attribute for an immutable data type--w/out resorting to __get_attribute__ magic.
Saturday, June 14, 2008
Pyrex for performance and obfuscation
I've recently been asked to obfuscate a bunch of Python code. Encryption is one possibility, but the user needs the key along with the encrypted code in order to run the code, so this is really just a round-about form of obfuscation. And if multi-billion dollar (and rather unsavory) industries can't get this right, I'd rather not even try.
One novel form of obfuscation is compilation to C-code, a task made relatively simple by Pyrex and, more recently, Cython. Both projects are mainly intended to ease the integration of C libraries with Python; both accomplish this by compiling native Python code into a .so shared object. This .so file should, in turn, be slightly harder to decypher than Python bytecode.
Pyrex isn't as actively maintained as Cython, but it is available via Macports, so I'm using Pyrex for now.
Pyrex appears to work by first translating your Python code into C, then compiling this C against the Python libraries. Unannotated Python objects remain PyObject * pointers -- it's quite possible that the Python interpreter, or VM, or whatever lies underneath, is still doing most of the heavy lifting with Pyrex-translated code; I can't make any sense of it.
But Pyrex also allows you to write Python-like code that gets translated to native C, with all the implied performance gains. As a simple example, I've done a naive implementation of the Fibonacci sequence in plain Python and in Pyrex' C/Python intermediary. Here's the file, called "pyrex_fib.pyx":
_cfib and pyfib are the same function, w/ _cfib implemented in Pyrex C notation; cfib is a wrapper around _cfib. (Native C functions can't be called directly from Python and must be wrapped.)
"pyrex_fib.pyx" is compiled to a Python-friendly .so file via distutils; here's the contents of "setup.py" -- lifted from Michael's Guide to Pyrex:
The compilation is accomplished via python setup.py build_ext --inplace, but note that bugs can result in the rather cryptic error message error: Pyrex does not appear to be installed on platform 'posix'
I also wrote a plain Python version, "py_fib.py":
This enables me to compare Pyrex-translated Python code stored in a .so to the same code stored in a regular Python module, and compare them both to the "native" version.
I do this comparison via a simple module that imports both forms and runs them, timing each invocation. Here's the output:
Interestingly, the Pyrex-translated Python code is about 20% slower than the regular Python; presumably, it's not benefiting from various interpreter optimizations. The "C" implementation blows them both out of the water.
Pyrex looks great for wrapping C libraries for Python, and might serve for code obfuscation, but the major limitation is the difficulty of moving non-scalar data types between C and Python: it wouldn't have been easy to return a Python dictionary from my cfib routine, for example.
One novel form of obfuscation is compilation to C-code, a task made relatively simple by Pyrex and, more recently, Cython. Both projects are mainly intended to ease the integration of C libraries with Python; both accomplish this by compiling native Python code into a .so shared object. This .so file should, in turn, be slightly harder to decypher than Python bytecode.
Pyrex isn't as actively maintained as Cython, but it is available via Macports, so I'm using Pyrex for now.
Pyrex appears to work by first translating your Python code into C, then compiling this C against the Python libraries. Unannotated Python objects remain PyObject * pointers -- it's quite possible that the Python interpreter, or VM, or whatever lies underneath, is still doing most of the heavy lifting with Pyrex-translated code; I can't make any sense of it.
But Pyrex also allows you to write Python-like code that gets translated to native C, with all the implied performance gains. As a simple example, I've done a naive implementation of the Fibonacci sequence in plain Python and in Pyrex' C/Python intermediary. Here's the file, called "pyrex_fib.pyx":
cdef _cfib( int i ):
if i < 3:
return 1
else:
return _cfib(i-1) + _cfib(i-2)
def cfib( i ):
return _cfib( i )
def pyfib( i ):
if i < 3:
return 1
else:
return pyfib(i-1) + pyfib(i-2)
_cfib and pyfib are the same function, w/ _cfib implemented in Pyrex C notation; cfib is a wrapper around _cfib. (Native C functions can't be called directly from Python and must be wrapped.)
"pyrex_fib.pyx" is compiled to a Python-friendly .so file via distutils; here's the contents of "setup.py" -- lifted from Michael's Guide to Pyrex:
from distutils.core import setup
from distutils.extension import Extension
from Pyrex.Distutils import build_ext
setup(
name = "PyrexGuide",
ext_modules=[
Extension("pyrex_fib", ["pyrex_fib.pyx"])
],
cmdclass = {'build_ext': build_ext}
)
The compilation is accomplished via python setup.py build_ext --inplace, but note that bugs can result in the rather cryptic error message error: Pyrex does not appear to be installed on platform 'posix'
I also wrote a plain Python version, "py_fib.py":
def pyfib( i ):
if i < 3:
return 1
else:
return pyfib(i-1) + pyfib(i-2)
This enables me to compare Pyrex-translated Python code stored in a .so to the same code stored in a regular Python module, and compare them both to the "native" version.
I do this comparison via a simple module that imports both forms and runs them, timing each invocation. Here's the output:
kieran@host:~/tmp/pyrex$ ./time_fib.py
Sat Jun 14 12:15:07 2008
pyrex_fib.cfib(40) = 102334155 in 9.6s
pyrex_fib.pyfib(40) = 102334155 in 121.5s
py_fib.pyfib(40) = 102334155 in 98.0s
Interestingly, the Pyrex-translated Python code is about 20% slower than the regular Python; presumably, it's not benefiting from various interpreter optimizations. The "C" implementation blows them both out of the water.
Pyrex looks great for wrapping C libraries for Python, and might serve for code obfuscation, but the major limitation is the difficulty of moving non-scalar data types between C and Python: it wouldn't have been easy to return a Python dictionary from my cfib routine, for example.
Friday, May 30, 2008
Ouroboros
Circular dependencies will break your Python code!
Given some module A that depends upon module B (ie, import B), and given a module B which depends upon module A, you'll get this rather cryptic error message:
ImportError: cannot import name A
This works at any remove, of course -- the circle could stretch through 1,000 modules, but once you forge that loop, you're toast.
The solution is to refactor your code to put routine from A needed by B into a separate module C that depends upon neither.
Given some module A that depends upon module B (ie, import B), and given a module B which depends upon module A, you'll get this rather cryptic error message:
ImportError: cannot import name A
This works at any remove, of course -- the circle could stretch through 1,000 modules, but once you forge that loop, you're toast.
The solution is to refactor your code to put routine from A needed by B into a separate module C that depends upon neither.
Wednesday, May 28, 2008
Leopard emacs is broken...
Which means that GNUplot is broken under Leopard, and with it, scipy.
Fortunately, there's a solution:
sudo mv /usr/bin/emacs-i386 /usr/bin/emacs-i386.backup
sudo /usr/libexec/dumpemacs -d
emacs --version
emacs
It's quite beyond me why the emacs shipping w/ Leopard is broken out of the box, but can be repaired via the dumpemacs command, but there it is.
Fortunately, there's a solution:
sudo mv /usr/bin/emacs-i386 /usr/bin/emacs-i386.backup
sudo /usr/libexec/dumpemacs -d
emacs --version
emacs
It's quite beyond me why the emacs shipping w/ Leopard is broken out of the box, but can be repaired via the dumpemacs command, but there it is.
Subscribe to:
Posts (Atom)