Skip to content

DM-7162: adding first skeleton and test for lightcurve handler #161

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Sep 9, 2016
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
@@ -0,0 +1,144 @@
/*
* License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt
*/
package edu.caltech.ipac.firefly.server.query.lc;

import edu.caltech.ipac.astro.IpacTableWriter;
import edu.caltech.ipac.firefly.server.ServerContext;
import edu.caltech.ipac.util.DataGroup;
import edu.caltech.ipac.util.VoTableUtil;
import edu.caltech.ipac.util.download.FailedRequestException;
import edu.caltech.ipac.util.download.URLDownload;
import org.apache.commons.lang.NotImplementedException;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;


/**
* .
* Should handle the LC transformations to get files out of the API result VOtable xml
*
* @author ejoliet
* @see PeriodogramAPIRequest
*/
public class IrsaLightCurveHandler implements LightCurveHandler {


/**
* TODO Update with correct API root url
*/
public final String rootApiUrl = "http://irsa.ipac.caltech.edu/periodogram";

public File getPeriodogramTable(PeriodogramAPIRequest request) {

return ipacTableFromAPI(request, RESULT_TABLES_IDX.PERIODOGRAM);

}


/**
* @return peaks table (default: 50 rows)
*/
public File getPeaksTable(PeriodogramAPIRequest request) {

return ipacTableFromAPI(request, RESULT_TABLES_IDX.PEAKS);
}

/**
* Return a phase folded curve form original light-curve
*
* @param tbl orginal lc table
* @param period period for phase folding the lc curve
* @return phase folded curve (x2 original input table 0,2 phase)
*/
public File toPhaseFoldedTable(File tbl, float period) {
//get raw lcTable and phase fold on time/period
//for now, return same table.
//TODO change it with the implementation DM-7165
return tbl;
}

/**
* Return the API URL to be called to get VOTable from Nexsci, which will contain 2 tables: periodogram and peaks tables.
* <p>
* TODO need to be implemented
*
* @param request object to contain the required paramter to make the API call
* @return the URL object
* @throws MalformedURLException
* @see LightCurveProcessor#computePeriodogram(PeriodogramAPIRequest, java.lang.String)
* @see IrsaLightCurveHandler#buildUrl(PeriodogramAPIRequest)
*/
protected URL buildUrl(PeriodogramAPIRequest request) throws MalformedURLException {
//loop other request and append to rootApiUrl
throw new NotImplementedException("Not yet implemented");
}

protected File extractTblFrom(File votableResult, RESULT_TABLES_IDX resultTable) {
File resultTblFile = null;
try {
resultTblFile = makeResultTempFile(resultTable);
DataGroup[] dataGroups = VoTableUtil.voToDataGroups(votableResult.getAbsolutePath());

IpacTableWriter.save(resultTblFile, dataGroups[resultTable.ordinal()]);
return resultTblFile;
} catch (IOException e) {
e.printStackTrace();
}
return resultTblFile;
}

protected File ipacTableFromAPI(PeriodogramAPIRequest request, RESULT_TABLES_IDX resultTable) {
File tempFile = null;
try {
/**
* @see LightCurveProcessor#computePeriodogram(PeriodogramAPIRequest, java.lang.String)
*/
URL url = buildUrl(request);

File apiResult = apiDownlaod(url);

tempFile = extractTblFrom(apiResult, resultTable);

} catch (IOException e) {
e.printStackTrace();
} catch (FailedRequestException e) {
e.printStackTrace();
}
return tempFile;
}

protected File apiDownlaod(URL url) throws IOException, FailedRequestException {

File apiResultTempFile = makeApiResultTempFile();

URLConnection aconn = URLDownload.makeConnection(url);
aconn.setRequestProperty("Accept", "*/*");
URLDownload.getDataToFile(aconn, apiResultTempFile); //TODO Get from cache

return apiResultTempFile;
}


protected File makeResultTempFile(RESULT_TABLES_IDX resultTable) throws IOException {
String prefix = "error";
switch (resultTable) {
case PERIODOGRAM:
prefix = "periodogram-";
break;
case PEAKS:
prefix = "peaks-";
break;
}

return File.createTempFile(prefix, ".tbl", ServerContext.getTempWorkDir());
}

protected File makeApiResultTempFile() throws IOException {
return File.createTempFile("lc-api-result-", ".xml", ServerContext.getTempWorkDir());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt
*/
package edu.caltech.ipac.firefly.server.query.lc;

import java.io.File;

/**
* Class should handle the input user parameter to
* call an API to
* get at least the periodogram and peaks table
* out of a raw time changin flux curve
*
* @author ejoliet
* @see PeriodogramAPIRequest
*/
public interface LightCurveHandler {
/**
* TODO check ordinals when API call is implemented
* Represent the tables in votable result from API: 0 for periodogram, 1 for peaks
*/
enum RESULT_TABLES_IDX {
PERIODOGRAM, PEAKS
}


/**
* return a periodogram table from a request
*
* @return periodogram (power vs period) file
*/
public File getPeriodogramTable(PeriodogramAPIRequest request);

/**
* Return the table which contains N peaks, N integer from request object
*
* @return peaks table
* @see PeriodogramAPIRequest#getNumberPeaks()
*/
public File getPeaksTable(PeriodogramAPIRequest request);

/**
* TODO add extra output parameters getter that might be interesting
*/
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/*
* License information at https://github.com/Caltech-IPAC/firefly/blob/master/License.txt
*/
package edu.caltech.ipac.firefly.server.query.lc;

import edu.caltech.ipac.firefly.core.EndUserException;
import edu.caltech.ipac.firefly.data.TableServerRequest;
import edu.caltech.ipac.firefly.server.ServerContext;
import edu.caltech.ipac.firefly.server.query.DataAccessException;
import edu.caltech.ipac.firefly.server.query.IpacTablePartProcessor;
import edu.caltech.ipac.firefly.server.query.SearchProcessorImpl;
import edu.caltech.ipac.firefly.server.util.Logger;
import edu.caltech.ipac.firefly.server.util.QueryUtil;
import edu.caltech.ipac.util.AppProperties;
import edu.caltech.ipac.util.StringUtils;
import edu.caltech.ipac.util.download.FailedRequestException;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;

/**
* This class takes care of the LC api call and return result IpacTable Data.
*/

@SearchProcessorImpl(id = "LightCurveProcessor")

public class LightCurveProcessor extends IpacTablePartProcessor {

private static final String PERIODOGRAM_API_URL = AppProperties.getProperty("periodogram.host", "default_periodogram_host_url");

private static final Logger.LoggerImpl _log = Logger.getLogger();

// API will return votable, depending on the request, return either peaks or periodogram table, which names are predefined here:
private static final String PERIODOGRAM_TABLE_NAME = "periodogram_table.tbl";
private static final String PEAKS_TABLE_NAME = "peaks_table.tbl";

/**
* Class handling the API call and returning LC result table
*/
public LightCurveProcessor() {

// TODO enable the nadler in constructor when the NexsciHandler is ready
// LightCurveHandler h = new IrsaLightCurveHandler() {
}

/**
* This method is defined as an abstract in the IpacTablePartProcessor and it is implemented here.
* The TableServerRequest is passed here and processed. Only when the "searchRequest" is set, the request
* is processed.
*
* @return File with statistics on a table
* @throws IOException
* @throws DataAccessException
*/
protected File loadDataFile(TableServerRequest request) throws IOException, DataAccessException {

PeriodogramAPIRequest req = QueryUtil.assureType(PeriodogramAPIRequest.class, request);
String tblType = req.getParam(PeriodogramAPIRequest.TABLE_NAME);
String tblName = (tblType != null && tblType.equalsIgnoreCase(PeriodogramAPIRequest.RESULT_TABLE))
? PERIODOGRAM_TABLE_NAME : PEAKS_TABLE_NAME;

//In order to get any of those tables, computing the periodogram need to happen:
// Result is a Votable containing 2 tables:periodogram and peaks
File resTable = null;
try {
resTable = computePeriodogram(req, tblName);
} catch (FailedRequestException e) {
e.printStackTrace();
}

// if (tblType.equalsIgnoreCase(PeriodogramAPIRequest.PEAKS_TABLE)) {
//
// }

return resTable;
}

/**
* From the request, get the file and the algorithm to compute the peridogram by calling external API
*
* @param req request
* @param tblName table name to distinguish them
* @return table file result either peaks por periodogram
* @throws FailedRequestException
*/
public File computePeriodogram(PeriodogramAPIRequest req, String tblName) throws FailedRequestException {

//Fake call API, parse VOTable result. See for example QueryMOS
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}

//TODO this is used with overwritten method. Once API known, remove and use the handler directly
LightCurveHandler h = new IrsaLightCurveHandler() {

/**
* For testing purposes returned periodogram from here:
* PeriodogramAPIRequest.RESULT_TABLE = "http://web.ipac.caltech.edu/staff/ejoliet/demo/vo-nexsci-result-sample.xml"
* TODO remove after implementing NexsciHandler
* @param req
* @return url api
* @throws MalformedURLException
*/
@Override
protected URL buildUrl(PeriodogramAPIRequest req) throws MalformedURLException {
/**
* For now just download the file from the url from req.getResultTable()
* and stream it out
*/
String SAMPLE_URL = req.getResultTable();
return new URL(SAMPLE_URL);
}
};

// LightCurveHandler h = new IrsaLightCurveHandler();
if (tblName.equalsIgnoreCase(PERIODOGRAM_TABLE_NAME)) {
return h.getPeriodogramTable(req);
} else if (tblName.equalsIgnoreCase(PEAKS_TABLE_NAME)) {
return h.getPeaksTable(req);
} else {
throw new FailedRequestException("Unable to deal with the request table name " + tblName);
}
}

private static File makeFileName(PeriodogramAPIRequest req) throws IOException {
return File.createTempFile("lc-result", ".xml", ServerContext.getPermWorkDir());
}

private URL createURL(PeriodogramAPIRequest req) throws EndUserException, IOException {
PeriodogramAPIRequest request = (PeriodogramAPIRequest) req.cloneRequest();
String url = req.getUrl();
if (url == null || url.length() < 5) {
url = PERIODOGRAM_API_URL;
}
String paramStr = buildParamFrom(request);
if (paramStr.startsWith("&")) {
paramStr = paramStr.substring(1);
}
url += "?" + paramStr;

return new URL(url);
}

private String buildParamFrom(PeriodogramAPIRequest request) {
String outputMode = request.getParam(PeriodogramAPIRequest.OUTPUT_MODE);
if (StringUtils.isEmpty(outputMode)) {
outputMode = "VOTable";
}
return "min_period=0&n_peaks=50";
}
}
Loading