見出し画像

DNA言語研究:だいぶん”間抜け”なサンプルプログラム

だれしもが ”却下” したくなる稚拙なプログラムであります。どどんと後悔します(定番の誤字でありますので、ご容赦ください・・・笑)、そう、あたらしいジャンル「造語:コミカル実験室(プログラミング)」の始まりです。

0.やりたかったこと

前回の投稿

・なんだかDNAやRNAを読んでたら、真似てみたくなって、でも、極少ない空き時間1か月くらいでできることってなんだぁ?って、考えてたら延び延びになって・・・。言い訳はいいか。なので、ちょっとでも ”らしさ” が出せればいいかな。

・本当は、TCP/IPインターネットを介してやるつもりはないのだ。新しい ”世界を血管でつなぐ” システムを創設したい。できるわけないけど・・・。

・とりあへず、UDPで一斉放射的データ送信して、受容体らしきポートを用意して、そこで投げたデータを認識して、一致してたら、なんかするというやつをつくってみた。でもアドレスとか自由にならないから、「おうちにいましょう」的ローカルアドレスで遊んでいます。

1.やっていること

・受容体を模したUDP4サーバーアプリ。(例として、アスパラギン酸コドン:ポート8080 と フェニルアラニンコドン:ポート9999)

・これにオリゴマーを模したテストプログラム(ローカルIPアドレスで、ポートに分けてオリゴマーらしき配列を送信)

・超いいかげんDNAを模したデータ定義(これ、”模した” なんて書いたら絶対叱られる・・・書いちゃってるけど)

2.プログラム(文末に展開)

・言語は、Node.js

・開発環境は、

画像1

3.ショボすぎるけど実行動画

(なんだ、この動画は。「みやすいだろう」と思って切り取ったら横長になりやがったぁ・・・)

4.サンプルプログラム

・の、前に。わたし、ぼちぼち引退しようかとおもうんです。こんなん書いてたんじゃ、だめじゃんねぇ・・・。すべって、ころんで、「おおいたけん」・・・失礼しました。次回は、ライフログで ”喜怒哀楽” を表現するサンプル書くつもり。それで、”稚拙な癖” が治んなかったら・・・亡。(現在、github準備中・・・なので、ベタでベターと張ります・・・笑)

■データ定義

//
// Data Definitions.
//

// This cell type is IP Address, has 127.0.0.1
const cCELL_TYPE_A = '127.0.0.1';
const cRECEPTOR_PORT_PATTERN_ASP = 8080; // codon : aspartic acid : GAUGAC

const cCELL_TYPE_B = '127.0.0.1';
const cRECEPTOR_PORT_PATTERN_PHE = 9999;

// DNA Class.
class clsDNA {
// Construction
//constructor(joy, angry, sad, fun) {
constructor(a, t, g, c) {
this.A = a; //Adenine : 哀? : Sad? : A
this.T = t; //Thymine : 喜? : Joy? : U
this.G = g; //Guanine : 楽? : Fun? : G
this.C = c; //Cytosine : 怒? : Angry? : C
}

Pair() {
let pDNA = new clsDNA(0, 0, 0, 0);
pDNA.A = this.A == 1? 0 : 1;
pDNA.T = this.T == 1 ? 0 : 1;
pDNA.G = this.G == 1 ? 0 : 1;
pDNA.C = this.C == 1 ? 0 : 1;
return pDNA;
}
};

// RNA Class.
class clsRNA {
// Construction
//constructor(joy, angry, sad, fun) {
constructor(a, u, g, c) {
this.A = a; //Adenine : 哀? : Sad? : A
this.U = u; //Uracil : 喜? : Joy? : T
this.G = g; //Guanine : 楽? : Fun? : G
this.C = c; //Cytosine : 怒? : Angry? : C
}

// Transcription RNA
Transcription (oDNA) {
let rna = new clsDNA(0, 0, 0, 0);

if (oDNA instanceof clsDNA) {
// Transcription Processing
rna.A = oDNA.A == 1 ? 0 : 1;
rna.T = oDNA.T == 1 ? 0 : 1;
rna.G = oDNA.G == 1 ? 0 : 1;
rna.C = oDNA.C == 1 ? 0 : 1;
}

return rna;
}
};

// Base Pair Class(BP).
class clsBASE_PAIR {
// Construction
//constructor(upper, lower) {
constructor(upper, lower, title, message) {
this.Upper = upper;
this.Lower = lower;
this.Title = title;
this.Message = message;
}

Processing(title, message) {
// テスト用処理
console.log(title + " " + message);
}
};


// Promoter (example: TATA).
const cPROMOTER_TATA = 'TATA';
var vPromoter = {}
vPromoter[cPROMOTER_TATA] =
[
{ A: 0, T: 1, G: 0, C: 0 },
{ A: 1, T: 0, G: 0, C: 0 },
{ A: 0, T: 1, G: 0, C: 0 },
{ A: 1, T: 0, G: 0, C: 0 }
];


// Codon Table.
const cCODON_START01 = 'Start01';
const cCODON_START02 = 'Start02';
const cCODON_START03 = 'Start03';
const cCODON_ASP = 'Asp';
const cCODON_PHE = 'Phe';
const cCODON_END = 'EndCodon';
var vCodonDefinition = {};
/* [=== for debug */
vCodonDefinition[cCODON_START01] = // AUG
[
{ A: 1, U: 0, G: 0, C: 0 },
{ A: 0, U: 1, G: 0, C: 0 },
{ A: 0, U: 0, G: 1, C: 0 }
];
vCodonDefinition[cCODON_START02] = // AUA
[
{ A: 1, U: 0, G: 0, C: 0 },
{ A: 0, U: 1, G: 0, C: 0 },
{ A: 1, U: 0, G: 0, C: 0 }
];
vCodonDefinition[cCODON_START03] = // GUG
[
{ A: 0, U: 0, G: 1, C: 0 },
{ A: 0, U: 1, G: 0, C: 0 },
{ A: 0, U: 0, G: 1, C: 0 }
];
vCodonDefinition[cCODON_ASP] = // GAU-GCA
[
{ A: 0, U: 0, G: 1, C: 0 },
{ A: 1, U: 0, G: 0, C: 0 },
{ A: 0, U: 1, G: 0, C: 0 },
{ A: 0, U: 0, G: 1, C: 0 },
{ A: 0, U: 0, G: 0, C: 1 },
{ A: 1, U: 0, G: 0, C: 0 }
];
vCodonDefinition[cCODON_PHE] = // UUU-UUC
[
{ A: 0, U: 1, G: 0, C: 0 },
{ A: 0, U: 1, G: 0, C: 0 },
{ A: 0, U: 1, G: 0, C: 0 },
{ A: 0, U: 1, G: 0, C: 0 },
{ A: 0, U: 1, G: 0, C: 0 },
{ A: 0, U: 0, G: 0, C: 1 }
];
vCodonDefinition[cCODON_END] = // UAG-AGA-UAA
[
{ A: 0, U: 1, G: 0, C: 0 },
{ A: 1, U: 0, G: 0, C: 0 },
{ A: 0, U: 0, G: 1, C: 0 },
{ A: 0, U: 1, G: 0, C: 0 },
{ A: 0, U: 0, G: 1, C: 0 },
{ A: 1, U: 0, G: 0, C: 0 },
{ A: 0, U: 1, G: 0, C: 0 },
{ A: 1, U: 0, G: 0, C: 0 },
{ A: 1, U: 0, G: 0, C: 0 }
];
/* */


// DNA Records.
const cRECORD_PROMOTER = 'Promotor';
const cRECORD_START = 'Start';
const cRECORD_DNA = 'DNA';
const cRECORD_END = 'End';
class clsDNARecord {
constructor(promoter, start, dna, end, title, message) {
this.Promotor = promoter;
this.Start = start;
this.DNA = dna;
this.End = end;
this.Title = title;
this.Message = message;
}
};
var vDNARecords = [];
var promt = vPromoter[cPROMOTER_TATA];
var start = vCodonDefinition[cCODON_START01];
var dna = vCodonDefinition[cCODON_ASP];
var endCodon = vCodonDefinition[cCODON_END];
var asp = new clsDNARecord(
promt,
start,
dna,
endCodon,
'ASP',
'***'
);
vDNARecords.push(asp);
dna = vCodonDefinition[cCODON_PHE];
var phe = new clsDNARecord(
promt,
start,
dna,
endCodon,
'PHE',
'***'
);
vDNARecords.push(phe);

var vDNAArray = [];
CreateInformation =
function () {
for (var i = 0; i < vDNARecords.length; i++) {
let record = vDNARecords[i];
for (var j = 0; j < record.Promotor.length; j++) {
let promt = record.Promotor[j];
let cDna = new clsDNA(promt.A, promt.T, promt.G, promt.C);
let pair = new clsBASE_PAIR(cDna, cDna.Pair(), '', '');
vDNAArray.push(pair);
}
for (var j = 0; j < record.Start.length; j++) {
let start = record.Start[j];
let cDna = new clsDNA(start.A, start.U, start.G, start.C);
let pair = new clsBASE_PAIR(cDna, cDna.Pair(), '', '');
vDNAArray.push(pair);
}
for (var j = 0; j < record.DNA.length; j++) {
let dna = record.DNA[j];
let cDna = new clsDNA(dna.A, dna.U, dna.G, dna.C);
let pair = new clsBASE_PAIR(cDna, cDna.Pair(), record.Title, record.Message + i);
vDNAArray.push(pair);
}
for (var j = 0; j < record.End.length; j++) {
let dna = record.End[j];
let cDna = new clsDNA(dna.A, dna.U, dna.G, dna.C);
let pair = new clsBASE_PAIR(cDna, cDna.Pair(), '', '');
vDNAArray.push(pair);
}
}
};
CreateInformation();

UnravelDNA =
function (origomer) {
let dnaIndex = 0;
let reserveIndex = 0;
let origomerCount = origomer.length;
let tataFlag = false;
while (dnaIndex < vDNAArray.length) {
let record;
let origomerIndex = 0;
let cancel = false;

// ...当座、定義通りの配列で実験

if (!cancel && !tataFlag) {
// ...プロモーター処理...
let promt = vPromoter[cPROMOTER_TATA];
let tataIndex = 0;
while (tataIndex < promt.length)
{
record = vDNAArray[dnaIndex];
let dna = promt[tataIndex];
if (
dna.C == record.Upper.C &&
dna.G == record.Upper.G &&
dna.A == record.Upper.A &&
dna.T == record.Upper.T
) {
dnaIndex++;
}
else {
cancel = false;
tataFlag = false;
startFlag = false;
break;
}

tataIndex++;
}

if (tataIndex >= promt.length) {
tataFlag = true;
reserveIndex = dnaIndex;
}
}
else if (tataFlag) {

// ...DNA処理...
while (origomerIndex < origomerCount) {
record = vDNAArray[dnaIndex];
if (
origomer[origomerIndex].C == record.Lower.C &&
origomer[origomerIndex].G == record.Lower.G &&
origomer[origomerIndex].A == record.Lower.A &&
origomer[origomerIndex].T == record.Lower.T
) {

if (record.Title != '' && record.Message != '')
{
record.Processing(record.Title, record.Message);
}

dnaIndex++;
origomerIndex++;
}
else {
cancel = true;
tataFlag = false;
startFlag = false;
dnaIndex = reserveIndex + origomerCount;
origomerIndex = 0;
break;
}
}
}

if (cancel)
continue;
else if (!tataFlag && !startFlag)
dnaIndex++;
}

};


module.exports = {
CELL_TYPE_A: cCELL_TYPE_A,
CELL_TYPE_B: cCELL_TYPE_B,
RECEPTOR_PORT_PATTERN_ASP: cRECEPTOR_PORT_PATTERN_ASP,
RECEPTOR_PORT_PATTERN_PHE: cRECEPTOR_PORT_PATTERN_PHE,
ClassDNA: clsDNA,
ClassRNA: clsRNA,
ClassBasePair: clsBASE_PAIR,
PROMOTER_TATA: cPROMOTER_TATA,
Promoter: vPromoter,
CODON_START01: cCODON_START01,
CODON_START02: cCODON_START02,
CODON_START03: cCODON_START03,
CODON_ASP: cCODON_ASP,
CODON_PHE: cCODON_PHE,
CODON_END: cCODON_END,
CodonDefinition: vCodonDefinition,
RECORD_PROMOTER: cRECORD_PROMOTER,
RECORD_START: cRECORD_START,
RECORD_DNA: cRECORD_DNA,
RECORD_END: cRECORD_END,
DNAArray: vDNAArray
};

■受容体らしきサーバーアプリケーション

//
// 細胞例)二つの受容体を持つ細胞
//

const dgram = require('dgram');

//
// Data Definitions.
//

var def = require('./defines.js');

//
// Programing Areas.
//

var message = '';

// 受容体例)アスパラギン酸コドン:ポート8080
const socketASP = dgram.createSocket('udp4');
socketASP.on('listening', () => {
const address = socketASP.address();
console.log('ASP socket listening on ' + address.address + ":" + address.port);
});
socketASP.on('message', (message, remote) => {
console.log('ASP [ ' + remote.address + ':' + remote.port + ' - ' + message + ' ]');

let response = '';
try {
// RNA creation.
let listRNA = [];
let listOligomer = JSON.parse(message);
for (var i = 0; i < listOligomer.length; i++){
let olg = listOligomer[i];
let cRNA = new def.ClassRNA(0, 0, 0, 0);
for (var j = 0; j < olg.length; j++) {
let cDNA = new def.ClassDNA(olg[j].A, olg[j].U, olg[j].G, olg[j].C)
let rna = cRNA.Transcription(cDNA);
listRNA.push(rna);
}
}
//response = 'Gets RNA ( ' + JSON.stringify(listRNA) + ' ) at ASP.';

// 自身のDNAから、ASPとオリゴマーを紐付ける。紐付けられなかったら、無視。
// 紐付いたら、解いて機能を発現。
UnravelDNA(listRNA);
}
catch (err) {
response = 'Message from ASP about Unknown( ' + message + ' ).';
console.log(err)
}
if (response != '') {
console.log(response);
}

//if (response != '') {
// socketASP.send(response, 0, response.length, remote.port, remote.address, (err, bytes) => { if (err) console.log(err) });
//}
});
socketASP.bind(def.RECEPTOR_PORT_PATTERN_ASP, def.CELL_TYPE_A);

// 受容体例)フェニルアラニンコドン:ポート9999
const socketPHE = dgram.createSocket('udp4');
socketPHE.on('listening', () => {
const address = socketPHE.address();
console.log('PHE socket listening on ' + address.address + ":" + address.port);
});
socketPHE.on('message', (message, remote) => {
console.log('PHE [ ' + remote.address + ':' + remote.port + ' - ' + message + ' ]');

let response = '';
try {
// RNA creation.
let listRNA = [];
let listOligomer = JSON.parse(message);
for (var i = 0; i < listOligomer.length; i++) {
let olg = listOligomer[i];
let cRNA = new def.ClassRNA(0, 0, 0, 0);
for (var j = 0; j < olg.length; j++) {
let cDNA = new def.ClassDNA(olg[j].A, olg[j].U, olg[j].G, olg[j].C)
let rna = cRNA.Transcription(cDNA);
listRNA.push(rna);
}
}
//response = 'Gets RNA ( ' + JSON.stringify(listRNA) + ' ) at PHE.';

// 自身のDNAから、PHEとオリゴマーを紐付ける。紐付けられなかったら、無視。
// 紐付いたら、解いて機能を発現。
UnravelDNA(listRNA);
}
catch (err) {
response = 'Message from PHE about Unknown( ' + message + ' ).';
console.log(err)
}
if (response != '') {
console.log(response);
}

//if (response != '') {
// socketPHE.send(response, 0, response.length, remote.port, remote.address, (err, bytes) => { if (err) console.log(err) });
//}
});
socketPHE.bind(def.RECEPTOR_PORT_PATTERN_PHE, def.CELL_TYPE_B);

//
// User Interface Areas.
//

const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});

const promptMessage = 'Ends input key as "Q"... \n';
var answer = '';
var prompt = promptMessage;

const commandProc = async () => {
function readCommand(question) {
return new Promise((resolve, reject) => {
readline.question(question, (answer) => {
if (answer == 'Q') {
reject(new Error(answer));
}
else {
resolve(answer);
}
});
});
};

while (prompt != '') {

// Waiting input key...
await readCommand(prompt).then(
function (inputData) {
if (inputData == '?') {
// Command help...
}
else {
// something processing...
}
}
).catch(
function (inputData) {
prompt = '';
}
);
}

//
// Termination Processing Areas.
//
readline.close();
readline.removeAllListeners();

socketASP.close();
socketPHE.close();
process.exit(0);
};

// Starts program.
commandProc();

■オリゴマーらしきテストプログラム

//
// 細胞機能発現テスト用
// オリゴマーによる機能発現を試みる。
//

const dgram = require('dgram');

var def = require('../defines.js');

//
// Programing Areas.
//

var message = '';

// This cell type is IP Address, has 127.0.0.1
const CELL_TYPE_TEST = '127.0.0.1';
const RECEPTOR_PORT_PATTERN_TEST = 8888;

const socketTest = dgram.createSocket('udp4');
socketTest.on('message', (message, remote) => {
console.log('Test [ ' + remote.address + ' : ' + remote.port + ' - ' + message + ' ]');
});
socketTest.bind(RECEPTOR_PORT_PATTERN_TEST, CELL_TYPE_TEST);


//
// User Interface Areas.
//

const readline = require('readline').createInterface({
input: process.stdin,
output: process.stdout
});

const promptMessage = 'Command input (Ends as "Q". or "?") ... ';
var answer = '';
var prompt = promptMessage;

const commandProc = async () => {
function readCommand(question) {
return new Promise((resolve, reject) => {
readline.question(question, (answer) => {
if (answer == 'Q') {
reject(new Error(answer));
}
else {
resolve(answer);
}
});
});
};

while (prompt != '') {

// Waiting input key...
await readCommand(prompt).then(
function (inputData) {
if (inputData == '?') {
// Command help...
console.log('Command example are ..."' + def.CODON_ASP + '" or "' + def.CODON_PHE + '"');
}
else {
console.log(message);
message = '';

// DNAオリゴマー生成
if (inputData == def.CODON_ASP || inputData == def.CODON_PHE) {
var listOligomer = [];
listOligomer.push(def.CodonDefinition[def.CODON_START01]);
if (inputData == def.CODON_ASP) {
listOligomer.push(def.CodonDefinition[def.CODON_ASP]);
}
else if (inputData == def.CODON_PHE) {
listOligomer.push(def.CodonDefinition[def.CODON_PHE]);
}
listOligomer.push(def.CodonDefinition[def.CODON_END]);
var sOligomer = JSON.stringify(listOligomer);
console.log(sOligomer);
const request = new Buffer.from(sOligomer);

// [=== DNAオリゴマー放出:本当は、ポートやアドレスを特定せずに送りたいところ。
socketTest.send(request, 0, request.length, def.RECEPTOR_PORT_PATTERN_ASP, def.CELL_TYPE_A, (err, bytes) => {
if (err) throw err;
});
//socketTest.send(request, 0, request.length, def.RECEPTOR_PORT_PATTERN_PHE, def.CELL_TYPE_B, (err, bytes) => {
// if (err) throw err;
//});
// ===]
}
else {
console.log('Unknown Command.')
}
}
}
).catch(
function (inputData) {
prompt = '';
}
);
}

//
// Termination Processing Areas.
//
readline.close();
readline.removeAllListeners();

socketTest.close();
process.exit(0);
};

// Starts program.
commandProc();

この記事が気に入ったらサポートをしてみませんか?