def __call__(self, z=0, **kwargs):
        """
        Return a binning matrix for the given redshift based on the original
        wavelengths provided when the class was initiated.
        """
        """
        wavelengths = self.to_wavelengths * (1 + z)

        # Map which pixels go to which index, assuming that the from_wavelengths
        # scale is linear.
        pixel_edges = np.hstack([
            wavelengths[0] - (wavelengths[1] - wavelengths[0])/2.,
            wavelengths[:-1] + np.diff(wavelengths)/2.,
            wavelengths[-1] + (wavelengths[-1] - wavelengths[-2])/2.])

        fractional_indices_scale = (pixel_edges - self.from_wavelengths[0]) \
            * self._scale
        int_fractional_indices_scale = fractional_indices_scale.astype(int)

        upper_diagonals = 1 - fractional_indices_scale[:-1] % 1
        lower_diagonals = fractional_indices_scale[1:] % 1
        central_diagonal_pixel_width = np.diff(int_fractional_indices_scale) - 1

        normalised_scale = 1.0/(upper_diagonals + central_diagonal_pixel_width \
            + lower_diagonals)

        # If the to_wavelength is linear then the normalised scale per pixel
        # would be the same for every pixel. Let's not assume that..
        px_normalised_scale = np.repeat(normalised_scale,
            central_diagonal_pixel_width)

        values = np.hstack([
            upper_diagonals * normalised_scale,
            lower_diagonals * normalised_scale,
            np.ones(central_diagonal_pixel_width.sum()) * px_normalised_scale])

        _ = np.arange(self.N)
        y_indices = np.clip(
            np.hstack([_, _, np.repeat(_, central_diagonal_pixel_width)]),
                0, self.N - 1)
        x_indices = np.clip(np.hstack([
            int_fractional_indices_scale[:-1],
            int_fractional_indices_scale[1:],
            1 + np.repeat(int_fractional_indices_scale[:-1],
                central_diagonal_pixel_width)
            ]), 0, self.M - 1)

        return sparse.coo_matrix((values, (x_indices, y_indices)),
            shape=(self.M, self.N))
        """

        new_wavelengths = self.to_wavelengths * (1 + z)

        data = []
        old_px_indices = []
        new_px_indices = []
        for i, new_wl_i in enumerate(new_wavelengths):

            # These indices should span just over the new wavelength pixel.
            indices = np.unique(np.clip(
                self.from_wavelengths.searchsorted(new_wavelengths[i:i + 2], side="left")\
                    + [-1, +1], 0, self.from_wavelengths.size - 1))
            N = np.ptp(indices)

            if N == 0:
                # 'Fake' pixel.
                data.append(np.nan)
                new_px_indices.append(i)
                old_px_indices.extend(indices)
                continue

            # Sanity checks.
            assert (self.from_wavelengths[indices[0]] <= new_wl_i \
                or indices[0] == 0)
            assert (new_wl_i <= self.from_wavelengths[indices[1]] \
                or indices[1] == self.from_wavelengths.size - 1)

            fractions = np.ones(N)

            # Edges are handled as fractions between rebinned pixels.
            _ = np.clip(i + 1, 0, new_wavelengths.size - 1)
            lhs = self.from_wavelengths[indices[0]:indices[0] + 2]
            rhs = self.from_wavelengths[indices[-1] - 1:indices[-1] + 1]
            fractions[0]  = (lhs[1] - new_wavelengths[i])/np.ptp(lhs)
            fractions[-1] = (new_wavelengths[_] - rhs[0])/np.ptp(rhs)

            # Being binned to a single pixel. Prevent overflow from fringe cases.
            fractions = np.clip(fractions, 0, 1)
            fractions /= fractions.sum()

            data.extend(fractions) 
            new_px_indices.extend([i] * N) # Mark the new pixel indices affected.
            old_px_indices.extend(np.arange(*indices)) # And the old pixel indices.

        return sparse.csc_matrix((data, (old_px_indices, new_px_indices)),
            shape=(self.from_wavelengths.size, new_wavelengths.size))
def __call__ ( self , z = 0 , ** kwargs ) : new_wavelengths = self . to_wavelengths * ( 1 + z ) data = [ ] old_px_indices = [ ] new_px_indices = [ ] for i , new_wl_i in enumerate ( new_wavelengths ) : indices = np . unique ( np . clip ( self . from_wavelengths . searchsorted ( new_wavelengths [ i : i + 2 ] , side = "left" ) + [ - 1 , + 1 ] , 0 , self . from_wavelengths . size - 1 ) ) N = np . ptp ( indices ) if N == 0 : data . append ( np . nan ) new_px_indices . append ( i ) old_px_indices . extend ( indices ) continue assert ( self . from_wavelengths [ indices [ 0 ] ] <= new_wl_i or indices [ 0 ] == 0 ) assert ( new_wl_i <= self . from_wavelengths [ indices [ 1 ] ] or indices [ 1 ] == self . from_wavelengths . size - 1 ) fractions = np . ones ( N ) _ = np . clip ( i + 1 , 0 , new_wavelengths . size - 1 ) lhs = self . from_wavelengths [ indices [ 0 ] : indices [ 0 ] + 2 ] rhs = self . from_wavelengths [ indices [ - 1 ] - 1 : indices [ - 1 ] + 1 ] fractions [ 0 ] = ( lhs [ 1 ] - new_wavelengths [ i ] ) / np . ptp ( lhs ) fractions [ - 1 ] = ( new_wavelengths [ _ ] - rhs [ 0 ] ) / np . ptp ( rhs ) fractions = np . clip ( fractions , 0 , 1 ) fractions /= fractions . sum ( ) data . extend ( fractions ) new_px_indices . extend ( [ i ] * N ) old_px_indices . extend ( np . arange ( * indices ) ) return sparse . csc_matrix ( ( data , ( old_px_indices , new_px_indices ) ) , shape = ( self . from_wavelengths . size , new_wavelengths . size ) )
Return a binning matrix for the given redshift based on the original
        wavelengths provided when the class was initiated.