def test_validate(self): validation = validate(self.experiment) self.assertTrue(validation) # Create temporary directory and test invalid config.json broken_experiment = "%s/broken_experiment" % self.tmpdir copy_directory(self.experiment, broken_experiment) # Missing file specified shutil.copyfile("%s/experiment.js" % broken_experiment, "%s/pizza.js" % broken_experiment) os.remove("%s/experiment.js" % broken_experiment) self.assertFalse(validate(broken_experiment)) shutil.copyfile("%s/pizza.js" % broken_experiment, "%s/experiment.js" % broken_experiment) # Invalid field for template broken_config = self.config[:] broken_config[0]["template"] = "invalid_framework" self.save_config(broken_config, broken_experiment) self.assertFalse(validate(broken_experiment)) # Missing required field broken_config = self.config[:] del broken_config[0]["exp_id"] self.save_config(broken_config, broken_experiment) self.assertFalse(validate(broken_experiment))
def test_validate(self): validation = validate(self.experiment) self.assertTrue(validation) # Create temporary directory and test invalid config.json broken_experiment = "%s/broken_experiment" %self.tmpdir copy_directory(self.experiment,broken_experiment) # Missing file specified shutil.copyfile("%s/experiment.js" %broken_experiment,"%s/pizza.js" %broken_experiment) os.remove("%s/experiment.js" %broken_experiment) self.assertFalse(validate(broken_experiment)) shutil.copyfile("%s/pizza.js" %broken_experiment,"%s/experiment.js" %broken_experiment) # Invalid field for template broken_config = self.config[:] broken_config[0]["template"] = "invalid_framework" self.save_config(broken_config,broken_experiment) self.assertFalse(validate(broken_experiment)) # Missing required field broken_config = self.config[:] del broken_config[0]["exp_id"] self.save_config(broken_config,broken_experiment) self.assertFalse(validate(broken_experiment))
def install_experiments(experiment_tags=None, repo_type="experiments"): # We will return list of experiments that did not install successfully errored_experiments = [] tmpdir = custom_battery_download(repos=[repo_type, "battery"]) # The git commit is saved with the experiment as the "version" repo = Repo("%s/%s" % (tmpdir, repo_type)) commit = repo.commit("master").__str__() experiments = get_experiments("%s/%s" % (tmpdir, repo_type), load=True, warning=False) if experiment_tags != None: experiments = [e for e in experiments if e[0]["exp_id"] in experiment_tags] for experiment in experiments: try: performance_variable = None rejection_variable = None if "experiment_variables" in experiment[0]: if isinstance(experiment[0]["experiment_variables"], list): for var in experiment[0]["experiment_variables"]: if var["type"].lower().strip() == "bonus": performance_variable = parse_experiment_variable(var) elif var["type"].lower().strip() == "credit": rejection_variable = parse_experiment_variable(var) else: parse_experiment_variable(var) # adds to database if isinstance(experiment[0]["reference"], list): reference = experiment[0]["reference"][0] else: reference = experiment[0]["reference"] cognitive_atlas_task = get_cognitiveatlas_task(experiment[0]["cognitive_atlas_task_id"]) new_experiment, _ = ExperimentTemplate.objects.update_or_create( exp_id=experiment[0]["exp_id"], defaults={ "name": experiment[0]["name"], "cognitive_atlas_task": cognitive_atlas_task, "publish": bool(experiment[0]["publish"]), "time": experiment[0]["time"], "reference": reference, "version": commit, "template": experiment[0]["template"], "performance_variable": performance_variable, "rejection_variable": rejection_variable, }, ) new_experiment.save() experiment_folder = "%s/%s/%s" % (tmpdir, repo_type, experiment[0]["exp_id"]) output_folder = "%s/%s/%s" % (media_dir, repo_type, experiment[0]["exp_id"]) if os.path.exists(output_folder): shutil.rmtree(output_folder) copy_directory(experiment_folder, output_folder) except: errored_experiments.append(experiment[0]["exp_id"]) shutil.rmtree(tmpdir) return errored_experiments
def install_experiments(experiment_tags=None,repo_type="experiments"): # We will return list of experiments that did not install successfully errored_experiments = [] tmpdir = custom_battery_download(repos=[repo_type,"battery"]) # The git commit is saved with the experiment as the "version" repo = Repo("%s/%s" %(tmpdir,repo_type)) commit = repo.commit('master').__str__() experiments = get_experiments("%s/%s" %(tmpdir,repo_type),load=True,warning=False) if experiment_tags != None: experiments = [e for e in experiments if e[0]["exp_id"] in experiment_tags] for experiment in experiments: try: performance_variable = None rejection_variable = None if "experiment_variables" in experiment[0]: if isinstance(experiment[0]["experiment_variables"],list): for var in experiment[0]["experiment_variables"]: if var["type"].lower().strip() == "bonus": performance_variable = parse_experiment_variable(var) elif var["type"].lower().strip() == "credit": rejection_variable = parse_experiment_variable(var) else: parse_experiment_variable(var) # adds to database if isinstance(experiment[0]["reference"],list): reference = experiment[0]["reference"][0] else: reference = experiment[0]["reference"] cognitive_atlas_task = get_cognitiveatlas_task(experiment[0]["cognitive_atlas_task_id"]) new_experiment,_ = ExperimentTemplate.objects.update_or_create(exp_id=experiment[0]["exp_id"], defaults={"name":experiment[0]["name"], "cognitive_atlas_task":cognitive_atlas_task, "publish":bool(experiment[0]["publish"]), "time":experiment[0]["time"], "reference":reference, "version":commit, "template":experiment[0]["template"], "performance_variable":performance_variable, "rejection_variable":rejection_variable}) new_experiment.save() experiment_folder = "%s/%s/%s" %(tmpdir,repo_type,experiment[0]["exp_id"]) output_folder = "%s/%s/%s" %(media_dir,repo_type,experiment[0]["exp_id"]) if os.path.exists(output_folder): shutil.rmtree(output_folder) copy_directory(experiment_folder,output_folder) except: errored_experiments.append(experiment[0]["exp_id"]) shutil.rmtree(tmpdir) return errored_experiments
def generate_base(battery_dest,tasks=None,experiment_repo=None,survey_repo=None,game_repo=None, add_experiments=True,add_surveys=True,add_games=True,battery_repo=None,warning=True): '''generate_base returns a folder with downloaded experiments, surveys, and battery, either specified by the user or a temporary directory, to be used by generate_local and generate (for psiturk) :param battery_dest: [required] is the output folder for your battery. This folder MUST NOT EXIST. :param battery_repo: location of psiturk-battery repo to use as a template. If not specified, will be downloaded to a temporary directory :param experiment_repo: location of a expfactory-experiments repo to check for valid experiments. If not specified, will be downloaded to a temporary directory :param survey_repo: location of a expfactory-surveys repo to check for valid surveys. If not specified, will be downloaded to a temporary directory :param tasks: a list of experiments and surveys, meaning the "exp_id" variable in the config.json, to include. This variable also conincides with the tasks folder name. :param warning: show warnings when validating experiments (default True) ''' if experiment_repo == None or battery_repo == None or survey_repo == None or game_repo == None: tmpdir = custom_battery_download() if experiment_repo == None: experiment_repo = "%s/experiments" %(tmpdir) if battery_repo == None: battery_repo = "%s/battery" %(tmpdir) if survey_repo == None: survey_repo = "%s/surveys" %(tmpdir) if game_repo == None: game_repo = "%s/games" %(tmpdir) # Copy battery skeleton to destination copy_directory(battery_repo,battery_dest) valid_experiments = [] valid_surveys = [] valid_games = [] if add_experiments == True: valid_experiments = get_experiments(experiment_repo,warning=warning) if add_surveys == True: valid_surveys = get_experiments(survey_repo,warning=warning,repo_type="surveys") if add_games == True: valid_games = get_experiments(game_repo,warning=warning,repo_type="games") # If the user wants to select a subset if tasks != None: valid_experiments = [x for x in valid_experiments if os.path.basename(x) in [os.path.basename(e) for e in tasks]] valid_surveys = [x for x in valid_surveys if os.path.basename(x) in [os.path.basename(e) for e in tasks]] valid_games = [x for x in valid_games if os.path.basename(x) in [os.path.basename(e) for e in tasks]] base = {"battery_repo":battery_repo, "experiment_repo":experiment_repo, "survey_repo":survey_repo, "game_repo":game_repo, "experiments":valid_experiments, "surveys":valid_surveys, "games":valid_games} return base
def move_experiments(valid_experiments,battery_dest,repo_type="experiments"): '''move_experiments Moves valid experiments into the experiments folder in battery repo :param valid_experiments: a list of full paths to valid experiments :param battery_dest: full path to battery destination folder :param repo_type: the kind of task to move (default is experiments) ''' moved_experiments = [] for valid_experiment in valid_experiments: try: experiment_folder = os.path.basename(valid_experiment) copy_directory(valid_experiment,"%s/static/%s/%s" %(battery_dest,repo_type,experiment_folder)) moved_experiments.append(valid_experiment) except: print "Cannot move %s, will not be added." %(valid_experiment) return moved_experiments
def move_experiments(valid_experiments, battery_dest, repo_type="experiments"): '''move_experiments Moves valid experiments into the experiments folder in battery repo :param valid_experiments: a list of full paths to valid experiments :param battery_dest: full path to battery destination folder :param repo_type: the kind of task to move (default is experiments) ''' moved_experiments = [] for valid_experiment in valid_experiments: try: experiment_folder = os.path.basename(valid_experiment) copy_directory( valid_experiment, "%s/static/%s/%s" % (battery_dest, repo_type, experiment_folder)) moved_experiments.append(valid_experiment) except: print("Cannot move %s, will not be added." % (valid_experiment)) return moved_experiments
def install_experiment_static(experiment, to_dir, from_dir, update=True, version=None): '''install_experiment_static will install an experiment object static files to the battery static folder. In the case of a special expfactory template (survey, experiment, or game) the template is rendered and then saved. If successful, returns True, otherwise False. :param experiment: the expdj.apps.experiments.models.Experiment :param to_dir: the directory to install to, typically in a battery folder :param from_dir: the temporary directory :param update: if the experiment files exist, remove them and install again (an update) :param version: if specified, will write a version id to the folder in file VERSION ''' if os.path.exists(to_dir): if update == True: shutil.rmtree(to_dir) else: # Experiment static install fail, found files and update is not True return False # Copy all experiment files into the folder copy_directory(from_dir, to_dir) battery = experiment.battery router_url = ( "%s%s" % (DOMAIN_NAME, battery.get_router_url(experiment.id))).encode('utf-8') if experiment.template in ['survey', 'jspsych']: index_html = install_experiment_template(experiment=experiment, battery=battery, router_url=router_url, to_dir=to_dir) else: try: index_html = install_experiment_custom(experiment=experiment, battery=battery, router_url=router_url, to_dir=to_dir) except Exception, message: return message
def tmp_experiment(folder=None, battery_folder=None): '''generate temporary directory with experiment :param folder: full path to experiment folder to preview (experiment, survey, or game). If none specified, PWD is used :param battery_folder: full path to battery folder to use as a template. If none specified, the expfactory-battery repo will be used. ''' if folder == None: folder = os.path.abspath(os.getcwd()) if battery_folder == None: tmpdir = custom_battery_download(repos=["battery"]) # If user has supplied a local battery folder, copy to tempdir else: tmpdir = tempfile.mkdtemp() copy_directory(battery_folder, "%s/battery" % tmpdir) experiment = load_experiment("%s" % folder) tag = experiment[0]["exp_id"] # Determine experiment template experiment_type = "experiments" if experiment[0]["template"] == "survey": experiment_type = "surveys" elif experiment[0]["template"] == "phaser": experiment_type = "games" # We will copy the entire experiment into the battery folder battery_folder = "%s/battery" % (tmpdir) experiment_folder = "%s/static/%s/%s" % (battery_folder, experiment_type, tag) if os.path.exists(experiment_folder): shutil.rmtree(experiment_folder) copy_directory(folder, experiment_folder) index_file = "%s/index.html" % (battery_folder) # Generate code for js and css exp_template = get_experiment_html(experiment, experiment_folder) filey = open(index_file, "w") filey.writelines(exp_template) filey.close() os.chdir(battery_folder) return tmpdir
def tmp_experiment(folder=None,battery_folder=None): '''generate temporary directory with experiment :param folder: full path to experiment folder to preview (experiment, survey, or game). If none specified, PWD is used :param battery_folder: full path to battery folder to use as a template. If none specified, the expfactory-battery repo will be used. ''' if folder==None: folder=os.path.abspath(os.getcwd()) if battery_folder == None: tmpdir = custom_battery_download(repos=["battery"]) # If user has supplied a local battery folder, copy to tempdir else: tmpdir = tempfile.mkdtemp() copy_directory(battery_folder,"%s/battery" %tmpdir) experiment = load_experiment("%s" %folder) tag = experiment[0]["exp_id"] # Determine experiment template experiment_type = "experiments" if experiment[0]["template"] == "survey": experiment_type = "surveys" elif experiment[0]["template"] == "phaser": experiment_type = "games" # We will copy the entire experiment into the battery folder battery_folder = "%s/battery" %(tmpdir) experiment_folder = "%s/static/%s/%s" %(battery_folder,experiment_type,tag) if os.path.exists(experiment_folder): shutil.rmtree(experiment_folder) copy_directory(folder,experiment_folder) index_file = "%s/index.html" %(battery_folder) # Generate code for js and css exp_template = get_experiment_html(experiment,experiment_folder) filey = open(index_file,"w") filey.writelines(exp_template) filey.close() os.chdir(battery_folder) return tmpdir
def main(args,parser,subparser): template = 'build/docker/Dockerfile.template' # Full path to template is required if provided via input if args.input is not None: template = args.input template = get_template(template) # For now, only one database provided database = args.database studyid = args.studyid experiments = args.experiments branch = "-b %s" %os.environ.get('EXPFACTORY_BRANCH','master') headless = "false" if args.headless is True: headless = "true" template = sub_template(template,"{{studyid}}",studyid) template = sub_template(template,"{{database}}",database) template = sub_template(template,"{{headless}}",headless) template = sub_template(template,"{{branch}}",branch) if args.headless is True: bot.info("Headless build detected, you will need to generate tokens for application entry with expfactory users --new") library = get_library(key='name') apps = "\n" # Add local experiments to library, first preference local_installs = 0 for experiment in experiments: if os.path.exists(experiment): bot.info('local experiment %s found, validating...' %experiment) # Is the experiment valid? cli = ExperimentValidator() valid = cli.validate(experiment, cleanup=False) if valid is True: local_installs +=1 config = load_experiment(experiment) exp_id = config['exp_id'] # If we aren't building in the experiment directory, we need to copy there output_dir = "%s/%s" %(os.path.abspath(os.path.dirname(args.output)), exp_id) experiment_dir = os.path.abspath(experiment) if output_dir != experiment_dir: copy_directory(experiment_dir, output_dir) config['local'] = os.path.abspath(experiment) library[exp_id] = config # Warn the user that local installs are not reproducible (from recipe) if local_installs > 0: bot.warning("%s local installs detected: build is not reproducible without experiment folders" %local_installs) # Build Image with Experiments for experiment in experiments: exp_id = os.path.basename(experiment) if exp_id in library: config = library[exp_id] app = "LABEL EXPERIMENT_%s /scif/apps/%s\n" %(exp_id, exp_id) # Here add custom build routine, should be list of lines if "install" in config: commands = "\n".join(["RUN %s "%s for x in config['install']]).strip('\n') app = "%s%s\n" %(app, commands) # The final installation step, either from Github (url) or local folder if "local" in config: app = "%sADD %s /scif/apps/%s\n" %(app, exp_id, exp_id) app = "%sWORKDIR /scif/apps\nRUN expfactory install %s\n" %(app, exp_id) else: app = "%sWORKDIR /scif/apps\nRUN expfactory install %s\n" %(app, config['github']) apps = "%s%s\n" %(apps,app) else: bot.warning('%s not in library, check spelling & punctuation.' %exp_id) if apps == "\n": bot.error('No valid experiments found, cancelling recipe build.') sys.exit(1) template = sub_template(template,"{{experiments}}",apps) outfile = write_file(args.output,template) bot.log("Recipe written to %s" %outfile)
from expfactory.experiment import get_experiments, get_validation_fields from expfactory.utils import copy_directory, sub_template from expfactory.vm import custom_battery_download from glob import glob import shutil import json import os # Download experiments to temporary directory tmpdir = custom_battery_download() static_content = glob("%s/battery/static/*" %tmpdir) # Update entire static directory copy_to = os.path.abspath("static/") for content in static_content: basename = os.path.basename(content) if os.path.isfile(content): shutil.copyfile(content,"%s/%s" %(copy_to,basename)) else: if os.path.exists("%s/%s" %(copy_to,basename)): shutil.rmtree("%s/%s" %(copy_to,basename)) copy_directory(content,"%s/%s" %(copy_to,basename)) shutil.rmtree(tmpdir)
def generate_new_survey(battery, exp_id, questions, lookup=None, update=True): '''generate_new_survey will use the survey template to generate a new survey (with config.json) in the install_dir. If the folder already exists, the files will be replaced given that update=True (default) :param battery: the battery to install the experiment to. :param exp_id: the exp_id, the unique id for the survey :param questions: the file handle for the questions :param update: Replace or update the files, if the survey already exists (default is True) :param lookup: (not required) a dictionary of values to look up for the config.json ''' # First install to temporary directory tmpdir = tempfile.mkdtemp() # What is the battery install_dir? install_dir = battery.get_install_dir() # Copy the survey template to the folder (all required files) needs_validation = "%s/%s" % (tmpdir, exp_id) copy_directory(survey_template, needs_validation) # Write the questions there with open('%s/survey.tsv' % (needs_validation), 'wb+') as destination: for chunk in questions.chunks(): destination.write(chunk) # Names must have quotes if "contributors" in lookup: if len(lookup['contributors']) > 0: lookup['contributors'] = ",".join( ['"%s"' % (n) for n in lookup["contributors"].split(',')]) # Remove weird /M carriage returns if "notes" in lookup: if len(lookup["notes"]) > 0: lookup['notes'] = ''.join(lookup['notes'].replace('\r\n', '')) # Read in the template files for config.json template = get_template("surveys/new_survey/config.json.template") lookup["exp_id"] = exp_id del lookup['questions'] config = template.render(context=lookup) write_template(config.encode('utf-8'), "%s/config.json" % (needs_validation)) os.remove("%s/config.json.template" % (needs_validation)) # Finally, validate the survey. If valid, add to database. valid = validate_surveys([exp_id], tmpdir, survey_file="survey.tsv", delim="\t") if valid == True: install_folder = '%s/%s' % (install_dir, exp_id) # The version will be the datetime string version = datetime.now().strftime("%s") # Install the folder as a new experiment! new_experiment, _ = Experiment.objects.update_or_create( exp_id=exp_id, battery=battery, defaults={ "name": lookup["name"], "time": lookup["time"], "reference": lookup["reference"], "version": version, "template": "survey" }) new_experiment.save() success = install_experiment_static(experiment=new_experiment, to_dir=install_folder, from_dir=needs_validation, version=version, update=update) if success != True: # If success returns as not true, is a mesage to indicate error valid = "%s: %s" (exp_id, success) shutil.rmtree(tmpdir) return valid
def generate_base(battery_dest, tasks=None, experiment_repo=None, survey_repo=None, game_repo=None, battery_repo=None, warning=True): '''generate_base returns a folder with downloaded experiments, surveys, and battery, either specified by the user or a temporary directory, to be used by generate_local and generate (for psiturk) :param battery_dest: [required] is the output folder for your battery. This folder MUST NOT EXIST. :param battery_repo: location of psiturk-battery repo to use as a template. If not specified, will be downloaded to a temporary directory :param experiment_repo: location of a expfactory-experiments repo to check for valid experiments. If not specified, will be downloaded to a temporary directory :param survey_repo: location of a expfactory-surveys repo to check for valid surveys. If not specified, will be downloaded to a temporary directory :param tasks: a list of experiments and surveys, meaning the "exp_id" variable in the config.json, to include. This variable also conincides with the tasks folder name. :param warning: show warnings when validating experiments (default True) ''' repos = [] tmpdir = None if battery_repo == None: tmpdir = custom_battery_download(repos=['battery']) battery_repo = "%s/battery" % (tmpdir) if experiment_repo == None and survey_repo == None and game_repo == None: tmpdir = custom_battery_download(tmpdir, ['experiments', 'surveys', 'games']) experiment_repo = "%s/experiments" % (tmpdir) survey_repo = "%s/surveys" % (tmpdir) game_repo = "%s/games" % (tmpdir) # Copy battery skeleton to destination copy_directory(battery_repo, battery_dest) valid_experiments = [] valid_surveys = [] valid_games = [] if experiment_repo is not None: valid_experiments = get_experiments(experiment_repo, warning=warning) if survey_repo is not None: valid_surveys = get_experiments(survey_repo, warning=warning, repo_type="surveys") if game_repo is not None: valid_games = get_experiments(game_repo, warning=warning, repo_type="games") # If the user wants to select a subset if tasks != None: valid_experiments = [ x for x in valid_experiments if os.path.basename(x) in [os.path.basename(e) for e in tasks] ] valid_surveys = [ x for x in valid_surveys if os.path.basename(x) in [os.path.basename(e) for e in tasks] ] valid_games = [ x for x in valid_games if os.path.basename(x) in [os.path.basename(e) for e in tasks] ] base = { "battery_repo": battery_repo, "experiment_repo": experiment_repo, "survey_repo": survey_repo, "game_repo": game_repo, "experiments": valid_experiments, "surveys": valid_surveys, "games": valid_games } return base
def generate_experiment_web(output_dir,experiment_folder=None,survey_folder=None,games_folder=None, make_table=True,make_index=True,make_experiments=True,make_data=True, make_surveys=True,make_games=True): '''get_experiment_table Generate a table with links to preview all experiments :param experiment_folder: folder with experiments inside :param survey_folder: folder with surveys inside :param games_folder: folder with games inside :param output_dir: output folder for experiment and table html, and battery files :param make_table: generate table.html :param make_index: generate d3 visualization index :param make_experiments: generate experiment preview files (linked from table and index) :param make_data: generate json/tsv data to download :param make_surveys: generate static files for surveys repos :param make_games: generate static files for games repos ''' repos=["experiments","battery"] if make_surveys == True: repos.append("surveys") if make_games == True: repos.append("games") tmpdir = custom_battery_download(repos=repos) if not os.path.exists(output_dir): os.mkdir(output_dir) if experiment_folder == None: experiment_folder = "%s/experiments" %tmpdir experiments = get_experiments(experiment_folder,load=True, warning=False) experiment_tags = [x[0]["exp_id"] for x in experiments] battery_repo = "%s/battery" %(tmpdir) if survey_folder == None: survey_folder = "%s/surveys" %tmpdir if games_folder == None: games_folder = "%s/games" %tmpdir # If the user wants surveys and/or games, add them on to tasks tasks = experiments if make_surveys == True: surveys = get_experiments(survey_folder,load=True,warning=False,repo_type="surveys") survey_tags = [x[0]["exp_id"] for x in surveys] tasks = experiments + surveys if make_games == True: games = get_experiments(games_folder,load=True,warning=False,repo_type="games") games_tags = [x[0]["exp_id"] for x in games] tasks = tasks + games # Fields to keep for the table fields = ['preview','exp_id','template', 'contributors','time', 'cognitive_atlas_task_id'] valid = pandas.DataFrame(columns=fields) # Make a table of experiment information for experiment in tasks: for field in experiment[0].keys(): if field in fields: values = experiment[0][field] # Join lists with a comma if field == "reference": if values != '': values = '<a href="%s" target="_blank">%s</a>' %(values,values) if isinstance(values,list): values = ",".join(values) valid.loc[experiment[0]["exp_id"],field] = values # Add a preview link valid.loc[experiment[0]["exp_id"],"preview"] = '<a href="%s.html" target="_blank">DEMO</a>' %(experiment[0]["exp_id"]) # If the user wants to create the index page if make_index == True: output_index = os.path.abspath("%s/index.html" %output_dir) # For each experiment, we will prepare an interactive node for the site nodes = [] for experiment in tasks: nodes.append('{"cluster": 1, "radius": "10", "color": colors[%s], "exp_id": "%s" }' %(choice([0,1,2]),experiment[0]["exp_id"])) # Generate index page index_template = get_template("%s/templates/expfactory_index.html" %get_installdir()) index_template = index_template.replace("[SUB_NODES_SUB]",",".join(nodes)) index_template = index_template.replace("[SUB_TOTAL_SUB]",str(len(nodes))) filey = open(output_index,"wb") filey.writelines(index_template) filey.close() # Update entire static directory old_dirs = ["templates","static"] for folder in old_dirs: copy_to = os.path.abspath("%s/%s" %(output_dir,folder)) copy_from = "%s/battery/%s" %(tmpdir,folder) if os.path.exists(copy_to): shutil.rmtree(copy_to) copy_directory(copy_from,copy_to) # Copy the favicon to web base shutil.copyfile("%s/battery/static/favicon.ico" %tmpdir,"%s/favicon.ico" %output_dir) # Clear old experiments experiment_dir = os.path.abspath("%s/static/experiments/" %output_dir) if os.path.exists(experiment_dir): shutil.rmtree(experiment_dir) # Clear old surveys, copy updated valid surveys into survey directory if make_surveys == True: survey_dir = os.path.abspath("%s/static/surveys/" %output_dir) if os.path.exists(survey_dir): shutil.rmtree(survey_dir) valid_surveys = ["%s/%s" %(survey_folder,x[0]["exp_id"]) for x in surveys] move_experiments(valid_surveys,battery_dest=output_dir,repo_type="surveys") # Clear old surveys, copy updated valid surveys into survey directory if make_games == True: games_dir = os.path.abspath("%s/static/games/" %output_dir) if os.path.exists(games_dir): shutil.rmtree(games_dir) valid_games = ["%s/%s" %(games_folder,x[0]["exp_id"]) for x in games] move_experiments(valid_games,battery_dest=output_dir,repo_type="games") # Copy updated valid experiments into our experiment directory valid_experiments = ["%s/%s" %(experiment_folder,x[0]["exp_id"]) for x in experiments] move_experiments(valid_experiments,battery_dest=output_dir) # If the user wants to make a table if make_table == True: table_template = get_template("%s/templates/table.html" %get_installdir()) output_table = os.path.abspath("%s/table.html" %output_dir) # First prepare rendered table table = '<table id="fresh-table" class="table">\n<thead>\n' for field in fields: table = '%s<th data-field="%s" data-sortable="true">%s</th>' %(table,field,field) table = '%s\n</thead>\n<tbody>\n' %(table) for row in valid.iterrows(): table = "%s<tr>\n" %(table) for field in row[1]: table = "%s<td>%s</td>\n" %(table,field) table = "%s</tr>\n" %(table) table = "%s</tbody></table>\n" %(table) # Write the new table table_template = table_template.replace("[[SUB_TABLE_SUB]]",table) filey = open("%s/table.html" %output_dir,"wb") filey.writelines(table_template) filey.close() if make_experiments == True: experiments_template = get_template("%s/templates/experiments_categories.html" %get_installdir()) output_exp = os.path.abspath("%s/experiments.html" %output_dir) if "CIRCLE_BRANCH" in os.environ.keys(): experiment_page = table_template else: experiment_page = get_cognitiveatlas_hierarchy(experiment_tags=experiment_tags,get_html=True) # Write the new table filey = open(output_exp,"wb") filey.writelines(experiment_page) filey.close() # For each experiment, we will generate a demo page for experiment in experiments: demo_page = os.path.abspath("%s/%s.html" %(output_dir,experiment[0]["exp_id"])) exp_template = get_experiment_html(experiment,"%s/%s" %(experiment_folder,experiment[0]["exp_id"])) filey = open(demo_page,"wb") filey.writelines(exp_template) filey.close() # if the user wants to make surveys if make_surveys == True: for experiment in surveys: demo_page = os.path.abspath("%s/%s.html" %(output_dir,experiment[0]["exp_id"])) exp_template = get_experiment_html(experiment,"%s/%s" %(survey_folder,experiment[0]["exp_id"])) filey = open(demo_page,"wb") filey.writelines(exp_template) filey.close() # if the user wants to make surveys if make_games == True: for experiment in games: demo_page = os.path.abspath("%s/%s.html" %(output_dir,experiment[0]["exp_id"])) exp_template = get_experiment_html(experiment,"%s/%s" %(games_folder,experiment[0]["exp_id"])) filey = open(demo_page,"wb") filey.writelines(exp_template) filey.close() # If the user wants to make data if make_data == True: data_folder = os.path.abspath("%s/data" %output_dir) if not os.path.exists(data_folder): os.mkdir(data_folder) save_pretty_json("%s/expfactory-experiments.json" %(data_folder),json.loads(valid.to_json(orient="records"))) valid.to_csv("%s/expfactory-experiments.tsv" %(data_folder),sep="\t",index=None) valid.to_pickle("%s/expfactory-experiments.pkl" %(data_folder))
def main(args, parser, subparser): # List of experiments is required template = get_template('build/docker/Dockerfile.template') # For now, only one database provided database = args.database studyid = args.studyid experiments = args.experiments template = sub_template(template, "{{studyid}}", studyid) template = sub_template(template, "{{database}}", database) library = get_library(key='name') apps = "\n" # Add local experiments to library, first preference local_installs = 0 for experiment in experiments: if os.path.exists(experiment): bot.info('local experiment %s found, validating...' % experiment) # Is the experiment valid? cli = ExperimentValidator() valid = cli.validate(experiment, cleanup=False) if valid is True: local_installs += 1 config = load_experiment(experiment) exp_id = config['exp_id'] # If we aren't building in the experiment directory, we need to copy there output_dir = "%s/%s" % (os.path.abspath( os.path.dirname(args.output)), exp_id) experiment_dir = os.path.abspath(experiment) if output_dir != experiment_dir: copy_directory(experiment_dir, output_dir) config['local'] = os.path.abspath(experiment) library[exp_id] = config # Warn the user that local installs are not reproducible (from recipe) if local_installs > 0: bot.warning( "%s local installs detected: build is not reproducible without experiment folders" % local_installs) # Build Image with Experiments for experiment in experiments: exp_id = os.path.basename(experiment) if exp_id in library: config = library[exp_id] app = "LABEL EXPERIMENT_%s /scif/apps/%s\n" % (exp_id, exp_id) # Here add custom build routine, should be list of lines if "install" in config: commands = "\n".join( ["RUN %s " % s for x in config['install']]).strip('\n') app = "%s%s\n" % (app, commands) # The final installation step, either from Github (url) or local folder if "local" in config: app = "%sADD %s /scif/apps/%s\n" % (app, exp_id, exp_id) app = "%sWORKDIR /scif/apps\nRUN expfactory install %s\n" % ( app, exp_id) else: app = "%sWORKDIR /scif/apps\nRUN expfactory install %s\n" % ( app, config['github']) apps = "%s%s\n" % (apps, app) else: bot.warning('%s not in library, check spelling & punctuation.' % exp_id) if apps == "\n": bot.error('No valid experiments found, cancelling recipe build.') sys.exit(1) template = sub_template(template, "{{experiments}}", apps) outfile = write_file(args.output, template) bot.log("Recipe written to %s" % outfile)
def main(args, parser, subparser): template = "build/docker/Dockerfile.template" # Full path to template is required if provided via input if args.input is not None: template = args.input template = get_template(template) # For now, only one database provided database = args.database studyid = args.studyid experiments = args.experiments branch = "-b %s" % os.environ.get("EXPFACTORY_BRANCH", "master") headless = "false" if args.headless is True: headless = "true" template = sub_template(template, "{{studyid}}", studyid) template = sub_template(template, "{{database}}", database) template = sub_template(template, "{{headless}}", headless) template = sub_template(template, "{{branch}}", branch) if args.headless is True: bot.info( "Headless build detected, you will need to generate tokens for application entry with expfactory users --new" ) library = get_library(key="name") apps = "\n" # Add local experiments to library, first preference local_installs = 0 for experiment in experiments: if os.path.exists(experiment): bot.info("local experiment %s found, validating..." % experiment) # Is the experiment valid? cli = ExperimentValidator() valid = cli.validate(experiment, cleanup=False) if valid is True: local_installs += 1 config = load_experiment(experiment) exp_id = config["exp_id"] # If we aren't building in the experiment directory, we need to copy there output_dir = "%s/%s" % ( os.path.abspath(os.path.dirname(args.output)), exp_id, ) experiment_dir = os.path.abspath(experiment) if output_dir != experiment_dir: copy_directory(experiment_dir, output_dir) config["local"] = os.path.abspath(experiment) library[exp_id] = config # Warn the user that local installs are not reproducible (from recipe) if local_installs > 0: bot.warning( "%s local installs detected: build is not reproducible without experiment folders" % local_installs ) # Build Image with Experiments for experiment in experiments: exp_id = os.path.basename(experiment) if exp_id in library: config = library[exp_id] app = "LABEL EXPERIMENT_%s /scif/apps/%s\n" % (exp_id, exp_id) # Here add custom build routine, should be list of lines if "install" in config: commands = "\n".join(["RUN %s " % s for x in config["install"]]).strip( "\n" ) app = "%s%s\n" % (app, commands) # The final installation step, either from Github (url) or local folder if "local" in config: app = "%sADD %s /scif/apps/%s\n" % (app, exp_id, exp_id) app = "%sWORKDIR /scif/apps\nRUN expfactory install %s\n" % ( app, exp_id, ) else: app = "%sWORKDIR /scif/apps\nRUN expfactory install %s\n" % ( app, config["github"], ) apps = "%s%s\n" % (apps, app) else: bot.warning("%s not in library, check spelling & punctuation." % exp_id) if apps == "\n": bot.error("No valid experiments found, cancelling recipe build.") sys.exit(1) template = sub_template(template, "{{experiments}}", apps) outfile = write_file(args.output, template) bot.log("Recipe written to %s" % outfile)