<resource schema="casa_lines">
	<meta name="creationDate">2022-02-24T13:25:12Z</meta>
	<meta name="schema-rank">500</meta>

	<meta name="title">Splatalogue CASA SLAP2</meta>
	<meta name="description" format="rst">
		This is a rendering of the `CASA Offline Splatalogue`_ in
		a draft SLAP2 service, mainly intended to enable verification of the
		standard.
		This is not recommended for production yet.  In particular, many
		InChIs are known wrong, and we have skipped several hundred lines
		because we did have no InChIs for their species at all.

		.. _CASA Offline Splatalogue: https://safe.nrao.edu/wiki/bin/view/ALMA/CASA_Offline_Splat_list
	</meta>
	<meta name="subject">spectral-line-identification</meta>
	<meta name="subject">atomic-physics</meta>
	<meta name="subject">molecular-physics</meta>

	<meta name="creator">Brogan, C.; Remijan, A. J.; Markwick-Kemper, A.</meta>

	<meta name="source">2007AAS...21113211R</meta>
	<meta name="contentLevel">Research</meta>
	<meta name="type">Catalog</meta>

	<meta name="coverage.waveband">Radio</meta>
	<meta name="coverage.waveband">Millimeter</meta>
	<meta name="coverage.waveband">Infrared</meta>

	<table id="data">
		<mixin>//slap2#lines</mixin>

		<column name="nrao_formula" type="text"
			ucd="meta.id;phys.mol"
			tablehead="NRAO formula"
			description="Chemical formula in NRAO's argot."/>
		<column name="quantnr" type="text"
			ucd="phys.atmol.configuration"
			tablehead="Quantum Numbers"
			description="Resolved Quantum Number as per
				http://www.cv.nrao.edu/php/splat/QuantumCode.html"/>
		<column name="dipole_moment"
			unit="D"
			tablehead="Dipole moment"
			description="Molecule dipole moment Sij μ²"/>
	</table>

	<coverage>
		<updater spectralTable="data"/>
	</coverage>

	<data id="import">
		<sources pattern="data/*.tsv"/>

		<reGrammar topIgnoredLines="1" fieldSep="\t"
			names="species, ignored, chem_name, restfreq, quantnr,
			intensity, dipole_moment, log_einstein_a, e_lower_cm, e_lower, e_upper, src"/>

		<make table="data">
			<rowmaker idmaps="*">
				<simplemaps>nrao_formula: species</simplemaps>
				<apply name="compute_inchis">
					<setup imports="gavo.protocols.linetap,gavo.api">
						<par name="KNOWN_SPECIES">{}</par>
						<code>
							# we identify species by their formula.  That's not
							# foolproof but good enough for this particular application.
							with open(
									rd.getAbsPath("res/species-key.txt"),
									encoding="utf-8") as src:
								for ln in src:
									try:
										formula, human, _, inchi, inchiKey, molw =\
											ln.split("\t")

										# if you ever add to the following code, go use
										# a proper inchi parser.
										if '/q+1' in inchi:
											charge = 1
										elif '/q-1' in inchi:
											charge = -1
										else:
											charge = 0

										KNOWN_SPECIES[formula
											] = human, inchi, inchiKey, molw, charge
									except ValueError:
										raise Exception(f"Bad species-key: {ln}")
						</code>
					</setup>
					<code>
						@commmon_name, @inchi, @inchikey, @molweight, @charge =\
							KNOWN_SPECIES[@species]
					</code>
				</apply>

				<apply procDef="//procs#dictMap">
					<bind name="key">"src"</bind>
					<bind name="mapping">{
						"CDMS": "bibcode:2005JMoSt.742..215M",
						"JPL": "bibcode:1998JQSRT..60..883P",
						"SLAIM":
							"https://physics.nist.gov/cgi-bin/micro/table5/start.pl",
					}</bind>
				</apply>

				<apply procDef="//slap2#populate-lines">
					<bind name="einsteina">10**float(@log_einstein_a)</bind>
					<bind name="inchi">@inchi</bind>
					<bind name="inchikey">@inchikey</bind>
					<bind name="ion_charge">@charge</bind>
					<bind name="line_title">"CASA "+@species+" "+@quantnr</bind>
					<bind name="lower_level_energy">float(@e_lower)*BOLTZMANN_K</bind>
					<bind name="lower_level_description">"See quantnr"</bind>
					<bind name="reference_uri">@src</bind>
					<bind name="species_mass">@molweight</bind>
					<bind name="species_name">@chem_name</bind>
					<bind name="upper_level_energy">float(@e_upper)*BOLTZMANN_K</bind>
					<bind name="upper_level_description">"See quantnr"</bind>
					<bind name="vacuum_wavelength"
						>LIGHT_C/(float(@restfreq)*1e9)</bind>
				</apply>
				<map key="quantnr">@quantnr.replace("&amp;Omega", "Ω")</map>
			</rowmaker>
		</make>
	</data>

	<table id="specsupp" mixin="//slap2#species-supplement">
		<meta name="description">
			Per-species metadata for the CASA lines.
		</meta>
		<column name="mol_structure" type="text"
			description="Inferred or divined molecule structure the GAVO
				data centre used to compute the inchi.  This is in a custom
				syntax explained in the footnote; use it for debugging if you
				disagree with an inchi."
				note="molsyn"/>

		<meta name="note" tag="molsyn">
			The molecule specification consists of whitespace-separated atoms or
			connections in arbitrary order.  An atom is ``[isotope]Atom[charge]``,
			where isotope is a number and charge a number of + or -.  A connection is
			index(-=#)index, where index enumerates the atom, 1-based and -,=,# is a
			single, double, or triple bond.

			Examples::
				H 1-2 H
				H H O 1-3 2-3
				H 1-2 C 2#3 C 3-4 C H H H 4-5 4-6 4-7
		</meta>
	</table>

	<data id="import-sp">
		<sources pattern="res/species-key.txt"/>
		<reGrammar
			fieldSep="\t"
			names="formula, human, dachs, inchi, inchiKey, molw"/>
		<make table="specsupp">
			<rowmaker idmaps="*">
				<apply procDef="//slap2#populate-species">
					<bind key="inchikey">@inchiKey</bind>
					<bind key="number_of_atoms">@molw</bind>
					<bind key="stoichiometric_formula">@formula</bind>
					<bind key="species_type"
						>'atom' if len(@dachs.split())==1 else 'molecule'</bind>
				</apply>
				<map key="mol_structure" source="dachs"/>
			</rowmaker>
		</make>
	</data>

	<service id="sp" allowed="species">
		<meta name="shortName">casa species</meta>
		<meta name="description">Search for species reflected in this resource
			here.</meta>
		<FEED source="//pql#DALIPars"/>
		<slap2SpeciesCore queriedTable="data" speciesTable="specsupp">
			<FEED source="//slap2#species-pars"/>
		</slap2SpeciesCore>
	</service>

	<service id="q" allowed="form,lines">
		<meta name="shortName">casa lines</meta>
		<meta name="description">These are spectral lines from the
			splatalogue that come with casa</meta>
		<meta name="slap.dataSource">observation/astrophysical</meta>
		<meta name="slap.testQuery">MAXREC=1</meta>

		<publish render="lines" sets="ivo_managed"/>
		<publish render="species" sets="ivo_managed" service="sp"/>

		<FEED source="//pql#DALIPars"/>
		<dbCore queriedTable="data">
			<property name="rejectExtras">ignored</property>
			<FEED source="//slap2#lines-pars"/>
		</dbCore>
	</service>

	<regSuite title="casa_lines regression">
		<regTest title="CASA lines endpoint inchikey plus wavelength">
			<url INCHIKEY="WSFSSNUMVMOOMR-OUBTZVSYSA-N"
				WAVELENGTH="0.27 0.28">q/lines</url>
			<code>
				row = self.getFirstVOTableRow()
				self.assertAlmostEqual(row["upper_level_energy"], 2.05957038855324e-20)
				self.assertAlmostEqual(row["einsteina"], 2.9360266952510552e-12)
				self.assertEqual(row["line_title"], "CASA H213CO 26(5,21)-26(5,22)")
				self.assertEqual(row["reference_uri"], 'bibcode:2005JMoSt.742..215M')
			</code>
		</regTest>

		<regTest title="CASA species endpoint">
			<url SPECIES="Ammon*">sp/species</url>
			<code>
				rows = self.getVOTableRows()
				self.assertTrue({
					r['stoichiometric_formula'] for r in rows} &gt;=
					{'ND3', 'NH2D', 'NHD2'},
					f"Hu?  Got back {rows}")
			</code>
		</regTest>
	</regSuite>
</resource>
