/[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 1157 by jonathan, Thu Jun 12 12:39:54 2003 UTC revision 1525 by jonathan, Wed Jul 30 15:42:56 2003 UTC
# Line 15  __version__ = "$Revision$" Line 15  __version__ = "$Revision$"
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  def generate_singletons(_list, numGroups, ramp):  def generate_singletons(_list, ramp):
24      """Generate a new classification consisting solely of singletons.      """Generate a new classification consisting solely of singletons.
25    
26      The resulting classification will consist of at most 'numGroups'      The resulting classification will consist of one group for each
27      groups whose group properties ramp between 'prop1' and 'prop2'. There      item in _list whose properties ramp between 'prop1' and 'prop2'.
28      could be fewer groups if '_list' contains fewer that 'numGroups' items.  
29        _list -- a list of values for each singleton
     _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.  
30    
31      ramp -- an object which implements the CustomRamp interface      ramp -- an object which implements the CustomRamp interface
32      """      """
33    
34      clazz = Classification()      clazz = Classification()
     if numGroups == 0: return clazz  
35    
36      ramp.SetNumGroups(numGroups)      i = 0
37        maxValue = float(len(_list) - 1)
38        if maxValue < 1: maxValue = 1
39    
40      for value, prop in zip(_list, ramp):      for value in _list:
41            prop = ramp.GetProperties(i / maxValue)
42          clazz.AppendGroup(ClassGroupSingleton(value, prop))          clazz.AppendGroup(ClassGroupSingleton(value, prop))
43            i += 1
44    
45      return clazz      return clazz
46    
# Line 58  def generate_uniform_distribution(min, m Line 55  def generate_uniform_distribution(min, m
55      """      """
56    
57      clazz = Classification()      clazz = Classification()
     if numGroups == 0: return clazz  
   
     ramp.SetNumGroups(numGroups)  
58    
59      cur_min = min      cur_min = min
60    
     i = 1  
61      end = "["      end = "["
62      for prop in ramp:      maxValue = float(numGroups - 1)
63        if maxValue < 1: maxValue = 1
64    
65        for i in range(1, numGroups + 1):
66    
67            prop = ramp.GetProperties(float(i-1) / maxValue)
68    
69          if intStep:          if intStep:
70              cur_max = min + int(round((i * (max - min + 1)) / float(numGroups)))              cur_max = min + int(round((i * (max - min + 1)) / float(numGroups)))
# Line 78  def generate_uniform_distribution(min, m Line 76  def generate_uniform_distribution(min, m
76              end = "]"              end = "]"
77    
78          if cur_min == cur_max:          if cur_min == cur_max:
79              range = Range(("[", cur_min, cur_max, "]"))              _range = Range(("[", cur_min, cur_max, "]"))
80          else:          else:
81              range = Range(("[", cur_min, cur_max, end))              _range = Range(("[", cur_min, cur_max, end))
82    
83          clazz.AppendGroup(ClassGroupRange(range, None, prop))          clazz.AppendGroup(ClassGroupRange(_range, prop))
84    
85          cur_min = cur_max          cur_min = cur_max
         i += 1  
86    
87      return clazz      return clazz
88    
   
89  def generate_quantiles(_list, percents, ramp, _range):  def generate_quantiles(_list, percents, ramp, _range):
90      """Generates a Classification which has groups of ranges that      """Generates a Classification which has groups of ranges that
91      represent quantiles of _list at the percentages given in percents.      represent quantiles of _list at the percentages given in percents.
# Line 126  def generate_quantiles(_list, percents, Line 122  def generate_quantiles(_list, percents,
122    
123              adjusted = quantiles[0]              adjusted = quantiles[0]
124    
             ramp.SetNumGroups(numGroups)  
   
125              start, min, endMax, right = _range.GetRange()              start, min, endMax, right = _range.GetRange()
126    
127              oldp = 0              oldp = 0
128              i = 1              i = 1
129              end = "]"              end = "]"
130    
131              for (q, p), prop in zip(quantiles[3], ramp):              maxValue = float(numGroups - 1)
132                if maxValue < 1: maxValue = 1
133                for (q, p) in quantiles[3]:
134    
135                    prop = ramp.GetProperties(float(i-1) / maxValue)
136    
137                  if i == numGroups:                  if i == numGroups:
138                      max = endMax                      max = endMax
139                      end = right                      end = right
140                  else:                  else:
141                      max = _list[q]                      max = _list[q]
142    
143                  group = ClassGroupRange(Range((start, min, max, end)),                  group = ClassGroupRange(Range((start, min, max, end)), prop)
                                         None, prop)  
144            
145                  group.SetLabel("%s%% - %s%%" % (round(oldp*100, 2),                  group.SetLabel("%s%% - %s%%" % (round(oldp*100, 2),
146                                                  round(p*100, 2)))                                                  round(p*100, 2)))
# Line 187  def GenQuantiles0(_list, percents, ramp, Line 185  def GenQuantiles0(_list, percents, ramp,
185          if numGroups > 0:          if numGroups > 0:
186              adjusted = quantiles[0]              adjusted = quantiles[0]
187    
             ramp.SetNumGroups(numGroups)  
   
188              start, min, endMax, right = _range.GetRange()              start, min, endMax, right = _range.GetRange()
189    
190              class0 = quantiles[3][0]              class0 = quantiles[3][0]
# Line 197  def GenQuantiles0(_list, percents, ramp, Line 193  def GenQuantiles0(_list, percents, ramp,
193              i = 1              i = 1
194              end = "]"              end = "]"
195    
196              for (q, p), prop in zip(quantiles[3][1:], ramp):              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:                  if i == numGroups:
202                      max = endMax                      max = endMax
203                      end = right                      end = right
204                  else:                  else:
205                      max = _list[q]                      max = _list[q]
206    
207                  group = ClassGroupRange(Range((start, min, max, end)),                  group = ClassGroupRange(Range((start, min, max, end)), prop)
                                         None, prop)  
208            
209                  group.SetLabel("%s%% - %s%%" % (round(oldp*100, 2),                  group.SetLabel("%s%% - %s%%" % (round(oldp*100, 2),
210                                                  round(p*100, 2)))                                                  round(p*100, 2)))
# Line 256  def calculate_quantiles(_list, percents, Line 255  def calculate_quantiles(_list, percents,
255      if len(percents) <= 1:      if len(percents) <= 1:
256          raise ValueError("percents parameter must have more than one item")          raise ValueError("percents parameter must have more than one item")
257    
258      if percents[len(percents) - 1] != 1.0:      if percents[-1] != 1.0:
259          raise ValueError("percents does not cover the entire range")          raise ValueError("percents does not cover the entire range")
260    
261      #      #
# Line 375  def calculate_quantiles(_list, percents, Line 374  def calculate_quantiles(_list, percents,
374                  [(q, (q - minIndex+1) / float(numValues)) \                  [(q, (q - minIndex+1) / float(numValues)) \
375                   for q in quantiles])                   for q in quantiles])
376    
 CLR  = 0  
 STEP = 1  
377  class CustomRamp:  class CustomRamp:
378    
379      def __init__(self, prop1, prop2):      def __init__(self, prop1, prop2):
380            """Create a ramp between prop1 and prop2."""
381          self.prop1 = prop1          self.prop1 = prop1
382          self.prop2 = prop2          self.prop2 = prop2
383    
         self.count = 0  
   
     def __iter__(self):  
         return self  
   
384      def GetRamp(self):      def GetRamp(self):
385            """Return this ramp."""
386          return self          return self
387    
388      def SetNumGroups(self, num):      def GetProperties(self, index):
389            """Return a ClassGroupProperties object whose properties
390          if num <= 0:          represent a point at 'index' between prop1 and prop2 in
391              return False          the constructor.
392    
393          self.count = int(num)          index -- a value such that 0 <= index <= 1
394          num = float(num)          """
395    
396          prop1 = self.prop1          if not (0 <= index <= 1):
397          prop2 = self.prop2              raise ValueError(_("invalid index"))
398    
399          clr = prop1.GetLineColor()          newProps = ClassGroupProperties()
400          lineColor2 = prop2.GetLineColor()  
401                    self.__SetProperty(self.prop1.GetLineColor(),
402          self.noLine = clr is not Color.Transparent \                             self.prop2.GetLineColor(),
403                          and lineColor2 is not Color.Transparent                             index, newProps.SetLineColor)
404            self.__SetProperty(self.prop1.GetFill(), self.prop2.GetFill(),
405                               index, newProps.SetFill)
406          self.lineInfo = self.__GetColorInfo(prop1.GetLineColor(),  
407                                              prop2.GetLineColor(),          w = (self.prop2.GetLineWidth() - self.prop1.GetLineWidth()) \
408                                              num)              * index \
409                + self.prop1.GetLineWidth()
410          self.fillInfo = self.__GetColorInfo(prop1.GetFill(),          newProps.SetLineWidth(int(round(w)))
411                                              prop2.GetFill(),  
412                                              num)          return newProps
413    
414          self.lineWidth = prop1.GetLineWidth()      def __SetProperty(self, color1, color2, index, setf):
415          self.lineWidthStep = (prop2.GetLineWidth() - self.lineWidth) / num          """Use setf to set the appropriate property for the point
416            index percent between color1 and color2. setf is a function
417          return True          to call that accepts a Color object or Transparent.
418            """
419      def next(self):  
420          if self.count == 0:          if color1 is Transparent and color2 is Transparent:
421              raise StopIteration              setf(Transparent)
422            elif color1 is Transparent:
423          prop = ClassGroupProperties()              setf(Color(
424                     color2.red   * index,
425          if self.lineInfo is None:                   color2.green * index,
426              prop.SetLineColor(Color.Transparent)                   color2.blue  * index))
427            elif color2 is Transparent:
428                setf(Color(
429                     color1.red   * index,
430                     color1.green * index,
431                     color1.blue  * index))
432          else:          else:
433              prop.SetLineColor(Color(self.lineInfo[CLR][0] / 255,              setf(Color(
434                                      self.lineInfo[CLR][1] / 255,                  (color2.red   - color1.red)   * index + color1.red,
435                                      self.lineInfo[CLR][2] / 255))                  (color2.green - color1.green) * index + color1.green,
436                    (color2.blue  - color1.blue)  * index + color1.blue))
             self.lineInfo[CLR][0] += self.lineInfo[STEP][0]  
             self.lineInfo[CLR][1] += self.lineInfo[STEP][1]  
             self.lineInfo[CLR][2] += self.lineInfo[STEP][2]  
437    
438          if self.fillInfo is None:  class MonochromaticRamp(CustomRamp):
439              prop.SetFill(Color.Transparent)      """Helper class to make ramps between two colors."""
         else:  
             prop.SetFill(Color(self.fillInfo[CLR][0] / 255,  
                             self.fillInfo[CLR][1] / 255,  
                             self.fillInfo[CLR][2] / 255))  
   
             self.fillInfo[CLR][0] += self.fillInfo[STEP][0]  
             self.fillInfo[CLR][1] += self.fillInfo[STEP][1]  
             self.fillInfo[CLR][2] += self.fillInfo[STEP][2]  
   
   
         prop.SetLineWidth(int(self.lineWidth))  
         self.lineWidth        += self.lineWidthStep  
   
         self.count -= 1  
   
         return prop  
   
     def __GetColorInfo(self, color1, color2, numGroups):  
   
         if color1 is Color.Transparent and color2 is Color.Transparent:  
             #  
             # 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)  
440    
441        def __init__(self, start, end):
442            """Create a Monochromatic Ramp.
443    
444          return (color, step)          start -- starting Color
445    
446  class MonochromaticRamp(CustomRamp):          end -- ending Color
447      def __init__(self, start, end):          """
448          sp = ClassGroupProperties()          sp = ClassGroupProperties()
449          sp.SetLineColor(start)          sp.SetLineColor(start)
450          sp.SetFill(start)          sp.SetFill(start)
# Line 498  class MonochromaticRamp(CustomRamp): Line 455  class MonochromaticRamp(CustomRamp):
455    
456          CustomRamp.__init__(self, sp, ep)          CustomRamp.__init__(self, sp, ep)
457    
458  class GreyRamp(MonochromaticRamp):  grey_ramp         = MonochromaticRamp(Color(1, 1, 1),  Color(0, 0, 0))
459      def __init__(self):  red_ramp          = MonochromaticRamp(Color(1, 1, 1),  Color(.8, 0, 0))
460          MonochromaticRamp.__init__(self, Color(1, 1, 1), Color(0, 0, 0))  green_ramp        = MonochromaticRamp(Color(1, 1, 1),  Color(0, .8, 0))
461    blue_ramp         = MonochromaticRamp(Color(1, 1, 1),  Color(0, 0, .8))
462  class RedRamp(MonochromaticRamp):  green_to_red_ramp = 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))  
463    
464  class HotToColdRamp:  class HotToColdRamp:
465        """A ramp that generates properties with colors ranging from
466        'hot' colors (e.g. red, orange) to 'cold' colors (e.g. green, blue)
467        """
468    
     def __iter__(self):  
         return self  
           
469      def GetRamp(self):      def GetRamp(self):
470            """Return this ramp."""
471          return self          return self
472    
473      def SetNumGroups(self, num):      def GetProperties(self, index):
474          if num < 0:          """Return a ClassGroupProperties object whose properties
475              return False          represent a point at 'index' between "hot" and "cold".
476    
477          self.num = float(num)          index -- a value such that 0 <= index <= 1
478          self.index = 0          """
   
         return True  
   
     def next(self):  
         if self.index == self.num:  
             raise StopIteration  
479    
480          clr = [1.0, 1.0, 1.0]          clr = [1.0, 1.0, 1.0]
481    
482          if self.index < (.25 * self.num):          if index < .25:
483              clr[0] = 0              clr[0] = 0
484              clr[1] = 4 * self.index / self.num              clr[1] = 4 * index
485          elif self.index < (.5 * self.num):          elif index < .5:
486              clr[0] = 0              clr[0] = 0
487              clr[2] = 1 + 4 * (.25 * self.num - self.index) / self.num              clr[2] = 1 + 4 * (.25 - index)
488          elif self.index < (.75 * self.num):          elif index < .75:
489              clr[0] = 4 * (self.index - .5 * self.num) / self.num              clr[0] = 4 * (index - .5)
490              clr[2] = 0              clr[2] = 0
491          else:          else:
492              clr[1] = 1 + 4 * (.75 * self.num - self.index) / self.num              clr[1] = 1 + 4 * (.75 - index)
493              clr[2] = 0              clr[2] = 0
494    
         self.index += 1  
   
495          prop = ClassGroupProperties()          prop = ClassGroupProperties()
496          prop.SetLineColor(Color(clr[0], clr[1], clr[2]))          prop.SetLineColor(Color(clr[0], clr[1], clr[2]))
497          prop.SetFill(Color(clr[0], clr[1], clr[2]))          prop.SetFill(Color(clr[0], clr[1], clr[2]))
498    
499          return prop          return prop
500    
501    class FixedRamp:
502        """FixedRamp allows particular properties of a ramp to be
503        held constant over the ramp.
504        """
505    
506        def __init__(self, ramp, fixes):
507            """
508            ramp -- a source ramp to get the default properties
509    
510            fixes -- a tuple (lineColor, lineWidth, fillColor) such that
511                 if any item is not None, the appropriate property will
512                 be fixed to that item value.
513            """
514    
515            self.fixes = fixes
516            self.ramp = ramp
517    
518        def GetRamp(self):
519            """Return this ramp."""
520            return self
521    
522        def GetProperties(self, index):
523            """Return a ClassGroupProperties object whose properties
524            represent a point at 'index' between the properties in
525            the ramp that initialized this FixedRamp.
526    
527            index -- a value such that 0 <= index <= 1
528            """
529    
530            props = self.ramp.GetProperties(index)
531            if self.fixes[0] is not None: props.SetLineColor(self.fixes[0])
532            if self.fixes[1] is not None: props.SetLineWidth(self.fixes[1])
533            if self.fixes[2] is not None: props.SetFill(self.fixes[2])
534    
535            return props

Legend:
Removed from v.1157  
changed lines
  Added in v.1525

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26