Page MenuHomeHEPForge

No OneTemporary

diff --git a/ChangeLog b/ChangeLog
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,601 +1,605 @@
+2019-05-08 Andy Buckley <andy.buckley@cern.ch>
+
+ * Apply patches to prof2-I, from Christine Rasmussen.
+
2018-10-02 Holger Schulz <iamholger@gmail.com>
* Release 2.3.0, probably the last C++ release.
2018-02-07 Andy Buckley <andy.buckley@cern.ch>
* Add numCoeffs, numParams, and exprString methods to Ipol.
2017-10-25 Holger Schulz <iamholger@gmail.com>
* Bugfix missing import statement
2017-12-29 Holger Schulz <iamholger@gmail.com>
* Exposed more C++ functions to python for Pade approximation testing
2017-11-10 Holger Schulz <iamholger@gmail.com>
* Release 2.2.2 --- this is the result of many months of fiddling
with especially multinest requirements.
* Sampling --- sobol, latin hypercube and random uniform sampler
--- something like PARAM 0 1 2 3 result in sub space
sampling
--- biases now work e.g. PARAM 0 1 exp(x)
* Ipol --- --order auto and friends automatically determine
best order, this avoids oversampling.
--- --logy parmeterises the logy of things, useful
for large paramspace and especially likelihood
--- --medianfilt can drop anchor points based on error
this is experimental and meant to deal with the
occasional huge NLO weight
--- The output has the valid region for each object now
stored at the end of the coefficients, this is also where
they are read from --- this allows the usage of
--medianfilt etc
* Tune --- Replace the grid sampling with the already existing
sampler machinery, so can use random, latin, sobol when
using --scan to find good start point for minuit
--- --profiles and --contours stores the minuit and minos
plots
--- limits are by default now set to the ipol region, this
can be overridden when using -x CL arg
--- tune script can read more than one ipol file
A lot of stuff has been put into libraries to allow reusing
individual steps.
* Multinest --- this is now supported in prof2-tune-nest
* GP --- gp_minimize via prof2-tune-gp
* emcee --- MCMC sampling via prof2-emcee
* Eigentunes --- prof2-eigentunes is back and working, deltaChi2
must be provided, however, via --target
* Bootstrapping in principle working but smearing is probably
more complicated than what we have now prof2-bootstrap
2017-08-22 Holger Schulz <holger.schulz@durham.ac.uk>
* Improvements to Ipol --- we allow different orders for each bin now,
there is also --order auto which does some jackknifing to figure out
the best suited polynomial order to avoid overfitting. The Ipol
outputformat is now binned 3 which dumps the minparam values and
maxparamvalues at the end of the coefficient string. This is necessary
as we now also allow to filter the inputs by median error (necessary
to tame NLO spiky histograms). The ranges are read back for each bin
separately now, happens in the C++ part.
* Overhaul of sampling, including things such as full support of sobol
sampling. Also, param range files with more than two numbers on a line
are interpreted as sub spaces for patch sampling.
* Add script prof2-ipolenvelopes which for each bin finds the minimum
and maximum polynomial value (using migrad) in the range of the
ipols validity. This is nice especially to check envelopes once
filtering in the ipol step was done
2017-05-18 Holger Schulz <holger.schulz@durham.ac.uk>
* Refitting of ipols using smeared ipol output.
Required some modification in data io structure.
2017-05-04 Holger Schulz <holger.schulz@durham.ac.uk>
* Fix in prof2-tune when checking analysis names, at the same time
allow for for closure test tuning, i.e. tune against input folder.
2017-05-02 Holger Schulz <holger.schulz@durham.ac.uk>
* Use -march=native according to eigen3 faq for better performance
as well as -O3 in pyext
* Replace modulus based status message by simple counter in ipol stage
* Set version to 2.2.2beta for imminent release
2017-04-28 Holger Schulz <holger.schulz@durham.ac.uk>
* Use BDSSVD in case Eigen >=3.3.3
* Reworked prof2-ipol and ipol.py to use mk_ipolbin rather than
mk_ipolhisto, some speedups plus additional benefit of being
able to fiddle with inividual bins in the ipol building stage
* add --minos switch to prof2-tune toi run MINOS
* Write GOF and NDOF into result file
2017-02-21 Andy Buckley <andy.buckley@cern.ch>
* Change prof2-ipol ierr mode default to 'symm'
2017-02-17 Andy Buckley <andy.buckley@cern.ch>
* Add a --limit-errs argument for prof2-tune, to avoid annoying
re-reading of large run dirs
* Tweaks to default error ipol order, and release figure handles
in envelope plotting.
2017-02-02 Holger Schulz <holger.schulz@durham.ac.uk>
* Update Copyright string
* Instead of exiting when prof2-ipol encounters nan coefficients in
value or error ipols, spit out a warning and ignore that histogram
entirely --- this makes prof2-ipol and friends much more robust
* tag as 2.2.1 and release.
2017-02-01 Holger Schulz <holger.schulz@durham.ac.uk>
* Use Agg as default matplotlib backend.
* Bump version to 2.2.1
2016-12-19 Holger Schulz <holger.schulz@cern.ch>
* Even more robust prof-tune, added --filter CL option to
automatically get rid of zero error bins
* Fixed a bug where IpolBin.n was never set which is needed for
the PointMatcher (i.e. weights syntax)
* Not using YODA Pointmatcher but own due to different regexes
required.
* Make release 2.2
2016-12-15 Holger Schulz <holger.schulz@cern.ch>
* More robust scripts and more meaningful error messages, especially
prof2-tune
2016-11-30 Holger Schulz <holger.schulz@cern.ch>
* Replace Counter code when running mk_Structure with much faster code
* Bump version to 2.2
* Bump DataFormat to binned 2
* Allow passing file names or open files (or similar streams) to
ipolio functions
* prof2-ipol can read yaml now
* Add some of Elliot's code for choosing sub spaces in prof2-ipol and
some plot routines to contrib
* Add SOBOL sampling to contrib
2016-08-26 Holger Schulz <holger.schulz@cern.ch>
* Use more readable Cython DL path in bootstrap
2016-07-18 Andy Buckley <andy.buckley@cern.ch>
* Typo fixes -- thanks to Leif Gellersen.
2016-07-14 Andy Buckley <andy.buckley@cern.ch>
* Release version 2.1.4
* Improve Makefile tests for ROOT and Cython versions.
2016-07-11 Andy Buckley <andy.buckley@cern.ch>
* Add Ipol min/max param vals getters and map them into Python.
* Add a built-in /REF-stripping option to data histo loading.
* Improvements to the Python ipol metadata interface.
2016-07-05 Andy Buckley <andy.buckley@cern.ch>
* Try to optimise long-vector building by not executing pow() if the exponent would be zero.
* Split C++ calcValue function into two, to allow re-use of a precalculated long-vector.
2016-06-23 Andy Buckley <andy.buckley@cern.ch>
* Split 'dot product' part of ipol value calculation into a standalone calcValue function.
* Use const references when passing const vectors in C++ API.
2016-04-14 Holger Schulz <holger.schulz@cern.ch>
* Introduce 1D sensitivity based on gradient
* User needs to specify --cmap or --grad when running prof2-sens now
2016-04-01 Holger Schulz <holger.schulz@cern.ch>
* Add a first version of the parametrisation using Machine Learning
2016-02-16 Holger Schulz <holger.schulz@cern.ch>
* Bump to version 2.1.3
2016-02-15 Holger Schulz <holger.schulz@cern.ch>
* prof2-sens: bugfix, add weight file usage, clean up CL
* prof2-I: add weight file usage
* prof2-predict: add weight file usage, fix output writing
* Extended documentation
2016-02-12 Holger Schulz <holger.schulz@cern.ch>
* Documentation including asciinema
2016-02-11 Holger Schulz <holger.schulz@cern.ch>
* Remove min_runs function, replace with numCoeffs
from C++ code
* Add prof2-envelopes script
* In prof-tune simplechi2 --- continue on weight==0
to allow some robustness when switching off bins
2016-02-10 Holger Schulz <holger.schulz@cern.ch>
* First version of prof2-runcombs plus sampling functions
salvaged from Prof1, modified to have no scipy dependence
* Add --rc switch to prof2-ipol to optionally read runcombs
Syntax is --rc runcoms.dat[colon]5
(Minimally invasive addon)
* Code cull in prof2-ipol. Only support multiprocessing
version, default 1 thread. Changed CL switch to '-j'.
2015-12-16 Holger Schulz <holger.schulz@cern.ch>
* Only calculate polynomials structure once per instance
-> significant speed increase
* Add the brute force grid scan (--scan) to prof2-tune
2015-12-11 Holger Schulz <holger.schulz@cern.ch>
* Minimiser tweaks --- no more need for param translation,
make strategy steerable (--strategy or -s), -q suppresses
iminuit output now, calculation and writing of correlation
matrix into results, dump weights into results file
2015-12-10 Holger Schulz <holger.schulz@cern.ch>
* Undo ui madness
* Remove numpy dependence (except sampling.py)
* Add prof-sens for sensitivity plotting exploting derivatives
2015-12-09 Holger Schulz <holger.schulz@cern.ch>
* Can specify PREFIX when calling make
2015-12-09 Andy Buckley <andy.buckley@cern.ch>
* Improve prof2-predict UI.
* Add metadata printing in prof2-lsipol debug mode.
* Add -v and -q flag shortcuts to all scripts.
2015-12-07 Holger Schulz <holger.schulz@cern.ch>
* Use __all__ in __init__.py
* Started sphinx documentation
* Support only iminuit, bump version to 2.2.alpha, restructure imports
* Sanity checks when calling parametrisation
2015-12-03 Andy Buckley <andy.buckley@cern.ch>
* Provide a version() function in the C++ library, and map it into
Python. Both sources use the VERSION variable defined in the
Makefile at build time.
* Reduce SVD fitting threshold to 1e-20.
2015-12-03 Holger Schulz <holger.schulz@cern.ch>
* Make derivative calculation work also when scaling params
* Let YODA write YODA
2015-12-02 Holger Schulz <holger.schulz@cern.ch>
* Derivative calculation
2015-11-28 Andy Buckley <andy.buckley@cern.ch>
* Version 2.1.2
* Revert range shift in Ipol.cc, since it produced (small)
numerical errors rather than improved stability. To be
understood...
* Add test/mkpolydata script, for generating polynomial pseudodata
used in closure tests.
2015-11-27 Andy Buckley <andy.buckley@cern.ch>
* Fix bug in histo loading.
* Adding log binning and other options to prof2-residuals.
2015-11-24 Andy Buckley <andy.buckley@cern.ch>
* Version 2.1.1 release.
* Fix prof2-predict YODA writing, and improve DataHisto.toYODA.
* Change parameter rescaling from using the [0,1] range to instead
use [1,2], to avoid arbitrarily scaled param numbers. BREAKS IPOL
FILE COMPATIBILITY WITH 2.1.0!!
* Set minimizer initial step size = prange/10.
* Add automatic determination of maximum MC errors in prof-tune,
and use them to regularize interpolated errs which could distort
the fit.
* Separate internal Minuit function names (with syntax
restrictions) from the free-form external param names.
2015-11-23 Andy Buckley <andy.buckley@cern.ch>
* Add pyext/professor2/chi2.py
* Add find_maxerrs() to the Python interface, for use in error regularisation.
* Use the param file name as a regex.
* Use __slots__ in the internal histogram and bin types, for better memory efficiency.
* Fix (re-fix?) use of inappropriate indices in calculation of mean and median MC uncertainties.
* More proactive data object deletion after conversion to YODA data format.
2015-11-22 Andy Buckley <andy.buckley@cern.ch>
* Version 2.1.0 (significant version change due to scaling, all-orders, and ROOT support)
2015-11-18 Andy Buckley <andy.buckley@cern.ch>
* dataio.py: Add ROOT file reading ability.
* Change rescaling I/O behaviour a bit, moving some hacked
Python-only Ipol string constructors into explicit API improvements, and
only activating rescaling if DoParamScaling is set true.
2015-11-16 Andy Buckley <andy.buckley@cern.ch>
* Add CPPFLAGS steering in Makefile and API tidying.
2015-11-11 Holger Schulz <holger.schulz@cern.ch>
* Add automatic raw param value -> unit range mapping to Ipol.
* Add any-order long vector calculation.
2015-11-10 Andy Buckley <andy.buckley@cern.ch>
* Add prof2-lsipol as a handy way to make a tuning weights file
and for general convenience.
2015-10-06 Andy Buckley <andy.buckley@cern.ch>
* Version 2.0.0
* Add 'make dist' target to Makefile, and tweak/reduce Cython necessity
* Allow calls to IpolBin and IpolHisto methods with params passed
as unpacked *args as well as a packed iterable.
* Add possibility to pass params as an dict-like as well as a list
or tuple of floats -- note that the dict-like must return
*ordered* values consistent with the Ipol training. Also ensure
the float type.
* Add conversion of C++ exceptions to Python exceptions.
* Add professor2.utils module, providing an opportunistic use of
OrderedDict for params so the params order required by Ipol is the
same as the order in which they are specified in the (first run's)
params.dat file.
* Change Python-mapped Ipol methods with no args to be properties.
* Add nice __repr__ methods for Histo and Bin objects.
* Specialise Histo as IpolHisto and DataHisto, and provide
toData{Histo,Bin} on IpolHisto and IpolBin respectively.
* Remove ProfMaster.
2015-10-04 Andy Buckley <andy.buckley@cern.ch>
* Add protection of svd.setThreshold call to ensure it is
supported/needed, via Eigen version number macros.
* Add vmin and vmax args to Ipol and IpolBin in Python.
2015-10-02 Andy Buckley <andy.buckley@cern.ch>
* Put histo file reading in a try..except block so read failures
on non-histo files in the run dirs are not fatal.
* Add protection in the histo loader, so we don't trip up on
Rivet's new cross-section and counter objects.
2015-09-30 Andy Buckley <andy.buckley@cern.ch>
* src/Ipol.h: Use Eigen/SVD include path rather than non-standard eigen3/Eigen/SVD.
2015-09-14 Holger Schulz <holger.schulz@durham.ac.uk>
* Use Eigen's svd.setThreshold(1e-20) to prevent the errors we saw with Eigen
3.2.2 and later when looking at 5th order polynomials in 3 dimensinos
with 900+ anchors
* Some clean up
2015-09-11 Andy Buckley <andy.buckley@cern.ch>
* Adding prof2-residuals script for ipol faithfulness testing.
* Rename scripts from prof-* to prof2-* to allow parallel installations of Prof1 and Prof2.
* Move some non-core scripts from bin to contrib.
* Make root-config dependency optional
* Lots of reworking to make prof-tune work again, and to use weight file parsing.
2015-09-10 Andy Buckley <andy.buckley@cern.ch>
* Use weight file path parsing in prof-ipol.
* Add prof.weights submodule, with a copy of PointMatcher and a
new read_pointmatchers function for handling weight files.
* Provide __version__attribute in the Python module.
* User script CLI consistency, simplification, general smoothing...
2015-08-30 Andy Buckley <andy.buckley@cern.ch>
* Add recursive scangrid generator function, and other tweaks.
2015-08-18 Andy Buckley <andy.buckley@cern.ch>
* Tweaks to ipol file parsing functions.
* Fix a bug in IpolBin's use of interpolated errors.
* Convert mean and median error parameterisation to use new 0th order ipols.
2015-08-15 Holger Schulz <holger.schulz@durham.ac.uk>
* A first version of catching singular matrices in the SVD
* Ipol has 1 additional argument, "threshold", that determines what
singular values are considered 0, fully propagated to pyext
* Going 2 Pro 2 Fessional
* Some startup checks of prof- scripts
* remove bin/prof-sampling, rename prof-prediction -> prof-predict
2015-08-13 Holger Schulz <holger.schulz@durham.ac.uk>
* Reverted unintended commit of hack.
* Added very basic prof-config script to bin
* Update PATH when sourcing setup.sh
2015-08-12 Holger Schulz <holger.schulz@durham.ac.uk>
* Added prof-prediction which reads in a ifile and a point in
parameter space (either a text file, a comma separated list or just
the args) and writes out an ipolhisto. Tested to work.
2015-08-03 Holger Schulz <holger.schulz@durham.ac.uk>
* Added 0-order polynomials, i.e. constant values.
Currently, the coefficent is simply the value of
the first anochorpoint.
2015-07-15 Holger Schulz <holger.schulz@durham.ac.uk>
* Some pull plotting functionality
2015-07-08 Holger Schulz <holger.schulz@durham.ac.uk>
* Calculate and print G.o.f.
* Write some meta info to results
* Read limits, fixed params from single textfile --limits
* Output files steered by --output
* Remove now obsolete bin/prof-interpolate
2015-07-08 Holger Schulz <holger.schulz@durham.ac.uk>
* First working version of prof-tune (pyminuit, simpleGOF)
* Multiprocessing to speed up prof-ipol (--multi)
* prof-ipol-tabulated to write out interpolation of tabulated data
* Minor bugfixes
2015-06-16 Andy Buckley <andy.buckley@cern.ch>
* Adding mean and median strategies for assigning constant ipol bin errors.
2015-06-03 Andy Buckley <andy.buckley@cern.ch>
* Adding a Bin base class in the Python side, and a coherent handling of multiple (interpolated) bin errors.
* Various tweaks and minor fixes.
2015-05-10 Andy Buckley <andy.buckley@cern.ch>
* Add 'Minuit' class importing to the __init__.py file.
2015-05-05 Andy Buckley <andy.buckley@cern.ch>
* Rewrite C++ ipolstring parsing using STL string functions rather than Boost: shorter! Boost dependency GONE :-)
* Replace boost::tuple with std::pair and clean up ParamPoints interface a bit.
* Add a --veto option to prof-sample, for a user-specified vetoing function.
* Move Sampler from prof-sample into professor2/__init__.py
2015-05-04 Andy Buckley <andy.buckley@cern.ch>
* Adding a first version of prof-tune with ipol reading from file.
* Adding options for (average) error interpolation and ipol persistency to prof-ipol and module functions.
2015-05-03 Andy Buckley <andy.buckley@cern.ch>
* Add bin/prof-ipol simple script using the functions below -- to be merged with prof-interpolate.
* professor2/__init__.py: Add Histo, DataBin, IpolBin and basic data handling functions.
* Remove unnecessary dlopen fiddling from professor2/__init__.py
2015-04-23 Andy Buckley <andy.buckley@cern.ch>
* Remove bound ParamPoints pointer from Ipol, and ditch lazy coeff evaluation in favour of simplicity and construct-time coeff calculating.
* Move long vector and coeff building into unbound functions rather than Ipol methods.
* Start of ChangeLog. Library has already iterated quite a bit.
* FILL IN EARLY HISTORY FROM HG LOG
diff --git a/bin/prof2-I b/bin/prof2-I
--- a/bin/prof2-I
+++ b/bin/prof2-I
@@ -1,462 +1,481 @@
#!/usr/bin/env python
"""\
%prog [<ipolfile>=ipol.dat [<refdir>]]
Interactive parameterisation explorer with optional ref data display
TODO:
* Need to allow no-ref visualisation
* Optionally display the envelope of input MC runs
"""
import optparse, os, sys
op = optparse.OptionParser(usage=__doc__)
op.add_option("-v", "--debug", dest="DEBUG", action="store_true", default=False, help="Turn on some debug messages")
op.add_option("-q", "--quiet", dest="QUIET", action="store_true", default=False, help="Turn off messages")
op.add_option("--wfile", dest="WFILE", default=None, help="Path to a weight file, used to restrict plotting to a subset of histograms (default: %default)")
# TODO: Add weight file parsing to decide which histos (and bin subsets) to interpolate
opts, args = op.parse_args()
## Get arguments
IFILE = "ipol.dat"
if len(args) >= 1:
IFILE = args[0]
REFDIR = None
if len(args) >= 2:
REFDIR = args[1]
## Load the Professor machinery
import professor2 as prof
from professor2 import misc
if not opts.QUIET:
print prof.logo
## Read in ipol histos
IHISTOS, METADATA = prof.read_ipoldata(IFILE)
## Weight file parsing
if opts.WFILE:
matchers = prof.read_pointmatchers(opts.WFILE)
for hn in IHISTOS.keys():
if not any(m.match_path(hn) for m in matchers.keys()):
del IHISTOS[hn]
if len(IHISTOS.keys())==0:
print "Nothing left after weight file parsing, exiting"
sys.exit(0)
## List of rivet analysis paths in IHISTOS
# TODO: Urgh, avoid this sort of noise-code!
ananames = list(set([filter(lambda x:len(x)>1, i.split("/"))[0] for i in IHISTOS.keys()]))
## Read reference data histos
import glob
HISTOS = {}
# TODO: consistent directory convention and protect against invalid structures
if REFDIR is not None:
reffiles = glob.glob(os.path.join(REFDIR, "*"))
for rf in reffiles:
HISTOS.update(prof.read_histos(rf))
## Find things available in both
available = []
for i in IHISTOS.keys():
if i in HISTOS.keys():
available.append([i,i])
ibins = []
databins = []
for a in available:
ibins.extend( IHISTOS[a[0]].bins)
databins.extend(HISTOS[a[1]].bins)
else:
ibins = []
available = [(i,i) for i in IHISTOS.keys()]
for a in available:
ibins.extend( IHISTOS[a[0]].bins)
## Sanity checks
if not ibins:
print "No bins ..., exiting"
import sys
sys.exit(1)
## Import and set up matplotlib (AFTER parsing arguments)
try:
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.figure import Figure
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigCanvas
from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg as NavigationToolbar
import wx, functools
params = {
'backend': 'pdf',
'axes.labelsize' : 16,
'text.size' : 16,
'legend.fontsize' : 16,
'axes.titlesize' : 16,
'xtick.labelsize' : 16,
'ytick.labelsize' : 16,
'text.usetex' : False,
'figure.dpi' : 50,
'lines.markersize' : 10,
'lines.linewidth' : 2,
'lines.elinewidth' : 3,
'lines.antialiased' : False,
#'patches.antialiased' : False,
'figure.subplot.left' : 0.05,
'figure.subplot.right' : 0.995,
'figure.subplot.bottom' : 0.1,
'figure.subplot.top' : 0.95,
'figure.subplot.wspace' : 0.15
}
for k, v in params.iteritems():
try:
matplotlib.rcParams[k] = v
except:
pass
except Exception, e:
print "Problem with getting & configuring matplotlib/WX interface method: %s" % e
print "Exiting!"
sys.exit(1)
observables=sorted([a[0] for a in available]) # When interested in comparison with data
#observables=sorted(IHISTOS.keys()) # all ipols, not neccessary data available
# TODO: add error bar plotting option (with errs from ipol)
def mk_line(obs, ppoint, derivative=False):
"""
Prepare points for matplotlib step
"""
X, Y = [], []
for b in IHISTOS[obs].bins:
X.append(b.xmin)
X.append(b.xmax)
if derivative:
y = b.der(ppoint)
else:
y = b.val(ppoint)
Y.append(y)
Y.append(y)
return X, Y
def mk_data(obs, prefix=""):
X, Y, dY = [], [], []
try:
for b in HISTOS[prefix+obs].bins:
X.append(b.xmid)
Y.append(b.val)
dY.append(b.err)
except Exception, e:
if opts.DEBUG:
print "No data available for %s"%obs
return X, Y, dY
def mk_pull(obs, ppoint, prefix="/REF"):
"""
Prepare points for matplotlib step
"""
X, Y = [], []
for num, b in enumerate(IHISTOS[obs].bins):
X.append(b.xmin)
X.append(b.xmax)
p=prof.misc.pull(HISTOS[prefix+obs].bins[num], b, ppoint)
Y.append(p)
Y.append(p)
return X, Y
class ParamFrame(wx.Frame):
"""
Simple frame with param sliders that update the main frame's plots.
"""
def __init__(self, parent):
no_sys_menu = wx.CAPTION
wx.Frame.__init__(self, None, title='Prof-I: Parameter control')#, style=no_sys_menu)
self.params = METADATA["ParamNames"].split()
self.panel = wx.Panel(self)
self.parent = parent
self.sliders = {}
## Parameter sliders and buttons
controlgrid = wx.GridBagSizer(hgap=5, vgap=2)
font = wx.Font(10, wx.MODERN, wx.NORMAL, wx.BOLD)
## Build the sliders and related objects
for i, param in enumerate(self.params):
### Add param names
t=wx.StaticText(self.panel, -1, param)
t.SetFont(font)
controlgrid.Add(t, pos=(i,0))
## Sliders
#http://www.wxpython.org/docs/api/wx.lib.agw.floatspin-module.html
from wx.lib.agw.floatspin import FloatSpin, EVT_FLOATSPIN
pmin = float(METADATA["MinParamVals"].split()[i])
pmax = float(METADATA["MaxParamVals"].split()[i])
from wx.lib.agw.floatspin import FloatSpin, EVT_FLOATSPIN
slider = FloatSpin(self.panel, -1, style=0, value=pmin + 0.5*(pmax-pmin),
min_val=pmin, max_val=pmax, increment=abs(pmax-pmin)/50., size=(400,40))
controlgrid.Add(slider, pos=(i,2))
self.sliders[param] = slider
self.Bind(EVT_FLOATSPIN, self.parent.sliderUpdate)
self.panel.SetSizer(controlgrid)
controlgrid.Fit(self)
class ProfIFrame(wx.Frame):
def __init__(self):
title = 'prof-I: Professor Interactive'
wx.Frame.__init__(self, None, -1, title)
# The Frame with the parameter thingies
self.child = ParamFrame(self)
self.child.Show()
# This frame
self.histos = {}
self.refhistos = {"left" : None, "right" : None}
self.logy = {"left" : False, "right" : False}
+ self.logx = {"left" : False, "right" : False}
self.pull = {"left" : False, "right" : False}
self.derivative = {"left" : False, "right" : False}
self.limits = {}
self.drawobs = { "left" : sorted(observables)[0],
"right" : sorted(observables)[1 if len(observables) > 1 else 0] }
self.createMainPanel()
self.updateObs(None, "left")
self.updateObs(None, "right")
def createMainPanel(self):
""" Creates the main panel with all the controls on it:
* mpl canvas
* mpl navigation toolbar
* Control panel for interaction
"""
self.dpi=50
self.panel = wx.Panel(self)
## Panel for observable diplay
self.fig = Figure((10.0, 4.0), dpi=self.dpi, facecolor="white")
self.canvas = FigCanvas(self.panel, -1, self.fig)
self.axes = self.fig.add_subplot(121)
self.axes2 = self.fig.add_subplot(122)
## Layout with box sizers
## matplotlib canvas and matplotlib toolbar
self.vbox = wx.BoxSizer(wx.VERTICAL)
self.vbox.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW | wx.EXPAND)
## Choice of observable 1
self.hbox = wx.GridBagSizer(hgap=5, vgap=2)
self.hbox.Add(wx.StaticText(self.panel, -1, "Obs 1:"), pos=(0,0))
self.obschoice1 = wx.Choice(self.panel, -1, (85, 18), choices=sorted(observables))
self.obschoice1.SetSelection(sorted(observables).index(self.drawobs["left"]))
self.hbox.Add(self.obschoice1, pos=(0,1))
self.logy1chkbx = wx.CheckBox(self.panel, -1, "logy")
+ self.logx1chkbx = wx.CheckBox(self.panel, -1, "logx")
self.hbox.Add(self.logy1chkbx, pos=(0,2))
+ self.hbox.Add(self.logx1chkbx, pos=(0,3))
self.Bind(wx.EVT_CHOICE, functools.partial(self.updateObs, which="left"), self.obschoice1)
self.Bind(wx.EVT_CHECKBOX, self.setLogy, self.logy1chkbx)
+ self.Bind(wx.EVT_CHECKBOX, self.setLogx, self.logx1chkbx)
self.pull1chkbx = wx.CheckBox(self.panel, -1, "pull")
- self.hbox.Add(self.pull1chkbx, pos=(0,3))
+ self.hbox.Add(self.pull1chkbx, pos=(0,4))
self.der1chkbx = wx.CheckBox(self.panel, -1, "derivative")
- self.hbox.Add(self.der1chkbx, pos=(0,4))
+ self.hbox.Add(self.der1chkbx, pos=(0,5))
self.Bind(wx.EVT_CHOICE, functools.partial(self.updateObs, which="left"), self.obschoice1)
self.Bind(wx.EVT_CHECKBOX, self.setPull, self.pull1chkbx)
self.Bind(wx.EVT_CHECKBOX, self.setDerivative, self.der1chkbx)
## Choice of observable 2
- self.hbox.Add(wx.StaticText(self.panel, -1, "Obs 2:"), pos=(0,5))
+ self.hbox.Add(wx.StaticText(self.panel, -1, "Obs 2:"), pos=(0,6))
self.obschoice2 = wx.Choice(self.panel, -1, (85, 18), choices=sorted(observables))
self.obschoice2.SetSelection(sorted(observables).index(self.drawobs["right"]))
- self.hbox.Add(self.obschoice2, pos=(0,6))
+ self.hbox.Add(self.obschoice2, pos=(0,7))
self.logy2chkbx = wx.CheckBox(self.panel, -1, "logy")
- self.hbox.Add(self.logy2chkbx, pos=(0,7))
+ self.logx2chkbx = wx.CheckBox(self.panel, -1, "logx")
+ self.hbox.Add(self.logy2chkbx, pos=(0,8))
+ self.hbox.Add(self.logx2chkbx, pos=(0,9))
self.Bind(wx.EVT_CHOICE, functools.partial(self.updateObs, which="right"), self.obschoice2)
self.Bind(wx.EVT_CHECKBOX, self.setLogy, self.logy2chkbx)
+ self.Bind(wx.EVT_CHECKBOX, self.setLogx, self.logx2chkbx)
self.pull2chkbx = wx.CheckBox(self.panel, -1, "pull")
- self.hbox.Add(self.pull2chkbx, pos=(0,8))
+ self.hbox.Add(self.pull2chkbx, pos=(0,10))
self.der2chkbx = wx.CheckBox(self.panel, -1, "derivative")
- self.hbox.Add(self.der2chkbx, pos=(0,9))
+ self.hbox.Add(self.der2chkbx, pos=(0,11))
self.Bind(wx.EVT_CHOICE, functools.partial(self.updateObs, which="right"), self.obschoice2)
self.Bind(wx.EVT_CHECKBOX, self.setPull, self.pull2chkbx)
self.Bind(wx.EVT_CHECKBOX, self.setDerivative, self.der2chkbx)
self.hbox.Fit(self)
self.vbox.Add(self.hbox)
- self.vbox.AddSpacer((10,10))
+ #self.vbox.AddSpacer((10,10))
+ self.vbox.AddSpacer(10)
self.hbox1 = wx.BoxSizer(wx.HORIZONTAL)
## vbox for x/y limits
self.limitgrid = wx.GridBagSizer(hgap=5, vgap=2)
# Buttons to reset
self.limitgrid.Add(wx.StaticText(self.panel, -1, "Limits 1:"), pos=(0,0))
self.resetBtn = wx.Button(self.panel, label="Reset")
self.Bind(wx.EVT_BUTTON, functools.partial(self.resetLimits, which="left"), self.resetBtn)
self.limitgrid.Add(self.resetBtn, pos=(0,1))
self.resetBtn2 = wx.Button(self.panel, label="Reset")
self.Bind(wx.EVT_BUTTON, functools.partial(self.resetLimits, which="right"), self.resetBtn2)
self.limitgrid.Add(self.resetBtn2, pos=(0,4))
# Input fields
limittypes = ("XMin", "XMax", "YMin", "YMax")
self.limits["left"] = {}
for num, i in enumerate(limittypes):
self.limitgrid.Add(wx.StaticText(self.panel, -1, i), pos=(num+1, 0))
textctrl = wx.TextCtrl(self.panel, -1, "None")
self.limitgrid.Add(textctrl, pos=(num+1,1))
self.limits["left"][i] = textctrl
self.limitgrid.Add(wx.StaticText(self.panel, -1, "Limits 2:"), pos=(0,3))
self.limits["right"] = {}
for num, i in enumerate(limittypes):
self.limitgrid.Add(wx.StaticText(self.panel, -1, i), pos=(num+1, 3))
textctrl = wx.TextCtrl(self.panel, -1, "None", style=wx.TE_PROCESS_ENTER)
self.limitgrid.Add(textctrl, pos=(num+1,4))
self.limits["right"][i] = textctrl
self.hbox1.Add(self.limitgrid)
# Bind text fields to sliderUpdate
for textctrl in self.limits["left"].values():
self.Bind(wx.EVT_TEXT,
self.sliderUpdate, textctrl)
for textctrl in self.limits["right"].values():
self.Bind(wx.EVT_TEXT,
self.sliderUpdate, textctrl)
## Add to the main vertical box
self.vbox.Add(self.hbox1)
self.panel.SetSizer(self.vbox)
self.vbox.Fit(self)
## Maximize the window
self.Maximize()
def setLogy(self, event):
""" See if the checkboxes are checked and set logy-scales accordingly """
for i in [(self.logy1chkbx, "left", self.axes), (self.logy2chkbx, "right", self.axes2)]:
if i[0].IsChecked():
#self.logy[i[1]]=True
i[2].set_yscale('log')
else:
#self.logy[i[1]]=False
i[2].set_yscale('linear')
self.sliderUpdate(None)
+ def setLogx(self, event):
+ """ See if the checkboxes are checked and set logx-scales accordingly """
+ for i in [(self.logx1chkbx, "left", self.axes), (self.logx2chkbx, "right", self.axes2)]:
+ if i[0].IsChecked():
+ #self.logx[i[1]]=True
+ i[2].set_xscale('log')
+ else:
+ #self.logx[i[1]]=False
+ i[2].set_xscale('linear')
+ self.sliderUpdate(None)
+
def setPull(self, event):
""" See if the checkboxes are checked and switch to pull mode """
for i in [(self.pull1chkbx, "left", self.axes), (self.pull2chkbx, "right", self.axes2)]:
if i[0].IsChecked():
self.pull[i[1]]=True
else:
self.pull[i[1]]=False
self.sliderUpdate(None)
def setDerivative(self, event):
""" See if the checkboxes are checked and switch to pull mode """
for i in [(self.der1chkbx, "left", self.axes), (self.der2chkbx, "right", self.axes2)]:
if i[0].IsChecked():
self.derivative[i[1]]=True
else:
self.derivative[i[1]]=False
self.sliderUpdate(None)
def sliderUpdate(self, event, redraw=True):
ppoint = self.getCurrentParamValues()
self.plotHistos(ppoint, redraw=redraw)
## Set plot limits
self.setLimits(self.axes, self.getLimits(self.limits["left"]))
self.setLimits(self.axes2, self.getLimits(self.limits["right"]))
self.canvas.draw()
def getCurrentParamValues(self):
return [self.child.sliders[k].GetValue() for k in self.child.params]
def resetLimits(self, event, which):
for i in "XMin XMax YMin YMax".split():
self.limits[which][i].SetValue("None")
self.updateObs(None, which)
def getLimits(self, limdict):
xmin = self.convertInput(limdict["XMin"].GetValue())
xmax = self.convertInput(limdict["XMax"].GetValue())
ymin = self.convertInput(limdict["YMin"].GetValue())
ymax = self.convertInput(limdict["YMax"].GetValue())
return xmin, xmax, ymin, ymax
def setLimits(self, sub, thelimits):
xmin, xmax, ymin, ymax = thelimits
sub.set_xlim(xmin, xmax)
sub.set_ylim(ymin, ymax)
def convertInput(self, inp):
try:
return float(inp)
except:
return None
def updateObs(self, event=None, which=None):
"""Update the observable assigned the L or R window.
"""
self.axes.clear()
self.axes2.clear()
if which in ("left", None):
self.drawobs["left"] = observables[self.obschoice1.GetSelection()]
if which in ("right", None):
self.drawobs["right"] = observables[self.obschoice2.GetSelection()]
## Set titles and axis labels, using the rivet plot file parser if possible
obs1 = self.drawobs["left"]
obs2 = self.drawobs["right"]
self.axes.set_title(obs1)
self.axes2.set_title(obs2)
if not self.pull['left']:
self.plotDataHisto(self.axes, 'left')
if not self.pull['right']:
self.plotDataHisto(self.axes2, 'right')
#
self.sliderUpdate(None, redraw=False)
def plotDataHisto(self, sub, which):
x,y,ye = mk_data(self.drawobs[which])
if len(x)>0:
self.refhistos[which] = sub.errorbar(x,y, yerr=ye, ls=" ", marker="o", color="k", label="Data")
def plotHistos(self, ppoint, redraw=False):
""" This plots the observable prediction calculated from the
parameterisation.
"""
for i in (['left', self.axes, self.drawobs["left"]],
['right',self.axes2, self.drawobs["right"]]):
# Get the coordinates for the ipol histos step draw
if self.pull[i[0]]:
X, Y = mk_pull(i[2], ppoint)#, self.logy[i[0]])
else:
X, Y = mk_line(i[2], ppoint, self.derivative[i[0]])#, self.logy[i[0]])
if redraw is False:
self.histos[i[0]] = i[1].step(X, Y, color="r", where="post")
else:
self.histos[i[0]][0].set_xdata(X)
self.histos[i[0]][0].set_ydata(Y)
## Workaround for changes in matplotlib 0.99
try:
i[1].redraw_in_frame()
except:
pass
## Run GUI application
app = wx.App()
ProfIFrame().Show()
app.MainLoop()

File Metadata

Mime Type
text/x-diff
Expires
Wed, May 14, 10:24 AM (1 d, 14 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5111114
Default Alt Text
(37 KB)

Event Timeline