def __init__(self, config, GS_dir): """ Load YAML config into a dictionary and assign values to variables for cleanliness """ _config = load_yaml_config(config, quiet=True) # Reset text colours after colourful print statements init(autoreset=True) self.model_name = _config['model_name'] self.m_med = _config['m_med'] self.m_d = _config['m_d'] self.n_f = _config['n_f'] self.r_inv = _config['r_inv'] self.x_sec_mg = _config['x_sec_mg'] self.alpha_d = _config['alpha_d'] self.process_type = _config['process_type'] self.year = _config['year'] self.GS_dir = GS_dir # Run everything print(Fore.CYAN + "Writing gen fragment...") self.set_dark_params() self.get_lambda_d() self.get_xsec() self.get_pythia_info() self.write_fragment()
def xsec_from_dict(in_file, m_med): """ Get cross section from yaml dictionary """ xsec_dict = load_yaml_config(in_file, quiet=True) try: x_sec = xsec_dict[m_med] except KeyError: if m_med < min(xsec_dict.keys()) or m_med > max(xsec_dict.keys()): raise ValueError( "m_med = {} is outside the range of the dictionary in '{}'". format(m_med, in_file)) else: # Cross sections given in increments of 100 GeV. Round m_med if required x_sec = xsec_dict[int(round(m_med, -2))] return x_sec
def main(config, resub=False, mode='batch'): # Load YAML config into a dictionary and assign values to variables for cleanliness input_params = load_yaml_config(config) # Set variables from config file process_type = input_params['process_type'] m_med = input_params['m_med'] n_events = input_params['n_events'] n_jobs = input_params['n_jobs'] m_d = input_params['m_d'] r_inv = input_params['r_inv'] alpha_d = input_params['alpha_d'] year = input_params['year'] # Check arguments in config file basic_checks(input_params) # Set process-specific variables if 's-channel' in process_type: med_type = 'Zp' model_prefix = 'SVJ_s' template_prefix = 'DMsimp_SVJ_s_spin1' elif 't-channel' in process_type: med_type = 'Phi' model_prefix = 'SVJ_t' template_prefix = 'DMsimp_SVJ_t' default_model_dir = os.path.join(os.environ['SVJ_MODELS_DIR'], template_prefix+'_editTemplate') model_name = '{prefix}_{year}_m{med}-{m_med}_mDQ-{m_d}_rinv-{rinv}_aD-{alphad}'.format( rinv=str(r_inv).replace('.', 'p'), alphad=str(alpha_d).replace('.', 'p'), # MadGraph doesn't like '.' in the model name prefix=model_prefix, med=med_type, **input_params) total_events = n_events * n_jobs # Remove failed gridpack for model if resubmitted if resub: print(Fore.CYAN + "Removing failed gridpack and resubmitting...") for file in glob.glob(os.path.join(os.environ['MG_GENPROD_DIR'], model_name+'*')): try: if os.path.isfile(file): os.remove(file) elif os.path.isdir(file): shutil.rmtree(file) except OSError as e: print("Error: {0} - {1}.".format(e.filename, e.strerror)) # If required, append config file with new parameters for simplicity in future steps with open(config, 'r+') as f: print(Fore.CYAN + "Updating config file with new parameters...") original_str = f.readlines() # Delete contents of file and update f.seek(0) f.truncate() # Strip model name and total events if they've changed since last use of config, and also blank lines for line in original_str: if any(line.startswith(x) for x in ['model_name:', 'total_events:', '\n']): continue else: f.write(line) # Write new parameters at the end of the file f.write("\nmodel_name: {}\ntotal_events: {}\n".format(model_name, total_events)) new_model_dir = os.path.join(os.environ['SVJ_MODELS_DIR'], model_name) if os.path.exists(new_model_dir): print("Model of type {} with parameters m_med = {}, m_d = {} already exists!".format(process_type, m_med, m_d)) else: # Copy model files to new directory and change relevant parameters according to config print(Fore.CYAN + "Copying template model...") shutil.copytree(default_model_dir, new_model_dir) # Read the parameters file (containing the dark particle masses) in the new model directory with open(os.path.join(new_model_dir, 'parameters.py'), 'r+') as f: old_params = Template(f.read()) # Fill placeholders with values chosen by user new_params = old_params.substitute(dark_quark_mass=str(m_d), mediator_mass=str(m_med)) f.seek(0) f.truncate() f.write(new_params) print(Fore.MAGENTA + "New parameters written in model files!") # Write param_card text file call('python {}'.format(os.path.join(new_model_dir, 'write_param_card.py')), shell=True) input_cards_dir = os.path.join(os.environ['SVJ_MG_INPUT_DIR'], model_name+"_input") # Create directory to store input cards and model files for MadGraph if not os.path.exists(input_cards_dir): os.mkdir(input_cards_dir) else: print("Directory containing MadGraph input cards exists! No need to create it.") # Remove previous input cards in case, e.g., n_events has changed for old_file in glob.glob(os.path.join(input_cards_dir, '*.dat')): os.remove(old_file) # Copy MadGraph input files from template card directory # Even if input_cards_dir existed before, copy the template files over in case parameters have changed for in_file in glob.glob(os.path.join(os.environ['SVJ_MG_INPUT_DIR'], template_prefix+'_input_template/*.dat')): # Get the suffix of the template card for specifying the basename in the dest. path card_type = re.search("(?<={0})(\w+).dat".format(template_prefix), in_file).group(0) shutil.copy(in_file, os.path.join(input_cards_dir, model_name+card_type)) # In input files, fill replacement fields with values chosen by user for modelFile in glob.glob(os.path.join(input_cards_dir, '*.dat')): with open(modelFile, 'r+') as mg_card: old_params = mg_card.read() # Make sure there are no curly braces in the input cards except those containing the replacement fields new_params = old_params.format(modelName=model_name, totalEvents=total_events, lhaid=lhaID_dict[year]) mg_card.seek(0) mg_card.truncate() mg_card.write(new_params) print(Fore.MAGENTA + "Parameters written for input card", os.path.basename(modelFile)) # Zip up model directory, specifying basedir to zip enclosing folder, not just files shutil.make_archive(os.path.join(input_cards_dir, model_name), 'tar', os.environ['SVJ_MODELS_DIR'], model_name) print(Fore.MAGENTA + "Copied model files to input directory!") # Require relative path between MG input files and genproductions' gridpack generation script rel_cards_dir = os.path.relpath(input_cards_dir, os.environ['MG_GENPROD_DIR']) # Run the gridpack generation call("{}/runGridpackGeneration.sh {} {} {}".format(os.path.dirname(os.path.realpath(__file__)), model_name, rel_cards_dir, mode), shell=True)
def main(config): # Load YAML config into a dictionary and assign values to variables for cleanliness input_params = load_yaml_config(config) model_name = input_params['model_name'] total_events = input_params['total_events'] n_jobs = input_params['n_jobs'] out_split_lhe = input_params['lhe_file_path'] process_type = input_params['process_type'] # Check arguments in config file basic_checks(input_params) # Set up some path variables for use later genprod_dir = os.environ['MG_GENPROD_DIR'] default_gridpack_dir = os.path.join(genprod_dir, model_name) lhe_gen_dir = os.path.join(default_gridpack_dir, model_name + '_gridpack', 'work', 'gridpack') gridpack_outdir = os.path.join(os.environ['SVJ_MG_FILES_DIR'], 'gridpacks') # Get cross section from gridpack generation log file with open(os.path.join(lhe_gen_dir, 'gridpack_generation.log'), 'r') as f: log_str = f.read() x_sec_mg = re.search("(?<=Cross-section : )(\d*.\d+)", log_str).group(0) # Append cross section to config file if not included already with open(config, 'r+') as f: config_str = f.read() if str(x_sec_mg) not in config_str: print( Fore.CYAN + "Appending config file with cross section as calculated by MadGraph..." ) f.seek(0) config_lines = f.readlines() f.seek(0) f.truncate() for i in config_lines: if i.startswith('x_sec_mg'): continue else: f.write(i) f.write("x_sec_mg: {}\n".format(x_sec_mg)) # Copy gridpack tarball to new directory for tarball in glob.glob(os.path.join(genprod_dir, model_name + '*.xz')): print(Fore.CYAN + "Copying {} to {}/".format(os.path.basename(tarball), gridpack_outdir)) shutil.copyfile( tarball, os.path.join(gridpack_outdir, os.path.basename(tarball))) os.remove(tarball) # Run the script produced with the gridpack to get the LHE file out and copy to gridpacks dir seed = random.randint(0, 1000000) call("cd {}; ./runcmsgrid.sh {} {}".format(lhe_gen_dir, total_events, seed), shell=True) in_lhe = os.path.join(gridpack_outdir, model_name + '_LHE.lhe') shutil.copyfile(os.path.join(lhe_gen_dir, 'cmsgrid_final.lhe'), in_lhe) # Delete untarred gridpack as it takes up unnecessary space shutil.rmtree(default_gridpack_dir) print(Fore.MAGENTA + "Removed untarred version of gridpack!") # Change PDGIDs for dark particles in preparation for hadronisation call('{}/utils/pid_change.sh {}'.format(os.environ['SVJ_TOP_DIR'], in_lhe), shell=True) # Split the LHE file, the output files being stored in the current directory print(Fore.CYAN + "Splitting LHE file...") splitLHE(inputFile=in_lhe, outFileNameBase=model_name + '_split', numFiles=n_jobs) os.remove(in_lhe) # Copy the split LHE files to directory specified by user if not os.path.exists(out_split_lhe): os.mkdir(out_split_lhe) for split_file in glob.glob( os.path.join(os.getcwd(), model_name + '_split*.lhe')): shutil.copy(split_file, out_split_lhe) os.remove(split_file) print(Fore.MAGENTA + "Split LHE files moved to {}".format(out_split_lhe))
def main(config): # Define variable for directory of script this_dir = os.path.dirname(os.path.realpath(__file__)) # Load YAML config into a dictionary and assign values to variables for cleanliness config = os.path.abspath(config) input_params = load_yaml_config(config) work_space = input_params['work_space'] lhe_file_path = input_params['lhe_file_path'] n_events = input_params['n_events'] n_jobs = input_params['n_jobs'] model_name = input_params['model_name'] year = input_params['year'] # Check arguments in config file thorough_checks(input_params) # Make a list of split LHE files for checks lhe_files = [] for file in os.listdir(lhe_file_path): if '{}_split'.format(model_name) in file and file.endswith('.lhe'): lhe_files.append(os.path.join(lhe_file_path, file)) if n_jobs > len(lhe_files): sys.exit( 'Number of jobs exceeds number of LHE files in directory. Check and try again.' ) if not os.path.exists(work_space): print(Fore.CYAN + "Work space doesn't exist. Creating it now...") os.makedirs(work_space) shutil.copy( os.path.join(os.environ['SVJ_TOP_DIR'], 'pileup_filelist_{}.txt'.format(year)), work_space) # Initialise proxy of grid certificate if required if 'root://' in lhe_file_path and 'X509_USER_PROXY' not in os.environ.keys( ): grid_cert_path = '{}/x509up_u{}'.format(work_space, os.getuid()) call('voms-proxy-init --voms cms --valid 168:00 --out {}'.format( grid_cert_path), shell=True) os.environ['X509_USER_PROXY'] = grid_cert_path # Get CMSSW versions and architecture info cmssw_info = CmsswInfo(year) cmssw_info.initialise_envs(location=work_space) if os.getcwd() != this_dir: os.chdir(this_dir) # Create additional directories gen_frag_dir = os.path.join(work_space, cmssw_info.gensim['version'], 'src', 'Configuration', 'GenProduction', 'python') extra_fullsim_dirs = [ gen_frag_dir, '{}/logs/{}'.format(work_space, model_name), '{}/output'.format(work_space), '{}/submission_scripts/{}'.format(work_space, model_name), ] for dir in extra_fullsim_dirs: if not os.path.exists(dir): os.makedirs(dir) # Create the gen fragment gen_frag = os.path.basename( WriteGenSimFragment(config, gen_frag_dir).out_file) # Compile after everything is written to ensure gen fragment can be linked to cmssw_info.compile_env(location=work_space, version=cmssw_info.gensim['version'], arch=cmssw_info.gensim['arch']) # Create scripts to hadd output files and resubmit failed jobs write_combine_script(work_space, model_name, cmssw_info.nano['version']) write_resubmitter_script(work_space, model_name, n_jobs) write_cleanup_script(work_space, model_name) lhe_base = os.path.join(lhe_file_path, '{}_split'.format(model_name)) sub_args = (work_space, gen_frag, lhe_base, model_name, n_events, year) # Write a single job file to submit everything at once main_job = HTCondorJob(*sub_args, queue=n_jobs) call('condor_submit {}'.format(main_job.job_file), shell=True) print(Fore.MAGENTA + "Jobs submitted. Monitor them with 'condor_q $USER'") print( Fore.CYAN + "Writing individual job files to make resubmitting failed jobs easier..." ) for seed in xrange(n_jobs): HTCondorJob(*sub_args, seed=seed)
Style.RESET_ALL) if __name__ == '__main__': parser = ArgumentParser(description=__doc__, formatter_class=ArgumentDefaultsHelpFormatter) parser.add_argument("config", type=str, help="Path to YAML config to parse") group = parser.add_mutually_exclusive_group(required=True) group.add_argument('-b', '--basic', action="store_true", help="Perform basic config checks") group.add_argument('-t', '--thorough', action="store_true", help="Perform thorough config checks") args = parser.parse_args() print(Fore.MAGENTA + "Checking config file...", Style.RESET_ALL) config_dict = load_yaml_config(args.config) if args.basic: basic_checks(config_dict) elif args.thorough: thorough_checks(config_dict) sys.exit("Completed")
def __init__(self, config): self.config = config self.in_params = load_yaml_config(self.config) self.n_jobs = in_params['n_jobs']