Just added a new config variable, "force_multiplier", which unsurprisingly muliplies...
[hooke.git] / hooke_cli.py
1 #!/usr/bin/env python
2
3 '''
4 hooke_cli.py
5
6 Command line module of Hooke.
7
8 Copyright (C) 2006 Massimo Sandal (University of Bologna, Italy).
9
10 This program is released under the GNU General Public License version 2.
11 '''
12
13
14 from libhooke import * #FIXME
15 import libhookecurve as lhc
16
17 import libinput as linp
18 import liboutlet as lout
19
20 from libhooke import WX_GOOD
21 from libhooke import HOOKE_VERSION
22
23 import wxversion
24 wxversion.select(WX_GOOD)
25 import wx
26
27 from wx.lib.newevent import NewEvent
28 from matplotlib.numerix import * #FIXME
29
30 import xml.dom.minidom
31 import sys, os, os.path, glob, shutil
32 import Queue
33 import cmd
34 import time
35
36 global __version__
37 global __codename__
38 global __releasedate__
39 __version__ = HOOKE_VERSION[0]
40 __codename__ = HOOKE_VERSION[1]
41 __releasedate__ = HOOKE_VERSION[2]
42
43 from matplotlib import __version__ as mpl_version
44 from wx import __version__ as wx_version
45 from wxmpl import __version__ as wxmpl_version
46 from scipy import __version__ as scipy_version
47 from numpy import __version__ as numpy_version
48 from sys import version as python_version
49 import platform
50
51
52 class HookeCli(cmd.Cmd):
53     
54     def __init__(self,frame,list_of_events,events_from_gui,config,drivers):
55         cmd.Cmd.__init__(self)
56                        
57         self.prompt = 'hooke: '
58         
59         
60         self.current_list=[] #the playlist we're using
61         
62         self.current=None    #the current curve under analysis. 
63         self.plots=None
64         '''
65         The actual hierarchy of the "current curve" is a bit complex:
66         
67         self.current = the lhc.HookeCurve container object of the current curve
68         self.current.curve = the current "real" curve object as defined in the filetype driver class
69         self.current.curve.default_plots() = the default plots of the filetype driver.
70         
71         The plot objects obtained by mean of self.current.curve.default_plots() 
72         then undergoes modifications by the plotmanip
73         modifier functions. The modified plot is saved in self.plots and used if needed by other functions.       
74         '''
75         
76         
77         self.pointer=0       #a pointer to navigate the current list
78                         
79         #Things that come from outside
80         self.frame=frame                        #the wx frame we refer to
81         self.list_of_events=list_of_events      #a list of wx events we use to interact with the GUI
82         self.events_from_gui=events_from_gui    #the Queue object we use to have messages from the GUI
83         self.config=config                      #the configuration dictionary
84         self.drivers=drivers                    #the file format drivers
85         
86         #get plot manipulation functions
87         plotmanip_functions=[]
88         for object_name in dir(self):
89                 if object_name[0:9]=='plotmanip':
90                     plotmanip_functions.append(getattr(self,object_name))
91         #put plotmanips in order
92         self.plotmanip=[None for item in self.config['plotmanips']]
93         for item in plotmanip_functions:
94             namefunction=item.__name__[10:]
95             if namefunction in self.config['plotmanips']:
96                 nameindex=self.config['plotmanips'].index(namefunction) #index of function in plotmanips config
97                 self.plotmanip[nameindex] = item
98             else:
99                 pass
100            
101             
102         self.playlist_saved=0 #Did we save the playlist?
103         self.playlist_name='' #Name of playlist
104         self.notes_saved=1 #Did we save the notes?
105         self.notes_filename=None #Name of notes
106
107         #create outlet
108         self.outlet=lout.Outlet()
109         
110         #Data that must be saved in the playlist, related to the whole playlist (not individual curves)
111         self.playlist_generics={} 
112         
113         #make sure we execute _plug_init() for every command line plugin we import
114         for plugin_name in self.config['plugins']:
115             try:
116                 plugin=__import__(plugin_name)
117                 try:
118                     eval('plugin.'+plugin_name+'Commands._plug_init(self)')
119                 except AttributeError:
120                     pass
121             except ImportError:
122                 pass
123
124         #load default list, if possible
125         self.do_loadlist(self.config['defaultlist'])
126         
127 #HELPER FUNCTIONS
128 #Everything sending an event should be here
129     def _measure_N_points(self, N, whatset=1):
130         '''
131         general helper function for N-points measures
132         '''
133         wx.PostEvent(self.frame,self.list_of_events['measure_points'](num_of_points=N, set=whatset))
134         while 1:
135             try:
136                 points=self.frame.events_from_gui.get()
137                 break
138             except Empty:
139                 pass
140         return points
141         
142     def _get_displayed_plot(self,dest=0):
143         '''
144         returns the currently displayed plot.
145         '''
146         wx.PostEvent(self.frame, self.list_of_events['get_displayed_plot'](dest=dest))
147         while 1:
148             try:
149                 displayed_plot=self.events_from_gui.get()
150             except Empty:
151                 pass
152             if displayed_plot:
153                 break
154         return displayed_plot
155     
156     def _send_plot(self,plots):
157         '''
158         sends a plot to the GUI
159         '''
160         wx.PostEvent(self.frame, self.list_of_events['plot_graph'](plots=plots))
161         return
162         
163     def _find_plotmanip(self, name):
164         '''
165         returns a plot manipulator function from its name
166         '''
167         return self.plotmanip[self.config['plotmanips'].index(name)]
168     
169     def _clickize(self, xvector, yvector, index):
170         '''
171         returns a ClickedPoint() object from an index and vectors of x, y coordinates       
172         '''
173         point=ClickedPoint()
174         point.index=index
175         point.absolute_coords=xvector[index],yvector[index]
176         point.find_graph_coords(xvector,yvector)
177         return point
178     
179 #HERE COMMANDS BEGIN
180     
181     def help_set(self):
182         print '''
183 SET
184 Sets a local configuration variable
185 -------------
186 Syntax: set [variable] [value]
187         '''
188     def do_set(self,args):
189         #FIXME: some variables in self.config should be hidden or intelligently configurated...
190         args=args.split()
191         if len(args)==0:
192             print 'You must specify a variable and a value'
193             print 'Available variables:'
194             print self.config.keys()
195             return
196         if args[0] not in self.config.keys():
197             print 'This is not an internal Hooke variable!'
198             return
199         if len(args)==1:
200             #FIXME:we should reload the config file and reset the config value
201             print self.config[args[0]]
202             return
203         key=args[0]
204         try: #try to have a numeric value
205             value=float(args[1])
206         except ValueError: #if it cannot be converted to float, it's None, or a string...
207             if value.lower()=='none':
208                 value=None
209             else:
210                 value=args[1]
211                 
212         self.config[key]=value
213         self.do_plot(0)
214         
215 #PLAYLIST MANAGEMENT AND NAVIGATION
216 #------------------------------------
217     
218     def help_loadlist(self):
219         print '''
220 LOADLIST
221 Loads a file playlist
222 -----------
223 Syntax: loadlist [playlist file]
224         '''
225     def do_loadlist(self, args):
226         #checking for args: if nothing is given as input, we warn and exit.
227         while len(args)==0:
228             args=linp.safeinput('File to load?')
229         
230         arglist=args.split()
231         play_to_load=arglist[0]
232         
233         #We assume a Hooke playlist has the extension .hkp
234         if play_to_load[-4:] != '.hkp':
235             play_to_load+='.hkp'
236         
237         try:            
238             playxml=PlaylistXML()
239             self.current_list, self.playlist_generics=playxml.load(play_to_load)
240             self.current_playxml=playxml
241         except IOError:
242             print 'File not found.'
243             return
244         
245         print 'Loaded %s curves' %len(self.current_list)
246         
247         if 'pointer' in self.playlist_generics.keys():
248             self.pointer=int(self.playlist_generics['pointer'])
249         else:
250             #if no pointer is found, set the current curve as the first curve of the loaded playlist
251             self.pointer=0
252         print 'Starting at curve ',self.pointer
253             
254         self.current=self.current_list[self.pointer]
255         
256         #resets saved/notes saved state
257         self.playlist_saved=0
258         self.playlist_name=''
259         self.notes_saved=0        
260     
261         self.do_plot(0)
262         
263         
264     def help_genlist(self):
265         print '''
266 GENLIST
267 Generates a file playlist.
268 Note it doesn't *save* it: see savelist for this.
269
270 If [input files] is a directory, it will use all files in the directory for playlist.
271 So:
272 genlist dir
273 genlist dir/
274 genlist dir/*.*
275
276 are all equivalent syntax.
277 ------------
278 Syntax: genlist [input files]
279         
280 '''
281     def do_genlist(self,args):
282         #args list is: input path, output name
283         if len(args)==0:
284             args=linp.safeinput('Input files?')
285                     
286         arglist=args.split()      
287         list_path=arglist[0]
288                   
289         #if it's a directory, is like /directory/*.*
290         #FIXME: probably a bit kludgy.
291         if os.path.isdir(list_path): 
292             if platform.system == 'Windows':
293                 SLASH="\\"
294             else:
295                 SLASH="/"
296             if list_path[-1] == SLASH:
297                 list_path=list_path+'*.*'
298             else:    
299                 list_path=list_path+SLASH+'*.*'
300         
301         #expanding correctly the input list with the glob module :)        
302         list_files=glob.glob(list_path)
303         list_files.sort()
304
305         self.current_list=[]
306         for item in list_files:
307             try:
308                 self.current_list.append(lhc.HookeCurve(os.path.abspath(item))) 
309             except:
310                 pass
311             
312         self.pointer=0    
313         if len(self.current_list)>0:
314             self.current=self.current_list[self.pointer]
315         else:
316             print 'Empty list!'
317             return
318         
319         #resets saved/notes saved state
320         self.playlist_saved=0
321         self.playlist_name=''
322         self.notes_saved=0  
323         
324         self.do_plot(0)
325        
326         
327     def do_savelist(self,args):
328         '''
329         SAVELIST
330         Saves the current file playlist on disk.
331         ------------
332         Syntax: savelist [filename]
333         '''
334         while len(args)==0:
335             args=linp.safeinput('Output file?',['savedlist.txt'])
336     
337         output_filename=args
338         
339         self.playlist_generics['pointer']=self.pointer
340         
341         #autocomplete filename if not specified
342         if output_filename[-4:] != '.hkp':
343             output_filename+='.hkp'
344         
345         playxml=PlaylistXML()
346         playxml.export(self.current_list, self.playlist_generics)
347         playxml.save(output_filename)                  
348         
349         #remembers we have saved playlist
350         self.playlist_saved=1
351         
352     def help_addtolist(self):
353         print '''
354 ADDTOLIST
355 Adds a file to the current playlist
356 --------------
357 Syntax: addtolist [filename]
358 '''
359     def do_addtolist(self,args):
360         #args list is: input path
361         if len(args)==0:
362             print 'You must give the input filename you want to add'
363             self.help_addtolist()
364             return
365           
366         filenames=glob.glob(args)
367         
368         for filename in filenames:
369             self.current_list.append(lhc.HookeCurve(os.path.abspath(filename)))
370         #we need to save playlist
371         self.playlist_saved=0
372     
373     def help_printlist(self):
374         print '''
375 PRINTLIST
376 Prints the list of curves in the current playlist
377 -------------
378 Syntax: printlist
379 '''
380     def do_printlist(self,args):
381         for item in self.current_list:
382             print item.path
383             
384     
385     def help_jump(self):
386         print '''
387 JUMP
388 Jumps to a given curve.
389 ------
390 Syntax: jump {$curve}
391
392 If the curve is not in the current playlist, it politely asks if we want to add it.
393         '''  
394     def do_jump(self,filename):
395         '''
396         jumps to the curve with the given filename.
397         if the filename is not in the playlist, it asks if we must add it or not.
398         '''
399         
400         if filename=='':
401             filename=linp.safeinput('Jump to?')
402             
403         filepath=os.path.abspath(filename)
404         print filepath
405                 
406         c=0
407         item_not_found=1
408         while item_not_found:
409             try:
410                 
411                 if self.current_list[c].path == filepath:
412                     self.pointer=c
413                     self.current=self.current_list[self.pointer]
414                     item_not_found=0
415                     self.do_plot(0)
416                 else:
417                     c+=1  
418             except IndexError:
419                 #We've found the end of the list.
420                 answer=linp.safeinput('Curve not found in playlist. Add it to list?',['y'])
421                 if answer.lower()[0]=='y':
422                     try:
423                         self.do_addtolist(filepath)
424                     except:
425                         print 'Curve file not found.'
426                         return
427                     self.current=self.current_list[-1]
428                     self.pointer=(len(current_list)-1)
429                     self.do_plot(0)
430                     
431                 item_not_found=0
432     
433     
434     def do_index(self,args):
435         '''
436         INDEX
437         Prints the index of the current curve in the list
438         -----
439         Syntax: index
440         '''
441         print self.pointer+1, 'of', len(self.current_list) 
442     
443     
444     def help_next(self):
445         print '''
446 NEXT
447 Go the next curve in the playlist.
448 If we are at the last curve, we come back to the first.
449 -----
450 Syntax: next, n
451         '''
452     def do_next(self,args):
453         try:
454             self.current.curve.close_all()
455         except:
456             print 'No curve file loaded, currently!'
457             print 'This should not happen, report to http://code.google.com/p/hooke'
458             return
459         
460         if self.pointer == (len(self.current_list)-1):
461             self.pointer=0
462             print 'Playlist finished; back to first curve.'
463         else:
464             self.pointer+=1
465         
466         self.current=self.current_list[self.pointer]
467         self.do_plot(0)
468         
469     
470     def help_n(self):
471         self.help_next()
472     def do_n(self,args):
473         self.do_next(args)
474         
475     def help_previous(self,args):
476         print '''
477 PREVIOUS
478 Go to the previous curve in the playlist.
479 If we are at the first curve, we jump to the last.
480 -------
481 Syntax: previous, p
482     '''
483     def do_previous(self,args):
484         try:
485             self.current.curve.close_all()
486         except:
487             print 'No curve file loaded, currently!'
488             print 'This should not happen, report to http://code.google.com/p/hooke'
489             return
490         if self.pointer == 0:
491             self.pointer=(len(self.current_list)-1)
492             print 'Start of playlist; jump to last curve.' 
493         else:
494             self.pointer-=1
495             
496         self.current=self.current_list[self.pointer]
497         self.do_plot(args)
498         
499             
500     def help_p(self):
501         self.help_previous()
502     def do_p(self,args):
503         self.do_previous(args)
504
505         
506 #PLOT INTERACTION COMMANDS
507 #-------------------------------    
508     def help_plot(self):
509         print '''
510 PLOT
511 Plots the current force curve
512 -------
513 Syntax: plot
514         '''
515     def do_plot(self,args):
516         
517         self.current.identify(self.drivers)
518         self.plots=self.current.curve.default_plots()
519         try:
520             self.plots=self.current.curve.default_plots()
521         except Exception, e:
522             print 'Unexpected error occurred in do_plot().'
523             print e
524             return
525             
526         #apply the plotmanip functions eventually present
527         nplots=len(self.plots)
528         c=0
529         while c<nplots:
530             for function in self.plotmanip: #FIXME: something strange happens about self.plotmanip[0]
531                 self.plots[c]=function(self.plots[c], self.current)
532                 
533             self.plots[c].xaxes=self.config['xaxes'] #FIXME: in the future, xaxes and yaxes should be set per-plot
534             self.plots[c].yaxes=self.config['yaxes']
535                 
536             c+=1
537
538         self._send_plot(self.plots)
539         
540     def _delta(self, set=1):
541         '''
542         calculates the difference between two clicked points
543         '''
544         print 'Click two points'
545         points=self._measure_N_points(N=2, whatset=set)
546         dx=abs(points[0].graph_coords[0]-points[1].graph_coords[0])
547         dy=abs(points[0].graph_coords[1]-points[1].graph_coords[1])
548         unitx=self.plots[points[0].dest].units[0]
549         unity=self.plots[points[0].dest].units[1]
550         return dx,unitx,dy,unity
551         
552     def do_delta(self,args):
553         '''
554         DELTA
555         
556         Measures the delta X and delta Y between two points.
557         ----
558         Syntax: delta
559         '''
560         dx,unitx,dy,unity=self._delta()
561         print str(dx)+' '+unitx
562         print str(dy)+' '+unity
563     
564     def _point(self, set=1):
565         '''calculates the coordinates of a single clicked point'''
566
567         print 'Click one point'
568         point=self._measure_N_points(N=1, whatset=set)
569         
570         x=point[0].graph_coords[0]
571         y=point[0].graph_coords[1]
572         unitx=self.plots[point[0].dest].units[0]
573         unity=self.plots[point[0].dest].units[1]
574         return x,unitx,y,unity
575         
576     def do_point(self,args):
577         '''
578         POINT
579         
580         Returns the coordinates of a point on the graph.
581         ----
582         Syntax: point
583         '''
584         x,unitx,y,unity=self._point()
585         print str(x)+' '+unitx
586         print str(y)+' '+unity
587         to_dump='point '+self.current.path+' '+str(x)+' '+unitx+', '+str(y)+' '+unity
588         self.outlet.push(to_dump)    
589    
590         
591     def do_close(self,args=None):
592         '''
593         CLOSE
594         Closes one of the two plots. If no arguments are given, the bottom plot is closed.
595         ------
596         Syntax: close [top,bottom]
597         '''
598         if args=='top':
599             to_close=0
600         elif args=='bottom':
601             to_close=1
602         else:
603             to_close=1
604         
605         close_plot=self.list_of_events['close_plot']
606         wx.PostEvent(self.frame, close_plot(to_close=to_close))
607         
608     def do_show(self,args=None):
609         '''
610         SHOW
611         Shows both plots.
612         ''' 
613         show_plots=self.list_of_events['show_plots']
614         wx.PostEvent(self.frame, show_plots())
615        
616         
617     
618     #PLOT EXPORT AND MANIPULATION COMMANDS
619     def help_export(self):
620         print '''
621 EXPORT
622 Saves the current plot as an image file
623 ---------------
624 Syntax: export [filename] {plot to export}
625
626 The supported formats are PNG and EPS; the file extension of the filename is automatically recognized
627 and correctly exported. Resolution is (for now) fixed at 150 dpi.
628
629 If you have a multiple plot, the optional plot to export argument tells Hooke which plot you want to export. If 0, the top plot is exported. If 1, the bottom plot is exported (Exporting both plots is still to implement)
630         '''
631     def do_export(self,args):
632         #FIXME: the bottom plot doesn't have the title
633         
634         dest=0
635         if args=='':
636             name=linp.safeinput('Filename?',[self.current.path+'.png'])
637         else:
638             args=args.split()
639             name=args[0]
640             if len(args) > 1:
641                 dest=int(args[1]) 
642                 
643         export_image=self.list_of_events['export_image']
644         wx.PostEvent(self.frame, export_image(name=name, dest=dest))
645         
646         
647     def help_txt(self):
648         print '''
649 TXT
650 Saves the current curve as a text file
651 Columns are, in order:
652 X1 , Y1 , X2 , Y2 , X3 , Y3 ...
653
654 -------------
655 Syntax: txt [filename] {plot to export}
656         '''
657     def do_txt(self,args):
658         
659         def transposed2(lists, defval=0):
660             '''
661             transposes a list of lists, i.e. from [[a,b,c],[x,y,z]] to [[a,x],[b,y],[c,z]] without losing
662             elements
663             (by Zoran Isailovski on the Python Cookbook online)
664             '''
665             if not lists: return []
666             return map(lambda *row: [elem or defval for elem in row], *lists)
667         
668         whichplot=0
669         args=args.split()
670         if len(args)==0:
671             filename=linp.safeinput('Filename?',[self.current.path+'.txt'])
672         else:
673             filename=linp.checkalphainput(args[0],self.current.path+'.txt',[])
674             try:
675                 whichplot=int(args[1])
676             except:
677                 pass
678             
679         columns=[]     
680         for dataset in self.plots[whichplot].vectors:
681             for i in range(0,len(dataset)): 
682                 columns.append([])
683                 for value in dataset[i]:
684                     columns[-1].append(str(value))                   
685         
686         rows=transposed2(columns, 'nan')
687         rows=[' , '.join(item) for item in rows]
688         text='\n'.join(rows)
689         
690         txtfile=open(filename,'w+')
691         txtfile.write(text)
692         txtfile.close()
693         
694     
695     #LOGGING, REPORTING, NOTETAKING
696     
697
698     def do_note_old(self,args):
699         '''
700         NOTE_OLD
701         **deprecated**: Use note instead. Will be removed in 0.9
702         
703         Writes or displays a note about the current curve.
704         If [anything] is empty, it displays the note, otherwise it adds a note.
705         The note is then saved in the playlist if you issue a savelist command
706         ---------------
707         Syntax: note_old [anything]        
708
709         '''
710         if args=='':
711             print self.current_list[self.pointer].notes
712         else:
713             #bypass UnicodeDecodeError troubles
714             try:
715                 args=args.decode('ascii')
716             except:
717                 args=args.decode('ascii','ignore')
718                 if len(args)==0:
719                     args='?'
720                     
721             self.current_list[self.pointer].notes=args
722         self.notes_saved=0
723             
724             
725     def do_note(self,args):
726         '''
727         NOTE
728         
729         Writes or displays a note about the current curve.
730         If [anything] is empty, it displays the note, otherwise it adds a note.
731         The note is then saved in the playlist if you issue a savelist command.
732         ---------------
733         Syntax: note_old [anything]        
734
735         '''
736         if args=='':
737             print self.current_list[self.pointer].notes
738         else:
739             if self.notes_filename == None:
740                 self.notes_filename=raw_input('Notebook filename? ')
741                 title_line='Notes taken at '+time.asctime()+'\n'
742                 f=open(self.notes_filename,'w')
743                 f.write(title_line)
744                 f.close()
745                 
746             #bypass UnicodeDecodeError troubles    
747             try:
748                args=args.decode('ascii')
749             except:
750                args=args.decode('ascii','ignore')
751                if len(args)==0:
752                    args='?'
753             self.current_list[self.pointer].notes=args
754             
755             f=open(self.notes_filename,'a+')
756             note_string=(self.current.path+'  |  '+self.current.notes+'\n')
757             f.write(note_string)
758             f.close()
759                            
760     def help_notelog(self):
761         print '''
762 NOTELOG
763 Writes a log of the notes taken during the session for the current
764 playlist
765 --------------        
766 Syntax notelog [filename]
767 '''        
768     def do_notelog(self,args):
769         
770         if len(args)==0:
771             args=linp.safeinput('Notelog filename?',['notelog.txt'])
772             
773         note_lines='Notes taken at '+time.asctime()+'\n'
774         for item in self.current_list:
775             if len(item.notes)>0:
776                 #FIXME: log should be justified
777                 #FIXME: file path should be truncated...
778                 note_string=(item.path+'  |  '+item.notes+'\n')
779                 note_lines+=note_string
780                 
781         try:
782             f=open(args,'a+')
783             f.write(note_lines)
784             f.close()
785         except IOError, (ErrorNumber, ErrorMessage):
786             print 'Error: notes cannot be saved. Catched exception:'
787             print ErrorMessage
788         
789         self.notes_saved=1
790
791     def help_copylog(self):
792         print '''
793 COPYLOG
794 Moves the annotated curves to another directory
795 -----------
796 Syntax copylog [directory]
797         '''
798     def do_copylog(self,args):
799         
800         if len(args)==0:
801             args=linp.safeinput('Destination directory?')  #TODO default
802         
803         mydir=os.path.abspath(args)
804         if not os.path.isdir(mydir):
805             print 'Destination is not a directory.'
806             return
807         
808         for item in self.current_list:
809             if len(item.notes)>0:
810                 try:
811                     shutil.copy(item.path, mydir)
812                 except (OSError, IOError):
813                     print 'Cannot copy file. '+item.path+' Perhaps you gave me a wrong directory?'
814
815 #OUTLET management
816 #-----------------
817     def do_outlet_show(self,args):
818         '''OUTLET_SHOW
819         ---------
820         Shows current content of outlet with index for reference
821         '''
822         self.outlet.printbuf()
823
824     def do_outlet_undo(self, args):
825         '''OUTLET_UNDO
826         ---------
827         Eliminates last entry in outlet
828         '''
829         print 'Erasing last entry'
830         self.outlet.pop()
831
832     def do_outlet_delete(self, args):
833         '''OUTLET_DELETE
834         Eliminates a particular entry from outlet
835         Syntax: outlet_delete n
836         '''
837         if len(args)==0:
838             print 'Index needed!, use outlet_show to know it'
839         else:
840             self.outlet.delete(args)
841
842 #OS INTERACTION COMMANDS
843 #-----------------    
844     def help_dir(self):
845         print '''
846 DIR, LS
847 Lists the files in the directory
848 ---------
849 Syntax: dir [path]
850           ls  [path]
851         '''
852     def do_dir(self,args):
853         
854         if len(args)==0:
855             args='*'
856         print glob.glob(args)
857         
858     def help_ls(self):
859         self.help_dir(self)
860     def do_ls(self,args):
861         self.do_dir(args)
862         
863     def help_pwd(self):
864         print '''
865 PWD
866 Gives the current working directory.
867 ------------
868 Syntax: pwd
869         '''
870     def do_pwd(self,args):
871         print os.getcwd()         
872     
873     def help_cd(self):
874         print '''
875 CD
876 Changes the current working directory
877 -----
878 Syntax: cd
879         '''
880     def do_cd(self,args):
881         mypath=os.path.abspath(args)
882         try:
883             os.chdir(mypath)
884         except OSError:
885             print 'I cannot access that directory.'
886     
887     
888     def help_system(self):
889         print '''
890 SYSTEM
891 Executes a system command line and reports the output
892 -----
893 Syntax system [command line]
894         '''
895         pass
896     def do_system(self,args):
897         waste=os.system(args)           
898             
899     def do_debug(self,args):
900         '''
901         this is a dummy command where I put debugging things
902         '''
903         print self.config['plotmanips']
904         pass
905             
906     def help_current(self):
907         print '''
908 CURRENT
909 Prints the current curve path.
910 ------
911 Syntax: current
912         '''
913     def do_current(self,args):
914         print self.current.path
915         
916     def do_info(self,args):
917         '''
918         INFO
919         ----
920         Returns informations about the current curve.
921         '''
922         print 'Path: ',self.current.path
923         print 'Experiment: ',self.current.curve.experiment
924         print 'Filetype: ',self.current.curve.filetype
925         for plot in self.current.curve.default_plots():
926             for set in plot.vectors:
927                 lengths=[len(item) for item in set]
928                 print 'Data set size: ',lengths
929         
930     def do_version(self,args):
931         '''
932         VERSION
933         ------
934         Prints the current version and codename, plus library version. Useful for debugging.
935         '''     
936         print 'Hooke '+__version__+' ('+__codename__+')'
937         print 'Released on: '+__releasedate__
938         print '---'
939         print 'Python version: '+python_version
940         print 'WxPython version: '+wx_version
941         print 'wxMPL version: '+wxmpl_version
942         print 'Matplotlib version: '+mpl_version
943         print 'SciPy version: '+scipy_version
944         print 'NumPy version: '+numpy_version
945         print '---'
946         print 'Platform: '+str(platform.uname())
947         print '---'
948         print 'Loaded plugins:',self.config['loaded_plugins']
949         
950     def help_exit(self):
951         print '''
952 EXIT, QUIT
953 Exits the program cleanly.
954 ------
955 Syntax: exit
956 Syntax: quit
957 '''    
958     def do_exit(self,args):
959         we_exit='N'
960         
961         if (not self.playlist_saved) or (not self.notes_saved):
962             we_exit=linp.safeinput('You did not save your playlist and/or notes. Exit?',['n'])
963         else:
964             we_exit=linp.safeinput('Exit?',['y'])
965         
966         if we_exit[0].upper()=='Y':
967             wx.CallAfter(self.frame.Close)
968             sys.exit(0)
969         else:
970             return
971     
972     def help_quit(self):
973         self.help_exit()
974     def do_quit(self,args):
975         self.do_exit(args)
976
977
978
979
980
981 if __name__ == '__main__':
982     mycli=HookeCli(0)
983     mycli.cmdloop()