class SVGExporter(Exporter): Name = "Scalable Vector Graphics (SVG)" allowCopy = True def __init__(self, item): Exporter.__init__(self, item) # tr = self.getTargetRect() self.params = Parameter( name="params", type="group", children=[ # {'name': 'width', 'type': 'float', 'value': tr.width(), 'limits': (0, None)}, # {'name': 'height', 'type': 'float', 'value': tr.height(), 'limits': (0, None)}, # {'name': 'viewbox clipping', 'type': 'bool', 'value': True}, # {'name': 'normalize coordinates', 'type': 'bool', 'value': True}, # {'name': 'normalize line width', 'type': 'bool', 'value': True}, ], ) # self.params.param('width').sigValueChanged.connect(self.widthChanged) # self.params.param('height').sigValueChanged.connect(self.heightChanged) def widthChanged(self): sr = self.getSourceRect() ar = sr.height() / sr.width() self.params.param("height").setValue(self.params["width"] * ar, blockSignal=self.heightChanged) def heightChanged(self): sr = self.getSourceRect() ar = sr.width() / sr.height() self.params.param("width").setValue(self.params["height"] * ar, blockSignal=self.widthChanged) def parameters(self): return self.params def export(self, fileName=None, toBytes=False, copy=False): if toBytes is False and copy is False and fileName is None: self.fileSaveDialog(filter="Scalable Vector Graphics (*.svg)") return ## Qt's SVG generator is not complete. (notably, it lacks clipping) ## Instead, we will use Qt to generate SVG for each item independently, ## then manually reconstruct the entire document. xml = generateSvg(self.item) if toBytes: return xml.encode("UTF-8") elif copy: md = QtCore.QMimeData() md.setData("image/svg+xml", QtCore.QByteArray(xml.encode("UTF-8"))) QtGui.QApplication.clipboard().setMimeData(md) else: with open(fileName, "wb") as fh: fh.write(asUnicode(xml).encode("utf-8"))
class ImageExporter(Exporter): Name = "Image File (PNG, TIF, JPG, ...)" def __init__(self, item): Exporter.__init__(self, item) tr = self.getTargetRect() self.params = Parameter(name='params', type='group', children=[ {'name': 'width', 'type': 'int', 'value': tr.width(), 'limits': (0, None)}, {'name': 'height', 'type': 'int', 'value': tr.height(), 'limits': (0, None)}, {'name': 'antialias', 'type': 'bool', 'value': True}, {'name': 'background', 'type': 'color', 'value': (0,0,0,255)}, ]) self.params.param('width').sigValueChanged.connect(self.widthChanged) self.params.param('height').sigValueChanged.connect(self.heightChanged) def widthChanged(self): sr = self.getSourceRect() ar = sr.height() / sr.width() self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged) def heightChanged(self): sr = self.getSourceRect() ar = sr.width() / sr.height() self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged) def parameters(self): return self.params def export(self, fileName=None): if fileName is None: filter = ["*."+str(f) for f in QtGui.QImageWriter.supportedImageFormats()] preferred = ['*.png', '*.tif', '*.jpg'] for p in preferred[::-1]: if p in filter: filter.remove(p) filter.insert(0, p) self.fileSaveDialog(filter=filter) return targetRect = QtCore.QRect(0, 0, self.params['width'], self.params['height']) sourceRect = self.getSourceRect() #self.png = QtGui.QImage(targetRect.size(), QtGui.QImage.Format_ARGB32) #self.png.fill(pyqtgraph.mkColor(self.params['background'])) bg = np.empty((self.params['width'], self.params['height'], 4), dtype=np.ubyte) color = self.params['background'] bg[:,:,0] = color.blue() bg[:,:,1] = color.green() bg[:,:,2] = color.red() bg[:,:,3] = color.alpha() self.png = pg.makeQImage(bg, alpha=True) painter = QtGui.QPainter(self.png) try: self.setExportMode(True, {'antialias': self.params['antialias'], 'background': self.params['background']}) self.getScene().render(painter, QtCore.QRectF(targetRect), sourceRect) finally: self.setExportMode(False) self.png.save(fileName) painter.end()
class SVGExporter(Exporter): Name = "Scalable Vector Graphics (SVG)" allowCopy = True def __init__(self, item): Exporter.__init__(self, item) #tr = self.getTargetRect() self.params = Parameter(name='params', type='group', children=[ #{'name': 'width', 'type': 'float', 'value': tr.width(), 'limits': (0, None)}, #{'name': 'height', 'type': 'float', 'value': tr.height(), 'limits': (0, None)}, #{'name': 'viewbox clipping', 'type': 'bool', 'value': True}, #{'name': 'normalize coordinates', 'type': 'bool', 'value': True}, #{'name': 'normalize line width', 'type': 'bool', 'value': True}, ]) #self.params.param('width').sigValueChanged.connect(self.widthChanged) #self.params.param('height').sigValueChanged.connect(self.heightChanged) def widthChanged(self): sr = self.getSourceRect() ar = sr.height() / sr.width() self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged) def heightChanged(self): sr = self.getSourceRect() ar = sr.width() / sr.height() self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged) def parameters(self): return self.params def export(self, fileName=None, toBytes=False, copy=False): if toBytes is False and copy is False and fileName is None: self.fileSaveDialog(filter="Scalable Vector Graphics (*.svg)") return ## Qt's SVG generator is not complete. (notably, it lacks clipping) ## Instead, we will use Qt to generate SVG for each item independently, ## then manually reconstruct the entire document. xml = generateSvg(self.item) if toBytes: return xml.encode('UTF-8') elif copy: md = QtCore.QMimeData() md.setData('image/svg+xml', QtCore.QByteArray(xml.encode('UTF-8'))) QtGui.QApplication.clipboard().setMimeData(md) else: with open(fileName, 'wb') as fh: fh.write(asUnicode(xml).encode('utf-8'))
class PrintExporter(Exporter): Name = "Printer" def __init__(self, item): Exporter.__init__(self, item) tr = self.getTargetRect() self.params = Parameter(name='params', type='group', children=[ {'name': 'width', 'type': 'float', 'value': 0.1, 'limits': (0, None), 'suffix': 'm', 'siPrefix': True}, {'name': 'height', 'type': 'float', 'value': (0.1 * tr.height()) / tr.width(), 'limits': (0, None), 'suffix': 'm', 'siPrefix': True}, ]) self.params.param('width').sigValueChanged.connect(self.widthChanged) self.params.param('height').sigValueChanged.connect(self.heightChanged) def widthChanged(self): sr = self.getSourceRect() ar = sr.height() / sr.width() self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged) def heightChanged(self): sr = self.getSourceRect() ar = sr.width() / sr.height() self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged) def parameters(self): return self.params def export(self, fileName=None): printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution) dialog = QtGui.QPrintDialog(printer) dialog.setWindowTitle("Print Document") if dialog.exec_() != QtGui.QDialog.Accepted: return; #dpi = QtGui.QDesktopWidget().physicalDpiX() #self.svg.setSize(QtCore.QSize(100,100)) #self.svg.setResolution(600) #res = printer.resolution() sr = self.getSourceRect() #res = sr.width() * .4 / (self.params['width'] * 100 / 2.54) res = QtGui.QDesktopWidget().physicalDpiX() printer.setResolution(res) rect = printer.pageRect() center = rect.center() h = self.params['height'] * res * 100. / 2.54 w = self.params['width'] * res * 100. / 2.54 x = center.x() - w/2. y = center.y() - h/2. targetRect = QtCore.QRect(x, y, w, h) sourceRect = self.getSourceRect() painter = QtGui.QPainter(printer) try: self.setExportMode(True, {'painter': painter}) self.getScene().render(painter, QtCore.QRectF(targetRect), QtCore.QRectF(sourceRect)) finally: self.setExportMode(False) painter.end()
class VideoExporter(Exporter): """ A custom class that allows exporting pyqtgraph elements as video. Choosing this as an export option opens a new window which displays the part of the program being recorded. """ Name = "Video file" allowCopy = True def __init__(self, item): Exporter.__init__(self, item) tr = self.getTargetRect() if isinstance(item, QGraphicsItem): scene = item.scene() else: scene = item bgbrush = scene.views()[0].backgroundBrush() bg = bgbrush.color() if bgbrush.style() == QtCore.Qt.NoBrush: bg.setAlpha(0) self.item = item self.params = Parameter(name='params', type='group', children=[ {'name': 'width', 'type': 'int', 'value': tr.width(), 'limits': (0, None)}, {'name': 'height', 'type': 'int', 'value': tr.height(), 'limits': (0, None)}, {'name': 'antialias', 'type': 'bool', 'value': True}, {'name': 'background', 'type': 'color', 'value': bg}, ]) self.params.param('width').sigValueChanged.connect(self.widthChanged) self.params.param('height').sigValueChanged.connect(self.heightChanged) def widthChanged(self): sr = self.getSourceRect() ar = float(sr.height()) / sr.width() self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged) def heightChanged(self): sr = self.getSourceRect() ar = float(sr.width()) / sr.height() self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged) def parameters(self): return self.params def export(self, fileName=None, toBytes=False, copy=False): area = self.getTargetRect() point = QtCore.QPoint(area.left(), area.top()) if isinstance(self.item, GraphicsScene): global_point = self.item.parent().mapToGlobal(point) w, h = self.params["width"], self.params["height"] else: global_point = self.item.scene().parent().mapToGlobal(point) w, h = self.params["width"] + 10, self.params["height"] + 10 self.video = VideoPlayer(w, h, global_point) self.video.show()
class PrintExporter(Exporter): Name = "Printer" def __init__(self, item): Exporter.__init__(self, item) tr = self.getTargetRect() self.params = Parameter(name='params', type='group', children=[ {'name': 'width', 'type': 'float', 'value': 0.1, 'limits': (0, None), 'suffix': 'm', 'siPrefix': True}, {'name': 'height', 'type': 'float', 'value': (0.1 * tr.height()) / tr.width(), 'limits': (0, None), 'suffix': 'm', 'siPrefix': True}, ]) self.params.param('width').sigValueChanged.connect(self.widthChanged) self.params.param('height').sigValueChanged.connect(self.heightChanged) def widthChanged(self): sr = self.getSourceRect() ar = sr.height() / sr.width() self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged) def heightChanged(self): sr = self.getSourceRect() ar = sr.width() / sr.height() self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged) def parameters(self): return self.params def export(self, fileName=None): printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution) dialog = QtGui.QPrintDialog(printer) dialog.setWindowTitle("Print Document") if dialog.exec_() != QtGui.QDialog.Accepted: return; #self.svg.setSize(QtCore.QSize(100,100)) #self.svg.setResolution(600) res = printer.resolution() rect = printer.pageRect() center = rect.center() h = self.params['height'] * res * 100. / 2.54 w = self.params['width'] * res * 100. / 2.54 x = center.x() - w/2. y = center.y() - h/2. targetRect = QtCore.QRect(x, y, w, h) sourceRect = self.getSourceRect() painter = QtGui.QPainter(printer) try: self.setExportMode(True) self.getScene().render(painter, QtCore.QRectF(targetRect), sourceRect) finally: self.setExportMode(False) painter.end()
class PQG_ImageExporter(Exporter): Name = "Working Image Exporter (PNG, TIF, JPG, ...)" allowCopy = True def __init__(self, item): Exporter.__init__(self, item) tr = self.getTargetRect() if isinstance(item, QtGui.QGraphicsItem): scene = item.scene() else: scene = item # scene.views()[0].backgroundBrush() bgbrush = pg.mkBrush('w') bg = bgbrush.color() if bgbrush.style() == QtCore.Qt.NoBrush: bg.setAlpha(0) self.params = Parameter(name='params', type='group', children=[ { 'name': 'width', 'type': 'int', 'value': tr.width(), 'limits': (0, None) }, { 'name': 'height', 'type': 'int', 'value': tr.height(), 'limits': (0, None) }, { 'name': 'antialias', 'type': 'bool', 'value': True }, { 'name': 'background', 'type': 'color', 'value': bg }, ]) self.params.param('width').sigValueChanged.connect(self.widthChanged) self.params.param('height').sigValueChanged.connect(self.heightChanged) def widthChanged(self): sr = self.getSourceRect() ar = float(sr.height()) / sr.width() self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged) def heightChanged(self): sr = self.getSourceRect() ar = float(sr.width()) / sr.height() self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged) def parameters(self): return self.params def export(self, fileName=None, toBytes=False, copy=False): if fileName is None and not toBytes and not copy: if USE_PYSIDE: filter = [ "*." + str(f) for f in QtGui.QImageWriter.supportedImageFormats() ] else: filter = [ "*." + bytes(f).decode('utf-8') for f in QtGui.QImageWriter.supportedImageFormats() ] preferred = ['*.png', '*.tif', '*.jpg'] for p in preferred[::-1]: if p in filter: filter.remove(p) filter.insert(0, p) self.fileSaveDialog(filter=filter) return targetRect = QtCore.QRect(0, 0, self.params['width'], self.params['height']) sourceRect = self.getSourceRect() #self.png = QtGui.QImage(targetRect.size(), QtGui.QImage.Format_ARGB32) # self.png.fill(pyqtgraph.mkColor(self.params['background'])) w, h = self.params['width'], self.params['height'] if w == 0 or h == 0: raise Exception( "Cannot export image with size=0 (requested export size is %dx%d)" % (w, h)) bg = np.empty( (int(self.params['width']), int(self.params['height']), 4), dtype=np.ubyte) color = self.params['background'] bg[:, :, 0] = color.blue() bg[:, :, 1] = color.green() bg[:, :, 2] = color.red() bg[:, :, 3] = color.alpha() self.png = fn.makeQImage(bg, alpha=True) # set resolution of image: origTargetRect = self.getTargetRect() resolutionScale = targetRect.width() / origTargetRect.width() #self.png.setDotsPerMeterX(self.png.dotsPerMeterX() * resolutionScale) #self.png.setDotsPerMeterY(self.png.dotsPerMeterY() * resolutionScale) painter = QtGui.QPainter(self.png) #dtr = painter.deviceTransform() try: self.setExportMode( True, { 'antialias': self.params['antialias'], 'background': self.params['background'], 'painter': painter, 'resolutionScale': resolutionScale }) painter.setRenderHint(QtGui.QPainter.Antialiasing, self.params['antialias']) self.getScene().render(painter, QtCore.QRectF(targetRect), QtCore.QRectF(sourceRect)) finally: self.setExportMode(False) painter.end() if copy: QtGui.QApplication.clipboard().setImage(self.png) elif toBytes: return self.png else: self.png.save(fileName)
class ImageExporter(Exporter): Name = "Image File (PNG, TIF, JPG, ...)" allowCopy = True def __init__(self, item): Exporter.__init__(self, item) tr = self.getTargetRect() if isinstance(item, QtGui.QGraphicsItem): scene = item.scene() else: scene = item bgbrush = scene.views()[0].backgroundBrush() bg = bgbrush.color() if bgbrush.style() == QtCore.Qt.NoBrush: bg.setAlpha(0) self.params = Parameter( name="params", type="group", children=[ {"name": "width", "type": "int", "value": tr.width(), "limits": (0, None)}, {"name": "height", "type": "int", "value": tr.height(), "limits": (0, None)}, {"name": "antialias", "type": "bool", "value": True}, {"name": "background", "type": "color", "value": bg}, ], ) self.params.param("width").sigValueChanged.connect(self.widthChanged) self.params.param("height").sigValueChanged.connect(self.heightChanged) def widthChanged(self): sr = self.getSourceRect() ar = float(sr.height()) / sr.width() self.params.param("height").setValue(self.params["width"] * ar, blockSignal=self.heightChanged) def heightChanged(self): sr = self.getSourceRect() ar = float(sr.width()) / sr.height() self.params.param("width").setValue(self.params["height"] * ar, blockSignal=self.widthChanged) def parameters(self): return self.params def export(self, fileName=None, toBytes=False, copy=False): if fileName is None and not toBytes and not copy: if USE_PYSIDE: filter = ["*." + str(f) for f in QtGui.QImageWriter.supportedImageFormats()] else: filter = ["*." + bytes(f).decode("utf-8") for f in QtGui.QImageWriter.supportedImageFormats()] preferred = ["*.png", "*.tif", "*.jpg"] for p in preferred[::-1]: if p in filter: filter.remove(p) filter.insert(0, p) self.fileSaveDialog(filter=filter) return targetRect = QtCore.QRect(0, 0, self.params["width"], self.params["height"]) sourceRect = self.getSourceRect() # self.png = QtGui.QImage(targetRect.size(), QtGui.QImage.Format_ARGB32) # self.png.fill(pyqtgraph.mkColor(self.params['background'])) bg = np.empty((self.params["width"], self.params["height"], 4), dtype=np.ubyte) color = self.params["background"] bg[:, :, 0] = color.blue() bg[:, :, 1] = color.green() bg[:, :, 2] = color.red() bg[:, :, 3] = color.alpha() self.png = pg.makeQImage(bg, alpha=True) ## set resolution of image: origTargetRect = self.getTargetRect() resolutionScale = targetRect.width() / origTargetRect.width() # self.png.setDotsPerMeterX(self.png.dotsPerMeterX() * resolutionScale) # self.png.setDotsPerMeterY(self.png.dotsPerMeterY() * resolutionScale) painter = QtGui.QPainter(self.png) # dtr = painter.deviceTransform() try: self.setExportMode( True, { "antialias": self.params["antialias"], "background": self.params["background"], "painter": painter, "resolutionScale": resolutionScale, }, ) painter.setRenderHint(QtGui.QPainter.Antialiasing, self.params["antialias"]) self.getScene().render(painter, QtCore.QRectF(targetRect), QtCore.QRectF(sourceRect)) finally: self.setExportMode(False) painter.end() if copy: QtGui.QApplication.clipboard().setImage(self.png) elif toBytes: return self.png else: self.png.save(fileName)
class PytplotExporter(pg.exporters.ImageExporter): def __init__(self, item): Exporter.__init__(self, item) tr = self.getTargetRect() if isinstance(item, QtGui.QGraphicsItem): scene = item.scene() else: scene = item # CHANGE: Used to be scene.views()[0].backgroundBrush() # That wasn't how to access the background of a GraphicsLayout object bgbrush = scene.backgroundBrush() bg = bgbrush.color() if bgbrush.style() == QtCore.Qt.NoBrush: bg.setAlpha(0) self.params = Parameter(name='params', type='group', children=[ { 'name': 'width', 'type': 'int', 'value': tr.width(), 'limits': (0, None) }, { 'name': 'height', 'type': 'int', 'value': tr.height(), 'limits': (0, None) }, { 'name': 'antialias', 'type': 'bool', 'value': True }, { 'name': 'background', 'type': 'color', 'value': bg }, ]) self.params.param('width').sigValueChanged.connect(self.widthChanged) self.params.param('height').sigValueChanged.connect(self.heightChanged) def export(self, fileName=None, toBytes=False, copy=False): if fileName is None and not toBytes and not copy: if pg.Qt.USE_PYSIDE: filter = [ "*." + str(f) for f in QtGui.QImageWriter.supportedImageFormats() ] else: filter = [ "*." + bytes(f).decode('utf-8') for f in QtGui.QImageWriter.supportedImageFormats() ] preferred = ['*.png', '*.tif', '*.jpg'] for p in preferred[::-1]: if p in filter: filter.remove(p) filter.insert(0, p) self.fileSaveDialog(filter=filter) return targetRect = QtCore.QRect(0, 0, self.params['width'], self.params['height']) sourceRect = self.getSourceRect() # self.png = QtGui.QImage(targetRect.size(), QtGui.QImage.Format_ARGB32) # self.png.fill(pyqtgraph.mkColor(self.params['background'])) w, h = self.params['width'], self.params['height'] if w == 0 or h == 0: raise Exception( "Cannot export image with size=0 (requested export size is %dx%d)" % (w, h)) bg = np.empty( (int(self.params['width']), int(self.params['height']), 4), dtype=np.ubyte) color = self.params['background'] bg[:, :, 0] = color.blue() bg[:, :, 1] = color.green() bg[:, :, 2] = color.red() bg[:, :, 3] = color.alpha() self.png = fn.makeQImage(bg, alpha=True) # set resolution of image: origTargetRect = self.getTargetRect() resolutionScale = targetRect.width() / origTargetRect.width() painter = QtGui.QPainter(self.png) # dtr = painter.deviceTransform() try: self.setExportMode( True, { 'antialias': self.params['antialias'], 'background': self.params['background'], 'painter': painter, 'resolutionScale': resolutionScale }) painter.setRenderHint(QtGui.QPainter.Antialiasing, self.params['antialias']) # CHANGE: Rendering the scence twice onto the QImage. The first time, make it one pixel in size. # Next, render the full thing. No idea why we need to render is twice, but we do. self.getScene().render(painter, QtCore.QRectF(0, 0, 1, 1), QtCore.QRectF(0, 0, 1, 1)) self.getScene().render(painter, QtCore.QRectF(targetRect), QtCore.QRectF(sourceRect)) finally: self.setExportMode(False) painter.end() if copy: QtGui.QApplication.clipboard().setImage(self.png) elif toBytes: return self.png else: self.png.save(fileName) def getPaintItems(self, root=None): """Return a list of all items that should be painted in the correct order.""" if root is None: root = self.item preItems = [] postItems = [] if isinstance(root, QtGui.QGraphicsScene): childs = [i for i in root.items() if i.parentItem() is None] rootItem = [] else: # CHANGE: For GraphicsLayouts, there is no function for childItems(), so I just # replaced it with .items() try: childs = root.childItems() except: childs = root.items() rootItem = [root] childs.sort(key=lambda a: a.zValue()) while len(childs) > 0: ch = childs.pop(0) tree = self.getPaintItems(ch) if int(ch.flags() & ch.ItemStacksBehindParent) > 0 or ( ch.zValue() < 0 and int(ch.flags() & ch.ItemNegativeZStacksBehindParent) > 0): preItems.extend(tree) else: postItems.extend(tree) return preItems + rootItem + postItems def getTargetRect(self): # CHANGE: Used to return self.item.sceneBoundingRect(). GraphicsLayouts don't have a # sceneBoundingRect(), but they have a rect() which appears to work just as well. return self.item.rect() def getSourceRect(self): # CHANGE: Used to return self.item.mapRectToDevice(self.item.boundingRect()). GraphicsLayouts don't have a # sceneBoundingRect() OR a mapRectToDevice, but they have a rect() which appears to work just as well. return self.item.rect()
class SVGExporter(Exporter): Name = "Scalable Vector Graphics (SVG)" allowCopy=True def __init__(self, item): Exporter.__init__(self, item) #tr = self.getTargetRect() self.params = Parameter(name='params', type='group', children=[ #{'name': 'width', 'type': 'float', 'value': tr.width(), 'limits': (0, None)}, #{'name': 'height', 'type': 'float', 'value': tr.height(), 'limits': (0, None)}, #{'name': 'viewbox clipping', 'type': 'bool', 'value': True}, #{'name': 'normalize coordinates', 'type': 'bool', 'value': True}, #{'name': 'normalize line width', 'type': 'bool', 'value': True}, ]) #self.params.param('width').sigValueChanged.connect(self.widthChanged) #self.params.param('height').sigValueChanged.connect(self.heightChanged) def widthChanged(self): sr = self.getSourceRect() ar = sr.height() / sr.width() self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged) def heightChanged(self): sr = self.getSourceRect() ar = sr.width() / sr.height() self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged) def parameters(self): return self.params def export(self, fileName=None, toBytes=False, copy=False): if toBytes is False and copy is False and fileName is None: self.fileSaveDialog(filter="Scalable Vector Graphics (*.svg)") return #self.svg = QtSvg.QSvgGenerator() #self.svg.setFileName(fileName) #dpi = QtGui.QDesktopWidget().physicalDpiX() ### not really sure why this works, but it seems to be important: #self.svg.setSize(QtCore.QSize(self.params['width']*dpi/90., self.params['height']*dpi/90.)) #self.svg.setResolution(dpi) ##self.svg.setViewBox() #targetRect = QtCore.QRect(0, 0, self.params['width'], self.params['height']) #sourceRect = self.getSourceRect() #painter = QtGui.QPainter(self.svg) #try: #self.setExportMode(True) #self.render(painter, QtCore.QRectF(targetRect), sourceRect) #finally: #self.setExportMode(False) #painter.end() ## Workaround to set pen widths correctly #data = open(fileName).readlines() #for i in range(len(data)): #line = data[i] #m = re.match(r'(<g .*)stroke-width="1"(.*transform="matrix\(([^\)]+)\)".*)', line) #if m is not None: ##print "Matched group:", line #g = m.groups() #matrix = list(map(float, g[2].split(','))) ##print "matrix:", matrix #scale = max(abs(matrix[0]), abs(matrix[3])) #if scale == 0 or scale == 1.0: #continue #data[i] = g[0] + ' stroke-width="%0.2g" ' % (1.0/scale) + g[1] + '\n' ##print "old line:", line ##print "new line:", data[i] #open(fileName, 'w').write(''.join(data)) ## Qt's SVG generator is not complete. (notably, it lacks clipping) ## Instead, we will use Qt to generate SVG for each item independently, ## then manually reconstruct the entire document. xml = generateSvg(self.item) if toBytes: return xml.encode('UTF-8') elif copy: md = QtCore.QMimeData() md.setData('image/svg+xml', QtCore.QByteArray(xml.encode('UTF-8'))) QtGui.QApplication.clipboard().setMimeData(md) else: with open(fileName, 'wb') as fh: fh.write(asUnicode(xml).encode('utf-8'))
class ImageExporter(Exporter): Name = "Image File (PNG, TIF, JPG, ...)" def __init__(self, item): Exporter.__init__(self, item) tr = self.getTargetRect() if isinstance(item, QtGui.QGraphicsItem): scene = item.scene() else: scene = item bg = scene.views()[0].backgroundBrush().color() self.params = Parameter(name='params', type='group', children=[ {'name': 'width', 'type': 'int', 'value': tr.width(), 'limits': (0, None)}, {'name': 'height', 'type': 'int', 'value': tr.height(), 'limits': (0, None)}, {'name': 'antialias', 'type': 'bool', 'value': True}, {'name': 'background', 'type': 'color', 'value': bg}, ]) self.params.param('width').sigValueChanged.connect(self.widthChanged) self.params.param('height').sigValueChanged.connect(self.heightChanged) def widthChanged(self): sr = self.getSourceRect() ar = float(sr.height()) / sr.width() self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged) def heightChanged(self): sr = self.getSourceRect() ar = float(sr.width()) / sr.height() self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged) def parameters(self): return self.params def export(self, fileName=None): if fileName is None: filter = ["*."+str(f) for f in QtGui.QImageWriter.supportedImageFormats()] preferred = ['*.png', '*.tif', '*.jpg'] for p in preferred[::-1]: if p in filter: filter.remove(p) filter.insert(0, p) self.fileSaveDialog(filter=filter) return targetRect = QtCore.QRect(0, 0, self.params['width'], self.params['height']) sourceRect = self.getSourceRect() #self.png = QtGui.QImage(targetRect.size(), QtGui.QImage.Format_ARGB32) #self.png.fill(pyqtgraph.mkColor(self.params['background'])) bg = np.empty((self.params['width'], self.params['height'], 4), dtype=np.ubyte) color = self.params['background'] bg[:,:,0] = color.blue() bg[:,:,1] = color.green() bg[:,:,2] = color.red() bg[:,:,3] = color.alpha() self.png = pg.makeQImage(bg, alpha=True) ## set resolution of image: origTargetRect = self.getTargetRect() resolutionScale = targetRect.width() / origTargetRect.width() #self.png.setDotsPerMeterX(self.png.dotsPerMeterX() * resolutionScale) #self.png.setDotsPerMeterY(self.png.dotsPerMeterY() * resolutionScale) painter = QtGui.QPainter(self.png) #dtr = painter.deviceTransform() try: self.setExportMode(True, {'antialias': self.params['antialias'], 'background': self.params['background'], 'painter': painter, 'resolutionScale': resolutionScale}) painter.setRenderHint(QtGui.QPainter.Antialiasing, self.params['antialias']) self.getScene().render(painter, QtCore.QRectF(targetRect), QtCore.QRectF(sourceRect)) finally: self.setExportMode(False) painter.end() self.png.save(fileName)
class GraphExporter(Exporter): Name = "Image File (PNG, TIF, JPG, ...)" allowCopy = True #Initialize the exporter def __init__(self, item): Exporter.__init__(self, item) tr = self.getTargetRect() if isinstance(item, QtGui.QGraphicsItem): scene = item.scene() else: scene = item bgbrush = scene.views()[0].backgroundBrush() bg = bgbrush.color() if bgbrush.style() == QtCore.Qt.NoBrush: bg.setAlpha(0) self.params = Parameter(name='params', type='group', children=[ { 'name': 'width', 'type': 'int', 'value': tr.width(), 'limits': (0, None) }, { 'name': 'height', 'type': 'int', 'value': tr.height(), 'limits': (0, None) }, { 'name': 'antialias', 'type': 'bool', 'value': True }, { 'name': 'background', 'type': 'color', 'value': bg }, ]) self.params.param('width').sigValueChanged.connect(self.widthChanged) self.params.param('height').sigValueChanged.connect(self.heightChanged) #Adjust the height relative to the width if the width changes def widthChanged(self): sr = self.getSourceRect() ar = float(sr.height()) / sr.width() self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged) #Adjust the width relative to the height if the width changes def heightChanged(self): sr = self.getSourceRect() ar = float(sr.width()) / sr.height() self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged) def parameters(self): return self.params def export(self, fileName=None, toBytes=False, copy=False): if fileName is None and not toBytes and not copy: if USE_PYSIDE: filter = [ "*." + str(f) for f in QtGui.QImageWriter.supportedImageFormats() ] else: filter = [ "*." + bytes(f).decode('utf-8') for f in QtGui.QImageWriter.supportedImageFormats() ] preferred = ['*.png', '*.tif', '*.jpg'] for p in preferred[::-1]: if p in filter: filter.remove(p) filter.insert(0, p) self.fileSaveDialog(filter=filter) return targetRect = QtCore.QRect(0, 0, self.params['width'], self.params['height']) sourceRect = self.getSourceRect() w, h = self.params['width'], self.params['height'] if w == 0 or h == 0: raise Exception( "Cannot export image with size=0 (requested export size is %dx%d)" % (w, h)) #BEFORE #bg = np.empty((self.params['width'], self.params['height'], 4), dtype=np.ubyte) #AFTER bgSize = ((int(self.params['width']), int(self.params['height']), 4)) bg = np.empty(bgSize, dtype=np.ubyte) #... I have no idea why that fixes it, I just guessed around and googled for 3 hours until it worked. #https://groups.google.com/forum/?nomobile=true#!topic/pyqtgraph/4jiAPUpLpF4 #Above link led me on the right track to fixing it but for some reason I also had to declare bgSize separately? color = self.params['background'] bg[:, :, 0] = color.blue() bg[:, :, 1] = color.green() bg[:, :, 2] = color.red() bg[:, :, 3] = color.alpha() self.png = fn.makeQImage(bg, alpha=True) ## set resolution of image: origTargetRect = self.getTargetRect() resolutionScale = targetRect.width() / origTargetRect.width() painter = QtGui.QPainter(self.png) try: self.setExportMode( True, { 'antialias': self.params['antialias'], 'background': self.params['background'], 'painter': painter, 'resolutionScale': resolutionScale }) painter.setRenderHint(QtGui.QPainter.Antialiasing, self.params['antialias']) self.getScene().render(painter, QtCore.QRectF(targetRect), QtCore.QRectF(sourceRect)) finally: self.setExportMode(False) painter.end() if copy: QtGui.QApplication.clipboard().setImage(self.png) elif toBytes: return self.png else: self.png.save(fileName)
class MovieExporter(Exporter): Name = "Movie File (MPEG, MP4)" allowCopy = False def __init__(self, item): Exporter.__init__(self, item) tr = self.getTargetRect() if isinstance(item, QtGui.QGraphicsItem): scene = item.scene() else: scene = item bgbrush = scene.views()[0].backgroundBrush() bg = bgbrush.color() if bgbrush.style() == QtCore.Qt.NoBrush: bg.setAlpha(0) # Search for DaXView wid = self.item.getViewWidget() while wid != None and not isinstance(wid, DaXView.DaXView): wid = wid.parent() self.daxview = wid self.params = Parameter(name='params', type='group', children=[ { 'name': 'width', 'type': 'int', 'value': tr.width(), 'limits': (0, None) }, { 'name': 'height', 'type': 'int', 'value': tr.height(), 'limits': (0, None) }, { 'name': 'frame rate', 'type': 'int', 'value': 20, 'limits': (1, 60) }, { 'name': 'antialias', 'type': 'bool', 'value': True }, { 'name': 'background', 'type': 'color', 'value': bg }, ]) self.params.param('width').sigValueChanged.connect(self.widthChanged) self.params.param('height').sigValueChanged.connect(self.heightChanged) def widthChanged(self): sr = self.getSourceRect() ar = float(sr.height()) / sr.width() self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged) def heightChanged(self): sr = self.getSourceRect() ar = float(sr.width()) / sr.height() self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged) def parameters(self): return self.params def export(self, fileName=None, toBytes=False, copy=False): # Can only export video from DaXView if self.daxview == None: return # Can only write to video if toBytes: return [] # Get filename from user (the fileSaveDialog function calls export after finishing) if fileName is None: self.fileSaveDialog(filter=['*.mpeg', '*.mp4']) return if fileName.endswith('.mpeg') == False and fileName.endswith( '.mp4') == False: fileName = fileName + '.mpeg' # Get directory where video should go dirName = os.path.dirname(fileName) # Play entire sequence and store to temporary PNG files progress = QtGui.QProgressDialog('Exporting movie...', 'Abort', 0, int(self.daxview.data.shape[0] * 1.1)) for i in range(self.daxview.data.shape[0]): # Set current frame self.daxview.setCurrentIndex(i) if i >= self.daxview.data.shape[0]: progress.setLabelText('Generating video...') # Export to png image targetRect = QtCore.QRect(0, 0, self.params['width'], self.params['height']) sourceRect = self.getSourceRect() #self.png = QtGui.QImage(targetRect.size(), QtGui.QImage.Format_ARGB32) #self.png.fill(pyqtgraph.mkColor(self.params['background'])) w, h = self.params['width'], self.params['height'] if w == 0 or h == 0: raise Exception( "Cannot export image with size=0 (requested export size is %dx%d)" % (w, h)) bg = np.empty((self.params['width'], self.params['height'], 4), dtype=np.ubyte) color = self.params['background'] bg[:, :, 0] = color.blue() bg[:, :, 1] = color.green() bg[:, :, 2] = color.red() bg[:, :, 3] = color.alpha() self.png = fn.makeQImage(bg, alpha=False) ## set resolution of image: origTargetRect = self.getTargetRect() resolutionScale = targetRect.width() / origTargetRect.width() painter = QtGui.QPainter(self.png) #dtr = painter.deviceTransform() try: self.setExportMode( True, { 'antialias': self.params['antialias'], 'background': self.params['background'], 'painter': painter, 'resolutionScale': resolutionScale }) painter.setRenderHint(QtGui.QPainter.Antialiasing, self.params['antialias']) self.getScene().render(painter, QtCore.QRectF(targetRect), QtCore.QRectF(sourceRect)) finally: self.setExportMode(False) painter.end() # Send to png file pngFile = dirName + '/temp_' + '{:03d}'.format(i) + '.png' self.png.save(pngFile) progress.setValue(i) QtGui.QApplication.processEvents() if progress.wasCanceled(): # Clean-up PNGs rmfiles = glob.glob('temp_*.png') for f in rmfiles: os.remove(f) progress.close() return progress.close() # Convert PNGs to movie with FFMPEG if fileName.endswith('mpeg'): codec = 'mpeg2video' else: codec = 'libx264' sp.call([ 'ffmpeg', '-r', str(self.params.param('frame rate').value()), '-i', dirName + '/temp_%03d.png', '-b:v', '1000K', '-c:v', codec, '-vframes', str(self.daxview.data.shape[0]), '-y', fileName ]) # Clean-up PNGs rmfiles = glob.glob(dirName + '/temp_*.png') for f in rmfiles: os.remove(f) return
class ImageExporter(Exporter): Name = "Image File (PNG, TIF, JPG, ...)" def __init__(self, item): Exporter.__init__(self, item) tr = self.getTargetRect() self.params = Parameter(name='params', type='group', children=[ { 'name': 'width', 'type': 'int', 'value': tr.width(), 'limits': (0, None) }, { 'name': 'height', 'type': 'int', 'value': tr.height(), 'limits': (0, None) }, { 'name': 'antialias', 'type': 'bool', 'value': True }, { 'name': 'background', 'type': 'color', 'value': (0, 0, 0, 255) }, ]) self.params.param('width').sigValueChanged.connect(self.widthChanged) self.params.param('height').sigValueChanged.connect(self.heightChanged) def widthChanged(self): sr = self.getSourceRect() ar = sr.height() / sr.width() self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged) def heightChanged(self): sr = self.getSourceRect() ar = sr.width() / sr.height() self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged) def parameters(self): return self.params def export(self, fileName=None): if fileName is None: filter = [ "*." + str(f) for f in QtGui.QImageWriter.supportedImageFormats() ] preferred = ['*.png', '*.tif', '*.jpg'] for p in preferred[::-1]: if p in filter: filter.remove(p) filter.insert(0, p) self.fileSaveDialog(filter=filter) return targetRect = QtCore.QRect(0, 0, self.params['width'], self.params['height']) sourceRect = self.getSourceRect() #self.png = QtGui.QImage(targetRect.size(), QtGui.QImage.Format_ARGB32) #self.png.fill(pyqtgraph.mkColor(self.params['background'])) bg = np.empty((self.params['width'], self.params['height'], 4), dtype=np.ubyte) color = self.params['background'] bg[:, :, 0] = color.blue() bg[:, :, 1] = color.green() bg[:, :, 2] = color.red() bg[:, :, 3] = color.alpha() self.png = pg.makeQImage(bg, alpha=True) painter = QtGui.QPainter(self.png) try: self.setExportMode( True, { 'antialias': self.params['antialias'], 'background': self.params['background'] }) painter.setRenderHint(QtGui.QPainter.Antialiasing, self.params['antialias']) self.getScene().render(painter, QtCore.QRectF(targetRect), sourceRect) finally: self.setExportMode(False) self.png.save(fileName) painter.end()
class SVGExporter(Exporter): Name = "Scalable Vector Graphics (SVG)" allowCopy = True def __init__(self, item): Exporter.__init__(self, item) #tr = self.getTargetRect() self.params = Parameter( name='params', type='group', children=[ #{'name': 'width', 'type': 'float', 'value': tr.width(), 'limits': (0, None)}, #{'name': 'height', 'type': 'float', 'value': tr.height(), 'limits': (0, None)}, #{'name': 'viewbox clipping', 'type': 'bool', 'value': True}, #{'name': 'normalize coordinates', 'type': 'bool', 'value': True}, #{'name': 'normalize line width', 'type': 'bool', 'value': True}, ]) #self.params.param('width').sigValueChanged.connect(self.widthChanged) #self.params.param('height').sigValueChanged.connect(self.heightChanged) def widthChanged(self): sr = self.getSourceRect() ar = sr.height() / sr.width() self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged) def heightChanged(self): sr = self.getSourceRect() ar = sr.width() / sr.height() self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged) def parameters(self): return self.params def export(self, fileName=None, toBytes=False, copy=False): if toBytes is False and copy is False and fileName is None: self.fileSaveDialog(filter="Scalable Vector Graphics (*.svg)") return #self.svg = QtSvg.QSvgGenerator() #self.svg.setFileName(fileName) #dpi = QtGui.QDesktopWidget().physicalDpiX() ### not really sure why this works, but it seems to be important: #self.svg.setSize(QtCore.QSize(self.params['width']*dpi/90., self.params['height']*dpi/90.)) #self.svg.setResolution(dpi) ##self.svg.setViewBox() #targetRect = QtCore.QRect(0, 0, self.params['width'], self.params['height']) #sourceRect = self.getSourceRect() #painter = QtGui.QPainter(self.svg) #try: #self.setExportMode(True) #self.render(painter, QtCore.QRectF(targetRect), sourceRect) #finally: #self.setExportMode(False) #painter.end() ## Workaround to set pen widths correctly #data = open(fileName).readlines() #for i in range(len(data)): #line = data[i] #m = re.match(r'(<g .*)stroke-width="1"(.*transform="matrix\(([^\)]+)\)".*)', line) #if m is not None: ##print "Matched group:", line #g = m.groups() #matrix = list(map(float, g[2].split(','))) ##print "matrix:", matrix #scale = max(abs(matrix[0]), abs(matrix[3])) #if scale == 0 or scale == 1.0: #continue #data[i] = g[0] + ' stroke-width="%0.2g" ' % (1.0/scale) + g[1] + '\n' ##print "old line:", line ##print "new line:", data[i] #open(fileName, 'w').write(''.join(data)) ## Qt's SVG generator is not complete. (notably, it lacks clipping) ## Instead, we will use Qt to generate SVG for each item independently, ## then manually reconstruct the entire document. xml = generateSvg(self.item) if toBytes: return xml.encode('UTF-8') elif copy: md = QtCore.QMimeData() md.setData('image/svg+xml', QtCore.QByteArray(xml.encode('UTF-8'))) QtGui.QApplication.clipboard().setMimeData(md) else: with open(fileName, 'w') as fh: fh.write(xml.encode('UTF-8'))
class SVGExporter(Exporter): Name = "Scalable Vector Graphics (SVG)" def __init__(self, item): Exporter.__init__(self, item) tr = self.getTargetRect() self.params = Parameter(name='params', type='group', children=[ {'name': 'width', 'type': 'float', 'value': tr.width(), 'limits': (0, None)}, {'name': 'height', 'type': 'float', 'value': tr.height(), 'limits': (0, None)}, ]) self.params.param('width').sigValueChanged.connect(self.widthChanged) self.params.param('height').sigValueChanged.connect(self.heightChanged) def widthChanged(self): sr = self.getSourceRect() ar = sr.height() / sr.width() self.params.param('height').setValue(self.params['width'] * ar, blockSignal=self.heightChanged) def heightChanged(self): sr = self.getSourceRect() ar = sr.width() / sr.height() self.params.param('width').setValue(self.params['height'] * ar, blockSignal=self.widthChanged) def parameters(self): return self.params def export(self, fileName=None): if fileName is None: self.fileSaveDialog(filter="Scalable Vector Graphics (*.svg)") return self.svg = QtSvg.QSvgGenerator() self.svg.setFileName(fileName) self.svg.setSize(QtCore.QSize(100,100)) #self.svg.setResolution(600) #self.svg.setViewBox() targetRect = QtCore.QRect(0, 0, self.params['width'], self.params['height']) sourceRect = self.getSourceRect() painter = QtGui.QPainter(self.svg) try: self.setExportMode(True) self.render(painter, QtCore.QRectF(targetRect), sourceRect) finally: self.setExportMode(False) painter.end() ## Workaround to set pen widths correctly data = open(fileName).readlines() for i in range(len(data)): line = data[i] m = re.match(r'(<g .*)stroke-width="1"(.*transform="matrix\(([^\)]+)\)".*)', line) if m is not None: #print "Matched group:", line g = m.groups() matrix = map(float, g[2].split(',')) #print "matrix:", matrix scale = max(abs(matrix[0]), abs(matrix[3])) if scale == 0 or scale == 1.0: continue data[i] = g[0] + ' stroke-width="%0.2g" ' % (1.0/scale) + g[1] + '\n' #print "old line:", line #print "new line:", data[i] open(fileName, 'w').write(''.join(data))
class DeviceProfiles(SettingsPlugin): sigRequestRedraw = Signal() sigRequestReduce = Signal() sigSimulateCalibrant = Signal() name = 'Device Profiles' def __init__(self): self.headermodel = None self.selectionmodel = None self.multiAI = MultiGeometry([]) self.AIs = dict() widget = ParameterTree() energy = SimpleParameter(name='Energy', type='float', value=10000, siPrefix=True, suffix='eV') wavelength = SimpleParameter(name='Wavelength', type='float', value=1.239842e-6 / 10000, siPrefix=True, suffix='m') self.parameter = Parameter(name="Device Profiles", type='group', children=[energy, wavelength]) widget.setParameters(self.parameter, showTop=False) icon = QIcon(str(path('icons/calibrate.png'))) super(DeviceProfiles, self).__init__(icon, "Device Profiles", widget) self.parameter.sigValueChanged.connect(self.sigRequestRedraw) self.parameter.sigValueChanged.connect(self.sigRequestReduce) self.parameter.sigTreeStateChanged.connect(self.simulateCalibrant) self.parameter.sigTreeStateChanged.connect(self.genAIs) self.parameter.sigValueChanged.connect(self.simulateCalibrant) def simulateCalibrant(self, *args): self.sigSimulateCalibrant.emit() def genAIs(self, parent, changes): for parameter, key, value in changes: if parameter.name == 'Wavelength': self.parameter.param('Energy').setValue( 1.239842e-6 / self.param('Wavelength').value(), blockSignal=self.parameter.sigTreeStateChanged) elif parameter.name == 'Energy': self.parameter.param('Wavelength').setValue( 1.239842e-6 / self.param('Energy').value(), blockSignal=self.WavelengthChanged) for parameter in self.parameter.children(): if isinstance(parameter, DeviceParameter): device = parameter.name() ai = self.AI(device) ai.set_wavelength(self.parameter['Wavelength']) ai.detector = parameter['Detector']() ai.detector.set_binning([parameter['Binning']] * 2) ai.detector.set_pixel1(parameter['Pixel Size X']) ai.detector.set_pixel2(parameter['Pixel Size Y']) fit2d = ai.getFit2D() fit2d['centerX'] = parameter['Center X'] fit2d['centerY'] = parameter['Center Y'] fit2d['directDist'] = parameter['Detector Distance'] * 1000 fit2d['tilt'] = parameter['Detector Tilt'] fit2d['tiltPlanRotation'] = parameter['Detector Rotation'] ai.setFit2D(**fit2d) def AI(self, device): if device not in self.AIs: self.addDevice(device) return self.AIs[device] def setAI(self, ai: AzimuthalIntegrator, device: str): self.AIs[device] = ai self.multiAI.ais = self.AIs.values() # propagate new ai to parameter fit2d = ai.getFit2D() try: self.setSilence(True) self.parameter.child(device, 'Detector').setValue(type(ai.detector)) self.parameter.child(device, 'Binning').setValue(ai.detector.binning[0]) self.parameter.child(device, 'Detector Tilt').setValue( fit2d['tiltPlanRotation']) self.parameter.child(device, 'Detector Rotation').setValue(fit2d['tilt']) self.parameter.child(device, 'Pixel Size X').setValue(ai.pixel1) self.parameter.child(device, 'Pixel Size Y').setValue(ai.pixel2) self.parameter.child(device, 'Center X').setValue(fit2d['centerX']) self.parameter.child(device, 'Center Y').setValue(fit2d['centerY']) self.parameter.child(device, 'Detector Distance').setValue( fit2d['directDist'] / 1000) self.parameter.child('Wavelength').setValue(ai.wavelength) finally: self.setSilence(False) self.simulateCalibrant() def setSilence(self, silence): if silence: self.parameter.sigTreeStateChanged.disconnect( self.simulateCalibrant) self.parameter.sigTreeStateChanged.disconnect(self.genAIs) else: self.parameter.sigTreeStateChanged.connect(self.simulateCalibrant) self.parameter.sigTreeStateChanged.connect(self.genAIs) def addDevice(self, device): try: self.setSilence(True) devicechild = DeviceParameter(device) self.parameter.addChild(devicechild) ai = AzimuthalIntegrator(wavelength=self.parameter['Wavelength']) self.AIs[device] = ai self.multiAI.ais = list(self.AIs.values()) finally: self.setSilence(False) def setModels(self, headermodel, selectionmodel): self.headermodel = headermodel self.headermodel.dataChanged.connect(self.dataChanged) self.selectionmodel = selectionmodel def dataChanged(self, start, end): devices = self.headermodel.item( self.selectionmodel.currentIndex()).header.devices() for device in devices: if device not in self.AIs: self.addDevice(device) def apply(self): AI = AzimuthalIntegrator( wavelength=self.parameter.child('Wavelength').value()) # if Calibration.isChecked(): # AI.setFit2D(self.getvalue('Detector Distance') * 1000., # self.getvalue('Center X'), # self.getvalue('Center Y'), # self.getvalue('Detector Tilt'), # 360. - self.getvalue('Detector Rotation'), # self.getvalue('Pixel Size Y') * 1.e6, # self.getvalue('Pixel Size X') * 1.e6) # elif self.wxdiffstyle.isChecked(): # AI.setFit2D(self.getvalue('Detector Distance') * 1000., # self.getvalue('Center X'), # self.getvalue('Center Y'), # self.getvalue('Detector Tilt') / 2. / np.pi * 360., # 360. - (2 * np.pi - self.getvalue('Detector Rotation')) / 2. / np.pi * 360., # self.getvalue('Pixel Size Y') * 1.e6, # self.getvalue('Pixel Size X') * 1.e6) # AI.set_wavelength(self.getvalue('Wavelength')) # # print AI activeCalibration = AI def save(self): self.apply() return self.parameter.saveState(filter='user') def restore(self, state): pass # self.parameter.restoreState(state, addChildren=False, removeChildren=False) def wavelengthChanged(self): self.param('Energy').setValue(1.239842e-6 / self.param('Wavelength').value(), blockSignal=self.EnergyChanged) def energyChanged(self): self.param('Wavelength').setValue(1.239842e-6 / self.param('Energy').value(), blockSignal=self.WavelengthChanged)