import {ShapesFactory} from "./olqv_shapes.js";
import {createAndAppendFromHTML, str2FloatArray} from "./utils.js";
import {DOMAccessor} from "./domelements.js";
import { ServerApi } from "./serverApi.js";
import {ContoursButton} from "./olqv_olbuttons.js";
/**
* @classdesc A class to create and to manage contours in the 2D part of YAFITS. A contour is a close line joining pixels sharing a given value: the contour level.
* Contours are created and manipulated with the {@link https://openlayers.org/en/v5.3.0/apidoc/|OpenLayers} API. In particular {@link https://openlayers.org/en/v5.3.0/apidoc/module-ol_Feature-Feature.html|Feature} and {@link https://openlayers.org/en/v5.3.0/apidoc/module-ol_geom_LineString-LineString.html| LineString} classes are used.
*
* This class only allows to create the contours as OpenLayers features and to define their behaviour in front of end user interactions.
* How the contour levels are defined and how their edges are calculated are tasks accomplished by instances of the class {@link ContoursFactoryGUI}.
*this.button = document.createElement("button");
* @extends ShapesFactory
*/
class ContoursFactory extends ShapesFactory {
static enter(what) {
//console.group(this.name + "." + what);
}
static exit() {
// console.groupEnd();
}
/**
* Creates an instance
* @param {Viewer} viewer instance of the {@link ./Viewer.html|Viewer} class that will host the contours.
*/
constructor(viewer) {
super(viewer, 'contour');
ContoursFactory.enter(this.constructor.name);
this.mode = this;
this.layer.setZIndex(10);
this.lastBox = null;
this._buttonObject = new ContoursButton(viewer);
/*this.button = document.createElement("button");
this.button.setAttribute("type", "button");
this.button.setAttribute("class", "btn btn-primary btn-sm");
this.button.setAttribute("data-toggle", "modal");
this.button.setAttribute("data-tooltip", "tooltip");
this.button.setAttribute("title", "Work with contours");
this.button.append("C");*/
/*
** This the behaviour when a contour has been selected.
*/
//let self = this;
this.selector.select['LineString'] = (feature) => {
ContoursFactory.enter("A contour is selected");
var p = this.getMeasureContourPromise(feature, this.relFITSFilePath);
p.then(
result => this.selected(result),
error => alert(error)
);
ContoursFactory.exit();
};
/*
** This the behaviour when a contour has been unselected.
*/
this.selector.unselect['LineString'] = (feature) => {
ContoursFactory.enter("A contour is unselected");
this.unselected(feature);
ContoursFactory.exit();
};
/*
** This the behaviour when a selected contour is going to be removed.
*/
this.selector.remove['LineString'] = (f) => {
ContoursFactory.enter("A selected contour is about to be removed");
this.remove(f);
ContoursFactory.exit();
};
ContoursFactory.exit(); // end of ctor
}
/**
* Utility. Returns the toolbox button that will activate this instance.
* @returns a {@link https://developer.mozilla.org/fr/docs/Web/HTML/Element/Button|button}
*/
getButtonObject() {
return this._buttonObject;
}
/*getButtonClick(){
if(this.isVisible){
this._buttonObject.getButton().classList.add("active");
}else{
this._buttonObject.getButton().classList.remove("active");
}
}*/
box(feature) {
console.log("box : entering");
let br = feature.get("properties")["measurements"]["boundingRect"]["value"];
let corners = [[br[0], br[1]],
[br[0] + br[2] - 1, br[1]],
[br[0] + br[2] - 1, br[1] + br[3] - 1],
[br[0], br[1] + br[3] - 1],
[br[0], br[1]]];
this.lastBox = new ol.Feature({ geometry: new ol.geom.Polygon([corners]) });
this.source.addFeature(this.lastBox);
console.log("box : exiting");
}
grid(feature) {
console.log("grid : entering");
let br = feature.get("properties")["measurements"]["boundingRect"]["value"];
let segments = new Array();
for (i = 0; i < br[2]; i++) {
segments.push(new ol.Feature({ geometry: new ol.geom.LineString([[br[0] + i, br[1]], [br[0] + i, br[1] + br[3] - 1]]) }));
}
for (i = 0; i < br[3]; i++) {
segments.push(new ol.Feature({ geometry: new ol.geom.LineString([[br[0], br[1] + i], [br[0] + br[2] - 1, br[1] + i]]) }));
}
this.source.addFeatures(segments);
console.log("grid : exiting");
}
/**
* Physical measure are defined by a numerical value and a physical unit
* @typedef PhysMeas
* @property {number} value - the numerical value
* @property {string} unit - the physical unit
*/
/**
* @typedef {Object} LineStringProperties
* @property {PhysMeas} level - the level of the contour
*
*/
/**
* Bounding rectangle.
* @typedef BoundingRect
* @property {number[4]} value - An array of four numbers representing in that order x, y, w and h.
* @property {string} unit - The unit in which are expressed x, y, w and h. Must be "pixels"
*/
/**
* Statistics on the area delimited by a contour.
* @typedef ContourMeasurement
* @property {PhysMeas} min - the minimum over the pixels values
* @property {PhysMeas} max - the maximum over the pixel values
* @property {PhysMeas} mean - the average of the pixel values
* @property {PhysMeas} stdev - the standard deviation of the pixel values
* @property {number} numpix - the number of pixels
* @property {PhysMeas} "percentage of total number of pixels" - self explanatory ( note that unit in that case is "%" )
* @property {BoundingRect} boundingRect - self explanatory
* @param {*} yAFITSContours
*/
/**
* What is a contour as expected by importYAFITSContours.
* @typedef {Object} LineStringFeature
* @property {string} type - <b>Must be equal to "LineString"</b>
* @property {number[][]} coordinates - an array of 2D coordinates
* @property {LineStringProperties} properties - its properties
*/
/**
* Adds an array of LineStringFeature to the {@link ./Viewer.html|Viewer} and draws them.
*
* @param {LineStringFeature[]} yAFITSContours - an array of {@link LineStringFeature}.
*/
importYAFITSContours(yAFITSContours) {
//ContoursFactory.enter(this.importYAFITSContours.name);
this.clear();
var features = new Array();
yAFITSContours.forEach((contour) => {
let coordinates = contour["coordinates"];
coordinates.push(coordinates[0]);;
let properties = contour["properties"];
properties["type"] = "contour"
let f = new ol.Feature({
geometry: new ol.geom.LineString(coordinates),
properties: properties
});
f.set("label", properties["level"]["value"].toExponential(3));
f.setStyle(this.style_f(f));
features.push(f);
}
);
this.source.addFeatures(features);
this.show();
this.close();
//ContoursFactory.exit()
}
/**
* Promise - Define the behaviour when a contour is selected on the graphic interface.
* @param {LineStringFeature} feature - The contour of area to measure
* @param {string} relFITSFilePath - the path to the FITS file of interest.
* @returns
*/
getMeasureContourPromise(feature, relFITSFilePath) {
ContoursFactory.enter(this.getMeasureContourPromise.name);
var p = new Promise(function (resolve, reject) {
var coordinates = feature.getGeometry().getCoordinates();
let properties = feature.get("properties");
let level = properties["level"]["value"].toExponential(3);
// If the contour has already been measured then victory ...
if ("measurements" in properties) {
resolve(feature);
}
// else measure it,asynchronously, and victory...or defeat
else {
DOMAccessor.showLoaderAction(true);
let serverApi = new ServerApi();
serverApi.measureContours(0, JSON.stringify(coordinates), level, relFITSFilePath, (resp)=>{
if (resp["status"] == false) {
reject(`Something went wrong with the measurements of contour. The message was '${resp["message"]}'`)
} else {
properties["measurements"] = resp["result"];
feature.set("properties", properties);
resolve(feature);
}
});
}
});
ContoursFactory.exit();
return p;
};
selected(contour) {
ContoursFactory.enter(this.selected.name);
/*let properties = contour.get("properties");
let level = properties["level"]["value"].toExponential(3);
let levelUnit = properties["level"]["unit"];
let title = 'Contour level at ' + level + ' ' + levelUnit;
this.infosBlock.headline(title);
this.infosBlock.populate(title, properties["measurements"]);*/
super.selected(contour);
ContoursFactory.exit()
}
open(interaction, cursor) {
ContoursFactory.enter(this.open.name);
super.open(interaction, cursor);
ContoursFactory.exit();
}
}; // End of class ContoursFactory
/**
* @class
* A complete GUI to define the contours levels and trigger their drawing (see {@link ContoursFactory}) once they are defined.
* The GUI is implemented as a modal whose HTML content is defined in the constructor.
* It provides the user with :
* <ul>
* <li> an interactive graphic representation of the pixels values histogram </li>
* <li> a text input area where contours levels numerical values can be entered/edited </li>
* <li> a interactive graphic representation of the pixel values cumulative distribution </li>
* <li> a text input area where quantiles can be entered/edited </li>
* </ul>
* Both graphics representations are clickable and can be used to define contours levels.
* Graphics are done with {@link https://www.highcharts.com/ HighCharts}
*/
class ContoursFactoryGUI {
static enter(what) {
//console.group(this.name + "." + what);
}
static exit() {
//console.groupEnd();
}
static interpolate(x, X, Y, i0, i1) {
ContoursFactoryGUI.enter(ContoursFactoryGUI.interpolate.name);
let result;
if ((i1 - i0) === 0) {
result = Y[i0];
}
else if ((i1 - i0) === 1 ) {
result = (x - X[i0]) * (Y[i1] - Y[i0]) / (X[i1] - X[i0]) + Y[i0]
}
else {
let imid = Math.floor((i0 + i1) / 2);
if (x < X[imid]) {
i1 = imid;
}
else {
i0 = imid;
}
result = ContoursFactoryGUI.interpolate(x, X, Y, i0, i1);
}
ContoursFactoryGUI.exit();
return result
}
/**
* Creates an instance.
* @param {Viewer} viewer - The Viewer that hosts the contours graphics representations.
* @param {string} relFITSFilePath - The path to the FITS file of interest.
*/
constructor(viewer, relFITSFilePath) {
ContoursFactoryGUI.enter(this.constructor.name);
this.viewer = viewer;
this.modalContoursFormId = `ModalContoursForm-${viewer.getDivId()}`;
this.collapseHistogramId = `collapseHistogram-${viewer.getDivId()}`;
this.collapseCumulDistId = `collapseCumulDist-${viewer.getDivId()}`;
this.cumulDistId = `cumulDist-${viewer.getDivId()}`;
this.histogramId = `histogram-${viewer.getDivId()}`;
this.infosBlock = viewer.infosBlock;
this.html = `
<div id="${this.modalContoursFormId}" class="modal fade">
<div class="modal-dialog modal-dialog-scrollable" role="document">
<div class="modal-content">
<div class="modal-header">
<h1 class="modal-title">Contours</h1>
</div>
<div class="modal-body">
<form role="form" method="POST" action="">
<input type="hidden" name="_token" value="">
<div class="form-group">
<a class="btn btn-primary" data-toggle="collapse" href="#${this.collapseHistogramId}" role="button"
aria-expanded="false" aria-controls="collapseExample">
Use the histogram to choose the contours levels...
</a>
<!-- <label class="control-label">Use the histogram to choose the contours levels...</label> -->
<div class="collapse" id="${this.collapseHistogramId}">
<div id="${this.histogramId}" style="height: 400px">
</div>
</div>
<label class="control-label">Enter contour level[s] (comma separated if more than one)</label>
<div>
<input class="form-control levels"></input>
</div>
</div>
<div class="form-group">
<a class="btn btn-primary" data-toggle="collapse" href="#${this.collapseCumulDistId}" role="button"
aria-expanded="false" aria-controls="collapseExample">
...or use the cumulative distribution function to choose the quantiles...
</a>
<div class="collapse" id="${this.collapseCumulDistId}">
<div id="${this.cumulDistId}" style="height: 400px">
</div>
</div>
<label class="control-label">Enter cumulative distribution function value[s] (comma separated if more than
one)</label>
<div>
<input class="form-control text-of-quantiles"></input>
</div>
</div>
</form>
<div class="row">
<div class="col">
<div class="btn-toolbar" role="group" aria-label="Markers actions">
<button type="button" class="btn btn-success update-contours btn-sm ml-1">Draw contours</button>
<button type="button" class="btn btn-success clear-contours btn-sm ml-1">Clear</button>
<button type="button" class="btn btn-success reset-contours btn-sm ml-1">Reset to default</button>
<button type="button" class="btn btn-primary btn-sm ml-1" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
</div>
`;
this.modal = createAndAppendFromHTML(this.html, this.viewer.getMap().getTargetElement());
this.text_of_quantiles = $(this.modal.querySelector(".text-of-quantiles"));
this.levels = $(this.modal.querySelector(".levels"));
this.defaultValue;
this.update_contours = $(this.modal.querySelector(".update-contours"));
let self = this;
function call_contours(event){
self.queryYAFITSContours(event.data.relFITSFilePath);
}
this.update_contours.click({relFITSFilePath : relFITSFilePath},call_contours);
this.levels.keyup(function (event) {
if (event.keyCode === 13) {
event.preventDefault(); /* Not sure this is useful */
this.queryYAFITSContours(relFITSFilePath);
}
}.bind(this));
this.text_of_quantiles.keyup(function (event) {
if (event.keyCode === 13) {
event.preventDefault(); /* Not sure this is useful */
this.queryYAFITSContours(relFITSFilePath);
}
}.bind(this));
this.clear_contours = $(this.modal.querySelector(".clear-contours"));
this.clear_contours.click(this.clear.bind(this));
this.reset_contours = $(this.modal.querySelector(".reset-contours"));
this.reset_contours.click(this.reset.bind(this));
this.contoursFactory = undefined;
this.contoursMethod = undefined;
this.levels.focus(() => { this.contoursMethod = "levels" });
this.text_of_quantiles.focus(() => { this.contoursMethod = "quantiles" });
$(this.modal).on("shown.bs.modal", this.shown.bind(this));
$(this.modal).on("hidden.bs.modal", this.hidden.bind(this));
ContoursFactoryGUI.exit();
}
/**
* Connect the GUI to a {@link ContoursFactory}
* @param {ContoursFactory} contoursFactory - the instance of {@link ContoursFactory} where the contours will be drawn.
*/
connect(contoursFactory) {
ContoursFactoryGUI.enter(this.connect.name);
this.contoursFactory = contoursFactory;
this.contoursFactory.getButtonObject().getButton().setAttribute("data-target", `#${this.modalContoursFormId}`);
ContoursFactoryGUI.exit();
}
/**
* Clear the contents of the GUI input elements
*/
clear() {
ContoursFactoryGUI.enter(this.clear.name);
this.text_of_quantiles.val("");
this.levels.val("");
this.contoursFactory.clear();
this.infosBlock.clear("");
ContoursFactoryGUI.exit();
}
/**
* Reset the contents of the GUI input elements
*/
reset() {
ContoursFactoryGUI.enter(this.reset.name);
this.clear();
if(this.defaultValue !== undefined){
this.levels.val(this.defaultValue);
this.contoursMethod = "levels";
}
ContoursFactoryGUI.exit();
}
shown() {
ContoursFactoryGUI.enter(this.shown.name);
this.contoursFactory.open(this.viewer.defaultInteraction, this.viewer.defaultCursor);
this.drawThings();
ContoursFactoryGUI.exit();
}
hidden() {
ContoursFactoryGUI.enter(this.hidden.name);
this.contoursFactory.close();
document.activeElement.blur()
ContoursFactoryGUI.exit();
}
/**
* Draw everything, i.e. histogram and cumulative distribution
*/
drawThings() {
ContoursFactoryGUI.enter(this.drawThings.name);
this.drawHistogram();
this.drawCumulativeDistribution();
ContoursFactoryGUI.exit();
}
/**
* Draw histogram
*/
drawHistogram() {
ContoursFactoryGUI.enter(this.drawHistogram.name);
let histogram = this.viewer.getStatistics()["histogram"];
let population = histogram[0];
let bins = histogram[1];
let data = new Array(2 * population.length);
for (let i = 0; i < population.length; i++) {
data[i] = [bins[i], population[i]];
data[i + 1] = [bins[i + 1], population[i]];
}
let mean = this.viewer.getStatistics()["mean"]
let stdev = this.viewer.getStatistics()["stdev"]
let that = this;
Highcharts.chart(`${this.histogramId}`, {
chart: {
type: 'line',
zoomType: 'x',
panning: true,
panKey: 'shift'
},
title: {
text: "Histogram of pixels values"
},
xAxis: {
title: { text: "Pixels values" },
minPadding: 0.05,
maxPadding: 0.05
},
yAxis: {
title: { text: "Population" }
},
plotOptions: {
series: {
cursor: 'pointer',
point: {
events: {
click: function (e) {
if (that.hasLevelsDefined())
that.levels.val(that.levels.val() + "," + e.point.x);
else
that.levels.val(e.point.x);
that.levels.focus();
}
}
},
marker: {
lineWidth: 2
}
}
},
series: [
{
name: 'population per bin',
type: 'line',
data: data
},
{
name: 'mean',
type: 'line',
dashStyle: "shortdot",
lineWidth: 2,
data: [
[mean, 0],
[mean, Math.max(...population)]
]
},
{
name: '+sigma',
type: 'line',
dashStyle: "shortdot",
lineWidth: 2,
data: [
[mean + stdev, 0],
[mean + stdev, Math.max(...population)]
]
},
{
name: '+2*sigma',
type: 'line',
dashStyle: "shortdot",
lineWidth: 2,
data: [
[mean + 2 * stdev, 0],
[mean + 2 * stdev, Math.max(...population)]
]
},
{
name: '+3*sigma',
type: 'line',
dashStyle: "shortdot",
lineWidth: 2,
data: [
[mean + 3 * stdev, 0],
[mean + 3 * stdev, Math.max(...population)]
]
}
]
});
ContoursFactoryGUI.exit();
}
/**
* Draw cumulative distribution.
*/
drawCumulativeDistribution() {
ContoursFactoryGUI.enter(this.drawCumulativeDistribution.name);
let histogram = this.viewer.getStatistics()["histogram"];
let bins = histogram[1];
let cumulDist = this.viewer.getStatistics()["cumuldist"];
let data = new Array(cumulDist.length);
for (let i = 0; i < data.length; i++) {
data[i] = [bins[i], cumulDist[i]];
}
let mean = this.viewer.getStatistics()["mean"]
let stdev = this.viewer.getStatistics()["stdev"]
let that = this;
let cumul_mean = ContoursFactoryGUI.interpolate(mean, bins, cumulDist, 0, data.length - 2);
let cumul_stdev = ContoursFactoryGUI.interpolate(mean + stdev, bins, cumulDist, 0, data.length - 2);
let cumul_two_stdev = ContoursFactoryGUI.interpolate(mean + 2 * stdev, bins, cumulDist, 0, data.length - 2);
let cumul_three_stdev = ContoursFactoryGUI.interpolate(mean + 3 * stdev, bins, cumulDist, 0, data.length - 2);
Highcharts.chart(`${this.cumulDistId}`, {
chart: {
type: 'line',
zoomType: 'x',
panning: true,
panKey: 'shift'
},
title: {
text: "Cumulative distribution function"
},
xAxis: {
title: { text: "Pixels values" },
minPadding: 0.05,
maxPadding: 0.05
},
yAxis: {
title: { text: "Cumulative distribution" }
},
plotOptions: {
series: {
cursor: 'pointer',
point: {
events: {
click: function (e) {
if (that.hasQuantilesDefined())
that.text_of_quantiles.val(that.text_of_quantiles.val() + "," + e.point.y);
else
that.text_of_quantiles.val(e.point.y);
that.text_of_quantiles.focus();
}
}
},
marker: {
lineWidth: 1
}
}
},
series: [
{
name: "cumulative distribution",
type: "line",
data: data
},
{
name: 'mean',
type: 'line',
dashStyle: "shortdot",
lineWidth: 2,
data: [
[mean, 0.],
[mean, cumul_mean]
]
},
{
name: '+sigma',
type: 'line',
dashStyle: "shortdot",
lineWidth: 2,
data: [
[mean + stdev, 0],
[mean + stdev, cumul_stdev]
]
},
{
name: '+2*sigma',
type: 'line',
dashStyle: "shortdot",
lineWidth: 2,
data: [
[mean + 2 * stdev, 0],
[mean + 2 * stdev, cumul_two_stdev]
]
},
{
name: '+3*sigma',
type: 'line',
dashStyle: "shortdot",
lineWidth: 2,
data: [
[mean + 3 * stdev, 0],
[mean + 3 * stdev, cumul_three_stdev]
]
}
]
});
ContoursFactoryGUI.exit();
}
/**
* Checks if the levels input area has values (true) or not (false)
* @returns {boolean}
*
*/
hasLevelsDefined() {
var result = this.levels.val().trim() != "";
return result;
}
/**
* Checks if the quantiles input area has values (true) or not (false)
* @returns {boolean}
*
*/
hasQuantilesDefined() {
var result = this.text_of_quantiles.val().trim() != "";
return result;
}
/**
* Parse the content of the levels text input area into an array of numbers
* @returns {number[]|false}
*/
parseTextOfLevels() {
ContoursFactoryGUI.enter(this.parseTextOfLevels.name);
let result = false;
let text = this.levels.val();
let x = str2FloatArray(text);
if (x) {
result = x.sort();
this.levels.val(result);
}
else {
alert("Input invalid to express a sequence of levels.");
}
ContoursFactoryGUI.exit();
return result;
}
/**
* Parse the content of the quantiles text input area into an array of numbers
* @returns {number[]|false}
*/
parseTextOfQuantiles() {
ContoursFactoryGUI.enter(this.parseTextOfQuantiles.name);
let result = false;
let text = this.text_of_quantiles.val();
let x = str2FloatArray(text, [0, 1]);
if (x) {
result = x.sort();
this.text_of_quantiles.val(result);
}
else {
alert("Input invalid to express a sequence of quantiles. It must be a ascending sequence of numbers in [0., 1.]");
}
ContoursFactoryGUI.exit();
return result;
}
/**
* When contours are calculated from their levels values.
* @typedef {Object} ContoursLevelsPostParams
* @property {number} iFreq - the index of the RA/DEC plane of interest.
* @property {number[]} levels - the array of levels numerical values.
*
*/
/**
* When contours are calculated from their quantiles values.
* @typedef {Object} ContoursQuantilesPostParams
* @property {number} iFreq - the index of the RA/DEC plane of interest.
* @property {number[]} quantiles - the array of quantiles numerical values.
*/
/**
* Union of ContoursLevelsPostParams and ContoursQuantilesPostParams
* @typedef {ContoursLevelsPostParams | ContoursQuantilesPostParams} ContoursOptParams
*/
/**
* How is structured the parameter sent to the contours lines calculator.
* @typedef {Object} ContoursPostParams
* @property {string} relFITSFilePath - the path to the FITS file of interest
* @property {string} optParams - JSON representation of a {@link ContoursOptParams}
*/
/**
* Promise. What has to be done to obtain the contours lines given their levels|quantiles.
* @param {ContoursPostParams} postParams
* @returns {LineStringFeature[]}
*/
getContoursPromise(postParams) {
ContoursFactoryGUI.enter(this.getContoursPromise.name);
let serverApi = new ServerApi();
var p = new Promise(function (resolve, reject) {
DOMAccessor.showLoaderAction(true);
serverApi.getContours(postParams, (resp)=>{
if (resp["status"] == false) {
reject(`Error 2 : Something went wrong during the generation of the contours. The message was '${resp["message"]}'`);
}
else {
resolve(resp["result"]["features"]);
}
})
})
ContoursFactoryGUI.exit();
return p;
}
/**
* Obtain the contours lines corresponding to the choosen levels or quantiles and trigger their drawings performed by the connected instance of {@link ContoursFactory}.
* @param {string} relFITSFilePath - The path to the FITS file of interest.
*/
queryYAFITSContours(relFITSFilePath) {
ContoursFactoryGUI.enter(this.queryYAFITSContours.name);
DOMAccessor.showLoaderAction(true);
// Actually the returned value is reduced to a single integer.
let iFREQ = this.viewer.getSliceRange();
let postParams;
var self = this;
// Build the parameters to accompany the POST, depends on the choosen contours calculation method.
switch (this.contoursMethod) {
case "levels":
if (this.hasLevelsDefined()) {
let levels = this.parseTextOfLevels();
if (levels) {
postParams = { 'relFITSFilePath': relFITSFilePath, 'optParams': JSON.stringify({ 'iFREQ': iFREQ, 'levels': levels }, 0, 4) }
}
}
else {
alert("No levels defined");
}
break;
case "quantiles":
if (this.hasQuantilesDefined()) {
let quantiles = this.parseTextOfQuantiles();
if (quantiles) {
postParams = { 'relFITSFilePath': relFITSFilePath, 'optParams': JSON.stringify({ 'iFREQ': iFREQ, 'quantiles': quantiles }, 0, 4) }
}
}
else {
alert("No quantiles defined");
}
break;
default:
alert("No contours method defined");
}
// Trigger the contours calculation promise. On positive return draw the contours.
if (postParams) {
var p = this.getContoursPromise(postParams);
p.then (
result => {
self.contoursFactory.importYAFITSContours(result);
$(`#${self.modalContoursFormId}`).modal("hide");
},
error => {
alert(`Error 1 : Something went wrong during the generation of the contours. The message was "${error}"`);
}
)
}else{
DOMAccessor.showLoaderAction(false);
}
ContoursFactoryGUI.exit();
}
drawYAFITSContoursByLevels(levels, relFITSFilePath) {
this.levels.val(levels.join(","));
this.contoursMethod = "levels";
this.queryYAFITSContours(relFITSFilePath);
}
setDefaultValue(levels){
this.levels.val(levels.join(","));
this.contoursMethod = "levels";
this.defaultValue = levels.join(",");
}
}; // End of class ContoursFactoryGUI
export {
ContoursFactory, ContoursFactoryGUI
}