2012-04-23 6 views
6

Estoy tratando de encontrar un buen algoritmo para crear una representación de una cadena de ADN right handed con surcos mayores y menores utilizando el carácter de guión, para un número arbitrario de caracteres.Algoritmo de generación de doble hélice

Esto es lo que tengo actualmente, utilizando 776 # 's:

#########     ########## 
    #########    ########## 
     #########    ########## 
     #########   ########## 
      ##########  ########## 
      ########## ########## 
       ###### ########## 
       ## ########## 
       ########## # 
       ########## ##### 
      ########## ######### 
      ########## ########## 
     ##########  ########## 
     ##########   ########## 
    ##########    ########## 
    ##########    ########## 
    ##########    ########## 
    ##########    ########## 
    ##########   ########## 
    ##########  ########## 
    ########### ########## 
     ######### ########## 
     ##### ########## 
      # ########## 
      ########## ### 
     ########## ####### 
     ########## ########## 
    ##########  ########## 
    ##########   ########## 
    ##########    ########## 
    ##########    ########## 
    ##########     ########## 
    ##########     ########## 
    ##########    ########## 
     ##########    ########## 
     ##########   ########## 
      ##########  ########## 
      ########## ########## 
       ####### ########## 
       #### ######### 
        ######### # 
        ########## ### 
       ########### ####### 

pero la hélice no se alinea perfectamente cuando intento manualmente para repetir la hélice a través de copiar/pegar.

Una solución que tiene el mismo ancho que el ejemplo anterior pero también tiene los pares cruzados de pares de bases (como en this image o en el patrón de bufanda a continuación), también es aceptable.

scarf pattern

+4

¿Por qué no se contabiliza el código que ha escrito hasta ahora? Puede alentar a las personas a responder. – user1202136

+0

El ejemplo anterior se realizó manualmente. Pero el ajuste fue laborioso y erróneo, así que es por eso que pensé que tenía que haber una forma mejor y más algorítmica de hacerlo. – BioGeek

Respuesta

6

La clave de esta pregunta es reconocer que puede representar cada filamento en la hélice como una combinación de ondas sinusoidales, una para la parte periódica y otra para la "profundidad" en la página. Una vez que haya parametrizado el problema de esta manera, puede controlar todos los aspectos de su hélice. El siguiente ejemplo usa * y # para mostrar los diferentes hilos para ilustrar el punto. Si eliges valores para la longitud de onda que no corresponden a valores enteros obtendrás menos resultados que óptimos, pero ahora puedes jugar con las entradas para encontrar lo que consideras la representación más estéticamente agradable.

from numpy import * 

amp = 10 
length = 100 
wavelength = 20 

omega = (2*pi)/wavelength 
phi = wavelength*(0.5) 
X = arange(1,length) 
Y1 = round_(amp*(sin(omega*X) + 1)) 
Y2 = round_(amp*(sin(omega*X+phi) + 1)) 

offset = phi/2 
Z1 = sin(omega*X + offset) 
Z2 = sin(omega*X + phi + offset) 

T1 = " ######### " 
T2 = " ********* " 
clen = len(T1) 

H = zeros((length,amp*2+clen),dtype='str') 
H[:,:] = " " 

for n,(y1,y2,z1,z2) in enumerate(zip(Y1,Y2,Z1,Z2)): 
    H[n,y1:y1+clen] = list(T1) 
    H[n,y2:y2+clen] = list(T2) 

    # Overwrite if first helix is on top 
    if z1>z2: H[n,y1:y1+clen] = list(T1) 

for line in H: 
    print "".join(line) 

Estos valores dan:

********* #########   
    *********  #########  
*********   ######### 
*********   ######### 
    *********   ######### 
    *********  ######### 
     ********* ######### 
      ****** #########  
       #########   
      ######### ****  
     ######### ********* 
    #########  ********* 
    #########   ********* 
#########   ********* 
#########   ********* 
#########  *********  
    ######### *********  
    ###### *********   
     *********    
     ********* ####   
    ********* #########   
    *********  #########  
*********   ######### 
*********   ######### 
    *********   ######### 
    *********  ######### 
     ********* ######### 
      ****** #########  
       #########   
+1

En la línea 19, no está claro qué filamento está delante de cuál. Cada uno aparece parcialmente detrás del otro. – recursive

+1

@recursive De acuerdo, agregó una compensación simple en el orden z que corrige esto. Necesitaban tener el zorder de sus respectivas fases desplazado por media longitud de onda. ¡Gracias! – Hooked

1
    ########## #### 
       ########## ######## 
      ########## ########### 
      ##########  ########## 
     ##########   ########## 
     ##########   ######### 
    ##########    ######### 
    ##########    ########## 
    ##########    ########## 
    ##########    ########## 
    ##########   ########## 
    ##########  ########## 
    ########### ########## 
     ######### ########## 
     ##### ########## 
      # ########## 
      ########## ### 
     ########## ####### 
     ########## ########## 
    ##########  ########## 
    ##########   ########## 
    ##########    ########## 
    ##########    ########## 
    ##########     ########## 
    ##########     ########## 
    ##########    ########## 
     ##########    ########## 
     ##########   ########## 
      ##########  ########## 
      ########## ########## 
       ####### ########## 
       #### ######### 
        ######### # 

. . .

Tristemente, quería que esa fuera la suma total de mi respuesta. Pero debería explicarlo: cuando realiza cambios en las teselaciones, necesita trabajar con la unidad repetitiva básica (y si modifica la forma en que se testala, debe modificar otras partes, pero no lo está haciendo). Corté tu patrón en lo que pensé que parecía una unidad repetitiva, luego copié y pegué una vez; cuando hice un cambio en la parte inferior, hice el mismo cambio en la parte superior.

< pensamientos profundos > A veces las soluciones más simples se encuentran sin pensar demasiado. </pensamientos profundos >

Sin embargo, definitivamente podría realizar un algoritmo de posterización en una imagen de ADN, convirtiéndolo en un mapa de bits. (Puede hacer esto en una imagen de la que tenga el copyright). Si no está obligado a utilizar el mismo personaje, también puede utilizar un generador de arte de arte, del que puede encontrar docenas en la web y en software de código abierto. a través de una búsqueda en Google. Sin embargo, esto no está dentro del alcance de las preguntas frecuentes de StackOverflow, así que no voy a entrar en detalles al respecto, excepto para vincular este documento científico sobre conversión de ascii-art de estilo vectorial: http://www.cse.cuhk.edu.hk/~ttwong/papers/asciiart/asciiart.pdf

+1

Esta es, sin duda, la forma más sencilla si no se requiere que se cree algorítmicamente. –

2

Esto debería dar es usted un buen comienzo:

from math import sin, cos, pi 

class RightHelix(object): 
    def __init__(self, maxima, minima, period, offset): 
     self.mid = 0.5 * (maxima + minima) 
     self.mag = 0.5 * (maxima - minima) 
     self.k = 2.0 * pi/period 
     self.offs = self.k * offset 
    def x(self, t): 
     return self.mid + self.mag * sin(self.k*t - self.offs) 
    def y(self, t): 
     return -self.mag * cos(self.k*t - self.offs) 

def main(): 
    rh = RightHelix(33, 7, 20, -2) 

    for t in range(40): 
     x,y = rh.x(t), rh.y(t) 
     print(' '*int(x-0.5) + ('O','X')[y>0]) 

if __name__=="__main__": 
    main() 

como se da, produce

      O 
           O 
           O 
           O 
           X 
           X 
          X 
         X 
        X 
       X 
      X 
     X 
     X 
     X 
     O 
     O 
      O 
       O 
        O 
         O 
          O 
           O 
           O 
           O 
           X 
           X 
          X 
         X 
        X 
       X 
      X 
     X 
     X 
     X 
     O 
     O 
      O 
       O 
        O 
         O 

(la X y O son sólo para mostrar que es, de hecho, una espiral a la derecha).

2

¿Qué tal este:

import math 

phaseA = math.pi/1.5 
phaseB = 0 
step = math.pi/20 
width = 30 # screen size 
breadth = 8 # breadth of DNA single string 

x = 0.0 
while True: 
    x += step 
    if x > 30.0: break 
    yA = math.sin(x + phaseA) 
    zA = math.cos(x + phaseA) 
    yB = math.sin(x + phaseB) 
    zB = math.cos(x + phaseB) 
    if zA > zB: # which is in front? 
    yTop, yBottom = yA, yB 
    else: 
    yTop, yBottom = yB, yA 
    # screenify values: 
    yTop = 1 + int((1.0 + yTop) /2.0 * (width-breadth)) 
    yBottom = 1 + int((1.0 + yBottom)/2.0 * (width-breadth)) 
    line = ' ' * yBottom + '#' * breadth + ' ' * (width-yBottom) 
    line = list(line) # make mutable 
    line[yTop-1] = ' ' 
    line[yTop+breadth+1] = ' ' 
    for i in range(breadth): 
    line[yTop+i] = '#' 
    print ''.join(line) 

que no utiliza un número determinado de valores hash para la salida, sin embargo. Tal vez este era uno de sus requisitos, no sé ...

Debe producir un patrón repetitivo siempre que el valor step sea una fracción de math.pi.

2

Aquí está mi enfoque. Probablemente no sea sustancialmente diferente a los demás, pero lo escribí, así que aquí va:

La mitad superior es la configuración. La mitad inferior es acción.

from math import cos, sin, pi 

length = 50 
width = 30 
thickness = 10 
rotation = 0.15 
strands = [0, 2 * pi/3] 
strand_char = "#" 

radius = width/2 
for line in range(length): 
    output = [" "] * (width + thickness + 2) 
    total_rotation = -line * rotation 
    sorted_strands = sorted(strands, key=lambda s: cos(total_rotation + s)) 
    for strand_offset in sorted_strands: 
     pos = int(radius * sin(total_rotation + strand_offset) + radius) 
     output[pos : pos + thickness + 2] = " " + strand_char * thickness + " " 
    print("".join(output)) 

Salida:

   ########## ##########  
      ##########  ########## 
      ##########   ########## 
     ##########   ########## 
     ##########    ########## 
    ##########    ########## 
    ##########    ########## 
    ##########    ##########  
    ##########    ##########  
##########    ##########  
##########    ##########   
##########   ##########   
##########   ##########    
    ##########  ##########    
    ########## ##########     
    ######## ##########     
    ##### ##########      
     # ##########      
     ########## #      
    ########## #####      
    ########## ########     
    ########## ##########     
##########  ##########    
##########   ##########    
##########   ##########   
##########    ##########   
##########    ##########  
    ##########    ##########  
    ##########    ########## 
    ##########    ########## 
    ##########    ########## 
     ##########    ########## 
     ##########   ########## 
      ##########   ########## 
      ##########  ########## 
       ########## ##########  
        ######## ##########  
        ##### ##########  
         # ##########   
         ########## #   
        ########## #####  
       ########## #########  
       ########## ########## 
      ##########  ########## 
      ##########   ########## 
     ##########   ########## 
     ##########    ########## 
    ##########    ########## 
    ##########    ########## 
    ##########    ##########  
+1

Tenga en cuenta, esta es una espiral con la mano IZQUIERDA ... –

+0

Gracias por la corrección. He invertido la rotación en el código. – recursive

Cuestiones relacionadas