/[thuban]/branches/WIP-pyshapelib-bramz/Thuban/Model/classgen.py
ViewVC logotype

Diff of /branches/WIP-pyshapelib-bramz/Thuban/Model/classgen.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 900 by jonathan, Wed May 14 11:15:41 2003 UTC revision 1425 by jonathan, Wed Jul 16 13:21:59 2003 UTC
# Line 5  Line 5 
5  # This program is free software under the GPL (>=v2)  # This program is free software under the GPL (>=v2)
6  # Read the file COPYING coming with Thuban for details.  # Read the file COPYING coming with Thuban for details.
7    
8    """
9    Functions to generate Classifications
10    """
11    
12    __version__ = "$Revision$"
13    # $Source$
14    # $Id$
15    
16  import operator  import operator
17    
18  from color import Color  from color import Color, Transparent
19  from range import Range  from range import Range
20  from classification import Classification, ClassGroupSingleton, \  from classification import Classification, ClassGroupSingleton, \
21      ClassGroupRange, ClassGroupProperties      ClassGroupRange, ClassGroupProperties
22    
23  class ClassGenerator:  def generate_singletons(_list, ramp):
24        """Generate a new classification consisting solely of singletons.
     def GenSingletonsFromList(self, _list, numGroups, ramp):  
         """Generate a new classification consisting solely of singletons.  
   
         The resulting classification will consist of at most 'numGroups'  
         groups whose group properties ramp between 'prop1' and 'prop2'. There  
         could be fewer groups if '_list' contains fewer that 'numGroups' items.  
   
         _list -- any object that implements the iterator interface  
   
         numGroups -- how many groups to generate. This can not be  
                      determined while the classification is being  
                      generated because the stepping values must  
                      be precalculated to ramp between prop1 and prop2.  
   
         ramp -- an object which implements the CustomRamp interface  
         """  
25    
26          clazz = Classification()      The resulting classification will consist of one group for each
27          if numGroups == 0: return clazz      item in _list whose properties ramp between 'prop1' and 'prop2'.
28    
29          ramp.SetNumGroups(numGroups)      _list -- a list of values for each singleton
30    
31          for value, prop in zip(_list, ramp):      ramp -- an object which implements the CustomRamp interface
32              clazz.AppendGroup(ClassGroupSingleton(value, prop))      """
33    
34          return clazz      clazz = Classification()
35    
36      def GenSingletons(self, min, max, numGroups, ramp):      i = 0
37        maxValue = float(len(_list) - 1)
38        if maxValue < 1: maxValue = 1
39    
40          clazz = Classification()      for value in _list:
41            prop = ramp.GetProperties(i / maxValue)
42            clazz.AppendGroup(ClassGroupSingleton(value, prop))
43            i += 1
44    
45          #step = int((max - min) / float(numGroups))      return clazz
46    
47          if numGroups > 0:  def generate_uniform_distribution(min, max, numGroups, ramp, intStep = False):
48        """Generate a classification with numGroups range groups
49        each with the same interval.
50    
51              step = int((max - min + 1) / float(numGroups))      intStep -- force the calculated stepping to an integer.
52              cur_value = min                 Useful if the values are integers but the
53                   number of groups specified doesn't evenly
54                   divide (max - min).
55        """
56    
57              ramp.SetNumGroups(numGroups)      clazz = Classification()
58    
59              for prop in ramp:      cur_min = min
                 clazz.AppendGroup(ClassGroupSingleton(cur_value), prop)  
                 cur_value += step  
   
         return clazz  
   
     def GenUniformDistribution(self, min, max, numGroups,  
                                ramp, intStep = False):  
         """Generate a classification with numGroups range groups  
         each with the same interval.  
   
         intStep -- force the calculated stepping to an integer.  
                    Useful if the values are integers but the  
                    number of groups specified doesn't evenly  
                    divide (max - min).  
         """  
60    
61          clazz = Classification()      end = "["
62          if numGroups == 0: return clazz      maxValue = float(numGroups - 1)
63        if maxValue < 1: maxValue = 1
64    
65          ramp.SetNumGroups(numGroups)      for i in range(1, numGroups + 1):
66    
67          step = (max - min) / float(numGroups)          prop = ramp.GetProperties(float(i-1) / maxValue)
68    
69          if intStep:          if intStep:
70              step = int(step)              cur_max = min + int(round((i * (max - min + 1)) / float(numGroups)))
71            else:
72                cur_max = min + (i * (max - min)) / float(numGroups)
73    
74          cur_min = min          if i == numGroups:
75          cur_max = cur_min + step              cur_max = max
76                end = "]"
77    
78          i = 0          if cur_min == cur_max:
79          end = "["              _range = Range(("[", cur_min, cur_max, "]"))
80          for prop in ramp:          else:
81                _range = Range(("[", cur_min, cur_max, end))
82    
83              if i == (numGroups - 1):          clazz.AppendGroup(ClassGroupRange(_range, prop))
                 cur_max = max  
                 end = "]"  
84    
85            cur_min = cur_max
86    
87              # this check guards against rounding issues      return clazz
             if cur_min != cur_max:  
                 range = Range("[" + str(float(cur_min)) + ";" +  
                                     str(float(cur_max)) + end)  
                 clazz.AppendGroup(ClassGroupRange(range, None, prop))  
88    
89              cur_min = cur_max  def generate_quantiles(_list, percents, ramp, _range):
90              cur_max += step      """Generates a Classification which has groups of ranges that
91              i += 1      represent quantiles of _list at the percentages given in percents.
92        Only the values that fall within _range are considered.
93    
94          return clazz      Returns a tuple (adjusted, Classification) where adjusted is
95        True if the Classification does not exactly represent the given
96        range, or if the Classification is empty.
97    
98        _list -- a sort list of values
99    
100      def GenQuantiles(self, _list, percents, ramp, _range):      percents -- a sorted list of floats in the range 0.0-1.0 which
101          """Generates a Classification which has groups of ranges that                  represent the upper bound of each quantile. the
102          represent quantiles of _list at the percentages given in percents.                  union of all percentiles should be the entire
103          Only the values that fall within _range are considered.                  range from 0.0-1.0
104    
105          Returns a tuple (adjusted, Classification) where adjusted is      ramp -- an object which implements the CustomRamp interface
         True if the Classification does not exactly represent the given  
         range, or if the Classification is empty.  
106    
107          _list -- a sort list of values      _range -- a Range object
108    
109          percents -- a sorted list of floats in the range 0.0-1.0 which      Raises a Value Error if 'percents' has fewer than two items, or
110                      represent the upper bound of each quantile      does not cover the entire range.
111        """
112    
113          ramp -- an object which implements the CustomRamp interface      clazz = Classification()
114        quantiles = calculate_quantiles(_list, percents, _range)
115        adjusted = True
116    
117          _range -- a Range object      if quantiles is not None:
         """  
118    
119          clazz = Classification()          numGroups = len(quantiles[3])
         quantiles = self.CalculateQuantiles(_list, percents, _range)  
         adjusted = True  
120    
121          if quantiles is not None:          if numGroups != 0:
122    
123              numGroups = len(quantiles[3])              adjusted = quantiles[0]
124    
125              if numGroups != 0:              start, min, endMax, right = _range.GetRange()
126    
127                  adjusted = quantiles[0]              oldp = 0
128                i = 1
129                end = "]"
130    
131                  ramp.SetNumGroups(numGroups)              maxValue = float(numGroups - 1)
132                if maxValue < 1: maxValue = 1
133                for (q, p) in quantiles[3]:
134    
135                  start, min, endMax, right = _range.GetRange()                  prop = ramp.GetProperties(float(i-1) / maxValue)
136    
137                  if str(min) == '-inf':                  if i == numGroups:
138                      min = "-oo"                      max = endMax
139                  elif str(min) == 'inf':                      end = right
140                      min = "oo"                  else:
141                        max = _list[q]
142    
143                  if str(endMax) == '-inf':                  group = ClassGroupRange(Range((start, min, max, end)), prop)
144                      endMax = "-oo"      
145                  elif str(endMax) == 'inf':                  group.SetLabel("%s%% - %s%%" % (round(oldp*100, 2),
146                      endMax = "oo"                                                  round(p*100, 2)))
147                    oldp = p
148                    start = "]"
149                    min = max
150                    clazz.AppendGroup(group)
151                    i += 1
152    
153                  oldp = 0      return (adjusted, clazz)
                 i = 1  
                 end = "]"  
154    
155                  for (q, p), prop in zip(quantiles[3], ramp):  def GenQuantiles0(_list, percents, ramp, _range):
156                      if i == numGroups:      """Same as GenQuantiles, but the first class won't be added to
157                          max = endMax      the classification.
                         end = right  
                     else:  
                         max = _list[q]  
158    
159                      group = ClassGroupRange(Range(start + str(min) + ";" +      Returns a tuple (adjusted, Classification, upper_class0) where
160                                                            str(max) + end),      upper_class0 is the highest value inside the first class.
                                             None, prop)  
           
                     group.SetLabel("%s%% - %s%%" % (round(oldp*100, 2),  
                                                     round(p*100, 2)))  
                     oldp = p  
                     start = "]"  
                     min = max  
                     clazz.AppendGroup(group)  
                     i += 1  
   
         return (adjusted, clazz)  
   
     def CalculateQuantiles(self, _list, percents, _range):  
         """Calculate quantiles for the given _list of percents from the  
         sorted list of values that are in range.  
                                                                                   
         This may not actually generate len(percents) quantiles if  
         many of the values that fall on quantile borders are the same.  
   
         Returns a tuple of the form:  
             (adjusted, minIndex, maxIndex, [quantile_list])  
   
         where adjusted is True if the the quantile percentages differ from  
         those supplied, minIndex is the index into _list where the  
         minimum value used is located, maxIndex is the index into _list  
         where the maximum value used is located, and quantile_list is a  
         list of tuples of the form: (list_index, quantile_percentage)  
   
         Returns None, if no quantiles could be generated based on the  
         given range or input list.  
161    
162          _list -- a sort list of values      _list -- a sort list of values
163    
164          percents -- a sorted list of floats in the range 0.0-1.0 which      percents -- a sorted list of floats in the range 0.0-1.0 which
165                      represent the upper bound of each quantile                  represent the upper bound of each quantile. the
166                    union of all percentiles should be the entire
167                    range from 0.0-1.0
168    
169          _range -- a Range object      ramp -- an object which implements the CustomRamp interface
         """  
       
         quantiles = []  
         adjusted = False  
170    
171          if len(percents) != 0:      _range -- a Range object
                                                                                 
             #  
             # find what part of the _list range covers  
             #  
             minIndex = -1  
             maxIndex = -2  
             for i in xrange(0, len(_list), 1):  
                 if operator.contains(_range, _list[i]):  
                     minIndex = i  
                     break  
   
             for i in xrange(len(_list)-1, -1, -1):  
                 if operator.contains(_range, _list[i]):  
                     maxIndex = i  
                     break  
   
             numValues = maxIndex - minIndex + 1  
   
             if numValues > 0:  
   
                 #  
                 # build a list of unique indices into list of where each  
                 # quantile *should* be. set adjusted if the resulting  
                 # indices are different  
                 #  
                 quantiles = {}  
                 for p in percents:  
                     index = min(minIndex + int(p*numValues)-1, maxIndex)  
   
                     adjusted = adjusted \  
                         or quantiles.has_key(index) \  
                         or ((index - minIndex + 1) / float(numValues)) != p  
   
                     quantiles[index] = 0  
   
                 quantiles = quantiles.keys()  
                 quantiles.sort()  
   
                 #  
                 # the current quantile index must be strictly greater than  
                 # the lowerBound  
                 #  
                 lowerBound = minIndex - 1  
       
                 for qindex in xrange(len(quantiles)):  
                     if lowerBound >= maxIndex:  
                         # discard higher quantiles  
                         quantiles = quantiles[:qindex]  
                         break  
       
                     # lowerBound + 1 is always a valid index  
       
                     #  
                     # bump up the current quantile index to be a usable index  
                     # if it currently falls below the lowerBound  
                     #  
                     if quantiles[qindex] <= lowerBound:  
                         quantiles[qindex] = lowerBound + 1  
           
                     listIndex = quantiles[qindex]  
                     value = _list[listIndex]  
       
                     #  
                     # look for similar values around the quantile index  
                     #  
                     lindex = listIndex - 1  
                     while lindex > lowerBound and value == _list[lindex]:  
                         lindex -= 1  
                     lcount = (listIndex - 1) - lindex  
       
                     rindex = listIndex + 1  
                     while rindex < maxIndex + 1 and value == _list[rindex]:  
                         rindex += 1  
                     rcount = (listIndex + 1) - rindex  
       
                     #  
                     # adjust the current quantile index based on how many  
                     # numbers in the _list are the same as the current value  
                     #  
                     newIndex = listIndex  
                     if lcount == rcount:  
                         if lcount != 0:  
                             #  
                             # there are an equal number of numbers to the left  
                             # and right, try going to the left first unless  
                             # doing so creates an empty quantile.  
                             #  
                             if lindex != lowerBound:  
                                 newIndex = lindex  
                             else:  
                                 newIndex = rindex - 1  
       
                     elif lcount < rcount:  
                         # there are fewer items to the left, so  
                         # try going to the left first unless  
                         # doing so creates an empty quantile.  
                         if lindex != lowerBound:  
                             newIndex = lindex  
                         else:  
                             newIndex = rindex - 1  
       
                     elif rcount < lcount:  
                         # there are fewer items to the right, so go to the right  
                         newIndex = rindex - 1  
       
                     adjusted = adjusted or newIndex != listIndex  
172    
173                      quantiles[qindex] = newIndex      Raises a Value Error if 'percents' has fewer than two items, or
174                      lowerBound = quantiles[qindex]      does not cover the entire range.
175            """
         #  
         # since quantiles is only set if the code is at least a little  
         # successful, an empty list will be generated in the case that  
         # we fail to get to the real body of the algorithm  
         #  
         if len(quantiles) == 0:  
             return None  
         else:  
             return (adjusted, minIndex, maxIndex,  
                     [(q, (q - minIndex+1) / float(numValues)) \  
                      for q in quantiles])  
176    
177  CLR  = 0      clazz = Classification()
178  STEP = 1      quantiles = calculate_quantiles(_list, percents, _range)
179  class CustomRamp:      adjusted = True
180    
181      def __init__(self, prop1, prop2):      if quantiles is not None:
         self.prop1 = prop1  
         self.prop2 = prop2  
182    
183          self.count = 0          numGroups = len(quantiles[3]) - 1
184    
185      def __iter__(self):          if numGroups > 0:
186          return self              adjusted = quantiles[0]
   
     def GetRamp(self):  
         return self  
187    
188      def SetNumGroups(self, num):              start, min, endMax, right = _range.GetRange()
189    
190          if num <= 0:              class0 = quantiles[3][0]
191              return False              min = _list[class0[0]]
192                oldp = class0[1]
193                i = 1
194                end = "]"
195    
196                maxValue = float(numGroups - 1)
197                if maxValue < 1: maxValue = 1
198                for (q, p) in quantiles[3][1:]:
199                    prop = ramp.GetProperties(float(i-1) / maxValue)
200    
201                    if i == numGroups:
202                        max = endMax
203                        end = right
204                    else:
205                        max = _list[q]
206    
207                    group = ClassGroupRange(Range((start, min, max, end)), prop)
208        
209                    group.SetLabel("%s%% - %s%%" % (round(oldp*100, 2),
210                                                    round(p*100, 2)))
211                    oldp = p
212                    start = "]"
213                    min = max
214                    clazz.AppendGroup(group)
215                    i += 1
216    
217        return (adjusted, clazz, _list[class0[0]])
218    
219    
220    def calculate_quantiles(_list, percents, _range):
221        """Calculate quantiles for the given _list of percents from the
222        sorted list of values that are in range.
223                                                                                
224        This may not actually generate len(percents) quantiles if
225        many of the values that fall on quantile borders are the same.
226    
227        Returns a tuple of the form:
228            (adjusted, minIndex, maxIndex, [quantile_list])
229    
230        where adjusted is True if the the quantile percentages differ from
231        those supplied, minIndex is the index into _list where the
232        minimum value used is located, maxIndex is the index into _list
233        where the maximum value used is located, and quantile_list is a
234        list of tuples of the form: (list_index, quantile_percentage)
235    
236        Returns None, if no quantiles could be generated based on the
237        given range or input list.
238    
239        _list -- a sort list of values
240    
241        percents -- a sorted list of floats in the range 0.0-1.0 which
242                    represent the upper bound of each quantile. the
243                    union of all percentiles should be the entire
244                    range from 0.0-1.0
245    
246        _range -- a Range object
247    
248        Raises a Value Error if 'percents' has fewer than two items, or
249        does not cover the entire range.
250        """
251    
252        quantiles = []
253        adjusted = False
254    
255        if len(percents) <= 1:
256            raise ValueError("percents parameter must have more than one item")
257    
258        if percents[-1] != 1.0:
259            raise ValueError("percents does not cover the entire range")
260    
261        #
262        # find what part of the _list range covers
263        #
264        minIndex = -1
265        maxIndex = -2
266        for i in xrange(0, len(_list), 1):
267            if operator.contains(_range, _list[i]):
268                minIndex = i
269                break
270    
271        for i in xrange(len(_list)-1, -1, -1):
272            if operator.contains(_range, _list[i]):
273                maxIndex = i
274                break
275    
276          self.count = int(num)      numValues = maxIndex - minIndex + 1
         num = float(num)  
277    
278          prop1 = self.prop1      if numValues > 0:
         prop2 = self.prop2  
279    
280          clr = prop1.GetLineColor()          #
281          lineColor2 = prop2.GetLineColor()          # build a list of unique indices into list of where each
282                    # quantile *should* be. set adjusted if the resulting
283          self.noLine = clr is not Color.Transparent \          # indices are different
284                          and lineColor2 is not Color.Transparent          #
285            quantiles = {}
286            for p in percents:
287                index = min(minIndex + int(p*numValues)-1, maxIndex)
288    
289                adjusted = adjusted \
290                    or quantiles.has_key(index) \
291                    or ((index - minIndex + 1) / float(numValues)) != p
292    
293                quantiles[index] = 0
294    
295          self.lineInfo = self.__GetColorInfo(prop1.GetLineColor(),          quantiles = quantiles.keys()
296                                              prop2.GetLineColor(),          quantiles.sort()
                                             num)  
297    
298          self.fillInfo = self.__GetColorInfo(prop1.GetFill(),          #
299                                              prop2.GetFill(),          # the current quantile index must be strictly greater than
300                                              num)          # the lowerBound
301            #
302            lowerBound = minIndex - 1
303    
304          self.lineWidth = prop1.GetLineWidth()          for qindex in xrange(len(quantiles)):
305          self.lineWidthStep = (prop2.GetLineWidth() - self.lineWidth) / num              if lowerBound >= maxIndex:
306                    # discard higher quantiles
307                    quantiles = quantiles[:qindex]
308                    break
309    
310          return True              # lowerBound + 1 is always a valid index
311    
312      def next(self):              #
313          if self.count == 0:              # bump up the current quantile index to be a usable index
314              raise StopIteration              # if it currently falls below the lowerBound
315                #
316                if quantiles[qindex] <= lowerBound:
317                    quantiles[qindex] = lowerBound + 1
318    
319          prop = ClassGroupProperties()              listIndex = quantiles[qindex]
320                value = _list[listIndex]
321    
322          if self.lineInfo is None:              #
323              prop.SetLineColor(Color.Transparent)              # look for similar values around the quantile index
324          else:              #
325              prop.SetLineColor(Color(self.lineInfo[CLR][0] / 255,              lindex = listIndex - 1
326                                      self.lineInfo[CLR][1] / 255,              while lindex > lowerBound and value == _list[lindex]:
327                                      self.lineInfo[CLR][2] / 255))                  lindex -= 1
328                lcount = (listIndex - 1) - lindex
329              self.lineInfo[CLR][0] += self.lineInfo[STEP][0]  
330              self.lineInfo[CLR][1] += self.lineInfo[STEP][1]              rindex = listIndex + 1
331              self.lineInfo[CLR][2] += self.lineInfo[STEP][2]              while rindex < maxIndex + 1 and value == _list[rindex]:
332                    rindex += 1
333                rcount = (listIndex + 1) - rindex
334    
335          if self.fillInfo is None:              #
336              prop.SetFill(Color.Transparent)              # adjust the current quantile index based on how many
337          else:              # numbers in the _list are the same as the current value
338              prop.SetFill(Color(self.fillInfo[CLR][0] / 255,              #
339                              self.fillInfo[CLR][1] / 255,              newIndex = listIndex
340                              self.fillInfo[CLR][2] / 255))              if lcount == rcount:
341                    if lcount != 0:
342                        #
343                        # there are an equal number of numbers to the left
344                        # and right, try going to the left first unless
345                        # doing so creates an empty quantile.
346                        #
347                        if lindex != lowerBound:
348                            newIndex = lindex
349                        else:
350                            newIndex = rindex - 1
351    
352              self.fillInfo[CLR][0] += self.fillInfo[STEP][0]              elif lcount < rcount:
353              self.fillInfo[CLR][1] += self.fillInfo[STEP][1]                  # there are fewer items to the left, so
354              self.fillInfo[CLR][2] += self.fillInfo[STEP][2]                  # try going to the left first unless
355                    # doing so creates an empty quantile.
356                    if lindex != lowerBound:
357                        newIndex = lindex
358                    else:
359                        newIndex = rindex - 1
360    
361                elif rcount < lcount:
362                    # there are fewer items to the right, so go to the right
363                    newIndex = rindex - 1
364    
365                adjusted = adjusted or newIndex != listIndex
366    
367                quantiles[qindex] = newIndex
368                lowerBound = quantiles[qindex]
369    
370        if len(quantiles) == 0:
371            return None
372        else:
373            return (adjusted, minIndex, maxIndex,
374                    [(q, (q - minIndex+1) / float(numValues)) \
375                     for q in quantiles])
376    
377    class CustomRamp:
378    
379          prop.SetLineWidth(int(self.lineWidth))      def __init__(self, prop1, prop2):
380          self.lineWidth        += self.lineWidthStep          self.prop1 = prop1
381            self.prop2 = prop2
382    
383          self.count -= 1      def GetRamp(self):
384            return self
385    
386          return prop      def GetProperties(self, index):
387            """Return a ClassGroupProperties object whose properties
388            represent a point at 'index' between prop1 and prop2 in
389            the constructor.
390    
391      def __GetColorInfo(self, color1, color2, numGroups):          index -- a value such that 0 <= index <= 1
392            """
393    
394          if color1 is Color.Transparent and color2 is Color.Transparent:          if not (0 <= index <= 1):
395              #              raise ValueError(_("invalid index"))
             # returning early  
             #  
             return None  
         elif color1 is not Color.Transparent and color2 is Color.Transparent:  
             color = [color1.red   * 255,  
                      color1.green * 255,  
                      color1.blue  * 255]  
             step = (0, 0, 0)  
         elif color1 is Color.Transparent and color2 is not Color.Transparent:  
             color = [color2.red   * 255,  
                      color2.green * 255,  
                      color2.blue  * 255]  
             step = (0, 0, 0)  
         else:  
             color = [color1.red   * 255,  
                      color1.green * 255,  
                      color1.blue  * 255]  
             step = ((color2.red   * 255 - color1.red   * 255)   / numGroups,  
                     (color2.green * 255 - color1.green * 255) / numGroups,  
                     (color2.blue  * 255 - color1.blue  * 255)  / numGroups)  
396    
397            newProps = ClassGroupProperties()
398    
399          return (color, step)          self.__SetProperty(self.prop1.GetLineColor(),
400                               self.prop2.GetLineColor(),
401                               index, newProps.SetLineColor)
402            self.__SetProperty(self.prop1.GetFill(), self.prop2.GetFill(),
403                               index, newProps.SetFill)
404    
405            w = (self.prop2.GetLineWidth() - self.prop1.GetLineWidth()) \
406                * index \
407                + self.prop1.GetLineWidth()
408            newProps.SetLineWidth(int(round(w)))
409    
410            return newProps
411    
412        def __SetProperty(self, color1, color2, index, setf):
413    
414            if color1 is Transparent and color2 is Transparent:
415                setf(Transparent)
416            elif color1 is Transparent:
417                setf(Color(
418                     color2.red   * index,
419                     color2.green * index,
420                     color2.blue  * index))
421            elif color2 is Transparent:
422                setf(Color(
423                     color1.red   * index,
424                     color1.green * index,
425                     color1.blue  * index))
426            else:
427                setf(Color(
428                    (color2.red   - color1.red)   * index + color1.red,
429                    (color2.green - color1.green) * index + color1.green,
430                    (color2.blue  - color1.blue)  * index + color1.blue))
431    
432  class MonochromaticRamp(CustomRamp):  class MonochromaticRamp(CustomRamp):
433      def __init__(self, start, end):      def __init__(self, start, end):
# Line 452  class MonochromaticRamp(CustomRamp): Line 441  class MonochromaticRamp(CustomRamp):
441    
442          CustomRamp.__init__(self, sp, ep)          CustomRamp.__init__(self, sp, ep)
443    
444  class GreyRamp(MonochromaticRamp):  GreyRamp       = MonochromaticRamp(Color(1, 1, 1),  Color(0, 0, 0))
445      def __init__(self):  RedRamp        = MonochromaticRamp(Color(1, 1, 1),  Color(.8, 0, 0))
446          MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, 0, 0))  GreenRamp      = MonochromaticRamp(Color(1, 1, 1),  Color(0, .8, 0))
447    BlueRamp       = MonochromaticRamp(Color(1, 1, 1),  Color(0, 0, .8))
448  class RedRamp(MonochromaticRamp):  GreenToRedRamp = MonochromaticRamp(Color(0, .8, 0), Color(1, 0, 0))
     def __init__(self):  
         MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(.8, 0, 0))  
   
 class GreenRamp(MonochromaticRamp):  
     def __init__(self):  
         MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, .8, 0))  
   
 class BlueRamp(MonochromaticRamp):  
     def __init__(self):  
         MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, 0, .8))  
   
 class GreenToRedRamp(MonochromaticRamp):  
     def __init__(self):  
         MonochromaticRamp.__init__(self, Color(0, .8, 0), Color(1, 0, 0))  
449    
450  class HotToColdRamp:  class HotToColdRamp:
451    
     def __iter__(self):  
         return self  
           
452      def GetRamp(self):      def GetRamp(self):
453          return self          return self
454    
455      def SetNumGroups(self, num):      def GetProperties(self, index):
456          if num < 0:          """Return a ClassGroupProperties object whose properties
457              return False          represent a point at 'index' between "hot" and "cold".
458    
459          self.num = float(num)          index -- a value such that 0 <= index <= 1
460          self.index = 0          """
   
         return True  
   
     def next(self):  
         if self.index == self.num:  
             raise StopIteration  
461    
462          clr = [1.0, 1.0, 1.0]          clr = [1.0, 1.0, 1.0]
463    
464          if self.index < (.25 * self.num):          if index < .25:
465              clr[0] = 0              clr[0] = 0
466              clr[1] = 4 * self.index / self.num              clr[1] = 4 * index
467          elif self.index < (.5 * self.num):          elif index < .5:
468              clr[0] = 0              clr[0] = 0
469              clr[2] = 1 + 4 * (.25 * self.num - self.index) / self.num              clr[2] = 1 + 4 * (.25 - index)
470          elif self.index < (.75 * self.num):          elif index < .75:
471              clr[0] = 4 * (self.index - .5 * self.num) / self.num              clr[0] = 4 * (index - .5)
472              clr[2] = 0              clr[2] = 0
473          else:          else:
474              clr[1] = 1 + 4 * (.75 * self.num - self.index) / self.num              clr[1] = 1 + 4 * (.75 - index)
475              clr[2] = 0              clr[2] = 0
476    
         self.index += 1  
   
477          prop = ClassGroupProperties()          prop = ClassGroupProperties()
478          prop.SetLineColor(Color(clr[0], clr[1], clr[2]))          prop.SetLineColor(Color(clr[0], clr[1], clr[2]))
479          prop.SetFill(Color(clr[0], clr[1], clr[2]))          prop.SetFill(Color(clr[0], clr[1], clr[2]))
480    
481          return prop          return prop
482    
483  #class Colors16Ramp:  class FixedRamp:
484  #      """FixedRamp allows particular properties of a ramp to be
485      #def __iter__(self):      held constant over the ramp.
486          #return self      """
487  #  
488      #def GetRamp(self):      def __init__(self, ramp, fixes):
489          #return self          """
490  #          ramp -- a source ramp to get the default properties
491      #def SetNumGroups(self, num):  
492          #if num < 0:          fixes -- a tuple (lineColor, lineWidth, fillColor) such that
493              #return False               if any item is not None, the appropriate property will
494  #               be fixed to that item value.
495          #self.index = 0          """
496  #  
497          #return True          self.fixes = fixes
498            self.ramp = ramp
499    
500        def GetRamp(self):
501            return self
502    
503        def GetProperties(self, index):
504            props = self.ramp.GetProperties(index)
505            if self.fixes[0] is not None: props.SetLineColor(self.fixes[0])
506            if self.fixes[1] is not None: props.SetLineWidth(self.fixes[1])
507            if self.fixes[2] is not None: props.SetFill(self.fixes[2])
508    
509            return props

Legend:
Removed from v.900  
changed lines
  Added in v.1425

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26