/*
* This file is part of ALOE.
*
* ALOE 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
* (at your option) any later version.
* ALOE 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 ALOE. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright (c) 2012 SCCL, University of Washington (http://depts.washington.edu/sccl)
*/
package etc.aloe;
import com.csvreader.CsvWriter;
import etc.aloe.data.EvaluationReport;
import etc.aloe.data.FeatureSpecification;
import etc.aloe.data.MessageSet;
import etc.aloe.data.Model;
import etc.aloe.data.ROC;
import etc.aloe.factories.PipelineFactory;
import etc.aloe.options.ModeOptions;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InvalidObjectException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Map;
import weka.core.Instances;
import weka.core.converters.CSVSaver;
/**
* Main Aloe controller superclass. Provides many useful IO methods used by the
* subcontrollers.
*
* @author Michael Brooks <mjbrooks@uw.edu>
*/
public abstract class Aloe {
private String[] cmdLineArgs = new String[0];
public void setCmdLineArgs(String[] cmdLineArgs) {
this.cmdLineArgs = cmdLineArgs;
}
protected PipelineFactory factory = null;
protected void setPipeline(String className) {
className = "etc.aloe.factories." + className;
try {
this.factory = (PipelineFactory) Class.forName(className).newInstance();
} catch (InstantiationException ex) {
System.err.println("Error instantiating pipeline class " + className);
System.err.println(ex.getMessage());
System.exit(1);
} catch (IllegalAccessException ex) {
System.err.println("Cannot access constructor for class " + className);
System.err.println(ex.getMessage());
System.exit(1);
} catch (ClassNotFoundException ex) {
System.err.println("Cannot find pipeline class " + className);
System.err.println(ex.getMessage());
System.exit(1);
}
}
protected MessageSet loadMessages(File inputCSVFile) {
MessageSet messages = new MessageSet();
messages.setDateFormat(factory.constructDateFormat());
try {
System.out.println("Reading messages from " + inputCSVFile);
InputStream inputCSV = new FileInputStream(inputCSVFile);
messages.load(inputCSV);
inputCSV.close();
} catch (FileNotFoundException e) {
System.err.println("Input CSV file " + inputCSVFile + " not found.");
System.exit(1);
} catch (InvalidObjectException e) {
System.err.println("Incorrect format in input CSV file " + inputCSVFile);
System.err.println("\t" + e.getMessage());
System.exit(1);
} catch (IOException e) {
System.err.println("File read error for " + inputCSVFile);
System.err.println("\t" + e.getMessage());
System.exit(1);
}
return messages;
}
protected Model loadModel(File inputModelFile) {
Model model = factory.constructModel();
try {
System.out.println("Reading model from " + inputModelFile);
InputStream inputModel = new FileInputStream(inputModelFile);
model.load(inputModel);
inputModel.close();
} catch (FileNotFoundException e) {
System.err.println("Model file " + inputModelFile + " not found.");
System.exit(1);
} catch (InvalidObjectException e) {
System.err.println("Incorrect format in model file " + inputModelFile);
System.err.println("\t" + e.getMessage());
System.exit(1);
} catch (IOException e) {
System.err.println("File read error for " + inputModelFile);
System.err.println("\t" + e.getMessage());
System.exit(1);
}
return model;
}
protected FeatureSpecification loadFeatureSpecification(File inputFeatureSpecFile) {
FeatureSpecification spec = new FeatureSpecification();
try {
System.out.println("Reading feature spec from " + inputFeatureSpecFile);
InputStream inputFeatureSpec = new FileInputStream(inputFeatureSpecFile);
spec.load(inputFeatureSpec);
inputFeatureSpec.close();
} catch (FileNotFoundException e) {
System.err.println("Feature specification file " + inputFeatureSpecFile + " not found.");
System.exit(1);
} catch (InvalidObjectException e) {
System.err.println("Incorrect format for feature specification file " + inputFeatureSpecFile);
System.err.println("\t" + e.getMessage());
System.exit(1);
} catch (IOException e) {
System.err.println("File read error for " + inputFeatureSpecFile);
System.err.println("\t" + e.getMessage());
System.exit(1);
}
return spec;
}
protected void saveMessages(MessageSet messages, File outputCSVFile) {
try {
OutputStream outputCSV = new FileOutputStream(outputCSVFile);
messages.save(outputCSV);
outputCSV.close();
System.out.println("Saved labeled data to " + outputCSVFile);
} catch (IOException e) {
System.err.println("Error saving messages to " + outputCSVFile);
System.err.println("\t" + e.getMessage());
}
}
protected void saveEvaluationReport(EvaluationReport evalReport, File outputEvaluationReportFile) {
try {
OutputStream outputEval = new FileOutputStream(outputEvaluationReportFile);
evalReport.save(outputEval);
outputEval.close();
System.out.println("Saved evaluation to " + outputEvaluationReportFile);
} catch (IOException e) {
System.err.println("Error saving evaluation report to " + outputEvaluationReportFile);
System.err.println("\t" + e.getMessage());
}
}
protected void saveROC(ROC roc, File outputROCFile) {
try {
OutputStream outputRoc = new FileOutputStream(outputROCFile);
roc.save(outputRoc);
outputRoc.close();
System.out.println("Saved ROC " + roc.getName() + " to " + outputROCFile);
} catch (IOException e) {
System.err.println("Error saving ROC " + roc.getName() + " to " + outputROCFile);
System.err.println("\t" + e.getMessage());
}
}
protected void saveFeatureSpecification(FeatureSpecification spec, File outputFeatureSpecFile) {
try {
OutputStream outputFeatureSpec = new FileOutputStream(outputFeatureSpecFile);
spec.save(outputFeatureSpec);
outputFeatureSpec.close();
System.out.println("Saved feature spec to " + outputFeatureSpecFile);
} catch (IOException e) {
System.err.println("Error saving feature spec to " + outputFeatureSpecFile);
System.err.println("\t" + e.getMessage());
}
}
protected void saveModel(Model model, File outputModelFile) {
try {
OutputStream outputModel = new FileOutputStream(outputModelFile);
model.save(outputModel);
outputModel.close();
System.out.println("Saved model to " + outputModelFile);
} catch (IOException e) {
System.err.println("Error saving model to " + outputModelFile);
System.err.println("\t" + e.getMessage());
}
}
protected void saveTopFeatures(List<String> topFeatures, File outputTopFeaturesFile) {
try {
PrintStream output = new PrintStream(outputTopFeaturesFile);
for (String feature : topFeatures) {
output.println(feature);
}
output.close();
System.out.println("Saved top features to " + outputTopFeaturesFile);
} catch (FileNotFoundException e) {
System.err.println("Top features file not found:" + outputTopFeaturesFile);
System.err.println("\t" + e.getMessage());
}
}
protected void saveFeatureWeights(List<Map.Entry<String, Double>> featureWeights, File outputFeatureWeightsFile) {
try {
CsvWriter writer = new CsvWriter(new FileWriter(outputFeatureWeightsFile), ',');
writer.write("Feature");
writer.write("Weight");
writer.write("WeightSquared");
writer.endRecord();
for (Map.Entry<String, Double> entry : featureWeights) {
writer.write(entry.getKey());
writer.write(entry.getValue() + "");
writer.write(entry.getValue() * entry.getValue() + "");
writer.endRecord();
}
writer.close();
System.out.println("Saved feature weights to " + outputFeatureWeightsFile);
} catch (IOException e) {
System.err.println("Error writing feature weights to " + outputFeatureWeightsFile);
System.err.println("\t" + e.getMessage());
}
}
protected void saveInstances(Instances instances, File outputFile) {
try {
CSVSaver saver = new CSVSaver();
saver.setFile(outputFile);
saver.setInstances(instances);
saver.writeBatch();
System.out.println("Saved instances to " + outputFile);
} catch (IOException e) {
System.err.println("Error writing instances to " + outputFile);
System.err.println("\t" + e.getMessage());
}
}
protected void saveCommand(File outputFile) {
try {
PrintStream output = new PrintStream(outputFile);
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm z");
String now = df.format(new Date());
output.println("# ALOE arguments (" + now + ")");
//Based on http://java.dzone.com/articles/programmatically-restart-java
//Based on http://stackoverflow.com/questions/13958318/is-it-possible-to-get-the-command-used-to-launch-the-jvm-in-java
// RuntimeMXBean bean = ManagementFactory.getRuntimeMXBean();
// List<String> args = bean.getInputArguments();
//
// for (int i = 0; i < args.size(); i++) {
// output.print(args.get(i) + " ");
// }
// print the non-JVM command line arguments using args
// name of the main class
// output.println("java " + System.getProperty("sun.java.command"));
output.println(getJavaCommand());
output.close();
System.out.println("Saved command to " + outputFile);
} catch (IOException e) {
System.err.println("Error writing command to " + outputFile);
System.err.println("\t" + e.getMessage());
}
}
private String getJavaCommand() {
// java binary
String java = "java";
// vm arguments
List<String> vmArguments = ManagementFactory.getRuntimeMXBean().getInputArguments();
StringBuffer vmArgsOneLine = new StringBuffer();
for (String arg : vmArguments) {
// if it's the agent argument : we ignore it otherwise the
// address of the old application and the new one will be in conflict
if (!arg.contains("-agentlib")) {
vmArgsOneLine.append(arg);
vmArgsOneLine.append(" ");
}
}
// init the command to execute, add the vm args
final StringBuffer cmd = new StringBuffer(java + " " + vmArgsOneLine);
// program main and program arguments
String[] mainCommand = System.getProperty("sun.java.command").split(" ");
// program main is a jar
if (mainCommand[0].endsWith(".jar")) {
// if it's a jar, add -jar mainJar
cmd.append("-jar ")
.append(new File(mainCommand[0]).getPath());
} else {
// else it's a .class, add the classpath and mainClass
cmd.append("-cp \"")
.append(System.getProperty("java.class.path"))
.append("\" ")
.append(mainCommand[0]);
}
// finally add program arguments
for (int i = 0; i < cmdLineArgs.length; i++) {
cmd.append(" ");
cmdLineArgs[i] = cmdLineArgs[i].replaceAll("\"", "\\\"");
if (cmdLineArgs[i].contains(" ")) {
cmd.append("\"")
.append(cmdLineArgs[i])
.append("\"");
} else {
cmd.append(cmdLineArgs[i]);
}
}
return cmd.toString();
}
public abstract void run(ModeOptions options);
}