Beispiel #1
0
def init_motors():
    ###data structure to construct the rotation sign for rotary motor
    numSeg = 20
    rotS = map((lambda n: pi/2+n*2.0*pi/numSeg), range(numSeg*3/4 + 1))
    zOffset = 0.005
    scaleS = 0.4
    drawing_globals.rotS0n = rotS0n = map(
        (lambda a: (scaleS*cos(a), scaleS*sin(a), 0.0 - zOffset)), rotS)
    drawing_globals.rotS1n = rotS1n = map(
        (lambda a: (scaleS*cos(a), scaleS*sin(a), 1.0 + zOffset)), rotS)

    ###Linear motor arrow sign data structure
    drawing_globals.halfHeight = 0.45
    drawing_globals.halfEdge = halfEdge = 3.0 * scaleS * sin(pi/numSeg)

    arrow0Vertices = [
        (rotS0n[-1][0]-halfEdge, rotS0n[-1][1], rotS0n[-1][2]), 
        (rotS0n[-1][0]+halfEdge, rotS0n[-1][1], rotS0n[-1][2]), 
        (rotS0n[-1][0], rotS0n[-1][1] + 2.0*halfEdge, rotS0n[-1][2])]
    arrow0Vertices.reverse()
    drawing_globals.arrow0Vertices = arrow0Vertices

    drawing_globals.arrow1Vertices = [
        (rotS1n[-1][0]-halfEdge, rotS1n[-1][1], rotS1n[-1][2]), 
        (rotS1n[-1][0]+halfEdge, rotS1n[-1][1], rotS1n[-1][2]), 
        (rotS1n[-1][0], rotS1n[-1][1] + 2.0*halfEdge, rotS1n[-1][2])]

    drawing_globals.halfEdge = halfEdge = 1.0/3.0 ##1.0/8.0
    drawing_globals.linearArrowVertices = [
        (0.0, -halfEdge, 0.0), (0.0, halfEdge, 0.0), (0.0, 0.0,2*halfEdge)]

    return
Beispiel #2
0
def wpdg(series,detrend=0,win='triangle'):
    samples = Numeric.shape(series)[0]

    wrange = Numeric.arange(0,samples,dtype='d') / (samples - 1.0);

    if win == 'blackman':
        window = 0.42 - 0.5 * Numeric.cos(2*math.pi*wrange) + 0.08 * Numeric.cos(4*math.pi*wrange)
    elif win == 'sin4':
        window = Numeric.sin(math.pi*wrange)**4.0
    else:
        # if we don't recognize a window, default to triangle
        pdlen = (samples - 1) / 2.0
        window = 1.0 - abs(Numeric.arange(0,samples,dtype='d') - pdlen) / (pdlen)

    wseries = series.copy()

    if detrend == 1:
        leastsquares(wseries,detrend=1)
    
    wseries *= window

    weight = samples * Numeric.sum(window ** 2)
    wpdgram = pdg(wseries) * (1.0 * samples**2 / weight)

    return wpdgram
Beispiel #3
0
 def CalculateTorus(self, a, b, u, v):
     """calculate point on torus"""
     pi2 = 2 * pi
     #transformation function - torus
     cf = cos(pi2*u)
     sf = sin(pi2*u)
     ct = cos(pi2*v)
     st = sin(pi2*v)
     #point on torus
     return Triple((a+b*ct)*cf, (a+b*ct)*sf, b*st)
Beispiel #4
0
 def CalculateTorus(self, a, b, u, v):
     """calculate point on torus"""
     pi2 = 2 * pi
     #transformation function - torus
     cf = cos(pi2 * u)
     sf = sin(pi2 * u)
     ct = cos(pi2 * v)
     st = sin(pi2 * v)
     #point on torus
     return Triple((a + b * ct) * cf, (a + b * ct) * sf, b * st)
Beispiel #5
0
def rotz(angle):
    ret = numerix.identity(4).astype(numerix.Float)
    ret[0, 0] = ret[1, 1] = numerix.cos(angle)
    sn = numerix.sin(angle)
    ret[0, 1] = -sn
    ret[1, 0] = sn
    return ret
Beispiel #6
0
def _compute_ribbon_point(origin,
                          basesPerTurn, 
                          duplexRise, 
                          unitVectorAlongLength,
                          unitVectorAlongLadderStep,
                          unitDepthVector,
                          peakDeviationFromCenter,
                          numberOfBasesDrawn , 
                          theta_offset
                          ):
    """
    """
    ##handedness = -1    
    ##theta_offset = 0.0
    #turn_angle = twistPerBase
    ##turn_angle = (handedness * 2 * pi) / basesPerTurn
    turn_angle = (2 * pi) / basesPerTurn
##    axial_offset = unitVectorAlongLength * duplexRise 
    cY = unitVectorAlongLadderStep 
    cZ = unitDepthVector

    theta = turn_angle * numberOfBasesDrawn + theta_offset # in radians
    y = cos(theta) * peakDeviationFromCenter 
    z = sin(theta) * peakDeviationFromCenter
##    vx = axial_offset # a Vector
    p = origin + y * cY + z * cZ
    return p
Beispiel #7
0
def polarToCartesian(rtp):
    """
    Convert polar coordinate array to cartesian coordinate array: 
    C{ r, S{theta}, S{phi} -> x,y,z }

    @param rtp: array of cartesian coordinates (r, theta, phi)
    @type  rtp: array

    @return: array of cartesian coordinates (x, y, z)
    @rtype: array
    """
    x = rtp[:, 0] * N.cos(rtp[:, 1]) * N.sin(rtp[:, 2])
    y = rtp[:, 0] * N.sin(rtp[:, 1]) * N.sin(rtp[:, 2])
    z = rtp[:, 0] * N.cos(rtp[:, 2])

    return N.transpose(N.concatenate(([x], [y], [z])))
Beispiel #8
0
def rotz(angle):
    ret = numerix.identity(4).astype(numerix.Float)
    ret[0,0] = ret[1,1] = numerix.cos(angle)
    sn = numerix.sin(angle)
    ret[0,1] = -sn
    ret[1,0] = sn
    return ret
Beispiel #9
0
def polarToCartesian( rtp ):
    """
    Convert polar coordinate array to cartesian coordinate array: 
    C{ r, S{theta}, S{phi} -> x,y,z }

    @param rtp: array of cartesian coordinates (r, theta, phi)
    @type  rtp: array

    @return: array of cartesian coordinates (x, y, z)
    @rtype: array
    """
    x = rtp[:,0] * N.cos( rtp[:,1] ) * N.sin( rtp[:,2] )
    y = rtp[:,0] * N.sin( rtp[:,1] ) * N.sin( rtp[:,2] )
    z = rtp[:,0] * N.cos( rtp[:,2] )

    return N.transpose( N.concatenate( ([x],[y],[z]) ) )
Beispiel #10
0
 def setangle(self, theta):
     """
     Set the quaternion's rotation to theta (destructive modification).
     (In the same direction as before.)
     """
     theta = Numeric.remainder(theta / 2.0, math.pi)
     self.vec[1:] = norm(self.vec[1:]) * Numeric.sin(theta)
     self.vec[0] = Numeric.cos(theta)
     self.__reset()
     return self
Beispiel #11
0
def proj2sphere(x, y):
    """
    project a point from a tangent plane onto a unit sphere
    """
    d = (x*x + y*y) ** .5
    theta = math.pi * 0.5 * d
    s = Numeric.sin(theta)
    if d > 0.0001:
        return V(s*x/d, s*y/d, Numeric.cos(theta))
    else:
        return V(0.0, 0.0, 1.0)
Beispiel #12
0
def eulerRotation(alpha, beta, gamma):
    """
    Builds a rotation matrix from successive rotations:
      1. rotation about y-axis by angle alpha
      2. rotation about x-axis by angle beta
      3. rotation about z-axis by angle gamma

    @author: Michael Habeck

    @param alpha: euler angle S{alpha}
    @type  alpha: float
    @param beta: euler angle S{beta}
    @type  beta: float
    @param gamma: euler angle S{gamma}
    @type  gamma: float

    @return: 3 x 3 array of float
    @rtype: array
    """
    cos_alpha = N.cos(alpha)
    sin_alpha = N.sin(alpha)
    cos_beta = N.cos(beta)
    sin_beta = N.sin(beta)
    cos_gamma = N.cos(gamma)
    sin_gamma = N.sin(gamma)

    R = N.zeros((3, 3), N.Float32)

    R[0][0] = cos_gamma * cos_alpha - sin_gamma * cos_beta * sin_alpha
    R[0][1] = cos_gamma * sin_alpha + sin_gamma * cos_beta * cos_alpha
    R[0][2] = sin_gamma * sin_beta

    R[1][0] = -sin_gamma * cos_alpha - cos_gamma * cos_beta * sin_alpha
    R[1][1] = -sin_gamma * sin_alpha + cos_gamma * cos_beta * cos_alpha
    R[1][2] = cos_gamma * sin_beta

    R[2][0] = sin_beta * sin_alpha
    R[2][1] = -sin_beta * cos_alpha
    R[2][2] = cos_beta

    return R
Beispiel #13
0
def gabor(x, y, xsigma, ysigma, frequency, phase):
    """
    Gabor pattern (sine grating multiplied by a circular Gaussian).
    """
    if xsigma == 0.0 or ysigma == 0.0:
        return x * 0.0

    with float_error_ignore():
        x_w = divide(x, xsigma)
        y_h = divide(y, ysigma)
        p = exp(-0.5 * x_w * x_w + -0.5 * y_h * y_h)
    return p * 0.5 * cos(2 * pi * frequency * y + phase)
Beispiel #14
0
def gabor(x, y, xsigma, ysigma, frequency, phase):
    """
    Gabor pattern (sine grating multiplied by a circular Gaussian).
    """
    if xsigma==0.0 or ysigma==0.0:
        return x*0.0
    
    with float_error_ignore():
        x_w = divide(x,xsigma)
        y_h = divide(y,ysigma)
        p = exp(-0.5*x_w*x_w + -0.5*y_h*y_h)
    return p * 0.5*cos(2*pi*frequency*y + phase)
Beispiel #15
0
def rotxyz(angles):
    ret = numerix.identity(4).astype(numerix.Float)
    
    ret[1,1] = ret[2,2] = numerix.cos(angles[0])
    sn = numerix.sin(angles[0])
    ret[1,2] = -sn
    ret[2,1] = sn
    
    cs = numerix.cos(angles[1])
    ret[0,0] = cs
    ret[2,2] += cs
    sn = numerix.sin(angles[1])
    ret[0,2] = sn
    ret[2,0] = -sn

    cs = numerix.cos(angles[2])
    ret[0,0] += cs
    ret[1,1] += cs
    sn = numerix.sin(angles[2])
    ret[0,1] = -sn
    ret[1,0] = sn
    return ret
Beispiel #16
0
def rotxyz(angles):
    ret = numerix.identity(4).astype(numerix.Float)

    ret[1, 1] = ret[2, 2] = numerix.cos(angles[0])
    sn = numerix.sin(angles[0])
    ret[1, 2] = -sn
    ret[2, 1] = sn

    cs = numerix.cos(angles[1])
    ret[0, 0] = cs
    ret[2, 2] += cs
    sn = numerix.sin(angles[1])
    ret[0, 2] = sn
    ret[2, 0] = -sn

    cs = numerix.cos(angles[2])
    ret[0, 0] += cs
    ret[1, 1] += cs
    sn = numerix.sin(angles[2])
    ret[0, 1] = -sn
    ret[1, 0] = sn
    return ret
Beispiel #17
0
def eulerRotation(alpha, beta, gamma):
    """
    Builds a rotation matrix from successive rotations:
      1. rotation about y-axis by angle alpha
      2. rotation about x-axis by angle beta
      3. rotation about z-axis by angle gamma

    @author: Michael Habeck

    @param alpha: euler angle S{alpha}
    @type  alpha: float
    @param beta: euler angle S{beta}
    @type  beta: float
    @param gamma: euler angle S{gamma}
    @type  gamma: float

    @return: 3 x 3 array of float
    @rtype: array
    """
    cos_alpha = N.cos(alpha); sin_alpha = N.sin(alpha)
    cos_beta  = N.cos(beta);  sin_beta  = N.sin(beta)
    cos_gamma = N.cos(gamma); sin_gamma = N.sin(gamma)

    R = N.zeros((3,3), N.Float32)

    R[0][0] = cos_gamma * cos_alpha - sin_gamma * cos_beta * sin_alpha
    R[0][1] = cos_gamma * sin_alpha + sin_gamma * cos_beta * cos_alpha
    R[0][2] = sin_gamma * sin_beta

    R[1][0] = -sin_gamma * cos_alpha - cos_gamma * cos_beta * sin_alpha
    R[1][1] = -sin_gamma * sin_alpha + cos_gamma * cos_beta * cos_alpha
    R[1][2] =  cos_gamma * sin_beta

    R[2][0] =  sin_beta * sin_alpha
    R[2][1] = -sin_beta * cos_alpha
    R[2][2] =  cos_beta

    return R
Beispiel #18
0
def init_cyls():
    # generate two circles in space as 13-gons, one rotated half a segment with
    # respect to the other these are used as cylinder ends [not quite true
    # anymore, see comments just below]
    slices = 13
    circ1 = map((lambda n: n*2.0*pi/slices), range(slices+1))
    circ2 = map((lambda a: a+pi/slices), circ1)
    drawing_globals.drum0 = drum0 = map((lambda a: (cos(a), sin(a), 0.0)),
                                        circ1)
    drum1 = map((lambda a: (cos(a), sin(a), 1.0)), circ2)
    drum1n = map((lambda a: (cos(a), sin(a), 0.0)), circ2)

    #grantham 20051213 I finally decided the look of the oddly twisted cylinder
    # bonds was not pretty enough, so I made a "drum2" which is just drum0 with
    # a 1.0 Z coordinate, a la drum1.
    #bruce 060609: this apparently introduced the bug of the drum1 end-cap of a
    # cylinder being "ragged" (letting empty space show through), which I fixed
    # by using drum2 for that cap rather than drum1.  drum1 is no longer used
    # except as an intermediate value in the next few lines.
    drawing_globals.drum2 = drum2 = map((lambda a: (cos(a), sin(a), 1.0)),
                                        circ1)

    # This edge list zips up the "top" vertex and normal and then the "bottom"
    # vertex and normal.  Thus each tuple in the sequence would be (vtop, ntop,
    # vbot, nbot) [grantham 20051213]
    # (bruce 051215 simplified the python usage in a way which should create the
    # same list.)
    drawing_globals.cylinderEdges = zip(drum0, drum0, drum2, drum0)

    circle = zip(drum0[:-1],drum0[1:],drum1[:-1]) +\
           zip(drum1[:-1],drum0[1:],drum1[1:])
    circlen = zip(drum0[:-1],drum0[1:],drum1n[:-1]) +\
            zip(drum1n[:-1],drum0[1:],drum1n[1:])

    drawing_globals.cap0n = (0.0, 0.0, -1.0)
    drawing_globals.cap1n = (0.0, 0.0, 1.0)
    drum0.reverse()
    return
Beispiel #19
0
    def setUp(self):
        from opengltk.OpenGL import GL, GLUT
        print "GL imported from: ", GL.__file__
        #print "Hit any key to quit."
        self.x = RandomArray.random( NUMDOTS) * 2 - 1
        self.y = RandomArray.random( NUMDOTS) * 2 - 1

        self.age = RandomArray.randint( 0,MAX_AGE, (NUMDOTS,))
        move_length = 0.005  # 1.0 = screen width
        angle = 0		 # in radians
        delta_angle = 0.2  # in radians
        self.move_x = move_length * Numeric.cos( angle)
        self.move_y = move_length * Numeric.sin( angle)
        self.halted = 0
Beispiel #20
0
    def drawLines(self):
        # angle has to be provided in radians
        angle = self.angle

        self.circlePtsAngles = self.circlePtsAngles + angle
        self.circlePtsAngles = Numeric.remainder(self.circlePtsAngles,
                                                 2 * math.pi)
        xcoords = Numeric.cos(self.circlePtsAngles)
        xsin = Numeric.sin(self.circlePtsAngles)
        if self.orient == 'horizontal':
            w = self.innerbox[2] - self.innerbox[0]
            r = w / 2
            c = self.innerbox[0] + r
            y1 = self.innerbox[1]
            y2 = self.innerbox[3]
        else:
            w = self.innerbox[3] - self.innerbox[1]
            r = w / 2
            c = self.innerbox[1] + r
            y1 = self.innerbox[0]
            y2 = self.innerbox[2]

        cl = self.canvas.create_line
        setCoords = self.canvas.coords
        setOpt = self.canvas.itemconfigure
        pi2 = math.pi / 2.
        drawLines = 0
        co = Numeric.take(xcoords,
                          Numeric.nonzero(Numeric.greater_equal(xsin, 0.0)))
        co = Numeric.sort(co)
        co = [-1] + list(co)
        for i in range(len(co)):
            x = c - int(co[i] * r)
            if self.orient == 'horizontal':
                setCoords(self.linesIds[i], x, y1, x, y2)
            else:
                setCoords(self.linesIds[i], y1, x, y2, x)
            shopt = self.shadowLinesOptions[i]
            x = x + shopt[0]
            if self.orient == 'horizontal':
                setCoords(self.shLinesIds[i], x, y1, x, y2)
            else:
                setCoords(self.shLinesIds[i], y1, x, y2, x)
            setOpt(self.shLinesIds[i], fill=shopt[1], width=shopt[2])
Beispiel #21
0
 def drawLines(self):
     # angle has to be provided in radians
     angle = self.angle
         
     self.circlePtsAngles = self.circlePtsAngles+angle
     self.circlePtsAngles = Numeric.remainder(self.circlePtsAngles,
                                              2*math.pi)
     xcoords = Numeric.cos(self.circlePtsAngles)
     xsin = Numeric.sin(self.circlePtsAngles)
     if self.orient=='horizontal':
         w = self.innerbox[2] - self.innerbox[0]
         r = w/2
         c = self.innerbox[0] + r
         y1 = self.innerbox[1]
         y2 = self.innerbox[3]
     else:
         w = self.innerbox[3] - self.innerbox[1]
         r = w/2
         c = self.innerbox[1] + r
         y1 = self.innerbox[0]
         y2 = self.innerbox[2]
         
     cl = self.canvas.create_line
     setCoords = self.canvas.coords
     setOpt = self.canvas.itemconfigure
     pi2 = math.pi/2.
     drawLines = 0
     co = Numeric.take(xcoords,
                       Numeric.nonzero(Numeric.greater_equal(xsin, 0.0)))
     co = Numeric.sort(co)
     co = [-1]+list(co)
     for i in range(len(co)):
         x = c - int(co[i]*r)
         if self.orient=='horizontal':
             setCoords(self.linesIds[i], x, y1, x, y2)
         else:
             setCoords(self.linesIds[i], y1, x, y2, x)
         shopt = self.shadowLinesOptions[i]
         x = x + shopt[0]
         if self.orient=='horizontal':
             setCoords(self.shLinesIds[i], x, y1, x, y2)
         else:
             setCoords(self.shLinesIds[i], y1, x, y2, x)
         setOpt(self.shLinesIds[i], fill = shopt[1], width=shopt[2])
    def __call__(self,**params):
        p=ParamOverrides(self,params)

        for template in p.plot_template:

            for sheet in topo.sim.objects(Sheet).values():
                name=template.keys().pop(0)
                plot=make_template_plot(template,sheet.sheet_views,sheet.xdensity,sheet.bounds,p.normalize,name=template[name])
                if plot:
                    bitmap=plot.bitmap
                    pylab.figure(figsize=(5,5))
                    isint=pylab.isinteractive() # Temporarily make non-interactive for plotting
                    pylab.ioff()                                         # Turn interactive mode off

                    pylab.imshow(bitmap.image,origin='lower',interpolation='nearest')
                    pylab.axis('off')

                    for (t,pref,sel,c) in p.overlay:
                        v = pylab.flipud(sheet.sheet_views[pref].view()[0])

                        if (t=='contours'):
                            pylab.contour(v,[sel,sel],colors=c,linewidths=2)

                        if (t=='arrows'):
                            s = pylab.flipud(sheet.sheet_views[sel].view()[0])
                            scale=int(pylab.ceil(log10(len(v))))
                            X=pylab.array([x for x in xrange(len(v)/scale)])
                            v_sc=pylab.zeros((len(v)/scale,len(v)/scale))
                            s_sc=pylab.zeros((len(v)/scale,len(v)/scale))
                            for i in X:
                                for j in X:
                                    v_sc[i][j]=v[scale*i][scale*j]
                                    s_sc[i][j]=s[scale*i][scale*j]
                            pylab.quiver(scale*X,scale*X,-cos(2*pi*v_sc)*s_sc,-sin(2*pi*v_sc)*s_sc,color=c,edgecolors=c,minshaft=3,linewidths=1)

                    p.title='%s overlaid with %s at time %s' %(plot.name,pref,topo.sim.timestr())
                    if isint: pylab.ion()
                    p.filename_suffix="_"+sheet.name
                    self._generate_figure(p)
Beispiel #23
0
def rotateAxis(theta, vector):
    """
    Calculate a left multiplying rotation matrix that rotates
    theta rad around vector.

    Taken from: http://osdir.com/ml/python.bio.devel/2008-09/msg00084.html

    Example:

    >>> m=rotateAxis(pi, N.array([1,0,0]))

    @type theta: float
    @param theta: the rotation angle


    @type vector: L{Vector}
    @param vector: the rotation axis

    @return: The rotation matrix, a 3x3 Numeric array.
    """
    vector = vector / N.linalg.norm(vector)
    x, y, z = vector
    c = N.cos(theta)
    s = N.sin(theta)
    t = 1 - c
    rot = N.zeros((3, 3), "d")
    # 1st row
    rot[0, 0] = t * x * x + c
    rot[0, 1] = t * x * y - s * z
    rot[0, 2] = t * x * z + s * y
    # 2nd row
    rot[1, 0] = t * x * y + s * z
    rot[1, 1] = t * y * y + c
    rot[1, 2] = t * y * z - s * x
    # 3rd row
    rot[2, 0] = t * x * z - s * y
    rot[2, 1] = t * y * z + s * x
    rot[2, 2] = t * z * z + c
    return rot
Beispiel #24
0
def rotateAxis(theta, vector):
    """
    Calculate a left multiplying rotation matrix that rotates
    theta rad around vector.

    Taken from: http://osdir.com/ml/python.bio.devel/2008-09/msg00084.html

    Example:

    >>> m=rotateAxis(pi, N.array([1,0,0]))

    @type theta: float
    @param theta: the rotation angle


    @type vector: L{Vector}
    @param vector: the rotation axis

    @return: The rotation matrix, a 3x3 Numeric array.
    """
    vector = vector / N.linalg.norm(vector)
    x,y,z=vector
    c=N.cos(theta)
    s=N.sin(theta)
    t=1-c
    rot=N.zeros((3,3), "d")
    # 1st row
    rot[0,0]=t*x*x+c
    rot[0,1]=t*x*y-s*z
    rot[0,2]=t*x*z+s*y
    # 2nd row
    rot[1,0]=t*x*y+s*z
    rot[1,1]=t*y*y+c
    rot[1,2]=t*y*z-s*x
    # 3rd row
    rot[2,0]=t*x*z-s*y
    rot[2,1]=t*y*z+s*x
    rot[2,2]=t*z*z+c
    return rot
Beispiel #25
0
    def draw(self):
        p = self.parameters # shorthand
        if p.on:
            # calculate center
            center = VisionEgg._get_center(p.position,p.anchor,(p.radius, p.radius))
            gl.glDisable(gl.GL_DEPTH_TEST)
            gl.glDisable(gl.GL_TEXTURE_2D)
            gl.glDisable(gl.GL_BLEND)

            if len(p.color)==3:
                gl.glColor3f(*p.color)
            elif len(p.color)==4:
                gl.glColor4f(*p.color)

          # Build filled circle from points
#           gl.glBegin(gl.GL_POINTS)
#           radius = int(math.ceil(p.radius))
#           for i in range(-radius, radius):
#               for j in range(-radius, radius):
#                   if(i * i + j * j < radius * radius):
#                       gl.glVertex3f(p.position[0] + i, p.position[1] + j, 0.0)
#           gl.glEnd() # GL_POINTS

            # Build filled circle from triangles (this is typically faster
            # then the commented code above with the points)
            gl.glBegin(gl.GL_TRIANGLE_FAN)
            gl.glVertex3f(p.position[0], p.position[1], 0.0)
            angles = Numeric.arange(p.num_triangles)/float(p.num_triangles)*2.0*math.pi
            verts = Numeric.zeros( (p.num_triangles,2), Numeric.Float )
            verts[:,0] = p.position[0] + p.radius * Numeric.cos(angles)
            verts[:,1] = p.position[1] + p.radius * Numeric.sin(angles)
            for i in range(verts.shape[0]):
                gl.glVertex2fv(verts[i])
            gl.glVertex2fv(verts[0])

            gl.glEnd() # GL_TRIANGLE_FAN
            if p.anti_aliasing:
                if not self._gave_alpha_warning:
                    if len(p.color) > 3 and p.color[3] != 1.0:
                        logger = logging.getLogger('VisionEgg.Arrow')
                        logger.warning("The parameter anti_aliasing is "
                                       "set to true in the Arrow "
                                       "stimulus class, but the color "
                                       "parameter specifies an alpha "
                                       "value other than 1.0.  To "
                                       "acheive anti-aliasing, ensure "
                                       "that the alpha value for the "
                                       "color parameter is 1.0.")
                        self._gave_alpha_warning = 1

                        # We've already drawn a filled polygon (aliased), now redraw
                        # the outline of the polygon (with anti-aliasing). (Using
                        # GL_POLYGON_SMOOTH results in artifactual lines where
                        # triangles were joined to create quad, at least on some OpenGL
                        # implementations.)

                # Calculate coverage value for each pixel of outline
                # and store as alpha
                gl.glEnable(gl.GL_LINE_SMOOTH)
                # Now specify how to use the alpha value
                gl.glBlendFunc(gl.GL_SRC_ALPHA,gl.GL_ONE_MINUS_SRC_ALPHA)
                gl.glEnable(gl.GL_BLEND)

                # Draw a second polygon in line mode, so the edges are anti-aliased
                gl.glPolygonMode(gl.GL_FRONT_AND_BACK,gl.GL_LINE)
                gl.glBegin(gl.GL_TRIANGLE_FAN)
                gl.glVertex3f(p.position[0], p.position[1], 0.0)
                angles = Numeric.arange(p.num_triangles)/float(p.num_triangles)*2.0*math.pi
                verts = Numeric.zeros( (p.num_triangles,2), Numeric.Float )
                verts[:,0] = p.position[0] + p.radius * Numeric.cos(angles)
                verts[:,1] = p.position[1] + p.radius * Numeric.sin(angles)
                for i in range(verts.shape[0]):
                    gl.glVertex2fv(verts[i])
                gl.glVertex2fv(verts[0])
                gl.glEnd() # GL_TRIANGLE_FAN

                # Set the polygon mode back to fill mode
                gl.glPolygonMode(gl.GL_FRONT_AND_BACK,gl.GL_FILL)
                gl.glDisable(gl.GL_LINE_SMOOTH)
Beispiel #26
0
    def draw(self):
        p = self.parameters  # shorthand
        if p.on:
            # calculate center
            center = VisionEgg._get_center(p.position, p.anchor,
                                           (p.radius, p.radius))
            gl.glDisable(gl.GL_DEPTH_TEST)
            gl.glDisable(gl.GL_TEXTURE_2D)
            gl.glDisable(gl.GL_BLEND)

            if len(p.color) == 3:
                gl.glColor3f(*p.color)
            elif len(p.color) == 4:
                gl.glColor4f(*p.color)

        # Build filled circle from points
#           gl.glBegin(gl.GL_POINTS)
#           radius = int(math.ceil(p.radius))
#           for i in range(-radius, radius):
#               for j in range(-radius, radius):
#                   if(i * i + j * j < radius * radius):
#                       gl.glVertex3f(p.position[0] + i, p.position[1] + j, 0.0)
#           gl.glEnd() # GL_POINTS

# Build filled circle from triangles (this is typically faster
# then the commented code above with the points)
            gl.glBegin(gl.GL_TRIANGLE_FAN)
            gl.glVertex3f(p.position[0], p.position[1], 0.0)
            angles = Numeric.arange(p.num_triangles) / float(
                p.num_triangles) * 2.0 * math.pi
            verts = Numeric.zeros((p.num_triangles, 2), Numeric.Float)
            verts[:, 0] = p.position[0] + p.radius * Numeric.cos(angles)
            verts[:, 1] = p.position[1] + p.radius * Numeric.sin(angles)
            for i in range(verts.shape[0]):
                gl.glVertex2fv(verts[i])
            gl.glVertex2fv(verts[0])

            gl.glEnd()  # GL_TRIANGLE_FAN
            if p.anti_aliasing:
                if not self._gave_alpha_warning:
                    if len(p.color) > 3 and p.color[3] != 1.0:
                        logger = logging.getLogger('VisionEgg.Arrow')
                        logger.warning("The parameter anti_aliasing is "
                                       "set to true in the Arrow "
                                       "stimulus class, but the color "
                                       "parameter specifies an alpha "
                                       "value other than 1.0.  To "
                                       "acheive anti-aliasing, ensure "
                                       "that the alpha value for the "
                                       "color parameter is 1.0.")
                        self._gave_alpha_warning = 1

                        # We've already drawn a filled polygon (aliased), now redraw
                        # the outline of the polygon (with anti-aliasing). (Using
                        # GL_POLYGON_SMOOTH results in artifactual lines where
                        # triangles were joined to create quad, at least on some OpenGL
                        # implementations.)

                # Calculate coverage value for each pixel of outline
                # and store as alpha
                gl.glEnable(gl.GL_LINE_SMOOTH)
                # Now specify how to use the alpha value
                gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
                gl.glEnable(gl.GL_BLEND)

                # Draw a second polygon in line mode, so the edges are anti-aliased
                gl.glPolygonMode(gl.GL_FRONT_AND_BACK, gl.GL_LINE)
                gl.glBegin(gl.GL_TRIANGLE_FAN)
                gl.glVertex3f(p.position[0], p.position[1], 0.0)
                angles = Numeric.arange(p.num_triangles) / float(
                    p.num_triangles) * 2.0 * math.pi
                verts = Numeric.zeros((p.num_triangles, 2), Numeric.Float)
                verts[:, 0] = p.position[0] + p.radius * Numeric.cos(angles)
                verts[:, 1] = p.position[1] + p.radius * Numeric.sin(angles)
                for i in range(verts.shape[0]):
                    gl.glVertex2fv(verts[i])
                gl.glVertex2fv(verts[0])
                gl.glEnd()  # GL_TRIANGLE_FAN

                # Set the polygon mode back to fill mode
                gl.glPolygonMode(gl.GL_FRONT_AND_BACK, gl.GL_FILL)
                gl.glDisable(gl.GL_LINE_SMOOTH)
Beispiel #27
0
    def addInternal(self, i, na, nb, nc, r, theta, phi):
        """
        Add another point, given its internal coordinates.  Once added
        via this routine, the cartesian coordinates for the point can
        be retrieved with getCartesian().

        @param i: Index of the point being added.  After this call, a
                  call to getCartesian with this index value will
                  succeed.  Index values less than 4 are ignored.
                  Index values should be presented here in sequence
                  beginning with 4.

        @param na: Index value for point A.  Point 'i' will be 'r'
                   distance units from point A.

        @param nb: Index value for point B.  Point 'i' will be located
                   such that the angle i-A-B is 'theta' degrees.

        @param nc: Index value for point C.  Point 'i' will be located
                      such that the torsion angle i-A-B-C is 'torsion'
                      degrees.

        @param r: Radial distance (in same units as resulting
                  cartesian coordinates) between A and i.

        @param theta: Angle in degrees of i-A-B.

        @param phi: Torsion angle in degrees of i-A-B-C
        """

        if (i < 4):
            return

        if (i != self._nextIndex):
            raise IndexError, "next index is %d not %r" % (self._nextIndex, i)

        cos_theta = cos(DEG2RAD * theta)
        xb = self._coords[nb][0] - self._coords[na][0]
        yb = self._coords[nb][1] - self._coords[na][1]
        zb = self._coords[nb][2] - self._coords[na][2]
        rba = 1.0 / sqrt(xb * xb + yb * yb + zb * zb)

        if abs(cos_theta) >= 0.999:
            # Linear case
            # Skip angles, just extend along A-B.
            rba = r * rba * cos_theta
            xqd = xb * rba
            yqd = yb * rba
            zqd = zb * rba
        else:
            xc = self._coords[nc][0] - self._coords[na][0]
            yc = self._coords[nc][1] - self._coords[na][1]
            zc = self._coords[nc][2] - self._coords[na][2]

            xyb = sqrt(xb * xb + yb * yb)

            inv = False
            if xyb < 0.001:
                # A-B points along the z axis.
                tmp = zc
                zc = -xc
                xc = tmp
                tmp = zb
                zb = -xb
                xb = tmp
                xyb = sqrt(xb * xb + yb * yb)
                inv = True

            costh = xb / xyb
            sinth = yb / xyb
            xpc = xc * costh + yc * sinth
            ypc = yc * costh - xc * sinth
            sinph = zb * rba
            cosph = sqrt(abs(1.0 - sinph * sinph))
            xqa = xpc * cosph + zc * sinph
            zqa = zc * cosph - xpc * sinph
            yzc = sqrt(ypc * ypc + zqa * zqa)
            if yzc < 1e-8:
                coskh = 1.0
                sinkh = 0.0
            else:
                coskh = ypc / yzc
                sinkh = zqa / yzc

            sin_theta = sin(DEG2RAD * theta)
            sin_phi = -sin(DEG2RAD * phi)
            cos_phi = cos(DEG2RAD * phi)

            # Apply the bond length.
            xd = r * cos_theta
            yd = r * sin_theta * cos_phi
            zd = r * sin_theta * sin_phi

            # Compute the atom position using bond and torsional angles.
            ypd = yd * coskh - zd * sinkh
            zpd = zd * coskh + yd * sinkh
            xpd = xd * cosph - zpd * sinph
            zqd = zpd * cosph + xd * sinph
            xqd = xpd * costh - ypd * sinth
            yqd = ypd * costh + xpd * sinth

            if inv:
                tmp = -zqd
                zqd = xqd
                xqd = tmp

        self._coords[i][0] = xqd + self._coords[na][0]
        self._coords[i][1] = yqd + self._coords[na][1]
        self._coords[i][2] = zqd + self._coords[na][2]
        self._nextIndex = self._nextIndex + 1
Beispiel #28
0
    def draw(self):
        # XXX This method is not speed-optimized. I just wrote it to
        # get the job done. (Nonetheless, it seems faster than the C
        # version commented out above.)

        p = self.parameters  # shorthand
        if p.center is not None:
            if not hasattr(VisionEgg.config, "_GAVE_CENTER_DEPRECATION"):
                logger = logging.getLogger('VisionEgg.Dots')
                logger.warning("Specifying DotArea2D by deprecated "
                               "'center' parameter deprecated.  Use "
                               "'position' parameter instead.  (Allows "
                               "use of 'anchor' parameter to set to "
                               "other values.)")
                VisionEgg.config._GAVE_CENTER_DEPRECATION = 1
            p.anchor = 'center'
            p.position = p.center[0], p.center[
                1]  # copy values (don't copy ref to tuple)
        if p.on:
            # calculate center
            center = VisionEgg._get_center(p.position, p.anchor, p.size)

            if p.anti_aliasing:
                if len(p.color) == 4 and not self._gave_alpha_warning:
                    if p.color[3] != 1.0:
                        logger = logging.getLogger('VisionEgg.Dots')
                        logger.warning("The parameter anti_aliasing is "
                                       "set to true in the DotArea2D "
                                       "stimulus class, but the color "
                                       "parameter specifies an alpha "
                                       "value other than 1.0.  To "
                                       "acheive the best anti-aliasing, "
                                       "ensure that the alpha value for "
                                       "the color parameter is 1.0.")
                        self._gave_alpha_warning = 1
                gl.glEnable(gl.GL_POINT_SMOOTH)
                # allow max_alpha value to control blending
                gl.glEnable(gl.GL_BLEND)
                gl.glBlendFunc(gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA)
            else:
                gl.glDisable(gl.GL_BLEND)

            now_sec = VisionEgg.time_func()
            if self.start_times_sec is not None:
                # compute extinct dots and generate new positions
                replace_indices = Numeric.nonzero(
                    Numeric.greater(now_sec - self.start_times_sec,
                                    p.dot_lifespan_sec))
                Numeric.put(self.start_times_sec, replace_indices, now_sec)

                new_x_positions = RandomArray.uniform(0.0, 1.0,
                                                      (len(replace_indices), ))
                Numeric.put(self.x_positions, replace_indices, new_x_positions)

                new_y_positions = RandomArray.uniform(0.0, 1.0,
                                                      (len(replace_indices), ))
                Numeric.put(self.y_positions, replace_indices, new_y_positions)

                new_random_directions_radians = RandomArray.uniform(
                    0.0, 2 * math.pi, (len(replace_indices), ))
                Numeric.put(self.random_directions_radians, replace_indices,
                            new_random_directions_radians)
            else:
                # initialize dot extinction values to random (uniform) distribution
                self.start_times_sec = RandomArray.uniform(
                    now_sec - p.dot_lifespan_sec, now_sec,
                    (self.constant_parameters.num_dots, ))

            signal_num_dots = int(
                round(p.signal_fraction * self.constant_parameters.num_dots))
            time_delta_sec = now_sec - self.last_time_sec
            self.last_time_sec = now_sec  # reset for next loop
            x_increment_normalized = math.cos(
                p.signal_direction_deg / 180.0 * math.pi
            ) * p.velocity_pixels_per_sec / p.size[0] * time_delta_sec
            y_increment_normalized = -math.sin(
                p.signal_direction_deg / 180.0 * math.pi
            ) * p.velocity_pixels_per_sec / p.size[1] * time_delta_sec
            self.x_positions[:signal_num_dots] += x_increment_normalized
            self.y_positions[:signal_num_dots] += y_increment_normalized

            num_random_dots = self.constant_parameters.num_dots - signal_num_dots
            random_x_increment_normalized = Numeric.cos(
                self.random_directions_radians[signal_num_dots:]
            ) * p.velocity_pixels_per_sec / p.size[0] * time_delta_sec
            random_y_increment_normalized = -Numeric.sin(
                self.random_directions_radians[signal_num_dots:]
            ) * p.velocity_pixels_per_sec / p.size[1] * time_delta_sec
            self.x_positions[signal_num_dots:] += random_x_increment_normalized
            self.y_positions[signal_num_dots:] += random_y_increment_normalized

            self.x_positions = Numeric.fmod(self.x_positions, 1.0)  # wrap
            self.y_positions = Numeric.fmod(self.y_positions, 1.0)

            self.x_positions = Numeric.fmod(self.x_positions + 1,
                                            1.0)  # wrap again for values < 1
            self.y_positions = Numeric.fmod(self.y_positions + 1, 1.0)

            xs = (self.x_positions - 0.5) * p.size[0] + center[0]
            ys = (self.y_positions - 0.5) * p.size[1] + center[1]

            if len(p.color) == 3:
                gl.glColor3f(*p.color)
            elif len(p.color) == 4:
                gl.glColor4f(*p.color)
            gl.glPointSize(p.dot_size)

            # Clear the modeview matrix
            gl.glMatrixMode(gl.GL_MODELVIEW)
            gl.glPushMatrix()

            gl.glDisable(gl.GL_TEXTURE_2D)

            if p.depth is None:
                depth = 0.0
            else:
                gl.glEnable(gl.GL_DEPTH_TEST)
                depth = p.depth
            zs = (depth, ) * len(xs)  # make N tuple with repeat value of depth
            draw_dots(xs, ys, zs)
            if p.anti_aliasing:
                gl.glDisable(gl.GL_POINT_SMOOTH)  # turn off
            gl.glPopMatrix()
Beispiel #29
0
    def addInternal(self, i, na, nb, nc, r, theta, phi):
        """
        Add another point, given its internal coordinates.  Once added
        via this routine, the cartesian coordinates for the point can
        be retrieved with getCartesian().

        @param i: Index of the point being added.  After this call, a
                  call to getCartesian with this index value will
                  succeed.  Index values less than 4 are ignored.
                  Index values should be presented here in sequence
                  beginning with 4.

        @param na: Index value for point A.  Point 'i' will be 'r'
                   distance units from point A.

        @param nb: Index value for point B.  Point 'i' will be located
                   such that the angle i-A-B is 'theta' degrees.

        @param nc: Index value for point C.  Point 'i' will be located
                      such that the torsion angle i-A-B-C is 'torsion'
                      degrees.

        @param r: Radial distance (in same units as resulting
                  cartesian coordinates) between A and i.

        @param theta: Angle in degrees of i-A-B.

        @param phi: Torsion angle in degrees of i-A-B-C
        """

        if (i < 4):
            return

        if (i != self._nextIndex):
            raise IndexError, "next index is %d not %r" % (self._nextIndex, i)

        cos_theta = cos(DEG2RAD * theta)
        xb = self._coords[nb][0] - self._coords[na][0]
        yb = self._coords[nb][1] - self._coords[na][1]
        zb = self._coords[nb][2] - self._coords[na][2]
        rba = 1.0 / sqrt(xb*xb + yb*yb + zb*zb)

        if abs(cos_theta) >= 0.999:
            # Linear case
            # Skip angles, just extend along A-B.
            rba = r * rba * cos_theta
            xqd = xb * rba
            yqd = yb * rba
            zqd = zb * rba
        else:
            xc = self._coords[nc][0] - self._coords[na][0]
            yc = self._coords[nc][1] - self._coords[na][1]
            zc = self._coords[nc][2] - self._coords[na][2]

            xyb = sqrt(xb*xb + yb*yb)

            inv = False
            if xyb < 0.001:
                # A-B points along the z axis.
                tmp = zc
                zc = -xc
                xc = tmp
                tmp = zb
                zb = -xb
                xb = tmp
                xyb = sqrt(xb*xb + yb*yb)
                inv = True

            costh = xb / xyb
            sinth = yb / xyb
            xpc = xc * costh + yc * sinth
            ypc = yc * costh - xc * sinth
            sinph = zb * rba
            cosph = sqrt(abs(1.0- sinph * sinph))
            xqa = xpc * cosph + zc * sinph
            zqa = zc * cosph - xpc * sinph
            yzc = sqrt(ypc * ypc + zqa * zqa)
            if yzc < 1e-8:
                coskh = 1.0
                sinkh = 0.0
            else:
                coskh = ypc / yzc
                sinkh = zqa / yzc

            sin_theta = sin(DEG2RAD * theta)
            sin_phi = -sin(DEG2RAD * phi)
            cos_phi = cos(DEG2RAD * phi)

            # Apply the bond length.
            xd = r * cos_theta
            yd = r * sin_theta * cos_phi
            zd = r * sin_theta * sin_phi

            # Compute the atom position using bond and torsional angles.
            ypd = yd * coskh - zd * sinkh
            zpd = zd * coskh + yd * sinkh
            xpd = xd * cosph - zpd * sinph
            zqd = zpd * cosph + xd * sinph
            xqd = xpd * costh - ypd * sinth
            yqd = ypd * costh + xpd * sinth

            if inv:
                tmp = -zqd
                zqd = xqd
                xqd = tmp

        self._coords[i][0] = xqd + self._coords[na][0]
        self._coords[i][1] = yqd + self._coords[na][1]
        self._coords[i][2] = zqd + self._coords[na][2]
        self._nextIndex = self._nextIndex + 1
Beispiel #30
0
def drawDnaRibbons(glpane,
                   endCenter1,  
                   endCenter2,
                   basesPerTurn,
                   duplexRise, 
                   glpaneScale,                   
                   lineOfSightVector,
                   displayStyle,
                   ribbon1_start_point = None,
                   ribbon2_start_point = None,
                   ribbon1_direction = None,
                   ribbon2_direction = None,
                   peakDeviationFromCenter = 9.5,
                   ribbonThickness = 2.0,
                   ribbon1Color = None, 
                   ribbon2Color = None,
                   stepColor = None):
    """
    Draw DNA ribbons where each strand is represented as a ribbon. DNA ribbons
    are drawn as sine waves with appropriate phase angles, with the phase
    angles computed in this method.

    @param endCenter1: Axis end 1
    @type  endCenter1: B{V}
    @param endCenter2: Axis end 2
    @type  endCenter2: B{V}
    @param basesPerTurn: Number of bases in a full turn.
    @type  basesPerTurn: float
    @param duplexRise: Center to center distance between consecutive steps
    @type  duplexRise: float
    @param glpaneScale: GLPane scale used in scaling arrow head drawing 
    @type  glpaneScale: float
    @param lineOfSightVector: Glpane lineOfSight vector, used to compute the 
                              the vector along the ladder step. 
    @type: B{V}    
    @param displayStyle: Rubberband display style (specified as an integer)
                         see comment in the method below. 
                         See also GLPane.displayMode.
    @type  displayStyle: int
    @param peakDeviationFromCenter: Distance of a peak from the axis 
                                    Also known as 'Amplitude' of a sine wave. 
    @type peakDeviationFromCenter: float
    @param ribbonThickness: Thickness of each of the the two ribbons
    @type ribbonThickness: float
    @param ribbon1Color: Color of ribbon1
    @param ribbon2Color: Color of ribbon2
    @see: B{DnaLineMode.Draw } (where it is used) for comments on color 
          convention

    TODO: as of 2008-04-22
      - Need more documentation
      -  This method is long mainly because of a number of custom drawing 
         See if that can be refactored e.g. methods like _drawRibbon1/strand1, 
         drawRibbon2 / strand2 etc. 
      - Further optimization / refactoring (low priority) 
    """

    #Try to match the rubberband display style as closely as possible to 
    #either the glpane's current display or the chunk display of the segment 
    #being edited. The caller should do the job of specifying the display style
    #it desires. As of 2008-02-20, this method only supports following display 
    #styles --Tubes, Ball and Stick, CPK and lines. the sphere radius 
    #for ball and stick or CPK is calculated approximately. 

    if displayStyle == diTrueCPK:
        SPHERE_RADIUS = 3.5
        ribbonThickness = 2.0
    elif displayStyle == diTUBES:
        SPHERE_RADIUS = 0.01
        ribbonThickness = 5.0
    elif displayStyle == diLINES:
        #Lines display and all other unsupported display styles
        SPHERE_RADIUS = 0.01
        ribbonThickness = 1.0
    else:
        #ball and stick display style. All other unsupported displays 
        #will be rendered in ball and stick display style
        SPHERE_RADIUS = 1.0
        ribbonThickness = 3.0
        
    



    ribbonLength = vlen(endCenter1 - endCenter2)

    #Don't draw the vertical line (step) passing through the startpoint unless 
    #the ribbonLength is at least equal to the duplexRise. 
    # i.e. do the drawing only when there are at least two ladder steps. 
    # This prevents a 'revolving line' effect due to the single ladder step at 
    # the first endpoint 
    if ribbonLength < duplexRise:
        return

    unitVectorAlongLength = norm(endCenter2 - endCenter1)
     
    ###===
    pointOnAxis = endCenter1

    axial_shift_1 = V(0.0, 0.0, 0.0) # might be changed below
    axial_shift_2 = V(0.0, 0.0, 0.0)
    
    # [these might be discarded and recomputed just below;
    #  the case where they aren't is (and I think was) untested.
    #  -- bruce 080422 comment]
    vectorAlongLadderStep =  cross(-lineOfSightVector, unitVectorAlongLength)
    unitVectorAlongLadderStep = norm(vectorAlongLadderStep)
    unitDepthVector = cross(unitVectorAlongLength,
                            unitVectorAlongLadderStep) ## * -1 
    
    numberOfBasesDrawn = 0
    theta_offset = 0
    x = 0
    ###
    #Formula .. Its a Sine Wave.
    # y(x) = A.sin(2*pi*f*x + phase_angle)  ------[1]
    # where --
    #      f = 1/T 
    #      A = Amplitude of the sine wave (or 'peak deviation from center') 
    #      y = y coordinate  of the sine wave -- distance is in Angstroms
    #      x = the x coordinate
    # phase_angle is computed for each wave. We know y at x =0. For example, 
    # for ribbon_1, , at x = 0, y = A. Putting these values in equation [1] 
    # we get the phase_angle. Similarly, for ribbon_2, at x = 0, y = -6 
    # Putting these values will give use the phase_angle_2. 
    # Note that for ribbon2_point, we subtract the value of equation [1] from 
    # the point on axis. 

    x = 0.0
    T =  duplexRise * basesPerTurn 
        # The 'Period' of the sine wave
        # (i.e. peak to peak distance between consecutive crests)

    amplitude = peakDeviationFromCenter
    amplitudeVector = unitVectorAlongLadderStep * amplitude
    depthVector = unitDepthVector * amplitude
        # Note: to reduce the effect of perspective view on rung direction,
        # we could multiply depthVector by 0.1 or 0.01. But this would lessen
        # the depth realism of line/sphere intersections. [bruce 080216]
    ###
    

    if ribbon1_start_point is not None:
        ribbon1_point = ribbon1_start_point        
    else:
        if ribbon2_start_point is not None:
            ribbon1_point = _get_ribbon_point_on_other_ribbon(
                ribbon2_start_point,
                ribbon2_direction,
                endCenter1,
                unitVectorAlongLength) 
            
        else:
            phase_angle_ribbon_1 = HALF_PI    
            theta_ribbon_1 = (TWICE_PI * x / T) + phase_angle_ribbon_1
            
            #Initialize ribbon1_point and ribbon2_point
            ribbon1_point = pointOnAxis + \
                            amplitudeVector * sin(theta_ribbon_1) + \
                            depthVector * cos(theta_ribbon_1)
            ribbon1_direction = +1
            
    drawDnaSingleRibbon(glpane,
                        endCenter1,  
                        endCenter2,
                        basesPerTurn,
                        duplexRise, 
                        # maybe: don't pass these three args, get from glpane
                        # instead? [bruce 080422 comment]
                        glpaneScale,
                        lineOfSightVector,
                        displayStyle,
                        ribbon1_start_point = ribbon1_point,
                        ribbon1_direction = ribbon1_direction,
                        peakDeviationFromCenter = peakDeviationFromCenter,
                        ribbonThickness = ribbonThickness,
                        ribbon1Color = ribbon1Color, 
                        stepColor = stepColor)

    if ribbon2_start_point is not None:
        ribbon2_point = ribbon2_start_point        
    else:
        if ribbon1_start_point is not None:
            ribbon2_point = _get_ribbon_point_on_other_ribbon(
                ribbon1_start_point,
                ribbon1_direction,
                endCenter1,
                unitVectorAlongLength)
            
        else:
            phase_angle_ribbon_2 = asin(-6.0/(amplitude))
            theta_ribbon_2 = (TWICE_PI * x / T) - phase_angle_ribbon_2    
            ribbon2_point = pointOnAxis - \
                            amplitudeVector * sin(theta_ribbon_2) + \
                            depthVector * cos(theta_ribbon_2)
            ribbon2_direction = -1
            
    drawDnaSingleRibbon(glpane,
                        endCenter1,  
                        endCenter2,
                        basesPerTurn,
                        duplexRise, 
                        # maybe: don't pass these three args, get from glpane
                        # instead? [bruce 080422 comment]
                        glpaneScale,
                        lineOfSightVector,
                        displayStyle,
                        ribbon1_start_point = ribbon2_point,
                        ribbon1_direction = ribbon2_direction,
                        peakDeviationFromCenter = peakDeviationFromCenter,
                        ribbonThickness = ribbonThickness,
                        ribbon1Color = ribbon2Color, 
                        stepColor = stepColor)
    
    del vectorAlongLadderStep
    
    return
Beispiel #31
0
def setup_drawer():
    """
    Set up the usual constant display lists in the current OpenGL context.

    WARNING: THIS IS ONLY CORRECT IF ONLY ONE GL CONTEXT CONTAINS DISPLAY LISTS
    -- or more precisely, only the GL context this has last been called in (or
    one which shares its display lists) will work properly with the routines in
    drawer.py, since the allocated display list names are stored in globals set
    by this function, but in general those names might differ if this was called
    in different GL contexts.
    """    
    spherelistbase = glGenLists(_NUM_SPHERE_SIZES)
    sphereList = []
    for i in range(_NUM_SPHERE_SIZES):
        sphereList += [spherelistbase+i]
        glNewList(sphereList[i], GL_COMPILE)
        glBegin(GL_TRIANGLE_STRIP) # GL_LINE_LOOP to see edges
        stripVerts = getSphereTriStrips(i)
        for vertNorm in stripVerts:
            glNormal3fv(vertNorm)
            glVertex3fv(vertNorm)
            continue
        glEnd()
        glEndList()
        continue
    drawing_globals.sphereList = sphereList

    # Sphere triangle-strip vertices for each level of detail.
    # (Cache and re-use the work of making them.)
    # Can use in converter-wrappered calls like glVertexPointerfv,
    # but the python arrays are re-copied to C each time.
    sphereArrays = []
    for i in range(_NUM_SPHERE_SIZES):
        sphereArrays += [getSphereTriStrips(i)]
        continue
    drawing_globals.sphereArrays = sphereArrays

    # Sphere glDrawArrays triangle-strip vertices for C calls.
    # (Cache and re-use the work of converting a C version.)
    # Used in thinly-wrappered calls like glVertexPointer.
    sphereCArrays = []
    for i in range(_NUM_SPHERE_SIZES):
        CArray = numpy.array(sphereArrays[i], dtype = numpy.float32)
        sphereCArrays += [CArray]
        continue
    drawing_globals.sphereCArrays = sphereCArrays

    # Sphere indexed vertices.
    # (Cache and re-use the work of making the indexes.)
    # Can use in converter-wrappered calls like glDrawElementsui,
    # but the python arrays are re-copied to C each time.
    sphereElements = []             # Pairs of lists (index, verts) .
    for i in range(_NUM_SPHERE_SIZES):
        sphereElements += [indexVerts(sphereArrays[i], .0001)]
        continue
    drawing_globals.sphereElements = sphereElements

    # Sphere glDrawElements index and vertex arrays for C calls.
    sphereCIndexTypes = []          # numpy index unsigned types.
    sphereGLIndexTypes = []         # GL index types for drawElements.
    sphereCElements = []            # Pairs of numpy arrays (Cindex, Cverts) .
    for i in range(_NUM_SPHERE_SIZES):
        (index, verts) = sphereElements[i]
        if len(index) < 256:
            Ctype = numpy.uint8
            GLtype = GL_UNSIGNED_BYTE
        else:
            Ctype = numpy.uint16
            GLtype = GL_UNSIGNED_SHORT
            pass
        sphereCIndexTypes += [Ctype]
        sphereGLIndexTypes += [GLtype]
        sphereCIndex = numpy.array(index, dtype = Ctype)
        sphereCVerts = numpy.array(verts, dtype = numpy.float32)
        sphereCElements += [(sphereCIndex, sphereCVerts)]
        continue
    drawing_globals.sphereCIndexTypes = sphereCIndexTypes
    drawing_globals.sphereGLIndexTypes = sphereGLIndexTypes
    drawing_globals.sphereCElements = sphereCElements

    if glGetString(GL_EXTENSIONS).find("GL_ARB_vertex_buffer_object") >= 0:

        # A GLBufferObject version for glDrawArrays.
        sphereArrayVBOs = []
        for i in range(_NUM_SPHERE_SIZES):
            vbo = GLBufferObject(GL_ARRAY_BUFFER_ARB,
                                 sphereCArrays[i], GL_STATIC_DRAW)
            sphereArrayVBOs += [vbo]
            continue
        drawing_globals.sphereArrayVBOs = sphereArrayVBOs

        # A GLBufferObject version for glDrawElements indexed verts.
        sphereElementVBOs = []              # Pairs of (IBO, VBO)
        for i in range(_NUM_SPHERE_SIZES):
            ibo = GLBufferObject(GL_ELEMENT_ARRAY_BUFFER_ARB,
                                 sphereCElements[i][0], GL_STATIC_DRAW)
            vbo = GLBufferObject(GL_ARRAY_BUFFER_ARB,
                                 sphereCElements[i][1], GL_STATIC_DRAW)
            sphereElementVBOs += [(ibo, vbo)]
            continue
        drawing_globals.sphereElementVBOs = sphereElementVBOs

        ibo.unbind()
        vbo.unbind()
        pass

    #bruce 060415
    drawing_globals.wiresphere1list = wiresphere1list = glGenLists(1)
    glNewList(wiresphere1list, GL_COMPILE)
    didlines = {} # don't draw each triangle edge more than once

    def shoulddoline(v1,v2):
        # make sure not list (unhashable) or Numeric array (bug in __eq__)
        v1 = tuple(v1)
        v2 = tuple(v2)
        if (v1,v2) not in didlines:
            didlines[(v1,v2)] = didlines[(v2,v1)] = None
            return True
        return False
    def doline(v1,v2):
        if shoulddoline(v1,v2):
            glVertex3fv(v1)
            glVertex3fv(v2)
        return
    glBegin(GL_LINES)
    ocdec = getSphereTriangles(1)
    for tri in ocdec:
        #e Could probably optim this more, e.g. using a vertex array or VBO or
        #  maybe GL_LINE_STRIP.
        doline(tri[0], tri[1])
        doline(tri[1], tri[2])
        doline(tri[2], tri[0])
    glEnd()
    glEndList()

    drawing_globals.CylList = CylList = glGenLists(1)
    glNewList(CylList, GL_COMPILE)
    glBegin(GL_TRIANGLE_STRIP)
    for (vtop, ntop, vbot, nbot) in drawing_globals.cylinderEdges:
        glNormal3fv(nbot)
        glVertex3fv(vbot)
        glNormal3fv(ntop)
        glVertex3fv(vtop)
    glEnd()
    glEndList()

    drawing_globals.CapList = CapList = glGenLists(1)
    glNewList(CapList, GL_COMPILE)
    glNormal3fv(drawing_globals.cap0n)
    glBegin(GL_POLYGON)
    for p in drawing_globals.drum0:
        glVertex3fv(p)
    glEnd()
    glNormal3fv(drawing_globals.cap1n)
    glBegin(GL_POLYGON)
    #bruce 060609 fix "ragged edge" bug in this endcap: drum1 -> drum2
    for p in drawing_globals.drum2:
        glVertex3fv(p)
    glEnd()
    glEndList()

    drawing_globals.diamondGridList = diamondGridList = glGenLists(1)
    glNewList(diamondGridList, GL_COMPILE)
    glBegin(GL_LINES)
    for p in drawing_globals.digrid:
        glVertex(p[0])
        glVertex(p[1])
    glEnd()
    glEndList()

    drawing_globals.lonsGridList = lonsGridList = glGenLists(1)
    glNewList(lonsGridList, GL_COMPILE)
    glBegin(GL_LINES)
    for p in drawing_globals.lonsEdges:
        glVertex(p[0])
        glVertex(p[1])
    glEnd()
    glEndList()

    drawing_globals.CubeList = CubeList = glGenLists(1)
    glNewList(CubeList, GL_COMPILE)
    glBegin(GL_QUAD_STRIP)
    # note: CubeList has only 4 faces of the cube; only suitable for use in
    # wireframes; see also solidCubeList [bruce 051215 comment reporting
    # grantham 20051213 observation]
    glVertex((-1,-1,-1))
    glVertex(( 1,-1,-1))
    glVertex((-1, 1,-1))
    glVertex(( 1, 1,-1))
    glVertex((-1, 1, 1))
    glVertex(( 1, 1, 1))
    glVertex((-1,-1, 1))
    glVertex(( 1,-1, 1))
    glVertex((-1,-1,-1))
    glVertex(( 1,-1,-1))
    glEnd()
    glEndList()

    drawing_globals.solidCubeList = solidCubeList = glGenLists(1)
    glNewList(solidCubeList, GL_COMPILE)
    glBegin(GL_QUADS)
    for i in xrange(len(drawing_globals.cubeIndices)):
        avenormals = V(0,0,0) #bruce 060302 fixed normals for flat shading 
        for j in xrange(4) :    
            nTuple = tuple(
                drawing_globals.cubeNormals[drawing_globals.cubeIndices[i][j]])
            avenormals += A(nTuple)
        avenormals = norm(avenormals)
        for j in xrange(4) :    
            vTuple = tuple(
                drawing_globals.cubeVertices[drawing_globals.cubeIndices[i][j]])
            #bruce 060302 made size compatible with glut.glutSolidCube(1.0)
            vTuple = A(vTuple) * 0.5
            glNormal3fv(avenormals)
            glVertex3fv(vTuple)
    glEnd()
    glEndList()                

    drawing_globals.rotSignList = rotSignList = glGenLists(1)
    glNewList(rotSignList, GL_COMPILE)
    glBegin(GL_LINE_STRIP)
    for ii in xrange(len(drawing_globals.rotS0n)):
        glVertex3fv(tuple(drawing_globals.rotS0n[ii]))
    glEnd()
    glBegin(GL_LINE_STRIP)
    for ii in xrange(len(drawing_globals.rotS1n)):
        glVertex3fv(tuple(drawing_globals.rotS1n[ii]))
    glEnd()
    glBegin(GL_TRIANGLES)
    for v in drawing_globals.arrow0Vertices + drawing_globals.arrow1Vertices:
        glVertex3f(v[0], v[1], v[2])
    glEnd()
    glEndList()

    drawing_globals.linearArrowList = linearArrowList = glGenLists(1)
    glNewList(linearArrowList, GL_COMPILE)
    glBegin(GL_TRIANGLES)
    for v in drawing_globals.linearArrowVertices:
        glVertex3f(v[0], v[1], v[2])
    glEnd()
    glEndList()

    drawing_globals.linearLineList = linearLineList = glGenLists(1)
    glNewList(linearLineList, GL_COMPILE)
    glEnable(GL_LINE_SMOOTH)
    glBegin(GL_LINES)
    glVertex3f(0.0, 0.0, -drawing_globals.halfHeight)
    glVertex3f(0.0, 0.0, drawing_globals.halfHeight)
    glEnd()
    glDisable(GL_LINE_SMOOTH)
    glEndList()

    drawing_globals.circleList = circleList = glGenLists(1)
    glNewList(circleList, GL_COMPILE)
    glBegin(GL_LINE_LOOP)
    for ii in range(60):
        x = cos(ii*2.0*pi/60)
        y = sin(ii*2.0*pi/60)
        glVertex3f(x, y, 0.0)
    glEnd()    
    glEndList()

    # piotr 080405
    drawing_globals.filledCircleList = filledCircleList = glGenLists(1)
    glNewList(filledCircleList, GL_COMPILE)
    glBegin(GL_POLYGON)
    for ii in range(60):
        x = cos(ii*2.0*pi/60)
        y = sin(ii*2.0*pi/60)
        glVertex3f(x, y, 0.0)
    glEnd()    
    glEndList()

    drawing_globals.lineCubeList = lineCubeList = glGenLists(1)
    glNewList(lineCubeList, GL_COMPILE)
    glBegin(GL_LINES)
    cvIndices = [0,1, 2,3, 4,5, 6,7, 0,3, 1,2, 5,6, 4,7, 0,4, 1,5, 2,6, 3,7]
    for i in cvIndices:
        glVertex3fv(tuple(drawing_globals.cubeVertices[i]))
    glEnd()
    glEndList()

    #initTexture('C:\\Huaicai\\atom\\temp\\newSample.png', 128,128)
    return # from setup_drawer
Beispiel #32
0
def getSphereTriStrips(level):
    steps = 2**level
    points = []                         # Triangle Strip vertices o be returned.

    # Construct an icosahedron with two vertices at the North and South Poles,
    # +-1 on the Y axis, as you look toward the X-Y plane with the Z axis
    # pointing out at you.  The "middle ring" vertices are all at the same
    # +-latitudes, on the intersection circles of the globe with a polar-axis
    # cylinder of the proper radius.
    #
    # The third "master vertex" of the icosahedron is placed on the X-Y plane,
    # which intersects the globe at the Greenwich Meridian (the semi-circle at
    # longitude 0, through Greenwich Observatory, 5 miles south-east of London.)
    #
    # The X (distance from the polar axis) and Y (height above the equatorial
    # plane) of the master vertex make a "golden rectangle", one unit high by
    # "phi" (1.6180339887498949) wide.  We normalize this to put it on the
    # unit-radius sphere, and take the distance from the axis as the cylinder
    # radius used to generate the rest of the vertices of the two middle rings.
    #
    # Plotted on the globe, the master vertex (first vertex of the North ring)
    # is lat-long 31.72,0 due south of London in Africa, about 45 miles
    # south-southwest of Benoud, Algeria.  The first vertex of the south ring is
    # rotated 1/10 of a circle east, at lat-long -31.72,36 in the south end of
    # the Indian Ocean, about 350 miles east-southeast of Durban, South Africa.
    #
    vert0 = norm(V(phi,1,0))   # Project the "master vertex" onto a unit sphere.
    cylRad = vert0[0]          # Icos vertex distance from the Y axis.
    ringLat = atan2(vert0[1], vert0[0]) * degreesPerRadian  # Latitude +-31.72 .

    # Basic triangle-strip icosahedron vertices.  Start and end with the Poles.
    # Reflect the master vertex into the southern hemisphere and rotate 5 copies
    # to make the middle rings of 5 vertices at North and South latitudes.
    p2_5 = 2*pi / 5.0
    # Simplify indexing by replicating the Poles, so everything is in fives.
    icosRings = [ 5 * [V(0.0, -1.0, 0.0)], # South Pole.

                  # South ring, first edge *centered on* the Greenwich Meridian.
                  [V(cylRad*cos((i-.5)*p2_5),-vert0[1], cylRad*sin((i-.5)*p2_5))
                   for i in range(5)],

                  # North ring, first vertex *on* the Greenwich Meridian.
                  [V(cylRad*cos(i*p2_5 ), vert0[1], cylRad*sin(i*p2_5))
                   for i in range(5)],

                  5 * [V(0.0, 1.0, 0.0)] ] # North Pole.


    # Three bands, going from bottom to top (South to North.)
    for band in range(3):
        lowerRing = icosRings[band]
        upperRing = icosRings[band+1]

        # Subdivide bands into sub-bands.  When level == 0, steps == 1,
        # subBand == 0, and we get just the icosahedron out.  (Really!)
        for subBand in range(steps):

            # Account for the tapering-in at the poles, making less points on
            # one edge of a sub-band than there are on the other edge.
            botOffset = 0
            if band is 0:      # South.
                botSteps = max(subBand, 1) # Don't divide by zero.
                topSteps = subBand + 1
                # Collapse the *first* triangle of south sub-band bottom edges.
                botOffset = -1
            elif band is 1:    # Middle.
                botSteps = topSteps = steps
            else:              # band is 2: North.
                botSteps = steps - subBand
                topSteps = max(steps - (subBand+1), 1)
                pass
            subBandSteps = max(botSteps, topSteps)

            # Do five segments, clockwise around the North Pole (East to West.)
            for seg in range(5):
                nextseg = (seg+1) % 5 # Wrap-around.

                # Interpolate ends of bottom & top edges of a sub-band segment.
                fractBot = float(subBand)/float(steps)
                fractTop = float(subBand+1)/float(steps)
                sbBotRight = fractBot * upperRing[seg] + \
                           (1.0-fractBot) * lowerRing[seg]
                sbTopRight = fractTop * upperRing[seg] + \
                           (1.0-fractTop) * lowerRing[seg]
                sbBotLeft = fractBot * upperRing[nextseg] + \
                          (1.0-fractBot) * lowerRing[nextseg]
                sbTopLeft = fractTop * upperRing[nextseg] + \
                          (1.0-fractTop) * lowerRing[nextseg]

                # Output the right end of the first segment of the sub-band.
                # We'll end up wrapping around to this same pair of points at
                # the left end of the last segment of the sub-band.
                if seg == 0:
                    # Project verts from icosahedron faces onto the unit sphere.
                    points += [norm(sbBotRight), norm(sbTopRight)]

                # Step across the sub-band edges from right to left,
                # stitching triangle pairs from their lower to upper edges.
                for step in range(1, subBandSteps+1):

                    # Interpolate step point pairs along the sub-band edges.
                    fractLower = float(step+botOffset)/float(botSteps)
                    lower = fractLower * sbBotLeft + \
                          (1.0-fractLower) * sbBotRight
                    # Collapse the *last* triangle of north sub-band top edges.
                    fractUpper = float(min(step, topSteps))/float(topSteps)
                    upper = fractUpper * sbTopLeft + \
                          (1.0-fractUpper) * sbTopRight

                    # Output verts, projected from icos faces onto unit sphere.
                    points += [norm(lower), norm(upper)]

                    continue # step
                continue # seg
            continue # subBand
        continue # band
    return points
Beispiel #33
0
 def __init__(self, x, y = None, z = None, w = None):
     if w is not None: # 4 numbers
         # [bruce comment 050518: note than ints are not turned to floats,
         #  and no checking (of types or values) or normalization is done,
         #  and that these arg names don't correspond to their meanings,
         #  which are W,x,y,z (as documented) rather than x,y,z,w.]
         self.vec = V(x, y, z, w)
     
     elif z is not None: # three axis vectors
         # Just use first two
         # [bruce comments 050518:
         #  - bugfix/optim: test z for None, not for truth value
         #    (only fixes z = V(0,0,0) which is not allowed here anyway, so not very important)
         #  - This case was not used until now, and was wrong for some or all inputs
         #    (not just returning the inverse quat as I initially thought);
         #    so I fixed it.
         #  - The old code sometimes used 'z' but the new code never does
         #    (except to decide to use this case, and when _DEBUG_QUATS to check the results).
         
         # Q(x, y, z) where x, y, and z are three orthonormal vectors
         # is the quaternion that rotates the standard axes into that
         # reference frame
         ##e could have a debug check for vlen(x), y,z, and ortho and right-handed...
         # but when this is false (due to caller bugs), the check_posns_near below should catch it.
         xfixer = Q( X_AXIS, x)
         y_axis_2 = xfixer.rot(Y_AXIS)
         yfixer = twistor( x, y_axis_2, y)
         res = xfixer
         res += yfixer # warning: modifies res -- xfixer is no longer what it was
         if _DEBUG_QUATS:
             check_posns_near( res.rot(X_AXIS), x, "x" )
             check_posns_near( res.rot(Y_AXIS), y, "y" )
             check_posns_near( res.rot(Z_AXIS), z, "z" )
         self.vec = res.vec
         if _DEBUG_QUATS:
             res = self # sanity check
             check_posns_near( res.rot(X_AXIS), x, "sx" )
             check_posns_near( res.rot(Y_AXIS), y, "sy" )
             check_posns_near( res.rot(Z_AXIS), z, "sz" )
         return
         # old code (incorrect and i think never called) commented out long ago, removed in rev. 1.27 [bruce 060228]
         
     elif type(y) in numTypes:
         # axis vector and angle [used often]
         v = (x / vlen(x)) * Numeric.sin(y * 0.5)
         self.vec = V(Numeric.cos(y * 0.5), v[0], v[1], v[2])
         
     elif y is not None:
         # rotation between 2 vectors [used often]
         #bruce 050518 bugfix/optim: test y for None, not for truth value
         # (only fixes y = V(0,0,0) which is not allowed here anyway, so not very important)
         # [I didn't yet verify it does this in correct order; could do that from its use
         # in bonds.py or maybe the new indirect use in jigs.py (if I checked iadd too). ###@@@]
         #bruce 050730 bugfix: when x and y are very close to equal, original code treats them as opposite.
         # Rewriting it to fix that, though not yet in an ideal way (just returns identity).
         # Also, when they're close but not that close, original code might be numerically unstable.
         # I didn't fix that problem.
         x = norm(x)
         y = norm(y)
         dotxy = Numeric.dot(x, y)
         v = cross(x, y)
         vl = Numeric.dot(v, v) ** .5
         if vl<0.000001:
             # x, y are very close, or very close to opposite, or one of them is zero
             if dotxy < 0:
                 # close to opposite; treat as actually opposite (same as pre-050730 code)
                 ax1 = cross(x, V(1, 0, 0))
                 ax2 = cross(x, V(0, 1, 0))
                 if vlen(ax1)>vlen(ax2):
                     self.vec = norm(V(0, ax1[0],ax1[1],ax1[2]))
                 else:
                     self.vec = norm(V(0, ax2[0],ax2[1],ax2[2]))
             else:
                 # very close, or one is zero -- we could pretend they're equal, but let's be a little
                 # more accurate than that -- vl is sin of desired theta, so vl/2 is approximately sin(theta/2)
                 # (##e could improve this further by using a better formula to relate sin(theta/2) to sin(theta)),
                 # so formula for xyz part is v/vl * vl/2 == v/2 [bruce 050730]
                 xyz = v / 2.0
                 sintheta2 = vl / 2.0 # sin(theta/2)
                 costheta2 = (1 - sintheta2**2) ** .5 # cos(theta/2)
                 self.vec = V(costheta2, xyz[0], xyz[1], xyz[2])
         else:
             # old code's method is numerically unstable if abs(dotxy) is close to 1. I didn't fix this.
             # I also didn't review this code (unchanged from old code) for correctness. [bruce 050730]
             theta = math.acos(min(1.0, max(-1.0, dotxy)))
             if Numeric.dot(y, cross(x, v)) > 0.0:
                 theta = 2.0 * math.pi - theta
             w = Numeric.cos(theta * 0.5)
             s = ((1 - w**2)**.5) / vl
             self.vec = V(w, v[0]*s, v[1]*s, v[2]*s)
         pass
     
     elif type(x) in numTypes:
         # just one number [#k is this ever used?]
         self.vec = V(1, 0, 0, 0)
     
     else:
         #bruce 050518 comment: a copy of the quat x, or of any length-4 sequence [both forms are used]
         self.vec = V(x[0], x[1], x[2], x[3])
     return # from Q.__init__
Beispiel #34
0
    def draw(self):
        # XXX This method is not speed-optimized. I just wrote it to
        # get the job done. (Nonetheless, it seems faster than the C
        # version commented out above.)

        p = self.parameters # shorthand
        if p.center is not None:
            if not hasattr(VisionEgg.config,"_GAVE_CENTER_DEPRECATION"):
                logger = logging.getLogger('VisionEgg.Dots')
                logger.warning("Specifying DotArea2D by deprecated "
                               "'center' parameter deprecated.  Use "
                               "'position' parameter instead.  (Allows "
                               "use of 'anchor' parameter to set to "
                               "other values.)")
                VisionEgg.config._GAVE_CENTER_DEPRECATION = 1
            p.anchor = 'center'
            p.position = p.center[0], p.center[1] # copy values (don't copy ref to tuple)
        if p.on:
            # calculate center
            center = VisionEgg._get_center(p.position,p.anchor,p.size)

            if p.anti_aliasing:
                if len(p.color) == 4 and not self._gave_alpha_warning:
                    if p.color[3] != 1.0:
                        logger = logging.getLogger('VisionEgg.Dots')
                        logger.warning("The parameter anti_aliasing is "
                                       "set to true in the DotArea2D "
                                       "stimulus class, but the color "
                                       "parameter specifies an alpha "
                                       "value other than 1.0.  To "
                                       "acheive the best anti-aliasing, "
                                       "ensure that the alpha value for "
                                       "the color parameter is 1.0.")
                        self._gave_alpha_warning = 1
                gl.glEnable( gl.GL_POINT_SMOOTH )
                # allow max_alpha value to control blending
                gl.glEnable( gl.GL_BLEND )
                gl.glBlendFunc( gl.GL_SRC_ALPHA, gl.GL_ONE_MINUS_SRC_ALPHA )
            else:
                gl.glDisable( gl.GL_BLEND )

            now_sec = VisionEgg.time_func()
            if self.start_times_sec is not None:
                # compute extinct dots and generate new positions
                replace_indices = Numeric.nonzero( Numeric.greater( now_sec - self.start_times_sec, p.dot_lifespan_sec) )
                Numeric.put( self.start_times_sec, replace_indices, now_sec )

                new_x_positions = RandomArray.uniform(0.0,1.0,
                                                      (len(replace_indices),))
                Numeric.put( self.x_positions, replace_indices, new_x_positions )

                new_y_positions = RandomArray.uniform(0.0,1.0,
                                                      (len(replace_indices),))
                Numeric.put( self.y_positions, replace_indices, new_y_positions )

                new_random_directions_radians = RandomArray.uniform(0.0,2*math.pi,
                                                                    (len(replace_indices),))
                Numeric.put( self.random_directions_radians, replace_indices, new_random_directions_radians )
            else:
                # initialize dot extinction values to random (uniform) distribution
                self.start_times_sec = RandomArray.uniform( now_sec - p.dot_lifespan_sec, now_sec,
                                                            (self.constant_parameters.num_dots,))

            signal_num_dots = int(round(p.signal_fraction * self.constant_parameters.num_dots))
            time_delta_sec = now_sec - self.last_time_sec
            self.last_time_sec = now_sec # reset for next loop
            x_increment_normalized =  math.cos(p.signal_direction_deg/180.0*math.pi) * p.velocity_pixels_per_sec / p.size[0] * time_delta_sec
            y_increment_normalized = -math.sin(p.signal_direction_deg/180.0*math.pi) * p.velocity_pixels_per_sec / p.size[1] * time_delta_sec
            self.x_positions[:signal_num_dots] += x_increment_normalized
            self.y_positions[:signal_num_dots] += y_increment_normalized

            num_random_dots = self.constant_parameters.num_dots - signal_num_dots
            random_x_increment_normalized =  Numeric.cos(self.random_directions_radians[signal_num_dots:]) * p.velocity_pixels_per_sec / p.size[0] * time_delta_sec
            random_y_increment_normalized = -Numeric.sin(self.random_directions_radians[signal_num_dots:]) * p.velocity_pixels_per_sec / p.size[1] * time_delta_sec
            self.x_positions[signal_num_dots:] += random_x_increment_normalized
            self.y_positions[signal_num_dots:] += random_y_increment_normalized

            self.x_positions = Numeric.fmod( self.x_positions, 1.0 ) # wrap
            self.y_positions = Numeric.fmod( self.y_positions, 1.0 )

            self.x_positions = Numeric.fmod( self.x_positions+1, 1.0 ) # wrap again for values < 1
            self.y_positions = Numeric.fmod( self.y_positions+1, 1.0 )

            xs = (self.x_positions - 0.5) * p.size[0] + center[0]
            ys = (self.y_positions - 0.5) * p.size[1] + center[1]

            if len(p.color)==3:
                gl.glColor3f(*p.color)
            elif len(p.color)==4:
                gl.glColor4f(*p.color)
            gl.glPointSize(p.dot_size)

            # Clear the modeview matrix
            gl.glMatrixMode(gl.GL_MODELVIEW)
            gl.glPushMatrix()

            gl.glDisable(gl.GL_TEXTURE_2D)

            if p.depth is None:
                depth = 0.0
            else:
                gl.glEnable(gl.GL_DEPTH_TEST)
                depth = p.depth
            zs = (depth,)*len(xs) # make N tuple with repeat value of depth
            draw_dots(xs,ys,zs)
            if p.anti_aliasing:
                gl.glDisable( gl.GL_POINT_SMOOTH ) # turn off
            gl.glPopMatrix()