2012-04-23 9 views
6

Sto cercando di creare un buon algoritmo per creare una rappresentazione di una stringa di DNA right handed con solchi maggiore e minore utilizzando il carattere di trattino, per un numero arbitrario di caratteri.Algoritmo di generazione di doppia elica

Questo è quello che ho attualmente, utilizzando 776 # 's:

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

ma l'elica non si allinea perfettamente quando provo manualmente per ripetere l'elica tramite copia/incolla.

Una soluzione che ha la stessa larghezza dell'esempio precedente ma ha anche le basi incrociate (come in this image o nel modello di sciarpa di seguito), è anche accettabile.

scarf pattern

+4

Perché non pubblicare il codice che avete scritto finora? Potrebbe incoraggiare le persone a rispondere. – user1202136

+0

L'esempio precedente è stato creato manualmente. Ma il tweaking è stato laborioso e errorprone, ecco perché ho pensato che ci fosse un modo migliore, più algoritmico per farlo. – BioGeek

risposta

6

La chiave per questa domanda è riconoscere che è possibile rappresentare ciascun filo sull'elica come una combinazione di onde sinusoidali - una per la porzione periodica e una per la "profondità" nella pagina. Una volta parametrizzato il problema in questo modo, puoi controllare ogni aspetto della tua spirale. L'esempio seguente utilizza * e # per mostrare i diversi fili per illustrare il punto. Se scegli i valori per la lunghezza d'onda che non corrispondono ai valori interi otterrai meno risultati ottimali, ma ora puoi giocare con gli input per trovare quella che consideri la rappresentazione più esteticamente gradevole.

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) 

Questi valori danno:

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

Sulla riga 19, non è chiaro quale filo è di fronte al quale. Ognuno appare in parte dietro l'altro. – recursive

+1

@recursive Agreed, ha aggiunto un semplice offset sull'ordine z che lo risolve. Avevano bisogno di avere lo zorder delle loro rispettive fasi spostato di mezzo lunghezza d'onda. Grazie! – Hooked

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

. . .

Purtroppo volevo che fosse la somma totale della mia risposta. Ma dovrei spiegare: quando si eseguono modifiche alle tesselazioni, è necessario lavorare con l'unità di ripetizione di base (e se si modifica il modo in cui è tesselato, è necessario modificarne altre parti, ma non lo si sta facendo). Ho tagliato il tuo disegno in quello che pensavo fosse un'unità ripetitiva, poi l'ho incollato una volta; quando ho apportato una modifica al fondo, ho apportato la stessa modifica alla parte superiore.

< profondi pensieri > A volte le soluzioni più semplici si trovano senza troppo pensare. </deep thoughts >

Tuttavia, è possibile eseguire un algoritmo di posterizzazione su un'immagine del DNA trasformandola in una bitmap. (Puoi farlo a un'immagine di cui hai il copyright.) Se non sei obbligato ad usare lo stesso personaggio, potresti anche usare un generatore di ASCII art, di cui puoi trovare dozzine sul web e in software open source tramite alcune ricerche su Google. Tuttavia, questo non è nel campo di applicazione delle Domande frequenti di StackOverflow, quindi non collegherò questo documento informatico alla conversione in stile vettoriale ascii-art: http://www.cse.cuhk.edu.hk/~ttwong/papers/asciiart/asciiart.pdf

+1

Questo è sicuramente il modo più semplice se non è necessario che venga creato algoritmicamente. –

2

Questo dovrebbe dare un discreto inizio:

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() 

come indicato, 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 e O sono solo per dimostrare che si tratta, in effetti, una spirale destrorsa).

2

Che ne dite di questo:

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) 

non fa uso di un numero specifico di hash per l'uscita, però. Forse questo era uno dei tuoi requisiti, non lo so ...

Dovrebbe produrre un modello ripetitivo finché il valore step è una frazione intera di math.pi.

2

Ecco il mio approccio. Probabilmente non è materialmente diverso da quello di chiunque altro, ma l'ho scritto, quindi eccola:

La metà superiore è la configurazione. La metà inferiore è azione.

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)) 

uscita:

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

Attenzione, questa è una spirale SINISTRA ... –

+0

Grazie per la correzione. Ho invertito la rotazione nel codice. – recursive

Problemi correlati