def prepL(self, maxL): if maxL not in self.lDict: latglq, longlq = psh.GLQGridCoord(maxL) thetaglq = latToTheta(latglq) phiglq = lonToPhi(longlq) nodes, weights = psh.SHGLQ(maxL) self.lDict[maxL] = (thetaglq, phiglq, nodes, weights) return self.lDict[maxL]
def prep_transforms(edgeLen, maxL, rMax): """ Build harmonics tables. This is expected to be called once per block. """ fullChain = prep_chain(edgeLen, maxL, rMax) lDict = {} for _, _, l in fullChain: nodes, weights = psh.SHGLQ(l) lDict[l] = (nodes, weights) #print('##### Completed prep_rotations') return fullChain, lDict
def TimingAccuracyGLQC(): # ---- input parameters ---- maxdeg = 2800 ls = np.arange(maxdeg + 1) beta = 1.5 print('Gauss-Legendre quadrature (complex)') # ---- create mask to filter out m<=l ---- mask = np.zeros((2, maxdeg + 1, maxdeg + 1), dtype=np.bool) mask[0, 0, 0] = True for l in ls: mask[:, l, :l + 1] = True mask[1, :, 0] = False # ---- create Gaussian powerlaw coefficients ---- print('creating {:d} random coefficients'.format(2 * (maxdeg + 1) * (maxdeg + 1))) cilm = np.zeros((2, maxdeg + 1, maxdeg + 1), dtype=np.complex) cilm.imag = np.random.normal(loc=0., scale=1., size=(2, maxdeg + 1, maxdeg + 1)) cilm.real = np.random.normal(loc=0., scale=1., size=(2, maxdeg + 1, maxdeg + 1)) old_power = shtools.SHPowerSpectrumC(cilm) new_power = 1. / (1. + ls)**beta # initialize degrees > 0 to power-law cilm[:, :, :] *= np.sqrt(new_power / old_power)[None, :, None] cilm[~mask] = 0. # ---- time spherical harmonics transform for lmax set to increasing # ---- powers of 2 ---- lmax = 2 print('lmax maxerror rms tprecompute tinverse tforward') while lmax <= maxdeg: # trim coefficients to lmax cilm_trim = cilm[:, :lmax + 1, :lmax + 1] mask_trim = mask[:, :lmax + 1, :lmax + 1] # precompute grid nodes and associated Legendre functions tstart = time.time() zeros, weights = shtools.SHGLQ(lmax) tend = time.time() tprecompute = tend - tstart # synthesis / inverse tstart = time.time() grid = shtools.MakeGridGLQC(cilm_trim, zeros) tend = time.time() tinverse = tend - tstart # analysis / forward tstart = time.time() cilm2_trim = shtools.SHExpandGLQC(grid, weights, zeros) tend = time.time() tforward = tend - tstart # compute error err = np.abs(cilm_trim[mask_trim] - cilm2_trim[mask_trim]) / \ np.abs(cilm_trim[mask_trim]) maxerr = err.max() rmserr = np.mean(err**2) print('{:4d} {:1.2e} {:1.2e} {:1.1e}s {:1.1e}s ' '{:1.1e}s'.format(lmax, maxerr, rmserr, tprecompute, tinverse, tforward)) lmax = lmax * 2
def ylms_to_samples(ylms, layer_list, n_chan): """ Given a subrange of ylms, transform to images on the sphere input: images: dimensions (batch_sz, N_BALL_SAMPS, n_chan) layer_list: python list of integer layer numbers n_chan: number of channels in the input returns: rslt: dimensions (blk_sz, hrm_samps, n_chan) where hrm_samps is the sum over layer_list of (2 * (l+1) * (l+1)) """ edge_len = 2 * RAD_PIXELS + 1 r_max = 0.5 * float(edge_len + 1) full_chain = prep_chain(edge_len, MAX_L, r_max) l_dict = {} for _, _, l in full_chain: nodes, weights = psh.SHGLQ(l) l_dict[l] = (nodes, weights) tot_hrm_sz = 0 for l in layer_list: tot_hrm_sz += np.prod(hrm_dims_from_l(l)) #print('tot_hrm_sz:', tot_hrm_sz) #print('keys: ', l_dict.keys()) def this_op(ylms): #print('ylms shape: ', ylms.shape) assert n_chan == ylms.shape[-1], 'Got the wrong number of channels' batch_sz, hrm_blk_sz = ylms.shape[:-1] rslt = np.zeros((batch_sz, N_BALL_SAMPS, n_chan)) for idx_batch in range(batch_sz): samp_offset = 0 hrm_offset = 0 for _, _, l in full_chain: samp_dim1, samp_dim2 = dims_from_l(l) samp_blk_sz = samp_dim1 * samp_dim2 if l in layer_list: hrm_dim1, hrm_dim2, hrm_dim3 = hrm_dims_from_l(l) hrm_blk_sz = hrm_dim1 * hrm_dim2 * hrm_dim3 #print('hrm_blk_sz:', hrm_blk_sz) for idx_chan in range(n_chan): hrm_blk = ylms[idx_batch, hrm_offset:hrm_offset + hrm_blk_sz, idx_chan] nodes, weights = l_dict[l] samp_blk = psh.MakeGridGLQ( tf.reshape(hrm_blk, [hrm_dim1, hrm_dim2, hrm_dim3]), nodes) #print('samp_blk shape: ', samp_blk.shape) rslt[idx_batch, samp_offset:samp_offset + samp_blk_sz, idx_chan] = samp_blk.flat hrm_offset += hrm_blk_sz samp_offset += samp_blk_sz return rslt rslt = tf.py_function(this_op, [ylms], dtypes.float32, name="ylms_to_samples") #with tf.control_dependencies([tf.print('rslt: ', rslt)]): rslt = tf.reshape(rslt, [-1, N_BALL_SAMPS, n_chan]) return rslt
def samples_to_ylms(images, layer_list, n_chan): """ Given a collection of samples on the sphere, transform the layers specified by layer_list to Ylms. Note that layer_list is specifying the radii to be transformed. All l values within those layers are included in the output Ylms. input: images: dimensions (batch_sz, N_BALL_SAMPS, n_chan) layer_list: python list of integer layer numbers n_chan: number of channels in the input returns: rslt: dimensions (blk_sz, hrm_samps, n_chan) where hrm_samps is the sum over layer_list of (2 * (l+1) * (l+1)) """ edge_len = 2 * RAD_PIXELS + 1 r_max = 0.5 * float(edge_len + 1) full_chain = prep_chain(edge_len, MAX_L, r_max) l_dict = {} for _, _, l in full_chain: nodes, weights = psh.SHGLQ(l) l_dict[l] = (nodes, weights) tot_hrm_sz = 0 for l in layer_list: tot_hrm_sz += np.prod(hrm_dims_from_l(l)) #print('tot_hrm_sz:', tot_hrm_sz) #print('keys: ', l_dict.keys()) def this_op(images): print('images shape: ', images.shape) assert n_chan == images.shape[-1], 'Got the wrong number of channels' batch_sz, blk_sz = images.shape[:-1] rslt = np.zeros((batch_sz, tot_hrm_sz, n_chan)) for idx_batch in range(batch_sz): samp_offset = 0 hrm_offset = 0 for _, _, l in full_chain: samp_dim1, samp_dim2 = dims_from_l(l) samp_blk_sz = samp_dim1 * samp_dim2 if l in layer_list: hrm_blk_sz = np.prod(hrm_dims_from_l(l)) #print('hrm_blk_sz:', hrm_blk_sz) for idx_chan in range(n_chan): samp_blk = images[idx_batch, samp_offset:samp_offset + samp_blk_sz, idx_chan] nodes, weights = l_dict[l] hrm_blk = psh.SHExpandGLQ( tf.reshape(samp_blk, [samp_dim1, samp_dim2]), weights, nodes) #print('hrm_blk shape: ', hrm_blk.shape) rslt[idx_batch, hrm_offset:hrm_offset + hrm_blk_sz, idx_chan] = hrm_blk.flat hrm_offset += hrm_blk_sz samp_offset += samp_blk_sz return rslt rslt = tf.py_function(this_op, [images], dtypes.float32, name="samples_to_ylms") #with tf.control_dependencies([tf.print('rslt: ', rslt)]): rslt = tf.reshape(rslt, [-1, tot_hrm_sz, n_chan]) return rslt