def test_startup_and_shutdown(): # Create an agent that throws an exception when it receives # a payload command packet. a = Agent() a.bind_udp_sockets() a.service_handler["Payload Command"] = Agent.raise_exception # Run agent. t = threading.Thread(target=Agent.run, args=(a,)) t.daemon = True t.start() # Send an ACK packet p = Packet() p.service = Supernova.service_id("Payload Command") p.dest_node = Supernova.get_my_id() p.ack = 1 Send.send_to_self(p) # Wait for and then assert that thread has *not* exited. t.join(0.01) assert t.is_alive() # Send a payload command packet -- SHUTDOWN p = Packet() p.service = Supernova.service_id("Payload Command") p.dest_node = Supernova.get_my_id() Send.send_to_self(p) # Wait for and then assert that thread has exited. t.join(0.01) assert not t.is_alive()
def send(packet): """Transmit a packet Args: packet : a ready-to-send Packet instance. Returns: Nothing """ if not isinstance(packet, Packet): raise TypeError("Expected a Packet object") # If the packet were too large, we'd need to split it. TODO. assert packet.data_len <= Packet.MAX_DATA_SIZE # Serialize the packet (including all headers and data) into a buffer of raw bytes buf = packet.serialize() if Send.ENABLE_TRACE: Send.TRACE_QUEUE.appendleft(buf) # Configure UDP socket to send to the bus sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # OK, send it!!! service_name = Supernova.SERVICES[packet.service-1] sock.sendto(buf, (Supernova.controller_ip(packet.src_node), Supernova.service_send_port(service_name, packet.src_node))) # Close socket sock.close()
def test_timeout(): # Create an agent that throws an exception when it receives # a payload command packet. a = Agent() a.bind_udp_sockets() a.service_handler["Payload Command"] = Agent.raise_exception # Set a timeout that is << delay. Agent.TIMEOUT = 0.005 # Run agent. t = threading.Thread(target=Agent.run, args=(a,)) t.daemon = True t.start() # Delay time.sleep(0.02) # Send a payload command packet -- SHUTDOWN p = Packet() p.service = Supernova.service_id("Payload Command") p.dest_node = Supernova.get_my_id() Send.send_to_self(p) # Wait for and then assert that thread has exited. t.join(0.01) assert not t.is_alive()
def test_socket_bind_error(): # Block socket sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) sock.bind((Supernova.payload_ip(Supernova.get_my_id()), Supernova.service_recv_port("Payload Command", Supernova.get_my_id())) ) a = Agent() a.bind_udp_sockets() # will fail gracefully a.close() sock.close()
def bind_udp_sockets(self): """ Bind UDP sockets to appropriate ports Effects: self.supernova_sock : set to a dict of interface names -> socket instances """ for i in Supernova.SERVICES: self.service_sock[i] = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) try: self.service_sock[i].bind((Supernova.payload_ip(self.payload_id), Supernova.service_recv_port(i, self.payload_id))) except Exception as e: print("Error binding socket for %s service: %s\n" % (i, repr(e)))
def print_it(packet): if packet.service == Supernova.service_id("Telemetry Packet"): tp = TelemetryPacket(packet) tp.deserialize() tp.printout() else: print("=== Begin ===") print(packet.data) print("=== End ===")
def test_handlers(): p = Packet() Agent.do_nothing(None) Agent.print_it(p) p.service = Supernova.service_id("Telemetry Packet") p.pkt_id = 113 p.data_len = 247 p.data = bytearray(247) Agent.print_it(p)
def send_payload_cmd(dest_payload_id, command, data): if isinstance(data, bytes) or isinstance(data, bytearray): data_len = len(data) elif data == None: data_len = 0 else: raise TypeError("Data argument is not an array of bytes") if data_len > Packet.MAX_DATA_SIZE: raise ValueError("Data length too long. TODO") p = Packet() # empty packet # --- Primary header # This is a bus command p.service = Supernova.service_id("Payload Command") p.dst_node = dest_payload_id p.pkt_type = 1 # 0: telemetry, 1: command # It's a single packet, so set the sequence flags appropriately. # TODO: support packet sequences p.seq_count = 0x00 # first (and last) packet p.seq_flags = 0x03 # first and last packet p.pkt_id = command # --- Secondary header p.scid = 0 # Spacecraft ID p.checksum_valid = 0x01 # Yes, valid (of course) p.ack = 0 # No, not an ACK p.auth_count = 0 # ??? p.pkt_subtype = 0x00 # Unused p.src_node = Supernova.get_my_id() p.pkt_subid = 0x00 # Unused p.byp_auth = 0x01 # Bypass authentication # --- Data p.data_len = data_len p.data = data Send.send(p)
def from_name(self, sn_name, band, tstart, scale, sn_info=[], model='Chev94', **kwargs): """Generate Injection instance from a supernova name and GALEX band, also creating a Supernova and LightCurve object in the process.""" sn = Supernova(sn_name, sn_info=sn_info) lc = LightCurve(sn, band, sed=model) return Injection(sn, lc, tstart, scale, **kwargs)
def __init__(self): """ Initialize an Agent object All service handlers are initially set to do nothing. """ self.payload_id = Supernova.get_my_id() self.service_sock = {} # Service handler functions. # Map of service name to method. self.service_handler = { "Payload Command" : Agent.do_nothing, "Payload Telemetry" : Agent.do_nothing, "Bus Command" : Agent.do_nothing, "Telemetry Packet" : Agent.do_nothing, "Telemetry Stream" : Agent.do_nothing, "Data Storage" : Agent.do_nothing, "Data Downlink" : Agent.do_nothing, "Data Upload" : Agent.do_nothing, "Time" : Agent.do_nothing, }
def send_to_self(packet): """ Transmit a packet to self. This is for testing purposes. Args: packet : a ready-to-send Packet instance. Returns: Nothing """ # Serialize the packet (including all headers and data) into a buffer of raw bytes buf = packet.serialize() # Configure UDP socket to send to the bus sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # OK, send it!!! service_name = Supernova.SERVICES[packet.service-1] sock.sendto(buf, ('127.0.0.1', Supernova.service_recv_port(service_name, packet.dest_node))) # Close socket sock.close()
def main(): sn_info = pd.read_csv(Path('ref/sn_info.csv'), index_col='name') det_sne = ['SN2007on', 'SN2008hv', 'SN2009gf', 'SN2010ai'] x_col = 't_delta_rest' y_col = 'luminosity_hostsub' yerr_col = 'luminosity_hostsub_err' fig, ax = plt.subplots(figsize=(6.5, 5), tight_layout=True) # Plot Swift SN2011fe from Brown+ 2012 band = 'UVM2' disc_date = Time('2011-08-24', format='iso').mjd dist = 6.4 * u.Mpc #from Shappee & Stanek 2011 dist_err = 0. * u.Mpc z = 0 # too close to need correction z_err = 0 a_v = 0 # won't worry about it right now a_band = 'NUV' # close enough wl_eff = effective_wavelength(band).value # UVM2 effective wavelength lc = import_swift('SN2011fe', disc_date, z) lc = lc[lc['Filter'] == band] lc['luminosity'], lc['luminosity_err'] = flux2luminosity( lc['flux'], lc['flux_err'], dist, dist_err, z, z_err, a_v, a_band) ax.plot(lc['t_delta_rest'], wl_eff * lc['luminosity'], color='brown', label='SN2011fe (%s)' % band, zorder=1, lw=2, rasterized=True) # Import and plot HST non-detections print('Importing HST non-detections...') hst_data = pd.read_csv(Path('ref/Graham_observations.csv'), index_col=0) wl_eff = effective_wavelength('F275W').value nondetections = hst_data[hst_data['Detection'] == False] for i, sn_name in enumerate(nondetections.index): obs = GrahamObservation(sn_name, hst_data) ax.scatter(obs.rest_phase, wl_eff * obs.luminosity_limit, marker='v', s=MS_HST**2, color='w', edgecolors=COLORS['F275W'], alpha=ALPHA_NON, zorder=3, rasterized=True) # Plot near-peak SNe Ia for sn_name in det_sne: sn = Supernova(sn_name, sn_info) band = 'NUV' lc = LightCurve(sn, band) lc.to_hz() # Convert to erg/s/Hz units # Effective filter frequency # nu_eff = (const.c / effective_wavelength(band)).to('Hz').value wl_eff = effective_wavelength(band).value # Plot near-peak detections detections = lc.detect_csm(DET_SIGMA, count=DET_COUNT) # ax.errorbar(detections[x_col], nu_eff * detections[y_col], # yerr=nu_eff * detections[yerr_col], label='%s (%s)' % (sn.name, band), # linestyle='none', ms=MS_DET, marker=MARKERS[sn.name], # color=COLORS[sn.name], mec='k', ecolor='k', elinewidth=1, # zorder=9, rasterized=True) ax.errorbar(detections[x_col], wl_eff * detections[y_col], yerr=wl_eff * detections[yerr_col], label='%s (%s)' % (sn.name, band), linestyle='none', ms=MS_DET, marker=MARKERS[sn.name], color=COLORS[sn.name], mec='k', ecolor='k', elinewidth=1, zorder=9, rasterized=True) # Plot non-detection limits print('Importing GALEX detections and limits...') for sn_name in tqdm(sn_info.index): sn = Supernova(sn_name, sn_info) for band in ['FUV', 'NUV']: try: plot_nondetection_limits(ax, sn, band, x_col, yerr_col, ymax=YLIM[1]) except (FileNotFoundError, pd.errors.EmptyDataError): continue # Import and plot HST detections print('Importing HST detections...') wl_eff = effective_wavelength('F275W').value detections = hst_data[hst_data['Detection']] markers = ['X', '*'] colors = ['y', 'r'] sizes = [64, 81] for i, sn_name in enumerate(detections.index): obs = GrahamObservation(sn_name, hst_data) ax.scatter(obs.rest_phase, wl_eff * obs.luminosity, marker=markers[i], color=colors[i], edgecolors='k', label='%s (F275W)' % sn_name, zorder=10, s=sizes[i]) print('Plotting...') # Format axes ax.set_xlabel('Time since discovery [rest-frame days]', size=12) ax.set_ylabel('$\\lambda L_\\lambda$ [erg s$^{-1}$]', size=12) ax.set_xlim(XLIM) ax.set_yscale('log') ax.set_ylim(YLIM) # Legend handles, labels = ax.get_legend_handles_labels() legend_elements = [ Line2D([0], [0], marker='v', markerfacecolor='w', markeredgecolor=COLORS['F275W'], markersize=MS_HST, alpha=ALPHA_NON, label='detection limit (F275W)', lw=0), Line2D([0], [0], marker='v', markerfacecolor=COLORS['FUV'], markeredgecolor='none', markersize=MS_GALEX, alpha=ALPHA_NON, label='detection limit (FUV)', lw=0), Line2D([0], [0], marker='v', markerfacecolor=COLORS['NUV'], markeredgecolor='none', markersize=MS_GALEX, alpha=ALPHA_NON, label='detection limit (NUV)', lw=0) ] plt.legend(handles=handles + legend_elements, loc='lower center', ncol=3, handletextpad=0.5, handlelength=1.0, bbox_to_anchor=(0.5, 1.01)) plt.savefig(Path('out/limits.pdf'), dpi=300) plt.savefig(Path('out/limits.png'), dpi=300) plt.show()
SIGMA = [5, 3] SIGCOUNT = [1, 3] L_15cp = 7.6e25 # erg/s/Hz L_nu = L_15cp * 3e18 / effective_wavelength('F275W').value # erg/s sn_info = pd.read_csv(Path('ref/sn_info.csv'), index_col='name') detections = [] total_epochs = 0 bg_epochs = 0 post_epochs = 0 below_15cp = 0 for sn_name in tqdm(sn_info.index): sn = Supernova(sn_name, sn_info) below_15cp_val = 0 for band in ['FUV', 'NUV']: try: lc = LightCurve(sn, band) except (FileNotFoundError, pd.errors.EmptyDataError): continue # Count observation epochs total_epochs += lc.data.shape[0] bg_epochs += lc.bg_data.shape[0] post_epochs += lc.data[lc.data['t_delta_rest'] > 0].shape[0] det = lc.detect_csm(SIGMA, SIGCOUNT)
def from_name(self, sn_name, band, sn_info=[], **kwargs): """Initialize LightCurve from SN name rather than Supernova instance.""" sn = Supernova(sn_name, sn_info=sn_info, ref_file=REF_FILE) return LightCurve(sn, band, **kwargs)
def main(sn_name, make_plot=False, sigma=SIGMA, count=SIGMA_COUNT, tmax=4000, pad=0, swift=False, cfa=False, legend_col=3, all_points=False): # sn_info = pd.read_csv(Path('ref/sn_info.csv'), index_col='name') sn_info = pd.read_csv(REF_FILE, index_col='name') sn = Supernova(sn_name, sn_info=sn_info, ref_file=REF_FILE) detect_cols = [ 't_delta_rest', 'flux_hostsub', 'flux_hostsub_err', 'luminosity_hostsub', 'luminosity_hostsub_err' ] limit_cols = ['t_delta_rest', 'flux_limit', 'luminosity_limit'] for band in ['FUV', 'NUV']: print('\n%s DATA' % band) try: lc = LightCurve.from_name(sn_name, band) print('Background: %s +/- %s erg/s/cm^2/AA' % (lc.bg, lc.bg_err_tot)) print('Background obs: %s' % lc.bg_data.shape[0]) # Display detections print('Detections:') detections = lc.detect_csm(sigma, count=count) if len(detections.index) == 0: print('None.') else: print(detections[detect_cols]) # Display upper limits print('Upper limits:') upper_lims = pd.DataFrame([]) upper_lims['t_delta_rest'] = lc('t_delta_rest') upper_lims['flux_bgsub'] = lc('flux_bgsub') upper_lims['flux_limit'] = lc('flux_hostsub_err') * DET_SIGMA upper_lims['luminosity_limit'] = lc( 'luminosity_hostsub_err') * DET_SIGMA print(upper_lims[upper_lims['t_delta_rest'] > 0]) print('Flux mean:', np.mean(upper_lims['flux_bgsub'])) print('Flux stdev:', np.std(upper_lims['flux_bgsub'])) print('Flux RMS:', np.sqrt(np.mean(upper_lims['flux_bgsub']**2))) except FileNotFoundError: print('No data available.') if make_plot: print('\nPlotting %s...' % sn.name) plot(sn, tmax=tmax, pad=pad, swift=swift, cfa=cfa, legend_col=legend_col, all_points=all_points)
def run_all(supernovae, iterations, tstart_lims, scale_lims, sn_info=[], overwrite=False, model='Chev94', save_dir=SAVE_DIR, **kwargs): """Run injection recovery trials on all supernovae in given list. Inputs: supernovae: list of supernova names iterations: iterations of injection & recovery for each SN tstart_lims: tuple or list of bounds on start time scale_lims: tuple or list of bounds on scale factor sn_info: supernova info reference DataFrame overwrite: bool, whether to overwrite previous save files kwargs: keyword arguments for run_trials """ # Remove SNe with previous save files from list if not overwrite: supernovae = [ s for s in supernovae if not check_save(s, iterations, save_dir=save_dir) ] for i, sn_name in enumerate(supernovae): print('\n%s [%s/%s]' % (sn_name, i + 1, len(supernovae))) # Initialize SN object sn = Supernova(sn_name, sn_info=sn_info) # Import light curves lcs = [] for band in ['FUV', 'NUV']: try: lc = LightCurve(sn, band, data_dir=DATA_DIR, sed=model) except: # No data for this channel continue # Skip if no data after minimum recovery time if np.max(lc.data['t_delta_rest']) < RECOV_MIN: print( '\tno %s data after minimum %s days past discovery, skipping' % (band, RECOV_MIN)) continue lcs.append(lc) # If light curve import was unsuccessful if len(lcs) == 0: print('\tno data available!') continue run_trials(sn, lcs, iterations, tstart_lims, scale_lims, model=model, save_dir=save_dir, **kwargs)
def from_file(self, fname, **kwargs): """Initialize LightCurve from file name.""" sn_name, self.band = fname2sn(fname) sn = Supernova(sn_name, ref_file=REF_FILE) return LightCurve(sn, self.band, **kwargs)