Skip to content

Commit 29a9a85

Browse files
committed
general clean up and documentation
1 parent 71b9c76 commit 29a9a85

10 files changed

Lines changed: 247 additions & 333 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ The `PU0` files above were merged and are stored under `/data_CMS/cms/alves/L1HG
103103
<a id="job-submission"></a>
104104
## Job Submission
105105

106-
Job submission to HT Condor is handled through `bye_splits/production/submit_scripts/job_submit.py` using the `job` section of `config.yaml` for its configuration. The configuration should include usual condor variables, i.e `user`, `proxy`, `queue`, and `local`, as well as a path to the `script` you would like to run on condor and a list of `arguments` that the script accepts. It then contains a section for each particle type which should contain a `submit_dir`, i.e. the directory in which to read and write submission related files, `files` which should be a `.txt` file containing the values you would like to iterate over, and `files_per_batch` which can be any number between 1 and the total number of values you would like to run.
106+
Job submission to HT Condor is handled through `bye_splits/production/submit_scripts/job_submit.py` using the `job` section of `config.yaml` for its configuration. The configuration should include usual condor variables, i.e `user`, `proxy`, `queue`, and `local`, as well as a path to the `script` you would like to run on condor. The `arguments` sub-section should contain `key/value` pairs matching the expected arguments that `script` accepts. The variable that you would like to iterate over should be set in `iterOver` and its value should correspond to a `key` in the `arguments` sub-section whose value is a list containing the values the script should iterate over. It then contains a section for each particle type which should contain a `submit_dir`, i.e. the directory in which to read and write submission related files, and `args_per_batch` which can be any number between 1 and `len(arguments[<iterOver>])`.
107107

108108

109109
<a id="org0bc224d"></a>

bye_splits/production/produce.cc

Lines changed: 0 additions & 94 deletions
This file was deleted.

bye_splits/production/submit_scripts/job_submit.py

Lines changed: 94 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -7,51 +7,105 @@
77
parent_dir = os.path.abspath(__file__ + 5 * "../")
88
sys.path.insert(0, parent_dir)
99

10-
from bye_splits.utils import params, common
10+
from bye_splits.utils import params, common, job_helpers
1111

1212
import subprocess
1313
import yaml
1414

15-
# Read particle specific variables from the YAML file
16-
particle_var = lambda part, var: config["job"][part][var]
17-
1815
class JobBatches:
16+
"""Class for setting up job batches and setting configuration
17+
variables. The function setup_batches() will take the list in
18+
config[arguments[<iterOver>]] and return a list of lists containing
19+
<args_per_batch> values in each sublist. Example for five total values
20+
with <args_per_batch> = 2:
21+
[0.01, 0.02, 0.03, 0.04, 0.05] --> [[0.01, 0.02], [0.03, 0.04], [0.05]]"""
22+
1923
def __init__(self, particle, config):
2024
self.particle = particle
21-
self.config = config
25+
self.config = config
2226
self.iterOver = config["job"]["iterOver"]
27+
self.particle_var = lambda part, var: config["job"][part][var]
2328

2429
def setup_batches(self):
2530
total = self.config["job"]["arguments"][self.iterOver]
2631

27-
vals_per_batch = particle_var(self.particle, "files_per_batch")
32+
vals_per_batch = self.particle_var(self.particle, "args_per_batch")
2833

2934
batches = [total[i: i + vals_per_batch] for i in range(0, len(total), vals_per_batch)]
3035

3136
return batches
3237

3338
class CondJobBase:
3439
def __init__(self, particle, config):
35-
self.particle = particle
36-
self.script = config["job"]["script"]
37-
self.iterOver = config["job"]["iterOver"]
38-
self.args = config["job"]["arguments"]
39-
self.queue = config["job"]["queue"]
40-
self.proxy = config["job"]["proxy"]
41-
self.local = config["job"]["local"]
42-
self.user = config["job"]["user"]
43-
self.particle_dir = particle_var(self.particle, "submit_dir")
44-
self.batches = JobBatches(particle, config).setup_batches()
40+
self.particle = particle
41+
self.script = config["job"]["script"]
42+
self.iterOver = config["job"]["iterOver"]
43+
self.args = config["job"]["arguments"]
44+
self.queue = config["job"]["queue"]
45+
self.proxy = config["job"]["proxy"]
46+
self.local = config["job"]["local"]
47+
self.user = config["job"]["user"]
48+
self.batch = JobBatches(particle, config)
49+
self.particle_dir = self.batch.particle_var(self.particle, "submit_dir")
50+
self.batches = self.batch.setup_batches()
51+
52+
def _write_arg_keys(self, current_version):
53+
"""Writes the line containing the argument
54+
names to the buffer list."""
55+
56+
arg_keys = ["Arguments ="]
57+
for arg in self.args.keys():
58+
arg_keys.append("$({})".format(arg))
59+
arg_keys = " ".join(arg_keys) + "\n"
60+
61+
current_version.append(arg_keys)
62+
63+
def _write_arg_values(self, current_version):
64+
"""Adds the argument values, where the batch lists are converted
65+
to strings as [val_1, val_2, ...] --> "[val_1;val_2]".
66+
The choice of a semicolon as the delimiter is arbitrary but it
67+
cannot be a comma because this is the delimeter condor itself uses.
68+
69+
Example:
70+
71+
queue radius, particle from (
72+
[0.01, 0.02], photon
73+
)
74+
incorrectly assigns radius="[0.01", particle="0.02]"
75+
76+
queue radius, particle from (
77+
[0.01;0.02], photon
78+
)
79+
correctly assigns radius="[0.01, 0.02]", particle="photon"
80+
"""
81+
arg_keys = ", ".join(self.args.keys())
82+
arg_keys = "queue " + arg_keys + " from (\n"
83+
current_version.append(arg_keys)
84+
for batch in self.batches:
85+
sub_args = list(self.args.keys())[1:]
86+
arg_vals = [self.args[key] for key in sub_args]
87+
all_vals = ["{}".format(batch).replace(", ", ";")]+arg_vals
88+
all_vals = ", ".join(all_vals) + "\n"
89+
current_version.append(all_vals)
90+
91+
current_version.append(")")
4592

4693
def prepare_batch_submission(self):
94+
"""Writes the .sh script that constitutes the executable
95+
in the .sub script. The basename will be the same as the fundamental
96+
script, followed by a version number. Stores the contents in a list that's
97+
used as a buffer and checked against the content in previous
98+
versions, only writing the file if an identical file doesn't
99+
already exist. The version number will be incrimented in this case."""
100+
47101
sub_dir = "{}subs/".format(self.particle_dir)
48102

49-
if not os.path.exists(sub_dir):
50-
os.makedirs(sub_dir)
103+
common.create_dir(sub_dir)
104+
51105
script_basename = os.path.basename(self.script).replace(".sh", "").replace(".py", "")
52106

53107
submit_file_name_template = "{}{}_submit.sh".format(sub_dir, script_basename)
54-
submit_file_versions = common.grab_most_recent(submit_file_name_template, return_all=True)
108+
submit_file_versions = job_helpers.grab_most_recent(submit_file_name_template, return_all=True)
55109

56110
current_version = []
57111
current_version.append("#!/usr/bin/env bash\n")
@@ -71,26 +125,27 @@ def prepare_batch_submission(self):
71125
current_version.append("bash {}".format(self.script))
72126

73127
# Write the file only if an identical file doesn't already exist
74-
self.sub_file = common.conditional_write(submit_file_versions, submit_file_name_template, current_version)
128+
self.sub_file = job_helpers.conditional_write(submit_file_versions, submit_file_name_template, current_version)
75129

76130
def prepare_multi_job_condor(self):
131+
"""Writes the .sub script that is submitted to HT Condor.
132+
Follows the same naming convention and conditional_write()
133+
procedure as the previous function."""
134+
77135
log_dir = "{}logs/".format(self.particle_dir)
78136

79137
script_basename = os.path.basename(self.script).replace(".sh", "").replace(".py", "")
80138

81139
job_file_name_template = "{}jobs/{}.sub".format(self.particle_dir, script_basename)
82140

83-
job_file_versions = common.grab_most_recent(job_file_name_template, return_all=True)
141+
job_file_versions = job_helpers.grab_most_recent(job_file_name_template, return_all=True)
84142

85143
current_version = []
86144
current_version.append("executable = {}\n".format(self.sub_file))
87145
current_version.append("Universe = vanilla\n")
88-
if len(self.args) > 0:
89-
current_version.append("Arguments =")
90146

91-
for arg in self.args.keys():
92-
current_version.append(" $({}) ".format(arg))
93-
current_version.append("\n")
147+
if len(self.args) > 0:
148+
self._write_arg_keys(current_version)
94149

95150
current_version.append("output = {}{}_C$(Cluster)P$(Process).out\n".format(log_dir, script_basename))
96151
current_version.append("error = {}{}_C$(Cluster)P$(Process).err\n".format(log_dir, script_basename))
@@ -100,52 +155,36 @@ def prepare_multi_job_condor(self):
100155
current_version.append("WNTag = el7\n")
101156
current_version.append('+SingularityCmd = ""\n')
102157
current_version.append("include: /opt/exp_soft/cms/t3/t3queue |\n")
103-
158+
104159
if len(self.args.keys()) > 0:
105-
arg_keys = ", ".join(self.args.keys())
106-
arg_keys = "queue " + arg_keys + " from (\n"
107-
current_version.append(arg_keys)
108-
for batch in self.batches:
109-
sub_args = list(self.args.keys())[1:]
110-
arg_vals = [self.args[key] for key in sub_args]
111-
all_vals = ["{}".format(batch).replace(", ", ";")]+arg_vals
112-
all_vals = ", ".join(all_vals) + "\n"
113-
current_version.append(all_vals)
114-
115-
current_version.append(")")
160+
self._write_arg_values(current_version)
116161

117162
# Write the file only if an identical file doesn't already exist
118-
self.submission_file = common.conditional_write(job_file_versions, job_file_name_template, current_version) # Save to launch later
163+
self.submission_file = job_helpers.conditional_write(job_file_versions, job_file_name_template, current_version) # Save to launch later
119164

120165
class CondJob:
166+
"""Creates the job directories and files
167+
with prepare_jobs() and runs the jobs with
168+
launch_jobs()."""
169+
121170
def __init__(self, particle, config):
122171
self.base = CondJobBase(particle=particle, config=config)
123172

124-
125173
def prepare_jobs(self):
126174

127-
configs = lambda dir: dir + "configs"
128-
jobs = lambda dir: dir + "jobs"
129-
logs = lambda dir: dir + "logs"
130-
131-
config_dir = configs(self.base.particle_dir)
132-
job_dir = jobs(self.base.particle_dir)
133-
log_dir = logs(self.base.particle_dir)
175+
config_dir = self.base.particle_dir + "configs"
176+
job_dir = self.base.particle_dir + "jobs"
177+
log_dir = self.base.particle_dir + "logs"
134178

135-
if not os.path.exists(config_dir):
136-
os.makedirs(config_dir)
137-
if not os.path.exists(job_dir):
138-
os.makedirs(job_dir)
139-
if not os.path.exists(log_dir):
140-
os.makedirs(log_dir)
179+
for d in (config_dir, job_dir, log_dir):
180+
common.create_dir(d)
141181

142182
self.base.prepare_batch_submission()
143183
self.base.prepare_multi_job_condor()
144184

145-
146185
def launch_jobs(self):
147186

148-
if self.base.local == True:
187+
if self.base.local:
149188
machine = "local"
150189
else:
151190
machine = "llrt3.in2p3.fr"

bye_splits/scripts/cluster_size/condor/run_cluster.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# coding: utf-8
22

3-
_all_ = []
3+
_all_ = ['cluster_radius']
44

55
import os
66
import sys
@@ -21,6 +21,11 @@
2121
import yaml
2222

2323
def cluster_radius(pars, cfg):
24+
"""Runs the default clustering algorithm using the
25+
specified radius. Runs on both negative and positive
26+
eta files, and adds layer weights to the cluster
27+
kwargs if specified."""
28+
2429
cluster_d = params.read_task_params("cluster")
2530

2631
particles = pars["particles"]
@@ -37,19 +42,20 @@ def cluster_radius(pars, cfg):
3742
if "weights" in cfg:
3843
cluster_d["weights"] = cfg["weights"]
3944

40-
for key in ("ClusterInTC", "ClusterInSeeds", "ClusterOutPlot", "ClusterOutValidation"):
41-
name = cluster_d[key]
45+
for eta_tag in ("negEta", "posEta"):
46+
for key in ("ClusterInTC", "ClusterInSeeds", "ClusterOutPlot", "ClusterOutValidation"):
47+
name = cluster_d[key]
4248

43-
cluster_d[key] = "{}_{}_{}_posEta_9oct".format(particles, pileup, name)
44-
45-
nevents_end = tasks.cluster.cluster_default(pars, **cluster_d)
49+
cluster_d[key] = "{}_{}_{}_{}".format(particles, pileup, name, eta_tag)
50+
51+
nevents_end = tasks.cluster.cluster_default(pars, **cluster_d)
4652

4753
if __name__ == "__main__":
4854
parser = argparse.ArgumentParser(description="")
4955
parser.add_argument("--radius", help="Coefficient to use as the max cluster radius", required=True, type=float)
5056
parser.add_argument("--particles", choices=("photons", "electrons", "pions"), required=True)
5157
parser.add_argument("--pileup", help="tag for PU200 vs PU0", choices=("PU0", "PU200"), required=True)
52-
parser.add_argument("--weighted", help="Apply pre-calculated layer weights", default=False)
58+
parser.add_argument("--weighted", help="Apply pre-caluclated layer weights", action="store_true")
5359
parsing.add_parameters(parser)
5460

5561
FLAGS = parser.parse_args()

0 commit comments

Comments
 (0)