#python debugger
import pdb
from numpy import *
from numpy.random import *
print 'some types'
print 42 #integer
print 'what is the answer to the meaning of the universe?'  #string
print 67.0J #imaginary
print 67.0J+1. #complex
print """string over 2
lines"""
print
print
print 'tuples'
#tuples
a=(34,45,90,100,'y')
print 'a=',a
print 'fifth element of a', a[4]
#slicing
print 'last 2 elements of tuple', a[-2:]
print 'all but last 2 elements of tuple', a[:-2]
#immutability
try:
    a[4]=5
except TypeError:
    print "You can't do this because tuples are immutable!"
print
print
print 'lists'
a=[34,45,90,100,'y']
b=a
print 'a=',a
b[2]='r'
print 'lists are mutable'
print 'a=',a
print 'expanding lists'
print [3,2]
print 'expanded lists'
print [3,2]*3
print [3,2]+[4]
print
print
#list methods
print 'list methods'
a=[1,2,3,4,5,6,7,8,9]
print a
#append x to end of a
x=4
a.append(x)
print a
b=[20,30,40]
a.extend(b)
print a
print a.count(4)
a.remove(4)
print a
a.sort()
print a
a.reverse()
print a
print
print 'strings'
print 'string literals'
a='Now is the Time'
print a
print 'slicing'
print a[1:5]
print
print 'error exception if index not in string'
print a[99:100]
print
print 'String Methods'
print 's.split'
print 'This is useful for inputtting data!'
lineofdata='1234,567,8910'
print 'Split the line at the commas'
x,y,z=lineofdata.split(",")
print x,y,z
print 'Slicing'
substring=lineofdata[0:6]
print 'substring=',substring
print
print 'dictionaries'
#empty dictionary
wife={}
#filled dictionary
wife={'fred':'wilma', 'barney':'betty'}
print wife
print wife['fred']
#iterate over keys and get entry
for hubby in wife:
    print hubby,wife[hubby]
print
print
print 'loops and controls'
x=2
if x<2:
    print 'x is less than 2'
elif x>2:
    print 'x>2'
else:
    print 'x=2'

x=0

while x<11:
    print 'x=',x, 'x**2=', x**2
    x+=1

for x in range(11):
    print x, x**2

print
print
print 'list comprehension'

x=[i**2 for i in range(10)]
print x
#can operate on existing list
z=[1j*y for y in x]
print z
#operate on 2 or more lists via zipping
#create a list via the arange method then derive 2 other lists from it
a=arange(0,100)
b=[x**2 for x in a]
c=[sqrt(x) for x in a]
d=sum([x+y+z for x,y,z in zip(a,b,c)])
print d

#method 2
d=sum([x+x**2+sqrt(x) for x in arange(0,100)])
print d
print
print
print 'reading data from files- method 1-- load data into a list'
#create a file object snork
snork= open('snorkel.csv')
#set up an empty list called 
data = []
for line in snork:
     gradient,mndepth,mnwdth,crx,capt,known,ef = line.split(',')
     data.append([float(gradient),float(mndepth),float(mnwdth),float(crx),int(capt),int(known),int(ef)])

print data[0] #prints the first record
#method load data into dictionary 
wsdata = open('watershed.csv')
WS = {}
for line in wsdata:
    wshd_id,temp,precip,str_cons,felsic,carbonate,forest,range1,urban,drain_den,sqkm,geo_road,anadac\
                                                                                                      = line.split(',')     #line continuation
    WS[wshd_id] = [int(wshd_id),float(temp),float(precip),float(str_cons),float(felsic),
                        float(carbonate),float(forest), float(range1),float(urban),float(drain_den),
                        float(sqkm),float(geo_road),float(anadac)]

print 'data for watershed 50'
print WS['50']
#close data objects
snork.close()
wsdata.close()
print
print
print 'writing data to files'

outdata=open('output.csv','w')
outdata.write(('%s\n') %('gradient, depth,width'))
snork= open('snorkel.csv')            
for line in snork:
    gradient,mndepth,mnwdth,crx,capt,known,ef = line.split(',')
    
    outdata.write(('%s,%s,%s\n') %(gradient, mndepth,mnwdth))

outdata.close()
snork.close()
print
print '********************************'

print 'functions'

#example of def

def mean(data):
    return sum(data)/float(len(data))
    #NOTE! without 'float' treats as integer division

#short cut method using lambda
xbar=lambda data:sum(data)/float(len(data))


#define list

x=[45,50,60,65,75]
print 'x=',x
#invoke functions

print 'mean(x)',mean(x)
print 'xbar(x)',xbar(x)
print
print
print 'using definitions together'

def fact(n):
    x=1
    for i in range(n,1,-1):
        x*=i
    return x

def comb(n,x):
    y=fact(n)/fact(x)/fact(n-x)
    return y

print '10 choose 5=', comb(10,5)
print
print
print 'combining functions into a class'
class combine:
    def fact(self,n):
        x=1
        for i in range(n,1,-1):
            x*=i
        return x
    def comb(self,n,x):
        y=fact(n)/fact(x)/fact(n-x)
        return y

#class instance
c=combine()
#invoking the bound method
print c.fact(10)
print c.comb(10,2)
print
print


print 'class / inheritances'

class mammal:
    #class representing mammals
    name='mammal'
    def lactate(self):
        print 'mammals lactate'
    def hair(self):
        print 'mammals have hair'
    def endothermy(self):
        print 'mammals are endothermic'

mammal().endothermy()

print
print





class marsupial(mammal):
    #inherits all attributes of class mammal
    name='marsupial'
    def placenta(self):
        print 'no placenta'

class placental(marsupial):
    #inherits from marsupial and mammal
    #replaces  name and placenta 
    name='placental'
    def placenta(self):
        print 'has a placenta'
print placental().name
placental().hair()
placental().placenta()
print
print
print
print
print 'special methods: enumerate'
#enumerate over and print index and value
print 'x=',x
print 'enumerate x'
for i,j in enumerate(x):
    print i,j
print
print
print 'another example this time with a string (this is useful in CR)'

hist='1001020'
print 'hist',hist
print 'enumerate hist'
for i,j in enumerate(hist):
    print i,j
print
print
print 'matrix operations'
inv=linalg.inv
det=linalg.det
eig=linalg.eig
A=mat([[5,6,7],[6,7,9],[9,10,11]])
B=inv(A)
print 'A=', A
print 'Inverse of A', B
print 'A*B=',A*B
print 'eigenvalues', eig(A)[0]
print 'eigenvectors',eig(A)[1]
print
print
print 'simualting random variables'
n=100
p=0.5
print 'single binomial variate with n=',n, 'and p=',p,'x=',binomial(n,p)
m=10
print m, ' binomial variates', binomial(n,p,m)
print
print
print 'binomial random variables with beta heterogeneity'
a=2
b=2
m=10
x=[binomial(n,beta(a,b)) for i in range(m)]
print '10 beta-binomial rvs', x








