Skip to content

Commit

Permalink
attempt to correct walking directions for #6
Browse files Browse the repository at this point in the history
  • Loading branch information
kltm committed Aug 2, 2022
1 parent 21ad214 commit 4bc0975
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 10 deletions.
94 changes: 91 additions & 3 deletions lib/graph.js
Original file line number Diff line number Diff line change
Expand Up @@ -1218,6 +1218,8 @@ graph.prototype.get_child_nodes = function(nb_id, in_pred){
};

/**
* Walk up a graph. Object to subject.
*
* Return a list with two nested lists, the first is a list of nodes,
* the second is a list of edges.
*
Expand All @@ -1229,7 +1231,7 @@ graph.prototype.get_child_nodes = function(nb_id, in_pred){
* @param {String} pid - (optional) over this predicate
* @returns {Array} as described above
*/
graph.prototype.walker = function(walking_fun, nb_id_or_list, pid){
graph.prototype.walker_up = function(walking_fun, nb_id_or_list, pid){
var anchor = this;

// Shared data structure to trim multiple paths.
Expand Down Expand Up @@ -1301,6 +1303,92 @@ graph.prototype.walker = function(walking_fun, nb_id_or_list, pid){
];
};

/**
* Walk down a graph. Subject to object.
*
* Return a list with two nested lists, the first is a list of nodes,
* the second is a list of edges.
*
* The argument function takes a node id and 0 or 1 predicates,
* returns a list of edges from the node in question.
*
* @param {Function} walking_fun - function as described above
* @param {String|Array} nb_id_or_list - the node id(s) to consider
* @param {String} pid - (optional) over this predicate
* @returns {Array} as described above
*/
graph.prototype.walker_down = function(walking_fun, nb_id_or_list, pid){
var anchor = this;

// Shared data structure to trim multiple paths.
// Nodes: color to get through the graph quickly and w/o cycles.
var seen_node_hash = {};
// Edges: just listed--hashing would be essentially the same
// as a call to graph.add_edge (I think--benchmark?).
var seen_edge_list = [];

// Define recursive ascent.
function rec_walk(nid){

//console.log('rec_walk on: ' + nid);

var results = [];
//var new_parent_edges = anchor.get_parent_edges(nid, pid);
var new_area_edges = walking_fun.call(anchor, nid, pid);

// Capture edge list for later adding.
each(new_area_edges, function(e){
seen_edge_list.push(e);
});

// Pull extant nodes from edges. NOTE: This is a retread of
// what happens in get_parent_nodes to avoid another call to
// get_parent_edges (as all this is now implemented).
var new_area_nodes = [];
each(new_area_edges, function(edge){
// Make sure that any found edges are in our world.
var sub_id = edge.subject_id();
var temp_node = anchor.get_node(sub_id);
if( temp_node ){
new_area_nodes.push( temp_node );
}
});

// Make sure we're in there too.
var tmp_node = anchor.get_node(nid);
if( tmp_node ){
new_area_nodes.push( tmp_node );
}

// Recur on unseen things and mark the current as seen.
each(new_area_nodes, function(new_node){
// Only do things we haven't ever seen before.
var new_node_id = new_node.id();
if( ! seen_node_hash[ new_node_id ] ){
seen_node_hash[ new_node_id ] = new_node;
rec_walk(new_node_id);
}
});

return results;
}

// Recursive call and collect data from search. Make multiple
// ids possible.
if( us.isArray(nb_id_or_list) ){
each(nb_id_or_list, function(item){
rec_walk(item);
});
}else{
rec_walk(nb_id_or_list);
}

return [
us.values(seen_node_hash),
seen_edge_list
];
};

/**
* Return new ancestors subgraph. Single id or id list as first
* argument. Predicate string/id is optional.
Expand All @@ -1314,7 +1402,7 @@ graph.prototype.get_ancestor_subgraph = function(nb_id_or_list, pid){
var anchor = this;

var walk_results =
anchor.walker(anchor.get_parent_edges, nb_id_or_list, pid);
anchor.walker_up(anchor.get_parent_edges, nb_id_or_list, pid);
var walked_nodes = walk_results[0];
var walked_edges = walk_results[1];

Expand Down Expand Up @@ -1343,7 +1431,7 @@ graph.prototype.get_descendent_subgraph = function(nb_id_or_list, pid){
var anchor = this;

var walk_results =
anchor.walker(anchor.get_child_edges, nb_id_or_list, pid);
anchor.walker_down(anchor.get_child_edges, nb_id_or_list, pid);
var walked_nodes = walk_results[0];
var walked_edges = walk_results[1];

Expand Down
32 changes: 25 additions & 7 deletions tests/go.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ describe('test using GO data', function(){
var go_nodes = null;
var go_edges = null;

// Pre-run.
// Pre-run.
before(function() {
// Remember, we are running from the project root, so relative
// to there (?).
Expand All @@ -35,7 +35,7 @@ describe('test using GO data', function(){
//print('index: ' + n + ' jnode: ' + jnode['id']);
g.add_node(new model.node(jnode['id']));
}

// Add all edges.
// print('all edges len: ' + bbop.model.go.edges.length);
for( var e = 0; e < go_edges.length; e++ ){
Expand All @@ -45,12 +45,12 @@ describe('test using GO data', function(){
jedge['object'],
jedge['predicate']));
}

//
assert.equal(3, g.get_root_nodes().length);//, 'right number of GO roots');
assert.equal(false, g.is_leaf_node('GO:0022008'));//, 'neurogenesis ! a leaf');
assert.equal(true, g.is_leaf_node('GO:0048174'));//, 'but this should be');

// Let's get serious about parents.
var p_hash = {};
var parents = g.get_parent_nodes('GO:0022008');
Expand All @@ -60,7 +60,7 @@ describe('test using GO data', function(){
assert.equal(2, parents.length);//, '2 parents');
assert.equal(true, p_hash['GO:0007399']);//, 'has 1 of 2');
assert.equal(true, p_hash['GO:0030154']);//, 'has 2 of 2');

// Let's get serious about children.
var c_hash = {};
var children = g.get_child_nodes('GO:0022008');
Expand All @@ -73,7 +73,7 @@ describe('test using GO data', function(){
assert.equal(true, c_hash['GO:0050768']);//, 'has 3 of 5');
assert.equal(true, c_hash['GO:0050769']);//, 'has 4 of 5');
assert.equal(true, c_hash['GO:0050767']);//, 'has 5 of 5');

// ファイト!
var sub = g.get_ancestor_subgraph('GO:0022008');
// Roots.
Expand All @@ -93,7 +93,25 @@ describe('test using GO data', function(){
assert.equal('GO:0048869', sub.get_child_nodes('GO:0009987')[0].id());//, 'to proc');
// General.
assert.equal(11, sub.all_nodes().length);//, '11 nodes');


// ファイト II!
var dec = g.get_descendent_subgraph('GO:0022008');
// Roots.
assert.equal(1, dec.get_root_nodes().length);//, '1 sub root');
assert.equal(false, dec.is_root_node('GO:0008150'));//, 'sub root');
assert.equal(false, dec.is_root_node('GO:0032502'));//, '! sub root 1');
assert.equal(true, dec.is_root_node('GO:0022008'));//, '! sub root 2');
// Leaves.
assert.equal(228, dec.get_leaf_nodes().length);//, '1 leaf');
assert.equal(false, dec.is_leaf_node('GO:0022008'));//, 'sub leaf');
// Graph structure up.
assert.equal(0, dec.get_parent_nodes('GO:0008150').length);
assert.equal(0, dec.get_parent_nodes('GO:0022008').length);
assert.equal(0, dec.get_parent_nodes('GO:0030154').length);

// General.
assert.equal(490, dec.all_nodes().length);//, '490 nodes');

});

});

0 comments on commit 4bc0975

Please sign in to comment.