/[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 886 by jonathan, Fri May 9 16:36:56 2003 UTC revision 895 by jonathan, Mon May 12 11:21:02 2003 UTC
# Line 14  from classification import Classificatio Line 14  from classification import Classificatio
14    
15  class ClassGenerator:  class ClassGenerator:
16    
17      def GenSingletonsFromList(self, list, numGroups, ramp):      def GenSingletonsFromList(self, _list, numGroups, ramp):
18          """Generate a new classification consisting solely of singletons.          """Generate a new classification consisting solely of singletons.
19    
20          The resulting classification will consist of at most 'numGroups'          The resulting classification will consist of at most 'numGroups'
21          groups whose group properties ramp between 'prop1' and 'prop2'. There          groups whose group properties ramp between 'prop1' and 'prop2'. There
22          could be fewer groups if 'list' contains fewer that 'numGroups' items.          could be fewer groups if '_list' contains fewer that 'numGroups' items.
23    
24          list -- any object that implements the iterator interface          _list -- any object that implements the iterator interface
25    
26          numGroups -- how many groups to generate. This can not be          numGroups -- how many groups to generate. This can not be
27                       determined while the classification is being                       determined while the classification is being
# Line 38  class ClassGenerator: Line 38  class ClassGenerator:
38    
39          ramp.SetNumGroups(numGroups)          ramp.SetNumGroups(numGroups)
40    
41          for value, prop in zip(list, ramp):          for value, prop in zip(_list, ramp):
42              clazz.AppendGroup(ClassGroupSingleton(value, prop))              clazz.AppendGroup(ClassGroupSingleton(value, prop))
43    
44          return clazz          return clazz
# Line 108  class ClassGenerator: Line 108  class ClassGenerator:
108          return clazz          return clazz
109    
110    
111      def GenQuantiles(self, list, percents, ramp, _range):      def GenQuantiles(self, _list, percents, ramp, _range):
112            """Generates a Classification which has groups of ranges that
113            represent quantiles of _list at the percentages given in percents.
114            Only the values that fall within _range are considered.
115    
116            Returns a tuple (adjusted, Classification) where adjusted is
117            True if the Classification does not exactly represent the given
118            range, or if the Classification is empty.
119    
120            _list -- a sort list of values
121    
122            percents -- a sorted list of floats in the range 0.0-1.0 which
123                        represent the upper bound of each quantile
124    
125            ramp -- an object which implements the CustomRamp interface
126    
127            _range -- a Range object
128            """
129    
130          clazz = Classification()          clazz = Classification()
131          quantiles = self.CalculateQuantiles(list, percents, _range)          quantiles = self.CalculateQuantiles(_list, percents, _range)
132          numGroups = len(quantiles[1])          adjusted = True
         if numGroups == 0: return clazz  
133    
134          ramp.SetNumGroups(numGroups)          if quantiles is not None:
135    
136                numGroups = len(quantiles[3])
137    
138          left, min, max, right = _range.GetRange()              if numGroups != 0:
139    
140          start = "["                  adjusted = quantiles[0]
         oldp = 0  
         for (q, p), prop in zip(quantiles[1], ramp):  
             max = list[q]  
             group = ClassGroupRange(Range(start + str(min) + ";" +  
                                                   str(max) + "]"),  
                                     None, prop)  
   
             group.SetLabel("%s%% - %s%%" % (round(oldp*100, 2),  
                                             round(p*100, 2)))  
             oldp = p  
             start = "]"  
             min = max  
             clazz.AppendGroup(group)  
141    
142          return (quantiles[0], clazz)                  ramp.SetNumGroups(numGroups)
143    
144                    min = _list[quantiles[1]]
145                    start = "["
146                    oldp = 0
147                    for (q, p), prop in zip(quantiles[3], ramp):
148                        max = _list[q]
149                        group = ClassGroupRange(Range(start + str(min) + ";" +
150                                                              str(max) + "]"),
151                                                None, prop)
152            
153                        group.SetLabel("%s%% - %s%%" % (round(oldp*100, 2),
154                                                        round(p*100, 2)))
155                        oldp = p
156                        start = "]"
157                        min = max
158                        clazz.AppendGroup(group)
159    
160      def CalculateQuantiles(self, list, percents, _range):          return (adjusted, clazz)
161          """Calculate quantiles for the given list of percents from the  
162        def CalculateQuantiles(self, _list, percents, _range):
163            """Calculate quantiles for the given _list of percents from the
164          sorted list of values that are in range.          sorted list of values that are in range.
165                                                                                                                                                                    
166          percents is a sorted list of floats in the range 0.0-1.0          This may not actually generate len(percents) quantiles if
   
         This may not actually generate numGroups quantiles if  
167          many of the values that fall on quantile borders are the same.          many of the values that fall on quantile borders are the same.
168    
169          Returns a tuple of the form: (adjusted, [quantile_list])          Returns a tuple of the form:
170                (adjusted, minIndex, maxIndex, [quantile_list])
171    
172            where adjusted is True if the the quantile percentages differ from
173            those supplied, minIndex is the index into _list where the
174            minimum value used is located, maxIndex is the index into _list
175            where the maximum value used is located, and quantile_list is a
176            list of tuples of the form: (list_index, quantile_percentage)
177    
178          where adjusted is true if the the quantile percentages differ from          Returns None, if no quantiles could be generated based on the
179          those supplied, and quantile_list is a list of tuples of the form:          given range or input list.
180              (list_index, quantile_percentage)  
181            _list -- a sort list of values
182    
183            percents -- a sorted list of floats in the range 0.0-1.0 which
184                        represent the upper bound of each quantile
185    
186            _range -- a Range object
187          """          """
188            
189          quantiles = []          quantiles = []
                                                                                   
190          adjusted = False          adjusted = False
191    
192          if len(percents) != 0:          if len(percents) != 0:
193                                                                                                                                                                
             #print "list:", list  
             #print "percents:", percents  
             #print "numGroups:", numGroups  
       
194              #              #
195              # find what part of the list range covers              # find what part of the _list range covers
196              #              #
197              minIndex = -1              minIndex = -1
198              maxIndex = -2              maxIndex = -2
199              for i in xrange(0, len(list), 1):              for i in xrange(0, len(_list), 1):
200                  if operator.contains(_range, list[i]):                  if operator.contains(_range, _list[i]):
201                      minIndex = i                      minIndex = i
202                      break                      break
203    
204              for i in xrange(len(list)-1, -1, -1):              for i in xrange(len(_list)-1, -1, -1):
205                  if operator.contains(_range, list[i]):                  if operator.contains(_range, _list[i]):
206                      maxIndex = i                      maxIndex = i
207                      break;                      break
208    
209              numValues = maxIndex - minIndex + 1              numValues = maxIndex - minIndex + 1
210              #print "minIndex:", minIndex, "maxIndex:", maxIndex  
211              if minIndex <= maxIndex:              if numValues > 0:
212    
213                  #                  #
214                  # build a list of unique indices into list of where each                  # build a list of unique indices into list of where each
215                  # quantile should be                  # quantile *should* be. set adjusted if the resulting
216                    # indices are different
217                  #                  #
218                  quantiles = {}                  quantiles = {}
219                  for p in percents:                  for p in percents:
# Line 189  class ClassGenerator: Line 221  class ClassGenerator:
221    
222                      adjusted = adjusted \                      adjusted = adjusted \
223                          or quantiles.has_key(index) \                          or quantiles.has_key(index) \
224                          or ((index+1) / float(numValues)) != p                          or ((index - minIndex + 1) / float(numValues)) != p
225    
226                      quantiles[index] = 0                      quantiles[index] = 0
227    
228                  quantiles = quantiles.keys()                  quantiles = quantiles.keys()
229                  quantiles.sort()                  quantiles.sort()
230    
                 #print "quantiles:", quantiles  
       
231                  #                  #
232                  # the current quantile index must be strictly greater than                  # the current quantile index must be strictly greater than
233                  # the lowerBound                  # the lowerBound
234                  #                  #
235                  lowerBound = minIndex - 1                  lowerBound = minIndex - 1
236            
237                  for qindex in range(len(quantiles)):                  for qindex in xrange(len(quantiles)):
238                      if lowerBound >= maxIndex:                      if lowerBound >= maxIndex:
239                          # discard higher quantiles                          # discard higher quantiles
240                          quantiles = quantiles[:qindex]                          quantiles = quantiles[:qindex]
# Line 212  class ClassGenerator: Line 242  class ClassGenerator:
242            
243                      # lowerBound + 1 is always a valid index                      # lowerBound + 1 is always a valid index
244            
       
245                      #                      #
246                      # bump up the current quantile index to be a usable index                      # bump up the current quantile index to be a usable index
247                      # if it currently falls below the lowerBound                      # if it currently falls below the lowerBound
248                      #                      #
249                      if quantiles[qindex] <= lowerBound:                      if quantiles[qindex] <= lowerBound:
250                          quantiles[qindex] = min(lowerBound + 1, maxIndex)                          quantiles[qindex] = lowerBound + 1
251                    
252                      listIndex = quantiles[qindex]                      listIndex = quantiles[qindex]
253                      value = list[quantiles[qindex]]                      value = _list[listIndex]
       
                     #print "-----------------------------------"  
                     #print "listIndex:", listIndex  
                     #print "value:", value  
254            
255                      #                      #
256                      # look for similar values around the quantile index                      # look for similar values around the quantile index
257                      #                      #
                   
                     #print "lowerBound:", lowerBound  
258                      lindex = listIndex - 1                      lindex = listIndex - 1
259                      lcount = 0                      while lindex > lowerBound and value == _list[lindex]:
                     while lindex > lowerBound:  
                         if value != list[lindex]: break  
                         lcount += 1  
260                          lindex -= 1                          lindex -= 1
261                        lcount = (listIndex - 1) - lindex
262            
263                      rindex = listIndex + 1                      rindex = listIndex + 1
264                      rcount = 0                      while rindex < maxIndex + 1 and value == _list[rindex]:
                     while rindex < maxIndex + 1:  
                         if value != list[rindex]: break  
                         rcount += 1  
265                          rindex += 1                          rindex += 1
266                            rcount = (listIndex + 1) - rindex
                     #print lcount, "(lcount)", rcount, "(rcount)"  
                     #print lindex, "(lindex)", rindex, "(rindex)"  
267            
268                      #                      #
269                      # adjust the current quantile index based on how many                      # adjust the current quantile index based on how many
270                      # numbers in the list are the same as the current value                      # numbers in the _list are the same as the current value
271                      #                      #
272                      newIndex = listIndex                      newIndex = listIndex
273                      if lcount == rcount:                      if lcount == rcount:
# Line 263  class ClassGenerator: Line 279  class ClassGenerator:
279                              #                              #
280                              if lindex != lowerBound:                              if lindex != lowerBound:
281                                  newIndex = lindex                                  newIndex = lindex
                                 #quantiles[qindex] = lindex  
282                              else:                              else:
283                                  newIndex = rindex - 1                                  newIndex = rindex - 1
                                 #quantiles[qindex] = rindex - 1  
284            
285                      elif lcount < rcount:                      elif lcount < rcount:
286                          # there are fewer items to the left, so                          # there are fewer items to the left, so
# Line 274  class ClassGenerator: Line 288  class ClassGenerator:
288                          # doing so creates an empty quantile.                          # doing so creates an empty quantile.
289                          if lindex != lowerBound:                          if lindex != lowerBound:
290                              newIndex = lindex                              newIndex = lindex
                             #quantiles[qindex] = lindex  
291                          else:                          else:
292                              newIndex = rindex - 1                              newIndex = rindex - 1
                             #quantiles[qindex] = rindex - 1  
293            
294                      elif rcount < lcount:                      elif rcount < lcount:
295                          # there are fewer items to the right, so go to the right                          # there are fewer items to the right, so go to the right
                         #quantiles[qindex] = rindex - 1  
296                          newIndex = rindex - 1                          newIndex = rindex - 1
297            
298                        adjusted = adjusted or newIndex != listIndex
299    
300                      quantiles[qindex] = newIndex                      quantiles[qindex] = newIndex
301                      lowerBound = quantiles[qindex]                      lowerBound = quantiles[qindex]
302            
303                      #print "quantiles:", quantiles          #
304                      #print "lowerBound:", lowerBound          # since quantiles is only set if the code is at least a little
305                    # successful, an empty list will be generated in the case that
306                  #print "================================="          # we fail to get to the real body of the algorithm
307                  #print "quantiles:", quantiles          #
308                  #print "qindex:", qindex          if len(quantiles) == 0:
309                    return None
310          return (adjusted, [(q, (q+1) / float(numValues)) for q in quantiles])          else:
311                return (adjusted, minIndex, maxIndex,
312                        [(q, (q - minIndex+1) / float(numValues)) \
313                         for q in quantiles])
314    
315  CLR  = 0  CLR  = 0
316  STEP = 1  STEP = 1

Legend:
Removed from v.886  
changed lines
  Added in v.895

[email protected]
ViewVC Help
Powered by ViewVC 1.1.26