Material for ASPP 2024
This commit is contained in:
		
						commit
						849682b13b
					
				
					 97 changed files with 8170 additions and 0 deletions
				
			
		
							
								
								
									
										286
									
								
								notebooks/walker/Step_0_Introduction/Step_0_Introduction.ipynb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										286
									
								
								notebooks/walker/Step_0_Introduction/Step_0_Introduction.ipynb
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								notebooks/walker/Step_0_Introduction/show
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								notebooks/walker/Step_0_Introduction/show
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
 | 
			
		||||
							
								
								
									
										81
									
								
								notebooks/walker/Step_0_Introduction/walker.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								notebooks/walker/Step_0_Introduction/walker.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,81 @@
 | 
			
		|||
import numpy as np
 | 
			
		||||
import matplotlib.pyplot as plt
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def sample_next_step(current_i, current_j, sigma_i, sigma_j, context_map,
 | 
			
		||||
                     random_state=np.random):
 | 
			
		||||
    """ Sample a new position for the walker. """
 | 
			
		||||
 | 
			
		||||
    # Combine the next-step proposal with the context map to get a next-step
 | 
			
		||||
    # probability map
 | 
			
		||||
    size = context_map.shape[0]
 | 
			
		||||
    next_step_map = next_step_proposal(current_i, current_j, sigma_i, sigma_j,
 | 
			
		||||
                                       size)
 | 
			
		||||
    next_step_probability = compute_next_step_probability(next_step_map,
 | 
			
		||||
                                                          context_map)
 | 
			
		||||
 | 
			
		||||
    # Draw a new position from the next-step probability map
 | 
			
		||||
    r = random_state.rand()
 | 
			
		||||
    cumulative_map = np.cumsum(next_step_probability)
 | 
			
		||||
    cumulative_map = cumulative_map.reshape(next_step_probability.shape)
 | 
			
		||||
    i_next, j_next = np.argwhere(cumulative_map >= r)[0]
 | 
			
		||||
 | 
			
		||||
    return i_next, j_next
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def next_step_proposal(current_i, current_j, sigma_i, sigma_j, size):
 | 
			
		||||
    """ Create the 2D proposal map for the next step of the walker. """
 | 
			
		||||
    # 2D Gaussian distribution , centered at current position,
 | 
			
		||||
    # and with different standard deviations for i and j
 | 
			
		||||
    grid_ii, grid_jj = np.mgrid[0:size, 0:size]
 | 
			
		||||
    rad = (
 | 
			
		||||
        (((grid_ii - current_i) ** 2) / (sigma_i ** 2))
 | 
			
		||||
        + (((grid_jj - current_j) ** 2) / (sigma_j ** 2))
 | 
			
		||||
    )
 | 
			
		||||
    p_next_step = np.exp(-(rad / 2.0)) / (2.0 * np.pi * sigma_i * sigma_j)
 | 
			
		||||
    return p_next_step / p_next_step.sum()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def compute_next_step_probability(next_step_map, context_map):
 | 
			
		||||
    """ Compute the next step probability map from next step proposal and
 | 
			
		||||
    context map. """
 | 
			
		||||
    next_step_probability = next_step_map * context_map
 | 
			
		||||
    next_step_probability /= next_step_probability.sum()
 | 
			
		||||
    return next_step_probability
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def create_context_map(size, map_type='flat'):
 | 
			
		||||
    """ Create a fixed context map. """
 | 
			
		||||
    if map_type == 'flat':
 | 
			
		||||
        context_map = np.ones((size, size))
 | 
			
		||||
    elif map_type == 'hills':
 | 
			
		||||
        grid_ii, grid_jj = np.mgrid[0:size, 0:size]
 | 
			
		||||
        i_waves = np.sin(grid_ii / 130) + np.sin(grid_ii / 10)
 | 
			
		||||
        i_waves /= i_waves.max()
 | 
			
		||||
        j_waves = np.sin(grid_jj / 100) + np.sin(grid_jj / 50) + \
 | 
			
		||||
            np.sin(grid_jj / 10)
 | 
			
		||||
        j_waves /= j_waves.max()
 | 
			
		||||
        context_map = j_waves + i_waves
 | 
			
		||||
    elif map_type == 'labyrinth':
 | 
			
		||||
        context_map = np.ones((size, size))
 | 
			
		||||
        context_map[50:100, 50:60] = 0
 | 
			
		||||
        context_map[20:89, 80:90] = 0
 | 
			
		||||
        context_map[90:120, 0:10] = 0
 | 
			
		||||
        context_map[120:size, 30:40] = 0
 | 
			
		||||
        context_map[180:190, 50:60] = 0
 | 
			
		||||
 | 
			
		||||
        context_map[50:60, 50:200] = 0
 | 
			
		||||
        context_map[179:189, 80:130] = 0
 | 
			
		||||
        context_map[110:120, 0:190] = 0
 | 
			
		||||
        context_map[120:size, 30:40] = 0
 | 
			
		||||
        context_map[180:190, 50:60] = 0
 | 
			
		||||
    context_map /= context_map.sum()
 | 
			
		||||
    return context_map
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def plot_trajectory(trajectory, context_map):
 | 
			
		||||
    """ Plot a trajectory over a context map. """
 | 
			
		||||
    trajectory = np.asarray(trajectory)
 | 
			
		||||
    plt.matshow(context_map)
 | 
			
		||||
    plt.plot(trajectory[:, 1], trajectory[:, 0], color='r')
 | 
			
		||||
    plt.show()
 | 
			
		||||
							
								
								
									
										208
									
								
								notebooks/walker/Step_1_classes/Step_1_classes_exercise.ipynb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								notebooks/walker/Step_1_classes/Step_1_classes_exercise.ipynb
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								notebooks/walker/Step_1_classes/exercise
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								notebooks/walker/Step_1_classes/exercise
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
 | 
			
		||||
							
								
								
									
										200
									
								
								notebooks/walker/Step_1_classes/solution/Step_1_classes.ipynb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										200
									
								
								notebooks/walker/Step_1_classes/solution/Step_1_classes.ipynb
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										91
									
								
								notebooks/walker/Step_1_classes/solution/walker.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								notebooks/walker/Step_1_classes/solution/walker.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,91 @@
 | 
			
		|||
import numpy as np
 | 
			
		||||
import matplotlib.pyplot as plt
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Walker:
 | 
			
		||||
    """ The Walker knows how to walk at random on a context map. """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, sigma_i, sigma_j, size, map_type='flat'):
 | 
			
		||||
        self.sigma_i = sigma_i
 | 
			
		||||
        self.sigma_j = sigma_j
 | 
			
		||||
        self.size = size
 | 
			
		||||
 | 
			
		||||
        if map_type == 'flat':
 | 
			
		||||
            context_map = np.ones((size, size))
 | 
			
		||||
        elif map_type == 'hills':
 | 
			
		||||
            grid_ii, grid_jj = np.mgrid[0:size, 0:size]
 | 
			
		||||
            i_waves = np.sin(grid_ii / 130) + np.sin(grid_ii / 10)
 | 
			
		||||
            i_waves /= i_waves.max()
 | 
			
		||||
            j_waves = np.sin(grid_jj / 100) + np.sin(grid_jj / 50) + \
 | 
			
		||||
                np.sin(grid_jj / 10)
 | 
			
		||||
            j_waves /= j_waves.max()
 | 
			
		||||
            context_map = j_waves + i_waves
 | 
			
		||||
        elif map_type == 'labyrinth':
 | 
			
		||||
            context_map = np.ones((size, size))
 | 
			
		||||
            context_map[50:100, 50:60] = 0
 | 
			
		||||
            context_map[20:89, 80:90] = 0
 | 
			
		||||
            context_map[90:120, 0:10] = 0
 | 
			
		||||
            context_map[120:size, 30:40] = 0
 | 
			
		||||
            context_map[180:190, 50:60] = 0
 | 
			
		||||
 | 
			
		||||
            context_map[50:60, 50:200] = 0
 | 
			
		||||
            context_map[179:189, 80:130] = 0
 | 
			
		||||
            context_map[110:120, 0:190] = 0
 | 
			
		||||
            context_map[120:size, 30:40] = 0
 | 
			
		||||
            context_map[180:190, 50:60] = 0
 | 
			
		||||
        context_map /= context_map.sum()
 | 
			
		||||
        self.context_map = context_map
 | 
			
		||||
 | 
			
		||||
        # Pre-compute a 2D grid of coordinates for efficiency
 | 
			
		||||
        self._grid_ii, self._grid_jj = np.mgrid[0:size, 0:size]
 | 
			
		||||
 | 
			
		||||
    # --- Walker public interface
 | 
			
		||||
 | 
			
		||||
    def sample_next_step(self, current_i, current_j, random_state=np.random):
 | 
			
		||||
        """ Sample a new position for the walker. """
 | 
			
		||||
 | 
			
		||||
        # Combine the next-step proposal with the context map to get a
 | 
			
		||||
        # next-step probability map
 | 
			
		||||
        next_step_map = self._next_step_proposal(current_i, current_j)
 | 
			
		||||
        selection_map = self._compute_next_step_probability(next_step_map)
 | 
			
		||||
 | 
			
		||||
        # Draw a new position from the next-step probability map
 | 
			
		||||
        r = random_state.rand()
 | 
			
		||||
        cumulative_map = np.cumsum(selection_map)
 | 
			
		||||
        cumulative_map = cumulative_map.reshape(selection_map.shape)
 | 
			
		||||
        i_next, j_next = np.argwhere(cumulative_map >= r)[0]
 | 
			
		||||
 | 
			
		||||
        return i_next, j_next
 | 
			
		||||
 | 
			
		||||
    # --- Walker non-public interface
 | 
			
		||||
 | 
			
		||||
    def _next_step_proposal(self, current_i, current_j):
 | 
			
		||||
        """ Create the 2D proposal map for the next step of the walker. """
 | 
			
		||||
 | 
			
		||||
        # 2D Gaussian distribution , centered at current position,
 | 
			
		||||
        # and with different standard deviations for i and j
 | 
			
		||||
        grid_ii, grid_jj = self._grid_ii, self._grid_jj
 | 
			
		||||
        sigma_i, sigma_j = self.sigma_i, self.sigma_j
 | 
			
		||||
 | 
			
		||||
        rad = (
 | 
			
		||||
            (((grid_ii - current_i) ** 2) / (sigma_i ** 2))
 | 
			
		||||
            + (((grid_jj - current_j) ** 2) / (sigma_j ** 2))
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        p_next_step = np.exp(-(rad / 2.0)) / (2.0 * np.pi * sigma_i * sigma_j)
 | 
			
		||||
        return p_next_step / p_next_step.sum()
 | 
			
		||||
 | 
			
		||||
    def _compute_next_step_probability(self, next_step_map):
 | 
			
		||||
        """ Compute the next step probability map from next step proposal and
 | 
			
		||||
        context map. """
 | 
			
		||||
        next_step_probability = next_step_map * self.context_map
 | 
			
		||||
        next_step_probability /= next_step_probability.sum()
 | 
			
		||||
        return next_step_probability
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def plot_trajectory(trajectory, context_map):
 | 
			
		||||
    """ Plot a trajectory over a context map. """
 | 
			
		||||
    trajectory = np.asarray(trajectory)
 | 
			
		||||
    plt.matshow(context_map)
 | 
			
		||||
    plt.plot(trajectory[:, 1], trajectory[:, 0], color='r')
 | 
			
		||||
    plt.show()
 | 
			
		||||
							
								
								
									
										81
									
								
								notebooks/walker/Step_1_classes/walker.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								notebooks/walker/Step_1_classes/walker.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,81 @@
 | 
			
		|||
import numpy as np
 | 
			
		||||
import matplotlib.pyplot as plt
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def sample_next_step(current_i, current_j, sigma_i, sigma_j, context_map,
 | 
			
		||||
                     random_state=np.random):
 | 
			
		||||
    """ Sample a new position for the walker. """
 | 
			
		||||
 | 
			
		||||
    # Combine the next-step proposal with the context map to get a next-step
 | 
			
		||||
    # probability map
 | 
			
		||||
    size = context_map.shape[0]
 | 
			
		||||
    next_step_map = next_step_proposal(current_i, current_j, sigma_i, sigma_j,
 | 
			
		||||
                                       size)
 | 
			
		||||
    next_step_probability = compute_next_step_probability(next_step_map,
 | 
			
		||||
                                                          context_map)
 | 
			
		||||
 | 
			
		||||
    # Draw a new position from the next-step probability map
 | 
			
		||||
    r = random_state.rand()
 | 
			
		||||
    cumulative_map = np.cumsum(next_step_probability)
 | 
			
		||||
    cumulative_map = cumulative_map.reshape(next_step_probability.shape)
 | 
			
		||||
    i_next, j_next = np.argwhere(cumulative_map >= r)[0]
 | 
			
		||||
 | 
			
		||||
    return i_next, j_next
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def next_step_proposal(current_i, current_j, sigma_i, sigma_j, size):
 | 
			
		||||
    """ Create the 2D proposal map for the next step of the walker. """
 | 
			
		||||
    # 2D Gaussian distribution , centered at current position,
 | 
			
		||||
    # and with different standard deviations for i and j
 | 
			
		||||
    grid_ii, grid_jj = np.mgrid[0:size, 0:size]
 | 
			
		||||
    rad = (
 | 
			
		||||
        (((grid_ii - current_i) ** 2) / (sigma_i ** 2))
 | 
			
		||||
        + (((grid_jj - current_j) ** 2) / (sigma_j ** 2))
 | 
			
		||||
    )
 | 
			
		||||
    p_next_step = np.exp(-(rad / 2.0)) / (2.0 * np.pi * sigma_i * sigma_j)
 | 
			
		||||
    return p_next_step / p_next_step.sum()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def compute_next_step_probability(next_step_map, context_map):
 | 
			
		||||
    """ Compute the next step probability map from next step proposal and
 | 
			
		||||
    context map. """
 | 
			
		||||
    next_step_probability = next_step_map * context_map
 | 
			
		||||
    next_step_probability /= next_step_probability.sum()
 | 
			
		||||
    return next_step_probability
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def create_context_map(size, map_type='flat'):
 | 
			
		||||
    """ Create a fixed context map. """
 | 
			
		||||
    if map_type == 'flat':
 | 
			
		||||
        context_map = np.ones((size, size))
 | 
			
		||||
    elif map_type == 'hills':
 | 
			
		||||
        grid_ii, grid_jj = np.mgrid[0:size, 0:size]
 | 
			
		||||
        i_waves = np.sin(grid_ii / 130) + np.sin(grid_ii / 10)
 | 
			
		||||
        i_waves /= i_waves.max()
 | 
			
		||||
        j_waves = np.sin(grid_jj / 100) + np.sin(grid_jj / 50) + \
 | 
			
		||||
            np.sin(grid_jj / 10)
 | 
			
		||||
        j_waves /= j_waves.max()
 | 
			
		||||
        context_map = j_waves + i_waves
 | 
			
		||||
    elif map_type == 'labyrinth':
 | 
			
		||||
        context_map = np.ones((size, size))
 | 
			
		||||
        context_map[50:100, 50:60] = 0
 | 
			
		||||
        context_map[20:89, 80:90] = 0
 | 
			
		||||
        context_map[90:120, 0:10] = 0
 | 
			
		||||
        context_map[120:size, 30:40] = 0
 | 
			
		||||
        context_map[180:190, 50:60] = 0
 | 
			
		||||
 | 
			
		||||
        context_map[50:60, 50:200] = 0
 | 
			
		||||
        context_map[179:189, 80:130] = 0
 | 
			
		||||
        context_map[110:120, 0:190] = 0
 | 
			
		||||
        context_map[120:size, 30:40] = 0
 | 
			
		||||
        context_map[180:190, 50:60] = 0
 | 
			
		||||
    context_map /= context_map.sum()
 | 
			
		||||
    return context_map
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def plot_trajectory(trajectory, context_map):
 | 
			
		||||
    """ Plot a trajectory over a context map. """
 | 
			
		||||
    trajectory = np.asarray(trajectory)
 | 
			
		||||
    plt.matshow(context_map)
 | 
			
		||||
    plt.plot(trajectory[:, 1], trajectory[:, 0], color='r')
 | 
			
		||||
    plt.show()
 | 
			
		||||
							
								
								
									
										166
									
								
								notebooks/walker/Step_2_plotting/Step_2_plotting.ipynb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										166
									
								
								notebooks/walker/Step_2_plotting/Step_2_plotting.ipynb
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										1
									
								
								notebooks/walker/Step_2_plotting/show
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								notebooks/walker/Step_2_plotting/show
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
 | 
			
		||||
							
								
								
									
										167
									
								
								notebooks/walker/Step_2_plotting/solution/Step_2_plotting.ipynb
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										167
									
								
								notebooks/walker/Step_2_plotting/solution/Step_2_plotting.ipynb
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										22
									
								
								notebooks/walker/Step_2_plotting/solution/plotting.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								notebooks/walker/Step_2_plotting/solution/plotting.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
import matplotlib.pyplot as plt
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def plot_trajectory(trajectory, context_map):
 | 
			
		||||
    """ Plot a trajectory over a context map. """
 | 
			
		||||
    trajectory = np.asarray(trajectory)
 | 
			
		||||
    plt.matshow(context_map)
 | 
			
		||||
    plt.plot(trajectory[:, 1], trajectory[:, 0], color='r')
 | 
			
		||||
    plt.show()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def plot_trajectory_hexbin(trajectory):
 | 
			
		||||
    """ Plot an hexagonal density map of a trajectory. """
 | 
			
		||||
    trajectory = np.asarray(trajectory)
 | 
			
		||||
    with plt.rc_context({'figure.figsize': (4, 4), 'axes.labelsize': 16, 
 | 
			
		||||
                         'xtick.labelsize': 14, 'ytick.labelsize': 14}):
 | 
			
		||||
        plt.hexbin(trajectory[:, 1], trajectory[:, 0], gridsize=30,
 | 
			
		||||
                   extent=(0, 200, 0, 200), edgecolors='none', cmap='Reds')
 | 
			
		||||
        plt.gca().invert_yaxis()
 | 
			
		||||
        plt.xlabel('X')
 | 
			
		||||
        plt.ylabel('Y')
 | 
			
		||||
							
								
								
									
										83
									
								
								notebooks/walker/Step_2_plotting/solution/walker.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								notebooks/walker/Step_2_plotting/solution/walker.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,83 @@
 | 
			
		|||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Walker:
 | 
			
		||||
    """ The Walker knows how to walk at random on a context map. """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, sigma_i, sigma_j, size, map_type='flat'):
 | 
			
		||||
        self.sigma_i = sigma_i
 | 
			
		||||
        self.sigma_j = sigma_j
 | 
			
		||||
        self.size = size
 | 
			
		||||
 | 
			
		||||
        if map_type == 'flat':
 | 
			
		||||
            context_map = np.ones((size, size))
 | 
			
		||||
        elif map_type == 'hills':
 | 
			
		||||
            grid_ii, grid_jj = np.mgrid[0:size, 0:size]
 | 
			
		||||
            i_waves = np.sin(grid_ii / 130) + np.sin(grid_ii / 10)
 | 
			
		||||
            i_waves /= i_waves.max()
 | 
			
		||||
            j_waves = np.sin(grid_jj / 100) + np.sin(grid_jj / 50) + \
 | 
			
		||||
                np.sin(grid_jj / 10)
 | 
			
		||||
            j_waves /= j_waves.max()
 | 
			
		||||
            context_map = j_waves + i_waves
 | 
			
		||||
        elif map_type == 'labyrinth':
 | 
			
		||||
            context_map = np.ones((size, size))
 | 
			
		||||
            context_map[50:100, 50:60] = 0
 | 
			
		||||
            context_map[20:89, 80:90] = 0
 | 
			
		||||
            context_map[90:120, 0:10] = 0
 | 
			
		||||
            context_map[120:size, 30:40] = 0
 | 
			
		||||
            context_map[180:190, 50:60] = 0
 | 
			
		||||
 | 
			
		||||
            context_map[50:60, 50:200] = 0
 | 
			
		||||
            context_map[179:189, 80:130] = 0
 | 
			
		||||
            context_map[110:120, 0:190] = 0
 | 
			
		||||
            context_map[120:size, 30:40] = 0
 | 
			
		||||
            context_map[180:190, 50:60] = 0
 | 
			
		||||
        context_map /= context_map.sum()
 | 
			
		||||
        self.context_map = context_map
 | 
			
		||||
 | 
			
		||||
        # Pre-compute a 2D grid of coordinates for efficiency
 | 
			
		||||
        self._grid_ii, self._grid_jj = np.mgrid[0:size, 0:size]
 | 
			
		||||
 | 
			
		||||
    # --- Walker public interface
 | 
			
		||||
 | 
			
		||||
    def sample_next_step(self, current_i, current_j, random_state=np.random):
 | 
			
		||||
        """ Sample a new position for the walker. """
 | 
			
		||||
 | 
			
		||||
        # Combine the next-step proposal with the context map to get a
 | 
			
		||||
        # next-step probability map
 | 
			
		||||
        next_step_map = self._next_step_proposal(current_i, current_j)
 | 
			
		||||
        selection_map = self._compute_next_step_probability(next_step_map)
 | 
			
		||||
 | 
			
		||||
        # Draw a new position from the next-step probability map
 | 
			
		||||
        r = random_state.rand()
 | 
			
		||||
        cumulative_map = np.cumsum(selection_map)
 | 
			
		||||
        cumulative_map = cumulative_map.reshape(selection_map.shape)
 | 
			
		||||
        i_next, j_next = np.argwhere(cumulative_map >= r)[0]
 | 
			
		||||
 | 
			
		||||
        return i_next, j_next
 | 
			
		||||
 | 
			
		||||
    # --- Walker non-public interface
 | 
			
		||||
 | 
			
		||||
    def _next_step_proposal(self, current_i, current_j):
 | 
			
		||||
        """ Create the 2D proposal map for the next step of the walker. """
 | 
			
		||||
 | 
			
		||||
        # 2D Gaussian distribution , centered at current position,
 | 
			
		||||
        # and with different standard deviations for i and j
 | 
			
		||||
        grid_ii, grid_jj = self._grid_ii, self._grid_jj
 | 
			
		||||
        sigma_i, sigma_j = self.sigma_i, self.sigma_j
 | 
			
		||||
 | 
			
		||||
        rad = (
 | 
			
		||||
            (((grid_ii - current_i) ** 2) / (sigma_i ** 2))
 | 
			
		||||
            + (((grid_jj - current_j) ** 2) / (sigma_j ** 2))
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        p_next_step = np.exp(-(rad / 2.0)) / (2.0 * np.pi * sigma_i * sigma_j)
 | 
			
		||||
        return p_next_step / p_next_step.sum()
 | 
			
		||||
 | 
			
		||||
    def _compute_next_step_probability(self, next_step_map):
 | 
			
		||||
        """ Compute the next step probability map from next step proposal and
 | 
			
		||||
        context map. """
 | 
			
		||||
        next_step_probability = next_step_map * self.context_map
 | 
			
		||||
        next_step_probability /= next_step_probability.sum()
 | 
			
		||||
        return next_step_probability
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										101
									
								
								notebooks/walker/Step_2_plotting/walker.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								notebooks/walker/Step_2_plotting/walker.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,101 @@
 | 
			
		|||
import numpy as np
 | 
			
		||||
import matplotlib.pyplot as plt
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Walker:
 | 
			
		||||
    """ The Walker knows how to walk at random on a context map. """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, sigma_i, sigma_j, size, map_type='flat'):
 | 
			
		||||
        self.sigma_i = sigma_i
 | 
			
		||||
        self.sigma_j = sigma_j
 | 
			
		||||
        self.size = size
 | 
			
		||||
 | 
			
		||||
        if map_type == 'flat':
 | 
			
		||||
            context_map = np.ones((size, size))
 | 
			
		||||
        elif map_type == 'hills':
 | 
			
		||||
            grid_ii, grid_jj = np.mgrid[0:size, 0:size]
 | 
			
		||||
            i_waves = np.sin(grid_ii / 130) + np.sin(grid_ii / 10)
 | 
			
		||||
            i_waves /= i_waves.max()
 | 
			
		||||
            j_waves = np.sin(grid_jj / 100) + np.sin(grid_jj / 50) + \
 | 
			
		||||
                np.sin(grid_jj / 10)
 | 
			
		||||
            j_waves /= j_waves.max()
 | 
			
		||||
            context_map = j_waves + i_waves
 | 
			
		||||
        elif map_type == 'labyrinth':
 | 
			
		||||
            context_map = np.ones((size, size))
 | 
			
		||||
            context_map[50:100, 50:60] = 0
 | 
			
		||||
            context_map[20:89, 80:90] = 0
 | 
			
		||||
            context_map[90:120, 0:10] = 0
 | 
			
		||||
            context_map[120:size, 30:40] = 0
 | 
			
		||||
            context_map[180:190, 50:60] = 0
 | 
			
		||||
 | 
			
		||||
            context_map[50:60, 50:200] = 0
 | 
			
		||||
            context_map[179:189, 80:130] = 0
 | 
			
		||||
            context_map[110:120, 0:190] = 0
 | 
			
		||||
            context_map[120:size, 30:40] = 0
 | 
			
		||||
            context_map[180:190, 50:60] = 0
 | 
			
		||||
        context_map /= context_map.sum()
 | 
			
		||||
        self.context_map = context_map
 | 
			
		||||
 | 
			
		||||
        # Pre-compute a 2D grid of coordinates for efficiency
 | 
			
		||||
        self._grid_ii, self._grid_jj = np.mgrid[0:size, 0:size]
 | 
			
		||||
 | 
			
		||||
    # --- Walker public interface
 | 
			
		||||
 | 
			
		||||
    def sample_next_step(self, current_i, current_j, random_state=np.random):
 | 
			
		||||
        """ Sample a new position for the walker. """
 | 
			
		||||
 | 
			
		||||
        # Combine the next-step proposal with the context map to get a
 | 
			
		||||
        # next-step probability map
 | 
			
		||||
        next_step_map = self._next_step_proposal(current_i, current_j)
 | 
			
		||||
        selection_map = self._compute_next_step_probability(next_step_map)
 | 
			
		||||
 | 
			
		||||
        # Draw a new position from the next-step probability map
 | 
			
		||||
        r = random_state.rand()
 | 
			
		||||
        cumulative_map = np.cumsum(selection_map)
 | 
			
		||||
        cumulative_map = cumulative_map.reshape(selection_map.shape)
 | 
			
		||||
        i_next, j_next = np.argwhere(cumulative_map >= r)[0]
 | 
			
		||||
 | 
			
		||||
        return i_next, j_next
 | 
			
		||||
 | 
			
		||||
    def plot_trajectory(self, trajectory):
 | 
			
		||||
        """ Plot a trajectory over a context map. """
 | 
			
		||||
        trajectory = np.asarray(trajectory)
 | 
			
		||||
        plt.matshow(self.context_map)
 | 
			
		||||
        plt.plot(trajectory[:, 1], trajectory[:, 0], color='r')
 | 
			
		||||
        plt.show()
 | 
			
		||||
 | 
			
		||||
    def plot_trajectory_hexbin(self, trajectory):
 | 
			
		||||
        """ Plot an hexagonal density map of a trajectory. """
 | 
			
		||||
        trajectory = np.asarray(trajectory)
 | 
			
		||||
        with plt.rc_context({'figure.figsize': (4, 4), 'axes.labelsize': 16, 
 | 
			
		||||
                             'xtick.labelsize': 14, 'ytick.labelsize': 14}):
 | 
			
		||||
            plt.hexbin(trajectory[:, 1], trajectory[:, 0], gridsize=30,
 | 
			
		||||
                       extent=(0, 200, 0, 200), edgecolors='none', cmap='Reds')
 | 
			
		||||
            plt.gca().invert_yaxis()
 | 
			
		||||
            plt.xlabel('X')
 | 
			
		||||
            plt.ylabel('Y')
 | 
			
		||||
 | 
			
		||||
    # --- Walker non-public interface
 | 
			
		||||
 | 
			
		||||
    def _next_step_proposal(self, current_i, current_j):
 | 
			
		||||
        """ Create the 2D proposal map for the next step of the walker. """
 | 
			
		||||
 | 
			
		||||
        # 2D Gaussian distribution , centered at current position,
 | 
			
		||||
        # and with different standard deviations for i and j
 | 
			
		||||
        grid_ii, grid_jj = self._grid_ii, self._grid_jj
 | 
			
		||||
        sigma_i, sigma_j = self.sigma_i, self.sigma_j
 | 
			
		||||
 | 
			
		||||
        rad = (
 | 
			
		||||
            (((grid_ii - current_i) ** 2) / (sigma_i ** 2))
 | 
			
		||||
            + (((grid_jj - current_j) ** 2) / (sigma_j ** 2))
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        p_next_step = np.exp(-(rad / 2.0)) / (2.0 * np.pi * sigma_i * sigma_j)
 | 
			
		||||
        return p_next_step / p_next_step.sum()
 | 
			
		||||
 | 
			
		||||
    def _compute_next_step_probability(self, next_step_map):
 | 
			
		||||
        """ Compute the next step probability map from next step proposal and
 | 
			
		||||
        context map. """
 | 
			
		||||
        next_step_probability = next_step_map * self.context_map
 | 
			
		||||
        next_step_probability /= next_step_probability.sum()
 | 
			
		||||
        return next_step_probability
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,173 @@
 | 
			
		|||
{
 | 
			
		||||
 "cells": [
 | 
			
		||||
  {
 | 
			
		||||
   "cell_type": "markdown",
 | 
			
		||||
   "metadata": {
 | 
			
		||||
    "nteract": {
 | 
			
		||||
     "transient": {
 | 
			
		||||
      "deleting": false
 | 
			
		||||
     }
 | 
			
		||||
    }
 | 
			
		||||
   },
 | 
			
		||||
   "source": [
 | 
			
		||||
    "# 1. Take a look at this (working) code\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "... and run it. We discussed that the `context_map` varies independently of the walker. Identify the part of the code that will be affected by this change."
 | 
			
		||||
   ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
   "cell_type": "code",
 | 
			
		||||
   "execution_count": 1,
 | 
			
		||||
   "metadata": {
 | 
			
		||||
    "ExecuteTime": {
 | 
			
		||||
     "end_time": "2022-08-18T09:50:40.616906Z",
 | 
			
		||||
     "start_time": "2022-08-18T11:50:40.181358+02:00"
 | 
			
		||||
    },
 | 
			
		||||
    "execution": {
 | 
			
		||||
     "iopub.execute_input": "2022-08-20T06:27:54.689Z",
 | 
			
		||||
     "iopub.status.busy": "2022-08-20T06:27:54.685Z",
 | 
			
		||||
     "iopub.status.idle": "2022-08-20T06:27:55.297Z",
 | 
			
		||||
     "shell.execute_reply": "2022-08-20T06:27:55.319Z"
 | 
			
		||||
    },
 | 
			
		||||
    "pycharm": {
 | 
			
		||||
     "name": "#%%\n"
 | 
			
		||||
    }
 | 
			
		||||
   },
 | 
			
		||||
   "outputs": [],
 | 
			
		||||
   "source": [
 | 
			
		||||
    "%matplotlib inline\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "from plotting import plot_trajectory, plot_trajectory_hexbin\n",
 | 
			
		||||
    "from walker import Walker\n"
 | 
			
		||||
   ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
   "cell_type": "code",
 | 
			
		||||
   "execution_count": null,
 | 
			
		||||
   "metadata": {
 | 
			
		||||
    "collapsed": true,
 | 
			
		||||
    "jupyter": {
 | 
			
		||||
     "outputs_hidden": false,
 | 
			
		||||
     "source_hidden": false
 | 
			
		||||
    },
 | 
			
		||||
    "nteract": {
 | 
			
		||||
     "transient": {
 | 
			
		||||
      "deleting": false
 | 
			
		||||
     }
 | 
			
		||||
    }
 | 
			
		||||
   },
 | 
			
		||||
   "outputs": [],
 | 
			
		||||
   "source": [
 | 
			
		||||
    "# Create a Walker instance\n",
 | 
			
		||||
    "walker = Walker(sigma_i=3, sigma_j=4, size=200, map_type='hills')\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "# Sample a next step 1000 times\n",
 | 
			
		||||
    "i, j = 100, 50\n",
 | 
			
		||||
    "trajectory = []\n",
 | 
			
		||||
    "for _ in range(1000):\n",
 | 
			
		||||
    "    i, j = walker.sample_next_step(i, j)\n",
 | 
			
		||||
    "    trajectory.append((i, j))\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "plot_trajectory(trajectory, walker.context_map)"
 | 
			
		||||
   ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
   "cell_type": "markdown",
 | 
			
		||||
   "metadata": {
 | 
			
		||||
    "nteract": {
 | 
			
		||||
     "transient": {
 | 
			
		||||
      "deleting": false
 | 
			
		||||
     }
 | 
			
		||||
    }
 | 
			
		||||
   },
 | 
			
		||||
   "source": [
 | 
			
		||||
    "# 2. Modify the above code to reflect the idea of a separate context_map module\n",
 | 
			
		||||
    "\n",
 | 
			
		||||
    "1. how would the import statement change as a result of needing a separate context_map module?\n",
 | 
			
		||||
    "2. what input arguments do the context_map functions need to take?\n",
 | 
			
		||||
    "3. how does the initialization of the walker change?\n",
 | 
			
		||||
    "    - i.e. instead of \"map_type\"\n",
 | 
			
		||||
    "\n"
 | 
			
		||||
   ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
   "cell_type": "code",
 | 
			
		||||
   "execution_count": null,
 | 
			
		||||
   "metadata": {},
 | 
			
		||||
   "outputs": [],
 | 
			
		||||
   "source": []
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
   "cell_type": "code",
 | 
			
		||||
   "execution_count": null,
 | 
			
		||||
   "metadata": {},
 | 
			
		||||
   "outputs": [],
 | 
			
		||||
   "source": []
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
   "cell_type": "markdown",
 | 
			
		||||
   "metadata": {
 | 
			
		||||
    "nteract": {
 | 
			
		||||
     "transient": {
 | 
			
		||||
      "deleting": false
 | 
			
		||||
     }
 | 
			
		||||
    }
 | 
			
		||||
   },
 | 
			
		||||
   "source": [
 | 
			
		||||
    "# 3. (optional) Actually break out the context map initialization\n",
 | 
			
		||||
    "1. Move context map initialization to three functions in a separate `context_map.py` module which all return a `context_map` array\n",
 | 
			
		||||
    "2. Modify the constructor of Walker to take a `context_map` array instead of a `map_type`\n",
 | 
			
		||||
    "3. Modify this notebook to use the new code and see if the code you wrote works!\n",
 | 
			
		||||
    "4. Try to run all the types:\n",
 | 
			
		||||
    "    - Run one simulation with a flat context map\n",
 | 
			
		||||
    "    - Run one simulation with a hill context map\n",
 | 
			
		||||
    "    - Run one simulation with a labyrinth context map"
 | 
			
		||||
   ]
 | 
			
		||||
  },
 | 
			
		||||
  {
 | 
			
		||||
   "cell_type": "code",
 | 
			
		||||
   "execution_count": null,
 | 
			
		||||
   "metadata": {},
 | 
			
		||||
   "outputs": [],
 | 
			
		||||
   "source": []
 | 
			
		||||
  }
 | 
			
		||||
 ],
 | 
			
		||||
 "metadata": {
 | 
			
		||||
  "hide_input": false,
 | 
			
		||||
  "kernelspec": {
 | 
			
		||||
   "display_name": "Python 3 (ipykernel)",
 | 
			
		||||
   "language": "python",
 | 
			
		||||
   "name": "python3"
 | 
			
		||||
  },
 | 
			
		||||
  "language_info": {
 | 
			
		||||
   "codemirror_mode": {
 | 
			
		||||
    "name": "ipython",
 | 
			
		||||
    "version": 3
 | 
			
		||||
   },
 | 
			
		||||
   "file_extension": ".py",
 | 
			
		||||
   "mimetype": "text/x-python",
 | 
			
		||||
   "name": "python",
 | 
			
		||||
   "nbconvert_exporter": "python",
 | 
			
		||||
   "pygments_lexer": "ipython3",
 | 
			
		||||
   "version": "3.11.3"
 | 
			
		||||
  },
 | 
			
		||||
  "nteract": {
 | 
			
		||||
   "version": "0.28.0"
 | 
			
		||||
  },
 | 
			
		||||
  "toc": {
 | 
			
		||||
   "nav_menu": {
 | 
			
		||||
    "height": "12px",
 | 
			
		||||
    "width": "252px"
 | 
			
		||||
   },
 | 
			
		||||
   "navigate_menu": true,
 | 
			
		||||
   "number_sections": true,
 | 
			
		||||
   "sideBar": true,
 | 
			
		||||
   "threshold": 4,
 | 
			
		||||
   "toc_cell": false,
 | 
			
		||||
   "toc_section_display": "block",
 | 
			
		||||
   "toc_window_display": false
 | 
			
		||||
  }
 | 
			
		||||
 },
 | 
			
		||||
 "nbformat": 4,
 | 
			
		||||
 "nbformat_minor": 1
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
import matplotlib.pyplot as plt
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def plot_trajectory(trajectory, context_map):
 | 
			
		||||
    """ Plot a trajectory over a context map. """
 | 
			
		||||
    trajectory = np.asarray(trajectory)
 | 
			
		||||
    plt.matshow(context_map)
 | 
			
		||||
    plt.plot(trajectory[:, 1], trajectory[:, 0], color='r')
 | 
			
		||||
    plt.show()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def plot_trajectory_hexbin(trajectory):
 | 
			
		||||
    """ Plot an hexagonal density map of a trajectory. """
 | 
			
		||||
    trajectory = np.asarray(trajectory)
 | 
			
		||||
    with plt.rc_context({'figure.figsize': (4, 4), 'axes.labelsize': 16, 
 | 
			
		||||
                         'xtick.labelsize': 14, 'ytick.labelsize': 14}):
 | 
			
		||||
        plt.hexbin(trajectory[:, 1], trajectory[:, 0], gridsize=30,
 | 
			
		||||
                   extent=(0, 200, 0, 200), edgecolors='none', cmap='Reds')
 | 
			
		||||
        plt.gca().invert_yaxis()
 | 
			
		||||
        plt.xlabel('X')
 | 
			
		||||
        plt.ylabel('Y')
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
""" CONTEXT MAP BUILDERS """
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def flat_context_map(size):
 | 
			
		||||
    """ A context map where all positions are equally likely. """
 | 
			
		||||
    return np.ones((size, size))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def hills_context_map(size):
 | 
			
		||||
    """ A context map with bumps and valleys. """
 | 
			
		||||
    grid_ii, grid_jj = np.mgrid[0:size, 0:size]
 | 
			
		||||
    i_waves = np.sin(grid_ii / 130) + np.sin(grid_ii / 10)
 | 
			
		||||
    i_waves /= i_waves.max()
 | 
			
		||||
    j_waves = np.sin(grid_jj / 100) + np.sin(grid_jj / 50) + \
 | 
			
		||||
        np.sin(grid_jj / 10)
 | 
			
		||||
    j_waves /= j_waves.max()
 | 
			
		||||
    context_map = j_waves + i_waves
 | 
			
		||||
    return context_map
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def labyrinth_context_map(size):
 | 
			
		||||
    """ A context map that looks like a labyrinth. """
 | 
			
		||||
    context_map = np.ones((size, size))
 | 
			
		||||
    context_map[50:100, 50:60] = 0
 | 
			
		||||
    context_map[20:89, 80:90] = 0
 | 
			
		||||
    context_map[90:120, 0:10] = 0
 | 
			
		||||
    context_map[120:size, 30:40] = 0
 | 
			
		||||
    context_map[180:190, 50:60] = 0
 | 
			
		||||
 | 
			
		||||
    context_map[50:60, 50:200] = 0
 | 
			
		||||
    context_map[179:189, 80:130] = 0
 | 
			
		||||
    context_map[110:120, 0:190] = 0
 | 
			
		||||
    context_map[120:size, 30:40] = 0
 | 
			
		||||
    context_map[180:190, 50:60] = 0
 | 
			
		||||
 | 
			
		||||
    return context_map
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
import matplotlib.pyplot as plt
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def plot_trajectory(trajectory, context_map):
 | 
			
		||||
    """ Plot a trajectory over a context map. """
 | 
			
		||||
    trajectory = np.asarray(trajectory)
 | 
			
		||||
    plt.matshow(context_map)
 | 
			
		||||
    plt.plot(trajectory[:, 1], trajectory[:, 0], color='r')
 | 
			
		||||
    plt.show()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def plot_trajectory_hexbin(trajectory):
 | 
			
		||||
    """ Plot an hexagonal density map of a trajectory. """
 | 
			
		||||
    trajectory = np.asarray(trajectory)
 | 
			
		||||
    with plt.rc_context({'figure.figsize': (4, 4), 'axes.labelsize': 16, 
 | 
			
		||||
                         'xtick.labelsize': 14, 'ytick.labelsize': 14}):
 | 
			
		||||
        plt.hexbin(trajectory[:, 1], trajectory[:, 0], gridsize=30,
 | 
			
		||||
                   extent=(0, 200, 0, 200), edgecolors='none', cmap='Reds')
 | 
			
		||||
        plt.gca().invert_yaxis()
 | 
			
		||||
        plt.xlabel('X')
 | 
			
		||||
        plt.ylabel('Y')
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,60 @@
 | 
			
		|||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Walker:
 | 
			
		||||
    """ The Walker knows how to walk at random on a context map. """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, sigma_i, sigma_j, context_map):
 | 
			
		||||
        self.sigma_i = sigma_i
 | 
			
		||||
        self.sigma_j = sigma_j
 | 
			
		||||
        self.size = context_map.shape[0]
 | 
			
		||||
        # Make sure that the context map is normalized
 | 
			
		||||
        context_map /= context_map.sum()
 | 
			
		||||
        self.context_map = context_map
 | 
			
		||||
 | 
			
		||||
        # Pre-compute a 2D grid of coordinates for efficiency
 | 
			
		||||
        self._grid_ii, self._grid_jj = np.mgrid[0:self.size, 0:self.size]
 | 
			
		||||
 | 
			
		||||
    # --- Walker public interface
 | 
			
		||||
 | 
			
		||||
    def sample_next_step(self, current_i, current_j, random_state=np.random):
 | 
			
		||||
        """ Sample a new position for the walker. """
 | 
			
		||||
 | 
			
		||||
        # Combine the next-step proposal with the context map to get a
 | 
			
		||||
        # next-step probability map
 | 
			
		||||
        next_step_map = self._next_step_proposal(current_i, current_j)
 | 
			
		||||
        selection_map = self._compute_next_step_probability(next_step_map)
 | 
			
		||||
 | 
			
		||||
        # Draw a new position from the next-step probability map
 | 
			
		||||
        r = random_state.rand()
 | 
			
		||||
        cumulative_map = np.cumsum(selection_map)
 | 
			
		||||
        cumulative_map = cumulative_map.reshape(selection_map.shape)
 | 
			
		||||
        i_next, j_next = np.argwhere(cumulative_map >= r)[0]
 | 
			
		||||
 | 
			
		||||
        return i_next, j_next
 | 
			
		||||
 | 
			
		||||
    # --- Walker non-public interface
 | 
			
		||||
 | 
			
		||||
    def _next_step_proposal(self, current_i, current_j):
 | 
			
		||||
        """ Create the 2D proposal map for the next step of the walker. """
 | 
			
		||||
 | 
			
		||||
        # 2D Gaussian distribution , centered at current position,
 | 
			
		||||
        # and with different standard deviations for i and j
 | 
			
		||||
        grid_ii, grid_jj = self._grid_ii, self._grid_jj
 | 
			
		||||
        sigma_i, sigma_j = self.sigma_i, self.sigma_j
 | 
			
		||||
 | 
			
		||||
        rad = (
 | 
			
		||||
            (((grid_ii - current_i) ** 2) / (sigma_i ** 2))
 | 
			
		||||
            + (((grid_jj - current_j) ** 2) / (sigma_j ** 2))
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        p_next_step = np.exp(-(rad / 2.0)) / (2.0 * np.pi * sigma_i * sigma_j)
 | 
			
		||||
        return p_next_step / p_next_step.sum()
 | 
			
		||||
 | 
			
		||||
    def _compute_next_step_probability(self, next_step_map):
 | 
			
		||||
        """ Compute the next step probability map from next step proposal and
 | 
			
		||||
        context map. """
 | 
			
		||||
        next_step_probability = next_step_map * self.context_map
 | 
			
		||||
        next_step_probability /= next_step_probability.sum()
 | 
			
		||||
        return next_step_probability
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,83 @@
 | 
			
		|||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Walker:
 | 
			
		||||
    """ The Walker knows how to walk at random on a context map. """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, sigma_i, sigma_j, size, map_type='flat'):
 | 
			
		||||
        self.sigma_i = sigma_i
 | 
			
		||||
        self.sigma_j = sigma_j
 | 
			
		||||
        self.size = size
 | 
			
		||||
 | 
			
		||||
        if map_type == 'flat':
 | 
			
		||||
            context_map = np.ones((size, size))
 | 
			
		||||
        elif map_type == 'hills':
 | 
			
		||||
            grid_ii, grid_jj = np.mgrid[0:size, 0:size]
 | 
			
		||||
            i_waves = np.sin(grid_ii / 130) + np.sin(grid_ii / 10)
 | 
			
		||||
            i_waves /= i_waves.max()
 | 
			
		||||
            j_waves = np.sin(grid_jj / 100) + np.sin(grid_jj / 50) + \
 | 
			
		||||
                np.sin(grid_jj / 10)
 | 
			
		||||
            j_waves /= j_waves.max()
 | 
			
		||||
            context_map = j_waves + i_waves
 | 
			
		||||
        elif map_type == 'labyrinth':
 | 
			
		||||
            context_map = np.ones((size, size))
 | 
			
		||||
            context_map[50:100, 50:60] = 0
 | 
			
		||||
            context_map[20:89, 80:90] = 0
 | 
			
		||||
            context_map[90:120, 0:10] = 0
 | 
			
		||||
            context_map[120:size, 30:40] = 0
 | 
			
		||||
            context_map[180:190, 50:60] = 0
 | 
			
		||||
 | 
			
		||||
            context_map[50:60, 50:200] = 0
 | 
			
		||||
            context_map[179:189, 80:130] = 0
 | 
			
		||||
            context_map[110:120, 0:190] = 0
 | 
			
		||||
            context_map[120:size, 30:40] = 0
 | 
			
		||||
            context_map[180:190, 50:60] = 0
 | 
			
		||||
        context_map /= context_map.sum()
 | 
			
		||||
        self.context_map = context_map
 | 
			
		||||
 | 
			
		||||
        # Pre-compute a 2D grid of coordinates for efficiency
 | 
			
		||||
        self._grid_ii, self._grid_jj = np.mgrid[0:size, 0:size]
 | 
			
		||||
 | 
			
		||||
    # --- Walker public interface
 | 
			
		||||
 | 
			
		||||
    def sample_next_step(self, current_i, current_j, random_state=np.random):
 | 
			
		||||
        """ Sample a new position for the walker. """
 | 
			
		||||
 | 
			
		||||
        # Combine the next-step proposal with the context map to get a
 | 
			
		||||
        # next-step probability map
 | 
			
		||||
        next_step_map = self._next_step_proposal(current_i, current_j)
 | 
			
		||||
        selection_map = self._compute_next_step_probability(next_step_map)
 | 
			
		||||
 | 
			
		||||
        # Draw a new position from the next-step probability map
 | 
			
		||||
        r = random_state.rand()
 | 
			
		||||
        cumulative_map = np.cumsum(selection_map)
 | 
			
		||||
        cumulative_map = cumulative_map.reshape(selection_map.shape)
 | 
			
		||||
        i_next, j_next = np.argwhere(cumulative_map >= r)[0]
 | 
			
		||||
 | 
			
		||||
        return i_next, j_next
 | 
			
		||||
 | 
			
		||||
    # --- Walker non-public interface
 | 
			
		||||
 | 
			
		||||
    def _next_step_proposal(self, current_i, current_j):
 | 
			
		||||
        """ Create the 2D proposal map for the next step of the walker. """
 | 
			
		||||
 | 
			
		||||
        # 2D Gaussian distribution , centered at current position,
 | 
			
		||||
        # and with different standard deviations for i and j
 | 
			
		||||
        grid_ii, grid_jj = self._grid_ii, self._grid_jj
 | 
			
		||||
        sigma_i, sigma_j = self.sigma_i, self.sigma_j
 | 
			
		||||
 | 
			
		||||
        rad = (
 | 
			
		||||
            (((grid_ii - current_i) ** 2) / (sigma_i ** 2))
 | 
			
		||||
            + (((grid_jj - current_j) ** 2) / (sigma_j ** 2))
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        p_next_step = np.exp(-(rad / 2.0)) / (2.0 * np.pi * sigma_i * sigma_j)
 | 
			
		||||
        return p_next_step / p_next_step.sum()
 | 
			
		||||
 | 
			
		||||
    def _compute_next_step_probability(self, next_step_map):
 | 
			
		||||
        """ Compute the next step probability map from next step proposal and
 | 
			
		||||
        context map. """
 | 
			
		||||
        next_step_probability = next_step_map * self.context_map
 | 
			
		||||
        next_step_probability /= next_step_probability.sum()
 | 
			
		||||
        return next_step_probability
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
""" CONTEXT MAP BUILDERS """
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def flat_context_map(size):
 | 
			
		||||
    """ A context map where all positions are equally likely. """
 | 
			
		||||
    return np.ones((size, size))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def hills_context_map(size):
 | 
			
		||||
    """ A context map with bumps and valleys. """
 | 
			
		||||
    grid_ii, grid_jj = np.mgrid[0:size, 0:size]
 | 
			
		||||
    i_waves = np.sin(grid_ii / 130) + np.sin(grid_ii / 10)
 | 
			
		||||
    i_waves /= i_waves.max()
 | 
			
		||||
    j_waves = np.sin(grid_jj / 100) + np.sin(grid_jj / 50) + \
 | 
			
		||||
        np.sin(grid_jj / 10)
 | 
			
		||||
    j_waves /= j_waves.max()
 | 
			
		||||
    context_map = j_waves + i_waves
 | 
			
		||||
    return context_map
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def labyrinth_context_map(size):
 | 
			
		||||
    """ A context map that looks like a labyrinth. """
 | 
			
		||||
    context_map = np.ones((size, size))
 | 
			
		||||
    context_map[50:100, 50:60] = 0
 | 
			
		||||
    context_map[20:89, 80:90] = 0
 | 
			
		||||
    context_map[90:120, 0:10] = 0
 | 
			
		||||
    context_map[120:size, 30:40] = 0
 | 
			
		||||
    context_map[180:190, 50:60] = 0
 | 
			
		||||
 | 
			
		||||
    context_map[50:60, 50:200] = 0
 | 
			
		||||
    context_map[179:189, 80:130] = 0
 | 
			
		||||
    context_map[110:120, 0:190] = 0
 | 
			
		||||
    context_map[120:size, 30:40] = 0
 | 
			
		||||
    context_map[180:190, 50:60] = 0
 | 
			
		||||
 | 
			
		||||
    return context_map
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
import matplotlib.pyplot as plt
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def plot_trajectory(trajectory, context_map):
 | 
			
		||||
    """ Plot a trajectory over a context map. """
 | 
			
		||||
    trajectory = np.asarray(trajectory)
 | 
			
		||||
    plt.matshow(context_map)
 | 
			
		||||
    plt.plot(trajectory[:, 1], trajectory[:, 0], color='r')
 | 
			
		||||
    plt.show()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def plot_trajectory_hexbin(trajectory):
 | 
			
		||||
    """ Plot an hexagonal density map of a trajectory. """
 | 
			
		||||
    trajectory = np.asarray(trajectory)
 | 
			
		||||
    with plt.rc_context({'figure.figsize': (4, 4), 'axes.labelsize': 16, 
 | 
			
		||||
                         'xtick.labelsize': 14, 'ytick.labelsize': 14}):
 | 
			
		||||
        plt.hexbin(trajectory[:, 1], trajectory[:, 0], gridsize=30,
 | 
			
		||||
                   extent=(0, 200, 0, 200), edgecolors='none', cmap='Reds')
 | 
			
		||||
        plt.gca().invert_yaxis()
 | 
			
		||||
        plt.xlabel('X')
 | 
			
		||||
        plt.ylabel('Y')
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,37 @@
 | 
			
		|||
""" CONTEXT MAP BUILDERS """
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def flat_context_map(size):
 | 
			
		||||
    """ A context map where all positions are equally likely. """
 | 
			
		||||
    return np.ones((size, size))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def hills_context_map(size):
 | 
			
		||||
    """ A context map with bumps and valleys. """
 | 
			
		||||
    grid_ii, grid_jj = np.mgrid[0:size, 0:size]
 | 
			
		||||
    i_waves = np.sin(grid_ii / 130) + np.sin(grid_ii / 10)
 | 
			
		||||
    i_waves /= i_waves.max()
 | 
			
		||||
    j_waves = np.sin(grid_jj / 100) + np.sin(grid_jj / 50) + \
 | 
			
		||||
        np.sin(grid_jj / 10)
 | 
			
		||||
    j_waves /= j_waves.max()
 | 
			
		||||
    context_map = j_waves + i_waves
 | 
			
		||||
    return context_map
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def labyrinth_context_map(size):
 | 
			
		||||
    """ A context map that looks like a labyrinth. """
 | 
			
		||||
    context_map = np.ones((size, size))
 | 
			
		||||
    context_map[50:100, 50:60] = 0
 | 
			
		||||
    context_map[20:89, 80:90] = 0
 | 
			
		||||
    context_map[90:120, 0:10] = 0
 | 
			
		||||
    context_map[120:size, 30:40] = 0
 | 
			
		||||
    context_map[180:190, 50:60] = 0
 | 
			
		||||
 | 
			
		||||
    context_map[50:60, 50:200] = 0
 | 
			
		||||
    context_map[179:189, 80:130] = 0
 | 
			
		||||
    context_map[110:120, 0:190] = 0
 | 
			
		||||
    context_map[120:size, 30:40] = 0
 | 
			
		||||
    context_map[180:190, 50:60] = 0
 | 
			
		||||
 | 
			
		||||
    return context_map
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,25 @@
 | 
			
		|||
""" Functions to compute next step proposal maps. """
 | 
			
		||||
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def gaussian_next_step_proposal(current_i, current_j, size, sigma_i, sigma_j):
 | 
			
		||||
    """ Gaussian next step proposal. """
 | 
			
		||||
    grid_ii, grid_jj = np.mgrid[0:size, 0:size]
 | 
			
		||||
 | 
			
		||||
    rad = (
 | 
			
		||||
        (((grid_ii - current_i) ** 2) / (sigma_i ** 2))
 | 
			
		||||
        + (((grid_jj - current_j) ** 2) / (sigma_j ** 2))
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    p_next_step = np.exp(-(rad / 2.0)) / (2.0 * np.pi * sigma_i * sigma_j)
 | 
			
		||||
    return p_next_step / p_next_step.sum()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def square_next_step_proposal(current_i, current_j, size, width):
 | 
			
		||||
    """ Square next step proposal. """
 | 
			
		||||
    grid_ii, grid_jj = np.mgrid[0:size, 0:size]
 | 
			
		||||
    inside_mask = (np.abs(grid_ii - current_i) <= width // 2) & (np.abs(grid_jj - current_j) <= width // 2)
 | 
			
		||||
    p_next_step = inside_mask / inside_mask.sum()
 | 
			
		||||
    return p_next_step
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
import matplotlib.pyplot as plt
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def plot_trajectory(trajectory, context_map):
 | 
			
		||||
    """ Plot a trajectory over a context map. """
 | 
			
		||||
    trajectory = np.asarray(trajectory)
 | 
			
		||||
    plt.matshow(context_map)
 | 
			
		||||
    plt.plot(trajectory[:, 1], trajectory[:, 0], color='r')
 | 
			
		||||
    plt.show()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def plot_trajectory_hexbin(trajectory):
 | 
			
		||||
    """ Plot an hexagonal density map of a trajectory. """
 | 
			
		||||
    trajectory = np.asarray(trajectory)
 | 
			
		||||
    with plt.rc_context({'figure.figsize': (4, 4), 'axes.labelsize': 16, 
 | 
			
		||||
                         'xtick.labelsize': 14, 'ytick.labelsize': 14}):
 | 
			
		||||
        plt.hexbin(trajectory[:, 1], trajectory[:, 0], gridsize=30,
 | 
			
		||||
                   extent=(0, 200, 0, 200), edgecolors='none', cmap='Reds')
 | 
			
		||||
        plt.gca().invert_yaxis()
 | 
			
		||||
        plt.xlabel('X')
 | 
			
		||||
        plt.ylabel('Y')
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,59 @@
 | 
			
		|||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Walker:
 | 
			
		||||
    """ The Walker knows how to walk at random on a context map. """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, context_map, next_step_proposal, next_step_proposal_arguments):
 | 
			
		||||
        self.size = context_map.shape[0]
 | 
			
		||||
        # Make sure that the context map is normalized
 | 
			
		||||
        context_map /= context_map.sum()
 | 
			
		||||
        self.context_map = context_map
 | 
			
		||||
        
 | 
			
		||||
        self.next_step_proposal = next_step_proposal
 | 
			
		||||
        self.next_step_proposal_arguments = next_step_proposal_arguments
 | 
			
		||||
 | 
			
		||||
    # --- Walker public interface
 | 
			
		||||
 | 
			
		||||
    def sample_next_step(self, current_i, current_j, random_state=np.random):
 | 
			
		||||
        """ Sample a new position for the walker. """
 | 
			
		||||
 | 
			
		||||
        # Combine the next-step proposal with the context map to get a
 | 
			
		||||
        # next-step probability map
 | 
			
		||||
        next_step_map = self.next_step_proposal(
 | 
			
		||||
            current_i, current_j, self.size, **self.next_step_proposal_arguments)
 | 
			
		||||
        selection_map = self._compute_next_step_probability(next_step_map)
 | 
			
		||||
 | 
			
		||||
        # Draw a new position from the next-step probability map
 | 
			
		||||
        r = random_state.rand()
 | 
			
		||||
        cumulative_map = np.cumsum(selection_map)
 | 
			
		||||
        cumulative_map = cumulative_map.reshape(selection_map.shape)
 | 
			
		||||
        i_next, j_next = np.argwhere(cumulative_map >= r)[0]
 | 
			
		||||
 | 
			
		||||
        return i_next, j_next
 | 
			
		||||
 | 
			
		||||
    # --- Walker non-public interface
 | 
			
		||||
 | 
			
		||||
    def _next_step_proposal(self, current_i, current_j):
 | 
			
		||||
        """ Create the 2D proposal map for the next step of the walker. """
 | 
			
		||||
 | 
			
		||||
        # 2D Gaussian distribution , centered at current position,
 | 
			
		||||
        # and with different standard deviations for i and j
 | 
			
		||||
        grid_ii, grid_jj = self._grid_ii, self._grid_jj
 | 
			
		||||
        sigma_i, sigma_j = self.sigma_i, self.sigma_j
 | 
			
		||||
 | 
			
		||||
        rad = (
 | 
			
		||||
            (((grid_ii - current_i) ** 2) / (sigma_i ** 2))
 | 
			
		||||
            + (((grid_jj - current_j) ** 2) / (sigma_j ** 2))
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        p_next_step = np.exp(-(rad / 2.0)) / (2.0 * np.pi * sigma_i * sigma_j)
 | 
			
		||||
        return p_next_step / p_next_step.sum()
 | 
			
		||||
 | 
			
		||||
    def _compute_next_step_probability(self, next_step_map):
 | 
			
		||||
        """ Compute the next step probability map from next step proposal and
 | 
			
		||||
        context map. """
 | 
			
		||||
        next_step_probability = next_step_map * self.context_map
 | 
			
		||||
        next_step_probability /= next_step_probability.sum()
 | 
			
		||||
        return next_step_probability
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,60 @@
 | 
			
		|||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Walker:
 | 
			
		||||
    """ The Walker knows how to walk at random on a context map. """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, sigma_i, sigma_j, context_map):
 | 
			
		||||
        self.sigma_i = sigma_i
 | 
			
		||||
        self.sigma_j = sigma_j
 | 
			
		||||
        self.size = context_map.shape[0]
 | 
			
		||||
        # Make sure that the context map is normalized
 | 
			
		||||
        context_map /= context_map.sum()
 | 
			
		||||
        self.context_map = context_map
 | 
			
		||||
 | 
			
		||||
        # Pre-compute a 2D grid of coordinates for efficiency
 | 
			
		||||
        self._grid_ii, self._grid_jj = np.mgrid[0:self.size, 0:self.size]
 | 
			
		||||
 | 
			
		||||
    # --- Walker public interface
 | 
			
		||||
 | 
			
		||||
    def sample_next_step(self, current_i, current_j, random_state=np.random):
 | 
			
		||||
        """ Sample a new position for the walker. """
 | 
			
		||||
 | 
			
		||||
        # Combine the next-step proposal with the context map to get a
 | 
			
		||||
        # next-step probability map
 | 
			
		||||
        next_step_map = self._next_step_proposal(current_i, current_j)
 | 
			
		||||
        selection_map = self._compute_next_step_probability(next_step_map)
 | 
			
		||||
 | 
			
		||||
        # Draw a new position from the next-step probability map
 | 
			
		||||
        r = random_state.rand()
 | 
			
		||||
        cumulative_map = np.cumsum(selection_map)
 | 
			
		||||
        cumulative_map = cumulative_map.reshape(selection_map.shape)
 | 
			
		||||
        i_next, j_next = np.argwhere(cumulative_map >= r)[0]
 | 
			
		||||
 | 
			
		||||
        return i_next, j_next
 | 
			
		||||
 | 
			
		||||
    # --- Walker non-public interface
 | 
			
		||||
 | 
			
		||||
    def _next_step_proposal(self, current_i, current_j):
 | 
			
		||||
        """ Create the 2D proposal map for the next step of the walker. """
 | 
			
		||||
 | 
			
		||||
        # 2D Gaussian distribution , centered at current position,
 | 
			
		||||
        # and with different standard deviations for i and j
 | 
			
		||||
        grid_ii, grid_jj = self._grid_ii, self._grid_jj
 | 
			
		||||
        sigma_i, sigma_j = self.sigma_i, self.sigma_j
 | 
			
		||||
 | 
			
		||||
        rad = (
 | 
			
		||||
            (((grid_ii - current_i) ** 2) / (sigma_i ** 2))
 | 
			
		||||
            + (((grid_jj - current_j) ** 2) / (sigma_j ** 2))
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        p_next_step = np.exp(-(rad / 2.0)) / (2.0 * np.pi * sigma_i * sigma_j)
 | 
			
		||||
        return p_next_step / p_next_step.sum()
 | 
			
		||||
 | 
			
		||||
    def _compute_next_step_probability(self, next_step_map):
 | 
			
		||||
        """ Compute the next step probability map from next step proposal and
 | 
			
		||||
        context map. """
 | 
			
		||||
        next_step_probability = next_step_map * self.context_map
 | 
			
		||||
        next_step_probability /= next_step_probability.sum()
 | 
			
		||||
        return next_step_probability
 | 
			
		||||
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							
							
								
								
									
										39
									
								
								notebooks/walker/Step_5_reproducibility/context_maps.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								notebooks/walker/Step_5_reproducibility/context_maps.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
""" CONTEXT MAP BUILDERS """
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def flat_context_map_builder(size):
 | 
			
		||||
    """ A context map where all positions are equally likely. """
 | 
			
		||||
    return np.ones((size, size))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def hills_context_map_builder(size):
 | 
			
		||||
    """ A context map with bumps and valleys. """
 | 
			
		||||
    grid_ii, grid_jj = np.mgrid[0:size, 0:size]
 | 
			
		||||
    i_waves = np.sin(grid_ii / 130) + np.sin(grid_ii / 10)
 | 
			
		||||
    i_waves /= i_waves.max()
 | 
			
		||||
    j_waves = np.sin(grid_jj / 100) + np.sin(grid_jj / 50) + \
 | 
			
		||||
        np.sin(grid_jj / 10)
 | 
			
		||||
    j_waves /= j_waves.max()
 | 
			
		||||
    context_map = j_waves + i_waves
 | 
			
		||||
    return context_map
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def labyrinth_context_map_builder(size):
 | 
			
		||||
    """ A context map that looks like a labyrinth. """
 | 
			
		||||
    context_map = np.ones((size, size))
 | 
			
		||||
    context_map[50:100, 50:60] = 0
 | 
			
		||||
    context_map[20:89, 80:90] = 0
 | 
			
		||||
    context_map[90:120, 0:10] = 0
 | 
			
		||||
    context_map[120:size, 30:40] = 0
 | 
			
		||||
    context_map[180:190, 50:60] = 0
 | 
			
		||||
 | 
			
		||||
    context_map[50:60, 50:200] = 0
 | 
			
		||||
    context_map[179:189, 80:130] = 0
 | 
			
		||||
    context_map[110:120, 0:190] = 0
 | 
			
		||||
    context_map[120:size, 30:40] = 0
 | 
			
		||||
    context_map[180:190, 50:60] = 0
 | 
			
		||||
 | 
			
		||||
    return context_map
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										1
									
								
								notebooks/walker/Step_5_reproducibility/exercise
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								notebooks/walker/Step_5_reproducibility/exercise
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
 | 
			
		||||
							
								
								
									
										22
									
								
								notebooks/walker/Step_5_reproducibility/plotting.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								notebooks/walker/Step_5_reproducibility/plotting.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
import matplotlib.pyplot as plt
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def plot_trajectory(trajectory, context_map):
 | 
			
		||||
    """ Plot a trajectory over a context map. """
 | 
			
		||||
    trajectory = np.asarray(trajectory)
 | 
			
		||||
    plt.matshow(context_map)
 | 
			
		||||
    plt.plot(trajectory[:, 1], trajectory[:, 0], color='r')
 | 
			
		||||
    plt.show()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def plot_trajectory_hexbin(trajectory):
 | 
			
		||||
    """ Plot an hexagonal density map of a trajectory. """
 | 
			
		||||
    trajectory = np.asarray(trajectory)
 | 
			
		||||
    with plt.rc_context({'figure.figsize': (4, 4), 'axes.labelsize': 16, 
 | 
			
		||||
                         'xtick.labelsize': 14, 'ytick.labelsize': 14}):
 | 
			
		||||
        plt.hexbin(trajectory[:, 1], trajectory[:, 0], gridsize=30,
 | 
			
		||||
                   extent=(0, 200, 0, 200), edgecolors='none', cmap='Reds')
 | 
			
		||||
        plt.gca().invert_yaxis()
 | 
			
		||||
        plt.xlabel('X')
 | 
			
		||||
        plt.ylabel('Y')
 | 
			
		||||
							
								
								
									
										42
									
								
								notebooks/walker/Step_5_reproducibility/run.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								notebooks/walker/Step_5_reproducibility/run.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,42 @@
 | 
			
		|||
import json
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
import git
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
import context_maps
 | 
			
		||||
from walker import Walker
 | 
			
		||||
 | 
			
		||||
# Use the following parameters to simulate and save a trajectory of the walker
 | 
			
		||||
 | 
			
		||||
seed = 42
 | 
			
		||||
sigma_i = 3
 | 
			
		||||
sigma_j = 4
 | 
			
		||||
size = 200
 | 
			
		||||
i, j = (50, 100)
 | 
			
		||||
n_iterations = 1000
 | 
			
		||||
# USE map_type hills
 | 
			
		||||
random_state = np.random.RandomState(seed)
 | 
			
		||||
 | 
			
		||||
# STEP 1: Create a context map
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# STEP 2: Create a Walker
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# STEP 3: Simulate the walk
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# STEP 4: Save the trajectory
 | 
			
		||||
curr_time = time.strftime("%Y%m%d-%H%M%S")
 | 
			
		||||
# save the npy file here!
 | 
			
		||||
 | 
			
		||||
# STEP 5: Save the metadata
 | 
			
		||||
# lookup git repository
 | 
			
		||||
repo = git.Repo(search_parent_directories=True)
 | 
			
		||||
sha = repo.head.object.hexsha
 | 
			
		||||
 | 
			
		||||
with open('meta.txt', 'w') as f:
 | 
			
		||||
    f.write(f'I estimated parameters at {curr_time}.\n')
 | 
			
		||||
    f.write(f'The git repo was at commit {sha}')
 | 
			
		||||
    # you can add any other information you want here!
 | 
			
		||||
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
""" CONTEXT MAP BUILDERS """
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def flat_context_map_builder(size):
 | 
			
		||||
    """ A context map where all positions are equally likely. """
 | 
			
		||||
    return np.ones((size, size))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def hills_context_map_builder(size):
 | 
			
		||||
    """ A context map with bumps and valleys. """
 | 
			
		||||
    grid_ii, grid_jj = np.mgrid[0:size, 0:size]
 | 
			
		||||
    i_waves = np.sin(grid_ii / 130) + np.sin(grid_ii / 10)
 | 
			
		||||
    i_waves /= i_waves.max()
 | 
			
		||||
    j_waves = np.sin(grid_jj / 100) + np.sin(grid_jj / 50) + \
 | 
			
		||||
        np.sin(grid_jj / 10)
 | 
			
		||||
    j_waves /= j_waves.max()
 | 
			
		||||
    context_map = j_waves + i_waves
 | 
			
		||||
    return context_map
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def labyrinth_context_map_builder(size):
 | 
			
		||||
    """ A context map that looks like a labyrinth. """
 | 
			
		||||
    context_map = np.ones((size, size))
 | 
			
		||||
    context_map[50:100, 50:60] = 0
 | 
			
		||||
    context_map[20:89, 80:90] = 0
 | 
			
		||||
    context_map[90:120, 0:10] = 0
 | 
			
		||||
    context_map[120:size, 30:40] = 0
 | 
			
		||||
    context_map[180:190, 50:60] = 0
 | 
			
		||||
 | 
			
		||||
    context_map[50:60, 50:200] = 0
 | 
			
		||||
    context_map[179:189, 80:130] = 0
 | 
			
		||||
    context_map[110:120, 0:190] = 0
 | 
			
		||||
    context_map[120:size, 30:40] = 0
 | 
			
		||||
    context_map[180:190, 50:60] = 0
 | 
			
		||||
 | 
			
		||||
    return context_map
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,2 @@
 | 
			
		|||
I estimated parameters at 20230628-192022.
 | 
			
		||||
The git repo was at commit 6a26566a46593a650ebfc86ebdbb28ee78ace079
 | 
			
		||||
							
								
								
									
										22
									
								
								notebooks/walker/Step_5_reproducibility/solution/plotting.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								notebooks/walker/Step_5_reproducibility/solution/plotting.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
import matplotlib.pyplot as plt
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def plot_trajectory(trajectory, context_map):
 | 
			
		||||
    """ Plot a trajectory over a context map. """
 | 
			
		||||
    trajectory = np.asarray(trajectory)
 | 
			
		||||
    plt.matshow(context_map)
 | 
			
		||||
    plt.plot(trajectory[:, 1], trajectory[:, 0], color='r')
 | 
			
		||||
    plt.show()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def plot_trajectory_hexbin(trajectory):
 | 
			
		||||
    """ Plot an hexagonal density map of a trajectory. """
 | 
			
		||||
    trajectory = np.asarray(trajectory)
 | 
			
		||||
    with plt.rc_context({'figure.figsize': (4, 4), 'axes.labelsize': 16, 
 | 
			
		||||
                         'xtick.labelsize': 14, 'ytick.labelsize': 14}):
 | 
			
		||||
        plt.hexbin(trajectory[:, 1], trajectory[:, 0], gridsize=30,
 | 
			
		||||
                   extent=(0, 200, 0, 200), edgecolors='none', cmap='Reds')
 | 
			
		||||
        plt.gca().invert_yaxis()
 | 
			
		||||
        plt.xlabel('X')
 | 
			
		||||
        plt.ylabel('Y')
 | 
			
		||||
							
								
								
									
										46
									
								
								notebooks/walker/Step_5_reproducibility/solution/run.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								notebooks/walker/Step_5_reproducibility/solution/run.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
import json
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
import git
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
import context_maps
 | 
			
		||||
from walker import Walker
 | 
			
		||||
 | 
			
		||||
# Use the following parameters to simulate and save a trajectory of the walker
 | 
			
		||||
 | 
			
		||||
seed = 42
 | 
			
		||||
sigma_i = 3
 | 
			
		||||
sigma_j = 4
 | 
			
		||||
size = 200
 | 
			
		||||
i, j = (50, 100)
 | 
			
		||||
n_iterations = 1000
 | 
			
		||||
# USE map_type hills
 | 
			
		||||
random_state = np.random.RandomState(seed)
 | 
			
		||||
 | 
			
		||||
# STEP 1: Create a context map
 | 
			
		||||
context_map = context_maps.hills_context_map_builder(size)
 | 
			
		||||
 | 
			
		||||
# STEP 2: Create a Walker
 | 
			
		||||
walker = Walker(sigma_i, sigma_j, context_map)
 | 
			
		||||
 | 
			
		||||
# STEP 3: Simulate the walk
 | 
			
		||||
 | 
			
		||||
trajectory = []
 | 
			
		||||
for _ in range(n_iterations):
 | 
			
		||||
    i, j = walker.sample_next_step(i, j, random_state)
 | 
			
		||||
    trajectory.append((i, j))
 | 
			
		||||
 | 
			
		||||
# STEP 4: Save the trajectory
 | 
			
		||||
curr_time = time.strftime("%Y%m%d-%H%M%S")
 | 
			
		||||
np.save(f"sim_{curr_time}", trajectory)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# STEP 5: Save the metadata
 | 
			
		||||
# lookup git repository
 | 
			
		||||
repo = git.Repo(search_parent_directories=True)
 | 
			
		||||
sha = repo.head.object.hexsha
 | 
			
		||||
 | 
			
		||||
with open('meta.txt', 'w') as f:
 | 
			
		||||
    f.write(f'I estimated parameters at {curr_time}.\n')
 | 
			
		||||
    f.write(f'The git repo was at commit {sha}')
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										60
									
								
								notebooks/walker/Step_5_reproducibility/solution/walker.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								notebooks/walker/Step_5_reproducibility/solution/walker.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,60 @@
 | 
			
		|||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Walker:
 | 
			
		||||
    """ The Walker knows how to walk at random on a context map. """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, sigma_i, sigma_j, context_map):
 | 
			
		||||
        self.sigma_i = sigma_i
 | 
			
		||||
        self.sigma_j = sigma_j
 | 
			
		||||
        self.size = context_map.shape[0]
 | 
			
		||||
        # Make sure that the context map is normalized
 | 
			
		||||
        context_map /= context_map.sum()
 | 
			
		||||
        self.context_map = context_map
 | 
			
		||||
 | 
			
		||||
        # Pre-compute a 2D grid of coordinates for efficiency
 | 
			
		||||
        self._grid_ii, self._grid_jj = np.mgrid[0:self.size, 0:self.size]
 | 
			
		||||
 | 
			
		||||
    # --- Walker public interface
 | 
			
		||||
 | 
			
		||||
    def sample_next_step(self, current_i, current_j, random_state=np.random):
 | 
			
		||||
        """ Sample a new position for the walker. """
 | 
			
		||||
 | 
			
		||||
        # Combine the next-step proposal with the context map to get a
 | 
			
		||||
        # next-step probability map
 | 
			
		||||
        next_step_map = self._next_step_proposal(current_i, current_j)
 | 
			
		||||
        selection_map = self._compute_next_step_probability(next_step_map)
 | 
			
		||||
 | 
			
		||||
        # Draw a new position from the next-step probability map
 | 
			
		||||
        r = random_state.rand()
 | 
			
		||||
        cumulative_map = np.cumsum(selection_map)
 | 
			
		||||
        cumulative_map = cumulative_map.reshape(selection_map.shape)
 | 
			
		||||
        i_next, j_next = np.argwhere(cumulative_map >= r)[0]
 | 
			
		||||
 | 
			
		||||
        return i_next, j_next
 | 
			
		||||
 | 
			
		||||
    # --- Walker non-public interface
 | 
			
		||||
 | 
			
		||||
    def _next_step_proposal(self, current_i, current_j):
 | 
			
		||||
        """ Create the 2D proposal map for the next step of the walker. """
 | 
			
		||||
 | 
			
		||||
        # 2D Gaussian distribution , centered at current position,
 | 
			
		||||
        # and with different standard deviations for i and j
 | 
			
		||||
        grid_ii, grid_jj = self._grid_ii, self._grid_jj
 | 
			
		||||
        sigma_i, sigma_j = self.sigma_i, self.sigma_j
 | 
			
		||||
 | 
			
		||||
        rad = (
 | 
			
		||||
            (((grid_ii - current_i) ** 2) / (sigma_i ** 2))
 | 
			
		||||
            + (((grid_jj - current_j) ** 2) / (sigma_j ** 2))
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        p_next_step = np.exp(-(rad / 2.0)) / (2.0 * np.pi * sigma_i * sigma_j)
 | 
			
		||||
        return p_next_step / p_next_step.sum()
 | 
			
		||||
 | 
			
		||||
    def _compute_next_step_probability(self, next_step_map):
 | 
			
		||||
        """ Compute the next step probability map from next step proposal and
 | 
			
		||||
        context map. """
 | 
			
		||||
        next_step_probability = next_step_map * self.context_map
 | 
			
		||||
        next_step_probability /= next_step_probability.sum()
 | 
			
		||||
        return next_step_probability
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										60
									
								
								notebooks/walker/Step_5_reproducibility/walker.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								notebooks/walker/Step_5_reproducibility/walker.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,60 @@
 | 
			
		|||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Walker:
 | 
			
		||||
    """ The Walker knows how to walk at random on a context map. """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, sigma_i, sigma_j, context_map):
 | 
			
		||||
        self.sigma_i = sigma_i
 | 
			
		||||
        self.sigma_j = sigma_j
 | 
			
		||||
        self.size = context_map.shape[0]
 | 
			
		||||
        # Make sure that the context map is normalized
 | 
			
		||||
        context_map /= context_map.sum()
 | 
			
		||||
        self.context_map = context_map
 | 
			
		||||
 | 
			
		||||
        # Pre-compute a 2D grid of coordinates for efficiency
 | 
			
		||||
        self._grid_ii, self._grid_jj = np.mgrid[0:self.size, 0:self.size]
 | 
			
		||||
 | 
			
		||||
    # --- Walker public interface
 | 
			
		||||
 | 
			
		||||
    def sample_next_step(self, current_i, current_j, random_state=np.random):
 | 
			
		||||
        """ Sample a new position for the walker. """
 | 
			
		||||
 | 
			
		||||
        # Combine the next-step proposal with the context map to get a
 | 
			
		||||
        # next-step probability map
 | 
			
		||||
        next_step_map = self._next_step_proposal(current_i, current_j)
 | 
			
		||||
        selection_map = self._compute_next_step_probability(next_step_map)
 | 
			
		||||
 | 
			
		||||
        # Draw a new position from the next-step probability map
 | 
			
		||||
        r = random_state.rand()
 | 
			
		||||
        cumulative_map = np.cumsum(selection_map)
 | 
			
		||||
        cumulative_map = cumulative_map.reshape(selection_map.shape)
 | 
			
		||||
        i_next, j_next = np.argwhere(cumulative_map >= r)[0]
 | 
			
		||||
 | 
			
		||||
        return i_next, j_next
 | 
			
		||||
 | 
			
		||||
    # --- Walker non-public interface
 | 
			
		||||
 | 
			
		||||
    def _next_step_proposal(self, current_i, current_j):
 | 
			
		||||
        """ Create the 2D proposal map for the next step of the walker. """
 | 
			
		||||
 | 
			
		||||
        # 2D Gaussian distribution , centered at current position,
 | 
			
		||||
        # and with different standard deviations for i and j
 | 
			
		||||
        grid_ii, grid_jj = self._grid_ii, self._grid_jj
 | 
			
		||||
        sigma_i, sigma_j = self.sigma_i, self.sigma_j
 | 
			
		||||
 | 
			
		||||
        rad = (
 | 
			
		||||
            (((grid_ii - current_i) ** 2) / (sigma_i ** 2))
 | 
			
		||||
            + (((grid_jj - current_j) ** 2) / (sigma_j ** 2))
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        p_next_step = np.exp(-(rad / 2.0)) / (2.0 * np.pi * sigma_i * sigma_j)
 | 
			
		||||
        return p_next_step / p_next_step.sum()
 | 
			
		||||
 | 
			
		||||
    def _compute_next_step_probability(self, next_step_map):
 | 
			
		||||
        """ Compute the next step probability map from next step proposal and
 | 
			
		||||
        context map. """
 | 
			
		||||
        next_step_probability = next_step_map * self.context_map
 | 
			
		||||
        next_step_probability /= next_step_probability.sum()
 | 
			
		||||
        return next_step_probability
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,39 @@
 | 
			
		|||
""" CONTEXT MAP BUILDERS """
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def flat_context_map_builder(size):
 | 
			
		||||
    """ A context map where all positions are equally likely. """
 | 
			
		||||
    return np.ones((size, size))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def hills_context_map_builder(size):
 | 
			
		||||
    """ A context map with bumps and valleys. """
 | 
			
		||||
    grid_ii, grid_jj = np.mgrid[0:size, 0:size]
 | 
			
		||||
    i_waves = np.sin(grid_ii / 130) + np.sin(grid_ii / 10)
 | 
			
		||||
    i_waves /= i_waves.max()
 | 
			
		||||
    j_waves = np.sin(grid_jj / 100) + np.sin(grid_jj / 50) + \
 | 
			
		||||
        np.sin(grid_jj / 10)
 | 
			
		||||
    j_waves /= j_waves.max()
 | 
			
		||||
    context_map = j_waves + i_waves
 | 
			
		||||
    return context_map
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def labyrinth_context_map_builder(size):
 | 
			
		||||
    """ A context map that looks like a labyrinth. """
 | 
			
		||||
    context_map = np.ones((size, size))
 | 
			
		||||
    context_map[50:100, 50:60] = 0
 | 
			
		||||
    context_map[20:89, 80:90] = 0
 | 
			
		||||
    context_map[90:120, 0:10] = 0
 | 
			
		||||
    context_map[120:size, 30:40] = 0
 | 
			
		||||
    context_map[180:190, 50:60] = 0
 | 
			
		||||
 | 
			
		||||
    context_map[50:60, 50:200] = 0
 | 
			
		||||
    context_map[179:189, 80:130] = 0
 | 
			
		||||
    context_map[110:120, 0:190] = 0
 | 
			
		||||
    context_map[120:size, 30:40] = 0
 | 
			
		||||
    context_map[180:190, 50:60] = 0
 | 
			
		||||
 | 
			
		||||
    return context_map
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
import matplotlib.pyplot as plt
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def plot_trajectory(trajectory, context_map):
 | 
			
		||||
    """ Plot a trajectory over a context map. """
 | 
			
		||||
    trajectory = np.asarray(trajectory)
 | 
			
		||||
    plt.matshow(context_map)
 | 
			
		||||
    plt.plot(trajectory[:, 1], trajectory[:, 0], color='r')
 | 
			
		||||
    plt.show()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def plot_trajectory_hexbin(trajectory):
 | 
			
		||||
    """ Plot an hexagonal density map of a trajectory. """
 | 
			
		||||
    trajectory = np.asarray(trajectory)
 | 
			
		||||
    with plt.rc_context({'figure.figsize': (4, 4), 'axes.labelsize': 16, 
 | 
			
		||||
                         'xtick.labelsize': 14, 'ytick.labelsize': 14}):
 | 
			
		||||
        plt.hexbin(trajectory[:, 1], trajectory[:, 0], gridsize=30,
 | 
			
		||||
                   extent=(0, 200, 0, 200), edgecolors='none', cmap='Reds')
 | 
			
		||||
        plt.gca().invert_yaxis()
 | 
			
		||||
        plt.xlabel('X')
 | 
			
		||||
        plt.ylabel('Y')
 | 
			
		||||
							
								
								
									
										46
									
								
								notebooks/walker/Step_6_loading_parameters_from_file/run.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								notebooks/walker/Step_6_loading_parameters_from_file/run.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
import json
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
import git
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
import context_maps
 | 
			
		||||
from walker import Walker
 | 
			
		||||
 | 
			
		||||
# Use the following parameters to simulate and save a trajectory of the walker
 | 
			
		||||
 | 
			
		||||
seed = 42
 | 
			
		||||
sigma_i = 3
 | 
			
		||||
sigma_j = 4
 | 
			
		||||
size = 200
 | 
			
		||||
i, j = (50, 100)
 | 
			
		||||
n_iterations = 1000
 | 
			
		||||
# USE map_type hills
 | 
			
		||||
random_state = np.random.RandomState(seed)
 | 
			
		||||
 | 
			
		||||
# STEP 1: Create a context map
 | 
			
		||||
context_map = context_maps.hills_context_map_builder(size)
 | 
			
		||||
 | 
			
		||||
# STEP 2: Create a Walker
 | 
			
		||||
walker = Walker(sigma_i, sigma_j, context_map)
 | 
			
		||||
 | 
			
		||||
# STEP 3: Simulate the walk
 | 
			
		||||
 | 
			
		||||
trajectory = []
 | 
			
		||||
for _ in range(n_iterations):
 | 
			
		||||
    i, j = walker.sample_next_step(i, j, random_state)
 | 
			
		||||
    trajectory.append((i, j))
 | 
			
		||||
 | 
			
		||||
# STEP 4: Save the trajectory
 | 
			
		||||
curr_time = time.strftime("%Y%m%d-%H%M%S")
 | 
			
		||||
np.save(f"sim_{curr_time}", trajectory)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# STEP 5: Save the metadata
 | 
			
		||||
# lookup git repository
 | 
			
		||||
repo = git.Repo(search_parent_directories=True)
 | 
			
		||||
sha = repo.head.object.hexsha
 | 
			
		||||
 | 
			
		||||
with open('meta.txt', 'w') as f:
 | 
			
		||||
    f.write(f'I estimated parameters at {curr_time}.\n')
 | 
			
		||||
    f.write(f'The git repo was at commit {sha}')
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
""" CONTEXT MAP BUILDERS """
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def flat_context_map_builder(size):
 | 
			
		||||
    """ A context map where all positions are equally likely. """
 | 
			
		||||
    return np.ones((size, size))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def hills_context_map_builder(size):
 | 
			
		||||
    """ A context map with bumps and valleys. """
 | 
			
		||||
    grid_ii, grid_jj = np.mgrid[0:size, 0:size]
 | 
			
		||||
    i_waves = np.sin(grid_ii / 130) + np.sin(grid_ii / 10)
 | 
			
		||||
    i_waves /= i_waves.max()
 | 
			
		||||
    j_waves = np.sin(grid_jj / 100) + np.sin(grid_jj / 50) + \
 | 
			
		||||
        np.sin(grid_jj / 10)
 | 
			
		||||
    j_waves /= j_waves.max()
 | 
			
		||||
    context_map = j_waves + i_waves
 | 
			
		||||
    return context_map
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def labyrinth_context_map_builder(size):
 | 
			
		||||
    """ A context map that looks like a labyrinth. """
 | 
			
		||||
    context_map = np.ones((size, size))
 | 
			
		||||
    context_map[50:100, 50:60] = 0
 | 
			
		||||
    context_map[20:89, 80:90] = 0
 | 
			
		||||
    context_map[90:120, 0:10] = 0
 | 
			
		||||
    context_map[120:size, 30:40] = 0
 | 
			
		||||
    context_map[180:190, 50:60] = 0
 | 
			
		||||
 | 
			
		||||
    context_map[50:60, 50:200] = 0
 | 
			
		||||
    context_map[179:189, 80:130] = 0
 | 
			
		||||
    context_map[110:120, 0:190] = 0
 | 
			
		||||
    context_map[120:size, 30:40] = 0
 | 
			
		||||
    context_map[180:190, 50:60] = 0
 | 
			
		||||
 | 
			
		||||
    return context_map
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# Register map builders
 | 
			
		||||
map_builders = {
 | 
			
		||||
    "flat": flat_context_map_builder,
 | 
			
		||||
    "hills": hills_context_map_builder,
 | 
			
		||||
    "labyrinth": labyrinth_context_map_builder,
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,10 @@
 | 
			
		|||
{
 | 
			
		||||
    "seed": 42,
 | 
			
		||||
    "sigma_i": 3,
 | 
			
		||||
    "sigma_j": 4,
 | 
			
		||||
    "size": 200,
 | 
			
		||||
    "map_type": "hills",
 | 
			
		||||
    "start_i": 50,
 | 
			
		||||
    "start_j": 100,
 | 
			
		||||
    "n_iterations": 1000
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,22 @@
 | 
			
		|||
import matplotlib.pyplot as plt
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def plot_trajectory(trajectory, context_map):
 | 
			
		||||
    """ Plot a trajectory over a context map. """
 | 
			
		||||
    trajectory = np.asarray(trajectory)
 | 
			
		||||
    plt.matshow(context_map)
 | 
			
		||||
    plt.plot(trajectory[:, 1], trajectory[:, 0], color='r')
 | 
			
		||||
    plt.show()
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
def plot_trajectory_hexbin(trajectory):
 | 
			
		||||
    """ Plot an hexagonal density map of a trajectory. """
 | 
			
		||||
    trajectory = np.asarray(trajectory)
 | 
			
		||||
    with plt.rc_context({'figure.figsize': (4, 4), 'axes.labelsize': 16, 
 | 
			
		||||
                         'xtick.labelsize': 14, 'ytick.labelsize': 14}):
 | 
			
		||||
        plt.hexbin(trajectory[:, 1], trajectory[:, 0], gridsize=30,
 | 
			
		||||
                   extent=(0, 200, 0, 200), edgecolors='none', cmap='Reds')
 | 
			
		||||
        plt.gca().invert_yaxis()
 | 
			
		||||
        plt.xlabel('X')
 | 
			
		||||
        plt.ylabel('Y')
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,42 @@
 | 
			
		|||
import json
 | 
			
		||||
import time
 | 
			
		||||
 | 
			
		||||
import git
 | 
			
		||||
import numpy as np
 | 
			
		||||
 | 
			
		||||
from walker import Walker
 | 
			
		||||
from context_maps import map_builders
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
with open("inputs.json", 'r') as f:
 | 
			
		||||
    inputs = json.load(f)
 | 
			
		||||
 | 
			
		||||
random_state = np.random.RandomState(inputs["seed"])
 | 
			
		||||
n_iterations = inputs["n_iterations"]
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
context_map_builder = map_builders[inputs["map_type"]]
 | 
			
		||||
context_map = context_map_builder(inputs["size"])
 | 
			
		||||
walker = Walker(inputs["sigma_i"], inputs["sigma_j"], context_map)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
trajectory = []
 | 
			
		||||
for _ in range(n_iterations):
 | 
			
		||||
    i, j = walker.sample_next_step(inputs["start_i"], inputs["start_j"],
 | 
			
		||||
                                   random_state)
 | 
			
		||||
    trajectory.append((i, j))
 | 
			
		||||
 | 
			
		||||
# STEP 4: Save the trajectory
 | 
			
		||||
curr_time = time.strftime("%Y%m%d-%H%M%S")
 | 
			
		||||
np.save(f"sim_{curr_time}", trajectory)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
# STEP 5: Save the metadata
 | 
			
		||||
# lookup git repository
 | 
			
		||||
repo = git.Repo(search_parent_directories=True)
 | 
			
		||||
sha = repo.head.object.hexsha
 | 
			
		||||
 | 
			
		||||
with open('meta.txt', 'w') as f:
 | 
			
		||||
    f.write(f'I estimated parameters at {curr_time}.\n')
 | 
			
		||||
    f.write(f'The git repo was at commit {sha}')
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,60 @@
 | 
			
		|||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Walker:
 | 
			
		||||
    """ The Walker knows how to walk at random on a context map. """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, sigma_i, sigma_j, context_map):
 | 
			
		||||
        self.sigma_i = sigma_i
 | 
			
		||||
        self.sigma_j = sigma_j
 | 
			
		||||
        self.size = context_map.shape[0]
 | 
			
		||||
        # Make sure that the context map is normalized
 | 
			
		||||
        context_map /= context_map.sum()
 | 
			
		||||
        self.context_map = context_map
 | 
			
		||||
 | 
			
		||||
        # Pre-compute a 2D grid of coordinates for efficiency
 | 
			
		||||
        self._grid_ii, self._grid_jj = np.mgrid[0:self.size, 0:self.size]
 | 
			
		||||
 | 
			
		||||
    # --- Walker public interface
 | 
			
		||||
 | 
			
		||||
    def sample_next_step(self, current_i, current_j, random_state=np.random):
 | 
			
		||||
        """ Sample a new position for the walker. """
 | 
			
		||||
 | 
			
		||||
        # Combine the next-step proposal with the context map to get a
 | 
			
		||||
        # next-step probability map
 | 
			
		||||
        next_step_map = self._next_step_proposal(current_i, current_j)
 | 
			
		||||
        selection_map = self._compute_next_step_probability(next_step_map)
 | 
			
		||||
 | 
			
		||||
        # Draw a new position from the next-step probability map
 | 
			
		||||
        r = random_state.rand()
 | 
			
		||||
        cumulative_map = np.cumsum(selection_map)
 | 
			
		||||
        cumulative_map = cumulative_map.reshape(selection_map.shape)
 | 
			
		||||
        i_next, j_next = np.argwhere(cumulative_map >= r)[0]
 | 
			
		||||
 | 
			
		||||
        return i_next, j_next
 | 
			
		||||
 | 
			
		||||
    # --- Walker non-public interface
 | 
			
		||||
 | 
			
		||||
    def _next_step_proposal(self, current_i, current_j):
 | 
			
		||||
        """ Create the 2D proposal map for the next step of the walker. """
 | 
			
		||||
 | 
			
		||||
        # 2D Gaussian distribution , centered at current position,
 | 
			
		||||
        # and with different standard deviations for i and j
 | 
			
		||||
        grid_ii, grid_jj = self._grid_ii, self._grid_jj
 | 
			
		||||
        sigma_i, sigma_j = self.sigma_i, self.sigma_j
 | 
			
		||||
 | 
			
		||||
        rad = (
 | 
			
		||||
            (((grid_ii - current_i) ** 2) / (sigma_i ** 2))
 | 
			
		||||
            + (((grid_jj - current_j) ** 2) / (sigma_j ** 2))
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        p_next_step = np.exp(-(rad / 2.0)) / (2.0 * np.pi * sigma_i * sigma_j)
 | 
			
		||||
        return p_next_step / p_next_step.sum()
 | 
			
		||||
 | 
			
		||||
    def _compute_next_step_probability(self, next_step_map):
 | 
			
		||||
        """ Compute the next step probability map from next step proposal and
 | 
			
		||||
        context map. """
 | 
			
		||||
        next_step_probability = next_step_map * self.context_map
 | 
			
		||||
        next_step_probability /= next_step_probability.sum()
 | 
			
		||||
        return next_step_probability
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,60 @@
 | 
			
		|||
import numpy as np
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class Walker:
 | 
			
		||||
    """ The Walker knows how to walk at random on a context map. """
 | 
			
		||||
 | 
			
		||||
    def __init__(self, sigma_i, sigma_j, context_map):
 | 
			
		||||
        self.sigma_i = sigma_i
 | 
			
		||||
        self.sigma_j = sigma_j
 | 
			
		||||
        self.size = context_map.shape[0]
 | 
			
		||||
        # Make sure that the context map is normalized
 | 
			
		||||
        context_map /= context_map.sum()
 | 
			
		||||
        self.context_map = context_map
 | 
			
		||||
 | 
			
		||||
        # Pre-compute a 2D grid of coordinates for efficiency
 | 
			
		||||
        self._grid_ii, self._grid_jj = np.mgrid[0:self.size, 0:self.size]
 | 
			
		||||
 | 
			
		||||
    # --- Walker public interface
 | 
			
		||||
 | 
			
		||||
    def sample_next_step(self, current_i, current_j, random_state=np.random):
 | 
			
		||||
        """ Sample a new position for the walker. """
 | 
			
		||||
 | 
			
		||||
        # Combine the next-step proposal with the context map to get a
 | 
			
		||||
        # next-step probability map
 | 
			
		||||
        next_step_map = self._next_step_proposal(current_i, current_j)
 | 
			
		||||
        selection_map = self._compute_next_step_probability(next_step_map)
 | 
			
		||||
 | 
			
		||||
        # Draw a new position from the next-step probability map
 | 
			
		||||
        r = random_state.rand()
 | 
			
		||||
        cumulative_map = np.cumsum(selection_map)
 | 
			
		||||
        cumulative_map = cumulative_map.reshape(selection_map.shape)
 | 
			
		||||
        i_next, j_next = np.argwhere(cumulative_map >= r)[0]
 | 
			
		||||
 | 
			
		||||
        return i_next, j_next
 | 
			
		||||
 | 
			
		||||
    # --- Walker non-public interface
 | 
			
		||||
 | 
			
		||||
    def _next_step_proposal(self, current_i, current_j):
 | 
			
		||||
        """ Create the 2D proposal map for the next step of the walker. """
 | 
			
		||||
 | 
			
		||||
        # 2D Gaussian distribution , centered at current position,
 | 
			
		||||
        # and with different standard deviations for i and j
 | 
			
		||||
        grid_ii, grid_jj = self._grid_ii, self._grid_jj
 | 
			
		||||
        sigma_i, sigma_j = self.sigma_i, self.sigma_j
 | 
			
		||||
 | 
			
		||||
        rad = (
 | 
			
		||||
            (((grid_ii - current_i) ** 2) / (sigma_i ** 2))
 | 
			
		||||
            + (((grid_jj - current_j) ** 2) / (sigma_j ** 2))
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
        p_next_step = np.exp(-(rad / 2.0)) / (2.0 * np.pi * sigma_i * sigma_j)
 | 
			
		||||
        return p_next_step / p_next_step.sum()
 | 
			
		||||
 | 
			
		||||
    def _compute_next_step_probability(self, next_step_map):
 | 
			
		||||
        """ Compute the next step probability map from next step proposal and
 | 
			
		||||
        context map. """
 | 
			
		||||
        next_step_probability = next_step_map * self.context_map
 | 
			
		||||
        next_step_probability /= next_step_probability.sum()
 | 
			
		||||
        return next_step_probability
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue