#include "dtlang.h"
using namespace std;
struct strCmp {
bool operator()( const std::string &s1, const std::string &s2 ) const {
return strcmp( s1.c_str(), s2.c_str() ) < 0;
}
};
namespace dtlang {
map<std::string, function_def> functions;
map<std::string, variable_def> vars;
map<std::string, variable_def> statements;
map<int, std::string> type_names;
}
void dtlang::initialize()
{
dtlang::initialize_variables();
dtlang::initialize_functions();
}
bool dtlang::params_to_variables(dtlang::parameters ¶ms, vector<dtlang::variable_def> &var_params, bool &end_input)
{
var_params.resize(params.size());
dtlang::parameters::iterator param_iter;
int count = 0;
for (param_iter = params.begin(); param_iter != params.end(); ++param_iter) {
if (!dtlang::parse_statement(*param_iter, var_params[count], true, true, end_input))
{
// Something bad happened
// Clean up the work we've already done.
for (int i = 0; i < count -1; i++) {
dtlang::delete_variable(var_params[i]);
}
cout << "Unable to parse " << *param_iter << endl << endl;
return false;
}
++count;
}
return true;
}
bool dtlang::parse(const std::string &str, bool &end_input) {
if (str == "") return true;
bool r;
std::string::const_iterator iter, end;
// Check if it is a comment
dtlang::comment_parser<std::string::const_iterator> pComment;
iter = str.begin();
end = str.end();
r = phrase_parse(iter, end, pComment, boost::spirit::ascii::space);
if (r && iter == end) {
return true;
}
// Check if it is an assignment
dtlang::assignment_parser<std::string::const_iterator> pAssignment;
dtlang::variable_assign var;
iter = str.begin();
end = str.end();
r = phrase_parse(iter, end, pAssignment, boost::spirit::ascii::space, var);
if (r && iter == end) {
// It is an assignment!
iter = var.value.begin();
end = var.value.end();
dtlang::variable_def new_var;
if (dtlang::parse_statement(var.value, new_var, true, true, end_input)) {
if (dtlang::vars.find(var.name) != dtlang::vars.end()) dtlang::delete_variable(dtlang::vars[var.name]);
dtlang::vars[var.name] = new_var;
return true;
}
cout << "Syntax error: " << var.value << endl << endl;
return false;
}
// Perhaps it's just a function call?
dtlang::variable_def dud_var; // A place holder
if (!dtlang::parse_statement(str, dud_var, false, false, end_input))
{
/* Failed To Parse */
std::string::const_iterator some = iter+30;
std::string context(iter, (some>end)?end:some);
cout << "Syntax error: \"" << context << "...\"" << endl << "Type \"help()\" for assistance." << endl << endl;
return false;
}
if (dud_var.type != dtlang::NO_RETURN && dud_var.type != dtlang::TYPE_VOID) {
dtlang::delete_variable(dud_var);
}
return true;
}
bool dtlang::parse_statement(const std::string &str, variable_def &var, const bool assignment, const bool make_copy, bool &end_input) {
bool r;
std::string::const_iterator iter = str.begin();
std::string::const_iterator end = str.end();
// Is it a function?
dtlang::function_parser<std::string::const_iterator> pFunction;
dtlang::function_call func;
r = phrase_parse(iter, end, pFunction, boost::spirit::ascii::space, func);
if (r && iter == end) {
if (func.first_param != "") { func.params.insert(func.params.begin(), (std::string)func.first_param); }
void *ret;
int r_type = dtlang::NO_RETURN;
if (assignment) r_type = dtlang::TYPE_VOID;
vector<dtlang::variable_def> var_params;
if (!dtlang::params_to_variables(func.params, var_params, end_input)) return false;
bool run_result = dtlang::runFunction(func.name, var_params, ret, r_type, end_input);
var.type = r_type;
var.obj = ret;
// Clean up the parameters
vector<dtlang::variable_def>::iterator iter;
for (iter = var_params.begin(); iter != var_params.end(); ++iter) {
dtlang::delete_variable(*iter);
}
if (func.name == "quit") { end_input = true; }
return true;
}
// Is it a string?
dtlang::string_parser<std::string::const_iterator> pString;
iter = str.begin();
end = str.end();
std::string *str_val = new std::string();
r = phrase_parse(iter, end, pString, boost::spirit::ascii::space, *str_val);
if (r && iter == end) { var.type = dtlang::TYPE_STRING; var.obj = str_val; return true; }
delete str_val;
// Is it a double?
dtlang::double_parser<std::string::const_iterator> pDouble;
iter = str.begin();
end = str.end();
double *double_val = new double();
r = phrase_parse(iter, end, pDouble, boost::spirit::ascii::space, *double_val);
if (r && iter == end) { var.type = dtlang::TYPE_DOUBLE; var.obj = double_val; return true; }
delete double_val;
// Is it an integer?
dtlang::integer_parser<std::string::const_iterator> pInteger;
iter = str.begin();
end = str.end();
int *int_val = new int();
r = phrase_parse(iter, end, pInteger, boost::spirit::ascii::space, *int_val);
if (r && iter == end) { var.type = dtlang::TYPE_INT; var.obj = int_val; return true; }
delete int_val;
// Is it a statement?
if (dtlang::statements.find(str) != dtlang::statements.end()) {
if (make_copy) {
variable_def oldvar = dtlang::statements[str];
var.type = oldvar.type;
switch(oldvar.type) {
case dtlang::TYPE_STRING:
var.obj = new std::string(*(static_cast<std::string*>(oldvar.obj)));
break;
case dtlang::TYPE_INT:
var.obj = new int(*(static_cast<int*>(oldvar.obj)));
break;
case dtlang::TYPE_DOUBLE:
var.obj = new double(*(static_cast<double*>(oldvar.obj)));
break;
default:
cout << "Unable to determine statement type for copying." << endl;
return false;
break;
}
} else {
var = dtlang::statements[str];
return true;
}
return true;
}
// We'll assume it's a variable
if (dtlang::vars.find(str) != dtlang::vars.end()) {
if (make_copy) {
variable_def oldvar = dtlang::vars[str];
var.type = oldvar.type;
switch(oldvar.type) {
case dtlang::TYPE_STRING:
var.obj = new std::string(*(static_cast<std::string*>(oldvar.obj)));
break;
case dtlang::TYPE_INT:
var.obj = new int(*(static_cast<int*>(oldvar.obj)));
break;
case dtlang::TYPE_DOUBLE:
var.obj = new double(*(static_cast<double*>(oldvar.obj)));
break;
case dtlang::TYPE_TRIAL:
var.obj = new Trial(*(static_cast<Trial*>(oldvar.obj)));
break;
case dtlang::TYPE_NET:
var.obj = new Net(*(static_cast<Net*>(oldvar.obj)));
break;
case dtlang::TYPE_RESULTS:
var.obj = new Results(*(static_cast<Results*>(oldvar.obj)));
break;
case dtlang::TYPE_SIMULATION:
var.obj = new Simulation(*(static_cast<Simulation*>(oldvar.obj)));
break;
case dtlang::TYPE_POPULATION:
var.obj = new Population(*(static_cast<Population*>(oldvar.obj)));
break;
default:
cout << "Unable to determine variable type for copying." << endl;
return false;
break;
}
} else {
// We create a new variable
// But the *obj pointer is the same
// So any changes to this variable change the first
var = dtlang::vars[str];
}
return true;
}
return false;
}
void dtlang::initialize_variables()
{
dtlang::variable_def v;
dtlang::type_names[dtlang::TYPE_VOID] = "Void";
dtlang::type_names[dtlang::TYPE_ANY] = "*ANY*";
dtlang::type_names[dtlang::TYPE_DOUBLE] = "Double";
dtlang::type_names[dtlang::TYPE_INT] = "Integer";
dtlang::type_names[dtlang::TYPE_POPULATION] = "Population";
dtlang::type_names[dtlang::TYPE_STRING] = "String";
dtlang::type_names[dtlang::TYPE_TRIAL] = "Trial";
dtlang::type_names[dtlang::TYPE_NET] = "Net";
dtlang::type_names[dtlang::TYPE_SIMULATION] = "Simulation";
dtlang::type_names[dtlang::TYPE_RESULTS] = "Results";
v.type = dtlang::TYPE_DOUBLE;
v.obj = new double(0);
dtlang::statements["false"] = v;
v.type = dtlang::TYPE_DOUBLE;
v.obj = new double(1);
dtlang::statements["true"] = v;
}
void dtlang::initialize_functions()
{
dtlang::function_def f;
dtlang::function_param p;
// quit()
f.help = "Quit to the command prompt.";
f.return_type = dtlang::TYPE_VOID;
f.params.clear();
dtlang::functions["quit"] = f;
// help()
f.help = "Display general usage information or help for a particular function.";
f.return_type = dtlang::TYPE_VOID;
f.params.clear();
p.type = dtlang::TYPE_STRING;
p.help = "Name of the function to get help for.";
p.optional = true;
p.name = "name";
f.params.push_back(p);
dtlang::functions["help"] = f;
// set()
f.help = "Set a system configuration variable.";
f.return_type = dtlang::TYPE_VOID;
f.params.clear();
p.type = dtlang::TYPE_STRING;
p.help = "Variable name";
p.optional = false;
p.name = "variable";
f.params.push_back(p);
p.type = dtlang::TYPE_DOUBLE;
p.help = "Variable value";
p.optional = false;
p.name = "value";
f.params.push_back(p);
dtlang::functions["set"] = f;
// modsim()
f.help = "Modify a simulation parameter with a single value after it has been loaded.";
f.return_type = dtlang::TYPE_SIMULATION;
f.params.clear();
p.type = dtlang::TYPE_SIMULATION;
p.help = "Simulation to modify.";
p.optional = false;
p.name = "simulation";
f.params.push_back(p);
p.type = dtlang::TYPE_STRING;
p.help = "Parameter ID";
p.optional = false;
p.name = "ID";
f.params.push_back(p);
p.type = dtlang::TYPE_DOUBLE;
p.help = "Value of the parameter";
p.optional = false;
p.name = "value";
f.params.push_back(p);
dtlang::functions["modsim"] = f;
//modsimr()
f.help = "Modify a simulation parameter with a range of values after it has been loaded.";
f.return_type = dtlang::TYPE_SIMULATION;
f.params.clear();
p.type = dtlang::TYPE_SIMULATION;
p.help = "Simulation to modify.";
p.optional = false;
p.name = "simulation";
f.params.push_back(p);
p.type = dtlang::TYPE_STRING;
p.help = "Parameter ID";
p.optional = false;
p.name = "ID";
f.params.push_back(p);
p.type = dtlang::TYPE_DOUBLE;
p.help = "Value of the range start.";
p.optional = false;
p.name = "start";
f.params.push_back(p);
p.type = dtlang::TYPE_DOUBLE;
p.help = "Value of the range end.";
p.optional = false;
p.name = "end";
f.params.push_back(p);
p.type = dtlang::TYPE_DOUBLE;
p.help = "Value of the range step value.";
p.optional = false;
p.name = "step";
f.params.push_back(p);
dtlang::functions["modsimr"] = f;
// vars()
f.help = "List the variables currently stored in the register.";
f.return_type = dtlang::TYPE_VOID;
f.params.clear();
dtlang::functions["vars"] = f;
// version()
f.help = "Display the current version.";
f.return_type = dtlang::TYPE_VOID;
f.params.clear();
dtlang::functions["version"] = f;
// funcs()
f.help = "List the functions available for use.";
f.return_type = dtlang::TYPE_VOID;
f.params.clear();
dtlang::functions["funcs"] = f;
// benchmark()
f.help = "Run a simple, multi-threaded benchmarking function.";
f.return_type = dtlang::TYPE_VOID;
f.params.clear();
p.type = dtlang::TYPE_DOUBLE;
p.help = "Number of times to run the benchmark. Higher numbers result in longer benchmark times.";
p.optional = true;
p.def = "1";
p.name="multiplier";
f.params.push_back(p);
dtlang::functions["benchmark"] = f;
// simulation()
f.help = "Initalize a simulation with a particular network.";
f.return_type = dtlang::TYPE_SIMULATION;
f.params.clear();
p.type = dtlang::TYPE_STRING;
p.help = "Filename of a network XML file.";
p.optional = false;
p.name = "network";
f.params.push_back(p);
p.type = dtlang::TYPE_STRING;
p.help = "Filename of a trial XML file.";
p.optional = false;
p.name = "trial";
f.params.push_back(p);
dtlang::functions["simulation"] = f;
// run()
f.help = "Run the current simulation. Will only work if at least one population has an input connected.";
f.return_type = dtlang::TYPE_RESULTS;
f.params.clear();
p.type = dtlang::TYPE_SIMULATION;
p.help = "The simulation you wish to run.";
p.optional = false;
p.name="simulation";
f.params.push_back(p);
p.type = dtlang::TYPE_STRING;
p.help = "Filename to save results to.";
p.optional = false;
p.name="filename";
f.params.push_back(p);
p.type = dtlang::TYPE_INT;
p.help = "Number of simulations to run for each input vector.";
p.optional = false;
p.name = "number_of_trials";
f.params.push_back(p);
p.type = dtlang::TYPE_DOUBLE;
p.help = "Number of milliseconds to delay before time zero and the start of a trial.";
p.optional = true;
p.def = "10";
p.name = "delay";
f.params.push_back(p);
p.type = dtlang::TYPE_INT;
p.help = "Set to false if you do not wish to store the voltage parameters.";
p.optional = true;
p.def = "1";
p.name = "store_voltage";
f.params.push_back(p);
dtlang::functions["run"] = f;
// load()
f.help = "Load a simulation that has already been run.";
f.return_type = dtlang::TYPE_RESULTS;
f.params.clear();
p.type = dtlang::TYPE_STRING;
p.help = "The filename where the simulation was saved.";
p.optional = false;
p.name = "filename";
f.params.push_back(p);
dtlang::functions["load"] = f;
// constrain()
f.help = "Constrain a results object along one of the unconstrained dimensions.";
f.return_type = dtlang::TYPE_RESULTS;
f.params.clear();
p.type = dtlang::TYPE_RESULTS;
p.help = "The results object that you wish to constrain.";
p.optional = false;
p.name = "results";
f.params.push_back(p);
p.type = dtlang::TYPE_STRING;
p.help = "The ID of the unconstrained dimension. Type print(your_results) to list these.";
p.optional = false;
p.name = "ID";
f.params.push_back(p);
p.type = dtlang::TYPE_DOUBLE;
p.help = "The value you wish to constrain this dimension to.";
p.optional = false;
p.name = "value";
f.params.push_back(p);
dtlang::functions["constrain"] = f;
// merge()
f.help = "Merge two results objects.";
f.return_type = dtlang::TYPE_RESULTS;
f.params.clear();
p.type = dtlang::TYPE_RESULTS;
p.help = "First result to merge. Can already be a merged result.";
p.optional = false;
p.name = "results1";
f.params.push_back(p);
p.type = dtlang::TYPE_RESULTS;
p.help = "Second result to merge. Must NOT be a merged result yet.";
p.optional = false;
p.name = "results2";
f.params.push_back(p);
dtlang::functions["merge"] = f;
// graphinputs()
f.help = "Display a graph showing some or all of the inputs from a trial. Uses the graph_width and graph_height variables.";
f.return_type = dtlang::TYPE_VOID;
f.params.clear();
p.type = dtlang::TYPE_TRIAL;
p.help = "A trial variable from an already loaded trial.";
p.optional = false;
p.name = "trial";
f.params.push_back(p);
p.type = dtlang::TYPE_STRING;
p.help = "Filename to save the generated postscript file to.";
p.optional = true;
p.def = "inputs.eps";
p.name = "filename";
f.params.push_back( p );
//dtlang::functions["graphinputs"] = f;
// graphspiketrains()
f.help = "Display spike trains for every trial of the given population.";
f.return_type = dtlang::TYPE_VOID;
f.params.clear();
p.type = dtlang::TYPE_RESULTS;
p.help = "A results variable constrained to a single dimension.";
p.optional = false;
p.name = "results";
f.params.push_back(p);
p.type = dtlang::TYPE_STRING;
p.help = "Population ID to plot.";
p.optional = false;
p.name = "populationID";
f.params.push_back( p );
p.type = dtlang::TYPE_STRING;
p.help = "Filename to save the generated postscript file to.";
p.optional = true;
p.def = "spikes.eps";
p.name = "filename";
f.params.push_back( p );
p.type = dtlang::TYPE_INT;
p.help = "Number of trials to print.";
p.optional = true;
p.def = "Every Trial";
p.name = "trials";
f.params.push_back( p );
p.type = dtlang::TYPE_INT;
p.help = "Time value to start at.";
p.optional = true;
p.def = "Results timeseries start.";
p.name = "start";
f.params.push_back( p );
p.type = dtlang::TYPE_INT;
p.help = "Time value to end at.";
p.optional = true;
p.def = "Results timeseries end.";
p.name = "end";
f.params.push_back( p );
dtlang::functions["graphspiketrains"] = f;
// graphnetwork()
f.help = "Produce a network flow diagram of the network.";
f.return_type = dtlang::TYPE_VOID;
f.params.clear();
p.type = dtlang::TYPE_RESULTS;
p.help = "Results from a block of simulations already run.";
p.optional = false;
p.name = "network";
f.params.push_back(p);
p.type = dtlang::TYPE_STRING;
p.help = "Filename to save the generated postscript file to.";
p.optional = true;
p.def = "network.eps";
p.name = "filename";
f.params.push_back(p);
dtlang::functions["graphnetwork"] = f;
// graphspikecounts()
f.help = "Plot mean spike counts over all trials in two dimensions (one on x-axis, on as separate series).";
f.return_type = dtlang::TYPE_VOID;
f.params.clear();
p.type = dtlang::TYPE_RESULTS;
p.help = "A results object constrained to have one or two free parameters.";
p.optional = false;
p.name = "results";
f.params.push_back(p);
p.type = dtlang::TYPE_STRING;
p.help = "Population ID to graph.";
p.optional = false;
p.name = "popID";
f.params.push_back(p);
p.type = dtlang::TYPE_STRING;
p.help = "ID of the dimension to graph on the x-axis.";
p.optional = false;
p.name = "x_axis";
f.params.push_back(p);
p.type = dtlang::TYPE_STRING;
p.help = "Filename to save the graph to.";
p.optional = false;
p.name = "filename";
f.params.push_back(p);
dtlang::functions["graphspikecounts"] = f;
// graphspikecounts3d()
dtlang::functions["graphspikecounts3d"] = f;
// graphspikecountsmap()
dtlang::functions["graphspikecountsmap"] = f;
// graphfirstspikelatency()
f.help = "Plot mean first spike latency over all trials in two dimensions (one on x-axis, on as separate series).";
dtlang::functions["graphfirstspikelatency"] = f;
// graphpsth()
f.help = "Produce a plot of the peri-stimulus time histogram";
f.return_type = dtlang::TYPE_VOID;
f.params.clear();
p.type = dtlang::TYPE_RESULTS;
p.help = "A results object constrained to have no free parameters.";
p.optional = false;
p.name = "results";
f.params.push_back(p);
p.type = dtlang::TYPE_STRING;
p.help = "Population ID to graph.";
p.optional = false;
p.name = "popID";
f.params.push_back(p);
p.type = dtlang::TYPE_STRING;
p.help = "Filename to save the graph to.";
p.optional = false;
p.name = "filename";
f.params.push_back(p);
dtlang::functions["graphpsth"] = f;
// graphtrial_voltage()
f.help = "Produce a plot of the voltage traces for each neuron in each population.";
f.return_type = dtlang::TYPE_VOID;
f.params.clear();
p.type = dtlang::TYPE_RESULTS;
p.help = "A results object constrained to have no free parameters.";
p.optional = false;
p.name = "results";
f.params.push_back(p);
p.type = dtlang::TYPE_INT;
p.help = "The trial number (zero based).";
p.optional = false;
p.name = "trial_number";
f.params.push_back(p);
p.type = dtlang::TYPE_STRING;
p.help = "Filename to save the graph to.";
p.optional = false;
p.name = "filename";
f.params.push_back(p);
dtlang::functions["graphtrial_voltage"] = f;
// graphtrial_spikes()
dtlang::functions["graphtrial_spikes"] = dtlang::functions["graphtrial_voltage"];
// external()
f.help = "Execute a series of commands as stored in an external file.";
f.return_type = dtlang::TYPE_VOID;
f.params.clear();
p.type = dtlang::TYPE_STRING;
p.help = "Filename of the external file.";
p.optional = false;
p.name = "filename";
f.params.push_back(p);
dtlang::functions["external"] = f;
// print()
f.help = "Print the contents of the variable.";
f.return_type = dtlang::TYPE_VOID;
f.params.clear();
p.type = dtlang::TYPE_ANY;
p.help = "Variable to print.";
p.optional = false;
p.name = "variable";
f.params.push_back(p);
dtlang::functions["print"] = f;
}
bool dtlang::runFunction(const std::string &name, const vector<variable_def> ¶ms, void *&r, int &r_type, bool &end_input)
{
dtlang::function_def f;
map<std::string, function_def>::iterator iter = dtlang::functions.find(name);
if (iter == dtlang::functions.end()) {
cout << "Error: Unknown function" << endl;
return false;
}
f = iter->second;
unsigned int req = 0;
unsigned int opt = 0;
vector<function_param>::iterator iter_param;
for (iter_param = f.params.begin(); iter_param != f.params.end(); ++iter_param) {
if (iter_param->optional == false) ++req;
if (iter_param->optional == true) ++opt;
}
if (params.size() < req || params.size() > req+opt) {
cout << "Error: Incorrect number of function parameters.\nType \"help(\"" << name << "\")\" for more information." << endl;
return false;
}
//TODO: Check if paramter type is correct
if (r_type != dtlang::NO_RETURN) {
r_type = dtlang::functions[name].return_type;
}
// Execute Functions
if (name == "quit") {
return dtlang::f_quit();
}
if (name == "help") {
if (params.size() == 0) {
return dtlang::f_help();
} else if (params.size() == 1) {
return dtlang::f_help(*(static_cast<std::string*>(params[0].obj)));
}
}
if (name == "set") {
return dtnet::set(*(static_cast<std::string*>(params[0].obj)), *(static_cast<double*>(params[1].obj)));
}
if (name == "version") {
return dtlang::f_version();
}
if (name == "modsim") {
r = new Simulation((static_cast<Simulation*>(params[0].obj))->net, (static_cast<Simulation*>(params[0].obj))->trial);
Range new_val(*(static_cast<double*>(params[2].obj)));
return dtnet::modsim(*(static_cast<Simulation*>(r)), *(static_cast<Simulation*>(params[0].obj)), *(static_cast<std::string*>(params[1].obj)), new_val);
}
if (name == "modsimr") {
r = new Simulation((static_cast<Simulation*>(params[0].obj))->net, (static_cast<Simulation*>(params[0].obj))->trial);
Range new_val(*(static_cast<double*>(params[2].obj)), *(static_cast<double*>(params[3].obj)), *(static_cast<double*>(params[4].obj)));
return dtnet::modsim(*(static_cast<Simulation*>(r)), *(static_cast<Simulation*>(params[0].obj)), *(static_cast<std::string*>(params[1].obj)), new_val);
}
/*
if (name == "graphinputs") {
if (params.size() == 1) {
return dtlang::f_graphinputs(*(static_cast<Trial*>(params[0].obj)), "inputs.eps");
} else if (params.size() == 2) {
return dtlang::f_graphinputs(*(static_cast<Trial*>(params[0].obj)), *(static_cast<std::string*>(params[1].obj)));
}
}
*/
if (name == "graphnetwork") {
if (params.size() == 1) {
return dtnet::graphnetwork(*(static_cast<Results*>(params[0].obj)), "network.eps");
} else if (params.size() == 2) {
return dtnet::graphnetwork(*(static_cast<Results*>(params[0].obj)), *(static_cast<std::string*>(params[1].obj)));
}
}
if (name == "graphpsth") {
return dtnet::graphpsth(*(static_cast<Results*>(params[0].obj)),
*(static_cast<std::string*>(params[1].obj)),
*(static_cast<std::string*>(params[2].obj)));
}
if (name == "graphtrial_voltage") {
return dtnet::graphtrial(dtnet::PLOT_VOLTAGE, *(static_cast<Results*>(params[0].obj)),
(int)*(static_cast<double*>(params[1].obj)),
*(static_cast<std::string*>(params[2].obj)));
}
if (name == "graphtrial_spikes") {
return dtnet::graphtrial(dtnet::PLOT_SPIKES, *(static_cast<Results*>(params[0].obj)),
(int)*(static_cast<double*>(params[1].obj)),
*(static_cast<std::string*>(params[2].obj)));
}
if (name == "graphspiketrains") {
if (params.size() == 2) {
return dtnet::graphspiketrains(*(static_cast<Results*>(params[0].obj)),
*(static_cast<std::string*>(params[1].obj)),
dtnet::DEFAULT,
dtnet::DEFAULT,
dtnet::DEFAULT,
"spikes.eps");
} else if (params.size() == 3) {
return dtnet::graphspiketrains(*(static_cast<Results*>(params[0].obj)),
*(static_cast<std::string*>(params[1].obj)),
dtnet::DEFAULT,
dtnet::DEFAULT,
dtnet::DEFAULT,
*(static_cast<std::string*>(params[2].obj)));
} else if (params.size() == 4) {
return dtnet::graphspiketrains(*(static_cast<Results*>(params[0].obj)),
*(static_cast<std::string*>(params[1].obj)),
(int)*(static_cast<double*>(params[3].obj)),
dtnet::DEFAULT,
dtnet::DEFAULT,
*(static_cast<std::string*>(params[2].obj)));
} else if (params.size() == 5) {
return dtnet::graphspiketrains(*(static_cast<Results*>(params[0].obj)),
*(static_cast<std::string*>(params[1].obj)),
(int)*(static_cast<double*>(params[3].obj)),
*(static_cast<double*>(params[4].obj)),
dtnet::DEFAULT,
*(static_cast<std::string*>(params[2].obj)));
} else if (params.size() == 6) {
return dtnet::graphspiketrains(*(static_cast<Results*>(params[0].obj)),
*(static_cast<std::string*>(params[1].obj)),
(int)*(static_cast<double*>(params[3].obj)),
*(static_cast<double*>(params[4].obj)),
*(static_cast<double*>(params[5].obj)),
*(static_cast<std::string*>(params[2].obj)));
}
}
if (name == "graphspikecounts") {
return dtnet::graphspikecounts(*(static_cast<Results*>(params[0].obj)),
*(static_cast<std::string*>(params[1].obj)),
*(static_cast<std::string*>(params[2].obj)),
*(static_cast<std::string*>(params[3].obj)),
dtnet::PLOT_FLAT
);
}
if (name == "graphspikecounts3d") {
return dtnet::graphspikecounts(*(static_cast<Results*>(params[0].obj)),
*(static_cast<std::string*>(params[1].obj)),
*(static_cast<std::string*>(params[2].obj)),
*(static_cast<std::string*>(params[3].obj)),
dtnet::PLOT_3D
);
}
if (name == "graphspikecountsmap") {
return dtnet::graphspikecounts(*(static_cast<Results*>(params[0].obj)),
*(static_cast<std::string*>(params[1].obj)),
*(static_cast<std::string*>(params[2].obj)),
*(static_cast<std::string*>(params[3].obj)),
dtnet::PLOT_MAP
);
}
if (name == "graphfirstspikelatency") {
return dtnet::graphfirstspikelatency(*(static_cast<Results*>(params[0].obj)),
*(static_cast<std::string*>(params[1].obj)),
*(static_cast<std::string*>(params[2].obj)),
*(static_cast<std::string*>(params[3].obj)),
dtnet::PLOT_FLAT
);
}
if (name == "vars") {
return dtlang::f_vars();
}
if (name == "funcs") {
return dtlang::f_funcs();
}
if (name == "run") {
if (r_type == dtlang::NO_RETURN) {
cout << "Error: \"" << name << "\" must be assigned to a variable." << endl;
return false;
}
r = new Results();
if (params.size() == 3) {
return dtnet::run( *(static_cast<Results*>(r)),
*(static_cast<Simulation*>(params[0].obj)),
*(static_cast<std::string*>(params[1].obj)),
(int)*(static_cast<double*>(params[2].obj)),
dtnet::get_dbl("delay"),
true // Store voltage by default
);
} else if (params.size() == 4) {
return dtnet::run( *(static_cast<Results*>(r)),
*(static_cast<Simulation*>(params[0].obj)),
*(static_cast<std::string*>(params[1].obj)),
(int)*(static_cast<double*>(params[2].obj)),
*(static_cast<double*>(params[3].obj)),
true // Store voltage by default
);
} else if (params.size() == 5) {
return dtnet::run( *(static_cast<Results*>(r)),
*(static_cast<Simulation*>(params[0].obj)),
*(static_cast<std::string*>(params[1].obj)),
(int)*(static_cast<double*>(params[2].obj)),
*(static_cast<double*>(params[3].obj)),
*(static_cast<int*>(params[4].obj)) != 0
);
}
}
if (name == "load") {
if (r_type == dtlang::NO_RETURN) {
cout << "Error: \"" << name << "\" must be assigned to a variable." << endl;
return false;
}
r = new Results();
return dtnet::load(*(static_cast<Results*>(r)), *(static_cast<std::string*>(params[0].obj)));
}
if (name == "print") {
return dtlang::f_print(params[0].obj, params[0].type);
}
if (name == "merge") {
if (r_type == dtlang::NO_RETURN) {
cout << "Error: \"" << name << "\" must be assigned to a variable." << endl;
return false;
}
r = new Results();
return dtnet::merge(*(static_cast<Results*>(r)), static_cast<Results*>(params[0].obj), static_cast<Results*>(params[1].obj));
}
if (name == "constrain") {
if (r_type == dtlang::NO_RETURN) {
cout << "Error: \"" << name << "\" must be assigned to a variable." << endl;
return false;
}
r = new Results();
return dtnet::constrain(*(static_cast<Results*>(r)), static_cast<Results*>(params[0].obj), *(static_cast<std::string*>(params[1].obj)), *(static_cast<double*>(params[2].obj)));
}
if (name == "print") {
return dtlang::f_print(params[0].obj, params[0].type);
}
if (name == "external") {
return dtlang::f_external(*(static_cast<std::string*>(params[0].obj)), end_input);
}
if (name == "simulation") {
if (r_type == dtlang::NO_RETURN) {
cout << "Error: \"" << name << "\" must be assigned to a variable." << endl;
return false;
}
Net network;
Trial trial;
if (dtlang::simulation(*(static_cast<std::string*>(params[0].obj)), *(static_cast<std::string*>(params[1].obj)), &network, &trial)) {
r = new Simulation(network,trial);
} else {
return false;
}
return true;
}
return false;
}
bool dtlang::f_vars() {
cout << endl << "Variable" << "\t" << "Type" << "\t" << "Value" << endl;
cout << "------------------------------------" << endl;
map<std::string, variable_def, strCmp>::iterator iter;
for (iter = dtlang::vars.begin(); iter != dtlang::vars.end(); ++iter) {
cout << iter->first << "\t\t";
cout << dtlang::type_names[iter->second.type] << "\t";
switch(iter->second.type) {
case dtlang::TYPE_STRING:
cout << *(static_cast<std::string*>(iter->second.obj));
break;
case dtlang::TYPE_INT:
cout << *(static_cast<int*>(iter->second.obj));
break;
case dtlang::TYPE_DOUBLE:
cout << *(static_cast<double*>(iter->second.obj));
break;
case dtlang::TYPE_TRIAL:
cout << "[Trial Object]";
break;
case dtlang::TYPE_NET:
cout << "[Net Object]";
break;
case dtlang::TYPE_RESULTS:
cout << "[Results Object]";
break;
default:
cout << "Unknown";
break;
}
cout << endl;
}
cout << endl;
return true;
}
bool dtlang::f_funcs() {
cout << endl << "Function" << "\t" << "Type" << "\t" << "Description" << endl;
cout << "------------------------------------" << endl;
map<std::string, function_def, strCmp>::iterator iter;
for (iter = dtlang::functions.begin(); iter != dtlang::functions.end(); ++iter) {
cout << iter->first << "\t";
if (iter->first.length() < 8) cout << "\t";
cout << dtlang::type_names[iter->second.return_type] << "\t";
cout << iter->second.help << endl;
}
cout << endl;
return true;
}
bool dtlang::f_help() {
cout << endl << "This is the command line where you can run functions or assign values to variables." << endl;
cout << "To call a function, type the function name, followed by a (, a list of parameters, and then a )." << endl;
cout << "For example, to quit back to the command prompt, type \"quit()\" and press ENTER." << endl;
cout << "To get help on a function, type \"help(functionname)\", such as \"help(loadinput)\"." << endl;
cout << "To change the timestep to 0.01 ms, type \"dt = 0.01\" and press ENTER." << endl;
cout << "A series of commands can also be stored in a file and run in sequence by typing \"external(file)\"." << endl;
cout << "Type \"funcs()\" to see a list of available functions." << endl;
cout << endl;
return true;
}
bool dtlang::f_help(std::string name) {
dtlang::function_def f;
map<std::string, function_def>::iterator iter = dtlang::functions.find(name);
if (iter == dtlang::functions.end()) {
cout << "Cannot find a function named \"" << name << "\"" << endl << endl;
return false;
}
f = iter->second;
vector<function_param>::iterator iter_param;
cout << endl << name << "(";
int opt = 0;
for (iter_param = f.params.begin(); iter_param != f.params.end(); ++iter_param) {
if (iter_param != f.params.begin()) cout << ", ";
if (iter_param->optional) { ++opt; cout << '['; }
cout << "<" << iter_param->name << ":" << dtlang::type_names[iter_param->type] << ">";
}
for (int i = 0; i < opt; ++i) { cout << "]"; };
cout << ")" << endl;
cout << f.help << endl;
cout << "Return Type: " << dtlang::type_names[f.return_type] << endl << endl;
for (iter_param = f.params.begin(); iter_param != f.params.end(); ++iter_param) {
cout << "<" << iter_param->name << ":" << dtlang::type_names[iter_param->type] << ">";
if (iter_param->optional) {
cout << "\t*Optional* (Default: " << iter_param->def << ")" << endl;
} else {
cout << "\t[Required]" << endl;
}
cout << "\t" << iter_param->help << endl;
}
cout << endl;
return true;
}
bool dtlang::f_quit() {
// Tell libdtnet that it's time to clean up and go home
dtnet::quit();
map<std::string, variable_def>::iterator iter;
for (iter = vars.begin(); iter != vars.end(); ++iter) {
dtlang::delete_variable(iter->second);
}
for (iter = statements.begin(); iter != statements.end(); ++iter) {
dtlang::delete_variable(iter->second);
}
cout << endl;
return true;
}
bool dtlang::delete_variable(variable_def var) {
/**
* Delete the object a variable points to.
*/
switch (var.type) {
case dtlang::TYPE_STRING:
delete static_cast<std::string*>(var.obj);
break;
case dtlang::TYPE_INT:
delete static_cast<int*>(var.obj);
break;
case dtlang::TYPE_DOUBLE:
delete static_cast<double*>(var.obj);
break;
case dtlang::TYPE_TRIAL:
delete static_cast<Trial*>(var.obj);
break;
case dtlang::TYPE_NET:
delete static_cast<Net*>(var.obj);
break;
case dtlang::TYPE_RESULTS:
delete static_cast<Results*>(var.obj);
break;
case dtlang::TYPE_SIMULATION:
delete static_cast<Simulation*>(var.obj);
break;
case dtlang::TYPE_POPULATION:
delete static_cast<Population*>(var.obj);
break;
default:
cout << "Attempted to free an unknown variable type. MEMORY LEAK!" << endl;
return false;
break;
}
return true;
}
bool f_delete(const std::string var) {
return true;
}
bool dtlang::f_external(const std::string filename, bool &end_input) {
std::string line;
ifstream script(filename.c_str());
if (script.is_open())
{
while (!script.eof() && !end_input)
{
getline(script, line);
if (line != "") // Skip blank lines
{
cout << VT_set_colors(VT_RED, VT_DEFAULT) << "extern" << VT_default_attributes << "> " << line << endl;
if (!dtlang::parse(line, end_input))
{
cout << "Error encountered in script. Halting execution." << endl << endl;
break;
}
}
}
script.close();
return false;
} else {
cout << "Unable to open " << filename << "." << endl << endl;
return false;
}
}
bool dtlang::simulation(const std::string net_filename, const std::string trial_filename, Net *net, Trial *trial) {
std::string error;
/* Load Network */
if (dtlang::verbose) cout << "...Loading network definition from " << net_filename;
if ( net->load(net_filename, error) == false ) {
if (dtlang::verbose) cout << "\t[FAILED]" << endl;
cout << "[X] " << error << endl;
return false;
}
if (dtlang::verbose) cout << "\t[OK]" << endl;
if (dtlang::verbose) cout << "...Loaded " << net->count_populations() << " populations" << endl;
/* Load Inputs */
if (dtlang::verbose) cout << "...Loading input vectors from " << trial_filename;
if ( trial->load(trial_filename, error) == false ) {
if (dtlang::verbose) cout << "\t[FAILED]" << endl;
cout << "[X] " << error << endl;
return false;
}
if (dtlang::verbose) cout << "\t[OK]" << endl;
if (dtlang::verbose) cout << "...Generated " << trial->count() << " input signals" << endl;
return true;
}
/*
bool dtlang::f_graphinputs(Trial &trial, std::string const &filename) {
vector<vector<double> >* signals = trial.signals();
vector<double>* timesteps = trial.timeSteps();
GLE gle;
GLE::PlotProperties plotProperties;
GLE::Color start;
start.r = 0.5;
start.g = 0.5;
start.b = 0.5;
plotProperties.first = start;
plotProperties.zeros = false;
gle.plot(*timesteps, *signals, plotProperties);
gle.canvasProperties.width = Settings::instance()->get_dbl("graph.width");
gle.canvasProperties.height = Settings::instance()->get_dbl("graph.height");
gle.draw(filename);
return true;
}
*/
bool dtlang::f_version() {
cout << "libdtnet: " << dtnet::version() << endl;
cout << "dtnet CLI: " << DTNETCLI_VERSION << endl;
return true;
}
bool dtlang::f_print(void* ptr, int const type) {
switch(type)
{
case dtlang::TYPE_STRING:
cout << *(static_cast<std::string*>(ptr)) << endl;
break;
case dtlang::TYPE_TRIAL: cout << static_cast<Trial*>(ptr)->toString();
break;
case dtlang::TYPE_NET:
cout << static_cast<Net*>(ptr)->toString();
break;
case dtlang::TYPE_RESULTS:
cout << static_cast<Results*>(ptr)->toString();
break;
case dtlang::TYPE_SIMULATION:
cout << static_cast<Simulation*>(ptr)->toString();
break;
case dtlang::TYPE_INT:
cout << *(static_cast<int*>(ptr)) << endl;
break;
case dtlang::TYPE_DOUBLE:
cout << *(static_cast<double*>(ptr)) << endl;
break;
default:
cout << "Cannot print this data type." << endl;
return false;
break;
}
return true;
}