Пример #1
0
    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
Пример #3
0
    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)
Пример #4
0
    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
Пример #5
0
    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)
Пример #6
0
    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()
Пример #7
0
    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()