// Group selection states
void resetTable(boolean groupsChanged)
{
- SequenceFeature[] tmpfeatures;
- String group = null, type;
- Vector<String> visibleChecks = new Vector<String>();
+ List<String> displayableTypes = new ArrayList<String>();
+ Set<String> foundGroups = new HashSet<String>();
++
AlignmentI alignment = av.getAlignment();
+
for (int i = 0; i < alignment.getHeight(); i++)
{
- if (alignment.getSequenceAt(i).getSequenceFeatures() == null)
- {
- continue;
- }
+ SequenceI seq = alignment.getSequenceAt(i);
- tmpfeatures = alignment.getSequenceAt(i).getSequenceFeatures();
- int index = 0;
- while (index < tmpfeatures.length)
+ /*
+ * get the sequence's groups for positional features
+ * and keep track of which groups are visible
+ */
+ Set<String> groups = seq.getFeatures().getFeatureGroups(true);
+ Set<String> visibleGroups = new HashSet<String>();
+ for (String group : groups)
{
- group = tmpfeatures[index].featureGroup;
- foundGroups.add(group);
-
- if (group == null || checkGroupState(group))
+ if (group == null || fr.checkGroupVisibility(group, true))
{
- type = tmpfeatures[index].getType();
- if (!visibleChecks.contains(type))
- {
- visibleChecks.addElement(type);
- }
+ visibleGroups.add(group);
}
- index++;
}
+
+ /*
+ * get distinct feature types for visible groups
+ * record distinct visible types
+ */
+ Set<String> types = seq.getFeatures().getFeatureTypesForGroups(true,
+ visibleGroups.toArray(new String[visibleGroups.size()]));
+ displayableTypes.addAll(types);
}
+ /*
+ * remove any checkboxes for groups not present
+ */
+ pruneGroups(foundGroups);
+
Component[] comps;
int cSize = featurePanel.getComponentCount();
MyCheckbox check;
av.setSelectionGroup(null);
}
- SequenceFeature[] features = findFeaturesAtRes(sequence,
+ List<SequenceFeature> features = findFeaturesAtRes(sequence,
sequence.findPosition(findRes(evt)));
- if (features != null && features.length > 0)
+ if (!features.isEmpty())
{
SearchResultsI highlight = new SearchResults();
- highlight.addResult(sequence, features[0].getBegin(),
- features[0].getEnd());
+ highlight.addResult(sequence, features.get(0).getBegin(), features
+ .get(0).getEnd());
seqCanvas.highlightSearchResults(highlight);
- }
- if (features != null && features.length > 0)
- {
+ SequenceFeature[] featuresArray = features
+ .toArray(new SequenceFeature[features.size()]);
seqCanvas.getFeatureRenderer().amendFeatures(
- new SequenceI[] { sequence }, featuresArray, false, ap,
- null);
- new SequenceI[] { sequence }, features, false, ap);
++ new SequenceI[] { sequence }, featuresArray, false, ap);
seqCanvas.highlightSearchResults(null);
}
AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
af.getViewport().setShowSequenceFeatures(showSeqFeatures);
af.getViewport().setFeaturesDisplayed(fd);
++ af.setMenusForViewport();
ColourSchemeI cs = ColourSchemeMapper.getJalviewColourScheme(
colourSchemeName, al);
if (cs != null)
{
/*
* YES_OPTION corresponds to the Amend button
+ * need to refresh Feature Settings if type, group or colour changed
*/
- boolean typeChanged = !lastFeatureAdded.equals(sf.type);
- String newType = lastFeatureAdded;
- String newFeatureGroup = lastFeatureGroupAdded;
- String newDescription = lastDescriptionAdded;
-
- sf.type = name.getText().trim();
- sf.featureGroup = group.getText().trim();
- sf.description = description.getText().replaceAll("\n", " ");
++ String newType = name.getText().trim();
++ String newFeatureGroup = group.getText().trim();
++ String newDescription = description.getText().replaceAll("\n", " ");
+ boolean refreshSettings = (!featureType.equals(sf.type) || !featureGroup
+ .equals(sf.featureGroup));
+ refreshSettings |= (fcol != oldcol);
-
- setColour(sf.type, fcol);
-
+ setColour(newType, fcol);
- getFeaturesDisplayed().setVisible(newType);
++/*?*/ getFeaturesDisplayed().setVisible(newType);
+ int newBegin = sf.begin;
+ int newEnd = sf.end;
try
{
- sf.begin = ((Integer) start.getValue()).intValue();
- sf.end = ((Integer) end.getValue()).intValue();
+ newBegin = ((Integer) start.getValue()).intValue();
+ newEnd = ((Integer) end.getValue()).intValue();
} catch (NumberFormatException ex)
{
+ // JSpinner doesn't accept invalid format data :-)
+ }
+
+ /*
+ * replace the feature by deleting it and adding a new one
+ * (to ensure integrity of SequenceFeatures data store)
+ */
+ sequences.get(0).deleteFeature(sf);
+ SequenceFeature newSf = new SequenceFeature(newType,
+ newDescription, newBegin, newEnd, sf.getScore(),
+ newFeatureGroup);
+ // ensure any additional properties are copied
+ if (sf.otherDetails != null)
+ {
+ newSf.otherDetails = new HashMap<String, Object>(sf.otherDetails);
+ }
+ ffile.parseDescriptionHTML(newSf, false);
+ // add any additional links not parsed from description
+ if (sf.links != null)
+ {
+ for (String link : sf.links)
+ {
+ newSf.addLink(link);
+ }
}
+ // amend features only gets one sequence to act on
+ sequences.get(0).addSequenceFeature(newSf);
- if (typeChanged)
- ffile.parseDescriptionHTML(sf, false);
+ if (refreshSettings)
{
- findAllFeatures();
+ featuresAdded();
}
}
}
typeWidth = new Hashtable<String, float[]>();
// TODO: change avWidth calculation to 'per-sequence' average and use long
// rather than float
- float[] avWidth = null;
- SequenceFeature[] tmpfeatures;
- String group = null, type;
- Vector<String> visibleChecks = new Vector<String>();
+
+ Set<String> displayableTypes = new HashSet<String>();
+ Set<String> foundGroups = new HashSet<String>();
- // Find out which features should be visible depending on which groups
- // are selected / deselected
- // and recompute average width ordering
+ /*
+ * determine which feature types may be visible depending on
+ * which groups are selected, and recompute average width data
+ */
for (int i = 0; i < af.getViewport().getAlignment().getHeight(); i++)
{
- tmpfeatures = af.getViewport().getAlignment().getSequenceAt(i)
- .getSequenceFeatures();
- if (tmpfeatures == null)
- {
- continue;
- }
+ SequenceI seq = af.getViewport().getAlignment().getSequenceAt(i);
- int index = 0;
- while (index < tmpfeatures.length)
+ /*
+ * get the sequence's groups for positional features
+ * and keep track of which groups are visible
+ */
+ Set<String> groups = seq.getFeatures().getFeatureGroups(true);
+ Set<String> visibleGroups = new HashSet<String>();
+ for (String group : groups)
{
- group = tmpfeatures[index].featureGroup;
- foundGroups.add(group);
-
- if (tmpfeatures[index].begin == 0 && tmpfeatures[index].end == 0)
- {
- index++;
- continue;
- }
-
if (group == null || checkGroupState(group))
{
- type = tmpfeatures[index].getType();
- if (!visibleChecks.contains(type))
- {
- visibleChecks.addElement(type);
- }
- }
- if (!typeWidth.containsKey(tmpfeatures[index].getType()))
- {
- typeWidth.put(tmpfeatures[index].getType(),
- avWidth = new float[3]);
+ visibleGroups.add(group);
}
- else
- {
- avWidth = typeWidth.get(tmpfeatures[index].getType());
- }
- avWidth[0]++;
- if (tmpfeatures[index].getBegin() > tmpfeatures[index].getEnd())
- {
- avWidth[1] += 1 + tmpfeatures[index].getBegin()
- - tmpfeatures[index].getEnd();
- }
- else
+ }
++ foundGroups.addAll(groups);
+
+ /*
+ * get distinct feature types for visible groups
+ * record distinct visible types, and their count and total length
+ */
+ Set<String> types = seq.getFeatures().getFeatureTypesForGroups(true,
+ visibleGroups.toArray(new String[visibleGroups.size()]));
+ for (String type : types)
+ {
+ displayableTypes.add(type);
+ float[] avWidth = typeWidth.get(type);
+ if (avWidth == null)
{
- avWidth[1] += 1 + tmpfeatures[index].getEnd()
- - tmpfeatures[index].getBegin();
+ avWidth = new float[2];
+ typeWidth.put(type, avWidth);
}
- index++;
+ // todo this could include features with a non-visible group
+ // - do we greatly care?
+ // todo should we include non-displayable features here, and only
+ // update when features are added?
+ avWidth[0] += seq.getFeatures().getFeatureCount(true, type);
+ avWidth[1] += seq.getFeatures().getTotalFeatureLength(type);
}
}
}
}
}
-
- if (minmax == null)
- {
- minmax = new Hashtable<String, float[][]>();
- }
-
- Set<String> oldGroups = new HashSet<String>(featureGroups.keySet());
++ // <<<<<<< HEAD
++ //
++ // =======
++ // if (minmax == null)
++ // {
++ // minmax = new Hashtable<String, float[][]>();
++ // }
++ //
++ // Set<String> oldGroups = new HashSet<String>(featureGroups.keySet());
++ // >>>>>>> refs/heads/develop
AlignmentI alignment = av.getAlignment();
+ List<String> allfeatures = new ArrayList<String>(); // or HashSet?
+
for (int i = 0; i < alignment.getHeight(); i++)
{
SequenceI asq = alignment.getSequenceAt(i);
- SequenceFeature[] features = asq.getSequenceFeatures();
-
- if (features == null)
+ for (String group : asq.getFeatures().getFeatureGroups(true))
{
- continue;
- }
-
- int index = 0;
- while (index < features.length)
- {
- String fgrp = features[index].getFeatureGroup();
- oldGroups.remove(fgrp);
- if (!featuresDisplayed.isRegistered(features[index].getType()))
++ // <<<<<<< HEAD
+ /*
+ * features in null group are always displayed; other groups
+ * keep their current visibility; new groups as 'newMadeVisible'
+ */
+ boolean groupDisplayed = true;
+ if (group != null)
++ // =======
++ // continue;
++ // }
++ //
++ // int index = 0;
++ // while (index < features.length)
++ // {
++ // String fgrp = features[index].getFeatureGroup();
++ // oldGroups.remove(fgrp);
++ // if (!featuresDisplayed.isRegistered(features[index].getType()))
++ // >>>>>>> refs/heads/develop
{
- if (fgrp != null)
++ // <<<<<<< HEAD
+ if (featureGroups.containsKey(group))
++ // =======
++ // if (fgrp != null)
++ // >>>>>>> refs/heads/develop
{
- Boolean groupDisplayed = featureGroups.get(fgrp);
- if (groupDisplayed == null)
- {
- groupDisplayed = Boolean.valueOf(newMadeVisible);
- featureGroups.put(fgrp, groupDisplayed);
- }
- if (!groupDisplayed.booleanValue())
- {
- index++;
- continue;
- }
+ groupDisplayed = featureGroups.get(group);
}
- if (!(features[index].begin == 0 && features[index].end == 0))
+ else
{
- // If beginning and end are 0, the feature is for the whole sequence
- // and we don't want to render the feature in the normal way
-
- if (newMadeVisible
- && !oldfeatures.contains(features[index].getType()))
- {
- // this is a new feature type on the alignment. Mark it for
- // display.
- featuresDisplayed.setVisible(features[index].getType());
- setOrder(features[index].getType(), 0);
- }
+ groupDisplayed = newMadeVisible;
+ featureGroups.put(group, groupDisplayed);
}
}
- if (!allfeatures.contains(features[index].getType()))
+ if (groupDisplayed)
{
- allfeatures.add(features[index].getType());
- }
- if (!Float.isNaN(features[index].score))
- {
- int nonpos = features[index].getBegin() >= 1 ? 0 : 1;
- float[][] mm = minmax.get(features[index].getType());
- if (mm == null)
- {
- mm = new float[][] { null, null };
- minmax.put(features[index].getType(), mm);
- }
- if (mm[nonpos] == null)
- {
- mm[nonpos] = new float[] { features[index].score,
- features[index].score };
-
- }
- else
+ Set<String> types = asq.getFeatures().getFeatureTypesForGroups(
+ true, group);
+ for (String type : types)
{
- if (mm[nonpos][0] > features[index].score)
- {
- mm[nonpos][0] = features[index].score;
- }
- if (mm[nonpos][1] < features[index].score)
+ if (!allfeatures.contains(type)) // or use HashSet and no test?
{
- mm[nonpos][1] = features[index].score;
+ allfeatures.add(type);
}
+ updateMinMax(asq, type, true); // todo: for all features?
}
}
- index++;
}
}
/*
- * oldGroups now consists of groups that no longer
- * have any feature in them - remove these
++ //<<<<<<< HEAD
+ * mark any new feature types as visible
*/
- for (String grp : oldGroups)
+ Collections.sort(allfeatures, String.CASE_INSENSITIVE_ORDER);
+ if (newMadeVisible)
{
- featureGroups.remove(grp);
+ for (String type : allfeatures)
+ {
+ if (!oldfeatures.contains(type))
+ {
+ featuresDisplayed.setVisible(type);
+ setOrder(type, 0);
+ }
+ }
++ // =======
++ // * oldGroups now consists of groups that no longer
++ // * have any feature in them - remove these
++ // */
++ // for (String grp : oldGroups)
++ // {
++ // featureGroups.remove(grp);
++ // >>>>>>> refs/heads/develop
}
updateRenderOrder(allfeatures);