diff --git a/src/app/core/net/api/RequestManager.ts b/src/app/core/net/api/RequestManager.ts index e11a72e..9311676 100644 --- a/src/app/core/net/api/RequestManager.ts +++ b/src/app/core/net/api/RequestManager.ts @@ -81,6 +81,7 @@ import { GetConversionJobRequest, GetConversionToolchainStatusRequest, SetDotplotAlignerPreferenceRequest, + ConvertAssemblyToAgpRequest, StopConversionJobRequest, RenameContigRequest, RenameScaffoldRequest, @@ -882,6 +883,16 @@ class RequestManager { return this.sendRequest(request).then((response) => response.data); } + public async convertAssemblyToAgp(options: { + filename: string; + outputFilename?: string; + overwrite?: boolean; + }): Promise<{ status: string; inputFilename: string; outputFilename: string }> { + return this.sendRequest(new ConvertAssemblyToAgpRequest(options)).then( + (response) => response.data + ); + } + public async startBatchConversionJobs( request: StartBatchConversionJobsRequest ): Promise<{ status: string; groupId: string; jobIds: string[] }> { diff --git a/src/app/core/net/api/request.ts b/src/app/core/net/api/request.ts index 82b8366..e71d6c4 100644 --- a/src/app/core/net/api/request.ts +++ b/src/app/core/net/api/request.ts @@ -214,6 +214,18 @@ class StartBatchConversionJobsRequest implements HiCTAPIRequest { ) {} } +class ConvertAssemblyToAgpRequest implements HiCTAPIRequest { + requestPath = "/convert/assembly-to-agp"; + + public constructor( + public readonly options: { + readonly filename: string; + readonly outputFilename?: string; + readonly overwrite?: boolean; + } + ) {} +} + class ListConversionJobsRequest implements HiCTAPIRequest { requestPath = "/convert/jobs/list"; } @@ -670,6 +682,7 @@ export { DropAllCachesRequest, StartConversionJobRequest, StartBatchConversionJobsRequest, + ConvertAssemblyToAgpRequest, ListConversionJobsRequest, GetConversionJobRequest, StopConversionJobRequest, diff --git a/src/app/core/net/dto/requestDTO.ts b/src/app/core/net/dto/requestDTO.ts index 677b62d..03c85e1 100644 --- a/src/app/core/net/dto/requestDTO.ts +++ b/src/app/core/net/dto/requestDTO.ts @@ -74,6 +74,7 @@ import { StartBatchConversionJobsRequest, StartDotplotJobsRequest, SetDotplotAlignerPreferenceRequest, + ConvertAssemblyToAgpRequest, ListDotplotJobsRequest, ListConversionJobsRequest, GetConversionJobRequest, @@ -129,6 +130,10 @@ abstract class HiCTAPIRequestDTO< return new StartBatchConversionJobsRequestDTO( entity as StartBatchConversionJobsRequest ); + case entity instanceof ConvertAssemblyToAgpRequest: + return new ConvertAssemblyToAgpRequestDTO( + entity as ConvertAssemblyToAgpRequest + ); case entity instanceof StartDotplotJobsRequest: return new StartDotplotJobsRequestDTO( entity as StartDotplotJobsRequest @@ -515,6 +520,16 @@ class StartBatchConversionJobsRequestDTO extends HiCTAPIRequestDTO { + toDTO(): Record { + return { + filename: this.entity.options.filename, + outputFilename: this.entity.options.outputFilename, + overwrite: this.entity.options.overwrite, + }; + } +} + class StartDotplotJobsRequestDTO extends HiCTAPIRequestDTO { toDTO(): Record { return { diff --git a/src/app/ui/components/upper_ribbon/CoolerConverter.vue b/src/app/ui/components/upper_ribbon/CoolerConverter.vue index 0db5899..7551495 100644 --- a/src/app/ui/components/upper_ribbon/CoolerConverter.vue +++ b/src/app/ui/components/upper_ribbon/CoolerConverter.vue @@ -285,7 +285,7 @@ const batchSelection: Ref> = ref(new Set()); const batchAssemblyFilename: Ref = ref(""); const assemblySelectorOpen: Ref = ref(false); const batchParallelJobs: Ref = ref(2); -const batchParallelism: Ref = ref(4); +const batchParallelism: Ref = ref(Math.max(1, navigator.hardwareConcurrency || 4)); const batchJobIds: Ref = ref([]); const batchStatusMap: Ref> = ref(new Map()); const batchProgressMap: Ref> = ref(new Map()); diff --git a/src/app/ui/components/upper_ribbon/DotplotGenerator.vue b/src/app/ui/components/upper_ribbon/DotplotGenerator.vue index a370122..c053850 100644 --- a/src/app/ui/components/upper_ribbon/DotplotGenerator.vue +++ b/src/app/ui/components/upper_ribbon/DotplotGenerator.vue @@ -293,8 +293,8 @@ const sampleBp = ref(250); const minAlignmentLength = ref(50); const extraMinimap2Args = ref(""); const alignerPreference = ref("auto"); -const alignmentThreads = ref(Math.max(1, Math.min(12, navigator.hardwareConcurrency || 4))); -const conversionThreads = ref(Math.max(1, Math.min(12, navigator.hardwareConcurrency || 4))); +const alignmentThreads = ref(Math.max(1, navigator.hardwareConcurrency || 4)); +const conversionThreads = ref(Math.max(1, navigator.hardwareConcurrency || 4)); const overwrite = ref(false); const fastaEntries = computed(() => diff --git a/src/app/ui/components/upper_ribbon/FileWizardModal.vue b/src/app/ui/components/upper_ribbon/FileWizardModal.vue index 3355940..4263e82 100644 --- a/src/app/ui/components/upper_ribbon/FileWizardModal.vue +++ b/src/app/ui/components/upper_ribbon/FileWizardModal.vue @@ -312,6 +312,13 @@
+
.agp is loaded after opening. .assembly is passed to .hic conversion; for already converted @@ -327,6 +334,13 @@
+
@@ -1279,6 +1293,34 @@ const onSelectorPicked = async (filename: string): Promise => { } }; +const convertAssemblySelectionToAgp = async ( + source: "primary" | "secondary" +): Promise => { + const filename = source === "primary" ? primaryAgp.value : secondaryAgp.value; + if (!filename.toLowerCase().endsWith(".assembly")) { + return; + } + const outputFilename = filename.replace(/\.assembly$/i, ".agp"); + if ( + !window.confirm( + `Convert ${filename} to ${outputFilename}? An existing AGP copy will be overwritten.` + ) + ) { + return; + } + const result = await props.networkManager.requestManager.convertAssemblyToAgp({ + filename, + outputFilename, + overwrite: true, + }); + if (source === "primary") { + primaryAgp.value = result.outputFilename; + } else { + secondaryAgp.value = result.outputFilename; + } + toast.success(`Created ${result.outputFilename}`); +}; + const sleep = (ms: number): Promise => new Promise((resolve) => window.setTimeout(resolve, ms));