Skip to content

Commit e8245db

Browse files
authored
Merge pull request #490 from Caltech-IPAC/dm-12305-HiPS
DM-12305: HIPS: begin proof of concept
2 parents 504d4dd + 1082c5f commit e8245db

File tree

78 files changed

+4533
-606
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+4533
-606
lines changed

src/firefly/html/demo/ffapi-coverage-test.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
color: {aTable: 'blue', bTable: 'yellow'},
7878
// overlayPosition : '149.9;68.8;EQ_J2000',
7979
OVErlayPosition : '149.08;68.739;EQ_J2000',
80+
useHiPS: true
8081
});
8182

8283
};

src/firefly/html/firefly.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,9 @@
2222
options : {
2323
MenuItemKeys: {maskOverlay:true},
2424
catalogSpacialOp: 'polygonWhenPlotExist',
25-
charts: {chartEngine: 'plotly', multitrace: true}
25+
charts: {chartEngine: 'plotly', multitrace: true},
26+
hips : {useForCoverage: true}
27+
2628
}
2729
}
2830
};
Loading
-2.53 KB
Loading

src/firefly/java/edu/caltech/ipac/firefly/server/visualize/VisJsonSerializer.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,8 +222,8 @@ public static JSONObject serializePlotImages(PlotImages pi) {
222222
imageMap = new JSONObject();
223223

224224
imageMap.put("url", image.getURL());
225-
imageMap.put("xoff", image.getXoff());
226-
imageMap.put("yoff", image.getYoff());
225+
imageMap.put("x", image.getXoff());
226+
imageMap.put("y", image.getYoff());
227227
imageMap.put("width", image.getWidth());
228228
imageMap.put("height", image.getHeight());
229229
imageMap.put("index", image.getIndex());

src/firefly/java/edu/caltech/ipac/firefly/visualize/RequestType.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@
1212
/**
1313
* @author Trey Roby
1414
*/
15-
public enum RequestType { SERVICE, FILE, URL, ALL_SKY, BLANK, PROCESSOR, RAWDATASET_PROCESSOR, TRY_FILE_THEN_URL }
15+
public enum RequestType { SERVICE, FILE, URL, HiPS, ALL_SKY, BLANK, PROCESSOR, RAWDATASET_PROCESSOR, TRY_FILE_THEN_URL }
1616

src/firefly/java/edu/caltech/ipac/util/RegionFactory.java

Lines changed: 3 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,34 +10,16 @@
1010

1111

1212
import edu.caltech.ipac.astro.CoordException;
13-
import edu.caltech.ipac.util.dd.ContainsOptions;
14-
import edu.caltech.ipac.util.dd.Global;
15-
import edu.caltech.ipac.util.dd.RegionFileElement;
16-
import edu.caltech.ipac.util.dd.RegParseException;
17-
import edu.caltech.ipac.util.dd.Region;
18-
import edu.caltech.ipac.util.dd.RegionAnnulus;
19-
import edu.caltech.ipac.util.dd.RegionBox;
20-
import edu.caltech.ipac.util.dd.RegionBoxAnnulus;
21-
import edu.caltech.ipac.util.dd.RegionCsys;
22-
import edu.caltech.ipac.util.dd.RegionDimension;
23-
import edu.caltech.ipac.util.dd.RegionEllipse;
24-
import edu.caltech.ipac.util.dd.RegionEllipseAnnulus;
25-
import edu.caltech.ipac.util.dd.RegionFont;
26-
import edu.caltech.ipac.util.dd.RegionLines;
27-
import edu.caltech.ipac.util.dd.RegionOptions;
28-
import edu.caltech.ipac.util.dd.RegionPoint;
29-
import edu.caltech.ipac.util.dd.RegionText;
30-
import edu.caltech.ipac.util.dd.RegionValue;
13+
import edu.caltech.ipac.util.dd.*;
3114
import edu.caltech.ipac.visualize.plot.CoordinateSys;
3215
import edu.caltech.ipac.visualize.plot.WorldPt;
3316

3417
import java.util.ArrayList;
18+
import java.util.Arrays;
3519
import java.util.HashMap;
3620
import java.util.List;
3721
import java.util.Map;
3822
import java.util.NoSuchElementException;
39-
import java.util.Arrays;
40-
import java.util.stream.Collectors;
4123

4224

4325
/**
@@ -818,6 +800,7 @@ private static String getRegionCSysStr(CoordinateSys csys) {
818800
else if (csys.equals(CoordinateSys.EQ_J2000)) retval= "J2000";
819801
else if (csys.equals(CoordinateSys.ECL_J2000)) retval= "ECLIPTIC";
820802
else if (csys.equals(CoordinateSys.ECL_J2000)) retval= "ECLIPTIC";
803+
else if (csys.equals(CoordinateSys.GALACTIC)) retval= "GALACTIC";
821804
else if (csys.equals(CoordinateSys.PIXEL)) retval= "IMAGE";
822805
else if (csys.equals(CoordinateSys.SCREEN_PIXEL)) retval= "PHYSICAL";
823806
else retval= "PHYSICAL";

src/firefly/js/core/AppDataCntlr.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@ export function dispatchAddTaskCount(componentId,taskId) {
8888
flux.process({type: ADD_TASK_COUNT, payload: {componentId,taskId}});
8989
}
9090

91+
92+
let taskCnt= 0;
93+
export function makeTaskId() {
94+
taskCnt++;
95+
return `task-${taskCnt}`;
96+
}
97+
9198
/**
9299
* @param componentId the id or array of ids of the component to record the task count
93100
* @param taskId id of task, create with makeTaskId()

src/firefly/js/core/AppDataReducers.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ const updateActiveTarget= function(state,action) {
8787
const addTaskCount= function(state,action) {
8888
var {componentId,taskId}= action.payload;
8989
if (!componentId && !taskId) return state;
90-
var taskArray= state.taskCounters[componentId] | [];
90+
var taskArray= state.taskCounters[componentId] || [];
9191
taskArray= [...taskArray,taskId];
9292
var taskCounters= Object.assign({}, taskCounters, {[componentId]:taskArray});
9393
return Object.assign({},state, {taskCounters});
@@ -96,7 +96,7 @@ const addTaskCount= function(state,action) {
9696
const removeTaskCount= function(state,action) {
9797
var {componentId,taskId}= action.payload;
9898
if (!componentId && !taskId) return state;
99-
var taskArray= state.taskCounters[componentId] | [];
99+
var taskArray= state.taskCounters[componentId] || [];
100100
taskArray= taskArray.filter( (id) => id!==taskId);
101101
var taskCounters= Object.assign({}, taskCounters, {[componentId]:taskArray});
102102
return Object.assign({},state, {taskCounters});

src/firefly/js/core/MasterSaga.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@ function createSaga({id, actions=[], callback, params, dispatch, getState}) {
120120
callback(action, cancelSelf, params, dispatch, getState);
121121
} catch (e) {
122122
console.log(`Encounter error while executing watcher: ${id} error: ${e}`);
123+
console.log(e);
123124
}
124125
}
125126
};

src/firefly/js/core/ReduxFlux.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ import NorthUpCompass from '../drawingLayers/NorthUpCompass.js';
5656
import Catalog from '../drawingLayers/Catalog.js';
5757
import Artifact from '../drawingLayers/Artifact.js';
5858
import WebGrid from '../drawingLayers/WebGrid.js';
59+
import HiPSGrid from '../drawingLayers/HiPSGrid.js';
5960

6061
import RegionPlot from '../drawingLayers/RegionPlot.js';
6162
import MarkerTool from '../drawingLayers/MarkerTool.js';
@@ -109,7 +110,7 @@ const actionCreators = new Map();
109110
const drawLayerFactory= DrawLayerFactory.makeFactory(ActiveTarget,SelectArea,DistanceTool,
110111
PointSelection, StatsPoint, NorthUpCompass,
111112
Catalog, Artifact, WebGrid, RegionPlot,
112-
MarkerTool, FootprintTool);
113+
MarkerTool, FootprintTool, HiPSGrid);
113114

114115
const cdtFactory= chartDataTypeFactory([DATATYPE_XYCOLS, DATATYPE_HISTOGRAM]);
115116
const chartsFactory= chartTypeFactory([PLOTLY_CHART, SCATTER_TBLVIEW, HISTOGRAM_TBLVIEW]);

src/firefly/js/drawingLayers/DistanceTool.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,15 +326,16 @@ function makeSelectObj(firstPt,currentPt, posAngle,cc) {
326326
if (world) {
327327
anyPt1 = cc.getWorldCoords(ptAry[0]);
328328
anyPt2 = cc.getWorldCoords(ptAry[1]);
329+
if (!anyPt1 || !anyPt2) return null;
329330
dist= VisUtil.computeDistance(anyPt1,anyPt2);
330331
}
331332
else {
332333
anyPt1 = ptAry[0];
333334
anyPt2 = ptAry[1];
335+
if (!anyPt1 || !anyPt2) return null;
334336
dist= screenDistance(anyPt1,anyPt2);
335337
}
336338

337-
if (!anyPt1 || !anyPt2) return null;
338339

339340
var obj= ShapeDataObj.makeLine(anyPt1,anyPt2);
340341
obj.style= Style.HANDLED;
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
/*
2+
* License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt
3+
*/
4+
5+
6+
import ImagePlotCntlr, {visRoot} from '../visualize/ImagePlotCntlr.js';
7+
import DrawLayerCntlr from '../visualize/DrawLayerCntlr.js';
8+
import {primePlot, isDrawLayerVisible} from '../visualize/PlotViewUtil.js';
9+
import {getBestHiPSlevel, getVisibleHiPSCells,
10+
getPointMaxSide, getMaxDisplayableHiPSLevel} from '../visualize/HiPSUtil.js';
11+
import FootprintObj from '../visualize/draw/FootprintObj.js';
12+
import ShapeDataObj from '../visualize/draw/ShapeDataObj.js';
13+
import {makeDrawingDef} from '../visualize/draw/DrawingDef.js';
14+
import DrawLayer, {DataTypes,ColorChangeType} from '../visualize/draw/DrawLayer.js';
15+
import {makeFactoryDef} from '../visualize/draw/DrawLayerFactory.js';
16+
import {makeImagePt} from '../visualize/Point.js';
17+
import CysConverter from '../visualize/CsysConverter';
18+
import {getUIComponent} from './HiPSGridlUI.jsx';
19+
20+
const ID= 'HIPS_GRID';
21+
const TYPE_ID= 'HIPS_GRID_TYPE';
22+
23+
24+
25+
const factoryDef= makeFactoryDef(TYPE_ID,creator,getDrawData,getLayerChanges,null,getUIComponent);
26+
27+
export default {factoryDef, TYPE_ID}; // every draw layer must default export with factoryDef and TYPE_ID
28+
29+
let idCnt=0;
30+
31+
32+
function creator(initPayload, presetDefaults) {
33+
34+
let drawingDef= makeDrawingDef('magenta', {lineWidth:1, size:6} );
35+
drawingDef= Object.assign(drawingDef,presetDefaults);
36+
37+
38+
idCnt++;
39+
40+
const options= {
41+
hasPerPlotData:true,
42+
isPointData:false,
43+
canUserChangeColor: ColorChangeType.DYNAMIC,
44+
gridType: 'auto',
45+
gridLockLevel: 3,
46+
};
47+
return DrawLayer.makeDrawLayer(`${ID}-${idCnt}`,TYPE_ID, {}, options, drawingDef);
48+
}
49+
50+
51+
function getDrawData(dataType, plotId, drawLayer, action, lastDataRet) {
52+
if (!isDrawLayerVisible(drawLayer, plotId)) return null;
53+
if (dataType!==DataTypes.DATA) return null;
54+
// return isEmpty(lastDataRet) ? computeDrawData(plotId) : lastDataRet;
55+
return computeDrawData(drawLayer, plotId);
56+
}
57+
58+
function getLayerChanges(drawLayer, action) {
59+
switch (action.type) {
60+
case ImagePlotCntlr.ANY_REPLOT:
61+
break;
62+
case DrawLayerCntlr.ATTACH_LAYER_TO_PLOT:
63+
const {plotId}= action.payload;
64+
let {plotIdAry}= action.payload;
65+
if (!plotIdAry && !plotId) return null;
66+
if (!plotIdAry) plotIdAry= [plotId];
67+
const title= Object.assign({},drawLayer.title);
68+
plotIdAry.forEach( (id) => title[id]= getTitle(id));
69+
return {title};
70+
case DrawLayerCntlr.MODIFY_CUSTOM_FIELD:
71+
return dealWithMods(drawLayer,action);
72+
break;
73+
}
74+
return null;
75+
}
76+
77+
78+
function getTitle() {
79+
return 'HiPS';
80+
}
81+
82+
83+
function dealWithMods(drawLayer,action) {
84+
const {changes}= action.payload;
85+
if (changes.gridType) {
86+
return {gridType:changes.gridType, gridLockLevel: changes.gridLockLevel || 3};
87+
}
88+
return null;
89+
}
90+
91+
function computeDrawData(drawLayer, plotId) {
92+
if (!plotId) return null;
93+
const plot= primePlot(visRoot(),plotId);
94+
if (!plot) return [];
95+
96+
const cc= CysConverter.make(plot);
97+
98+
let norder;
99+
if (drawLayer.gridType==='lock') {
100+
norder= Math.min(Number(drawLayer.gridLockLevel), getMaxDisplayableHiPSLevel(plot));
101+
}
102+
else {
103+
const limitByMax= drawLayer.gridType==='match';
104+
norder= getBestHiPSlevel(plot, limitByMax);
105+
if (norder==='allsky') norder= 3;
106+
}
107+
108+
const {fov, centerWp}= getPointMaxSide(plot, plot.viewDim);
109+
const cells= getVisibleHiPSCells(norder,centerWp,fov, plot.dataCoordSys);
110+
111+
// const fpAry= cells.map( (c) => c.wpCorners);
112+
const fpAry= cells
113+
.map( (c) => {
114+
const scrCorners= c.wpCorners.map( (corner) => cc.getImageCoords(corner));
115+
if (scrCorners.some ((scrC) => !scrC)) return null;
116+
return scrCorners;
117+
})
118+
.filter( (c) => c);
119+
120+
121+
122+
const idAry= cells
123+
.map( (c) => {
124+
const s1= cc.getImageCoords(c.wpCorners[0]);
125+
const s2= cc.getImageCoords(c.wpCorners[2]);
126+
if (!s1 || !s2) return null;
127+
return ShapeDataObj.makeTextWithOffset(makeImagePt(-10,-6), makeImagePt( (s1.x+s2.x)/2, (s1.y+s2.y)/2), `${norder}/${c.ipix}`);
128+
})
129+
.filter( (v) => v);
130+
return [FootprintObj.make(fpAry), ...idAry];
131+
}
132+
133+
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/*
2+
* License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt
3+
*/
4+
5+
/*
6+
* License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt
7+
*/
8+
9+
import React from 'react';
10+
import PropTypes from 'prop-types';
11+
import {RadioGroupInputFieldView} from '../ui/RadioGroupInputFieldView.jsx';
12+
import {ListBoxInputFieldView} from '../ui/ListBoxInputField.jsx';
13+
import {dispatchModifyCustomField} from '../visualize/DrawLayerCntlr.js';
14+
import {getBestHiPSlevel, getMaxDisplayableHiPSLevel} from '../visualize/HiPSUtil.js';
15+
import {primePlot} from '../visualize/PlotViewUtil.js';
16+
17+
18+
const options= [ {label: 'Auto', value: 'auto'},
19+
{label: 'Match Image Depth', value: 'match'},
20+
{label: 'Lock', value: 'lock'}
21+
];
22+
23+
24+
export const getUIComponent = (drawLayer,pv) => <HiPSGridUI drawLayer={drawLayer} pv={pv}/>;
25+
26+
function HiPSGridUI({drawLayer,pv}) {
27+
28+
const tStyle= {
29+
display:'inline-block',
30+
whiteSpace: 'nowrap',
31+
minWidth: '3em',
32+
paddingLeft : 5
33+
};
34+
35+
const {gridType}= drawLayer;
36+
37+
38+
return (
39+
<div>
40+
41+
<div>
42+
<div style={{display:'flex', alignItems: 'flex-end', paddingLeft:7}}>
43+
<RadioGroupInputFieldView options={options} value={gridType}
44+
alignment={'vertical'}
45+
onChange={(ev) => changeHipsPref(drawLayer,pv,ev.target.value)} />
46+
{gridType==='lock' && showLevelOp(drawLayer,pv) }
47+
</div>
48+
</div>
49+
</div>
50+
);
51+
}
52+
53+
54+
function showLevelOp(drawLayer, pv) {
55+
56+
const plot= primePlot(pv);
57+
if (!plot) return null;
58+
59+
const norder= getMaxDisplayableHiPSLevel(plot);
60+
61+
const {gridLockLevel}= drawLayer;
62+
const value= Math.min(norder, Number(gridLockLevel));
63+
64+
const lockOp= [];
65+
for(let i= 1; i<=norder;i++) lockOp.push({label:i+'', value:i});
66+
67+
68+
return (
69+
<ListBoxInputFieldView
70+
71+
inline={true}
72+
value={value}
73+
onChange={(ev) => changeLockLevelPref(drawLayer,pv,ev.target.value)}
74+
labelWidth={10}
75+
label={' '}
76+
tooltip={ 'Chooseh HiPS grid level'}
77+
options={lockOp}
78+
multiple={false}
79+
/>
80+
)
81+
}
82+
83+
84+
function changeHipsPref(drawLayer,pv,value) {
85+
dispatchModifyCustomField(drawLayer.drawLayerId, {gridType:value,gridLockLevel:drawLayer.gridLockLevel},pv.plotId);
86+
}
87+
88+
function changeLockLevelPref(drawLayer,pv,value) {
89+
dispatchModifyCustomField(drawLayer.drawLayerId, {gridType:'lock', gridLockLevel:value},pv.plotId);
90+
}
91+
92+
HiPSGridUI.propTypes= {
93+
drawLayer : PropTypes.object.isRequired,
94+
pv : PropTypes.object.isRequired
95+
};
96+

src/firefly/js/drawingLayers/MarkerTool.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ export function markerToolMoveActionCreator(rawAction) {
183183

184184
newSize = [lengthToArcsec(Math.abs(imagePt.x - imageCenter.x)*2, cc, imgUnit),
185185
lengthToArcsec(Math.abs(imagePt.y - imageCenter.y)*2, cc, imgUnit)];
186+
if (newSize[0] < 2) newSize[0]=2;
187+
if (newSize[1] < 2) newSize[1]=2;
186188
move.newSize = {size: newSize, unitType: ShapeDataObj.UnitType.ARCSEC}; // in world size
187189
isHandle = { isOutline: true, isResize: true};
188190
} else if (markerStatus === MarkerStatus.relocate || markerStatus === MarkerStatus.attached_relocate) {

0 commit comments

Comments
 (0)