Ejemplo n.º 1
0
def align(raw1, raw2):
    d1 = Align.normalize_by_percentile(raw1)
    d2 = Align.normalize_by_percentile(raw2)

    d1, d2 = pile([d1, d2])
    d1_ = mask_noise(d1)
    d2_ = mask_noise(d2)

    offset, error, _ = skimage.feature.register_translation(d1_, d2_)

    data = pile([raw1, raw2])
    result = Align.apply_offsets(data, [
        offset,
        [0, 0],
    ])
    #     noised = np.array([d1_, d2_])
    return result, offset
Ejemplo n.º 2
0
    def _align_phenotype_channels(data,target,source,riders=[],upsample_factor=2, window=2, remove=False):
        windowed = Align.apply_window(data[[target,source]],window)
        # remove noise?
        offsets = Align.calculate_offsets(windowed,upsample_factor=upsample_factor)
        if not isinstance(riders,list):
            riders = [riders]
        full_offsets = np.zeros((data.shape[0],2))
        full_offsets[[source]+riders] = offsets[1]
        aligned = Align.apply_offsets(data, full_offsets)
        if remove == 'target':
            channel_order = list(range(data.shape[0]))
            channel_order.remove(source)
            channel_order.insert(target+1,source)
            aligned = aligned[channel_order]
            aligned = remove_channels(aligned, target)
        elif remove == 'source':
            aligned = remove_channels(aligned, source)

        return aligned
Ejemplo n.º 3
0
    def _align(data, method='DAPI', upsample_factor=2, window=4):
        """Expects input array of dimensions (CYCLE, CHANNEL, I, J).
        If window is 
        """
        data = np.array(data)
        assert data.ndim == 4, 'Input data must have dimensions CYCLE, CHANNEL, I, J'

        # align between SBS channels for each cycle
        aligned = data.copy()
        align_it = lambda x: Align.align_within_cycle(
            x, window=window, upsample_factor=upsample_factor)
        aligned[:, 1:] = np.array([align_it(x) for x in aligned[:, 1:]])

        if method == 'DAPI':
            # align cycles using the DAPI channel
            aligned = Align.align_between_cycles(
                aligned,
                channel_index=0,
                window=window,
                upsample_factor=upsample_factor)
        elif method == 'SBS_mean':
            # calculate cycle offsets using the average of SBS channels
            target = Align.apply_window(aligned[:, 1:],
                                        window=window).max(axis=1)
            normed = Align.normalize_by_percentile(target)
            offsets = Align.calculate_offsets(normed,
                                              upsample_factor=upsample_factor)
            # apply cycle offsets to each channel
            for channel in range(aligned.shape[1]):
                aligned[:,
                        channel] = Align.apply_offsets(aligned[:, channel],
                                                       offsets)

        return aligned
Ejemplo n.º 4
0
    def _align_SBS(data,
                   method='DAPI',
                   upsample_factor=2,
                   window=4,
                   cutoff=1,
                   align_within_cycle=True):
        """Rigid alignment of sequencing cycles and channels. 

        Expects `data` to be an array with dimensions (CYCLE, CHANNEL, I, J).
        A centered subset of data is used if `window` is greater 
        than one. Subpixel alignment is done if `upsample_factor` is greater than
        one (can be slow).
        """
        data = np.array(data)
        assert data.ndim == 4, 'Input data must have dimensions CYCLE, CHANNEL, I, J'

        # align between SBS channels for each cycle
        aligned = data.copy()
        if align_within_cycle:
            align_it = lambda x: Align.align_within_cycle(
                x, window=window, upsample_factor=upsample_factor)
            if data.shape[1] == 4:
                n = 0
                align_it = lambda x: Align.align_within_cycle(x,
                                                              window=window,
                                                              upsample_factor=
                                                              upsample_factor,
                                                              cutoff=cutoff)
            else:
                n = 1

            aligned[:, n:] = np.array([align_it(x) for x in aligned[:, n:]])

        if method == 'DAPI':
            # align cycles using the DAPI channel
            aligned = Align.align_between_cycles(
                aligned,
                channel_index=0,
                window=window,
                upsample_factor=upsample_factor)
        elif method == 'SBS_mean':
            # calculate cycle offsets using the average of SBS channels
            target = Align.apply_window(aligned[:, 1:],
                                        window=window).max(axis=1)
            normed = Align.normalize_by_percentile(target)
            normed[normed > cutoff] = cutoff
            offsets = Align.calculate_offsets(normed,
                                              upsample_factor=upsample_factor)
            # apply cycle offsets to each channel
            for channel in range(aligned.shape[1]):
                aligned[:,
                        channel] = Align.apply_offsets(aligned[:, channel],
                                                       offsets)

        return aligned
Ejemplo n.º 5
0
    def _merge_SBS(data, upsample_factor=2, window=2, cutoff=1,
        align_within_cycle=True, keep_trailing=False, n=1, c1=False, binning=False):
        """
        Fast-mode SBS: merge and align based on modified align_SBS (method=SBS_mean)
        Slow-mode SBS:
            Remove DAPI channel
            Based on remove_channels: 
                Remove channel or list of channels from array of shape (..., CHANNELS, I, J).
        """
        
        data = np.array(data)
        if keep_trailing:
            valid_channels = min([len(x) for x in data])
            data = np.array([x[-valid_channels:] for x in data])
        

        # for fast-mode SBS, all channels merged into one array with dimensions CHANNEL, I, J 
        if not c1: 
            aligned = np.expand_dims(data, axis=0)
            assert aligned.ndim == 4, 'Input data must have dimensions CYCLE, CHANNEL, I, J'

            # align between SBS channels for each cycle
            if align_within_cycle:
                align_it = lambda x: Align.align_within_cycle(x, window=window, upsample_factor=upsample_factor)
                if aligned.shape[1] == 4:
                    n = 0
                    align_it = lambda x: Align.align_within_cycle(x, window=window, 
                        upsample_factor=upsample_factor)
                # else:
                #     n = 1
                aligned[:, n:] = np.array([align_it(x) for x in aligned[:, n:]])
            
            # calculate cycle offsets using the average of SBS channels
            target = Align.apply_window(aligned[:, :], window=window).max(axis=1)
            normed = Align.normalize_by_percentile(target)
            normed[normed > cutoff] = cutoff
            offsets = Align.calculate_offsets(normed, upsample_factor=upsample_factor)
            # apply cycle offsets to each channel
            for channel in range(aligned.shape[1]):
                aligned[:, channel] = Align.apply_offsets(aligned[:, channel], offsets)

        # for slow-mode SBS, remove CYCLE dimension and DAPI channel -> array with dimensions CHANNEL, I, J

        if c1:
            assert data.ndim == 4, 'Input data must have dimensions CYCLE, CHANNEL, I, J'
            remove_index = 0 # DAPI channel
            aligned = remove_channels(data, remove_index)

        if binning:
            sbs = skimage.measure.block_reduce(aligned, block_size=(1,1,2,2), func=np.max)
        else: 
            sbs = aligned
        
        return sbs[0]
Ejemplo n.º 6
0
    def _align_phenotype_channels(files,target,source,riders=[],upsample_factor=2, window=2, remove=False):
        """
        For fast-mode imaging: merge separate channel tifs into one stack
        Expects files to be a list of strings of filenames
        Merged data will be in the order of (CYCLE, CHANNEL, I, J)
        
        Target = int 
            Channel index to which source channels are aligned to
        Source = int or list of integers
            Channel with similar pattern to target used to calculate offsets for alignment
            If list, calculate offsets for each channel to target separately 
            10/1/20 NOTE: current code does not accomodate for riders if multiple sources listed
        Riders - list of integers
            Channels to be aligned to target using offset calculated from source
        """
        
        data = np.array(files)

        # in the case that data has shape (CYCLE, CHANNEL, I, J):
        if data.ndim == 4:
            data = data[0]

        if not isinstance(source,list):
            windowed = Align.apply_window(data[[target,source]],window)
            # remove noise?
            offsets = Align.calculate_offsets(windowed,upsample_factor=upsample_factor)
            
            if not isinstance(riders,list):
                riders = [riders]
            
            full_offsets = np.zeros((data.shape[0],2))
            full_offsets[[source]+riders] = offsets[1]
            aligned = Align.apply_offsets(data, full_offsets)
        else:
            full_offsets = np.zeros((data.shape[0],2))
            for src in source:
                windowed = Align.apply_window(data[[target,src]],window)
                offsets = Align.calculate_offsets(windowed,upsample_factor=upsample_factor)
                full_offsets[[src]] = offsets[1]
            aligned = Align.apply_offsets(data, full_offsets)

        if remove == 'target':
            channel_order = list(range(data.shape[0]))
            channel_order.remove(source)
            channel_order.insert(target+1,source)
            aligned = aligned[channel_order]
            aligned = remove_channels(aligned, target)
        elif remove == 'source':
            aligned = remove_channels(aligned, source)

        return aligned
Ejemplo n.º 7
0
    def _align_SBS(data, method='DAPI', upsample_factor=2, window=2, cutoff=1, q_norm=70,
        align_within_cycle=True, cycle_files=None, keep_trailing=False, n=1, remove_for_cycle_alignment=None, rescale_channels=None, rescale_factors=None):
        """Rigid alignment of sequencing cycles and channels. 

        Expects `data` to be an array with dimensions (CYCLE, CHANNEL, I, J). 'n' 
        determines the first SBS channel in 'data'.
        A centered subset of data is used if `window` is greater 
        than one. Subpixel alignment is done if `upsample_factor` is greater than
        one (can be slow).
        
        If channel rebalancing is needed, insert list of channel indices (e.g.,Cy3=1, A594=2, etc)
        for "rescale_channels", and a list of the factors by which you want to multiply the channels' arrays for "rescale_factors".
        Channel rebalancing function is currently configured for 12 cycle experiments.
        """
        #description = ops.filenames.parse_filename(file,custom_patterns=file_pattern)

        if cycle_files is not None:
            arr = []
            # snakemake passes de-nested list of numpy arrays
            current = 0
            for cycle in cycle_files:
                #print(cycle)
                if cycle == 1:
                    arr.append(np.array(data[cycle-1]))
                    #print(np.shape(arr))
                    #current += cycle
                if cycle==len(cycle_files):
                    arr.append(np.array(data[cycle-1]))
                    data = np.array(arr)
                else:
                    arr.append(np.array(data[cycle-1]))
                    #print(np.shape(arr))
                    current += cycle

            #data = np.array(arr)

        else:
            data = np.array(data)
            
        if rescale_channels is not None:
            for num in range(0,12):
                for i in range(0,len(rescale_channels)):
                    data[num][rescale_channels[i]]=data[num][rescale_channels[i]]*rescale_factors[i]

        if keep_trailing != False | data.ndim==1:
            channels = [len(x) for x in data]
            stacked = np.array([x[-min(channels):] for x in data])
        else:
            stacked = data

        if keep_trailing == 'propagate_extras':
            extras = np.array(channels)-min(channels)
            arr = []
            for cycle,extra in enumerate(extras):
                if extra != 0:
                    arr.extend([data[cycle][extra_ch] for extra_ch in range(extra)])
            propagate = np.array(arr)
            stacked = np.concatenate((np.array([propagate]*stacked.shape[0]),stacked),axis=1)
        else:
            extras = [0,]*stacked.shape[0]

        # if data.ndim==1:
        #     # data stacked with different cycle numbers?
        #     # assume extra channels exist are on the first cycle, first channels
        #     # does not return extra channels
        #     channels = [len(x) for x in data]
        #     extra = max(channels) - min(channels)
        #     #stack channels in common
        #     stacked = np.array([data[0][extra:]]+[data[cycle] for cycle in range(1,data.shape[0])])
        #     #copy extra channels across other cycles
        #     stacked = np.concatenate((np.array([data[0][:extra]]*stacked.shape[0]),stacked),axis=1)
        # else:
        #     extra = 0
        #     stacked = data
        print(stacked.ndim)
        assert stacked.ndim == 4, 'Input data must have dimensions CYCLE, CHANNEL, I, J'

        # align between SBS channels for each cycle
        aligned = stacked.copy()
        if align_within_cycle:
            align_it = lambda x: Align.align_within_cycle(x, window=window, upsample_factor=upsample_factor)
            
            aligned[:, n:] = np.array([align_it(x) for x in aligned[:, n:]])
            

        if method == 'DAPI':
            # align cycles using the DAPI channel
            aligned = Align.align_between_cycles(aligned, channel_index=0, 
                                window=window, upsample_factor=upsample_factor)
        elif method == 'SBS_mean':
            # calculate cycle offsets using the average of SBS channels
            sbs_channels = list(range(n,aligned.shape[1]))
            if remove_for_cycle_alignment != None:
                sbs_channels.remove(remove_for_cycle_alignment)

            target = Align.apply_window(aligned[:, sbs_channels], window=window).max(axis=1)
            normed = Align.normalize_by_percentile(target, q_norm=q_norm)
            normed[normed > cutoff] = cutoff
            offsets = Align.calculate_offsets(normed, upsample_factor=upsample_factor)
            # apply cycle offsets to each channel
            for channel in range(aligned.shape[1]):
                if channel >= sum(extras):
                    aligned[:, channel] = Align.apply_offsets(aligned[:, channel], offsets)
                else:
                    # don't apply offsets to extra channel in the cycle it was acquired
                    offset_cycles = list(range(aligned.shape[0])).remove(list(np.cumsum(extras)>channel).index(True))
                    aligned[offset_cycles, channel] = Align.apply_offsets(aligned[offset_cycles, channel], offsets)

        return aligned