|
1 |
/***************************************
|
|
2 |
* Copyright 2010-2013 CNES - CENTRE NATIONAL d'ETUDES SPATIALES
|
|
3 |
*
|
|
4 |
* This file is part of SITools2.
|
|
5 |
*
|
|
6 |
* SITools2 is free software: you can redistribute it and/or modify
|
|
7 |
* it under the terms of the GNU General Public License as published by
|
|
8 |
* the Free Software Foundation, either version 3 of the License, or
|
|
9 |
* (at your option) any later version.
|
|
10 |
*
|
|
11 |
* SITools2 is distributed in the hope that it will be useful,
|
|
12 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14 |
* GNU General Public License for more details.
|
|
15 |
*
|
|
16 |
* You should have received a copy of the GNU General Public License
|
|
17 |
* along with SITools2. If not, see <http://www.gnu.org/licenses/>.
|
|
18 |
***************************************/
|
|
19 |
/*global Ext, sitools, projectGlobal, commonTreeUtils, showResponse, DEFAULT_PREFERENCES_FOLDER,
|
|
20 |
document, i18n, $, Flotr, userLogin, SitoolsDesk, sql2ext, loadUrl,SitoolsDesk,,
|
|
21 |
SITOOLS_DATE_FORMAT, SITOOLS_DEFAULT_IHM_DATE_FORMAT, DEFAULT_LIVEGRID_BUFFER_SIZE*/
|
|
22 |
/*
|
|
23 |
* @include "../viewDataDetail/viewDataDetail.js"
|
|
24 |
* @include "../../sitoolsProject.js"
|
|
25 |
* @include "../../desktop/desktop.js"
|
|
26 |
* @include "../../desktop/navProfile/fixed.js"
|
|
27 |
*/
|
|
28 |
/**
|
|
29 |
*
|
|
30 |
* <a href="https://sourceforge.net/tracker/?func=detail&aid=3313793&group_id=531341&atid=2158259">[3313793]</a><br/>
|
|
31 |
* 16/06/2011 m.gond {Display the right number of data plotted} <br/>
|
|
32 |
*
|
|
33 |
* ExtJS layout for plotting data
|
|
34 |
*/
|
|
35 |
|
|
36 |
Ext.namespace('sitools.user.component');
|
|
37 |
/**
|
|
38 |
* @cfg {String} dataUrl the dataset url attachment
|
|
39 |
* @cfg {} columnModel the dataset's column model
|
|
40 |
* @cfg {} filters the list of filters to apply (filters from the dataview)
|
|
41 |
* @cfg {String} selections the selections as a String to add to the URL (selections from the dataview)
|
|
42 |
* @cfg {String} datasetName the name of the dataset
|
|
43 |
* @cfg {} formParam list of parameters from a query form
|
|
44 |
* @cfg {} formMultiDsParams list of parameters from a multidataset query form
|
|
45 |
* @cfg {String} datasetId the id of the dataset
|
|
46 |
* @cfg {string} componentType Should be "plot"
|
|
47 |
* @requires sitools.user.component.viewDataDetail
|
|
48 |
* @class sitools.user.component.viewCubeService
|
|
49 |
* @extends Ext.Panel
|
|
50 |
*/
|
|
51 |
|
|
52 |
sitools.user.component.viewCubeService = function (config) {
|
|
53 |
|
|
54 |
Ext.apply(this, config);
|
|
55 |
|
|
56 |
this.datasetName = config.datasetName;
|
|
57 |
this.datasetId = config.datasetId;
|
|
58 |
this.columnModel = config.columnModel;
|
|
59 |
var mapCanvasID,selCanvasID,canHistoID,sliderColorID,controlHistoID;
|
|
60 |
|
|
61 |
var rec;
|
|
62 |
if (Ext.isEmpty(this.record)) {
|
|
63 |
rec = config.dataview.getSelections()[0];
|
|
64 |
}else{
|
|
65 |
rec = this.record;
|
|
66 |
}
|
|
67 |
|
|
68 |
var naxis1, naxis2, naxis3, sizePix;
|
|
69 |
|
|
70 |
var selectionType = "pixel";
|
|
71 |
var slice;
|
|
72 |
var imageSlice;
|
|
73 |
var limitVal = [];
|
|
74 |
var pixelSelected = [];
|
|
75 |
var colors = [];
|
|
76 |
|
|
77 |
this.tabPanel = new Ext.TabPanel({ name:'tabPanel',region : 'center',autoScroll : true});
|
|
78 |
var itemsTab = [];
|
|
79 |
|
|
80 |
this.panels = new Ext.Panel({ name:'panels', title: 'Cube Explorer', layout: 'table', layoutConfig: {columns:2},autoScroll : true });
|
|
81 |
var itemsPanels = [];
|
|
82 |
|
|
83 |
// Searching for primary key name
|
|
84 |
var primaryKeyName = "";
|
|
85 |
Ext.each(rec.fields.items, function (field) {
|
|
86 |
if (field.primaryKey) { primaryKeyName = field.name; }
|
|
87 |
});
|
|
88 |
var primaryKeyValue = rec.get(primaryKeyName);
|
|
89 |
var request = "?1=1&p[0]=LISTBOXMULTIPLE|" + primaryKeyName + "|" + primaryKeyValue + "|";
|
|
90 |
|
|
91 |
Ext.Ajax.on('beforerequest', function(connection,options){ Ext.getBody().mask('Retrieving data from fits file...'); });
|
|
92 |
Ext.Ajax.on('requestcomplete', function(connection,options){ Ext.getBody().unmask(); });
|
|
93 |
Ext.Ajax.on('requestexception', function(connection,options){ Ext.getBody().unmask(); });
|
|
94 |
|
|
95 |
Ext.Ajax.request({
|
|
96 |
url : this.dataview.sitoolsAttachementForUsers+"/plugin/getFitsDataSpectro"+request,
|
|
97 |
method : "GET",
|
|
98 |
scope : this,
|
|
99 |
waitMsg : 'Processing your request...',
|
|
100 |
success : function (ret) {
|
|
101 |
var json = Ext.decode(ret.responseText);
|
|
102 |
naxis1 = json.NAXIS1;
|
|
103 |
naxis2 = json.NAXIS2;
|
|
104 |
naxis3 = json.NAXIS3;
|
|
105 |
var imageWidth, imageHeight;
|
|
106 |
var margin = 0;
|
|
107 |
var destopHeight = Ext.get("x-desktop").getHeight() - 50 - 4*margin;
|
|
108 |
var destopWidth = Ext.get("x-desktop").getWidth();
|
|
109 |
var controlHeight = 200;
|
|
110 |
var controlWidth = 400;
|
|
111 |
var imageHeightWanted = destopHeight - controlHeight;
|
|
112 |
|
|
113 |
sizePix = Math.floor(imageHeightWanted/naxis2);
|
|
114 |
imageWidth = naxis1 * sizePix;
|
|
115 |
imageHeight = naxis2 * sizePix;
|
|
116 |
slice = parseInt(naxis3/2);
|
|
117 |
var layersZone = "";
|
|
118 |
// layer for map
|
|
119 |
mapCanvasID = "mapCanvas"+getAnId();
|
|
120 |
layersZone = layersZone + '<canvas id="'+mapCanvasID+'"+ style="z-index: 1; position:absolute; left:0px; top:0px;" width="'+imageWidth+'" height="'+imageHeight+'"></canvas>';
|
|
121 |
// layer for selection tool
|
|
122 |
selCanvasID = "selCanvas"+getAnId();
|
|
123 |
layersZone = layersZone + '<canvas id="'+selCanvasID+'" style="z-index: 2; position:absolute; left:0px; top:0px;" width="'+imageWidth+'" height="'+imageHeight+'"></canvas>';
|
|
124 |
|
|
125 |
var map = new Ext.Panel({
|
|
126 |
id: 'panelImage',
|
|
127 |
region: 'west',
|
|
128 |
html: layersZone,
|
|
129 |
width: imageWidth,
|
|
130 |
height: imageHeight,
|
|
131 |
});
|
|
132 |
itemsPanels.push(map);
|
|
133 |
|
|
134 |
var spectrum = new Ext.Panel({
|
|
135 |
id: 'panelSpectrum',
|
|
136 |
rowspan: 2,
|
|
137 |
width: destopWidth-Math.max(controlWidth,imageWidth),
|
|
138 |
height: destopHeight,
|
|
139 |
});
|
|
140 |
itemsPanels.push(spectrum);
|
|
141 |
|
|
142 |
var sliderDepth = new Ext.Slider({
|
|
143 |
id: 'sliderDepthID',
|
|
144 |
width: 114,
|
|
145 |
minValue: 0,
|
|
146 |
maxValue: json.WAVE.length-1,
|
|
147 |
value: parseInt(naxis3/2),
|
|
148 |
listeners : {
|
|
149 |
change: function(slider){
|
|
150 |
slice = slider.getValue();
|
|
151 |
plotColorHisto(slice,json,0,100);
|
|
152 |
Ext.getCmp('sliderColorID').setValue(0,0,false);
|
|
153 |
Ext.getCmp('sliderColorID').setValue(1,100,false);
|
|
154 |
drawMap(sizePix,json,slice,false,[]);
|
|
155 |
Ext.getCmp('wave').setValue('<b>'+slice+' - '+json.WAVE[slice].toFixed(2)+' ('+json.UNIT_WAVE+')</b>');
|
|
156 |
plotSpectra(pixelSelected,selectionType,json,spectrum,slice);
|
|
157 |
},
|
|
158 |
dragend: function(slider){
|
|
159 |
slice = slider.getValue();
|
|
160 |
limitVal = [];//plotColorHisto(slice,json,0,100);
|
|
161 |
plotColorHisto(slice,json,0,100);
|
|
162 |
drawMap(sizePix,json,slice,false,[]);
|
|
163 |
}
|
|
164 |
}
|
|
165 |
});
|
|
166 |
canHistoID= "canHisto"+getAnId();
|
|
167 |
var colorHisto = new Ext.Panel({
|
|
168 |
html: '<canvas id="'+canHistoID+'" width="'+120+'" height="'+50+'"></canvas>',
|
|
169 |
width: 120,
|
|
170 |
height: 50
|
|
171 |
});
|
|
172 |
sliderColorID = "sliderColor"+getAnId();
|
|
173 |
var sliderColor = new Ext.slider.MultiSlider({
|
|
174 |
id: sliderColorID,
|
|
175 |
width: 114,//parseInt(imageWidth/4),
|
|
176 |
minValue: 0,
|
|
177 |
maxValue: 100,
|
|
178 |
values: [0,100],
|
|
179 |
listeners : {
|
|
180 |
change: function(slider){
|
|
181 |
limitVal = plotColorHisto(slice,json,slider.thumbs[0].value,slider.thumbs[1].value);
|
|
182 |
drawMap(sizePix,json,slice,false,limitVal);
|
|
183 |
},
|
|
184 |
dragend: function(slider){
|
|
185 |
limitVal = plotColorHisto(slice,json,slider.thumbs[0].value,slider.thumbs[1].value);
|
|
186 |
drawMap(sizePix,json,slice,false,limitVal);
|
|
187 |
}
|
|
188 |
}
|
|
189 |
});
|
|
190 |
controlHistoID = "controlHisto"+getAnId();
|
|
191 |
var controlHisto = new Ext.Panel({
|
|
192 |
id: controlHistoID,
|
|
193 |
fieldLabel: "Slice color scale",
|
|
194 |
heigth: controlHeight,
|
|
195 |
xtype: 'compositefield',
|
|
196 |
items : [ sliderColor, colorHisto ]
|
|
197 |
});
|
|
198 |
controlPanelID = "controlPanel"+getAnId();
|
|
199 |
var controlForm = new Ext.form.FormPanel({
|
|
200 |
id: controlPanelID,
|
|
201 |
heigth: controlHeight,
|
|
202 |
width: controlWidth,
|
|
203 |
items : [{
|
|
204 |
fieldLabel: 'Coordinates',
|
|
205 |
xtype: 'compositefield',
|
|
206 |
items: [{ xtype: 'displayfield', value: 'RA'},
|
|
207 |
{ xtype: 'displayfield', id: 'ra_field', name : 'ra', width: 75 },
|
|
208 |
{ xtype: 'displayfield', value: 'DEC'},
|
|
209 |
{ xtype: 'displayfield', id: 'dec_field', name : 'dec', width: 75 }]
|
|
210 |
},
|
|
211 |
{
|
|
212 |
fieldLabel: 'Selection Type',
|
|
213 |
xtype: 'compositefield',
|
|
214 |
padding: '5px',
|
|
215 |
items: [{xtype: 'radiogroup',
|
|
216 |
width: parseInt(imageWidth/2),
|
|
217 |
listeners: {
|
|
218 |
change:function( radiogroup, newValue ) {
|
|
219 |
selectionType = newValue.inputValue;
|
|
220 |
// ORIGINAL can = document.getElementById('selCanvas');
|
|
221 |
can = document.getElementById(selCanvasID);
|
|
222 |
clearArea(can);
|
|
223 |
pixelSelected = [];
|
|
224 |
plotSpectra(pixelSelected,selectionType,json,spectrum,slice);
|
|
225 |
drawSelectionPlot(sizePix,spectrum,json,selectionType);
|
|
226 |
}
|
|
227 |
},
|
|
228 |
items: [{ inputValue: 'pixel', boxLabel: 'Pixel(s)', name: 'radioGroup', checked: true},
|
|
229 |
{ inputValue: 'line', boxLabel: 'Line', name: 'radioGroup' }/*,*/
|
|
230 |
]
|
|
231 |
},{
|
|
232 |
xtype: 'button',
|
|
233 |
width: 50,
|
|
234 |
height: 30,
|
|
235 |
text: 'Clear',
|
|
236 |
handler: function(){
|
|
237 |
// ORIGINAL can = document.getElementById('selCanvas');
|
|
238 |
can = document.getElementById(selCanvasID);
|
|
239 |
clearArea(can);
|
|
240 |
pixelSelected = [];
|
|
241 |
plotSpectra(pixelSelected,selectionType,json,spectrum,slice);
|
|
242 |
}
|
|
243 |
}
|
|
244 |
]
|
|
245 |
},{
|
|
246 |
fieldLabel: 'Cube Depth Index',
|
|
247 |
xtype: 'compositefield',
|
|
248 |
items: [sliderDepth,{id: 'wave', xtype: 'displayfield',value: '<b>'+sliderDepth.getValue()+' - '+json.WAVE[sliderDepth.getValue()].toFixed(2)+' ('+json.UNIT_WAVE+')</b>'/*,*/}]
|
|
249 |
},
|
|
250 |
controlHisto
|
|
251 |
]
|
|
252 |
});
|
|
253 |
itemsPanels.push(controlForm);
|
|
254 |
this.panels.add(itemsPanels);
|
|
255 |
this.panels.doLayout();
|
|
256 |
itemsTab.push(this.panels);
|
|
257 |
var headerPanel = new Ext.Panel({
|
|
258 |
title: 'Header(s)',
|
|
259 |
id: 'headerPanel',
|
|
260 |
autoScroll: true,
|
|
261 |
layout: 'accordion',
|
|
262 |
width: imageWidth+(imageHeight+controlHeight),
|
|
263 |
height: imageHeight+controlHeight,
|
|
264 |
});
|
|
265 |
|
|
266 |
itemsAccordion = [];
|
|
267 |
nbreHDUs = json.HDUs;
|
|
268 |
for (var i=0; i<nbreHDUs; i++){
|
|
269 |
var extension = "";
|
|
270 |
var extensionName = "Header "+i;
|
|
271 |
if (i==0) {extensionName = "Primary";}
|
|
272 |
var jsonHeader = [];
|
|
273 |
for (var j = 0; j < json.HEADERSGRID[i].length; j++) {
|
|
274 |
if (json.HEADERSGRID[i][j][0]=="EXTNAME") {extensionName=json.HEADERSGRID[i][j][1];}
|
|
275 |
if (json.HEADERSGRID[i][j][0]=="XTENSION") {extension=json.HEADERSGRID[i][j][1];}
|
|
276 |
extensionName = extensionName.charAt(0).toUpperCase() + extensionName.slice(1).toLowerCase();
|
|
277 |
jsonHeader.push({
|
|
278 |
key: json.HEADERSGRID[i][j][0],
|
|
279 |
value: json.HEADERSGRID[i][j][1],
|
|
280 |
description: json.HEADERSGRID[i][j][2]
|
|
281 |
});
|
|
282 |
}
|
|
283 |
var storeHeader = new Ext.data.JsonStore({
|
|
284 |
fields : ['key','value','description'],
|
|
285 |
});
|
|
286 |
storeHeader.loadData(jsonHeader, false);
|
|
287 |
var gridHeader = new Ext.grid.GridPanel({
|
|
288 |
title: "<html><b>"+i+" - "+extensionName+" - <font color='red'>"+extension+"</font></b></html>",
|
|
289 |
autoScroll: true,
|
|
290 |
layout: 'fit',
|
|
291 |
store : storeHeader,
|
|
292 |
colModel: new Ext.grid.ColumnModel({
|
|
293 |
columns: [{header: 'Key', width: 200, dataIndex: 'key', sortable: true},
|
|
294 |
{header: 'Value', width: 300, dataIndex: 'value'},
|
|
295 |
{header: 'Description', width: 600, dataIndex: 'description'},
|
|
296 |
]
|
|
297 |
})
|
|
298 |
});
|
|
299 |
itemsAccordion.push(gridHeader);
|
|
300 |
}
|
|
301 |
headerPanel.add(itemsAccordion);
|
|
302 |
itemsTab.push(headerPanel);
|
|
303 |
this.tabPanel.add(itemsTab);
|
|
304 |
this.tabPanel.setActiveTab(0);
|
|
305 |
this.tabPanel.doLayout();
|
|
306 |
|
|
307 |
plotColorHisto(slice,json,0,100);
|
|
308 |
drawMap(sizePix,json,slice,true,limitVal);
|
|
309 |
plotSpectra(pixelSelected,selectionType,json,spectrum,slice);
|
|
310 |
|
|
311 |
drawSelectionPlot(sizePix,spectrum,json,selectionType);
|
|
312 |
|
|
313 |
},
|
|
314 |
failure: function(){ alert("Ajax Request Failed !"); }
|
|
315 |
});
|
|
316 |
this.items = [this.tabPanel];
|
|
317 |
|
|
318 |
function getImageSlice(jSON,slice,limitValues) {
|
|
319 |
imageSlice = [];
|
|
320 |
for (var x = 0; x < naxis1; x++) {
|
|
321 |
for (var y = 0; y < naxis2; y++) {
|
|
322 |
b = jSON.SPECTRUM[x][(naxis2-1)-y][slice];
|
|
323 |
if (limitValues.length==0){
|
|
324 |
if (b!="NaN"){ imageSlice.push(b); }
|
|
325 |
} else {
|
|
326 |
if (b!="NaN" && b>limitValues[0] && b<limitValues[1]){ imageSlice.push(b); }
|
|
327 |
}
|
|
328 |
}
|
|
329 |
}
|
|
330 |
return imageSlice;
|
|
331 |
}
|
|
332 |
|
|
333 |
function drawMap(sizeRec, jSON, slice, init, limitValues) {
|
|
334 |
|
|
335 |
// ORIGINAL canMap = document.getElementById('mapCanvas');
|
|
336 |
canMap = document.getElementById(mapCanvasID);
|
|
337 |
ctxCube = canMap.getContext('2d');
|
|
338 |
if (init) { ctxCube.scale(sizeRec,sizeRec); }
|
|
339 |
drawSlice(jSON,slice,limitValues);
|
|
340 |
|
|
341 |
function drawSlice(jSON,slice,limitValues) {
|
|
342 |
|
|
343 |
imageSlice = getImageSlice(jSON,slice,limitValues);
|
|
344 |
if (imageSlice.length!=0) {
|
|
345 |
var min = Math.min.apply(Math, imageSlice);
|
|
346 |
var max = Math.max.apply(Math, imageSlice);
|
|
347 |
|
|
348 |
for (var x = 0; x < naxis1; x++) {
|
|
349 |
for (var y = 0; y < naxis2; y++) {
|
|
350 |
b = jSON.SPECTRUM[x][(naxis2-1)-y][slice];
|
|
351 |
if (b!="NaN"){
|
|
352 |
b = ((b - min)/(min+max))*256 | 0;
|
|
353 |
ctxCube.fillStyle = 'rgb('+b+','+b+','+b+')';
|
|
354 |
ctxCube.fillRect(x, y, 1, 1);
|
|
355 |
}
|
|
356 |
}
|
|
357 |
}
|
|
358 |
}
|
|
359 |
}
|
|
360 |
}
|
|
361 |
|
|
362 |
function clearArea(can) {
|
|
363 |
ctx = can.getContext('2d');
|
|
364 |
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
|
|
365 |
}
|
|
366 |
|
|
367 |
function drawSelectionPlot(sizeRec,containerSpec,jSON,selectionType) {
|
|
368 |
|
|
369 |
var can, ctx, canX, canY, lastX, lastY, mouseIsDown = false;
|
|
370 |
|
|
371 |
// Selection drawing
|
|
372 |
// ORIGINAL canOrig = document.getElementById('selCanvas');
|
|
373 |
canOrig = document.getElementById(selCanvasID);
|
|
374 |
can = canOrig.cloneNode(true);
|
|
375 |
canOrig.parentNode.replaceChild(can, canOrig);
|
|
376 |
|
|
377 |
ctx = can.getContext('2d');
|
|
378 |
ctx.strokeStyle = 'white';
|
|
379 |
ctx.lineWidth = 2;
|
|
380 |
|
|
381 |
|
|
382 |
clearArea(can);
|
|
383 |
pixelSelected = [];
|
|
384 |
colors = [];
|
|
385 |
|
|
386 |
can.addEventListener("mousedown", mouseDown);
|
|
387 |
can.addEventListener("mousemove", mouseMove);
|
|
388 |
can.addEventListener("mouseup", mouseUp);
|
|
389 |
|
|
390 |
function deg_to_dms (deg) {
|
|
391 |
var d = Math.floor (deg);
|
|
392 |
var minfloat = (deg-d)*60;
|
|
393 |
var m = Math.floor(minfloat);
|
|
394 |
var secfloat = (minfloat-m)*60;
|
|
395 |
var s = Math.round(secfloat);
|
|
396 |
if (s==60) { m++; s=0; }
|
|
397 |
if (m==60) { d++; m=0; }
|
|
398 |
return ("" + d + "°" + m + "'" + secfloat.toFixed(2) + '"');
|
|
399 |
}
|
|
400 |
|
|
401 |
function mouseDown(e) {
|
|
402 |
clearArea(can);
|
|
403 |
mouseIsDown = true;
|
|
404 |
var rect = can.getBoundingClientRect();
|
|
405 |
lastX = e.clientX - rect.left* (can.width / rect.width);
|
|
406 |
lastY = e.clientY - rect.top* (can.height / rect.height);
|
|
407 |
}
|
|
408 |
|
|
409 |
function mouseMove(e) {
|
|
410 |
var rect = can.getBoundingClientRect();
|
|
411 |
canX = e.clientX - rect.left;
|
|
412 |
canY = e.clientY - rect.top;
|
|
413 |
if (mouseIsDown) { drawSelection(lastX,lastY,canX,canY,selectionType); }
|
|
414 |
displayRaDec(canX,canY);
|
|
415 |
}
|
|
416 |
|
|
417 |
function mouseUp(e) {
|
|
418 |
mouseIsDown = false;
|
|
419 |
var rect = can.getBoundingClientRect();
|
|
420 |
canX = e.clientX- rect.left* (can.width / rect.width);
|
|
421 |
canY = e.clientY-rect.top* (can.height / rect.height);
|
|
422 |
drawSelectedPixels(lastX,lastY,canX,canY,selectionType);
|
|
423 |
}
|
|
424 |
|
|
425 |
function drawSelection(lastX, lastY, x, y, selectionType) {
|
|
426 |
clearArea(can);
|
|
427 |
ctx.strokeStyle = 'red';
|
|
428 |
|
|
429 |
if (selectionType=="line"){
|
|
430 |
ctx.beginPath();
|
|
431 |
ctx.moveTo(lastX, lastY);
|
|
432 |
ctx.lineTo(x, y);
|
|
433 |
ctx.stroke();
|
|
434 |
}
|
|
435 |
}
|
|
436 |
|
|
437 |
function displayRaDec(canX,canY) {
|
|
438 |
xFits = Math.floor(canX/sizeRec);
|
|
439 |
yFits = Math.floor(canY/sizeRec);
|
|
440 |
var ra = jSON.CRVAL1 + (xFits-(jSON.CRPIX1-1))*jSON.CDELT1;
|
|
441 |
var dec = jSON.CRVAL2 + (((naxis2-1)-(jSON.CRPIX2-1))-yFits)*jSON.CDELT2;
|
|
442 |
Ext.getCmp('ra_field').setValue('<b>'+deg_to_dms(ra)+'</b>');
|
|
443 |
Ext.getCmp('dec_field').setValue('<b>'+deg_to_dms(dec)+'</b>');
|
|
444 |
}
|
|
445 |
|
|
446 |
function allreadySelected(array,x,y){
|
|
447 |
for ( var pix = 0; pix<array.length; pix++) {
|
|
448 |
if ( array[pix][0]==x && array[pix][1]==y ) { return pix;}
|
|
449 |
}
|
|
450 |
return -1;
|
|
451 |
}
|
|
452 |
|
|
453 |
function hexaDecimalColor(i) {
|
|
454 |
function componentToHex(c) {
|
|
455 |
var hex = c.toString(16);
|
|
456 |
return hex.length == 1 ? "0" + hex : hex;
|
|
457 |
}
|
|
458 |
function rgbToHex(r, g, b) {
|
|
459 |
return "#" + componentToHex(r) + componentToHex(g) + componentToHex(b);
|
|
460 |
}
|
|
461 |
|
|
462 |
if (i%3 == 1) {return rgbToHex(0,Math.random()*256|0,Math.random()*256|0);}
|
|
463 |
if (i%3 == 2) {return rgbToHex(Math.random()*256|0,0,Math.random()*256|0);}
|
|
464 |
if (i%3 == 0) {return rgbToHex(Math.random()*256|0,Math.random()*256|0,0);}
|
|
465 |
|
|
466 |
}
|
|
467 |
|
|
468 |
function drawSelectedPixels(startx,starty,endx,endy,selectionType) {
|
|
469 |
|
|
470 |
clearArea(can);
|
|
471 |
|
|
472 |
if (selectionType=="pixel"){
|
|
473 |
xFits = Math.floor(startx/sizeRec);
|
|
474 |
yFits = Math.floor(starty/sizeRec);
|
|
475 |
|
|
476 |
if (jSON.SPECTRUM[xFits][(naxis2-1)-yFits][parseInt(naxis3/2)]!="NaN"){
|
|
477 |
if (allreadySelected(pixelSelected,xFits,yFits)!=-1){
|
|
478 |
var idx = allreadySelected(pixelSelected,xFits,yFits);
|
|
479 |
pixelSelected = pixelSelected.slice(0,idx).concat( pixelSelected.slice(idx+1) );
|
|
480 |
colors = colors.slice(0,idx).concat( colors.slice(idx+1) );
|
|
481 |
} else {
|
|
482 |
pixelSelected.push([xFits,yFits]);
|
|
483 |
colors.push(hexaDecimalColor(colors.length));
|
|
484 |
}
|
|
485 |
for ( var pixel = 0; pixel<pixelSelected.length; pixel++) {
|
|
486 |
xFits = pixelSelected[pixel][0];
|
|
487 |
yFits = pixelSelected[pixel][1];
|
|
488 |
ctx.strokeStyle = colors[pixel];
|
|
489 |
ctx.strokeRect(xFits*sizeRec+1,yFits*sizeRec+1,sizeRec-1,sizeRec-1);
|
|
490 |
}
|
|
491 |
}
|
|
492 |
}
|
|
493 |
|
|
494 |
if (selectionType=="line"){
|
|
495 |
|
|
496 |
pixelSelected = [];
|
|
497 |
colors = [];
|
|
498 |
|
|
499 |
startX = Math.floor(startx/sizeRec);
|
|
500 |
startY = Math.floor(starty/sizeRec);
|
|
501 |
endX = Math.ceil(endx/sizeRec);
|
|
502 |
endY = Math.ceil(endy/sizeRec);
|
|
503 |
slope = (endY-startY)/(endX-startX);
|
|
504 |
|
|
505 |
for (var x = Math.min(startX,endX); x <= Math.max(startX,endX); x++) {
|
|
506 |
if (slope>0) { y = Math.floor(slope*(x-Math.min(startX,endX))) + Math.min(startY,endY); }
|
|
507 |
else { y = Math.floor(slope*(x-Math.min(startX,endX))) + Math.max(startY,endY); }
|
|
508 |
if (jSON.SPECTRUM[x][(naxis2-1)-y][parseInt(naxis3/2)]!="NaN" ){
|
|
509 |
color = hexaDecimalColor(colors.length);
|
|
510 |
colors.push(color);
|
|
511 |
ctx.strokeStyle = color;
|
|
512 |
ctx.strokeRect(x*sizeRec+1,y*sizeRec+1,sizeRec-1,sizeRec-1);
|
|
513 |
pixelSelected.push([x,y]);
|
|
514 |
}
|
|
515 |
}
|
|
516 |
|
|
517 |
slope = (endX-startX)/(endY-startY);
|
|
518 |
for (var y = Math.min(startY,endY); y <= Math.max(startY,endY); y++) {
|
|
519 |
if (slope>0) { x = Math.floor(slope*(y-Math.min(startY,endY))) + Math.min(startX,endX); }
|
|
520 |
else { x = Math.floor(slope*(y-Math.min(startY,endY))) + Math.max(startX,endX); }
|
|
521 |
if (jSON.SPECTRUM[x][(naxis2-1)-y][parseInt(naxis3/2)]!="NaN" && allreadySelected(pixelSelected,x,y)==-1){
|
|
522 |
//color = '#'+Math.floor(Math.random()*16777215).toString(16);
|
|
523 |
color = hexaDecimalColor(colors.length);
|
|
524 |
colors.push(color);
|
|
525 |
ctx.strokeStyle = color;
|
|
526 |
ctx.strokeRect(x*sizeRec+1,y*sizeRec+1,sizeRec-1,sizeRec-1);
|
|
527 |
pixelSelected.push([x,y]);
|
|
528 |
}
|
|
529 |
}
|
|
530 |
}
|
|
531 |
plotSpectra(pixelSelected,selectionType,jSON,containerSpec,slice);
|
|
532 |
}
|
|
533 |
|
|
534 |
}
|
|
535 |
|
|
536 |
function plotSpectra(pixelSelected,selectionType,jSON,containerSpec,slice){
|
|
537 |
|
|
538 |
//Spectrum
|
|
539 |
var spec = [];
|
|
540 |
var zero = [];
|
|
541 |
|
|
542 |
var minF, maxF, xFits, yFits, titlePlot = "";
|
|
543 |
|
|
544 |
var trunc = 3;
|
|
545 |
|
|
546 |
zero.push([parseFloat(jSON.WAVE[trunc]),0]);
|
|
547 |
zero.push([parseFloat(jSON.WAVE[jSON.WAVE.length-trunc]),0]);
|
|
548 |
|
|
549 |
var unitWave = "("+jSON.UNIT_WAVE+")";
|
|
550 |
var unitFlux = "("+jSON.UNIT_QTTY+")";
|
|
551 |
var infoFlux = jSON.INFO_QTTY;
|
|
552 |
var infoWave = jSON.INFO_WAVE;
|
|
553 |
|
|
554 |
if (selectionType=="rect" || selectionType=="circ") {
|
|
555 |
var specLine = [];
|
|
556 |
for ( var i = trunc; i <= jSON.WAVE.length - trunc; i++) {
|
|
557 |
var fluxXY = 0;
|
|
558 |
var nbPix = 0;
|
|
559 |
for ( var pixel = 0; pixel<pixelSelected.length; pixel++){
|
|
560 |
xFits = pixelSelected[pixel][0];
|
|
561 |
yFits = pixelSelected[pixel][1];
|
|
562 |
if (jSON.SPECTRUM[xFits][(naxis2-1)-yFits][i]!="Nan"){
|
|
563 |
fluxXY = fluxXY+ ( jSON.SPECTRUM[xFits][(naxis2-1)-yFits][i] / (pixelSelected.length) );
|
|
564 |
nbPix++;
|
|
565 |
}
|
|
566 |
}
|
|
567 |
fluxXY = fluxXY / nbPix;
|
|
568 |
if (i==trunc){minF = fluxXY; maxF = fluxXY;}
|
|
569 |
if (fluxXY<minF && !isNaN(fluxXY)){minF = fluxXY;}
|
|
570 |
if (fluxXY>maxF && !isNaN(fluxXY)){maxF = fluxXY;}
|
|
571 |
waveXY = parseFloat(jSON.WAVE[i]);
|
|
572 |
specLine.push([waveXY,fluxXY]);
|
|
573 |
}
|
|
574 |
|
|
575 |
titlePlot = "Average "+infoFlux+" "+unitFlux+" for all selected pixel(s)";
|
|
576 |
spec.push(specLine);
|
|
577 |
}
|
|
578 |
|
|
579 |
|
|
580 |
if (selectionType=="line" || selectionType=="pixel" ){
|
|
581 |
for ( var pixel = 0; pixel<pixelSelected.length; pixel++) {
|
|
582 |
var specLine = [];
|
|
583 |
for ( var i = trunc; i <= jSON.WAVE.length - trunc; i++) {
|
|
584 |
xFits = pixelSelected[pixel][0];
|
|
585 |
yFits = pixelSelected[pixel][1];
|
|
586 |
fluxXY = jSON.SPECTRUM[xFits][(naxis2-1)-yFits][i];
|
|
587 |
if (i==trunc && pixel == 0){minF = fluxXY; maxF = fluxXY;}
|
|
588 |
if (fluxXY<minF && !isNaN(fluxXY)){minF = fluxXY;}
|
|
589 |
if (fluxXY>maxF && !isNaN(fluxXY)){maxF = fluxXY;}
|
|
590 |
waveXY = parseFloat(jSON.WAVE[i]);
|
|
591 |
specLine.push([waveXY,fluxXY]);
|
|
592 |
}
|
|
593 |
spec.push(specLine);
|
|
594 |
|
|
595 |
}
|
|
596 |
|
|
597 |
titlePlot = infoFlux+" "+unitFlux+" for each selected pixel(s)";
|
|
598 |
}
|
|
599 |
|
|
600 |
margeF = 0.1*(maxF-minF);
|
|
601 |
|
|
602 |
var sliceLine = [];
|
|
603 |
sliceLine.push([parseFloat(jSON.WAVE[slice]),minF-margeF]);
|
|
604 |
sliceLine.push([parseFloat(jSON.WAVE[slice]),maxF+margeF]);
|
|
605 |
|
|
606 |
options = {
|
|
607 |
HtmlText: true,
|
|
608 |
xaxis: { title: infoWave+" "+unitWave, noTicks: 4 },
|
|
609 |
yaxis: { min: minF-margeF, max: maxF+margeF, base: Math.E,
|
|
610 |
tickFormatter: function(x) {
|
|
611 |
return parseFloat(x).toExponential();
|
|
612 |
}
|
|
613 |
},
|
|
614 |
lines: { show: true },
|
|
615 |
points: { show: false },//{ show: true, radius: 1 },
|
|
616 |
selection: { mode: 'xy', fps: 50 },
|
|
617 |
title: titlePlot,
|
|
618 |
subtitle: "Click on pixel(s) to display spectra - Select plot area to zoom on - Click to unzoom",
|
|
619 |
mouse: { track: true, relative: true }
|
|
620 |
};
|
|
621 |
|
|
622 |
container = $(containerSpec.body.id);
|
|
623 |
|
|
624 |
function drawGraph(spectralData,opts) {
|
|
625 |
var o = Flotr._.extend(Flotr._.clone(options), opts || {});
|
|
626 |
varToPlot = [];
|
|
627 |
varToPlot.push(
|
|
628 |
{
|
|
629 |
data: zero,
|
|
630 |
color: '#FC0000',
|
|
631 |
});
|
|
632 |
/* varToPlot.push(
|
|
633 |
{
|
|
634 |
data: sliceLine,
|
|
635 |
color: '#FC0000',
|
|
636 |
});*/
|
|
637 |
if (spectralData.length!=0) {
|
|
638 |
for (var i = 0; i<=spectralData.length;i++){
|
|
639 |
varToPlot.push(
|
|
640 |
{
|
|
641 |
data: spectralData[i],
|
|
642 |
color: colors[i]
|
|
643 |
});
|
|
644 |
}
|
|
645 |
}
|
|
646 |
Flotr.draw(container, varToPlot, o);
|
|
647 |
|
|
648 |
}
|
|
649 |
drawGraph(spec);
|
|
650 |
|
|
651 |
Flotr.EventAdapter.observe(container, 'flotr:select', function(area) {
|
|
652 |
drawGraph(spec,{
|
|
653 |
xaxis: { min: area.x1, max: area.x2 },
|
|
654 |
yaxis: { min: area.y1, max: area.y2 }
|
|
655 |
});
|
|
656 |
});
|
|
657 |
|
|
658 |
Flotr.EventAdapter.observe(container, 'flotr:click', function() {
|
|
659 |
drawGraph(spec);
|
|
660 |
});
|
|
661 |
|
|
662 |
}
|
|
663 |
|
|
664 |
function plotColorHisto(slice,jSON,sliderL,sliderR){
|
|
665 |
|
|
666 |
imageSlice = getImageSlice(jSON,slice,[]);
|
|
667 |
|
|
668 |
var nbrBin = 100;
|
|
669 |
|
|
670 |
var minS = Math.min.apply(Math, imageSlice);
|
|
671 |
var maxS = Math.max.apply(Math, imageSlice);
|
|
672 |
var binSize = (maxS-minS)/nbrBin;
|
|
673 |
|
|
674 |
histo = [];
|
|
675 |
for (var x = 0; x < nbrBin; x++) { histo.push(0);}
|
|
676 |
for (var x = 0; x < imageSlice.length; x++) { histo[Math.floor((imageSlice[x]-minS)/binSize)-1] += 1; }
|
|
677 |
|
|
678 |
var maxHisto = Math.max.apply(Math, histo);
|
|
679 |
|
|
680 |
console.log("histo.length :"+histo.length+" maxHisto : "+maxHisto+" minS : "+minS+" maxS :"+maxS+" binSize : "+binSize);
|
|
681 |
// ORIGINAL canHisto = document.getElementById(canHistoID);
|
|
682 |
canHisto = document.getElementById(canHistoID);
|
|
683 |
ctxHisto = canHisto.getContext('2d');
|
|
684 |
|
|
685 |
ctxHisto.clearRect(0, 0, ctxHisto.canvas.width, ctxHisto.canvas.height);
|
|
686 |
|
|
687 |
ctxHisto.strokeStyle = 'black';
|
|
688 |
ctxHisto.lineWidth = 1;
|
|
689 |
var c = Math.floor((ctxHisto.canvas.height-10)/maxHisto);
|
|
690 |
|
|
691 |
for (var x = 0; x < histo.length; x++){
|
|
692 |
if(c == 0) c=1;
|
|
693 |
// ORIGINAL ctxHisto.strokeRect( 6+x, ctxHisto.canvas.height-5, 1, (-1)*histo[x]*Math.floor((ctxHisto.canvas.height-10)/maxHisto) );
|
|
694 |
ctxHisto.strokeRect( 6+x, ctxHisto.canvas.height-5, 1, (-1)*histo[x]*c );
|
|
695 |
}
|
|
696 |
ctxHisto.strokeStyle = 'red';
|
|
697 |
ctxHisto.strokeRect( 6+sliderL, ctxHisto.canvas.height-5, 1, (-1)*(ctxHisto.canvas.height-10) );
|
|
698 |
ctxHisto.strokeRect( 6+sliderR, ctxHisto.canvas.height-5, 1, (-1)*(ctxHisto.canvas.height-10) );
|
|
699 |
|
|
700 |
return [minS+sliderL*binSize, minS+sliderR*binSize];
|
|
701 |
|
|
702 |
}
|
|
703 |
|
|
704 |
function getAnId(){
|
|
705 |
var id = Ext.id();
|
|
706 |
id = parseInt(id.replace("ext-gen", ""));
|
|
707 |
return id;
|
|
708 |
}
|
|
709 |
//***********************************************************************************************************************************************************
|
|
710 |
/*
|
|
711 |
* Constructor call
|
|
712 |
*/
|
|
713 |
sitools.user.component.viewCubeService.superclass.constructor.call(this, Ext.apply({
|
|
714 |
id : 'viewCube-panel',
|
|
715 |
datasetName : config.datasetName,
|
|
716 |
layout : 'border',
|
|
717 |
autoScroll : true,
|
|
718 |
items : [ this.tabPanel ]
|
|
719 |
}, config));
|
|
720 |
|
|
721 |
};
|
|
722 |
|
|
723 |
Ext.extend(sitools.user.component.viewCubeService, Ext.Panel, {
|
|
724 |
/**
|
|
725 |
* Must be implemented to save window Settings
|
|
726 |
* @return {}
|
|
727 |
*/
|
|
728 |
_getSettings : function () {
|
|
729 |
return {
|
|
730 |
datasetName : this.datasetName,
|
|
731 |
preferencesPath : this.preferencesPath,
|
|
732 |
preferencesFileName : this.preferencesFileName
|
|
733 |
};
|
|
734 |
},
|
|
735 |
/**
|
|
736 |
* Load the userPreferences...
|
|
737 |
*/
|
|
738 |
afterRender : function () {
|
|
739 |
sitools.user.component.viewCubeService.superclass.afterRender.call(this);
|
|
740 |
},
|
|
741 |
|
|
742 |
});
|
|
743 |
|
|
744 |
Ext.reg('sitools.user.component.viewCubeService', sitools.user.component.viewCubeService);
|
|
745 |
|
Ajout du services client pour le cube explorer