Skip to content

Commit

Permalink
Improve exporting for mcq-cli / local
Browse files Browse the repository at this point in the history
  • Loading branch information
tzok committed Oct 16, 2018
1 parent 0e38d8e commit 647fb8a
Show file tree
Hide file tree
Showing 7 changed files with 267 additions and 101 deletions.
29 changes: 29 additions & 0 deletions mcq-cli/colorbars.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#! /usr/bin/env Rscript
library(lattice)
library(RColorBrewer)

args = commandArgs(trailingOnly=TRUE)
if (length(args)==0) {
stop("At least one argument must be supplied (input file)\n")
}

c <- read.csv(file=args[1], header=FALSE)
residues <- c[1,]
dotbrackets <- c[2,]
c <- c[3:nrow(c),1:ncol(c)]
models <- c[,1]
c <- c[1:nrow(c),2:ncol(c)]
c <- t(c)
m <- as.matrix(c)
mode(m) <- 'numeric'

residues <- unlist(residues)
dotbrackets <- unlist(dotbrackets)
models <- unlist(models)

m <- ifelse(m > 60, 60, m)
p <- colorRampPalette(brewer.pal(9, 'YlOrRd'))

pdf('colorbars.pdf', width=11)
levelplot(m, col.regions=p, xlab='', ylab='', scales=list(x=list(at=0:nrow(m), labels=dotbrackets), y=list(at=1:ncol(m), labels=models)))
dev.off()
6 changes: 3 additions & 3 deletions mcq-cli/src/main/java/pl/poznan/put/mcq/cli/Global.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import pl.poznan.put.interfaces.Exportable;
import pl.poznan.put.interfaces.Visualizable;
import pl.poznan.put.matching.StructureSelection;
import pl.poznan.put.rna.torsion.RNATorsionAngleType;
import pl.poznan.put.torsion.MasterTorsionAngleType;
import pl.poznan.put.types.DistanceMatrix;
import pl.poznan.put.utility.ExecHelper;
import pl.poznan.put.utility.svg.Format;
Expand All @@ -50,7 +50,7 @@ public static void main(final String[] args) throws ParseException {
final CommandLineParser parser = new DefaultParser();
final CommandLine commandLine = parser.parse(Global.OPTIONS, args);
final List<StructureSelection> models = Helper.selectModels(commandLine);
final List<RNATorsionAngleType> angles = Helper.parseAngles(commandLine);
final List<MasterTorsionAngleType> angles = Helper.parseAngles(commandLine);
final MCQ mcq = new MCQ(angles);

final long size = models.size();
Expand Down Expand Up @@ -94,7 +94,7 @@ public void complete(final GlobalMatrix matrix) {
Listener.exportResults(directory, matrix);
Listener.exportDrawing(directory, partitionalClustering);
Listener.exportClustering(directory, partitionalClustering);
System.out.println("Results available in file: " + directory);
System.out.println("Results available in: " + directory);
} catch (final IOException e) {
System.err.println("Failed to store results");
e.printStackTrace(System.err);
Expand Down
10 changes: 5 additions & 5 deletions mcq-cli/src/main/java/pl/poznan/put/mcq/cli/Helper.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import pl.poznan.put.pdb.analysis.PdbModel;
import pl.poznan.put.rna.torsion.RNATorsionAngleType;
import pl.poznan.put.structure.tertiary.StructureManager;
import pl.poznan.put.torsion.MasterTorsionAngleType;

@Slf4j
public final class Helper {
Expand Down Expand Up @@ -186,9 +187,9 @@ private static String modelName(final File modelFile, final PdbModel model) {
return StringUtils.isNotBlank(idCode) ? idCode : modelFile.getName();
}

public static List<RNATorsionAngleType> parseAngles(final CommandLine commandLine) {
public static List<MasterTorsionAngleType> parseAngles(final CommandLine commandLine) {
if (commandLine.hasOption(Helper.OPTION_ANGLES.getOpt())) {
final List<RNATorsionAngleType> angles = new ArrayList<>();
final List<MasterTorsionAngleType> angles = new ArrayList<>();

for (final String angleName : commandLine.getOptionValues(Helper.OPTION_ANGLES.getOpt())) {
angles.add(RNATorsionAngleType.valueOf(angleName));
Expand All @@ -197,9 +198,8 @@ public static List<RNATorsionAngleType> parseAngles(final CommandLine commandLin
return angles;
}

return Arrays.stream(RNATorsionAngleType.mainAngles())
.map(t -> (RNATorsionAngleType) t)
.collect(Collectors.toList());
// do not use Arrays.asList because it creates unmodifiable list and this one is modified further
return Arrays.stream(RNATorsionAngleType.mainAngles()).collect(Collectors.toList());
}

public static boolean isHelpRequested(final String[] args) throws ParseException {
Expand Down
186 changes: 117 additions & 69 deletions mcq-cli/src/main/java/pl/poznan/put/mcq/cli/Local.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
import java.io.IOException;
import java.io.OutputStream;
import java.util.List;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableModel;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
Expand All @@ -15,105 +16,152 @@
import org.apache.commons.io.FileUtils;
import org.w3c.dom.svg.SVGDocument;
import pl.poznan.put.comparison.MCQ;
import pl.poznan.put.comparison.local.MCQLocalResult;
import pl.poznan.put.comparison.exception.IncomparableStructuresException;
import pl.poznan.put.comparison.local.LocalComparator;
import pl.poznan.put.comparison.local.ModelsComparisonResult;
import pl.poznan.put.comparison.local.SelectedAngle;
import pl.poznan.put.comparison.mapping.AngleDeltaMapper;
import pl.poznan.put.comparison.mapping.ComparisonMapper;
import pl.poznan.put.comparison.mapping.RangeDifferenceMapper;
import pl.poznan.put.interfaces.Exportable;
import pl.poznan.put.matching.FragmentMatch;
import pl.poznan.put.matching.ResidueComparison;
import pl.poznan.put.matching.SelectionMatch;
import pl.poznan.put.matching.StructureSelection;
import pl.poznan.put.pdb.PdbParsingException;
import pl.poznan.put.pdb.analysis.PdbCompactFragment;
import pl.poznan.put.rna.torsion.RNATorsionAngleType;
import pl.poznan.put.svg.SecondaryStructureVisualizer;
import pl.poznan.put.torsion.TorsionAngleDelta;
import pl.poznan.put.torsion.MasterTorsionAngleType;
import pl.poznan.put.utility.ExecHelper;
import pl.poznan.put.utility.TabularExporter;
import pl.poznan.put.utility.svg.Format;
import pl.poznan.put.utility.svg.SVGHelper;

@SuppressWarnings({"UseOfSystemOutOrSystemErr", "MethodWithTooExceptionsDeclared"})
@SuppressWarnings({"CallToSystemExit", "UseOfSystemOutOrSystemErr"})
public final class Local {
private static final Options OPTIONS =
new Options()
.addOption(Helper.OPTION_TARGET)
.addOption(Helper.OPTION_MODEL)
.addOption(Helper.OPTION_MODELS)
.addOption(Helper.OPTION_SELECTION_TARGET)
.addOption(Helper.OPTION_SELECTION_MODEL)
.addOption(Helper.OPTION_ANGLES);

public static void main(final String[] args)
throws ParseException, IOException, PdbParsingException {
throws ParseException, IncomparableStructuresException {
if (Helper.isHelpRequested(args)) {
Helper.printHelp("local", Local.OPTIONS);
return;
}

final CommandLineParser parser = new DefaultParser();
final CommandLine commandLine = parser.parse(Local.OPTIONS, args);
final StructureSelection s1 = Helper.selectTarget(commandLine);
final StructureSelection s2 = Helper.selectModel(commandLine);
final StructureSelection target = Helper.selectTarget(commandLine);
final List<StructureSelection> models = Helper.selectModels(commandLine);

// check for gaps
Stream.concat(Stream.of(target), models.stream())
.parallel()
.filter(selection -> selection.getCompactFragments().size() != 1)
.peek(
selection ->
System.err.println("The following structure contains gaps: " + selection.getName()))
.findAny()
.ifPresent(selection -> System.exit(1));

// check for size
final int expectedSize = target.getResidues().size();
models
.parallelStream()
.filter(selection -> selection.getResidues().size() != expectedSize)
.peek(
selection ->
System.err.printf(
"The following structure has different size (%d) than the target (%d)%n",
selection.getResidues().size(), expectedSize))
.findAny()
.ifPresent(selection -> System.exit(1));

final PdbCompactFragment targetFragment = target.getCompactFragments().get(0);
final List<PdbCompactFragment> modelFragments =
models
.stream()
.map(selection -> selection.getCompactFragments().get(0))
.collect(Collectors.toList());

// rename
targetFragment.setName(target.getName());
IntStream.range(0, models.size())
.forEach(i -> modelFragments.get(i).setName(models.get(i).getName()));

final List<MasterTorsionAngleType> angleTypes = Helper.parseAngles(commandLine);
angleTypes.add(RNATorsionAngleType.getAverageOverMainAngles());

final LocalComparator mcq = new MCQ(angleTypes);
final ModelsComparisonResult comparisonResult =
mcq.compareModels(targetFragment, modelFragments);
final File directory = Local.exportResults(comparisonResult);
System.out.println("Results are available in: " + directory);
}

final List<RNATorsionAngleType> angleTypes = Helper.parseAngles(commandLine);
final MCQ mcq = new MCQ(angleTypes);
final MCQLocalResult result = (MCQLocalResult) mcq.comparePair(s1, s2);
private static File exportResults(final ModelsComparisonResult comparisonResult) {
try {
final File directory = ExecHelper.createRandomDirectory();
Local.exportTable(directory, comparisonResult);
comparisonResult
.getFragmentMatches()
.parallelStream()
.forEach(fragmentMatch -> Local.exportModelResults(directory, fragmentMatch));
return directory;
} catch (final IOException e) {
throw new IllegalArgumentException("Failed to export results", e);
}
}

final File directory = ExecHelper.createRandomDirectory();
final File csvFile = new File(directory, "results.csv");
private static void exportModelResults(
final File parentDirectory, final FragmentMatch fragmentMatch) {
try {
final String name = fragmentMatch.getModelFragment().getName();
final File directory = new File(parentDirectory, name);
FileUtils.forceMkdir(directory);

Local.exportSecondaryStructureImage(
fragmentMatch, directory, "delta.svg", AngleDeltaMapper.getInstance());
Local.exportSecondaryStructureImage(
fragmentMatch, directory, "range.svg", RangeDifferenceMapper.getInstance());
Local.exportDifferences(fragmentMatch, directory);
} catch (final IOException e) {
throw new IllegalArgumentException("Failed to export results", e);
}
}

try (final OutputStream stream = new FileOutputStream(csvFile)) {
result.export(stream);
private static void exportDifferences(final Exportable fragmentMatch, final File directory)
throws IOException {
final File file = new File(directory, "differences.csv");
try (final OutputStream stream = new FileOutputStream(file)) {
fragmentMatch.export(stream);
}
}

final SelectionMatch selectionMatch = result.getSelectionMatch();
final List<FragmentMatch> fragmentMatches = selectionMatch.getFragmentMatches();

for (int i = 0, fragmentMatchesSize = fragmentMatches.size(); i < fragmentMatchesSize; i++) {
final FragmentMatch fragmentMatch = fragmentMatches.get(i);

// FIXME: creating charts is now a domain of mcq4structures
// final File chartFile = new File(directory, String.format("chart-%02d.svg", i));
// final SVGDocument chartSvg = fragmentMatch.visualize(1052, 744);
// FileUtils.writeByteArrayToFile(chartFile, SVGHelper.export(chartSvg, Format.SVG));

final File secondaryFile = new File(directory, String.format("secondary-%02d.svg", i));
final SVGDocument secondarySvg =
SecondaryStructureVisualizer.visualize(fragmentMatch, AngleDeltaMapper.getInstance());
FileUtils.writeByteArrayToFile(secondaryFile, SVGHelper.export(secondarySvg, Format.SVG));

for (final RNATorsionAngleType angleType : angleTypes) {
final File angleRangesFile =
new File(directory, String.format("angle-%s-%02d.csv", angleType.getExportName(), i));
final List<ResidueComparison> residueComparisons = fragmentMatch.getResidueComparisons();
final Object[][] data = new Object[fragmentMatch.getResidueCount()][];

for (int j = 0, size = residueComparisons.size(); j < size; j++) {
final ResidueComparison residueComparison = residueComparisons.get(j);
final TorsionAngleDelta angleDelta = residueComparison.getAngleDelta(angleType);

data[j] = new Object[8];
data[j][0] = residueComparison.getTarget();
data[j][1] = angleDelta.getTarget().getDegrees();
data[j][2] = angleType.getRange(angleDelta.getTarget()).getDisplayName();
data[j][3] = residueComparison.getModel();
data[j][4] = angleDelta.getModel().getDegrees();
data[j][5] = angleType.getRange(angleDelta.getModel()).getDisplayName();
data[j][6] = angleDelta.getDelta().getDegrees();
data[j][7] = angleDelta.getRangeDifference();
}

final String[] columns = {
"Target Residue", "Target Value", "Target Range",
"Model Residue", "Model Value", "Model Range",
"Value Difference", "Range Difference"
};
final TableModel tableModel = new DefaultTableModel(data, columns);

try (final OutputStream stream = new FileOutputStream(angleRangesFile)) {
TabularExporter.export(tableModel, stream);
}
}
private static void exportSecondaryStructureImage(
final FragmentMatch fragmentMatch,
final File directory,
final String filename,
final ComparisonMapper deltaMapper)
throws IOException {
final SVGDocument svg = SecondaryStructureVisualizer.visualize(fragmentMatch, deltaMapper);
final File file = new File(directory, filename);

try (final OutputStream stream = new FileOutputStream(file)) {
stream.write(SVGHelper.export(svg, Format.SVG));
}
}

System.out.println("Results are available in: " + directory);
private static void exportTable(
final File directory, final ModelsComparisonResult comparisonResult) throws IOException {
final File file = new File(directory, "table.csv");
try (final OutputStream stream = new FileOutputStream(file)) {
final SelectedAngle selectedAngle =
comparisonResult.selectAngle(RNATorsionAngleType.getAverageOverMainAngles());
selectedAngle.export(stream);
}
}

private Local() {
Expand Down
2 changes: 1 addition & 1 deletion mcq-core/src/main/java/pl/poznan/put/comparison/MCQ.java
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ public final ModelsComparisonResult compareModels(
if ((fragment.getMoleculeType() != target.getMoleculeType())
|| (fragment.getResidues().size() != target.getResidues().size())) {
throw new IncomparableStructuresException(
"All models must be of the same type and size as the " + "reference structure");
"All models must be of the same type and size as the reference structure");
}
}

Expand Down
Loading

0 comments on commit 647fb8a

Please sign in to comment.