Skip to content

Commit

Permalink
Merge pull request #90 from cinemascience/plot
Browse files Browse the repository at this point in the history
Plot
  • Loading branch information
dhrogers authored Nov 14, 2023
2 parents 3cf41c6 + 15b6ec6 commit fd4f199
Show file tree
Hide file tree
Showing 15 changed files with 373 additions and 64 deletions.
47 changes: 30 additions & 17 deletions examples/theater/PlotExample.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,49 @@
vf0.insertView( 0, pycinema.theater.views.NodeEditorView() )
vf1 = vf0.insertFrame(1)
vf1.setVerticalOrientation()
PlotLineView_0 = vf1.insertView( 0, pycinema.theater.views.PlotLineView() )
PlotBarView_0 = vf1.insertView( 1, pycinema.theater.views.PlotBarView() )
vf1.setSizes([425, 424])
vf0.setSizes([848, 847])
PlotBarView_0 = vf1.insertView( 0, pycinema.theater.views.PlotBarView() )
PlotLineView_0 = vf1.insertView( 1, pycinema.theater.views.PlotLineView() )
PlotScatterView_0 = vf1.insertView( 2, pycinema.theater.views.PlotScatterView() )
vf1.setSizes([292, 288, 295])
vf0.setSizes([706, 705])

# filters
CinemaDatabaseReader_0 = pycinema.filters.CinemaDatabaseReader()
PlotLineItem_0 = pycinema.filters.PlotLineItem()
PlotBarItem_0 = pycinema.filters.PlotBarItem()
PlotLineItem_0 = pycinema.filters.PlotLineItem()
PlotScatterItem_0 = pycinema.filters.PlotScatterItem()

# properties
PlotLineView_0.inputs.title.set("Sample Line Chart", False)
PlotLineView_0.inputs.background.set("white", False)
PlotLineView_0.inputs.plotitem.set(PlotLineItem_0.outputs.plotitem, False)
PlotBarView_0.inputs.title.set("Plot Title", False)
PlotBarView_0.inputs.background.set("white", False)
PlotBarView_0.inputs.plotitem.set(PlotBarItem_0.outputs.plotitem, False)
PlotLineView_0.inputs.title.set("Plot Title", False)
PlotLineView_0.inputs.background.set("white", False)
PlotLineView_0.inputs.plotitem.set(PlotLineItem_0.outputs.plotitem, False)
PlotScatterView_0.inputs.title.set("Plot Title", False)
PlotScatterView_0.inputs.background.set("white", False)
PlotScatterView_0.inputs.plotitem.set(PlotScatterItem_0.outputs.plotitem, False)
CinemaDatabaseReader_0.inputs.path.set("data/plot-line.cdb", False)
CinemaDatabaseReader_0.inputs.file_column.set("FILE", False)
PlotLineItem_0.inputs.table.set(CinemaDatabaseReader_0.outputs.table, False)
PlotLineItem_0.inputs.x.set("b", False)
PlotLineItem_0.inputs.y.set("c", False)
PlotLineItem_0.inputs.linetype.set("default", False)
PlotLineItem_0.inputs.linecolor.set("red", False)
PlotLineItem_0.inputs.linewidth.set(1.0, False)
PlotBarItem_0.inputs.table.set(CinemaDatabaseReader_0.outputs.table, False)
PlotBarItem_0.inputs.x.set("a", False)
PlotBarItem_0.inputs.y.set("b", False)
PlotBarItem_0.inputs.barcolor.set("blue", False)
PlotBarItem_0.inputs.barwidth.set(0.5, False)
PlotBarItem_0.inputs.brushcolor.set("blue", False)
PlotBarItem_0.inputs.width.set(0.5, False)
PlotLineItem_0.inputs.table.set(CinemaDatabaseReader_0.outputs.table, False)
PlotLineItem_0.inputs.x.set("a", False)
PlotLineItem_0.inputs.y.set("b", False)
PlotLineItem_0.inputs.penstyle.set("dash", False)
PlotLineItem_0.inputs.pencolor.set("red", False)
PlotLineItem_0.inputs.penwidth.set(2.0, False)
PlotScatterItem_0.inputs.table.set(CinemaDatabaseReader_0.outputs.table, False)
PlotScatterItem_0.inputs.x.set("a", False)
PlotScatterItem_0.inputs.y.set("b", False)
PlotScatterItem_0.inputs.pencolor.set("black", False)
PlotScatterItem_0.inputs.penwidth.set(1.0, False)
PlotScatterItem_0.inputs.brushcolor.set("gray", False)
PlotScatterItem_0.inputs.symbol.set("o", False)
PlotScatterItem_0.inputs.size.set(5.0, False)

# execute pipeline
PlotLineView_0.update()
PlotBarView_0.update()
40 changes: 40 additions & 0 deletions examples/theater/URLCarScatterplot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import pycinema
import pycinema.filters
import pycinema.theater
import pycinema.theater.views

# pycinema settings
PYCINEMA = { 'VERSION' : '2.0.0'}

# layout
vf0 = pycinema.theater.Theater.instance.centralWidget()
vf0.setHorizontalOrientation()
vf1 = vf0.insertFrame(0)
vf1.setVerticalOrientation()
vf1.insertView( 0, pycinema.theater.views.NodeEditorView() )
TableView_1 = vf1.insertView( 1, pycinema.theater.views.TableView() )
vf1.setSizes([610, 440])
PlotScatterView_0 = vf0.insertView( 1, pycinema.theater.views.PlotScatterView() )
vf0.setSizes([1111, 1110])

# filters
PlotScatterItem_0 = pycinema.filters.PlotScatterItem()
CSVReader_0 = pycinema.filters.CSVReader()

# properties
PlotScatterView_0.inputs.title.set("Electric Range vs. Model Year for Vehicles in Washington State (2023)", False)
PlotScatterView_0.inputs.background.set("white", False)
PlotScatterView_0.inputs.plotitem.set(PlotScatterItem_0.outputs.plotitem, False)
PlotScatterItem_0.inputs.table.set(CSVReader_0.outputs.table, False)
PlotScatterItem_0.inputs.x.set("Model Year", False)
PlotScatterItem_0.inputs.y.set("Electric Range", False)
PlotScatterItem_0.inputs.pencolor.set("default", False)
PlotScatterItem_0.inputs.penwidth.set(1.0, False)
PlotScatterItem_0.inputs.brushcolor.set("light blue", False)
PlotScatterItem_0.inputs.symbol.set("o", False)
PlotScatterItem_0.inputs.size.set(10.0, False)
TableView_1.inputs.table.set(CSVReader_0.outputs.table, False)
CSVReader_0.inputs.path.set("https://data.wa.gov/api/views/f6w7-q2d2/rows.csv?accessType=DOWNLOAD", False)

# execute pipeline
PlotScatterView_0.update()
33 changes: 32 additions & 1 deletion pycinema/Core.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import traceback
import pprint
import re
import numpy as np

class Image():
def __init__(self, channels=None, meta=None):
Expand Down Expand Up @@ -55,14 +56,44 @@ def isNumber(s):
t = type(s)
if t == int or t == float:
return True
if t == str:
else:
# assume it is a string
try:
sf = float(s)
return True
except ValueError:
return False
return False

#
# table helper functions
#

#
# get the column index from a table, return -1 on failure
#
def getColumnIndexFromTable(table, colname):
ID = -1

colnames = table[0]
if colname in colnames:
ID = colnames.index(colname)

return ID

#
# get a column of values from a table
#
def getColumnFromTable(table, colname):
colID = getColumnIndexFromTable(table, colname)

if colID == -1:
print("ERROR: no column named \'" + colname + "\'")
return None

else:
return [row [colID] for row in table[1:]]

def getTableExtent(table):
try:
nRows = len(table)
Expand Down
58 changes: 58 additions & 0 deletions pycinema/filters/CSVReader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from pycinema import Filter, isURL
import csv
import requests
from os.path import exists

class CSVReader(Filter):

def __init__(self):
super().__init__(
inputs={
'path': ''
},
outputs={
'table': [[]]
}
)

def _update(self):

table = []
csvPath = self.inputs.path.get()

if isURL(csvPath):
with requests.Session() as s:
print("requesting " + csvPath)
download = s.get(csvPath)
decoded = download.content.decode('utf-8')
csvdecoded = csv.reader(decoded.splitlines(), delimiter=',')
rows = list(csvdecoded)
for row in rows:
table.append(row)

else:
if not csvPath:
self.outputs.table.set([[]])
return 0

if not exists(csvPath):
print('[ERROR] file not found:', csvPath)
self.outputs.table.set([[]])
return 0

try:
with open(csvPath, 'r+') as csvfile:
rows = csv.reader(csvfile, delimiter=',')
for row in rows:
table.append(row)
except:
print('[ERROR] Unable to open file:', csvPath)
self.outputs.table.set([[]])
return 0

# remove empty lines
table = list(filter(lambda row: len(row)>0, table))

self.outputs.table.set(table)

return 1
58 changes: 58 additions & 0 deletions pycinema/filters/ImageMetadataToScatterItem.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
from .PlotItem import *

import numpy as np

#
# ImageMetadataToScatterItem
#
class ImageMetadataToScatterItem(PlotItem):

def __init__(self):
super().__init__(
inputs={
'images' : [],
'x' : 'none',
'y' : 'none',
'pencolor' : 'default',
'penwidth' : 1.0,
'brushcolor': 'default',
'symbol' : 'x',
'size' : 1.0
},
outputs={
'plotitem' : {}
}
)

def _update(self):

xdata = []
ydata = []
xlabel = self.inputs.x.get()
ylabel = self.inputs.y.get()
for image in self.inputs.images.get():
xdata.append(image.meta[xlabel])
ydata.append(image.meta[ylabel])

out = { 'x' : {
'label' : self.inputs.x.get(),
'data' : xdata
},
'y' : {
'label' : self.inputs.y.get(),
'data' : ydata
},
'pen' : {
'color' : self.inputs.pencolor.get(),
'width' : self.inputs.penwidth.get(),
},
'brush' : {
'color' : self.inputs.brushcolor.get()
},
'symbol': self.inputs.symbol.get(),
'size' : self.inputs.size.get()
}
self.outputs.plotitem.set({})
self.outputs.plotitem.set(out)

return 1
18 changes: 8 additions & 10 deletions pycinema/filters/PlotBarItem.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,17 @@ def __init__(self):
'table' : None,
'x' : 'none',
'y' : 'none',
'barcolor' : 'default',
'barwidth' : 1.0
'brushcolor': 'default',
'width' : 1.0
},
outputs={
'plotitem' : {}
}
)

def _update(self):
xID = self._getColumnIndex(self.inputs.x.get())
xdata = self._getFloatArrayFromTable(xID)
yID = self._getColumnIndex(self.inputs.y.get())
ydata = self._getFloatArrayFromTable(yID)
xdata = self._getColumnFromTable(self.inputs.x.get())
ydata = self._getColumnFromTable(self.inputs.y.get())

out = { 'x' : {
'label' : self.inputs.x.get(),
Expand All @@ -39,10 +37,10 @@ def _update(self):
'label' : self.inputs.y.get(),
'data' : ydata
},
'bar' : {
'color' : self.inputs.barcolor.get(),
'width' : self.inputs.barwidth.get()
}
'brush' : {
'color' : self.inputs.brushcolor.get(),
},
'width' : self.inputs.width.get()
}
self.outputs.plotitem.set({})
self.outputs.plotitem.set(out)
Expand Down
18 changes: 3 additions & 15 deletions pycinema/filters/PlotItem.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from pycinema import Filter
from pycinema import Filter, isNumber, getColumnFromTable

import PIL
import numpy as np
Expand All @@ -15,17 +15,5 @@ class PlotItem(Filter):
def __init__(self, inputs={}, outputs={}):
super().__init__(inputs, outputs)

def _getColumnIndex(self, colname):
ID = 0

colnames = self.inputs.table.get()[0]
ID = colnames.index(colname)

return ID

def _getFloatArrayFromTable(self, colID):
data = self.inputs.table.get()
t = np.array(data)
row = t[:, colID]

return row[1:].astype(float)
def _getColumnFromTable(self, colname):
return getColumnFromTable(self.inputs.table.get(), colname)
20 changes: 9 additions & 11 deletions pycinema/filters/PlotLineItem.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,18 @@ def __init__(self):
'table' : None,
'x' : 'none',
'y' : 'none',
'linetype' : 'default',
'linecolor' : 'default',
'linewidth' : 1.0
'penstyle' : 'default',
'pencolor' : 'default',
'penwidth' : 1.0
},
outputs={
'plotitem' : 'none'
}
)

def _update(self):
xID = self._getColumnIndex(self.inputs.x.get())
xdata = self._getFloatArrayFromTable(xID)
yID = self._getColumnIndex(self.inputs.y.get())
ydata = self._getFloatArrayFromTable(yID)
xdata = self._getColumnFromTable(self.inputs.x.get())
ydata = self._getColumnFromTable(self.inputs.y.get())

out = { 'x' : {
'label' : self.inputs.x.get(),
Expand All @@ -38,10 +36,10 @@ def _update(self):
'label' : self.inputs.y.get(),
'data' : ydata
},
'line' : {
'type' : self.inputs.linetype.get(),
'color' : self.inputs.linecolor.get(),
'width' : self.inputs.linewidth.get()
'pen' : {
'style' : self.inputs.penstyle.get(),
'color' : self.inputs.pencolor.get(),
'width' : self.inputs.penwidth.get()
}
}
self.outputs.plotitem.set({})
Expand Down
Loading

0 comments on commit fd4f199

Please sign in to comment.