<resource schema="mlqso">
	<!-- The publication the things come from, for image title purposes -->
	<macDef name="sourcepub">2012A&amp;A...544A..62S</macDef>

	<meta name="creationDate">2012-04-24T12:46:00Z</meta>
	<meta name="schema-rank">1000</meta>
	<meta name="title">Spectra of Strongly Lensed Quasars</meta>
	<meta name="creator">Sluse, D.</meta>

	<meta name="subject">strong-gravitational-lensing</meta>
	<meta name="subject">quasars</meta>
	<meta name="subject">spectroscopy</meta>

	<meta name="description" format="rst"><![CDATA[
		An archive of optical and near-infrared spectra of strongly lensed
		quasars and the lensing galaxies.  The spectra are resolved to about a
		few Ångstroms and are flux-calibrated.  The spectra resulted from
		deblending the lensed images in bidimensional spectra available from
		the SSAP service for `ivo://org.gavo.dc/mlqso/q/s
		<\internallink{mlqso/q/s/info}>`_.
	]]></meta>

	<meta name="source">2012A&amp;A...544A..62S</meta>
	<meta name="coverage.waveband">Optical</meta>
	<meta name="coverage.waveband">Infrared</meta>
	<meta name="data.type">Archive</meta>
	<meta name="facility">Very Large Telescope</meta>
	<meta name="instrument">FORS</meta>

	<meta name="_related" title="Slit spectra"
		>\internallink{mlqso/q/webcube/form}</meta>
	<meta name="_related" title="Bidim. spectra (SSAP)"
		>\internallink{mlqso/q/s/info}</meta>
	<meta name="_related" title="Bidim. spectra"
		>\internallink{mlqso/q/sf/form}</meta>
	<meta name="_related" title="QSO spectra (SSAP)"
		>\internallink{mlqso/q/q/info}</meta>
	<meta name="_related" title="QSO spectra"
		>\internallink{mlqso/q/web/form}</meta>

	<FEED source="//procs#license-cc-by" what="Data in this service"/>

	<table id="slitspectra" onDisk="True">
		<meta name="description">
			Bidimensional spectra of galaxies lensing QSOs.
		</meta>
		<meta name="_associatedDatalinkService">
			<meta name="serviceId">dlraw</meta>
			<meta name="idColumn">ssa_pubDID</meta>
		</meta>
		<mixin
			fluxUnit=" "
			spectralUnit="10**-9m"
			creator="Dominique Sluse"
			instrument="FORS"
			dataSource="pointed"
			creationType="archival"
			collection="mlqso"
			reference="2012A&amp;A...544A..62S"
			fluxCalibration="UNCALIBRATED"
			spectralCalibration="ABSOLUTE"
			spectralResolution="1e-10"
		>//ssap#hcd</mixin>
		<mixin
			facility_name="'Very Large Telescope'"
			em_res_power="2000"
			calibLevel="1">//obscore#publishSSAPHCD</mixin>
		<column name="remark" type="text"
			ucd="meta.note"
			tablehead="Remark"
			description="Remarks on the data set by the data creator."
			verbLevel="10"/>
	</table>

	<table id="fluxes" onDisk="True">
		<meta name="description">
			Uncalibrated flux values for the observations in the slitspectra
			table.
		</meta>

		<index columns="obsId" cluster="True"/>
		<index columns="lambda"/>

		<column name="obsId" type="text"
			tablehead="Obs"
			description="Internal identifier of the observation"/>
		<column name="lambda"
			unit="nm"
			tablehead="λ"
			description="Wavelength"/>
		<column name="flux"
			unit="Jy"
			tablehead="flux"
			description="Flux"/>
		<column name="error"
			unit="Jy"
			tablehead="Err. flux"
			description="Error in Flux"/>
	</table>


	<table id="qsospectra" onDisk="true">
		<meta name="description">
			Spectra of lensed components, deconvolved from the spatially resolved
			spectra in the slitspectra table.
		</meta>
		<meta name="_associatedDatalinkService">
			<meta name="serviceId">dlqso</meta>
			<meta name="idColumn">ssa_pubDID</meta>
		</meta>
		<mixin
			fluxUnit="10**-28J m-3"
			spectralUnit="10**-9m"
			creator="Dominique Sluse"
			instrument="FORS"
			dataSource="pointed"
			creationType="archival"
			reference="Sluse, A&amp;A, submitted"
			fluxCalibration="ABSOLUTE"
			spectralCalibration="ABSOLUTE"
			spectralResolution="1e-10"
		>//ssap#hcd</mixin>
		<column name="remark" type="text"
			ucd="meta.note"
			tablehead="Remark"
			description="Remarks on the data set by the data creator."
			verbLevel="10"/>
	</table>

	<table id="cubes" onDisk="True" namePath="//obscore#ObsCore">
		<mixin>//products#table</mixin>
		<meta name="_associatedDatalinkService">
			<meta name="serviceId">dlqso</meta>
			<meta name="idColumn">obs_publisher_did</meta>
		</meta>
		<mixin
			productType="'cube'"
			title="obs_title"
			ra="s_ra"
			dec="s_dec"
			coverage="s_region"
			fov="0.002"
			emMin="4e-7"
			emMax="8e-7"
			em_ucd="'em.wl'"
			em_xel="1224"
			tMin="t_min"
			tMax="t_max"
			oUCD="'phot.flux;em.opt'"
			sResolution="0.0001"
			facility_name="'Very Large Telescope'"
			instrumentName="'FORS'"
			mime="'application/fits'"
			calibLevel="1"
			targetName="target_name"
			targetClass="'QSO'"
			emResPower="600"
			did="obs_publisher_did"
			collectionName="'mlqso slit'"
		>//obscore#publish</mixin>
		<meta name="description">
			Bidirectional spectra as FITS image.
		</meta>
		<LOOP listItems="obs_id obs_title obs_publisher_did
			target_name t_exptime t_min t_max s_region s_ra s_dec">
			<events>
				<column original="\item"/>
			</events>
		</LOOP>

		<column name="datalink" type="text"
			ucd="meta.ref.url"
			tablehead="Datalink"
			description="Datalinks (related data, cutouts, etc) for this dataset"
			verbLevel="15"
			displayHint="type=url">
			<property name="targetType"
				>application/x-votable+xml;content=datalink</property>
			<property name="targetTitle">Datalink</property>
		</column>
	</table>

	<table id="instance" onDisk="False">
		<mixin ssaTable="slitspectra"
			spectralDescription="Wavelength"
			fluxDescription="Flux"
			>//ssap#sdm-instance</mixin>

		<meta name="description">A spectrum from a slit spectrum obtained
			for systems of quasars and lensing galaxies.  See
			ivo://org.gavo.dc/mlqso/q/q</meta>

		<column name="fluxerror" unit="adu" ucd="stat.error;phot.flux;em.opt"/>
	</table>

	<coverage>
		<updater sourceTable="qsospectra" mocOrder="8"/>
			<spectral>2.23976e-19 4.66302e-19</spectral>
			<temporal>53304 53969</temporal>
			<spatial>8/73542,76229,269379,280164,361299,420262,421952,432077,435726,588262,714781,758793,774232</spatial>
	</coverage>

	<data id="import_cubes">
		<property key="previewDir">previews</property>
		<sources pattern="data/*_data.fits" recurse="True">
			<!-- the following file yields a "segment overlaps" error from pgsphere
			that apparently is due to a bug.  When that bug is fixed, unignore this
			source  -->
			<ignoreSources patterns="*J1226*"/>
		</sources>
		<fitsProdGrammar qnd="True">
			<rowfilter procDef="//products#define">
				<bind name="table">'\schema.cubes'</bind>
				<bind name="preview_mime">"image/jpeg"</bind>
				<bind name="preview">\standardPreviewPath</bind>
			</rowfilter>
		</fitsProdGrammar>
		<make table="cubes">
			<rowmaker>
				<apply name="getCoverage">
					<setup>
						<code>
							from gavo.base.coords import wcs
							atan2, sin, cos = math.atan2, math.sin, math.cos
						</code>
					</setup>
					<code>
						# astropy calcFootprint can't know what to do here
						transform = wcs.WCS(vars["header_"], naxis=(2,3)).all_pix2world
						slitStart = transform(1,0,0)
						slitEnd = transform(@NAXIS2,0,0)
						ra0, dec0 = float(slitStart[0]), float(slitStart[1])
						ra1, dec1 = float(slitEnd[0]), float(slitEnd[1])

						# make make a polygon by shifting the slit a couple of
						# arcsecs left and right
						pa = atan2(ra1-ra0, dec1-dec0)
						w = 0.001
						result["s_region"] = pgsphere.SPoly([
							pgsphere.SPoint.fromDegrees(ra0+w*sin(pa),dec0-w*cos(pa)),
							pgsphere.SPoint.fromDegrees(ra1+w*sin(pa),dec1-w*cos(pa)),
							pgsphere.SPoint.fromDegrees(ra1-w*sin(pa),dec1+w*cos(pa)),
							pgsphere.SPoint.fromDegrees(ra0-w*sin(pa),dec0+w*cos(pa))])
						result["s_ra"] = float(ra0+ra1)/2
						result["s_dec"] = float(dec0+dec1)/2
					</code>
				</apply>

				<var name="pubDID"
					>"ivo://org.gavo.dc/tap?"+\inputRelativePath</var>
				<map dest="obs_id">@pubDID</map>
				<map dest="obs_title"
						>"\sourcepub %s %s"%(@OBJECT, @MJD_OBS)</map>
				<map dest="obs_publisher_did">@pubDID</map>
				<map dest="target_name">@OBJECT</map>
				<map dest="t_exptime">@EXPTIME</map>
				<map dest="t_min">@TM_START</map>
				<map dest="t_max">@TM_END</map>
				<map dest="datalink">makeAbsoluteURL("/mlqso/q/d/dlmeta?ID=%s"%
					@pubDID)</map>
			</rowmaker>
		</make>
	</data>

	<data id="import_qso">
		<property key="previewDir">previews</property>
		<sources pattern="data/*[ABCD].fits"/>
		<fitsProdGrammar>
			<rowfilter procDef="//products#define">
				<bind name="table">"\schema.qsospectra"</bind>
				<bind name="preview_mime">"image/png"</bind>
				<bind name="preview">\standardPreviewPath</bind>
			</rowfilter>
		</fitsProdGrammar>
		<make table="qsospectra">
			<rowmaker idmaps="ssa_*">
				<var name="specLo">(@CRVAL1+(1-@CRPIX1)*@CDELT1)*1e-9</var>
				<var name="specHi">(@CRVAL1+(@NAXIS1-@CRPIX1)*@CDELT1)*1e-9</var>
				<var name="specExt">@specHi-@specLo</var>
				<var name="specMid">(@specHi+@specLo)/2</var>

				<apply procDef="//ssap#setMeta" name="qsometa">
					<bind name="pubDID"
						>"ivo://org.gavo.dc/mlqso/q/q?"+\inputRelativePath</bind>
					<bind name="length">@NAXIS1</bind>
					<bind name="specext">@specExt</bind>
					<bind name="targname">@OBJECT</bind>
					<bind name="alpha">@RA</bind>
					<bind name="delta">@DEC</bind>
					<bind name="redshift">@REDSHIFT</bind>
					<bind name="dateObs">mjdToDateTime(@MJD_OBS)</bind>
					<bind name="timeExt">@EXPTIME</bind>
					<bind name="specend">@specHi</bind>
					<bind name="cdate">@DATE</bind>
					<bind name="snr">100</bind>
					<bind name="targclass">"QSO"</bind>
					<bind name="specstart">@specLo</bind>
					<bind name="specmid">@specMid</bind>
					<bind name="dstitle"
						>"\sourcepub %s %s"%(@OBJECT, @MJD_OBS)</bind>
					<bind name="bandpass">"OPTICAL"</bind>
				</apply>

				<map dest="remark" src="REMARK"/>
			</rowmaker>
		</make>
	</data>

	<data id="import_slits" auto="False">
		<property key="previewDir">previews</property>
		<sources pattern="data/slits/*_data.fits"/>
		<customGrammar module="res/cubegrammar" isDispatching="True">
			<rowfilter procDef="//products#define">
				<bind key="table">"mlqso.slitspectra"</bind>
				<bind key="mime">"application/x-votable+xml"</bind>
				<bind key="path">\fullDLURL{d}</bind>
				<bind key="accref">"mlqso/"+@obsId</bind>
				<bind name="preview_mime">"image/png"</bind>
				<bind name="preview">\standardPreviewPath</bind>
			</rowfilter>
		</customGrammar>
		<make table="slitspectra" role="metadata">
			<rowmaker idmaps="ssa_*">
				<var name="specLo">(@CRVAL1+(1-@CRPIX1)*@CDELT1)*1e-9</var>
				<var name="specHi">(@CRVAL1+(@NAXIS1-@CRPIX1)*@CDELT1)*1e-9</var>
				<var name="specExt">@specHi-@specLo</var>
				<var name="specMid">(@specHi+@specLo)/2</var>

				<apply procDef="//ssap#setMeta" name="slitmeta">
					<bind name="pubDID"
						>"ivo://org.gavo.dc/mlqso/"+\inputRelativePath</bind>
					<bind name="length">@NAXIS1</bind>
					<bind name="specext">@specExt</bind>
					<bind name="targname">@OBJECT</bind>
					<bind name="redshift">@REDSHIFT</bind>
					<bind name="alpha">@RA</bind>
					<bind name="delta">@DEC</bind>
					<bind name="dateObs">mjdToDateTime(@MJD_OBS)</bind>
					<bind name="timeExt">@EXPTIME</bind>
					<bind name="specend">@specHi</bind>
					<bind name="cdate">@DATE</bind>
					<bind name="snr">100</bind>
					<bind name="specstart">@specLo</bind>
					<bind name="specmid">@specMid</bind>
					<bind name="dstitle"
						>"%s %s, pixel %s"%(@OBJECT, @MJD_OBS, @pixno)</bind>
					<bind name="bandpass">"OPTICAL"</bind>
				</apply>

				<map dest="remark">vars.get("REMARK", "")</map>
			</rowmaker>
		</make>
		<make table="fluxes" role="fluxes"/>
	</data>

	<data id="qsospect">
		<embeddedGrammar>
			<iterator>
				<setup>
					<code>
						from gavo.utils import fitstools
						from gavo.utils import pyfits
					</code>
				</setup>
				<code>
				hdu = pyfits.open(os.path.join(base.getConfig("inputsDir"),
					self.sourceToken["accref"]))[0]
				ax = fitstools.WCSAxis("lambda",
					hdu.header["CRVAL1"],
					hdu.header["CRPIX1"],
					hdu.header["CDELT1"],
					hdu.header["CTYPE1"])
				for ind, val in enumerate(hdu.data):
					yield {"flux": val, "spectral": ax.pixToPhys(ind+1)}
				 </code>
			</iterator>
		</embeddedGrammar>
		<make table="instance">
			<parmaker>
				<apply procDef="//ssap#feedSSAToSDM"/>
				<map dest="remark">vars.get("remark", "")</map>
			</parmaker>
		</make>
	</data>

	<service id="d" allowed="dlget,dlmeta,static">
		<meta name="title">Datalink service for full slit spectra</meta>
		<property name="staticData">data/slits</property>

		<datalinkCore>
			<descriptorGenerator procDef="//soda#fits_genDesc">
				<bind name="contentQualifier">"#slit-spectrum"</bind>
			</descriptorGenerator>
			<FEED source="//soda#fits_standardDLFuncs"
				accrefPrefix="mlqso/data/slits"
				spectralAxis="1"
				wavelengthOverride="'nm'"/>
			
			<metaMaker semantics="#error">
				<code>
					stem = descriptor.accref.split("/")[-1].split("_")[0]
					yield descriptor.makeLink(
						makeAbsoluteURL("\rdId/d/static/%s_err.fits"%stem),
						description="Associated errors",
						contentType="application/fits")
				</code>
			</metaMaker>
		</datalinkCore>
	</service>

	<data id="get_slitcomponent">
		<!-- datamaker to pull spectra values out of the database -->
		<embeddedGrammar>
			<iterator>
				<code>
					obsId = self.sourceToken["accref"].split("/")[-1]
					with base.getTableConn() as conn:
						for row in conn.queryToDicts(
								"SELECT lambda as spectral, flux, error as fluxerror"
								" FROM \schema.fluxes"
								" WHERE obsId=%(obsId)s ORDER BY lambda", {"obsId": obsId}):
							yield row
				</code>
			</iterator>
		 </embeddedGrammar>
		<make table="instance">
			 <parmaker>
				 <apply procDef="//ssap#feedSSAToSDM"/>
			 </parmaker>
		</make>
	</data>

	<service id="dlraw" allowed="dlget,dlmeta">
		<meta name="title">Datalink service to retrieve individual spectra</meta>
		<datalinkCore>
			<descriptorGenerator procDef="//soda#sdm_genDesc">
				<bind name="ssaTD">"\rdId#slitspectra"</bind>
				<bind key="useAccref">False</bind>
			</descriptorGenerator>
			<dataFunction procDef="//soda#sdm_genData">
				<bind name="builder">"\rdId#get_slitcomponent"</bind>
			</dataFunction>
			<FEED source="//soda#sdm_plainfluxcalib"/>
			<FEED source="//soda#sdm_cutout"/>
			<FEED source="//soda#sdm_format"/>
		</datalinkCore>
	</service>

	<service id="s" allowed="ssap.xml">
		<meta name="title">Lensed QSOs, bidimensional spectra (SSAP)</meta>
		<meta name="description">Reduced bidimensional spectra across
			lensed QSO systems (not flux calibrated).
			The extracted spectra of the quasar lensed images
			are avalialable from ivo://org.gavo.dc/mlqso/q/q.</meta>
		<meta name="short_name">mlqso bidi ssa</meta>
		<ssapCore queriedTable="slitspectra">
			<property name="previews">auto</property>
			<FEED source="//ssap#hcd_condDescs"/>
		</ssapCore>
	</service>

	<service id="sf" allowed="form">
		<meta name="title">Lensed QSOs, bidimensional spectra</meta>
		<meta name="description">Reduced bidimensional spectra across
			lensed QSO systems (not flux calibrated).
			The extracted spectra of the quasar lensed images
			are avalialable from ivo://org.gavo.dc/mlqso/q/q.</meta>
		<meta name="short_name">mlqso bidi form</meta>

		<dbCore queriedTable="slitspectra">
			<condDesc>
				<inputKey original="ssa_targname">
					<values fromdb="ssa_targname from mlqso.qsospectra order by
						ssa_targname"/>
				</inputKey>
			</condDesc>
			<condDesc buildFrom="ssa_dateObs"/>
			<outputTable autoCols="ssa_dstitle, accref, accsize,
				ssa_targname, ssa_location, ssa_dateObs"/>
		</dbCore>
	</service>

	<service id="web" allowed="form">
		<meta name="title">Spectra of lensed QSOs</meta>
		<meta name="shortName">mlqso web</meta>


		<dbCore queriedTable="qsospectra">
			<condDesc>
				<inputKey original="ssa_targname">
					<values fromdb="ssa_targname from mlqso.qsospectra order by
						ssa_targname"/>
				</inputKey>
			</condDesc>
			<condDesc buildFrom="ssa_dateObs"/>
		</dbCore>
		<outputTable autoCols="ssa_dstitle,ssa_redshift,
				ssa_timeExt,remark">
			<FEED source="//ssap#atomicCoords"/>
			<outputField original="accref" displayHint="type=product"/>
			<outputField original="ssa_dateObs" displayHint="type=humanDate"/>
			<outputField original="ssa_specstart" displayHint="displayUnit=nm"/>
			<outputField original="ssa_specend" displayHint="displayUnit=nm"/>
		</outputTable>
	</service>

	<service id="dlqso" allowed="dlget,dlmeta">
		<meta name="title">Datalink service to retrieve QSO spectra</meta>
		<datalinkCore>
			<descriptorGenerator procDef="//soda#sdm_genDesc">
				<bind name="ssaTD">"\rdId#qsospectra"</bind>
				<bind name="useAccref">False</bind>
			</descriptorGenerator>
			<dataFunction procDef="//soda#sdm_genData">
				<bind name="builder">"\rdId#qsospect"</bind>
			</dataFunction>
			<FEED source="//soda#sdm_plainfluxcalib"/>
			<FEED source="//soda#sdm_cutout"/>
			<FEED source="//soda#sdm_format"/>
		</datalinkCore>
	</service>

	<service id="q" allowed="ssap.xml">
		<meta name="title">Spectra of lensed QSOs (SSAP)</meta>
		<meta name="shortName">mlqso bidi ssa</meta>
		<meta name="ssap.dataSource">pointed</meta>
		<meta name="ssap.testQuery">POS=148.75,-1.5&amp;SIZE=0.1</meta>
		<meta name="ssap.creationType">spectralExtraction</meta>

		<ssapCore queriedTable="qsospectra">
			<property name="previews">auto</property>
			<FEED source="//ssap#hcd_condDescs"/>
		</ssapCore>
		<meta name="short_name">mlqso ssa</meta>
		<publish render="ssap.xml" sets="ivo_managed"/>
		<publish render="form" sets="ivo_managed,local" service="web"/>
	</service>

	<service id="webcube" allowed="form">
		<meta name="title">Slit spectra of lensed QSOs</meta>
		<meta name="shortName">mlqso slit web</meta>

		<dbCore queriedTable="cubes">
			<condDesc original="//scs#humanInput"/>
			<condDesc>
				<inputKey original="target_name">
					<values fromdb="target_name from mlqso.cubes order by target_name"/>
				</inputKey>
			</condDesc>
		</dbCore>

			<outputTable autoCols="accref, accsize, datalink, target_name,
					t_min, t_max,
					s_ra, s_dec, obs_title, obs_publisher_did">
			</outputTable>

	</service>


	<regSuite>
		<regTest title="slits datalink metadata">
			<url ID="ivo://org.gavo.dc/~?mlqso/data/slits/Q0142_data.fits"
				>d/dlmeta</url>
			<code><![CDATA[
				self.assertHasStrings(
					"/mlqso/q/d/static/Q0142_err.fits",
					"<TD>#error</TD>",
					"mlqso/data/slits/Q0142_data.fits</TD>",
					"406080",
					'<MIN value="-9.7549465997',
					'<MAX value="-9.7544977981',
					'#slit-spectrum')
				self.assertXpath("//v:PARAM[@ucd='em.wl']/v:VALUES/v:MIN",
					{"value": "4.4e-07"})
			]]></code>
		</regTest>

		<regTest title="slits soda cutout">
			<url
				ID="ivo://org.gavo.dc/~?mlqso/data/slits/Q0142_data.fits"
				CIRCLE="26.3180 -9.7546 0.0001"
				BAND="4.6e-7 4.65e-7"
			>d/dlget</url>
			<code>
			self.assertHasStrings(self.data,
				"NAXIS1  =                   20",
				"NAXIS2  =                    9",
				b"DN\\xfa\\x85DZ\\xa9\\xe4DL1")
			</code>
		</regTest>

		<regTest title="mlq qso soda cutout">
			<url
				ID="ivo://org.gavo.dc/mlqso/q/q?mlqso/data/HE0047B.fits"
				BAND="4.6e-7 4.65e-7"
				FORMAT="application/fits"
			>dlqso/dlget</url>
			<code>
			self.assertHasStrings(self.data,
				"NAXIS1  =                   20",
				"NAXIS2  =                   19",
				"\\t+")
			</code>
		</regTest>

		<regTest title="mlqso SSA queryData works." tags="bigserver">
			<url RESPONSEFORMAT="votabletd" REQUEST="queryData"
				POS="148.75094277675205, -2.5013888783513862"
				MAXREC="50" SIZE="1.0">s/ssap.xml</url>
			<code><![CDATA[
				self.assertHasStrings(
					"An archive of optical and near-infrared spectra",
					"<TD>BRI0952-0115</TD>",
					"148.750049822028", "-1.5013986999906",
					'value="ivo://ivoa.net/std/soda#sync-1.0"',
					'ref="ssa_pubDID"')
			]]></code>
		</regTest>
	</regSuite>
</resource>
