Modeling Tumor Growth Using the Gompertz Model

Let’s consider a medical example where we analyze the growth of a tumor over time.

We’ll use $Python$ to model the tumor growth, solve the differential equation, and visualize the results.

Problem Statement

The growth of a tumor can often be modeled using the Gompertz growth model, which is given by the differential equation:

$$
\frac{dV}{dt} = a V \ln\left(\frac{K}{V}\right)
$$

  • $ V(t) $ is the volume of the tumor at time $ t $.
  • $ a $ is the growth rate of the tumor.
  • $ K $ is the carrying capacity, i.e., the maximum volume the tumor can reach.

Python Implementation

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
import numpy as np
from scipy.integrate import solve_ivp
import matplotlib.pyplot as plt

# Define the Gompertz growth model
def gompertz_growth(t, V, a, K):
return a * V * np.log(K / V)

# Parameters
a = 0.1 # Growth rate
K = 1000 # Carrying capacity (maximum tumor volume)
V0 = 10 # Initial tumor volume

# Time span for the solution
t_span = (0, 50) # From t=0 to t=50
t_eval = np.linspace(t_span[0], t_span[1], 300) # Points where the solution is evaluated

# Solve the differential equation
sol = solve_ivp(gompertz_growth, t_span, [V0], args=(a, K), t_eval=t_eval, method='RK45')

# Extract the solution
V = sol.y[0]

# Plot the results
plt.figure(figsize=(10, 6))
plt.plot(sol.t, V, label='Tumor Volume (V)', color='b')
plt.xlabel('Time (t)')
plt.ylabel('Tumor Volume (V)')
plt.title('Tumor Growth Over Time (Gompertz Model)')
plt.legend()
plt.grid(True)
plt.show()

Explanation

  1. Gompertz Growth Model:

The differential equation $\frac{dV}{dt} = a V \ln\left(\frac{K}{V}\right)$ is implemented in the gompertz_growth function.
This function takes the current time t, the current tumor volume V, and the parameters a and K to compute the rate of change of the tumor volume.

  1. Parameters:

    • a = 0.1: This is the growth rate of the tumor.
    • K = 1000: This is the carrying capacity, the maximum volume the tumor can reach.
    • V0 = 10: This is the initial volume of the tumor at time t=0.
  2. Solving the Differential Equation:

We use solve_ivp from scipy.integrate to solve the differential equation.
The method RK45 is a Runge-Kutta method of order $5(4)$, which is suitable for solving non-stiff differential equations.

  1. Plotting the Results:

The tumor volume V is plotted against time t.
The plot shows how the tumor volume grows over time, approaching the carrying capacity K.

Graph Interpretation

  • The tumor volume starts at V0 = 10 and grows rapidly at first.
  • As the tumor volume approaches the carrying capacity K = 1000, the growth rate slows down.
  • The tumor volume asymptotically approaches the carrying capacity, but never exceeds it.

This model is useful in oncology for understanding tumor growth dynamics and planning treatment strategies.

Output

The output will be a graph showing the tumor volume V over time t.

The curve will start at V0 = 10 and gradually approach K = 1000, illustrating the Gompertz growth behavior.

Population-Resource Dynamics

Let’s solve an environmental science problem using $Python$.

We will model Population Dynamics and Resource Consumption, a crucial topic in environmental science to understand sustainability and ecological balance.


Problem Statement

We want to simulate the interactions between a population and a renewable resource:

  • A population consumes a natural resource for survival.
  • The resource regenerates over time but is depleted by consumption.
  • If consumption exceeds regeneration, the resource may collapse, leading to population decline.
  • Conversely, if the resource is abundant, the population may grow.

We will model this using the Lotka-Volterra equations, which are typically used for predator-prey dynamics but can also describe resource-consumer interactions.


Methodology

  1. Population and Resource Dynamics:
    • Population growth is proportional to available resources.
    • Resource regeneration follows logistic growth.
  2. Differential Equations:
    • $ \frac{dR}{dt} = r \cdot R \left(1 - \frac{R}{K}\right) - c \cdot P \cdot R $
    • $ \frac{dP}{dt} = e \cdot c \cdot P \cdot R - m \cdot P $
      • $ R $: Resource quantity
      • $ P $: Population size
      • $ r $: Resource growth rate
      • $ K $: Carrying capacity of the resource
      • $ c $: Consumption rate
      • $ e $: Efficiency of resource to population growth
      • $ m $: Mortality rate of the population
  3. Simulation:
    • Use numerical integration to simulate population-resource dynamics over time.
  4. Visualization:
    • Plot resource and population sizes over time.
    • Phase plot to observe cyclical behavior.

Required Libraries

We’ll use the following libraries:

  • numpy: For numerical calculations.
  • scipy: To solve differential equations.
  • matplotlib: To visualize the results.
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
import numpy as np
from scipy.integrate import solve_ivp
import matplotlib.pyplot as plt

# Parameters
r = 0.5 # Resource growth rate
K = 100 # Resource carrying capacity
c = 0.02 # Consumption rate
e = 0.1 # Efficiency of resource use
m = 0.1 # Mortality rate of population

# Differential equations
def model(t, y):
R, P = y
dRdt = r * R * (1 - R / K) - c * P * R
dPdt = e * c * P * R - m * P
return [dRdt, dPdt]

# Initial conditions
R0 = 80 # Initial resource quantity
P0 = 10 # Initial population size
y0 = [R0, P0]

# Time span
t_span = (0, 200)
t_eval = np.linspace(t_span[0], t_span[1], 1000)

# Solve differential equations
solution = solve_ivp(model, t_span, y0, t_eval=t_eval)

# Extract results
time = solution.t
R = solution.y[0]
P = solution.y[1]

# Plot Resource and Population over Time
plt.figure(figsize=(10, 5))
plt.plot(time, R, label='Resource', color='green')
plt.plot(time, P, label='Population', color='blue')
plt.title('Population and Resource Dynamics Over Time')
plt.xlabel('Time')
plt.ylabel('Quantity')
plt.legend()
plt.grid(True)
plt.show()

# Phase Plot (Resource vs Population)
plt.figure(figsize=(6, 6))
plt.plot(R, P, color='purple')
plt.title('Phase Plot: Resource vs Population')
plt.xlabel('Resource Quantity')
plt.ylabel('Population Size')
plt.grid(True)
plt.show()

Explanation

  1. Differential Equations:
    • The resource grows logistically and is consumed by the population.
    • Population growth is dependent on resource availability.
  2. Numerical Integration:
    We use scipy.integrate.solve_ivp() to numerically solve the differential equations over a specified time span.
  3. Visualization:
    • Time Series Plot: Shows resource and population dynamics over time.
    • Phase Plot: Shows the relationship between resource and population size, revealing cyclical interactions.

Analysis of Results

  1. Time Series Plot:

    • Oscillations in both resource and population sizes indicate cyclical predator-prey-like dynamics.
    • When the resource is abundant, the population grows.
    • As the population consumes the resource, the resource decreases, leading to a population decline.
    • This allows the resource to regenerate, starting the cycle again.
  2. Phase Plot:

    • The cyclical pattern represents the feedback loop between resource availability and population growth.
    • The trajectory suggests a stable limit cycle, indicating sustainable oscillations rather than collapse or unbounded growth.

Environmental Implications

This model illustrates the delicate balance between resource consumption and population growth, relevant for:

  • Sustainability Analysis: Ensuring renewable resources are not overexploited.
  • Conservation Biology: Managing species populations and their habitats.
  • Agricultural Planning: Balancing crop yields with environmental impacts.

Analyzing the Relationship Between Education Level and Income Using Python

Let’s consider a sociological example where we analyze the relationship between education level and income.

We’ll use $Python$ to simulate data, analyze it, and visualize the results.

Example: Education Level and Income

Hypothesis: Higher education levels are associated with higher income.

Step 1: Simulate Data

We’ll create a synthetic dataset where:

  • Education Level is measured in years (e.g., $12$ years for high school, $16$ for a bachelor’s degree, etc.).
  • Income is measured in thousands of dollars per year.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# Set a seed for reproducibility
np.random.seed(42)

# Simulate data
n = 100 # Number of samples
education_level = np.random.randint(12, 21, n) # Years of education (12 to 20 years)
income = 20 * education_level + np.random.normal(0, 10, n) # Income in thousands of dollars

# Create a DataFrame
data = pd.DataFrame({'Education_Level': education_level, 'Income': income})

# Display the first few rows
print(data.head())

Step 2: Analyze the Data

We’ll use a simple linear regression to analyze the relationship between education level and income.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from sklearn.linear_model import LinearRegression

# Prepare the data
X = data[['Education_Level']]
y = data['Income']

# Fit the model
model = LinearRegression()
model.fit(X, y)

# Get the coefficients
slope = model.coef_[0]
intercept = model.intercept_

print(f"Slope (Coefficient for Education Level): {slope}")
print(f"Intercept: {intercept}")

Step 3: Visualize the Results

We’ll plot the data points and the regression line to visualize the relationship.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Plot the data points
plt.figure(figsize=(10, 6))
sns.scatterplot(x='Education_Level', y='Income', data=data, color='blue', label='Data Points')

# Plot the regression line
plt.plot(X, model.predict(X), color='red', label='Regression Line')

# Add labels and title
plt.xlabel('Education Level (Years)')
plt.ylabel('Income (Thousands of Dollars)')
plt.title('Relationship Between Education Level and Income')
plt.legend()

# Show the plot
plt.show()

Step 4: Interpret the Results

   Education_Level      Income
0               18  363.268452
1               15  299.188810
2               19  384.677948
3               16  327.361224
4               18  352.202981
Slope (Coefficient for Education Level): 19.71155398870412
Intercept: 5.404657619066882

  • Slope (Coefficient for Education Level): This value indicates how much income increases for each additional year of education.

For example, if the slope is $20$, it means that for each additional year of education, income increases by $$20,000$ on average.

  • Intercept: This is the expected income when the education level is $0$ years.
    In this context, it may not have a practical interpretation since education level cannot be $0$.

Step 5: Conclusion

The scatter plot with the regression line shows a positive relationship between education level and income.

As education level increases, income tends to increase as well.

This supports our hypothesis that higher education levels are associated with higher income.

Full Code

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
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.linear_model import LinearRegression

# Set a seed for reproducibility
np.random.seed(42)

# Simulate data
n = 100 # Number of samples
education_level = np.random.randint(12, 21, n) # Years of education (12 to 20 years)
income = 20 * education_level + np.random.normal(0, 10, n) # Income in thousands of dollars

# Create a DataFrame
data = pd.DataFrame({'Education_Level': education_level, 'Income': income})

# Display the first few rows
print(data.head())

# Prepare the data
X = data[['Education_Level']]
y = data['Income']

# Fit the model
model = LinearRegression()
model.fit(X, y)

# Get the coefficients
slope = model.coef_[0]
intercept = model.intercept_

print(f"Slope (Coefficient for Education Level): {slope}")
print(f"Intercept: {intercept}")

# Plot the data points
plt.figure(figsize=(10, 6))
sns.scatterplot(x='Education_Level', y='Income', data=data, color='blue', label='Data Points')

# Plot the regression line
plt.plot(X, model.predict(X), color='red', label='Regression Line')

# Add labels and title
plt.xlabel('Education Level (Years)')
plt.ylabel('Income (Thousands of Dollars)')
plt.title('Relationship Between Education Level and Income')
plt.legend()

# Show the plot
plt.show()

This code simulates data, fits a linear regression model, and visualizes the relationship between education level and income.

The results suggest that higher education levels are associated with higher income, which is a common finding in sociological research.

GC content calculation across DNA sequences

I’ll create a bioinformatics example that analyzes DNA sequences and visualizes the results.

We’ll create a program that:

  1. Analyzes GC content across a DNA sequence using a sliding window
  2. Finds potential CpG islands (regions with high GC content)
  3. Visualizes the results
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
import numpy as np
import matplotlib.pyplot as plt

def calculate_gc_content(sequence, window_size=100, step_size=1):
"""
Calculate GC content using a sliding window approach

Args:
sequence (str): DNA sequence
window_size (int): Size of the sliding window
step_size (int): Step size for sliding the window

Returns:
tuple: Positions and corresponding GC contents
"""
positions = []
gc_contents = []

for i in range(0, len(sequence) - window_size + 1, step_size):
window = sequence[i:i + window_size]
gc_count = window.count('G') + window.count('C')
gc_content = (gc_count / window_size) * 100
positions.append(i)
gc_contents.append(gc_content)

return positions, gc_contents

def find_cpg_islands(positions, gc_contents, threshold=60):
"""
Find potential CpG islands based on GC content threshold

Args:
positions (list): List of positions
gc_contents (list): List of GC contents
threshold (float): GC content threshold for CpG islands

Returns:
list: Start positions of potential CpG islands
"""
islands = []
for i, (pos, gc) in enumerate(zip(positions, gc_contents)):
if gc > threshold:
if not islands or pos - islands[-1] > 100: # New island
islands.append(pos)
return islands

# Example DNA sequence (simulated)
np.random.seed(42)
bases = ['A', 'T', 'G', 'C']
sequence = ''.join(np.random.choice(bases, size=1000))

# Add a simulated CpG island
cpg_island = 'GC' * 50 # Create a GC-rich region
sequence = sequence[:400] + cpg_island + sequence[500:]

# Calculate GC content
positions, gc_contents = calculate_gc_content(sequence, window_size=100, step_size=10)

# Find CpG islands
cpg_islands = find_cpg_islands(positions, gc_contents)

# Plotting
plt.figure(figsize=(12, 6))
plt.plot(positions, gc_contents, 'b-', label='GC Content')
plt.axhline(y=60, color='r', linestyle='--', label='CpG Island Threshold')

# Mark CpG islands
for island in cpg_islands:
plt.axvline(x=island, color='g', alpha=0.3)

plt.xlabel('Position in Sequence')
plt.ylabel('GC Content (%)')
plt.title('DNA Sequence Analysis: GC Content and CpG Islands')
plt.legend()
plt.grid(True)
plt.show()

# Print statistics
print(f"Average GC content: {np.mean(gc_contents):.2f}%")
print(f"Number of potential CpG islands: {len(cpg_islands)}")
for i, pos in enumerate(cpg_islands, 1):
print(f"CpG island {i} starts at position {pos}")

Let me explain the code and its components:

  1. Key Functions:

    • calculate_gc_content: Calculates GC content using a sliding window approach
    • find_cpg_islands: Identifies regions with high GC content (potential CpG islands)
  2. Analysis Process:

    • We generate a random DNA sequence of $1000$ bases
    • Insert a simulated CpG island (GC-rich region) in the middle
    • Calculate GC content using a $100$bp window, sliding $10$bp at a time
    • Identify regions where GC content exceeds $60$% as potential CpG islands
  3. Visualization:

    • Blue line shows GC content across the sequence
    • Red dashed line indicates the CpG island threshold ($60$%)
    • Green vertical lines mark the start of potential CpG islands
    • The plot includes proper labels and a legend
  4. Statistics Output:

    Average GC content: 56.00%
    Number of potential CpG islands: 2
    CpG island 1 starts at position 300
    CpG island 2 starts at position 410
    
    • Calculates and displays average GC content
    • Shows the number and positions of potential CpG islands

This example demonstrates several important bioinformatics concepts:

  • Sequence composition analysis
  • Sliding window analysis
  • Feature detection (CpG islands)
  • Data visualization

Ancient Civilizations Population Trends, 3000 BCE - 0 CE

I’ll create a historical data analysis example using $Python$.

Let’s analyze the rise and fall of different ancient civilizations by comparing their estimated population sizes over time.

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
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns

# Create sample historical data
data = {
'Year': [-3000, -2500, -2000, -1500, -1000, -500, 0],
'Egyptian': [0.5, 1.5, 2.0, 3.0, 2.5, 2.0, 1.5],
'Mesopotamian': [0.3, 2.0, 3.0, 2.5, 1.5, 1.0, 0.8],
'Greek': [0.1, 0.2, 0.5, 1.0, 2.0, 3.5, 3.0],
'Roman': [0.0, 0.1, 0.2, 0.5, 1.0, 2.5, 4.0]
}

# Create DataFrame
df = pd.DataFrame(data)

# Calculate total population and peak years for each civilization
analysis_results = {}
for civ in ['Egyptian', 'Mesopotamian', 'Greek', 'Roman']:
peak_value = df[civ].max()
peak_year = df.loc[df[civ].idxmax(), 'Year']
analysis_results[civ] = {
'Peak Population': peak_value,
'Peak Year': peak_year
}

# Create visualization
plt.figure(figsize=(12, 6))
for civ in ['Egyptian', 'Mesopotamian', 'Greek', 'Roman']:
plt.plot(df['Year'], df[civ], marker='o', label=civ)

plt.title('Ancient Civilizations: Estimated Population Growth (Millions)')
plt.xlabel('Year (BCE/CE)')
plt.ylabel('Estimated Population (Millions)')
plt.grid(True, linestyle='--', alpha=0.7)
plt.legend()

# Add annotations for peak points
for civ in ['Egyptian', 'Mesopotamian', 'Greek', 'Roman']:
peak_year = analysis_results[civ]['Peak Year']
peak_pop = analysis_results[civ]['Peak Population']
plt.annotate(f'{civ}\nPeak: {peak_pop}M',
xy=(peak_year, peak_pop),
xytext=(10, 10),
textcoords='offset points')

print("Analysis Results:")
for civ, results in analysis_results.items():
print(f"\n{civ}:")
print(f"Peak Population: {results['Peak Population']} million")
print(f"Peak Year: {results['Peak Year']} {'BCE' if results['Peak Year'] < 0 else 'CE'}")

Let me explain this historical data analysis:

  1. Data Structure:

    • We created a dataset spanning from $3000$ BCE to $0$ CE
    • Tracked estimated populations (in millions) for four major ancient civilizations
    • Used simplified numbers for educational purposes
  2. Analysis Features:

    • Tracks population changes over $3000$ years
    • Identifies peak population periods for each civilization
    • Shows the transition of power between civilizations
    • Visualizes historical overlap between civilizations
  3. Key Findings:

    • Egyptian civilization peaked earliest (around $1500$ BCE)
    • Mesopotamian civilization peaked around $2000$ BCE
    • Greek civilization reached its height around $500$ BCE
    • Roman civilization was still rising at $0$ CE
    • Shows clear patterns of civilizational succession
  4. Visualization Features:

    • Line graph with distinct colors for each civilization
    • Markers showing specific data points
    • Grid lines for easier reading
    • Annotations showing peak points
    • Clear labels and legend

This code demonstrates several historical analysis concepts:

  • Time series analysis of historical data
  • Comparative analysis of concurrent civilizations
  • Identification of peak periods and transitions
  • Visualization of long-term historical trends

Calculating the Hubble Parameter

To explore a cosmology example using $Python$, we can calculate the Hubble parameter at different redshifts and visualize the results.

The Hubble parameter is crucial in cosmology as it describes the rate of expansion of the universe.

1. Theoretical Background

The Hubble parameter $ H(z) $ can be expressed as:

$$
H(z) = H_0 \sqrt{\Omega_m (1 + z)^3 + \Omega_\Lambda}
$$

  • $ H_0 $ is the Hubble constant (approximately $70$ km/s/Mpc).
  • $ \Omega_m $ is the matter density parameter (approximately $0.3$).
  • $ \Omega_\Lambda $ is the dark energy density parameter (approximately $0.7$).
  • $ z $ is the redshift.

2. Python Code Implementation

Here’s how to implement this in $Python$:

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
import numpy as np
import matplotlib.pyplot as plt

# Constants
H0 = 70 # Hubble constant in km/s/Mpc
Omega_m = 0.3 # Matter density parameter
Omega_Lambda = 0.7 # Dark energy density parameter

# Function to calculate Hubble parameter
def hubble_parameter(z):
return H0 * np.sqrt(Omega_m * (1 + z)**3 + Omega_Lambda)

# Redshift values
z_values = np.linspace(0, 3, 100) # From 0 to 3
H_values = hubble_parameter(z_values)

# Plotting
plt.figure(figsize=(10, 6))
plt.plot(z_values, H_values, label='Hubble Parameter H(z)', color='blue')
plt.title('Hubble Parameter vs Redshift')
plt.xlabel('Redshift (z)')
plt.ylabel('Hubble Parameter (km/s/Mpc)')
plt.axhline(y=H0, color='r', linestyle='--', label='H0 = 70 km/s/Mpc')
plt.legend()
plt.grid()
plt.show()

3. Explanation of the Code

  • Imports: We import numpy for numerical calculations and matplotlib.pyplot for plotting.

  • Constants: We define the Hubble constant and density parameters.

  • Function: The hubble_parameter function computes $ H(z) $ using the formula provided.

  • Redshift Values: We create an array of redshift values ranging from $0$ to $3$.

  • Calculation: We calculate the Hubble parameter for each redshift value.

  • Plotting: We use matplotlib to create a plot of the Hubble parameter against redshift.
    A horizontal line indicates the Hubble constant value.

4. Result Interpretation

The graph shows how the Hubble parameter increases with redshift, indicating that the expansion rate of the universe was faster in the past.

The dashed red line represents the current value of the Hubble constant, providing a reference point.

This example illustrates a fundamental concept in cosmology and demonstrates how to use $Python$ for calculations and visualizations in this field.

Radioactive Decay and Half-Life Calculation

Example in Nuclear Physics

Problem Statement:

A radioactive substance undergoes exponential decay, which can be described by the equation:
$$
N(t) = N_0 e^{-\lambda t}
$$

  • $N(t)$ is the number of undecayed nuclei at time $t$.
  • $N_0$ is the initial number of nuclei.
  • $\lambda$ is the decay constant.
  • $t$ is time.

The half-life ($T_{1/2}$) of the substance is related to $\lambda$ by:
$$
T_{1/2} = \frac{\ln(2)}{\lambda}
$$

Task:

  1. Simulate radioactive decay for a sample of $1000$ nuclei over $10$ half-lives.
  2. Plot the number of remaining nuclei as a function of time.
  3. Verify that at $T_{1/2}$, half of the original nuclei remain.

Python Implementation

Below is the $Python$ code to solve and visualize the decay process.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import numpy as np
import matplotlib.pyplot as plt

# Constants
N0 = 1000 # Initial number of nuclei
half_life = 5 # Half-life in arbitrary time units
lambda_ = np.log(2) / half_life # Decay constant

time = np.linspace(0, 10 * half_life, 1000) # Time from 0 to 10 half-lives
N_t = N0 * np.exp(-lambda_ * time) # Decay equation

# Plot results
plt.figure(figsize=(8, 5))
plt.plot(time, N_t, label=f"Radioactive Decay (Half-life = {half_life} units)", color='blue')
plt.axvline(half_life, linestyle='--', color='red', label=f"T_1/2 = {half_life} units")
plt.axhline(N0/2, linestyle='--', color='green', label=f"N = {N0//2} at T_1/2")

plt.xlabel("Time")
plt.ylabel("Remaining Nuclei")
plt.title("Exponential Radioactive Decay")
plt.legend()
plt.grid()
plt.show()

Explanation of the Code

  1. Initialization:

    • The initial number of nuclei is set to $1000$.
    • The half-life is defined as $5$ arbitrary time units.
    • The decay constant $\lambda$ is calculated using $\lambda = \ln(2)/T_{1/2}$.
  2. Simulation:

    • Time is generated as an array from $0$ to $10$ half-lives.
    • The number of remaining nuclei is computed using the exponential decay formula.
  3. Visualization:

    • A plot is generated showing the decay curve.
    • A vertical dashed line marks $T_{1/2}$.
    • A horizontal dashed line marks $N_0/2$, verifying that half of the nuclei remain at $T_{1/2}$.

This provides a clear illustration of radioactive decay over time.

Modeling First-Order Chemical Reactions

Let’s explore a problem in Chemistry related to chemical kinetics, specifically the rate of a first-order reaction.

A first-order reaction is one where the rate of reaction depends linearly on the concentration of a single reactant.


Problem Statement

We will model the concentration of a reactant over time for a first-order reaction and plot the concentration as a function of time.
The rate law for a first-order reaction is given by:
$$
\frac{d[A]}{dt} = -k[A]
$$

  • $ [A] $ = concentration of the reactant
  • $ k $ = rate constant
  • $ t $ = time

The integrated rate law for a first-order reaction is:
$$
[A] = [A]_0 e^{-kt}
$$

  • $ [A]_0 $ = initial concentration of the reactant

Python Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import numpy as np
import matplotlib.pyplot as plt

# Parameters
A0 = 1.0 # Initial concentration in mol/L
k = 0.1 # Rate constant in s^-1
time = np.linspace(0, 50, 500) # Time range from 0 to 50 seconds

# Calculate concentration over time
A = A0 * np.exp(-k * time)

# Plot concentration vs time
plt.figure(figsize=(10, 6))
plt.plot(time, A, color='blue', linewidth=2, label='[A]')
plt.title('First-Order Reaction: Concentration vs Time')
plt.xlabel('Time (s)')
plt.ylabel('Concentration [A] (mol/L)')
plt.grid(True)

# Highlight half-life
half_life = np.log(2) / k
plt.axvline(x=half_life, color='red', linestyle='--', label=f'Half-life = {half_life:.2f} s')
plt.legend()
plt.show()

Explanation

  1. Rate Law:

    • The rate of a first-order reaction is proportional to the concentration of the reactant:
      $$
      \frac{d[A]}{dt} = -k[A]
      $$
  2. Integrated Rate Law:

    • The integrated rate law for a first-order reaction is:
      $$
      [A] = [A]_0 e^{-kt}
      $$
    • This equation describes how the concentration of the reactant decreases exponentially over time.
  3. Parameters:

    • $ [A]_0 = 1.0 \text{mol/L} $: Initial concentration of the reactant.
    • $ k = 0.1 \text{s}^{-1} $: Rate constant.
  4. Time Range:

    • We define a time range from $0$ to $50$ seconds using np.linspace.
  5. Plotting:

    • The concentration $ [A] $ is plotted as a function of time.
    • A vertical dashed line is added to highlight the half-life of the reaction.

Result

The graph shows the concentration of the reactant $ [A] $ as a function of time:

  • At $ t = 0 $, the concentration is $ [A]_0 = 1.0 , \text{mol/L} $.
  • As time increases, the concentration decreases exponentially.
  • The half-life $( t_{1/2} )$ is the time required for the concentration to reduce to half of its initial value.
    For this reaction, the half-life is:
    $$
    t_{1/2} = \frac{\ln(2)}{k} \approx 6.93 \text{s}
    $$

Interpretation

  • Exponential Decay: The concentration of the reactant decreases exponentially over time, which is characteristic of first-order kinetics.
  • Half-Life: The half-life is constant for a first-order reaction and is independent of the initial concentration.
    This is a key feature of first-order reactions.

This example demonstrates how $Python$ can be used to model and visualize chemical kinetics, providing insights into the behavior of chemical reactions.

Electronic Band Structure in a 1D Crystal

Example Problem

In solid-state physics, one of the fundamental concepts is the electronic band structure.

A simple way to model this is using the tight-binding approximation for a 1D crystal with a single atomic orbital per site.

The energy dispersion relation for a one-dimensional crystal with lattice constant $ a $ and hopping energy $ t $ is given by:

$$
E(k) = E_0 - 2t \cos(ka)
$$

  • $ E(k) $ is the energy of the electron,
  • $ E_0 $ is the on-site energy,
  • $ t $ is the hopping integral,
  • $ k $ is the wave vector, and
  • $ a $ is the lattice constant.

This function represents a simple tight-binding model for a one-dimensional solid.


Python Implementation

Let’s compute and visualize the electronic band structure using $Python$.

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
import numpy as np
import matplotlib.pyplot as plt

# Define parameters
a = 1.0 # Lattice constant
E0 = 0.0 # On-site energy
t = 1.0 # Hopping integral

# Define k values in the first Brillouin zone
k = np.linspace(-np.pi/a, np.pi/a, 500)

# Compute energy band structure
E_k = E0 - 2 * t * np.cos(k * a)

# Plot the band structure
plt.figure(figsize=(8, 5))
plt.plot(k, E_k, label="$E(k) = E_0 - 2t \cos(ka)$", color='b')
plt.axhline(0, color='black', linewidth=0.5, linestyle='--')
plt.axvline(0, color='black', linewidth=0.5, linestyle='--')
plt.xlabel("Wave vector k")
plt.ylabel("Energy E(k)")
plt.title("Electronic Band Structure in 1D Crystal")
plt.legend()
plt.grid()
plt.show()

Explanation

  1. We define the lattice constant $( a )$, on-site energy $( E_0 )$, and hopping integral $( t )$.
  2. We generate wave vectors $ k $ within the first Brillouin zone $ -\pi/a \leq k \leq \pi/a $.
  3. We compute the energy dispersion using $ E(k) = E_0 - 2t \cos(ka) $.
  4. We plot $ E(k) $ as a function of $ k $, showing the band structure of the 1D crystal.

Interpretation

  • The energy band has a cosine shape, typical for tight-binding models.
  • The bandwidth (difference between maximum and minimum $ E(k) $ ) is $ 4t $.
  • The band is symmetric around $ k = 0 $ due to the periodic nature of the lattice.

This is a basic yet powerful model for understanding electronic band structures in solids.

Diffusion of Molecules in a Cell

Problem

In biophysics, diffusion is a fundamental process governing the movement of molecules inside biological cells.

The movement of molecules follows Fick’s Second Law of Diffusion:

$$
\frac{\partial C}{\partial t} = D \frac{\partial^2 C}{\partial x^2}
$$

  • $ C(x,t) $ = Concentration of molecules at position $ x $ and time $ t $,
  • $ D $ = Diffusion coefficient ($m²/s$).

We will solve the 1D diffusion equation for a Gaussian initial distribution using the finite difference method and visualize how molecules spread over time.

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
import numpy as np
import matplotlib.pyplot as plt

# Constants
D = 1e-9 # Diffusion coefficient (m²/s)
L = 1e-3 # Length of the domain (m)
nx = 100 # Number of spatial points
dx = L / nx # Spatial step
dt = 0.1 # Time step (s)
time_steps = 500 # Number of time steps

# Spatial grid
x = np.linspace(0, L, nx)

# Initial concentration (Gaussian distribution)
C = np.exp(-((x - L/2)**2 / (2 * (L/10)**2)))

# Time evolution using the finite difference method
for _ in range(time_steps):
C[1:-1] = C[1:-1] + D * dt / dx**2 * (C[2:] - 2*C[1:-1] + C[:-2])

# Plot results
plt.figure(figsize=(10, 6))
plt.plot(x * 1e3, C, color='blue', linewidth=2)
plt.title('1D Diffusion of Molecules in a Cell', fontsize=16)
plt.xlabel('Position (mm)', fontsize=14)
plt.ylabel('Concentration (arbitrary units)', fontsize=14)
plt.grid(True)
plt.show()

Explanation of the Code

  1. Constants:

    • D = 1e-9: Diffusion coefficient (e.g., small molecules in water).
    • L = 1e-3: Domain length (1 $mm$, representing a cellular environment).
    • dx: Spatial step.
    • dt: Time step.
  2. Initial Condition:

    • Gaussian distribution at the center, simulating a localized molecular release.
  3. Numerical Solution:

    • Finite Difference Method updates concentration over time using Fick’s Law.
  4. Plotting:

    • X-axis: Position in mm.
    • Y-axis: Concentration.
    • The spread of molecules is observed as time progresses.

Interpreting the Graph

  • Initially, molecules are concentrated at the center.
  • Over time, diffusion spreads the concentration evenly.
  • This is crucial in drug delivery and nutrient transport in cells.