From 63c92f8ddbebcc1711365fda27e8b4a92c4cfa4b Mon Sep 17 00:00:00 2001
From: "J.-S. Caux" <J.S.Caux@uva.nl>
Date: Sat, 27 Jan 2018 08:39:37 +0100
Subject: [PATCH] Add tiered-level stats

---
 journals/models.py                    |  49 ++++++-
 stats/templates/stats/statistics.html | 182 ++++++++++++++++----------
 stats/templatetags/stats_extras.py    |  67 +++-------
 3 files changed, 176 insertions(+), 122 deletions(-)

diff --git a/journals/models.py b/journals/models.py
index 0d30f3a42..0f833006d 100644
--- a/journals/models.py
+++ b/journals/models.py
@@ -51,11 +51,26 @@ class Journal(models.Model):
     def get_abbreviation_citation(self):
         return journal_name_abbrev_citation(self.name)
 
-    def citation_rate(self):
+    def nr_publications(self, Tier=None):
+        pubs = Publication.objects.filter(in_issue__in_volume__in_journal=self)
+        if Tier:
+            pubs.filter(accepted_submission__eicrecommendations__recommendation=Tier)
+        return pubs.count()
+
+    def avg_processing_duration(self):
+        duration = Publication.objects.filter(
+            in_issue__in_volume__in_journal=self).aggregate(
+                avg=Avg(F('publication_date') - F('submission_date')))['avg']
+        if not duration: return 0
+        return duration.days + duration.seconds/86400
+
+    def citation_rate(self, Tier=None):
         """
         Returns the citation rate in units of nr citations per article per year.
         """
         pubs = Publication.objects.filter(in_issue__in_volume__in_journal=self)
+        if Tier:
+            pubs.filter(accepted_submission__eicrecommendations__recommendation=Tier)
         ncites = 0
         deltat = 1 # to avoid division by zero
         for pub in pubs:
@@ -83,11 +98,26 @@ class Volume(models.Model):
     def doi_string(self):
         return '10.21468/' + self.doi_label
 
+    def nr_publications(self, Tier=None):
+        pubs = Publication.objects.filter(in_issue__in_volume=self)
+        if Tier:
+            pubs.filter(accepted_submission__eicrecommendations__recommendation=Tier)
+        return pubs.count()
+
+    def avg_processing_duration(self):
+        duration = Publication.objects.filter(
+            in_issue__in_volume=self).aggregate(
+                avg=Avg(F('publication_date') - F('submission_date')))['avg']
+        if not duration: return 0
+        return duration.days + duration.seconds/86400
+
     def citation_rate(self):
         """
         Returns the citation rate in units of nr citations per article per year.
         """
         pubs = Publication.objects.filter(in_issue__in_volume=self)
+        if Tier:
+            pubs.filter(accepted_submission__eicrecommendations__recommendation=Tier)
         ncites = 0
         deltat = 1 # to avoid division by zero
         for pub in pubs:
@@ -147,11 +177,26 @@ class Issue(models.Model):
         return self.start_date <= timezone.now().date() and\
                self.until_date >= timezone.now().date()
 
-    def citation_rate(self):
+    def nr_publications(self, Tier=None):
+        pubs = Publication.objects.filter(in_issue=self)
+        if Tier:
+            pubs.filter(accepted_submission__eicrecommendations__recommendation=Tier)
+        return pubs.count()
+
+    def avg_processing_duration(self):
+        duration = Publication.objects.filter(
+            in_issue=self).aggregate(
+                avg=Avg(F('publication_date') - F('submission_date')))['avg']
+        if not duration: return 0
+        return duration.days + duration.seconds/86400
+
+    def citation_rate(self, Tier=None):
         """
         Returns the citation rate in units of nr citations per article per year.
         """
         pubs = Publication.objects.filter(in_issue=self)
+        if Tier:
+            pubs.filter(accepted_submission__eicrecommendations__recommendation=Tier)
         ncites = 0
         deltat = 1 # to avoid division by zero
         for pub in pubs:
diff --git a/stats/templates/stats/statistics.html b/stats/templates/stats/statistics.html
index 61fa1a21d..3f02a3981 100644
--- a/stats/templates/stats/statistics.html
+++ b/stats/templates/stats/statistics.html
@@ -41,78 +41,122 @@
 </ul>
 
 {% if journal %}
-    <h2>Results:</h2>
-    <table class="table">
-      <tr>
-    	<th>DOI label</th>
-    	{% if year %}
-    	<th>Year</th>
-    	<th>Nr submissions<br/>(distinct)</th>
-	<th>Nr submissions<br/>(including resubmissions)</th>
-	<th>Nr assignment failed</th>
-	<th>Nr accepted/<br/>published</th>
-	<th>Nr rejected</th>
-	<th>Nr withdrawn</th>
-    	{% else %}
-    	<th>Nr publications</th>
-    	<th>Duration average</th>
-	<th>Citation rate (per paper per year)</ht>
-	{% endif %}
-      </tr>
-      <tr>
-    	{% if issue %}
-    	<td>{{ issue.doi_label }}</td>
-    	<td>{{ issue|issue_nr_publications }}</td>
-    	<td>{{ issue|issue_avg_processing_duration|floatformat:2 }} days</td>
-	<td>{{ issue|issue_citation_rate|floatformat:2 }}</td>
-    	{% elif volume %}
-    	<td>{{ volume.doi_label }}</td>
-    	<td>{{ volume|volume_nr_publications }}</td>
-    	<td>{{ volume|volume_avg_processing_duration|floatformat:2 }} days</td>
-	<td>{{ volume|volume_citation_rate|floatformat:2 }}</td>
-    	{% else %}
-    	<td>{{ journal.doi_label }}</td>
-    	{% if year %}
-    	<td>{{ year }}</td>
-    	<td>{{ submissions|submissions_count_distinct }}</td>
-    	<td>{{ submissions|length }}</td>
-	<td>{{ submissions.assignment_failed.count }}</td>
-	<td>{{ submissions.accepted.count|add:submissions.published.count }}</td>
-	<td>{{ submissions.rejected.count }}</td>
-	<td>{{ submissions.withdrawn.count }}</td>
-    	{% else %}
-    	<td>{{ journal|journal_nr_publications }}</td>
-    	<td>{{ journal|journal_avg_processing_duration|floatformat:2 }} days</td>
-	<td>{{ journal|journal_citation_rate|floatformat:2 }}</td>
-	{% endif %}
-    	{% endif %}
-      </tr>
-    </table>
+<h2>Results:</h2>
+<table class="table">
+  <tr>
+    <th>DOI label</th>
+    {% if year %}
+    <th>Year</th>
+    <th>Nr submissions<br/>(distinct)</th>
+    <th>Nr submissions<br/>(including resubmissions)</th>
+    <th>Nr assignment failed</th>
+    <th>Nr accepted/<br/>published</th>
+    <th>Nr rejected</th>
+    <th>Nr withdrawn</th>
+    {% else %}
+    <th>Nr publications</th>
+    <th>Duration average</th>
+    <th>Citation rate (per paper per year)</th>
     {% endif %}
-
+  </tr>
+  <tr>
+    {% if issue %}
+    <td>{{ issue.doi_label }}</td>
+    <td>{% nr_publications issue %}</td>
+    <td>{% avg_processing_duration issue as avg %}{{ avg|floatformat:2 }} days</td>
+    <td>{% citation_rate issue as cr %}{{ cr|floatformat:2 %}</td>
+    {% elif volume %}
+    <td>{{ volume.doi_label }}</td>
+    <td>{% nr_publications volume %}</td>
+    <td>{% avg_processing_duration volume as avg %}{{ avg|floatformat:2 }} days</td>
+    <td>{% citation_rate volume as cr %}{{ cr|floatformat:2 }}</td>
+    {% else %}
+    <td>{{ journal.doi_label }}</td>
     {% if year %}
-    <h2>Refereeing stats for {{ year }}</h2>
-    <table class="table">
-      <tr>
-	<th>Nr refereeing<br/>invitations</th>
-	<th>Nr accepted</th>
-	<th>Nr declined</th>
-	<th>Nr pending</th>
-	<th>Nr reports<br/>obtained</th>
-	<th>Nr obtained<br/>(invited)</th>
-	<th>Nr obtained<br/>(contributed)</th>
-      </tr>
-      <tr>
-	<td>{{ nr_ref_inv }}</td>
-	<td>{{ nr_acc }} ({% widthratio nr_acc nr_ref_inv 100 %}&#37;)</td>
-	<td>{{ nr_dec }} ({% widthratio nr_dec nr_ref_inv 100 %}&#37;)</td>
-	<td>{{ nr_pen }} ({% widthratio nr_pen nr_ref_inv 100 %}&#37;)</td>
-	<td>{{ nr_rep_obt }}</td>
-	<td>{{ nr_rep_obt_inv }} ({% widthratio nr_rep_obt_inv nr_rep_obt 100 %}&#37;)</td>
-	<td>{{ nr_rep_obt_con }} ({% widthratio nr_rep_obt_con nr_rep_obt 100 %}&#37;)</td>
-      </tr>
-    </table>
+    <td>{{ year }}</td>
+    <td>{{ submissions|submissions_count_distinct }}</td>
+    <td>{{ submissions|length }}</td>
+    <td>{{ submissions.assignment_failed.count }}</td>
+    <td>{{ submissions.accepted.count|add:submissions.published.count }}</td>
+    <td>{{ submissions.rejected.count }}</td>
+    <td>{{ submissions.withdrawn.count }}</td>
+    {% else %}
+    <td>{% nr_publications journal %}</td>
+    <td>{% avg_processing_duration journal as avg %}{{ avg|floatformat:2 }} days</td>
+    <td>{% citation_rate journal as cr %}{{ cr|floatformat:2 }}</td>
+    {% endif %}
     {% endif %}
+  </tr>
+</table>
+
+<table class="table">
+  <tr>
+    <th>DOI label</th>
+    <th colspan="3">Nr per Tier</th>
+    <th colspan="3">Citation rate (per paper per year)</th>
+  </tr>
+  <tr>
+    <th></th>
+    <th>I</th>
+    <th>II</th>
+    <th>IIII</th>
+    <th>I</th>
+    <th>II</th>
+    <th>IIII</th>
+  </tr>
+  <tr>
+    {% if issue %}
+    <td>{% issue.doi_label }}</td>
+    <td>{% nr_publications issue Tier=1 %}</td>
+    <td>{% nr_publications issue Tier=2 %}</td>
+    <td>{% nr_publications issue Tier=3 %}</td>
+    <td>{% citation_rate issue Tier=1 as cr %}{{ cr|floatformat:2 }}</td>
+    <td>{% citation_rate issue Tier=2 as cr %}{{ cr|floatformat:2 }}</td>
+    <td>{% citation_rate issue Tier=3 as cr %}{{ cr|floatformat:2 }}</td>
+    {% elif volume %}
+    <td>{{ volume.doi_label }}</td>
+    <td>{% nr_publications volume Tier=1 %}</td>
+    <td>{% nr_publications volume Tier=2 %}</td>
+    <td>{% nr_publications volume Tier=3 %}</td>
+    <td>{% citation_rate volume Tier=1 as cr %}{{ cr|floatformat:2 }}</td>
+    <td>{% citation_rate volume Tier=2 as cr %}{{ cr|floatformat:2 }}</td>
+    <td>{% citation_rate volume Tier=3 as cr %}{{ cr|floatformat:2 }}</td>
+    {% else %}
+    <td>{{ journal.doi_label }}</td>
+    <td>{% nr_publications journal Tier=1 %}</td>
+    <td>{% nr_publications journal Tier=2 %}</td>
+    <td>{% nr_publications journal Tier=3 %}</td>
+    <td>{% citation_rate journal Tier=1 as cr %}{{ cr|floatformat:2 }}</td>
+    <td>{% citation_rate journal Tier=2 as cr %}{{ cr|floatformat:2 }}</td>
+    <td>{% citation_rate journal Tier=3 as cr %}{{ cr|floatformat:2 }}</td>
+    {% endif %}
+  </tr>
+</table>
+{% endif %}
+
+{% if year %}
+<h2>Refereeing stats for {{ year }}</h2>
+<table class="table">
+  <tr>
+    <th>Nr refereeing<br/>invitations</th>
+    <th>Nr accepted</th>
+    <th>Nr declined</th>
+    <th>Nr pending</th>
+    <th>Nr reports<br/>obtained</th>
+    <th>Nr obtained<br/>(invited)</th>
+    <th>Nr obtained<br/>(contributed)</th>
+  </tr>
+  <tr>
+    <td>{{ nr_ref_inv }}</td>
+    <td>{{ nr_acc }} ({% widthratio nr_acc nr_ref_inv 100 %}&#37;)</td>
+    <td>{{ nr_dec }} ({% widthratio nr_dec nr_ref_inv 100 %}&#37;)</td>
+    <td>{{ nr_pen }} ({% widthratio nr_pen nr_ref_inv 100 %}&#37;)</td>
+    <td>{{ nr_rep_obt }}</td>
+    <td>{{ nr_rep_obt_inv }} ({% widthratio nr_rep_obt_inv nr_rep_obt 100 %}&#37;)</td>
+    <td>{{ nr_rep_obt_con }} ({% widthratio nr_rep_obt_con nr_rep_obt 100 %}&#37;)</td>
+  </tr>
+</table>
+{% endif %}
 
 
 {% endblock content %}
diff --git a/stats/templatetags/stats_extras.py b/stats/templatetags/stats_extras.py
index d63622554..fb0b8cdf2 100644
--- a/stats/templatetags/stats_extras.py
+++ b/stats/templatetags/stats_extras.py
@@ -9,6 +9,22 @@ register = template.Library()
 
 
 
+@register.simple_tag
+def avg_processing_duration(obj, *args, **kwargs):
+    method = getattr(obj, avg_processing_duration)
+    return method(*args, **kwargs)
+
+@register.simple_tag
+def nr_publications(obj, *args, **kwargs):
+    method = getattr(obj, nr_publications)
+    return method(*args, **kwargs)
+
+@register.simple_tag
+def citation_rate(obj, *args, **kwargs):
+    method = getattr(obj, citation_rate)
+    return method(*args, **kwargs)
+
+
 @register.filter(name='submissions_count_distinct')
 def submissions_count_distinct(submissions):
     identifiers_wo_vn_nr = []
@@ -25,54 +41,3 @@ def journal_publication_years(journal):
         if volume.until_date.year not in years:
             years.append(volume.until_date.year)
     return sorted(years)
-
-
-@register.filter(name='journal_nr_publications')
-def journal_nr_publications(journal):
-    return Publication.objects.filter(in_issue__in_volume__in_journal=journal).count()
-
-@register.filter(name='journal_avg_processing_duration')
-def journal_avg_processing_duration(journal):
-    duration = Publication.objects.filter(
-        in_issue__in_volume__in_journal=journal).aggregate(
-            avg=Avg(F('publication_date') - F('submission_date')))['avg']
-    if not duration: return 0
-    return duration.days + duration.seconds/86400
-
-@register.filter(name='journal_citation_rate')
-def journal_citation_rate(journal):
-    return journal.citation_rate()
-
-
-@register.filter(name='volume_nr_publications')
-def volume_nr_publications(volume):
-    return Publication.objects.filter(in_issue__in_volume=volume).count()
-
-@register.filter(name='volume_avg_processing_duration')
-def volume_avg_processing_duration(volume):
-    duration = Publication.objects.filter(
-        in_issue__in_volume=volume).aggregate(
-            avg=Avg(F('publication_date') - F('submission_date')))['avg']
-    if not duration: return 0
-    return duration.days + duration.seconds/86400
-
-@register.filter(name='volume_citation_rate')
-def volume_citation_rate(volume):
-    return volume.citation_rate()
-
-
-@register.filter(name='issue_nr_publications')
-def issue_nr_publications(issue):
-    return Publication.objects.filter(in_issue=issue).count()
-
-@register.filter(name='issue_avg_processing_duration')
-def issue_avg_processing_duration(issue):
-    duration = Publication.objects.filter(
-        in_issue=issue).aggregate(
-            avg=Avg(F('publication_date') - F('submission_date')))['avg']
-    if not duration: return 0
-    return duration.days + duration.seconds/86400
-
-@register.filter(name='issue_citation_rate')
-def issue_citation_rate(issue):
-    return issue.citation_rate()
-- 
GitLab