<resource schema="rosat">
	<meta name="creationDate">2015-07-09T08:00:00</meta>
	<meta name="schema-rank">20</meta>
	<meta name="title">ROSAT results</meta>
	<meta name="creator">Voges, W.; Aschenbach, B.; Boller, Th.; Brauninger,
		H.; Briel, U.; Burkert, W.; Dennerl, K.; Englhauser, J.; Gruber, R.; Haberl,
		F.; Hartner, G.; Hasinger, G.; Pfeffermann, E.; Pietsch, W.; Predehl, P.;
		Schmitt, J.; Trumper, J.; Zimmermann, U.</meta>

	<meta name="description" format="rst">
		ROSAT was an orbiting x-ray observatory active in the 1990s.
		We provide a table of all photons observed during ROSAT's all-sky
		survey (RASS) as well as images of both survey and pointed observations.

		For ROSAT data products, see
		http://www.xray.mpe.mpg.de/cgi-bin/rosat/rosat-survey
	</meta>

	<meta name="subject">surveys</meta>
	<meta name="subject">x-ray-astronomy</meta>

	<meta name="source">2000IAUC.7432R...1V</meta>
	<meta name="type">Catalog</meta>
	<meta name="facility">ROSAT</meta>

	<meta name="coverage.waveband">X-ray</meta>

	<coverage>
		<temporal>1990-06-01 1998-09-20</temporal>
		<spatial>0/0-11</spatial>
		<spectral>0.1[keV] 2.5[keV]</spectral>
	</coverage>

	<!-- =============================================
	PHOTONS TABLE AND SERVICE
	================================================== -->

	<table id="photons" onDisk="True" adql="True" mixin="//scs#q3cindex"
			primary="id">
		<meta name="description">A table of x-ray photons detected by ROSAT</meta>
		<stc>
			Time TT "detection_time"
			Position ICRS "raj2000" "dej2000"
			Spectral "energy_cor" unit keV
		</stc>

		<index columns="energy_cor"/>
		<index columns="detection_time"/>

		<column name="raj2000" type="double precision"
			unit="deg" ucd="pos.eq.ra;meta.main"
			tablehead="RA"
			description="Right Ascension, equinox 2000.0"
			verbLevel="1"
			displayHint="sf=5"/>
		<column name="dej2000" type="double precision"
			unit="deg" ucd="pos.eq.dec;meta.main"
			tablehead="DE"
			description="Declination, equinox 2000.0"
			verbLevel="1"
			displayHint="sf=5"/>
		<column name="detection_time" type="double precision"
			unit="yr" ucd="time.start"
			tablehead="Detection Time"
			description="Time the photon was detected, in Julian years."
			verbLevel="1"
			displayHint="sf=8"/>
		<column name="energy_cor" type="real"
			unit="keV" ucd="phys.energy;em.X-ray"
			tablehead="Energy"
			description="Energy of incoming photon (corrected) [keV]"
			verbLevel="1"/><!-- http://www.xray.mpe.mpg.de/rosat/browser/data-browser/main/help.html#eb -->

		<column name="position_error" type="real"
			unit="arcsec" ucd="stat.error;pos.eq"
			tablehead="Position error"
			description="Total positional error, 1{sigma} arcsec"
			verbLevel="1"/>
		<column name="glong" type="real"
			unit="deg" ucd="pos.galactic.lon"
			tablehead="Galactic lon"
			description="Galactic longitude"
			verbLevel="1"/>
		<column name="glat" type="real"
			unit="deg" ucd="pos.galactic.lat"
			tablehead="Galactic lat"
			description="Galactic latitude"
			verbLevel="1"/>
		<column name="pulseht_channel" type="smallint"
			unit="" ucd=""
			tablehead="Pulse height ch."
			description="Channel of the pulse height.  This is a measure for
				the energy of the incoming photon, where one channel corresponds
				to about 10 eV; a pulse height channel of 127 thus indicates
				an incoming photon of about 1.3 keV."
			verbLevel="21">
			<values nullLiteral="-1"/>
		</column>
		<column name="exposure_time" type="real"
			unit="s" ucd="time.duration;obs.exposure"
			tablehead="Exp. time"
			description="ROSAT cluster survey exposure time"
			verbLevel="1"
			displayHint="sf=1"/>
		<column name="field_id" type="smallint"
			ucd="meta.id;obs.field"
			tablehead="Field id"
			description="RASS field id"
			verbLevel="21">
			<values nullLiteral="-1"/>
		</column>
		<column name="ix" type="smallint"
			unit="pixel"
			ucd="pos.cartesian.x;instr.det"
			tablehead="x"
			description="X pixel coordinate"
			verbLevel="21">
			<values nullLiteral="-1"/>
		</column>
		<column name="iy" type="smallint"
			unit="pixel"
			ucd="pos.cartesian.y;instr.det"
			tablehead="y"
			description="Y pixel coordinate"
			verbLevel="21">
			<values nullLiteral="-1"/>
		</column>
		<column name="id" type="bigint"
			ucd="meta.id;meta.main"
			tablehead="ID"
			description="Photon identifier (a combination of observation date and
				detector coordinates)"
			verbLevel="1">
			<values nullLiteral="-1"/>
		</column>
	</table>
	
	<data id="import_photons" auto="False">
		<sources pattern="data/*.csv.gz"/>
		<csvGrammar preFilter="zcat" delimiter="," />
		<make table="photons">
			<rowmaker idmaps="*">
				<map src="ra" dest="raj2000" />
				<map src="dec" dest="dej2000" />
				<!-- use the last couple of digits on the detection time for the
					primary key; we need a high temporal resolution for when there's
					bursts -->
				<map dest="id"><![CDATA[int(@detection_time.replace(".", "")[-9:]
					) << 32 | int(@ix) << 16 | int(@iy)]]></map>
				<map dest="detection_time">dateTimeToJYear(
					datetime.datetime(1990, 6, 1, 21, 6, 51)+
					datetime.timedelta(seconds=float(@detection_time)))
				</map>
			</rowmaker>
		</make>
	</data>

	<service id="cone" allowed="scs.xml,form">
		<meta name="shortName">ROSAT cone</meta>
		<meta name="title">ROSAT All Sky Survey Photon Event List Cone Search</meta>
		<meta name="description" format="rst">
			A table of all individual photons observed with
			ROSAT in its all sky survey mode.
		</meta>

		<meta name="testQuery">
			<meta name="ra">42.68</meta>
			<meta name="dec">1.96</meta>
			<meta name="sr">0.01</meta>
		</meta>
		<dbCore queriedTable="photons">
			<FEED source="//scs#coreDescs"/>
			<condDesc buildFrom="energy_cor"/>
			<condDesc>
				<inputKey original="id" required="False"/>
			</condDesc>
		</dbCore>
		<publish render="scs.xml" sets="ivo_managed"/>
		<publish render="form" sets="ivo_managed,local"/>
		<outputTable verbLevel="20"/>
	</service>



	<!-- =============================================
	IMAGES TABLE AND SERVICE
	================================================== -->

	<table id="images" onDisk="True" mixin="//siap#pgs" adql="true">
		<meta name="description">Metadata for ROSAT pointed observations and
			the ROSAT All Sky Survey (RASS) images</meta>

		<meta name="_associatedDatalinkService">
			<meta name="serviceId">dl</meta>
			<meta name="idColumn">pubdid</meta>
		</meta>

		<mixin
			obs_collection="'RASS'"
			facility_name="'ROSAT'"
			o_ucd="'phot.flux;em.x-ray'"
			createDIDIndex="True"
		>//obscore#publishSIAP</mixin>

		<index columns="bandpassId"/>
		<index columns="bandpassLo"/>
		<index columns="bandpassHi"/>
		<index columns="seqno"/>

		<column name="seqno" type="integer" required="True"
			ucd="meta.id;obs"
			tablehead="ROR seq#"
			description="ROR sequence number"
			verbLevel="10"/>
		<column name="followup" type="integer"
			ucd="meta.code;obs"
			tablehead="Followup"
			description="Number of follow-up observation (0=first observation,
				NULL=mispointing)"
			verbLevel="15">
			<values nullLiteral="-1"/>
		</column>
		<column name="obstype" type="text"
			ucd="meta.code;meta.file"
			tablehead="Data type"
			description="Type of data in the file (associated products available
				through datalink of by querying through seqno)"
			verbLevel="1"
			note="t"/>
		<column name="pubdid" type="text"
			ucd="meta.id"
			tablehead="PubDID"
			description="Publisher dataset identifier (this lets you
				access datalink services and the like)"
			verbLevel="1"/>
		<column name="dlurl" type="text"
			ucd="meta.ref.url"
			tablehead="Datalink"
			description="Link to a datalink document for this dataset, this
				lets you access associate data)"
			verbLevel="1"
			displayHint="type=url">
			<property name="targetType"
				>application/x-votable+xml;content=datalink</property>
			<property name="targetTitle">Datalink</property>
		</column>

		<column original="bandpassLo" displayHint="displayUnit=Angstrom"/>
		<column original="bandpassHi" displayHint="displayUnit=Angstrom"/>
		<column original="bandpassRefval" displayHint="displayUnit=Angstrom"/>

		<meta name="note" tag="t">
			Codes used here include:

			===  ==============================================================
			im1  photon image in the broad band (0.1-2.4 keV)
			im2  photon image in the hard band  (0.4-2.4 keV)
			im3  photon image in the soft band  (0.1-0.4 keV)
			ime  image of the average photon energy
			bk1  background image in the broad band (0.1-2.4 keV)
			bk2  background image in the hard band  (0.4-2.4 keV)
			bk3  background image in the soft band  (0.1-0.4 keV)
			mex  merged map of exposure times for the broad band  (0.1-2.4 keV)
			===  ==============================================================

		</meta>
	</table>

	<data id="import_images">
		<sources pattern="image_data/*.fits.gz" recurse="true"/>
		<fitsProdGrammar>
			<rowfilter name="parseFileName">
				<!-- see image_data/README -->
				<setup>
					<code>
						imageTypes = set("im1 im2 im3 ime bk1 bk2 bk3".split())
					</code>
				</setup>
				<code>
					stem = \srcstem
					fupCode = stem[8]
					if fupCode=='n':
						@followup = 0
					elif fupCode=='m':
						@followup = None
					else:
						@followup = int(stem[9:10])
					
					@obstype = stem[-3:]
					@seqno = int(stem[2:8])

					if @obstype in ["anc", "tap"]:
						raise base.SkipThis()

					@srcmime = "application/fits"

					yield row
				</code>
			</rowfilter>

			<rowfilter procDef="//products#define">
				<bind key="table">"\schema.images"</bind>
				<bind key="datalink">\dlMetaURI{dl}</bind>
				<bind key="mime">@srcmime</bind>
			</rowfilter>
		</fitsProdGrammar>

		<make table="images">
			<rowmaker idmaps="followup, obstype, seqno">
				<apply name="skipUnwanted">
					<setup>
						<par name="imageTypes">frozenset([
							"im1", "im2", "im3", "ime",
							"bkg", "bk1", "bk2", "bk3",
							"mex"])</par>
					</setup>
					<code>
					<!-- There's a set of files that do not contain data and
					therefore have botched WCS while looking like images.
					These have NAXIS=0; unfortunately, so do the tables.  So,
					I'm only skipping if I have reason to expect an image -->
					if vars.get("NAXIS")==0 and @obstype in imageTypes:
						raise IgnoreThisRow("Empty image file skipped")
					
					<!-- I'm also skipping files on the poles, as pywcs doesn't
					cope with them.  Figure out a workaround RSN. -->
					if vars.get("CRVAL2")==90. or vars.get("CRVAL2")==-90.:
						raise IgnoreThisRow("FIXME: Items on the poles missing")
					</code>
				</apply>

				<apply name="inferImageMeta">
					<setup>
						<par name="metaMap">{
							'im1': (0.1, 2.4, "ROSAT Soft/Medium X-Ray"),
							'im2': (0.4, 2.4, "ROSAT Medium X-Ray"),
							'im3': (0.1, 0.4, "ROSAT Soft X-Ray"),
							'ime': (None, None, "ROSAT Soft/Medium X-Ray"),
							'bk1': (0.1, 2.4, "ROSAT Soft/Medium X-Ray"),
							'bk2': (0.4, 2.4, "ROSAT Medium X-Ray"),
							'bk3': (0.1, 0.4, "ROSAT Soft X-Ray"),
						}</par>
					</setup>
					<code> # Energies in keV
						@energyLo, @energyHi, @bandpassId = metaMap.get(@obstype,
							(None, None, None))
					</code>
				</apply>

				<apply procDef="//siap#computePGS" name="computePGS">
					<bind key="missingIsError">False</bind>
				</apply>
				
				<!-- LIVETIME probably is exposure time in seconds -->
				<var key="dateObs">@MJD_OBS+@LIVETIME/3600./24/2</var>

				<!-- lambda = c/nu = h c/E
						 with astropy: constants.h*constants.c/((1*units.keV).to(units.J))
						 = 1.2398419292004204e-09 m*keV -->
				<apply procDef="//siap#setMeta">
					<bind key="bandpassId">@bandpassId</bind>
					<bind key="bandpassLo">@energyHi and 1.2398419e-9/@energyHi</bind>
					<bind key="bandpassHi">@energyLo and 1.2398419e-9/@energyLo</bind>
					<bind key="bandpassRefval">@energyLo and 1.2398419e-9*2/(
						@energyHi+@energyLo)</bind>
					<bind key="dateObs">@dateObs</bind>
					<bind key="instrument">"ROSAT "+@INSTRUME</bind>
					<bind key="pixflags">"F"</bind>
					<bind key="title">" ".join(["ROSAT", @INSTRUME, @bandpassId or "-",
						str(mjdToDateTime(@dateObs))])</bind>
				</apply>
				<map key="pubdid">\standardPubDID</map>
				<map key="dlurl">@prodtblDatalink</map>
			</rowmaker>
		</make>
	</data>

	<service id="dl" allowed="dlmeta">
		<meta name="shortName">ROSAT datalink</meta>
		<meta name="title">ROSAT image products datalink</meta>
		<meta name="description">Datalink service for ROSAT images.  This
			gives access to images in the various bands, background maps,
			and other ancillary data.
			
			For more detailed information on the various data products,
			please refer to
			http://www.xray.mpe.mpg.de/rosat/archive/docs/rdf.ps.gz
			</meta>
		<datalinkCore>
			<metaMaker semantics="#coderived">
				<setup>
					<par key="metamap">{
						"im1":  ("#coderived",
							"photon image in the broad band (0.1-2.4 keV)",
							"#image"),
						"im2":  ("#coderived",
							"photon image in the hard band  (0.4-2.4 keV)",
							"#image"),
						"im3":  ("#coderived",
							"photon image in the soft band  (0.1-0.4 keV)",
							"#image"),
						"ime":  ("#coderived",
							"image of the average photon energy",
							"#image"),
						"bkg":  ("#progenitor",
							"total background image",
							"#image"),
						"bk1":  ("#progenitor",
							"background image in the broad band (0.1-2.4 keV)",
							"#image"),
						"bk2":  ("#progenitor",
							"background image in the hard band  (0.4-2.4 keV)",
							"#image"),
						"bk3":  ("#progenitor",
							"background image in the soft band  (0.1-0.4 keV)",
							"#image"),
						"mex":  ("#calibration",
							"map of exposure times, computed for the broad band.",
							None),
						"anc":  ("#documentation",
							"ANCILLARY -- orbit, aspect and housekeeping -- data (cf."
							" http://www.xray.mpe.mpg.de/rosat/archive/docs/rdf.ps.gz)",
							None),
						"bas":  ("#progenitor",
							"BASIC -- photon event lists and good times -- data (cf."
							" http://www.xray.mpe.mpg.de/rosat/archive/docs/rdf.ps.gz)",
							"#event"),
						"his":  ("#documentation",
							"Processing history (cf."
							" http://www.xray.mpe.mpg.de/rosat/archive/docs/rdf.ps.gz)",
							None),
						"src":  ("#derivation",
							"Source analysis results (cf."
							" http://www.xray.mpe.mpg.de/rosat/archive/docs/rdf.ps.gz)",
							None),
						"prt":  ("#preview-plot",
							"Postscript files and SASS printout (cf."
							" http://www.xray.mpe.mpg.de/rosat/archive/docs/rdf.ps.gz)",
							None),
						"raw":  ("#progenitor",
							"Uncorrected events list (cf."
							" http://www.xray.mpe.mpg.de/rosat/archive/docs/rdf.ps.gz)",
							"#event"),
						"ltc":  ("#derivation",
							"Source lightcurves (cf."
							" http://www.xray.mpe.mpg.de/rosat/archive/docs/rdf.ps.gz)",
							"#timeseries"),
					}</par>
				</setup>
				<code>
					# Ahem: I don't have a descriptorGenerator here, so I do this
					# here
					descriptor.contentQualifier = "#image"
					stem =descriptor.accref.split("/")[-1]
					seqno = int(stem[2:8])
					thisFollowup = stem[8]
					if thisFollowup=='n':
						thisFollowup = 0
					elif thisFollowup=='m':
						thisFollowup = None
					else:
						thisFollowup = int(stem[9:10])

					followupArtefacts = []

					with base.getTableConn() as conn:
						for row in conn.queryToDicts(
								"SELECT * FROM rosat.images WHERE seqno=%(seqno)s",
								locals()):
							semantics, description, contentQualifier = metamap.get(
								row["obstype"],
								("#unknown", "Some artefact of the processing pipeline"
									" (we're trying to figure out what this is)."))

							if row["accref"]==descriptor.accref:
								# the thing itself is returned as #this
								continue

							if row["followup"]!=thisFollowup:
								followupArtefacts.append(row)
								continue

							yield descriptor.makeLink(
								makeAbsoluteURL("getproduct/"+row["accref"]),
								contentType="image/fits", semantics=semantics,
								description=description,
								contentLength=row["accsize"],
								contentQualifier=contentQualifier)
					
					if followupArtefacts:
						# there are previous or followup observations; generate
						# a single datalink for each of these sets; we use the
						# broadband image for that hoping that will usually exist.
						relatedIds = set(r["accref"][:-11] for r in followupArtefacts)
						for relId in relatedIds:
							yield descriptor.makeLink(
								self.parent.getURL("dlmeta")+"?ID="+urllib.parse.quote(
									descriptor.pubDID.split("?")[0]+"?"+relId
									+"im1.fits.gz"),
									contentType="application/x-votable+xml;content=datalink",
									description="Previous observation or re-observation of"
									" this field.")
				</code>
			</metaMaker>

			<metaMaker semantics="#documentation">
				<code>
					yield descriptor.makeLink(
						"http://www.xray.mpe.mpg.de/rosat/archive/docs/rdf.ps.gz",
						contentType="application/postscript",
						description="Documentation of the data products",
						contentLength=157836)
				</code>
			</metaMaker>
		</datalinkCore>
	</service>

	<service id="im" allowed="siap.xml,form">
		<meta name="shortName">ROSAT images</meta>
		<meta name="title">ROSAT Survey and Pointed Images</meta>
		<meta name="description">Images taken by the ROSAT x-ray observatory.
		This comprises both pointed observations and images taken within
		the all-sky survey.</meta>

		<meta name="sia.type">Pointed</meta>

		<meta name="testQuery.pos.ra">160</meta>
		<meta name="testQuery.pos.dec">-80</meta>
		<meta name="testQuery.size.ra">0.1</meta>
		<meta name="testQuery.size.dec">0.1</meta>

		<dbCore queriedTable="images">
			<condDesc original="//siap#protoInput"/>
			<condDesc original="//siap#humanInput"/>
			<condDesc buildFrom="dateObs"/>
			<condDesc>
				<inputKey original="bandpassId">
					<values fromdb="bandpassid from \schema.images"/>
				</inputKey>
			</condDesc>
			<condDesc>
				<phraseMaker>
					<code>
						yield "obstype in ('im1', 'im2', 'im3', 'ime')"
					</code>
				</phraseMaker>
			</condDesc>

		</dbCore>
		<publish render="siap.xml" sets="ivo_managed"/>
		<publish render="form" sets="ivo_managed,local"/>
	</service>

	<regSuite title="ROSAT images service">
		<regTest title="ROSAT SIAP only returns rows containing images.">
			<url POS="160,-80" SIZE="0.1,0.1" INTERSECT="COVERS">im/siap.xml</url>
			<code>
				types = set([row["obstype"] for row in self.getVOTableRows()])
				self.assertEqual(types, set(["im1", "im2", "im3",
					"ime"]))
			</code>
		</regTest>

		<regTest title="ROSAT Datalink returns reasonable data">
			<url ID="ivo://org.gavo.dc/~?rosat/image_data/rda_1/wg900026p--1_n1_p1_r2_f2_p2/rp900026m01_im1.fits.gz"
				>dl/dlmeta</url>
			<code>
				data = self.getVOTableRows()
				self.assertEqual(len(data), 16)
				self.assertEqual(
					set((r["semantics"], r["content_qualifier"]) for r in data), {
						('#calibration', None),
						('#coderived', '#image'),
						('#coderived', None),
						('#derivation', '#timeseries'),
						('#documentation', None),
						('#preview', None),
						('#preview-plot', None),
						('#progenitor', '#event'),
						('#progenitor', '#image'),
						('#this', '#image'),})

				previousLinks = [row for row in data
					if row["description"].startswith("Previous")]
				self.assertEqual(previousLinks[0]['access_url'].split("/", 3)[-1],
					"rosat/q/dl/dlmeta?ID=ivo%3A//org.gavo.dc/~%3Frosat/"
					"image_data/rda_3/wg900026p_n1_p1_r2_f2_p1/rp900026n00_im1.fits.gz")
			</code>
		</regTest>
	</regSuite>

	<regSuite title="ROSAT photons test">
			<regTest title="ROSAT photons SCS works">
				<url RA="40.4" DEC="4.3" SR="0.05" VERB="3">cone/scs.xml</url>
				<code><![CDATA[
					rows = self.getVOTableRows()
					self.assertEqual(len(rows), 10)
					self.assertTrue('4097758959261912416' in
						set(r["id"] for r in rows),
						"Expected photon missing in ROSAT photon catalog")
					self.assertTrue(1991.06 < min(r["detection_time"]
						for r in rows) < 1992, "ROSAT detection time computation broke")
				]]></code>
			</regTest>
	</regSuite>
</resource>
