# help: python3 makeini.py -h import argparse import errno import glob import logging import os import sys import time import itertools from numpy import * from shutil import copy2, rmtree, move try: import xml.etree.cElementTree as ET except ImportError: import xml.etree.ElementTree as ET SUCCESS = 0 FAILURE = 1 ego = os.path.basename(sys.argv[0]).split(".")[0] + ".txt" print("ego: ", ego) logfile = "log_%s"%ego logging.basicConfig(filename=logfile, level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') # ============= some directories ============= #HOME = os.path.expanduser("~") #TRUNK = HOME + "/Workspace/ped|ynamics/JuPedSim/jpscore/" #JPSCORE = TRUNK + "bin/jpscore" #CURDIR = os.getcwd() # ============= some default dictionaries ============= default_value = {'tmax':1000, 'seed':1111, 'geometry':'', 'number':1, 'num_threads':1, 'file':'', 'model_id':1, 'exit_crossing_strategy':3, 'cell_size':2.2, 'operational_model_id':1} # only these tags can be multiplied tags = ['tmax', 'seed', 'geometry', 'exit_crossing_strategy', 'num_threads', 'stepsize'] # format tag-attribute attributes_tags = ['group-pre_movement_mean', 'group-number', 'group-router_id', 'group-agent_parameter_id', 'group-premovement_sigma', 'agents-operational_model_id', 'linkedcells-cell_size', 'v0-mu', 'v0-sigma', 'v0_upstairs-mu', 'v0_upstairs-sigma', 'v0_downstairs-mu', 'v0_downstairs-sigma', 'bmax-mu', 'bmin-mu', 'amin-mu', 'tau-mu', 'atau-mu', 'force_ped-dist_max', 'force_ped-disteff_max', 'force_ped-interpolation_width', 'force_ped-nu', 'force_ped-b', 'force_ped-c', 'force_wall-dist_max', 'force_wall-disteff_max', 'force_wall-interpolation_width', 'force_wall-nu', 'force_wall-b', 'force_wall-c', 'source-frequency', 'source-agents_max', ] import numpy as np # cor_tags = np.unique([att.split("_")[0] for att in attributes_tags]).astype(str)a cor_tags = [att.split("-")[0] for att in attributes_tags] attributes = [att.split(tag+"-")[1] for (att, tag) in zip(attributes_tags, cor_tags)] cor_tags = np.unique(cor_tags) attributes = np.unique(attributes) input_tags = {} # ======================================================= def getParserArgs(): parser = argparse.ArgumentParser(description='Generate inifiles for jpscore simulations. ') parser.add_argument("-f", "--file", metavar='in-file', required=True, help='Master inifile') args = parser.parse_args() return args # ======================================================= def make_dir(path): if os.path.exists(path): rmtree(path) try: os.makedirs(path) except OSError as exception: if exception.errno != errno.EEXIST: raise # ======================================================= def get_tag(node): # geometry if node.tag == "geometry": geometries = [] geom = glob.glob("%s/*.xml"%node.text) for g in geom: geometries.append('../geometries' + g.split(".xml")[0].split("geometries")[1] + ".xml") # the geometries are relative to the inifiles directory #print geometries return geometries else: text = node.text if text: value = eval(text) else: value = default_value[node.tag] return value # ======================================================= def get_attribute(node): text = '' values = [] for node_attrib in list(node.attrib.keys()): if node_attrib in attributes: text = node.attrib[node_attrib] if text: value = eval(text) else: value = 0 if isinstance(value, list) or isinstance(value, ndarray): if len(value) > 1: values.append([value, str(node.tag)+"-"+str(node_attrib), node_attrib]) return values # ======================================================= def get_product(root): """ read values, which may be lists or arrays of len>1 and return a list of dics composed of the cartesian product of these lists. example: we read from the file (xml --> root) the following {'num_threads': [5, 1, 2], 'tmax': [1, 2]} return is: [ {'numCPU': 5, 'tmax': 1}, {'numCPU': 5, 'tmax': 2}, {'numCPU': 1, 'tmax': 1}, {'numCPU': 1, 'tmax': 2}, {'numCPU': 2, 'tmax': 1}, {'numCPU': 2, 'tmax': 2} ] """ for node in root.iter(): tag = node.tag if tag in tags: # ignore tags that are not of interest d = get_tag(node) if isinstance(d, list) or isinstance(d, ndarray) or isinstance(d, range): # in case some tags have multiple values if tag not in input_tags and len(d) > 1: # ignore lists with one element (equiv to scalars) # if tag in tags: input_tags[tag] = d elif bool(set(node.attrib.keys()) & set(attributes)): # check our list of attributes values = get_attribute(node) # d, atr_tag, attr # value, atr_tag, atr for value in values: d = value[0] atr_tag = value[1] input_tags[atr_tag] = d else: continue result_prod = [dict(zip(input_tags, x)) for x in itertools.product(*iter(input_tags.values()))] return result_prod # ======================================================= def make_filename(directory, d): name = "%s/inifiles/ini"%directory traj = "../trajectories/traj" #%directory for key, value in d.items(): if key == "geometry": value = os.path.basename(value) # if key == "num_threads": # value = "numCPU" name += "_" + key + "_" + str(value) traj += "_" + key + "_" + str(value) if not name.endswith("xml"): name += ".xml" if not traj.endswith("xml"): traj += ".xml" #print "name", (name) return name, traj # ======================================================= def update_tag_value(root, tag, value): for rank in root.iter(tag): rank.text = str(value) # ======================================================= def update_attrib_value(root, attr_tag, value): # location print ("update_attrib_value: ", attr_tag, value) # raw_input() if attr_tag == "location": # e.g. location for r in root.iter(): if attr_tag in r.attrib: r.attrib[attr_tag] = str(value) return attr = attr_tag.split("-")[1] cor_tag = attr_tag.split("-")[0] for r in root.iter(cor_tag): if attr in r.attrib: r.attrib[attr] = str(value) # ======================================================= def make_file(masterfile, tree, result): """ Given a list of dictionaries produce an xml file for each dic. The file is first copied from masterfile. """ directory = os.path.dirname(os.path.abspath(masterfile)) #args.directory root = tree.getroot() for item in result: newfile, trajfile = make_filename(directory, item) copy2(masterfile, newfile) #update trajectory file update_attrib_value(root, "location", trajfile) if not os.path.isfile(newfile): logging.error("make_file: could not create file %s"%newfile) sys.exit(FAILURE) for tag, value in item.items(): # print "tag: ", tag, "value:", value # raw_input() if tag in attributes_tags: update_attrib_value(root, tag, value) else: update_tag_value(root, tag, value) logging.info('>> %s'%newfile) tree.write(newfile) # ======================================================= if __name__ == "__main__": time1 = time.clock() args = getParserArgs() masterfile = args.file if not os.path.isfile(masterfile): logging.error("ERROR: file %s does not exist."%masterfile) sys.exit(FAILURE) directory = os.path.dirname(os.path.abspath(masterfile)) #args.directory logging.info('working directory = <%s>'%directory) logging.info('master inifile = <%s>'%masterfile) make_dir("%s/trajectories"%directory) make_dir("%s/inifiles"%directory) tree = ET.parse(masterfile) root = tree.getroot() result = get_product(root) make_file(masterfile, tree, result) time2 = time.clock() print(directory) print("%s/%s"%(directory, logfile)) print(os.path.isfile("%s/%s"%(directory, logfile))) if not os.path.isfile("%s/%s"%(directory, logfile)): move(logfile, directory) logging.info('time elapsed: %.2f to generate %d files'%(time2 - time1, len(result))) if 0: sys.exit(FAILURE) else: sys.exit(SUCCESS)