Lanzar en un mismo 'job' para SLURM 10 lineas de ejecuación de YASARA.


Situación: estamos haciendo simulaciones de docking de una libreria de 4, 8 millones de compuestos, framentada en porciones de 500 compuestos almacenados en ficheros SDF. Esto supone 9.780 framentos, que se ejecutarian en otros tantos 'jobs' lanzados a un cluster con colas gobernadas por SLURM. Si no podemos lanzar más de 100 con nuestro usuario en el clúster, si podemos conseguir que cada 'job' lanzado pueda ejecutar 10 trabajos de YASARA. Esto es lo que consigue el siguiente script que genera ficheros *.sbatch con 10 líneas de ejecución.


# -*- coding: iso-8859-1 -*-

import os

base_path = "/lustre/home/ic/jant.encinar/py-linux/15_docking-YAS"
var_file_path = f"{base_path}/_lista-4-variables-en-4-columnas.txt"
template_file_path = f"{base_path}/_15-template-config-UMH_DOCKING.txt"

with open(var_file_path, 'r') as var_file:
    var_lines = [line.strip() for line in var_file if line.strip()]

block_size = 10

for block_index in range(0, len(var_lines), block_size):

    block = var_lines[block_index:block_index + block_size]

    if len(block) < block_size:
        break

    with open(template_file_path, 'r') as template_file:
        template_lines = template_file.readlines()

    # Variables del primer registro del bloque
    first_variables = [v.strip() for v in block[0].split('\t')]
    variable_1 = first_variables[0]
    variable_2_first = first_variables[1]

    # Sustituir variable-1 y variable-2 (solo cabecera/base)
    template_lines = [
        line.replace("[variable-1]", variable_1)
            .replace("[variable-2]", variable_2_first)
        for line in template_lines
    ]

    # Localizar línea yasara
    yasara_index = None
    for i, line in enumerate(template_lines):
        if "yasara -txt" in line:
            yasara_index = i
            break

    if yasara_index is None:
        raise RuntimeError("No se encontró la línea de ejecución de yasara.")

    # Generar 10 ejecuciones YASARA
    yasara_commands = []
    for line in block:
        variables = [v.strip() for v in line.split('\t')]
        var2 = variables[1]
        var3 = variables[2]

        cmd = (
            "/lustre/home/ic/jant.encinar/yasara-25-1-13/yasara -txt "
            "/lustre/home/ic/jant.encinar/py-linux/15_docking-YAS/"
            "_dock_runscreening-salva-10-kcal-mol_25-1-13.mcr "
            f"\"MacroTarget='/lustre/home/ic/jant.encinar/runDC/{var2}/{var3}'\""
        )

        yasara_commands.append(cmd + "\n")

    template_lines[yasara_index:yasara_index+1] = yasara_commands

    # Localizar inicio del bloque de limpieza original
    cleanup_start = None
    for i, line in enumerate(template_lines):
        if "# Borra ficheros" in line:
            cleanup_start = i
            break

    if cleanup_start is None:
        raise RuntimeError("No se encontró el bloque de limpieza.")

    # Generar nuevos bloques de limpieza (10)
    cleanup_commands = ["# Borra ficheros tras terminar todas las ejecuciones\n"]

    for line in block:
        variables = [v.strip() for v in line.split('\t')]
        var2 = variables[1]

        cleanup_commands.extend([
            f"cd /lustre/home/ic/jant.encinar/runDC/{var2}/\n",
            "rm *.adr *.err *.out *.map *_bestposes.pdb *_bestposes.sdf\n",
            "cd /lustre/home/ic/jant.encinar/\n",
            f"mv /lustre/home/ic/jant.encinar/{var2}/ /lustre/home/ic/jant.encinar/runDC/{var2}_fin/\n",
            "\n"
        ])

    # Reemplazar todo el bloque de limpieza original
    template_lines[cleanup_start:] = cleanup_commands

    output_filename = f"{variable_1}.sbatch"
    output_file_path = os.path.join(base_path, output_filename)

    with open(output_file_path, 'w') as output_file:
        output_file.writelines(template_lines)

print("Proceso completado con éxito!")

Como ejemplo de _lista-4-variables-en-4-columnas.txt.

Como ejemplo de _15-template-config-UMH_DOCKING.txt.