From a2ff589d01fd75a10c9ada02b9afd2cd8e668a9e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Nicolas=20FERNANDEZ=20NU=C3=91EZ?=
 <nicolas.fernandez@ird.fr>
Date: Fri, 21 Mar 2025 16:26:47 +0100
Subject: [PATCH] Fix typo l. 66 Run_GeVarLi.sh (if-fi) v.2025.03_001

---
 Run_GeVarLi.sh                                |   5 +-
 workflow/rules/symlinks_renamming.smk         |  16 +-
 workflow/rules/workflow_reporting.smk         |  61 ++---
 .../__pycache__/functions.cpython-312.pyc     | Bin 6453 -> 6456 bytes
 workflow/scripts/functions.py                 |   3 +-
 workflow/scripts/settings.py                  | 214 ++++++++++++++++++
 6 files changed, 243 insertions(+), 56 deletions(-)
 create mode 100644 workflow/scripts/settings.py

diff --git a/Run_GeVarLi.sh b/Run_GeVarLi.sh
index 7759f91..b0fc8bf 100755
--- a/Run_GeVarLi.sh
+++ b/Run_GeVarLi.sh
@@ -63,6 +63,7 @@ else # If yes, intern shell source conda
     source ~/mambaforge/etc/profile.d/conda.sh 2> /dev/null                            # local user with mambaforge ¡ Deprecated !
     source ~/miniconda3/etc/profile.d/conda.sh 2> /dev/null                            # local user with miniconda3 ¡ Deprecated !
     source /usr/local/bioinfo/miniconda3-23.10.0-1/etc/profile.d/conda.sh 2> /dev/null # iTROP HPC server (conda 23.11.0)
+fi
 
 ###############################################################################
 ### SPINNER ###
@@ -195,7 +196,7 @@ snakemake \
 echo -e "\n ${green} > Snakemake: run${nc} \n"
 snakemake \
     --directory ${workdir}/ \
-    --snakefile ${workdir}/workflow/Snakefile\
+    --snakefile ${workdir}/workflow/Snakefile \
     --cores ${max_threads} \
     --resources mem_gb=${max_memory} \
     --rerun-incomplete \
@@ -211,4 +212,4 @@ snakemake \
 echo -e "\n Deactivate ${ylo}Workflow-Core${nc} conda environment."
 conda deactivate
 
-###############################################################################
\ No newline at end of file
+###############################################################################
diff --git a/workflow/rules/symlinks_renamming.smk b/workflow/rules/symlinks_renamming.smk
index eb72ba6..f4bfce3 100644
--- a/workflow/rules/symlinks_renamming.smk
+++ b/workflow/rules/symlinks_renamming.smk
@@ -20,21 +20,17 @@
 ###############################################################################
 rule config:
     # Aim: Load configuration file
-    # Use: yq -r . <CONFIG_FILE>
+    # Use: 
     message:
         """
         ~ Configuration ∞ Show analyses settings ~
         """
-    conda:
-        WORKFLOW
     input:
         config_file = "config/config.yaml"
     output:
-        done = temp("done.temp")
-    shell:
-        "bash workflow/scripts/settings.sh "
-        "&& "
-        "touch {output.done}"
+        setting_log = "results/10_Reports/settings.log"
+    script:
+        "workflow/scripts/settings.py "
 
 ###############################################################################
 rule symlinks:
@@ -47,8 +43,8 @@ rule symlinks:
         Reads: ___________ R{wildcards.mate}
         """
     input:
-        valid_fastq = lambda wildcards: os.path.abspath(VALID_FASTQ[wildcards.sample][wildcards.mate]),
-        done = "done.temp"
+        setting_log = "results/10_Reports/settings.log",
+        valid_fastq = lambda wildcards: os.path.abspath(VALID_FASTQ[wildcards.sample][wildcards.mate])
     output:
         symlink = temp("results/symlinks/{sample}_R{mate}.fastq.gz")
     log:
diff --git a/workflow/rules/workflow_reporting.smk b/workflow/rules/workflow_reporting.smk
index ee6152f..da31bbb 100644
--- a/workflow/rules/workflow_reporting.smk
+++ b/workflow/rules/workflow_reporting.smk
@@ -50,14 +50,14 @@ rule snakemake_report:
         """
         ~ Report ∞ Generate a workflow report in HTML format ~
         """
-    conda:
-        WORKFLOW
+    #conda:
+    #    WORKFLOW
     params:
         #style_sheet = STYLE_SHEET
     input:
         multiqc = "results/10_Reports/multiqc/",
         time = "results/10_Reports/time.log",
-        summary = "results/10_Reports/files-summary.txt",
+        summary = "results/10_Reports/files-summary.tsv",
         graph = expand("results/10_Reports/graphs/{graph_type}.{ext}",
             graph_type = GRAPH_TYPE,
             ext = GRAPH_EXT),
@@ -85,7 +85,7 @@ rule snakemake_summary:
     input:
         final_outputs = get_final_outputs()
     output:
-        summary = "results/10_Reports/files-summary.txt"
+        summary = "results/10_Reports/files-summary.tsv"
     log:
         "results/10_Reports/tools-log/files-summary.log"
     shell:
@@ -166,52 +166,27 @@ rule log_time:
     output:
         time_log = "results/10_Reports/time.log"
     run:
-        time_stamp_start = time.strftime("%Y-%m-%d %H:%M", time.localtime(start_time)) # Get system: analyzes starting time
-        time_stamp_end = time.strftime("%Y-%m-%d %H:%M", time.localtime())             # Get date / hour ending analyzes
-        elapsed_time = int(time.time() - start_time) # Get SECONDS counter
-        hours = elapsed_time // 3600                 # /3600 = hours
-        minutes = (elapsed_time % 3600) // 60        # %3600 /60 = minutes
-        seconds = elapsed_time % 60                  # %60 = seconds
-        formatted_time = f"{hours:02d}:{minutes:02d}:{seconds:02d}" # Format
-        green = "\033[32m" # ANSI green color code
-        ylo = "\033[33m"   # ANSI yellow color code
-        nc = "\033[0m"     # ANSI no-color code
+        time_stamp_start = time.strftime("%Y-%m-%d %H:%M", time.localtime(START_TIME))
+        time_stamp_end = time.strftime("%Y-%m-%d %H:%M", time.localtime())
+        elapsed_time = int(time.time() - START_TIME)
+        hours = elapsed_time // 3600
+        minutes = (elapsed_time % 3600) // 60
+        seconds = elapsed_time % 60
+        formatted_time = f"{hours:02d}:{minutes:02d}:{seconds:02d}"
+        green = "\033[32m"
+        ylo = "\033[33m"
+        nc = "\033[0m"
         message_time = f"""
 {green}Start time{nc} _____________ {time_stamp_start}
 {green}End time{nc} _______________ {time_stamp_end}
 {green}Processing time{nc} ________ {ylo}{formatted_time}{nc}
 """
-        print(message_time) # Print time message
-        ansi_escape = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]') # ANSI escape code
-        message_clean = ansi_escape.sub('', message_time) # Clean ANSI escape code
-        with open(output.time_log, "w") as f: # Log time message
+        print(message_time)
+        ansi_escape = re.compile(r'\x1B\[[0-?]*[ -/]*[@-~]')
+        message_clean = ansi_escape.sub('', message_time)
+        with open(output.time_log, "w") as f:
             f.write(message_clean)
 
-###############################################################################
-rule log_setup:
-    # Aim: log user setup
-    # Use:
-    message:
-        """
-        ~ Log ∞ User setup ~
-        """
-    input:
-        setup = "config/config.yaml",
-    output:
-        setup_log = "results/10_Reports/setup.log"
-    run:
-        import subprocess
-        uname = subprocess.check_output(["uname", "-a"]).decode().strip()
-        fastq_dir = subprocess.check_output(["yq", "-Mr", ".fastq_dir", input.setup]).decode().strip()
-        try:
-            fastq_files = subprocess.check_output(["bash", "-c", "ls -1 {}/*.fastq.gz 2>/dev/null | wc -l".format(fastq_dir)]).decode().strip()
-        except Exception:
-            fastq_files = "0"
-        with open(output.setup_log, "w") as f:
-            f.write("OS info: " + uname + "\n")
-            f.write("Fastq directory: " + fastq_dir + "\n")
-            f.write("Number of fastq files: " + fastq_files + "\n")
-
 ###############################################################################
 rule log_environments:
     # Aim: copy conda environments files to results
diff --git a/workflow/scripts/__pycache__/functions.cpython-312.pyc b/workflow/scripts/__pycache__/functions.cpython-312.pyc
index 09825b982dd622ec6f2390258070bd704c9da8c8..039460ac12bd9424bf39c41de31f949261905bb6 100644
GIT binary patch
delta 70
zcmdmLw8Mz^G%qg~0}!wm-A(V`$a_(QQGW7$5i!=1%)IpC&EG}RnFRzGScR^$NL*x*
YxFBhDg~fVup2R-R1V%>5B4waP0QJcf2mk;8

delta 67
zcmdmCwAG0BG%qg~0}!k{dn-L?Bkx5KMw!X?MZ}m&3pW1}NoN+|V_+4!&LVM<MdE^_
V`4tw6$%PX8IO7=^C5x1Sx&YCr6MO&w

diff --git a/workflow/scripts/functions.py b/workflow/scripts/functions.py
index fc28f23..e55beb1 100644
--- a/workflow/scripts/functions.py
+++ b/workflow/scripts/functions.py
@@ -172,7 +172,8 @@ def get_final_outputs():
                                 caller = CALLER,
                                 assigner = ASSIGNER))
     # logs
-    final_outputs.append("results/10_Reports/setup.log")
+    #final_outputs.append("results/10_Reports/setup.log")
+    final_outputs.append("results/10_Reports/settings.log")
     final_outputs.append("results/10_Reports/config.log")
     final_outputs.append("results/10_Reports/envs/")
     # return final_outpus
diff --git a/workflow/scripts/settings.py b/workflow/scripts/settings.py
new file mode 100644
index 0000000..5d9a94b
--- /dev/null
+++ b/workflow/scripts/settings.py
@@ -0,0 +1,214 @@
+#!/usr/bin/env python3
+
+import os
+import sys
+import subprocess
+import platform
+import re
+import glob
+import time
+import yaml
+
+# Get working directory
+workdir = os.path.abspath(os.path.join(os.path.dirname(__file__), "../../"))
+
+# Get version
+version_file = os.path.join(workdir, "VERSION.txt")
+try:
+    with open(version_file, "r") as vf:
+        version = vf.read().strip()
+except Exception:
+    version = "N/A"
+
+# Define colors
+blue = "\033[1;34m"
+green = "\033[1;32m"
+red = "\033[1;31m"
+ylo = "\033[1;33m"
+nc = "\033[0m"
+
+# Get system information
+system_platform = platform.system().lower()
+if "darwin" in system_platform:
+    os_type = "osx"
+elif "linux" in system_platform:
+    os_type = "linux"
+elif "bsd" in system_platform:
+    os_type = "bsd"
+elif "sunos" in system_platform:
+    os_type = "solaris"
+elif "windows" in system_platform:
+    os_type = "windows"
+else:
+    os_type = "unknown (" + system_platform + ")"
+
+# Get hardware information
+if os_type == "osx":
+    try:
+        model_name = subprocess.check_output(["sysctl", "-n", "machdep.cpu.brand_string"]).decode().strip()
+        physical_cpu = subprocess.check_output(["sysctl", "-n", "hw.physicalcpu"]).decode().strip()
+        logical_cpu = subprocess.check_output(["sysctl", "-n", "hw.logicalcpu"]).decode().strip()
+        mem_size = subprocess.check_output(["sysctl", "-n", "hw.memsize"]).decode().strip()  # en octets
+        ram_gb = int(mem_size) // (1024 ** 3)
+    except Exception:
+        model_name = physical_cpu = logical_cpu = ram_gb = "N/A"
+elif os_type in ["linux", "bsd", "solaris"]:
+    try:
+        lscpu_out = subprocess.check_output(["lscpu"]).decode()
+        model_name = ""
+        physical_cpu = ""
+        threads_cpu = ""
+        for line in lscpu_out.splitlines():
+            if "Model name:" in line:
+                model_name = line.split(":", 1)[1].strip()
+            if line.startswith("CPU(s):"):
+                physical_cpu = line.split(":", 1)[1].strip()
+            if "Thread(s) per core:" in line:
+                threads_cpu = line.split(":", 1)[1].strip()
+        if physical_cpu and threads_cpu:
+            logical_cpu = int(physical_cpu) * int(threads_cpu)
+        else:
+            logical_cpu = "N/A"
+    except Exception:
+        model_name = physical_cpu = logical_cpu = "N/A"
+    try:
+        with open("/proc/meminfo", "r") as meminfo:
+            for line in meminfo:
+                if line.startswith("MemTotal:"):
+                    mem_kb = int(re.findall(r'\d+', line)[0])
+                    ram_gb = mem_kb // (1024 ** 2)
+                    break
+    except Exception:
+        ram_gb = "N/A"
+else:
+    print(f"\nPlease, use a UNIX-like operating system (linux, osx, WSL).")
+    sys.exit(0)
+
+# Get network status
+def is_online():
+    for host in ["google.com", "cloudflare.com"]:
+        try:
+            subprocess.check_call(
+                ["ping", "-c", "1", "-W", "5", host],
+                stdout=subprocess.DEVNULL,
+                stderr=subprocess.DEVNULL,
+            )
+            return True
+        except subprocess.CalledProcessError:
+            continue
+    return False
+
+network = "Online" if is_online() else "Offline"
+
+# Get version
+def get_version(cmd, fallback="N/A"):
+    try:
+        return subprocess.check_output(cmd).decode().strip()
+    except Exception:
+        return fallback
+
+conda_version = get_version(["conda", "--version"])
+mamba_version = get_version(["mamba", "--version"]).splitlines()[0]
+snakemake_version = get_version(["snakemake", "--version"])
+
+# Get configuration
+config_file = os.path.join(workdir, "config", "config.yaml")
+with open(config_file, "r") as cf:
+    config_data = yaml.safe_load(cf)
+
+# Get fastq directory
+fastq_dir = config_data.get("fastq_dir", "")
+fastq_files = len(glob.glob(os.path.join(fastq_dir, "*.fastq.gz")))
+fastq_R1 = len(glob.glob(os.path.join(fastq_dir, "*R1*.fastq.gz")))
+fastq_R2 = len(glob.glob(os.path.join(fastq_dir, "*R2*.fastq.gz")))
+
+# Get resources
+resources = config_data.get("resources", {})
+max_threads = resources.get("cpus", "N/A")
+max_memory = resources.get("ram", "N/A")
+
+# Get modules
+modules = config_data.get("modules", {})
+qualities = modules.get("qualities", "N/A")
+keeptrim = modules.get("keeptrim", "N/A")
+cleapping = modules.get("cleapping", "N/A")
+covstats = modules.get("covstats", "N/A")
+consensus = modules.get("consensus", "N/A")
+lineages = modules.get("lineages", "N/A")
+gisaid = modules.get("gisaid", "N/A")
+
+# Get consensus parameters
+consensus_params = config_data.get("consensus", {})
+reference_conf = consensus_params.get("reference", "N/A")
+mapper = consensus_params.get("mapper", "N/A")
+min_cov = consensus_params.get("min_cov", "N/A")
+min_freq = consensus_params.get("min_freq", "N/A")
+assigner = consensus_params.get("assigner", "N/A")
+
+# Get other parameters
+nextclade_dataset = config_data.get("nextclade", {}).get("dataset", "N/A")
+fastqscreen_subset = config_data.get("fastq_screen", {}).get("subset", "N/A")
+cutadapt_clipping = config_data.get("cutadapt", {}).get("clipping", "N/A")
+
+# Get time stamp
+time_stamp_start = time.strftime("%Y-%m-%d %H:%M", time.localtime())
+
+# Create message
+message_settings = f"""{blue}------------------------------------------------------------------------{nc}
+{blue}#####{nc} {red}Configuration{nc} {blue}#####{nc}
+{blue}-------------------------{nc}
+
+{green}Starting time{nc} ______________ {time_stamp_start}
+
+{green}Conda version{nc} ______________ {ylo}{conda_version}{nc}
+{green}Mamba version{nc} ______________ {ylo}{mamba_version}{nc}
+{green}Snakemake version{nc} __________ {ylo}{snakemake_version}{nc}
+
+{green}Max threads{nc} ________________ {red}{max_threads}{nc} of {ylo}{logical_cpu}{nc} threads available
+{green}Max memory{nc} _________________ {red}{max_memory}{nc} of {ylo}{ram_gb}{nc} Gb available
+{green}Jobs memory{nc} ________________ {red}N/A{nc} Gb per job
+
+{green}Network{nc} ____________________ {red}{network}{nc}
+
+{green}Working directory{nc} _________ '{ylo}{workdir}{nc}'
+
+{green}Fastq directory{nc} ___________ '{ylo}{fastq_dir}{nc}'
+{green}  > Fastq processed{nc} ________ {red}{fastq_files}{nc} fastq files
+{green}  > Forward reads{nc} __________ {red}{fastq_R1}{nc} R1
+{green}  > Reverse reads{nc} __________ {red}{fastq_R2}{nc} R2
+
+{blue}Modules:{nc}
+{green}  > Quality Control{nc} ________ {red}{qualities}{nc}
+{green}  > Keep Trim{nc} ______________ {red}{keeptrim}{nc}
+{green}  > Soft Clipping{nc} __________ {red}{cleapping}{nc}
+{green}  > Cov Stats{nc} ______________ {red}{covstats}{nc}
+{green}  > Consensus{nc} ______________ {red}{consensus}{nc}
+{green}  > Lineages{nc} _______________ {red}{lineages}{nc}
+{green}  > Gisaid{nc} _________________ {red}{gisaid}{nc}
+
+{blue}Params:{nc}
+{green}  > Reference genome{nc} _______ {ylo}{reference_conf}{nc}
+{green}  > Mapper{nc} ________________ {ylo}{mapper}{nc}
+{green}  > Min coverage{nc} ___________ {red}{min_cov}{nc} X
+{green}  > Min allele frequency{nc} ___ {red}{min_freq}{nc}
+{green}  > Assigner{nc} ______________ {red}{assigner}{nc}
+{green}    - Nextclade dataset{nc} _____ {red}{nextclade_dataset}{nc}
+{green}  > Fastq-Screen subset{nc} ____ {red}{fastqscreen_subset}{nc}
+{green}  > Cutadapt clipping{nc} ______ {red}{cutadapt_clipping} nt{nc}
+"""
+
+# Print message
+print(message_settings)
+
+# Clean message
+ansi_escape = re.compile(r'\x1B\[[0-9;]*[mK]')
+message_clean = ansi_escape.sub('', message_settings)
+
+# Create log file
+results_dir = os.path.join(workdir, "results", "10_Reports")
+os.makedirs(results_dir, exist_ok=True)
+
+# Write log file
+log_file = os.path.join(results_dir, "settings.log")
+with open(log_file, "w") as logf:
+    logf.write(message_clean)
\ No newline at end of file
-- 
GitLab