def calc_blm_full(self, blms_in): ''' Convert samples in blm space to blm complex values including negetive m vals Input: blms ordered dictionary Ouput: blms_full, list including blms with negative m vals ''' ## Array of blm values for both +ve and -ve indices blms_full = np.zeros(2 * self.blm_size - self.blmax - 1, dtype='complex') for jj in range(blms_full.size): lval, mval = self.bl_idx[jj], self.bm_idx[jj] if mval >= 0: blms_full[jj] = blms_in[Alm.getidx(self.blmax, lval, mval)] elif mval < 0: mval = -mval blms_full[jj] = (-1)**mval * np.conj(blms_in[Alm.getidx( self.blmax, lval, mval)]) return blms_full
def __init__(self, alm): [tlm, elm, blm] = alm self.lmaxt = Alm.getlmax(len(tlm)) self.lmaxe = Alm.getlmax(len(elm)) self.lmaxb = Alm.getlmax(len(blm)) self.lmax = max(self.lmaxt, self.lmaxe, self.lmaxb) self.elm = elm self.blm = blm self.tlm = tlm
def blm_params_2_blms(self, blm_params): ''' convert blm parameter values where amplitudes and phases are seperate to complex blm values. ''' ## initialize blm_vals array blm_vals = np.zeros(self.blm_size, dtype='complex') ## this is b00, alsways set to 1 blm_vals[0] = 1 ## counter for blm_vals cnt = 0 for lval in range(1, self.params['lmax'] + 1): for mval in range(lval + 1): idx = Alm.getidx(self.blmax, lval, mval) if mval == 0: blm_vals[idx] = blm_params[cnt] cnt = cnt + 1 else: #blm_vals[idx] = blm_params[cnt] + 1j * blm_params[cnt+1] ## prior on amplitude, phase blm_vals[idx] = blm_params[cnt] * np.exp( 1j * blm_params[cnt + 1]) cnt = cnt + 2 return blm_vals
def alm_splice(alm_lo, alm_hi, lsplit): """Returns an alm with lmax = lmax(alm_hi) which is alm_lo for (l <= lsplit) alm_hi for (l > lsplit.) """ if hasattr(alm_lo, 'alm_splice'): return alm_lo.alm_splice(alm_hi, lsplit) alm_lo_lmax = Alm.getlmax(len(alm_lo)) alm_hi_lmax = Alm.getlmax(len(alm_hi)) assert alm_lo_lmax >= lsplit and alm_hi_lmax >= lsplit alm_re = np.copy(alm_hi) for m in range(0, lsplit + 1): alm_re[(m * (2 * alm_hi_lmax + 1 - m) // 2 + m):(m * (2 * alm_hi_lmax + 1 - m) // 2 + lsplit + 1)] = \ alm_lo[(m * (2 * alm_lo_lmax + 1 - m) // 2 + m):(m * (2 * alm_lo_lmax + 1 - m) // 2 + lsplit + 1)] return alm_re
def __init__(self, alm): [elm, blm] = alm assert len(elm) == len(blm), (len(elm), len(blm)) self.lmax = Alm.getlmax(len(elm)) self.elm = elm self.blm = blm
def alm_copy(alm, lmax=None): """Copies the alm array, with the option to reduce its lmax. """ if hasattr(alm, 'alm_copy'): return alm.alm_copy(lmax=lmax) lmox = Alm.getlmax(len(alm)) assert (lmax <= lmox) if (lmox == lmax) or (lmax is None): ret = np.copy(alm) else: ret = np.zeros(Alm.getsize(lmax), dtype=np.complex) for m in range(0, lmax + 1): ret[((m * (2 * lmax + 1 - m) // 2) + m):(m * (2 * lmax + 1 - m) // 2 + lmax + 1)] = \ alm[((m * (2 * lmox + 1 - m) // 2) + m):(m * (2 * lmox + 1 - m) // 2 + lmax + 1)] return ret
def idxtoalm(self, lmax, ii): ''' index --> (l, m) function which works for negetive indices too ''' alm_size = Alm.getsize(lmax) if ii >= (2 * alm_size - lmax - 1): raise ValueError('Index larger than acceptable') elif ii < alm_size: l, m = Alm.getlm(lmax, ii) else: l, m = Alm.getlm(lmax, ii - alm_size + lmax + 1) if m == 0: raise ValueError( 'Something wrong with ind -> (l, m) conversion') else: m = -m return l, m
def alm2rlm(alm): """Converts a complex alm to 'real harmonic' coefficients rlm. This 'real harmonic' form is used for the dense matrix preconditioner tools. """ lmax = Alm.getlmax(alm.size) rlm = np.zeros((lmax + 1)**2, dtype=float) ls = np.arange(0, lmax + 1) l2s = ls**2 rt2 = np.sqrt(2.) rlm[l2s] = alm[ls].real for m in range(1, lmax + 1): rlm[l2s[m:] + 2 * m - 1] = alm[m * (2 * lmax + 1 - m) // 2 + ls[m:]].real * rt2 rlm[l2s[m:] + 2 * m + 0] = alm[m * (2 * lmax + 1 - m) // 2 + ls[m:]].imag * rt2 return rlm
def rlm2alm(rlm): """Converts 'real harmonic' coefficients rlm to complex alm. Inverse of alm2rlm. """ lmax = int(np.sqrt(len(rlm)) - 1) assert (lmax + 1)**2 == len(rlm) alm = np.zeros(Alm.getsize(lmax), dtype=complex) ls = np.arange(0, lmax + 1, dtype=int) l2s = ls**2 ir2 = 1.0 / np.sqrt(2.) alm[ls] = rlm[l2s] for m in range(1, lmax + 1): alm[m * (2 * lmax + 1 - m) // 2 + ls[m:]] = (rlm[l2s[m:] + 2 * m - 1] + 1.j * rlm[l2s[m:] + 2 * m + 0]) * ir2 return alm
def __init__(self): self.blmax = self.params['lmax'] self.almax = 2 * self.blmax ## size of arrays: for blms its only non-negative m values but for alms it is all of them self.alm_size = (self.almax + 1)**2 self.blm_size = Alm.getsize(self.blmax) ## calculate and store beta self.calc_beta() ## calculate and store the output of the idxtoalm method for blmax. ## This will be used many times for the spherical harmonic likelihood ## Array of blm values for both +ve and -ve indices self.bl_idx = np.zeros(2 * self.blm_size - self.blmax - 1, dtype='int') self.bm_idx = np.zeros(2 * self.blm_size - self.blmax - 1, dtype='int') for ii in range(self.bl_idx.size): #lval, mval = Alm.getlm(blmax, jj) self.bl_idx[ii], self.bm_idx[ii] = self.idxtoalm(self.blmax, ii)
def plotmaker(params, parameters, inj): ''' Make posterior plots from the samples generated by tge mcmc/nested sampling algorithm. Parameters ----------- params : dictionary Dictionary of config params parameters: string Array or list of strings with names of the parameters inj : int Injection dict ''' post = np.loadtxt(params['out_dir'] + "/post_samples.txt") ## setup the truevals dict truevals = [] if params['modeltype'] == 'isgwb': truevals.append(inj['log_Np']) truevals.append(inj['log_Na']) truevals.append(inj['alpha']) truevals.append(inj['ln_omega0']) elif params['modeltype'] == 'noise_only': truevals.append(inj['log_Np']) truevals.append(inj['log_Na']) elif params['modeltype'] == 'isgwb_only': truevals.append(inj['alpha']) truevals.append(inj['ln_omega0']) elif params['modeltype'] == 'sph_sgwb': truevals.append(inj['log_Np']) truevals.append(inj['log_Na']) truevals.append(inj['alpha']) truevals.append(inj['ln_omega0']) ## get blms for lval in range(1, params['lmax'] + 1): for mval in range(lval + 1): idx = Alm.getidx(params['lmax'], lval, mval) if mval == 0: truevals.append(np.real(inj['blms'][idx])) else: truevals.append(np.abs(inj['blms'][idx])) truevals.append(np.angle(inj['blms'][idx])) if len(truevals) > 0: knowTrue = 1 ## Bit for whether we know the true vals or not else: knowTrue = 0 npar = len(parameters) plotrange = [0.999] * npar if params['out_dir'][-1] != '/': params['out_dir'] = params['out_dir'] + '/' ## Make corner plots fig = corner.corner( post, range=plotrange, labels=parameters, quantiles=(0.16, 0.84), smooth=None, smooth1d=None, show_titles=True, title_kwargs={"fontsize": 12}, label_kwargs={"fontsize": 14}, fill_contours=True, use_math_text=True, ) # Put correct values # Extract the axes axes = np.array(fig.axes).reshape((npar, npar)) for ii in range(npar): ax = axes[ii, ii] ## Draw truevals if they exist if knowTrue: ax.axvline(truevals[ii], color="g", label='true value') ## Save posterior plt.savefig(params['out_dir'] + 'corners.png', dpi=150) print("Posteriors plots printed in " + params['out_dir'] + "corners.png") plt.close()
def plotmaker(params, parameters, inj): ''' Make posterior plots from the samples generated by tge mcmc/nested sampling algorithm. Parameters ----------- params : dictionary Dictionary of config params parameters: string Array or list of strings with names of the parameters npar : int Dimensionality of the parameter space ''' post = np.loadtxt(params['out_dir'] + "/post_samples.txt") ## if modeltype is sph, first call the mapmaker. if params['modeltype'] == 'sph_sgwb': mapmaker(params, post) ## setup the truevals dict truevals = [] if params['modeltype'] == 'isgwb': truevals.append(inj['log_Np']) truevals.append(inj['log_Na']) truevals.append(inj['alpha']) truevals.append(inj['ln_omega0']) elif params['modeltype'] == 'noise_only': truevals.append(inj['log_Np']) truevals.append(inj['log_Na']) elif params['modeltype'] == 'isgwb_only': truevals.append(inj['alpha']) truevals.append(inj['ln_omega0']) elif params['modeltype'] == 'sph_sgwb': truevals.append(inj['log_Np']) truevals.append(inj['log_Na']) truevals.append(inj['alpha']) truevals.append(inj['ln_omega0']) ## get blms for lval in range(1, params['lmax'] + 1): for mval in range(lval + 1): idx = Alm.getidx(params['lmax'], lval, mval) if mval == 0: truevals.append(np.real(inj['blms'][idx])) else: truevals.append(np.abs(inj['blms'][idx])) truevals.append(np.angle(inj['blms'][idx])) if len(truevals) > 0: knowTrue = 1 ## Bit for whether we know the true vals or not else: knowTrue = 0 npar = len(parameters) plotrange = [0.999] * npar if params['out_dir'][-1] != '/': params['out_dir'] = params['out_dir'] + '/' ## Make chainconsumer corner plots cc = ChainConsumer() cc.add_chain(post, parameters=parameters) cc.configure(smooth=False, kde=False, max_ticks=2, sigmas=np.array([1, 2]), label_font_size=18, tick_font_size=18, \ summary=False, statistics="max_central", spacing=2, summary_area=0.95, cloud=False, bins=1.2) cc.configure_truth(color='g', ls='--', alpha=0.7) if knowTrue: fig = cc.plotter.plot(figsize=(16, 16), truth=truevals) else: fig = cc.plotter.plot(figsize=(16, 16)) ## make axis labels to be parameter summaries sum_data = cc.analysis.get_summary() axes = np.array(fig.axes).reshape((npar, npar)) # Adjust axis labels for ii in range(npar): ax = axes[ii, ii] # get the right summary for the parameter ii sum_ax = sum_data[parameters[ii]] err = [sum_ax[2] - sum_ax[1], sum_ax[1] - sum_ax[0]] if np.abs(sum_ax[1]) <= 1e-3: mean_def = '{0:.3e}'.format(sum_ax[1]) eidx = mean_def.find('e') base = float(mean_def[0:eidx]) exponent = int(mean_def[eidx + 1:]) mean_form = str(base) + ' \\times ' + '10^{' + str(exponent) + '} ' else: mean_form = '{0:.3f}'.format(sum_ax[1]) if np.abs(err[0]) <= 1e-2: err[0] = '{0:.4f}'.format(err[0]) else: err[0] = '{0:.2f}'.format(err[0]) if np.abs(err[1]) <= 1e-2: err[1] = '{0:.4f}'.format(err[1]) else: err[1] = '{0:.2f}'.format(err[1]) label = parameters[ii][:-1] + ' = ' + mean_form + '^{+' + err[ 0] + '}_{-' + err[1] + '}$' ax.set_title(label, {'fontsize': 18}, loc='left') ## Save posterior plt.savefig(params['out_dir'] + 'corners.png', dpi=150) print("Posteriors plots printed in " + params['out_dir'] + "corners.png") plt.close()
def mapmaker(params, post): # size of the blm array blm_size = Alm.getsize(params['lmax']) ## we will plot with a larger nside than the analysis for finer plots nside = 2 * params['nside'] npix = hp.nside2npix(nside) # Initialize power skymap omega_map = np.zeros(npix) blmax = params['lmax'] for ii in range(post.shape[0]): sample = post[ii, :] # Omega at 1 mHz Omega_1mHz = (10**(sample[3])) * (1e-3 / 25)**(sample[2]) ## blms. blms = np.append([1], sample[4:]) ## Complex array of blm values for both +ve m values blm_vals = np.zeros(blm_size, dtype='complex') ## this is b00, alsways set to 1 blm_vals[0] = 1 norm, cnt = 1, 1 for lval in range(1, blmax + 1): for mval in range(lval + 1): idx = Alm.getidx(blmax, lval, mval) if mval == 0: blm_vals[idx] = blms[cnt] cnt = cnt + 1 else: ## prior on amplitude, phase blm_vals[idx] = blms[cnt] * np.exp(1j * blms[cnt + 1]) cnt = cnt + 2 norm = np.sum(blm_vals[0:(blmax + 1)]**2) + np.sum( 2 * np.abs(blm_vals[(blmax + 1):])**2) prob_map = (1.0 / norm) * (hp.alm2map(blm_vals, nside, verbose=False))**2 ## add to the omega map omega_map = omega_map + Omega_1mHz * prob_map omega_map = omega_map / post.shape[0] hp.mollview(omega_map, title='Posterior predictive skymap of $\\Omega(f= 1mHz)$') hp.graticule() plt.savefig(params['out_dir'] + '/post_skymap.png', dpi=150) print('saving injected skymap at ' + params['out_dir'] + '/post_skymap.png') plt.close() #### ------------ Now plot median value # median values of the posteriors med_vals = np.median(post, axis=0) ## blms. blms_median = np.append([1], med_vals[4:]) # Omega at 1 mHz Omega_1mHz_median = (10**(med_vals[3])) * (1e-3 / 25)**(med_vals[2]) ## Complex array of blm values for both +ve m values blm_median_vals = np.zeros(blm_size, dtype='complex') ## this is b00, alsways set to 1 blm_median_vals[0] = 1 cnt = 1 for lval in range(1, blmax + 1): for mval in range(lval + 1): idx = Alm.getidx(blmax, lval, mval) if mval == 0: blm_median_vals[idx] = blms_median[cnt] cnt = cnt + 1 else: ## prior on amplitude, phase blm_median_vals[idx] = blms_median[cnt] * np.exp( 1j * blms_median[cnt + 1]) cnt = cnt + 2 norm = np.sum(blm_median_vals[0:(blmax + 1)]**2) + np.sum( 2 * np.abs(blm_median_vals[(blmax + 1):])**2) Omega_median_map = Omega_1mHz_median * (1.0 / norm) * (hp.alm2map( blm_median_vals, nside, verbose=False))**2 hp.mollview(omega_map, title='median skymap of $\\Omega(f= 1mHz)$') hp.graticule() plt.savefig(params['out_dir'] + '/post_median_skymap.png', dpi=150) print('saving injected skymap at ' + params['out_dir'] + '/post_median_skymap.png') plt.close() return