## Mittwoch, 27. Juni 2012

### Python 004: My first closure

Depending on the presence of a number of files, a couple of functions had to be called. But depending on the kind of file, a different function was required. However, for each file, the logic to determine if the corresponding function should be called or not is the same. For technical reasons, the respective functions are in different modules (executed through some Ajax).
So it seemed to me I would have to write the logic part specifically for each case, i.e. for each case where a file is available or not.
Something as below:

if file_exists('-ini'):
function_one()
if not file_exists('-ini'):
generate_ini_file()
function_one()
if file_exits('-fin'):
function_two()
if not file_exists('-fin'):
generate_fin_file()
function_two()


and so on. However, I remembered, in Python everything is an object. Even functions. So, why not prepare a function, which takes care of the logic and the execution of the function which I want to apply to each of the corresponding files. But then, where should the applied function come from? Exactly, from a closure. This basically is a function which generates functions at runtime. What kind of arguments does it take? Precicely, the function you actually want to call. Huh? Yes, of course the applied function needs to be defined somewhere, but thats another story, lets assume we have it. It could look something like this:

def translate_com(target):
"""Calling VMD and returning the output directly."""
vmd_src = 'mol load pdb %s-fix.pdb\n' % (bio_lib.pdb_base_path + target)\
+ 'set HOME ' + bio_lib.vmd_base_path + '\n'\
+ 'molinfo 0 get center\n'\
+ 'env\n'
comp = Popen([bio_lib.vmd_cmd_path, '-dispdev', 'text', '-eofexit'],
stdout=PIPE, stdin=PIPE, stderr=PIPE, shell=False)
comp.stdin.write(vmd_src)
vmd_com_result = comp.communicate()[0]

for line in vmd_com_result.split('\n'):
if len(line) > 0 and line[0] == '{':
com_xyz = [float(i) for i in line[1:-1].split()]
com_xyz = [i*(-1) for i in com_xyz]
# Calling the VMD reorientation script.
reo_src = bio_lib.get_reo_src(com_xyz, target)
vmdp = Popen([bio_lib.vmd_cmd_path, '-dispdev', 'text', '-eofexit'],
stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=False)
vmdp.stdin.write(reo_src)
print vmdp.communicate()[0]


It does something, other functions are doing similar things. This is, e.g., the 'function_two' above. So for each of these, there would be a logic block as this:

def check_availability_and_translate(target):
# Force overwrite.
if overwrite:
translate_com(target)
# Does not exist.
if not os.path.exists(bio_lib.pdb_base_path + target + '-reo.pdb'):
translate_com(target)
else:
# Use existing.
if os.path.exists(bio_lib.pdb_base_path + target + '-reo.pdb'):
print "Structure available."
# Fixed structure not available.
else:
reo.translate_com(target)


In the above, there's also a bit of user interaction coming in, but that's not the point. The point is, all this is the same for each of my functions. So, lets generate a function that returns this logic, but takes the 'translate_com' function as an argument and calls it whenever *a* function is called:

def closure(state):
"""
'state': '-ini', '-fin', '-reo'
"""
# Force overwrite.
if overwrite:
print "Overwriting"
func(target)
# Does not exist.
if not os.path.exists(pdb_base_path + target + state):
func(target)
# Use existing.
else:
# Use existing.
if os.path.exists(pdb_base_path + target + state):
print "Structure available."
# Structure not available.
else:
func(target)
return check_availability_and_apply


The fun is in the last line. As one can see, a function is returned which was built within the closure. So how can I now call (or maybe better "apply") the 'translate_com' function?

closure('-ini.pdb')(target, uploaded, overwrite, translate_com)



closure('-fix.pdb')(target, uploaded, overwrite, fix_pdb)