diff --git a/gracedb/api.py b/gracedb/api.py index a5b2abcfeef091ed2238f7b845f6ad56eb152a21..dd7b18a52306098e37a3c3cede69e8963c8fde3c 100644 --- a/gracedb/api.py +++ b/gracedb/api.py @@ -369,8 +369,7 @@ class EventList(APIView): if query: form = SimpleSearchForm(request.GET) if form.is_valid(): - cooked_query = form.cleaned_data['query'] - events = events.filter(cooked_query).distinct() + events = form.cleaned_data['query'] else: d = {'error': 'Invalid query' } return Response(d,status=status.HTTP_400_BAD_REQUEST) diff --git a/gracedb/forms.py b/gracedb/forms.py index 93448eb7178745e64c35af82dc3ef71425a5fb46..2e5497ae33ec54178079e8d9d6fc6757c0a67fcb 100644 --- a/gracedb/forms.py +++ b/gracedb/forms.py @@ -4,8 +4,10 @@ from django.utils.safestring import mark_safe from django.utils.html import escape 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 = "☞" @@ -20,13 +22,17 @@ class GraceQueryField(forms.CharField): from django.db.models import Q queryString = forms.CharField.clean(self, queryString) try: - return parseQuery(queryString) + return Event.objects.filter(parseQuery(queryString)).distinct() except ParseException, e: err = "Error: " + escape(e.pstr[:e.loc]) + errorMarker + escape(e.pstr[e.loc:]) raise forms.ValidationError(mark_safe(err)) + except FieldError, e: + # XXX error message can be more polished than this + err = "Error: " + str(e) + 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})) diff --git a/gracedb/migrations/0009_add_single_inspiral.py b/gracedb/migrations/0009_add_single_inspiral.py new file mode 100644 index 0000000000000000000000000000000000000000..60811a224d6dda7418fc8bf28f2b53327d36d799 --- /dev/null +++ b/gracedb/migrations/0009_add_single_inspiral.py @@ -0,0 +1,271 @@ +# -*- coding: utf-8 -*- +import datetime +from south.db import db +from south.v2 import SchemaMigration +from django.db import models + + +class Migration(SchemaMigration): + + def forwards(self, orm): + # Adding model 'SingleInspiral' + db.create_table('gracedb_singleinspiral', ( + ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)), + ('event', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['gracedb.Event'])), + ('ifo', self.gf('django.db.models.fields.CharField')(max_length=20, null=True)), + ('search', self.gf('django.db.models.fields.CharField')(max_length=20, null=True)), + ('channel', self.gf('django.db.models.fields.CharField')(max_length=20)), + ('end_time', self.gf('django.db.models.fields.IntegerField')(null=True)), + ('end_time_ns', self.gf('django.db.models.fields.IntegerField')(null=True)), + ('end_time_gmst', self.gf('django.db.models.fields.FloatField')(null=True)), + ('impulse_time', self.gf('django.db.models.fields.IntegerField')(null=True)), + ('impulse_time_ns', self.gf('django.db.models.fields.IntegerField')(null=True)), + ('template_duration', self.gf('django.db.models.fields.FloatField')(null=True)), + ('event_duration', self.gf('django.db.models.fields.FloatField')(null=True)), + ('amplitude', self.gf('django.db.models.fields.FloatField')(null=True)), + ('eff_distance', self.gf('django.db.models.fields.FloatField')(null=True)), + ('coa_phase', self.gf('django.db.models.fields.FloatField')(null=True)), + ('mass1', self.gf('django.db.models.fields.FloatField')(null=True)), + ('mass2', self.gf('django.db.models.fields.FloatField')(null=True)), + ('mchirp', self.gf('django.db.models.fields.FloatField')(null=True)), + ('mtotal', self.gf('django.db.models.fields.FloatField')(null=True)), + ('eta', self.gf('django.db.models.fields.FloatField')(null=True)), + ('kappa', self.gf('django.db.models.fields.FloatField')(null=True)), + ('chi', self.gf('django.db.models.fields.FloatField')(null=True)), + ('tau0', self.gf('django.db.models.fields.FloatField')(null=True)), + ('tau2', self.gf('django.db.models.fields.FloatField')(null=True)), + ('tau3', self.gf('django.db.models.fields.FloatField')(null=True)), + ('tau4', self.gf('django.db.models.fields.FloatField')(null=True)), + ('tau5', self.gf('django.db.models.fields.FloatField')(null=True)), + ('ttotal', self.gf('django.db.models.fields.FloatField')(null=True)), + ('psi0', self.gf('django.db.models.fields.FloatField')(null=True)), + ('psi3', self.gf('django.db.models.fields.FloatField')(null=True)), + ('alpha', self.gf('django.db.models.fields.FloatField')(null=True)), + ('alpha1', self.gf('django.db.models.fields.FloatField')(null=True)), + ('alpha2', self.gf('django.db.models.fields.FloatField')(null=True)), + ('alpha3', self.gf('django.db.models.fields.FloatField')(null=True)), + ('alpha4', self.gf('django.db.models.fields.FloatField')(null=True)), + ('alpha5', self.gf('django.db.models.fields.FloatField')(null=True)), + ('alpha6', self.gf('django.db.models.fields.FloatField')(null=True)), + ('beta', self.gf('django.db.models.fields.FloatField')(null=True)), + ('f_final', self.gf('django.db.models.fields.FloatField')(null=True)), + ('snr', self.gf('django.db.models.fields.FloatField')(null=True)), + ('chisq', self.gf('django.db.models.fields.FloatField')(null=True)), + ('chisq_dof', self.gf('django.db.models.fields.IntegerField')(null=True)), + ('bank_chisq', self.gf('django.db.models.fields.FloatField')(null=True)), + ('bank_chisq_dof', self.gf('django.db.models.fields.IntegerField')(null=True)), + ('cont_chisq', self.gf('django.db.models.fields.FloatField')(null=True)), + ('cont_chisq_dof', self.gf('django.db.models.fields.IntegerField')(null=True)), + ('sigmasq', self.gf('django.db.models.fields.FloatField')(null=True)), + ('rsqveto_duration', self.gf('django.db.models.fields.FloatField')(null=True)), + ('Gamma0', self.gf('django.db.models.fields.FloatField')(null=True)), + ('Gamma1', self.gf('django.db.models.fields.FloatField')(null=True)), + ('Gamma2', self.gf('django.db.models.fields.FloatField')(null=True)), + ('Gamma3', self.gf('django.db.models.fields.FloatField')(null=True)), + ('Gamma4', self.gf('django.db.models.fields.FloatField')(null=True)), + ('Gamma5', self.gf('django.db.models.fields.FloatField')(null=True)), + ('Gamma6', self.gf('django.db.models.fields.FloatField')(null=True)), + ('Gamma7', self.gf('django.db.models.fields.FloatField')(null=True)), + ('Gamma8', self.gf('django.db.models.fields.FloatField')(null=True)), + ('Gamma9', self.gf('django.db.models.fields.FloatField')(null=True)), + )) + db.send_create_signal('gracedb', ['SingleInspiral']) + + + def backwards(self, orm): + # Deleting model 'SingleInspiral' + db.delete_table('gracedb_singleinspiral') + + + models = { + 'auth.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '80'}), + 'permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}) + }, + 'auth.permission': { + 'Meta': {'ordering': "('content_type__app_label', 'content_type__model', 'codename')", 'unique_together': "(('content_type', 'codename'),)", 'object_name': 'Permission'}, + 'codename': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'content_type': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['contenttypes.ContentType']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'}) + }, + 'auth.user': { + 'Meta': {'object_name': 'User'}, + 'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'email': ('django.db.models.fields.EmailField', [], {'max_length': '75', 'blank': 'True'}), + 'first_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'groups': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Group']", 'symmetrical': 'False', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}), + 'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'is_superuser': ('django.db.models.fields.BooleanField', [], {'default': 'False'}), + 'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}), + 'last_name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'blank': 'True'}), + 'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}), + 'user_permissions': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['auth.Permission']", 'symmetrical': 'False', 'blank': 'True'}), + 'username': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30'}) + }, + 'contenttypes.contenttype': { + 'Meta': {'ordering': "('name',)", 'unique_together': "(('app_label', 'model'),)", 'object_name': 'ContentType', 'db_table': "'django_content_type'"}, + 'app_label': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'model': ('django.db.models.fields.CharField', [], {'max_length': '100'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + }, + 'gracedb.approval': { + 'Meta': {'object_name': 'Approval'}, + 'approvedEvent': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gracedb.Event']"}), + 'approver': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'approvingCollaboration': ('django.db.models.fields.CharField', [], {'max_length': '1'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}) + }, + 'gracedb.coincinspiralevent': { + 'Meta': {'ordering': "['-id']", 'object_name': 'CoincInspiralEvent', '_ormbases': ['gracedb.Event']}, + 'combined_far': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'end_time': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}), + 'end_time_ns': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}), + 'event_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['gracedb.Event']", 'unique': 'True', 'primary_key': 'True'}), + 'false_alarm_rate': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'ifos': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '20'}), + 'mass': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'mchirp': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'minimum_duration': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'snr': ('django.db.models.fields.FloatField', [], {'null': 'True'}) + }, + 'gracedb.event': { + 'Meta': {'ordering': "['-id']", 'object_name': 'Event'}, + 'analysisType': ('django.db.models.fields.CharField', [], {'max_length': '20'}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'far': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'gpstime': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}), + 'group': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gracedb.Group']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'instruments': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '20'}), + 'labels': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['gracedb.Label']", 'through': "orm['gracedb.Labelling']", 'symmetrical': 'False'}), + 'likelihood': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'nevents': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}), + 'submitter': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'uid': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '20'}) + }, + 'gracedb.eventlog': { + 'Meta': {'ordering': "['-created']", 'object_name': 'EventLog'}, + 'comment': ('django.db.models.fields.TextField', [], {}), + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'event': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gracedb.Event']"}), + 'filename': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '100'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'issuer': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}) + }, + 'gracedb.group': { + 'Meta': {'object_name': 'Group'}, + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '20'}) + }, + 'gracedb.label': { + 'Meta': {'object_name': 'Label'}, + 'defaultColor': ('django.db.models.fields.CharField', [], {'default': "'black'", 'max_length': '20'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '20'}) + }, + 'gracedb.labelling': { + 'Meta': {'object_name': 'Labelling'}, + 'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}), + 'creator': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['auth.User']"}), + 'event': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gracedb.Event']"}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'label': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gracedb.Label']"}) + }, + 'gracedb.multiburstevent': { + 'Meta': {'ordering': "['-id']", 'object_name': 'MultiBurstEvent', '_ormbases': ['gracedb.Event']}, + 'amplitude': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'bandwidth': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'central_freq': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'confidence': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'duration': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'event_ptr': ('django.db.models.fields.related.OneToOneField', [], {'to': "orm['gracedb.Event']", 'unique': 'True', 'primary_key': 'True'}), + 'false_alarm_rate': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'ifos': ('django.db.models.fields.CharField', [], {'default': "''", 'max_length': '20'}), + 'ligo_angle': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'ligo_angle_sig': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'ligo_axis_dec': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'ligo_axis_ra': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'peak_time': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}), + 'peak_time_ns': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}), + 'snr': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'start_time': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}), + 'start_time_ns': ('django.db.models.fields.PositiveIntegerField', [], {'null': 'True'}) + }, + 'gracedb.singleinspiral': { + 'Gamma0': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'Gamma1': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'Gamma2': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'Gamma3': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'Gamma4': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'Gamma5': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'Gamma6': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'Gamma7': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'Gamma8': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'Gamma9': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'Meta': {'object_name': 'SingleInspiral'}, + 'alpha': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'alpha1': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'alpha2': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'alpha3': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'alpha4': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'alpha5': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'alpha6': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'amplitude': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'bank_chisq': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'bank_chisq_dof': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'beta': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'channel': ('django.db.models.fields.CharField', [], {'max_length': '20'}), + 'chi': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'chisq': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'chisq_dof': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'coa_phase': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'cont_chisq': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'cont_chisq_dof': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'eff_distance': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'end_time': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'end_time_gmst': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'end_time_ns': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'eta': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'event': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['gracedb.Event']"}), + 'event_duration': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'f_final': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'ifo': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True'}), + 'impulse_time': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'impulse_time_ns': ('django.db.models.fields.IntegerField', [], {'null': 'True'}), + 'kappa': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'mass1': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'mass2': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'mchirp': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'mtotal': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'psi0': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'psi3': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'rsqveto_duration': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'search': ('django.db.models.fields.CharField', [], {'max_length': '20', 'null': 'True'}), + 'sigmasq': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'snr': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'tau0': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'tau2': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'tau3': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'tau4': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'tau5': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'template_duration': ('django.db.models.fields.FloatField', [], {'null': 'True'}), + 'ttotal': ('django.db.models.fields.FloatField', [], {'null': 'True'}) + }, + 'gracedb.tag': { + 'Meta': {'object_name': 'Tag'}, + 'displayName': ('django.db.models.fields.CharField', [], {'max_length': '200', 'null': 'True'}), + 'eventlogs': ('django.db.models.fields.related.ManyToManyField', [], {'to': "orm['gracedb.EventLog']", 'symmetrical': 'False'}), + 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}), + 'name': ('django.db.models.fields.CharField', [], {'max_length': '100'}) + } + } + + complete_apps = ['gracedb'] \ No newline at end of file diff --git a/gracedb/models.py b/gracedb/models.py index 85cac3616a37e2abfe3a00b63c5eff57fce104ec..52d3e6a87263750f1f32c3fefb7b73c4849641db 100644 --- a/gracedb/models.py +++ b/gracedb/models.py @@ -12,6 +12,15 @@ import string import os import logging +import glue +import glue.ligolw +import glue.ligolw.utils +import glue.ligolw.table +import glue.ligolw.lsctables +from glue.lal import LIGOTimeGPS + +log = logging.getLogger('gracedb.models') + # XXX ER2.utils. utils is in project directory. ugh. from utils import posixToGpsTime @@ -287,6 +296,129 @@ class MultiBurstEvent(Event): ligo_angle = models.FloatField(null=True) ligo_angle_sig = models.FloatField(null=True) +class SingleInspiral(models.Model): + event = models.ForeignKey(Event, null=False) + ifo = models.CharField(max_length=20, null=True) + search = models.CharField(max_length=20, null=True) + channel = models.CharField(max_length=20) + end_time = models.IntegerField(null=True) + end_time_ns = models.IntegerField(null=True) + end_time_gmst = models.FloatField(null=True) + impulse_time = models.IntegerField(null=True) + impulse_time_ns = models.IntegerField(null=True) + template_duration = models.FloatField(null=True) + event_duration = models.FloatField(null=True) + amplitude = models.FloatField(null=True) + eff_distance = models.FloatField(null=True) + coa_phase = models.FloatField(null=True) + mass1 = models.FloatField(null=True) + mass2 = models.FloatField(null=True) + mchirp = models.FloatField(null=True) + mtotal = models.FloatField(null=True) + eta = models.FloatField(null=True) + kappa = models.FloatField(null=True) + chi = models.FloatField(null=True) + tau0 = models.FloatField(null=True) + tau2 = models.FloatField(null=True) + tau3 = models.FloatField(null=True) + tau4 = models.FloatField(null=True) + tau5 = models.FloatField(null=True) + ttotal = models.FloatField(null=True) + psi0 = models.FloatField(null=True) + psi3 = models.FloatField(null=True) + alpha = models.FloatField(null=True) + alpha1 = models.FloatField(null=True) + alpha2 = models.FloatField(null=True) + alpha3 = models.FloatField(null=True) + alpha4 = models.FloatField(null=True) + alpha5 = models.FloatField(null=True) + alpha6 = models.FloatField(null=True) + beta = models.FloatField(null=True) + f_final = models.FloatField(null=True) + snr = models.FloatField(null=True) + chisq = models.FloatField(null=True) + chisq_dof = models.IntegerField(null=True) + bank_chisq = models.FloatField(null=True) + bank_chisq_dof = models.IntegerField(null=True) + cont_chisq = models.FloatField(null=True) + cont_chisq_dof = models.IntegerField(null=True) + sigmasq = models.FloatField(null=True) + rsqveto_duration = models.FloatField(null=True) + Gamma0 = models.FloatField(null=True) + Gamma1 = models.FloatField(null=True) + Gamma2 = models.FloatField(null=True) + Gamma3 = models.FloatField(null=True) + Gamma4 = models.FloatField(null=True) + Gamma5 = models.FloatField(null=True) + Gamma6 = models.FloatField(null=True) + Gamma7 = models.FloatField(null=True) + Gamma8 = models.FloatField(null=True) + Gamma9 = models.FloatField(null=True) + + def end_time_full(self): + return LIGOTimeGPS(self.end_time, self.end_time_ns) + + def impulse_time_full(self): + return LIGOTimeGPS(self.impulse_time, self.impulse_time_ns) + + @classmethod + def create_events_from_ligolw_table(cls, table, event): + """For an Event, given a table (loaded by ligolw.utils.load_filename or similar) create SingleEvent tables for the event""" + + field_names = cls.field_names() + created_events = [] + + log.debug("Single/create from table/fields: " + str(field_names)) + + for row in table: + e = cls(event=event) + log.debug("Single/creating event") + for column in field_names: + value = getattr(row, column) + log.debug("Setting column '%s' with value '%s'" % (column, value)) + setattr(e, column, value) + e.save() + created_events.append(e) + + return created_events + + @classmethod + def update_event(cls, event, datafile=None): + """Given an Event (and optional location of coinc.xml) update SingleInspiral data""" + # XXX Need a better way to find original data. + if datafile is None: + datafile = os.path.join(event.datadir(), 'coinc.xml') + + try: + xmldoc = glue.ligolw.utils.load_filename(datafile) + except IOError: + return None + + # Extract Single Inspiral Information + s_inspiral_tables = glue.ligolw.table.getTablesByName( + xmldoc, + glue.ligolw.lsctables.SnglInspiralTable.tableName) + + # Concatentate the tables' rows into a single table + table = sum(s_inspiral_tables, []) + + event.singleinspiral_set.all().delete() + + return cls.create_events_from_ligolw_table(table, event) + + @classmethod + def field_names(cls): + try: + return cls._field_names + except AttributeError: pass + model_field_names = set([ x.name for x in cls._meta.fields ]) + ligolw_field_names = set( + glue.ligolw.lsctables.SnglInspiralTable.validcolumns.keys()) + + cls._field_names = model_field_names.intersection(ligolw_field_names) + return cls._field_names + + ## Tags (user-defined log message attributes) class Tag(models.Model): """Tag Model""" diff --git a/gracedb/query.py b/gracedb/query.py index 60f8402f0ef5a8f1137a7047e88a9a6935170812..7abcf5f15d2db0fd0de913c9c0e53a20010d815b 100644 --- a/gracedb/query.py +++ b/gracedb/query.py @@ -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])) diff --git a/gracedb/translator.py b/gracedb/translator.py index d790c643e9db8167bc342085a54173c468398697..163ac604741657604682f173ef19c0faaa697cf1 100644 --- a/gracedb/translator.py +++ b/gracedb/translator.py @@ -1,10 +1,12 @@ import os -from models import EventLog +from .models import EventLog +from .models import SingleInspiral import glue import glue.ligolw.utils +import glue.ligolw.lsctables from gracedb.serialize import populate_inspiral_tables, \ populate_omega_tables, \ @@ -120,6 +122,15 @@ def handle_uploaded_data(event, datafilename, event.save() + # Extract Single Inspiral Information + s_inspiral_tables = glue.ligolw.table.getTablesByName( + xmldoc, + glue.ligolw.lsctables.SnglInspiralTable.tableName) + + # Concatentate the tables' rows into a single table + table = sum(s_inspiral_tables, []) + SingleInspiral.create_events_from_ligolw_table(table, event) + elif event.analysisType == "HWINJ": log_comment = "Log File Created" xmldoc = glue.ligolw.utils.load_filename(datafilename) @@ -241,6 +252,15 @@ def handle_uploaded_data(event, datafilename, event.save() + # Extract Single Inspiral Information + s_inspiral_tables = glue.ligolw.table.getTablesByName( + xmldoc, + glue.ligolw.lsctables.SnglInspiralTable.tableName) + + # Concatentate the tables' rows into a single table + table = sum(s_inspiral_tables, []) + SingleInspiral.create_events_from_ligolw_table(table, event) + elif event.analysisType == 'OM': # Omega #here's how it works for bursts #xmldoc, log_data, temp_data_loc = populate_burst_tables("initial.data") diff --git a/gracedb/views.py b/gracedb/views.py index 259dfaa8251a7e6ac0978e9616a153a5d7e5f31d..0fd1fb119059d7683f77b7c7388a4456dca9f5f6 100644 --- a/gracedb/views.py +++ b/gracedb/views.py @@ -15,6 +15,7 @@ from django.contrib.auth.decorators import login_required from models import Event, Group, EventLog, Labelling, Label, Tag from models import CoincInspiralEvent from models import MultiBurstEvent +from models import SingleInspiral from forms import CreateEventForm, EventSearchForm, SimpleSearchForm from alert import issueAlert, issueAlertForLabel, issueAlertForUpdate from translator import handle_uploaded_data @@ -588,6 +589,7 @@ def view(request, graceid): for event in a.neighbors()] context['skyalert_authorized'] = skyalert_authorized(request) context['blessed_tags'] = settings.BLESSED_TAGS + context['single_inspiral_events'] = list(a.singleinspiral_set.all()) return render_to_response( [ 'gracedb/event_detail_{0}.html'.format(a.analysisType), 'gracedb/event_detail.html'], @@ -598,8 +600,7 @@ def cli_search(request): assert request.user form = SimpleSearchForm(request.POST) if form.is_valid(): - query = form.cleaned_data['query'] - objects = Event.objects.filter(query).distinct() + objects = form.cleaned_data['query'] if 'ligolw' in request.POST or 'ligolw' in request.GET: from glue.ligolw import utils @@ -715,9 +716,7 @@ def search(request, format=""): form = SimpleSearchForm(request.POST) rawquery = request.POST['query'] if form.is_valid(): - query = form.cleaned_data['query'] - - objects = Event.objects.filter(query).distinct() + objects = form.cleaned_data['query'] if format == "json": return HttpResponse("Not Implemented") @@ -1033,8 +1032,7 @@ def latest(request): context['rawquery'] = request.GET.get('query') or request.POST.get('query') or "" if form.is_valid(): - query = form.cleaned_data['query'] - objects = Event.objects.filter(query).distinct().order_by("-created")[:15] + objects = form.cleaned_data['query'] context['objects'] = map(limit, objects) context['error'] = False else: diff --git a/ligoauth/migrations/0003_utf8ify_user_tables.py b/ligoauth/migrations/0003_utf8ify_user_tables.py index de37a64585828948892f81936dd8a33f647aedb4..da45edd177b2298bf1cac346acbbf556d6ef034a 100644 --- a/ligoauth/migrations/0003_utf8ify_user_tables.py +++ b/ligoauth/migrations/0003_utf8ify_user_tables.py @@ -11,6 +11,7 @@ class Migration(DataMigration): db.execute("ALTER TABLE ligoauth_ligoldapuser CONVERT TO CHARACTER SET UTF8") db.execute("ALTER TABLE auth_user DEFAULT CHARACTER SET UTF8") db.execute("ALTER TABLE auth_user CONVERT TO CHARACTER SET UTF8") + db.execute("ALTER TABLE auth_user MODIFY username VARCHAR(100)") def backwards(self, orm): # We can't go back! diff --git a/templates/gracedb/event_detail_HM.html b/templates/gracedb/event_detail_HM.html index d1f0f693c88452194a4ec483d96f7d5782f5243b..f84eb8350bc4890642f85321a73cc1e599cab982 100644 --- a/templates/gracedb/event_detail_HM.html +++ b/templates/gracedb/event_detail_HM.html @@ -1,32 +1 @@ -{% extends "gracedb/event_detail.html" %} - -{% load scientific %} - -{# Analysis-specific attributes for an LM event#} -{% block analysis_specific %} -<h3>Analysis-Specific Attributes</h3> - -<table class="analysis_specific"> <tbody> - <tr> - <td> <table class="event"> <tbody> - <tr> <th> ifos </th> <td> {{object.ifos}} </td> </tr> - <tr> <th> end_time </th> <td> {{object.end_time}} </td> </tr> - <tr> <th> end_time_ns </th> <td> {{object.end_time_ns}} </td> </tr> - </tbody></table> - </td> - <td> <table class="event"> <tbody> - <tr> <th> mass </th> <td> {{object.mass|floatformat:"-4"}} </td> </tr> - <tr> <th> mchirp </th> <td> {{object.mchirp|floatformat:"-4"}} </td> </tr> - <tr> <th> minimum_duration </th> <td> {{object.minimum_duration|scientific}} </td> </tr> - </tbody></table> - </td> - <td> <table class="event"> <tbody> - <tr> <th> snr </th> <td> {{object.snr|floatformat:"-4"}} </td> </tr> - <tr> <th> false_alarm_rate </th> <td> {{object.false_alarm_rate|floatformat:"-4"}} </td> </tr> - <tr> <th> combined_far </th> <td> {{object.combined_far|scientific}} </td> </tr> - </tbody></table> - </td> - - </tr> -</tbody> </table> -{% endblock %} +{% extends "gracedb/event_detail_LM.html" %} diff --git a/templates/gracedb/event_detail_LM.html b/templates/gracedb/event_detail_LM.html index d1f0f693c88452194a4ec483d96f7d5782f5243b..a02d436d216fc96e49520d2482d6590e4a4a984d 100644 --- a/templates/gracedb/event_detail_LM.html +++ b/templates/gracedb/event_detail_LM.html @@ -29,4 +29,333 @@ </tr> </tbody> </table> + +{% if single_inspiral_events %} +<!-- Single Inspiral Data --> +<div id="single_inspiral_tables" + data-dojo-type="dijit/TitlePane" + data-dojo-props="title: 'Single Inspiral Tables', open: false"> +<table> + <tr> + <th>IFO</th> + {% for e in single_inspiral_events %} + <th>{{ e.ifo }}</th> + {% endfor %} + </tr> + <tr> + <th>Search</th> + {% for e in single_inspiral_events %} + <td>{{ e.search }}</td> + {% endfor %} + </tr> + <tr> + <th>Channel</th> + {% for e in single_inspiral_events %} + <td>{{ e.channel }}</td> + {% endfor %} + </tr> + <tr> + <th>End Time</th> + {% for e in single_inspiral_events %} + <td>{{ e.end_time_full }}</td> + {% endfor %} + </tr> + <tr> + <th>Impulse Time</th> + {% for e in single_inspiral_events %} + <td>{{ e.impulse_time_full }}</td> + {% endfor %} + </tr> + <tr> + <th>Template Duration</th> + {% for e in single_inspiral_events %} + <td>{{ e.template_duration }}</td> + {% endfor %} + </tr> + <tr> + <th>Event Duration</th> + {% for e in single_inspiral_events %} + <td>{{ e.event_duration }}</td> + {% endfor %} + </tr> + <tr> + <th>Amplitude</th> + {% for e in single_inspiral_events %} + <td>{{ e.amplitude }}</td> + {% endfor %} + </tr> + <tr> + <th>Effective Distance</th> + {% for e in single_inspiral_events %} + <td>{{ e.eff_distance }}</td> + {% endfor %} + </tr> + <tr> + <th>COA Phase</th> + {% for e in single_inspiral_events %} + <td>{{ e.coa_phase }}</td> + {% endfor %} + </tr> + <tr> + <th>Mass 1</th> + {% for e in single_inspiral_events %} + <td>{{ e.mass1 }}</td> + {% endfor %} + </tr> + <tr> + <th>Mass 2</th> + {% for e in single_inspiral_events %} + <td>{{ e.mass2 }}</td> + {% endfor %} + </tr> + <tr> + <th>MChirp</th> + {% for e in single_inspiral_events %} + <td>{{ e.mchirp }}</td> + {% endfor %} + </tr> + <tr> + <th>MTotal</th> + {% for e in single_inspiral_events %} + <td>{{ e.mtotal }}</td> + {% endfor %} + </tr> + <tr> + <th>η</th> + {% for e in single_inspiral_events %} + <td>{{ e.eta }}</td> + {% endfor %} + </tr> + <tr> + <th>κ</th> + {% for e in single_inspiral_events %} + <td>{{ e.kappa }}</td> + {% endfor %} + </tr> + <tr> + <th>χ</th> + {% for e in single_inspiral_events %} + <td>{{ e.chi }}</td> + {% endfor %} + </tr> + <tr> + <th>τ<sub>0</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.tau0 }}</td> + {% endfor %} + </tr> + <tr> + <th>τ<sub>2</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.tau2 }}</td> + {% endfor %} + </tr> + <tr> + <th>τ<sub>3</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.tau3 }}</td> + {% endfor %} + </tr> + <tr> + <th>τ<sub>4</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.tau4 }}</td> + {% endfor %} + </tr> + <tr> + <th>τ<sub>5</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.tau5 }}</td> + {% endfor %} + </tr> + <tr> + <th>τ<sub>Total</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.ttotal }}</td> + {% endfor %} + </tr> + <tr> + <th>Ψ<sub>0</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.psi0 }}</td> + {% endfor %} + </tr> + <tr> + <th>Ψ<sub>3</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.psi3 }}</td> + {% endfor %} + </tr> + <tr> + <th>α</th> + {% for e in single_inspiral_events %} + <td>{{ e.alpha }}</td> + {% endfor %} + </tr> + <tr> + <th>α<sub>1</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.alpha1 }}</td> + {% endfor %} + </tr> + <tr> + <th>α<sub>2</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.alpha2 }}</td> + {% endfor %} + </tr> + <tr> + <th>α<sub>3</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.alpha3 }}</td> + {% endfor %} + </tr> + <tr> + <th>α<sub>4</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.alpha4 }}</td> + {% endfor %} + </tr> + <tr> + <th>α<sub>5</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.alpha5 }}</td> + {% endfor %} + </tr> + <tr> + <th>α<sub>6</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.alpha6 }}</td> + {% endfor %} + </tr> + <tr> + <th>β</th> + {% for e in single_inspiral_events %} + <td>{{ e.beta }}</td> + {% endfor %} + </tr> + <tr> + <th>F Final</th> + {% for e in single_inspiral_events %} + <td>{{ e.f_final }}</td> + {% endfor %} + </tr> + <tr> + <th>SNR</th> + {% for e in single_inspiral_events %} + <td>{{ e.snr }}</td> + {% endfor %} + </tr> + <tr> + <th>χ<sup>2</sup></th> + {% for e in single_inspiral_events %} + <td>{{ e.chisq }}</td> + {% endfor %} + </tr> + <tr> + <th>χ<sup>2</sup> DOF</th> + {% for e in single_inspiral_events %} + <td>{{ e.chisq_dof }}</td> + {% endfor %} + </tr> + <tr> + <th>Bank χ<sup>2</sup></th> + {% for e in single_inspiral_events %} + <td>{{ e.bank_chisq }}</td> + {% endfor %} + </tr> + <tr> + <th>Bank χ<sup>2</sup> DOF</th> + {% for e in single_inspiral_events %} + <td>{{ e.bank_chisq_dof }}</td> + {% endfor %} + </tr> + <tr> + <th>Cont χ<sup>2</sup></th> + {% for e in single_inspiral_events %} + <td>{{ e.cont_chisq }}</td> + {% endfor %} + </tr> + <tr> + <th>Cont χ<sup>2</sup> DOF</th> + {% for e in single_inspiral_events %} + <td>{{ e.cont_chisq_dof }}</td> + {% endfor %} + </tr> + <tr> + <th>Σ<sup>2</sup></th> + {% for e in single_inspiral_events %} + <td>{{ e.sigmasq }}</td> + {% endfor %} + </tr> + <tr> + <th>RSQ Veto Duration</th> + {% for e in single_inspiral_events %} + <td>{{ e.rsqveto_duration }}</td> + {% endfor %} + </tr> + <tr> + <th>Γ<sub>0</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.gamma0 }}</td> + {% endfor %} + </tr> + <tr> + <th>Γ<sub>1</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.gamma1 }}</td> + {% endfor %} + </tr> + <tr> + <th>Γ<sub>2</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.gamma2 }}</td> + {% endfor %} + </tr> + <tr> + <th>Γ<sub>3</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.gamma3 }}</td> + {% endfor %} + </tr> + <tr> + <th>Γ<sub>4</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.gamma4 }}</td> + {% endfor %} + </tr> + <tr> + <th>Γ<sub>5</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.gamma5 }}</td> + {% endfor %} + </tr> + <tr> + <th>Γ<sub>6</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.gamma6 }}</td> + {% endfor %} + </tr> + <tr> + <th>Γ<sub>7</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.gamma7 }}</td> + {% endfor %} + </tr> + <tr> + <th>Γ<sub>8</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.gamma8 }}</td> + {% endfor %} + </tr> + <tr> + <th>Γ<sub>9</sub></th> + {% for e in single_inspiral_events %} + <td>{{ e.gamma9 }}</td> + {% endfor %} + </tr> +</table> +</div> +{% endif %} + {% endblock %} diff --git a/templates/gracedb/event_detail_MBTA.html b/templates/gracedb/event_detail_MBTA.html index 81ba7576fa013ec7644aa556f4ce01c85cb5dd3b..f84eb8350bc4890642f85321a73cc1e599cab982 100644 --- a/templates/gracedb/event_detail_MBTA.html +++ b/templates/gracedb/event_detail_MBTA.html @@ -1,9 +1 @@ -{% extends "gracedb/event_detail.html" %} - -{# Analysis-specific attributes for a LowMass event#} -{% block analysis_specific %} - <p/> -<h3>Event Log File</h3> -{{eventdesc}} - -{% endblock %} +{% extends "gracedb/event_detail_LM.html" %} diff --git a/templates/gracedb/query_help_frag.html b/templates/gracedb/query_help_frag.html index abe924f255f2dfb5413b4e4d0a5dac8af7636329..ae2b8b9a76b6177bb0f844346b63d2efa73edb98 100644 --- a/templates/gracedb/query_help_frag.html +++ b/templates/gracedb/query_help_frag.html @@ -1,5 +1,15 @@ <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" & far < 1e-7</code></li> + <li><code>singleinspiral.mchirp >= 1.6 & eff_distance in 40.5,55 </code></li> + <li><code>(si.channel = "DMT-STRAIN" | si.channel = "DMT-PAIN") & si.snr < 5</code></li> + <li><code>mb.snr in 1,3 & mb.central_freq > 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>