def convolve_energies(self, events, prng): """ Convolve the events with a RMF file. """ mylog.info("Reading response matrix file (RMF): %s" % self.rmf) rmf = RedistributionMatrixFile(self.rmf) eidxs = np.argsort(events["eobs"]) sorted_e = events["eobs"][eidxs].d detectedChannels = [] # run through all photon energies and find which bin they go in fcurr = 0 last = sorted_e.size pbar = get_pbar("Scattering energies with RMF", last) for (k, low), high in zip(enumerate(rmf.elo), rmf.ehi): # weight function for probabilities from RMF weights = np.nan_to_num(np.float64(rmf.data["MATRIX"][k])) if weights.sum() <= 0.0: continue weights /= weights.sum() # build channel number list associated to array value, # there are groups of channels in rmfs with nonzero probabilities trueChannel = [] f_chan = ensure_numpy_array(np.nan_to_num(rmf.data["F_CHAN"][k])) n_chan = ensure_numpy_array(np.nan_to_num(rmf.data["N_CHAN"][k])) for start, nchan in zip(f_chan, n_chan): if start > -1: if nchan == 0: trueChannel.append(start) else: trueChannel += list(range(start, start + nchan)) trueChannel = np.array(trueChannel) nc = trueChannel.size if nc > 0: ww = weights[:nc] e = sorted_e[fcurr:last] nn = np.logical_and(low <= e, e < high).sum() channelInd = prng.choice(nc, size=nn, p=ww) detectedChannels.append(trueChannel[channelInd]) fcurr += nn pbar.update(fcurr) pbar.finish() for key in ["xpix", "ypix", "xsky", "ysky"]: events.events[key] = events[key][eidxs] events.events["eobs"] = YTArray(sorted_e, "keV") events.events[rmf.header["CHANTYPE"]] = np.concatenate( detectedChannels).astype("int") events.parameters["RMF"] = rmf.filename events.parameters["ChannelType"] = rmf.header["CHANTYPE"] events.parameters["Telescope"] = rmf.header["TELESCOP"] events.parameters["Instrument"] = rmf.header["INSTRUME"] events.parameters["Mission"] = rmf.header.get("MISSION", "")
def _find_points(self, x, y, z): """ Returns the (objects, indices) of leaf grids containing a number of (x,y,z) points """ x = ensure_numpy_array(x) y = ensure_numpy_array(y) z = ensure_numpy_array(z) if not len(x) == len(y) == len(z): raise AssertionError("Arrays of indices must be of the same size") grid_tree = self._get_grid_tree() pts = MatchPointsToGrids(grid_tree, len(x), x, y, z) ind = pts.find_points_in_tree() return self.grids[ind], ind
def rotate(self, theta, rot_vector=None, rot_center=None): r"""Rotate by a given angle Rotate the view. If `rot_vector` is None, rotation will occur around the `north_vector`. Parameters ---------- theta : float, in radians Angle (in radians) by which to rotate the view. rot_vector : array_like, optional Specify the rotation vector around which rotation will occur. Defaults to None, which sets rotation around `north_vector` rot_center : array_like, optional Specify the center around which rotation will occur. Defaults to None, which sets rotation around the original camera position (i.e. the camera position does not change) Examples -------- >>> import yt >>> import numpy as np >>> from yt.visualization.volume_rendering.api import Scene >>> sc = Scene() >>> cam = sc.add_camera() >>> # rotate the camera by pi / 4 radians: >>> cam.rotate(np.pi/4.0) >>> # rotate the camera about the y-axis instead of cam.north_vector: >>> cam.rotate(np.pi/4.0, np.array([0.0, 1.0, 0.0])) >>> # rotate the camera about the origin instead of its own position: >>> cam.rotate(np.pi/4.0, rot_center=np.array([0.0, 0.0, 0.0])) """ rotate_all = rot_vector is not None if rot_vector is None: rot_vector = self.north_vector if rot_center is None: rot_center = self._position rot_vector = ensure_numpy_array(rot_vector) rot_vector = rot_vector/np.linalg.norm(rot_vector) new_position = self._position - rot_center R = get_rotation_matrix(theta, rot_vector) new_position = np.dot(R, new_position) + rot_center if (new_position == self._position).all(): normal_vector = self.unit_vectors[2] else: normal_vector = rot_center - new_position normal_vector = normal_vector/np.sqrt((normal_vector**2).sum()) if rotate_all: self.switch_view( normal_vector=np.dot(R, normal_vector), north_vector=np.dot(R, self.unit_vectors[1])) else: self.switch_view(normal_vector=np.dot(R, normal_vector)) if (new_position != self._position).any(): self.set_position(new_position)
def _find_field_values_at_points(self, fields, coords): r"""Find the value of fields at a set of coordinates. Returns the values [field1, field2,...] of the fields at the given (x, y, z) points. Returns a numpy array of field values cross coords """ coords = self.ds.arr(ensure_numpy_array(coords), 'code_length') grids = self._find_points(coords[:, 0], coords[:, 1], coords[:, 2])[0] fields = ensure_list(fields) mark = np.zeros(3, dtype=np.int) out = [] # create point -> grid mapping grid_index = {} for coord_index, grid in enumerate(grids): if grid not in grid_index: grid_index[grid] = [] grid_index[grid].append(coord_index) out = [] for field in fields: funit = self.ds._get_field_info(field).units out.append(self.ds.arr(np.empty((len(coords))), funit)) for grid in grid_index: cellwidth = (grid.RightEdge - grid.LeftEdge) / grid.ActiveDimensions for field_index, field in enumerate(fields): for coord_index in grid_index[grid]: mark = ((coords[coord_index, :] - grid.LeftEdge) / cellwidth) mark = np.array(mark, dtype='int64') out[field_index][coord_index] = \ grid[field][mark[0], mark[1], mark[2]] if len(fields) == 1: return out[0] return out
def __init__(self, left_edge, right_edge, color=None): assert (left_edge.shape == (3, )) assert (right_edge.shape == (3, )) if color is None: color = np.array([1.0, 1.0, 1.0, 1.0]) color = ensure_numpy_array(color) color.shape = (1, 4) corners = get_corners(left_edge.copy(), right_edge.copy()) order = [0, 1, 1, 2, 2, 3, 3, 0] order += [4, 5, 5, 6, 6, 7, 7, 4] order += [0, 4, 1, 5, 2, 6, 3, 7] vertices = np.empty([24, 3]) for i in range(3): vertices[:, i] = corners[order, i, ...].ravel(order='F') vertices = vertices.reshape((12, 2, 3)) super(BoxSource, self).__init__(vertices, color, color_stride=24)
def __call__(self, chunk): num_photons_max = 10000000 emid = self.spectral_model.emid ebins = self.spectral_model.ebins nchan = len(emid) kT = (kboltz * chunk[self.temperature_field]).in_units("keV").v if len(kT) == 0: return EM = chunk[self.emission_measure_field].v idxs = np.argsort(kT) kT_sorted = kT[idxs] idx_min = np.searchsorted(kT_sorted, self.kT_min) idx_max = np.searchsorted(kT_sorted, self.kT_max) idxs = idxs[idx_min:idx_max] num_cells = len(idxs) if num_cells == 0: return kT_idxs = np.digitize(kT[idxs], self.kT_bins) - 1 bcounts = np.bincount(kT_idxs).astype("int") bcounts = bcounts[bcounts > 0] n = int(0) bcell = [] ecell = [] for bcount in bcounts: bcell.append(n) ecell.append(n + bcount) n += bcount kT_idxs = np.unique(kT_idxs) cell_em = EM[idxs] * self.spectral_norm if isinstance(self.Zmet, float): metalZ = self.Zmet * np.ones(num_cells) else: metalZ = chunk[self.Zmet].v[idxs] * self.Zconvert number_of_photons = np.zeros(num_cells, dtype="int64") energies = np.zeros(num_photons_max) start_e = 0 end_e = 0 for ibegin, iend, ikT in zip(bcell, ecell, kT_idxs): kT = self.kT_bins[ikT] + 0.5 * self.dkT[ikT] cem = cell_em[ibegin:iend] cspec, mspec = self.spectral_model.get_spectrum(kT) tot_ph_c = cspec.d.sum() tot_ph_m = mspec.d.sum() cell_norm_c = tot_ph_c * cem cell_norm_m = tot_ph_m * metalZ[ibegin:iend] * cem cell_norm = cell_norm_c + cell_norm_m cell_n = ensure_numpy_array(self.prng.poisson(lam=cell_norm)) number_of_photons[ibegin:iend] = cell_n end_e += int(cell_n.sum()) if self.method == "invert_cdf": cumspec_c = np.cumsum(cspec.d) cumspec_m = np.cumsum(mspec.d) cumspec_c = np.insert(cumspec_c, 0, 0.0) cumspec_m = np.insert(cumspec_m, 0, 0.0) ei = start_e for cn, Z in zip(number_of_photons[ibegin:iend], metalZ[ibegin:iend]): self.pbar.update() if cn == 0: continue # The rather verbose form of the few next statements is a # result of code optimization and shouldn't be changed # without checking for perfomance degradation. See # https://bitbucket.org/yt_analysis/yt/pull-requests/1766 # for details. if self.method == "invert_cdf": cumspec = cumspec_c cumspec += Z * cumspec_m norm_factor = 1.0 / cumspec[-1] cumspec *= norm_factor randvec = self.prng.uniform(size=cn) randvec.sort() cell_e = np.interp(randvec, cumspec, ebins) elif self.method == "accept_reject": tot_spec = cspec.d tot_spec += Z * mspec.d norm_factor = 1.0 / tot_spec.sum() tot_spec *= norm_factor eidxs = self.prng.choice(nchan, size=cn, p=tot_spec) cell_e = emid[eidxs] while ei + cn > num_photons_max: num_photons_max *= 2 if num_photons_max > energies.size: energies.resize(num_photons_max, refcheck=False) energies[ei:ei + cn] = cell_e ei += cn start_e = end_e active_cells = number_of_photons > 0 idxs = idxs[active_cells] return number_of_photons[active_cells], idxs, energies[:end_e].copy()
def __call__(self, chunk): num_photons_max = 10000000 emid = self.spectral_model.emid ebins = self.spectral_model.ebins nchan = len(emid) kT = (kboltz*chunk[self.temperature_field]).in_units("keV").v if len(kT) == 0: return EM = chunk[self.emission_measure_field].v idxs = np.argsort(kT) kT_sorted = kT[idxs] idx_min = np.searchsorted(kT_sorted, self.kT_min) idx_max = np.searchsorted(kT_sorted, self.kT_max) idxs = idxs[idx_min:idx_max] num_cells = len(idxs) if num_cells == 0: return kT_idxs = np.digitize(kT[idxs], self.kT_bins)-1 bcounts = np.bincount(kT_idxs).astype("int") bcounts = bcounts[bcounts > 0] n = int(0) bcell = [] ecell = [] for bcount in bcounts: bcell.append(n) ecell.append(n+bcount) n += bcount kT_idxs = np.unique(kT_idxs) cell_em = EM[idxs]*self.spectral_norm if self.nei: metalZ = np.zeros(num_cells) elem_keys = self.var_ion_keys else: elem_keys = self.var_elem_keys if isinstance(self.Zmet, float): metalZ = self.Zmet*np.ones(num_cells) else: metalZ = chunk[self.Zmet].v[idxs]*self.Zconvert elemZ = None if self.num_var_elem > 0: elemZ = np.zeros((self.num_var_elem, num_cells)) for j, key in enumerate(elem_keys): value = self.var_elem[key] if isinstance(value, float): elemZ[j, :] = value else: elemZ[j, :] = chunk[value].v[idxs]*self.mconvert[key] number_of_photons = np.zeros(num_cells, dtype="int64") energies = np.zeros(num_photons_max) start_e = 0 end_e = 0 for ibegin, iend, ikT in zip(bcell, ecell, kT_idxs): kT = self.kT_bins[ikT] + 0.5*self.dkT[ikT] cem = cell_em[ibegin:iend] cspec, mspec, vspec = self.spectral_model.get_spectrum(kT) tot_ph_c = cspec.d.sum() tot_ph_m = mspec.d.sum() cell_norm_c = tot_ph_c*cem cell_norm_m = tot_ph_m*metalZ[ibegin:iend]*cem cell_norm = cell_norm_c + cell_norm_m if vspec is not None: cell_norm_v = np.zeros(cem.size) for j in range(self.num_var_elem): tot_ph_v = vspec.d[j, :].sum() cell_norm_v += tot_ph_v*elemZ[j, ibegin:iend]*cem cell_norm += cell_norm_v cell_n = ensure_numpy_array(self.prng.poisson(lam=cell_norm)) number_of_photons[ibegin:iend] = cell_n end_e += int(cell_n.sum()) if self.method == "invert_cdf": cumspec_c = np.insert(np.cumsum(cspec.d), 0, 0.0) cumspec_m = np.insert(np.cumsum(mspec.d), 0, 0.0) if vspec is None: cumspec_v = None else: cumspec_v = np.zeros((self.num_var_elem, nchan+1)) for j in range(self.num_var_elem): cumspec_v[j, 1:] = np.cumsum(vspec.d[j, :]) ei = start_e for icell in range(ibegin, iend): self.pbar.update() cn = number_of_photons[icell] if cn == 0: continue # The rather verbose form of the few next statements is a # result of code optimization and shouldn't be changed # without checking for perfomance degradation. See # https://bitbucket.org/yt_analysis/yt/pull-requests/1766 # for details. if self.method == "invert_cdf": cumspec = cumspec_c cumspec += metalZ[icell] * cumspec_m if cumspec_v is not None: for j in range(self.num_var_elem): cumspec += elemZ[j, icell]*cumspec_v[j, :] norm_factor = 1.0 / cumspec[-1] cumspec *= norm_factor randvec = self.prng.uniform(size=cn) randvec.sort() cell_e = np.interp(randvec, cumspec, ebins) elif self.method == "accept_reject": tot_spec = cspec.d tot_spec += metalZ[icell] * mspec.d if vspec is not None: for j in range(self.num_var_elem): tot_spec += elemZ[j, icell]*vspec.d[j, :] norm_factor = 1.0 / tot_spec.sum() tot_spec *= norm_factor eidxs = self.prng.choice(nchan, size=cn, p=tot_spec) cell_e = emid[eidxs] while ei+cn > num_photons_max: num_photons_max *= 2 if num_photons_max > energies.size: energies.resize(num_photons_max, refcheck=False) energies[ei:ei+cn] = cell_e ei += cn start_e = end_e active_cells = number_of_photons > 0 idxs = idxs[active_cells] ncells = idxs.size return ncells, number_of_photons[active_cells], idxs, energies[:end_e].copy()