Applies calibration solution to data array. Assumes structure of (nint, nbl, nch, npol).

def apply(self, data):
        """ Applies calibration solution to data array. Assumes structure of (nint, nbl, nch, npol).
        """

        # find best skyfreq for each channel
        skyfreqs = n.unique(self.skyfreq[self.select])    # one per spw
        nch_tot = len(self.freqs)
        chan_bandnum = [range(nch_tot*i/len(skyfreqs), nch_tot*(i+1)/len(skyfreqs)) for i in range(len(skyfreqs))]  # divide chans by number of spw in solution
        self.logger.info('Solutions for %d spw: (%s)' % (len(skyfreqs), skyfreqs))

        for j in range(len(skyfreqs)):
            skyfreq = skyfreqs[j]
            chans = chan_bandnum[j]
            self.logger.info('Applying gain solution for chans from %d-%d' % (chans[0], chans[-1]))

            # define freq structure to apply delay solution
            nch = len(chans)
            chanref = nch/2    # reference channel at center
            relfreq = self.chansize*(n.arange(nch) - chanref)   # relative frequency

            for i in range(len(self.blarr)):
                ant1, ant2 = self.blarr[i]  # ant numbers (1-based)
                for pol in self.polind:
                    # apply gain correction
                    invg1g2 = self.calcgain(ant1, ant2, skyfreq, pol)
                    data[:,i,chans,pol-self.polind[0]] = data[:,i,chans,pol-self.polind[0]] * invg1g2    # hack: lousy data pol indexing

                    # apply delay correction
                    d1d2 = self.calcdelay(ant1, ant2, skyfreq, pol)
                    delayrot = 2*n.pi*(d1d2[0] * 1e-9) * relfreq      # phase to rotate across band
                    data[:,i,chans,pol-self.polind[0]] = data[:,i,chans,pol-self.polind[0]] * n.exp(-1j*delayrot[None, None, :])