/*
* Copyright 2004-2010 Information & Software Engineering Group (188/1)
* Institute of Software Technology and Interactive Systems
* Vienna University of Technology, Austria
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.ifs.tuwien.ac.at/dm/somtoolbox/license.html
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package at.tuwien.ifs.somtoolbox.apps.analysis;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import com.martiansoftware.jsap.FlaggedOption;
import com.martiansoftware.jsap.JSAP;
import com.martiansoftware.jsap.JSAPException;
import com.martiansoftware.jsap.JSAPResult;
import com.martiansoftware.jsap.Parameter;
import com.martiansoftware.jsap.Switch;
import com.martiansoftware.jsap.UnflaggedOption;
import com.martiansoftware.jsap.stringparsers.FileStringParser;
import at.tuwien.ifs.somtoolbox.apps.config.OptionFactory;
import at.tuwien.ifs.somtoolbox.apps.viewer.CommonSOMViewerStateData;
import at.tuwien.ifs.somtoolbox.apps.viewer.MapPNode;
import at.tuwien.ifs.somtoolbox.data.InputData;
import at.tuwien.ifs.somtoolbox.data.SOMLibSparseInputData;
import at.tuwien.ifs.somtoolbox.input.SOMLibFormatInputReader;
import at.tuwien.ifs.somtoolbox.layers.metrics.MetricException;
import at.tuwien.ifs.somtoolbox.models.GrowingSOM;
import at.tuwien.ifs.somtoolbox.util.StdErrProgressWriter;
import at.tuwien.ifs.somtoolbox.visualization.clustering.CompleteLinkageTreeBuilder;
import at.tuwien.ifs.somtoolbox.visualization.clustering.SingleLinkageTreeBuilder;
import at.tuwien.ifs.somtoolbox.visualization.clustering.TreeBuilder;
import at.tuwien.ifs.somtoolbox.visualization.clustering.WardsLinkageTreeBuilder;
/**
* @author Jakob Frank
* @version $Id: PlaylistAnalysis.java 3589 2010-05-21 10:42:01Z mayer $
*/
public class PlaylistAnalysis {
public static final Parameter[] OPTIONS = {
OptionFactory.getOptUnitDescriptionFile(true),
OptionFactory.getOptWeightVectorFile(true),
OptionFactory.getOptInputVectorFile(true),
new Switch("help", 'h', "help", "Print this help."),
new Switch("raw", JSAP.NO_SHORTFLAG, "raw", "print the raw values"),
new FlaggedOption("clusters", JSAP.INTEGER_PARSER, null, false, 'c', "cluster").setAllowMultipleDeclarations(true),
new FlaggedOption("clustertreebuilder", JSAP.STRING_PARSER, null, false, JSAP.NO_SHORTFLAG, "treebuilder"),
new FlaggedOption("output", FileStringParser.getParser(), ".", false, 'o', JSAP.NO_LONGFLAG),
new FlaggedOption("basename", JSAP.STRING_PARSER, "analysis", false, 'B', "baseName",
"the basename for the result files"),
new UnflaggedOption("playlist", FileStringParser.getParser(), true,
"a playlist or a directory containing playlists") };
private InputData inputData;
private String outBasename;
private File outDir;
private GrowingSOM som;
private List<PLAnalyser> analysers;
private String headerString;
private MapPNode map;
public PlaylistAnalysis() {
analysers = new LinkedList<PLAnalyser>();
}
private void analyse(File file, boolean rawVal) throws IOException, MetricException {
if (file.isDirectory()) {
analyseDir(file, rawVal);
return;
}
String plName = file.getName();
List<String> playList = loadPlaylist(file);
for (PLAnalyser a : analysers) {
a.analyse(plName, playList);
}
}
private void analyse(File[] listFiles, boolean rawVal) throws IOException, MetricException {
StdErrProgressWriter progress = new StdErrProgressWriter(listFiles.length, "Analyzing playlists: ", 10);
for (File file : listFiles) {
analyse(file, rawVal);
progress.progress();
}
}
private void analyseDir(File file, boolean rawVal) throws IOException, MetricException {
// FIXME: use util.ExtensionFilenameFilter
analyse(file.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.endsWith(".m3u");
}
}), rawVal);
}
public InputData getInputData() {
return inputData;
}
public String getOutBasename() {
return outBasename;
}
public File getOutDir() {
return outDir;
}
public GrowingSOM getSom() {
return som;
}
private void load(JSAPResult params) throws Exception {
String HEADER_TMPL = "##config%n" + "# Started: %tF - %<tT%n" + "# UnitFile: %s%n" + "# WGTFile: %s%n"
+ "# VectorFile: %s%n" + "#%n%s" + "# MapSize: %d x %d%n" + "# VectorDimensions: %d%n"
+ "# VectorCount: %d%n" + "##config-end%n";
String clusterHeader = "";
SOMLibFormatInputReader reader = new SOMLibFormatInputReader(params.getString("weightVectorFile"),
params.getString("unitDescriptionFile"), null);
som = new GrowingSOM(reader);
map = new MapPNode(null, reader, new CommonSOMViewerStateData(), true);
inputData = new SOMLibSparseInputData(params.getString("inputVectorFile"));
int[] clusters = params.getIntArray("clusters");
if (clusters.length > 0) {
TreeBuilder clusterer = null;
String reqBuilder = params.getString("clustertreebuilder");
if (reqBuilder == null || reqBuilder.equalsIgnoreCase("single")) {
clusterer = new SingleLinkageTreeBuilder();
} else if (reqBuilder.equalsIgnoreCase("complete")) {
clusterer = new CompleteLinkageTreeBuilder();
} else if (reqBuilder.equalsIgnoreCase("wards")) {
clusterer = new WardsLinkageTreeBuilder();
} else {
throw new Exception("Unsupported or unknown ClusterTreeBuilder: \"" + reqBuilder + "\"");
}
clusterHeader = String.format("# TreeBuilder: %s%n# Clusters: %s%n#%n", clusterer.getClusteringAlgName(),
Arrays.toString(clusters));
map.buildTree(clusterer);
}
outDir = params.getFile("output");
outBasename = params.getString("basename");
headerString = String.format(HEADER_TMPL, new Date(), params.getString("unitDescriptionFile"),
params.getString("weightVectorFile"), params.getString("unitDescriptionFile"), clusterHeader,
som.getLayer().getXSize(), som.getLayer().getYSize(), inputData.dim(), inputData.numVectors());
for (PLAnalyser a : analysers) {
a.init(this);
}
}
public MapPNode getMap() {
return map;
}
private void shutdown() {
for (PLAnalyser a : analysers) {
a.finish();
}
analysers.clear();
inputData = null;
som = null;
map = null;
}
public void printHeader(PrintStream ps) {
ps.println(headerString);
}
/**
* @param playlist Playlist to analize
* @return List of entries in the Playlist.
* @throws FileNotFoundException if the file does not exist, is a directory rather than a regular file, or for some
* other reason cannot be opened for reading.
* @throws IOException If an I/O error occurs
*/
private static List<String> loadPlaylist(File playlist) throws FileNotFoundException, IOException {
LinkedList<String> playList = new LinkedList<String>();
BufferedReader br = new BufferedReader(new FileReader(playlist));
for (String line = br.readLine(); line != null; line = br.readLine()) {
line = line.trim();
if (line.length() == 0 || line.startsWith("#")) {
// Blank Lines & Comments
continue;
}
playList.add(line);
}
return playList;
}
/**
* @param _args Command Line parameters.
*/
public static void main(String[] _args) {
try {
JSAPResult args = OptionFactory.parseResults(_args, OPTIONS);
PlaylistAnalysis pa = new PlaylistAnalysis();
pa.registerAnalyzer(new PLInputSpaceAnalyser());
pa.registerAnalyzer(new PLOutputSpaceAnalyser());
pa.registerAnalyzer(new PLStepSequenceAnalyser());
int[] clusters = args.getIntArray("clusters");
for (int c : clusters) {
pa.registerAnalyzer(new PLClusterSpaceAnalyser(c));
}
pa.load(args);
pa.analyse(args.getFile("playlist"), args.getBoolean("raw"));
pa.shutdown();
} catch (JSAPException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
System.out.println("EXIT!");
System.exit(0);
}
}
private void registerAnalyzer(PLAnalyser inputSpaceAnalyser) {
analysers.add(inputSpaceAnalyser);
}
}