def make_normalized_image(self, newname, image): header = image.get_header() # normalize the data coadds = header.get('COADDS', 1) ndr = header.get('NDR', 1) divisor = coadds * ndr data_np = image.get_data() data_np = data_np / divisor # create a new image new_image = AstroImage.AstroImage(data_np=data_np, logger=self.logger) new_image.set(name=newname) new_image.update_keywords(header) new_image.update_keywords( dict(COADD=1, COADDS=1, NDR=1, FRAMEID=newname)) if self.settings.get('cache_normalized_images', True): # write out a cached copy so we can reload as necessary try: prefix = os.path.join(os.environ['GEN2COMMON'], 'data_cache') except KeyError: prefix = '/tmp' cached_path = os.path.join(prefix, newname + '.fits') new_image.set(path=cached_path) if not os.path.exists(cached_path): new_image.save_as_file(cached_path) return new_image
def load_file(self, filepath): image = AstroImage.AstroImage(logger=self.logger) image.load_file(filepath) self.fitsimage.set_image(image) self.setWindowTitle(filepath) # create compass try: try: self.fitsimage.deleteObjectByTag(self.cp_tag) except KeyError: pass (x, y, xn, yn, xe, ye) = image.calc_compass_center() self.logger.debug("x=%d y=%d xn=%d yn=%d xe=%d ye=%d" % (x, y, xn, yn, xe, ye)) Compass = self.fitsimage.getDrawClass('compass') self.fitsimage.add(Compass(x, y, xn, yn, xe, ye, color='skyblue', fontsize=14), tag=self.cp_tag) except Exception as e: self.logger.warn("Can't calculate compass: %s" % (str(e)))
def load_image(self, filepath): # Create an image. Assume type to be an AstroImage unless # the MIME association says it is something different. try: typ, subtyp = self.guess_filetype(filepath) except Exception: # Can't determine file type: assume and attempt FITS typ, subtyp = 'image', 'fits' if (typ == 'image') and (subtyp != 'fits'): image = RGBImage.RGBImage(logger=self.logger) else: image = AstroImage.AstroImage(logger=self.logger) try: self.logger.info("Loading image from %s" % (filepath)) image.load_file(filepath) #self.gui_do(chinfo.fitsimage.onscreen_message, "") except Exception as e: errmsg = "Failed to load file '%s': %s" % (filepath, str(e)) self.logger.error(errmsg) try: (type, value, tb) = sys.exc_info() tb_str = "\n".join(traceback.format_tb(tb)) except Exception as e: tb_str = "Traceback information unavailable." self.gui_do(self.show_error, errmsg + '\n' + tb_str) #chinfo.fitsimage.onscreen_message("Failed to load file", delay=1.0) raise ControlError(errmsg) self.logger.debug("Successfully loaded file into image object.") return image
def create_blank_image(ra_deg, dec_deg, fov_deg, px_scale, rot_deg, cdbase=[1, 1], dtype=None, logger=None, pfx='dp'): # ra and dec in traditional format ra_txt = wcs.raDegToString(ra_deg, format='%02d:%02d:%06.3f') dec_txt = wcs.decDegToString(dec_deg, format='%s%02d:%02d:%05.2f') # Create an empty image imagesize = int(round(fov_deg / px_scale)) # round to an even size if imagesize % 2 != 0: imagesize += 1 ## # round to an odd size ## if imagesize % 2 == 0: ## imagesize += 1 width = height = imagesize if dtype is None: dtype = numpy.float32 data = numpy.zeros((height, width), dtype=dtype) crpix = float(imagesize // 2) header = OrderedDict(( ('SIMPLE', True), ('BITPIX', -32), ('EXTEND', True), ('NAXIS', 2), ('NAXIS1', imagesize), ('NAXIS2', imagesize), ('RA', ra_txt), ('DEC', dec_txt), ('EQUINOX', 2000.0), ('OBJECT', 'MOSAIC'), ('LONPOLE', 180.0), )) # Add basic WCS keywords wcshdr = wcs.simple_wcs(crpix, crpix, ra_deg, dec_deg, px_scale, rot_deg, cdbase=cdbase) header.update(wcshdr) # Create image container image = AstroImage.AstroImage(data, logger=logger) image.update_keywords(header) # give the image a name get_image_name(image, pfx=pfx) return image
def _data_to_image(data): ids = data.component_ids() data_np = data[ids[0]] data_meta = {} if hasattr(data.coords, 'header'): h = AstroImage.AstroHeader() h.update(data.coords.header) data_meta['header'] = h image = AstroImage.AstroImage(data_np=data_np, metadata=data_meta) if hasattr(data.coords, 'wcs'): image.wcs.load_header(data.coords.wcs.to_header()) return image
def load_file(self, filepath): image = AstroImage.AstroImage(logger=self.logger) image.load_file(filepath) self.fitsimage.set_image(image) self.setWindowTitle(filepath) # create compass try: try: self.fitsimage.delete_object_by_tag(self.cp_tag) except KeyError: pass width, height = image.get_size() x, y = width / 2.0, height / 2.0 # radius we want the arms to be (approx 1/4 the largest dimension) radius = float(max(width, height)) / 4.0 Compass = self.fitsimage.get_draw_class('compass') self.fitsimage.add(Compass(x, y, radius, color='skyblue', fontsize=14), tag=self.cp_tag) except Exception as e: self.logger.warning("Can't calculate compass: %s" % (str(e)))
def mosaic_some(self, paths, image_loader=None): if image_loader is None: image_loader = self.fv.load_image for url in paths: if self.ev_intr.isSet(): break mosaic_hdus = self.settings.get('mosaic_hdus', False) if mosaic_hdus: self.logger.debug("mosaicing hdus") # User wants us to mosaic HDUs # TODO: do this in a different thread? with pyfits.open(url, 'readonly') as in_f: i = 0 for hdu in in_f: i += 1 # TODO: I think we need a little more rigorous test # than just whether the data section is empty if hdu.data is None: continue self.logger.debug("ingesting hdu #%d" % (i)) image = AstroImage.AstroImage(logger=self.logger) image.load_hdu(hdu) image.set(name='hdu%d' % (i)) image = self.preprocess(image) self.ingest_one(image) else: image = image_loader(url) image = self.preprocess(image) self.ingest_one(image)
def load_hdu(self, hdu, dstobj=None, **kwargs): from ginga import AstroImage # Put here to avoid circular import typ = self.get_hdu_type(hdu) if typ == 'image': # <-- data is an image ahdr = AstroImage.AstroHeader() self.fromHDU(hdu, ahdr) metadata = dict(header=ahdr) data = hdu.read() if dstobj is None: # get model class for this type of object obj_class = self.factory_dict.get('image', None) if obj_class is None: raise FITSError( "I don't know how to load objects of kind 'image'") dstobj = obj_class(logger=self.logger) dstobj.load_data(data, metadata=metadata) elif typ == 'table': # <-- data is a table raise FITSError( "FITS tables are not yet readable using ginga/fitsio") return dstobj
def setup_module(): """Create objects once and re-use throughout this module.""" global img_dict if minversion(astropy, '3.1'): USE_APE14 = True else: USE_APE14 = False img_dict = {} for modname in _wcsmods: if modname == 'astropy_ape14' and not USE_APE14: continue if not wcsmod.use(modname, raise_err=False): continue img_dict[modname] = {} for dim in _hdr.keys(): w = wcsmod.WCS(_logger) with warnings.catch_warnings(): warnings.simplefilter("ignore") w.load_header(_hdr[dim]) img = AstroImage.AstroImage(logger=_logger) img.wcs = w if dim == '2d': img.revnaxis = [] img.naxispath = [] else: # 3d img.revnaxis = [0] img.naxispath = [0] img_dict[modname][dim] = img
def load_hdu(self, hdu, dstobj=None, **kwargs): from ginga import AstroImage # Put here to avoid circular import hduinfo = hdu.get_info() hdutype = hduinfo.get('hdutype', None) ahdr = AstroImage.AstroHeader() self.fromHDU(hdu, ahdr) metadata = dict(header=ahdr) data = hdu.read() if hdutype == fitsio.IMAGE_HDU: # <-- data is an image if dstobj is None: # get model class for this type of object obj_class = self.factory_dict.get('image', None) if obj_class is None: raise FITSError( "I don't know how to load objects of kind 'image'") dstobj = obj_class(logger=self.logger) dstobj.load_data(data, metadata=metadata) elif hdutype in (fitsio.ASCII_TBL, fitsio.BINARY_TBL): # <-- data is a table raise FITSError( "FITS tables are not yet readable using ginga/fitsio") return dstobj
def load_idx(self, idx, **kwargs): if idx is None: idx = self.find_first_good_idx() typ = self.get_idx_type(idx) if typ == 'image': from ginga import AstroImage, RGBImage header = self.get_header(idx) data_np = np.copy(self._f[idx].value) if 'PALETTE' in header: p_idx = header['PALETTE'] p_data = self._f[p_idx].value data_np = p_data[data_np] image = RGBImage.RGBImage(logger=self.logger) else: image = AstroImage.AstroImage(logger=self.logger) image.update_keywords(header) image.set_data(data_np) name = iohelper.name_image_from_path(self._path, idx=idx) image.set(path=self._path, name=name, idx=idx, image_loader=load_file) return image raise ValueError("I don't know how to read dataset '{}'".format(idx))
def load_file(self, filepath): image = AstroImage.AstroImage(logger=self.logger) with asdf.open(filepath) as asdf_f: image.load_asdf(asdf_f) self.fitsimage.set_image(image) self.setWindowTitle(filepath)
def set_data(self, data, metadata=None, redraw=True): dims = data.shape ## assert (len(dims) == 2), \ ## FitsImageError("Only 2D images are supported!") image = AstroImage.AstroImage(data, metadata=metadata, logger=self.logger) self.set_image(image, redraw=redraw)
def load_hdu(self, hdu): """ Load an HDU into the viewer. """ image = AstroImage.AstroImage(logger=self.logger) image.load_hdu(hdu) self.set_image(image)
def load_data(self, data_np): """ Load raw numpy data into the viewer. """ image = AstroImage.AstroImage(logger=self.logger) image.set_data(data_np) self.set_image(image)
def load_fits(self, filepath): """ Load a FITS file into the viewer. """ image = AstroImage.AstroImage(logger=self.logger) image.load_file(filepath) self.set_image(image)
def load_hdu(self, hdu, dstobj=None, **kwargs): if isinstance(hdu, ( pyfits.ImageHDU, pyfits.CompImageHDU, pyfits.PrimaryHDU, )): # <-- data is an image if dstobj is None: # get model class for this type of object obj_class = self.factory_dict.get('image', None) if obj_class is None: raise FITSError( "I don't know how to load objects of kind 'image'") dstobj = obj_class(logger=self.logger) # For now, call back into the object to load it from pyfits-style # HDU in future migrate to storage-neutral format dstobj.load_hdu(hdu, **kwargs) elif isinstance(hdu, (pyfits.TableHDU, pyfits.BinTableHDU)): # <-- data is a table # Handle ASDF embedded in FITS. # TODO: Populate EXTNAME, EXTVER, NAXISn in ASDF meta from HDU? # TODO: How to read from all the different ASDF layouts? # TODO: Cache the ASDF object? from ginga.util import io_asdf if io_asdf.have_asdf and hdu.name == 'ASDF': from asdf.fits_embed import AsdfInFits from ginga import AstroImage self.logger.debug('Attempting to load {} extension from ' 'FITS'.format(hdu.name)) dstobj = AstroImage.AstroImage() with AsdfInFits.open(self.fits_f) as asdf_f: dstobj.load_asdf(asdf_f) return dstobj if dstobj is None: self.logger.debug('Attempting to load table from FITS') # get model class for this type of object obj_class = self.factory_dict.get('table', None) if obj_class is None: raise FITSError( "I don't know how to load objects of kind 'table'") dstobj = obj_class(logger=self.logger) # For now, call back into the object to load it from pyfits-style # HDU in future migrate to storage-neutral format dstobj.load_hdu(hdu, **kwargs) else: raise FITSError("I don't know how to read this HDU") return dstobj
def loadImage(self, data_np): """Load image array.""" # Set image self.image = data_np aimg = AstroImage.AstroImage(self.logger) aimg.set_data(self.image) self.set_image(aimg)
def _load(self): """ Loads an image into the viewer, applying appropriate transformations for proper display. Checks if an HDU has been loaded already and retrieves if needed and then displays that HDU. Uses multiprocessing techniques for simultaneous downloads and dictionaries to keep track of which images have been already loaded for faster image switching. """ # load the image if not already available, for now we'll put this in here. if self.candidates is None: self.logger.info("No candidates loaded.") return # loads first candidate if self.candidate is None: self.next() return key = self.key while True: # noinspection PyBroadException try: if key not in self.astro_images: # TODO: MEF image = AstroImage.AstroImage(logger=self.logger) image.load_hdu(self.loaded_hdu) self.astro_images[key] = image self.set_image(self.astro_images[key]) if self.zoom is not None: self.zoom_to(self.zoom) self._rotate() if self.center is not None: self._align() # the image cutout is considered the first object on the canvas, this deletes everything over top of it self.canvas.delete_objects(self.canvas.get_objects()[1:]) if key not in self.null_observation: self.mark_aperture() self.header_box.set_text("Header:" + self.info) self.logger.info("Loaded: {}".format( self.candidate[self.obs_number].comment.frame)) break except Exception as ex: self.logger.info(str(ex)) self.logger.info( "Skipping candidate {} due to load failure.".format( self.candidate[0].provisional_name)) self.next() break self._center = WCS(self.header).all_pix2world( self.get_data_size()[0] / 2, self.get_data_size()[1] / 2, 0)
def make_image(data_np, oldimage, header, pfx='dp'): # Prepare a new image with the numpy array as data image = AstroImage.AstroImage() image.set_data(data_np) # Set the header to be the old image header updated # with items from the new header oldhdr = oldimage.get_header() oldhdr.update(header) image.update_keywords(oldhdr) # give the image a name get_image_name(image, pfx=pfx) return image
def mosaic(paths, logger, outfile=None): logger.info("Mosaicing images...") image = AstroImage.AstroImage(logger=logger) mosaic = image.mosaic(paths) if outfile: try: os.remove(outfile) except: pass logger.info("Writing mosaic file to %s ..." % (outfile)) mosaic.write_fits(outfile)
def load_file(self, filepath): log.info(f'Loading image: {filepath}') self.clear_overlays() image = AstroImage.AstroImage(logger=self.logger) image.load_file(filepath) if self.medfilt is True: log.info('Median filtering image for display') data = image.get_data() filtered_image = medfilt(data, (3, 3)) image.set_data(filtered_image) self.image = image self.fitsimage.set_image(image) self.setWindowTitle(f'{filepath} {self.medfilt_str}') self.overlay_catalog()
def test_pixtoradec_scalar(self, modname): if not wcsmod.use(modname, raise_err=False): pytest.skip("WCS '{}' not available".format(modname)) wcs = wcsmod.WCS(self.logger) #if wcs.wcs is None: # pytest.skip("WCS '{}' not available".format(modname)) wcs.load_header(self.header) img = AstroImage.AstroImage(logger=self.logger) img.wcs = wcs img.revnaxis = [] ra_deg_v1 = 300.2308791294835 dec_deg_v1 = 22.691653517073615 ra_deg, dec_deg = img.pixtoradec(120, 100) np.testing.assert_allclose(ra_deg, ra_deg_v1), np.testing.assert_allclose(dec_deg, dec_deg_v1)
def test_radectopix_scalar(self, modname): if not wcsmod.use(modname, raise_err=False): pytest.skip("WCS '{}' not available".format(modname)) wcs = wcsmod.WCS(self.logger) #if wcs.wcs is None: # pytest.skip("WCS '{}' not available".format(modname)) wcs.load_header(self.header) img = AstroImage.AstroImage(logger=self.logger) img.wcs = wcs img.naxispath = [] x_v1 = 120 y_v1 = 100 x, y = img.radectopix(300.2308791294835, 22.691653517073615) np.testing.assert_allclose(x, x_v1) np.testing.assert_allclose(y, y_v1)
def load_asdf(asdf_obj, idx=None, logger=None): """ Load data from an open ASDF object. Parameters ---------- asdf_obj : obj ASDF or ASDF-in-FITS object. idx : None Currently unused. Reserved for future use to identify specific data set of an ASDF object containing the data of interest. logger : python logging object Currently unused. Reserved for future use in logging Returns ------- data : ndarray or `None` Image data, if found. wcs : obj or `None` GWCS object or models, if found. ahdr : dict Header containing metadata. """ # TODO: support other types, like AstroTable, if ASDF can contain them data_obj = AstroImage.AstroImage(logger=logger) # TODO: idx may contain info about what part of the file to load # e.g. should we pass as 'data_key' parameter? data, wcs, ahdr = load_from_asdf(asdf_obj) data_obj.setup_data(data, naxispath=None) wcsinfo = wcsmod.get_wcs_class('astropy_ape14') data_obj.wcs = wcsinfo.wrapper_class(logger=logger) data_obj.wcs.wcs = wcs if wcs is not None: data_obj.wcs.coordsys = wcs.output_frame.name return data_obj
def loader(filepath, logger=None, **kwargs): """ Load an object from an ASDF file. See :func:`ginga.util.loader` for more info. TODO: kwargs may contain info about what part of the file to load """ # see ginga.util.loader module # TODO: return an AstroTable if loading a table, etc. # for now, assume always an image from ginga import AstroImage image = AstroImage.AstroImage(logger=logger) with asdf.open(filepath) as asdf_f: #image.load_asdf(asdf_f, **kwargs) image.load_asdf(asdf_f) return image
def radectopix_scalar_runtest(self, modname): if not wcsmod.use(modname, raise_err=False): return False wcs = wcsmod.WCS(self.logger) wcs.load_header(self.header) img = AstroImage.AstroImage(logger=self.logger) img.wcs = wcs img.naxispath = [] x_v1 = 120 y_v1 = 100 x, y = img.radectopix(300.2308791294835, 22.691653517073615) assert numpy.isclose(x, x_v1), \ ValueError("x does not match (%f != %f)" % (x, x_v1)) assert numpy.isclose(y, y_v1), \ ValueError("y does not match (%f != %f)" % (y, y_v1)) return True
def mosaic_some(self, paths, image_loader=None): if image_loader == None: image_loader = self.fv.load_image for url in paths: if self.ev_intr.isSet(): break mosaic_hdus = self.settings.get('mosaic_hdus', False) if mosaic_hdus: self.logger.debug("mosaicing hdus") # User wants us to mosaic HDUs # TODO: do this in a different thread? with pyfits.open(url, 'readonly') as in_f: i = 0 for hdu in in_f: i += 1 if hdu.data == None: continue self.logger.debug("ingesting hdu #%d" % (i)) image = AstroImage.AstroImage(logger=self.logger) image.load_hdu(hdu) image.set(name='hdu%d' % (i)) with self.lock: self.fv.gui_call(self.fv.error_wrap, self.ingest_one, image) with self.lock: count = self.ingest_count else: image = image_loader(url) with self.lock: self.fv.gui_call(self.fv.error_wrap, self.ingest_one, image) count = self.ingest_count self.update_progress(float(count)/self.total_files) if count == self.total_files: self.end_progress() total_elapsed = time.time() - self.start_time msg = "Done. Total=%.2f Process=%.2f (sec)" % ( total_elapsed, self.process_elapsed) self.update_status(msg)
def set_hdu(self, idx): self.logger.debug("Loading fits hdu #%d" % (idx)) image = AstroImage.AstroImage(logger=self.logger) try: hdu = self.fits_f[idx - 1] dims = list(hdu.data.shape) dims.reverse() image.load_hdu(hdu) image.set(path=self.path) self.fitsimage.set_image(image) self.build_naxis(dims) self.curhdu = idx - 1 self.logger.debug("HDU #%d loaded." % (idx)) except Exception as e: errmsg = "Error loading FITS HDU #%d: %s" % (idx, str(e)) self.logger.error(errmsg) self.fv.show_error(errmsg)
def pixtoradec_scalar_runtest(self, modname): if not wcsmod.use(modname, raise_err=False): return False wcs = wcsmod.WCS(self.logger) wcs.load_header(self.header) img = AstroImage.AstroImage(logger=self.logger) img.wcs = wcs img.revnaxis = [] ra_deg_v1 = 300.2308791294835 dec_deg_v1 = 22.691653517073615 ra_deg, dec_deg = img.pixtoradec(120, 100) assert numpy.isclose(ra_deg, ra_deg_v1), \ ValueError("RA deg does not match (%f != %f)" % (ra_deg, ra_deg_v1)) assert numpy.isclose(dec_deg, dec_deg_v1), \ ValueError("DEC deg does not match (%f != %f)" % (dec_deg, dec_deg_v1)) return True