def reverse_add_data(self, data_item): """ Adds data from specviz to glue. Parameters ---------- data_item : :class:`specviz.core.items.DataItem` The data item recently added to model. """ new_data = Data(label=data_item.name) new_data.coords = coordinates_from_header(data_item.spectrum.wcs) flux_component = Component(data_item.spectrum.flux, data_item.spectrum.flux.unit) new_data.add_component(flux_component, "Flux") disp_component = Component(data_item.spectrum.spectral_axis, data_item.spectrum.spectral_axis.unit) new_data.add_component(disp_component, "Dispersion") if data_item.spectrum.uncertainty is not None: uncert_component = Component(data_item.spectrum.uncertainty.array, data_item.spectrum.uncertainty.unit) new_data.add_component(uncert_component, "Uncertainty") self._session.data_collection.append(new_data)
def cube_to_data(self, cube, output_label=None, output_component_id=None): """ Convert SpectralCube to final output. self.output_as_component is checked here. if self.output_as_component: add new component to self.data else: create new data and return it. :param cube: SpectralCube :param output_label: Name of new Data. :param output_component_id: label of new component :return: """ original_data = self.data new_component = Component(cube._data.copy(), self.component_unit) if self.output_as_component: original_data.add_component(new_component, output_component_id) return None else: new_data = Data(label=output_label) new_data.coords = coordinates_from_header(cube.header) new_data.add_component(new_component, output_component_id) return new_data
def _load_GALFAHI_data_LowRes(filename, **kwargs): # Data loader customized for GALFA-HI data cube # Resize the data cube into lower resolution in velocity/space def _bin_cube(cube, factor, axis_label): # resize the cube to lower resolution shape = cube.shape if axis_label == 'VELO': new_shape = (shape[0]/factor, factor, shape[1], shape[2]) return cube.reshape(new_shape).mean(axis = 1) elif axis_label == 'RADEC': new_shape = (shape[0], shape[1]/factor, factor, shape[2]/factor, factor) return cube.reshape(new_shape).mean(axis = 4).mean(axis = 2) else: return cube # change the header for those cubes that has been binned into low resolutions def _get_new_header(header, factor, axis_label): new_header = header if axis_label == 'VELO': new_header['NAXIS3'] = header['NAXIS3'] / factor new_header['CRVAL3'] = header['CRVAL3'] new_header['CRPIX3'] = float(header['CRPIX3'] / factor) new_header['CDELT3'] = header['CDELT3'] * factor elif axis_label == 'RADEC': for ax in [1, 2]: new_header['NAXIS%d'%(ax)] = header['NAXIS%d'%(ax)] / factor new_header['CRVAL%d'%(ax)] = header['CRVAL%d'%(ax)] new_header['CRPIX%d'%(ax)] = float(header['CRPIX%d'%(ax)] / factor) new_header['CDELT%d'%(ax)] = header['CDELT%d'%(ax)] * factor else: new_header = header # m/s --> km/s new_header['CDELT3'] = new_header['CDELT3'] * (10**(-3)) return new_header def _get_cube_center(header, cubeshape): ra = header['CRVAL1'] + header['CDELT1'] * (np.arange(cubeshape[2])+0.5 - header['CRPIX1']) ## degree dec = header['CRVAL2'] + header['CDELT2'] * (np.arange(cubeshape[1])+0.5 - header['CRPIX2']) ## degree return np.mean(ra), np.mean(dec) data_list = [] # add 3 data objects with different resolutions: for factor, axis_label in zip([4, 16, 2], ['VELO', 'VELO', 'RADEC']): cube = fits.getdata(filename) header = fits.getheader(filename) cen_ra, cen_dec = _get_cube_center(header, cube.shape) new_header = _get_new_header(header, factor, axis_label) cube_name = 'G_%d%+.2fradec_%.1fkm/s_%.1fa' % (cen_ra, cen_dec, new_header['CDELT3'], new_header['CDELT2']*60.) data = Data() data.coords = coordinates_from_header(new_header) data.add_component(_bin_cube(cube, factor, axis_label), cube_name) data.label = cube_name data_list.append(data) del data, cube, header return data_list
def acs_cutout_image_reader(file_name): """ Data loader for the ACS cut-outs for the DEIMOS spectra. The cutouts contain only the image. """ hdulist = fits.open(file_name) data = Data(label='ACS Cutout Image') data.coords = coordinates_from_header(hdulist[0].header) data.header = hdulist[0].header data.add_component(hdulist[0].data, 'Flux') return data
def _load_fits_generic(filename, **kwargs): hdulist = fits.open(filename) groups = dict() label_base = basename(filename).rpartition('.')[0] if not label_base: label_base = basename(filename) for extnum, hdu in enumerate(hdulist): if hdu.data is not None: hdu_name = hdu.name if hdu.name else str(extnum) if is_image_hdu(hdu): shape = hdu.data.shape try: data = groups[shape] except KeyError: label = '{}[{}]'.format( label_base, 'x'.join(str(x) for x in shape) ) data = Data(label=label) data.coords = coordinates_from_header(hdu.header) groups[shape] = data data.add_component(component=hdu.data, label=hdu_name) elif is_table_hdu(hdu): # Loop through columns and make component list table = Table(hdu.data) table_name = '{}[{}]'.format( label_base, hdu_name ) for column_name in table.columns: column = table[column_name] shape = column.shape data_label = '{}[{}]'.format( table_name, 'x'.join(str(x) for x in shape) ) try: data = groups[data_label] except KeyError: data = Data(label=data_label) groups[data_label] = data component = Component.autotyped(column, units=column.unit) data.add_component(component=component, label=column_name) return [data for data in groups.itervalues()]
def casalike_cube(filename, **kwargs): """ This provides special support for 4D CASA FITS - like cubes, which have 2 spatial axes, a spectral axis, and a stokes axis in that order. Each stokes cube is split out as a separate component """ from astropy.io import fits result = Data() with fits.open(filename, **kwargs) as hdulist: array = hdulist[0].data header = hdulist[0].header result.coords = coordinates_from_header(header) for i in range(array.shape[0]): result.add_component(array[[i]], label='STOKES %i' % i) return result
def nirspec_spectrum2d_reader(file_name): """ Data loader for simulated NIRSpec 2D spectrum. This function extracts the DATA, QUALITY, and VAR extensions and returns them as a glue Data object. It then uses the header keywords of the DATA extension to detemine the wavelengths. """ hdulist = fits.open(file_name) data = Data(label='2D Spectrum') data.header = hdulist['DATA'].header data.coords = coordinates_from_header(hdulist[1].header) data.add_component(hdulist['DATA'].data, 'Flux') data.add_component(hdulist['VAR'].data, 'Uncertainty') return data
def _load_fits_generic(filename, **kwargs): hdulist = fits.open(filename) groups = defaultdict(Data) for extnum, hdu in enumerate(hdulist): if not isinstance(hdu, fits.TableHDU) and\ hdu.data is not None: shape = hdu.data.shape if shape not in groups: label = '{}[{}]'.format( basename(filename).split('.', 1)[0], 'x'.join((str(x) for x in shape)) ) data = Data(label=label) data.coords = coordinates_from_header(hdu.header) groups[shape] = data else: data = groups[shape] data.add_component(component=hdu.data, label=hdu.header.get('EXTNAME', 'EXT[{}]'.format(str(extnum)))) return [data for data in groups.itervalues()]
def to_glue(self, label="yt", data_collection=None): """ Takes the data in the FITSImageData instance and exports it to Glue (http://www.glueviz.org) for interactive analysis. Optionally add a *label*. If you are already within the Glue environment, you can pass a *data_collection* object, otherwise Glue will be started. """ from glue.core import DataCollection, Data from glue.core.coordinates import coordinates_from_header from glue.qt.glue_application import GlueApplication image = Data(label=label) image.coords = coordinates_from_header(self.wcs.to_header()) for k,f in self.items(): image.add_component(f.data, k) if data_collection is None: dc = DataCollection([image]) app = GlueApplication(dc) app.start() else: data_collection.append(image)
def nirspec_level2_reader(file_name): """ Data Loader for level2 products. Uses extension information to index fits hdu list. The ext info is included in the file_name as follows: <file_path>[<ext>] """ file_name, ext = split_file_name(file_name, default_ext=1) hdulist = fits.open(file_name) data = Data(label="2D Spectra") data.header = hdulist[ext].header data.coords = coordinates_from_header(hdulist[ext].header) data.add_component(hdulist[ext].data, 'Level2 Flux') # TODO: update uncertainty once data model becomes clear data.add_component(np.sqrt(hdulist[ext + 2].data), 'Level2 Uncertainty') hdulist.close() return data
def gridded_data(filename, format='auto', **kwargs): result = Data() # Try and automatically find the format if not specified if format == 'auto': format = file_format(filename) # Read in the data if is_fits(filename): from astropy.io import fits arrays = extract_data_fits(filename, **kwargs) header = fits.getheader(filename) result.coords = coordinates_from_header(header) elif is_hdf5(filename): arrays = extract_data_hdf5(filename, **kwargs) else: raise Exception("Unkonwn format: %s" % format) for component_name in arrays: comp = Component.autotyped(arrays[component_name]) result.add_component(comp, component_name) return result
def casalike_cube(filename, **kwargs): """ This provides special support for 4D CASA FITS - like cubes, which have 2 spatial axes, a spectral axis, and a stokes axis in that order. Each stokes cube is split out as a separate component """ from astropy.io import fits result = Data() if 'ignore_missing_end' not in kwargs: kwargs['ignore_missing_end'] = True with fits.open(filename, mode='denywrite', **kwargs) as hdulist: array = hdulist[0].data header = hdulist[0].header result.coords = coordinates_from_header(header) for i in range(array.shape[0]): units = header.get('BUNIT') component = Component.autotyped(array[[i]], units=units) result.add_component(component, label='STOKES %i' % i) return result
def _load_GALFAHI_data(filename, **kwargs): def _get_cube_center(header, cubeshape): ra = header['CRVAL1'] + header['CDELT1'] * (np.arange(cubeshape[2])+0.5 - header['CRPIX1']) ## degree dec = header['CRVAL2'] + header['CDELT2'] * (np.arange(cubeshape[1])+0.5 - header['CRPIX2']) ## degree return np.mean(ra), np.mean(dec) # add the primary components cube = fits.getdata(filename) header = fits.getheader(filename) header['CDELT3'] = header['CDELT3'] * (10**(-3)) # m/s --> km/s cen_ra, cen_dec = _get_cube_center(header, cube.shape) nn = filename.split('/')[-1] # cube_name = '%s_RA%dDEC%d' % (nn[0:3], cen_ra, cen_dec) cube_name = 'G_%d%+.2fradec_%.1fkm/s_%.1fa' % (cen_ra, cen_dec, header['CDELT3'], header['CDELT2']*60.) data = Data() data.coords = coordinates_from_header(header) data.add_component(cube, cube_name) data.label = cube_name data_list = [] data_list.append(data) data_list.append(data) return data_list
def to_glue(self, label="yt", data_collection=None): """ Takes the data in the FITSImageData instance and exports it to Glue (http://glueviz.org) for interactive analysis. Optionally add a *label*. If you are already within the Glue environment, you can pass a *data_collection* object, otherwise Glue will be started. """ from glue.core import DataCollection, Data from glue.core.coordinates import coordinates_from_header try: from glue.app.qt.application import GlueApplication except ImportError: from glue.qt.glue_application import GlueApplication image = Data(label=label) image.coords = coordinates_from_header(self.wcs.to_header()) for k in self.fields: image.add_component(self[k].data, k) if data_collection is None: dc = DataCollection([image]) app = GlueApplication(dc) app.start() else: data_collection.append(image)
def nirspec_spectrum2d_reader(file_name): """ Data loader for simulated NIRSpec 2D spectrum. This function extracts the DATA, QUALITY, and VAR extensions and returns them as a glue Data object. It then uses the header keywords of the DATA extension to detemine the wavelengths. """ file_name, ext = split_file_name(file_name, default_ext=1) hdulist = fits.open(file_name) data = Data(label="2D Spectrum") data.header = hdulist['PRIMARY'].header data.coords = coordinates_from_header(hdulist[ext].header) data.add_component(hdulist[ext].data, 'Flux') data.add_component(np.sqrt(hdulist[ext + 2].data), 'Uncertainty') hdulist.close() return data
def nirspec_spectrum2d_reader(file_name): """ Data loader for simulated NIRSpec 2D spectrum. This function extracts the DATA, QUALITY, and VAR extensions and returns them as a glue Data object. It then uses the header keywords of the DATA extension to detemine the wavelengths. """ file_name, ext = split_file_name(file_name, default_ext=1) hdulist = fits.open(file_name) data = Data(label="2D Spectrum") data.header = hdulist['PRIMARY'].header data.coords = coordinates_from_header(hdulist[ext].header) data.add_component(hdulist[ext].data, 'Flux') data.add_component(np.sqrt(hdulist[ext + 2].data), 'Uncertainty') hdulist.close() return data
def to_glue(self, label="yt", data_collection=None): """ Takes the data in the FITSImageBuffer and exports it to Glue (http://www.glueviz.org) for interactive analysis. Optionally add a *label*. If you are already within the Glue environment, you can pass a *data_collection* object, otherwise Glue will be started. """ from glue.core import DataCollection, Data from glue.core.coordinates import coordinates_from_header from glue.qt.glue_application import GlueApplication field_dict = dict((key, self[key].data) for key in self.keys()) image = Data(label=label) image.coords = coordinates_from_header(self.wcs.to_header()) for k, v in field_dict.items(): image.add_component(v, k) if data_collection is None: dc = DataCollection([image]) app = GlueApplication(dc) app.start() else: data_collection.append(image)
def casalike_cube(filename, **kwargs): """ This provides special support for 4D CASA FITS - like cubes, which have 2 spatial axes, a spectral axis, and a stokes axis in that order. Each stokes cube is split out as a separate component """ from astropy.io import fits result = Data() if 'ignore_missing_end' not in kwargs: kwargs['ignore_missing_end'] = True with fits.open(filename, **kwargs) as hdulist: array = hdulist[0].data header = hdulist[0].header result.coords = coordinates_from_header(header) for i in range(array.shape[0]): units = header.get('BUNIT') component = Component.autotyped(array[[i]], units=units) result.add_component(component, label='STOKES %i' % i) return result
def fits_reader(source, auto_merge=False, exclude_exts=None, label=None): """ Read in all extensions from a FITS file. Parameters ---------- source: str or HDUList The pathname to the FITS file. If an HDUList is passed in, simply use that. auto_merge: bool Merge extensions that have the same shape and only one has a defined WCS. exclude_exts: [hdu, ] or [index, ] List of HDU's to exclude from reading. This can be a list of HDU's or a list of HDU indexes. """ from astropy.io import fits from astropy.table import Table exclude_exts = exclude_exts or [] if not isinstance(source, fits.hdu.hdulist.HDUList): hdulist = fits.open(source) hdulist.verify('fix') else: hdulist = source groups = OrderedDict() extension_by_shape = OrderedDict() if label is not None: label_base = label else: hdulist_name = hdulist.filename() if hdulist_name is None: hdulist_name = "HDUList" label_base = basename(hdulist_name).rpartition('.')[0] if not label_base: label_base = basename(hdulist_name) # Create a new image Data. def new_data(): label = '{0}[{1}]'.format(label_base, hdu_name) data = Data(label=label) data.coords = coords groups[hdu_name] = data extension_by_shape[shape] = hdu_name return data for extnum, hdu in enumerate(hdulist): hdu_name = hdu.name if hdu.name else "HDU{0}".format(extnum) if (hdu.data is not None and hdu.data.size > 0 and hdu_name not in exclude_exts and extnum not in exclude_exts): if is_image_hdu(hdu): shape = hdu.data.shape coords = coordinates_from_header(hdu.header) if not auto_merge or has_wcs(coords): data = new_data() else: try: data = groups[extension_by_shape[shape]] except KeyError: data = new_data() data.add_component(component=hdu.data, label=hdu_name) elif is_table_hdu(hdu): # Loop through columns and make component list table = Table(hdu.data) label = '{0}[{1}]'.format(label_base, hdu_name) data = Data(label=label) groups[hdu_name] = data for column_name in table.columns: column = table[column_name] component = Component(column, units=column.unit) data.add_component(component=component, label=column_name) return [groups[idx] for idx in groups]
def load_data(self, data_filenames): """ Load the data based on the extensions defined in the matching YAML file. THen create the datacube and return it. :param data_filename: :return: """ label = None data = None ifucube = IFUCube() for data_filename in data_filenames.split(','): hdulist = ifucube.open(data_filename, fix=self._check_ifu_valid) # Good in this case means the file has 3D data and can be loaded by SpectralCube.read if self._check_ifu_valid and not ifucube.get_good(): # Popup takes precedence and accepting continues operation and canceling closes the program self.popup_ui.ifucube_log.setText(ifucube.get_log_output()) self.popup_ui.setModal(True) self.popup_ui.show() self.popup_ui.button_accept.clicked.connect(self._accept_button_click) self.popup_ui.button_cancel.clicked.connect(self._reject_button_click) if not label: label = "{}: {}".format(self._name, splitext(basename(data_filename))[0]) data = Data(label=label) # this attribute is used to indicate to the cubeviz layout that # this is a cubeviz-specific data component. data.meta[CUBEVIZ_LAYOUT] = self._name data_coords_set = False for ii, hdu in enumerate(hdulist): if 'NAXIS' in hdu.header and hdu.header['NAXIS'] == 3: # Set the coords based on the first 3D HDU if not data_coords_set: data.coords = coordinates_from_header(hdu.header) data_coords_set = True component_name = str(ii) if 'EXTNAME' in hdu.header: component_name = hdu.header['EXTNAME'] # The data must be floating point as spectralcube is expecting floating point data data.add_component(component=hdu.data.astype(np.float), label=component_name) if 'BUNIT' in hdu.header: c = data.get_component(component_name) c.units = self.get_units(hdu.header) else: # Creates a unique component name component_name = str(ii) data.add_component(component=hdu.data.astype(np.float), label=component_name) # For the purposes of exporting, we keep a reference to the original HDUList object data._cubeviz_hdulist = hdulist return data
def fits_reader(source, auto_merge=False, exclude_exts=None, label=None): """ Read in all extensions from a FITS file. Parameters ---------- source: str or HDUList The pathname to the FITS file. If an HDUList is passed in, simply use that. auto_merge: bool Merge extensions that have the same shape and only one has a defined WCS. exclude_exts: [hdu, ] or [index, ] List of HDU's to exclude from reading. This can be a list of HDU's or a list of HDU indexes. """ from astropy.io import fits from astropy.table import Table exclude_exts = exclude_exts or [] if isinstance(source, fits.hdu.hdulist.HDUList): hdulist = source close_hdulist = False else: hdulist = fits.open(source, ignore_missing_end=True) hdulist.verify('fix') close_hdulist = True groups = OrderedDict() extension_by_shape = OrderedDict() if label is not None: label_base = label else: hdulist_name = hdulist.filename() if hdulist_name is None: hdulist_name = "HDUList" label_base = basename(hdulist_name).rpartition('.')[0] if not label_base: label_base = basename(hdulist_name) # Create a new image Data. def new_data(suffix=True): if suffix: label = '{0}[{1}]'.format(label_base, hdu_name) else: label = label_base data = Data(label=label) data.coords = coords # We need to be careful here because some header values are special # objects that we should convert to strings for key, value in hdu.header.items(): if (key == 'COMMENT' or key == 'HISTORY'): if key not in data.meta: data.meta[key] = [str(value)] else: data.meta[key].append(str(value)) elif isinstance(value, string_types) or isinstance(value, (int, float, bool)): data.meta[key] = value else: data.meta[key] = str(value) groups[hdu_name] = data extension_by_shape[shape] = hdu_name return data for extnum, hdu in enumerate(hdulist): hdu_name = hdu.name if hdu.name else "HDU{0}".format(extnum) if (hdu.data is not None and hdu.data.size > 0 and hdu_name not in exclude_exts and extnum not in exclude_exts): if is_image_hdu(hdu): shape = hdu.data.shape coords = coordinates_from_header(hdu.header) if not auto_merge or has_wcs(coords): data = new_data(suffix=len(hdulist) > 1) else: try: data = groups[extension_by_shape[shape]] except KeyError: data = new_data(suffix=len(hdulist) > 1) data.add_component(component=hdu.data, label=hdu_name) elif is_table_hdu(hdu): # Loop through columns and make component list table = Table.read(hdu, format='fits') label = '{0}[{1}]'.format(label_base, hdu_name) data = Data(label=label) groups[hdu_name] = data for column_name in table.columns: column = table[column_name] if column.ndim != 1: warnings.warn("Dropping column '{0}' since it is not 1-dimensional".format(column_name)) continue component = Component.autotyped(column, units=column.unit) data.add_component(component=component, label=column_name) if close_hdulist: hdulist.close() return [groups[idx] for idx in groups]
def fits_reader(source, auto_merge=False, exclude_exts=None, label=None): """ Read in all extensions from a FITS file. Parameters ---------- source: str or HDUList The pathname to the FITS file. If an HDUList is passed in, simply use that. auto_merge: bool Merge extensions that have the same shape and only one has a defined WCS. exclude_exts: [hdu, ] or [index, ] List of HDU's to exclude from reading. This can be a list of HDU's or a list of HDU indexes. """ from astropy.io import fits from astropy.table import Table exclude_exts = exclude_exts or [] if isinstance(source, fits.hdu.hdulist.HDUList): hdulist = source close_hdulist = False else: hdulist = fits.open(source, ignore_missing_end=True) hdulist.verify('fix') close_hdulist = True groups = OrderedDict() extension_by_shape = OrderedDict() if label is not None: label_base = label else: hdulist_name = hdulist.filename() if hdulist_name is None: hdulist_name = "HDUList" label_base = basename(hdulist_name).rpartition('.')[0] if not label_base: label_base = basename(hdulist_name) # Create a new image Data. def new_data(suffix=True): if suffix: label = '{0}[{1}]'.format(label_base, hdu_name) else: label = label_base data = Data(label=label) data.coords = coords # We need to be careful here because some header values are special # objects that we should convert to strings for key, value in hdu.header.items(): if (key == 'COMMENT' or key == 'HISTORY'): if key not in data.meta: data.meta[key] = [str(value)] else: data.meta[key].append(str(value)) elif isinstance(value, string_types) or isinstance(value, (int, float, bool)): data.meta[key] = value else: data.meta[key] = str(value) groups[hdu_name] = data extension_by_shape[shape] = hdu_name return data for extnum, hdu in enumerate(hdulist): hdu_name = hdu.name if hdu.name else "HDU{0}".format(extnum) if (hdu.data is not None and hdu.data.size > 0 and hdu_name not in exclude_exts and extnum not in exclude_exts): if is_image_hdu(hdu): shape = hdu.data.shape coords = coordinates_from_header(hdu.header) units = hdu.header.get('BUNIT') if not auto_merge or has_wcs(coords): data = new_data(suffix=len(hdulist) > 1) else: try: data = groups[extension_by_shape[shape]] except KeyError: data = new_data(suffix=len(hdulist) > 1) component = Component.autotyped(hdu.data, units=units) data.add_component(component=component, label=hdu_name) elif is_table_hdu(hdu): # Loop through columns and make component list table = Table.read(hdu, format='fits') label = '{0}[{1}]'.format(label_base, hdu_name) data = Data(label=label) groups[hdu_name] = data for column_name in table.columns: column = table[column_name] if column.ndim != 1: warnings.warn("Dropping column '{0}' since it is not 1-dimensional".format(column_name)) continue component = Component.autotyped(column, units=column.unit) data.add_component(component=component, label=column_name) if close_hdulist: hdulist.close() return [groups[idx] for idx in groups]
def fits_reader(source, auto_merge=False, exclude_exts=None, label=None): """ Read in all extensions from a FITS file. Parameters ---------- source: str or HDUList The pathname to the FITS file. If an HDUList is passed in, simply use that. auto_merge: bool Merge extensions that have the same shape and only one has a defined WCS. exclude_exts: [hdu, ] or [index, ] List of HDU's to exclude from reading. This can be a list of HDU's or a list of HDU indexes. """ from astropy.io import fits from astropy.table import Table exclude_exts = exclude_exts or [] if not isinstance(source, fits.hdu.hdulist.HDUList): hdulist = fits.open(source, ignore_missing_end=True) hdulist.verify('fix') else: hdulist = source groups = OrderedDict() extension_by_shape = OrderedDict() if label is not None: label_base = label else: hdulist_name = hdulist.filename() if hdulist_name is None: hdulist_name = "HDUList" label_base = basename(hdulist_name).rpartition('.')[0] if not label_base: label_base = basename(hdulist_name) # Create a new image Data. def new_data(): label = '{0}[{1}]'.format( label_base, hdu_name ) data = Data(label=label) data.coords = coords groups[hdu_name] = data extension_by_shape[shape] = hdu_name return data for extnum, hdu in enumerate(hdulist): hdu_name = hdu.name if hdu.name else "HDU{0}".format(extnum) if (hdu.data is not None and hdu.data.size > 0 and hdu_name not in exclude_exts and extnum not in exclude_exts): if is_image_hdu(hdu): shape = hdu.data.shape coords = coordinates_from_header(hdu.header) if not auto_merge or has_wcs(coords): data = new_data() else: try: data = groups[extension_by_shape[shape]] except KeyError: data = new_data() data.add_component(component=hdu.data, label=hdu_name) elif is_table_hdu(hdu): # Loop through columns and make component list table = Table.read(hdu, format='fits') label = '{0}[{1}]'.format( label_base, hdu_name ) data = Data(label=label) groups[hdu_name] = data for column_name in table.columns: column = table[column_name] if column.ndim != 1: warnings.warn("Dropping column '{0}' since it is not 1-dimensional".format(column_name)) continue component = Component.autotyped(column, units=column.unit) data.add_component(component=component, label=column_name) return [groups[idx] for idx in groups]
def _load_fits_generic(source, exclude_exts=None, **kwargs): """Read in all extensions from a FITS file. Parameters ---------- source: str or HDUList The pathname to the FITS file. If and HDUList is passed in, simply use that. exclude_exts: [hdu, ] or [index, ] List of HDU's to exclude from reading. This can be a list of HDU's or a list of HDU indexes. """ exclude_exts = exclude_exts or [] if not isinstance(source, fits.hdu.hdulist.HDUList): hdulist = fits.open(source) else: hdulist = source groups = dict() label_base = basename(hdulist.filename()).rpartition('.')[0] if not label_base: label_base = basename(hdulist.filename()) for extnum, hdu in enumerate(hdulist): hdu_name = hdu.name if hdu.name else str(extnum) if hdu.data is not None and \ hdu_name not in exclude_exts and \ extnum not in exclude_exts: if is_image_hdu(hdu): shape = hdu.data.shape try: data = groups[shape] except KeyError: label = '{}[{}]'.format( label_base, 'x'.join(str(x) for x in shape) ) data = Data(label=label) data.coords = coordinates_from_header(hdu.header) groups[shape] = data data.add_component(component=hdu.data, label=hdu_name) elif is_table_hdu(hdu): # Loop through columns and make component list table = Table(hdu.data) table_name = '{}[{}]'.format( label_base, hdu_name ) for column_name in table.columns: column = table[column_name] shape = column.shape data_label = '{}[{}]'.format( table_name, 'x'.join(str(x) for x in shape) ) try: data = groups[data_label] except KeyError: data = Data(label=data_label) groups[data_label] = data component = Component(column, units=column.unit) data.add_component(component=component, label=column_name) return [data for data in six.itervalues(groups)]
def load_data(self, data_filenames): """ Load the data based on the extensions defined in the matching YAML file. THen create the datacube and return it. :param data_filename: :return: """ label = None data = None ifucube = IFUCube() for data_filename in data_filenames.split(','): hdulist = ifucube.open(data_filename, fix=self._check_ifu_valid) # Good in this case means the file has 3D data and can be loaded by SpectralCube.read if self._check_ifu_valid and not ifucube.get_good(): # Popup takes precedence and accepting continues operation and canceling closes the program self.popup_ui.ifucube_log.setText(ifucube.get_log_output()) self.popup_ui.setModal(True) self.popup_ui.show() self.popup_ui.button_accept.clicked.connect( self._accept_button_click) self.popup_ui.button_cancel.clicked.connect( self._reject_button_click) if not label: label = "{}: {}".format(self._name, splitext(basename(data_filename))[0]) data = Data(label=label) # this attribute is used to indicate to the cubeviz layout that # this is a cubeviz-specific data component. data.meta[CUBEVIZ_LAYOUT] = self._name data_coords_set = False for ii, hdu in enumerate(hdulist): if 'NAXIS' in hdu.header and hdu.header['NAXIS'] == 3: # Set the coords based on the first 3D HDU if not data_coords_set: data.coords = coordinates_from_header(hdu.header) data_coords_set = True component_name = str(ii) if 'EXTNAME' in hdu.header: component_name = hdu.header['EXTNAME'] # The data must be floating point as spectralcube is expecting floating point data data.add_component(component=hdu.data.astype(np.float), label=component_name) if 'BUNIT' in hdu.header: c = data.get_component(component_name) c.units = self.get_units(hdu.header) else: # Creates a unique component name component_name = str(ii) data.add_component(component=hdu.data.astype(np.float), label=component_name) # For the purposes of exporting, we keep a reference to the original HDUList object data._cubeviz_hdulist = hdulist return data