OpenMPCD
PlotTools.py
1 import matplotlib.pyplot as plt
2 import matplotlib.widgets
3 import numpy
4 
5 def findRangesOfEqualSign(data):
6  if len(data) == 0:
7  return []
8 
9  sign = None
10  lastPos = None
11  ranges = []
12  for index, value in enumerate(data):
13  pos = value >= 0
14  if sign is None:
15  sign = pos
16  lastPos = 0
17  continue
18 
19  if pos != sign:
20  range_ = [lastPos, index]
21  ranges.append((range_, sign))
22 
23  lastPos = index
24  sign = not sign
25 
26  range_ = [lastPos, len(data)]
27  ranges.append((range_, sign))
28 
29  return ranges
30 
31 def plotDashedIfNegative(x, y, yErrors=None, logY=False, defaultLowerErrorBound=1e-30, ** kwargs):
32  ax = kwargs.pop('ax', plt.gca())
33  kwargs.pop('linestyle', None)
34 
35  ranges = findRangesOfEqualSign(y)
36 
37  if not ranges:
38  return ax.plot(x, y, **kwargs)
39 
40  color = None
41  lines = []
42  for range_, sign in ranges:
43  linestyle = '-' if sign else '--'
44 
45  currentX = x[range_[0]:range_[1]]
46  currentY = y[range_[0]:range_[1]]
47  if not sign:
48  currentY = -numpy.array(currentY)
49  current_line, = ax.plot(currentX, currentY, linestyle=linestyle, **kwargs)
50  lines.append(current_line)
51 
52  if color is None:
53  color = current_line.get_color()
54  kwargs['color'] = color
55  kwargs.pop('label', None)
56 
57  if yErrors is not None:
58  lowerBounds = []
59  upperBounds = []
60 
61  for key, value in enumerate(y):
62  lower = value - yErrors[key]
63  upper = value + yErrors[key]
64 
65  if value < 0:
66  lower, upper = -upper, -lower
67 
68  if logY:
69  if lower < 0:
70  lower = defaultLowerErrorBound
71 
72  if upper < 0:
73  upper = defaultLowerErrorBound
74 
75  lowerBounds.append(lower)
76  upperBounds.append(upper)
77 
78  ax.fill_between(x, lowerBounds, upperBounds, alpha=0.3)
79 
80  return lines
81 
82 
83 class DiscreteSliderWidget(matplotlib.widgets.Slider):
84  """
85  A matplotlib-compatible slider widget, the values of which are discrete.
86  """
87 
88  def __init__(self, *args, **kwargs):
89  """
90  The constructor.
91 
92  The following keyword arguments are accepted for speacial treatment in
93  this class:
94  - `stepSize` specifies the step size with which the slider is allowed
95  to move. That is, values that can be taken on by the slider are
96  integer multiples of `stepSize`. This value must be of type `int` and
97  be positive. Defaults to `1`.
98 
99  @throw TypeError
100  Throws if any of the parameters described in the main body of
101  the documentation of this class is of the wrong type.
102  @throw ValueError
103  Throws if any of the parameters described in the main body of
104  the documentation of this class has an invalid value.
105 
106  @param[in] args
107  Positional arguments, which will be passed to the base class'
108  constructor.
109  @param[in] kwargs
110  Keyword arguments, which will be passed to the base class'
111  constructor, with the exception of the keyword arguments
112  described in the main body of the documentation of this
113  function.
114  """
115 
116  self._stepSize = kwargs.pop('stepSize', 1)
117  self._valinit = kwargs.get('valinit', None)
118 
119  if isinstance(self._valinit, (int, float)) and self._valinit == 0:
120  #workaround for broken rendering of slider
121  kwargs['valinit'] = 1e-10
122 
123  if not isinstance(self._stepSize, int):
124  raise TypeError()
125  if self._stepSize <= 0:
126  raise ValueError()
127 
128  matplotlib.widgets.Slider.__init__(self, *args, **kwargs)
129 
130 
131  def set_val(self, continuousValue):
132  """
133  Called when the slider moves.
134 
135  @param[in] continuousValue
136  The value the slider has been moved to, as a continuous
137  variable.
138  """
139 
140  self.val = continuousValue
141 
142  discreteValue = int(continuousValue // self._stepSize) * self._stepSize
143 
144  self.poly.xy[2][0] = discreteValue
145  self.poly.xy[3][0] = discreteValue
146 
147  self.valtext.set_text(self.valfmt % discreteValue)
148 
149  if self.drawon:
150  self.ax.figure.canvas.draw()
151 
152  if self.eventson:
153  for callback in self.observers.values():
154  callback(discreteValue)
MPCDAnalysis.PlotTools.DiscreteSliderWidget.set_val
def set_val(self, continuousValue)
Definition: PlotTools.py:141
MPCDAnalysis.PlotTools.DiscreteSliderWidget.val
val
Definition: PlotTools.py:143
MPCDAnalysis.PlotTools.DiscreteSliderWidget._stepSize
_stepSize
Definition: PlotTools.py:118
MPCDAnalysis.PlotTools.DiscreteSliderWidget._valinit
_valinit
Definition: PlotTools.py:119
MPCDAnalysis.PlotTools.DiscreteSliderWidget.__init__
def __init__(self, *args, **kwargs)
Definition: PlotTools.py:116