def set_file_name(self): """Determine filename.""" uni_mods = os.path.join(paths.models(), 'universe/') self.file_name = uni_mods + 'dm_mw.db' if self.test: uni_mods = os.path.join(paths.models(), 'universe/') self.file_name = uni_mods + 'test_dm_mw.db'
def dm_mw(gl, gb, model='ne2001'): """ Return DM values for given coordinates from NE2001 healpix Args: gl (array): Galactic longitude [fractional degrees] gb (array): Galactic latitude [fractional degrees] model (str): one of 'ne2001', 'ymw16' Returns: dm_mw (array): Galactic dispersion measure [pc*cm^-3] """ if model == 'ne2001': data_file = os.path.join(paths.models(), 'healpix/dm-ne2001-30kpc.fits') elif model == 'ymw16': data_file = os.path.join(paths.models(), 'healpix/dm-ymw16-30kpc.fits') data = hp.read_map(data_file, verbose=False, dtype=np.float64) nside = hp.npix2nside(len(data)) # This sets map resolution (NSIDE) pixloc = hp.ang2pix(nside, gl, gb, lonlat=True) return data[pixloc]
def set_file_name(self): """Determine filename.""" uni_mods = os.path.join(paths.models(), 'universe/') def cvt(value): """Convert a float to a string without a period.""" return str(value).replace('.', 'd') # Convert paras = ['h0', cvt(self.H_0), 'wm', cvt(self.W_m), 'wv', cvt(self.W_v)] f = '-'.join(paras) self.file_name = uni_mods + f + '.db'
def get_beam_props(model, fwhm): """Get beam properties. Args: model (str): Which model to use. fwhm (float): FWHM [frac. deg]. Returns: beam_size, pixel_scale, beam_array """ # Set up beam arrays models = ('wsrt-apertif', 'parkes-htru', 'chime-frb', 'gaussian', 'airy', 'wsrt-apertif_real') if model in models: place = paths.models() + f'/beams/{model}.npy' beam_array = np.load(place) # Set up details if using beam arrays if model.startswith('wsrt-apertif'): pixel_scale = 0.94 / 60 # Degrees per pixel [deg] beam_size = 25. # [sq deg] elif model == 'parkes-htru': pixel_scale = 54 / 3600 # Degrees per pixel [deg] beam_size = 9. # [sq deg] elif model == 'chime-frb': pixel_scale = 0.08 # Degrees per pixel [deg] beam_size = 180 * 80 # [sq deg] # If integrating over 180*80 degrees # Wolfram Alpha input: # integral_0^pi integral_0^(4*pi/9) sin(theta) d theta d phi # square radians to square degrees beam_size = 8522 # [sq deg] elif model == 'gaussian': pixel_scale = fwhm / 95 # Degrees per pixel [deg] beam_size = (pixel_scale * beam_array.shape[0])**2 elif model == 'airy': pixel_scale = fwhm / 31 # Degrees per pixel [deg] beam_size = (pixel_scale * beam_array.shape[0])**2 elif model.startswith('perfect'): pixel_scale = None beam_size = None beam_array = None else: raise ValueError('Beam model input not recognised.') return beam_size, pixel_scale, beam_array
""" Series of galactic operations (doesn't that sound cool?!). ...as in converting coordinates, calculating DM etc. """ import ctypes as C import math import os import numpy as np from frbpoppy.paths import paths from frbpoppy.log import pprint # Import fortran libraries uni_mods = os.path.join(paths.models(), 'universe/') dm_mods = os.path.join(paths.models(), 'ne2001/') loc = os.path.join(dm_mods, 'libne2001.so') ne2001lib = C.CDLL(loc) ne2001lib.dm_.restype = C.c_float def frac_deg(ra, dec): """Convert coordinates expressed in hh:mm:ss to fractional degrees.""" # Inspired by Joe Filippazzo calculator rh, rm, rs = [float(r) for r in ra.split(':')] ra = rh * 15 + rm / 4 + rs / 240 dd, dm, ds = [float(d) for d in dec.split(':')] if dd < 0: sign = -1 else:
def intensity_profile(self, shape=1, dimensions=2, rep_loc='random'): """Calculate intensity profile. Args: shape (tuple): Usually the shape of frbs.s_peak dimensions (int): Use a 2D beampattern or a 1D one. rep_loc (str): 'same' or 'random'. Whether repeaters are observed in the same spot or a different spot Returns: array, array: intensity profile, offset from beam [arcmin] """ # Calculate Full Width Half Maximum from beamsize self.fwhm = 2 * math.sqrt( self.beam_size_fwhm / math.pi) * 60 # [arcmin] offset = self.fwhm / 2 # Radius = diameter/2. if rep_loc == 'same': r = r = np.random.random(shape[0]) else: r = np.random.random(shape) if dimensions == 2: # 2D offset *= np.sqrt(r) elif dimensions == 1: # 1D offset *= r # Allow for a perfect beam pattern in which all is detected if self.gain_pattern == 'perfect': int_pro = np.ones(shape) self.beam_size = self.beam_size_fwhm return int_pro, offset # Formula's based on 'Interferometry and Synthesis in Radio # Astronomy' by A. Richard Thompson, James. M. Moran and # George W. Swenson, JR. (Second edition), around p. 15 max_offset = self.max_offset(self.n_sidelobes) self.beam_size = math.pi * (self.fwhm / 2 * max_offset / 60)**2 # [sq degrees] if self.gain_pattern == 'gaussian': # Set the maximum offset equal to the null after a sidelobe # I realise this pattern isn't an airy, but you have to cut # somewhere offset *= max_offset alpha = 2 * math.sqrt(math.log(2)) int_pro = np.exp(-(alpha * offset / self.fwhm)**2) return int_pro, offset elif self.gain_pattern == 'airy': # Set the maximum offset equal to the null after a sidelobe offset *= max_offset c = 299792458 conv = math.pi / (60 * 180) # Conversion arcmins -> radians eff_diam = c / (self.central_freq * 1e6 * conv * self.fwhm) a = eff_diam / 2 # Effective radius of telescope lamda = c / (self.central_freq * 1e6) ka = (2 * math.pi * a / lamda) kasin = ka * np.sin(offset * conv) int_pro = 4 * (j1(kasin) / kasin)**2 return int_pro, offset elif self.gain_pattern in ['parkes', 'apertif']: place = paths.models() + f'/beams/{self.gain_pattern}.npy' beam_array = np.load(place) b_shape = beam_array.shape ran_x = np.random.randint(0, b_shape[0], shape) ran_y = np.random.randint(0, b_shape[1], shape) int_pro = beam_array[ran_x, ran_y] offset = np.sqrt((ran_x - b_shape[0] / 2)**2 + (ran_y - b_shape[1] / 2)**2) # Scaling factors to correct for pixel scale if self.gain_pattern == 'apertif': # 1 pixel = 0.94' offset *= 240 / 256 # [arcmin] self.beam_size = 25. if self.gain_pattern == 'parkes': # 1 pixel = 54" offset *= 0.9 # [arcmin] self.beam_size = 9. return int_pro, offset else: pprint(f'Gain pattern "{self.gain_pattern}" not recognised')
def create_table(self, parallel=True): """Create a lookup table for dispersion measure.""" # Connect to database conn = sqlite3.connect(self.file_name) c = conn.cursor() # Set array of coordinates gls = np.arange(-180., 180. + self.step, self.step).round(1) gbs = np.arange(-90., 90. + self.step, self.step).round(1) dist = 0.1 # [Gpc] gls = gls.astype(np.float32) gbs = gbs.astype(np.float32) # Create database c.execute('create table dm ' + '(gl real, gb real, dm_mw real)') # Give an update on the progress m = [ 'Creating a DM lookup table', ' - Only needs to happen once', ' - Unfortunately pretty slow', ' - Prepare to wait for ~1.5h (4 cores)', ' - Time given as [time_spent<time_left] in (hh:)mm:ss', 'Starting to calculate DM values' ] for n in m: pprint(n) n_opt = len(gls) * len(gbs) options = np.array(np.meshgrid(gls, gbs)).T.reshape(-1, 2) dm_mw = np.zeros(len(options)).astype(np.float32) def dm_tot(i, dm_mw): gl, gb = options[i] dm_mw[i] = go.ne2001_dist_to_dm(dist, gl, gb) if parallel: temp_path = os.path.join(paths.models(), 'universe/') + 'temp.mmap' self.temp_path = temp_path # Make a temp memmap to have a sharedable memory object temp = np.memmap(temp_path, dtype=dm_mw.dtype, shape=len(dm_mw), mode='w+') # Parallel process in order to populate array r = range(n_opt) j = min([4, os.cpu_count() - 1]) print(os.cpu_count()) Parallel(n_jobs=j)(delayed(dm_tot)(i, temp) for i in tqdm(r)) # Map results r = np.concatenate((options, temp[:, np.newaxis]), axis=1) results = map(tuple, r.tolist()) # Delete the temporary directory and contents try: os.remove(temp_path) except FileNotFoundError: print(f'Unable to remove {temp_path}') else: for i in tqdm(range(n_opt)): dm_tot(i, dm_mw) # Save results to database dm_mw = dm_mw.astype(np.float32) r = np.concatenate((options, dm_mw[:, np.newaxis]), axis=1) results = map(tuple, r.tolist()) pprint(' - Saving results') c.executemany('insert into dm values (?,?,?)', results) # Make for easier searching c.execute('create index ix on dm (gl, gb)') # Save conn.commit() pprint('Finished DM table')
...as in converting coordinates, calculating DM etc. """ import ctypes as C import csv import math import os import random import numpy as np from frbpoppy.paths import paths from frbpoppy.log import pprint # Import fortran libraries uni_mods = os.path.join(paths.models(), 'universe/') dm_mods = os.path.join(paths.models(), 'dm/') loc = os.path.join(dm_mods, 'libne2001.so') ne2001lib = C.CDLL(loc) ne2001lib.dm_.restype = C.c_float def frac_deg(ra, dec): """Convert coordinates expressed in hh:mm:ss to fractional degrees.""" # Inspired by Joe Filippazzo calculator rh, rm, rs = [float(r) for r in ra.split(':')] ra = rh*15 + rm/4 + rs/240 dd, dm, ds = [float(d) for d in dec.split(':')] if dd < 0: sign = -1 else: