import numpy as np
import PyQt5 # make sure pyqtgraph imports Qt5
import pyqtgraph
from artiq.applets .simple import TitleApplet
class XYPlot( pyqtgraph.PlotWidget ) :
def __init__ ( self , args) :
pyqtgraph.PlotWidget .__init__ ( self )
self .args = args
def data_changed( self , data, mods, title) :
try :
y = data[ self .args .y ] [ 1 ]
except KeyError :
return
x = data.get ( self .args .x , ( False , None ) ) [ 1 ]
if x is None :
x = np.arange ( len ( y) )
error = data.get ( self .args .error , ( False , None ) ) [ 1 ]
fit = data.get ( self .args .fit , ( False , None ) ) [ 1 ]
if not len ( y) or len ( y) != len ( x) :
return
if error is not None and hasattr ( error, "__len__" ) :
if not len ( error) :
error = None
elif len ( error) != len ( y) :
return
if fit is not None :
if not len ( fit) :
fit = None
elif len ( fit) != len ( y) :
return
self .clear ( )
self .plot ( x, y, pen= None , symbol = "x" )
self .setTitle ( title)
if error is not None :
# See https://g...content-available-to-author-only...b.com/pyqtgraph/pyqtgraph/issues/211
if hasattr ( error, "__len__" ) and not isinstance ( error, np.ndarray ) :
error = np.array ( error)
errbars = pyqtgraph.ErrorBarItem (
x= np.array ( x) , y= np.array ( y) , height= error)
self .addItem ( errbars)
if fit is not None :
xi = np.argsort ( x)
self .plot ( x[ xi] , fit[ xi] )
def main( ) :
applet = TitleApplet( XYPlot)
applet.add_dataset ( "y" , "Y values" )
applet.add_dataset ( "x" , "X values" , required= False )
applet.add_dataset ( "error" , "Error bars for each X value" , required= False )
applet.add_dataset ( "fit" , "Fit values for each X value" , required= False )
applet.run ( )
if __name__ == "__main__" :
main( )
aW1wb3J0IG51bXB5IGFzIG5wCmltcG9ydCBQeVF0NSAgIyBtYWtlIHN1cmUgcHlxdGdyYXBoIGltcG9ydHMgUXQ1CmltcG9ydCBweXF0Z3JhcGgKCmZyb20gYXJ0aXEuYXBwbGV0cy5zaW1wbGUgaW1wb3J0IFRpdGxlQXBwbGV0CgoKY2xhc3MgWFlQbG90KHB5cXRncmFwaC5QbG90V2lkZ2V0KToKICAgIGRlZiBfX2luaXRfXyhzZWxmLCBhcmdzKToKICAgICAgICBweXF0Z3JhcGguUGxvdFdpZGdldC5fX2luaXRfXyhzZWxmKQogICAgICAgIHNlbGYuYXJncyA9IGFyZ3MKCiAgICBkZWYgZGF0YV9jaGFuZ2VkKHNlbGYsIGRhdGEsIG1vZHMsIHRpdGxlKToKICAgICAgICB0cnk6CiAgICAgICAgICAgIHkgPSBkYXRhW3NlbGYuYXJncy55XVsxXQogICAgICAgIGV4Y2VwdCBLZXlFcnJvcjoKICAgICAgICAgICAgcmV0dXJuCiAgICAgICAgeCA9IGRhdGEuZ2V0KHNlbGYuYXJncy54LCAoRmFsc2UsIE5vbmUpKVsxXQogICAgICAgIGlmIHggaXMgTm9uZToKICAgICAgICAgICAgeCA9IG5wLmFyYW5nZShsZW4oeSkpCiAgICAgICAgZXJyb3IgPSBkYXRhLmdldChzZWxmLmFyZ3MuZXJyb3IsIChGYWxzZSwgTm9uZSkpWzFdCiAgICAgICAgZml0ID0gZGF0YS5nZXQoc2VsZi5hcmdzLmZpdCwgKEZhbHNlLCBOb25lKSlbMV0KCiAgICAgICAgaWYgbm90IGxlbih5KSBvciBsZW4oeSkgIT0gbGVuKHgpOgogICAgICAgICAgICByZXR1cm4KICAgICAgICBpZiBlcnJvciBpcyBub3QgTm9uZSBhbmQgaGFzYXR0cihlcnJvciwgIl9fbGVuX18iKToKICAgICAgICAgICAgaWYgbm90IGxlbihlcnJvcik6CiAgICAgICAgICAgICAgICBlcnJvciA9IE5vbmUKICAgICAgICAgICAgZWxpZiBsZW4oZXJyb3IpICE9IGxlbih5KToKICAgICAgICAgICAgICAgIHJldHVybgogICAgICAgIGlmIGZpdCBpcyBub3QgTm9uZToKICAgICAgICAgICAgaWYgbm90IGxlbihmaXQpOgogICAgICAgICAgICAgICAgZml0ID0gTm9uZQogICAgICAgICAgICBlbGlmIGxlbihmaXQpICE9IGxlbih5KToKICAgICAgICAgICAgICAgIHJldHVybgoKICAgICAgICBzZWxmLmNsZWFyKCkKICAgICAgICBzZWxmLnBsb3QoeCwgeSwgcGVuPU5vbmUsIHN5bWJvbD0ieCIpCiAgICAgICAgc2VsZi5zZXRUaXRsZSh0aXRsZSkKICAgICAgICBpZiBlcnJvciBpcyBub3QgTm9uZToKICAgICAgICAgICAgIyBTZWUgaHR0cHM6Ly9nLi4uY29udGVudC1hdmFpbGFibGUtdG8tYXV0aG9yLW9ubHkuLi5iLmNvbS9weXF0Z3JhcGgvcHlxdGdyYXBoL2lzc3Vlcy8yMTEKICAgICAgICAgICAgaWYgaGFzYXR0cihlcnJvciwgIl9fbGVuX18iKSBhbmQgbm90IGlzaW5zdGFuY2UoZXJyb3IsIG5wLm5kYXJyYXkpOgogICAgICAgICAgICAgICAgZXJyb3IgPSBucC5hcnJheShlcnJvcikKICAgICAgICAgICAgZXJyYmFycyA9IHB5cXRncmFwaC5FcnJvckJhckl0ZW0oCiAgICAgICAgICAgICAgICB4PW5wLmFycmF5KHgpLCB5PW5wLmFycmF5KHkpLCBoZWlnaHQ9ZXJyb3IpCiAgICAgICAgICAgIHNlbGYuYWRkSXRlbShlcnJiYXJzKQogICAgICAgIGlmIGZpdCBpcyBub3QgTm9uZToKICAgICAgICAgICAgeGkgPSBucC5hcmdzb3J0KHgpCiAgICAgICAgICAgIHNlbGYucGxvdCh4W3hpXSwgZml0W3hpXSkKCgpkZWYgbWFpbigpOgogICAgYXBwbGV0ID0gVGl0bGVBcHBsZXQoWFlQbG90KQogICAgYXBwbGV0LmFkZF9kYXRhc2V0KCJ5IiwgIlkgdmFsdWVzIikKICAgIGFwcGxldC5hZGRfZGF0YXNldCgieCIsICJYIHZhbHVlcyIsIHJlcXVpcmVkPUZhbHNlKQogICAgYXBwbGV0LmFkZF9kYXRhc2V0KCJlcnJvciIsICJFcnJvciBiYXJzIGZvciBlYWNoIFggdmFsdWUiLCByZXF1aXJlZD1GYWxzZSkKICAgIGFwcGxldC5hZGRfZGF0YXNldCgiZml0IiwgIkZpdCB2YWx1ZXMgZm9yIGVhY2ggWCB2YWx1ZSIsIHJlcXVpcmVkPUZhbHNlKQogICAgYXBwbGV0LnJ1bigpCgppZiBfX25hbWVfXyA9PSAiX19tYWluX18iOgogICAgbWFpbigp