Beispiel #1
0
 def __init__(self, part, row, col, idnum=0):
     self._doc = part.document()
     super(VirtualHelix, self).__init__(part)
     self._coord = (row, col)  # col, row
     self._part = part
     self._scaf_strandset = StrandSet(StrandType.SCAFFOLD, self)
     self._stap_strandset = StrandSet(StrandType.STAPLE, self)
     # If self._part exists, it owns self._number
     # in that only it may modify it through the
     # private interface. The public interface for
     # setNumber just routes the call to the parent
     # dnapart if one is present. If self._part == None
     # the virtualhelix owns self._number and may modify it.
     self._number = None
     self.setNumber(idnum)
Beispiel #2
0
 def __init__(self, part, row, col, idnum=0):
     self._doc = part.document()
     super(VirtualHelix, self).__init__(part)
     self._coord = (row, col) # col, row
     self._part = part
     self._scaf_strandset = StrandSet(StrandType.SCAFFOLD, self)
     self._stap_strandset = StrandSet(StrandType.STAPLE, self)
     # If self._part exists, it owns self._number
     # in that only it may modify it through the
     # private interface. The public interface for
     # setNumber just routes the call to the parent
     # dnapart if one is present. If self._part == None
     # the virtualhelix owns self._number and may modify it.
     self._number = None
     self.setNumber(idnum)
Beispiel #3
0
class VirtualHelix(ProxyObject):
    """
    VirtualHelix is a container class for two StrandSet objects (one scaffold
    and one staple). The Strands all share the same helix axis. It is called
    "virtual" because many different Strands (i.e. sub-oligos) combine to
    form the "helix", just as many fibers may be braided together to 
    form a length of rope.
    """

    def __init__(self, part, row, col, idnum=0):
        self._doc = part.document()
        super(VirtualHelix, self).__init__(part)
        self._coord = (row, col) # col, row
        self._part = part
        self._scaf_strandset = StrandSet(StrandType.SCAFFOLD, self)
        self._stap_strandset = StrandSet(StrandType.STAPLE, self)
        # If self._part exists, it owns self._number
        # in that only it may modify it through the
        # private interface. The public interface for
        # setNumber just routes the call to the parent
        # dnapart if one is present. If self._part == None
        # the virtualhelix owns self._number and may modify it.
        self._number = None
        self.setNumber(idnum)
    # end def

    def __repr__(self):
        return "<%s(%d)>" % (self.__class__.__name__, self._number)

    ### SIGNALS ###
    virtualHelixRemovedSignal = ProxySignal(ProxyObject, name='virtualHelixRemovedSignal')  #pyqtSignal(QObject)  # self
    virtualHelixNumberChangedSignal = ProxySignal(ProxyObject, int, name='virtualHelixNumberChangedSignal') #pyqtSignal(QObject, int)  # self, num

    ### SLOTS ###

    ### ACCESSORS ###
    def scaf(self, idx):
        """ Returns the strand at idx in self's scaffold, if any """
        return self._scaf_strandset.getStrand(idx)

    def stap(self, idx):
        """ Returns the strand at idx in self's scaffold, if any """
        return self._stap_strandset.getStrand(idx)

    def coord(self):
        return self._coord
    # end def

    def number(self):
        return self._number
    # end def

    def part(self):
        return self._part
    # end def
    
    def document(self):
        return self._doc
    # end def
    
    def setNumber(self, number):
        if self._number != number:
            num_to_vh_dict = self._part._number_to_virtual_helix
            # if self._number is not None:
            num_to_vh_dict[self._number] = None
            self._number = number
            self.virtualHelixNumberChangedSignal.emit(self, number)
            num_to_vh_dict[number] = self
    # end def

    def setPart(self, new_part):
        self._part = new_part
        self.setParent(new_part)
    # end def

    def scaffoldStrandSet(self):
        return self._scaf_strandset
    # end def

    def stapleStrandSet(self):
        return self._stap_strandset
    # end def

    def undoStack(self):
        return self._part.undoStack()
    # end def

    ### METHODS FOR QUERYING THE MODEL ###
    def scaffoldIsOnTop(self):
        return self.isEvenParity()

    def getStrandSetByIdx(self, idx):
        """
        This is a path-view-specific accessor
        idx == 0 means top strand
        idx == 1 means bottom strand
        """
        if idx == 0:
            if self.isEvenParity():
                return self._scaf_strandset
            else:
                return self._stap_strandset
        else:
            if self.isEvenParity():
                return self._stap_strandset
            else:
                return self._scaf_strandset
    # end def

    def getStrandSetByType(self, strand_type):
        if strand_type == StrandType.SCAFFOLD:
            return self._scaf_strandset
        else:
            return self._stap_strandset
    # end def

    def getStrandSets(self):
        """Return a tuple of the scaffold and staple StrandSets."""
        return self._scaf_strandset, self._stap_strandset
    # end def

    def hasStrandAtIdx(self, idx):
        """Return a tuple for (Scaffold, Staple). True if
           a strand is present at idx, False otherwise."""
        return (self._scaf_strandset.hasStrandAt(idx, idx),\
                self._stap_strandset.hasStrandAt(idx, idx))
    # end def

    def indexOfRightmostNonemptyBase(self):
        """Returns the rightmost nonempty base in either scaf of stap."""
        return max(self._scaf_strandset.indexOfRightmostNonemptyBase(),\
                   self._stap_strandset.indexOfRightmostNonemptyBase())
    # end def

    def isDrawn5to3(self, strandset):
        is_scaf = strandset == self._scaf_strandset
        is_even = self.isEvenParity()
        return is_even == is_scaf
    # end def

    def isEvenParity(self):
        return self._part.isEvenParity(*self._coord)
    # end def

    def strandSetBounds(self, idx_helix, idx_type):
        """
        forwards the query to the strandset
        """
        return self.strandSet(idx_helix, idx_type).bounds()
    # end def

    ### METHODS FOR EDITING THE MODEL ###
    def destroy(self):
        # QObject also emits a destroyed() Signal
        self.setParent(None)
        self.deleteLater()
    # end def
    
    def remove(self, use_undostack=True):
        """
        Removes a VirtualHelix from the model. Accepts a reference to the 
        VirtualHelix, or a (row,col) lattice coordinate to perform a lookup.
        """
        if use_undostack:
            self.undoStack().beginMacro("Delete VirtualHelix")
        self._scaf_strandset.remove(use_undostack)
        self._stap_strandset.remove(use_undostack)
        c = RemoveVirtualHelixCommand(self.part(), self)
        if use_undostack:
            self.undoStack().push(c)
            self.undoStack().endMacro()
        else:
            c.redo()
    # end def

    ### PUBLIC SUPPORT METHODS ###
    def deepCopy(self, part):
        """
        This only copies as deep as the VirtualHelix
        strands get copied at the oligo and added to the Virtual Helix
        """
        vh = VirtualHelix(part, self._number)
        vh._coords = (self._coord[0], self._coord[1])
        # If self._part exists, it owns self._number
        # in that only it may modify it through the
        # private interface. The public interface for
        # setNumber just routes the call to the parent
        # dnapart if one is present. If self._part == None
        # the virtualhelix owns self._number and may modify it.
        self._number = idnum
    # end def

    def getLegacyStrandSetArray(self, strand_type):
        """Called by legacyencoder."""
        if strand_type == StrandType.SCAFFOLD:
            return self._scaf_strandset.getLegacyArray()
        else:
            return self._stap_strandset.getLegacyArray()

    def shallowCopy(self):
        pass
    # end def

    # def translateCoords(self, deltaCoords):
    #     """
    #     for expanding a helix
    #     """
    #     deltaRow, deltaCol = deltaCoords
    #     row, col = self._coord
    #     self._coord = row + deltaRow, col + deltaCol
    # # end def

# end class
Beispiel #4
0
class VirtualHelix(ProxyObject):
    """
    VirtualHelix is a container class for two StrandSet objects (one scaffold
    and one staple). The Strands all share the same helix axis. It is called
    "virtual" because many different Strands (i.e. sub-oligos) combine to
    form the "helix", just as many fibers may be braided together to 
    form a length of rope.
    """
    def __init__(self, part, row, col, idnum=0):
        self._doc = part.document()
        super(VirtualHelix, self).__init__(part)
        self._coord = (row, col)  # col, row
        self._part = part
        self._scaf_strandset = StrandSet(StrandType.SCAFFOLD, self)
        self._stap_strandset = StrandSet(StrandType.STAPLE, self)
        # If self._part exists, it owns self._number
        # in that only it may modify it through the
        # private interface. The public interface for
        # setNumber just routes the call to the parent
        # dnapart if one is present. If self._part == None
        # the virtualhelix owns self._number and may modify it.
        self._number = None
        self.setNumber(idnum)

    # end def

    def __repr__(self):
        return "<%s(%d)>" % (self.__class__.__name__, self._number)

    ### SIGNALS ###
    virtualHelixRemovedSignal = ProxySignal(
        ProxyObject,
        name='virtualHelixRemovedSignal')  #pyqtSignal(QObject)  # self
    virtualHelixNumberChangedSignal = ProxySignal(
        ProxyObject, int, name='virtualHelixNumberChangedSignal'
    )  #pyqtSignal(QObject, int)  # self, num

    ### SLOTS ###

    ### ACCESSORS ###
    def scaf(self, idx):
        """ Returns the strand at idx in self's scaffold, if any """
        return self._scaf_strandset.getStrand(idx)

    def stap(self, idx):
        """ Returns the strand at idx in self's scaffold, if any """
        return self._stap_strandset.getStrand(idx)

    def coord(self):
        return self._coord

    # end def

    def number(self):
        return self._number

    # end def

    def part(self):
        return self._part

    # end def

    def document(self):
        return self._doc

    # end def

    def setNumber(self, number):
        if self._number != number:
            num_to_vh_dict = self._part._number_to_virtual_helix
            # if self._number is not None:
            num_to_vh_dict[self._number] = None
            self._number = number
            self.virtualHelixNumberChangedSignal.emit(self, number)
            num_to_vh_dict[number] = self

    # end def

    def setPart(self, new_part):
        self._part = new_part
        self.setParent(new_part)

    # end def

    def scaffoldStrandSet(self):
        return self._scaf_strandset

    # end def

    def stapleStrandSet(self):
        return self._stap_strandset

    # end def

    def undoStack(self):
        return self._part.undoStack()

    # end def

    ### METHODS FOR QUERYING THE MODEL ###
    def scaffoldIsOnTop(self):
        return self.isEvenParity()

    def getStrandSetByIdx(self, idx):
        """
        This is a path-view-specific accessor
        idx == 0 means top strand
        idx == 1 means bottom strand
        """
        if idx == 0:
            if self.isEvenParity():
                return self._scaf_strandset
            else:
                return self._stap_strandset
        else:
            if self.isEvenParity():
                return self._stap_strandset
            else:
                return self._scaf_strandset

    # end def

    def getStrandSetByType(self, strand_type):
        if strand_type == StrandType.SCAFFOLD:
            return self._scaf_strandset
        else:
            return self._stap_strandset

    # end def

    def getStrandSets(self):
        """Return a tuple of the scaffold and staple StrandSets."""
        return self._scaf_strandset, self._stap_strandset

    # end def

    def hasStrandAtIdx(self, idx):
        """Return a tuple for (Scaffold, Staple). True if
           a strand is present at idx, False otherwise."""
        return (self._scaf_strandset.hasStrandAt(idx, idx),\
                self._stap_strandset.hasStrandAt(idx, idx))

    # end def

    def indexOfRightmostNonemptyBase(self):
        """Returns the rightmost nonempty base in either scaf of stap."""
        return max(self._scaf_strandset.indexOfRightmostNonemptyBase(),\
                   self._stap_strandset.indexOfRightmostNonemptyBase())

    # end def

    def isDrawn5to3(self, strandset):
        is_scaf = strandset == self._scaf_strandset
        is_even = self.isEvenParity()
        return is_even == is_scaf

    # end def

    def isEvenParity(self):
        return self._part.isEvenParity(*self._coord)

    # end def

    def strandSetBounds(self, idx_helix, idx_type):
        """
        forwards the query to the strandset
        """
        return self.strandSet(idx_helix, idx_type).bounds()

    # end def

    ### METHODS FOR EDITING THE MODEL ###
    def destroy(self):
        # QObject also emits a destroyed() Signal
        self.setParent(None)
        self.deleteLater()

    # end def

    def remove(self, use_undostack=True):
        """
        Removes a VirtualHelix from the model. Accepts a reference to the 
        VirtualHelix, or a (row,col) lattice coordinate to perform a lookup.
        """
        if use_undostack:
            self.undoStack().beginMacro("Delete VirtualHelix")
        self._scaf_strandset.remove(use_undostack)
        self._stap_strandset.remove(use_undostack)
        c = RemoveVirtualHelixCommand(self.part(), self)
        if use_undostack:
            self.undoStack().push(c)
            self.undoStack().endMacro()
        else:
            c.redo()

    # end def

    ### PUBLIC SUPPORT METHODS ###
    def deepCopy(self, part):
        """
        This only copies as deep as the VirtualHelix
        strands get copied at the oligo and added to the Virtual Helix
        """
        vh = VirtualHelix(part, self._number)
        vh._coords = (self._coord[0], self._coord[1])
        # If self._part exists, it owns self._number
        # in that only it may modify it through the
        # private interface. The public interface for
        # setNumber just routes the call to the parent
        # dnapart if one is present. If self._part == None
        # the virtualhelix owns self._number and may modify it.
        self._number = idnum

    # end def

    def getLegacyStrandSetArray(self, strand_type):
        """Called by legacyencoder."""
        if strand_type == StrandType.SCAFFOLD:
            return self._scaf_strandset.getLegacyArray()
        else:
            return self._stap_strandset.getLegacyArray()

    def shallowCopy(self):
        pass

    # end def

    # def translateCoords(self, deltaCoords):
    #     """
    #     for expanding a helix
    #     """
    #     deltaRow, deltaCol = deltaCoords
    #     row, col = self._coord
    #     self._coord = row + deltaRow, col + deltaCol
    # # end def


# end class
Beispiel #5
0
    def determineStrandSetBounds(self, selected_strand_list: List[Tuple[
        Strand, EndsSelected]], strandset: StrandSet) -> Tuple[int, int]:
        """Determine the bounds of a :class:`StrandSet` ``strandset`` among a
        a list of selected strands in that same ``strandset``

        Args:
            selected_strand_list: list of ``( Strands, (is_low, is_high) )`` items
            strandset: of interest

        Returns:
            tuple: min low bound and min high bound index
        """
        length = strandset.length()
        min_high_delta = min_low_delta = max_ss_idx = length - 1  # init the return values
        ss_dict = self._selection_dict[strandset]

        for strand, value in selected_strand_list:
            idx_low, idx_high = strand.idxs()
            low_neighbor, high_neighbor = strandset.getNeighbors(strand)
            # print(low_neighbor, high_neighbor)
            if value[0]:  # the end is selected
                if low_neighbor is None:
                    temp = idx_low - 0
                else:
                    if low_neighbor in ss_dict:
                        value_N = ss_dict[low_neighbor]
                        # we only care if the low neighbor is not selected
                        temp = min_low_delta if value_N[
                            1] else idx_low - low_neighbor.highIdx() - 1
                    # end if
                    else:  # not selected
                        temp = idx_low - low_neighbor.highIdx() - 1
                    # end else

                if temp < min_low_delta:
                    min_low_delta = temp
                # end if
                # check the other end of the strand
                if not value[1]:
                    temp = idx_high - idx_low - 1
                    if temp < min_high_delta:
                        min_high_delta = temp

            # end if
            if value[1]:
                if high_neighbor is None:
                    temp = max_ss_idx - idx_high
                else:
                    if high_neighbor in ss_dict:
                        value_N = ss_dict[high_neighbor]
                        # we only care if the low neighbor is not selected
                        temp = min_high_delta if value_N[
                            0] else high_neighbor.lowIdx() - idx_high - 1
                    # end if
                    else:  # not selected
                        temp = high_neighbor.lowIdx() - idx_high - 1
                    # end else

                # end else
                if temp < min_high_delta:
                    min_high_delta = temp
                # end if
                # check the other end of the strand
                if not value[0]:
                    temp = idx_high - idx_low - 1
                    if temp < min_low_delta:
                        min_low_delta = temp
            # end if
        # end for
        return (min_low_delta, min_high_delta)
	#Determine position for oligo strands (first oligo: from 1 --> length/2 second oligo: next (length/2)+1 --> length )
	oligo_pos.append([1,int(int(i[2])/2),int(int(i[2])/2)+1,int(i[2])])
	
# Max length of the Strand Set
MAX_LENGTH = 64
offset_idx = 0

# Make the container for the StrandSets 
ss_fwd = [None]*vhCounter
ss_rev = [None]*vhCounter

# Create the StrandsSets and fill them with Strands 
# The assumption here is that Scaffold is forward strand and that the reverse strands is Staple Strands
try: 
	for i in range(vhCounter):	
		ss_fwd[i] = StrandSet(is_fwd=True, id_num=i, part=part, initial_size=MAX_LENGTH)
		ss_rev[i] = StrandSet(is_fwd=False, id_num=i, part=part, initial_size=MAX_LENGTH)   
		ss_fwd[i].createStrand(base_idx_low=offset_idx, base_idx_high=offset_idx+oligo_pos[i][3], color='#0066cc')
		ss_rev[i].createStrand(base_idx_low=offset_idx, base_idx_high=offset_idx+oligo_pos[i][1], color='#f44242')
		ss_rev[i].createStrand(base_idx_low=offset_idx+oligo_pos[i][2], base_idx_high=offset_idx+oligo_pos[i][3], color='#007200')
		part.fwd_strandsets[i] = ss_fwd[i]
		part.rev_strandsets[i] = ss_rev[i] 
except Exception: 
	print('Failed to create StrandSet/Strands')

"""
print('\t', fwd_ss, '\t', [s.idxs() for s in fwd_ss.strands()], '\n\t\t\t\t',
          [s.getColor() for s in fwd_ss.strands()])
print('\t', rev_ss, '\t', [s.idxs() for s in rev_ss.strands()], '\n\t\t\t\t',
          [s.getColor() for s in rev_ss.strands()])
Beispiel #7
0
    def determineStrandSetBounds(self,  selected_strand_list: List[Tuple[Strand, EndsSelected]],
                                        strandset: StrandSet) -> Tuple[int, int]:
        """Determine the bounds of a :class:`StrandSet` ``strandset`` among a
        a list of selected strands in that same ``strandset``

        Args:
            selected_strand_list: list of ``( Strands, (is_low, is_high) )`` items
            strandset: of interest

        Returns:
            tuple: min low bound and min high bound index
        """
        length = strandset.length()
        min_high_delta = min_low_delta = max_ss_idx = length - 1  # init the return values
        ss_dict = self._selection_dict[strandset]

        for strand, value in selected_strand_list:
            idx_low, idx_high = strand.idxs()
            low_neighbor, high_neighbor = strandset.getNeighbors(strand)
            # print(low_neighbor, high_neighbor)
            if value[0]:    # the end is selected
                if low_neighbor is None:
                    temp = idx_low - 0
                else:
                    if low_neighbor in ss_dict:
                        value_N = ss_dict[low_neighbor]
                        # we only care if the low neighbor is not selected
                        temp = min_low_delta if value_N[1] else idx_low - low_neighbor.highIdx() - 1
                    # end if
                    else:  # not selected
                        temp = idx_low - low_neighbor.highIdx() - 1
                    # end else

                if temp < min_low_delta:
                    min_low_delta = temp
                # end if
                # check the other end of the strand
                if not value[1]:
                    temp = idx_high - idx_low - 1
                    if temp < min_high_delta:
                        min_high_delta = temp

            # end if
            if value[1]:
                if high_neighbor is None:
                    temp = max_ss_idx - idx_high
                else:
                    if high_neighbor in ss_dict:
                        value_N = ss_dict[high_neighbor]
                        # we only care if the low neighbor is not selected
                        temp = min_high_delta if value_N[0] else high_neighbor.lowIdx() - idx_high - 1
                    # end if
                    else:  # not selected
                        temp = high_neighbor.lowIdx() - idx_high - 1
                    # end else

                # end else
                if temp < min_high_delta:
                    min_high_delta = temp
                # end if
                # check the other end of the strand
                if not value[0]:
                    temp = idx_high - idx_low - 1
                    if temp < min_low_delta:
                        min_low_delta = temp
            # end if
        # end for
        return (min_low_delta, min_high_delta)