Skip to content
Snippets Groups Projects
Commit 1cb93e23 authored by Brian Moe's avatar Brian Moe
Browse files

Query on event attributes. #933

parent ae2e1f04
No related branches found
No related tags found
No related merge requests found
......@@ -6,7 +6,8 @@ from models import Event, Group, Label
from django.contrib.auth.models import User
from django.core.exceptions import FieldError
from query import parseQuery, ParseException
from query import parseQuery
from pyparsing import ParseException
htmlEntityStar = "★"
htmlEntityRightPointingHand = "☞"
......@@ -31,7 +32,7 @@ class GraceQueryField(forms.CharField):
raise forms.ValidationError(mark_safe(err))
except Exception, e:
# What could this be and how can we handle it better? XXX
raise forms.ValidationError(str(e))
raise forms.ValidationError(str(e)+str(type(e)))
class SimpleSearchForm(forms.Form):
query = GraceQueryField(required=False, widget=forms.TextInput(attrs={'size':60}))
......
......@@ -23,7 +23,7 @@ from pyparsing import \
Word, nums, Literal, CaselessLiteral, delimitedList, Suppress, QuotedString, \
Keyword, Combine, Or, Optional, OneOrMore, alphas, Regex, \
opAssoc, operatorPrecedence, oneOf, \
stringStart, stringEnd, ParseException
stringStart, stringEnd
def maybeRange(name, dbname=None):
dbname = dbname or name
......@@ -170,41 +170,59 @@ labelQ.setParseAction(lambda toks: ("label", toks[0]))
###########################
# Query on event attributes
attrNumExprOperators = { "<" : "__lt",
"<=": "__lte",
"=" : "",
">" : "__gt",
">=": "__gte",
}
lparen = Suppress('(')
rparen = Suppress(')')
attrNumExprLhs = Keyword("far") | Keyword("gpstime")
exprOperators = { "<" : "__lt",
"<=": "__lte",
"=" : "",
">" : "__gt",
">=": "__gte",
}
tableTranslations = {
'si': 'singleinspiral',
'ci': 'coincinspiralevent',
'mb': 'multiburstevent',
'coincinspiral': 'coincinspiralevent',
'multiburst': 'multiburstevent',
}
def buildDjangoQueryField(toks):
toks = [name.lower() for name in toks]
return "__".join([tableTranslations.get(name, name) for name in toks])
exponent = Combine(Word("Ee") + Optional(Word("+-"))+Word(nums))
afloat = Combine( Word(nums) + Optional(Combine(Literal(".") + Word(nums))) )
attrNumExprRhs = Combine( Optional(Word("+-")) + afloat + Optional(exponent) )
attrNumExprRhs.setParseAction(lambda toks: float(toks[0]))
afloat = Combine( Word(nums) + \
Optional(Combine(Literal(".") + Word(nums))) ) + \
Optional(exponent)
afloat.setParseAction(lambda toks: float(toks[0]))
lhs = delimitedList(Word(alphas+'_'), '.')
lhs.setParseAction(buildDjangoQueryField)
attrNumExprOp = Or(map(Literal, attrNumExprOperators.keys()))
attrNumExprOp.setParseAction(lambda toks: attrNumExprOperators[toks[0]])
rhs = afloat | QuotedString('"')
attrNumExpr = attrNumExprLhs + attrNumExprOp + attrNumExprRhs
attrNumExpr.setParseAction(lambda toks: Q(**{toks[0]+toks[1]: toks[2]}))
op = Or(map(Literal, exprOperators.keys()))
op.setParseAction(lambda toks: exprOperators[toks[0]])
#attrIfoExpr = Keyword("ifos").suppress() + Literal("=").suppress() + Word("LVH12,")
#attrIfoExpr.setParseAction(lambda toks: Q(instruments=toks[0]))
simpleTerm = lhs + op + rhs
simpleTerm.setParseAction(lambda toks: Q(**{toks[0]+toks[1]: toks[2]}))
#attrExpr = attrIfoExpr | attrNumExpr
attrExpr = attrNumExpr
rangeTerm = lhs + Suppress('in') + rhs + Suppress(",") + rhs
rangeTerm.setParseAction(lambda toks: Q(**{toks[0]+"__range": toks[1:]}))
attrExprs = operatorPrecedence(attrExpr,
term = simpleTerm | rangeTerm
attrExpressions = operatorPrecedence(term,
[(minusop, 1, opAssoc.RIGHT, lambda a,b,toks: ~toks[0][0]),
(orop, 2, opAssoc.LEFT, lambda a,b,toks: reduce(Q.__or__, toks[0].asList(), Q())),
(andop, 2, opAssoc.LEFT, lambda a,b,toks: reduce(Q.__and__, toks[0].asList(), Q())),
]).setParseAction(lambda toks: toks[0])
attributeQ = Optional(Suppress(Keyword('attr:'))) + attrExprs.copy()
#attributeQ = lparen + attrExpressions + rparen
attributeQ = attrExpressions.copy()
attributeQ.setParseAction(lambda toks: ("attr", toks[0]))
......
<div id="hints" style="display: none;">
<h4>By Event Attributes</h4>
Relational and range queries can be made on event attributes.
<ul>
<li><code>instruments = "H1,L1,V1" &amp; far &lt; 1e-7</code></li>
<li><code>singleinspiral.mchirp &gt;= 1.6 &amp; eff_distance in 40.5,55 </code></li>
<li><code>(si.channel = "DMT-STRAIN" | si.channel = "DMT-PAIN") &amp; si.snr &lt; 5</code></li>
<li><code>mb.snr in 1,3 &amp; mb.central_freq &gt; 1000</code></li>
</ul>
Attributes in the common event object (eg gpstime, far, instruments) do not need qualifiers. Attributes specific to inspiral or burst events, for example, require qualification. Abbreviations are available: <code>si</code> for singleinspiral, <code>ci</code> for coincinspiral and <code>mb</code> for multiburst.
<h4>By GPS Time</h4>
Specifiy an exact GPS time, or a range.
Integers will be assumed to be GPS times, making the <code>gpstime:</code>
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment