Esempio n. 1
0
def calc_avg_amps(refs_all, data_shape, nchans=4, altcol=True):
    """Calculate amplifier averages
    
    Save the average reference value for each amplifier in each frame.
    Assume by default that alternating columns are offset from each other,
    so we save two arrays: self.refs_amps_avg1 and self.refs_amps_avg2. 
    Each array has a size of (namp, ngroup).

    Parameters
    ----------
    refs_all : ndarray
        The top and/or bottom references pixels order 
        in a shape (nz, nref_rows, nx)
    data_shape : tuple
        Shape of the data array: (nz, ny, nx).
    nchans : int
        Number of amplifier output channels.
    altcol : bool
        Calculate separate reference values for even/odd columns? 
        Default=True.
    """

    nz, ny, nx = data_shape
    chsize = int(nx / nchans)

    if altcol:
        refs_amps_avg1 = []
        refs_amps_avg2 = []
        for ch in range(nchans):
            # Channel indices
            ich1 = ch * chsize
            ich2 = ich1 + chsize

            # Slice out alternating columns
            refs_ch1 = refs_all[:, :, ich1:ich2 - 1:2].reshape((nz, -1))
            refs_ch2 = refs_all[:, :, ich1 + 1:ich2:2].reshape((nz, -1))

            # Take the resistant mean
            chavg1 = robust.mean(refs_ch1, axis=1)
            chavg2 = robust.mean(refs_ch2, axis=1)

            refs_amps_avg1.append(chavg1)
            refs_amps_avg2.append(chavg2)

        return (np.array(refs_amps_avg1), np.array(refs_amps_avg2))
    else:
        refs_amps_avg = []
        for ch in range(nchans):
            # Channel indices
            ich1 = ch * chsize
            ich2 = ich1 + chsize

            # Slice out alternating columns
            refs_ch = refs_all[:, :, ich1:ich2].reshape((nz, -1))

            # Take the resistant mean and reshape for broadcasting
            chavg = robust.mean(refs_ch, axis=1).reshape(-1, 1, 1)
            refs_amps_avg.append(chavg)

        return np.array(refs_amps_avg)
Esempio n. 2
0
def calc_avg_amps(refs_all, data_shape, nchans=4, altcol=True):
    """
    Save the average reference value for each amplifier in each frame.
    This assumes that alternating columns are offset from each other,
    so we save two arrays: self.refs_amps_avg1 and self.refs_amps_avg2. Each array
    has a size of (namp, ngroup).

    top_ref   (bool) : Include top reference rows when correcting channel offsets.
    bot_ref   (bool) : Include bottom reference rows when correcting channel offsets.
    """

    nz, ny, nx = data_shape
    chsize = int(nx / nchans)

    if altcol:
        refs_amps_avg1 = []
        refs_amps_avg2 = []
        for ch in range(nchans):
            # Channel indices
            ich1 = ch * chsize
            ich2 = ich1 + chsize

            # Slice out alternating columns
            refs_ch1 = refs_all[:, :, ich1:ich2 - 1:2].reshape((nz, -1))
            refs_ch2 = refs_all[:, :, ich1 + 1:ich2:2].reshape((nz, -1))

            # Take the resistant mean
            chavg1 = robust.mean(refs_ch1, axis=1)
            chavg2 = robust.mean(refs_ch2, axis=1)

            refs_amps_avg1.append(chavg1)
            refs_amps_avg2.append(chavg2)

        return (np.array(refs_amps_avg1), np.array(refs_amps_avg2))
    else:
        refs_amps_avg = []
        for ch in range(nchans):
            # Channel indices
            ich1 = ch * chsize
            ich2 = ich1 + chsize

            # Slice out alternating columns
            refs_ch = refs_all[:, :, ich1:ich2].reshape((nz, -1))

            # Take the resistant mean and reshape for broadcasting
            chavg = robust.mean(refs_ch, axis=1).reshape(-1, 1, 1)
            refs_amps_avg.append(chavg)

        return np.array(refs_amps_avg)
Esempio n. 3
0
    def correct_amp_refs(self, supermean=False):
        """Correct amplifier offsets
        
        Use values in ``self.refs_amps_avg`` to correct amplifier offsets.

        Parameters
        ----------
        supermean : bool
            Add back the overall mean of the reference pixels.
        """

        # Check to make sure refs_amps_avg is valid
        if (self.refs_amps_avg is None):
            _log.warning(
                'self.refs_amps_avg is set to None. No offsets applied.')
            return
            #raise ValueError('self.refs_amps_avg is set to None')

        # Supermean
        # the average of the average is the DC level of the output channel
        smean = robust.mean(refs_all) if supermean else 0.0

        nchans = self.detector.nout
        chsize = self.detector.chsize
        nz, ny, nx = self.data.shape
        for ch in range(nchans):
            # Channel indices
            ich1 = int(ch * chsize)
            ich2 = int(ich1 + chsize)

            # In-place subtraction of channel averages
            if self.altcol:
                for i in range(nz):
                    self.data[i, :,
                              ich1:ich2 - 1:2] -= self.refs_amps_avg[0][ch, i]
                    self.data[i, :,
                              ich1 + 1:ich2:2] -= self.refs_amps_avg[1][ch, i]
            else:
                for i in range(nz):
                    self.data[i, :, ich1:ich2] -= self.refs_amps_avg[ch, i]

        # Add back supermean
        if supermean: self.data += smean
Esempio n. 4
0
    def correct_amp_refs(self, supermean=False):
        """
        Use values from calc_avg_amps to correct amplifier offsets.

        supermean (bool) : Add back the overall mean of the reference pixels.
        """

        # Check to make sure refs_amps_avg is valid
        if (self.refs_amps_avg is None):
            raise ValueError('self.refs_amps_avg is set to None')

        # Supermean
        # the average of the average is the DC level of the output channel
        smean = robust.mean(refs_all) if supermean else 0.0

        nchans = self.detector.nout
        chsize = self.detector.chsize
        nz, ny, nx = self.data.shape
        for ch in range(nchans):
            # Channel indices
            ich1 = ch * chsize
            ich2 = ich1 + chsize

            # In-place subtraction of channel averages
            if self.altcol:
                for i in range(nz):
                    self.data[i, :,
                              ich1:ich2 - 1:2] -= self.refs_amps_avg[0][ch, i]
                    self.data[i, :,
                              ich1 + 1:ich2:2] -= self.refs_amps_avg[1][ch, i]
            else:
                for i in range(nz):
                    self.data[i, :, ich1:ich2] -= self.refs_amps_avg[ch, i]

        # Add back supermean
        if supermean: self.data += smean
Esempio n. 5
0
def reffix_amps(cube,
                nchans=4,
                in_place=True,
                altcol=True,
                supermean=False,
                top_ref=True,
                bot_ref=True,
                ntop=4,
                nbot=4,
                **kwargs):
    """Correct amplifier offsets
    
    Matches all amplifier outputs of the detector to a common level.

    This routine subtracts the average of the top and bottom reference rows
    for each amplifier and frame individually.

    By default, reference pixel corrections are performed in place since it's
    faster and consumes less memory.

    Parameters
    ----------
    cube : ndarray
        Input datacube. Can be two or three dimensions (nz,ny,nx).
    nchans : int
        Number of output amplifier channels in the detector. Default=4.
    altcol : bool
        Calculate separate reference values for even/odd columns.
    supermean : bool
        Add back the overall mean of the reference pixels.
    in_place : bool
        Perform calculations in place. Input array is overwritten.
    top_ref : bool
        Include top reference rows when correcting channel offsets.
    bot_ref : bool
        Include bottom reference rows when correcting channel offsets.
    ntop : int
        Specify the number of top reference rows.
    nbot : int
        Specify the number of bottom reference rows.
    """

    if not in_place:
        cube = np.copy(cube)

    # Check the number of dimensions are valid.
    ndim = len(cube.shape)
    if ndim == 2:
        ny, nx = cube.shape
        nz = 1
        cube = cube.reshape((nz, ny, nx))
    elif ndim == 3:
        nz, ny, nx = cube.shape
    else:
        raise ValueError('Input data can only have 2 or 3 dimensions. \
                          Found {} dimensions.'.format(ndim))

    chsize = int(nx / nchans)

    # Number of reference rows to use
    # Set nt or nb equal to 0 if we don't want to use either
    nt = ntop if top_ref else 0
    nb = nbot if bot_ref else 0

    if (nt + nb) == 0:
        print("No reference pixels available for use. Returning...")
        return

    # Slice out reference pixels
    refs_bot = cube[:, :nb, :]
    refs_top = cube[:, -nt:, :]
    if nt == 0:
        refs_all = refs_bot
    elif nb == 0:
        refs_all = refs_top
    else:
        refs_all = np.hstack((refs_bot, refs_top))

    assert refs_all.shape[1] == (nb + nt)

    # Supermean
    # the average of the average is the DC level of the output channel
    smean = robust.mean(refs_all) if supermean else 0.0

    # Calculate avg reference values for each frame and channel
    refs_amps_avg = calc_avg_amps(refs_all,
                                  cube.shape,
                                  nchans=nchans,
                                  altcol=altcol)

    for ch in range(nchans):
        # Channel indices
        ich1 = ch * chsize
        ich2 = ich1 + chsize

        # In-place subtraction of channel medians
        if altcol:
            for i in range(nz):
                cube[i, :, ich1:ich2 - 1:2] -= refs_amps_avg[0][ch, i]
                cube[i, :, ich1 + 1:ich2:2] -= refs_amps_avg[1][ch, i]
        else:
            for i in range(nz):
                cube[i, :, ich1:ich2] -= refs_amps_avg[ch, i]

    # Add back supermean
    if supermean: cube += smean

    cube = cube.squeeze()
    return cube