Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

1. Intro / How to manage your Python Project

30th October 2025

For our first session, we (Sophie & Lawrence) gave an introduction to the workshop series and covered some tips & tricks on Python code development.

Session Recording

If you are having trouble viewing it above, try using the link directly.

Code examples

Below are some of the code examples that were shared during the session.

Here was an example of bad coding practice (hard coded values, poor variable naming, no comments or docstrings, etc.):

example_bad_code.py
# Script to process neuroimaging data for two subjects
# Requires numpy and nibabel
# pip install nibabel numpy

import numpy as n
import nibabel as ni

THR = 150
S_SIZE = 64

# =======================================================
#               PROCESSING FOR SUBJ_001
# =======================================================


dat1 = n.random.randint(0, 300, size=(S_SIZE, S_SIZE, S_SIZE), dtype=n.int16)
SCALAR_VAL = 2.0
hdr1 = n.array([[SCALAR_VAL, 0., 0., -100.],
                 [0., SCALAR_VAL, 0., -100.],
                 [0., 0., SCALAR_VAL, -100.],
                 [0., 0., 0., 1.  ]])
img1 = ni.Nifti1Image(dat1, hdr1)
print(f"Loaded image data for Subj 001 with shape: {dat1.shape}")

a = n.mean(dat1)
b = n.max(dat1)
c = n.min(dat1)

print(f"Subj 001 Stats: Mean={a:.2f}, Max={b}, Min={c}")

p_dat = n.copy(dat1)
p_dat[p_dat < THR] = 0
print(f"Applied threshold {THR} to Subj 001 data.")

out_dat_1 = ni.Nifti1Image(p_dat, hdr1)
ni.save(out_dat_1, 'test/results/s1_th_img.nii.gz')
print(f"Saved processed data for Subj 001.")


# =======================================================
#               PROCESSING FOR SUBJ_002
# =======================================================

S_SIZE = 128

dat2 = n.random.randint(0, 300, size=(S_SIZE, S_SIZE, S_SIZE), dtype=n.int16)
A_SCALAR = 2.0
hdr2 = n.array([[A_SCALAR, 0., 0., -100.],
                 [0., A_SCALAR, 0., -100.],
                 [0., 0., A_SCALAR, -100.],
                 [0., 0., 0., 1.  ]])
img2 = ni.Nifti1Image(dat2, hdr2)
print(f"Loaded image data for Subj 002 with shape: {dat2.shape}")

a2 = n.mean(dat2)
b2 = n.max(dat2)
c2 = n.min(dat2)

print(f"Subj 002 Stats: Mean={a2:.2f}, Max={b2}, Min={c2}")

p_dat2 = n.copy(dat2)
p_dat2[p_dat2 < THR] = 0
print(f"Applied threshold {THR} to Subj 002 data.")

out_dat_2 = ni.Nifti1Image(p_dat2, hdr2)
ni.save(out_dat_2, 'test/results/s1_th_img.nii.gz')
print(f"Saved processed data for Subj 002.")

Then we looked at how argparse can be used to provide inputs to a function or script.

argsparse_example.py
import argparse

def print_message(text):
    print(f"Your messsage is: {text}")

#%% Parse information 
parser = argparse.ArgumentParser()
parser.add_argument('--message', dest='text_message', help='A simple text message to print', required=True)
args = parser.parse_args()

# call function to do correction
print_message(args.text_message)

This can be useful when working with the cluster and submitting scripts or batch jobs where you may not want to hard code certain input parameters or arguments (like absolute filepaths). Here is an example bash script that can be used to submit the above code example.

For full details and instructions on using the UCL CS Cluster, visit the HPC website.

run_argsparse_example.sh
#!/bin/bash -l

# Example script 

# Request Time (format hours:minutes:seconds).
#$ -l h_rt=XX:XX:XX
# Request RAM per core. 
#$ -l tmem=XXG
#$ -l h_vmem=XXG
#$ -R y
#$ -pe smp XX

#$ -o /YOUR/OUTPUT/PATH # folder to store the shell outputs

#Set Name 
#$ -N EXAMPLE

date
hostname

#Setup python 
source /share/apps/source_files/python/python-3.9.5.source

# Loop over arguments looking for -i and -o
args=("$@")
i=0
while [ $i -lt $# ]; do
    #Set npy data 
    if ( [ ${args[i]} = "-message" ] ) ; then
        let i=$i+1
        text_message=${args[i]}
    elif  ( [ ${args[i]} = "-script" ] ) ; then
        let i=$i+1
        script_to_run=${args[i]}
    fi 
    let i=$i+1
done

# Check if user gave correct inputs
if [[ -z "${text_message}" ]] || [[ -z "${script_to_run}" ]]; then
    correct_input=0
else 
    correct_input=1
fi

#Check the user has provided the correct inputs
if ( [[ ${correct_input} -eq 0 ]] ) ; then
  echo ""
  echo "Incorrect input. Please see below for correct use"
  echo ""
  echo "Options:"
  echo " -message:         A simple text message  -- REQUIRED"
  echo " -script:          A python script setup with arsparse  -- REQUIRED"
  echo ""
  echo "${script_name} -script /PATH/TO/argsparse_example.py -message "Hello world""
  echo ""
  exit
fi

echo "Calling Python Script"
python3 ${script_to_run} --message ${text_message}

Slides

To be updated.