<resource schema="bgds">
	<macDef name="pubDIDBase">ivo://\getConfig{ivoa}{authority}/~?\rdId/</macDef>
	
	<meta name="creationDate">2018-07-18T11:44:26Z</meta>
	<meta name="schema-rank">20</meta>

	<meta name="title">BGDS time series</meta>
	<meta name="description" format="rst">
		From the Bochum Galactic Disk Survey, time series have been obtained in the
		r and i bands on an (up to) nightly basis. Depending on the field, the time
		series contain up to more than 300 nights over more than 7 years. Each
		measurement represents the averaged flux over 10 minutes of observation
		(from 9 averaged 10s images).

		The Bochum Galactic Disk Survey is an ongoing project to monitor the
		stellar content of the Galactic disk in a 6 degree wide stripe centered on
		the Galactic plane. The data has been recorded since mid-2010 in Sloan r
		and i simultaneously with the Robotic Bochum Twin Telescope (RoBoTT) at the
		Universitaetssternwarte Bochum near Cerro Armazones in the Chilean Atacama
		desert. It contains measurements of about 2x10^7 stars over more than seven
		years. Additionally, intermittent measurements in Johnson UVB and Sloan z
		have been recorded as well.
	</meta>

	<meta name="IsContinuedBy">
		<meta name="ivoId">ivo://org.gavo.dc/bgds/l2/ssa</meta
		>BGDS DR2 Lightcurves</meta>

	<meta name="subject">surveys</meta>
	<meta name="subject">galaxy-planes</meta>
	<meta name="subject">milky-way-galaxy</meta>
	<meta name="subject">variable-stars</meta>
	<meta name="subject">broad-band-photometry</meta>
	<meta name="subject">time-domain-astronomy</meta>

	<meta name="creator">Hackstein, M.; Haas, M.; Fein, C.; Chini, R.</meta>
	<meta name="instrument">Robotic Bochum Twin Telescope (RoBoTT)</meta>
	<meta name="facility">Universitätssternwarte Bochum near Cerro
		Armazones</meta>

	<meta name="source">2015AN....336..590H</meta>
	<meta name="contentLevel">Research</meta>
	<meta name="type">Survey</meta>
	<meta name="productTypeServed">timeseries</meta>

	<meta name="copyright" format="rst">
		If you use GDS data, please cite
		:bibcode:`2015AN....336..590H`.
	</meta>

	<meta name="isPreviousVersionOf"
		ivoId="ivo://org.gavo.dc/bgds/l2/ssa">BGDS light curves DR2</meta>

	<meta name="coverage">
		<meta name="waveband">Optical</meta>
	</meta>

	<!-- ####################################################3
	     basic tables (essentially from upstream -->

	<STREAM id="common_columns">
		<stc>
			Position ICRS "ra" "dec"
		</stc>

		<column name="obs_id" type="text"
			ucd="meta.id;meta.main"
			description="Main identifier of this observation (a single
				object may have multiple observations in different bands and fields)"
			verbLevel="1"/>

		<column name="ra" type="double precision"
			ucd="pos.eq.ra;meta.main"
			description="ICRS right ascension for this object."
			verbLevel="1"/>
		<column name="dec" type="double precision"
			ucd="pos.eq.dec;meta.main"
			description="ICRS declination for this object."
			verbLevel="1"/>
		<column name="mean_mag"
			unit="mag" ucd="phot.mag;stat.mean"
			tablehead="〈mag〉"
			description="Mean magnitude in \banddesig."
			verbLevel="5"/>
		<column name="err_mag"
			unit="mag" ucd="stat.error;phot.mag"
			tablehead="Err〈mag〉"
			description="Error in mean magnitude in this band"
			verbLevel="15"/>
		<column name="amp"
			unit="mag" ucd="phot.mag;arith.diff"
			tablehead="Amplitude"
			description="Difference between brightest and weakest observation."
			verbLevel="15"/>

		<column name="flux"
			unit="mJy" ucd="phot.flux;stat.mean"
			tablehead="〈flux〉"
			description="Mean flux in this band; this is computed from the
				mean magnitude based on Landolt standard stars."
			verbLevel="5"/>
		<column name="err_flux"
			unit="mJy" ucd="stat.error;phot.flux"
			tablehead="Err〈flux〉"
			description="Error in mean flux in this band"
			verbLevel="15"/>
		<column name="nobs" type="smallint" required="True"
			ucd="meta.number;obs"
			tablehead="#Obs"
			description="Number of observations in this light curve"
			verbLevel="25"/>
	</STREAM>


	<NXSTREAM id="common-makerstuff">
		<simplemaps>
			ra:RA, dec:DEC,
			err_mag: MAGERR,
			amp: AMP,
			flux: FLUX, err_flux: FLUXERR,
			nobs: NOBS,
		</simplemaps>
		<var key="fieldid"
			>re.search("GDS_([^/]*)", \\\\inputRelativePath).group(1)</var>
		<map key="mean_mag" source="MAG(MED)"/>
		<map key="obs_id">"BGDS-%s-\\band-%.7f%+.7f"%(@fieldid, @RA, @DEC)</map>
	</NXSTREAM>

	<LOOP>
		<csvItems>
			band, filter, pathspec
			b,  Johnson B, B_j
			u,  Johnson U, U_j
			v,  Johnson V, V_j
			z,  SDSS z,    z_s
		</csvItems>
		<events>
			<table id="phot_\band" onDisk="True" mixin="//scs#q3cindex" adql="Hidden">
				<mixin>//scs#pgs-pos-index</mixin>
				<meta name="description">
					BGDS wideband photometry in the \filter band.  A union of all
					the BGDS measurements is available in phot_all.
				</meta>

				<FEED source="common_columns" banddesig="the \filter band."/>
				<primary>obs_id</primary>
			</table>

			<data id="import_\band">
				<sources pattern="data/tables/*/\pathspec/*.fits.gz"/>

				<fitsTableGrammar/>

				<make table="phot_\band">
					<rowmaker>
						<FEED source="common-makerstuff"/>
					</rowmaker>
				</make>
			</data>
		</events>
	</LOOP>

	<LOOP>
		<csvItems>
			band, filter, pathspec
			i,  SDSS i,   i_s
			r,  SDSS r,   r_s
		</csvItems>
		<events>
			<table id="phot_\band" onDisk="True" mixin="//scs#q3cindex" adql="Hidden">
				<mixin>//scs#pgs-pos-index</mixin>
				<meta name="description">
					BGDS mean broadband photometry and lightcurves measurements
					in the \filter band.  All BGDS broadband mean photometry
					is available in phot_all.
				</meta>

				<index columns="time_min"/>
				<index columns="time_max"/>

				<FEED source="common_columns" banddesig="the \filter band"/>

				<!-- the following index is for obscore, in particular the
				datalink on obscore, which needs quick pubDID searches -->
				<index name="obscore\\tablename\\+pubdid"
					>('\\pubDIDBase' || obs_id)</index>

				<index columns="field"/>
				<index columns="ssa_location" method="GIST"/>

				<column name="ssa_location" type="spoint"
					description="The observed position as an ADQL POINT"
					verbLevel="35"/>

				<column name="mjds" type="double precision[154]"
					unit="d" ucd="time.epoch"
					tablehead="T[]"
					description="An array containing the epochs of the time series"
					verbLevel="30"/>
				<column name="mags" type="real[154]"
					unit="mag" ucd="phot.mag"
					tablehead="mag[]"
					description="An array containing the values of the time series."
					verbLevel="30"/>
				<column name="mag_errs" type="real[154]"
					unit="mag" ucd="stat.error;phot.mag"
					tablehead="Err(mag)[]"
					description="An array containing the errors of mags."
					verbLevel="30"/>

				<column name="variable" type="boolean" required="True"
					ucd="meta.code;src.var"
					tablehead="Var?"
					description="1 if the object is classified as variable by the BGDS
						pipeline"
					verbLevel="15"/>

				<column name="time_min" type="double precision" xtype="mjd"
					unit="d" ucd="time.epoch;stat.min"
					tablehead="1. Obs"
					description="First timestamp in time series (MJD Topocentric UTC)"
					verbLevel="1"/>
				<column name="time_max" type="double precision" xtype="mjd"
					unit="d" ucd="time.epoch;stat.max"
					tablehead="Last Obs"
					description="Last timestamp in time series (MJD Topocentric UTC)"
					verbLevel="1"/>
				<column name="time_mean" type="double precision"
					unit="d" ucd="time.epoch;stat.mean"
					tablehead="&lt;Obs>"
					description="Mean epoch of observation"
					verbLevel="25"/>
				<column name="length" type="smallint" required="True"
					tablehead="#Meas"
					description="Number of good measurements"
					verbLevel="25"/>

				<column name="field" type="text"
					ucd="meta.id;obs.field"
					tablehead="Field"
					description="Survey field observed."
					verbLevel="15">
				</column>
			</table>

			<data id="import_\band">
				<sources pattern="data/tables/*/\pathspec/*.fits.gz"/>

				<fitsTableGrammar/>

				<make table="phot_\band">
					<rowmaker id="make_with_time_series">
						<FEED source="common-makerstuff"/>
						<apply name="remove_invalid_measurements">
							<code>
								@LCMJD = @LCMJD[@LCMAG!=99.0]
								@LCMAGERR = @LCMAGERR[@LCMAG!=99.0]
								@LCMAG = @LCMAG[@LCMAG!=99.0]
							</code>
						</apply>
						<map key="mjds" source="LCMJD"/>
						<map key="mags" source="LCMAG"/>
						<map key="mag_errs" source="LCMAGERR"/>
						<map key="variable" source="VARIABLE"/>
						<map key="time_min">min(@LCMJD)</map>
						<map key="time_max">max(@LCMJD)</map>
						<map key="time_mean">sum(@LCMJD)/@LCMJD.shape[0]</map>
						<map key="length">@LCMAG.shape[0]</map>
						<map key="field">\\inputRelativePath.split("/")[-3]</map>
						<map key="ssa_location"
							>pgsphere.SPoint.fromDegrees(@RA, @DEC)</map>
					</rowmaker>
				</make>
			</data>
		</events>
	</LOOP>

		<coverage>
			<!-- copied from bgds/q -->
			<spectral>1.777e-19 6.621e-19</spectral>
			<temporal>55450 58106.4</temporal>
			<spatial>3/336,338,450-451,461,472,591-592,613,615,621,651-652,659,662-663 4/1301,1303,1358,1376-1377,1379-1380,1382,1794,1816,1818-1819,1822-1823,1829,1840-1841,1892,1894,1897,2327,2333,2335,2357-2359,2376,2378,2400,2402,2408,2492-2493,2495,2528,2530,2536,2538,2591,2599,2601-2603,2612-2614,2616,2634-2635,2643,2646-2647,2656-2657,2688-2690</spatial>
	</coverage>

	<table id="phot_all" adql="true" onDisk="True">
		<meta name="description">
			All mean photometry of bgds in one table.  It may be simpler
			to write queries against the split-band tables phot_band.
			Measurements in different fields and bands have not been merged, as
			that procedure is too error-prone in crowded milky way regions.
		</meta>
		<column name="band_name" type="text"
			ucd="meta.id;instr.filter"
			tablehead="Filter"
			description="The band the mean photometry is given for."
			verbLevel="1"/>
		<FEED source="common_columns" banddesig="band given in phot_band"/>

		<viewStatement>
			CREATE VIEW \curtable AS (SELECT \colNames FROM (
					SELECT 'Johnson B' as band_name,
						b.*
					FROM \schema.phot_b as b
				UNION ALL
					SELECT 'Johnson U' as band_name,
						u.*
					FROM \schema.phot_u as u
				UNION ALL
					SELECT 'Johnson V' as band_name,
						v.*
					FROM \schema.phot_v as v
				UNION ALL
					SELECT 'SDSS z' as band_name,
						z.*
					FROM \schema.phot_z as z
				UNION ALL
					SELECT 'SDSS i' as band_name,
						obs_id, ra, dec, mean_mag, err_mag, amp, flux, err_flux, nobs
					FROM \schema.phot_i as i
				UNION ALL
					SELECT 'SDSS r' as band_name,
						obs_id, ra, dec, mean_mag, err_mag, amp, flux, err_flux, nobs
					FROM \schema.phot_r as r
			) as allbands)
		</viewStatement>
	</table>

	<data id="make_phot_all">
		<make table="phot_all"/>
	</data>

	<service id="meanphot" allowed="form,scs.xml">
		<publish render="scs.xml" sets="ivo_managed"/>
		<publish render="form" sets="local,ivo_managed"/>
		<meta name="shortName">BGDS mean phot</meta>
		<meta name="title">BGDS Mean Photometry Cone Search</meta>
		<meta name="description">Extracted sources from the Bochum Galactic
			Disk Survey.  We provide mean photometry in U, B, V, z, r, and i
			bands.  Note that sources in different bands are not matched.
			Also, sources sitting in the regions imaged in multiple fields
			have not been matched even within one band.

			In i and r, BGDS light curves are available.  See related
			services for details.
		</meta>
		<meta>
			testQuery.ra:  100.14501
			testQuery.dec: -1.65446
			testQuery.sr:  0.0001
		</meta>
		<scsCore queriedTable="phot_all">
			<FEED source="//scs#coreDescs"/>
     	<condDesc buildFrom="mean_mag"/>
     	<condDesc buildFrom="err_mag"/>
     	<condDesc buildFrom="amp"/>
     	<condDesc>
     		<inputKey original="band_name">
     			<values id="bandnames">
						<option>Johnson B</option>
						<option>SDSS i</option>
						<option>SDSS r</option>
						<option>Johnson V</option>
						<option>Johnson U</option>
						<option>SDSS z</option>
     			</values>
     		</inputKey>
     	</condDesc>
		</scsCore>
	</service>


	<!-- ######################################################
	     SSA+time series ###################################### -->

	<table id="ssa_time_series" onDisk="true" adql="Hidden">
		<meta name="description">
			This table contains about metadata about the photometric time
			series from BGDS in IVOA SSA format.  The actual data is
			available through a datalink service or in the phot_i and
			phot_r tables.
			</meta>

		<meta name="_associatedDatalinkService">
			<meta name="serviceId">tsdl</meta>
			<meta name="idColumn">ssa_pubDID</meta>
		</meta>

		<mixin
			fluxUCD="phot.flux.density;em.wl"
			fluxUnit="s**-1"
			spectralUnit="m"
			spectralUCD="em.wl"
			>//ssap#mixc</mixin>

		<stc>
			TimeInterval UTC TOPOCENTER "time_min" "time_max"
		</stc>

		<column original="phot_all.obs_id"/>
		<column original="phot_i.time_min"/>
		<column original="phot_i.time_max"/>
		<column original="phot_all.amp"/>
		<column original="phot_all.mean_mag"/>
		<column original="phot_i.field"/>
		<column original="phot_i.ra"/>
		<column original="phot_i.dec"/>
		<column original="phot_i.mjds"/>
		<column original="phot_i.mags"/>

		<viewStatement>
			CREATE VIEW \curtable AS (SELECT \colNames FROM
				(SELECT
				obs_id as obs_id,
				amp as amp,
				mean_mag as mean_mag,
				field as field,
				'\getConfig{web}{serverURL}/bgds/l/tsdl/dlget?ID='||obs_id as accref,
				NULL::text as owner,
				NULL::date as embargo,
				'application/x-votable+xml'::TEXT as mime,
				10000 as accsize,
				'BGDS ' || band || ' time series for ' || obs_id as ssa_dstitle,
				NULL::text as ssa_creatorDID,
				'\pubDIDBase' || obs_id as ssa_pubDID,
				NULL::timestamp as ssa_cdate,
				NULL::timestamp as ssa_pdate,
				band as ssa_bandpass,
				NULL::text as ssa_cversion,
				field as ssa_targname,
				NULL::text as ssa_targclass,
				NULL::real as ssa_redshift,
				NULL::spoint as ssa_targetpos,
				NULL::real as ssa_snr,
				NULL::real as ssa_aperture,
				ssa_location,
				time_mean as ssa_dateObs,
				time_max-time_min as ssa_timeExt,
				specmid as ssa_specmid,
				specend-specstart as ssa_specext,
				specstart as ssa_specstart,
				specend as ssa_specend,
				length as ssa_length,
				'timeseries'::TEXT as ssa_dstype,
				'ivo://org.gavo.dc/org'::TEXT as ssa_publisher,
				'Hackstein, M. et al'::TEXT as ssa_creator,
				'BGDS time series'::TEXT as ssa_collection,
				'\metaString{instrument}'::TEXT as ssa_instrument,
				'survey'::TEXT as ssa_datasource,
				'archival'::TEXT as ssa_creationtype,
				'\metaString{source}'::TEXT as ssa_reference,
				NULL::real as ssa_fluxStatError,
				NULL::real as ssa_fluxSysError,
				'ABSOLUTE'::TEXT as ssa_fluxcalib,
				NULL::real as ssa_binSize,
				NULL::real as ssa_spectStatError,
				NULL::real as ssa_spectSysError,
				'ABSOLUTE'::TEXT as ssa_speccalib,
				NULL::real as ssa_specres,
				time_min as time_min,
				time_max as time_max,
				ra as ra,
				dec as dec,
				mjds as mjds,
				mags as mags
				FROM (
				SELECT
					'SDSS i' as band,
					6.65e-7 as specstart,
					8.39e-7 as specend,
					7.44e-7 as specmid,
					* FROM \schema.phot_i
				UNION ALL
				SELECT
					'SDSS r' as band,
					5.42e-7 as specstart,
					6.99e-7 as specend,
					6.12e-7 as specmid,
					* FROM \schema.phot_r) as src) as q)
		</viewStatement>
	</table>

	<data id="make_ssa">
		<make table="ssa_time_series"/>
	</data>

	<service id="tsform" allowed="form">
		<meta name="title">Bochum Galactic Disk Survey (BGDS) light
			curves browser service</meta>
		<dbCore queriedTable="ssa_time_series">
			<condDesc buildFrom="ssa_location"/>
			<condDesc buildFrom="amp"/>
			<condDesc buildFrom="mean_mag"/>
			<condDesc buildFrom="field"/>
			<condDesc>
				<inputKey original="ssa_bandpass">
					<values>
						<option>SDSS i</option>
						<option>SDSS r</option>
					</values>
				</inputKey>
			</condDesc>
		</dbCore>

		<outputTable>
			<FEED source="//ssap#atomicCoords"/>
			<autoCols>accref, ssa_bandpass, mean_mag, amp</autoCols>
			<column original="time_min" displayHint="type=humanDate"/>
			<column original="time_max" displayHint="type=humanDate"/>
		</outputTable>
	</service>

	<service id="ssa" allowed="form,ssap.xml">
	 	<meta name="shortName">BGDS TS SSAP</meta>
		<meta name="ssap.dataSource">survey</meta>
		<meta name="ssap.creationType">archival</meta>
		<meta name="ssap.testQuery">MAXREC=1</meta>
		<meta name="ssap.complianceLevel">query</meta>
		<publish render="ssap.xml" sets="ivo_managed"/>
		<publish render="form" sets="ivo_managed,local" service="tsform"/>

		<meta name="title">Bochum Galactic Disk Survey (BGDS) light
			curves</meta>
		<meta name="description">This service exposes the
			Light curves of stars produced by the Bochum Galactic Disk Survey;
			several million light curves are provided in the SDSS i and r bands.
			The lightcurves are published per-band.  This is DR1; for new
			work, use DR2</meta>

		<ssapCore queriedTable="ssa_time_series">
			<FEED source="//ssap#hcd_condDescs">
				<PRUNE id="timeCond"/>
			</FEED>
			<condDesc>
				<inputKey name="TIME" type="pql-float"
					unit="d" ucd="time.epoch"
					utype="ssa:Char.TimeAxis.Coverage.Location.Value"
					description="Time covered by the time series"
					multiplicity="forced-single">
					<!-- TODO: enter limits -->
				</inputKey>
				<phraseMaker>
					<code>
					parsed = pql.PQLFloatPar.fromLiteral(
						inPars.get("TIME", None), "TIME")
					yield parsed.getSQLForInterval(
						"time_min", "time_max", outPars)
					</code>
				</phraseMaker>
			</condDesc>
			<condDesc buildFrom="field"/>
		</ssapCore>
	</service>


	<!-- ######################################################
	     building time series -->

	<STREAM id="time-series-template">
		<table id="instance_\band_short">
			<mixin	
				effectiveWavelength="\effective_wavelength"
				filterIdentifier='"\band_human"'
				longitude="@ra"
				latitude="@dec"
				phot_description="BDGS magnitude in \band_human"
				phot_ucd='phot.mag;\band_ucd'
				phot_unit="mag"
				pos_epoch="J2015.5"
				refframe="ICRS"
				refposition="BARYCENTER"
				time0="2400000.5"
				time_description="Barycentric time of observation"
				timescale="TCB"
			>//timeseries#phot-0</mixin>
			<dm>
				(ivoa:Measurement) {
					value: @phot
					statError: @mag_error
				}
			</dm>

			<dm>
				(ds:Dataset) {
					dataProductType: TIMESERIES
					title: @title
					curation:
						(ds:Curation) {
							calibLevel: 1
							publisher:
								(ds:Publisher) {
									name: "GAVO Data Center"
									publisherId: "ivo://org.gavo.dc"
								}
						}
				}
			</dm>

			<param name="obs_id" type="text"
				ucd="meta.id;meta.main"
				description="BGDS id of the observation"/>
			<param name="title" type="text"
				ucd="meta.title;obs"
				description="Publisher-assigned title of the data set"/>
			<param name="ra" type="double precision"
				ucd="pos.eq.ra"
				description="BGDS RA of source object"/>
			<param name="dec" type="double precision"
				ucd="pos.eq.dec"
				description="BGDS Dec of source object"/>
			<param name="filter" type="text"
				ucd="meta.id;instr.filter"
				description="Filter used."/>
			<param name="field" type="text"
				ucd="meta.id;obs.field"
				description="Field observed."/>

			<column name="mag_error"
				unit="mag" ucd="stat.error;phot.mag;\band_ucd"
				description="Error in \band_human magnitude."/>
			<column name="stamp_url" type="text"
				ucd="meta.ref.url"
				tablehead="Image"
				description="Link to a cutout of the source image."/>
		</table>
	</STREAM>

	<LOOP source="time-series-template">
		<csvItems>
			band_short, band_human, band_ucd, effective_wavelength
			i,          SDSS/i,     em.opt.I, 7.44e-7
			r,          SDSS/r,     em.opt.R, 6.12e-7
		</csvItems>
	</LOOP>

	<data id="make_instance" auto="False">
		<embeddedGrammar>
			<!-- the source token is a TSDescriptor from the tsdl service -->
			<iterator>
				<code>
					epochs, mags, errors = (
						self.sourceToken.row["mjds"],
						self.sourceToken.row["mags"],
						self.sourceToken.row["mag_errs"])

					labels = ["obs_time", "phot", "mag_error"]
					for tup in zip(epochs, mags, errors):
						res = dict(zip(labels, tup))
						res["field"] = self.sourceToken.row["field"]
						yield res
				</code>
			</iterator>

			<pargetter>
				<code>
					with base.getTableConn() as conn:
						res = list(conn.queryToDicts(
							"SELECT * FROM \schema.ssa_time_series WHERE obs_id=%(obs_id)s"
								" LIMIT 2",
							{"obs_id": self.sourceToken.obsId}))
					return res[0]
				</code>
			</pargetter>
		</embeddedGrammar>

		<make table="instance_i">
			<parmaker idmaps="obs_id">
				<map key="title">("BGDS %(ssa_bandpass)s time series for"
					" the observation %(obs_id)s")%vars</map>
				<map dest="ra">@ssa_location.asDALI()[0]</map>
				<map dest="dec">@ssa_location.asDALI()[1]</map>
				<map dest="field">"-".join(@obs_id.split("-")[1:3])</map>
				<map dest="filter">@ssa_bandpass</map>
			</parmaker>
			<rowmaker idmaps="*">
				<apply name="compute_stamp_url">
					<!-- unfortunately, it is impossible to forsee the file
					name from the data we have here; the dates in the file names
					are only loosely related to the MJD.  Hence, we use a special
					hack on the BGDS datalink service, which also accepts
					ID=MAGIC/field/band/mjd and will choose the best fit in
					the image DB.  Sigh. -->
					<code>
						pars = targetTable.getParamDict()
						imgId = "MAGIC/%s/%s/%f"%(
							pars["field"], pars["filter"], @obs_time)
						@stamp_url = ("http://dc.g-vo.org/bgds/q/dl/dlget?ID="
							+urllib.parse.quote(imgId)
							+"&amp;CIRCLE=%s+%s+%s"%(pars["ra"], pars["dec"], 0.01))
					</code>
				</apply>
			</rowmaker>
		</make>
	</data>

	<service id="tsdl" allowed="dlmeta,dlget">
		<meta name="title">BGDS time series datalink</meta>
		<meta name="description">
			This service produces time series datasets for Bochum
			Galactic Disk Survey lightcurves.
		</meta>

		<datalinkCore>
			<descriptorGenerator>
				<setup>
					<code>
						from gavo import svcs

						class TSDescriptor(ProductDescriptor):
							def __init__(self, pubDID):
								# We accept "local" pubDIDs (without ivo://...?), too
								if pubDID.startswith("ivo://"):
									self.pubDID = pubDID
									self.obsId = pubDID.split("?")[-1].split("/")[-1]
								else:
									self.obsId = pubDID
									self.pubDID = '\pubDIDBase'+pubDID

								self.band = self.obsId.split("-")[3]
								# ward off SQL injection
								if self.band not in "ir":
									raise svcs.UnknownURI(
										"No time series for band %s"%self.band)

								self.suppressAutoLinks = True

								with base.getTableConn() as conn:
									res = list(conn.queryToDicts(
										"SELECT * FROM \schema.phot_%s"
										" WHERE obs_id=%%(obsId)s"%self.band,
										{"obsId": self.obsId}))
								if not res:
									raise svcs.UnknownURI(
										"BGDS has no lightcurve for %s"%self.obsId)

								self.row = res[0]
					</code>
				</setup>
				<code>
					return TSDescriptor(pubDID)
				</code>
			</descriptorGenerator>

			<metaMaker semantics="#this">
				<code>
					yield descriptor.makeLink(
						makeAbsoluteURL("\rdId/tsdl/dlget?ID=%s"%(descriptor.pubDID)),
						description="BGDS time series for %s."%(
							descriptor.obsId),
						contentType="application/x-votable+xml",
						contentLength=15000,
						contentQualifier="#timeseries")
				</code>
			</metaMaker>

			<metaMaker semantics="#preview">
				<code>
					yield descriptor.makeLink(
						makeAbsoluteURL("\rdId/preview/qp/%s"%(descriptor.obsId)),
						description="Preview for %s"%descriptor.obsId,
						contentType="image/png",
						contentLength="2000")
				</code>
			</metaMaker>

			<dataFunction>
				<setup>
					<code>
						from gavo import rsc
					</code>
				</setup>
				<code>
					dd = rd.getById("make_instance")
					descriptor.data = rsc.Data.createWithTable(dd,
						rd.getById("instance_"+descriptor.band))
					descriptor.data = rsc.makeData(
						dd,
						data=descriptor.data,
						forceSource=descriptor)
				</code>
			</dataFunction>

			<dataFormatter>
				<code>
					from gavo import formats
					return (base.votableType, 	
						formats.getFormatted("vodml", descriptor.data))
				</code>
			</dataFormatter>
		</datalinkCore>
	</service>

	<service id="preview" allowed="qp">
		<property name="queryField">obs_id</property>
		<meta name="description">
			A service returning PNG thumbnails for time series.  It takes
			the obs id for which to generate a preview from the remaining
			fragments.
		</meta>
		<pythonCore>
			<inputTable>
				<inputKey name="obs_id" type="text"
					tablehead="Obs. Id"
					description="Observation id of the object to create the preview
						for."/>
			</inputTable>
			<coreProc>
				<setup>
					<code>
						from gavo.svcs import UnknownURI
						from gavo.helpers.processing import SpectralPreviewMaker
					</code>
				</setup>
				<code>
					obsId = inputTable.getParam("obs_id")
					# always go through a mapping here or you'll create a SQL injection.
					try:
						srcTable = {
							"r": "bgds.phot_r",
							"i": "bgds.phot_i",
							}[obsId.split("-")[3]]
					except KeyError:
						raise UnknownURI("No time series in the %s band here"%
							obsId.split("-")[3])

					with base.getUntrustedConn() as conn:
						res = list(conn.query(
							"SELECT mjds, mags FROM %s WHERE obs_id=%%(obs_id)s"%
								srcTable, {"obs_id": obsId}))
					if not res:
						raise UnknownURI("No time series for obs id %s."%obsId)
					return "image/png", SpectralPreviewMaker.get2DPlot(
						list(zip(*res[0])))
				</code>
			</coreProc>
		</pythonCore>
	</service>

	<regSuite title="bgds regression">
		<regTest title="BGDS SCS serves plausible data">
			<url RA="100.14501"
					DEC="-1.65446" SR="0.0001"
				>meanphot/scs.xml</url>
			<code>
				rows = self.getVOTableRows()
				rows.sort(key=lambda r: r["band_name"])
				self.assertTrue(set(r["band_name"] for r in rows).issuperset(
					set(["Johnson B", "SDSS z"])))
				self.assertAlmostEqual(rows[0]["mean_mag"], 17.506620407104492)
				self.assertEqual(rows[-1]["obs_id"], "BGDS-0644-0035-z-100.1449700-1.6543900")
			</code>
		</regTest>

		<regTest title="BGDS SSAP serves plausible data">
			<url REQUEST="queryData" POS="100.11441,-1.65559" SIZE="0.00001"
				field='GDS_0644-0035'
				>ssa/ssap.xml</url>
			<code>
				rows = self.getVOTableRows()
				self.assertEqual(len(rows), 1)
				self.assertEqual(rows[0]["ssa_pubDID"],
					"ivo://org.gavo.dc/~?bgds/l/BGDS-0644-0035-i-100.1144144-1.6555938")
				self.assertAlmostEqual(rows[0]["time_max"], 57800.038588)
				self.assertTrue(rows[0]["accref"].endswith(
					"bgds/l/tsdl/dlget?ID=BGDS-0644-0035-i-100.1144144-1.6555938"))
			</code>
		</regTest>

		<regTest title="BGDS time series form returns data (and links)">
			<url parSet="form" pos_ssa_location="100.726160 -1.656270"
				sr_ssa_location="0.1">tsform/form</url>
			<code><![CDATA[
				self.assertHasStrings(
					'bgds/l/tsdl/dlget?ID=BGDS-0644-0035-i-100.7261598-1.6562726">',
					'<td>SDSS i</td>',)
			]]></code>
		</regTest>

		<regTest title="BGDS time series retrievable (short id).">
			<url ID="BGDS-0644-0035-i-100.1144144-1.6555938"
				>tsdl/dlget</url>
			<code>
				row = self.getFirstVOTableRow(rejectExtras=False)
				self.assertAlmostEqual(row["obs_time"], 55467.348507)
				self.assertAlmostEqual(row["phot"], 16.1383553, 6)
				self.assertEqual(row["stamp_url"],
					EqualingRE(r"http://dc.g-vo.org/bgds/q/dl/dlget\\?ID=MAGIC/0644-0035/SDSS%20i/55467.348507&amp;CIRCLE=100.11441440.*\\+-1.6555938008.*\\+0.01"))
				self.assertXpath("//v:GROUP[@name='photcal']"
					"/v:PARAM[@name='filterIdentifier']", dict(
					ucd="meta.id;instr.filter",
					value="SDSS/i"))
			</code>
		</regTest>

		<regTest title="BGDS time series datalink">
			<url ID="ivo://org.gavo.dc/~?bgds/l/BGDS-0644-0035-r-100.2782207-1.6564102"
				>tsdl/dlmeta</url>
			<code>
				bySemantics = dict((row["semantics"], row)
					for row in self.getVOTableRows())
				self.assertTrue(bySemantics["#this"]["access_url"].endswith(
					"/bgds/l/tsdl/dlget?ID=ivo://org.gavo.dc/~"
						"?bgds/l/BGDS-0644-0035-r-100.2782207-1.6564102"))
				self.assertEqual(bySemantics["#this"]["content_qualifier"],
					"#timeseries")
				self.assertTrue(bySemantics["#preview"]["access_url"].endswith(
					"/bgds/l/preview/qp/BGDS-0644-0035-r-100.2782207-1.6564102"))
			</code>
		</regTest>

		<regTest title="BGDS time series preview gives a reasonable error message
				for a bad band">
			<url>preview/qp/BGDS-0644-0035-b-100.2782207-1.6564102</url>
			<code>
				self.assertHasStrings("No time series in the b band here")
				self.assertHTTPStatus(404)
			</code>
		</regTest>

		<regTest title="BGDS time series preview looks like a PNG">
			<url>preview/qp/BGDS-0644-0035-r-100.2782207-1.6564102</url>
			<code>
				self.assertHasStrings(
					"PNG",
					"qV0r")
					# well, the latter is just binary nonsense and is subject to change
			</code>
		</regTest>
	</regSuite>
</resource>
