Project

General

Profile

Download (12.1 KB) Statistics
| Branch: | Tag: | Revision:
1
// $Id$
2
/**
3
* Copyright (C) 2014 EDIT
4
* European Distributed Institute of Taxonomy
5
* http://www.e-taxonomy.eu
6
*
7
* The contents of this file are subject to the Mozilla Public License Version 1.1
8
* See LICENSE.TXT at the top of this package for the full license terms.
9
*/
10
package eu.etaxonomy.taxeditor.editor.molecular;
11

    
12

    
13
import info.bioinfweb.libralign.alignmentarea.AlignmentArea;
14
import info.bioinfweb.libralign.alignmentarea.content.AlignmentContentArea;
15
import info.bioinfweb.libralign.dataarea.implementations.ConsensusSequenceArea;
16
import info.bioinfweb.libralign.dataarea.implementations.SequenceIndexArea;
17
import info.bioinfweb.libralign.dataarea.implementations.pherogram.PherogramArea;
18
import info.bioinfweb.libralign.editsettings.EditSettingsChangeEvent;
19
import info.bioinfweb.libralign.editsettings.EditSettingsListener;
20
import info.bioinfweb.libralign.multiplealignments.AlignmentAreaList;
21
import info.bioinfweb.libralign.multiplealignments.MultipleAlignmentsContainer;
22
import info.bioinfweb.libralign.pherogram.provider.BioJavaPherogramProvider;
23
import info.bioinfweb.libralign.pherogram.provider.PherogramProvider;
24
import info.bioinfweb.libralign.sequenceprovider.SequenceDataProvider;
25
import info.bioinfweb.libralign.sequenceprovider.implementations.PackedSequenceDataProvider;
26
import info.bioinfweb.libralign.sequenceprovider.tokenset.BioJavaTokenSet;
27
import info.bioinfweb.libralign.sequenceprovider.tokenset.TokenSet;
28

    
29
import java.io.File;
30
import java.io.IOException;
31
import java.io.InputStream;
32
import java.net.URI;
33
import java.util.ArrayList;
34
import java.util.Collection;
35
import java.util.Collections;
36
import java.util.Map;
37
import java.util.TreeMap;
38

    
39
import org.biojava.bio.chromatogram.ChromatogramFactory;
40
import org.biojava.bio.chromatogram.UnsupportedChromatogramFormatException;
41
import org.biojava3.core.sequence.compound.DNACompoundSet;
42
import org.biojava3.core.sequence.compound.NucleotideCompound;
43
import org.eclipse.core.runtime.IProgressMonitor;
44
import org.eclipse.swt.SWT;
45
import org.eclipse.swt.widgets.Composite;
46
import org.eclipse.ui.IActionBars;
47
import org.eclipse.ui.IEditorInput;
48
import org.eclipse.ui.IEditorSite;
49
import org.eclipse.ui.PartInitException;
50
import org.eclipse.ui.PlatformUI;
51
import org.eclipse.ui.commands.ICommandService;
52
import org.eclipse.ui.part.EditorPart;
53

    
54
import eu.etaxonomy.taxeditor.editor.handler.ToggleInsertOverwriteHandler;
55
import eu.etaxonomy.taxeditor.editor.handler.ToggleLeftRightInsertionHandler;
56

    
57

    
58

    
59
/**
60
 * Editor component to edit a contig alignment used to combine different overlapping pherograms from Sanger sequencing to
61
 * a consensus sequence.
62
 * <p>
63
 * The contained GUI components used to edit the alignment come from <a href="http://bioinfweb.info/LibrAlign/">LibrAlign</a>.
64
 *
65
 * @author Ben Stöver
66
 * @author pplitzner
67
 * @date 04.08.2014
68
 */
69
public class AlignmentEditor extends EditorPart {
70
    public static final String ID = "eu.etaxonomy.taxeditor.editor.molecular.AlignmentEditor";
71
	public static final int READS_AREA_INDEX = 1;
72
	public static final int CONSENSUS_AREA_INDEX = READS_AREA_INDEX + 1;
73
	public static final String DEFAULT_READ_NAME_PREFIX = "Read ";
74
	
75

    
76
    private MultipleAlignmentsContainer alignmentsContainer = null;
77
    private Map<Integer, URI> uriMap = new TreeMap<Integer, URI>();  //TODO Move this to ContigSequenceDataProvider
78

    
79

    
80
    private void refreshToolbarElement(String id) {
81
		ICommandService commandService = 
82
				(ICommandService)PlatformUI.getWorkbench().getActiveWorkbenchWindow().getService(ICommandService.class);
83
		if (commandService != null) {
84
			commandService.refreshElements(id, Collections.EMPTY_MAP);
85
		}    	
86
    }
87
    
88

    
89
    private void registerEditSettingListener(MultipleAlignmentsContainer container) {
90
    	container.getEditSettings().addListener(new EditSettingsListener() {
91
					@Override
92
					public void workingModeChanged(EditSettingsChangeEvent e) {}  // Currently nothing to do
93
					
94
					@Override
95
					public void insertLeftInDataAreaChanged(EditSettingsChangeEvent e) {
96
						updateStatusBar();
97
				    	refreshToolbarElement(ToggleLeftRightInsertionHandler.COMMAND_ID);
98
					}
99
					
100
					@Override
101
					public void insertChanged(EditSettingsChangeEvent e) {
102
						updateStatusBar();
103
				    	refreshToolbarElement(ToggleInsertOverwriteHandler.COMMAND_ID);
104
					}
105
				});
106
    }
107
    
108
    
109
    private AlignmentArea createIndexArea(MultipleAlignmentsContainer container) {
110
		AlignmentArea result = new AlignmentArea(container);
111
		result.setAllowVerticalScrolling(false);
112
		result.getContentArea().getDataAreas().getTopAreas().add(new SequenceIndexArea(result.getContentArea()));
113
		return result;
114
    }
115
    
116
    
117
    private AlignmentArea createEditableAlignmentArea(MultipleAlignmentsContainer container, boolean allowVerticalScrolling) {
118
		AlignmentArea result = new AlignmentArea(container);
119
		result.setAllowVerticalScrolling(allowVerticalScrolling);
120

    
121
		TokenSet<NucleotideCompound> tokenSet = new BioJavaTokenSet<NucleotideCompound>(new DNACompoundSet(), true);
122
		SequenceDataProvider<NucleotideCompound> provider = new PackedSequenceDataProvider<NucleotideCompound>(tokenSet);
123
		result.getContentArea().setSequenceProvider(provider, false);
124
		
125
		return result;
126
	}
127

    
128
    
129
    private AlignmentArea createConsensusHintArea(MultipleAlignmentsContainer container, 
130
    		SequenceDataProvider<?> sequenceProvider) {
131
    	
132
		AlignmentArea result = new AlignmentArea(container);
133
		result.setAllowVerticalScrolling(false);
134
		result.getContentArea().getDataAreas().getBottomAreas().add(
135
				new ConsensusSequenceArea(result.getContentArea(), sequenceProvider));
136
		return result;
137
    }
138
    
139
    
140
    private MultipleAlignmentsContainer getAlignmentsContainer() {
141
    	if (alignmentsContainer == null) {
142
    		alignmentsContainer = new MultipleAlignmentsContainer();
143
    		
144
    		AlignmentAreaList list = alignmentsContainer.getAlignmentAreas();
145
    		list.add(createIndexArea(alignmentsContainer));
146
    		AlignmentArea readsArea = createEditableAlignmentArea(alignmentsContainer, true);
147
    		list.add(readsArea);  // Make sure READS_AREA_INDEX is correct.
148
    		list.add(createEditableAlignmentArea(alignmentsContainer, false));  // Make sure COMSENSUS_AREA_INDEX is correct.
149
    		list.add(createConsensusHintArea(alignmentsContainer, 
150
    				readsArea.getContentArea().getSequenceProvider()));
151
    		
152
    		registerEditSettingListener(alignmentsContainer);
153
       	}
154
		return alignmentsContainer;
155
	}
156
    
157
    
158
    private AlignmentArea getReadsArea() {
159
    	return getAlignmentsContainer().getAlignmentAreas().get(READS_AREA_INDEX);
160
    }
161

    
162

    
163
    private AlignmentArea getConsensusArea() {
164
    	return getAlignmentsContainer().getAlignmentAreas().get(CONSENSUS_AREA_INDEX);
165
    }
166

    
167

    
168
	/* (non-Javadoc)
169
     * @see org.eclipse.ui.part.WorkbenchPart#createPartControl(org.eclipse.swt.widgets.Composite)
170
     */
171
    @Override
172
    public void createPartControl(Composite parent) {
173
		getAlignmentsContainer().createSWTWidget(parent, SWT.NONE);
174
		updateStatusBar();
175

    
176
		// Just for testing:
177
		try {
178
			addRead(new File("D:/Users/BenStoever/Documents/Studium/Projekte/Promotion/EDITor/Quelltexte/LibrAlign branch/Repository/eu.etaxonomy.taxeditor.editor/src/main/resources/AlignmentTestData/JR430_JR-P01.ab1").toURI());
179
			addRead(new File("D:/Users/BenStoever/Documents/Studium/Projekte/Promotion/EDITor/Quelltexte/LibrAlign branch/Repository/eu.etaxonomy.taxeditor.editor/src/main/resources/AlignmentTestData/JR444_JR-P05.ab1").toURI());
180
			
181
			// Add test consensus sequence:
182
			SequenceDataProvider consensusProvider = getConsensusArea().getContentArea().getSequenceProvider();
183
			int id = consensusProvider.addSequence("Consensus");
184
			Collection<Object> tokens = new ArrayList<Object>();  // First save tokens in a collection to avoid GUI updated for each token.
185
			tokens.add(consensusProvider.getTokenSet().tokenByKeyChar('A'));
186
			tokens.add(consensusProvider.getTokenSet().tokenByKeyChar('C'));
187
			tokens.add(consensusProvider.getTokenSet().tokenByKeyChar('G'));
188
			tokens.add(consensusProvider.getTokenSet().tokenByKeyChar('T'));
189
			consensusProvider.insertTokensAt(id, 0, tokens);
190
		}
191
		catch (Exception e) {
192
			throw new RuntimeException(e);
193
		}
194
    }
195
    
196
    
197
    private void updateStatusBar() {
198
        IActionBars bars = getEditorSite().getActionBars();
199
        bars.getStatusLineManager().setMessage("Edit mode: " + 
200
        		(getReadsArea().getContentArea().getEditSettings().isInsert() ? "Insert" : "Overwrite") + "  " +
201
        		"Insertion in pherogram: " +
202
	       		(getReadsArea().getContentArea().getEditSettings().isInsertLeftInDataArea() ? "Left" : "Right"));
203
    }
204

    
205
    
206
    /* (non-Javadoc)
207
     * @see org.eclipse.ui.part.EditorPart#doSave(org.eclipse.core.runtime.IProgressMonitor)
208
     */
209
    @Override
210
    public void doSave(IProgressMonitor monitor) {
211
        // TODO Auto-generated method stub
212

    
213
    }
214
    
215

    
216
    /* (non-Javadoc)
217
     * @see org.eclipse.ui.part.EditorPart#doSaveAs()
218
     */
219
    @Override
220
    public void doSaveAs() {
221
        // TODO Auto-generated method stub
222

    
223
    }
224
    
225

    
226
    /* (non-Javadoc)
227
     * @see org.eclipse.ui.part.EditorPart#init(org.eclipse.ui.IEditorSite, org.eclipse.ui.IEditorInput)
228
     */
229
    @Override
230
    public void init(IEditorSite site, IEditorInput input) throws PartInitException {
231
        setSite(site);
232
        setInput(input);
233
    }
234
    
235

    
236
    /* (non-Javadoc)
237
     * @see org.eclipse.ui.part.EditorPart#isDirty()
238
     */
239
    @Override
240
    public boolean isDirty() {
241
        // TODO Auto-generated method stub
242
        return false;
243
    }
244
    
245

    
246
    /* (non-Javadoc)
247
     * @see org.eclipse.ui.part.EditorPart#isSaveAsAllowed()
248
     */
249
    @Override
250
    public boolean isSaveAsAllowed() {
251
        // TODO Auto-generated method stub
252
        return false;
253
    }
254
    
255

    
256
    @Override
257
    public void setFocus() {}
258

    
259
    
260
    public boolean isInsertMode() {
261
        return getAlignmentsContainer().getEditSettings().isInsert();
262
    }
263

    
264
    
265
    public boolean isInsertLeftInPherogram() {
266
        return getAlignmentsContainer().getEditSettings().isInsertLeftInDataArea();
267
    }
268
    
269
    
270
    public void toggleLeftRightInsertionInPherogram() {
271
    	getAlignmentsContainer().getEditSettings().toggleInsertLeftInDataArea();
272
    }
273
    
274

    
275
    public void toggleInsertOverwrite() {
276
    	getAlignmentsContainer().getEditSettings().toggleInsert();
277
    }
278
    
279
    
280
	public static PherogramProvider readPherogram(URI uri) throws IOException, UnsupportedChromatogramFormatException {
281
		PherogramProvider result;
282
		InputStream stream = uri.toURL().openStream();
283
		try {
284
			result = new BioJavaPherogramProvider(ChromatogramFactory.create(stream));
285
		}
286
		finally {
287
			stream.close();
288
		}
289
		return result;
290
	}
291

    
292
	
293
	private String newReadName() {
294
		int index = 1;
295
		while (getReadsArea().getContentArea().getSequenceProvider().sequenceIDByName(DEFAULT_READ_NAME_PREFIX + index) 
296
				!= SequenceDataProvider.NO_SEQUENCE_FOUND) {
297
			
298
			index++;
299
		}
300
		return DEFAULT_READ_NAME_PREFIX + index;
301
	}
302

    
303
	
304
    public void addRead(URI pherogramURI) throws IOException, UnsupportedChromatogramFormatException {
305
    	addRead(newReadName(), pherogramURI);
306
    }
307
    
308
    
309
    public void addRead(String name, URI pherogramURI) throws IOException, UnsupportedChromatogramFormatException {
310
		AlignmentContentArea contentArea = getReadsArea().getContentArea();
311
		SequenceDataProvider provider = contentArea.getSequenceProvider();
312
		PherogramProvider pherogramProvider = readPherogram(pherogramURI);  // Must happen before a sequence is added, because it might throw an exception.
313
		
314
        // Create sequence:
315
		provider.addSequence(name);
316
		int id = provider.sequenceIDByName(name);
317
		
318
		// Copy base call sequence into alignment:
319
		Collection<Object> tokens = new ArrayList<Object>();  // First save tokens in a collection to avoid GUI updated for each token.
320
		for (int i = 0; i < pherogramProvider.getSequenceLength(); i++) {
321
			tokens.add(provider.getTokenSet().tokenByKeyChar(
322
				pherogramProvider.getBaseCall(i).getUpperedBase().charAt(0)));
323
		}
324
		provider.insertTokensAt(id, 0, tokens);
325
		
326
		// Add data area:
327
		PherogramArea pherogramArea = new PherogramArea(contentArea, pherogramProvider);
328
		pherogramArea.addMouseListener(new PherogramMouseListener(pherogramURI));
329
		contentArea.getDataAreas().getSequenceAreas(id).add(pherogramArea);
330
		
331
		// Save source URI:
332
		uriMap.put(id, pherogramURI);
333
	}
334
}
(1-1/6)