def adaptTable(origTable, newColumns): """returns a Data instance created from origTable with columns taken from newColumns. The adaptation works like this: (1) if names and units of newColumns are a subset of origTable.columns, return a table with the rows from origTable and the columns from newColumns. (1a) if origTable has a noPostprocess attribute, proceed to (4) (2) if names of newColumns are a subset of origTable.columns match but one or more units don't, set up a conversion routine and create new rows, combining them with newColumns to the result. (3) else raise an error. (4) Finally, stick the whole thing into a data container. This stinks. I'm plotting to do away with it. """ if hasattr(origTable, "noPostprocess"): colDiffs = None newTd = origTable.tableDef else: colDiffs = base.computeColumnConversions(newColumns, origTable.tableDef.columns) newTd = origTable.tableDef.copy(origTable.tableDef.parent) newTd.columns = newColumns if not colDiffs: newTable = table.InMemoryTable(newTd, rows=origTable.rows) newTable.meta_ = origTable.meta_ newTable._params = origTable._params else: # we need to do work newTd.copyMetaFrom(origTable.tableDef) rmk = rscdef.RowmakerDef(None) for col in newColumns: exprStart = "" if col.name in colDiffs: exprStart = "%s*" % colDiffs[col.name] rmk.feedObject( "map", rmkdef.MapRule( rmk, dest=col.name, content_="%svars[%s]" % (exprStart, repr(col.name))).finishElement(None)) newTable = table.InMemoryTable(newTd, validate=False) mapper = rmk.finishElement(None).compileForTableDef(newTd) for r in origTable: newTable.addRow(mapper(r, newTable)) newTable._params = origTable._params return rsc.wrapTable(newTable, rdSource=origTable.tableDef)
def makeVOTable(data, ctx=None, **kwargs): """returns a votable.V.VOTABLE object representing data. data can be an rsc.Data or an rsc.Table. data can be a data or a table instance, tablecoding any key in votable.tableEncoders. You may pass a VOTableContext object; if you don't a context with all defaults will be used. A deprecated alternative is to directly pass VOTableContext constructor arguments as additional keyword arguments. Don't do this, though, we'll probably remove the option to do so at some point. You will usually pass the result to votable.write. The object returned contains DelayedTables, i.e., most of the content will only be realized at render time. """ ctx = ctx or VOTableContext(**kwargs) data = rsc.wrapTable(data) if ctx.version==(1,1): vot = V.VOTABLE11() elif ctx.version==(1,2): vot = V.VOTABLE12() elif ctx.version==(1,3): vot = V.VOTABLE() elif ctx.version==(1,4): vot = V.VOTABLE() # TODO: When 1.4 XSD comes out, actually implement else: raise votable.VOTableError("No toplevel element for VOTable version %s"% ctx.version) vot[_iterToplevelMeta(ctx, data)] vot[_makeResource(ctx, data)] if ctx.produceVODML: if ctx.modelsUsed: # if we declare any models, we'll need vo-dml ctx.addVODMLPrefix("vo-dml") for model in ctx.modelsUsed.values(): vot[model.getVOT(ctx)] if ctx.suppressNamespace: # use this for "simple" table with nice element names vot._fixedTagMaterial = "" # What follows is a hack around the insanity of stuffing # unused namespaces and similar detritus into VOTable's roots. rootAttrs = data.getMeta("_votableRootAttributes") if rootAttrs: rootHacks = [vot._fixedTagMaterial]+[ item.getContent() for item in rootAttrs] vot._fixedTagMaterial = " ".join(s for s in rootHacks if s) return vot
def _makeDataFor(resultTable): """returns an rsc.Data instance containing resultTable and some additional metadata. """ resData = rsc.wrapTable(resultTable) resData.addMeta("info", "Query successful", infoName="QUERY_STATUS", infoValue="OK") resData.addMeta("_type", "results") # setLimit is the effective maximum number of rows returned # as determined by adqlglue.morphADQL (or similar functions) resData.setLimit = getattr(resultTable.tableDef, "setLimit", None) return resData
def writeDataAsFITS(data, outputFile, acquireSamples=False): """a formats.common compliant data writer. This will write out table params as header cards. To serialise those yourself (as is required for spectral data model compliant tables), set an attribute IgnoreTableParams (with an arbitrary value) on the table. """ data = rsc.wrapTable(data) fitsName = makeFITSTableFile(data, acquireSamples) try: src = open(fitsName) utils.cat(src, outputFile) src.close() finally: os.unlink(fitsName)
def _run_queryData(self, service, inputTable, queryMeta): format = inputTable.getParam("FORMAT") or "" if format.lower() == "metadata": return self._makeMetadata(service) limits = [ q for q in (inputTable.getParam("MAXREC", None), inputTable.getParam("TOP")) if q ] if not limits: limits = [base.getConfig("ivoa", "dalDefaultLimit")] limit = min(min(limits), base.getConfig("ivoa", "dalHardLimit")) queryMeta["dbLimit"] = limit res = svcs.DBCore.run(self, service, inputTable, queryMeta) if len(res) == limit: queryStatus = "OVERFLOW" queryStatusBody = ( "Exactly %s rows were returned. This means your" " query probably reached the match limit. Increase MAXREC." % limit) else: queryStatus = "OK" queryStatusBody = "" self._addPreviewLinks(res) # We wrap our result into a data instance since we need to set the # result type data = rsc.wrapTable(res) data.setMeta("_type", "results") data.addMeta("_votableRootAttributes", 'xmlns:ssa="http://www.ivoa.net/xml/DalSsap/v1.0"') # The returnRaw property is a hack, mainly for unit testing; # The renderer would have to add the QUERY_STATUS here. if service.getProperty("returnData", False): return data # we fix tablecoding to td for now since nobody seems to like # binary tables and we don't have huge tables here. votCtx = votablewrite.VOTableContext(tablecoding="td") vot = votablewrite.makeVOTable(data, votCtx) pubDIDId = votCtx.getIdFor(res.tableDef.getColumnByName("ssa_pubDID")) resElement = vot.getChildDict()["RESOURCE"][0] resElement[ V.INFO(name="SERVICE_PROTOCOL", value=self.ssapVersion)["SSAP"], V.INFO(name="QUERY_STATUS", value=queryStatus)[queryStatusBody]] datalinkId = service.getProperty("datalink", None) if datalinkId and res: dlService = self.rd.getById(datalinkId) dlCore = getDatalinkCore(dlService, res) # new and shiny datalink (keep) # (we're just using endpoint 0; it should a the sync service) dlEndpoint = dlCore.datalinkEndpoints[0] vot[dlEndpoint.asVOT(votCtx, dlService.getURL(dlEndpoint.rendName), linkIdTo=pubDIDId)] # Also point to the dl metadata service vot[V.RESOURCE(type="meta", utype="adhoc:service")[ V.PARAM(name="standardID", datatype="char", arraysize="*", value="ivo://ivoa.net/std/DataLink#links-1.0"), V.PARAM(name="accessURL", datatype="char", arraysize="*", value=self.rd.getById(datalinkId).getURL("dlmeta")), V.GROUP(name="inputParams")[V.PARAM( name="ID", datatype="char", arraysize="*", ref=pubDIDId, ucd="meta.id;meta.main" )[V.LINK(content_role="ddl:id-source", value="#" + pubDIDId)]]]] return "application/x-votable+xml", votable.asString(vot)