2012/05/31

python tips: effective sparse matrix operation ?

#!/usr/bin/env python
#coding:utf-8
 
import numpy as np
import scipy as sp
from scipy.sparse import *
from numpy.random import *
from collections import OrderedDict
from datetime import datetime
 
# performance logger
import cProfile as profile
import pstats
 
from itertools import groupby
from operator import itemgetter

def gen_mat(M, N, R, format="csc"):
    """generating lil_matrix with random valuables"""
    mat = sp.sparse.rand(M, N, R, format=format, dtype=np.dtype('float64'))
    mat = mat * 250
    print("{0}x{1} matrix (sparsity:{2}, # of data:{3}) is generated...".format(M, N, R, mat.nnz))
    return mat
 
def join_columns1(spamat, target_col):
    """join columns using getcol() which requires object copying"""
    return reduce(lambda x,y: x+y, [spamat[:,index] for index in target_col])

def join_columns2(lilmat, target_col):
    """join columns using lil_matrix's getrowview() which does not require object copying """
    lilt = lilmat.T
    return reduce(lambda x,y: x+y, (lilt.getrowview(index) for index in target_col))

def join_columns3(coomat, N):
    """join columns using coo indices, numpy's fancy index and pydict"""
    dic = {}

    def dic_update(key, val):
        if (dic.has_key(key)):
            dic[key] += val
        else:
            dic[key] = val

    mask = (coomat.col % 26 == 0)
    row = coomat.row[mask]
    data = coomat.data[mask]
    n = len(row)

    [dic_update(row[index], data[index]) for index in range(n)]
    return dic

def get_elapsed_time(func, listargs):
    """wrapper for calculating consuming time of function"""
    s = datetime.now()
    ret = func(*listargs)
    e = datetime.now()
    print("{0}\t{1}".format((e-s), func.__name__))
    return ret
     
def bench(M, N, R, L):
    column_indexes = frozenset([i for i in range(0, N, 26)])

    print("# lil_matrix")
    lilmat = gen_mat(M, N, R, format="lil")
    # get_elapsed_time(join_columns1, (lilmat, column_indexes)) # very slow!
    get_elapsed_time(join_columns2, (lilmat, column_indexes)) # bit slow

    print("# csc_matrix")
    cscmat = lilmat.tocsc()
    get_elapsed_time(join_columns1, (cscmat, column_indexes)) # bit fast

    print("# csr_matrix")
    csrmat = cscmat.tocsr()
    get_elapsed_time(join_columns1, (cscmat, column_indexes)) # bit fast

    print("# coo_matrix")
    coomat = cscmat.tocoo()
    get_elapsed_time(join_columns1, (cscmat, column_indexes)) # bit fast
    get_elapsed_time(join_columns3, (coomat, N))              # very fast

def main():
    M = 1400000      # n_row
    N = 50000        # n_col
    R = 0.0005       # sparsity
    L = int(N * 0.2) # column_indexes
 
    print("-------------------------------------")
    print("M:{0}, N:{1}, R:{2}, L:{3}".format(M, N, R, L))
    print("-------------------------------------")
    bench(M, N, R, L)
     
if __name__ == "__main__":
   main()
-------------------------------------
M:1400, N:5000, R:0.001, L:1000
-------------------------------------
1400x5000 matrix (sparsity:0.001, # of data:7000) is generated...
# lil_matrix
0:00:01.576205 join_columns1
0:00:00.044499 join_columns2
# csc_matrix
0:00:00.047233 join_columns1
# csr_matrix
0:00:00.047329 join_columns1
# coo_matrix
0:00:00.047277 join_columns1
0:00:00.000282 join_columns3

-------------------------------------
M:140000, N:50000, R:0.001, L:10000
-------------------------------------
140000x50000 matrix (sparsity:0.001, # of data:7000000) is generated...
# lil_matrix
0:00:03.003079 join_columns2
# csc_matrix
0:00:02.640237 join_columns1
# csr_matrix
0:00:02.640100 join_columns1
# coo_matrix
0:00:02.647828 join_columns1
0:00:00.300576 join_columns3

statistics tips: my covariance matrix implementation on python

#!/usr/bin/env python                                                                                                                
#coding: utf-8                                                                                                                       
                                                                                                                                     
import numpy as np                                                                                                                   
from numpy.random import *                                                                                                           
                                                                                                                                     
def get_covariance_matrix(A):                                                                                                        
    N, M = A.shape                                                                                                                   
    ret = np.reshape(np.zeros(N*M), (N,M))                                                                                           
                                                                                                                                     
    for n in range(0, N):                                                                                                            
        for m in range(0, M):                                                                                                        
            ret[n][m] = calc_covariance(A, n, m)                                                                                     
                                                                                                                                     
    return ret                                                                                                                       
                                                                                                                                     
def calc_covariance(A, n, m):                                                                                                        
    nominator = np.sum((A[n] - np.average(A[n])) * (A[m] - np.average(A[m])))                                                        
    denominator = A.shape[0] - 1                                                                                                     
    return nominator/denominator                                                                                                     
                                                                                                                                     
def test():                                                                                                                          
    D = 4                                                                                                                            
    A = np.reshape([randint(100) for i in range(D**2)], (D, D))                                                                      
                                                                                                                                     
    print("# numpy.cov() output:")                                                                                                   
    print(np.cov(A))                                                                                                                 
                                                                                                                                     
    print("# my covariance matrix:")                                                                                                 
    print(get_covariance_matrix(A))                                                                                                  
                                                                                                                                     
    print("# my precision matrix:")                                                                                                  
    print(get_covariance_matrix(A) ** -1)  
                                                                                                                                     
if __name__ == "__main__":                                                                                                           
    test()                             
yaboo@overtones:~$ python kyoubunsan.py
# numpy.cov() output:
[[  226.91666667   -26.83333333   -39.33333333   499.75      ]
 [  -26.83333333   328.33333333   629.          -257.83333333]
 [  -39.33333333   629.          1432.66666667  -882.        ]
 [  499.75        -257.83333333  -882.          1976.25      ]]                                                                      
# my covariance matrix:
[[  226.91666667   -26.83333333   -39.33333333   499.75      ]
 [  -26.83333333   328.33333333   629.          -257.83333333]
 [  -39.33333333   629.          1432.66666667  -882.        ]
 [  499.75        -257.83333333  -882.          1976.25      ]]
# my precision matrix:                                                                                                               
[[ 0.0044069  -0.03726708 -0.02542373  0.002001  ]
 [-0.03726708  0.00304569  0.00158983 -0.00387847]
 [-0.02542373  0.00158983  0.000698   -0.00113379]
 [ 0.002001   -0.00387847 -0.00113379  0.00050601]]

2012/05/22

algorithm tips: Sparse Matrix Multiplication Package (SMMP)

UNDERWRITING... Matrix operation is very useful for improving computing speed of our codes. For this operation, python has very popular packages such as numpy and scipy. In this article, I show sample code to calculate dot product using sparse matrix and vector with numpy and scipy.
import scipy
import numpy
from scipy.sparse import *
from numpy.random import *

vec = create_vec(N)
mat = create_mat(N,M)
ans = mat.dot(vec)
In above code, mat.dot(vec) calculates dot product. This method implements sparse matrix multiplication pacakage called SMMP which computational complexity is : O(n_row*K^2 + max(n_row,n_col))  where n_row is # of matrix rows, n_col is # of matrix columns, K is the maximum index for nonzero value in a row of A and column of B.

python tips: unpickling object is very slow because of garbage collection

In python, unpickling gigantic object from file is very much time consuming because of python's garbage collection. Python's garbage collection starts when cPickle loads gigantic object contains a lot of container object and number of container objects in the object exceed threshold of collect() method, python's garbage collection starts.
Now, assume you have 2GB pickle object which contains huge dictionary object in your file system and your python code load it. I compare loading time with/without garbage collection in python 2.7.2 on Ubuntu12.04.
#!/usr/local/bin/python                                                         
#coding: utf-8                                                                  
                                                                                
import cPickle as pickle                                                        
from datetime import datetime                                                   
import gc
                                                                                
F = file('gigantic_data.pickle', 'rb')                                          
s = datetime.now()                                                              
myobj = pickle.load(F)                                                          
e = datetime.now()                                                              
F.close()
                                                                                
print("load_pickle takes is {0}".(e-s))

# disabling cyclic garbage collection
gc.disable()

F = file('gigantic_data.pickle', 'rb')                                          
s = datetime.now()                                                              
myobj = pickle.load(F)                                                          
e = datetime.now()                                                              
F.close()

print("load_pickle takes is {0}".(e-s))
> /usr/local/bin/python above_script.py
load_pickle takes 0:15:16.530199
load_pickle takes 0:00:14.195409

2012/05/18

python tips: multiprocessing and shared memory

With multiprocessing package, it is extremely easy to make programs which share tasks with multiple workers(processes). This post is memo for how to share object which initialized by parent process with child process.

General way for sharing object between parent process and child processes is using Queue or Pipe. However, it's the easiest way for me to use global valuable. Below code is just a example of how to share object between processes using global valuable.


#!/usr/bin/env python
# coding:utf-8

import os
import multiprocessing

x = 10
y = 20
z = []
a = None
b = [1,2,3]
c = None

c = 3

def main():
    a = 1
    print("###############################")
    print("x:: {0}".format(print_value(x)))
    print("y:: {0}".format(print_value(y)))
    print("z:: {0}".format(print_value(z)))
    print("a:: {0}".format(print_value(a)))
    print("b:: {0}".format(print_value(b)))
    print("c:: {0}".format(print_value(c)))
    print("###############################")
    pool = multiprocessing.Pool(3)
    pool.map(func, [1,2,3], chunksize=1)
    

def print_value(val):
    return "{0}, id:{1}".format(val, id(val))
    
def func(val):
    print("pid: {0}, process_number: {1}".format(os.getpid(), val))
    print("x:: {0}".format(print_value(x)))
    print("y:: {0}".format(print_value(y)))
    print("z:: {0}".format(print_value(z)))    
    print("a:: {0}".format(print_value(a)))
    print("b:: {0}".format(print_value(b)))
    print("c:: {0}".format(print_value(c)))    

if __name__ == "__main__":
    main()

Here is output from above code. 'id' means memory-address pointed by valuable.
yaboo@ubuntu:~$ python shared_memory.py 
###############################
x:: 10, id:24606432
y:: 20, id:24606192
z:: [], id:139931380327848
a:: 1, id:24606648
b:: [1, 2, 3], id:139931380327920
c:: 4, id:24606576
###############################
pid: 3747, process_number: 1
x:: 10, id:24606432
pid: 3748, process_number: 2
y:: 20, id:24606192
x:: 10, id:24606432
z:: [], id:139931380327848
pid: 3749, process_number: 3
y:: 20, id:24606192
a:: None, id:9071744
x:: 10, id:24606432
z:: [], id:139931380327848
y:: 20, id:24606192
b:: [1, 2, 3], id:139931380327920
a:: None, id:9071744
c:: 3, id:24606600
z:: [], id:139931380327848
a:: None, id:9071744
b:: [1, 2, 3], id:139931380327920
b:: [1, 2, 3], id:139931380327920
c:: 3, id:24606600
c:: 3, id:24606600
yaboo@ubuntu:~$ 

2012/05/01

tips: port-forwarding with ssh

These are memos for usage of port forwarding with ssh command. First of all, you need to enable ssh port forwarding with below command.
ssh -f -N -L [#port]:[dest_hostname]:22 [user_name_for_proxy_host]@[proxy_hostname]
If you want to transfer some files use below commands.
scp -P [#port] [user_name_for_dest_host]@localhost:[filename] ./[filename]
scp -P [#port]  ./[filename] [user_name_for_dest_host]@localhost:[filename]
If you want to login with ssh, use below commands.
ssh -p [#port] [user_name_for_dest_host]@localhost

2012/01/25

python tips: array computation with numpy II

As previous post shows, for-loop calculation in array computations needs more processing time than vectorized calculation. There are some techniques for fasten calculation over arrays. Sample code shown below is one of them.
>>> from numpy import *
>>> 
>>> A = array([[1,2,3], [4,5,6], [7,8,9]])
>>> 
>>> def somefunc(x):
...     x1 = x
...     x2 = x - 3
...     return where(x < 7, x1, x2)
... 
>>> somefunc(A)
array([[1, 2, 3],
       [4, 5, 6],
       [4, 5, 6]])
>>> 

python tips: array computation with numpy

I compared performance of array computations. Listed below are results and codes of some experiments which introduced in the book named 'Python Scripting for Computational Science (3rd edition)'.
>>> from numpy import *
>>> import time
>>> 
>>> a = linspace(0, 1, 1E+07)
>>> t0 = time.clock()
>>> b = 3*a - 1
>>> 
>>> t1 = time.clock()
>>> 
>>> for i in xrange(a.size):
...     b[i] = 3*a[i] -1
... 
>>> t2 = time.clock()
>>> 
>>> print '3*a-1: %g sec, loop: %g sec' %(t1-t0, t2-t1)
3*a-1: 0.05 sec, loop: 15.46 sec

python tips: create shapefile with python


Long time has been passed since last post.

Here, I want to show the way to create Shapefile, which is standard data format for geometry data, using python.

Among several python tools such as geoscript, pyshp and pyproj which support operations of Shapefiles, I introduce how to use pyshp.

Pyshp is open source, provides shapefile library written all in pure python and distributed under MIT lisence.

You can download it as shapfile.py from  the official web site or just install via easy_install command:


# easy_install pyshp

However most of available operations of pyshp are introduced in the web site, I write some code using pyshp here just for my memo.

If you want to know more, I recommend looking over the web site and make some sample code according to tutorials.

#!/usr/bin/env python

import shapefile

def create_square(x=0., y=0., i=1.):
    return [[[x, y], [x+i, y], [x+i, y+i], [x, y+i], [x, y]]]

def define_geometry(w):
    # 1st record's geometry
    w.poly(parts=create_square(0, 0, 1))
    # 2nd record's geometry
    w.poly(parts=create_square(1, 1, 1))
    # 3rd record's geometry
    w.poly(parts=create_square(0.5, 0.5, 1))
    return w

def define_fields(w):
    w.field('FLD_1st')
    w.field('FLD_2nd', 'N', '10')
    return w

def fill_attributes(w):
    w.record('hoge', 'hogehogeho')
    w.record('mage', 'mage1')
    w.record('moge', 'mogemoge')
    return w

def create_proj_file(filename):
    # this function creates .proj file which defines projection.
    prj = open("%s.prj" % filename, "w")
    epsg = 'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433]]'
    prj.write(epsg)
    prj.close()

def main():
    filename = 'test'
    w = shapefile.Writer(shapefile.POLYGON)
    w = define_geometry(w)
    w = define_fields(w)
    w = fill_attributes(w)
    w.save('./' + filename)
    create_proj_file(filename)

if __name__ == "__main__":
    main()                                                                                             

2011/09/11

sphinx tips: add subsubsection into pdf compiled by make all-pdf-ja

When sphinx compiles latex files, it chooses cls file which written in conf.py.
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents =
   ('index', 'sample_document.tex', u'This is sample',
     u'Author Name', 'manual'),
]
If 'manual' is specified in conf.py, sphinx read sphinxmanual.cls when it compiles latex file. So, if you want to enable subsubsection, you should edit sphinxmanual.cls or other specified cls file. In my environment, original sphinxmanual.cls is located in /usr/local/lib/python2.6/dist-packages/Sphinx-1.0.7-py2.6.egg/sphinx/texinputs/sphinxmanual.cls. And you can enable subsubsection with editing this cls file like below.
before:
\setcounter{secnumdepth}{2}

after:
\setcounter{secnumdepth}{3}
enjoy.

2011/09/02

sphinx tips: generate center-aligned table in pdf document

When we type 'make latex' command in sphinx root directory, sphinx generates set of latex files from rst files based on '/usr/share/pyshared/sphinx/writers/latex.py' which defines rules for generating latex files. If you do not like default behavior of latex generator, you can change it by modifying the code.

Sometimes I was annoyed by left-aligned table which is automatically created by using csv-table directive when creating a pdf document. So, I changed some part of latex.py. Below is difference between original latex.py and bit-of modified latex.py which can generate center-aligned table by using csv-table.

( ... just added '\begin{center}' and '\end{center}' command )

617c617
<             self.body.append('\n\\begin{threeparttable}\n'
---
>             self.body.append('\n\\begin{center}\n\\begin{threeparttable}\n'
664c664
<             self.body.append('\\end{threeparttable}\n\n')
---
>             self.body.append('\\end{threeparttable}\n\\end{center}\n\n')

2011/08/21

postgres tips: enable plpgsql for implementing stored procedure

This entry is just a memo for me 8^)
If we want to implement stored procedure to any database, it is necessary to type below command.


createlang -d dbname plpgsql

2011/08/16

python tips: draw beta distribution with matplotlib



import numpy as np
import numpy as np
import pylab as pl
import scipy.special as ss

def beta(a, b, mew):
    e1 = ss.gamma(a + b)
    e2 = ss.gamma(a)
    e3 = ss.gamma(b)
    e4 = mew ** (a - 1)
    e5 = (1 - mew) ** (b - 1)
    return (e1/(e2*e3)) * e4 * e5

def plot_beta(a, b):
    Ly = []
    Lx = []
    mews = np.mgrid[0:1:100j]
    for mew in mews:
        Lx.append(mew)
        Ly.append(beta(a, b, mew))
    pl.plot(Lx, Ly, label="a=%f, b=%f" %(a,b))

def main():
    plot_beta(0.1, 0.1)
    plot_beta(1, 1)
    plot_beta(2, 3)
    plot_beta(8, 4)
    pl.xlim(0.0, 1.0)
    pl.ylim(0.0, 3.0)
    pl.legend()
    pl.show()

if __name__ == "__main__":
    main()

2011/08/13

postgres tips: calculate degree with stored procedure

-- User-Defined-Function for calculate degree
-- ------------------------------------------

-- This function calculates cos from vector(0,1)

-- .. code-block:: sql
--    :linenos:

CREATE OR REPLACE FUNCTION GET_COS
    (v2_x FLOAT, v2_y FLOAT)
RETURNS FLOAT AS
$$
DECLARE
    v1_x FLOAT;
    v1_y FLOAT;
    v1_v2 FLOAT;
    length_v1 FLOAT;
    length_v2 FLOAT;
    cos FLOAT;
BEGIN
    v1_x := 0.;
    v1_y := 1.;
    v1_v2 := (v1_x * v2_x) + (v1_y * v2_y);
    length_v1 := sqrt(power(v1_x,2) + power(v1_y,2));
    length_v2 := sqrt(power(v2_x,2) + power(v2_y,2));
    cos := v1_v2 / (length_v1 * length_v2);
    RETURN cos;
END;
$$ language plpgsql;

-- This function calculates sin from vector(0,1)

-- .. code-block:: sql
--    :linenos:

CREATE OR REPLACE FUNCTION GET_SIN
    (v2_x FLOAT, v2_y FLOAT)
RETURNS FLOAT AS
$$
DECLARE
    v1_x FLOAT;
    v1_y FLOAT;
    det FLOAT;
    length_v1 FLOAT;
    length_v2 FLOAT;
    sin FLOAT;
BEGIN
    v1_x := 0.;
    v1_y := 1.;
    det := (v1_x * v2_y) - (v1_y * v2_x);
    length_v1 := sqrt(power(v1_x,2) + power(v1_y,2));
    length_v2 := sqrt(power(v2_x,2) + power(v2_y,2));
    sin := det / (length_v1 * length_v2);
    RETURN sin;
END;
$$ language plpgsql;

-- This function calculates degree from vector(0,1)

-- .. code-block:: sql
--    :linenos:

CREATE OR REPLACE FUNCTION GET_DEGREE
    (x FLOAT, y FLOAT)
RETURNS FLOAT AS
$$
DECLARE
    sin FLOAT;
    cos FLOAT;
    degree FLOAT;
BEGIN
    sin := GET_SIN(x, y);
    cos := GET_COS(x, y);
    IF sin >= 0 AND cos >= 0 THEN
        degree := degrees(acos(cos));
    ELSEIF sin >= 0 AND cos < 0 THEN
        degree := degrees(acos(cos));
    ELSEIF sin < 0 AND cos < 0 THEN
        degree := 180. - degrees(asin(sin));
    ELSEIF sin < 0 AND cos >= 0 THEN
        degree := 360. + degrees(asin(sin));
    END IF;
    RETURN degree;
END;
$$ language plpgsql;

memo for my low-memory brain: calculate intersection from two lines in 2-D.

This is my memo for basic geometry-formula.
Now, I want to calculate intersection of two lines(Line1 and Line2).

Line1: passes point (x1=0, y1=9) and (x2=2, y2=5).
Line2: passes point (x3=1, y3=1) and (x4=3, y4=0).

Firstly, we can express these lines as following:
Line1:
Line2:

Secondly, we can get intersection (x,y) by solving below linear algebra:










Finally, using inverse matrix, we can easily calculate intersection:



sphinx tips: how to easily write a document for several scripts?

Today, I explain how to write a sphinx document for several scripts in an easy way. Assume that you are now writing postgres scripts and need to write document for them. Now, you have two postgres scripts named sample{1,2}.sql and these scripts are written like below.

-- Sample1.sql
-- -----------

-- This SQL does something!!
-- A definition of sample_table shown below.

-- =============== =========== ============
-- Column Name     Type        Description
-- =============== =========== ============
-- foo             TEXT        foo?
-- bar             TEXT        bar?
-- baz             FLOAT       baz?
-- =============== =========== ============

-- :NOTE: just return 10 records
-- :TODO: just return 11 records

-- .. code-block:: sql
--    :linenos:

SELECT
    *
FROM
    sample_table
LIMIT 10;


-- Sample2.sql
-- -----------

-- This SQL extract data from columns named foo, bar...

-- :NOTE: just return 10 records
-- :TODO: just return 11 records

-- .. code-block:: sql
--    :linenos:

SELECT
    foo,
    bar
FROM
    sample_table
LIMIT 11;

As you can see above, there are rst formatted comments in sql scripts. If you write this kind of comments in sql scripts, you can easily convert them to html/latex-styled pdf! Below shell scripts can convert above sql scripts into one rst document.

#!/bin/sh
# convert_sql2rst.sh

output_rst="sample.rst"

if [ -e ${output_rst} ]; then
    rm ${output_rst}
fi

echo "=======================" >> ${output_rst}
echo "This is sample chapter!" >> ${output_rst}
echo "=======================" >> ${output_rst}
echo "" >> ${output_rst}

for sql_file in `ls *.sql`
do
    echo "converting ${sql_file} to rst-formatted document..."
    sed ${sql_file} -e 's/^/    /g' | \
    sed -e 's/^    -- //g' >> ${output_rst}
    echo "" >> ${output_rst}
    echo "" >> ${output_rst}
done

Now, put all of above scripts into same sphinx-root directory and edit your index.rst for including ${output_rst}. Next, do this:

yaboo@maniac:~/Projects/SqlProject$ sh convert_sql2rst.sh 
converting sample.sql to rst-formatted document...
converting sample2.sql to rst-formatted document...
yaboo@maniac:~/Projects/SqlProject$ make html
sphinx-build -b html -d _build/doctrees   . _build/html
Making output directory...
Running Sphinx v1.0.7
loading pickled environment... not yet created
building [html]: targets for 2 source files that are out of date
updating environment: 2 added, 0 changed, 0 removed
reading sources... [100%] sample                                                
looking for now-outdated files... none found
pickling environment... done
checking consistency... done
preparing documents... done
writing output... [100%] sample                                                 
writing additional files... genindex search
copying static files... done
dumping search index... done
dumping object inventory... done
build succeeded.

Build finished. The HTML pages are in _build/html.

Finally, you can get document like this.


2011/08/11

python tips: draw poisson pdf graph with matplotlib




this is a code for drawing a graph of poisson pdf with matplotlib.

#!/usr/bin/env python                                                           
#coding: utf-8                                                                  
                                                                                
import pylab as pl                                                              
import numpy as np                                                              
                                                                                
def get_factorial(n):                                                           
    if n == 0:                                                                  
        return 1                                                                
    else:                                                                       
        return n * get_factorial(n-1)                                           
                                                                                
def get_probability(p, n, r):                                                   
    mew = float(n) * p                                                          
    denom = (mew ** r) * np.exp(-1 * mew)                                       
    molec = get_factorial(r)                                                    
                                                                                
    return denom/float(molec)                                                   
                                                                                
def plot_poisson_distrib(p, n, lt, lab):                                        
    xl = [nr for nr in range(0, 20, 1)]                                         
    yl = [get_probability(p, n, nr) for nr in range(0, 20, 1)]                  
    pl.plot(xl, yl, lt, label=lab)                                              
                                                                                
def main():                                                                     
    p = 0.02                                                                    
                                                                                
    mew = 1.0                                                                   
    plot_poisson_distrib(p, (mew / p), 'b-', 'P(%f,%f)' %(mew,p))               
                                                                                
    mew = 2.5                                                                   
    plot_poisson_distrib(p, (mew / p), 'r-', 'P(%f,%f)' %(mew,p))               
                                                                                
    mew = 5.0                                                                   
    plot_poisson_distrib(p, (mew / p), 'g-', 'P(%f,%f)' %(mew,p))               
                                                                                
    pl.ylabel('p(x)')                                                           
    pl.xlabel('x')                                                              
    pl.legend()                                                                 
    pl.show()                                                                   
                                                                                
if __name__ == "__main__":                                                      
    main()

and output of above code is:


python tips: draw binary pdf graph with matplotlib



this is a code for drawing a graph of binary probability distribution with matplotlib.

#!/usr/bin/env python                                                           
#coding: utf-8                                                                  
                                                                                
import pylab as pl                                                              
                                                                                
def combination(n, r):                                                          
    if (r == 0) or (n == r):                                                    
        return 1.0                                                              
                                                                                
    denom = reduce(lambda x, y: x*y, [i for i in range(1, n+1)])                
    mol_l = reduce(lambda x, y: x*y, [i for i in range(1, n-r+1)])              
    mol_r = reduce(lambda x, y: x*y, [i for i in range(1, r+1)])                
    return float(denom / (mol_l * mol_r))                                       
                                                                                
def get_probability(p, n, r):                                                   
    q = 1 - p                                                                   
    return combination(n, r) * (p ** r) * (q ** (n-r))                          
                                                                                
def plot_bin_distrib(p, n, lt, lab):                                            
    xl = [nr for nr in range(0, n+1, 1)]                                        
    yl = [get_probability(p, n, nr) for nr in range(0, n+1, 1)]                 
    pl.plot(xl, yl, lt, label=lab)                                              
                                                                                
def main():                                                                     
    p = 1.0/3.0                                                                 
    n = 10                                                                      
    plot_bin_distrib(p, n, 'b-', 'Bin(%s,%f)' %(n,p))                           
    n = 20                                                                      
    plot_bin_distrib(p, n, 'r-', 'Bin(%s,%f)' %(n,p))                           
    n = 30                                                                      
    plot_bin_distrib(p, n, 'g-', 'Bin(%s,%f)' %(n,p))                           
    n = 40                                                                      
    plot_bin_distrib(p, n, 'y-', 'Bin(%s,%f)' %(n,p))                           
                                                                                
    pl.ylabel('p(x)')                                                           
    pl.xlabel('x')                                                              
    pl.legend()                                                                 
    pl.show()                                                                   
                                                                                
if __name__ == "__main__":                                                      
    main()

and here is output from above code.


2011/08/10

python tips: use of chain generator

The book titled "Expert Python Programming" introduces pipeline of generators.
This concept is very useful for dividing loop codes to small parts.
Below is my example code that prints digit pyramid.

def change_value():
    for step in range(1, 10):
        yield step

def create_box(steps):
    for step in steps:
        yield (' ').join( str(step) for i in range(2 * step - 1) )

def create_pyramid(height):
    boxes = create_box(change_value())
    for step, box in enumerate(boxes):
        if step == height:
            break
        else:
            print ('').join(' ' for i in range((height - step)*2)) + box

Result of above code is ...

>>> create_pyramid(9)
                  1
                2 2 2
              3 3 3 3 3
            4 4 4 4 4 4 4
          5 5 5 5 5 5 5 5 5
        6 6 6 6 6 6 6 6 6 6 6
      7 7 7 7 7 7 7 7 7 7 7 7 7
    8 8 8 8 8 8 8 8 8 8 8 8 8 8 8
  9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9 9

2011/08/07

postgres tips: stored procedure for calculating distance on the earth

CREATE FUNCTION GET_DISTANCE
    (alat FLOAT, alon FLOAT, lat FLOAT, lon FLOAT)
RETURNS FLOAT AS
$$
DECLARE
    radius_earth FLOAT;
    radian_lat FLOAT;
    radian_lon FLOAT;
    distance_v FLOAT;
    distance_h FLOAT;
    distance FLOAT;
BEGIN
    -- Insert earth radius
    SELECT INTO radius_earth 6378.137;

    -- Calculate difference between lat and alat
    SELECT INTO radian_lat radians(lat - alat);

    -- Calculate difference between lon and alon
    SELECT INTO radian_lon radians(lon - alon);

    -- Calculate vertical distance
    SELECT INTO distance_v (radius_earth * radian_lat);

    -- Calculate horizontal distance
    SELECT INTO distance_h (cos(radians(alat)) * radius_earth * radian_lon);

    -- Calculate distance(km) and convert it to distance(meter)
    SELECT INTO distance sqrt(pow(distance_h,2) + pow(distance_v,2)) * 1000;

    -- Returns distance
    RETURN DISTANCE;
END;
$$ language plpgsql;


> createlang plpgsql mytestdb
> psql -d mytestdb
mytestdb=# CREATE FUNCTION GET_DISTANCE
mytestdb-#     (alat FLOAT, alon FLOAT, lat FLOAT, lon FLOAT)
mytestdb-# RETURNS FLOAT AS
mytestdb-# $$
mytestdb$# DECLARE
mytestdb$#     radius_earth FLOAT;
mytestdb$#     radian_lat FLOAT;
mytestdb$#     radian_lon FLOAT;
mytestdb$#     distance_v FLOAT;
mytestdb$#     distance_h FLOAT;
mytestdb$#     distance FLOAT;
mytestdb$# BEGIN
mytestdb$#     -- Insert earth radius
mytestdb$#     SELECT INTO radius_earth 6378.137;
mytestdb$#
mytestdb$#     -- Calculate difference between lat and alat
mytestdb$#     SELECT INTO radian_lat radians(lat - alat);
mytestdb$#
mytestdb$#     -- Calculate difference between lon and alon
mytestdb$#     SELECT INTO radian_lon radians(lon - alon);
mytestdb$#
mytestdb$#     -- Calculate vertical distance
mytestdb$#     SELECT INTO distance_v (radius_earth * radian_lat);
mytestdb$#
mytestdb$#     -- Calculate horizontal distance
mytestdb$#     SELECT INTO distance_h (cos(radians(alat)) * radius_earth * radian_lon);
mytestdb$#
mytestdb$#     -- Calculate distance(km) and convert it to distance(meter)
mytestdb$#     SELECT INTO distance sqrt(pow(distance_h,2) + pow(distance_v,2)) * 1000;
mytestdb$#
mytestdb$#     -- Returns distance
mytestdb$#     RETURN DISTANCE;
mytestdb$# END;
mytestdb$# $$ language plpgsql;
CREATE FUNCTION
mytestdb=# select GET_DISTANCE(34.701909, 135.4949770, 35.681382, 139.766084);
   get_distance
------------------
 405807.810663345
(1 行)

100