Skip to content

Commit 0453e92

Browse files
author
zhang
committed
FIREFLY-116
Clean up codes
1 parent 3284731 commit 0453e92

File tree

3 files changed

+112
-58
lines changed

3 files changed

+112
-58
lines changed

src/firefly/js/visualize/FitsHeaderUtil.js

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,19 @@ export function makeHeaderParse(header, altWcs='') {
8686
const retAry= [];
8787
let i= 0;
8888
for (let headerIdx = startIdx; headerIdx <= endIdx; headerIdx++) {
89-
retAry[i]= getNumberHeader(header, `${keyRoot}${headerIdx}${altWcs}`,NaN);
89+
retAry[i]= getNumberHeader(header, `${keyRoot}${headerIdx}${altWcs}`,def);
9090
i++;
9191
}
9292
return retAry;
93+
},
94+
hasKeyStartWith(startKeys){
95+
let key;
96+
for (key in header) {
97+
if (key.startsWith(startKeys)) {
98+
return true;
99+
}
100+
}
101+
return false;
93102
}
94103
};
95104
}
@@ -127,11 +136,19 @@ export function makeDoubleHeaderParse(header,zeroHeader,altWcs) {
127136
},
128137
getDoubleAry(keyRoot,altWcs, startIdx,endIdx,def=undefined) {
129138
if (startIdx>endIdx) return def;
130-
const retAry= hp.getDoubleAry(keyRoot,altWcs,startIdx,endIdx);
131-
let arrNaN = retAry.filter( (v)=> isNaN(v) );
132-
if (arrNaN.length!==retAry.length) return retAry;
139+
const retAry= hp.getDoubleAry(keyRoot,altWcs,startIdx,endIdx, def);
140+
let validValueArr = retAry.filter( (v)=> v!==def );
141+
if (validValueArr.length>0) return retAry;
133142
return zhp ? zhp.getDoubleAry(keyRoot,altWcs, startIdx,endIdx,def) : def;
134143
},
144+
hasKeyStartWith(startKeys){
145+
if (hp.hasKeyStartWith(startKeys)){
146+
return true;
147+
}
148+
else {
149+
return zhp ? zhp.hasKeyStartWith(startKeys):false;
150+
}
151+
},
135152
isDefinedHeaderList: (list) => hp.isDefinedHeaderList(list) || (zhp && zhp.isDefinedHeaderList(list))
136153
};
137154
}

src/firefly/js/visualize/projection/Wavelength.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
1-
2-
3-
4-
1+
/**
2+
* References:
3+
* 1. "Representations of spectral coordinates in FITS", by E. W. Greisen1,M.R.Calabretta2, F.G.Valdes3,
4+
* and S. L. Allen. A&A Volume 446, Number 2, February I 2006
5+
* 2. "Representations of world coordinates in FITS" A&A 395, 1061-1075 (2002) DOI: 10.1051/0004-6361:20021326
6+
* E. W. Greisen1 - M. R. Calabretta2
7+
*
8+
*/
59

610
export const PLANE = 'PLANE';
711
export const LINEAR = 'LINEAR';

src/firefly/js/visualize/projection/WavelengthHeaderParser.js

Lines changed: 83 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@
22
* License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt
33
*/
44

5-
import {makeDoubleHeaderParse,getHeader} from '../FitsHeaderUtil.js';
5+
import {makeDoubleHeaderParse} from '../FitsHeaderUtil.js';
66
import {AWAV, F2W, LINEAR, LOG, PLANE, TAB, V2W, WAVE} from './Wavelength.js';
77

88
export function parseWavelengthHeaderInfo(header, altWcs='', zeroHeader, wlTable) {
99
const parse= makeDoubleHeaderParse(header, zeroHeader, altWcs);
1010
const which= altWcs?'1':getWCSAXES(parse);
11-
const mijMatrixKeyRoot = getPC_ijKey(header, zeroHeader,which);
11+
const mijMatrixKeyRoot = getPC_ijKey(parse,which);
1212
return calculateWavelengthParams(parse,altWcs,which,mijMatrixKeyRoot, wlTable);
1313
}
1414

@@ -24,52 +24,26 @@ const L_10= Math.log(10);
2424
/**
2525
* According to A&A 395, 1061-1075 (2002) DOI: 10.1051/0004-6361:20021326
2626
* Representations of world coordinates in FITS E. W. Greisen1 - M. R. Calabretta2
27-
* paper, the CD_ij is for the older FITs header. The newer FITs header has PC only.
27+
* https://www.aanda.org/articles/aa/full/2002/45/aah3859/aah3859.html
28+
* the CD_ij is for the older FITs header. The newer FITs header has PC only.
2829
* 1. If both PC and CD exist, it is wrong. Exception is thrown
2930
* 2. If PC is not exist, one or more CD is exist, use CD_ij (j=1..N); if any of CD_ij
3031
* is not defined, the default is 0.0;
3132
* 3. If any PC_ij is defined or neigther PC nor CD is defined, we use PC, the default
3233
* is 0 for j!=i and 1 if j==i
3334
*
34-
* @param header
35-
* @param zeroHeader
35+
*
36+
* @param parser
3637
* @param which
37-
* @returns {string}
38+
* @returns {*}
3839
*/
39-
function getPC_ijKey(header, zeroHeader,which){
40-
41-
var key;
42-
let hasPC=false, hasCD=false;
43-
for (key in header) {
44-
if (key.startsWith(`PC${which}_`)) {
45-
hasPC = true;
46-
break;
47-
}
48-
}
49-
if (!hasPC && zeroHeader){
50-
for (key in zeroHeader) {
51-
if (key.startsWith(`PC${which}_`)) {
52-
hasPC = true;
53-
break;
54-
}
55-
}
56-
}
57-
for (key in header) {
58-
if (key.startsWith(`CD${which}_`)) {
59-
hasCD = true;
60-
break;
61-
}
62-
}
63-
if (!hasCD && zeroHeader){
64-
for (key in zeroHeader) {
65-
if (key.startsWith(`CD${which}_`)) {
66-
hasCD = true;
67-
break;
68-
}
69-
}
70-
}
40+
function getPC_ijKey(parser,which){
41+
42+
let hasPC = parser.hasKeyStartWith(`PC${which}_`);
43+
let hasCD = parser.hasKeyStartWith(`CD${which}_`);
44+
7145
if (hasPC && hasCD){
72-
throw Error('The FITs header contains both PC_ij and CD_ij');
46+
return undefined;
7347
}
7448
if (!hasPC && hasCD){
7549
return 'CD';
@@ -79,6 +53,10 @@ function getPC_ijKey(header, zeroHeader,which){
7953

8054

8155
/**
56+
* This method will return the value of the WCSAXES. NOTE: the WCSAXES can be any naxis, it does
57+
* not have to be 3. In general, if the wavelength is depending on two dimensional images, it most likely
58+
* is 3. But the axis 3 can also be other quantity such as Frequency etc.
59+
*
8260
* If the FITs header has 'WCSAXES', this will be the wavelength axis.
8361
* If 'WCSAXES' is not defined, the default will be the larger of naxis and the j where j=1, 2, 3, ..)
8462
* @param parse
@@ -101,18 +79,55 @@ function getWCSAXES(parse){
10179
}
10280

10381
}
104-
function assignDefault(inArr, keyRoot, which, N){
82+
83+
/**
84+
*
85+
* Reference: A&A 395, 1061-1075 (2002) DOI: 10.1051/0004-6361:20021326
86+
* Representations of world coordinates in FITS E. W. Greisen1 - M. R. Calabretta2
87+
* paper, the CD_ij is for the older FITs header. The newer FITs header has PC only.
88+
*
89+
* This method is checking the pc_ij and r_j array. If any of the values are undefined,
90+
* the default are assigned. The default values are defined as following based on the reference
91+
* paper above:
92+
*
93+
* PC_ij: an array defined in the FITs header. Fhe size of the dimension is N. N is defined by
94+
* WCSAXES or naxis
95+
* i: the wcsaxes's value, if the wcsaxes = 2, then i=2
96+
* j: 0, ...N
97+
* If any of the PC_ij is not defined in the header, the following default is assigned:
98+
* 1. PC i_j = 1.0 when i = j
99+
* 2. PC i_j = 0.0 when i!=j
100+
*
101+
* If instead of using PC, CD is used, the following default is assigned:
102+
* CD i_j 0.0 NOTE: CD i_j's default is different from PC i_j
103+
*
104+
*
105+
* r_j: An array of the CRPIX values, the size of the dimension is N. N is defined by
106+
* WCSAXES or naxis
107+
* j: 0,...N
108+
*
109+
* Default values:
110+
* if r_j = value of CRPIXj, if it is not defined, the default value is 0.0
111+
*
112+
* @param inArr
113+
* @param keyRoot
114+
* @param which
115+
* @param N
116+
* @returns {Array}
117+
*/
118+
function applyDefaultValues(inArr, keyRoot, which, N){
105119
let retAry=[];
106120
for (let i=0; i<N; i++) {
107121
if (inArr && inArr[i] && !isNaN(inArr[i])){
122+
//if inArr is defined and it has a valid value
108123
retAry[i]=inArr[i];
109124
continue;
110125
}
111-
switch (keyRoot){
126+
switch (keyRoot){ //either inArr is undefined, or inArr[i] is undefined
112127
case 'PC':
113128
retAry[i] = (i+1) === parseInt(which)? 1:0;
114129
break;
115-
case 'CRPIX':
130+
case 'CRPIX' || 'CD':
116131
retAry[i] = 0.0;
117132
break;
118133
};
@@ -146,7 +161,15 @@ function isWaveLength(ctype, pc_3j){
146161
*/
147162
function calculateWavelengthParams(parse, altWcs, which, pc_3j_key,wlTable) {
148163

149-
164+
/*
165+
* Base on the reference: A&A 395, 1061-1075 (2002) DOI: 10.1051/0004-6361:20021326
166+
* Representations of world coordinates in FITS E. W. Greisen. The default values
167+
* defined below:
168+
* CDELT i 1.0
169+
* CTYPE i ' ' (i.e. a linear undefined axis)
170+
* CUNIT i ' ' (i.e. undefined)
171+
* NOTE: i is the which variable here.
172+
*/
150173
const ctype= parse.getValue(`CTYPE${which}${altWcs}`, ' ');
151174
const crpix= parse.getDoubleValue(`CRPIX${which}${altWcs}`, 0.0);
152175
const crval= parse.getDoubleValue(`CRVAL${which}${altWcs}`, 0.0);
@@ -155,12 +178,12 @@ function calculateWavelengthParams(parse, altWcs, which, pc_3j_key,wlTable) {
155178
const restWAV= parse.getDoubleValue('RESTWAV'+altWcs, 0);
156179
const nAxis= parse.getIntValue('NAXIS'+altWcs);
157180
const N= parse.getIntOneOfValue(['WCSAXES', 'WCSAXIS', 'NAXIS'], -1);
158-
let pc_3j = parse.getDoubleAry(`${pc_3j_key}${which}_`,altWcs,1,N); //|| parse.getDoubleAry('CD3_',altWcs,1,N, which);
159-
let r_j = parse.getDoubleAry('CRPIX',altWcs,1,N);
181+
let pc_3j = parse.getDoubleAry(`${pc_3j_key}${which}_`,altWcs,1,N, undefined);
182+
let r_j = parse.getDoubleAry('CRPIX',altWcs,1,N, undefined);
160183

161184
//check if any value is not defined, use default
162-
pc_3j = assignDefault(pc_3j,pc_3j_key, which, N);
163-
r_j = assignDefault(r_j, 'CRPIX', which, N);
185+
pc_3j = applyDefaultValues(pc_3j,pc_3j_key, which, N);
186+
r_j = applyDefaultValues(r_j, 'CRPIX', which, N);
164187

165188
const ps3_0= parse.getValue(`PS${which}_0${altWcs}`, '');
166189
const ps3_1= parse.getValue(`PS${which}_1${altWcs}`, '');
@@ -178,14 +201,24 @@ function calculateWavelengthParams(parse, altWcs, which, pc_3j_key,wlTable) {
178201
//ccc can be 'F2W', 'V2W', 'LOG', 'TAB' or empty that means linear. If the header does not have this kind
179202
// CTYPEka defined, we check if the it is a spectra cube. If it is a spectra cube, we display the wavelength
180203
// at each plane.
181-
182204
const isWL = isWaveLength(ctype, pc_3j);
205+
206+
//If it is a cube plane FITS, plot and display the wavelength at each plane
183207
if (canDoPlaneCalc && !isWL && nAxis===3 ) {
208+
//The FITs has wavelength planes, and each plane has the same wavelength, ie. the third axis
209+
//is wavelength
184210
return makeSimplePlaneBased(crpix, crval, cdelt,nAxis, wlType, units, 'use PLANE since is cube and parameters missing');
185211
}
186212

187-
//When one of three is not defined, we don't show the wavelength in the readout.
188-
if (!algorithm || !wlType || !isWL ) return;
213+
//Plot and display the wavelength as one of the mouse readout only if the FITs header
214+
//contains the required parameters and the wavelength is depending on the image axes.
215+
/* We don't show the wavelength in the mouse readout in following four situations:
216+
* 1. Algorithm is not defined
217+
* 2. wlType is not defined or the type is not supported
218+
* 3. The FITs file is not wavelength type (may be plane)
219+
* 4. It has both PC_ij and CD_ij, thus, we don't know which parameters to use
220+
*/
221+
if (!algorithm || !wlType || !isWL || !pc_3j_key) return;
189222

190223

191224
if (algorithm===LOG){ //the values in CRPIXk and CDi_j (PC_i_j) are log based on 10 rather than natural log, so a factor is needed.

0 commit comments

Comments
 (0)