File size: 11,771 Bytes
cfcbbc8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
#!/bin/bash
#
# run_smk_sequential.sh - Run Snakemake workflows one at a time for debugging
#
# This script runs each Snakemake workflow sequentially to observe
# the behavior of prompt scripts, supervisor, and coder in real time.
#
# Usage:
#   ./run_smk_sequential.sh                    # Run all steps
#   ./run_smk_sequential.sh --step1           # Run summarize_root (both rules)
#   ./run_smk_sequential.sh --step2           # Run create_numpy
#   ./run_smk_sequential.sh --step3           # Run preprocess
#   ./run_smk_sequential.sh --step4           # Run scores
#   ./run_smk_sequential.sh --step5           # Run categorization
#   ./run_smk_sequential.sh --step1 --step3   # Run summarize_root + preprocess
#

if [ -f ~/.apikeys.sh ]; then
    source ~/.apikeys.sh
fi

# Parse command line arguments
RUN_STEP1=false
RUN_STEP2=false
RUN_STEP3=false
RUN_STEP4=false
RUN_STEP5=false
VALIDATE_STEPS=false
OUTPUT_DIR="results"
CONFIG="config.yml"

# Remember the project root where this script is invoked
PROJECT_ROOT="$(pwd)"


while [[ $# -gt 0 ]]; do
    case $1 in
        --step1)
            RUN_STEP1=true
            shift
            ;;
        --step2)
            RUN_STEP2=true
            shift
            ;;
        --step3)
            RUN_STEP3=true
            shift
            ;;
        --step4)
            RUN_STEP4=true
            shift
            ;;
        --step5)
            RUN_STEP5=true
            shift
            ;;
        --validate)
            VALIDATE_STEPS=true
            shift
            ;;
        --out-dir)
            OUTPUT_DIR="$2"
            shift
            shift
            ;;
        --job-id)
            # Create unique directory based on job ID
            OUTPUT_DIR="results_job_$2"
            shift
            shift
            ;;
        --auto-dir)
            # Create unique directory with timestamp
            TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
            OUTPUT_DIR="results_${TIMESTAMP}"
            shift
            ;;
        --config)
            CONFIG="$2"
            shift
            shift
            ;;
        --help|-h)
            echo "Usage: $0 [OPTIONS]"
            echo ""
            echo "Run Snakemake workflows for ATLAS analysis"
            echo ""
            echo "Options:"
            echo "  --step1    Run summarize_root workflow (both rules: data generation + prompt processing)"
            echo "  --step2    Run create_numpy workflow"
            echo "  --step3    Run preprocess workflow"
            echo "  --step4    Run scores workflow"
            echo "  --step5    Run categorization workflow"
            echo "  --validate    Run validation after each successful step"
            echo "  --out-dir DIR    Custom output directory (default: results)"
            echo "  --job-id ID    Create unique directory: results_job_ID"
            echo "  --auto-dir    Create unique directory with timestamp: results_YYYYMMDD_HHMMSS"
            echo "  --help     Show this help message"
            echo ""
            echo "Examples:"
            echo "  $0 --step1 --auto-dir              # results_20250916_143052/"
            echo "  $0 --step1 --job-id 12345          # results_job_12345/"
            echo "  $0 --step1 --out-dir my_run_1      # my_run_1/"
            echo ""
            echo "If no options are provided, all steps are run sequentially."
            exit 0
            ;;
        *)
            echo "Unknown option: $1"
            echo "Use --help for usage information"
            exit 1
            ;;
    esac
done

# If no specific steps requested, run all
if [[ "$RUN_STEP1" == "false" && "$RUN_STEP2" == "false" && "$RUN_STEP3" == "false" && "$RUN_STEP4" == "false" && "$RUN_STEP5" == "false" ]]; then
    RUN_STEP1=true
    RUN_STEP2=true
    RUN_STEP3=true
    RUN_STEP4=true
    RUN_STEP5=true
    echo "=== Running All Snakemake Workflows Sequentially (Output: ${OUTPUT_DIR}) ==="
else
    echo "=== Running Selected Snakemake Workflows (Output: ${OUTPUT_DIR}) ==="
fi
echo ""

# Set up environment
module load python
conda activate llm_env

# Resolve config file to an absolute path so Snakemake can always find it
if [[ "${CONFIG}" = /* ]]; then
    CONFIG_PATH="${CONFIG}"
else
    CONFIG_PATH="${PROJECT_ROOT}/${CONFIG}"
fi

if [[ ! -f "${CONFIG_PATH}" ]]; then
    echo "❌ Config file not found at ${CONFIG_PATH}"
    exit 1
fi

# Copy and prepare workflow files

OUTPUT_DIR="${OUTPUT_DIR%/}"
if [[ "${OUTPUT_DIR}" = /* ]]; then
    BASE_DIR="${OUTPUT_DIR}"
else
    BASE_DIR="$PWD/${OUTPUT_DIR}"
fi

echo "Preparing workflow files..."
mkdir -p ${OUTPUT_DIR}/prompts_temp
cp -r prompts/* ${OUTPUT_DIR}/prompts_temp/
sed -i "s#{BASE_DIR}#${BASE_DIR}#g" ${OUTPUT_DIR}/prompts_temp/*.txt

cp workflow/summarize_root.smk ${OUTPUT_DIR}/summarize_root_temp.smk
cp workflow/create_numpy.smk ${OUTPUT_DIR}/create_numpy_temp.smk
cp workflow/preprocess.smk ${OUTPUT_DIR}/preprocess_temp.smk
cp workflow/scores.smk ${OUTPUT_DIR}/scores_temp.smk
cp workflow/categorization.smk ${OUTPUT_DIR}/categorization_temp.smk
cp supervisor_coder.py ${OUTPUT_DIR}/supervisor_coder.py
cp write_prompt.py ${OUTPUT_DIR}/write_prompt.py
cp check_soln.py ${OUTPUT_DIR}/check_soln.py

sed -i "s#{BASE_DIR}#${BASE_DIR}#g" ${OUTPUT_DIR}/*_temp.smk
# Replace {CONFIG} in temp snakemake files with the absolute path to the project's config
sed -i "s#{CONFIG}#${CONFIG_PATH}#g" ${OUTPUT_DIR}/*_temp.smk

# Copy solutions for validation
echo "Copying reference solution arrays for validation..."
mkdir -p ${OUTPUT_DIR}/solution/arrays
# Remove any existing files first to avoid permission issues
rm -f ${OUTPUT_DIR}/solution/arrays/*
cp solution/arrays/* ${OUTPUT_DIR}/solution/arrays/

# Create output directory
mkdir -p ${OUTPUT_DIR}/generated_code
mkdir -p ${OUTPUT_DIR}/logs
cp utils.py ${OUTPUT_DIR}/generated_code/utils.py

# Clean up any existing numpy files (store metrics under logs)
rm -f ${OUTPUT_DIR}/logs/success.npy ${OUTPUT_DIR}/logs/calls.npy ${OUTPUT_DIR}/logs/input_tokens.npy ${OUTPUT_DIR}/logs/output_tokens.npy

echo "Starting sequential execution..."
echo ""

# Function to run a single workflow
run_workflow() {
    local workflow_name=$1
    local smk_file=$2
    local target=$3
    local step_number=$4

    echo "========================================="
    echo "Running: $workflow_name"
    echo "Target: $target"
    echo "Time: $(date)"
    echo "========================================="

    # cd into OUTPUT_DIR and do all the work there
    if ! pushd "$OUTPUT_DIR" > /dev/null; then
        echo "❌ Failed to cd into $OUTPUT_DIR"
        return 1
    fi

    # Print the command that will be executed (run inside ${OUTPUT_DIR})
    # Commented out original with --stats, kept for reference
    # echo "Command: snakemake -s \"$smk_file\" -j 1 --forcerun \"$target\" --rerun-incomplete --configfile \"${CONFIG}\" --latency-wait 120 --verbose --stats logs/${workflow_name}.stats > logs/${workflow_name}.log 2>&1"
    echo "Command: snakemake -s \"$smk_file\" -j 1 --forcerun \"$target\" --rerun-incomplete --configfile \"${CONFIG}\" --latency-wait 120 --verbose > logs/${workflow_name}.log 2>&1"
    echo ""

    local start_time=$SECONDS

    # Run snakemake from inside the output directory. Use BASE_DIR for the config file
    # so Snakemake can find the main config.yml even when cwd is the job folder.
    # Original Snakemake run with --stats (commented out)
    # if snakemake -s "$smk_file" -j 1 --forcerun "$target" --rerun-incomplete --configfile "${CONFIG}" --latency-wait 120 --verbose --stats "logs/${workflow_name}.stats" > "logs/${workflow_name}.log" 2>&1; then
    if snakemake -s "$smk_file" -j 1 --forcerun "$target" --rerun-incomplete --configfile "${CONFIG_PATH}" --latency-wait 120 --verbose > "logs/${workflow_name}.log" 2>&1; then
        local duration=$((SECONDS - start_time))
        echo ""
        echo "✅ $workflow_name completed successfully in ${duration}s"
        echo ""
        
        # Run validation for this step if it completed successfully
        if [[ "$VALIDATE_STEPS" == "true" ]]; then
            echo "Running validation for Step $step_number..."
                if python check_soln.py --out_dir "${BASE_DIR}" --step $step_number >> "logs/${workflow_name}_validation.log" 2>&1; then
                echo "✅ Step $step_number validation completed"
                # Check if validation passed
                if [[ -f "${OUTPUT_DIR}/logs/success.npy" ]]; then
                    validation_result=$(python -c "import numpy as np; print(np.load('${OUTPUT_DIR}/logs/success.npy')[$step_number-1])")
                    if [[ "$validation_result" == "1" ]]; then
                        echo "✅ Step $step_number validation: PASS"
                    else
                        echo "❌ Step $step_number validation: FAIL"
                    fi
                fi
            else
                echo "❌ Step $step_number validation failed to run"
            fi
            echo ""
        fi
        popd > /dev/null
        return 0
    else
        local duration=$((SECONDS - start_time))
        echo ""
        echo "❌ $workflow_name failed after ${duration}s"
        echo ""
        popd > /dev/null
        return 1
    fi
}

# Run workflows sequentially based on flags
step_counter=1

if [[ "$RUN_STEP1" == "true" ]]; then
    echo "$step_counter. Running summarize_root workflow (both rules)..."
    # Run both rules: first summarize_root, then insert_root_summary
    run_workflow "summarize_root" "summarize_root_temp.smk" "summarize_root" 1
    run_workflow "insert_root_summary" "summarize_root_temp.smk" "insert_root_summary" 1
    ((step_counter++))
fi

if [[ "$RUN_STEP2" == "true" ]]; then
    echo "$step_counter. Running create_numpy workflow..."
    run_workflow "create_numpy" "create_numpy_temp.smk" "create_numpy" 2
    ((step_counter++))
fi

if [[ "$RUN_STEP3" == "true" ]]; then
    echo "$step_counter. Running preprocess workflow..."
    run_workflow "preprocess" "preprocess_temp.smk" "preprocess" 3
    ((step_counter++))
fi

if [[ "$RUN_STEP4" == "true" ]]; then
    echo "$step_counter. Running scores workflow..."
    run_workflow "scores" "scores_temp.smk" "scores" 4
    ((step_counter++))
fi

if [[ "$RUN_STEP5" == "true" ]]; then
    echo "$step_counter. Running categorization workflow..."
    run_workflow "categorization" "categorization_temp.smk" "categorization" 5
    ((step_counter++))
fi

echo ""
echo "=== Sequential Execution Complete ==="
echo "Check ${OUTPUT_DIR}/ for output files"
echo "Check ${OUTPUT_DIR}/logs/*.log files for detailed logs"
if [[ "$VALIDATE_STEPS" == "true" ]]; then
    echo "Check ${OUTPUT_DIR}/logs/*_validation.log files for validation results"
fi

# Optional: Run final comprehensive validation (only if all steps were run)
if [[ "$RUN_STEP1" == "true" && "$RUN_STEP2" == "true" && "$RUN_STEP3" == "true" && "$RUN_STEP4" == "true" && "$RUN_STEP5" == "true" ]]; then
    echo ""
    if [[ "$VALIDATE_STEPS" == "false" ]]; then
        read -p "Run final comprehensive validation? (y/n): " -n 1 -r
        echo ""
        if [[ $REPLY =~ ^[Yy]$ ]]; then
            echo "Running final comprehensive validation..."
            python check_soln.py --out_dir ${OUTPUT_DIR}
        fi
    else
        echo "Running final comprehensive validation..."
        python check_soln.py --out_dir ${OUTPUT_DIR}
    fi
else
    echo ""
    echo "Note: Final comprehensive validation skipped (not all steps were run)"
fi

# Clean up
echo ""
# echo "Cleaning up temporary files..."
# Comment out the next line to keep prompts_temp for inspection
# rm -rf prompts_temp
# rm -f *_temp.smk
# rm -rf .snakemake  # Clean up Snakemake's default log directory

echo -e "Done!\n"