Skip to content

Commit

Permalink
Merge pull request #5 from nodedge/feature/log-analyzer
Browse files Browse the repository at this point in the history
Feature/log analyzer
  • Loading branch information
nodedge committed Nov 1, 2020
2 parents ce7c5bb + cf48a98 commit 8100c85
Show file tree
Hide file tree
Showing 24 changed files with 1,298 additions and 22 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,5 @@ _template/
*.egg-info/
.tox/
examples/examples
ui
ui
log/
2 changes: 1 addition & 1 deletion .isort.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,5 @@ include_trailing_comma = True
force_grid_wrap=0
use_parentheses=True

known_third_party = PIL,PySide2,pyqtconsole,pytest,pytestqt,recommonmark,setuptools
known_third_party = PIL,PyQt5,PySide2,coloredlogs,numpy,pandas,pyqtconsole,pyqtgraph,pytest,pytestqt,recommonmark,setuptools,yaml

4 changes: 4 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ include readthedocs.yml
include mypy.ini
include .bumpversion.cfg
include CODE_OF_CONDUCT.md
include logging.yaml

include .flake8
include .isort.cfg
Expand All @@ -34,3 +35,6 @@ recursive-exclude docs/build *

include *.txt
recursive-include nodedge *

recursive-exclude logs *
recursive-exclude demos *
50 changes: 50 additions & 0 deletions demos/demo_json.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import json

from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import *


class ViewTree(QTreeWidget):
def __init__(self, value):

super().__init__()

def fill_item(item, value):
def new_item(parent, text, val=None):
child = QTreeWidgetItem([text])
child.setFlags(child.flags() | Qt.ItemIsEditable)
fill_item(child, val)
parent.addChild(child)
child.setExpanded(True)

if value is None:
return
elif isinstance(value, dict):
for key, val in sorted(value.items()):
new_item(item, str(key), val)
elif isinstance(value, (list, tuple)):
for val in value:
text = (
str(val)
if not isinstance(val, (dict, list, tuple))
else "[%s]" % type(val).__name__
)
new_item(item, text, val)
else:
new_item(item, str(value))

fill_item(self.invisibleRootItem(), value)


if __name__ == "__main__":

app = QApplication([])

fname = QFileDialog.getOpenFileName()
json_file = open(fname[0], "r")
file = json.load(json_file)

window = ViewTree(file)
window.setGeometry(300, 100, 900, 600)
window.show()
app.exec_()
21 changes: 21 additions & 0 deletions demos/demo_pqtgraph.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import pyqtgraph as pg
from PySide2 import QtWidgets


class WdgPlot(QtWidgets.QWidget):
def __init__(self, parent=None):
super(WdgPlot, self).__init__(parent)
layout = QtWidgets.QVBoxLayout(self)

pw = pg.PlotWidget()
pw.plot([1, 2, 3, 4])
layout.addWidget(pw)


if __name__ == "__main__":
import sys

app = QtWidgets.QApplication(sys.argv)
w = WdgPlot()
w.show()
sys.exit(app.exec_())
169 changes: 169 additions & 0 deletions demos/demo_pyqtgraph_flowchart.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,169 @@
# -*- coding: utf-8 -*-
"""
This example demonstrates writing a custom Node subclass for use with flowcharts.
We implement a couple of simple image processing nodes.
"""
# from pyqtgraph import initExample ## Add path to library (just for examples; you do not need this)

import numpy as np
import pyqtgraph as pg
import pyqtgraph.flowchart.library as fclib
from pyqtgraph.flowchart import Flowchart, Node
from pyqtgraph.flowchart.library.common import CtrlNode
from pyqtgraph.Qt import QtCore, QtGui

app = QtGui.QApplication([])

## Create main window with a grid layout inside
win = QtGui.QMainWindow()
win.setWindowTitle("pyqtgraph example: FlowchartCustomNode")
cw = QtGui.QWidget()
win.setCentralWidget(cw)
layout = QtGui.QGridLayout()
cw.setLayout(layout)

## Create an empty flowchart with a single input and output
fc = Flowchart(terminals={"dataIn": {"io": "in"}, "dataOut": {"io": "out"}})
w = fc.widget()

layout.addWidget(fc.widget(), 0, 0, 2, 1)

## Create two ImageView widgets to display the raw and processed data with contrast
## and color control.
v1 = pg.ImageView()
v2 = pg.ImageView()
layout.addWidget(v1, 0, 1)
layout.addWidget(v2, 1, 1)

win.show()

## generate random input data
data = np.random.normal(size=(100, 100))
data = 25 * pg.gaussianFilter(data, (5, 5))
data += np.random.normal(size=(100, 100))
data[40:60, 40:60] += 15.0
data[30:50, 30:50] += 15.0
# data += np.sin(np.linspace(0, 100, 1000))
# data = metaarray.MetaArray(data, info=[{'name': 'Time', 'values': np.linspace(0, 1.0, len(data))}, {}])

## Set the raw data as the input value to the flowchart
fc.setInput(dataIn=data)


## At this point, we need some custom Node classes since those provided in the library
## are not sufficient. Each node will define a set of input/output terminals, a
## processing function, and optionally a control widget (to be displayed in the
## flowchart control panel)


class ImageViewNode(Node):
"""Node that displays image data in an ImageView widget"""

nodeName = "ImageView"

def __init__(self, name):
self.view = None
## Initialize node with only a single input terminal
Node.__init__(self, name, terminals={"data": {"io": "in"}})

def setView(self, view): ## setView must be called by the program
self.view = view

def process(self, data, display=True):
## if process is called with display=False, then the flowchart is being operated
## in batch processing mode, so we should skip displaying to improve performance.

if display and self.view is not None:
## the 'data' argument is the value given to the 'data' terminal
if data is None:
self.view.setImage(
np.zeros((1, 1))
) # give a blank array to clear the view
else:
self.view.setImage(data)


## We will define an unsharp masking filter node as a subclass of CtrlNode.
## CtrlNode is just a convenience class that automatically creates its
## control widget based on a simple data structure.
class UnsharpMaskNode(CtrlNode):
"""Return the input data passed through an unsharp mask."""

nodeName = "UnsharpMask"
uiTemplate = [
("sigma", "spin", {"value": 1.0, "step": 1.0, "bounds": [0.0, None]}),
(
"strength",
"spin",
{
"value": 1.0,
"dec": True,
"step": 0.5,
"minStep": 0.01,
"bounds": [0.0, None],
},
),
]

def __init__(self, name):
## Define the input / output terminals available on this node
terminals = {
"dataIn": dict(io="in"), # each terminal needs at least a name and
"dataOut": dict(io="out"), # to specify whether it is input or output
} # other more advanced options are available
# as well..

CtrlNode.__init__(self, name, terminals=terminals)

def process(self, dataIn, display=True):
# CtrlNode has created self.ctrls, which is a dict containing {ctrlName: widget}
sigma = self.ctrls["sigma"].value()
strength = self.ctrls["strength"].value()
output = dataIn - (strength * pg.gaussianFilter(dataIn, (sigma, sigma)))
return {"dataOut": output}


## To make our custom node classes available in the flowchart context menu,
## we can either register them with the default node library or make a
## new library.


## Method 1: Register to global default library:
# fclib.registerNodeType(ImageViewNode, [('Display',)])
# fclib.registerNodeType(UnsharpMaskNode, [('Image',)])

## Method 2: If we want to make our custom node available only to this flowchart,
## then instead of registering the node type globally, we can create a new
## NodeLibrary:
library = fclib.LIBRARY.copy() # start with the default node set
library.addNodeType(ImageViewNode, [("Display",)])
# Add the unsharp mask node to two locations in the menu to demonstrate
# that we can create arbitrary menu structures
library.addNodeType(
UnsharpMaskNode, [("Image",), ("Submenu_test", "submenu2", "submenu3")]
)
fc.setLibrary(library)

## Now we will programmatically add nodes to define the function of the flowchart.
## Normally, the user will do this manually or by loading a pre-generated
## flowchart file.

v1Node = fc.createNode("ImageView", pos=(0, -150))
v1Node.setView(v1)

v2Node = fc.createNode("ImageView", pos=(150, -150))
v2Node.setView(v2)

fNode = fc.createNode("UnsharpMask", pos=(0, 0))
fc.connectTerminals(fc["dataIn"], fNode["dataIn"])
fc.connectTerminals(fc["dataIn"], v1Node["data"])
fc.connectTerminals(fNode["dataOut"], v2Node["data"])
fc.connectTerminals(fNode["dataOut"], fc["dataOut"])

## Start Qt event loop unless running in interactive mode or using pyside.
if __name__ == "__main__":
import sys

if (sys.flags.interactive != 1) or not hasattr(QtCore, "PYQT_VERSION"):
QtGui.QApplication.instance().exec_()

0 comments on commit 8100c85

Please sign in to comment.