def alignZeroShiftImages(imagedata1,imagedata2,bin): """Align start-angle images for tilt series where data is collect in two halves""" no_wx=True bin = int(bin) if not no_wx: # Tilt correlator needs wx which is not available on the cluster # This method is consistent with the rest of leginonxcorr and will # revert correction channels is needed even though it is likely # unnecessary fakenode = node.Node('fake',imagedata1['session']) correlator = tiltcorrelator.Correlator(fakenode, 0, bin,lpf=1.5) for imagedata in (imagedata1,imagedata2): correlator.correlate(imagedata, tiltcorrection=True, channel=None) peak = correlator.getShift(False) fakenode.die() else: # phase correlation array1 = imagedata1['image'] array2 = imagedata2['image'] if bin != 1: array1 = imagefun.bin(array1, bin) array2 = imagefun.bin(array2, bin) shift = simpleCorrelation(array1,array2) peak = {'x':-shift[1]*bin,'y':shift[0]*bin} # x (row) shift on image coordinate is of opposite sign return {'shiftx':-peak['x'], 'shifty':peak['y']}
def processImage(self, imgdata, filtarray): #Ignore array filter array = imgdata['image'] imgmax = self.params['max'] imgmin = self.params['min'] outfile = os.path.join(self.params['rundir'], imgdata['filename']) if self.params['fft'] is True: outfile += ".fft" outfile += ".jpg" if imgmin > imgmax: imgmax = array.max() imgmin = array.min() shape = array.shape maxdim = max(shape) if self.params['fft'] is True: ## fft's are binned by 2 array = imagefun.bin(array, 2) array = imagefun.power(array) maxdim /= 2 bin = int(math.ceil(float(maxdim / self.params['imgsize']))) array = imagefun.bin(array, bin) jpg.write(array, outfile, min=imgmin, max=imgmax, quality=self.params['quality'], stdval=self.params['stdval'])
def alignZeroShiftImages(imagedata1, imagedata2, bin): """Align start-angle images for tilt series where data is collect in two halves""" no_wx = True bin = int(bin) if not no_wx: # Tilt correlator needs wx which is not available on the cluster # This method is consistent with the rest of leginonxcorr and will # revert correction channels is needed even though it is likely # unnecessary fakenode = node.Node('fake', imagedata1['session']) correlator = tiltcorrelator.Correlator(fakenode, 0, bin, lpf=1.5) for imagedata in (imagedata1, imagedata2): correlator.correlate(imagedata, tiltcorrection=True, channel=None) peak = correlator.getShift(False) fakenode.die() else: # phase correlation array1 = imagedata1['image'] array2 = imagedata2['image'] if bin != 1: array1 = imagefun.bin(array1, bin) array2 = imagefun.bin(array2, bin) shift = simpleCorrelation(array1, array2) peak = {'x': -shift[1] * bin, 'y': shift[0] * bin} # x (row) shift on image coordinate is of opposite sign return {'shiftx': -peak['x'], 'shifty': peak['y']}
def writeMrcStack(path, stackname, mrc_files, binning=1): apDisplay.printMsg("Writing MRC stack file... ") stackname = os.path.join(path, stackname) im = mrc.read(mrc_files[0]) image = imagefun.bin(im, binning) mrc.write(image,stackname) del mrc_files[0] for mrcfile in mrc_files: im = mrc.read(mrcfile) image = imagefun.bin(im, binning) mrc.append(image, stackname)
def writeMrcStack(path, stackname, mrc_files, binning=1): apDisplay.printMsg("Writing MRC stack file... ") stackname = os.path.join(path, stackname) im = mrc.read(mrc_files[0]) image = imagefun.bin(im, binning) mrc.write(image, stackname) del mrc_files[0] for mrcfile in mrc_files: im = mrc.read(mrcfile) image = imagefun.bin(im, binning) mrc.append(image, stackname)
def testMRCImages(): file1,file2 = sys.argv[1:3] print 'reading MRCs' image1 = mrc.read(file1) image2 = mrc.read(file2) image1 = imagefun.bin(image1, 4) image2 = imagefun.bin(image2, 4) print 'register...' #result = register(image1, image2, range() #result = register2(image1, image2, range(86,95)) result = register2(image1, image2, range(90,91))
def makeStack(self, tiltseries, mrc_files): stackname = self.getFilename(tiltseries) + '.st' stackname = os.path.join(self.settings['path'], stackname) im = mrc.read(mrc_files[0]) image = imagefun.bin(im, int(self.settings['binning'])) mrc.write(image, stackname) #shutil.copy(mrc_files[0], stackname) del mrc_files[0] for mrcfile in mrc_files: im = mrc.read(mrcfile) image = imagefun.bin(im, int(self.settings['binning'])) mrc.append(image, stackname)
def makeStack(self, tiltseries, mrc_files): stackname = self.getFilename(tiltseries) + '.st' stackname = os.path.join(self.settings['path'], stackname) im = mrc.read(mrc_files[0]) image = imagefun.bin(im, int(self.settings['binning'])) mrc.write(image,stackname) #shutil.copy(mrc_files[0], stackname) del mrc_files[0] for mrcfile in mrc_files: im = mrc.read(mrcfile) image = imagefun.bin(im, int(self.settings['binning'])) mrc.append(image, stackname)
def binAndAddCTFlabel(self, image, ht, rpixelsize, binning=1, defocus=None): pow = imagefun.power(image) binned = imagefun.bin(pow, binning) # No ctf estimation until it works better so that this node does not # depend on coma beam-tilt calibration s = None ctfdata = None ''' try: ctfdata = fftfun.fitFirstCTFNode(pow,rpixelsize['x'], defocus, ht) except Exception, e: self.logger.error("ctf fitting failed: %s" % e) ctfdata = None if ctfdata: self.logger.info('z0 %.3f um, zast %.3f um (%.0f ), angle= %.1f deg' % (ctfdata[0]*1e6,ctfdata[1]*1e6,ctfdata[2]*100, ctfdata[3]*180.0/math.pi)) s = '%d' % int(ctfdata[0]*1e9) #elif self.ace2exe: elif False: ctfdata = self.estimateCTF(imagedata) z0 = (ctfdata['defocus1'] + ctfdata['defocus2']) / 2 s = '%d' % (int(z0*1e9),) ''' if s: t = numpil.textArray(s) t = ndimage.zoom(t, (min(binned.shape)-40.0)*0.08/(t.shape)[0]) minvalue = arraystats.min(binned) maxvalue = arraystats.max(binned) t = minvalue + t * (maxvalue-minvalue) imagefun.pasteInto(t, binned, (20,20)) return binned, ctfdata
def overlayshadow(self, shadowimg, parentimg, alpha=0.5): binning = parentimg.shape[0] / shadowimg.shape[0] if binning != 1: parentimg = imagefun.bin(parentimg, binning) overlay = parentimg + shadowimg * alpha * ( parentimg.max() - parentimg.min()) / max(shadowimg.max(), 1) return overlay, parentimg
def addCTFlabel(self, image, ht, rpixelsize, binning=1, defocus=None): pow = imagefun.power(image) binned = imagefun.bin(pow, binning) s = None try: ctfdata = fftfun.fitFirstCTFNode(pow,rpixelsize['x'], defocus, ht) except Exception, e: self.logger.error("ctf fitting failed: %s" % e) ctfdata = None
def correlate(self, imagedata, tiltcorrection=True, channel=None, wiener=False, taper=0, corrtype="phase"): image = self.getCenterSquareImage(imagedata["image"]) if len(image.shape) != 2 or image.shape[0] != image.shape[1]: raise ValueError if self.correlation_binning != 1: image = imagefun.bin(image, int(self.correlation_binning)) # create new imagedata according to the additional bin camdata = leginon.leginondata.CameraEMData(initializer=imagedata["camera"]) camdata["binning"] = { "x": camdata["binning"]["x"] * self.correlation_binning, "y": camdata["binning"]["y"] * self.correlation_binning, } newimagedata = leginon.leginondata.AcquisitionImageData(initializer=imagedata) newimagedata["camera"] = camdata # numpy 2.0 does not allow inplace assignment involving different kinds # convert to float first image = image.astype(numpy.float) mean = image.mean() image -= mean if self.hanning is None or image.shape[0] != self.hanning.shape[0]: self.hanning = hanning(image.shape[0]) image *= self.hanning newimagedata["image"] = image if tiltcorrection: # stage tilt corrector stretchs and updates the image in imagedata according to its stage matrix calibration self.tiltcorrector.undo_tilt(newimagedata) image = newimagedata["image"] if taper > 0: taperboundary = int((image.shape)[0] * taper * 0.01) imagefun.taper(image, taperboundary) self.correlation.insertImage(image) self.channel = channel if corrtype == "phase": try: pc = self.correlation.phaseCorrelate(wiener=wiener) except correlator.MissingImageError: return else: try: pc = self.correlation.crossCorrelate() except correlator.MissingImageError: return peak = self.peakfinder.subpixelPeak(newimage=pc) rows, columns = self.peak2shift(peak, pc.shape) self.raw_shift = {"x": columns, "y": rows} self.shift["x"] -= self.raw_shift["x"] * self.correlation_binning self.shift["y"] += self.raw_shift["y"] * self.correlation_binning pc = self.swapQuadrants(pc) return pc
def insertTableau(self, imagedata, angle, rad): image = imagedata['image'] binning = self.settings['tableau binning'] if self.settings['tableau type'] != 'beam tilt series-image': binned, ctfdata = self.binAndAddCTFlabel(image, self.ht, self.cs, self.rpixelsize, binning, self.defocus) self.ctfdata.append(ctfdata) else: binned = imagefun.bin(image, binning) self.tableauimages.append(binned) self.tableauangles.append(angle) self.tableaurads.append(rad)
def findCaustic(input, smallrange, bigrange, mask, binning=None): ''' Initial search for caustic figure in binned image, then in original. ''' if binning is not None: print '**First binned by %s:' % (binning, ) ## first run it with initial binning bin_input = imagefun.bin(input, binning) smallmin = int(numpy.floor(smallrange[0] / float(binning))) smallmax = int(numpy.ceil(smallrange[1] / float(binning))) + 1 bin_radii_small = numpy.arange(smallmin, smallmax) bigmin = int(numpy.floor(bigrange[0] / float(binning))) bigmax = int(numpy.ceil(bigrange[1] / float(binning))) + 1 bin_radii_big = numpy.arange(bigmin, bigmax) small_circle, big_circle = __findCaustic(bin_input, bin_radii_small, bin_radii_big, mask) # set up ranges for full size image halfbin = binning / 2.0 ### XXX need to make sure new radii do not include more than original rsmall = small_circle['radius'] smallmin = int(numpy.floor(rsmall * binning - binning / 1.0)) smallmax = int(numpy.ceil(rsmall * binning + binning / 1.0)) smallrange = smallmin, smallmax rbig = big_circle['radius'] bigmin = int(numpy.floor(rbig * binning - binning / 1.0)) bigmax = int(numpy.ceil(rbig * binning + binning / 1.0)) bigrange = bigmin, bigmax small_row0 = binning * (small_circle['center'][0] - 1) small_row1 = binning * (small_circle['center'][0] + 1) small_col0 = binning * (small_circle['center'][1] - 1) small_col1 = binning * (small_circle['center'][1] + 1) small_limit = small_row0, small_row1, small_col0, small_col1 big_row0 = binning * (big_circle['center'][0] - 1) big_row1 = binning * (big_circle['center'][0] + 1) big_col0 = binning * (big_circle['center'][1] - 1) big_col1 = binning * (big_circle['center'][1] + 1) big_limit = big_row0, big_row1, big_col0, big_col1 print '**Full size:' radii_small = numpy.arange(smallrange[0], smallrange[1] + 1, dtype=numpy.int) radii_big = numpy.arange(bigrange[0], bigrange[1] + 1, dtype=numpy.int) small_circle, big_circle = __findCaustic(input, radii_small, radii_big, mask, small_limit, big_limit) return small_circle, big_circle
def correlate(self, imagedata, tiltcorrection=True, channel=None,wiener=False,taper=0,corrtype='phase'): image = imagedata['image'] if len(image.shape) != 2 or image.shape[0] != image.shape[1]: raise ValueError if self.correlation_binning != 1: image = imagefun.bin(image, int(self.correlation_binning)) # create new imagedata according to the additional bin camdata = leginon.leginondata.CameraEMData(initializer =imagedata['camera']) camdata['binning'] = {'x':camdata['binning']['x']*self.correlation_binning, 'y':camdata['binning']['y']*self.correlation_binning} newimagedata = leginon.leginondata.AcquisitionImageData(initializer=imagedata) newimagedata['camera']=camdata mean = image.mean() image -= mean if self.hanning is None or image.shape[0] != self.hanning.shape[0]: self.hanning = hanning(image.shape[0]) image *= self.hanning newimagedata['image'] = image if tiltcorrection: # stage tilt corrector stretchs and updates the image in imagedata according to its stage matrix calibration self.tiltcorrector.undo_tilt(newimagedata) image = newimagedata['image'] if taper > 0: taperboundary = int((image.shape)[0]*taper*0.01) imagefun.taper(image,taperboundary) self.correlation.insertImage(image) self.channel = channel if corrtype == 'phase': try: pc = self.correlation.phaseCorrelate(wiener=wiener) except correlator.MissingImageError: return else: try: pc = self.correlation.crossCorrelate() except correlator.MissingImageError: return peak = self.peakfinder.subpixelPeak(newimage=pc) rows, columns = self.peak2shift(peak, pc.shape) self.raw_shift = {'x': columns, 'y': rows} self.shift['x'] -= self.raw_shift['x']*self.correlation_binning self.shift['y'] += self.raw_shift['y']*self.correlation_binning pc = self.swapQuadrants(pc) return pc
def processImage(self, imgdata, filtarray): #Ignore array filter array = imgdata['image'] imgmax = self.params['max'] imgmin = self.params['min'] outfile = os.path.join(self.params['rundir'], imgdata['filename']) if self.params['fft'] is True: outfile+=".fft" outfile+=".jpg" if imgmin > imgmax: imgmax = array.max() imgmin = array.min() shape = array.shape maxdim = max(shape) if self.params['fft'] is True: ## fft's are binned by 2 array = imagefun.bin(array,2) array = imagefun.power(array) maxdim/=2 bin = int(math.ceil(float(maxdim/self.params['imgsize']))) array = imagefun.bin(array,bin) jpg.write(array, outfile, min=imgmin, max=imgmax, quality=self.params['quality'], stdval=self.params['stdval'])
def insertTableau(self, imagedata, angle, rad): image = imagedata['image'] binning = self.settings['tableau binning'] if self.settings['tableau type'] != 'beam tilt series-image': self.ht = imagedata['scope']['high tension'] if not self.rpixelsize: self.rpixelsize = self.btcalclient.getImageReciprocalPixelSize(imagedata) binned, ctfdata = self.binAndAddCTFlabel(image, self.ht, self.rpixelsize, binning, self.defocus) self.ctfdata.append(ctfdata) else: binned = imagefun.bin(image, binning) self.tableauimages.append(binned) self.tableauangles.append(angle) self.tableaurads.append(rad)
def findCaustic(input, smallrange, bigrange, mask, binning=None): ''' Initial search for caustic figure in binned image, then in original. ''' if binning is not None: print '**First binned by %s:' % (binning,) ## first run it with initial binning bin_input = imagefun.bin(input, binning) smallmin = int(numpy.floor(smallrange[0] / float(binning))) smallmax = int(numpy.ceil(smallrange[1] / float(binning)))+1 bin_radii_small = numpy.arange(smallmin, smallmax) bigmin = int(numpy.floor(bigrange[0] / float(binning))) bigmax = int(numpy.ceil(bigrange[1] / float(binning)))+1 bin_radii_big = numpy.arange(bigmin, bigmax) small_circle, big_circle = __findCaustic(bin_input, bin_radii_small, bin_radii_big, mask) # set up ranges for full size image halfbin = binning / 2.0 ### XXX need to make sure new radii do not include more than original rsmall = small_circle['radius'] smallmin = int(numpy.floor(rsmall * binning - binning/1.0)) smallmax = int(numpy.ceil(rsmall * binning + binning/1.0)) smallrange = smallmin, smallmax rbig = big_circle['radius'] bigmin = int(numpy.floor(rbig * binning - binning/1.0)) bigmax = int(numpy.ceil(rbig * binning + binning/1.0)) bigrange = bigmin, bigmax small_row0 = binning * (small_circle['center'][0] - 1) small_row1 = binning * (small_circle['center'][0] + 1) small_col0 = binning * (small_circle['center'][1] - 1) small_col1 = binning * (small_circle['center'][1] + 1) small_limit = small_row0, small_row1, small_col0, small_col1 big_row0 = binning * (big_circle['center'][0] - 1) big_row1 = binning * (big_circle['center'][0] + 1) big_col0 = binning * (big_circle['center'][1] - 1) big_col1 = binning * (big_circle['center'][1] + 1) big_limit = big_row0, big_row1, big_col0, big_col1 print '**Full size:' radii_small = numpy.arange(smallrange[0], smallrange[1]+1, dtype=numpy.int) radii_big = numpy.arange(bigrange[0], bigrange[1]+1, dtype=numpy.int) small_circle, big_circle = __findCaustic(input, radii_small, radii_big, mask, small_limit, big_limit) return small_circle, big_circle
def insertTableau(self, imagedata, angle, rad): image = imagedata['image'] binning = self.settings['tableau binning'] if self.settings['tableau type'] != 'beam tilt series-image': self.ht = imagedata['scope']['high tension'] if not self.rpixelsize: self.rpixelsize = self.btcalclient.getImageReciprocalPixelSize( imagedata) binned, ctfdata = self.binAndAddCTFlabel(image, self.ht, self.rpixelsize, binning, self.defocus) self.ctfdata.append(ctfdata) else: binned = imagefun.bin(image, binning) self.tableauimages.append(binned) self.tableauangles.append(angle) self.tableaurads.append(rad)
def displayCurrent(self): imarray = numpy.zeros((2, 2)) while imarray.max() == 0: currentname = self.files[self.currentindex] self.logger.info('Displaying %s' % (currentname)) dir = self.maskdir fullname = os.path.join(dir, currentname) imarray = self.readPNG(fullname) if imarray.max() == 0: if self.forward: if self.currentindex == len(self.files) - 1: self.logger.info('End reached.') return else: self.currentindex += 1 else: if self.currentindex == 0: self.logger.info('Beginning reached.') return else: self.currentindex -= 1 if currentname.find('_mask') > -1: alpha = 0.5 imgdata = self.images[self.currentindex] parentimg = imgdata['image'] maskshape = imarray.shape targets = apMask.getRegionsAsTargets(self.maskrundata, maskshape, imgdata) if targets is None or len(targets) == 0: self.logger.warning('No Mask Regions in this Image') keep = apDatabase.getImgAssessmentStatus(imgdata) if keep == False: self.logger.warning('Rejected Image, Mask Irelavent') self.alltargets = targets[:] self.setTargets(targets, 'Regions') binning = parentimg.shape[0] / imarray.shape[0] parentimg = imagefun.bin(parentimg, binning) overlay = apMask.overlayMask(parentimg, imarray) self.setImage(overlay, 'Mask') imarray = parentimg self.setImage(imarray, 'Image')
def displayCurrent(self): imarray = numpy.zeros((2,2)) while imarray.max() == 0: currentname = self.files[self.currentindex] self.logger.info('Displaying %s' % (currentname)) dir = self.maskdir fullname = os.path.join(dir, currentname) imarray = self.readPNG(fullname) if imarray.max() ==0: if self.forward: if self.currentindex == len(self.files)-1: self.logger.info('End reached.') return else: self.currentindex += 1 else: if self.currentindex == 0: self.logger.info('Beginning reached.') return else: self.currentindex -= 1 if currentname.find('_mask') > -1: alpha = 0.5 imgdata = self.images[self.currentindex] parentimg = imgdata['image'] maskshape = imarray.shape targets = apMask.getRegionsAsTargets(self.maskrundata,maskshape,imgdata) if targets is None or len(targets)==0: self.logger.warning('No Mask Regions in this Image') keep = apDatabase.getImgAssessmentStatus(imgdata) if keep == False: self.logger.warning('Rejected Image, Mask Irelavent') self.alltargets = targets[:] self.setTargets(targets, 'Regions') binning = parentimg.shape[0]/imarray.shape[0] parentimg=imagefun.bin(parentimg,binning) overlay = apMask.overlayMask(parentimg,imarray) self.setImage(overlay, 'Mask') imarray=parentimg self.setImage(imarray, 'Image')
def overlayMask(image,mask): if mask is None: return image imageshape=image.shape maskshape=mask.shape alpha = 0.25 if maskshape != imageshape: binning = float(maskshape[0])/imageshape[0] if binning > 1: maskbinned = imagefun.bin(mask,binning) else: maskbinned = nd.zoom(mask,1/binning) else: maskbinned = mask if mask.max() !=0: overlay=image+maskbinned*alpha*(image.max()-image.min())/mask.max() else: overlay=image return overlay
def binAndAddCTFlabel(self, image, ht, cs, rpixelsize, binning=1, defocus=None): pow = imagefun.power(image) binned = imagefun.bin(pow, binning) # No ctf estimation until it works better so that this node does not # depend on coma beam-tilt calibration s = None ctfdata = None ''' try: ctfdata = fftfun.fitFirstCTFNode(pow,rpixelsize['x'], defocus, ht, cs) except Exception, e: self.logger.error("ctf fitting failed: %s" % e) ctfdata = None if ctfdata: self.logger.info('z0 %.3f um, zast %.3f um (%.0f ), angle= %.1f deg' % (ctfdata[0]*1e6,ctfdata[1]*1e6,ctfdata[2]*100, ctfdata[3]*180.0/math.pi)) s = '%d' % int(ctfdata[0]*1e9) #elif self.ace2exe: elif False: ctfdata = self.estimateCTF(imagedata) z0 = (ctfdata['defocus1'] + ctfdata['defocus2']) / 2 s = '%d' % (int(z0*1e9),) ''' if s: t = numpil.textArray(s) t = ndimage.zoom(t, (min(binned.shape) - 40.0) * 0.08 / (t.shape)[0]) minvalue = arraystats.min(binned) maxvalue = arraystats.max(binned) t = minvalue + t * (maxvalue - minvalue) imagefun.pasteInto(t, binned, (20, 20)) return binned, ctfdata
def overlayshadow(self,shadowimg,parentimg,alpha=0.5): binning = parentimg.shape[0]/shadowimg.shape[0] if binning != 1: parentimg=imagefun.bin(parentimg,binning) overlay=parentimg+shadowimg*alpha*(parentimg.max()-parentimg.min())/max(shadowimg.max(),1) return overlay,parentimg
def bin_img(image, bin): """ zoom does a bad job of binning """ #return ndimage.zoom(img,1.0/float(binning),order=1) """ numextension used to cause mem leaks """ #return imagefun.bin(image,bin) return imagefun.bin(image, bin)
def bin_img(image,bin): """ zoom does a bad job of binning """ #return ndimage.zoom(img,1.0/float(binning),order=1) """ numextension used to cause mem leaks """ #return imagefun.bin(image,bin) return imagefun.bin(image,bin)
def correlate(self, imagedata, tiltcorrection=True, channel=None, wiener=False, taper=0, corrtype='phase'): image = self.getCenterSquareImage(imagedata['image']) if len(image.shape) != 2 or image.shape[0] != image.shape[1]: raise ValueError if self.correlation_binning != 1: image = imagefun.bin(image, int(self.correlation_binning)) # create new imagedata according to the additional bin camdata = leginon.leginondata.CameraEMData( initializer=imagedata['camera']) camdata['binning'] = { 'x': camdata['binning']['x'] * self.correlation_binning, 'y': camdata['binning']['y'] * self.correlation_binning } newimagedata = leginon.leginondata.AcquisitionImageData( initializer=imagedata) newimagedata['camera'] = camdata # numpy 2.0 does not allow inplace assignment involving different kinds # convert to float first image = image.astype(numpy.float) mean = image.mean() image -= mean if self.hanning is None or image.shape[0] != self.hanning.shape[0]: self.hanning = hanning(image.shape[0]) image *= self.hanning newimagedata['image'] = image if tiltcorrection: # stage tilt corrector stretchs and updates the image in imagedata according to its stage matrix calibration self.tiltcorrector.undo_tilt(newimagedata) image = newimagedata['image'] if taper > 0: taperboundary = int((image.shape)[0] * taper * 0.01) imagefun.taper(image, taperboundary) self.correlation.insertImage(image) self.channel = channel if corrtype == 'phase': try: pc = self.correlation.phaseCorrelate(wiener=wiener) except correlator.MissingImageError: return else: try: pc = self.correlation.crossCorrelate() except correlator.MissingImageError: return peak = self.peakfinder.subpixelPeak(newimage=pc) rows, columns = self.peak2shift(peak, pc.shape) self.raw_shift = {'x': columns, 'y': rows} self.shift['x'] -= self.raw_shift['x'] * self.correlation_binning self.shift['y'] += self.raw_shift['y'] * self.correlation_binning pc = self.swapQuadrants(pc) return pc