Difference between revisions of "CompSciWeek9"

From Predictive Chemistry
Jump to: navigation, search
(Created page with "= Class 1, an in-depth look at class structure = * magic methods, __init__, etc. * class inheritance - extending something that does almost what you want ** ex. inheriting from …")
 
(Class 2, python's ctypes)
Line 57: Line 57:
 
** Declaring function types.
 
** Declaring function types.
 
** Performance test
 
** Performance test
Reference: [https://docs.python.org/2/library/ctypes.html]
+
Reference: [https://docs.python.org/2/library/ctypes.html Python Docs] [http://wiki.scipy.org/Cookbook/Ctypes Numpy + Ctypes Cookbook]
   
  +
'''dwt.c''' - run one step of a discrete wavelet transformation.
 
<source lang="C">
 
<source lang="C">
 
#include <stdint.h>
 
#include <stdint.h>
Line 90: Line 91:
 
</source>
 
</source>
   
  +
Compile the C code to a shared library using gcc:
 
<source lang="bash">
 
<source lang="bash">
 
gcc -o dwt_c.so -shared dwt.c
 
gcc -o dwt_c.so -shared dwt.c
 
</source>
 
</source>
   
  +
Now load and run the object from python:
  +
'''dwt.py'''
 
<source lang="python">
 
<source lang="python">
 
from ctypes import CDLL, c_int32, c_double
 
from ctypes import CDLL, c_int32, c_double
Line 128: Line 132:
 
print run_dwt(np.arange(11))
 
print run_dwt(np.arange(11))
 
</source>
 
</source>
  +
  +
'''vis.py''' - visualize the DWT by running on image data
  +
<source lang="python">
  +
import PIL
  +
from dwt import run_dwt, np
  +
  +
# convert to 1-color (luminance)
  +
img = PIL.Image.open("Mitosis.png").convert("L")
  +
x = np.array(img)
  +
  +
y = np.array(map(run_dwt, x))
  +
  +
img = PIL.Image.fromarray(y)
  +
img.show()
  +
</source>
  +
  +
Here's a test image to use:
  +
[[File:Mitosis.png]]
  +
Image from [http://brookeborel.com/2011/06/02/363/ Brooke Borel].

Revision as of 11:53, 22 October 2014

Class 1, an in-depth look at class structure

  • magic methods, __init__, etc.
  • class inheritance - extending something that does almost what you want
    • ex. inheriting from dict
  • isinstance() function
  • methods and calling convention - the first argument to a class method is always the class (i.e. self)
  • Binary operations __add__, __mul__, etc. - these have type class -> class -> class
  • static (immutable) vs. dynamic (mutable)
    • classes are static
    • instances are dynamic
      • unless you only initialize and don't ever change them
      • if you know it's static and __hash__ is implemented, you can use it as a key

Example - wrapping a numpy array in a static class to build a cache: <source lang="python"> from numpy import *

  1. TODO: make static!

class s_ndarray:

   def __init__(self, x):
       self.x = x
   def __hash__(self):
       return hash(self.x.__repr__())

a = s_ndarray(arange(12))

  1. array -> float

def en(x): print "Running (expensive) energy calculation." return x[0]

  1. { s_ndarray : float } -> s_ndarray -> float

def en_cached(cache, x): if x not in cache: cache[x] = en(x.x) # peel off s_ndarray and run the en function return cache[x]

cache = {} x = s_ndarray(arange(12)) y = s_ndarray(ones(12)) print en_cached(cache, x) print en_cached(cache, y)

print cache

  1. these don't need to call en

print en_cached(cache, y) print en_cached(cache, y) </source>

Class 2, python's ctypes

  • Compiling a c code as a shared object
    • the trouble with integers - always pick a fixed size!
  • loading with ctypes
    • Declaring function types.
    • Performance test

Reference: Python Docs Numpy + Ctypes Cookbook

dwt.c - run one step of a discrete wavelet transformation. <source lang="C">

  1. include <stdint.h>

/* Calculate the step-function discrete wavelet transformation

* on the data x, placing the result in y.
* 
*   This assumes x and y are already allocated and of size n.
*
* x = ababab ababab
* y = (a+b)  (b-a)
*/

int32_t dwt(double *x, double *y, int32_t n) { int i; // index into x, moves from 0, ..., n-1 int a = 0; // index into y sum, moves from 0, ..., ceil n/2 int b = (n+1)/2; // index into y difference, moves from (ceil n/2)+1, ..., n-1

for(i=0; i<n-1; i+=2) { y[a] = 0.5*(x[i+1]+x[i]); y[b] = x[i+1]-x[i]; a += 1; b += 1; } // odd case, ceil n/2 = (n+1)/2 and we have an extra sum if(i == n-1) { y[a] = x[i]; }

return 0; } </source>

Compile the C code to a shared library using gcc: <source lang="bash"> gcc -o dwt_c.so -shared dwt.c </source>

Now load and run the object from python: dwt.py <source lang="python"> from ctypes import CDLL, c_int32, c_double import numpy as np import numpy.ctypeslib as ct import os

cwd = os.path.dirname(os.path.abspath(__file__)) dw = CDLL(os.path.join(cwd, "dwt_c.so"))

  1. Shorthand for setting function prototypes

def decl_fn(a, *args):

       a.argtypes = args[:-1]
       a.restype = args[-1]

def void_fn(a, *args):

       decl_fn(a, *(args+(None,)))

def int_fn(a, *args):

       decl_fn(a, *(args+(c_int32,)))

def dbl_fn(a, *args):

       decl_fn(a, *(args+(c_double,)))
  1. Building up common, useful data types

intarr = np.ctypeslib.ndpointer(dtype=np.int32, flags='C_CONTIGUOUS') dblarr = np.ctypeslib.ndpointer(dtype=np.float64, flags='C_CONTIGUOUS')

decl_fn(dw.dwt, dblarr, dblarr, c_int32)

def run_dwt(x): y = np.zeros(x.shape, dtype=np.float64) print dw.dwt(x.astype(np.float64), y, len(x)) return y

print run_dwt(np.arange(12)) print run_dwt(np.arange(11)) </source>

vis.py - visualize the DWT by running on image data <source lang="python"> import PIL from dwt import run_dwt, np

  1. convert to 1-color (luminance)

img = PIL.Image.open("Mitosis.png").convert("L") x = np.array(img)

y = np.array(map(run_dwt, x))

img = PIL.Image.fromarray(y) img.show() </source>

Here's a test image to use: Mitosis.png Image from Brooke Borel.