Skip to content

Commit 778f9ed

Browse files
Merge pull request #378 from qbicsoftware/release/0.28.0
Release/0.28.0
2 parents 3c7dccf + c2316af commit 778f9ed

File tree

4 files changed

+116
-20
lines changed

4 files changed

+116
-20
lines changed

src/main/groovy/life/qbic/datamodel/datasets/NfCorePipelineResult.groovy

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ final class NfCorePipelineResult {
4545

4646
private SampleIds sampleIds
4747

48+
// The RunId is only generated if the result was generated by a NF-Tower instance
4849
private RunId runId
4950

5051
private PipelineInformationFolder pipelineInformationFolder
@@ -53,7 +54,7 @@ final class NfCorePipelineResult {
5354

5455
private List<DataFolder> processFolders
5556

56-
NfCorePipelineResult(PipelineInformationFolder pipelineInformationFolder, QualityControlFolder qualityControlFolder, List<DataFolder> processFolders, RunId runId, SampleIds sampleIds) {
57+
NfCorePipelineResult(PipelineInformationFolder pipelineInformationFolder, QualityControlFolder qualityControlFolder, List<DataFolder> processFolders, RunId runId, SampleIds sampleIds) {
5758
Objects.requireNonNull(pipelineInformationFolder, "Please provide a PipelineInformation folder.")
5859
Objects.requireNonNull(qualityControlFolder, "Please provide a QualityControl folder")
5960
Objects.requireNonNull(processFolders, "Please provide a List of process folders")
@@ -67,6 +68,17 @@ final class NfCorePipelineResult {
6768
this.sampleIds = sampleIds
6869
}
6970

71+
NfCorePipelineResult(PipelineInformationFolder pipelineInformationFolder, QualityControlFolder qualityControlFolder, List<DataFolder> processFolders, SampleIds sampleIds) {
72+
Objects.requireNonNull(pipelineInformationFolder, "Please provide a PipelineInformation folder.")
73+
Objects.requireNonNull(qualityControlFolder, "Please provide a QualityControl folder")
74+
Objects.requireNonNull(processFolders, "Please provide a List of process folders")
75+
Objects.requireNonNull(sampleIds, "Please provide a sampleIds file")
76+
this.pipelineInformationFolder = pipelineInformationFolder
77+
this.qualityControlFolder = qualityControlFolder
78+
this.processFolders = processFolders
79+
this.sampleIds = sampleIds
80+
}
81+
7082
/**
7183
* Static factory method that creates a new nfcoreExperiment instance from the bioinformatic pipeline output.
7284
* See this @{link <a href="https://github.com/qbicsoftware/data-model-lib/blob/master/src/test/resources/examples/resultset/valid-resultset-example.json">example</a>}
@@ -80,14 +92,13 @@ final class NfCorePipelineResult {
8092

8193
//Check if all required folders are in root directory
8294
Objects.requireNonNull(bioinformaticPipelineOutput.get("pipelineInformation"), "The root folder must contain a PipelineInformation folder.")
83-
Objects.requireNonNull(bioinformaticPipelineOutput.get("qualityControl"),"The root folder must contain a QualityControl folder.")
95+
Objects.requireNonNull(bioinformaticPipelineOutput.get("qualityControl"), "The root folder must contain a QualityControl folder.")
8496
Objects.requireNonNull(bioinformaticPipelineOutput.get("processFolders"), "The root folder must contain at least one process folder.")
8597
//Check if all required files are in the pipeline_info directory
8698
Map pipelineInfoMap = bioinformaticPipelineOutput["pipelineInformation"] as Map
8799
Objects.requireNonNull(pipelineInfoMap.get("softwareVersions"), "The pipeline_info folder must contain a softwareVersions.yml file.")
88100
Objects.requireNonNull(pipelineInfoMap.get("executionReport"), "The pipeline_info folder must contain a executionReport.html file.")
89101
//Check if all required files are in root directory
90-
Objects.requireNonNull(bioinformaticPipelineOutput.get("runId"), "The root folder must contain a run_id.txt file.")
91102
Objects.requireNonNull(bioinformaticPipelineOutput.get("sampleIds"), "The root folder must contain an sample_ids.txt file.")
92103

93104
//Parse all folders in the root directory
@@ -108,12 +119,16 @@ final class NfCorePipelineResult {
108119
pipelineInformation.softwareVersions = softwareVersions as SoftwareVersions
109120
pipelineInformation.executionReport = executionReport as ExecutionReport
110121

111-
//Parse all files in the root directory
112-
DataFile runId = parseFile(bioinformaticPipelineOutput.get("runId") as Map) as RunId
122+
//Parse all mandatory files in the root directory
113123
DataFile sampleIds = parseFile(bioinformaticPipelineOutput.get("sampleIds") as Map) as SampleIds
114124

115-
//Create new NfCorePipelineResult with parsed information
116-
return new NfCorePipelineResult(pipelineInformation, qualityControl, processFolders, runId, sampleIds)
125+
// Parse optional Files in the root directory and generate NfCorePipelineResult accordingly
126+
if (bioinformaticPipelineOutput.get("runId") != null) {
127+
DataFile runId = parseFile(bioinformaticPipelineOutput.get("runId") as Map) as RunId
128+
return new NfCorePipelineResult(pipelineInformation, qualityControl, processFolders, runId, sampleIds)
129+
} else {
130+
return new NfCorePipelineResult(pipelineInformation, qualityControl, processFolders, sampleIds)
131+
}
117132
}
118133

119134
/**
@@ -165,11 +180,12 @@ final class NfCorePipelineResult {
165180
/*
166181
* Helper method that creates a DataFile instance from a map
167182
*/
183+
168184
private static DataFile parseFile(Map fileTree) throws IllegalArgumentException {
169185
String name = fileTree.get("name")
170186
String fileType = fileTree.get("fileType")
171187
String path = fileTree.get("path")
172-
188+
173189
for (String nfCoreFileType : nfCoreFileTypes) {
174190
Class<?> c = Class.forName(nfCoreFileType)
175191
Method method = c.getDeclaredMethod("create", String.class, String.class)
@@ -183,15 +199,15 @@ final class NfCorePipelineResult {
183199
}
184200
}
185201
// We have to check for files of unknown type since this Parser will encounter variable file output dependent on the pipeline
186-
if(!fileType)
187-
{
188-
throw new IllegalArgumentException("File $name with path $path is of unknown nfcore file type.")
202+
if (!fileType) {
203+
throw new IllegalArgumentException("File $name with path $path is of unknown nfcore file type.")
189204
}
190205
}
191206

192207
/*
193208
* Helper method that creates a DataFolder instance from a map
194209
*/
210+
195211
private static DataFolder parseFolder(Map fileTree) throws IllegalArgumentException {
196212

197213
def name = fileTree.get("name") as String
@@ -215,25 +231,27 @@ final class NfCorePipelineResult {
215231
* Helper method that tries to create a DataFolder instance
216232
* based on the DataFolder's different static factory create methods.
217233
*/
234+
218235
private static Optional<DataFolder> tryToCreateDataFolder(Method method,
219236
String name,
220237
String relativePath,
221238
List children) {
222239
Optional<DataFolder> folder = Optional.empty()
223-
try {
224-
// We only have named Folders
225-
def dataFolder = method.invoke(null, name, relativePath, children) as DataFolder
226-
folder = Optional.of(dataFolder)
227-
} catch (InvocationTargetException e2) {
228-
// Do nothing
229-
}
240+
try {
241+
// We only have named Folders
242+
def dataFolder = method.invoke(null, name, relativePath, children) as DataFolder
243+
folder = Optional.of(dataFolder)
244+
} catch (InvocationTargetException e2) {
245+
// Do nothing
246+
}
230247

231248
return folder
232249
}
233250

234251
/*
235252
* Helper method that parses the children of a folder.
236253
*/
254+
237255
private static List parseChildren(List<Map> children) {
238256
def parsedChildren = []
239257
children.each { Map unknownChild ->

src/main/resources/schemas/bioinformatics-analysis-result-set.schema.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,6 @@
115115
"pipelineInformation",
116116
"qualityControl",
117117
"processFolders",
118-
"sampleIds",
119-
"runId"
118+
"sampleIds"
120119
]
121120
}

src/test/groovy/life/qbic/datamodel/datasets/datastructure/NfCorePipelineResultSpec.groovy

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ class NfCorePipelineResultSpec extends Specification {
3535
@Shared
3636
Map missingQualityControlDataStructure
3737

38+
@Shared
39+
Map validDataStructureWithoutRunId
40+
3841
def setupSpec() {
3942
InputStream validStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("examples/resultset/valid-resultset-example.json")
4043
validDataStructure = (Map) new JsonSlurper().parse(validStream)
@@ -55,6 +58,10 @@ class NfCorePipelineResultSpec extends Specification {
5558
InputStream missingQualityControlStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("examples/resultset/missing-quality-control-resultset-example.json")
5659
missingQualityControlDataStructure = (Map) new JsonSlurper().parse(missingQualityControlStream)
5760
missingQualityControlStream.close()
61+
62+
InputStream validStreamWithoutRunId = Thread.currentThread().getContextClassLoader().getResourceAsStream("examples/resultset/valid-resultset-no-run_id-example.json")
63+
validDataStructureWithoutRunId = (Map) new JsonSlurper().parse(validStreamWithoutRunId)
64+
validStreamWithoutRunId.close()
5865
}
5966

6067
def "Create NfCorePipelineOutput from Map successfully"() {
@@ -122,4 +129,24 @@ class NfCorePipelineResultSpec extends Specification {
122129
thrown(NullPointerException)
123130
}
124131

132+
def "Create NfCorePipelineOutput from Map without RunId successfully"() {
133+
given:
134+
final Map validExample = validDataStructureWithoutRunId
135+
136+
when:
137+
final NfCorePipelineResult validPipelineResult = NfCorePipelineResult.createFrom(validExample)
138+
SampleIds sampleIds = validPipelineResult.getSampleIds()
139+
List<DataFolder> processFolders = validPipelineResult.getProcessFolders()
140+
QualityControlFolder qualityControlFolder = validPipelineResult.getQualityControlFolder()
141+
PipelineInformationFolder pipelineInformationFolder = validPipelineResult.getPipelineInformation()
142+
143+
then:
144+
sampleIds.name == "sample_ids.txt"
145+
processFolders.get(0).name == "salmon"
146+
qualityControlFolder.name == "multiqc"
147+
pipelineInformationFolder.getSoftwareVersions().name == "software_versions.yml"
148+
pipelineInformationFolder.getExecutionReport().name == "execution_report.html"
149+
assert validPipelineResult.runId == null
150+
}
151+
125152
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
{
2+
"pipelineInformation": {
3+
"name": "pipeline_info",
4+
"path": "./pipeline_info",
5+
"children": [],
6+
"softwareVersions": {
7+
"name": "software_versions.yml",
8+
"fileType": "yml",
9+
"path": "./pipeline_info/software_versions.yml"
10+
},
11+
"executionReport": {
12+
"name": "execution_report.html",
13+
"fileType": "html",
14+
"path": "./pipeline_info/execution_report.html"
15+
}
16+
},
17+
"qualityControl": {
18+
"name": "multiqc",
19+
"path": "./multiqc",
20+
"children": [
21+
{
22+
"name": "star_salmon",
23+
"path": "./multiqc/star_salmon",
24+
"children": [
25+
{
26+
"name": "multiqc_report.html",
27+
"path": "./multiqc/star_salmon/multiqc_report.html",
28+
"fileType": "html"
29+
}
30+
]
31+
}
32+
]
33+
},
34+
"processFolders": [
35+
{
36+
"name": "salmon",
37+
"path": "./salmon",
38+
"children": [
39+
{
40+
"name": "salmon.merged.gene_tpm.tsv",
41+
"fileType": "tsv",
42+
"path": "./salmon/salmon.merged.gene_tpm.tsv"
43+
}
44+
]
45+
}
46+
],
47+
"sampleIds": {
48+
"name": "sample_ids.txt",
49+
"fileType": "txt",
50+
"path": "./sample_ids.txt"
51+
}
52+
}

0 commit comments

Comments
 (0)