def integrate_flux(ifu, fibersize, image, platescale): """ iterate over pixels in the 2d numpy array image and identify the hexagon the pixel is in in the list of Hex structures ifu. Return a list of floats with the summed fluxes in each hexagon. """ pointy = hexlib.Layout(hexlib.layout_pointy, fibersize, hexlib.Point(0,0)) fluxes = np.zeros(len(ifu), dtype=np.float) for (x,y), flux in np.ndenumerate(image): p = Point(x*platescale,y*platescale) hex = pixel_to_hex(pointy, p) i = find_hex(ifu, hex) if i>=0: flux[i] += image(x,y)
def __init__(self, ifuModel): """ Initialize the IFU class """ self.ifuModel = ifuModel self.lensKernel = None self.lensID = None self.blockID = None self.blockN = None self.CurrentID = 0 if isinstance(self.ifuModel, (float, int)): if int(self.ifuModel) == self.ifuModel: self.ifuModel = int(self.ifuModel) else: sys.exit( "Number of elements requested is not a integer number") self.lenspitch = 0.174 # in mm self.lensx = None self.lensy = None self.lensr = 0.160 * 0.5 # in mm self.cubex = None # this will be blank if the ifu model is read from a table self.cubey = None # this will be blank if the ifu model is read from a table self.ring = None # this MAY be blank if the ifu model is read from a table self.lensT = 1.0 self.hexLayout = hexlib.Layout(hexlib.layout_flat, self.lenspitch, hexlib.Point(0, 0)) self.mkIfu(N=self.ifuModel) elif isinstance(self.ifuModel, str): try: asciiIfu = ascii.read(self.ifuModel, format="commented_header", delimiter="\t") except: sys.exit("Reading an ifuModel from a file is not yet defined.") try: self.lensx = asciiIfu['lensx'] self.lensy = asciiIfu['lensy'] self.lensr = asciiIfu['lensr'] self.lensT = asciiIfu['lensT'] except: sys.exit( "IFU model read from %s does not contain a valid definition of lens positions" )
def make_hex_kernel(radius,imgsize,antialias=5,debug=False): """ Generate a 2D numpy array with the characteristic function of a hexagon of size 'radius' (center to corner) in units of pixels of the array. The image will have dimensions of imgsize x imgsize and the hexagon will be at the integer center. """ antialias=5 imgsize*=antialias center = imgsize//2+1 pointy = hexlib.Layout(hexlib.layout_pointy, radius*antialias, hexlib.Point(center,center)) polygon = hexlib.polygon_corners(pointy,hexlib.Hex(0,0,0)) img = Image.new('L', (imgsize, imgsize), 0) ImageDraw.Draw(img).polygon(polygon, outline=1, fill=1) mask = np.array(img,dtype=float) mask /= np.sum(mask) mask = int_rebin(mask, (imgsize//antialias,imgsize//antialias)) if debug==True: plt.imshow(mask) plt.show() return mask
def makeHexLensKernel(self): """ Generate a 2D numpy array with the characteristic function of a hexagon of size 'radius' (center to corner) in units of pixels of the array. The image will have dimensions of imgsize x imgsize and the hexagon will be at the integer center. """ rlensmm = np.mean(self.telescope.ifu.lensr) rlensarcsec = rlensmm * self.telescope.platescale() rlenspix = rlensarcsec / self.hdr['PIXSCALE'] imgsize = 2 * rlenspix antialias = 5 imgsize = int(imgsize * antialias) center = imgsize // 2 + 1 hexLayout = hexlib.Layout(hexlib.layout_pointy, rlenspix * antialias, hexlib.Point(center, center)) polygon = hexlib.polygon_corners(hexLayout, hexlib.Hex(0, 0, 0)) img = Image.new('L', (imgsize, imgsize), 0) ImageDraw.Draw(img).polygon(polygon, outline=1, fill=1) kernel = np.array(img, dtype=float) kernel /= np.sum(kernel) kernel = int_rebin(kernel, (imgsize // antialias, imgsize // antialias)) return kernel
def lvm_sample_image (fimg, platescale, lenslet_size=36.2, reconstruct=False, debug=False): """ Sample an image to simulating observing with LVM. Inputs: fimg fits image to observe with LVM platescale fits image plate scale in arcsec/pix lenslet_size size of the LVM lenslet elements. 36.2 by default (LVM160). Use 6.8 for LVM1000. note that to properly simulate the 1m observations you will have to make sure the input images are properly sampled. 1" or better is required. The LVM160 simulations can use a coarser input image scale. reconstruct return list of samples (false) or reconstructed image (true) debug show intermediate plots for illustration (false by default) Return: x,y,f x and y positions and values f of the image sampled at the dither locations OR img reconstructed image from the samples if reconstruct==True (simple interpolation) """ img, hdr = fits.getdata(fimg, 0, header=True) hex_diameter=lenslet_size # convolve image with lenslet/fiber footprint fiber = make_hex_kernel(hex_diameter/2.0/platescale, 21, debug=False) imgf = convolve_with_kernel(img, fiber) if debug==True: plt.imshow(fiber) plt.show() # generate the IFU and the locations of the dithers ifu = mkifu(30) # make one large IFU for now. 30 Rings. Later simulate proper tiling layout = hexlib.Layout(hexlib.layout_flat, hex_diameter/2.0, hexlib.Point(img.shape[0]/2*platescale,img.shape[1]/2*platescale)) dither = mkdither(layout,ifu,debug=False) # transform all the fiber centers to X,Y from hex coordinates ifuc = cubetoxy(ifu,layout) ifux = np.array([i.x for i in ifuc]) ifuy = np.array([i.y for i in ifuc]) if debug==True: plt.imshow(imgf,clim=(0.4, 7.0)) for i in dither: plt.scatter((ifux+i[0])/platescale, (ifuy+i[1])/platescale, s=1) plt.show() # sample the convolved image in the IFU+dithers x=[] y=[] q = scipy.interpolate.interp2d( range(imgf.shape[1]), range(imgf.shape[0]), imgf, kind='cubic' ) for i in dither: x = np.append(x, (ifux+i[0])/platescale) y = np.append(y, (ifuy+i[1])/platescale) f = [] for i in range(len(x)): f = np.append(f, q(x[i], y[i])) if reconstruct==True: # attempt at reconstruction using the samples X, Y = np.meshgrid(range(imgf.shape[1]), range(imgf.shape[0])) imgr = scipy.interpolate.griddata( (x,y), f, (X,Y), method='cubic') inf = np.invert(np.isfinite(imgr)) imgr[inf] = 0. return imgr else: return x,y,f