Алгоритм генерации двойной спирали

Я пытаюсь создать хороший алгоритм, чтобы создать представление правой строки ДНК с основными и второстепенными канавками, используя символ тире, для произвольного количества символов.

Это то, что я сейчас имею, используя 776 # :

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

но спираль не идеально выравнивается, когда я вручную пытаюсь повторить спираль посредством копирования / вставки.

Также приемлемо решение, имеющее такую ​​же ширину, что и пример выше, но также имеет крестообразные пары базового пара (как на этом изображении или в схеме шарфа ниже).

рисунок шарфа

Ключом к этому вопросу является признание того, что вы можете представлять каждую цепочку на спирали как комбинацию синусоидальных волн – одну для периодической части и одну для «глубины» на странице. Как только вы параметризировали проблему таким образом, вы можете контролировать каждый аспект вашей спирали. В приведенном ниже примере используются * и # чтобы показать разные нити, чтобы проиллюстрировать эту точку. Если вы выберете значения длины волны, которые не соизмеримы с целыми значениями, вы получите меньше оптимальных результатов – но теперь вы можете играть со входами, чтобы найти то, что вы считаете самым эстетически приятным представлением.

 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) 

Эти значения дают:

  ********* ######### ********* ######### ********* ######### ********* ######### ********* ######### ********* ######### ********* ######### ****** ######### ######### ######### **** ######### ********* ######### ********* ######### ********* ######### ********* ######### ********* ######### ********* ######### ********* ###### ********* ********* ********* #### ********* ######### ********* ######### ********* ######### ********* ######### ********* ######### ********* ######### ********* ######### ****** ######### ######### 

Это должно дать вам достойный старт:

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

как указано, производит

  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 

(Xs и Os просто показывают, что это действительно правая спираль).

Как насчет этого:

 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) 

Однако он не использует определенное количество хэшей для вывода. Возможно, это был один из ваших требований, не знаю …

Он должен создавать повторяющийся шаблон, если значение step представляет собой целую math.pi в math.pi

Вот мой подход. Это, вероятно, не существенно отличается от чьего-либо, но я написал его, так что вот оно:

Верхняя половина – это конфигурация. Нижняя половина – это действие.

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

Вывод:

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

, , ,

К сожалению, я хотел, чтобы это было итогом моего ответа. Но я должен объяснить: когда вы выполняете изменения в тесселяции, вам нужно работать с базовым повторяющимся блоком (и если вы измените способ его тесселяции, вам придется изменить другие его части, но вы этого не делаете). Я порезал свой узор в то, что, как я думал, выглядел как повторяющийся блок, а затем скопировал его один раз; когда я сделал изменения на дно, я сделал то же самое изменение в верхней части.

<глубокие мысли> Иногда самые простые решения можно найти без особого размышления. </ deep thoughts>

Тем не менее, вы можете определенно выполнить алгоритм постеризации на изображении ДНК, превратив его в растровое изображение. (Вы можете сделать это с изображением, на которое у вас есть авторские права.) Если вы не можете использовать один и тот же символ, вы также можете использовать генератор ascii art, из которого вы можете найти десятки в Интернете и в программном обеспечении с открытым исходным кодом через некоторые поисковые запросы Google. Это, однако, не входит в сферу часто задаваемых вопросов StackOverflow, поэтому я не буду подробно останавливаться на этом, кроме ссылки на эту статью по информатике об векторном стиле ascii-art: http: //www.cse.cuhk .edu.hk / ~ ttwong / документы / AsciiArt / asciiart.pdf