Example #1
0
def validateCoherence(arySegments):
    # Collapse all segments into a single list and measure coherence
    aryVectors = [ i for f, ary in arySegments for i in ary ]
    aryCoherence = [ 0 for i in xrange(len(aryVectors)) ]
    for i in xrange(2, len(aryVectors)):
        if Codons.isCoherent([ aryVectors[i-2], aryVectors[i-1], aryVectors[i-0] ]):
            aryCoherence[i-2] += 1
            aryCoherence[i-1] += 1
            aryCoherence[i-0] += 1
            
    # Divide measured coherence into lists matching the original segments
    for i in xrange(len(arySegments)):
        aryCoherence[i:i] = [ aryCoherence[i:i+len(arySegments[i][1]) ] ]
        aryCoherence[i+1:i+1+len(arySegments[i][1])] = []

    # Check the expected coherence of each segment against that measured
    for i in xrange(len(arySegments)):
        fCoherent, aryVectors = arySegments[i]
        if (fCoherent and aryCoherence[i].count(0)) or (not fCoherent and (aryCoherence[i].count(0) != len(aryCoherence[i]))):
            if i > 0:
                fC, aryV = arySegments[i-1]
                Common.sayError('Coherent(%c) %d - %s' % (fC and 'T' or 'F', len(aryV), ' '.join([ Codons.Vectors.toName(id) for id in aryV ])))
            Common.sayError('Coherent(%c) %d - %s' % (fCoherent and 'T' or 'F', len(aryVectors), ' '.join([ Codons.Vectors.toName(id) for id in aryVectors ])))
            Common.sayError('                - %s' % ' '.join([ ' %d ' % j for j in aryCoherence[i] ]))
            if i < len(arySegments)-1:
                fC, aryV = arySegments[i+1]
                Common.sayError('Coherent(%c) %d - %s' % (fC and 'T' or 'F', len(aryV), ' '.join([ Codons.Vectors.toName(id) for id in aryV ])))
            raise Common.BiologicError('Failed to create a gene with proper coherence - segment %d should be %s but has %s vectors' % (i+1,
                                                                                                                                fCoherent and 'Coherent' or 'Incoherent',
                                                                                                                                fCoherent and 'Incoherent' or 'Coherent'))
Example #2
0
def buildGenes(uchHan, aryGenes):
    Common.say('Creating %d gene(s)' % len(aryGenes))
    
    han = loadHan(uchHan)
    
    strAuthor = Globals.strAuthor and (" author='%s'" % Globals.strAuthor) or ''

    aryGeneNames = []
    for specification in aryGenes:
        Common.say('Creating gene from specification ' + specification)

        gs = GeneSpecification(specification != Constants.strDefault and specification or '', han)
        gsName = gs.toName(han.unicode) + Common.Constants.extGene
        gsPoints = gs.getPoints()
        Common.say('Gene to be named ' + gsName)

        ptCurrent = Genome.Point(pt=gsPoints[0][1][0])
        arySegments = []

        # Convert each set of points into a list of vectors
        for iSegment in xrange(len(gsPoints)):
            fCoherent, aryPoints = gsPoints[iSegment]
            
            # Build the segment starting from the current location
            # - Ensure incoherent segments always begin at the current location
            #   (This causes moves to absorb the tracing error, effectively trading placement error for stroke fit error.)
            if not fCoherent:
                aryPoints[0].x = ptCurrent.x
                aryPoints[0].y = ptCurrent.y
            ptCurrent, aryVectors = buildSegment(ptCurrent, fCoherent, aryPoints)
            
            if not fCoherent:
                # If the segment contains too few vectors, pad it with an incoherent sequence
                # - If there are no vectors, use No/So/Ea/We - binding code will ensure proper coherence at the endpoints
                # - Otherwise, use the four points of the direction "compass" that are guaranteed incoherent with the last vector
                if len(aryVectors) < 3:
                    iDirection = len(aryVectors) and Codons.Directions.add(Codons.Vectors.toDirection(aryVectors[-1]), 3) or Codons.Directions.North
                    aryVectors.append(Codons.Vectors.create(iDirection))
                    aryVectors.append(Codons.Vectors.create(Codons.Directions.toOpposite(iDirection)))
                    
                    iDirection = Codons.Directions.add(iDirection, 2)
                    aryVectors.append(Codons.Vectors.create(iDirection))
                    aryVectors.append(Codons.Vectors.create(Codons.Directions.toOpposite(iDirection)))
                    
                # Inject vectors to force incoherency for incoherent segments
                # - Essentially, add a vector pair to every two that forces incoherency
                # - Walking the list must take into account injected vector pairs
                else:
                    iVector = 0
                    while iVector < len(aryVectors):
                        if Codons.isCoherent([aryVectors[iVector-2], aryVectors[iVector-1], aryVectors[iVector+0]]):
                            idVector = aryVectors[iVector]
                            aryVectors.insert(iVector+0, Codons.Vectors.toOpposite(idVector))
                            aryVectors.insert(iVector+1, idVector)
                        iVector += 1

            # Ensure the vectors "bind" without affecting the coherence of an adjoining segment
            if iSegment:
                fCoherencePrev, aryVectorsPrev = arySegments[-1]
                if Codons.isCoherent([ aryVectorsPrev[-2], aryVectorsPrev[-1], aryVectors[0] ]) or Codons.isCoherent([ aryVectorsPrev[-1], aryVectors[0], aryVectors[1] ]):
                    if not fCoherencePrev:
                        aryVectorsPrev += [ Codons.Vectors.toOpposite(aryVectorsPrev[-1]), aryVectorsPrev[-1], aryVectors[0], Codons.Vectors.toOpposite(aryVectors[0]) ]
                    else:
                        aryVectors[:0] = [ Codons.Vectors.toOpposite(aryVectorsPrev[-1]), aryVectorsPrev[-1], aryVectors[0], Codons.Vectors.toOpposite(aryVectors[0]) ]

            arySegments.append((fCoherent, aryVectors))

        validateCoherence(arySegments)

        aryCodons = [ Codons.Vectors.toVector(idVector).codon for fCoherent, aryVectors in arySegments for idVector in aryVectors ]
        aryCodons[:0] = [ 'ATG' ]
        aryCodons.append(Codons.Vectors.toVector(Codons.Vectors.create(Codons.Directions.Stop, Codons.Constants.iVectorShort)).codon)

        aryStrokes = []
        iStroke = 0
        iBase = 4
        for fCoherent, aryVectors in arySegments:
            if fCoherent:
                aryStrokes.append(_GENE_STROKE % (iBase, iBase+(len(aryVectors)*3-1), gs.mapStrokeToHan(iStroke)+1))
                iStroke += 1
            iBase += len(aryVectors) * 3

        strGene = _GENE_DEFINITION % (str(uuid.uuid4()).upper(), strAuthor, datetime.datetime.utcnow().isoformat(), _NAME, str(gs),
                                    ''.join(aryCodons), len(aryCodons)*3,
                                    gsPoints[0][1][0].x, gsPoints[0][1][0].y,
                                    han.unicode,
                                    '\n'.join(aryStrokes))

        strPath = Common.resolvePath(os.path.join(Globals.strGenePath, Common.makeHanPath(gsName)))
        strDir = os.path.dirname(strPath)
        if not os.path.exists(strDir):
            try: os.makedirs(os.path.dirname(strPath))
            except OSError, err: raise Common.BiologicError('Unable to create %s - %s' % (strDir, str(err)))
        
        try:
            fileGene = os.open(strPath, os.O_CREAT | os.O_TRUNC | os.O_WRONLY, 0664)
            os.write(fileGene, strGene)
        except IOError, err: raise Common.BiologicError('Unable to create %s - %s' % (strPath, str(err)))
        os.close(fileGene)
        
        Common.say('\tWrote %s - %d codons, %d bases' % (strPath, len(aryCodons), len(aryCodons)*3))
        aryGeneNames.append(gsName)

    return aryGeneNames