def createParamList(self, params): ''' Ceate a list of params, so these can be written as group. :param params: List of params (list of dicts). Each dict contains the information for one parameter. :type params: list :returns: paramList, list of lxml.objectify.ObjectifiedElements :rtype: list ''' for param in params: # get value from database value = self.event[param.get('column')] if value: # extract param description # TODO: set Description as well try: paramList.extend( vp.Param(name=param.get('param_name'), value=self.event[param.get('column')], unit=param.get('unit'), ucd=param.get('ucd'))) except NameError: paramList = [ vp.Param(name=param.get('param_name'), value=self.event[param.get('column')], unit=param.get('unit'), ucd=param.get('ucd'))] return paramList
def test_autoconvert_on(self): """...but we provide some python smarts to alleviate this.""" self.v.What.append(vp.Param(name='Dead Parrot')) self.v.What.append(vp.Param(name='The Answer', value=42)) self.v.What.append(vp.Param(name='What is the time?', value=datetime.datetime.utcnow())) self.v.What.append(vp.Param(name='This is a lie', value=False)) self.assertTrue(vp.valid_as_v2_0(self.v))
def test_autoconvert_off(self): """Param values can only be strings...""" self.v.What.append(vp.Param(name='Dead Parrot', ac=False)) self.v.What.append( vp.Param(name='The Answer', value=str(42), ac=False)) self.assertTrue(vp.valid_as_v2_0(self.v)) with self.assertRaises(TypeError): self.v.What.append(vp.Param(name='IntValue', value=42, ac=False))
def generate_voevent(self, feed_id): event_data = self.event_id_data_map[feed_id] stream_id = self.feed_id_to_stream_id(feed_id) v = create_skeleton_4pisky_voevent( substream=self.substream, stream_id=stream_id, role=vp.definitions.roles.observation, date=datetime.datetime.utcnow()) vp.add_how(v, references=[vp.Reference(uri=self.url)]) v.How.Description = "Parsed from Swift burst-analysis listings by 4PiSky-Bot." # Simply copy the WhereWhen from the trigger event: v.WhereWhen = self.trigger_event.WhereWhen v.What.append(vp.Param("TrigID", value=self.trigger_id, ucd="meta.id")) vp.add_citations(v, event_ivorns=[ vp.EventIvorn( ivorn=self.trigger_event.attrib['ivorn'], cite_type=vp.definitions.cite_types.followup) ]) if SwiftFeedKeys.duration in feed_id: duration_data = event_data[SwiftFeedKeys.duration] battblocks_failed = duration_data['battblocks_failed'] battblocks_param = vp.Param('battblocks_failed', value=battblocks_failed, ucd='meta.code.error') battblocks_param.Description = """\ If 'battblocks_failed' is 'True', the source-page contains the 'battblocks failed' warning. This means the duration analysis is bad, usually because the source is not actually a GRB burst. """ duration_params = [] if not battblocks_failed: duration_params.extend([ vp.Param(k, value=duration_data.get(k), unit='s', ucd='time.duration') for k in (SwiftFeedKeys.t90, SwiftFeedKeys.t50) ]) duration_params.extend([ vp.Param(k, value=duration_data.get(k), unit='s', ucd='meta.code.error;time.duration') for k in (SwiftFeedKeys.t90_err, SwiftFeedKeys.t50_err) ]) duration_params.append(battblocks_param) v.What.append( vp.Group(params=duration_params, name=SwiftFeedKeys.duration)) return v
def test_pull_params(self): """ Basic functionality tested here, but this function is deprecated due to some serious flaws. See ``test_get_toplevel_params``. """ swift_params = vp.pull_params(self.swift_grb_v2_packet) # General example, check basic functionality self.assertEqual(swift_params[None]['Packet_Type']['value'], '61') self.assertEqual( swift_params['Misc_Flags']['Values_Out_of_Range']['value'], 'false') # Check ordering is preserved self.assertEqual( list(swift_params[None].keys())[:3], ['Packet_Type', 'Pkt_Ser_Num', 'TrigID']) # Test empty What section params = vp.pull_params(self.blank) self.assertEqual(params, {}) # Test known (generated) example single_par = copy(self.blank) single_par.What.append(vp.Param(name="test_param", value=123)) params = vp.pull_params(single_par) self.assertEqual(len(params), 1) self.assertEqual(list(params[None].keys()), ['test_param']) # Test case where a What Group is present, but empty: params = vp.pull_params(self.moa_packet) self.assertEqual(params['Misc_Flags'], {}) # Test case where a Param is present with no name: params = vp.pull_params(self.gaia_noname_param_packet)
def test_get_toplevel_params(self): v = self.blank p_foo1 = vp.Param(name='foo', value=42, unit='bars', ac=True) p_foo2 = vp.Param(name='foo', value=123, unit='bars', ac=True) p_noname = vp.Param(name='delete_me', value=111) param_list = [p_foo1, p_foo2, p_noname] del p_noname.attrib['name'] v.What.extend(param_list) # Show flaws in old routine: with pytest.warns(FutureWarning): old_style_toplevel_param_dict = vp.pull_params(v)[None] # print(old_style_toplevel_param_dict) vp.assert_valid_as_v2_0(v) # The old 'pull_params' routine will simply drop Params with duplicate # names: assert len(old_style_toplevel_param_dict) == (len(param_list) - 1) none_group = vp.Group([], name=None) complex_group1 = vp.Group([ vp.Param(name='real', value=1.), vp.Param(name='imag', value=0.5) ], name='complex') complex_group2 = vp.Group([ vp.Param(name='real', value=1.5), vp.Param(name='imag', value=2.5) ], name='complex') group_list = [none_group, complex_group1, complex_group2] v.What.extend(group_list) vp.assert_valid_as_v2_0(v) old_style_toplevel_param_dict_w_group = vp.pull_params(v)[None] # An un-named group will also overshadow top-level Params. # This is a total fail, even though it's actually in-spec. assert len(old_style_toplevel_param_dict_w_group) == 0 toplevel_params = vp.get_toplevel_params(v) # .values method behaves like regular dict, one value for each key: assert len(toplevel_params.values()) == (len(param_list) - 1) # Use .allvalues if you want to see duplicates: assert len(toplevel_params.allvalues()) == len(param_list) grouped_params = vp.get_grouped_params(v) assert len(grouped_params.values()) == len(group_list) - 1 assert len(grouped_params.allvalues()) == len(group_list)
print(vp.prettystr(v.Who)) # ##Adding ``What`` content## # # We'll add details from this GAIA event: # # | Name | UTC timestamp | RA | Dec | AlertMag | HistMag | HistStdDev | Class | Comment | Published | # |-----------|---------------------|-----------|-----------|----------|---------|------------|---------|----------------------------------------------------------|-------------------| # | Gaia14adi | 2014-11-07 01:05:09 | 168.47841 | -23.01221 | 18.77 | 19.62 | 0.07 | unknown | Fading source on top of 2MASS Galaxy (offset from bulge) | 2 Dec 2014, 13:55 | # Now let's add details of the observation itself. We'll record both the magnitude that Gaia is reporting for this particular event, and the historic values they also provide: # In[ ]: v.What.append(vp.Param(name="mag", value=18.77, ucd="phot.mag")) h_m = vp.Param(name="hist_mag", value=19.62, ucd="phot.mag") h_s = vp.Param(name="hist_scatter", value=0.07, ucd="phot.mag") v.What.append(vp.Group(params=[h_m, h_s], name="historic")) # ##Adding ``WhereWhen`` details## # Now we need to specify where and when the observation was made. Rather than trying to specify a position for Gaia, we'll just call it out by name. Note that Gaia don't provide errors on the position they cite, so we're rather optimistically using 0: # In[ ]: vp.add_where_when(v, coords=vp.Position2D( ra=168.47841, dec=-23.01221, err=0, units='deg',
def create_grb_voevent(grb_dic, conf_vo, what_com, atable): """ Create VO event with observation plan for a given telescope in the network :param gw_dic: dictionary with GRB infos :param conf_vo: dictionary to be used to fill header of VO event :param what_com: dictionary with common infos needed for VO creation :param atable: astropy table with observation plan and meta data :return: voevent object """ # get telescope name and role, will be used several time tel_name = what_com['tel_name'] obs_mode = what_com['obs_mode'] voevent = basic_grb_voevent(grb_dic, conf_vo, what_com) #GBM ground or final position if grb_dic["Packet_Type"] == 112 or grb_dic["Packet_Type"] == 115: pixloc = vp.Param(name="Loc_url", value=str(grb_dic["skymap"]["localization_name"]), ucd="meta.ref.url", dataType="string") pixloc.Description = "URL to retrieve location of the healpix skymap" voevent.What.append(pixloc) if tel_name != "": name_tel = vp.Param(name="Name_tel", value=str(tel_name), ucd="instr", dataType="string") name_tel.Description = "Name of the telescope used for the observation strategy" voevent.What.append(name_tel) if atable and atable[0]: # now prepare observation plan or galaxies list fields = objectify.Element("Table", name="Obs_plan") fields.Description = "Tiles for the observation plan" # first field is the identificaiton of the field # it will be different between tiling and galaxy targetting if obs_mode == "Tiling": field_id = objectify.SubElement(fields, "Field", name="Field_id", ucd="", unit="", dataType="string") field_id.Description = "ID of the field of FOV" tel_obsplan = np.transpose( np.array([ atable['rank_id'], atable['RA'], atable['DEC'], atable['Prob'] ])) else: field_id = objectify.SubElement(fields, "Field", name="Gal_id", ucd="", unit="", dataType="string") field_id.Description = "ID of the galaxy" # For galaxie we will uniformize how we name them based on catalogs gal_id = utils_too.uniformize_galnames(atable) tel_obsplan = np.transpose( np.array([ gal_id, atable['RAJ2000'], atable['DEJ2000'], atable['S'] ])) # right_asc = objectify.SubElement(fields, "Field", name="RA", ucd="pos.eq.ra ", unit="deg", dataType="float") right_asc = objectify.SubElement(fields, "Field", name="RA", ucd="pos.eq.ra ", unit="deg", dataType="float") right_asc.Description = "The right ascension at center of fov in equatorial coordinates" dec = objectify.SubElement(fields, "Field", name="Dec", ucd="pos.eq.ra ", unit="deg", dataType="float") dec.Description = "The declination at center of fov in equatorial coordinates" os_grade = objectify.SubElement(fields, "Field", name="Os_score", ucd="meta.number", unit="None", dataType="float") os_grade.Description = "Gives the importance of the tile/galaxy to observe" data = objectify.SubElement(fields, "Data") # loop on the observation plan # put a limit to 500 fields otherwise get an error when sending a VO event for i in np.arange(min(500, len(tel_obsplan))): table_row = objectify.SubElement(data, "TR") for j in np.arange(len(tel_obsplan[i])): # objectify.SubElement(TR, "TD",value=str(Tel_dic["OS"][i][j])) objectify.SubElement(table_row, 'TD') table_row.TD[-1] = str(tel_obsplan[i][j]) voevent.What.append(fields) grb_dic["dateobs"] = grb_dic["dateobs"].replace(tzinfo=pytz.utc) vp.add_where_when(voevent, coords=vp.Position2D( ra=grb_dic["ra"], dec=grb_dic["dec"], err=grb_dic["error"], units='deg', system=vp.definitions.sky_coord_system.utc_fk5_geo), obs_time=grb_dic["dateobs"], observatory_location=grb_dic["inst"]) # Check everything is schema compliant: vp.assert_valid_as_v2_0(voevent) return voevent
def generate_voevent(self, feed_id): rowdict = self.event_id_data_map[feed_id] params = rowdict['param'] urls = rowdict['url'] stream_id = self.feed_id_to_stream_id(feed_id) v = create_skeleton_4pisky_voevent(substream=self.substream, stream_id=stream_id, role=vp.definitions.roles.observation, date=datetime.datetime.utcnow() ) vp.add_how(v, references=vp.Reference(uri=self.url)) v.How.Description = "Parsed from ASASSN listings page by 4PiSky-Bot." timestamp_dt = asassn_timestamp_str_to_datetime( params[AsassnKeys.detection_timestamp]) posn_sc = SkyCoord(params['ra'], params['dec'], unit=(u.hourangle, u.deg)) # Couldn't find a formal analysis of positional accuracy, but # http://dx.doi.org/10.1088/0004-637X/788/1/48 # states the angular resolution as 16 arcseconds, so we'll go with that. err_radius_estimate = 16 * u.arcsec posn_simple = vp.Position2D(ra=posn_sc.ra.deg, dec=posn_sc.dec.deg, err=err_radius_estimate.to(u.deg).value, units=vp.definitions.units.degrees, system=vp.definitions.sky_coord_system.utc_icrs_geo, ) vp.add_where_when( v, coords=posn_simple, obs_time=timestamp_dt, observatory_location=vp.definitions.observatory_location.geosurface) asassn_params = [vp.Param(key, params[key]) for key in (AsassnKeys.id_asassn, AsassnKeys.id_other, AsassnKeys.detection_timestamp, AsassnKeys.ra, AsassnKeys.dec, AsassnKeys.spec_class, AsassnKeys.comment, ) if key in params ] if AsassnKeys.mag_v in params: asassn_params.append( vp.Param(AsassnKeys.mag_v, params[AsassnKeys.mag_v], unit='mag', ucd="phot.mag", ) ) if AsassnKeys.id_other in urls: asassn_params.append( vp.Param(AsassnKeys.id_other, urls[AsassnKeys.id_other][0][0]) ) asassn_urls = [vp.Param(key, urls[key][0][1]) for key in urls] v.What.append(vp.Group(params=asassn_params, name=self.text_params_groupname)) v.What.append(vp.Group(params=asassn_urls, name=self.url_params_groupname)) return v
vp.set_who(v, date=datetime.datetime.utcnow(), author_ivorn="voevent.4pisky.org") vp.set_author(v, title="4PiSky Testing Node", shortName="Tim") # Now create some Parameters for entry in the 'What' section. # Strictly speaking, parameter values should be strings, # with a manually specified dataType; one of # `string` (default), `int` , or `float`. # e.g. int_flux = vp.Param(name='int_flux', value="2.0e-3", unit='Janskys', ucd='em.radio.100-200MHz', dataType='float', ac=False) int_flux.Description = 'Integrated Flux' # But with ac=True (autoconvert) we switch on some magic to take care # of this for us automatically. # See ``Param`` docstring for details. p_flux = vp.Param(name='peak_flux', value=1.5e-3, unit='Janskys', ucd='em.radio.100-200MHz', ac=True) p_flux.Description = 'Peak Flux' v.What.append(vp.Group(params=[p_flux, int_flux], name='source_flux'))
def create_voevent(jsonfile=None, deployment=False, **kwargs): """ template syntax for voeventparse creation of voevent """ required = [ 'internalname', 'mjds', 'dm', 'width', 'snr', 'ra', 'dec', 'radecerr' ] preferred = ['fluence', 'p_flux', 'importance', 'dmerr'] # set values dd = kwargs.copy() if jsonfile is not None: # as made by caltechdata.set_metadata for k, v in trigger.items(): if k in required + preferred: dd[k] = v assert all([ k in dd for k in required ]), f'Input keys {list(dd.keys())} not complete (requires {required})' # TODO: set this correctly dt = time.Time(dd['mjds'], format='mjd').to_datetime(timezone=pytz.utc) # create voevent instance role = vp.definitions.roles.observation if deployment else vp.definitions.roles.test v = vp.Voevent( stream='', # TODO: check stream_id=1, role=role) vp.set_who(v, date=datetime.datetime.utcnow(), author_ivorn="voevent.dsa-110.caltech.org") # TODO: check vp.set_author(v, title="DSA-110 Testing Node", contactName="Casey Law", contactEmail="*****@*****.**") params = [] dm = vp.Param(name="dm", value=str(dd['dm']), unit="pc/cm^3", ucd="phys.dispMeasure;em.radio.750-1500MHz", dataType='float', ac=True) dm.Description = 'Dispersion Measure' params.append(dm) width = vp.Param(name="width", value=str(dd['width']), unit="ms", ucd="time.duration;src.var.pulse", dataType='float', ac=True) width.Description = 'Temporal width of burst' params.append(width) snr = vp.Param(name="snr", value=str(dd['snr']), ucd="stat.snr", dataType='float', ac=True) snr.Description = 'Signal to noise ratio' params.append(snr) if 'fluence' in dd: fluence = vp.Param( name='fluence', value=str(dd['fluence']), unit='Jansky ms', ucd='em.radio.750-1500MHz', # TODO: check dataType='float', ac=False) fluence.Description = 'Fluence' params.append(fluence) if 'p_flux' in dd: p_flux = vp.Param(name='peak_flux', value=str(dd['p_flux']), unit='Janskys', ucd='em.radio.750-1500MHz', dataType='float', ac=True) p_flux.Description = 'Peak Flux' params.append(p_flux) if 'dmerr' in dd: dmerr = vp.Param(name="dm_error", value=str(dd['dmerr']), unit="pc/cm^3", ucd="phys.dispMeasure;em.radio.750-1500MHz", dataType='float', ac=True) dmerr.Description = 'Dispersion Measure error' params.append(dmerr) v.What.append(vp.Group(params=params, name='event parameters')) vp.add_where_when(v, coords=vp.Position2D( ra=str(dd['ra']), dec=str(dd['dec']), err=str(dd['radecerr']), units='deg', system=vp.definitions.sky_coord_system.utc_fk5_geo), obs_time=dt, observatory_location='OVRO') print("\n***Here is your WhereWhen:***\n") print(vp.prettystr(v.WhereWhen)) print("\n***And your What:***\n") print(vp.prettystr(v.What)) vp.add_how(v, descriptions='Discovered with DSA-110', references=vp.Reference('http://deepsynoptic.org')) if 'importance' in dd: vp.add_why(v, importance=str(dd['importance'])) else: vp.add_why(v) v.Why.Name = str(dd['internalname']) vp.assert_valid_as_v2_0(v) return v
def NewVOEvent(dm, dm_err, width, snr, flux, ra, dec, semiMaj, semiMin, ymw16, name, importance, utc, gl, gb): z = dm/1200.0 #May change errDeg = semiMaj/60.0 # Parse UTC utc_YY = int(utc[:4]) utc_MM = int(utc[5:7]) utc_DD = int(utc[8:10]) utc_hh = int(utc[11:13]) utc_mm = int(utc[14:16]) utc_ss = float(utc[17:]) t = Time('T'.join([utc[:10], utc[11:]]), scale='utc', format='isot') mjd = t.mjd now = Time.now() mjd_now = now.mjd ivorn = ''.join([name, str(utc_hh), str(utc_mm), '/', str(mjd_now)]) v = vp.Voevent(stream='nl.astron.apertif/alert', stream_id=ivorn, role=vp.definitions.roles.test) # v = vp.Voevent(stream='nl.astron.apertif/alert', stream_id=ivorn, role=vp.definitions.roles.observation) # Author origin information vp.set_who(v, date=datetime.datetime.utcnow(), author_ivorn="nl.astron") # Author contact information vp.set_author(v, title="ASTRON ALERT FRB Detector", contactName="Leon Oostrum", contactEmail="*****@*****.**", shortName="ALERT") # Parameter definitions #Apertif-specific observing configuration %%TODO: update parameters as necessary for new obs config beam_sMa = vp.Param(name="beam_semi-major_axis", unit="MM", ucd="instr.beam;pos.errorEllipse;phys.angSize.smajAxis", ac=True, value=semiMaj) beam_sma = vp.Param(name="beam_semi-minor_axis", unit="MM", ucd="instr.beam;pos.errorEllipse;phys.angSize.sminAxis", ac=True, value=semiMin) beam_rot = vp.Param(name="beam_rotation_angle", value=0.0, unit="Degrees", ucd="instr.beam;pos.errorEllipse;instr.offset", ac=True) tsamp = vp.Param(name="sampling_time", value=0.0496, unit="ms", ucd="time.resolution", ac=True) bw = vp.Param(name="bandwidth", value=300.0, unit="MHz", ucd="instr.bandwidth", ac=True) nchan = vp.Param(name="nchan", value="1536", dataType="int", ucd="meta.number;em.freq;em.bin", unit="None") cf = vp.Param(name="centre_frequency", value=1400.0, unit="MHz", ucd="em.freq;instr", ac=True) npol = vp.Param(name="npol", value="2", dataType="int", unit="None") bits = vp.Param(name="bits_per_sample", value="8", dataType="int", unit="None") gain = vp.Param(name="gain", value=1.0, unit="K/Jy", ac=True) tsys = vp.Param(name="tsys", value=75.0, unit="K", ucd="phot.antennaTemp", ac=True) backend = vp.Param(name="backend", value="ARTS") # beam = vp.Param(name="beam", value= ) v.What.append(vp.Group(params=[beam_sMa, beam_sma, beam_rot, tsamp, bw, nchan, cf, npol, bits, gain, tsys, backend], name="observatory parameters")) #Event parameters DM = vp.Param(name="dm", ucd="phys.dispMeasure", unit="pc/cm^3", ac=True, value=dm ) # DM_err = vp.Param(name="dm_err", ucd="stat.error;phys.dispMeasure", unit="pc/cm^3", ac=True, value=dm_err) Width = vp.Param(name="width", ucd="time.duration;src.var.pulse", unit="ms", ac=True, value=width) SNR = vp.Param(name="snr", ucd="stat.snr", unit="None", ac=True, value=snr) Flux = vp.Param(name="flux", ucd="phot.flux", unit="Jy", ac=True, value=flux) Flux.Description = "Calculated from radiometer equation. Not calibrated." Gl = vp.Param(name="gl", ucd="pos.galactic.lon", unit="Degrees", ac=True, value=gl) Gb = vp.Param(name="gb", ucd="pos.galactic.lat", unit="Degrees", ac=True, value=gb) v.What.append(vp.Group(params=[DM, Width, SNR, Flux, Gl, Gb], name="event parameters")) # v.What.append(vp.Group(params=[DM, DM_err, Width, SNR, Flux, Gl, Gb], name="event parameters")) #Advanced parameters (note, change script if using a differeing MW model) mw_dm = vp.Param(name="MW_dm_limit", unit="pc/cm^3", ac=True, value=ymw16) mw_model = vp.Param(name="galactic_electron_model", value="YMW16") redshift_inferred = vp.Param(name="redshift_inferred", ucd="src.redshift", unit="None", value=z) redshift_inferred.Description = "Redshift estimated using z = DM/1200.0 (Ioka 2003)" v.What.append(vp.Group(params=[mw_dm, mw_model, redshift_inferred], name="advanced parameters")) #WhereWhen vp.add_where_when(v, coords=vp.Position2D(ra=ra, dec=dec, err=errDeg, units='deg', system=vp.definitions.sky_coord_system.utc_fk5_geo), obs_time=datetime.datetime(utc_YY,utc_MM,utc_DD,utc_hh,utc_mm,int(utc_ss), tzinfo=pytz.UTC), observatory_location="WSRT") #Why vp.add_why(v, importance=imp) v.Why.Name = name if vp.valid_as_v2_0(v): with open('%s.xml' % utc, 'wb') as f: voxml = vp.dumps(v) xmlstr = minidom.parseString(voxml).toprettyxml(indent=" ") f.write(xmlstr) print(vp.prettystr(v.Who)) print(vp.prettystr(v.What)) print(vp.prettystr(v.WhereWhen)) print(vp.prettystr(v.Why)) else: print "Unable to write file %s.xml" % name
def init_voevent(conf_vo, what_com): """ Create common structure for all VO events :param conf_vo: dictionary with common info, needed for header :param what_com: dictionary with common info for all type of events :return: vo event object """ # initiate VO event object through voeventparse voevent = vp.Voevent(stream=conf_vo["stream"], stream_id=conf_vo["streamid"], role=conf_vo["role"]) # include who part, required by VO protocol vp.set_who(voevent, date=datetime.datetime.utcnow(), author_ivorn=conf_vo["authorivorn"]) # info of the origin, required by VO protocol vp.set_author(voevent, contactName=conf_vo["contactName"]) vp.set_author(voevent, shortName=conf_vo["Experiment"]) vp.set_author(voevent, contactPhone=conf_vo["contactPhone"]) vp.set_author(voevent, contactEmail=conf_vo["contactEmail"]) # fill infos from the original event, add them to What section # first type of the alert (GW, neutrinos, ...) alertype = vp.Param(name="Event_type", value=what_com["event_type"], ucd="meta.id", dataType="string") alertype.Description = "Type of the alert" voevent.What.append(alertype) # include event name provided by the external observatory or GRANDMA eventid = vp.Param(name="Event_ID", value=what_com["name_id"], ucd="meta.id", dataType="string") eventid.Description = "Name event, given by external observatory" voevent.What.append(eventid) # include trigger number provided by the external observatory trigid = vp.Param(name="Trigger_ID", value=what_com["trigger_id"], ucd="meta.id", dataType="string") trigid.Description = "Trigger ID, given by external observatory" voevent.What.append(trigid) # Provide the status of the alert, given by external observatory alertstatus = vp.Param(name="Event_status", value=what_com["event_status"], ucd="meta.version", dataType="string") alertstatus.Description = "Event status (preliminary, initial, update, retraction)" voevent.What.append(alertstatus) # Serial number of the revision alertstatus_iter = vp.Param(name="Pkt_ser_num", value=str(what_com["pkt_ser_num"]), ucd="meta.number", dataType="int") alertstatus_iter.Description = \ "Packet serial number since beginning, increase by 1 for every revision received" voevent.What.append(alertstatus_iter) if what_com["event_status"] not in ["Retraction", "retraction"]: # Instrument(s) involved in the alert triginstru = vp.Param(name="Instruments", value=what_com["inst"], ucd="meta.code", dataType="string") triginstru.Description = "Instruments which originated of the alert" voevent.What.append(triginstru) # include longshort provided by the external observatory eventid = vp.Param(name="LongShort", value=str(what_com["longshort"]), ucd="meta.id", dataType="string") eventid.Description = "Long-short classification, given by external observatory" voevent.What.append(eventid) # include hardness ratio classification provided by the external observatory hratio = vp.Param(name="Hratio", value=str(what_com["hratio"]), ucd="meta.number", dataType="float") hratio.Description = "Hardness ratio classification, given by external observatory" voevent.What.append(hratio) # include sun_distance classification provided by the external observatory sun_distance = vp.Param(name="Sun_distance", value=str(what_com["sun_distance"]), ucd="meta.number", dataType="float") sun_distance.Description = "Sun distance from space, given by external observatory" voevent.What.append(sun_distance) # include moon_distance classification provided by the external observatory moon_distance = vp.Param(name="Moon_distance", value=str(what_com["moon_distance"]), ucd="meta.number", dataType="float") moon_distance.Description = "Moon distance from space, given by external observatory" voevent.What.append(moon_distance) # include moon_illumination classification provided by the external observatory moon_illum = vp.Param(name="Moon_illum", value=str(what_com["moon_illum"]), ucd="meta.number", dataType="float") moon_illum.Description = "Moon illumination from space, given by external observatory" voevent.What.append(moon_illum) return voevent
def generate_voevent(self, feed_id): event_data = self.event_id_data_map[feed_id] stream_id = self.feed_id_to_stream_id(feed_id) v = create_skeleton_4pisky_voevent(substream=self.substream, stream_id=stream_id, role=vp.definitions.roles.observation, date=datetime.datetime.utcnow() ) gsaw_event_url = 'http://gsaweb.ast.cam.ac.uk/alerts/alert/'+feed_id vp.add_how(v, references=[vp.Reference(uri=self.url), vp.Reference(uri=gsaw_event_url) ] ) v.How.Description = "Parsed from GAIA Science Alerts listings by 4PiSky-Bot." posn_sc = SkyCoord(event_data[GaiaKeys.ra], event_data[GaiaKeys.dec], unit=(u.deg, u.deg)) # Astrometric accuracy is a guesstimate, # http://gsaweb.ast.cam.ac.uk/alerts/tableinfo states that: # "The sky position may either refer to a source in Gaia's own # catalogue, or to a source in an external catalogue (e.g. SDSS) used as # a reference for combining Gaia observations. Where the position comes # from Gaia's catalogue, it is derived from a single, Gaia observation # at the triggering point of the alert; this is not an astrometric # measurement to the full precision of the Gaia main mission." # # We assume a 'worst-case' scenario of 100mas from SDSS at mag r=22, cf # http://classic.sdss.org/dr7/products/general/astrometry.html err_radius_estimate = 0.1 * u.arcsec posn_simple = vp.Position2D(ra=posn_sc.ra.deg, dec=posn_sc.dec.deg, err=err_radius_estimate.to(u.deg).value, units=vp.definitions.units.degrees, system=vp.definitions.sky_coord_system.utc_icrs_geo, ) # NB GAIA values are in Barycentric co-ordinate time # (http://en.wikipedia.org/wiki/Barycentric_Coordinate_Time) observation_time_tcb = astropy.time.Time( event_data[GaiaKeys.obs_timestamp], scale='tcb') # We convert to UTC, in keeping with other feeds: observation_time_utc_dt = observation_time_tcb.utc.datetime observation_time_utc_dt = observation_time_utc_dt.replace(tzinfo=pytz.UTC) vp.add_where_when( v, coords=posn_simple, obs_time=observation_time_utc_dt, observatory_location=vp.definitions.observatory_location.geosurface) gaia_params = [vp.Param('Name', event_data[GaiaKeys.name])] gaia_params.extend([vp.Param(key.strip(), event_data[key]) for key in (GaiaKeys.alert_class, GaiaKeys.obs_timestamp, GaiaKeys.pub_timestamp, GaiaKeys.ra, GaiaKeys.dec, GaiaKeys.comment, ) ]) gaia_params.extend([vp.Param(key.strip(), event_data[key], unit='mag', ucd='phot.mag') for key in ( GaiaKeys.mag_alert, GaiaKeys.mag_historic, GaiaKeys.mag_historic_std_dev, ) ]) v.What.append(vp.Group(params=gaia_params, name=self.text_params_groupname)) return v
def _NewVOEvent(self, dm, dm_err, width, snr, flux, ra, dec, semiMaj, semiMin, ymw16, name, importance, utc, gl, gb, gain, dt=TSAMP.to(u.ms).value, delta_nu_MHz=(BANDWIDTH / NCHAN).to(u.MHz).value, nu_GHz=1.37, posang=0, test=None): """ Create a VOEvent :param float dm: Dispersion measure (pc cm**-3) :param float dm_err: Error on DM (pc cm**-3) :param float width: Pulse width (ms) :param float snr: Signal-to-noise ratio :param float flux: flux density (mJy) :param float ra: Right ascension (deg) :param float dec: Declination (deg) :param float semiMaj: Localisation region semi-major axis (arcmin) :param float semiMin: Localisation region semi-minor axis (arcmin) :param float ymw16: YMW16 DM (pc cm**-3) :param str name: Source name :param float importance: Trigger importance (0-1) :param str utc: UTC arrival time in ISOT format :param float gl: Galactic longitude (deg) :param float gb: Galactic latitude (deg) :param float gain: Telescope gain (K Jy**-1) :param float dt: Telescope time resolution (ms) :param float delta_nu_MHz: Telescope frequency channel width (MHz) :param float nu_GHz: Telescope centre frequency (GHz) :param float posang: Localisation region position angle (deg) :param bool test: Whether to send a test event or observation event """ z = dm / 1000.0 # May change errDeg = semiMaj / 60.0 # Parse UTC utc_YY = int(utc[:4]) utc_MM = int(utc[5:7]) utc_DD = int(utc[8:10]) utc_hh = int(utc[11:13]) utc_mm = int(utc[14:16]) utc_ss = float(utc[17:]) t = Time(utc, scale='utc', format='isot') # IERS server is down, avoid using it t.delta_ut1_utc = 0 mjd = t.mjd ivorn = ''.join([name, str(utc_hh), str(utc_mm), '/', str(mjd)]) # use default value for test flag if not set if test is None: test = self.test # Set role to either test or real observation if test: self.logger.info("Event type is test") v = vp.Voevent(stream='nl.astron.apertif/alert', stream_id=ivorn, role=vp.definitions.roles.test) else: self.logger.info("Event type is observation") v = vp.Voevent(stream='nl.astron.apertif/alert', stream_id=ivorn, role=vp.definitions.roles.observation) # Author origin information vp.set_who(v, date=datetime.datetime.utcnow(), author_ivorn="nl.astron") # Author contact information vp.set_author(v, title="ARTS FRB alert system", contactName="Leon Oostrum", contactEmail="*****@*****.**", shortName="ALERT") # Parameter definitions # Apertif-specific observing configuration beam_sMa = vp.Param(name="beam_semi-major_axis", unit="MM", ucd="instr.beam;pos.errorEllipse;phys.angSize.smajAxis", ac=True, value=semiMaj) beam_sma = vp.Param(name="beam_semi-minor_axis", unit="MM", ucd="instr.beam;pos.errorEllipse;phys.angSize.sminAxis", ac=True, value=semiMin) beam_rot = vp.Param(name="beam_rotation_angle", value=str(posang), unit="Degrees", ucd="instr.beam;pos.errorEllipse;instr.offset", ac=True) tsamp = vp.Param(name="sampling_time", value=str(dt), unit="ms", ucd="time.resolution", ac=True) bw = vp.Param(name="bandwidth", value=str(delta_nu_MHz), unit="MHz", ucd="instr.bandwidth", ac=True) nchan = vp.Param(name="nchan", value=str(NCHAN), dataType="int", ucd="meta.number;em.freq;em.bin", unit="None") cf = vp.Param(name="centre_frequency", value=str(1000 * nu_GHz), unit="MHz", ucd="em.freq;instr", ac=True) npol = vp.Param(name="npol", value="2", dataType="int", unit="None") bits = vp.Param(name="bits_per_sample", value="8", dataType="int", unit="None") gain = vp.Param(name="gain", value=str(gain), unit="K/Jy", ac=True) tsys = vp.Param(name="tsys", value=str(TSYS.to(u.Kelvin).value), unit="K", ucd="phot.antennaTemp", ac=True) backend = vp.Param(name="backend", value="ARTS") # beam = vp.Param(name="beam", value= ) v.What.append(vp.Group(params=[beam_sMa, beam_sma, beam_rot, tsamp, bw, nchan, cf, npol, bits, gain, tsys, backend], name="observatory parameters")) # Event parameters DM = vp.Param(name="dm", ucd="phys.dispMeasure", unit="pc/cm^3", ac=True, value=str(dm)) DM_err = vp.Param(name="dm_err", ucd="stat.error;phys.dispMeasure", unit="pc/cm^3", ac=True, value=str(dm_err)) Width = vp.Param(name="width", ucd="time.duration;src.var.pulse", unit="ms", ac=True, value=str(width)) SNR = vp.Param(name="snr", ucd="stat.snr", unit="None", ac=True, value=str(snr)) Flux = vp.Param(name="flux", ucd="phot.flux", unit="Jy", ac=True, value=str(flux)) Flux.Description = "Calculated from radiometer equation. Not calibrated." Gl = vp.Param(name="gl", ucd="pos.galactic.lon", unit="Degrees", ac=True, value=str(gl)) Gb = vp.Param(name="gb", ucd="pos.galactic.lat", unit="Degrees", ac=True, value=str(gb)) # v.What.append(vp.Group(params=[DM, Width, SNR, Flux, Gl, Gb], name="event parameters")) v.What.append(vp.Group(params=[DM, DM_err, Width, SNR, Flux, Gl, Gb], name="event parameters")) # Advanced parameters (note, change script if using a differeing MW model) mw_dm = vp.Param(name="MW_dm_limit", unit="pc/cm^3", ac=True, value=str(ymw16)) mw_model = vp.Param(name="galactic_electron_model", value="YMW16") redshift_inferred = vp.Param(name="redshift_inferred", ucd="src.redshift", unit="None", value=str(z)) redshift_inferred.Description = "Redshift estimated using z = DM/1000.0" v.What.append(vp.Group(params=[mw_dm, mw_model, redshift_inferred], name="advanced parameters")) # WhereWhen vp.add_where_when(v, coords=vp.Position2D(ra=ra, dec=dec, err=errDeg, units='deg', system=vp.definitions.sky_coord_system.utc_fk5_geo), obs_time=datetime.datetime(utc_YY, utc_MM, utc_DD, utc_hh, utc_mm, int(utc_ss), tzinfo=pytz.UTC), observatory_location="WSRT") # Why vp.add_why(v, importance=importance) v.Why.Name = name if vp.valid_as_v2_0(v): with open('{}.xml'.format(utc), 'wb') as f: voxml = vp.dumps(v) xmlstr = minidom.parseString(voxml).toprettyxml(indent=" ") f.write(xmlstr.encode()) self.logger.info(vp.prettystr(v.Who)) self.logger.info(vp.prettystr(v.What)) self.logger.info(vp.prettystr(v.WhereWhen)) self.logger.info(vp.prettystr(v.Why)) else: self.logger.error("Unable to write file {}.xml".format(name))
def add_gw_voevent_content(voevent, gw_dic, obsplan): """ Add specific information for GW event nature and physical properties :param voevent: VO event object to be updated :param gw_dic: dictionary with GW information :param obsplan: type of Observation plan performed (tiling, galaxy) :return: """ # Include FAR for the event proba = vp.Param(name="FAR", value=str(gw_dic["FAR"]), ucd="arith.rate;stat.falsealarm", dataType="float") proba.Description = "False Alarm probability" voevent.What.append(proba) obs_plan = vp.Param(name="Obs_plan", value=obsplan, ucd="obs_plan", dataType="string") obs_plan.Description = "Observation plan done using either tiling or galaxy" voevent.What.append(obs_plan) eventpage = vp.Param(name="Quicklook_url", value=gw_dic["EventPage"], ucd="meta.ref.url", dataType="string") eventpage.Description = "Web page for evolving status of this GW candidate" voevent.What.append(eventpage) lum = vp.Param(name="Distance", value=str(gw_dic["lum"]), ucd="meta.number", dataType="float") lum.Description = "Luminosity distance (Mpc)" voevent.What.append(lum) errlum = vp.Param(name="Err_distance", value=str(gw_dic["errlum"]), ucd="meta.number", dataType="float") errlum.Description = "Std for the luminosity distance (Mpc)" voevent.What.append(errlum) s50cr = vp.Param(name="50cr_skymap", value=str(gw_dic["50cr"]), ucd="meta.number", dataType="float") s50cr.Description = "Sky localization area (50 pourcent confident region)" voevent.What.append(s50cr) s90cr = vp.Param(name="90cr_skymap", value=str(gw_dic["90cr"]), ucd="meta.number", dataType="float") s90cr.Description = "Sky localization area (90 pourcent confident region)" voevent.What.append(s90cr) group = vp.Param(name="Group", value=gw_dic["Group"], ucd="meta.code", dataType="string") group.Description = "Data analysis working group" voevent.What.append(group) bns = vp.Param(name="BNS", value=str(gw_dic["BNS"]), dataType="float", ucd="stat.probability") bns.Description = "Probability that the source is a binary neutron star merger" nsbh = vp.Param(name="NSBH", value=str(gw_dic["NSBH"]), dataType="float", ucd="stat.probability") nsbh.Description = "Probability that the source is a neutron star - black hole merger" bbh = vp.Param(name="BBH", value=str(gw_dic["BBH"]), dataType="float", ucd="stat.probability") bbh.Description = "Probability that the source is a binary black hole merger" massgap = vp.Param(name="MassGap", value=str(gw_dic["MassGap"]), dataType="float", ucd="stat.probability") massgap.Description = "Probability that mass of one of the objects lies in 3-5 Ms" terrestrial = vp.Param(name="Terrestrial", value=str(gw_dic["Terrestrial"]), dataType="float", ucd="stat.probability") terrestrial.Description = "Probability that the source is " \ "terrestrial (i.e., a background noise fluctuation or a glitch)" group_class = vp.Group(params=[bns, nsbh, bbh, terrestrial, massgap], name="Classification") group_class.Description = "Source classification: binary neutron star " \ "(BNS), neutron star-black hole (NSBH), " \ "binary black hole (BBH), or terrestrial (noise)" voevent.What.append(group_class) has_ns = vp.Param(name="HasNS", value=str(gw_dic["HasNS"]), dataType="float", ucd="stat.probability") has_ns.Description = "Probability that at least one object " \ "in the binary has a mass that is less than 3 solar masses" has_remnant = vp.Param(name="HasRemnant", value=str(gw_dic["HasRemnant"]), dataType="float", ucd="stat.probability") has_remnant.Description = "Probability that a nonzero mass was ejected " \ "outside the central remnant object" group_prop = vp.Group(params=[has_ns, has_remnant], name="Properties") group_prop.Description = "Qualitative properties of the source, " \ "conditioned on the assumption that the signal " \ "is an astrophysical compact binary merger" voevent.What.append(group_prop)