\n";
return 1;
}
#
# Display template metadata and values in a table
#
function ShowMetadata() {
$guid = $this->guid();
$vers = $this->vers();
$query_result =
DBQueryFatal("select i.* from experiment_template_metadata as m ".
"left join experiment_template_metadata_items as i on ".
" m.metadata_guid=i.guid and m.metadata_vers=i.vers ".
"where m.parent_guid='$guid' and ".
" m.parent_vers='$vers' and ".
" m.internal=0 and m.hidden=0");
if (! mysql_num_rows($query_result))
return 0;
echo "
\n";
return 1;
}
#
# Show the instance list for a template.
#
function ShowInstances() {
$guid = $this->guid();
$vers = $this->vers();
$query_result =
DBQueryFatal("select e.*,count(r.node_id) as nodes, ".
" round(minimum_nodes+.1,0) as min_nodes ".
"from experiment_template_instances as i ".
"left join experiments as e on e.idx=i.exptidx ".
"left join reserved as r on e.pid=r.pid and ".
" e.eid=r.eid ".
"where e.pid is not null and ".
" (i.parent_guid='$guid' and ".
" i.parent_vers='$vers') ".
"group by e.pid,e.eid order by e.state,e.eid");
if (! mysql_num_rows($query_result))
return;
echo "
\n";
}
#
# Show the historical instance list for a template.
#
function ShowHistory($expand) {
$guid = $this->guid();
$vers = $this->vers();
$query_result =
DBQueryFatal("select i.*,r.archive_tag ".
" from experiment_template_instances as i ".
"left join experiment_stats as s on ".
" s.exptidx=i.exptidx ".
"left join experiment_resources as r on ".
" r.idx=s.rsrcidx ".
"where (i.parent_guid='$guid' and ".
" i.parent_vers='$vers') ".
"order by i.start_time");
if (! mysql_num_rows($query_result))
return 0;
echo "
\n";
if ($expandit) {
$instance = new TemplateInstance($exptidx);
echo "
\n";
echo " \n";
echo "
 
\n";
echo "
\n";
$instance->ShowRunList(0);
echo "
\n";
echo "
\n";
}
}
echo "
\n";
}
#
# Dump the image map for a template to the output.
#
function ShowGraph() {
$guid = $this->guid();
$vers = $this->vers();
# Make the link unique to force reload on the client side.
$now = time();
$query_result =
DBQueryFatal("select imap from experiment_template_graphs ".
"where parent_guid='$guid'");
if (!mysql_num_rows($query_result)) {
USERERROR("Experiment Template $guid is no longer in the DB!", 1);
}
$row = mysql_fetch_array($query_result);
$imap = $row['imap'];
echo "
";
echo "
\n";
echo "
\n";
echo "\n";
echo $imap;
echo "\n";
echo "
\n";
echo "
\n";
}
#
# Dump the NS file into its own iframe.
#
function ShowNS() {
$guid = $this->guid();
$vers = $this->vers();
echo "
";
echo "\n";
echo "
";
}
#
# Dump the visualization into its own iframe.
#
function ShowVis($zoom = 1.25, $detail = 1) {
$guid = $this->guid();
$pid = $this->pid();
$eid = $this->eid();
# Make the link unique to force reload on the client side.
$now = time();
echo "
";
echo "
\n";
echo "
\n";
echo "\n";
echo "
\n";
echo "
\n";
}
#
# Grab the zoom and detail for the current viz picture, as a default.
#
function CurrentVisDetails() {
$pid = $this->pid();
$eid = $this->eid();
$query_result =
DBQueryFatal("select zoom,detail from vis_graphs ".
"where pid='$pid' and eid='$eid'");
if (!mysql_num_rows($query_result)) {
return array(1.25, 1);
}
$row = mysql_fetch_array($query_result);
$zoom = $row['zoom'];
$detail = $row['detail'];
return array($zoom, $detail);
}
#
# Grab array of input files for a template, indexed by input_idx.
#
function InputFiles() {
$guid = $this->guid();
$vers = $this->vers();
$input_list = array();
$query_result =
DBQueryFatal("select * from experiment_template_inputs ".
"where parent_guid='$guid' and parent_vers='$vers'");
while ($row = mysql_fetch_array($query_result)) {
$input_idx = $row['input_idx'];
$input_query =
DBQueryFatal("select input ".
" from experiment_template_input_data ".
"where idx='$input_idx'");
$input_row = mysql_fetch_array($input_query);
$input_list[] = $input_row['input'];
}
return $input_list;
}
#
# Return number of parameters.
#
function ParameterCount() {
$guid = $this->guid();
$vers = $this->vers();
$query_result =
DBQueryFatal("select name,value ".
" from experiment_template_parameters ".
"where parent_guid='$guid' and ".
" parent_vers='$vers'");
return mysql_num_rows($query_result);
}
#
# Return number of metadata items
#
function MetadataCount() {
$guid = $this->guid();
$vers = $this->vers();
$query_result =
DBQueryFatal("select internal ".
" from experiment_template_metadata as m ".
"where m.parent_guid='$guid' and ".
" m.parent_vers='$vers' and ".
" m.internal=0 and m.hidden=0");
return mysql_num_rows($query_result);
}
#
# Return number of instances
#
function InstanceCount() {
$guid = $this->guid();
$vers = $this->vers();
$query_result =
DBQueryFatal("select * from experiment_template_instances as i ".
"where (i.parent_guid='$guid' and ".
" i.parent_vers='$vers')");
return mysql_num_rows($query_result);
}
#
# Look for a metadata item in a template, by the guid/vers of the
# metadata. Returns a class instance (see below).
#
function LookupMetadataByGUID($metadata_guid, $metadata_vers) {
return TemplateMetadata::TemplateLookupByGUID($this,
$metadata_guid,
$metadata_vers);
}
# Ditto by name,
function LookupMetadataByName($metadata_name) {
return TemplateMetadata::TemplateLookupByName($this, $metadata_name);
}
# Grab the graph data.
function GraphImage(&$image) {
$guid = $this->guid();
$query_result =
DBQueryWarn("select image from experiment_template_graphs ".
"where parent_guid='$guid'");
if (!$query_result || !mysql_num_rows($query_result)) {
return -1;
}
$row = mysql_fetch_array($query_result);
$image = $row['image'];
return 0;
}
#
# Return an array of the formal parameters for a template.
#
function FormalParameters(&$parameters) {
$parameters = array();
$guid = $this->guid();
$vers = $this->vers();
$query_result =
DBQueryFatal("select name,value ".
" from experiment_template_parameters ".
"where parent_guid='$guid' and ".
" parent_vers='$vers' ".
"order by name");
while ($row = mysql_fetch_array($query_result)) {
$name = $row['name'];
$value = $row['value'];
$parameters[$name] = $value;
}
return 0;
}
#
# Return an array of the formal parameters for a template.
#
function FormalParameterMouseOvers(&$mouseovers) {
$mouseovers = array();
$guid = $this->guid();
$vers = $this->vers();
$query_result =
DBQueryFatal("select p.name,m.value as description ".
" from experiment_template_parameters as p ".
"left join experiment_template_metadata_items as m ".
" on m.guid=p.metadata_guid and ".
" m.vers=p.metadata_vers ".
"where p.parent_guid='$guid' and ".
" p.parent_vers='$vers'");
while ($row = mysql_fetch_array($query_result)) {
$name = $row['name'];
$description = $row['description'];
if (isset($description) && $description != "") {
$mouseovers[$name] = MakeMouseOver($description);
}
}
return 0;
}
#
# Find next candidate for a template (modify) TID
#
function NextTID() {
$tid = $this->tid();
$guid = $this->guid();
$query_result =
DBQueryFatal("select MAX(vers) from experiment_templates ".
"where guid='$guid'");
if (mysql_num_rows($query_result) == 0) {
return "T" . substr(md5(uniqid($foo, true)), 0, 10);
}
$row = mysql_fetch_array($query_result);
$foo = $row[0] + 1;
return "${tid}-V${foo}";
}
#
# Return array of template events, ordered by time.
#
function EventList(&$eventlist) {
$eventlist = array();
$guid = $this->guid();
$vers = $this->vers();
$query_result =
DBQueryFatal("select * from experiment_template_events ".
"where parent_guid='$guid' and ".
" parent_vers='$vers' ".
"order by time");
$i = 0;
while ($row = mysql_fetch_array($query_result)) {
$eventlist[$i++] = $row;
}
return 0;
}
function EventCount() {
$guid = $this->guid();
$vers = $this->vers();
$query_result =
DBQueryFatal("select count(*) from experiment_template_events ".
"where parent_guid='$guid' and ".
" parent_vers='$vers' ");
$row = mysql_fetch_array($query_result);
$count = $row[0];
return $count;
}
function DeleteEvent($vname) {
$guid = $this->guid();
$vers = $this->vers();
DBQueryFatal("delete from experiment_template_events ".
"where parent_guid='$guid' and ".
" parent_vers='$vers' and ".
" vname='$vname'");
return 0;
}
function ModifyEvent($vname, $changes) {
$guid = $this->guid();
$vers = $this->vers();
$sets = array();
while (list ($key, $value) = each ($changes)) {
$value = addslashes($value);
$sets[] = "$key='$value'";
}
DBQueryFatal("update experiment_template_events set ".
implode(",", $sets) . " ".
"where parent_guid='$guid' and ".
" parent_vers='$vers' and ".
" vname='$vname'");
return 0;
}
}
#
# This is the class for a template instance (swapin).
#
class TemplateInstance
{
var $template;
var $instance;
var $experiment;
#
# Instances are found by their experiment index.
#
function TemplateInstance($exptidx) {
$exptidx = addslashes($exptidx);
$query_result =
DBQueryFatal("select * ".
" from experiment_template_instances ".
"where exptidx='$exptidx'");
if (!$query_result || !mysql_num_rows($query_result)) {
$this->template = NULL;
$this->instance = NULL;
return;
}
$this->instance = mysql_fetch_array($query_result);
$this->template = new Template($this->instance['parent_guid'],
$this->instance['parent_vers']);
$this->experiment = Experiment::Lookup($exptidx);
}
# Hmm, how does one cause an error in a php constructor?
function IsValid() {
return !is_null($this->instance);
}
# Do class level lookup.
function LookupByExptidx($exptidx) {
$foo = new TemplateInstance($exptidx);
if ($foo->IsValid())
return $foo;
return null;
}
# accessors
function idx() {
return (is_null($this->instance) ? -1 : $this->instance['idx']);
}
function exptidx() {
return (is_null($this->instance) ? -1 : $this->instance['exptidx']);
}
function runidx() {
return (is_null($this->instance) ? -1 : $this->instance['runidx']);
}
function pid() {
return (is_null($this->instance) ? -1 : $this->instance['pid']);
}
function eid() {
return (is_null($this->instance) ? -1 : $this->instance['eid']);
}
function uid() {
return (is_null($this->instance) ? -1 : $this->instance['uid']);
}
function guid() {
return (is_null($this->instance) ? -1 :
$this->instance['parent_guid']);
}
function vers() {
return (is_null($this->instance) ? -1 :
$this->instance['parent_vers']);
}
function start_time() {
return (is_null($this->instance) ? -1 :
$this->instance['start_time']);
}
function stop_time() {
return (is_null($this->instance) ? -1 :
$this->instance['stop_time']);
}
function pause_time() {
return (is_null($this->instance) ? -1 :
$this->instance['pause_time']);
}
function template() {
return (is_null($this->instance) ? -1 : $this->template);
}
function GetTemplate() {
return $this->template;
}
function GetExperiment() {
return $this->experiment;
}
#
# Load the project object for an experiment.
#
function Project() {
$pid = $this->pid();
if (! ($project = Project::Lookup($pid))) {
TBERROR("Could not lookup project $pid!", 1);
}
return $project;
}
# Is instance actually running (current experiment).
function Instantiated() {
return ($this->experiment ? 1 : 0);
}
#
# Show an instance.
#
function Show($detailed, $withanno = 0) {
$exptidx = $this->exptidx();
$runidx = $this->runidx();
$guid = $this->guid();
$vers = $this->vers();
$pid = $this->pid();
$uid = $this->uid();
$start = $this->start_time();
$stop = $this->stop_time();
$template= $this->template();
$pcount = $template->ParameterCount();
if (! ($user = User::Lookup($uid))) {
TBERROR("Could not lookup object for user $uid", 1);
}
$showuser_url = CreateURL("showuser", $user);
# If the instance is swapped in, we can provide a link to
# experiment.
if ($this->experiment) {
$showexp_url = CreateURL("showexp", $this->experiment);
}
echo "
\n";
}
if ($withanno) {
$this->ShowAnnotation();
}
if ($detailed) {
$this->ShowRunList(1);
}
echo "
\n";
}
#
# Page header; spit back some html for the typical page header.
#
function PageHeader() {
$template = $this->template();
$exptidx = $this->exptidx();
$html = $template->PageHeader();
$guid = $this->guid();
$vers = $this->vers();
$eid = $this->eid();
$html .= ", Instance " .
MakeLink("instance", "instance=$exptidx", $eid) .
"";
return $html;
}
#
# A variant that points to the active experiment.
#
function ExpPageHeader() {
$template = $this->template();
$html = $template->PageHeader();
$guid = $this->guid();
$vers = $this->vers();
$pid = $this->pid();
$eid = $this->eid();
$html .= ", Instance " .
MakeLink("project", "pid=$pid", $pid) . "/" .
MakeLink("experiment", "pid=$pid&eid=$eid", $eid) .
"";
return $html;
}
#
# Ditto for a run, although run should its own class.
#
function RunPageHeader($runidx) {
$template = $this->template();
$exptidx = $this->exptidx();
$html = $this->PageHeader();
$guid = $this->guid();
$vers = $this->vers();
$eid = $this->eid();
$runid = $this->GetRunID($runidx);
$html .= ", Run " .
MakeAnchor(CreateURL("experimentrun_show", $this,
"runidx", $runidx), $runid) .
"";
return $html;
}
#
# Show the current bindings. This depends on the state of the instance.
# If not swapped in, the instance bindings are current. If swapped in,
# the most recent run bindings are current (current run, or last run).
#
function ShowCurrentBindings() {
global $TB_EXPTSTATE_SWAPPED;
if ($this->experiment) {
$experiment = $this->experiment;
if ($experiment->state() == $TB_EXPTSTATE_SWAPPED) {
# Show the instance bindings is swapped.
return $this->ShowBindings();
}
elseif ($this->runidx()) {
return $this->ShowRunBindings();
}
return $this->ShowLastRunBindings();
}
return $this->ShowBindings();
}
#
# Display instance bindings in a table
#
function ShowBindings() {
$instance_idx = $this->idx();
$query_result =
DBQueryWarn("select * from experiment_template_instance_bindings ".
"where instance_idx='$instance_idx'");
if (!mysql_num_rows($query_result))
return 0;
echo "
\n";
return 1;
}
#
# Display last run bindings in a table
#
function ShowLastRunBindings() {
return $this->ShowRunBindings($this->LastRunIdx());
}
#
# Show the run list for an instance.
#
function ShowRunList($withheader) {
$exptidx = $this->exptidx();
$guid = $this->guid();
$vers = $this->vers();
$query_result =
DBQueryFatal("select * from experiment_runs ".
"where exptidx='$exptidx'");
if (! mysql_num_rows($query_result))
return 0;
if ($withheader) {
echo "