Программа-конвертор EMBL - PDB (filename.dne - filename.ent)

Евгений Неделько объясняет Кушелеву, как работает программа dne2ent.exe

Синим цветом отмечены слова Кушелева. Красным - Евгения Неделько. Черным - текст программы

001 program dne2ent;

-Ну, program dne2ent – это понятно, это – имя программы.

002 uses

003 SysUtils,

А что такое SysUtils?

-SysUtils – это системный модуль. В DELFI есть два модуля. Первый – это SysUtils. Второй называется Syste. Его подключать не надо. Процедура Uses занимается подключением дополнительных модулей, из которых собирается программа.

Каждый модуль может содержать набор процедур (подпрограмм), классов, объектов.

SysUtils подключается по умолчанию, но явное упоминание не помешает, тем более, что у меня определена такая штука, как эксепшн (исключение). Многие важные вещи, которые используются в DELFI описаны именно в SysUtils.

004 Unit1 in 'Unit1.pas',

-Прекрасно, а вот эта следующая строчка unit in ‘Unit1.pas’

-Это вызов модуля Unit1. Сейчас я нажму Ctrl+Enter и щелкну по Unit1, и этот модуль сейчас откроется. В этом модуле, собственно вся эта программа и размещается.

-Понятно, тогда мы можем вернуться назад?

-Можем.

005 imports in 'imports.pas';

-А что это такое, Imports?

-Imports – это тоже модуль, который я подключаю. Здесь я указываю, какие модули я подключаю. Если указано имя файла, то это как правило мой модуль, если не указано, то это – системный модуль.

-А если бы Unit1 был бы системным модулем, то вместо Unit1 in ‘Unit1.pas’ было бы написано просто Unit1 ?

-Совершенно верно.

Я тебе сейчас покажу. Здесь есть такая штука, как вью проджект менеджер. Он как раз показывает вот эту структуру. То, что в этом файле (dnt) находится. Он показывает, что используется этот файл и этот. Т.е. это – два модуля, которые я сам написал и подключаю.

-А все остальные – стандартные?

-Да. В дальнейшем я этот Imports использую без указания, где он находится, потому, что здесь он уже установлен.

006 {$R *.RES}

007 begin

-Бегин – это понятно, это – начало.

008 Try

А Трай?

-Трай это делается следующая штука. Запускается все, что находится после Трая, и тут две конструкции. Первая – не такая, как сейчас написана, а . . .

Когда он выполняет то, что здесь написано, то даже, если выскочит ошибка, выполняет вот здесь. Олвэйз(always)

А здесь наоборот. Этот кусок выполняется только в том случае, если произошла какая-нибудь ошибка.

Try – переводится как “попытаться сделать что-то”, а в случае

009 main;

010 except

исключения (exept – исключение) выводится сообщение.

011 on E: Exception do

012 begin

013 writeln(Format('Exception %s with message "%s" was raised at %p',[E.ClassName, E.Message, ExceptAddr]))

-А райт л.н. – что значит л.н.?

-С л.н. означает, что с переводом строки.

Это – консульная программа. Она по другому устроена. Не так, как обычно.

В этом случае ввод-вывод похож на работу с обычным Паскалем (досовским).

-А Exeption %s – это что означает?

-Видишь, это процедура “Формат”. Тыкаем мышкой на нее, нажимаем F1 и получаем подсказку (по-английски естественно). Программисты должны знать английский язык.

%s – означает строка символов.

-А процент (%)

% - это ключевое слово.

Я хочу, чтобы было написано: “Ислючение с таким-то названием (%s) с сообщением таким-то (“%s”) произошло по адресу (%p). В квадратных скобках определяются новые переменные.

Здесь единственное место после begin, когда можно определять новые переменные.

014 end;

015 end;

016 end.

Далее рассмотрим модуль Imports

001 unit imports;

002 interface

Интерфейс - это все, что доступно снаружи.

Имплементэйшн - описание, как это работает

В этой части модуля нет описания алгоритма. Здесь описано, какие процедуры надо сделать доступными снаружи. Это могут быть классы

Здесь, например, описан класс (Class)

Я нажимаю Ctrl+стелочка вверх или Ctrl+стрелочка вниз для переключения между описаниями в интерфейсе и имплиментэйшн

Это мэйн-процедура, о работе которой я расскажу отдельно

Я тебе расскажу о типах, используемых в языке Паскаль.

-Это я сам прочитаю. Ты мне объясни, что делает эта строчка.

Возвращаясь ко второй строке программы хотелось бы понять, что делает строка interface?

interface - implementation работают аналогично begin - end

-А что такое uses? (строка номер 3)

-Юзес - это использование какого-либо модуля. И в интерфейсе и в имплиментэйшн могут использоваться какие-то модули. Здесь мы видим использование модуля SysUtils (строка 4)

003 uses

004 SysUtils;

005 type

-А тайп - это описание типов?

-Да.

006 {fgBasicTypes}

007 Float = Single;

-Почему ты написал Флоат = Сингл?

-Потому, что в Паскале нет типа Флоат, а я здесь использую процедуры, которые давным-давно написал в другой системе, где этот тип был, а менять текст не хочется...

008 TVertex = record

Рекорд - это запись. В отличие от массива это структура из элементов, различающихся типом и именем. TVertex - это структура из трех элементов (x,y,z). Как я работаю с этой структурой:

****************************

009 x,y,z: Float;

010 end;

011 { TStrings class }

012 TStrings = class

Теперь о классах. Структура напоминает некий бумажный бланк, в котором есть поля (в данном случае это поименованные области памяти), которые можно заполнить.

Если массив чем-то напоминает бумагу в клеточку (таблицу), то СТРУКТУРА больше похожа на дерево. А класс - это та же структура, только более сложная. В ней кроме значений могут быть методы. Принципы, как работать с элементами этой структуры. Логика немного другая. Это некий объект, у которого есть какие-то свойства, например, цвет, размер... и законы взаимодействия.

На этом уровне абстракции создается класс TStrings. Это массив строк, у которого есть какие-то

013 private

private, т.е. внутренние параметры, которые никому снаружи недоступны, есть малодоступные методы, связанные с обработкой ошибок, и есть доступная снаружи (паблик - public ) часть.

У объектов есть интересное свойство. Допустим у меня есть просто объект и есть объект-фрукт. У фрукта по отношению к просто объекту добавляется какое-нибудь свойство, например, зрелость. Теперь, я хочу создать новый объект-яблоко. Яблоко будет наследовать все свойства объекта-фрукта. К фрукту-объекту мы добавим свойство "сорт" для получения объекта-яблока. Таким образом мы можем наращивать иерархию свойств...

-Не заботясь о том, что компьютер захлебнется?

-На самом деле для компьютера это не страшно, а программировать станет значительно удобнее. Тебе не нужно будет каждый раз все это описывать. А кроме того, ты можешь работать с десятком яблок и сотней апельсинов как с фруктами.

-Тогда пойдем дальше. Приват (013) это что такое?

013 private - это частное. Частные данные.

014 FList: array of string;

-А Эфлист эррэй оф стринг?

014 FList: array of string; - массив строк. Поскольку здесь не указан размер, то считается, что это динамический массив переменного размера.

015 protected

protected - защищенные данные, которые снаружи никак не доступны, но доступны наследникам. А private - не наследуются, т.е. private-свойства объекта-фрукта не наследуются объектом-яблоком, точнее, оно наследуется, но к нему нельзя получить доступ.

016 procedure Error(const Msg: string; Data: Integer);

-Это некая функция, которая выдает сообщение об ошибке. В скобках - параметры функции.

017 function Get(Index: Integer): string;

-Это другая фунция, имя которой используется как имя переменной для передачи выходного значения функции. Этой функции передается индекс элемента (порядковый номер строки), а она возвращает в качестве значения строку символов из этого массива строк.

В этой функции есть метод Add и Clear. Не надо специально переопределять динамический массив и проверять границы.

018 function GetCount: Integer;

-Взять количество элементов, т.е. определить количество строк в массиве строк.

019 procedure Put(Index: Integer; const S: string); virtual;

-Положить. В массив строк можно записать новое значение (новую строку). В результате одна из строк массива будет переписана:

было: красный оранжевый желтый зеленый ??? ??? ???

стало: красный оранжевый желтый зеленый голубой синий фиолетовый

Ты эту функцию не можешь вызвать, т.к. она "protected". Она вызывается, когда ты вызываешь "strings". Ты говоришь: "strings с каким-то номером равняется чему-то". Автоматически вызывается эта функция, и в эту строчку вписывается то, чему ты написал она должна равняться.

020 procedure SetTextStr(const Value: string); virtual;

-Это тебе не нужно...

-Ха ха ха!

-На самом деле это та самая штука, ради которой я ее использовал... В ней задается одна строчка, в которой есть символы переноса. Она находит символы переноса в последовательности считанного как одна строка файла, а затем превращает эту квазистроку в массив строк, используя эти символы (возврат каретки + перевод строки) как разделители элементов массива.

Эта функция освобождает память, а затем загружает туда файл, прочитанный как одна строка. Затем, по символам (возврат каретки + перевод строки)находятся концы строк и настоящие короткие строки переписываются в массив строк.

Кстати, почему ты не спрашиваешь, что такое Virtual?

-Да, что это такое?

-Допустим, для яблока мы знаем метод, как его срывать. Для фрукта мы еще не знаем. Поэтому мы говорим, что для фрукта есть медот "сорвать", но как это делать, мы пока не знаем. Объявляем метод виртуальным, а в дальнейшем он получит конкретное содержание. Этот метод будет наследоваться, но грубо говоря только имя метода.

Допустим, у нас есть массив фруктов, в который входят и яблоки и апельсины. У каждого есть метод "сорвать". Когда я оперирую с массивом, как с множеством фруктов, то я вызываю виртуальный метод, говорю: "сорви-ка мне фрукт", а яблоки и апельсины срываются разными методами, но срывая фрукты я об этом не забочусь. Виртуальный метод сам реализуется по-разному для яблок и апельсинов.

Таким образом можно на обобщенном уровне работать с различными конкретными методами одновременно.

Итак, Virtual указывает на то, что некий метод, унаследованный в дальнейшем объектами-наследниками, может переопределяться.

021 public

022 destructor Destroy; override;

Например, destructor (деструктор) - это процедура, удаляющая объекты. Она вызывается автоматически, когда ты выполняешь команду Free (освободить). Free это тот-же destroy, только free проверяет: если элемент уже удален, то destroy не выполняется.

022 destructor Destroy; override;

override - означает переопределить уже определенную ранее функцию. Эта процедура определена в типе TObject. Этот тип приписывается ко всем классам. Все классы являются наследником этого объекта (TObject).

В этом объекте есть много всяких "приятных" функций, типа того же Destroy.

После того, как мы переопределили Destroy, во всех наших объектах-наследниках будет выполняться переопределенная функция Destroy.

В нашем случае переопределенный Destroy удаляет кроме всего прочего все строчки из памяти, которую мы временно занимали.

-А если бы ты не переопределил бы эту функцию, то что было бы с программой?

-Утечка памяти. Память не освобождалась бы, а новая занималась бы...

-Понятно, а что такое 021 public? Это означает, что все, что ниже - доступно?

-Да. Это значит, что мы можем удалить объект (массив строк), добавить строчку, причем эта функция вернет индекс (номер строки) в массиве строк.

Кстати, функции не обязательно могут обрабатывать значения. Можно вызвать функцию, она что-то сделает, вернет значение, которое можно проигнорировать.

023 function Add(const S: string): Integer;

024 procedure Clear;

024 procedure Clear; - очищает список строк.

025 procedure LoadFromFile(const FileName: string);

LoadFromFile - загружает файл с именем Filename, возвращая в качестве значения квазистроку (весь список строк текстового файла)

-Мне сейчас интересно разобраться в том, что нельзя прочитать в учебниках.

-А это стандартный модуль, т.е. процедуры, вынуты из стандартного модуля. Немного переделал, чтобы он меньше места занимал...

Imports - сделан для того, чтобы это все меньше место занимало. Я убрал из этого класса все лишнее.

026 property Count: Integer read GetCount;

property Count - очень интересная штука. В отличие от свойства FList, это свойство, в котором мы можем ограничивать доступ. Например, для определения количества мы можем вызвать какую-нибудь функцию, которая будет вычислять это количество. Допустим это количество символов в строке. Оно нигде не задается, а вычисляется.

Свойство Count означает, что когда мы будем обращаться к переменной GetCount, автоматически будет вызываться функция, вычисляющая количество символов в строке, которую мы анализируем.

027 property Strings[Index: Integer]: string read Get write Put; default;

027 property Strings - свойство "Массив". Это свойство, у которого есть параметр, т.е. строка с таким-то номером. Напрямую из памяти мы не можем считать строку, а по номеру можем.

028 end;

029 TStringList = class(TStrings);

029 TStringList = class(TStrings); - это самое простое наследование. TStringList является наследником TStrings, т.е. наследует все его свойства. При этом никаких новых свойств не добавляется.

Дело в том, что имя TStringList - это стандартное имя. Мне пришлось определить, что это наследник TStrings.

030 EStringListError = class(Exception);

Это то же самое, только EStringListError является наследником метода Exception

031 implementation

На этой строке заканчивается интерфейс.

-И начинается внутренняя часть?

-Да.

032 { TStrings }

033 function TStrings.Add(const S: string): Integer;

Функция TStrings добавляет строку. Она считает количество элементов и возвращает номер добавленного в конец элемента.

034 begin

-А это, как она это делает?

-Да

035 Result := GetCount;

GetCount - это номер последнего элемента + 1. Дело в том, что нумерация элементов начинается с нуля. Функция GetCount считает количество элементов. Пока мы не добавили очередной элемент, Count указывает на элемент после последнего.

036 SetLength(FList,Result+1);

Затем мы говорим: SetLength (установить длину) на Result+1 (количество)в результате Result указывает на последний элемент.

037 FList[Result] := S;

И соответственно в список (в массив) добавляется соответствующий Result.

038 end;

-А зачем это делается?

-Чтобы добавить элемент в конец массива.

-Ты сдвинул показатель?

-Нет, мы увеличили длину массива

-А как ты это сделал?

-SetLength. Это - функция, которая изменяет длину динамического массива. Длину строки, например. Строка - это в сущности тоже динамический массив (динамический массив символов).

039 procedure TStrings.Clear;

-А процедура TStrings чего делает?

-TStrings - это класс. А процедура называется Clear

040 begin

041 SetLength(FList,0);

-Устанавливаем длину FList в 0. В резульате получаем пустой список нулевой длины.

042 end;

043 destructor TStrings.Destroy;

-Теперь очищаем освободившуюся память

044 begin

045 Clear;

-Стирание области памяти

046 inherited Destroy;

-Вызов родительского Destroy (объекта)

inherited используется для вызова родительского метода.

047 end;

048 procedure TStrings.Error(const Msg: string; Data: Integer);

-Стандартная обработка ошибочной ситуации

049 function ReturnAddr: Pointer;

050 asm

051 MOV EAX,[EBP+4]

MOV - это перемещение. Чего-то она из стека читает...

052 end;

053 begin

054 raise EStringListError.CreateFmt(Msg, [Data]) at ReturnAddr;

raise - выдает исключение, т.е. сообщение об ошибке. Например, если индекс (номер строки) оказывается отрицательным, то выдается сообщение об ошибке.

Т.е. Мы пытаемся прочитать строчку с номером -1, а нам сообщают, что, нету мол... Возвращается значение Error, которое выводится в сообщении.

055 end;

056 function TStrings.Get(Index: Integer): string;

Метод Get, который выдает результат. Если Index мы указали неправильно, то выдается сообщение об ошибке, а если правильно, то выдается значение строки символов.

Index - аргумент этой функции. Мы должны его сообщить при обращении к ней.

FList - это динамический массив строк, из которого мы по индексу читаем строку.

057 begin

058 if (Index < 0) or (Index >= GetCount)

GetCount берет и считает, сколько элементов в списке (сколько строк)

В нашей программе в FList хранится текст из EMBL-файла и может еще что-то храниться.

Очень важно бывает абстрагироваться от конкретной задачи. Мы создаем массив строк. Нам совершенно не важно, зачем он нужен. Тем самым мы создаем законченный объект, который не зависит от конкретной задачи.

В библиотеке стандартных модулей как раз собраны объекты, которые можно использовать в разных задачах, т.к. они в определенном смысле универсальны.

059 then Error('List index out of bounds',Index)

060 else Result := FList[Index];

061 end;

062 function TStrings.GetCount: Integer;

063 begin

064 Result := Length(FList)

065 end;

066 procedure TStrings.LoadFromFile(const FileName: string);

Здесь FileName - имя файла, который передается функции LoadFromFile в качестве аргумента.

067 var

068 Size: Integer;

069 S: string;

070 f: file;

071 begin

072 Assign(f, FileName);

073 Reset(f,1);

Методом Reset эта программа-функция открывает файл. Файл с размером записи = 1. Единица измерения в данном файле = 1 байт.

074 try

075 Size := FileSize(f);

Здесь определяется размер этого файла (FileSize)

076 SetString(S, nil, Size);

SetString - это метод, который создает пустую (nil) строку, длиной Size.

077 BlockRead(f,PChar(S)^, Size);

Затем, методом BlockRead этот файл целиком читаем в эту квазистроку (до 2Гигабайт). Таким образом мы весь файл читаем как одну строку. Затем в памяти уже разбираем на отделные элементы-строки по разделителям (возврат каретки + перевод строки)

078 SetTextStr(S);

079 finally

В случае ошибки

080 Close(f);

все равно закрыть файл, чтобы не было в памяти потерянных файлов.

081 end;

082 end;

083 procedure TStrings.Put(Index: Integer; const S: string);

Put работает аналогично Get. Записывает строку в список, проверяет значение индекса...

-А что записывается в список?

-То, что передашь... В данном случае const (константу) string (строку).

-Записывается что-то в строку?

-Не в строку, а в список (List) строк.

-А что за список?

-Наш список строк. Мы сделали объект, который хорошо работает со строками. Есть встроенный в DELFI объект работы со строками (ReaveString), который не очень хорошо работает со строками. По этому я вместо того, чтобы напрямую воспользоваться стандартным методом DELFI, я использую свой метод (усовершенствованный). Что-то проверяю, что-то делаю, а потом уже вызываю стандартный метод DELFI.

FList - это объект-список (list) DELFI, который я обрабатываю по-своему.

084 begin

085 if (Index < 0) or (Index >= GetCount)

086 then Error('List index out of bounds',Index)

087 else FList[Index] := s;

Поэтому я вызываю этот список (FList) с номером (Index), т.е. в дельфовый массив "список" (точнее в элемент массива, т.е. в строку) с номером "индекс" я записываю строку S.

-Я не понял, что за чем ты делаешь?

-В объектно-ориентированном языке не нужно думать о последовательности операций.

Представь себе, что у нас есть массив строк. Что с ним можно сделать?

-Можно, например, выбрать одну из строк списка.

-Правильно. У меня для этого есть метод "Get".

-Можно записать в список строку.

-Да. Для этого у меня есть метод "Put".

Могу все стереть. Для этого есть "Clear".

Могу в него считать файл.

088 end;

089 procedure TStrings.SetTextStr(const Value: string);

Этот метод разбирает файл на отдельные элементы-строки символов. Этот метод написан не мной в Паскале. Как он работает, я не разбирался.

Эта программа берет строку, в которой есть символы (возврат каретки + перевод строки) и

запихивает в свой массив в качестве элемента-строки массива-списка.

-А этот массив как-то поименован?

-FList. Ниже в тексте он должен быть...

090 var

091 P, Start: PChar;

092 S: string;

093 begin

094 try

095 Clear;

096 P := PChar(Value);

097 if P <> nil then

098 while P^ <> #0 do

099 begin

100 Start := P;

101 while not (P^ in [#0, #10, #13]) do Inc(P);

#10, #13 - это коды символов "возврат каретки" и "перевод строки" соответственно

По этим символам программа находит настоящие строки и отправляет их поштучно в массив элементов-строк.

102 SetString(S, Start, P - Start);

103 Add(S);

104 if P^ = #13 then Inc(P);

105 if P^ = #10 then Inc(P);

106 end;

107 finally

108 end;

109 end;

110 end.

-Как можно назвать все эти функции, которые мы рассмотрели?

-Это все были "Импорты", которые я взял из DELFI и чуть-чуть переделал.

Главная функция этого модуля - хранить строки (прочитанные как одна строка и разобранные на элементы-строки массива-списка).

Далее рассмотрим модуль Unit1.pas

Поскольку эта программа не совсем правильная, на все это надо смотреть с конца...

По классическей схеме вызывается модуль main.

614 procedure main;

615 var

616 s: string;

617 begin

618 Writeln;

Он в любом случае выводит текст: Copyright.

619 Writeln('(c) 1995-1999 Nanoworld lab., Moscow');

620 Writeln('(c) 1995-1999 A.Yu.Kushelev');

621 Writeln;

Далее, если параметров нет, вызывает помощь,

622 if ParamCount<1 then

623 begin

624 Writeln('Using:');

625 Writeln(' dne2ent source[.dne] [destination.ent]');

626 end else

если параметр один, обрабатывает соответствующий файл,

627 if ParamCount<2 then

628 begin

629 Writeln('Processing...');

630 s := ParamStr(1);

631 if (Length(s)>4)and(s[Length(s)-3]='.')

632 then SetLength(s,Length(s)-4);

633 ProcessFiles(s+'.dne',s+'.ent');

634 Writeln('Done.');

635 end else

а если параметров два, то вызывает программу ProcessFiles с параметром 1 и параметром 2.

636 begin

637 Writeln('Processing...');

Далее, что делает процесс-файлз, что там происходит?

595 procedure ProcessFiles(const src,dst: string);

596 var

597 tStr: string;

598 begin

Сначала загружается стринг-лист (список строчек) из файла СРЦ.

599 slSrc := TStringList.Create;

600 try

Читаем диапазон СРЦ (не СРЦ, а CDS - Си-Ди-Эс)

601 slSrc.LoadFromFile(src);

-А как это происходит?

-При помощи этой процедуры: Нажимает Ctrl и превращаем DELFI в своеобразный браузер.

602 ReadSrcRng(slSrc);

Затем, 603 LoadDNESeq(slSrc); лоад ДНЕ - загружается последовательность. Эта процедура читает кодирующую последовательность по CDS.

603 LoadDNESeq(slSrc);

Затем, сохраняется эта кодирующая последовательность

604 tStr := fDNEString;
Обрезает исходную последовательность в соответствии с CDS, т.е. в соответствии с начальным и конечным индексом, прочитанным вот здесь вот...

605 Delete (tStr, fEnd+1, Length(tStr));

606 Delete (tStr, 1, fStart-1);

и переводит ее в последовательность атомов

607 TranslateDNESeq (tStr);

608 //AddLines;

и затем пишет ent-файл

609 WriteENT(dst);

610 finally

611 slSrc.Free;

612 end;

613 end;

Таким образом, выполнив процедуру 595 procedure ProcessFiles(const src,dst: string); мы возвращаемся в главную программу (main)

638 ProcessFiles(ParamStr(1),ParamStr(2));

Вернулись и пишем “Все нормально” (Done)

639 Writeln('Done.');

640 end;

641 end;

642 end.

Это конец модуля Unit1. А теперь, вернемся к началу.

-Интересно было бы разобраться в деталях...

-Сейчас будем смотреть детали по порядку.

602 ReadSrcRng(slSrc);

Рид срц рэндж что там происходит?

273 procedure ReadSrcRng(Strings: TStrings);

274 var

275 i,pp: integer;

276 s,ss: String;

277 begin

278 for i := 0 to Strings.Count-1 do

279 begin

Выбирается нужная строчка s

280 s := Strings[i];

Далее, смотрится: Если первые два символа в этой строке “FT”, то

281 if Copy(s, 1, 2) = 'FT' then

282 begin

эти первые буквы удаляются,

283 Delete (s, 1, 2);

затем удаляются пробелы,

284 s := TrimLeft (s);

смотрится, если есть строчка “CDS”,

285 if UpperCase(Copy(s, 1, 3)) = 'CDS' then begin

то высчитывается диапазон индексов кодирующей последовательности, заданный в CDS

1, 2, 3 – циферки выдергиваются... Сперва они выдергиваются, как строчки в S и SS

Получаются две строчки.

286 Delete (s, 1, 3);

В одной такая штука ('123..6789' – s),

287 s := TrimLeft (s); // '123..6789' - s

288 pp := pos ('.', s); // 4 – pp

а в другой – такая ('123' – ss).

289 ss := Copy(s, 1, pp-1); // '123' - ss

290 Delete (s, 1, pp+1); // '6789' - s

291 if Copy(ss, 1, 1) = '<' then Delete (ss, 1, 1);

292 if Copy(s, 1, 1) = '>' then Delete (s, 1, 1);

Потом с помощью функции val, встроенной в Паскаль, высчитывается само значение, т.е. преобразуется символьный формат цифр в числовые значения. Далее возвращаются вычисленные значения

293 val (ss, fStart, pp);

294 if pp<>0 then fStart := 0;

295 val (s, FEnd, pp);

296 if pp<>0 then fEnd := 0;

297 exit;

298 end;

299 end;

300 end;

301 end;

Следующая процедура: рид лоад DNE сиквенс

603 LoadDNESeq(slSrc);

Захожу в текст этой процедуры. Что тут происходит?

302 procedure LoadDNESeq (Strings: TStrings);

303 var

304 i: integer;

305 tStr: string;

306 begin

307 i := 0;

Все строчки просматриваются на предмет, не начинаются ли они с пробела? Если они начинаются не с пробела, то пропускаются.

Если очередная строка начинается с пробела, то

308 while (i < Strings.Count) and (Copy(Strings[i], 1, 1) <> ' ') do

309 inc(i);

310 fDNEString := '';

311 while (i < Strings.Count) and (Copy(Strings[i], 1, 1) = ' ') do

312 begin

эти пробелы убираются функцией Trim

313 tStr := Trim (Strings[i]);

314 Pos(' ', tStr) > 0 do

затем удаляются все промежуточные пробелы “while (пока) есть пробелы удалять их”

315 Delete (tStr, Pos(' ', tStr), 1);

Затем в fDNEString добавляется кусочек tStr, который нашелся в данной строчке кода ДНК

Кончается формирование кодирующей последовательности ДНК как только встретится строчка, начинающаяся не с пробела. 308 while (i < Strings.Count) and (Copy(Strings[i], 1, 1) <> ' ') do

316 fDNEString := fDNEString + tStr;

317 inc(i);

318 end;

319 end;

-Не понятно назначение этих двух строк после END

320 var

321 offset: TVertex;

Теперь рассмотрим процедуру “транслэйт ДНЕ-сиквенс”

607 TranslateDNESeq (tStr);

Заходим в текст этой процедуры, которая преобразует эту самую строчку. Что тут происходит?

Offset. Что это такое? Щас соображу...

Даже не соображу, а покажу...

Каждый раз, когда мы добавляем элемент, мы должны все это как-то сдвинуть. И этот сдвиг берется вот отсюда. Предыдущий аминокислотный остаток предполагается лежащим в начале координат (0,0,0) а координаты вот этого Эн являются вектором сдвига.

532 procedure TranslateDNESeq (Seq: string);

533 var

534 _1,_2,_3: TGrpIndex;

535 begin

536 offset := Atoms_Common[1].p;

Затем, я использовал функцию CorrectAtom, которая крутит из позиции, где ты снимал координаты всех атомов в позицию, которая принята в программе за исходную ориентацию.

537 CorrectAtom(offset);

538 while Length (Seq)>=3 do begin

Затем кусками по три выдираются первый,

539 _1 := DneToInt (Seq[1]);

второй

540 _2 := DneToInt (Seq[2]);

и третий символ триплета кодирующей последовательности.

541 _3 := DneToInt (Seq[3]);

Далее в соответствии с этими тремя символами вызывается табличная функция DNE_Groups

Далее структура белка поворачивается, там же она сдвигается на offset,

542 Rotate (DNE_Groups [_1, _2, _3]);

затем втыкается новый триплет в соответствии с символами (_1, _2, _3);

543 AddTriplet (_1, _2, _3);

и удаляется из строчки Seq эти три символа (они уже отработаны) и начинаем работать со следующим триплетом.

544 Delete (Seq,1,3);

545 end;

546 end;

Следующая процедура:

Врайт Ент

609 WriteENT(dst);

Переходим к тексту этой процедуры.

547 procedure WriteENT(const dst: string);

548 var

549 i: integer;

550 f: text;

551 s: string;

552 begin

Открывается файл “дестинайшн”

553 Assign(f,dst);

554 Rewrite(f);

Устанавливается, что разделителем дробной части от целой будет точка, а не запятая, как принято по умолчанию в Windows
555 DecimalSeparator := '.';

556 for i := 0 to Length(Atoms)-1 do

557 with Atoms[i] do

558 begin

Здесь у меня расписана разметка выходного бланка: какие поля, по скольку символов, в каких позициях... Короче, как устроена структура ent-файла.

559 {

Сначала нужно вывести четыре символа “ATOM”, затем номер атома, затем имя атома, затем имя аминокислотного остатка, например, CYS, затем номер остатка, затем координаты атома, затем какие-то числа, которые какую-то напряженность означают (нам они не нужны, я их забиваю нулями, точнее единичками, потом какой-то комментарий, который не используется, и в конце номер строчки дублируется.

560 ATOM 360 CA CYS 48 21.690 28.114 17.923 1.00 6.00 3 1SN3 447

561 " " " " " " " " " " " "

562 1234567 234 234 2345 23456 23456789012 2345678 2345678 23456 23456 2345678901234

563 12345678901234567890123456789012345678901234567890123456789012345678901234567890

564 }

565 s := 'ATOM ';

566 s := s + Format('%4d',[i]);

567 s := s + ' '+ch1+ch2+ch3;

568 s := s + ' '+Ami;

569 s := s + Format('%6d',[n1]);

570 s := s + Format('%12.2f',[p.x]);

571 s := s + Format('%8.2f',[p.y]);

572 s := s + Format('%8.2f',[p.z]);

573 s := s + Format('%6.2f',[1.00]);

574 s := s + Format('%6.2f',[6.00]);

575 s := s + ' 1SN3';

576 s := s + Format('%4d',[i]);

577 writeln(f,s);

578 end;

579 (* for i := 0 to Length(Lines)-1 do

580 with Lines[i] do

581 begin

Коннект никак не используется. Сначала я пытался их как-то соединять, но это оказалось не нужным. Можно сейчас это все стереть.

-Нет, давай это сотрем позже.

582 {

583 CONECT 2 4 7RXN 667

584 " " " " "

585 1234 2345

586 }

587 s := 'CONECT ';

588 s := s + Format('%4d',[b]);

589 s := s + Format('%5d',[e]);

590 s := s + ' 7RXN 667';

591 writeln(f,s);

592 end;*)

593 close(f);

594 end;

По крупному мы еще не посмотрели Рорэйт

542 Rotate (DNE_Groups [_1, _2, _3]);

Переходим к тексту процедуры “Ротэйт”

322 procedure Rotate (Kind: TGrpIndex);

323 var

324 i: integer;

325 t:Float;

326 tCos,tSin: Extended;

327 begin

328 for i:=0 to Length(atoms)-1 do begin

329 with Atoms[i].p do begin

Первая,

330 tCos := cos (DNE_Angles[Kind]. x / 180 * pi);

331 tSin := sin (DNE_Angles[Kind]. x / 180 * pi);

332 t := y * tCos - Z * tSin;

333 z := y * tSin + Z * tCos; y := t;

вторая

334 tCos := cos (DNE_Angles[Kind]. y / 180 * pi);

335 tSin := sin (DNE_Angles[Kind]. y / 180 * pi);

336 t := z * tCos - x * tSin;

337 x := z * tSin + x * tCos; z := t;

и третья ось

-А вот это очень любопытно!

Цикл до какого значения идет?

-Количество атомов минус один. 328 for i:=0 to Length(atoms)-1 do begin

Атомы от нуля считаются.

-И ты крутишь все атомы?

-Да.

-А что означает: 329 with Atoms[i].p do begin

-Это означает, что для каждой координаты. p(пэ) – это координата итого атома Atoms[i]

-А как считаются новые координаты через косинусы?

-Это стандартное афинное преобразование

338 tCos := cos (DNE_Angles[Kind]. z / 180 * pi);

339 tSin := sin (DNE_Angles[Kind]. z / 180 * pi);

Икс на косинус минус игрек на синус...

-Ты можешь где-то в комментариях это записать, а я потом буду разбираться

-Что записать?

-Что это за формула?

-Стандартные афинные преобразования

-Стандартные афинные преобразования поворота вокруг точки?

-Относительно начала координат

-Это надо бы записать, хотя можно не записывать, а просто сказать, а я сам потом запишу... У меня время пока что дешевле твоего...

А вторая серия преобразований?

-Тоже самое, только относительно другой оси. Сначала поворачиваем относительно икса, потом игрека, а потом зета.

-А дальше?

-После того, как вокруг всех трех осей покрутили, теперь сдвигаем.

340 t := x * tCos - y * tSin;

341 y := x * tSin + y * tCos; x := t;

342 x := x + 3;//offset.x*0.1;

-А почему сдвигаем только по х?

-А у нас такой алгоритм. Рибосома двигает белок только по иксу.

343 // y := y + offset.y*0.1;

344 // z := z + offset.z*0.1;

345 end;

346 end;

347 end;

Дальше смотрим прецедуру “Эдд триплет”

543 AddTriplet (_1, _2, _3);

Переходим к тексту этой процедуры

387 procedure AddTriplet (_1,_2,_3: TGrpIndex);

388 var

389 ami: string[3];

390 begin

391 ami := DNE_AMI[_1,_2,_3];

392 if ami='TKD' then exit; // TKD

393 inc(fCntr);

394 AddAtoms(ami,Atoms_Common);

В зависимости от значения очередного элемента, мы добавляем в структуру белка соответствующую аминокислоту, в частности лизин 400 _a: AddAtoms(ami,Atoms_Lys);

395 case _1 of

396 _a:

397 case _2 of

398 _a:

399 case _3 of

В зависимости от триплета добавляются атомы соответствующей аминокислоты с помощью процедуры AddAtoms.

В качестве аргументов указываются массив с атомами и название аминокислоты

Для функции AddAtoms все равно, какая это аминокислота. Ей передали ее название и атомы, а она их добавляет к другому массиву (уже целого белка)

-Значит, ты по каждому триплету вытаскиваешь подготовленные данные по каждой аминокислоте?

-Да

-А как ты учитываешь разную длину радикалов?

-Для каждого массива я четко указываю его длину.

Поэтому мне и пришлось делать кейс такой, потому, что каждый массив имеет свою длину.

400 _a: AddAtoms(ami,Atoms_Lys);

401 _c: AddAtoms(ami,Atoms_Asn);

402 _g: AddAtoms(ami,Atoms_Lys);

403 _t: AddAtoms(ami,Atoms_Asn)

404 end;

405 _c:

406 case _3 of

407 _a: AddAtoms(ami,Atoms_Thr);

408 _c: AddAtoms(ami,Atoms_Thr);

409 _g: AddAtoms(ami,Atoms_Thr);

410 _t: AddAtoms(ami,Atoms_Thr)

411 end;

412 _g:

413 case _3 of

414 _a: AddAtoms(ami,Atoms_Arg_bottom);

415 _c: AddAtoms(ami,Atoms_Ser_teta);

416 _g: AddAtoms(ami,Atoms_Arg_bottom);

417 _t: AddAtoms(ami,Atoms_Ser_teta)

418 end;

419 _t:

420 case _3 of

421 _a: AddAtoms(ami,Atoms_Ile);

422 _c: AddAtoms(ami,Atoms_Ile);

423 _g: AddAtoms(ami,Atoms_Met);

424 _t: AddAtoms(ami,Atoms_Ile)

425 end;

426 end;

427 _c:

428 case _2 of

429 _a:

430 case _3 of

431 _a: AddAtoms(ami,Atoms_Gln);

432 _c: AddAtoms(ami,Atoms_His);

433 _g: AddAtoms(ami,Atoms_Gln);

434 _t: AddAtoms(ami,Atoms_His)

435 end;

436 _c:

437 case _3 of

438 _a: AddAtoms(ami,Atoms_Pro);

439 _c: AddAtoms(ami,Atoms_Pro);

440 _g: AddAtoms(ami,Atoms_Pro);

441 _t: AddAtoms(ami,Atoms_Pro)

442 end;

443 _g:

444 case _3 of

445 _a: AddAtoms(ami,Atoms_Arg_top);

446 _c: AddAtoms(ami,Atoms_Arg_top);

447 _g: AddAtoms(ami,Atoms_Arg_top);

448 _t: AddAtoms(ami,Atoms_Arg_top)

449 end;

450 _t:

451 case _3 of

452 _a: AddAtoms(ami,Atoms_Leu_lambda);

453 _c: AddAtoms(ami,Atoms_Leu_lambda);

454 _g: AddAtoms(ami,Atoms_Leu_lambda);

455 _t: AddAtoms(ami,Atoms_Leu_lambda)

456 end;

457 end;

458 _g:

459 case _2 of

460 _a:

461 case _3 of

462 _a: AddAtoms(ami,Atoms_Glu);

463 _c: AddAtoms(ami,Atoms_Asp);

464 _g: AddAtoms(ami,Atoms_Glu);

465 _t: AddAtoms(ami,Atoms_Asp)

466 end;

467 _c:

468 case _3 of

469 _a: AddAtoms(ami,Atoms_Ala);

470 _c: AddAtoms(ami,Atoms_Ala);

471 _g: AddAtoms(ami,Atoms_Ala);

472 _t: AddAtoms(ami,Atoms_Ala)

473 end;

474 _g:

475 case _3 of

476 _a: exit; // AddAtoms(ami,Atoms_Gly);

477 _c: exit; // AddAtoms(ami,Atoms_Gly);

478 _g: exit; // AddAtoms(ami,Atoms_Gly);

479 _t: exit; // AddAtoms(ami,Atoms_Gly);

480 end;

481 _t:

482 case _3 of

483 _a: AddAtoms(ami,Atoms_Val);

484 _c: AddAtoms(ami,Atoms_Val);

485 _g: AddAtoms(ami,Atoms_Val);

486 _t: AddAtoms(ami,Atoms_Val)

487 end;

488 end;

489 _t:

490 case _2 of

491 _a:

492 case _3 of

493 _a: exit; // TKD

494 _c: AddAtoms(ami,Atoms_Tyr);

495 _g: exit; // TKD

496 _t: AddAtoms(ami,Atoms_Tyr)

497 end;

498 _c:

499 case _3 of

500 _a: AddAtoms(ami,Atoms_Ser_teta);

501 _c: AddAtoms(ami,Atoms_Ser_teta);

502 _g: AddAtoms(ami,Atoms_Ser_teta);

503 _t: AddAtoms(ami,Atoms_Ser_teta)

504 end;

505 _g:

506 case _3 of

507 _a: exit; // TKD

508 _c: AddAtoms(ami,Atoms_Cys);

509 _g: AddAtoms(ami,Atoms_Trp);

510 _t: AddAtoms(ami,Atoms_Cys)

511 end;

512 _t:

513 case _3 of

514 _a: AddAtoms(ami,Atoms_Leu_teta);

515 _c: AddAtoms(ami,Atoms_Phe);

516 _g: AddAtoms(ami,Atoms_Leu_teta);

517 _t: AddAtoms(ami,Atoms_Phe)

518 end;

519 end;

520 end;

521 end;

Далее, смотрим таблицу имен аминокислот.

Она задается в процедуре main (строка 031)

000 unit Unit1;

001 interface

002 procedure main;

003 implementation

004 uses

005 SysUtils, Imports{, Classes, Registry, IniFiles, fgBasicTypes};

006 type

007 TGrpIndex = 1..4;

008 TAtom = record

009 p: TVertex;

010 ch1, ch2, ch3: char;

011 n1: integer;

012 Ami: string[3];

013 end;

014 TAtomsArray = array of TAtom;

015 const

016 DNE_Angles: array [1..4] of TVertex = (

017 (x: 10; y: 30; z: 97),

018 (x: 0; y:120; z:120),

019 (x: 0; y: 30; z:-60),

020 (x: 10; y: 30; z: 80));

021 DNE_Null: TVertex = (x: 0; y: 0; z: 0);

022 DNE_Groups: array [TGrpIndex, TGrpIndex, TGrpIndex] of TGrpIndex =

023 (((1,2,3,4), (1,3,3,1), (1,2,3,4), (1,2,3,4) ),

024 ((1,2,3,4), (1,3,3,1), (1,2,3,1), (1,3,3,1) ),

025 ((1,2,3,4), (1,1,3,1), (1,3,3,1), (1,1,3,1) ),

026 ((1,2,3,4), (1,3,3,1), (1,2,3,4), (1,2,3,4) ));

027 _c = 1;

028 _a = 2;

029 _t = 3;

030 _g = 4;

Это – таблица имен аминокислот. Она позволяет по комбинации символов (ссс, сса...) определить имя аминокислоты.

-Для того, чтобы имя этой аминокислоты вывести в ent-файл?

-Да

031 DNE_AMI: array [TGrpIndex, TGrpIndex, TGrpIndex] of string[3] =

032 (((('PRO'), // ccc

033 ('PRO'), // cca

034 ('PRO'), // cct

035 ('PRO')), // ccg

036 (('HIS'), // cac

037 ('GLN'), // caa

038 ('HIS'), // cat

039 ('GLN')), // cag

040 (('LEU'), // ctc

041 ('LEU'), // cta

042 ('LEU'), // ctt

043 ('LEU')), // ctg

044 (('ARG'), // cgc

045 ('ARG'), // cga

046 ('ARG'), // cgt

047 ('ARG'))),// cgg

048 ((('THR'), // acc

049 ('THR'), // aca

050 ('THR'), // act

051 ('THR')), // acg

052 (('ASN'), // aac

053 ('LYS'), // aaa

054 ('ASN'), // aat

055 ('LYS')), // aag

056 (('ILE'), // atc

057 ('ILE'), // ata

058 ('ILE'), // att

059 ('MET')), // atg

060 (('SER'), // agc

061 ('ARG'), // aga

062 ('SER'), // agt

063 ('ARG'))),// agg

064 ((('SER'), // tcc

065 ('SER'), // tca

066 ('SER'), // tct

067 ('SER')), // tcg

068 (('TYR'), // tac

069 ('TKD'), // taa

070 ('TYR'), // tat

071 ('TKD')), // tag

072 (('PHE'), // ttc

073 ('LEU'), // tta

074 ('PHE'), // ttt

075 ('LEU')), // ttg

076 (('CYS'), // tgc

077 ('TKD'), // tga

078 ('CYS'), // tgt

079 ('TRP'))),// tgg

080 ((('ALA'), // gcc

081 ('ALA'), // gca

082 ('ALA'), // gct

083 ('ALA')), // gcg

084 (('ASP'), // gac

085 ('GLU'), // gaa

086 ('ASP'), // gat

087 ('GLU')), // gag

088 (('VAL'), // gtc

089 ('VAL'), // gta

090 ('VAL'), // gtt

091 ('VAL')), // gtg

092 (('GLY'), // ggc

093 ('GLY'), // gga

094 ('GLY'), // ggt

095 ('GLY'))) // ggg

096 );

097 // == < auto converted in Excel > ==========

Затем, здесь таблица координат атомов

098 Atoms_Common: array [1..4] of TAtom = (

099 (p:(x: 23.1; y: 9.7; z: 31.3); ch1:'N'; ch2:' '; ch3:' '),

100 (p:(x: 9.7; y:-14.4; z: 0 ); ch1:'C'; ch2:'A'; ch3:' '),

101 (p:(x:-20.3; y:-24.6; z: 0 ); ch1:'C'; ch2:' '; ch3:' '),

102 (p:(x:-45.5; y:-10.7; z: 0 ); ch1:'O'; ch2:' '; ch3:' '));

103 Atoms_Lys: array [1..5] of TAtom = (

104 (p:(x: 8.4; y: 23.3; z: 0 ); ch1:'C'; ch2:'B'; ch3:' '),

105 (p:(x: 23.7; y: 42; z:-22.9); ch1:'C'; ch2:'G'; ch3:' '),

106 (p:(x: 39.7; y: 29.2; z:-51.4); ch1:'C'; ch2:'D'; ch3:' '),

107 (p:(x: 43.4; y: -5.3; z: -61); ch1:'C'; ch2:'E'; ch3:' '),

108 (p:(x: 33.7; y: -33; z:-43.4); ch1:'N'; ch2:'Z'; ch3:' '));

109 Atoms_Asn: array [1..4] of TAtom = (

110 (p:(x: 8.4; y: 23.3; z: 0 ); ch1:'C'; ch2:'B'; ch3:' '),

111 (p:(x: 28.4; y: 29.7; z: 36.6); ch1:'C'; ch2:'G'; ch3:' '),

112 (p:(x: 40.4; y: 13.6; z: 56); ch1:'O'; ch2:'D'; ch3:'1'),

113 (p:(x: 20.6; y: 62; z: 23.2); ch1:'N'; ch2:'D'; ch3:'2'));

114 Atoms_Thr: array [1..3] of TAtom = (

115 (p:(x: 8.4; y: 23.3; z: 0 ); ch1:'C'; ch2:'B'; ch3:' '),

116 (p:(x: 26.2; y: 35.3; z:-28.3); ch1:'O'; ch2:'G'; ch3:'1'),

117 (p:(x: -27; y: 34.7; z: 0 ); ch1:'C'; ch2:'G'; ch3:'2'));

118 Atoms_Arg_bottom: array [1..7] of TAtom = (

119 (p:(x: 8.4; y: 23.3; z: 0 ); ch1:'C'; ch2:'B'; ch3:' '),

120 (p:(x: 22.3; y: 43.1; z:-22.7); ch1:'C'; ch2:'G'; ch3:' '),

121 (p:(x: 39.7; y: 29; z:-50.6); ch1:'C'; ch2:'D'; ch3:' '),

122 (p:(x: 41.1; y: -9.5; z: -55); ch1:'N'; ch2:'E'; ch3:' '),

123 (p:(x: 80.9; y:-10.9; z: -55); ch1:'C'; ch2:'Z'; ch3:' '),

124 (p:(x:102.9; y: 4.3; z: -55); ch1:'N'; ch2:'H'; ch3:'1'),

125 (p:(x: 68.1; y: -47; z:-60.6); ch1:'N'; ch2:'H'; ch3:'2'));

126 Atoms_Ser_teta: array [1..2] of TAtom = (

127 (p:(x: 8.4; y: 23.3; z: 0 ); ch1:'C'; ch2:'B'; ch3:' '),

128 (p:(x:-26.5; y: 35.3; z: 0 ); ch1:'O'; ch2:'G'; ch3:' '));

129 Atoms_Ile: array [1..4] of TAtom = (

130 (p:(x: 8.4; y: 23.3; z: 0 ); ch1:'C'; ch2:'B'; ch3:' '),

131 (p:(x: 26.1; y: 35.6; z:-28.5); ch1:'C'; ch2:'G'; ch3:'1'),

132 (p:(x: 37.3; y: 6.7; z:-50.2); ch1:'C'; ch2:'G'; ch3:'2'),

133 (p:(x:-26.8; y: 35.6; z: 0 ); ch1:'C'; ch2:'D'; ch3:'1'));

134 Atoms_Met: array [1..4] of TAtom = (

135 (p:(x: 8.4; y: 23.3; z: 0 ); ch1:'C'; ch2:'B'; ch3:' '),

136 (p:(x:-26.7; y: 35.7; z: 0 ); ch1:'C'; ch2:'G'; ch3:' '),

137 (p:(x:-46.8; y: 68.9; z: 0 ); ch1:'S'; ch2:'D'; ch3:' '),

138 (p:(x:-75.4; y: 39.9; z: 0 ); ch1:'C'; ch2:'E'; ch3:' '));

139 Atoms_Gln: array [1..5] of TAtom = (

140 (p:(x: 8.4; y: 23.3; z: 0 ); ch1:'C'; ch2:'B'; ch3:' '),

141 (p:(x: 26.6; y: 34.8; z:-28.2); ch1:'C'; ch2:'G'; ch3:' '),

142 (p:(x: -2.9; y: 54.1; z:-42.4); ch1:'C'; ch2:'D'; ch3:' '),

143 (p:(x:-28.9; y: 60.5; z:-37.8); ch1:'O'; ch2:'E'; ch3:'1'),

144 (p:(x: 25.1; y: 59.6; z: -68); ch1:'N'; ch2:'E'; ch3:'2'));

145 Atoms_His: array [1..6] of TAtom = (

146 (p:(x: 16.5; y: 20.7; z: 0 ); ch1:'C'; ch2:'B'; ch3:' '),

147 (p:(x: 8.9; y: 47.2; z: 0 ); ch1:'C'; ch2:'G'; ch3:' '),

148 (p:(x: 1.7; y: 73.2; z: 0 ); ch1:'N'; ch2:'D'; ch3:'1'),

149 (p:(x:-23.6; y: 65.6; z: 0 ); ch1:'C'; ch2:'D'; ch3:'2'),

150 (p:(x:-16.4; y: 40; z: 0 ); ch1:'N'; ch2:'E'; ch3:'2'),

151 (p:(x: -8.8; y: 14.7; z: 0 ); ch1:'C'; ch2:'E'; ch3:'1'));

152 Atoms_Pro: array [1..3] of TAtom = (

153 (p:(x: 8.4; y: 23.3; z: 0 ); ch1:'C'; ch2:'B'; ch3:' '),

154 (p:(x: 26.7; y: 34.7; z: 34); ch1:'C'; ch2:'G'; ch3:' '),

155 (p:(x: 39.9; y: 6.3; z: 53.5); ch1:'C'; ch2:'D'; ch3:' '));

156 Atoms_Arg_top: array [1..7] of TAtom = (

157 (p:(x: 8.4; y: 23.3; z: 0 ); ch1:'C'; ch2:'B'; ch3:' '),

158 (p:(x: 22.5; y: 42.4; z:-22.9); ch1:'C'; ch2:'G'; ch3:' '),

159 (p:(x: 39.7; y: 28.7; z:-51.4); ch1:'C'; ch2:'D'; ch3:' '),

160 (p:(x: 40.1; y: -9.3; z:-56.2); ch1:'N'; ch2:'E'; ch3:' '),

161 (p:(x: 20.9; y:-10.5; z:-89.1); ch1:'C'; ch2:'Z'; ch3:' '),

162 (p:(x: 6.9; y: 4.7;z:-106.7); ch1:'N'; ch2:'H'; ch3:'1'),

163 (p:(x: 30.9; y:-48.2; z:-80.6); ch1:'N'; ch2:'H'; ch3:'2'));

164 Atoms_Leu_lambda: array [1..4] of TAtom = (

165 (p:(x: 8.4; y: 23.3; z: 0 ); ch1:'C'; ch2:'B'; ch3:' '),

166 (p:(x: 26.1; y: 35.6; z:-28.5); ch1:'C'; ch2:'G'; ch3:' '),

167 (p:(x: 55.4; y: 56.4; z:-18.5); ch1:'C'; ch2:'D'; ch3:'1'),

168 (p:(x: 2.1; y: 54.8; z:-49.6); ch1:'C'; ch2:'D'; ch3:'2'));

169 Atoms_Glu: array [1..5] of TAtom = (

170 (p:(x: 8.4; y: 23.3; z: 0 ); ch1:'C'; ch2:'B'; ch3:' '),

171 (p:(x: 26.6; y: 34.8; z:-28.2); ch1:'C'; ch2:'G'; ch3:' '),

172 (p:(x: -2.9; y: 54.1; z:-42.4); ch1:'C'; ch2:'D'; ch3:' '),

173 (p:(x:-28.9; y: 60.5; z:-37.8); ch1:'O'; ch2:'E'; ch3:'1'),

174 (p:(x: 25.1; y: 59.6; z: -68); ch1:'O'; ch2:'E'; ch3:'2'));

175 Atoms_Asp: array [1..4] of TAtom = (

176 (p:(x: 8.4; y: 23.3; z: 0 ); ch1:'C'; ch2:'B'; ch3:' '),

177 (p:(x: 28.4; y: 29.7; z: 36.6); ch1:'C'; ch2:'G'; ch3:' '),

178 (p:(x: 40.4; y: 13.6; z: 56); ch1:'O'; ch2:'D'; ch3:'1'),

179 (p:(x: 20.6; y: 62; z: 23.2); ch1:'O'; ch2:'D'; ch3:'2'));

180 Atoms_Ala: array [1..1] of TAtom = (

181 (p:(x: 8.4; y: 23.3; z: 0 ); ch1:'C'; ch2:'B'; ch3:' '));

182 Atoms_Val: array [1..3] of TAtom = (

183 (p:(x: 8.4; y: 23.3; z: 0 ); ch1:'C'; ch2:'B'; ch3:' '),

184 (p:(x: 26.2; y: 35.3; z:-28.3); ch1:'C'; ch2:'G'; ch3:'1'),

185 (p:(x: -27; y: 34.7; z: 0 ); ch1:'C'; ch2:'G'; ch3:'2'));

186 Atoms_Tyr: array [1..8] of TAtom = (

187 (p:(x: 8.4; y: 23.3; z: 0 ); ch1:'C'; ch2:'B'; ch3:' '),

188 (p:(x: 24.8; y: 47.3; z:-24.9); ch1:'C'; ch2:'D'; ch3:'2'),

189 (p:(x: 35.5; y: 63.1; z: -43); ch1:'C'; ch2:'E'; ch3:'2'),

190 (p:(x: 47.5; y: 50.7; z:-64.6); ch1:'C'; ch2:'Z'; ch3:' '),

191 (p:(x: 48.3; y: 25; z:-66.6); ch1:'C'; ch2:'E'; ch3:'1'),

192 (p:(x: 36.8; y: 10.8; z:-47.8); ch1:'C'; ch2:'D'; ch3:'1'),

193 (p:(x: 26; y: 23.7; z:-26.5); ch1:'C'; ch2:'G'; ch3:' '),

194 (p:(x: 52.5; y: 83.2; z:-72.9); ch1:'O'; ch2:'H'; ch3:' '));

195 Atoms_Ser_lambda: array [1..2] of TAtom = (

196 (p:(x: 8.4; y: 23.3; z: 0 ); ch1:'C'; ch2:'B'; ch3:' '),

197 (p:(x: 26.1; y: 35.9; z: 33.2); ch1:'O'; ch2:'G'; ch3:' '));

198 Atoms_Cys: array [1..2] of TAtom = (

199 (p:(x: 8.4; y: 23.3; z: 0 ); ch1:'C'; ch2:'B'; ch3:' '),

200 (p:(x: 26.1; y: 35.9; z: 33.2); ch1:'S'; ch2:'G'; ch3:' '));

201 Atoms_Trp: array [1..10] of TAtom = (

202 (p:(x: 8.4; y: 23.3; z: 0 ); ch1:'C'; ch2:'B'; ch3:' '),

203 (p:(x: 22.5; y: 33.2; z:-23.4); ch1:'C'; ch2:'G'; ch3:' '),

204 (p:(x: 36.7; y: 40.6; z:-45.5); ch1:'C'; ch2:'D'; ch3:'1'),

205 (p:(x: 48.9; y: 47.9; z:-68.2); ch1:'C'; ch2:'D'; ch3:'2'),

206 (p:(x: 32.5; y: 68; z:-39.2); ch1:'N'; ch2:'E'; ch3:'1'),

207 (p:(x: 42; y: 98.6; z: -55); ch1:'C'; ch2:'E'; ch3:'2'),

208 (p:(x: 28.3; y: 93.2; z:-32.9); ch1:'C'; ch2:'E'; ch3:'3'),

209 (p:(x: 16.2; y: 84.3; z:-10.8); ch1:'C'; ch2:'Z'; ch3:'2'),

210 (p:(x: 19.4; y: 59.5; z:-17.1); ch1:'C'; ch2:'Z'; ch3:'3'),

211 (p:(x: 45.1; y: 73.7; z:-61.3); ch1:'C'; ch2:'H'; ch3:'2'));

212 Atoms_Leu_teta: array [1..4] of TAtom = (

213 (p:(x: 8.4; y: 23.3; z: 0 ); ch1:'C'; ch2:'B'; ch3:' '),

214 (p:(x:-26.7; y: 35.7; z: 0 ); ch1:'C'; ch2:'G'; ch3:' '),

215 (p:(x:-32.4; y: 55.2; z: 33.9); ch1:'C'; ch2:'D'; ch3:'1'),

216 (p:(x:-32.4; y: 55.2; z:-27.2); ch1:'C'; ch2:'D'; ch3:'2'));

217 Atoms_Phe: array [1..7] of TAtom = (

218 (p:(x: 8.4; y: 23.3; z: 0 ); ch1:'C'; ch2:'B'; ch3:' '),

219 (p:(x: 24.8; y: 47.3; z:-24.9); ch1:'C'; ch2:'G'; ch3:' '),

220 (p:(x: 35.5; y: 63.1; z: -43); ch1:'C'; ch2:'D'; ch3:'1'),

221 (p:(x: 47.5; y: 50.7; z:-64.6); ch1:'C'; ch2:'E'; ch3:'1'),

222 (p:(x: 48.3; y: 25; z:-66.6); ch1:'C'; ch2:'Z'; ch3:' '),

223 (p:(x: 36.8; y: 10.8; z:-47.8); ch1:'C'; ch2:'E'; ch3:'2'),

224 (p:(x: 26; y: 23.7; z:-26.5); ch1:'C'; ch2:'D'; ch3:'2'));

225 // == < auto converted in Excel > ==========

226 var

227 Atoms: TAtomsArray;

228 slSrc: TStringList;

229 fDNEString: string;

230 fStart, fEnd: integer;

231 fCntr: integer = 0;

232 procedure LoadConst;

233 // var

234 // i: integer;

235 begin

236 { with TIniFile.Create(ExtractFilePath(ParamStr(0))+'NanoWrld.ini') do

237 try

238 with DNE_Angles [1] do begin

Затем, таблица углов DNE, на которые надо поворачивать белок в зависимости от варианта композиции

239 x := ReadInteger ('DNE', 'Angle1X', 100) / 10;

240 y := ReadInteger ('DNE', 'Angle1Y', 300) / 10;

241 z := ReadInteger ('DNE', 'Angle1Z', 970) / 10;

242 end;

243 with DNE_Angles [2] do begin

244 x := ReadInteger ('DNE', 'Angle2X', 0) / 10;

245 y := ReadInteger ('DNE', 'Angle2Y', 1200) / 10;

246 z := ReadInteger ('DNE', 'Angle2Z', 1200) / 10;

247 end;

248 with DNE_Angles [3] do begin

249 x := ReadInteger ('DNE', 'Angle3X', 0) / 10;

250 y := ReadInteger ('DNE', 'Angle3Y', 300) / 10;

251 z := ReadInteger ('DNE', 'Angle3Z', -600) / 10;

252 end;

253 with DNE_Angles [4] do begin

254 x := ReadInteger ('DNE', 'Angle4X', 100) / 10;

255 y := ReadInteger ('DNE', 'Angle4Y', 300) / 10;

256 z := ReadInteger ('DNE', 'Angle4Z', 800) / 10;

257 end;

258 finally

259 Free;

260 end;

261 with TRegIniFile.Create('Software\NanoWorld') do

262 try

263 for i:=1 to 4 do

264 with DNE_Angles[i] do begin

265 x := ReadInteger ('DNE', 'Angle'+IntToStr(i)+'X', round(x*10)) / 10;

266 y := ReadInteger ('DNE', 'Angle'+IntToStr(i)+'Y', round(y*10)) / 10;

267 z := ReadInteger ('DNE', 'Angle'+IntToStr(i)+'Z', round(z*10)) / 10;

268 end;

269 finally

270 Free;

271 end;}

272 end;

Это вот тип атома

007 TGrpIndex = 1..4;

008 TAtom = record

009 p: TVertex;

Атом в себе хранит координаты (четыре буквы максимум)

010 ch1, ch2, ch3: char;

n1 – это номер атома

011 n1: integer;

Ami – это название аминокислоты, к которой относится данный атом.

012 Ami: string[3];

013 end;

TatomsArray – массив атомов переменной длины (динамический массив)

014 TAtomsArray = array of TAtom;

015 const

016 DNE_Angles: array [1..4] of TVertex = (

017 (x: 10; y: 30; z: 97),

018 (x: 0; y:120; z:120),

019 (x: 0; y: 30; z:-60),

020 (x: 10; y: 30; z: 80));

021 DNE_Null: TVertex = (x: 0; y: 0; z: 0);

-Это массив групп поворота (собственно композиционный генетический код)

022 DNE_Groups: array [TGrpIndex, TGrpIndex, TGrpIndex] of TGrpIndex =

023 (((1,2,3,4), (1,3,3,1), (1,2,3,4), (1,2,3,4) ),

024 ((1,2,3,4), (1,3,3,1), (1,2,3,1), (1,3,3,1) ),

025 ((1,2,3,4), (1,1,3,1), (1,3,3,1), (1,1,3,1) ),

026 ((1,2,3,4), (1,3,3,1), (1,2,3,4), (1,2,3,4) ));

-Это простенькая функция, которая преобразует варианты поворота из символьной в цифровую форму

027 _c = 1;

028 _a = 2;

029 _t = 3;

030 _g = 4;

-Ну, что мы со всеми процедурами разобрались?

-Здесь есть еще метод “лоад конст”, про который я тебе не рассказал, который позволяет углы DNE считывать из реестра ини-файла, который я закомментарил для экономии места

-Давай мы это сразу сотрем.

-Все, стерли.

Хэппи энд!

273 procedure ReadSrcRng(Strings: TStrings);

274 var

275 i,pp: integer;

276 s,ss: String;

277 begin

278 for i := 0 to Strings.Count-1 do

279 begin

280 s := Strings[i];

281 if Copy(s, 1, 2) = 'FT' then

282 begin

283 Delete (s, 1, 2);

284 s := TrimLeft (s);

285 if UpperCase(Copy(s, 1, 3)) = 'CDS' then begin

286 Delete (s, 1, 3);

287 s := TrimLeft (s); // '123..6789' - s

288 pp := pos ('.', s); // 4 - pp

289 ss := Copy(s, 1, pp-1); // '123' - ss

290 Delete (s, 1, pp+1); // '6789' - s

291 if Copy(ss, 1, 1) = '<' then Delete (ss, 1, 1);

292 if Copy(s, 1, 1) = '>' then Delete (s, 1, 1);

293 val (ss, fStart, pp);

294 if pp<>0 then fStart := 0;

295 val (s, FEnd, pp);

296 if pp<>0 then fEnd := 0;

297 exit;

298 end;

299 end;

300 end;

301 end;

302 procedure LoadDNESeq (Strings: TStrings);

303 var

304 i: integer;

305 tStr: string;

306 begin

307 i := 0;

308 while (i < Strings.Count) and (Copy(Strings[i], 1, 1) <> ' ') do

309 inc(i);

310 fDNEString := '';

311 while (i < Strings.Count) and (Copy(Strings[i], 1, 1) = ' ') do

312 begin

313 tStr := Trim (Strings[i]);

314 while Pos(' ', tStr) > 0 do

315 Delete (tStr, Pos(' ', tStr), 1);

316 fDNEString := fDNEString + tStr;

317 inc(i);

318 end;

319 end;

320 var

321 offset: TVertex;

322 procedure Rotate (Kind: TGrpIndex);

323 var

324 i: integer;

325 t:Float;

326 tCos,tSin: Extended;

327 begin

328 for i:=0 to Length(atoms)-1 do begin

329 with Atoms[i].p do begin

330 tCos := cos (DNE_Angles[Kind]. x / 180 * pi);

331 tSin := sin (DNE_Angles[Kind]. x / 180 * pi);

332 t := y * tCos - Z * tSin;

333 z := y * tSin + Z * tCos; y := t;

334 tCos := cos (DNE_Angles[Kind]. y / 180 * pi);

335 tSin := sin (DNE_Angles[Kind]. y / 180 * pi);

336 t := z * tCos - x * tSin;

337 x := z * tSin + x * tCos; z := t;

338 tCos := cos (DNE_Angles[Kind]. z / 180 * pi);

339 tSin := sin (DNE_Angles[Kind]. z / 180 * pi);

340 t := x * tCos - y * tSin;

341 y := x * tSin + y * tCos; x := t;

342 x := x + 3;//offset.x*0.1;

343 // y := y + offset.y*0.1;

344 // z := z + offset.z*0.1;

345 end;

346 end;

347 end;

348 procedure CorrectAtom(var p: TVertex);

349 var

350 t:Float;

351 tCos,tSin: Extended;

352 begin

353 with p do

354 begin

355 tCos := cos ( {} -60 {} / 180 * pi);

356 tSin := sin ( {} -60 {} / 180 * pi);

357 t := x * tCos - y * tSin;

358 y := x * tSin + y * tCos; x := t;

359 t := y * 0 - z * 1;

360 z := y * 1 + z * 0; y := t;

361 x := x+80;

362 y := y+9;

363 z := z+11;

364 tCos := cos ( {} 14 {} / 180 * pi);

365 tSin := sin ( {} 14 {} / 180 * pi);

366 t := x * tCos - y * tSin;

367 y := x * tSin + y * tCos; x := t;

368 x := x*0.03;

369 y := y*0.03;

370 z := z*0.03;

371 end;

372 end;

373 procedure AddAtoms (const ami: string; const a: array of TAtom);

374 var

375 i,s: integer;

376 begin

377 s := Length(atoms);

378 SetLength(atoms,Length(atoms)+Length(a));

379 for i := low(a) to high(a) do

380 begin

381 atoms[s+i-low(a)] := a[i];

382 CorrectAtom(atoms[s+i-low(a)].p);

383 atoms[s+i-low(a)].n1 := fCntr;

384 atoms[s+i-low(a)].Ami := ami;

385 end;

386 end;

387 procedure AddTriplet (_1,_2,_3: TGrpIndex);

388 var

389 ami: string[3];

390 begin

391 ami := DNE_AMI[_1,_2,_3];

392 if ami='TKD' then exit; // TKD

393 inc(fCntr);

394 AddAtoms(ami,Atoms_Common);

395 case _1 of

396 _a:

397 case _2 of

398 _a:

399 case _3 of

400 _a: AddAtoms(ami,Atoms_Lys);

401 _c: AddAtoms(ami,Atoms_Asn);

402 _g: AddAtoms(ami,Atoms_Lys);

403 _t: AddAtoms(ami,Atoms_Asn)

404 end;

405 _c:

406 case _3 of

407 _a: AddAtoms(ami,Atoms_Thr);

408 _c: AddAtoms(ami,Atoms_Thr);

409 _g: AddAtoms(ami,Atoms_Thr);

410 _t: AddAtoms(ami,Atoms_Thr)

411 end;

412 _g:

413 case _3 of

414 _a: AddAtoms(ami,Atoms_Arg_bottom);

415 _c: AddAtoms(ami,Atoms_Ser_teta);

416 _g: AddAtoms(ami,Atoms_Arg_bottom);

417 _t: AddAtoms(ami,Atoms_Ser_teta)

418 end;

419 _t:

420 case _3 of

421 _a: AddAtoms(ami,Atoms_Ile);

422 _c: AddAtoms(ami,Atoms_Ile);

423 _g: AddAtoms(ami,Atoms_Met);

424 _t: AddAtoms(ami,Atoms_Ile)

425 end;

426 end;

427 _c:

428 case _2 of

429 _a:

430 case _3 of

431 _a: AddAtoms(ami,Atoms_Gln);

432 _c: AddAtoms(ami,Atoms_His);

433 _g: AddAtoms(ami,Atoms_Gln);

434 _t: AddAtoms(ami,Atoms_His)

435 end;

436 _c:

437 case _3 of

438 _a: AddAtoms(ami,Atoms_Pro);

439 _c: AddAtoms(ami,Atoms_Pro);

440 _g: AddAtoms(ami,Atoms_Pro);

441 _t: AddAtoms(ami,Atoms_Pro)

442 end;

443 _g:

444 case _3 of

445 _a: AddAtoms(ami,Atoms_Arg_top);

446 _c: AddAtoms(ami,Atoms_Arg_top);

447 _g: AddAtoms(ami,Atoms_Arg_top);

448 _t: AddAtoms(ami,Atoms_Arg_top)

449 end;

450 _t:

451 case _3 of

452 _a: AddAtoms(ami,Atoms_Leu_lambda);

453 _c: AddAtoms(ami,Atoms_Leu_lambda);

454 _g: AddAtoms(ami,Atoms_Leu_lambda);

455 _t: AddAtoms(ami,Atoms_Leu_lambda)

456 end;

457 end;

458 _g:

459 case _2 of

460 _a:

461 case _3 of

462 _a: AddAtoms(ami,Atoms_Glu);

463 _c: AddAtoms(ami,Atoms_Asp);

464 _g: AddAtoms(ami,Atoms_Glu);

465 _t: AddAtoms(ami,Atoms_Asp)

466 end;

467 _c:

468 case _3 of

469 _a: AddAtoms(ami,Atoms_Ala);

470 _c: AddAtoms(ami,Atoms_Ala);

471 _g: AddAtoms(ami,Atoms_Ala);

472 _t: AddAtoms(ami,Atoms_Ala)

473 end;

474 _g:

475 case _3 of

476 _a: exit; // AddAtoms(ami,Atoms_Gly);

477 _c: exit; // AddAtoms(ami,Atoms_Gly);

478 _g: exit; // AddAtoms(ami,Atoms_Gly);

479 _t: exit; // AddAtoms(ami,Atoms_Gly);

480 end;

481 _t:

482 case _3 of

483 _a: AddAtoms(ami,Atoms_Val);

484 _c: AddAtoms(ami,Atoms_Val);

485 _g: AddAtoms(ami,Atoms_Val);

486 _t: AddAtoms(ami,Atoms_Val)

487 end;

488 end;

489 _t:

490 case _2 of

491 _a:

492 case _3 of

493 _a: exit; // TKD

494 _c: AddAtoms(ami,Atoms_Tyr);

495 _g: exit; // TKD

496 _t: AddAtoms(ami,Atoms_Tyr)

497 end;

498 _c:

499 case _3 of

500 _a: AddAtoms(ami,Atoms_Ser_teta);

501 _c: AddAtoms(ami,Atoms_Ser_teta);

502 _g: AddAtoms(ami,Atoms_Ser_teta);

503 _t: AddAtoms(ami,Atoms_Ser_teta)

504 end;

505 _g:

506 case _3 of

507 _a: exit; // TKD

508 _c: AddAtoms(ami,Atoms_Cys);

509 _g: AddAtoms(ami,Atoms_Trp);

510 _t: AddAtoms(ami,Atoms_Cys)

511 end;

512 _t:

513 case _3 of

514 _a: AddAtoms(ami,Atoms_Leu_teta);

515 _c: AddAtoms(ami,Atoms_Phe);

516 _g: AddAtoms(ami,Atoms_Leu_teta);

517 _t: AddAtoms(ami,Atoms_Phe)

518 end;

519 end;

520 end;

521 end;

522 function DneToInt (c: Char): TGrpIndex;

523 begin

524 case c of

525 'C','c': Result := 1;

526 'A','a': Result := 2;

257 'T','t': Result := 3;

528 'G','g': Result := 4;

529 else Result := 1;

530 end;

531 end;

532 procedure TranslateDNESeq (Seq: string);

533 var

534 _1,_2,_3: TGrpIndex;

535 begin

536 offset := Atoms_Common[1].p;

537 CorrectAtom(offset);

538 while Length (Seq)>=3 do begin

539 _1 := DneToInt (Seq[1]);

540 _2 := DneToInt (Seq[2]);

541 _3 := DneToInt (Seq[3]);

542 Rotate (DNE_Groups [_1, _2, _3]);

543 AddTriplet (_1, _2, _3);

544 Delete (Seq,1,3);

545 end;

546 end;

547 procedure WriteENT(const dst: string);

548 var

549 i: integer;

550 f: text;

551 s: string;

552 begin

553 Assign(f,dst);

554 Rewrite(f);

555 DecimalSeparator := '.';

556 for i := 0 to Length(Atoms)-1 do

557 with Atoms[i] do

558 begin

559 {

560 ATOM 360 CA CYS 48 21.690 28.114 17.923 1.00 6.00 3 1SN3 447

561 " " " " " " " " " " " "

562 1234567 234 234 2345 23456 23456789012 2345678 2345678 23456 23456 2345678901234

563 12345678901234567890123456789012345678901234567890123456789012345678901234567890

564 }

565 s := 'ATOM ';

566 s := s + Format('%4d',[i]);

567 s := s + ' '+ch1+ch2+ch3;

568 s := s + ' '+Ami;

569 s := s + Format('%6d',[n1]);

570 s := s + Format('%12.2f',[p.x]);

571 s := s + Format('%8.2f',[p.y]);

572 s := s + Format('%8.2f',[p.z]);

573 s := s + Format('%6.2f',[1.00]);

574 s := s + Format('%6.2f',[6.00]);

575 s := s + ' 1SN3';

576 s := s + Format('%4d',[i]);

577 writeln(f,s);

578 end;

579 (* for i := 0 to Length(Lines)-1 do

580 with Lines[i] do

581 begin

582 {

583 CONECT 2 4 7RXN 667

584 " " " " "

585 1234 2345

586 }

587 s := 'CONECT ';

588 s := s + Format('%4d',[b]);

589 s := s + Format('%5d',[e]);

590 s := s + ' 7RXN 667';

591 writeln(f,s);

592 end;*)

593 close(f);

594 end;

595 procedure ProcessFiles(const src,dst: string);

596 var

597 tStr: string;

598 begin

599 slSrc := TStringList.Create;

600 try

601 slSrc.LoadFromFile(src);

602 ReadSrcRng(slSrc);

603 LoadDNESeq(slSrc);

604 tStr := fDNEString;

605 Delete (tStr, fEnd+1, Length(tStr));

606 Delete (tStr, 1, fStart-1);

607 TranslateDNESeq (tStr);

608 //AddLines;

609 WriteENT(dst);

610 finally

611 slSrc.Free;

612 end;

613 end;

По классическей схеме вызывается модуль main.

614 procedure main;

615 var

616 s: string;

617 begin

618 Writeln;

Он в любом случае выводит текст: Copyright.

619 Writeln('(c) 1995-1999 Nanoworld lab., Moscow');

620 Writeln('(c) 1995-1999 A.Yu.Kushelev');

621 Writeln;

Далее, если параметров нет, вызывает помощь,

622 if ParamCount<1 then

623 begin

624 Writeln('Using:');

625 Writeln(' dne2ent source[.dne] [destination.ent]');

626 end else

если параметр один, обрабатывает соответствующий файл,

627 if ParamCount<2 then

628 begin

629 Writeln('Processing...');

630 s := ParamStr(1);

631 if (Length(s)>4)and(s[Length(s)-3]='.')

632 then SetLength(s,Length(s)-4);

633 ProcessFiles(s+'.dne',s+'.ent');

634 Writeln('Done.');

635 end else

а если параметров два, то вызывает программу ProcessFiles с параметром 1 и параметром 2.

636 begin

637 Writeln('Processing...');

Далее, что делает процесс-файлз, что там происходит?

595 procedure ProcessFiles(const src,dst: string);

596 var

597 tStr: string;

598 begin

Сначала загружается стринг-лист (список строчек) из файла СРЦ.

599 slSrc := TStringList.Create;

600 try

Читаем диапазон СРЦ (не СРЦ, а CDS - Си-Ди-Эс)

601 slSrc.LoadFromFile(src);

-А как это происходит?

-При помощи этой процедуры: Нажимает Ctrl и превращаем DELFI в своеобразный браузер.

602 ReadSrcRng(slSrc);

Затем, 603 LoadDNESeq(slSrc); лоад ДНЕ - загружается последовательность. Эта процедура читает кодирующую последовательность по CDS.

603 LoadDNESeq(slSrc);

Затем, сохраняется эта кодирующая последовательность

604 tStr := fDNEString;
Обрезает исходную последовательность в соответствии с CDS, т.е. в соответствии с начальным и конечным индексом, прочитанным вот здесь вот...

605 Delete (tStr, fEnd+1, Length(tStr));

606 Delete (tStr, 1, fStart-1);

и переводит ее в последовательность атомов

607 TranslateDNESeq (tStr);

608 //AddLines;

и затем пишет ent-файл

609 WriteENT(dst);

610 finally

611 slSrc.Free;

612 end;

613 end;

Таким образом, выполнив процедуру 595 procedure ProcessFiles(const src,dst: string); мы возвращаемся в главную программу (main)

638 ProcessFiles(ParamStr(1),ParamStr(2));

И пишем “Все нормально” (Done)

639 Writeln('Done.');

640 end;

641 end;

642 end.

 

 

http://ftp.decsy.ru/nanoworld/index.htm