dashboard
Version:
Create dashboards with gadgets on node.js
453 lines (372 loc) • 13.4 kB
text/xml
xml version="1.0" encoding="UTF-8"
<Module>
<ModulePrefs title="Color Magnitude Diagram">
<Require feature="locked-domain" />
<Require feature="dynamic-height"/>
<Require feature="opensocial-0.8"/>
<Require feature="minimessage"/>
</ModulePrefs>
<Content type="html"><![CDATA[
<!-- chart dependencies -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js" type="text/javascript"></script>
<script src="http://sky.astro.washington.edu/gadgets/highcharts/highcharts.js" type="text/javascript"></script>
<div id="divSelections" style="width: 100%;">
<table>
<TBODY>
<TR>
<td>
</td>
</TR>
<TR>
<td>
<input id="btDoHR" onclick="hr.plotHR();" type="button" value="Plot Color Magnitude"/>
</td>
<td>
<img id="imgSpinner" src="images/spinnerGrey.gif" style="display:none" />
</td>
<td>
<div id="divStatusText"></div>
</td>
</TR>
<!-- <TR>
<td>
<input type='checkbox' id='ckViewUnselected' onclick="hr.toggleViewUnselected();"/>
View unselected
</td>
</TR>
-->
</TBODY>
</table>
</div>
<div id="divChart1">
</div>
<script src="http://sky.astro.washington.edu/gadgets/js/gDataInterface.js" type="text/javascript"></script>
<script src="http://sky.astro.washington.edu/gadgets/js/astroObjectLib.js" type="text/javascript"></script>
<script type="text/javascript">
// Plot (hr) object is global
var hr = null,
debug = true;
// Writes to the console if debug (global) is true
function debugLog(msg){
if ((debug === true) && (window.console && console.log)) {
console.log(GADGET_NAME + ": " + msg);
}
return;
}
// GLOBAL CONSTANTS
var GADGET_NAME = "Color_Magnitude" + "_" + Math.floor(Math.random()*100000+1).toString();
var chart1; // globally available
var ICON_URL_SELECTED = 'http://sky.astro.washington.edu/gadgets/images/target_yellow.png',
ICON_URL_DEFAULT = 'http://sky.astro.washington.edu/gadgets/images/target.png';
// Writes to the console if debug (global) is true
function debugLog(msg){
if ((debug === true) && (window.console && console.log)) {
console.log(GADGET_NAME + ": " + msg);
}
return;
}
// create HR object
function init(){
hr = new Plotter();
gadgets.window.adjustHeight();
}
function Plotter(){
var my = new Object();
// CONSTANTS
var DEFAULT_NAMESPACE = "NS1",
MM_TIMER_DURATION = 4,
PLOT_HEIGHT = 400,
PLOT_WIDTH = 300;
// PRIVATE
var _namespaceList = [ DEFAULT_NAMESPACE ], // list of our current Namespaces. Just init with the default
_objList = [],
_lastSelectedObjs = [];
// Private Helper Variables
var di = new gDataInterface(GADGET_NAME, DEFAULT_NAMESPACE); // make dataInterface object, init with default
var miniMsg = new gadgets.MiniMessage();// make MiniMessage object
// INIT
var msg = miniMsg.createStaticMessage("Attempting to register gadget...");
di.registerMe( { gadgetName : GADGET_NAME,
namespaceList : _namespaceList,
variableList : [ "VP_Coord", "Active_Point_List", "VP_Point_List" ],
triggerList : [],
successCallback : registrationSuccess,
failureCallback : registrationFailure
} );
// Callback after successful registration
function registrationSuccess(){
debugLog('Registration successful');
if (msg) {
miniMsg.dismissMessage(msg);
// free up msg
msg = null;
miniMsg.createTimerMessage("Registration Succesful.", MM_TIMER_DURATION);
}
}
// Callback after a failure of registration
// displays message showing failure
function registrationFailure(){
debugLog('Registration FAILED!');
miniMsg.dismissMessage(msg);
miniMsg.createDismissibleMessage("Unable to register gadget.\nWe cannot communicate with other gadgets.");
}
// PUBLIC METHODS
my.plotHR = function() {
// TODO: other ways to choose the bounds we want on the gadget
showSpinner(true, "Getting objects...");
// disappear the chart
showVisualization(false);
// get current VP bounds
// bounds is array of CelestialCoordinates: [topLeft, bottomRight]
var bounds = di.readVariable(DEFAULT_NAMESPACE, "VP_Current_Bounds");
if (bounds === null){
alert('Set bounds');
showSpinner(false, "");
return;
}
// get objects within bounds from catalogue
// multiply ra by 15 to convert to degrees
// TODO: option for other catalogues
var maxObjs = 500;
var sdssQueryData = {cmd: "SELECT TOP " + maxObjs + " objid,modelMag_g,modelMag_r,modelMag_i,ra,dec FROM PhotoPrimary WHERE ra BETWEEN " +
bounds[0].getRa() * 15 + " AND " +
bounds[1].getRa() * 15 + " AND dec BETWEEN " +
bounds[1].getDec() + " AND " + bounds[0].getDec() +
" AND modelMag_g > -9999" +
" ORDER BY modelMag_g ASC",
format: "xml" };
// var sdssQueryData = {cmd: "SELECT TOP 500 p.ra,p.dec,p.type,p.modelmag_g,p.modelmag_r,p.modelmag_i,p.run,p.rerun,p.camcol,p.field,p.obj,p.objid,dbo.fIAUFromEq(p.ra,p.dec),r.z,r.Zerr FROM Galaxy as p, photoz as r WHERE p.ObjID=r.ObjID and p.modelmag_r<21 and p.ra<" + bounds[0].getRa() * 15 + " and p.ra>" + bounds[1].getRa() * 15 + " and p.dec>" + bounds[1].getDec() + " and p.dec<" + bounds[0].getDec() + " order by p.modelmag_r",
// format: "xml" };
url = 'http://cas.sdss.org/public/en/tools/search/x_sql.asp';
makeGETRequest(url, sdssQueryData, sdssResponseCB);
}
function makeGETRequest(url, data, callback) {
var params = {};
getdata = gadgets.io.encodeValues(data);
params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;
url = url + '?' + getdata;
gadgets.io.makeRequest(url, callback, params);
}
function sdssResponseCB(obj) {
// parse the XML
if (obj.errors.length > 0){
// errors
debugLog(obj.errors);
showSpinner(false, 'Service: ' + obj.errors);
return;
}
else if (obj.text === ""){
// returned empty string
showSpinner(false, 'Service returned empty string');
return;
}
//alert(obj.text);
xmlDoc = xmlStringToDoc(obj.text);
// walk XML to create points and write to objectData
// TODO: make objectData with tree widget
var objDataText = [];
var pointsList = [];
var rows = xmlDoc.getElementsByTagName('Row');
if (rows.length === 0){
// no rows
showSpinner(false, 'No Objects');
}
else if ((rows.length === 1) && (rows[0].textContent.indexOf('No rows returned') !== -1)){
// the special case answer is that no rows were returned
showSpinner(false, 'No Objects');
return;
}
// We probably have valid data at this point, so parse it and display it
// Write total # rows to the gadget display
objDataText.push("<b>Total Objects: " + rows.length + "</b></br>");
for (var i=0,len=rows.length; i<len; i++){
var row = rows[i];
var cc = new UW.astro.CelestialCoordinate(0,0);
var cObj = new UW.astro.CelestialObject();
// loop through attributes
for (var k=0, kLen=row.attributes.length; k<kLen; k++){
// k is the attribute index
var attName = row.attributes[k].nodeName;
var attValue = row.attributes[k].nodeValue;
cc.appendDescription('<b>' + attName + "</b>: " + attValue + "</br>");
// TODO: make an SDSS Data table inside the description
// set all the cc properties
switch(attName){
case "ra":
// divide ra by 15 to convert to hours
cc.setRa(attValue /15);
break;
case "dec":
cc.setDec(attValue);
break;
case "modelMag_g":
cObj.setGMag(attValue);
break;
case "modelMag_r":
cObj.setRMag(attValue);
break;
}
// add text for gadget display
objDataText.push(attName + ": " + attValue + "</br>");
}
cObj.setCelestialCoord(cc);
// add point to the list
pointsList.push(cObj);
}
// write the points to the scatter plot
plotPointsList(pointsList);
showSpinner(false, "");
}
/// selected stuf do this!
// pubList.setModifiedById(id, true);
///
function setSelectedByMinMax(xMin, xMax, yMin, yMax) {
alert('x: ' + xMin + ', ' + xMax + '\ny: ' + yMin + ', ' + yMax);
// debugLog('x: ' + xMin + ', ' + xMax + '\ny: ' + yMin + ', ' + yMax);
// loop through all points and set the selected ones
// x axis is g-r
// y axis is r
var pubList = di.readVariable(DEFAULT_NAMESPACE, "VP_Point_List");
// turn last selected back to red
//alert('_lastSelectedObjs.length: '+_lastSelectedObjs.length)
for (var i=0, len=_lastSelectedObjs.length; i<len; i++) {
var id = _lastSelectedObjs[i].getCelestialCoord().getCObjId();
var p = pubList.getItemById(id);
if (p !== null) {
p.setIconUrl(ICON_URL_DEFAULT);
pubList.setModifiedById(id, true);
}
}
_lastSelectedObjs = [];
for (var i=0, len=_objList.length; i<len; i++) {
var obj = _objList[i];
var cc = obj.getCelestialCoord();
var id = cc.getCObjId();
var g = obj.getGMag();
var r = obj.getRMag();
if (g-r > xMin && g-r < xMax && r > yMin && r < yMax) {
var p = pubList.getItemById(id);
if (p !== null) {
p.setIconUrl(ICON_URL_SELECTED);
pubList.setModifiedById(id, true);
_lastSelectedObjs.push(obj);
}
}
}
di.writeVariable(DEFAULT_NAMESPACE, "VP_Point_List", pubList);
}
// plots the g-r vs. g on the color-magnitude diagram
// @param pList: is an array of celestial coordinates
// with g and r as properties
function plotPointsList(pList) {
var graphData = [];
// clear the points list
_objList = [];
// write the points to the public point list
var pubList = di.readVariable(DEFAULT_NAMESPACE, "VP_Point_List");
if (pubList === null){
pubList = new UW.astro.UniqIdList();
}
for (var i=0, len=pList.length; i<len; i++) {
var cObj = pList[i];
var g = Math.round(cObj.getGMag() * 10000000) / 10000000; // round to 7 decimal places
var r = Math.round(cObj.getRMag() * 10000000) / 10000000; // round to 7 decimal places
if ((g !== null) && (r !== null)) {
var g_r = Math.round((g-r) * 10000000) / 10000000;
// only display -1 < g-r < 3
if ((g_r >= -1) && (g_r <= 3)) {
graphData.push( [g_r, r] );
// add this point to the points list
_objList.push(cObj);
var id = pubList.append(cObj.getCelestialCoord()); // returns item id
cObj.getCelestialCoord().setCObjId(id);
}
}
}
$(document).ready(function() {
chart1 = new Highcharts.Chart({
chart: {
renderTo: 'divChart1',
defaultSeriesType: 'scatter',
zoomType: 'xy',
events : {
selection: function(event) {
event.preventDefault();
setSelectedByMinMax(event.xAxis[0].min, event.xAxis[0].max, event.yAxis[0].min, event.yAxis[0].max);
}
}
},
title: {
text: 'Color Magnitude'
},
xAxis: {
title: {
enabled: true,
text: 'g - r'
},
startOnTick: true,
endOnTick: true,
showLastLabel: true
},
yAxis: {
title: {
text: 'r'
},
reversed: true
},
series: [{
name: 'Set 1',
data: graphData
}]
});
});
document.getElementById('divChart1').style.height = PLOT_HEIGHT + "px";
di.writeVariable(DEFAULT_NAMESPACE, "VP_Point_List", pubList);
showVisualization(true);
}
toggleViewUnselected = function() {
}
// HELPER
function isViewUnselected(view) {
return document.getElementById('ckViewUnselected').checked;
}
function showVisualization(show) {
if (show) {
document.getElementById('divChart1').style.display = "block";
}
else {
document.getElementById('divChart1').style.display = "hidden";
}
gadgets.window.adjustHeight();
}
function showSpinner(show, text){
// set text status
document.getElementById('divStatusText').innerHTML = text;
if (show){
document.getElementById('imgSpinner').style.visibility = 'block';
}
else{
document.getElementById('imgSpinner').style.visibility = 'hidden';
}
}
function xmlStringToDoc(text){
if (window.DOMParser){
parser=new DOMParser();
xmlDoc=parser.parseFromString(text,"text/xml");
}
else // Internet Explorer
{
xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
xmlDoc.async="false";
xmlDoc.loadXML(text);
}
// TODO: test to verify its created
return xmlDoc;
}
return my;
}
gadgets.util.registerOnLoadHandler(init);
</script>
]]>
</Content>
</Module>