import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
this.structureManager = structureManager;
chimera = null;
chimeraListenerThread = null;
- currentModelsMap = new HashMap<Integer, ChimeraModel>();
+ currentModelsMap = new HashMap<>();
}
public List<ChimeraModel> getChimeraModels(String modelName,
ModelType modelType)
{
- List<ChimeraModel> models = new ArrayList<ChimeraModel>();
+ List<ChimeraModel> models = new ArrayList<>();
for (ChimeraModel model : currentModelsMap.values())
{
if (modelName.equals(model.getModelName())
public Map<String, List<ChimeraModel>> getChimeraModelsMap()
{
- Map<String, List<ChimeraModel>> models = new HashMap<String, List<ChimeraModel>>();
+ Map<String, List<ChimeraModel>> models = new HashMap<>();
for (ChimeraModel model : currentModelsMap.values())
{
String modelName = model.getModelName();
public Map<Integer, ChimeraModel> getSelectedModels()
{
- Map<Integer, ChimeraModel> selectedModelsMap = new HashMap<Integer, ChimeraModel>();
+ Map<Integer, ChimeraModel> selectedModelsMap = new HashMap<>();
List<String> chimeraReply = sendChimeraCommand(
"list selection level molecule", true);
if (chimeraReply != null)
*/
public List<String> getSelectedResidueSpecs()
{
- List<String> selectedResidues = new ArrayList<String>();
+ List<String> selectedResidues = new ArrayList<>();
List<String> chimeraReply = sendChimeraCommand(
"list selection level residue", true);
if (chimeraReply != null)
// TODO: [Optional] Handle smiles names in a better way in Chimera?
public List<ChimeraModel> getModelList()
{
- List<ChimeraModel> modelList = new ArrayList<ChimeraModel>();
+ List<ChimeraModel> modelList = new ArrayList<>();
List<String> list = sendChimeraCommand("list models type molecule",
true);
if (list != null)
*/
public List<String> getPresets()
{
- ArrayList<String> presetList = new ArrayList<String>();
+ ArrayList<String> presetList = new ArrayList<>();
List<String> output = sendChimeraCommand("preset list", true);
if (output != null)
{
// iterate over possible paths for starting Chimera
for (String chimeraPath : chimeraPaths)
{
- File path = new File(chimeraPath);
- // uncomment the next line to simulate Chimera not installed
- // path = new File(chimeraPath + "x");
- if (!path.canExecute())
- {
- error += "File '" + path + "' does not exist.\n";
- continue;
- }
try
{
- List<String> args = new ArrayList<String>();
+ // ensure symbolic links are resolved
+ chimeraPath = Paths.get(chimeraPath).toRealPath().toString();
+ File path = new File(chimeraPath);
+ // uncomment the next line to simulate Chimera not installed
+ // path = new File(chimeraPath + "x");
+ if (!path.canExecute())
+ {
+ error += "File '" + path + "' does not exist.\n";
+ continue;
+ }
+ List<String> args = new ArrayList<>();
args.add(chimeraPath);
// shows Chimera output window but suppresses REST responses:
// args.add("--debug");
break;
} catch (Exception e)
{
- // Chimera could not be started
+ // Chimera could not be started using this path
error += e.getMessage();
}
}
public List<String> getAttrList()
{
- List<String> attributes = new ArrayList<String>();
+ List<String> attributes = new ArrayList<>();
final List<String> reply = sendChimeraCommand("list resattr", true);
if (reply != null)
{
public Map<ChimeraResidue, Object> getAttrValues(String aCommand,
ChimeraModel model)
{
- Map<ChimeraResidue, Object> values = new HashMap<ChimeraResidue, Object>();
+ Map<ChimeraResidue, Object> values = new HashMap<>();
final List<String> reply = sendChimeraCommand("list residue spec "
+ model.toSpec() + " attribute " + aCommand, true);
if (reply != null)
protected List<String> sendRestCommand(String command)
{
String restUrl = "http://127.0.0.1:" + this.chimeraRestPort + "/run";
- List<NameValuePair> commands = new ArrayList<NameValuePair>(1);
+ List<NameValuePair> commands = new ArrayList<>(1);
commands.add(new BasicNameValuePair("command", command));
- List<String> reply = new ArrayList<String>();
+ List<String> reply = new ArrayList<>();
BufferedReader response = null;
try
{
Datatype type;
/**
- * Note one instance of this attribute, recording unique, non-null names,
- * and the min/max of any numerical values
+ * Note one instance of this attribute, recording unique, non-null
+ * descriptions, and the min/max of any numerical values
*
* @param desc
* @param value
if (value != null)
{
- try
- {
- float f = Float.valueOf(value);
- min = hasValue ? Float.min(min, f) : f;
- max = hasValue ? Float.max(max, f) : f;
- hasValue = true;
- type = (type == null || type == Datatype.Number) ? Datatype.Number
- : Datatype.Mixed;
- } catch (NumberFormatException e)
+ value = value.trim();
+
+ /*
+ * Parse numeric value unless we have previously
+ * seen text data for this attribute type
+ */
+ if (type == null || type == Datatype.Number)
{
- // not a number, ignore for min-max purposes
- type = (type == null || type == Datatype.Character)
- ? Datatype.Character
- : Datatype.Mixed;
+ try
+ {
+ float f = Float.valueOf(value);
+ min = hasValue ? Float.min(min, f) : f;
+ max = hasValue ? Float.max(max, f) : f;
+ hasValue = true;
+ type = (type == null || type == Datatype.Number)
+ ? Datatype.Number
+ : Datatype.Mixed;
+ } catch (NumberFormatException e)
+ {
+ /*
+ * non-numeric data: treat attribute as Character (or Mixed)
+ */
+ type = (type == null || type == Datatype.Character)
+ ? Datatype.Character
+ : Datatype.Mixed;
+ min = 0f;
+ max = 0f;
+ hasValue = false;
+ }
}
}
}
/**
* Answers the [min, max] value range of the given attribute for the given
- * feature type, if known, else null. Attributes which only have text values
- * would normally return null, however text values which happen to be numeric
- * could result in a 'min-max' range.
+ * feature type, if known, else null. Attributes with a mixture of text and
+ * numeric values are considered text (do not return a min-max range).
*
* @param featureType
* @param attName
* @see https://github.com/Ensembl/ensembl-rest/wiki/Change-log
* @see http://rest.ensembl.org/info/rest?content-type=application/json
*/
- private static final String LATEST_ENSEMBLGENOMES_REST_VERSION = "6.0";
+ private static final String LATEST_ENSEMBLGENOMES_REST_VERSION = "6.3";
- private static final String LATEST_ENSEMBL_REST_VERSION = "6.1";
+ private static final String LATEST_ENSEMBL_REST_VERSION = "6.3";
private static final String REST_CHANGE_LOG = "https://github.com/Ensembl/ensembl-rest/wiki/Change-log";
private static Map<String, EnsemblData> domainData;
- // @see https://github.com/Ensembl/ensembl-rest/wiki/Output-formats
- private static final String PING_URL = "http://rest.ensembl.org/info/ping.json";
-
private final static long AVAILABILITY_RETEST_INTERVAL = 10000L; // 10 seconds
private final static long VERSION_RETEST_INTERVAL = 1000L * 3600; // 1 hr
{
textarea.setDocument(textarea.getEditorKit().createDefaultDocument());
textarea.setText(text);
+ textarea.setCaretPosition(0);
}
@Override
* if a numeric condition is selected, show the value range
* as a tooltip on the value input field
*/
- setPatternTooltip(filterBy, selectedCondition, patternField);
+ setNumericHints(filterBy, selectedCondition, patternField);
/*
* add remove button if filter is populated (non-empty pattern)
}
/**
- * If a numeric comparison condition is selected, retrieve the min-max range for
- * the value (score or attribute), and set it as a tooltip on the value file
+ * If a numeric comparison condition is selected, retrieves the min-max range
+ * for the value (score or attribute), and sets it as a tooltip on the value
+ * field. If the field is currently empty, then pre-populates it with
+ * <ul>
+ * <li>the minimum value, if condition is > or >=</li>
+ * <li>the maximum value, if condition is < or <=</li>
+ * </ul>
*
* @param attName
* @param selectedCondition
* @param patternField
*/
- private void setPatternTooltip(String attName,
+ private void setNumericHints(String attName,
Condition selectedCondition, JTextField patternField)
{
patternField.setToolTipText("");
float[] minMax = getMinMax(attName);
if (minMax != null)
{
- String tip = String.format("(%s - %s)",
- DECFMT_2_2.format(minMax[0]), DECFMT_2_2.format(minMax[1]));
+ String minFormatted = DECFMT_2_2.format(minMax[0]);
+ String maxFormatted = DECFMT_2_2.format(minMax[1]);
+ String tip = String.format("(%s - %s)", minFormatted, maxFormatted);
patternField.setToolTipText(tip);
+ if (patternField.getText().isEmpty())
+ {
+ if (selectedCondition == Condition.GE
+ || selectedCondition == Condition.GT)
+ {
+ patternField.setText(minFormatted);
+ }
+ else
+ {
+ if (selectedCondition == Condition.LE
+ || selectedCondition == Condition.LT)
+ {
+ patternField.setText(maxFormatted);
+ }
+ }
+ }
}
}
}
ItemListener listener = condCombo.getItemListeners()[0];
condCombo.removeItemListener(listener);
boolean condIsValid = false;
+
condCombo.removeAllItems();
for (Condition c : Condition.values())
{
- if ((c.isNumeric() && type != Datatype.Character)
+ if ((c.isNumeric() && type == Datatype.Number)
|| (!c.isNumeric() && type != Datatype.Number))
{
condCombo.addItem(c);
condCombo.setSelectedIndex(0);
}
- condCombo.addItemListener(listener);
-
/*
* clear pattern if it is now invalid for condition
*/
patternField.setText("");
}
}
+
+ /*
+ * restore the listener
+ */
+ condCombo.addItemListener(listener);
}
/**
Condition cond = (Condition) condCombo.getSelectedItem();
String pattern = valueField.getText().trim();
- setPatternTooltip(attName, cond, valueField);
+ setNumericHints(attName, cond, valueField);
if (pattern.length() == 0 && cond.needsAPattern())
{
* load any HMMER profile
*/
String hmmJarFile = jseqs[i].getHmmerProfile();
- if (hmmJarFile != null)
+ if (hmmJarFile != null && jprovider != null)
{
loadHmmerProfile(jprovider, hmmJarFile, alignmentSeq);
}
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.List;
* @param cmd
* command short name e.g. hmmalign
* @return
+ * @throws IOException
*/
- protected String getCommandPath(String cmd)
+ protected String getCommandPath(String cmd) throws IOException
{
String binariesFolder = Cache.getProperty(Preferences.HMMER_PATH);
+ // ensure any symlink to the directory is resolved:
+ binariesFolder = Paths.get(binariesFolder).toRealPath().toString();
File file = FileUtils.getExecutable(cmd, binariesFolder);
if (file == null && af != null)
{
package jalview.io;
import jalview.api.FeatureColourI;
+import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.DBRefEntry;
import jalview.datamodel.DBRefSource;
import jalview.datamodel.SequenceFeature;
sb.append("<br>").append(tmp);
maxWidth = Math.max(maxWidth, tmp.length());
}
+
SequenceI ds = sequence;
while (ds.getDatasetSequence() != null)
{
ds = ds.getDatasetSequence();
}
+ /*
+ * add any annotation scores
+ */
+ AlignmentAnnotation[] anns = ds.getAnnotation();
+ for (int i = 0; anns != null && i < anns.length; i++)
+ {
+ AlignmentAnnotation aa = anns[i];
+ if (aa != null && aa.hasScore() && aa.sequenceRef != null)
+ {
+ sb.append("<br>").append(aa.label).append(": ")
+ .append(aa.getScore());
+ }
+ }
+
if (showDbRefs)
{
maxWidth = Math.max(maxWidth, appendDbRefs(sb, ds, summary));
fromHighest = Integer.MIN_VALUE;
for (int[] range : fromRange)
{
+ if (range.length != 2)
+ {
+ // throw new IllegalArgumentException(range);
+ System.err.println(
+ "Invalid format for fromRange " + Arrays.toString(range)
+ + " may cause errors");
+ }
fromLowest = Math.min(fromLowest, Math.min(range[0], range[1]));
fromHighest = Math.max(fromHighest, Math.max(range[0], range[1]));
}
toHighest = Integer.MIN_VALUE;
for (int[] range : toRange)
{
+ if (range.length != 2)
+ {
+ // throw new IllegalArgumentException(range);
+ System.err.println("Invalid format for toRange "
+ + Arrays.toString(range)
+ + " may cause errors");
+ }
toLowest = Math.min(toLowest, Math.min(range[0], range[1]));
toHighest = Math.max(toHighest, Math.max(range[0], range[1]));
}
for (int[] range : getToRanges())
{
int[] transferred = map.locateInTo(range[0], range[1]);
- if (transferred == null)
+ if (transferred == null || transferred.length % 2 != 0)
{
return null;
}
- toRanges.add(transferred);
+
+ /*
+ * convert [start1, end1, start2, end2, ...]
+ * to [[start1, end1], [start2, end2], ...]
+ */
+ for (int i = 0; i < transferred.length;)
+ {
+ toRanges.add(new int[] { transferred[i], transferred[i + 1] });
+ i += 2;
+ }
}
return new MapList(getFromRanges(), toRanges, outFromRatio, outToRatio);
assertEquals(2, toMap.getFromRanges().get(0).length);
assertEquals(1, toMap.getFromRanges().get(0)[0]);
assertEquals(12, toMap.getFromRanges().get(0)[1]);
- assertEquals(1, toMap.getToRanges().size());
- assertEquals(4, toMap.getToRanges().get(0).length);
+ assertEquals(2, toMap.getToRanges().size());
+ assertEquals(2, toMap.getToRanges().get(0).length);
assertEquals(158, toMap.getToRanges().get(0)[0]);
assertEquals(164, toMap.getToRanges().get(0)[1]);
- assertEquals(210, toMap.getToRanges().get(0)[2]);
- assertEquals(214, toMap.getToRanges().get(0)[3]);
+ assertEquals(210, toMap.getToRanges().get(1)[0]);
+ assertEquals(214, toMap.getToRanges().get(1)[1]);
// or summarised as (but toString might change in future):
- assertEquals("[ [1, 12] ] 1:1 to [ [158, 164, 210, 214] ]",
+ assertEquals("[ [1, 12] ] 1:1 to [ [158, 164] [210, 214] ]",
toMap.toString());
/*
assertEquals("GRCh38", toLoci.getAssemblyId());
assertEquals("7", toLoci.getChromosomeId());
toMap = toLoci.getMap();
- assertEquals("[ [1, 12] ] 1:1 to [ [158, 164, 210, 214] ]",
+ assertEquals("[ [1, 12] ] 1:1 to [ [158, 164] [210, 214] ]",
toMap.toString());
}
assertNull(fa.getMinMax("Pfam", "kd"));
sf.setValue("domain", "xyz");
assertNull(fa.getMinMax("Pfam", "kd"));
- sf.setValue("kd", "some text");
- assertNull(fa.getMinMax("Pfam", "kd"));
sf.setValue("kd", "1.3");
assertEquals(fa.getMinMax("Pfam", "kd"), new float[] { 1.3f, 1.3f });
sf.setValue("kd", "-2.6");
assertEquals(fa.getMinMax("Pfam", "kd"), new float[] { -2.6f, 1.3f });
+ // setting 'mixed' character and numeric values wipes the min/max value
+ sf.setValue("kd", "some text");
+ assertNull(fa.getMinMax("Pfam", "kd"));
+
Map<String, String> csq = new HashMap<>();
csq.put("AF", "-3");
sf.setValue("CSQ", csq);
*/
MapList ml1 = new MapList(new int[] { 3, 4, 8, 12 }, new int[] { 5, 8,
11, 13 }, 1, 1);
+ assertEquals("{[3, 4], [8, 12]}", prettyPrint(ml1.getFromRanges()));
+ assertEquals("{[5, 8], [11, 13]}", prettyPrint(ml1.getToRanges()));
+
MapList ml2 = new MapList(new int[] { 1, 50 }, new int[] { 40, 45, 70,
75, 90, 127 }, 1, 1);
+ assertEquals("{[1, 50]}", prettyPrint(ml2.getFromRanges()));
+ assertEquals("{[40, 45], [70, 75], [90, 127]}",
+ prettyPrint(ml2.getToRanges()));
+
MapList compound = ml1.traverse(ml2);
- assertEquals(compound.getFromRatio(), 1);
- assertEquals(compound.getToRatio(), 1);
+ assertEquals(1, compound.getFromRatio());
+ assertEquals(1, compound.getToRatio());
List<int[]> fromRanges = compound.getFromRanges();
- assertEquals(fromRanges.size(), 2);
+ assertEquals(2, fromRanges.size());
assertArrayEquals(new int[] { 3, 4 }, fromRanges.get(0));
assertArrayEquals(new int[] { 8, 12 }, fromRanges.get(1));
List<int[]> toRanges = compound.getToRanges();
- assertEquals(toRanges.size(), 2);
+ assertEquals(4, toRanges.size());
// 5-8 maps to 44-45,70-71
// 11-13 maps to 74-75,90
- assertArrayEquals(new int[] { 44, 45, 70, 71 }, toRanges.get(0));
- assertArrayEquals(new int[] { 74, 75, 90, 90 }, toRanges.get(1));
+ assertArrayEquals(new int[] { 44, 45 }, toRanges.get(0));
+ assertArrayEquals(new int[] { 70, 71 }, toRanges.get(1));
+ assertArrayEquals(new int[] { 74, 75 }, toRanges.get(2));
+ assertArrayEquals(new int[] { 90, 90 }, toRanges.get(3));
/*
* 1:1 over 1:1 backwards ('reverse strand')
new int[] { 1000, 901, 600, 201 }, 1, 1);
compound = ml1.traverse(ml2);
- assertEquals(compound.getFromRatio(), 1);
- assertEquals(compound.getToRatio(), 1);
+ assertEquals(1, compound.getFromRatio());
+ assertEquals(1, compound.getToRatio());
fromRanges = compound.getFromRanges();
- assertEquals(fromRanges.size(), 1);
+ assertEquals(1, fromRanges.size());
assertArrayEquals(new int[] { 1, 50 }, fromRanges.get(0));
toRanges = compound.getToRanges();
- assertEquals(toRanges.size(), 1);
- assertArrayEquals(new int[] { 931, 901, 600, 582 }, toRanges.get(0));
+ assertEquals(2, toRanges.size());
+ assertArrayEquals(new int[] { 931, 901 }, toRanges.get(0));
+ assertArrayEquals(new int[] { 600, 582 }, toRanges.get(1));
/*
* 1:1 plus 1:3 should result in 1:3
1, 3);
compound = ml1.traverse(ml2);
- assertEquals(compound.getFromRatio(), 1);
- assertEquals(compound.getToRatio(), 3);
+ assertEquals(1, compound.getFromRatio());
+ assertEquals(3, compound.getToRatio());
fromRanges = compound.getFromRanges();
- assertEquals(fromRanges.size(), 1);
+ assertEquals(1, fromRanges.size());
assertArrayEquals(new int[] { 1, 30 }, fromRanges.get(0));
// 11-40 maps to 31-50,91-160
toRanges = compound.getToRanges();
- assertEquals(toRanges.size(), 1);
- assertArrayEquals(new int[] { 31, 50, 91, 160 }, toRanges.get(0));
+ assertEquals(2, toRanges.size());
+ assertArrayEquals(new int[] { 31, 50 }, toRanges.get(0));
+ assertArrayEquals(new int[] { 91, 160 }, toRanges.get(1));
/*
* 3:1 plus 1:1 should result in 3:1
1, 1);
compound = ml1.traverse(ml2);
- assertEquals(compound.getFromRatio(), 3);
- assertEquals(compound.getToRatio(), 1);
+ assertEquals(3, compound.getFromRatio());
+ assertEquals(1, compound.getToRatio());
fromRanges = compound.getFromRanges();
- assertEquals(fromRanges.size(), 1);
+ assertEquals(1, fromRanges.size());
assertArrayEquals(new int[] { 1, 30 }, fromRanges.get(0));
// 11-20 maps to 11-15, 91-95
toRanges = compound.getToRanges();
- assertEquals(toRanges.size(), 1);
- assertArrayEquals(new int[] { 11, 15, 91, 95 }, toRanges.get(0));
+ assertEquals(2, toRanges.size());
+ assertArrayEquals(new int[] { 11, 15 }, toRanges.get(0));
+ assertArrayEquals(new int[] { 91, 95 }, toRanges.get(1));
/*
* 1:3 plus 3:1 should result in 1:1
3, 1);
compound = ml1.traverse(ml2);
- assertEquals(compound.getFromRatio(), 1);
- assertEquals(compound.getToRatio(), 1);
+ assertEquals(1, compound.getFromRatio());
+ assertEquals(1, compound.getToRatio());
fromRanges = compound.getFromRanges();
- assertEquals(fromRanges.size(), 1);
+ assertEquals(1, fromRanges.size());
assertArrayEquals(new int[] { 21, 40 }, fromRanges.get(0));
// 13-72 maps 3:1 to 55-70, 121-124
toRanges = compound.getToRanges();
- assertEquals(toRanges.size(), 1);
- assertArrayEquals(new int[] { 55, 70, 121, 124 }, toRanges.get(0));
+ assertEquals(2, toRanges.size());
+ assertArrayEquals(new int[] { 55, 70 }, toRanges.get(0));
+ assertArrayEquals(new int[] { 121, 124 }, toRanges.get(1));
/*
* 3:1 plus 1:3 should result in 1:1
1, 3);
compound = ml1.traverse(ml2);
- assertEquals(compound.getFromRatio(), 1);
- assertEquals(compound.getToRatio(), 1);
+ assertEquals(1, compound.getFromRatio());
+ assertEquals(1, compound.getToRatio());
fromRanges = compound.getFromRanges();
- assertEquals(fromRanges.size(), 1);
+ assertEquals(1, fromRanges.size());
assertArrayEquals(new int[] { 31, 90 }, fromRanges.get(0));
// 13-32 maps to 47-50,71-126
toRanges = compound.getToRanges();
- assertEquals(toRanges.size(), 1);
- assertArrayEquals(new int[] { 47, 50, 71, 126 }, toRanges.get(0));
+ assertEquals(2, toRanges.size());
+ assertArrayEquals(new int[] { 47, 50 }, toRanges.get(0));
+ assertArrayEquals(new int[] { 71, 126 }, toRanges.get(1));
/*
* method returns null if not all regions are mapped through