Commit 54768777 authored by Matija Obreza's avatar Matija Obreza

PDCIStatistics for FaoInstitute

parent 5732b972
......@@ -24,6 +24,7 @@ import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.PrePersist;
import javax.persistence.PreUpdate;
import javax.persistence.Table;
import javax.persistence.Transient;
......@@ -77,6 +78,7 @@ public class PDCI extends VersionedModel {
private int cropName = 0;
@PrePersist
@PreUpdate
protected void prePersist() {
this.score = calculateScore();
this.scoreHist = (float) (Math.ceil(this.score * 2) / 2);
......
/**
* Copyright 2015 Global Crop Diversity Trust
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
package org.genesys2.server.model.genesys;
import java.io.Serializable;
import java.util.List;
/**
* Institute PDCI statistics
*/
public class PDCIStatistics implements Serializable {
private Float min = null;
private Float max = null;
private Double avg = null;
private long[] histogram = new long[21];
private Long count;
public void setMin(Float value) {
this.min = value;
}
public Float getMin() {
return min;
}
public void setMax(Float value) {
this.max = value;
}
public Float getMax() {
return max;
}
public void setAvg(Double value) {
this.avg = value;
}
public Double getAvg() {
return avg;
}
public void setCount(Long value) {
this.count = value;
}
public Long getCount() {
return count;
}
public long[] getHistogram() {
return histogram;
}
/**
* Converts {@link #histogram} to flot.categories compatible JSON
*
* @return
*/
public String getHistogramJson() {
StringBuffer sb = new StringBuffer();
sb.append("[ ");
for (int i = 0; i < histogram.length; i++) {
if (i > 0)
sb.append(", ");
sb.append("['").append(i / 2.0).append("', ").append(histogram[i]).append("]");
}
sb.append(" ]");
return sb.toString();
}
/**
* Fill {@link #histogram} with data
*
* @param hist
*/
public void makeHistogram(List<Object[]> hist) {
for (Object[] h : hist) {
// Determining JPA data types
// System.err.println("Hist " + h[0].getClass() + " " +
// h[1].getClass());
int index = (int) (((Float) h[0]) * 2);
long count = (Long) h[1];
// System.err.println("Index for " + h[0] + " = " + index +
// " count=" + count);
histogram[index] = count;
}
}
}
......@@ -16,7 +16,10 @@
package org.genesys2.server.persistence.domain;
import java.util.List;
import org.genesys2.server.model.genesys.PDCI;
import org.genesys2.server.model.impl.FaoInstitute;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
......@@ -25,4 +28,25 @@ public interface PDCIRepository extends JpaRepository<PDCI, Long> {
@Query("select pdci from PDCI pdci where pdci.accession.id=?1")
PDCI findByAccessionId(Long accessionId);
/**
* Gets [ min(pdci.score), max(pdci.score), avg(pdci.score), count(pdci) ]
* for PDCI of {@link FaoInstitute}
*
* @param faoInstitute
* @return [ Float min(pdci.score), Float max(pdci.score), Double
* avg(pdci.score), Long count(pdci) ]
*/
@Query("select min(pdci.score), max(pdci.score), avg(pdci.score), count(pdci) from Accession a join a.accessionId.pdci pdci where a.institute = ?1")
Object statistics(FaoInstitute faoInstitute);
/**
* Get PDCI histogram for {@link FaoInstitute} by
* {@link PDCI#getScoreHist()}
*
* @param faoInstitute
* @return List of [ scoreHist, count ]
*/
@Query("select pdci.scoreHist, count(pdci) from Accession a join a.accessionId.pdci pdci where a.institute = ?1 group by pdci.scoreHist")
List<Object[]> histogram(FaoInstitute faoInstitute);
}
......@@ -40,6 +40,7 @@ import org.genesys2.server.model.genesys.ExperimentTrait;
import org.genesys2.server.model.genesys.Metadata;
import org.genesys2.server.model.genesys.Method;
import org.genesys2.server.model.genesys.PDCI;
import org.genesys2.server.model.genesys.PDCIStatistics;
import org.genesys2.server.model.genesys.SvalbardData;
import org.genesys2.server.model.genesys.Taxonomy2;
import org.genesys2.server.model.impl.AccessionIdentifier3;
......@@ -232,4 +233,6 @@ public interface GenesysService {
PDCI loadPDCI(Long accessionId);
PDCIStatistics statisticsPDCI(FaoInstitute faoInstitute);
}
......@@ -16,6 +16,9 @@
package org.genesys2.server.service;
import org.genesys2.server.model.genesys.PDCIStatistics;
import org.genesys2.server.model.impl.FaoInstitute;
public interface StatisticsService {
long numberOfCountries();
......@@ -24,4 +27,6 @@ public interface StatisticsService {
long numberOfAccessions();
PDCIStatistics statisticsPDCI(FaoInstitute faoInstitute);
}
......@@ -61,6 +61,7 @@ import org.genesys2.server.model.genesys.ExperimentTrait;
import org.genesys2.server.model.genesys.Metadata;
import org.genesys2.server.model.genesys.Method;
import org.genesys2.server.model.genesys.PDCI;
import org.genesys2.server.model.genesys.PDCIStatistics;
import org.genesys2.server.model.genesys.SelfCopy;
import org.genesys2.server.model.genesys.SvalbardData;
import org.genesys2.server.model.genesys.Taxonomy2;
......@@ -1557,6 +1558,7 @@ public class GenesysServiceImpl implements GenesysService, DatasetService {
@Override
@Transactional
@CacheEvict(value = "statistics", allEntries = true)
public PDCI updatePDCI(Long accessionId) {
if (pdciCalculator == null) {
return null;
......@@ -1569,4 +1571,31 @@ public class GenesysServiceImpl implements GenesysService, DatasetService {
}
return repoPdci.save(pdciCalculator.updatePdci(pdci, accessionId));
}
@Override
public PDCIStatistics statisticsPDCI(FaoInstitute faoInstitute) {
PDCIStatistics stats = new PDCIStatistics();
Object[] overall = (Object[]) repoPdci.statistics(faoInstitute);
if (overall == null) {
LOG.warn("No PDCI statistics for " + faoInstitute);
return null;
}
// Determining JPA data types
// System.err.println(overall[0].getClass());
// System.err.println(overall[1].getClass());
// System.err.println(overall[2].getClass());
// System.err.println(overall[3].getClass());
stats.setMin((Float) overall[0]);
stats.setMax((Float) overall[1]);
stats.setAvg((Double) overall[2]);
stats.setCount((Long) overall[3]);
List<Object[]> hist = repoPdci.histogram(faoInstitute);
stats.makeHistogram(hist);
return stats;
}
}
......@@ -16,6 +16,10 @@
package org.genesys2.server.service.impl;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.genesys2.server.model.genesys.PDCIStatistics;
import org.genesys2.server.model.impl.FaoInstitute;
import org.genesys2.server.service.GenesysService;
import org.genesys2.server.service.GeoService;
import org.genesys2.server.service.InstituteService;
......@@ -28,6 +32,8 @@ import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional(readOnly = true)
public class StatisticsServiceImpl implements StatisticsService {
public static final Log LOG = LogFactory.getLog(StatisticsServiceImpl.class);
@Autowired
private GeoService geoService;
......@@ -54,4 +60,13 @@ public class StatisticsServiceImpl implements StatisticsService {
public long numberOfAccessions() {
return genesysService.countAll();
}
@Override
@Cacheable(unless = "#result == null", value = "statistics", key = "'stats.' + #root.methodName + '-' + #faoInstitute.id")
public PDCIStatistics statisticsPDCI(FaoInstitute faoInstitute) {
if (LOG.isInfoEnabled()) {
LOG.info("Regenerating PDCI statistics for " + faoInstitute);
}
return genesysService.statisticsPDCI(faoInstitute);
}
}
......@@ -94,12 +94,6 @@ public class ElasticUpdater {
* @param ids
*/
public void update(Class<?> clazz, Long id) {
// If Accession, update PDCI
if (Accession.class.equals(clazz) && id !=null) {
genesysService.updatePDCI(id);
}
ElasticNode node = new ElasticNode(clazz, id);
elasticRemoveQueue.remove(node);
......
......@@ -8,7 +8,9 @@ import javax.annotation.Resource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.genesys2.server.model.genesys.Accession;
import org.genesys2.server.service.ElasticService;
import org.genesys2.server.service.GenesysService;
import org.genesys2.server.service.worker.ElasticUpdater.ElasticNode;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
......@@ -41,6 +43,9 @@ class ElasticUpdaterProcessor implements Runnable, InitializingBean, DisposableB
@Resource
private IQueue<ElasticNode> elasticUpdateQueue;
@Autowired
private GenesysService genesysService;
private long indexDelay = 5000;
private HashMap<String, Set<Long>> buckets = new HashMap<String, Set<Long>>();
......@@ -130,6 +135,12 @@ class ElasticUpdaterProcessor implements Runnable, InitializingBean, DisposableB
return;
String className = toUpdate.getClassName();
// If Accession, update PDCI
if (Accession.class.getName().equals(className)) {
genesysService.updatePDCI(toUpdate.getId());
}
Set<Long> bucket = buckets.get(className);
if (bucket == null) {
buckets.put(className, bucket = new HashSet<Long>());
......
......@@ -30,6 +30,7 @@ import org.genesys2.server.service.DSService;
import org.genesys2.server.service.FilterConstants;
import org.genesys2.server.service.GenesysService;
import org.genesys2.server.service.InstituteService;
import org.genesys2.server.service.StatisticsService;
import org.genesys2.server.service.TaxonomyService;
import org.genesys2.server.service.TraitService;
import org.genesys2.server.service.impl.NonUniqueAccessionException;
......@@ -69,6 +70,9 @@ public class AccessionController extends BaseController {
@Autowired(required = false)
private PDCICalculator pdciCalculator;
@Autowired
private StatisticsService statisticsService;
@RequestMapping("/id/{accessionId}")
public String view(ModelMap model, @PathVariable(value = "accessionId") long accessionId) {
_logger.debug("Viewing ACN " + accessionId);
......@@ -118,6 +122,7 @@ public class AccessionController extends BaseController {
}
model.addAttribute("pdci", pdci);
model.addAttribute("institutePDCI", statisticsService.statisticsPDCI(accession.getInstitute()));
} catch (Throwable e) {
_logger.warn(e.getMessage(), e);
......
......@@ -37,6 +37,7 @@ import org.genesys2.server.service.GenesysService;
import org.genesys2.server.service.GeoService;
import org.genesys2.server.service.InstituteService;
import org.genesys2.server.service.OrganizationService;
import org.genesys2.server.service.StatisticsService;
import org.genesys2.server.service.TaxonomyService;
import org.genesys2.server.service.impl.FilterHandler;
import org.genesys2.server.service.impl.FilterHandler.AppliedFilter;
......@@ -83,6 +84,9 @@ public class WiewsController extends BaseController {
@Autowired
private DownloadService downloadService;
@Autowired
private StatisticsService statisticsService;
@RequestMapping("/")
public String view(ModelMap model, @RequestParam(value = "page", required = false, defaultValue = "1") int page) {
model.addAttribute("pagedData", instituteService.listPGRInstitutes(new PageRequest(page - 1, 50, new Sort("code"))));
......@@ -128,6 +132,7 @@ public class WiewsController extends BaseController {
model.addAttribute("statisticsGenus", genesysService.statisticsGenusByInstitute(faoInstitute, new PageRequest(0, 30)));
model.addAttribute("statisticsTaxonomy", genesysService.statisticsSpeciesByInstitute(faoInstitute, new PageRequest(0, 30)));
model.addAttribute("statisticsPDCI", statisticsService.statisticsPDCI(faoInstitute));
return "/wiews/details";
}
......
......@@ -622,7 +622,8 @@ admin.kpi.execution.page=KPI Execution
admin.kpi.executionrun.page=Execution run details
accession.pdci=Passport Data Completeness Index
accession.pdci.jumbo=PDCI Score: {0} of 10.0
accession.pdci.jumbo=PDCI Score: {0,number,0.00} of 10.0
accession.pdci.institute-avg=Average PDCI score for this institute is {0,number,0.00}
accession.pdci.about-link=Read about Passport Data Completeness Index
accession.pdci.independent-items=Independent of the population type
accession.pdci.dependent-items=Depending on the population type
......
......@@ -11,7 +11,7 @@ var GenesysMaps = {
this.lng = lng;
this.noWrap = true;
},
loaded : false,
queue : [],
loadedMaps : [],
......@@ -89,6 +89,27 @@ GenesysMaps.BoundingBox.prototype.getBounds = function() {
};
var GenesysChart = {
histogram : function(placeholder, data) {
$.plot(placeholder, [ {
data : data,
color : '#88ba42'
} ], {
series : {
bars : {
show : true,
barWidth : 0.4,
fill : 1,
lineWidth : 0,
align : 'center'
}
},
xaxis : {
tickLength : 0
}
});
},
chart : function(placeholder, url, options, labelCallback, clickCallback) {
var defaultOptions = {
......@@ -328,7 +349,7 @@ var GenesysFilterUtil = {
fe.toggleClass('edit-filter');
fe.find('.filter-values').parent().toggleClass('col-lg-9').toggleClass('col-lg-4');
},
normKey: function(key) {
normKey : function(key) {
return key.replace(/\./g, '-').replace(/:/g, '_');
}
};
......
......@@ -645,7 +645,27 @@
<security:authorize access="isAuthenticated()">
<c:if test="${pdci ne null}">
<local:pdci value="${pdci}" />
<div class="crop-details">
<h4>
<spring:message code="accession.pdci" />
</h4>
<div class="jumbotron pdci-score">
<div>
<h3>
<spring:message code="accession.pdci.jumbo" arguments="${pdci.score}" />
</h3>
<small> <c:if test="${institutePDCI ne null}">
<spring:message code="accession.pdci.institute-avg" arguments="${institutePDCI.avg}" />
</c:if> <a href="<c:url value="/content/passport-data-completeness-index" />"><spring:message
code="accession.pdci.about-link"
/></a></small>
</div>
</div>
<local:pdci value="${pdci}" />
</div>
</c:if>
</security:authorize>
......
......@@ -6,40 +6,23 @@
<%
%>
<div class="crop-details">
<h4>
<spring:message code="accession.pdci" />
</h4>
<div class="jumbotron pdci-score">
<div>
<h3>
<spring:message code="accession.pdci.jumbo" arguments="${value.score}" />
</h3>
<small><a href="<c:url value="/content/passport-data-completeness-index" />"><spring:message
code="accession.pdci.about-link"
/></a></small>
</div>
</div>
<%-- <h5>
<%-- <h5>
<spring:message code="accession.pdci.independent-items" />
</h5> --%>
<div class="row">
<c:forEach items="${pdci.independentItems}" var="item">
<div class="col-sm-3 col-xs-5 ${pdci[item] == 0 ? 'pdci-improve' : ''}">${item.toUpperCase()}</div>
<div class="col-sm-1 col-xs-1">${pdci[item]}</div>
</c:forEach>
</div>
<h5>
<spring:message code="accession.pdci.dependent-items" />
</h5>
<div class="row">
<c:forEach items="${pdci.dependentItems}" var="item">
<div class="col-sm-3 col-xs-5 ${pdci[item] == 0 ? 'pdci-improve' : ''}">${item.toUpperCase()}</div>
<div class="col-sm-1 col-xs-1">${pdci[item]}</div>
</c:forEach>
</div>
<div class="row">
<c:forEach items="${pdci.independentItems}" var="item">
<div class="col-sm-3 col-xs-5 ${pdci[item] == 0 ? 'pdci-improve' : ''}">${item.toUpperCase()}</div>
<div class="col-sm-1 col-xs-1">${pdci[item]}</div>
</c:forEach>
</div>
<h5>
<spring:message code="accession.pdci.dependent-items" />
</h5>
<div class="row">
<c:forEach items="${pdci.dependentItems}" var="item">
<div class="col-sm-3 col-xs-5 ${pdci[item] == 0 ? 'pdci-improve' : ''}">${item.toUpperCase()}</div>
<div class="col-sm-1 col-xs-1">${pdci[item]}</div>
</c:forEach>
</div>
<%-- <c:forEach items="${pdci.independentItems}" var="item">
accession.pdci.${item}=<br />
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment