diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ec38163350bde9a23011f3d3a5beecf29872f290..cd4a460b845fa96c346ce545eaac736a7274082c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -111,7 +111,7 @@ before_script: - .cache/apt coverage: '/^TOTAL\s+.*\s+(\d+\.?\d*)%/' tags: - - cit + - executor-docker test:3.7: <<: *test @@ -127,7 +127,7 @@ branch_image: - runner_system_failure - stuck_or_timeout_failure tags: - - cit + - executor-docker latest_image: stage: latest @@ -143,4 +143,4 @@ latest_image: - runner_system_failure - stuck_or_timeout_failure tags: - - cit + - executor-docker diff --git a/config/settings/vm/base.py b/config/settings/vm/base.py index b4162cd1beeef4766173a48324077e975704f114..ba48e1a8db495113fcc8405e265d3a32ae731adc 100644 --- a/config/settings/vm/base.py +++ b/config/settings/vm/base.py @@ -78,7 +78,7 @@ CACHES = { }, } -CACHE_MIDDLEWARE_SECONDS = 30 +CACHE_MIDDLEWARE_SECONDS = 5 # DB "cool-down" factor for when a db conflict is detected. This # factor scales a random number of seconds between zero and one. diff --git a/gracedb/events/templatetags/mediaviews.py b/gracedb/events/templatetags/mediaviews.py index fa17997f7852ca62df57a5f2de1cc17b8ae9c153..61cd794a742694c1a0151302e1b4f4cdedabb7f7 100644 --- a/gracedb/events/templatetags/mediaviews.py +++ b/gracedb/events/templatetags/mediaviews.py @@ -279,6 +279,7 @@ def is_in_rrt_subcategory(event, rrt_subcategory): and not event.search.name == "EarlyWarning" ) | ( event.group.name == "Burst" + and event.search and event.pipeline.name =="CWB" and event.search.name == "BBH" ) @@ -290,7 +291,7 @@ def is_in_rrt_subcategory(event, rrt_subcategory): elif rrt_subcategory == "Burst": return ( event.group.name == "Burst" - and not( event.pipeline.name == "CWB" and + and not( event.search and event.pipeline.name == "CWB" and event.search.name == "BBH") ) diff --git a/gracedb/static/css/override-new.css b/gracedb/static/css/override-new.css index ffc2b405f870dcd2be73eb64ea6257da9df76aa6..17348dadcab782da908106cbc5dc0a6cfd577edd 100644 --- a/gracedb/static/css/override-new.css +++ b/gracedb/static/css/override-new.css @@ -1,5 +1,14 @@ /* CSS file for overriding other styles */ +/* CSS for bottom row image sizes */ + +.banner-img +{ + display: inline-block !important; + max-width: 12% !important; + max-height: 45px; +} + .btn-navbar { background-color: #29527A; diff --git a/gracedb/superevents/templatetags/public_alerts.py b/gracedb/superevents/templatetags/public_alerts.py index 297ad414a37c8eea510135de3354cf98e52417dd..9a35faccf0c21b2a4eac427f147628559b44ad18 100644 --- a/gracedb/superevents/templatetags/public_alerts.py +++ b/gracedb/superevents/templatetags/public_alerts.py @@ -24,7 +24,7 @@ def omegascan_links(superevent, run): return mark_safe(o3_deepomegascan_fmt.format(sid=superevent.superevent_id)) else: link_list = [] - for filename in set(superevent.log_set.filter(filename__contains='omegascan').values_list('filename', flat=True)): + for filename in superevent.log_set.filter(filename__contains='omegascan').order_by('filename').values_list('filename', flat=True): # get the absolute uri for the file: file_url = build_absolute_uri(reverse('api:default:superevents:superevent-file-detail', args=[superevent.superevent_id, filename])) diff --git a/gracedb/superevents/urls.py b/gracedb/superevents/urls.py index 6efb2d8e4fd8a6fbe8f788ff109e4e5a570c3eb6..17ab0d4340f94ec5384319c529113fcb6bc1e157 100644 --- a/gracedb/superevents/urls.py +++ b/gracedb/superevents/urls.py @@ -25,16 +25,16 @@ suburlpatterns = [ # Note to future generations: don't name a GW 'public' or the link breaks. public_urlpatterns = [ - # View of all public candidates - path('public/', views.SupereventPublic.as_view(), - name="public-alerts"), - - # redirect to the main public page. TODO: do something with the - # integer? like jump to a specific table on the page? maybe have - # a pull-down menu from the "Public Alerts" link that jumps to a - # specific observation run? - path('public/<slug:obsrun>/', views.public_alerts_redirect, - name="public-alerts-redirect"), + # The /superevents/public/ url route gets redirected to the + # latest observation run. + path('public/', views.public_alerts_redirect, + name="public-alerts-redirect"), + + # each run has its own page, but must be in the list of runs that's + # in settings/base.py. Otherwise, 404 (this gets defined in the view). + # the "obsrun" variable controls which events are shown. + path('public/<slug:obsrun>/', views.SupereventPublic.as_view(), + name="public-alerts"), ] legacy_urlpatterns = public_urlpatterns + [ diff --git a/gracedb/superevents/views.py b/gracedb/superevents/views.py index 077cfe3a915df4ac1da8522a2d8b50e0d6c66337..ce31355f147a239dab06eb61450e11b7ab271f85 100644 --- a/gracedb/superevents/views.py +++ b/gracedb/superevents/views.py @@ -3,6 +3,8 @@ import os from lal import gpstime from django.conf import settings +from django.db.models import Q +from django.http import Http404 from django.shortcuts import redirect from django.urls import reverse from django.utils.decorators import method_decorator @@ -150,9 +152,9 @@ class SupereventFileList(SupereventDetailView): # observation run. If for some reason a user puts in a random # slug, then it just goes to the top of the public page, so it's # pretty fail-safe. -def public_alerts_redirect(request, obsrun=None): - response = redirect('/superevents/public/#{run}'.format(run=obsrun)) - return response +def public_alerts_redirect(request): + return redirect('/superevents/public/{run}'.format( + run=settings.PUBLIC_PAGE_RUNS[0])) # The public alerts page: @method_decorator(public_if_public_access_allowed, name='dispatch') @@ -165,17 +167,46 @@ class SupereventPublic(DisplayFarMixin, ListView): gcnurl_template_o3 = 'https://gcn.gsfc.nasa.gov/other/GW{sd_id}.gcn3' gcnurl_template = 'https://gcn.nasa.gov/circulars?query={sd_id}' default_skymap_filename = 'bayestar.png' + burst_skymap_filename = '{pipeline}.png' pe_results_tagname = 'pe_results' - def get_queryset(self, **kwargs): - # Query only for public events - # NOTE: may want to fix this to only O3 events at some point + # Query only for public events for the given observation run. + # if it's not in the run list, return a 404. + self.obsrun = self.kwargs.get('obsrun') + if self.obsrun not in settings.PUBLIC_PAGE_RUNS: + raise Http404 + qs = Superevent.objects.filter(is_exposed=True, - category=Superevent.SUPEREVENT_CATEGORY_PRODUCTION) \ + category=Superevent.SUPEREVENT_CATEGORY_PRODUCTION, + t_0__range=RUN_MAP[self.obsrun]) \ .prefetch_related('voevent_set', 'log_set') return qs + # Define insignificance per run: + def significant_events(self, sevents): + # We're checking for ADVREQ|ADVOK|ADVNO + # https://git.ligo.org/computing/gracedb/server/-/issues/303#note_725082 + # So use Q filters for these: + significant_filter = Q() + if self.obsrun in ['ER15', 'O4']: + significant_filter = Q(labels__name='ADVREQ') | \ + Q(labels__name='ADVOK') | \ + Q(labels__name='ADVNO') + + return sevents.filter(significant_filter) + + + # and some documentation for the definition of significance. + # Note: this value is also used as a trigger to show the significance + # button and bullet. + def insignificant_docs(self, run): + if run in ['ER15', 'O4']: + return 'https://emfollow.docs.ligo.org/userguide/content.html#significance' + else: + return None + + def get_skymap_image(self, superevent, voevent=None): skymap_image = None public_logs = superevent.log_set.filter(tags__name='public') @@ -190,10 +221,22 @@ class SupereventPublic(DisplayFarMixin, ListView): skymap_image = voevent_skymap_image # If skymap_image is None, we didn't find an image based on the - # skymap file in the VOEvent, so try the default. - if (skymap_image is None and - public_logs.filter(filename=self.default_skymap_filename).exists()): - skymap_image = self.default_skymap_filename + # skymap file in the VOEvent, so try the default. The name of a default + # skymap will change if it's a burst event or not. + if skymap_image is None: + # Burst events: + if superevent.preferred_event.group.name == 'Burst': + # Set up a filter for mixed (pipeline) case. + # In O4, the convention was all lower case, but O3 was mixed case. argghhhh + skymap_log_list = public_logs.filter(filename__iexact=self.burst_skymap_filename.format( + pipeline=superevent.preferred_event.pipeline.name)) + + if skymap_log_list.exists(): + skymap_image = skymap_log_list.first().filename + + # Other events: + elif public_logs.filter(filename=self.default_skymap_filename).exists(): + skymap_image = self.default_skymap_filename if skymap_image: # Add version to image name to be safe @@ -213,97 +256,103 @@ class SupereventPublic(DisplayFarMixin, ListView): # For each superevent, get list of log messages and construct pastro # string table_data = {} - for run in settings.PUBLIC_PAGE_RUNS: - candidates = 0 - retractions = 0 - table_data[run] = {} - - # Define an empty queryset that we're going to export: - sevents = Superevent.objects.none() - - # Filter and loop over exposed superevents for the given run: - run_events = self.object_list.filter(t_0__range=RUN_MAP[run]) - for se in run_events: - - # External links to GCN notice and circular - se.noticeurl = self.noticeurl_template.format(s_id= + candidates = 0 + retractions = 0 + + # get insignificant events + sig_events = self.significant_events(self.object_list) + + # Filter and loop over exposed superevents for the given run: + for se in self.object_list: + + # External links to GCN notice and circular + se.noticeurl = self.noticeurl_template.format(s_id= + se.default_superevent_id) + if self.obsrun == "O3": + se.gcnurl = self.gcnurl_template_o3.format(sd_id= + se.default_superevent_id[1:]) + else: + se.gcnurl = self.gcnurl_template.format(sd_id= se.default_superevent_id) - if run == "O3": - se.gcnurl = self.gcnurl_template_o3.format(sd_id= - se.default_superevent_id[1:]) - else: - se.gcnurl = self.gcnurl_template.format(sd_id= - se.default_superevent_id) - - se.t0_iso = gpstime.gps_to_utc(se.t_0).isoformat(' ').split('.')[0] - se.t0_utc = se.t0_iso.split()[1] - - # Get display FARs for preferred_event - se.far_hz, se.far_hr, se.far_limit = self.get_display_far( - obj=se.preferred_event) - - # Get list of voevents, filtering out retractions - voe = se.voevent_set.exclude(voevent_type= - VOEvent.VOEVENT_TYPE_RETRACTION).order_by('-N').first() - - # Get skymap image (if a public one exists) - se.skymap_image = self.get_skymap_image(se, voe) - - # Was the candidate retracted? - se.retract = se.voevent_set.filter(voevent_type= - VOEvent.VOEVENT_TYPE_RETRACTION).exists() - candidates += int(not se.retract) - retractions += int(se.retract) - - # Get list of viewable logs for user which are tagged with - # 'analyst_comments' - viewable_logs = se.log_set.filter(tags__name='public').filter( - tags__name='analyst_comments') - # Compile comments from these logs - se.comments = ' ** '.join(list(viewable_logs.values_list( - 'comment', flat=True))) - if se.retract: - if se.comments: - se.comments = " ** " + se.comments - se.comments = "RETRACTED" + se.comments - - # Get list of PE results - pe_results = get_objects_for_user(self.request.user, - self.log_view_permission, - klass=se.log_set.filter(tags__name=self.pe_results_tagname)) - # Compile comments from these logs - se.pe = ' ** '.join(list(pe_results.values_list( - 'comment', flat=True))) - - # Get p_astro probabilities - if voe is not None: - pastro_values = [("BNS", voe.prob_bns), - ("NSBH", voe.prob_nsbh), - ("BBH", voe.prob_bbh), - ("Terrestrial", voe.prob_terrestrial), - ("MassGap", voe.prob_mass_gap), - ("HasMassGap", voe.prob_has_mass_gap)] - pastro_values.sort(reverse=True, key=lambda p_a: 0.0 if p_a[1] is None else p_a[1]) - sourcelist = [] - for key, value in pastro_values: - if value is None: - value = 0.0 - if value > 0.01: - prob = int(round(100*value)) - if prob == 100: prob = '>99' - sourcestr = "{0} ({1}%)".format(key, prob) - sourcelist.append(sourcestr) - se.sourcetypes = ', '.join(sourcelist) - - - # Now add it to the output dict, with the key being the run value: - table_data[run]['events'] = run_events - table_data[run]['candidates'] = candidates - table_data[run]['retractions'] = retractions + + se.t0_iso = gpstime.gps_to_utc(se.t_0).isoformat(' ').split('.')[0] + se.t0_utc = se.t0_iso.split()[1] + + # Get display FARs for preferred_event + se.far_hz, se.far_hr, se.far_limit = self.get_display_far( + obj=se.preferred_event) + + # Get list of voevents, filtering out retractions + voe = se.voevent_set.exclude(voevent_type= + VOEvent.VOEVENT_TYPE_RETRACTION).order_by('-N').first() + + # Get skymap image (if a public one exists) + se.skymap_image = self.get_skymap_image(se, voe) + + # Was the candidate retracted? + se.retract = se.voevent_set.filter(voevent_type= + VOEvent.VOEVENT_TYPE_RETRACTION).exists() + candidates += int(not se.retract) + retractions += int(se.retract) + + # is the candidate significant? + se.signif = se in sig_events + + # Get list of viewable logs for user which are tagged with + # 'analyst_comments' + viewable_logs = se.log_set.filter(tags__name='public').filter( + tags__name='analyst_comments') + # Compile comments from these logs + se.comments = ' ** '.join(list(viewable_logs.values_list( + 'comment', flat=True))) + if se.retract: + if se.comments: + se.comments = " ** " + se.comments + se.comments = "RETRACTED" + se.comments + + # Get list of PE results + pe_results = get_objects_for_user(self.request.user, + self.log_view_permission, + klass=se.log_set.filter(tags__name=self.pe_results_tagname)) + # Compile comments from these logs + se.pe = ' ** '.join(list(pe_results.values_list( + 'comment', flat=True))) + + # Get p_astro probabilities + if voe is not None: + pastro_values = [("BNS", voe.prob_bns), + ("NSBH", voe.prob_nsbh), + ("BBH", voe.prob_bbh), + ("Terrestrial", voe.prob_terrestrial), + ("MassGap", voe.prob_mass_gap),] + pastro_values.sort(reverse=True, key=lambda p_a: 0.0 if p_a[1] is None else p_a[1]) + sourcelist = [] + for key, value in pastro_values: + if value is None: + value = 0.0 + if value > 0.01: + prob = int(round(100*value)) + if prob == 100: prob = '>99' + sourcestr = "{0} ({1}%)".format(key, prob) + sourcelist.append(sourcestr) + se.sourcetypes = ', '.join(sourcelist) + + + # Now add it to the output dict, with the key being the run value: + table_data['events'] = self.object_list + + total_events = self.object_list.count() # export the dictionary for rendering: + context['signif_docs'] = self.insignificant_docs(self.obsrun) context['data'] = table_data - context['runs'] = settings.PUBLIC_PAGE_RUNS + context['run'] = self.obsrun + context['total_events'] = self.object_list.count() + context['total_sig'] = sig_events.count() + context['total_insig'] = context['total_events'] - context['total_sig'] + context['candidates'] = candidates + context['retractions'] = retractions + context['sig_cands'] = context['total_sig'] - retractions return context diff --git a/gracedb/templates/alerts/index.html b/gracedb/templates/alerts/index.html index 6336babd132ae697454f1ca40938a46379e36769..65107127eeea444f2e6949cf3a0b635ec1b76a54 100644 --- a/gracedb/templates/alerts/index.html +++ b/gracedb/templates/alerts/index.html @@ -6,7 +6,6 @@ {% load static %} {% block headcontents %} - <link rel="stylesheet" href="{% static "css/bootstrap_buttons.css" %}"></script> {{ block.super }} {% endblock %} diff --git a/gracedb/templates/base.html b/gracedb/templates/base.html index 648cb24ab5f86b340fc177dda876c3627900ad6d..5748412d0c566a3510e78a0a65fcd552a3b4403d 100644 --- a/gracedb/templates/base.html +++ b/gracedb/templates/base.html @@ -4,13 +4,12 @@ <head> {% load static %} - <!--Import bootstrap and custom colors--> - <link type="text/css" rel="stylesheet" href="{% static "bootstrap/dist/css/bootstrap.min.css" %}" media="screen,projection"/> + <!--Import Stylesheets--> + <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.2.1/dist/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous"> <link type="text/css" rel="stylesheet" href="{% static "css/themecolors.css" %}" /> <link type="text/css" rel="stylesheet" href="https://cdn.datatables.net/1.10.21/css/jquery.dataTables.min.css" /> - <!---<link type="text/css" rel="stylesheet" href="https://cdn.datatables.net/1.10.21/css/dataTables.bootstrap4.min.css" />--> - <link type="text/css" rel="stylesheet" href="{% static "/ekko-lightbox/dist/ekko-lightbox.css" %}" /> - <link rel="stylesheet" href="{% static "trumbowyg/dist/ui/trumbowyg.min.css" %}"> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ekko-lightbox/5.3.0/ekko-lightbox.css" integrity="sha512-Velp0ebMKjcd9RiCoaHhLXkR1sFoCCWXNp6w4zj1hfMifYB5441C+sKeBl/T/Ka6NjBiRfBBQRaQq65ekYz3UQ==" crossorigin="anonymous" referrerpolicy="no-referrer" /> + <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/Trumbowyg/2.21.0/ui/trumbowyg.min.css" integrity="sha512-XjpikIIW1P7jUS8ZWIznGs9KHujZQxhbnEsqMVQ5GBTTRmmJe32+ULipOxFePB8F8j9ahKmCjyJJ22VNEX60yg==" crossorigin="anonymous" referrerpolicy="no-referrer" /> <link type="text/css" rel="stylesheet" href="{% static "css/override-new.css" %}" /> <!--Let browser know website is optimized for mobile--> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> @@ -18,6 +17,7 @@ {% block headcontents %} + <!-- import scripts --> {# remove requests for favicon #} <link rel="icon" href="data:,"> <title>GraceDB | {% block title %}{% endblock %}</title> @@ -38,7 +38,7 @@ <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.form/4.3.0/jquery.form.js"></script> <script src="https://cdn.datatables.net/1.10.22/js/jquery.dataTables.min.js"></script> - <script src="{% static "trumbowyg/dist/trumbowyg.min.js" %}"></script> + <script src="https://cdnjs.cloudflare.com/ajax/libs/Trumbowyg/2.21.0/trumbowyg.min.js" integrity="sha512-l6MMck8/SpFCgbJnIEfVsWQ8MaNK/n2ppTiELW3I2BFY5pAm/WjkNHSt+2OD7+CZtygs+jr+dAgzNdjNuCU7kw==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script> @@ -49,7 +49,6 @@ <!-- add after bootstrap.min.js --> <script src="https://cdn.rawgit.com/afeld/bootstrap-toc/v1.0.1/dist/bootstrap-toc.min.js"></script> <!--ending the TOC stuff --> - <script src="{% static "ekko-lightbox/dist/ekko-lightbox.js" %}"></script> <!-- lightbox script ---> <script type="text/javascript"> $(document).on('click', '[data-toggle="lightbox"]', function(event) { @@ -79,6 +78,8 @@ <body data-spy="scroll" data-target="#toc" id="{% block pageid %}{% endblock %}"{% block bodyattrs %}{% endblock %}> +<div class="container-fluid overflow-auto" style="max-width: 1200px;"> + {% block nav %} {% include "navbar_frag.html" %} @@ -102,24 +103,25 @@ </div> - <div class="row my-5"> + <div class="row"> <div class="col align-self-center"> <center> - <img height="45" src="{% static "images/nsf_4-color_bitmap_logo.png" %}" /> - <img height="45" src="{% static "images/ligo-blue.gif" %}" /> - <img height="45" src="{% static "images/LSC_logo50.png" %}" /> - <img height="45" src="{% static "images/Virgo_logo50.png" %}" /> - <img height="45" src="{% static "images/kagra.png" %}" /> + <img class="banner-img" src="{% static "images/nsf_4-color_bitmap_logo.png" %}" /> + <img class="banner-img" src="{% static "images/ligo-blue.gif" %}" /> + <img class="banner-img" src="{% static "images/LSC_logo50.png" %}" /> + <img class="banner-img" src="{% static "images/Virgo_logo50.png" %}" /> + <img class="banner-img" src="{% static "images/kagra.png" %}" /> {% if user and user.username == "chad.hanna@LIGO.ORG" %} - <img height="45" src="{% static "images/PI_Logo-anim.gif" %}" /> + <img class="banner-img" src="{% static "images/PI_Logo-anim.gif" %}" /> {% endif %} {% if user and user.username == "kipp.cannon@LIGO.ORG" %} - <img height="45" src="{% static "images/utokyo2.gif" %}" /> + <img class="banner-img" src="{% static "images/utokyo2.gif" %}" /> {% endif %} </center> </div> </div> +</div> </body> </html> diff --git a/gracedb/templates/gracedb/index.html b/gracedb/templates/gracedb/index.html index c9500cc6a3900a4c292d0110ac7d6db5d349b791..ac098d576a8257d0957e62cdabca1eed41177a63 100644 --- a/gracedb/templates/gracedb/index.html +++ b/gracedb/templates/gracedb/index.html @@ -7,51 +7,6 @@ {% block content %} -<!-- stuff for the recent events plot --> - - -<style> -/* -body { - background-color: #f2f4f8; - font: 12px ; -} */ -.axis text { - font: 16px sans-serif; - /*font-weight: bold; */ -} - -.axis line { - fill: none; - stroke: #000; - shape-rendering: crispEdges; -} - -.axis path { - display: none; -} - -.legend { - font-size: 16px; - font-weight: bold; - text-anchor: start; - cursor: pointer; -} - -</style> - -<div class="row"> -<div class="col-1"></div> -<div class="col-10"> -{% if recent_events != "" %} -<h2>Recent Events</h2> -<div id="recent_events_plot"></div> -<br/> -{% endif %} - -<!-- I find myself needing some more space. --> -<!-- <br/> --> - <h5>GraceDB Overview</h5> <hr> <p > @@ -86,7 +41,6 @@ body { <br> <p ><small><b>Server code version: </b> <a href="https://git.ligo.org/computing/gracedb/server/-/tree/gracedb-{{server_version}}" class="text-monospace" >{{server_version}}</a></p></small> -</div> <!--XXX Infrastructure for human signoffs. Hopefully this will not be permanent. --> {% if signoff_authorized %} @@ -128,142 +82,5 @@ body { {% endif %} {% endif %} -<div class="col-1"></div> -</div> - -<!-- lots of script for the recent events plot --> -{% if recent_events %} -<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.5/d3.min.js"></script> -<script> - -var margin = {top: 0, right: 100, bottom: 70, left: 200}; -var width = 1000 - margin.left - margin.right; -var delta_y = 26; - -// Times look like "2015-10-15T13:08:31+00:00 -var parseDate = d3.time.format("%Y-%m-%dT%X+00:00").parse; - -var x = d3.time.scale() - .range([0, width]); - -var y = d3.scale.ordinal() -//var color = d3.scale.category10(); -var color = d3.scale.ordinal(); - -var xAxis = d3.svg.axis() - .scale(x) - .orient("bottom"); - -var svg = d3.select("#recent_events_plot").append("svg") - .attr("width", width + margin.left + margin.right) - - -var data_string = '{{ recent_events|safe }}'; -var data = JSON.parse(data_string); - -// Convert the text in the created column to dates, use to set the x domain. -data.forEach(function(d) { - d.created = parseDate(d.created); -}); -x.domain(d3.extent(data, function(d) { return d.created; })); - -// I suspect there is a better and less annoying way of doing all this. -// But I don't really know what it is. We specify the ordering of the -// pipelines and the color for each pipeline that may be present. -var PIPELINE_ORDER = [ 'gstlal', 'MBTAOnline', 'CWB', 'oLIB', 'Fermi', 'Swift', 'SNEWS', 'HardwareInjection']; - -// These are the first 8 colors of category 10 -var COLOR_HASH = {}; -COLOR_HASH['gstlal'] = '#1f77b4'; -COLOR_HASH['MBTAOnline'] = '#ff7f0e'; -COLOR_HASH['CWB'] = '#2ca02c'; -COLOR_HASH['oLIB'] = '#d62728'; -COLOR_HASH['Fermi'] = '#9467bd'; -COLOR_HASH['Swift'] = '#8c564b'; -COLOR_HASH['SNEWS'] = '#e377c2'; -COLOR_HASH['HardwareInjection'] = '#7f7f7f'; - -// Pull out the unique pipeline names present in the data -var data_pipelines = d3.map(data, function(d) { return d.pipeline; }).keys(); - -// Select pipelines from our ordering according to those present in the data. -var pipelines = []; -PIPELINE_ORDER.forEach(function(d) { - if (data_pipelines.indexOf(d) >= 0) { - pipelines.push(d); - } -}); - -// Create the list of colors -var pipeline_colors = []; -pipelines.forEach(function(d) { - pipeline_colors.push(COLOR_HASH[d]); -}); - -// Now set the domain and range of our color map. -color.domain(pipelines); -color.range(pipeline_colors); - -// Now that you know how many pipelines there are, you can determine the height. -height = pipelines.length * delta_y; - -var container = svg - .attr("height", height + margin.top + margin.bottom) - .append("g") - .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); - -// Calculate the height coordinates for the different pipelines. -var y_range_values = []; -pipelines.forEach(function(d, i) { - y_range_values.push(height - i*delta_y); -}); -y.domain(pipelines).range(y_range_values); - -// Create the yAxis here, since you need a valid scale. -var yAxis = d3.svg.axis() - .scale(y) - .orient("left"); - -var xAxis_yloc = height + delta_y/2; -container.append("g") - .attr("class", "x axis") - .attr("transform", "translate(0," + xAxis_yloc + ")") - .call(xAxis) - .selectAll("text") - .attr("y", 6) - .attr("x", -12) - .attr("dy", "0.5em") - .attr("transform", "rotate(315)") - .style("text-anchor", "end"); - -var yAxis_xloc = - delta_y/2; -container.append("g") - .attr("class", "y axis") - .attr("transform", "translate(" + yAxis_xloc + ",0)") - .call(yAxis) - -container.selectAll(".y.axis text") - .attr("fill", function(d) { return color(d); }) - -var line_length = 12; - -var get_url = function(d) { - return {% url 'home' %} + d.graceid; -} - -container.append("g").selectAll("line") - .data(data) -.enter().append("svg:a") - .attr("xlink:href", function(d) { return get_url(d); }) -.append("line") - .attr("x1", function(d) { return x(d.created); }) - .attr("x2", function(d) { return x(d.created); }) - .attr("y1", function(d) { return y(d.pipeline) - line_length/2; }) - .attr("y2", function(d) { return y(d.pipeline) + line_length/2; }) - .attr("stroke-width", 5) - .attr("stroke", function(d) { return color(d.pipeline); }) - -</script> -{% endif %} {% endblock %} diff --git a/gracedb/templates/gracedb/manage_pipelines.html b/gracedb/templates/gracedb/manage_pipelines.html index d4d9c0b25a899656adf3066cddc312ebf4a16b11..55602a820e5e6dab6523eae78b47918bcf5e43ee 100644 --- a/gracedb/templates/gracedb/manage_pipelines.html +++ b/gracedb/templates/gracedb/manage_pipelines.html @@ -7,7 +7,6 @@ {% load static %} {% block headcontents %} - <link rel="stylesheet" href="{% static "css/bootstrap_buttons.css" %}"> {{ block.super }} {% endblock %} diff --git a/gracedb/templates/navbar_frag.html b/gracedb/templates/navbar_frag.html index d803c72cb4fe927d49737d0df38755c83ba76d61..62569d3bc8997e02736110e311bc49c92ea65c57 100644 --- a/gracedb/templates/navbar_frag.html +++ b/gracedb/templates/navbar_frag.html @@ -19,14 +19,14 @@ <ul class="navbar-nav"> <li class="nav-item"> <div class="btn-group"> - <a class="btn btn-small btn-navbar shadow-none" href="{% url "superevents:public-alerts" %}" role="button">Public Alerts</a> + <a class="btn btn-small btn-navbar shadow-none" href="{% url "superevents:public-alerts-redirect" %}" role="button">Public Alerts</a> <button type="button" class="btn btn-small shadow-none btn-split dropdown-toggle dropdown-toggle-split" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <span class="sr-only">Toggle Dropdown</span> </button> <div class="dropdown-menu"> - <a class="dropdown-item" href="{% url "superevents:public-alerts" %}O4">O4</a> - <a class="dropdown-item" href="{% url "superevents:public-alerts" %}ER15">ER15</a> - <a class="dropdown-item" href="{% url "superevents:public-alerts" %}O3">O3</a> + <a class="dropdown-item" href="{% url "superevents:public-alerts" "O4" %}">O4</a> + <a class="dropdown-item" href="{% url "superevents:public-alerts" "ER15"%}">ER15</a> + <a class="dropdown-item" href="{% url "superevents:public-alerts" "O3" %}">O3</a> </div> </div> </li> diff --git a/gracedb/templates/search/query.html b/gracedb/templates/search/query.html index d2928b50323afbd02edd74566fe69fea1848a92f..d8c934adc5caf2dabbd596d3b02be3c85ee03087 100644 --- a/gracedb/templates/search/query.html +++ b/gracedb/templates/search/query.html @@ -96,5 +96,4 @@ $(document).ready(function() { } ); } ); </script> - {% endblock %} diff --git a/gracedb/templates/superevents/detail.html b/gracedb/templates/superevents/detail.html index e9fcc74db911c585b776de8ea63ece81519f4515..989157a4a1e9f0e1991f45ec526c026575c974b0 100644 --- a/gracedb/templates/superevents/detail.html +++ b/gracedb/templates/superevents/detail.html @@ -10,24 +10,9 @@ <link rel="stylesheet" href="{% static "css/labeltips.css" %}" /> <script src="{% static "dojo/dojo.js" %}" data-dojo-config="async: true"></script> -<!-- Styles for dgrid --> -<!-- <link rel="stylesheet" href="{% static "dgrid/css/dgrid.css" %}" /> --> -<!-- Styles for the editor components --> -<link rel="stylesheet" href="{% static "dojox/editor/plugins/resources/css/PageBreak.css" %}" /> -<link rel="stylesheet" href="{% static "dojox/editor/plugins/resources/css/ShowBlockNodes.css" %}" /> -<link rel="stylesheet" href="{% static "dojox/editor/plugins/resources/css/Preview.css" %}" /> -<link rel="stylesheet" href="{% static "dojox/editor/plugins/resources/css/Save.css" %}" /> -<link rel="stylesheet" href="{% static "dojox/editor/plugins/resources/css/Breadcrumb.css" %}" /> -<link rel="stylesheet" href="{% static "dojox/editor/plugins/resources/css/FindReplace.css" %}" /> -<link rel="stylesheet" href="{% static "dojox/editor/plugins/resources/css/PasteFromWord.css" %}" /> -<link rel="stylesheet" href="{% static "dojox/editor/plugins/resources/css/InsertAnchor.css" %}" /> -<link rel="stylesheet" href="{% static "dojox/editor/plugins/resources/css/CollapsibleToolbar.css" %}" /> -<link rel="stylesheet" href="{% static "dojox/editor/plugins/resources/css/Blockquote.css" %}" /> -<link rel="stylesheet" href="{% static "dojox/editor/plugins/resources/css/Smiley.css" %}" /> -<!-- Styles for the lightboxes. --> -<link rel="stylesheet" href="{% static "dojox/image/resources/LightboxNano.css" %}" /> -<!-- Local style declarations --> -<link rel="stylesheet" href="{% static "dijit/themes/tundra/tundra.css" %}" /> +<!-- +<script src="https://cdnjs.cloudflare.com/ajax/libs/dojo/1.10.4/dojo.js" integrity="sha512-WycJzB2nldja5RSTIdAacWBZlR8vpmfMqmmj+i6bQ7JncC5u3deuJBlEUPq5uGYkO8MzP28xkLHiZlkeYVtKlw==" crossorigin="anonymous" referrerpolicy="no-referrer" data-dojo-config="async: true"></script> +--> <!-- the main JavaScript block is pulled in with an include --> <script> diff --git a/gracedb/templates/superevents/public_alerts.html b/gracedb/templates/superevents/public_alerts.html index 53648a67c5c0be8c0e937033f15a40d72459b004..39b7f71fde5f0136f70db8a203a112e25f934952 100644 --- a/gracedb/templates/superevents/public_alerts.html +++ b/gracedb/templates/superevents/public_alerts.html @@ -18,113 +18,146 @@ {% block pageid %}public{% endblock %} {% block jscript %} -<link rel="stylesheet" type="text/css" href="{% static "tablesaw/dist/tablesaw.css" %}" /> -<script language="javascript" type="text/javascript" src="{% static "tablesaw/dist/tablesaw.js" %}"></script> -<script language="javascript" type="text/javascript" src="{% static "tablesaw/dist/tablesaw-init.js" %}"></script> +<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/tablesaw/3.1.2/tablesaw.css" integrity="sha512-Gh62F+VzywHWpYtkkUqg2QmF2B67AeDmZv6uXznRUxXNUCFrRFlZRI2gKo2Bf3cgG5dAxAgxRJah3GgpJ0Z1Mw==" crossorigin="anonymous" referrerpolicy="no-referrer" /> +<script src="https://cdnjs.cloudflare.com/ajax/libs/tablesaw/3.1.2/tablesaw.js" integrity="sha512-pJ/SPF4B6ZzEZp4b86/xpcZdcVkqtwyd/orBJQwOasT9S0qyIHcis2wRS/WGV4T4J8YrwqA/rPm+jDwQKkQs4Q==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> +<script src="https://cdnjs.cloudflare.com/ajax/libs/tablesaw/3.1.2/tablesaw-init.js" integrity="sha512-ct5fXUTmBz4voTyyxShWMjCpNKnAkw3zWIKETeQi8NBa9lPG6/Gf4b4+XvjB1kgaXzwM3e5R2EXF8J7+WsYu/w==" crossorigin="anonymous" referrerpolicy="no-referrer"></script> {% endblock %} {% block content %} <div class="row"> -<div class="col mx-1"> -<h4 style="font-weight: lighter;">LIGO/Virgo/KAGRA Public Alerts</h4> -<ul style="list-style-type: square; font-weight: lighter;"> - <li>Retractions are marked in <span stlye="color: red;">red</span>.</li> - <li>More details about public alerts are provided in the <a href="https://emfollow.docs.ligo.org/userguide/">LIGO/Virgo/KAGRA Alerts User Guide</a>.</li> -</ul> -<h5 style="font-weight: lighter;">Jump to:</h4> -<ul style="list-style-type: square; font-weight: lighter;"> -{% for run in runs %} - <li> <a href="#{{ run }}">{{ run }} Public Alerts </a></li> -{% endfor %} -</ul> - -{% for run, tabledata in data.items %} - - {% if tabledata.retractions != 1 %} - {% firstof "s" as plural %} - {% endif %} - <hr /> - <a id="{{ run }}"><h4 style='font-weight: lighter;'>{{ run }} Detection Candidates: <b>{{ tabledata.candidates }}</b> ({{ tabledata.retractions }} Retraction{{ plural }})</h4></a> - - {% if tabledata.candidates > 0 %} - <div class="tablesaw-overflow"> - <table class="tablesaw table-hover table-condensed table-resp-gracedb shadow p-3 mb-5 rounded" data-tablesaw-sortable data-tablesaw-sortable-switch data-tablesaw-mode="columntoggle" data-tablesaw-minimap> - <thead class="table-detail-th"><tr> - <th scope="col" data-tablesaw-sortable-col data-tablesaw-priority="persist">Event ID</th> - <th scope="col" data-tablesaw-sortable-col data-tablesaw-priority="1">Possible Source (Probability)</th> - <th scope="col" data-tablesaw-sortable-col data-tablesaw-sortable-string data-tablesaw-priority="2">UTC</th> - <th scope="col" data-tablesaw-col data-tablesaw-priority="3">GCN</th> - <th scope="col" data-tablesaw-col data-tablesaw-priority="4">Location</th> - <th scope="col" data-tablesaw-sortable-col data-tablesaw-priority="5">FAR</th> - <th scope="col" data-tablesaw-col data-tablesaw-priority="6">Comments</th> - <th scope="col" data-tablesaw-sortable-col data-tablesaw-priority="0">GPS</th> - - {% if user_is_internal %} - <th scope="col" data-tablesaw-col data-tablesaw-priority="6">Ω Scan</th> - {% endif %} - - </tr> - </thead> - <tbody> - - - {% for event in tabledata.events %} - <tr{% if event.retract %} style="background-color: #EDD;" {% endif %}> - - <td style="min-width: 100px;"> - <a href="{% url "superevents:view" event.superevent_id %}">{{ event.default_superevent_id }}</a> - </td> - <td style="min-width: 100px;">{{ event.sourcetypes }}</td> - <td style="min-width: 140px;"> - <span style="font-size: 0px;">{{ event.t_0|floatformat:2 }}</span>{{ event.t_0_date }}<br/> - {{ event.t0_utc }} UTC - </td> - <td style="min-width: 110px;"> - {% if run == "O3" %} - <a href={{ event.gcnurl }}>GCN Circulars</a><br/> - {% else %} - <a href={{ event.gcnurl }}>GCN Circular Query</a><br/> + <div class="col mx-1"> + <h4 style="font-weight: lighter;">LIGO/Virgo/KAGRA Public Alerts</h4> + <ul style="list-style-type: square; font-weight: lighter;"> + <li>More details about public alerts are provided in the <a href="https://emfollow.docs.ligo.org/userguide/">LIGO/Virgo/KAGRA Alerts User Guide</a>.</li> + <li>Retractions are marked in <span style="color:red;">red</span>. Retraction means that the candidate was manually vetted and is no longer considered a candidate of interest.</li> + {% if signif_docs %} + <li>Less-significant events are marked in <span style="background-color: #E5E4E2">grey</span>, and are not manually vetted. Consult the <a href=" {{ signif_docs }}" target="_blank">LVK Alerts User Guide</a> for more information on significance in {{ run }}.</li> {% endif %} + </ul> + <hr> - <a href={{ event.noticeurl }}>Notices</a> | <a href="{% url "legacy_apiweb:default:superevents:superevent-voevent-list" event.default_superevent_id %}">VOE</a> - </td> - <td> - {% if event.skymap_image %} - <a href="{{ event.skymap_image }}"> - <img src="{{ event.skymap_image }}" width="120px" /> - </a> - {% else %} - No public skymap image found. - {% endif %} - </td> - <td style="min-width: 120px;"> - <!-- Hidden float FAR value for table sorting --> - <span style="font-size: 0px;">{{ event.far_hz|floatformat:20 }}</span>{{ event.far_hr }} - </td> - <td style="min-width: 80px;">{{ event.comments|safe }} </td> - <td>{{ event.t_0|floatformat:2 }} </td> - - {% if user_is_internal %} - <!-- Add Omega scans and PE results for LVC users --> - <td style="min-width: 70px;"> - {{ event | omegascan_links:run }} - </td> + {% if signif_docs %} + <p> + <h5 style='font-weight: lighter;'>{{ run }} Significant Detection Candidates: <b>{{ sig_cands }}</b> ({{ total_sig }} Total - {{ retractions }} Retracted)</h5> + </p> + <p> + <h5 style='font-weight: lighter;'>{{ run }} Low Significance Detection Candidates: <b>{{ total_insig }}</b> (Total)</h5> + </p> + {% else %} + <p> + <h5 style='font-weight: lighter;'>{{ run }} Detection Candidates: <b>{{ candidates }}</b> ({{total_events}} Total - {{ retractions }} Retracted)</h5> + </p> {% endif %} - - </tr> - {% endfor %} - </tbody></table> - </div> - - {% else %} + + <br> + {% if signif_docs %} + <script> + $(document).ready(function(){ + $('#hideInsigButton').on('click', function () { + var text=$('#hideInsigButton').text(); + if(text === 'Show Significant Events Only'){ + $(this).html('Show All Public Events'); + } else{ + $(this).html('Show Significant Events Only'); + } + }); + }); + </script> + + <a class="btn btn-primary" role="button" data-toggle="collapse" href="#insignificant" aria-expanded="true" aria-controls="insignificant" id="hideInsigButton">Show Significant Events Only</a> + <br> + <br> + {% endif %} + + {% if candidates > 0 or retractions > 0 %} + <div class="tablesaw-overflow"> + <table class="tablesaw table-condensed table-resp-gracedb shadow p-3 mb-5 rounded" data-tablesaw-sortable data-tablesaw-sortable-switch data-tablesaw-mode="columntoggle" data-tablesaw-minimap> + <thead class="table-detail-th"><tr> + <th scope="col" data-tablesaw-sortable-col data-tablesaw-priority="persist">Event ID</th> + <th scope="col" data-tablesaw-sortable-col data-tablesaw-priority="1">Possible Source (Probability)</th> + {% if signif_docs %} + <th scope="col" data-tablesaw-sortable-col data-tablesaw-priority="1">Significant</th> + {% endif %} + <th scope="col" data-tablesaw-sortable-col data-tablesaw-sortable-string data-tablesaw-priority="2">UTC</th> + <th scope="col" data-tablesaw-col data-tablesaw-priority="3">GCN</th> + <th scope="col" data-tablesaw-col data-tablesaw-priority="4">Location</th> + <th scope="col" data-tablesaw-sortable-col data-tablesaw-priority="5">FAR</th> + <th scope="col" data-tablesaw-col data-tablesaw-priority="6">Comments</th> + <th scope="col" data-tablesaw-sortable-col data-tablesaw-priority="0">GPS</th> + + {% if user_is_internal %} + <th scope="col" data-tablesaw-col data-tablesaw-priority="6">Ω Scan</th> + {% endif %} + + </tr> + </thead> + <tbody> + + + {% for event in data.events %} + + {% if event.retract %} + <tr style="background-color: #EDD;" {% if not event.signif %} class="collapse show" id="insignificant" {% endif %}> + {% elif not event.signif %} + <tr style="background-color: #E5E4E2" class="collapse show" id="insignificant"> + {% endif %} + + <td style="min-width: 100px;"> + <a href="{% url "superevents:view" event.superevent_id %}">{{ event.default_superevent_id }}</a> + </td> + <td style="min-width: 100px;">{{ event.sourcetypes }}</td> + {% if signif_docs %} + <td style="min-width: 100px;">{% if event.signif %} Yes {% else %} No {% endif %}</td> + {% endif %} + <td style="min-width: 140px;"> + <span style="font-size: 0px;">{{ event.t_0|floatformat:2 }}</span>{{ event.t_0_date }}<br/> + {{ event.t0_utc }} UTC + </td> + <td style="min-width: 110px;"> + {% if run == "O3" %} + <a href={{ event.gcnurl }}>GCN Circulars</a><br/> + {% else %} + <a href={{ event.gcnurl }}>GCN Circular Query</a><br/> + {% endif %} + + <a href={{ event.noticeurl }}>Notices</a> | <a href="{% url "legacy_apiweb:default:superevents:superevent-voevent-list" event.default_superevent_id %}">VOE</a> + </td> + <td> + {% if event.skymap_image %} + <a href="{{ event.skymap_image }}"> + <img src="{{ event.skymap_image }}" width="120px" /> + </a> + {% else %} + No public skymap image found. + {% endif %} + </td> + <td style="min-width: 120px;"> + <!-- Hidden float FAR value for table sorting --> + <span style="font-size: 0px;">{{ event.far_hz|floatformat:20 }}</span>{{ event.far_hr }} + </td> + <td style="min-width: 80px;">{{ event.comments|safe }} </td> + <td>{{ event.t_0|floatformat:2 }} </td> + + {% if user_is_internal %} + <!-- Add Omega scans and PE results for LVC users --> + <td style="min-width: 70px;"> + {{ event | omegascan_links:run }} + </td> + {% endif %} + + </tr> + {% endfor %} + </tbody></table> + </div> + + {% else %} <br /> <h5 style='margin-left: 40px; font-weight: lighter;'>No {{ run }} candidates at present.</h5> - {% endif %} - <br/> + {% endif %} + <br/> -{% endfor %} -</div> + </div> </div> </div>