Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package edu.caltech.ipac.firefly.server.query;

import edu.caltech.ipac.firefly.data.*;
import edu.caltech.ipac.firefly.data.DownloadRequest;
import edu.caltech.ipac.firefly.data.FileInfo;
import edu.caltech.ipac.firefly.data.HttpResultInfo;
import edu.caltech.ipac.firefly.data.ServerRequest;
import edu.caltech.ipac.firefly.server.ServerContext;
import edu.caltech.ipac.firefly.server.db.EmbeddedDbUtil;
import edu.caltech.ipac.firefly.server.network.HttpServiceInput;
Expand All @@ -9,12 +12,17 @@
import edu.caltech.ipac.table.DataGroup;
import edu.caltech.ipac.table.MappedData;
import edu.caltech.ipac.table.io.VoTableReader;
import edu.caltech.ipac.util.FileUtil;
import edu.caltech.ipac.util.download.URLDownload;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static edu.caltech.ipac.util.FileUtil.getUniqueFileNameForGroup;
import static org.apache.commons.lang.StringUtils.substringAfterLast;
Expand Down Expand Up @@ -55,27 +63,32 @@ private List<FileGroup> computeFileGroup(DownloadRequest request) throws DataAcc
String contentType = tmpFileInfo.getAttribute(HttpResultInfo.CONTENT_TYPE);

String colNames = request.getSearchRequest().getParam("templateColNames");
boolean useSourceUrlFileName= request.getSearchRequest().getBooleanParam("useSourceUrlFileName",false);
String[] cols = colNames != null ? colNames.split(",") : null;

String ext_file_name = getFileName(idx,cols,dgDataUrl);
String ext_file_name = getFileName(idx,cols,useSourceUrlFileName,dgDataUrl,url);
String extension;

if (access_format != null) {
if (access_format.contains("datalink")) {
ext_file_name = getUniqueFileNameForGroup(ext_file_name, dataLinkFolders);
List<FileInfo> tmpFileInfos = parseDatalink(url, ext_file_name);
List<FileInfo> tmpFileInfos = parseDatalink(url, ext_file_name, useSourceUrlFileName);
fileInfos.addAll(tmpFileInfos);
}
else { //non datalink entry - such as fits,jpg etc.
extension = access_format.replaceAll(".*/", "");
ext_file_name += "." + extension;
if (!useSourceUrlFileName || !FileUtil.getExtension(ext_file_name).isEmpty()) {
extension = access_format.replaceAll(".*/", "");
ext_file_name += "." + extension;
}
FileInfo fileInfo = new FileInfo(tmpFile.getPath(), ext_file_name, 0);
fileInfos.add(fileInfo);
}
}
else { //access_format is null, so try and get it from the url's Content_Type
extension = getExtFromURL(contentType);
ext_file_name += "." + extension;
if (!useSourceUrlFileName || !FileUtil.getExtension(ext_file_name).isEmpty()) {
extension = getExtFromURL(contentType);
ext_file_name += "." + extension;
}
FileInfo fileInfo = new FileInfo(tmpFile.getPath(), ext_file_name, 0);
fileInfos.add(fileInfo);
}
Expand All @@ -89,7 +102,7 @@ private List<FileGroup> computeFileGroup(DownloadRequest request) throws DataAcc
return Arrays.asList(new FileGroup(fileInfos, null, 0, "ObsCore Download Files"));
}

public static List<FileInfo> parseDatalink(URL url, String prepend_file_name) {
public static List<FileInfo> parseDatalink(URL url, String prepend_file_name, boolean useSourceUrlFileName) {
List<FileInfo> fileInfos = new ArrayList<>();;
try {
File tmpFile = File.createTempFile("datlink-", ".xml", ServerContext.getTempWorkDir());
Expand Down Expand Up @@ -125,13 +138,26 @@ public static List<FileInfo> parseDatalink(URL url, String prepend_file_name) {

if (testSem(sem,"#this") || testSem(sem,"#thumbnail") ||testSem(sem,"#preview") ||
testSem(sem,"#preview-plot")) {
String ext_file_name = prepend_file_name;
ext_file_name = testSem(sem, "#this") ? ext_file_name : ext_file_name + "-" + substringAfterLast(sem, "#");
String extension = "unknown";
extension = content_type != null ? getExtFromURL(content_type) : getExtFromURL(accessUrl);
ext_file_name += "." + extension;
//create a folder only if makeDataLinkFolder is true
ext_file_name = makeDataLinkFolder ? prepend_file_name + "/" + ext_file_name : ext_file_name;

String ext_file_name= null;
if (useSourceUrlFileName) {
String fileName= new URL(accessUrl).getFile();
String ext= FileUtil.getExtension(fileName);
if (!ext.isEmpty()) ext_file_name= fileName;
}
if (ext_file_name==null){
ext_file_name = prepend_file_name;
ext_file_name = testSem(sem, "#this") ? ext_file_name : ext_file_name + "-" + substringAfterLast(sem, "#");
String extension = "unknown";
extension = content_type != null ? getExtFromURL(content_type) : getExtFromURL(accessUrl);
ext_file_name += "." + extension;
//create a folder only if makeDataLinkFolder is true
ext_file_name = makeDataLinkFolder ? prepend_file_name + "/" + ext_file_name : ext_file_name;
}




FileInfo fileInfo = new FileInfo(accessUrl, ext_file_name, 0);
fileInfos.add(fileInfo);
}
Expand Down Expand Up @@ -170,13 +196,20 @@ public static String makeValidString(String val) {
//remove spaces and replace all non-(alphanumeric,period,underscore,hyphen) chars with underscore
return val.replaceAll("\\s", "").replaceAll("[^a-zA-Z0-9._-]", "_");
}
public static String getFileName(int idx, String[] colNames, MappedData dgDataUrl) {
public static String getFileName(int idx, String[] colNames, boolean useSourceUrlFileName, MappedData dgDataUrl, URL url) {
String obs_collection = (String) dgDataUrl.get(idx, "obs_collection");
String instrument_name = (String) dgDataUrl.get(idx, "instrument_name");
String obs_id = (String) dgDataUrl.get(idx, "obs_id");
String obs_title = (String) dgDataUrl.get(idx, "obs_title");
String file_name = "";

//option 0: if useSourceUrlFileName is true the try to get it from the URL
if (useSourceUrlFileName) {
String fileName= url.getFile();
String ext= FileUtil.getExtension(fileName);
if (!ext.isEmpty()) return fileName;
}

//option 1: use productTitleTemplate (colNames) if available to construct file name
if (colNames != null) {
for(String col : colNames) {
Expand Down
12 changes: 9 additions & 3 deletions src/firefly/js/templates/common/ttFeatureWatchers.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {dispatchAddTableTypeWatcherDef} from '../../core/MasterSaga.js';
import {dispatchTableUiUpdate} from '../../tables/TablesCntlr.js';
import {getActiveTableId, getMetaEntry, getTableUiByTblId, getTblById} from '../../tables/TableUtil.js';
import {DownloadButton, DownloadOptionPanel} from '../../ui/DownloadDialog.jsx';
import {getTapObsCoreOptions} from '../../ui/tap/TableSearchHelpers.jsx';
import {getTapObsCoreOptions, getTapObsCoreOptionsGuess} from '../../ui/tap/TableSearchHelpers.jsx';
import {isObsCoreLike} from '../../voAnalyzer/TableAnalysis.js';
import {getCatalogWatcherDef} from '../../visualize/saga/CatalogWatcher.js';
import {getUrlLinkWatcherDef} from '../../visualize/saga/UrlLinkWatcher.js';
Expand Down Expand Up @@ -66,11 +66,17 @@ function setupObsCorePackaging(tbl_id) {
}

function updateSearchRequest( tbl_id='', dlParams='', sRequest=null) {
const template= getAppOptions().tapObsCore?.productTitleTemplate;
const hostname= new URL(sRequest.source)?.hostname;

const template= getTapObsCoreOptionsGuess(hostname)?.productTitleTemplate;
const useSourceUrlFileName= getTapObsCoreOptionsGuess(hostname)?.packagerUsesSourceUrlFileName;


const templateColNames= template && getColNameFromTemplate(template);
const searchRequest = cloneDeep( sRequest);
searchRequest.template = template;
searchRequest.templateColNames = templateColNames?.toString();
searchRequest.useSourceUrlFileName= useSourceUrlFileName;
return searchRequest;
}

Expand All @@ -85,7 +91,7 @@ const PrepareDownload = React.memo(() => {
<div>
<DownloadButton>
<DownloadOptionPanel {...{
updateSearchRequest: updateSearchRequest,
updateSearchRequest,
showZipStructure: false, //flattened files, except for datalink (with more than one valid file)
dlParams: {
FileGroupProcessor:'ObsCorePackager',
Expand Down
13 changes: 12 additions & 1 deletion src/firefly/js/ui/tap/TableSearchHelpers.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import HelpIcon from 'firefly/ui/HelpIcon';
import {isEqual} from 'lodash';
import {isEqual, isObject} from 'lodash';
import Prism from 'prismjs';
import PropTypes from 'prop-types';
import React, {useEffect, useRef} from 'react';
Expand Down Expand Up @@ -30,6 +30,17 @@ const DEF_ERR_MSG= 'Constraints Error';
export const getTapObsCoreOptions= (serviceLabel) =>
getAppOptions().tapObsCore?.[serviceLabel] ?? getAppOptions().tapObsCore ?? {};



export function getTapObsCoreOptionsGuess(serviceLabelGuess) {
const {tapObsCore={}}= getAppOptions();
if (!serviceLabelGuess) return tapObsCore;
const guessKey= Object.entries(tapObsCore)
.find( ([key,value]) => isObject(value) && serviceLabelGuess.includes(key))?.[0];
return getTapObsCoreOptions(guessKey);
}


/**
* make a FieldErrorList object
* @returns {FieldErrorList}
Expand Down
9 changes: 9 additions & 0 deletions src/firefly/js/ui/tap/TapSearchRootPanel.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {dispatchTableSearch} from 'firefly/tables/TablesCntlr.js';
import {showInfoPopup, showYesNoPopup} from 'firefly/ui/PopupUtil.jsx';
import {dispatchHideDialog} from 'firefly/core/ComponentCntlr.js';
import {dispatchHideDropDown} from 'firefly/core/LayoutCntlr.js';
import {MetaConst} from '../../data/MetaConst.js';
import {
ConstraintContext, getTapUploadSchemaEntry, getUploadServerFile, getUploadTableName,
getHelperConstraints, getUploadConstraint,
Expand All @@ -32,6 +33,7 @@ import {
import {SectionTitle, AdqlUI, BasicUI} from 'firefly/ui/tap/TableSelectViewPanel.jsx';
import {useFieldGroupMetaState} from '../SimpleComponent.jsx';
import {PREF_KEY} from 'firefly/tables/TablePref.js';
import {getTapObsCoreOptions} from './TableSearchHelpers.jsx';



Expand Down Expand Up @@ -98,6 +100,10 @@ export function getServiceLabel(serviceUrl) {
return (serviceUrl && (tapOps.find( (e) => e.value===serviceUrl)?.labelOnly)) || '';
}

export function getServiceHiPS(serviceUrl) {
const tapOps= getTapServices();
return (serviceUrl && (tapOps.find( (e) => e.value===serviceUrl)?.hipsUrl)) || '';
}


export function TapSearchPanel({initArgs= {}, titleOn=true}) {
Expand Down Expand Up @@ -384,6 +390,7 @@ function onTapSearchSubmit(request,serviceUrl,tapBrowserState) {
const hasMaxrec = !isNaN(parseInt(maxrec));
const doSubmit = () => {
const serviceLabel= getServiceLabel(serviceUrl);
const hips= getServiceHiPS(serviceUrl);
const adqlClean = adql.replace(/\s/g, ' '); // replace all whitespaces with spaces
const params = {serviceUrl, QUERY: adqlClean};
if (isUpload) {
Expand All @@ -399,6 +406,8 @@ function onTapSearchSubmit(request,serviceUrl,tapBrowserState) {
additionalMeta[PREF_KEY]= `${tapBrowserState.schemaName}-${tapBrowserState.tableName}`;
}
additionalMeta.serviceLabel= serviceLabel;
if (hips) additionalMeta[MetaConst.COVERAGE_HIPS]= hips;

treq.META_INFO= {...treq.META_INFO, ...additionalMeta };
dispatchTableSearch(treq, {backgroundable: true, showFilters: true, showInfoButton: true});
};
Expand Down
24 changes: 22 additions & 2 deletions src/firefly/js/visualize/ZoomUtil.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,28 @@ import {convertAngle} from './VisUtil.js';
*/
export const FullType = new Enum(['ONLY_WIDTH', 'WIDTH_HEIGHT', 'ONLY_HEIGHT']);

export const imageLevels= [.0125, .025, .05,.1,.25,.3, .4, .5, .75, .8, .9, 1, 1.25, 1.5,2, 2.5,3, 3.5,
4,5, 6, 7,8, 9, 10, 11, 12, 13, 14, 15, 16, 18,20,22,24,28, 32];
/**
* This is the master list of zoom levels for Firefly image displays.
* These zoom levels are used when clicking on the +/- icons, and are
* also used to construct the zoom-level dialog. Scroll-wheel zooming
* can reach levels between the steps.
*/

export const imageLevels = [
/* For zoomed-out images we use large steps - factors of 2. */
0.015625, 0.03125, 0.0625, 0.125, 0.25,
/* Otherwise we use four steps per factor of two, */
/* i.e., the 4th root of 2 or about 1.189 / 19%, */
/* rounded to three digits after the decimal. */
0.297, 0.354, 0.420, 0.5,
0.595, 0.707, 0.841, 1,
1.189, 1.414, 1.682, 2,
2.378, 2.828, 3.364, 4,
4.757, 5.657, 6.727, 8,
9.514, 11.314, 13.454, 16,
19.027, 22.627, 26.909, 32
];

export const imageLevelsReversed= [...imageLevels].reverse();


Expand Down
9 changes: 4 additions & 5 deletions src/firefly/js/visualize/reducer/HandlePlotCreation.js
Original file line number Diff line number Diff line change
Expand Up @@ -327,12 +327,11 @@ function plotOverlayFail(state,action) {
}

function plotFail(state,action) {
const {description, plotId}= action.payload;
const {plotViewAry}= state;
const plotView= getPlotViewById(state,plotId);
if (!plotView) return state;
const {description, plotId, plotIdAry:inPlotIdAry=[]}= action.payload;
const plotIdAry= plotId ? [plotId] : inPlotIdAry;
const changes= {plottingStatusMsg:description,serverCall:'fail', nonRecoverableFail:true };
return {...state, plotViewAry:clonePvAry(plotViewAry,plotId,changes)};
const plotViewAry= state.plotViewAry?.map( (pv) => plotIdAry.includes(pv.plotId) ? {...pv,...changes} : pv);
return {...state, plotViewAry};
}

function hipsFail(state,action) {
Expand Down
3 changes: 2 additions & 1 deletion src/firefly/js/visualize/task/PlotImageTask.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ async function executeGroupSearch(rawAction, dispatcher) {
const wpResult= await callGetWebPlotGroup(wpRequestAry, requestKey);
processPlotImageSuccessResponse(dispatcher,rawAction.payload,wpResult);
} catch (e) {
dispatcher( { type: ImagePlotCntlr.PLOT_IMAGE_FAIL, payload: {wpRequestAry, error:e} } );
const plotIdAry= wpRequestAry.map( (r) => r.getPlotId()).filter( (id) => id);
dispatcher( { type: ImagePlotCntlr.PLOT_IMAGE_FAIL, payload: {plotIdAry, wpRequestAry, error:e} } );
logger.error('plot group error', e);
}
}
Expand Down