forked from ngloria1/PropSim
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Functional to print out PropSim data, and validate units. Doesn't ch…
…ange EntryVAr color when unit is bad, and only has SimulateLiquid atm.
- Loading branch information
Showing
24 changed files
with
1,249 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
# Compiled source # | ||
################### | ||
*.com | ||
*.class | ||
*.dll | ||
*.exe | ||
*.o | ||
*.so | ||
|
||
# Pycaches # | ||
############ | ||
__pycache__/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,32 @@ | ||
; Name diameter(mm) Length(mm) delay propellant_weight(kg) mass(kg) | ||
O31100-I 143 2438 P 17.09 29.03 SSI | ||
0.010 16.636 | ||
0.560 3829.721 | ||
1.110 3760.421 | ||
1.670 3696.314 | ||
2.220 3629.055 | ||
2.770 3565.833 | ||
3.320 3499.594 | ||
3.870 3431.874 | ||
4.420 3364.197 | ||
4.980 3298.928 | ||
5.530 3232.819 | ||
6.080 3160.431 | ||
6.630 3093.359 | ||
7.180 3024.405 | ||
7.730 2953.992 | ||
8.290 2878.338 | ||
8.840 2450.623 | ||
9.390 866.595 | ||
9.940 593.645 | ||
10.490 377.097 | ||
11.040 206.774 | ||
11.600 90.791 | ||
12.150 54.471 | ||
12.700 111.568 | ||
13.250 65.152 | ||
13.800 23.593 | ||
14.350 8.281 | ||
14.910 11.829 | ||
15.460 10.580 | ||
16.010 0.000 | ||
O6900-I 143 2438 P 3.85 15.79 SSI | ||
0.010 1320.418 | ||
0.200 1561.631 | ||
0.400 1546.229 | ||
0.590 1531.306 | ||
0.790 1516.129 | ||
0.980 1500.406 | ||
1.180 1482.341 | ||
1.370 1466.933 | ||
1.570 1451.104 | ||
1.760 1434.491 | ||
1.960 1417.684 | ||
2.150 1401.527 | ||
2.350 1384.385 | ||
2.540 1368.230 | ||
2.740 1352.983 | ||
2.930 1337.996 | ||
3.130 1322.032 | ||
3.320 1307.148 | ||
3.520 1290.261 | ||
3.710 1275.134 | ||
3.910 1259.703 | ||
4.100 1245.385 | ||
4.300 1230.102 | ||
4.490 1215.732 | ||
4.690 1200.258 | ||
4.880 490.540 | ||
5.080 428.407 | ||
5.270 376.835 | ||
5.470 329.905 | ||
5.655 0.000 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from PythonLib.MainWindow import MainWindow | ||
|
||
if __name__ == '__main__': | ||
mainwindow = MainWindow() # construct the MainWindow | ||
mainwindow.run() # run the MainWindow |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
''' | ||
EntryVar: | ||
An InputVar class for a string-input value. Implements conversions to baseunit from the string-parsed unit before sending to MATLAB | ||
(assumes that the input unit has already been validated). | ||
The ToggleVar has two additional optional argument: linkedvars and disableon. If linkedvars is a list of InputVar items, | ||
those items will be disabled whenever the ToggleVar is in the disableon state. | ||
''' | ||
|
||
import tkinter as tk | ||
import tkinter.ttk as ttk | ||
from .InputVar import InputVar | ||
from .units import units | ||
|
||
class EntryVar(InputVar): | ||
def __init__(self, name, defaultval, baseunit, structname = None, description = ''): | ||
super().__init__(name, defaultval, baseunit, structname, description) # use parent constructor | ||
|
||
self.numeric_val = None # the numeric value parsed from the input string, set in self.parse_value | ||
self.parsed_unit = None # the unit parsed from the input string, set in self.parse_value | ||
|
||
def get(self): | ||
''' Accesses the current value of self.var and returns it. ''' | ||
return self.var.get() | ||
|
||
def put(self, val): | ||
''' Set current value of self.var. ''' | ||
self.var.set(val) | ||
|
||
def get_type(self): | ||
''' Return the base type of this input var. ''' | ||
return self.baseunit | ||
|
||
def build(self, matlabeng): | ||
''' Build this variable in the MATLAB engine's workspace. ''' | ||
if self.numeric_val is None: | ||
myval = 0 # if entry is disabled, just plug in a dummy value (won't matter) | ||
else: | ||
myval = units.convert(self.numeric_val, self.parsed_unit, self.baseunit) # convert to baseunit | ||
matlabeng.eval(self.structname + '.' + self.name + '=' + str(myval) + ' ;', nargout = 0) # use eval to make struct variable in MATLAB workspace | ||
|
||
def makewidget(self, parent): | ||
''' Create the tk widget for this input, using parent as the parent widget. ''' | ||
self.var = tk.StringVar(parent, self.defaultval) # a Tk variable storing current status of this variable | ||
self.widget = ttk.Entry(parent, style = 'EntryVar.TEntry', textvariable=self.var, validate='focus', validatecommand=lambda *a: 'invalid' not in self.widget.state()) | ||
self.widget.bind("<FocusOut>", lambda e: self.validate()) | ||
self.widget.bind("<FocusIn>", lambda e: self.on_entry()) | ||
|
||
def validate(self): | ||
''' Parse the user input, separating it into a value and a unit. Set the self.numeric_val and self.parsed_unit vars based on findings. ''' | ||
# basic string format is <value> [<unit>] or just <value>. Handle both cases: | ||
if 'disabled' in self.widget.state(): | ||
return True # if entry is disabled, don't bother validating | ||
splitstr = self.get() | ||
splitstr = splitstr.strip('] ') # remove closing brace and leading/trailing whitespace | ||
splitstr = splitstr.split('[') # split into a list | ||
try: | ||
self.numeric_val = float(splitstr[0].strip()) | ||
except: | ||
self.set_err() | ||
return "Error: Variable " + self.name + " has a non-float value: " + self.splitstr[0] | ||
if len(splitstr) > 1: # if a unit was included | ||
if units.validate_units(splitstr[1].strip(), self.baseunit): | ||
self.parsed_unit = splitstr[1] | ||
return True | ||
else: | ||
self.set_err() | ||
return "Error: Variable " + self.name + " has a unit incompatible with the base unit. \n" + "\t Base unit is [" + self.baseunit + "] and compatible units are: " + ', '.join(units.get_compatible_units(self.baseunit)) | ||
else: | ||
self.parsed_unit = self.baseunit # if no unit was provided, assume the base unit | ||
return True # if you got here, you're good | ||
|
||
def set_err(self): | ||
''' Change the style to reflect that an error was found during parsing. ''' | ||
self.widget.state(['invalid']) | ||
|
||
def on_entry(self): | ||
''' Change the style back to the default when the user clicks in this entry. This stops error color-changes from being permanent. ''' | ||
self.widget.state(['!invalid']) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
''' | ||
GasVar: | ||
An InputVar class for a Gas object (see the Matlab code for Gas.m in Supporting Files). Users select from a dropdown of defined | ||
gases. To add gases, they must be manually included in the gas_library dict below. | ||
TODO: Add more common gases! | ||
''' | ||
|
||
import tkinter as tk | ||
import tkinter.ttk as ttk | ||
from .InputVar import InputVar | ||
|
||
# gases available in GasVar dropdown - cv is in J/kg/K, molecular mass in kg/mol | ||
gas_library = {'nitrogen' :{'c_v': 743.0, 'molecular_mass':0.0280134}, | ||
'helium' :{'c_v':3.12, 'molecular_mass': 0.0040026} | ||
} | ||
|
||
class GasVar(InputVar): | ||
def __init__(self, name, defaultval, baseunit='gas', structname = None, description = ''): | ||
super().__init__(name, defaultval, baseunit, structname, description) # use parent constructor | ||
|
||
def get(self): | ||
''' Accesses the current value of self.var and returns it. ''' | ||
return self.var.get() | ||
|
||
def put(self, val): | ||
''' Set current value of self.var. ''' | ||
self.var.set(val) | ||
|
||
def get_type(self): | ||
''' Return the base type of this input var. ''' | ||
return self.baseunit | ||
|
||
def build(self, matlabeng): | ||
''' Build this variable in the MATLAB engine's workspace. ''' | ||
''' NOTE: This assumes that a Pressurant object has already been created and assigned to the struct name. ''' | ||
mygas = self.get() # get the name of the gas from the gas library to be used | ||
matlabeng.eval(self.name+' = Gas();' ,nargout=0) # create gas object | ||
matlabeng.eval(self.name+'.c_v = ' + str(gas_library[mygas]['c_v']) + ' ;', nargout=0) | ||
matlabeng.eval(self.name+'.molecular_mass = ' + str(gas_library[mygas]['molecular_mass']) + ' ;', nargout=0) | ||
matlabeng.eval(self.structname+'.gas_properties = '+self.name+' ;', nargout=0) | ||
|
||
def makewidget(self, parent): | ||
''' Create the tk widget for this input, using parent as the parent widget. ''' | ||
self.var = tk.StringVar(parent, self.defaultval) # a Tk variable storing current status of this variable (0/False is off, 1/True is on) | ||
self.widget = ttk.OptionMenu(parent, self.var, self.defaultval, *(gas_library.keys())) # create dropdown of gas names | ||
|
||
def validate(self): | ||
''' Determine if the selection is valid. ''' | ||
if self.get() in gas_library.keys(): # should always be true, as the user has selected from a dropdown | ||
return True | ||
else: | ||
return "You have selected an invalid gas for " + self.name |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
''' | ||
InputPane: | ||
A ttk.Notebook of SimPages, allowing the user to switch between which MATLAB function they want to use. | ||
If a page has a solution, users will be asked if they wish to save before switching tabs using SimPage.promptforsave() . | ||
This class also owns the Save and Save As methods, and directs them to the appropriate SimPage based on which is selected. | ||
''' | ||
|
||
import tkinter as tk | ||
import tkinter.ttk as ttk | ||
|
||
class InputPane(ttk.Notebook): | ||
def __init__(self, mainframe, mainwindow, matlabeng, simpages): | ||
super().__init__(mainframe) | ||
self.mainframe = mainframe | ||
self.mainwindow = mainwindow | ||
self.matlabeng = matlabeng | ||
self.simpages = simpages | ||
|
||
self.curr_tab = 0 # index of current tab | ||
|
||
for page in simpages: | ||
page.makewidget(self, self.matlabeng) # create each SimPage with self as the parent | ||
self.add(page, text = page.name) # create a tab for this frame, with name as the tab name | ||
|
||
#self.bind("<<NotebookTabChanged>>", lambda event: self.ontabchange() ) | ||
|
||
def promptsave_sim(self): | ||
self.simpages[self.curr_tab].promptforsave(self.matlabeng) | ||
|
||
def save_sim(self): | ||
self.simpages[self.curr_tab].saveworkspace(self.matlabeng) | ||
|
||
def saveas_sim(self): | ||
self.simpages[self.curr_tab].saveworkspaceas(self.matlabeng) | ||
|
||
def ontabchange(self): | ||
if self.simpages[self.curr_tab].promptforsave(self.matlabeng): # prompt for SimPage save on the tab you're switching from | ||
self.curr_tab = self.index(self.select()) # if saved or rejected option, set new tab | ||
else: | ||
self.select(self.curr_tab) # if canceled or closed window, go back to previous tab |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
''' | ||
InputVar: | ||
An abstract base class containing information about an input variable. Input variables have the following properties: | ||
- a name, corresponding to the name of the matlab variable they modify | ||
- a widget, corresponding to a tK widget object created on init | ||
- a value, which can be retrieved using the get() function or set using put() (initially set to a user-defined default) | ||
- a baseunit, which is either a unit string (e.g. 'kg', 'ft', or 'psi') indicating the unit of the MATLAB var, 'boolean', 'file', or 'gas', accessed with get_type() | ||
- a struct name, corresponding to which struct in MATLAB this variable belongs (None or '' means the variable isn't part of a struct) | ||
In addition to the methods described above, InputVars should have a build(matlabeng) function that constructions that variable in the workspace | ||
of the matlab engine passed as a function argument. They should also have a makewidget(parent) function that constructs a tkinter widget, using the | ||
passed argument as the parent widget. Finally, inheritors should have a validate() function that confirms if the user input for that value is consistent | ||
(return a string describing the err if not). | ||
All children inherit the function make_tooltip(widget), which creates a tooltip linked to the widget passed as an argument. When users hover their mouse over | ||
that widget, a pop-up window appears providing a description of that InputVar. | ||
''' | ||
from .ToolTip import ToolTip | ||
|
||
MAX_TOOLTIP_LINELEN = 40 | ||
|
||
class InputVar(): | ||
def __init__(self, name, defaultval, baseunit, structname = None, description = ''): | ||
self.name = name | ||
self.defaultval = defaultval | ||
self.baseunit = baseunit | ||
self.structname = structname | ||
self.description = description | ||
self.var = None # a Tk variable storing current status of this variable | ||
self.widget = None # a Tk widget | ||
self.tooltip = None # a Tooltip object, initialized with maketooltip() | ||
|
||
def get(self): | ||
''' Accesses the current value of self.var and returns it. ''' | ||
raise NotImplementedError() | ||
|
||
def put(self, val): | ||
''' Set current value of self.var. ''' | ||
raise NotImplementedError() | ||
|
||
def get_type(self): | ||
''' Return the base type of this input var. ''' | ||
return self.baseunit | ||
|
||
def build(self, matlabeng): | ||
''' Build this variable in the MATLAB engine's workspace. ''' | ||
raise NotImplementedError() | ||
|
||
def makewidget(self, parent): | ||
''' Create the tk widget for this input, using parent as the parent widget. ''' | ||
raise NotImplementedError() | ||
|
||
def validate(self): | ||
''' Confirm whether the user input is valid or not. ''' | ||
raise NotImplementedError() | ||
|
||
def maketooltip(self, tip_widget): | ||
''' Create a tooltip that is linked to a tip_widget. ''' | ||
if self.get_type().lower() not in ('gas','boolean','file'): | ||
descrip_str = self.name + ' ( unit: [' + self.get_type() + '] )\n' | ||
else: | ||
descrip_str = self.name + ' ( type: ' + self.get_type() + ' )\n' | ||
descrip_str += '-'*len(descrip_str)+ '\n' | ||
split_desc = self.description.split(' ') # split description by spaces | ||
curr_line_len = 0 | ||
while split_desc: # while words remain in list | ||
nextword = split_desc.pop(0) | ||
if curr_line_len + len(nextword) < MAX_TOOLTIP_LINELEN: | ||
descrip_str += ' ' + nextword # if room on line, add next word (with space before it) | ||
curr_line_len += len(nextword) | ||
else: | ||
descrip_str += '\n' # if no room on line, end line | ||
descrip_str += nextword # add word | ||
curr_line_len = len(nextword) # line is now this long | ||
|
||
self.tooltip = ToolTip(tip_widget, descrip_str) # use ToolTip constructor |
Oops, something went wrong.