Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Displaying (nicely) an algebraic expression in PyQt [duplicate]

In my python program is a hierarchy of mathematical objects I've created, that represent mathematical formulae.
For example, there's Collection, which is a series of Equations, which is a container of two Sums, Products, Quotients, Exponants or Logarithms, which are all establishments upon Figures, which can be numerical or variables.

I need to display to the user, a step of mathematical operations to perform to achieve certain tasks, such as getting unknown variables, etc. Currently, I generate this 'guide' in plain text, much like...

F = (m)(a)  
m = (F)/(a)  
a = 2, F = 3  
m = (3)/(2) = 1.5

However, representing complex formulas in plain text (eg: log[2](n)=(m)((a)^(2)) ) is ugly, and defeats a goal of the program, which is to maintain upmost clarity of procedure for the user.

I'm currently writing the GUI in PyQt4, and need to make a representation of the formulaes (each step) that can be displayed in a Qt Application. The formulaes do not need to be in text. Due to the object structure, it's extremely easy to convert the objects into mark up text as needed. The actual method of display can be anything, as long as I can cleanly chuck it in my GUI, such as an SVG, an image, etc.

  • At first, I considered MathML, but read that PyQt ignores MathML tags when displaying HTML, and that a QMmlWidget once existed for this exact task, but has been deprecated.
  • I then read that a combination of sympy, svgmath and QSvgWidget worked, displaying the formulaes as Svgs, but I need my code to be distributable, which the font configuration stuff in setting up svgmath inhibits.
  • I thought this looked promising: Display LaTeX Equations in-line with terminal but the videos run a total length of almost 4 hours, for which I don't have the patience.

I'm almost inclined to code it myself, using PIL or something like that to convert my math objects straight to an image, but I'd hate to think somebody has already achieved this, with a better job.

Any and all help is extremely appreciated!
Thanks!

like image 245
Anti Earth Avatar asked Dec 31 '12 04:12

Anti Earth


1 Answers

From the blog Gulon.co.uk. She's provided a simple yet powerful example for rendering LateX equations in pyQt. I have copied from there and pasted below:

from PyQt4.QtCore import *

from PyQt4.QtGui import *

from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas


class MathTextLabel(QWidget):

    def __init__(self, mathText, parent=None, **kwargs):
        QWidget.__init__(self, parent, **kwargs)

        l=QVBoxLayout(self)
        l.setContentsMargins(0,0,0,0)

        r,g,b,a=self.palette().base().color().getRgbF()

    self._figure=Figure(edgecolor=(r,g,b), facecolor=(r,g,b))
    self._canvas=FigureCanvas(self._figure)
    l.addWidget(self._canvas)

    self._figure.clear()
    text=self._figure.suptitle(
        mathText,
        x=0.0,
        y=1.0,
        horizontalalignment='left',
        verticalalignment='top',
        size=qApp.font().pointSize()*2)
    self._canvas.draw()

    (x0,y0),(x1,y1)=text.get_window_extent().get_points()
    w=x1-x0; h=y1-y0

    self._figure.set_size_inches(w/80, h/80)
    self.setFixedSize(w,h)

if __name__=='__main__':
    from sys import argv, exit

    class Widget(QWidget):
        def __init__(self, parent=None, **kwargs):
            QWidget.__init__(self, parent, **kwargs)

            l=QVBoxLayout(self)
            l.addWidget(QLabel("<h1>Discrete Fourier Transform</h1>"))

            mathText=r'$X_k = \sum_{n=0}^{N-1} x_n . e^{\frac{-i2\pi kn}{N}}$'
            l.addWidget(MathTextLabel(mathText, self),     alignment=Qt.AlignHCenter)

    a=QApplication(argv)
    w=Widget()
    w.show()
    w.raise_()
    exit(a.exec_())

Translated to PyQt5

from PyQt5 import QtCore, QtGui, QtWidgets
from PyQt5.QtWidgets import QVBoxLayout
from PyQt5.QtCore import Qt
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas


class MathTextLabel(QtWidgets.QWidget):

    def __init__(self, mathText, parent=None, **kwargs):
        super(QtWidgets.QWidget, self).__init__(parent, **kwargs)

        l=QVBoxLayout(self)
        l.setContentsMargins(0,0,0,0)

        r,g,b,a=self.palette().base().color().getRgbF()

        self._figure=Figure(edgecolor=(r,g,b), facecolor=(r,g,b))
        self._canvas=FigureCanvas(self._figure)
        l.addWidget(self._canvas)
        self._figure.clear()
        text=self._figure.suptitle(
            mathText,
            x=0.0,
            y=1.0,
            horizontalalignment='left',
            verticalalignment='top',
            size=QtGui.QFont().pointSize()*2
        )
        self._canvas.draw()

        (x0,y0),(x1,y1)=text.get_window_extent().get_points()
        w=x1-x0; h=y1-y0

        self._figure.set_size_inches(w/80, h/80)
        self.setFixedSize(w,h)

if __name__=='__main__':
    from sys import argv, exit

    class Widget(QtWidgets.QWidget):
        def __init__(self, parent=None, **kwargs):
            super(QtWidgets.QWidget, self).__init__(parent, **kwargs)

            l=QVBoxLayout(self)
            mathText=r'$X_k = \sum_{n=0}^{N-1} x_n . e^{\frac{-i2\pi kn}{N}}$'
            l.addWidget(MathTextLabel(mathText, self), alignment=Qt.AlignHCenter)

    a=QtWidgets.QApplication(argv)
    w=Widget()
    w.show()
    w.raise_()
    exit(a.exec_())
like image 196
Jlondono Avatar answered Oct 14 '22 20:10

Jlondono