diff --git a/build.gradle.kts b/build.gradle.kts index 68546e7..46128a6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,7 +4,7 @@ plugins { } group = "net.maizegenetics" -version = "0.2.4" +version = "0.2.5" repositories { mavenCentral() @@ -19,7 +19,6 @@ dependencies { implementation("com.google.guava:guava:33.1.0-jre") implementation("com.github.samtools:htsjdk:4.0.1") - testImplementation(kotlin("test")) } diff --git a/src/main/kotlin/net/maizegenetics/commands/ConvertCoordinates.kt b/src/main/kotlin/net/maizegenetics/commands/ConvertCoordinates.kt index d5def90..88c5acc 100644 --- a/src/main/kotlin/net/maizegenetics/commands/ConvertCoordinates.kt +++ b/src/main/kotlin/net/maizegenetics/commands/ConvertCoordinates.kt @@ -111,8 +111,11 @@ class ConvertCoordinates : CliktCommand(name = "convert-coordinates") { } // Run convert_coords.py + // Set PYTHONPATH so Python can find the 'python' package for imports + val pythonPath = mlimputeDir.resolve("src").toString() logger.info("Running convert_coords.py") val exitCode = ProcessRunner.runCommand( + "env", "PYTHONPATH=$pythonPath", "pixi", "run", "python", pythonScript.toString(), "--assembly-list", assemblyList.toString(), diff --git a/src/main/kotlin/net/maizegenetics/commands/GenerateRecombinedSequences.kt b/src/main/kotlin/net/maizegenetics/commands/GenerateRecombinedSequences.kt index 82f4612..1e0e3a5 100644 --- a/src/main/kotlin/net/maizegenetics/commands/GenerateRecombinedSequences.kt +++ b/src/main/kotlin/net/maizegenetics/commands/GenerateRecombinedSequences.kt @@ -120,8 +120,11 @@ class GenerateRecombinedSequences : CliktCommand(name = "generate-recombined-seq } // Run write_fastas.py + // Set PYTHONPATH so Python can find the 'python' package for imports + val pythonPath = mlimputeDir.resolve("src").toString() logger.info("Running write_fastas.py") val exitCode = ProcessRunner.runCommand( + "env", "PYTHONPATH=$pythonPath", "pixi", "run", "python", pythonScript.toString(), "--assembly-list", assemblyList.toString(), diff --git a/src/main/kotlin/net/maizegenetics/commands/Orchestrate.kt b/src/main/kotlin/net/maizegenetics/commands/Orchestrate.kt index 770414a..7e53ddc 100644 --- a/src/main/kotlin/net/maizegenetics/commands/Orchestrate.kt +++ b/src/main/kotlin/net/maizegenetics/commands/Orchestrate.kt @@ -1,6 +1,7 @@ package net.maizegenetics.commands import com.github.ajalt.clikt.core.CliktCommand +import com.github.ajalt.clikt.core.parse import com.github.ajalt.clikt.parameters.options.default import com.github.ajalt.clikt.parameters.options.option import com.github.ajalt.clikt.parameters.options.required @@ -167,24 +168,14 @@ class Orchestrate : CliktCommand(name = "orchestrate") { logger.info("AUTO-SETUP: Running setup-environment") logger.info("=".repeat(80)) - val args = buildList { - add("setup-environment") - add("--work-dir=${workDir}") - } - - val exitCode = ProcessRunner.runCommand( - "./gradlew", "run", "--args=${args.joinToString(" ")}", - workingDir = File("."), - logger = logger - ) - - if (exitCode != 0) { - logger.error("setup-environment failed with exit code $exitCode") - return false + return try { + SetupEnvironment().parse(listOf("--work-dir=$workDir")) + logger.info("setup-environment completed successfully") + true + } catch (e: Exception) { + logger.error("setup-environment failed: ${e.message}", e) + false } - - logger.info("setup-environment completed successfully") - return true } private fun parseYamlConfig(configPath: Path): PipelineConfig { @@ -217,6 +208,7 @@ class Orchestrate : CliktCommand(name = "orchestrate") { } // Parse maf_to_gvcf + @Suppress("UNCHECKED_CAST") val mafToGvcfMap = configMap["maf_to_gvcf"] as? Map val mafToGvcf = mafToGvcfMap?.let { MafToGvcfConfig( @@ -227,6 +219,7 @@ class Orchestrate : CliktCommand(name = "orchestrate") { } // Parse downsample_gvcf + @Suppress("UNCHECKED_CAST") val downsampleGvcfMap = configMap["downsample_gvcf"] as? Map val downsampleGvcf = downsampleGvcfMap?.let { DownsampleGvcfConfig( @@ -241,6 +234,7 @@ class Orchestrate : CliktCommand(name = "orchestrate") { } // Parse convert_to_fasta + @Suppress("UNCHECKED_CAST") val convertToFastaMap = configMap["convert_to_fasta"] as? Map val convertToFasta = convertToFastaMap?.let { ConvertToFastaConfig( diff --git a/src/main/kotlin/net/maizegenetics/commands/PickCrossovers.kt b/src/main/kotlin/net/maizegenetics/commands/PickCrossovers.kt index d1f1cd7..974606a 100644 --- a/src/main/kotlin/net/maizegenetics/commands/PickCrossovers.kt +++ b/src/main/kotlin/net/maizegenetics/commands/PickCrossovers.kt @@ -77,12 +77,17 @@ class PickCrossovers : CliktCommand(name = "pick-crossovers") { FileUtils.createOutputDirectory(outputDir, logger) // Run pick_crossovers.py + // Set PYTHONPATH so Python can find the 'python' package for imports + // Use absolute paths since the working directory is set to outputDir + // Use sh -c to set PYTHONPATH inside pixi's environment + val pythonPath = mlimputeDir.resolve("src").toAbsolutePath().toString() + val scriptPath = pythonScript.toAbsolutePath().toString() + val refFastaPath = refFasta.toAbsolutePath().toString() + val assemblyListPath = assemblyList.toAbsolutePath().toString() + val shellCommand = "PYTHONPATH='$pythonPath' python '$scriptPath' --ref-fasta '$refFastaPath' --assembly-list '$assemblyListPath'" logger.info("Running pick_crossovers.py") val exitCode = ProcessRunner.runCommand( - "pixi", "run", - "python", pythonScript.toString(), - "--ref-fasta", refFasta.toString(), - "--assembly-list", assemblyList.toString(), + "pixi", "run", "sh", "-c", shellCommand, workingDir = outputDir.toFile(), logger = logger ) diff --git a/src/main/kotlin/net/maizegenetics/commands/SetupEnvironment.kt b/src/main/kotlin/net/maizegenetics/commands/SetupEnvironment.kt index ae6dadf..c7af9c7 100644 --- a/src/main/kotlin/net/maizegenetics/commands/SetupEnvironment.kt +++ b/src/main/kotlin/net/maizegenetics/commands/SetupEnvironment.kt @@ -98,7 +98,8 @@ class SetupEnvironment : CliktCommand(name = "setup-environment") { .toFile() if (mlImputeGradlew.exists()) { - if (mlImputeGradlew.setExecutable(true)) { + // setExecutable(true, false) makes it executable for all users (like chmod +x) + if (mlImputeGradlew.setExecutable(true, false)) { logger.info("Made MLImpute gradlew executable: ${mlImputeGradlew.path}") } else { logger.warn("Failed to set executable permissions on gradlew: ${mlImputeGradlew.path}") diff --git a/src/main/resources/pixi.toml b/src/main/resources/pixi.toml index 0415d62..bb9c0a6 100644 --- a/src/main/resources/pixi.toml +++ b/src/main/resources/pixi.toml @@ -20,6 +20,7 @@ seqkit = "*" crossmap = "*" parallel = "*" pysam = "*" +samtools = "*" # Linux-only dependencies (AnchorWave not available on macOS) [target.linux-64.dependencies]