1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 """ A python file to replace the fortran script gen_ximprove.
16 This script analyses the result of the survey/ previous refine and
17 creates the jobs for the following script.
18 """
19 from __future__ import division
20
21 import collections
22 import os
23 import glob
24 import logging
25 import math
26 import re
27 import subprocess
28 import shutil
29 import stat
30 import sys
31
32 try:
33 import madgraph
34 except ImportError:
35 MADEVENT = True
36 import internal.sum_html as sum_html
37 import internal.banner as bannermod
38 import internal.misc as misc
39 import internal.files as files
40 import internal.cluster as cluster
41 import internal.combine_grid as combine_grid
42 import internal.combine_runs as combine_runs
43 import internal.lhe_parser as lhe_parser
44 else:
45 MADEVENT= False
46 import madgraph.madevent.sum_html as sum_html
47 import madgraph.various.banner as bannermod
48 import madgraph.various.misc as misc
49 import madgraph.iolibs.files as files
50 import madgraph.various.cluster as cluster
51 import madgraph.madevent.combine_grid as combine_grid
52 import madgraph.madevent.combine_runs as combine_runs
53 import madgraph.various.lhe_parser as lhe_parser
54
55 logger = logging.getLogger('madgraph.madevent.gen_ximprove')
56 pjoin = os.path.join
59 """a class to call the fortran gensym executable and handle it's output
60 in order to create the various job that are needed for the survey"""
61
62
63 @ staticmethod
66
67 combining_job = 2
68 splitted_grid = False
69 min_iterations = 3
70 mode= "survey"
71
72
74
75 try:
76 super(gensym, self).__init__(cmd, opt)
77 except TypeError:
78 pass
79
80
81 self.run_statistics = {}
82
83 self.cmd = cmd
84 self.run_card = cmd.run_card
85 self.me_dir = cmd.me_dir
86
87
88
89 self.cross = collections.defaultdict(int)
90 self.abscross = collections.defaultdict(int)
91 self.sigma = collections.defaultdict(int)
92 self.chi2 = collections.defaultdict(int)
93
94 self.splitted_grid = False
95 if self.cmd.proc_characteristics['loop_induced']:
96 nexternal = self.cmd.proc_characteristics['nexternal']
97 self.splitted_grid = max(2, (nexternal-2)**2)
98 if hasattr(self.cmd, "opts") and self.cmd.opts['accuracy'] == 0.1:
99 self.cmd.opts['accuracy'] = 0.02
100
101 if isinstance(cmd.cluster, cluster.MultiCore) and self.splitted_grid > 1:
102 self.splitted_grid = int(cmd.cluster.nb_core**0.5)
103 if self.splitted_grid == 1 and cmd.cluster.nb_core >1:
104 self.splitted_grid = 2
105
106
107 if self.run_card['survey_splitting'] != -1:
108 self.splitted_grid = self.run_card['survey_splitting']
109 if self.run_card['survey_nchannel_per_job'] != -1:
110 self.combining_job = self.run_card['survey_nchannel_per_job']
111
112 self.splitted_Pdir = {}
113 self.splitted_for_dir = lambda x,y: self.splitted_grid
114 self.combining_job_for_Pdir = lambda x: self.combining_job
115 self.lastoffset = {}
116
117 - def launch(self, to_submit=True, clean=True):
118 """ """
119
120 self.subproc = [l.strip() for l in open(pjoin(self.me_dir,'SubProcesses',
121 'subproc.mg'))]
122 subproc = self.subproc
123
124 P_zero_result = []
125
126 nb_tot_proc = len(subproc)
127 job_list = {}
128 for nb_proc,subdir in enumerate(subproc):
129 self.cmd.update_status('Compiling for process %s/%s. <br> (previous processes already running)' % \
130 (nb_proc+1,nb_tot_proc), level=None)
131
132 subdir = subdir.strip()
133 Pdir = pjoin(self.me_dir, 'SubProcesses',subdir)
134 logger.info(' %s ' % subdir)
135
136
137 if clean:
138 for match in misc.glob('*ajob*', Pdir):
139 if os.path.basename(match)[:4] in ['ajob', 'wait', 'run.', 'done']:
140 os.remove(match)
141 for match in misc.glob('G*', Pdir):
142 if os.path.exists(pjoin(match,'results.dat')):
143 os.remove(pjoin(match, 'results.dat'))
144 if os.path.exists(pjoin(match, 'ftn25')):
145 os.remove(pjoin(match, 'ftn25'))
146
147
148 self.cmd.compile(['gensym'], cwd=Pdir)
149 if not os.path.exists(pjoin(Pdir, 'gensym')):
150 raise Exception, 'Error make gensym not successful'
151
152
153 p = misc.Popen(['./gensym'], stdout=subprocess.PIPE,
154 stderr=subprocess.STDOUT, cwd=Pdir)
155
156 (stdout, _) = p.communicate('')
157
158 if os.path.exists(pjoin(self.me_dir,'error')):
159 files.mv(pjoin(self.me_dir,'error'), pjoin(Pdir,'ajob.no_ps.log'))
160 P_zero_result.append(subdir)
161 continue
162
163 jobs = stdout.split()
164 job_list[Pdir] = jobs
165 try:
166
167 [float(s) for s in jobs]
168 except Exception:
169 logger.debug("unformated string found in gensym. Please check:\n %s" % stdout)
170 done=False
171 job_list[Pdir] = []
172 lines = stdout.split('\n')
173 for l in lines:
174 try:
175 [float(s) for s in l.split()]
176 except:
177 continue
178 else:
179 if done:
180 raise Exception, 'Parsing error in gensym: %s' % stdout
181 job_list[Pdir] = l.split()
182 done = True
183 if not done:
184 raise Exception, 'Parsing error in gensym: %s' % stdout
185
186 self.cmd.compile(['madevent'], cwd=Pdir)
187 if to_submit:
188 self.submit_to_cluster(job_list)
189 job_list = {}
190
191 return job_list, P_zero_result
192
193 - def resubmit(self, min_precision=1.0, resubmit_zero=False):
194 """collect the result of the current run and relaunch each channel
195 not completed or optionally a completed one with a precision worse than
196 a threshold (and/or the zero result channel)"""
197
198 job_list, P_zero_result = self.launch(to_submit=False, clean=False)
199
200 for P , jobs in dict(job_list).items():
201 misc.sprint(jobs)
202 to_resub = []
203 for job in jobs:
204 if os.path.exists(pjoin(P, 'G%s' % job)) and os.path.exists(pjoin(P, 'G%s' % job, 'results.dat')):
205 one_result = sum_html.OneResult(job)
206 try:
207 one_result.read_results(pjoin(P, 'G%s' % job, 'results.dat'))
208 except:
209 to_resub.append(job)
210 if one_result.xsec == 0:
211 if resubmit_zero:
212 to_resub.append(job)
213 elif max(one_result.xerru, one_result.xerrc)/one_result.xsec > min_precision:
214 to_resub.append(job)
215 else:
216 to_resub.append(job)
217 if to_resub:
218 for G in to_resub:
219 try:
220 shutil.rmtree(pjoin(P, 'G%s' % G))
221 except Exception, error:
222 misc.sprint(error)
223 pass
224 misc.sprint(to_resub)
225 self.submit_to_cluster({P: to_resub})
226
227
228
229
230
231
232
233
234
235
236
238 """ """
239
240 if self.run_card['job_strategy'] > 0:
241 if len(job_list) >1:
242 for path, dirs in job_list.items():
243 self.submit_to_cluster({path:dirs})
244 return
245 path, value = job_list.items()[0]
246 nexternal = self.cmd.proc_characteristics['nexternal']
247 current = open(pjoin(path, "nexternal.inc")).read()
248 ext = re.search(r"PARAMETER \(NEXTERNAL=(\d+)\)", current).group(1)
249
250 if self.run_card['job_strategy'] == 2:
251 self.splitted_grid = 2
252 if nexternal == int(ext):
253 to_split = 2
254 else:
255 to_split = 0
256 if hasattr(self, 'splitted_Pdir'):
257 self.splitted_Pdir[path] = to_split
258 else:
259 self.splitted_Pdir = {path: to_split}
260 self.splitted_for_dir = lambda x,y : self.splitted_Pdir[x]
261 elif self.run_card['job_strategy'] == 1:
262 if nexternal == int(ext):
263 combine = 1
264 else:
265 combine = self.combining_job
266 if hasattr(self, 'splitted_Pdir'):
267 self.splitted_Pdir[path] = combine
268 else:
269 self.splitted_Pdir = {path: combine}
270 self.combining_job_for_Pdir = lambda x : self.splitted_Pdir[x]
271
272 if not self.splitted_grid:
273 return self.submit_to_cluster_no_splitting(job_list)
274 elif self.cmd.cluster_mode == 0:
275 return self.submit_to_cluster_no_splitting(job_list)
276 elif self.cmd.cluster_mode == 2 and self.cmd.options['nb_core'] == 1:
277 return self.submit_to_cluster_no_splitting(job_list)
278 else:
279 return self.submit_to_cluster_splitted(job_list)
280
281
283 """submit the survey without the parralelization.
284 This is the old mode which is still usefull in single core"""
285
286
287 self.write_parameter(parralelization=False, Pdirs=job_list.keys())
288
289
290
291 for Pdir, jobs in job_list.items():
292 jobs = list(jobs)
293 i=0
294 while jobs:
295 i+=1
296 to_submit = ['0']
297 for _ in range(self.combining_job_for_Pdir(Pdir)):
298 if jobs:
299 to_submit.append(jobs.pop(0))
300
301 self.cmd.launch_job(pjoin(self.me_dir, 'SubProcesses', 'survey.sh'),
302 argument=to_submit,
303 cwd=pjoin(self.me_dir,'SubProcesses' , Pdir))
304
305
307 """prepare the input_file for submitting the channel"""
308
309
310 if 'SubProcesses' not in Pdir:
311 Pdir = pjoin(self.me_dir, 'SubProcesses', Pdir)
312
313
314 self.splitted_Pdir[(Pdir, G)] = int(nb_job)
315
316
317
318 run_card = self.cmd.run_card
319 options = {'event' : submit_ps,
320 'maxiter': 1,
321 'miniter': 1,
322 'accuracy': self.cmd.opts['accuracy'],
323 'helicity': run_card['nhel_survey'] if 'nhel_survey' in run_card \
324 else run_card['nhel'],
325 'gridmode': -2,
326 'channel' : G
327 }
328
329 Gdir = pjoin(Pdir, 'G%s' % G)
330 self.write_parameter_file(pjoin(Gdir, 'input_app.txt'), options)
331
332
333 assert os.path.exists(pjoin(Gdir, "ftn25"))
334
335
336
337
338 packet = cluster.Packet((Pdir, G, step+1),
339 self.combine_iteration,
340 (Pdir, G, step+1))
341
342 if step ==0:
343 self.lastoffset[(Pdir, G)] = 0
344
345
346 for i in xrange(int(nb_job)):
347 name = "G%s_%s" % (G,i+1)
348 self.lastoffset[(Pdir, G)] += 1
349 offset = self.lastoffset[(Pdir, G)]
350 self.cmd.launch_job(pjoin(self.me_dir, 'SubProcesses', 'refine_splitted.sh'),
351 argument=[name, 'G%s'%G, offset],
352 cwd= Pdir,
353 packet_member=packet)
354
355
357 """ submit the version of the survey with splitted grid creation
358 """
359
360
361
362
363 for Pdir, jobs in job_list.items():
364 if not jobs:
365 continue
366 if self.splitted_for_dir(Pdir, jobs[0]) <= 1:
367 return self.submit_to_cluster_no_splitting({Pdir:jobs})
368
369 self.write_parameter(parralelization=True, Pdirs=[Pdir])
370
371
372 for job in jobs:
373 packet = cluster.Packet((Pdir, job, 1), self.combine_iteration, (Pdir, job, 1))
374 for i in range(self.splitted_for_dir(Pdir, job)):
375 self.cmd.launch_job(pjoin(self.me_dir, 'SubProcesses', 'survey.sh'),
376 argument=[i+1, job],
377 cwd=pjoin(self.me_dir,'SubProcesses' , Pdir),
378 packet_member=packet)
379
381
382 grid_calculator, cross, error = self.combine_grid(Pdir, G, step)
383
384
385 nb_events = grid_calculator.target_evt
386
387 Gdirs = []
388 for i in range(self.splitted_for_dir(Pdir, G)):
389 path = pjoin(Pdir, "G%s_%s" % (G, i+1))
390 Gdirs.append(path)
391
392
393
394
395
396 need_submit = False
397 if step < self.min_iterations and cross != 0:
398 if step == 1:
399 need_submit = True
400 else:
401 across = self.abscross[(Pdir,G)]/(self.sigma[(Pdir,G)]+1e-99)
402 tot_across = self.get_current_axsec()
403 if across / tot_across < 1e-6:
404 need_submit = False
405 elif error < self.cmd.opts['accuracy'] / 100:
406 need_submit = False
407 else:
408 need_submit = True
409
410 elif step >= self.cmd.opts['iterations']:
411 need_submit = False
412 elif self.cmd.opts['accuracy'] < 0:
413
414 raise Exception, "Not Implemented"
415 elif self.abscross[(Pdir,G)] == 0:
416 need_submit = False
417 else:
418 across = self.abscross[(Pdir,G)]/(self.sigma[(Pdir,G)]+1e-99)
419 tot_across = self.get_current_axsec()
420 if across == 0:
421 need_submit = False
422 elif across / tot_across < 1e-5:
423 need_submit = False
424 elif error > self.cmd.opts['accuracy']:
425 need_submit = True
426 else:
427 need_submit = False
428
429
430 if cross:
431 grid_calculator.write_grid_for_submission(Pdir,G,
432 self.splitted_for_dir(Pdir, G),
433 nb_events,mode=self.mode,
434 conservative_factor=5.0)
435
436 xsec_format = '.%ig'%(max(3,int(math.log10(1.0/float(error)))+2)
437 if float(cross)!=0.0 and float(error)!=0.0 else 8)
438 if need_submit:
439 message = "%%s/G%%s is at %%%s +- %%.3g pb. Now submitting iteration #%s."%(xsec_format, step+1)
440 logger.info(message%\
441 (os.path.basename(Pdir), G, float(cross),
442 float(error)*float(cross)))
443 self.resubmit_survey(Pdir,G, Gdirs, step)
444 elif cross:
445 logger.info("Survey finished for %s/G%s at %s"%(
446 os.path.basename(Pdir),G,('%%%s +- %%.3g pb'%xsec_format))%
447 (float(cross), float(error)*float(cross)))
448
449 newGpath = pjoin(self.me_dir,'SubProcesses' , Pdir, 'G%s' % G)
450 if not os.path.exists(newGpath):
451 os.mkdir(newGpath)
452
453
454 files.cp(pjoin(Gdirs[0], 'ftn25'),
455 pjoin(self.me_dir,'SubProcesses' , Pdir, 'G%s' % G, 'ftn26'))
456
457
458 fsock = open(pjoin(newGpath, 'events.lhe'), 'w')
459 for Gdir in Gdirs:
460 fsock.write(open(pjoin(Gdir, 'events.lhe')).read())
461
462
463 files.cp(pjoin(Gdirs[0], 'log.txt'),
464 pjoin(self.me_dir,'SubProcesses' , Pdir, 'G%s' % G))
465
466
467
468 self.write_results(grid_calculator, cross, error, Pdir, G, step)
469 else:
470 logger.info("Survey finished for %s/G%s [0 cross]", os.path.basename(Pdir),G)
471
472 Gdir = pjoin(self.me_dir,'SubProcesses' , Pdir, 'G%s' % G)
473 if not os.path.exists(Gdir):
474 os.mkdir(Gdir)
475
476 files.cp(pjoin(Gdirs[0], 'log.txt'), Gdir)
477
478 self.write_results(grid_calculator, cross, error, Pdir, G, step)
479
480 return 0
481
482 - def combine_grid(self, Pdir, G, step, exclude_sub_jobs=[]):
483 """ exclude_sub_jobs is to remove some of the subjobs if a numerical
484 issue is detected in one of them. Warning is issue when this occurs.
485 """
486
487
488 grid_calculator = combine_grid.grid_information(self.run_card['nhel'])
489
490 for i in range(self.splitted_for_dir(Pdir, G)):
491 if i in exclude_sub_jobs:
492 continue
493 path = pjoin(Pdir, "G%s_%s" % (G, i+1))
494 fsock = misc.mult_try_open(pjoin(path, 'results.dat'))
495 one_result = grid_calculator.add_results_information(fsock)
496 fsock.close()
497 if one_result.axsec == 0:
498 grid_calculator.onefail = True
499 continue
500 fsock = misc.mult_try_open(pjoin(path, 'grid_information'))
501 grid_calculator.add_one_grid_information(fsock)
502 fsock.close()
503 os.remove(pjoin(path, 'results.dat'))
504
505
506
507
508
509
510 cross, across, sigma = grid_calculator.get_cross_section()
511
512
513
514 maxwgt = grid_calculator.get_max_wgt(0.01)
515 if maxwgt:
516 nunwgt = grid_calculator.get_nunwgt(maxwgt)
517
518
519
520
521 apply_instability_security = False
522 rel_contrib = 0.0
523 if (self.__class__ != gensym or step > 1):
524 Pdir_across = 0.0
525 Gdir_across = 0.0
526 for (mPdir,mG) in self.abscross.keys():
527 if mPdir == Pdir:
528 Pdir_across += (self.abscross[(mPdir,mG)]/
529 (self.sigma[(mPdir,mG)]+1e-99))
530 if mG == G:
531 Gdir_across += (self.abscross[(mPdir,mG)]/
532 (self.sigma[(mPdir,mG)]+1e-99))
533 rel_contrib = abs(Gdir_across/(Pdir_across+1e-99))
534 if rel_contrib > (1.0e-8) and \
535 nunwgt < 2 and len(grid_calculator.results) > 1:
536 apply_instability_security = True
537
538 if apply_instability_security:
539
540 th_maxwgt = [(r.th_maxwgt,i) for i,r in enumerate(grid_calculator.results)]
541 th_maxwgt.sort()
542 ratio = th_maxwgt[-1][0]/th_maxwgt[-2][0]
543 if ratio > 1e4:
544 logger.warning(
545 """"One Event with large weight have been found (ratio = %.3g) in channel G%s (with rel.contrib=%.3g).
546 This is likely due to numerical instabilities. The associated job is discarded to recover.
547 For offline investigation, the problematic discarded events are stored in:
548 %s"""%(ratio,G,rel_contrib,pjoin(Pdir,'DiscardedUnstableEvents')))
549 exclude_sub_jobs = list(exclude_sub_jobs)
550 exclude_sub_jobs.append(th_maxwgt[-1][1])
551 grid_calculator.results.run_statistics['skipped_subchannel'] += 1
552
553
554 gPath = pjoin(Pdir, "G%s_%s" % (G, th_maxwgt[-1][1]+1))
555 if os.path.isfile(pjoin(gPath,'events.lhe')):
556 lhe_file = lhe_parser.EventFile(pjoin(gPath,'events.lhe'))
557 discardedPath = pjoin(Pdir,'DiscardedUnstableEvents')
558 if not os.path.exists(discardedPath):
559 os.mkdir(discardedPath)
560 if os.path.isdir(discardedPath):
561
562
563 evtRecord = open(pjoin(discardedPath,'discarded_G%s.dat'%G),'a')
564 lhe_file.seek(0)
565 try:
566 evtRecord.write('\n'+str(max(lhe_file,key=lambda evt:abs(evt.wgt))))
567 except Exception:
568
569 lhe_file.close()
570 evtRecord.write(pjoin(gPath,'events.lhe').read())
571 evtRecord.close()
572
573 return self.combine_grid(Pdir, G, step, exclude_sub_jobs)
574
575
576 if across !=0:
577 if sigma != 0:
578 self.cross[(Pdir,G)] += cross**3/sigma**2
579 self.abscross[(Pdir,G)] += across * cross**2/sigma**2
580 self.sigma[(Pdir,G)] += cross**2/ sigma**2
581 self.chi2[(Pdir,G)] += cross**4/sigma**2
582
583 cross = self.cross[(Pdir,G)]/self.sigma[(Pdir,G)]
584 if step > 1:
585 error = math.sqrt(abs((self.chi2[(Pdir,G)]/cross**2 - \
586 self.sigma[(Pdir,G)])/(step-1))/self.sigma[(Pdir,G)])
587 else:
588 error = sigma/cross
589 else:
590 self.cross[(Pdir,G)] = cross
591 self.abscross[(Pdir,G)] = across
592 self.sigma[(Pdir,G)] = 0
593 self.chi2[(Pdir,G)] = 0
594 cross = self.cross[(Pdir,G)]
595 error = 0
596
597 else:
598 error = 0
599
600 grid_calculator.results.compute_values(update_statistics=True)
601 if (str(os.path.basename(Pdir)), G) in self.run_statistics:
602 self.run_statistics[(str(os.path.basename(Pdir)), G)]\
603 .aggregate_statistics(grid_calculator.results.run_statistics)
604 else:
605 self.run_statistics[(str(os.path.basename(Pdir)), G)] = \
606 grid_calculator.results.run_statistics
607
608 self.warnings_from_statistics(G, grid_calculator.results.run_statistics)
609 stats_msg = grid_calculator.results.run_statistics.nice_output(
610 '/'.join([os.path.basename(Pdir),'G%s'%G]))
611
612 if stats_msg:
613 logger.log(5, stats_msg)
614
615
616 for i in range(self.splitted_for_dir(Pdir, G)):
617 path = pjoin(Pdir, "G%s_%s" % (G, i+1))
618 try:
619 os.remove(pjoin(path, 'grid_information'))
620 except OSError, oneerror:
621 if oneerror.errno != 2:
622 raise
623 return grid_calculator, cross, error
624
626 """Possible warn user for worrying MadLoop stats for this channel."""
627
628 if stats['n_madloop_calls']==0:
629 return
630
631 EPS_fraction = float(stats['exceptional_points'])/stats['n_madloop_calls']
632
633 msg = "Channel %s has encountered a fraction of %.3g\n"+ \
634 "of numerically unstable loop matrix element computations\n"+\
635 "(which could not be rescued using quadruple precision).\n"+\
636 "The results might not be trusted."
637
638 if 0.01 > EPS_fraction > 0.001:
639 logger.warning(msg%(G,EPS_fraction))
640 elif EPS_fraction > 0.01:
641 logger.critical((msg%(G,EPS_fraction)).replace('might', 'can'))
642 raise Exception, (msg%(G,EPS_fraction)).replace('might', 'can')
643
645
646 across = 0
647 for (Pdir,G) in self.abscross:
648 across += self.abscross[(Pdir,G)]/(self.sigma[(Pdir,G)]+1e-99)
649 return across
650
651 - def write_results(self, grid_calculator, cross, error, Pdir, G, step):
652
653
654 if cross == 0:
655 abscross,nw, luminosity = 0, 0, 0
656 wgt, maxit,nunwgt, wgt, nevents = 0,0,0,0,0
657 maxwgt = 0
658 error = 0
659 else:
660 grid_calculator.results.compute_values()
661 abscross = self.abscross[(Pdir,G)]/self.sigma[(Pdir,G)]
662 nw = grid_calculator.results.nw
663 wgt = grid_calculator.results.wgt
664 maxit = step
665 wgt = 0
666 nevents = grid_calculator.results.nevents
667 maxwgt = grid_calculator.get_max_wgt()
668 nunwgt = grid_calculator.get_nunwgt()
669 luminosity = nunwgt/cross
670
671
672 def fstr(nb):
673 data = '%E' % nb
674 nb, power = data.split('E')
675 nb = float(nb) /10
676 power = int(power) + 1
677 return '%.5fE%+03i' %(nb,power)
678 line = '%s %s %s %i %i %i %i %s %s %s %s 0.0 0\n' % \
679 (fstr(cross), fstr(error*cross), fstr(error*cross),
680 nevents, nw, maxit,nunwgt,
681 fstr(luminosity), fstr(wgt), fstr(abscross), fstr(maxwgt))
682
683 fsock = open(pjoin(self.me_dir,'SubProcesses' , Pdir, 'G%s' % G,
684 'results.dat'),'w')
685 fsock.writelines(line)
686 fsock.close()
687
689 """submit the next iteration of the survey"""
690
691
692 run_card = self.cmd.run_card
693 options = {'event' : 2**(step) * self.cmd.opts['points'] / self.splitted_grid,
694 'maxiter': 1,
695 'miniter': 1,
696 'accuracy': self.cmd.opts['accuracy'],
697 'helicity': run_card['nhel_survey'] if 'nhel_survey' in run_card \
698 else run_card['nhel'],
699 'gridmode': -2,
700 'channel' : ''
701 }
702
703 if int(options['helicity']) == 1:
704 options['event'] = options['event'] * 2**(self.cmd.proc_characteristics['nexternal']//3)
705
706 for Gdir in Gdirs:
707 self.write_parameter_file(pjoin(Gdir, 'input_app.txt'), options)
708
709
710
711 packet = cluster.Packet((Pdir, G, step+1), self.combine_iteration, \
712 (Pdir, G, step+1))
713 nb_step = len(Gdirs) * (step+1)
714 for i,subdir in enumerate(Gdirs):
715 subdir = subdir.rsplit('_',1)[1]
716 subdir = int(subdir)
717 offset = nb_step+i+1
718 offset=str(offset)
719 tag = "%s.%s" % (subdir, offset)
720
721 self.cmd.launch_job(pjoin(self.me_dir, 'SubProcesses', 'survey.sh'),
722 argument=[tag, G],
723 cwd=pjoin(self.me_dir,'SubProcesses' , Pdir),
724 packet_member=packet)
725
726
727
728
730 """ """
731
732 template =""" %(event)s %(maxiter)s %(miniter)s !Number of events and max and min iterations
733 %(accuracy)s !Accuracy
734 %(gridmode)s !Grid Adjustment 0=none, 2=adjust
735 1 !Suppress Amplitude 1=yes
736 %(helicity)s !Helicity Sum/event 0=exact
737 %(channel)s """
738 options['event'] = int(options['event'])
739 open(path, 'w').write(template % options)
740
741
742
744 """Write the parameter of the survey run"""
745
746 run_card = self.cmd.run_card
747
748 options = {'event' : self.cmd.opts['points'],
749 'maxiter': self.cmd.opts['iterations'],
750 'miniter': self.min_iterations,
751 'accuracy': self.cmd.opts['accuracy'],
752 'helicity': run_card['nhel_survey'] if 'nhel_survey' in run_card \
753 else run_card['nhel'],
754 'gridmode': 2,
755 'channel': ''
756 }
757
758 if int(options['helicity'])== 1:
759 options['event'] = options['event'] * 2**(self.cmd.proc_characteristics['nexternal']//3)
760
761 if parralelization:
762 options['gridmode'] = -2
763 options['maxiter'] = 1
764 options['miniter'] = 1
765 options['event'] /= self.splitted_grid
766
767 if not Pdirs:
768 Pdirs = self.subproc
769
770 for Pdir in Pdirs:
771 path =pjoin(Pdir, 'input_app.txt')
772 self.write_parameter_file(path, options)
773
777
778
779
780 gen_events_security = 1.2
781 combining_job = 0
782 max_request_event = 1000
783 max_event_in_iter = 5000
784 min_event_in_iter = 1000
785 max_splitting = 130
786 min_iter = 3
787 max_iter = 9
788 keep_grid_for_refine = False
789
790
791 @ staticmethod
794
795
797 """Choose in which type of refine we want to be"""
798
799 if cmd.proc_characteristics['loop_induced']:
800 return super(gen_ximprove, cls).__new__(gen_ximprove_share, cmd, opt)
801 elif gen_ximprove.format_variable(cmd.run_card['gridpack'], bool):
802 return super(gen_ximprove, cls).__new__(gen_ximprove_gridpack, cmd, opt)
803 elif cmd.run_card["job_strategy"] == 2:
804 return super(gen_ximprove, cls).__new__(gen_ximprove_share, cmd, opt)
805 else:
806 return super(gen_ximprove, cls).__new__(gen_ximprove_v4, cmd, opt)
807
808
810
811 try:
812 super(gen_ximprove, self).__init__(cmd, opt)
813 except TypeError:
814 pass
815
816 self.run_statistics = {}
817 self.cmd = cmd
818 self.run_card = cmd.run_card
819 run_card = self.run_card
820 self.me_dir = cmd.me_dir
821
822
823 self.gridpack = run_card['gridpack']
824 self.nhel = run_card['nhel']
825 if "nhel_refine" in run_card:
826 self.nhel = run_card["nhel_refine"]
827
828 if self.run_card['refine_evt_by_job'] != -1:
829 self.max_request_event = run_card['refine_evt_by_job']
830
831
832
833 self.gen_events = True
834 self.min_iter = 3
835 self.parralel = False
836
837 self.err_goal = 0.01
838 self.max_np = 9
839 self.split_channels = False
840
841 self.nreq = 2000
842 self.iseed = 4321
843
844
845 self.results = 0
846
847 if isinstance(opt, dict):
848 self.configure(opt)
849 elif isinstance(opt, bannermod.GridpackCard):
850 self.configure_gridpack(opt)
851
854
868
869
890
892 """not needed but for gridpack --which is not handle here for the moment"""
893 return
894
895
897 """return the list of channel that need to be improved"""
898
899 assert self.err_goal >=1
900 self.err_goal = int(self.err_goal)
901
902 goal_lum = self.err_goal/(self.results.axsec+1e-99)
903 logger.info('Effective Luminosity %s pb^-1', goal_lum)
904
905 all_channels = sum([list(P) for P in self.results],[])
906 all_channels.sort(cmp= lambda x,y: 1 if y.get('luminosity') - \
907 x.get('luminosity') > 0 else -1)
908
909 to_refine = []
910 for C in all_channels:
911 if C.get('axsec') == 0:
912 continue
913 if goal_lum/(C.get('luminosity')+1e-99) >= 1 + (self.gen_events_security-1)/2:
914 logger.debug("channel %s is at %s (%s) (%s pb)", C.name, C.get('luminosity'), goal_lum/(C.get('luminosity')+1e-99), C.get('xsec'))
915 to_refine.append(C)
916 elif C.get('xerr') > max(C.get('axsec'),
917 (1/(100*math.sqrt(self.err_goal)))*all_channels[-1].get('axsec')):
918 to_refine.append(C)
919
920 logger.info('need to improve %s channels' % len(to_refine))
921 return goal_lum, to_refine
922
924 """update the html from this object since it contains all the information"""
925
926
927 run = self.cmd.results.current['run_name']
928 if not os.path.exists(pjoin(self.cmd.me_dir, 'HTML', run)):
929 os.mkdir(pjoin(self.cmd.me_dir, 'HTML', run))
930
931 unit = self.cmd.results.unit
932 P_text = ""
933 if self.results:
934 Presults = self.results
935 else:
936 self.results = sum_html.collect_result(self.cmd, None)
937 Presults = self.results
938
939 for P_comb in Presults:
940 P_text += P_comb.get_html(run, unit, self.cmd.me_dir)
941
942 Presults.write_results_dat(pjoin(self.cmd.me_dir,'SubProcesses', 'results.dat'))
943
944 fsock = open(pjoin(self.cmd.me_dir, 'HTML', run, 'results.html'),'w')
945 fsock.write(sum_html.results_header)
946 fsock.write('%s <dl>' % Presults.get_html(run, unit, self.cmd.me_dir))
947 fsock.write('%s </dl></body>' % P_text)
948
949 self.cmd.results.add_detail('cross', Presults.xsec)
950 self.cmd.results.add_detail('error', Presults.xerru)
951
952 return Presults.xsec, Presults.xerru
953
976
978
979 for path in misc.glob(pjoin('*', '*','multijob.dat'), pjoin(self.me_dir, 'SubProcesses')):
980 open(path,'w').write('0\n')
981
983 """ """
984 if nb_split <=1:
985 return
986 f = open(pjoin(self.me_dir, 'SubProcesses', Channel.get('name'), 'multijob.dat'), 'w')
987 f.write('%i\n' % nb_split)
988 f.close()
989
999
1000 alphabet = "abcdefghijklmnopqrstuvwxyz"
1002 """generate the script in order to generate a given number of event"""
1003
1004
1005
1006 goal_lum, to_refine = self.find_job_for_event()
1007
1008
1009 self.reset_multijob()
1010
1011 jobs = []
1012
1013
1014
1015 if self.combining_job >1:
1016
1017 new_order = []
1018 if self.combining_job % 2 == 0:
1019 for i in range(len(to_refine) //2):
1020 new_order.append(to_refine[i])
1021 new_order.append(to_refine[-i-1])
1022 if len(to_refine) % 2:
1023 new_order.append(to_refine[i+1])
1024 else:
1025 for i in range(len(to_refine) //3):
1026 new_order.append(to_refine[i])
1027 new_order.append(to_refine[-2*i-1])
1028 new_order.append(to_refine[-2*i-2])
1029 if len(to_refine) % 3 == 1:
1030 new_order.append(to_refine[i+1])
1031 elif len(to_refine) % 3 == 2:
1032 new_order.append(to_refine[i+2])
1033
1034 assert set([id(C) for C in to_refine]) == set([id(C) for C in new_order])
1035 to_refine = new_order
1036
1037
1038
1039 for C in to_refine:
1040
1041 needed_event = goal_lum*C.get('axsec')
1042 nb_split = int(max(1,((needed_event-1)// self.max_request_event) +1))
1043 if not self.split_channels:
1044 nb_split = 1
1045 if nb_split > self.max_splitting:
1046 nb_split = self.max_splitting
1047 nb_split=max(1, nb_split)
1048
1049
1050
1051 if C.get('nunwgt') > 0:
1052 nevents = needed_event / nb_split * (C.get('nevents') / C.get('nunwgt'))
1053
1054 nevents = int(nevents / (2**self.min_iter-1))
1055 else:
1056 nevents = self.max_event_in_iter
1057
1058 if nevents < self.min_event_in_iter:
1059 nb_split = int(nb_split * nevents / self.min_event_in_iter) + 1
1060 nevents = self.min_event_in_iter
1061
1062
1063 nevents = max(self.min_event_in_iter, min(self.max_event_in_iter, nevents))
1064 logger.debug("%s : need %s event. Need %s split job of %s points", C.name, needed_event, nb_split, nevents)
1065
1066
1067
1068 self.write_multijob(C, nb_split)
1069
1070 packet = cluster.Packet((C.parent_name, C.name),
1071 combine_runs.CombineRuns,
1072 (pjoin(self.me_dir, 'SubProcesses', C.parent_name)),
1073 {"subproc": C.name, "nb_split":nb_split})
1074
1075
1076
1077 info = {'name': self.cmd.results.current['run_name'],
1078 'script_name': 'unknown',
1079 'directory': C.name,
1080 'P_dir': C.parent_name,
1081 'Ppath': pjoin(self.cmd.me_dir, 'SubProcesses', C.parent_name),
1082 'offset': 1,
1083 'nevents': nevents,
1084 'maxiter': self.max_iter,
1085 'miniter': self.min_iter,
1086 'precision': -goal_lum/nb_split,
1087 'nhel': self.run_card['nhel'],
1088 'channel': C.name.replace('G',''),
1089 'grid_refinment' : 0,
1090 'base_directory': '',
1091 'packet': packet,
1092 }
1093
1094 if nb_split == 1:
1095 jobs.append(info)
1096 else:
1097 for i in range(nb_split):
1098 new_info = dict(info)
1099 new_info['offset'] = i+1
1100 new_info['directory'] += self.alphabet[i % 26] + str((i+1)//26)
1101 if self.keep_grid_for_refine:
1102 new_info['base_directory'] = info['directory']
1103 jobs.append(new_info)
1104
1105 self.create_ajob(pjoin(self.me_dir, 'SubProcesses', 'refine.sh'), jobs)
1106
1107
1108 - def create_ajob(self, template, jobs, write_dir=None):
1109 """create the ajob"""
1110
1111 if not jobs:
1112 return
1113
1114 if not write_dir:
1115 write_dir = pjoin(self.me_dir, 'SubProcesses')
1116
1117
1118 P2job= collections.defaultdict(list)
1119 for j in jobs:
1120 P2job[j['P_dir']].append(j)
1121 if len(P2job) >1:
1122 for P in P2job.values():
1123 self.create_ajob(template, P, write_dir)
1124 return
1125
1126
1127
1128 path = pjoin(write_dir, jobs[0]['P_dir'])
1129
1130 template_text = open(template, 'r').read()
1131
1132
1133 if self.combining_job > 1:
1134 skip1=0
1135 n_channels = len(jobs)
1136 nb_sub = n_channels // self.combining_job
1137 nb_job_in_last = n_channels % self.combining_job
1138 if nb_sub == 0:
1139 nb_sub = 1
1140 nb_job_in_last =0
1141 if nb_job_in_last:
1142 nb_sub +=1
1143 skip1 = self.combining_job - nb_job_in_last
1144 if skip1 > nb_sub:
1145 self.combining_job -=1
1146 return self.create_ajob(template, jobs, write_dir)
1147 combining_job = self.combining_job
1148 else:
1149
1150
1151 skip1=0
1152 combining_job =1
1153 nb_sub = len(jobs)
1154
1155
1156 nb_use = 0
1157 for i in range(nb_sub):
1158 script_number = i+1
1159 if i < skip1:
1160 nb_job = combining_job -1
1161 else:
1162 nb_job = min(combining_job, len(jobs))
1163 fsock = open(pjoin(path, 'ajob%i' % script_number), 'w')
1164 for j in range(nb_use, nb_use + nb_job):
1165 if j> len(jobs):
1166 break
1167 info = jobs[j]
1168 info['script_name'] = 'ajob%i' % script_number
1169 info['keeplog'] = 'false'
1170 if "base_directory" not in info:
1171 info["base_directory"] = "./"
1172 fsock.write(template_text % info)
1173 nb_use += nb_job
1174
1175 fsock.close()
1176 return script_number
1177
1179 """create the ajob to achieve a give precision on the total cross-section"""
1180
1181
1182 assert self.err_goal <=1
1183 xtot = abs(self.results.xsec)
1184 logger.info("Working on precision: %s %%" %(100*self.err_goal))
1185 all_channels = sum([list(P) for P in self.results if P.mfactor],[])
1186 limit = self.err_goal * xtot / len(all_channels)
1187 to_refine = []
1188 rerr = 0
1189 for C in all_channels:
1190 cerr = C.mfactor*(C.xerru + len(all_channels)*C.xerrc)
1191 if cerr > abs(limit):
1192 to_refine.append(C)
1193 else:
1194 rerr += cerr
1195 rerr *=rerr
1196 if not len(to_refine):
1197 return
1198
1199
1200 limit = math.sqrt((self.err_goal * xtot)**2 - rerr/math.sqrt(len(to_refine)))
1201 for C in to_refine[:]:
1202 cerr = C.mfactor*(C.xerru + len(to_refine)*C.xerrc)
1203 if cerr < limit:
1204 to_refine.remove(C)
1205
1206
1207 logger.info('need to improve %s channels' % len(to_refine))
1208
1209
1210 jobs = []
1211
1212
1213
1214 for C in to_refine:
1215
1216
1217 yerr = C.mfactor*(C.xerru+len(to_refine)*C.xerrc)
1218 nevents = 0.2*C.nevents*(yerr/limit)**2
1219
1220 nb_split = int((nevents*(C.nunwgt/C.nevents)/self.max_request_event/ (2**self.min_iter-1))**(2/3))
1221 nb_split = max(nb_split, 1)
1222
1223 if nb_split > self.max_splitting:
1224 nb_split = self.max_splitting
1225
1226 if nb_split >1:
1227 nevents = nevents / nb_split
1228 self.write_multijob(C, nb_split)
1229
1230 nevents = min(self.min_event_in_iter, max(self.max_event_in_iter, nevents))
1231
1232
1233
1234 info = {'name': self.cmd.results.current['run_name'],
1235 'script_name': 'unknown',
1236 'directory': C.name,
1237 'P_dir': C.parent_name,
1238 'Ppath': pjoin(self.cmd.me_dir, 'SubProcesses', C.parent_name),
1239 'offset': 1,
1240 'nevents': nevents,
1241 'maxiter': self.max_iter,
1242 'miniter': self.min_iter,
1243 'precision': yerr/math.sqrt(nb_split)/(C.get('xsec')+ yerr),
1244 'nhel': self.run_card['nhel'],
1245 'channel': C.name.replace('G',''),
1246 'grid_refinment' : 1
1247 }
1248
1249 if nb_split == 1:
1250 jobs.append(info)
1251 else:
1252 for i in range(nb_split):
1253 new_info = dict(info)
1254 new_info['offset'] = i+1
1255 new_info['directory'] += self.alphabet[i % 26] + str((i+1)//26)
1256 jobs.append(new_info)
1257 self.create_ajob(pjoin(self.me_dir, 'SubProcesses', 'refine.sh'), jobs)
1258
1260 """update the html from this object since it contains all the information"""
1261
1262
1263 run = self.cmd.results.current['run_name']
1264 if not os.path.exists(pjoin(self.cmd.me_dir, 'HTML', run)):
1265 os.mkdir(pjoin(self.cmd.me_dir, 'HTML', run))
1266
1267 unit = self.cmd.results.unit
1268 P_text = ""
1269 if self.results:
1270 Presults = self.results
1271 else:
1272 self.results = sum_html.collect_result(self.cmd, None)
1273 Presults = self.results
1274
1275 for P_comb in Presults:
1276 P_text += P_comb.get_html(run, unit, self.cmd.me_dir)
1277
1278 Presults.write_results_dat(pjoin(self.cmd.me_dir,'SubProcesses', 'results.dat'))
1279
1280 fsock = open(pjoin(self.cmd.me_dir, 'HTML', run, 'results.html'),'w')
1281 fsock.write(sum_html.results_header)
1282 fsock.write('%s <dl>' % Presults.get_html(run, unit, self.cmd.me_dir))
1283 fsock.write('%s </dl></body>' % P_text)
1284
1285 self.cmd.results.add_detail('cross', Presults.xsec)
1286 self.cmd.results.add_detail('error', Presults.xerru)
1287
1288 return Presults.xsec, Presults.xerru
1289
1314
1329
1331 """Doing the refine in multicore. Each core handle a couple of PS point."""
1332
1333 nb_ps_by_job = 2000
1334 mode = "refine"
1335 gen_events_security = 1.15
1336
1337
1338
1340
1341 super(gen_ximprove_share, self).__init__(*args, **opts)
1342 self.generated_events = {}
1343 self.splitted_for_dir = lambda x,y : self.splitted_Pdir[(x,y)]
1344
1345
1347 """generate the script in order to generate a given number of event"""
1348
1349
1350
1351 goal_lum, to_refine = self.find_job_for_event()
1352 self.goal_lum = goal_lum
1353
1354
1355 total_ps_points = 0
1356 channel_to_ps_point = []
1357 for C in to_refine:
1358
1359 try:
1360 os.remove(pjoin(self.me_dir, "SubProcesses",C.parent_name, C.name, "events.lhe"))
1361 except:
1362 pass
1363
1364
1365 needed_event = goal_lum*C.get('axsec')
1366 if needed_event == 0:
1367 continue
1368
1369 if C.get('nunwgt') > 0:
1370 nevents = needed_event * (C.get('nevents') / C.get('nunwgt'))
1371
1372 nevents = int(nevents / (2**self.min_iter-1))
1373 else:
1374 nb_split = int(max(1,((needed_event-1)// self.max_request_event) +1))
1375 if not self.split_channels:
1376 nb_split = 1
1377 if nb_split > self.max_splitting:
1378 nb_split = self.max_splitting
1379 nevents = self.max_event_in_iter * self.max_splitting
1380 else:
1381 nevents = self.max_event_in_iter * nb_split
1382
1383 if nevents > self.max_splitting*self.max_event_in_iter:
1384 logger.warning("Channel %s/%s has a very low efficiency of unweighting. Might not be possible to reach target" % \
1385 (C.name, C.parent_name))
1386 nevents = self.max_event_in_iter * self.max_splitting
1387
1388 total_ps_points += nevents
1389 channel_to_ps_point.append((C, nevents))
1390
1391 if self.cmd.options["run_mode"] == 1:
1392 if self.cmd.options["cluster_size"]:
1393 nb_ps_by_job = total_ps_points /int(self.cmd.options["cluster_size"])
1394 else:
1395 nb_ps_by_job = self.nb_ps_by_job
1396 elif self.cmd.options["run_mode"] == 2:
1397 remain = total_ps_points % self.cmd.options["nb_core"]
1398 if remain:
1399 nb_ps_by_job = 1 + (total_ps_points - remain) / self.cmd.options["nb_core"]
1400 else:
1401 nb_ps_by_job = total_ps_points / self.cmd.options["nb_core"]
1402 else:
1403 nb_ps_by_job = self.nb_ps_by_job
1404
1405 nb_ps_by_job = int(max(nb_ps_by_job, 500))
1406
1407 for C, nevents in channel_to_ps_point:
1408 if nevents % nb_ps_by_job:
1409 nb_job = 1 + int(nevents // nb_ps_by_job)
1410 else:
1411 nb_job = int(nevents // nb_ps_by_job)
1412 submit_ps = min(nevents, nb_ps_by_job)
1413 if nb_job == 1:
1414 submit_ps = max(submit_ps, self.min_event_in_iter)
1415 self.create_resubmit_one_iter(C.parent_name, C.name[1:], submit_ps, nb_job, step=0)
1416 needed_event = goal_lum*C.get('xsec')
1417 logger.debug("%s/%s : need %s event. Need %s split job of %s points", C.parent_name, C.name, needed_event, nb_job, submit_ps)
1418
1419
1421
1422 grid_calculator, cross, error = self.combine_grid(Pdir, G, step)
1423
1424
1425 Gdirs = []
1426 for i in range(self.splitted_for_dir(Pdir, G)):
1427 path = pjoin(Pdir, "G%s_%s" % (G, i+1))
1428 Gdirs.append(path)
1429 assert len(grid_calculator.results) == len(Gdirs) == self.splitted_for_dir(Pdir, G)
1430
1431
1432
1433 needed_event = cross * self.goal_lum
1434 if needed_event == 0:
1435 return 0
1436
1437
1438 if self.err_goal >=1:
1439 if needed_event > self.gen_events_security * self.err_goal:
1440 needed_event = int(self.gen_events_security * self.err_goal)
1441
1442 if (Pdir, G) in self.generated_events:
1443 old_nunwgt, old_maxwgt = self.generated_events[(Pdir, G)]
1444 else:
1445 old_nunwgt, old_maxwgt = 0, 0
1446
1447 if old_nunwgt == 0 and os.path.exists(pjoin(Pdir,"G%s" % G, "events.lhe")):
1448
1449 lhe = lhe_parser.EventFile(pjoin(Pdir,"G%s" % G, "events.lhe"))
1450 old_nunwgt = lhe.unweight(None, trunc_error=0.005, log_level=0)
1451 old_maxwgt = lhe.max_wgt
1452
1453
1454
1455 maxwgt = max(grid_calculator.get_max_wgt(), old_maxwgt)
1456 new_evt = grid_calculator.get_nunwgt(maxwgt)
1457 efficiency = new_evt / sum([R.nevents for R in grid_calculator.results])
1458 nunwgt = old_nunwgt * old_maxwgt / maxwgt
1459 nunwgt += new_evt
1460
1461
1462 one_iter_nb_event = max(grid_calculator.get_nunwgt(),1)
1463 drop_previous_iteration = False
1464
1465 n_target_one_iter = (needed_event-one_iter_nb_event) / ( one_iter_nb_event/ sum([R.nevents for R in grid_calculator.results]))
1466 n_target_combined = (needed_event-nunwgt) / efficiency
1467 if n_target_one_iter < n_target_combined:
1468
1469
1470 drop_previous_iteration = True
1471 nunwgt = one_iter_nb_event
1472 maxwgt = grid_calculator.get_max_wgt()
1473 new_evt = nunwgt
1474 efficiency = ( one_iter_nb_event/ sum([R.nevents for R in grid_calculator.results]))
1475
1476 try:
1477 if drop_previous_iteration:
1478 raise IOError
1479 output_file = open(pjoin(Pdir,"G%s" % G, "events.lhe"), 'a')
1480 except IOError:
1481 output_file = open(pjoin(Pdir,"G%s" % G, "events.lhe"), 'w')
1482
1483 misc.call(["cat"] + [pjoin(d, "events.lhe") for d in Gdirs],
1484 stdout=output_file)
1485 output_file.close()
1486
1487
1488 if nunwgt < 0.6 * needed_event and step > self.min_iter:
1489 lhe = lhe_parser.EventFile(output_file.name)
1490 old_nunwgt =nunwgt
1491 nunwgt = lhe.unweight(None, trunc_error=0.01, log_level=0)
1492
1493
1494 self.generated_events[(Pdir, G)] = (nunwgt, maxwgt)
1495
1496
1497
1498 if nunwgt >= int(0.96*needed_event)+1:
1499
1500 logger.info("found enough event for %s/G%s" % (os.path.basename(Pdir), G))
1501 self.write_results(grid_calculator, cross, error, Pdir, G, step, efficiency)
1502 return 0
1503 elif step >= self.max_iter:
1504 logger.debug("fail to find enough event")
1505 self.write_results(grid_calculator, cross, error, Pdir, G, step, efficiency)
1506 return 0
1507
1508 nb_split_before = len(grid_calculator.results)
1509 nevents = grid_calculator.results[0].nevents
1510 if nevents == 0:
1511 nevents = max(g.nevents for g in grid_calculator.results)
1512
1513 need_ps_point = (needed_event - nunwgt)/(efficiency+1e-99)
1514 need_job = need_ps_point // nevents + 1
1515
1516 if step < self.min_iter:
1517
1518 job_at_first_iter = nb_split_before/2**(step-1)
1519 expected_total_job = job_at_first_iter * (2**self.min_iter-1)
1520 done_job = job_at_first_iter * (2**step-1)
1521 expected_remaining_job = expected_total_job - done_job
1522
1523 logger.debug("efficiency status (smaller is better): %s", need_job/expected_remaining_job)
1524
1525 need_job = min(need_job, expected_remaining_job*1.25)
1526
1527 nb_job = (need_job-0.5)//(2**(self.min_iter-step)-1) + 1
1528 nb_job = max(1, nb_job)
1529 grid_calculator.write_grid_for_submission(Pdir,G,
1530 self.splitted_for_dir(Pdir, G), nb_job*nevents ,mode=self.mode,
1531 conservative_factor=self.max_iter)
1532 logger.info("%s/G%s is at %i/%i (%.2g%%) event. Resubmit %i job at iteration %i." \
1533 % (os.path.basename(Pdir), G, int(nunwgt),int(needed_event)+1,
1534 (float(nunwgt)/needed_event)*100.0 if needed_event>0.0 else 0.0,
1535 nb_job, step))
1536 self.create_resubmit_one_iter(Pdir, G, nevents, nb_job, step)
1537
1538
1539 elif step < self.max_iter:
1540 if step + 1 == self.max_iter:
1541 need_job = 1.20 * need_job
1542
1543 nb_job = int(min(need_job, nb_split_before*1.5))
1544 grid_calculator.write_grid_for_submission(Pdir,G,
1545 self.splitted_for_dir(Pdir, G), nb_job*nevents ,mode=self.mode,
1546 conservative_factor=self.max_iter)
1547
1548
1549 logger.info("%s/G%s is at %i/%i ('%.2g%%') event. Resubmit %i job at iteration %i." \
1550 % (os.path.basename(Pdir), G, int(nunwgt),int(needed_event)+1,
1551 (float(nunwgt)/needed_event)*100.0 if needed_event>0.0 else 0.0,
1552 nb_job, step))
1553 self.create_resubmit_one_iter(Pdir, G, nevents, nb_job, step)
1554
1555
1556
1557 return 0
1558
1559
1560 - def write_results(self, grid_calculator, cross, error, Pdir, G, step, efficiency):
1561
1562
1563 if cross == 0:
1564 abscross,nw, luminosity = 0, 0, 0
1565 wgt, maxit,nunwgt, wgt, nevents = 0,0,0,0,0
1566 error = 0
1567 else:
1568 grid_calculator.results.compute_values()
1569 abscross = self.abscross[(Pdir,G)]/self.sigma[(Pdir,G)]
1570 nunwgt, wgt = self.generated_events[(Pdir, G)]
1571 nw = int(nunwgt / efficiency)
1572 nunwgt = int(nunwgt)
1573 maxit = step
1574 nevents = nunwgt
1575
1576 luminosity = nunwgt/cross
1577
1578
1579 def fstr(nb):
1580 data = '%E' % nb
1581 nb, power = data.split('E')
1582 nb = float(nb) /10
1583 power = int(power) + 1
1584 return '%.5fE%+03i' %(nb,power)
1585 line = '%s %s %s %i %i %i %i %s %s %s 0.0 0.0 0\n' % \
1586 (fstr(cross), fstr(error*cross), fstr(error*cross),
1587 nevents, nw, maxit,nunwgt,
1588 fstr(luminosity), fstr(wgt), fstr(abscross))
1589
1590 fsock = open(pjoin(self.me_dir,'SubProcesses' , Pdir, 'G%s' % G,
1591 'results.dat'),'w')
1592 fsock.writelines(line)
1593 fsock.close()
1594
1599
1600 min_iter = 1
1601 max_iter = 12
1602 max_request_event = 1e12
1603 max_event_in_iter = 5000
1604 min_event_in_iter = 1000
1605 combining_job = sys.maxint
1606
1610
1612
1613 self.ngran = -1
1614 self.gscalefact = {}
1615 self.readonly = False
1616 if 'ngran' in opts:
1617 self.gran = opts['ngran']
1618
1619 if 'readonly' in opts:
1620 self.readonly = opts['readonly']
1621 super(gen_ximprove_gridpack,self).__init__(*args, **opts)
1622 if self.ngran == -1:
1623 self.ngran = 1
1624
1626 """return the list of channel that need to be improved"""
1627 import random
1628
1629 assert self.err_goal >=1
1630 self.err_goal = int(self.err_goal)
1631 self.gscalefact = {}
1632
1633 xtot = self.results.axsec
1634 goal_lum = self.err_goal/(xtot+1e-99)
1635
1636
1637 all_channels = sum([list(P) for P in self.results],[])
1638 all_channels.sort(cmp= lambda x,y: 1 if y.get('luminosity') - \
1639 x.get('luminosity') > 0 else -1)
1640
1641 to_refine = []
1642 for C in all_channels:
1643 tag = C.get('name')
1644 self.gscalefact[tag] = 0
1645 R = random.random()
1646 if C.get('axsec') == 0:
1647 continue
1648 if (goal_lum * C.get('axsec') < R*self.ngran ):
1649 continue
1650 self.gscalefact[tag] = max(1, 1/(goal_lum * C.get('axsec')/ self.ngran))
1651
1652 logger.debug('request events for ', C.get('name'), 'cross=',
1653 C.get('axsec'), 'needed events = ', goal_lum * C.get('axsec'))
1654 to_refine.append(C)
1655
1656 logger.info('need to improve %s channels' % len(to_refine))
1657 return goal_lum, to_refine
1658
1660 """generate the script in order to generate a given number of event"""
1661
1662
1663
1664 goal_lum, to_refine = self.find_job_for_event()
1665
1666 jobs = []
1667
1668
1669
1670 for C in to_refine:
1671
1672 needed_event = max(goal_lum*C.get('axsec'), self.ngran)
1673 nb_split = 1
1674
1675
1676 if C.get('nunwgt') > 0:
1677 nevents = needed_event / nb_split * (C.get('nevents') / C.get('nunwgt'))
1678
1679 nevents = int(nevents / (2**self.min_iter-1))
1680 else:
1681 nevents = self.max_event_in_iter
1682
1683 if nevents < self.min_event_in_iter:
1684 nevents = self.min_event_in_iter
1685
1686
1687 nevents = max(self.min_event_in_iter, min(self.max_event_in_iter, nevents))
1688 logger.debug("%s : need %s event. Need %s split job of %s points", C.name, needed_event, nb_split, nevents)
1689
1690
1691
1692 info = {'name': self.cmd.results.current['run_name'],
1693 'script_name': 'unknown',
1694 'directory': C.name,
1695 'P_dir': os.path.basename(C.parent_name),
1696 'offset': 1,
1697 'Ppath': pjoin(self.cmd.me_dir, 'SubProcesses', C.parent_name),
1698 'nevents': nevents,
1699 'maxiter': self.max_iter,
1700 'miniter': self.min_iter,
1701 'precision': -1*int(needed_event+1)/C.get('axsec'),
1702 'requested_event': needed_event,
1703 'nhel': self.run_card['nhel'],
1704 'channel': C.name.replace('G',''),
1705 'grid_refinment' : 0,
1706 'base_directory': '',
1707 'packet': None,
1708 }
1709
1710
1711 jobs.append(info)
1712
1713
1714 write_dir = '.' if self.readonly else None
1715 self.create_ajob(pjoin(self.me_dir, 'SubProcesses', 'refine.sh'), jobs, write_dir)
1716
1717 done = []
1718 for j in jobs:
1719 if j['P_dir'] in done:
1720 continue
1721
1722
1723 pwd = pjoin(os.getcwd(),j['P_dir']) if self.readonly else pjoin(self.me_dir, 'SubProcesses', j['P_dir'])
1724 exe = pjoin(pwd, 'ajob1')
1725 st = os.stat(exe)
1726 os.chmod(exe, st.st_mode | stat.S_IEXEC)
1727
1728
1729 cluster.onecore.launch_and_wait(exe, cwd=pwd, packet_member=j['packet'])
1730
1731 write_dir = '.' if self.readonly else pjoin(self.me_dir, 'SubProcesses')
1732 self.check_events(goal_lum, to_refine, jobs, write_dir)
1733
1734
1736 """check that we get the number of requested events if not resubmit."""
1737
1738 new_jobs = []
1739
1740 for C, job_info in zip(to_refine, jobs):
1741 P = job_info['P_dir']
1742 G = job_info['channel']
1743 axsec = C.get('axsec')
1744 requested_events= job_info['requested_event']
1745
1746
1747 new_results = sum_html.OneResult((P,G))
1748 new_results.read_results(pjoin(Sdir,P, 'G%s'%G, 'results.dat'))
1749
1750
1751 if new_results.get('nunwgt') < requested_events:
1752 pwd = pjoin(os.getcwd(),job_info['P_dir'],'G%s'%G) if self.readonly else \
1753 pjoin(self.me_dir, 'SubProcesses', job_info['P_dir'],'G%s'%G)
1754 job_info['requested_event'] -= new_results.get('nunwgt')
1755 job_info['precision'] -= -1*job_info['requested_event']/axsec
1756 job_info['offset'] += 1
1757 new_jobs.append(job_info)
1758 files.mv(pjoin(pwd, 'events.lhe'), pjoin(pwd, 'events.lhe.previous'))
1759
1760 if new_jobs:
1761 self.create_ajob(pjoin(self.me_dir, 'SubProcesses', 'refine.sh'), new_jobs, Sdir)
1762
1763 done = []
1764 for j in new_jobs:
1765 if j['P_dir'] in done:
1766 continue
1767 G = j['channel']
1768
1769 pwd = pjoin(os.getcwd(),j['P_dir']) if self.readonly \
1770 else pjoin(self.me_dir, 'SubProcesses', j['P_dir'])
1771 exe = pjoin(pwd, 'ajob1')
1772 st = os.stat(exe)
1773 os.chmod(exe, st.st_mode | stat.S_IEXEC)
1774
1775
1776 cluster.onecore.launch_and_wait(exe, cwd=pwd, packet_member=j['packet'])
1777 pwd = pjoin(pwd, 'G%s'%G)
1778
1779 files.put_at_end(pjoin(pwd, 'events.lhe'),pjoin(pwd, 'events.lhe.previous'))
1780
1781 return self.check_events(goal_lum, to_refine, new_jobs, Sdir)
1782