''' This module contains class WeightFrame that is used as a tab in
parameters frame to edit and display weights.
'''
from tkinter.ttk import Button, Frame, LabelFrame
from tkinter import N, W, S, E
from pyDEA.core.utils.dea_utils import create_bounds
from pyDEA.core.gui_modules.text_for_weights_gui import TextForWeights
from pyDEA.core.gui_modules.scrollable_frame_gui import VerticalScrolledFrame
[docs]class WeightFrame(Frame):
''' This class represents weights editor. It allows to display, modify
and validate weights.
Attributes:
parent (Tk object): parent of this widget.
current_categories (list of str): list of current categories,
this list is not modified by this class.
params (Parameters): Parameters object with all parameter values.
Note:
This class does not change values in Parameters object
until the weight
restrictions are validated, see on_validate_weights().
weights_status_str (StringVar): StringVar object that is used
to show an error if it occurred after validating weights.
abs_weights (TextForWeights): text widget for displaying and editing
absolute weight restrictions.
virtual_weights (TextForWeights): text widget for displaying and
editing virtual weight restrictions.
price_ratio_weights (TextForWeights): text widget for displaying and
editing price-ratio weight restrictions.
Args:
parent (Tk object): parent of this widget.
current_categories (list of str): list of current categories,
this list is not modified by this class.
params (Parameters): Parameters object with all parameter values
weights_status_str (StringVar): StringVar object that is used to
show an error if it occurred after validating weights.
'''
def __init__(self, parent, current_categories, params, weights_status_str,
*args, **kw):
super().__init__(parent, *args, **kw)
self.parent = parent
self.current_categories = current_categories
self.params = params
self.weights_status_str = weights_status_str
self.abs_weights = None
self.virtual_weights = None
self.price_ratio_weights = None
self.create_widgets()
[docs] def add_weights(self):
''' Adds weight restrictions stored in params to the appropriate
text widgets if such weight restrictions can be parsed and
contain categories that are also present in current_categories.
'''
self.remove_all_weights()
self._add_given_weights(self.abs_weights, 'ABS_WEIGHT_RESTRICTIONS')
self._add_given_weights(self.virtual_weights,
'VIRTUAL_WEIGHT_RESTRICTIONS')
self._add_given_weights(self.price_ratio_weights,
'PRICE_RATIO_RESTRICTIONS')
def _add_given_weights(self, text_widget, weights_name):
''' Adds given weight restrictions to a given text widget.
Args:
text_widget (TextForWeights): text widget where weight
restrictions will be added.
weights_name (str): name of the parameter that stores weight
restrictions in params.
Example:
If currently parameters contain absolute weight
restrictions "I1 >= 0.1", then we can add this constraint to the
text widget as follows:
>>> self._add_given_weights(self.abs_weights,
'ABS_WEIGHT_RESTRICTIONS')
'''
weights = self.params.get_set_of_parameters(weights_name)
weights_were_added = False
if weights:
for weight in weights:
weight_as_list = []
weight_as_list.append(weight)
try:
create_bounds(weight_as_list, self.current_categories)
except ValueError:
pass # everything that we cannot parse is ignored
else:
text_widget.insert_weight(weight)
weights_were_added = True
if weights_were_added:
self.parent.change_weight_tab_name('Weights editor*')
[docs] def remove_all_weights(self):
''' Removes all weight restrictions from all text widgets.
Note:
Parameters object is not affected by this. All weight
restrictions will still be there. Parameters are updated
only when they are validated,
i.e. when the user presses validate weights button or run
button.
'''
self.parent.change_weight_tab_name('Weights editor')
self.weights_status_str.set('')
self.abs_weights.delete_weights()
self.virtual_weights.delete_weights()
self.price_ratio_weights.delete_weights()
[docs] def on_validate_weights(self):
''' Validates weights of all text widgets and displays an error if
some of the weights are invalid.
Note:
Parameters object is modified by this method.
'''
abs_weights_present = self.abs_weights.validate_weights()
virtual_weights_present = self.virtual_weights.validate_weights()
price_ratio_weights_present = self.price_ratio_weights.validate_weights()
if (self.abs_weights.error_tag_exists or
self.virtual_weights.error_tag_exists or
self.price_ratio_weights.error_tag_exists):
self.weights_status_str.set(
'Some of the weight restrictions cannot be parsed. \n'
'For error details, see Weights editor tab.')
else:
self.weights_status_str.set('')
if (abs_weights_present or virtual_weights_present or
price_ratio_weights_present):
self.parent.change_weight_tab_name('Weights editor*')
else:
self.parent.change_weight_tab_name('Weights editor')