import numpy as np from scipy.interpolate import interp1d from matplotlib import pylab as plt from astropy.io import fits from PIL import Image def remove_nans(im: np.ndarray) -> np.ndarray: nans = np.isnan(im) out = np.copy(im) out[nans] = 0 return out def scale(im: np.ndarray, gamma: float=3, hist_peak: float=40, aux_im=None): """ Scales the im array pixel values such that details in faint regions and bright regions are both clearly visible. Outputs an image with values from 0 and 255, inclusive. Optionally, an auxiliary image can be provided, in which case this image will be scaled using the same parameters as the primary image, im. """ sigmoid = np.arctan im = remove_nans(im) minval = np.percentile(im, 0.05) maxval = np.percentile(im, 99.85) data = (im - minval) / (maxval - minval) data = 255 * sigmoid(gamma * data) / 1.57079 left = np.percentile(data, 2) vals, bins = np.histogram(data.flat, bins=512, range=(0, 255)) peak = bins[np.argmax(vals)] - left peak = 0.3 if peak <= 0.15 else peak correction = interp1d([0, peak, 255], [0.08 * hist_peak / peak, hist_peak / peak, 1.0 ], kind='slinear', fill_value=(0,1), bounds_error=False) data -= left data *= correction(data) data = np.clip(data, 0, 255) if aux_im is not None: aux_data = (aux_im - minval) / (maxval - minval) aux_data = 255 * sigmoid(gamma * aux_data) / 1.57079 aux_data -= left aux_data *= correction(aux_data) data = np.clip(aux_data, 0, 255) else: aux_data = None return data, aux_data def display(image: np.ndarray, cmap='gray'): """Scales and displays an image.""" scaled, _ = scale(image) plt.ion() plt.imshow(scaled, origin='lower', cmap=cmap) plt.ioff() def save_as_image(image_data: np.ndarray, filename: str): image = Image.fromarray(image_data).transpose(Image.FLIP_TOP_BOTTOM).convert('RGB') print(f"Saving {filename}.") image.save(filename) def make_jpegs(filename: str): """ Reads all of the science layers of a NISP Spectroscopic exposure and saves each as a separate JPEG image. """ fits_file = fits.open(filename) obs_id = fits_file[0].header['OBS_ID'] dither = fits_file[0].header['DITHOBS'] for ext in fits_file: if '.SCI' in ext.name: img_data, _ = scale(ext.data) jpeg_name = f"{obs_id}-dither-{dither}-{ext.name}.jpg" save_as_image(img_data, jpeg_name) fits_file.close()