/**
* Copyright (C) DataMelt project. The jHPLot package by S.Chekanov and Work.ORG
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program;
* if not, see .
*
* Additional permission under GNU GPL version 3 section 7:
* If you have received this program as a library with written permission from the DataMelt team,
* you can link or combine this library with your non-GPL project to convey the resulting work.
* In this case, this library should be considered as released under the terms of
* GNU Lesser public license (see ),
* provided you include this license notice and a URL through which recipients can access the
* Corresponding Source.
**/
package jhplot;
import java.text.DecimalFormat;
import java.util.StringTokenizer;
import java.awt.Color;
import java.io.*;
import java.net.URL;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import cern.colt.list.DoubleArrayList;
import cern.jet.stat.Descriptive;
import jhplot.gui.HelpBrowser;
import jhplot.io.PReader;
import jplot.DataArray2D;
/**
* A container to hold data points in X,Y,Z. Should be used to plot data in 3D.
* This is a high-performance array implementation.
*
* @author S.Chekanov
*
*/
public class P2D extends Plottable implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private DoubleArrayList dataX;
private DoubleArrayList dataY;
private DoubleArrayList dataZ;
private Color c;
private int s;
/**
* Construct an empty container
**/
public P2D() {
this("No title");
}
/**
* Construct an empty container with a title
*
* @param title
* New title
*/
public P2D(String title) {
dataX = new DoubleArrayList();
dataY = new DoubleArrayList();
dataZ = new DoubleArrayList();
this.title = title;
this.c = Color.BLACK;
this.s = 5;
}
/**
* Get color attribute
*
* @return Color
*/
public Color getSymbolColor() {
return c;
}
/**
* Sets symbol color
*
* @param c
* Color
*/
public void setSymbolColor(Color c) {
this.c = c;
}
/**
* Get size of the symbols
*
* @return size of the symbols
*/
public int getSymbolSize() {
return s;
}
/**
* Read P2D from a file. The old content will be lost. The file should
* contain 3 columns: x,y,z. Comment lines starting with "#" and "*" are ignored.
*
* @param br
* Input buffered reader
*
* @return zero if success
*/
public int read(BufferedReader br) {
// clear all data before reading
clear();
try {
String line;
// dis.available() returns 0 if the file does not have more lines.
while ((line = br.readLine()) != null) {
line = line.trim();
if (!line.startsWith("#") && !line.startsWith("*")) {
StringTokenizer st = new StringTokenizer(line);
int ncount = st.countTokens(); // number of words
double[] snum = new double[ncount];
if (ncount != 3) {
ErrorMessage("Error in reading the file:\n"
+ Integer.toString(ncount)
+ " entries per line is found!");
return 3;
}
// split this line
int mm = 0;
while (st.hasMoreTokens()) { // make sure there is stuff
// to get
String tmp = st.nextToken();
// read double
double dd = 0;
try {
dd = Double.parseDouble(tmp.trim());
} catch (NumberFormatException e) {
ErrorMessage("Error in reading the line "
+ Integer.toString(mm + 1));
return 3;
}
snum[mm] = dd;
mm++;
} // end loop over each line
dataX.add(snum[0]);
dataY.add(snum[1]);
dataZ.add(snum[2]);
} // skip #
// this statement reads the line from the file and print it to
// System.out.println(line);
}
// dispose all the resources after using them.
br.close();
} catch (FileNotFoundException e) {
ErrorMessage("File not found!");
e.printStackTrace();
return 2;
} catch (IOException e) {
e.printStackTrace();
return 1;
}
return 0;
}
/**
* Read P2D from a file.
*
* The old content will be lost. Use a space to separate values in columns and tab to put new row.
* Comment lines starting with "#" and "*" are ignored.
*
*
* @param sfile
* input file
* @return zero if success
*/
public int read(File sfile) {
BufferedReader is = PReader.read(sfile);
if (is == null) return 1;
return read(is);
}
/**
* Read data from URL.
* Use a space to separate values in columns and tab to put new row.
* @param url URL location of input file
*/
public int read(URL url)
{
BufferedReader is = PReader.read(url);
if (is == null) return 1;
return read(is);
}
/**
* Read P2D from a file.
* It can read URL if the string starts from http or ftp, otherwise a file on the file system is assumed.
*
* The old content will be lost. Use a space to separate values in columns and tab to put new row.
* Comment lines starting with "#" and "*" are ignored.
*
* @param sfile
* File name with input
* @return zero if success
*/
public int read(String sfile) {
BufferedReader is = PReader.read(sfile);
if (is == null) return 1;
return read(is);
}
/**
* Read P2D from a GZiped file.
* It can read URL if the string starts from http or ftp, otherwise a file on the file system is assumed.
*
* Use a space to separate values in columns and tab to put new row.
* @param sfile
* File name with input (extension .gz)
* @return zero if success
*/
public int readGZip(String sfile) {
BufferedReader is = PReader.readGZip(sfile);
if (is == null) return 1;
return read(is);
}
/**
* Read P1D from a Zipped file. The old content will be lost. The file
* should contain 2, or 4, or 6, or 10 columns: 1) x,y: data without any
* errors 2) x,y, y(upper), y(lower) - data with 1st level errors on Y 3)
* x,y, x(left), x(right), y(upper), y(lower) - data with 1st level errors
* on X and Y 4) x,y, x(left), x(right), y(upper), y(lower), x(leftSys),
* x(rightSys), y(upperSys), y(lowerSys) - data with X and Y and 1st and 2nd
* level errors
*
* @param sfile
* File name with input (extension zip)
* @return zero if success
*/
public int readZip(String sfile) {
// clear all data
clear();
try {
ZipFile zf = new ZipFile(sfile);
Enumeration entries = zf.entries();
BufferedReader input = new BufferedReader(new InputStreamReader(
System.in));
while (entries.hasMoreElements()) {
ZipEntry ze = (ZipEntry) entries.nextElement();
// System.out.println("Read " + ze.getName() + "?");
String inputLine = input.readLine();
if (inputLine.equalsIgnoreCase("yes")) {
long size = ze.getSize();
if (size > 0) {
// System.out.println("Length is " + size);
BufferedReader br = new BufferedReader(
new InputStreamReader(zf.getInputStream(ze)));
String line;
while ((line = br.readLine()) != null) {
line = line.trim();
if (!line.startsWith("#") && !line.startsWith("*")) {
StringTokenizer st = new StringTokenizer(line);
int ncount = st.countTokens(); // number of
// words
// String[] sword = new String[ncount];
double[] snum = new double[ncount];
if (ncount != 3 ) {
ErrorMessage("Error in reading the file:\n"
+ Integer.toString(ncount)
+ " entries per line is found!");
return 3;
}
// split this line
int mm = 0;
while (st.hasMoreTokens()) { // make sure there
// is stuff
// to get
String tmp = st.nextToken();
// read double
double dd = 0;
try {
dd = Double.parseDouble(tmp.trim());
} catch (NumberFormatException e) {
ErrorMessage("Error in reading the line "
+ Integer.toString(mm + 1));
return 3;
}
snum[mm] = dd;
mm++;
} // end loop over each line
dataX.add(snum[0] );
dataY.add(snum[1] );
dataZ.add(snum[2] );
} // skip #
}
br.close();
}
}
}
} catch (FileNotFoundException e) {
ErrorMessage("File not found:" + sfile);
e.printStackTrace();
return 1;
} catch (IOException e) {
e.printStackTrace();
return 2;
}
return 0;
}
/**
* Sets the symbol size
*
* @param s
* symbol size
*/
public void setSymbolSize(int s) {
this.s = s;
}
/**
* Construct a P2D from a file. Data should be separated by space in 3
* columns.
*
* @param title
* Title of the container
* @param sfile
* File name with input. It can be either a file on a file system or URL location (must start from http or ftp)
*/
public P2D(String title, String sfile) {
this(title);
read(sfile);
}
/**
* Write a P2D to an external file.
*
* @param name
* File name with output
*/
public void toFile(String name) {
DecimalFormat dfb = new DecimalFormat("##.#####E00");
Date dat = new Date();
String today = String.valueOf(dat);
try {
FileOutputStream f1 = new FileOutputStream(new File(name));
PrintStream tx = new PrintStream(f1);
tx.println("# DataMelt: output from P2D " + this.title);
tx.println("# DataMelt: created at " + today);
tx.println("# x,y,z");
tx.println("#");
for (int i = 0; i < size(); i++) {
String x = dfb.format(getX(i));
String y = dfb.format(getY(i));
String z = dfb.format(getZ(i));
tx.println(x + " " + y + " " + z);
}
f1.close();
} catch (IOException e) {
ErrorMessage("Error in the output file");
e.printStackTrace();
}
}
/**
* Merge two P2D containers
*
* @param a
* Container to be added
* @return New P2D container
*/
public P2D merge(P2D a) {
for (int i = 0; i < a.size(); i++) {
add(a.getX(i), a.getY(i), a.getZ(i));
}
return this;
}
/**
* Set data in a form of DataArray
*
* @param data
* input data
*
*/
public void setDataArray(DataArray2D data) {
for (int i=0; i