def sidlst_to_csd(sid, lst, sid_ref, t_ref): """ Convert an integer DRAO sidereal day and LST to a float CHIME sidereal day Parameters ---------- sid : int DRAO sidereal day lst : float, in hours local sidereal time sid_ref : int DRAO sidereal day at the reference time t_ref t_ref : skyfield time object, Julian days Reference time Returns ------- output : float CHIME sidereal day """ csd_ref = int( ephemeris.csd(ephemeris.datetime_to_unix( t_ref.utc_datetime()))) csd = sid - sid_ref + csd_ref return csd + lst / ephemeris.SIDEREAL_S / 24.0
def __init__(self): super(FilterExisting, self).__init__() self.csd_list = [] self.corr_files = {} if mpiutil.rank0: # Look for CSDs in the current directory import glob files = glob.glob("*") if self.existing_csd_regex: for file_ in files: mo = re.search(self.existing_csd_regex, file_) if mo is not None: self.csd_list.append(int(mo.group(1))) # Search the database to get the start and end times of all correlation files from chimedb import data_index as di from chimedb.core import connect from ch_util import ephemeris connect() query = (di.ArchiveFile.select( di.ArchiveAcq.name, di.ArchiveFile.name, di.CorrFileInfo.start_time, di.CorrFileInfo.finish_time, ).join(di.ArchiveAcq).switch(di.ArchiveFile).join(di.CorrFileInfo)) for acq, fname, start, finish in query.tuples(): if start is None or finish is None: continue start_csd = ephemeris.csd(start) finish_csd = ephemeris.csd(finish) name = os.path.join(acq, fname) self.corr_files[name] = (start_csd, finish_csd) self.log.debug("Skipping existing CSDs %s", repr(self.csd_list)) # Broadcast results to other ranks self.corr_files = mpiutil.world.bcast(self.corr_files, root=0) self.csd_list = mpiutil.world.bcast(self.csd_list, root=0)
def add_file(self, filename): # Make sure this file is not currently in the transit tracker if self.contains_file(filename): return # Read file time range with h5py.File(filename, 'r') as handler: timestamp = handler['index_map']['time']['ctime'][:] timestamp0 = np.median(timestamp) # Convert to right ascension ra = ephemeris.lsa(timestamp) csd = ephemeris.csd(timestamp) # Loop over available sources for name, src in self.iteritems(): src_ra, src_dec = ephemeris.object_coords(src.body, date=timestamp0, deg=True) src_ra = (src_ra + src.shift) % 360.0 # Determine if any times in this file fall # in a window around transit of this source hour_angle = ra - src_ra hour_angle = hour_angle + 360.0 * (hour_angle < -180.0) - 360.0 * ( hour_angle > 180.0) good_time = np.flatnonzero(np.abs(hour_angle) < src.window) if good_time.size > 0: # Determine the csd for the transit contained in this file icsd = np.unique( np.floor(csd[good_time] - (hour_angle[good_time] / 360.0))) if icsd.size > 1: RuntimeError("Error estimating CSD.") key = int(icsd[0]) min_ha, max_ha = np.percentile(hour_angle, [0, 100]) # Add to list of files to analyze for this source if key in src.files: src.files[key].append((filename, hour_angle)) src.file_span[key][0] = min(min_ha, src.file_span[key][0]) src.file_span[key][1] = max(max_ha, src.file_span[key][1]) else: src.files[key] = [(filename, hour_angle)] src.file_span[key] = [min_ha, max_ha]
def test_csd(): """Test CHIME sidereal day definition.""" # csd_zero = 1384489290.908534 # csd_zero = 1384489290.224582 csd_zero = 1384489291.0995445 et1 = ephemeris.datetime_to_unix(datetime(2013, 11, 14)) # Check the zero of CSD (1e-7 accuracy ~ 10 milliarcsec) assert ephemeris.csd(csd_zero) == approx(0.0, abs=1e-6) # Check that the fractional part is equal to the transit RA assert (360.0 * (ephemeris.csd(et1) % 1.0)) == approx( ephemeris.chime.unix_to_lsa(et1), abs=1e-7 ) # Check a specific precalculated CSD csd1 = -1.1848449724498247 assert ephemeris.csd(et1) == approx(csd1, abs=1e-7) # Check vectorization test_args = np.array([csd_zero, et1]) test_ans = np.array([0.0, csd1]) assert ephemeris.csd(test_args) == approx(test_ans, abs=1e-7)
def setup(self, files): """Divide the list of files up into sidereal days. Parameters ---------- files : list List of files to load. """ self.files = files filemap = None if self.comm.rank == 0: se_times = get_times(self.files) se_csd = ephemeris.csd(se_times) days = np.unique(np.floor(se_csd).astype(np.int)) # Construct list of files in each day filemap = [(day, _days_in_csd(day, se_csd, extra=self.padding)) for day in days] # Filter our days with only a few files in them. filemap = [(day, dmap) for day, dmap in filemap if dmap.size > 1] filemap.sort() self.filemap = self.comm.bcast(filemap, root=0) # Set up frequency selection. if self.freq_physical: basefreq = np.linspace(800.0, 400.0, 1024, endpoint=False) self.freq_sel = sorted( set([ np.argmin(np.abs(basefreq - freq)) for freq in self.freq_physical ])) elif self.channel_range and (len(self.channel_range) <= 3): self.freq_sel = list(range(*self.channel_range)) elif self.channel_index: self.freq_sel = self.channel_index else: self.freq_sel = None
def view(self): if self.lsd is None: return panel.pane.Markdown("No data selected.") try: sens_container = self.data.load_file(self.revision, self.lsd, "sensitivity") except DataError as err: return panel.pane.Markdown( f"Error: {str(err)}. Please report this problem.") # Index map for ra (x-axis) sens_csd = csd(sens_container.time) index_map_ra = (sens_csd - self.lsd.lsd) * 360 axis_name_ra = "RA [degrees]" # Index map for frequency (y-axis) index_map_f = np.linspace(800.0, 400.0, 1024, endpoint=False) axis_name_f = "Frequency [MHz]" # Apply data selections if self.polarization == self.mean_pol_text: sel_pol = np.where((sens_container.index_map["pol"] == "XX") | (sens_container.index_map["pol"] == "YY"))[0] sens = np.squeeze(sens_container.measured[:, sel_pol]) sens = np.squeeze(np.nanmean(sens, axis=1)) else: sel_pol = np.where( sens_container.index_map["pol"] == self.polarization)[0] sens = np.squeeze(sens_container.measured[:, sel_pol]) if self.flag_mask: sens = np.where(self._flags_mask(index_map_ra).T, np.nan, sens) # Set flagged data to nan sens = np.where(sens == 0, np.nan, sens) if self.mask_rfi: try: rfi_container = self.data.load_file(self.revision, self.lsd, "rfi") except DataError as err: return panel.pane.Markdown( f"Error: {str(err)}. Please report this problem.") rfi = np.squeeze(rfi_container.mask[:]) # calculate percentage masked to print later rfi_percentage = round(np.count_nonzero(rfi) / rfi.size * 100) sens *= np.where(rfi, np.nan, 1) if self.divide_by_estimate: estimate = np.squeeze(sens_container.radiometer[:, sel_pol]) if self.polarization == self.mean_pol_text: estimate = np.squeeze(np.nanmean(estimate, axis=1)) estimate = np.where(estimate == 0, np.nan, estimate) sens = sens / estimate if self.transpose: sens = sens.T index_x = index_map_f index_y = index_map_ra axis_names = [axis_name_f, axis_name_ra] xlim, ylim = self.ylim, self.xlim else: index_x = index_map_ra index_y = index_map_f axis_names = [axis_name_ra, axis_name_f] xlim, ylim = self.xlim, self.ylim image_opts = { "clim": self.colormap_range, "logz": self.logarithmic_colorscale, "cmap": process_cmap("viridis", provider="matplotlib"), "colorbar": True, "xticks": [0, 60, 120, 180, 240, 300, 360], } if self.mask_rfi: image_opts["title"] = f"RFI mask: {rfi_percentage}%" overlay_opts = { "xlim": xlim, "ylim": ylim, } # Fill in missing data img = hv_image_with_gaps(index_x, index_y, sens, opts=image_opts, kdims=axis_names).opts(**overlay_opts) if self.serverside_rendering is not None: # set colormap cmap_inferno = copy.copy(matplotlib_cm.get_cmap("viridis")) # Set z-axis normalization (other possible values are 'eq_hist', 'cbrt'). if self.logarithmic_colorscale: normalization = "log" else: normalization = "linear" # datashade/rasterize the image img = self.serverside_rendering( img, cmap=cmap_inferno, precompute=True, x_range=xlim, y_range=ylim, normalization=normalization, # TODO: set xticks like above ) if self.mark_day_time: # Calculate the sun rise/set times on this sidereal day # Start and end times of the CSD start_time = csd_to_unix(self.lsd.lsd) end_time = csd_to_unix(self.lsd.lsd + 1) times, rises = chime.rise_set_times( skyfield_wrapper.ephemeris["sun"], start_time, end_time, diameter=-10, ) sun_rise = 0 sun_set = 0 for t, r in zip(times, rises): if r: sun_rise = (unix_to_csd(t) % 1) * 360 else: sun_set = (unix_to_csd(t) % 1) * 360 # Highlight the day time data opts = { "color": "grey", "alpha": 0.5, "line_width": 1, "line_color": "black", "line_dash": "dashed", } span = hv.HSpan if self.transpose else hv.VSpan if sun_rise < sun_set: img *= span(sun_rise, sun_set).opts(**opts) else: img *= span(self.xlim[0], sun_set).opts(**opts) img *= span(sun_rise, self.xlim[-1]).opts(**opts) img.opts( # Fix height, but make width responsive height=self.height, responsive=True, bgcolor="lightgray", shared_axes=True, ) return panel.Row(img, width_policy="max")