001/* 002 * BioJava development code 003 * 004 * This code may be freely distributed and modified under the 005 * terms of the GNU Lesser General Public Licence. This should 006 * be distributed with the code. If you do not have a copy, 007 * see: 008 * 009 * http://www.gnu.org/copyleft/lesser.html 010 * 011 * Copyright for this code is held jointly by the individual 012 * authors. These should be listed in @author doc comments. 013 * 014 * For more information on the BioJava project and its aims, 015 * or to join the biojava-l mailing list, visit the home page 016 * at: 017 * 018 * http://www.biojava.org/ 019 * 020 */ 021 022package org.biojava.bio.search; 023 024import org.biojava.bio.Annotatable; 025import org.biojava.bio.Annotation; 026import org.biojava.bio.alignment.Alignment; 027import org.biojava.bio.seq.StrandedFeature.Strand; 028import org.biojava.utils.AbstractChangeable; 029import org.biojava.utils.ChangeForwarder; 030import org.biojava.utils.ChangeListener; 031import org.biojava.utils.ChangeSupport; 032import org.biojava.utils.ChangeType; 033import org.biojava.utils.ObjectUtil; 034 035/** 036 * <p><code>SimpleSeqSimilaritySearchSubHit</code> objects represent 037 * sub-hits which make up a hit. In the case of Blast these correspond 038 * to HSPs.</p> 039 * 040 * @author Keith James 041 * @author Gerald Loeffler 042 * @since 1.1 043 */ 044public class SimpleSeqSimilaritySearchSubHit extends AbstractChangeable 045 implements SeqSimilaritySearchSubHit 046{ 047 protected transient ChangeForwarder annotationForwarder; 048 049 private double score; 050 private double pValue; 051 private double eValue; 052 private int queryStart; 053 private int queryEnd; 054 private Strand queryStrand; 055 private int subjectStart; 056 private int subjectEnd; 057 private Strand subjectStrand; 058 private Alignment alignment; 059 private Annotation annotation; 060 061 // Hashcode is cached after first calculation because the data on 062 // which is is based do not change 063 private int hc; 064 private boolean hcCalc; 065 066 /** 067 * Creates a new <code>SimpleSeqSimilaritySearchSubHit</code> 068 * object. 069 * 070 * @param queryStart an <code>int</code> value indicating the 071 * start coordinate of the hit on the query sequence. 072 * @param queryEnd an <code>int</code> value indicating the end 073 * coordinate of the hit on the query sequence. 074 * @param queryStrand a <code>Strand</code> object indicating the 075 * strand of the hit with respect to the query sequence, which may 076 * be null for protein similarities. 077 * @param subjectStart an <code>int</code> value indicating the 078 * start coordinate of the hit on the subject sequence. 079 * @param subjectEnd an <code>int</code> value indicating the end 080 * coordinate of the hit on the query sequence. 081 * @param subjectStrand a <code>Strand</code> object indicating 082 * the strand of the hit with respect to the query sequence, which 083 * may be null for protein similarities. 084 * @param score a <code>double</code> value; the score of the 085 * subhit, which may not be NaN. 086 * @param eValue a <code>double</code> the E-value of the 087 * subhit, which may be NaN. 088 * @param pValue a <code>double</code> value; the P-value of the 089 * hit, which may be NaN. 090 * @param alignment an <code>Alignment</code> object containing 091 * the alignment described by the subhit region, which may not be 092 * null. 093 */ 094 public SimpleSeqSimilaritySearchSubHit(double score, 095 double eValue, 096 double pValue, 097 int queryStart, 098 int queryEnd, 099 Strand queryStrand, 100 int subjectStart, 101 int subjectEnd, 102 Strand subjectStrand, 103 Alignment alignment, 104 Annotation annotation) 105 { 106 if (Double.isNaN(score)) 107 { 108 throw new IllegalArgumentException("score was NaN"); 109 } 110 111 // pValue may be NaN 112 // eValue may be NaN 113 if (alignment == null) 114 { 115 throw new IllegalArgumentException("alignment was null"); 116 } 117 118 if (annotation == null) 119 { 120 throw new IllegalArgumentException("annotation was null"); 121 } 122 123 // Lock alignment by vetoing all changes 124 alignment.addChangeListener(ChangeListener.ALWAYS_VETO); 125 126 // Lock the annotation by vetoing all changes to properties 127 annotation.addChangeListener(ChangeListener.ALWAYS_VETO); 128 129 this.score = score; 130 this.eValue = eValue; 131 this.pValue = pValue; 132 this.queryStart = queryStart; 133 this.queryEnd = queryEnd; 134 this.queryStrand = queryStrand; 135 this.subjectStart = subjectStart; 136 this.subjectEnd = subjectEnd; 137 this.subjectStrand = subjectStrand; 138 this.alignment = alignment; 139 this.annotation = annotation; 140 141 hcCalc = false; 142 } 143 144 public double getScore() 145 { 146 return score; 147 } 148 149 public double getPValue() 150 { 151 return pValue; 152 } 153 154 public double getEValue() 155 { 156 return eValue; 157 } 158 159 public int getQueryStart() 160 { 161 return queryStart; 162 } 163 164 public int getQueryEnd() 165 { 166 return queryEnd; 167 } 168 169 public Strand getQueryStrand() 170 { 171 return queryStrand; 172 } 173 174 public int getSubjectStart() 175 { 176 return subjectStart; 177 } 178 179 public int getSubjectEnd() 180 { 181 return subjectEnd; 182 } 183 184 public Strand getSubjectStrand() 185 { 186 return subjectStrand; 187 } 188 189 public Alignment getAlignment() 190 { 191 return alignment; 192 } 193 194 /** 195 * <code>getAnnotation</code> returns the Annotation associated 196 * with this sub-hit. 197 * 198 * @return an <code>Annotation</code>. 199 */ 200 public Annotation getAnnotation() 201 { 202 return annotation; 203 } 204 205 public boolean equals(Object other) 206 { 207 if (other == this) return true; 208 if (other == null) return false; 209 210 if (! other.getClass().equals(this.getClass())) return false; 211 212 SimpleSeqSimilaritySearchSubHit that = 213 (SimpleSeqSimilaritySearchSubHit) other; 214 215 if (! ObjectUtil.equals(this.score, that.score)) 216 return false; 217 if (! ObjectUtil.equals(this.pValue, that.pValue)) 218 return false; 219 if (! ObjectUtil.equals(this.eValue, that.eValue)) 220 return false; 221 if (! ObjectUtil.equals(this.queryStart, that.queryStart)) 222 return false; 223 if (! ObjectUtil.equals(this.queryEnd, that.queryEnd)) 224 return false; 225 if (! ObjectUtil.equals(this.queryStrand, that.queryStrand)) 226 return false; 227 if (! ObjectUtil.equals(this.subjectStart, that.subjectStart)) 228 return false; 229 if (! ObjectUtil.equals(this.subjectEnd, that.subjectEnd)) 230 return false; 231 if (! ObjectUtil.equals(this.subjectStrand, that.subjectStrand)) 232 return false; 233 if (! ObjectUtil.equals(this.annotation, that.annotation)) 234 return false; 235 236 return true; 237 } 238 239 public int hashCode() 240 { 241 if (! hcCalc) 242 { 243 hc = ObjectUtil.hashCode(hc, score); 244 hc = ObjectUtil.hashCode(hc, pValue); 245 hc = ObjectUtil.hashCode(hc, eValue); 246 hc = ObjectUtil.hashCode(hc, queryStart); 247 hc = ObjectUtil.hashCode(hc, queryEnd); 248 hc = ObjectUtil.hashCode(hc, queryStrand); 249 hc = ObjectUtil.hashCode(hc, subjectStart); 250 hc = ObjectUtil.hashCode(hc, subjectEnd); 251 hc = ObjectUtil.hashCode(hc, subjectStrand); 252 hc = ObjectUtil.hashCode(hc, annotation); 253 hcCalc = true; 254 } 255 256 return hc; 257 } 258 259 public String toString() 260 { 261 return "SimpleSeqSimilaritySearchSubHit with score " + getScore(); 262 } 263 264 protected ChangeSupport getChangeSupport(ChangeType ct) 265 { 266 ChangeSupport cs = super.getChangeSupport(ct); 267 268 if (annotationForwarder == null && 269 (ct.isMatchingType(Annotatable.ANNOTATION) || Annotatable.ANNOTATION.isMatchingType(ct))) 270 { 271 annotationForwarder = 272 new ChangeForwarder.Retyper(this, cs, Annotation.PROPERTY); 273 getAnnotation().addChangeListener(annotationForwarder, 274 Annotatable.ANNOTATION); 275 } 276 277 return cs; 278 } 279}