From 81e45647983012a43e381df6ff61035b26c061e1 Mon Sep 17 00:00:00 2001 From: kamichal Date: Wed, 30 Mar 2016 00:51:57 +0200 Subject: [PATCH] addin' readme --- .gitignore | 4 + PrawoWiazkiApp.py | 315 ++++++++++++++++++++++++++++++++++++++++++++++ PyQtKaWig.py | 196 +++++++++++++++++++++++++++++ WzorErlanga.py | 79 ++++++++++++ __init__.py | 4 + readme.rst | 6 + 6 files changed, 604 insertions(+) create mode 100644 .gitignore create mode 100644 PrawoWiazkiApp.py create mode 100644 PyQtKaWig.py create mode 100644 WzorErlanga.py create mode 100644 __init__.py create mode 100644 readme.rst diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8f5dfd1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +*.pyc +*.project +*.pydevproject + diff --git a/PrawoWiazkiApp.py b/PrawoWiazkiApp.py new file mode 100644 index 0000000..c5d5644 --- /dev/null +++ b/PrawoWiazkiApp.py @@ -0,0 +1,315 @@ +#!/usr/bin/env python +# -*- coding:utf-8 -*- +''' +Created on 5 Feb 2016 + +@author: kamichal +''' + +from PyQt4 import QtGui, QtCore + +from WzorErlanga import ErlangB +from PyQtKaWig import SuwakPoziomy, WidzetWykres + +from matplotlib.font_manager import FontProperties + +class WatekObliczeniowy(QtCore.QThread): + ''' Obliczenia sa wykonywane w osobnym watku. + Kiedy watek sie konczy, sane sa wysylane przez sygnal ''' + sygnalPoliczone = QtCore.pyqtSignal(dict) + + def __init__(self, parent = None): + super(WatekObliczeniowy, self).__init__(parent) + self.parent = parent + + @QtCore.pyqtSlot(dict) + def SlotZamowNowy(self, slownik): + self.zamowienie = slownik + self.start() # uruchom watek + + def run(self): + try: + sloZ = self.zamowienie + if 'typ' in sloZ.keys(): + A = sloZ['wartA'] + N = sloZ['wartN'] + XX = self.__dziedzinaX(A, sloZ['typ']) + self.zamowienie['EbX'] = XX + self.zamowienie['EbY'] = ErlangB(XX, N) + (self.zamowienie['kursorX'], + self.zamowienie['kursorY']) = self.__GenerujKursor(A,N) + + if 'podpis' in self.zamowienie.keys(): + self.zamowienie['podpisPlus'] = \ + (self.zamowienie['podpis'] + '= %.3f' % ErlangB(A, N)) + + if self.zamowienie['podgPW']: + ErB2 = ErlangB(2*A, 2*N) + self.zamowienie['kursor2X'] = 2*A + self.zamowienie['kursor2Y'] = ErB2 + if 'podpis' in self.zamowienie.keys(): + self.zamowienie['podpisPlus'] += ( + ' (Eb2= %.3f)' % ErB2) + + self.sygnalPoliczone.emit(self.zamowienie) + else: + print 'bledny slownik zamowienia' + + except (RuntimeError, TypeError, NameError): + raise ('Blad slownika') + + def __dziedzinaX(self, x_zamawiane, typ): + if typ == 'podglad': + Npkt = 32 + else: + Npkt = 200 + x_max = max(32, x_zamawiane) + return [(1.0 * x * x_max / Npkt) for x in range(Npkt)] + + def __GenerujKursor(self, A, N): + XX = [A, A, 0] + erlb = ErlangB(A, N) + YY = [0, erlb, erlb] + return (XX, YY) + + +class FormularzKreslenia(QtGui.QWidget): + sygNowyFormularz = QtCore.pyqtSignal(dict) + + def __init__(self, parent = None): + super(FormularzKreslenia, self).__init__(parent) + self.setMaximumHeight(72) + + + self.ukladLewy = QtGui.QVBoxLayout() + self.ukladPrawy = QtGui.QVBoxLayout() + self.ukladPrzyciskow = QtGui.QHBoxLayout() + + self.parN = SuwakPoziomy(self, 'N', u'linii\nsieci') + self.parN.UstawMax(170) # silnia wiecej nie wyrobi + self.parN.SygnSuwakPoszedl.connect(self.__SlotZmianaFormularza) + + self.parA = SuwakPoziomy(self, 'A', u'abonentow') + self.parA.UstawMax(600) + self.parA.SygnSuwakPoszedl.connect(self.__SlotZmianaFormularza) + + self.ukladLewy.addWidget(self.parN) + self.ukladLewy.addWidget(self.parA) + + self.opisSeriiDanych = QtGui.QLineEdit(self) + self.opisSeriiDanych.setText('wykres') + + self.wyswPrawoWiazki = QtGui.QCheckBox(self) + self.wyswPrawoWiazki.setText(u'wyświetl Prawo\nWiązki (2N,2A)') + self.wyswPrawoWiazki.clicked.connect(self.__SlotZmianaFormularza) + + self.zatwierdz = QtGui.QPushButton(self) + self.zatwierdz.setText(u'wykreśl') + self.zatwierdz.setMinimumHeight(30) + self.zatwierdz.clicked.connect(self.__SlotZlozZamowienie) + + self.zmazik = QtGui.QPushButton(self) + self.zmazik.setText(u'wyczyść') + self.zmazik.setMinimumHeight(30) + self.zmazik.clicked.connect(parent.SlotCzysc) + + self.ukladPrzyciskow.addWidget(self.wyswPrawoWiazki) + self.ukladPrzyciskow.addWidget(self.zatwierdz) + self.ukladPrzyciskow.addWidget(self.zmazik) + + self.ukladPrawy.addWidget(self.opisSeriiDanych) + self.ukladPrawy.addLayout(self.ukladPrzyciskow) + + self.formularz = QtGui.QHBoxLayout(self) + self.formularz.addLayout(self.ukladLewy) + self.formularz.addLayout(self.ukladPrawy) + + + self.__aktualizujPodpis() + + @QtCore.pyqtSlot() + def __SlotZmianaFormularza(self): + self.__aktualizujPodpis() + slownik = self.__FormuujZamowienie() + slownik['typ'] = 'podglad' + self.sygNowyFormularz.emit(slownik) + + @QtCore.pyqtSlot() + def __SlotZlozZamowienie(self): + slownik = self.__FormuujZamowienie() + slownik['typ'] = 'zatwierdzone' + slownik['podpis'] = str(self.opisSeriiDanych.text()) + self.sygNowyFormularz.emit(slownik) + + def __FormuujZamowienie(self): + return { + 'wartN' : self.parN.wartosc.value() , + 'wartA' : self.parA.wartosc.value(), + 'podgPW': self.wyswPrawoWiazki.isChecked()} + + def __aktualizujPodpis(self): + #format = 'Eb 1,%dN (%dA)' + formatWys = 'E 1,%d(%d)' + podpis = formatWys % (self.parN.wartosc.value(), + self.parA.wartosc.value()) + + self.opisSeriiDanych.setText(podpis) + +class KontrolerWykresuErlanga(QtGui.QWidget): + def __init__(self, parent = None): + super(KontrolerWykresuErlanga, self).__init__(parent) + + self.formularz = FormularzKreslenia(self) + self.oknoRysowania = WidzetWykres(self) + + self.ukladPionowy = QtGui.QVBoxLayout(self) + self.ukladPionowy.addWidget(self.formularz) + self.ukladPionowy.addWidget(self.oknoRysowania) + + self.watek = WatekObliczeniowy(self) + self.watek.sygnalPoliczone.connect(self.SlotZamowienie) + self.watek.finished.connect(self.SlotWatekZakonczony) + + self.formularz.sygNowyFormularz.connect(self.watek.SlotZamowNowy) + + self.SlotCzysc() + + @QtCore.pyqtSlot() + def SlotCzysc(self): + self.listaZamowien = [] + self.slownikPodgladu = {} + + self.oknoRysowania.axis.clear() + self.oknoRysowania.canvas.draw() + + @QtCore.pyqtSlot(dict) + def SlotZamowienie(self, slo): + if 'typ' in slo.keys(): + if slo['typ'] == 'zatwierdzone': + # zatwierdzone są akumulowane + self.listaZamowien.append(slo) + self.slownikPodgladu = {} + elif slo['typ'] == 'podglad': + # podglad jest zastepowany + self.slownikPodgladu = slo + else: + print 'bledny slownik zamowienia' + + self.__RysujZeSlownika() + + @QtCore.pyqtSlot() + def SlotWatekZakonczony(self): + pass # print 'ol rajt!' + + def __RysujZeSlownika(self): + + self.oknoRysowania.axis.clear() + + for n, zam in enumerate(self.listaZamowien): + self.oknoRysowania.axis.plot(zam['kursorX'], + zam['kursorY'], + label=zam['podpisPlus'], + c=self.oknoRysowania.kolorLini(n), + marker=self.oknoRysowania.stylMarkera(n), + ls = '-.') + + if self.listaZamowien: + fontP = FontProperties() + fontP.set_size('small') + self.oknoRysowania.axis.legend(prop = fontP, loc=4) + + for n, zam in enumerate(self.listaZamowien): + self.oknoRysowania.axis.plot( + zam['EbX'], + zam['EbY'], + label = zam['podpis'], + c=self.oknoRysowania.kolorLini(n)) + + if 'kursor2X' in zam.keys() and 'kursor2Y' in zam.keys(): + self.oknoRysowania.axis.plot( + zam['kursor2X'], + zam['kursor2Y'], + label=zam['podpisPlus'], + c=self.oknoRysowania.kolorLini(n), + marker=self.oknoRysowania.stylMarkera(n), + ls = ':') + + + if self.slownikPodgladu: + pdg = self.slownikPodgladu + self.oknoRysowania.axis.plot(pdg['EbX'], + pdg['EbY'], + c = '#040802', + ls = '--') + self.oknoRysowania.axis.plot(pdg['kursorX'], + pdg['kursorY'], + c = '#040802', + ls = ':') + + if 'kursor2X' in pdg.keys() and 'kursor2Y' in pdg.keys(): + self.oknoRysowania.axis.plot( + pdg['kursor2X'], + pdg['kursor2Y'], + c= '#040802', + marker='x', + ls = ':') + + self.oknoRysowania.axis.grid(b=None, which='major', color="#CCCCCC") + self.oknoRysowania.axis.set_xlabel(u'Ilość abonentów') + self.oknoRysowania.axis.set_ylabel(u'Prawd. blokady') + self.oknoRysowania.canvas.draw() + + +class OknoGlowne(QtGui.QWidget): + def __init__(self, parent = None): + super(OknoGlowne, self).__init__(parent) + + self.zakladki = QtGui.QTabWidget(self) + zakladka1 = QtGui.QWidget() + zakladka2 = KontrolerWykresuErlanga(self) + + edytorTekstu = QtGui.QTextEdit(self) + edytorTekstu.setText(self.__opis()) + edytorTekstu.setReadOnly(True) + + ukladZakladki1 = QtGui.QVBoxLayout() + ukladZakladki1.addWidget(edytorTekstu) + zakladka1.setLayout(ukladZakladki1) + + ukladOkna = QtGui.QVBoxLayout(self) + ukladOkna.addWidget(self.zakladki) + + self.zakladki.addTab(zakladka1, "Opis programu") + self.zakladki.addTab(zakladka2, "Wykres B-Erlang'a (A)") + self.zakladki.setCurrentIndex(1) + self.zakladki.setWindowTitle('ErlangB') + self.zakladki.show() + def __opis(self): + return u''' Ten program wizualizuje wyniki obliczeń według wzoru Erlanga-B w następującej postaci: + + E1,N(A) = ( A^N / N! ) / ( suma dla i od 0 do N (A^i / i!)) + + Ponieważ we wzorze użyta została silnia, to ograniczona jest wartość N do 170 linii sieci (wynik 170! jest liczbą całkowitą, która zajmuje bodajże tysiąc bitów, zatem to jest i tak niezły wynik). Silnia jest obliczana inkrementacyjnie, ale został wykorzystany dość szybki algorytm jej obliczania - dotychczas obliczone wartości dla kolejnych liczb naturalnych są umieszczane w tablicy wyników do przyszłego użycia. + +Z polskiej wikipedii: + Erlang – jednostka natężenia ruchu telekomunikacyjnego. Nazwa wywodzi się od nazwiska Agnera Krarupa Erlanga, autora teorii masowej obsługi, znanej również jako teoria kolejek, która stanowi uogólnienie zjawisk zaobserwowanych w telekomunikacji. + +Dla danego systemu telekomunikacyjnego składającego się z N linii, i czasu obserwacji równego 1 godzinie (60 minut), jeśli linia ta zajęta jest cały czas przez pełną godzinę, to natężenie ruchu wynosi 1 Erlang; odpowiednio, jeśli linia ta zajęta jest przez 30 minut, natężenie to wynosi 0,5 Erlanga. + + Program został napisany w języku Python 2.7. z użyciem bibliotek matplotlib oraz PyQt4 i nakładki PyQt na matplotlib (FigureCanvasQTAgg z backend_qt4agg). Instalator programu dla środowisk bez interpretera Python 2.7. to PyInstaller + + Pierwotni autorzy: (Małgorzata Kania, Michał Kaczmarczyk) @ Politechnika Wrocławska, wydział Elektroniki. + + ''' + +if __name__ == "__main__": + import sys + + app = QtGui.QApplication(sys.argv) + app.setApplicationName('OknoGlowne') + + main = OknoGlowne() + main.resize(666, 333) + main.show() + + sys.exit(app.exec_()) diff --git a/PyQtKaWig.py b/PyQtKaWig.py new file mode 100644 index 0000000..20def25 --- /dev/null +++ b/PyQtKaWig.py @@ -0,0 +1,196 @@ +''' +Created on 24 Jan 2016 + +@author: kamichal +''' + +from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg +from matplotlib.figure import Figure +import random +from PyQt4 import QtGui, QtCore + + +class SuwakPoziomy(QtGui.QWidget): + SygnSuwakPoszedl = QtCore.pyqtSignal() + + def __init__(self, parent=None, nazwa='', jednostka=''): + super(SuwakPoziomy, self).__init__(parent) + + + self.nazwa = QtGui.QLabel(self) + self.nazwa.setText(nazwa + ' = ') + + self.wartosc = QtGui.QSpinBox(self) + + self.postfiks = QtGui.QLabel(self) + self.postfiks.setText(jednostka) + + self.suwak = QtGui.QSlider(QtCore.Qt.Horizontal, self) + self.suwak.valueChanged.connect(self.wartosc.setValue) + self.suwak.valueChanged.connect(self.SygnSuwakPoszedl) + self.wartosc.valueChanged.connect(self.suwak.setValue) + self.wartosc.valueChanged.connect(self.SygnSuwakPoszedl) + + self.ukladWidzetu = QtGui.QHBoxLayout(self) + self.ukladWidzetu.addWidget(self.nazwa) + self.ukladWidzetu.addWidget(self.wartosc) + self.ukladWidzetu.addWidget(self.postfiks) + self.ukladWidzetu.addWidget(self.suwak) + + def UstawMin(self, maxWart): + self.suwak.setMinimum(maxWart) + self.wartosc.setMinimum(maxWart) + + def UstawMax(self, maxWart): + self.suwak.setMaximum(maxWart) + self.wartosc.setMaximum(maxWart) + + +class WidzetWykres(QtGui.QWidget): + def __init__(self, parent=None): + super(WidzetWykres, self).__init__(parent) + + self.figure = Figure() + self.canvas = FigureCanvasQTAgg(self.figure) + + self.axis = self.figure.add_subplot(111) + + self.ukladPionowy = QtGui.QVBoxLayout(self) + self.ukladPionowy.addWidget(self.canvas) + + def kolorLini(self, n=0): + kolory = ( + 'b' # blue + 'g' # green + 'r' # red + 'c' # cyan + 'm' # magenta + 'y' # yellow + 'k' # black + 'w' # white + ) + return kolory[n % len(kolory)] + + + def stylMarkera(self, n=0): + znaczniki = ( + 'x', # x + 'o', # circle + 'v', # triangle_down + '^', # triangle_up + '<', # triangle_left + '>', # triangle_right + '1', # tri_down + '2', # tri_up + '3', # tri_left + '4', # tri_right + '8', # octagon + 's', # square + 'p', # pentagon + '*', # star + 'h', # hexagon1 + '.', # point + 'H', # hexagon2 + '+', # plus + ',', # pixel + 'D', # diamond + 'd', # thin_diamond + '|', # vline + '_' # hline + ) + return znaczniki[n%len(znaczniki)] + +class TestOknoGlowne(QtGui.QWidget): + def __init__(self, parent=None): + super(TestOknoGlowne, self).__init__(parent) + +# self.suwak = SuwakPoziomy(self) + + self.tA = SuwakPoziomy(self,'Asd',"opis moze\nbyc lamany") + self.tA.UstawMax(1000) + + self.tB = SuwakPoziomy(self,'N','[Watt]') + self.tB.wartosc.setMaximum(200) + self.tB.postfiks.setText('[laczy]') + + self.tC = SuwakPoziomy(self,'E','[V]') + + self.uklad = QtGui.QVBoxLayout(self) + self.uklad.addWidget(self.tA) + self.uklad.addWidget(self.tB) + self.uklad.addWidget(self.tC) + +class TestWykresow(QtGui.QWidget): + def __init__(self, parent=None): + super(TestWykresow, self).__init__(parent) + +# self.suwak = SuwakPoziomy(self) + + self.W = WidzetWykres(self) + +# self.RysujCosTam() + self.RysujSlownikiem() + self.zatwierdz = QtGui.QPushButton(self) + self.zatwierdz.setText("Jeszcze raz") + self.zatwierdz.clicked.connect(self.RysujCosTam) + + self.uklad = QtGui.QVBoxLayout(self) + self.uklad.addWidget(self.W) + self.uklad.addWidget(self.zatwierdz) + + @QtCore.pyqtSlot() + def RysujCosTam(self): + self.W.axis.clear() + + N = 16 + XX = range(N) + YY = [] + + for _ in range(4): + tmp = random.sample(range(N), N) + YY.append(tmp) + + for i, seria in enumerate(YY): + self.W.axis.plot(XX, seria, + c=self.W.kolory[i], + marker=self.W.styleMarkerow[i]) + self.W.canvas.draw() + + @QtCore.pyqtSlot() + def RysujSlownikiem(self): + self.W.axis.clear() + N = 16 + XX = range(N) + dane = [] + + for _ in range(4): + tmp = random.randint(0,5) + YY = random.sample(range(N), N) + dane.append({'xx':XX, + 'yy':YY, + 'ma':self.W.styleMarkerow[tmp], + 'ko':self.W.kolory[tmp] + }) + + for seria in dane: + self.W.axis.plot(seria['xx'], + seria['yy'], + c=seria['ko'], + marker=seria['ma']) + + self.W.canvas.draw() + + + +if __name__ == "__main__": + import sys + + app = QtGui.QApplication(sys.argv) + app.setApplicationName('OknoGlowne') + +# main = TestOknoGlowne() + main = TestWykresow() + main.resize(666, 333) + main.show() + + sys.exit(app.exec_()) \ No newline at end of file diff --git a/WzorErlanga.py b/WzorErlanga.py new file mode 100644 index 0000000..a41fdea --- /dev/null +++ b/WzorErlanga.py @@ -0,0 +1,79 @@ +''' +Created on 23 Jan 2016 + +@author: kamichal +''' + +_FAC_TABLE = [1, 1] +def szybkaSilnia(n): + if n < len(_FAC_TABLE): + return _FAC_TABLE[n] + + last = len(_FAC_TABLE) - 1 + total = _FAC_TABLE[last] + for i in range(last + 1, n + 1): + total *= i + _FAC_TABLE.append(total) + + return total + +def ErlangB(A,N): + ''' Ta wersja funkcji moze byc wywolywana + z listami jako argumentami ''' + if A is None or N is None: + print 'blad wywolania funkcji ErlangB' + return None + + try: + if type(A) is list: + if type(N) is list: + E = [[] for _ in range(len(A))] + ia = 0 + for a in A: + for n in N: + w = ErlangBPojed(a, n) + E[ia].append(w) + ia += 1 + else: + E = [] + for a in A: + E.append(ErlangBPojed(a, N)) + else: + if type(N) is list: + E = [] + for n in N: + E.append(ErlangBPojed(A, n)) + else: + E = ErlangBPojed(A,N) + + return E + except OverflowError: + print ("numeric overflow, najprawdopodobniej silnia nie wyrabia ") + return None + +def ErlangBPojed(A,N): + ''' Wedlug wzoru: + E1,N(A) = ( A^N / N! ) / ( suma i od 0 do N (A^i / i!)) ''' + if N == 0: + return 1 + + szereg = 0.0 + for i in range(0,N+1): + szereg += A**i / szybkaSilnia(i) + + Eb = (( A**N ) / szybkaSilnia(N) )/ szereg + return Eb + +def TestErlanga(): + print 'Wzor Erlanga, potfornie prosty test' + print ' rzuc okiem, czy to sa poprawne wartosci' + for a in range (0,6): + for n in range(0,6): + print "E 1,%d(%d) = %f" % (n, a, ErlangBPojed(a,n)) + + +if __name__ == '__main__': + TestErlanga() + + + \ No newline at end of file diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..ca20119 --- /dev/null +++ b/__init__.py @@ -0,0 +1,4 @@ +#!/usr/bin/env python +# -*- coding:utf-8 -*- + +pass \ No newline at end of file diff --git a/readme.rst b/readme.rst new file mode 100644 index 0000000..015132f --- /dev/null +++ b/readme.rst @@ -0,0 +1,6 @@ +============= +Prawo Wiązki +============= + +A quick project for my university (telecommunication). +