d7dee86316125b90d3d9b87f7fadef71a4b7ad04
[jalview.git] / src / org / biojava / dasobert / feature / FeatureTrackConverter.java
1 /*
2  *                  BioJava development code
3  *
4  * This code may be freely distributed and modified under the
5  * terms of the GNU Lesser General Public Licence.  This should
6  * be distributed with the code.  If you do not have a copy,
7  * see:
8  *
9  *      http://www.gnu.org/copyleft/lesser.html
10  *
11  * Copyright for this code is held jointly by the individual
12  * authors.  These should be listed in @author doc comments.
13  *
14  * For more information on the BioJava project and its aims,
15  * or to join the biojava-l mailing list, visit the home page
16  * at:
17  *
18  *      http://www.biojava.org/
19  * 
20  * Created on Dec 5, 2007
21  * 
22  */
23
24 package org.biojava.dasobert.feature;
25
26 import java.awt.Color;
27 import java.util.ArrayList;
28 import java.util.Iterator;
29 import java.util.List;
30 import java.util.Map;
31
32
33
34 /** converts the features from their "raw" representation as a Map
35  * into a Feature class
36  * @author Andreas Prlic
37  *
38  */
39 public class FeatureTrackConverter {
40
41         public static final Color HELIX_COLOR  = new Color(255,51,51);
42         public static final Color STRAND_COLOR = new Color(255,204,51);
43         public static final Color TURN_COLOR   = new Color(204,204,204); 
44
45
46         // some  annotation types, for which there is a special treatment
47         public static final String DISULFID_TYPE = "DISULFID";
48         public static final String SECSTRUC_TYPE = "SECSTRUC";
49         public static final String METAL_TYPE    = "METAL";
50         public static final String MSD_SITE_TYPE = "MSD_SITE";
51
52         String type;
53         public static final String TYPE_HISTOGRAM = "histogram";
54         public static final String TYPE_DEFAULT   = "default";
55
56
57         // rotate between these colors
58         public static final  Color[] entColors = new Color []{
59                 new Color(51,51,255), // blue
60                 new Color(102,255,255),    // cyan
61                 new Color(153,255,153), // green
62                 new Color(153,255,153), // green
63                 new Color(255,153,153), // pink
64                 new Color(255,51,51),   // red
65                 new Color(255,51,255)    // pink 
66         };
67
68         public static final String[] txtColors = new String[] { 
69                 "blue",
70                 "pink",
71                 "green",
72                 "yellow",
73                 "red",
74                 "cyan",
75         "pink"};
76
77         Map[] stylesheet;
78
79         boolean isHistogram = false;
80
81
82         public FeatureTrackConverter(){
83                 type = TYPE_DEFAULT;    
84                 stylesheet = new Map[0];
85         }
86
87         public FeatureTrackConverter(Map[] stylesheet){
88
89                 if (stylesheet == null)
90                         stylesheet = new Map[0];
91
92                 this.stylesheet = stylesheet;
93
94         }
95
96
97         public FeatureTrackConverter(Map[] stylesheet, boolean isHistogram){
98                 this(stylesheet);
99                 this.isHistogram = isHistogram;
100                 if ( isHistogram)
101                         type = TYPE_HISTOGRAM;
102         }
103         public String getType() {
104                 return type;
105         }
106
107         public void setType(String type) {
108                 if ( type.equals(TYPE_HISTOGRAM))
109                         isHistogram = true;
110                 this.type = type;
111         }
112
113         public boolean isHistogram() {
114                 return isHistogram;
115         }
116
117
118         public void setHistogram(boolean isHistogram) {
119                 this.isHistogram = isHistogram;
120         }
121
122         
123
124         
125
126         public  FeatureTrack[] convertMap2Features(Map[] mapfeatures){
127                 List features = new ArrayList();
128
129                 boolean first = true ;
130                 boolean secstruc = false ;
131                 boolean isGroup  = false;
132
133                 FeatureTrack feat = null ;
134                 Segment segment   = null ;
135
136                 int featuresCounter = 0;
137                 String prevGroup = null;
138
139                 for (int i = 0 ; i< mapfeatures.length;i++) {
140
141                         Map currentFeatureMap = mapfeatures[i];
142                         String type = (String) currentFeatureMap.get("TYPE") ;
143
144                         
145                         
146                         String group = (String) currentFeatureMap.get("GROUP");
147                         if ( group != null){
148                                 if ( prevGroup != null) {
149                                         if ( group.equals(prevGroup)){
150                                                 feat.setName(group);
151                                                 isGroup = true;
152                                         } else {
153                                                 isGroup = false;
154                                         }
155                                 } else {
156                                         isGroup = false;
157                                 }
158                         } else {
159                                 isGroup = false;
160                         }                       
161
162                         // we are skipping literature references for the moment 
163                         // TODO: add a display to spice for non-positional features
164                         //
165                         if ( type.equals("reference") || type.equals("GOA")){
166                                 continue ;
167                         }
168
169                         if (! first) 
170                         {
171                                 // if not first feature
172
173                                 if ( (! secstruc ) && (! isGroup) )  {             
174
175                                         // if not secondary structure and not in a group ...
176                                         features = testAddFeatures(features,feat);
177
178
179                                 } else if ( ! 
180                                                 (
181                                                                 type.equals("HELIX")  || 
182                                                                 type.equals("STRAND") || 
183                                                                 type.equals("TURN")  
184                                                 ) 
185                                 )
186                                 {
187                                         // end of secondary structure
188                                         secstruc = false ;
189                                         if ( feat != null && (! isGroup)) {                                             
190                                                 features = testAddFeatures(features,feat);                        
191                                         }
192
193                                 }
194                         } // end of not first
195
196                         first = false ;             
197                         if ( (! secstruc) && (! isGroup)) {                             
198                                 featuresCounter +=1;
199                                 feat = getNewFeat(currentFeatureMap);       
200                         }
201
202
203
204
205                         if (type.equals("STRAND")){
206                                 secstruc = true ;                               
207                                 currentFeatureMap.put("colorTxt","yellow");
208                                 feat.setName("SECSTRUC");       
209                                 feat.setType("SECSTRUC");
210                         }
211
212                         else if (type.equals("HELIX")) {
213                                 secstruc = true ;                               
214                                 currentFeatureMap.put("colorTxt","red");
215                                 feat.setName("SECSTRUC");
216                                 feat.setType("SECSTRUC");
217                         }   
218
219                         else if (type.equals("TURN")) {
220                                 secstruc = true ;                               
221                                 currentFeatureMap.put("colorTxt","white");
222
223                                 feat.setName("SECSTRUC");
224                                 feat.setType("SECSTRUC");
225                         }     
226                         else {
227                                 secstruc = false ;                              
228                                 currentFeatureMap.put("colorTxt",txtColors[featuresCounter%txtColors.length]);
229                                 if ( ! isGroup) {
230                                         try {
231                                                 feat.setName(type);
232                                         
233                                         } catch ( NullPointerException e) {
234                                                 //e.printStackTrace();
235                                                 feat.setName("null");
236                                         }
237                                 }
238                         }
239
240                         segment = getNewSegment(currentFeatureMap);
241
242                         feat.addSegment(segment);       
243                         prevGroup = group;
244                 }   
245
246                 if ( feat != null)  
247                         features =testAddFeatures(features,feat);
248
249
250                 return (FeatureTrack[]) features.toArray(new FeatureTrack[features.size()]);
251         }
252
253         /**      test if this features is added as a new feature to the features list, 
254          * or if it is joint with an already existing one...
255          * 
256          * @param features
257          * @param newFeature
258          * @return a List of FeatureTrack objects
259          */
260         protected  List testAddFeatures(List features,FeatureTrack newFeature){
261                 
262                 //System.out.println("testing " + newFeature + " " + newFeature.getScore());   
263                 Iterator iter = features.iterator();
264
265
266                 if ( isHistogramFeatureType(newFeature)) {  
267                         
268                         // return histogram type features
269                         type = TYPE_HISTOGRAM;
270
271                         Segment seg = getHistogramSegmentFromFeature(newFeature);
272
273                         while (iter.hasNext()){
274                                 FeatureTrack knownFeature = (FeatureTrack) iter.next() ;
275                                 String knownType = knownFeature.getType();
276
277                                 //System.out.println("found histogram style " + feat);
278                                 // set type of this DAS source to being HISTOGRAM style
279
280
281                                 if ( knownType.equals(newFeature.getType())){
282                                         // convert the feature into a HistogramSegment and add to the already known feature
283
284                                         knownFeature.addSegment(seg);
285                                         // we can return now
286                                         return features;
287                                 }
288
289
290                         }
291                         // we could not link this to any existing feature
292                         // convert it to a new HistogramFeature
293                         HistogramFeature hfeat = new HistogramFeature();
294
295                         hfeat.setLink(newFeature.getLink());
296                         hfeat.setMethod(newFeature.getMethod());
297                         hfeat.setName(newFeature.getName());
298                         hfeat.setNote(newFeature.getNote());
299                         hfeat.setScore("0");
300                         hfeat.setSource(newFeature.getSource());
301                         hfeat.addSegment(seg);
302                         hfeat.setType(newFeature.getType());
303
304                         newFeature = hfeat;
305                         features.add(newFeature);
306                         return features;
307                 } 
308
309
310
311                 while (iter.hasNext()){
312                         FeatureTrack knownFeature = (FeatureTrack) iter.next() ;
313                         // this only compares method source and type ...
314                         boolean sameFeat = false;
315                         if ( knownFeature.equals(newFeature))
316                                 sameFeat = true;
317
318                         if ( ( knownFeature.getSource().equals(newFeature.getSource() )) &&
319                                         ( knownFeature.getMethod().equals(newFeature.getMethod())) &&
320                                         ( knownFeature.getNote().equals(newFeature.getNote())) &&
321                                         isSecondaryStructureFeat(knownFeature) && 
322                                         isSecondaryStructureFeat(newFeature))
323                                 sameFeat =true;
324
325                         if ( sameFeat) {
326
327                                 // seems to be of same type, method and source, so check if the segments can be joined
328
329                                 List tmpsegs = knownFeature.getSegments();
330                                 Iterator segiter = tmpsegs.iterator();
331                                 List newsegs = newFeature.getSegments();
332                                 Iterator newsegsiter = newsegs.iterator();
333                                 boolean overlap = false;
334                                 while (newsegsiter.hasNext()){
335                                         Segment newseg = (Segment)newsegsiter.next();
336
337
338                                         while (segiter.hasNext()){
339                                                 Segment tmpseg = (Segment) segiter.next();
340
341                                                 if (  tmpseg.overlaps(newseg))
342                                                         overlap = true;
343                                         }
344                                 }
345
346                                 if ( ! overlap){
347                                         // add all new segments to old features...
348                                         newsegsiter = newsegs.iterator();
349                                         while (newsegsiter.hasNext()){
350                                                 Segment newseg = (Segment)newsegsiter.next();
351                                                 knownFeature.addSegment(newseg);
352                                         }
353
354                                         return features;
355                                 } 
356                         }
357
358                 }
359
360                 //      if we get here, the  features could not be joint with any other one, so there is always some overlap
361                 // add to the list of known features
362                 features.add(newFeature);
363                 return features;
364         }
365
366         private FeatureTrack getNewFeat(Map currentFeatureMap) {
367                 FeatureTrack feat = new FeatureTrackImpl();
368                 //logger.finest(currentFeatureMap);
369                 //System.out.println("DrawableDasSource " + currentFeatureMap);
370                 feat.setSource((String)currentFeatureMap.get("dassource"));
371                 feat.setName(  (String)currentFeatureMap.get("NAME"));
372                 feat.setType(  (String)currentFeatureMap.get("TYPE"));
373                 feat.setLink(  (String)currentFeatureMap.get("LINK"));
374                 feat.setNote(  (String)currentFeatureMap.get("NOTE"));
375                 
376                 String typeID       = (String) currentFeatureMap.get("TYPE_ID");
377                 String typeCategory = (String) currentFeatureMap.get("TYPE_CATEGORY");
378                 feat.setTypeID(typeID);
379                 feat.setTypeCategory(typeCategory);
380                 
381                 String method = (String)currentFeatureMap.get("METHOD");
382                 if ( method == null) { method = "";}
383                 feat.setMethod(method);
384                 feat.setScore( (String)currentFeatureMap.get("SCORE"));
385                 return feat ;
386         }
387
388         private Segment getNewSegment(Map featureMap) {
389                 Segment s = new SegmentImpl();
390                 String sstart = (String)featureMap.get("START") ;
391                 String send   = (String)featureMap.get("END")   ;
392                 int start = Integer.parseInt(sstart) ;
393                 int end   = Integer.parseInt(send)   ;
394                 s.setStart(start);
395                 s.setEnd(end);
396                 s.setName((String)featureMap.get("TYPE"));
397                 s.setTxtColor((String)featureMap.get("colorTxt"));  
398                 s.setColor((Color)featureMap.get("color"));
399                 s.setNote((String) featureMap.get("NOTE"));
400                 return s ;
401
402         }
403
404         private boolean isSecondaryStructureFeat(FeatureTrack feat){
405                 String type = feat.getType();
406                 if (
407                                 type.equals("HELIX")  || 
408                                 type.equals("STRAND") || 
409                                 type.equals("TURN")
410                 ) return true;
411                 return false;
412         }
413
414         private boolean isHistogramFeatureType(FeatureTrack feat){
415                 String ftype = feat.getType();
416
417                 Map[] style = stylesheet;
418
419                 //System.out.println("is HistogramFeature type " + ftype + " " + style );
420
421
422                 // todo : move this info into a config file...
423
424                 if ( ftype.equals("hydrophobicity")){
425                         return true;
426                 }
427                 if ( getType().equals(TYPE_HISTOGRAM) )
428                         return true;
429
430
431
432                 if (style != null ) {
433
434                         for ( int i =0; i< style.length ; i++){
435                                 Map m = style[i];
436
437                                 // make sure the stylesheet is for this feature type
438                                 String styleType = (String) m.get("type");
439                                 if ( styleType != null) {
440                                         if ( ! styleType.equals(ftype)){
441                                                 continue;
442                                         }
443                                 } else {
444                                         continue;
445                                 }
446
447                                 String type = (String) m.get("style");
448                                 if ( type != null) {
449                                         //System.out.println("stylesheet type " + type);
450                                         if ( type.equals("gradient") || ( type.equals("lineplot")) || ( type.equals("histogram"))){
451
452                                                 return true;
453                                         }
454                                 }
455                         }
456                 }
457
458                 return false;
459         }
460
461
462         private HistogramSegment getHistogramSegmentFromFeature(FeatureTrack feat){
463                 HistogramSegment s = new HistogramSegment();
464
465                 double score = 0.0;
466
467                 try {
468                         score = Double.parseDouble(feat.getScore());
469
470                 } catch (Exception e){
471                         //e.printStackTrace();
472                 }
473                 s.setScore(score);              
474                 List segments = feat.getSegments();
475                 if (segments.size() > 0){
476                         Segment seg = (Segment) segments.get(0);
477                         s.setName(seg.getName());
478                         s.setStart(seg.getStart());
479                         s.setEnd(seg.getEnd());
480                         s.setNote(seg.getNote());
481                         s.setColor(seg.getColor());
482                         s.setTxtColor(seg.getTxtColor());
483                 }
484
485
486                 return s;
487         }
488
489
490 }