def get_spectra(self, streakspeed_in_meV_per_fs, keep_originals=False, discretized=True): '''returns streaked spectra, measured with "number_electronsx" simulated electrons or nondiscretized as a tuple''' from streaking_cal.statistics import weighted_avg_and_std if not (self.is_low_res()): (streaked1, streaked2 ) = self.__get_streaked_spectra(streakspeed_in_meV_per_fs) streaked1 = interp(tof_ens_gpu, self.__eAxis, streaked1) streaked2 = interp(tof_ens_gpu, self.__eAxis, streaked2) xuvonly = interp(tof_ens_gpu, self.__eAxis, cp.square(cp.abs(self.__spec))) if not (keep_originals): self.__eAxis = None self.__spec = None t_square = cp.square(cp.abs(self.__temp)) t_mean, _ = weighted_avg_and_std(self.__tAxis.get(), t_square.get()) self.__temp = interp(cp.asarray(standard_full_time), self.__tAxis - t_mean, t_square).get() self.__temp = self.__temp / cp.sum(self.__temp) self.__tAxis = standard_full_time self.__is_low_res = True self.__streakedspectra = np.asarray( (xuvonly.get(), streaked1.get(), streaked2.get())) self.__streakspeed = streakspeed_in_meV_per_fs self.__tAxis = standard_full_time if discretized: streaked1 = self.discretized_spectrum(streaked1, self.num_electrons1) streaked2 = self.discretized_spectrum(streaked2, self.num_electrons2) self.__streakspeed = streakspeed_in_meV_per_fs return cp.asnumpy(xuvonly), cp.asnumpy(streaked1), cp.asnumpy( streaked2) elif discretized: (xuvonly, streaked1, streaked2) = self.__streakedspectra streaked1 = self.discretized_spectrum(streaked1, self.num_electrons1) streaked2 = self.discretized_spectrum(streaked2, self.num_electrons2) return cp.asnumpy(xuvonly), cp.asnumpy(streaked1), cp.asnumpy( streaked2) else: return self.__streakedspectra.copy()
def _index_or_values_interpolation(column, index=None): """ Interpolate over a float column. assumes a linear interpolation strategy using the index of the data to denote spacing of the x values. For example the data and index [1.0, NaN, 4.0], [1, 3, 4] would result in [1.0, 3.0, 4.0] """ # figure out where the nans are mask = cp.isnan(column) # trivial cases, all nan or no nans num_nan = mask.sum() if num_nan == 0 or num_nan == len(column): return column to_interp = Frame(data={None: column}, index=index) known_x_and_y = to_interp._apply_boolean_mask(as_column(~mask)) known_x = known_x_and_y._index._column.values known_y = known_x_and_y._data.columns[0].values result = cp.interp(to_interp._index.values, known_x, known_y) # find the first nan first_nan_idx = (mask == 0).argmax().item() result[:first_nan_idx] = np.nan return result
def resampled_TOF_signal(self, TOF_signal): from numpy import take_along_axis, interp sorted_TOF_signal = take_along_axis(TOF_signal, self.TOF_times_sort_order, axis=0) resampled_TOF_signal = interp(Raw_data.TOF_times, self.sorted_TOF_times, sorted_TOF_signal) return resampled_TOF_signal
def resampled_VLS_signal(self, VLS_signal): from numpy import take_along_axis, interp sorted_VLS_signal = take_along_axis(VLS_signal, self.VLS_pixels_sort_order, axis=0) resampled_VLS_signal = interp(Raw_data.VLS_pixels, self.sorted_VLS_pixels, sorted_VLS_signal) return resampled_VLS_signal
def _match_cumulative_cdf(source, template): """ Return modified source array so that the cumulative density function of its values matches the cumulative density function of the template. """ src_values, src_unique_indices, src_counts = cp.unique(source.ravel(), return_inverse=True, return_counts=True) tmpl_values, tmpl_counts = cp.unique(template.ravel(), return_counts=True) # calculate normalized quantiles for each array src_quantiles = cp.cumsum(src_counts) / source.size tmpl_quantiles = cp.cumsum(tmpl_counts) / template.size interp_a_values = cp.interp(src_quantiles, tmpl_quantiles, tmpl_values) return interp_a_values[src_unique_indices].reshape(source.shape)
def GetSASE_gpu(CentralEnergy, dE_FWHM, dt_FWHM, samples=0, onlyT=False): from cupy import interp import cupy as cp h = 4.135667662 #in eV*fs dE = dE_FWHM / 2.355 #in eV, converts to sigma dt = dt_FWHM / 2.355 #in fs, converts to sigma if samples == 0: samples = int(600. * dt * CentralEnergy / h) else: if (samples < 400. * dt * CentralEnergy / h): print( "Number of samples is a little small, proceeding anyway. Got", samples, "prefer more than", 400. * dt * CentralEnergy / h) EnAxis = cp.linspace(0., 20. * CentralEnergy, num=samples, dtype=cp.float32) newEaxis = cp.linspace(0, 140, 32 * 1024) # EnInput=cp.zeros(samples, dtype=cp.complex64) # for i in range(samples): EnInput = cp.exp(-(EnAxis - CentralEnergy)**2 / 2. / dE**2 + 2 * cp.pi * 1j * cp.random.random(size=samples), dtype=cp.complex64) EnInput = interp(newEaxis, EnAxis, EnInput) newTaxis = cp.fft.fftfreq(32 * 1024, d=140 / (32 * 1024)) * h TOutput = cp.exp(-newTaxis**2 / 2. / dt**2) * cp.fft.fft(EnInput) # sort TOutput and newTaxis ind = cp.argsort(newTaxis, axis=0) newTaxis = cp.sort(newTaxis) TOutput = cp.take_along_axis(TOutput, ind, axis=0) # En_FFT=cp.fft.fft(EnInput) # TAxis=cp.fft.fftfreq(samples,d=(20.*CentralEnergy)/samples)*h # TOutput=cp.exp(-TAxis**2/2./dt**2)*En_FFT if not (onlyT): EnOutput = cp.fft.ifft(TOutput) if (onlyT): return newTaxis, TOutput else: return newEaxis, EnOutput, newTaxis, TOutput
def equalize_hist(image, nbins=256, mask=None): """Return image after histogram equalization. Parameters ---------- image : array Image array. nbins : int, optional Number of bins for image histogram. Note: this argument is ignored for integer images, for which each integer is its own bin. mask: ndarray of bools or 0s and 1s, optional Array of same shape as `image`. Only points at which mask == True are used for the equalization, which is applied to the whole image. Returns ------- out : float array Image array after histogram equalization. Notes ----- This function is adapted from [1]_ with the author's permission. References ---------- .. [1] http://www.janeriksolem.net/histogram-equalization-with-python-and.html .. [2] https://en.wikipedia.org/wiki/Histogram_equalization """ if mask is not None: mask = cp.array(mask, dtype=bool) cdf, bin_centers = cumulative_distribution(image[mask], nbins) else: cdf, bin_centers = cumulative_distribution(image, nbins) if False: out = cp.interp(image.flat, bin_centers, cdf) else: # TODO: grlee77: no cp.interp, so have to transfer out = cp.asarray( np.interp(image.get().flat, bin_centers.get(), cdf.get()) ) return out.reshape(image.shape)
def _match_cumulative_cdf(source, template): """ Return modified source array so that the cumulative density function of its values matches the cumulative density function of the template. """ src_values, src_unique_indices, src_counts = cp.unique(source.ravel(), return_inverse=True, return_counts=True) tmpl_values, tmpl_counts = cp.unique(template.ravel(), return_counts=True) # calculate normalized quantiles for each array src_quantiles = cp.cumsum(src_counts) / source.size tmpl_quantiles = cp.cumsum(tmpl_counts) / template.size # TODO: grlee77: cp.interp does not exist, so have to transfer to CPU if not hasattr(cp, "interp"): src_quantiles = src_quantiles.get() tmpl_quantiles = tmpl_quantiles.get() tmpl_values = tmpl_values.get() interp_a_values = cp.asarray( np.interp(src_quantiles, tmpl_quantiles, tmpl_values)) else: interp_a_values = cp.interp(src_quantiles, tmpl_quantiles, tmpl_values) return interp_a_values[src_unique_indices].reshape(source.shape)
def _calibrate(self, img, findCarrier = True, useCupy = False): assert len(img) > 2 self.N = len(img[0, :, :]) if self.N != self._lastN: self._allocate_arrays() ''' define k grids ''' self._dx = self.pixelsize / self.magnification # Sampling in image plane self._res = self.wavelength / (2 * self.NA) self._oversampling = self._res / self._dx self._dk = self._oversampling / (self.N / 2) # Sampling in frequency plane self._k = np.arange(-self._dk * self.N / 2, self._dk * self.N / 2, self._dk, dtype=np.double) self._dx2 = self._dx / 2 self._kr = np.sqrt(self._k ** 2 + self._k[:,np.newaxis] ** 2, dtype=np.single) kxbig = np.arange(-self._dk * self.N, self._dk * self.N, self._dk, dtype=np.single) kybig = kxbig[:,np.newaxis] '''Sum input images if there are more than 3''' if len(img) > 3: imgs = np.zeros((3, self.N, self.N), dtype=np.single) for i in range(3): imgs[i, :, :] = np.sum(img[i:(len(img) // 3) * 3:3, :, :], 0, dtype = np.single) else: imgs = np.single(img) '''Separate bands into DC and 1 high frequency band''' M = exp(1j * 2 * pi / 3) ** ((np.arange(0, 2)[:, np.newaxis]) * np.arange(0, 3)) sum_prepared_comp = np.zeros((2, self.N, self.N), dtype=np.complex64) wienerfilter = np.zeros((2 * self.N, 2 * self.N), dtype=np.single) for k in range(0, 2): for l in range(0, 3): sum_prepared_comp[k, :, :] = sum_prepared_comp[k, :, :] + imgs[l, :, :] * M[k, l] if findCarrier: # minimum search radius in k-space mask1 = (self._kr > 1.9 * self.eta) if useCupy: self.kx, self.ky = self._coarseFindCarrier_cupy(sum_prepared_comp[0, :, :], sum_prepared_comp[1, :, :], mask1) else: self.kx, self.ky = self._coarseFindCarrier(sum_prepared_comp[0, :, :], sum_prepared_comp[1, :, :], mask1) if useCupy: ckx, cky, p, ampl = self._refineCarrier_cupy(sum_prepared_comp[0, :, :], sum_prepared_comp[1, :, :], self.kx, self.ky) else: ckx, cky, p, ampl = self._refineCarrier(sum_prepared_comp[0, :, :], sum_prepared_comp[1, :, :], self.kx, self.ky) self.kx = ckx # store found kx, ky, p and ampl values self.ky = cky self.p = p self.ampl = ampl if self.debug: print(f'kx = {ckx}') print(f'ky = {cky}') print(f'p = {p}') print(f'a = {ampl}') ph = np.single(2 * pi * self.NA / self.wavelength) xx = np.arange(-self._dx2 * self.N, self._dx2 * self.N, self._dx2, dtype=np.single) yy = xx if self.usemodulation: A = ampl else: A = 1 for idx_p in range(0, 3): pstep = idx_p * 2 * pi / 3 if useCupy: self._reconfactor[idx_p, :, :] = ( 1 + 4 / A * cp.outer(cp.exp(cp.asarray(1j * (ph * cky * yy - pstep + p))), cp.exp(cp.asarray(1j * ph * ckx * xx))).real).get() else: self._reconfactor[idx_p, :, :] = ( 1 + 4 / A * np.outer(np.exp(1j * (ph * cky * yy - pstep + p)), np.exp(1j * ph * ckx * xx)).real) # calculate pre-filter factors mask2 = (self._kr < 2) self._prefilter = np.single((self._tfm(self._kr, mask2) * self._attm(self._kr, mask2))) self._prefilter = fft.fftshift(self._prefilter) mtot = np.full((2 * self.N, 2 * self.N), False) krbig = sqrt((kxbig - ckx) ** 2 + (kybig - cky) ** 2) mask = (krbig < 2) mtot = mtot | mask wienerfilter[mask] = wienerfilter[mask] + (self._tf(krbig[mask]) ** 2) * self._att(krbig[mask]) krbig = sqrt((kxbig + ckx) ** 2 + (kybig + cky) ** 2) mask = (krbig < 2) mtot = mtot | mask wienerfilter[mask] = wienerfilter[mask] + (self._tf(krbig[mask]) ** 2) * self._att(krbig[mask]) krbig = sqrt(kxbig ** 2 + kybig ** 2) mask = (krbig < 2) mtot = mtot | mask wienerfilter[mask] = wienerfilter[mask] + (self._tf(krbig[mask]) ** 2) * self._att(krbig[mask]) self.wienerfilter = wienerfilter if self.debug: plt.figure() plt.title('WienerFilter') plt.imshow(wienerfilter) th = np.linspace(0, 2 * pi, 360, dtype = np.single) inv = np.geterr()['invalid'] np.seterr(invalid = 'ignore') kmaxth = np.fmax(2, np.fmax(ckx * np.cos(th) + cky * np.sin(th) + np.sqrt(4 - (ckx * np.sin(th)) ** 2 - (cky * np.cos(th)) ** 2 + ckx * cky * np.sin(2 * th)), - ckx * np.cos(th) - cky * np.sin(th) + np.sqrt(4 - (ckx * np.sin(th)) ** 2 - (cky * np.cos(th)) ** 2 + ckx * cky * np.sin(2 * th)))) np.seterr(invalid = inv) if useCupy and 'interp' in dir(cp): # interp not available in cupy version < 9.0.0 kmax = cp.interp(cp.arctan2(cp.asarray(kybig), cp.asarray(kxbig)), cp.asarray(th), cp.asarray(kmaxth), period=2 * pi).astype(np.single).get() else: kmax = np.interp(np.arctan2(kybig, kxbig), th, kmaxth, period=2 * pi).astype(np.single) wienerfilter = mtot * (1 - krbig * mtot / kmax) / (wienerfilter * mtot + self.w ** 2) self._postfilter = fft.fftshift(wienerfilter) if opencv: self._reconfactorU = [cv2.UMat(self._reconfactor[idx_p, :, :]) for idx_p in range(0, 3)] self._prefilter_ocv = np.single(cv2.dft(fft.ifft2(self._prefilter).real)) pf = np.zeros((self.N, self.N, 2), dtype=np.single) pf[:, :, 0] = self._prefilter pf[:, :, 1] = self._prefilter self._prefilter_ocvU = cv2.UMat(np.single(pf)) self._postfilter_ocv = np.single(cv2.dft(fft.ifft2(self._postfilter).real)) pf = np.zeros((2 * self.N, 2 * self.N, 2), dtype=np.single) pf[:, :, 0] = self._postfilter pf[:, :, 1] = self._postfilter self._postfilter_ocvU = cv2.UMat(np.single(pf)) if cupy: self._postfilter_cp = cp.asarray(self._postfilter)
def _calibrate(self, img, findCarrier=True, useCupy=False): assert len(img) > 6 self.N = len(img[0, :, :]) if self.N != self._lastN: self._allocate_arrays() ''' define k grids ''' self._dx = self.pixelsize / self.magnification # Sampling in image plane self._res = self.wavelength / (2 * self.NA) self._oversampling = self._res / self._dx self._dk = self._oversampling / (self.N / 2 ) # Sampling in frequency plane self._k = np.arange(-self._dk * self.N / 2, self._dk * self.N / 2, self._dk, dtype=np.double) self._dx2 = self._dx / 2 self._kr = np.sqrt(self._k**2 + self._k[:, np.newaxis]**2, dtype=np.single) kxbig = np.arange(-self._dk * self.N, self._dk * self.N, self._dk, dtype=np.single) kybig = kxbig[:, np.newaxis] '''Sum input images if there are more than 7''' if len(img) > 7: imgs = np.zeros((7, self.N, self.N), dtype=np.single) for i in range(7): imgs[i, :, :] = np.sum(img[i:(len(img) // 7) * 7:7, :, :], 0, dtype=np.single) else: imgs = np.single(img) '''Separate bands into DC and 3 high frequency bands''' M = np.complex64( exp(1j * 2 * pi / 7)**((np.arange(0, 4)[:, np.newaxis]) * np.arange(0, 7))) wienerfilter = np.zeros((2 * self.N, 2 * self.N), dtype=np.single) if useCupy: sum_prepared_comp = cp.dot(cp.asarray(M), cp.asarray(imgs).transpose( (1, 0, 2))).get() else: sum_prepared_comp = np.zeros((4, self.N, self.N), dtype=np.complex64) for k in range(0, 4): for l in range(0, 7): sum_prepared_comp[k, :, :] = sum_prepared_comp[ k, :, :] + imgs[l, :, :] * M[k, l] # find parameters ckx = np.zeros((3, 1), dtype=np.single) cky = np.zeros((3, 1), dtype=np.single) p = np.zeros((3, 1), dtype=np.single) ampl = np.zeros((3, 1), dtype=np.single) if findCarrier: # minimum search radius in k-space mask1 = (self._kr > 1.9 * self.eta) for i in range(0, 3): if useCupy: self.kx[i], self.ky[i] = self._coarseFindCarrier_cupy( sum_prepared_comp[0, :, :], sum_prepared_comp[i + 1, :, :], mask1) else: self.kx[i], self.ky[i] = self._coarseFindCarrier( sum_prepared_comp[0, :, :], sum_prepared_comp[i + 1, :, :], mask1) for i in range(0, 3): if useCupy: ckx[i], cky[i], p[i], ampl[i] = self._refineCarrier_cupy( sum_prepared_comp[0, :, :], sum_prepared_comp[i + 1, :, :], self.kx[i], self.ky[i]) else: ckx[i], cky[i], p[i], ampl[i] = self._refineCarrier( sum_prepared_comp[0, :, :], sum_prepared_comp[i + 1, :, :], self.kx[i], self.ky[i]) self.kx = ckx # store found kx, ky, p and ampl values self.ky = cky self.p = p self.ampl = ampl if self.debug: print(f'kx = {ckx[0]}, {ckx[1]}, {ckx[2]}') print(f'ky = {cky[0]}, {cky[1]}, {cky[2]}') print(f'p = {p[0]}, {p[1]}, {p[2]}') print(f'a = {ampl[0]}, {ampl[1]}, {ampl[2]}') ph = np.single(2 * pi * self.NA / self.wavelength) xx = np.arange(-self._dx2 * self.N, self._dx2 * self.N, self._dx2, dtype=np.single) yy = xx if self.usemodulation: A = [float(ampl[i]) for i in range(3)] else: if self.axial: A = [6.0 for i in range(3)] else: A = [12.0 for i in range(3)] for idx_p in range(0, 7): pstep = idx_p * 2 * pi / 7 if useCupy: self._reconfactor[idx_p, :, :] = ( 1 + 4 / A[0] * cp.outer( cp.exp( cp.asarray(1j * (ph * cky[0] * yy - pstep + p[0]))), cp.exp(cp.asarray(1j * ph * ckx[0] * xx))).real + 4 / A[1] * cp.outer( cp.exp( cp.asarray(1j * (ph * cky[1] * yy - 2 * pstep + p[1]))), cp.exp(cp.asarray(1j * ph * ckx[1] * xx))).real + 4 / A[2] * cp.outer( cp.exp( cp.asarray(1j * (ph * cky[2] * yy - 3 * pstep + p[2]))), cp.exp(cp.asarray(1j * ph * ckx[2] * xx))).real).get() else: self._reconfactor[idx_p, :, :] = (1 + 4 / A[0] * np.outer( np.exp(1j * (ph * cky[0] * yy - pstep + p[0])), np.exp(1j * ph * ckx[0] * xx)).real + 4 / A[1] * np.outer( np.exp(1j * (ph * cky[1] * yy - 2 * pstep + p[1])), np.exp( 1j * ph * ckx[1] * xx)).real + 4 / A[2] * np.outer( np.exp(1j * (ph * cky[2] * yy - 3 * pstep + p[2])), np.exp(1j * ph * ckx[2] * xx)).real) # calculate pre-filter factors mask2 = (self._kr < 2) self._prefilter = np.single( (self._tfm(self._kr, mask2) * self._attm(self._kr, mask2))) self._prefilter = fft.fftshift(self._prefilter) mtot = np.full((2 * self.N, 2 * self.N), False) th = np.linspace(0, 2 * pi, 360, dtype=np.single) inv = np.geterr()['invalid'] kmaxth = 2 for i in range(0, 3): krbig = sqrt((kxbig - ckx[i])**2 + (kybig - cky[i])**2) mask = (krbig < 2) mtot = mtot | mask wienerfilter[mask] = wienerfilter[mask] + (self._tf( krbig[mask])**2) * self._att(krbig[mask]) krbig = sqrt((kxbig + ckx[i])**2 + (kybig + cky[i])**2) mask = (krbig < 2) mtot = mtot | mask wienerfilter[mask] = wienerfilter[mask] + (self._tf( krbig[mask])**2) * self._att(krbig[mask]) np.seterr(invalid='ignore' ) # Silence sqrt warnings for kmaxth calculations kmaxth = np.fmax( kmaxth, np.fmax( ckx[i] * np.cos(th) + cky[i] * np.sin(th) + np.sqrt(4 - (ckx[i] * np.sin(th))**2 - (cky[i] * np.cos(th))**2 + ckx[i] * cky[i] * np.sin(2 * th)), -ckx[i] * np.cos(th) - cky[i] * np.sin(th) + np.sqrt(4 - (ckx[i] * np.sin(th))**2 - (cky[i] * np.cos(th))**2 + ckx[i] * cky[i] * np.sin(2 * th)))) np.seterr(invalid=inv) if self.debug: plt.figure() plt.plot(th, kmaxth) krbig = sqrt(kxbig**2 + kybig**2) mask = (krbig < 2) mtot = mtot | mask wienerfilter[mask] = ( wienerfilter[mask] + self._tf(krbig[mask])**2 * self._att(krbig[mask])) self.wienerfilter = wienerfilter if useCupy and 'interp' in dir( cp): # interp not available in cupy version < 9.0.0 kmax = cp.interp(cp.arctan2(cp.asarray(kybig), cp.asarray(kxbig)), cp.asarray(th), cp.asarray(kmaxth), period=2 * pi).astype(np.single).get() else: kmax = np.interp(np.arctan2(kybig, kxbig), th, kmaxth, period=2 * pi).astype(np.single) if self.debug: plt.figure() plt.title('WienerFilter') plt.imshow(wienerfilter) wienerfilter = mtot * (1 - krbig * mtot / kmax) / ( wienerfilter * mtot + self.w**2) self._postfilter = fft.fftshift(wienerfilter) if self.cleanup: imgo = self.reconstruct_fftw(img) kernel = np.ones((5, 5), np.uint8) mask_tmp = abs(fft.fftshift(fft.fft2(imgo))) > ( 10 * gaussian_filter(abs(fft.fftshift(fft.fft2(imgo))), 5)) mask = scipy.ndimage.morphology.binary_dilation( np.single(mask_tmp), kernel) mask[self.N - 12:self.N + 13, self.N - 12:self.N + 13] = np.full( (25, 25), False) mask_shift = (fft.fftshift(mask)) self._postfilter[mask_shift.astype(bool)] = 0 if opencv: self._reconfactorU = [ cv2.UMat(self._reconfactor[idx_p, :, :]) for idx_p in range(0, 7) ] self._prefilter_ocv = np.single( cv2.dft(fft.ifft2(self._prefilter).real)) pf = np.zeros((self.N, self.N, 2), dtype=np.single) pf[:, :, 0] = self._prefilter pf[:, :, 1] = self._prefilter self._prefilter_ocvU = cv2.UMat(np.single(pf)) self._postfilter_ocv = np.single( cv2.dft(fft.ifft2(self._postfilter).real)) pf = np.zeros((2 * self.N, 2 * self.N, 2), dtype=np.single) pf[:, :, 0] = self._postfilter pf[:, :, 1] = self._postfilter self._postfilter_ocvU = cv2.UMat(np.single(pf)) if cupy: self._postfilter_cp = cp.asarray(self._postfilter)
def __call__(self, x): return xp.interp(xp.asarray(x), self.xx, self.yy)