Пример #1
0
 def __init__(self, *args, **kwargs):
     super(SquarePart, self).__init__(self, *args, **kwargs)
     self._maxRow = kwargs.get('maxRow', app().prefs.squareRows)
     self._maxCol = kwargs.get('maxCol', app().prefs.squareCols)
     self._maxBase = int(
         kwargs.get('maxSteps',
                    app().prefs.squareSteps) * self._step - 1)
Пример #2
0
 def __init__(self, *args, **kwargs):
     super(HoneycombPart, self).__init__(self, *args, **kwargs)
     self._maxRow = kwargs.get('maxRow', app().prefs.honeycombRows)
     self._maxCol = kwargs.get('maxCol', app().prefs.honeycombCols)
     self._maxBase = int(
         kwargs.get('maxSteps',
                    app().prefs.honeycombSteps) * self._step - 1)
Пример #3
0
 def __init__(self):
     super(Document, self).__init__()
     self._undoStack = QUndoStack()
     self._parts = []
     self._assemblies = []
     self._controller = None
     self._selectedPart = None
     # the dictionary maintains what is selected
     self._selectionDict = {}
     # the added list is what was recently selected or deselected
     self._selectedChangedDict = {}
     cadnano.app().documentWasCreatedSignal.emit(self)
Пример #4
0
    def staplePreDecoratorSelected(self, listNames):
        """
        Callback function that is called from mayaSelectionContext when a
        PreDecorator geometry is called, notifies the Part Model of this
        event. XXX - [SB] In the future we should clean up this interaction.
        """
        if (len(listNames) > 1):
            # If we have more than one PreDecorator Selected, deselect all but
            # the last one
            cmds.select(listNames[0:len(listNames) - 1], deselect=True)

        selectionList = []

        for name in listNames:
            if name in self.decoratorToVirtualHelixItem:
                (virtualHelixItem, baseIdx, strand) = \
                                        self.decoratorToVirtualHelixItem[name]
                selectionList.append(
                    (virtualHelixItem.row(), virtualHelixItem.col(), baseIdx))
        if len(selectionList) == 0 and \
           self.selectionCountCache == 0:
            # a dumb cache check to prevent deselection to be broadcasted too
            # many times, but could cause problems
            return

        # XXX - [SB] we want to only send the signal to "active part" but
        # not sure how to get that
        for doc in app().documentControllers:
            if doc.win.actionModify.isChecked():
                for partItem in doc.win.solidroot.partItems():
                    partModel = partItem.part()
                    partModel.selectPreDecorator(selectionList)
        self.selectionCountCache = len(selectionList)
Пример #5
0
 def __init__(self, mID, modelStrand, virtualHelixItem):
     """
     The parent should be a VirtualHelixItem.
     Initialize function creates the Maya Node for the strand, and setups
     the lookup tables inside of mayaObjectManager (Mom) so that the Maya
     Node can be globally found given a strand, and the other way around.
     Also, sets up StrandItemController that is used to setup all the
     slots and signals between strand model and this strandItem.
     """
     self._modelStrand = modelStrand
     self._virtualHelixItem = virtualHelixItem
     self._viewroot = app().activeDocument.win.solidroot
     mayaNodeInfo = ()
     # print "solidview.StrandItem.__init__ %s" % mID
     if (modelStrand.strandSet().isScaffold()):
         mayaNodeInfo = self.createMayaHelixNodes(
             virtualHelixItem.x(), virtualHelixItem.y(),
             modelStrand.oligo().color(), StrandType.Scaffold, mID)
     else:
         mayaNodeInfo = self.createMayaHelixNodes(
             virtualHelixItem.x(), virtualHelixItem.y(),
             modelStrand.oligo().color(), StrandType.Staple, mID)
     #self.onStrandDidMove(strand)
     m = Mom()
     m.cnToMaya[modelStrand] = mayaNodeInfo
     m.mayaToCn[mayaNodeInfo[2]] = modelStrand
     m.mayaToCn[mayaNodeInfo[0]] = modelStrand
     self.updateSize()
     self._controller = StrandItemController(self, modelStrand)
Пример #6
0
    def doRelease(self):
        # print "RELEASED"

        self.isMouseDown = False

        if(self.deltaFront != 0):
            app().activeDocument.document().resizeSelection(self.deltaFront)

        if(self.deltaBack != 0):
            app().activeDocument.document().resizeSelection(self.deltaBack)

        m = Mom()
        m.strandsSelected(self.helicesNames, (True, True))

        cmds.hide(helixManip.transformName)

        self.frontDistance = 0
        self.backDistance = 0

        return OpenMaya.kUnknownParameter
Пример #7
0
    def safeScale(self, delta):
        currentScaleLevel = self.transform().m11()
        scaleFactor = 1 + delta * \
           (self._scaleDownRate if delta < 0 else self._scaleUpRate) * \
           (app().prefs.zoomSpeed/100.)
        newScaleLevel = currentScaleLevel * scaleFactor
        newScaleLevel = util.clamp(currentScaleLevel * scaleFactor,\
                              self._scale_limit_min,\
                              self._scale_limit_max)
        scaleChange = newScaleLevel / currentScaleLevel
        self.scale(scaleChange, scaleChange)

        self.resetGL()
Пример #8
0
 def _addBasesCallback(self, n):
     """
     Given a user-chosen number of bases to add, snap it to an index
     where index modulo stepsize is 0 and calls resizeVirtualHelices to
     adjust to that size.
     """
     part = self._modelPart
     self._addBasesDialog.intValueSelected.disconnect(
         self._addBasesCallback)
     del self._addBasesDialog
     maxDelta = int(n / part.stepSize()) * part.stepSize()
     part.resizeVirtualHelices(0, maxDelta)
     if app().isInMaya():
         import maya.cmds as cmds
         cmds.select(clear=True)
Пример #9
0
    def strandsSelected(self, listNames, value=(True, True)):
        if self.ignoreExternalSelectionSignal:
            return

        self.ignoreExternalSelectionSignal = True
        strandList = []
        for nodeName in listNames:
            if (nodeName in self.mayaToCn):
                strandList.append(self.mayaToCn[nodeName])
        doc = app().activeDocument
        # # XXX [SB] THIS IS A HACK, should not need to do this!!!
        # doc.win.pathroot.clearStrandSelections()

        doc.win.solidroot.selectedChanged(strandList, value)
        self.ignoreExternalSelectionSignal = False
Пример #10
0
    def __init__(self, win):
        super(PathToolManager, self).__init__()
        self.window = win
        self._activeTool = None
        self._activePart = None
        self.selectTool = SelectTool(self)
        self.pencilTool = PencilTool(self)
        self.breakTool = BreakTool(self)
        self.eraseTool = EraseTool(self)
        self.insertionTool = InsertionTool(self)
        self.skipTool = SkipTool(self)
        self.paintTool = PaintTool(
            self)  # (self, win.pathGraphicsView.toolbar)
        self.addSeqTool = AddSeqTool(self)

        def installTool(toolName, window):
            toolWidget = getattr(window, 'actionPath' + toolName)
            lToolName = toolName[0].lower() + toolName[1:]
            tool = getattr(self, lToolName + 'Tool')
            tool.actionName = 'actionPath' + toolName

            def clickHandler(self):
                toolWidget.setChecked(True)
                self.setActiveTool(tool)
                if hasattr(tool, 'widgetClicked'):
                    tool.widgetClicked()

            selectToolMethodName = 'choose' + toolName + 'Tool'
            setattr(self.__class__, selectToolMethodName, clickHandler)
            handler = getattr(self, selectToolMethodName)
            toolWidget.triggered.connect(handler)
            return toolWidget

        tools = ('Select', 'Pencil', 'Break', 'Erase', 'Insertion', 'Skip',
                 'Paint', 'AddSeq')
        ag = QActionGroup(win)
        # Call installTool on every tool
        list(
            map((lambda toolName: ag.addAction(installTool(toolName, win))),
                tools))
        ag.setExclusive(True)
        # Select the preferred Startup tool
        startupToolName = app().prefs.getStartupToolName()
        getattr(self, 'choose' + startupToolName + 'Tool')()
Пример #11
0
 def _removeBasesClicked(self):
     """
     Determines the minimum maxBase index where index modulo stepsize == 0
     and is to the right of the rightmost nonempty base, and then resize
     each calls the resizeVirtualHelices to adjust to that size.
     """
     part = self._modelPart
     stepSize = part.stepSize()
     # first find out the right edge of the part
     idx = part.indexOfRightmostNonemptyBase()
     # next snap to a multiple of stepsize
     idx = int(ceil(float(idx + 1) / stepSize)) * stepSize
     # finally, make sure we're a minimum of stepSize bases
     idx = util.clamp(idx, part.stepSize(), 10000)
     delta = idx - (part.maxBaseIdx() + 1)
     if delta < 0:
         part.resizeVirtualHelices(0, delta)
         if app().isInMaya():
             import maya.cmds as cmds
             cmds.select(clear=True)
Пример #12
0
    def mouseReleaseEvent(self, event):
        """docstring for mouseReleaseEvent"""
        part = self.part()
        uS = part.undoStack()
        strands = []
        # Look at the undo stack in reverse order
        for i in range(uS.index()-1, 0, -1):
            # Check for contiguous strand additions
            m = _strand_re.match(uS.text(i))
            if m:
                strands.insert(0, list(map(int, m.groups())))
            else:
                break

        if len(strands) > 1:
            autoScafType = app().prefs.getAutoScafType()
            util.beginSuperMacro(part, "Auto-connect")
            if autoScafType == "Mid-seam":
                self.autoScafMidSeam(strands)
            elif autoScafType == "Raster":
                self.autoScafRaster(strands)
            util.endSuperMacro(part)
Пример #13
0
def decode(document, string):
    if cadnano.app().isGui():
        # from ui.dialogs.ui_latticetype import Ui_LatticeType
        # util.qtWrapImport('QtGui', globals(),  ['QDialog', 'QDialogButtonBox'])
        dialog = QDialog()
        dialogLT = Ui_LatticeType()  # reusing this dialog, should rename
        dialogLT.setupUi(dialog)

    # try:  # try to do it fast
    #     try:
    #         import cjson
    #         packageObject = cjson.decode(string)
    #     except:  # fall back to if cjson not available or on decode error
    #         packageObject = json.loads(string)
    # except ValueError:
    #     dialogLT.label.setText("Error decoding JSON object.")
    #     dialogLT.buttonBox.setStandardButtons(QDialogButtonBox.Ok)
    #     dialog.exec()
    #     return
    packageObject = json.loads(string)

    if packageObject.get('.format', None) != 'caDNAno2':
        import_legacy_dict(document, packageObject)
Пример #14
0
    def __init__(self, parent=None, docCtrlr=None):
        super(DocumentWindow, self).__init__(parent)
        self.controller = docCtrlr
        doc = docCtrlr.document()
        self.setupUi(self)
        self.settings = QSettings()
        self._readSettings()
        # Slice setup
        self.slicescene = QGraphicsScene(parent=self.sliceGraphicsView)
        self.sliceroot = SliceRootItem(rect=self.slicescene.sceneRect(),\
                                       parent=None,\
                                       window=self,\
                                       document=doc)
        self.sliceroot.setFlag(
            QGraphicsItem.GraphicsItemFlag.ItemHasNoContents)
        self.slicescene.addItem(self.sliceroot)
        self.slicescene.setItemIndexMethod(
            QGraphicsScene.ItemIndexMethod.NoIndex)
        assert self.sliceroot.scene() == self.slicescene
        self.sliceGraphicsView.setScene(self.slicescene)
        self.sliceGraphicsView.sceneRootItem = self.sliceroot
        self.sliceGraphicsView.setName("SliceView")
        self.sliceToolManager = SliceToolManager(self)
        # Path setup
        self.pathscene = QGraphicsScene(parent=self.pathGraphicsView)
        self.pathroot = PathRootItem(rect=self.pathscene.sceneRect(),\
                                     parent=None,\
                                     window=self,\
                                     document=doc)
        self.pathroot.setFlag(QGraphicsItem.GraphicsItemFlag.ItemHasNoContents)
        self.pathscene.addItem(self.pathroot)
        self.pathscene.setItemIndexMethod(
            QGraphicsScene.ItemIndexMethod.NoIndex)
        assert self.pathroot.scene() == self.pathscene
        self.pathGraphicsView.setScene(self.pathscene)
        self.pathGraphicsView.sceneRootItem = self.pathroot
        self.pathGraphicsView.setScaleFitFactor(0.9)
        self.pathGraphicsView.setName("PathView")
        self.pathColorPanel = ColorPanel()
        self.pathGraphicsView.toolbar = self.pathColorPanel  # HACK for customqgraphicsview
        self.pathscene.addItem(self.pathColorPanel)
        self.pathToolManager = PathToolManager(self)
        self.sliceToolManager.pathToolManager = self.pathToolManager
        self.pathToolManager.sliceToolManager = self.sliceToolManager
        self.tool_managers = (self.sliceToolManager, self.pathToolManager)

        # set the selection filter default
        doc.documentSelectionFilterChangedSignal.emit(
            ["endpoint", "scaffold", "staple", "xover"])

        self.pathGraphicsView.setupGL()
        self.sliceGraphicsView.setupGL()
        if GL:
            pass
            # self.slicescene.drawBackground = self.drawBackgroundGL
            # self.pathscene.drawBackground = self.drawBackgroundGL

        if app().isInMaya():
            from .solidview.solidrootitem import SolidRootItem
            self.splitter.setOrientation(Qt.Vertical)
            self.setUnifiedTitleAndToolBarOnMac(False)
            modState = self.actionModify.isChecked()
            self.solidroot = SolidRootItem(parent=None,
                                           document=doc,
                                           modState=modState)

        # Edit menu setup
        self.actionUndo = docCtrlr.undoStack().createUndoAction(self)
        self.actionRedo = docCtrlr.undoStack().createRedoAction(self)
        self.actionUndo.setText(
            QApplication.translate("MainWindow", "Undo", None))
        self.actionUndo.setShortcut(
            QApplication.translate("MainWindow", "Ctrl+Z", None))
        self.actionRedo.setText(
            QApplication.translate("MainWindow", "Redo", None))
        self.actionRedo.setShortcut(
            QApplication.translate("MainWindow", "Ctrl+Shift+Z", None))

        self.sep = QAction(self)
        self.sep.setSeparator(True)
        self.menuEdit.insertAction(self.actionModify, self.sep)
        self.menuEdit.insertAction(self.sep, self.actionRedo)
        self.menuEdit.insertAction(self.actionRedo, self.actionUndo)
        self.splitter.setSizes([400, 400])  # balance splitter size
        self.statusBar().showMessage("")
Пример #15
0
import json
from .legacydecoder import import_legacy_dict
from cadnano2.ui.dialogs.ui_latticetype import Ui_LatticeType
import cadnano2.util as util
import cadnano2.cadnano as cadnano
if cadnano.app().isGui():  # headless:
    from cadnano2.ui.dialogs.ui_latticetype import Ui_LatticeType
    util.qtWrapImport('QtWidgets', globals(), ['QDialog', 'QDialogButtonBox'])


def decode(document, string):
    if cadnano.app().isGui():
        # from ui.dialogs.ui_latticetype import Ui_LatticeType
        # util.qtWrapImport('QtGui', globals(),  ['QDialog', 'QDialogButtonBox'])
        dialog = QDialog()
        dialogLT = Ui_LatticeType()  # reusing this dialog, should rename
        dialogLT.setupUi(dialog)

    # try:  # try to do it fast
    #     try:
    #         import cjson
    #         packageObject = cjson.decode(string)
    #     except:  # fall back to if cjson not available or on decode error
    #         packageObject = json.loads(string)
    # except ValueError:
    #     dialogLT.label.setText("Error decoding JSON object.")
    #     dialogLT.buttonBox.setStandardButtons(QDialogButtonBox.Ok)
    #     dialog.exec()
    #     return
    packageObject = json.loads(string)
Пример #16
0
 def focusInEvent(self):
     app().undoGroup.setActiveStack(self.controller.undoStack())
Пример #17
0
from collections import defaultdict

from cadnano2.model.document import Document
from cadnano2.model.enum import LatticeType, StrandType
from cadnano2.model.parts.honeycombpart import HoneycombPart
from cadnano2.model.parts.squarepart import SquarePart
from cadnano2.model.virtualhelix import VirtualHelix
from cadnano2.views import styles
import cadnano2.util as util
import cadnano2.cadnano as cadnano
# import Qt stuff into the module namespace with PySide, PyQt4 independence
util.qtWrapImport('QtGui', globals(), ['QColor'])
if cadnano.app().isGui():
    from cadnano2.ui.dialogs.ui_latticetype import Ui_LatticeType
    util.qtWrapImport('QtWidgets', globals(), ['QDialog', 'QDialogButtonBox'])

NODETAG = "node"
NAME = "name"
OBJ_ID = "objectid"
INST_ID = "instanceid"
DONE = "done"
CHECKED = "check"
LOCKED = "locked"

VHELIX = "vhelix"
NUM = "num"
COL = "col"
ROW = "row"
SCAFFOLD = "scaffold"
STAPLE = "staple"
INSERTION = "insertion"
Пример #18
0
def import_legacy_dict(document, obj, latticeType=LatticeType.Honeycomb):
    """
    Parses a dictionary (obj) created from reading a json file and uses it
    to populate the given document with model data.
    """
    numBases = len(obj['vstrands'][0]['scaf'])
    if cadnano.app().isGui():
        # from ui.dialogs.ui_latticetype import Ui_LatticeType
        # util.qtWrapImport('QtGui', globals(),  ['QDialog', 'QDialogButtonBox'])
        dialog = QDialog()
        dialogLT = Ui_LatticeType()
        dialogLT.setupUi(dialog)
        # DETERMINE LATTICE TYPE
        if numBases % 21 == 0 and numBases % 32 == 0:
            if dialog.exec() == 1:
                latticeType = LatticeType.Square
            else:
                latticeType = LatticeType.Honeycomb
        elif numBases % 32 == 0:
            latticeType = LatticeType.Square
        elif numBases % 21 == 0:
            latticeType = LatticeType.Honeycomb
        else:
            if dialog.exec() == 1:
                latticeType = LatticeType.Square
            else:
                latticeType = LatticeType.Honeycomb
    else:  # Headless, assume the latticeType arg was meaningful
        pass

    # DETERMINE MAX ROW,COL
    maxRowJson = maxColJson = 0
    for helix in obj['vstrands']:
        maxRowJson = max(maxRowJson, int(helix['row']) + 1)
        maxColJson = max(maxColJson, int(helix['col']) + 1)

    # CREATE PART ACCORDING TO LATTICE TYPE
    if latticeType == LatticeType.Honeycomb:
        steps = numBases / 21
        nRows = max(30, maxRowJson, cadnano.app().prefs.honeycombRows)
        nCols = max(32, maxColJson, cadnano.app().prefs.honeycombCols)
        part = HoneycombPart(document=document,
                             maxRow=nRows,
                             maxCol=nCols,
                             maxSteps=steps)
    elif latticeType == LatticeType.Square:
        isSQ100 = True  # check for custom SQ100 format
        for helix in obj['vstrands']:
            if helix['col'] != 0:
                isSQ100 = False
                break
        if isSQ100:
            dialogLT.label.setText("Is this a SQ100 file?")
            if dialog.exec() == 1:
                nRows, nCols = 100, 1
            else:
                nRows, nCols = 40, 30
        else:
            nRows, nCols = 40, 30
        steps = numBases / 32
        nRows = max(30, maxRowJson, cadnano.app().prefs.squareRows)
        nCols = max(32, maxColJson, cadnano.app().prefs.squareCols)
        part = SquarePart(document=document,
                          maxRow=nRows,
                          maxCol=nCols,
                          maxSteps=steps)
    else:
        raise TypeError("Lattice type not recognized")
    document._addPart(part, useUndoStack=False)

    # POPULATE VIRTUAL HELICES
    orderedCoordList = []
    vhNumToCoord = {}
    for helix in obj['vstrands']:
        vhNum = helix['num']
        row = helix['row']
        col = helix['col']
        scaf = helix['scaf']
        coord = (row, col)
        vhNumToCoord[vhNum] = coord
        orderedCoordList.append(coord)
    # make sure we retain the original order
    for vhNum in sorted(vhNumToCoord.keys()):
        row, col = vhNumToCoord[vhNum]
        part.createVirtualHelix(row, col, useUndoStack=False)
    part.setImportedVHelixOrder(orderedCoordList)

    # INSTALL STRANDS AND COLLECT XOVER LOCATIONS
    numHelixes = len(obj['vstrands']) - 1
    scaf_seg = defaultdict(list)
    scaf_xo = defaultdict(list)
    stap_seg = defaultdict(list)
    stap_xo = defaultdict(list)
    try:
        for helix in obj['vstrands']:
            vhNum = helix['num']
            row = helix['row']
            col = helix['col']
            scaf = helix['scaf']
            stap = helix['stap']
            insertions = helix['loop']
            skips = helix['skip']
            vh = part.virtualHelixAtCoord((row, col))
            scafStrandSet = vh.scaffoldStrandSet()
            stapStrandSet = vh.stapleStrandSet()
            assert(len(scaf)==len(stap) and len(stap)==part.maxBaseIdx()+1 and\
                   len(scaf)==len(insertions) and len(insertions)==len(skips))
            # read scaffold segments and xovers
            for i in range(len(scaf)):
                fiveVH, fiveIdx, threeVH, threeIdx = scaf[i]
                if fiveVH == -1 and threeVH == -1:
                    continue  # null base
                if isSegmentStartOrEnd(StrandType.Scaffold, vhNum, i, fiveVH,\
                                       fiveIdx, threeVH, threeIdx):
                    scaf_seg[vhNum].append(i)
                if fiveVH != vhNum and threeVH != vhNum:  # special case
                    scaf_seg[vhNum].append(
                        i)  # end segment on a double crossover
                if is3primeXover(StrandType.Scaffold, vhNum, i, threeVH,
                                 threeIdx):
                    scaf_xo[vhNum].append((i, threeVH, threeIdx))
            assert (len(scaf_seg[vhNum]) % 2 == 0)
            # install scaffold segments
            for i in range(0, len(scaf_seg[vhNum]), 2):
                lowIdx = scaf_seg[vhNum][i]
                highIdx = scaf_seg[vhNum][i + 1]
                scafStrandSet.createStrand(lowIdx, highIdx, useUndoStack=False)
            # read staple segments and xovers
            for i in range(len(stap)):
                fiveVH, fiveIdx, threeVH, threeIdx = stap[i]
                if fiveVH == -1 and threeVH == -1:
                    continue  # null base
                if isSegmentStartOrEnd(StrandType.Staple, vhNum, i, fiveVH,\
                                       fiveIdx, threeVH, threeIdx):
                    stap_seg[vhNum].append(i)
                if fiveVH != vhNum and threeVH != vhNum:  # special case
                    stap_seg[vhNum].append(
                        i)  # end segment on a double crossover
                if is3primeXover(StrandType.Staple, vhNum, i, threeVH,
                                 threeIdx):
                    stap_xo[vhNum].append((i, threeVH, threeIdx))
            assert (len(stap_seg[vhNum]) % 2 == 0)
            # install staple segments
            for i in range(0, len(stap_seg[vhNum]), 2):
                lowIdx = stap_seg[vhNum][i]
                highIdx = stap_seg[vhNum][i + 1]
                stapStrandSet.createStrand(lowIdx, highIdx, useUndoStack=False)
    except AssertionError:
        if not cadnano.app().isGui():
            print("Unrecognized file format.")
        else:
            dialogLT.label.setText("Unrecognized file format.")
            dialogLT.buttonBox.setStandardButtons(QDialogButtonBox.Ok)
            dialog.exec()

    # INSTALL XOVERS
    for helix in obj['vstrands']:
        vhNum = helix['num']
        row = helix['row']
        col = helix['col']
        scaf = helix['scaf']
        stap = helix['stap']
        insertions = helix['loop']
        skips = helix['skip']
        fromVh = part.virtualHelixAtCoord((row, col))
        scafStrandSet = fromVh.scaffoldStrandSet()
        stapStrandSet = fromVh.stapleStrandSet()
        # install scaffold xovers
        for (idx5p, toVhNum, idx3p) in scaf_xo[vhNum]:
            # idx3p is 3' end of strand5p, idx5p is 5' end of strand3p
            strand5p = scafStrandSet.getStrand(idx5p)
            toVh = part.virtualHelixAtCoord(vhNumToCoord[toVhNum])
            strand3p = toVh.scaffoldStrandSet().getStrand(idx3p)
            part.createXover(strand5p,
                             idx5p,
                             strand3p,
                             idx3p,
                             useUndoStack=False)
        # install staple xovers
        for (idx5p, toVhNum, idx3p) in stap_xo[vhNum]:
            # idx3p is 3' end of strand5p, idx5p is 5' end of strand3p
            strand5p = stapStrandSet.getStrand(idx5p)
            toVh = part.virtualHelixAtCoord(vhNumToCoord[toVhNum])
            strand3p = toVh.stapleStrandSet().getStrand(idx3p)
            part.createXover(strand5p,
                             idx5p,
                             strand3p,
                             idx3p,
                             useUndoStack=False)

    # SET DEFAULT COLOR
    for oligo in part.oligos():
        if oligo.isStaple():
            defaultColor = styles.DEFAULT_STAP_COLOR
        else:
            defaultColor = styles.DEFAULT_SCAF_COLOR
        oligo.applyColor(defaultColor, useUndoStack=False)

    # COLORS, INSERTIONS, SKIPS
    for helix in obj['vstrands']:
        vhNum = helix['num']
        row = helix['row']
        col = helix['col']
        scaf = helix['scaf']
        stap = helix['stap']
        insertions = helix['loop']
        skips = helix['skip']
        vh = part.virtualHelixAtCoord((row, col))
        scafStrandSet = vh.scaffoldStrandSet()
        stapStrandSet = vh.stapleStrandSet()
        # install insertions and skips
        for baseIdx in range(len(stap)):
            sumOfInsertSkip = insertions[baseIdx] + skips[baseIdx]
            if sumOfInsertSkip != 0:
                scaf_strand = scafStrandSet.getStrand(baseIdx)
                stap_strand = stapStrandSet.getStrand(baseIdx)
                if scaf_strand:
                    scaf_strand.addInsertion(baseIdx,
                                             sumOfInsertSkip,
                                             useUndoStack=False)
                elif stap_strand:
                    stap_strand.addInsertion(baseIdx,
                                             sumOfInsertSkip,
                                             useUndoStack=False)
        # end for
        # populate colors
        for baseIdx, colorNumber in helix['stap_colors']:
            color = QColor((colorNumber >> 16) & 0xFF,
                           (colorNumber >> 8) & 0xFF,
                           colorNumber & 0xFF).name()
            strand = stapStrandSet.getStrand(baseIdx)
            strand.oligo().applyColor(color, useUndoStack=False)
Пример #19
0
                pos += minStapleLegLen
            if not isTerminalStrand:
                maxIdx -= minStapleLegLen
            while idx <= maxIdx:
                isTerminalNode = isTerminalStrand and idx == maxIdx
                nodes.append((pos, strand, idx, isTerminalNode))
                idx += 1
                pos += 1
            pos += minStapleLegLen - 1
        else:
            minIdx, idx = strand.lowIdx(), strand.highIdx() + 1
            if strand != firstStrand:
                idx -= minStapleLegLen
                pos += minStapleLegLen
            if not isTerminalStrand:
                minIdx += minStapleLegLen
            while idx >= minIdx:
                isTerminalNode = isTerminalStrand and idx == minIdx
                nodes.append((pos, strand, idx, isTerminalNode))
                idx -= 1
                pos += 1
            pos += minStapleLegLen - 1
        strand = nextStrand
        if isTerminalStrand:
            break
    # if nodes:  # dump the node array to stdout
    #     print ' '.join(str(n[0])+':'+str(n[2]) for n in nodes) + (' :: %i'%oligo.length()) + repr(nodes[-1])
    return nodes

cadnano.app().breakStaples = breakStaples
Пример #20
0
    def updateSelectionBoxes(self):
        selectedItems = cmds.ls(self.helixTransformName + "*", selection=True)
        if selectedItems:
            bbox = cmds.exactWorldBoundingBox(selectedItems)
            cmds.setAttr(self.selectionBox + ".scale",
                         bbox[3] - bbox[0],
                         bbox[4] - bbox[1],
                         bbox[5] - bbox[2],
                         type="double3")
            cmds.setAttr(self.selectionBox + ".translate",
                         (bbox[0] + bbox[3]) / 2, (bbox[1] + bbox[4]) / 2,
                         (bbox[2] + bbox[5]) / 2,
                         type="double3")
            cmds.showHidden(self.selectionBox)

            selectionDict = app().activeDocument.document().selectionDict()

            frontEp = 0
            backEp = 0

            for strandSetDict in selectionDict.values():
                for strand, value in strandSetDict.items():
                    frontEp += int(value[0])
                    backEp += int(value[1])

            if (frontEp == 0) ^ (backEp == 0):
                epBoundBox = None
                for strandSetDict in selectionDict.values():
                    for strand, value in strandSetDict.items():
                        # XXX The following line is a work around for broken
                        # path selection in model, remove when fixed
                        if not strand in self.cnToMaya:
                            continue
                        helixNode = self.cnToMaya[strand]
                        boundBox = cmds.exactWorldBoundingBox(helixNode[1])
                        # might be better to get the rise this way...
                        #n = OpenMaya.MFnDependencyNode(helixNode)
                        #risePlug = n.findPlug("rise")
                        #rise = risePlug.asDouble()
                        # but this works too
                        idxL, idxH = strand.idxs()
                        rise = (boundBox[5] - boundBox[2]) / (idxH - idxL + 1)
                        if frontEp == 0:
                            boundBox[5] = boundBox[2] + rise
                        elif backEp == 0:
                            boundBox[2] = boundBox[5] - rise
                        if epBoundBox == None:
                            epBoundBox = boundBox
                        else:
                            # union the boxes
                            epBoundBox[0] = min(epBoundBox[0], boundBox[0])
                            epBoundBox[1] = min(epBoundBox[1], boundBox[1])
                            epBoundBox[2] = min(epBoundBox[2], boundBox[2])
                            epBoundBox[3] = max(epBoundBox[3], boundBox[3])
                            epBoundBox[4] = max(epBoundBox[4], boundBox[4])
                            epBoundBox[5] = max(epBoundBox[5], boundBox[5])

                # XXX The following line is a work around for broken
                # path selection in model, remove when fixed
                if not epBoundBox == None:

                    cmds.showHidden(self.epSelectionBox)
                    cmds.setAttr(self.epSelectionBox + ".scale",
                                 epBoundBox[3] - epBoundBox[0],
                                 epBoundBox[4] - epBoundBox[1],
                                 epBoundBox[5] - epBoundBox[2],
                                 type="double3")
                    cmds.setAttr(self.epSelectionBox + ".translate",
                                 (epBoundBox[0] + epBoundBox[3]) / 2,
                                 (epBoundBox[1] + epBoundBox[4]) / 2,
                                 (epBoundBox[2] + epBoundBox[5]) / 2,
                                 type="double3")

            else:
                cmds.hide(self.epSelectionBox)

        else:
            cmds.hide(self.selectionBox)
            cmds.hide(self.epSelectionBox)