/*
* License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt
*/
import {get} from 'lodash';
import {isImage,isPlot} from './WebPlot.js';
/**
* @global
* @public
* @typedef {Array.<{}>} FitsHeader
*
* @prop <Array
* @prop {number} height
*
*/
export const HdrConst= {
// Common FITS Headers
CTYPE1 : 'CTYPE1',
CTYPE2 : 'CTYPE2',
CTYPE3 : 'CTYPE3',
BITPIX : 'BITPIX',
CRPIX1 : 'CRPIX1',
CRPIX2 : 'CRPIX2',
CRVAL1 : 'CRVAL1',
CRVAL2 : 'CRVAL2',
CDELT1 : 'CDELT1',
CDELT2 : 'CDELT2',
CROTA1 : 'CROTA1',
CROTA2 : 'CROTA2',
DATAMAX : 'DATAMAX',
DATAMIN : 'DATAMIN',
EXTNAME : 'EXTNAME',
NAXIS1 : 'NAXIS1',
NAXIS2 : 'NAXIS2',
NAXIS3 : 'NAXIS3',
// FITS Headers that are added by firefly
SPOT_OFF : 'SPOT_OFF', // Extension Offset (added by Firefly)
SPOT_EXT : 'SPOT_EXT', // Extension Number (added by Firefly)
SPOT_HS : 'SPOT_HS', // Header block size on disk (added by Firefly)
SPOT_BP : 'SPOT_BP', // Original Bitpix value (added by Firefly)
SPOT_PL : 'SPOT_PL', // Plane of FITS cube (added by Firefly)
};
const alphabetAry= 'ABCDEFGHIJKLMNOPQRSTUVWZYZ'.split('');
/**
* return an array of all the alt projections in this file.
* @param header
* @return {string[]}
*/
export const geAtlProjectionIDs= (header) => alphabetAry.filter( (c) => header[HdrConst.CTYPE1+c]);
export function makeHeaderParse(header, altWcs='') {
return {
header,
getIntValue: (key, def= 0) => parseInt(getNumberHeader(header,key,def)),
getIntOneOfValue: (keyAry, def=0) => {
const foundKey= keyAry.find( (k) => !isNaN(getNumberHeader(header,k,NaN)) );
return foundKey ? getNumberHeader(header, foundKey,def) : def;
},
getValue: (key, def= '') => getHeader(header, key, def),
getDoubleValue: (key, def) => getNumberHeader(header,key,def),
getDoubleOneOfValue: (keyAry, def=0) => {
const foundKey= keyAry.find( (k) => !isNaN(getNumberHeader(header,k,NaN)) );
return foundKey ? getNumberHeader(header, foundKey,def) : def;
},
isDefinedHeaderList(list) {
const key= list.find( (i) => header[i+altWcs]);
return Boolean(key);
},
getDoubleAry(keyRoot,altWcs, startIdx,endIdx,def=undefined) {
if (startIdx>endIdx) return def;
const retAry= [];
let i= 0;
for (let headerIdx = startIdx; headerIdx <= endIdx; headerIdx++) {
retAry[i]= getNumberHeader(header, `${keyRoot}${headerIdx}${altWcs}`,def);
i++;
}
return retAry;
},
hasKeyStartWith(startKeys){
let key;
for (key in header) {
if (key.startsWith(startKeys)) {
return true;
}
}
return false;
}
};
}
export function makeDoubleHeaderParse(header,zeroHeader,altWcs) {
const hp= makeHeaderParse(header, altWcs);
const zhp= zeroHeader && makeHeaderParse(zeroHeader, altWcs);
return {
header,
zeroHeader,
getIntValue(key, def = 0) {
const v1 = hp.getIntValue(key, NaN);
if (!isNaN(v1)) return v1;
return zhp ? zhp.getIntValue(key, def) : def;
},
getIntOneOfValue: (keyAry, def=0) => {
const v1= hp.getIntOneOfValue(keyAry,NaN);
if (!isNaN(v1)) return v1;
return zhp ? zhp.getIntOneOfValue(keyAry, def) : def;
},
getValue: (key, def = '') => {
const v1 = hp.getValue(key, 'TEST--EMPTY');
if (v1!=='TEST--EMPTY') return v1;
return zhp ? zhp.getValue(key, def) : def;
},
getDoubleValue(key, def) {
const v1 = hp.getDoubleValue(key, NaN);
if (!isNaN(v1)) return v1;
return zhp ? zhp.getDoubleValue(key, def) : def;
},
getDoubleOneOfValue(keyAry, def) {
const v1= hp.getDoubleOneOfValue(keyAry,NaN);
if (!isNaN(v1)) return v1;
return zhp ? zhp.getDoubleOneOfValue(keyAry, def) : def;
},
getDoubleAry(keyRoot,altWcs, startIdx,endIdx,def=undefined) {
if (startIdx>endIdx) return def;
const retAry= hp.getDoubleAry(keyRoot,altWcs,startIdx,endIdx, def);
let validValueArr = retAry.filter( (v)=> v!==def );
if (validValueArr.length>0) return retAry;
return zhp ? zhp.getDoubleAry(keyRoot,altWcs, startIdx,endIdx,def) : def;
},
hasKeyStartWith(startKeys){
if (hp.hasKeyStartWith(startKeys)){
return true;
}
else {
return zhp ? zhp.hasKeyStartWith(startKeys):false;
}
},
isDefinedHeaderList: (list) => hp.isDefinedHeaderList(list) || (zhp && zhp.isDefinedHeaderList(list))
};
}
//=============================================================
//=============================================================
//---------- Header functions
//=============================================================
//=============================================================
/**
*
* @param {WebPlot|Object} plotOrHeader image WebPlot or Header obj
* @param headerKey
* @return {{value:string,comment:string,idx:number}}
*/
function getHeaderObj(plotOrHeader,headerKey) {
if (!plotOrHeader) return {};
if (isPlot(plotOrHeader)) {
const plot= plotOrHeader;
if (!isImage(plot) ) return {};
return get(plot,['header',headerKey],{});
}
else {
return plotOrHeader[headerKey] || {};
}
}
/**
* return a header description given a header key
* @param {WebPlot|Object} plotOrHeader image WebPlot or Header obj
* @param {string} headerKey key
* @return {string} the description of the header if it exist otherwise an empty string
*/
export function getHeaderDesc(plotOrHeader,headerKey) {
return getHeaderObj(plotOrHeader, headerKey)['comment'] || '';
}
/**
* return a header value given a header key
* @param {WebPlot|Object} plotOrHeader image WebPlot or Header obj
* @param {string} headerKey key
* @param {string} [defVal] the default value
* @return {string} the value of the header if it exist, otherwise the default value
*/
export function getHeader(plotOrHeader,headerKey, defVal= undefined) {
return getHeaderObj(plotOrHeader, headerKey)['value'] || defVal;
}
/**
* return a header number value given a header key
* @param {WebPlot|Object} plotOrHeader image WebPlot or Header obj
* @param {string} headerKey key
* @param {number} [defVal] the default value
* @return {number} the number value of the header if it exist and can be converted to a number, otherwise the default value
*/
export function getNumberHeader(plotOrHeader, headerKey, defVal= NaN) {
const v= getHeader(plotOrHeader,headerKey,'');
if (v==='') return defVal;
const n= Number(v);
return isNaN(n) ? defVal : n;
}