class ImageSession: def __init__(self, master, filename, hdu=0): # filename should be a string! self.filename = filename self.hdu = hdu # The master window? self.master = master if not os.path.exists(self.filename): tkMessageBox.showerror("File not found", "File {0} doesn't exist!".format(file)) return self.openFile() self.createWindow() def openFile(self): # Try to open the file and read in the data from HDU try: hdulist = pf.open(self.filename) try: if hdulist[self.hdu].header['XTENSION'] == 'BINTABLE': tkMessageBox.showerror("HDU Error", "The HDU {0} is not an ImageHDU!".format(self.hdu)) raise util.NotAnImageHDUError("The HDU {0} is not an ImageHDU!".format(self.hdu)) # HDU is a table -- throw an error! except KeyError: # HDU is an image, carry on! pass self.rawData = hdulist[self.hdu].data self.rawData.shape except IOError: tkMessageBox.showerror("FITS file error ", "File {0} does not appear to be a valid FITS file!".format(self.filename)) raise util.ImageSessionError("File {0} does not appear to be a valid FITS file!".format(self.filename)) except AttributeError: tkMessageBox.showerror("FITS file error ", "File {0} does not appear to have data in HDU 0.".format(self.filename)) raise util.ImageSessionError("File {0} does not appear to have data in HDU 0.".format(self.filename)) def createWindow(self): # Create the actual window to draw the image and scale controls self.ImageWindow = Tk.Toplevel(self.master) self.ImageWindow.title(self.filename) #self.ImageWindow.protocol("WM_DELETE_WINDOW", self.closeImage) # TODO: THIS SHOULD DETECT SCREEN RESOLUTION screenSize = (1050/1.5, 1680/1.5) if self.rawData.shape[0] > screenSize[0] and self.rawData.shape[1] > screenSize[1]: factor1 = screenSize[0] / self.rawData.shape[0] factor2 = screenSize[1] / self.rawData.shape[1] self.zoomFactor = min([factor1, factor2]) elif self.rawData.shape[1] > screenSize[0]: self.zoomFactor = screenSize[0]/ self.rawData.shape[1] elif self.rawData.shape[0] > screenSize[1]: self.zoomFactor = screenSize[1] / self.rawData.shape[0] else: self.zoomFactor = 1. # Create the image tools scaleTypeLabel = Tk.Label(self.ImageWindow, text="Scaling: ") scaleTypeLabel.grid(row=0, column=0) self.scalingName = Tk.StringVar() self.scalingName.set("arcsinh") self.scalingOption = Tk.OptionMenu(self.ImageWindow, self.scalingName, "arcsinh","linear","sqrt", command=self.setRescaler) self.scalingOption.grid(row=0, column=1) rescaleLabel = Tk.Label(self.ImageWindow, text="Rescale: ") rescaleLabel.grid(row=1, column=0) self.scaleValue = Tk.Scale(self.ImageWindow, from_=-4, to=6, resolution=0.05, orient=Tk.HORIZONTAL, showvalue=1, length=300) self.scaleValue.set(1.0) self.scaleValue.grid(row=1, column=1) minLabel = Tk.Label(self.ImageWindow, text="Min Pixel Value: ") minLabel.grid(row=2, column=0) self.minValue = Tk.Scale(self.ImageWindow, resolution=0.05, orient=Tk.HORIZONTAL, showvalue=1, length=300) self.minValue.set(1.0) self.minValue.grid(row=2, column=1) maxLabel = Tk.Label(self.ImageWindow, text="Max Pixel Value: ") maxLabel.grid(row=3, column=0) self.maxValue = Tk.Scale(self.ImageWindow, resolution=0.05, orient=Tk.HORIZONTAL, showvalue=1, length=300) self.maxValue.set(1.0) self.maxValue.grid(row=3, column=1) # Set the min/max slider boundaries self.minValue.config(from_=self.rawData.min(), to=self.rawData.max()) self.minValue.set(self.rawData.min()) self.maxValue.config(from_=self.rawData.min(), to=self.rawData.max()) self.maxValue.set(self.rawData.max()) # Set the default rescaler self.rescaler = util.arcsinhStretch self.scaleImage() self.drawImage() # Bind the sliders to the scaleImage() method self.scaleValue.bind("<ButtonRelease-1>", self.redraw) self.minValue.bind("<ButtonRelease-1>", self.redraw) self.maxValue.bind("<ButtonRelease-1>", self.redraw) self.scalingOption.bind("<ButtonRelease-1>", self.redraw) def setRescaler(self, event): self.rescaler = scalingTypes[self.scalingName.get()] def redraw(self, event=None): """ This rescales and redraws the image using the current values for scaling """ self.scaleImage() self.drawImage() def updateThumbnail(self, event): """ """ self.lastMousePosition = (event.x, event.y) self.pilThumbnail = self.pilImage.transform(self.pilImage.size, Image.EXTENT, (event.x-25,event.y-25,event.x+25,event.y+25)) self.thumbnailImage = ImageTk.PhotoImage(self.pilThumbnail.resize((200,200))) self.thumbnailImageLabel.configure(image=self.thumbnailImage) def scaleImage(self): """ This method re-scales the image data """ self.scaledData = 255.0*self.rescaler(self.rawData, beta=10.**self.scaleValue.get(), min=self.minValue.get(), max=self.maxValue.get(), clip=True) def plotContour(self, event): """ If the 'c' key is pressed, generate a contour plot of whatever is in the thumbnail zoom box """ self.contourPlot = Tk.Toplevel(self.master) self.contourPlot.title("Contour plot for: {0}".format(self.filename)) rawShape = self.rawData.shape lastx, lasty = self.lastMousePosition lastx = round(lastx/self.zoomFactor) lasty = round(lasty/self.zoomFactor) boxHalfSize = 25/self.zoomFactor x1,y1,x2,y2 = [x for x in map(round, (lastx-boxHalfSize,lasty-boxHalfSize,lastx+boxHalfSize,lasty+boxHalfSize))] if x1 < 0: x1 = 0 x2 = boxHalfSize*2 if x2 > rawShape[1]: x2 = rawShape[1] x1 = x2 - boxHalfSize*2 if y1 < 0: y1 = 0 y2 = boxHalfSize*2 if y2 > rawShape[0]: y2 = rawShape[0] y1 = y2 - boxHalfSize*2 thumbData = self.rawData[y1:y2, x1:x2] shp = thumbData.shape x,y = np.meshgrid(range(shp[0]), range(shp[1])) self.fig = Figure(figsize=(5,5)) ax = self.fig.add_subplot(111) ax.contour(x, y, thumbData) ax.set_ylim(ax.get_ylim()[::-1]) ax.get_xaxis().set_ticks([]) ax.get_yaxis().set_ticks([]) self.canvas = FigureCanvasTkAgg(self.fig, master=self.contourPlot) self.canvas.get_tk_widget().pack(side='top', fill='both', expand=1) def drawImage(self): """ This method will draw the image into a PhotoImage object in the new image window """ self.pilImage = Image.fromarray(self.scaledData.astype(np.uint8)) newSize = (int(self.pilImage.size[0]*self.zoomFactor), int(self.pilImage.size[1]*self.zoomFactor)) self.pilImage = self.pilImage.resize(newSize) self.tkImage = ImageTk.PhotoImage(self.pilImage) self.canvas = Tk.Canvas(self.ImageWindow, width=newSize[0], height=newSize[1], bd=0) self.canvas.create_image(0, 0, image=self.tkImage, anchor="nw") self.canvas.grid(row=0, column=2, rowspan=5, sticky="nswe") self.canvas.bind("<Motion>", self.updateThumbnail) self.canvas.bind("c", self.plotContour) self.canvas.focus_set() """ # Code for source detection: numSigma = 2. labels, num = snd.label(self.rawData > (numSigma*np.std(self.rawData)), np.ones((3,3))) coords = snd.center_of_mass(self.rawData, labels, range(1,num+1)) rad = 5. for coord in coords: y,x = coord x = x*self.zoomFactor y = y*self.zoomFactor circ1 = self.canvas.create_oval(x-rad,y-rad,x+rad,y+rad, outline='red') """ self.pilThumbnail = self.pilImage.transform(self.pilImage.size, Image.EXTENT, (0,0,50,50)) self.pilThumbnail = self.pilThumbnail.resize((200,200)) self.thumbnailImage = ImageTk.PhotoImage(self.pilThumbnail) self.thumbnailImageLabel = Tk.Label(self.ImageWindow, image=self.thumbnailImage, command=None) self.thumbnailImageLabel.grid(row=4, column=0, columnspan=2, rowspan=5)