import jalview.datamodel.SequenceI;
import jalview.datamodel.StructureViewerModel;
import jalview.datamodel.StructureViewerModel.StructureData;
+import jalview.datamodel.features.FeatureMatcher;
+import jalview.datamodel.features.FeatureMatcherI;
+import jalview.datamodel.features.FeatureMatcherSet;
+import jalview.datamodel.features.FeatureMatcherSetI;
import jalview.ext.varna.RnaModel;
import jalview.gui.StructureViewer.ViewerType;
import jalview.io.DataSourceType;
import jalview.schemabinding.version2.AnnotationColours;
import jalview.schemabinding.version2.AnnotationElement;
import jalview.schemabinding.version2.CalcIdParam;
+import jalview.schemabinding.version2.Colour;
+import jalview.schemabinding.version2.CompoundMatcher;
import jalview.schemabinding.version2.DBRef;
import jalview.schemabinding.version2.Features;
import jalview.schemabinding.version2.Group;
import jalview.schemabinding.version2.MapListTo;
import jalview.schemabinding.version2.Mapping;
import jalview.schemabinding.version2.MappingChoice;
+import jalview.schemabinding.version2.MatchCondition;
+import jalview.schemabinding.version2.MatcherSet;
import jalview.schemabinding.version2.OtherData;
import jalview.schemabinding.version2.PdbentryItem;
import jalview.schemabinding.version2.Pdbids;
import jalview.schemabinding.version2.Tree;
import jalview.schemabinding.version2.UserColours;
import jalview.schemabinding.version2.Viewport;
+import jalview.schemabinding.version2.types.ColourThreshTypeType;
+import jalview.schemabinding.version2.types.FeatureMatcherByType;
+import jalview.schemabinding.version2.types.NoValueColour;
import jalview.schemes.AnnotationColourGradient;
import jalview.schemes.ColourSchemeI;
import jalview.schemes.ColourSchemeProperty;
import jalview.schemes.UserColourScheme;
import jalview.structure.StructureSelectionManager;
import jalview.structures.models.AAStructureBindingModel;
+import jalview.util.Format;
import jalview.util.MessageManager;
import jalview.util.Platform;
import jalview.util.StringUtils;
import jalview.util.jarInputStreamProvider;
+import jalview.util.matcher.Condition;
import jalview.viewmodel.AlignmentViewport;
import jalview.viewmodel.ViewportRanges;
import jalview.viewmodel.seqfeatures.FeatureRendererSettings;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
}
}
- void clearSeqRefs()
- {
- if (_cleartables)
- {
- if (seqRefIds != null)
- {
- seqRefIds.clear();
- }
- if (seqsToIds != null)
- {
- seqsToIds.clear();
- }
- if (incompleteSeqs != null)
- {
- incompleteSeqs.clear();
- }
- // seqRefIds = null;
- // seqsToIds = null;
- }
- else
- {
- // do nothing
- warn("clearSeqRefs called when _cleartables was not set. Doing nothing.");
- // seqRefIds = new Hashtable();
- // seqsToIds = new IdentityHashMap();
- }
- }
-
void initSeqRefs()
{
if (seqsToIds == null)
}
if (sf.otherDetails != null)
{
- String key;
- Iterator<String> keys = sf.otherDetails.keySet().iterator();
- while (keys.hasNext())
+ /*
+ * save feature attributes, which may be simple strings or
+ * map valued (have sub-attributes)
+ */
+ for (Entry<String, Object> entry : sf.otherDetails.entrySet())
{
- key = keys.next();
- OtherData keyValue = new OtherData();
- keyValue.setKey(key);
- keyValue.setValue(sf.otherDetails.get(key).toString());
- features.addOtherData(keyValue);
+ String key = entry.getKey();
+ Object value = entry.getValue();
+ if (value instanceof Map<?, ?>)
+ {
+ for (Entry<String, Object> subAttribute : ((Map<String, Object>) value)
+ .entrySet())
+ {
+ OtherData otherData = new OtherData();
+ otherData.setKey(key);
+ otherData.setKey2(subAttribute.getKey());
+ otherData.setValue(subAttribute.getValue().toString());
+ features.addOtherData(otherData);
+ }
+ }
+ else
+ {
+ OtherData otherData = new OtherData();
+ otherData.setKey(key);
+ otherData.setValue(value.toString());
+ features.addOtherData(otherData);
+ }
}
}
// SAVE TREES
// /////////////////////////////////
- if (!storeDS && av.currentTree != null)
+ if (!storeDS && av.getCurrentTree() != null)
{
// FIND ANY ASSOCIATED TREES
// NOT IMPLEMENTED FOR HEADLESS STATE AT PRESENT
{
Tree tree = new Tree();
tree.setTitle(tp.getTitle());
- tree.setCurrentTree((av.currentTree == tp.getTree()));
+ tree.setCurrentTree((av.getCurrentTree() == tp.getTree()));
tree.setNewick(tp.getTree().print());
tree.setThreshold(tp.treeCanvas.threshold);
{
jalview.schemabinding.version2.FeatureSettings fs = new jalview.schemabinding.version2.FeatureSettings();
- String[] renderOrder = ap.getSeqPanel().seqCanvas
- .getFeatureRenderer().getRenderOrder()
- .toArray(new String[0]);
+ FeatureRenderer fr = ap.getSeqPanel().seqCanvas
+ .getFeatureRenderer();
+ String[] renderOrder = fr.getRenderOrder().toArray(new String[0]);
Vector<String> settingsAdded = new Vector<>();
if (renderOrder != null)
{
for (String featureType : renderOrder)
{
- FeatureColourI fcol = ap.getSeqPanel().seqCanvas
- .getFeatureRenderer().getFeatureStyle(featureType);
Setting setting = new Setting();
setting.setType(featureType);
+
+ /*
+ * save any filter for the feature type
+ */
+ FeatureMatcherSetI filter = fr.getFeatureFilter(featureType);
+ if (filter != null) {
+ Iterator<FeatureMatcherI> filters = filter.getMatchers().iterator();
+ FeatureMatcherI firstFilter = filters.next();
+ setting.setMatcherSet(Jalview2XML.marshalFilter(
+ firstFilter, filters, filter.isAnded()));
+ }
+
+ /*
+ * save colour scheme for the feature type
+ */
+ FeatureColourI fcol = fr.getFeatureStyle(featureType);
if (!fcol.isSimpleColour())
{
setting.setColour(fcol.getMaxColour().getRGB());
setting.setMin(fcol.getMin());
setting.setMax(fcol.getMax());
setting.setColourByLabel(fcol.isColourByLabel());
+ if (fcol.isColourByAttribute())
+ {
+ setting.setAttributeName(fcol.getAttributeName());
+ }
setting.setAutoScale(fcol.isAutoScaled());
setting.setThreshold(fcol.getThreshold());
+ Color noColour = fcol.getNoColour();
+ if (noColour == null)
+ {
+ setting.setNoValueColour(NoValueColour.NONE);
+ }
+ else if (noColour.equals(fcol.getMaxColour()))
+ {
+ setting.setNoValueColour(NoValueColour.MAX);
+ }
+ else
+ {
+ setting.setNoValueColour(NoValueColour.MIN);
+ }
// -1 = No threshold, 0 = Below, 1 = Above
setting.setThreshstate(fcol.isAboveThreshold() ? 1
: (fcol.isBelowThreshold() ? 0 : -1));
setting.setDisplay(
av.getFeaturesDisplayed().isVisible(featureType));
- float rorder = ap.getSeqPanel().seqCanvas.getFeatureRenderer()
+ float rorder = fr
.getOrder(featureType);
if (rorder > -1)
{
}
// is groups actually supposed to be a map here ?
- Iterator<String> en = ap.getSeqPanel().seqCanvas
- .getFeatureRenderer().getFeatureGroups().iterator();
+ Iterator<String> en = fr.getFeatureGroups().iterator();
Vector<String> groupsAdded = new Vector<>();
while (en.hasNext())
{
}
Group g = new Group();
g.setName(grp);
- g.setDisplay(((Boolean) ap.getSeqPanel().seqCanvas
- .getFeatureRenderer().checkGroupVisibility(grp, false))
+ g.setDisplay(((Boolean) fr.checkGroupVisibility(grp, false))
.booleanValue());
fs.addGroup(g);
groupsAdded.addElement(grp);
jarInputStreamProvider jprovider = createjarInputStreamProvider(file);
af = loadJalviewAlign(jprovider);
+ af.setMenusForViewport();
} catch (MalformedURLException e)
{
features[f].getEnd(), features[f].getScore(),
features[f].getFeatureGroup());
sf.setStatus(features[f].getStatus());
+
+ /*
+ * load any feature attributes - include map-valued attributes
+ */
+ Map<String, Map<String, String>> mapAttributes = new HashMap<>();
for (int od = 0; od < features[f].getOtherDataCount(); od++)
{
OtherData keyValue = features[f].getOtherData(od);
- if (keyValue.getKey().startsWith("LINK"))
+ String attributeName = keyValue.getKey();
+ String attributeValue = keyValue.getValue();
+ if (attributeName.startsWith("LINK"))
{
- sf.addLink(keyValue.getValue());
+ sf.addLink(attributeValue);
}
else
{
- sf.setValue(keyValue.getKey(), keyValue.getValue());
+ String subAttribute = keyValue.getKey2();
+ if (subAttribute == null)
+ {
+ // simple string-valued attribute
+ sf.setValue(attributeName, attributeValue);
+ }
+ else
+ {
+ // attribute 'key' has sub-attribute 'key2'
+ if (!mapAttributes.containsKey(attributeName))
+ {
+ mapAttributes.put(attributeName, new HashMap<>());
+ }
+ mapAttributes.get(attributeName).put(subAttribute,
+ attributeValue);
+ }
}
-
}
+ for (Entry<String, Map<String, String>> mapAttribute : mapAttributes
+ .entrySet())
+ {
+ sf.setValue(mapAttribute.getKey(), mapAttribute.getValue());
+ }
+
// adds feature to datasequence's feature set (since Jalview 2.10)
al.getSequenceAt(i).addSequenceFeature(sf);
}
StructureData filedat = oldFiles.get(id);
String pdbFile = filedat.getFilePath();
SequenceI[] seq = filedat.getSeqList().toArray(new SequenceI[0]);
- binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE);
+ binding.getSsm().setMapping(seq, null, pdbFile, DataSourceType.FILE,
+ null);
binding.addSequenceForStructFile(pdbFile, seq);
}
// and add the AlignmentPanel's reference to the view panel
af.viewport.setShowGroupConservation(false);
}
- // recover featre settings
+ // recover feature settings
if (jms.getFeatureSettings() != null)
{
+ FeatureRenderer fr = af.alignPanel.getSeqPanel().seqCanvas
+ .getFeatureRenderer();
FeaturesDisplayed fdi;
af.viewport.setFeaturesDisplayed(fdi = new FeaturesDisplayed());
String[] renderOrder = new String[jms.getFeatureSettings()
.getSettingCount(); fs++)
{
Setting setting = jms.getFeatureSettings().getSetting(fs);
+ String featureType = setting.getType();
+
+ /*
+ * restore feature filters (if any)
+ */
+ MatcherSet filters = setting.getMatcherSet();
+ if (filters != null)
+ {
+ FeatureMatcherSetI filter = Jalview2XML
+ .unmarshalFilter(featureType, filters);
+ if (!filter.isEmpty())
+ {
+ fr.setFeatureFilter(featureType, filter);
+ }
+ }
+
+ /*
+ * restore feature colour scheme
+ */
+ Color maxColour = new Color(setting.getColour());
if (setting.hasMincolour())
{
- FeatureColourI gc = setting.hasMin()
- ? new FeatureColour(new Color(setting.getMincolour()),
- new Color(setting.getColour()), setting.getMin(),
- setting.getMax())
- : new FeatureColour(new Color(setting.getMincolour()),
- new Color(setting.getColour()), 0, 1);
+ /*
+ * minColour is always set unless a simple colour
+ * (including for colour by label though it doesn't use it)
+ */
+ Color minColour = new Color(setting.getMincolour());
+ Color noValueColour = minColour;
+ NoValueColour noColour = setting.getNoValueColour();
+ if (noColour == NoValueColour.NONE)
+ {
+ noValueColour = null;
+ }
+ else if (noColour == NoValueColour.MAX)
+ {
+ noValueColour = maxColour;
+ }
+ float min = setting.hasMin() ? setting.getMin() : 0f;
+ float max = setting.hasMin() ? setting.getMax() : 1f;
+ FeatureColourI gc = new FeatureColour(minColour, maxColour,
+ noValueColour, min, max);
+ if (setting.getAttributeNameCount() > 0)
+ {
+ gc.setAttributeName(setting.getAttributeName());
+ }
if (setting.hasThreshold())
{
gc.setThreshold(setting.getThreshold());
gc.setColourByLabel(setting.getColourByLabel());
}
// and put in the feature colour table.
- featureColours.put(setting.getType(), gc);
+ featureColours.put(featureType, gc);
}
else
{
- featureColours.put(setting.getType(),
- new FeatureColour(new Color(setting.getColour())));
+ featureColours.put(featureType,
+ new FeatureColour(maxColour));
}
- renderOrder[fs] = setting.getType();
+ renderOrder[fs] = featureType;
if (setting.hasOrder())
{
- featureOrder.put(setting.getType(), setting.getOrder());
+ featureOrder.put(featureType, setting.getOrder());
}
else
{
- featureOrder.put(setting.getType(), new Float(
+ featureOrder.put(featureType, new Float(
fs / jms.getFeatureSettings().getSettingCount()));
}
if (setting.getDisplay())
{
- fdi.setVisible(setting.getType());
+ fdi.setVisible(featureType);
}
}
Map<String, Boolean> fgtable = new Hashtable<>();
// jms.getFeatureSettings().getTransparency() : 0.0, featureOrder);
FeatureRendererSettings frs = new FeatureRendererSettings(renderOrder,
fgtable, featureColours, 1.0f, featureOrder);
- af.alignPanel.getSeqPanel().seqCanvas.getFeatureRenderer()
- .transferSettings(frs);
-
+ fr.transferSettings(frs);
}
if (view.getHiddenColumnsCount() > 0)
}
- public jalview.gui.AlignmentPanel copyAlignPanel(AlignmentPanel ap,
- boolean keepSeqRefs)
+ /**
+ * Provides a 'copy' of an alignment view (on action New View) by 'saving' the
+ * view as XML (but not to file), and then reloading it
+ *
+ * @param ap
+ * @return
+ */
+ public AlignmentPanel copyAlignPanel(AlignmentPanel ap)
{
initSeqRefs();
JalviewModel jm = saveState(ap, null, null, null);
- if (!keepSeqRefs)
- {
- clearSeqRefs();
- jm.getJalviewModelSequence().getViewport(0).setSequenceSetId(null);
- }
- else
- {
- uniqueSetSuffix = "";
- jm.getJalviewModelSequence().getViewport(0).setId(null); // we don't
- // overwrite the
- // view we just
- // copied
- }
+ uniqueSetSuffix = "";
+ jm.getJalviewModelSequence().getViewport(0).setId(null);
+ // we don't overwrite the view we just copied
+
if (this.frefedSequence == null)
{
- frefedSequence = new Vector();
+ frefedSequence = new Vector<>();
}
viewportsAdded.clear();
return af.alignPanel;
}
- /**
- * flag indicating if hashtables should be cleared on finalization TODO this
- * flag may not be necessary
- */
- private final boolean _cleartables = true;
-
private Hashtable jvids2vobj;
- /*
- * (non-Javadoc)
- *
- * @see java.lang.Object#finalize()
- */
- @Override
- protected void finalize() throws Throwable
- {
- // really make sure we have no buried refs left.
- if (_cleartables)
- {
- clearSeqRefs();
- }
- this.seqRefIds = null;
- this.seqsToIds = null;
- super.finalize();
- }
-
private void warn(String msg)
{
warn(msg, null);
{
return counter++;
}
+
+ /**
+ * Populates an XML model of the feature colour scheme for one feature type
+ *
+ * @param featureType
+ * @param fcol
+ * @return
+ */
+ protected static jalview.schemabinding.version2.Colour marshalColour(
+ String featureType, FeatureColourI fcol)
+ {
+ jalview.schemabinding.version2.Colour col = new jalview.schemabinding.version2.Colour();
+ if (fcol.isSimpleColour())
+ {
+ col.setRGB(Format.getHexString(fcol.getColour()));
+ }
+ else
+ {
+ col.setRGB(Format.getHexString(fcol.getMaxColour()));
+ col.setMin(fcol.getMin());
+ col.setMax(fcol.getMax());
+ col.setMinRGB(jalview.util.Format.getHexString(fcol.getMinColour()));
+ col.setAutoScale(fcol.isAutoScaled());
+ col.setThreshold(fcol.getThreshold());
+ col.setColourByLabel(fcol.isColourByLabel());
+ col.setThreshType(fcol.isAboveThreshold() ? ColourThreshTypeType.ABOVE
+ : (fcol.isBelowThreshold() ? ColourThreshTypeType.BELOW
+ : ColourThreshTypeType.NONE));
+ if (fcol.isColourByAttribute())
+ {
+ col.setAttributeName(fcol.getAttributeName());
+ }
+ Color noColour = fcol.getNoColour();
+ if (noColour == null)
+ {
+ col.setNoValueColour(NoValueColour.NONE);
+ }
+ else if (noColour == fcol.getMaxColour())
+ {
+ col.setNoValueColour(NoValueColour.MAX);
+ }
+ else
+ {
+ col.setNoValueColour(NoValueColour.MIN);
+ }
+ }
+ col.setName(featureType);
+ return col;
+ }
+
+ /**
+ * Populates an XML model of the feature filter(s) for one feature type
+ *
+ * @param firstMatcher
+ * the first (or only) match condition)
+ * @param filter
+ * remaining match conditions (if any)
+ * @param and
+ * if true, conditions are and-ed, else or-ed
+ */
+ protected static MatcherSet marshalFilter(FeatureMatcherI firstMatcher,
+ Iterator<FeatureMatcherI> filters, boolean and)
+ {
+ MatcherSet result = new MatcherSet();
+
+ if (filters.hasNext())
+ {
+ /*
+ * compound matcher
+ */
+ CompoundMatcher compound = new CompoundMatcher();
+ compound.setAnd(and);
+ MatcherSet matcher1 = marshalFilter(firstMatcher,
+ Collections.emptyIterator(), and);
+ compound.addMatcherSet(matcher1);
+ FeatureMatcherI nextMatcher = filters.next();
+ MatcherSet matcher2 = marshalFilter(nextMatcher, filters, and);
+ compound.addMatcherSet(matcher2);
+ result.setCompoundMatcher(compound);
+ }
+ else
+ {
+ /*
+ * single condition matcher
+ */
+ MatchCondition matcherModel = new MatchCondition();
+ matcherModel.setCondition(
+ firstMatcher.getMatcher().getCondition().getStableName());
+ matcherModel.setValue(firstMatcher.getMatcher().getPattern());
+ if (firstMatcher.isByAttribute())
+ {
+ matcherModel.setBy(FeatureMatcherByType.BYATTRIBUTE);
+ matcherModel.setAttributeName(firstMatcher.getAttribute());
+ }
+ else if (firstMatcher.isByLabel())
+ {
+ matcherModel.setBy(FeatureMatcherByType.BYLABEL);
+ }
+ else if (firstMatcher.isByScore())
+ {
+ matcherModel.setBy(FeatureMatcherByType.BYSCORE);
+ }
+ result.setMatchCondition(matcherModel);
+ }
+
+ return result;
+ }
+
+ /**
+ * Loads one XML model of a feature filter to a Jalview object
+ *
+ * @param featureType
+ * @param matcherSetModel
+ * @return
+ */
+ protected static FeatureMatcherSetI unmarshalFilter(
+ String featureType, MatcherSet matcherSetModel)
+ {
+ FeatureMatcherSetI result = new FeatureMatcherSet();
+ try
+ {
+ unmarshalFilterConditions(result, matcherSetModel, true);
+ } catch (IllegalStateException e)
+ {
+ // mixing AND and OR conditions perhaps
+ System.err.println(
+ String.format("Error reading filter conditions for '%s': %s",
+ featureType, e.getMessage()));
+ // return as much as was parsed up to the error
+ }
+
+ return result;
+ }
+
+ /**
+ * Adds feature match conditions to matcherSet as unmarshalled from XML
+ * (possibly recursively for compound conditions)
+ *
+ * @param matcherSet
+ * @param matcherSetModel
+ * @param and
+ * if true, multiple conditions are AND-ed, else they are OR-ed
+ * @throws IllegalStateException
+ * if AND and OR conditions are mixed
+ */
+ protected static void unmarshalFilterConditions(
+ FeatureMatcherSetI matcherSet, MatcherSet matcherSetModel,
+ boolean and)
+ {
+ MatchCondition mc = matcherSetModel.getMatchCondition();
+ if (mc != null)
+ {
+ /*
+ * single condition
+ */
+ FeatureMatcherByType filterBy = mc.getBy();
+ Condition cond = Condition.fromString(mc.getCondition());
+ String pattern = mc.getValue();
+ FeatureMatcherI matchCondition = null;
+ if (filterBy == FeatureMatcherByType.BYLABEL)
+ {
+ matchCondition = FeatureMatcher.byLabel(cond, pattern);
+ }
+ else if (filterBy == FeatureMatcherByType.BYSCORE)
+ {
+ matchCondition = FeatureMatcher.byScore(cond, pattern);
+
+ }
+ else if (filterBy == FeatureMatcherByType.BYATTRIBUTE)
+ {
+ String[] attNames = mc.getAttributeName();
+ matchCondition = FeatureMatcher.byAttribute(cond, pattern,
+ attNames);
+ }
+
+ /*
+ * note this throws IllegalStateException if AND-ing to a
+ * previously OR-ed compound condition, or vice versa
+ */
+ if (and)
+ {
+ matcherSet.and(matchCondition);
+ }
+ else
+ {
+ matcherSet.or(matchCondition);
+ }
+ }
+ else
+ {
+ /*
+ * compound condition
+ */
+ MatcherSet[] matchers = matcherSetModel.getCompoundMatcher()
+ .getMatcherSet();
+ boolean anded = matcherSetModel.getCompoundMatcher().getAnd();
+ if (matchers.length == 2)
+ {
+ unmarshalFilterConditions(matcherSet, matchers[0], anded);
+ unmarshalFilterConditions(matcherSet, matchers[1], anded);
+ }
+ else
+ {
+ System.err.println("Malformed compound filter condition");
+ }
+ }
+ }
+
+ /**
+ * Loads one XML model of a feature colour to a Jalview object
+ *
+ * @param colourModel
+ * @return
+ */
+ protected static FeatureColourI unmarshalColour(
+ jalview.schemabinding.version2.Colour colourModel)
+ {
+ FeatureColourI colour = null;
+
+ if (colourModel.hasMax())
+ {
+ Color mincol = null;
+ Color maxcol = null;
+ Color noValueColour = null;
+
+ try
+ {
+ mincol = new Color(Integer.parseInt(colourModel.getMinRGB(), 16));
+ maxcol = new Color(Integer.parseInt(colourModel.getRGB(), 16));
+ } catch (Exception e)
+ {
+ Cache.log.warn("Couldn't parse out graduated feature color.", e);
+ }
+
+ NoValueColour noCol = colourModel.getNoValueColour();
+ if (noCol == NoValueColour.MIN)
+ {
+ noValueColour = mincol;
+ }
+ else if (noCol == NoValueColour.MAX)
+ {
+ noValueColour = maxcol;
+ }
+
+ colour = new FeatureColour(mincol, maxcol, noValueColour,
+ colourModel.getMin(),
+ colourModel.getMax());
+ String[] attributes = colourModel.getAttributeName();
+ if (attributes != null && attributes.length > 0)
+ {
+ colour.setAttributeName(attributes);
+ }
+ if (colourModel.hasAutoScale())
+ {
+ colour.setAutoScaled(colourModel.getAutoScale());
+ }
+ if (colourModel.hasColourByLabel())
+ {
+ colour.setColourByLabel(colourModel.getColourByLabel());
+ }
+ if (colourModel.hasThreshold())
+ {
+ colour.setThreshold(colourModel.getThreshold());
+ }
+ ColourThreshTypeType ttyp = colourModel.getThreshType();
+ if (ttyp != null)
+ {
+ if (ttyp == ColourThreshTypeType.ABOVE)
+ {
+ colour.setAboveThreshold(true);
+ }
+ else if (ttyp == ColourThreshTypeType.BELOW)
+ {
+ colour.setBelowThreshold(true);
+ }
+ }
+ }
+ else
+ {
+ Color color = new Color(Integer.parseInt(colourModel.getRGB(), 16));
+ colour = new FeatureColour(color);
+ }
+
+ return colour;
+ }
}