Skip to content

Commit e2b2b79

Browse files
Merge pull request #37 from platforma-open/julenmendieta/avoidCheckingFastaContent
Julenmendieta/avoidCheckingFastaContent
2 parents 73faf66 + 941be59 commit e2b2b79

10 files changed

Lines changed: 203 additions & 105 deletions

File tree

.changeset/tasty-loops-flash.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@platforma-open/milaboratories.immune-assay-data.check-content-empty": patch
3+
"@platforma-open/milaboratories.immune-assay-data.workflow": patch
4+
---
5+
6+
Improve empty input detection

pnpm-lock.yaml

Lines changed: 89 additions & 77 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pnpm-workspace.yaml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ packages:
44
- software/coverage-mode-calc
55
- software/fasta-to-tsv
66
- software/xlsx-to-csv
7+
- software/check-content-empty
78
- workflow
89
- model
910
- ui
@@ -15,13 +16,13 @@ catalog:
1516
'@milaboratories/ts-builder': 1.3.0
1617
'@milaboratories/ts-configs': 1.2.2
1718
'@platforma-sdk/workflow-tengo': 5.9.1
18-
'@platforma-sdk/model': 1.58.19
19-
'@platforma-sdk/ui-vue': 1.58.19
20-
'@platforma-sdk/tengo-builder': 2.4.27
19+
'@platforma-sdk/model': 1.58.22
20+
'@platforma-sdk/ui-vue': 1.58.25
21+
'@platforma-sdk/tengo-builder': 2.4.28
2122
'@platforma-sdk/package-builder': 3.11.6
22-
'@platforma-sdk/block-tools': 2.6.67
23+
'@platforma-sdk/block-tools': 2.6.68
2324
'@platforma-sdk/eslint-config': 1.2.0
24-
'@platforma-sdk/test': 1.58.20
25+
'@platforma-sdk/test': 1.58.24
2526
'@milaboratories/helpers': 1.13.7
2627
'@milaboratories/graph-maker': 1.2.3
2728
'@milaboratories/multi-sequence-alignment': 1.47.3
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"name": "@platforma-open/milaboratories.immune-assay-data.check-content-empty",
3+
"version": "1.0.0",
4+
"scripts": {
5+
"build": "pl-pkg build",
6+
"prepublishOnly": "pl-pkg prepublish",
7+
"do-pack": "rm -f *.tgz && pl-pkg build && pnpm pack && mv platforma-open*.tgz package.tgz",
8+
"changeset": "changeset",
9+
"version-packages": "changeset version"
10+
},
11+
"files": [
12+
"./dist/**/*"
13+
],
14+
"dependencies": {},
15+
"devDependencies": {
16+
"@platforma-sdk/package-builder": "catalog:",
17+
"@platforma-open/milaboratories.runenv-python-3": "catalog:"
18+
},
19+
"block-software": {
20+
"entrypoints": {
21+
"main": {
22+
"binary": {
23+
"artifact": {
24+
"type": "python",
25+
"registry": "platforma-open",
26+
"environment": "@platforma-open/milaboratories.runenv-python-3:3.12.10",
27+
"dependencies": {
28+
"toolset": "pip",
29+
"requirements": "requirements.txt"
30+
},
31+
"root": "./src"
32+
},
33+
"cmd": [
34+
"python",
35+
"{pkg}/main.py"
36+
]
37+
}
38+
}
39+
}
40+
}
41+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import argparse
2+
import sys
3+
4+
def main():
5+
parser = argparse.ArgumentParser(description="Check if a file has a minimum number of non-empty lines.")
6+
parser.add_argument("-i", "--input", required=True, help="Input file path.")
7+
parser.add_argument("-n", "--min_lines", type=int, default=1, help="Minimum number of non-empty lines required to be considered 'not empty'.")
8+
9+
args = parser.parse_args()
10+
11+
try:
12+
count = 0
13+
with open(args.input, 'r') as f:
14+
for line in f:
15+
if line.strip():
16+
count += 1
17+
if count >= args.min_lines:
18+
break
19+
20+
# print "true" if it's empty (count < min_lines), "false" if it has enough content
21+
print("true" if count < args.min_lines else "false")
22+
23+
except FileNotFoundError:
24+
print(f"Error: File '{args.input}' not found.")
25+
sys.exit(1)
26+
except Exception as e:
27+
print(f"An unexpected error occurred: {e}")
28+
sys.exit(1)
29+
30+
if __name__ == "__main__":
31+
main()

software/check-content-empty/src/requirements.txt

Whitespace-only changes.

workflow/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
"@platforma-open/milaboratories.immune-assay-data.coverage-mode-calc": "workspace:*",
1616
"@platforma-open/milaboratories.immune-assay-data.fasta-to-tsv": "workspace:*",
1717
"@platforma-open/milaboratories.immune-assay-data.xlsx-to-csv": "workspace:*",
18+
"@platforma-open/milaboratories.immune-assay-data.check-content-empty": "workspace:*",
1819
"@platforma-open/soedinglab.software-mmseqs2": "catalog:"
1920
},
2021
"devDependencies": {

workflow/src/analysis.tpl.tengo

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ fastaToTsvSw := assets.importSoftware("@platforma-open/milaboratories.immune-ass
1212
addHeaderSw := assets.importSoftware("@platforma-open/milaboratories.immune-assay-data.add-header:main")
1313
covModeCalcSw := assets.importSoftware("@platforma-open/milaboratories.immune-assay-data.coverage-mode-calc:main")
1414
xlsxToCsvSw := assets.importSoftware("@platforma-open/milaboratories.immune-assay-data.xlsx-to-csv:main")
15+
checkContentEmptySw := assets.importSoftware("@platforma-open/milaboratories.immune-assay-data.check-content-empty:main")
1516

1617
runAlignmentTpl := assets.importTemplate(":run-alignment")
1718
checkContentEmptyTpl := assets.importTemplate(":check-content-empty")
@@ -274,16 +275,24 @@ self.body(func(args) {
274275
arg("-o").arg("results_with_header.tsv").
275276
addFile("results.tsv", mmseqsOutput).
276277
saveFile("results_with_header.tsv").
277-
saveFileContent("results_with_header.tsv").
278278
run()
279279

280280
mmseqsResultTsv := addHeaderRun.getFile("results_with_header.tsv")
281-
mmseqsResultContent := addHeaderRun.getFileContent("results_with_header.tsv")
282281

283-
// Use subtemplate to check if file is empty
282+
// Check if results are empty (only header line or nothing)
283+
checkResultsRun := exec.builder().
284+
software(checkContentEmptySw).
285+
arg("-i").arg("input.file").
286+
arg("-n").arg("2"). // Require at least 2 non-empty lines (header + 1 data line)
287+
addFile("input.file", mmseqsResultTsv).
288+
saveStdoutContent().
289+
mem("8GiB").
290+
cpu(1).
291+
inLightQueue().
292+
run()
293+
284294
checkResult := render.create(checkContentEmptyTpl, {
285-
content: mmseqsResultContent,
286-
mode: "headerOnly"
295+
content: checkResultsRun.getStdoutContent()
287296
})
288297
emptyResults := checkResult.output("result")
289298

workflow/src/check-content-empty.tpl.tengo

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,6 @@ text := import("text")
44
self.defineOutputs("result")
55

66
self.body(func(args) {
7-
content := string(args.content.getData())
8-
mode := args.mode
9-
10-
isEmpty := false
11-
if mode == "raw" {
12-
// No header line (e.g. FASTA): empty content means no data
13-
isEmpty = text.trim_space(content) == ""
14-
} else if mode == "headerOnly" {
15-
// File has a header line (e.g. TSV with added header): empty means <= 1 line
16-
lines := text.split(text.trim_space(content), "\n")
17-
isEmpty = len(lines) <= 1
18-
}
19-
20-
return { result: isEmpty }
7+
// 'content' is the stdout of the check-software (already a "true"/"false" string)
8+
return { result: text.trim_space(string(args.content.getData())) == "true" }
219
})

workflow/src/main.tpl.tengo

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ processOutputsTpl := assets.importTemplate(":process-outputs")
1616
checkContentEmptyTpl := assets.importTemplate(":check-content-empty")
1717

1818
prepareFastaSw := assets.importSoftware("@platforma-open/milaboratories.immune-assay-data.prepare-fasta:main")
19+
checkContentEmptySw := assets.importSoftware("@platforma-open/milaboratories.immune-assay-data.check-content-empty:main")
1920

2021
wf.prepare(func(args){
2122
bundleBuilder := wf.createPBundleBuilder()
@@ -103,15 +104,23 @@ wf.body(func(args) {
103104
arg("--seq_col").arg("sequence").
104105
arg("--id_col").arg("seqId").
105106
saveFile("output.fasta").
106-
saveFileContent("output.fasta").
107107
run()
108108
clonesFasta := clonesFastaRun.getFile("output.fasta")
109-
clonesFastaContent := clonesFastaRun.getFileContent("output.fasta")
110109

111110
// Check if clones are empty before running mmseqs2
111+
checkClonesRun := exec.builder().
112+
software(checkContentEmptySw).
113+
arg("-i").arg("input.file").
114+
arg("-n").arg("1").
115+
addFile("input.file", clonesFasta).
116+
saveStdoutContent().
117+
mem("8GiB").
118+
cpu(1).
119+
inLightQueue().
120+
run()
121+
112122
checkClonesResult := render.create(checkContentEmptyTpl, {
113-
content: clonesFastaContent,
114-
mode: "raw"
123+
content: checkClonesRun.getStdoutContent()
115124
})
116125
emptyClonesInput := checkClonesResult.output("result")
117126

0 commit comments

Comments
 (0)