def perturb(rpath, wpath, kl_path, Z_path, dth_path, nkl):
    
    # inputs
    # Z_path   : where to write out the sample normal 
    # dth_path : where to write out the random rotation
    # nkl      : where to truncate the K-L expansion

    cdim, sdim, x, y, z = read_blade.read_coords(rpath)
    
    # translate blade random amount (rotate about x axis)
    random.seed()
    dth = random.randn(1)*pi/180*0.1/3.0
    for i in range(cdim):
        for j in range(sdim):
            r = sqrt(y[i,j]**2 + z[i,j]**2)
            th = math.atan2(z[i,j],y[i,j])
            y[i,j] = r*cos(th+dth)
            z[i,j] = r*sin(th+dth)

    # write out dth
    f = open(dth_path,'w')
    f.write('%e\n' % dth)
    f.close()
    
    # generate and write out the Z for this mesh
    random.seed() 
    Z = random.randn(nkl)    # normal distribution vector
    f = open(Z_path,'w')
    for i in range(nkl):
        f.write('%e\n' % Z[i])
    f.close()

    # read in PCA modes and singular values 
    lines = file(kl_path+'S.dat').readlines()
    S = array([line.strip().split()[0] for line in lines], float).T
    n_modes = len(S)
    fp = zeros((cdim,sdim))
    for i in range(nkl):
        cdim,sdim,V = read_blade.read_mode(kl_path+'V'+str(i+1)+'.dat')
        fp += Z[i]*sqrt(S[i])*V
     
    np = read_blade.calcNormals(x,y,z)
    
    xp = x + np[:,:,0]*fp
    yp = y + np[:,:,1]*fp
    zp = z + np[:,:,2]*fp
     
    # write out the blade surface
    f = open(wpath,'w')
    f.write('CDIM:       %d\n' % cdim)
    f.write('SDIM:       %d\n' % sdim)
    for i in arange(cdim):
        for j in arange(sdim):
            f.write('%20.8E' * 3 % (xp[i,j],yp[i,j],zp[i,j]))
            f.write('\n')
    
    f.close()

    # write out to tecplot format
    write_tecplot.write_blade_surf(xp,yp,zp,fp,'blade.dat')
def perturb(rpath, wpath, pca_path, scale, mode):

    # inputs
    # Z_path : where to write out the sample normal 
    # npca   : where to truncate the PCA expansion

    cdim, sdim, x, y, z = read_blade.read_coords(rpath)

    # perturb using only one of the transformed modes
    lines = file(pca_path+'S.dat').readlines()
    S = array([line.strip().split()[0] for line in lines], float).T
    fp = zeros((cdim,sdim))
    cdim,sdim,V = read_blade.read_mode(pca_path+'V'+str(mode)+'.dat')
    fp += scale*S[mode-1]*V
     
    np = read_blade.calcNormals(x,y,z)
    
    xp = x + np[:,:,0]*fp
    yp = y + np[:,:,1]*fp
    zp = z + np[:,:,2]*fp
     
    # write out the blade surface
    f = open(wpath,'w')
    f.write('CDIM:       %d\n' % cdim)
    f.write('SDIM:       %d\n' % sdim)
    for i in arange(cdim):
        for j in arange(sdim):
            f.write('%20.8E' * 3 % (xp[i,j],yp[i,j],zp[i,j]))
            f.write('\n')
    
    f.close()

    # test to see how they look
    '''
    i = 3
    cdim,sdim,V = read_blade.read_mode(pca_path+'V'+str(i+1)+'.dat')
    s, t = read_blade.xyz2st(x,y,z)
    print s[0],s[1]
    pylab.contourf(s,t,V.T,50)
    pylab.colorbar()
    pylab.show()
    '''
     
    '''
    fig = pylab.figure()
    ax = Axes3D(fig)
    surf = ax.plot_surface(sg, tg, fp, rstride=1, cstride=1, cmap = cm.jet)
    '''
    
    '''
    fig = pylab.figure()
    ax = Axes3D(fig)
    surf = ax.plot_surface(tg, sg, nf[1:-1,1:-1,2], rstride=1, cstride=1, cmap = cm.jet)
    # fig.colorbar(surf)
    '''

    ''' 
# mean of the Jacobians
meanJ = mean(stackJ,axis=0)

# compute SVD of stacked Jacobian
V,S,UT = linalg.svd(stackJ)

# read in the surface mesh
rpath = '/mnt/pwfiles/ericdow/random_blade/input/rotor37_coarse/blade_surf.dat'
cdim, sdim, x, y, z = read_blade.read_coords(rpath)

# read in the PCA modes
pca_path = '/mnt/pwfiles/ericdow/random_blade/input/rotor37_coarse/pca_modes_gp/'
V_pca = zeros((NZ,cdim,sdim))
for i in range(NZ):
    cdim,sdim,V_pca[i,:,:] = read_blade.read_mode(pca_path+'V'+str(i+1)+'.dat')

V_pca_tmp = zeros((NZ,cdim*sdim))
for i in range(NZ):
    V_pca_tmp[i,:] = reshape(V_pca[i,:,:],(cdim*sdim))

# transform the modes
V_trans_tmp = dot(dot(UT.T,eye(NZ)*S_pca),V_pca_tmp)

V_trans = zeros((NZ,cdim,sdim))
for i in range(NZ):
    V_trans[i,:,:] = reshape(V_trans_tmp[i,:],(cdim,sdim))

# write out the transformed modes
for imode in range(V_trans.shape[0]):
    fname = 'V'+str(imode+1)+'.dat'
pylab.xlabel('K-L mode index (i)')
pylab.ylabel('Average |dJ/dZ_i|')
pylab.title('Jacobian of speed-line shift with '+str(M)+' nearest neighbors')

# compute SVD of stacked Jacobian
V,S,UT = linalg.svd(stackJ)

# read in the surface mesh
rpath = '/mnt/pwfiles/ericdow/random_blade/input/rotor37_coarse/blade_surf.dat'
cdim, sdim, x, y, z = read_blade.read_coords(rpath)

# read in the K-L modes
kl_path = '/mnt/pwfiles/ericdow/random_blade/input/rotor37_coarse/kl_modes/'
V_kl = zeros((NZ,cdim,sdim))
for i in range(NZ):
    cdim,sdim,V_kl[i,:,:] = read_blade.read_mode(kl_path+'V'+str(i+1)+'.dat')

V_kl_tmp = zeros((NZ,cdim*sdim))
for i in range(NZ):
    V_kl_tmp[i,:] = reshape(V_kl[i,:,:],(cdim*sdim))

# transform the modes
V_trans_tmp = dot(dot(UT,eye(NZ)*S_kl),V_kl_tmp)

V_trans = zeros((NZ,cdim,sdim))
for i in range(NZ):
    V_trans[i,:,:] = reshape(V_trans_tmp[i,:],(cdim,sdim))

'''
# write out the transformed modes
for imode in range(V_trans.shape[0]):
def perturb(rpath, wpath, pca_path, Z_path, npca):

    # inputs
    # Z_path : where to write out the sample normal 
    # npca   : where to truncate the PCA expansion

    cdim, sdim, x, y, z = read_blade.read_coords(rpath)

    # generate and write out the Z for this mesh
    random.seed() 
    Z = random.randn(npca)    # normal distribution vector
    f = open(Z_path,'w')
    for i in range(npca):
        f.write('%e\n' % Z[i])
    f.close()

    ################################
    # SCALE PCA MODES BY CHORD RATIO
    ################################
    # r5_chord = 0.859 # inches at hub
    # r37_chord = 2.17 # inches at hub
    # scale = r37_chord/r5_chord
    scale = 1.0 

    # read in PCA modes and singular values 
    lines = file(pca_path+'S.dat').readlines()
    S = array([line.strip().split()[0] for line in lines], float).T
    n_modes = len(S)
    # add the mean
    cdim,sdim,fp = read_blade.read_mode(pca_path+'mean.dat')
    # add the PCA modes
    for i in range(npca):
        cdim,sdim,V = read_blade.read_mode(pca_path+'V'+str(i+1)+'.dat')
        fp += scale*Z[i]*S[i]*V
     
    np = read_blade.calcNormals(x,y,z)
    
    xp = x + np[:,:,0]*fp
    yp = y + np[:,:,1]*fp
    zp = z + np[:,:,2]*fp
     
    # write out the blade surface
    f = open(wpath,'w')
    f.write('CDIM:       %d\n' % cdim)
    f.write('SDIM:       %d\n' % sdim)
    for i in arange(cdim):
        for j in arange(sdim):
            f.write('%20.8E' * 3 % (xp[i,j],yp[i,j],zp[i,j]))
            f.write('\n')
    
    f.close()

    # write out to tecplot format
    # write_tecplot.write_blade_surf(xp,yp,zp,fp,'blade.dat')

    # test to see how they look
    '''
    i = 3
    cdim,sdim,V = read_blade.read_mode(pca_path+'V'+str(i+1)+'.dat')
    s, t = read_blade.xyz2st(x,y,z)
    print s[0],s[1]
    pylab.contourf(s,t,V.T,50)
    pylab.colorbar()
    pylab.show()
    '''
     
    '''
    fig = pylab.figure()
    ax = Axes3D(fig)
    surf = ax.plot_surface(sg, tg, fp, rstride=1, cstride=1, cmap = cm.jet)
    '''
    
    '''
    fig = pylab.figure()
    ax = Axes3D(fig)
    surf = ax.plot_surface(tg, sg, nf[1:-1,1:-1,2], rstride=1, cstride=1, cmap = cm.jet)
    # fig.colorbar(surf)
    '''

    '''