Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"recommendations": [
"oxc.oxc-vscode"
]
}
40 changes: 40 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
{
"editor.defaultFormatter": "oxc.oxc-vscode",
"[typescript]": {
"editor.defaultFormatter": "oxc.oxc-vscode",
"editor.tabSize": 2
},
"[vue]": {
"editor.defaultFormatter": "oxc.oxc-vscode",
"editor.tabSize": 2
},
"[javascript]": {
"editor.defaultFormatter": "oxc.oxc-vscode",
"editor.tabSize": 2
},
"[css]": {
"editor.defaultFormatter": "oxc.oxc-vscode",
"editor.tabSize": 2
},
"[scss]": {
"editor.defaultFormatter": "oxc.oxc-vscode",
"editor.tabSize": 2
},
"[html]": {
"editor.defaultFormatter": "oxc.oxc-vscode",
"editor.tabSize": 2
},
"[yaml]": {
"editor.defaultFormatter": "oxc.oxc-vscode",
"editor.tabSize": 2
},
"[markdown]": {
"editor.defaultFormatter": "oxc.oxc-vscode",
"editor.tabSize": 2
},
"[json]": {
"editor.defaultFormatter": "oxc.oxc-vscode",
"editor.tabSize": 2
},
"typescript.tsdk": "./node_modules/typescript/lib"
}
3 changes: 3 additions & 0 deletions model/.oxfmtrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"ignorePatterns": ["dist", "CHANGELOG.md"]
}
3 changes: 3 additions & 0 deletions model/.oxlintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"extends": ["node_modules/@milaboratories/ts-builder/dist/configs/oxlint-block-model.json"]
}
4 changes: 0 additions & 4 deletions model/eslint.config.mjs

This file was deleted.

12 changes: 6 additions & 6 deletions model/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,17 @@
"types": "dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"sources": "./src/index.ts",
"import": "./dist/index.js",
"types": "./dist/index.d.ts"
"import": "./dist/index.js"
},
"./dist/*": "./dist/*"
},
"scripts": {
"lint": "eslint .",
"fmt": "ts-builder format",
"check": "ts-builder check --target block-model",
"watch": "ts-builder build --target block-model --watch",
"build": "ts-builder build --target block-model && block-tools build-model",
"type-check": "ts-builder type-check --target block-model",
"test": "vitest --run --passWithNoTests",
"do-pack": "rm -f *.tgz && pnpm pack && mv *.tgz package.tgz"
},
Expand All @@ -31,7 +31,7 @@
"@platforma-sdk/block-tools": "catalog:",
"@platforma-sdk/eslint-config": "catalog:",
"eslint": "catalog:",
"vitest": "catalog:",
"typescript": "catalog:"
"typescript": "catalog:",
"vitest": "catalog:"
}
}
195 changes: 106 additions & 89 deletions model/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import type { ImportFileHandle, InferHrefType, PlDataTableStateV2, PlRef } from '@platforma-sdk/model';
import type {
ImportFileHandle,
InferHrefType,
PlDataTableStateV2,
PlRef,
} from "@platforma-sdk/model";
import {
BlockModel,
createPlDataTableStateV2,
createPlDataTableV2,
isPColumnSpec,
parseResourceMap,
type InferOutputsType,
} from '@platforma-sdk/model';
import { ProgressPrefix } from './progress';
} from "@platforma-sdk/model";
import { ProgressPrefix } from "./progress";

export type CloneClusteringMode = 'relaxed' | 'default' | 'off';
export type CloneClusteringMode = "relaxed" | "default" | "off";
export type AssemblingFeature = string;
export type StopCodonType = 'amber' | 'ochre' | 'opal';
export type ReferenceInputMode = 'fastaFile' | 'fastaSequence' | 'libraryFile' | 'buildLibrary';
export type StopCodonType = "amber" | "ochre" | "opal";
export type ReferenceInputMode = "fastaFile" | "fastaSequence" | "libraryFile" | "buildLibrary";

export interface VAnchorPoints {
fr1Begin: number;
Expand Down Expand Up @@ -85,101 +90,105 @@ export interface BlockArgsValid extends BlockArgs {
librarySequence: string;
}

export const platforma = BlockModel.create('Heavy')
export const platforma = BlockModel.create("Heavy")

.withArgs<BlockArgs>({
defaultBlockLabel: '',
customBlockLabel: '',
chains: 'IGHeavy',
cloneClusteringMode: 'relaxed',
tagPattern: '',
assemblingFeature: 'VDJRegion',
defaultBlockLabel: "",
customBlockLabel: "",
chains: "IGHeavy",
cloneClusteringMode: "relaxed",
tagPattern: "",
assemblingFeature: "VDJRegion",
imputeGermline: false,
})
.withUiState<UiState>({
referenceInputMode: 'fastaSequence',
referenceInputMode: "fastaSequence",
tableState: createPlDataTableStateV2(),
})

.output('qc', (ctx) => {
const acc = ctx.outputs?.resolve('qc');
.output("qc", (ctx) => {
const acc = ctx.outputs?.resolve("qc");
if (!acc || !acc.getInputsLocked()) return undefined;
return parseResourceMap(acc, (acc) => acc.getFileHandle(), true);
})

.output('reports', (ctx) =>
parseResourceMap(
ctx.outputs?.resolve('reports'),
(acc) => acc.getFileHandle(),
false,
),
.output("reports", (ctx) =>
parseResourceMap(ctx.outputs?.resolve("reports"), (acc) => acc.getFileHandle(), false),
)

.output('logs', (ctx) => {
.output("logs", (ctx) => {
return ctx.outputs !== undefined
? parseResourceMap(
ctx.outputs?.resolve('logs'),
(acc) => acc.getLogHandle(),
false,
)
? parseResourceMap(ctx.outputs?.resolve("logs"), (acc) => acc.getLogHandle(), false)
: undefined;
})

.output('progress', (ctx) => {
.output("progress", (ctx) => {
return ctx.outputs !== undefined
? parseResourceMap(
ctx.outputs?.resolve('logs'),
ctx.outputs?.resolve("logs"),
(acc) => acc.getProgressLog(ProgressPrefix),
false,
)
: undefined;
})

.output('referenceLibrary', (ctx) => {
.output("referenceLibrary", (ctx) => {
return ctx.outputs !== undefined
? ctx.outputs?.resolve({ field: 'referenceLibrary', assertFieldType: 'Input', allowPermanentAbsence: true })?.getRemoteFileHandle()
? ctx.outputs
?.resolve({
field: "referenceLibrary",
assertFieldType: "Input",
allowPermanentAbsence: true,
})
?.getRemoteFileHandle()
: undefined;
})

.output('debugOutput', (ctx) => {
.output("debugOutput", (ctx) => {
return ctx.outputs !== undefined
? ctx.outputs?.resolve({ field: 'debugOutput', assertFieldType: 'Input', allowPermanentAbsence: true })?.getLogHandle()
? ctx.outputs
?.resolve({ field: "debugOutput", assertFieldType: "Input", allowPermanentAbsence: true })
?.getLogHandle()
: undefined;
})

.output('started', (ctx) => ctx.outputs !== undefined)
.output("started", (ctx) => ctx.outputs !== undefined)

.output('done', (ctx) => {
.output("done", (ctx) => {
return ctx.outputs !== undefined
? parseResourceMap(
ctx.outputs?.resolve('clns'),
(_acc) => true,
false,
).data.map((e) => e.key[0] as string)
? parseResourceMap(ctx.outputs?.resolve("clns"), (_acc) => true, false).data.map(
(e) => e.key[0] as string,
)
: undefined;
})

.output('prerunLibrary', (ctx) =>
ctx.prerun?.resolve({ field: 'referenceLibrary', assertFieldType: 'Input', allowPermanentAbsence: true })?.getFileHandle(),
.output("prerunLibrary", (ctx) =>
ctx.prerun
?.resolve({
field: "referenceLibrary",
assertFieldType: "Input",
allowPermanentAbsence: true,
})
?.getFileHandle(),
)

.retentiveOutput('inputOptions', (ctx) => {
.retentiveOutput("inputOptions", (ctx) => {
return ctx.resultPool.getOptions((v) => {
if (!isPColumnSpec(v)) return false;
const domain = v.domain;
return (
v.name === 'pl7.app/sequencing/data'
&& (v.valueType as string) === 'File'
&& domain !== undefined
&& (domain['pl7.app/fileExtension'] === 'fasta'
|| domain['pl7.app/fileExtension'] === 'fasta.gz'
|| domain['pl7.app/fileExtension'] === 'fastq'
|| domain['pl7.app/fileExtension'] === 'fastq.gz')
v.name === "pl7.app/sequencing/data" &&
(v.valueType as string) === "File" &&
domain !== undefined &&
(domain["pl7.app/fileExtension"] === "fasta" ||
domain["pl7.app/fileExtension"] === "fasta.gz" ||
domain["pl7.app/fileExtension"] === "fastq" ||
domain["pl7.app/fileExtension"] === "fastq.gz")
);
});
})

.output('sampleLabels', (ctx): Record<string, string> | undefined => {
.output("sampleLabels", (ctx): Record<string, string> | undefined => {
const inputRef = ctx.args.datasetRef;
if (inputRef === undefined) return undefined;

Expand All @@ -189,71 +198,79 @@ export const platforma = BlockModel.create('Heavy')
return ctx.resultPool.findLabelsForColumnAxis(spec, 0);
})

.output('rawTsvs', (ctx) => {
if (ctx.outputs === undefined)
return undefined;
const pCols = ctx.outputs?.resolve('clonotypeTables')?.getPColumns();
.output("rawTsvs", (ctx) => {
if (ctx.outputs === undefined) return undefined;
const pCols = ctx.outputs?.resolve("clonotypeTables")?.getPColumns();
if (pCols === undefined) {
return undefined;
}
return pCols.map((pCol) => {
return {
...pCol,
id: (JSON.parse(pCol.id) as { name: string }).name,
data: parseResourceMap(pCol.data, (acc) => acc.getRemoteFileHandle(), false),
};
}).filter((pCol) => pCol.data.isComplete).map((pCol) => {
return {
...pCol,
data: pCol.data.data,
};
});
return pCols
.map((pCol) => {
return {
...pCol,
id: (JSON.parse(pCol.id) as { name: string }).name,
data: parseResourceMap(pCol.data, (acc) => acc.getRemoteFileHandle(), false),
};
})
.filter((pCol) => pCol.data.isComplete)
.map((pCol) => {
return {
...pCol,
data: pCol.data.data,
};
});
})

.outputWithStatus('pt', (ctx) => {
const pCols = ctx.outputs?.resolve({ field: 'qcReportTable', assertFieldType: 'Input', allowPermanentAbsence: true })?.getPColumns();
.outputWithStatus("pt", (ctx) => {
const pCols = ctx.outputs
?.resolve({ field: "qcReportTable", assertFieldType: "Input", allowPermanentAbsence: true })
?.getPColumns();
if (pCols === undefined) {
return undefined;
}
return createPlDataTableV2(
ctx,
pCols,
ctx.uiState.tableState,
);
return createPlDataTableV2(ctx, pCols, ctx.uiState.tableState);
})

.sections((_ctx) => {
return [
{ type: 'link', href: '/', label: 'Main' },
{ type: 'link', href: '/qc-report-table', label: 'QC Report Table' },
{ type: "link", href: "/", label: "Main" },
{ type: "link", href: "/qc-report-table", label: "QC Report Table" },
];
})

.argsValid((ctx) => {
const mode = ctx.uiState.referenceInputMode ?? 'fastaSequence';
const mode = ctx.uiState.referenceInputMode ?? "fastaSequence";
const hasDataset = ctx.args.datasetRef !== undefined;
if (mode === 'libraryFile') {
if (mode === "libraryFile") {
return hasDataset && ctx.args.libraryFile !== undefined;
}
if (mode === 'buildLibrary') {
if (mode === "buildLibrary") {
return hasDataset && (ctx.args.libraryEntries?.length ?? 0) > 0;
}
return hasDataset && (ctx.uiState.librarySequence !== undefined || ctx.args.vGenes !== undefined);
return (
hasDataset && (ctx.uiState.librarySequence !== undefined || ctx.args.vGenes !== undefined)
);
})

.output('isRunning', (ctx) => ctx.outputs?.getIsReadyOrError() === false)
.output("isRunning", (ctx) => ctx.outputs?.getIsReadyOrError() === false)

.output('libraryUploadProgress', (ctx) =>
ctx.outputs?.resolve({ field: 'libraryImportHandle', allowPermanentAbsence: true })?.getImportProgress(), { isActive: true })
.output(
"libraryUploadProgress",
(ctx) =>
ctx.outputs
?.resolve({ field: "libraryImportHandle", allowPermanentAbsence: true })
?.getImportProgress(),
{ isActive: true },
)

.title(() => 'MiXCR Amplicon Alignment')
.title(() => "MiXCR Amplicon Alignment")

.subtitle((ctx) => ctx.args.customBlockLabel || ctx.args.defaultBlockLabel || '')
.subtitle((ctx) => ctx.args.customBlockLabel || ctx.args.defaultBlockLabel || "")

.done(2);

export type BlockOutputs = InferOutputsType<typeof platforma>;
export type Href = InferHrefType<typeof platforma>;
export * from './progress';
export * from './qc';
export * from './reports';
export * from "./progress";
export * from "./qc";
export * from "./reports";
5 changes: 3 additions & 2 deletions model/src/progress.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const ProgressPrefix = '[==PROGRESS==]';
export const ProgressPrefix = "[==PROGRESS==]";

export const ProgressPattern = /(?<stage>[^:]*):(?: *(?<progress>[0-9.]+)%)?(?: *ETA: *(?<eta>.+))?/;
export const ProgressPattern =
/(?<stage>[^:]*):(?: *(?<progress>[0-9.]+)%)?(?: *ETA: *(?<eta>.+))?/;
Comment thread
AStaroverov marked this conversation as resolved.
Loading
Loading