Skip to content

Commit

Permalink
Refactoring to patterns + entropy tests
Browse files Browse the repository at this point in the history
  • Loading branch information
Kawa, Jakub authored and Kawa, Jakub committed Aug 22, 2017
1 parent ea1f9f6 commit 2dc3b03
Show file tree
Hide file tree
Showing 13 changed files with 317 additions and 132 deletions.
8 changes: 8 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,14 @@
<version>1.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/junit/junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>

</dependencies>


Expand Down
50 changes: 50 additions & 0 deletions src/main/java/com/github/superzer0/BarcodesEntropy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.github.superzer0;

import edu.stanford.math.plex4.homology.barcodes.Interval;

import java.util.List;

public class BarcodesEntropy {

public static double computeDiagramEntropy(int maxFiltration, List<Interval<Double>> intervals) {

double entropy = 0;
double L = 0;
for (Interval<Double> interval : intervals) {
Double l = getLValueFromInterval(maxFiltration, interval);
L += l;
}

for (Interval<Double> interval : intervals) {
Double l = getLValueFromInterval(maxFiltration, interval);
if (l == 0d)
continue;

double p = l / L;
entropy += p * Math.log(p);
}

return entropy * -1;
}

private static Double getLValueFromInterval(double maxFiltration, Interval<Double> interval) {
if (interval == null)
return 0d;

Double rightIndex;
Double leftIndex;
if (interval.isRightInfinite()) {
rightIndex = maxFiltration;
} else {
rightIndex = interval.getEnd();
}

if (interval.isLeftInfinite()) {
leftIndex = 0d;
} else {
leftIndex = interval.getStart();
}

return rightIndex - leftIndex;
}
}
3 changes: 0 additions & 3 deletions src/main/java/com/github/superzer0/DefaultSettings.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
package com.github.superzer0;

/**
* Created by SG0219908 on 8/21/2017.
*/
public class DefaultSettings {
public static final String DEFAULT_IMAGE_CAPTION = "Barcodes";
public static final String DEFAULT_HOMOLOGY_FILE_NAME = "persistent_homology_summary.txt";
Expand Down
148 changes: 28 additions & 120 deletions src/main/java/com/github/superzer0/Main.java
Original file line number Diff line number Diff line change
@@ -1,58 +1,54 @@
package com.github.superzer0;

import com.esotericsoftware.minlog.Log;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.superzer0.services.IIntervalsAction;
import com.github.superzer0.services.IntervalsActionsFactory;
import com.github.superzer0.services.IoService;
import com.github.superzer0.services.ProcessingInputParams;
import edu.stanford.math.plex4.api.Plex4;
import edu.stanford.math.plex4.homology.barcodes.BarcodeCollection;
import edu.stanford.math.plex4.homology.barcodes.Interval;
import edu.stanford.math.plex4.homology.barcodes.PersistenceInvariantDescriptor;
import edu.stanford.math.plex4.homology.chain_basis.Simplex;
import edu.stanford.math.plex4.homology.interfaces.AbstractPersistenceAlgorithm;
import edu.stanford.math.plex4.io.BarcodeWriter;
import edu.stanford.math.plex4.metric.landmark.MaxMinLandmarkSelector;
import edu.stanford.math.plex4.streams.impl.VietorisRipsStream;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

public class Main {

public static void main(String[] args) throws IOException {

Log.INFO();
IoService ioService = new IoService();

ProcessingInputParams inputParams = GetInputParams(args);
Log.info("Input Params: " + inputParams.toString());
ProcessingInputParams inputParams = ioService.getInputParams(args);
double[][] points = ioService.readPointsCloud(inputParams);

ObjectMapper mapper = new ObjectMapper();
BarcodeCollection<Double> computedIntervals = computeIntervals(inputParams, points);

double[][] points = mapper.readValue(
new File(inputParams.getPointsCloudFilePath().toString()), double[][].class);
IntervalsActionsFactory actionsFactory = new IntervalsActionsFactory();
List<IIntervalsAction> actions = actionsFactory.getIntervalsActions();

runActionsWithFaultTolerance(actions, computedIntervals, inputParams);
}

private static BarcodeCollection<Double> computeIntervals(ProcessingInputParams inputParams, double[][] points) {
VietorisRipsStream<double[]> vietorisRipsStream = getVietorisRipsStream(inputParams, points);
AbstractPersistenceAlgorithm<Simplex> modularSimplicialAlgorithm =
Plex4.getModularSimplicialAlgorithm(inputParams.getMaxDimension(), 2);

Log.info("Starting computing intervals... ");

BarcodeCollection<Double> computedIntervals =
modularSimplicialAlgorithm.computeIntervals(vietorisRipsStream);

BarcodeCollection<Double> computedIntervals = modularSimplicialAlgorithm.computeIntervals(vietorisRipsStream);
Log.info("Computing intervals done.");

saveBarcodesText(inputParams, computedIntervals);
saveBarcodePlot(inputParams, computedIntervals);
saveDiagramsEntropy(inputParams, computedIntervals);
return computedIntervals;
}

private static VietorisRipsStream<double[]> getVietorisRipsStream(ProcessingInputParams inputParams, double[][] points) {
private static VietorisRipsStream<double[]> getVietorisRipsStream(ProcessingInputParams inputParams,
double[][] points) {
VietorisRipsStream<double[]> vietorisRipsStream;

if (inputParams.isUseLandmarks()) {
if (inputParams.useLandmarks()) {
int lazyPointsToProcess = getLazyPointCount(points.length, inputParams.getMaxLandmarks());
MaxMinLandmarkSelector<double[]> minMaxSelector = Plex4.createMaxMinSelector(points, lazyPointsToProcess);
vietorisRipsStream = Plex4.createVietorisRipsStream(minMaxSelector,
Expand All @@ -67,104 +63,16 @@ private static VietorisRipsStream<double[]> getVietorisRipsStream(ProcessingInpu
return vietorisRipsStream;
}

private static void saveBarcodePlot(ProcessingInputParams inputParams, BarcodeCollection<Double> computedIntervals) {
try {
Log.info("Creating barcode plot... ");
createBarcodePlot(computedIntervals, inputParams.getMaxFiltrationValue(),
inputParams.getOutputFolder().toString());
Log.info("Created barcode plot.");
} catch (IOException e) {
Log.error("Creating barcode plot failed", e);
}
}

private static void saveBarcodesText(ProcessingInputParams inputParams, BarcodeCollection<Double> computedIntervals) {
try (PrintWriter writer = new PrintWriter(Paths.get(inputParams.getOutputFolder().toString(),
DefaultSettings.DEFAULT_HOMOLOGY_FILE_NAME).toString(), "UTF-8")) {
Log.info("Saving intervals as text with basic info...");

writer.println(computedIntervals.getBettiNumbers());
writer.println(computedIntervals.toString());
Log.info("Saving intervals done.");
} catch (IOException e) {
Log.error("Saving intervals as text with basic info failed", e);
}
}

private static ProcessingInputParams GetInputParams(String[] args) {
if (args.length < 5) {
Log.error("Not enough params");
throw new IndexOutOfBoundsException();
}

ProcessingInputParams inputParams = new ProcessingInputParams();
inputParams.setPointsCloudFilePath(args[0]);
inputParams.setMaxDimension(args[1]);
inputParams.setMaxFiltrationValue(args[2]);
inputParams.setUseLandmarks(args[3]);
inputParams.setMaxLandmarks(args[4]);
inputParams.setOutputFolder(args[5]);

return inputParams;
}

private static <G> void createBarcodePlot(PersistenceInvariantDescriptor<Interval<Double>, G> collection,
double endPoint, String folderPath) throws IOException {
BarcodeWriter writer = BarcodeWriter.getInstance();

for (int dimension : collection.getDimensions()) {
String imageFilename = DefaultSettings.DEFAULT_IMAGE_CAPTION + "_" + dimension;
String fullFileName = imageFilename + "." + writer.getExtension();
String path = Paths.get(folderPath, fullFileName).toString();
writer.writeToFile(collection, dimension, endPoint, imageFilename, path);
}
}

private static void saveDiagramsEntropy(ProcessingInputParams inputParams, BarcodeCollection<Double> computedIntervals) {
List<Double> entropiesList = new ArrayList<>();

Log.error("Computing diagrams entropy...");

for (int dimension : computedIntervals.getDimensions()) {
List<Interval<Double>> intervalsAtDimension = computedIntervals.getIntervalsAtDimension(dimension);
if (intervalsAtDimension != null)
entropiesList.add(computeDiagramEntropy(intervalsAtDimension));
}

try (PrintWriter writer = new PrintWriter(Paths.get(inputParams.getOutputFolder().toString(),
DefaultSettings.DEFAULT_ENTROPY_FILE_NAME).toString(), "UTF-8")) {

ObjectMapper mapper = new ObjectMapper();
mapper.writeValue(writer, entropiesList);
Log.error("Computing diagrams entropy done");

} catch (IOException ioException) {
Log.error("Saving entropy failed", ioException);
}
}

private static double computeDiagramEntropy(List<Interval<Double>> intervals) {

int entropy = 0;
double L = 0;
for (Interval<Double> interval : intervals) {
if (interval == null)
continue;

Double l = interval.getEnd() - interval.getStart();
L += l;
private static void runActionsWithFaultTolerance(List<IIntervalsAction> actions,
BarcodeCollection<Double> computedIntervals,
ProcessingInputParams inputParams) {
for (IIntervalsAction action : actions) {
try {
action.run(inputParams, computedIntervals);
} catch (Exception ex) {
Log.warn("Error when executing action", ex);
}
}

for (Interval<Double> interval : intervals) {
if (interval == null)
continue;

Double l = interval.getEnd() - interval.getStart();
double p = l / L;
entropy += p * Math.log(p);
}

return entropy * -1;
}

private static int getLazyPointCount(int pointsNumber, int maxLandmarks) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.github.superzer0.services;

import edu.stanford.math.plex4.homology.barcodes.BarcodeCollection;

public interface IIntervalsAction {
void run(ProcessingInputParams inputParams, BarcodeCollection<Double> computedIntervals);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.github.superzer0.services;

import com.github.superzer0.services.intervalsActions.SaveIntervalsAsText;
import com.github.superzer0.services.intervalsActions.SaveIntervalsDiagrams;
import com.github.superzer0.services.intervalsActions.SaveIntervalsEntropy;

import java.util.ArrayList;
import java.util.List;

public class IntervalsActionsFactory {

public List<IIntervalsAction> getIntervalsActions() {
List<IIntervalsAction> actions = new ArrayList<>();
actions.add(new SaveIntervalsAsText());
actions.add(new SaveIntervalsDiagrams());
actions.add(new SaveIntervalsEntropy());
return actions;
}
}
38 changes: 38 additions & 0 deletions src/main/java/com/github/superzer0/services/IoService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package com.github.superzer0.services;

import com.esotericsoftware.minlog.Log;
import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.File;
import java.io.IOException;

public class IoService {

public double[][] readPointsCloud(ProcessingInputParams processingInputParams) throws IOException {

ObjectMapper mapper = new ObjectMapper();

return mapper.readValue(
new File(processingInputParams.getPointsCloudFilePath().toString()), double[][].class);
}

public ProcessingInputParams getInputParams(String[] args) {
if (args.length < 5) {
Log.error("Not enough params");
throw new IndexOutOfBoundsException();
}

ProcessingInputParams inputParams = new ProcessingInputParams();
inputParams.setPointsCloudFilePath(args[0]);
inputParams.setMaxDimension(args[1]);
inputParams.setMaxFiltrationValue(args[2]);
inputParams.setUseLandmarks(args[3]);
inputParams.setMaxLandmarks(args[4]);
inputParams.setOutputFolder(args[5]);

Log.info("Input Params: " + inputParams.toString());

return inputParams;
}

}
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package com.github.superzer0;
package com.github.superzer0.services;

import java.nio.file.Path;
import java.nio.file.Paths;

/**
* Created by SG0219908 on 8/13/2017.
*/
public class ProcessingInputParams {

private Path pointsCloudFilePath;
Expand All @@ -20,7 +17,7 @@ private static void CheckStringParam(String inputValue, String param) {
throw new IllegalArgumentException("Provided input is not valid for " + param);
}

Path getPointsCloudFilePath() {
public Path getPointsCloudFilePath() {
return pointsCloudFilePath;
}

Expand All @@ -29,7 +26,7 @@ void setPointsCloudFilePath(String pointsCloudFilePath) {
this.pointsCloudFilePath = Paths.get(pointsCloudFilePath.replace("\"", ""));
}

int getMaxDimension() {
public int getMaxDimension() {
return maxDimension;
}

Expand All @@ -38,7 +35,7 @@ void setMaxDimension(String maxDimension) {
this.maxDimension = Integer.parseInt(maxDimension);
}

int getMaxFiltrationValue() {
public int getMaxFiltrationValue() {
return maxFiltrationValue;
}

Expand All @@ -47,7 +44,7 @@ void setMaxFiltrationValue(String maxFiltrationValue) {
this.maxFiltrationValue = Integer.parseInt(maxFiltrationValue);
}

boolean isUseLandmarks() {
public boolean useLandmarks() {
return useLandmarks;
}

Expand All @@ -56,7 +53,7 @@ void setUseLandmarks(String useLandmarks) {
this.useLandmarks = Boolean.parseBoolean(useLandmarks);
}

Path getOutputFolder() {
public Path getOutputFolder() {
return outputFolder;
}

Expand Down
Loading

0 comments on commit 2dc3b03

Please sign in to comment.