def test_low_dec(self): with open(datapaths.swift_bat_grb_pos_v2) as f: good_src = voeventparse.load(f) with open(datapaths.swift_bat_grb_low_dec) as f: bad_src = voeventparse.load(f) good_fk5 = convert_voe_coords_to_eqposn( voeventparse.get_event_position(good_src)) bad_fk5 = convert_voe_coords_to_eqposn( voeventparse.get_event_position(bad_src)) self.assertIsNone(filters.ami.reject(good_fk5)) self.assertIsNotNone(filters.ami.reject(bad_fk5))
def handle_grb(v): ivorn = v.attrib['ivorn'] TrigID = v.find(".//Param[@name='TrigID']").attrib['value'] web_link = 'https://gcn.gsfc.nasa.gov/other/' + TrigID + '.swift' grb_length = is_short(v) # Work out if it is short or long: if grb_length == 'short': coords = voeventparse.pull_astro_coords(v) c = voeventparse.get_event_position(v) if c.dec > 15.0: send_telegram("GRB above declination cutoff of +15 degrees " + web_link) #send_mail("GRB above declination cutoff of +15 degrees "+web_link, "Short GRB above Dec cutoff") else: os.system('python schedule_atca.py ' + str(c.ra) + ' ' + str(c.dec) + ' ' + web_link + ' ' + 'SHORT_GRB') n = Notifier() n.send_notification(title="SWIFT Short GRB >> TRIGGERING!", text="Coords are {}".format(coords)) send_telegram("SHORT GRB TRIGGERING " + web_link) if grb_length == 'mid': coords = voeventparse.pull_astro_coords(v) c = voeventparse.get_event_position(v) if c.dec > 15.0: send_telegram("GRB above declination cutoff of +15 degrees " + web_link) #send_mail("GRB above declination cutoff of +15 degrees "+web_link, "Mid GRB above Dec cutoff") else: n = Notifier() n.send_notification(title="SWIFT Mid GRB >> ON HOLD!", text="Coords are {}".format(coords)) #mid_grb_email('Please check:'+web_link, "Mid duration GRB", str(c.ra), str(c.dec)) send_telegram('Please check:' + web_link + " Mid duration GRB RA=" + str(c.ra) + ' DEC=' + str(c.dec)) # Send out SMS #send_SMS(c.ra, c.dec, web_link, subject='Mid GRB') if grb_length == 'long': #send_mail("Long GRB not triggering "+web_link, "Long GRB") send_telegram("Long GRB not triggering " + web_link) if grb_length == 'mag': coords = voeventparse.pull_astro_coords(v) c = voeventparse.get_event_position(v) if c.dec > 15.0: send_telegram( "GRB / Magnetar above declination cutoff of +15 degrees " + web_link) else: n = Notifier() n.send_notification(title="SWIFT / Magnetar >> ON HOLD!", text="Coords are {}".format(coords)) send_telegram('Please check:' + web_link + " Magnetar RA=" + str(c.ra) + ' DEC=' + str(c.dec))
def handle_flare_star(v): n = Notifier() ivorn = v.attrib['ivorn'] name_not_used, tel = get_name(v) name = get_flare_name(v) if tel == "SWIFT": TrigID = v.find(".//Param[@name='TrigID']").attrib['value'] web_link = 'https://gcn.gsfc.nasa.gov/other/' + TrigID + '.swift' if tel == "MAXI": TrigID = v.find(".//Param[@name='TrigID']").attrib['value'] web_link = 'https://gcn.gsfc.nasa.gov/other/8' + TrigID + '.maxi' #web_link = 'http://gcn.gsfc.nasa.gov/maxi.html' coords = voeventparse.pull_astro_coords(v) c = voeventparse.get_event_position(v) sub = vp.prettystr(v.What.Description) if "The sub-sub-threshold Swift-BAT trigger position notice" in sub: #send_mail("Flare Star "+name+" sub-sub threshold trigger", "Not triggering") send_telegram("Flare Star " + name + " sub-sub threshold trigger", "Not triggering") n.send_notification(title="Flare Star " + name + " sub-sub threshold burst ", text="Coords are {}".format(coords)) else: ra = get_flare_RA(name) dec = get_flare_DEC(name) n.send_notification(title="Flare Star " + name + " Detected >> TRIGGERING!", text="Coords are {}".format(coords)) os.system('python schedule_atca.py ' + str(ra) + ' ' + str(dec) + ' ' + web_link + ' ' + tel)
def __init__(self, voevent, alert_notification_period=None): self.voevent = voevent self.ivorn = self.voevent.attrib['ivorn'] self.alert_notification_period = alert_notification_period if self.alert_notification_period is None: self.alert_notification_period = default_alert_notification_period if not GaiaAlert.packet_type_matches(voevent): raise ValueError( "Cannot instantiate GaiaAlert; packet header mismatch.") group_params = voeventparse.get_grouped_params(self.voevent) text_params_grp = group_params[GaiaFeed.text_params_groupname] self.text_params = OrderedDict( (k, d['value']) for k, d in text_params_grp.items()) self.id = self.text_params.get('Name') self.inferred_name = False self.isotime = voeventparse.get_event_time_as_utc(self.voevent) self.position = convert_voe_coords_to_eqposn( voeventparse.get_event_position(self.voevent)) self.url_params = { 'GSA':'http://gsaweb.ast.cam.ac.uk/alerts/alert/'+self.id}
def __init__(self, voevent, alert_notification_period=None): self.voevent = voevent self.ivorn = self.voevent.attrib['ivorn'] self.alert_notification_period = alert_notification_period if self.alert_notification_period is None: self.alert_notification_period = default_alert_notification_period if not AsassnAlert.packet_type_matches(voevent): raise ValueError( "Cannot instantiate AsassnAlert; packet header mismatch.") group_params = voeventparse.get_grouped_params(self.voevent) text_params_grp = group_params[AsassnFeed.text_params_groupname] self.text_params = OrderedDict( (k, d['value']) for k, d in text_params_grp.items()) url_params_grp = group_params[AsassnFeed.url_params_groupname] self.url_params = OrderedDict( (k, d['value']) for k, d in url_params_grp.items()) self.id = self.text_params.get(AsassnKeys.id_asassn) if self.id is None: self.id = self.text_params.get(AsassnKeys.id_other) # Assigned name according to the 'why' section of voevent packet: self.inferred_name = 'ASASSN @ ' + self.text_params.get( AsassnKeys.detection_timestamp) self.isotime = voeventparse.get_event_time_as_utc(self.voevent) self.position = convert_voe_coords_to_eqposn( voeventparse.get_event_position(self.voevent))
def test_get_event_position(self): known_swift_grb_posn = vp.Position2D(ra=74.741200, dec=-9.313700, err=0.05, units='deg', system='UTC-FK5-GEO') p = vp.get_event_position(self.swift_grb_v2_packet) self.assertEqual(p, known_swift_grb_posn) self.assertIsInstance(p.ra, float)
def from_etree(root): """ Load up the coords, if present, for initializing with the Voevent. .. note:: Current implementation is quite slack with regard to co-ordinate systems - it is assumed that, for purposes of searching the database using spatial queries, the FK5 / ICRS reference systems and and geocentric/barycentric reference frames are sufficiently similar that we can just take the RA/Dec and insert it 'as-is' into the database. This is partly justified on the assumption that anyone in need of ultra-high precision co-ordinates will need to take account of mission specific properties anyway (e.g. position of GAIA at time of detection) and so will only be using the spatial query for a coarse search, then parsing packets to determine precise locations. """ acceptable_coord_systems = ( vp.definitions.sky_coord_system.utc_fk5_geo, vp.definitions.sky_coord_system.utc_fk5_topo, vp.definitions.sky_coord_system.utc_icrs_geo, vp.definitions.sky_coord_system.utc_icrs_topo, vp.definitions.sky_coord_system.tdb_fk5_bary, vp.definitions.sky_coord_system.tdb_icrs_bary, ) position_list = [] astrocoords = root.xpath( 'WhereWhen/ObsDataLocation/ObservationLocation/AstroCoords') if astrocoords: for idx, entry in enumerate(astrocoords): posn = vp.get_event_position(root, idx) if posn.system not in acceptable_coord_systems: raise NotImplementedError( "Loading position from coord-sys " "is not yet implemented: {} ".format(posn.system)) if posn.units != vp.definitions.units.degrees: raise NotImplementedError( "Loading positions in formats other than degrees " "is not yet implemented.") try: isotime = vp.get_event_time_as_utc(root, idx) except: logger.warning("Error pulling event time for ivorn {}, " "setting to NULL".format( root.attrib['ivorn'])) isotime = None position_list.append( Coord(ra=posn.ra, dec=posn.dec, error=posn.err, time=isotime)) return position_list
def get_coord(v, coordname): ''' Get coordinate from VOEvent file. - transform to HH:MM:SS if coordname=ra - transform to DD:HH:SS if coordname=dec :param v: VOEvent xml :param coordname: coordinate name ('ra' or 'dec') :type v: lxml.objectify.ObjectifiedElement :type coordname: str :returns: location string in HH:MM:SS.MS for coordname=ra or DD:HH:SS.MS for coordname=dec :rtype: str ''' try: units = getattr(vp.get_event_position(v, index=0), 'units') except AttributeError: return None if not (units == 'deg'): raise AttributeError( 'Unable to determine units for position: {}'.format( vp.get_event_position(v, index=0))) position = vp.get_event_position(v, index=0) if (position.system == 'UTC-FK5-GEO'): skcoord = SkyCoord(ra=position.ra * u.degree, dec=position.dec * u.degree, frame='fk5') else: # use default reference frame skcoord = SkyCoord(ra=position.ra * u.degree, dec=position.dec * u.degree) if (coordname == 'ra'): # ra location is in hms coordloc = skcoord.ra.hms elif (coordname == 'dec'): # dec location is in dms coordloc = skcoord.dec.dms # format location tuple to string locstring = '{}:{}:{}'.format( str(int(round(coordloc[0]))).zfill(2), str(abs(int(round(coordloc[1])))).zfill(2), "{:.2f}".format(abs(coordloc[2])).zfill(5)) return locstring
def test_spatial_query(self, fixture_db_session): s = fixture_db_session posn = vp.get_event_position(swift_bat_grb_655721) # Cone search centred on the known co-ords should return the row: results = s.query(Coord).filter( coord_cone_search_clause(posn.ra, posn.dec, 0.5)).all() assert len(results) == 1 # Now bump the cone to the side (so not matching) and check null return results = s.query(Coord).filter( coord_cone_search_clause(posn.ra, posn.dec + 1.0, 0.5)).all() assert len(results) == 0
def __init__(self, payload): super().__init__(payload) # Get XML param dicts # NB: you can't store these on the Event because they're unpickleable. top_params = vp.get_toplevel_params(self.voevent) # group_params = vp.get_grouped_params(self.voevent) # Default params self.notice = EVENT_DICTIONARY[self.packet_type]['notice_type'] self.type = EVENT_DICTIONARY[self.packet_type]['event_type'] self.source = EVENT_DICTIONARY[self.packet_type]['source'] # Get the run and event ID (e.g. 13311922683750) self.id = top_params['AMON_ID']['value'] # Create our own event name (e.g. ICECUBE_13311922683750) self.name = '{}_{}'.format(self.source, self.id) # Get info from the VOEvent # signalness: the probability this is an astrophysical signal relative to backgrounds self.signalness = float(top_params['signalness']['value']) self.far = float(top_params['FAR']['value']) # Position coordinates self.position = vp.get_event_position(self.voevent) self.coord = SkyCoord(ra=self.position.ra, dec=self.position.dec, unit=self.position.units) self.target = FixedTarget(self.coord) # Position error self.coord_error = Angle(self.position.err, unit=self.position.units) # Systematic error for cascade event is given, so = 0 if self.notice == 'ICECUBE_CASCADE': self.systematic_error = Angle(0, unit='deg') else: self.systematic_error = Angle(.2, unit='deg') self.total_error = Angle(np.sqrt(self.coord_error**2 + self.systematic_error**2), unit='deg') # Enclosed skymap url for CASCADE_EVENT, but others # Get skymap URL if 'skymap_fits' in top_params: self.skymap_url = top_params['skymap_fits']['value'] else: self.skymap_url = None # Don't download the skymap here, it may well be very large. # Only do it when it's absolutely necessary # These params will only be set once the skymap is downloaded self.contour_areas = {0.5: None, 0.9: None}
def test_set_wherewhen(self): tz_aware_timestamp = datetime.datetime.utcnow().replace(tzinfo=pytz.UTC) vp.add_where_when(self.v, coords=self.coords1, obs_time=tz_aware_timestamp, observatory_location=vp.definitions.observatory_location.geosurface) self.assertTrue(vp.valid_as_v2_0(self.v)) self.assertEqual(self.coords1, vp.get_event_position(self.v)) self.assertIsNotNone(vp.get_event_time_as_utc(self.v)) astrocoords = self.v.xpath( 'WhereWhen/ObsDataLocation/ObservationLocation/AstroCoords' )[0] isotime_str = str(astrocoords.Time.TimeInstant.ISOTime) self.assertFalse('+' in isotime_str)
def test_coords_loaded(self, fixture_db_session): s = fixture_db_session n_total_coords = s.query(Coord).count() assert n_total_coords == 1 grb_packet_coords = s.query(Voevent).filter( Voevent.ivorn == swift_bat_grb_655721.attrib['ivorn']).one().coords assert len(grb_packet_coords) == 1 coord0 = grb_packet_coords[0] bat_voevent_id = s.query(Voevent.id).filter( Voevent.ivorn == swift_bat_grb_655721.attrib['ivorn']).scalar() assert coord0.voevent_id == bat_voevent_id position = vp.get_event_position(swift_bat_grb_655721) assert coord0.ra == position.ra assert coord0.dec == position.dec assert coord0.error == position.err
def __init__(self, voevent): self.voevent = voevent self.ivorn = self.voevent.attrib['ivorn'] if not BatGrb.packet_type_matches(voevent): raise ValueError("Cannot instantiate AsassnAlert; packet header mismatch.") id_long_short = self._pull_swift_bat_id() self.id_long = 'SWIFT_' + id_long_short[0] self.id = 'SWIFT_' + id_long_short[1] #Assigned name according to the 'why' section of voevent packet: self.inferred_name = self.voevent.Why.Inference.Name self.isotime = voeventparse.get_event_time_as_utc(self.voevent) self.group_params = voeventparse.get_grouped_params(self.voevent) self.position = convert_voe_coords_to_eqposn( voeventparse.get_event_position(self.voevent)) self.alert_notification_period = False
def test_coords_loaded(self, fixture_db_session): s = fixture_db_session n_total_coords = s.query(Coord).count() assert n_total_coords == 1 grb_packet_coords = s.query(Voevent).filter( Voevent.ivorn == swift_bat_grb_655721.attrib['ivorn'] ).one().coords assert len(grb_packet_coords) == 1 coord0 = grb_packet_coords[0] bat_voevent_id = s.query(Voevent.id).filter( Voevent.ivorn == swift_bat_grb_655721.attrib['ivorn'] ).scalar() assert coord0.voevent_id == bat_voevent_id position = vp.get_event_position(swift_bat_grb_655721) assert coord0.ra == position.ra assert coord0.dec == position.dec assert coord0.error == position.err
def assign_test_client_and_initdb(self, flask_test_client, fixture_db_session): self.c = flask_test_client # Purely for brevity n_packets = 17 packets = heartbeat_packets(n_packets=n_packets) for counter, pkt in enumerate(packets, start=1): packet_dec = 180.0 / n_packets * counter - 90 coords = vp.Position2D( ra=15, dec=packet_dec, err=0.1, units=vp.definitions.units.degrees, system=vp.definitions.sky_coord_system.utc_icrs_geo) # print "Inserting coords", coords vp.add_where_when( pkt, coords=coords, obs_time=iso8601.parse_date(pkt.Who.Date.text), observatory_location=vp.definitions.observatory_location.geosurface ) self.packets = packets self.ivorn_dec_map = {} for pkt in self.packets: posn = vp.get_event_position(pkt) self.ivorn_dec_map[pkt.attrib['ivorn']] = posn.dec fixture_db_session.add(Voevent.from_etree(pkt))
def assign_test_client_and_initdb(self, flask_test_client, fixture_db_session): self.c = flask_test_client # Purely for brevity n_packets = 17 packets = heartbeat_packets(n_packets=n_packets) for counter, pkt in enumerate(packets, start=1): packet_dec = 180.0 / n_packets * counter -90 coords = vp.Position2D( ra=15, dec=packet_dec, err=0.1, units=vp.definitions.units.degrees, system=vp.definitions.sky_coord_system.utc_icrs_geo) # print "Inserting coords", coords vp.add_where_when( pkt, coords=coords, obs_time=iso8601.parse_date(pkt.Who.Date.text), observatory_location=vp.definitions.observatory_location.geosurface ) self.packets = packets self.ivorn_dec_map = {} for pkt in self.packets: posn = vp.get_event_position(pkt) self.ivorn_dec_map[pkt.attrib['ivorn']] = posn.dec fixture_db_session.add(Voevent.from_etree(pkt))
def handler(): """ Convert VOEvent from stdin to parquet file, and store it. The user will have to define the following constants: EVENTDIR: str USEHDFS: bool HOST: str PORT: int USER: str They are stored in the fink_voevent/vo_writer.py file. Usage as a Comet handler: twistd -n comet --verbose --local-ivo=ivo://fink-broker/$(hostname)\ --remote=voevent.4pisky.org --cmd=fink_voevent/vo_writer.py Usage as a standard script: cat a_voevent_from_disk | fink_voevent/vo_writer.py """ # Check if the outdir exists if not vo.check_dir_exist(EVENTDIR, USEHDFS): print("EVENTDIR={} does not exist".format(EVENTDIR)) print("Create it or edit fink_broker/vo_writer.py") sys.exit() # Read the data from the stdin (string) packet_data = sys.stdin.buffer.read() # Load as XML xml_packet_data = voeventparse.loads(packet_data) # Extract the ivorn ivorn = xml_packet_data.attrib['ivorn'] # Skip if the event is a test if not vo.is_observation(xml_packet_data): print('test/utility received - {}'.format(ivorn)) return 0 # Extract information about position and time coords = voeventparse.get_event_position(xml_packet_data) time_utc = str(voeventparse.get_event_time_as_utc(xml_packet_data)) # Store useful information for coincidence in a DataFrame df = pd.DataFrame.from_dict( { 'ivorn': [ivorn], 'ra': [coords.ra], 'dec': [coords.dec], 'err': [coords.err], 'units': [coords.units], 'timeUTC': [time_utc], 'raw_event': packet_data} ) # Filename for the event is based on the ivorn. fn = '{}/{}.parquet'.format(EVENTDIR, vo.string_to_filename(ivorn)) # Get the connector if USEHDFS: fs = vo.get_hdfs_connector(HOST, PORT, USER) else: fs = None vo.write_dataframe(df, outpath=fn, fs=fs) return 0
def handle_flarestar(v, pretend=False): """ Handles the actual VOEvent parsing, generating observations if appropriate. :param v: string in VOEvent XML format :param pretend: Boolean, True if we don't want to actually schedule the observations. :return: None """ ivorn = v.attrib['ivorn'] log.debug("processing Flare Star {0}".format(ivorn)) name = v.Why.Inference.Name trig_id = v.find(".//Param[@name='TrigID']").attrib['value'] c = voeventparse.get_event_position(v) if c.dec > DEC_LIMIT: msg = "Flare Star {0} above declination cutoff of +10 degrees".format( name) log.debug(msg) log.debug("Not triggering") handlers.send_email( from_address='*****@*****.**', to_addresses=DEBUG_NOTIFY_LIST, subject='GRB_fermi_swift debug notification for trigger: %s' % trig_id, msg_text=DEBUG_EMAIL_TEMPLATE % msg, attachments=[('voevent.xml', voeventparse.dumps(v))]) return if trig_id not in xml_cache: fs = FlareStar(event=v) fs.trigger_id = trig_id xml_cache[trig_id] = fs else: fs = xml_cache[trig_id] fs.add_event(v) ra = c.ra dec = c.dec fs.add_pos((ra, dec, 0.)) fs.debug("Flare Star {0} is detected at RA={1}, Dec={2}".format( name, ra, dec)) req_time_min = 30 # look at the schedule obslist = triggerservice.obslist(obstime=1800) if obslist is not None and len(obslist) > 0: fs.debug("Currently observing:") fs.debug(str(obslist)) # are we currently observing *this* GRB? obs = str( obslist[0][1]) # in case the obslist is returning unicode strings fs.debug("obs {0}, trig {1}".format(obs, trig_id)) # Same GRB trigger from same telescope if obs == trig_id: fs.info("already observing this star") fs.info("not triggering again") handlers.send_email( from_address='*****@*****.**', to_addresses=DEBUG_NOTIFY_LIST, subject='GRB_fermi_swift debug notification for trigger: %s' % trig_id, msg_text=DEBUG_EMAIL_TEMPLATE % '\n'.join([str(x) for x in fs.loglist]), attachments=[('voevent.xml', voeventparse.dumps(v))]) return else: fs.debug("Current schedule empty") fs.debug("Triggering") # label as SWIFT or MAXI for the trigger type ttype = v.attrib['ivorn'].split('/')[-1].split('#')[0] emaildict = { 'triggerid': fs.trigger_id, 'trigtime': Time.now().iso, 'ra': Angle(fs.ra[-1], unit=astropy.units.deg).to_string(unit=astropy.units.hour, sep=':'), 'dec': Angle(fs.dec[-1], unit=astropy.units.deg).to_string(unit=astropy.units.deg, sep=':'), 'name': name } email_text = EMAIL_TEMPLATE % emaildict email_subject = EMAIL_SUBJECT_TEMPLATE % fs.trigger_id # Do the trigger result = fs.trigger_observation( ttype=ttype, obsname=trig_id, time_min=req_time_min, pretend=pretend, project_id=PROJECT_ID, secure_key=SECURE_KEY, email_tolist=NOTIFY_LIST, email_text=email_text, email_subject=email_subject, creator='VOEvent_Auto_Trigger: FlareStar_swift_maxi=%s' % __version__, voevent=voeventparse.dumps(v)) if result is None: handlers.send_email( from_address='*****@*****.**', to_addresses=DEBUG_NOTIFY_LIST, subject='GRB_fermi_swift debug notification for trigger: %s' % trig_id, msg_text=DEBUG_EMAIL_TEMPLATE % '\n'.join([str(x) for x in fs.loglist]), attachments=[('voevent.xml', voeventparse.dumps(v))])
# Changing values: v_copy.Who.Author.shortName = 'BillyBob' v_copy.attrib['role'] = voeventparse.definitions.roles.test print("Changes valid? ", voeventparse.valid_as_v2_0(v_copy)) v_copy.attrib['role'] = 'flying circus' print("How about now? ", voeventparse.valid_as_v2_0(v_copy)) print("But the original is ok, because we copied? ", voeventparse.valid_as_v2_0(v)) v.Who.BadPath = "This new attribute certainly won't conform with the schema." assert voeventparse.valid_as_v2_0(v) == False del v.Who.BadPath assert voeventparse.valid_as_v2_0(v) == True ####################################################### # And now, SCIENCE ####################################################### c = voeventparse.get_event_position(v) print("Coords:", c) print() toplevel_params = voeventparse.get_toplevel_params(v) # print("Toplevel Params:") # pp.pprint(toplevel_params.items()) print("Trigger ID:", toplevel_params['TrigID']['value']) grouped_params = voeventparse.get_grouped_params(v) # pp.pprint(grouped_params.allitems()) print( "GRB Identified:", grouped_params['Solution_Status']['GRB_Identified']['value'])
def __init__(self, payload): super().__init__(payload) # Get XML param dicts # NB: you can't store these on the Event because they're unpickleable. top_params = vp.get_toplevel_params(self.voevent) group_params = vp.get_grouped_params(self.voevent) # Default params self.notice = EVENT_DICTIONARY[self.packet_type]['notice_type'] self.type = 'GRB' self.source = EVENT_DICTIONARY[self.packet_type]['source'] # Get the event ID (e.g. 579943502) self.id = top_params['TrigID']['value'] # Create our own event name (e.g. Fermi_579943502) self.name = '{}_{}'.format(self.source, self.id) # Get properties from the VOEvent if self.source == 'Fermi': self.properties = { key: group_params['Trigger_ID'][key]['value'] for key in group_params['Trigger_ID'] if key != 'Long_short' } try: self.duration = group_params['Trigger_ID']['Long_short'][ 'value'] except KeyError: # Some don't have the duration self.duration = 'unknown' elif self.source == 'Swift': self.properties = { key: group_params['Solution_Status'][key]['value'] for key in group_params['Solution_Status'] } for key in self.properties: if self.properties[key] == 'true': self.properties[key] = True elif self.properties[key] == 'false': self.properties[key] = False # Position coordinates self.position = vp.get_event_position(self.voevent) self.coord = SkyCoord(ra=self.position.ra, dec=self.position.dec, unit=self.position.units) self.target = FixedTarget(self.coord) # Position error self.coord_error = Angle(self.position.err, unit=self.position.units) if self.source == 'Fermi': self.systematic_error = Angle(5.6, unit='deg') else: self.systematic_error = Angle(0, unit='deg') self.total_error = Angle(np.sqrt(self.coord_error**2 + self.systematic_error**2), unit='deg') # Galactic coordinates self.gal_lat = self.coord.galactic.b.value galactic_center = SkyCoord(l=0, b=0, unit='deg,deg', frame='galactic') self.gal_dist = self.coord.galactic.separation(galactic_center).value # Try creating the Fermi skymap url # Fermi haven't actually updated their alerts to include the URL to the HEALPix skymap, # but we can try and create it based on the typical location. try: old_url = top_params['LightCurve_URL']['value'] skymap_url = old_url.replace('lc_medres34', 'healpix_all').replace( '.gif', '.fit') self.skymap_url = skymap_url except Exception: # Worth a try, fall back to creating our own self.skymap_url = None # Don't create or download the skymap here, it may well be very large. # Only do it when it's absolutely necessary # These params will only be set once the skymap is downloaded self.contour_areas = {0.5: None, 0.9: None}
def set_dict(ve, groupid, phot_dict={}, event_dict={}): """ assign values to TNS dictionary. Most values taken from parsed VOEvent file. - groupid is associated with bot registred with TNS (used for "reporting_groupid" and "groupid"). Optional dictionary input to overload some fields: - phot_dict is dictionary for "photometry" keys to set: "snr", "flux", "flux_error", "fluence", "burst_width", "sampling_time". - event_dict is dictionary for other TNS keys (from frb_report set): "internal_name", "reporter", "remarks", "host_name", "repeater_of_objid". """ tns_dict['frb_report']['0']["internal_name"] = str(ve.Why.Name) tns_dict['frb_report']['0']["reporter"] = "Casey J. Law" pos = voeventparse.get_event_position(ve) tns_dict['frb_report']['0']['ra']['value'] = pos.ra tns_dict['frb_report']['0']['dec']['value'] = pos.dec tns_dict['frb_report']['0']['ra']['error'] = pos.err tns_dict['frb_report']['0']['dec']['error'] = pos.err dt = voeventparse.get_event_time_as_utc(ve) dtstring = f'{dt.date().isoformat()} {dt.time().isoformat()}' tns_dict['frb_report']['0']["discovery_datetime"] = dtstring tns_dict['frb_report']['0']["reporting_groupid"] = groupid tns_dict['frb_report']['0']["groupid"] = groupid tns_dict['frb_report']['0']["at_type"] = "5" # FRBs params = voeventparse.get_grouped_params(ve) tns_dict['frb_report']['0']["dm"] = params['event parameters']['dm'][ 'value'] try: tns_dict['frb_report']['0']["dmerr"] = params['event parameters'][ 'dm_error']['value'] except KeyError: pass tns_dict['frb_report']['0']["photometry"]["photometry_group"]["0"][ "snr"] = params['event parameters']['snr']['value'] tns_dict['frb_report']['0']["photometry"]["photometry_group"]["0"][ "burst_width"] = params['event parameters']['width']['value'] tns_dict['frb_report']['0']["photometry"]["photometry_group"]["0"][ "filter_value"] = 129 tns_dict['frb_report']['0']["photometry"]["photometry_group"]["0"][ "instrument_value"] = 239 tns_dict['frb_report']['0']["photometry"]["photometry_group"]["0"][ "flux"] = 0 # TODO: set this tns_dict['frb_report']['0']["photometry"]["photometry_group"]["0"][ "flux_error"] = 0 # TODO: set this tns_dict['frb_report']['0']["photometry"]["photometry_group"]["0"][ "limiting_flux"] = 0 tns_dict['frb_report']['0']["photometry"]["photometry_group"]["0"][ "obsdate"] = dtstring tns_dict['frb_report']['0']["photometry"]["photometry_group"]["0"][ "flux_units"] = "Jy" tns_dict['frb_report']['0']["photometry"]["photometry_group"]["0"][ "ref_freq"] = "1405" tns_dict['frb_report']['0']["photometry"]["photometry_group"]["0"][ "inst_bandwidth"] = "250" tns_dict['frb_report']['0']["photometry"]["photometry_group"]["0"][ "channels_no"] = 1024 tns_dict['frb_report']['0']["photometry"]["photometry_group"]["0"][ "sampling_time"] = 1 # set photometry values for key, value in phot_dict.items(): if key in tns_dict['frb_report']['0']["photometry"][ "photometry_group"]["0"]: print(f'Overloading event key {key} with {value}') tns_dict['frb_report']['0']["photometry"]["photometry_group"]["0"][ key] = value # overload other values for key, value in event_dict.items(): if key in tns_dict['frb_report']['0']: print(f'Overloading event key {key} with {value}') tns_dict['frb_report']['0'][key] = value return tns_dict
def from_etree(root): """ Load up the coords, if present, for initializing with the Voevent. .. note:: Current implementation is quite slack with regard to co-ordinate systems - it is assumed that, for purposes of searching the database using spatial queries, the FK5 / ICRS reference systems and and geocentric/barycentric reference frames are sufficiently similar that we can just take the RA/Dec and insert it 'as-is' into the database. This is partly justified on the assumption that anyone in need of ultra-high precision co-ordinates will need to take account of mission specific properties anyway (e.g. position of GAIA at time of detection) and so will only be using the spatial query for a coarse search, then parsing packets to determine precise locations. """ acceptable_coord_systems = ( vp.definitions.sky_coord_system.utc_fk5_geo, vp.definitions.sky_coord_system.utc_fk5_topo, vp.definitions.sky_coord_system.utc_icrs_geo, vp.definitions.sky_coord_system.utc_icrs_topo, vp.definitions.sky_coord_system.tdb_fk5_bary, vp.definitions.sky_coord_system.tdb_icrs_bary, ) position_list = [] astrocoords = root.xpath( 'WhereWhen/ObsDataLocation/ObservationLocation/AstroCoords' ) if astrocoords: for idx, entry in enumerate(astrocoords): posn = vp.get_event_position(root,idx) if posn.system not in acceptable_coord_systems: raise NotImplementedError( "Loading position from coord-sys " "is not yet implemented: {} ".format( posn.system ) ) if posn.units != vp.definitions.units.degrees: raise NotImplementedError( "Loading positions in formats other than degrees " "is not yet implemented." ) try: isotime = vp.get_event_time_as_utc(root,idx) except: logger.warning( "Error pulling event time for ivorn {}, " "setting to NULL".format(root.attrib['ivorn']) ) isotime = None position_list.append( Coord(ra = posn.ra, dec = posn.dec, error = posn.err, time = isotime) ) return position_list