Combines patches for JAL-3806 prior to redaction of shared CDS dataset sequences with patches for JAL-3673
Conflicts:
src/jalview/datamodel/AlignedCodonFrame.java
src/jalview/util/MappingUtils.java
test/jalview/util/MappingUtilsTest.java
// Import channel_properties
channelDir = string("${jalviewDir}/${channel_properties_dir}/${propertiesChannelName}")
channelGradleProperties = string("${channelDir}/channel_gradle.properties")
+ channelPropsFile = string("${channelDir}/${resource_dir}/${channel_props}")
overrideProperties(channelGradleProperties, false)
// local build environment properties
// can be "projectDir/local.properties"
}
getdownWebsiteResourceFilenames += "${getdownAppDistDir}/${getdown_build_properties}"
+ copy {
+ from channelPropsFile
+ into getdownWebsiteDir
+ }
+ getdownWebsiteResourceFilenames += file(channelPropsFile).getName()
+
// set some getdown_txt_ properties then go through all properties looking for getdown_txt_...
def props = project.properties.sort { it.key }
if (getdownAltJavaMinVersion != null && getdownAltJavaMinVersion.length() > 0) {
from launchJvl
from getdownLauncher
from "${getdownWebsiteDir}/${getdown_build_properties}"
+ from "${getdownWebsiteDir}/${channel_props}"
if (file(getdownLauncher).getName() != getdown_launcher) {
rename(file(getdownLauncher).getName(), getdown_launcher)
}
-1.8.3-1.2.10_FJVL
+1.8.3-1.2.11_FJVL
-1.8.3-1.2.10_JVL
+1.8.3-1.2.11_JVL
<parent>
<groupId>com.threerings.getdown</groupId>
<artifactId>getdown</artifactId>
- <version>1.8.3-1.2.10_FJVL</version>
+ <version>1.8.3-1.2.11_FJVL</version>
</parent>
<artifactId>getdown-ant</artifactId>
<parent>
<groupId>com.threerings.getdown</groupId>
<artifactId>getdown</artifactId>
- <version>1.8.3-1.2.10_FJVL</version>
+ <version>1.8.3-1.2.11_FJVL</version>
</parent>
<artifactId>getdown-core</artifactId>
import jalview.bin.HiDPISetting;
import jalview.bin.MemorySetting;
-//import com.install4j.api.launcher.Variables;
+import jalview.util.LaunchUtils;
import com.threerings.getdown.util.*;
// avoid ambiguity with java.util.Base64 which we can't use as it's 1.8+
continue;
}
}
+
+ // use saved preferences if no cmdline args
+ LaunchUtils.loadChannelProps(getAppDir());
+ if (LaunchUtils.getBooleanUserPreference(MemorySetting.CUSTOMISED_SETTINGS)) {
+ if (jvmmempc == null) {
+ jvmmempc = LaunchUtils.getUserPreference(MemorySetting.MEMORY_JVMMEMPC);
+ }
+ if (jvmmemmax == null) {
+ jvmmemmax = LaunchUtils.getUserPreference(MemorySetting.MEMORY_JVMMEMMAX);
+ }
+ }
// add the memory setting from jvmmempc and jvmmemmax
long maxMemLong = -1;
/*
+
+ private static String ADJUSTMENT_MESSAGE = null;
* Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
* Copyright (C) $$Year-Rel$$ The Jalview Authors
*
* @author bsoares
*
*/
+
public class MemorySetting
{
public static final String MAX_HEAPSIZE_PERCENT_PROPERTY_NAME = "jvmmempc";
private static final long NOMEM_MAX_HEAPSIZE_GB_DEFAULT = 8;
+ public static final String NS = "MEMORY";
+
+ public static final String CUSTOMISED_SETTINGS = NS
+ + "_CUSTOMISED_SETTINGS";
+
+ public static final String MEMORY_JVMMEMPC = NS + "_"
+ + MAX_HEAPSIZE_PERCENT_PROPERTY_NAME.toUpperCase();
+
+ public static final String MEMORY_JVMMEMMAX = NS + "_"
+ + MAX_HEAPSIZE_PROPERTY_NAME.toUpperCase();
+
protected static boolean logToClassChecked = false;
+ public static String memorySuffixes = "bkmgt"; // order of the suffixes is
+ // important!
+
public static long getMemorySetting()
{
return getMemorySetting(null, null);
}
+ public static long getMemorySetting(String jvmmemmaxarg,
+ String jvmmempcarg)
+ {
+ return getMemorySetting(jvmmemmaxarg, jvmmempcarg, true, false);
+ }
+
/**
* Decide on appropriate memory setting for Jalview based on the two arguments
* values: jvmmempc - the maximum percentage of total physical memory to
* @param jvmmempcarg
* Max percentage of physical memory to use. Defaults to "90".
*
+ * @param useProps
+ * boolean to decide whether to look at System properties.
+ *
* @return The amount of memory (in bytes) to allocate to Jalview
*/
public static long getMemorySetting(String jvmmemmaxarg,
- String jvmmempcarg)
+ String jvmmempcarg, boolean useProps, boolean quiet)
{
// actual Xmx value-to-be
long maxMemLong = -1;
+ clearAdjustmentMessage();
// (absolute) jvmmaxmem setting, start with default
long memmax = MAX_HEAPSIZE_GB_DEFAULT * GIGABYTE;
- if (jvmmemmaxarg == null)
+ if (jvmmemmaxarg == null && useProps)
{
jvmmemmaxarg = System.getProperty(MAX_HEAPSIZE_PROPERTY_NAME);
}
String jvmmemmax = jvmmemmaxarg;
if (jvmmemmax != null && jvmmemmax.length() > 0)
{
- long multiplier = 1;
- switch (jvmmemmax.toLowerCase().substring(jvmmemmax.length() - 1))
- {
- case "t":
- multiplier = 1099511627776L; // 2^40
- jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
- break;
- case "g":
- multiplier = 1073741824; // 2^30
- jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
- break;
- case "m":
- multiplier = 1048576; // 2^20
- jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
- break;
- case "k":
- multiplier = 1024; // 2^10
- jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
- break;
- case "b":
- multiplier = 1; // 2^0
- jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
- break;
- default:
- break;
- }
-
// parse the arg
try
{
- memmax = Long.parseLong(jvmmemmax);
+ memmax = memoryStringToLong(jvmmemmax);
+ if (memmax == 0)
+ {
+ throw (new NumberFormatException("Not allowing 0"));
+ }
} catch (NumberFormatException e)
{
memmax = MAX_HEAPSIZE_GB_DEFAULT * GIGABYTE;
- System.out.println("MemorySetting Property '"
+ setAdjustmentMessage("MemorySetting Property '"
+ MAX_HEAPSIZE_PROPERTY_NAME + "' (" + jvmmemmaxarg
- + "') badly formatted, using default ("
- + MAX_HEAPSIZE_GB_DEFAULT + "g).");
- }
-
- // apply multiplier if not too big (i.e. bigger than a long)
- if (Long.MAX_VALUE / memmax < multiplier)
- {
- memmax = MAX_HEAPSIZE_GB_DEFAULT * GIGABYTE;
- System.out.println("MemorySetting Property '"
- + MAX_HEAPSIZE_PROPERTY_NAME + "' (" + jvmmemmaxarg
- + ") too big, using default (" + MAX_HEAPSIZE_GB_DEFAULT
- + "g).");
- }
- else
- {
- memmax = multiplier * memmax;
+ + "') badly formatted or 0, using default ("
+ + MAX_HEAPSIZE_GB_DEFAULT + "g).", quiet);
}
// check at least minimum value (this accounts for negatives too)
if (memmax < APPLICATION_MIN_MEMORY)
{
memmax = APPLICATION_MIN_MEMORY;
- System.out.println("MemorySetting Property '"
+ setAdjustmentMessage("MemorySetting Property '"
+ MAX_HEAPSIZE_PROPERTY_NAME + "' (" + jvmmemmaxarg
+ ") too small, using minimum (" + APPLICATION_MIN_MEMORY
- + ").");
+ + ").", quiet);
}
}
else
{
// no need to warn if no setting
- // System.out.println("MemorySetting Property '" + maxHeapSizeProperty
+ // adjustmentMessage("MemorySetting Property '" + maxHeapSizeProperty
// + "' not
// set.");
}
// get max percent of physical memory, starting with default
float percent = MAX_HEAPSIZE_PERCENT_DEFAULT;
- if (jvmmempcarg == null)
+ if (jvmmempcarg == null && useProps)
{
jvmmempcarg = System.getProperty(MAX_HEAPSIZE_PERCENT_PROPERTY_NAME);
}
{
if (jvmmempc != null)
{
- float trypercent = Float.parseFloat(jvmmempc);
- if (0 < trypercent && trypercent <= 100f)
+ int trypercent = Integer.parseInt(jvmmempc);
+ if (0 <= trypercent && trypercent <= 100)
{
percent = trypercent;
}
else
{
- System.out.println("MemorySetting Property '"
+ setAdjustmentMessage("MemorySetting Property '"
+ MAX_HEAPSIZE_PERCENT_PROPERTY_NAME
- + "' should be in range 1..100. Using default " + percent
- + "%");
+ + "' should be in range 0..100. Using default " + percent
+ + "%", quiet);
}
}
} catch (NumberFormatException e)
{
- System.out.println("MemorySetting property '"
+ setAdjustmentMessage("MemorySetting property '"
+ MAX_HEAPSIZE_PERCENT_PROPERTY_NAME + "' (" + jvmmempcarg
- + ") badly formatted");
+ + ") badly formatted", quiet);
}
// catch everything in case of no com.sun.management.OperatingSystemMXBean
{
mempc = physicalMem - LEAVE_FREE_MIN_MEMORY;
reducedmempc = true;
- System.out.println("MemorySetting Property '"
+ setAdjustmentMessage("MemorySetting Property '"
+ MAX_HEAPSIZE_PERCENT_PROPERTY_NAME + "' (" + jvmmempcarg
+ ") too large. Leaving free space for OS and reducing to ("
- + mempc + ").");
+ + mempc + ").", quiet);
}
// check for minimum application memsize
{
if (reducedmempc)
{
- System.out.println("Reduced MemorySetting (" + mempc
+ setAdjustmentMessage("Reduced MemorySetting (" + mempc
+ ") too small. Increasing to application minimum ("
- + APPLICATION_MIN_MEMORY + ").");
+ + APPLICATION_MIN_MEMORY + ").", quiet);
}
else
{
- System.out.println("MemorySetting Property '"
+ setAdjustmentMessage("MemorySetting Property '"
+ MAX_HEAPSIZE_PERCENT_PROPERTY_NAME + "' ("
+ jvmmempcarg + ") too small. Using minimum ("
- + APPLICATION_MIN_MEMORY + ").");
+ + APPLICATION_MIN_MEMORY + ").", quiet);
}
mempc = APPLICATION_MIN_MEMORY;
}
{
// not enough memory for application, just try and grab what we can!
mempc = physicalMem;
- System.out.println(
+ setAdjustmentMessage(
"Not enough physical memory for application. Ignoring MemorySetting Property '"
+ MAX_HEAPSIZE_PERCENT_PROPERTY_NAME + "' ("
+ jvmmempcarg
+ "). Using maximum memory available ("
- + physicalMem + ").");
+ + physicalMem + ").",
+ quiet);
}
} catch (Throwable t)
{
memoryPercentError = true;
- System.out.println(
- "Problem calling GetMemory.getPhysicalMemory(). Likely to be problem with com.sun.management.OperatingSystemMXBean");
+ setAdjustmentMessage(
+ "Problem calling GetMemory.getPhysicalMemory(). Likely to be problem with com.sun.management.OperatingSystemMXBean",
+ quiet);
t.printStackTrace();
}
// == null))
&& memmax > NOMEM_MAX_HEAPSIZE_GB_DEFAULT * GIGABYTE)
{
- System.out.println(
+ setAdjustmentMessage(
"Capping maximum memory to " + NOMEM_MAX_HEAPSIZE_GB_DEFAULT
- + "g due to failure to read physical memory size.");
+ + "g due to failure to read physical memory size.",
+ quiet);
memmax = NOMEM_MAX_HEAPSIZE_GB_DEFAULT * GIGABYTE;
}
return maxMemLong;
}
+ public static boolean isValidMemoryString(String text)
+ {
+ if (text.length() > 0)
+ {
+ char lastChar = text.charAt(text.length() - 1);
+ char[] otherChars = text.substring(0, text.length() - 1)
+ .toCharArray();
+ for (char c : otherChars)
+ {
+ if (c < '0' || c > '9')
+ {
+ return false;
+ }
+ }
+ if ((lastChar < '0' || lastChar > '9') && memorySuffixes
+ .indexOf(Character.toLowerCase(lastChar)) == -1)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static long memoryStringToLong(String memString)
+ throws NumberFormatException
+ {
+ if (!isValidMemoryString(memString)) // not valid
+ {
+ throw (new NumberFormatException("Not a valid memory string"));
+ }
+ char suffix = Character
+ .toLowerCase(memString.charAt(memString.length() - 1));
+ if ('0' <= suffix && suffix <= '9') // no suffix
+ {
+ return Long.valueOf(memString);
+ }
+ if (memorySuffixes.indexOf(suffix) == -1) // suffix is unknown
+ {
+ return -1;
+ }
+
+ long multiplier = (long) Math.pow(2,
+ memorySuffixes.indexOf(suffix) * 10); // note order of suffixes in
+ // memorySuffixes important
+ // here!
+ // parse the arg. NumberFormatExceptions passed on to calling method
+ long mem = Long
+ .parseLong(memString.substring(0, memString.length() - 1));
+ if (mem == 0)
+ {
+ return 0;
+ }
+
+ // apply multiplier only if result is not too big (i.e. bigger than a long)
+ if (Long.MAX_VALUE / mem > multiplier)
+ {
+ return multiplier * mem;
+ }
+ else
+ {
+ // number too big for a Long. Limit to Long.MAX_VALUE
+ System.out.println("Memory parsing of '" + memString
+ + "' produces number too big. Limiting to Long.MAX_VALUE="
+ + Long.MAX_VALUE);
+ return Long.MAX_VALUE;
+ }
+ }
+
+ public static String memoryLongToString(long mem)
+ {
+ return memoryLongToString(mem, "%.1f");
+ }
+
+ public static String memoryLongToString(long mem, String format)
+ {
+ int exponent = 0;
+ float num = mem;
+ char suffix = 'b';
+
+ for (int i = 0; i < memorySuffixes.length(); i++)
+ {
+ char s = Character.toUpperCase(memorySuffixes.charAt(i));
+ if (mem < (long) Math.pow(2, exponent + 10)
+ || i == memorySuffixes.length() - 1) // last suffix
+ {
+ suffix = s;
+ num = (float) (mem / Math.pow(2, exponent));
+ break;
+ }
+ exponent += 10;
+ }
+
+ return String.format(format, num) + suffix;
+ }
+
+ private static String ADJUSTMENT_MESSAGE = null;
+
+ private static void setAdjustmentMessage(String reason, boolean quiet)
+ {
+ ADJUSTMENT_MESSAGE = reason;
+ if (!quiet)
+ {
+ System.out.println(reason);
+ }
+ }
+
+ public static void clearAdjustmentMessage()
+ {
+ ADJUSTMENT_MESSAGE = null;
+ }
+
+ public static String getAdjustmentMessage()
+ {
+ return ADJUSTMENT_MESSAGE;
+ }
+
}
\ No newline at end of file
--- /dev/null
+package jalview.util;
+
+import java.awt.Image;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.swing.ImageIcon;
+
+public class ChannelProperties
+{
+
+ public static final String CHANNEL_PROPERTIES_FILENAME = "channel.props";
+
+ private static Properties channelProps;
+
+ private static final Properties defaultProps;
+
+ private static Map<String, Image> imageMap = new HashMap<String, Image>();
+
+ private static Map<String, URL> urlMap = new HashMap<String, URL>();
+
+ private static final ArrayList<Image> iconList;
+
+ static
+ {
+ defaultProps = new Properties();
+ // these should be kept up to date, but in real life they should never
+ // actually be used anyway.
+ defaultProps.put("app_name", "Jalview");
+ defaultProps.put("banner", "/default_images/jalview_banner.png");
+ defaultProps.put("logo.16", "/default_images/jalview_logo-16.png");
+ defaultProps.put("logo.32", "/default_images/jalview_logo-32.png");
+ defaultProps.put("logo.38", "/default_images/jalview_logo-38.png");
+ defaultProps.put("logo.48", "/default_images/jalview_logo-48.png");
+ defaultProps.put("logo.64", "/default_images/jalview_logo-64.png");
+ defaultProps.put("logo.128", "/default_images/jalview_logo-128.png");
+ defaultProps.put("logo.256", "/default_images/jalview_logo-256.png");
+ defaultProps.put("logo.512", "/default_images/jalview_logo-512.png");
+ defaultProps.put("rotatable_logo.48",
+ "/default_images/rotatable_jalview_logo-38.png");
+ defaultProps.put("bg_logo.28", "/default_images/barton_group-28.png");
+ defaultProps.put("bg_logo.30", "/default_images/barton_group-30.png");
+ defaultProps.put("bg_logo.32", "/default_images/barton_group-32.png");
+ defaultProps.put("uod_banner.28", "/default_images/UoD_banner-28.png");
+ defaultProps.put("uod_banner.30", "/default_images/UoD_banner-30.png");
+ defaultProps.put("uod_banner.32", "/default_images/UoD_banner-32.png");
+ defaultProps.put("default_appbase",
+ "https://www.jalview.org/getdown/release/1.8");
+ defaultProps.put("preferences.filename", ".jalview_properties");
+
+ // load channel_properties
+ Properties tryChannelProps = new Properties();
+ URL channelPropsURL = ChannelProperties.class
+ .getResource("/" + CHANNEL_PROPERTIES_FILENAME);
+ if (channelPropsURL == null)
+ {
+ // complete failure of channel_properties, set all properties to defaults
+ System.err.println("Failed to find '/" + CHANNEL_PROPERTIES_FILENAME
+ + "' file at '"
+ + (channelPropsURL == null ? "null"
+ : channelPropsURL.toString())
+ + "'. Using class defaultProps.");
+ tryChannelProps = defaultProps;
+ }
+ else
+ {
+ try
+ {
+ InputStream channelPropsIS = channelPropsURL.openStream();
+ tryChannelProps.load(channelPropsIS);
+ channelPropsIS.close();
+ } catch (IOException e)
+ {
+ System.err.println(e.getMessage());
+ // return false;
+ }
+ }
+ channelProps = tryChannelProps;
+
+ /*
+ * The following slight palava for caching an icon list is so that all sizes of icons
+ * are the same. i.e. if there are /any/ channel_properties icons to use, then _only_
+ * use those channel_properties icons, don't mix in class default icons for missing
+ * sizes. If there are _no_ (usable) channel icons then we can use the class default icons.
+ */
+ iconList = new ArrayList<Image>();
+ List<String> sizes = Arrays.asList("16", "32", "48", "64", "128", "256",
+ "512");
+ for (String size : sizes)
+ {
+ Image logo = null;
+ // not using defaults or class props first time through
+ logo = ChannelProperties.getImage("logo." + size, null, false);
+ if (logo != null)
+ {
+ iconList.add(logo);
+ }
+ }
+ // now add the class defaults if there were no channel icons defined
+ if (iconList.size() == 0)
+ {
+ for (String size : sizes)
+ {
+ Image logo = null;
+ String path = defaultProps.getProperty("logo." + size);
+ URL imageURL = ChannelProperties.class.getResource(path);
+ ImageIcon imgIcon = imageURL == null ? null
+ : new ImageIcon(imageURL);
+ logo = imgIcon == null ? null : imgIcon.getImage();
+ if (logo != null)
+ {
+ iconList.add(logo);
+ }
+ }
+ }
+ }
+
+ protected static void loadProps(File dir)
+ {
+ File channelPropsFile = new File(dir, CHANNEL_PROPERTIES_FILENAME);
+ if (channelPropsFile.exists())
+ {
+ try
+ {
+ InputStream is = new FileInputStream(channelPropsFile);
+ channelProps.load(is);
+ } catch (FileNotFoundException e)
+ {
+ System.err.println(e.getMessage());
+ } catch (IOException e)
+ {
+ System.err.println(e.getMessage());
+ }
+ }
+ }
+
+ private static Properties channelProps()
+ {
+ return channelProps;
+ }
+
+ private static Map<String, Image> imageMap()
+ {
+ return imageMap;
+ }
+
+ private static Map<String, URL> urlMap()
+ {
+ return urlMap;
+ }
+
+ /*
+ * getProperty(key) will get property value from channel_properties for key.
+ * If no property for key is found, it will fall back to using the defaultProps defined for this class.
+ */
+ public static String getProperty(String key)
+ {
+ return getProperty(key, null, true);
+ }
+
+ /*
+ * getProperty(key, defaultVal) will get property value from channel_properties for key.
+ * If no property for key is found, it will return defaultVal and NOT fall back to the class defaultProps.
+ */
+ public static String getProperty(String key, String defaultVal)
+ {
+ return getProperty(key, defaultVal, false);
+ }
+
+ /*
+ * internal method. note that setting useClassDefaultProps=true will ignore the provided defaultVal
+ */
+ private static String getProperty(String key, String defaultVal,
+ boolean useClassDefaultProps)
+ {
+ if (channelProps() != null)
+ {
+ if (channelProps().containsKey(key))
+ {
+ return channelProps().getProperty(key,
+ useClassDefaultProps ? defaultProps.getProperty(key)
+ : defaultVal);
+ }
+ else
+ {
+ System.err.println("Failed to get channel property '" + key + "'");
+ }
+ }
+ return null;
+ }
+
+ /*
+ * getImage(key) returns the channel defined image for property key. If that is null (e.g. due to
+ * no defined channel image or the image file being corrupt/unusable/missing) it uses the image
+ * defined in defaultChannelProps
+ */
+ public static Image getImage(String key)
+ {
+ return getImage(key, null, true);
+ }
+
+ /*
+ * getImage(key, defaultImg) will get image associated with value from channel_properties for key.
+ * If no property or associated image for key is found (or is usable), it will return defaultImg
+ * and NOT fall back to the class defaultProps.
+ */
+ public static Image getImage(String key, Image defaultImg)
+ {
+ return getImage(key, defaultImg, false);
+ }
+
+ /*
+ * internal method. note that setting useClassDefaultImage=true will ignore the provided defaultImg
+ */
+ private static Image getImage(String key, Image defaultImg,
+ boolean useClassDefaultImage)
+ {
+ Image img = null;
+ if (imageMap().containsKey(key))
+ {
+ img = imageMap().get(key);
+ }
+ // Catch a previously untried or failed load
+ if (img == null)
+ {
+ String path = getProperty(key, null, useClassDefaultImage);
+ if (path == null) // no channel property or class default property (if
+ // requested)
+ {
+ return useClassDefaultImage ? null : defaultImg;
+ }
+
+ URL imageURL = ChannelProperties.class.getResource(path);
+ ImageIcon imgIcon = imageURL == null ? null : new ImageIcon(imageURL);
+ img = imgIcon == null ? null : imgIcon.getImage();
+ if (img == null)
+ {
+ System.err.println(
+ "Failed to load channel image " + key + "=" + path);
+ if (!useClassDefaultImage)
+ {
+ return defaultImg;
+ }
+ }
+ else
+ {
+ imageMap().put(key, img);
+ urlMap.put(key, imageURL);
+ }
+ }
+ return img;
+ }
+
+ /*
+ * Public method to get the URL object pointing to a cached image.
+ */
+ public static URL getImageURL(String key)
+ {
+ if (getImage(key) != null)
+ {
+ if (urlMap().containsKey(key))
+ {
+ return urlMap().getOrDefault(key, null);
+ }
+ System.err.println(
+ "Do not use getImageURL(key) before using getImage(key...)");
+ }
+ return null;
+ }
+
+ /*
+ * Get a List of Icon images of different sizes.
+ */
+ public static ArrayList<Image> getIconList()
+ {
+ return iconList;
+ }
+}
--- /dev/null
+package jalview.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Properties;
+
+public class LaunchUtils
+{
+
+ public static void loadChannelProps(File dir)
+ {
+ ChannelProperties.loadProps(dir);
+ }
+
+ private static Properties userPreferences = null;
+
+ public static String getUserPreference(String key)
+ {
+ if (userPreferences == null)
+ {
+ String channelPrefsFilename = ChannelProperties
+ .getProperty("preferences.filename");
+ if (channelPrefsFilename == null)
+ {
+ return null;
+ }
+ File propertiesFile = new File(System.getProperty("user.home"),
+ channelPrefsFilename);
+ if (!propertiesFile.exists())
+ {
+ return null;
+ }
+ try
+ {
+ userPreferences = new Properties();
+ userPreferences.load(new FileInputStream(propertiesFile));
+ } catch (FileNotFoundException e)
+ {
+ // didn't find user preferences file
+ return null;
+ } catch (IOException e)
+ {
+ System.err.println(e.getMessage());
+ return null;
+ }
+ }
+ return userPreferences.getProperty(key);
+ }
+
+ public static boolean getBooleanUserPreference(String key)
+ {
+ return Boolean.parseBoolean(getUserPreference(key));
+ }
+}
--- /dev/null
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview 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 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview 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 Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+package jalview.util;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+public class StringUtils
+{
+ private static final Pattern DELIMITERS_PATTERN = Pattern
+ .compile(".*='[^']*(?!')");
+
+ private static final char PERCENT = '%';
+
+ private static final boolean DEBUG = false;
+
+ /*
+ * URL encoded characters, indexed by char value
+ * e.g. urlEncodings['='] = urlEncodings[61] = "%3D"
+ */
+ private static String[] urlEncodings = new String[255];
+
+ /**
+ * Returns a new character array, after inserting characters into the given
+ * character array.
+ *
+ * @param in
+ * the character array to insert into
+ * @param position
+ * the 0-based position for insertion
+ * @param count
+ * the number of characters to insert
+ * @param ch
+ * the character to insert
+ */
+ public static final char[] insertCharAt(char[] in, int position,
+ int count, char ch)
+ {
+ char[] tmp = new char[in.length + count];
+
+ if (position >= in.length)
+ {
+ System.arraycopy(in, 0, tmp, 0, in.length);
+ position = in.length;
+ }
+ else
+ {
+ System.arraycopy(in, 0, tmp, 0, position);
+ }
+
+ int index = position;
+ while (count > 0)
+ {
+ tmp[index++] = ch;
+ count--;
+ }
+
+ if (position < in.length)
+ {
+ System.arraycopy(in, position, tmp, index, in.length - position);
+ }
+
+ return tmp;
+ }
+
+ /**
+ * Delete
+ *
+ * @param in
+ * @param from
+ * @param to
+ * @return
+ */
+ public static final char[] deleteChars(char[] in, int from, int to)
+ {
+ if (from >= in.length || from < 0)
+ {
+ return in;
+ }
+
+ char[] tmp;
+
+ if (to >= in.length)
+ {
+ tmp = new char[from];
+ System.arraycopy(in, 0, tmp, 0, from);
+ to = in.length;
+ }
+ else
+ {
+ tmp = new char[in.length - to + from];
+ System.arraycopy(in, 0, tmp, 0, from);
+ System.arraycopy(in, to, tmp, from, in.length - to);
+ }
+ return tmp;
+ }
+
+ /**
+ * Returns the last part of 'input' after the last occurrence of 'token'. For
+ * example to extract only the filename from a full path or URL.
+ *
+ * @param input
+ * @param token
+ * a delimiter which must be in regular expression format
+ * @return
+ */
+ public static String getLastToken(String input, String token)
+ {
+ if (input == null)
+ {
+ return null;
+ }
+ if (token == null)
+ {
+ return input;
+ }
+ String[] st = input.split(token);
+ return st[st.length - 1];
+ }
+
+ /**
+ * Parses the input string into components separated by the delimiter. Unlike
+ * String.split(), this method will ignore occurrences of the delimiter which
+ * are nested within single quotes in name-value pair values, e.g. a='b,c'.
+ *
+ * @param input
+ * @param delimiter
+ * @return elements separated by separator
+ */
+ public static String[] separatorListToArray(String input,
+ String delimiter)
+ {
+ int seplen = delimiter.length();
+ if (input == null || input.equals("") || input.equals(delimiter))
+ {
+ return null;
+ }
+ List<String> jv = new ArrayList<>();
+ int cp = 0, pos, escape;
+ boolean wasescaped = false, wasquoted = false;
+ String lstitem = null;
+ while ((pos = input.indexOf(delimiter, cp)) >= cp)
+ {
+ escape = (pos > 0 && input.charAt(pos - 1) == '\\') ? -1 : 0;
+ if (wasescaped || wasquoted)
+ {
+ // append to previous pos
+ jv.set(jv.size() - 1, lstitem = lstitem + delimiter
+ + input.substring(cp, pos + escape));
+ }
+ else
+ {
+ jv.add(lstitem = input.substring(cp, pos + escape));
+ }
+ cp = pos + seplen;
+ wasescaped = escape == -1;
+ // last separator may be in an unmatched quote
+ wasquoted = DELIMITERS_PATTERN.matcher(lstitem).matches();
+ }
+ if (cp < input.length())
+ {
+ String c = input.substring(cp);
+ if (wasescaped || wasquoted)
+ {
+ // append final separator
+ jv.set(jv.size() - 1, lstitem + delimiter + c);
+ }
+ else
+ {
+ if (!c.equals(delimiter))
+ {
+ jv.add(c);
+ }
+ }
+ }
+ if (jv.size() > 0)
+ {
+ String[] v = jv.toArray(new String[jv.size()]);
+ jv.clear();
+ if (DEBUG)
+ {
+ System.err.println("Array from '" + delimiter
+ + "' separated List:\n" + v.length);
+ for (int i = 0; i < v.length; i++)
+ {
+ System.err.println("item " + i + " '" + v[i] + "'");
+ }
+ }
+ return v;
+ }
+ if (DEBUG)
+ {
+ System.err.println(
+ "Empty Array from '" + delimiter + "' separated List");
+ }
+ return null;
+ }
+
+ /**
+ * Returns a string which contains the list elements delimited by the
+ * separator. Null items are ignored. If the input is null or has length zero,
+ * a single delimiter is returned.
+ *
+ * @param list
+ * @param separator
+ * @return concatenated string
+ */
+ public static String arrayToSeparatorList(String[] list, String separator)
+ {
+ StringBuffer v = new StringBuffer();
+ if (list != null && list.length > 0)
+ {
+ for (int i = 0, iSize = list.length; i < iSize; i++)
+ {
+ if (list[i] != null)
+ {
+ if (v.length() > 0)
+ {
+ v.append(separator);
+ }
+ // TODO - escape any separator values in list[i]
+ v.append(list[i]);
+ }
+ }
+ if (DEBUG)
+ {
+ System.err
+ .println("Returning '" + separator + "' separated List:\n");
+ System.err.println(v);
+ }
+ return v.toString();
+ }
+ if (DEBUG)
+ {
+ System.err.println(
+ "Returning empty '" + separator + "' separated List\n");
+ }
+ return "" + separator;
+ }
+
+ /**
+ * Converts a list to a string with a delimiter before each term except the
+ * first. Returns an empty string given a null or zero-length argument. This
+ * can be replaced with StringJoiner in Java 8.
+ *
+ * @param terms
+ * @param delim
+ * @return
+ */
+ public static String listToDelimitedString(List<String> terms,
+ String delim)
+ {
+ StringBuilder sb = new StringBuilder(32);
+ if (terms != null && !terms.isEmpty())
+ {
+ boolean appended = false;
+ for (String term : terms)
+ {
+ if (appended)
+ {
+ sb.append(delim);
+ }
+ appended = true;
+ sb.append(term);
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * Convenience method to parse a string to an integer, returning 0 if the
+ * input is null or not a valid integer
+ *
+ * @param s
+ * @return
+ */
+ public static int parseInt(String s)
+ {
+ int result = 0;
+ if (s != null && s.length() > 0)
+ {
+ try
+ {
+ result = Integer.parseInt(s);
+ } catch (NumberFormatException ex)
+ {
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Compares two versions formatted as e.g. "3.4.5" and returns -1, 0 or 1 as
+ * the first version precedes, is equal to, or follows the second
+ *
+ * @param v1
+ * @param v2
+ * @return
+ */
+ public static int compareVersions(String v1, String v2)
+ {
+ return compareVersions(v1, v2, null);
+ }
+
+ /**
+ * Compares two versions formatted as e.g. "3.4.5b1" and returns -1, 0 or 1 as
+ * the first version precedes, is equal to, or follows the second
+ *
+ * @param v1
+ * @param v2
+ * @param pointSeparator
+ * a string used to delimit point increments in sub-tokens of the
+ * version
+ * @return
+ */
+ public static int compareVersions(String v1, String v2,
+ String pointSeparator)
+ {
+ if (v1 == null || v2 == null)
+ {
+ return 0;
+ }
+ String[] toks1 = v1.split("\\.");
+ String[] toks2 = v2.split("\\.");
+ int i = 0;
+ for (; i < toks1.length; i++)
+ {
+ if (i >= toks2.length)
+ {
+ /*
+ * extra tokens in v1
+ */
+ return 1;
+ }
+ String tok1 = toks1[i];
+ String tok2 = toks2[i];
+ if (pointSeparator != null)
+ {
+ /*
+ * convert e.g. 5b2 into decimal 5.2 for comparison purposes
+ */
+ tok1 = tok1.replace(pointSeparator, ".");
+ tok2 = tok2.replace(pointSeparator, ".");
+ }
+ try
+ {
+ float f1 = Float.valueOf(tok1);
+ float f2 = Float.valueOf(tok2);
+ int comp = Float.compare(f1, f2);
+ if (comp != 0)
+ {
+ return comp;
+ }
+ } catch (NumberFormatException e)
+ {
+ System.err
+ .println("Invalid version format found: " + e.getMessage());
+ return 0;
+ }
+ }
+
+ if (i < toks2.length)
+ {
+ /*
+ * extra tokens in v2
+ */
+ return -1;
+ }
+
+ /*
+ * same length, all tokens match
+ */
+ return 0;
+ }
+
+ /**
+ * Converts the string to all lower-case except the first character which is
+ * upper-cased
+ *
+ * @param s
+ * @return
+ */
+ public static String toSentenceCase(String s)
+ {
+ if (s == null)
+ {
+ return s;
+ }
+ if (s.length() <= 1)
+ {
+ return s.toUpperCase();
+ }
+ return s.substring(0, 1).toUpperCase() + s.substring(1).toLowerCase();
+ }
+
+ /**
+ * A helper method that strips off any leading or trailing html and body tags.
+ * If no html tag is found, then also html-encodes angle bracket characters.
+ *
+ * @param text
+ * @return
+ */
+ public static String stripHtmlTags(String text)
+ {
+ if (text == null)
+ {
+ return null;
+ }
+ String tmp2up = text.toUpperCase();
+ int startTag = tmp2up.indexOf("<HTML>");
+ if (startTag > -1)
+ {
+ text = text.substring(startTag + 6);
+ tmp2up = tmp2up.substring(startTag + 6);
+ }
+ // is omission of "<BODY>" intentional here??
+ int endTag = tmp2up.indexOf("</BODY>");
+ if (endTag > -1)
+ {
+ text = text.substring(0, endTag);
+ tmp2up = tmp2up.substring(0, endTag);
+ }
+ endTag = tmp2up.indexOf("</HTML>");
+ if (endTag > -1)
+ {
+ text = text.substring(0, endTag);
+ }
+
+ if (startTag == -1 && (text.contains("<") || text.contains(">")))
+ {
+ text = text.replaceAll("<", "<");
+ text = text.replaceAll(">", ">");
+ }
+ return text;
+ }
+
+ /**
+ * Answers the input string with any occurrences of the 'encodeable'
+ * characters replaced by their URL encoding
+ *
+ * @param s
+ * @param encodable
+ * @return
+ */
+ public static String urlEncode(String s, String encodable)
+ {
+ if (s == null || s.isEmpty())
+ {
+ return s;
+ }
+
+ /*
+ * do % encoding first, as otherwise it may double-encode!
+ */
+ if (encodable.indexOf(PERCENT) != -1)
+ {
+ s = urlEncode(s, PERCENT);
+ }
+
+ for (char c : encodable.toCharArray())
+ {
+ if (c != PERCENT)
+ {
+ s = urlEncode(s, c);
+ }
+ }
+ return s;
+ }
+
+ /**
+ * Answers the input string with any occurrences of {@code c} replaced with
+ * their url encoding. Answers the input string if it is unchanged.
+ *
+ * @param s
+ * @param c
+ * @return
+ */
+ static String urlEncode(String s, char c)
+ {
+ String decoded = String.valueOf(c);
+ if (s.indexOf(decoded) != -1)
+ {
+ String encoded = getUrlEncoding(c);
+ if (!encoded.equals(decoded))
+ {
+ s = s.replace(decoded, encoded);
+ }
+ }
+ return s;
+ }
+
+ /**
+ * Answers the input string with any occurrences of the specified (unencoded)
+ * characters replaced by their URL decoding.
+ * <p>
+ * Example: {@code urlDecode("a%3Db%3Bc", "-;=,")} should answer
+ * {@code "a=b;c"}.
+ *
+ * @param s
+ * @param encodable
+ * @return
+ */
+ public static String urlDecode(String s, String encodable)
+ {
+ if (s == null || s.isEmpty())
+ {
+ return s;
+ }
+
+ for (char c : encodable.toCharArray())
+ {
+ String encoded = getUrlEncoding(c);
+ if (s.indexOf(encoded) != -1)
+ {
+ String decoded = String.valueOf(c);
+ s = s.replace(encoded, decoded);
+ }
+ }
+ return s;
+ }
+
+ /**
+ * Does a lazy lookup of the url encoding of the given character, saving the
+ * value for repeat lookups
+ *
+ * @param c
+ * @return
+ */
+ private static String getUrlEncoding(char c)
+ {
+ if (c < 0 || c >= urlEncodings.length)
+ {
+ return String.valueOf(c);
+ }
+
+ String enc = urlEncodings[c];
+ if (enc == null)
+ {
+ try
+ {
+ enc = urlEncodings[c] = URLEncoder.encode(String.valueOf(c),
+ "UTF-8");
+ } catch (UnsupportedEncodingException e)
+ {
+ enc = urlEncodings[c] = String.valueOf(c);
+ }
+ }
+ return enc;
+ }
+
+ public static int firstCharPosIgnoreCase(String text, String chars)
+ {
+ int min = text.length() + 1;
+ for (char c : chars.toLowerCase().toCharArray())
+ {
+ int i = text.toLowerCase().indexOf(c);
+ if (0 <= i && i < min)
+ {
+ min = i;
+ }
+ }
+ return min < text.length() + 1 ? min : -1;
+ }
+}
<parent>
<groupId>com.threerings.getdown</groupId>
<artifactId>getdown</artifactId>
- <version>1.8.3-1.2.10_FJVL</version>
+ <version>1.8.3-1.2.11_FJVL</version>
</parent>
<artifactId>getdown-launcher</artifactId>
_getdown = getdown;
_msgs = msgs;
+ String[] hostPortAuthUser = ProxyUtil.jalviewProxyProperties(getdown._app);
+ String host = hostPortAuthUser[0];
+ String port = hostPortAuthUser[1];
+ boolean proxyAuth = Boolean.parseBoolean(hostPortAuthUser[2]);
+ String username = hostPortAuthUser[3];
+
setLayout(new VGroupLayout());
setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
add(new SaneLabelField(get("m.configure_proxy")));
JPanel row = new JPanel(new GridLayout());
row.add(new SaneLabelField(get("m.proxy_host")), BorderLayout.WEST);
row.add(_host = new SaneTextField());
+ _host.setText(host);
add(row);
row = new JPanel(new GridLayout());
row.add(new SaneLabelField(get("m.proxy_port")), BorderLayout.WEST);
row.add(_port = new SaneTextField());
+ _port.setText(port);
add(row);
add(new Spacer(5, 5));
row = new JPanel(new GridLayout());
row.add(new SaneLabelField(get("m.proxy_auth_required")), BorderLayout.WEST);
_useAuth = new JCheckBox();
+ _useAuth.setSelected(proxyAuth);
row.add(_useAuth);
add(row);
row = new JPanel(new GridLayout());
row.add(new SaneLabelField(get("m.proxy_username")), BorderLayout.WEST);
_username = new SaneTextField();
- _username.setEnabled(false);
+ _username.setText(username);
+ _username.setEnabled(_useAuth.isSelected());
row.add(_username);
add(row);
row = new JPanel(new GridLayout());
row.add(new SaneLabelField(get("m.proxy_password")), BorderLayout.WEST);
_password = new SanePasswordField();
- _password.setEnabled(false);
+ _password.setEnabled(_useAuth.isSelected());
row.add(_password);
add(row);
package com.threerings.getdown.launcher;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.PrintStream;
import java.net.Authenticator;
import java.net.HttpURLConnection;
import java.util.Iterator;
import java.util.ServiceLoader;
+import jalview.util.LaunchUtils;
+
import ca.beq.util.win32.registry.RegistryKey;
import ca.beq.util.win32.registry.RegistryValue;
import ca.beq.util.win32.registry.RootKey;
port = hostPort[1];
}
+ // look in jalview_properties
+ String[] hostPortAuthUser = jalviewProxyProperties(app);
+ host = hostPortAuthUser[0];
+ port = hostPortAuthUser[1];
+ boolean proxyAuth = Boolean.parseBoolean(hostPortAuthUser[2]);
+ String username = hostPortAuthUser[3];
+
if (StringUtil.isBlank(host)) {
return false;
}
// yay, we found a proxy configuration, configure it in the app
- initProxy(app, host, port, null, null);
+ initProxy(app, host, port, username, null);
return true;
}
+ public static String[] jalviewProxyProperties(Application app) {
+ String host = null;
+ String port = null;
+ boolean proxyAuth = false;
+ String username = null;
+ LaunchUtils.loadChannelProps(app.getAppDir());
+ if (LaunchUtils.getBooleanUserPreference("USE_PROXY")) {
+ host = LaunchUtils.getUserPreference("PROXY_SERVER_HTTPS");
+ port = LaunchUtils.getUserPreference("PROXY_PORT_HTTPS");
+ if (StringUtil.isBlank(host)) {
+ host = LaunchUtils.getUserPreference("PROXY_SERVER");
+ port = LaunchUtils.getUserPreference("PROXY_PORT");
+ }
+ proxyAuth = LaunchUtils.getBooleanUserPreference("PROXY_AUTH");
+ if (proxyAuth) {
+ username = LaunchUtils.getUserPreference("PROXY_AUTH_USERNAME");
+ }
+ }
+ return new String[]{ host, port, String.valueOf(proxyAuth), username };
+ }
+
public static boolean canLoadWithoutProxy (URL rurl)
{
log.info("Testing whether proxy is needed, via: " + rurl);
public static void initProxy (Application app, String host, String port,
String username, String password)
{
+System.out.println("**** initProxy(app, '"+host+"', "+port+", '"+username+"', "+(password==null?"null":"*x"+password.length())+")");
// check whether we have saved proxy credentials
String appDir = app.getAppDir().getAbsolutePath();
ServiceLoader<ProxyAuth> loader = ServiceLoader.load(ProxyAuth.class);
if [ x$JVLVERSION != x ]; then
export VERSION=$JVLVERSION
else
- export VERSION=1.8.3-1.2.10_JVL
+ export VERSION=1.8.3-1.2.11_JVL
fi
if [ x${VERSION%_JVL} = x$VERSION ]; then
<groupId>com.threerings.getdown</groupId>
<artifactId>getdown</artifactId>
<packaging>pom</packaging>
- <version>1.8.3-1.2.10_FJVL</version>
+ <version>1.8.3-1.2.11_FJVL</version>
<name>getdown</name>
<description>An application installer and updater.</description>
flexmark_css = utils/doc/github.css
channel_properties_dir = utils/channels
+channel_props = channel.props
install4j_home_dir = ~/buildtools/install4j8
install4j_copyright_message = ...
<td>
<ul>
<li>
+ TO DOCUMENT: JAL-3700,JAL-3751,JAL-3763
+ </li>
+ <li>
<!-- JAL-3915 -->Removed RNAview checkbox and logic from
Structure Preferences
</li>
label.log_level_tooltip = Temporarily set the log level for this console. The log level will revert to {0} when this Java console is closed.
label.copy_to_clipboard = Copy to clipboard
label.copy_to_clipboard_tooltip = Copy all of the log text in this console to the system clipboard
+label.startup = Startup
+label.memory = Memory
+label.customise_memory_settings = Customise maximum memory settings
+label.memory_setting_text = New memory settings will only come into effect the next time you start Jalview
+label.maximum_memory_used = Maximum memory limited to both
+label.percent_of_physical_memory = Maximum percent of physical memory
+label.maximum_memory = Maximum absolute memory
+label.maximum_memory_tooltip = Enter memory as an integer number optionally followed by 'b', 'k', 'm', 'g' or 't'
+label.adjustments_for_this_computer = Adjustments for this computer
+label.memory_example_text = Maximum memory that would be used with these settings on this computer
+label.memory_example_tooltip = The memory allocated to Jalview is the smaller of the percentage of physical memory (default 90%) and the maximum absolute memory (default 32GB). If your computer's memory cannot be ascertained then the maximum absolute memory defaults to 8GB (if not customised).<br>Jalview will always try and reserve 512MB for the OS and at least 512MB for itself.
label.log_level_tooltip = Establezca temporalmente el nivel de registro para esta consola. El nivel de registro volverá a {0} cuando se cierre esta consola de Java.
label.copy_to_clipboard = Copiar en el portapapeles
label.copy_to_clipboard_tooltip = Copie todo el texto de registro en esta consola al portapapeles del sistema
+label.startup = Inicio
+label.memory = Memoria
+label.customise_memory_settings = Personalizar la configuración de memoria máxima
+label.memory_setting_text = La nueva configuración de memoria solo entrará en vigor la próxima vez que inicie Jalview
+label.maximum_memory_used = Memoria máxima limitada a ambos
+label.percent_of_physical_memory = Porcentaje máximo de memoria fÃsica
+label.maximum_memory = Memoria absoluta máxima
+label.maximum_memory_tooltip = Ingrese la memoria como un número entero seguido opcionalmente por 'b', 'k', 'm', 'g' o 't'
+label.adjustments_for_this_computer = Ajustes para esta computadora
+label.memory_example_text = Memoria máxima que se usarÃa con esta configuración en esta computadora
+label.memory_example_tooltip = La memoria asignada a Jalview es el menor entre el porcentaje de memoria fÃsica (predeterminado 90%) y la memoria absoluta máxima (predeterminado 32 GB). Si no se puede determinar la memoria de su computadora, la memoria absoluta máxima predeterminada es de 8 GB (si no está personalizada).<br>Jalview siempre intentará reservar 512 MB para el sistema operativo y al menos 512 MB para sà mismo.
import java.util.Locale;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import jalview.bin.Cache;
import jalview.commands.RemoveGapColCommand;
import jalview.datamodel.AlignedCodon;
import jalview.datamodel.AlignedCodonFrame;
import jalview.util.MapList;
import jalview.util.MappingUtils;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.NoSuchElementException;
-import java.util.Set;
-import java.util.SortedMap;
-import java.util.TreeMap;
-
/**
* grab bag of useful alignment manipulation operations Expect these to be
* refactored elsewhere at some point.
SequenceI newSeq = null;
- final MapList maplist = mapping.getMap();
- if (maplist.isContiguous() && maplist.isFromForwardStrand())
- {
- /*
- * just a subsequence, keep same dataset sequence
- */
- int start = maplist.getFromLowest();
- int end = maplist.getFromHighest();
- newSeq = seq.getSubSequence(start - 1, end);
- newSeq.setName(seqId);
- }
- else
- {
- /*
- * construct by splicing mapped from ranges
- */
- char[] seqChars = seq.getSequence();
- List<int[]> fromRanges = maplist.getFromRanges();
- int cdsWidth = MappingUtils.getLength(fromRanges);
- char[] newSeqChars = new char[cdsWidth];
+ /*
+ * construct CDS sequence by splicing mapped from ranges
+ */
+ char[] seqChars = seq.getSequence();
+ List<int[]> fromRanges = mapping.getMap().getFromRanges();
+ int cdsWidth = MappingUtils.getLength(fromRanges);
+ char[] newSeqChars = new char[cdsWidth];
- int newPos = 0;
- for (int[] range : fromRanges)
+ int newPos = 0;
+ for (int[] range : fromRanges)
+ {
+ if (range[0] <= range[1])
{
- if (range[0] <= range[1])
- {
- // forward strand mapping - just copy the range
- int length = range[1] - range[0] + 1;
- System.arraycopy(seqChars, range[0] - 1, newSeqChars, newPos,
- length);
- newPos += length;
- }
- else
+ // forward strand mapping - just copy the range
+ int length = range[1] - range[0] + 1;
+ System.arraycopy(seqChars, range[0] - 1, newSeqChars, newPos,
+ length);
+ newPos += length;
+ }
+ else
+ {
+ // reverse strand mapping - copy and complement one by one
+ for (int i = range[0]; i >= range[1]; i--)
{
- // reverse strand mapping - copy and complement one by one
- for (int i = range[0]; i >= range[1]; i--)
- {
- newSeqChars[newPos++] = Dna.getComplement(seqChars[i - 1]);
- }
+ newSeqChars[newPos++] = Dna.getComplement(seqChars[i - 1]);
}
}
}
else
{
- System.err.println(
- "JAL-2154 regression: warning - found (and ignnored a duplicate CDS sequence):"
- + mtch.toString());
+ Cache.log.error(
+ "JAL-2154 regression: warning - found (and ignored) a duplicate CDS sequence:" + mtch.toString());
}
}
}
import java.util.List;
import jalview.util.ChannelProperties;
+import jalview.util.LaunchUtils;
/**
* A Launcher class for Jalview. This class is used to launch Jalview from the
}
}
+ // use saved preferences if no cmdline args
+ boolean useCustomisedSettings = LaunchUtils
+ .getBooleanUserPreference(MemorySetting.CUSTOMISED_SETTINGS);
+ if (useCustomisedSettings)
+ {
+ if (jvmmempc == null)
+ {
+ jvmmempc = LaunchUtils
+ .getUserPreference(MemorySetting.MEMORY_JVMMEMPC);
+ }
+ if (jvmmemmax == null)
+ {
+ jvmmemmax = LaunchUtils
+ .getUserPreference(MemorySetting.MEMORY_JVMMEMMAX);
+ }
+ }
+
// add memory setting if not specified
boolean memSet = false;
boolean dockIcon = false;
e.printStackTrace();
}
// System.exit(0);
-
}
}
/*
+
+ private static String ADJUSTMENT_MESSAGE = null;
* Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
* Copyright (C) $$Year-Rel$$ The Jalview Authors
*
* @author bsoares
*
*/
-import java.util.Locale;
-
public class MemorySetting
{
public static final String MAX_HEAPSIZE_PERCENT_PROPERTY_NAME = "jvmmempc";
private static final long NOMEM_MAX_HEAPSIZE_GB_DEFAULT = 8;
+ public static final String NS = "MEMORY";
+
+ public static final String CUSTOMISED_SETTINGS = NS
+ + "_CUSTOMISED_SETTINGS";
+
+ public static final String MEMORY_JVMMEMPC = NS + "_"
+ + MAX_HEAPSIZE_PERCENT_PROPERTY_NAME.toUpperCase();
+
+ public static final String MEMORY_JVMMEMMAX = NS + "_"
+ + MAX_HEAPSIZE_PROPERTY_NAME.toUpperCase();
+
protected static boolean logToClassChecked = false;
+ public static String memorySuffixes = "bkmgt"; // order of the suffixes is
+ // important!
+
public static long getMemorySetting()
{
return getMemorySetting(null, null);
}
+ public static long getMemorySetting(String jvmmemmaxarg,
+ String jvmmempcarg)
+ {
+ return getMemorySetting(jvmmemmaxarg, jvmmempcarg, true, false);
+ }
+
/**
* Decide on appropriate memory setting for Jalview based on the two arguments
* values: jvmmempc - the maximum percentage of total physical memory to
* @param jvmmempcarg
* Max percentage of physical memory to use. Defaults to "90".
*
+ * @param useProps
+ * boolean to decide whether to look at System properties.
+ *
* @return The amount of memory (in bytes) to allocate to Jalview
*/
public static long getMemorySetting(String jvmmemmaxarg,
- String jvmmempcarg)
+ String jvmmempcarg, boolean useProps, boolean quiet)
{
// actual Xmx value-to-be
long maxMemLong = -1;
+ clearAdjustmentMessage();
// (absolute) jvmmaxmem setting, start with default
long memmax = MAX_HEAPSIZE_GB_DEFAULT * GIGABYTE;
- if (jvmmemmaxarg == null)
+ if (jvmmemmaxarg == null && useProps)
{
jvmmemmaxarg = System.getProperty(MAX_HEAPSIZE_PROPERTY_NAME);
}
String jvmmemmax = jvmmemmaxarg;
if (jvmmemmax != null && jvmmemmax.length() > 0)
{
- long multiplier = 1;
- switch (jvmmemmax.toLowerCase(Locale.ROOT).substring(jvmmemmax.length() - 1))
- {
- case "t":
- multiplier = 1099511627776L; // 2^40
- jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
- break;
- case "g":
- multiplier = 1073741824; // 2^30
- jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
- break;
- case "m":
- multiplier = 1048576; // 2^20
- jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
- break;
- case "k":
- multiplier = 1024; // 2^10
- jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
- break;
- case "b":
- multiplier = 1; // 2^0
- jvmmemmax = jvmmemmax.substring(0, jvmmemmax.length() - 1);
- break;
- default:
- break;
- }
-
// parse the arg
try
{
- memmax = Long.parseLong(jvmmemmax);
+ memmax = memoryStringToLong(jvmmemmax);
+ if (memmax == 0)
+ {
+ throw (new NumberFormatException("Not allowing 0"));
+ }
} catch (NumberFormatException e)
{
memmax = MAX_HEAPSIZE_GB_DEFAULT * GIGABYTE;
- System.out.println("MemorySetting Property '"
+ setAdjustmentMessage("MemorySetting Property '"
+ MAX_HEAPSIZE_PROPERTY_NAME + "' (" + jvmmemmaxarg
- + "') badly formatted, using default ("
- + MAX_HEAPSIZE_GB_DEFAULT + "g).");
- }
-
- // apply multiplier if not too big (i.e. bigger than a long)
- if (Long.MAX_VALUE / memmax < multiplier)
- {
- memmax = MAX_HEAPSIZE_GB_DEFAULT * GIGABYTE;
- System.out.println("MemorySetting Property '"
- + MAX_HEAPSIZE_PROPERTY_NAME + "' (" + jvmmemmaxarg
- + ") too big, using default (" + MAX_HEAPSIZE_GB_DEFAULT
- + "g).");
- }
- else
- {
- memmax = multiplier * memmax;
+ + "') badly formatted or 0, using default ("
+ + MAX_HEAPSIZE_GB_DEFAULT + "g).", quiet);
}
// check at least minimum value (this accounts for negatives too)
if (memmax < APPLICATION_MIN_MEMORY)
{
memmax = APPLICATION_MIN_MEMORY;
- System.out.println("MemorySetting Property '"
+ setAdjustmentMessage("MemorySetting Property '"
+ MAX_HEAPSIZE_PROPERTY_NAME + "' (" + jvmmemmaxarg
+ ") too small, using minimum (" + APPLICATION_MIN_MEMORY
- + ").");
+ + ").", quiet);
}
}
else
{
// no need to warn if no setting
- // System.out.println("MemorySetting Property '" + maxHeapSizeProperty
+ // adjustmentMessage("MemorySetting Property '" + maxHeapSizeProperty
// + "' not
// set.");
}
// get max percent of physical memory, starting with default
float percent = MAX_HEAPSIZE_PERCENT_DEFAULT;
- if (jvmmempcarg == null)
+ if (jvmmempcarg == null && useProps)
{
jvmmempcarg = System.getProperty(MAX_HEAPSIZE_PERCENT_PROPERTY_NAME);
}
{
if (jvmmempc != null)
{
- float trypercent = Float.parseFloat(jvmmempc);
- if (0 < trypercent && trypercent <= 100f)
+ int trypercent = Integer.parseInt(jvmmempc);
+ if (0 <= trypercent && trypercent <= 100)
{
percent = trypercent;
}
else
{
- System.out.println("MemorySetting Property '"
+ setAdjustmentMessage("MemorySetting Property '"
+ MAX_HEAPSIZE_PERCENT_PROPERTY_NAME
- + "' should be in range 1..100. Using default " + percent
- + "%");
+ + "' should be in range 0..100. Using default " + percent
+ + "%", quiet);
}
}
} catch (NumberFormatException e)
{
- System.out.println("MemorySetting property '"
+ setAdjustmentMessage("MemorySetting property '"
+ MAX_HEAPSIZE_PERCENT_PROPERTY_NAME + "' (" + jvmmempcarg
- + ") badly formatted");
+ + ") badly formatted", quiet);
}
// catch everything in case of no com.sun.management.OperatingSystemMXBean
{
mempc = physicalMem - LEAVE_FREE_MIN_MEMORY;
reducedmempc = true;
- System.out.println("MemorySetting Property '"
+ setAdjustmentMessage("MemorySetting Property '"
+ MAX_HEAPSIZE_PERCENT_PROPERTY_NAME + "' (" + jvmmempcarg
+ ") too large. Leaving free space for OS and reducing to ("
- + mempc + ").");
+ + mempc + ").", quiet);
}
// check for minimum application memsize
{
if (reducedmempc)
{
- System.out.println("Reduced MemorySetting (" + mempc
+ setAdjustmentMessage("Reduced MemorySetting (" + mempc
+ ") too small. Increasing to application minimum ("
- + APPLICATION_MIN_MEMORY + ").");
+ + APPLICATION_MIN_MEMORY + ").", quiet);
}
else
{
- System.out.println("MemorySetting Property '"
+ setAdjustmentMessage("MemorySetting Property '"
+ MAX_HEAPSIZE_PERCENT_PROPERTY_NAME + "' ("
+ jvmmempcarg + ") too small. Using minimum ("
- + APPLICATION_MIN_MEMORY + ").");
+ + APPLICATION_MIN_MEMORY + ").", quiet);
}
mempc = APPLICATION_MIN_MEMORY;
}
{
// not enough memory for application, just try and grab what we can!
mempc = physicalMem;
- System.out.println(
+ setAdjustmentMessage(
"Not enough physical memory for application. Ignoring MemorySetting Property '"
+ MAX_HEAPSIZE_PERCENT_PROPERTY_NAME + "' ("
+ jvmmempcarg
+ "). Using maximum memory available ("
- + physicalMem + ").");
+ + physicalMem + ").",
+ quiet);
}
} catch (Throwable t)
{
memoryPercentError = true;
- System.out.println(
- "Problem calling GetMemory.getPhysicalMemory(). Likely to be problem with com.sun.management.OperatingSystemMXBean");
+ setAdjustmentMessage(
+ "Problem calling GetMemory.getPhysicalMemory(). Likely to be problem with com.sun.management.OperatingSystemMXBean",
+ quiet);
t.printStackTrace();
}
// == null))
&& memmax > NOMEM_MAX_HEAPSIZE_GB_DEFAULT * GIGABYTE)
{
- System.out.println(
+ setAdjustmentMessage(
"Capping maximum memory to " + NOMEM_MAX_HEAPSIZE_GB_DEFAULT
- + "g due to failure to read physical memory size.");
+ + "g due to failure to read physical memory size.",
+ quiet);
memmax = NOMEM_MAX_HEAPSIZE_GB_DEFAULT * GIGABYTE;
}
return maxMemLong;
}
-}
\ No newline at end of file
+ public static boolean isValidMemoryString(String text)
+ {
+ if (text.length() > 0)
+ {
+ char lastChar = text.charAt(text.length() - 1);
+ char[] otherChars = text.substring(0, text.length() - 1)
+ .toCharArray();
+ for (char c : otherChars)
+ {
+ if (c < '0' || c > '9')
+ {
+ return false;
+ }
+ }
+ if ((lastChar < '0' || lastChar > '9') && memorySuffixes
+ .indexOf(Character.toLowerCase(lastChar)) == -1)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public static long memoryStringToLong(String memString)
+ throws NumberFormatException
+ {
+ if (!isValidMemoryString(memString)) // not valid
+ {
+ throw (new NumberFormatException("Not a valid memory string"));
+ }
+ char suffix = Character
+ .toLowerCase(memString.charAt(memString.length() - 1));
+ if ('0' <= suffix && suffix <= '9') // no suffix
+ {
+ return Long.valueOf(memString);
+ }
+ if (memorySuffixes.indexOf(suffix) == -1) // suffix is unknown
+ {
+ return -1;
+ }
+
+ long multiplier = (long) Math.pow(2,
+ memorySuffixes.indexOf(suffix) * 10); // note order of suffixes in
+ // memorySuffixes important
+ // here!
+ // parse the arg. NumberFormatExceptions passed on to calling method
+ long mem = Long
+ .parseLong(memString.substring(0, memString.length() - 1));
+ if (mem == 0)
+ {
+ return 0;
+ }
+
+ // apply multiplier only if result is not too big (i.e. bigger than a long)
+ if (Long.MAX_VALUE / mem > multiplier)
+ {
+ return multiplier * mem;
+ }
+ else
+ {
+ // number too big for a Long. Limit to Long.MAX_VALUE
+ System.out.println("Memory parsing of '" + memString
+ + "' produces number too big. Limiting to Long.MAX_VALUE="
+ + Long.MAX_VALUE);
+ return Long.MAX_VALUE;
+ }
+ }
+
+ public static String memoryLongToString(long mem)
+ {
+ return memoryLongToString(mem, "%.3f");
+ }
+
+ public static String memoryLongToString(long mem, String format)
+ {
+ int exponent = 0;
+ float num = mem;
+ char suffix = 'b';
+
+ for (int i = 0; i < memorySuffixes.length(); i++)
+ {
+ char s = Character.toUpperCase(memorySuffixes.charAt(i));
+ if (mem < (long) Math.pow(2, exponent + 10)
+ || i == memorySuffixes.length() - 1) // last suffix
+ {
+ suffix = s;
+ num = (float) (mem / Math.pow(2, exponent));
+ break;
+ }
+ exponent += 10;
+ }
+
+ return String.format(format, num) + suffix;
+ }
+
+ private static String ADJUSTMENT_MESSAGE = null;
+
+ private static void setAdjustmentMessage(String reason, boolean quiet)
+ {
+ ADJUSTMENT_MESSAGE = reason;
+ if (!quiet)
+ {
+ System.out.println(reason);
+ }
+ }
+
+ public static void clearAdjustmentMessage()
+ {
+ ADJUSTMENT_MESSAGE = null;
+ }
+
+ public static String getAdjustmentMessage()
+ {
+ return ADJUSTMENT_MESSAGE;
+ }
+
+}
*/
package jalview.datamodel;
-import jalview.util.MapList;
-import jalview.util.MappingUtils;
-
import java.util.AbstractList;
import java.util.ArrayList;
import java.util.List;
+import jalview.util.MapList;
+import jalview.util.MappingUtils;
+
/**
* Stores mapping between the columns of a protein alignment and a DNA alignment
* and a list of individual codon to amino acid mappings between sequences.
{
return mapping;
}
-
+
/**
* Returns true if the mapping covers the full length of the given sequence.
* This allows us to distinguish the CDS that codes for a protein from
/**
* Adds any regions mapped to or from position {@code pos} in sequence
* {@code seq} to the given search results
- *
+ * Note: recommend first using the .covers(,true,true) to ensure mapping covers both sequences
* @param seq
* @param pos
* @param sr
}
/**
+ * Return the corresponding aligned or dataset dna sequence for given amino
+ * acid sequence, or null if not found. returns the sequence from the first
+ * mapping found that involves the protein sequence.
*
- * @param sequenceRef
- * @return null or corresponding aaSeq entry for dnaSeq entry
+ * @param aaSeqRef
+ * @return
*/
public SequenceI getDnaForAaSeq(SequenceI aaSeqRef)
{
/**
* Add search results for regions in other sequences that translate or are
- * translated from a particular position in seq
+ * translated from a particular position in seq (which may be an aligned or
+ * dataset sequence)
*
* @param seq
* @param index
public void markMappedRegion(SequenceI seq, int index,
SearchResultsI results)
{
- int[] codon;
SequenceI ds = seq.getDatasetSequence();
- for (SequenceToSequenceMapping ssm : mappings)
+ if (ds == null)
{
- if (ssm.covers(seq,true,true))
- {
- if ((ssm.fromSeq == seq || ssm.fromSeq == ds))
- {
- codon = ssm.mapping.map.locateInTo(index, index);
- if (codon != null)
- {
- for (int i = 0; i < codon.length; i += 2)
- {
- results.addResult(ssm.mapping.to, codon[i], codon[i + 1]);
- }
- }
- }
- else if ((ssm.mapping.to == seq || ssm.mapping.to == ds))
- {
- {
- codon = ssm.mapping.map.locateInFrom(index, index);
- if (codon != null)
- {
- for (int i = 0; i < codon.length; i += 2)
- {
- results.addResult(ssm.fromSeq, codon[i], codon[i + 1]);
- }
- }
- }
- }}
+ ds = seq;
}
- }
-
- /**
- * Returns the DNA codon positions (base 1) for the given position (base 1) in
- * a mapped protein sequence, or null if no mapping is found.
- *
- * Intended for use in aligning cDNA to match aligned protein. Only the first
- * mapping found is returned, so not suitable for use if multiple protein
- * sequences are mapped to the same cDNA (but aligning cDNA as protein is
- * ill-defined for this case anyway).
- *
- * @param seq
- * the DNA dataset sequence
- * @param aaPos
- * residue position (base 1) in a protein sequence
- * @return
- */
- public int[] getDnaPosition(SequenceI seq, int aaPos)
- {
- /*
- * Adapted from markMappedRegion().
- */
- MapList ml = null;
- int i = 0;
for (SequenceToSequenceMapping ssm : mappings)
{
- if (ssm.fromSeq == seq)
- {
- ml = getdnaToProt()[i];
- break;
+ if (ssm.covers(seq,true,true)) {
+ ssm.markMappedRegion(ds, index, results);
}
- i++;
}
- return ml == null ? null : ml.locateInFrom(aaPos, aaPos);
}
/**
* Two AlignedCodonFrame objects are equal if they hold the same ordered list
* of mappings
*
- * @see SequenceToSequenceMapping#
+ * @see SequenceToSequenceMapping#equals
*/
@Override
public boolean equals(Object obj)
{
return mappings;
}
+
+ /**
+ * Returns the first mapping found which is between the two given sequences,
+ * and covers the full extent of both.
+ *
+ * @param seq1
+ * @param seq2
+ * @return
+ */
+ public SequenceToSequenceMapping getCoveringMapping(SequenceI seq1,
+ SequenceI seq2)
+ {
+ for (SequenceToSequenceMapping mapping : mappings)
+ {
+ if (mapping.covers(seq2) && mapping.covers(seq1))
+ {
+ return mapping;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns the first mapping found which is between the given dataset sequence
+ * and another, is a triplet mapping (3:1 or 1:3), and covers the full extent
+ * of both sequences involved
+ *
+ * @param seq
+ * @return
+ */
+ public SequenceToSequenceMapping getCoveringCodonMapping(SequenceI seq)
+ {
+ for (SequenceToSequenceMapping mapping : mappings)
+ {
+ if (mapping.getMapping().getMap().isTripletMap()
+ && mapping.covers(seq))
+ {
+ if (mapping.fromSeq == seq
+ && mapping.covers(mapping.getMapping().getTo()))
+ {
+ return mapping;
+ }
+ else if (mapping.getMapping().getTo() == seq
+ && mapping.covers(mapping.fromSeq))
+ {
+ return mapping;
+ }
+ }
+ }
+ return null;
+ }
}
}
/**
- * Two SearchResults are considered equal if they contain the same matches in
- * the same order.
+ * Two SearchResults are considered equal if they contain the same matches
+ * (Sequence, start position, end position) in the same order
+ *
+ * @see Match#equals(Object)
*/
@Override
public boolean equals(Object obj)
int[] localRange = mf.getMappedPositions(start, end);
if (localRange == null)
{
+ // e.g. variant extending to stop codon so not mappable
return;
}
start = localRange[0];
import ext.edu.ucsf.rbvi.strucviz2.StructureManager;
import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
import jalview.bin.Cache;
+import jalview.bin.MemorySetting;
import jalview.ext.pymol.PymolManager;
import jalview.gui.Help.HelpId;
import jalview.gui.StructureViewer.ViewerType;
* Set Backups tab defaults
*/
loadLastSavedBackupsOptions();
+
+ /*
+ * Set Startup tab defaults
+ */
+
}
/**
Cache.applicationProperties.setProperty(
BackupFilesPresetEntry.SAVEDCONFIG, savedBFPE.toString());
+ /*
+ * Save Memory Settings
+ */
+ Cache.applicationProperties.setProperty(
+ MemorySetting.CUSTOMISED_SETTINGS,
+ Boolean.toString(customiseMemorySetting.isSelected()));
+ Cache.applicationProperties.setProperty(MemorySetting.MEMORY_JVMMEMPC,
+ Integer.toString(jvmMemoryPercentSlider.getValue()));
+ Cache.applicationProperties.setProperty(MemorySetting.MEMORY_JVMMEMMAX,
+ jvmMemoryMaxTextField.getText());
+
+ /*
+ * save and close Preferences
+ */
+
Cache.saveProperties();
Desktop.instance.doConfigureStructurePrefs();
try
import javax.swing.AbstractCellEditor;
import javax.swing.BorderFactory;
+import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JButton;
import javax.swing.JPasswordField;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
+import javax.swing.JSlider;
import javax.swing.JSpinner;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer;
import jalview.bin.Cache;
+import jalview.bin.MemorySetting;
import jalview.fts.core.FTSDataColumnPreferences;
import jalview.fts.core.FTSDataColumnPreferences.PreferenceSource;
import jalview.fts.service.pdb.PDBFTSRestClient;
import jalview.io.IntKeyStringValueEntry;
import jalview.util.MessageManager;
import jalview.util.Platform;
+import jalview.util.StringUtils;
/**
* Base class for the Preferences panel.
private JLabel messageLabel = new JLabel("", JLabel.CENTER);
+ /*
+ * Startup tab components
+ */
+
+ protected JCheckBox customiseMemorySetting = new JCheckBox();
+
+ protected JLabel exampleMemoryLabel = new JLabel();
+
+ protected JTextArea exampleMemoryMessageTextArea = new JTextArea();
+
+ protected JLabel maxMemoryLabel = new JLabel();
+
+ protected JLabel jvmMemoryPercentLabel = new JLabel();
+
+ protected JSlider jvmMemoryPercentSlider = new JSlider();
+
+ protected JLabel jvmMemoryPercentDisplay = new JLabel();
+
+ protected JLabel jvmMemoryMaxLabel = new JLabel();
+
+ protected JTextField jvmMemoryMaxTextField = new JTextField(null, 8);
+
+ protected JComboBox<Object> lafCombo = new JComboBox<>();
+
/**
* Creates a new GPreferences object.
*/
tabbedPane.add(initEditingTab(),
MessageManager.getString("label.editing"));
+ tabbedPane.add(initStartupTab(),
+ MessageManager.getString("label.startup"));
+
/*
* See WsPreferences for the real work of configuring this tab.
*/
updateBackupFilesExampleLabel();
}
+ /*
+ * Load the saved Memory settings
+ */
+ protected void loadLastSavedMemorySettings()
+ {
+ customiseMemorySetting.setSelected(
+ Cache.getDefault(MemorySetting.CUSTOMISED_SETTINGS, false));
+ jvmMemoryPercentSlider
+ .setValue(Cache.getDefault(MemorySetting.MEMORY_JVMMEMPC, 90));
+ jvmMemoryMaxTextField.setText(
+ Cache.getDefault(MemorySetting.MEMORY_JVMMEMMAX, "32g"));
+ }
+
private boolean warnAboutSuffixReverseChange()
{
BackupFilesPresetEntry bfpe = BackupFilesPresetEntry
&& nowSuffixTemplate.equals(savedSuffixTemplate);
}
+ /* Initialises the Startup tabbed panel.
+ *
+ * @return
+ * */
+
+ private JPanel initStartupTab()
+ {
+ JPanel startupTab = new JPanel();
+ startupTab.setBorder(
+ new TitledBorder(MessageManager.getString("label.memory")));
+ startupTab.setLayout(new GridBagLayout());
+
+ GridBagConstraints gbc = new GridBagConstraints();
+ gbc.weightx = 0.0;
+ gbc.weighty = 0.0;
+ gbc.anchor = GridBagConstraints.FIRST_LINE_START;
+ gbc.fill = GridBagConstraints.NONE;
+
+ initMemoryPanel();
+
+ gbc.gridheight = 1;
+ gbc.gridwidth = 3;
+
+ gbc.gridy = 0; // row 1
+ gbc.gridx = 0;
+ JLabel memoryText = new JLabel();
+ memoryText.setFont(LABEL_FONT_ITALIC);
+ memoryText
+ .setText(MessageManager.getString("label.memory_setting_text"));
+ startupTab.add(memoryText, gbc);
+
+ gbc.gridy++; // row 2
+ gbc.gridx = 0;
+ JPanel exampleMemoryPanel = new JPanel();
+ exampleMemoryPanel
+ .setLayout(new BoxLayout(exampleMemoryPanel, BoxLayout.Y_AXIS));
+ exampleMemoryPanel.setToolTipText(JvSwingUtils.wrapTooltip(true,
+ MessageManager.getString("label.memory_example_tooltip")));
+ JLabel exampleTextLabel = new JLabel();
+ exampleTextLabel
+ .setText(MessageManager.getString("label.memory_example_text"));
+ exampleTextLabel.setForeground(Color.GRAY);
+ exampleTextLabel.setFont(LABEL_FONT);
+ exampleMemoryPanel.add(exampleTextLabel);
+ exampleMemoryPanel.add(exampleMemoryLabel);
+ exampleMemoryPanel.setBackground(Color.WHITE);
+ exampleMemoryPanel.setBorder(BorderFactory.createEtchedBorder());
+ startupTab.add(exampleMemoryPanel, gbc);
+
+ gbc.gridy++; // row 3
+ gbc.gridx = 0;
+ startupTab.add(customiseMemorySetting, gbc);
+
+ gbc.gridy += 2; // row 4 with a gap
+ gbc.gridx = 0;
+ startupTab.add(maxMemoryLabel, gbc);
+
+ gbc.gridy += 2; // row 5
+ gbc.gridx = 0;
+ gbc.gridwidth = 1;
+ startupTab.add(jvmMemoryPercentLabel, gbc);
+ gbc.gridx++;
+ startupTab.add(jvmMemoryPercentSlider, gbc);
+ gbc.gridx++;
+ // gbc.weightx = 0.1;
+ startupTab.add(jvmMemoryPercentDisplay, gbc);
+ // gbc.weightx = 1.0;
+ gbc.gridwidth = 3;
+
+ gbc.gridy++; // row 6
+ gbc.gridx = 0;
+ startupTab.add(jvmMemoryMaxLabel, gbc);
+ gbc.gridx++;
+ startupTab.add(jvmMemoryMaxTextField, gbc);
+
+ gbc.gridy++; // row 7
+ gbc.gridx = 0;
+ gbc.gridwidth = 4;
+ exampleMemoryMessageTextArea.setBackground(startupTab.getBackground());
+ JScrollPane sp = new JScrollPane(exampleMemoryMessageTextArea);
+ sp.setBorder(BorderFactory.createEmptyBorder());
+ sp.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
+ sp.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER);
+ startupTab.add(sp, gbc);
+
+ // fill empty space to push widget to top left
+ gbc.gridy++;
+ gbc.weighty = 1.0;
+ gbc.gridx = 100;
+ gbc.gridwidth = 1;
+ gbc.weightx = 1.0;
+ startupTab.add(new JPanel(), gbc);
+
+ setMemoryPercentDisplay();
+ memoryOptionsSetEnabled();
+ return startupTab;
+ }
+
+ private void initMemoryPanel()
+ {
+ // Enable memory settings checkbox
+ customiseMemorySetting.setFont(LABEL_FONT_BOLD);
+ customiseMemorySetting.setText(
+ MessageManager.getString("label.customise_memory_settings"));
+ customiseMemorySetting.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ memoryOptionsSetEnabled();
+ }
+ });
+
+ loadLastSavedMemorySettings();
+
+ exampleMemoryLabel.setFont(LABEL_FONT_BOLD);
+ exampleMemoryLabel.setBackground(Color.WHITE);
+
+ maxMemoryLabel = new JLabel(
+ MessageManager.getString("label.maximum_memory_used"));
+ maxMemoryLabel.setFont(LABEL_FONT_BOLD);
+
+ // Maximum memory percentage slider
+ jvmMemoryPercentLabel.setFont(LABEL_FONT);
+ jvmMemoryPercentLabel.setText(
+ MessageManager.getString("label.percent_of_physical_memory"));
+ jvmMemoryPercentSlider.setPaintLabels(true);
+ jvmMemoryPercentSlider.setPaintTicks(true);
+ jvmMemoryPercentSlider.setPaintTrack(true);
+ jvmMemoryPercentSlider.setMajorTickSpacing(50);
+ jvmMemoryPercentSlider.setMinorTickSpacing(10);
+ jvmMemoryPercentSlider.addChangeListener(new ChangeListener()
+ {
+ @Override
+ public void stateChanged(ChangeEvent e)
+ {
+ setMemoryPercentDisplay();
+ }
+ });
+ jvmMemoryPercentDisplay.setFont(LABEL_FONT);
+ setMemoryPercentDisplay();
+
+ // Maximum memory cap textbox
+ jvmMemoryMaxLabel.setFont(LABEL_FONT);
+ jvmMemoryMaxLabel
+ .setText(MessageManager.getString("label.maximum_memory"));
+ initMemoryMaxTextField();
+
+ exampleMemoryMessageTextArea.setFont(LABEL_FONT_ITALIC);
+ exampleMemoryMessageTextArea.setForeground(Color.GRAY);
+ exampleMemoryMessageTextArea.setEditable(false);
+ exampleMemoryMessageTextArea.setLineWrap(true);
+ exampleMemoryMessageTextArea.setWrapStyleWord(true);
+ exampleMemoryMessageTextArea.setText(" ");
+ exampleMemoryMessageTextArea.setRows(2);
+ exampleMemoryMessageTextArea.setColumns(40);
+
+ setExampleMemoryLabel();
+ }
+
+ private void initMemoryMaxTextField()
+ {
+ jvmMemoryMaxTextField.setToolTipText(
+ MessageManager.getString("label.maximum_memory_tooltip"));
+ jvmMemoryMaxTextField.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent arg0)
+ {
+ validateMemoryMaxTextField();
+ setExampleMemoryLabel();
+ }
+ });
+
+ jvmMemoryMaxTextField.addKeyListener(new KeyListener()
+ {
+ @Override
+ public void keyReleased(KeyEvent e)
+ {
+ validateMemoryMaxTextField();
+ setExampleMemoryLabel();
+ }
+
+ @Override
+ public void keyPressed(KeyEvent e)
+ {
+ }
+
+ // try and stop invalid typing
+ @Override
+ public void keyTyped(KeyEvent e)
+ {
+ char c = Character.toLowerCase(e.getKeyChar());
+ String text = jvmMemoryMaxTextField.getText();
+ String suffixes = "tgmkb";
+ int pos = jvmMemoryMaxTextField.getCaretPosition();
+ int suffixPos = StringUtils.firstCharPosIgnoreCase(text, suffixes);
+ if (!((('0' <= c && c <= '9')
+ && (suffixPos == -1 || pos <= suffixPos)) // digits only allowed
+ // before suffix
+ || (suffixes.indexOf(Character.toLowerCase(c)) >= 0 // valid
+ // suffix
+ && pos == text.length() // at end of text and
+ && suffixPos == -1) // there isn't already one
+ ))
+ {
+ // don't process
+ e.consume();
+ }
+ }
+ });
+ }
+
+ private boolean isMemoryMaxTextFieldValid()
+ {
+ return MemorySetting
+ .isValidMemoryString(jvmMemoryMaxTextField.getText());
+ }
+
+ private void validateMemoryMaxTextField()
+ {
+ if (isMemoryMaxTextFieldValid())
+ {
+ jvmMemoryMaxTextField.setBackground(Color.WHITE);
+ }
+ else
+ {
+ jvmMemoryMaxTextField.setBackground(Color.PINK);
+ }
+ }
+
+ private void setMemoryPercentDisplay()
+ {
+ jvmMemoryPercentDisplay
+ .setText(jvmMemoryPercentSlider.getValue() + "%");
+ setExampleMemoryLabel();
+ }
+
+ private void setExampleMemoryLabel()
+ {
+ boolean selected = customiseMemorySetting.isSelected();
+ int jvmmempc = jvmMemoryPercentSlider.getValue();
+ String jvmmemmax = jvmMemoryMaxTextField.getText();
+
+ long mem;
+ if (selected && (0 <= jvmmempc && jvmmempc <= 100)
+ && MemorySetting.isValidMemoryString(jvmmemmax))
+ {
+ mem = MemorySetting.getMemorySetting(jvmmemmax,
+ String.valueOf(jvmmempc), false, true);
+ }
+ else
+ {
+ mem = MemorySetting.getMemorySetting(null, null, false, true);
+ }
+ exampleMemoryLabel.setText(MemorySetting.memoryLongToString(mem));
+ String message = MemorySetting.getAdjustmentMessage();
+ exampleMemoryMessageTextArea.setText(
+ MessageManager.getString("label.adjustments_for_this_computer")
+ + ": "
+ + (message == null
+ ? MessageManager.getString("label.none")
+ : message));
+ }
+
+ private void memoryOptionsSetEnabled()
+ {
+ boolean enabled = customiseMemorySetting.isSelected();
+ // leave exampleMemoryLabel enabled always
+ maxMemoryLabel.setEnabled(enabled);
+ jvmMemoryPercentLabel.setEnabled(enabled);
+ jvmMemoryPercentSlider.setEnabled(enabled);
+ jvmMemoryPercentDisplay.setEnabled(enabled);
+ jvmMemoryMaxLabel.setEnabled(enabled);
+ jvmMemoryMaxTextField.setEnabled(enabled);
+ exampleMemoryMessageTextArea.setEnabled(enabled);
+ setExampleMemoryLabel();
+ }
+
/**
* Initialises the Backups tabbed panel.
*
package jalview.util;
import java.awt.Image;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import javax.swing.ImageIcon;
-import jalview.bin.Cache;
-
public class ChannelProperties
{
- private static final String CHANNEL_PROPERTIES_FILENAME = "/channel.props";
+ public static final String CHANNEL_PROPERTIES_FILENAME = "channel.props";
- private static final Properties channelProps;
+ private static Properties channelProps;
private static final Properties defaultProps;
// load channel_properties
Properties tryChannelProps = new Properties();
URL channelPropsURL = ChannelProperties.class
- .getResource(CHANNEL_PROPERTIES_FILENAME);
+ .getResource("/" + CHANNEL_PROPERTIES_FILENAME);
if (channelPropsURL == null)
{
// complete failure of channel_properties, set all properties to defaults
- System.err.println("Failed to find '" + CHANNEL_PROPERTIES_FILENAME
+ System.err.println("Failed to find '/" + CHANNEL_PROPERTIES_FILENAME
+ "' file at '"
+ (channelPropsURL == null ? "null"
: channelPropsURL.toString())
channelPropsIS.close();
} catch (IOException e)
{
- Cache.log.warn(e.getMessage());
+ System.err.println(e.getMessage());
// return false;
}
}
Image logo = null;
String path = defaultProps.getProperty("logo." + size);
URL imageURL = ChannelProperties.class.getResource(path);
- logo = new ImageIcon(imageURL).getImage();
+ ImageIcon imgIcon = imageURL == null ? null
+ : new ImageIcon(imageURL);
+ logo = imgIcon == null ? null : imgIcon.getImage();
if (logo != null)
{
iconList.add(logo);
}
}
+ protected static void loadProps(File dir)
+ {
+ File channelPropsFile = new File(dir, CHANNEL_PROPERTIES_FILENAME);
+ if (channelPropsFile.exists())
+ {
+ try
+ {
+ InputStream is = new FileInputStream(channelPropsFile);
+ channelProps.load(is);
+ } catch (FileNotFoundException e)
+ {
+ System.err.println(e.getMessage());
+ } catch (IOException e)
+ {
+ System.err.println(e.getMessage());
+ }
+ }
+ }
+
private static Properties channelProps()
{
return channelProps;
}
URL imageURL = ChannelProperties.class.getResource(path);
- img = new ImageIcon(imageURL).getImage();
+ ImageIcon imgIcon = imageURL == null ? null : new ImageIcon(imageURL);
+ img = imgIcon == null ? null : imgIcon.getImage();
if (img == null)
{
System.err.println(
--- /dev/null
+package jalview.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Properties;
+
+public class LaunchUtils
+{
+
+ public static void loadChannelProps(File dir)
+ {
+ ChannelProperties.loadProps(dir);
+ }
+
+ private static Properties userPreferences = null;
+
+ public static String getUserPreference(String key)
+ {
+ if (userPreferences == null)
+ {
+ String channelPrefsFilename = ChannelProperties
+ .getProperty("preferences.filename");
+ if (channelPrefsFilename == null)
+ {
+ return null;
+ }
+ File propertiesFile = new File(System.getProperty("user.home"),
+ channelPrefsFilename);
+ if (!propertiesFile.exists())
+ {
+ return null;
+ }
+ try
+ {
+ userPreferences = new Properties();
+ userPreferences.load(new FileInputStream(propertiesFile));
+ } catch (FileNotFoundException e)
+ {
+ // didn't find user preferences file
+ return null;
+ } catch (IOException e)
+ {
+ System.err.println(e.getMessage());
+ return null;
+ }
+ }
+ return userPreferences.getProperty(key);
+ }
+
+ public static boolean getBooleanUserPreference(String key)
+ {
+ return Boolean.parseBoolean(getUserPreference(key));
+ }
+}
int mappedEndResidue = 0;
for (AlignedCodonFrame acf : codonFrames)
{
+ // rather than use acf.getCoveringMapping() we iterate through all
+ // mappings to make sure all CDS are selected for a protein
for (SequenceToSequenceMapping map: acf.getMappings())
{
if (map.covers(selected) && map.covers(seq))
{
for (AlignedCodonFrame acf : mappings)
{
- SequenceI mappedSeq = mappingToNucleotide ? acf.getDnaForAaSeq(seq)
- : acf.getAaForDnaSeq(seq);
- if (mappedSeq != null)
- {
for (SequenceI seq2 : mapTo.getSequences())
{
- if (seq2.getDatasetSequence() == mappedSeq)
+ /*
+ * the corresponding peptide / CDS is the one for which there is
+ * a complete ('covering') mapping to 'seq'
+ */
+ SequenceI peptide = mappingToNucleotide ? seq2 : seq;
+ SequenceI cds = mappingToNucleotide ? seq : seq2;
+ SequenceToSequenceMapping s2s = acf.getCoveringMapping(cds,
+ peptide);
+ if (s2s != null)
{
mappedOrder.add(seq2);
j++;
break;
}
}
- }
}
}
if (colsel == null)
{
- return; // mappedColumns;
+ return;
}
char fromGapChar = mapFrom.getAlignment().getGapCharacter();
mapHiddenColumns(regions.next(), codonFrames, newHidden,
fromSequences, toSequences, fromGapChar);
}
- return; // mappedColumns;
+ return;
}
/**
*/
for (SequenceI toSeq : toSequences)
{
- if (toSeq.getDatasetSequence() == mappedSeq)
+ if (toSeq.getDatasetSequence() == mappedSeq
+ && mappedStartResidue >= toSeq.getStart()
+ && mappedEndResidue <= toSeq.getEnd())
{
int mappedStartCol = toSeq.findIndex(mappedStartResidue);
int mappedEndCol = toSeq.findIndex(mappedEndResidue);
{
text = text.substring(0, endTag);
}
-
+
if (startTag == -1 && (text.contains("<") || text.contains(">")))
{
text = text.replaceAll("<", "<");
}
/**
- * Answers the input string with any occurrences of the 'encodeable' characters
- * replaced by their URL encoding
+ * Answers the input string with any occurrences of the 'encodeable'
+ * characters replaced by their URL encoding
*
* @param s
* @param encodable
}
return enc;
}
+
+ public static int firstCharPosIgnoreCase(String text, String chars)
+ {
+ int min = text.length() + 1;
+ for (char c : chars.toLowerCase().toCharArray())
+ {
+ int i = text.toLowerCase().indexOf(c);
+ if (0 <= i && i < min)
+ {
+ min = i;
+ }
+ }
+ return min < text.length() + 1 ? min : -1;
+ }
}
import jalview.api.FeatureColourI;
import jalview.api.FeaturesDisplayedI;
import jalview.datamodel.AlignedCodonFrame;
+import jalview.datamodel.AlignedCodonFrame.SequenceToSequenceMapping;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.MappedFeatures;
-import jalview.datamodel.Mapping;
import jalview.datamodel.SearchResultMatchI;
import jalview.datamodel.SearchResults;
import jalview.datamodel.SearchResultsI;
* todo: direct lookup of CDS for peptide and vice-versa; for now,
* have to search through an unordered list of mappings for a candidate
*/
- Mapping mapping = null;
+ SequenceToSequenceMapping mapping = null;
SequenceI mapFrom = null;
for (AlignedCodonFrame acf : mappings)
{
- mapping = acf.getMappingForSequence(sequence);
- if (mapping == null || !mapping.getMap().isTripletMap())
+ mapping = acf.getCoveringCodonMapping(ds);
+ if (mapping == null)
{
- continue; // we are only looking for 3:1 or 1:3 mappings
+ continue;
}
SearchResultsI sr = new SearchResults();
- acf.markMappedRegion(ds, pos, sr);
+ mapping.markMappedRegion(ds, pos, sr);
for (SearchResultMatchI match : sr.getResults())
{
int fromRes = match.getStart();
}
}
- return new MappedFeatures(mapping, mapFrom, pos, residue, result);
+ return new MappedFeatures(mapping.getMapping(), mapFrom, pos, residue, result);
}
@Override
JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
}
- private static final int TEST_TIMEOUT = 9000; // Note longer timeout needed
+ private static final int TEST_TIMEOUT = 10500; // Note longer timeout needed
// on
// full test run than on
// individual tests
@Test(groups = { "Functional" }, dataProvider = "hidpiScaleArguments")
public void testHiDPISettings(int scale)
{
- if (Platform.isLinux())
+ if (!Platform.isLinux())
{
throw new SkipException(
"Not linux platform, not testing actual scaling with "
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertFalse;
+import static org.testng.AssertJUnit.assertNotNull;
import static org.testng.AssertJUnit.assertNull;
import static org.testng.AssertJUnit.assertSame;
import static org.testng.AssertJUnit.assertTrue;
import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
-import jalview.gui.JvOptionPane;
-import jalview.util.MapList;
-
import java.util.Arrays;
import java.util.List;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
+import jalview.datamodel.AlignedCodonFrame.SequenceToSequenceMapping;
+import jalview.gui.JvOptionPane;
+import jalview.util.MapList;
+
public class AlignedCodonFrameTest
{
public void testGetMappedRegion()
{
// introns lower case, exons upper case
- final Sequence seq1 = new Sequence("Seq1", "c-G-TA-gC-gT-T");
- seq1.createDatasetSequence();
- final Sequence seq2 = new Sequence("Seq2", "-TA-gG-Gg-CG-a");
- seq2.createDatasetSequence();
+ final Sequence dna1 = new Sequence("Seq1/10-18", "c-G-TA-gC-gT-T");
+ dna1.createDatasetSequence();
+ final Sequence dna2 = new Sequence("Seq2/20-28", "-TA-gG-Gg-CG-a");
+ dna2.createDatasetSequence();
- final Sequence aseq1 = new Sequence("Seq1", "-P-R");
- aseq1.createDatasetSequence();
- final Sequence aseq2 = new Sequence("Seq2", "-LY-Q");
- aseq2.createDatasetSequence();
+ final Sequence pep1 = new Sequence("Seq1/3-4", "-P-R");
+ pep1.createDatasetSequence();
+ final Sequence pep2 = new Sequence("Seq2/7-9", "-LY-Q");
+ pep2.createDatasetSequence();
/*
* First with no mappings
*/
AlignedCodonFrame acf = new AlignedCodonFrame();
- assertNull(acf.getMappedRegion(seq1, aseq1, 1));
+ assertNull(acf.getMappedRegion(dna1, pep1, 3));
/*
* Set up the mappings for the exons (upper-case bases)
* Note residue Q is unmapped
*/
- MapList map = new MapList(new int[] { 2, 4, 6, 6, 8, 9 }, new int[] {
- 1, 2 }, 3, 1);
- acf.addMap(seq1.getDatasetSequence(), aseq1.getDatasetSequence(), map);
- map = new MapList(new int[] { 1, 2, 4, 5, 7, 8 }, new int[] { 1, 2 },
+ MapList map1 = new MapList(new int[] { 11, 13, 15, 15, 17, 18 }, new int[] {
+ 3, 4 }, 3, 1);
+ acf.addMap(dna1.getDatasetSequence(), pep1.getDatasetSequence(), map1);
+ MapList map2 = new MapList(new int[] { 20, 21, 23, 24, 26, 27 }, new int[] { 7, 9 },
3, 1);
- acf.addMap(seq2.getDatasetSequence(), aseq2.getDatasetSequence(), map);
+ acf.addMap(dna2.getDatasetSequence(), pep2.getDatasetSequence(), map2);
- assertArrayEquals(new int[] { 2, 4 },
- acf.getMappedRegion(seq1, aseq1, 1));
- assertArrayEquals(new int[] { 6, 6, 8, 9 },
- acf.getMappedRegion(seq1, aseq1, 2));
- assertArrayEquals(new int[] { 1, 2, 4, 4 },
- acf.getMappedRegion(seq2, aseq2, 1));
- assertArrayEquals(new int[] { 5, 5, 7, 8 },
- acf.getMappedRegion(seq2, aseq2, 2));
+ /*
+ * get codon positions for peptide position
+ */
+ assertArrayEquals(new int[] { 11, 13 },
+ acf.getMappedRegion(dna1, pep1, 3));
+ assertArrayEquals(new int[] { 15, 15, 17, 18 },
+ acf.getMappedRegion(dna1, pep1, 4));
+ assertArrayEquals(new int[] { 20, 21, 23, 23 },
+ acf.getMappedRegion(dna2, pep2, 7));
+ assertArrayEquals(new int[] { 24, 24, 26, 27 },
+ acf.getMappedRegion(dna2, pep2, 8));
/*
- * No mapping from seq2 to Q
+ * No mapping from dna2 to Q
*/
- assertNull(acf.getMappedRegion(seq2, aseq2, 3));
+ assertNull(acf.getMappedRegion(dna2, pep2, 9));
/*
- * No mapping from sequence 1 to sequence 2
+ * No mapping from dna1 to pep2
*/
- assertNull(acf.getMappedRegion(seq1, aseq2, 1));
+ assertNull(acf.getMappedRegion(dna1, pep2, 7));
+
+ /*
+ * get peptide position for codon position
+ */
+ assertArrayEquals(new int[] { 3, 3 },
+ acf.getMappedRegion(pep1, dna1, 11));
+ assertArrayEquals(new int[] { 3, 3 },
+ acf.getMappedRegion(pep1, dna1, 12));
+ assertArrayEquals(new int[] { 3, 3 },
+ acf.getMappedRegion(pep1, dna1, 13));
+ assertNull(acf.getMappedRegion(pep1, dna1, 14)); // intron base, not mapped
+
}
@Test(groups = { "Functional" })
assertEquals(1, acf.getMappingsFromSequence(seq1).size());
assertSame(before, acf.getMappingsFromSequence(seq1).get(0));
}
+
+ @Test(groups = { "Functional" })
+ public void testGetCoveringMapping()
+ {
+ SequenceI dna = new Sequence("dna", "acttcaATGGCGGACtaattt");
+ SequenceI cds = new Sequence("cds/7-15", "ATGGCGGAC");
+ cds.setDatasetSequence(dna);
+ SequenceI pep = new Sequence("pep", "MAD");
+
+ /*
+ * with null argument or no mappings
+ */
+ AlignedCodonFrame acf = new AlignedCodonFrame();
+ assertNull(acf.getCoveringMapping(null, null));
+ assertNull(acf.getCoveringMapping(dna, null));
+ assertNull(acf.getCoveringMapping(null, pep));
+ assertNull(acf.getCoveringMapping(dna, pep));
+
+ /*
+ * with a non-covering mapping e.g. overlapping exon
+ */
+ MapList map = new MapList(new int[] { 7, 9 }, new int[] {
+ 1, 1 }, 3, 1);
+ acf.addMap(dna, pep, map);
+ assertNull(acf.getCoveringMapping(dna, pep));
+
+ acf = new AlignedCodonFrame();
+ MapList map2 = new MapList(new int[] { 13, 18 }, new int[] {
+ 2, 2 }, 3, 1);
+ acf.addMap(dna, pep, map2);
+ assertNull(acf.getCoveringMapping(dna, pep));
+
+ /*
+ * with a covering mapping from CDS (dataset) to protein
+ */
+ acf = new AlignedCodonFrame();
+ MapList map3 = new MapList(new int[] { 7, 15 }, new int[] {
+ 1, 3 }, 3, 1);
+ acf.addMap(dna, pep, map3);
+ assertNull(acf.getCoveringMapping(dna, pep));
+ SequenceToSequenceMapping mapping = acf.getCoveringMapping(cds, pep);
+ assertNotNull(mapping);
+
+ /*
+ * with a mapping that extends to stop codon
+ */
+ acf = new AlignedCodonFrame();
+ MapList map4 = new MapList(new int[] { 7, 18 }, new int[] {
+ 1, 3 }, 3, 1);
+ acf.addMap(dna, pep, map4);
+ assertNull(acf.getCoveringMapping(dna, pep));
+ assertNull(acf.getCoveringMapping(cds, pep));
+ SequenceI cds2 = new Sequence("cds/7-18", "ATGGCGGACtaa");
+ cds2.setDatasetSequence(dna);
+ mapping = acf.getCoveringMapping(cds2, pep);
+ assertNotNull(mapping);
+ }
+
+ /**
+ * Test the method that adds mapped positions to SearchResults
+ */
+ @Test(groups = { "Functional" })
+ public void testMarkMappedRegion()
+ {
+ // introns lower case, exons upper case
+ final Sequence dna1 = new Sequence("Seq1/10-18", "c-G-TA-gC-gT-T");
+ dna1.createDatasetSequence();
+ final Sequence dna2 = new Sequence("Seq2/20-28", "-TA-gG-Gg-CG-a");
+ dna2.createDatasetSequence();
+
+ final Sequence pep1 = new Sequence("Seq1/3-4", "-P-R");
+ pep1.createDatasetSequence();
+ final Sequence pep2 = new Sequence("Seq2/7-9", "-LY-Q");
+ pep2.createDatasetSequence();
+
+ /*
+ * First with no mappings
+ */
+ AlignedCodonFrame acf = new AlignedCodonFrame();
+ SearchResults sr = new SearchResults();
+ acf.markMappedRegion(dna1, 12, sr);
+ assertTrue(sr.isEmpty());
+
+ /*
+ * Set up the mappings for the exons (upper-case bases)
+ * Note residue Q is unmapped
+ */
+ MapList map1 = new MapList(new int[] { 11, 13, 15, 15, 17, 18 }, new int[] {
+ 3, 4 }, 3, 1);
+ acf.addMap(dna1.getDatasetSequence(), pep1.getDatasetSequence(), map1);
+ MapList map2 = new MapList(new int[] { 20, 21, 23, 24, 26, 27 }, new int[] { 7, 8 },
+ 3, 1);
+ acf.addMap(dna2.getDatasetSequence(), pep2.getDatasetSequence(), map2);
+
+ /*
+ * intron bases are not mapped
+ */
+ acf.markMappedRegion(dna1, 10, sr);
+ assertTrue(sr.isEmpty());
+
+ /*
+ * Q is not mapped
+ */
+ acf.markMappedRegion(pep2, 9, sr);
+ assertTrue(sr.isEmpty());
+
+ /*
+ * mark peptide position for exon position (of aligned sequence)
+ */
+ acf.markMappedRegion(dna1, 11, sr);
+ SearchResults expected = new SearchResults();
+ expected.addResult(pep1.getDatasetSequence(), 3, 3);
+ assertEquals(sr, expected);
+
+ /*
+ * mark peptide position for exon position of dataset sequence - same result
+ */
+ sr = new SearchResults();
+ acf.markMappedRegion(dna1.getDatasetSequence(), 11, sr);
+ assertEquals(sr, expected);
+
+ /*
+ * marking the same position a second time should not create a duplicate match
+ */
+ acf.markMappedRegion(dna1.getDatasetSequence(), 12, sr);
+ assertEquals(sr, expected);
+
+ /*
+ * mark exon positions for peptide position (of aligned sequence)
+ */
+ sr = new SearchResults();
+ acf.markMappedRegion(pep2, 7, sr); // codon positions 20, 21, 23
+ expected = new SearchResults();
+ expected.addResult(dna2.getDatasetSequence(), 20, 21);
+ expected.addResult(dna2.getDatasetSequence(), 23, 23);
+ assertEquals(sr, expected);
+
+ /*
+ * add another codon to the same SearchResults
+ */
+ acf.markMappedRegion(pep1.getDatasetSequence(), 4, sr); // codon positions 15, 17, 18
+ expected.addResult(dna1.getDatasetSequence(), 15, 15);
+ expected.addResult(dna1.getDatasetSequence(), 17, 18);
+ assertEquals(sr, expected);
+ }
+
+ @Test(groups = { "Functional" })
+ public void testGetCoveringCodonMapping()
+ {
+ SequenceI dna = new Sequence("dna/10-30", "acttcaATGGCGGACtaattt");
+ // CDS sequence with its own dataset sequence (JAL-3763)
+ SequenceI cds = new Sequence("cds/1-9", "-A--TGGC-GGAC");
+ cds.createDatasetSequence();
+ SequenceI pep = new Sequence("pep/1-3", "MAD");
+
+ /*
+ * with null argument or no mappings
+ */
+ AlignedCodonFrame acf = new AlignedCodonFrame();
+ assertNull(acf.getCoveringCodonMapping(null));
+ assertNull(acf.getCoveringCodonMapping(dna));
+ assertNull(acf.getCoveringCodonMapping(pep));
+
+ /*
+ * with a non-covering mapping e.g. overlapping exon
+ */
+ MapList map = new MapList(new int[] { 16, 18 }, new int[] {
+ 1, 1 }, 3, 1);
+ acf.addMap(dna, pep, map);
+ assertNull(acf.getCoveringCodonMapping(dna));
+ assertNull(acf.getCoveringCodonMapping(pep));
+
+ acf = new AlignedCodonFrame();
+ MapList map2 = new MapList(new int[] { 13, 18 }, new int[] {
+ 2, 2 }, 3, 1);
+ acf.addMap(dna, pep, map2);
+ assertNull(acf.getCoveringCodonMapping(dna));
+ assertNull(acf.getCoveringCodonMapping(pep));
+
+ /*
+ * with a covering mapping from CDS (dataset) to protein
+ */
+ acf = new AlignedCodonFrame();
+ MapList map3 = new MapList(new int[] { 1, 9 }, new int[] {
+ 1, 3 }, 3, 1);
+ acf.addMap(cds.getDatasetSequence(), pep, map3);
+ assertNull(acf.getCoveringCodonMapping(dna));
+ SequenceToSequenceMapping mapping = acf.getCoveringCodonMapping(pep);
+ assertNotNull(mapping);
+ SequenceToSequenceMapping mapping2 = acf.getCoveringCodonMapping(cds.getDatasetSequence());
+ assertSame(mapping, mapping2);
+
+ /*
+ * with a mapping that extends to stop codon
+ * (EMBL CDS location often includes the stop codon)
+ * - getCoveringCodonMapping is lenient (doesn't require exact length match)
+ */
+ SequenceI cds2 = new Sequence("cds/1-12", "-A--TGGC-GGACTAA");
+ cds2.createDatasetSequence();
+ acf = new AlignedCodonFrame();
+ MapList map4 = new MapList(new int[] { 1, 12 }, new int[] {
+ 1, 3 }, 3, 1);
+ acf.addMap(cds2, pep, map4);
+ mapping = acf.getCoveringCodonMapping(cds2.getDatasetSequence());
+ assertNotNull(mapping);
+ mapping2 = acf.getCoveringCodonMapping(pep);
+ assertSame(mapping, mapping2);
+ }
}
{
Cache.initLogger();
}
-
+
@BeforeClass(alwaysRun = true)
public void setUpJvOptionPane()
{
assertArrayEquals(new int[] { 5, 6 }, merged.get(1));
assertArrayEquals(new int[] { 12, 8 }, merged.get(2));
assertArrayEquals(new int[] { 8, 7 }, merged.get(3));
-
+
// 'subsumed' ranges are preserved
ranges.clear();
ranges.add(new int[] { 10, 30 });
- ranges.add(new int[] { 15, 25 });
+ ranges.add(new int[] { 15, 25 });
+
merged = MapList.coalesceRanges(ranges);
assertEquals(2, merged.size());
assertArrayEquals(new int[] { 10, 30 }, merged.get(0));
protein.setCodonFrames(acfList);
/*
- * Select Seq1 and Seq3 in the protein (startRes=endRes=0)
+ * Select Seq1 and Seq3 in the protein
*/
SequenceGroup sg = new SequenceGroup();
sg.setColourText(true);
sg.setOutlineColour(Color.LIGHT_GRAY);
sg.addSequence(protein.getSequenceAt(0), false);
sg.addSequence(protein.getSequenceAt(2), false);
+ sg.setEndRes(protein.getWidth() - 1);
/*
* Verify the mapped sequence group in dna
assertSame(cdna.getSequenceAt(0), mappedGroup.getSequences().get(0));
assertSame(cdna.getSequenceAt(2), mappedGroup.getSequences().get(1));
assertEquals(0, mappedGroup.getStartRes());
- assertEquals(2, mappedGroup.getEndRes());
+ assertEquals(2, mappedGroup.getEndRes()); // 3 columns (1 codon)
/*
* Verify mapping sequence group from dna to protein
overlap = MappingUtils.findOverlap(ranges, 13, 15);
assertNull(overlap);
}
+
+ /**
+ * Test mapping a sequence group where sequences in and outside the group
+ * share a dataset sequence (e.g. alternative CDS for the same gene)
+ * <p>
+ * This scenario doesn't arise after JAL-3763 changes, but test left as still valid
+ * @throws IOException
+ */
+ @Test(groups = { "Functional" })
+ public void testMapSequenceGroup_sharedDataset() throws IOException
+ {
+ /*
+ * Set up dna and protein Seq1/2/3 with mappings (held on the protein
+ * viewport). CDS sequences share the same 'gene' dataset sequence.
+ */
+ SequenceI dna = new Sequence("dna", "aaatttgggcccaaatttgggccc");
+ SequenceI cds1 = new Sequence("cds1/1-6", "aaattt");
+ SequenceI cds2 = new Sequence("cds1/4-9", "tttggg");
+ SequenceI cds3 = new Sequence("cds1/19-24", "gggccc");
+
+ cds1.setDatasetSequence(dna);
+ cds2.setDatasetSequence(dna);
+ cds3.setDatasetSequence(dna);
+
+ SequenceI pep1 = new Sequence("pep1", "KF");
+ SequenceI pep2 = new Sequence("pep2", "FG");
+ SequenceI pep3 = new Sequence("pep3", "GP");
+ pep1.createDatasetSequence();
+ pep2.createDatasetSequence();
+ pep3.createDatasetSequence();
+
+ /*
+ * add mappings from coding positions of dna to respective peptides
+ */
+ AlignedCodonFrame acf = new AlignedCodonFrame();
+ acf.addMap(dna, pep1,
+ new MapList(new int[]
+ { 1, 6 }, new int[] { 1, 2 }, 3, 1));
+ acf.addMap(dna, pep2,
+ new MapList(new int[]
+ { 4, 9 }, new int[] { 1, 2 }, 3, 1));
+ acf.addMap(dna, pep3,
+ new MapList(new int[]
+ { 19, 24 }, new int[] { 1, 2 }, 3, 1));
+
+ List<AlignedCodonFrame> acfList = Arrays
+ .asList(new AlignedCodonFrame[]
+ { acf });
+
+ AlignmentI cdna = new Alignment(new SequenceI[] { cds1, cds2, cds3 });
+ AlignmentI protein = new Alignment(
+ new SequenceI[]
+ { pep1, pep2, pep3 });
+ AlignViewportI cdnaView = new AlignViewport(cdna);
+ AlignViewportI peptideView = new AlignViewport(protein);
+ protein.setCodonFrames(acfList);
+
+ /*
+ * Select pep1 and pep3 in the protein alignment
+ */
+ SequenceGroup sg = new SequenceGroup();
+ sg.setColourText(true);
+ sg.setIdColour(Color.GREEN);
+ sg.setOutlineColour(Color.LIGHT_GRAY);
+ sg.addSequence(pep1, false);
+ sg.addSequence(pep3, false);
+ sg.setEndRes(protein.getWidth() - 1);
+
+ /*
+ * Verify the mapped sequence group in dna is cds1 and cds3
+ */
+ SequenceGroup mappedGroup = MappingUtils.mapSequenceGroup(sg,
+ peptideView, cdnaView);
+ assertTrue(mappedGroup.getColourText());
+ assertSame(sg.getIdColour(), mappedGroup.getIdColour());
+ assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
+ assertEquals(2, mappedGroup.getSequences().size());
+ assertSame(cds1, mappedGroup.getSequences().get(0));
+ assertSame(cds3, mappedGroup.getSequences().get(1));
+ // columns 1-6 selected (0-5 base zero)
+ assertEquals(0, mappedGroup.getStartRes());
+ assertEquals(5, mappedGroup.getEndRes());
+
+ /*
+ * Select mapping sequence group from dna to protein
+ */
+ sg.clear();
+ sg.addSequence(cds2, false);
+ sg.addSequence(cds1, false);
+ sg.setStartRes(0);
+ sg.setEndRes(cdna.getWidth() - 1);
+ mappedGroup = MappingUtils.mapSequenceGroup(sg, cdnaView, peptideView);
+ assertTrue(mappedGroup.getColourText());
+ assertSame(sg.getIdColour(), mappedGroup.getIdColour());
+ assertSame(sg.getOutlineColour(), mappedGroup.getOutlineColour());
+ assertEquals(2, mappedGroup.getSequences().size());
+ assertSame(protein.getSequenceAt(1), mappedGroup.getSequences().get(0));
+ assertSame(protein.getSequenceAt(0), mappedGroup.getSequences().get(1));
+ assertEquals(0, mappedGroup.getStartRes());
+ assertEquals(1, mappedGroup.getEndRes()); // two columns
+ }
}
uod_banner.30=/images/UoD_banner-30.png
uod_banner.32=/images/UoD_banner-32.png
default_appbase=https://www.jalview.org/getdown/release/1.8
-preferences.filename=.jalview_properties
+preferences.filename=.jalview_nonrelease_properties
annotations => {shortname=>"annotations",name=>"Jalview Annotations",extensions=>["annotations","jvannotations"]},
mmcif => {shortname=>"mmcif",name=>"CIF",extensions=>["cif"]},
mmcif2 => {shortname=>"mmcif2",name=>"mmCIF",extensions=>["mcif","mmcif"]},
- jvl => {shortname=>"jvl",name=>"Jalview Launch",extensions=>["jvl"],iconfile=>"Jalview-Launch"},
+ jvl => {shortname=>"jvl",name=>"Jalview Launch",extensions=>["jvl"],iconfile=>"jvl_file"},
jnet => {shortname=>"jnet",name=>"JnetFile",extensions=>["concise","jnet"]},
scorematrix => {shortname=>"scorematrix",name=>"Substitution Matrix",extensions=>["mat"]},
};
<key>CFBundleTypeName</key>
<string>Jalview Launch File</string>
<key>CFBundleTypeIconFile</key>
-<string>Jalview-Launch.icns</string>
+<string>jvl_file.icns</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleTypeMIMETypes</key>
<property name="launcherId" type="string">JALVIEW</property>
<property name="macIconFile">
<object class="com.install4j.api.beans.ExternalFile">
- <string>Jalview-Launch.icns</string>
+ <string>jvl_file.icns</string>
</object>
</property>
<property name="macRole" type="enum" class="com.install4j.runtime.beans.actions.desktop.MacAssociationRole" value="EDITOR" />
<property name="unix" type="boolean" value="true" />
<property name="unixIconFile">
<object class="com.install4j.api.beans.ExternalFile">
- <string>Jalview-Launch.png</string>
+ <string>jvl_file.png</string>
</object>
</property>
<property name="unixMimeType" type="string">application/x-jalview-jvl+text</property>
<property name="windowsIconFile">
<object class="com.install4j.api.beans.ExternalFile">
- <string>Jalview-Launch.ico</string>
+ <string>jvl_file.ico</string>
</object>
</property>
</serializedBean>
<file name=".background/jalview_dmg_background.png" file="${compiler:JALVIEW_DIR}/${compiler:MACOS_DMG_BG_IMAGE}" />
<file name=".DS_Store" file="${compiler:JALVIEW_DIR}/${compiler:MACOS_DMG_DS_STORE}" />
<file name="${compiler:JALVIEW_APPLICATION_NAME}.app/Contents/Resources/Jalview-File.icns" file="${compiler:JALVIEW_DIR}/${compiler:INSTALL4J_UTILS_DIR}/Jalview-File.icns" />
- <file name="${compiler:JALVIEW_APPLICATION_NAME}.app/Contents/Resources/Jalview-Launch.icns" file="${compiler:JALVIEW_DIR}/${compiler:INSTALL4J_UTILS_DIR}/Jalview-Launch.icns" />
+ <file name="${compiler:JALVIEW_APPLICATION_NAME}.app/Contents/Resources/jvl_file.icns" file="${compiler:JALVIEW_DIR}/${compiler:INSTALL4J_UTILS_DIR}/jvl_file.icns" />
<symlink name="${compiler:JALVIEW_APPLICATION_NAME}.app/Contents/MacOS/${compiler:WRAPPER_LINK}" target="../Resources/app/${compiler:WRAPPER_SCRIPT_BIN_DIR}/${compiler:BASH_WRAPPER_SCRIPT}" />
</topLevelFiles>
</macosArchive>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ id="Layer_1"
+ x="0px"
+ y="0px"
+ viewBox="0 0 85.33334 85.333347"
+ enable-background="new 0 0 595.238 595.238"
+ xml:space="preserve"
+ sodipodi:docname="jvl_file.svg"
+ width="85.333344"
+ height="85.333344"
+ inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"><sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="2152"
+ inkscape:window-height="1410"
+ id="namedview11"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:zoom="2.7754382"
+ inkscape:cx="42.666672"
+ inkscape:cy="42.515809"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="0"
+ inkscape:current-layer="Layer_1" />
+ <metadata
+ id="metadata41">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs39">
+
+
+
+
+
+
+ </defs>
+ <g
+ id="g4756"
+ transform="translate(4.0769397e-6,-0.15086052)"><rect
+ style="fill:#0084a9;stroke-width:1"
+ id="rect2"
+ height="20.911402"
+ width="20.91173"
+ y="32.353989"
+ x="32.057495" /><path
+ inkscape:connector-curvature="0"
+ id="polygon4"
+ d="M 0,0.30172379 0.00572055,53.26261 H 10.525655 V 10.821168 H 68.897858 L 58.376942,0.30172379 Z"
+ style="fill:#ad208e;stroke-width:1" /><path
+ inkscape:connector-curvature="0"
+ id="polygon6"
+ d="m 26.699622,26.995298 h 31.67732 L 68.897858,16.921076 H 16.62115 v 36.329112 h 10.078472 z"
+ style="fill:#f78e1e;stroke-width:1" /><polygon
+ transform="matrix(0.16344439,0,0,0.16344439,-6.339681,-5.9678396)"
+ style="fill:#009ddc;stroke-width:6.11828899"
+ id="polygon8"
+ points="137.861,494.236 202.225,558.595 560.882,558.607 560.848,234.574 496.501,234.574 496.501,494.26 " /><polygon
+ transform="matrix(0.16344439,0,0,0.16344439,-6.339681,-5.9678396)"
+ style="fill:#c1d82f;stroke-width:6.11828899"
+ id="polygon10"
+ points="457.329,234.646 395.688,234.646 395.688,395.282 38.904,395.282 100.535,456.929 457.329,456.929 " /><path
+ inkscape:connector-curvature="0"
+ style="fill:none;stroke:#000000;stroke-width:0.1"
+ id="path32"
+ d="M 0.43525241,58.050222" /></g>
+</svg>
\ No newline at end of file