/* DatabaseInferredFeature.java
*
* created: 2009
*
* This file is part of Artemis
*
* Copyright (C) 2009 Genome Research Limited
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
*/
package uk.ac.sanger.artemis.io;
import java.util.List;
import uk.ac.sanger.artemis.Entry;
import uk.ac.sanger.artemis.EntryGroup;
import uk.ac.sanger.artemis.FeatureChangeEvent;
import uk.ac.sanger.artemis.FeatureChangeListener;
import uk.ac.sanger.artemis.FeatureSegmentVector;
import uk.ac.sanger.artemis.FeatureVector;
import uk.ac.sanger.artemis.util.OutOfRangeException;
import uk.ac.sanger.artemis.util.ReadOnlyException;
/**
* A feature (CDS and UTRs) that is inferred from a chado
* database hierarchy (gene, transcript, exon, and polypeptide)
* defined by the ChadoCanonicalGene
.
*/
public class DatabaseInferredFeature
extends GFFStreamFeature implements FeatureChangeListener
{
public DatabaseInferredFeature(Key key,
Location location,
QualifierVector qualifiers,
ChadoCanonicalGene gene)
{
super(key, location, qualifiers);
setChadoGene(gene);
}
public void addFeatureListeners()
{
if(!getKey().equals(Key.CDS))
return;
String parent = (String) getQualifierByName("Parent").getValues().get(0);
if(getChadoGene().getProteinOfTranscript(parent) == null)
return;
Feature protein = getChadoGene().getProteinOfTranscript(parent);
((uk.ac.sanger.artemis.Feature)protein.getUserData()).addFeatureChangeListener(this);
List list = getChadoGene().getSpliceSitesOfTranscript(parent, "exon");
for(int i=0; i 0)
{
List listUTR = getChadoGene().get5UtrOfTranscript(transcriptID);
boolean isFound = containsAll(listUTR, r_diff_5);
if(!isFound)
{
Feature utrFeature = addUTR(transcriptID, "five_prime_UTR", r_diff_5,
getChadoGene().get5UtrOfTranscript(transcriptID), entry);
getChadoGene().add5PrimeUtr(transcriptID, utrFeature);
}
}
else
removeUTR(getChadoGene().get5UtrOfTranscript(transcriptID), entry);
if(r_diff_3.size() > 0)
{
List listUTR = getChadoGene().get3UtrOfTranscript(transcriptID);
boolean isFound = containsAll(listUTR, r_diff_3);
if(!isFound)
{
Feature utrFeature = addUTR(transcriptID, "three_prime_UTR", r_diff_3,
getChadoGene().get3UtrOfTranscript(transcriptID), entry);
getChadoGene().add3PrimeUtr(transcriptID, utrFeature);
}
}
else
removeUTR(getChadoGene().get3UtrOfTranscript(transcriptID), entry);
}
catch (ReadOnlyException e)
{
e.printStackTrace();
}
catch (EntryInformationException e)
{
e.printStackTrace();
}
}
/**
* Classify the ranges based on the exon and protein ranges.
* The range is divided into 5'UTR, 3'UTR and CDS ranges.
* @param proteinRange
* @param exonRange
* @param isComplement
* @param r_diff_5
* @param r_diff_3
* @param r_cds
*/
private void findRanges(Range proteinRange,
Range exonRange,
boolean isComplement,
RangeVector r_diff_5,
RangeVector r_diff_3,
RangeVector r_cds)
{
if( !proteinRange.contains(exonRange) )
{
if(exonRange.getStart () < proteinRange.getStart () &&
exonRange.getEnd () > proteinRange.getEnd ())
{
try
{
if(isComplement)
{
r_diff_3.add(new Range(exonRange.getStart(), proteinRange.getStart()-1));
r_diff_5.add(new Range(proteinRange.getEnd()+1, exonRange.getEnd()));
}
else
{
r_diff_5.add(new Range(exonRange.getStart(), proteinRange.getStart()-1));
r_diff_3.add(new Range(proteinRange.getEnd()+1, exonRange.getEnd()));
}
r_cds.add(new Range(proteinRange.getStart(), proteinRange.getEnd()));
}
catch (OutOfRangeException e){ e.printStackTrace(); }
}
else if(exonRange.getStart() >= proteinRange.getStart() &&
exonRange.getStart() < proteinRange.getEnd())
{
// exon is partially CDS and UTR
try
{
r_cds.add(new Range(exonRange.getStart(), proteinRange.getEnd()));
if(isComplement)
r_diff_5.add(new Range(proteinRange.getEnd()+1, exonRange.getEnd()));
else
r_diff_3.add(new Range(proteinRange.getEnd()+1, exonRange.getEnd()));
}
catch (OutOfRangeException e){ e.printStackTrace(); }
}
else if(exonRange.getEnd() > proteinRange.getStart() &&
exonRange.getEnd() <= proteinRange.getEnd())
{
try
{
r_cds.add(new Range(proteinRange.getStart(), exonRange.getEnd()));
if(isComplement)
r_diff_3.add(new Range(exonRange.getStart(), proteinRange.getStart()-1));
else
r_diff_5.add(new Range(exonRange.getStart(), proteinRange.getStart()-1));
}
catch (OutOfRangeException e){ e.printStackTrace(); }
}
else if(exonRange.getStart() < proteinRange.getStart())
r_diff_5.add(exonRange);
else if(exonRange.getStart() > proteinRange.getStart())
r_diff_3.add(exonRange);
}
else
r_cds.add(exonRange);
}
/**
* Override to ensure that associated features get updated.
*/
public void setLocation (final Location location)
throws ReadOnlyException, OutOfRangeException
{
if(getQualifierByName("Parent") != null)
removeFeatureListeners();
super.setLocation(location);
if(getKey().equals(Key.CDS) && getQualifierByName("Parent") != null)
{
// update the exon feature
String transcriptID = (String) getQualifierByName("Parent").getValues().get(0);
Feature exonFeature =
((Feature)(getChadoGene().getSpliceSitesOfTranscript(transcriptID, "exon").get(0)));
RangeVector exonRanges = exonFeature.getLocation().getRanges();
RangeVector cdsRanges = getLocation().getRanges();
FeatureSegmentVector segments =
((uk.ac.sanger.artemis.Feature)exonFeature.getUserData()).getSegments();
for(int i=0; iRangeVector.
* @param listUTR
* @param newRanges
* @return
*/
private boolean containsAll(List listUTR,
RangeVector newRanges)
{
RangeVector oldRanges = new RangeVector();
if(listUTR != null)
{
for(int i=0;iRangeVector contains all the ranges
* in a second RangeVector
.
* @param newRanges
* @param oldRanges
* @return
*/
private boolean containsAll(RangeVector newRanges,
RangeVector oldRanges)
{
if(newRanges.size() != oldRanges.size())
return false;
for(int i=0; i