Instruction:
Here you have a function in Python 3, explain what it does
def sendMessage(self, msg):
        if msg._messageType in (1, 2):
            assert msg.destination, 'Failed to specify a message destination'

        if msg.destination is not None:
            if msg.destination[0] == ':':
                p = self.clients.get(msg.destination, None)
            else:
                p = self.busNames.get(msg.destination, None)
                if p:
                    p = p[0]

            # print 'SND: ', msg._messageType, ' to ',  p.uniqueName, 'serial',
            # msg.serial,

            if p:
                p.sendMessage(msg)
            else:
                log.msg(
                    'Invalid bus name in msg.destination: '
                    + msg.destination
                )
        else:
            self.router.routeMessage(msg)

Response: Sends the supplied message to the correct destination.


Instruction:
Explain what the following Python 3 code does
def sendSignal(self, p, member, signature=None, body=None,
                   path='/org/freedesktop/DBus',
                   interface='org.freedesktop.DBus'):
        """
        Sends a signal to a specific connection

        @type p: L{BusProtocol}
        @param p: L{BusProtocol} instance to send a signal to

        @type member: C{string}
        @param member: Name of the signal to send

        @type path: C{string}
        @param path: Path of the object emitting the signal. Defaults to
                     'org/freedesktop/DBus'

        @type interface: C{string}
        @param interface: If specified, this specifies the interface containing
            the desired method. Defaults to 'org.freedesktop.DBus'

        @type body: None or C{list}
        @param body: If supplied, this is a list of signal arguments. The
            contents of the list must match the signature.

        @type signature: None or C{string}
        @param signature: If specified, this specifies the DBus signature of
            the body of the DBus Signal message. This string must be a valid
            Signature string as defined by the DBus specification. If the body
            argumnent is supplied, this parameter must be provided.
        """
        if not isinstance(body, (list, tuple)):
            body = [body]

        s = message.SignalMessage(path, member, interface,
                                  p.uniqueName, signature, body)
        p.sendMessage(s)

Response: Sends a signal to a specific connection.


Instruction:
Can you generate the documentation for the following Python 3 function
def broadcastSignal(self, member, signature=None, body=None,
                        path='/org/freedesktop/DBus',
                        interface='org.freedesktop.DBus'):
        """
        Sends a signal to all connections with registered interest

        @type member: C{string}
        @param member: Name of the signal to send

        @type path: C{string}
        @param path: Path of the object emitting the signal. Defaults to
                     'org/freedesktop/DBus'

        @type interface: C{string}
        @param interface: If specified, this specifies the interface containing
            the desired method. Defaults to 'org.freedesktop.DBus'

        @type body: None or C{list}
        @param body: If supplied, this is a list of signal arguments. The
            contents of the list must match the signature.

        @type signature: None or C{string}
        @param signature: If specified, this specifies the DBus signature of
            the body of the DBus Signal message. This string must be a valid
            Signature string as defined by the DBus specification. If the body
            argumnent is supplied , this parameter must be provided.
        """
        if not isinstance(body, (list, tuple)):
            body = [body]

        s = message.SignalMessage(path, member, interface,
                                  None, signature, body)
        self.router.routeMessage(s)

Response: Sends a signal to all connections with the same name and interface.


Instruction:
Implement a Python 3 function for
parsing a raw binary message and returns a new object.

Response:
def parseMessage(rawMessage, oobFDs):
    """
    Parses the raw binary message and returns a L{DBusMessage} subclass.
    Unmarshalling DBUS 'h' (UNIX_FD) gets the FDs from the oobFDs list.

    @type rawMessage: C{str}
    @param rawMessage: Raw binary message to parse

    @rtype: L{DBusMessage} subclass
    @returns: The L{DBusMessage} subclass corresponding to the contained
              message
    """

    lendian = rawMessage[0] == b'l'[0]

    nheader, hval = marshal.unmarshal(
        _headerFormat,
        rawMessage,
        0,
        lendian,
        oobFDs,
    )

    messageType = hval[1]

    if messageType not in _mtype:
        raise error.MarshallingError(
            'Unknown Message Type: ' + str(messageType)
        )

    m = object.__new__(_mtype[messageType])

    m.rawHeader = rawMessage[:nheader]

    npad = nheader % 8 and (8 - nheader % 8) or 0

    m.rawPadding = rawMessage[nheader: nheader + npad]

    m.rawBody = rawMessage[nheader + npad:]

    m.serial = hval[5]

    for code, v in hval[6]:
        try:
            setattr(m, _hcode[code], v)
        except KeyError:
            pass

    if m.signature:
        nbytes, m.body = marshal.unmarshal(
            m.signature,
            m.rawBody,
            lendian=lendian,
            oobFDs=oobFDs,
        )

    return m


Instruction:
How would you explain what the following Python 3 function does
def _marshal(self, newSerial=True, oobFDs=None):
        flags = 0

        if not self.expectReply:
            flags |= 0x1

        if not self.autoStart:
            flags |= 0x2

        # may be overriden below, depending on oobFDs
        _headerAttrs = self._headerAttrs

        # marshal body before headers to know if the 'unix_fd' header is needed
        if self.signature:
            binBody = b''.join(
                marshal.marshal(
                    self.signature,
                    self.body,
                    oobFDs=oobFDs
                )[1]
            )
            if oobFDs:
                # copy class based _headerAttrs to add a unix_fds header this
                # time
                _headerAttrs = list(self._headerAttrs)
                _headerAttrs.append(('unix_fds', 9, False))
                self.unix_fds = len(oobFDs)
        else:
            binBody = b''

        self.headers = []

        for attr_name, code, _ in _headerAttrs:
            hval = getattr(self, attr_name, None)

            if hval is not None:
                if attr_name == 'path':
                    hval = marshal.ObjectPath(hval)
                elif attr_name == 'signature':
                    hval = marshal.Signature(hval)
                elif attr_name == 'unix_fds':
                    hval = marshal.UInt32(hval)

                self.headers.append([code, hval])

        self.bodyLength = len(binBody)

        if newSerial:
            self.serial = DBusMessage._nextSerial

            DBusMessage._nextSerial += 1

        binHeader = b''.join(marshal.marshal(
            _headerFormat,
            [
                self.endian,
                self._messageType,
                flags,
                self._protocolVersion,
                self.bodyLength,
                self.serial,
                self.headers
            ],
            lendian=self.endian == ord('l')
        )[1])

        headerPadding = marshal.pad['header'](len(binHeader))

        self.rawHeader = binHeader
        self.rawPadding = headerPadding
        self.rawBody = binBody

        self.rawMessage = b''.join([binHeader, headerPadding, binBody])

        if len(self.rawMessage) > self._maxMsgLen:
            raise error.MarshallingError(
                'Marshalled message exceeds maximum message size of %d' %
                (self._maxMsgLen,),
            )

Response: Marshal the message into binary format.


Instruction:
Implement a Python 3 function for
encrypting the given plaintext value

Response:
def encrypt(self, plaintext):
        """Encrypt the given plaintext value"""
        if not isinstance(plaintext, int):
            raise ValueError('Plaintext must be an integer value')
        if not self.in_range.contains(plaintext):
            raise OutOfRangeError('Plaintext is not within the input range')
        return self.encrypt_recursive(plaintext, self.in_range, self.out_range)


Instruction:
Can you generate the documentation for the following Python 3 function
def decrypt(self, ciphertext):
        if not isinstance(ciphertext, int):
            raise ValueError('Ciphertext must be an integer value')
        if not self.out_range.contains(ciphertext):
            raise OutOfRangeError('Ciphertext is not within the output range')
        return self.decrypt_recursive(ciphertext, self.in_range, self.out_range)

Response: Decrypt the given ciphertext value


Instruction:
Here you have a function in Python 3, explain what it does
def tape_gen(self, data):

        # FIXME
        data = str(data).encode()

        # Derive a key from data
        hmac_obj = hmac.HMAC(self.key, digestmod=hashlib.sha256)
        hmac_obj.update(data)
        assert hmac_obj.digest_size == 32
        digest = hmac_obj.digest()

        # Use AES in the CTR mode to generate a pseudo-random bit string
        aes_algo = algorithms.AES(digest)
        aes_cipher = Cipher(aes_algo, mode=CTR(b'\x00' * 16), backend=default_backend())
        encryptor = aes_cipher.encryptor()

        while True:
            encrypted_bytes = encryptor.update(b'\x00' * 16)
            # Convert the data to a list of bits
            bits = util.str_to_bitstring(encrypted_bytes)
            for bit in bits:
                yield bit

Response: Generate a bit string from the given data string


Instruction:
How would you implement a function in Python 3 that
generates a random key for ope cipher.

Response:
def generate_key(block_size=32):
        """Generate random key for ope cipher.

        Parameters
        ----------
        block_size : int, optional
            Length of random bytes.

        Returns
        -------
        random_key : str
            A random key for encryption.

        Notes:
        ------
        Implementation follows https://github.com/pyca/cryptography
        """
        random_seq = os.urandom(block_size)
        random_key = base64.b64encode(random_seq)
        return random_key


Instruction:
Given the following Python 3 function, write the documentation
def byte_to_bitstring(byte):
    assert 0 <= byte <= 0xff
    bits = [int(x) for x in list(bin(byte + 0x100)[3:])]
    return bits

Response: Convert one byte to a list of bits


Instruction:
Make a summary of the following Python 3 code
def str_to_bitstring(data):
    assert isinstance(data, bytes), "Data must be an instance of bytes"
    byte_list = data_to_byte_list(data)
    bit_list = [bit for data_byte in byte_list for bit in byte_to_bitstring(data_byte)]
    return bit_list

Response: Convert a string to a list of bits


Instruction:
How would you explain what the following Python 3 function does
def sample_hgd(in_range, out_range, nsample, seed_coins):
    in_size = in_range.size()
    out_size = out_range.size()
    assert in_size > 0 and out_size > 0
    assert in_size <= out_size
    assert out_range.contains(nsample)

    # 1-based index of nsample in out_range
    nsample_index = nsample - out_range.start + 1
    if in_size == out_size:
        # Input and output domains have equal size
        return in_range.start + nsample_index - 1

    in_sample_num = HGD.rhyper(nsample_index, in_size, out_size - in_size, seed_coins)
    if in_sample_num == 0:
        return in_range.start
    else:
        in_sample = in_range.start + in_sample_num - 1
        assert in_range.contains(in_sample)
        return in_sample

Response: Get a sample from the hypergeometric distribution using the provided bit list as a source of randomness


Instruction:
Can you generate a brief explanation for the following Python 3 code
def sample_uniform(in_range, seed_coins):
    if isinstance(seed_coins, list):
        seed_coins.append(None)
        seed_coins = iter(seed_coins)
    cur_range = in_range.copy()
    assert cur_range.size() != 0
    while cur_range.size() > 1:
        mid = (cur_range.start + cur_range.end) // 2
        bit = next(seed_coins)
        if bit == 0:
            cur_range.end = mid
        elif bit == 1:
            cur_range.start = mid + 1
        elif bit is None:
            raise NotEnoughCoinsError()
        else:
            raise InvalidCoinError()
    assert cur_range.size() == 1
    return cur_range.start

Response: Uniformly select a number from the range using the bit list as a source of randomness


Instruction:
Write a Python 3 function for
starting a HTTP download returning a HTTPDownloader object

Response:
def __downloadPage(factory, *args, **kwargs):
    """Start a HTTP download, returning a HTTPDownloader object"""

    # The Twisted API is weird:
    # 1) web.client.downloadPage() doesn't give us the HTTP headers
    # 2) there is no method that simply accepts a URL and gives you back
    #    a HTTPDownloader object

    #TODO: convert getPage() usage to something similar, too

    downloader = factory(*args, **kwargs)
    if downloader.scheme == 'https':
        from twisted.internet import ssl
        contextFactory = ssl.ClientContextFactory()
        reactor.connectSSL(downloader.host, downloader.port,
                           downloader, contextFactory)
    else:
        reactor.connectTCP(downloader.host, downloader.port,
                           downloader)
    return downloader


Instruction:
Can you implement a function in Python 3 that
encodes the multipart request.

Response:
def __encodeMultipart(self, fields, files):
        """
        fields is a sequence of (name, value) elements for regular form fields.
        files is a sequence of (name, filename, value) elements for data to be uploaded as files
        Return (content_type, body) ready for httplib.HTTP instance
        """
        boundary = mimetools.choose_boundary()
        crlf = '\r\n'

        l = []
        for k, v in fields:
            l.append('--' + boundary)
            l.append('Content-Disposition: form-data; name="%s"' % k)
            l.append('')
            l.append(v)
        for (k, f, v) in files:
            l.append('--' + boundary)
            l.append('Content-Disposition: form-data; name="%s"; filename="%s"' % (k, f))
            l.append('Content-Type: %s' % self.__getContentType(f))
            l.append('')
            l.append(v)
        l.append('--' + boundary + '--')
        l.append('')
        body = crlf.join(l)

        return boundary, body


Instruction:
Implement a function in Python 3 to
return a deferred for a HTTP client after handling incoming headers

Response:
def __clientDefer(self, c):
        """Return a deferred for a HTTP client, after handling incoming headers"""
        def handle_headers(r):
            self.gotHeaders(c.response_headers)
            return r

        return c.deferred.addBoth(handle_headers)


Instruction:
Make a summary of the following Python 3 code
def __doDownloadPage(self, *args, **kwargs):
        logger.debug("download page: %r, %r", args, kwargs)

        return self.__clientDefer(downloadPage(*args, **kwargs))

Response: Works like client. downloadPage but handles incoming headers


Instruction:
Write a Python 3 function for
verifying a user s credentials.

Response:
def verify_credentials(self, delegate=None):
        "Verify a user's credentials."
        parser = txml.Users(delegate)
        return self.__downloadPage('/account/verify_credentials.xml', parser)


Instruction:
Can you generate the documentation for the following Python 3 function
def update(self, status, source=None, params={}):
        "Update your status.  Returns the ID of the new post."
        params = params.copy()
        params['status'] = status
        if source:
            params['source'] = source
        return self.__parsed_post(self.__post('/statuses/update.xml', params),
            txml.parseUpdateResponse)

Response: Update your status. Returns the ID of the new post.


Instruction:
Write a Python 3 script to
get updates from friends. Calls the delgate once for each status object received.

Response:
def friends(self, delegate, params={}, extra_args=None):
        """Get updates from friends.

        Calls the delgate once for each status object received."""
        return self.__get('/statuses/friends_timeline.xml', delegate, params,
            txml.Statuses, extra_args=extra_args)


Instruction:
Can you write a function in Python 3 where it
gets updates from friends. MimeType Calls the delgate once for each status object received.

Response:
def home_timeline(self, delegate, params={}, extra_args=None):
        """Get updates from friends.

        Calls the delgate once for each status object received."""
        return self.__get('/statuses/home_timeline.xml', delegate, params,
            txml.Statuses, extra_args=extra_args)


Instruction:
Implement a Python 3 function for
getting the most recent updates for a user.

Response:
def user_timeline(self, delegate, user=None, params={}, extra_args=None):
        """Get the most recent updates for a user.

        If no user is specified, the statuses for the authenticating user are
        returned.

        See search for example of how results are returned."""
        if user:
            params['id'] = user
        return self.__get('/statuses/user_timeline.xml', delegate, params,
                          txml.Statuses, extra_args=extra_args)


Instruction:
Can you tell what is the following Python 3 function doing
def public_timeline(self, delegate, params={}, extra_args=None):
        "Get the most recent public timeline."

        return self.__get('/statuses/public_timeline.atom', delegate, params,
                          extra_args=extra_args)

Response: Get the most recent public timeline.


Instruction:
How would you code a function in Python 3 to
get the direct messages for the authenticating user.

Response:
def direct_messages(self, delegate, params={}, extra_args=None):
        """Get direct messages for the authenticating user.

        Search results are returned one message at a time a DirectMessage
        objects"""
        return self.__get('/direct_messages.xml', delegate, params,
                          txml.Direct, extra_args=extra_args)


Instruction:
Can you tell what is the following Python 3 function doing
def send_direct_message(self, text, user=None, delegate=None, screen_name=None, user_id=None, params={}):
        params = params.copy()
        if user is not None:
            params['user'] = user
        if user_id is not None:
            params['user_id'] = user_id
        if screen_name is not None:
            params['screen_name'] = screen_name
        params['text'] = text
        parser = txml.Direct(delegate)
        return self.__postPage('/direct_messages/new.xml', parser, params)

Response: Send a direct message to the user.


Instruction:
How would you code a function in Python 3 to
get the most recent replies for the authenticating user.

Response:
def replies(self, delegate, params={}, extra_args=None):
        """Get the most recent replies for the authenticating user.

        See search for example of how results are returned."""
        return self.__get('/statuses/replies.atom', delegate, params,
                          extra_args=extra_args)


Instruction:
Make a summary of the following Python 3 code
def follow_user(self, user, delegate):
        parser = txml.Users(delegate)
        return self.__postPage('/friendships/create/%s.xml' % (user), parser)

Response: Follow the given user. Returns the user info back to the given delegate.


Instruction:
Can you tell what is the following Python 3 function doing
def unfollow_user(self, user, delegate):
        parser = txml.Users(delegate)
        return self.__postPage('/friendships/destroy/%s.xml' % (user), parser)

Response: Unfollows the given user. Returns the user info back to the given delegate.


Instruction:
How would you code a function in Python 3 to
get the list of friends for a user. Calls the delegate with each user object found.

Response:
def list_friends(self, delegate, user=None, params={}, extra_args=None, page_delegate=None):
        """Get the list of friends for a user.

        Calls the delegate with each user object found."""
        if user:
            url = '/statuses/friends/' + user + '.xml'
        else:
            url = '/statuses/friends.xml'

        return self.__get_maybe_paging(url, delegate, params, txml.PagedUserList, extra_args, page_delegate)


Instruction:
Write a Python 3 script to
get the info for a specific user. Returns a delegate that will receive the user in a callback.

Response:
def show_user(self, user):
        """Get the info for a specific user.

        Returns a delegate that will receive the user in a callback."""

        url = '/users/show/%s.xml' % (user)
        d = defer.Deferred()

        self.__downloadPage(url, txml.Users(lambda u: d.callback(u))) \
            .addErrback(lambda e: d.errback(e))

        return d


Instruction:
How would you explain what the following Python 3 function does
def search(self, query, delegate, args=None, extra_args=None):
        if args is None:
            args = {}
        args['q'] = query
        return self.__doDownloadPage(self.search_url + '?' + self._urlencode(args),
            txml.Feed(delegate, extra_args), agent=self.agent)

Response: Perform a search query.


Instruction:
Explain what the following Python 3 code does
def startService(self):
        service.Service.startService(self)
        self._toState('idle')

        try:
            self.connect()
        except NoConsumerError:
            pass

Response:
Start the service.

        This causes a transition to the C{'idle'} state, and then calls
        L{connect} to attempt an initial conection.


Instruction:
How would you code a function in Python 3 to
connect to the current state of the current Tweets.

Response:
def connect(self, forceReconnect=False):
        """
        Check current conditions and initiate connection if possible.

        This is called to check preconditions for starting a new connection,
        and initating the connection itself.

        If the service is not running, this will do nothing.

        @param forceReconnect: Drop an existing connection to reconnnect.
        @type forceReconnect: C{False}

        @raises L{ConnectError}: When a connection (attempt) is already in
            progress, unless C{forceReconnect} is set.

        @raises L{NoConsumerError}: When there is no consumer for incoming
        tweets. No further connection attempts will be made, unless L{connect}
        is called again.
        """
        if self._state == 'stopped':
            raise Error("This service is not running. Not connecting.")
        if self._state == 'connected':
            if forceReconnect:
                self._toState('disconnecting')
                return True
            else:
                raise ConnectError("Already connected.")
        elif self._state == 'aborting':
            raise ConnectError("Aborting connection in progress.")
        elif self._state == 'disconnecting':
            raise ConnectError("Disconnect in progress.")
        elif self._state == 'connecting':
            if forceReconnect:
                self._toState('aborting')
                return True
            else:
                raise ConnectError("Connect in progress.")

        if self.delegate is None:
            if self._state != 'idle':
                self._toState('idle')
            raise NoConsumerError()

        if self._state == 'waiting':
            if self._reconnectDelayedCall.called:
                self._reconnectDelayedCall = None
                pass
            else:
                self._reconnectDelayedCall.reset(0)
                return True

        self._toState('connecting')
        return True


Instruction:
Create a Python 3 function to
call when the connection has been established. This method is called when an HTTP 200 response has been received, with the protocol that decodes the individual Twitter stream elements. That protocol will call the consumer for all Twitter entries received. The protocol, stored in L{protocol}, has a deferred that fires when the connection is closed, causing a transition to the C{'disconnected'} state. @param protocol: The Twitter stream protocol. @type protocol: L{TwitterStream}

Response:
def makeConnection(self, protocol):
        """
        Called when the connection has been established.

        This method is called when an HTTP 200 response has been received,
        with the protocol that decodes the individual Twitter stream elements.
        That protocol will call the consumer for all Twitter entries received.

        The protocol, stored in L{protocol}, has a deferred that fires when
        the connection is closed, causing a transition to the
        C{'disconnected'} state.

        @param protocol: The Twitter stream protocol.
        @type protocol: L{TwitterStream}
        """
        self._errorState = None

        def cb(result):
            self.protocol = None
            if self._state == 'stopped':
                # Don't transition to any other state. We are stopped.
                pass
            else:
                if isinstance(result, failure.Failure):
                    reason = result
                else:
                    reason = None
                self._toState('disconnected', reason)

        self.protocol = protocol
        d = protocol.deferred
        d.addBoth(cb)


Instruction:
Can you create a Python 3 function that
attempts to reconnect. If the current back-off delay is 0, L{connect} is called. Otherwise, it will cause a transition to the C{'waiting'} state, ultimately causing a call to L{connect} when the delay expires.

Response:
def _reconnect(self, errorState):
        """
        Attempt to reconnect.

        If the current back-off delay is 0, L{connect} is called. Otherwise,
        it will cause a transition to the C{'waiting'} state, ultimately
        causing a call to L{connect} when the delay expires.
        """
        def connect():
            if self.noisy:
                log.msg("Reconnecting now.")
            self.connect()

        backOff = self.backOffs[errorState]

        if self._errorState != errorState or self._delay is None:
            self._errorState = errorState
            self._delay = backOff['initial']
        else:
            self._delay = min(backOff['max'], self._delay * backOff['factor'])

        if self._delay == 0:
            connect()
        else:
            self._reconnectDelayedCall = self.reactor.callLater(self._delay,
                                                                connect)
            self._toState('waiting')


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _toState(self, state, *args, **kwargs):
        try:
            method = getattr(self, '_state_%s' % state)
        except AttributeError:
            raise ValueError("No such state %r" % state)

        log.msg("%s: to state %r" % (self.__class__.__name__, state))
        self._state = state
        method(*args, **kwargs)

Response: Transition to the next state.


Instruction:
Write a Python 3 script for
stating of an error.

Response:
def _state_error(self, reason):
        """
        The connection attempt resulted in an error.

        Attempt a reconnect with a back-off algorithm.
        """
        log.err(reason)

        def matchException(failure):
            for errorState, backOff in self.backOffs.iteritems():
                if 'errorTypes' not in backOff:
                    continue
                if failure.check(*backOff['errorTypes']):
                    return errorState

            return 'other'

        errorState = matchException(reason)
        self._reconnect(errorState)


Instruction:
Write a Python 3 script for
calling when a line is received.

Response:
def lineReceived(self, line):
        """
        Called when a line is received.

        We expect a length in bytes or an empty line for keep-alive. If
        we got a length, switch to raw mode to receive that amount of bytes.
        """
        if line and line.isdigit():
            self._expectedLength = int(line)
            self._rawBuffer = []
            self._rawBufferLength = 0
            self.setRawMode()
        else:
            self.keepAliveReceived()


Instruction:
How would you explain what the following Python 3 function does
def rawDataReceived(self, data):
        self._rawBuffer.append(data)
        self._rawBufferLength += len(data)

        if self._rawBufferLength >= self._expectedLength:
            receivedData = ''.join(self._rawBuffer)
            expectedData = receivedData[:self._expectedLength]
            extraData = receivedData[self._expectedLength:]

            self._rawBuffer = None
            self._rawBufferLength = None
            self._expectedLength = None

            self.datagramReceived(expectedData)
            self.setLineMode(extraData)

Response: Called when raw data is received.


Instruction:
Can you create a Python 3 function that
fills this objects attributes from a dictionary for known properties.

Response:
def fromDict(cls, data):
        """
        Fill this objects attributes from a dict for known properties.
        """
        obj = cls()
        obj.raw = data
        for name, value in data.iteritems():
            if cls.SIMPLE_PROPS and name in cls.SIMPLE_PROPS:
                setattr(obj, name, value)
            elif cls.COMPLEX_PROPS and name in cls.COMPLEX_PROPS:
                value = cls.COMPLEX_PROPS[name].fromDict(value)
                setattr(obj, name, value)
            elif cls.LIST_PROPS and name in cls.LIST_PROPS:
                value = [cls.LIST_PROPS[name].fromDict(item)
                         for item in value]
                setattr(obj, name, value)

        return obj


Instruction:
Implement a function in Python 3 to
decode the JSON - encoded datagram and call the callback.

Response:
def datagramReceived(self, data):
        """
        Decode the JSON-encoded datagram and call the callback.
        """
        try:
            obj = json.loads(data)
        except ValueError, e:
            log.err(e, 'Invalid JSON in stream: %r' % data)
            return

        if u'text' in obj:
            obj = Status.fromDict(obj)
        else:
            log.msg('Unsupported object %r' % obj)
            return

        self.callback(obj)


Instruction:
Can you implement a function in Python 3 that
calls when the connection is lost.

Response:
def connectionLost(self, reason):
        """
        Called when the body is complete or the connection was lost.

        @note: As the body length is usually not known at the beginning of the
        response we expect a L{PotentialDataLoss} when Twitter closes the
        stream, instead of L{ResponseDone}. Other exceptions are treated
        as error conditions.
        """
        self.setTimeout(None)
        if reason.check(ResponseDone, PotentialDataLoss):
            self.deferred.callback(None)
        else:
            self.deferred.errback(reason)


Instruction:
Explain what the following Python 3 code does
def simpleListFactory(list_type):
    def create(delegate, extra_args=None):
        """Create a Parser object for the specific tag type, on the fly"""
        return listParser(list_type, delegate, extra_args)
    return create

Response: Used for simple parsers that support only one type of object


Instruction:
How would you code a function in Python 3 to
set a delegate for a sub - sub - item according to a list of names

Response:
def setSubDelegates(self, namelist, before=None, after=None):
        """Set a delegate for a sub-sub-item, according to a list of names"""
        if len(namelist) > 1:
            def set_sub(i):
                i.setSubDelegates(namelist[1:], before, after)
            self.setBeforeDelegate(namelist[0], set_sub)
        elif len(namelist) == 1:
            self.setDelegate(namelist[0], before, after)


Instruction:
Implement a function in Python 3 to
split a path into sentinel list_path and path

Response:
def _split_path(path):
    """split a path return by the api

    return
        - the sentinel:
        - the rest of the path as a list.
        - the original path stripped of / for normalisation.
    """
    path = path.strip('/')
    list_path = path.split('/')
    sentinel = list_path.pop(0)
    return sentinel, list_path, path


Instruction:
Create a Python 3 function for
deactivating the contents manager class

Response:
def deactivate(profile='default'):
    """should be a matter of just unsetting the above keys
    """
    with jconfig(profile) as config:
        deact = True;
        if not getattr(config.NotebookApp.contents_manager_class, 'startswith',lambda x:False)('jupyterdrive'):
            deact=False
        if 'gdrive' not in getattr(config.NotebookApp.tornado_settings,'get', lambda _,__:'')('contents_js_source',''):
            deact=False
        if deact:
            del config['NotebookApp']['tornado_settings']['contents_js_source']
            del config['NotebookApp']['contents_manager_class']


Instruction:
Here you have a function in Python 3, explain what it does
def sequence_type(seq):
    '''Validates a coral.sequence data type.

    :param sequence_in: input DNA sequence.
    :type sequence_in: any
    :returns: The material - 'dna', 'rna', or 'peptide'.
    :rtype: str
    :raises: ValueError

    '''
    if isinstance(seq, coral.DNA):
        material = 'dna'
    elif isinstance(seq, coral.RNA):
        material = 'rna'
    elif isinstance(seq, coral.Peptide):
        material = 'peptide'
    else:
        raise ValueError('Input was not a recognized coral.sequence object.')
    return material

Response: Validates a coral. sequence data type. Returns the material - dna rna or peptide.


Instruction:
Can you implement a function in Python 3 that
simulates a PCR. :param template: DNA template from which to PCR. :type template: coral.DNA :param primer1: First PCR primer. :type primer1: coral.Primer :param primer2: First PCR primer. :type primer2: coral.Primer :param min_tm: Minimum melting temperature (Tm) at which primers must bind to the template. :type min_tm: float :param min_primer_len: Minimum amount of template homology required at the 3' end of each primer. :type min_primer_len: int :returns: A dsDNA Amplicon. :rtype: coral.DNA :raises: PrimingError if a primer binds more than once on the template, primers bind in overlapping sequence of the template, there are no forward primer binding sites or reverse priming sites, or if the PCR would work only on a circular version of the template (if template is linear).

Response:
def pcr(template, primer1, primer2, min_tm=50.0, min_primer_len=14):
    '''Simulate a PCR.

    :param template: DNA template from which to PCR.
    :type template: coral.DNA
    :param primer1: First PCR primer.
    :type primer1: coral.Primer
    :param primer2: First PCR primer.
    :type primer2: coral.Primer
    :param min_tm: Minimum melting temperature (Tm) at which primers must bind
                   to the template.
    :type min_tm: float
    :param min_primer_len: Minimum amount of template homology required at the
                           3' end of each primer.
    :type min_primer_len: int
    :returns: A dsDNA Amplicon.
    :rtype: coral.DNA
    :raises: PrimingError if a primer binds more than once on the template,
             primers bind in overlapping sequence of the template, there are no
             forward primer binding sites or reverse priming sites, or if the
             PCR would work only on a circular version of the template (if
             template is linear).

    '''
    # Find match in top or bottom strands for each primer
    p1_matches = coral.analysis.anneal(template, primer1, min_tm=min_tm,
                                       min_len=min_primer_len)
    p2_matches = coral.analysis.anneal(template, primer2, min_tm=min_tm,
                                       min_len=min_primer_len)
    p1_binding_locations = [m[0] for strand in p1_matches for m in strand]
    p2_binding_locations = [m[0] for strand in p2_matches for m in strand]

    # Ensure unique top and bottom matches
    if len(p1_binding_locations) > 1:
        primer_msg = 'Multiple primer 1 binding locations: {}'
        raise PrimingError(primer_msg.format(p1_binding_locations))

    if len(p2_binding_locations) > 1:
        primer_msg = 'Multiple primer 2 binding locations: {}'
        raise PrimingError(primer_msg.format(p2_binding_locations))

    if not p1_binding_locations and not p2_binding_locations:
        raise PrimingError('Neither primer binds the template')

    if not p1_binding_locations:
        raise PrimingError('Primer 1 does not bind the template')

    if not p2_binding_locations:
        raise PrimingError('Primer 2 does not bind the template')

    # Check that primers bind on opposite strands of the template
    tops = p1_matches[0] + p2_matches[0]
    bottoms = p1_matches[1] + p2_matches[1]
    if not tops:
        raise PrimingError('No primers bind the template\'s top strand.')
    if not bottoms:
        raise PrimingError('No primers bind the template\'s bottom strand.')

    # Figure out which primer matches the top strand
    if p1_matches[0]:
        # primer1 is top
        fwd = primer1
        rev = primer2
    else:
        # primer2 matches top strand
        fwd = primer2
        rev = primer1

    # Now we can simulate the PCR. If primer locations are overlapping, we
    # throw an error. If the primers won't amplify a product (e.g. a linear
    # template with primers facing away from one another), throw a different
    # error. Otherwise, amplify the product, including any overhangs.

    # 3' locations, annealing region length
    fwd_3, fwd_len = tops[0]
    rev_3, rev_len = bottoms[0]

    # 5' locations
    fwd_5 = fwd_3 - fwd_len
    rev_5 = rev_3 - rev_len

    # location on the top strand where the 'reverse' primer ends (its 3' end)
    rev_3_top = len(template) - rev_3
    rev_5_top = len(template) - rev_5
    # TODO: Use % operator?
    if rev_5_top > len(template):
        rev_5_top = rev_5_top - len(template)

    # overhangs
    fwd_overhang = fwd.primer()[:-fwd_len]
    rev_overhang = rev.primer()[:-rev_len]

    # TODO: what about searching substrings over circulate templates?
    # Cases:
    # 1)  Primers point towards one another - overlapping is fine
    #       -> isolate region between 5' annealing regions and tack on the
    #          rest of the overhang.
    # 2)  Primers point away from one another, template is linear
    #       -> error
    # 3)  Primers point away from one another, template is circular
    #       a) Primers don't overlap
    #           -> rotate to 'top' primer start, extract sequence
    #       b) Primers overlap
    #           -> Extract whole sequence as linear fragment, tack on rest of
    #              'bottom' primer. May disrupt features.
    if template.circular:
        # Circular template - primers always point towards one another
        if rev_3_top > fwd_3:
            # Inter-primer region doesn't go over the origin (index 0)
            # However, the 'anneal' region may extend over it.
            # FIXME: handle case where 'anneal' region extends over origin
            # FIXME: simplify - just generate 'before' and 'after', then
            # combine with preamplicon later
            if rev_3_top + rev_len > len(template):
                # Reverse primer extends over the origin
                if fwd_5 - fwd_len < 0:
                    # Forward primer extends over the origin
                    preamplicon = template.linearize()
                    # Add extra anneal regions
                    before = template[fwd_5:]
                    after = template[:rev_5_top]
                    preamplicon = before + preamplicon + after
                else:
                    # Only the reverse primer extends over the origin
                    preamplicon = template[fwd_5:]
                    after = template[:rev_5_top]
                    preamplicon = preamplicon + after
            elif fwd_5 - fwd_len < 0:
                # Only the forward primer extends over the origin
                before = template[fwd_5:]
                preamplicon = before + template[:rev_5_top]
            else:
                # Extract like normal
                preamplicon = template[fwd_5:len(template) - rev_5]
        else:
            # Inter-primer region goes over the origin (index 0)
            preamplicon_len = len(template) - fwd_5 + rev_5_top
            preamplicon = template.rotate(-fwd_5)[:preamplicon_len]
    else:
        # Linear template
        if rev_3_top < fwd_5 or fwd_3 > rev_5_top:
            # Primers point away from one another.
            raise PrimingError('Primers point away from one another.')
        else:
            # Primers point towards each other.
            preamplicon = template[fwd_5:len(template) - rev_5]

    # Add overhangs
    amplicon = (fwd_overhang.to_ds() +
                preamplicon +
                rev_overhang.to_ds().reverse_complement())

    return amplicon


Instruction:
Write a Python 3 function for
giving a DNA template and a restriction endonuclease reaction return a list of digested DNA fragments.

Response:
def digest(dna, restriction_enzyme):
    '''Restriction endonuclease reaction.

    :param dna: DNA template to digest.
    :type dna: coral.DNA
    :param restriction_site: Restriction site to use.
    :type restriction_site: RestrictionSite
    :returns: list of digested DNA fragments.
    :rtype: coral.DNA list

    '''
    pattern = restriction_enzyme.recognition_site
    located = dna.locate(pattern)
    if not located[0] and not located[1]:
        return [dna]
    # Bottom strand indices are relative to the bottom strand 5' end.
    # Convert to same type as top strand
    pattern_len = len(pattern)
    r_indices = [len(dna) - index - pattern_len for index in
                 located[1]]
    # If sequence is palindrome, remove redundant results
    if pattern.is_palindrome():
        r_indices = [index for index in r_indices if index not in
                     located[0]]
    # Flatten cut site indices
    cut_sites = sorted(located[0] + r_indices)
    # Go through each cut site starting at highest one
    # Cut remaining template once, generating remaining + new
    current = [dna]
    for cut_site in cut_sites[::-1]:
        new = _cut(current, cut_site, restriction_enzyme)
        current.append(new[1])
        current.append(new[0])
    current.reverse()
    # Combine first and last back together if digest was circular
    if dna.circular:
        current[0] = current.pop() + current[0]
    return current


Instruction:
Explain what the following Python 3 code does
def _cut(dna, index, restriction_enzyme):
    '''Cuts template once at the specified index.

    :param dna: DNA to cut
    :type dna: coral.DNA
    :param index: index at which to cut
    :type index: int
    :param restriction_enzyme: Enzyme with which to cut
    :type restriction_enzyme: coral.RestrictionSite
    :returns: 2-element list of digested sequence, including any overhangs.
    :rtype: list

    '''
    # TODO: handle case where cut site is outside of recognition sequence,
    # for both circular and linear cases where site is at index 0
    # Find absolute indices at which to cut
    cut_site = restriction_enzyme.cut_site
    top_cut = index + cut_site[0]
    bottom_cut = index + cut_site[1]

    # Isolate left and ride sequences
    to_cut = dna.pop()
    max_cut = max(top_cut, bottom_cut)
    min_cut = min(top_cut, bottom_cut)
    left = to_cut[:max_cut]
    right = to_cut[min_cut:]

    # If applicable, leave overhangs
    diff = top_cut - bottom_cut
    if not diff:
        # Blunt-end cutter, no adjustment necessary
        pass
    elif diff > 0:
        # 3' overhangs
        left = coral.reaction.five_resect(left.flip(), diff).flip()
        right = coral.reaction.five_resect(right, diff)
    else:
        # 5' overhangs
        left = coral.reaction.three_resect(left, abs(diff))
        right = coral.reaction.three_resect(right.flip(), abs(diff)).flip()

    return [left, right]

Response: Cuts template once at the specified index.


Instruction:
Can you tell what is the following Python 3 function doing
def ipynb_to_rst(directory, filename):
    print(filename)
    os.chdir(directory)
    subprocess.Popen(["ipython", "nbconvert", "--to", "rst",
                      filename],
                     stdout=subprocess.PIPE,
                     stderr=subprocess.PIPE,
                     cwd=directory)

Response: Converts a given file in a directory to an rst in the same directory.


Instruction:
Given the following Python 3 function, write the documentation
def convert_ipynbs(directory):
    # The ipython_examples dir has to be in the same dir as this script
    for root, subfolders, files in os.walk(os.path.abspath(directory)):
        for f in files:
            if ".ipynb_checkpoints" not in root:
                if f.endswith("ipynb"):
                    ipynb_to_rst(root, f)

Response:
Recursively converts all ipynb files in a directory into rst files in
    the same directory.


Instruction:
Given the following Python 3 function, write the documentation
def _context_walk(dna, window_size, context_len, step):
    '''Generate context-dependent 'non-boundedness' scores for a DNA sequence.

    :param dna: Sequence to score.
    :type dna: coral.DNA
    :param window_size: Window size in base pairs.
    :type window_size: int
    :param context_len: The number of bases of context to use when analyzing
                        each window.
    :type context_len: int
    :param step: The number of base pairs to move for each new window.
    :type step: int

    '''
    # Generate window indices
    window_start_ceiling = len(dna) - context_len - window_size
    window_starts = range(context_len - 1, window_start_ceiling, step)
    window_ends = [start + window_size for start in window_starts]

    # Generate left and right in-context subsequences
    l_starts = [step * i for i in range(len(window_starts))]
    l_seqs = [dna[start:end] for start, end in zip(l_starts, window_ends)]
    r_ends = [x + window_size + context_len for x in window_starts]
    r_seqs = [dna[start:end].reverse_complement() for start, end in
              zip(window_starts, r_ends)]

    # Combine and calculate nupack pair probabilities
    seqs = l_seqs + r_seqs
    pairs_run = coral.analysis.nupack_multi(seqs, 'dna', 'pairs', {'index': 0})
    # Focus on pair probabilities that matter - those in the window
    pairs = [run[-window_size:] for run in pairs_run]
    # Score by average pair probability
    lr_scores = [sum(pair) / len(pair) for pair in pairs]

    # Split into left-right contexts again and sum for each window
    l_scores = lr_scores[0:len(seqs) / 2]
    r_scores = lr_scores[len(seqs) / 2:]
    scores = [(l + r) / 2 for l, r in zip(l_scores, r_scores)]

    # Summarize and return window indices and score
    summary = zip(window_starts, window_ends, scores)

    return summary

Response: Generate a context - dependent non - boundedness score for a DNA sequence.


Instruction:
How would you code a function in Python 3 to
walk through the sequence of interest in windows of window_size evaluate free pair probabilities.

Response:
def windows(self, window_size=60, context_len=90, step=10):
        '''Walk through the sequence of interest in windows of window_size,
        evaluate free (unbound) pair probabilities.

        :param window_size: Window size in base pairs.
        :type window_size: int
        :param context_len: The number of bases of context to use when
                            analyzing each window.
        :type context_len: int
        :param step: The number of base pairs to move for each new window.
        :type step: int

        '''
        self.walked = _context_walk(self.template, window_size, context_len,
                                    step)
        self.core_starts, self.core_ends, self.scores = zip(*self.walked)
        return self.walked


Instruction:
Make a summary of the following Python 3 code
def plot(self):
        '''Plot the results of the run method.'''
        try:
            from matplotlib import pylab
        except ImportError:
            raise ImportError('Optional dependency matplotlib not installed.')

        if self.walked:
            fig = pylab.figure()
            ax1 = fig.add_subplot(111)
            ax1.plot(self.core_starts, self.scores, 'bo-')
            pylab.xlabel('Core sequence start position (base pairs).')
            pylab.ylabel('Score - Probability of being unbound.')
            pylab.show()
        else:
            raise Exception('Run calculate() first so there\'s data to plot!')

Response: Plot the results of the run method.


Instruction:
Write a Python 3 script to
simulate a primer binding event. Will find the maximum subset of basepairs in the primer that binds to the template and extend them until the maximum basepair is found.

Response:
def anneal(template, primer, min_tm=50.0, min_len=10):
    '''Simulates a primer binding event. Will find the maximum subset
    of bases in the primer that binds to the template, including overhang
    sequences. **Note**: Primer binding locations indicate the 3' end of the
    primer, not the begining of the annealing sequence.

    :param template: DNA template for which to bind a primer.
    :type template: coral.DNA
    :param primer: Primer to bind to template.
    :type primer: coral.Primer
    :param min_tm: The cutoff melting temperature for primer binding - a binder
                   with a lower Tm will be rejected.
    :type min_tm: float
    :param min_len: The cutoff for bases required for binding - a binder with
                    fewer bases will be rejected.
    :type min_len: int
    :returns: A length 2 list (top and bottom strands) of matches. Each
              match is itself a 2-tuple indicating (1) the location on the
              template of the 3' end of the primer binding site and (2) the
              length of the match (number of bases), e.g. [[(25, 15)],[]] would
              indicate a single top-strand match at template position 25 with
              15 bases of 3' primer homology.
    :rtype: list
    :raises: PrimerLengthError if primer length is too small.
             AnnealError if inputs are of the wrong type.

    '''
    # TODO: add possibility for primer basepair mismatch
    if len(primer) < min_len:
        msg = 'Primer length is shorter than min_len argument.'
        raise PrimerLengthError(msg)
    if len(template) < min_len:
        msg = 'Template is shorter than the min_len argument.'
        raise AnnealError(msg)

    # Strategy: locate all min-length matches, then extend them until they
    # no longer match. This provides an advantage over the previous strategy of
    # updating a dictionary with indices from coral.DNA.locate() as keys, as
    # the latter's indices may actually move for a given primer as it passes
    # over the origin
    def update_match_linear(base, location_length, anneal_seq):
        '''Increase the location and length of binding site, if applicable.'''
        # TODO: this is very inefficient - should stop updating once the first
        # mismatch occurs.
        location, length = location_length

        if location == 0:
            return location_length

        location_next = location - 1
        length_next = length + 1
        seq = base[location_next:location_next + length_next]

        if seq == anneal_seq:
            return (location_next, length_next)
        else:
            return location_length

    def update_match_circular(base, location_length, anneal_seq):
        '''Increase the location and length of binding site, if applicable.'''
        # TODO: this is very inefficient - should stop updating once the first
        # mismatch occurs.
        base_len = len(base)
        location, length = location_length
        if location == 0:
            location_next = base_len - 1
        else:
            location_next = location - 1
        length_next = length + 1

        if (location_next + length_next) > base_len:
            upstream = base[location_next:]
            downstream = base[:length_next - (base_len - location_next)]
            seq = upstream + downstream
        else:
            # No need to 'rotate' sequence
            seq = base[location_next:location_next + length_next]

        if seq == anneal_seq:
            return (location_next, length_next)
        else:
            return location_length

    if template.circular:
        update_fun = update_match_circular
    else:
        update_fun = update_match_linear

    # Maximum annealing length to test (can't exceed template length)
    max_len = min(len(template), len(primer))

    primer_dna = primer.to_ds()
    anneal_len = min_len
    anneal_seq = primer_dna[-anneal_len:]
    binding_data = []
    for k, strand_locs in enumerate(template.locate(anneal_seq)):
        matches = zip(strand_locs, [min_len] * len(strand_locs))
        for i in range(anneal_len + 1, max_len + 1):
            anneal_seq = primer_dna[-i:]
            for j, match in enumerate(matches):
                if k == 0:
                    matches[j] = update_fun(template.top, match, anneal_seq)
                else:
                    matches[j] = update_fun(template.bottom, match,
                                            anneal_seq)
        binding_data.append(matches)

    # Now, filter out all the matches that are too short
    for i in reversed(range(len(primer_dna) + 1)):
        min_len = i + 1
        tm = primer_dna[-min_len:].tm()
        if tm < min_tm:
            break

    for strand in binding_data:
        for i in reversed(range(len(strand))):
            if strand[i][1] < min_len:
                strand.pop(i)

    # Finally, adjust the position to be the 3' end
    for strand in binding_data:
        for i, match in enumerate(strand):
            length = match[1]
            loc_new = match[0] + length
            if loc_new > len(template):
                # Circularly permute
                loc_new = loc_new - len(template)
            strand[i] = [loc_new, length]

    # Overwriting dictionary keys ensures uniqueness
    # fwd_matches = {}
    # rev_matches = {}
    # for i in range(len(primer) - min_len + 1)[::-1]:
    #     primer_dna = primer.overhang + primer.anneal
    #     annealing = primer_dna[i:]
    #     anneal_temp = annealing.tm()
    #     anneal_len = len(annealing)
    #     if anneal_temp > min_tm:
    #         p_matches = template.locate(annealing)
    #         for match in p_matches[0]:
    #             fwd_matches[match + anneal_len] = anneal_len
    #         for match in p_matches[1]:
    #             rev_matches[match + anneal_len] = anneal_len

    # # Convert dictionaries to lists
    # fwds = [[key, val] for key, val in fwd_matches.iteritems()]
    # revs = [[key, val] for key, val in rev_matches.iteritems()]

    return binding_data


Instruction:
Can you create a Python 3 function that
designs a primer to a nearest - neighbor Tm setpoint.

Response:
def primer(dna, tm=65, min_len=10, tm_undershoot=1, tm_overshoot=3,
           end_gc=False, tm_parameters='cloning', overhang=None,
           structure=False):
    '''Design primer to a nearest-neighbor Tm setpoint.

    :param dna: Sequence for which to design a primer.
    :type dna: coral.DNA
    :param tm: Ideal primer Tm in degrees C.
    :type tm: float
    :param min_len: Minimum primer length.
    :type min_len: int
    :param tm_undershoot: Allowed Tm undershoot.
    :type tm_undershoot: float
    :param tm_overshoot: Allowed Tm overshoot.
    :type tm_overshoot: float
    :param end_gc: Obey the 'end on G or C' rule.
    :type end_gc: bool
    :param tm_parameters: Melting temp calculator method to use.
    :type tm_parameters: string
    :param overhang: Append the primer to this overhang sequence.
    :type overhang: str
    :param structure: Evaluate primer for structure, with warning for high
                      structure.
    :type structure: bool
    :returns: A primer.
    :rtype: coral.Primer
    :raises: ValueError if the input sequence is lower than the Tm settings
             allow.
             ValueError if a primer ending with G or C can't be found given
             the Tm settings.

    '''
    # Check Tm of input sequence to see if it's already too low
    seq_tm = coral.analysis.tm(dna, parameters=tm_parameters)
    if seq_tm < (tm - tm_undershoot):
        msg = 'Input sequence Tm is lower than primer Tm setting'
        raise ValueError(msg)
    # Focus on first 90 bases - shouldn't need more than 90bp to anneal
    dna = dna[0:90]

    # Generate primers from min_len to 'tm' + tm_overshoot
    # TODO: this is a good place for optimization. Only calculate as many
    # primers as are needed. Use binary search.
    primers_tms = []
    last_tm = 0
    bases = min_len
    while last_tm <= tm + tm_overshoot and bases != len(dna):
        next_primer = dna[0:bases]
        last_tm = coral.analysis.tm(next_primer, parameters=tm_parameters)
        primers_tms.append((next_primer, last_tm))
        bases += 1

    # Trim primer list based on tm_undershoot and end_gc
    primers_tms = [(primer, melt) for primer, melt in primers_tms if
                   melt >= tm - tm_undershoot]
    if end_gc:
        primers_tms = [pair for pair in primers_tms if
                       pair[0][-1] == coral.DNA('C') or
                       pair[0][-1] == coral.DNA('G')]
    if not primers_tms:
        raise ValueError('No primers could be generated using these settings')

    # Find the primer closest to the set Tm, make it single stranded
    tm_diffs = [abs(melt - tm) for primer, melt in primers_tms]
    best_index = tm_diffs.index(min(tm_diffs))
    best_primer, best_tm = primers_tms[best_index]
    best_primer = best_primer.top

    # Apply overhang
    if overhang:
        overhang = overhang.top

    output_primer = coral.Primer(best_primer, best_tm, overhang=overhang)

    def _structure(primer):
        '''Check annealing sequence for structure.

        :param primer: Primer for which to evaluate structure
        :type primer: sequence.Primer

        '''
        # Check whole primer for high-probability structure, focus in on
        # annealing sequence, report average
        nupack = coral.analysis.Nupack(primer.primer())
        pairs = nupack.pairs(0)
        anneal_len = len(primer.anneal)
        pairs_mean = sum(pairs[-anneal_len:]) / anneal_len
        if pairs_mean < 0.5:
            warnings.warn('High probability structure', Warning)
        return pairs_mean
    if structure:
        _structure(output_primer)
    return output_primer


Instruction:
How would you code a function in Python 3 to
design primers for PCR amplifying any arbitrary sequence.

Response:
def primers(dna, tm=65, min_len=10, tm_undershoot=1, tm_overshoot=3,
            end_gc=False, tm_parameters='cloning', overhangs=None,
            structure=False):
    '''Design primers for PCR amplifying any arbitrary sequence.

    :param dna: Input sequence.
    :type dna: coral.DNA
    :param tm: Ideal primer Tm in degrees C.
    :type tm: float
    :param min_len: Minimum primer length.
    :type min_len: int
    :param tm_undershoot: Allowed Tm undershoot.
    :type tm_undershoot: float
    :param tm_overshoot: Allowed Tm overshoot.
    :type tm_overshoot: float
    :param end_gc: Obey the 'end on G or C' rule.
    :type end_gc: bool
    :param tm_parameters: Melting temp calculator method to use.
    :type tm_parameters: string
    :param overhangs: 2-tuple of overhang sequences.
    :type overhangs: tuple
    :param structure: Evaluate each primer for structure, with warning for high
                      structure.
    :type structure: bool
    :returns: A list primers (the output of primer).
    :rtype: list

    '''
    if not overhangs:
        overhangs = [None, None]
    templates = [dna, dna.reverse_complement()]
    primer_list = []
    for template, overhang in zip(templates, overhangs):
        primer_i = primer(template, tm=tm, min_len=min_len,
                          tm_undershoot=tm_undershoot,
                          tm_overshoot=tm_overshoot, end_gc=end_gc,
                          tm_parameters=tm_parameters,
                          overhang=overhang, structure=structure)
        primer_list.append(primer_i)
    return primer_list


Instruction:
Write a Python 3 function for
giving a list of DNA sequences assemble into a single construct.

Response:
def assemble_oligos(dna_list, reference=None):
    '''Given a list of DNA sequences, assemble into a single construct.
    :param dna_list: List of DNA sequences - they must be single-stranded.
    :type dna_list: coral.DNA list
    :param reference: Expected sequence - once assembly completed, this will
    be used to reorient the DNA (assembly could potentially occur from either
    side of a linear DNA construct if oligos are in a random order). If this
    fails, an AssemblyError is raised.
    :type reference: coral.DNA
    :raises: AssemblyError if it can't assemble for any reason.
    :returns: A single assembled DNA sequence
    :rtype: coral.DNA

    '''
    # FIXME: this protocol currently only supports 5' ends on the assembly
    # Find all matches for every oligo. If more than 2 per side, error.
    # Self-oligo is included in case the 3' end is self-complementary.
    # 1) Find all unique 3' binders (and non-binders).
    match_3 = [bind_unique(seq, dna_list, right=True) for i, seq in
               enumerate(dna_list)]
    # 2) Find all unique 5' binders (and non-binders).
    match_5 = [bind_unique(seq, dna_list, right=False) for i, seq in
               enumerate(dna_list)]
    # Assemble into 2-tuple
    zipped = zip(match_5, match_3)

    # 3) If none found, error out with 'oligo n has no binders'
    for i, oligo_match in enumerate(zipped):
        if not any(oligo_match):
            error = 'Oligo {} has no binding partners.'.format(i + 1)
            raise AssemblyError(error)
    # 4) There should be exactly 2 oligos that bind at 3' end but
    # not 5'.
    ends = []
    for i, (five, three) in enumerate(zipped):
        if five is None and three is not None:
            ends.append(i)
    # 5) If more than 2, error with 'too many ends'.
    if len(ends) > 2:
        raise AssemblyError('Too many (>2) end oligos found.')
    # 6) If more than 2, error with 'not enough ends'.
    if len(ends) < 2:
        raise AssemblyError('Not enough (<2) end oligos found.')
    # NOTE:If 1-4 are satisfied, unique linear assembly has been found (proof?)
    # 8) Start with first end and build iteratively
    last_index = ends[0]
    assembly = dna_list[last_index]
    flip = True
    # This would be slightly less complicated if the sequences were tied to
    # their match info in a tuple
    # Append next region n - 1 times
    for i in range(len(dna_list) - 1):
        if flip:
            # Next oligo needs to be flipped before concatenation
            # Grab 3' match from last oligo's info
            current_index, matchlen = zipped[last_index][1]
            # Get new oligo sequence, make double-stranded for concatenation
            next_oligo = dna_list[current_index].to_ds()
            # Reverse complement for concatenation
            next_oligo = next_oligo.reverse_complement()
            # Don't reverse complement the next one
            flip = False
        else:
            # Grab 5' match from last oligo's info
            current_index, matchlen = zipped[last_index][0]
            # Get new oligo sequence, make double-stranded for concatenation
            next_oligo = dna_list[current_index].to_ds()
            # Reverse complement the next one
            flip = True
        # Trim overlap from new sequence
        next_oligo = next_oligo[(matchlen - 1):]
        # Concatenate and update last oligo's information
        assembly += next_oligo
        last_index = current_index
    if reference:
        if assembly == reference or assembly == reference.reverse_complement():
            return assembly
        else:
            raise AssemblyError('Assembly did not match reference')
    else:
        return assembly


Instruction:
Can you create a Python 3 function that
binds a sequence to a sequence that uniquely matches the reverse - complement of the associated 5 or 3 region of one sequence in a list of query sequences.

Response:
def bind_unique(reference, query_list, min_overlap=12, right=True):
    '''(5' or 3' region on reference sequence that uniquely matches the reverse
    complement of the associated (5' or 3') region of one sequence in a list of
    query sequences.

    :param reference: Reference sequence.
    :type reference: coral.DNA
    :param query_list: List of query sequences.
    :type query_list: coral.DNA list
    :param min_overlap: Minimum overlap for a match (in bp).
    :type min_overlap: int
    :param right: Check right side of sequence (3'). False results in 5' check.
    :type right: bool
    :returns: Tuple of the indices of any matches and the size of the match in
              bp.
    :rtype: tuple of ints
    :raises: AssemblyError if more than one match is found.

    '''
    size = min_overlap
    found = []
    # Reverse complementing here provides massive speedup?
    rev_query = [seq.reverse_complement() for seq in query_list]
    while not found and not size > len(reference):
        for i, seq in enumerate(rev_query):
            if right:
                # FIXME: these getitems are the slowest part of assembly
                # Easiest speedup?
                if reference.endswith(seq[:size]):
                    found.append(i)
            else:
                if reference.startswith(seq[-size:]):
                    found.append(i)
        size += 1
    if len(found) > 1:
        raise AssemblyError('Ambiguous oligo binding')
    if not found:
        return None
    else:
        return found[0], size


Instruction:
Make a summary of the following Python 3 code
def nonmatches(self):
        '''Report mismatches, indels, and coverage.'''
        # For every result, keep a dictionary of mismatches, insertions, and
        # deletions
        report = []
        for result in self.aligned_results:
            report.append(self._analyze_single(self.aligned_reference, result))

        return report

Response: Report mismatches indels deletions and coverage.


Instruction:
Write a Python 3 function for
making a summary plot of the alignment and highlight nonmatches.

Response:
def plot(self):
        '''Make a summary plot of the alignment and highlight nonmatches.'''
        import matplotlib.pyplot as plt
        import matplotlib.patches as patches

        # Constants to use throughout drawing
        n = len(self.results)
        nbases = len(self.aligned_reference)
        barheight = 0.4

        # Vary height of figure based on number of results
        figheight = 3 + 3 * (n - 1)
        fig = plt.figure(figsize=(9, figheight))
        ax1 = fig.add_subplot(111)

        # Plot bars to represent coverage area
        # Reference sequence
        ax1.add_patch(patches.Rectangle((0, 0), nbases, barheight,
                                        facecolor='black'))
        # Results
        for i, report in enumerate(self.nonmatches()):
            j = i + 1
            start, stop = report['coverage']
            patch = patches.Rectangle((start, j), stop - start, barheight,
                                      facecolor='darkgray')
            ax1.add_patch(patch)

            # Draw a vertical line for each type of result
            plt.vlines(report['mismatches'], j, j + barheight,
                       colors='b')
            plt.vlines(report['insertions'], j, j + barheight,
                       colors='r')

            # Terminal trailing deletions shouldn't be added
            deletions = []
            crange = range(*report['coverage'])
            deletions = [idx for idx in report['deletions'] if idx in crange]
            plt.vlines(deletions, j, j + barheight,
                       colors='g')

        ax1.set_xlim((0, nbases))
        ax1.set_ylim((-0.3, n + 1))
        ax1.set_yticks([i + barheight / 2 for i in range(n + 1)])
        ax1.set_yticklabels(['Reference'] + self.names)

        # Add legend
        mismatch_patch = patches.Patch(color='blue', label='Mismatch')
        insertion_patch = patches.Patch(color='red', label='Insertion')
        deletion_patch = patches.Patch(color='green', label='Deletion')
        plt.legend(handles=[mismatch_patch, insertion_patch, deletion_patch],
                   loc=1, ncol=3, mode='expand', borderaxespad=0.)

        plt.show()


Instruction:
Create a Python 3 function to
report mistmatches and indels for a single aligned reference and result.

Response:
def _analyze_single(self, reference, result):
        '''Report mistmatches and indels for a single (aligned) reference and
        result.'''
        # TODO: Recalculate coverage based on reference (e.g. sequencing result
        # longer than template
        reference_str = str(reference)
        result_str = str(result)
        report = {'mismatches': [], 'insertions': [], 'deletions': []}
        for i, (ref, res) in enumerate(zip(reference_str, result_str)):
            if ref != res:
                # It's a mismatch or indel
                if ref == '-':
                    report['insertions'].append(i)
                if res == '-':
                    report['deletions'].append(i)
                else:
                    report['mismatches'].append(i)

        start = len(result_str) - len(result_str.lstrip('-'))
        stop = len(result_str) - len(result_str.rstrip('-'))
        report['coverage'] = [start, stop]

        return report


Instruction:
Implement a Python 3 function for
removing terminal Ns from sequencing results.

Response:
def _remove_n(self):
        '''Remove terminal Ns from sequencing results.'''
        for i, result in enumerate(self.results):
            largest = max(str(result).split('N'), key=len)
            start = result.locate(largest)[0][0]
            stop = start + len(largest)
            if start != stop:
                self.results[i] = self.results[i][start:stop]


Instruction:
Can you generate a brief explanation for the following Python 3 code
def random_dna(n):
    '''Generate a random DNA sequence.

    :param n: Output sequence length.
    :type n: int
    :returns: Random DNA sequence of length n.
    :rtype: coral.DNA

    '''
    return coral.DNA(''.join([random.choice('ATGC') for i in range(n)]))

Response: Generate a random DNA sequence.


Instruction:
Write a Python 3 function that can
generate randomized codons given a peptide sequence.

Response:
def random_codons(peptide, frequency_cutoff=0.0, weighted=False, table=None):
    '''Generate randomized codons given a peptide sequence.

    :param peptide: Peptide sequence for which to generate randomized
                    codons.
    :type peptide: coral.Peptide
    :param frequency_cutoff: Relative codon usage cutoff - codons that
                             are rarer will not be used. Frequency is
                             relative to average over all codons for a
                             given amino acid.
    :param frequency_cutoff: Codon frequency table to use.
    :param weighted: Use codon table
    :type weighted: bool
    :param table: Codon frequency table to use. Table should be organized
                  by amino acid, then be a dict of codon: frequency.
                  Only relevant if weighted=True or frequency_cutoff > 0.
                  Tables available:

                  constants.molecular_bio.CODON_FREQ_BY_AA['sc'] (default)
    :type table: dict
    :returns: Randomized sequence of codons (DNA) that code for the input
              peptide.
    :rtype: coral.DNA
    :raises: ValueError if frequency_cutoff is set so high that there are no
             codons available for an amino acid in the input peptide.

    '''
    if table is None:
        table = CODON_FREQ_BY_AA['sc']
    # Process codon table using frequency_cutoff
    new_table = _cutoff(table, frequency_cutoff)
    # Select codons randomly or using weighted distribution
    rna = ''
    for amino_acid in str(peptide):
        codons = new_table[amino_acid.upper()]
        if not codons:
            raise ValueError('No {} codons at freq cutoff'.format(amino_acid))
        if weighted:
            cumsum = []
            running_sum = 0
            for codon, frequency in codons.iteritems():
                running_sum += frequency
                cumsum.append(running_sum)
            random_num = random.uniform(0, max(cumsum))
            for codon, value in zip(codons, cumsum):
                if value > random_num:
                    selection = codon
                    break
        else:
            selection = random.choice(codons.keys())
        rna += selection
    return coral.RNA(rna)


Instruction:
Write a Python 3 function that can
generate a new codon frequency table given a mean cutoff.

Response:
def _cutoff(table, frequency_cutoff):
    '''Generate new codon frequency table given a mean cutoff.

    :param table: codon frequency table of form {amino acid: codon: frequency}
    :type table: dict
    :param frequency_cutoff: value between 0 and 1.0 for mean frequency cutoff
    :type frequency_cutoff: float
    :returns: A codon frequency table with some codons removed.
    :rtype: dict

    '''
    new_table = {}
    # IDEA: cutoff should be relative to most-frequent codon, not average?
    for amino_acid, codons in table.iteritems():
        average_cutoff = frequency_cutoff * sum(codons.values()) / len(codons)
        new_table[amino_acid] = {}
        for codon, frequency in codons.iteritems():
            if frequency > average_cutoff:
                new_table[amino_acid][codon] = frequency
    return new_table


Instruction:
Can you create a Python 3 function that
acquires a genome from Entrez and return it as a sequence.

Response:
def fetch_genome(genome_id):
    '''Acquire a genome from Entrez

    '''
    # TODO: Can strandedness by found in fetched genome attributes?
    # TODO: skip read/write step?
    # Using a dummy email for now - does this violate NCBI guidelines?
    email = 'loremipsum@gmail.com'
    Entrez.email = email

    print 'Downloading Genome...'
    handle = Entrez.efetch(db='nucleotide', id=str(genome_id), rettype='gb',
                           retmode='text')
    print 'Genome Downloaded...'
    tmpfile = os.path.join(mkdtemp(), 'tmp.gb')
    with open(tmpfile, 'w') as f:
        f.write(handle.read())
    genome = coral.seqio.read_dna(tmpfile)

    return genome


Instruction:
Can you generate the documentation for the following Python 3 function
def cofold(self, strand1, strand2, temp=37.0, dangles=2, nolp=False,
               nogu=False, noclosinggu=False, constraints=None,
               canonicalbponly=False, partition=-1, pfscale=None, gquad=False):
        '''Run the RNAcofold command and retrieve the result in a dictionary.

        :param strand1: Strand 1 for running RNAcofold.
        :type strand1: coral.DNA or coral.RNA
        :param strand1: Strand 2 for running RNAcofold.
        :type strand2: coral.DNA or coral.RNA
        :param temp: Temperature at which to run the calculations.
        :type temp: float
        :param dangles: How to treat dangling end energies. Set to 0 to ignore
                        dangling ends. Set to 1 to limit unpaired bases to
                        at most one dangling end (default for MFE calc). Set to
                        2 (the default) to remove the limit in 1. Set to 3 to
                        allow coaxial stacking of adjacent helices in
                        .multi-loops
        :type dangles: int
        :param nolp: Produce structures without lonely pairs (isolated single
                     base pairs).
        :type nolp: bool
        :param nogu: Do not allow GU pairs.
        :type nogu: bool
        :param noclosinggu: Do not allow GU pairs at the end of helices.
        :type noclosinggu: bool
        :param constraints: Any structural constraints to use. Format is
                            defined at
                            http://www.tbi.univie.ac.at/RNA/RNAfold.1.html
        :type constraints: str
        :param canonicalbponly: Remove non-canonical base pairs from the
                                structure constraint (if applicable).
        :type canonicalbponly: bool
        :param partition: Calculates the partition function for the sequence.
        :type partition: int
        :param pfscale: Scaling factor for the partition function.
        :type pfScale: float
        :param gquad: Incorporate G-Quadruplex formation into the structure
                      prediction.
        :type gquad: bool

        :returns: Dictionary of calculated values, defaulting to values of MFE
                  ('mfe': float) and dotbracket structure ('dotbracket': str).
                  More keys are added depending on keyword arguments.
        :rtype: dict

        '''
        cmd_args = []
        cmd_kwargs = {'--temp=': str(temp)}
        cmd_kwargs['--dangles='] = dangles
        if nolp:
            cmd_args.append('--noLP')
        if nogu:
            cmd_args.append('--noGU')
        if noclosinggu:
            cmd_args.append('--noClosingGU')
        if constraints is not None:
            cmd_args.append('--constraint')
            if canonicalbponly:
                cmd_args.append('--canonicalBPonly')
        if partition:
            cmd_args.append('--partfunc')
        if pfscale is not None:
            cmd_kwargs['pfScale'] = float(pfscale)
        if gquad:
            cmd_args.append('--gquad')

        inputs = ['>strands\n{}&{}'.format(str(strand1), str(strand2))]
        if constraints is not None:
            inputs.append(constraints)

        rnafold_output = self._run('RNAcofold', inputs, cmd_args, cmd_kwargs)

        # Process the output
        output = {}
        lines = rnafold_output.splitlines()
        # Line 1 is the name of the sequence input, line 2 is the sequence
        lines.pop(0)
        lines.pop(0)
        # Line 3 is the dotbracket + mfe for strand1
        line3 = lines.pop(0)
        output['dotbracket'] = self._lparse(line3, '^(.*) \(')
        output['mfe'] = float(self._lparse(line3, ' \((.*)\)$'))
        # Optional outputs
        if partition:
            # Line 4 is 'a coarse representation of the pair probabilities' and
            # the ensemble free energy
            line4 = lines.pop(0)
            output['coarse'] = self._lparse(line4, '^(.*) \[')
            output['ensemble'] = float(self._lparse(line4, ' \[(.*)\]$'))
            # Line 5 is the centroid structure, its free energy, and distance
            # to the ensemble
            line5 = lines.pop(0)
            'ensemble (.*),'
            output['frequency'] = float(self._lparse(line5, 'ensemble (.*),'))
            output['deltaG'] = float(self._lparse(line5, 'binding=(.*)$'))
            # Parse the postscript file (the only place the probability matrix
            # is)
            with open(os.path.join(self._tempdir, 'strands_dp.ps')) as f:
                pattern = 'start of base pair probability data\n(.*)\nshowpage'
                dotplot_file = f.read()
                dotplot_data = re.search(pattern, dotplot_file,
                                         flags=re.DOTALL).group(1).split('\n')
                # Dimension of the dotplot - compares seq1, seq2 to self and
                # to each other (concatenation of seq1 and seq2 = axis)
                dim = len(strand1) + len(strand2)
                ensemble_probs = np.zeros((dim, dim))
                optimal_probs = np.zeros((dim, dim))

                for point in dotplot_data:
                    point_split = point.split(' ')
                    # Use zero indexing
                    i = int(point_split[0]) - 1
                    j = int(point_split[1]) - 1
                    sqprob = float(point_split[2])
                    probtype = point_split[3]
                    if probtype == 'ubox':
                        ensemble_probs[i][j] = sqprob**2
                    else:
                        optimal_probs[i][j] = sqprob**2
                output['ensemble_matrix'] = ensemble_probs
                output['optimal_matrix'] = optimal_probs

        return output

Response: Run the RNAcofold command and retrieve the result in a dictionary.


Instruction:
Implement a function in Python 3 to
run the RNAfold command and retrieve the result in a dictionary.

Response:
def fold(self, strand, temp=37.0, dangles=2, nolp=False, nogu=False,
             noclosinggu=False, constraints=None, canonicalbponly=False,
             partition=False, pfscale=None, imfeelinglucky=False, gquad=False):
        '''Run the RNAfold command and retrieve the result in a dictionary.

        :param strand: The DNA or RNA sequence on which to run RNAfold.
        :type strand: coral.DNA or coral.RNA
        :param temp: Temperature at which to run the calculations.
        :type temp: float
        :param dangles: How to treat dangling end energies. Set to 0 to ignore
                        dangling ends. Set to 1 to limit unpaired bases to
                        at most one dangling end (default for MFE calc). Set to
                        2 (the default) to remove the limit in 1. Set to 3 to
                        allow coaxial stacking of adjacent helices in
                        .multi-loops
        :type dangles: int
        :param nolp: Produce structures without lonely pairs (isolated single
                     base pairs).
        :type nolp: bool
        :param nogu: Do not allow GU pairs.
        :type nogu: bool
        :param noclosinggu: Do not allow GU pairs at the end of helices.
        :type noclosinggu: bool
        :param constraints: Any structural constraints to use. Format is
                            defined at
                            http://www.tbi.univie.ac.at/RNA/RNAfold.1.html
        :type constraints: str
        :param canonicalbponly: Remove non-canonical base pairs from the
                                structure constraint (if applicable).
        :type canonicalbponly: bool
        :param partition: Generates the partition function, generating a coarse
                          grain structure ('coarse') in the format described at
                          http://www.itc.univie.ac.at/~ivo/RNA/RNAlib/PF-Fold.h
                          tml, the ensemble free energy ('ensemble'), the
                          centroid structure ('centroid'), the free energy of
                          the centroid structure ('centroid_fe'), and its
                          distance from the ensemble ('centroid_d').
        :type partition: int
        :param pfscale: Scaling factor for the partition function.
        :type pfScale: float
        :param imfeelinglucky: Returns the one secondary structure from the
                               Boltzmann equilibrium according to its
                               probability in the ensemble.
        :type imfeelinglucky: bool
        :param gquad: Incorporate G-Quadruplex formation into the structure
                      prediction.
        :type gquad: bool

        :returns: Dictionary of calculated values, defaulting to values of MFE
                  ('mfe': float) and dotbracket structure ('dotbracket': str).
                  More keys are added depending on keyword arguments.
        :rtype: dict

        '''
        cmd_args = []
        cmd_kwargs = {'--temp=': str(temp)}
        cmd_kwargs['--dangles='] = dangles
        if nolp:
            cmd_args.append('--noLP')
        if nogu:
            cmd_args.append('--noGU')
        if noclosinggu:
            cmd_args.append('--noClosingGU')
        if constraints is not None:
            cmd_args.append('--constraint')
            if canonicalbponly:
                cmd_args.append('--canonicalBPonly')
        if partition:
            cmd_args.append('--partfunc')
        if pfscale is not None:
            cmd_kwargs['pfScale'] = float(pfscale)
        if gquad:
            cmd_args.append('--gquad')

        inputs = [str(strand)]
        if constraints is not None:
            inputs.append(constraints)

        if strand.circular:
            cmd_args.append('--circ')
        rnafold_output = self._run('RNAfold', inputs, cmd_args, cmd_kwargs)

        # Process the output
        output = {}
        lines = rnafold_output.splitlines()
        # Line 1 is the sequence as RNA
        lines.pop(0)
        # Line 2 is the dotbracket + mfe
        line2 = lines.pop(0)
        output['dotbracket'] = self._lparse(line2, '^(.*) \(')
        output['mfe'] = float(self._lparse(line2, ' \((.*)\)$'))
        # Optional outputs
        if partition:
            # Line 3 is 'a coarse representation of the pair probabilities' and
            # the ensemble free energy
            line3 = lines.pop(0)
            output['coarse'] = self._lparse(line3, '^(.*) \[')
            output['ensemble'] = float(self._lparse(line3, ' \[(.*)\]$'))
            # Line 4 is the centroid structure, its free energy, and distance
            # to the ensemble
            line4 = lines.pop(0)
            output['centroid'] = self._lparse(line4, '^(.*) \{')
            output['centroid_fe'] = float(self._lparse(line4, '^.*{(.*) d'))
            output['centroid_d'] = float(self._lparse(line4, 'd=(.*)}$'))

        return output


Instruction:
Can you write a function in Python 3 where it
calculates expected fraction of primer dimers.

Response:
def dimers(primer1, primer2, concentrations=[5e-7, 3e-11]):
    '''Calculate expected fraction of primer dimers.

    :param primer1: Forward primer.
    :type primer1: coral.DNA
    :param primer2: Reverse primer.
    :type primer2: coral.DNA
    :param template: DNA template.
    :type template: coral.DNA
    :param concentrations: list of concentrations for primers and the
                           template. Defaults are those for PCR with 1kb
                           template.
    :type concentrations: list
    :returns: Fraction of dimers versus the total amount of primer added.
    :rtype: float

    '''
    # It is not reasonable (yet) to use a long template for doing these
    # computations directly, as NUPACK does an exhaustive calculation and
    # would take too long without a cluster.
    # Instead, this function compares primer-primer binding to
    # primer-complement binding

    # Simulate binding of template vs. primers
    nupack = coral.analysis.NUPACK([primer1.primer(), primer2.primer(),
                                    primer1.primer().reverse_complement(),
                                    primer2.primer().reverse_complement()])
    # Include reverse complement concentration
    primer_concs = [concentrations[0]] * 2
    template_concs = [concentrations[1]] * 2
    concs = primer_concs + template_concs
    nupack_concs = nupack.concentrations(2, conc=concs)
    dimer_conc = nupack_concs['concentrations'][5]
    #primer1_template = nupack_concs['concentrations'][6]
    #primer2_template = nupack_concs['concentrations'][10]
    return dimer_conc / concs[0]


Instruction:
Make a summary of the following Python 3 code
def read_dna(path):
    '''Read DNA from file. Uses BioPython and coerces to coral format.

    :param path: Full path to input file.
    :type path: str
    :returns: DNA sequence.
    :rtype: coral.DNA

    '''
    filename, ext = os.path.splitext(os.path.split(path)[-1])

    genbank_exts = ['.gb', '.ape']
    fasta_exts = ['.fasta', '.fa', '.fsa', '.seq']
    abi_exts = ['.abi', '.ab1']

    if any([ext == extension for extension in genbank_exts]):
        file_format = 'genbank'
    elif any([ext == extension for extension in fasta_exts]):
        file_format = 'fasta'
    elif any([ext == extension for extension in abi_exts]):
        file_format = 'abi'
    else:
        raise ValueError('File format not recognized.')

    seq = SeqIO.read(path, file_format)
    dna = coral.DNA(str(seq.seq))
    if seq.name == '.':
        dna.name = filename
    else:
        dna.name = seq.name

    # Features
    for feature in seq.features:
        try:
            dna.features.append(_seqfeature_to_coral(feature))
        except FeatureNameError:
            pass
    dna.features = sorted(dna.features, key=lambda feature: feature.start)
    # Used to use data_file_division, but it's inconsistent (not always the
    # molecule type)
    dna.circular = False
    with open(path) as f:
        first_line = f.read().split()
        for word in first_line:
            if word == 'circular':
                dna.circular = True

    return dna

Response: Reads a DNA file and returns it as a sequence.


Instruction:
How would you explain what the following Python 3 function does
def read_sequencing(directory):
    '''Read .seq and .abi/.ab1 results files from a dir.

    :param directory: Path to directory containing sequencing files.
    :type directory: str
    :returns: A list of DNA sequences.
    :rtype: coral.DNA list

    '''
    dirfiles = os.listdir(directory)
    seq_exts = ['.seq', '.abi', '.ab1']
    # Exclude files that aren't sequencing results
    seq_paths = [x for x in dirfiles if os.path.splitext(x)[1] in seq_exts]
    paths = [os.path.join(directory, x) for x in seq_paths]
    sequences = [read_dna(x) for x in paths]

    return sequences

Response: Reads. seq and. ab1 results files from a directory.


Instruction:
Implement a function in Python 3 to
write a DNA sequence to a file.

Response:
def write_dna(dna, path):
    '''Write DNA to a file (genbank or fasta).

    :param dna: DNA sequence to write to file
    :type dna: coral.DNA
    :param path: file path to write. Has to be genbank or fasta file.
    :type path: str

    '''
    # Check if path filetype is valid, remember for later
    ext = os.path.splitext(path)[1]
    if ext == '.gb' or ext == '.ape':
        filetype = 'genbank'
    elif ext == '.fa' or ext == '.fasta':
        filetype = 'fasta'
    else:
        raise ValueError('Only genbank or fasta files are supported.')

    # Convert features to Biopython form
    # Information lost on conversion:
    #     specificity of feature type
    #     strandedness
    #     topology
    features = []
    for feature in dna.features:
        features.append(_coral_to_seqfeature(feature))
    # Biopython doesn't like 'None' here
    # FIXME: this is a legacy feature - remove?
    bio_id = dna.id if hasattr(dna, 'id') else ''
    # Maximum length of name is 16
    seq = SeqRecord(Seq(str(dna), alphabet=ambiguous_dna), id=bio_id,
                    name=dna.name[0:16].replace(' ', '_'), features=features,
                    description=dna.name)
    if dna.circular:
        seq.annotations['data_file_division'] = 'circular'
    else:
        seq.annotations['data_file_division'] = 'linear'

    if filetype == 'genbank':
        SeqIO.write(seq, path, 'genbank')
    elif filetype == 'fasta':
        SeqIO.write(seq, path, 'fasta')


Instruction:
Implement a function in Python 3 to
write a list of primers out to a csv file.

Response:
def write_primers(primer_list, path, names=None, notes=None):
    '''Write a list of primers out to a csv file. The first three columns are
    compatible with the current IDT order form (name, sequence, notes). By
    default there are no notes, which is an optional parameter.

    :param primer_list: A list of primers.
    :type primer_list: coral.Primer list
    :param path: A path to the csv you want to write.
    :type path: str
    :param names: A list of strings to name each oligo. Must be the same length
                  as the primer_list.
    :type names: str list
    :param notes: A list of strings to provide a note for each oligo. Must be
                  the same length as the primer_list.
    :type notes: str list

    '''
    # Check for notes and names having the right length, apply them to primers
    if names is not None:
        if len(names) != len(primer_list):
            names_msg = 'Mismatch in number of notes and primers.'
            raise PrimerAnnotationError(names_msg)
        for i, name in enumerate(names):
            primer_list[i].name = name
    if notes is not None:
        if len(notes) != len(primer_list):
            notes_msg = 'Mismatch in number of notes and primers.'
            raise PrimerAnnotationError(notes_msg)
        for i, note in enumerate(notes):
            primer_list[i].note = note

    # Write to csv
    with open(path, 'w') as csv_file:
        writer = csv.writer(csv_file)
        writer.writerow(['name', 'sequence', 'notes'])
        for primer in primer_list:
            string_rep = str(primer.overhang).lower() + str(primer.anneal)
            writer.writerow([primer.name, string_rep, primer.note])


Instruction:
Write a Python 3 script to
translate genbank feature types into usable ones.

Response:
def _process_feature_type(feature_type, bio_to_coral=True):
    '''Translate genbank feature types into usable ones (currently identical).
    The feature table is derived from the official genbank spec (gbrel.txt)
    available at http://www.insdc.org/documents/feature-table

    :param feature_type: feature to convert
    :type feature_type: str
    :param bio_to_coral: from coral to Biopython (True) or the other direction
                   (False)
    :param bio_to_coral: bool
    :returns: coral version of genbank feature_type, or vice-versa.
    :rtype: str

    '''

    err_msg = 'Unrecognized feature type: {}'.format(feature_type)
    if bio_to_coral:
        try:
            name = coral.constants.genbank.TO_CORAL[feature_type]
        except KeyError:
            raise ValueError(err_msg)
    else:
        try:
            name = coral.constants.genbank.TO_BIO[feature_type]
        except KeyError:
            raise ValueError(err_msg)
    return name


Instruction:
Create a Python 3 function to
convert a Biopython SeqFeature to a coral. Feature.

Response:
def _seqfeature_to_coral(feature):
    '''Convert a Biopython SeqFeature to a coral.Feature.

    :param feature: Biopython SeqFeature
    :type feature: Bio.SeqFeature

    '''
    # Some genomic sequences don't have a label attribute
    # TODO: handle genomic cases differently than others. Some features lack
    # a label but should still be incorporated somehow.
    qualifiers = feature.qualifiers
    if 'label' in qualifiers:
        feature_name = qualifiers['label'][0]
    elif 'locus_tag' in qualifiers:
        feature_name = qualifiers['locus_tag'][0]
    else:
        raise FeatureNameError('Unrecognized feature name')
    # Features with gaps are special, require looking at subfeatures
    # Assumption: subfeatures are never more than one level deep
    if feature.location_operator == 'join':
        # Feature has gaps. Have to figure out start/stop from subfeatures,
        # calculate gap indices. A nested feature model may be required
        # eventually.
        # Reorder the sub_feature list by start location
        # Assumption: none of the subfeatures overlap so the last entry in
        # the reordered list also has the final stop point of the feature.
        # FIXME: Getting a deprecation warning about using sub_features
        # instead of feature.location being a CompoundFeatureLocation
        reordered = sorted(feature.location.parts,
                           key=lambda location: location.start)
        starts = [int(location.start) for location in reordered]
        stops = [int(location.end) for location in reordered]
        feature_start = starts.pop(0)
        feature_stop = stops.pop(-1)
        starts = [start - feature_start for start in starts]
        stops = [stop - feature_start for stop in stops]
        feature_gaps = list(zip(stops, starts))
    else:
        # Feature doesn't have gaps. Ignore subfeatures.
        feature_start = int(feature.location.start)
        feature_stop = int(feature.location.end)
        feature_gaps = []
    feature_type = _process_feature_type(feature.type)
    if feature.location.strand == -1:
        feature_strand = 1
    else:
        feature_strand = 0
    if 'gene' in qualifiers:
        gene = qualifiers['gene']
    else:
        gene = []
    if 'locus_tag' in qualifiers:
        locus_tag = qualifiers['locus_tag']
    else:
        locus_tag = []
    coral_feature = coral.Feature(feature_name, feature_start,
                                  feature_stop, feature_type,
                                  gene=gene, locus_tag=locus_tag,
                                  qualifiers=qualifiers,
                                  strand=feature_strand,
                                  gaps=feature_gaps)
    return coral_feature