/[ascend]/trunk/pygtk/diagnose.py
ViewVC logotype

Diff of /trunk/pygtk/diagnose.py

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

trunk/pygtk/interface/diagnose.py revision 283 by johnpye, Wed Feb 8 15:30:50 2006 UTC trunk/pygtk/diagnose.py revision 2684 by sreenatha, Tue Feb 26 01:56:46 2013 UTC
# Line 1  Line 1 
1  import gtk  import gtk
2  import gtk.glade  import ascpy
 import ascend  
3  from itertools import groupby  from itertools import groupby
4  from operator import itemgetter  from operator import itemgetter
5  import math  import math
6    import re
7    
8    import config
9    from infodialog import *
10    from preferences import *
11    
12    ZOOM_RE = re.compile(r"([0-9]+)\s*%?")
13    MAX_ZOOM_SIZE = float(2000) # float
14    MAX_ZOOM_RATIO = float(16) # float
15    AT_BOUND_TOL = 0.0001;
16    
17  class DiagnoseWindow:  class DiagnoseWindow:
18      def __init__(self,GLADE_FILE,browser):      def __init__(self,browser,block=0):
19          self.browser=browser          self.browser=browser
20          _xml = gtk.glade.XML(GLADE_FILE,"diagnosewin")          self.browser.builder.add_objects_from_file(self.browser.glade_file, ["diagnosewin"])
21          _xml.signal_autoconnect(self)            self.browser.builder.connect_signals(self)
22            self.window = self.browser.builder.get_object("diagnosewin")
23            self.window.grab_focus()
24            self.window.set_transient_for(self.browser.window)
25    
26          self.window = _xml.get_widget("diagnosewin")          self.prefs = Preferences()
         self.image = _xml.get_widget("image")  
         self.blockentry = _xml.get_widget("blockentry")  
27    
28          self.varview = _xml.get_widget("varview")          try:
29                _icon = gtk.Image()
30                _iconpath = browser.assets_dir+'diagnose'+config.ICON_EXTENSION
31                print "ICON PATH =",_iconpath
32                _icon.set_from_file(_iconpath)
33                print "ICON = ",_icon
34                self.window.set_icon(_icon)
35            except:
36                pass
37            
38            self.blockstatus = self.browser.builder.get_object("blockstatustext")
39    
40            self.imagescroll = self.browser.builder.get_object("imagescroll")
41            self.image = self.browser.builder.get_object("image")
42            self.blockentry = self.browser.builder.get_object("blockentry")
43            self.zoomentry = self.browser.builder.get_object("zoomentry")
44    
45            self.var = None; self.rel = None
46            self.varname = self.browser.builder.get_object("varname1")
47            self.varval = self.browser.builder.get_object("varval")
48            self.varinfobutton = self.browser.builder.get_object("varinfobutton")
49            self.relname = self.browser.builder.get_object("relname1")
50            self.relresid = self.browser.builder.get_object("relresid")
51            self.relinfobutton = self.browser.builder.get_object("relinfobutton")
52            self.preferred_units_check = self.browser.builder.get_object("preferred_units_check")
53            if self.prefs.getBoolPref("Diagnose","show_preferred_units")==True:
54                self.preferred_units_check.set_active(True)
55            else:
56                self.preferred_units_check.set_active(False)
57    
58            self.varview = self.browser.builder.get_object("varview")
59          self.varbuf = gtk.TextBuffer()          self.varbuf = gtk.TextBuffer()
60          self.varview.set_buffer(self.varbuf)          self.varview.set_buffer(self.varbuf)
61          self.varcollapsed = _xml.get_widget("varcollapsed")          self.varcollapsed = self.browser.builder.get_object("varcollapsed")
62          self.relview = _xml.get_widget("relview")            self.relview = self.browser.builder.get_object("relview")  
63          self.relcollapsed = _xml.get_widget("relcollapsed")          self.relcollapsed = self.browser.builder.get_object("relcollapsed")
64          self.relvalues = _xml.get_widget("relvalues")          self.relvalues = self.browser.builder.get_object("relvalues")
65          self.rellabels = _xml.get_widget("rellabels")          self.rellabels = self.browser.builder.get_object("rellabels")
66          self.relrels = _xml.get_widget("relrels")          self.relrels = self.browser.builder.get_object("relrels")
67          self.relresids = _xml.get_widget("relresids")          self.relresids = self.browser.builder.get_object("relresids")
68          self.relbuf = gtk.TextBuffer()          self.relbuf = gtk.TextBuffer()
69          self.relview.set_buffer(self.relbuf)          self.relview.set_buffer(self.relbuf)
70            self.im = None
71            self.block = 0
72            self.apply_prefs()
73    
74          self.prepare_data()          self.prepare_data()
75          self.fill_values(0) # block zero          self.fill_values(block) # block zero
76    
77      def run(self):      def run(self):
78          self.window.run()          self.window.run()
79          self.window.hide()          self.window.hide()
80    
81        def apply_prefs(self):
82            vc = self.browser.prefs.getBoolPref("Diagnose","varcollapsed",True)
83    
84            print "VARCOLLAPSED =",vc
85            self.varcollapsed.set_active(vc)
86            self.relcollapsed.set_active(self.browser.prefs.getBoolPref("Diagnose","relcollapsed",True))
87    
88      def prepare_data(self):      def prepare_data(self):
89          # convert incidence map to pylab numarray type:          # convert incidence map to pylab numarray type:
90          print "PREPARING DATA"          print "PREPARING DATA to be loaded"
91          self.im = self.browser.sim.getIncidenceMatrix()          self.im = self.browser.sim.getIncidenceMatrix()
92          self.data = self.im.getIncidenceData()          self.data = self.im.getIncidenceData()
93          print "DATA LOADED"          print "DATA LOADED"
94    
95          self.canvas = None          self.zoom=1;
96            
97      def fill_values(self, block):      def fill_values(self, block):
98          print "FILL VALUES %d" % block          
99          try:          try:
100                if self.im.getNumBlocks()==0:
101                    print "NO BLOCKS!"
102                    self.image.set_from_stock(gtk.STOCK_DIALOG_ERROR
103                        ,gtk.ICON_SIZE_DIALOG
104                    )
105                    self.browser.reporter.reportError(
106                        "Can't 'Diagnose blocks' until solver has been used."
107                    )
108                    return;
109              rl,cl,rh,ch = self.im.getBlockLocation(block)              rl,cl,rh,ch = self.im.getBlockLocation(block)
110          except IndexError:          except IndexError:
111              print "invalid block"              if block >= self.im.getNumBlocks():
112                    block = self.im.getNumBlocks() - 1
113                    rl,cl,rh,ch = self.im.getBlockLocation(block)
114                else:              
115                    print "BLOCK INDEX ERROR: block =",block
116                    self.blockentry.set_text(str(self.block))
117                    return
118            except RuntimeError,e:
119                print "ERROR GETTING BLOCK LOCATION:",str(e)
120                self.blockentry.set_text(str(self.block))
121              return              return
122    
123          self.block = block          self.block = block
124          self.blockentry.set_text(str(block))          self.blockentry.set_text(str(block))
125    
126            self.rl = rl
127            self.cl = cl
128            self.rh = rh
129            self.ch = ch
130    
131          nr = int(rh-rl+1);          nr = int(rh-rl+1);
132          nc = int(ch-cl+1);          nc = int(ch-cl+1);
133    
# Line 68  class DiagnoseWindow: Line 142  class DiagnoseWindow:
142          pinkdot = [chr(255), chr(127), chr(127)]          pinkdot = [chr(255), chr(127), chr(127)]
143          skydot = [chr(127), chr(127), chr(255)]          skydot = [chr(127), chr(127), chr(255)]
144          bluedot = [chr(0), chr(0), chr(255)]          bluedot = [chr(0), chr(0), chr(255)]
145                    hotpinkdot = [chr(255), chr(47), chr(179)] # very big (+/-)
146            brightbluedot = [chr(71), chr(157), chr(255)] # very small (+/-)
147            greendot = [chr(87), chr(193), chr(70)] # close to 1
148            orangedot = [chr(255), chr(207), chr(61)] # 10-1000
149            bluegreendot = [chr(70), chr(221), chr(181)] # 0.001 - 0.1
150          for i in self.data:          for i in self.data:
151              if i.row < rl or i.row > rh or i.col < cl or i.col > ch:              if i.row < rl or i.row > rh or i.col < cl or i.col > ch:
152                  continue                  continue
# Line 77  class DiagnoseWindow: Line 155  class DiagnoseWindow:
155              pos = rowstride*r + 3*c              pos = rowstride*r + 3*c
156              dot = blackdot;              dot = blackdot;
157              var = self.im.getVariable(i.col);              var = self.im.getVariable(i.col);
158              try:              if abs( (var.getValue()-var.getUpperBound())/ var.getNominal() )  < AT_BOUND_TOL:
159                    dot = reddot
160                elif abs( var.getValue() - var.getLowerBound() ) / var.getNominal() < AT_BOUND_TOL:
161                    dot = reddot
162                else:
163                  rat = var.getValue() / var.getNominal()                  rat = var.getValue() / var.getNominal()
164                  print "SCALE i.col =",rat                  if rat!=0:
165                  val = math.log(rat);                      try:
166                  print "LOG i.col =",val                          val = abs(rat)
167                  if val > 1:                          if abs(rat) > 1000:
168                      dot = reddot;                              dot = hotpinkdot
169                  elif var < -1:                          elif abs(rat) > 10:
170                      dot = bluedot;                              dot = orangedot
171                  elif var > 0:                          elif abs(rat) < 0.001:
172                      dot = pinkdot;                              dot = brightbluedot
173                  elif var < 0:                          elif abs(rat) < 10 and abs(rat) > 0.1:
174                      dot = skydot;                              dot = greendot
175              except ValueError, e:                          elif abs(rat) > 0.001 and abs(rat) < 0.1:
176                  pass                              dot = bluegreendot
177              print "DOT: ",dot                          else:
178                                dot = blackdot
179                        except ValueError, e:
180                            pass
181                #print "DOT: ",dot
182              b[pos], b[pos+1], b[pos+2] = dot              b[pos], b[pos+1], b[pos+2] = dot
183    
184          d = ''.join(b)          d = ''.join(b)
185    
186          print "DONE IMAGE CREATION"          print "DONE IMAGE CREATION"
   
         pb = gtk.gdk.pixbuf_new_from_data(d, gtk.gdk.COLORSPACE_RGB, False, 8 \  
                 , nc, nr, rowstride)  
187            
188            self.pixbuf = gtk.gdk.pixbuf_new_from_data(d, gtk.gdk.COLORSPACE_RGB, False, 8 \
189                    , nc, nr, rowstride);
190    
191          if nc > nr:          self.nr = nr
192              w = 400          self.nc = nc
193              h = 400 * nr / nc;          self.zoom = -1 # to fit, up to max 16x
194          else:          self.do_zoom()
195              h = 400  
196              w = 400 * nr / nc;          print "DONE IMAGE TRANSFER TO SERVER"
197    
198            self.fill_var_names()
199            self.fill_rel_names()
200            self.fill_block_status()
201        
202            self.fill_selection_info()
203    
204          if h/nr > 16 or w/nc > 16:          print "DONE FILL VALUES"
             h= nr*16  
             w= nc*16  
205    
206          if nc < 200 and nr < 200:      def fill_selection_info(self):
207              pb1 = pb.scale_simple(w,h,gtk.gdk.INTERP_NEAREST)          if self.var:
208                self.varname.set_text(self.var.getName())
209                default_units = self.var.getInstance().getType().getDimensions().getDefaultUnits().getName().toString()
210                pref_units = self.var.getInstance().getType().getPreferredUnits()
211                if pref_units and self.prefs.getBoolPref("Diagnose","show_preferred_units",True):
212                    varval = str(self.var.getValue())+" "+pref_units.getName().toString()
213                else:
214                    if default_units=="?":
215                        varval = str(self.var.getValue())
216                    else:
217                        varval = str(self.var.getValue())+" "+default_units
218                self.varval.set_text(varval)
219                self.varinfobutton.set_sensitive(True)
220          else:          else:
221              pb1 = pb.scale_simple(w,h,gtk.gdk.INTERP_BILINEAR)              self.varname.set_text("")
222                self.varval.set_text("")
223                self.varinfobutton.set_sensitive(False)
224    
225            if self.rel:
226                self.relname.set_text(self.rel.getName())
227                self.relresid.set_text(str(self.rel.getResidual()))
228                self.relinfobutton.set_sensitive(True)
229            else:
230                self.relname.set_text("")
231                self.relresid.set_text("")
232                self.relinfobutton.set_sensitive(False)
233    
234        def do_zoom(self):
235            if self.zoom == -1:
236                w, h = self.imagescroll.size_request()
237                #print "SCALE TO FIX, w=%d, h=%d" % (w,h)
238                if self.nc/self.nr > w/h:
239                    # a 'wide' image    
240                    self.zoom = float(w) / self.nc
241                else:
242                    self.zoom = float(h) / self.nr
243    
244            #self.browser.reporter.reportNote("Diagnose window: preliminary calculated zoom = %f (nr = %d, nc = %d)" % (self.zoom, self.nr, self.nc))
245                    
         del pb;  
246    
247          print "DONE IMAGE PREPARATION"          if self.zoom > MAX_ZOOM_RATIO:
248                self.zoom = MAX_ZOOM_RATIO
249    
250          self.image.set_from_pixbuf(pb1)          if self.zoom * self.nc > MAX_ZOOM_SIZE or self.zoom * self.nr > MAX_ZOOM_SIZE:
251                self.browser.reporter.reportNote("image is too big, reducing to MAX_ZOOM_SIZE = %f" % MAX_ZOOM_SIZE);
252                self.zoom = MAX_ZOOM_SIZE / max(self.nc,self.nr)
253    
254            #self.browser.reporter.reportNote("Diagnose window: matrix zoom = %f" % self.zoom)
255            w = int(self.zoom * self.nc);
256            h = int(self.zoom * self.nr);
257                
258            self.zoomentry.set_text("%d %%" % (int(self.zoom*100)) )
259    
260          print "DONE IMAGE TRANSFER TO SERVER"          if self.zoom < 2:
261                pb1 = self.pixbuf.scale_simple(w,h,gtk.gdk.INTERP_BILINEAR)
262            else:
263                pb1 = self.pixbuf.scale_simple(w,h,gtk.gdk.INTERP_NEAREST)
264            
265            self.image.set_from_pixbuf(pb1)
266    
267          self.fill_var_names()      def fill_block_status(self):
268          self.fill_rel_names()          print "FILL BLOCK STATUS"
269            s = self.im.getBlockStatus(self.block)
270            ss = "Failed"
271            if s == ascpy.IM_CONVERGED:
272                ss = "Converged"
273            elif s == ascpy.IM_NOT_YET_ATTEMPTED:
274                ss = "Not attempted yet"
275            elif s == ascpy.IM_OVER_TIME:
276                ss += " (time limit)"
277            elif s == ascpy.IM_OVER_ITER:
278                ss += " (iter limit)"
279            self.blockstatus.set_text(ss);
280            
281    
282      def fill_var_names(self):      def fill_var_names(self):
283            print "FILL VAR NAMES"
284    
285          names = [str(i) for i in self.im.getBlockVars(self.block)]          names = [str(i) for i in self.im.getBlockVars(self.block)]
286    
287            #print "NAMES:",names
288    
289          if self.varcollapsed.get_active():          if self.varcollapsed.get_active():
290              res = collapse(names)              res = reduce(names)
291              rows = []              rows = []
292              for k in res:              for k in res:
293                  if k=="":                  if k=="":
# Line 146  class DiagnoseWindow: Line 300  class DiagnoseWindow:
300              text = "\n".join(names)              text = "\n".join(names)
301          self.varbuf.set_text(text)          self.varbuf.set_text(text)
302    
303            print "DONE VAR NAMES"
304    
305      def fill_rel_names(self):      def fill_rel_names(self):
306          names = [str(i) for i in self.im.getBlockRels(self.block)]          print "REL NAMES"
307    
308            rels = self.im.getBlockRels(self.block)
309    
310            print "GOT RELS, NOW GETTING NAMES"
311    
312            names = [str(i) for i in rels]
313    
314            #print "NAMES =",names
315    
316          if self.relcollapsed.get_active():          if self.relcollapsed.get_active():
317              text = "\n".join(collapse(names))              res = reduce(names)
318                rows = []
319                for k in res:
320                    if k=="":
321                        for r in res[k]:
322                            rows.append(r)
323                    else:
324                        rows.append( '%s:\n\t%s' % (k, "\n\t".join(res[k])) )
325                text = "\n".join(rows)
326          else:          else:
327              text = "\n".join(names)              text = "\n".join(names)
328          self.relbuf.set_text(text)          self.relbuf.set_text(text)
329    
330            print "DONE REL NAMES"
331    
332      def set_block(self, block):      def set_block(self, block):
         self.block = block;  
333          self.fill_values(block)          self.fill_values(block)
334    
335        def set_zoom(self,zoom):
336            self.zoom = zoom
337            self.do_zoom()
338    
339        def show_cursor(self,x,y):
340            c = self.cl + int(x/self.zoom)
341            r = self.rl + int(y / self.zoom)
342            if c > self.ch or r > self.rh:
343                #print "OUT OF RANGE"
344                return
345            self.var = self.im.getVariable(c)
346            self.rel = self.im.getRelation(r)
347            self.fill_selection_info()
348    
349        # GUI EVENT HOOKS-----------------------------------------------------------
350    
351        def on_diagnosewin_close(self,*args):
352            self.window.response(gtk.RESPONSE_CLOSE);
353    
354        def on_preferred_units_toggle(self,widget):
355            _v = widget.get_active()
356            self.prefs.setBoolPref("Diagnose","show_preferred_units",_v)
357            self.fill_selection_info()
358    
359        # incidence data view
360    
361      def on_varcollapsed_toggled(self,*args):      def on_varcollapsed_toggled(self,*args):
362          print "COLLAPSED-TOGGLED"          vc = self.varcollapsed.get_active()
363          self.fill_var_names()          self.browser.prefs.setBoolPref("Diagnose","varcollapsed",vc)    
364            if self.im:
365                self.fill_var_names()
366    
367      def on_relcollapsed_toggled(self,*args):      def on_relcollapsed_toggled(self,*args):
368          print "COLLAPSED-TOGGLED"          rc = self.varcollapsed.get_active()
369          self.fill_rel_names()          self.browser.prefs.setBoolPref("Diagnose","relcollapsed",rc)    
370            if self.im:
371                self.fill_rel_names()
372    
373        # detailed information about vars and rels (solver-side information!)
374    
375        def on_varinfobutton_clicked(self,*args):
376            title = "Variable '%s'" % self.var
377            text = "%s\n%s\n" % (title,"(from the solver's view)")
378            units = " "
379            default_units = self.var.getInstance().getType().getDimensions().getDefaultUnits().getName().toString()
380            pref_units = self.var.getInstance().getType().getPreferredUnits()
381            if pref_units and self.prefs.getBoolPref("Diagnose","show_preferred_units",True):
382                units += pref_units.getName().toString()
383            else:
384                if default_units!="?":
385                    units += default_units
386            _rows = {
387                "Value": self.var.getValue()
388                ,"Nominal": self.var.getNominal()
389                ,"Lower bound": self.var.getLowerBound()
390                ,"Upper bound": self.var.getUpperBound()
391            }
392            for k,v in _rows.iteritems():
393                text += "\n  %s\t%s" % (k,value_human(v)+units)
394            
395            text += "\n\nIncident with %d relations:" % self.var.getNumIncidentRelations()
396            for r in self.var.getIncidentRelations():
397                text += "\n  %s" % r.getName()
398    
399            _dialog = InfoDialog(self.browser,self.window,text,title,tabs=(150,300))
400            _dialog.run()
401    
402        def on_relinfobutton_clicked(self,*args):
403            title = "Relation '%s'" % self.rel
404            text = "%s\n%s\n" % (title,"(from the solver's view)")
405            text += "\n  %s\t%15f" % ("Residual", self.rel.getResidual())
406    
407            text += "\n\nRelation expression:\n"
408            text += self.rel.getRelationAsString()
409    
410            text += "\n\nIncident with %d variables:" % self.rel.getNumIncidentVariables()
411            for v in self.rel.getIncidentVariables():
412                units = " "
413                default_units = v.getInstance().getType().getDimensions().getDefaultUnits().getName().toString()
414                pref_units = v.getInstance().getType().getPreferredUnits()
415                if pref_units and self.prefs.getBoolPref("Diagnose","show_preferred_units",True):
416                    units += pref_units.getName().toString()
417                else:
418                    if default_units != "?" :
419                        units += default_units
420                text += "\n  %s\t= %s" % ( v.getName(),value_human(v.getValue())+units )
421    
422            _dialog = InfoDialog(self.browser,self.window,text,title,tabs=(150,300))
423            _dialog.run()
424            
425    
426        # block navigation
427    
428      def on_nextbutton_clicked(self,*args):      def on_nextbutton_clicked(self,*args):
429          self.set_block(self.block + 1)          self.set_block(self.block + 1)
430    
431      def on_prevbutton_clicked(self,*args):      def on_prevbutton_clicked(self,*args):
432          self.set_block(self.block - 1)                self.set_block(self.block - 1)  
433    
434        def on_prevbigbutton_clicked(self,*args):
435            b = self.block - 1
436            while b >= 0:
437                rl,cl,rh,ch = self.im.getBlockLocation(b)
438                if rh-rl > 0 or ch-cl>0:
439                    self.set_block(b)
440                    return
441                b = b - 1
442            print "NO PRECEDING 'BIG' BLOCKS"
443            
444        def on_nextbigbutton_clicked(self,*args):
445            b = self.block + 1
446            n = self.im.getNumBlocks()
447            while b < n:
448                rl,cl,rh,ch = self.im.getBlockLocation(b)
449                if rh-rl > 0 or ch-cl>0:
450                    self.set_block(b)
451                    return
452                b = b + 1
453            print "NO FOLLOWING 'BIG' BLOCKS"
454        
455      def on_blockentry_key_press_event(self,widget,event):      def on_blockentry_key_press_event(self,widget,event):
456          keyname = gtk.gdk.keyval_name(event.keyval)          keyname = gtk.gdk.keyval_name(event.keyval)
457          print "KEY ",keyname          print "KEY ",keyname
458          if keyname=="Return":          if keyname=="Return":
459              self.set_block( int(self.blockentry.get_text()) )              self.set_block( int(self.blockentry.get_text()) )
460    
461  # The following is from      # zoom in and out
462    
463        def on_zoominbutton_clicked(self,*args):
464            z = int( math.log(self.zoom)/math.log(2) )
465            z = pow(2,z + 1);
466            self.set_zoom(z)
467    
468        def on_zoomoutbutton_clicked(self,*args):
469            z = int( math.log(self.zoom)/math.log(2) + 0.999)
470            z = pow(2,z - 1);
471            self.set_zoom(z)        
472    
473        def on_zoomentry_key_press_event(self,widget,event):
474            keyname = gtk.gdk.keyval_name(event.keyval)
475            print "KEY ",keyname
476            if keyname=="Return":
477                t = self.zoomentry.get_text()
478                m = ZOOM_RE.match(t)
479                if not m:
480                    self.zoomentry.set_text("%d %%" % int(self.zoom*100))
481                for mm in m:
482                    print m
483                self.set_zoom( int(self.zoomentry.get_text()) )
484    
485        # clicking in incidence matrix to get updated information at RHS
486    
487        def on_imageevent_motion_notify_event(self,widget,event):
488            self.show_cursor(event.x, event.y)
489    
490        def on_imageevent_button_press_event(self,widget,event):
491            self.show_cursor(event.x, event.y)
492    
493    
494    def value_human(v):
495        if v==0 or abs( math.log10(abs(v)) )<8:
496            return "%f" % v
497        return "%e" % v
498    
499    #---------------------------------------
500    # Procedures to 'fold' a list of items from a hierarchy
501  # http://www.experts-exchange.com/Programming/Programming_Languages/Python/Q_21719649.html  # http://www.experts-exchange.com/Programming/Programming_Languages/Python/Q_21719649.html
502    # It's still buggy, I think
503    
504  def fold(data):  def fold(data):
505      """ fold sorted numeric sequence data into ranged representation:      """ fold sorted numeric sequence data into ranged representation:
# Line 187  def fold(data): Line 507  def fold(data):
507      '[1,4-6,10,15-18,22,25-28]'      '[1,4-6,10,15-18,22,25-28]'
508      """      """
509      folded = []      folded = []
510      for k, g in groupby(enumerate(data), lambda (i,x):i-x):      for k, g in groupby(enumerate(sorted(data)), lambda (i,x):i-x):
511          seq = map(itemgetter(1), g)          seq = map(itemgetter(1), g)
512          if len(seq) > 1:          if len(seq) > 1:
513              x = '%s-%s' % (seq[0], seq[-1])              x = '%s-%s' % (seq[0], seq[-1])
# Line 196  def fold(data): Line 516  def fold(data):
516          folded.append(x)          folded.append(x)
517      return folded and '[%s]' % ','.join(folded) or ''      return folded and '[%s]' % ','.join(folded) or ''
518    
519  def collapse(names):  def reduce(names):
520      """reduce a list of items into something more readable:      """reduce a list of items nto something more readable:
521      >>> data = 'C.x C.p C.T C.delta[1] C.delta[2] C.delta[3] C.sat.x C.sat.p C.h C.delta[5]'.split()      >>> data = 'C.x C.p C.T C.delta[1] C.delta[2] C.delta[3] C.sat.x C.sat.p C.h C.delta[5]'.split()
522      >>> res = reduce(data)      >>> res = reduce(data)
523      >>> for k in sorted(res):      >>> for k in sorted(res):
# Line 205  def collapse(names): Line 525  def collapse(names):
525      C: T, delta[1-3,5], h, p, x      C: T, delta[1-3,5], h, p, x
526      C.sat: p, x      C.sat: p, x
527      """      """
528      data = sorted([n.split('.') for n in names], key=len)      data = sorted([n.split('.') for n in sorted(names)], key=len)
529      res = {}      res = {}
530      for k, g in groupby(data, lambda x: len(x)):      for k, g in groupby(data, lambda x: len(x)):
531          item = g.next()          if k == 1:
532          assert len(item) == k              indexed = {}
533          key = '.'.join(item[:-1])              seq = set([get(indexed, item) for item in g])
534          indexed = {}              res['[global]'] = [ i+fold(indexed.get(i, [])) for i in sorted(seq) ]
535          seq = set(get(indexed, item))          else:
536          for item in g:              for key, g1 in groupby(g, lambda x: '.'.join(x[:-1])):
537              seq.add(get(indexed, item))                  indexed = {}
538          res[key] = [i+fold(indexed.get(i, [])) for i in sorted(seq)]                  seq = set(get(indexed, item) for item in g1)
539                    res[key] = [ i+fold(indexed.get(i, [])) for i in sorted(seq) ]
540      return res      return res
541    
542  def get(indexed, item):  def get(indexed, item):
# Line 224  def get(indexed, item): Line 545  def get(indexed, item):
545          item, idx = item[:-1].split('[')          item, idx = item[:-1].split('[')
546          indexed.setdefault(item, []).append(int(idx))          indexed.setdefault(item, []).append(int(idx))
547      return item      return item
548    

Legend:
Removed from v.283  
changed lines
  Added in v.2684

john.pye@anu.edu.au
ViewVC Help
Powered by ViewVC 1.1.22