source: branches/GUIdev/DuchampParameterGUI.py @ 1329

Last change on this file since 1329 was 1329, checked in by KelvinHsu, 11 years ago

Some neating up of the code (not much...)

  • Property svn:executable set to *
File size: 34.6 KB
Line 
1#!/usr/bin/env python
2
3#-------------------------------------------------------------------------------
4# Name:        DuchampParameterGUI
5# Purpose:
6#
7# Author:      Kelvin
8#
9# Created:     4/12/2013
10#-------------------------------------------------------------------------------
11
12import os
13
14# Python 2 packages
15try:
16    from Tkinter import *
17    import tkFileDialog
18
19# Python 3 packages
20except ImportError:
21    from tkinter import *
22    import tkinter.filedialog as tkFileDialog
23
24
25# Determine the current directory.
26directory = os.getcwd()
27
28# Define the default file path.
29defaultParamFileDirectory = directory
30defaultParamFileName = '/InputComplete'
31defaultParamFilePath = defaultParamFileDirectory + defaultParamFileName
32
33
34# This reads parameter files with the specified format.
35def readParamFile(paramFilePath):
36
37    # Create a dictionary that maps parameter names to its value and a list to keep track of its order.
38    parameters = {}
39    orderedParameters = []
40
41    try:
42        # Open the given parameter file.
43        paramFile = open(paramFilePath)
44
45        # Load files for lines of parameter data in the specified format and
46        # store them into the dictionary.
47        for line in paramFile:
48            if line[0] != '#' and len(line.split()) > 1:
49                linebits = line.split()
50                parameters[linebits[0]] = linebits[1]
51                orderedParameters = orderedParameters + [linebits[0]]
52
53        paramFile.close()
54
55    # Note that if the file could not be read, then the dictionary will stay empty.
56    # The GUI window can make use of this fact.
57    except IOError:
58        print("Cannot open file")
59
60    return(parameters, orderedParameters)
61
62
63# This reads the default file for all relevant information of parameter classes, description, type, and format.
64def readParamByClass(paramFilePath):
65
66    # Create a diciontary that maps parameter names to its class and a list to keep track of class orders.
67    classOfParameter = {}
68    classNames = []
69
70    # Create dictionaries that maps parameter names to its description, value type, and value format.
71    description = {}
72    paramType = {}
73    paramFormat = {}
74
75    try:
76        # Open the given parameter file.
77        paramFile = open(paramFilePath)
78
79        # Load files for lines of parameter data in the specified format and
80        # store them into the dictionaries.
81        for line in paramFile:
82
83            if line[0:3] == '###' and len(line.split('###')) > 1:
84                className = line.strip('###').strip()
85                classNames = classNames + [className]
86
87            elif line[0:2] == '#*' and len(line.split()) > 1 and '--' in line:
88                param = line.split()[1].strip()
89                paramType[param] = line.split('[')[1].split(']')[0].strip()
90                paramFormat[param] = line.split('{')[1].split('}')[0].strip()
91                description[param] = '--'.join(line.split('--')[1:len(line.split('--'))]).strip()
92               
93            elif line[0] != '#' and len(line.split()) > 1:
94                linebits = line.split()
95                classOfParameter[linebits[0]] = className
96
97        paramFile.close()
98
99    # Note that if the file could not be read, then the dictionary will stay empty.
100    # The GUI window can make use of this fact.
101    except IOError:
102        print("Cannot open file")
103                 
104    return(classOfParameter, classNames, description, paramType, paramFormat)
105
106
107# Define a function to create a parameter file with the specified format.
108# It will return 0 if the file already exists and will not overwrite the file just yet (unless write = 1)
109#                1 if the file is successfully created (or overwriten)
110#               -1 if the file was not successfully created (or overwriten) due to some error
111def writeParamFile(newParamFilePath, parameters, parameterOrder, write):
112
113    # If we want to make sure if it is okay to write, do the following.
114    if write != 1:
115       
116        # First, try opening the file for reading.
117        # If the file exists for reading, then close it and then return a 0,
118        # which the GUI window use to warn the user that a file with that name already exists.
119        try:
120            newParamFile = open(newParamFilePath)
121            newParamFile.close()
122            return(0)
123
124        # If we have trouble reading the file, then the file doesn't exist and we're safe to write to it.
125        except IOError:
126            write = 1
127
128    # If we are sure we can write to the file, then do it.
129    if write == 1:
130
131        try:
132            newParamFile = open(newParamFilePath, 'w')
133           
134            # Write the editted set of parameters into the new file.
135            for par in parameterOrder:
136                newParamFile.write('%s    %s\n'%(par, parameters[par]))
137
138            newParamFile.close()
139            return(1)
140       
141        except IOError:
142            return(-1)
143
144
145# This function determines the longest word in a dictionary.
146def longestWordLength(dictionary):
147    return(len(max(dictionary.keys(), key = len)))
148
149# This function determines the longest value in a dictionary.
150def longestValueLength(dictionary):
151    return(len(max(dictionary.values(), key = len)))
152
153# This is the minimum space between the a word and its definition in a dictionary when we want to display it.
154minimumSpace = 5
155
156# This appends the appropriate space after a single word in a dictionary.
157# Note: Can this be optimised?
158def tabbedDictionaryLine(dictionary, word, star):
159
160    if word in dictionary:
161
162        # Determine the residual space our word will have compared to the longest word.
163        residualSpace = longestWordLength(dictionary) - len(word)
164       
165        if star == 0:
166
167            # Add extra space after the word based on the minimum separatio between the word and its definition.
168            space = ' '*(minimumSpace + residualSpace)
169            tabbedWord = word + space
170
171            # Return the word with the appropriate spaces appended.
172            return(tabbedWord)
173        elif star == 1:
174
175            star = ' (*) '
176           
177            # Add extra space after the word based on the minimum separatio between the word and its definition.
178            space = star + ' '*residualSpace + ' '*(minimumSpace - len(star))
179            tabbedWord = word + space
180
181            # Return the word with the appropriate spaces appended.
182            return(tabbedWord)
183
184        else:
185            print("Coding Error: 'Star' is not binary")
186
187    # This exception is not needed, as the function will always be called with a word within the dictionary.
188    else:
189        print(word + "is not in the dictionary")
190        return(' ')
191
192# This determines the longest line that will be printed in a dictionary given the above method.
193def longestLineLength(dictionary):
194
195    maxLineLength = longestWordLength(dictionary) + longestValueLength(dictionary) + minimumSpace
196    return(maxLineLength)
197
198def lower(stringArray):
199
200    lowerArray = []
201
202    L = len(stringArray)
203   
204    for i in range(L):
205        lowerArray += [stringArray[i].lower()]
206
207    return lowerArray
208
209#-------------------------------------------------------------------------------
210# GUI - Tkinter section
211
212class mainInterface:
213
214    def __init__(self, master):
215       
216        # --------------------------------------------------
217        # Initialise the GUI window.
218        self.frame = Frame(master)
219        self.frame.grid()
220        # --------------------------------------------------
221
222        # --------------------------------------------------
223        # Menu
224        self.menubar = Menu(master)
225
226        # File Menu
227        self.filemenu = Menu(self.menubar, tearoff = 0)
228        self.filemenu.add_command(label = "Open", command = self.createInputInterface)
229        self.filemenu.add_command(label = "Save specification", command = self.createSpecifiedOutputInterface)
230        self.filemenu.add_command(label = "Save all specification", command = self.createEffectiveOutputInterface)
231        self.filemenu.add_separator()
232        self.filemenu.add_command(label = "Exit", command = self.frame.quit)
233        self.menubar.add_cascade(label = "File", menu = self.filemenu)
234
235
236        # Options Menu
237        self.editmenu = Menu(self.menubar, tearoff = 0)
238        self.editmenu.add_command(label = "Cut", command = self.notImplementedYet)
239        self.editmenu.add_command(label = "Copy", command = self.notImplementedYet)
240        self.editmenu.add_command(label = "Paste", command = self.notImplementedYet)
241        self.menubar.add_cascade(label = "Options", menu = self.editmenu)
242
243        # Help Menu
244        self.helpmenu = Menu(self.menubar, tearoff = 0)
245        self.helpmenu.add_command(label = "About", command = self.notImplementedYet)
246        self.menubar.add_cascade(label = "Help", menu = self.helpmenu)
247        # --------------------------------------------------
248       
249
250
251       
252        # Row 1-10 reserved for future extensions
253       
254        # --------------------------------------------------
255        # Parameter name and value entry
256        self.parameterLabel = Label(self.frame, text = "Parameter: ", foreground = "Blue")
257        self.parameterLabel.grid(row = 11, column = 1, columnspan = 2)
258
259        self.valueLabel = Label(self.frame, text = "Value: ", foreground = "Forest Green")
260        self.valueLabel.grid(row = 11, column = 3, columnspan = 2)
261
262        self.parameterEntry = Entry(self.frame, width = 25)
263        self.parameterEntry.bind("<Return>", self.checkParameterEvent)
264        self.parameterEntry.grid(row = 12, column = 1, padx = 10, columnspan = 2)
265
266        self.valueEntry = Entry(self.frame, width = 25)
267        self.valueEntry.bind("<Return>", self.updateParameterEvent)
268        self.valueEntry.grid(row = 12, column = 3, padx = 10, columnspan = 2)
269        # --------------------------------------------------
270
271        # --------------------------------------------------
272        # Check, update, and describe parameter buttons
273        self.checkButton = Button(self.frame, text = "Check", command = self.checkParameterWithDescription)
274        self.checkButton.grid(row = 13, column = 1, padx = 10, pady = 10)
275       
276        self.updateButton = Button(self.frame, text = "Update", command = self.updateParameter)
277        self.updateButton.grid(row = 13, column = 2, padx = 10, pady = 10)
278
279        self.revertDefaultButton = Button(self.frame, text = "Revert to default", command = self.revertDefault)
280        self.revertDefaultButton.grid(row = 13, column = 4, padx = 10, pady = 10, columnspan = 2)
281        # --------------------------------------------------
282
283        # Row 14-15 reserved for displaying the information queried from above
284
285        # --------------------------------------------------
286        # List parameter files buttons (default and specified)
287        self.listDefault = Button(self.frame, text = "List Default Parameters", command = lambda: self.listParameters("Default"))
288        self.listDefault.grid(row = 16, column = 1, padx = 10, pady = 10, columnspan = 2)
289
290        self.listSpecified = Button(self.frame, text = "List User Specified Parameters", command = lambda: self.listParameters("Specified"))
291        self.listSpecified.grid(row = 17, column = 1, padx = 10, pady = 10, columnspan = 2)
292
293        self.listEffective = Button(self.frame, text = "List Effective Parameters", command = lambda: self.listParameters("Effective"))
294        self.listEffective.grid(row = 18, column = 1, padx = 10, pady = 10, columnspan = 2)
295        # --------------------------------------------------
296
297
298        # --------------------------------------------------
299        # Radio Buttons
300
301        # Obtain (parameter: class) dictionary, and a list of the names of classes in order
302        (self.classOfParameter, self.classNames, self.description, self.paramType, self.paramFormat) = readParamByClass(defaultParamFilePath)
303
304        # Initialise the variable containing the name of the class to be displayed
305        self.whichClass = StringVar()
306
307        # Index the buttons
308        i = 0
309
310
311        # Create each radio button in order
312        for name in self.classNames:
313           
314            b = Radiobutton(self.frame, text = name, variable = self.whichClass, value = name, indicatoron = 0, command = lambda: self.listParameters("Class"), width = 30)
315
316            # Place them at appropriate positions
317            r = 19 + int(i/2)
318
319            if (i % 2) == 0:
320                c = 1
321            else:
322                c = 3
323
324            # Make them stick to the left
325            b.grid(row = r, column = c, columnspan = 2) #, sticky = W)
326            i = i + 1
327        # --------------------------------------------------
328       
329##        # --------------------------------------------------
330##        # Button for quiting
331##        self.buttonQUIT = Button(self.frame, text = "QUIT", fg = "red", command = self.frame.quit)
332##        self.buttonQUIT.grid(row = 40, column = 4, padx = 20, pady = 10, sticky = E)
333##        # --------------------------------------------------
334
335        # --------------------------------------------------
336        # Variable definitions throughout the window
337       
338        # Firstly, determine the default list of parameters
339        (self.defaultParameters, self.orderedParameters) = readParamFile(defaultParamFilePath)
340
341        # Then, determine the user specified list of parameters
342        self.userSpecifiedParameters = {}
343        self.orderedSpecifiedParameters = []
344
345        # This is the effective parameters
346        self.effectiveParameters = dict(self.defaultParameters)
347
348        # Define the string variables in the parameter name and value entry section
349        self.resultTitle = StringVar()
350        self.result = StringVar()
351        self.notesTitle = StringVar()
352        self.notes = StringVar()
353        self.color = StringVar()
354
355        # Define the string variables for entering file directories, names, and paths   
356        self.userSpecifiedFileDirectory = StringVar()
357        self.userSpecifiedFileName = StringVar()
358        self.userSpecifiedFilePath = StringVar()
359       
360        # Load the file that contains the descriptions for each parameter
361        #self.description = readDescriptionFile(descriptionFilePath)
362        # --------------------------------------------------
363       
364
365        # Firstly, if the default parameter file was not loaded, notify the user
366        if self.defaultParameters == {} or self.description == {} or self.paramType == {} or self.paramFormat == {}:
367
368            self.createNoticeBox("Input")
369            return()
370       
371
372        self.userSpecifiedFileName = 'duchampHIPASS.txt'
373       
374    def notImplementedYet(self):
375   
376        self.notYetBox = Toplevel(width = 200, borderwidth = 20)
377        self.notYetBox.title("Be patient!")
378        self.notYetMsg = Message(self.notYetBox, text = "Wait! This button is still under developement!")
379        self.notYetMsg.grid(row = 1, column = 1, columnspan = 2)
380           
381        self.notYetOkay = Button(self.notYetBox, text = "Alright!", foreground = "White", command = self.notYetBox.destroy)
382        self.notYetOkay.grid(row = 2, column = 1, columnspan = 2)
383       
384    # This checks the value of the parameter entered in the parameter entry box
385    def checkParameter(self):
386
387        # Determine which parameter the user wants to check
388        par = self.parameterEntry.get()
389
390        # Find which list it is in and determine its value
391        # Note that specified list takes priority
392        if par.lower() in lower(self.orderedSpecifiedParameters):
393            index = lower(self.orderedSpecifiedParameters).index(par.lower())
394            parameter2check = self.orderedSpecifiedParameters[index]
395            value = self.userSpecifiedParameters[parameter2check]
396            paramInfo = par + ': ' + value
397            self.color.set("Forest Green")
398            defaultYN = "Specified Value"
399        elif par.lower() in lower(self.orderedParameters):
400            index = lower(self.orderedParameters).index(par.lower())
401            parameter2check = self.orderedParameters[index]
402            value = self.defaultParameters[parameter2check]
403            paramInfo = parameter2check + ': ' + value
404            self.color.set("Forest Green")
405            defaultYN = "Default Value"
406        else:
407            value = "N/A"
408            paramInfo = '"' + par + '" does not exist'
409            self.color.set("Red")
410            defaultYN = "N/A"
411
412
413        # Store the results from the above
414        self.resultTitle.set("Parameter Information")
415        self.result.set(paramInfo)
416        self.notesTitle.set("Default/Specified")
417        self.notes.set(defaultYN)
418
419        self.valueEntry.delete(0, END)
420        self.valueEntry.insert(0, value)
421
422        # --------------------------------------------------
423        # Windows that correspond to the variables above
424        self.resultLabel = Label(self.frame, textvariable = self.resultTitle)
425        self.resultLabel.grid(row = 14, column = 1, pady = 0, columnspan = 2)
426
427        self.resultValue = Label(self.frame, textvariable = self.result, foreground = self.color.get())
428        self.resultValue.grid(row = 15, column = 1, pady = 10, columnspan = 2)
429
430        self.notesLabel = Label(self.frame, textvariable = self.notesTitle)
431        self.notesLabel.grid(row = 14, column = 3, pady = 0, columnspan = 2)
432
433        self.notesValue = Label(self.frame, textvariable = self.notes)
434        self.notesValue.grid(row = 15, column = 3, pady = 10, columnspan = 2)
435        # --------------------------------------------------
436
437       
438       
439       
440    # This updates the value of the parameter entered in the parameter entry box
441    def updateParameter(self):
442
443        # Determine which parameter the user wants to update
444        par = self.parameterEntry.get()
445
446        # Update the value and determine if the parameter is being changed or added into the list
447        if par.lower() in lower(self.orderedSpecifiedParameters):
448            value2write = self.valueEntry.get()
449            index = lower(self.orderedSpecifiedParameters).index(par.lower())
450            parameter2update = self.orderedSpecifiedParameters[index]
451            self.userSpecifiedParameters[parameter2update] = value2write
452            paramInfo = parameter2update + ': ' + value2write
453            newParamYN = "Updated specified parameter list"
454            self.color.set("Blue")
455        elif par.lower() in lower(self.orderedParameters):
456            index = lower(self.orderedParameters).index(par.lower())
457            parameter2update = self.orderedParameters[index]
458            value2write = self.valueEntry.get()
459            self.userSpecifiedParameters[parameter2update] = value2write
460            paramInfo = parameter2update + ': ' + value2write
461            newParamYN = "Added in specified parameter list"
462            self.color.set("Blue")
463
464            self.orderedSpecifiedParameters = self.orderedSpecifiedParameters + [parameter2update]
465        else:
466            paramInfo = '"' + par + '" does not exist'
467            newParamYN = "-"
468            self.color.set("Red")
469
470        # Store the results from above
471        self.resultTitle.set("Parameter Information")
472        self.result.set(paramInfo)
473        self.notesTitle.set("Notes")
474        self.notes.set(newParamYN)
475
476        # --------------------------------------------------
477        # Windows that correspond to the variables above
478        self.resultLabel = Label(self.frame, textvariable = self.resultTitle)
479        self.resultLabel.grid(row = 14, column = 1, pady = 0, columnspan = 2)
480
481        self.resultValue = Label(self.frame, textvariable = self.result, foreground = self.color.get())
482        self.resultValue.grid(row = 15, column = 1, pady = 10, columnspan = 2)
483
484        self.notesLabel = Label(self.frame, textvariable = self.notesTitle)
485        self.notesLabel.grid(row = 14, column = 3, pady = 0, columnspan = 2)
486
487        self.notesValue = Label(self.frame, textvariable = self.notes)
488        self.notesValue.grid(row = 15, column = 3, pady = 10, columnspan = 2)
489        # --------------------------------------------------
490
491        # Update the effective parameters
492        self.effectiveParameters.update(self.defaultParameters) # In case default wasn't loaded before
493        self.effectiveParameters.update(self.userSpecifiedParameters)
494       
495
496        self.listParameters("Specified")
497
498    def checkParameterWithDescription(self):
499       
500        self.checkParameter()
501        self.showDescription()
502
503    def checkParameterEvent(self, event):
504
505        self.checkParameterWithDescription()
506
507    def updateParameterEvent(self, event):
508
509        self.updateParameter()
510       
511
512    # This displays a description of the parameter entered in the parameter entry box
513    def showDescription(self):
514
515        # Determine which parameter to describe
516        par = self.parameterEntry.get()
517
518        # Determine if the parameter is within the description file
519        if par.lower() in lower(self.orderedParameters):
520            index = lower(self.orderedParameters).index(par.lower())
521            parameter2describe = self.orderedParameters[index]           
522            description = self.description[parameter2describe]
523        else:
524            parameter2describe = par
525            description = "No description available"
526
527        # Create the description
528        self.descriptionList = Listbox(self.frame, width = longestLineLength(self.defaultParameters) + 5, font = ('courier', (10)))
529        self.descriptionList.grid(row = 30, column = 1, columnspan = 4)
530
531        try:
532            self.descriptionList.insert(END, "Description of '" + parameter2describe + "'")
533            self.descriptionList.insert(END, "Class: " + self.classOfParameter[parameter2describe])
534            self.descriptionList.insert(END, "Type: " + self.paramType[parameter2describe])
535            self.descriptionList.insert(END, "Format: " + self.paramFormat[parameter2describe])
536            self.descriptionList.insert(END, " ")
537           
538        except KeyError:
539            self.descriptionList.delete(0, END)
540            self.descriptionList.insert(END, "Please Enter a parameter")
541            return
542       
543
544        descriptionWords = description.split()
545
546        largestWordLength = 0
547
548        for word in descriptionWords:
549            if len(word) > largestWordLength:
550                largestWordLength = len(word)
551        b = 0
552
553        for i in range(len(descriptionWords)):
554                           
555            phrase = ' '.join(descriptionWords[b:i])
556                           
557            if len(phrase) > longestLineLength(self.defaultParameters) - largestWordLength:
558                line = phrase
559
560                self.descriptionList.insert(END, line) 
561                b = i
562
563        self.descriptionList.insert(END, ' '.join(descriptionWords[b:]))
564       
565    def revertDefault(self):
566
567        # Determine which parameter the user wants to revert
568        parameter2revert = self.parameterEntry.get()
569
570        finalValue = self.defaultParameters.get(parameter2revert, "N/A")
571        paramInfo = parameter2revert + ': ' + finalValue
572
573        # Revert the value and determine if the parameter was already default
574        if parameter2revert in self.userSpecifiedParameters:
575
576            del(self.userSpecifiedParameters[parameter2revert])
577            self.orderedSpecifiedParameters.remove(parameter2revert)
578            alreadyDefaultYN = "Reverted back to default"
579            self.color.set("Sky Blue")
580        elif parameter2revert in self.defaultParameters:
581
582            alreadyDefaultYN = "Already default"
583            self.color.set("Sky Blue")
584        else:
585            paramInfo = '"' + parameter2revert + '" does not exist'
586            alreadyDefaultYN = "-"
587            self.color.set("Red")
588
589        # Store the results from above
590        self.resultTitle.set("Parameter Information")
591        self.result.set(paramInfo)
592        self.notesTitle.set("Notes")
593        self.notes.set(alreadyDefaultYN)
594
595        self.valueEntry.delete(0, END)
596        self.valueEntry.insert(0, finalValue)
597
598        # --------------------------------------------------
599        # Windows that correspond to the variables above
600        self.resultLabel = Label(self.frame, textvariable = self.resultTitle)
601        self.resultLabel.grid(row = 14, column = 1, pady = 0, columnspan = 2)
602
603        self.resultValue = Label(self.frame, textvariable = self.result, foreground = self.color.get())
604        self.resultValue.grid(row = 15, column = 1, pady = 10, columnspan = 2)
605
606        self.notesLabel = Label(self.frame, textvariable = self.notesTitle)
607        self.notesLabel.grid(row = 14, column = 3, pady = 0, columnspan = 2)
608
609        self.notesValue = Label(self.frame, textvariable = self.notes)
610        self.notesValue.grid(row = 15, column = 3, pady = 10, columnspan = 2)
611        # --------------------------------------------------
612
613        # Update the effective parameters
614        self.effectiveParameters.update(self.defaultParameters) # In case default wasn't loaded before
615        self.effectiveParameters.update(self.userSpecifiedParameters)
616       
617
618        self.listParameters("Specified")
619    # This displays a list of parameters
620    def listParameters(self, parameterSet):
621
622        paramOrder = self.orderedParameters
623       
624        if parameterSet == "Default":
625            self.parameters = self.defaultParameters
626        elif parameterSet == "Specified":
627            self.parameters = self.userSpecifiedParameters
628            paramOrder = self.orderedSpecifiedParameters
629        elif parameterSet == "Effective":
630            self.parameters = self.effectiveParameters
631        elif parameterSet == "Class":
632            self.effectiveParameters.update(self.defaultParameters) # In case default wasn't loaded before
633            self.effectiveParameters.update(self.userSpecifiedParameters)
634            self.parameters = self.effectiveParameters
635            className = self.whichClass.get()
636        else:
637            print("Coding Error: Used wrong parameter set.")
638            return
639
640        # If the list is empty, it means we haven't loaded it yet
641        if self.parameters == {}:
642           
643            self.createNoticeBox1(title = "Notice", message = "No " + parameterSet + " Parameter File Loaded", command = self.noUpdate, buttonText = "Okay")
644
645        # Otherwise we can print it using the specified format
646        else:
647
648
649            self.paramListScrollBar = Scrollbar(self.frame)
650            self.paramListScrollBar.grid(row = 30, column = 5, ipady = 65)
651           
652            self.parameterList = Listbox(self.frame, yscrollcommand = self.paramListScrollBar.set, width = longestLineLength(self.defaultParameters) + 5, font = ('courier', (10)))
653            self.parameterList.grid(row = 30, column = 1, columnspan = 4)
654
655            if parameterSet == "Class":
656                self.parameterList.insert(END, className)
657            else:
658                self.parameterList.insert(END, parameterSet + " set of Parameters")
659               
660            self.parameterList.insert(END, " ")
661
662            star = 0
663
664            for par in paramOrder:
665
666                if parameterSet == "Effective":
667                    if par in self.userSpecifiedParameters:
668                        star = 1
669                    else:
670                        star = 0
671                       
672                if parameterSet == "Class":
673
674                    if self.classOfParameter[par] == className:
675
676                        if par in self.userSpecifiedParameters:
677                            star = 1
678                        else:
679                            star = 0
680
681                        tabbedPar = tabbedDictionaryLine(self.parameters, par, star)
682                        self.parameterList.insert(END, tabbedPar + self.parameters[par])
683                   
684                else:
685                    tabbedPar = tabbedDictionaryLine(self.parameters, par, star)
686                    self.parameterList.insert(END, tabbedPar + self.parameters[par])
687
688                   
689
690            self.paramListScrollBar.config(command = self.parameterList.yview)
691
692            self.list2read = self.parameterList
693            self.parameterList.bind("<ButtonRelease-1>", self.checkItem)
694            self.parameterList.bind("<ButtonRelease-3>", self.checkItemDescript)
695            self.parameterList.bind("<Return>", self.checkItemDescript)
696
697
698    def checkItem(self, event):
699
700        self.doCheckItem(0)
701
702    def checkItemDescript(self, event):
703
704        self.doCheckItem(1)
705
706    def doCheckItem(self, describeFlag):
707
708        try:
709            if int(self.list2read.curselection()[0]) != 0:
710
711                line = self.list2read.get(self.list2read.curselection())
712                linebits = line.split()
713                parameter = linebits[0]
714
715                self.parameterEntry.delete(0, END)
716                self.parameterEntry.insert(0, parameter)
717
718                if describeFlag == 0:
719                    self.checkParameter()
720                elif describeFlag == 1:
721                    self.checkParameterWithDescription()
722                else:
723                    print("Coding Error: Describe flag not binary")
724                   
725        except IndexError:
726            pass
727       
728
729       
730       
731
732           
733       
734    def createInputInterface(self):
735
736        self.file_opt = options = {}
737        options['defaultextension'] = '.txt'
738        options['filetypes'] = [('text files', '.txt'), ('all files', '.*')]
739        options['initialdir'] = os.getcwd
740        options['initialfile'] = 'duchampHIPASS.txt'
741        options['parent'] = self.frame
742        options['title'] = 'Load Parameter File'
743
744        self.userSpecifiedFilePath = tkFileDialog.askopenfilename(**self.file_opt)
745
746        self.userSpecifiedFileName = self.userSpecifiedFilePath.split('/')[-1]
747        self.updateInputFile()
748       
749
750    def createSpecifiedOutputInterface(self):
751       
752        self.file_opt = options = {}
753        options['defaultextension'] = '.txt'
754        options['filetypes'] = [('text files', '.txt'), ('all files', '.*')]
755        options['initialdir'] = os.getcwd
756        options['initialfile'] = self.userSpecifiedFileName.split('.')[0] + 'Edited.' + self.userSpecifiedFileName.split('.')[1]
757        options['parent'] = self.frame
758        options['title'] = 'Save User Specified Parameters'
759
760        self.newFilePath = tkFileDialog.asksaveasfilename(**self.file_opt)
761
762        writeParamFile(self.newFilePath, self.userSpecifiedParameters, self.orderedSpecifiedParameters, 1)
763       
764    def createEffectiveOutputInterface(self):
765       
766        self.file_opt = options = {}
767        options['defaultextension'] = '.txt'
768        options['filetypes'] = [('text files', '.txt'), ('all files', '.*')]
769        options['initialdir'] = os.getcwd
770        options['initialfile'] = self.userSpecifiedFileName.split('.')[0] + 'AllEdited.' + self.userSpecifiedFileName.split('.')[1]
771        options['parent'] = self.frame
772        options['title'] = 'Save List of Effective Parameters'
773
774        self.newFilePath = tkFileDialog.asksaveasfilename(**self.file_opt)
775
776        writeParamFile(self.newFilePath, self.effectiveParameters, self.orderedParameters, 1)
777       
778
779
780    # This decides whether to load or update the input files for default and specified parameters
781    def updateInputFile(self):
782
783        try:
784            fin = open(self.userSpecifiedFilePath, 'r')
785            fin.close()
786           
787            # If the list is empty, that means we are loading the file for the first time
788            if self.userSpecifiedParameters == {}:
789
790                self.createNoticeBox1(title = "Notice", message = "Input Files Loaded", command = self.yesUpdate , buttonText = "Okay")
791
792            # If the list is non-empty, this means we risk rewritting any edits we have made
793            else:
794
795                msg = "Are you sure? Any edits you've made in the previous session will be lost and replaced with the contents of the new files."
796                self.createNoticeBox2(title = "Notice", message = msg, command1 = self.yesUpdate, command2 = self.noUpdate, buttonText1 = "Yes", buttonText2 = "No")
797        except IOError:
798            pass
799        except TypeError:
800            pass
801            print("TypeError")
802       
803    # This loads or updates the input files for default and specified parameters
804    def yesUpdate(self):
805
806        # The notice box can go away
807        self.noticeBox.destroy()
808
809        # Then we can determine the list of specified and effective parameters
810        (self.userSpecifiedParameters, self.orderedSpecifiedParameters) = readParamFile(self.userSpecifiedFilePath)
811        self.effectiveParameters.update(self.userSpecifiedParameters)
812       
813        messages = []
814       
815        # If the file is empty, let the user know.
816        if self.userSpecifiedParameters == {}:
817
818            messages += ["The file you loaded is empty. Parameter file discarded."]
819           
820
821        else:
822            self.listParameters("Specified")
823
824            for par in self.orderedSpecifiedParameters:
825
826                if par not in self.defaultParameters:
827
828                    messages += ["Some parameters loaded are not part of the default set of parameters."]
829                    break
830
831        fin = open(self.userSpecifiedFilePath)
832
833        for line in fin:
834
835            if line[0] != '#' and len(line) > 1 and len(line.split()) > 1:
836
837                if len(line.split()) != 2:
838
839                    messages += ["File loaded has the wrong format. Loaded inputs may be incorrect."]
840                    break
841
842        fin.close()
843
844        for msg in messages:
845
846            self.createNoticeBox1(title = "Notice", message = msg, command = self.noUpdate, buttonText = "Dismiss")
847               
848
849       
850    def noUpdate(self):
851
852        self.noticeBox.destroy()
853       
854
855    def createNoticeBox1(self, title, message, command, buttonText = "Dismiss"):
856       
857        self.noticeBox = Toplevel(width = 200, borderwidth = 20)
858        self.noticeBox.title(title)
859       
860        self.noticeMsg = Message(self.noticeBox, text = message)
861        self.noticeMsg.grid(row = 1, column = 1, columnspan = 2)
862       
863        self.noticeBoxButton = Button(self.noticeBox, text = buttonText, command = command)
864        self.noticeBoxButton.grid(row = 2, column = 1, pady = 5, columnspan = 2)
865
866
867    def createNoticeBox2(self, title, message, command1, command2, buttonText1 = "Yes", buttonText2 = "No"):
868
869        self.noticeBox = Toplevel(width = 200, borderwidth = 20)
870        self.noticeBox.title(title)
871       
872        self.noticeMsg = Message(self.noticeBox, text = message)
873        self.noticeMsg.grid(row = 1, column = 1, columnspan = 2)
874       
875        self.noticeBoxButton1 = Button(self.noticeBox, text = buttonText1, command = command1)
876        self.noticeBoxButton1.grid(row = 2, column = 1, pady = 5)
877       
878        self.noticeBoxButton2 = Button(self.noticeBox, text = buttonText2, command = command2)
879        self.noticeBoxButton2.grid(row = 2, column = 2, pady = 5)       
880
881   
882
883
884
885
886
887
888
889def main():
890    root = Tk()
891    root.wm_title("Duchamp Parameters")
892
893    interface = mainInterface(root)
894
895    root.config(menu = interface.menubar)
896   
897    root.mainloop()
898
899    try:
900        root.destroy()
901    except TclError:
902        pass
903
904#-------------------------------------------------------------------------------
905
906if __name__ == '__main__':
907    main()
Note: See TracBrowser for help on using the repository browser.