Compare commits
3 Commits
developmen
...
dev/plotte
Author | SHA1 | Date |
---|---|---|
David Pineau | 777b2bbf0b | |
Lam Pham-Sy | 49e6510b7a | |
Lam Pham-Sy | d819d71049 |
117
README.md
117
README.md
|
@ -9,6 +9,7 @@ multiple components making up the whole Project.
|
||||||
* [Shuffle](#shuffle) to shuffle an array.
|
* [Shuffle](#shuffle) to shuffle an array.
|
||||||
* [Errors](#errors) load an object of errors instances.
|
* [Errors](#errors) load an object of errors instances.
|
||||||
- [errors/arsenalErrors.json](errors/arsenalErrors.json)
|
- [errors/arsenalErrors.json](errors/arsenalErrors.json)
|
||||||
|
* [Plotter] (#plotter) plot graphs from data files
|
||||||
|
|
||||||
## Guidelines
|
## Guidelines
|
||||||
|
|
||||||
|
@ -46,3 +47,119 @@ console.log(errors.AccessDenied);
|
||||||
// AccessDenied: true }
|
// AccessDenied: true }
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Plotter
|
||||||
|
|
||||||
|
It supports to plot a simple graph or multiple graphs.
|
||||||
|
|
||||||
|
- Simple graph: only one graph is plotted
|
||||||
|
- Multiplot: multiple graphs are plotted
|
||||||
|
|
||||||
|
Before plotting graph, we need define config parameters for Plotter vian
|
||||||
|
a '.json' file or an object.
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
``` js
|
||||||
|
import Plotter from 'arsenal';
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Use '.json' file
|
||||||
|
|
||||||
|
This file should have the following structure:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
{
|
||||||
|
"dataFolder": "./tests/functional", // REQUIRED
|
||||||
|
"dataFile": "data.txt", // REQUIRED
|
||||||
|
"output": "simple_file", // REQUIRED
|
||||||
|
"method": "simple", // or "multiplot", optional, default "simple"
|
||||||
|
"width": 12, // optional, default 29.7cm
|
||||||
|
"height": 10, // optional, default 21cm
|
||||||
|
// for simple plot, xCol must be an positive number
|
||||||
|
"xCol": 1, // optional, default 1
|
||||||
|
// for simple plot, yCol must be an array. Each element must be either a
|
||||||
|
// number or an array of length 2. In the latter case, a line with
|
||||||
|
// yerrorbars will be plotted
|
||||||
|
"yCols": [2, 3, [4, 5], 6], // optional, default [2]
|
||||||
|
"font": "CMR14", // optional, default CMR14
|
||||||
|
"fontSize": 14, // optional, default 12
|
||||||
|
"title": "Simple plot", // optional, default 'title'
|
||||||
|
"xLabel": "x-axis label", // optional, default 'xLabel'
|
||||||
|
"yLabel": "y-axis label", // optional, default 'yLabel'
|
||||||
|
"lineTitle": ["Test1", "Test2", "Test 3", "Test 4"], // optional
|
||||||
|
"message": "Functional test for plotter, use config file", // optional
|
||||||
|
"grid": "xtics ytics", // optional, default 'xtics ytics'
|
||||||
|
"styleData": "linespoints", // optional, default 'linespoints'
|
||||||
|
"lineSize": 1, // optional, default 1
|
||||||
|
"pointSize": 1, // optional, default 1
|
||||||
|
"legendPos": "top right" // optional default "top right"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, plot graph by
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
process.env.PLOTTER_CONFIG_FILE = 'path_to_the_json_config_file';
|
||||||
|
const plotter = new Plotter();
|
||||||
|
plotter.plotData(err => {
|
||||||
|
if (err) {
|
||||||
|
// error occurs
|
||||||
|
}
|
||||||
|
// plot's done
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Use object
|
||||||
|
|
||||||
|
Define an object containing parameters for Plotter:
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const config = {
|
||||||
|
dataFolder: './tests/functional',
|
||||||
|
dataFile: 'data.txt',
|
||||||
|
output: 'multiplot_arg',
|
||||||
|
method: 'multiplot',
|
||||||
|
nbGraphsPerRow: 3,
|
||||||
|
nbGraphsPerCol: 2,
|
||||||
|
width: 10,
|
||||||
|
height: 5,
|
||||||
|
// for multiple plot, xCol must be an array of 1 element or
|
||||||
|
// nbGraphsPerRow * nbGraphsPerCol elements. In the first case, x-axis
|
||||||
|
// is the same for all graphs
|
||||||
|
xCol: [1, 1, 1, 1, 1, 1],
|
||||||
|
// for multiple plot, yCol must be an array of
|
||||||
|
// nbGraphsPerRow * nbGraphsPerCol elements. Each element must be either a
|
||||||
|
// number or an array. In the latter case, the array can contains either
|
||||||
|
// positive number or array of length 2 (same as simple plot)
|
||||||
|
yCols: [[2, 3], 3, [[4, 5]], [4, 6], [2, 5], [6]],
|
||||||
|
graphsOrder: 'rowsfirst',
|
||||||
|
font: 'CMR14',
|
||||||
|
fontSize: 14,
|
||||||
|
title: 'Multiplot',
|
||||||
|
xLabel: ['xLabel1', 'xLabel2', 'xLabel3', 'xLabel4', 'xLabel5',
|
||||||
|
'xLabel6'],
|
||||||
|
yLabel: ['yLabel1', 'yLabel2', 'yLabel3', 'yLabel4', 'yLabel5',
|
||||||
|
'yLabel6'],
|
||||||
|
lineTitle: [['Col2', 'Col3'], ['Col3'], ['Col4-5'],
|
||||||
|
['Col4', 'Col6'], ['Col2', 'Col5'], ['Col6']],
|
||||||
|
message: 'Functional test for plotter, config via argument',
|
||||||
|
grid: 'xtics ytics',
|
||||||
|
styleData: 'linespoints',
|
||||||
|
lineSize: 1,
|
||||||
|
pointSize: 1,
|
||||||
|
legendPos: 'top left',
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then, plot graph by
|
||||||
|
|
||||||
|
```javascript
|
||||||
|
const plotter = new Plotter(config);
|
||||||
|
plotter.plotData(err => {
|
||||||
|
if (err) {
|
||||||
|
// error occurs
|
||||||
|
}
|
||||||
|
// plot's done
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
1
index.js
1
index.js
|
@ -3,4 +3,5 @@ module.exports = {
|
||||||
errors: require('./lib/errors.js'),
|
errors: require('./lib/errors.js'),
|
||||||
shuffle: require('./lib/shuffle'),
|
shuffle: require('./lib/shuffle'),
|
||||||
stringHash: require('./lib/stringHash'),
|
stringHash: require('./lib/stringHash'),
|
||||||
|
plotter: require('./lib/plotter'),
|
||||||
};
|
};
|
||||||
|
|
|
@ -0,0 +1,343 @@
|
||||||
|
'use strict'; // eslint-disable-line strict
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const spawn = require('child_process').spawn;
|
||||||
|
const stderr = process.stderr;
|
||||||
|
|
||||||
|
const simple = 'simple';
|
||||||
|
const multiplot = 'multiplot';
|
||||||
|
|
||||||
|
function getConfig() {
|
||||||
|
let config;
|
||||||
|
let configFilePath;
|
||||||
|
if (process.env.PLOTTER_CONFIG_FILE !== undefined) {
|
||||||
|
configFilePath = process.env.PLOTTER_CONFIG_FILE;
|
||||||
|
} else {
|
||||||
|
configFilePath = './config.json';
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const data = fs.readFileSync(configFilePath, { encoding: 'utf-8' });
|
||||||
|
config = JSON.parse(data);
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(`could not parse config file: ${err.message}`);
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Plotter {
|
||||||
|
/**
|
||||||
|
* @param {Object} _config: configuration for plotter
|
||||||
|
* @return {this} Plotter
|
||||||
|
*/
|
||||||
|
constructor(_config) {
|
||||||
|
const config = _config || getConfig();
|
||||||
|
|
||||||
|
if (!config) {
|
||||||
|
throw new Error('missing config for Plotter\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!config.dataFile) {
|
||||||
|
throw new Error('missing data file in config\n');
|
||||||
|
}
|
||||||
|
if (!config.output) {
|
||||||
|
throw new Error('missing name for output files in config\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.gnuExt = '.gnu';
|
||||||
|
this.outputExt = '.pdf';
|
||||||
|
|
||||||
|
this.method = config.method || simple;
|
||||||
|
|
||||||
|
// folder where data, gnu, output files locate
|
||||||
|
this.dataFolder = config.dataFolder;
|
||||||
|
|
||||||
|
this.dataFile = `${this.dataFolder}/${config.dataFile}`;
|
||||||
|
this.output = `${this.dataFolder}/${config.output}${this.outputExt}`;
|
||||||
|
this.gnuFile = `${this.dataFolder}/${config.output}${this.gnuExt}`;
|
||||||
|
|
||||||
|
// data column for x-axis
|
||||||
|
this.xCol = config.xCol || 1;
|
||||||
|
// data column for y-axis
|
||||||
|
this.yCols = config.yCols || [2];
|
||||||
|
// data can be given as an array instead of froma data file
|
||||||
|
this.data = config.data;
|
||||||
|
|
||||||
|
// graph config
|
||||||
|
this.width = config.width || 29.7;
|
||||||
|
this.height = config.height || 21;
|
||||||
|
this.font = config.font || 'CMR14';
|
||||||
|
this.fontSize = config.fontSize || 12;
|
||||||
|
this.title = config.title || 'title';
|
||||||
|
this.xLabel = config.xLabel || 'xLabel';
|
||||||
|
this.yLabel = config.yLabel || 'yLabel';
|
||||||
|
this.lineTitle = config.lineTitle;
|
||||||
|
this.message = config.message.replace(/\n#/g, '\\n').replace(/#/g, '');
|
||||||
|
this.grid = config.grid || 'xtics ytics';
|
||||||
|
this.styleData = config.styleData || 'linespoints';
|
||||||
|
this.lineSize = config.lineSize || 1;
|
||||||
|
this.pointSize = config.pointSize || 1;
|
||||||
|
this.legendPos = config.legendPos || 'top left';
|
||||||
|
|
||||||
|
/* for multiplot */
|
||||||
|
this.nbGraphsPerCol = config.nbGraphsPerCol || 1;
|
||||||
|
this.nbGraphsPerRow = config.nbGraphsPerRow || 1;
|
||||||
|
this.nbGraphs = this.nbGraphsPerCol * this.nbGraphsPerRow;
|
||||||
|
this.graphsOrder = config.graphsOrder || 'rowsfirst';
|
||||||
|
this.layout = `${this.nbGraphsPerCol},${this.nbGraphsPerRow}`;
|
||||||
|
|
||||||
|
// graph size
|
||||||
|
this.size = `${this.width * this.nbGraphsPerRow}cm,` +
|
||||||
|
`${this.height * this.nbGraphsPerCol}cm`;
|
||||||
|
|
||||||
|
this.checkConsistentParams(err => {
|
||||||
|
if (err) {
|
||||||
|
throw new Error(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
checkConsistentParams(cb) {
|
||||||
|
if (!this.dataFolder) {
|
||||||
|
throw new Error('missing folder storing data, .gnu and ' +
|
||||||
|
'output files\n');
|
||||||
|
}
|
||||||
|
if (this.dataFile === undefined && !this.data) {
|
||||||
|
throw new Error('missing data for Plotter\n');
|
||||||
|
} else if (this.dataFile) {
|
||||||
|
try {
|
||||||
|
fs.statSync(this.dataFile);
|
||||||
|
} catch (e) {
|
||||||
|
throw new Error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.method === simple && isNaN(this.xCol) || this.xCol < 1) {
|
||||||
|
return cb('\'xCol\' must be a positive number\n');
|
||||||
|
}
|
||||||
|
if (!Array.isArray(this.yCols)) {
|
||||||
|
return cb('\'yCols\' must be an array of column indices\n');
|
||||||
|
}
|
||||||
|
if (!this.lineTitle) {
|
||||||
|
this.lineTitle = new Array(this.yCols.length);
|
||||||
|
} else if (this.lineTitle &&
|
||||||
|
this.lineTitle.length !== this.yCols.length) {
|
||||||
|
return cb('\'yCols\' and \'lineTitle\' must have a same length\n');
|
||||||
|
}
|
||||||
|
if (this.styleData !== 'lines' && this.styleData !== 'points' &&
|
||||||
|
this.styleData !== 'linespoints') {
|
||||||
|
return cb('\'styleData\' must be either \'lines\', \'points\'' +
|
||||||
|
'or \'linespoints\'\n');
|
||||||
|
}
|
||||||
|
if (this.method === multiplot) {
|
||||||
|
if (!Array.isArray(this.xCol) ||
|
||||||
|
this.xCol.length !== this.nbGraphs) {
|
||||||
|
return cb(`'xCol' must be an array of ${this.nbGraphs} nbs\n`);
|
||||||
|
}
|
||||||
|
if (!Array.isArray(this.yCols) ||
|
||||||
|
this.yCols.length !== this.nbGraphs) {
|
||||||
|
return cb('\'yCols\' must be an array of ' +
|
||||||
|
`${this.nbGraphs} elements\n`);
|
||||||
|
}
|
||||||
|
this.yCols.forEach((yCol, yColIdx) => {
|
||||||
|
if (!Array.isArray(yCol)) {
|
||||||
|
if (!isNaN(yCol)) {
|
||||||
|
this.yCols[yColIdx] = [yCol];
|
||||||
|
} else {
|
||||||
|
return cb(`Element ${yCol} of \'yCols\' must be ` +
|
||||||
|
'either a number of an array\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
});
|
||||||
|
if (this.graphsOrder !== 'rowsfirst' &&
|
||||||
|
this.graphsOrder !== 'columnsfirst') {
|
||||||
|
return cb('\'graphsOrder\' must be either \'rowsfirst\'' +
|
||||||
|
'or \'columnsfirst\'\n');
|
||||||
|
}
|
||||||
|
if (!Array.isArray(this.xLabel) ||
|
||||||
|
this.xLabel.length !== this.nbGraphs) {
|
||||||
|
this.xLabel = (new Array(this.nbGraphs)).fill(this.xLabel);
|
||||||
|
}
|
||||||
|
if (!Array.isArray(this.yLabel) ||
|
||||||
|
this.yLabel.length !== this.nbGraphs) {
|
||||||
|
this.yLabel = (new Array(this.nbGraphs)).fill(this.yLabel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
genLegend() {
|
||||||
|
return `${new Date()}\\n${this.message}\\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* function creates .gnu command to plot data on columns of a data file
|
||||||
|
* @param {string} file: data file name
|
||||||
|
* @param {array} cols: [col1, col2, col3]
|
||||||
|
* @param {array} every: [firstLine, step, lastLine]
|
||||||
|
* @param {string} title: curve title
|
||||||
|
* @param {string} type: 'lines' or 'points' or 'linespoints'
|
||||||
|
* @param {number} color: curve color
|
||||||
|
* @param {boolean} nextFlag: fasle -> last line
|
||||||
|
* @param {number} lt: curve line type
|
||||||
|
* @param {number} lw: curve line weight
|
||||||
|
* @param {number} ps: curve point size
|
||||||
|
* @param {array} fit: [func, title] for fit
|
||||||
|
* @return {this} this
|
||||||
|
*/
|
||||||
|
plotLine(file, cols, every, title, type, color, nextFlag, lt, lw, ps, fit) {
|
||||||
|
const _type = type || 'linespoints';
|
||||||
|
const _lt = lt || 1;
|
||||||
|
const _lw = lw || 2;
|
||||||
|
const _ps = ps || 1;
|
||||||
|
let str;
|
||||||
|
|
||||||
|
let _title;
|
||||||
|
if (title) {
|
||||||
|
_title = `title '${title}'`;
|
||||||
|
} else {
|
||||||
|
_title = 'notitle';
|
||||||
|
}
|
||||||
|
|
||||||
|
let _every = '';
|
||||||
|
if (every) {
|
||||||
|
if (every.length === 2) {
|
||||||
|
_every = `every ${every[1]}::${every[0]} `;
|
||||||
|
} else if (every.length === 3) {
|
||||||
|
_every = `every ::${every[0]}::${every[2]} `;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
str = `"${file}" ${_every} u ${cols[0]}:${cols[1]} ` +
|
||||||
|
`${_title} w ${_type} lc ${color} lt ${_lt} lw ${_lw}`;
|
||||||
|
if (type === 'points' || type === 'linespoints') {
|
||||||
|
str += ` pt ${color} ps ${_ps}`;
|
||||||
|
}
|
||||||
|
if (cols[2]) {
|
||||||
|
str += `, "${file}" ${_every} u ${cols[0]}:${cols[1]}:${cols[2]} ` +
|
||||||
|
`notitle w yerrorbars lc ${color} lt ${_lt} lw ${_lw} ` +
|
||||||
|
`pt ${color} ps ${_ps}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fit) {
|
||||||
|
str += `,\ ${fit[0]} title ${fit[1]}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextFlag) {
|
||||||
|
str += ',\\';
|
||||||
|
}
|
||||||
|
str += `\n`;
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function creates .gnu files that plots a graph of one or multiple lines
|
||||||
|
* If yCol is an array of two elements, it will plot with errorbars where
|
||||||
|
* the first element is average, the second one is standard-deviation
|
||||||
|
* @param {function} cb: callback function
|
||||||
|
* @return {function} callback
|
||||||
|
*/
|
||||||
|
simple(cb) {
|
||||||
|
let color = 1;
|
||||||
|
let content =
|
||||||
|
`set terminal pdfcairo size ${this.size} enhanced color ` +
|
||||||
|
`font "${this.font}, ${this.fontSize}"\n` +
|
||||||
|
`set key ${this.legendPos} Left reverse box width 3 height 1.5\n` +
|
||||||
|
`set style data ${this.styleData}\n` +
|
||||||
|
`set xlabel '${this.xLabel}'\n` +
|
||||||
|
`set ylabel '${this.yLabel}'\n` +
|
||||||
|
`set grid ${this.grid}\n` +
|
||||||
|
`set title "${this.title}\\n${this.message}"\n` +
|
||||||
|
`set output '${this.output}'\n` +
|
||||||
|
'plot ';
|
||||||
|
this.yCols.forEach((yCol, yColIdx) => {
|
||||||
|
let xyAxis = [this.xCol, yCol];
|
||||||
|
if (Array.isArray(yCol) && yCol.length === 2) {
|
||||||
|
xyAxis = [this.xCol, yCol[0], yCol[1]];
|
||||||
|
}
|
||||||
|
content += this.plotLine(this.dataFile, xyAxis, null,
|
||||||
|
`${this.lineTitle[yColIdx]}`, this.styleData, color,
|
||||||
|
yColIdx < this.yCols.length - 1, null, this.lineSize,
|
||||||
|
this.pointSize);
|
||||||
|
color++;
|
||||||
|
});
|
||||||
|
content += `\n`;
|
||||||
|
fs.writeFile(this.gnuFile, content, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* function creates .gnu files that plots a graph of one or multiple lines
|
||||||
|
* with yerrorbars
|
||||||
|
* @param {function} cb: callback function
|
||||||
|
* @return {function} callback
|
||||||
|
*/
|
||||||
|
multiplot(cb) {
|
||||||
|
let color = 1;
|
||||||
|
let content =
|
||||||
|
`set terminal pdfcairo size ${this.size} enhanced color ` +
|
||||||
|
`font "${this.font}, ${this.fontSize}"\n` +
|
||||||
|
'set key top left Left reverse box width 3 height 1.5\n' +
|
||||||
|
`set style data ${this.styleData}\n` +
|
||||||
|
`set xlabel '${this.xLabel}'\n` +
|
||||||
|
`set ylabel '${this.yLabel}'\n` +
|
||||||
|
`set grid ${this.grid}\n` +
|
||||||
|
`set output '${this.output}'\n` +
|
||||||
|
`set multiplot layout ${this.layout} ${this.graphsOrder} ` +
|
||||||
|
`title "${this.title}\\n${this.message}"\n`;
|
||||||
|
this.yCols.forEach((yCol, yColIdx) => {
|
||||||
|
content +=
|
||||||
|
`unset xlabel; set xlabel '${this.xLabel[yColIdx]}'\n` +
|
||||||
|
`unset ylabel; set ylabel '${this.yLabel[yColIdx]}'\n` +
|
||||||
|
'plot ';
|
||||||
|
yCol.forEach((_yCol, _yColIdx) => {
|
||||||
|
let xyAxis = [this.xCol[yColIdx], _yCol];
|
||||||
|
if (Array.isArray(_yCol) && _yCol.length === 2) {
|
||||||
|
xyAxis = [this.xCol[yColIdx], _yCol[0], _yCol[1]];
|
||||||
|
}
|
||||||
|
content += this.plotLine(this.dataFile, xyAxis, null,
|
||||||
|
`${this.lineTitle[yColIdx][_yColIdx]}`, this.styleData,
|
||||||
|
color, _yColIdx < yCol.length - 1, null, this.lineSize,
|
||||||
|
this.pointSize);
|
||||||
|
color++;
|
||||||
|
});
|
||||||
|
content += `\n`;
|
||||||
|
});
|
||||||
|
content += `\n`;
|
||||||
|
content += `unset multiplot; set output\n`;
|
||||||
|
fs.writeFile(this.gnuFile, content, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
createAllGnuFiles(cb) {
|
||||||
|
let createGnuFile;
|
||||||
|
if (this.method === simple) {
|
||||||
|
createGnuFile = this.simple.bind(this);
|
||||||
|
}
|
||||||
|
if (this.method === multiplot) {
|
||||||
|
createGnuFile = this.multiplot.bind(this);
|
||||||
|
}
|
||||||
|
createGnuFile(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
plotData(cb) {
|
||||||
|
stderr.write('plotting..');
|
||||||
|
this.createAllGnuFiles(err => {
|
||||||
|
if (err) {
|
||||||
|
cb(err); return;
|
||||||
|
}
|
||||||
|
const cmd = `gnuplot ${this.gnuFile}`;
|
||||||
|
|
||||||
|
const gnuplot = spawn('bash', ['-c', cmd]);
|
||||||
|
gnuplot.on('exit', () => {
|
||||||
|
stderr.write(`done\n`);
|
||||||
|
return cb();
|
||||||
|
});
|
||||||
|
|
||||||
|
gnuplot.on('error', err => {
|
||||||
|
stderr.write(`gnuplot error: ${err}\n`);
|
||||||
|
return cb(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Plotter;
|
|
@ -5,7 +5,7 @@
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "git+https://github.com/scality/IronMan-Arsenal.git"
|
"url": "git+https://github.com/scality/Arsenal.git"
|
||||||
},
|
},
|
||||||
"contributors": [
|
"contributors": [
|
||||||
{ "name": "David Pineau", "email": "" },
|
{ "name": "David Pineau", "email": "" },
|
||||||
|
@ -14,15 +14,15 @@
|
||||||
],
|
],
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/scality/IronMan-Arsenal/issues"
|
"url": "https://github.com/scality/Arsenal/issues"
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/scality/IronMan-Arsenal#readme",
|
"homepage": "https://github.com/scality/Arsenal#readme",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"eslint": "^2.4.0",
|
"eslint": "^2.4.0",
|
||||||
"eslint-config-airbnb": "^6.0.0",
|
"eslint-config-airbnb": "^6.0.0",
|
||||||
"eslint-config-ironman": "scality/IronMan-Guidelines#rel/1.0",
|
"eslint-config-ironman": "scality/Guidelines#rel/1.1",
|
||||||
"level": "^1.3.0",
|
"level": "^1.3.0",
|
||||||
"mocha": "^2.3.3",
|
"mocha": "^2.3.3",
|
||||||
"temp": "^0.8.3"
|
"temp": "^0.8.3"
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Note, a line starting with '#' will be ignored
|
||||||
|
# #Ok Test1 Test2 Test3 Test4
|
||||||
|
100 1.2 1.5 0.9 0.2 2.3
|
||||||
|
200 1.5 1.6 0.3 0.1 1.1
|
||||||
|
300 1.3 1.9 0.8 0.5 0.3
|
||||||
|
400 1.7 2.0 1.2 0.6 0.9
|
||||||
|
500 1.9 2.1 1.9 0.9 1.7
|
|
@ -0,0 +1,24 @@
|
||||||
|
{
|
||||||
|
"method": "multiplot",
|
||||||
|
"nbGraphsPerRow": 2,
|
||||||
|
"nbGraphsPerCol": 3,
|
||||||
|
"dataFolder": "./tests/functional",
|
||||||
|
"dataFile": "data.txt",
|
||||||
|
"output": "multiplot_file",
|
||||||
|
"xCol": [1, 1, 1, 1, 1, 1],
|
||||||
|
"yCols": [[2, 3], [3], [[4, 5]], [4, 6], [2, 5], [6]],
|
||||||
|
"graphsOrder": "rowsfirst",
|
||||||
|
"font": "CMR14",
|
||||||
|
"fontSize": 14,
|
||||||
|
"title": "Multiple plot",
|
||||||
|
"xLabel": "Number of successes",
|
||||||
|
"yLabel": "Average of latency (ms)",
|
||||||
|
"lineTitle": [["Col2", "Col3"], ["Col3"], ["Col4-5"],
|
||||||
|
["Col4", "Col6"], ["Col2", "Col5"], ["Col6"]],
|
||||||
|
"message": "Functional test for plotter, use config file",
|
||||||
|
"grid": "xtics ytics",
|
||||||
|
"styleData": "linespoints",
|
||||||
|
"lineSize": 1,
|
||||||
|
"pointSize": 1,
|
||||||
|
"legendPos": "top right"
|
||||||
|
}
|
|
@ -0,0 +1,75 @@
|
||||||
|
'use strict'; // eslint-disable-line strict
|
||||||
|
|
||||||
|
const Plotter = require('../../lib/plotter');
|
||||||
|
|
||||||
|
describe('Plot functional test', () => {
|
||||||
|
it('simple plot with .json config file', done => {
|
||||||
|
process.env.PLOTTER_CONFIG_FILE = `${__dirname}/simple.json`;
|
||||||
|
const plotter = new Plotter();
|
||||||
|
plotter.plotData(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('simple plot with config assigned via argument', done => {
|
||||||
|
const config = {
|
||||||
|
method: 'simple',
|
||||||
|
dataFile: 'data.txt',
|
||||||
|
output: 'simple_arg',
|
||||||
|
dataFolder: './tests/functional/test',
|
||||||
|
xCol: 1,
|
||||||
|
yCols: [2, 3, [4, 5], 6],
|
||||||
|
font: 'CMR14',
|
||||||
|
fontSize: 14,
|
||||||
|
title: 'Simple plot',
|
||||||
|
xLabel: 'x-axis label',
|
||||||
|
yLabel: 'y-axis label',
|
||||||
|
lineTitle: ['Test1', 'Test2', 'Test 3', 'Test 4'],
|
||||||
|
message: 'Functional test for plotter, config via argument',
|
||||||
|
grid: 'xtics ytics',
|
||||||
|
styleData: 'linespoints',
|
||||||
|
lineSize: 1,
|
||||||
|
pointSize: 1,
|
||||||
|
legendPos: 'top left',
|
||||||
|
};
|
||||||
|
const plotter = new Plotter(config);
|
||||||
|
plotter.plotData(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('multiplot with .json config file', done => {
|
||||||
|
process.env.PLOTTER_CONFIG_FILE = `${__dirname}/multiplot.json`;
|
||||||
|
const plotter = new Plotter();
|
||||||
|
plotter.plotData(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('multiplot with config assigned via argument', done => {
|
||||||
|
const config = {
|
||||||
|
method: 'multiplot',
|
||||||
|
nbGraphsPerRow: 3,
|
||||||
|
nbGraphsPerCol: 2,
|
||||||
|
width: 10,
|
||||||
|
height: 5,
|
||||||
|
dataFile: 'data.txt',
|
||||||
|
output: 'multiplot_arg',
|
||||||
|
dataFolder: './tests/functional',
|
||||||
|
xCol: [1, 1, 1, 1, 1, 1],
|
||||||
|
yCols: [[2, 3], 3, [[4, 5]], [4, 6], [2, 5], [6]],
|
||||||
|
graphsOrder: 'rowsfirst',
|
||||||
|
font: 'CMR14',
|
||||||
|
fontSize: 14,
|
||||||
|
title: 'Multiplot',
|
||||||
|
xLabel: ['xLabel1', 'xLabel2', 'xLabel3', 'xLabel4', 'xLabel5',
|
||||||
|
'xLabel6'],
|
||||||
|
yLabel: ['yLabel1', 'yLabel2', 'yLabel3', 'yLabel4', 'yLabel5',
|
||||||
|
'yLabel6'],
|
||||||
|
lineTitle: [['Col2', 'Col3'], ['Col3'], ['Col4-5'],
|
||||||
|
['Col4', 'Col6'], ['Col2', 'Col5'], ['Col6']],
|
||||||
|
message: 'Functional test for plotter, config via argument',
|
||||||
|
grid: 'xtics ytics',
|
||||||
|
styleData: 'linespoints',
|
||||||
|
lineSize: 1,
|
||||||
|
pointSize: 1,
|
||||||
|
legendPos: 'top left',
|
||||||
|
};
|
||||||
|
const plotter = new Plotter(config);
|
||||||
|
plotter.plotData(done);
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,22 @@
|
||||||
|
{
|
||||||
|
"method": "simple",
|
||||||
|
"width": 12,
|
||||||
|
"height": 10,
|
||||||
|
"dataFolder": "./tests/functional",
|
||||||
|
"dataFile": "data.txt",
|
||||||
|
"output": "simple_file",
|
||||||
|
"xCol": 1,
|
||||||
|
"yCols": [2, 3, [4, 5], 6],
|
||||||
|
"font": "CMR14",
|
||||||
|
"fontSize": 14,
|
||||||
|
"title": "Simple plot",
|
||||||
|
"xLabel": "Number of successes",
|
||||||
|
"yLabel": "Average of latency (ms)",
|
||||||
|
"lineTitle": ["Test1", "Test2", "Test 3", "Test 4"],
|
||||||
|
"message": "Functional test for plotter, use config file",
|
||||||
|
"grid": "xtics ytics",
|
||||||
|
"styleData": "linespoints",
|
||||||
|
"lineSize": 1,
|
||||||
|
"pointSize": 1,
|
||||||
|
"legendPos": "top right"
|
||||||
|
}
|
Loading…
Reference in New Issue