Пример #1
0
def 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=None,
        ribbon1_direction=None,
        peakDeviationFromCenter=9.5,
        ribbonThickness=2.0,
        ribbon1Color=None,
        stepColor=None):
    """
    @see: drawDnaRibbons (method in this file)
    @see: DnaStrand_GraphicsMode._drawHandles()
    """

    if 0:
        # debug code, useful to see where the argument points are located
        # [bruce 080422]
        draw_debug_text(glpane, endCenter1, "endCenter1")
        draw_debug_text(glpane, endCenter2, "endCenter2")
        draw_debug_text(glpane, ribbon1_start_point, "ribbon1_start_point")

    #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

    if stepColor is None:
        stepColor = env.prefs[DarkBackgroundContrastColor_prefs_key]

    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. It also means the dna duplex axis can be determined
    # below from the two endpoints.
    if ribbonLength < duplexRise:
        return

    unitVectorAlongLength = norm(endCenter2 - endCenter1)

    glDisable(GL_LIGHTING)
    ##glPushMatrix()
    ##glTranslatef(endCenter1[0], endCenter1[1], endCenter1[2])
    ##pointOnAxis = V(0, 0, 0)
    pointOnAxis = endCenter1

    axial_shift = V(0.0, 0.0, 0.0)  # might be changed below

    # [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

    if ribbon1_start_point is not None:
        # [revise the meaning of these values to give the coordinate system
        #  with the right phase in which to draw the ribbon.
        #  bruce 080422 bugfix]
        vectorAlongLadderStep0 = ribbon1_start_point - endCenter1
        # note: this might not be perpendicular to duplex axis.
        # fix by subtracting off the parallel component.
        # but add the difference back to every point below.
        vectorAlongLadderStep = vectorAlongLadderStep0 - \
            dot( unitVectorAlongLength,
                 vectorAlongLadderStep0 ) * unitVectorAlongLength
        axial_shift = (vectorAlongLadderStep0 - vectorAlongLadderStep)
        # note: even using this, there is still a small glitch in the
        # location of the first drawn sphere vs. the ribbon point... don't
        # know why. [bruce 080422]
        unitVectorAlongLadderStep = norm(vectorAlongLadderStep)
        unitDepthVector = cross(unitVectorAlongLength,
                                unitVectorAlongLadderStep)  ## * -1
        pass
    del vectorAlongLadderStep

    ###===
    #Following limits the arrowHead Size to the given value. When you zoom out,
    #the rest of ladder drawing becomes smaller (expected) and the following
    #check ensures that the arrowheads are drawn proportionately.
    # (Not using a 'constant' to do this as using glpaneScale gives better
    #results)
    if glpaneScale > 40:
        arrowDrawingScale = 40
    else:
        arrowDrawingScale = glpaneScale

    #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.

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

    numberOfBasesDrawn = 0
    theta_offset = 0

    ##    phase_angle_ribbon_1 = HALF_PI
    ##    theta_ribbon_1 = (TWICE_PI * x / T) + phase_angle_ribbon_1

    #Initialize ribbon1_point
    # [note: might not be needed, since identical to first point
    #  computed during loop, but present code uses it to initialize
    #  previous_ribbon1_point during loop [bruce 080422 comment]]
    ribbon1_point = _compute_ribbon_point(
        pointOnAxis + axial_shift, basesPerTurn, duplexRise,
        unitVectorAlongLength, unitVectorAlongLadderStep, unitDepthVector,
        peakDeviationFromCenter, numberOfBasesDrawn, theta_offset)

    while x < ribbonLength:
        #Draw the axis point.
        drawPoint(stepColor, pointOnAxis)

        previousPointOnAxis = pointOnAxis
        previous_ribbon1_point = ribbon1_point

        ribbon1_point = _compute_ribbon_point(
            pointOnAxis + axial_shift, basesPerTurn, duplexRise,
            unitVectorAlongLength, unitVectorAlongLadderStep, unitDepthVector,
            peakDeviationFromCenter, numberOfBasesDrawn, theta_offset)

        if x == duplexRise and ribbon1_direction == -1:
            # For ribbon_2 we need to draw an arrow head for y at x = 0.
            # To do this, we need the 'next ribbon_2' point in order to
            # compute the appropriate vectors. So when x = duplexRise, the
            # previous_ribbon2_point is nothing but y at x = 0.
            arrowLengthVector2 = norm(ribbon1_point - previous_ribbon1_point)
            arrowHeightVector2 = cross(-lineOfSightVector, arrowLengthVector2)
            drawArrowHead(ribbon1Color, previous_ribbon1_point,
                          arrowDrawingScale, -arrowHeightVector2,
                          -arrowLengthVector2)

        # Draw sphere over previous_ribbon1_point and not ribbon1_point.
        # This is so we don't draw a sphere over the last point on ribbon1
        # (instead, it is drawn as an arrowhead after the while loop).
        drawsphere(ribbon1Color,
                   previous_ribbon1_point,
                   SPHERE_RADIUS,
                   SPHERE_DRAWLEVEL,
                   opacity=SPHERE_OPACITY)

        drawline(stepColor, pointOnAxis, ribbon1_point)

        #Increment the pointOnAxis and x
        pointOnAxis = pointOnAxis + unitVectorAlongLength * duplexRise
        x += duplexRise
        numberOfBasesDrawn += 1

        if previous_ribbon1_point:
            drawline(ribbon1Color,
                     previous_ribbon1_point,
                     ribbon1_point,
                     width=ribbonThickness,
                     isSmooth=True)
            arrowLengthVector1 = norm(ribbon1_point - previous_ribbon1_point)
            arrowHeightVector1 = cross(-lineOfSightVector, arrowLengthVector1)
            pass

        continue  # while x < ribbonLength

    if ribbon1_direction == 1:
        #Arrow head for endpoint of ribbon_1.
        drawArrowHead(ribbon1Color, ribbon1_point, arrowDrawingScale,
                      arrowHeightVector1, arrowLengthVector1)

    #The second axis endpoint of the dna is drawn as a transparent sphere.
    #Note that the second axis endpoint is NOT NECESSARILY endCenter2 . In fact
    # those two are equal only at the ladder steps. In other case (when the
    # ladder step is not completed), the endCenter1 is ahead of the
    #'second axis endpoint of the dna'
    drawsphere(AXIS_ENDPOINT_SPHERE_COLOR,
               previousPointOnAxis,
               AXIS_ENDPOINT_SPHERE_RADIUS,
               AXIS_ENDPOINT_SPHERE_DRAWLEVEL,
               opacity=AXIS_ENDPOINT_SPHERE_OPACITY)

    ##glPopMatrix()
    glEnable(GL_LIGHTING)
    return  # from drawDnaSingleRibbon
Пример #2
0
 def viewBack(self):
     cmd = greenmsg("Back View: ")
     info = 'Current view is Back View'
     env.history.message(cmd + info)
     self.glpane.rotateView(Q(V(0, 1, 0), math.pi))
Пример #3
0
 def viewRight(self):
     cmd = greenmsg("Right View: ")
     info = 'Current view is Right View'
     env.history.message(cmd + info)
     self.glpane.rotateView(Q(V(0, 1, 0), -math.pi / 2))
Пример #4
0
    def viewNormalTo(self):  #
        """
        Set view to the normal vector of the plane defined by 3 or more
        selected atoms or a jig's (Motor or RectGadget) axis.
        """
        cmd = greenmsg("Set View Normal To: ")

        chunks = self.assy.selmols
        jigs = self.assy.getSelectedJigs()
        atoms = self.assy.selatoms_list()

        #following fixes bug 1748 ninad 061003.
        if len(chunks) > 0 and len(atoms) == 0:
            # Even though chunks have an axis, it is not necessarily the same
            # axis attr stored in the chunk.  Get the chunks atoms and let
            # compute_heuristic_axis() recompute them.
            for c in range(len(chunks)):
                atoms += chunks[c].atoms.values()
        elif len(jigs) == 1 and len(atoms) == 0:
            # Warning: RectGadgets have no atoms.  We handle this special case below.
            atoms = jigs[0].atoms
        elif len(atoms) < 3:
            # There is a problem when allowing only 2 selected atoms.
            # Changing requirement to 3 atoms fixes bug 1418. mark 060322
            msg = redmsg(
                "Please select some atoms, jigs, and/or chunks, covering at least 3 atoms"
            )
            print "ops_view.py len(atoms) = ", len(atoms)
            env.history.message(cmd + msg)
            return

        # This check is needed for jigs that have no atoms.  Currently, this
        # is the case for RectGadgets (ESP Image and Grid Plane) only.
        if len(atoms):
            pos = A(map(lambda a: a.posn(), atoms))
            nears = [self.glpane.out, self.glpane.up]
            axis = compute_heuristic_axis(pos,
                                          'normal',
                                          already_centered=False,
                                          nears=nears,
                                          dflt=None)
        else:  # We have a jig with no atoms.
            axis = jigs[0].getaxis()  # Get the jig's axis.
            # If axis is pointing into the screen, negate (reverse) axis.
            if dot(axis, self.glpane.lineOfSight) > 0:
                axis = -axis

        if not axis:
            msg = orangemsg(
                "Warning: Normal axis could not be determined. No change in view."
            )
            env.history.message(cmd + msg)
            return

        # Compute the destination quat (q2).
        q2 = Q(V(0, 0, 1), axis)
        q2 = q2.conj()

        self.glpane.rotateView(q2)

        info = 'View set to normal vector of the plane defined by the selected atoms.'
        env.history.message(cmd + info)
Пример #5
0
 def viewFlipViewHorz(self):
     """
     Flip view horizontally.
     """
     self.glpane.rotateView(self.glpane.quat + Q(V(1, 0, 0), math.pi))
Пример #6
0
 def __up(self, _q=V(0, 1, 0)):
     return self.quat.unrot(_q)
Пример #7
0
 def __out(self, _q=V(0, 0, 1)):
     return self.quat.unrot(_q)
Пример #8
0
    def compute_memo(self, chunk):
        """If drawing chunk in this display mode can be optimized by precomputing some info from chunk's appearance,
        compute that info and return it.
           If this computation requires preference values, access them as env.prefs[key],
        and that will cause the memo to be removed (invalidated) when that preference value is changed by the user.
           This computation is assumed to also depend on, and only on, chunk's appearance in ordinary display modes
        (i.e. it's invalidated whenever havelist is). There is not yet any way to change that,
        so bugs will occur if any ordinarily invisible chunk info affects this rendering,
        and potential optimizations will not be done if any ordinarily visible info is not visible in this rendering.
        These can be fixed if necessary by having the real work done within class Chunk's _recompute_ rules,
        with this function or drawchunk just accessing the result of that (and sometimes causing its recomputation),
        and with whatever invalidation is needed being added to appropriate setter methods of class Chunk.
        If the real work can depend on more than chunk's ordinary appearance can, the access would need to be in drawchunk;
        otherwise it could be in drawchunk or in this method compute_memo.
        """
        # for this example, we'll turn the chunk axes into a cylinder.
        # Since chunk.axis is not always one of the vectors chunk.evecs (actually chunk.poly_evals_evecs_axis[2]),
        # it's best to just use the axis and center, then recompute a bounding cylinder.
        if not chunk.atoms:
            return None

        # Put up hourglass cursor to indicate we are busy. Restore the cursor below. Mark 060621.
        QApplication.setOverrideCursor(QCursor(Qt.WaitCursor))
        env.history.message(
            self.cmdname + "Computing surface. Please wait...")  # Mark 060621.
        env.history.h_update(
        )  # Update history widget with last message. # Mark 060623.

        _report_psurface_import_status()  # prints only once per session

        if _psurface_import_worked:  # cpp surface stuff
            center = chunk.center
            bcenter = chunk.abs_to_base(center)
            rad = 0.0
            margin = 0
            radiuses = []
            spheres = []
            atoms = []
            coltypes = []
            for a in chunk.atoms.values():
                col = a.drawing_color()
                ii = 0
                for ic in range(len(coltypes)):
                    ct = coltypes[ic]
                    if ct == col:
                        break
                    ii += 1
                if ii >= len(coltypes):
                    coltypes.append(col)
                atoms.append(ii)
                dispjunk, ra = a.howdraw(diTrueCPK)
                if ra > margin: margin = ra
                radiuses.append(ra)
                p = a.posn() - center
                spheres.append(p)
                r = p[0]**2 + p[1]**2 + p[2]**2
                if r > rad: rad = r
            rad = sqrt(rad)
            radius = rad + margin
            cspheres = []
            from utilities.debug_prefs import debug_pref, Choice_boolean_True
            use_colors = debug_pref(
                "surface: use colors?", Choice_boolean_True
            )  #bruce 060927 (old code had 0 for use_colors)
            for i in range(len(spheres)):
                st = spheres[i] / radius
                rt = radiuses[i] / radius
                # cspheres.append((st[0],st[1],st[2],rt,use_colors))
                cspheres.append((st[0], st[1], st[2], rt, atoms[i]))
            #cspheres.append((-0.3,0,0,0.3,1))
            #cspheres.append((0.3,0,0,0.3,2))
            color = chunk.drawing_color()
            if color is None:
                color = V(0.5, 0.5, 0.5)
            #  create surface
            level = 3
            if rad > 6: level = 4
            ps = psurface
            # 0 - sphere triangles
            # 1 - torus rectangles
            # 2 - omega rectangles
            method = 2
            ((em, pm, am), nm) = ps.CreateSurface(cspheres, level, method)
            cm = []
            if True:  # True for color
                for i in range(len(am)):
                    cm.append(coltypes[am[i]])
            else:
                for i in range(len(am)):
                    cm.append((0.5, 0.5, 0.5))
            tm = (em, pm, cm)
        else:  # python surface stuff
            center = chunk.center
            bcenter = chunk.abs_to_base(center)
            rad = 0.0
            s = Surface()
            margin = 0
            for a in chunk.atoms.values():
                dispjunk, ra = a.howdraw(diTrueCPK)
                if ra > margin: margin = ra
                s.radiuses.append(ra)
                p = a.posn() - center
                s.spheres.append(Triple(p[0], p[1], p[2]))
                r = p[0]**2 + p[1]**2 + p[2]**2
                if r > rad: rad = r
            rad = sqrt(rad)
            radius = rad + margin
            for i in range(len(s.spheres)):
                s.spheres[i] /= radius
                s.radiuses[i] /= radius
            color = chunk.drawing_color()
            if color is None:
                color = V(0.5, 0.5, 0.5)
            #  create surface
            level = 3
            if rad > 6: level = 4
            ts = getSphereTriangles(level)
            #ts = s.TorusTriangles(0.7, 0.3, 20)
            tm = s.SurfaceTriangles(ts)
            nm = s.SurfaceNormals()

        QApplication.restoreOverrideCursor(
        )  # Restore the cursor. Mark 060621.
        env.history.message(self.cmdname + "Done.")  # Mark 060621.

        return (bcenter, radius, color, tm, nm)
Пример #9
0
class test_globals:
    ALWAYS_GL_UPDATE = True  # redraw as often as possible
    SPIN = True  # spin the view on each redraw ...
    SPINQUAT = Q(V(1, 0, 0), V(0, 0, 1)) / 90.0  # ... by 1 degree per frame
    printFrames = True  # print frames-per-second to console
Пример #10
0
def drawGPGrid(glpane, color, line_type, w, h, uw, uh, up, right):
    """
    Draw grid lines for a Grid Plane.
    
    glpane = the glpane
    color = grid line and unit text color
    line_type is: 0=None, 1=Solid, 2=Dashed or 3=Dotted
    w = width
    h = height
    uw = width spacing between grid lines
    uh = height spacing between grid lines
    """

    if line_type == NO_LINE:
        return

    if uw > w: uw = w
    if uh > h: uh = h

    Z_OFF = 0.0  #0.001

    glDisable(GL_LIGHTING)
    glColor3fv(color)

    hw = w / 2.0
    hh = h / 2.0

    #glEnable(GL_LINE_SMOOTH)
    #glEnable(GL_BLEND)
    #glBlendFunc(GL_SRC_ALPHA, GL_ONE)#_MINUS_SRC_ALPHA)

    if line_type > 1:
        glEnable(GL_LINE_STIPPLE)
        if line_type == DASHED_LINE:
            glLineStipple(1, 0x00FF)  #  dashed
        elif line_type == DOTTED_LINE:
            glLineStipple(1, 0x0101)  #  dotted
        else:
            print "drawGPGrid(): line_type '", line_type, \
                  "' is not valid.  Drawing dashed grid line."
            glLineStipple(1, 0x00FF)  #  dashed

    glBegin(GL_LINES)

    #Draw horizontal lines
    y1 = 0
    while y1 > -hh:
        glVertex3f(-hw, y1, Z_OFF)
        glVertex3f(hw, y1, Z_OFF)
        y1 -= uh

    y1 = 0
    while y1 < hh:
        glVertex3f(-hw, y1, Z_OFF)
        glVertex3f(hw, y1, Z_OFF)
        y1 += uh

    #Draw vertical lines
    x1 = 0
    while x1 < hw:
        glVertex3f(x1, hh, Z_OFF)
        glVertex3f(x1, -hh, Z_OFF)
        x1 += uw

    x1 = 0
    while x1 > -hw:
        glVertex3f(x1, hh, Z_OFF)
        glVertex3f(x1, -hh, Z_OFF)
        x1 -= uw

    glEnd()

    if line_type > 1:
        glDisable(GL_LINE_STIPPLE)

    # Draw unit labels for gridlines (in nm).
    text_color = color

    import sys
    if sys.platform == "darwin":
        # WARNING: Anything smaller than 9 pt on Mac OS X results in
        # un-rendered text. Not sure why. -- piotr 080616
        font_size = 9
    else:
        font_size = 8

    text_offset = 0.5  # Offset from edge of border, in Angstroms.

    # Draw unit text labels for horizontal lines (nm)
    y1 = 0
    while y1 > -hh:
        y1 -= uh
        drawtext("%g" % (-y1 / 10.0), text_color, V(hw + text_offset, y1, 0.0),
                 font_size, glpane)
    drawtext("%g" % (-y1 / 10.0), text_color, V(hw + text_offset, y1, 0.0),
             font_size, glpane)

    y1 = 0
    while y1 < hh:
        drawtext("%g" % (-y1 / 10.0), text_color, V(hw + text_offset, y1, 0.0),
                 font_size, glpane)
        y1 += uh
    drawtext("%g" % (-y1 / 10.0), text_color, V(hw + text_offset, y1, 0.0),
             font_size, glpane)

    # Draw unit text labels for vertical lines (nm).
    x1 = 0
    while x1 < hw:
        drawtext("%g" % (x1 / 10.0), text_color, V(x1, hh + text_offset, 0.0),
                 font_size, glpane)
        x1 += uw
    drawtext("%g" % (x1 / 10.0), text_color, V(x1, hh + text_offset, 0.0),
             font_size, glpane)

    x1 = 0
    while x1 > -hw:
        drawtext("%g" % (x1 / 10.0), text_color, V(x1, hh + text_offset, 0.0),
                 font_size, glpane)
        x1 -= uw
    drawtext("%g" % (x1 / 10.0), text_color, V(x1, hh + text_offset, 0.0),
             font_size, glpane)

    glEnable(GL_LIGHTING)
    return
Пример #11
0
    def _draw(self, hCenter = None, highlighted = False):
        """
        Draw the resize handle. It does the actual drawing work.

        @param hCenter: The center of the handle. If None, use the handle's
                        I{center} property.
        @type  hCenter: L{V} or None

        @param highlighted: This argument determines if the handle is
                            drawn in the highlighted color.
        @type  highlighted: bool
        @see: {self.draw} where this method is called.
        """

        if hCenter:
            if self.center != hCenter:
                self.center = hCenter

        #Use glpane's scale for drawing the handle. This makes sure that
        # the handle is non-zoomable.
        side = self.glpane.scale * 0.018
        glPushMatrix()


        #Translate to the center of the handle
        glTranslatef(self.center[0],
                     self.center[1],
                     self.center[2])

        #Bruce suggested undoing the glpane.quat rotation and plane quat
        #rotation  before drawing the handle geometry. -- ninad 20070525

        parent_q = self.parent.quat

        if parent_q:
            glRotatef(-parent_q.angle * ONE_RADIAN,
                       parent_q.x,
                       parent_q.y,
                       parent_q.z)

        glpane_q = self.glpane.quat
        glRotatef(-glpane_q.angle * ONE_RADIAN,
                   glpane_q.x,
                   glpane_q.y,
                   glpane_q.z)

        drawPlane(env.prefs[selectionColor_prefs_key],
                  side,
                  side,
                  self.textureReady,
                  0.9,
                  SOLID         = True,
                  pickCheckOnly = self.pickCheckOnly)

        handle_hw = side/2.0 #handle's half width
        handle_hh = side/2.0 #handle's half height
        handle_corner = [V(-handle_hw,  handle_hh, 0.0),
                         V(-handle_hw, -handle_hh, 0.0),
                         V( handle_hw, -handle_hh, 0.0),
                         V( handle_hw,  handle_hh, 0.0)]

        if highlighted:
            drawLineLoop(orange, handle_corner, width = 6)
        else:
            drawLineLoop( black, handle_corner, width = 2)
        glPopMatrix()
Пример #12
0
    def build(self, name, assy, position, mol=None, createPrinted=False):
        """
        Build a nanotube from the parameters in the Property Manger dialog.
        """
        endPoint1, endPoint2 = self.getEndPoints()
        cntAxis = endPoint2 - endPoint1
        length = vlen(cntAxis)

        # This can take a few seconds. Inform the user.
        # 100 is a guess. --Mark 051103.
        if not createPrinted:
            # If it's a multi-wall tube, only print the "Creating" message once.
            if length > 100.0:
                env.history.message("This may take a moment...")
        PROFILE = False
        if PROFILE:
            sw = Stopwatch()
            sw.start()
        xyz = self.xyz
        if mol == None:
            mol = Chunk(assy, name)
        atoms = mol.atoms
        mlimits = self.mlimits
        # populate the tube with some extra carbons on the ends
        # so that we can trim them later
        self.populate(mol, length + 4 * self.maxlen)

        # Apply twist and distortions. Bends probably would come
        # after this point because they change the direction for the
        # length. I'm worried about Z distortion because it will work
        # OK for stretching, but with compression it can fail. BTW,
        # "Z distortion" is a misnomer, we're stretching in the Y
        # direction.
        for atm in atoms.values():
            # twist
            x, y, z = atm.posn()
            twistRadians = self.twist * z
            c, s = cos(twistRadians), sin(twistRadians)
            x, y = x * c + y * s, -x * s + y * c
            atm.setposn(V(x, y, z))
        for atm in atoms.values():
            # z distortion
            x, y, z = atm.posn()
            z *= (self.zdist + length) / length
            atm.setposn(V(x, y, z))
        length += self.zdist
        for atm in atoms.values():
            # xy distortion
            x, y, z = atm.posn()
            radius = self.getRadius()
            x *= (radius + 0.5 * self.xydist) / radius
            y *= (radius - 0.5 * self.xydist) / radius
            atm.setposn(V(x, y, z))

        # Judgement call: because we're discarding carbons with funky
        # valences, we will necessarily get slightly more ragged edges
        # on nanotubes. This is a parameter we can fiddle with to
        # adjust the length. My thought is that users would prefer a
        # little extra length, because it's fairly easy to trim the
        # ends, but much harder to add new atoms on the end.
        LENGTH_TWEAK = self.getBondLength()

        # trim all the carbons that fall outside our desired length
        # by doing this, we are introducing new singlets
        for atm in atoms.values():
            x, y, z = atm.posn()
            if (z > .5 * (length + LENGTH_TWEAK)
                    or z < -.5 * (length + LENGTH_TWEAK)):
                atm.kill()

        # Apply bend. Equations are anomalous for zero bend.
        if abs(self.bend) > pi / 360:
            R = length / self.bend
            for atm in atoms.values():
                x, y, z = atm.posn()
                theta = z / R
                x, z = R - (R - x) * cos(theta), (R - x) * sin(theta)
                atm.setposn(V(x, y, z))

        def trimCarbons():
            """
            Trim all the carbons that only have one carbon neighbor.
            """
            for i in range(2):
                for atm in atoms.values():
                    if not atm.is_singlet() and len(atm.realNeighbors()) == 1:
                        atm.kill()

        trimCarbons()

        # If we're not picky about endings, we don't need to trim carbons
        if self.endings == "Capped":
            # buckyball endcaps
            addEndcap(mol, length, self.getRadius())
        if self.endings == "Hydrogen":
            # hydrogen terminations
            for atm in atoms.values():
                atm.Hydrogenate()
        elif self.endings == "Nitrogen":
            # nitrogen terminations.
            # This option has been removed from the "Endings" combo box
            # in the PM. 2008-05-02 --mark
            dstElem = PeriodicTable.getElement('N')
            atomtype = dstElem.find_atomtype('sp2')
            for atm in atoms.values():
                if len(atm.realNeighbors()) == 2:
                    atm.Transmute(dstElem, force=True, atomtype=atomtype)

        # Translate structure to desired position
        for atm in atoms.values():
            v = atm.posn()
            atm.setposn(v + position)

        if PROFILE:
            t = sw.now()
            env.history.message(
                greenmsg("%g seconds to build %d atoms" %
                         (t, len(atoms.values()))))

        if self.numwalls > 1:
            n += int(self.spacing * 3 + 0.5)  # empirical tinkering
            self.build(name,
                       assy,
                       endPoint1,
                       endPoint2,
                       position,
                       mol=mol,
                       createPrinted=True)

        # Orient the nanotube.
        if self.numwalls == 1:
            # This condition ensures that MWCTs get oriented only once.
            self._orient(mol, endPoint1, endPoint2)

        return mol
Пример #13
0
 def add(element, x, y, z, atomtype='sp2'):
     atm = Atom(element, V(x, y, z), mol)
     atm.set_atomtype_but_dont_revise_singlets(atomtype)
     return atm
Пример #14
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
Пример #15
0
 def __right(self, _q=V(1, 0, 0)):
     return self.quat.unrot(_q)
class EditNanotube_ResizeHandle(DraggableHandle_AlongLine):
    """
    Provides a resize handle for editing the length of an existing NanotubeSegment.
    """

    #Handle color will be changed depending on whether the the handle is grabbed
    #So this is a 'State variable and its value is used in 'appearance'
    #(given as an optional argument to 'Sphere')
    handleColor = State(Color, olive)

    #The state ref that determines the radius (of the sphere) of this handle.
    #See EditNanotube_EditCommand._determine_resize_handle_radius() for more
    #details
    sphereRadius = Option(StateRef, 1.2)

    #Stateusbar text. Variable needs to be renamed in superclass.
    sbar_text = Option(str,
                       "Drag the handle to resize the segment",
                       doc="Statusbar text on mouseover")

    #Command object specified as an 'Option' during instantiation of the class
    #see EditNanotube_EditCommand class definition.
    command = Option(Action, doc='The Command which instantiates this handle')

    #Current position of the handle. i.e. it is the position of the handle
    #under the mouse. (its differert than the 'orifinal position)
    #This variable is used in self.command.graphicsMode to draw a rubberband
    #line  and also to specify the endPoint2 of the structure while modifying
    #it. See EditNanotube_EditCommand.modifyStructure for details.
    currentPosition = _self.origin + _self.direction * _self.height_ref.value

    #Fixed end of the structure (self.command.struct) ..meaning that end won't
    #move while user grabbs and draggs this handle (attached to a the other
    #'moving endPoint) . This variable is used to specify endPoint1 of the
    #structure while modifyin it.  See EditNanotube_EditCommand.modifyStructure
    #and self.on_release for details.
    fixedEndOfStructure = Option(Point, V(0, 0, 0))

    #If this is false, the 'highlightable' object i.e. this handle
    #won't be drawn. See DraggableHandle.py for the declararion of
    #the delegate(that defines a Highlightable) We define a If_Exprs to check
    #whether to draw the highlightable object.
    should_draw = State(bool, True)

    appearance = Overlay(
        Sphere(_self.sphereRadius, handleColor, center=ORIGIN),
        Arrow(color=handleColor,
              arrowBasePoint=ORIGIN +
              _self.direction * 2.0 * _self.sphereRadius,
              tailPoint=ORIGIN,
              tailRadius=_self.sphereRadius * 0.3,
              scale=_self.command.glpane.scale))

    HHColor = env.prefs[hoverHighlightingColor_prefs_key]
    appearance_highlighted = Option(
        Drawable,
        Overlay(
            Sphere(_self.sphereRadius, HHColor, center=ORIGIN),
            Arrow(color=HHColor,
                  arrowBasePoint=ORIGIN +
                  _self.direction * 2.0 * _self.sphereRadius,
                  tailPoint=ORIGIN,
                  tailRadius=_self.sphereRadius * 0.3,
                  scale=_self.command.glpane.scale)))

    def on_press(self):
        """
        Actions when handle is pressed (grabbed, during leftDown event)
        @see: B{SelectChunks.GraphicsMode.leftDown}
        @see: B{EditNanotube_EditCommand.grabbedHandle}
        @see: B{EditNanotube_GraphicsMode.Draw} (which uses some attributes of
             the current grabbed handle of the command.
        @see: B{DragHandle_API}
        """
        #Change the handle color when handle is grabbed. See declaration of
        #self.handleColor in the class definition.
        self.handleColor = env.prefs[selectionColor_prefs_key]
        #assign 'self' as the curent grabbed handle of the command.
        self.command.grabbedHandle = self

    def on_drag(self):
        """
        Method called while dragging this handle .
        @see: B{DragHandle_API}
        """
        #Does nothing at the moment.
        pass

    def on_release(self):
        """
        This method gets called during leftUp (when the handle is released)
        @see: B{EditNanotube_EditCommand.modifyStructure}
        @see: self.on_press
        @see: B{SelectChunks.GraphicsMode.leftUp}
        @see: B{DragHandle_API}
        """
        self.handleColor = olive
        if self.command and hasattr(self.command, 'modifyStructure'):
            self.command.modifyStructure()
            #Clear the grabbed handle attribute (the handle is no longer
            #grabbed)
            self.command.grabbedHandle = None

    def hasValidParamsForDrawing(self):
        """
        Returns True if the handles origin and direction are not 'None'.

        @see: NanotubeSesgment_GraphicsMode._draw_handles() where the caller
              uses this to decide whether this handle can be drawn without
              a problem.
        """
        #NOTE: Better to do it in the drawing code of this class?
        #But it uses a delegate to draw stuff (see class Highlightable)
        #May be we should pass this method to that delegate as an optional
        #argument -- Ninad 2008-04-02

        #NOTES: See also:
        #delegate in class DraggableHandle defined as --
        #delegate = If_Exprs(_self.should_draw, Highlightable(....))
        if self.origin is None:
            self.should_draw = False
        else:
            self.should_draw = True

        return self.should_draw
Пример #17
0
 def __left(self, _q=V(-1, 0, 0)):
     return self.quat.unrot(_q)
    def leftADown(self, objectUnderMouse, event):
        """
        Method called during mouse left down . It sets some parameters
        necessary for rotating the structure around its own axis (during
        a left drag to follow) In graphics modes such as
        RotateChunks_GraphicsMode, rotating entities around their own axis is
        acheived by holding down 'A' key and then left dragging , thats why the
        method is named as 'leftADrag'  (A= Axis)
        """
        ma = V(0, 0, 0)

        if self.command and self.command.struct:
            ma = self.command.struct.getAxisVector()

        self._axis_for_constrained_motion = self.command.struct.getAxisVector()

        #@see: NanotubeSegment.get_all_content_chunks() for details about
        #what it returns. See also NanotubeSegment.isAncestorOf() which
        #is called in self.leftDown to determine whether the NanotubeSegment
        #user is editing is an ancestor of the selobj. (it also considers
        #'logical contents' while determining whether it is an ancestor.
        #-- Ninad 2008-03-11
        self._movablesForLeftDrag = self.command.struct.get_all_content_chunks(
        )

        ma = norm(V(dot(ma, self.o.right), dot(ma, self.o.up)))

        self.Zmat = A([ma, [-ma[1], ma[0]]])

        obj = objectUnderMouse

        if obj is None:  # Cursor over empty space.
            self.emptySpaceLeftDown(event)
            #Left A drag is not possible unless the cursor is over a
            #selected object. So make sure to let self.leftAError method sets
            #proper flag so that left-A drag won't be done in this case.
            return

        if isinstance(obj, Atom):
            self._translateAlongAxis = True
            self._rotateAboutAxis = False
            self._freeDragWholeStructure = False
        elif 0:  #@@@ isinstance(obj, Atom): # Rotate about axis not supported.
            self._translateAlongAxis = False
            self._rotateAboutAxis = True
            self._freeDragWholeStructure = False
            #The self._commonCenterForrotation is a point on segment axis
            #about which the whole segment will be rotated. Specifying this
            #as a common center  for rotation fixes bug 2578. We determine this
            #by selecting the center of the axis atom that is connected
            #(bonded) to the strand atom being left dragged. Using this as a
            #common center instead of the avaraging the center of the segment
            #axis atoms has an advantage. We compute the rotation offset 'dy'
            #with reference to the strand atom being dragged, so it seems more
            #appropriate to use the nearest axis center for segment rotation
            #about axis. But what happens if the axis is not straigt but is
            #curved? Should we select the averaged center of all axis atoms?
            #..that may not be right. Or should we take _average center_ of
            #a the following axis atoms --strand atoms axis_neighbors and
            #axis atom centers directly connected to this axis atom.
            #  -- Ninad 2008-03-25
            self._commonCenterForRotation = obj.axis_neighbor().posn()
        elif isinstance(obj, Bond):
            self._translateAlongAxis = False
            self._rotateAboutAxis = False
            self._freeDragWholeStructure = True

        self.o.SaveMouse(event)
        self.dragdist = 0.0
        return
Пример #19
0
 def __down(self, _q=V(0, -1, 0)):
     return self.quat.unrot(_q)
    def leftDrag(self, event):
        """
        Method called during Left drag event.
        """
        if self.mouse_within_stickiness_limit(event, DRAG_STICKINESS_LIMIT):
            # [let this happen even for drag_handlers -- bruce 060728]
            return

        self.current_obj_clicked = False

        #If there is a drag handler (e.g. a segment resize handle is being
        #dragged, call its drag method and don't proceed further.

        #NOTE:
        #In SelectChunks_GraphicsMode.leftDrag, there is a condition statement
        #which checks if self.drag_handler is in assy.getSelecteedMovables
        #I don't know why it does that... I think it always assums that the
        #drag handler is officially a node in the MT? In our case,
        #the drag handler is a 'Highlightable' object (actually
        #an instance of 'EditNanotube_ResizeHandle' (has superclass from
        #exprs module ..which implements API for a highlightable object
        #So it doesn't get registered in the selectMovables list. Thats why
        #we are not calling _superclass.leftDrag. The above mentioned
        #method in the superclass needs to be revised -- Ninad 2008-02-01

        if self.drag_handler is not None:
            self.dragHandlerDrag(self.drag_handler, event)
            return

        #If the cursor was not over something that belonged to structure
        #being edited (example - atom or bond of a differnt NanotubeSegment)
        #don't do left drag.(left drag will work only for the NanotubeSegment
        #eing edited)
        if self.cursor_over_when_LMB_pressed != 'Structure Being Edited':
            return

        #Duplicates some code from SelectChunks_GraphicsMode.leftDrag
        #see a to do comment below in this method
        if self.cursor_over_when_LMB_pressed == 'Empty Space':
            self.emptySpaceLeftDrag(event)
            return

        if self.o.modkeys is not None:
            # If a drag event has happened after the cursor was over an atom
            # and a modkey is pressed, do a 2D region selection as if the
            # atom were absent.
            self.emptySpaceLeftDown(self.LMB_press_event)
            #bruce 060721 question: why don't we also do emptySpaceLeftDrag
            # at this point?
            return

        #TODO: This duplicates some code from SelectChunks_GraphicsMode.leftDrag

        #Following code will never be called if a handle is grabbed.
        #Thus, it instructs what to do for other cases (when user is not moving
        #the draggable handles)

        #First, don't draw handles (set the flag here so that self.Draw_other knows
        #not to draw handles) This skips unnecessary computation of new handle
        #position during left dragging. The flag is reset to True in leftUp
        if self.command and self.command.handles:
            if self.command.grabbedHandle is None:
                self._handleDrawingRequested = False

        #Copies AND modifies some code from Move_GraphicsMode for doing
        #leftDrag translation or rotation.

        w = self.o.width + 0.0
        h = self.o.height + 0.0
        deltaMouse = V(event.pos().x() - self.o.MousePos[0],
                       self.o.MousePos[1] - event.pos().y())

        a = dot(self.Zmat, deltaMouse)
        dx, dy = a * V(self.o.scale / (h * 0.5), 2 * math.pi / w)

        offset = None

        if self._translateAlongAxis:
            offset = dx * self._axis_for_constrained_motion
            for mol in self._movablesForLeftDrag:
                mol.move(offset)

        if self._rotateAboutAxis:
            rotation_quat = Q(self._axis_for_constrained_motion, -dy)
            self.o.assy.rotateSpecifiedMovables(
                rotation_quat,
                movables=self._movablesForLeftDrag,
                commonCenter=self._commonCenterForRotation)

        if self._freeDragWholeStructure:
            try:
                point = self.dragto(self.movingPoint, event)
                offset = point - self.movingPoint
                self.o.assy.translateSpecifiedMovables(
                    offset, movables=self._movablesForLeftDrag)
                self.movingPoint = point
            except:
                #may be self.movingPoint is not defined in leftDown?
                #(e.g. _superclass.leftDown doesn't get called or as a bug? )
                print_compact_traceback(
                    "bug:unable to free drag the whole segment")

        if offset:  # Update the nanotube endpoints.
            endPt1, endPt2 = self.command.struct.nanotube.getEndPoints()
            endPt1 += offset
            endPt2 += offset
            self.command.struct.nanotube.setEndPoints(endPt1, endPt2)

        self.dragdist += vlen(deltaMouse)  #k needed?? [bruce 070605 comment]

        self.o.SaveMouse(event)
        self.o.assy.changed()  #ninad060924 fixed bug 2278
        self.o.gl_update()
        return
Пример #21
0
 def __lineOfSight(self, _q=V(0, 0, -1)):
     return self.quat.unrot(_q)
Пример #22
0
 def _hashAtomPos(self, pos):
     return int(dot(V(1000000, 1000, 1), floor(pos * 1.2)))
Пример #23
0
 def viewFlipViewVert(self):
     """
     Flip view vertically.
     """
     self.glpane.rotateView(self.glpane.quat + Q(V(0, 1, 0), math.pi))
Пример #24
0
    def _createStructure(self):
        """
        Creates and returns the structure (in this case a L{Group} object that
        contains the DNA strand and axis chunks.
        @return : group containing that contains the DNA strand and axis chunks.
        @rtype: L{Group}
        @note: This needs to return a DNA object once that model is implemented
        """

        params = self._gatherParameters()

        # No error checking in build_struct, do all your error
        # checking in gather_parameters
        numberOfBases, \
                     dnaForm, \
                     dnaModel, \
                     basesPerTurn, \
                     duplexRise, \
                     endPoint1, \
                     endPoint2 = params

        if numberOfBases < 2:
            #Don't create a duplex with only one or 0 bases!
            #Reset a few variables. This should be done by calling a separate
            #method on command (there is similar code in self.createStructures)
            #as well.
            self.mouseClickPoints = []
            self.graphicsMode.resetVariables()

            msg  = redmsg("Cannot preview/insert a DNA duplex with less than 2 base pairs.")
            self.propMgr.updateMessage(msg)

            self.dna = None # Fixes bug 2530. Mark 2007-09-02
            return None
        else:
            msg = "Click two more endpoints to insert another DNA duplex."
            self.propMgr.updateMessage(msg)


        #If user enters the number of basepairs and hits preview i.e. endPoint1
        #and endPoint2 are not entered by the user and thus have default value
        #of V(0, 0, 0), then enter the endPoint1 as V(0, 0, 0) and compute
        #endPoint2 using the duplex length.
        #Do not use '==' equality check on vectors! its a bug. Use same_vals
        # or Veq instead.
        if Veq(endPoint1 , endPoint2) and Veq(endPoint1, V(0, 0, 0)):
            endPoint2 = endPoint1 + \
                      self.win.glpane.right * \
                      getDuplexLength('B-DNA', numberOfBases)

        if dnaForm == 'B-DNA':
            if dnaModel == 'PAM3':
                dna = B_Dna_PAM3_Generator()
            elif dnaModel == 'PAM5':
                dna = B_Dna_PAM5_Generator()
            else:
                print "bug: unknown dnaModel type: ", dnaModel
        else:
            raise PluginBug("Unsupported DNA Form: " + dnaForm)

        self.dna  =  dna  # needed for done msg

        # self.name needed for done message
        if self.create_name_from_prefix:
            # create a new name
            name = self.name = gensym(self.prefix, self.win.assy) # (in _build_struct)
            self._gensym_data_for_reusing_name = (self.prefix, name)
        else:
            # use externally created name
            self._gensym_data_for_reusing_name = None
                # (can't reuse name in this case -- not sure what prefix it was
                #  made with)
            name = self.name


        # Create the model tree group node.
        # Make sure that the 'topnode'  of this part is a Group (under which the
        # DNa group will be placed), if the topnode is not a group, make it a
        # a 'Group' (applicable to Clipboard parts).See part.py
        # --Part.ensure_toplevel_group method. This is an important line
        # and it fixes bug 2585
        self.win.assy.part.ensure_toplevel_group()

        if self._parentDnaGroup is None:
            print_compact_stack("bug: Parent DnaGroup in InsertDna_EditCommand"\
                                "is None. This means the previous command "\
                                "was not 'BuildDna_EditCommand' Ignoring for now")
            if self._fallbackDnaGroup is None:
                self._createFallbackDnaGroup()

            dnaGroup = self._fallbackDnaGroup
        else:
            dnaGroup = self._parentDnaGroup


        dnaSegment = DnaSegment(self.name,
                                self.win.assy,
                                dnaGroup,
                                editCommand = self  )
        try:
            # Make the DNA duplex. <dnaGroup> will contain three chunks:
            #  - Strand1
            #  - Strand2
            #  - Axis
            dna.make(dnaSegment,
                     numberOfBases,
                     basesPerTurn,
                     duplexRise,
                     endPoint1,
                     endPoint2)

            #set some properties such as duplexRise and number of bases per turn
            #This information will be stored on the DnaSegment object so that
            #it can be retrieved while editing this object.
            #This works with or without dna_updater. Now the question is
            #should these props be assigned to the DnaSegment in
            #dnaDuplex.make() itself ? This needs to be answered while modifying
            #make() method to fit in the dna data model. --Ninad 2008-03-05

            #WARNING 2008-03-05: Since self._modifyStructure calls
            #self._createStructure() If in the near future, we actually permit
            #modifying a
            #structure (such as dna) without actually recreating the whole
            #structre, then the following properties must be set in
            #self._modifyStructure as well. Needs more thought.
            props = (duplexRise, basesPerTurn)

            dnaSegment.setProps(props)

            return dnaSegment


        except (PluginBug, UserError):
            # Why do we need UserError here? Mark 2007-08-28
            dnaSegment.kill_with_contents()
            raise PluginBug("Internal error while trying to create DNA duplex.")
Пример #25
0
 def viewRotateMinus90(self):  # Added by Mark. 051013.
     """
     Decrement the current view by 90 degrees around the vertical axis.
     """
     self.glpane.rotateView(self.glpane.quat + Q(V(0, 1, 0), -math.pi / 2))
Пример #26
0
Bruce 071105 revised init code, and split PAM3 and PAM5 data into separate files.
"""

from geometry.VQT import V, A, norm
from utilities.constants import DIAMOND_BOND_LENGTH

_DIRECTIONAL_BOND_ELEMENTS_chemical = ('X',) # mark 071014

# ==

# the formations of bonds -- standard offsets

# (note: these are public symbols that can also be used in
#  element data files for pseudoatoms)

uvec = norm(V(1,1,1))
tetra4 = uvec * A([[1,1,1], [-1,1,-1], [-1,-1,1], [1,-1,-1]])
tetra3 = uvec * A([[-1,1,-1], [-1,-1,1], [1,-1,-1]])
oxy2 = A([[-1,0,0], [0.2588, -0.9659, 0]])
tetra2 = A([[-1,0,0], [0.342, -0.9396, 0]])
straight = A([[-1,0,0], [1,0,0]])
flat = A([[-0.5,0.866,0], [-0.5,-0.866,0], [1,0,0]])
onebond = A([[1,0,0]]) # for use with valence-1 elements

# mark 060129. New default colors for Alpha 7.
_defaultRadiusAndColor = {
    "X": (1.1,  [0.8, 0.0, 0.0]),
    "H" : (1.2,  [0.78, 0.78, 0.78]),
    "He" : (1.4,  [0.42, 0.45, 0.55]),
    "Li" : (4.0,  [0.0, 0.5, 0.5]),
    "Be" : (3.0,  [0.98, 0.67, 1.0]),
Пример #27
0
 def viewBottom(self):
     cmd = greenmsg("Bottom View: ")
     info = 'Current view is Bottom View'
     env.history.message(cmd + info)
     self.glpane.rotateView(Q(V(1, 0, 0), -math.pi / 2))
Пример #28
0
from utilities import debug_flags
from model.jigs import Jig
from geometry.VQT import V, Q, A, cross, vlen, norm, twistor_angle

from operations.bond_chains import grow_bond_chain

from model.bond_constants import V_SINGLE
from model.bond_constants import V_DOUBLE
from model.bond_constants import V_TRIPLE
from model.bond_constants import V_AROMATIC
from model.bond_constants import V_GRAPHITE
from model.bond_constants import V_CARBOMERIC

DFLT_OUT = V(
    0.0, -0.6, 0.8
)  # these are rotated from standard out = V(0,0,1), up = V(0,1,0) but still orthonormal
DFLT_UP = V(0.0, 0.8, 0.6)

# _recompile_counter is useful for development, and is harmless otherwise
try:
    _recompile_counter
except:
    _recompile_counter = 1
else:
    # increment the counter only when the module got recompiled, not just when it got reloaded from the same .pyc file
    if __file__.endswith(".py"):
        _recompile_counter += 1
        print "_recompile_counter incremented to", _recompile_counter
    else:
        pass  ## print "_recompile_counter unchanged at", _recompile_counter
Пример #29
0
    def viewTop(self):
        cmd = greenmsg("Top View: ")
        info = 'Current view is Top View'
        env.history.message(cmd + info)

        self.glpane.rotateView(Q(V(1, 0, 0), math.pi / 2))
Пример #30
0
def planepoint(v, i, j, k):
    mat = V(polyMat[i], polyMat[j], polyMat[k])
    vec = V(v[i], v[j], v[k])
    return solve_linear_equations(mat, vec)