+
+ /*
+ * make a gene-length sequence filled with gaps
+ * we will fill in the bases for transcript regions
+ */
+ char[] seqChars = new char[gene.getLength()];
+ Arrays.fill(seqChars, al.getGapCharacter());
+
+ /*
+ * look for exon features of the transcript, failing that for CDS
+ * (for example ENSG00000124610 has 1 CDS but no exon features)
+ */
+ String parentId = "transcript:" + accId;
+ List<SequenceFeature> splices = findFeatures(gene,
+ SequenceOntology.EXON, parentId);
+ if (splices.isEmpty())
+ {
+ splices = findFeatures(gene, SequenceOntology.CDS, parentId);
+ }
+
+ int transcriptLength = 0;
+ final char[] geneChars = gene.getSequence();
+ int offset = gene.getStart(); // to convert to 0-based positions
+ List<int[]> mappedFrom = new ArrayList<int[]>();
+
+ for (SequenceFeature sf : splices)
+ {
+ int start = sf.getBegin() - offset;
+ int end = sf.getEnd() - offset;
+ int spliceLength = end - start + 1;
+ System.arraycopy(geneChars, start, seqChars, start, spliceLength);
+ transcriptLength += spliceLength;
+ mappedFrom.add(new int[] { sf.getBegin(), sf.getEnd() });
+ }
+
+ Sequence transcript = new Sequence(accId, seqChars, 1, transcriptLength);
+ transcript.createDatasetSequence();
+
+ al.addSequence(transcript);
+
+ /*
+ * transfer features to the new sequence; we use EnsemblCdna to do this,
+ * to filter out unwanted features types (see method retainFeature)
+ */
+ List<int[]> mapTo = new ArrayList<int[]>();
+ mapTo.add(new int[] { 1, transcriptLength });
+ MapList mapping = new MapList(mappedFrom, mapTo, 1, 1);
+ new EnsemblCdna().transferFeatures(gene.getSequenceFeatures(),
+ transcript.getDatasetSequence(), mapping, parentId);
+
+ /*
+ * and finally fetch the protein product and save as a cross-reference
+ */
+ addProteinProduct(transcript);
+
+ return transcript;
+ }
+
+ /**
+ * Returns a list of the transcript features on the sequence whose Parent is
+ * the gene for the accession id. Also removes all transcript features from
+ * the gene sequence, as we have no further need for them and they obscure
+ * more useful features on the display.
+ *
+ * @param accId
+ * @param geneSequence
+ * @return
+ */
+ protected List<SequenceFeature> getTranscriptFeatures(String accId,
+ SequenceI geneSequence)
+ {
+ List<SequenceFeature> transcriptFeatures = new ArrayList<SequenceFeature>();
+