[VIVO-1119] Add D3 based versions of the co-authorship / investigator visualisations, which can be used via the runtime.properties
This commit is contained in:
parent
ec29715259
commit
85ad30d611
12 changed files with 1039 additions and 59 deletions
|
@ -311,6 +311,17 @@ resource.altmetric=enabled
|
|||
#
|
||||
visualization.temporal = enabled
|
||||
|
||||
#
|
||||
# The co-authorship and co-investigator graphs have two variants - the traditional Flash based view,
|
||||
# and views using D3.
|
||||
# The traditional views require that users have Flash installed as a plugin, whereas D3 works on any
|
||||
# modern browser.
|
||||
# Currently, it is not possible to choose between them from the UI. You can choose to either have
|
||||
# the Flash visualizations, OR the D3 visualizations.
|
||||
# If this option is not present or set to disabled, then the Flash visualizations will be used.
|
||||
# If this option is present and set to enabled, then the D3 visualizations will be used.
|
||||
visualization.d3 = enabled
|
||||
|
||||
#
|
||||
# Types of individual for which we can create proxy editors.
|
||||
# If this is omitted, defaults to http://www.w3.org/2002/07/owl#Thing
|
||||
|
|
|
@ -18,6 +18,11 @@ a.no_href_styles {
|
|||
width: 67%;
|
||||
margin-left: 33%;
|
||||
}
|
||||
.vis_stats_full {
|
||||
background: #fff;
|
||||
clear: right;
|
||||
width: 100%;
|
||||
}
|
||||
.vis-tables {
|
||||
padding: 10px;
|
||||
background-color: #FFF;
|
||||
|
@ -27,6 +32,12 @@ a.no_href_styles {
|
|||
width: 44%;
|
||||
margin: 0 10px 10px 0;
|
||||
}
|
||||
#chord-info-div {
|
||||
border: 1px solid #000000;
|
||||
background: #F5F5F5;
|
||||
padding: 5px;
|
||||
z-index: 10;
|
||||
}
|
||||
p.datatable {
|
||||
font-size: 12px;
|
||||
display: block;
|
||||
|
@ -46,6 +57,10 @@ p.datatable {
|
|||
width: 67%;
|
||||
float: right;
|
||||
}
|
||||
#sparkline-container-full {
|
||||
clear: both;
|
||||
width: 100%;
|
||||
}
|
||||
#body h1 {
|
||||
margin: 0;
|
||||
}
|
||||
|
|
5
productMods/js/d3.min.js
vendored
Normal file
5
productMods/js/d3.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
|
@ -15,6 +15,23 @@
|
|||
<div class="staticPageBackground">
|
||||
<div id="${visContainerID}">
|
||||
<script type="text/javascript">
|
||||
<#if sparklineVO.shortVisMode>
|
||||
var visualizationOptions = {
|
||||
width: 150,
|
||||
height: 60,
|
||||
color: '3399CC',
|
||||
chartType: 'ls',
|
||||
chartLabel: 'r'
|
||||
};
|
||||
<#else>
|
||||
var visualizationOptions = {
|
||||
width: 250,
|
||||
height: 75,
|
||||
color: '3399CC',
|
||||
chartType: 'ls',
|
||||
chartLabel: 'r'
|
||||
};
|
||||
</#if>
|
||||
|
||||
function drawCoauthorsSparklineVisualization(providedSparklineImgTD) {
|
||||
|
||||
|
@ -49,22 +66,8 @@
|
|||
maxValue: '${sparklineVO.latestRenderedPublicationYear?c}'
|
||||
}]));
|
||||
|
||||
var visualizationOptions = {
|
||||
width: 150,
|
||||
height: 60,
|
||||
color: '3399CC',
|
||||
chartType: 'ls',
|
||||
chartLabel: 'r'
|
||||
}
|
||||
<#else>
|
||||
|
||||
var visualizationOptions = {
|
||||
width: 250,
|
||||
height: 75,
|
||||
color: '3399CC',
|
||||
chartType: 'ls',
|
||||
chartLabel: 'r'
|
||||
}
|
||||
</#if>
|
||||
|
||||
|
||||
|
@ -246,7 +249,7 @@
|
|||
var row = $('<tr>');
|
||||
sparklineImgTD = $('<td>');
|
||||
sparklineImgTD.attr('id', '${sparklineContainerID}_img');
|
||||
sparklineImgTD.attr('width', '150');
|
||||
sparklineImgTD.attr('width', visualizationOptions.width);
|
||||
sparklineImgTD.attr('class', 'sparkline_style');
|
||||
|
||||
row.append(sparklineImgTD);
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<table id='${tableID}'>
|
||||
<caption>
|
||||
${tableCaption} <a href="${fileDownloadLink}">(.CSV ${i18n().file_capitalized})</a>
|
||||
</caption>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>
|
||||
${tableCollaboratorColumnName}
|
||||
</th>
|
||||
<th>
|
||||
${tableActivityColumnName}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<#list tableContent.collaborators as collaborator>
|
||||
<#if collaborator_index gt 0>
|
||||
<tr>
|
||||
<td>
|
||||
${collaborator.collaboratorName}
|
||||
</td>
|
||||
<td>
|
||||
${tableContent.collaborationMatrix[0][collaborator_index]}
|
||||
</td>
|
||||
</tr>
|
||||
</#if>
|
||||
</#list>
|
||||
|
||||
</tbody>
|
||||
</table>
|
|
@ -15,6 +15,23 @@
|
|||
<div class="staticPageBackground">
|
||||
<div id="${visContainerID}">
|
||||
<script type="text/javascript">
|
||||
<#if sparklineVO.shortVisMode>
|
||||
var visualizationOptions = {
|
||||
width: 150,
|
||||
height: 60,
|
||||
color: '3399CC',
|
||||
chartType: 'ls',
|
||||
chartLabel: 'r'
|
||||
};
|
||||
<#else>
|
||||
var visualizationOptions = {
|
||||
width: 250,
|
||||
height: 75,
|
||||
color: '3399CC',
|
||||
chartType: 'ls',
|
||||
chartLabel: 'r'
|
||||
};
|
||||
</#if>
|
||||
|
||||
function drawCoInvestigatorsSparklineVisualization(providedSparklineImgTD) {
|
||||
|
||||
|
@ -53,14 +70,6 @@
|
|||
|
||||
</#if>
|
||||
|
||||
var visualizationOptions = {
|
||||
width: 150,
|
||||
height: 60,
|
||||
color: '3399CC',
|
||||
chartType: 'ls',
|
||||
chartLabel: 'r'
|
||||
}
|
||||
|
||||
/*
|
||||
This means that all the publications have unknown years & we do not need to display
|
||||
the sparkline.
|
||||
|
@ -243,7 +252,7 @@
|
|||
var row = $('<tr>');
|
||||
sparklineImgTD = $('<td>');
|
||||
sparklineImgTD.attr('id', '${sparklineContainerID}_img');
|
||||
sparklineImgTD.attr('width', '150');
|
||||
sparklineImgTD.attr('width', visualizationOptions.width);
|
||||
sparklineImgTD.attr('class', 'sparkline_style');
|
||||
|
||||
row.append(sparklineImgTD);
|
||||
|
|
|
@ -15,6 +15,23 @@
|
|||
<div class="staticPageBackground">
|
||||
<div id="${visContainerID}">
|
||||
<script type="text/javascript">
|
||||
<#if sparklineVO.shortVisMode>
|
||||
var visualizationOptions = {
|
||||
width: 150,
|
||||
height: 60,
|
||||
color: '3399CC',
|
||||
chartType: 'ls',
|
||||
chartLabel: 'r'
|
||||
};
|
||||
<#else>
|
||||
var visualizationOptions = {
|
||||
width: 250,
|
||||
height: 75,
|
||||
color: '3399CC',
|
||||
chartType: 'ls',
|
||||
chartLabel: 'r'
|
||||
};
|
||||
</#if>
|
||||
|
||||
function drawGrantCountVisualization(providedSparklineImgTD) {
|
||||
|
||||
|
@ -53,13 +70,6 @@
|
|||
|
||||
</#if>
|
||||
|
||||
var visualizationOptions = {
|
||||
width: 150,
|
||||
height: 60,
|
||||
color: '3399CC',
|
||||
chartType: 'ls',
|
||||
chartLabel: 'r'
|
||||
}
|
||||
|
||||
/*
|
||||
This means that all the publications have unknown years & we do not need to display
|
||||
|
@ -236,7 +246,7 @@
|
|||
var row = $('<tr>');
|
||||
sparklineImgTD = $('<td>');
|
||||
sparklineImgTD.attr('id', '${sparklineContainerID}_img');
|
||||
sparklineImgTD.attr('width', '150');
|
||||
sparklineImgTD.attr('width', visualizationOptions.width);
|
||||
sparklineImgTD.attr('class', 'sparkline_style');
|
||||
|
||||
row.append(sparklineImgTD);
|
||||
|
|
|
@ -0,0 +1,345 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<#assign standardVisualizationURLRoot ="/visualization">
|
||||
<#assign shortVisualizationURLRoot ="/vis">
|
||||
<#assign ajaxVisualizationURLRoot ="/visualizationAjax">
|
||||
<#assign dataVisualizationURLRoot ="/visualizationData">
|
||||
|
||||
<#assign egoURI ="${egoURIParam?url}">
|
||||
<#assign egoCoAuthorshipDataFeederURL = '${urls.base}${dataVisualizationURLRoot}?vis=coauthorship&uri=${egoURI}&vis_mode=coauthor_network_stream&labelField=label'>
|
||||
|
||||
<#if egoLocalName?has_content >
|
||||
<#assign coprincipalinvestigatorURL = '${urls.base}${shortVisualizationURLRoot}/investigator-network/${egoLocalName}'>
|
||||
<#else>
|
||||
<#assign coprincipalinvestigatorURL = '${urls.base}${shortVisualizationURLRoot}/investigator-network/?uri=${egoURI}'>
|
||||
</#if>
|
||||
|
||||
<#assign egoCoAuthorsListDataFileURL = '${urls.base}${dataVisualizationURLRoot}?vis=coauthorship&uri=${egoURI}&vis_mode=coauthors'>
|
||||
<#assign egoCoAuthorshipNetworkDataFileURL = '${urls.base}${dataVisualizationURLRoot}?vis=coauthorship&uri=${egoURI}&vis_mode=coauthor_network_download'>
|
||||
|
||||
<#assign googleVisualizationAPI = 'https://www.google.com/jsapi?autoload=%7B%22modules%22%3A%5B%7B%22name%22%3A%22visualization%22%2C%22version%22%3A%221%22%2C%22packages%22%3A%5B%22areachart%22%2C%22imagesparkline%22%5D%7D%5D%7D'>
|
||||
<#assign coAuthorPersonLevelJavaScript = '${urls.base}/js/visualization/coauthorship/coauthorship-personlevel.js'>
|
||||
<#assign commonPersonLevelJavaScript = '${urls.base}/js/visualization/personlevel/person-level.js'>
|
||||
|
||||
<#assign coInvestigatorIcon = '${urls.images}/visualization/coauthorship/co_investigator_icon.png'>
|
||||
|
||||
<script type="text/javascript" src="${googleVisualizationAPI}"></script>
|
||||
|
||||
<script language="JavaScript" type="text/javascript">
|
||||
<!--
|
||||
// -----------------------------------------------------------------------------
|
||||
// Globals
|
||||
var egoURI = "${egoURI}";
|
||||
var unEncodedEgoURI = "${egoURIParam}";
|
||||
var egoCoAuthorshipDataFeederURL = "${egoCoAuthorshipDataFeederURL}";
|
||||
var egoCoAuthorsListDataFileURL = "${egoCoAuthorsListDataFileURL}";
|
||||
var contextPath = "${urls.base}";
|
||||
|
||||
var visualizationDataRoot = "${dataVisualizationURLRoot}";
|
||||
// -->
|
||||
|
||||
var i18nStringsCoauthorship = {
|
||||
coAuthorsString: '${i18n().co_authors_capitalized}',
|
||||
authorString: '${i18n().author_capitalized}',
|
||||
publicationsWith: '${i18n().publications_with}',
|
||||
publicationsString: "${i18n().through_today}",
|
||||
coauthorsString: '${i18n().co_author_s_capitalized}'
|
||||
};
|
||||
var i18nStringsPersonLvl = {
|
||||
fileCapitalized: '${i18n().file_capitalized}',
|
||||
contentRequiresFlash: '${i18n().content_requires_flash}',
|
||||
getFlashString: '${i18n().get_flash}'
|
||||
};
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="${coAuthorPersonLevelJavaScript}"></script>
|
||||
<script type="text/javascript" src="${commonPersonLevelJavaScript}"></script>
|
||||
|
||||
${scripts.add('<script type="text/javascript" src="${urls.base}/js/visualization/visualization-helper-functions.js"></script>')}
|
||||
${scripts.add('<script type="text/javascript" src="${urls.base}/js/d3.min.js"></script>')}
|
||||
|
||||
${stylesheets.add('<link rel="stylesheet" type="text/css" href="${urls.base}/css/visualization/personlevel/page.css" />',
|
||||
'<link rel="stylesheet" type="text/css" href="${urls.base}/css/visualization/visualization.css" />')}
|
||||
|
||||
<#assign egoVivoProfileURL = "${urls.base}/individual?uri=${egoURI}" />
|
||||
|
||||
<script language="JavaScript" type="text/javascript">
|
||||
|
||||
$(document).ready(function(){
|
||||
|
||||
processProfileInformation("ego_label",
|
||||
"ego_moniker",
|
||||
"ego_profile_image",
|
||||
jQuery.parseJSON(getWellFormedURLs("${egoURIParam}", "profile_info")));
|
||||
|
||||
<#if (numOfCoAuthorShips?? && numOfCoAuthorShips <= 0) || (numOfAuthors?? && numOfAuthors <= 0) >
|
||||
if ($('#ego_label').text().length > 0) {
|
||||
setProfileName('no_coauthorships_person', $('#ego_label').text());
|
||||
}
|
||||
</#if>
|
||||
|
||||
|
||||
$.ajax({
|
||||
url: "${urls.base}/visualizationAjax",
|
||||
data: ({vis: "utilities", vis_mode: "SHOW_GRANTS_LINK", uri: '${egoURIParam}'}),
|
||||
dataType: "json",
|
||||
success:function(data){
|
||||
|
||||
/*
|
||||
Collaboratorship links do not show up by default. They should show up only if there any data to
|
||||
show on that page.
|
||||
*/
|
||||
if (data.numOfGrants !== undefined && data.numOfGrants > 0) {
|
||||
$(".toggle_visualization").show();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
// RENDER CHORD
|
||||
|
||||
var labels = [];
|
||||
var uris = [];
|
||||
var matrix = [];
|
||||
|
||||
var matrixX = 0;
|
||||
<#list coAuthorshipData.collaborationMatrix as row>
|
||||
matrix[matrixX] = [];
|
||||
<#list row as cell>
|
||||
matrix[matrixX].push(${cell?c});
|
||||
</#list>
|
||||
matrixX++;
|
||||
</#list>
|
||||
<#list coAuthorshipData.collaborators as collaborator>
|
||||
labels.push("${collaborator.collaboratorName}");
|
||||
uris.push("${collaborator.collaboratorURI}");
|
||||
</#list>
|
||||
|
||||
var chord = d3.layout.chord()
|
||||
.padding(0.05)
|
||||
.sortSubgroups(d3.descending)
|
||||
.matrix(matrix);
|
||||
|
||||
var width = 725;
|
||||
var height = 725;
|
||||
var padding = 175;
|
||||
var inner_radius = Math.min(width, height) * 0.37;
|
||||
var outer_radius = Math.min(width, height) * 0.39;
|
||||
|
||||
var fill = d3.scale.category10();
|
||||
|
||||
var svg = d3.select('#chord').append('svg')
|
||||
.attr('width', width+padding)
|
||||
.attr('height', height+padding)
|
||||
.append('g').attr('transform', 'translate(' + (width+padding) / 2 + ',' + (height+padding) / 2 +')');
|
||||
|
||||
svg.append('g').selectAll('path').data(chord.groups).enter()
|
||||
.append('path').style('fill', function(val) { return val.index == 0 ? "#000000" : fill(val.index); })
|
||||
.style('stroke', function(val) { return val.index == 0 ? "#000000" : fill(val.index); })
|
||||
.attr('d', d3.svg.arc().innerRadius(inner_radius).outerRadius(outer_radius))
|
||||
.on('click', chord_click())
|
||||
.on("mouseover", chord_hover(.05))
|
||||
.on("mouseout", chord_hover(.8));
|
||||
|
||||
var group_ticks = function (d) {
|
||||
var k = (d.endAngle - d.startAngle) / d.value;
|
||||
return d3.range(d.value / 2, d.value, d.value / 2).map(function (v) {
|
||||
return {
|
||||
angle: v * k + d.startAngle,
|
||||
label: Math.round(d.value)
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
var chord_ticks = svg.append('g')
|
||||
.selectAll('g')
|
||||
.data(chord.groups)
|
||||
.enter().append('g')
|
||||
.selectAll('g')
|
||||
.data(group_ticks)
|
||||
.enter().append('g')
|
||||
.attr('transform', function (d) {
|
||||
return 'rotate(' + (d.angle * 180 / Math.PI - 90) + ') translate(' + outer_radius + ',0)';
|
||||
});
|
||||
|
||||
svg.append('g')
|
||||
.attr('class', 'chord')
|
||||
.selectAll('path')
|
||||
.data(chord.chords)
|
||||
.enter().append('path')
|
||||
.style('fill', function (d) { return fill(d.target.index); })
|
||||
.attr('d', d3.svg.chord().radius(inner_radius))
|
||||
.style('opacity', .8);
|
||||
|
||||
svg.append("g").selectAll(".arc")
|
||||
.data(chord.groups)
|
||||
.enter().append("svg:text")
|
||||
.attr("dy", ".35em")
|
||||
.attr("style", function(d) { return d.index == 0 ? "font-size: .75em; font-weight: bold;" : "font-size: .70em;"; } )
|
||||
.attr("text-anchor", function(d) { return ((d.startAngle + d.endAngle) / 2) > Math.PI ? "end" : null; })
|
||||
.attr("transform", function(d) {
|
||||
return "rotate(" + (((d.startAngle + d.endAngle) / 2) * 180 / Math.PI - 90) + ")"
|
||||
+ "translate(" + (height *.40) + ")"
|
||||
+ (((d.startAngle + d.endAngle) / 2) > Math.PI ? "rotate(180)" : "");
|
||||
})
|
||||
.text(function(d) {
|
||||
return labels[d.index];
|
||||
})
|
||||
.on('click', chord_click())
|
||||
.on("mouseover", chord_hover(.05))
|
||||
.on("mouseout", chord_hover(.8));
|
||||
|
||||
function chord_hover(opacity) {
|
||||
return function(g, i) {
|
||||
if (opacity > .5) {
|
||||
var chordInfoDiv = d3.select('#chord-info-div');
|
||||
chordInfoDiv.style('display', 'none');
|
||||
} else {
|
||||
var hoverEvent = d3.event;
|
||||
var topPos = hoverEvent.pageY - 60;
|
||||
var leftPos = hoverEvent.pageX + 10;
|
||||
|
||||
var chord = d3.select('#chord').node();
|
||||
var chordInfoDiv = d3.select('#chord-info-div');
|
||||
var hoverMsg = labels[i] + "<br/>";
|
||||
if (i > 0) {
|
||||
hoverMsg += matrix[i][0] + " Joint ${i18n().publication_s_capitalized}<br/>";
|
||||
} else {
|
||||
hoverMsg += "${coAuthorshipData.collaboratorsCount} ${i18n().co_author_s_capitalized}<br/>";
|
||||
}
|
||||
|
||||
chordInfoDiv.html(hoverMsg);
|
||||
chordInfoDiv.style('display', 'block');
|
||||
chordInfoDiv.style('position', 'absolute');
|
||||
|
||||
if (d3.mouse(chord)[1] > height / 2) {
|
||||
topPos += 80;
|
||||
}
|
||||
chordInfoDiv.style('top', topPos + 'px');
|
||||
|
||||
if (hoverEvent.pageX > document.body.clientWidth / 2) {
|
||||
leftPos = hoverEvent.pageX + 10;
|
||||
} else {
|
||||
leftPos = hoverEvent.pageX - (10 + chordInfoDiv.node().getBoundingClientRect().width);
|
||||
}
|
||||
chordInfoDiv.style('left', leftPos + 'px');
|
||||
}
|
||||
|
||||
svg.selectAll(".chord path")
|
||||
.filter(function(d) { return d.source.index != i && d.target.index != i; })
|
||||
.transition()
|
||||
.style("opacity", opacity);
|
||||
}
|
||||
}
|
||||
|
||||
function chord_click() {
|
||||
return function (g, i) {
|
||||
if (i > 0) {
|
||||
window.location.href = getWellFormedURLs(uris[i], "profile");
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<div id="body">
|
||||
<div class="sub_headings"><h2><a href="${egoVivoProfileURL}" title="${i18n().author_name}"><span id="ego_label"></span></a><br />${i18n().co_author_network} </h2></div>
|
||||
<#if (numOfCoAuthorShips?? && numOfCoAuthorShips > 0) || (numOfAuthors?? && numOfAuthors > 0) >
|
||||
<div class = "graphml-file-link">(<a href="${egoCoAuthorshipNetworkDataFileURL}" title="GraphML ${i18n().file}">GraphML ${i18n().file}</a>)</div>
|
||||
<#else>
|
||||
|
||||
<#if numOfAuthors?? && numOfAuthors <= 0 >
|
||||
<#assign authorsText = "multi-author" />
|
||||
</#if>
|
||||
|
||||
<div id="no_coauthorships">${i18n().currently_no_papers_for(authorsText!)}
|
||||
<a href="${egoVivoProfileURL}" title="${i18n().co_authorship}"><span id="no_coauthorships_person" class="author_name">${i18n().this_author}</span></a> ${i18n().in_the_vivo_db}
|
||||
</div>
|
||||
</#if>
|
||||
|
||||
<div class = "toggle_visualization">
|
||||
<div id="coinvestigator_link_container" class="collaboratorship-link-container">
|
||||
<div class="collaboratorship-icon"><a href="${coprincipalinvestigatorURL}" title="${i18n().co_investigator}"><img src="${coInvestigatorIcon}" alt="${i18n().co_investigator_icon}"/></a></div>
|
||||
<div class="collaboratorship-link">
|
||||
<h3><a href="${coprincipalinvestigatorURL}" title="${i18n().co_investigator_network}">${i18n().co_investigator_network_capitalized}</a></h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="clear:both;"></div>
|
||||
|
||||
<#if (numOfAuthors?? && numOfAuthors > 0) >
|
||||
<#else>
|
||||
|
||||
<span id="no_coauthorships">${i18n().no_papers_for}
|
||||
<a href="${egoVivoProfileURL}" title="${i18n().co_authorship}"><span id="no_coauthorships_person" class="author_name">${i18n().this_author}</span></a> ${i18n().in_the_vivo_db}
|
||||
</span>
|
||||
|
||||
</#if>
|
||||
|
||||
<#if (numOfCoAuthorShips?? && numOfCoAuthorShips > 0) || (numOfAuthors?? && numOfAuthors > 0) >
|
||||
|
||||
<div id="bodyPannel">
|
||||
<div id="chord" style="float: right;"></div>
|
||||
</div>
|
||||
</#if>
|
||||
|
||||
<#if (numOfAuthors?? && numOfAuthors > 0) >
|
||||
|
||||
<#-- Sparkline -->
|
||||
<div id="sparkline-container-full">
|
||||
|
||||
<#assign displayTable = false />
|
||||
|
||||
<#assign sparklineVO = egoPubSparklineVO />
|
||||
<div id="publication-count-sparkline-include"><#include "personPublicationSparklineContent.ftl"></div>
|
||||
|
||||
<#assign sparklineVO = uniqueCoauthorsSparklineVO />
|
||||
<div id="coauthor-count-sparkline-include"><#include "coAuthorshipSparklineContent.ftl"></div>
|
||||
</div>
|
||||
|
||||
<div class="vis_stats_full">
|
||||
|
||||
<div class="sub_headings" id="table_heading"><h3>${i18n().tables_capitalized}</h3></div>
|
||||
|
||||
<div class="vis-tables">
|
||||
|
||||
<p id="publications_table_container" class="datatable">
|
||||
|
||||
<#assign tableID = "publication_data_table" />
|
||||
<#assign tableCaption = "${i18n().publications_per_year} " />
|
||||
<#assign tableActivityColumnName = "${i18n().publications_capitalized}" />
|
||||
<#assign tableContent = egoPubSparklineVO.yearToActivityCount />
|
||||
<#assign fileDownloadLink = egoPubSparklineVO.downloadDataLink />
|
||||
|
||||
<#include "yearToActivityCountTable.ftl">
|
||||
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
<#if (numOfCoAuthorShips?? && numOfCoAuthorShips > 0) >
|
||||
|
||||
<div class="vis-tables">
|
||||
<p id="coauth_table_container" class="datatable">
|
||||
<#assign tableID = "coauthorships_table" />
|
||||
<#assign tableCaption = "${i18n().co_authors_capitalized} " />
|
||||
<#assign tableCollaboratorColumnName = "${i18n().author_capitalized}" />
|
||||
<#assign tableActivityColumnName = "${i18n().publications_with}" />
|
||||
<#assign tableContent = coAuthorshipData />
|
||||
<#assign fileDownloadLink = uniqueCoauthorsSparklineVO.downloadDataLink />
|
||||
|
||||
<#include "collaboratorToActivityCountTable.ftl">
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</#if>
|
||||
|
||||
<div style="clear:both"></div>
|
||||
|
||||
</div>
|
||||
|
||||
</#if>
|
||||
|
||||
</div>
|
||||
<div id="chord-info-div" style="display: none;"></div>
|
|
@ -0,0 +1,359 @@
|
|||
<#-- $This file is distributed under the terms of the license in /doc/license.txt$ -->
|
||||
|
||||
<#assign standardVisualizationURLRoot ="/visualization">
|
||||
<#assign shortVisualizationURLRoot ="/vis">
|
||||
<#assign ajaxVisualizationURLRoot ="/visualizationAjax">
|
||||
<#assign dataVisualizationURLRoot ="/visualizationData">
|
||||
|
||||
<#assign egoURI ="${egoURIParam?url}">
|
||||
<#assign egoCoInvestigationDataFeederURL = '${urls.base}${dataVisualizationURLRoot}?vis=coprincipalinvestigator&uri=${egoURI}&vis_mode=copi_network_stream&labelField=label'>
|
||||
|
||||
<#assign coauthorshipURL = '${urls.base}${shortVisualizationURLRoot}/author-network/?uri=${egoURI}'>
|
||||
|
||||
<#if egoLocalName?has_content >
|
||||
<#assign coauthorshipURL = '${urls.base}${shortVisualizationURLRoot}/author-network/${egoLocalName}'>
|
||||
<#else>
|
||||
<#assign coauthorshipURL = '${urls.base}${shortVisualizationURLRoot}/author-network/?uri=${egoURI}'>
|
||||
</#if>
|
||||
|
||||
<#assign egoCoInvestigatorsListDataFileURL = '${urls.base}${dataVisualizationURLRoot}?vis=coprincipalinvestigator&uri=${egoURI}&vis_mode=copis'>
|
||||
<#assign egoCoInvestigationNetworkDataFileURL = '${urls.base}${dataVisualizationURLRoot}?vis=coprincipalinvestigator&uri=${egoURI}&vis_mode=copi_network_download'>
|
||||
|
||||
<#assign coAuthorIcon = '${urls.images}/visualization/coauthorship/co_author_icon.png'>
|
||||
|
||||
<#assign googleVisualizationAPI = 'https://www.google.com/jsapi?autoload=%7B%22modules%22%3A%5B%7B%22name%22%3A%22visualization%22%2C%22version%22%3A%221%22%2C%22packages%22%3A%5B%22areachart%22%2C%22imagesparkline%22%5D%7D%5D%7D'>
|
||||
<#assign coInvestigatorPersonLevelJavaScript = '${urls.base}/js/visualization/coPIship/coPIship-person-level.js'>
|
||||
<#assign commonPersonLevelJavaScript = '${urls.base}/js/visualization/personlevel/person-level.js'>
|
||||
|
||||
<script type="text/javascript" src="${googleVisualizationAPI}"></script>
|
||||
|
||||
<script language="JavaScript" type="text/javascript">
|
||||
<!--
|
||||
// -----------------------------------------------------------------------------
|
||||
// Globals
|
||||
var egoURI = "${egoURI}";
|
||||
var unEncodedEgoURI = "${egoURIParam}";
|
||||
var egoCoInvestigationDataFeederURL = "${egoCoInvestigationDataFeederURL}";
|
||||
var egoCoInvestigatorsListDataFileURL = "${egoCoInvestigatorsListDataFileURL}";
|
||||
|
||||
var contextPath = "${urls.base}";
|
||||
|
||||
var visualizationDataRoot = "${dataVisualizationURLRoot}";
|
||||
|
||||
// -->
|
||||
var i18nStringsCoPi = {
|
||||
coInvestigatorString: '${i18n().co_inestigators_capitalized}',
|
||||
investigatorString: '${i18n().investigator_capitalized}',
|
||||
grantsWithString: '${i18n().grants_with}',
|
||||
grantsCapitalized: '${i18n().grant_s_capitalized}',
|
||||
coInvestigatorCapitalized: '${i18n().co_investigator_s_capitalized}'
|
||||
};
|
||||
var i18nStringsPersonLvl = {
|
||||
fileCapitalized: '${i18n().file_capitalized}',
|
||||
contentRequiresFlash: '${i18n().content_requires_flash}',
|
||||
getFlashString: '${i18n().get_flash}'
|
||||
};
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="${coInvestigatorPersonLevelJavaScript}"></script>
|
||||
<script type="text/javascript" src="${commonPersonLevelJavaScript}"></script>
|
||||
|
||||
${scripts.add('<script type="text/javascript" src="${urls.base}/js/visualization/visualization-helper-functions.js"></script>')}
|
||||
${scripts.add('<script type="text/javascript" src="${urls.base}/js/d3.min.js"></script>')}
|
||||
|
||||
${stylesheets.add('<link rel="stylesheet" type="text/css" href="${urls.base}/css/visualization/personlevel/page.css" />',
|
||||
'<link rel="stylesheet" type="text/css" href="${urls.base}/css/visualization/visualization.css" />')}
|
||||
|
||||
<#assign loadingImageLink = "${urls.images}/visualization/ajax-loader.gif">
|
||||
|
||||
<#assign egoVivoProfileURL = "${urls.base}/individual?uri=${egoURI}" />
|
||||
|
||||
<script language="JavaScript" type="text/javascript">
|
||||
|
||||
$(document).ready(function(){
|
||||
|
||||
processProfileInformation("ego_label",
|
||||
"ego_moniker",
|
||||
"ego_profile_image",
|
||||
jQuery.parseJSON(getWellFormedURLs("${egoURIParam}", "profile_info")));
|
||||
|
||||
<#if (numOfCoInvestigations?? && numOfCoInvestigations <= 0) || (numOfInvestigators?? && numOfInvestigators <= 0) >
|
||||
if ($('#ego_label').text().length > 0) {
|
||||
setProfileName('no_coinvestigations_person', $('#ego_label').text());
|
||||
}
|
||||
</#if>
|
||||
|
||||
$.ajax({
|
||||
url: "${urls.base}/visualizationAjax",
|
||||
data: ({vis: "utilities", vis_mode: "SHOW_AUTHORSHIP_LINK", uri: '${egoURIParam}'}),
|
||||
dataType: "json",
|
||||
success:function(data){
|
||||
|
||||
/*
|
||||
Collaboratorship links do not show up by default. They should show up only if there any data to
|
||||
show on that page.
|
||||
*/
|
||||
if (data.numOfPublications !== undefined && data.numOfPublications > 0) {
|
||||
$(".toggle_visualization").show();
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
// RENDER CHORD
|
||||
|
||||
var labels = [];
|
||||
var uris = [];
|
||||
var matrix = [];
|
||||
|
||||
var matrixX = 0;
|
||||
<#list coInvestigatorData.collaborationMatrix as row>
|
||||
matrix[matrixX] = [];
|
||||
<#list row as cell>
|
||||
matrix[matrixX].push(${cell?c});
|
||||
</#list>
|
||||
matrixX++;
|
||||
</#list>
|
||||
<#list coInvestigatorData.collaborators as collaborator>
|
||||
labels.push("${collaborator.collaboratorName}");
|
||||
uris.push("${collaborator.collaboratorURI}");
|
||||
</#list>
|
||||
|
||||
var chord = d3.layout.chord()
|
||||
.padding(0.05)
|
||||
.sortSubgroups(d3.descending)
|
||||
.matrix(matrix);
|
||||
|
||||
var width = 725;
|
||||
var height = 725;
|
||||
var padding = 175;
|
||||
var inner_radius = Math.min(width, height) * 0.37;
|
||||
var outer_radius = Math.min(width, height) * 0.39;
|
||||
|
||||
var fill = d3.scale.category10();
|
||||
|
||||
var svg = d3.select('#chord').append('svg')
|
||||
.attr('width', width+padding)
|
||||
.attr('height', height+padding)
|
||||
.append('g').attr('transform', 'translate(' + (width+padding) / 2 + ',' + (height+padding) / 2 +')');
|
||||
|
||||
svg.append('g').selectAll('path').data(chord.groups).enter()
|
||||
.append('path').style('fill', function(val) { return val.index == 0 ? "#000000" : fill(val.index); })
|
||||
.style('stroke', function(val) { return val.index == 0 ? "#000000" : fill(val.index); })
|
||||
.attr('d', d3.svg.arc().innerRadius(inner_radius).outerRadius(outer_radius))
|
||||
.on('click', chord_click())
|
||||
.on("mouseover", chord_hover(.05))
|
||||
.on("mouseout", chord_hover(.8));
|
||||
|
||||
var group_ticks = function (d) {
|
||||
var k = (d.endAngle - d.startAngle) / d.value;
|
||||
return d3.range(d.value / 2, d.value, d.value / 2).map(function (v) {
|
||||
return {
|
||||
angle: v * k + d.startAngle,
|
||||
label: Math.round(d.value)
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
var chord_ticks = svg.append('g')
|
||||
.selectAll('g')
|
||||
.data(chord.groups)
|
||||
.enter().append('g')
|
||||
.selectAll('g')
|
||||
.data(group_ticks)
|
||||
.enter().append('g')
|
||||
.attr('transform', function (d) {
|
||||
return 'rotate(' + (d.angle * 180 / Math.PI - 90) + ') translate(' + outer_radius + ',0)';
|
||||
});
|
||||
|
||||
svg.append('g')
|
||||
.attr('class', 'chord')
|
||||
.selectAll('path')
|
||||
.data(chord.chords)
|
||||
.enter().append('path')
|
||||
.style('fill', function (d) { return fill(d.target.index); })
|
||||
.attr('d', d3.svg.chord().radius(inner_radius))
|
||||
.style('opacity', .8);
|
||||
|
||||
svg.append("g").selectAll(".arc")
|
||||
.data(chord.groups)
|
||||
.enter().append("svg:text")
|
||||
.attr("dy", ".35em")
|
||||
.attr("style", function(d) { return d.index == 0 ? "font-size: .75em; font-weight: bold;" : "font-size: .70em;"; } )
|
||||
.attr("text-anchor", function(d) { return ((d.startAngle + d.endAngle) / 2) > Math.PI ? "end" : null; })
|
||||
.attr("transform", function(d) {
|
||||
return "rotate(" + (((d.startAngle + d.endAngle) / 2) * 180 / Math.PI - 90) + ")"
|
||||
+ "translate(" + (height *.40) + ")"
|
||||
+ (((d.startAngle + d.endAngle) / 2) > Math.PI ? "rotate(180)" : "");
|
||||
})
|
||||
.text(function(d) {
|
||||
return labels[d.index];
|
||||
})
|
||||
.on('click', chord_click())
|
||||
.on("mouseover", chord_hover(.05))
|
||||
.on("mouseout", chord_hover(.8));
|
||||
|
||||
function chord_hover(opacity) {
|
||||
return function(g, i) {
|
||||
if (opacity > .5) {
|
||||
var chordInfoDiv = d3.select('#chord-info-div');
|
||||
chordInfoDiv.style('display', 'none');
|
||||
} else {
|
||||
var hoverEvent = d3.event;
|
||||
var topPos = hoverEvent.pageY - 60;
|
||||
var leftPos = hoverEvent.pageX + 10;
|
||||
|
||||
var chord = d3.select('#chord').node();
|
||||
var chordInfoDiv = d3.select('#chord-info-div');
|
||||
var hoverMsg = labels[i] + "<br/>";
|
||||
if (i > 0) {
|
||||
hoverMsg += matrix[i][0] + " Joint ${i18n().grant_s_capitalized}<br/>";
|
||||
} else {
|
||||
hoverMsg += "${coInvestigatorData.collaboratorsCount} ${i18n().co_investigator_s_capitalized}<br/>";
|
||||
}
|
||||
|
||||
chordInfoDiv.html(hoverMsg);
|
||||
chordInfoDiv.style('display', 'block');
|
||||
chordInfoDiv.style('position', 'absolute');
|
||||
|
||||
if (d3.mouse(chord)[1] > height / 2) {
|
||||
topPos += 80;
|
||||
}
|
||||
chordInfoDiv.style('top', topPos + 'px');
|
||||
|
||||
if (hoverEvent.pageX > document.body.clientWidth / 2) {
|
||||
leftPos = hoverEvent.pageX + 10;
|
||||
} else {
|
||||
leftPos = hoverEvent.pageX - (10 + chordInfoDiv.node().getBoundingClientRect().width);
|
||||
}
|
||||
chordInfoDiv.style('left', leftPos + 'px');
|
||||
}
|
||||
|
||||
svg.selectAll(".chord path")
|
||||
.filter(function(d) { return d.source.index != i && d.target.index != i; })
|
||||
.transition()
|
||||
.style("opacity", opacity);
|
||||
}
|
||||
}
|
||||
|
||||
function chord_click() {
|
||||
return function (g, i) {
|
||||
if (i > 0) {
|
||||
window.location.href = getWellFormedURLs(uris[i], "profile");
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<div id="body">
|
||||
<div class="sub_headings"><h2><a href="${egoVivoProfileURL}" title="${i18n().investigator_name}"><span id="ego_label"></span></a><br />${i18n().co_investigator_network_capitalized} </h2></div>
|
||||
|
||||
<#if (numOfInvestigators?? && numOfInvestigators > 0) >
|
||||
|
||||
<#if (numOfCoInvestigations?? && numOfCoInvestigations > 0) || (numOfInvestigators?? && numOfInvestigators > 0) >
|
||||
<div class = "graphml-file-link"><a href="${egoCoInvestigationNetworkDataFileURL}" title="${i18n().co_investigator}">(GraphML ${i18n().file_capitalized})</a></div>
|
||||
<#else>
|
||||
|
||||
<#if numOfInvestigators?? && numOfInvestigators <= 0 >
|
||||
<#assign investigatorsText = "multi-investigator" />
|
||||
</#if>
|
||||
|
||||
<span id="no_coinvestigations">${i18n().currently_no_grants_for(investigatorsText!)}
|
||||
<a href="${egoVivoProfileURL}" title="${i18n().investigator_name}"><span id="no_coinvestigations_person" class="investigator_name">${i18n().this_investigator}</span></a> ${i18n().in_the_vivo_db}
|
||||
</span>
|
||||
</#if>
|
||||
|
||||
<#else>
|
||||
|
||||
<span id="no_coinvestigations">${i18n().no_grants_for}
|
||||
<a href="${egoVivoProfileURL}" title="${i18n().co_investigator}"><span id="no_coinvestigations_person" class="investigator_name">${i18n().this_investigator}</span></a> ${i18n().in_the_vivo_db}
|
||||
</span>
|
||||
|
||||
</#if>
|
||||
|
||||
<div class = "toggle_visualization">
|
||||
<div id="coauthorship_link_container" class="collaboratorship-link-container">
|
||||
<div class="collaboratorship-icon"><a href="${coauthorshipURL}" title="${i18n().co_author}"><img src="${coAuthorIcon}" alt="${i18n().co_author_icon}"/></a></div>
|
||||
<div class="collaboratorship-link">
|
||||
<h3><a href="${coauthorshipURL}" title="${i18n().co_author_network}">${i18n().co_author_network}</a></h3>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div style="clear:both;"></div>
|
||||
|
||||
|
||||
<#if (numOfCoInvestigations?? && numOfCoInvestigations > 0) || (numOfInvestigators?? && numOfInvestigators > 0) >
|
||||
|
||||
<div id="bodyPannel">
|
||||
<div id="chord" style="float: right;"></div>
|
||||
</div>
|
||||
</#if>
|
||||
|
||||
|
||||
<#if (numOfInvestigators?? && numOfInvestigators > 0) >
|
||||
|
||||
<#-- Sparkline -->
|
||||
<div id="sparkline-container-full">
|
||||
|
||||
<#assign displayTable = false />
|
||||
|
||||
<#assign sparklineVO = egoGrantSparklineVO />
|
||||
<div id="grant-count-sparkline-include"><#include "personGrantSparklineContent.ftl"></div>
|
||||
|
||||
<#assign sparklineVO = uniqueCoInvestigatorsSparklineVO />
|
||||
<div id="coinvestigator-count-sparkline-include"><#include "coInvestigationSparklineContent.ftl"></div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="vis_stats_full">
|
||||
|
||||
<div class="sub_headings" id="table_heading"><h3>${i18n().tables_capitalized}</h3></div>
|
||||
<p style="float:left;font-size:.9em">${i18n().grant_info_for_all_years} <img class="filterInfoIcon" width="16px" height="16px" id="imageIconThree" src="${urls.images}/iconInfo.png" alt="${i18n().info_icon}" title="${i18n().grant_sparkline_note}" /></p>
|
||||
|
||||
<div style="clear:both"></div>
|
||||
|
||||
<div class="vis-tables">
|
||||
|
||||
<p id="grants_table_container" class="datatable">
|
||||
|
||||
<#assign tableID = "grant_data_table" />
|
||||
<#assign tableCaption = "${i18n().grants_per_year}" />
|
||||
<#assign tableActivityColumnName = "${i18n().grants_capitalized}" />
|
||||
<#assign tableContent = egoGrantSparklineVO.yearToActivityCount />
|
||||
<#assign fileDownloadLink = egoGrantSparklineVO.downloadDataLink />
|
||||
|
||||
<#include "yearToActivityCountTable.ftl">
|
||||
|
||||
</p>
|
||||
|
||||
</div>
|
||||
|
||||
<#if (numOfCoInvestigations?? && numOfCoInvestigations > 0) >
|
||||
|
||||
<div class="vis-tables">
|
||||
|
||||
<p id="coinve_table_container" class="datatable">
|
||||
<#assign tableID = "coinvestigations_table" />
|
||||
<#assign tableCaption = "${i18n().co_investigator_s_capitalized} " />
|
||||
<#assign tableCollaboratorColumnName = "${i18n().investigator_capitalized}" />
|
||||
<#assign tableActivityColumnName = "${i18n().grants_with}" />
|
||||
<#assign tableContent = coInvestigatorData />
|
||||
<#assign fileDownloadLink = uniqueCoInvestigatorsSparklineVO.downloadDataLink />
|
||||
|
||||
<#include "collaboratorToActivityCountTable.ftl">
|
||||
</p>
|
||||
</div>
|
||||
|
||||
</#if>
|
||||
|
||||
<div style="clear:both"></div>
|
||||
|
||||
</div>
|
||||
|
||||
</#if>
|
||||
|
||||
</div>
|
||||
<div id="chord-info-div" style="display: none;"></div>
|
|
@ -15,6 +15,23 @@
|
|||
<div class="staticPageBackground">
|
||||
<div id="${visContainerID}">
|
||||
<script type="text/javascript">
|
||||
<#if sparklineVO.shortVisMode>
|
||||
var visualizationOptions = {
|
||||
width: 150,
|
||||
height: 60,
|
||||
color: '3399CC',
|
||||
chartType: 'ls',
|
||||
chartLabel: 'r'
|
||||
};
|
||||
<#else>
|
||||
var visualizationOptions = {
|
||||
width: 250,
|
||||
height: 75,
|
||||
color: '3399CC',
|
||||
chartType: 'ls',
|
||||
chartLabel: 'r'
|
||||
};
|
||||
</#if>
|
||||
|
||||
function drawPubCountVisualization(providedSparklineImgTD) {
|
||||
|
||||
|
@ -50,21 +67,8 @@
|
|||
maxValue: '${sparklineVO.latestRenderedPublicationYear?c}'
|
||||
}]));
|
||||
|
||||
var visualizationOptions = {
|
||||
width: 150,
|
||||
height: 60,
|
||||
color: '3399CC',
|
||||
chartType: 'ls',
|
||||
chartLabel: 'r'
|
||||
}
|
||||
<#else>
|
||||
var visualizationOptions = {
|
||||
width: 250,
|
||||
height: 75,
|
||||
color: '3399CC',
|
||||
chartType: 'ls',
|
||||
chartLabel: 'r'
|
||||
}
|
||||
|
||||
</#if>
|
||||
|
||||
|
||||
|
@ -247,7 +251,7 @@
|
|||
var row = $('<tr>');
|
||||
sparklineImgTD = $('<td>');
|
||||
sparklineImgTD.attr('id', '${sparklineContainerID}_img');
|
||||
sparklineImgTD.attr('width', '150');
|
||||
sparklineImgTD.attr('width', visualizationOptions.width);
|
||||
sparklineImgTD.attr('class', 'sparkline_style');
|
||||
|
||||
row.append(sparklineImgTD);
|
||||
|
|
|
@ -5,7 +5,10 @@ package edu.cornell.mannlib.vitro.webapp.visualization.personlevel;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
|
||||
import edu.cornell.mannlib.vitro.webapp.visualization.collaborationutils.CoAuthorshipData;
|
||||
import edu.cornell.mannlib.vitro.webapp.visualization.visutils.CollaborationDataViewHelper;
|
||||
import org.apache.axis.utils.StringUtils;
|
||||
import org.apache.commons.logging.Log;
|
||||
|
||||
import com.hp.hpl.jena.query.Dataset;
|
||||
|
@ -239,6 +242,12 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler {
|
|||
|
||||
String standaloneTemplate = "coAuthorPersonLevel.ftl";
|
||||
|
||||
String property = ConfigurationProperties.getBean(vitroRequest).getProperty("visualization.d3");
|
||||
if ("enabled".equalsIgnoreCase(property)) {
|
||||
body.put("coAuthorshipData", new CollaborationDataViewHelper(coAuthorshipVO));
|
||||
standaloneTemplate = "coAuthorPersonLevelD3.ftl";
|
||||
}
|
||||
|
||||
body.put("egoURIParam", egoURI);
|
||||
|
||||
body.put("egoLocalName", UtilityFunctions.getIndividualLocalName(egoURI, vitroRequest));
|
||||
|
@ -291,6 +300,12 @@ public class PersonLevelRequestHandler implements VisualizationRequestHandler {
|
|||
|
||||
String standaloneTemplate = "coPIPersonLevel.ftl";
|
||||
|
||||
String property = ConfigurationProperties.getBean(vitroRequest).getProperty("visualization.d3");
|
||||
if ("enabled".equalsIgnoreCase(property)) {
|
||||
body.put("coInvestigatorData", new CollaborationDataViewHelper(coPIVO));
|
||||
standaloneTemplate = "coPIPersonLevelD3.ftl";
|
||||
}
|
||||
|
||||
body.put("egoGrantSparklineVO", egoGrantSparklineVO);
|
||||
body.put("uniqueCoInvestigatorsSparklineVO", uniqueCopisSparklineVO);
|
||||
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||
|
||||
package edu.cornell.mannlib.vitro.webapp.visualization.visutils;
|
||||
|
||||
import edu.cornell.mannlib.vitro.webapp.visualization.collaborationutils.CollaborationData;
|
||||
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Collaboration;
|
||||
import edu.cornell.mannlib.vitro.webapp.visualization.valueobjects.Collaborator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class CollaborationDataViewHelper {
|
||||
private static final int MAX_COLLABORATORS = 35;
|
||||
private CollaborationData data;
|
||||
|
||||
private List<Collaborator> collaborators = null;
|
||||
|
||||
private int[][] collaborationMatrix = null;
|
||||
|
||||
public CollaborationDataViewHelper(CollaborationData data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public int getCollaboratorsCount() {
|
||||
init(MAX_COLLABORATORS);
|
||||
return data.getCollaborators().size();
|
||||
}
|
||||
|
||||
public int[][] getCollaborationMatrix() {
|
||||
init(MAX_COLLABORATORS);
|
||||
return collaborationMatrix;
|
||||
}
|
||||
|
||||
public List<Collaborator> getCollaborators() {
|
||||
init(MAX_COLLABORATORS);
|
||||
return collaborators;
|
||||
}
|
||||
|
||||
private synchronized void init(int max) {
|
||||
if (collaborators != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
collaborators = new ArrayList<>(max);
|
||||
|
||||
// Find the top N collaborators
|
||||
|
||||
// Threshold is the lowest number of activities currently in the table
|
||||
// Start at maximum possible value
|
||||
int threshold = Integer.MAX_VALUE;
|
||||
|
||||
// Iterate through each collaborator
|
||||
for (Collaborator collaborator : data.getCollaborators()) {
|
||||
|
||||
// Only include the collaborator if it isn't the focus of the view
|
||||
if (collaborator.getCollaboratorID() != data.getEgoCollaborator().getCollaboratorID()) {
|
||||
|
||||
// If the number of activities exceeds the threshold, it needs to be included in the top N
|
||||
if (collaborator.getNumOfActivities() > threshold) {
|
||||
// If we've filled the Top N
|
||||
if (collaborators.size() == max - 1) {
|
||||
// Remove the last (lowest) entry of the Top N
|
||||
collaborators.remove(collaborators.size() - 1);
|
||||
}
|
||||
|
||||
// Find the place to insert the new entry
|
||||
int insert = collaborators.size();
|
||||
while (insert > 0) {
|
||||
insert--;
|
||||
if (collaborators.get(insert).getNumOfActivities() > collaborator.getNumOfActivities()) {
|
||||
insert++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (insert < 0) {
|
||||
// If we didn't find a place to insert, insert it at the start
|
||||
collaborators.add(0, collaborator);
|
||||
} else if (insert < collaborators.size()) {
|
||||
// If the insert position is before the end of the list, insert at that position
|
||||
collaborators.add(insert, collaborator);
|
||||
} else {
|
||||
// Otherwise, add to the end of the list
|
||||
collaborators.add(collaborator);
|
||||
}
|
||||
|
||||
// Update the threshold with the new lowest position entry
|
||||
threshold = collaborators.get(collaborators.size() - 1).getNumOfActivities();
|
||||
} else {
|
||||
// If we are below the threshold, check if the top N is full
|
||||
if (collaborators.size() < max - 1) {
|
||||
// Top N is incomplete, so add to the end of the list
|
||||
collaborators.add(collaborator);
|
||||
|
||||
// And record the new collaboration as the threshold
|
||||
threshold = collaborator.getNumOfActivities();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now add the person that is the focus to the start of the list
|
||||
collaborators.add(0, data.getEgoCollaborator());
|
||||
|
||||
// Generate a list of collaborator IDs for use in filling the matrix
|
||||
List<Integer> collabIDs = new ArrayList<Integer>(collaborators.size());
|
||||
for (Collaborator collaborator : collaborators) {
|
||||
collabIDs.add(collaborator.getCollaboratorID());
|
||||
}
|
||||
|
||||
// If we only want to visualize collaborations between the main focus and others, set this to false
|
||||
boolean fullMatrix = true;
|
||||
|
||||
// Initialise the matrix
|
||||
collaborationMatrix = new int[collaborators.size()][collaborators.size()];
|
||||
|
||||
// For every row in the matrix
|
||||
for (int x = 0; x < collaborators.size(); x++) {
|
||||
// Get the collaborator associated with this row
|
||||
Collaborator collaboratorX = collaborators.get(x);
|
||||
|
||||
// Generate a list of possible collaborations for this row
|
||||
List<Collaboration> possibleCollaborations = new ArrayList<>();
|
||||
|
||||
// Go through all of the collaborations
|
||||
for (Collaboration collaboration : data.getCollaborations()) {
|
||||
// Get the collaborators
|
||||
Collaborator source = collaboration.getSourceCollaborator();
|
||||
Collaborator target = collaboration.getTargetCollaborator();
|
||||
|
||||
// If the collaborator for this row is involved in the collaboration, add it to the list of possibles
|
||||
if (source.getCollaboratorID() == collaboratorX.getCollaboratorID() || target.getCollaboratorID() == collaboratorX.getCollaboratorID()) {
|
||||
possibleCollaborations.add(collaboration);
|
||||
}
|
||||
}
|
||||
|
||||
// For every column in the matrix
|
||||
for (int y = 0; y < collaborators.size(); y++) {
|
||||
// Get the collaborator associated with this column
|
||||
Collaborator collaboratorY = collaborators.get(y);
|
||||
|
||||
// If this is the first row, first column, or we are creating a full matrix of all collaborations
|
||||
if (x == 0 || y == 0 || fullMatrix) {
|
||||
// Go through all of the possible collaborations
|
||||
for (Collaboration collaboration : possibleCollaborations) {
|
||||
// Get the collaborators
|
||||
Collaborator source = collaboration.getSourceCollaborator();
|
||||
Collaborator target = collaboration.getTargetCollaborator();
|
||||
|
||||
// If the source is the row collaborator and the target is the column collaborator
|
||||
if (source.getCollaboratorID() == collaboratorX.getCollaboratorID() && target.getCollaboratorID() == collaboratorY.getCollaboratorID()) {
|
||||
// Add the number of collaborations to the matrix, and stop processing collaborations
|
||||
collaborationMatrix[x][y] = collaboration.getNumOfCollaborations();
|
||||
break;
|
||||
}
|
||||
|
||||
// If the source is the column collaborator and the target is the row collaborator
|
||||
if (source.getCollaboratorID() == collaboratorY.getCollaboratorID() && target.getCollaboratorID() == collaboratorX.getCollaboratorID()) {
|
||||
// Add the number of collaborations to the matrix, and stop processing collaborations
|
||||
collaborationMatrix[x][y] = collaboration.getNumOfCollaborations();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the activity count for the top left matrix entry (focus - focus collaboration)
|
||||
collaborationMatrix[0][0] = 0;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue