Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added 'deepforge.image(<name>, <tensor>)' support. Fixes #519 #575

Merged
merged 1 commit into from
Jul 30, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/common/Constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ define({

// DeepForge metadata creation in dist execution
START_CMD: 'deepforge-cmd',

IMAGE: 'IMG',

GRAPH_CREATE: 'GRAPH',
GRAPH_PLOT: 'PLOT',
GRAPH_CREATE_LINE: 'LINE'
Expand Down
73 changes: 57 additions & 16 deletions src/plugins/ExecuteJob/ExecuteJob.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ define([
name,
id,
idsToDelete = [],
type,
base,
child;

this.lastAppliedCmd[nodeId] = 0;
Expand All @@ -142,9 +144,16 @@ define([
if (this.isMetaTypeOf(child, this.META.Metadata)) {
id = this.core.getPath(child);
name = this.core.getAttribute(child, 'name');
base = this.core.getBase(child);
type = this.core.getAttribute(base, 'name');

this._markForDeletion[nodeId][id] = child;
this._oldMetadataByName[nodeId][name] = id;
// namespace by metadata type
if (!this._oldMetadataByName[nodeId][type]) {
this._oldMetadataByName[nodeId][type] = {};
}

this._oldMetadataByName[nodeId][type][name] = id;

// children of metadata nodes get deleted
idsToDelete = idsToDelete
Expand Down Expand Up @@ -314,13 +323,13 @@ define([
);

config = {
cmd: 'bash',
args: ['run.sh'],
cmd: 'node',
args: ['start.js'],
outputInterval: OUTPUT_INTERVAL,
resultArtifacts: outputs
};
files['executor_config.json'] = JSON.stringify(config, null, 4);
files['run.sh'] = Templates.BASH;
files['start.js'] = _.template(Templates.START)(CONSTANTS);

// Save the artifact
// Remove empty hashes
Expand Down Expand Up @@ -879,23 +888,14 @@ define([
ExecuteJob.prototype[CONSTANTS.GRAPH_CREATE] = function (job, id) {
var graph,
name = Array.prototype.slice.call(arguments, 2).join(' '),
jobId = this.core.getPath(job),
oldMetadata = this._oldMetadataByName[jobId],
oldId;
jobId = this.core.getPath(job);

id = jobId + '/' + id;
this.logger.info(`Creating graph ${id} named ${name}`);

// Check if the graph already exists
if (oldMetadata && oldMetadata[name]) {
oldId = oldMetadata[name];
graph = this._markForDeletion[jobId][oldId];

// Reset points
this.core.setAttribute(graph, 'points', '');

delete this._markForDeletion[jobId][oldId];
} else { // create new graph
graph = this._getExistingMetadata(jobId, 'Graph', name);
if (!graph) {
graph = this.core.createNode({
base: this.META.Graph,
parent: job
Expand Down Expand Up @@ -948,5 +948,46 @@ define([
this._metadata[jobId + '/' + id] = line;
};

ExecuteJob.prototype[CONSTANTS.IMAGE] = function (job, hash) {
var jobId = this.core.getPath(job),
name = Array.prototype.slice.call(arguments, 2).join(' '),
id = jobId + '/IMAGE/' + name,
imageNode = this._metadata[id]; // Look for the metadata imageNode

id = jobId + '/' + id;
this.logger.info(`Creating graph ${id} named ${name}`);

if (!imageNode) {

// Check if the imageNode already exists
imageNode = this._getExistingMetadata(jobId, 'Image', name);
if (!imageNode) {
imageNode = this.core.createNode({
base: this.META.Image,
parent: job
});
this.core.setAttribute(imageNode, 'name', name);
}
this._metadata[id] = imageNode;
}

this.core.setAttribute(imageNode, 'data', hash);
};

ExecuteJob.prototype._getExistingMetadata = function (jobId, type, name) {
var oldMetadata = this._oldMetadataByName[jobId] &&
this._oldMetadataByName[jobId][type],
node,
id;

if (oldMetadata && oldMetadata[name]) {
id = oldMetadata[name];
node = this._markForDeletion[jobId][id];
delete this._markForDeletion[jobId][id];
}

return node || null;
};

return ExecuteJob;
});
18 changes: 18 additions & 0 deletions src/plugins/ExecuteJob/templates/deepforge.ejs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ function deepforge._cmd(...)
print(cmd)
end

-- Graph support
Graph = torch.class('deepforge.Graph')

function Graph:__init(name)
Expand All @@ -43,4 +44,21 @@ function Graph:line(name, opts)
return deepforge._Line(self.id, name, opts)
end

-- Image support
function deepforge.image(name, tensor)
require 'image'
require 'paths'

-- save it in the tmp directory
local filename = name .. '.png'
local path = paths.concat('metadata', filename)

if paths.dir('metadata') == nil then
paths.mkdir('metadata')
end

image.save(path, tensor)
deepforge._cmd("<%= IMAGE %>", name)
end

return deepforge
5 changes: 3 additions & 2 deletions src/plugins/ExecuteJob/templates/index.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
/*globals define*/
define([
'text!./start.ejs',
'text!./entry.ejs',
'text!./main.ejs',
'text!./deepforge.ejs',
'text!./serialize.ejs',
'text!./deserialize.ejs'
], function(
START,
ENTRY,
MAIN,
DEEPFORGE,
SERIALIZE,
DESERIALIZE
) {

var BASH = 'th init.lua 2>&1';
return {
BASH,
START,
ENTRY,
MAIN,
SERIALIZE,
Expand Down
81 changes: 81 additions & 0 deletions src/plugins/ExecuteJob/templates/start.ejs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// A wrapper for the torch script which:
// - merges stdout, stderr
// - receives some commands and uploads intermediate data
var spawn = require('child_process').spawn,
fs = require('fs'),
log = console.error,
logger = {};

// Create the stderr only logger
['error', 'warn', 'info', 'log', 'debug'].forEach(method => logger[method] = log);

// Get the BlobClient...
var COMMAND_PREFIX = '<%= START_CMD %>',
IMAGE = '<%= IMAGE %>',
requirejs = require('webgme').requirejs;

requirejs([
'blob/BlobClient'
], function(
BlobClient
) {
var url = process.env.ORIGIN_URL || 'http://127.0.0.1:8888',
protocol = url.split('://').shift(),
address,
port = (url.split(':') || ['80']).pop();

address = url.replace(protocol + '://', '')
.replace(':' + port, '');

var blobClient = new BlobClient({
server: address,
httpsecure: protocol === 'https',
serverPort: port,
logger: logger
});

var uploadImage = function(line) {
var args = line.split(/\s+/),
name = args.slice(2).join(' ').replace(/\s+$/, ''),
filename = 'metadata/' + name + '.png';

// Upload the image from metadata/
fs.readFile(filename, (err, content) => {
if (err) {
console.error(`Could not read ${filename}: ${err}`);
return;
}

// Add hash to the image command
blobClient.putFile(filename, content)
.then(hash => {
args.splice(2, 0, hash);
console.log(args.join(' '));
})
.fail(err => console.error(`${filename} upload failed: ${err}`));
});
};

var onStdout = function(data) {
var lines = data.toString().split('\n'),
result = [],
cmdStart;

// Check for commands...
for (var i = 0; i < lines.length; i++) {
cmdStart = lines[i].indexOf(COMMAND_PREFIX);
if (cmdStart !== -1 && lines[i].indexOf(IMAGE) !== -1) {
uploadImage(lines[i]);
} else {
result.push(lines[i]);
}
}

process.stdout.write(result.join('\n'));
};

// Run 'th init.lua' and merge the stdout, stderr
var job = spawn('th', ['init.lua']);
job.stdout.on('data', onStdout);
job.stderr.on('data', data => process.stdout.write(data));
});
Binary file modified src/seeds/cifar10/cifar10.webgmex
Binary file not shown.
Binary file modified src/seeds/pipeline/pipeline.webgmex
Binary file not shown.
Binary file modified src/seeds/project/project.webgmex
Binary file not shown.
Binary file modified src/seeds/xor/xor.webgmex
Binary file not shown.
6 changes: 6 additions & 0 deletions src/visualizers/Visualizers.json
Original file line number Diff line number Diff line change
Expand Up @@ -88,5 +88,11 @@
"title": "LineGraph",
"panel": "panels/LineGraph/LineGraphPanel",
"DEBUG_ONLY": false
},
{
"id": "ImageViewer",
"title": "ImageViewer",
"panel": "panels/ImageViewer/ImageViewerPanel",
"DEBUG_ONLY": false
}
]
Loading