Skip to content

Commit b5c17ff

Browse files
authored
Merge pull request #272 from ProgrammingLife2017/annotation-parsing
Annotation parsing + search on fields
2 parents cba1480 + e9da281 commit b5c17ff

File tree

8 files changed

+601
-28
lines changed

8 files changed

+601
-28
lines changed

src/main/java/programminglife/gui/controller/GuiController.java

+34-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,9 @@
2626
import jp.uphy.javafx.console.ConsoleView;
2727
import programminglife.ProgrammingLife;
2828
import programminglife.controller.RecentFileController;
29+
import programminglife.model.Feature;
2930
import programminglife.model.GenomeGraph;
31+
import programminglife.parser.AnnotationParser;
3032
import programminglife.parser.GraphParser;
3133
import programminglife.utility.Alerts;
3234
import programminglife.utility.Console;
@@ -36,8 +38,11 @@
3638
import java.awt.*;
3739
import java.awt.datatransfer.Clipboard;
3840
import java.awt.datatransfer.StringSelection;
39-
import java.io.*;
41+
import java.io.File;
42+
import java.io.FileNotFoundException;
43+
import java.io.IOException;
4044
import java.nio.charset.Charset;
45+
import java.util.Map;
4146
import java.util.Observable;
4247
import java.util.Observer;
4348
import java.util.Random;
@@ -84,6 +89,7 @@ public class GuiController implements Observer {
8489
private GraphController graphController;
8590
private RecentFileController recentFileController;
8691
private File file;
92+
private Map<String, Feature> features;
8793
private File recentFile = new File("Recent.txt");
8894
private Thread parseThread;
8995

@@ -92,7 +98,6 @@ public class GuiController implements Observer {
9298
private static final double ZOOM_FACTOR = 1.05d;
9399

94100

95-
96101
/**
97102
* The initialize will call the other methods that are run in the .
98103
*/
@@ -149,10 +154,21 @@ public GraphParser openFile(File file) throws IOException {
149154
* @param file The {@link File} to open.
150155
* @throws IOException if the {@link File} is not found.
151156
*/
152-
public void openAnnotationFile(File file) throws IOException {
157+
public AnnotationParser openAnnotationFile(File file) throws IOException {
158+
AnnotationParser annotationParser = null;
153159
if (file != null) {
160+
System.out.println("Opening annotation " + file);
161+
annotationParser = new AnnotationParser(file);
162+
annotationParser.addObserver(this);
163+
annotationParser.getProgressCounter().addObserver(this);
154164

165+
if (this.parseThread != null) {
166+
this.parseThread.interrupt();
167+
}
168+
this.parseThread = new Thread(annotationParser);
169+
this.parseThread.start();
155170
}
171+
return annotationParser;
156172
}
157173

158174
@Override
@@ -172,6 +188,11 @@ public void update(Observable o, Object arg) {
172188
String msg = (String) arg;
173189
Platform.runLater(() -> ProgrammingLife.getStage().setTitle(msg));
174190
}
191+
} else if (o instanceof AnnotationParser) {
192+
if (arg instanceof Map) {
193+
Console.println("[%s] Annotations parsed.", Thread.currentThread().getName());
194+
this.setFeatures(((AnnotationParser) o).getFeatures());
195+
}
175196
} else if (o instanceof ProgressCounter) {
176197
progressBar.setVisible(true);
177198
ProgressCounter progress = (ProgressCounter) o;
@@ -494,10 +515,12 @@ private void initRightSearchTab() {
494515
AnchorPane page = loader.load();
495516
final HighlightController highlightController = loader.getController();
496517
highlightController.setGraphController(this.getGraphController());
518+
highlightController.setGUIController(this);
497519
searchTab.setContent(page);
498520
searchTab.setDisable(true);
499521
searchTab.setOnSelectionChanged(event -> {
500522
highlightController.initGenome();
523+
highlightController.initAnnotations();
501524
highlightController.initMinMax();
502525
});
503526
} catch (IOException e) {
@@ -552,6 +575,14 @@ public void setFile(File file) {
552575
this.file = file;
553576
}
554577

578+
private void setFeatures(Map<String, Feature> features) {
579+
this.features = features;
580+
}
581+
582+
public Map<String, Feature> getFeatures() {
583+
return this.features;
584+
}
585+
555586
GraphController getGraphController() {
556587
return this.graphController;
557588
}

src/main/java/programminglife/gui/controller/HighlightController.java

+36
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,28 @@
55
import javafx.scene.control.CheckBox;
66
import javafx.scene.control.TextField;
77
import javafx.scene.paint.Color;
8+
import programminglife.model.Annotation;
9+
import programminglife.model.Feature;
810
import programminglife.utility.NumbersOnlyListener;
911

12+
import java.util.Collection;
13+
import java.util.LinkedHashSet;
14+
import java.util.Map;
15+
import java.util.Set;
16+
import java.util.stream.Collectors;
17+
1018
/**
1119
* Controller class for the highlights.
1220
*/
1321
public class HighlightController {
1422

1523
private static final Color HIGHLIGHT_MIN_MAX_COLOR = Color.HOTPINK;
1624
private GraphController graphController;
25+
private GuiController guiController;
1726

1827
@FXML private Button btnHighlight;
1928
@FXML private AutoCompleteTextField txtGenome;
29+
@FXML private AutoCompleteTextField txtAnnotations;
2030
@FXML private TextField txtMin;
2131
@FXML private TextField txtMax;
2232
@FXML private CheckBox checkMin;
@@ -59,6 +69,28 @@ public void initGenome() {
5969
txtGenome.getEntries().addAll(graphController.getGraph().getGenomeNames());
6070
}
6171

72+
public void initAnnotations() {
73+
txtAnnotations.getEntries().clear();
74+
if (guiController.getFeatures() != null) {
75+
txtAnnotations.getEntries().addAll(guiController.getFeatures().keySet());
76+
77+
Set<Set<Annotation>> c = guiController.getFeatures()
78+
.values()
79+
.stream()
80+
.map(Feature::getAnnotations)
81+
.collect(Collectors.toSet());
82+
83+
Set<String> search = new LinkedHashSet<>();
84+
85+
c.forEach(setOfAnno -> setOfAnno.forEach(anno -> anno.getTextFields().entrySet().forEach(entry -> {
86+
search.add(entry.getKey());
87+
search.addAll(entry.getValue());
88+
})));
89+
90+
txtAnnotations.getEntries().addAll(search);
91+
}
92+
}
93+
6294
/**
6395
* Initializes the Min and Max field + checkbox.
6496
*/
@@ -109,4 +141,8 @@ private void highlightMinMax() {
109141
void setGraphController(GraphController graphController) {
110142
this.graphController = graphController;
111143
}
144+
145+
public void setGUIController(GuiController guiController) {
146+
this.guiController = guiController;
147+
}
112148
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
package programminglife.model;
2+
3+
import org.jetbrains.annotations.NotNull;
4+
5+
import java.util.*;
6+
import java.util.stream.Collectors;
7+
8+
/**
9+
* An Annotation for a genome.
10+
*/
11+
public class Annotation {
12+
private final String id;
13+
private final String file;
14+
private int genomeIndex;
15+
private final String originalGenomeID;
16+
17+
private final int startCoordinate;
18+
private final int endCoordinate;
19+
20+
private final Map<String, Set<String>> textFields;
21+
22+
/**
23+
* A constructor for an Annotation.
24+
* @param id The ID of this Annotation.
25+
* @param file The file for this Annotation.
26+
* @param originalGenomeID The original String for the genome. These should be mapped to the
27+
* genome indices in the {@link GenomeGraph}.
28+
* @param startCoordinate The starting coordinate within the genome.
29+
* @param endCoordinate The end coordinate within the genome.
30+
*/
31+
public Annotation(String id, String file, String originalGenomeID,
32+
int startCoordinate, int endCoordinate) {
33+
this.id = id;
34+
this.file = file;
35+
this.genomeIndex = -1;
36+
this.originalGenomeID = originalGenomeID;
37+
this.startCoordinate = startCoordinate;
38+
this.endCoordinate = endCoordinate;
39+
this.textFields = new LinkedHashMap<>();
40+
}
41+
42+
/**
43+
* Add a text attribute.
44+
* If the attribute already exists, this value is added to it.
45+
* @param name The name of the attribute.
46+
* @param value The value of the attribute.
47+
*/
48+
public void addAttribute(String name, String value) {
49+
getOrCreateAttribute(name).add(value);
50+
}
51+
52+
/**
53+
* Add multiple values to a single attribute.
54+
* If the attribute did not exist yet, it is created.
55+
* @param name The name of the attribute.
56+
* @param values The values to add.
57+
*/
58+
public void addMultiAttribute(String name, Set<String> values) {
59+
getOrCreateAttribute(name).addAll(values);
60+
}
61+
62+
/**
63+
* Add multiple values to a single attribute.
64+
* If the attribute did not exist yet, it is created.
65+
* @param name The name of the attribute.
66+
* @param values The values to add.
67+
*/
68+
public void addMultiAttribute(String name, String[] values) {
69+
Collections.addAll(getOrCreateAttribute(name), values);
70+
}
71+
72+
/**
73+
* Get or create an attribute. This returns the value set for an attribute.
74+
* If the attribute didn't exist yet, it is created.
75+
* @param name The name of the attribute.
76+
* @return The set of values for this attribute.
77+
*/
78+
@NotNull
79+
private Set<String> getOrCreateAttribute(String name) {
80+
return textFields.computeIfAbsent(name, k -> new HashSet<>());
81+
}
82+
83+
@Override
84+
public boolean equals(Object o) {
85+
if (this == o) {
86+
return true;
87+
}
88+
if (o == null || getClass() != o.getClass()) {
89+
return false;
90+
}
91+
92+
Annotation that = (Annotation) o;
93+
94+
return id.equals(that.id)
95+
&& file.equals(that.file)
96+
&& startCoordinate == that.startCoordinate
97+
&& endCoordinate == that.endCoordinate
98+
&& (
99+
genomeIndex == that.genomeIndex && genomeIndex != -1 // they have the same genomeIndex
100+
|| originalGenomeID.equals(that.originalGenomeID) // or the original names were equal
101+
)
102+
&& textFields.equals(that.textFields);
103+
}
104+
105+
@Override
106+
public int hashCode() {
107+
return id.hashCode() + 31 * file.hashCode();
108+
}
109+
110+
@Override
111+
public String toString() {
112+
return String.format("Annotations {ID: %s; file: %s; genomeIndex: %d; "
113+
+ "originalGenomeID: %s; start: %d; end: %d; textFields: %s}",
114+
id,
115+
file,
116+
genomeIndex,
117+
originalGenomeID,
118+
startCoordinate,
119+
endCoordinate,
120+
textFields.entrySet().stream().map(entry ->
121+
String.format("{%s: {%s}}", entry.getKey(),
122+
entry.getValue().stream().collect(Collectors.joining(", ")))
123+
).collect(Collectors.joining(", "))
124+
);
125+
}
126+
127+
public String getId() {
128+
return id;
129+
}
130+
131+
public String getFileName() {
132+
return file;
133+
}
134+
135+
public int getGenomeIndex() {
136+
return genomeIndex;
137+
}
138+
139+
public void setGenomeIndex(int genomeIndex) {
140+
this.genomeIndex = genomeIndex;
141+
}
142+
143+
public String getOriginalGenomeID() {
144+
return originalGenomeID;
145+
}
146+
147+
public int getStartCoordinate() {
148+
return startCoordinate;
149+
}
150+
151+
public int getEndCoordinate() {
152+
return endCoordinate;
153+
}
154+
155+
public Map<String, Set<String>> getTextFields() {
156+
return textFields;
157+
}
158+
}

0 commit comments

Comments
 (0)