Reputation: 95
I would like to plot a 2D spectrum where the x coordinate is the spectral dimension (wavelength) and the y coordinate is the spatial dimension (in arcseconds of the sky) using pyqtgraph.
I've been able to do this using an ImageItem() but I cannot seem to figure out how to display the x and y axes in the right coordinates. I don't want to just change the labels or the ticks but indeed the coordinates of the plot because I later need to perform operations using these values (wavelength and arcsecs).
Here is a minimal working example:
import pyqtgraph as pg
import numpy as np
# The fake data
wvlg = np.linspace(300, 600, 5000)
arcsec = np.linspace(-5, 5, 100)
flux = np.ones((wvlg.shape[0], arcsec.shape[0])) * np.exp(-(arcsec)**2/0.1)
flux += np.random.normal(0, 0.1, size=(wvlg.shape[0], arcsec.shape[0]))
# The plotting
win = pg.GraphicsLayoutWidget(show=True)
ax2D = win.addPlot(title='2D spectrum', row=0, col=0)
img = pg.ImageItem()
img.setImage(flux)
ax2D.addItem(img)
# Some line converting the x and y values to wvlg and arcsec
This gives an image where the x and y axis show the index value, whereas I would like to show the corresponding wavelength and arcsec values.
Is there an easy way to do this that I just grossly overlooked in the documentation?
Upvotes: 1
Views: 1898
Reputation: 5546
You can use the setRect
method of the ImageItem
class to set the extent of the data. See my example below.
Note that I moved the image by half a pixel so that the pixel centers match the exact coordinates. Otherwise the coordinates would align with one of the pixel's corner points.
import pyqtgraph as pg
import numpy as np
from PyQt5 import QtCore, QtWidgets
def main():
app = QtWidgets.QApplication([])
# The fake data
wvlg = np.linspace(300, 600, 5000)
arcsec = np.linspace(-5, 5, 100)
flux = np.ones((wvlg.shape[0], arcsec.shape[0])) * np.exp(-(arcsec)**2/0.1)
flux += np.random.normal(0, 0.1, size=(wvlg.shape[0], arcsec.shape[0]))
# The plotting
win = pg.GraphicsLayoutWidget()
ax2D = win.addPlot(title='2D spectrum', row=0, col=0)
img = pg.ImageItem()
img.setImage(flux)
ax2D.addItem(img)
print(flux.shape)
# Move the image by half a pixel so that the center of the pixels are
# located at the coordinate values
dx = wvlg[1]-wvlg[0]
dy = arcsec[1]-arcsec[0]
print("pixel size x: {}, pixel size y: {}".format(dx, dy))
rect = QtCore.QRectF(wvlg[0] - dx/2, arcsec[0] - dy/2,
wvlg[-1] - wvlg[0], arcsec[-1] - arcsec[0])
print(rect)
img.setRect(rect)
ax2D.setLabels(left='arcsec', bottom='wvlg')
win.show()
win.raise_()
app.exec_()
if __name__ == "__main__":
main()
Upvotes: 2