diff --git a/README.md b/README.md
index 4beb48917..7ef070b38 100644
--- a/README.md
+++ b/README.md
@@ -9,8 +9,8 @@ PHAT is under development in the Zehbe Lab ([http://zehbelab.weebly.com/](http:/
**Project Supervisor/Principal Investigator:** Dr. Ingeborg Zehbe, LU/TBRHRI Research Chair & Senior Scientist
**Project Lead/Biologist:** Robert Jackson, PhD Biotech Candidate
**Project Lead/Software Developer:** Chris Gibb, HBSc Comp Sci Student
-**Team Members:** Mitchell Pynn, Shane Liu, Jeremy Braun
+**Team Members:** Mitchell Pynn, Shane Liu, Jeremy Braun, Nick Catanzaro, Zachary Moorman
**How to Cite PHAT (pre-print):**
-Gibb CM, Jackson R, Mohammed S, Fiaidhi J, Zehbe I. Pathogen-Host Analysis Tool (PHAT): an Integrative Platform to Analyze Pathogen-Host Relationships in Next-Generation Sequencing Data. bioRxiv. https://doi.org/10.1101/178327
+Gibb CM, Jackson R, Mohammed S, Fiaidhi J, Zehbe I. Pathogen-Host Analysis Tool (PHAT): an Integrative Platform to Analyze Pathogen-Host Relationships in Next-Generation Sequencing Data. bioRxiv. https://doi.org/10.1101/178327
\ No newline at end of file
diff --git a/src/CheckForUpdateProcess.ts b/src/CheckForUpdateProcess.ts
index 0e5338d2b..130cad04d 100644
--- a/src/CheckForUpdateProcess.ts
+++ b/src/CheckForUpdateProcess.ts
@@ -1,4 +1,5 @@
import {AtomicOperationForkEvent,CompletionFlags} from "./req/atomicOperationsIPC";
+import * as atomic from "./req/operations/atomicOperations";
import * as getUpdate from "./req/getLatestUpdate";
let flags : CompletionFlags = new CompletionFlags();
@@ -28,7 +29,7 @@ process.on
data : res
}
);
- process.exit(0);
+ atomic.exitFork(0);
}).catch((arg : any) => {
console.log(arg);
flags.done = true;
@@ -41,7 +42,7 @@ process.on
data : arg
}
);
- process.exit(1);
+ atomic.exitFork(1);
});
}
}
@@ -58,7 +59,7 @@ process.on
data : err.message
}
);
- process.exit(1);
+ atomic.exitFork(1);
});
process.on("unhandledRejection",function(err : Error){
console.log(err);
@@ -72,5 +73,5 @@ process.on("unhandledRejection",function(err : Error){
data : err.message
}
);
- process.exit(1);
+ atomic.exitFork(1);
});
\ No newline at end of file
diff --git a/src/DownloadAndInstallUpdateProcess.ts b/src/DownloadAndInstallUpdateProcess.ts
index 010dc1bf9..fb61199fc 100644
--- a/src/DownloadAndInstallUpdateProcess.ts
+++ b/src/DownloadAndInstallUpdateProcess.ts
@@ -3,6 +3,7 @@ import * as cp from "child_process";
let GitHubReleases = require("github-releases");
+import * as atomic from "./req/operations/atomicOperations";
import {AtomicOperationForkEvent,CompletionFlags} from "./req/atomicOperationsIPC";
import {getReadable} from "./req/getAppPath";
@@ -71,7 +72,7 @@ process.on
);
installer.unref();
}
- process.exit(0);
+ atomic.exitFork(0);
});
});
@@ -90,7 +91,7 @@ process.on
data : err
}
);
- process.exit(1);
+ atomic.exitFork(1);
});
process.on("unhandledRejection",function(err : string){
console.log("ERROR "+err);
@@ -104,5 +105,5 @@ process.on("unhandledRejection",function(err : string){
data : err
}
);
- process.exit(1);
+ atomic.exitFork(1);
});
\ No newline at end of file
diff --git a/src/InputBamFileProcess.ts b/src/InputBamFileProcess.ts
index 00defcd22..ad4d4a989 100644
--- a/src/InputBamFileProcess.ts
+++ b/src/InputBamFileProcess.ts
@@ -106,7 +106,7 @@ process.on(
flags.done = true
flags.success = true;
update();
- process.exit(0);
+ atomic.exitFork(0);
})();
}
}
diff --git a/src/LinkRefSeqToAlignmentProcess.ts b/src/LinkRefSeqToAlignmentProcess.ts
index c11606eef..3659b1983 100644
--- a/src/LinkRefSeqToAlignmentProcess.ts
+++ b/src/LinkRefSeqToAlignmentProcess.ts
@@ -98,7 +98,7 @@ process.on(
flags.success = true;
update();
- process.exit(0);
+ atomic.exitFork(0);
})();
}
}
diff --git a/src/OpenProjectProcess.ts b/src/OpenProjectProcess.ts
index e640c8e94..3e910d37d 100644
--- a/src/OpenProjectProcess.ts
+++ b/src/OpenProjectProcess.ts
@@ -1,3 +1,4 @@
+import * as atomic from "./req/operations/atomicOperations";
import {AtomicOperationForkEvent,CompletionFlags} from "./req/atomicOperationsIPC";
import {ProjectManifest} from "./req/projectManifest";
import {openProject} from "./req//openProject";
@@ -40,7 +41,7 @@ process.on
flags : flags,
}
);
- process.exit(0);
+ atomic.exitFork(0);
}).catch((err) => {
flags.done = true;
flags.failure = true;
@@ -52,7 +53,7 @@ process.on
data : err
}
);
- process.exit(1);
+ atomic.exitFork(1);
});
}
}
@@ -69,7 +70,7 @@ process.on
data : err
}
);
- process.exit(1);
+ atomic.exitFork(1);
});
process.on("unhandledRejection",function(err : string){
@@ -84,5 +85,5 @@ process.on("unhandledRejection",function(err : string){
data : err
}
);
- process.exit(1);
+ atomic.exitFork(1);
});
\ No newline at end of file
diff --git a/src/RenderCoverageTrackProcess.ts b/src/RenderCoverageTrackProcess.ts
index 134f061d2..ecf2b482e 100644
--- a/src/RenderCoverageTrackProcess.ts
+++ b/src/RenderCoverageTrackProcess.ts
@@ -1,3 +1,4 @@
+import * as atomic from "./req/operations/atomicOperations";
import {AtomicOperationForkEvent,CompletionFlags} from "./req/atomicOperationsIPC";
import {AlignData} from "./req/alignData"
import * as cf from "./req/renderer/circularFigure";
@@ -39,7 +40,7 @@ process.on
}
}
);
- process.exit(0);
+ atomic.exitFork(0);
});
}
}
@@ -55,5 +56,5 @@ process.on
data : err
}
);
- process.exit(1);
+ atomic.exitFork(1);
});
\ No newline at end of file
diff --git a/src/RenderSNPTrackProcess.ts b/src/RenderSNPTrackProcess.ts
index a08dd1ae8..f227b4ac0 100644
--- a/src/RenderSNPTrackProcess.ts
+++ b/src/RenderSNPTrackProcess.ts
@@ -1,3 +1,4 @@
+import * as atomic from "./req/operations/atomicOperations";
import {AtomicOperationForkEvent,CompletionFlags} from "./req/atomicOperationsIPC";
import {AlignData} from "./req/alignData"
import * as cf from "./req/renderer/circularFigure";
@@ -39,7 +40,7 @@ process.on
}
}
);
- process.exit(0);
+ atomic.exitFork(0);
});
}
}
@@ -56,7 +57,7 @@ process.on
data : err
}
);
- process.exit(1);
+ atomic.exitFork(1);
});
process.on("unhandledRejection",function(err : string){
@@ -71,5 +72,5 @@ process.on("unhandledRejection",function(err : string){
data : err
}
);
- process.exit(1);
+ atomic.exitFork(1);
});
diff --git a/src/RunAlignmentProcess.ts b/src/RunAlignmentProcess.ts
index eeaa17a90..6ff0fadd7 100644
--- a/src/RunAlignmentProcess.ts
+++ b/src/RunAlignmentProcess.ts
@@ -121,7 +121,7 @@ process.on(
flags.done = true;
flags.success = true;
update();
- process.exit(0);
+ atomic.exitFork(0);
});
});
diff --git a/src/SaveCurrentProjectProcess.ts b/src/SaveCurrentProjectProcess.ts
index 9ecd83ca4..71127d7cf 100644
--- a/src/SaveCurrentProjectProcess.ts
+++ b/src/SaveCurrentProjectProcess.ts
@@ -1,11 +1,11 @@
-import {handleForkFailures} from "./req/operations/atomicOperations";
+import * as atomic from "./req/operations/atomicOperations";
import {AtomicOperationForkEvent,CompletionFlags} from "./req/atomicOperationsIPC";
import {ProjectManifest} from "./req/projectManifest";
import {saveCurrentProject} from "./req//saveCurrentProject";
let proj : ProjectManifest;
let flags : CompletionFlags = new CompletionFlags();
-handleForkFailures();
+atomic.handleForkFailures();
process.on
(
"message",function(ev : AtomicOperationForkEvent)
@@ -29,7 +29,7 @@ process.on
flags : flags,
}
);
- process.exit(0);
+ atomic.exitFork(0);
}).catch((err) => {
flags.done = true;
flags.failure = true;
@@ -41,7 +41,7 @@ process.on
data : err
}
);
- process.exit(1);
+ atomic.exitFork(1);
});
}
}
diff --git a/src/circularGenomeBuilder.html b/src/circularGenomeBuilder.html
index 97b3d23bb..cc8b849fe 100644
--- a/src/circularGenomeBuilder.html
+++ b/src/circularGenomeBuilder.html
@@ -69,6 +69,11 @@
Modal title
Delete Figure
+
+ Figure Options
+
+
diff --git a/src/circularGenomeBuilderRenderer.ts b/src/circularGenomeBuilderRenderer.ts
index 5b2ff79a1..bbf150e41 100644
--- a/src/circularGenomeBuilderRenderer.ts
+++ b/src/circularGenomeBuilderRenderer.ts
@@ -156,25 +156,33 @@ $
totalTracks++;
if(ops[i].flags.done && ops[i].flags.success)
{
- console.log("compiled "+ops[i].uuid);
if(ops[i].uuid)
{
+ console.log("compiled "+ops[i].uuid);
tc.removeTrack(ops[i].uuid);
genomeView.firstRender = true;
}
+ else if(ops[i].compileBase)
+ {
+ console.log("compiled base figure");
+ tc.resetBaseFigureSVG();
+ genomeView.firstRender = true;
+ }
}
}
}
}
if(totalTracks > 0)
document.getElementById("navBarLoadingText").innerHTML = `Recalculating ${totalTracks} tracks`;
- if(totalTracks == 1)
+ if(totalTracks == 0)
{
- setTimeout(function(){
- document.getElementById("navBarLoadingText").innerHTML = ``;
- },1000);
+ document.getElementById("navBarLoadingText").innerHTML = ``;
}
}
+ else if(arg.val === undefined)
+ {
+ document.getElementById("navBarLoadingText").innerHTML = ``;
+ }
}
}
viewMgr.render();
diff --git a/src/compileTemplatesProcess.ts b/src/compileTemplatesProcess.ts
index e0b58bd60..3abe4b857 100644
--- a/src/compileTemplatesProcess.ts
+++ b/src/compileTemplatesProcess.ts
@@ -81,8 +81,9 @@ function compileAndSend()
data : {
figure : figure
}
+ },function(){
+ process.exit(0);
});
- process.exit(0);
}
process.on(
diff --git a/src/guiTests/req/closeToolBar.ts b/src/guiTests/req/closeToolBar.ts
index b1f8bc01a..ebd89d8af 100644
--- a/src/guiTests/req/closeToolBar.ts
+++ b/src/guiTests/req/closeToolBar.ts
@@ -11,7 +11,6 @@ export async function closeToolBar() : Promise
{
console.log("Failed to open tool bar!");
console.log(toolBar);
- //process.exit(1);
}
toolBar[0].close();
resolve();
diff --git a/src/req/operations/CheckForUpdate.ts b/src/req/operations/CheckForUpdate.ts
index 805588187..a63d070b9 100644
--- a/src/req/operations/CheckForUpdate.ts
+++ b/src/req/operations/CheckForUpdate.ts
@@ -23,38 +23,26 @@ export class CheckForUpdate extends atomic.AtomicOperation
this.closeLogOnSuccess = true;
this.logRecord = atomic.openLog(this.name,"Check for Update");
let self = this;
- this.checkForUpdateProcess = cp.fork(getReadable("CheckForUpdate.js"));
- this.addPID(this.checkForUpdateProcess.pid);
- this.checkForUpdateProcess.on(
- "message",function(ev : AtomicOperationForkEvent)
+ this.checkForUpdateProcess = atomic.makeFork("CheckForUpdate.js",{
+ setData : true,
+ data : {}
+ },function(ev : AtomicOperationForkEvent){
+ self.logObject(ev);
+ if(ev.finishedSettingData == true)
{
- self.logObject(ev);
- if(ev.finishedSettingData == true)
- {
- self.checkForUpdateProcess.send(
- {
- run : true
- }
- );
- }
- if(ev.update == true)
- {
- self.extraData = ev.data;
- self.flags = ev.flags;
- self.update();
- }
- }
- );
- setTimeout(
- function(){
self.checkForUpdateProcess.send(
{
- setData : true,
- data : {
- }
+ run : true
}
);
- },500
- );
+ }
+ if(ev.update == true)
+ {
+ self.extraData = ev.data;
+ self.flags = ev.flags;
+ self.update();
+ }
+ });
+ this.addPID(this.checkForUpdateProcess.pid);
}
}
\ No newline at end of file
diff --git a/src/req/operations/CompileTemplates.ts b/src/req/operations/CompileTemplates.ts
index f78986288..937b94815 100644
--- a/src/req/operations/CompileTemplates.ts
+++ b/src/req/operations/CompileTemplates.ts
@@ -30,42 +30,31 @@ export class CompileTemplates extends atomic.AtomicOperation
public run() : void
{
let self = this;
- this.compileTemplatesProcess = cp.fork(getReadable("compileTemplates.js"));
- this.addPID(this.compileTemplatesProcess.pid);
- self.compileTemplatesProcess.on(
- "message",function(ev : AtomicOperationForkEvent){
- if(ev.update == true)
+ this.compileTemplatesProcess = atomic.makeFork("compileTemplates.js",{
+ setData : true,
+ data : {
+ figure : self.figure,
+ uuid : self.uuid,
+ compileBase : self.compileBase
+ },
+ name : self.name,
+ description : "Compile Templates For Figure"
+ },function(ev : AtomicOperationForkEvent){
+ if(ev.update == true)
+ {
+ self.flags = ev.flags;
+ if(ev.flags.done)
+ {
+ self.logRecord = ev.logRecord;
+ atomic.recordLogRecord(ev.logRecord);
+ }
+ if(ev.flags.success)
{
- self.flags = ev.flags;
- if(ev.flags.done)
- {
- self.logRecord = ev.logRecord;
- atomic.recordLogRecord(ev.logRecord);
- }
- if(ev.flags.success)
- {
- self.figure = ev.data.figure;
- }
- self.update();
+ self.figure = ev.data.figure;
}
+ self.update();
}
- );
-
- setTimeout(
- function(){
- self.compileTemplatesProcess.send(
- {
- setData : true,
- data : {
- figure : self.figure,
- uuid : self.uuid,
- compileBase : self.compileBase
- },
- name : self.name,
- description : "Compile Templates For Figure"
- }
- );
- },10
- );
+ });
+ this.addPID(this.compileTemplatesProcess.pid);
}
}
\ No newline at end of file
diff --git a/src/req/operations/DownloadAndInstallUpdate.ts b/src/req/operations/DownloadAndInstallUpdate.ts
index 55fd63b22..0e25bd30f 100644
--- a/src/req/operations/DownloadAndInstallUpdate.ts
+++ b/src/req/operations/DownloadAndInstallUpdate.ts
@@ -19,38 +19,27 @@ export class DownloadAndInstallUpdate extends atomic.AtomicOperation
{
this.logRecord = atomic.openLog(this.name,"Download and Install Update");
let self = this;
- this.downloadAndInstallUpdateProcess = cp.fork(getReadable("DownloadAndInstallUpdate.js"));
- this.addPID(this.downloadAndInstallUpdateProcess.pid);
- this.downloadAndInstallUpdateProcess.on(
- "message",function(ev : AtomicOperationForkEvent)
- {
- if(ev.finishedSettingData == true)
- {
- self.downloadAndInstallUpdateProcess.send(
- {
- run : true
- }
- );
- }
- if(ev.update == true)
- {
- self.extraData = ev.data;
- self.flags = ev.flags;
- self.update();
- }
+ this.downloadAndInstallUpdateProcess = atomic.makeFork("DownloadAndInstallUpdate.js",{
+ setData : true,
+ data : {
+ asset : self.asset
}
- );
- setTimeout(
- function(){
+ },function(ev : AtomicOperationForkEvent){
+ if(ev.finishedSettingData == true)
+ {
self.downloadAndInstallUpdateProcess.send(
{
- setData : true,
- data : {
- asset : self.asset
- }
+ run : true
}
);
- },500
- );
+ }
+ if(ev.update == true)
+ {
+ self.extraData = ev.data;
+ self.flags = ev.flags;
+ self.update();
+ }
+ });
+ this.addPID(this.downloadAndInstallUpdateProcess.pid);
}
}
\ No newline at end of file
diff --git a/src/req/operations/InputBamFile.ts b/src/req/operations/InputBamFile.ts
index f30197963..dcfd0aa41 100644
--- a/src/req/operations/InputBamFile.ts
+++ b/src/req/operations/InputBamFile.ts
@@ -22,50 +22,40 @@ export class InputBamFile extends atomic.AtomicOperation
this.closeLogOnFailure = false;
this.closeLogOnSuccess = false;
let self = this;
- this.inputBamFileProcess = cp.fork(getReadable("InputBamFile.js"));
- this.addPID(this.inputBamFileProcess.pid);
- self.inputBamFileProcess.on(
- "message",function(ev : AtomicOperationForkEvent){
- if(ev.finishedSettingData == true)
- {
- self.inputBamFileProcess.send(
- {
- run : true
- }
- );
- }
- if(ev.update == true)
- {
- self.flags = ev.flags;
- if(ev.flags.done)
- {
- self.alignData = ev.data.alignData;
- if(ev.flags.failure == true && self.alignData)
- {
- //make sure output dir is deleted on failure
- self.destinationArtifactsDirectories.push(getArtifactDir(self.alignData));
- }
- self.logRecord = ev.logRecord;
- atomic.recordLogRecord(ev.logRecord);
- }
- self.progressMessage = ev.progressMessage;
- self.update();
- }
- }
- );
- setTimeout(
- function(){
+ this.inputBamFileProcess = atomic.makeFork("InputBamFile.js",{
+ setData : true,
+ data : {
+ bamPath : self.bamPath
+ },
+ name : self.name,
+ description : "Input Bam File"
+ },function(ev : AtomicOperationForkEvent){
+ if(ev.finishedSettingData == true)
+ {
self.inputBamFileProcess.send(
{
- setData : true,
- data : {
- bamPath : self.bamPath
- },
- name : self.name,
- description : "Input Bam File"
+ run : true
}
);
}
- );
+ if(ev.update == true)
+ {
+ self.flags = ev.flags;
+ if(ev.flags.done)
+ {
+ self.alignData = ev.data.alignData;
+ if(ev.flags.failure == true && self.alignData)
+ {
+ //make sure output dir is deleted on failure
+ self.destinationArtifactsDirectories.push(getArtifactDir(self.alignData));
+ }
+ self.logRecord = ev.logRecord;
+ atomic.recordLogRecord(ev.logRecord);
+ }
+ self.progressMessage = ev.progressMessage;
+ self.update();
+ }
+ });
+ this.addPID(this.inputBamFileProcess.pid);
}
}
\ No newline at end of file
diff --git a/src/req/operations/InstallUpdate.ts b/src/req/operations/InstallUpdate.ts
index 66dd250a5..08ca92630 100644
--- a/src/req/operations/InstallUpdate.ts
+++ b/src/req/operations/InstallUpdate.ts
@@ -20,20 +20,15 @@ export class InstallUpdate extends atomic.AtomicOperation
let self = this;
try
{
- this.installUpdateJob = cp.fork(getReadable("installUpdate.js"));
- this.addPID(this.installUpdateJob.pid);
- this.installUpdateJob.on
- (
- "message",function(data : any)
+ this.installUpdateJob = atomic.makeFork("installUpdate.js",{},function(data : any){
+ if(data.totalFiles)
{
- if(data.totalFiles)
- {
- self.filesInUpdate = data.totalFiles;
- self.update();
- self.setSuccess(self.flags);
- }
+ self.filesInUpdate = data.totalFiles;
+ self.update();
+ self.setSuccess(self.flags);
}
- );
+ });
+ this.addPID(this.installUpdateJob.pid);
}
catch(err)
diff --git a/src/req/operations/LinkRefSeqToAlignment.ts b/src/req/operations/LinkRefSeqToAlignment.ts
index 35221f58d..d2207f5c9 100644
--- a/src/req/operations/LinkRefSeqToAlignment.ts
+++ b/src/req/operations/LinkRefSeqToAlignment.ts
@@ -26,51 +26,41 @@ export class LinkRefSeqToAlignment extends atomic.AtomicOperation
this.closeLogOnFailure = false;
this.closeLogOnSuccess = false;
let self = this;
- this.linkRefSeqToAlignmentProcess = cp.fork(getReadable("LinkRefSeqToAlignment.js"));
- this.addPID(this.linkRefSeqToAlignmentProcess.pid);
- self.linkRefSeqToAlignmentProcess.on(
- "message",function(ev : AtomicOperationForkEvent){
- if(ev.finishedSettingData == true)
+ this.linkRefSeqToAlignmentProcess = atomic.makeFork("LinkRefSeqToAlignment.js",{
+ setData : true,
+ data : {
+ align : self.alignData,
+ fasta : self.fasta
+ },
+ name : self.name,
+ description : "Link Ref Seq To Alignment"
+ },function(ev : AtomicOperationForkEvent){
+ if(ev.finishedSettingData == true)
+ {
+ self.linkRefSeqToAlignmentProcess.send(
+ {
+ run : true
+ }
+ );
+ }
+ if(ev.update == true)
+ {
+ self.flags = ev.flags;
+ if(ev.flags.success == true)
{
- self.linkRefSeqToAlignmentProcess.send(
- {
- run : true
- }
- );
+ self.alignData = ev.data.alignData;
}
- if(ev.update == true)
+ if(ev.flags.done)
{
- self.flags = ev.flags;
- if(ev.flags.success == true)
- {
- self.alignData = ev.data.alignData;
- }
- if(ev.flags.done)
- {
- self.logRecord = ev.logRecord;
- atomic.recordLogRecord(ev.logRecord);
- }
- self.step = ev.step;
- self.progressMessage = ev.progressMessage;
- console.log(self.step+" "+self.progressMessage);
- self.update();
+ self.logRecord = ev.logRecord;
+ atomic.recordLogRecord(ev.logRecord);
}
+ self.step = ev.step;
+ self.progressMessage = ev.progressMessage;
+ console.log(self.step+" "+self.progressMessage);
+ self.update();
}
- );
- setTimeout(
- function(){
- self.linkRefSeqToAlignmentProcess.send(
- {
- setData : true,
- data : {
- align : self.alignData,
- fasta : self.fasta
- },
- name : self.name,
- description : "Link Ref Seq To Alignment"
- }
- );
- },500
- );
+ });
+ this.addPID(this.linkRefSeqToAlignmentProcess.pid);
}
}
\ No newline at end of file
diff --git a/src/req/operations/OpenProject.ts b/src/req/operations/OpenProject.ts
index fbb3c783e..15f629071 100644
--- a/src/req/operations/OpenProject.ts
+++ b/src/req/operations/OpenProject.ts
@@ -27,49 +27,37 @@ export class OpenProject extends atomic.AtomicOperation
{
this.logRecord = atomic.openLog(this.name,"Open Project");
let self = this;
- this.openProjectProcess = cp.fork(getReadable("OpenProject.js"));
- this.addPID(this.openProjectProcess.pid);
- self.openProjectProcess.on(
- "message",function(ev : AtomicOperationForkEvent)
+ this.openProjectProcess = atomic.makeFork("OpenProject.js",{
+ setData : true,
+ data : {
+ proj : self.proj,
+ externalProjectPath : self.externalProjectPath
+ },
+ readableBasePath : getReadable(""),
+ writableBasePath : getWritable(""),
+ readableAndWritableBasePath : getReadableAndWritable("")
+
+ },function(ev : AtomicOperationForkEvent){
+ self.logObject(ev);
+ if(ev.finishedSettingData == true)
{
- self.logObject(ev);
- if(ev.finishedSettingData == true)
- {
- self.openProjectProcess.send(
- {
- run : true
- }
- );
- }
- if(ev.update == true)
- {
- self.extraData = ev.data;
- self.flags = ev.flags;
- if(ev.flags.success == true)
- {
- self.setSuccess(self.flags);
- }
- self.update();
- }
- }
- );
- setTimeout(
- function(){
self.openProjectProcess.send(
{
- setData : true,
- data : {
- proj : self.proj,
- externalProjectPath : self.externalProjectPath
- },
- readableBasePath : getReadable(""),
- writableBasePath : getWritable(""),
- readableAndWritableBasePath : getReadableAndWritable("")
-
+ run : true
}
);
- },10
- );
-
+ }
+ if(ev.update == true)
+ {
+ self.extraData = ev.data;
+ self.flags = ev.flags;
+ if(ev.flags.success == true)
+ {
+ self.setSuccess(self.flags);
+ }
+ self.update();
+ }
+ });
+ this.addPID(this.openProjectProcess.pid);
}
}
\ No newline at end of file
diff --git a/src/req/operations/RenderCoverageTrack.ts b/src/req/operations/RenderCoverageTrack.ts
index cead8cdff..f2129b422 100644
--- a/src/req/operations/RenderCoverageTrack.ts
+++ b/src/req/operations/RenderCoverageTrack.ts
@@ -34,9 +34,40 @@ export class RenderCoverageTrackForContig extends atomic.AtomicOperation
{
this.logRecord = atomic.openLog(this.name,"Render Coverage Track");
let self = this;
- this.renderCoverageTrackProcess = cp.fork(getReadable("RenderCoverageTrack.js"));
+ this.renderCoverageTrackProcess = atomic.makeFork("RenderCoverageTrack.js",{
+ setData : true,
+ data : {
+ alignData : self.alignData,
+ contiguuid : self.contiguuid,
+ circularFigure : self.circularFigure,
+ colour : self.colour
+ }
+ },function(ev : AtomicOperationForkEvent){
+ if(ev.finishedSettingData == true)
+ {
+ self.renderCoverageTrackProcess.send(
+ {
+ run : true
+ }
+ );
+ }
+
+ if(ev.update == true)
+ {
+ self.extraData = ev.data;
+ self.flags = ev.flags;
+ if(ev.flags.success == true)
+ {
+ self.circularFigure = ev.data.circularFigure;
+ self.contiguuid = ev.data.contiguuid;
+ self.alignData = ev.data.alignData;
+ self.colour = ev.data.colour;
+ }
+ self.update();
+ }
+ });
this.addPID(this.renderCoverageTrackProcess.pid);
- self.renderCoverageTrackProcess.on(
+ /*self.renderCoverageTrackProcess.on(
"message",function(ev : AtomicOperationForkEvent)
{
if(ev.finishedSettingData == true)
@@ -77,6 +108,6 @@ export class RenderCoverageTrackForContig extends atomic.AtomicOperation
}
);
},500
- );
+ );*/
}
}
\ No newline at end of file
diff --git a/src/req/operations/RenderSNPTrack.ts b/src/req/operations/RenderSNPTrack.ts
index 37770660b..7de0fb258 100644
--- a/src/req/operations/RenderSNPTrack.ts
+++ b/src/req/operations/RenderSNPTrack.ts
@@ -34,48 +34,37 @@ export class RenderSNPTrackForContig extends atomic.AtomicOperation
{
this.logRecord = atomic.openLog(this.name,"Render SNP Track");
let self = this;
- this.renderSNPTrackProcess = cp.fork(getReadable("RenderSNPTrack.js"));
- this.addPID(this.renderSNPTrackProcess.pid);
- self.renderSNPTrackProcess.on(
- "message",function(ev : AtomicOperationForkEvent)
- {
- if(ev.finishedSettingData == true)
- {
- self.renderSNPTrackProcess.send(
- {
- run : true
- }
- );
- }
- if(ev.update == true)
- {
- self.extraData = ev.data;
- self.flags = ev.flags;
- if(ev.flags.success == true)
- {
- self.circularFigure = ev.data.circularFigure;
- self.contiguuid = ev.data.contiguuid;
- self.alignData = ev.data.alignData;
- self.colour = ev.data.colour;
- }
- self.update();
- }
+ this.renderSNPTrackProcess = atomic.makeFork("RenderSNPTrack.js",{
+ setData : true,
+ data : {
+ alignData : self.alignData,
+ contiguuid : self.contiguuid,
+ circularFigure : self.circularFigure,
+ colour : self.colour
}
- );
- setTimeout(
- function(){
+ },function(ev : AtomicOperationForkEvent){
+ if(ev.finishedSettingData == true)
+ {
self.renderSNPTrackProcess.send(
{
- setData : true,
- data : {
- alignData : self.alignData,
- contiguuid : self.contiguuid,
- circularFigure : self.circularFigure,
- colour : self.colour
- }
+ run : true
}
);
- },500
- );
+ }
+ if(ev.update == true)
+ {
+ self.extraData = ev.data;
+ self.flags = ev.flags;
+ if(ev.flags.success == true)
+ {
+ self.circularFigure = ev.data.circularFigure;
+ self.contiguuid = ev.data.contiguuid;
+ self.alignData = ev.data.alignData;
+ self.colour = ev.data.colour;
+ }
+ self.update();
+ }
+ });
+ this.addPID(this.renderSNPTrackProcess.pid);
}
}
\ No newline at end of file
diff --git a/src/req/operations/RunAlignment.ts b/src/req/operations/RunAlignment.ts
index 9f3061cd5..f421e3b3d 100644
--- a/src/req/operations/RunAlignment.ts
+++ b/src/req/operations/RunAlignment.ts
@@ -43,55 +43,45 @@ export class RunAlignment extends atomic.AtomicOperation
this.closeLogOnFailure = false;
this.closeLogOnSuccess = false;
let self = this;
- this.runAlignmentProcess = cp.fork(getReadable("RunAlignment.js"));
- this.addPID(this.runAlignmentProcess.pid);
- self.runAlignmentProcess.on(
- "message",function(ev : AtomicOperationForkEvent){
- if(ev.finishedSettingData == true)
- {
- self.runAlignmentProcess.send(
- {
- run : true
- }
- );
- }
- if(ev.pid)
+ this.runAlignmentProcess = atomic.makeFork("RunAlignment.js",{
+ setData : true,
+ data : {
+ alignData : self.alignData
+ },
+ name : self.name,
+ description : "Run Alignment"
+ },function(ev : AtomicOperationForkEvent){
+ if(ev.finishedSettingData == true)
+ {
+ self.runAlignmentProcess.send(
+ {
+ run : true
+ }
+ );
+ }
+ if(ev.pid)
+ {
+ self.addPID(ev.pid);
+ console.log(ev.pid);
+ }
+ if(ev.update == true)
+ {
+ self.flags = ev.flags;
+ if(ev.flags.success == true)
{
- self.addPID(ev.pid);
- console.log(ev.pid);
+ self.alignData = ev.data.alignData;
}
- if(ev.update == true)
+ if(ev.flags.done)
{
- self.flags = ev.flags;
- if(ev.flags.success == true)
- {
- self.alignData = ev.data.alignData;
- }
- if(ev.flags.done)
- {
- self.logRecord = ev.logRecord;
- atomic.recordLogRecord(ev.logRecord);
- }
- self.step = ev.step;
- self.progressMessage = ev.progressMessage;
- console.log(self.step+" "+self.progressMessage);
- self.update();
+ self.logRecord = ev.logRecord;
+ atomic.recordLogRecord(ev.logRecord);
}
+ self.step = ev.step;
+ self.progressMessage = ev.progressMessage;
+ console.log(self.step+" "+self.progressMessage);
+ self.update();
}
- );
- setTimeout(
- function(){
- self.runAlignmentProcess.send(
- {
- setData : true,
- data : {
- alignData : self.alignData
- },
- name : self.name,
- description : "Run Alignment"
- }
- );
- },500
- );
+ });
+ this.addPID(this.runAlignmentProcess.pid);
}
}
\ No newline at end of file
diff --git a/src/req/operations/SaveCurrentProject.ts b/src/req/operations/SaveCurrentProject.ts
index 261a671c1..f7f2ca32c 100644
--- a/src/req/operations/SaveCurrentProject.ts
+++ b/src/req/operations/SaveCurrentProject.ts
@@ -21,42 +21,30 @@ export class SaveCurrentProject extends atomic.AtomicOperation
{
this.logRecord = atomic.openLog(this.name,"Save Current Project");
let self = this;
- this.saveCurrentProjectProcess = cp.fork(getReadable("SaveCurrentProject.js"));
- this.addPID(this.saveCurrentProjectProcess.pid);
- self.saveCurrentProjectProcess.on(
- "message",function(ev : AtomicOperationForkEvent)
+ this.saveCurrentProjectProcess = atomic.makeFork("SaveCurrentProject.js",{
+ setData : true,
+ data : self.proj
+ },function(ev : AtomicOperationForkEvent){
+ self.logObject(ev);
+ if(ev.finishedSettingData == true)
{
- self.logObject(ev);
- if(ev.finishedSettingData == true)
- {
- self.saveCurrentProjectProcess.send(
- {
- run : true
- }
- );
- }
- if(ev.update == true)
- {
- self.extraData = ev.data;
- self.flags = ev.flags;
- if(ev.flags.success == true)
- {
- self.setSuccess(self.flags);
- }
- self.update();
- }
- }
- );
- setTimeout(
- function(){
self.saveCurrentProjectProcess.send(
{
- setData : true,
- data : self.proj
+ run : true
}
);
- },500
- );
-
+ }
+ if(ev.update == true)
+ {
+ self.extraData = ev.data;
+ self.flags = ev.flags;
+ if(ev.flags.success == true)
+ {
+ self.setSuccess(self.flags);
+ }
+ self.update();
+ }
+ });
+ this.addPID(this.saveCurrentProjectProcess.pid);
}
}
\ No newline at end of file
diff --git a/src/req/operations/atomicOperations.ts b/src/req/operations/atomicOperations.ts
index 1d3641ad8..a9742b64d 100644
--- a/src/req/operations/atomicOperations.ts
+++ b/src/req/operations/atomicOperations.ts
@@ -1,6 +1,7 @@
import {EventEmitter} from "events";
import * as fs from "fs";
import * as readline from "readline";
+import * as cp from "child_process";
const uuidv4 : () => string = require("uuid/v4");
import * as rimraf from "rimraf";
@@ -8,7 +9,7 @@ import * as mkdirp from "mkdirp";
import {AtomicOperationForkEvent} from "./../atomicOperationsIPC";
import {SpawnRequestParams} from "./../JobIPC";
-import {getReadableAndWritable} from "./../getAppPath";
+import {getReadableAndWritable,getReadable} from "./../getAppPath";
/**
* Class representing some operation which should be run atomically
@@ -294,7 +295,7 @@ export abstract class AtomicOperation
*/
public logObject(obj : any) : void
{
- logString(this.logRecord,JSON.stringify(obj));
+ logString(this.logRecord,JSON.stringify(obj,undefined,4));
}
}
@@ -315,6 +316,62 @@ export class ForkLogger extends AtomicOperation
public run(){}
}
+
+/**
+ * Forks target, passing data and piping stdout/stderr to console.
+ * Calls cb on messages from the forked ChildProcess
+ *
+ * @export
+ * @param {string} target
+ * @param {*} data
+ * @param {(ev : any) => void} cb
+ * @returns {cp.ChildProcess}
+ */
+export function makeFork(target : string,data : any,cb : (ev : any) => void) : cp.ChildProcess
+{
+ let res = cp.fork(
+ getReadable(target),[],{
+ silent : true
+ }
+ );
+
+ res.stdout.on("data",function(data : Buffer){
+ console.log(data.toString());
+ });
+
+ res.stderr.on("data",function(data : Buffer){
+ console.error(data.toString());
+ });
+
+ res.on("message",function(ev : any){
+ cb(ev);
+ });
+
+ res.on("exit",function(code : number){
+ console.log(`${target} exited with ${code}`);
+ });
+
+ setTimeout(
+ function(){
+ res.send(data);
+ },10
+ );
+
+ return res;
+}
+
+/**
+ * Disconnects IPC channel and triggers a process exit of retCode
+ *
+ * @export
+ * @param {number} retCode
+ */
+export function exitFork(retCode : number) : void
+{
+ process.disconnect();
+ process.exitCode = retCode;
+}
+
/**
* Registers traps for unhandled errors in the current process. Logs exception details and stack traces
* using the provided logger
@@ -345,7 +402,7 @@ export function handleForkFailures(logger? : ForkLogger,progressMessage? : strin
}
process.send(failureObj);
- process.exit(1);
+ exitFork(1);
};
(process as NodeJS.EventEmitter).on("uncaughtException",function(err : Error){
diff --git a/src/req/renderer/circularFigure.ts b/src/req/renderer/circularFigure.ts
index 7ab4ba320..332595e40 100644
--- a/src/req/renderer/circularFigure.ts
+++ b/src/req/renderer/circularFigure.ts
@@ -174,6 +174,8 @@ export class CircularFigure
public radius : number;
public height : number;
public width : number;
+ public isInteractive : boolean;
+ public showContigNames : boolean;
public circularFigureBPTrackOptions : CircularFigureBPTrackOptions;
public renderedCoverageTracks : Array;
public renderedSNPTracks : Array;
@@ -203,6 +205,18 @@ export class CircularFigure
this.contigs[1].loaded = true;
}
this.customContigs = new Array();
+ this.isInteractive = true;
+ this.showContigNames = true;
+ let totalBP = 0;
+ for(let i = 0; i != this.contigs.length; ++i)
+ {
+ totalBP += this.contigs[i].bp;
+ }
+ if(this.contigs.length >= 50 || totalBP >= 1000000)
+ {
+ this.isInteractive = false;
+ this.showContigNames = false;
+ }
cacheBaseFigure(this);
}
}
@@ -232,7 +246,7 @@ export abstract class FigureCanvas
* @param {number} [end=-1]
* @returns {string}
*/
-export function renderContig(contig : Contig,start : number = -1,end : number = -1) : string
+export function renderContig(figure : CircularFigure,contig : Contig,start : number = -1,end : number = -1) : string
{
if(start == -1)
start = contig.start;
@@ -247,12 +261,13 @@ export function renderContig(contig : Contig,start : number = -1,end : number =
vAdjust : contig.vAdjust,
markerStyle : `fill:${contig.color};opacity:${contig.opacity};`,
uuid : contig.uuid,
- onClick : "markerOnClick"
+ onClick : "markerOnClick",
+ isInteractive : figure.isInteractive
})}
${markerLabel.add(
{
type : "path",
- text : contig.alias,
+ text : figure.showContigNames ? contig.alias : "",
labelStyle : `fill:${contig.fontFill};opacity:${contig.opacity};`
})}
${markerLabel.end()}
@@ -280,7 +295,8 @@ export function renderBaseFigure(figure : CircularFigure) : string
{
text : figure.name,
labelStyle : "font-size:20px;font-weight:400",
- onClick : "figureNameOnClick"
+ onClick : "figureNameOnClick",
+ isInteractive : figure.isInteractive
})}
${trackLabel.end()}
${(()=>
@@ -289,12 +305,12 @@ export function renderBaseFigure(figure : CircularFigure) : string
let lastLocation = 0;
for(let i = 0; i != figure.contigs.length; ++i)
{
- res += renderContig(figure.contigs[i],lastLocation,lastLocation+figure.contigs[i].bp);
+ res += renderContig(figure,figure.contigs[i],lastLocation,lastLocation+figure.contigs[i].bp);
lastLocation = lastLocation + figure.contigs[i].bp;
}
for(let i = 0; i != figure.customContigs.length; ++i)
{
- res += renderContig(figure.customContigs[i],figure.customContigs[i].start,figure.customContigs[i].end);
+ res += renderContig(figure,figure.customContigs[i],figure.customContigs[i].start,figure.customContigs[i].end);
}
return res;
})()}
@@ -363,6 +379,20 @@ export function getBaseFigureSVGFromCache(figure : CircularFigure) : string
return (fs.readFileSync(getReadableAndWritable(`rt/circularFigures/${figure.uuid}/baseFigure.svg`)));
}
+/**
+ * Deletes the contents of the current disk SVG cache for the base figure of figure
+ *
+ * @export
+ * @param {CircularFigure} figure
+ */
+export function deleteBaseFigureSVGFromCache(figure : CircularFigure) : void
+{
+ try
+ {
+ fs.unlinkSync(getReadableAndWritable(`rt/circularFigures/${figure.uuid}/baseFigure.svg`));
+ }
+ catch(err){}
+}
/**
* Returns the distance from the begginning of the figure to the begginning of the contig specified by contiguuid
diff --git a/src/req/renderer/circularGenome/trackLabel.ts b/src/req/renderer/circularGenome/trackLabel.ts
index 7fc835a0e..26ca38c17 100644
--- a/src/req/renderer/circularGenome/trackLabel.ts
+++ b/src/req/renderer/circularGenome/trackLabel.ts
@@ -1,15 +1,16 @@
export function add(
- options? : {
+ options : {
text? : string,
labelStyle? : string,
vAdjust? : string,
wAdjust? : string,
- onClick? : string
+ onClick? : string,
+ isInteractive : boolean
}
) : string
{
let res = `
- {return options.onClick ? `ng-click="${options.onClick}()"` : "";})()} ${
+ {return options.onClick ? `ng-click="${options.onClick}()"` : "";})()}` : ""} ${
(
()=>
{
diff --git a/src/req/renderer/circularGenome/trackMarker.ts b/src/req/renderer/circularGenome/trackMarker.ts
index c17d0fa68..5e80f0a45 100644
--- a/src/req/renderer/circularGenome/trackMarker.ts
+++ b/src/req/renderer/circularGenome/trackMarker.ts
@@ -1,5 +1,5 @@
export function add(
- options? : {
+ options : {
start? : string,
end? : string,
markerStyle? : string,
@@ -9,13 +9,14 @@ export function add(
vAdjust? : number,
wAdjust? : string,
uuid? : string,
- onClick? : string
+ onClick? : string,
+ isInteractive : boolean
}
) : string
{
let res = `
{
diff --git a/src/req/renderer/circularGenomeBuilderRenderer/centreFigure.ts b/src/req/renderer/circularGenomeBuilderRenderer/centreFigure.ts
index 970389c81..6dcfd994d 100644
--- a/src/req/renderer/circularGenomeBuilderRenderer/centreFigure.ts
+++ b/src/req/renderer/circularGenomeBuilderRenderer/centreFigure.ts
@@ -1,4 +1,11 @@
import * as cf from "./../circularFigure";
+/**
+ * Center div based on the dimensions of figure and the window
+ *
+ * @export
+ * @param {HTMLElement} div
+ * @param {cf.CircularFigure} figure
+ */
export function centreFigure(div : HTMLElement,figure : cf.CircularFigure) : void
{
if(div)
diff --git a/src/req/renderer/circularGenomeBuilderRenderer/displayFigure.ts b/src/req/renderer/circularGenomeBuilderRenderer/displayFigure.ts
index 445903e3e..a78452163 100644
--- a/src/req/renderer/circularGenomeBuilderRenderer/displayFigure.ts
+++ b/src/req/renderer/circularGenomeBuilderRenderer/displayFigure.ts
@@ -7,7 +7,54 @@ import * as viewMgr from "./../viewMgr";
import * as masterView from "./masterView";
import {GenomeView} from "./genomeView";
import {centreFigure} from "./centreFigure";
+/**
+ * Displays the currently set figure
+ *
+ * @export
+ * @param {GenomeView} self
+ * @returns {Promise}
+ */
export async function displayFigure(self : GenomeView) : Promise
+{
+ if(!self.genome.isInteractive)
+ return await displayNonInteractiveFigure(self);
+ else
+ return await displayInteractiveFigure(self);
+
+}
+/**
+ * Renders a figure as a non-interactive SVG using the specified canvas
+ *
+ * @export
+ * @param {GenomeView} self
+ * @returns {Promise}
+ */
+export async function displayNonInteractiveFigure(self : GenomeView) : Promise
+{
+ return new Promise((resolve,reject) => {
+ tc.refreshCache(self.genome);
+ removeDiv(self);
+
+ let $div : any = $(`
+
+ ${getSelectedDataTrackSVGsFromCache(self)}
+ ${tc.baseFigureSVG ? tc.baseFigureSVG : ""}
+
+ `);
+
+ $(document.body).append($div);
+ centreFigure(document.getElementById(self.div),self.genome);
+ resolve();
+ });
+}
+/**
+ * Renders a figure as interactive using Angular bindings using the specified canvas
+ *
+ * @export
+ * @param {GenomeView} self
+ * @returns {Promise}
+ */
+export async function displayInteractiveFigure(self : GenomeView) : Promise
{
//This is an unholy mess adapted from the example given inline in the
//angular source code https://github.com/angular/angular.js/blob/master/src/auto/injector.js
@@ -25,19 +72,8 @@ export async function displayFigure(self : GenomeView) : Promise
return new Promise((resolve,reject) => {
setImmediate(function(){
setImmediate(function(){
- try
- {
- document.body.removeChild(document.getElementById("controls"));
- }
- catch(err){}
- try
- {
- //Remove the div this view is bound to
- document.body.removeChild(document.getElementById(self.div));
- }
- catch(err){}
- $("#"+self.div).remove();
-
+
+ removeDiv(self);
for(let i = 0; i != self.genome.contigs.length; ++i)
{
@@ -68,39 +104,11 @@ export async function displayFigure(self : GenomeView) : Promise
$div = $(`
- ${(()=>{
- let res = "";
- for(let i = 0; i != self.genome.renderedCoverageTracks.length; ++i)
- {
- if(self.genome.renderedCoverageTracks[i].checked)
- {
- try
- {
- res += `
`;
- res += tc.getCachedCoverageTrack(self.genome.renderedCoverageTracks[i]);
- res += `
`;
- }
- catch(err){}
- }
- }
- for(let i = 0; i != self.genome.renderedSNPTracks.length; ++i)
- {
- if(self.genome.renderedSNPTracks[i].checked)
- {
- try
- {
- res += `
`;
- res += tc.getCachedSNPTrack(self.genome.renderedSNPTracks[i]);
- res += `
`;
- }
- catch(err){}
- }
- }
- return res;
- })()}
-
- ${templates}
-
+ ${getSelectedDataTrackSVGsFromCache(self)}
+
+
+ ${templates}
+
`);
$(document.body).append($div);
@@ -151,4 +159,65 @@ export async function displayFigure(self : GenomeView) : Promise
});
});
});
+}
+
+/**
+ * Delete the div used by self for rendering
+ *
+ * @export
+ * @param {GenomeView} self
+ */
+export function removeDiv(self : GenomeView) : void
+{
+ try
+ {
+ document.body.removeChild(document.getElementById("controls"));
+ }
+ catch(err){}
+ try
+ {
+ //Remove the div this view is bound to
+ document.body.removeChild(document.getElementById(self.div));
+ }
+ catch(err){}
+ $("#"+self.div).remove();
+}
+
+/**
+ * Returns SVGs for all selected tracks, wrapped in divs ready for rendering
+ *
+ * @export
+ * @param {GenomeView} self
+ * @returns {string}
+ */
+export function getSelectedDataTrackSVGsFromCache(self : GenomeView) : string
+{
+ let res = "";
+ for(let i = 0; i != self.genome.renderedCoverageTracks.length; ++i)
+ {
+ if(self.genome.renderedCoverageTracks[i].checked)
+ {
+ try
+ {
+ res += ``;
+ res += tc.getCachedCoverageTrack(self.genome.renderedCoverageTracks[i]);
+ res += `
`;
+ }
+ catch(err){}
+ }
+ }
+ for(let i = 0; i != self.genome.renderedSNPTracks.length; ++i)
+ {
+ if(self.genome.renderedSNPTracks[i].checked)
+ {
+ try
+ {
+ res += ``;
+ res += tc.getCachedSNPTrack(self.genome.renderedSNPTracks[i]);
+ res += `
`;
+ }
+ catch(err){}
+ }
+ }
+ return res;
}
\ No newline at end of file
diff --git a/src/req/renderer/circularGenomeBuilderRenderer/exportToSVG.ts b/src/req/renderer/circularGenomeBuilderRenderer/exportToSVG.ts
index 9ff6ac433..452de661f 100644
--- a/src/req/renderer/circularGenomeBuilderRenderer/exportToSVG.ts
+++ b/src/req/renderer/circularGenomeBuilderRenderer/exportToSVG.ts
@@ -2,6 +2,15 @@ import * as fs from "fs";
import {GenomeView} from "./genomeView";
import * as cf from "./../circularFigure";
+/**
+ * Writes the SVG to fileName. Allows DOM updates to interleave execution
+ *
+ * @export
+ * @param {GenomeView} self
+ * @param {string} fileName
+ * @param {string} svg
+ * @returns {Promise}
+ */
export async function writeSVG(self : GenomeView,fileName : string,svg : string) : Promise
{
return new Promise((resolve,reject) => {
@@ -20,6 +29,13 @@ export async function writeSVG(self : GenomeView,fileName : string,svg : string)
});
}
+/**
+ * Serializes the canvas div. Allows DOM updates to interleave execution
+ *
+ * @export
+ * @param {GenomeView} self
+ * @returns {Promise}
+ */
export async function serializeFigure(self : GenomeView) : Promise
{
return new Promise((resolve,reject) => {
@@ -47,6 +63,13 @@ export async function serializeFigure(self : GenomeView) : Promise
valid SVG. Here, we pass all of the raw templates needed for the current figure to angular to compile into
one single SVG that is ready for serialization.
*/
+/**
+ * JIT compiles the entire figure into one SVG, ignoring all precompiled SVGS. Allows DOM updates to interleave execution
+ *
+ * @export
+ * @param {GenomeView} self
+ * @returns {Promise}
+ */
export async function renderSVG(self : GenomeView) : Promise
{
return new Promise((resolve,reject) => {
diff --git a/src/req/renderer/circularGenomeBuilderRenderer/genomeView.ts b/src/req/renderer/circularGenomeBuilderRenderer/genomeView.ts
index 25e125502..70b736063 100644
--- a/src/req/renderer/circularGenomeBuilderRenderer/genomeView.ts
+++ b/src/req/renderer/circularGenomeBuilderRenderer/genomeView.ts
@@ -16,17 +16,51 @@ import {displayFigure} from "./displayFigure";
import {centreFigure} from "./centreFigure";
import {writeLoadingModal} from "./writeLoadingModal";
import {setSelectedContigByUUID} from "./writeContigEditorModal";
+import {reCacheBaseFigure} from "./reCacheBaseFigure";
+import * as tc from "./templateCache";
import {writeSVG,serializeFigure,renderSVG} from "./exportToSVG";
require("angular");
require("@chgibb/angularplasmid");
let app : any = angular.module('myApp',['angularplasmid']);
+/**
+ * Manages the display and behaviour of the figure being edited
+ *
+ * @export
+ * @class GenomeView
+ * @extends {viewMgr.View}
+ * @implements {cf.FigureCanvas}
+ */
export class GenomeView extends viewMgr.View implements cf.FigureCanvas
{
+ /**
+ * The current figure being displayed
+ *
+ * @type {cf.CircularFigure}
+ * @memberof GenomeView
+ */
public genome : cf.CircularFigure;
+ /**
+ * Reconstruct the figure using cached data
+ *
+ * @type {boolean}
+ * @memberof GenomeView
+ */
public firstRender : boolean;
+ /**
+ * Aligns for this figure
+ *
+ * @type {Array}
+ * @memberof GenomeView
+ */
public alignData : Array;
+ /**
+ * Bound Angular scope for genome
+ *
+ * @type {*}
+ * @memberof GenomeView
+ */
public scope : any;
public constructor(name : string,div : string)
{
@@ -35,8 +69,17 @@ export class GenomeView extends viewMgr.View implements cf.FigureCanvas
}
public onMount() : void{}
public onUnMount() : void{}
+ /**
+ * Update the Angular scope for genome
+ *
+ * @param {cf.FigureCanvas} [scope]
+ * @returns {void}
+ * @memberof GenomeView
+ */
public updateScope(scope? : cf.FigureCanvas) : void
{
+ if(!this.genome.isInteractive)
+ return;
if(scope)
this.scope = scope;
this.scope.genome = this.genome;
@@ -51,6 +94,11 @@ export class GenomeView extends viewMgr.View implements cf.FigureCanvas
this.scope.div = this.div;
}
+ /**
+ * Export genome to SVG
+ *
+ * @memberof GenomeView
+ */
public exportSVG()
{
let self = this;
@@ -96,6 +144,14 @@ export class GenomeView extends viewMgr.View implements cf.FigureCanvas
}
);
}
+ /**
+ * Called when a trackMarker is clicked by the user
+ *
+ * @param {*} $event
+ * @param {*} $marker
+ * @param {string} uuid
+ * @memberof GenomeView
+ */
public markerOnClick($event : any,$marker : any,uuid : string) : void
{
let masterView = viewMgr.getViewByName("masterView");
@@ -104,6 +160,11 @@ export class GenomeView extends viewMgr.View implements cf.FigureCanvas
masterView.showModal();
viewMgr.render();
}
+ /**
+ * Called when the name of the figure is clicked by the user
+ *
+ * @memberof GenomeView
+ */
public figureNameOnClick() : void
{
let self = this;
@@ -116,14 +177,20 @@ export class GenomeView extends viewMgr.View implements cf.FigureCanvas
let masterView = viewMgr.getViewByName("masterView");
let genomeView = viewMgr.getViewByName("genomeView",masterView.views);
- genomeView.firstRender = true;
+
//Save changes
- masterView.dataChanged();
+ masterView.saveFigureChanges();
//Re render
+ genomeView.firstRender = true;
viewMgr.render();
}
});
}
+ /**
+ * Should be called when genome.radius changes
+ *
+ * @memberof GenomeView
+ */
public inputRadiusOnChange()
{
this.genome.height = this.genome.radius*10;
@@ -131,6 +198,11 @@ export class GenomeView extends viewMgr.View implements cf.FigureCanvas
//Re center figure
this.postRender();
}
+ /**
+ * Should be called when the track interval changes
+ *
+ * @memberof GenomeView
+ */
public showBPTrackOnChange()
{
let masterView = viewMgr.getViewByName("masterView");
@@ -172,6 +244,11 @@ export class GenomeView extends viewMgr.View implements cf.FigureCanvas
return " ";
return undefined;
}
+ /**
+ * Recenter figure and clean artifacts
+ *
+ * @memberof GenomeView
+ */
public postRender() : void
{
if(this.genome !== undefined)
diff --git a/src/req/renderer/circularGenomeBuilderRenderer/masterView.ts b/src/req/renderer/circularGenomeBuilderRenderer/masterView.ts
index 9813db1fd..5b40d6ca9 100644
--- a/src/req/renderer/circularGenomeBuilderRenderer/masterView.ts
+++ b/src/req/renderer/circularGenomeBuilderRenderer/masterView.ts
@@ -9,7 +9,8 @@ const dialogs = Dialogs();
import {SaveKeyEvent} from "./../../ipcEvents";
import {AtomicOperationIPC} from "./../../atomicOperationsIPC";
import * as viewMgr from "./../viewMgr";
-import {CircularFigure,} from "./../circularFigure";
+import {CircularFigure} from "./../circularFigure";
+import {reCacheBaseFigure} from "./reCacheBaseFigure";
import {Fasta} from "./../../fasta";
import {AlignData} from "./../../alignData";
@@ -20,6 +21,7 @@ import {writeAlignsModal} from "./writeAlignsModal";
import {writeAvailableTracksModal} from "./writeAvailableTracksModal";
import {writeContigEditorModal} from "./writeContigEditorModal";
import {writeContigCreatorModal} from "./writeContigCreatorModal";
+import {writeEditContigsModal} from "./writeEditContigsModal";
import {writeLoadingModal} from "./writeLoadingModal";
@@ -32,6 +34,13 @@ export function addView(arr : Array,div : string)
{
arr.push(new View(div));
}
+/**
+ * Manages the display and the behaviour of the figure editor
+ *
+ * @export
+ * @class View
+ * @extends {viewMgr.View}
+ */
export class View extends viewMgr.View
{
public views : Array;
@@ -42,6 +51,7 @@ export class View extends viewMgr.View
public availableTracksModalOpen : boolean;
public contigEditorModalOpen : boolean;
public contigCreatorModalOpen : boolean;
+ public editContigsModalOpen : boolean;
public loadingModal : boolean;
public constructor(div : string)
{
@@ -53,8 +63,15 @@ export class View extends viewMgr.View
this.availableTracksModalOpen = false;
this.contigEditorModalOpen = false;
this.contigCreatorModalOpen = false;
+ this.editContigsModalOpen = false;
this.loadingModal = false;
}
+ /**
+ * Retrieve all the alignments run for the currently open figure
+ *
+ * @returns {(Array | undefined)}
+ * @memberof View
+ */
public getAlignsForOpenGenome() : Array | undefined
{
let res : Array = new Array();
@@ -72,6 +89,11 @@ export class View extends viewMgr.View
return undefined;
return res;
}
+ /**
+ * Show the modal, with whatever happens to be on it. Bootstrap only allows a single modal
+ *
+ * @memberof View
+ */
public showModal() : void
{
try
@@ -81,6 +103,11 @@ export class View extends viewMgr.View
}
catch(err){}
}
+ /**
+ * Dismiss the modal
+ *
+ * @memberof View
+ */
public dismissModal() : void
{
($(".modal")).modal("hide");
@@ -91,7 +118,14 @@ export class View extends viewMgr.View
this.availableTracksModalOpen = false;
this.contigCreatorModalOpen = false;
this.contigEditorModalOpen = false;
+ this.editContigsModalOpen = false;
}
+ /**
+ * Highlight the currently open figure in the "Figures" dropdown
+ *
+ * @returns {void}
+ * @memberof View
+ */
public setSelectedFigureInDropDown() : void
{
let genomeView = viewMgr.getViewByName("genomeView",this.views);
@@ -109,6 +143,11 @@ export class View extends viewMgr.View
}
}
}
+ /**
+ * Update the textbox in the navbar with the radius of the open figure
+ *
+ * @memberof View
+ */
public setFigureRadiusInInput() : void
{
let genomeView = viewMgr.getViewByName("genomeView",this.views);
@@ -118,6 +157,11 @@ export class View extends viewMgr.View
else
el.value = genomeView.genome.radius.toString();
}
+ /**
+ * Update the textbox in the navbar with the track interval of the open figure
+ *
+ * @memberof View
+ */
public setFigureBPIntervalInput() : void
{
let genomeView = viewMgr.getViewByName("genomeView",this.views);
@@ -127,6 +171,12 @@ export class View extends viewMgr.View
else
el.value = genomeView.genome.circularFigureBPTrackOptions.interval.toString();
}
+ /**
+ * Update the checkbox in the navbar with the interval status of the open figure
+ *
+ * @returns {void}
+ * @memberof View
+ */
public setShowBPIntervalCheckBox() : void
{
let genomeView = viewMgr.getViewByName("genomeView",this.views);
@@ -138,6 +188,11 @@ export class View extends viewMgr.View
else if(genomeView.genome.circularFigureBPTrackOptions.showLabels == 1)
checkbox.checked = true;
}
+ /**
+ * On startup. Apply behaviour to static dropdowns and controls
+ *
+ * @memberof View
+ */
public onMount() : void
{
GenomeView.addView(this.views,"genomeView");
@@ -148,7 +203,7 @@ export class View extends viewMgr.View
let genomeView = viewMgr.getViewByName("genomeView",this.views);
let self = this;
window.onbeforeunload = function(e){
- self.dataChanged();
+ self.saveFigureChanges();
}
document.getElementById("figures").onclick = function(this : HTMLElement,ev : MouseEvent){
for(let i = 0; i != self.fastaInputs.length; ++i)
@@ -160,7 +215,7 @@ export class View extends viewMgr.View
self.fastaInputs[i].uuid,
self.fastaInputs[i].contigs
));
- self.dataChanged();
+ self.saveFigureChanges();
genomeView.genome = self.circularFigures[self.circularFigures.length - 1];
genomeView.firstRender = true;
viewMgr.render();
@@ -180,6 +235,34 @@ export class View extends viewMgr.View
}
}
}
+ document.getElementById("figureOptions").onclick = function(this : HTMLElement,ev : MouseEvent){
+ if((event.target).id == `${genomeView.genome.uuid}ToggleInteractivity`)
+ {
+ genomeView.genome.isInteractive = !genomeView.genome.isInteractive;
+ self.saveFigureChanges();
+ genomeView.firstRender = true;
+ viewMgr.render();
+ }
+ if((event.target).id == `${genomeView.genome.uuid}ToggleContigNames`)
+ {
+ genomeView.genome.showContigNames = !genomeView.genome.showContigNames;
+ self.saveFigureChanges();
+ genomeView.firstRender = true;
+ viewMgr.render();
+ }
+ if((event.target).id == `EditFigureName`)
+ {
+ genomeView.figureNameOnClick();
+ }
+ if((event.target).id ==`EditContigs`)
+ {
+ self.editContigsModalOpen = true;
+ writeEditContigsModal();
+ self.showModal();
+
+ }
+ }
+
document.getElementById("showBPIntervalCheckBox").onclick = function(this : HTMLElement,ev : MouseEvent){
document.getElementById("updateNavBarButton").click();
}
@@ -237,6 +320,8 @@ export class View extends viewMgr.View
document.getElementById("updateNavBarButton").onclick = function(this : HTMLElement,ev : MouseEvent){
let radiusHasChanged = false;
+ let trackIntervalChanged = false;
+ let showIntervalChanged = false;
if(!genomeView.genome)
return;
let radius = parseInt((document.getElementById("figureRadiusInput")).value);
@@ -249,22 +334,29 @@ export class View extends viewMgr.View
let trackInterval = parseInt((document.getElementById("figureBPIntervalInput")).value);
if(trackInterval)
+ {
+ if(trackInterval != genomeView.genome.circularFigureBPTrackOptions.interval)
+ trackIntervalChanged = true;
genomeView.genome.circularFigureBPTrackOptions.interval = trackInterval;
+ }
let showInterval = ((document.getElementById("showBPIntervalCheckBox")).checked);
if(showInterval !== undefined)
{
+ if((showInterval === true && genomeView.genome.circularFigureBPTrackOptions.showLabels == 0) || (showInterval === false && genomeView.genome.circularFigureBPTrackOptions.showLabels == 1))
+ showIntervalChanged = true;
if(showInterval === true)
genomeView.genome.circularFigureBPTrackOptions.showLabels = 1;
else
genomeView.genome.circularFigureBPTrackOptions.showLabels = 0;
}
- if(radiusHasChanged)
+ if(radiusHasChanged || trackIntervalChanged || showIntervalChanged)
{
- tc.triggerReCompileForAllTracks(genomeView.genome);
+ genomeView.firstRender = true;
+ tc.triggerReCompileForWholeFigure(genomeView.genome);
+ self.saveFigureChanges();
}
genomeView.updateScope();
- self.dataChanged();
viewMgr.render();
}
@@ -280,8 +372,15 @@ export class View extends viewMgr.View
this.views[i].onUnMount();
}
}
+ /**
+ * Update dynamic dropdowns and controls. Call render on GenomeView
+ *
+ * @returns {string}
+ * @memberof View
+ */
public renderView() : string
{
+ let genomeView = viewMgr.getViewByName("genomeView",this.views);
let res = "";
for(let i = 0; i != this.fastaInputs.length; ++i)
{
@@ -306,6 +405,17 @@ export class View extends viewMgr.View
}
}
document.getElementById("figures").innerHTML = res;
+
+ res = ""
+ if(genomeView.genome)
+ {
+ res += `${genomeView.genome.isInteractive ? "Disable Interactivity" : "Enable Interactivity"}`;
+ res += `${genomeView.genome.showContigNames ? "Don't Show Contig Names" : "Show Contig Names"}`;
+ res += `Edit Figure Name`;
+ res += `Edit Contigs`;
+ }
+ document.getElementById("figureOptions").innerHTML = res;
+
for(let i = 0; i != this.views.length; ++i)
{
this.views[i].render();
@@ -336,6 +446,11 @@ export class View extends viewMgr.View
this.setFigureBPIntervalInput();
this.setShowBPIntervalCheckBox();
}
+ /**
+ * Save circular figures for the open project
+ *
+ * @memberof View
+ */
public dataChanged() : void
{
ipc.send(
@@ -348,6 +463,21 @@ export class View extends viewMgr.View
}
);
}
+ /**
+ * Save changes to the open figure. Resets SVG caches to force figure updating
+ *
+ * @memberof View
+ */
+ public saveFigureChanges() : void
+ {
+ let genomeView = viewMgr.getViewByName("genomeView",this.views);
+ this.dataChanged();
+ if(genomeView.genome)
+ {
+ tc.resetCaches();
+ reCacheBaseFigure(genomeView.genome);
+ }
+ }
public divClickEvents(event : JQueryEventObject) : void
{
let genomeView = viewMgr.getViewByName("genomeView",this.views);
diff --git a/src/req/renderer/circularGenomeBuilderRenderer/reCacheBaseFigure.ts b/src/req/renderer/circularGenomeBuilderRenderer/reCacheBaseFigure.ts
index bec62b53d..a0936fd00 100644
--- a/src/req/renderer/circularGenomeBuilderRenderer/reCacheBaseFigure.ts
+++ b/src/req/renderer/circularGenomeBuilderRenderer/reCacheBaseFigure.ts
@@ -1,18 +1,12 @@
import * as cf from "./../circularFigure";
-export async function reCacheBaseFigure(figure : cf.CircularFigure) : Promise
+/**
+ * Rerenders figure's template cache, resets SVG cache
+ *
+ * @export
+ * @param {cf.CircularFigure} figure
+ */
+export function reCacheBaseFigure(figure : cf.CircularFigure) : void
{
- return new Promise((resolve,reject) => {
- (async function() : Promise {
- return new Promise((resolve,reject) => {
- setImmediate(function(){
- setImmediate(function(){
- cf.cacheBaseFigure(figure);
- resolve();
- });
- });
- });
- })().then(() => {
- resolve();
- });
- });
+ cf.cacheBaseFigure(figure);
+ cf.deleteBaseFigureSVGFromCache(figure);
}
\ No newline at end of file
diff --git a/src/req/renderer/circularGenomeBuilderRenderer/templateCache.ts b/src/req/renderer/circularGenomeBuilderRenderer/templateCache.ts
index 516d45162..c1a86fa1e 100644
--- a/src/req/renderer/circularGenomeBuilderRenderer/templateCache.ts
+++ b/src/req/renderer/circularGenomeBuilderRenderer/templateCache.ts
@@ -37,17 +37,41 @@ class CachedSNPTrackSVG
}
}
-let baseFigureTemplateString = "";
+export let baseFigureSVG : string = undefined;
let coverageTrackCache = new Array();;
let SNPTrackCache = new Array();
+/**
+ * Clear the in-memory cache of the SVG for the base figure
+ *
+ * @export
+ */
+export function resetBaseFigureSVG() : void
+{
+ baseFigureSVG = undefined;
+}
+
+/**
+ * Clear all in-memory caches
+ *
+ * @export
+ */
export function resetCaches() : void
{
coverageTrackCache = new Array();
SNPTrackCache = new Array();
+ baseFigureSVG = undefined
}
+/**
+ * Update caches for newFigure with new data (if changes are detected).
+ * Will reset and rebuild caches if this function is called with a figure
+ * different from the one used the last time it was called
+ *
+ * @export
+ * @param {cf.CircularFigure} newFigure
+ */
export function refreshCache(newFigure : cf.CircularFigure) : void
{
if(!figure || newFigure.uuid != figure.uuid)
@@ -55,6 +79,28 @@ export function refreshCache(newFigure : cf.CircularFigure) : void
resetCaches();
figure = newFigure;
}
+ console.log(newFigure);
+ if(!newFigure.isInteractive)
+ {
+ if(!baseFigureSVG)
+ {
+ try
+ {
+ baseFigureSVG = cf.getBaseFigureSVGFromCache(figure);
+ }
+ catch(err)
+ {
+ ipc.send(
+ "runOperation",
+ {
+ opName : "compileTemplates",
+ figure : newFigure,
+ compileBase : true
+ }
+ );
+ }
+ }
+ }
//load tracks which had not been loaded previously
let found = false;
@@ -123,24 +169,16 @@ export function refreshCache(newFigure : cf.CircularFigure) : void
}
}
}
-
- /*for(let i = 0; i != newFigure.renderedSNPTracks.length; ++i)
- {
- found = false;
- for(let k = 0; k != SNPTrackCache.length; ++k)
- {
- if(newFigure.renderedSNPTracks[i].uuid == SNPTrackCache[k].trackRecord.uuid)
- {
- found = true;
- break;
- }
- }
- if(!found)
- SNPTrackCache.push(new CachedSNPTrackSVG(newFigure.renderedSNPTracks[i]));
- }*/
}
-//retrieve loaded tracks
+
+/**
+ * Retrieve an (already loaded) SVG for the specified coverage track
+ *
+ * @export
+ * @param {cf.RenderedCoverageTrackRecord} trackRecord
+ * @returns {string}
+ */
export function getCachedCoverageTrack(trackRecord : cf.RenderedCoverageTrackRecord) : string
{
for(let i = 0; i != coverageTrackCache.length; ++i)
@@ -151,6 +189,13 @@ export function getCachedCoverageTrack(trackRecord : cf.RenderedCoverageTrackRec
throw new Error(`Could not fetch ${trackRecord.uuid} from cache`);
}
+/**
+ * Retrieve an (already loaded) SVG for the specified SNP track
+ *
+ * @export
+ * @param {cf.RenderedSNPTrackRecord} trackRecord
+ * @returns {string}
+ */
export function getCachedSNPTrack(trackRecord : cf.RenderedSNPTrackRecord) : string
{
for(let i = 0; i != SNPTrackCache.length; ++i)
@@ -161,6 +206,13 @@ export function getCachedSNPTrack(trackRecord : cf.RenderedSNPTrackRecord) : str
throw new Error(`Could not fetch ${trackRecord.uuid} from cache`);
}
+/**
+ * Deletes the track specified by uuid from the in-memory cache
+ *
+ * @export
+ * @param {string} uuid
+ * @returns {void}
+ */
export function removeTrack(uuid : string) : void
{
for(let i = 0; i != coverageTrackCache.length; ++i)
@@ -183,10 +235,28 @@ export function removeTrack(uuid : string) : void
}
}
-export function triggerReCompileForAllTracks(newFigure : cf.CircularFigure) : void
+/**
+ * Triggers a compile for each compononent of newFigure (including non-visible data tracks) regardless of cache status.
+ * Will only trigger a compile for the base figure if the figure is non-interactive
+ * @export
+ * @param {cf.CircularFigure} newFigure
+ * @returns {void}
+ */
+export function triggerReCompileForWholeFigure(newFigure : cf.CircularFigure) : void
{
if(!figure)
return;
+ if(!figure.isInteractive)
+ {
+ ipc.send(
+ "runOperation",
+ {
+ opName : "compileTemplates",
+ figure : newFigure,
+ compileBase : true
+ }
+ );
+ }
for(let i = 0; i != coverageTrackCache.length; ++i)
{
ipc.send(
diff --git a/src/req/renderer/circularGenomeBuilderRenderer/writeAlignsModal.ts b/src/req/renderer/circularGenomeBuilderRenderer/writeAlignsModal.ts
index de493ad78..c750cac2e 100644
--- a/src/req/renderer/circularGenomeBuilderRenderer/writeAlignsModal.ts
+++ b/src/req/renderer/circularGenomeBuilderRenderer/writeAlignsModal.ts
@@ -3,6 +3,11 @@ import * as masterView from "./masterView";
import * as genomeView from "./genomeView";
import {writeAvailableTracksModal,setSelectedAlign} from "./writeAvailableTracksModal";
import {getReadable} from "./../../getAppPath";
+/**
+ * Writes the alignment selection menu into the modal
+ *
+ * @export
+ */
export function writeAlignsModal() : void
{
let masterView = viewMgr.getViewByName("masterView");
diff --git a/src/req/renderer/circularGenomeBuilderRenderer/writeAvailableTracksModal.ts b/src/req/renderer/circularGenomeBuilderRenderer/writeAvailableTracksModal.ts
index 557bb8884..fc4e15b3a 100644
--- a/src/req/renderer/circularGenomeBuilderRenderer/writeAvailableTracksModal.ts
+++ b/src/req/renderer/circularGenomeBuilderRenderer/writeAvailableTracksModal.ts
@@ -10,10 +10,21 @@ import {getReadable} from "./../../getAppPath";
require("@claviska/jquery-minicolors");
let selectedAlign : AlignData;
+/**
+ * Set the selected alignment to view track options for
+ *
+ * @export
+ * @param {AlignData} align
+ */
export function setSelectedAlign(align : AlignData) : void
{
selectedAlign = align;
}
+/**
+ * Writes the data track selection menu into the modal
+ *
+ * @export
+ */
export function writeAvailableTracksModal() : void
{
let masterView = viewMgr.getViewByName("masterView");
diff --git a/src/req/renderer/circularGenomeBuilderRenderer/writeContigCreatorModal.ts b/src/req/renderer/circularGenomeBuilderRenderer/writeContigCreatorModal.ts
index cd7435bf6..c6990d243 100644
--- a/src/req/renderer/circularGenomeBuilderRenderer/writeContigCreatorModal.ts
+++ b/src/req/renderer/circularGenomeBuilderRenderer/writeContigCreatorModal.ts
@@ -4,6 +4,11 @@ import * as genomeView from "./genomeView";
import * as cf from "./../circularFigure";
import {reCacheBaseFigure} from "./reCacheBaseFigure";
import {writeLoadingModal} from "./writeLoadingModal";
+/**
+ * Writes the contig creation menu into the modal
+ *
+ * @export
+ */
export function writeContigCreatorModal() : void
{
let masterView = viewMgr.getViewByName("masterView");
@@ -61,12 +66,11 @@ export function writeContigCreatorModal() : void
masterView.loadingModal = true;
writeLoadingModal();
setTimeout(function(){
- reCacheBaseFigure(genomeView.genome).then(() => {
- masterView.loadingModal = false;
- masterView.dismissModal();
- genomeView.firstRender = true;
- viewMgr.render();
- });
+ reCacheBaseFigure(genomeView.genome);
+ masterView.loadingModal = false;
+ masterView.dismissModal();
+ genomeView.firstRender = true;
+ viewMgr.render();
},10);
viewMgr.render();
diff --git a/src/req/renderer/circularGenomeBuilderRenderer/writeContigEditorModal.ts b/src/req/renderer/circularGenomeBuilderRenderer/writeContigEditorModal.ts
index 9d81a9f0a..3f9f6a6b0 100644
--- a/src/req/renderer/circularGenomeBuilderRenderer/writeContigEditorModal.ts
+++ b/src/req/renderer/circularGenomeBuilderRenderer/writeContigEditorModal.ts
@@ -9,6 +9,13 @@ import {reCacheBaseFigure} from "./reCacheBaseFigure";
import {writeLoadingModal} from "./writeLoadingModal";
let contig : cf.Contig;
let editedAlias = "";
+/**
+ * Set the contig to edit by uuid
+ *
+ * @export
+ * @param {string} uuid
+ * @returns {void}
+ */
export function setSelectedContigByUUID(uuid : string) : void
{
let masterView = viewMgr.getViewByName("masterView");
@@ -35,6 +42,11 @@ export function setSelectedContigByUUID(uuid : string) : void
}
}
+/**
+ * Writes the contig editor menu into the modal
+ *
+ * @export
+ */
export function writeContigEditorModal() : void
{
if(!contig)
@@ -105,21 +117,8 @@ export function writeContigEditorModal() : void
}
masterView.contigEditorModalOpen = false;
masterView.dismissModal();
-
- masterView.dataChanged();
-
- masterView.loadingModal = true;
- writeLoadingModal();
-
- setTimeout(function(){
- reCacheBaseFigure(genomeView.genome).then(() => {
- masterView.loadingModal = false;
- masterView.dismissModal();
- genomeView.firstRender = true;
- viewMgr.render();
- });
- },10);
-
+ genomeView.firstRender = true;
+ masterView.saveFigureChanges();
viewMgr.render();
}
diff --git a/src/req/renderer/circularGenomeBuilderRenderer/writeEditContigsModal.ts b/src/req/renderer/circularGenomeBuilderRenderer/writeEditContigsModal.ts
new file mode 100644
index 000000000..b29fb6dc6
--- /dev/null
+++ b/src/req/renderer/circularGenomeBuilderRenderer/writeEditContigsModal.ts
@@ -0,0 +1,69 @@
+import * as viewMgr from "./../viewMgr";
+import * as masterView from "./masterView";
+import * as genomeView from "./genomeView";
+
+/**
+ * Writes the list of contigs to edit into the modal
+ *
+ * @export
+ */
+export function writeEditContigsModal() : void
+{
+ let masterView = viewMgr.getViewByName("masterView");
+ let genomeView = viewMgr.getViewByName("genomeView",masterView.views);
+
+ let title = `Select Contig to Edit`;
+
+ let body = ``;
+ if(!genomeView.genome)
+ {
+ body = `
+ You must select a figure to edit before you can view it's contigs to edit.
+ `;
+ }
+ else if(genomeView.genome)
+ {
+ body += `Custom Contigs
`;
+ if(genomeView.genome.customContigs.length > 0)
+ {
+ for(let i = 0; i != genomeView.genome.customContigs.length; ++i)
+ {
+ body += `${genomeView.genome.customContigs[i].name}
`;
+ }
+ }
+ else
+ {
+ body += `No custom contigs
`;
+ }
+
+ body += `Reference Contigs
`;
+
+ for(let i = 0; i != genomeView.genome.contigs.length; ++i)
+ {
+ body += `${genomeView.genome.contigs[i].name}
`;
+ }
+ }
+
+ let footer = ``;
+
+ document.getElementById("modalTitle").innerHTML = title;
+ document.getElementById("modalBody").innerHTML = body;
+ document.getElementById("modalFooter").innerHTML = footer;
+
+ if(genomeView.genome.customContigs.length > 0)
+ {
+ for(let i = 0; i != genomeView.genome.customContigs.length; ++i)
+ {
+ document.getElementById(`${genomeView.genome.customContigs[i].uuid}Edit`).onclick = function(this : HTMLElement,ev : MouseEvent){
+ genomeView.markerOnClick(undefined,undefined,genomeView.genome.customContigs[i].uuid);
+ }
+ }
+ }
+
+ for(let i = 0; i != genomeView.genome.contigs.length; ++i)
+ {
+ document.getElementById(`${genomeView.genome.contigs[i].uuid}Edit`).onclick = function(this : HTMLElement,ev : MouseEvent){
+ genomeView.markerOnClick(undefined,undefined,genomeView.genome.contigs[i].uuid);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/req/renderer/circularGenomeBuilderRenderer/writeLoadingModal.ts b/src/req/renderer/circularGenomeBuilderRenderer/writeLoadingModal.ts
index dae01ae8a..d92772632 100644
--- a/src/req/renderer/circularGenomeBuilderRenderer/writeLoadingModal.ts
+++ b/src/req/renderer/circularGenomeBuilderRenderer/writeLoadingModal.ts
@@ -1,3 +1,8 @@
+/**
+ * Writes a generic loading message into the modal. May be modified by #loadingText after being written
+ *
+ * @export
+ */
export function writeLoadingModal() : void
{
let title = `Loading...`;