slhaplot

changeset 134
323754f1d261
parent 133
5e27f4121fd1
child 136
1218f20d4cf5
equal deleted inserted replaced
133:5e27f4121fd1 134:323754f1d261
15 15
16 TODOs: 16 TODOs:
17 * Merge labels if shifting fails (cf. "poi" test spectrum file). 17 * Merge labels if shifting fails (cf. "poi" test spectrum file).
18 * Avoid overlap/too-tight clustering of y-axis ticks. Looks fine for *most* 18 * Avoid overlap/too-tight clustering of y-axis ticks. Looks fine for *most*
19 spectra I've seen with 100 GeV intervals, but it should be handled properly. 19 spectra I've seen with 100 GeV intervals, but it should be handled properly.
20 * Use object wrapper for format strings, to centralise "needs pdflatex?"-type
21 questions and provide UI case-insensitivity
22 * Allow user to provide a file which defines the particle line x-positions, labels, etc. 20 * Allow user to provide a file which defines the particle line x-positions, labels, etc.
23 * Allow use of --outname to specify a list of output base names for multiple inputs. 21 * Allow use of --outname to specify a list of output base names for multiple inputs.
24 * Use proper distinction between physical, plot-logical, and plot output coords. 22 * Use proper distinction between physical, plot-logical, and plot output coords.
25 * Allow user control over aspect ratio / geometry. 23 * Allow user control over aspect ratio / geometry.
26 * Use scaling to allow the y coordinates to be in units of 100 GeV in TikZ output. 24 * Use scaling to allow the y coordinates to be in units of 100 GeV in TikZ output.
80 self.textlabel = texlabel 78 self.textlabel = texlabel
81 self.anchor = anchor 79 self.anchor = anchor
82 self.color = color 80 self.color = color
83 81
84 82
83 # ## Python version workaround
84 # if not "any" in dir():
85 # def any(*args):
86 # for i in args:
87 # if i: return True
88 # return False
89
90
85 class OutputFormatSpec(object): 91 class OutputFormatSpec(object):
86 """Object to abstract translation of semi-arbitrary format strings into 92 """Object to abstract translation of semi-arbitrary format strings into
87 something more semantically queryable.""" 93 something more semantically queryable."""
88 pass 94
95 def __init__(self, fmtstr):
96 self.format_string = fmtstr.lower()
97 if "tikz" not in self.format_string:
98 self.format_string = "tikz" + self.format_string
99 if self.format_string == "tikz":
100 self.format_string = "tikztex"
101 elif self.format_string == "tikzfrag":
102 self.format_string = "tikztexfrag"
103 if "frag" in self.format_string and any(f in self.format_string for f in ["pdf", "eps", "png"]):
104 logging.error("Oops! You can't currently use LaTeX fragment output together with graphics "
105 "formats, since the graphics can't be built from the incomplete LaTeX "
106 "file. We'll fix this, but for now you will have to run slhaplot twice: "
107 "once for the LaTeX fragment, and another time for the graphical output "
108 "formats. Exiting...")
109 sys.exit(1)
110
111 def make_tex(self):
112 return ("tex" in self.format_string and not "frag" in self.format_string)
113
114 def make_texfrag(self):
115 return ("texfrag" in self.format_string)
116
117 def make_pdf(self):
118 return ("pdf" in self.format_string)
119
120 def make_eps(self):
121 return ("eps" in self.format_string)
122
123 def make_png(self):
124 return ("png" in self.format_string)
125
126
127 def need_tikz(self):
128 for f in ["pdf", "eps", "png"]:
129 if f in self.format_string:
130 return True
131 return False
132
133 def need_epslatex(self):
134 for f in ["eps"]:
135 if f in self.format_string:
136 return True
137 return False
138
139 def need_pdflatex(self):
140 for f in ["pdf", "png"]:
141 if f in self.format_string:
142 return True
143 return False
144
145 def need_convert(self):
146 for f in ["png"]:
147 if f in self.format_string:
148 return True
149 return False
150
151 def need_compilation(self):
152 return self.need_epslatex() or self.need_pdflatex()
153
154 def file_extensions(self):
155 return [f for f in ["tex", "pdf", "eps", "png"] if f in self.format_string]
156
89 157
90 158
91 import pyslha 159 import pyslha
92 import sys, optparse, logging 160 import sys, optparse, logging
93 parser = optparse.OptionParser(usage=__doc__, version=pyslha.__version__) 161 parser = optparse.OptionParser(usage=__doc__, version=pyslha.__version__)
152 if opts.DECAYS_MINBR.endswith("%"): 220 if opts.DECAYS_MINBR.endswith("%"):
153 opts.DECAYS_MINBR = float(opts.DECAYS_MINBR[:-1]) / 100.0 221 opts.DECAYS_MINBR = float(opts.DECAYS_MINBR[:-1]) / 100.0
154 else: 222 else:
155 opts.DECAYS_MINBR = float(opts.DECAYS_MINBR) 223 opts.DECAYS_MINBR = float(opts.DECAYS_MINBR)
156 224
157 ## Output format wrangling 225 ## Output format handling: convert string arg to a more semantically queryable type
158 if "tikz" not in opts.FORMAT: 226 opts.FORMAT = OutputFormatSpec(opts.FORMAT)
159 opts.FORMAT = "tikz" + opts.FORMAT
160 if opts.FORMAT == "tikz":
161 opts.FORMAT = "tikztex"
162 elif opts.FORMAT == "tikzfrag":
163 opts.FORMAT = "tikztexfrag"
164 if "frag" in opts.FORMAT and any(f in opts.FORMAT for f in ["pdf", "eps", "png"]):
165 logging.error("Oops! You can't currently use LaTeX fragment output together with graphics "
166 "formats, since the graphics can't be built from the incomplete LaTeX "
167 "file. We'll fix this, but for now you will have to run slhaplot twice: "
168 "once for the LaTeX fragment, and another time for the graphical output "
169 "formats. Exiting...")
170 sys.exit(1)
171 227
172 228
173 ## Check non-optional arguments 229 ## Check non-optional arguments
174 INFILES = args 230 INFILES = args
175 if len(INFILES) == 0: 231 if len(INFILES) == 0:
182 238
183 ## Test for external packages 239 ## Test for external packages
184 import subprocess 240 import subprocess
185 241
186 ## Test for tikz package if rendering the LaTeX source 242 ## Test for tikz package if rendering the LaTeX source
187 if not any(f in opts.FORMAT for f in ["pdf", "eps", "png"]): 243 if opts.FORMAT.need_tikz():
188 p = subprocess.Popen(["which", "kpsewhich"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 244 p = subprocess.Popen(["which", "kpsewhich"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
189 rtn = p.wait() 245 rtn = p.wait()
190 if rtn != 0: 246 if rtn != 0:
191 logging.warning("WARNING: kpsewhich could not be found: check for tikz package cannot be run") 247 logging.warning("WARNING: kpsewhich could not be found: check for tikz package cannot be run")
192 else: 248 else:
195 if rtn != 0: 251 if rtn != 0:
196 logging.error("LaTeX tikz.sty could not be found: graphical format modes cannot work") 252 logging.error("LaTeX tikz.sty could not be found: graphical format modes cannot work")
197 sys.exit(3) 253 sys.exit(3)
198 254
199 ## Test for pdflatex if we need to make a PDF 255 ## Test for pdflatex if we need to make a PDF
200 if "pdf" in opts.FORMAT or "png" in opts.FORMAT: 256 if opts.FORMAT.need_pdflatex():
201 p = subprocess.Popen(["which", "pdflatex"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 257 p = subprocess.Popen(["which", "pdflatex"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
202 rtn = p.wait() 258 rtn = p.wait()
203 if rtn != 0: 259 if rtn != 0:
204 logging.error("pdflatex could not be found: PDF format mode (and dependent ones like PNG) cannot work") 260 logging.error("pdflatex could not be found: PDF format mode (and dependent ones like PNG) cannot work")
205 sys.exit(3) 261 sys.exit(3)
206 262
207 ## Test for convert if we need to make a bitmap format 263 ## Test for convert if we need to make a bitmap format
208 if "png" in opts.FORMAT: 264 if opts.FORMAT.need_convert():
209 p = subprocess.Popen(["which", "convert"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 265 p = subprocess.Popen(["which", "convert"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
210 rtn = p.wait() 266 rtn = p.wait()
211 if rtn != 0: 267 if rtn != 0:
212 logging.error("convert could not be found: PNG format mode cannot work") 268 logging.error("convert could not be found: PNG format mode cannot work")
213 sys.exit(3) 269 sys.exit(3)
214 270
215 ## Test for latex, dvips and ps2eps if making an EPS 271 ## Test for latex, dvips and ps2eps if making an EPS
216 if "eps" in opts.FORMAT: 272 if opts.FORMAT.need_epslatex():
217 p = subprocess.Popen(["which", "latex"], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 273 p = subprocess.Popen(["which", "latex"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
218 rtn = p.wait() 274 rtn = p.wait()
219 if rtn != 0: 275 if rtn != 0:
220 logging.error("latex could not be found: EPS format mode cannot work") 276 logging.error("latex could not be found: EPS format mode cannot work")
221 sys.exit(3) 277 sys.exit(3)
244 elif "." in o: 300 elif "." in o:
245 o = o[:o.rindex(".")] 301 o = o[:o.rindex(".")]
246 outname = o 302 outname = o
247 303
248 ## Info for the user 304 ## Info for the user
249 # TODO: Print all output filenames explicitly? 305 extlist = opts.FORMAT.file_extensions()
250 extlist = [f for f in ["tex", "pdf", "eps", "png"] if f in opts.FORMAT]
251 extstr = ",".join(extlist) 306 extstr = ",".join(extlist)
252 if len(extlist) > 1: 307 if len(extlist) > 1:
253 extstr = "{" + extstr + "}" 308 extstr = "{" + extstr + "}"
254 logging.info("Plotting %s -> %s.%s" % (infile, outname, extstr)) 309 logging.info("Plotting %s -> %s.%s" % (infile, outname, extstr))
255 310
435 f.close() 490 f.close()
436 491
437 out = "" 492 out = ""
438 493
439 ## TIKZ FORMAT 494 ## TIKZ FORMAT
440 if "tikz" in opts.FORMAT: 495 # TODO: Remove this test?
496 if "tikz" in opts.FORMAT.format_string:
441 497
442 ## Comment out the preamble etc. if only the TikZ fragment is wanted 498 ## Comment out the preamble etc. if only the TikZ fragment is wanted
443 c = "" 499 c = ""
444 if opts.FORMAT == "tikztexfrag": 500 if opts.FORMAT.make_texfrag():
445 c = "%" 501 c = "%"
446 502
447 ## Write LaTeX header 503 ## Write LaTeX header
448 out += "%% http://pypi.python.org/pypi/pyslha\n\n" 504 out += "%% http://pypi.python.org/pypi/pyslha\n\n"
449 out += c + "\\documentclass[11pt]{article}\n" 505 out += c + "\\documentclass[11pt]{article}\n"
561 ## Write LaTeX footer 617 ## Write LaTeX footer
562 out += c + "\end{document}\n" 618 out += c + "\end{document}\n"
563 619
564 620
565 ## Write output 621 ## Write output
566 if "tex" in opts.FORMAT: 622 if opts.FORMAT.make_tex():
567 writeout(out, outname+".tex") 623 writeout(out, outname+".tex")
568 624
569 if any(f in opts.FORMAT for f in ["pdf", "eps", "png"]): 625 if opts.FORMAT.need_compilation():
570 ## Run LaTeX 626 ## Run LaTeX
571 import tempfile, shutil, subprocess 627 import tempfile, shutil, subprocess
572 tmpdir = tempfile.mkdtemp() 628 tmpdir = tempfile.mkdtemp()
573 writeout(out, os.path.join(tmpdir, "mytmp.tex")) 629 writeout(out, os.path.join(tmpdir, "mytmp.tex"))
574 630
576 "Convenience method to reduce repeated subprocess.Popen call noise in what follows." 632 "Convenience method to reduce repeated subprocess.Popen call noise in what follows."
577 return subprocess.Popen(cmdlist, cwd=tmpdir, 633 return subprocess.Popen(cmdlist, cwd=tmpdir,
578 stdout=subprocess.PIPE, stderr=subprocess.PIPE) 634 stdout=subprocess.PIPE, stderr=subprocess.PIPE)
579 635
580 ## Processing via PDF 636 ## Processing via PDF
581 if any(f in opts.FORMAT for f in ["pdf", "png"]): 637 if opts.FORMAT.need_pdflatex():
582 try: 638 try:
583 p = mktmpprocess(["pdflatex", r"\scrollmode\input", "mytmp.tex"]) 639 p = mktmpprocess(["pdflatex", r"\scrollmode\input", "mytmp.tex"])
584 p.wait() 640 p.wait()
585 if "pdf" in opts.FORMAT: 641 if opts.FORMAT.make_pdf():
586 shutil.copyfile(os.path.join(tmpdir, "mytmp.pdf"), outname+".pdf") 642 shutil.copyfile(os.path.join(tmpdir, "mytmp.pdf"), outname+".pdf")
587 except Exception, e: 643 except Exception, e:
588 logging.error("pdflatex could not be run: PDF and/or PNG format mode cannot work") 644 logging.error("pdflatex could not be run: PDF and/or PNG format mode cannot work")
589 shutil.rmtree(tmpdir) 645 shutil.rmtree(tmpdir)
590 sys.exit(3) 646 sys.exit(3)
591 # TODO: Can we use a finally block to make sure that the tmpdir is cleared up, despite the 'sys.exit's? 647 # TODO: Can we use a finally block to make sure that the tmpdir is cleared up, despite the 'sys.exit's?
592 648
593 ## Turning the PDF into a PNG if required 649 ## Turning the PDF into a PNG if required
594 if "png" in opts.FORMAT: 650 if opts.FORMAT.make_png():
595 try: 651 try:
596 p = mktmpprocess(["convert", "-density", "150", "-flatten", "mytmp.pdf", "mytmp.png"]) 652 p = mktmpprocess(["convert", "-density", "150", "-flatten", "mytmp.pdf", "mytmp.png"])
597 p.wait() 653 p.wait()
598 shutil.copyfile(os.path.join(tmpdir, "mytmp.png"), outname+".png") 654 shutil.copyfile(os.path.join(tmpdir, "mytmp.png"), outname+".png")
599 except Exception, e: 655 except Exception, e:
600 logging.error("convert could not be run: PNG format mode cannot work") 656 logging.error("convert could not be run: PNG format mode cannot work")
601 shutil.rmtree(tmpdir) 657 shutil.rmtree(tmpdir)
602 sys.exit(3) 658 sys.exit(3)
603 659
604 ## Making a PS or EPS 660 ## Making a PS or EPS
605 if any(f in opts.FORMAT for f in ["eps"]): 661 if opts.FORMAT.make_eps():
606 try: 662 try:
607 p = mktmpprocess(["latex", r"\scrollmode\input", "mytmp.tex"]) 663 p = mktmpprocess(["latex", r"\scrollmode\input", "mytmp.tex"])
608 p.wait() 664 p.wait()
609 except Exception, e: 665 except Exception, e:
610 logging.error("latex could not be run: EPS format mode cannot work") 666 logging.error("latex could not be run: EPS format mode cannot work")

mercurial