Esempio n. 1
0
r = somefunc(x, y, z)
print r
# (40, [3, -1, 20], [[0, 0, 0], [0, 0, 0], [0, 0, 20]])
print "d^2(somefunc)/dzdx:", r[2][2][0]  # 0
print "d^2(somefunc)/dz^2:", r[2][2][2]  # 20

print "\n\ntesting interpolation:"
from Scientific.Functions.Interpolation import InterpolatingFunction as Ip

t = linspace(0, 10, 101)
v = sin(t)
vi = Ip((t,), v)
# interpolate and compare with exact result:
print "interpolated:", vi(5.05), " exact:", sin(5.05)
# interpolate the derivative of v:
vid = vi.derivative()
print "interpolated derivative:", vid(5.05), " exact:", cos(5.05)
# compute the integral of v over all t values:
print "definite integral:", vi.definiteIntegral(), " exact:", -cos(t[-1]) - (-cos(t[0]))

# add path to Grid2D (for testing interpolation on a 2D grid):
sys.path.insert(0, os.path.join(os.environ["scripting"], "src", "py", "examples"))
from Grid2D import Grid2D

g = Grid2D(dx=0.1, dy=0.2)
f = g(lambda x, y: sin(pi * x) * sin(pi * y))
fi = Ip((g.xcoor, g.ycoor), f)
# interpolate at (0.51,0.42) and compare with exact result:
print "interpolation in 2D grid:", fi(0.51, 0.42), " exact value:", sin(pi * 0.51) * sin(pi * 0.42)
# (0.94640171438438569, 0.96810522380784525)
Esempio n. 2
0
r = somefunc(x, y, z)
print r
# (40, [3, -1, 20], [[0, 0, 0], [0, 0, 0], [0, 0, 20]])
print "d^2(somefunc)/dzdx:", r[2][2][0]  # 0
print "d^2(somefunc)/dz^2:", r[2][2][2]  # 20

print "\n\ntesting interpolation:"
from Scientific.Functions.Interpolation \
     import InterpolatingFunction as Ip
t = sequence(0, 10, 0.1)
v = sin(t)
vi = Ip((t, ), v)
# interpolate and compare with exact result:
print "interpolated:", vi(5.05), " exact:", sin(5.05)
# interpolate the derivative of v:
vid = vi.derivative()
print "interpolated derivative:", vid(5.05), " exact:", cos(5.05)
# compute the integral of v over all t values:
print "definite integral:", vi.definiteIntegral(), \
      " exact:", -cos(t[-1]) - (-cos(t[0]))

# add path to Grid2D:
sys.path.insert(0,
                os.path.join(os.environ['scripting'], 'src', 'py', 'examples'))
from Grid2D import Grid2D
g = Grid2D(dx=0.1, dy=0.2)
f = g('sin(pi*x)*sin(pi*y)')
fi = Ip((g.xcoor, g.ycoor), f)
# interpolate at (0.51,0.42) and compare with exact result:
print "interpolation in 2D grid:", fi(0.51,0.42), \
      " exact value:", sin(pi*0.51)*sin(pi*0.42)
Esempio n. 3
0
class DensityMap:
    def __init__(self, filename):
        if filename is None:
            return
        filetype = os.path.splitext(filename)[1]
        if filetype.lower() == '.ezd':
            self.readEZD(filename)
        elif filetype.lower() == '.ccp4':
            self.readCCP4(filename)
        else:
            raise ValueError("Unknown file type %s" % filetype)
        self.map = None
        self.box = Box(
            Vector(self.x_axis[0], self.y_axis[0], self.z_axis[0]),
            Vector(self.x_axis[-1], self.y_axis[-1], self.z_axis[-1]))
        self.normalize()

    def readEZD(filename):
        file = open(filename)
        while 1:
            line = file.readline()
            if not line:
                raise IOError, "unexpected end of file"
            words = string.split(line)
            if words[0] == 'MAP':
                break
            if words[0] == 'CELL':
                cell_x, cell_y, cell_z, alpha, beta, gamma = \
                        map(float, words[1:])
                if alpha != 90. or beta != 90. or gamma != 90.:
                    raise ValueError, "cell must be rectangular"
            if words[0] == 'EXTENT':
                self.nx, self.ny, self.nz = map(float, words[1:])
            if words[0] == 'GRID':
                gnx, gny, gnz = map(float, words[1:])

        data = []
        while 1:
            line = file.readline()
            if not line:
                raise IOError, "unexpected end of file"
            line = string.join(string.split(line, '.-'), '. -')
            words = string.split(line)
            if words[0] == 'END':
                break
            for value in map(float, words):
                data.append(value)

        data = N.array(data)
        data.shape = (self.nz, self.ny, self.nx)
        self.data = N.transpose(data)
        self.x_axis = N.arange(self.nx) * (cell_x / gnx) * Units.Ang
        self.y_axis = N.arange(self.ny) * (cell_y / gny) * Units.Ang
        self.z_axis = N.arange(self.nz) * (cell_z / gnz) * Units.Ang

    def readCCP4(self, filename):
        mapfile = file(filename)
        header_data = mapfile.read(1024)
        NC, NR, NS, MODE, NCSTART, NRSTART, NSSTART, NX, NY, NZ, X, Y, Z, \
            ALPHA, BETA, GAMMA, MAPC, MAPR, MAPS, AMIN, AMAX, AMEAN, \
            ISPG, NSYMBT, LSKFLG = struct.unpack('=10l6f3l3f3l',
                                                 header_data[:4*25])
        if MODE == 2:
            byte_order = '='
        elif MODE == 33554432:
            NC, NR, NS, MODE, NCSTART, NRSTART, NSSTART, NX, NY, NZ, X, Y, Z, \
                ALPHA, BETA, GAMMA, MAPC, MAPR, MAPS, AMIN, AMAX, AMEAN, \
                ISPG, NSYMBT, LSKFLG = struct.unpack('>10l6f3l3f3l',
                                                     header_data[:4*25])
            byte_order = '>'
            if MODE == 33554432:
                NC, NR, NS, MODE, NCSTART, NRSTART, NSSTART, NX, NY, NZ, \
                    X, Y, Z, ALPHA, BETA, GAMMA, MAPC, MAPR, MAPS, \
                    AMIN, AMAX, AMEAN, ISPG, NSYMBT, LSKFLG \
                    = struct.unpack('<10l6f3l3f3l', header_data[:4*25])
                byte_order = '<'

        else:
            raise IOError("Not a mode 2 CCP4 map file")

        symmetry_data = mapfile.read(NSYMBT)
        map_data = mapfile.read(4 * NS * NR * NC)

        if byte_order == '=':
            array = N.fromstring(map_data, N.Float32, NC * NR * NS)
        else:
            array = N.zeros((NS * NR * NC, ), N.Float32)
            index = 0
            while len(map_data) >= 4 * 10000:
                values = struct.unpack(byte_order + '10000f',
                                       map_data[:4 * 10000])
                array[index:index + 10000] = N.array(values, N.Float32)
                index += 10000
                map_data = map_data[4 * 10000:]
            values = struct.unpack(byte_order + '%df' % (len(map_data) / 4),
                                   map_data)
            array[index:] = N.array(values, N.Float32)

        del map_data

        array.shape = (NS, NR, NC)
        self.data = N.transpose(array)

        resolution_x = X * Units.Ang / NX
        resolution_y = Y * Units.Ang / NY
        resolution_z = Z * Units.Ang / NZ

        self.x_axis = (NCSTART + N.arange(NC)) * resolution_x
        self.y_axis = (NRSTART + N.arange(NR)) * resolution_y
        self.z_axis = (NSSTART + N.arange(NS)) * resolution_z

    def __getitem__(self, item):
        if not isinstance(item, tuple) or len(item) != 3:
            raise ValueError("indexation requires three slices")
        sx, sy, sz = item
        if not (isinstance(sx, slice) and isinstance(sy, slice) \
                and isinstance(sz, slice)):
            raise ValueError("indexation requires three slices")
        new_map = DensityMap(None)
        new_map.data = self.data[sx, sy, sz]
        new_map.x_axis = self.x_axis[sx]
        new_map.y_axis = self.y_axis[sy]
        new_map.z_axis = self.z_axis[sz]
        new_map.map = None
        new_map.box = Box(
            Vector(new_map.x_axis[0], new_map.y_axis[0], new_map.z_axis[0]),
            Vector(new_map.x_axis[-1], new_map.y_axis[-1], new_map.z_axis[-1]))
        return new_map

    def normalize(self):
        self.data /= N.sum(N.ravel(self.data))

    def makePositive(self):
        min = N.minimum.reduce(N.ravel(self.data))
        if min < 0:
            nonzero_mask = self.data != 0
            self.data = (self.data - min) * nonzero_mask

    def _makeMapObjects(self):
        if self.map is None:
            self.map = InterpolatingFunction(
                (self.x_axis, self.y_axis, self.z_axis), self.data, 0.)
            self.map_gx = self.map.derivative(0)
            self.map_gy = self.map.derivative(1)
            self.map_gz = self.map.derivative(2)

    def center(self):
        self.map = None
        x_center = N.sum(
            N.ravel(self.x_axis[:, N.NewAxis, N.NewAxis] * self.data))
        y_center = N.sum(
            N.ravel(self.y_axis[N.NewAxis, :, N.NewAxis] * self.data))
        z_center = N.sum(
            N.ravel(self.z_axis[N.NewAxis, N.NewAxis, :] * self.data))
        self.x_axis = self.x_axis - x_center
        self.y_axis = self.y_axis - y_center
        self.z_axis = self.z_axis - z_center
        self.box = Box(
            Vector(self.x_axis[0], self.y_axis[0], self.z_axis[0]),
            Vector(self.x_axis[-1], self.y_axis[-1], self.z_axis[-1]))

    def principalAxes(self):
        r = self._rGrid()
        cm = N.sum(N.sum(N.sum(self.data[..., N.NewAxis] * r)))
        r = r - cm[N.NewAxis, N.NewAxis, N.NewAxis, :]
        nx, ny, nz = self.data.shape
        t = 0.
        for i in range(nx):  # make loops explicit to conserve memory
            for j in range(ny):
                for k in range(nz):
                    t = t + self.data[i, j, k] * r[i, j, k, N.NewAxis, :] * \
                        r[i, j, k, :, N.NewAxis]
        ev, axes = eigenvectors(t)
        return map(lambda a, b: (Vector(a), b), axes, ev)

    def principalPoints(self):
        (ex, vx), (ey, vy), (ez, vz) = self.principalAxes()
        axes = N.array([ex.array, ey.array, ez.array])
        r = self._rGrid()
        cm = N.sum(N.sum(N.sum(self.data[..., N.NewAxis] * r)))
        r = r - cm[N.NewAxis, N.NewAxis, N.NewAxis, :]
        regions = N.greater(N.dot(r, N.transpose(axes)), 0)
        regions = N.sum(N.array([[[[1, 2, 4]]]]) * regions, -1)
        points = []
        for i in range(8):
            mask = N.equal(regions, i)
            weight = N.sum(N.sum(N.sum(mask * self.data)))
            cmr = N.sum(N.sum(N.sum((mask*self.data)[..., N.NewAxis]*r))) \
                  / weight + cm
            points.append(Vector(cmr))
        return points

    def overlap(self, object):
        self._makeMapObjects()
        sum = 0.
        for a in object.atomList():
            x, y, z = a.position()
            sum = sum + self.map(x, y, z)
        return sum

    def gradient(self, object):
        self._makeMapObjects()
        g = ParticleVector(object.universe())
        for a in object.atomList():
            x, y, z = a.position()
            g[a] = Vector(self.map_gx(x, y, z), self.map_gy(x, y, z),
                          self.map_gz(x, y, z))
        return g

    def atomMap(self, object, r0=0.3):
        r = self._rGrid()
        atom_map = N.zeros(self.data.shape, N.Float)
        cutoff = 4. * r0
        for a in object.atomList():
            # An over-eager optimization: it should use
            # an enlarged box
            #if not self.box.enclosesPoint(a.position()):
            #    continue
            ra = a.position().array
            xi1 = N.sum(self.x_axis < ra[0] - cutoff)
            xi2 = N.sum(self.x_axis < ra[0] + cutoff)
            yi1 = N.sum(self.y_axis < ra[1] - cutoff)
            yi2 = N.sum(self.y_axis < ra[1] + cutoff)
            zi1 = N.sum(self.z_axis < ra[2] - cutoff)
            zi2 = N.sum(self.z_axis < ra[2] + cutoff)
            if xi2 > xi1 and yi2 > yi1 and zi2 > zi1:
                dr = r[xi1:xi2, yi1:yi2, zi1:zi2] - \
                     ra[N.NewAxis, N.NewAxis, N.NewAxis, :]
                w = N.exp(-0.5 * N.sum(dr**2, axis=-1) / r0**2)
                lmap = atom_map[xi1:xi2, yi1:yi2, zi1:zi2]
                N.add(lmap, w, lmap)
        N.divide(atom_map, N.sum(N.sum(N.sum(atom_map))), atom_map)
        return atom_map

    def fit(self, object, r0=0.4, w_neg=1.):
        diff = self.atomMap(object, r0) - self.data
        N.multiply(diff, 1. + (w_neg - 1.) * N.less(diff, 0.), diff)
        return N.sum(N.sum(N.sum(diff**2)))

    def fitWithGradient(self, object, r0=0.4, w_neg=1.):
        r = self._rGrid()
        atom_map = N.zeros(self.data.shape, N.Float)
        cutoff = 4. * r0
        for a in object.atomList():
            ra = a.position().array
            xi1 = N.sum(self.x_axis < ra[0] - cutoff)
            xi2 = N.sum(self.x_axis < ra[0] + cutoff)
            yi1 = N.sum(self.y_axis < ra[1] - cutoff)
            yi2 = N.sum(self.y_axis < ra[1] + cutoff)
            zi1 = N.sum(self.z_axis < ra[2] - cutoff)
            zi2 = N.sum(self.z_axis < ra[2] + cutoff)
            if xi2 > xi1 and yi2 > yi1 and zi2 > zi1:
                dr = r[xi1:xi2, yi1:yi2, zi1:zi2] - \
                     ra[N.NewAxis, N.NewAxis, N.NewAxis, :]
                w = N.exp(-0.5 * N.sum(dr**2, axis=-1) / r0**2)
                lmap = atom_map[xi1:xi2, yi1:yi2, zi1:zi2]
                N.add(lmap, w, lmap)
        norm_factor = 1. / N.sum(N.sum(N.sum(atom_map)))
        N.multiply(atom_map, norm_factor, atom_map)
        N.subtract(atom_map, self.data, atom_map)
        weight = 1. + (w_neg - 1.) * N.less(atom_map, 0.)
        N.multiply(atom_map, weight, atom_map)
        g = ParticleVector(object.universe())
        for a in object.atomList():
            ra = a.position().array
            xi1 = N.sum(self.x_axis < ra[0] - cutoff)
            xi2 = N.sum(self.x_axis < ra[0] + cutoff)
            yi1 = N.sum(self.y_axis < ra[1] - cutoff)
            yi2 = N.sum(self.y_axis < ra[1] + cutoff)
            zi1 = N.sum(self.z_axis < ra[2] - cutoff)
            zi2 = N.sum(self.z_axis < ra[2] + cutoff)
            if xi2 > xi1 and yi2 > yi1 and zi2 > zi1:
                dr = r[xi1:xi2, yi1:yi2, zi1:zi2] - \
                     ra[N.NewAxis, N.NewAxis, N.NewAxis, :]
                lmap = atom_map[xi1:xi2, yi1:yi2, zi1:zi2]
                lw = weight[xi1:xi2, yi1:yi2, zi1:zi2]
                w = N.exp(-0.5 * N.sum(dr**2, axis=-1) / r0**2)
                v = N.sum(
                    N.sum(
                        N.sum(lmap[..., N.NewAxis] * lw[..., N.NewAxis] * dr *
                              w[..., N.NewAxis])))
                g[a] = Vector(v)
        return N.sum(N.sum(N.sum(atom_map**2))), -2 * norm_factor * g / r0**2

    def _rGrid(self):
        x = N.add.outer(N.add.outer(self.x_axis, 0 * self.y_axis),
                        0 * self.z_axis)[..., N.NewAxis]
        y = N.add.outer(N.add.outer(0 * self.x_axis, self.y_axis),
                        0 * self.z_axis)[..., N.NewAxis]
        z = N.add.outer(N.add.outer(0 * self.x_axis, 0 * self.y_axis),
                        self.z_axis)[..., N.NewAxis]
        return N.concatenate((x, y, z), axis=-1)

    def clipBelow(self, cutoff):
        mask = self.clipMask(cutoff)
        self.data *= mask
        self.data /= N.add.reduce(N.ravel(self.data))
        self.map = None

    def clipAbove(self, cutoff):
        mask = self.clipMask(cutoff)
        self.data *= (1 - mask)
        self.data /= N.add.reduce(N.ravel(self.data))
        self.map = None

    def clipMask(self, cutoff):
        max_value = N.maximum.reduce(N.ravel(self.data))
        mask = N.greater_equal(self.data, cutoff * max_value)
        gradient_masks = []
        for i in range(len(mask.shape)):
            upper_index = i * index_expression[::] + index_expression[1::]
            lower_index = i * index_expression[::] + index_expression[:-1:]
            gmask1 = N.greater(self.data[upper_index], self.data[lower_index])
            gmask2 = N.greater(self.data[lower_index], self.data[upper_index])
            gradient_masks.append((gmask1, gmask2))
        while 1:
            new_mask = 0 * mask
            for i in range(len(mask.shape)):
                upper_index = i * index_expression[::] + index_expression[1::]
                lower_index = i * index_expression[::] + index_expression[:-1:]
                upper_mask, lower_mask = gradient_masks[i]
                N.logical_or(new_mask[upper_index],
                             N.logical_and(mask[lower_index], lower_mask),
                             new_mask[upper_index])
                N.logical_or(new_mask[lower_index],
                             N.logical_and(mask[upper_index], upper_mask),
                             new_mask[lower_index])
            N.logical_and(new_mask, N.logical_not(mask), new_mask)
            N.logical_or(mask, new_mask, mask)
            if N.sum(N.ravel(new_mask)) == 0:
                break
        return mask

    def dataDump(self, filename):
        outfile = file(filename, 'w')
        data = N.ravel(N.transpose(self.data))
        data = 10000. * data / N.maximum.reduce(data)
        data.shape = (len(data) / 7, 7)
        for line in data:
            for number in line:
                outfile.write('%.1f ' % number)
            outfile.write('\n')
        outfile.close()

    def writeVTK(self, filename):
        import pyvtk
        origin = N.array([self.x_axis[0], self.y_axis[0], self.z_axis[0]])
        spacing = N.array([self.x_axis[1], self.y_axis[1], self.z_axis[1]]) \
                  - origin
        values = pyvtk.Scalars(N.ravel(N.transpose(self.data)),
                               'electron density')
        data = pyvtk.VtkData(
            pyvtk.StructuredPoints(self.data.shape, origin, spacing),
            'Density map', pyvtk.PointData(values))
        data.tofile(filename, format='binary')

    def view(self, gmodule, lower, upper, file=None):
        scene = gmodule.Scene()
        scale = gmodule.ColorScale(1.)
        size = 0.5 * min(self.x_axis[1], self.y_axis[1], self.z_axis[1])
        for i in range(self.nx):
            for j in range(self.ny):
                for k in range(self.nz):
                    value = self.data[i, j, k]
                    if value > lower and value < upper:
                        center = Vector(self.x_axis[i], self.y_axis[j],
                                        self.z_axis[k])
                        m = gmodule.Material(diffuse_color=scale(value))
                        object = gmodule.Sphere(center, size, material=m)
                        scene.addObject(object)
        if file is None:
            scene.view()
        else:
            scene.writeToFile(file)

    def viewVMD(self, filename=None, pdb_filename=None):
        run_vmd = 0
        if filename is None:
            filename = tempfile.mktemp()
            run_vmd = 1
        file = open(filename, 'w')
        if pdb_filename is not None:
            file.write('mol load pdb %s\n' % pdb_filename)
        file.write('mol volume top "Electron Density" \\\n')
        x_origin = self.x_axis[0] / Units.Ang
        y_origin = self.y_axis[0] / Units.Ang
        z_origin = self.z_axis[0] / Units.Ang
        x_length = self.x_axis[-1] / Units.Ang - x_origin
        y_length = self.y_axis[-1] / Units.Ang - y_origin
        z_length = self.z_axis[-1] / Units.Ang - z_origin
        file.write('  {%f %f %f} \\\n' % (x_origin, y_origin, z_origin))
        file.write('  {%f 0. 0.} \\\n' % x_length)
        file.write('  {0. %f 0.} \\\n' % y_length)
        file.write('  {0. 0. %f} \\\n' % z_length)
        file.write('  %d %d %d \\\n' % self.data.shape)
        file.write('  {')
        factor = 1. / N.maximum.reduce(N.ravel(self.data))
        for iz in range(self.data.shape[2]):
            for iy in range(self.data.shape[1]):
                for ix in range(self.data.shape[0]):
                    file.write(str(factor * self.data[ix, iy, iz]) + ' ')
        file.write('}\n')
        file.write('mol addrep top\nmol modstyle 1 top isosurface\n')
        if run_vmd:
            file.write('file delete %s\n' % filename)
        file.close()
        if run_vmd:
            os.system('vmd -e ' + filename + ' 1> /dev/null 2>&1')

    def writeXPlor(self, filename):
        from Scientific.IO.FortranFormat import FortranFormat, FortranLine
        file = open(filename, 'w')
        file.write('\n       1 !NTITLE\n')
        file.write('REMARKS Electronic density map\n')
        data = [
            self.data.shape[0], 1, self.data.shape[0], self.data.shape[1], 1,
            self.data.shape[1], self.data.shape[2], 1, self.data.shape[2]
        ]
        file.write(str(FortranLine(data, '9I8')) + '\n')
        x = (self.x_axis[-1] - self.x_axis[0]) / Units.Ang
        y = (self.y_axis[-1] - self.y_axis[0]) / Units.Ang
        z = (self.z_axis[-1] - self.z_axis[0]) / Units.Ang
        data = [x, y, z] + 3 * [90.]
        file.write(str(FortranLine(data, '6E12.5')) + '\n')
        file.write('ZYX\n')
        map_data = N.ravel(self.data)
        map_data = map_data / N.maximum.reduce(map_data)
        average = N.sum(map_data) / len(map_data)
        sd = N.sqrt(N.sum((map_data - average)**2) / len(map_data))
        map_data.shape = self.data.shape
        for i in range(self.data.shape[2]):
            file.write(str(FortranLine([i], 'I8')) + '\n')
            data = list(N.ravel(N.transpose(map_data[:, :, i])))
            while data:
                file.write(str(FortranLine(data[:6],
                                           '%dE12.5' % min(6, len(data)))) \
                           + '\n')
                data = data[6:]
        file.write(str(FortranLine([-9999], 'I8')) + '\n')
        file.write(str(FortranLine([average, sd], '2(E12.4,1X)')) + '\n')
        file.close()