/* =========================================================== * 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