<resource schema="lamost5">
	<meta name="creationDate">2019-10-11T10:57:00</meta>
	<meta name="schema-rank">1000</meta>
	<meta name="title">LAMOST DR5 survey spectra</meta>

	<meta name="subject">spectroscopy</meta>
	<meta name="subject">surveys</meta>
	<meta name="subject">stars</meta>
	<meta name="subject">galaxies</meta>

	<meta name="facility">LAMOST</meta>
	<meta name="instrument">LAMOST</meta>
	<meta name="content.type">Archive</meta>
	<meta name="coverage.waveband">Optical</meta>
	<meta name="coverage.waveband">Infrared</meta>
	<meta name="creator">National Astronomical Observatories,
		Chinese Academy of Sciences</meta>
	<meta name="rights" format="rst">The data was obtained from
		http://dr5.lamost.org/v3/ – terms and condition may apply.

		The metadata descriptions were provided in part by the Czech VO,
		in particular Petr Skoda and Jiri Nadvornik.
	</meta>
	<meta name="description" format="rst">
		This services provides 1D spectra from DR5 of LAMOST (Large Sky Area
		Multi-Object Fiber Spectroscopic Telescope) through SSAP;
		data is served both in VO-standard SDM and, via datalink, the original
		SDSS-inspired FITS described in
		http://dr5.lamost.org/doc/data-production-description .
	</meta>

	<table id="data" onDisk="true" adql="True">
		<index columns="ssa_pubDID"/>
		<index columns="ssa_specstart"/>
		<index columns="ssa_specend"/>
		<FEED source="//scs#splitPosIndex"
			long="degrees(long(ssa_location))" lat="degrees(lat(ssa_location))"/>
		<FEED source="//ssap#obscore-time-index"/>

		<mixin
			collection="LAMOST5"
			fluxSI=""
			fluxUCD="phot.flux.density;em.wl"
			spectralSI="Angstrom"
			spectralUCD="em.wl"
			creator="LAMOST DAS"
			instrument="LAMOST"
			dataSource="pointed"
			creationType="archival"
			fluxCalibration="RELATIVE"
			spectralCalibration="ABSOLUTE"
			spectralUnit="Angstrom"
			statFluxError=""
			sysFluxError=""
			statSpectError=""
			sysSpectError=""
			spectralResolution="1500"
			fluxUnit="count"
		>//ssap#hcd</mixin>
<!--		<mixin
			collectionName="'LAMOST5'"
			dataproduct_type="'spectrum'"
			em_res_power="4000"
			instrument_name="'LAMOST'"
			calibLevel="1">//obscore#publishSSAPMIXC</mixin>-->
		<meta name="_associatedDatalinkService">
			<meta name="serviceId">sdl</meta>
			<meta name="idColumn">ssa_pubDID</meta>
		</meta>
		
		<column name="raj2000" unit="deg" type="double precision"
			ucd="pos.eq.ra;meta.main"
			description="Observed RA of the object"/>
		<column name="dej2000" unit="deg" type="double precision"
			ucd="pos.eq.dec;meta.main"
			description="Main value of declination"/>
		<column name="ssa_targsubclass" type="text"
			tablehead="Ob. subcls" verbLevel="25"
			description="Object subclass"/>
	</table>

	<coverage>
		<updater sourceTable="data"/>
		<spatial>1/23 2/1,4,6,8,16,18-20,22,24,26,33-35,40,85,105,109 3/0-2,9-10,12-14,20-21,23,28-29,37-42,44,48,50,68,71,84-85,92-94,101-103,108-110,112-113,128-130,144-146,150-151,153-154,157,164,166-168,171,173-174,209,212-213,226,232-234,277,287,295,297,299-301,303-304,311,315,317-319,345-348,350-351,357,361-363,366-367,406-407,409,413,415,425-426,428,430-432,434-435,442-443,445,447,485,487,489,494-496,498-499,504-505 4/13-15,34,44-45,47,60-62,89-91,120-122,124,144-145,147,172,174,181-182,185,187-188,198-199,208,276-277,279-280,282-283,344,346-347,349,351,400-402,444,456-458,464,480,482,524,527,588,590-592,594-595,597,599,610-611,620-621,623-625,633-634,636,660,662-663,676-678,680-681,689,691,700,705-710,712-714,716,736,773,781,786,791-793,795-796,798-799,802,814,821,825,830,833,840-841,844-845,856-857,859-862,866-867,872-873,876,878,881,886,889,901,911,914,916,920,922-924,926,941-946,954-955,992,1103-1104,1115,1117-1119,1125,1127,1131-1134,1137-1140,1142,1144-1145,1147,1167,1175,1178-1179,1186-1187,1192-1193,1195,1208,1210-1211,1220,1224-1226,1228,1231,1233,1235-1238,1242,1248,1251,1254,1258-1259,1265,1267,1341-1343,1359,1379,1397-1399,1422-1423,1425,1432,1434-1435,1437-1439,1443,1456,1458-1459,1461-1463,1591,1597-1599,1613-1615,1619,1621-1623,1633-1635,1640,1642-1643,1646-1647,1650-1651,1657-1659,1671,1677,1679,1696-1697,1699,1708-1709,1711,1717-1719,1733-1735,1760-1762,1765-1767,1777,1779,1785-1787,1896,1898-1900,1902-1903,1933,1935,1939,1944-1946,1961-1962,1964,1966-1969,1971-1973,1988,1990-1991,2008,2010,2012,2025,2028-2029,2031-2034,2037-2038,2040-2041,2043,2045-2047,2300-2301,2303,2555,2558-2559,2815 5/48-49,51,129-130,132-133,135,141-143,185,187,252-254,353-355,492-493,500-501,504-506,585-587,692-694,700,702-703,720,722,732-734,745-747,756,784-786,788,790-791,816,840,896-898,900-901,1112-1114,1124-1126,1380-1382,1393,1395,1400-1402,1520-1522,1524,1612-1614,1780-1782,1784-1786,1836-1838,1840-1842,1844,1864,1926,1952,2100-2102,2104-2106,2358-2359,2373-2375,2384-2386,2392,2394-2395,2432-2434,2437-2439,2488-2489,2491,2506-2507,2509,2511,2528,2530-2531,2540-2542,2644-2646,2716,2718,2728-2730,2732-2733,2735,2752-2753,2755,2761,2763,2817-2819,2844-2845,2860-2862,2872,2880-2882,2884,2948,2950,2952-2953,2956,3072-3073,3075-3076,3089,3091,3100-3101,3103,3132-3133,3136-3138,3140-3141,3143,3148,3150-3153,3156,3158,3161-3163,3176-3177,3188-3189,3191,3232,3239,3248,3250-3251,3262,3268-3269,3278-3280,3283,3289,3292-3293,3311-3312,3315,3324,3328-3329,3338-3341,3343,3368-3370,3372-3373,3384-3386,3388,3433,3435,3453,3455-3456,3458-3459,3462-3463,3473-3475,3480,3482,3500-3501,3509-3511,3516-3518,3521,3523,3533,3535-3536,3538,3543,3548-3550,3564-3565,3568-3570,3576,3594-3595,3597-3599,3601,3608,3610,3612-3613,3643,3648,3650,3653,3655,3661,3670,3672-3673,3675-3678,3686-3687,3701-3703,3708-3710,3760-3761,3788-3790,3792,3794,3799,3805,3814-3815,3825-3828,3850,3857,3859-3860,3862,3865,3868,3872-3874,4391,4400,4402-4403,4408-4409,4411,4420,4429,4431,4453,4455,4464-4466,4497,4507,4521,4523,4540,4542,4546-4547,4564,4566-4567,4572-4574,4584-4585,4587,4661-4663,4667,4694,4697-4699,4706,4709-4711,4736,4738-4739,4743,4777-4779,4836-4837,4839,4884,4888-4890,4908-4909,4923,4931,4937,4956-4958,4963,4965-4967,4972,4974-4975,4998-5002,5009,5011-5014,5020,5022-5024,5026-5027,5029,5031,5056-5057,5059,5065-5067,5339,5342-5343,5358-5359,5361,5363,5399,5405-5407,5423,5429,5431,5433-5435,5509,5513-5515,5584-5585,5587,5671,5677,5682-5683,5685-5687,5697,5699,5705,5707-5710,5732,5734,5745,5747,5771,5831,5842,6385,6387,6427-6428,6430-6431,6439,6443,6445-6447,6449-6451,6465-6470,6473,6475,6480-6481,6483,6529-6531,6564,6566-6567,6577-6582,6592,6594-6595,6597-6599,6624-6625,6627,6707,6714-6715,6793,6795,6840,6842,6865-6867,6928,6930-6931,7052,7054-7056,7058-7059,7105,7107,7113,7115,7137-7139,7413-7415,7420-7421,7423,7483-7484,7486-7487,7572-7573,7606,7616,7618-7619,7624-7625,7646-7647,7668-7669,7711,7726-7727,7731,7737,7739,7750-7751,7754-7755,7789-7791,7812-7813,7815,7821,7823,7841-7843,7852-7853,7855,7860-7862,7881-7883,7897-7901,7903,8005,8007-8008,8010,8013,8015-8016,8018,8024,8026,8031,8037,8046-8047,8053-8058,8060-8061,8063,8096-8098,8106-8110,8120-8121,8123,8140,8142-8144,8147,8156,8158-8159,8168-8170,8176,8178-8179,9179,9182-9183,9194-9195,9211,10226-10227,10229-10231,11246-11247,11255,11258-11259,12247,12251-12252,12254-12255,12273,12276-12277,12279 6/201,203,512-513,515,524-526,536-537,539,561,563,736-737,745-747,1020,1022-1023,1409-1411,1976-1977,1980-1981,1983,2008-2010,2013,2028-2030,2336-2337,2339,2780-2781,2806-2807,2884-2886,2894-2895,2940,2944-2946,2949,2951,2957-2959,2978,3032,3040,3148,3150-3151,3156-3157,3159,3268-3270,3272-3274,3276,3280-3281,3284-3285,3304,3306,3364-3366,3368-3370,3596-3598,3608-3609,3612,3616-3617,3648,4460,4462-4463,4509-4511,5532-5534,5568-5569,5571,5577-5579,5612-5614,6092-6094,6100-6102,6104-6105,6112-6114,6120,6461-6463,7132-7134,7148-7150,7152-7154,7156,7356-7357,7372-7373,7380-7382,7384-7385,7392,7394,7460,7462,7464,7696-7698,7728,7812,7816,8412,8414-8415,8428-8429,8431,9424,9426-9427,9430-9431,9489-9491,9548-9550,9572,9574,9740,9742-9745,9747,9960-9962,10017-10022,10032-10033,10035,10041-10043,10116,10118-10119,10172,10174,10192,10208-10209,10212,10588,10590-10591,10868-10870,10876,10878-10879,10924-10925,10927,10937-10939,11016-11018,11040,11216,11218,11224,11232-11234,11236,11240,11264-11265,11267,11384-11385,11388-11389,11492-11494,11532-11534,11544,11552-11554,11556,11560,11804,11806,11816-11817,11820-11821,11828,11832,12296-12297,12299,12309,12312-12314,12352-12353,12355,12361,12363,12388-12389,12408-12409,12487,12493-12495,12517,12519,12536-12537,12540-12541,12556,12558-12559,12568-12570,12598-12599,12616-12617,12620-12621,12623,12628-12629,12631,12636,12638-12639,12642,12716-12717,12719,12760,12762-12763,12810-12811,12814,12850,12856,12858,12932-12934,12936,12949-12951,12980-12981,12983,12996,12998-12999,13040,13042-13043,13081,13084-13085,13126-13129,13131,13153,13155,13160,13162-13165,13176-13177,13180-13181,13183,13189,13191,13197,13239,13256,13259,13269-13272,13274-13277,13279,13304-13306,13325,13327,13344,13346-13347,13349-13351,13369-13371,13484-13486,13496-13497,13500-13501,13503,13548-13550,13556-13558,13560-13561,13728-13729,13731,13737,13739,13808-13810,13830-13831,13847,13889-13891,13912,13924-13926,13989,13991,14013,14033-14035,14076,14081,14117,14128-14129,14131,14137,14139,14148-14150,14159,14165,14167,14170-14171,14204-14205,14208,14210,14215-14218,14221,14223,14240,14245,14247,14264-14265,14269,14284-14286,14288,14290,14308,14312,14365-14367,14370-14371,14375,14385-14387,14400-14401,14403,14408,14410-14411,14414,14436,14438,14444,14446,14461,14463,14528-14530,14536,14538,14549,14551,14558-14560,14567,14570,14617,14619,14641-14643,14648-14650,14652-14653,14674-14675,14684,14686-14687,14696-14697,14699,14716,14719,14736,14738-14739,14743,14800,14802-14803,14844-14846,15048-15050,15052-15053,15055,15164-15165,15172-15174,15180,15182,15184-15185,15189-15191,15193,15195,15200-15202,15215,15217,15226-15227,15230,15232-15234,15236,15240,15242-15243,15245-15247,15255,15297-15299,15316,15319-15322,15328-15330,15332-15333,15404,15406-15407,15424-15425,15427,15433,15435,15444,15446,15452,15454,15457,15459,15476,15500-15502,15520,15522,15904-15906,15908,17557-17559,17588-17589,17591,17604,17606-17607,17685,17687-17690,17693-17695,17713,17715,17721,17809,17811,17817-17819,17829,17831-17832,17834,17837,17839,17868,17870-17871,17997,18021-18023,18025-18027,18063,18071,18074,18077-18079,18083,18089-18091,18165-18167,18172,18174-18176,18178-18180,18182-18183,18260-18262,18300-18301,18303,18344-18345,18347,18641-18643,18661-18663,18765-18767,18773,18775,18781-18783,18816,18818-18819,18830-18831,18833-18835,18948,18950-18951,18965-18968,18970,19104-19105,19352-19353,19355,19540-19542,19544-19546,19564-19566,19568,19570,19640-19641,19644-19645,19664,19666,19672,19674-19675,19678-19682,19684-19685,19691,19757,19839,19850-19851,19857,19859,19892,19894-19895,19984,19986-19987,20012-20014,20033,20035,20041-20043,20060-20061,20086-20087,20100,20102-20103,20113,20115,20121,20123,20232-20233,20235,20258,21353,21355,21421-21423,21429,21431,21441,21443,21449,21451,21589,21591,21617,21619,21686-21687,21710-21711,21713,21715,21722-21723,21730-21731,22045,22051,22344-22345,22347,22654-22655,22679,22717,22722-22723,22726-22727,22737-22739,22817,22819,22825-22827,22844-22846,22932,22934,22940,22942-22943,22985,22987,23063,23069-23071,23077-23079,23082-23083,23312-23313,23316-23317,23320,23322-23323,23360,23373-23375,25423,25434-25435,25437-25439,25445,25447,25453,25455,25513-25516,25518-25519,25530-25531,25533-25535,25537,25539,25545,25547,25701-25703,25716,25718-25719,25751,25766-25767,25769,25771,25778-25779,25794-25795,25857-25859,25884-25886,25888-25889,25891,25896,25898-25899,25928-25929,25931,26114-26115,26260-26262,26305,26307,26332-26334,26372-26374,26384-26385,26387,26504-26505,26709,26711,26714-26715,26717-26719,26725,26727,26733,26813-26815,26823,26852-26853,26855,27168-27169,27171,27177,27179,27365,27367,27373-27375,27456-27458,27716,27718-27719,28212-28213,28215,28229-28230,28416-28417,28419,28425-28427,28448-28450,28456,28459,28545-28547,29567,29645,29647,29650-29651,29669,29674-29676,29678-29679,29689-29691,29925-29927,29940,29942-29943,30120,30122,30250-30251,30254-30255,30271,30277,30301,30303,30314-30315,30318-30319,30325,30354,30357-30360,30365,30367,30416,30418,30430-30431,30468,30470-30471,30488,30490,30505,30508,30512,30514,30573,30575,30578-30579,30581-30583,30624,30626,30632,30661,30680-30681,30684-30685,30841-30843,30887,30893-30895,30898-30899,30902,30918-30919,30954-30955,30998-30999,31152,31154-31155,31236-31237,31239,31245,31256-31257,31259,31281,31283,31289,31291,31361,31363,31416,31418-31419,31452-31453,31455,31520-31522,31584,31586-31587,31609-31611,31824-31826,31828,31832-31834,32019,32025,32027,32038,32044,32046,32049,32059,32070,32076,32078,32100,32108,32110-32111,32119,32145,32147,32152,32154,32156-32157,32178,32182-32183,32208,32210-32211,32249-32251,32396,32416,32418-32419,32422-32423,32446-32447,32489-32491,32564,32566-32567,32581,32583-32585,32587,32628-32629,32631,32686,32708-32709,32711,36671,36710-36711,36714-36715,36722-36723,36726,36757,36759,36765,36767,36794,36832-36833,36836-36837,36839,36842-36843,40797,40858-40859,40862-40863,40869,40871,40877,40899,40902-40903,40913-40915,44979,44982-44983,45017-45019,45026,48981-48983,48997-48999,49001,49003,49013-49015,49112-49113,49141</spatial>
		<spectral>2.22832e-20 5.36879e-19</spectral>
		<temporal>55858.5 57920.8</temporal>
	</coverage>

	<data id="import">
		<sources recurse="true" patterns="data/*.fits*"/>

		<!-- we return "normal" VOTable products; original and continuum
		  normalised available through datalink; the accref is the file
		  path without any extension. -->
		<fitsProdGrammar>
			<rowfilter procDef="//products#define">
				<bind name="table">"\schema.data"</bind>
				<bind key="accref">(\inputRelativePath{True}).replace(
					".fits.gz", "")</bind>
				<bind name="mime">"application/x-votable+xml"</bind>
				<bind name="path">(\fullDLURL{sdl}).replace(".fits.gz", "")</bind>
				<bind name="fsize">100000</bind>
				<bind name="preview_mime">"image/png"</bind>
				<bind name="preview"
					>("\internallink{\rdId/preview/qp/}"+\inputRelativePath).replace(
						".fits.gz", "")</bind>
			</rowfilter>
		</fitsProdGrammar>

		<make table="data">
			<rowmaker idmaps="*">
				<var name="specLo">10**(@CRVAL1+(1-@CRPIX1)*@CD1_1)*1e-10</var>
				<var name="specHi">10**(@CRVAL1+(@NAXIS1-@CRPIX1)*@CD1_1)*1e-10</var>
				<var name="specExt">@specHi-@specLo</var>
				<var name="specMid">(@specHi+@specLo)/2</var>
				
				<apply name="fixDate">
				<code>
					if vars["DATE"].split(":")[-1] == "60":
						vars["DATE"] = (":").join(vars["DATE"].split(":")[:-1]) + "59"
				</code>
				</apply>

				<apply procDef="//ssap#setMeta">
					<bind name="dstitle">\inputRelativePath</bind>
					<!-- A creator DID would be nice... -->
					<bind name="pubDID">\standardPubDID</bind>
					<bind name="cdate">@DATE</bind>
					<bind name="bandpass">"Optical"</bind>
					<bind name="targname">@DESIG</bind>
					<bind name="targclass">@CLASS</bind>
					<bind name="alpha">@RA</bind>
					<bind name="delta">@DEC</bind>
					<!-- Do we want to actually compute obs midpoint here? -->
					<bind name="dateObs">parseTimestamp(@DATE_OBS.split(".")[0])</bind>
					<!-- btw I'm pretty sure the comment for EQUINOX is wrong -->
					<bind name="timeExt">@EXPTIME</bind>
					<bind name="length">@NAXIS1</bind>

					<bind name="aperture">0.000916667</bind>
					<!-- Do we need to evaluate CXX headers for those?  Get them
					from somewhere else? -->
					<bind name="specmid">@specMid</bind>
					<bind name="specext">@specExt</bind>
					<bind name="specstart">@specLo</bind>
					<bind name="specend">@specHi</bind>
					<bind name="redshift">parseWithNull(@Z, float, -9999.)</bind>
				</apply>
				<simplemaps>raj2000: RA, dej2000:DEC, ssa_targsubclass:SUBCLASS</simplemaps>
			</rowmaker>
		</make>
	</data>

	<STREAM id="spectrum-commoncolumns">
		<column name="flux_error"
			ucd="stat.error;phot.flux.density;em.wl"
			tablehead="Err(flux)"
			description="Flux error, comuted as sqrt(invsig),
				where invsig is the inverse simga^2 from the LAMOST FITS."/>
		<column name="flags" type="smallint" required="True"
			ucd="meta.code.qual"
			tablehead="Flags"
			description="Extraction flags; this is the 'ormask' from the upstream
				data, where a bit is set if a condition is met on one or more of the
				exposures: Bit 0: Bad pixel on CCD; bit 1: Bad profile in extraction;
				bit 2: No sky information at this wavelength; bit 3: Sky level to
				high; bit 4: fiber trace out of the CCD; bit 5: no good data."/>
	</STREAM>

	
	<service id="preview" allowed="qp">
		<property name="queryField">accref</property>
		<meta name="description">
			A service returning PNG thumbnails for LAMOST spectra.
			The accref for which to generate a preview is taken from
			the path items after the qp.
		</meta>
		<pythonCore>
			<inputTable>
				<inputKey name="accref" type="text"
					tablehead="accref"
					description="Accref of a spectrum to create the preview
						for."/>
			</inputTable>
			<coreProc>
				<setup>
					<code>
						from gavo.svcs import UnknownURI
						from gavo.utils import pyfits
						from gavo.helpers.processing import SpectralPreviewMaker
					</code>
				</setup>
				<code>
					accref = inputTable.getParam("accref")
					if not accref.startswith("lamost5"):
						raise UnknownURI("I cannot do previews for this accref"
							" (if it is one, that is)")
					
					hdus = pyfits.open(
						os.path.join(base.getConfig("inputsDir"), accref)+".fits.gz")
					return "image/png", SpectralPreviewMaker.get2DPlot(
						list(enumerate(hdus[0].data[0,:])))
				</code>
			</coreProc>
		</pythonCore>
	</service>

	<STREAM id="coreDef">
		<FEED source="//ssap#hcd_condDescs">
			<PRUNE id="TARGETNAME_cond"/>
		</FEED>
		<condDesc>
			<!-- match targetname case-folded and ignoring blanks -->
			<inputKey  name="TARGETNAME"
				original="//ssap#instance.ssa_targname" std="True"/>
			<phraseMaker>
				<code>
				key = inputKeys[0].name
				val = inPars.get(key, None)
				if val is not None:
					val = val.replace(" ", "").upper()
					yield ("upper(replace(ssa_targname , ' ', ''))=%%(%s)s"%
						base.getSQLKey(key, val, outPars))
				</code>
			</phraseMaker>
		</condDesc>
	</STREAM>

	<table id="spectrum-phys">
		<meta name="description" format="rst">
			A LAMOST spectrum with physical fluxes;
			note that the flux has a relative calibration as described by
			:bibcode:`2012RAA....12..453S`</meta>
		<mixin ssaTable="data" spectralDescription="Air wavelength"
			fluxDescription="Flux">//ssap#sdm-instance</mixin>
		<FEED source="spectrum-commoncolumns"/>
	</table>

	<table id="spectrum-norm">
		<meta name="description">A LAMOST spectrum with continuum-normalised
			fluxes.</meta>
		<mixin ssaTable="data" spectralDescription="Air wavelength"
			fluxDescription="Flux, normalised so max(flux)=1"
				>//ssap#sdm-instance</mixin>
		<FEED source="spectrum-commoncolumns"/>
	</table>

	<!-- we're implementing a bit more of sdm datalink because we want fast
	cutouts without having to parse the whole thing.  -->

	<service id="sdl" allowed="dlget,dlmeta,static">
		<meta name="title">LAMOST Spectral Datalink Service</meta>
		<property name="staticData">data</property>
		<datalinkCore>
			<descriptorGenerator procDef="//soda#sdm_genDesc">
				<bind name="ssaTD">"\rdId#data"</bind>
			</descriptorGenerator>
	
			<metaMaker semantics="#progenitor">
				<code>
					if not descriptor.pubDID:
						return
					relFName = descriptor.pubDID.split(
						"?lamost5/")[-1]+".fits.gz"
					yield descriptor.makeLinkFromFile(
						relFName,
						description="Original LAMOST5, SDSS-like FITS")
				</code>
			</metaMaker>

			<metaMaker>
				<code>
					yield MS(InputKey, name="FLUXCALIB", type="text",
						multiplicity="forced-single",
						ucd="phot.calib",
						utype="ssa:Char.FluxAxis.Calibration",
						description="Get the spectrum in a given calibration; we"
							" offer normalized (maximum=1) in addition to relative"
							" (as LAMOST gives the fluxes).",
						values=MS(Values, options=[
							MS(Option, content_=val)
								for val in ["relative", "normalized"]]))
				</code>
			</metaMaker>

			<metaMaker>
				<code>
					yield MS(InputKey, type="double precision[2]", xtype="interval",
						name="BAND", multiplicity="forced-single",
						unit="m", ucd="em.wl",
						description="Spectral cutout interval",
						values=MS(Values,
							min=descriptor.limits["ssa_specstart"].min,
							max=descriptor.limits["ssa_specend"].max))
				</code>
			</metaMaker>

			<dataFunction name="load_data">
				<setup>
					<code>
						from gavo import rsc
						from gavo.utils import fitstools
						from gavo.utils import pyfits
					</code>
				</setup>

				<code>
					accref = descriptor.accref+".fits.gz"
					fitsPath = os.path.join(
						base.getConfig("inputsDir"), accref)

					hdus = pyfits.open(fitsPath)
					params = descriptor.ssaRow

					# we're cool about unsupported fluxcalibs here; nobody will
					# catch us, and I can't see much danger.
					normalise = args.get("FLUXCALIB")=="normalized"
					if normalise:
						td = rd.getById("spectrum-norm")
						normalizer = max(hdus[0].data[0,:])
						params["ssa_fluxcalib"] = "NORMALIZED"
						# replace this with fluxUnitOverride in the mixin once
						# that's implemented
						td.getColumnByName("flux").unit = " "
					else:
						td = rd.getById("spectrum-phys")
						normalizer = 1

					hdr = hdus[0].header
					data = hdus[0].data
					# LAMOST WCS is severely broken: CD1_1 for a spectral axis.  Oh my.
					# Let's fiddle things by hand, and then do log/10** manually below.
					specWCS = fitstools.WCSAxis(
						"spectral",
						hdr["CRVAL1"],
						hdr["CRPIX1"],
						hdr["CD1_1"],
						axisLength=hdr["NAXIS1"])
						
					if args.get("BAND") is None:
						# no band given, just load the whole thing
						loPix = 0
						hiPix = data.shape[1]
					
					else:
						loLam, hiLam = args["BAND"]
						loPix = int(max(0, specWCS.physToPix(math.log10(loLam*1e10))))
						hiPix = int(min(
							data.shape[1],
							specWCS.physToPix(math.log10(hiLam*1e10))))

						loLam, hiLam = data[2,loPix]*1e-10, data[2,hiPix]*1e-10
						params["ssa_specext"] = hiLam-loLam
						params["ssa_specstart"] = loLam
						params["ssa_specend"] = hiLam
						params["ssa_specmid"] = (hiLam+loLam)/2

					rows = []
					for pixInd, row in enumerate(data.T[loPix:hiPix]):
						rows.append({
							"spectral": row[2],
							"flux": row[0]/normalizer,
							"flux_error": 1/math.sqrt(row[1]) if row[1] else None,
							"flags": int(row[4])})
					hdus.close()

					t = rsc.TableForDef(td, rows=rows)
					for key, value in params.items():
						t.setParam(key, value)
					descriptor.data = rsc.wrapTable(t)
				</code>
			</dataFunction>

			<FEED source="//soda#sdm_format"/>
		</datalinkCore>
	</service>

	<service id="web" defaultRenderer="form">
		<meta name="shortName">LAMOST DR5 Web</meta>
		<meta name="title">LAMOST DR5 Spectra Web Interface</meta>
		<meta name="_related" title="LAMOST DR5 SSAP"
			>\internallink{lamost5/q/ssa/info}</meta>
		
		<dbCore queriedTable="data">
			<condDesc buildFrom="ssa_targname"/>
			<condDesc buildFrom="ssa_location"/>
			<condDesc buildFrom="ssa_dateObs"/>
		</dbCore>

		<outputTable>
			<autoCols>accref, mime, ssa_targname, ssa_location, ssa_aperture,
				ssa_dateObs</autoCols>
			<outputField original="ssa_specstart" displayHint="displayUnit=Angstrom"/>
			<outputField original="ssa_specend" displayHint="displayUnit=Angstrom"/>
			<outputField name="datalink" type="text"
				select="ssa_pubdid"
				ucd="meta.ref.url"
				tablehead="DL"
				description="URL of a datalink document for this dataset."
				verbLevel="1">
				<formatter><![CDATA[
					if data:
						return T.a(href="/\rdId/sdl/dlmeta?ID="+
							getattr(urllib, "parse", urllib).quote(data))["[Datalink]"]
					else:
						return ""
				]]></formatter>
			</outputField>
		</outputTable>
	</service>

	<service id="ssa" allowed="ssap.xml,form">
		<meta name="shortName">LAMOST DR5 SSAP</meta>
		<meta name="ssap.dataSource">pointed</meta>
		<meta name="ssap.creationType">archival</meta>
		<meta name="ssap.testQuery">MAXREC=1</meta>

		<publish render="ssap.xml" sets="ivo_managed"/>
		<publish render="form" sets="ivo_managed,local" service="web"/>
		<ssapCore queriedTable="data">
			<property name="previews">auto</property>
			<FEED source="coreDef"/>
			<FEED source="//ssap#hcd_condDescs"/>
		</ssapCore>
	</service>

	<regSuite title="LAMOST5 regression">
		<regTest title="LAMOST5 SSA yields plausible data">
			<url request="querydata" POS="332.39212,-1.865556" SIZE="0.0001"
				>ssa/ssap.xml</url>
			<code>
				row = self.getFirstVOTableRow()
				self.assertAlmostEqual(row["ssa_specext"], 5.39705e-07)
				self.assertEqual(row["accsize"], 100000)
				self.assertEqual(row["ssa_targname"], 'LAMOST J220934.11-015156.0')
				self.assertAlmostEqual(row["ssa_dateObs"], 55858.5208333335)
				self.assertTrue(row["preview"].endswith(
					"/getproduct/lamost5/data/20111024/F5902/"
					"spec-55859-F5902_sp01-010?preview=True"))
			</code>
		</regTest>

		<regTest title="LAMOST5 datalink has expected links">
			<url ID="ivo://org.gavo.dc/~?lamost5/data/20111024/F5902/spec-55859-F5902_sp01-010"
				>sdl/dlmeta</url>
			<code>
				rows = self.getVOTableRows()
				bySemantics = {row["semantics"]:
						row["access_url"].split("/lamost5/q")[-1]
					for row in rows if row["access_url"]}
				self.assertEqual(bySemantics["#preview"], "/preview/qp"
					"/lamost5/data/20111024/F5902/spec-55859-F5902_sp01-010")
				self.assertEqual(bySemantics["#progenitor"],
					"/sdl/static/20111024/F5902/spec-55859-F5902_sp01-010.fits.gz")
				self.assertEqual(bySemantics["#this"],
					EqualingRE(".*/getproduct/lamost5/data/20111024/F5902"
					"/spec-55859-F5902_sp01-010"))
			</code>
		</regTest>

		<regTest title="LAMOST original FITS accessible">
			<url>sdl/static/20111024/F5902/spec-55859-F5902_sp01-010.fits.gz</url>
			<code>
				self.assertHasStrings(
					b'\\x1f\\x8b',
					"spec-55859-F5902")
			</code>
		</regTest>

		<regTest title="LAMOST5 preview looks like a PNG">
			<url httpHonorRedirects="True">/getproduct/lamost5/data/
				20111024/F5902/spec-55859-F5902_sp01-010?preview=True</url>
			<code>
				self.assertHasStrings("PNG", "IDAT", b"\\x45\\xff")
			</code>
		</regTest>

		<regTest title="LAMOST5 SDM spectrum looks about right">
			<url httpHonorRedirects="True">/getproduct/lamost5/data/20111024
				/F5902/spec-55859-F5902_sp01-010</url>
			<code>
				row = self.getFirstVOTableRow(rejectExtras=False)
				self.assertAlmostEqual(row["spectral"], 3699.986328125)
				self.assertAlmostEqual(row["flux"], 96.8080368041)
				self.assertAlmostEqual(row["flux_error"], 71.36109161376953)
				self.assertXpath("//v:PARAM[@utype='spec:"
					"Spectrum.Char.SpatialAxis.Coverage.Bounds.Extent']", {
						"value": EqualingRE(r"0.00091666\d*"),
						"datatype": "float",
						"ucd": "phys.angSize;instr.fov",
						"unit": "deg"})
				self.assertXpath("//v:FIELD[@name='flux']", {
					"unit": "count",})
			</code>
		</regTest>

		<regTest title="LAMOST5 SDM cutout">
			<url
				ID="lamost5/data/20111024/F5902/spec-55859-F5902_sp01-010"
				BAND="5.3e-7 5.31e-7"
				>sdl/dlget</url>
			<code>
				rows = self.getVOTableRows()
				self.assertEqual(len(rows), 8)
				self.assertAlmostEqual(rows[0]["spectral"], 5300.2958984375)
				self.assertAlmostEqual(rows[-1]["spectral"], 5308.845703125)
				self.assertAlmostEqual(rows[0]["flux"], 6.183320999145508)
				self.assertAlmostEqual(rows[0]["flux_error"], 3.688295841217041)
				self.assertXpath("//v:PARAM[@utype='spec:"
					"Spectrum.Char.SpectralAxis.Coverage.Bounds.Start']", {
						"value": EqualingRE(r"5.3002958\\d*e-07"),
						"datatype": "float",
						"ucd": "em.wl;stat.min",
						"unit": "m"})
				self.assertXpath("//v:FIELD[@name='flux']", {
					"unit": "count",})
			</code>
		</regTest>

		<regTest title="LAMOST5 SDM cutout, normalized calibration">
			<url
				ID="lamost5/data/20111024/F5902/spec-55859-F5902_sp01-010"
				FLUXCALIB="normalized"
				BAND="5.3e-7 5.31e-7"
				>sdl/dlget</url>
			<code>
				rows = self.getVOTableRows()
				self.assertEqual(len(rows), 8)
				self.assertAlmostEqual(rows[0]["spectral"], 5300.2958984375)
				self.assertAlmostEqual(rows[-1]["spectral"], 5308.845703125)
				self.assertAlmostEqual(rows[0]["flux"], 0.034412521868944)
				self.assertAlmostEqual(rows[0]["flux_error"], 3.688295841217041)
				self.assertXpath("//v:FIELD[@name='flux']", {
					"unit": " ",})
			</code>
		</regTest>

	</regSuite>
</resource>
