Skip to content

Commit 7f9ef92

Browse files
author
Ezequiel Torres
committed
Added Common folder not included in last commit
1 parent 39d7515 commit 7f9ef92

File tree

3 files changed

+373
-0
lines changed

3 files changed

+373
-0
lines changed

MLC/GUI/Common/QtWaitingSpinner.py

Lines changed: 222 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
"""
2+
The MIT License (MIT)
3+
4+
Copyright (c) 2012-2014 Alexander Turkin
5+
Copyright (c) 2014 William Hallatt
6+
Copyright (c) 2015 Jacob Dawid
7+
Copyright (c) 2016 Luca Weiss
8+
9+
Permission is hereby granted, free of charge, to any person obtaining a copy
10+
of this software and associated documentation files (the "Software"), to deal
11+
in the Software without restriction, including without limitation the rights
12+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13+
copies of the Software, and to permit persons to whom the Software is
14+
furnished to do so, subject to the following conditions:
15+
16+
The above copyright notice and this permission notice shall be included in all
17+
copies or substantial portions of the Software.
18+
19+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25+
SOFTWARE.
26+
"""
27+
28+
import math
29+
30+
from PyQt5.QtCore import *
31+
from PyQt5.QtGui import *
32+
from PyQt5.QtWidgets import *
33+
34+
35+
class QtWaitingSpinner(QWidget):
36+
37+
def __init__(self, parent, centerOnParent=True, disableParentWhenSpinning=False, modality=Qt.NonModal):
38+
QWidget.__init__(self, parent)
39+
40+
self._centerOnParent = centerOnParent
41+
self._disableParentWhenSpinning = disableParentWhenSpinning
42+
43+
# WAS IN initialize()
44+
self._color = QColor(Qt.black)
45+
self._roundness = 100.0
46+
self._minimumTrailOpacity = 3.14159265358979323846
47+
self._trailFadePercentage = 80.0
48+
self._revolutionsPerSecond = 1.57079632679489661923
49+
self._numberOfLines = 20
50+
self._lineLength = 10
51+
self._lineWidth = 2
52+
self._innerRadius = 10
53+
self._currentCounter = 0
54+
self._isSpinning = False
55+
56+
self._timer = QTimer(self)
57+
self._timer.timeout.connect(self.rotate)
58+
self.updateSize()
59+
self.updateTimer()
60+
self.hide()
61+
# END initialize()
62+
63+
self.setWindowModality(modality)
64+
self.setAttribute(Qt.WA_TranslucentBackground)
65+
66+
def paintEvent(self, QPaintEvent):
67+
self.updatePosition()
68+
painter = QPainter(self)
69+
painter.fillRect(self.rect(), Qt.transparent)
70+
painter.setRenderHint(QPainter.Antialiasing, True)
71+
72+
if self._currentCounter >= self._numberOfLines:
73+
self._currentCounter = 0
74+
75+
painter.setPen(Qt.NoPen)
76+
for i in range(0, self._numberOfLines):
77+
painter.save()
78+
painter.translate(
79+
self._innerRadius + self._lineLength, self._innerRadius + self._lineLength)
80+
rotateAngle = float(360 * i) / float(self._numberOfLines)
81+
painter.rotate(rotateAngle)
82+
painter.translate(self._innerRadius, 0)
83+
distance = self.lineCountDistanceFromPrimary(
84+
i, self._currentCounter, self._numberOfLines)
85+
color = self.currentLineColor(
86+
distance, self._numberOfLines, self._trailFadePercentage,
87+
self._minimumTrailOpacity, self._color)
88+
painter.setBrush(color)
89+
painter.drawRoundedRect(
90+
QRect(0, -self._lineWidth / 2, self._lineLength,
91+
self._lineWidth), self._roundness,
92+
self._roundness, Qt.RelativeSize)
93+
painter.restore()
94+
95+
def start(self):
96+
self.updatePosition()
97+
self._isSpinning = True
98+
self.show()
99+
100+
if self.parentWidget and self._disableParentWhenSpinning:
101+
self.parentWidget().setEnabled(False)
102+
103+
if not self._timer.isActive():
104+
self._timer.start()
105+
self._currentCounter = 0
106+
107+
def stop(self):
108+
self._isSpinning = False
109+
self.hide()
110+
111+
if self.parentWidget() and self._disableParentWhenSpinning:
112+
self.parentWidget().setEnabled(True)
113+
114+
if self._timer.isActive():
115+
self._timer.stop()
116+
self._currentCounter = 0
117+
118+
def setNumberOfLines(self, lines):
119+
self._numberOfLines = lines
120+
self._currentCounter = 0
121+
self.updateTimer()
122+
123+
def setLineLength(self, length):
124+
self._lineLength = length
125+
self.updateSize()
126+
127+
def setLineWidth(self, width):
128+
self._lineWidth = width
129+
self.updateSize()
130+
131+
def setInnerRadius(self, radius):
132+
self._innerRadius = radius
133+
self.updateSize()
134+
135+
def color(self):
136+
return self._color
137+
138+
def roundness(self):
139+
return self._roundness
140+
141+
def minimumTrailOpacity(self):
142+
return self._minimumTrailOpacity
143+
144+
def trailFadePercentage(self):
145+
return self._trailFadePercentage
146+
147+
def revolutionsPersSecond(self):
148+
return self._revolutionsPerSecond
149+
150+
def numberOfLines(self):
151+
return self._numberOfLines
152+
153+
def lineLength(self):
154+
return self._lineLength
155+
156+
def lineWidth(self):
157+
return self._lineWidth
158+
159+
def innerRadius(self):
160+
return self._innerRadius
161+
162+
def isSpinning(self):
163+
return self._isSpinning
164+
165+
def setRoundness(self, roundness):
166+
self._roundness = max(0.0, min(100.0, roundness))
167+
168+
def setColor(self, color=Qt.black):
169+
self._color = QColor(color)
170+
171+
def setRevolutionsPerSecond(self, revolutionsPerSecond):
172+
self._revolutionsPerSecond = revolutionsPerSecond
173+
self.updateTimer()
174+
175+
def setTrailFadePercentage(self, trail):
176+
self._trailFadePercentage = trail
177+
178+
def setMinimumTrailOpacity(self, minimumTrailOpacity):
179+
self._minimumTrailOpacity = minimumTrailOpacity
180+
181+
def rotate(self):
182+
self._currentCounter += 1
183+
if self._currentCounter >= self._numberOfLines:
184+
self._currentCounter = 0
185+
self.update()
186+
187+
def updateSize(self):
188+
size = (self._innerRadius + self._lineLength) * 2
189+
self.setFixedSize(size, size)
190+
191+
def updateTimer(self):
192+
self._timer.setInterval(
193+
1000 / (self._numberOfLines * self._revolutionsPerSecond))
194+
195+
def updatePosition(self):
196+
if self.parentWidget() and self._centerOnParent:
197+
self.move(self.parentWidget().width() / 2 - self.width() / 2,
198+
self.parentWidget().height() / 2 - self.height() / 2)
199+
200+
def lineCountDistanceFromPrimary(self, current, primary, totalNrOfLines):
201+
distance = primary - current
202+
if distance < 0:
203+
distance += totalNrOfLines
204+
return distance
205+
206+
def currentLineColor(self, countDistance, totalNrOfLines, trailFadePerc, minOpacity, colorinput):
207+
color = QColor(colorinput)
208+
if countDistance == 0:
209+
return color
210+
minAlphaF = minOpacity / 100.0
211+
distanceThreshold = int(
212+
math.ceil((totalNrOfLines - 1) * trailFadePerc / 100.0))
213+
if countDistance > distanceThreshold:
214+
color.setAlphaF(minAlphaF)
215+
else:
216+
alphaDiff = color.alphaF() - minAlphaF
217+
gradient = alphaDiff / float(distanceThreshold + 1)
218+
resultAlpha = color.alphaF() - gradient * countDistance
219+
# If alpha is out of bounds, clip it.
220+
resultAlpha = min(1.0, max(0.0, resultAlpha))
221+
color.setAlphaF(resultAlpha)
222+
return color

MLC/GUI/Common/__init__.py

Whitespace-only changes.

MLC/GUI/Common/util.py

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
# -*- coding: utf-8 -*-
2+
# MLC (Machine Learning Control): A genetic algorithm library to solve chaotic problems
3+
# Copyright (C) 2015-2017, Thomas Duriez (thomas.duriez@gmail.com)
4+
# Copyright (C) 2015, Adrian Durán (adrianmdu@gmail.com)
5+
# Copyright (C) 2015-2017, Ezequiel Torres Feyuk (ezequiel.torresfeyuk@gmail.com)
6+
# Copyright (C) 2016-2017, Marco Germano Zbrun (marco.germano@intraway.com)
7+
# Copyright (C) 2016-2017, Raúl Lopez Skuba (raulopez0@gmail.com)
8+
#
9+
# This program is free software: you can redistribute it and/or modify
10+
# it under the terms of the GNU General Public License as published by
11+
# the Free Software Foundation, either version 3 of the License, or
12+
# (at your option) any later version.
13+
#
14+
# This program is distributed in the hope that it will be useful,
15+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
# GNU General Public License for more details.
18+
#
19+
# You should have received a copy of the GNU General Public License
20+
# along with this program. If not, see <http://www.gnu.org/licenses/>
21+
22+
import os
23+
import sys
24+
import traceback
25+
26+
from MLC.Common.LispTreeExpr.LispTreeExpr import LispTreeExpr
27+
from MLC.Common.LispTreeExpr.LispTreeExpr import ExprException
28+
from MLC.Common.PreevaluationManager import PreevaluationManager
29+
from MLC.individual.Individual import Individual
30+
from MLC.Log.log import get_gui_logger
31+
from MLC.Population.Evaluation.EvaluatorFactory import EvaluatorFactory
32+
from PyQt5.QtWidgets import QMessageBox
33+
34+
logger = get_gui_logger()
35+
36+
"""
37+
Utilities functions used in more than one class or python module
38+
"""
39+
40+
41+
def test_individual_value(parent, experiment_name, log_prefix, indiv_value, config):
42+
try:
43+
"""
44+
Evaluate an individual in order to check its correctness. Handle Exceptions
45+
"""
46+
LispTreeExpr.check_expression(indiv_value)
47+
individual = Individual.generate(config=config,
48+
rhs_value=indiv_value)
49+
callback = EvaluatorFactory.get_callback()
50+
return callback.cost(individual)
51+
except ExprException, err:
52+
# Print the error message returned in the exception,
53+
# removing the prefix ([EXPR_EXCEPTION]])
54+
QMessageBox.critical(parent,
55+
"Invalid Individual",
56+
"Individual inserted is not well-formed. "
57+
"Error Msg: {0}"
58+
.format(err.message[err.message.find(']') + 2:]))
59+
logger.error("{0} Experiment {1} - "
60+
"Individual inserted is not well-formed. "
61+
"Error Msg: {2}"
62+
.format(log_prefix, experiment_name,
63+
err.message[err.message.find(']') + 2:]))
64+
except Exception, err:
65+
QMessageBox.critical(parent,
66+
"Invalid Evaluation Script",
67+
"Check the evaluation script to be correct. "
68+
"Error Msg: {0}. \n Traceback: {1}"
69+
.format(err, traceback.format_exc()))
70+
71+
logger.error("{0} Experiment {1} - "
72+
"Individual inserted is not a valid individual. "
73+
"Check the evaluation script to be correct. "
74+
"Error Msg: {2}. Traceback:\n{3}"
75+
.format(log_prefix, experiment_name, err, traceback.format_exc()))
76+
77+
return None
78+
79+
80+
def check_individual_value(parent, experiment_name, log_prefix, indiv_value, nodialog=False):
81+
try:
82+
"""
83+
Evaluate an individual in order to check its correctness. Handle Exceptions
84+
"""
85+
LispTreeExpr.check_expression(indiv_value)
86+
return True
87+
except ExprException, err:
88+
# Print the error message returned in the exception,
89+
# removing the prefix ([EXPR_EXCEPTION]])
90+
if not nodialog:
91+
QMessageBox.critical(parent,
92+
"Invalid Individsual",
93+
"Individual inserted is not well-formed. "
94+
"Error Msg: {0}"
95+
.format(err.message[err.message.find(']') + 2:]))
96+
logger.error("{0} Experiment {1} - "
97+
"Individual inserted is not well-formed. "
98+
"Error Msg: {2}"
99+
.format(log_prefix, experiment_name,
100+
err.message[err.message.find(']') + 2:]))
101+
return False
102+
103+
104+
def check_if_indiv_pass_preevaluation(parent, experiment_name, log_prefix, indiv_value, config):
105+
try:
106+
"""
107+
Evaluate an individual in order to check its correctness. Handle Exceptions
108+
"""
109+
LispTreeExpr.check_expression(indiv_value)
110+
individual = Individual.generate(config=config,
111+
rhs_value=indiv_value)
112+
callback = PreevaluationManager.get_callback()
113+
return callback.preev(individual)
114+
except ExprException, err:
115+
# Print the error message returned in the exception,
116+
# removing the prefix ([EXPR_EXCEPTION]])
117+
QMessageBox.critical(parent,
118+
"Invalid Individual",
119+
"Individual inserted is not well-formed. "
120+
"Error Msg: {0}"
121+
.format(err.message[err.message.find(']') + 2:]))
122+
logger.error("{0} Experiment {1} - "
123+
"Individual inserted is not well-formed. "
124+
"Error Msg: {2}"
125+
.format(log_prefix, experiment_name,
126+
err.message[err.message.find(']') + 2:]))
127+
except Exception, err:
128+
QMessageBox.critical(parent,
129+
"Invalid Evaluation Script",
130+
"Check the evaluation script to be correct. "
131+
"Error Msg: {0}.".format(err))
132+
logger.error("{0} Experiment {1} - "
133+
"Individual inserted is not a valid individual. "
134+
"Check the evaluation script to be correct. "
135+
"Error Msg: {2}."
136+
.format(log_prefix, experiment_name, err))
137+
138+
return None
139+
140+
141+
def add_permissions_to_file(filepath, permissions, user_password=None):
142+
# Create the command to execute
143+
cmd = 'chmod {0} {1}'.format(permissions, filepath)
144+
logger.info('Proceed to give {0} permissions to file {1}'.format(permissions, filepath))
145+
if user_password:
146+
cmd_error_code = os.system('echo %s |sudo -S %s' % (user_password, cmd))
147+
# Erase the passwd stored, so sudo obliged us to insert it again
148+
os.system('sudo -K')
149+
return cmd_error_code == 0
150+
else:
151+
return os.system(cmd) == 0

0 commit comments

Comments
 (0)