def slice_to_spectrogram(self, y_coord, x_coord=None, **kwargs): """ For a time-lambda-y cube, given a y-coordinate, returns a sunpy spectrogram. Keyword arguments are passed on to Spectrogram's __init__. Parameters ---------- y_coord: int The y-coordinate to pick when converting to a spectrogram. x_coord: int The x-coordinate to pick. This is only used for hypercubes. """ if self.axes_wcs.wcs.ctype[0] not in ['TIME', 'UTC']: raise cu.CubeError( 1, 'Cannot create a spectrogram with no time axis') if self.axes_wcs.wcs.ctype[1] != 'WAVE': raise cu.CubeError(2, 'A spectral axis is needed in a spectrogram') if self.data.ndim == 3: data = self.data[:, :, cu.pixelize(y_coord, self.axes_wcs, 2)] else: if x_coord is None: raise cu.CubeError(4, 'An x-coordinate is needed for 4D cubes') data = self.data[:, :, cu.pixelize(y_coord, self.axes_wcs, 2), cu.pixelize(x_coord, self.axes_wcs, 3)] time_axis = self.time_axis().value freq_axis = self.wavelength_axis().value if 'DATE_OBS' in self.meta: tformat = '%Y-%m-%dT%H:%M:%S.%f' start = datetime.datetime.strptime(self.meta['DATE_OBS'], tformat) else: start = datetime.datetime(1, 1, 1) if 'DATE_END' in self.meta: tformat = '%Y-%m-%dT%H:%M:%S.%f' end = datetime.datetime.strptime(self.meta['DATE_END'], tformat) else: dif = time_axis[-1] - time_axis[0] unit = self.axes_wcs.wcs.cunit[0] dif = dif * u.Unit(unit) days = dif.to(sday) lapse = datetime.timedelta(days.value) end = start + lapse return Spectrogram(data=data, time_axis=time_axis, freq_axis=freq_axis, start=start, end=end, **kwargs)
def slice_to_spectrogram(self, y_coord, x_coord=None, **kwargs): """ For a time-lambda-y cube, given a y-coordinate, returns a sunpy spectrogram. Keyword arguments are passed on to Spectrogram's __init__. Parameters ---------- y_coord: int The y-coordinate to pick when converting to a spectrogram. x_coord: int The x-coordinate to pick. This is only used for hypercubes. """ if self.axes_wcs.wcs.ctype[0] not in ['TIME', 'UTC']: raise cu.CubeError(1, 'Cannot create a spectrogram with no time axis') if self.axes_wcs.wcs.ctype[1] != 'WAVE': raise cu.CubeError(2, 'A spectral axis is needed in a spectrogram') if self.data.ndim == 3: data = self.data[:, :, cu.pixelize(y_coord, self.axes_wcs, 2)] else: if x_coord is None: raise cu.CubeError(4, 'An x-coordinate is needed for 4D cubes') data = self.data[:, :, cu.pixelize(y_coord, self.axes_wcs, 2), cu.pixelize(x_coord, self.axes_wcs, 3)] time_axis = self.time_axis().value freq_axis = self.wavelength_axis().value if 'DATE_OBS'in self.meta: tformat = '%Y-%m-%dT%H:%M:%S.%f' start = datetime.datetime.strptime(self.meta['DATE_OBS'], tformat) else: start = datetime.datetime(1, 1, 1) if 'DATE_END' in self.meta: tformat = '%Y-%m-%dT%H:%M:%S.%f' end = datetime.datetime.strptime(self.meta['DATE_END'], tformat) else: dif = time_axis[-1] - time_axis[0] unit = self.axes_wcs.wcs.cunit[0] dif = dif * u.Unit(unit) days = dif.to(sday) lapse = datetime.timedelta(days.value) end = start + lapse return Spectrogram(data=data, time_axis=time_axis, freq_axis=freq_axis, start=start, end=end, **kwargs)
def slice_to_lightcurve(self, wavelength, y_coord=None, x_coord=None): """ For a time-lambda-y cube, returns a lightcurve with curves at the specified wavelength and given y-coordinate. If no y is given, all of them will be used (meaning the lightcurve object could contain more than one timecurve.) Parameters ---------- wavelength: int or astropy quantity The wavelength to take the y-coordinates from y_coord: int or astropy quantity, optional The y-coordinate to take the lightcurve from. x_coord: int or astropy quantity, optional In the case of hypercubes, specify an extra celestial coordinate. """ if self.axes_wcs.wcs.ctype[0] not in ['TIME', 'UTC']: raise cu.CubeError(1, 'Cannot create a lightcurve with no time axis') if self.axes_wcs.wcs.ctype[1] != 'WAVE': raise cu.CubeError(2, 'A spectral axis is needed in a lightcurve') if self.data.ndim == 3: data = self._choose_wavelength_slice(wavelength) if y_coord is not None: data = data[:, cu.pixelize(y_coord, self.axes_wcs, 1)] else: if y_coord is None and x_coord is None: raise cu.CubeError(4, "At least one coordinate must be given") if y_coord is None: y_coord = slice(None, None, None) else: y_coord = cu.pixelize(y_coord, self.axes_wcs, 2) if x_coord is None: x_coord = slice(None, None, None) else: x_coord = cu.pixelize(x_coord, self.axes_wcs, 3) item = (slice(None, None, None), wavelength, y_coord, x_coord) data = self.data[item] return LightCurve(data=data, meta=self.meta)
def slice_to_spectrum(self, *coords, **kwargs): """ For a cube containing a spectral dimension, returns a sunpy spectrum. The given coordinates represent which values to take. If they are None, then the corresponding axis is summed. Parameters ---------- fst_coord: int or None The first coordinate to pick. Keep in mind that depending on the cube, this may be in the first or second axis. If None, the whole axis will be taken and its values summed. snd_coord: int or None The second coordinate to pick. This will always correspond to the third axis. If None, the whole axis will be taken and its values summed. """ if 'WAVE' not in self.axes_wcs.wcs.ctype: raise cu.CubeError(2, 'Spectral axis needed to create a spectrum') axis = -1 if self.axes_wcs.wcs.ctype[0] == 'WAVE' else -2 pixels = [cu.pixelize(coord, self.axes_wcs, axis) for coord in coords] item = range(len(pixels)) if axis == -1: item[1:] = pixels item[0] = slice(None, None, None) item = [slice(None, None, None) if i is None else i for i in item] else: item[0] = pixels[0] item[1] = slice(None, None, None) item[2:] = pixels[1:] item = [slice(None, None, None) if i is None else i for i in item] data = self.data[item] errors = (None if self.uncertainty is None else self.uncertainty[item]) mask = None if self.mask is None else self.mask[item] for i in range(len(pixels)): if pixels[i] is None: if i == 0: sumaxis = 1 if axis == -1 else 0 else: sumaxis = 1 if i == 2 else i data = data.sum(axis=sumaxis) mask = mask.sum(axis=sumaxis) kwargs.update({'uncertainty': errors, 'mask': mask}) wavelength_axis = self.wavelength_axis() freq_axis, cunit = wavelength_axis.value, wavelength_axis.unit err = self.uncertainty[item] if self.uncertainty is not None else None kwargs.update({'uncertainty': err}) return Spectrum(np.array(data), np.array(freq_axis), cunit, **kwargs)
def slice_to_map(self, chunk, snd_dim=None, *args, **kwargs): """ Converts a given frequency chunk to a SunPy Map. Extra parameters are passed on to Map. Parameters ---------- chunk: int or astropy quantity or tuple The piece of the cube to convert to a map. If it's a single number, then it will return that single-slice map, otherwise it will aggregate the given range. Depending on the cube, this may correspond to a time or an energy dimension snd_dim: int or astropy quantity or tuple, optional Only used for hypercubes, the wavelength to choose from; works in the same way as chunk. """ if self.axes_wcs.wcs.ctype[1] == 'WAVE' and self.data.ndim == 3: error = "Cannot construct a map with only one spatial dimension" raise cu.CubeError(3, error) if isinstance(chunk, tuple): item = slice(cu.pixelize(chunk[0], self.axes_wcs, -1), cu.pixelize(chunk[1], self.axes_wcs, -1), None) maparray = self.data[item].sum(0) else: maparray = self.data[cu.pixelize(chunk, self.axes_wcs, -1)] if self.data.ndim == 4: if snd_dim is None: error = "snd_dim must be given when slicing hypercubes" raise cu.CubeError(4, error) if isinstance(snd_dim, tuple): item = slice(cu.pixelize(snd_dim[0], self.axes_wcs, -1), cu.pixelize(snd_dim[1], self.axes_wcs, -1), None) maparray = maparray[item].sum(0) else: maparray = maparray[cu.pixelize(snd_dim, self.axes_wcs, -1)] mapheader = MetaDict(self.meta) gmap = GenericMap(data=maparray, header=mapheader, *args, **kwargs) return gmap