diff --git a/svc_2019/q.rd b/svc_2019/q.rd index cc4dcc7d1f876ff25b1f14a474fee4f4f0cd58c0..bd121d6ee04a6e8982fa30fe78ddfcc5e2dfd5a1 100644 --- a/svc_2019/q.rd +++ b/svc_2019/q.rd @@ -20,37 +20,60 @@ <meta name="coverage.waveband">Radio</meta> - <table id="main" onDisk="True" mixin="//siap#pgs" adql="False"> - -<!-- <mixin - calibLevel="2" - collectionName="'%a few letters identifying this data%'" - targetName="%column name of an object designation%" - expTime="%column name of an exposure time%" - targetClass="'%simbad taget class%'" - >//obscore#publishSIAP</mixin>--> - + <STREAM id="localcolumns"> <column name="beam_major" - unit="arcsec" ucd="" + unit="arcsec" ucd="phys.angsize;instr.beam" tablehead="Beam (maj)" description="Major axis of beam (perhaps half-sensitivity) size." verbLevel="15"/> <column name="beam_minor" - unit="arcsec" ucd="" + unit="arcsec" ucd="phys.angsize;instr.beam" tablehead="Beam (min)" description="Minor axis of beam (perhaps half-sensitivity) size." verbLevel="15"/> <column name="beam_pa" - unit="degree" ucd="" + unit="degree" ucd="pos.angsize;instr.beam" tablehead="Beam (PA)" description="Position agle of beam." verbLevel="15"/> <column name="object" type="text" - ucd="" + ucd="meta.id;src" tablehead="Object" description="Target object observed" verbLevel="10"/> + <column name="obsid" type="text" + ucd="meta.id;obs" + tablehead="Obs. Id" + description="APERTIF observation id; use datalink to discover other + data products from this observation." + verbLevel="5"/> + <column name="datalink" type="text" + tablehead="Datalink Access" + description="URL of a datalink document for the dataset (raw data, + derived data" + displayHint="type=url"> + <property name="targetType" + >application/x-votable+xml;content=datalink</property> + <property name="targetTitle">Datalink</property> + </column> + </STREAM> + + <table id="main" onDisk="True" mixin="//siap#pgs" adql="False"> + + <meta name="_associatedDatalinkService"> + <meta name="serviceId">dl</meta> + <meta name="idColumn">accref</meta> + </meta> + +<!-- <mixin + calibLevel="2" + collectionName="'%a few letters identifying this data%'" + targetName="%column name of an object designation%" + expTime="%column name of an exposure time%" + targetClass="'%simbad taget class%'" + >//obscore#publishSIAP</mixin>--> + <FEED source="localcolumns"/> </table> <coverage> @@ -72,12 +95,16 @@ with open(self.sourceToken, "rb") as f: fitses = pickle.load(f) - + for fitsdesc in fitses: + # relpath must be the path relative to the root URL given below. + relpath = fitsdesc["name"][2:] + rawdict = dict( (card.keyword.replace("-", "_"), card.value) for card in fitstools.parseCards(fitsdesc["header"])) - rawdict["accref"] = fitsdesc["name"] + rawdict["relpath"] = relpath + rawdict["accref"] = "svc_2019/"+relpath rawdict["fsize"] = fitsdesc["size"] yield rawdict </code> @@ -87,10 +114,10 @@ <bind key="accref">@accref</bind> <bind key="fsize">@fsize</bind> <bind key="path" - >"https://alta.astron.nl/webdav/SVC_2019_Imaging/"+accref</bind> + >"https://alta.astron.nl/webdav/SVC_2019_Imaging/"+@relpath</bind> <bind key="preview" >"https://alta.astron.nl/alta-static/media/"+( - accref[:-5]+".png")</bind> + @relpath[:-5]+".png")</bind> <bind key="preview_mime">"image/png"</bind> </rowfilter> @@ -98,14 +125,12 @@ <make table="main"> <rowmaker> - <map key="beam_major">@BMAJ</map> - <map key="beam_minor">@BMIN</map> - <map key="beam_pa">@BPA</map> + <map key="beam_major" nullExcs="KeyError">@BMAJ</map> + <map key="beam_minor" nullExcs="KeyError">@BMIN</map> + <map key="beam_pa" nullExcs="KeyError">@BPA</map> <map key="object">@OBJECT</map> - - <map key="bandpassRefval">LIGHT_C/@CRVAL3</map> - <map key="bandpassLo">LIGHT_C/(@CRVAL3+@CDELT3)</map> - <map key="bandpassHi">LIGHT_C/(@CRVAL3-@CDELT3)</map> + <map key="obsid">@relpath.split("/")[0]</map> + <map key="datalink">\dlMetaURI{dl}</map> <apply procDef="//siap#setMeta"> <bind key="dateObs">@DATE_OBS</bind> @@ -116,21 +141,85 @@ <apply> <code> - if @NAXIS4==1: - @NAXIS -= 1 - if @NAXIS3==1: + if "NAXIS4" in vars: + if @NAXIS4==1: @NAXIS -= 1 + if @NAXIS3==1: + @NAXIS -= 1 </code> </apply> <apply procDef="//siap#computePGS"/> - <!-- any custom columns need to be mapped here; do *not* use - idmaps="*" with SIAP --> + <apply name="computeBandpass"> + <code> + # right now, the spectral axis is always 3, so let's try + # this. If this ever becomes variable, we'll probably + # want to look at CTYPEn for FREQ-OBS + specAxis = getWCSAxis(vars, 3, True) + nSpecPix = vars.get("NAXIS3") + if not nSpecPix: + return + elif nSpecPix==1: + result["bandpassRefval"] = LIGHT_C/specAxis.pixToPhys(1) + result["bandpassLo"] = LIGHT_C/specAxis.pixToPhys(0.5) + result["bandpassHi"] = LIGHT_C/specAxis.pixToPhys(1.5) + elif nSpecPix>1: + result["bandpassRefval"] = LIGHT_C/specAxis.pixToPhys(nSpecPix/2) + result["bandpassHi"] = LIGHT_C/specAxis.pixToPhys(nSpecPix+0.5) + result["bandpassLo"] = LIGHT_C/specAxis.pixToPhys(0.5) + </code> + </apply> + </rowmaker> </make> </data> + <service id="dl" allowed="dlmeta"> + <meta name="description"> + This datalink service gives all data products related to an observation. + Pass in accrefs of any product that's resulted from the observation. + </meta> + + <datalinkCore> + <descriptorGenerator> + <code> + accref = pubDID.split("?")[-1] + desc = ProductDescriptor.fromAccref(pubDID, accref) + return desc + </code> + </descriptorGenerator> + + <metaMaker> + <setup> + <par name="fnameToMeta"> { + "image_mf_V.fits": ( + "#derivation", + "Continuum image generated by summing along the spectral axis"), + }</par> + </setup> + <code> + obsid = descriptor.pubDID.split("/")[1] + with base.getTableConn() as conn: + for row in conn.queryToDicts( + "SELECT * FROM \schema.main" + " WHERE obsid=%(obsid)s", locals()): + + sem, desc = fnameToMeta.get( + row["accref"].split("/")[-1], + ("#unknown", "Missing Description")) + + yield descriptor.makeLink( + row["accref"], + semantics=sem, + description=desc, + contentType="image/fits", + contentLength=row["accsize"]) + </code> + </metaMaker> + </datalinkCore> + </service> + <!-- if you want to build an attractive form-based service from SIAP, you probably want to have a custom form service; for just basic functionality, this should do, however. -->