From bfbddcc7316b1de7e230d6fdc59786133608b493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20K=C3=B6gl?= Date: Fri, 23 Nov 2012 14:03:40 +0100 Subject: [PATCH] sync to notebook --- reflowctl/reflowctl_gui.py | 209 +++++++++++++++----- reflowctl/solder_types/leadfree_noclean.xml | 36 +--- 2 files changed, 165 insertions(+), 80 deletions(-) diff --git a/reflowctl/reflowctl_gui.py b/reflowctl/reflowctl_gui.py index 56601cd..3fb9ca5 100755 --- a/reflowctl/reflowctl_gui.py +++ b/reflowctl/reflowctl_gui.py @@ -3,6 +3,8 @@ import sys, os, random, copy, struct +from datetime import datetime + from collections import deque from operator import attrgetter @@ -56,6 +58,11 @@ def set_colors(temp_levels): +def get_valid_neigbors(temp_level, temp_levels): + ix = temp_levels.index(temp_level) + return temp_levels[ix-1], temp_levels[ix+1] + + def create_profile_header(x_list, y_list): tpl = "#ifndef _H_SOLDER_PROFILE\n" \ "#define _H_SOLDER_PROFILE\n" \ @@ -99,11 +106,31 @@ def getTemperature(): class TempLevel(QtCore.QObject): def __init__(self, name, temp, is_env=False): + super(TempLevel, self).__init__() self.name = name self.temp = temp self.is_env = is_env self.color = None + def __str__(self): + return "" % (self.name, self.temp) + + def __lt__(self, other): + return self.temp < other.temp + + def __le__(self, other): + return self.temp <= other.temp + + def __eq__(self, other): + return self.temp == other.temp + + def is_between(self, tl1, tl2): + tmp = [tl1, tl2, self] + tmp.sort() + return self == tmp[1] + + __repr__ = __str__ + class TempLevelModel(QtCore.QAbstractTableModel): solder_changed = QtCore.pyqtSignal() @@ -184,8 +211,11 @@ class TempLevelModel(QtCore.QAbstractTableModel): self.reset() + + class TempLevelWidget(QtGui.QWidget): temp_level_removed = QtCore.pyqtSignal(TempLevel) + temp_levels_changed = QtCore.pyqtSignal() solder_changed = QtCore.pyqtSignal() def __init__(self, parent, readonly=False): @@ -246,12 +276,14 @@ class TempLevelWidget(QtGui.QWidget): def setData(self, solder): self.temp_level_model.setTempLevels(solder.temp_levels) self.temp_level_view.resizeColumnsToContents() + self.temp_level_view.setCurrentIndex(self.temp_level_model.index(0, 0)) def add_temp_level(self): index = self.temp_level_view.currentIndex() self.temp_level_model.add_temp_level(index, TempLevel("new " + str(self.temp_level_model.rowCount(None)), 0)) self.temp_level_view.setCurrentIndex(self.temp_level_model.index(index.row() + 1, 0)) + self.temp_levels_changed.emit() def remove_temp_level(self): @@ -328,26 +360,32 @@ class Solder(QtCore.QObject): def calc_rate(self, x1, y1, x2, y2): return (y2 - y1) / (x2 - x1) - def check_duration_constraints(self, temp_level, used): + def check_duration_constraints(self, temp_level, used, ix): x = list() y = list() temp_levels = None value = None + dx = 0 for temp_levels, value in self.durations: tl_len = len(temp_levels) - if temp_levels and temp_levels[0] == temp_level and tl_len > 1: + print "check dur", dx, temp_level, repr(temp_levels), self.ud + if temp_levels and temp_levels[0] == temp_level and tl_len > 1 and dx not in self.ud: if temp_level not in used: used.add(temp_level) x.append(self.time) y.append(temp_level.temp) + self.ud.add(dx) + print "using duration constraint", dx if tl_len == 2: + ix = self.temp_levels.index(temp_levels[1]) y.append(temp_levels[1].temp) used.add(temp_levels[1]) self.time += value x.append(self.time) elif tl_len >= 3: + ix = self.temp_levels.index(temp_levels[-1]) part = value / (tl_len - 1) for tl in temp_levels[1:]: used.add(tl) @@ -357,30 +395,41 @@ class Solder(QtCore.QObject): y.append(tl.temp) self.log.append("* Duration connection: TempLevel %r connected to TempLevels %r" % (temp_level.name, [tl.name for tl in temp_levels[1:]])) + return x, y, ix + dx += 1 + raise Exception() - return x, y - - def check_rate_constraints(self, temp_level, used): + def check_rate_constraints(self, temp_level, used, ix): x = list() y = list() + rx = 0 for temp_levels, value in self.rates: tl_len = len(temp_levels) - if temp_levels and temp_levels[0] == temp_level and tl_len > 1: + print "check rate", rx, temp_level, repr(temp_levels), self.ur + if temp_levels and tl_len > 1 and rx not in self.ur and (temp_levels[0] == temp_level or temp_level.is_between(*temp_levels)): + if temp_level < temp_levels[1] and value < 0: + self.log.append("!RateError: negative rate for increasing temp levels is wrong") + elif temp_level > temp_levels[1] and value > 0: + self.log.append("!RateError: positive rate for decreasing temp levels is wrong") if temp_level not in used: used.add(temp_level) x.append(self.time) y.append(temp_level.temp) + self.ur.add(rx) + print "using rate constraint", rx self.time += (temp_levels[1].temp - temp_level.temp) / value used.add(temp_levels[1]) x.append(self.time) y.append(temp_levels[1].temp) - + ix = self.temp_levels.index(temp_levels[-1]) self.log.append("* Rate connection: TempLevel %r connected to TempLevels %r" % (temp_level.name, [tl.name for tl in temp_levels[1:]])) - - return x, y + return x, y, ix + rx += 1 + raise Exception() def calc_profile(self): + print self.calc_profile self.log = list() x = list() @@ -390,18 +439,39 @@ class Solder(QtCore.QObject): self.time = 0 used = set() unused = list() - for temp_level in self.temp_levels: - dur_x, dur_y = self.check_duration_constraints(temp_level, used) - rate_x, rate_y = self.check_rate_constraints(temp_level, used) + ix = 0 + last = len(self.temp_levels) + self.ud = set() + self.ur = set() + count = len(self.durations) + len(self.rates) + print "max rounds", count + while 1: + print "while", ix, last, x, y, self.ud, self.ur + temp_level = self.temp_levels[ix] + count -= 1 - if len(dur_x) > 0: + try: + dur_x, dur_y, dur_new_ix = self.check_duration_constraints(temp_level, used, ix) + ix = dur_new_ix + print "dur_new_ix", dur_new_ix x.extend(dur_x) y.extend(dur_y) - elif len(rate_x) > 0: - x.extend(rate_x) - y.extend(rate_y) - elif temp_level not in used: - unused.append(temp_level) + except Exception, e: + print e + try: + rate_x, rate_y, rate_new_ix = self.check_rate_constraints(temp_level, used, ix) + ix = rate_new_ix + print "rate_new_ix", rate_new_ix + x.extend(rate_x) + y.extend(rate_y) + except Exception, e: + print e + ix+=1 + #if temp_level not in used: + #unused.append(temp_level) + + if (y and y[-1] == y[0]) or count <= 0: + break self.log.append("") map(self.log.append, ["* Missing Connection: %r" % tl.name for tl in unused]) @@ -525,7 +595,7 @@ class SolderListModel(QtCore.QAbstractListModel): return QtCore.Qt.ItemFlags(QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable) def create_solder(self): - solder = Solder(None, "new", "") + solder = Solder(None, datetime.now().strftime("%Y-%M-%D %H:%m:%s"), "") tl = solder.add_temp_level("environment temp", getTemperature(), True) tl.color = QtGui.QColor(0, 0, 0) @@ -535,7 +605,12 @@ class SolderListModel(QtCore.QAbstractListModel): @staticmethod def dirname(): return os.path.join(os.path.dirname(__file__), "solder_types") - + + def check_name(self, name): + for solder in self.listdata: + if name == solder.name: + return False + return True class SolderWidget(QtGui.QWidget): @@ -746,8 +821,8 @@ class ConstraintWidget(QtGui.QWidget): self.spinbox_block = False self.constraint_model = ConstraintListModel(self) # constraint selection - self.all_temp_levels = TempLevelModel(self) # temp_level selection pool - self.selected_temp_levels = TempLevelModel(self) # selected temp_levels + self.temp_levels_model = TempLevelModel(self) # temp_level selection pool + self.selected_temp_levels_model = TempLevelModel(self) # selected temp_levels self.controls = AddRemoveValueWidget(self) self.constraint_controls = AddRemoveWidget(self, False) @@ -761,16 +836,16 @@ class ConstraintWidget(QtGui.QWidget): self.constraint_view = QtGui.QListView(self) self.constraint_view.setModel(self.constraint_model) - self.all_temp_levels_view = QtGui.QListView(self) - self.all_temp_levels_view.setModel(self.all_temp_levels) + self.temp_levels_view = QtGui.QListView(self) + self.temp_levels_view.setModel(self.temp_levels_model) self.selected_temp_levels_view = QtGui.QListView(self) - self.selected_temp_levels_view.setModel(self.selected_temp_levels) + self.selected_temp_levels_view.setModel(self.selected_temp_levels_model) h = QtGui.QHBoxLayout() h.addWidget(self.constraint_view, 1) h.addWidget(self.constraint_controls, 1) - h.addWidget(self.all_temp_levels_view, 3) + h.addWidget(self.temp_levels_view, 3) h.addWidget(self.controls, 1) h.addWidget(self.selected_temp_levels_view, 3) @@ -825,9 +900,10 @@ class ConstraintWidget(QtGui.QWidget): def setData(self, solder): self.solder = solder - self.all_temp_levels.setTempLevels(solder.temp_levels) + self.temp_levels_model.setTempLevels(solder.temp_levels) self._set_data(solder) self.set_controls() + self.temp_levels_view.setCurrentIndex(self.temp_levels_model.index(0,0)) self.controls.up_button.setEnabled(False) self.controls.down_button.setEnabled(False) @@ -868,24 +944,24 @@ class ConstraintWidget(QtGui.QWidget): raise NotImplementedError() def add_temp_level_to_constraint(self): - src_row = self.all_temp_levels_view.currentIndex().row() - temp_level = self.all_temp_levels.temp_levels[src_row] - self.selected_temp_levels.temp_levels.append(temp_level) - self.selected_temp_levels.reset() - self.selected_temp_levels_view.setCurrentIndex(self.selected_temp_levels.index(len(self.selected_temp_levels.temp_levels)-1,0)) + src_row = self.temp_levels_view.currentIndex().row() + temp_level = self.temp_levels_model.temp_levels[src_row] + self.selected_temp_levels_model.temp_levels.append(temp_level) + self.selected_temp_levels_model.reset() + self.selected_temp_levels_view.setCurrentIndex(self.selected_temp_levels_model.index(len(self.selected_temp_levels_model.temp_levels)-1,0)) self.solder_changed.emit() def remove_temp_level_from_constraint(self): - del self.selected_temp_levels.temp_levels[self.selected_temp_levels_view.currentIndex().row()] - self.selected_temp_levels.reset() + del self.selected_temp_levels_model.temp_levels[self.selected_temp_levels_view.currentIndex().row()] + self.selected_temp_levels_model.reset() self.selected_temp_levels_view.clearSelection() self.solder_changed.emit() def remove_constraint(self): - src_row = self.all_temp_levels_view.currentIndex().row() + src_row = self.temp_levels_view.currentIndex().row() del self.constraint_model.constraint_list[src_row] self.constraint_model.reset() - self.selected_temp_levels.clear() + self.selected_temp_levels_model.clear() self.set_controls() self.solder_changed.emit() @@ -897,6 +973,10 @@ class ConstraintWidget(QtGui.QWidget): self.constraint_model.constraint_list[src_index][1] = value self.solder_changed.emit() + def temp_levels_changed(self): + print self.temp_levels_changed + self.temp_levels_model.reset() + def slot_temp_level_removed(self, temp_level): deletes = deque() ix = 0 @@ -911,14 +991,14 @@ class ConstraintWidget(QtGui.QWidget): def temp_level_up(self): dst_row = self.selected_temp_levels_view.currentIndex().row() - self.selected_temp_levels.temp_levels[dst_row - 1], self.selected_temp_levels.temp_levels[dst_row] = self.selected_temp_levels.temp_levels[dst_row], self.selected_temp_levels.temp_levels[dst_row - 1] - self.selected_temp_levels.reset() + self.selected_temp_levels_model.temp_levels[dst_row - 1], self.selected_temp_levels_model.temp_levels[dst_row] = self.selected_temp_levels_model.temp_levels[dst_row], self.selected_temp_levels_model.temp_levels[dst_row - 1] + self.selected_temp_levels_model.reset() self.solder_changed.emit() def temp_level_down(self): dst_row = self.selected_temp_levels_view.currentIndex().row() - self.selected_temp_levels.temp_levels[dst_row], self.selected_temp_levels.temp_levels[dst_row + 1] = self.selected_temp_levels.temp_levels[dst_row + 1], self.selected_temp_levels.temp_levels[dst_row] - self.selected_temp_levels.reset() + self.selected_temp_levels_model.temp_levels[dst_row], self.selected_temp_levels_model.temp_levels[dst_row + 1] = self.selected_temp_levels_model.temp_levels[dst_row + 1], self.selected_temp_levels_model.temp_levels[dst_row] + self.selected_temp_levels_model.reset() self.solder_changed.emit() @@ -936,11 +1016,11 @@ class DurationConstraintWidget(ConstraintWidget): if index.isValid(): self.spinbox_block = True temp_levels, value = self.constraint_model.constraint_list[index.row()] - self.selected_temp_levels.setTempLevels(temp_levels) + self.selected_temp_levels_model.setTempLevels(temp_levels) self.controls.value.setValue(value) else: self.spinbox_block = True - self.selected_temp_levels.setTempLevels(list()) + self.selected_temp_levels_model.setTempLevels(list()) self.controls.value.setValue(0) @@ -959,11 +1039,11 @@ class RateConstraintWidget(ConstraintWidget): if index.isValid(): self.spinbox_block = True temp_levels, value = self.constraint_model.constraint_list[index.row()] - self.selected_temp_levels.setTempLevels(temp_levels) + self.selected_temp_levels_model.setTempLevels(temp_levels) self.controls.value.setValue(value) else: self.spinbox_block = True - self.selected_temp_levels.setTempLevels([]) + self.selected_temp_levels_model.setTempLevels([]) self.controls.value.setValue(0) @@ -1034,6 +1114,25 @@ class Report(QtGui.QWidget): super(Report, self).__init__(parent) + self.operator = QtGui.QLineEdit(self) + self.date_begin = QtGui.QDateTimeEdit(self) + self.date_end = QtGui.QDateTimeEdit(self) + self.durations = list() + + self.plot_file = "" + + layout = QtGui.QGridLayout(self) + layout.addWidget(QtGui.QLabel("operator"), 0, 0) + layout.addWidget(QtGui.QLabel("date begin"), 1, 0) + layout.addWidget(QtGui.QLabel("date end"), 2, 0) + layout.addWidget(self.operator, 0, 1) + layout.addWidget(self.date_begin, 1, 1) + layout.addWidget(self.date_end, 2, 1) + + def export_pdf(self): + pass + + class ApplicationWindow(QtGui.QMainWindow): def __init__(self): QtGui.QMainWindow.__init__(self) @@ -1053,6 +1152,8 @@ class ApplicationWindow(QtGui.QMainWindow): QtCore.Qt.CTRL + QtCore.Qt.Key_D) self.file_menu.addAction('S&ave plot', self.save_plot, QtCore.Qt.CTRL + QtCore.Qt.Key_A) + self.file_menu.addAction('&Quit', self.show_report, + QtCore.Qt.CTRL + QtCore.Qt.Key_T) self.file_menu.addAction('&Quit', self.fileQuit, QtCore.Qt.CTRL + QtCore.Qt.Key_Q) @@ -1074,6 +1175,10 @@ class ApplicationWindow(QtGui.QMainWindow): self.profile_view_action.setCheckable(True) self.controls_view_action.setCheckable(True) + self.report = Report(self) + + self.report.hide() + #self.connect(self.profile_view_action, #QtCore.SIGNAL("triggered()"), #self.open_profile_view) @@ -1169,6 +1274,9 @@ class ApplicationWindow(QtGui.QMainWindow): self.temp_level_widget.temp_level_removed.connect(self.duration_widget.slot_temp_level_removed) self.temp_level_widget.temp_level_removed.connect(self.rate_widget.slot_temp_level_removed) + self.temp_level_widget.temp_levels_changed.connect(self.duration_widget.temp_levels_changed) + self.temp_level_widget.temp_levels_changed.connect(self.rate_widget.temp_levels_changed) + def getPlotter(self): return self.plotter @@ -1204,6 +1312,9 @@ class ApplicationWindow(QtGui.QMainWindow): self.controls_widget.hide() self.settings_widget.show() + def show_report(self): + self.report.exec() + def save_plot(self): file_choices = "PNG (*.png)|*.png" @@ -1212,6 +1323,7 @@ class ApplicationWindow(QtGui.QMainWindow): def save_solder(self): self.plotter.solder.save() + self.solder_widget.solder_model.listdata.sort(key=lambda x: x.name) self.solder_widget.solder_model.reset() new_index = self.solder_widget.solder_model.index(self.solder_widget.solder_model.listdata.index(self.plotter.solder)) self.solder_widget.solder_view.setCurrentIndex(new_index) @@ -1252,5 +1364,10 @@ def main(): sys.exit(qApp.exec_()) -if __name__ == '__main__': - main() +#if __name__ == '__main__': + #main() + + +tls = [TempLevel('peak', 260), TempLevel('environment temp', 20.0)] +a = TempLevel('tal', 200) +print a.is_between(*tls) diff --git a/reflowctl/solder_types/leadfree_noclean.xml b/reflowctl/solder_types/leadfree_noclean.xml index ae5ee13..3aeaa73 100644 --- a/reflowctl/solder_types/leadfree_noclean.xml +++ b/reflowctl/solder_types/leadfree_noclean.xml @@ -1,34 +1,2 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + \ No newline at end of file