1 |
// $Id: goodrun.cc,v 1.10 2011/03/30 22:20:27 warren Exp $
|
2 |
|
3 |
// CINT is allowed to see this, but nothing else:
|
4 |
#include "goodrun.h"
|
5 |
|
6 |
#ifndef __CINT__
|
7 |
|
8 |
#include <assert.h>
|
9 |
#include <stdio.h>
|
10 |
#include <stdlib.h>
|
11 |
#include <string.h>
|
12 |
#include <unistd.h>
|
13 |
#include <sys/types.h>
|
14 |
#include <sys/wait.h>
|
15 |
#include <sys/stat.h>
|
16 |
#include <set>
|
17 |
#include <string>
|
18 |
|
19 |
enum file_type { TEXT, JSON };
|
20 |
|
21 |
struct run_and_lumi {
|
22 |
unsigned int run;
|
23 |
long long int lumi_min;
|
24 |
long long int lumi_max;
|
25 |
};
|
26 |
|
27 |
bool operator < (const struct run_and_lumi &r1, const struct run_and_lumi &r2)
|
28 |
{
|
29 |
return r1.run < r2.run;
|
30 |
}
|
31 |
|
32 |
typedef std::multiset<struct run_and_lumi> set_t;
|
33 |
static set_t good_runs_;
|
34 |
static bool good_runs_loaded_ = false;
|
35 |
|
36 |
static const char json_py[] =
|
37 |
"#! /usr/bin/env python \n"
|
38 |
" \n"
|
39 |
"# usage to print out good run selection for goodrun.cc: \n"
|
40 |
"# convertGoodRunsList_JSON.py <json file> \n"
|
41 |
" \n"
|
42 |
"import sys,json \n"
|
43 |
" \n"
|
44 |
"runs = json.load(open(sys.argv[1],\"r\")) \n"
|
45 |
" \n"
|
46 |
"for run in runs.keys(): \n"
|
47 |
" for lumiBlock in runs[run] : \n"
|
48 |
" if len(lumiBlock) != 2 : \n"
|
49 |
" print 'ERROR reading lumi block: run:',run,'lumiBlock:',lumiBlock \n"
|
50 |
" else: \n"
|
51 |
" # print 'run ' + str(run) + ', min lumi ' + str(lumiBlock[0]) + ', max lumi ' + str(lumiBlock[1])\n"
|
52 |
" print run,lumiBlock[0],lumiBlock[1] \n"
|
53 |
" \n";
|
54 |
//"print '' \n";
|
55 |
|
56 |
static int load_runs (const char *fname, enum file_type type)
|
57 |
{
|
58 |
good_runs_.clear();
|
59 |
FILE *file = 0;
|
60 |
switch (type) {
|
61 |
case TEXT:
|
62 |
file = fopen(fname, "r");
|
63 |
if (file == 0) {
|
64 |
perror("opening good run list");
|
65 |
return 0;
|
66 |
}
|
67 |
break;
|
68 |
case JSON:
|
69 |
{
|
70 |
// first make a temp file with the python parsing code
|
71 |
FILE *pyfile = fopen("tmp.py", "w");
|
72 |
if (pyfile == 0) {
|
73 |
perror("opening tmp file");
|
74 |
return 0;
|
75 |
}
|
76 |
fprintf(pyfile, "%s", json_py);
|
77 |
fclose(pyfile);
|
78 |
chmod("tmp.py", S_IRUSR | S_IWUSR | S_IXUSR);
|
79 |
// now execute a command to convert the JSON file to text
|
80 |
pid_t child = fork();
|
81 |
if (child == -1) {
|
82 |
perror("forking process to convert JSON good run list");
|
83 |
return 0;
|
84 |
}
|
85 |
if (child == 0) {
|
86 |
FILE *f = freopen((std::string(fname) + ".tmp").c_str(), "w", stdout);
|
87 |
if (f == 0) {
|
88 |
perror("opening good run list");
|
89 |
return 127;
|
90 |
}
|
91 |
execlp("./tmp.py", "", fname, (char *)0);
|
92 |
perror("executing JSON conversion script");
|
93 |
exit(127);
|
94 |
}
|
95 |
if (child != 0) {
|
96 |
int status;
|
97 |
waitpid(child, &status, 0);
|
98 |
if (status != 0) {
|
99 |
printf("conversion exited abnormally, consult previous errors\n");
|
100 |
return 0;
|
101 |
}
|
102 |
}
|
103 |
printf("note: converted JSON file is in %s.tmp, "
|
104 |
"please consult in case of parsing errors\n", fname);
|
105 |
file = fopen((std::string(fname) + ".tmp").c_str(), "r");
|
106 |
if (file == 0) {
|
107 |
perror("opening good run list");
|
108 |
return 0;
|
109 |
}
|
110 |
unlink("tmp.py");
|
111 |
break;
|
112 |
}
|
113 |
default:
|
114 |
break;
|
115 |
}
|
116 |
int s;
|
117 |
int line = 0;
|
118 |
do {
|
119 |
int n;
|
120 |
char buf[1024] = "";
|
121 |
// read a line from the file, not including the newline (if
|
122 |
// there is a newline)
|
123 |
s = fscanf(file, "%1024[^\n]%n", buf, &n);
|
124 |
assert(n < 1023);
|
125 |
if (s != 1) {
|
126 |
if (s != EOF) {
|
127 |
perror("reading good run list");
|
128 |
return 0;
|
129 |
} else {
|
130 |
if (ferror(file)) {
|
131 |
perror("reading good run list");
|
132 |
return 0;
|
133 |
}
|
134 |
}
|
135 |
} else if (strlen(buf) != 0 && buf[0] == '#') {
|
136 |
line++;
|
137 |
// printf("Read a comment line (line %d) from the good run list: %s\n", line, buf);
|
138 |
} else {
|
139 |
line++;
|
140 |
// printf("Read a line from the good run list: %s\n", buf);
|
141 |
unsigned int run;
|
142 |
char *pbuf = buf;
|
143 |
s = sscanf(pbuf, " %u%n", &run, &n);
|
144 |
if (s != 1) {
|
145 |
fprintf(stderr, "Expected a run number (unsigned int)"
|
146 |
" in the first position of line %d: %s\n", line, buf);
|
147 |
assert(s == 1);
|
148 |
}
|
149 |
pbuf += n;
|
150 |
long long int lumi_min = -1;
|
151 |
long long int lumi_max = -1;
|
152 |
s = sscanf(pbuf, " %lld%n", &lumi_min, &n);
|
153 |
// if there is no lumi_min specified, that means the
|
154 |
// entire run is good
|
155 |
if (s == 1) {
|
156 |
pbuf += n;
|
157 |
s = sscanf(pbuf, " %lld%n", &lumi_max, &n);
|
158 |
if (s != 1) {
|
159 |
fprintf(stderr, "Expected a max lumi section in a lumi section range"
|
160 |
" (int) in the third position of line %d: %s\n", line, buf);
|
161 |
assert(s == 1);
|
162 |
}
|
163 |
pbuf += n;
|
164 |
}
|
165 |
char trail[1024] = "";
|
166 |
s = sscanf(pbuf, " %s", trail);
|
167 |
if (strlen(trail) != 0) {
|
168 |
fprintf(stderr, "Unexpected trailing junk (%s) on line %d: %s\n", trail, line, buf);
|
169 |
assert(s == 0);
|
170 |
}
|
171 |
// printf("Read line: run %u, min lumi %lld, max lumi %lld\n", run, lumi_min, lumi_max);
|
172 |
struct run_and_lumi new_entry = { run, lumi_min, lumi_max };
|
173 |
good_runs_.insert(new_entry);
|
174 |
}
|
175 |
// advance past the newline
|
176 |
char newlines[1024] = "";
|
177 |
s = fscanf(file, "%[ \f\n\r\t\v]", newlines);
|
178 |
if (s != -1 && strlen(newlines) != 1) {
|
179 |
fprintf(stderr, "Warning: unexpected white space following line %d\n", line);
|
180 |
// but that's just a warning
|
181 |
}
|
182 |
} while (s == 1);
|
183 |
fclose(file);
|
184 |
if (type == JSON)
|
185 |
unlink((std::string(fname) + ".tmp").c_str());
|
186 |
return line;
|
187 |
}
|
188 |
|
189 |
bool goodrun (unsigned int run, unsigned int lumi_block)
|
190 |
{
|
191 |
if (not good_runs_loaded_) {
|
192 |
int ret = load_runs("goodruns.txt", TEXT);
|
193 |
assert(ret != 0);
|
194 |
good_runs_loaded_ = true;
|
195 |
}
|
196 |
// we assume that an empty list means accept anything
|
197 |
if (good_runs_.size() == 0)
|
198 |
return true;
|
199 |
// find all blocks with this run number
|
200 |
struct run_and_lumi r_a_l = { run, 0, 0 };
|
201 |
std::pair<set_t::const_iterator, set_t::const_iterator> good_blocks =
|
202 |
good_runs_.equal_range(r_a_l);
|
203 |
for (set_t::const_iterator i = good_blocks.first;
|
204 |
i != good_blocks.second; ++i) {
|
205 |
// printf("considering run %u, min %lld, max %lld\n",
|
206 |
// i->run, i->lumi_min, i->lumi_max);
|
207 |
if (i->lumi_min <= lumi_block) {
|
208 |
if (i->lumi_max == -1 || i->lumi_max >= lumi_block)
|
209 |
return true;
|
210 |
}
|
211 |
}
|
212 |
return false;
|
213 |
}
|
214 |
|
215 |
int min_run ()
|
216 |
{
|
217 |
if (not good_runs_loaded_)
|
218 |
return -1;
|
219 |
set_t::const_iterator first = good_runs_.begin();
|
220 |
if (first != good_runs_.end())
|
221 |
return first->run;
|
222 |
return -1;
|
223 |
}
|
224 |
|
225 |
int max_run ()
|
226 |
{
|
227 |
if (not good_runs_loaded_)
|
228 |
return -1;
|
229 |
set_t::const_iterator last = good_runs_.end();
|
230 |
if (last != good_runs_.begin()) {
|
231 |
last--;
|
232 |
return last->run;
|
233 |
}
|
234 |
return -1;
|
235 |
}
|
236 |
|
237 |
bool goodrun_json (unsigned int run, unsigned int lumi_block)
|
238 |
{
|
239 |
if (not good_runs_loaded_) {
|
240 |
int ret = load_runs("goodruns.json", JSON);
|
241 |
assert(ret != 0);
|
242 |
good_runs_loaded_ = true;
|
243 |
}
|
244 |
// once the JSON good-run list is loaded, there's no difference
|
245 |
// between TEXT and JSON
|
246 |
return goodrun(run, lumi_block);
|
247 |
}
|
248 |
|
249 |
void set_goodrun_file (const char* filename)
|
250 |
{
|
251 |
int ret = load_runs(filename, TEXT);
|
252 |
assert(ret != 0);
|
253 |
good_runs_loaded_ = true;
|
254 |
}
|
255 |
|
256 |
void set_goodrun_file_json (const char* filename)
|
257 |
{
|
258 |
int ret = load_runs(filename, JSON);
|
259 |
assert(ret != 0);
|
260 |
good_runs_loaded_ = true;
|
261 |
}
|
262 |
|
263 |
int min_run_min_lumi ()
|
264 |
{
|
265 |
if (not good_runs_loaded_)
|
266 |
return -1;
|
267 |
set_t::const_iterator first = good_runs_.begin();
|
268 |
if (first != good_runs_.end())
|
269 |
return first->lumi_min;
|
270 |
return -1;
|
271 |
}
|
272 |
|
273 |
int max_run_max_lumi ()
|
274 |
{
|
275 |
if (not good_runs_loaded_)
|
276 |
return -1;
|
277 |
set_t::const_iterator last = good_runs_.end();
|
278 |
if (last != good_runs_.begin()) {
|
279 |
last--;
|
280 |
return last->lumi_max;
|
281 |
}
|
282 |
return -1;
|
283 |
}
|
284 |
|
285 |
#endif // __CUNT__
|
286 |
|