text:
""" matrix based distance metrics, and related coordinate transforms

functions to compute distance matrices row by row from abundance matrices,
typically samples (rows) vs. species/OTU's (cols)

DISTANCE FUNCTIONS
For distance functions, the API resembles the following (but see function
docstring for specifics):
    * comparisons are between rows (samples)
    * input: 2D numpy array.  Limited support for non-2D arrays if
    strict==False
    * output: numpy 2D array float ('d') type.  shape (inputrows, inputrows)
    for sane input data
    * two rows of all zeros *typically* returns 0 distance between them
    * negative values are only allowed for some distance metrics,
    in these cases if strict==True, negative input values return a ValueError,
    and if strict==False, errors or misleading return values may result
    * functions prefaced with "binary" consider only presense/absense in
    input data (qualitative rather than quantitative)

TRANSFORM FUNCTIONS
* For transform functions, very little error checking exists.  0/0 evals
in transform fomulas will throw errors, and negative data will return
spurious results or throw errors
* The transform functions are as described in
    Legendre, P. and E. Gallagher. 2001.  Ecologically meaningful
    transformations for ordination of species data.  Oecologia: 129: 271-280.
These and allow the use
of ordination methods such as PCA and RDA, which are Euclidean-based,
for the analysis of community data, while circumventing the problems associated
with the Euclidean distance. The matrix that is returned still has samples as
rows and species as columns, but the values are transformed so that when
programs such as PCA calculate euclidean distances on the matrix, chord,
chisquare, 'species profile', or hellinger distances will result.

EXAMPLE USAGE:
    >from distance_transform import dist_euclidean
    >from numpy import array

    >abundance_data = array([[1, 3],
                            [5, 2],
                            [0.1, 22]],'d')

    >dists = dist_euclidean(abundance_data)

    >print dists

    array([[  0.        ,   4.12310563,  19.02130385],
           [  4.12310563,   0.        ,  20.5915031 ],
           [ 19.02130385,  20.5915031 ,   0.        ]])

"""
from __future__ import division
import numpy
from numpy import (array, zeros, logical_and, logical_or, logical_xor, where,
    mean, std, argsort, take, ravel, logical_not, shape, sqrt, abs,
    sum, square, asmatrix, asarray, multiply, min, rank, any, all, isfinite,
    nonzero, nan_to_num, geterr, seterr, isnan)
# any, all from numpy override built in any, all, preventing:
# ValueError: The truth value of an array with more than one element is
# ambiguous. Use a.any() or a.all()

from numpy.linalg import norm

__author__ = "Justin Kuczynski"
__copyright__ = "Copyright 2007-2012, The Cogent Project"
__credits__ = ["Rob Knight", "Micah Hamady", "Justin Kuczynski",
                    "Zongzhi Liu", "Catherine Lozupone",
                    "Antonio Gonzalez Pena", "Greg Caporaso"]
__license__ = "GPL"
__version__ = "1.5.3"
__maintainer__ = "Justin Kuczynski"
__email__ = "justinak@gmail.com"
__status__ = "Prototype"

def _rankdata(a):
    """ Ranks the data in a, dealing with ties appropritely.  First ravels
    a.  Adapted from Gary Perlman's |Stat ranksort.
    private helper function

    Returns: array of length equal to a, containing rank scores
    """
    a = ravel(a)
    n = len(a)
    ivec = argsort(a)
    svec = take(a, ivec)
    sumranks = dupcount = 0
    newarray = zeros(n,'d')
    for i in range(n):
        sumranks = sumranks + i
        dupcount = dupcount + 1
        if i==n-1 or svec[i] <> svec[i+1]:
            averank = sumranks / float(dupcount) + 1
            for j in range(i-dupcount+1,i+1):
                newarray[ivec[j]] = averank
                sumranks = dupcount = 0
    return newarray

def trans_chord(m):
    """perform a chord distance transformation on the rows of m

    transforms m to m' so that the euclidean dist between the rows of m' equals
    the chord dist between the rows of m.
    Ref:
    Legendre, P. and E. Gallagher. 2001.  Ecologically meaningful
    transformations for ordination of species data.  Oecologia: 129: 271-280.
    """
    m = asmatrix(m)
    row_norms = sqrt(sum(square(m), axis=1))
    result = m / row_norms
    return result

def trans_chisq(m):
    """perform a chi squared distance transformation on the rows of m

    transforms m to m' so that the euclidean dist between the rows of m' equals
    the chi squared dist between the rows of m.
    Ref:
    Legendre, P. and E. Gallagher. 2001.  Ecologically meaningful
    transformations for ordination of species data.  Oecologia: 129: 271-280.
    """
    m = asmatrix(m)
    grand_sum, row_sums, col_sums = m.sum(), m.sum(1), m.sum(0)
    result = m * sqrt(grand_sum)
    result /= row_sums
    result /= sqrt(col_sums)
    return result

def trans_specprof(m):
    """perform a species profile distance transformation on the rows of m

    transforms m to m' so that the euclidean dist between the rows of m' equals
    the species profile dist between the rows of m.
    Ref:
    Legendre, P. and E. Gallagher. 2001.  Ecologically meaningful
    transformations for ordination of species data.  Oecologia: 129: 271-280.
    """
    m = asmatrix(m)
    row_sums = sum(m, axis=1)
    result = m / row_sums
    return result

def trans_hellinger(m):
    """perform a hellinger distance transformation on the rows of m

    transforms m to m' so that the euclidean dist between the rows of m' equals
    the hellinger dist between the rows of m.
    Ref:
    Legendre, P. and E. Gallagher. 2001.  Ecologically meaningful
    transformations for ordination of species data.  Oecologia: 129: 271-280.
    """
    m = asmatrix(m)
    row_sums = sum(m, axis=1)
    result = sqrt(m / row_sums)
    return result

def dist_bray_curtis(datamtx, strict=True):
    """ returns bray curtis distance (normalized manhattan distance) btw rows

    dist(a,b) = manhattan distance / sum on i( (a_i + b_i) )

    see for example:
    Faith et al. 1987
    Compositional dissimilarity as a robust measure of ecological distance
    Vegitatio

    * comparisons are between rows (samples)
    * input: 2D numpy array.  Limited support for non-2D arrays if
    strict==False
    * output: numpy 2D array float ('d') type.  shape (inputrows, inputrows)
    for sane input data
    * two rows of all zeros returns 0 distance between them
    * if strict==True, raises ValueError if any of the input data is negative,
    not finite, or if the input data is not a rank 2 array (a matrix).
    * if strict==False, assumes input data is a matrix with nonnegative
    entries.  If rank of input data is < 2, returns an empty 2d array (shape:
    (0, 0) ).  If 0 rows or 0 colunms, also returns an empty 2d array.
    """
    if strict:
        if not all(isfinite(datamtx)):
            raise ValueError("non finite number in input matrix")
        if any(datamtx<0.0):
            raise ValueError("negative value in input matrix")
        if rank(datamtx) != 2:
            raise ValueError("input matrix not 2D")
        numrows, numcols = shape(datamtx)
    else:
        try:
            numrows, numcols = shape(datamtx)
        except ValueError:
            return zeros((0,0),'d')

    if numrows == 0 or numcols == 0:
        return zeros((0,0),'d')

    dists = zeros((numrows,numrows),'d')
    for i in range(numrows):
        r1 = datamtx[i,:]
        for j in range(i):
            r2 = datamtx[j,:]
            abs_v = float(sum(abs(r1 - r2)))
            v = sum(r1 + r2)
            cur_d = 0.0
            if v > 0:
                cur_d = abs_v/v

            dists[i][j] = dists[j][i] = cur_d
    return dists

dist_bray_curtis_faith = dist_bray_curtis

def dist_bray_curtis_magurran(datamtx, strict=True):
    """ returns bray curtis distance (quantitative sorensen) btw rows

    dist(a,b) = 2*sum on i( min( a_i, b_i)) / sum on i( (a_i + b_i) )

    see for example:
    Magurran 2004
    Bray 1957

    * comparisons are between rows (samples)
    * input: 2D numpy array.  Limited support for non-2D arrays if
    strict==False
    * output: numpy 2D array float ('d') type.  shape (inputrows, inputrows)
    for sane input data
    * two rows of all zeros returns 0 distance between them
    * if strict==True, raises ValueError if any of the input data is negative,
    not finite, or if the input data is not a rank 2 array (a matrix).
    * if strict==False, assumes input data is a matrix with nonnegative
    entries.  If rank of input data is < 2, returns an empty 2d array (shape:
    (0, 0) ).  If 0 rows or 0 colunms, also returns an empty 2d array.
    """
    if strict:
        if not numpy.all(numpy.isfinite(datamtx)):
            raise ValueError("non finite number in input matrix")
        if numpy.any(datamtx<0.0):
            raise ValueError("negative value in input matrix")
        if numpy.rank(datamtx) != 2:
            raise ValueError("input matrix not 2D")
        numrows, numcols = numpy.shape(datamtx)
    else:
        try:
            numrows, numcols = numpy.shape(datamtx)
        except ValueError:
            return numpy.zeros((0,0),'d')

    if numrows == 0 or numcols == 0:
        return numpy.zeros((0,0),'d')

    dists = numpy.zeros((numrows,numrows),'d')
    for i in range(numrows):
        r1 = datamtx[i,:]
        r1sum = r1.sum()
        for j in range(i):
            r2 = datamtx[j,:]
            r2sum = r2.sum()
            minvals = numpy.min([r1,r2],axis=0)

            if (r1sum + r2sum) == 0:
                dists[i][j] = dists[j][i] = 0.0
            else:
                dissim = 1 - ( (2*minvals.sum()) / (r1sum + r2sum) )
                dists[i][j] = dists[j][i] = dissim
    return dists

def dist_canberra(datamtx, strict=True):
    """returns a row-row canberra dist matrix

    see for example:
    Faith et al. 1987
    Compositional dissimilarity as a robust measure of ecological distance
    Vegitatio

    * comparisons are between rows (samples)
    * input: 2D numpy array.  Limited support for non-2D arrays if
    strict==False
    * output: numpy 2D array float ('d') type.  shape (inputrows, inputrows)
    for sane input data
    * two rows of all zeros returns 0 distance between them
    * if strict==True, raises ValueError if any of the input data is negative,
    not finite, or if the input data is not a rank 2 array (a matrix).
    * if strict==False, assumes input data is a matrix with nonnegative
    entries.  If rank of input data is < 2, returns an empty 2d array (shape:
    (0, 0) ).  If 0 rows or 0 colunms, also returns an empty 2d array.
    * chisq dist normalizes by column sums - empty columns (all zeros) are
    ignored here
    """
    if strict:
        if not all(isfinite(datamtx)):
            raise ValueError("non finite number in input matrix")
        if any(datamtx<0.0):
            raise ValueError("negative value in input matrix")
        if rank(datamtx) != 2:
            raise ValueError("input matrix not 2D")
        numrows, numcols = shape(datamtx)
    else:
        try:
            numrows, numcols = shape(datamtx)
        except ValueError:
            return zeros((0,0),'d')

    oldstate = seterr(invalid='ignore',divide='ignore')
    if numrows == 0 or numcols == 0:
        return zeros((0,0),'d')
    dists = zeros((numrows,numrows),'d')
    for i in range(numrows):
        r1 = datamtx[i]
        for j in range(i):
            r2 = datamtx[j]
            dist = 0.0
            net = abs( r1 - r2 ) / (r1 + r2)

            net = nan_to_num(net)
            num_nonzeros = nonzero(net)[0].size
            dists[i,j] = dists[j,i] = nan_to_num(net.sum()/num_nonzeros)

    seterr(**oldstate)
    return dists

def dist_chisq(datamtx, strict=True):
    """returns a row-row chisq dist matrix

    see for example:
    Faith et al. 1987
    Compositional dissimilarity as a robust measure of ecological distance
    Vegitatio

    * comparisons are between rows (samples)
    * input: 2D numpy array.  Limited support for non-2D arrays if
    strict==False
    * output: numpy 2D array float ('d') type.  shape (inputrows, inputrows)
    for sane input data
    * two rows of all zeros returns 0 distance between them
    * an all zero row compared with a not all zero row returns a distance of 1
    * if strict==True, raises ValueError if any of the input data is negative,
    not finite, or if the input data is not a rank 2 array (a matrix).
    * if strict==False, assumes input data is a matrix with nonnegative
    entries.  If rank of input data is < 2, returns an empty 2d array (shape:
    (0, 0) ).  If 0 rows or 0 colunms, also returns an empty 2d array.
    * chisq dist normalizes by column sums - empty columns (all zeros) are
    ignored here
    """
    if strict:
        if not all(isfinite(datamtx)):
            raise ValueError("non finite number in input matrix")
        if any(datamtx<0.0):
            raise ValueError("negative value in input matrix")
        if rank(datamtx) != 2:
            raise ValueError("input matrix not 2D")
        numrows, numcols = shape(datamtx)
    else:
        try:
            numrows, numcols = shape(datamtx)
        except ValueError:
            return zeros((0,0),'d')

    if numrows == 0 or numcols == 0:
        return zeros((0,0),'d')
    dists = zeros((numrows,numrows),'d')
    sqrt_grand_sum = sqrt(sum(datamtx))
    rowsums, colsums = sum(datamtx, axis=1), sum(datamtx, axis=0)
    if not colsums.all():
        for i in range(len(colsums)):
            if colsums[i] == 0.0:
                colsums[i] = 1.0
    for i in range(numrows):
        r1 = datamtx[i]
        r1sum = rowsums[i]
        for j in range(i):
            r2 = datamtx[j]
            r2sum = rowsums[j]
            if r1sum == 0.0 or r2sum == 0.0:
                if r1sum == 0.0 and r2sum == 0.0:
                    dist = 0.0
                else: dist = 1.0
            else:
                dist = sqrt_grand_sum *\
                    sqrt(sum( multiply((1./colsums) ,
                    square(r1/r1sum - r2/r2sum)) ))
            dists[i,j] = dists[j,i] = dist
    return dists

def dist_chord(datamtx, strict=True):
    """returns a row-row chord dist matrix

    attributed to Orloci (with accent).  see Legendre 2001,
    ecologically meaningful...

    * comparisons are between rows (samples)
    * input: 2D numpy array.  Limited support for non-2D arrays if
    strict==False
    * output: numpy 2D array float ('d') type.  shape (inputrows, inputrows)
    for sane input data
    * two rows of all zeros returns 0 distance between them
    * an all zero row compared with a not all zero row returns a distance of 1
    * if strict==True, raises ValueError if any of the input data is
    not finite, or if the input data is not a rank 2 array (a matrix).
    * if strict==False, assumes input data is a 2d matrix.
    If rank of input data is < 2, returns an empty 2d array (shape:
    (0, 0) ).  If 0 rows or 0 colunms, also returns an empty 2d array.
    """
    if strict:
        if not all(isfinite(datamtx)):
            raise ValueError("non finite number in input matrix")
        if rank(datamtx) != 2:
            raise ValueError("input matrix not 2D")
        numrows, numcols = shape(datamtx)
    else:
        try:
            numrows, numcols = shape(datamtx)
        except ValueError:
            return zeros((0,0),'d')

    if numrows == 0 or numcols == 0:
        return zeros((0,0),'d')
    dists = zeros((numrows,numrows),'d')
    for i in range(numrows):
        r1 = datamtx[i] # cache here
        r1norm = norm(r1)
        for j in range(i):
            r2 = datamtx[j]
            r2norm = norm(r2)
            if r1norm == 0.0 or r2norm == 0.0:
                if r1norm == 0.0 and r2norm == 0.0:
                    dist = 0.0
                else: dist = 1.0
            else:
                dist = norm(r1/r1norm - r2/r2norm)
            dists[i,j] = dists[j,i] = dist

    return dists

def dist_euclidean(datamtx, strict=True):
    """returns a row by row euclidean dist matrix

    returns the euclidean norm of row1 - row2 for all rows in datamtx
    * comparisons are between rows (samples)
    * input: 2D numpy array.  Limited support for non-2D arrays if
    strict==False
    * output: numpy 2D array float ('d') type.  shape (inputrows, inputrows)
    for sane input data
    * if strict==True, raises ValueError if any of the input data is
    not finite, or if the input data is not a rank 2 array (a matrix).
    * if strict==False, assumes input data is a 2d matrix.
    If rank of input data is < 2, returns an empty 2d array (shape:
    (0, 0) ).  If 0 rows or 0 colunms, also returns an empty 2d array.
    """
    datamtx = asarray(datamtx, 'd')
    if strict:
        if not all(isfinite(datamtx)):
            raise ValueError("non finite number in input matrix")
        if rank(datamtx) != 2:
            raise ValueError("input matrix not 2D")
        numrows, numcols = shape(datamtx)
    else:
        try:
            numrows, numcols = shape(datamtx)
        except ValueError:
            return zeros((0,0),'d')

    if numrows == 0 or numcols == 0:
        return zeros((0,0),'d')
    dists = zeros((numrows,numrows),'d')
    for r in range(numrows):
        for c in range(r):
            dist = norm(datamtx[r] - datamtx[c])
            if isnan(dist):
                raise RuntimeError('ERROR: overflow when computing euclidean distance')
            dists[r,c] = dists[c,r] = dist

    return dists

def dist_gower(datamtx, strict=True):
    """returns a row-row gower dist matrix

    see for example, Faith et al., 1987

    * note that the comparison between any two rows is dependent on the entire
    data matrix, d_ij is a fn of all of datamtx, not just i,j
    * comparisons are between rows (samples)
    * any column containing identical data for all rows is ignored (this
    prevents a 0/0 error in the formula for gower distance
    * input: 2D numpy array.  Limited support for non-2D arrays if
    strict==False
    * output: numpy 2D array float ('d') type.  shape (inputrows, inputrows)
    for sane input data
    * two rows of all zeros returns 0 distance between them
    * if strict==True, raises ValueError if any of the input data is
    not finite, or if the input data is not a rank 2 array (a matrix).
    * if strict==False, assumes input data is a 2d matrix.
    If rank of input data is < 2, returns an empty 2d array (shape:
    (0, 0) ).  If 0 rows or 0 colunms, also returns an empty 2d array.
    """
    if strict:
        if not all(isfinite(datamtx)):
            raise ValueError("non finite number in input matrix")
        if rank(datamtx) != 2:
            raise ValueError("input matrix not 2D")
        numrows, numcols = shape(datamtx)
    else:
        try:
            numrows, numcols = shape(datamtx)
        except ValueError:
            return zeros((0,0),'d')

    if numrows == 0 or numcols == 0:
        return zeros((0,0),'d')
    dists = zeros((numrows,numrows),'d')
    coldiffs = datamtx.max(axis=0) - datamtx.min(axis=0)
    for i in range(numcols):
        if coldiffs[i] == 0.0:
            coldiffs[i] = 1.0 # numerator will be zero anyway

    for i in range(numrows):
        r1 = datamtx[i]
        for j in range(i):
            r2 = datamtx[j]
            rowdiff = r2 - r1
            dist = sum(abs(r1 - r2) / coldiffs)
            dists[i,j] = dists[j,i] = dist

    return dists

def dist_hellinger(datamtx, strict=True):
    """returns a row-row hellinger dist matrix

    * comparisons are between rows (samples)
    * input: 2D numpy array.  Limited support for non-2D arrays if
    strict==False
    * output: numpy 2D array float ('d') type.  shape (inputrows, inputrows)
    for sane input data
    * two rows of all zeros returns 0 distance between them
    * an all zero row compared with a not all zero row returns a distance of 1
    * if strict==True, raises ValueError if any of the input data is negative,
    not finite, or if the input data is not a rank 2 array (a matrix).
    * if strict==False, assumes input data is a matrix with nonnegative
    entries.  If rank of input data is < 2, returns an empty 2d array (shape:
    (0, 0) ).  If 0 rows or 0 colunms, also returns an empty 2d array.
    """
    if strict:
        if not all(isfinite(datamtx)):
            raise ValueError("non finite number in input matrix")
        if any(datamtx<0.0):
            raise ValueError("negative value in input matrix")
        if rank(datamtx) != 2:
            raise ValueError("input matrix not 2D")
        numrows, numcols = shape(datamtx)
    else:
        try:
            numrows, numcols = shape(datamtx)
        except ValueError:
            return zeros((0,0),'d')

    if numrows == 0 or numcols == 0:
        return zeros((0,0),'d')
    dists = zeros((numrows,numrows),'d')
    for i in range(numrows):
        r1 = datamtx[i]
        r1sum = sum(r1)
        for j in range(i):
            r2 = datamtx[j]
            r2sum = sum(r2)
            if r1sum == 0.0 or r2sum == 0.0:
                if r1sum == 0.0 and r2sum == 0.0:
                    dist = 0.0
                else: dist = 1.0
            else:
                dist = norm(sqrt(r1/r1sum) - sqrt(r2/r2sum))
            dists[i,j] = dists[j,i] = dist

    return dists

def dist_kulczynski(datamtx, strict=True):
    """ calculates the kulczynski distances between rows of a matrix

    see for example Faith et al., composiitonal dissimilarity, 1987
    returns a distance of 1 between a row of zeros and a row with at least one
    nonzero element

    * comparisons are between rows (samples)
    * input: 2D numpy array.  Limited support for non-2D arrays if
    strict==False
    * output: numpy 2D array float ('d') type.  shape (inputrows, inputrows)
    for sane input data
    * two rows of all zeros returns 0 distance between them
    * an all zero row compared with a not all zero row returns a distance of 1
    * if strict==True, raises ValueError if any of the input data is negative,
    not finite, or if the input data is not a rank 2 array (a matrix).
    * if strict==False, assumes input data is a matrix with nonnegative
    entries.  If rank of input data is < 2, returns an empty 2d array (shape:
    (0, 0) ).  If 0 rows or 0 colunms, also returns an empty 2d array.
    """
    if strict:
        if not all(isfinite(datamtx)):
            raise ValueError("non finite number in input matrix")
        if any(datamtx<0.0):
            raise ValueError("negative value in input matrix")
        if rank(datamtx) != 2:
            raise ValueError("input matrix not 2D")
        numrows, numcols = shape(datamtx)
    else:
        try:
            numrows, numcols = shape(datamtx)
        except ValueError:
            return zeros((0,0),'d')

    if numrows == 0 or numcols == 0:
        return zeros((0,0),'d')
    dists = zeros((numrows,numrows),'d')
    rowsums = datamtx.sum(axis=1)
    # rowsum: the sum of elements in a row
    # cache to avoid recalculating for each pair
    for i in range(numrows):
        irowsum = rowsums[i]
        r1 = datamtx[i]
        for j in range(i):
            r2 = datamtx[j]
            jrowsum = rowsums[j]
            rowminsum = float(sum(where(r1<r2, r1,r2)))
            if (irowsum == 0.0 and jrowsum == 0.0):
                cur_d = 0.0 # => two rows of zeros
            elif (irowsum == 0.0 or jrowsum == 0.0):
                cur_d = 1.0 # one row zeros, one not all zeros
            else:
                cur_d = 1.0 - (((rowminsum/irowsum) + (rowminsum/jrowsum))/2.0)
            dists[i][j] = dists[j][i] = cur_d
    return dists

def dist_manhattan(datamtx, strict=True):
    """ returns manhattan (city block) distance between rows

    dist(a,b) = sum on i( abs(a_i - b_i) )
    negative values ok (but not tested)

    * comparisons are between rows (samples)
    * input: 2D numpy array.  Limited support for non-2D arrays if
    strict==False
    * output: numpy 2D array float ('d') type.  shape (inputrows, inputrows)
    for sane input data
    * if strict==True, raises ValueError if any of the input data is
    not finite, or if the input data is not a rank 2 array (a matrix).
    * if strict==False, assumes input data is a 2d matrix.
    If rank of input data is < 2, returns an empty 2d array (shape:
    (0, 0) ).  If 0 rows or 0 colunms, also returns an empty 2d array.
    """
    if strict:
        if not all(isfinite(datamtx)):
            raise ValueError("non finite number in input matrix")
        if rank(datamtx) != 2:
            raise ValueError("input matrix not 2D")
        numrows, numcols = shape(datamtx)
    else:
        try:
            numrows, numcols = shape(datamtx)
        except ValueError:
            return zeros((0,0),'d')

    if numrows == 0 or numcols == 0:
        return zeros((0,0),'d')
    dists = zeros((numrows,numrows),'d')
    for i in range(numrows):
        r1 = datamtx[i] # cache here
        for j in range(i):
            dists[i,j] = dists[j,i] = sum(abs(r1 - datamtx[j]))

    return dists

def dist_abund_jaccard(datamtx, strict=True):
    """Calculate abundance-based Jaccard distance between rows

    The abundance-based Jaccard index is defined in Chao et. al.,
    Ecology Lett. 8, 148 (2005), eq. 5:

    J_abd = UV / (U + V - UV), where

    U = sum of relative abundances of shared species in a
    V = sum of relative abundances of shared species in b

    The Chao-Jaccard distance is 1 - J_abd

    * comparisons are between rows (samples)
    * input: 2D numpy array.  Limited support for non-2D arrays if
    strict==False
    * output: numpy 2D array float ('d') type.  shape (inputrows, inputrows)
    for sane input data
    * two rows of all zeros returns 0 distance between them
    * an all zero row compared with a not all zero row returns a distance of 1
    * if strict==True, raises ValueError if any of the input data is negative,
    not finite, or if the input data is not a rank 2 array (a matrix).
    * if strict==False, assumes input data is a matrix with nonnegative
    entries.  If rank of input data is < 2, returns an empty 2d array (shape:
    (0, 0) ).  If 0 rows or 0 colunms, also returns an empty 2d array.
    """
    if strict:
        if not all(isfinite(datamtx)):
            raise ValueError("non finite number in input matrix")
        if any(datamtx<0.0):
            raise ValueError("negative value in input matrix")
        if rank(datamtx) != 2:
            raise ValueError("input matrix not 2D")
        numrows, numcols = shape(datamtx)
    else:
        try:
            numrows, numcols = shape(datamtx)
        except ValueError:
            return zeros((0,0),'d')

    if numrows == 0 or numcols == 0:
        return zeros((0,0),'d')
    dists = zeros((numrows,numrows),'d')

    rowsums = datamtx.sum(axis=1, dtype='float')

    for i in range(numrows):
        row1 = datamtx[i]
        N1 = rowsums[i]

        for j in range(i):
            row2 = datamtx[j]
            N2 = rowsums[j]

            if N1 == 0.0 and N2 == 0.0:
                similarity = 1.0
            elif N1 == 0.0 or N2 == 0.0:
                similarity = 0.0
            else:
                shared = logical_and(row1, row2)
                u = sum(row1[shared]) / N1
                v = sum(row2[shared]) / N2
                # Verified by graphical inspection
                if u == 0.0 and v == 0.0:
                    similarity = 0.0
                else:
                    similarity = (u * v) / (u + v - (u * v))

            dists[i][j] = dists[j][i] = 1 - similarity
    return dists

def dist_morisita_horn(datamtx, strict=True):
    """ returns morisita-horn distance between rows

    dist(a,b) = 1 - 2*sum(a_i * b_i) /( (d_a + d_b)* N_a * N_b )

    see book: magurran 2004 pg 246

    * comparisons are between rows (samples)
    * input: 2D numpy array.  Limited support for non-2D arrays if
    strict==False
    * output: numpy 2D array float ('d') type.  shape (inputrows, inputrows)
    for sane input data
    * two rows of all zeros returns 0 distance between them
    * an all zero row compared with a not all zero row returns a distance of 1
    * if strict==True, raises ValueError if any of the input data is negative,
    not finite, or if the input data is not a rank 2 array (a matrix).
    * if strict==False, assumes input data is a matrix with nonnegative
    entries.  If rank of input data is < 2, returns an empty 2d array (shape:
    (0, 0) ).  If 0 rows or 0 colunms, also returns an empty 2d array.
    """
    if strict:
        if not all(isfinite(datamtx)):
            raise ValueError("non finite number in input matrix")
        if any(datamtx<0.0):
            raise ValueError("negative value in input matrix")
        if rank(datamtx) != 2:
            raise ValueError("input matrix not 2D")
        numrows, numcols = shape(datamtx)
    else:
        try:
            numrows, numcols = shape(datamtx)
        except ValueError:
            return zeros((0,0),'d')

    if numrows == 0 or numcols == 0:
        return zeros((0,0),'d')
    dists = zeros((numrows,numrows),'d')

    rowsums = datamtx.sum(axis=1, dtype='float')
    row_ds = (datamtx**2).sum(axis=1, dtype='float') # these are d_a, etc

    for i in range(numrows):
        if row_ds[i] !=0.:
            row_ds[i] = row_ds[i] / rowsums[i]**2
    # this leaves row_ds zero if actually 0/0
    for i in range(numrows):
        row1 = datamtx[i]
        N1 = rowsums[i]
        d1 = row_ds[i]
        for j in range(i):
            row2 = datamtx[j]
            N2 = rowsums[j]
            d2 = row_ds[j]
            if N2 == 0.0 and N1==0.0:
                dist = 0.0
            elif N2 == 0.0 or N1==0.0:
                dist = 1.0
            else:
            # d's zero only if N's zero, and we already checked for that
                similarity = 2*sum(row1*row2)
                similarity = similarity / ( (d1 + d2) * N1 * N2 )
                dist = 1 - similarity
            dists[i][j] = dists[j][i] = dist
    return dists

def dist_pearson(datamtx, strict=True):
    """ Calculates pearson distance (1-r) between rows

    note that the literature sometimer refers to the pearson dissimilarity
    as (1 - r)/2 (e.g.: BC Blaxall et al. 2003: Differential Myocardial Gene
    Expression in the Development and Rescue of Murine Heart Failure)

    for pearson's r, see for example: Thirteen Ways to Look at the
    Correlation Coefficient by J rodgers, 1988

    * distance varies between 0-2, inclusive.
    * Flat rows (all elements itentical) will return a distance of 1 relative
    to any non-flat row, and a distance of zero to another flat row
    * comparisons are between rows (samples)
    * input: 2D numpy array.  Limited support for non-2D arrays if
    strict==False
    * output: numpy 2D array float ('d') type.  shape (inputrows, inputrows)
    for sane input data
    * two rows of all zeros returns 0 distance between them
    * an all zero row compared with a not all zero row returns a distance of 1
    * if strict==True, raises ValueError if any of the input data is
    not finite, or if the input data is not a rank 2 array (a matrix).
    * if strict==False, assumes input data is a 2d matrix
    If rank of input data is < 2, returns an empty 2d array (shape:
    (0, 0) ).  If 0 rows or 0 colunms, also returns an empty 2d array.
    """
    if strict:
        if not all(isfinite(datamtx)):
            raise ValueError("non finite number in input matrix")
        if rank(datamtx) != 2:
            raise ValueError("input matrix not 2D")
        numrows, numcols = shape(datamtx)
    else:
        try:
            numrows, numcols = shape(datamtx)
        except ValueError:
            return zeros((0,0),'d')

    if numrows == 0 or numcols == 0:
        return zeros((0,0),'d')

    rowmeans =  mean(datamtx, axis=1)
    rowstds =  std(datamtx, axis=1)

    dists = zeros((numrows,numrows),'d')
    n = float(numrows)

    for i in range(numrows):
        r1 = datamtx[i,:]
        r1m = rowmeans[i]
        r1dev = r1 - r1m
        for j in range(i):
            r2 = datamtx[j,:]
            r2m = rowmeans[j]
            r2dev = r2 - r2m
            top = sum(r1dev*r2dev)
            sum1 = sum(r1dev**2)
            sum2 = sum(r2dev**2)

            if (sum1 == 0.0 and sum2 == 0.0):
                r = 1.0
            elif (sum1 == 0.0 or sum2 == 0.0):
                r = 0.0
            else:
                bottom = sqrt(sum1 * sum2)
                r = top/bottom

            dists[i][j] = dists[j][i] = 1.0 - r

    return dists

def dist_soergel(datamtx, strict=True):
    """ Calculate soergel distance between rows of a matrix

    see for example Evaluation of Distance Metrics..., Fechner 2004
    dist(a,b) = sum on i( abs(a_i - b_i) ) / sum on i( max(a_i, b_i) )

    returns: a symmetric distance matrix, numrows X numrows
    * comparisons are between rows (samples)
    * input: 2D numpy array.  Limited support for non-2D arrays if
    strict==False
    * output: numpy 2D array float ('d') type.  shape (inputrows, inputrows)
    for sane input data
    * two rows of all zeros returns 0 distance between them
    * if strict==True, raises ValueError if any of the input data is negative,
    not finite, or if the input data is not a rank 2 array (a matrix).
    * if strict==False, assumes input data is a matrix with nonnegative
    entries.  If rank of input data is < 2, returns an empty 2d array (shape:
    (0, 0) ).  If 0 rows or 0 colunms, also returns an empty 2d array.
    """
    if strict:
        if not all(isfinite(datamtx)):
            raise ValueError("non finite number in input matrix")
        if any(datamtx<0.0):
            raise ValueError("negative value in input matrix")
        if rank(datamtx) != 2:
            raise ValueError("input matrix not 2D")
        numrows, numcols = shape(datamtx)
    else:
        try:
            numrows, numcols = shape(datamtx)
        except ValueError:
            return zeros((0,0),'d')

    if numrows == 0 or numcols == 0:
        return zeros((0,0),'d')
    dists = zeros((numrows,numrows),'d')
    for i in range(numrows):
        r1 = datamtx[i,:]
        for j in range(i):
            r2 = datamtx[j,:]
            top = float(sum(abs(r1 - r2)))
            bot = float(sum(where(r1>r2, r1,r2)))
            if bot <= 0.0:
                cur_d = 0.0
            else:
                cur_d = top/bot
            dists[i][j] = dists[j][i] = cur_d
    return dists

def dist_spearman_approx(datamtx, strict=True):
    """ Calculate spearman rank distance (1-r) using an approximation formula

    considers only rank order of elements in a row, averaging ties
    [19.2, 2.1, 0.03, 2.1] -> [3, 1.5, 0, 1.5]
    then performs dist(a,b) = 6 * sum(D^2) / (N*(N^2 - 1))
    where D is difference in rank of element i between row a and row b,
    N is the length of either row

    * formula fails for < 2 columns, returns a zeros matrix
    * comparisons are between rows (samples)
    * input: 2D numpy array.  Limited support for non-2D arrays if
    strict==False
    * output: numpy 2D array float ('d') type.  shape (inputrows, inputrows)
    for sane input data
    * if strict==True, raises ValueError if any of the input data is
    not finite, or if the input data is not a rank 2 array (a matrix), or if
    there are less than 2 colunms
    * if strict==False, assumes input data is a 2d matrix.
    If rank of input data is < 2, returns an empty 2d array (shape:
    (0, 0) ).  If 0 rows or 0 colunms, also returns an empty 2d array.
    """
    if strict:
        if not all(isfinite(datamtx)):
            raise ValueError("non finite number in input matrix")
        if rank(datamtx) != 2:
            raise ValueError("input matrix not 2D")
        numrows, numcols = shape(datamtx)
        if numcols < 2:
            raise ValueError("input matrix has < 2 colunms")
    else:
        try:
            numrows, numcols = shape(datamtx)
        except ValueError:
            return zeros((0,0),'d')

    if numrows == 0 or numcols == 0:
        return zeros((0,0),'d')
    dists = zeros((numrows,numrows),'d')

    if numcols < 2:
        return dists # formula fails for < 2 elements per row

    for i in range(numrows):
        r1 = datamtx[i,:]
        rank1 = _rankdata(r1)
        for j in range(i):
            r2 = datamtx[j,:]
            rank2 = _rankdata(r2)
            rankdiff = rank1 - rank2
            dsqsum = sum((rankdiff)**2)
            dist = 6*dsqsum / float(numcols*(numcols**2-1))

            dists[i][j] = dists[j][i] = dist
    return dists

def dist_specprof(datamtx, strict=True):
    """returns a row-row species profile distance matrix

    * comparisons are between rows (samples)
    * input: 2D numpy array.  Limited support for non-2D arrays if
    strict==False
    * output: numpy 2D array float ('d') type.  shape (inputrows, inputrows)
    for sane input data
    * two rows of all zeros returns 0 distance between them
    * an all zero row compared with a not all zero row returns a distance of 1
    * if strict==True, raises ValueError if any of the input data is negative,
    not finite, or if the input data is not a rank 2 array (a matrix).
    * if strict==False, assumes input data is a matrix with nonnegative
    entries.  If rank of input data is < 2, returns an empty 2d array (shape:
    (0, 0) ).  If 0 rows or 0 colunms, also returns an empty 2d array.
    """
    if strict:
        if not all(isfinite(datamtx)):
            raise ValueError("non finite number in input matrix")
        if any(datamtx<0.0):
            raise ValueError("negative value in input matrix")
        if rank(datamtx) != 2:
            raise ValueError("input matrix not 2D")
        numrows, numcols = shape(datamtx)
    else:
        try:
            numrows, numcols = shape(datamtx)
        except ValueError:
            return zeros((0,0),'d')

    if numrows == 0 or numcols == 0:
        return zeros((0,0),'d')
    dists = zeros((numrows,numrows),'d')
    for i in range(numrows):
        r1 = datamtx[i]
        r1sum = sum(r1)
        for j in range(i):
            r2 = datamtx[j]
            r2sum = sum(r2)
            if r1sum == 0.0 or r2sum == 0.0:
                if r1sum == 0.0 and r2sum == 0.0:
                    dist = 0.0
                else: dist = 1.0
            else:
                dist = norm((r1/r1sum) - (r2/r2sum))
            dists[i,j] = dists[j,i] = dist

    return dists

def binary_dist_otu_gain(otumtx):
    """ Calculates number of new OTUs observed in sample A wrt sample B

        This is an non-phylogenetic distance matrix analagous to unifrac_g.
        The number of OTUs gained in each sample is computed with respect to
        each other sample.

    """
    result = []
    for i in otumtx:
        row = []
        for j in otumtx:
            gain = 0
            for i_val, j_val in zip(i, j):
                if i_val > 0 and j_val == 0:
                    gain += 1
            row.append(gain)
        result.append(row)
    return array(result)

def binary_dist_chisq(datamtx, strict=True):
    """Calculates binary chi-square dist between rows, returns dist matrix.

    converts input array to bool, then uses dist_chisq
    """
    datamtx = datamtx.astype(bool)
    datamtx = datamtx.astype(float)
    return dist_chisq(datamtx, strict=True)

def binary_dist_chord(datamtx, strict=True):
    """Calculates binary chord dist between rows, returns dist matrix.

    converts input array to bool, then uses dist_chisq
    for binary data, this is identical to a binary hellinger distance
    """
    datamtx = datamtx.astype(bool)
    datamtx = datamtx.astype(float)
    return dist_chord(datamtx, strict=True)

def binary_dist_sorensen_dice(datamtx, strict=True):
    """Calculates Sorensen-Dice distance btw rows, returning distance matrix.

    Note: Treats array as bool. This distance = 1 - dice's coincidence index
    see Measures of the Amount of Ecologic Association Between Species
    Author(s): Lee R. Dice, 1945
    The 'o' in sorensen should be a non-ascii char, but isn't here for ease
    of use
    this is identical to a binary bray-curtis distance, as well as the
    binary whittaker distance metric.

    a = num 1's in a
    b = num 1's in b
    c = num that are 1's in both a and b
    Dice dist = 1 - (2*c)/(a + b).
    also known as whittaker:
    whittaker = (a + b - c)/( 0.5*(a+b) ) - 1

    * comparisons are between rows (samples)
    * input: 2D numpy array.  Limited support for non-2D arrays if
    strict==False
    * output: numpy 2D array float ('d') type.  shape (inputrows, inputrows)
    for sane input data
    * two rows of all zeros returns 0 distance between them
    * negative input values are not allowed - will return nonsensical results
    and/or throw errors
    """
    datamtx = datamtx.astype(bool)
    datamtx = datamtx.astype(float)
    if strict:
        if not all(isfinite(datamtx)):
            raise ValueError("non finite number in input matrix")
        if any(datamtx<0.0):
            raise ValueError("negative value in input matrix")
        if rank(datamtx) != 2:
            raise ValueError("input matrix not 2D")
        numrows, numcols = shape(datamtx)
    else:
        try:
            numrows, numcols = shape(datamtx)
        except ValueError:
            return zeros((0,0),'d')

    if numrows == 0 or numcols == 0:
        return zeros((0,0),'d')
    dists = zeros((numrows,numrows),'d')
    rowsums = datamtx.sum(axis=1)

    for i in range(numrows):
        row1 = datamtx[i]
        for j in range(i):
            row2 = datamtx[j]
            bottom = float(rowsums[i] + rowsums[j])
            cur_d = 0.0
            if bottom:
                cur_d = 1-(2*logical_and(row1,row2).sum()/bottom)
            dists[i][j] = dists[j][i] = cur_d
    return dists

def binary_dist_euclidean(datamtx, strict=True):
    """Calculates binary euclidean distance between rows, returns dist matrix.

    converts input array to bool, then uses dist_euclidean
    """
    datamtx = datamtx.astype(bool)
    datamtx = datamtx.astype(float)
    return dist_euclidean(datamtx, strict=True)

def binary_dist_hamming(datamtx, strict=True):
    """Calculates hamming distance btw rows, returning distance matrix.

    Note: Treats array as bool.
    see for example wikipedia hamming_distance, 20 jan 2008

    hamming is identical to binary manhattan distance

    Binary hamming:
    a = num 1's in a
    b = num 1's in b
    c = num that are 1's in both a and b
    hamm = a + b - 2c

    * comparisons are between rows (samples)
    * input: 2D numpy array.  Limited support for non-2D arrays if
    strict==False
    * output: numpy 2D array float ('d') type.  shape (inputrows, inputrows)
    for sane input data
    * two rows of all zeros returns 0 distance between them
    * if strict==True, raises ValueError if any of the input data is negative,
    not finite, or if the input data is not a rank 2 array (a matrix).
    * if strict==False, assumes input data is a matrix with nonnegative
    entries.  If rank of input data is < 2, returns an empty 2d array (shape:
    (0, 0) ).  If 0 rows or 0 colunms, also returns an empty 2d array.
    """
    datamtx = datamtx.astype(bool)
    datamtx = datamtx.astype(float)
    if strict:
        if not all(isfinite(datamtx)):
            raise ValueError("non finite number in input matrix")
        if any(datamtx<0.0):
            raise ValueError("negative value in input matrix")
        if rank(datamtx) != 2:
            raise ValueError("input matrix not 2D")
        numrows, numcols = shape(datamtx)
    else:
        try:
            numrows, numcols = shape(datamtx)
        except ValueError:
            return zeros((0,0),'d')

    if numrows == 0 or numcols == 0:
        return zeros((0,0),'d')
    dists = zeros((numrows,numrows),'d')
    rowsums = datamtx.sum(axis=1)

    for i in range(numrows):
        first = datamtx[i]
        a = rowsums[i]
        for j in range(i):
            second = datamtx[j]
            b = rowsums[j]
            c = float(logical_and(first, second).sum())
            dist = a + b - (2.0*c)
            dists[i][j] = dists[j][i] = dist
    return dists

def binary_dist_jaccard(datamtx, strict=True):
    """Calculates jaccard distance between rows, returns distance matrix.

    converts matrix to boolean.  jaccard dist = 1 - jaccard index

    see for example: wikipedia jaccard index (20 jan 2009)
    this is identical to a binary version of the soergel distance

    Binary jaccard:
    a = num 1's in a
    b = num 1's in b
    c = num that are 1's in both a and b
    jaccard = 1 - (c/(a+b-c))

    * comparisons are between rows (samples)
    * input: 2D numpy array.  Limited support for non-2D arrays if
    strict==False
    * output: numpy 2D array float ('d') type.  shape (inputrows, inputrows)
    for sane input data
    * two rows of all zeros returns 0 distance between them
    * if strict==True, raises ValueError if any of the input data is negative,
    not finite, or if the input data is not a rank 2 array (a matrix).
    * if strict==False, assumes input data is a matrix with nonnegative
    entries.  If rank of input data is < 2, returns an empty 2d array (shape:
    (0, 0) ).  If 0 rows or 0 colunms, also returns an empty 2d array.
    """
    datamtx = datamtx.astype(bool)
    datamtx = datamtx.astype(float)
    if strict:
        if not all(isfinite(datamtx)):
            raise ValueError("non finite number in input matrix")
        if any(datamtx<0.0):
            raise ValueError("negative value in input matrix")
        if rank(datamtx) != 2:
            raise ValueError("input matrix not 2D")
        numrows, numcols = shape(datamtx)
    else:
        try:
            numrows, numcols = shape(datamtx)
        except ValueError:
            return zeros((0,0),'d')

    if numrows == 0 or numcols == 0:
        return zeros((0,0),'d')
    dists = zeros((numrows,numrows),'d')

    rowsums = datamtx.sum(axis=1)
    for i in range(numrows):
        first = datamtx[i]
        a = rowsums[i]
        for j in range(i):
            second = datamtx[j]
            b = rowsums[j]
            c = float(logical_and(first, second).sum())
            if a==0.0 and b==0.0:
                dist = 0.0
            else:
                dist = 1.0 - (c/(a+b-c))
            dists[i][j] = dists[j][i] = dist
    return dists

def binary_dist_lennon(datamtx, strict=True):
    """Calculates lennon distance between rows, returns distance matrix.

    converts matrix to boolean.  jaccard dist = 1 - lennon similarity
    lennon's similarity is a modification of simpson's index
    see Jack J.  Lennon, The geographical structure of British bird
    distributions: diversity, spatial turnover and scale

    Binary lennon:
    a = num 1's in a
    b = num 1's in b
    c = num that are 1's in both a and b
    lennon = 1 - (c/(c + min(a-c,b-c)))

    * comparisons are between rows (samples)
    * input: 2D numpy array.  Limited support for non-2D arrays if
    strict==False
    * output: numpy 2D array float ('d') type.  shape (inputrows, inputrows)
    for sane input data
    * two rows of all zeros returns 0 distance between them
    * if strict==True, raises ValueError if any of the input data is negative,
    not finite, or if the input data is not a rank 2 array (a matrix).
    * if strict==False, assumes input data is a matrix with nonnegative
    entries.  If rank of input data is < 2, returns an empty 2d array (shape:
    (0, 0) ).  If 0 rows or 0 colunms, also returns an empty 2d array.
    """
    datamtx = datamtx.astype(bool)
    datamtx = datamtx.astype(float)
    if strict:
        if not all(isfinite(datamtx)):
            raise ValueError("non finite number in input matrix")
        if any(datamtx<0.0):
            raise ValueError("negative value in input matrix")
        if rank(datamtx) != 2:
            raise ValueError("input matrix not 2D")
        numrows, numcols = shape(datamtx)
    else:
        try:
            numrows, numcols = shape(datamtx)
        except ValueError:
            return zeros((0,0),'d')

    if numrows == 0 or numcols == 0:
        return zeros((0,0),'d')
    dists = zeros((numrows,numrows),'d')

    rowsums = datamtx.sum(axis=1)
    for i in range(numrows):
        first = datamtx[i]
        a = rowsums[i]
        for j in range(i):
            second = datamtx[j]
            b = rowsums[j]
            c = float(logical_and(first, second).sum())
            if a==0.0 and b==0.0:
                dist = 0.0
            elif c==0.0:
                dist = 1.0
            else:
                dist = 1.0 - (c/(c + min([a-c,b-c])))
            dists[i][j] = dists[j][i] = dist
    return dists

def binary_dist_ochiai(datamtx, strict=True):
    """Calculates ochiai distance btw rows, returning distance matrix.

    Note: Treats array as bool.
    see for example:
    On the Mathematical Significance of the Similarity Index of Ochiai...
    Bolton, 1991

    a = num 1's in a
    b = num 1's in b
    c = num that are 1's in both a and b
    ochiai = 1 - (c/sqrt(a*b))

    * comparisons are between rows (samples)
    * input: 2D numpy array.  Limited support for non-2D arrays if
    strict==False
    * output: numpy 2D array float ('d') type.  shape (inputrows, inputrows)
    for sane input data
    * two rows of all zeros returns 0 distance between them
    * an all zero row compared with a not all zero row returns a distance of 1
    * if strict==True, raises ValueError if any of the input data is negative,
    not finite, or if the input data is not a rank 2 array (a matrix).
    * if strict==False, assumes input data is a matrix with nonnegative
    entries.  If rank of input data is < 2, returns an empty 2d array (shape:
    (0, 0) ).  If 0 rows or 0 colunms, also returns an empty 2d array.
    """
    datamtx = datamtx.astype(bool)
    datamtx = datamtx.astype(float)
    if strict:
        if not all(isfinite(datamtx)):
            raise ValueError("non finite number in input matrix")
        if any(datamtx<0.0):
            raise ValueError("negative value in input matrix")
        if rank(datamtx) != 2:
            raise ValueError("input matrix not 2D")
        numrows, numcols = shape(datamtx)
    else:
        try:
            numrows, numcols = shape(datamtx)
        except ValueError:
            return zeros((0,0),'d')

    if numrows == 0 or numcols == 0:
        return zeros((0,0),'d')
    dists = zeros((numrows,numrows),'d')
    rowsums = datamtx.sum(axis=1)

    for i in range(numrows):
        first = datamtx[i]
        a = rowsums[i]
        for j in range(i):
            second = datamtx[j]
            b = rowsums[j]
            c = float(logical_and(first, second).sum())
            if a==0.0 and b==0.0:
                dist = 0.0
            elif a==0.0 or b==0.0:
                dist = 1.0
            else:
                dist = 1.0 - (c/sqrt(a*b))
            dists[i][j] = dists[j][i] = dist
    return dists

def binary_dist_pearson(datamtx, strict=True):
    """Calculates binary pearson distance between rows, returns distance matrix

    converts input array to bool, then uses dist_pearson
    """

    datamtx = datamtx.astype(bool)
    datamtx = datamtx.astype(float)
    return dist_pearson(datamtx, strict=True)

if __name__ == "__main__":
    """ just a test run"""
    matrix1 = array(    [   [10,8,4,1],
                            [8,6,2,1],
                            [0,0,0,0],
                            [0,0,1,0],
                            [1,1,0,1],
                            [1,0,8,10],
                            [0,0,0,0],
                            [8,6,2,1],
                                    ])

    res = dist_euclidean(matrix1)
    print "euclidean distance result: \n"
    print res


text:
<html>
<head>
  <title>With Popup</title>
</head>
<body>

<button onclick="window.open('popup.html')">open popup</button>
</body>
</html>

redpajama_set_name: RedPajamaGithub


text:
<resources>
    <string name="app_name">RecyclerViewHeader</string>
    <string name="header">header</string>
    <string name="item">item</string>

</resources>


text:
from six.moves import http_client
import webob

from keystoneplayground.api.middleware import version_negotiation
from keystoneplayground.tests import base

class TestVersionNegotiationFilter(base.TestCase):

    def test_accept_header_with_serialization_format(self):
        middleware = version_negotiation.VersionNegotiationFilter(None)
        h = {'Accept': 'application/vnd.openstack.keystoneplayground.v1+json'}
        request = webob.Request.blank('/test', headers=h)
        middleware.process_request(request)
        self.assertEqual(1,
                         request.environ['api.version'])
        self.assertEqual('/v1/test',
                         request.path_info)

    def test_accept_header_without_serialization_format(self):
        middleware = version_negotiation.VersionNegotiationFilter(None)
        h = {'Accept': 'application/vnd.openstack.keystoneplayground.v1'}
        request = webob.Request.blank('/test', headers=h)
        middleware.process_request(request)
        self.assertEqual(1,
                         request.environ['api.version'])
        self.assertEqual('/v1/test',
                         request.path_info)

    def test_accept_header_no_version(self):
        middleware = version_negotiation.VersionNegotiationFilter(None)
        h = {'Accept': 'application/vnd.openstack.keystoneplayground+json'}
        request = webob.Request.blank('/v1/test', headers=h)
        middleware.process_request(request)
        self.assertEqual(1,
                         request.environ['api.version'])
        self.assertEqual('/v1/test',
                         request.path_info)

    def test_accept_header_unknown_mediatype(self):
        middleware = version_negotiation.VersionNegotiationFilter(None)
        h = {'Accept': 'application/json'}
        request = webob.Request.blank('/v1/test', headers=h)
        middleware.process_request(request)
        self.assertEqual(1,
                         request.environ['api.version'])
        self.assertEqual('/v1/test',
                         request.path_info)

    def test_no_header(self):
        middleware = version_negotiation.VersionNegotiationFilter(None)
        h = {}
        request = webob.Request.blank('/v1/test', headers=h)
        middleware.process_request(request)
        self.assertEqual(1,
                         request.environ['api.version'])
        self.assertEqual('/v1/test',
                         request.path_info)

    def test_no_version(self):
        middleware = version_negotiation.VersionNegotiationFilter(None)
        h = {'Accept': 'application/json'}
        request = webob.Request.blank('/test', headers=h)
        app = middleware.process_request(request)
        self.assertEqual(http_client.MULTIPLE_CHOICES,
                         app.__call__(request).status_code)

    def test_version_index(self):
        middleware = version_negotiation.VersionNegotiationFilter(None)
        h = {'Accept': 'application/json'}
        request = webob.Request.blank('/v1', headers=h)
        middleware.process_request(request)
        self.assertEqual('/v1/',
                         request.path_info)


text:
<?php

// autoload.php @generated by Composer

require_once __DIR__ . '/composer' . '/autoload_real.php';

return ComposerAutoloaderInit50d14cfe6584736ec8ee22f8d8291f02::getLoader();


text:
========
Licenses
========

.. literalinclude:: ../LICENSE


text:
<?php

namespace Sofa\Eloquence\Tests;

use Illuminate\Database\Query\Builder as Query;
use Illuminate\Database\Query\Grammars\Grammar;
use Illuminate\Database\Eloquent\Model;
use Sofa\Eloquence\Relations\JoinerFactory;

use Mockery as m;

class JoinerTest extends \PHPUnit_Framework_TestCase {

    public function setUp()
    {
        $this->factory = new JoinerFactory;
    }

    public function tearDown()
    {
        m::close();
    }

    /**
     * @test
     */
    public function it_joins_dot_nested_relations()
    {
        $sql = 'select * from "users" '.
               'inner join "profiles" on "users"."profile_id" = "profiles"."id" '.
               'inner join "companies" on "companies"."morphable_id" = "profiles"."id" and "companies"."morphable_type" = ?';

        $query = $this->getQuery();
        $joiner = $this->factory->make($query);

        $joiner->join('profile.company');

        $this->assertEquals($sql, $query->toSql());
    }

    /**
     * @test
     *
     * @expectedException \LogicException
     */
    public function it_cant_join_morphTo()
    {
        $query = $this->getQuery();
        $joiner = $this->factory->make($query);

        $joiner->join('morphs');
    }

    /**
     * @test
     */
    public function it_joins_relations_on_query_builder()
    {
        $sql = 'select * from "users" '.
               'right join "company_user" on "company_user"."user_id" = "users"."id" '.
               'right join "companies" on "company_user"."company_id" = "companies"."id"';

        $eloquent = $this->getQuery();
        $model = $eloquent->getModel();
        $query = $eloquent->getQuery();
        $joiner = $this->factory->make($query, $model);

        $joiner->rightJoin('companies');

        $this->assertEquals($sql, $query->toSql());
    }

    /**
     * @test
     */
    public function it_joins_relations_on_eloquent_builder()
    {
        $sql = 'select * from "users" '.
               'left join "companies" on "companies"."user_id" = "users"."id" '.
               'left join "profiles" on "profiles"."company_id" = "companies"."id"';

        $query = $this->getQuery();
        $joiner = $this->factory->make($query);

        $joiner->leftJoin('profiles');

        $this->assertEquals($sql, $query->toSql());
    }

    public function getQuery()
    {
        $model = new JoinerUserStub;
        $grammarClass = "Illuminate\Database\Query\Grammars\SQLiteGrammar";
        $processorClass = "Illuminate\Database\Query\Processors\SQLiteProcessor";
        $grammar = new $grammarClass;
        $processor = new $processorClass;
        $schema = m::mock('StdClass');
        $connection = m::mock('Illuminate\Database\ConnectionInterface', ['getQueryGrammar' => $grammar, 'getPostProcessor' => $processor]);
        $resolver = m::mock('Illuminate\Database\ConnectionResolverInterface', ['connection' => $connection]);
        $class = get_class($model);
        $class::setConnectionResolver($resolver);
        return $model->newQuery();
    }
}

class JoinerUserStub extends Model {

    protected $table = 'users';

    public function profile()
    {
        return $this->belongsTo('Sofa\Eloquence\Tests\JoinerProfileStub', 'profile_id');
    }

    public function companies()
    {
        return $this->belongsToMany('Sofa\Eloquence\Tests\JoinerCompanyStub', 'company_user', 'user_id', 'company_id');
    }

    public function profiles()
    {
        // due to lack of getters on HasManyThrough this relation works only with default fk!
        $related = 'Sofa\Eloquence\Tests\JoinerProfileStub';
        $through = 'Sofa\Eloquence\Tests\JoinerCompanyStub';
        return $this->hasManyThrough($related, $through, 'user_id', 'company_id');
    }

    public function posts()
    {
        return $this->hasMany('Sofa\Eloquence\Tests\JoinerPostStub', 'user_id');
    }

    public function morphed()
    {
        return $this->morphOne('Sofa\Eloquence\Tests\MorphOneStub');
    }

    public function morphs()
    {
        return $this->morphTo();
    }
}

class JoinerProfileStub extends Model {
    protected $table = 'profiles';

    public function company()
    {
        return $this->morphOne('Sofa\Eloquence\Tests\JoinerCompanyStub', 'morphable');
    }
}

class JoinerCompanyStub extends Model {
    protected $table = 'companies';
}

class JoinerPostStub extends Model {
    protected $table = 'posts';
}

class MorphOneStub extends Model {
    protected $table = 'morphs';
}


text:
package org.plummtw.jinrou.snippet

import scala.xml._
import net.liftweb._
import net.liftweb.mapper._
import http._
import js._
import util._
import S._
import SHtml._
import Helpers._

import org.plummtw.jinrou.model._
import org.plummtw.jinrou.enum._
import org.plummtw.jinrou.util._
import org.plummtw.jinrou.data._

import java.util.{GregorianCalendar, Calendar}

// 村莊處理用 Lock
object GameProcessLock {
  val lock_hash = scala.collection.mutable.Map[Long, Object]()

  // 每個 村莊 給一個 Lock
  def get_lock(id: Long) : Object = {
    if (!lock_hash.contains(id)) {
      lock_hash(id) = new Object()
    }

    return lock_hash(id)
  }

  def remove_lock(id: Long) = {
    lock_hash -= id
  }
}

// 村莊處理用 Cache
class GameProcessCacheData() {

}

object GameProcessCache {
  val room_cache = scala.collection.mutable.Map[Long, scala.collection.mutable.Map[String, NodeSeq]]()

  // 每個 村莊 給一個
  def get_cache(id: Long, type_str: String, refresh: Boolean, generate_method: ()=>NodeSeq) : NodeSeq = {
    if (!room_cache.contains(id)) {
      room_cache(id) = new scala.collection.mutable.HashMap[String, NodeSeq]
    }

    val cache = room_cache(id)

    if ((refresh == true) || (!cache.contains(type_str))) {
      //println("generate cache " + type_str + " " + id.toString)
      cache(type_str) = generate_method()
      //println(cache(type_str).toString)
    }

    return cache(type_str)
  }

  def remove_cache(id: Long) = {
    room_cache -= id
  }
}

class GameController {
  // 產生 Javascript 字串 force_reload
  private def js_force_reload(room_no : String) : String = {
    """function force_reload() {
         top.location.href = 'game_frame.html?room_no=""" + room_no + """'
    }"""
  }

  private def js_up_force_reload(room_no : String) : String = {
    """function up_force_reload() {
         parent.frames['up'].location.href = 'up_normal.html?room_no=""" + room_no + """'
    }"""
  }

  /*
  // 產生 Javascript 字串 setupbgcolor
  private def js_setupbgcolor(background_color:String, text_color:String) : String = {
    """function setupbgcolor() {
         parent.frames['up'].document.bgColor    = '""" + background_color + """';
         parent.frames['up'].document.fgColor    = '""" + text_color + """';
         parent.frames['up'].document.linkColor  = 'blue';
         parent.frames['up'].document.vlinkColor = 'blue';
         parent.frames['up'].document.alinkColor = 'red';
    }"""
  }

  // 產生 Javascript 字串 setvotelink
  private def js_setvotelink(room_no : String) : String = {
    ""
    /*"""function setvotelink() {
         for(i=0;i<parent.frames['up'].document.links.length;i++) {
           if(parent.frames['up'].document.links[i].name == 'vote_link'){
             parent.frames['up'].document.links[i].href = 'game_action?room_no=""" + room_no +"""';
             parent.frames['up'].document.links[i].hash ='game_top'
           }
         }
    }""" */
  }
  */

  // 產生 Javascript 字串 realtime_output
  private def js_realtime_output(room_day: RoomDay, room: Room) : String = {
    def date_string(datetime : GregorianCalendar) : String  = {
      String.format("new Date(%s,%s,%s,%s,%s,%s)",
        datetime.get(Calendar.YEAR).toString, datetime.get(Calendar.MONTH).toString,
        datetime.get(Calendar.DAY_OF_MONTH).toString, datetime.get(Calendar.HOUR_OF_DAY).toString,
        datetime.get(Calendar.MINUTE).toString, datetime.get(Calendar.SECOND).toString)
    }

    val s_datetime = new GregorianCalendar()
    val e_datetime = new GregorianCalendar()
    if (room_day.day_no.is == 0) {
       """function realtime_output() {
         php_now = """ + date_string(s_datetime) + """;
         local_now = new Date();
         diff_sec = Math.floor( (local_now - php_now) / 1000);
         //document.realtime_form.realtime_output.value = "伺服器與本地時間差:" + diff_sec + "秒";
         $("#realtime_output").val("伺服器與本地時間差:" + diff_sec + "秒");
       }"""
    } else {
      s_datetime.setTime(room_day.created.is)
      e_datetime.setTime(room_day.created.is)

      var until_string = ""
      if (room_day.day_no.is % 2 == 0) {
        e_datetime.add(Calendar.MINUTE, room.day_minutes.is)
        until_string = "日落"
      } else {
        e_datetime.add(Calendar.MINUTE, room.night_minutes.is)
        until_string = "早上"
      }

      """starttime = """ + date_string(s_datetime) + """;
      endtime   = """ + date_string(e_datetime) + """;
      diffseconds = Math.floor((endtime - starttime)/1000);
      function realtime_output() {
        nowtime = new Date();
        leftseconds = diffseconds - Math.floor((nowtime - starttime)/1000);
        lefttime = new Date(0,0,0,0,0,leftseconds);
        virtual_left_seconds = Math.floor(12*60*60*(leftseconds / diffseconds));
        virtual_lefttime = new Date(0,0,0,0,0,virtual_left_seconds);
        if(leftseconds > 0){
          //document.realtime_form.realtime_output.value = " """ + until_string + """剩餘 " + virtual_lefttime.getHours()+"時間"+virtual_lefttime.getMinutes()+"分 (實際時間 "+lefttime.getMinutes()+"分"+lefttime.getSeconds()+"秒)"; \n\
          $("#realtime_output").val(" """ + until_string + """剩餘 " + virtual_lefttime.getHours()+"時間"+virtual_lefttime.getMinutes()+"分 (實際時間 "+lefttime.getMinutes()+"分"+lefttime.getSeconds()+"秒)");
        } else {
          overseconds = Math.abs(leftseconds);
          overtime = new Date(0,0,0,0,0,overseconds);
          //document.realtime_form.realtime_output.value = "超過時間 "+overtime.getMinutes()+"分"+overtime.getSeconds()+"秒"; \n\
          $("#realtime_output").val("超過時間 "+overtime.getMinutes()+"分"+overtime.getSeconds()+"秒");
        }
        tid = setTimeout('realtime_output()', 1000);
      }"""
    }
  }

  // 產生 Javascript 字串 onload_string
  private def js_onload_string(force_reload: Boolean, up_force_reload: Boolean) : String = {
    val force_reload_str    = if (force_reload)    "force_reload();" else ""
    val up_force_reload_str = if (up_force_reload) "up_force_reload();" else ""

    /*"""window.onload=function() {
      """ + force_reload_str + up_force_reload_str + """
      realtime_output();
    };"""*/

    """$(document).ready(function(){
        """ + force_reload_str + up_force_reload_str + """
        realtime_output();
      });"""
  }

  // 主畫面觀看頁面
  def view (xhtml : Group) : NodeSeq = {
    val room_no = S.param("room_no").getOrElse(S.getSessionAttribute("room_id").getOrElse("0"))
    val room_id : Long =
      try { room_no.toLong }
      catch { case e: Exception => 0 }    //val room        = Room.get(room_id)
    val room_list   = Room.findAll(By(Room.id, room_id))
    val room        = if (room_list.length == 0) null else room_list(0)

    // 參數

    if (room == null) {
      S.error(找不到村莊)
      S.redirectTo("main.html")
    }
    if (room.status.is == RoomStatusEnum.ENDED.toString()) {
      //S.error(遊戲已經結束)
      S.redirectTo("game_end.html?room_no=" + room_no)
    }

    val room_day_list   = RoomDay.findAll(By(RoomDay.room_id, room_id), OrderBy(RoomDay.day_no, Descending))
    val room_day        = if (room_day_list.length == 0) null else room_day_list(0)
    if (room_day == null) {
      S.error(找不到遊戲日)
      S.redirectTo("main.html")
    }
    //println("dead_line : " + room_day.deadline.is)

    // 設定顏色
    val (background_color, text_color) = JinrouUtil.color_helper(room, room_day)
    val css_style = JinrouUtil.css_style(background_color, text_color)

    // 檢查是否登入
    var message_refresh        = false
    var force_reload           = false
    var up_force_reload        = false
    var swf_filename           = ""
    var user_entry : UserEntry = null
    var user_role  : RoleData  = RoleNone

    val user_entry_no : String = S.getSessionAttribute("user_id").getOrElse("")
    if ((S.getSessionAttribute("room_id").getOrElse("") == room_no) &&
        (user_entry_no != "")){
      val user_entry_list   = UserEntry.findAll(By(UserEntry.id, user_entry_no.toLong), By(UserEntry.room_id, room_id))
      user_entry            = if (user_entry_list.length == 0) null else user_entry_list(0)

      if (user_entry == null) {
        S.setSessionAttribute("room_id", "")
        S.setSessionAttribute("user_id", "")
        S.error(找不到對應的玩家 {user_entry_no})
        S.redirectTo("main.html")
      }
    }

    var alert_message =
      if (room_day.deadline.is == null)

      else if (user_entry != null) {

      } else

    // 是否更新 Session 內容
    val auto_reload = S.param("auto_reload").getOrElse("0")
    if (auto_reload != "0")
      S.setSessionAttribute("auto_reload", auto_reload)

    val play_sound = S.param("play_sound").getOrElse("0")
    if (play_sound != "0")
      S.setSessionAttribute("play_sound", play_sound)

    val list_down = S.param("list_down").getOrElse("0")
    if (list_down != "0")
      S.setSessionAttribute("list_down", list_down)
    //println("list_down : " + list_down)

    val link_page = if (user_entry != null) "game_frame.html" else "game_view.html"

    val game_title_with_user2 : NodeSeq =
             if (room_day.day_no.is == 0)
                 Seq([自刪],
                     [離開])
             else
                 //Seq([離開],
                 //    {user_entry.check_voted(room_day,room)})
                 Seq([離開])
    val game_title_with_user : NodeSeq =
             Seq([登出]) ++ game_title_with_user2

    val game_title : NodeSeq = Seq({room.room_name.is} 村
          ~{room.room_comment.is}~[{room_no}號村]
         {
           if (user_entry != null)
             game_title_with_user
           else
             Seq()
         },
)

    val play_sound_option : scala.xml.Elem =
      if (S.getSessionAttribute("play_sound") == "on")
        off on
      else
        off on

    val list_down_option : scala.xml.Elem =
      if (S.getSessionAttribute("list_down") == "on")
        ↑訊息
      else
        ↓訊息

    // 更新 Cache 機制未完成
    // (room_day.day_no.is == 0)
    val user_entrys = UserEntry.findAll(By(UserEntry.room_id, room_id))

    val abandon_option : NodeSeq =
      if ((room_day.day_no.is > 9) || (user_entry == null) || (!user_entry.live.is))
        Seq()
      else {
        val abandon_vote_param = S.param("abandon").getOrElse("0")

        val abandon_votes = SpecialVote.findAll(By(SpecialVote.roomday_id, room_day.id.is), By(SpecialVote.mtype, MTypeEnum.SPECIAL_VOTE_ABANDON.toString))
        val live_user_entrys = user_entrys.filter(_.live.is)
        val abandon_counts   = Math.max((live_user_entrys.length + 1) / 2, 5)
        val player_abandon_voted = abandon_votes.filter(x => x.actioner_id.is == user_entry.id.is)

        if ((abandon_vote_param == "on") && (player_abandon_voted.length == 0)) {
          SpecialVote.create.roomday_id(room_day.id.is).actioner_id(user_entry.id.is).mtype(MTypeEnum.SPECIAL_VOTE_ABANDON.toString).save
          if (user_entry.sex.is.toString == "M")
            Talk.create.roomday_id(room_day.id.is).actioner_id(user_entry.id.is).mtype(MTypeEnum.OBJECTION_MALE.toString).save
          else
            Talk.create.roomday_id(room_day.id.is).actioner_id(user_entry.id.is).mtype(MTypeEnum.OBJECTION_FEMALE.toString).save

          if (abandon_votes.length +1 >= abandon_counts) {
            room.status(RoomStatusEnum.ENDED.toString).victory(RoomVictoryEnum.ABANDONED.toString).save
            RoomDay.create.room_id(room.id.is).day_no(room_day.day_no.is + 1).vote_time(1).save
            S.redirectTo("game_end.html?room_no=" + room_no)
          }
          Seq(廢村[{abandon_votes.length +1}/{abandon_counts}])
        } else if (player_abandon_voted.length > 0) {
          Seq(廢村[{abandon_votes.length}/{abandon_counts}])
        } else {
          Seq(廢村[{abandon_votes.length}/{abandon_counts}])
        }
      }

    val game_option : NodeSeq = Seq([自動更新](
         手動
         15秒
         20秒
         30秒)
         [音效通知]({ play_sound_option })
         { list_down_option } {abandon_option}
         )

    def sound_object(swf_filename: String) =
      if ((swf_filename == "") || (S.getSessionAttribute("play_sound") != "on"))

      else
        <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=4,0,0,0" width="0" height="0">
          <param name="movie" value={"swf/" + swf_filename} />
          <param name="quality" value="high" />
          <param name="loop" value="true" />
          <embed src={"swf/" + swf_filename} quality="high" width="0" height="0" loop="true" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash">
          </embed>
        </object>

    val game_info : NodeSeq = if ((user_entry != null) && (room_day.day_no == 0))

           需要遊戲全體人員投'開始遊戲'才能開始遊戲(完成投票的玩家其名單背景顏色會變粉紅)

 else

    val login_form : NodeSeq = if (user_entry == null) Seq(
         <form action={"login.html?room_no=" + room_no} method="POST">

            帳號<input type="text" name="uname" size="20"/>密碼
            <input type="password" name="password" size="20" style="txt-align:rignt;ime-mode: disabled;" />
            <input type="submit" value="登入"/>
            { if (room_day.day_no.is == 0)
                Seq([住民登錄1],
                    [住民登錄2])
              else scala.xml.NodeSeq.Empty }
             [離開]

         </form>) else Seq()

    val dead_mode    = (room.status.is != RoomStatusEnum.ENDED.toString) &&
                       (user_entry != null) && (!user_entry.live.is)
    val heaven_mode  = (room.status.is == RoomStatusEnum.ENDED.toString) ||
                     ((room.status.is == RoomStatusEnum.PLAYING.toString) &&
                      (room.has_flag(RoomFlagEnum.TEST_MODE))) ||
                     ((user_entry != null) && (!user_entry.live.is) &&
                      (room.has_flag(RoomFlagEnum.DEATH_LOOK)))
    //println("heaven_mode " + heaven_mode.toString)

    if (GameProcesser.check_deadline(room, room_day, user_entrys)) {
      S.redirectTo("game_view.html?room_no=" + room_no)
    }

    //def user_table = GameProcessCache.get_cache(room_id, "user_table", true,
    //  ()=>UserEntryHelper.user_table(user_entrys, heaven_mode))
    var user_table_down : NodeSeq = NodeSeq.Empty
    var user_table =
      UserEntryHelper.user_table(room, user_entry, user_entrys, heaven_mode)
    if (S.getSessionAttribute("list_down") == "on") {
      user_table_down = user_table
      user_table = NodeSeq.Empty
    }

    // 這邊可能靈界和正常看到的不同,要準備兩份 Cache 先不弄
    // (room_day.day_no.is %2 == 1) || message_refresh
    //def messages     = GameProcessCache.get_cache(room_id, "messages", true,
    //  ()=>MessageHelper.messages_normal(room, room_day, user_entry, heaven_mode, user_entrys))
    val vote_godfat_blind = SystemMessage.findAll(By(SystemMessage.roomday_id, room_day.id.is),
//                                                  By(SystemMessage.actionee_id, user_entry.id.is),
                                                  By(SystemMessage.mtype, MTypeEnum.VOTE_GODFAT_BLIND2.toString))
    val is_blinded =
      if (vote_godfat_blind.length == 0)
        false
      else if (user_entry == null)
        true
      else if ((user_entry.test_foxside(room, room_day, user_entrys)) || (heaven_mode))
      //if (vote_godfat_blind.filter(_.actionee_id.is == user_entry.id.is).length == 0)
        false
      else
        true

    var messages     =
      MessageHelper.messages_normal(room, room_day, user_entry, heaven_mode, is_blinded, user_entrys)

    val item_intro =
      if (room.has_flag(RoomFlagEnum.ITEM_MODE) && (user_entry != null) &&
          (user_entry.live.is) && (room_day.day_no.is != 0)) {
        val system_messages = SystemMessage.findAll(By(SystemMessage.roomday_id,  room_day.id.is),
                                                    By(SystemMessage.actioner_id, user_entry.id.is))
        val item_messages = system_messages.filter(_.mtype.is.substring(0,1) == MTypeEnum.ITEM_PREFIX)
        val item_result =
          if (item_messages.length != 0) {
            val item_message = item_messages(0)
            val item_datas = ItemEnum.ITEM_MAP.values.toList.filter(_.action_enum.toString == item_message.mtype.is)
            if (item_datas.length > 0 )
              item_datas(0).item_intro(room, room_day, user_entry, user_entrys)
            else ""
          } else ""

        //{"持有道具:" + ItemEnum.get_item(user_entry.item_flags.is).tag_string + " " + item_result}
        {ItemEnum.get_item(user_entry.item_flags.is).item_pic}{item_result}
      } else

    val role_intro =
      if ((user_entry != null) && (user_entry.live.is) && (room_day.day_no.is != 0))
      {
        val role_data = RoleEnum.get_role(user_entry.role.is.substring(0,1))
        var result = Seq(role_data.generate_role_intro(room, room_day, user_entry, user_entrys),
                         role_data.generate_role_ability(room, room_day, user_entry, user_entrys))

        val subrole_data = SubroleEnum.get_subrole(user_entry.subrole.is)
        //if (user_entry.subrole != SubroleNone)
        //if (user_entry.subrole.is == SubroleEnum.AUTHORITY.toString)
          result = result ++ Seq(subrole_data.subrole_intro)

        val is_mob = user_entry.has_flag(UserEntryFlagEnum.BECAME_MOB)
        if (is_mob)
          result = result ++ Seq() //<暴民模式>

        // 教徒時互相知道身分
        val live_pontiff = user_entrys.filter(x=>(x.current_role == RoleEnum.PONTIFF) && (x.live.is))

        // 可以得知所有教徒身份的人有三
        // 1. 副教主
        // 2. 非失憶教主
        // 3. 教徒有開教友會,且第七日之後
        val is_pontiff_view = (user_entry.subrole.is == SubroleEnum.SUBPONTIFF.toString) ||
                              ((user_entry.current_role == RoleEnum.PONTIFF)  &&
                               (!user_entry.test_memoryloss(room, room_day, user_entrys)) ||
                              ((live_pontiff.length != 0) &&
                               (user_entry.has_flag(UserEntryFlagEnum.RELIGION)) &&
                               (room_day.day_no.is > 11) && (room.has_flag(RoomFlagEnum.PONTIFF_OPTION1))))

        if (is_pontiff_view) {
          val users_religion = user_entrys.filter(x=>(x.id.is != user_entry.id.is) &&
                                                    ((x.current_role == RoleEnum.PONTIFF) ||
                                                     (x.has_flag(UserEntryFlagEnum.RELIGION))))
          val religion_str = users_religion.map(_.handle_name.is).mkString("", " ","")

          //
和你同一教派的成員有:	{religion_str}

)
          result = result ++ Seq(

	{religion_str}

)
        } else if ((live_pontiff.length != 0) &&
            ((user_entry.has_flag(UserEntryFlagEnum.RELIGION)))){
          val users_religion = user_entrys.filter(x=>((x.current_role == RoleEnum.PONTIFF) ||
                                                     (x.has_flag(UserEntryFlagEnum.RELIGION))))
          val live_users_religion = users_religion.filter(_.live.is)

          //
教派成員總數:	{users_religion.length.toString}	存活教派成員總數:
          result = result ++ Seq(

	{users_religion.length.toString}
                {live_users_religion.length.toString}

)
        }

        if (user_entry.has_flag(UserEntryFlagEnum.LOVER)) {
          val users_lovers = user_entrys.filter(x=>(x.id.is != user_entry.id.is) &&
                                                   (x.has_flag(UserEntryFlagEnum.LOVER)))
          val lovers_str = users_lovers.map(_.handle_name.is).mkString("", " ","")

          result = result ++ Seq(

	{lovers_str}

)
        }

        result
      }
      else
        Seq()

    var vote_tag_d     : NodeSeq = NodeSeq.Empty
    var vote_tag_n     : NodeSeq = NodeSeq.Empty
    var last_words_tag : NodeSeq = NodeSeq.Empty
    var dead_tag       : NodeSeq = NodeSeq.Empty

    if (room_day.day_no.is >= 2)  {
      val last_day  = RoomDay.findAll(By(RoomDay.room_id, room.id.is), By(RoomDay.day_no, room_day.day_no.is - 1))(0)
      val last_day2 = RoomDay.findAll(By(RoomDay.room_id, room.id.is), By(RoomDay.day_no, room_day.day_no.is - 2))(0)

      // 產生投票字串
      val  vote_tag_pair     = VoteHelper.get_vote_tag(room, room_day, user_entrys, heaven_mode, last_day, last_day2)
      vote_tag_d = vote_tag_pair._1
      vote_tag_n = vote_tag_pair._2

      // 產生死亡訊息字串
      val death_last_day  = SystemMessage.findAll(By(SystemMessage.roomday_id, last_day.id.is),  Like(SystemMessage.mtype, MTypeEnum.DEATH.toString + "%"),
                                                  OrderBy(SystemMessage.actioner_id, Ascending))
      val death_last_day2 = SystemMessage.findAll(By(SystemMessage.roomday_id, last_day2.id.is), Like(SystemMessage.mtype, MTypeEnum.DEATH.toString + "%"),
                                                  OrderBy(SystemMessage.actioner_id, Ascending))
      val deaths = death_last_day++death_last_day2

      dead_tag   = MiscHelper.get_dead_tag(deaths, user_entrys)

      // 白天時產生遺言字串
      if (room_day.day_no.is % 2 == 0) {
        last_words_tag = MiscHelper.get_lastwords_tag(deaths, user_entrys)
      } else if (room_day.day_no.is >= 3) {
        // 晚上時產生前一天的遺言字串
        val last_day3 = RoomDay.findAll(By(RoomDay.room_id, room.id.is), By(RoomDay.day_no, room_day.day_no.is - 3))(0)
        val death_last_day3  = SystemMessage.findAll(By(SystemMessage.roomday_id, last_day3.id.is),  Like(SystemMessage.mtype, MTypeEnum.DEATH.toString + "%"),
                                                     OrderBy(SystemMessage.actioner_id, Ascending))
        val deaths_n = death_last_day2++death_last_day3

        last_words_tag   = MiscHelper.get_lastwords_tag(deaths_n, user_entrys)

      }
    }

    val self_lastwords_tag = MiscHelper.get_self_lastwords_tag(user_entry)

    if (user_entry != null) {
      if (user_entry.last_day_no.is != room_day.day_no.is) {
        user_entry.last_day_no(room_day.day_no.is)
        user_entry.save()

        if (room.status.is == RoomStatusEnum.ENDED.toString)
          force_reload = true
        else if (user_entry.live.is) {
          up_force_reload = true
          if (room_day.day_no.is %2 == 0)
             swf_filename = "sound_morning.swf"
        } else {
         val last_day        = RoomDay.findAll(By(RoomDay.room_id, room.id.is), By(RoomDay.day_no, room_day.day_no.is - 1))(0)
         val death_last_day  = SystemMessage.findAll(By(SystemMessage.roomday_id, last_day.id.is),  By(SystemMessage.actioner_id, user_entry.id.is),
                                                     Like(SystemMessage.mtype, MTypeEnum.DEATH.toString + "%"))
         if (death_last_day.length != 0)
           force_reload = true
        }
      }

      if (room_day.deadline.is != null)
        swf_filename = "sound_revote.swf"
    }

    bind("entry", xhtml,
      "reload_tag"        -> <meta http-equiv="refresh" content={S.getSessionAttribute("auto_reload").getOrElse("")} />,
      "css_style"         -> ,
      "js_force_reload"   -> ,
      "js_up_force_reload"   -> ,
      //"js_setupbgcolor"   -> ,
      //"js_setvotelink"    -> ,
      "js_realtimeoutput" -> ,
      "js_onload_string"  -> ,
      "game_title"        -> game_title,
      "game_option"       -> game_option,
      "sound_object"      -> sound_object(swf_filename),
      "game_info"         -> game_info,
      "login_form"        -> login_form,
      "day_no"            -> {((room_day.day_no.is+2)/2).toString},
      "weather"           -> {WeatherEnum.get_weather(room_day.weather.is)},
      "live_player"       -> {user_entrys.count(_.live.is).toString},
      "auction"           -> (if (room.has_flag(RoomFlagEnum.ITEM_MODE) && (room_day.day_no.is != 0))
                              //{"(競標:" + ItemEnum.get_item(room_day.item.is).tag_string + ")"}
                              (競標:{ItemEnum.get_item(room_day.item.is).item_pic})
                              else ),
      "alert_message"     -> alert_message,
      "user_table"        -> user_table,
      "item_intro"        -> item_intro,
      "role_intro"        -> role_intro,
      "vote_tag_d"        -> vote_tag_d,
      "messages"          -> messages,
      "last_words_tag"    -> last_words_tag,
      "dead_tag"          -> dead_tag,
      "vote_tag_n"        -> vote_tag_n,
      "self_last_words"   -> self_lastwords_tag,
      "user_table_down"   -> user_table_down
    )
  }

}


text:
package com.kiterette.mochi;

import android.app.Activity;
import android.app.Fragment;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.EditText;

public class UserFragment extends Fragment {
    private Button nextButton;
    private EditText userName, userOrder;

    private OnFragmentInteractionListener mListener;

    public UserFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_user, container, false);
        nextButton = (Button)v.findViewById(R.id.user_next_button);
        userName = (EditText)v.findViewById(R.id.userNameEditText);
        userOrder = (EditText)v.findViewById(R.id.userOrderEditText);

        nextButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mListener.onNextUserButtonClick(userName.getText().toString(), userOrder.getText().toString());
            }
        });
        return v;
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnFragmentInteractionListener) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString()
                    + " must implement OnFragmentInteractionListener");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    public interface OnFragmentInteractionListener {
        public void onNextUserButtonClick(String name, String order);
    }
}


text:
package zk

import (
	"encoding/json"
	"flag"
	"fmt"
	"log"
	"os"
	"sort"
	"strings"
	"time"

//	"launchpad.net/gozk/zookeeper"
)

const (
	DEFAULT_BASE_TIMEOUT = 5 * time.Second
)

var zkConfigPaths = []string{"/etc/zookeeper/zk_client.json"}
var localCell = flag.String("zk.local-cell", "",
	"closest zk cell used for /zk/local paths")
var localAddrs = flag.String("zk.local-addrs", "",
	"list of zookeeper servers (host:port, ...)")
var globalAddrs = flag.String("zk.global-addrs", "",
	"list of global zookeeper servers (host:port, ...)")
var baseTimeout = flag.Duration("zk.base-timeout", DEFAULT_BASE_TIMEOUT,
	"zk or zkocc base timeout (see zkconn.go and zkoccconn.go)")

// Read the cell from -zk.local-cell, or the environment ZK_CLIENT_LOCAL_CELL
// or guess the cell by the hostname. This is either the first two characters
// or the character before a dash '-'.
func GuessLocalCell() string {
	if *localCell != "" {
		return *localCell
	}

	envCell := os.Getenv("ZK_CLIENT_LOCAL_CELL")
	if envCell != "" {
		return envCell
	}

	hostname, err := os.Hostname()
	if err != nil {
		panic(err) // should never happen
	}

	shortHostname := strings.Split(hostname, ".")[0]
	hostParts := strings.Split(shortHostname, "-")
	if len(hostParts) > 1 {
		return hostParts[0]
	}
	return shortHostname[:2]
}

func ZkCellFromZkPath(zkPath string) (string, error) {
	pathParts := strings.Split(zkPath, "/")
	if len(pathParts) < 3 {
		return "", fmt.Errorf("no cell name in path: %v", zkPath)
	}
	if pathParts[0] != "" || pathParts[1] != "zk" {
		return "", fmt.Errorf("path should start with /zk/: %v", zkPath)
	}
	cell := pathParts[2]
	if strings.Contains(cell, "-") {
		return "", fmt.Errorf("invalid cell name %v", cell)
	}
	return cell, nil
}

func getConfigPaths() []string {
	zkConfigPath := os.Getenv("ZK_CLIENT_CONFIG")
	if zkConfigPath != "" {
		return []string{zkConfigPath}
	}
	return zkConfigPaths
}

func getCellAddrMap() map[string]string {
	var cellAddrMap map[string]string
	for _, configPath := range getConfigPaths() {
		file, err := os.Open(configPath)
		if err != nil {
			log.Printf("error reading config file: %v: %v", configPath, err)
			continue
		}
		err = json.NewDecoder(file).Decode(&cellAddrMap)
		file.Close()
		if err != nil {
			log.Printf("error decoding config file %v: %v", configPath, err)
			continue
		}

		break
	}
	return cellAddrMap
}

func ZkPathToZkAddr(zkPath string, useCache bool) (string, error) {
	cell, err := ZkCellFromZkPath(zkPath)
	if err != nil {
		return "", err
	}

	cellAddrMap := getCellAddrMap()
	if cell == "local" {
		cell = GuessLocalCell()
	} else if cell == "global" {
		if *globalAddrs != "" {
			return *globalAddrs, nil
		} else if _, ok := cellAddrMap[cell]; !ok {
			// if there is no "global" cell, look for a dc-specific
			// address for the global cell
			cell = GuessLocalCell() + "-global"
		}
	}
	if useCache {
		cell += ":_zkocc"
	}

	addr := cellAddrMap[cell]
	if addr != "" {
		return addr, nil
	}

	return "", fmt.Errorf("no addr found for zk cell: %#v", cell)
}

// returns all the known cells, alphabetically ordered. It will
// include 'global' if there is a dc-specific global cell or a global cell
func ZkKnownCells(useCache bool) []string {
	localCell := GuessLocalCell()
	cellAddrMap := getCellAddrMap()
	result := make([]string, 0, len(cellAddrMap))
	foundGlobal := false
	for cell, _ := range cellAddrMap {
		// figure out cell name and if it's zkocc
		isZkoccCell := false
		name := cell
		if strings.HasSuffix(name, ":_zkocc") {
			name = name[:len(name)-7]
			isZkoccCell = true
		}
		if (useCache && !isZkoccCell) || (!useCache && isZkoccCell) {
			// this is not the zkocc you're looking for
			continue
		}

		// handle global, we just remember it
		if name == "global" {
			foundGlobal = true
			continue
		}

		// skip global cells, remember if we have our global
		if strings.HasSuffix(name, "-global") {
			if name == localCell+"-global" {
				foundGlobal = true
			}
			continue
		}

		// non-global cell
		result = append(result, name)
	}
	if foundGlobal {
		result = append(result, "global")
	}
	sort.Strings(result)
	return result
}

// GetZkSubprocessFlags returns the flags necessary to run a sub-process
// that would connect to the same zk servers as this process
// (assuming the environment of the sub-process is the same as ours)
func GetZkSubprocessFlags() []string {
	result := make([]string, 0, 0)
	if *localCell != "" {
		result = append(result, "-zk.local-cell", *localCell)
	}
	if *localAddrs != "" {
		result = append(result, "-zk.local-addrs", *localAddrs)
	}
	if *globalAddrs != "" {
		result = append(result, "-zk.global-addrs", *globalAddrs)
	}
	if *baseTimeout != DEFAULT_BASE_TIMEOUT {
		result = append(result, "-zk.base-timeout", baseTimeout.String())
	}
	return result
}


text:
'use strict';

const path = require('path');
const nohm = require('nohm').Nohm;
const Promise = require('bluebird');

module.exports = app => {
  const config = app.config.nohm;
  let useRedis;
  const { redis } = config;
  if (redis) {
    if (typeof redis === 'function') {
      useRedis = redis(app);
    } else {
      useRedis = redis;
    }
  } else {
    useRedis = app.redis;
  }
  if (!useRedis || typeof useRedis.on !== 'function') {
    throw new Error('redis client must not be null please confirm you config the redis plugin');
  }

  // waiting until the app is ready .
  app.beforeStart(() => new Promise(resolve => {
    if (useRedis.connected === true) {
      nohm.setClient(useRedis);
      resolve();
      return;
    }
    useRedis.on('connect', () => {
      // hack  ioredis check this field but ioredis not set
      useRedis.connected = true;
      nohm.setClient(useRedis);
      resolve();
    });
  }));

  const suffix = config.suffix;
  Promise.promisifyAll(nohm.prototype, {
    suffix,
  });
  const name = 'nohmModel';
  const directory = path.join(app.config.baseDir, config.modelPath);
  app.loader.loadToApp(directory, name, {
    call: false,
    initializer(model, opt) {
      let returnModel;
      if (typeof model === 'function') {
        if (model.prototype instanceof nohm) {
          returnModel = model;
        } else {
          returnModel = model(app);
        }
      }
      if (!returnModel) {
        app.coreLogger.info(`[egg-nohm] ignore null file:${opt.path}`);
        return null;
      }
      // model static method promise
      Promise.promisifyAll(returnModel, {
        suffix,
      });
      return returnModel;
    },
  });
};