@@ -165,6 +165,12 @@ def __init__(self, minValue, maxValue, unitSystem=None):
165165
166166 @staticmethod
167167 def checkFinite (value , name = 'value' ):
168+ """Check that value is a finite number.
169+
170+ If it is, return it. If not, raise GraphError describing the
171+ problem, using name in the error message.
172+ """
173+
168174 if math .isnan (value ):
169175 raise GraphError ('Encountered NaN %s' % (name ,))
170176 elif math .isinf (value ):
@@ -173,12 +179,31 @@ def checkFinite(value, name='value'):
173179
174180 @staticmethod
175181 def chooseDelta (x ):
182+ """Choose a reasonable axis range given that one limit is x.
183+
184+ Given that end of the axis range (i.e., minValue or maxValue) is
185+ x, choose a reasonable distance to the other limit.
186+ """
187+
176188 if abs (x ) < 1.0e-9 :
177189 return 1.0
178190 else :
179191 return 0.1 * abs (x )
180192
181193 def reconcileLimits (self ):
194+ """If self.minValue is not less than self.maxValue, fix the problem.
195+
196+ If self.minValue is not less than self.maxValue, adjust
197+ self.minValue and/or self.maxValue (depending on which was not
198+ specified explicitly by the user) to make self.minValue <
199+ self.maxValue. If the user specified both limits explicitly, then
200+ raise GraphError.
201+ """
202+
203+ if self .minValue < self .maxValue :
204+ # The limits are already OK.
205+ return
206+
182207 minFixed = (self .minValueSource in ['min' ])
183208 maxFixed = (self .maxValueSource in ['max' , 'limit' ])
184209
@@ -196,6 +221,26 @@ def reconcileLimits(self):
196221 self .maxValue = average + delta
197222
198223 def applySettings (self , axisMin = None , axisMax = None , axisLimit = None ):
224+ """Apply the specified settings to this axis.
225+
226+ Set self.minValue, self.minValueSource, self.maxValue,
227+ self.maxValueSource, and self.axisLimit reasonably based on the
228+ parameters provided.
229+
230+ Arguments:
231+
232+ axisMin -- a finite number, or None to choose a round minimum
233+ limit that includes all of the data.
234+
235+ axisMax -- a finite number, 'max' to use the maximum value
236+ contained in the data, or None to choose a round maximum limit
237+ that includes all of the data.
238+
239+ axisLimit -- a finite number to use as an upper limit on maxValue,
240+ or None to impose no upper limit.
241+
242+ """
243+
199244 if axisMin is not None and not math .isnan (axisMin ):
200245 self .minValueSource = 'min'
201246 self .minValue = self .checkFinite (axisMin , 'axis min' )
@@ -206,24 +251,32 @@ def applySettings(self, axisMin=None, axisMax=None, axisLimit=None):
206251 self .maxValueSource = 'max'
207252 self .maxValue = self .checkFinite (axisMax , 'axis max' )
208253
209- if axisLimit is not None and not math .isnan (axisLimit ):
210- if axisLimit < self .maxValue :
211- self .maxValue = self .checkFinite (axisLimit , 'axis limit' )
212- self .maxValueSource = 'limit'
213- # The limit has already been imposed, so there is no need to
214- # remember it:
215- self .axisLimit = None
216- elif not math .isinf (axisLimit ):
217- # We still need to remember axisLimit to avoid rounding top to
218- # a value larger than axisLimit:
219- self .axisLimit = axisLimit
220- else :
254+ if axisLimit is None or math .isnan (axisLimit ):
221255 self .axisLimit = None
256+ elif axisLimit < self .maxValue :
257+ self .maxValue = self .checkFinite (axisLimit , 'axis limit' )
258+ self .maxValueSource = 'limit'
259+ # The limit has already been imposed, so there is no need to
260+ # remember it:
261+ self .axisLimit = None
262+ elif math .isinf (axisLimit ):
263+ # It must be positive infinity, which is the same as no limit:
264+ self .axisLimit = None
265+ else :
266+ # We still need to remember axisLimit to avoid rounding top to
267+ # a value larger than axisLimit:
268+ self .axisLimit = axisLimit
222269
223- if not (self .minValue < self .maxValue ):
224- self .reconcileLimits ()
270+ self .reconcileLimits ()
225271
226272 def makeLabel (self , value ):
273+ """Create a label for the specified value.
274+
275+ Create a label string containing the value and its units (if any),
276+ based on the values of self.step, self.span, and self.unitSystem.
277+
278+ """
279+
227280 value , prefix = format_units (value , self .step , system = self .unitSystem )
228281 span , spanPrefix = format_units (self .span , self .step , system = self .unitSystem )
229282 if prefix :
@@ -246,11 +299,17 @@ def makeLabel(self, value):
246299
247300
248301class _LinearAxisTics (_AxisTics ):
302+ """Axis ticmarks with uniform spacing."""
303+
249304 def __init__ (self , minValue , maxValue , unitSystem = None ):
250305 _AxisTics .__init__ (self , minValue , maxValue , unitSystem = unitSystem )
251306 self .step = None
307+ self .span = None
308+ self .binary = None
252309
253310 def setStep (self , step ):
311+ """Set the size of steps between ticmarks."""
312+
254313 self .step = self .checkFinite (float (step ), 'axis step' )
255314
256315 def generateSteps (self , minStep ):
@@ -279,7 +338,7 @@ def computeSlop(self, step, divisor):
279338 """Compute the slop that would result from step and divisor.
280339
281340 Return the slop, or None if this combination can't cover the full
282- range.
341+ range. See chooseStep() for the definition of "slop".
283342
284343 """
285344
@@ -419,6 +478,8 @@ def __init__(self, minValue, maxValue, unitSystem=None, base=10.0):
419478 if base <= 1.0 :
420479 raise GraphError ('Logarithmic base must be greater than one' )
421480 self .base = self .checkFinite (base , 'log base' )
481+ self .step = None
482+ self .span = None
422483
423484 def setStep (self , step ):
424485 # step is ignored for Logarithmic tics:
@@ -1780,7 +1841,7 @@ def toSeconds(t):
17801841
17811842
17821843def safeArgs (args ):
1783- """Iterate over valid, finite values an in iterable.
1844+ """Iterate over valid, finite values in an iterable.
17841845
17851846 Skip any items that are None, NaN, or infinite.
17861847 """
@@ -1862,6 +1923,9 @@ def format_units(v, step=None, system="si"):
18621923 http://en.wikipedia.org/wiki/Binary_prefix
18631924 """
18641925
1926+ if v is None :
1927+ return v , ""
1928+
18651929 if step is None :
18661930 condition = lambda size : abs (v ) >= size
18671931 else :
@@ -1880,6 +1944,11 @@ def format_units(v, step=None, system="si"):
18801944
18811945
18821946def find_x_times (start_dt , unit , step ):
1947+ if not isinstance (start_dt , datetime ):
1948+ raise ValueError ("Invalid start_dt: %s" % start_dt )
1949+ if not isinstance (step , int ) or not step > 0 :
1950+ raise ValueError ("Invalid step value: %s" % step )
1951+
18831952 if unit == SEC :
18841953 dt = start_dt .replace (second = start_dt .second - (start_dt .second % step ))
18851954 x_delta = timedelta (seconds = step )
0 commit comments