node-genome
Version:
notion of a biologically inspired genome driven by a gene regulatory network
905 lines (550 loc) • 25.1 kB
JavaScript
"use strict";
module.exports.init = function(spec, my) { // functional inheritance Crockford 2008 pg 52
var path = require('path');
function resolvePath(str) {
if (str.substr(0, 2) === '~/') {
str = (process.env.HOME || process.env.HOMEPATH || process.env.HOMEDIR || process.cwd()) + str.substr(1);
}
return path.resolve(str);
}
var genome_node_obj = require('./genome_node');
var that = {},
spec = spec || { name : "Corinde Wiers"};
my = my || {};
// ---
var shared_utils = require("shared-utils");
// ---
var network_nodes = []; // initialize fresh network
// var network_edges = []; // initialize fresh network
var network_timeseries = []; // each element contains a list of gene nodes which influence that neighborhood
var default_edge_weight = 12;
var max_index_show_dna = 3;
// stens TODO - ignore for now - put in later
// var factor_genometime_to_clocktime = 3052.7; // multiplier mapping from count of timeslices in
// network_timeseries to count of samples in output buffer
var genome_buffer; // output audio buffer
that.genome_buffer = genome_buffer;
var max_samples;
that.max_samples = max_samples;
var name = spec.name;
that.name = name;
that.get_random_float = shared_utils.get_random_in_range_inclusive_float;
/* TODO
ignore stretch factor for both genome_node and genome timeseries ... for now
*/
// ---
var set_random_seed = function(given_seed) {
shared_utils.set_random_seed(given_seed);
};
that.set_random_seed = set_random_seed;
// ---
var show_genome_node = function(given_node) {
// console.log("name\t", given_node.name);
// console.log("says\t", given_node.says());
console.log("nodeid\t", given_node.nodeid);
console.log("nodedata\t", given_node.nodedata);
console.log("factor_stretch\t", given_node.factor_stretch);
console.log("size\t", given_node.size);
// console.log("typeof buffer \t", typeof given_node.buffer);
console.log("buffer length\t", given_node.buffer.length);
var max_index_to_show = 3;
max_index_to_show = (given_node.size < max_index_to_show) ?
given_node.size : max_index_to_show;
for (var index = 0; index < max_index_to_show; index++) {
// console.log(index, " buffer content\t", given_node.buffer[index]);
console.log("%d buffer content ", index, given_node.buffer[index]);
}
console.log("<><><> <><><> <><><>");
};
that.show_genome_node = show_genome_node;
// ---
/*
var get_size_buffer_this_gene = function(given_gene) {
return network_nodes[given_gene]["audio_obj"]["buffer"].length;
};
that.get_size_buffer_this_gene = get_size_buffer_this_gene;
*/
var get_size_buffer_this_gene = function(given_gene) {
return network_nodes[given_gene].buffer.length;
};
that.get_size_buffer_this_gene = get_size_buffer_this_gene;
// ---
// var put_it_here;
/*
var set_value_node_buffer = function(given_gene, given_buffer_index, new_value) {
console.log("PRE set_value_node_buffer ", given_gene, given_buffer_index, new_value);
// var curr_node = network_nodes[given_gene];
// network_nodes[given_gene].audio_obj.buffer[given_buffer_index] = new_value;
network_nodes[given_gene]["audio_obj"]["buffer"][given_buffer_index] = new_value;
console.log("POST set_value_node_buffer ", given_gene, given_buffer_index, new_value,
network_nodes[given_gene].audio_obj.buffer[given_buffer_index],
network_nodes[given_gene]["audio_obj"]["buffer"][given_buffer_index]);
};
that.set_value_node_buffer = set_value_node_buffer;
*/
var set_value_node_buffer = function(given_gene, given_buffer_index, given_value) {
// network_nodes[given_gene].audio_obj.buffer[given_buffer_index] = given_value;
// network_nodes[given_gene].buffer[given_buffer_index] = given_value;
// var curr_node = network_nodes[given_gene];
// curr_node.set_value_buffer(given_buffer_index, given_value);
// network_nodes[given_gene].audio_obj.buffer[given_buffer_index] = given_value;
// put_it_here = given_value;
// console.log("PREEEEEE set_value_node_buffer ", network_nodes[given_gene].buffer[given_buffer_index]);
// console.log("new value ", given_value);
network_nodes[given_gene].buffer[given_buffer_index] = given_value;
// console.log("POOOOST set_value_node_buffer ", network_nodes[given_gene].buffer[given_buffer_index]);
};
that.set_value_node_buffer = set_value_node_buffer;
// ---
var get_value_node_buffer = function(given_gene, given_buffer_index) {
// console.log("TOP get_value_node_buffer");
// console.log("get_value_node_buffer ", given_gene, given_buffer_index);
// console.log(" buffer value ", network_nodes[given_gene].audio_obj.buffer[given_buffer_index]);
// return curr_node.audio_obj.buffer[given_buffer_index];
// return network_nodes[given_gene].audio_obj.buffer[given_buffer_index];
// return put_it_here;
return network_nodes[given_gene].buffer[given_buffer_index];
};
that.get_value_node_buffer = get_value_node_buffer;
// ---
// timeslices : [
// [ {nodeid: 1, weight: 10}, {nodeid: 3, weight: 10} ],
// [ {nodeid: 4, weight: 10} ],
// [ {nodeid: 2, weight: 10}, {nodeid: 0, weight: 10} ],
// ]
var show_genetic_storehouse = function (given_max_index_show_dna) {
console.log("\n\nTOP ................. show_genetic_storehouse .................");
var meso_max_index_show_dna = given_max_index_show_dna || max_index_show_dna;
console.log("meso_max_index_show_dna ", meso_max_index_show_dna);
// console.log("FIRST ... network_timeseries\t", network_timeseries);
console.log("SECOND ... network_nodes");
for (var chronos in network_timeseries) {
var curr_timeslice = network_timeseries[chronos];
// console.log("\n\nchronos ", chronos, " curr_timeslice ", curr_timeslice, "\n\n____");
for (var curr_gene in curr_timeslice) {
var nodedata = curr_timeslice[curr_gene];
var curr_buffer = network_nodes[curr_gene].buffer;
console.log("chronos ", chronos,
// " curr_timeslice ", curr_timeslice,
" curr_gene ", curr_gene,
" buffer.length ", curr_buffer.length,
" nodedata ", nodedata);
var local_max_index_show_dna = meso_max_index_show_dna;
local_max_index_show_dna = (curr_buffer.length < local_max_index_show_dna) ?
curr_buffer.length : local_max_index_show_dna;
console.log("local_max_index_show_dna ", local_max_index_show_dna);
for (var index = 0; index < local_max_index_show_dna; index++) {
console.log("curr_gene ", curr_gene, " buffer index ", index, curr_buffer[index]);
}
}
}
console.log("BOT ................. show_genetic_storehouse .................\n\n");
};
that.show_genetic_storehouse = show_genetic_storehouse;
var show = function(given_label) {
var local_label = given_label || "showing genome ";
console.log("------- now showing network_nodes");
console.log("------- now showing network_nodes");
console.log("------- now showing network_nodes");
for (var curr_nodeid in network_nodes) {
console.log(local_label, " nodeid ", curr_nodeid);
console.log("\nNAME TOOOP --------------");
show_genome_node(network_nodes[curr_nodeid]);
console.log("------------------ BOOOOT\n");
};
/*
console.log("------- now showing network_edges");
console.log("------- now showing network_edges");
console.log("------- now showing network_edges");
for (var nodeid_from in network_edges) {
console.log(local_label, " edge from ", nodeid_from);
for (var nodeid_to in network_edges[nodeid_from]) {
console.log(local_label, " edge nodeid_from ", nodeid_from,
" nodeid_to ", nodeid_to,
" weight ", network_edges[nodeid_from][nodeid_to]);
};
// network_edges[nodeid_from].show_genome_edge();
};
*/
console.log("------- now showing network_timeseries");
console.log("------- now showing network_timeseries");
console.log("------- now showing network_timeseries");
for (var curr_timeslice in network_timeseries) {
console.log("curr_timeslice ", curr_timeslice);
for (var curr_nodeid_in_timeslice in network_timeseries[curr_timeslice]) {
// console.log("curr_timeslice ", curr_timeslice,
// " curr_nodeid_in_timeslice ", curr_nodeid_in_timeslice,
// " aaaaaaaaaaaaa ", network_timeseries[curr_timeslice][curr_nodeid_in_timeslice]);
var curr_nodedata = network_timeseries[curr_timeslice][curr_nodeid_in_timeslice];
console.log("time ", curr_timeslice, " nodeid ", curr_nodeid_in_timeslice,
" weight ", curr_nodedata["weight"], " blah ", curr_nodedata["blah"]);
}
}
};
that.show = show;
var add_node = function(given_new_nodes_json) { // adds to network object
// console.log("yo yo yo");
// console.log(given_new_nodes_json);
// console.log("boo boo boo");
var all_new_nodes = given_new_nodes_json["nodes"];
// console.log("all_new_nodes ", all_new_nodes);
// console.log("iiiiiiiiiiiiiii");
// for (var i = 0; i < Things.length; i++) {
// Things[i]
// };
// show(all_new_nodes, "showing all_new_nodes");
for (var curr_nodeid in all_new_nodes) {
// console.log("nodeid ", curr_nodeid);
// populate buffer for this gene with random points of a curve
var curr_genome_node = genome_node_obj.genome_node({ nodeid: curr_nodeid,
nodedata: all_new_nodes[curr_nodeid],
// nodedata: { size : 2048},
name : "Scott Stensland",
get_random_float : that.get_random_float,
});
if (typeof network_nodes[curr_nodeid] != "undefined") {
var err_msg = "ERROR - you are trying to add duplicate nodeid : " + curr_nodeid;
console.log(err_msg);
process.exit(4);
}
// ---
/*
if (typeof all_new_nodes[curr_nodeid].size === "undefined") {
var err_msg = "ERROR - you must supply spec.nodedata.size";
console.log(err_msg);
process.exit(3);
};
var size = all_new_nodes[curr_nodeid].size;
console.log("NAME size size size ", size);
// curr_genome_node.buffer = new Float32Array(size);
curr_genome_node.buffer = new Float64Array(size);
var curr_value_float;
for (var index = 0; index < size; index++) {
curr_value_float = that.get_random_float(-1.0, 1.0);
console.log("PREEEEE NAME curr_value_float ", curr_value_float);
curr_genome_node.buffer[index] = curr_value_float;
console.log("POSTTTTT NAME curr_genome_node.buffer[index] ", curr_genome_node.buffer[index]);
if (index < 5) {
console.log(index, curr_genome_node.buffer[index]);
}
}
*/
// ---
// console.log("NAME TOP", curr_genome_node.get_node_name(), " BOT");
network_nodes[curr_nodeid] = curr_genome_node;
// console.log("NAME TOP", network_nodes[curr_nodeid].size, " BOT");
// network_nodes[curr_nodeid].show_genome_node();
console.log("about to show_genome_node ", curr_nodeid);
show_genome_node(network_nodes[curr_nodeid]);
}
// console.log("all_new_nodes ------->", all_new_nodes, "<-------");
};
that.add_node = add_node;
// ---
var add_timeslices = function (given_new_timeslices_json) {
var all_new_timeslices = given_new_timeslices_json["timeslices"];
// console.log("all_new_timeslices ", all_new_timeslices);
// ---
if (typeof all_new_timeslices == "undefined") {
console.log("all_new_timeslices is NOT defined so exiting from add_edge ");
return;
};
var size_array = all_new_timeslices.length;
for (var index = 0; index < size_array; index++) {
var curr_value = all_new_timeslices[index];
// console.log("\n\n --------- new timeslice -------------- ");
// console.log(index, " curr_value ", curr_value);
var curr_timeslice = {};
for (var curr_nodedata in curr_value) {
var curr_node_in_timeslice = {};
// console.log(index, " curr_value ", curr_value,
// " curr_nodedata ", curr_value[curr_nodedata]);
var nodeid = curr_value[curr_nodedata]["nodeid"];
if (typeof nodeid == "undefined") {
var err_msg = "ERROR - new timeslice missing tag : nodeid";
console.log(err_msg);
process.exit(6);
};
// ---
var weight = curr_value[curr_nodedata]["weight"];
if (typeof weight == "undefined") {
var err_msg = "ERROR - new timeslice missing tag : weight";
console.log(err_msg);
process.exit(7);
};
// ---
curr_node_in_timeslice["weight"] = weight;
curr_node_in_timeslice["blah"] = 186;
curr_timeslice[nodeid] = curr_node_in_timeslice;
};
network_timeseries[index] = curr_timeslice;
};
// console.log("network_timeseries ", network_timeseries);
};
that.add_timeslices = add_timeslices;
// ---
var pop_direct_genome = function ( total_genes,
total_gene_types,
total_timeslices,
ave_gene_size
) {
console.log("total_nodes ", total_genes);
console.log("total_timeslices ", total_gene_types);
console.log("total_timeslices ", total_timeslices);
console.log("ave_gene_size ", ave_gene_size);
var gene_density = total_genes / total_timeslices;
console.log("gene_density ", gene_density);
console.log("gene_density ", gene_density);
console.log("gene_density ", gene_density);
console.log("gene_density ", gene_density);
var default_gene_size = ave_gene_size;
var default_gene_weight = 10;
var nodes = {};
for (var curr_gene = 0; curr_gene < total_gene_types; curr_gene++) {
nodes[curr_gene] = { size: default_gene_size};
}
console.log("nodes ", nodes);
// ---
var timeslices = [];
for (var curr_chronos = 0; curr_chronos < total_timeslices; curr_chronos++) {
timeslices[curr_chronos] = []; // initialize array element
};
for (var curr_gene_instance = 0; curr_gene_instance < total_genes; curr_gene_instance++) {
// timeslices[curr_chronos] = []; // OK
// timeslices[curr_chronos] = {nodeid: 1, weight: 10}, {nodeid: 3, weight: 10}, {nodeid: 0, weight: 10} ;
var location_new_gene_instance = shared_utils.get_random_in_range_inclusive_int(0, total_timeslices - 1);
var curr_random_gene = shared_utils.get_random_in_range_inclusive_int(0, total_gene_types - 1);
console.log("location_new_gene_instance ", location_new_gene_instance);
timeslices[location_new_gene_instance].push({nodeid : curr_random_gene, weight : default_gene_weight });
};
// timeslices[0] = inner_timeslices;
// timeslices = inner_timeslices;
// console.log("timeslices ", timeslices);
// --- now insert parts into output genome object
var entire_genome = {
"nodes" : nodes,
"timeslices" : timeslices,
};
// console.log("entire_genome ", entire_genome);
add_node(entire_genome);
add_timeslices(entire_genome);
};
that.pop_direct_genome = pop_direct_genome;
// ---
var pop_pointed_genome = function ( total_genes,
total_gene_types,
total_timeslices,
ave_gene_size,
genes_start_time
) {
// populate curves for each gene where start buffer index is given
console.log("total_nodes ", total_genes);
console.log("total_timeslices ", total_gene_types);
console.log("total_timeslices ", total_timeslices);
console.log("ave_gene_size ", ave_gene_size);
console.log("genes_start_time ", genes_start_time);
var default_gene_size = ave_gene_size;
var default_gene_weight = 10;
var nodes = {};
for (var curr_gene = 0; curr_gene < total_gene_types; curr_gene++) {
nodes[curr_gene] = { size: default_gene_size};
}
console.log("nodes ", nodes);
// ---
var timeslices = [];
for (var curr_chronos = 0; curr_chronos < total_timeslices; curr_chronos++) {
timeslices[curr_chronos] = []; // initialize array element
};
for (var curr_gene_instance = 0; curr_gene_instance < total_genes; curr_gene_instance++) {
var location_new_gene_instance;
var curr_random_gene = shared_utils.get_random_in_range_inclusive_int(0, total_gene_types - 1);
// --- does this gene type live in object : genes_start_time
if (typeof genes_start_time[curr_random_gene] !== "undefined") {
console.log("OK cool found curr gene ", curr_random_gene, " inside genes_start_time");
var value_gene_start_time = genes_start_time[curr_random_gene];
console.log("AAAAbout to check value_gene_start_time ", value_gene_start_time);
switch (value_gene_start_time) {
case "middle" : {
console.log("OK now do it value_gene_start_time ", value_gene_start_time);
location_new_gene_instance = ~~(total_timeslices / 2.0);
// console.log("OK location_new_gene_instance ", location_new_gene_instance);
break;
}
// --- default - catch all if not identifed above
default :
console.log("ERROR - invalid value found in genes_start_time : ", value_gene_start_time,
" for gene ", curr_random_gene);
process.exit(8);
break;
}
} else {
console.log("boo hoo failed to find ", curr_random_gene, " inside genes_start_time");
}
// var location_new_gene_instance = shared_utils.get_random_in_range_inclusive_int(0, total_timeslices - 1);
// var location_new_gene_instance = total_timeslices / 2;
// location_new_gene_instance = 128;
// console.log("location_new_gene_instance ", location_new_gene_instance);
timeslices[location_new_gene_instance].push({nodeid : curr_random_gene, weight : default_gene_weight });
};
// timeslices[0] = inner_timeslices;
// timeslices = inner_timeslices;
// console.log("timeslices ", timeslices);
// --- now insert parts into output genome object
var entire_genome = {
"nodes" : nodes,
"timeslices" : timeslices,
};
// console.log("entire_genome ", entire_genome);
add_node(entire_genome);
add_timeslices(entire_genome);
// process.exit(8);
};
that.pop_pointed_genome = pop_pointed_genome;
// ---
var pop_genome = function(spec) {
var spec = spec || {
flavor : "direct",
total_genes : 10,
total_gene_types : 5,
total_timeslices : 100,
ave_gene_size : 10,
};
var flavor = spec.flavor || "boohoo";
console.log('OOOOOOOOOOOOOOOOOO');
console.log('OOOOOOOOOOOOOOOOOO');
console.log('OOOOOOOOOOOOOOOOOO');
console.log('OOOOOOOOOOOOOOOOOO');
console.log("spec ", spec);
console.log("flavor ", spec.flavor);
switch (flavor) {
case "direct" : {
console.log("total_nodes ", spec.total_genes);
console.log("total_timeslices ", spec.total_gene_types);
console.log("total_timeslices ", spec.total_timeslices);
console.log("total_timeslices ", spec.ave_gene_size);
pop_direct_genome( spec.total_genes,
spec.total_gene_types,
spec.total_timeslices,
spec.ave_gene_size
);
break;
};
// ---
case "pointed" : {
console.log("total_nodes ", spec.total_genes);
console.log("total_timeslices ", spec.total_gene_types);
console.log("total_timeslices ", spec.total_timeslices);
console.log("genes_start_time ", spec.genes_start_time);
pop_pointed_genome( spec.total_genes,
spec.total_gene_types,
spec.total_timeslices,
spec.ave_gene_size,
spec.genes_start_time
);
break;
};
// --- default - catch all if not identifed above
default :
console.log("ERROR - you must define spec property : flavor in pop_genome");
process.exit(4);
break;
}
};
that.pop_genome = pop_genome;
// ---
var get_genome_buffer = function() {
return genome_buffer;
};
that.get_genome_buffer = get_genome_buffer;
// ---
var show_genome_buffer = function() {
console.log("TTT _________ show_genome_buffer _________");
var max_chronos_to_show_genome_buffer = 9999999;
max_chronos_to_show_genome_buffer = (genome_buffer.length < max_chronos_to_show_genome_buffer) ?
genome_buffer.length : max_chronos_to_show_genome_buffer;
console.log("genome_buffer.length ", genome_buffer.length);
console.log("max_chronos_to_show_genome_buffer ", max_chronos_to_show_genome_buffer);
for (var index = 0; index < max_chronos_to_show_genome_buffer; index++) {
console.log(index, genome_buffer[index]);
};
console.log("BBB _________ show_genome_buffer _________");
};
that.show_genome_buffer = show_genome_buffer;
// ---
var parse_genome_synth_sound = function() {
// console.log("-----TOP parse_genome_synth_sound ");
var count_num_chronos_in_network_timeseries = network_timeseries.length;
// console.log("count_num_chronos_in_network_timeseries ", count_num_chronos_in_network_timeseries);
// ... put this after below looping which calculates additional leading and lagging sample counts
// convert float into int ... using : x = ~~(somefloat);
// max_samples = ~~(count_num_chronos_in_network_timeseries * factor_genometime_to_clocktime);
max_samples = count_num_chronos_in_network_timeseries;
// console.log("max_samples ", max_samples);
genome_buffer = new Float32Array(max_samples);
// console.log("genome_buffer length ", genome_buffer.length);
// factor_genometime_to_clocktime <-- mapping between count of entries in network_timeseries
// and number of samples in final output buffer
var num_samples_available_prior_to_start_timeseries = 0; // based on width of each gene curve
// very wide gene curves will widen final output
for (var curr_chronos in network_timeseries) {
var curr_timeslice = network_timeseries[curr_chronos];
// console.log("\n\nchronos ", chronos, " curr_timeslice ", curr_timeslice, "\n\n____");
// console.log("\n\n", curr_chronos, " _________________ ",
// num_samples_available_prior_to_start_timeseries, curr_timeslice, "\n\n");
for (var curr_gene in curr_timeslice) {
var nodedata = curr_timeslice[curr_gene];
// console.log("\nnode ", curr_gene, " bbbbbbbbbbbbbbbbbbbbbbb --------------\n");
// console.log("curr_chronos ", curr_chronos,
// // " curr_timeslice ", curr_timeslice,
// " curr_gene ", curr_gene,
// " nodedata ", nodedata);
var curr_buffer = network_nodes[curr_gene].buffer;
// var curr_buffer_size = network_nodes[curr_gene].buffer.length;
var curr_buffer_size = curr_buffer.length;
// console.log("curr_buffer_size ", curr_buffer_size);
// ---
var offset_sample_mid = ~~(curr_buffer_size / 2);
// console.log("offset_sample_mid ", offset_sample_mid);
var curr_buffer_index_minimum = (curr_chronos > offset_sample_mid) ? 0 :
(offset_sample_mid - curr_chronos);
// console.log("curr_buffer_index_minimum ", curr_buffer_index_minimum);
// console.log("curr_chronos ", curr_chronos);
// console.log("curr_buffer_index_minimum ", curr_buffer_index_minimum);
// console.log("offset_sample_mid ", offset_sample_mid);
// var curr_buffer_index_minimum_relative = curr_chronos + curr_buffer_index_minimum - offset_sample_mid;
// console.log("curr_buffer_index_minimum_relative ", curr_buffer_index_minimum_relative);
// var curr_buffer_index_maximum = (max_samples - 1 > curr_buffer_size) ?
// curr_buffer_size :
// (offset_sample_mid + (max_samples - curr_chronos) - 1);
var curr_timeline_min = curr_chronos - (offset_sample_mid - curr_buffer_index_minimum);
// console.log("curr_timeline_min ", curr_timeline_min);
// if (max_samples - 1 - curr_chronos > curr_buffer_size - offset_sample_mid) {
var curr_buffer_index_maximum = (max_samples - curr_chronos >=
curr_buffer_size - offset_sample_mid) ?
curr_buffer_size - 1 :
max_samples - 1 - curr_chronos + offset_sample_mid;
// console.log("curr_buffer_index_maximum ", curr_buffer_index_maximum);
var curr_timeline_max = parseInt(curr_chronos, 10) +
parseInt(curr_buffer_index_maximum, 10) -
parseInt(offset_sample_mid, 10);
// console.log("curr_timeline_max ", curr_timeline_max);
var curr_synth_timeslice = curr_timeline_min;
for (var index = curr_buffer_index_minimum; index <= curr_buffer_index_maximum; index++) {
// console.log(index, curr_synth_timeslice, curr_buffer[index]);
genome_buffer[curr_synth_timeslice] += curr_buffer[index];
curr_synth_timeslice++;
}
}
num_samples_available_prior_to_start_timeseries++;
}
};
that.parse_genome_synth_sound = parse_genome_synth_sound;
// ---
var set_value_buffer = function(given_index, given_value) {
audio_obj.buffer[given_index] = given_value;
console.log(given_value, " vvvvvvvv set_value_buffer ... new value ", audio_obj.buffer[given_index]);
};
that.set_value_buffer = set_value_buffer;
// ---
return that;
};