/jalviewApplet.jar
/benchmarking/lib
*.class
+*.patch
/site
/site-resources
/libjs
--- /dev/null
+--- build.gradle 2023-07-02 09:21:09.216542293 +0200
++++ ../jalview_new/build.gradle 2023-05-15 19:20:46.892861180 +0200
+@@ -45,8 +45,8 @@
+ id 'java'
+ id 'application'
+ id 'eclipse'
+- id "com.diffplug.gradle.spotless" version "3.28.0"
+- id 'com.github.johnrengelman.shadow' version '4.0.3'
++ id "com.diffplug.spotless" version "6.18.0" //.gradle.spotless" "3.28.0"
++ id 'com.github.johnrengelman.shadow' version '8.1.1' // was 4.0.3
+ id 'com.install4j.gradle' version '9.0.6'
+ id 'com.dorongold.task-tree' version '2.1.0' // only needed to display task dependency tree with gradle task1 [task2 ...] taskTree
+ id 'com.palantir.git-version' version '0.13.0' apply false
+@@ -183,6 +183,7 @@
+ testDir = string("${jalviewDir}/${bareTestSourceDir}")
+
+ classesDir = string("${jalviewDir}/${classes_dir}")
++ destinationDirectory = file(classesDir)
+
+ // clover
+ useClover = clover.equals("true")
+@@ -547,14 +548,14 @@
+ main {
+ java {
+ srcDirs sourceDir
+- outputDir = file(classesDir)
++ destinationDirectory = file(classesDir)
+ }
+
+ resources {
+ srcDirs = [ resourcesBuildDir, docBuildDir, helpBuildDir ]
+ }
+
+- compileClasspath = files(sourceSets.main.java.outputDir)
++ compileClasspath = files(sourceSets.main.java.destinationDirectory)
+ compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
+
+ runtimeClasspath = compileClasspath
+@@ -564,14 +565,14 @@
+ clover {
+ java {
+ srcDirs cloverInstrDir
+- outputDir = cloverClassesDir
++ destinationDirectory = cloverClassesDir
+ }
+
+ resources {
+ srcDirs = sourceSets.main.resources.srcDirs
+ }
+
+- compileClasspath = files( sourceSets.clover.java.outputDir )
++ compileClasspath = files( sourceSets.clover.java.destinationDirectory )
+ //compileClasspath += files( testClassesDir )
+ compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
+ compileClasspath += fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
+@@ -583,14 +584,14 @@
+ test {
+ java {
+ srcDirs testSourceDir
+- outputDir = file(testClassesDir)
++ destinationDirectory = file(testClassesDir)
+ }
+
+ resources {
+ srcDirs = useClover ? sourceSets.clover.resources.srcDirs : sourceSets.main.resources.srcDirs
+ }
+
+- compileClasspath = files( sourceSets.test.java.outputDir )
++ compileClasspath = files( sourceSets.test.java.destinationDirectory )
+ compileClasspath += useClover ? sourceSets.clover.compileClasspath : sourceSets.main.compileClasspath
+ compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
+
+@@ -615,7 +616,7 @@
+ }
+
+ classpath {
+- //defaultOutputDir = sourceSets.main.java.outputDir
++ //defaultOutputDir = sourceSets.main.java.destinationDirectory
+ configurations.each{ c->
+ if (c.isCanBeResolved()) {
+ minusConfigurations += [c]
+@@ -654,7 +655,7 @@
+ HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
+
+ sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
+- //don't want to add outputDir as eclipse is using its own output dir in bin/main
++ //don't want to add destinationDirectory as eclipse is using its own output dir in bin/main
+ if (it.isDirectory() || ! it.exists()) {
+ // don't add dirs to classpath, especially if they don't exist
+ return false // groovy "continue" in .any closure
+@@ -674,7 +675,7 @@
+ }
+
+ sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
+- //no longer want to add outputDir as eclipse is using its own output dir in bin/main
++ //no longer want to add destinationDirectory as eclipse is using its own output dir in bin/main
+ if (it.isDirectory() || ! it.exists()) {
+ // don't add dirs to classpath
+ return false // groovy "continue" in .any closure
+@@ -1051,7 +1052,7 @@
+
+ clean {
+ doFirst {
+- delete sourceSets.main.java.outputDir
++ delete sourceSets.main.java.destinationDirectory
+ }
+ }
+
+@@ -1059,7 +1060,7 @@
+ cleanTest {
+ dependsOn cleanClover
+ doFirst {
+- delete sourceSets.test.java.outputDir
++ delete sourceSets.test.java.destinationDirectory
+ }
+ }
+
+@@ -1151,7 +1152,7 @@
+
+ task copyDocs(type: Copy) {
+ def inputDir = "${jalviewDir}/${doc_dir}"
+- def outputDir = "${docBuildDir}/${doc_dir}"
++ def destinationDirectory = "${docBuildDir}/${doc_dir}"
+ from(inputDir) {
+ include('**/*.txt')
+ include('**/*.md')
+@@ -1172,10 +1173,10 @@
+ exclude('**/*.html')
+ exclude('**/*.xml')
+ }
+- into outputDir
++ into destinationDirectory
+
+ inputs.dir(inputDir)
+- outputs.dir(outputDir)
++ outputs.dir(destinationDirectory)
+ }
+
+
+@@ -1240,15 +1241,15 @@
+ }
+ if (inFrontMatter) {
+ def m = null
+- if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/) {
++ if (m == line =~ /^date:\s*(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/) {
+ map["date"] = new Date().parse("yyyy-MM-dd HH:mm:ss", m[0][1])
+- } else if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2})/) {
++ } else if (m == line =~ /^date:\s*(\d{4}-\d{2}-\d{2})/) {
+ map["date"] = new Date().parse("yyyy-MM-dd", m[0][1])
+- } else if (m = line =~ /^channel:\s*(\S+)/) {
++ } else if (m == line =~ /^channel:\s*(\S+)/) {
+ map["channel"] = m[0][1]
+- } else if (m = line =~ /^version:\s*(\S+)/) {
++ } else if (m == line =~ /^version:\s*(\S+)/) {
+ map["version"] = m[0][1]
+- } else if (m = line =~ /^\s*([^:]+)\s*:\s*(\S.*)/) {
++ } else if (m == line =~ /^\s*([^:]+)\s*:\s*(\S.*)/) {
+ map[ m[0][1] ] = m[0][2]
+ }
+ if (dateOnly && map["date"] != null) {
+@@ -1307,7 +1308,7 @@
+ def inSection = false
+ changes.eachLine { line ->
+ def m = null
+- if (m = line =~ /^##([^#].*)$/) {
++ if (m == line =~ /^##([^#].*)$/) {
+ if (inSection) {
+ changesHugo += "</div>\n\n"
+ }
+@@ -1317,7 +1318,7 @@
+ section = section.replaceAll(/[^a-z0-9_\-]/, "")
+ changesHugo += "<div class=\"${section}\">\n\n"
+ inSection = true
+- } else if (m = line =~ /^(\s*-\s*)<!--([^>]+)-->(.*?)(<br\/?>)?\s*$/) {
++ } else if (m == line =~ /^(\s*-\s*)<!--([^>]+)-->(.*?)(<br\/?>)?\s*$/) {
+ def comment = m[0][2].trim()
+ if (comment != "") {
+ comment = comment.replaceAll('"', """)
+@@ -1387,7 +1388,7 @@
+ def sectionName = null
+ content.eachLine { line ->
+ def m = null
+- if (m = line =~ /^##([^#].*)$/) {
++ if (m == line =~ /^##([^#].*)$/) {
+ if (sectionName != null) {
+ sections[sectionName] = sectionContent
+ sectionName = null
+@@ -1410,7 +1411,7 @@
+
+ task copyHelp(type: Copy) {
+ def inputDir = helpSourceDir
+- def outputDir = "${helpBuildDir}/${help_dir}"
++ def destinationDirectory = "${helpBuildDir}/${help_dir}"
+ from(inputDir) {
+ include('**/*.txt')
+ include('**/*.md')
+@@ -1435,14 +1436,15 @@
+ exclude('**/*.xml')
+ exclude('**/*.jhm')
+ }
+- into outputDir
++ into destinationDirectory
+
+ inputs.dir(inputDir)
+ outputs.files(helpFile)
+- outputs.dir(outputDir)
++ outputs.dir(destinationDirectory)
+ }
+
+
++/*
+ task releasesTemplates {
+ group "help"
+ description "Recreate whatsNew.html and releases.html from markdown files and templates in help"
+@@ -1519,9 +1521,9 @@
+ def lm = null
+ def rContentProcessed = ""
+ rContent.eachLine { line ->
+- if (lm = line =~ /^(\s*-)(\s*<!--[^>]*?-->)(.*)$/) {
++ if (lm == line =~ /^(\s*-)(\s*<!--[^>]*?-->)(.*)$/) {
+ line = "${lm[0][1]}${lm[0][3]}${lm[0][2]}"
+- } else if (lm = line =~ /^###([^#]+.*)$/) {
++ } else if (lm == line =~ /^###([^#]+.*)$/) {
+ line = "_${lm[0][1].trim()}_"
+ }
+ rContentProcessed += line + "\n"
+@@ -1579,13 +1581,14 @@
+ outputs.file(whatsnewHtmlFile)
+ }
+
++*/
+
+ task copyResources(type: Copy) {
+ group = "build"
+ description = "Copy (and make text substitutions in) the resources dir to the build area"
+
+ def inputDir = resourceDir
+- def outputDir = resourcesBuildDir
++ def destinationDirectory = resourcesBuildDir
+ from(inputDir) {
+ include('**/*.txt')
+ include('**/*.md')
+@@ -1606,10 +1609,10 @@
+ exclude('**/*.html')
+ exclude('**/*.xml')
+ }
+- into outputDir
++ into destinationDirectory
+
+ inputs.dir(inputDir)
+- outputs.dir(outputDir)
++ outputs.dir(destinationDirectory)
+ }
+
+ task copyChannelResources(type: Copy) {
+@@ -1618,16 +1621,17 @@
+ description = "Copy the channel resources dir to the build resources area"
+
+ def inputDir = "${channelDir}/${resource_dir}"
+- def outputDir = resourcesBuildDir
++ def destinationDirectory = resourcesBuildDir
+ from inputDir
+- into outputDir
++ into destinationDirectory
+
+ inputs.dir(inputDir)
+- outputs.dir(outputDir)
++ outputs.dir(destinationDirectory)
+ }
+
+ task createBuildProperties(type: WriteProperties) {
+ dependsOn copyResources
++ dependsOn copyChannelResources
+ group = "build"
+ description = "Create the ${buildProperties} file"
+
+@@ -1651,6 +1655,7 @@
+
+ task buildIndices(type: JavaExec) {
+ dependsOn copyHelp
++ //dependsOn releasesTemplates
+ classpath = sourceSets.main.compileClasspath
+ main = "com.sun.java.help.search.Indexer"
+ workingDir = "${helpBuildDir}/${help_dir}"
+@@ -1678,15 +1683,25 @@
+ dependsOn buildResources
+ dependsOn copyDocs
+ dependsOn copyHelp
+- dependsOn releasesTemplates
++ //dependsOn releasesTemplates
+ dependsOn convertMdFiles
+ dependsOn buildIndices
+ }
+
+
++// random block of dependencies
+ compileJava.dependsOn prepare
+ run.dependsOn compileJava
+ //run.dependsOn prepare
++compileTestJava.dependsOn compileJava //
++compileTestJava.dependsOn buildIndices //
++processResources.dependsOn copyChannelResources //
++processResources.dependsOn copyResources //
++processResources.dependsOn createBuildProperties //
++processResources.dependsOn copyDocs //
++processResources.dependsOn convertMdFiles //
++processResources.dependsOn copyHelp //
++processResources.dependsOn buildIndices //
+
+
+ //testReportDirName = "test-reports" // note that test workingDir will be $jalviewDir
+@@ -1731,6 +1746,7 @@
+ }
+
+
++/*
+ task compileLinkCheck(type: JavaCompile) {
+ options.fork = true
+ classpath = files("${jalviewDir}/${utils_dir}")
+@@ -1765,6 +1781,7 @@
+ inputs.dir(helpBuildDir)
+ outputs.file(helpLinksCheckerOutFile)
+ }
++*/
+
+
+ // import the pubhtmlhelp target
+@@ -1779,10 +1796,14 @@
+ }
+ }
+
++// block of dependencies
++//compileTestJava.dependsOn compileLinkCheck //
++//copyChannelResources.dependsOn compileLinkCheck //
++//convertMdFiles.dependsOn compileLinkCheck //
+
+ jar {
+ dependsOn prepare
+- dependsOn linkCheck
++ dependsOn //linkCheck
+
+ manifest {
+ attributes "Main-Class": main_class,
+@@ -1792,8 +1813,8 @@
+ "Implementation-Version": JALVIEW_VERSION
+ }
+
+- def outputDir = "${jalviewDir}/${package_dir}"
+- destinationDirectory = file(outputDir)
++ def destinationDirectory = "${jalviewDir}/${package_dir}"
++ destinationDirectory = file(destinationDirectory)
+ archiveFileName = rootProject.name+".jar"
+ duplicatesStrategy "EXCLUDE"
+
+@@ -1804,11 +1825,11 @@
+ exclude "**/*.jar"
+ exclude "**/*.jar.*"
+
+- inputs.dir(sourceSets.main.java.outputDir)
++ inputs.dir(sourceSets.main.java.destinationDirectory)
+ sourceSets.main.resources.srcDirs.each{ dir ->
+ inputs.dir(dir)
+ }
+- outputs.file("${outputDir}/${archiveFileName}")
++ outputs.file("${destinationDirectory}/${archiveFileName}")
+ }
+
+
+@@ -1867,7 +1888,7 @@
+
+ mainClassName = shadow_jar_main_class
+ mergeServiceFiles()
+- classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
++ archiveClassifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
+ minimize()
+ }
+
+@@ -2922,10 +2943,10 @@
+
+ def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
+ inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
+- def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
++ def destinationDirectory = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
+
+ from inputFiles
+- into outputDir
++ into destinationDirectory
+ }
+
+
+@@ -3033,13 +3054,13 @@
+ dependsOn jalviewjsTransferUnzipAllLibs
+ def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
+ inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
+- def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
++ def destinationDirectory = "${jalviewDir}/${jalviewjsSiteDir}"
+
+ from inputFiles
+- into outputDir
++ into destinationDirectory
+ def outputFiles = []
+ rename { filename ->
+- outputFiles += "${outputDir}/${filename}"
++ outputFiles += "${destinationDirectory}/${filename}"
+ null
+ }
+ preserve {
+@@ -3058,13 +3079,13 @@
+ dependsOn buildResources
+
+ def inputFiles = fileTree(dir: resourcesBuildDir)
+- def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
++ def destinationDirectory = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
+
+ from inputFiles
+- into outputDir
++ into destinationDirectory
+ def outputFiles = []
+ rename { filename ->
+- outputFiles += "${outputDir}/${filename}"
++ outputFiles += "${destinationDirectory}/${filename}"
+ null
+ }
+ preserve {
+@@ -3077,13 +3098,13 @@
+
+ task jalviewjsSyncSiteResources (type: Sync) {
+ def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
+- def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
++ def destinationDirectory = "${jalviewDir}/${jalviewjsSiteDir}"
+
+ from inputFiles
+- into outputDir
++ into destinationDirectory
+ def outputFiles = []
+ rename { filename ->
+- outputFiles += "${outputDir}/${filename}"
++ outputFiles += "${destinationDirectory}/${filename}"
+ null
+ }
+ preserve {
+@@ -3097,13 +3118,13 @@
+ task jalviewjsSyncBuildProperties (type: Sync) {
+ dependsOn createBuildProperties
+ def inputFiles = [file(buildProperties)]
+- def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
++ def destinationDirectory = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
+
+ from inputFiles
+- into outputDir
++ into destinationDirectory
+ def outputFiles = []
+ rename { filename ->
+- outputFiles += "${outputDir}/${filename}"
++ outputFiles += "${destinationDirectory}/${filename}"
+ null
+ }
+ preserve {
+@@ -3322,7 +3343,7 @@
+ def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
+ def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
+ def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
+- def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
++ def destinationDirectory = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
+ def prefixFile = "${jsDir}/core/coretop2.js"
+ def suffixFile = "${jsDir}/core/corebottom2.js"
+
+@@ -3366,8 +3387,8 @@
+ }
+ def list = fileTree(dir: j2sDir, includes: filelist)
+
+- def jsfile = "${outputDir}/core${name}.js"
+- def zjsfile = "${outputDir}/core${name}.z.js"
++ def jsfile = "${destinationDirectory}/core${name}.js"
++ def zjsfile = "${destinationDirectory}/core${name}.z.js"
+
+ jalviewjsCoreClasslists += [
+ 'jsfile': jsfile,
+@@ -3385,8 +3406,8 @@
+ // _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
+ def stevesoftClasslistName = "_stevesoft"
+ def stevesoftClasslist = [
+- 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
+- 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
++ 'jsfile': "${destinationDirectory}/core${stevesoftClasslistName}.js",
++ 'zjsfile': "${destinationDirectory}/core${stevesoftClasslistName}.z.js",
+ 'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
+ 'name': stevesoftClasslistName
+ ]
+@@ -3419,8 +3440,8 @@
+ ]
+ )
+ def allClasslist = [
+- 'jsfile': "${outputDir}/core${allClasslistName}.js",
+- 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
++ 'jsfile': "${destinationDirectory}/core${allClasslistName}.js",
++ 'zjsfile': "${destinationDirectory}/core${allClasslistName}.z.js",
+ 'list': allJsFiles,
+ 'name': allClasslistName
+ ]
+@@ -3473,11 +3494,11 @@
+ dependsOn jalviewjsBuildAllCores
+ def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
+ def inputFile = file(inputFileName)
+- def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
++ def destinationDirectory = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
+
+ def outputFiles = []
+ jalviewjsCoreClasslists.each { cl ->
+- def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
++ def outputFile = "${destinationDirectory}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
+ cl['outputfile'] = outputFile
+ outputFiles += outputFile
+ }
+@@ -3496,13 +3517,13 @@
+ dependsOn jalviewjsBuildAllCores
+ dependsOn jalviewjsPublishCoreTemplates
+ def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
+- def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
++ def destinationDirectory = "${jalviewDir}/${jalviewjsSiteDir}"
+
+ from inputFiles
+- into outputDir
++ into destinationDirectory
+ def outputFiles = []
+ rename { filename ->
+- outputFiles += "${outputDir}/${filename}"
++ outputFiles += "${destinationDirectory}/${filename}"
+ null
+ }
+ preserve {
testDir = string("${jalviewDir}/${bareTestSourceDir}")
classesDir = string("${jalviewDir}/${classes_dir}")
+ destinationDirectory = file(classesDir)
// clover
useClover = clover.equals("true")
main {
java {
srcDirs sourceDir
- outputDir = file(classesDir)
+ destinationDirectory = file(classesDir)
}
resources {
srcDirs = [ resourcesBuildDir, docBuildDir, helpBuildDir ]
}
- compileClasspath = files(sourceSets.main.java.outputDir)
+ compileClasspath = files(sourceSets.main.java.destinationDirectory)
compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
runtimeClasspath = compileClasspath
clover {
java {
srcDirs cloverInstrDir
- outputDir = cloverClassesDir
+ destinationDirectory = cloverClassesDir
}
resources {
srcDirs = sourceSets.main.resources.srcDirs
}
- compileClasspath = files( sourceSets.clover.java.outputDir )
+ compileClasspath = files( sourceSets.clover.java.destinationDirectory )
//compileClasspath += files( testClassesDir )
compileClasspath += fileTree(dir: "${jalviewDir}/${libDir}", include: ["*.jar"])
compileClasspath += fileTree(dir: "${jalviewDir}/${clover_lib_dir}", include: ["*.jar"])
test {
java {
srcDirs testSourceDir
- outputDir = file(testClassesDir)
+ destinationDirectory = file(testClassesDir)
}
resources {
srcDirs = useClover ? sourceSets.clover.resources.srcDirs : sourceSets.main.resources.srcDirs
}
- compileClasspath = files( sourceSets.test.java.outputDir )
+ compileClasspath = files( sourceSets.test.java.destinationDirectory )
compileClasspath += useClover ? sourceSets.clover.compileClasspath : sourceSets.main.compileClasspath
compileClasspath += fileTree(dir: "${jalviewDir}/${utils_dir}/testnglibs", include: ["**/*.jar"])
}
classpath {
- //defaultOutputDir = sourceSets.main.java.outputDir
+ //defaultOutputDir = sourceSets.main.java.destinationDirectory
configurations.each{ c->
if (c.isCanBeResolved()) {
minusConfigurations += [c]
HashMap<String, Boolean> alreadyAddedLibPath = new HashMap<>();
sourceSets.main.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
- //don't want to add outputDir as eclipse is using its own output dir in bin/main
+ //don't want to add destinationDirectory as eclipse is using its own output dir in bin/main
if (it.isDirectory() || ! it.exists()) {
// don't add dirs to classpath, especially if they don't exist
return false // groovy "continue" in .any closure
}
sourceSets.test.compileClasspath.findAll { it.name.endsWith(".jar") }.any {
- //no longer want to add outputDir as eclipse is using its own output dir in bin/main
+ //no longer want to add destinationDirectory as eclipse is using its own output dir in bin/main
if (it.isDirectory() || ! it.exists()) {
// don't add dirs to classpath
return false // groovy "continue" in .any closure
clean {
doFirst {
- delete sourceSets.main.java.outputDir
+ delete sourceSets.main.java.destinationDirectory
}
}
cleanTest {
dependsOn cleanClover
doFirst {
- delete sourceSets.test.java.outputDir
+ delete sourceSets.test.java.destinationDirectory
}
}
task copyDocs(type: Copy) {
def inputDir = "${jalviewDir}/${doc_dir}"
- def outputDir = "${docBuildDir}/${doc_dir}"
+ def destinationDirectory = "${docBuildDir}/${doc_dir}"
from(inputDir) {
include('**/*.txt')
include('**/*.md')
exclude('**/*.html')
exclude('**/*.xml')
}
- into outputDir
+ into destinationDirectory
inputs.dir(inputDir)
- outputs.dir(outputDir)
+ outputs.dir(destinationDirectory)
}
}
if (inFrontMatter) {
def m = null
- if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/) {
+ if (m == line =~ /^date:\s*(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/) {
map["date"] = new Date().parse("yyyy-MM-dd HH:mm:ss", m[0][1])
- } else if (m = line =~ /^date:\s*(\d{4}-\d{2}-\d{2})/) {
+ } else if (m == line =~ /^date:\s*(\d{4}-\d{2}-\d{2})/) {
map["date"] = new Date().parse("yyyy-MM-dd", m[0][1])
- } else if (m = line =~ /^channel:\s*(\S+)/) {
+ } else if (m == line =~ /^channel:\s*(\S+)/) {
map["channel"] = m[0][1]
- } else if (m = line =~ /^version:\s*(\S+)/) {
+ } else if (m == line =~ /^version:\s*(\S+)/) {
map["version"] = m[0][1]
- } else if (m = line =~ /^\s*([^:]+)\s*:\s*(\S.*)/) {
+ } else if (m == line =~ /^\s*([^:]+)\s*:\s*(\S.*)/) {
map[ m[0][1] ] = m[0][2]
}
if (dateOnly && map["date"] != null) {
def inSection = false
changes.eachLine { line ->
def m = null
- if (m = line =~ /^##([^#].*)$/) {
+ if (m == line =~ /^##([^#].*)$/) {
if (inSection) {
changesHugo += "</div>\n\n"
}
section = section.replaceAll(/[^a-z0-9_\-]/, "")
changesHugo += "<div class=\"${section}\">\n\n"
inSection = true
- } else if (m = line =~ /^(\s*-\s*)<!--([^>]+)-->(.*?)(<br\/?>)?\s*$/) {
+ } else if (m == line =~ /^(\s*-\s*)<!--([^>]+)-->(.*?)(<br\/?>)?\s*$/) {
def comment = m[0][2].trim()
if (comment != "") {
comment = comment.replaceAll('"', """)
def sectionName = null
content.eachLine { line ->
def m = null
- if (m = line =~ /^##([^#].*)$/) {
+ if (m == line =~ /^##([^#].*)$/) {
if (sectionName != null) {
sections[sectionName] = sectionContent
sectionName = null
task copyHelp(type: Copy) {
def inputDir = helpSourceDir
- def outputDir = "${helpBuildDir}/${help_dir}"
+ def destinationDirectory = "${helpBuildDir}/${help_dir}"
from(inputDir) {
include('**/*.txt')
include('**/*.md')
exclude('**/*.xml')
exclude('**/*.jhm')
}
- into outputDir
+ into destinationDirectory
inputs.dir(inputDir)
outputs.files(helpFile)
- outputs.dir(outputDir)
+ outputs.dir(destinationDirectory)
}
+/*
task releasesTemplates {
group "help"
description "Recreate whatsNew.html and releases.html from markdown files and templates in help"
def lm = null
def rContentProcessed = ""
rContent.eachLine { line ->
- if (lm = line =~ /^(\s*-)(\s*<!--[^>]*?-->)(.*)$/) {
+ if (lm == line =~ /^(\s*-)(\s*<!--[^>]*?-->)(.*)$/) {
line = "${lm[0][1]}${lm[0][3]}${lm[0][2]}"
- } else if (lm = line =~ /^###([^#]+.*)$/) {
+ } else if (lm == line =~ /^###([^#]+.*)$/) {
line = "_${lm[0][1].trim()}_"
}
rContentProcessed += line + "\n"
outputs.file(whatsnewHtmlFile)
}
+*/
task copyResources(type: Copy) {
group = "build"
description = "Copy (and make text substitutions in) the resources dir to the build area"
def inputDir = resourceDir
- def outputDir = resourcesBuildDir
+ def destinationDirectory = resourcesBuildDir
from(inputDir) {
include('**/*.txt')
include('**/*.md')
exclude('**/*.html')
exclude('**/*.xml')
}
- into outputDir
+ into destinationDirectory
inputs.dir(inputDir)
- outputs.dir(outputDir)
+ outputs.dir(destinationDirectory)
}
task copyChannelResources(type: Copy) {
description = "Copy the channel resources dir to the build resources area"
def inputDir = "${channelDir}/${resource_dir}"
- def outputDir = resourcesBuildDir
+ def destinationDirectory = resourcesBuildDir
from(inputDir) {
include(channel_props)
filter(ReplaceTokens,
from(inputDir) {
exclude(channel_props)
}
- into outputDir
+ into destinationDirectory
inputs.dir(inputDir)
- outputs.dir(outputDir)
+ outputs.dir(destinationDirectory)
}
task createBuildProperties(type: WriteProperties) {
dependsOn copyResources
+ dependsOn copyChannelResources
group = "build"
description = "Create the ${buildProperties} file"
task buildIndices(type: JavaExec) {
dependsOn copyHelp
+ //dependsOn releasesTemplates
classpath = sourceSets.main.compileClasspath
main = "com.sun.java.help.search.Indexer"
workingDir = "${helpBuildDir}/${help_dir}"
dependsOn buildResources
dependsOn copyDocs
dependsOn copyHelp
- dependsOn releasesTemplates
+ //dependsOn releasesTemplates
dependsOn convertMdFiles
dependsOn buildIndices
}
+// random block of dependencies
compileJava.dependsOn prepare
run.dependsOn compileJava
-compileTestJava.dependsOn compileJava
-
-
-
+//run.dependsOn prepare
+compileTestJava.dependsOn compileJava //
+compileTestJava.dependsOn buildIndices //
+processResources.dependsOn copyChannelResources //
+processResources.dependsOn copyResources //
+processResources.dependsOn createBuildProperties //
+processResources.dependsOn copyDocs //
+processResources.dependsOn convertMdFiles //
+processResources.dependsOn copyHelp //
+processResources.dependsOn buildIndices //
test {
group = "Verification"
description = "Runs all testTaskN tasks)"
/* END of test tasks results summary */
+/*
task compileLinkCheck(type: JavaCompile) {
options.fork = true
classpath = files("${jalviewDir}/${utils_dir}")
inputs.dir(helpBuildDir)
outputs.file(helpLinksCheckerOutFile)
}
+*/
// import the pubhtmlhelp target
}
}
+// block of dependencies
+//compileTestJava.dependsOn compileLinkCheck //
+//copyChannelResources.dependsOn compileLinkCheck //
+//convertMdFiles.dependsOn compileLinkCheck //
jar {
dependsOn prepare
- dependsOn linkCheck
+ dependsOn //linkCheck
manifest {
attributes "Main-Class": main_class,
"Implementation-Version": JALVIEW_VERSION
}
- def outputDir = "${jalviewDir}/${package_dir}"
- destinationDirectory = file(outputDir)
+ def destinationDirectory = "${jalviewDir}/${package_dir}"
+ destinationDirectory = file(destinationDirectory)
archiveFileName = rootProject.name+".jar"
duplicatesStrategy "EXCLUDE"
exclude "**/*.jar"
exclude "**/*.jar.*"
- inputs.dir(sourceSets.main.java.outputDir)
+ inputs.dir(sourceSets.main.java.destinationDirectory)
sourceSets.main.resources.srcDirs.each{ dir ->
inputs.dir(dir)
}
- outputs.file("${outputDir}/${archiveFileName}")
+ outputs.file("${destinationDirectory}/${archiveFileName}")
}
// this mainClassName is mandatory but gets ignored due to manifest created in doFirst{}. Set the Main-Class as an attribute in launcherJar instead
mainClassName = shadow_jar_main_class
mergeServiceFiles()
- classifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
+ archiveClassifier = "all-"+JALVIEW_VERSION+"-j"+JAVA_VERSION
minimize()
}
def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_eclipse_dropins_dir}", include: "*.jar")
inputFiles += file("${jalviewDir}/${jalviewjsJ2sPlugin}")
- def outputDir = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
+ def destinationDirectory = "${jalviewDir}/${jalviewjsBuildDir}/${jalviewjs_eclipse_tmp_dropins_dir}"
from inputFiles
- into outputDir
+ into destinationDirectory
}
dependsOn jalviewjsTransferUnzipAllLibs
def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteLibDir}")
inputFiles += fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}")
- def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
+ def destinationDirectory = "${jalviewDir}/${jalviewjsSiteDir}"
from inputFiles
- into outputDir
+ into destinationDirectory
def outputFiles = []
rename { filename ->
- outputFiles += "${outputDir}/${filename}"
+ outputFiles += "${destinationDirectory}/${filename}"
null
}
preserve {
dependsOn buildResources
def inputFiles = fileTree(dir: resourcesBuildDir)
- def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
+ def destinationDirectory = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
from inputFiles
- into outputDir
+ into destinationDirectory
def outputFiles = []
rename { filename ->
- outputFiles += "${outputDir}/${filename}"
+ outputFiles += "${destinationDirectory}/${filename}"
null
}
preserve {
task jalviewjsSyncSiteResources (type: Sync) {
def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjs_site_resource_dir}")
- def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
+ def destinationDirectory = "${jalviewDir}/${jalviewjsSiteDir}"
from inputFiles
- into outputDir
+ into destinationDirectory
def outputFiles = []
rename { filename ->
- outputFiles += "${outputDir}/${filename}"
+ outputFiles += "${destinationDirectory}/${filename}"
null
}
preserve {
task jalviewjsSyncBuildProperties (type: Sync) {
dependsOn createBuildProperties
def inputFiles = [file(buildProperties)]
- def outputDir = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
+ def destinationDirectory = "${jalviewDir}/${jalviewjsSiteDir}/${jalviewjs_j2s_subdir}"
from inputFiles
- into outputDir
+ into destinationDirectory
def outputFiles = []
rename { filename ->
- outputFiles += "${outputDir}/${filename}"
+ outputFiles += "${destinationDirectory}/${filename}"
null
}
preserve {
def swingJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_j2s_subdir}"
def libJ2sDir = "${jalviewDir}/${jalviewjsTransferSiteLibDir}/${jalviewjs_j2s_subdir}"
def jsDir = "${jalviewDir}/${jalviewjsTransferSiteSwingJsDir}/${jalviewjs_js_subdir}"
- def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
+ def destinationDirectory = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}/${jalviewjs_j2s_subdir}/core"
def prefixFile = "${jsDir}/core/coretop2.js"
def suffixFile = "${jsDir}/core/corebottom2.js"
}
def list = fileTree(dir: j2sDir, includes: filelist)
- def jsfile = "${outputDir}/core${name}.js"
- def zjsfile = "${outputDir}/core${name}.z.js"
+ def jsfile = "${destinationDirectory}/core${name}.js"
+ def zjsfile = "${destinationDirectory}/core${name}.z.js"
jalviewjsCoreClasslists += [
'jsfile': jsfile,
// _stevesoft core. add any cores without a classlist here (and the inputs and outputs)
def stevesoftClasslistName = "_stevesoft"
def stevesoftClasslist = [
- 'jsfile': "${outputDir}/core${stevesoftClasslistName}.js",
- 'zjsfile': "${outputDir}/core${stevesoftClasslistName}.z.js",
+ 'jsfile': "${destinationDirectory}/core${stevesoftClasslistName}.js",
+ 'zjsfile': "${destinationDirectory}/core${stevesoftClasslistName}.z.js",
'list': fileTree(dir: j2sDir, include: "com/stevesoft/pat/**/*.js"),
'name': stevesoftClasslistName
]
]
)
def allClasslist = [
- 'jsfile': "${outputDir}/core${allClasslistName}.js",
- 'zjsfile': "${outputDir}/core${allClasslistName}.z.js",
+ 'jsfile': "${destinationDirectory}/core${allClasslistName}.js",
+ 'zjsfile': "${destinationDirectory}/core${allClasslistName}.z.js",
'list': allJsFiles,
'name': allClasslistName
]
dependsOn jalviewjsBuildAllCores
def inputFileName = "${jalviewDir}/${j2s_coretemplate_html}"
def inputFile = file(inputFileName)
- def outputDir = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
+ def destinationDirectory = "${jalviewDir}/${jalviewjsTransferSiteCoreDir}"
def outputFiles = []
jalviewjsCoreClasslists.each { cl ->
- def outputFile = "${outputDir}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
+ def outputFile = "${destinationDirectory}/${jalviewjsJalviewTemplateName}_${cl.name}.html"
cl['outputfile'] = outputFile
outputFiles += outputFile
}
dependsOn jalviewjsBuildAllCores
dependsOn jalviewjsPublishCoreTemplates
def inputFiles = fileTree(dir: "${jalviewDir}/${jalviewjsTransferSiteCoreDir}")
- def outputDir = "${jalviewDir}/${jalviewjsSiteDir}"
+ def destinationDirectory = "${jalviewDir}/${jalviewjsSiteDir}"
from inputFiles
- into outputDir
+ into destinationDirectory
def outputFiles = []
rename { filename ->
- outputFiles += "${outputDir}/${filename}"
+ outputFiles += "${destinationDirectory}/${filename}"
null
}
preserve {
- <!-- JAL-4054 --> Installers built with install4j10
- <!-- JAL-4167 --> Create separate gradle test task for some tests
- <!-- JAL-4212 --> Prevent gradle test on macOS continuously grabbing focus
-- <!-- JAL-4111 --> Allow gradle build to create suffixed DEVELOP-... builds with channel appbase
+- <!-- JAL-4111 --> Allow gradle build to create suffixed DEVELOP-... builds with channel
- <!-- JAL-4288 --> Update .jvl generation in build.gradle for jalview branch builds
- <!-- JAL-4243 --> Jalview bio.tools description maintained under jalview's git repo and bundled with source release
- <!-- JAL-4110 --> Output stderr and stdout when running tests via gradle
- <!-- JAL-3599 --> New gradle task providing runtime acceptance test for JalviewJS based on Chromium for Tests (still work in progress)
-
## Issues Resolved
- <!-- JAL-2961 --> Jmol view not always centred on structures when multiple structures are viewed
- <!-- JAL-3772 --> Unsaved Alignment windows close without prompting to save, individually or at application quit.
action.by_tree_order = By Tree Order
action.sort = Sort
action.calculate_tree = Calculate Tree...
-action.calculate_tree_pca = Calculate Tree or PCA...
+action.calculate_tree_pca = Calculate Tree, PCA or PaSiMap...
action.help = Help
action.by_annotation = By Annotation...
action.invert_sequence_selection = Invert Sequence Selection
label.undo_command = Undo {0}
label.redo_command = Redo {0}
label.principal_component_analysis = Principal Component Analysis
+label.pasimap = PaSiMap
label.average_distance_identity = Average Distance Using % Identity
label.neighbour_joining_identity = Neighbour Joining Using % Identity
label.choose_calculation = Choose Calculation
label.output_values = Output Values...
label.output_points = Output points...
label.output_transformed_points = Output transformed points
+label.output_alignment = Output pairwise alignments
+label.pairwise_alignment_for_params = Pairwise alignments for {0}
label.input_data = Input Data...
label.nucleotide_matrix = Nucleotide matrix
label.protein_matrix = Protein matrix
label.annotation_for_displayid = <p><h2>Annotation for {0} </h2></p><p>
label.pdb_sequence_mapping = PDB - Sequence Mapping
label.pca_details = PCA details
+label.pasimap_details = PaSiMap details
label.redundancy_threshold_selection = Redundancy threshold selection
label.user_defined_colours = User defined colours
label.jalviewLite_release = JalviewLite - Release {0}
label.edit_sbrs_entry = Edit Simple Bioinformatics Rest Service entry
label.pca_recalculating = Recalculating PCA
label.pca_calculating = Calculating PCA
+label.pasimap_recalculating = Recalculating PaSiMap
+label.pasimap_calculating = Calculating PaSiMap
label.select_foreground_colour = Choose foreground colour
label.select_colour_for_text = Select Colour for Text
label.adjust_foreground_text_colour_threshold = Adjust Foreground Text Colour Threshold
label.edit_annotation_name_description = Edit Annotation Name/Description
label.alignment = alignment
label.pca = PCA
+label.pasimap = PaSiMap
label.create_image_of = Create {0} image of {1}
label.click_to_edit = Click to edit, right-click for menu
label.backupfiles_confirm_delete = Confirm delete
action.by_tree_order = Por orden del árbol
action.sort = Ordenar
action.calculate_tree = Calcular árbol...
-action.calculate_tree_pca = Calcular árbol o ACP...
+action.calculate_tree_pca = Calcular árbol, ACP o PaSiMap...
action.help = Ayuda
action.by_annotation = Por anotación...
action.invert_sequence_selection = Invertir selección de secuencias
label.undo_command = Deshacer {0}
label.redo_command = Rehacer {0}
label.principal_component_analysis = Análisis del Componente Principal
+label.pasimap = PaSiMap
label.average_distance_identity = Distancia Media Usando % de Identidad
label.neighbour_joining_identity = Unir vecinos utilizando % de Identidad
label.choose_calculation = Elegir el cálculo
label.output_values = Valores de salida...
label.output_points = Puntos de salida...
label.output_transformed_points = Puntos de salida transformados
+label.output_alignment = Alineaciones de pares de salida
+label.pairwise_alignment_for_params = Alineaciiones por pares para {0}
label.input_data = Datos de entrada...
label.nucleotide_matrix = Matriz nucleotÃdica
label.protein_matrix = Matriz proteica
label.edit_sbrs_entry = Editar entrada SBRS
label.pca_recalculating = Recalculando ACP
label.pca_calculating = Calculando ACP
+label.pasimap_recalculating = Recalculando PaSiMap
+label.pasimap_calculating = Calculando PaSiMap
label.select_foreground_colour = Escoger color del primer plano
label.select_colour_for_text = Seleccione el color del texto
label.adjust_foreground_text_colour_threshold = Ajustar el umbral del color del texto en primer plano
label.edit_annotation_name_description = Editar el nombre/descripción de la anotación
label.alignment = alineamiento
label.pca = ACP
+label.pasimap = PaSiMap
label.create_image_of = Crear imagen {0} de {1}
label.click_to_edit = Haga clic para editar, clic en el botón derecho para ver el menú
label.backupfiles_confirm_delete = Confirmar borrar
*/
package jalview.analysis;
-import java.util.Locale;
-
import jalview.analysis.scoremodels.PIDModel;
import jalview.analysis.scoremodels.ScoreMatrix;
import jalview.analysis.scoremodels.ScoreModels;
import jalview.datamodel.Mapping;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceI;
+import jalview.math.MiscMath;
import jalview.util.Comparison;
import jalview.util.Format;
import jalview.util.MapList;
import java.awt.Color;
import java.awt.Graphics;
import java.io.PrintStream;
+import java.lang.IllegalArgumentException;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.HashMap;
import java.util.List;
import java.util.StringTokenizer;
+import java.util.Locale;
/**
- *
- *
* @author $author$
* @version $Revision$
*/
{
private static final int MAX_NAME_LENGTH = 30;
- private static final int GAP_OPEN_COST = 120;
+ private static final int DEFAULT_OPENCOST = 120;
+
+ private static final int DEFAULT_EXTENDCOST = 20;
+
+ private int GAP_OPEN_COST=DEFAULT_OPENCOST;
- private static final int GAP_EXTEND_COST = 20;
+ private int GAP_EXTEND_COST=DEFAULT_EXTENDCOST;
private static final int GAP_INDEX = -1;
float[][] score;
+ float alignmentScore;
+
float[][] E;
float[][] F;
public String astr2 = "";
+ public String indelfreeAstr1 = "";
+
+ public String indelfreeAstr2 = "";
+
/** DOCUMENT ME!! */
public int seq1start;
public float maxscore;
+ public float meanScore; //needed for PaSiMap
+
+ public int hypotheticMaxScore; // needed for PaSiMap
+
int prev = 0;
StringBuffer output = new StringBuffer();
* @param type
* molecule type, either AlignSeq.PEP or AlignSeq.DNA
*/
+ public AlignSeq(int opencost, int extcost)
+ {
+ GAP_OPEN_COST = opencost;
+ GAP_EXTEND_COST = extcost;
+ }
public AlignSeq(SequenceI s1, SequenceI s2, String type)
{
seqInit(s1, s1.getSequenceAsString(), s2, s2.getSequenceAsString(),
/**
* Creates a new AlignSeq object.
*
- * @param s1
- * DOCUMENT ME!
- * @param s2
- * DOCUMENT ME!
+ * @param s1,string1
+ * s1 reference sequence for string1
+ * @param s2,string2
+ * s2 reference sequence for string2
* @param type
- * DOCUMENT ME!
+ * molecule type, either AlignSeq.PEP or AlignSeq.DNA
*/
public AlignSeq(SequenceI s1, String string1, SequenceI s2,
String string2, String type)
string2.toUpperCase(Locale.ROOT), type);
}
+ public AlignSeq(SequenceI s1, SequenceI s2, String type, int opencost,
+ int extcost)
+ {
+ this(s1,s2,type);
+ GAP_OPEN_COST=opencost;
+ GAP_EXTEND_COST=extcost;
+ }
+
+ public AlignSeq(SequenceI s12, String string1, SequenceI s22,
+ String string2, String type2, int defaultOpencost,
+ int defaultExtendcost)
+ {
+ this(s12,string1,s22,string2,type2);
+ GAP_OPEN_COST=defaultOpencost;
+ GAP_EXTEND_COST=defaultExtendcost;
+ }
+
/**
* DOCUMENT ME!
*
}
/**
+ * returns the overall score of the alignment
+ *
+ * @return
+ */
+ public float getAlignmentScore()
+ {
+ return alignmentScore;
+ }
+
+ /**
* DOCUMENT ME!
*
* @return DOCUMENT ME!
public void seqInit(SequenceI s1, String string1, SequenceI s2,
String string2, String type)
{
+ seqInit(s1,string1,s2,string2,type,GAP_OPEN_COST,GAP_EXTEND_COST);
+ }
+ public void seqInit(SequenceI s1, String string1, SequenceI s2,
+ String string2, String type, int opening,int extension)
+ {
+ GAP_OPEN_COST=opening;
+ GAP_EXTEND_COST=extension;
this.s1 = s1;
this.s2 = s2;
setDefaultParams(type);
int trace;
maxscore = score[i][j] / 10f;
- seq1end = maxi + 1;
- seq2end = maxj + 1;
aseq1 = new int[seq1.length + seq2.length];
aseq2 = new int[seq1.length + seq2.length];
count = (seq1.length + seq2.length) - 1;
+
while (i > 0 && j > 0)
{
aseq1[count] = seq1[i];
sb2.append(s2str.charAt(j));
}
+
+ /*
+ * we built the character strings backwards, so now
+ * reverse them to convert to sequence strings
+ */
+ astr1 = sb1.reverse().toString();
+ astr2 = sb2.reverse().toString();
+ }
+
+ /**
+ * DOCUMENT ME!
+ */
+ public void traceAlignmentWithEndGaps()
+ {
+ // Find the maximum score along the rhs or bottom row
+ float max = -Float.MAX_VALUE;
+
+ for (int i = 0; i < seq1.length; i++)
+ {
+ if (score[i][seq2.length - 1] > max)
+ {
+ max = score[i][seq2.length - 1];
+ maxi = i;
+ maxj = seq2.length - 1;
+ }
+ }
+
+ for (int j = 0; j < seq2.length; j++)
+ {
+ if (score[seq1.length - 1][j] > max)
+ {
+ max = score[seq1.length - 1][j];
+ maxi = seq1.length - 1;
+ maxj = j;
+ }
+ }
+
+ int i = maxi;
+ int j = maxj;
+ int trace;
+ maxscore = score[i][j] / 10f;
+
+ //prepare trailing gaps
+ while ((i < seq1.length - 1) || (j < seq2.length - 1))
+ {
+ i++;
+ j++;
+ }
+ seq1end = i + 1;
+ seq2end = j + 1;
+
+ aseq1 = new int[seq1.length + seq2.length];
+ aseq2 = new int[seq1.length + seq2.length];
+
+ StringBuilder sb1 = new StringBuilder(aseq1.length);
+ StringBuilder sb2 = new StringBuilder(aseq2.length);
+
+ count = (seq1.length + seq2.length) - 1;
+
+ //get trailing gaps
+ while ((i >= seq1.length) || (j >= seq2.length))
+ {
+ if (i >= seq1.length)
+ {
+ aseq1[count] = GAP_INDEX;
+ sb1.append("-");
+ aseq2[count] = seq2[j];
+ sb2.append(s2str.charAt(j));
+ } else if (j >= seq2.length) {
+ aseq1[count] = seq1[i];
+ sb1.append(s1str.charAt(i));
+ aseq2[count] = GAP_INDEX;
+ sb2.append("-");
+ }
+ i--;
+ j--;
+ }
+
+ while (i > 0 && j > 0)
+ {
+ aseq1[count] = seq1[i];
+ sb1.append(s1str.charAt(i));
+ aseq2[count] = seq2[j];
+ sb2.append(s2str.charAt(j));
+
+ trace = findTrace(i, j);
+
+ if (trace == 0)
+ {
+ i--;
+ j--;
+ }
+ else if (trace == 1)
+ {
+ j--;
+ aseq1[count] = GAP_INDEX;
+ sb1.replace(sb1.length() - 1, sb1.length(), "-");
+ }
+ else if (trace == -1)
+ {
+ i--;
+ aseq2[count] = GAP_INDEX;
+ sb2.replace(sb2.length() - 1, sb2.length(), "-");
+ }
+
+ count--;
+ }
+
+ seq1start = i + 1;
+ seq2start = j + 1;
+
+ aseq1[count] = seq1[i];
+ sb1.append(s1str.charAt(i));
+ aseq2[count] = seq2[j];
+ sb2.append(s2str.charAt(j));
+
+ //get initial gaps
+ while (j > 0 || i > 0)
+ {
+ if (j > 0)
+ {
+ j--;
+ sb1.append("-");
+ sb2.append(s2str.charAt(j));
+ } else if (i > 0) {
+ i--;
+ sb1.append(s1str.charAt(i));
+ sb2.append("-");
+ }
+ }
+
/*
* we built the character strings backwards, so now
* reverse them to convert to sequence strings
{
int n = seq1.length;
int m = seq2.length;
-
+ final int GAP_EX_COST=GAP_EXTEND_COST;
+ final int GAP_OP_COST = GAP_OPEN_COST;
// top left hand element
score[0][0] = scoreMatrix.getPairwiseScore(s1str.charAt(0),
s2str.charAt(0)) * 10;
- E[0][0] = -GAP_EXTEND_COST;
+ E[0][0] = -GAP_EX_COST;
F[0][0] = 0;
// Calculate the top row first
for (int j = 1; j < m; j++)
{
// What should these values be? 0 maybe
- E[0][j] = max(score[0][j - 1] - GAP_OPEN_COST,
- E[0][j - 1] - GAP_EXTEND_COST);
- F[0][j] = -GAP_EXTEND_COST;
+ E[0][j] = max(score[0][j - 1] - GAP_OP_COST,
+ E[0][j - 1] - GAP_EX_COST);
+ F[0][j] = -GAP_EX_COST;
float pairwiseScore = scoreMatrix.getPairwiseScore(s1str.charAt(0),
s2str.charAt(j));
- score[0][j] = max(pairwiseScore * 10, -GAP_OPEN_COST,
- -GAP_EXTEND_COST);
+ score[0][j] = max(pairwiseScore * 10, -GAP_OP_COST,
+ -GAP_EX_COST);
traceback[0][j] = 1;
}
// Now do the left hand column
for (int i = 1; i < n; i++)
{
- E[i][0] = -GAP_OPEN_COST;
- F[i][0] = max(score[i - 1][0] - GAP_OPEN_COST,
- F[i - 1][0] - GAP_EXTEND_COST);
+ E[i][0] = -GAP_OP_COST;
+ F[i][0] = max(score[i - 1][0] - GAP_OP_COST,
+ F[i - 1][0] - GAP_EX_COST);
float pairwiseScore = scoreMatrix.getPairwiseScore(s1str.charAt(i),
s2str.charAt(0));
{
for (int j = 1; j < m; j++)
{
- E[i][j] = max(score[i][j - 1] - GAP_OPEN_COST,
- E[i][j - 1] - GAP_EXTEND_COST);
- F[i][j] = max(score[i - 1][j] - GAP_OPEN_COST,
- F[i - 1][j] - GAP_EXTEND_COST);
+ E[i][j] = max(score[i][j - 1] - GAP_OP_COST,
+ E[i][j - 1] - GAP_EX_COST);
+ F[i][j] = max(score[i - 1][j] - GAP_OP_COST,
+ F[i - 1][j] - GAP_EX_COST);
float pairwiseScore = scoreMatrix.getPairwiseScore(s1str.charAt(i),
s2str.charAt(j));
public static AlignSeq doGlobalNWAlignment(SequenceI s1, SequenceI s2,
String type)
{
- AlignSeq as = new AlignSeq(s1, s2, type);
+ return doGlobalNWAlignment(s1, s2, type, DEFAULT_OPENCOST,DEFAULT_EXTENDCOST);
+ }
+ public static AlignSeq doGlobalNWAlignment(SequenceI s1, SequenceI s2,
+ String type, int opencost,int extcost)
+ {
+
+ AlignSeq as = new AlignSeq(s1, s2, type,opencost,extcost);
as.calcScoreMatrix();
as.traceAlignment();
}
return redundancy;
}
+
+ /**
+ * calculate the mean score of the alignment
+ * mean score is equal to the score of an alignmenet of two sequences with randomly shuffled AA sequence composited of the same AA as the two original sequences
+ *
+ */
+ public void meanScore()
+ {
+ int length = indelfreeAstr1.length(); //both have the same length
+ //create HashMap for counting residues in each sequence
+ HashMap<Character, Integer> seq1ResCount = new HashMap<Character, Integer>();
+ HashMap<Character, Integer> seq2ResCount = new HashMap<Character, Integer>();
+
+ // for both sequences (String indelfreeAstr1 or 2) create a key for the residue and add 1 each time its encountered
+ for (char residue: indelfreeAstr1.toCharArray())
+ {
+ seq1ResCount.putIfAbsent(residue, 0);
+ seq1ResCount.replace(residue, seq1ResCount.get(residue) + 1);
+ }
+ for (char residue: indelfreeAstr2.toCharArray())
+ {
+ seq2ResCount.putIfAbsent(residue, 0);
+ seq2ResCount.replace(residue, seq2ResCount.get(residue) + 1);
+ }
+
+ // meanscore = for each residue pair get the number of appearance and add (countA * countB * pairwiseScore(AB))
+ // divide the meanscore by the sequence length afterwards
+ float _meanscore = 0;
+ for (char resA : seq1ResCount.keySet())
+ {
+ for (char resB : seq2ResCount.keySet())
+ {
+ int countA = seq1ResCount.get(resA);
+ int countB = seq2ResCount.get(resB);
+
+ float scoreAB = scoreMatrix.getPairwiseScore(resA, resB);
+
+ _meanscore += countA * countB * scoreAB;
+ }
+ }
+ _meanscore /= length;
+ this.meanScore = _meanscore;
+ }
+
+ public float getMeanScore()
+ {
+ return this.meanScore;
+ }
+
+ /**
+ * calculate the hypothetic max score using the self-alignment of the sequences
+ */
+ public void hypotheticMaxScore()
+ {
+ int _hmsA = 0;
+ int _hmsB = 0;
+ for (char residue: indelfreeAstr1.toCharArray())
+ {
+ _hmsA += scoreMatrix.getPairwiseScore(residue, residue);
+ }
+ for (char residue: indelfreeAstr2.toCharArray())
+ {
+ _hmsB += scoreMatrix.getPairwiseScore(residue, residue);
+ }
+ this.hypotheticMaxScore = (_hmsA < _hmsB) ? _hmsA : _hmsB; // take the lower self alignment
+
+ }
+
+ public int getHypotheticMaxScore()
+ {
+ return this.hypotheticMaxScore;
+ }
+
+ /**
+ * create strings based of astr1 and astr2 but without gaps
+ */
+ public void getIndelfreeAstr()
+ {
+ int n = astr1.length(); // both have the same length
+ for (int i = 0; i < n; i++)
+ {
+ if (Character.isLetter(astr1.charAt(i)) && Character.isLetter(astr2.charAt(i))) // if both sequences dont have a gap -> add to indelfreeAstr
+ {
+ this.indelfreeAstr1 += astr1.charAt(i);
+ this.indelfreeAstr2 += astr2.charAt(i);
+ }
+ }
+ }
+
+ /**
+ * calculates the overall score of the alignment
+ * preprescore = sum of all scores - all penalties
+ * if preprescore < 1 ~ alignmentScore = Float.NaN >
+ * alignmentScore = ((preprescore - meanScore) / (hypotheticMaxScore - meanScore)) * coverage
+ */
+ public void scoreAlignment()
+ {
+
+ getIndelfreeAstr();
+ meanScore();
+ hypotheticMaxScore();
+ // cannot calculate score because denominator would be zero
+ if (this.hypotheticMaxScore == this.meanScore)
+ {
+ this.alignmentScore = Float.NaN;
+ return;
+ }
+ int n = indelfreeAstr1.length();
+
+ float score = 0;
+ boolean aGapOpen = false;
+ boolean bGapOpen = false;
+ for (int i = 0; i < n; i++)
+ {
+ char char1 = indelfreeAstr1.charAt(i);
+ char char2 = indelfreeAstr2.charAt(i);
+ boolean aIsLetter = Character.isLetter(char1);
+ boolean bIsLetter = Character.isLetter(char2);
+ if (aIsLetter && bIsLetter) // if pair -> get score
+ {
+ score += scoreMatrix.getPairwiseScore(char1, char2);
+ } else if (!aIsLetter && !bIsLetter) { // both are gap -> skip
+ } else if ((!aIsLetter && aGapOpen) || (!bIsLetter && bGapOpen)) { // one side gapopen -> score - gap_extend
+ score -= GAP_EXTEND_COST;
+ } else { // no gap open -> score - gap_open
+ score -= GAP_OPEN_COST;
+ }
+ // adjust GapOpen status in both sequences
+ aGapOpen = (!aIsLetter) ? true : false;
+ bGapOpen = (!bIsLetter) ? true : false;
+ }
+
+ float preprescore = score; // if this score < 1 --> alignment score = Float.NaN
+ score = (score - this.meanScore) / (this.hypotheticMaxScore - this.meanScore);
+ int[] _max = MiscMath.findMax(new int[]{astr1.replace("-","").length(), astr2.replace("-","").length()}); // {index of max, max}
+ float coverage = (float) n / (float) _max[1]; // indelfreeAstr length / longest sequence length
+ float prescore = score; // only debug
+ score *= coverage;
+
+ //System.out.println(String.format("prepre-score: %f, pre-score: %f, longlength: %d\nscore: %1.16f, mean: %f, max: %d", preprescore, prescore, _max[1], score, this.meanScore, this.hypotheticMaxScore));
+ float minScore = 0f;
+ this.alignmentScore = (score <= minScore) ? Float.NaN : score;
+ }
+
+ public void clear()
+ {
+ score = null;
+ alignmentScore = 0f;
+ E = null;
+ F = null;
+ traceback = null; // todo is this actually used?
+ seq1 = null;
+ seq2 = null;
+ s1 = null;
+ s2 = null;
+ s1str = null;
+ s2str = null;
+ maxi = 0;
+ maxj = 0;
+ aseq1 = null;
+ aseq2 = null;
+ astr1 = "";
+ astr2 = "";
+ indelfreeAstr1 = "";
+ indelfreeAstr2 = "";
+ seq1start = 0;
+ seq1end = 0;
+ seq2start = 0;
+ seq2end = 0;
+ count = 0;
+ maxscore = 0f;
+ meanScore = 0f; //needed for PaSiMap
+ hypotheticMaxScore = 0; // needed for PaSiMap
+ prev = 0;
+ StringBuffer output = new StringBuffer();
+ String type = null; // AlignSeq.PEP or AlignSeq.DNA
+ }
}
--- /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.analysis;
+
+//import jalview.datamodel.AlignmentView;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.SequenceI;
+import jalview.gui.Desktop;
+import jalview.gui.JvOptionPane;
+import jalview.viewmodel.AlignmentViewport;
+
+import java.util.Comparator;
+import java.util.Hashtable;
+import java.util.HashSet;
+import java.util.TreeSet;
+
+/**
+ * @Author MorellThomas
+ */
+
+public class Connectivity
+{
+
+ /**
+ * Returns the number of unique connections for each sequence
+ * only connections with a score of above 0 count
+ *
+ * @param av sequences
+ * @param scores alignment scores
+ *
+ * @return connectivity
+ */
+ public static Hashtable<SequenceI, Integer> getConnectivity(AlignmentViewport av, float[][] scores, byte dim) throws RuntimeException
+ {
+ boolean isSelection = av.getSelectionGroup() != null && av.getSelectionGroup().getSize() > 0;
+ SequenceI[] sequences;
+ if (isSelection)
+ {
+ sequences = (SequenceI[]) av.getAlignmentView(isSelection).getAlignmentAndHiddenColumns(av.getGapCharacter())[0];
+ } else {
+ sequences = av.getAlignment().getSequencesArray();
+ }
+
+ Hashtable<SequenceI, Integer> connectivity = new Hashtable<SequenceI, Integer>();
+ // for each unique connection
+ for (int i = 0; i < sequences.length; i++)
+ {
+ connectivity.putIfAbsent(sequences[i], 0);
+ for (int j = 0; j < i; j++)
+ {
+ connectivity.putIfAbsent(sequences[j], 0);
+ int iOld = connectivity.get(sequences[i]);
+ int jOld = connectivity.get(sequences[j]);
+ // count the connection if its score is not NaN
+//System.out.println(String.format("%s - %s : %f", sequences[i].getName(), sequences[j].getName(), scores[i][j]));
+ if (!Float.isNaN(scores[i][j]))
+ {
+ connectivity.put(sequences[i], ++iOld);
+ connectivity.put(sequences[j], ++jOld);
+ }
+ }
+ }
+
+ // if a sequence has too few connections, abort
+ connectivity.forEach((sequence, connection) ->
+ {
+ System.out.println(String.format("%s: %d", sequence.getName(), connection));
+ if (connection < dim)
+ {
+ JvOptionPane.showInternalMessageDialog(Desktop.desktop, String.format("Insufficient number of connections for %s (%d, should be %d or more)", sequence.getName(), connection, dim), "Connectivity Error", JvOptionPane.WARNING_MESSAGE);
+ throw new ConnectivityException(sequence.getName(), connection, dim);
+ }
+ } );
+
+ return connectivity;
+ }
+
+}
--- /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.analysis;
+
+public class ConnectivityException extends RuntimeException
+{
+ private String sequence;
+ private int connection;
+ private byte dim;
+
+ public ConnectivityException(String sequence, int connection, byte dim)
+ {
+ this("Insufficient number of connections", sequence, connection, dim);
+ }
+
+ public ConnectivityException(String message, String sequence, int connection, byte dim)
+ {
+ super(String.format("%s for %s (%d, should be %d or more)", message, sequence, connection, dim));
+ this.sequence = sequence;
+ this.connection = connection;
+ this.dim = dim;
+ }
+
+ public String getSequence()
+ {
+ return sequence;
+ }
+
+ public int getConnection()
+ {
+ return connection;
+ }
+
+ public byte getDim()
+ {
+ return dim;
+ }
+
+}
}
else
{
- allFeatures = sf.getAllFeatures(null);
+ //allFeatures = sf.getAllFeatures(null);
+ allFeatures = sf.getAllFeatures();
}
// so we can check we are advancing when debugging
long fpos = 0;
--- /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.analysis;
+
+import jalview.api.analysis.ScoreModelI;
+import jalview.api.analysis.SimilarityParamsI;
+import jalview.bin.Console;
+import jalview.datamodel.Point;
+import jalview.datamodel.SequenceI;
+import jalview.datamodel.SequenceGroup;
+import jalview.gui.PairwiseAlignPanel;
+import jalview.math.Matrix;
+import jalview.math.MatrixI;
+import jalview.viewmodel.AlignmentViewport;
+
+import java.io.PrintStream;
+import java.util.Hashtable;
+
+/**
+ * Performs Principal Component Analysis on given sequences
+ * @AUTHOR MorellThomas
+ */
+public class PaSiMap implements Runnable
+{
+ /*
+ * inputs
+ */
+ final private AlignmentViewport seqs;
+
+ final private ScoreModelI scoreModel;
+
+ final private byte dim = 8;
+
+ final private int openCost = 100;
+
+ final private int extendCost = 5;
+
+ /*
+ * outputs
+ */
+ final private PairwiseAlignPanel alignment;
+
+ private MatrixI pairwiseScores;
+
+ private MatrixI eigenMatrix;
+
+ /**
+ * Constructor given the sequences to compute for, the similarity model to
+ * use, and a set of parameters for sequence comparison
+ *
+ * @param sequences
+ * @param sm
+ * @param options
+ */
+ public PaSiMap(AlignmentViewport sequences, ScoreModelI sm, PairwiseAlignPanel pap)
+ {
+ this.seqs = sequences;
+ this.scoreModel = sm;
+ this.alignment = pap;
+ }
+
+ /**
+ * Returns Eigenvalue
+ *
+ * @param i
+ * Index of diagonal within matrix
+ *
+ * @return Returns value of diagonal from matrix
+ */
+ public double getEigenvalue(int i)
+ {
+ return eigenMatrix.getD()[i];
+ }
+
+ /**
+ * Returns coordinates for each datapoint
+ *
+ * @param l
+ * DOCUMENT ME!
+ * @param n
+ * DOCUMENT ME!
+ * @param mm
+ * DOCUMENT ME!
+ * @param factor ~ is 1
+ *
+ * @return DOCUMENT ME!
+ */
+ public Point[] getComponents(int l, int n, int mm, float factor)
+ {
+ Point[] out = new Point[getHeight()];
+
+ for (int i = 0; i < out.length; i++)
+ {
+ float x = (float) component(i, l) * factor;
+ float y = (float) component(i, n) * factor;
+ float z = (float) component(i, mm) * factor;
+ out[i] = new Point(x, y, z);
+ }
+
+ return out;
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @param n
+ * DOCUMENT ME!
+ *
+ * @return DOCUMENT ME!
+ */
+ public double[] component(int n)
+ {
+ // n = index of eigenvector
+ double[] out = new double[getWidth()];
+
+ for (int i = 0; i < out.length; i++)
+ {
+ out[i] = component(n, i);
+ }
+
+ return out;
+ }
+
+ /**
+ * DOCUMENT ME!
+ *
+ * @param row
+ * DOCUMENT ME!
+ * @param n
+ * DOCUMENT ME!
+ *
+ * @return DOCUMENT ME!
+ */
+ double component(int row, int n)
+ {
+ return eigenMatrix.getValue(row, n);
+ }
+
+ /**
+ * Answers a formatted text report of the PaSiMap calculation results (matrices
+ * and eigenvalues) suitable for display
+ *
+ * @return
+ */
+ public String getDetails()
+ {
+ StringBuilder sb = new StringBuilder(1024);
+ sb.append("PaSiMap calculation using ").append(scoreModel.getName())
+ .append(" sequence similarity matrix\n========\n\n");
+ PrintStream ps = wrapOutputBuffer(sb);
+
+ /*
+ * coordinates matrix, with D vector
+ */
+ sb.append(" --- Pairwise correlation coefficients ---\n");
+ pairwiseScores.print(ps, "%8.6f ");
+ ps.println();
+
+ sb.append(" --- Eigenvalues ---\n");
+ eigenMatrix.printD(ps, "%15.4e");
+ ps.println();
+
+ sb.append(" --- Coordinates ---\n");
+ eigenMatrix.print(ps, "%8.6f ");
+ ps.println();
+
+ return sb.toString();
+ }
+
+ /**
+ * Performs the PaSiMap calculation
+ *
+ * creates a new gui/PairwiseAlignPanel with the input sequences (AlignmentViewport)
+ * uses analysis/AlignSeq to creatue the pairwise alignments and calculate the AlignmentScores (float for each pair)
+ * gets all float[][] scores from the gui/PairwiseAlignPanel
+ * checks the connections for each sequence with AlignmentViewport seqs.calculateConnectivity(float[][] scores, int dim) (from analysis/Connectivity) -- throws an Exception if insufficient
+ * creates a math/MatrixI pairwiseScores of the float[][] scores
+ * copys the scores and fills the diagonal to create a symmetric matrix using math/Matrix.fillDiagonal()
+ * performs the analysis/ccAnalysis with the symmetric matrix
+ * gets the eigenmatrix and the eigenvalues using math/Matrix.tqli()
+ */
+ @Override
+ public void run()
+ {
+ try
+ {
+ //alignment = new PairwiseAlignPanel(seqs, true, 100, 5);
+ alignment.calculate();
+ float[][] scores = alignment.getAlignmentScores(); //bigger index first -- eg scores[14][13]
+
+ seqs.calculateConnectivity(scores, dim);
+
+ pairwiseScores = new Matrix(scores);
+ pairwiseScores.fillDiagonal();
+
+ eigenMatrix = pairwiseScores.copy();
+
+ ccAnalysis cc = new ccAnalysis(pairwiseScores, dim);
+ eigenMatrix = cc.run().mirrorCol();
+
+ } catch (Exception q)
+ {
+ Console.error("Error computing PaSiMap: " + q.getMessage());
+ q.printStackTrace();
+ }
+ }
+
+ /**
+ * Returns a PrintStream that wraps (appends its output to) the given
+ * StringBuilder
+ *
+ * @param sb
+ * @return
+ */
+ protected PrintStream wrapOutputBuffer(StringBuilder sb)
+ {
+ PrintStream ps = new PrintStream(System.out)
+ {
+ @Override
+ public void print(String x)
+ {
+ sb.append(x);
+ }
+
+ @Override
+ public void println()
+ {
+ sb.append("\n");
+ }
+ };
+ return ps;
+ }
+
+ /**
+ * Answers the N dimensions of the NxM PaSiMap matrix. This is the number of
+ * sequences involved in the pairwise score calculation.
+ *
+ * @return
+ */
+ public int getHeight()
+ {
+ // TODO can any of seqs[] be null?
+ return eigenMatrix.height();// seqs.getSequences().length;
+ }
+
+ /**
+ * Answers the M dimensions of the NxM PaSiMap matrix. This is the number of
+ * sequences involved in the pairwise score calculation.
+ *
+ * @return
+ */
+ public int getWidth()
+ {
+ // TODO can any of seqs[] be null?
+ return eigenMatrix.width();// seqs.getSequences().length;
+ }
+
+ /**
+ * Answers the sequence pairwise similarity scores which were the first step
+ * of the PaSiMap calculation
+ *
+ * @return
+ */
+ public MatrixI getPairwiseScores()
+ {
+ return pairwiseScores;
+ }
+
+ public void setPairwiseScores(MatrixI m)
+ {
+ pairwiseScores = m;
+ }
+
+ public MatrixI getEigenmatrix()
+ {
+ return eigenMatrix;
+ }
+
+ public void setEigenmatrix(MatrixI m)
+ {
+ eigenMatrix = m;
+ }
+
+ public PairwiseAlignPanel getAlignments()
+ {
+ return alignment;
+ }
+
+ public String getAlignmentOutput()
+ {
+ return alignment.getAlignmentOutput();
+ }
+
+ public byte getDim()
+ {
+ return dim;
+ }
+}
--- /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.
+ */
+
+/*
+* Copyright 2018-2022 Kathy Su, Kay Diederichs
+*
+* This program 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.
+*
+* This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+/**
+* Ported from https://doi.org/10.1107/S2059798317000699 by
+* @AUTHOR MorellThomas
+*/
+
+package jalview.analysis;
+
+import jalview.bin.Console;
+import jalview.math.MatrixI;
+import jalview.math.Matrix;
+import jalview.math.MiscMath;
+
+import java.lang.Math;
+import java.lang.System;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+
+import org.apache.commons.math3.linear.Array2DRowRealMatrix;
+import org.apache.commons.math3.linear.SingularValueDecomposition;
+
+/**
+ * A class to model rectangular matrices of double values and operations on them
+ */
+public class ccAnalysis
+{
+ private byte dim = 0; //dimensions
+
+ private MatrixI scoresOld; //input scores
+
+ public ccAnalysis(MatrixI scores, byte dim)
+ {
+ // round matrix to .4f to be same as in pasimap
+ for (int i = 0; i < scores.height(); i++)
+ {
+ for (int j = 0; j < scores.width(); j++)
+ {
+ if (!Double.isNaN(scores.getValue(i,j)))
+ {
+ scores.setValue(i, j, (double) Math.round(scores.getValue(i,j) * (int) 10000) / 10000);
+ }
+ }
+ }
+ this.scoresOld = scores;
+ this.dim = dim;
+ }
+
+ /**
+ * Initialise a distrust-score for each hypothesis (h) of hSigns
+ * distrust = conHypNum - proHypNum
+ *
+ * @param hSigns ~ hypothesis signs (+/-) for each sequence
+ * @param scores ~ input score matrix
+ *
+ * @return distrustScores
+ */
+ private int[] initialiseDistrusts(byte[] hSigns, MatrixI scores)
+ {
+ int[] distrustScores = new int[scores.width()];
+
+ // loop over symmetric matrix
+ for (int i = 0; i < scores.width(); i++)
+ {
+ byte hASign = hSigns[i];
+ int conHypNum = 0;
+ int proHypNum = 0;
+
+ for (int j = 0; j < scores.width(); j++)
+ {
+ double cell = scores.getRow(i)[j]; // value at [i][j] in scores
+ byte hBSign = hSigns[j];
+ if (!Double.isNaN(cell))
+ {
+ byte cellSign = (byte) Math.signum(cell); //check if sign of matrix value fits hyptohesis
+ if (cellSign == hASign * hBSign)
+ {
+ proHypNum++;
+ } else {
+ conHypNum++;
+ }
+ }
+ }
+ distrustScores[i] = conHypNum - proHypNum; //create distrust score for each sequence
+ }
+ return distrustScores;
+ }
+
+ /**
+ * Optemise hypothesis concerning the sign of the hypothetical value for each hSigns by interpreting the pairwise correlation coefficients as scalar products
+ *
+ * @param hSigns ~ hypothesis signs (+/-)
+ * @param distrustScores
+ * @param scores ~ input score matrix
+ *
+ * @return hSigns
+ */
+ private byte[] optimiseHypothesis(byte[] hSigns, int[] distrustScores, MatrixI scores)
+ {
+ // get maximum distrust score
+ int[] maxes = MiscMath.findMax(distrustScores);
+ int maxDistrustIndex = maxes[0];
+ int maxDistrust = maxes[1];
+
+ // if hypothesis is not optimal yet
+ if (maxDistrust > 0)
+ {
+ //toggle sign for hI with maximum distrust
+ hSigns[maxDistrustIndex] *= -1;
+ // update distrust at same position
+ distrustScores[maxDistrustIndex] *= -1;
+
+ // also update distrust scores for all hI that were not changed
+ byte hASign = hSigns[maxDistrustIndex];
+ for (int NOTmaxDistrustIndex = 0; NOTmaxDistrustIndex < distrustScores.length; NOTmaxDistrustIndex++)
+ {
+ if (NOTmaxDistrustIndex != maxDistrustIndex)
+ {
+ byte hBSign = hSigns[NOTmaxDistrustIndex];
+ double cell = scores.getValue(maxDistrustIndex, NOTmaxDistrustIndex);
+
+ // distrust only changed if not NaN
+ if (!Double.isNaN(cell))
+ {
+ byte cellSign = (byte) Math.signum(cell);
+ // if sign of cell matches hypothesis decrease distrust by 2 because 1 more value supporting and 1 less contradicting
+ // else increase by 2
+ if (cellSign == hASign * hBSign)
+ {
+ distrustScores[NOTmaxDistrustIndex] -= 2;
+ } else {
+ distrustScores[NOTmaxDistrustIndex] += 2;
+ }
+ }
+ }
+ }
+ //further optimisation necessary
+ return optimiseHypothesis(hSigns, distrustScores, scores);
+
+ } else {
+ return hSigns;
+ }
+ }
+
+ /**
+ * takes the a symmetric MatrixI as input scores which may contain Double.NaN
+ * approximate the missing values using hypothesis optimisation
+ *
+ * runs analysis
+ *
+ * @param scores ~ score matrix
+ *
+ * @return
+ */
+ public MatrixI run () throws Exception
+ {
+ //initialse eigenMatrix and repMatrix
+ MatrixI eigenMatrix = scoresOld.copy();
+ MatrixI repMatrix = scoresOld.copy();
+ try
+ {
+ /*
+ * Calculate correction factor for 2nd and higher eigenvalue(s).
+ * This correction is NOT needed for the 1st eigenvalue, because the
+ * unknown (=NaN) values of the matrix are approximated by presuming
+ * 1-dimensional vectors as the basis of the matrix interpretation as dot
+ * products.
+ */
+
+ System.out.println("Input correlation matrix:");
+ eigenMatrix.print(System.out, "%1.4f ");
+
+ int matrixWidth = eigenMatrix.width(); // square matrix, so width == height
+ int matrixElementsTotal = (int) Math.pow(matrixWidth, 2); //total number of elemts
+
+ float correctionFactor = (float) (matrixElementsTotal - eigenMatrix.countNaN()) / (float) matrixElementsTotal;
+
+ /*
+ * Calculate hypothetical value (1-dimensional vector) h_i for each
+ * dataset by interpreting the given correlation coefficients as scalar
+ * products.
+ */
+
+ /*
+ * Memory for current hypothesis concerning sign of each h_i.
+ * List of signs for all h_i in the encoding:
+ * * 1: positive
+ * * 0: zero
+ * * -1: negative
+ * Initial hypothesis: all signs are positive.
+ */
+ byte[] hSigns = new byte[matrixWidth];
+ Arrays.fill(hSigns, (byte) 1);
+
+ //Estimate signs for each h_i by refining hypothesis on signs.
+ hSigns = optimiseHypothesis(hSigns, initialiseDistrusts(hSigns, eigenMatrix), eigenMatrix);
+
+
+ //Estimate absolute values for each h_i by determining sqrt of mean of
+ //non-NaN absolute values for every row.
+ double[] hAbs = MiscMath.sqrt(eigenMatrix.absolute().meanRow());
+
+ //Combine estimated signs with absolute values in obtain total value for
+ //each h_i.
+ double[] hValues = MiscMath.elementwiseMultiply(hSigns, hAbs);
+
+ /*Complement symmetric matrix by using the scalar products of estimated
+ *values of h_i to replace NaN-cells.
+ *Matrix positions that have estimated values
+ *(only for diagonal and upper off-diagonal values, due to the symmetry
+ *the positions of the lower-diagonal values can be inferred).
+ List of tuples (row_idx, column_idx).*/
+
+ ArrayList<int[]> estimatedPositions = new ArrayList<int[]>();
+
+ // for off-diagonal cells
+ for (int rowIndex = 0; rowIndex < matrixWidth - 1; rowIndex++)
+ {
+ for (int columnIndex = rowIndex + 1; columnIndex < matrixWidth; columnIndex++)
+ {
+ double cell = eigenMatrix.getValue(rowIndex, columnIndex);
+ if (Double.isNaN(cell))
+ {
+ //calculate scalar product as new cell value
+ cell = hValues[rowIndex] * hValues[columnIndex];
+ //fill in new value in cell and symmetric partner
+ eigenMatrix.setValue(rowIndex, columnIndex, cell);
+ eigenMatrix.setValue(columnIndex, rowIndex, cell);
+ //save positions of estimated values
+ estimatedPositions.add(new int[]{rowIndex, columnIndex});
+ }
+ }
+ }
+
+ // for diagonal cells
+ for (int diagonalIndex = 0; diagonalIndex < matrixWidth; diagonalIndex++)
+ {
+ double cell = Math.pow(hValues[diagonalIndex], 2);
+ eigenMatrix.setValue(diagonalIndex, diagonalIndex, cell);
+ estimatedPositions.add(new int[]{diagonalIndex, diagonalIndex});
+ }
+
+ /*Refine total values of each h_i:
+ *Initialise h_values of the hypothetical non-existant previous iteration
+ *with the correct format but with impossible values.
+ Needed for exit condition of otherwise endless loop.*/
+ System.out.print("initial values: [ ");
+ for (double h : hValues)
+ {
+ System.out.print(String.format("%1.4f, ", h));
+ }
+ System.out.println(" ]");
+
+
+ double[] hValuesOld = new double[matrixWidth];
+
+ int iterationCount = 0;
+
+ // repeat unitl values of h do not significantly change anymore
+ while (true)
+ {
+ for (int hIndex = 0; hIndex < matrixWidth; hIndex++)
+ {
+ double newH = Arrays.stream(MiscMath.elementwiseMultiply(hValues, eigenMatrix.getRow(hIndex))).sum() / Arrays.stream(MiscMath.elementwiseMultiply(hValues, hValues)).sum();
+ hValues[hIndex] = newH;
+ }
+
+ System.out.print(String.format("iteration %d: [ ", iterationCount));
+ for (double h : hValues)
+ {
+ System.out.print(String.format("%1.4f, ", h));
+ }
+ System.out.println(" ]");
+
+ //update values of estimated positions
+ for (int[] pair : estimatedPositions) // pair ~ row, col
+ {
+ double newVal = hValues[pair[0]] * hValues[pair[1]];
+ eigenMatrix.setValue(pair[0], pair[1], newVal);
+ eigenMatrix.setValue(pair[1], pair[0], newVal);
+ }
+
+ iterationCount++;
+
+ //exit loop as soon as new values are similar to the last iteration
+ if (MiscMath.allClose(hValues, hValuesOld, 0d, 1e-05d, false))
+ {
+ break;
+ }
+
+ //save hValues for comparison in the next iteration
+ System.arraycopy(hValues, 0, hValuesOld, 0, hValues.length);
+ }
+
+ //-----------------------------
+ //Use complemented symmetric matrix to calculate final representative
+ //vectors.
+
+ //Eigendecomposition.
+ eigenMatrix.tred();
+ eigenMatrix.tqli();
+
+ System.out.println("eigenmatrix");
+ eigenMatrix.print(System.out, "%8.2f");
+ System.out.println();
+ System.out.println("uncorrected eigenvalues");
+ eigenMatrix.printD(System.out, "%2.4f ");
+ System.out.println();
+
+ double[] eigenVals = eigenMatrix.getD();
+
+ TreeMap<Double, Integer> eigenPairs = new TreeMap<>(Comparator.reverseOrder());
+ for (int i = 0; i < eigenVals.length; i++)
+ {
+ eigenPairs.put(eigenVals[i], i);
+ }
+
+ // matrix of representative eigenvectors (each row is a vector)
+ double[][] _repMatrix = new double[eigenVals.length][dim];
+ double[][] _oldMatrix = new double[eigenVals.length][dim];
+ double[] correctedEigenValues = new double[dim];
+
+ int l = 0;
+ for (Entry<Double, Integer> pair : eigenPairs.entrySet())
+ {
+ double eigenValue = pair.getKey();
+ int column = pair.getValue();
+ double[] eigenVector = eigenMatrix.getColumn(column);
+ //for 2nd and higher eigenvalues
+ if (l >= 1)
+ {
+ eigenValue /= correctionFactor;
+ }
+ correctedEigenValues[l] = eigenValue;
+ for (int j = 0; j < eigenVector.length; j++)
+ {
+ _repMatrix[j][l] = (eigenValue < 0) ? 0.0 : - Math.sqrt(eigenValue) * eigenVector[j];
+ double tmpOldScore = scoresOld.getColumn(column)[j];
+ _oldMatrix[j][dim - l - 1] = (Double.isNaN(tmpOldScore)) ? 0.0 : tmpOldScore;
+ }
+ l++;
+ if (l >= dim)
+ {
+ break;
+ }
+ }
+
+ System.out.println("correctedEigenValues");
+ MiscMath.print(correctedEigenValues, "%2.4f ");
+
+ repMatrix = new Matrix(_repMatrix);
+ repMatrix.setD(correctedEigenValues);
+ MatrixI oldMatrix = new Matrix(_oldMatrix);
+
+ MatrixI dotMatrix = repMatrix.postMultiply(repMatrix.transpose());
+
+ double rmsd = scoresOld.rmsd(dotMatrix);
+
+ System.out.println("iteration, rmsd, maxDiff, rmsdDiff");
+ System.out.println(String.format("0, %8.5f, -, -", rmsd));
+ // Refine representative vectors by minimising sum-of-squared deviates between dotMatrix and original score matrix
+ for (int iteration = 1; iteration < 21; iteration++) // arbitrarily set to 20
+ {
+ MatrixI repMatrixOLD = repMatrix.copy();
+ MatrixI dotMatrixOLD = dotMatrix.copy();
+
+ // for all rows/hA in the original matrix
+ for (int hAIndex = 0; hAIndex < oldMatrix.height(); hAIndex++)
+ {
+ double[] row = oldMatrix.getRow(hAIndex);
+ double[] hA = repMatrix.getRow(hAIndex);
+ hAIndex = hAIndex;
+ //find least-squares-solution fo rdifferences between original scores and representative vectors
+ double[] hAlsm = leastSquaresOptimisation(repMatrix, scoresOld, hAIndex);
+ // update repMatrix with new hAlsm
+ for (int j = 0; j < repMatrix.width(); j++)
+ {
+ repMatrix.setValue(hAIndex, j, hAlsm[j]);
+ }
+ }
+
+ // dot product of representative vecotrs yields a matrix with values approximating the correlation matrix
+ dotMatrix = repMatrix.postMultiply(repMatrix.transpose());
+ // calculate rmsd between approximation and correlation matrix
+ rmsd = scoresOld.rmsd(dotMatrix);
+
+ // calculate maximum change of representative vectors of current iteration
+ MatrixI diff = repMatrix.subtract(repMatrixOLD).absolute();
+ double maxDiff = 0.0;
+ for (int i = 0; i < diff.height(); i++)
+ {
+ for (int j = 0; j < diff.width(); j++)
+ {
+ maxDiff = (diff.getValue(i, j) > maxDiff) ? diff.getValue(i, j) : maxDiff;
+ }
+ }
+
+ // calculate rmsd between current and previous estimation
+ double rmsdDiff = dotMatrix.rmsd(dotMatrixOLD);
+
+ System.out.println(String.format("%d, %8.5f, %8.5f, %8.5f", iteration, rmsd, maxDiff, rmsdDiff));
+
+ if (!(Math.abs(maxDiff) > 1e-06))
+ {
+ repMatrix = repMatrixOLD.copy();
+ break;
+ }
+ }
+
+
+ } catch (Exception q)
+ {
+ Console.error("Error computing cc_analysis: " + q.getMessage());
+ q.printStackTrace();
+ }
+ System.out.println("final coordinates:");
+ repMatrix.print(System.out, "%1.8f ");
+ return repMatrix;
+ }
+
+ /**
+ * Create equations system using information on originally known
+ * pairwise correlation coefficients (parsed from infile) and the
+ * representative result vectors
+ *
+ * Each equation has the format:
+ * hA * hA - pairwiseCC = 0
+ * with:
+ * hA: unknown variable
+ * hB: known representative vector
+ * pairwiseCC: known pairwise correlation coefficien
+ *
+ * The resulting equations system is overdetermined, if there are more
+ * equations than unknown elements
+ *
+ * @param x ~ unknown n-dimensional column-vector
+ * (needed for generating equations system, NOT to be specified by user).
+ * @param hAIndex ~ index of currently optimised representative result vector.
+ * @param h ~ matrix with row-wise listing of representative result vectors.
+ * @param originalRow ~ matrix-row of originally parsed pairwise correlation coefficients.
+ *
+ * @return
+ */
+ private double[] originalToEquasionSystem(double[] hA, MatrixI repMatrix, MatrixI scoresOld, int hAIndex)
+ {
+ double[] originalRow = scoresOld.getRow(hAIndex);
+ int nans = MiscMath.countNaN(originalRow);
+ double[] result = new double[originalRow.length - nans];
+
+ //for all pairwiseCC in originalRow
+ int resultIndex = 0;
+ for (int hBIndex = 0; hBIndex < originalRow.length; hBIndex++)
+ {
+ double pairwiseCC = originalRow[hBIndex];
+ // if not NaN -> create new equation and add it to the system
+ if (!Double.isNaN(pairwiseCC))
+ {
+ double[] hB = repMatrix.getRow(hBIndex);
+ result[resultIndex++] = MiscMath.sum(MiscMath.elementwiseMultiply(hA, hB)) - pairwiseCC;
+ } else {
+ }
+ }
+ return result;
+ }
+
+ /**
+ * returns the jacobian matrix
+ * @param repMatrix ~ matrix of representative vectors
+ * @param hAIndex ~ current row index
+ *
+ * @return
+ */
+ private MatrixI approximateDerivative(MatrixI repMatrix, MatrixI scoresOld, int hAIndex)
+ {
+ //hA = x0
+ double[] hA = repMatrix.getRow(hAIndex);
+ double[] f0 = originalToEquasionSystem(hA, repMatrix, scoresOld, hAIndex);
+ double[] signX0 = new double[hA.length];
+ double[] xAbs = new double[hA.length];
+ for (int i = 0; i < hA.length; i++)
+ {
+ signX0[i] = (hA[i] >= 0) ? 1 : -1;
+ xAbs[i] = (Math.abs(hA[i]) >= 1.0) ? Math.abs(hA[i]) : 1.0;
+ }
+ double rstep = Math.pow(Math.ulp(1.0), 0.5);
+
+ double[] h = new double [hA.length];
+ for (int i = 0; i < hA.length; i++)
+ {
+ h[i] = rstep * signX0[i] * xAbs[i];
+ }
+
+ int m = f0.length;
+ int n = hA.length;
+ double[][] jTransposed = new double[n][m];
+ for (int i = 0; i < h.length; i++)
+ {
+ double[] x = new double[h.length];
+ System.arraycopy(hA, 0, x, 0, h.length);
+ x[i] += h[i];
+ double dx = x[i] - hA[i];
+ double[] df = originalToEquasionSystem(x, repMatrix, scoresOld, hAIndex);
+ for (int j = 0; j < df.length; j++)
+ {
+ df[j] -= f0[j];
+ jTransposed[i][j] = df[j] / dx;
+ }
+ }
+ MatrixI J = new Matrix(jTransposed).transpose();
+ return J;
+ }
+
+ /**
+ * norm of regularized (by alpha) least-squares solution minus Delta
+ * @param alpha
+ * @param suf
+ * @param s
+ * @param Delta
+ *
+ * @return
+ */
+ private double[] phiAndDerivative(double alpha, double[] suf, double[] s, double Delta)
+ {
+ double[] denom = MiscMath.elementwiseAdd(MiscMath.elementwiseMultiply(s, s), alpha);
+ double pNorm = MiscMath.norm(MiscMath.elementwiseDivide(suf, denom));
+ double phi = pNorm - Delta;
+ // - sum ( suf**2 / denom**3) / pNorm
+ double phiPrime = - MiscMath.sum(MiscMath.elementwiseDivide(MiscMath.elementwiseMultiply(suf, suf), MiscMath.elementwiseMultiply(MiscMath.elementwiseMultiply(denom, denom), denom))) / pNorm;
+ return new double[]{phi, phiPrime};
+ }
+
+ /**
+ * class holding the result of solveLsqTrustRegion
+ */
+ private class TrustRegion
+ {
+ private double[] step;
+ private double alpha;
+ private int iteration;
+
+ public TrustRegion(double[] step, double alpha, int iteration)
+ {
+ this.step = step;
+ this.alpha = alpha;
+ this.iteration = iteration;
+ }
+
+ public double[] getStep()
+ {
+ return this.step;
+ }
+
+ public double getAlpha()
+ {
+ return this.alpha;
+ }
+
+ public int getIteration()
+ {
+ return this.iteration;
+ }
+ }
+
+ /**
+ * solve a trust-region problem arising in least-squares optimisation
+ * @param n ~ number of variables
+ * @param m ~ number of residuals
+ * @param uf
+ * @param s ~ singular values of J
+ * @param V ~ transpose of VT
+ * @param Delta ~ radius of a trust region
+ * @param alpha ~ initial guess for alpha
+ *
+ * @return
+ */
+ private TrustRegion solveLsqTrustRegion(int n, int m, double[] uf, double[] s, MatrixI V, double Delta, double alpha)
+ {
+ double[] suf = MiscMath.elementwiseMultiply(s, uf);
+
+ //check if J has full rank and tr Gauss-Newton step
+ boolean fullRank = false;
+ if (m >= n)
+ {
+ double threshold = s[0] * Math.ulp(1.0) * m;
+ fullRank = s[s.length - 1] > threshold;
+ }
+ if (fullRank)
+ {
+ double[] p = MiscMath.elementwiseMultiply(V.sumProduct(MiscMath.elementwiseDivide(uf, s)), -1);
+ if (MiscMath.norm(p) <= Delta)
+ {
+ TrustRegion result = new TrustRegion(p, 0.0, 0);
+ return result;
+ }
+ }
+
+ double alphaUpper = MiscMath.norm(suf) / Delta;
+ double alphaLower = 0.0;
+ if (fullRank)
+ {
+ double[] phiAndPrime = phiAndDerivative(0.0, suf, s, Delta);
+ alphaLower = - phiAndPrime[0] / phiAndPrime[1];
+ }
+
+ alpha = (!fullRank && alpha == 0.0) ? alpha = Math.max(0.001 * alphaUpper, Math.pow(alphaLower * alphaUpper, 0.5)) : alpha;
+
+ int iteration = 0;
+ while (iteration < 10) // 10 is default max_iter
+ {
+ alpha = (alpha < alphaLower || alpha > alphaUpper) ? alpha = Math.max(0.001 * alphaUpper, Math.pow(alphaLower * alphaUpper, 0.5)) : alpha;
+ double[] phiAndPrime = phiAndDerivative(alpha, suf, s, Delta);
+ double phi = phiAndPrime[0];
+ double phiPrime = phiAndPrime[1];
+
+ alphaUpper = (phi < 0) ? alpha : alphaUpper;
+ double ratio = phi / phiPrime;
+ alphaLower = Math.max(alphaLower, alpha - ratio);
+ alpha -= (phi + Delta) * ratio / Delta;
+
+ if (Math.abs(phi) < 0.01 * Delta) // default rtol set to 0.01
+ {
+ break;
+ }
+ iteration++;
+ }
+
+ // p = - V.dot( suf / (s**2 + alpha))
+ double[] tmp = MiscMath.elementwiseDivide(suf, MiscMath.elementwiseAdd(MiscMath.elementwiseMultiply(s, s), alpha));
+ double[] p = MiscMath.elementwiseMultiply(V.sumProduct(tmp), -1);
+
+ // Make the norm of p equal to Delta, p is changed only slightly during this.
+ // It is done to prevent p lie outside of the trust region
+ p = MiscMath.elementwiseMultiply(p, Delta / MiscMath.norm(p));
+
+ TrustRegion result = new TrustRegion(p, alpha, iteration + 1);
+ return result;
+ }
+
+ /**
+ * compute values of a quadratic function arising in least squares
+ * function: 0.5 * s.T * (J.T * J + diag) * s + g.T * s
+ *
+ * @param J ~ jacobian matrix
+ * @param g ~ gradient
+ * @param s ~ steps and rows
+ *
+ * @return
+ */
+ private double evaluateQuadratic(MatrixI J, double[] g, double[] s)
+ {
+
+ double[] Js = J.sumProduct(s);
+ double q = MiscMath.dot(Js, Js);
+ double l = MiscMath.dot(s, g);
+
+ return 0.5 * q + l;
+ }
+
+ /**
+ * update the radius of a trust region based on the cost reduction
+ *
+ * @param Delta
+ * @param actualReduction
+ * @param predictedReduction
+ * @param stepNorm
+ * @param boundHit
+ *
+ * @return
+ */
+ private double[] updateTrustRegionRadius(double Delta, double actualReduction, double predictedReduction, double stepNorm, boolean boundHit)
+ {
+ double ratio = 0;
+ if (predictedReduction > 0)
+ {
+ ratio = actualReduction / predictedReduction;
+ } else if (predictedReduction == 0 && actualReduction == 0) {
+ ratio = 1;
+ } else {
+ ratio = 0;
+ }
+
+ if (ratio < 0.25)
+ {
+ Delta = 0.25 * stepNorm;
+ } else if (ratio > 0.75 && boundHit) {
+ Delta *= 2.0;
+ }
+
+ return new double[]{Delta, ratio};
+ }
+
+ /**
+ * trust region reflective algorithm
+ * @param repMatrix ~ Matrix containing representative vectors
+ * @param scoresOld ~ Matrix containing initial observations
+ * @param index ~ current row index
+ * @param J ~ jacobian matrix
+ *
+ * @return
+ */
+ private double[] trf(MatrixI repMatrix, MatrixI scoresOld, int index, MatrixI J)
+ {
+ //hA = x0
+ double[] hA = repMatrix.getRow(index);
+ double[] f0 = originalToEquasionSystem(hA, repMatrix, scoresOld, index);
+ int nfev = 1;
+ int m = J.height();
+ int n = J.width();
+ double cost = 0.5 * MiscMath.dot(f0, f0);
+ double[] g = J.transpose().sumProduct(f0);
+ double Delta = MiscMath.norm(hA);
+ int maxNfev = hA.length * 100;
+ double alpha = 0.0; // "Levenberg-Marquardt" parameter
+
+ double gNorm = 0;
+ boolean terminationStatus = false;
+ int iteration = 0;
+
+ while (true)
+ {
+ gNorm = MiscMath.norm(g);
+ if (terminationStatus || nfev == maxNfev)
+ {
+ break;
+ }
+ SingularValueDecomposition svd = new SingularValueDecomposition(new Array2DRowRealMatrix(J.asArray()));
+ MatrixI U = new Matrix(svd.getU().getData());
+ double[] s = svd.getSingularValues();
+ MatrixI V = new Matrix(svd.getV().getData()).transpose();
+ double[] uf = U.transpose().sumProduct(f0);
+
+ double actualReduction = -1;
+ double[] xNew = new double[hA.length];
+ double[] fNew = new double[f0.length];
+ double costNew = 0;
+ double stepHnorm = 0;
+
+ while (actualReduction <= 0 && nfev < maxNfev)
+ {
+ TrustRegion trustRegion = solveLsqTrustRegion(n, m, uf, s, V, Delta, alpha);
+ double[] stepH = trustRegion.getStep();
+ alpha = trustRegion.getAlpha();
+ int nIterations = trustRegion.getIteration();
+ double predictedReduction = - (evaluateQuadratic(J, g, stepH));
+
+ xNew = MiscMath.elementwiseAdd(hA, stepH);
+ fNew = originalToEquasionSystem(xNew, repMatrix, scoresOld, index);
+ nfev++;
+
+ stepHnorm = MiscMath.norm(stepH);
+
+ if (MiscMath.countNaN(fNew) > 0)
+ {
+ Delta = 0.25 * stepHnorm;
+ continue;
+ }
+
+ // usual trust-region step quality estimation
+ costNew = 0.5 * MiscMath.dot(fNew, fNew);
+ actualReduction = cost - costNew;
+
+ double[] updatedTrustRegion = updateTrustRegionRadius(Delta, actualReduction, predictedReduction, stepHnorm, stepHnorm > (0.95 * Delta));
+ double DeltaNew = updatedTrustRegion[0];
+ double ratio = updatedTrustRegion[1];
+
+ // default ftol and xtol = 1e-8
+ boolean ftolSatisfied = actualReduction < (1e-8 * cost) && ratio > 0.25;
+ boolean xtolSatisfied = stepHnorm < (1e-8 * (1e-8 + MiscMath.norm(hA)));
+ terminationStatus = ftolSatisfied || xtolSatisfied;
+ if (terminationStatus)
+ {
+ break;
+ }
+
+ alpha *= Delta / DeltaNew;
+ Delta = DeltaNew;
+
+ }
+ if (actualReduction > 0)
+ {
+ hA = xNew;
+ f0 = fNew;
+ cost = costNew;
+
+ J = approximateDerivative(repMatrix, scoresOld, index);
+
+ g = J.transpose().sumProduct(f0);
+ } else {
+ stepHnorm = 0;
+ actualReduction = 0;
+ }
+ iteration++;
+ }
+
+ return hA;
+ }
+
+ /**
+ * performs the least squares optimisation
+ * adapted from https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.least_squares.html#scipy.optimize.least_squares
+ *
+ * @param repMatrix ~ Matrix containing representative vectors
+ * @param scoresOld ~ Matrix containing initial observations
+ * @param index ~ current row index
+ *
+ * @return
+ */
+ private double[] leastSquaresOptimisation(MatrixI repMatrix, MatrixI scoresOld, int index)
+ {
+ MatrixI J = approximateDerivative(repMatrix, scoresOld, index);
+ double[] result = trf(repMatrix, scoresOld, index, J);
+ return result;
+ }
+
+}
import javax.swing.AbstractButton;
import javax.swing.ButtonGroup;
-import javax.swing.ButtonModel;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JComponent;
import javax.swing.JEditorPane;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
+import javax.swing.JProgressBar;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;
}
@Override
+ public JProgressBar getProgressBar(long id)
+ {
+ if (progressBar != null)
+ return progressBar.getProgressBar(id);
+ return null;
+ }
+
+ @Override
public void registerHandler(final long id,
final IProgressIndicatorHandler handler)
{
*/
package jalview.gui;
+import jalview.analysis.TreeBuilder;
+import jalview.analysis.scoremodels.ScoreModels;
+import jalview.analysis.scoremodels.SimilarityParams;
+import jalview.api.analysis.ScoreModelI;
+import jalview.api.analysis.SimilarityParamsI;
+import jalview.bin.Cache;
+import jalview.datamodel.SequenceGroup;
+import jalview.util.MessageManager;
+import jalview.viewmodel.AlignmentViewport;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
}
+ private static final int MIN_PASIMAP_SELECTION = 8;
+
AlignFrame af;
JRadioButton pca;
+ JRadioButton pasimap;
+
JRadioButton neighbourJoining;
JRadioButton averageDistance;
*/
private PCAPanel pcaPanel;
+ private PaSiMapPanel pasimapPanel;
+
/**
* Constructor
*
MessageManager.getString("label.principal_component_analysis"));
pca.setOpaque(false);
+ pasimap = new JRadioButton( // create the JRadioButton for pasimap with label.pasimap as its text
+ MessageManager.getString("label.pasimap"));
+ pasimap.setOpaque(false);
+
neighbourJoining = new JRadioButton(
MessageManager.getString("label.tree_calc_nj"));
neighbourJoining.setSelected(true);
pcaBorderless.add(pca, FlowLayout.LEFT);
calcChoicePanel.add(pcaBorderless, FlowLayout.LEFT);
+ // create pasimap panel
+ JPanel pasimapBorderless = new JPanel(new FlowLayout(FlowLayout.LEFT)); // create new JPanel (button) for pasimap
+ pasimapBorderless.setBorder(
+ BorderFactory.createEmptyBorder(2, b.left, 2, b.right)); // set border (margin) for button (same as treePanel and pca)
+ pasimapBorderless.setOpaque(false); // false -> stops every pixel inside border from being painted
+ pasimapBorderless.add(pasimap, FlowLayout.LEFT); // add pasimap button to the JPanel
+ calcChoicePanel.add(pasimapBorderless, FlowLayout.LEFT); // add button with border and everything to the overall ChoicePanel
+
treePanel.add(neighbourJoining);
treePanel.add(averageDistance);
ButtonGroup calcTypes = new ButtonGroup();
calcTypes.add(pca);
+ calcTypes.add(pasimap);
calcTypes.add(neighbourJoining);
calcTypes.add(averageDistance);
}
};
pca.addActionListener(calcChanged);
+ pasimap.addActionListener(calcChanged); // add the calcChanged ActionListener to pasimap --> <++> idk
neighbourJoining.addActionListener(calcChanged);
averageDistance.addActionListener(calcChanged);
* return value of true means enabled and selected
*/
boolean checkPca = checkEnabled(pca, size, MIN_PCA_SELECTION);
+ boolean checkPasimap = checkEnabled(pasimap, size, MIN_PASIMAP_SELECTION); // check if pasimap is enabled and min_size is fulfilled
boolean checkNeighbourJoining = checkEnabled(neighbourJoining, size,
MIN_TREE_SELECTION);
boolean checkAverageDistance = checkEnabled(averageDistance, size,
MIN_TREE_SELECTION);
- if (checkPca || checkNeighbourJoining || checkAverageDistance)
+ if (checkPca || checkPasimap || checkNeighbourJoining || checkAverageDistance)
{
calculate.setToolTipText(null);
calculate.setEnabled(true);
protected void calculate_actionPerformed()
{
boolean doPCA = pca.isSelected();
+ boolean doPaSiMap = pasimap.isSelected();
String modelName = modelNames.getSelectedItem().toString();
String ssSource = "";
Object selectedItem = ssSourceDropdown.getSelectedItem();
{
params.setSecondaryStructureSource(ssSource);
}
- if (doPCA)
+
+ if (doPCA && !doPaSiMap)
{
openPcaPanel(modelName, params);
}
+ else if (doPaSiMap && !doPCA)
+ {
+ openPasimapPanel(modelName, params);
+ }
else
{
openTreePanel(modelName, params);
}
- // closeFrame();
+ closeFrame();
}
/**
}
/**
+ * Open a new PaSiMap panel on the desktop
+ *
+ * @param modelName
+ * @param params
+ */
+ protected void openPasimapPanel(String modelName, SimilarityParamsI params)
+ {
+ AlignViewport viewport = af.getViewport();
+
+ /*
+ * gui validation shouldn't allow insufficient sequences here, but leave
+ * this check in in case this method gets exposed programmatically in future
+ */
+ if (((viewport.getSelectionGroup() != null)
+ && (viewport.getSelectionGroup().getSize() < MIN_PASIMAP_SELECTION)
+ && (viewport.getSelectionGroup().getSize() > 0))
+ || (viewport.getAlignment().getHeight() < MIN_PASIMAP_SELECTION))
+ {
+ JvOptionPane.showInternalMessageDialog(this,
+ MessageManager.formatMessage(
+ "label.you_need_at_least_n_sequences",
+ MIN_PASIMAP_SELECTION),
+ MessageManager
+ .getString("label.sequence_selection_insufficient"),
+ JvOptionPane.WARNING_MESSAGE);
+ return;
+ }
+
+ /*
+ * construct the panel and kick off its calculation thread
+ */
+ pasimapPanel = new PaSiMapPanel(af.alignPanel, modelName, params);
+ new Thread(pasimapPanel).start();
+
+ }
+
+ /**
*
*/
protected void closeFrame()
*/
package jalview.gui;
+import java.awt.Font;
import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
}
/**
+ * set font size of the textarea
+ * @param size
+ */
+ public void setFont(Font font)
+ {
+ textarea.setFont(font);
+ }
+
+ /**
* DOCUMENT ME!
*/
public void setForInput(AlignmentViewPanel viewpanel)
{
}
}
+
+ /**
+ * show menu for changing the font
+ * @param e
+ */
+ @Override
+ public void fontSizeMenu_actionPerformed(ActionEvent e)
+ {
+ new FontChooser(this);
+ }
/**
* DOCUMENT ME!
}
}
+ @Override
+ public JProgressBar getProgressBar(long id)
+ {
+ if (progressBars == null)
+ return null;
+
+ if (progressBars.get(Long.valueOf(id)) == null)
+ return null;
+
+ for (Component c : progressBars.get(Long.valueOf(id)).getComponents())
+ {
+ if (c.getClass() == JProgressBar.class)
+ return (JProgressBar) c;
+ }
+ return null;
+ }
+
/*
* (non-Javadoc)
*
TreePanel tp;
+ CutAndPasteTransfer cap;
+
/*
* The font on opening the dialog (to be restored on Cancel)
*/
init();
}
+ /**
+ * Creates a new FontChooser for a CutAndPasteTransfer
+ * @param cap
+ */
+ public FontChooser(CutAndPasteTransfer cap)
+ {
+ oldFont = new Font("Monospaced", Font.PLAIN, 12);
+ this.cap = cap;
+ init();
+ }
+
void init()
{
frame = new JInternalFrame();
frame.setFrameIcon(null);
frame.setContentPane(this);
- smoothFont.setSelected(ap.av.antiAlias);
-
- /*
- * Enable 'scale protein as cDNA' in a SplitFrame view. The selection is
- * stored in the ViewStyle of both dna and protein Viewport. Also enable
- * checkbox for copy font changes to other half of split frame.
- */
- boolean inSplitFrame = ap.av.getCodingComplement() != null;
- if (inSplitFrame)
+ if (!isCapFont())
{
- oldComplementFont = ((AlignViewport) ap.av.getCodingComplement())
- .getFont();
- oldComplementSmooth = ((AlignViewport) ap.av
- .getCodingComplement()).antiAlias;
- scaleAsCdna.setVisible(true);
- scaleAsCdna.setSelected(ap.av.isScaleProteinAsCdna());
- fontAsCdna.setVisible(true);
- fontAsCdna.setSelected(ap.av.isProteinFontAsCdna());
+ smoothFont.setSelected(ap.av.antiAlias);
+
+ /*
+ * Enable 'scale protein as cDNA' in a SplitFrame view. The selection is
+ * stored in the ViewStyle of both dna and protein Viewport. Also enable
+ * checkbox for copy font changes to other half of split frame.
+ */
+ boolean inSplitFrame = ap.av.getCodingComplement() != null;
+ if (inSplitFrame)
+ {
+ oldComplementFont = ((AlignViewport) ap.av.getCodingComplement())
+ .getFont();
+ oldComplementSmooth = ((AlignViewport) ap.av
+ .getCodingComplement()).antiAlias;
+ scaleAsCdna.setVisible(true);
+ scaleAsCdna.setSelected(ap.av.isScaleProteinAsCdna());
+ fontAsCdna.setVisible(true);
+ fontAsCdna.setSelected(ap.av.isProteinFontAsCdna());
+ }
}
if (isTreeFont())
return tp != null;
}
+ private boolean isCapFont()
+ {
+ return cap != null;
+ }
/**
* DOCUMENT ME!
*/
splitFrame.repaint();
}
}
+ else if (isCapFont())
+ {
+ cap.setFont(newFont);
+ }
monospaced.setSelected(mw == iw);
*/
package jalview.gui;
+import javax.swing.JProgressBar;
+
/**
* Visual progress indicator interface.
*
*/
boolean operationInProgress();
+ /**
+ *
+ * @param id
+ * @return progressbar mapped to id
+ */
+ public JProgressBar getProgressBar(long id);
+
}
import javax.swing.ButtonGroup;
import javax.swing.JMenuItem;
+import javax.swing.JProgressBar;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.event.InternalFrameAdapter;
import javax.swing.event.InternalFrameEvent;
getRotatableCanvas().ap = panel;
PaintRefresher.Register(PCAPanel.this, panel.av.getSequenceSetId());
}
+
+ @Override
+ public JProgressBar getProgressBar(long id)
+ {
+ return progressBar.getProgressBar(id);
+ }
}
--- /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.gui;
+
+import jalview.analysis.scoremodels.ScoreModels;
+import jalview.api.AlignViewportI;
+import jalview.api.analysis.ScoreModelI;
+import jalview.api.analysis.SimilarityParamsI;
+import jalview.bin.Console;
+import jalview.datamodel.Alignment;
+import jalview.datamodel.AlignmentI;
+import jalview.datamodel.AlignmentView;
+import jalview.datamodel.HiddenColumns;
+import jalview.datamodel.SequenceI;
+import jalview.gui.ImageExporter.ImageWriterI;
+import jalview.gui.JalviewColourChooser.ColourChooserListener;
+import jalview.jbgui.GPaSiMapPanel;
+import jalview.math.RotatableMatrix.Axis;
+import jalview.util.ImageMaker;
+import jalview.util.MessageManager;
+import jalview.viewmodel.AlignmentViewport;
+import jalview.viewmodel.PaSiMapModel;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+import java.awt.print.PrinterJob;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import javax.swing.ButtonGroup;
+import javax.swing.JMenuItem;
+import javax.swing.JProgressBar;
+import javax.swing.JRadioButtonMenuItem;
+import javax.swing.event.InternalFrameAdapter;
+import javax.swing.event.InternalFrameEvent;
+
+/**
+ * The panel holding the Pairwise Similarity Map 3-D visualisation
+ */
+public class PaSiMapPanel extends GPaSiMapPanel
+ implements Runnable, IProgressIndicator
+{
+ private static final int MIN_WIDTH = 470;
+
+ private static final int MIN_HEIGHT = 250;
+
+ private final int GAP_OPEN_COST = 100;
+
+ private final int GAP_EXTEND_COST = 5;
+
+ private RotatableCanvas rc;
+
+ AlignmentPanel ap;
+
+ AlignmentViewport av;
+
+ private PaSiMapModel pasimapModel;
+
+ private int top = 0;
+
+ private IProgressIndicator progressBar;
+
+ private long progId;
+
+ private boolean working;
+
+ /**
+ * Constructor given sequence data, a similarity (or distance) score model
+ * name, and score calculation parameters
+ *
+ * @param alignPanel
+ * @param modelName
+ * @param params
+ */
+ public PaSiMapPanel(AlignmentPanel alignPanel, String modelName,
+ SimilarityParamsI params)
+ {
+ super(8); // dim = 8
+ this.av = alignPanel.av;
+ this.ap = alignPanel;
+ boolean nucleotide = av.getAlignment().isNucleotide();
+
+ //progressBar = new ProgressBar(statusPanel, statusBar);
+
+ addInternalFrameListener(new InternalFrameAdapter()
+ {
+ @Override
+ public void internalFrameClosed(InternalFrameEvent e)
+ {
+ close_actionPerformed();
+ }
+ });
+
+ boolean selected = av.getSelectionGroup() != null
+ && av.getSelectionGroup().getSize() > 0;
+ SequenceI[] seqs;
+ if (!selected)
+ {
+ seqs = av.getAlignment().getSequencesArray();
+ }
+ else
+ {
+ seqs = av.getSelectionGroup().getSequencesInOrder(av.getAlignment());
+ }
+
+ ScoreModelI scoreModel = ScoreModels.getInstance()
+ .getScoreModel(modelName, ap);
+ setPasimapModel(
+ new PaSiMapModel(av, seqs, nucleotide, scoreModel));
+ PaintRefresher.Register(this, av.getSequenceSetId());
+
+ setRotatableCanvas(new RotatableCanvas(alignPanel));
+ this.getContentPane().add(getRotatableCanvas(), BorderLayout.CENTER);
+
+ addKeyListener(getRotatableCanvas());
+ validate();
+ }
+
+ /**
+ * Ensure references to potentially very large objects (the PaSiMap matrices) are
+ * nulled when the frame is closed
+ */
+ protected void close_actionPerformed()
+ {
+ setPasimapModel(null);
+ if (this.rc != null)
+ {
+ this.rc.sequencePoints = null;
+ this.rc.setAxisEndPoints(null);
+ this.rc = null;
+ }
+ }
+
+ @Override
+ protected void bgcolour_actionPerformed()
+ {
+ String ttl = MessageManager.getString("label.select_background_colour");
+ ColourChooserListener listener = new ColourChooserListener()
+ {
+ @Override
+ public void colourSelected(Color c)
+ {
+ rc.setBgColour(c);
+ rc.repaint();
+ }
+ };
+ JalviewColourChooser.showColourChooser(this, ttl, rc.getBgColour(),
+ listener);
+ }
+
+ /**
+ * Calculates the PaSiMap and displays the results
+ */
+ @Override
+ public void run()
+ {
+ working = true;
+ progId = System.currentTimeMillis();
+ progressBar = this;
+ String message = MessageManager.getString("label.pasimap_recalculating");
+ if (getParent() == null)
+ {
+ progressBar = ap.alignFrame;
+ message = MessageManager.getString("label.pasimap_calculating");
+ }
+ progressBar.setProgressBar(message, progId);
+ try
+ {
+ //&! remove big seqs
+ for (SequenceI seq : av.getAlignment().getSequencesArray())
+ {
+ if (seq.getLength() > 20000)
+ {
+ //TODO add warning dialog
+ av.getAlignment().deleteSequence(seq);
+ }
+ }
+
+ PairwiseAlignPanel pap = new PairwiseAlignPanel(av, true, GAP_OPEN_COST, GAP_EXTEND_COST, false);
+System.out.println(pap != null);
+ setPairwiseAlignPanel(pap);
+ getPasimapModel().calculate(pap);
+
+ xCombobox.setSelectedIndex(0);
+ yCombobox.setSelectedIndex(1);
+ zCombobox.setSelectedIndex(2);
+
+ getPasimapModel().updateRc(getRotatableCanvas());
+ // rc.invalidate();
+ setTop(getPasimapModel().getTop());
+
+ } catch (OutOfMemoryError er)
+ {
+ new OOMWarning("calculating PaSiMap", er);
+ working = false;
+ return;
+ } finally
+ {
+ progressBar.setProgressBar("", progId);
+ }
+
+ repaint();
+ if (getParent() == null)
+ {
+ Desktop.addInternalFrame(this,
+ MessageManager.formatMessage("label.calc_title", "PaSiMap",
+ getPasimapModel().getScoreModelName()),
+ 475, 450);
+ this.setMinimumSize(new Dimension(MIN_WIDTH, MIN_HEIGHT));
+ }
+ working = false;
+ }
+
+ /**
+ * Updates the PaSiMap display after a change of component to use for x, y or z
+ * axis
+ */
+ @Override
+ protected void doDimensionChange()
+ {
+ if (getTop() == 0)
+ {
+ return;
+ }
+
+ int dim1 = getTop() - xCombobox.getSelectedIndex();
+ int dim2 = getTop() - yCombobox.getSelectedIndex();
+ int dim3 = getTop() - zCombobox.getSelectedIndex();
+ getPasimapModel().updateRcView(dim1, dim2, dim3);
+ getRotatableCanvas().resetView();
+ }
+
+ /**
+ * Sets the selected checkbox item index for PaSiMap dimension (1, 2, 3...) for
+ * the given axis (X/Y/Z)
+ *
+ * @param index
+ * @param axis
+ */
+ public void setSelectedDimensionIndex(int index, Axis axis)
+ {
+ switch (axis)
+ {
+ case X:
+ xCombobox.setSelectedIndex(index);
+ break;
+ case Y:
+ yCombobox.setSelectedIndex(index);
+ break;
+ case Z:
+ zCombobox.setSelectedIndex(index);
+ break;
+ default:
+ }
+ }
+
+ @Override
+ protected void outputValues_actionPerformed()
+ {
+ CutAndPasteTransfer cap = new CutAndPasteTransfer();
+ try
+ {
+ cap.setText(getPasimapModel().getDetails());
+ Desktop.addInternalFrame(cap,
+ MessageManager.getString("label.pasimap_details"), 500, 500);
+ } catch (OutOfMemoryError oom)
+ {
+ new OOMWarning("opening PaSiMap details", oom);
+ cap.dispose();
+ }
+ }
+
+ @Override
+ protected void showLabels_actionPerformed()
+ {
+ getRotatableCanvas().showLabels(showLabels.getState());
+ }
+
+ @Override
+ protected void print_actionPerformed()
+ {
+ PaSiMapPrinter printer = new PaSiMapPrinter();
+ printer.start();
+ }
+
+ /**
+ * If available, shows the data which formed the inputs for the PaSiMap as a new
+ * alignment
+ */
+ @Override
+ public void originalSeqData_actionPerformed()
+ {
+ // JAL-2647 disabled after load from project (until save to project done)
+ if (getPasimapModel().getInputData() == null)
+ {
+ Console.info(
+ "Unexpected call to originalSeqData_actionPerformed - should have hidden this menu action.");
+ return;
+ }
+ // decide if av alignment is sufficiently different to original data to
+ // warrant a new window to be created
+ // create new alignment window with hidden regions (unhiding hidden regions
+ // yields unaligned seqs)
+ // or create a selection box around columns in alignment view
+ // test Alignment(SeqCigar[])
+ char gc = '-';
+ try
+ {
+ // we try to get the associated view's gap character
+ // but this may fail if the view was closed...
+ gc = av.getGapCharacter();
+ } catch (Exception ex)
+ {
+ }
+
+ Object[] alAndColsel = getPasimapModel().getInputData()
+ .getAlignmentView(false).getAlignmentAndHiddenColumns(gc);
+
+ if (alAndColsel != null && alAndColsel[0] != null)
+ {
+ // AlignmentOrder origorder = new AlignmentOrder(alAndColsel[0]);
+
+ AlignmentI al = new Alignment((SequenceI[]) alAndColsel[0]);
+ AlignmentI dataset = (av != null && av.getAlignment() != null)
+ ? av.getAlignment().getDataset()
+ : null;
+ if (dataset != null)
+ {
+ al.setDataset(dataset);
+ }
+
+ if (true)
+ {
+ // make a new frame!
+ AlignFrame af = new AlignFrame(al, (HiddenColumns) alAndColsel[1],
+ AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
+
+ // >>>This is a fix for the moment, until a better solution is
+ // found!!<<<
+ // af.getFeatureRenderer().transferSettings(alignFrame.getFeatureRenderer());
+
+ // af.addSortByOrderMenuItem(ServiceName + " Ordering",
+ // msaorder);
+
+ Desktop.addInternalFrame(af, MessageManager.formatMessage(
+ "label.original_data_for_params", new String[]
+ { this.title }), AlignFrame.DEFAULT_WIDTH,
+ AlignFrame.DEFAULT_HEIGHT);
+ }
+ }
+ /*
+ * CutAndPasteTransfer cap = new CutAndPasteTransfer(); for (int i = 0; i <
+ * seqs.length; i++) { cap.appendText(new jalview.util.Format("%-" + 15 +
+ * "s").form( seqs[i].getName())); cap.appendText(" " + seqstrings[i] +
+ * "\n"); }
+ *
+ * Desktop.addInternalFrame(cap, "Original Data", 400, 400);
+ */
+ }
+
+ class PaSiMapPrinter extends Thread implements Printable
+ {
+ @Override
+ public void run()
+ {
+ PrinterJob printJob = PrinterJob.getPrinterJob();
+ PageFormat defaultPage = printJob.defaultPage();
+ PageFormat pf = printJob.pageDialog(defaultPage);
+
+ if (defaultPage == pf)
+ {
+ /*
+ * user cancelled
+ */
+ return;
+ }
+
+ printJob.setPrintable(this, pf);
+
+ if (printJob.printDialog())
+ {
+ try
+ {
+ printJob.print();
+ } catch (Exception PrintException)
+ {
+ PrintException.printStackTrace();
+ }
+ }
+ }
+
+ @Override
+ public int print(Graphics pg, PageFormat pf, int pi)
+ throws PrinterException
+ {
+ pg.translate((int) pf.getImageableX(), (int) pf.getImageableY());
+
+ getRotatableCanvas().drawBackground(pg);
+ getRotatableCanvas().drawScene(pg);
+ if (getRotatableCanvas().drawAxes)
+ {
+ getRotatableCanvas().drawAxes(pg);
+ }
+
+ if (pi == 0)
+ {
+ return Printable.PAGE_EXISTS;
+ }
+ else
+ {
+ return Printable.NO_SUCH_PAGE;
+ }
+ }
+ }
+
+ public void makePaSiMapImage(ImageMaker.TYPE type) throws Exception
+ {
+ int width = getRotatableCanvas().getWidth();
+ int height = getRotatableCanvas().getHeight();
+ ImageWriterI writer = new ImageWriterI()
+ {
+ @Override
+ public void exportImage(Graphics g) throws Exception
+ {
+ RotatableCanvas canvas = getRotatableCanvas();
+ canvas.drawBackground(g);
+ canvas.drawScene(g);
+ if (canvas.drawAxes)
+ {
+ canvas.drawAxes(g);
+ }
+ }
+ };
+ String pasimap = MessageManager.getString("label.pasimap");
+ ImageExporter exporter = new ImageExporter(writer, null, type, pasimap);
+ exporter.doExport(null, this, width, height, pasimap);
+ }
+
+ @Override
+ protected void viewMenu_menuSelected()
+ {
+ buildAssociatedViewMenu();
+ }
+
+ /**
+ * Builds the menu showing the choice of possible views (for the associated
+ * sequence data) to which the PaSiMap may be linked
+ */
+ void buildAssociatedViewMenu()
+ {
+ AlignmentPanel[] aps = PaintRefresher
+ .getAssociatedPanels(av.getSequenceSetId());
+ if (aps.length == 1 && getRotatableCanvas().av == aps[0].av)
+ {
+ associateViewsMenu.setVisible(false);
+ return;
+ }
+
+ associateViewsMenu.setVisible(true);
+
+ if ((viewMenu
+ .getItem(viewMenu.getItemCount() - 2) instanceof JMenuItem))
+ {
+ viewMenu.insertSeparator(viewMenu.getItemCount() - 1);
+ }
+
+ associateViewsMenu.removeAll();
+
+ JRadioButtonMenuItem item;
+ ButtonGroup buttonGroup = new ButtonGroup();
+ int iSize = aps.length;
+
+ for (int i = 0; i < iSize; i++)
+ {
+ final AlignmentPanel panel = aps[i];
+ item = new JRadioButtonMenuItem(panel.av.getViewName(),
+ panel.av == getRotatableCanvas().av);
+ buttonGroup.add(item);
+ item.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent evt)
+ {
+ selectAssociatedView(panel);
+ }
+ });
+
+ associateViewsMenu.add(item);
+ }
+
+ final JRadioButtonMenuItem itemf = new JRadioButtonMenuItem(
+ "All Views");
+
+ buttonGroup.add(itemf);
+
+ itemf.setSelected(getRotatableCanvas().isApplyToAllViews());
+ itemf.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent evt)
+ {
+ getRotatableCanvas().setApplyToAllViews(itemf.isSelected());
+ }
+ });
+ associateViewsMenu.add(itemf);
+
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * jalview.jbgui.GPaSiMapPanel#outputPoints_actionPerformed(java.awt.event.ActionEvent
+ * )
+ */
+ @Override
+ protected void outputPoints_actionPerformed()
+ {
+ CutAndPasteTransfer cap = new CutAndPasteTransfer();
+ try
+ {
+ cap.setText(getPasimapModel().getPointsasCsv(false,
+ xCombobox.getSelectedIndex(), yCombobox.getSelectedIndex(),
+ zCombobox.getSelectedIndex()));
+ Desktop.addInternalFrame(cap, MessageManager
+ .formatMessage("label.points_for_params", new String[]
+ { this.getTitle() }), 500, 500);
+ } catch (OutOfMemoryError oom)
+ {
+ new OOMWarning("exporting PaSiMap points", oom);
+ cap.dispose();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * jalview.jbgui.GPaSiMapPanel#outputProjPoints_actionPerformed(java.awt.event
+ * .ActionEvent)
+ */
+ @Override
+ protected void outputProjPoints_actionPerformed()
+ {
+ CutAndPasteTransfer cap = new CutAndPasteTransfer();
+ try
+ {
+ cap.setText(getPasimapModel().getPointsasCsv(true,
+ xCombobox.getSelectedIndex(), yCombobox.getSelectedIndex(),
+ zCombobox.getSelectedIndex()));
+ Desktop.addInternalFrame(cap, MessageManager.formatMessage(
+ "label.transformed_points_for_params", new String[]
+ { this.getTitle() }), 500, 500);
+ } catch (OutOfMemoryError oom)
+ {
+ new OOMWarning("exporting transformed PaSiMap points", oom);
+ cap.dispose();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * jalview.jbgui.GPaSiMapPanel#outputAlignment_actionPerformed(java.awt.event
+ * .ActionEvent)
+ */
+ @Override
+ protected void outputAlignment_actionPerformed()
+ {
+ CutAndPasteTransfer cap = new CutAndPasteTransfer();
+ try
+ {
+ cap.setText(getPasimapModel().getAlignmentOutput());
+ Desktop.addInternalFrame(cap, MessageManager.formatMessage(
+ "label.pairwise_alignment_for_params", new String[] { this.getTitle() }), 500, 500);
+ } catch (OutOfMemoryError oom)
+ {
+ new OOMWarning("exporting pairwise alignments", oom);
+ cap.dispose();
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see jalview.gui.IProgressIndicator#setProgressBar(java.lang.String, long)
+ */
+ @Override
+ public void setProgressBar(String message, long id)
+ {
+ progressBar.setProgressBar(message, id);
+ // if (progressBars == null)
+ // {
+ // progressBars = new Hashtable();
+ // progressBarHandlers = new Hashtable();
+ // }
+ //
+ // JPanel progressPanel;
+ // Long lId = Long.valueOf(id);
+ // GridLayout layout = (GridLayout) statusPanel.getLayout();
+ // if (progressBars.get(lId) != null)
+ // {
+ // progressPanel = (JPanel) progressBars.get(Long.valueOf(id));
+ // statusPanel.remove(progressPanel);
+ // progressBars.remove(lId);
+ // progressPanel = null;
+ // if (message != null)
+ // {
+ // statusBar.setText(message);
+ // }
+ // if (progressBarHandlers.contains(lId))
+ // {
+ // progressBarHandlers.remove(lId);
+ // }
+ // layout.setRows(layout.getRows() - 1);
+ // }
+ // else
+ // {
+ // progressPanel = new JPanel(new BorderLayout(10, 5));
+ //
+ // JProgressBar progressBar = new JProgressBar();
+ // progressBar.setIndeterminate(true);
+ //
+ // progressPanel.add(new JLabel(message), BorderLayout.WEST);
+ // progressPanel.add(progressBar, BorderLayout.CENTER);
+ //
+ // layout.setRows(layout.getRows() + 1);
+ // statusPanel.add(progressPanel);
+ //
+ // progressBars.put(lId, progressPanel);
+ // }
+ // // update GUI
+ // // setMenusForViewport();
+ // validate();
+ }
+
+ /*
+ * make the progressBar determinate and update its progress
+ */
+ public void updateProgressBar(int lengthOfTask, int progress)
+ {
+ JProgressBar pBar = progressBar.getProgressBar(progId);
+ if (pBar.isIndeterminate())
+ {
+ pBar.setMaximum(lengthOfTask);
+ pBar.setValue(0);
+ pBar.setIndeterminate(false);
+ }
+ updateProgressBar(progress);
+ }
+ public void updateProgressBar(int progress)
+ {
+ JProgressBar pBar = progressBar.getProgressBar(progId);
+ pBar.setValue(progress);
+ pBar.repaint();
+ }
+
+ //&!
+ public void setPairwiseAlignPanel(PairwiseAlignPanel pap)
+ {
+ pap.addPropertyChangeListener(new PropertyChangeListener()
+ {
+ @Override
+ public void propertyChange(PropertyChangeEvent pcEvent)
+ {
+ if (PairwiseAlignPanel.PROGRESS.equals(pcEvent.getPropertyName()))
+ {
+ updateProgressBar((int) pcEvent.getNewValue());
+ } else if (PairwiseAlignPanel.TOTAL.equals(pcEvent.getPropertyName())) {
+ updateProgressBar((int) pcEvent.getNewValue(), 0);
+ }
+ }
+ });
+ }
+
+ @Override
+ public void registerHandler(final long id,
+ final IProgressIndicatorHandler handler)
+ {
+ progressBar.registerHandler(id, handler);
+ // if (progressBarHandlers == null ||
+ // !progressBars.contains(Long.valueOf(id)))
+ // {
+ // throw new
+ // Error(MessageManager.getString("error.call_setprogressbar_before_registering_handler"));
+ // }
+ // progressBarHandlers.put(Long.valueOf(id), handler);
+ // final JPanel progressPanel = (JPanel) progressBars.get(Long.valueOf(id));
+ // if (handler.canCancel())
+ // {
+ // JButton cancel = new JButton(
+ // MessageManager.getString("action.cancel"));
+ // final IProgressIndicator us = this;
+ // cancel.addActionListener(new ActionListener()
+ // {
+ //
+ // @Override
+ // public void actionPerformed(ActionEvent e)
+ // {
+ // handler.cancelActivity(id);
+ // us.setProgressBar(MessageManager.formatMessage("label.cancelled_params",
+ // new String[]{((JLabel) progressPanel.getComponent(0)).getText()}), id);
+ // }
+ // });
+ // progressPanel.add(cancel, BorderLayout.EAST);
+ // }
+ }
+
+ /**
+ *
+ * @return true if any progress bars are still active
+ */
+ @Override
+ public boolean operationInProgress()
+ {
+ return progressBar.operationInProgress();
+ }
+
+ @Override
+ protected void resetButton_actionPerformed()
+ {
+ int t = getTop();
+ setTop(0); // ugly - prevents dimensionChanged events from being processed
+ xCombobox.setSelectedIndex(0);
+ yCombobox.setSelectedIndex(1);
+ setTop(t);
+ zCombobox.setSelectedIndex(2);
+ }
+
+ /**
+ * Answers true if PaSiMap calculation is in progress, else false
+ *
+ * @return
+ */
+ public boolean isWorking()
+ {
+ return working;
+ }
+
+ /**
+ * Answers the selected checkbox item index for PaSiMap dimension for the X, Y or
+ * Z axis of the display
+ *
+ * @param axis
+ * @return
+ */
+ public int getSelectedDimensionIndex(Axis axis)
+ {
+ switch (axis)
+ {
+ case X:
+ return xCombobox.getSelectedIndex();
+ case Y:
+ return yCombobox.getSelectedIndex();
+ default:
+ return zCombobox.getSelectedIndex();
+ }
+ }
+
+ public void setShowLabels(boolean show)
+ {
+ showLabels.setSelected(show);
+ }
+
+ /**
+ * Sets the input data used to calculate the PaSiMap. This is provided for
+ * 'restore from project', which does not currently support this (AL-2647), so
+ * sets the value to null, and hides the menu option for "Input Data...". J
+ *
+ * @param data
+ */
+ public void setInputData(AlignmentViewport data)
+ {
+ getPasimapModel().setInputData(data);
+ originalSeqData.setVisible(data != null);
+ }
+
+ public AlignViewportI getAlignViewport()
+ {
+ return av;
+ }
+
+ public PaSiMapModel getPasimapModel()
+ {
+ return pasimapModel;
+ }
+
+ public void setPasimapModel(PaSiMapModel pasimapModel)
+ {
+ this.pasimapModel = pasimapModel;
+ }
+
+ public RotatableCanvas getRotatableCanvas()
+ {
+ return rc;
+ }
+
+ public void setRotatableCanvas(RotatableCanvas rc)
+ {
+ this.rc = rc;
+ }
+
+ public int getTop()
+ {
+ return top;
+ }
+
+ public void setTop(int top)
+ {
+ this.top = top;
+ }
+
+ /**
+ * set the associated view for this PaSiMap.
+ *
+ * @param panel
+ */
+ public void selectAssociatedView(AlignmentPanel panel)
+ {
+ getRotatableCanvas().setApplyToAllViews(false);
+
+ ap = panel;
+ av = panel.av;
+
+ getRotatableCanvas().av = panel.av;
+ getRotatableCanvas().ap = panel;
+ PaintRefresher.Register(PaSiMapPanel.this, panel.av.getSequenceSetId());
+ }
+
+ @Override
+ public JProgressBar getProgressBar(long id)
+ {
+ return progressBar.getProgressBar(id);
+ }
+}
import jalview.jbgui.GPairwiseAlignPanel;
import jalview.util.MessageManager;
import jalview.viewmodel.AlignmentViewport;
+import jalview.math.MiscMath;
+import java.beans.PropertyChangeListener;
import java.awt.event.ActionEvent;
import java.util.Vector;
+import javax.swing.event.SwingPropertyChangeSupport;
/**
* DOCUMENT ME!
private static final String DASHES = "---------------------\n";
+ private float[][] scores;
+
+ private float[][] alignmentScores; // scores used by PaSiMap
+
+ private int GAP_OPEN_COST;
+
+ private int GAP_EXTEND_COST;
+
AlignmentViewport av;
Vector<SequenceI> sequences;
+ private String alignmentOutput;
+
+ private boolean suppressTextbox;
+
+ private boolean discardAlignments;
+
+ private boolean endGaps;
+
+ // for listening
+ public static final String TOTAL = "total";
+
+ public static final String PROGRESS = "progress";
+
+ private int total;
+
+ private int progress;
+
/**
* Creates a new PairwiseAlignPanel object.
*
* @param viewport
* DOCUMENT ME!
+ * @param endGaps ~ toggle gaps and the beginning and end of sequences
*/
public PairwiseAlignPanel(AlignmentViewport viewport)
{
+ this(viewport, false, 120, 20, true); // default penalties used in AlignSeq
+ }
+ public PairwiseAlignPanel(AlignmentViewport viewport, boolean endGaps, int gapOpenCost, int gapExtendCost)
+ {
+ this(viewport, endGaps, gapOpenCost, gapExtendCost, true);
+ }
+ public PairwiseAlignPanel(AlignmentViewport viewport, boolean endGaps, int gapOpenCost, int gapExtendCost, boolean run)
+ {
super();
this.av = viewport;
+ this.GAP_OPEN_COST = gapOpenCost;
+ this.GAP_EXTEND_COST = gapExtendCost;
+ this.endGaps = endGaps;
+ this.total = MiscMath.combinations(av.getAlignment().getHeight(), 2);
+
+ if (run)
+ calculate();
+System.out.println("Creating pap");
+ }
+
+ public void calculate()
+ {
+
+ SequenceGroup selectionGroup = av.getSelectionGroup();
+ StringBuilder sb = new StringBuilder(1024);
sequences = new Vector<SequenceI>();
- SequenceGroup selectionGroup = viewport.getSelectionGroup();
boolean isSelection = selectionGroup != null
&& selectionGroup.getSize() > 0;
- AlignmentView view = viewport.getAlignmentView(isSelection);
- // String[] seqStrings = viewport.getViewAsString(true);
+ AlignmentView view = av.getAlignmentView(isSelection);
+ // String[] seqStrings = av.getViewAsString(true);
String[] seqStrings = view
- .getSequenceStrings(viewport.getGapCharacter());
+ .getSequenceStrings(av.getGapCharacter());
SequenceI[] seqs;
if (isSelection)
{
seqs = (SequenceI[]) view
- .getAlignmentAndHiddenColumns(viewport.getGapCharacter())[0];
+ .getAlignmentAndHiddenColumns(av.getGapCharacter())[0];
}
else
{
seqs = av.getAlignment().getSequencesArray();
}
- String type = (viewport.getAlignment().isNucleotide()) ? AlignSeq.DNA
+ String type = (av.getAlignment().isNucleotide()) ? AlignSeq.DNA
: AlignSeq.PEP;
float[][] scores = new float[seqs.length][seqs.length];
+ float[][] alignmentScores = new float[seqs.length][seqs.length];
double totscore = 0D;
int count = seqs.length;
boolean first = true;
+ progress = 0;
+ firePropertyChange(TOTAL, 0, total);
+
+ suppressTextbox = count<10;
+ discardAlignments = count<15;
+
for (int i = 1; i < count; i++)
{
+ // fill diagonal alignmentScores with Float.NaN
+ alignmentScores[i - 1][i - 1] = Float.NaN;
for (int j = 0; j < i; j++)
{
AlignSeq as = new AlignSeq(seqs[i], seqStrings[i], seqs[j],
- seqStrings[j], type);
+ seqStrings[j], type, GAP_OPEN_COST, GAP_EXTEND_COST);
if (as.s1str.length() == 0 || as.s2str.length() == 0)
{
}
as.calcScoreMatrix();
- as.traceAlignment();
+ if (endGaps)
+ {
+ as.traceAlignmentWithEndGaps();
+ } else {
+ as.traceAlignment();
+ }
+ as.scoreAlignment();
if (!first)
{
jalview.bin.Console.outPrintln(DASHES);
textarea.append(DASHES);
+ sb.append(DASHES);
}
first = false;
- as.printAlignment(System.out);
+ if (discardAlignments) {
+ as.printAlignment(System.out);
+ }
scores[i][j] = as.getMaxScore() / as.getASeq1().length;
+ alignmentScores[i][j] = as.getAlignmentScore();
totscore = totscore + scores[i][j];
- textarea.append(as.getOutput());
- sequences.add(as.getAlignedSeq1());
- sequences.add(as.getAlignedSeq2());
+ if (suppressTextbox)
+ {
+ textarea.append(as.getOutput());
+ sb.append(as.getOutput());
+ }
+ if (discardAlignments)
+ {
+ sequences.add(as.getAlignedSeq1());
+ sequences.add(as.getAlignedSeq2());
+ }
+
+ firePropertyChange(PROGRESS, progress, ++progress);
}
}
+ alignmentScores[count - 1][count - 1] = Float.NaN;
+
+ this.scores = scores;
+ this.alignmentScores = alignmentScores;
if (count > 2)
{
printScoreMatrix(seqs, scores, totscore);
}
+
+ alignmentOutput = sb.toString();
+ }
+
+ public float[][] getScores()
+ {
+ return this.scores;
+ }
+
+ public float[][] getAlignmentScores()
+ {
+ return this.alignmentScores;
+ }
+
+ public String getAlignmentOutput()
+ {
+ return this.alignmentOutput;
}
/**
MessageManager.getString("label.pairwise_aligned_sequences"),
AlignFrame.DEFAULT_WIDTH, AlignFrame.DEFAULT_HEIGHT);
}
+
+ public long getTotal()
+ {
+ return total;
+ }
+
+ public long getProgress()
+ {
+ return progress;
+ }
}
});
}
+ /*
+ *
+ */
+ public JProgressBar getProgressBar(long id)
+ {
+ for (Component component : progressBars.get(id).getComponents())
+ {
+ if (component.getClass().equals(JProgressBar.class))
+ return (JProgressBar) component;
+ }
+ return null;
+ }
+
}
private Point[] axisEndPoints;
// fields for 'select rectangle' (JAL-1124)
- // int rectx1;
- // int recty1;
- // int rectx2;
- // int recty2;
+ int rectx1;
+ int recty1;
+ int rectx2;
+ int recty2;
AlignmentViewport av;
}
}
// //Now the rectangle
- // if (rectx2 != -1 && recty2 != -1) {
- // g.setColor(Color.white);
- //
- // g.drawRect(rectx1,recty1,rectx2-rectx1,recty2-recty1);
- // }
+ if (rectx2 != -1 && recty2 != -1) {
+ g.setColor(Color.white);
+
+ g.drawRect(rectx1,recty1,rectx2-rectx1,recty2-recty1);
+ }
}
/**
// Cache.warn("DEBUG: Rectangle selection");
// todo not yet enabled as rectx2, recty2 are always -1
// need to set them in mouseDragged; JAL-1124
- // if ((rectx2 != -1) && (recty2 != -1))
- // {
- // rectSelect(rectx1, recty1, rectx2, recty2);
- // }
+ if ((rectx2 != -1) && (recty2 != -1))
+ {
+ rectSelect(rectx1, recty1, rectx2, recty2);
+ }
}
repaint();
mouseX = x;
mouseY = y;
- // rectx1 = x;
- // recty1 = y;
- // rectx2 = -1;
- // recty2 = -1;
+ rectx1 = x;
+ recty1 = y;
+ rectx2 = -1;
+ recty2 = -1;
SequenceI found = findSequenceAtPoint(x, y);
// Check if this is a rectangle drawing drag
if ((evt.getModifiersEx() & InputEvent.BUTTON2_DOWN_MASK) != 0)
{
- // rectx2 = evt.getX();
- // recty2 = evt.getY();
+ rectx2 = evt.getX();
+ recty2 = evt.getY();
}
else
{
{
SequencePoint sp = sequencePoints.get(i);
int tmp1 = (int) (((sp.coord.x - centre[0]) * getScaleFactor())
+ * (getWidth() / 3.15)
+ (getWidth() / 2.0));
+ float pre1 = ((sp.coord.x - centre[0]) * getScaleFactor());
int tmp2 = (int) (((sp.coord.y - centre[1]) * getScaleFactor())
+ * (getHeight() / 1.70)
+ (getHeight() / 2.0));
+ float pre2 = ((sp.coord.y - centre[1]) * getScaleFactor());
if ((tmp1 > x1) && (tmp1 < x2) && (tmp2 > y1) && (tmp2 < y2))
{
if (av != null)
{
SequenceI sequence = sp.getSequence();
+ if (av.getSelectionGroup() == null)
+ {
+ SequenceGroup sg = new SequenceGroup();
+ sg.setEndRes(av.getAlignment().getWidth() - 1);
+ av.setSelectionGroup(sg);
+ }
if (!av.getSelectionGroup().getSequences(null).contains(sequence))
{
av.getSelectionGroup().addSequence(sequence, true);
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
+import javax.swing.JProgressBar;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
}
}
+
+ @Override
+ public JProgressBar getProgressBar(long id)
+ {
+ return progressBar.getProgressBar(id);
+ }
}
import javax.swing.JEditorPane;
import javax.swing.JInternalFrame;
import javax.swing.JPanel;
+import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTabbedPane;
import javax.swing.JTextArea;
{
return progressBar.operationInProgress();
}
+
+ @Override
+ public JProgressBar getProgressBar(long id)
+ {
+ return progressBar.getProgressBar(id);
+ }
}
JMenuItem pasteMenu = new JMenuItem();
+ JMenuItem fontSizeMenu = new JMenuItem();
+
BorderLayout borderLayout2 = new BorderLayout();
protected JPanel inputButtonPanel = new JPanel();
pasteMenu_actionPerformed(e);
}
});
+ fontSizeMenu.setText(MessageManager.getString("action.change_font"));
+ fontSizeMenu.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ fontSizeMenu_actionPerformed(e);
+ }
+ });
copyItem.setText(MessageManager.getString("action.copy"));
copyItem.addActionListener(new ActionListener()
{
editMenu.add(selectAll);
editMenu.add(copyItem);
editMenu.add(pasteMenu);
+ editMenu.add(fontSizeMenu);
this.getContentPane().add(scrollPane, java.awt.BorderLayout.CENTER);
inputButtonPanel.add(ok);
inputButtonPanel.add(cancel);
}
/**
+ * shows a menu for changing the font
+ * @param e
+ */
+ public void fontSizeMenu_actionPerformed(ActionEvent e)
+ {
+ }
+
+ /**
* DOCUMENT ME!
*
* @param e
zCombobox.addItem("dim " + i);
}
}
+ public GPCAPanel(int dim)
+ {
+ try
+ {
+ jbInit();
+ } catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+ for (int i = 1; i <= dim; i++)
+ {
+ xCombobox.addItem("dim " + i);
+ yCombobox.addItem("dim " + i);
+ zCombobox.addItem("dim " + i);
+ }
+ }
private void jbInit() throws Exception
{
--- /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.jbgui;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+import javax.swing.JCheckBoxMenuItem;
+import javax.swing.JComboBox;
+import javax.swing.JInternalFrame;
+import javax.swing.JLabel;
+import javax.swing.JMenu;
+import javax.swing.JMenuBar;
+import javax.swing.JMenuItem;
+import javax.swing.JPanel;
+import javax.swing.event.MenuEvent;
+import javax.swing.event.MenuListener;
+
+import jalview.util.ImageMaker.TYPE;
+import jalview.util.MessageManager;
+
+public class GPaSiMapPanel extends JInternalFrame
+{
+ private static final Font VERDANA_12 = new Font("Verdana", 0, 12);
+
+ protected JComboBox<String> xCombobox = new JComboBox<>();
+
+ protected JComboBox<String> yCombobox = new JComboBox<>();
+
+ protected JComboBox<String> zCombobox = new JComboBox<>();
+
+ protected JMenu viewMenu = new JMenu();
+
+ protected JCheckBoxMenuItem showLabels = new JCheckBoxMenuItem();
+
+ protected JMenu associateViewsMenu = new JMenu();
+
+ protected JLabel statusBar = new JLabel();
+
+ protected JPanel statusPanel = new JPanel();
+
+ protected JMenuItem originalSeqData;
+
+ /**
+ * Constructor
+ */
+ public GPaSiMapPanel()
+ {
+ try
+ {
+ jbInit();
+ } catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+ for (int i = 1; i < 8; i++)
+ {
+ xCombobox.addItem("dim " + i);
+ yCombobox.addItem("dim " + i);
+ zCombobox.addItem("dim " + i);
+ }
+ }
+ public GPaSiMapPanel(int dim)
+ {
+ try
+ {
+ jbInit();
+ } catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+ for (int i = 1; i <= dim; i++)
+ {
+ xCombobox.addItem("dim " + i);
+ yCombobox.addItem("dim " + i);
+ zCombobox.addItem("dim " + i);
+ }
+ }
+
+ private void jbInit() throws Exception
+ {
+ setFrameIcon(null);
+ setName("jalview-pca");
+ this.getContentPane().setLayout(new BorderLayout());
+ JPanel jPanel2 = new JPanel();
+ jPanel2.setLayout(new FlowLayout());
+ JLabel jLabel1 = new JLabel();
+ jLabel1.setFont(VERDANA_12);
+ jLabel1.setText("x=");
+ JLabel jLabel2 = new JLabel();
+ jLabel2.setFont(VERDANA_12);
+ jLabel2.setText("y=");
+ JLabel jLabel3 = new JLabel();
+ jLabel3.setFont(VERDANA_12);
+ jLabel3.setText("z=");
+ jPanel2.setBackground(Color.white);
+ jPanel2.setBorder(null);
+ zCombobox.setFont(VERDANA_12);
+ zCombobox.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ doDimensionChange();
+ }
+ });
+ yCombobox.setFont(VERDANA_12);
+ yCombobox.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ doDimensionChange();
+ }
+ });
+ xCombobox.setFont(VERDANA_12);
+ xCombobox.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ doDimensionChange();
+ }
+ });
+ JButton resetButton = new JButton();
+ resetButton.setFont(VERDANA_12);
+ resetButton.setText(MessageManager.getString("action.reset"));
+ resetButton.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ resetButton_actionPerformed();
+ }
+ });
+ JMenu fileMenu = new JMenu();
+ fileMenu.setText(MessageManager.getString("action.file"));
+ JMenu saveMenu = new JMenu();
+ saveMenu.setText(MessageManager.getString("action.save_as"));
+ JMenuItem eps = new JMenuItem("EPS");
+ eps.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ makePCAImage(TYPE.EPS);
+ }
+ });
+ JMenuItem png = new JMenuItem("PNG");
+ png.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ makePCAImage(TYPE.PNG);
+ }
+ });
+ JMenuItem outputValues = new JMenuItem();
+ outputValues.setText(MessageManager.getString("label.output_values"));
+ outputValues.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ outputValues_actionPerformed();
+ }
+ });
+ JMenuItem outputPoints = new JMenuItem();
+ outputPoints.setText(MessageManager.getString("label.output_points"));
+ outputPoints.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ outputPoints_actionPerformed();
+ }
+ });
+ JMenuItem outputProjPoints = new JMenuItem();
+ outputProjPoints.setText(
+ MessageManager.getString("label.output_transformed_points"));
+ outputProjPoints.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ outputProjPoints_actionPerformed();
+ }
+ });
+ JMenuItem print = new JMenuItem();
+ print.setText(MessageManager.getString("action.print"));
+ print.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ print_actionPerformed();
+ }
+ });
+ JMenuItem outputAlignment = new JMenuItem();
+ outputAlignment.setText(
+ MessageManager.getString("label.output_alignment"));
+ outputAlignment.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ outputAlignment_actionPerformed();
+ }
+ });
+ viewMenu.setText(MessageManager.getString("action.view"));
+ viewMenu.addMenuListener(new MenuListener()
+ {
+ @Override
+ public void menuSelected(MenuEvent e)
+ {
+ viewMenu_menuSelected();
+ }
+
+ @Override
+ public void menuDeselected(MenuEvent e)
+ {
+ }
+
+ @Override
+ public void menuCanceled(MenuEvent e)
+ {
+ }
+ });
+ showLabels.setText(MessageManager.getString("label.show_labels"));
+ showLabels.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ showLabels_actionPerformed();
+ }
+ });
+ JMenuItem bgcolour = new JMenuItem();
+ bgcolour.setText(MessageManager.getString("action.background_colour"));
+ bgcolour.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ bgcolour_actionPerformed();
+ }
+ });
+ originalSeqData = new JMenuItem();
+ originalSeqData.setText(MessageManager.getString("label.input_data"));
+ originalSeqData.addActionListener(new ActionListener()
+ {
+ @Override
+ public void actionPerformed(ActionEvent e)
+ {
+ originalSeqData_actionPerformed();
+ }
+ });
+ associateViewsMenu.setText(
+ MessageManager.getString("label.associate_nodes_with"));
+
+ statusPanel.setLayout(new GridLayout());
+ statusBar.setFont(VERDANA_12);
+ // statusPanel.setBackground(Color.lightGray);
+ // statusBar.setBackground(Color.lightGray);
+ // statusPanel.add(statusBar, null);
+ JPanel panelBar = new JPanel(new BorderLayout());
+ panelBar.add(jPanel2, BorderLayout.NORTH);
+ panelBar.add(statusPanel, BorderLayout.SOUTH);
+ this.getContentPane().add(panelBar, BorderLayout.SOUTH);
+ jPanel2.add(jLabel1, null);
+ jPanel2.add(xCombobox, null);
+ jPanel2.add(jLabel2, null);
+ jPanel2.add(yCombobox, null);
+ jPanel2.add(jLabel3, null);
+ jPanel2.add(zCombobox, null);
+ jPanel2.add(resetButton, null);
+
+ JMenuBar jMenuBar1 = new JMenuBar();
+ jMenuBar1.add(fileMenu);
+ jMenuBar1.add(viewMenu);
+ setJMenuBar(jMenuBar1);
+ fileMenu.add(saveMenu);
+ fileMenu.add(outputValues);
+ fileMenu.add(print);
+ fileMenu.add(originalSeqData);
+ fileMenu.add(outputPoints);
+ fileMenu.add(outputProjPoints);
+ fileMenu.add(outputAlignment);
+ saveMenu.add(eps);
+ saveMenu.add(png);
+ viewMenu.add(showLabels);
+ viewMenu.add(bgcolour);
+ viewMenu.add(associateViewsMenu);
+ }
+
+ protected void resetButton_actionPerformed()
+ {
+ }
+
+ protected void outputPoints_actionPerformed()
+ {
+ }
+
+ protected void outputProjPoints_actionPerformed()
+ {
+ }
+
+ protected void outputAlignment_actionPerformed()
+ {
+ }
+
+ public void makePCAImage(TYPE imageType)
+ {
+ }
+
+ protected void outputValues_actionPerformed()
+ {
+ }
+
+ protected void print_actionPerformed()
+ {
+ }
+
+ protected void showLabels_actionPerformed()
+ {
+ }
+
+ protected void bgcolour_actionPerformed()
+ {
+ }
+
+ protected void originalSeqData_actionPerformed()
+ {
+ }
+
+ protected void viewMenu_menuSelected()
+ {
+ }
+
+ protected void doDimensionChange()
+ {
+ }
+}
import jalview.util.MessageManager;
import java.io.PrintStream;
+import java.lang.Math;
import java.util.Arrays;
/**
}
}
+ public Matrix(float[][] values)
+ {
+ this.rows = values.length;
+ this.cols = this.rows == 0 ? 0 : values[0].length;
+
+ /*
+ * make a copy of the values array, for immutability
+ */
+ this.value = new double[rows][];
+ int i = 0;
+ for (float[] row : values)
+ {
+ if (row != null)
+ {
+ value[i] = new double[row.length];
+ int j = 0;
+ for (float oldValue : row)
+ {
+ value[i][j] = oldValue;
+ j++;
+ }
+ }
+ i++;
+ }
+ }
+
@Override
public MatrixI transpose()
{
*/
for (int k = 0; k < in.width(); k++)
{
- tmp[i][j] += (in.getValue(i, k) * this.value[k][j]);
+ if (!Double.isNaN(in.getValue(i,k)) && !Double.isNaN(this.value[k][j]))
+ {
+ tmp[i][j] += (in.getValue(i, k) * this.value[k][j]);
+ }
}
}
}
}
/**
+ * returns the matrix as a double[][] array
+ *
+ * @return
+ */
+ @Override
+ public double[][] asArray()
+ {
+ return value;
+ }
+
+ /**
* Returns an array containing the values in the specified column
*
* @param col
*
* @return
*/
+ @Override
public double[] getColumn(int col)
{
double[] out = new double[rows];
@Override
public void printD(PrintStream ps, String format)
{
- for (int j = 0; j < rows; j++)
+ for (int j = 0; j < d.length; j++)
{
Format.print(ps, format, d[j]);
}
}
}
+ /**
+ * Add d to all entries of this matrix
+ *
+ * @param d ~ value to add
+ */
+ @Override
+ public void add(double d)
+ {
+ for (double[] row : value)
+ {
+ if (row != null)
+ {
+ for (int i = 0; i < row.length; i++)
+ {
+ row[i] += d;
+ }
+ }
+ }
+ }
+
@Override
public void setD(double[] v)
{
}
return true;
}
+
+ /**
+ * Returns a copy in which every value in the matrix is its absolute
+ *
+ * @return
+ */
+ @Override
+ public MatrixI absolute()
+ {
+ MatrixI copy = this.copy();
+ for (int i = 0; i < copy.width(); i++)
+ {
+ double[] row = copy.getRow(i);
+ if (row != null)
+ {
+ for (int j = 0; j < row.length; j++)
+ {
+ row[j] = Math.abs(row[j]);
+ }
+ }
+ }
+ return copy;
+ }
+
+ /**
+ * Returns the mean of each row
+ *
+ * @return
+ */
+ @Override
+ public double[] meanRow()
+ {
+ double[] mean = new double[rows];
+ int i = 0;
+ for (double[] row : value)
+ {
+ if (row != null)
+ {
+ mean[i++] = MiscMath.mean(row);
+ }
+ }
+ return mean;
+ }
+
+ /**
+ * Returns the mean of each column
+ *
+ * @return
+ */
+ @Override
+ public double[] meanCol()
+ {
+ double[] mean = new double[cols];
+ for (int j = 0; j < cols; j++)
+ {
+ double[] column = getColumn(j);
+ if (column != null)
+ {
+ mean[j] = MiscMath.mean(column);
+ }
+ }
+ return mean;
+ }
+
+ /**
+ * return a flattened matrix containing the sum of each column
+ *
+ * @return
+ */
+ @Override
+ public double[] sumCol()
+ {
+ double[] sum = new double[cols];
+ for (int j = 0; j < cols; j++)
+ {
+ double[] column = getColumn(j);
+ if (column != null)
+ {
+ sum[j] = MiscMath.sum(column);
+ }
+ }
+ return sum;
+ }
+
+ /**
+ * returns the mean value of the complete matrix
+ *
+ * @return
+ */
+ @Override
+ public double mean()
+ {
+ double sum = 0;
+ int nanCount = 0;
+ for (double[] row : value)
+ {
+ for (double col : row)
+ {
+ if (!Double.isNaN(col))
+ {
+ sum += col;
+ } else {
+ nanCount++;
+ }
+ }
+ }
+ return sum / (double) (this.rows * this.cols - nanCount);
+ }
+
+ /**
+ * fills up a diagonal matrix with its transposed copy
+ * !other side should be filled with 0
+ * !keeps Double.NaN found in either side
+ *
+ * TODO check on which side it was diagonal and only do calculations for the other side
+ */
+ @Override
+ public void fillDiagonal()
+ {
+ int n = this.rows;
+ int m = this.cols;
+ MatrixI copy = this.transpose(); // goes through each element in the matrix and
+ for (int i = 0; i < n; i++) // adds the value in the transposed copy to the original value
+ {
+ for (int j = 0; j < m; j++)
+ {
+ if (i != j)
+ {
+ this.addValue(i, j, copy.getValue(i,j));
+ }
+ }
+ }
+ }
+
+ /**
+ * counts the number of Double.NaN in the matrix
+ *
+ * @return
+ */
+ @Override
+ public int countNaN()
+ {
+ int NaN = 0;
+ for (int i = 0; i < this.rows; i++)
+ {
+ for (int j = 0; j < this.cols; j++)
+ {
+ if (Double.isNaN(this.getValue(i,j)))
+ {
+ NaN++;
+ }
+ }
+ }
+ return NaN;
+ }
+
+ /**
+ * performs an element-wise addition of this matrix by another matrix ~ this - m
+ * @param m ~ other matrix
+ *
+ * @return
+ */
+ @Override
+ public MatrixI add(MatrixI m)
+ {
+ if (m.width() != cols || m.height() != rows)
+ {
+ throw new IllegalArgumentException("Can't add a " + m.height() + "x" + m.width() + " to a " + this.rows + "x" + this.cols + " matrix");
+ }
+ double[][] tmp = new double[this.rows][this.cols];
+ for (int i = 0; i < this.rows; i++)
+ {
+ for (int j = 0; j < this.cols; j++)
+ {
+ tmp[i][j] = this.getValue(i,j) + m.getValue(i,j);
+ }
+ }
+ return new Matrix(tmp);
+ }
+
+ /**
+ * performs an element-wise subtraction of this matrix by another matrix ~ this - m
+ * @param m ~ other matrix
+ *
+ * @return
+ */
+ @Override
+ public MatrixI subtract(MatrixI m)
+ {
+ if (m.width() != cols || m.height() != rows)
+ {
+ throw new IllegalArgumentException("Can't subtract a " + m.height() + "x" + m.width() + " from a " + this.rows + "x" + this.cols + " matrix");
+ }
+ double[][] tmp = new double[this.rows][this.cols];
+ for (int i = 0; i < this.rows; i++)
+ {
+ for (int j = 0; j < this.cols; j++)
+ {
+ tmp[i][j] = this.getValue(i,j) - m.getValue(i,j);
+ }
+ }
+ return new Matrix(tmp);
+ }
+
+ /**
+ * performs an element-wise multiplication of this matrix by another matrix ~ this * m
+ * @param m ~ other matrix
+ *
+ * @return
+ */
+ @Override
+ public MatrixI elementwiseMultiply(MatrixI m)
+ {
+ if (m.width() != cols || m.height() != rows)
+ {
+ throw new IllegalArgumentException("Can't multiply a " + this.rows + "x" + this.cols + " by a " + m.height() + "x" + m.width() + " matrix");
+ }
+ double[][] tmp = new double[this.rows][this.cols];
+ for (int i = 0; i < this.rows; i++)
+ {
+ for (int j = 0; j < this.cols; j++)
+ {
+ tmp[i][j] = this.getValue(i, j) * m.getValue(i,j);
+ }
+ }
+ return new Matrix(tmp);
+ }
+
+ /**
+ * performs an element-wise division of this matrix by another matrix ~ this / m
+ * @param m ~ other matrix
+ *
+ * @return
+ */
+ @Override
+ public MatrixI elementwiseDivide(MatrixI m)
+ {
+ if (m.width() != cols || m.height() != rows)
+ {
+ throw new IllegalArgumentException("Can't divide a " + this.rows + "x" + this.cols + " by a " + m.height() + "x" + m.width() + " matrix");
+ }
+ double[][] tmp = new double[this.rows][this.cols];
+ for (int i = 0; i < this.rows; i++)
+ {
+ for (int j = 0; j < this.cols; j++)
+ {
+ tmp[i][j] = this.getValue(i, j) / m.getValue(i,j);
+ }
+ }
+ return new Matrix(tmp);
+ }
+
+ /**
+ * calculate the root-mean-square for tow matrices
+ * @param m ~ other matrix
+ *
+ * @return
+ */
+ @Override
+ public double rmsd(MatrixI m)
+ {
+ MatrixI squaredDeviates = this.subtract(m);
+ squaredDeviates = squaredDeviates.preMultiply(squaredDeviates);
+ return Math.sqrt(squaredDeviates.mean());
+ }
+
+ /**
+ * calculates the Frobenius norm of this matrix
+ *
+ * @return
+ */
+ @Override
+ public double norm()
+ {
+ double result = 0;
+ for (double[] row : value)
+ {
+ for (double val : row)
+ {
+ result += Math.pow(val, 2);
+ }
+ }
+ return Math.sqrt(result);
+ }
+
+ /**
+ * returns the sum of all values in this matrix
+ *
+ * @return
+ */
+ @Override
+ public double sum()
+ {
+ double sum = 0;
+ for (double[] row : value)
+ {
+ for (double val : row)
+ {
+ sum += (Double.isNaN(val)) ? 0.0 : val;
+ }
+ }
+ return sum;
+ }
+
+ /**
+ * returns the sum-product of this matrix with vector v
+ * @param v ~ vector
+ *
+ * @return
+ */
+ @Override
+ public double[] sumProduct(double[] v)
+ {
+ if (v.length != cols)
+ {
+ throw new IllegalArgumentException("Vector and matrix do not have the same dimension! (" + v.length + " != " + cols + ")");
+ }
+ double[] result = new double[rows];
+ for (int i = 0; i < rows; i++)
+ {
+ double[] row = value[i];
+ double sum = 0;
+ for (int j = 0; j < row.length; j++)
+ {
+ sum += row[j] * v[j];
+ }
+ result[i] = sum;
+ }
+ return result;
+ }
+
+ /**
+ * mirrors columns of the matrix
+ *
+ * @return
+ */
+ @Override
+ public MatrixI mirrorCol()
+ {
+ double[][] result = new double[rows][cols];
+ for (int i = 0; i < rows; i++)
+ {
+ int k = cols - 1; // reverse col
+ for (int j = 0; j < cols; j++)
+ {
+ result[i][k--] = this.getValue(i,j);
+ }
+ }
+ return new Matrix(result);
+ }
}
void setValue(int i, int j, double d);
/**
+ * Returns the matrix as a double[][] array
+ *
+ * @return
+ */
+ double[][] asArray();
+
+ /**
* Answers a copy of the values in the i'th row
*
* @return
double[] getRow(int i);
/**
+ * Answers a copy of the values in the i'th column
+ *
+ * @return
+ */
+ double[] getColumn(int i);
+
+ /**
* Answers a new matrix with a copy of the values in this one
*
* @return
void multiply(double d);
/**
+ * Add d to all entries of this matrix
+ *
+ * @param d ~ value to add
+ */
+ void add(double d);
+
+ /**
* Answers true if the two matrices have the same dimensions, and
* corresponding values all differ by no more than delta (which should be a
* positive value), else false
* @return
*/
boolean equals(MatrixI m2, double delta);
+
+ /**
+ * Returns a copy in which every value in the matrix is its absolute
+ */
+ MatrixI absolute();
+
+ /**
+ * Returns the mean of each row
+ */
+ double[] meanRow();
+
+ /**
+ * Returns the mean of each column
+ */
+ double[] meanCol();
+
+ /**
+ * Returns a flattened matrix containing the sum of each column
+ *
+ * @return
+ */
+ double[] sumCol();
+
+ /**
+ * returns the mean value of the complete matrix
+ */
+ double mean();
+
+ /**
+ * fills up a diagonal matrix with its transposed copy
+ * !other side should be filled with either 0 or Double.NaN
+ */
+ void fillDiagonal();
+
+ /**
+ * counts the number of Double.NaN in the matrix
+ *
+ * @return
+ */
+ int countNaN();
+
+ /**
+ * performs an element-wise addition of this matrix by another matrix
+ * !matrices have to be the same size
+ * @param m ~ other matrix
+ *
+ * @return
+ * @throws IllegalArgumentException
+ * if this and m do not have the same dimensions
+ */
+ MatrixI add(MatrixI m);
+
+ /**
+ * performs an element-wise subtraction of this matrix by another matrix
+ * !matrices have to be the same size
+ * @param m ~ other matrix
+ *
+ * @return
+ * @throws IllegalArgumentException
+ * if this and m do not have the same dimensions
+ */
+ MatrixI subtract(MatrixI m);
+
+ /**
+ * performs an element-wise multiplication of this matrix by another matrix ~ this * m
+ * !matrices have to be the same size
+ * @param m ~ other matrix
+ *
+ * @return
+ * @throws IllegalArgumentException
+ * if this and m do not have the same dimensions
+ */
+ MatrixI elementwiseMultiply(MatrixI m);
+
+ /**
+ * performs an element-wise division of this matrix by another matrix ~ this / m
+ * !matrices have to be the same size
+ * @param m ~ other matrix
+ *
+ * @return
+ * @throws IllegalArgumentException
+ * if this and m do not have the same dimensions
+ */
+ MatrixI elementwiseDivide(MatrixI m);
+
+ /**
+ * calculates the root-mean-square for two matrices
+ * @param m ~ other matrix
+ *
+ * @return
+ */
+ double rmsd(MatrixI m);
+
+ /**
+ * calculates the Frobenius norm of this matrix
+ *
+ * @return
+ */
+ double norm();
+
+ /**
+ * returns the sum of all values in this matrix
+ *
+ * @return
+ */
+ double sum();
+
+ /**
+ * returns the sum-product of this matrix with vector v
+ * @param v ~ vector
+ *
+ * @return
+ * @throws IllegalArgumentException
+ * if this.cols and v do not have the same length
+ */
+ double[] sumProduct(double[] v);
+
+ /**
+ * mirrors the columns of this matrix
+ *
+ * @return
+ */
+ MatrixI mirrorCol();
}
--- /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.math;
+
+import jalview.util.Format;
+
+import java.lang.Math;
+import java.util.Arrays;
+
+/**
+ * A collection of miscellaneous mathematical operations
+ * @AUTHOR MorellThomas
+ */
+public class MiscMath
+{
+ /**
+ * prints an array
+ * @param m ~ array
+ */
+ public static void print(double[] m, String format)
+ {
+ System.out.print("[ ");
+ for (double a : m)
+ {
+ Format.print(System.out, format + " ", a);
+ }
+ System.out.println("]");
+ }
+
+ /**
+ * calculates the mean of an array
+ *
+ * @param m ~ array
+ * @return
+ */
+ public static double mean(double[] m)
+ {
+ double sum = 0;
+ int nanCount = 0;
+ for (int i = 0; i < m.length; i++)
+ {
+ if (!Double.isNaN(m[i])) // ignore NaN values in the array
+ {
+ sum += m[i];
+ } else {
+ nanCount++;
+ }
+ }
+ return sum / (double) (m.length - nanCount);
+ }
+
+ /**
+ * calculates the sum of an array
+ *
+ * @param m ~ array
+ * @return
+ */
+ public static double sum(double[] m)
+ {
+ double sum = 0;
+ for (int i = 0; i < m.length; i++)
+ {
+ if (!Double.isNaN(m[i])) // ignore NaN values in the array
+ {
+ sum += m[i];
+ }
+ }
+ return sum;
+ }
+
+ /**
+ * calculates the square root of each element in an array
+ *
+ * @param m ~ array
+ *
+ * @return
+ * TODO
+ * make general with function passed -> apply function to each element
+ */
+ public static double[] sqrt(double[] m)
+ {
+ double[] sqrts = new double[m.length];
+ for (int i = 0; i < m.length; i++)
+ {
+ sqrts[i] = Math.sqrt(m[i]);
+ }
+ return sqrts;
+ }
+
+ /**
+ * calculate element wise multiplication of two arrays with the same length
+ *
+ * @param a ~ array
+ * @param b ~ array
+ *
+ * @return
+ */
+ public static double[] elementwiseMultiply(byte[] a, double[] b) throws RuntimeException
+ {
+ if (a.length != b.length) // throw exception if the arrays do not have the same length
+ {
+ throw new SameLengthException(a.length, b.length);
+ }
+ double[] result = new double[a.length];
+ for (int i = 0; i < a.length; i++)
+ {
+ result[i] = a[i] * b[i];
+ }
+ return result;
+ }
+ public static double[] elementwiseMultiply(double[] a, double[] b) throws RuntimeException
+ {
+ if (a.length != b.length) // throw exception if the arrays do not have the same length
+ {
+ throw new SameLengthException(a.length, b.length);
+ }
+ double[] result = new double[a.length];
+ for (int i = 0; i < a.length; i++)
+ {
+ result[i] = a[i] * b[i];
+ }
+ return result;
+ }
+ public static byte[] elementwiseMultiply(byte[] a, byte[] b) throws RuntimeException
+ {
+ if (a.length != b.length) // throw exception if the arrays do not have the same length
+ {
+ throw new SameLengthException(a.length, b.length);
+ }
+ byte[] result = new byte[a.length];
+ for (int i = 0; i < a.length; i++)
+ {
+ result[i] = (byte) (a[i] * b[i]);
+ }
+ return result;
+ }
+ public static double[] elementwiseMultiply(double[] a, double b)
+ {
+ double[] result = new double[a.length];
+ for (int i = 0; i < a.length; i++)
+ {
+ result[i] = a[i] * b;
+ }
+ return result;
+ }
+
+ /**
+ * calculate element wise division of two arrays ~ a / b
+ *
+ * @param a ~ array
+ * @param b ~ array
+ *
+ * @return
+ */
+ public static double[] elementwiseDivide(double[] a, double[] b) throws RuntimeException
+ {
+ if (a.length != b.length) // throw exception if the arrays do not have the same length
+ {
+ throw new SameLengthException(a.length, b.length);
+ }
+ double[] result = new double[a.length];
+ for (int i = 0; i < a.length; i++)
+ {
+ result[i] = a[i] / b[i];
+ }
+ return result;
+ }
+
+ /**
+ * calculate element wise addition of two arrays
+ *
+ * @param a ~ array
+ * @param b ~ array
+ *
+ * @return
+ */
+ public static double[] elementwiseAdd(double[] a, double[] b) throws RuntimeException
+ {
+ if (a.length != b.length) // throw exception if the arrays do not have the same length
+ {
+ throw new SameLengthException(a.length, b.length);
+ }
+ double[] result = new double[a.length];
+
+ for (int i = 0; i < a.length; i++)
+ {
+ result[i] += a[i] + b[i];
+ }
+ return result;
+ }
+ public static double[] elementwiseAdd(double[] a, double b)
+ {
+ double[] result = new double[a.length];
+ for (int i = 0; i < a.length; i++)
+ {
+ result[i] = a[i] + b;
+ }
+ return result;
+ }
+
+ /**
+ * returns true if two arrays are element wise within a tolerance
+ *
+ * @param a ~ array
+ * @param b ~ array
+ * @param rtol ~ relative tolerance
+ * @param atol ~ absolute tolerance
+ * @param equalNAN ~ whether NaN at the same position return true
+ *
+ * @return
+ */
+ public static boolean allClose(double[] a, double[] b, double rtol, double atol, boolean equalNAN)
+ {
+ boolean areEqual = true;
+ for (int i = 0; i < a.length; i++)
+ {
+ if (equalNAN && (Double.isNaN(a[i]) && Double.isNaN(b[i]))) // if equalNAN == true -> skip the NaN pair
+ {
+ continue;
+ }
+ if (Math.abs(a[i] - b[i]) > (atol + rtol * Math.abs(b[i]))) // check for the similarity condition -> if not met -> break and return false
+ {
+ areEqual = false;
+ break;
+ }
+ }
+ return areEqual;
+ }
+
+ /**
+ * returns the index of the maximum and the maximum value of an array
+ *
+ * @param a ~ array
+ *
+ * @return
+ */
+ public static int[] findMax(int[] a)
+ {
+ int max = 0;
+ int maxIndex = 0;
+ for (int i = 0; i < a.length; i++)
+ {
+ if (a[i] > max)
+ {
+ max = a[i];
+ maxIndex = i;
+ }
+ }
+ return new int[]{maxIndex, max};
+ }
+
+ /**
+ * returns the dot product of two arrays
+ * @param a ~ array a
+ * @param b ~ array b
+ *
+ * @return
+ */
+ public static double dot(double[] a, double[] b)
+ {
+ if (a.length != b.length)
+ {
+ throw new IllegalArgumentException(String.format("Vectors do not have the same length (%d, %d)!", a.length, b.length));
+ }
+
+ double aibi = 0;
+ for (int i = 0; i < a.length; i++)
+ {
+ aibi += a[i] * b[i];
+ }
+ return aibi;
+ }
+
+ /**
+ * returns the euklidian norm of the vector
+ * @param v ~ vector
+ *
+ * @return
+ */
+ public static double norm(double[] v)
+ {
+ double result = 0;
+ for (double i : v)
+ {
+ result += Math.pow(i, 2);
+ }
+ return Math.sqrt(result);
+ }
+
+ /**
+ * returns the number of NaN in the vector
+ * @param v ~ vector
+ *
+ * @return
+ */
+ public static int countNaN(double[] v)
+ {
+ int cnt = 0;
+ for (double i : v)
+ {
+ if (Double.isNaN(i))
+ {
+ cnt++;
+ }
+ }
+ return cnt;
+ }
+
+ /**
+ * recursively calculates the permutations of total n items with r items per combination
+ * according to n!/(n-r)! by only multiplying the relevant terms
+ * @param n
+ * @param r
+ *
+ * @return permutations
+ */
+ public static long permutations(int n, int r)
+ {
+ if (n < r)
+ return permutations(r, n);
+
+ long result = 1l;
+ for (int i = 0; i < r; i++)
+ {
+ result *= (n-i);
+ }
+ return result;
+ }
+
+ /**
+ * calculate all unique combinations of n elements into r sized groups
+ * @param n
+ * @param r
+ *
+ * @return
+ */
+ public static int combinations(int n, int r)
+ {
+ int result = 1;
+ for (int i = 0; i < r; i++)
+ {
+ result *= (n-1);
+ }
+ return (int) (result / MiscMath.factorial(r));
+ }
+
+ /**
+ * calculate the factorial of n (n >= 0)
+ * @param n
+ *
+ * @return
+ */
+ public static int factorial(int n)
+ {
+ int result = 1;
+ for (int i = 0; i < n; i++)
+ {
+ result *= (n - i);
+ }
+ return result;
+ }
+
+}
--- /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.math;
+
+public class SameLengthException extends RuntimeException
+{
+ public SameLengthException(int lengthA, int lengthB)
+ {
+ this("Your arrays do not have the same length!", lengthA, lengthB);
+ }
+
+ public SameLengthException(String message, int lengthA, int lengthB)
+ {
+ super(String.format("%s (%d and %d)", message, lengthA, lengthB));
+ }
+
+}
import java.util.Map;
import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
+import jalview.analysis.Connectivity;
import jalview.analysis.Conservation;
import jalview.analysis.TreeModel;
import jalview.api.AlignCalcManagerI;
+ savedUpToDate);
return savedUpToDate;
}
+
+ public Hashtable<SequenceI, Integer> calculateConnectivity(float[][] scores, byte dim)
+ {
+ return Connectivity.getConnectivity(this, scores, dim);
+ }
}
top = height - 1;
points = new Vector<>();
- Point[] scores = pca.getComponents(top - 1, top - 2, top - 3, 100);
+ Point[] scores = pca.getComponents(top - 1, top - 2, top - 3, 1);
for (int i = 0; i < height; i++)
{
public void updateRcView(int dim1, int dim2, int dim3)
{
// note: actual indices for components are dim1-1, etc (patch for JAL-1123)
- Point[] scores = pca.getComponents(dim1 - 1, dim2 - 1, dim3 - 1, 100);
+ Point[] scores = pca.getComponents(dim1 - 1, dim2 - 1, dim3 - 1, 1);
for (int i = 0; i < pca.getHeight(); i++)
{
--- /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.viewmodel;
+
+import jalview.analysis.PaSiMap;
+import jalview.api.RotatableCanvasI;
+import jalview.api.analysis.ScoreModelI;
+import jalview.api.analysis.SimilarityParamsI;
+import jalview.datamodel.AlignmentView;
+import jalview.datamodel.Point;
+import jalview.datamodel.SequenceI;
+import jalview.datamodel.SequencePoint;
+import jalview.gui.PairwiseAlignPanel;
+import jalview.viewmodel.AlignmentViewport;
+
+import java.util.List;
+import java.util.Vector;
+
+public class PaSiMapModel
+{
+ /*
+ * inputs
+ */
+ private AlignmentViewport inputData;
+
+ private final SequenceI[] seqs;
+
+ /*
+ * options - score model, nucleotide / protein
+ */
+ private ScoreModelI scoreModel;
+
+ private boolean nucleotide = false;
+
+ /*
+ * outputs
+ */
+ private PaSiMap pasimap;
+
+ int top;
+
+ private List<SequencePoint> points;
+
+ /**
+ * Constructor given sequence data, score model and score calculation
+ * parameter options.
+ *
+ * @param seqData
+ * @param sqs
+ * @param nuc
+ * @param modelName
+ * @param params
+ */
+ public PaSiMapModel(AlignmentViewport seqData, SequenceI[] sqs, boolean nuc,
+ ScoreModelI modelName)
+ {
+ inputData = seqData;
+ seqs = sqs;
+ nucleotide = nuc;
+ scoreModel = modelName;
+ }
+
+ /**
+ * Performs the PaSiMap calculation (in the same thread) and extracts result data
+ * needed for visualisation by PaSiMapPanel
+ */
+ public void calculate(PairwiseAlignPanel pap)
+ {
+ pasimap = new PaSiMap(inputData, scoreModel, pap);
+ pasimap.run(); // executes in same thread, wait for completion
+
+ // Now find the component coordinates
+ int ii = 0;
+
+ while ((ii < seqs.length) && (seqs[ii] != null))
+ {
+ ii++;
+ }
+
+ int width = pasimap.getWidth();
+ int height = pasimap.getHeight();
+ top = width;
+
+ points = new Vector<>();
+ Point[] scores = pasimap.getComponents(width - 1, width - 2, width - 3, 1);
+
+ for (int i = 0; i < height; i++)
+ {
+ SequencePoint sp = new SequencePoint(seqs[i], scores[i]);
+ points.add(sp);
+ }
+ }
+
+ public void updateRc(RotatableCanvasI rc)
+ {
+ rc.setPoints(points, pasimap.getHeight());
+ }
+
+ public boolean isNucleotide()
+ {
+ return nucleotide;
+ }
+
+ public void setNucleotide(boolean nucleotide)
+ {
+ this.nucleotide = nucleotide;
+ }
+
+ /**
+ * Answers the index of the principal dimension of the PaSiMap
+ *
+ * @return
+ */
+ public int getTop()
+ {
+ return top;
+ }
+
+ public void setTop(int t)
+ {
+ top = t;
+ }
+
+ /**
+ * Updates the 3D coordinates for the list of points to the given dimensions.
+ * Principal dimension is getTop(). Next greatest eigenvector is getTop()-1.
+ * Note - pasimap.getComponents starts counting the spectrum from rank-2 to zero,
+ * rather than rank-1, so getComponents(dimN ...) == updateRcView(dimN+1 ..)
+ *
+ * @param dim1
+ * @param dim2
+ * @param dim3
+ */
+ public void updateRcView(int dim1, int dim2, int dim3)
+ {
+ // note: actual indices for components are dim1-1, etc (patch for JAL-1123)
+ Point[] scores = pasimap.getComponents(dim1 - 1, dim2 - 1, dim3 - 1, 1);
+
+ for (int i = 0; i < pasimap.getHeight(); i++)
+ {
+ points.get(i).coord = scores[i];
+ }
+ }
+
+ public String getDetails()
+ {
+ return pasimap.getDetails();
+ }
+
+ public String getAlignmentOutput()
+ {
+ return pasimap.getAlignmentOutput();
+ }
+
+ public AlignmentViewport getInputData()
+ {
+ return inputData;
+ }
+
+ public void setInputData(AlignmentViewport data)
+ {
+ inputData = data;
+ }
+
+ public String getPointsasCsv(boolean transformed, int xdim, int ydim,
+ int zdim)
+ {
+ StringBuffer csv = new StringBuffer();
+ csv.append("\"Sequence\"");
+ if (transformed)
+ {
+ csv.append(",");
+ csv.append(xdim);
+ csv.append(",");
+ csv.append(ydim);
+ csv.append(",");
+ csv.append(zdim);
+ }
+ else
+ {
+ for (int d = 1, dmax = (int) pasimap.getDim(); d <= dmax; d++)
+ {
+ csv.append("," + d);
+ }
+ }
+ csv.append("\n");
+ for (int s = 0; s < seqs.length; s++)
+ {
+ csv.append("\"" + seqs[s].getName() + "\"");
+ if (!transformed)
+ {
+ double[] fl = pasimap.component(s);
+ for (int d = fl.length - 1; d >= 0; d--)
+ {
+ csv.append(",");
+ csv.append(fl[d]);
+ }
+ } else {
+ Point p = points.get(s).coord;
+ csv.append(",").append(p.x);
+ csv.append(",").append(p.y);
+ csv.append(",").append(p.z);
+ }
+ csv.append("\n");
+ }
+ return csv.toString();
+ }
+
+ public String getScoreModelName()
+ {
+ return scoreModel == null ? "" : scoreModel.getName();
+ }
+
+ public void setScoreModel(ScoreModelI sm)
+ {
+ this.scoreModel = sm;
+ }
+
+ public List<SequencePoint> getSequencePoints()
+ {
+ return points;
+ }
+
+ public void setSequencePoints(List<SequencePoint> sp)
+ {
+ points = sp;
+ }
+
+ /**
+ * Answers the object holding the values of the computed PaSiMap
+ *
+ * @return
+ */
+ public PaSiMap getPasimapData()
+ {
+ return pasimap;
+ }
+
+ public void setPaSiMap(PaSiMap data)
+ {
+ pasimap = data;
+ }
+}
String s = "aArRnNzZxX *.-?";
assertArrayEquals(expected, as.indexEncode(s));
}
+ @Test(groups= {"Functional"})
+ public void testGlobalAlignment()
+ {
+ String seq1="CAGCTAGCG",seq2="CCATACGA";
+ Sequence sq1=new Sequence("s1",seq1),sq2=new Sequence("s2",seq2);
+ // AlignSeq doesn't report the unaligned regions at either end of sequences
+ //String alseq1="-CAGCTAGCG-",alseq2="CCA--TA-CGA";
+ // so we check we have the aligned segment correct only
+ String alseq1="CAGCTAGCG",alseq2="CA--TA-CG";
+ AlignSeq as = AlignSeq.doGlobalNWAlignment(sq1,sq2,AlignSeq.DNA);
+ assertEquals(as.getAStr1()+"\n"+as.getAStr2(),alseq1+"\n"+alseq2);
+ }
}