/* ===========================================================
* WFDB Java : Interface to WFDB Applications.
*
* ===========================================================
*
* (C) Copyright 2012, by Ikaro Silva
*
* Project Info:
* Code: http://code.google.com/p/wfdb-java/
* WFDB: http://www.physionet.org/physiotools/wfdb.shtml
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see .
*
*
*
* Original Author: Ikaro Silva
* Contributor(s): Daniel J. Scott;
*
* Changes
* -------
* Check: http://code.google.com/p/wfdb-java/list
*/
/**
* @author Ikaro Silva
* @version 1.0
* @since 1.0
*/
package org.physionet.wfdb;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.physionet.wfdb.jni.Rdsamp;
public class Wfdbexec {
private String commandName;
private static final String fsep=SystemSettings.fsep;
private static final String osArch= SystemSettings.getosArch();
private static final String osName=SystemSettings.getOsName();
protected static final String WFDB_JAVA_HOME=SystemSettings.getWFDB_JAVA_HOME();
private String WFDB_PATH=null;
private String WFDBCAL=null;
private List commandInput;
protected static Map env;
protected static File EXECUTING_DIR=null;
protected String[] arguments;
private int DoubleArrayListCapacity=0;
private int FloatArrayListCapacity=0;
private int ShortArrayListCapacity=0;
private int LongArrayListCapacity=0;
private static Logger logger =
Logger.getLogger(Wfdbexec.class.getName());
private String commandDir;
private long initialWaitTime;
private String WFDB_NATIVE_BIN;
private String LD_PATH;
public static boolean customArchFlag=false;
public Wfdbexec(String commandName, String commandDir,boolean customArchFlag){
logger.finest("\n\t***Setting exec commandName to: " + commandDir + commandName);
this.commandName=commandName;
this.commandDir=commandDir;
Wfdbexec.customArchFlag=customArchFlag;
setWFDB_NATIVE_BIN(SystemSettings.getWFDB_NATIVE_BIN(customArchFlag));
LD_PATH=SystemSettings.getLD_PATH(customArchFlag);
}
public Wfdbexec(String commandName,boolean customArchFlag){
this(commandName,SystemSettings.getWFDB_NATIVE_BIN(customArchFlag)+"bin" + fsep,customArchFlag);
}
public void setArguments(String[] args){
arguments=args;
}
public void setWFDB_PATH(String str){
//According to http://www.physionet.org/physiotools/wpg/wpg_14.htm#WFDB-path-syntax
//use white space as best option for all the operating systems
logger.finest("\n\t***Setting WFDB to: " + str);
WFDB_PATH=str;
}
public void setWFDBCAL(String str){
logger.finest("\n\t***Setting WFDBCAL to: " + str);
WFDBCAL=str;
}
protected void setExecName(String execName) {
commandName = execName;
}
public void setInitialWaitTime(long tm){
initialWaitTime=tm;
}
public void setWFDB_NATIVE_BIN(String str){
WFDB_NATIVE_BIN=str;
}
public void setCustomArchFlag(boolean flag){
this.customArchFlag=flag;
}
public void setExecutingDir(File dir){
logger.finer("\n\t***Setting EXECUTING_DIR: "
+ dir);
EXECUTING_DIR=dir;
}
private void gen_exec_arguments() {
commandInput = new ArrayList();
commandInput.add(commandDir + commandName);
logger.finest("\n\t***commandInput.add = " + commandDir + commandName);
if(arguments != null){
for(String i: arguments)
commandInput.add(i);
}
}
public synchronized ArrayList execToStringList() throws Exception {
gen_exec_arguments();
ArrayList results= new ArrayList();
ProcessBuilder launcher = setLauncher();
ErrorReader er = null;
logger.fine("\n\t***Executing Launcher with commandInput : " + "\t" + commandInput);
String line = null;
try {
logger.finer("\n\t***Starting exec process...");
Process p = launcher.start();
logger.finer("\n\t***Creating read buffer and waiting for exec process...");
BufferedReader output = new BufferedReader(new InputStreamReader(
p.getInputStream(),"US-ASCII"));
er = new ErrorReader(p.getErrorStream(), logger);
er.start();
//Wait for the initial stream in case process is slow
logger.finest("\n\t***Waiting for data stream from launcher...");
long thisTime=System.currentTimeMillis();
long waitTime=thisTime;
while (!output.ready()){
if((waitTime-thisTime)> initialWaitTime){
logger.finest("Process data stream wait time exceeded ("
+ initialWaitTime + " milliseconds )");
logger.finest("\n\t***Could not get data stream, exiting...");
break;
}else {
try {
Thread.sleep(100);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
waitTime=System.currentTimeMillis();
}
}
if(output.ready()){
logger.finest("\n\t***A was stream initialized, checking if data or err...");
}
while ((line = output.readLine()) != null){
logger.finest("\n\t***Reading output: \n" + line);
results.add(line);
}
} catch (Exception e) {
System.err.println("error executing: " +
commandName);
e.printStackTrace();
return null;
} finally {
if (er != null) {
er.join();
}
}
return results;
}
public synchronized ArrayList execWithStandardInput(String[] inputData) throws Exception {
gen_exec_arguments();
ProcessBuilder launcher = setLauncher();
launcher.redirectErrorStream(true);
Process process= null;
int exitStatus = 1;
ArrayList results=null;
try {
process = launcher.start();
if (process != null) {
OutputReader or= new OutputReader(process.getInputStream()) ;
InputWriter iw= new InputWriter(process.getOutputStream(), inputData);
iw.start();
or.start();
iw.join();
or.join();
results=or.getResults();
}
exitStatus=process.waitFor();
} catch (IOException e) {
System.err.println("Either couldn't read from the template file or couldn't write to the OutputStream.");
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
process.destroy();
if(exitStatus != 0){
System.err.println("Process exited with errors!! Error code = "
+exitStatus);
for(String tmp : results)
System.err.println(tmp);
}
return results;
}
public synchronized ArrayList execWithStandardInput(byte[] inputData) throws Exception {
gen_exec_arguments();
ProcessBuilder launcher = setLauncher();
launcher.redirectErrorStream(true);
Process process= null;
int exitStatus = 1;
ArrayList results=null;
try {
process = launcher.start();
if (process != null) {
OutputReader or= new OutputReader(process.getInputStream()) ;
InputWriter iw= new InputWriter(process.getOutputStream(), inputData);
iw.start();
or.start();
iw.join();
or.join();
results=or.getResults();
}
exitStatus=process.waitFor();
} catch (IOException e) {
System.err.println("Either couldn't read from the template file or couldn't write to the OutputStream.");
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
process.destroy();
if(exitStatus != 0){
System.err.println("Process exited with errors!! Error code = "
+exitStatus);
for(String tmp : results)
System.err.println(tmp);
}
return results;
}
public synchronized ArrayList execWithStandardInput(double[][] inputData) throws Exception {
String[] stringArr=new String[inputData.length];
for(int i=0;i execToStringList(String[] args) throws Exception {
setArguments(args);
return execToStringList();
}
public double[][] execToDoubleArray(String[] args) throws Exception {
setArguments(args);
gen_exec_arguments();
ArrayList results= new ArrayList();
if(DoubleArrayListCapacity>0){
//Set capacity to ensure more efficiency
results.ensureCapacity(DoubleArrayListCapacity);
}
double[][] data=null;
int isTime=-1;//Index in case one of the columns is time as string
ProcessBuilder launcher = null;
ErrorReader er = null;
logger.finest("\n\t***Setting launcher in exectToDoubleArray");
try {
launcher = setLauncher();
logger.finest("\n\t***Launcher created sucessfully in exectToDoubleArray");
} catch (Exception e1) {
System.err.println("***Error in setting the system launcher:" + e1.toString());
e1.printStackTrace();
}
try {
logger.finest("\n\t***Starting launcher in exectToDoubleArray");
Process p = launcher.start();
BufferedReader output = new BufferedReader(new InputStreamReader(
p.getInputStream(),"US-ASCII"));
String line;
String[] tmpStr=null;
Double[] tmpArr=null;
char[] tmpCharArr=null;
int colInd;
int dataCheck=0;
er = new ErrorReader(p.getErrorStream(), logger);
er.start();
//Wait for the initial stream in case process is slow
logger.finest("\n\t***Waiting for data stream from launcher...");
long thisTime=System.currentTimeMillis();
long waitTime=thisTime;
while (!output.ready()){
if((waitTime-thisTime)> initialWaitTime){
logger.finest("Process data stream wait time exceeded ("
+ initialWaitTime + " milliseconds )");
logger.finest("\n\t***Could not get data stream, exiting...");
break;
}else {
try {
Thread.sleep(100);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
waitTime=System.currentTimeMillis();
}
}
if(output.ready()){
logger.finest("\n\t***Streamed communication received, checking if error or data...");
}
/* The number of columns for the output array */
int N=1;
/* Just get the second column. We only care about annotation samples */
if (commandName.equals("rdann")){
while ((line = output.readLine()) != null){
tmpStr=line.trim().split("\\s+");
tmpArr=new Double[1];
tmpArr[0] = Double.valueOf(tmpStr[1]);
if(results.isEmpty() && dataCheck==tmpStr.length){
System.err.println("Error: Cannot convert to double: ");
System.err.println(line);
throw new NumberFormatException("Cannot convert");
}else {
results.add(tmpArr);
}
}
}
/* For non rdann function calls */
else{
while ((line = output.readLine()) != null){
tmpStr=line.trim().split("\\s+");
tmpArr=new Double[tmpStr.length];
//loop through columns
for(colInd=0;colInd-1){
N--;
}
}
//Wait to for exit value
int exitValue = p.waitFor();
if(exitValue != 0){
System.err.println("Command exited with non-zero status!!");
}
//Convert data to Double Array
//TODO: find a way to use .toArray in case of column deletion
//data=new double[results.size()][N];
//data=results.toArray(data); this should replace the loops below
data=new double[results.size()][N];
int index=0;
if(isTime>-1) {
for(int i=0;i -1 && k != isTime)
index = (k>isTime) ? (k-1) :k;
data[i][index]=tmpData[k];
}
}
} else { //Optimized for case where there is no
//column deletion
for(int i=0;i execToDoubleList(String[] args) throws Exception {
setArguments(args);
gen_exec_arguments();
ArrayList results= new ArrayList();
if(DoubleArrayListCapacity>0){
//Set capacity to ensure more efficiency
results.ensureCapacity(DoubleArrayListCapacity);
}
int isTime=-1;//Index in case one of the columns is time as string
ProcessBuilder launcher = null;
ErrorReader er = null;
logger.finest("\n\t***Setting launcher in exectToDoubleArray");
try {
launcher = setLauncher();
logger.finest("\n\t***Launcher created sucessfully in exectToDoubleArray");
} catch (Exception e1) {
System.err.println("***Error in setting the system launcher:" + e1.toString());
e1.printStackTrace();
}
try {
logger.finest("\n\t***Starting launcher in exectToDoubleArray");
Process p = launcher.start();
BufferedReader output = new BufferedReader(new InputStreamReader(
p.getInputStream()));
String line;
String[] tmpStr=null;
char[] tmpCharArr=null;
int colInd;
er = new ErrorReader(p.getErrorStream(), logger);
er.start();
//Wait for the initial stream in case process is slow
logger.finest("\n\t***Waiting for data stream from launcher...");
long thisTime=System.currentTimeMillis();
long waitTime=thisTime;
while (!output.ready()){
if((waitTime-thisTime)> initialWaitTime){
logger.finest("Process data stream wait time exceeded ("
+ initialWaitTime + " milliseconds )");
logger.finest("\n\t***Could not get data stream, exiting...");
break;
}else {
try {
Thread.sleep(100);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
waitTime=System.currentTimeMillis();
}
}
if(output.ready()){
logger.finest("\n\t***Streamed communication received, checking if error or data...");
}
while ((line = output.readLine()) != null){
tmpStr=line.trim().split("\\s+");
//loop through columns
for(colInd=0;colInd results= new ArrayList();
if(FloatArrayListCapacity>0){
//Set capacity to ensure more efficiency
results.ensureCapacity(FloatArrayListCapacity);
}
float[][] data=null;
int isTime=-1;//Index in case one of the columns is time as string
ProcessBuilder launcher = null;
ErrorReader er = null;
logger.finest("\n\t***Setting launcher in exectToFloatArray");
try {
launcher = setLauncher();
logger.finest("\n\t***Launcher created sucessfully in exectToFloatArray");
} catch (Exception e1) {
System.err.println("***Error in setting the system launcher:" + e1.toString());
e1.printStackTrace();
}
try {
logger.finest("\n\t***Starting launcher in exectToFloatArray");
Process p = launcher.start();
BufferedReader output = new BufferedReader(new InputStreamReader(
p.getInputStream()));
String line;
String[] tmpStr=null;
Float[] tmpArr=null;
char[] tmpCharArr=null;
int colInd;
int dataCheck=0;
er = new ErrorReader(p.getErrorStream(), logger);
er.start();
//Wait for the initial stream in case process is slow
logger.finest("\n\t***Waiting for data stream from launcher...");
long thisTime=System.currentTimeMillis();
long waitTime=thisTime;
while (!output.ready()){
if((waitTime-thisTime)> initialWaitTime){
logger.finest("Process data stream wait time exceeded ("
+ initialWaitTime + " milliseconds )");
logger.finest("\n\t***Could not get data stream, exiting...");
break;
}else {
try {
Thread.sleep(100);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
waitTime=System.currentTimeMillis();
}
}
if(output.ready()){
logger.finest("\n\t***Streamed communication received, checking if error or data...");
}
while ((line = output.readLine()) != null){
tmpStr=line.trim().split("\\s+");
tmpArr=new Float[tmpStr.length];
//loop through columns
for(colInd=0;colInd-1){
N--;
}
//TODO: find a way to use .toArray in case of column deletion
//data=new double[results.size()][N];
//data=results.toArray(data); this should replace the loops below
data=new float[results.size()][N];
int index=0;
if(isTime>-1) {
for(int i=0;i -1 && k != isTime)
index = (k>isTime) ? (k-1) :k;
data[i][index]=tmpData[k];
}
}
} else { //Optimized for case where there is no
//column deletion
for(int i=0;i results= new ArrayList();
if(LongArrayListCapacity>0){
//Set capacity to ensure more efficiency
results.ensureCapacity(LongArrayListCapacity);
}
long[][] data=null;
int isTime=-1;//Index in case one of the columns is time as string
ProcessBuilder launcher = null;
ErrorReader er = null;
logger.finest("\n\t***Setting launcher in exectToLongArray");
try {
launcher = setLauncher();
logger.finest("\n\t***Launcher created sucessfully in exectToLongArray");
} catch (Exception e1) {
System.err.println("***Error in setting the system launcher:" + e1.toString());
e1.printStackTrace();
}
try {
logger.finest("\n\t***Starting launcher in exectToLongArray");
Process p = launcher.start();
BufferedReader output = new BufferedReader(new InputStreamReader(
p.getInputStream()));
String line;
String[] tmpStr=null;
Long[] tmpArr=null;
char[] tmpCharArr=null;
int colInd;
int dataCheck=0;
er = new ErrorReader(p.getErrorStream(), logger);
er.start();
//Wait for the initial stream in case process is slow
logger.finest("\n\t***Waiting for data stream from launcher...");
long thisTime=System.currentTimeMillis();
long waitTime=thisTime;
while (!output.ready()){
if((waitTime-thisTime)> initialWaitTime){
logger.finest("Process data stream wait time exceeded ("
+ initialWaitTime + " milliseconds )");
logger.finest("\n\t***Could not get data stream, exiting...");
break;
}else {
try {
Thread.sleep(100);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
waitTime=System.currentTimeMillis();
}
}
if(output.ready()){
logger.finest("\n\t***Streamed communication received, checking if error or data...");
}
while ((line = output.readLine()) != null){
tmpStr=line.trim().split("\\s+");
tmpArr=new Long[tmpStr.length];
//loop through columns
for(colInd=0;colInd-1){
N--;
}
//TODO: find a way to use .toArray in case of column deletion
//data=new double[results.size()][N];
//data=results.toArray(data); this should replace the loops below
data=new long[results.size()][N];
int index=0;
if(isTime>-1) {
for(int i=0;i -1 && k != isTime)
index = (k>isTime) ? (k-1) :k;
data[i][index]=tmpData[k];
}
}
} else { //Optimized for case where there is no
//column deletion
for(int i=0;i results= new ArrayList();
if(ShortArrayListCapacity>0){
//Set capacity to ensure more efficiency
results.ensureCapacity(ShortArrayListCapacity);
}
short[][] data=null;
int isTime=-1;//Index in case one of the columns is time as string
ProcessBuilder launcher = null;
ErrorReader er = null;
logger.finest("\n\t***Setting launcher in exectToShortArray");
try {
launcher = setLauncher();
logger.finest("\n\t***Launcher created sucessfully in exectToShortArray");
} catch (Exception e1) {
System.err.println("***Error in setting the system launcher:" + e1.toString());
e1.printStackTrace();
}
try {
logger.finest("\n\t***Starting launcher in exectToShortArray");
Process p = launcher.start();
BufferedReader output = new BufferedReader(new InputStreamReader(
p.getInputStream()));
String line;
String[] tmpStr=null;
Short[] tmpArr=null;
char[] tmpCharArr=null;
int colInd;
int dataCheck=0;
er = new ErrorReader(p.getErrorStream(), logger);
er.start();
//Wait for the initial stream in case process is slow
logger.finest("\n\t***Waiting for data stream from launcher...");
long thisTime=System.currentTimeMillis();
long waitTime=thisTime;
while (!output.ready()){
if((waitTime-thisTime)> initialWaitTime){
logger.finest("Process data stream wait time exceeded ("
+ initialWaitTime + " milliseconds )");
logger.finest("\n\t***Could not get data stream, exiting...");
break;
}else {
try {
Thread.sleep(100);
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
}
waitTime=System.currentTimeMillis();
}
}
if(output.ready()){
logger.finest("\n\t***Streamed communication received, checking if error or data...");
}
while ((line = output.readLine()) != null){
tmpStr=line.trim().split("\\s+");
tmpArr=new Short[tmpStr.length];
//loop through columns
for(colInd=0;colInd-1){
N--;
}
//TODO: find a way to use .toArray in case of column deletion
//data=new double[results.size()][N];
//data=results.toArray(data); this should replace the loops below
data=new short[results.size()][N];
int index=0;
if(isTime>-1) {
for(int i=0;i -1 && k != isTime)
index = (k>isTime) ? (k-1) :k;
data[i][index]=tmpData[k];
}
}
} else { //Optimized for case where there is no
//column deletion
for(int i=0;i getEnvironment(){
ArrayList variables= new ArrayList();
variables.add("WFDB_JAVA_HOME= " + WFDB_JAVA_HOME);
logger.finer("\n\t***WFDB_JAVA_HOME: " + WFDB_JAVA_HOME);
variables.add("WFDB_NATIVE_BIN= " + WFDB_NATIVE_BIN);
logger.finer("\n\t***WFDB_NATIVE_BIN: " + WFDB_NATIVE_BIN);
variables.add("EXECUTING_DIR= "+ EXECUTING_DIR);
logger.finer("\n\t***Exec dir: " + EXECUTING_DIR);
variables.add("osName= " + osName);
logger.finer("\n\t***OS: " + osName);
variables.add("fullOsName= " + System.getProperty("os.name"));
logger.finer("\n\t***fullOsName: " + System.getProperty("os.name"));
variables.add("osArch= " + osArch);
logger.finer("\n\t***OS Arch: " + osArch);
variables.add("customArchFlag= " + customArchFlag);
logger.finer("\n\t***customArchFlag: " + customArchFlag);
variables.add("OS Version= " + System.getProperty("os.version"));
logger.finer("\n\t***OS Version: " + System.getProperty("os.version"));
variables.add("JVM Version= " + System.getProperty("java.version"));
logger.finer("\n\t***JVM Version: " + System.getProperty("java.version"));
return variables;
}
public void printEnvironment(){
for(String tmp : env.keySet()){
if(tmp == null){
System.out.println("Environment is null");
}else{
System.out.println(tmp + " = " + env.get(tmp));
}
}
}
public void setDoubleArrayListCapacity(int capacity){
DoubleArrayListCapacity=capacity;
}
public void setFloatArrayListCapacity(int capacity){
FloatArrayListCapacity=capacity;
}
public void setLongArrayListCapacity(int capacity){
LongArrayListCapacity=capacity;
}
public void setShortArrayListCapacity(int capacity){
ShortArrayListCapacity=capacity;
}
public void setLogLevel(int level){
//Include this method to allow for debugging within MATLAB instances
Level debugLevel;
switch (level) {
case 0:
debugLevel=Level.OFF;break;
case 1:
debugLevel=Level.SEVERE;break;
case 2:
debugLevel=Level.WARNING;break;
case 3:
debugLevel=Level.INFO;break;
case 4:
debugLevel=Level.FINEST;break;
case 5:
debugLevel=Level.ALL;break;
default :
debugLevel=Level.OFF;break;
}
Handler[] handlers =
Logger.getLogger( "" ).getHandlers();
for ( int index = 0; index < handlers.length; index++ ) {
handlers[index].setLevel( debugLevel );
}
Logger.getLogger("org.physionet").setLevel(debugLevel);
}
public static void main(String[] args) throws Exception {
Level debugLevel = Level.FINEST;//use for debugging Level.FINEST;
if(debugLevel != null){
Handler[] handlers =
Logger.getLogger( "" ).getHandlers();
for ( int index = 0; index < handlers.length; index++ ) {
handlers[index].setLevel( debugLevel );
}
Logger.getLogger("org.physionet.wfdb.Wfdbexec").setLevel(debugLevel);
Logger.getLogger("org.physionet.wfdb.SystemSettings").setLevel(debugLevel);
}
Wfdbexec exec = new Wfdbexec(args[0],Boolean.getBoolean(args[1]));
double[][] data = exec.execToDoubleArray(Arrays.copyOfRange(args,1,args.length));
for(int row=0;row