diff --git a/paper_code/anisotropy/figure1.py b/packaged-code/anisotropy/figure1.py similarity index 100% rename from paper_code/anisotropy/figure1.py rename to packaged-code/anisotropy/figure1.py diff --git a/paper_code/anisotropy/figure2.py b/packaged-code/anisotropy/figure2.py similarity index 100% rename from paper_code/anisotropy/figure2.py rename to packaged-code/anisotropy/figure2.py diff --git a/paper_code/anisotropy/figure3.py b/packaged-code/anisotropy/figure3.py similarity index 100% rename from paper_code/anisotropy/figure3.py rename to packaged-code/anisotropy/figure3.py diff --git a/paper_code/anisotropy/figure4.py b/packaged-code/anisotropy/figure4.py similarity index 100% rename from paper_code/anisotropy/figure4.py rename to packaged-code/anisotropy/figure4.py diff --git a/paper_code/anisotropy/figure5.py b/packaged-code/anisotropy/figure5.py similarity index 100% rename from paper_code/anisotropy/figure5.py rename to packaged-code/anisotropy/figure5.py diff --git a/paper_code/anisotropy/figure6.py b/packaged-code/anisotropy/figure6.py similarity index 100% rename from paper_code/anisotropy/figure6.py rename to packaged-code/anisotropy/figure6.py diff --git a/paper_code/anisotropy/figure7and8.py b/packaged-code/anisotropy/figure7and8.py similarity index 100% rename from paper_code/anisotropy/figure7and8.py rename to packaged-code/anisotropy/figure7and8.py diff --git a/paper_code/anisotropy/model_bem_flat_plate_experiment.py b/packaged-code/anisotropy/model_bem_flat_plate_experiment.py similarity index 100% rename from paper_code/anisotropy/model_bem_flat_plate_experiment.py rename to packaged-code/anisotropy/model_bem_flat_plate_experiment.py diff --git a/paper_code/anisotropy/model_bem_slot_experiment.py b/packaged-code/anisotropy/model_bem_slot_experiment.py similarity index 100% rename from paper_code/anisotropy/model_bem_slot_experiment.py rename to packaged-code/anisotropy/model_bem_slot_experiment.py diff --git a/paper_code/anisotropy/model_data/corner_anisotropy_data/R1.0_L20_n50000_cn3 b/packaged-code/anisotropy/model_data/corner_anisotropy_data/R1.0_L20_n50000_cn3 similarity index 100% rename from paper_code/anisotropy/model_data/corner_anisotropy_data/R1.0_L20_n50000_cn3 rename to packaged-code/anisotropy/model_data/corner_anisotropy_data/R1.0_L20_n50000_cn3 diff --git a/paper_code/anisotropy/model_data/corner_anisotropy_sweep.py b/packaged-code/anisotropy/model_data/corner_anisotropy_sweep.py similarity index 100% rename from paper_code/anisotropy/model_data/corner_anisotropy_sweep.py rename to packaged-code/anisotropy/model_data/corner_anisotropy_sweep.py diff --git a/paper_code/anisotropy/model_data/slot_anisotropy_data/anisotropy_sweep_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0_N33.csv b/packaged-code/anisotropy/model_data/slot_anisotropy_data/anisotropy_sweep_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0_N33.csv similarity index 100% rename from paper_code/anisotropy/model_data/slot_anisotropy_data/anisotropy_sweep_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0_N33.csv rename to packaged-code/anisotropy/model_data/slot_anisotropy_data/anisotropy_sweep_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0_N33.csv diff --git a/paper_code/anisotropy/model_data/slot_anisotropy_data/centroids_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0.csv b/packaged-code/anisotropy/model_data/slot_anisotropy_data/centroids_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0.csv similarity index 100% rename from paper_code/anisotropy/model_data/slot_anisotropy_data/centroids_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0.csv rename to packaged-code/anisotropy/model_data/slot_anisotropy_data/centroids_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0.csv diff --git a/paper_code/anisotropy/model_data/slot_anisotropy_data/normals_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0.csv b/packaged-code/anisotropy/model_data/slot_anisotropy_data/normals_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0.csv similarity index 100% rename from paper_code/anisotropy/model_data/slot_anisotropy_data/normals_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0.csv rename to packaged-code/anisotropy/model_data/slot_anisotropy_data/normals_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0.csv diff --git a/paper_code/anisotropy/model_data/slot_anisotropy_sweep.py b/packaged-code/anisotropy/model_data/slot_anisotropy_sweep.py similarity index 100% rename from paper_code/anisotropy/model_data/slot_anisotropy_sweep.py rename to packaged-code/anisotropy/model_data/slot_anisotropy_sweep.py diff --git a/paper_code/anisotropy/model_data/square_anisotropy_data/R1.0_L15_n20000_i32 b/packaged-code/anisotropy/model_data/square_anisotropy_data/R1.0_L15_n20000_i32 similarity index 100% rename from paper_code/anisotropy/model_data/square_anisotropy_data/R1.0_L15_n20000_i32 rename to packaged-code/anisotropy/model_data/square_anisotropy_data/R1.0_L15_n20000_i32 diff --git a/paper_code/anisotropy/model_data/square_anisotropy_sweep.py b/packaged-code/anisotropy/model_data/square_anisotropy_sweep.py similarity index 100% rename from paper_code/anisotropy/model_data/square_anisotropy_sweep.py rename to packaged-code/anisotropy/model_data/square_anisotropy_sweep.py diff --git a/paper_code/anisotropy/model_data/triangle_anisotropy_data/R1.0_L15_n20000_i32 b/packaged-code/anisotropy/model_data/triangle_anisotropy_data/R1.0_L15_n20000_i32 similarity index 100% rename from paper_code/anisotropy/model_data/triangle_anisotropy_data/R1.0_L15_n20000_i32 rename to packaged-code/anisotropy/model_data/triangle_anisotropy_data/R1.0_L15_n20000_i32 diff --git a/paper_code/anisotropy/model_data/triangle_anisotropy_sweep.py b/packaged-code/anisotropy/model_data/triangle_anisotropy_sweep.py similarity index 100% rename from paper_code/anisotropy/model_data/triangle_anisotropy_sweep.py rename to packaged-code/anisotropy/model_data/triangle_anisotropy_sweep.py diff --git a/paper_code/anisotropy/model_sa_corner_experiment.py b/packaged-code/anisotropy/model_sa_corner_experiment.py similarity index 100% rename from paper_code/anisotropy/model_sa_corner_experiment.py rename to packaged-code/anisotropy/model_sa_corner_experiment.py diff --git a/paper_code/anisotropy/model_sa_equi_triangle_experiment.py b/packaged-code/anisotropy/model_sa_equi_triangle_experiment.py similarity index 100% rename from paper_code/anisotropy/model_sa_equi_triangle_experiment.py rename to packaged-code/anisotropy/model_sa_equi_triangle_experiment.py diff --git a/paper_code/anisotropy/model_sa_square_experiment.py b/packaged-code/anisotropy/model_sa_square_experiment.py similarity index 100% rename from paper_code/anisotropy/model_sa_square_experiment.py rename to packaged-code/anisotropy/model_sa_square_experiment.py diff --git a/paper_code/anisotropy/util/analysis_utils.py b/packaged-code/anisotropy/util/analysis_utils.py similarity index 100% rename from paper_code/anisotropy/util/analysis_utils.py rename to packaged-code/anisotropy/util/analysis_utils.py diff --git a/paper_code/anisotropy/util/bem.py b/packaged-code/anisotropy/util/bem.py similarity index 100% rename from paper_code/anisotropy/util/bem.py rename to packaged-code/anisotropy/util/bem.py diff --git a/paper_code/anisotropy/util/determineDisplacement.py b/packaged-code/anisotropy/util/determineDisplacement.py similarity index 100% rename from paper_code/anisotropy/util/determineDisplacement.py rename to packaged-code/anisotropy/util/determineDisplacement.py diff --git a/paper_code/anisotropy/util/file_utils.py b/packaged-code/anisotropy/util/file_utils.py similarity index 100% rename from paper_code/anisotropy/util/file_utils.py rename to packaged-code/anisotropy/util/file_utils.py diff --git a/paper_code/anisotropy/util/gen_utils.py b/packaged-code/anisotropy/util/gen_utils.py similarity index 100% rename from paper_code/anisotropy/util/gen_utils.py rename to packaged-code/anisotropy/util/gen_utils.py diff --git a/paper_code/anisotropy/util/moi_utils.py b/packaged-code/anisotropy/util/moi_utils.py similarity index 100% rename from paper_code/anisotropy/util/moi_utils.py rename to packaged-code/anisotropy/util/moi_utils.py diff --git a/paper_code/anisotropy/util/mp4.py b/packaged-code/anisotropy/util/mp4.py similarity index 100% rename from paper_code/anisotropy/util/mp4.py rename to packaged-code/anisotropy/util/mp4.py diff --git a/paper_code/anisotropy/util/mraw.py b/packaged-code/anisotropy/util/mraw.py similarity index 100% rename from paper_code/anisotropy/util/mraw.py rename to packaged-code/anisotropy/util/mraw.py diff --git a/paper_code/anisotropy/util/plotting_utils.py b/packaged-code/anisotropy/util/plotting_utils.py similarity index 100% rename from paper_code/anisotropy/util/plotting_utils.py rename to packaged-code/anisotropy/util/plotting_utils.py diff --git a/paper_code/anisotropy/util/vector_utils.py b/packaged-code/anisotropy/util/vector_utils.py similarity index 100% rename from paper_code/anisotropy/util/vector_utils.py rename to packaged-code/anisotropy/util/vector_utils.py diff --git a/packaged-code/pacakged-gui/README.md b/packaged-code/pacakged-gui/README.md new file mode 100644 index 0000000000000000000000000000000000000000..558cbfebd7e88b41b7993ef11b9f3681f0d9819e --- /dev/null +++ b/packaged-code/pacakged-gui/README.md @@ -0,0 +1,15 @@ +# Bubble Analysis GUI +`bubble_analysis_gui.py` is a GUI program written with PyQt5 that allows a series of readings to be inspected and analysed easily. A demonstration can be found [here](https://xorg.us/2018-07-18_12-07-23.mp4). + +#### Instructions +1) On running the script a file selection prompt will appear. Select the folder that contains the index.csv file. +2) Find as many readings in your data that contain the same geometry and have a common coordinate (for example a constant y). Navigate to an empty frame (no bubble) and click 'Add Frame' under 'Calibration'. If you select incorrect frames you can restart by clicking 'Clear Frames'. When you have selected a series of frames click 'Calibrate'. This will take a moment to run and will result in a 'mm/px' value being shown in the 'Calibration' status box. +3) You can navigate through your data with the navigation buttons provided or slide the slider to advance through the frames. +4) You can click on a frame to take measurements, left click once at the start of your measurement and again at the end. A red line will appear and the status box at the bottom of the window will show details about your measurement. The angle noted is measured from the positive horizontal (x) direction anti-clockwise (Note: the order in which you choose your points is important in angle measurement). Right clicking will clear your measurement. +5) There are numerous other options for debugging and information. + +#### Recording Data +To use this analysis tool data must be recorded in the correct format. +- index.csv must be a CSV file with headers "x", "y", "idx" (names are not important but order is). +- Each position index should have its own directory containing movies. +It is suggested to view the existing data as a reference. \ No newline at end of file diff --git a/packaged-code/pacakged-gui/bubble_analysis_gui.py b/packaged-code/pacakged-gui/bubble_analysis_gui.py new file mode 100644 index 0000000000000000000000000000000000000000..00f36216db78173b46f71e4bab9edd922f736b28 --- /dev/null +++ b/packaged-code/pacakged-gui/bubble_analysis_gui.py @@ -0,0 +1,1005 @@ +""" +A program that displays frames from positions and allows them to be measured. + +TODO: +- Allow measurements to be saved for use in other scripts + -> Ensure measurements allow for reproducibility and repeatability. + -> Save to file and allow minor variations to assess error. +- Create a better position selection UI (grid of images?). + -> Maybe make a composite image from all the positions after calibration. + -> Snap to the nearest position centered on the cursor (allow clicking and dragging). +(- Implement zooming + -> Zoom parameter exists but zoom center and actual zooming is not implemented.)? +""" + +import ctypes +import importlib +import math +import os +import sys +import time + +import numpy as np +from PyQt5 import QtGui +from PyQt5.QtCore import Qt, QTimer, QSize, QThread, QObject, pyqtSignal +from PyQt5.QtGui import QPainter, QPen, QIcon, QPixmap, QResizeEvent +from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QVBoxLayout, QHBoxLayout, QTextBrowser, QMainWindow, \ + QPushButton, QSlider, QSpacerItem, QSizePolicy, QStyle, QFileDialog, QLayout, QCheckBox + +import util.vector_utils as vect +import util.analysis_utils as au +import util.calibration_utils as cu +import util.determineDisplacement as dd +import util.file_utils as file +import util.mraw_converter as mraw_converter +import util.qt_utils as qtu +from util.pixel_correction import load_norm_mat + + +class JumpSlider(QSlider): + """ From https://stackoverflow.com/a/29639127/5270376 """ + + def mousePressEvent(self, ev): + """ Jump to click position """ + self.setValue(QStyle.sliderValueFromPosition(self.minimum(), self.maximum(), ev.x(), self.width())) + + def mouseMoveEvent(self, ev): + """ Jump to pointer position while moving """ + self.setValue(QStyle.sliderValueFromPosition(self.minimum(), self.maximum(), ev.x(), self.width())) + + +class Player(QObject): + frames = None + fps = None + skip = False + frame_update = pyqtSignal(int) + finished = pyqtSignal() + + def __init__(self, frames=100, fps=30) -> None: + super().__init__() + self.frames = frames + self.fps = fps + + def play(self, i=0): + last_time = None + while i < self.frames and not self.skip: + if last_time is None or time.time() - last_time > 1 / self.fps: + self.frame_update.emit(i) + i += 1 + last_time = time.time() + app.processEvents() + self.skip = False + self.finished.emit() + + +class PositionSelection(QWidget): + """ + TODO: + -> Maybe make a composite image from all the positions after calibration. + -> Snap to the nearest position centered on the cursor (allow clicking and dragging). + """ + + +class ImageDisplayWidget(QWidget): + pixmap = None + + height = None + width = None + + def set_size(self): + self.setMinimumHeight(self.pixmap.height()) + self.setMinimumWidth(self.pixmap.width()) + + self.setMaximumHeight(self.pixmap.height()) + self.setMaximumWidth(self.pixmap.width()) + + def set_image(self, image): + pixmap = qtu.frame_to_pixmap(image) + pixmap = pixmap.scaledToHeight(pixmap.height()) + + self.pixmap = pixmap + + self.set_size() + self.update() + + def set_image_from_png(self, png_path, scale=0.5): + self.pixmap = QPixmap(png_path) + + self.pixmap = self.pixmap.scaledToHeight(int(round(self.pixmap.height() * scale))) + + self.set_size() + + self.update() + + def clear_image(self): + self.pixmap = None + self.setAutoFillBackground(True) + p = self.palette() + p.setColor(self.backgroundRole(), Qt.gray) + self.setPalette(p) + + self.update() + + def paintEvent(self, e): + if self.pixmap is not None: + # Draw frame. + qp = QPainter() + if qp.isActive(): + qp.setRenderHint(QPainter.Antialiasing) + qp.begin(self) + qp.drawPixmap(0, 0, self.pixmap) + qp.end() + + +class DataWidget(QWidget): + point_1 = None + point_2 = None + frame_idx = None + repeat_idx = None + position_idx = None + total_frames = None + movie = None + norm_mat = None + + scale = None + mm_per_pixel = None + + file_dir = None + + positions = None + + position_prefix = None + + draw_binary = False + show_debug = False + raw = False + + def __init__(self, text_area, position_status, file_dir, aux_box: ImageDisplayWidget, main_window: QMainWindow, + scale=1, parent=None, frame_idx=0, max_frames=100): + if parent: + super().__init__(parent) + else: + super().__init__() + self.text_area = text_area + self.position_status = position_status + self.aux_box = aux_box + self.main_window = main_window + + self.frame_idx = frame_idx + self.max_frames = max_frames + + self.scale = scale + + self.change_dir(file_dir) + + self.width = self.scale * 384 + self.height = self.scale * 264 + self.setSizePolicy(QSizePolicy(QSizePolicy.MinimumExpanding, QSizePolicy.MinimumExpanding)) + + # self.setAutoFillBackground(True) + # p = self.palette() + # p.setColor(self.backgroundRole(), Qt.black) + # self.setPalette(p) + + self.update_text() + + def sizeHint(self): + return QSize(384, 264) + + def change_dir(self, file_dir): + # Reset to zero to avoid jumping into a position that doesn't exist + self.frame_idx = 0 + self.repeat_idx = 0 + + self.file_dir = file_dir + self.set_positions(file_dir) + + self.norm_mat = load_norm_mat(file_dir) + if np.std(self.norm_mat) > 0.1: # Something has probably gone wrong + print("Warning: Pixel correction matrix (norm_mat) appears to have malfunctioned and so will be ignored.") + self.norm_mat = None + + self.position_prefix = file.get_prefix_from_idxs(file_dir, np.array(self.positions)[:, 2][0:5]) + + self.set_position(0) + if hasattr(self.main_window, "calibration"): + self.main_window.calibration.load_calibration() + + def set_positions(self, file_dir): + index_file = open(file_dir + "index.csv") + index_lines = index_file.readlines() + + positions = [] # x, y, index + + for i in range(1, len(index_lines)): # Start at 1 to skip header. + split = index_lines[i].strip().split(",") + positions.append([float(split[0]), float(split[1]), split[2]]) # x, y, index number + + # Sort by x + self.positions = sorted(positions, key=lambda r: float(r[2])) + + def update(self): + super().update() + self.update_text() + self.aux_box.update() + self.main_window.update() + + def resizeEvent(self, a0: QResizeEvent) -> None: + last_scale = self.scale + width_ratio = self.frameGeometry().width() / 384 + height_ratio = self.frameGeometry().height() / 264 + self.scale = min(width_ratio, height_ratio) + + if self.point_1 is not None: + self.point_1[0] *= self.scale / last_scale + self.point_1[1] *= self.scale / last_scale + + if self.point_2 is not None: + self.point_2[0] *= self.scale / last_scale + self.point_2[1] *= self.scale / last_scale + + # TODO: Fix this so that the dimension with extra space doesn't expand forever + # self.frameGeometry().setWidth(round(self.scale * 384)) + # self.frameGeometry().setHeight(round(self.scale * 264)) + + def set_position(self, position_idx): + last_position_idx = self.position_idx + self.position_idx = position_idx + r_dir_path = self.file_dir + self.position_prefix + str(self.positions[self.position_idx][2]).rjust(4, + '0') + "/" + if self.movie is not None: + self.movie.close() + + self.movie = file.get_mraw_from_dir(r_dir_path) + self.move_points(last_position_idx) + + def paintEvent(self, e): + r_dir_path = self.file_dir + self.position_prefix + str(self.positions[self.position_idx][2]).rjust(4, + '0') + "/" + image = self.movie[self.frame_idx + self.max_frames * self.repeat_idx] + bg_img = self.movie[0] + binary = dd.makeBinary(np.int32(bg_img) - np.int32(image)) + self.total_frames = self.movie.image_count + + movie_min, movie_max = np.min(image), np.max(image) + + png_path = r_dir_path + "analysis_plot_r{0}.png".format(self.repeat_idx) + if os.path.exists(png_path): + self.aux_box.set_image_from_png(png_path) + else: + self.aux_box.clear_image() + self.main_window.update() + + # Convert to pixel map. + if self.draw_binary: + pixmap = qtu.frame_to_pixmap(np.int32(binary), autoscale=True) + else: + pixmap = qtu.frame_to_pixmap(image, autoscale=not self.raw, min=movie_min, max=movie_max, + norm_mat=None if self.raw else self.norm_mat) + pixmap = pixmap.scaledToHeight(pixmap.height() * self.scale) + + # Draw frame. + qp = QPainter() + if qp.isActive(): + qp.setRenderHint(QPainter.Antialiasing) + qp.begin(self) + qp.drawPixmap(0, 0, pixmap) + + # Draw bubble position + if self.show_debug: + b_pos_x, b_pos_y, area, ecc, sol, jet_tip = au.analyse_frame(image, bg_img, debug=True) + + if b_pos_x is not None and b_pos_y is not None and jet_tip is not None: + self.draw_line(qp, [(b_pos_x + 1) * self.scale, (b_pos_y + 1) * self.scale], + [(jet_tip[0] + 1) * self.scale, (jet_tip[1] + 1) * self.scale], colour=Qt.green) + + if b_pos_x is not None and b_pos_y is not None: + self.draw_point(qp, [(b_pos_x + 1) * self.scale, (b_pos_y + 1) * self.scale], + Qt.magenta) + + if area is not None: + self.draw_circle(qp, [(b_pos_x + 1) * self.scale, (b_pos_y + 1) * self.scale], + self.scale * np.sqrt(area / np.pi), Qt.magenta) + + if b_pos_x is not None and b_pos_y is not None \ + and ecc is not None and sol is not None and jet_tip is not None: + if area is None: + qp.drawText(b_pos_x * self.scale + 5, + b_pos_y * self.scale + 5, f"ecc = {ecc:.2f}, sol = {sol:.2f}") + else: + tip_ratio = np.linalg.norm(np.subtract(jet_tip, [b_pos_x, b_pos_y])) / np.sqrt(area / np.pi) + qp.drawText((b_pos_x + np.sqrt(area / np.pi)) * self.scale, + (b_pos_y + np.sqrt(area / np.pi)) * self.scale, + f"ecc = {ecc:.2f}, sol = {sol:.2f}, R = {np.sqrt(area / np.pi):.2f}, tr = {tip_ratio:.2f}") + + # Draw ruler. + if self.point_1 is not None and self.point_2 is None: + self.draw_point(qp, self.point_1) + if self.point_1 is not None and self.point_2 is not None: + self.draw_line(qp) + + qp.end() + + def save_reading_movie(self): + r_dir_path = self.file_dir + self.position_prefix + str(self.positions[self.position_idx][2]).rjust(4, + '0') + "/" + mov = file.get_mraw_from_dir(r_dir_path) + + filename = str(QFileDialog.getSaveFileName(self, "Select Save Directory", + r_dir_path + "video" + "_" + str(self.repeat_idx) + ".mp4")[0]) + if filename == "": + return + if filename[-4:] != ".mp4": + filename += ".mp4" + + # These settings make OpenCV compain about stuff, but they still give much nicer quality. + if self.raw: + mraw_converter.convert(mov, filename, codec='avc1', fps=24, + frame_range=(100 * self.repeat_idx, 100 * (self.repeat_idx + 1) - 1), + autoscale_brightness=False, norm_mat=None, writer='cv2') + else: + mraw_converter.convert(mov, filename, codec='avc1', fps=24, + frame_range=(100 * self.repeat_idx, 100 * (self.repeat_idx + 1) - 1), + autoscale_brightness=True, norm_mat=self.norm_mat, writer='cv2') + + def draw_point(self, qp, point, colour=Qt.red): + pen = QPen(colour, 4, Qt.SolidLine) + qp.setRenderHint(QPainter.Antialiasing) + qp.setPen(pen) + qp.drawPoint(point[0], point[1]) + + def draw_line(self, qp, p1=None, p2=None, colour=Qt.red): + pen = QPen(colour, 2, Qt.SolidLine) + qp.setRenderHint(QPainter.Antialiasing) + qp.setPen(pen) + if p1 is None or p2 is None: + qp.drawLine(self.point_1[0], self.point_1[1], self.point_2[0], self.point_2[1]) + else: + qp.drawLine(p1[0], p1[1], p2[0], p2[1]) + + def draw_circle(self, qp, center, radius, colour=Qt.red): + pen = QPen(colour, 2, Qt.SolidLine) + qp.setRenderHint(QPainter.Antialiasing) + qp.setPen(pen) + qp.drawEllipse(center[0] - radius, center[1] - radius, 2 * radius, 2 * radius) + + def next_frame(self): + self.frame_idx += 1 + if self.frame_idx >= self.max_frames: + self.frame_idx = 0 + self.update() + + def previous_frame(self): + self.frame_idx -= 1 + if self.frame_idx < 0: + self.frame_idx = self.max_frames - 1 + self.update() + + def move_points(self, last_position_idx): + if self.mm_per_pixel is not None: + px_per_mm = 1 / self.mm_per_pixel + last_position = self.positions[last_position_idx] + this_position = self.positions[self.position_idx] + if last_position[0] != this_position[0]: + dx_mm = last_position[0] - this_position[0] + if self.point_1 is not None: + self.point_1[0] += self.scale * dx_mm * px_per_mm + if self.point_2 is not None: + self.point_2[0] += self.scale * dx_mm * px_per_mm + if last_position[1] != this_position[1]: + dy_mm = last_position[1] - this_position[1] + if self.point_1 is not None: + self.point_1[1] -= self.scale * dy_mm * px_per_mm + if self.point_2 is not None: + self.point_2[1] -= self.scale * dy_mm * px_per_mm + + def next_position(self): + self.repeat_idx = 0 + if self.position_idx + 1 >= len(self.positions): + self.set_position(0) + else: + self.set_position(self.position_idx + 1) + self.update() + + def previous_position(self): + self.repeat_idx = 0 + if self.position_idx - 1 < 0: + self.set_position(len(self.positions) - 1) + else: + self.set_position(self.position_idx - 1) + self.update() + + def next_repeat(self): + self.repeat_idx += 1 + if self.frame_idx + self.repeat_idx * self.max_frames >= self.total_frames: + self.repeat_idx = int(self.total_frames / self.max_frames) - 1 + self.update() + + def previous_repeat(self): + self.repeat_idx -= 1 + if self.repeat_idx < 0: + self.repeat_idx = 0 + self.update() + + def set_frame(self, frame_idx): + self.frame_idx = frame_idx + self.update() + + def set_draw_binary(self, draw_binary): + self.draw_binary = draw_binary + self.update() + + def set_show_debug(self, show_debug): + self.show_debug = show_debug + self.update() + + def set_raw(self, raw): + self.raw = raw + self.update() + + def update_text(self): + # Line 1 + text = "Frame: {0}".format(self.frame_idx) + text += " Repeat: {0}".format(self.repeat_idx) + if self.point_1 is not None: + text += " Point 1: {0:.1f}, {1:.1f} (px)".format(self.point_1[0] / self.scale, + self.point_1[1] / self.scale) + if self.mm_per_pixel is not None: + text += " {0:.2f}, {1:.2f} (mm)".format( + self.positions[self.position_idx][0] + self.mm_per_pixel * self.point_1[0] / self.scale, + self.positions[self.position_idx][1] + self.mm_per_pixel * (264 - self.point_1[1] / self.scale)) + if self.point_2 is not None: + text += " Point 2: {0:.1f}, {1:.1f} (px)".format(self.point_2[0] / self.scale, + self.point_2[1] / self.scale) + if self.mm_per_pixel is not None: + text += " {0:.2f}, {1:.2f} (mm)".format( + self.positions[self.position_idx][0] + self.mm_per_pixel * self.point_2[0] / self.scale, + self.positions[self.position_idx][1] + self.mm_per_pixel * (264 - self.point_2[1] / self.scale)) + # Line 2 + if self.point_1 is not None and self.point_2 is not None: + dx = (self.point_2[0] - self.point_1[0]) / self.scale + dy = (self.point_2[1] - self.point_1[1]) / self.scale + length = math.sqrt(dx ** 2 + dy ** 2) + text += "\nLength (px): {0:.2f}".format(length) + text += " dx (px) = {0:.2f} dy (px) = {1:.2f}".format(dx, dy) + + # y measured backwards (point_2 to point_1) to correct for inverted axis. + text += " Angle (rad): {0:.4f}".format(math.atan2(-dy, dx)) + + # Line 3 + if self.mm_per_pixel is not None: + text += "\nLength (mm): {0:.2f}".format(length * self.mm_per_pixel) + text += " dx (mm) = {0:.2f} dy (mm) = {1:.2f}".format(dx * self.mm_per_pixel, + -dy * self.mm_per_pixel) + + self.text_area.setText(text) + + # Position status + position_status_text = "x = {0:.2f}" \ + "\ny = {1:.2f}" \ + "\nidx = {2}" \ + .format(self.positions[self.position_idx][0], self.positions[self.position_idx][1], + self.positions[self.position_idx][2]) + self.position_status.setText(position_status_text) + + def mousePressEvent(self, event): + if event.buttons() & Qt.LeftButton: + if self.point_1 is None and self.point_2 is None: + self.point_1 = [event.x(), event.y()] + elif self.point_1 is not None and self.point_2 is None: + self.point_2 = [event.x(), event.y()] + else: + self.point_1 = [event.x(), event.y()] + self.point_2 = None + self.update() + if event.buttons() & Qt.RightButton: + self.point_1 = None + self.point_2 = None + self.update() + self.update_text() + + def mouseMoveEvent(self, event): + if event.buttons() & Qt.LeftButton: + if self.point_1 is not None: + self.point_2 = [event.x(), event.y()] + self.update() + + def get_current_frame_data(self): + x = self.positions[self.position_idx][0] + y = self.positions[self.position_idx][1] + mov = file.get_mraw_from_dir( + self.file_dir + self.position_prefix + str(self.positions[self.position_idx][2]).rjust(4, '0') + "/") + image = mov[self.frame_idx + self.max_frames * self.repeat_idx] + self.total_frames = mov.image_count + mov.close() + return x, y, image + + def incr_y(self): + cur_x = self.positions[self.position_idx][0] + cur_y = self.positions[self.position_idx][1] + + min_y_dif = None # type: float + min_x_dif = None # type: float + min_r = None + for r in range(len(self.positions)): + position_y = self.positions[r][1] + position_x = self.positions[r][0] + if position_y > cur_y: + y_dif = abs(position_y - cur_y) + x_dif = abs(position_x - cur_x) + if min_y_dif is None or y_dif < min_y_dif: + min_x_dif = x_dif + min_y_dif = y_dif + min_r = r + elif y_dif == min_y_dif and x_dif < min_x_dif: + min_x_dif = x_dif + min_r = r + if min_r is not None: + last_position_idx = self.position_idx + self.set_position(min_r) + self.repeat_idx = 0 + self.update() + + def decr_y(self): + cur_x = self.positions[self.position_idx][0] + cur_y = self.positions[self.position_idx][1] + + min_y_dif = None # type: float + min_x_dif = None # type: float + min_r = None + for r in range(len(self.positions)): + position_y = self.positions[r][1] + position_x = self.positions[r][0] + if position_y < cur_y: + y_dif = abs(position_y - cur_y) + x_dif = abs(position_x - cur_x) + if min_y_dif is None or y_dif < min_y_dif: + min_x_dif = x_dif + min_y_dif = y_dif + min_r = r + elif y_dif == min_y_dif and x_dif < min_x_dif: + min_x_dif = x_dif + min_r = r + if min_r is not None: + last_position_idx = self.position_idx + self.set_position(min_r) + self.repeat_idx = 0 + self.update() + + def incr_x(self): + cur_x = self.positions[self.position_idx][0] + cur_y = self.positions[self.position_idx][1] + + min_y_dif = None # type: float + min_x_dif = None # type: float + min_r = None + for r in range(len(self.positions)): + position_y = self.positions[r][1] + position_x = self.positions[r][0] + if position_x > cur_x: + y_dif = abs(position_y - cur_y) + x_dif = abs(position_x - cur_x) + if min_x_dif is None or x_dif < min_x_dif: + min_x_dif = x_dif + min_y_dif = y_dif + min_r = r + elif x_dif == min_x_dif and y_dif < min_y_dif: + min_y_dif = y_dif + min_r = r + if min_r is not None: + last_position_idx = self.position_idx + self.set_position(min_r) + self.repeat_idx = 0 + self.update() + + def decr_x(self): + cur_x = self.positions[self.position_idx][0] + cur_y = self.positions[self.position_idx][1] + + min_y_dif = None # type: float + min_x_dif = None # type: float + min_r = None + for r in range(len(self.positions)): + position_y = self.positions[r][1] + position_x = self.positions[r][0] + if position_x < cur_x: + y_dif = abs(position_y - cur_y) + x_dif = abs(position_x - cur_x) + if min_x_dif is None or x_dif < min_x_dif: + min_x_dif = x_dif + min_y_dif = y_dif + min_r = r + elif x_dif == min_x_dif and y_dif < min_y_dif: + min_y_dif = y_dif + min_r = r + if min_r is not None: + last_position_idx = self.position_idx + self.set_position(min_r) + self.repeat_idx = 0 + self.update() + + +class CalibrationWidget(QWidget): + calibration_frames = None # x, y, frame + text_area = None + mm_per_pixel = None + + def __init__(self, data_widget: DataWidget, parent=None): + if parent: + super().__init__(parent) + else: + super().__init__() + + self.data_widget = data_widget + self.calibration_frames = [] + + vbox = QVBoxLayout() + vbox.setAlignment(Qt.AlignTop) + vbox.setSizeConstraint(QLayout.SetFixedSize) + + label = QLabel("Calibration") + label.setStyleSheet("QLabel { font-weight: bold; }") + label.setAlignment(Qt.AlignHCenter) + label.setMaximumHeight(16) + + text_area = QTextBrowser() + text_area.setMaximumHeight(36) + text_area.setMaximumWidth(100) + self.text_area = text_area + + add_frame_button = QPushButton("Add Frame") + add_frame_button.clicked.connect(self.take_frame) + clear_frames_button = QPushButton("Clear Frames") + clear_frames_button.clicked.connect(self.clear_frames) + calibrate_button = QPushButton("Calibrate") + calibrate_button.clicked.connect(self.calibrate) + + vbox.addWidget(label) + vbox.addWidget(add_frame_button) + vbox.addWidget(clear_frames_button) + vbox.addWidget(calibrate_button) + vbox.addWidget(text_area) + self.setLayout(vbox) + + self.load_calibration() + self.update_text() + + def take_frame(self): + self.calibration_frames.append(self.data_widget.get_current_frame_data()) + self.update_text() + + def clear_frames(self): + self.calibration_frames.clear() + self.update_text() + + def load_calibration(self): + file_dir = self.data_widget.file_dir + if os.path.exists(file_dir + "params.py"): + sys.path.append(file_dir) + import params + importlib.reload(params) + sys.path.remove(file_dir) + + if params.mm_per_px: + self.mm_per_pixel = params.mm_per_px + self.data_widget.mm_per_pixel = params.mm_per_px + self.update_text() + + def calibrate(self): + mm_per_pixels = [] + for i in range(1, len(self.calibration_frames)): + x_1 = self.calibration_frames[i - 1][0] + y_1 = self.calibration_frames[i - 1][1] + + x_2 = self.calibration_frames[i][0] + y_2 = self.calibration_frames[i][1] + + if x_2 == x_1 and y_2 == y_1: + self.text_area.setText("Warning!\nDuplicate frame.") + continue + + mm = math.sqrt((x_2 - x_1) ** 2 + (y_2 - y_1) ** 2) + + px_offset = cu.calculate_offset(self.calibration_frames[i - 1][2], self.calibration_frames[i][2]) + print(px_offset) + px = vect.mag(px_offset) + if px == 0: + self.text_area.setText("Error!\nNo offset found.") + continue + mm_per_pixels.append(mm / px) + + if len(mm_per_pixels) == 0: + return + self.mm_per_pixel = np.mean(mm_per_pixels) + self.data_widget.mm_per_pixel = self.mm_per_pixel + self.update_text() + + def update_text(self): + text = "Frames: {0}".format(len(self.calibration_frames)) + if self.mm_per_pixel is not None: + text += "\nmm/px = {0:.4f}".format(self.mm_per_pixel) + self.text_area.setText(text) + + +class BubbleAnalyser(QMainWindow, QObject): + player_play_signal = pyqtSignal(int) + + def __init__(self, file_dir=None): + QMainWindow.__init__(self) + QObject.__init__(self) + while file_dir is None or not os.path.exists(file_dir + "index.csv"): + file_dir = str(QFileDialog.getExistingDirectory(self, "Select Directory", "../")) + if file_dir == "": + QTimer.singleShot(0, self.close) + return + else: + file_dir += "/" + + self.title = 'Bubble Analysis - ' + file_dir + + self.setWindowTitle(self.title) + self.setWindowIcon(QIcon('icon.png')) + + # Reset the App ID to interact more nicely with Windows (separate icon from generic Python etc.). + myappid = u'bubble_analysis.py' # arbitrary string + ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(myappid) + + # Build text area + text_area = QTextBrowser() + text_area.setMaximumHeight(52) + + # Build side bar area. + side_bar = QVBoxLayout() + side_bar.setAlignment(Qt.AlignTop) + + # Build position box + position_box = QVBoxLayout() + position_box.setContentsMargins(8, 0, 8, 0) + position_box.setSizeConstraint(QLayout.SetFixedSize) + position_label = QLabel("Position") + position_label.setStyleSheet("QLabel { font-weight: bold; }") + position_label.setAlignment(Qt.AlignHCenter) + position_label.setMaximumHeight(16) + position_box.setAlignment(Qt.AlignTop) + + position_back = QPushButton("Previous") + position_back.setAutoRepeat(True) + position_forward = QPushButton("Next") + position_forward.setAutoRepeat(True) + + incr_x = QPushButton("x +") + incr_x.setAutoRepeat(True) + incr_x.setMaximumWidth(40) + decr_x = QPushButton("x -") + decr_x.setAutoRepeat(True) + decr_x.setMaximumWidth(40) + incr_y = QPushButton("y +") + incr_y.setAutoRepeat(True) + incr_y.setMaximumWidth(40) + decr_y = QPushButton("y -") + decr_y.setAutoRepeat(True) + decr_y.setMaximumWidth(40) + position_buttons = QVBoxLayout() + position_buttons.setAlignment(Qt.AlignHCenter) + x_buttons = QHBoxLayout() + x_buttons.addWidget(decr_x) + x_buttons.addWidget(incr_x) + incr_y_wrapper = QHBoxLayout() + incr_y_wrapper.addWidget(incr_y) + decr_y_wrapper = QHBoxLayout() + decr_y_wrapper.addWidget(decr_y) + position_buttons.addLayout(incr_y_wrapper) + position_buttons.addLayout(x_buttons) + position_buttons.addLayout(decr_y_wrapper) + + flag_repeat = QPushButton("Flag Invalid Repeat") + flag_repeat.clicked.connect(self.flag_invalid_repeat) + + position_status = QTextBrowser() + position_status.setMaximumHeight(52) + position_status.setMaximumWidth(100) + position_box.addWidget(position_label) + position_box.addWidget(position_forward) + position_box.addWidget(position_back) + position_box.addWidget(position_status) + position_box.addLayout(position_buttons) + position_box.addWidget(flag_repeat) + + # Build auxiliary box + aux_box = ImageDisplayWidget() + + # Build image area + self.data_widget = DataWidget(text_area, position_status, file_dir, aux_box, self) + + position_forward.clicked.connect(self.data_widget.next_position) + position_back.clicked.connect(self.data_widget.previous_position) + incr_x.clicked.connect(self.data_widget.incr_x) + decr_x.clicked.connect(self.data_widget.decr_x) + incr_y.clicked.connect(self.data_widget.incr_y) + decr_y.clicked.connect(self.data_widget.decr_y) + + save_repeat = QPushButton("Save Repeat Movie") + save_repeat.clicked.connect(self.data_widget.save_reading_movie) + position_box.addWidget(save_repeat) + + dir_change = QPushButton("Change Directory") + dir_change.clicked.connect(self.select_dir) + position_box.addWidget(dir_change) + + # Build calibration widget + self.calibration = CalibrationWidget(self.data_widget) + side_bar.addWidget(self.calibration) + side_bar.addLayout(position_box) + + # Build upper area (image and side buttons) + upper_box = QHBoxLayout() + # upper_box.addSpacerItem(QSpacerItem(20, 40, QSizePolicy.Preferred, QSizePolicy.Minimum)) + upper_box.addWidget(self.data_widget) + # upper_box.addSpacerItem(QSpacerItem(20, 40, QSizePolicy.Preferred, QSizePolicy.Minimum)) + upper_box.addLayout(side_bar) + + # Build button area + slider = JumpSlider(Qt.Horizontal) + slider.setFocusPolicy(Qt.StrongFocus) + slider.setTickPosition(QSlider.TicksBothSides) + slider.setTickInterval(10) + slider.setSingleStep(1) + slider.setValue(0) + slider.setMinimum(0) + slider.setMaximum(99) + slider.valueChanged.connect(self.set_frame_from_slider) + self.slider = slider + + self.player_thread = QThread() + self.player = Player() + self.player.moveToThread(self.player_thread) + self.player.frame_update.connect(self.set_frame_from_player) + self.player.finished.connect(self.on_player_finished) + self.player_play_signal.connect(self.player.play) + + spacer = QSpacerItem(20, 40, QSizePolicy.Minimum, QSizePolicy.Minimum) + + button_box = QHBoxLayout() + frame_back = QPushButton("Previous Frame") + frame_back.setAutoRepeat(True) + frame_back.clicked.connect(self.previous_frame) + button_box.addWidget(frame_back) + frame_forward = QPushButton("Next Frame") + frame_forward.setAutoRepeat(True) + frame_forward.clicked.connect(self.next_frame) + button_box.addWidget(frame_forward) + + button_box.addItem(spacer) + + rep_back = QPushButton("Previous Repeat") + rep_back.setAutoRepeat(True) + rep_back.clicked.connect(self.data_widget.previous_repeat) + button_box.addWidget(rep_back) + rep_forward = QPushButton("Next Repeat") + rep_forward.setAutoRepeat(True) + rep_forward.clicked.connect(self.data_widget.next_repeat) + button_box.addWidget(rep_forward) + + button_box.addItem(spacer) + + self.loop_toggle = QCheckBox("Loop") + self.loop_toggle.stateChanged.connect(lambda _: self.toggle_loop(self.loop_toggle.isChecked())) + button_box.addWidget(self.loop_toggle) + + binary_toggle = QCheckBox("Binary") + binary_toggle.stateChanged.connect(lambda _: self.data_widget.set_draw_binary(binary_toggle.isChecked())) + button_box.addWidget(binary_toggle) + + debug_toggle = QCheckBox("Debug") + debug_toggle.stateChanged.connect(lambda _: self.data_widget.set_show_debug(debug_toggle.isChecked())) + button_box.addWidget(debug_toggle) + + auto_bright_toggle = QCheckBox("Raw Output") + auto_bright_toggle.setChecked(False) + auto_bright_toggle.stateChanged.connect( + lambda _: self.data_widget.set_raw(auto_bright_toggle.isChecked())) + button_box.addWidget(auto_bright_toggle) + + self.rand_toggle = QCheckBox("Randomise") + button_box.addWidget(self.rand_toggle) + + # Build window contents + vbox = QVBoxLayout() # Main box. + hbox = QHBoxLayout() # Box containing the main box and auxiliary box. + central_widget = QWidget() + central_widget.setLayout(hbox) + + # Put together the main box + vbox.addLayout(upper_box) + vbox.addWidget(slider) + vbox.addLayout(button_box) + vbox.addWidget(text_area) + + # Add the auxiliary box + hbox.addLayout(vbox) + hbox.addWidget(aux_box) + + self.setCentralWidget(central_widget) + self.show() + self.update() + self.player_thread.start() + + def set_frame_from_slider(self): + self.data_widget.set_frame(self.slider.value()) + + def set_frame_from_player(self, i): + self.data_widget.set_frame(i) + self.slider.setValue(i) + + def toggle_loop(self, loop): + if loop: + self.slider.setEnabled(False) + self.player_play_signal.emit(self.slider.value()) + else: + self.player.skip = True # This is probably pretty unhealthy but it'll do + + def on_player_finished(self): + if self.loop_toggle.isChecked(): + if self.rand_toggle.isChecked(): + rand_pos = np.random.randint(len(self.data_widget.positions)) + self.data_widget.set_position(rand_pos) + rand_rep = np.random.randint(int(self.data_widget.total_frames / self.data_widget.max_frames)) + self.data_widget.repeat_idx = rand_rep + self.data_widget.update() + + self.player_play_signal.emit(0) + else: + self.slider.setEnabled(True) + + def next_frame(self): + self.data_widget.next_frame() + self.slider.setValue(self.data_widget.frame_idx) + + def previous_frame(self): + self.data_widget.previous_frame() + self.slider.setValue(self.data_widget.frame_idx) + + def update(self): + # self.resize(self.minimumSizeHint()) + super().update() + + def flag_invalid_repeat(self): + f = open(self.data_widget.file_dir + "invalid_readings.txt", "a") + f.write("{0}:{1}\n".format(self.data_widget.positions[self.data_widget.position_idx][2], + self.data_widget.repeat_idx)) + f.close() + + def select_dir(self): + file_dir = None + while file_dir is None or not os.path.exists(file_dir + "index.csv"): + file_dir = str( + QFileDialog.getExistingDirectory(self, "Select Directory", self.data_widget.file_dir + "../")) + if file_dir == "": + return + else: + file_dir += "/" + + self.calibration.clear_frames() + self.calibration.load_calibration() + self.data_widget.change_dir(file_dir) + self.slider.setSliderPosition(0) + self.title = 'Bubble Analysis - ' + file_dir + self.setWindowTitle(self.title) + + def keyPressEvent(self, e: QtGui.QKeyEvent): + if e.key() == Qt.Key_Slash: + self.loop_toggle.setChecked(not self.loop_toggle.isChecked()) + if e.key() == Qt.Key_Comma: + self.data_widget.previous_frame() + self.slider.setValue(self.data_widget.frame_idx) + if e.key() == Qt.Key_Period: + self.data_widget.next_frame() + self.slider.setValue(self.data_widget.frame_idx) + + +if __name__ == '__main__': + app = QApplication(sys.argv) + ex = BubbleAnalyser() + # ex.show() + # ex = BubbleAnalyser("../../Data/Test1/HSweep4/") + sys.exit(app.exec_()) diff --git a/packaged-code/pacakged-gui/icon.png b/packaged-code/pacakged-gui/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..80ed0787decb4706102ca384107b3d9288fc3e86 Binary files /dev/null and b/packaged-code/pacakged-gui/icon.png differ diff --git a/packaged-code/pacakged-gui/run_bubble_analysis.bat b/packaged-code/pacakged-gui/run_bubble_analysis.bat new file mode 100644 index 0000000000000000000000000000000000000000..201356000b1e0a36a2680c3a435c928c929594d0 --- /dev/null +++ b/packaged-code/pacakged-gui/run_bubble_analysis.bat @@ -0,0 +1,2 @@ +python ./bubble_analysis_gui.py +PAUSE \ No newline at end of file diff --git a/paper_code/porous/util/analysis_utils.py b/packaged-code/pacakged-gui/util/analysis_utils.py similarity index 100% rename from paper_code/porous/util/analysis_utils.py rename to packaged-code/pacakged-gui/util/analysis_utils.py diff --git a/packaged-code/pacakged-gui/util/calibration_utils.py b/packaged-code/pacakged-gui/util/calibration_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..47fbac51ac0a2e84b0da5c912202a5ec0907afed --- /dev/null +++ b/packaged-code/pacakged-gui/util/calibration_utils.py @@ -0,0 +1,51 @@ +import math + +import matplotlib.pyplot as plt +import numpy as np +import skimage.transform as tf +from skimage.registration import phase_cross_correlation +from skimage.filters import sobel, threshold_triangle +from skimage.restoration import denoise_bilateral + +import util.plotting_utils as pu +import util.file_utils as fu + + +def calculate_offset(frame_1, frame_2, plot_compared_frames=False): + """ + Calculates a required offset of frame_1 in direction dir such that it maps onto frame_2 as closely as possible. + + :param frame_1: Frame to be moved. + :param frame_2: Frame to be mapped onto. + :param plot_compared_frames: Whether to plot the final frame comparison. + :return: Offset required in direction. + """ + frame_1 = denoise_bilateral(frame_1, channel_axis=None, bins=2, mode='reflect', sigma_spatial=2.5) + frame_2 = denoise_bilateral(frame_2, channel_axis=None, bins=2, mode='reflect', sigma_spatial=2.5) + frame_1 = sobel(frame_1, mask=np.ones(frame_1.shape, dtype=bool)) + frame_2 = sobel(frame_2, mask=np.ones(frame_1.shape, dtype=bool)) + + # thresh_1 = threshold_triangle(frame_1) + # thresh_2 = threshold_triangle(frame_2) + # thresh = (thresh_1 + thresh_2) / 2 + # frame_1 = frame_1 > thresh + # frame_2 = frame_2 > thresh + + offset, error, _ = phase_cross_correlation(frame_1, frame_2, normalization=None) + if plot_compared_frames: + tform = tf.SimilarityTransform(translation=[offset[1], offset[0]]) + pu.plot_frame(tf.warp(frame_1, tform), show_immediately=False) + pu.plot_frame(frame_2, show_immediately=False) + plt.show() + + return offset + + +if __name__ == '__main__': + # cal_dir = "../../../Data/SidewaysSeries/w2.2h2.7/" + # print(calculate_mm_per_pixel(cal_dir, plot_compared_frames=True)) + # mraw_1 = fu.get_mraw_from_dir("../../../../Data/SlotSweeps/w1h3/movie_S0013/") + # mraw_2 = fu.get_mraw_from_dir("../../../../Data/SlotSweeps/w1h3/movie_S0001/") + mraw_1 = fu.get_mraw_from_dir("C:/Users/eda1g15/OneDrive - University of Southampton/Research/Porous Materials/Data/~25VF/Purer water between 3 degassed again/movie_C001H001S0001/") + mraw_2 = fu.get_mraw_from_dir("C:/Users/eda1g15/OneDrive - University of Southampton/Research/Porous Materials/Data/~25VF/Purer water between 3 degassed again/movie_C001H001S0002/") + print(calculate_offset(mraw_1[0], mraw_2[0], True)) diff --git a/paper_code/porous/util/determineDisplacement.py b/packaged-code/pacakged-gui/util/determineDisplacement.py similarity index 100% rename from paper_code/porous/util/determineDisplacement.py rename to packaged-code/pacakged-gui/util/determineDisplacement.py diff --git a/paper_code/porous/util/file_utils.py b/packaged-code/pacakged-gui/util/file_utils.py similarity index 100% rename from paper_code/porous/util/file_utils.py rename to packaged-code/pacakged-gui/util/file_utils.py diff --git a/paper_code/porous/util/mp4.py b/packaged-code/pacakged-gui/util/mp4.py similarity index 100% rename from paper_code/porous/util/mp4.py rename to packaged-code/pacakged-gui/util/mp4.py diff --git a/paper_code/porous/util/mraw.py b/packaged-code/pacakged-gui/util/mraw.py similarity index 100% rename from paper_code/porous/util/mraw.py rename to packaged-code/pacakged-gui/util/mraw.py diff --git a/packaged-code/pacakged-gui/util/mraw_converter.py b/packaged-code/pacakged-gui/util/mraw_converter.py new file mode 100644 index 0000000000000000000000000000000000000000..9118de1a8a9a96a3860623823c0555d4b90a4526 --- /dev/null +++ b/packaged-code/pacakged-gui/util/mraw_converter.py @@ -0,0 +1,170 @@ +# -*- coding: utf-8 -*- +""" +Created on Thu Jul 6 14:36:00 2017 + +@author: Ivo Peters +ivo.r.peters@gmail.com + +Modified by Elijah Andrews +""" + +import numpy as np +# import matplotlib.pyplot as plt +import cv2 +from PIL import Image +from subprocess import Popen, PIPE +import os +import multiprocessing + +from util.mraw import mraw +from util.pixel_correction import safe_correct, load_norm_mat +import util.file_utils as file + + +def convert(mraw_obj, outputFile, codec='XVID', fps=24, frame_range=None, scale=1, contrast=1, crf=18, + autoscale_brightness=False, norm_mat=None, writer='ffmpeg'): + """ + Convert a given mraw object into a video file. + :param mraw_obj: mraw object + :param outputFile: output file path + :param codec: four letter codec name - ignored if using writer='ffmpeg' + :param fps: frames per second in the output file + :param frame_range: range of frames to include, [a, b] inclusive of both a and b + :param scale: image scale + :param contrast: contrast ratio + :param crf: Constant Rate Factor (quality), only used for writer='ffmpeg' + :param autoscale_brightness: whether to scale brightness based on maximum and minimum brightnesses in the image + :param writer: which video-writing method to use (cv2 or ffmpeg) + """ + movie = mraw_obj + if frame_range is None: + frame_range = (0, len(movie)) + + if writer == "cv2": + if type(codec) is str and len(codec) == 4: + codec = cv2.VideoWriter_fourcc(codec[0], codec[1], codec[2], codec[3]) + out = cv2.VideoWriter(outputFile, codec, fps, + (movie.width * scale, movie.height * scale), + 0) + elif writer == "ffmpeg": + p = Popen(['ffmpeg', + '-y', # Overwrite files + '-f', 'image2pipe', # Input format + '-r', '24', # Framerate + '-i', '-', # stdin + '-c:v', 'libx264', # Codec + '-preset', 'slow', + '-crf', f'{crf}', # H264 Constant Rate Factor (quality, lower is better) + '-loglevel', 'quiet', # Stop yelling at me + '-flush_packets', '1', + outputFile], stdin=PIPE) + + movie_min = np.min([np.min(movie[i]) for i in range(frame_range[0], frame_range[1] + 1)]) + movie_max = np.max([np.max(movie[i]) for i in range(frame_range[0], frame_range[1] + 1)]) + movie_ptp = movie_max - movie_min + for i in range(frame_range[0], frame_range[1] + 1): + frame = movie[i] + if norm_mat is not None: + frame = safe_correct(frame, norm_mat) + if autoscale_brightness: + frame = ((frame - movie_min) / (movie_ptp / 255.0)).astype(np.uint8) + else: + frame = np.uint8(np.double(frame) / (2 ** 12) * 255) # Convert to 8 bit colour. + if scale != 1: + frame = cv2.resize(frame, (movie.width * scale, movie.height * scale)) + if contrast != 1: + frame = cv2.convertScaleAbs(frame, alpha=contrast) + + if writer == "cv2": + out.write(frame) + elif writer == "ffmpeg": + im = Image.fromarray(frame) + im.save(p.stdin, 'PNG') + + if writer == "cv2": + out.release() + elif writer == "ffmpeg": + p.stdin.close() + p.wait() + + +def convert_mraw(mraw_obj, outputFile, codec='XVID', fps=24, separate_readings=True, writer="ffmpeg", norm_mat=None): + movie = mraw_obj + if separate_readings: + repeats = movie.image_count // 100 + for i in range(repeats): + filename = outputFile[:-4] + "_" + str(i) + outputFile[-4:] + convert(movie, filename, frame_range=(i * 100, (i + 1) * 100 - 1), + codec=codec, fps=fps, contrast=1, writer=writer, norm_mat=norm_mat) + else: + convert(mraw_obj, outputFile, codec=codec, fps=fps, contrast=1, writer=writer, norm_mat=norm_mat) + + +def convert_series(dir_path, codec="mp4v", file_format="mp4", writer="ffmpeg", px_correct=True): + print(dir_path) + index_file = open(dir_path + "index.csv") + index_lines = index_file.readlines() + index_file.close() + + input_data = [] # x, y, index + + for i in range(1, len(index_lines)): # Start at 1 to skip header. + split = index_lines[i].strip().split(",") + input_data.append([float(split[0]), float(split[1]), split[2]]) # x, y, index number + + reading_prefix = file.get_prefix_from_idxs(dir_path, np.array(input_data)[:, 2]) + for i in range(len(input_data)): + print("Converting reading {0}. - {1}".format(input_data[i][2], dir_path)) + reading_path = dir_path + reading_prefix + str(input_data[i][2]).rjust(4, "0") + "/" + mraw_obj = file.get_mraw_from_dir(reading_path) + if px_correct: + norm_mat = load_norm_mat(dir_path) + else: + norm_mat = None + convert_mraw(mraw_obj, reading_path + "video." + file_format, + codec=codec, separate_readings=True, writer=writer, norm_mat=norm_mat) + + +if __name__ == "__main__": + # Anisotropy modelling paper + # to_convert = ["E:/Data/Lebo/Restructured Data/Equilateral triangle/", + # "E:/Data/Lebo/Restructured Data/Equilateral triangle 2/", + # "E:/Data/Lebo/Restructured Data/Square/", + # "E:/Data/Lebo/Restructured Data/Square 2/", + # "E:/Data/Lebo/Restructured Data/Square 3/", + # "C:/Users/eda1g15/OneDrive - University of Southampton/Research/Porous Materials/Data/Solid plate/"] + + to_convert = [] + + # Porous plates paper + root_dir = "C:/Users/eda1g15/OneDrive - University of Southampton/Research/Porous Materials/Data/Steel plates/" + + for root, _, files in os.walk(root_dir): + if "params.py" in files: + to_convert.append(root + "/") + + for cdir in to_convert: + print(cdir) + print(f"Found {len(to_convert)} data sets") + + pool = multiprocessing.Pool(processes=os.cpu_count() - 1) # Leave one core for the rest of us + pool.map(convert_series, to_convert) + pool.close() + + # this_path = "C:/Users/eda1g15/OneDrive - University of Southampton/Research/Porous Materials/Data/" \ + # "Steel plates/w48vf24circles/Between 3 holes/" + # norm_mat = load_norm_mat(this_path) + # this_mraw = file.get_mraw_from_dir(this_path + "movie_C001H001S0026/") + # convert_mraw(this_mraw, this_path + "movie_C001H001S0026/" + "video.mp4", norm_mat=norm_mat) + + # TESTING OPTIONS + # basic_norm_mat = load_norm_mat() + + # convert(file.get_mraw_from_dir( + # "C:/Users/eda1g15/OneDrive - University of Southampton/Research/Porous Materials/Data/2something Hole 1mm Acrylic 50mm Plate/The Lump/normal_angle_C001H001S0001/"), + # "converted.mp4", codec="mp4v", frame_range=[200, 300], scale=2, contrast=1, autoscale_brightness=True) + + # this_dir = "C:/Users/eda1g15/OneDrive - University of Southampton/Research/Porous Materials/Data/Misc/OAP mirror testing/sono-100power-75att_C001H001S0001/" + # convert(file.get_mraw_from_dir(this_dir), this_dir + "luminescence/luminescence1.png", codec=0, + # frame_range=[400, 499], + # scale=1, contrast=1, fps=0, autoscale_brightness=True, norm_mat=basic_norm_mat) diff --git a/packaged-code/pacakged-gui/util/pixel_correction.py b/packaged-code/pacakged-gui/util/pixel_correction.py new file mode 100644 index 0000000000000000000000000000000000000000..2609cdae9dbc4c8c36ba2a4403fe905981d3c1bb --- /dev/null +++ b/packaged-code/pacakged-gui/util/pixel_correction.py @@ -0,0 +1,69 @@ +import numpy as np +import matplotlib.pyplot as plt +import os + +from util.mraw import mraw +from util.file_utils import get_mraw_from_dir, get_prefix_from_idxs + + +def load_norm_mat(dataset_dir="C:/Users/eda1g15/OneDrive - University of Southampton/Research/Porous Materials/" + "Data/Steel plates/w20vf24squares/On a hole/"): + """ Load a normalisation matrix for pixel errors. Default dataset dir is set for a clean data set. """ + subdirs = [d for d in os.listdir(dataset_dir) if "movie_C001H001S" in d or "movie_S" in d or "movie" in d] + all_idxs = [] + max_idx = 0 + for sd in subdirs: + if "movie_C001H001S" in sd: + idx = int(sd.split("movie_C001H001S")[-1]) + elif "movie_S" in sd: + idx = int(sd.split("movie_S")[-1]) + elif "movie" in sd: + idx = int(sd.split("movie")[-1]) + else: + raise RuntimeError("Could not find movies in " + dataset_dir) + + if idx > max_idx: + max_idx = idx + + all_idxs.append(idx) + + prefix = get_prefix_from_idxs(dataset_dir, all_idxs) + + norm_mats = [] + if len(all_idxs) > 10: + first_blank = max_idx - 2 + else: + first_blank = max_idx + for i in range(first_blank, max_idx + 1): + max_mraw = get_mraw_from_dir(dataset_dir + f"{prefix}{i:04d}/") # type: mraw + med = np.median(max_mraw[0]) + norm_mats.append(med / max_mraw[0]) + return np.median(norm_mats, axis=0) + + +def safe_correct(frame, norm_mat, max_value=2 ** 12 - 1): + """ Performs pixel correction but ignores saturated pixels. """ + out = np.copy(np.float64(frame)) + np.multiply(norm_mat, frame, out=out, where=frame != max_value) + np.minimum(out, max_value, out=out) # Cap values that become over-saturated (possible for almost-saturated pixels). + return out + + +if __name__ == "__main__": + mov_dir = "C:/Users/eda1g15/OneDrive - University of Southampton/Research/Porous Materials/" \ + "Data/Steel plates/w12vf16triangles/On a hole/movie_C001H001S0001/" + normalisation_mat = load_norm_mat(mov_dir + "../") + + mov = get_mraw_from_dir(mov_dir) # type: mraw + plt.figure() + plt.imshow(mov[32], plt.cm.gray) + plt.xticks([]) + plt.yticks([]) + plt.tight_layout() + + plt.figure() + plt.imshow(normalisation_mat * mov[32], plt.cm.gray) + plt.xticks([]) + plt.yticks([]) + plt.tight_layout() + plt.show() diff --git a/paper_code/porous/util/plotting_utils.py b/packaged-code/pacakged-gui/util/plotting_utils.py similarity index 100% rename from paper_code/porous/util/plotting_utils.py rename to packaged-code/pacakged-gui/util/plotting_utils.py diff --git a/packaged-code/pacakged-gui/util/qt_utils.py b/packaged-code/pacakged-gui/util/qt_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..ab2d9a2f42350063db0fc5f9a3d9caba5ba5a28a --- /dev/null +++ b/packaged-code/pacakged-gui/util/qt_utils.py @@ -0,0 +1,18 @@ +import numpy as np +from PyQt5.QtGui import QImage, QPixmap +from util.pixel_correction import safe_correct + + +def frame_to_pixmap(frame, autoscale=True, min=None, max=None, norm_mat=None): + if norm_mat is not None: + frame = safe_correct(frame, norm_mat) + if autoscale: + if min is not None and max is not None: + img_8bit = ((frame - min) / ((max - min) / 255.0)).astype(np.uint8) # map the data range to 0 - 255 + else: + img_8bit = ((frame - frame.min()) / (frame.ptp() / 255.0)).astype(np.uint8) # map the data range to 0 - 255 + else: + img_8bit = (frame / (4095 / 255)).astype(np.uint8) + img = QImage(img_8bit, img_8bit.shape[1], img_8bit.shape[0], QImage.Format_Grayscale8) + pixmap = QPixmap(img) + return pixmap diff --git a/paper_code/slots/bem/util/vector_utils.py b/packaged-code/pacakged-gui/util/vector_utils.py similarity index 100% rename from paper_code/slots/bem/util/vector_utils.py rename to packaged-code/pacakged-gui/util/vector_utils.py diff --git a/paper_code/porous/fig_data/complex_geometry_anisotropy_data.csv b/packaged-code/porous/fig_data/complex_geometry_anisotropy_data.csv similarity index 100% rename from paper_code/porous/fig_data/complex_geometry_anisotropy_data.csv rename to packaged-code/porous/fig_data/complex_geometry_anisotropy_data.csv diff --git a/paper_code/porous/fig_data/surface_nucleation.mp4 b/packaged-code/porous/fig_data/surface_nucleation.mp4 similarity index 100% rename from paper_code/porous/fig_data/surface_nucleation.mp4 rename to packaged-code/porous/fig_data/surface_nucleation.mp4 diff --git a/paper_code/porous/figure10.py b/packaged-code/porous/figure10.py similarity index 100% rename from paper_code/porous/figure10.py rename to packaged-code/porous/figure10.py diff --git a/paper_code/porous/figure12.py b/packaged-code/porous/figure12.py similarity index 100% rename from paper_code/porous/figure12.py rename to packaged-code/porous/figure12.py diff --git a/paper_code/porous/figure13.py b/packaged-code/porous/figure13.py similarity index 100% rename from paper_code/porous/figure13.py rename to packaged-code/porous/figure13.py diff --git a/paper_code/porous/figure14and15.py b/packaged-code/porous/figure14and15.py similarity index 100% rename from paper_code/porous/figure14and15.py rename to packaged-code/porous/figure14and15.py diff --git a/paper_code/porous/figure3.py b/packaged-code/porous/figure3.py similarity index 100% rename from paper_code/porous/figure3.py rename to packaged-code/porous/figure3.py diff --git a/paper_code/porous/figure4.py b/packaged-code/porous/figure4.py similarity index 100% rename from paper_code/porous/figure4.py rename to packaged-code/porous/figure4.py diff --git a/paper_code/porous/figure5.py b/packaged-code/porous/figure5.py similarity index 100% rename from paper_code/porous/figure5.py rename to packaged-code/porous/figure5.py diff --git a/paper_code/porous/figure6.py b/packaged-code/porous/figure6.py similarity index 100% rename from paper_code/porous/figure6.py rename to packaged-code/porous/figure6.py diff --git a/paper_code/porous/figure7.py b/packaged-code/porous/figure7.py similarity index 100% rename from paper_code/porous/figure7.py rename to packaged-code/porous/figure7.py diff --git a/paper_code/porous/figure8.py b/packaged-code/porous/figure8.py similarity index 100% rename from paper_code/porous/figure8.py rename to packaged-code/porous/figure8.py diff --git a/paper_code/porous/figure9.py b/packaged-code/porous/figure9.py similarity index 100% rename from paper_code/porous/figure9.py rename to packaged-code/porous/figure9.py diff --git a/paper_code/porous/steel_porous_plate_anisotropy.py b/packaged-code/porous/steel_porous_plate_anisotropy.py similarity index 100% rename from paper_code/porous/steel_porous_plate_anisotropy.py rename to packaged-code/porous/steel_porous_plate_anisotropy.py diff --git a/paper_code/thesis/chapter 2/util/analysis_utils.py b/packaged-code/porous/util/analysis_utils.py similarity index 100% rename from paper_code/thesis/chapter 2/util/analysis_utils.py rename to packaged-code/porous/util/analysis_utils.py diff --git a/paper_code/porous/util/bem.py b/packaged-code/porous/util/bem.py similarity index 100% rename from paper_code/porous/util/bem.py rename to packaged-code/porous/util/bem.py diff --git a/paper_code/thesis/chapter 2/util/determineDisplacement.py b/packaged-code/porous/util/determineDisplacement.py similarity index 100% rename from paper_code/thesis/chapter 2/util/determineDisplacement.py rename to packaged-code/porous/util/determineDisplacement.py diff --git a/paper_code/porous/util/drawing_utils.py b/packaged-code/porous/util/drawing_utils.py similarity index 100% rename from paper_code/porous/util/drawing_utils.py rename to packaged-code/porous/util/drawing_utils.py diff --git a/paper_code/thesis/chapter 2/util/file_utils.py b/packaged-code/porous/util/file_utils.py similarity index 100% rename from paper_code/thesis/chapter 2/util/file_utils.py rename to packaged-code/porous/util/file_utils.py diff --git a/paper_code/porous/util/gen_utils.py b/packaged-code/porous/util/gen_utils.py similarity index 100% rename from paper_code/porous/util/gen_utils.py rename to packaged-code/porous/util/gen_utils.py diff --git a/paper_code/thesis/chapter 2/util/mp4.py b/packaged-code/porous/util/mp4.py similarity index 100% rename from paper_code/thesis/chapter 2/util/mp4.py rename to packaged-code/porous/util/mp4.py diff --git a/paper_code/thesis/chapter 2/util/mraw.py b/packaged-code/porous/util/mraw.py similarity index 100% rename from paper_code/thesis/chapter 2/util/mraw.py rename to packaged-code/porous/util/mraw.py diff --git a/paper_code/thesis/chapter 2/util/plotting_utils.py b/packaged-code/porous/util/plotting_utils.py similarity index 100% rename from paper_code/thesis/chapter 2/util/plotting_utils.py rename to packaged-code/porous/util/plotting_utils.py diff --git a/paper_code/slots/bem/bem.py b/packaged-code/slots/bem/bem.py similarity index 100% rename from paper_code/slots/bem/bem.py rename to packaged-code/slots/bem/bem.py diff --git a/paper_code/slots/bem/slot.py b/packaged-code/slots/bem/slot.py similarity index 100% rename from paper_code/slots/bem/slot.py rename to packaged-code/slots/bem/slot.py diff --git a/paper_code/slots/bem/util/file_utils.py b/packaged-code/slots/bem/util/file_utils.py similarity index 100% rename from paper_code/slots/bem/util/file_utils.py rename to packaged-code/slots/bem/util/file_utils.py diff --git a/paper_code/slots/bem/util/gen_utils.py b/packaged-code/slots/bem/util/gen_utils.py similarity index 100% rename from paper_code/slots/bem/util/gen_utils.py rename to packaged-code/slots/bem/util/gen_utils.py diff --git a/paper_code/slots/bem/util/plotting_utils.py b/packaged-code/slots/bem/util/plotting_utils.py similarity index 100% rename from paper_code/slots/bem/util/plotting_utils.py rename to packaged-code/slots/bem/util/plotting_utils.py diff --git a/paper_code/thesis/chapter 3/bem/util/vector_utils.py b/packaged-code/slots/bem/util/vector_utils.py similarity index 100% rename from paper_code/thesis/chapter 3/bem/util/vector_utils.py rename to packaged-code/slots/bem/util/vector_utils.py diff --git a/paper_code/slots/figure_plots/all_direct_comparisons.py b/packaged-code/slots/figure_plots/all_direct_comparisons.py similarity index 100% rename from paper_code/slots/figure_plots/all_direct_comparisons.py rename to packaged-code/slots/figure_plots/all_direct_comparisons.py diff --git a/paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y1.94.csv b/packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y1.94.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y1.94.csv rename to packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y1.94.csv diff --git a/paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y2.91.csv b/packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y2.91.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y2.91.csv rename to packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y2.91.csv diff --git a/paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y3.89.csv b/packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y3.89.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y3.89.csv rename to packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y3.89.csv diff --git a/paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H12_Y2.63.csv b/packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H12_Y2.63.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H12_Y2.63.csv rename to packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H12_Y2.63.csv diff --git a/paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y1.77.csv b/packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y1.77.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y1.77.csv rename to packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y1.77.csv diff --git a/paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y2.29.csv b/packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y2.29.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y2.29.csv rename to packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y2.29.csv diff --git a/paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y2.81.csv b/packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y2.81.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y2.81.csv rename to packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y2.81.csv diff --git a/paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y3.32.csv b/packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y3.32.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y3.32.csv rename to packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y3.32.csv diff --git a/paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y3.84.csv b/packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y3.84.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y3.84.csv rename to packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y3.84.csv diff --git a/paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3b_Y2.66.csv b/packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3b_Y2.66.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3b_Y2.66.csv rename to packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3b_Y2.66.csv diff --git a/paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3b_Y3.68.csv b/packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3b_Y3.68.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3b_Y3.68.csv rename to packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H3b_Y3.68.csv diff --git a/paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y1.52.csv b/packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y1.52.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y1.52.csv rename to packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y1.52.csv diff --git a/paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y1.99.csv b/packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y1.99.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y1.99.csv rename to packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y1.99.csv diff --git a/paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y2.48.csv b/packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y2.48.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y2.48.csv rename to packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y2.48.csv diff --git a/paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y2.99.csv b/packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y2.99.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y2.99.csv rename to packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y2.99.csv diff --git a/paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y3.50.csv b/packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y3.50.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y3.50.csv rename to packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y3.50.csv diff --git a/paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H9_Y1.66.csv b/packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H9_Y1.66.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H9_Y1.66.csv rename to packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H9_Y1.66.csv diff --git a/paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H9_Y2.66.csv b/packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H9_Y2.66.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H9_Y2.66.csv rename to packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W2H9_Y2.66.csv diff --git a/paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W4H12_Y2.43.csv b/packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W4H12_Y2.43.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W4H12_Y2.43.csv rename to packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W4H12_Y2.43.csv diff --git a/paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W4H12_Y3.43.csv b/packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W4H12_Y3.43.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W4H12_Y3.43.csv rename to packaged-code/slots/figure_plots/experiment_data/mean_data/mean_sweep_W4H12_Y3.43.csv diff --git a/paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y1.94.csv b/packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y1.94.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y1.94.csv rename to packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y1.94.csv diff --git a/paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y2.91.csv b/packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y2.91.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y2.91.csv rename to packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y2.91.csv diff --git a/paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y3.89.csv b/packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y3.89.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y3.89.csv rename to packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y3.89.csv diff --git a/paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H12_Y2.63.csv b/packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H12_Y2.63.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H12_Y2.63.csv rename to packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H12_Y2.63.csv diff --git a/paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y1.77.csv b/packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y1.77.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y1.77.csv rename to packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y1.77.csv diff --git a/paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y2.29.csv b/packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y2.29.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y2.29.csv rename to packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y2.29.csv diff --git a/paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y2.81.csv b/packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y2.81.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y2.81.csv rename to packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y2.81.csv diff --git a/paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y3.32.csv b/packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y3.32.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y3.32.csv rename to packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y3.32.csv diff --git a/paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y3.84.csv b/packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y3.84.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y3.84.csv rename to packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y3.84.csv diff --git a/paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3b_Y2.66.csv b/packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3b_Y2.66.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3b_Y2.66.csv rename to packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3b_Y2.66.csv diff --git a/paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3b_Y3.68.csv b/packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3b_Y3.68.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3b_Y3.68.csv rename to packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3b_Y3.68.csv diff --git a/paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y1.52.csv b/packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y1.52.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y1.52.csv rename to packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y1.52.csv diff --git a/paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y1.99.csv b/packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y1.99.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y1.99.csv rename to packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y1.99.csv diff --git a/paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y2.48.csv b/packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y2.48.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y2.48.csv rename to packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y2.48.csv diff --git a/paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y2.99.csv b/packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y2.99.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y2.99.csv rename to packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y2.99.csv diff --git a/paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y3.50.csv b/packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y3.50.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y3.50.csv rename to packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y3.50.csv diff --git a/paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H9_Y1.66.csv b/packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H9_Y1.66.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H9_Y1.66.csv rename to packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H9_Y1.66.csv diff --git a/paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H9_Y2.66.csv b/packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H9_Y2.66.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H9_Y2.66.csv rename to packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H9_Y2.66.csv diff --git a/paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W4H12_Y2.43.csv b/packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W4H12_Y2.43.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W4H12_Y2.43.csv rename to packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W4H12_Y2.43.csv diff --git a/paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W4H12_Y3.43.csv b/packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W4H12_Y3.43.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W4H12_Y3.43.csv rename to packaged-code/slots/figure_plots/experiment_data/raw_data/raw_data_sweep_W4H12_Y3.43.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y1.94.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y1.94.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y1.94.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y1.94.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y2.91.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y2.91.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y2.91.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y2.91.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y3.89.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y3.89.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y3.89.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y3.89.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H12_Y2.63.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H12_Y2.63.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H12_Y2.63.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H12_Y2.63.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y1.77.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y1.77.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y1.77.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y1.77.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y2.29.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y2.29.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y2.29.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y2.29.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y2.81.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y2.81.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y2.81.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y2.81.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y3.32.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y3.32.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y3.32.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y3.32.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y3.84.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y3.84.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y3.84.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y3.84.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3b_Y2.66.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3b_Y2.66.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3b_Y2.66.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3b_Y2.66.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3b_Y3.68.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3b_Y3.68.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3b_Y3.68.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3b_Y3.68.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y1.52.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y1.52.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y1.52.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y1.52.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y1.99.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y1.99.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y1.99.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y1.99.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y2.48.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y2.48.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y2.48.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y2.48.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y2.99.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y2.99.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y2.99.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y2.99.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y3.50.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y3.50.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y3.50.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y3.50.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H9_Y1.66.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H9_Y1.66.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H9_Y1.66.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H9_Y1.66.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H9_Y2.66.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H9_Y2.66.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H9_Y2.66.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H9_Y2.66.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W4H12_Y2.43.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W4H12_Y2.43.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W4H12_Y2.43.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W4H12_Y2.43.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W4H12_Y3.43.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W4H12_Y3.43.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W4H12_Y3.43.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W4H12_Y3.43.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y1.94.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y1.94.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y1.94.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y1.94.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y2.91.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y2.91.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y2.91.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y2.91.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y3.89.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y3.89.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y3.89.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y3.89.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H12_Y2.63.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H12_Y2.63.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H12_Y2.63.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H12_Y2.63.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y1.77.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y1.77.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y1.77.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y1.77.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y2.29.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y2.29.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y2.29.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y2.29.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y2.81.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y2.81.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y2.81.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y2.81.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y3.32.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y3.32.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y3.32.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y3.32.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y3.84.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y3.84.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y3.84.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y3.84.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3b_Y2.66.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3b_Y2.66.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3b_Y2.66.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3b_Y2.66.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3b_Y3.68.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3b_Y3.68.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3b_Y3.68.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3b_Y3.68.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y1.52.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y1.52.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y1.52.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y1.52.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y1.99.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y1.99.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y1.99.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y1.99.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y2.48.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y2.48.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y2.48.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y2.48.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y2.99.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y2.99.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y2.99.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y2.99.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y3.50.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y3.50.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y3.50.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y3.50.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H9_Y1.66.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H9_Y1.66.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H9_Y1.66.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H9_Y1.66.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H9_Y2.66.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H9_Y2.66.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H9_Y2.66.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H9_Y2.66.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W4H12_Y2.43.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W4H12_Y2.43.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W4H12_Y2.43.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W4H12_Y2.43.csv diff --git a/paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W4H12_Y3.43.csv b/packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W4H12_Y3.43.csv similarity index 100% rename from paper_code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W4H12_Y3.43.csv rename to packaged-code/slots/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W4H12_Y3.43.csv diff --git a/paper_code/slots/figure_plots/figure10.py b/packaged-code/slots/figure_plots/figure10.py similarity index 100% rename from paper_code/slots/figure_plots/figure10.py rename to packaged-code/slots/figure_plots/figure10.py diff --git a/paper_code/slots/figure_plots/figure11.py b/packaged-code/slots/figure_plots/figure11.py similarity index 100% rename from paper_code/slots/figure_plots/figure11.py rename to packaged-code/slots/figure_plots/figure11.py diff --git a/paper_code/slots/figure_plots/figure12.py b/packaged-code/slots/figure_plots/figure12.py similarity index 100% rename from paper_code/slots/figure_plots/figure12.py rename to packaged-code/slots/figure_plots/figure12.py diff --git a/paper_code/slots/figure_plots/figure13.py b/packaged-code/slots/figure_plots/figure13.py similarity index 100% rename from paper_code/slots/figure_plots/figure13.py rename to packaged-code/slots/figure_plots/figure13.py diff --git a/paper_code/slots/figure_plots/figure13_data/W1H3_experimental b/packaged-code/slots/figure_plots/figure13_data/W1H3_experimental similarity index 100% rename from paper_code/slots/figure_plots/figure13_data/W1H3_experimental rename to packaged-code/slots/figure_plots/figure13_data/W1H3_experimental diff --git a/paper_code/slots/figure_plots/figure13_data/W1H3_numerical b/packaged-code/slots/figure_plots/figure13_data/W1H3_numerical similarity index 100% rename from paper_code/slots/figure_plots/figure13_data/W1H3_numerical rename to packaged-code/slots/figure_plots/figure13_data/W1H3_numerical diff --git a/paper_code/slots/figure_plots/figure13_data/W2H3a_experimental b/packaged-code/slots/figure_plots/figure13_data/W2H3a_experimental similarity index 100% rename from paper_code/slots/figure_plots/figure13_data/W2H3a_experimental rename to packaged-code/slots/figure_plots/figure13_data/W2H3a_experimental diff --git a/paper_code/slots/figure_plots/figure13_data/W2H3a_numerical b/packaged-code/slots/figure_plots/figure13_data/W2H3a_numerical similarity index 100% rename from paper_code/slots/figure_plots/figure13_data/W2H3a_numerical rename to packaged-code/slots/figure_plots/figure13_data/W2H3a_numerical diff --git a/paper_code/slots/figure_plots/figure5.py b/packaged-code/slots/figure_plots/figure5.py similarity index 100% rename from paper_code/slots/figure_plots/figure5.py rename to packaged-code/slots/figure_plots/figure5.py diff --git a/paper_code/slots/figure_plots/figure5_data/centroids_n20000_w2.00_h2.00_drat0.1_wthresh12_len100.csv b/packaged-code/slots/figure_plots/figure5_data/centroids_n20000_w2.00_h2.00_drat0.1_wthresh12_len100.csv similarity index 100% rename from paper_code/slots/figure_plots/figure5_data/centroids_n20000_w2.00_h2.00_drat0.1_wthresh12_len100.csv rename to packaged-code/slots/figure_plots/figure5_data/centroids_n20000_w2.00_h2.00_drat0.1_wthresh12_len100.csv diff --git a/paper_code/slots/figure_plots/figure5_data/normals_n20000_w2.00_h2.00_drat0.1_wthresh12_len100.csv b/packaged-code/slots/figure_plots/figure5_data/normals_n20000_w2.00_h2.00_drat0.1_wthresh12_len100.csv similarity index 100% rename from paper_code/slots/figure_plots/figure5_data/normals_n20000_w2.00_h2.00_drat0.1_wthresh12_len100.csv rename to packaged-code/slots/figure_plots/figure5_data/normals_n20000_w2.00_h2.00_drat0.1_wthresh12_len100.csv diff --git a/paper_code/slots/figure_plots/figure5_data/vel_sweep_n20000_W2.00_H2.00_drat0.1_wthresh12_len100_N64.csv b/packaged-code/slots/figure_plots/figure5_data/vel_sweep_n20000_W2.00_H2.00_drat0.1_wthresh12_len100_N64.csv similarity index 100% rename from paper_code/slots/figure_plots/figure5_data/vel_sweep_n20000_W2.00_H2.00_drat0.1_wthresh12_len100_N64.csv rename to packaged-code/slots/figure_plots/figure5_data/vel_sweep_n20000_W2.00_H2.00_drat0.1_wthresh12_len100_N64.csv diff --git a/paper_code/slots/figure_plots/figure6.py b/packaged-code/slots/figure_plots/figure6.py similarity index 100% rename from paper_code/slots/figure_plots/figure6.py rename to packaged-code/slots/figure_plots/figure6.py diff --git a/paper_code/slots/figure_plots/figure6_data/h_collapse_n20000_H1.0.csv b/packaged-code/slots/figure_plots/figure6_data/h_collapse_n20000_H1.0.csv similarity index 100% rename from paper_code/slots/figure_plots/figure6_data/h_collapse_n20000_H1.0.csv rename to packaged-code/slots/figure_plots/figure6_data/h_collapse_n20000_H1.0.csv diff --git a/paper_code/slots/figure_plots/figure6_data/h_collapse_n20000_H2.0.csv b/packaged-code/slots/figure_plots/figure6_data/h_collapse_n20000_H2.0.csv similarity index 100% rename from paper_code/slots/figure_plots/figure6_data/h_collapse_n20000_H2.0.csv rename to packaged-code/slots/figure_plots/figure6_data/h_collapse_n20000_H2.0.csv diff --git a/paper_code/slots/figure_plots/figure6_data/h_collapse_n20000_H3.0.csv b/packaged-code/slots/figure_plots/figure6_data/h_collapse_n20000_H3.0.csv similarity index 100% rename from paper_code/slots/figure_plots/figure6_data/h_collapse_n20000_H3.0.csv rename to packaged-code/slots/figure_plots/figure6_data/h_collapse_n20000_H3.0.csv diff --git a/paper_code/slots/figure_plots/figure6_data/h_collapse_n20000_H4.0.csv b/packaged-code/slots/figure_plots/figure6_data/h_collapse_n20000_H4.0.csv similarity index 100% rename from paper_code/slots/figure_plots/figure6_data/h_collapse_n20000_H4.0.csv rename to packaged-code/slots/figure_plots/figure6_data/h_collapse_n20000_H4.0.csv diff --git a/paper_code/slots/figure_plots/figure6_data/h_collapse_n20000_H5.0.csv b/packaged-code/slots/figure_plots/figure6_data/h_collapse_n20000_H5.0.csv similarity index 100% rename from paper_code/slots/figure_plots/figure6_data/h_collapse_n20000_H5.0.csv rename to packaged-code/slots/figure_plots/figure6_data/h_collapse_n20000_H5.0.csv diff --git a/paper_code/slots/figure_plots/figure7.py b/packaged-code/slots/figure_plots/figure7.py similarity index 100% rename from paper_code/slots/figure_plots/figure7.py rename to packaged-code/slots/figure_plots/figure7.py diff --git a/paper_code/slots/figure_plots/figure7_data/y_collapse_n20000_Y1.0.csv b/packaged-code/slots/figure_plots/figure7_data/y_collapse_n20000_Y1.0.csv similarity index 100% rename from paper_code/slots/figure_plots/figure7_data/y_collapse_n20000_Y1.0.csv rename to packaged-code/slots/figure_plots/figure7_data/y_collapse_n20000_Y1.0.csv diff --git a/paper_code/slots/figure_plots/figure7_data/y_collapse_n20000_Y2.0.csv b/packaged-code/slots/figure_plots/figure7_data/y_collapse_n20000_Y2.0.csv similarity index 100% rename from paper_code/slots/figure_plots/figure7_data/y_collapse_n20000_Y2.0.csv rename to packaged-code/slots/figure_plots/figure7_data/y_collapse_n20000_Y2.0.csv diff --git a/paper_code/slots/figure_plots/figure7_data/y_collapse_n20000_Y3.0.csv b/packaged-code/slots/figure_plots/figure7_data/y_collapse_n20000_Y3.0.csv similarity index 100% rename from paper_code/slots/figure_plots/figure7_data/y_collapse_n20000_Y3.0.csv rename to packaged-code/slots/figure_plots/figure7_data/y_collapse_n20000_Y3.0.csv diff --git a/paper_code/slots/figure_plots/figure7_data/y_collapse_n20000_Y4.0.csv b/packaged-code/slots/figure_plots/figure7_data/y_collapse_n20000_Y4.0.csv similarity index 100% rename from paper_code/slots/figure_plots/figure7_data/y_collapse_n20000_Y4.0.csv rename to packaged-code/slots/figure_plots/figure7_data/y_collapse_n20000_Y4.0.csv diff --git a/paper_code/slots/figure_plots/figure7_data/y_collapse_n20000_Y5.0.csv b/packaged-code/slots/figure_plots/figure7_data/y_collapse_n20000_Y5.0.csv similarity index 100% rename from paper_code/slots/figure_plots/figure7_data/y_collapse_n20000_Y5.0.csv rename to packaged-code/slots/figure_plots/figure7_data/y_collapse_n20000_Y5.0.csv diff --git a/paper_code/slots/figure_plots/figure8.py b/packaged-code/slots/figure_plots/figure8.py similarity index 100% rename from paper_code/slots/figure_plots/figure8.py rename to packaged-code/slots/figure_plots/figure8.py diff --git a/paper_code/slots/figure_plots/figure8_data/peak_sweep_20000_16x16_plate_100.csv b/packaged-code/slots/figure_plots/figure8_data/peak_sweep_20000_16x16_plate_100.csv similarity index 100% rename from paper_code/slots/figure_plots/figure8_data/peak_sweep_20000_16x16_plate_100.csv rename to packaged-code/slots/figure_plots/figure8_data/peak_sweep_20000_16x16_plate_100.csv diff --git a/paper_code/slots/figure_plots/figure9.py b/packaged-code/slots/figure_plots/figure9.py similarity index 100% rename from paper_code/slots/figure_plots/figure9.py rename to packaged-code/slots/figure_plots/figure9.py diff --git a/paper_code/slots/figure_plots/model_predictions/W1.23H2.74Y1.94_bem_slot_prediction_20000_0.25_15.csv b/packaged-code/slots/figure_plots/model_predictions/W1.23H2.74Y1.94_bem_slot_prediction_20000_0.25_15.csv similarity index 100% rename from paper_code/slots/figure_plots/model_predictions/W1.23H2.74Y1.94_bem_slot_prediction_20000_0.25_15.csv rename to packaged-code/slots/figure_plots/model_predictions/W1.23H2.74Y1.94_bem_slot_prediction_20000_0.25_15.csv diff --git a/paper_code/slots/figure_plots/model_predictions/W1.23H2.74Y2.91_bem_slot_prediction_20000_0.25_15.csv b/packaged-code/slots/figure_plots/model_predictions/W1.23H2.74Y2.91_bem_slot_prediction_20000_0.25_15.csv similarity index 100% rename from paper_code/slots/figure_plots/model_predictions/W1.23H2.74Y2.91_bem_slot_prediction_20000_0.25_15.csv rename to packaged-code/slots/figure_plots/model_predictions/W1.23H2.74Y2.91_bem_slot_prediction_20000_0.25_15.csv diff --git a/paper_code/slots/figure_plots/model_predictions/W1.23H2.74Y3.89_bem_slot_prediction_20000_0.25_15.csv b/packaged-code/slots/figure_plots/model_predictions/W1.23H2.74Y3.89_bem_slot_prediction_20000_0.25_15.csv similarity index 100% rename from paper_code/slots/figure_plots/model_predictions/W1.23H2.74Y3.89_bem_slot_prediction_20000_0.25_15.csv rename to packaged-code/slots/figure_plots/model_predictions/W1.23H2.74Y3.89_bem_slot_prediction_20000_0.25_15.csv diff --git a/paper_code/slots/figure_plots/model_predictions/W2.14H8.21Y1.66_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/slots/figure_plots/model_predictions/W2.14H8.21Y1.66_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/slots/figure_plots/model_predictions/W2.14H8.21Y1.66_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/slots/figure_plots/model_predictions/W2.14H8.21Y1.66_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/slots/figure_plots/model_predictions/W2.14H8.21Y2.66_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/slots/figure_plots/model_predictions/W2.14H8.21Y2.66_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/slots/figure_plots/model_predictions/W2.14H8.21Y2.66_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/slots/figure_plots/model_predictions/W2.14H8.21Y2.66_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/slots/figure_plots/model_predictions/W2.20H11.50Y2.63_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/slots/figure_plots/model_predictions/W2.20H11.50Y2.63_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/slots/figure_plots/model_predictions/W2.20H11.50Y2.63_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/slots/figure_plots/model_predictions/W2.20H11.50Y2.63_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/slots/figure_plots/model_predictions/W2.20H2.70Y1.77_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/slots/figure_plots/model_predictions/W2.20H2.70Y1.77_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/slots/figure_plots/model_predictions/W2.20H2.70Y1.77_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/slots/figure_plots/model_predictions/W2.20H2.70Y1.77_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/slots/figure_plots/model_predictions/W2.20H2.70Y2.29_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/slots/figure_plots/model_predictions/W2.20H2.70Y2.29_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/slots/figure_plots/model_predictions/W2.20H2.70Y2.29_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/slots/figure_plots/model_predictions/W2.20H2.70Y2.29_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/slots/figure_plots/model_predictions/W2.20H2.70Y2.81_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/slots/figure_plots/model_predictions/W2.20H2.70Y2.81_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/slots/figure_plots/model_predictions/W2.20H2.70Y2.81_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/slots/figure_plots/model_predictions/W2.20H2.70Y2.81_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/slots/figure_plots/model_predictions/W2.20H2.70Y3.32_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/slots/figure_plots/model_predictions/W2.20H2.70Y3.32_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/slots/figure_plots/model_predictions/W2.20H2.70Y3.32_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/slots/figure_plots/model_predictions/W2.20H2.70Y3.32_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/slots/figure_plots/model_predictions/W2.20H2.70Y3.84_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/slots/figure_plots/model_predictions/W2.20H2.70Y3.84_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/slots/figure_plots/model_predictions/W2.20H2.70Y3.84_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/slots/figure_plots/model_predictions/W2.20H2.70Y3.84_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/slots/figure_plots/model_predictions/W2.20H2.90Y2.66_bem_slot_prediction_20000_0.25_8.csv b/packaged-code/slots/figure_plots/model_predictions/W2.20H2.90Y2.66_bem_slot_prediction_20000_0.25_8.csv similarity index 100% rename from paper_code/slots/figure_plots/model_predictions/W2.20H2.90Y2.66_bem_slot_prediction_20000_0.25_8.csv rename to packaged-code/slots/figure_plots/model_predictions/W2.20H2.90Y2.66_bem_slot_prediction_20000_0.25_8.csv diff --git a/paper_code/slots/figure_plots/model_predictions/W2.20H2.90Y3.68_bem_slot_prediction_20000_0.25_8.csv b/packaged-code/slots/figure_plots/model_predictions/W2.20H2.90Y3.68_bem_slot_prediction_20000_0.25_8.csv similarity index 100% rename from paper_code/slots/figure_plots/model_predictions/W2.20H2.90Y3.68_bem_slot_prediction_20000_0.25_8.csv rename to packaged-code/slots/figure_plots/model_predictions/W2.20H2.90Y3.68_bem_slot_prediction_20000_0.25_8.csv diff --git a/paper_code/slots/figure_plots/model_predictions/W2.20H5.40Y1.52_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/slots/figure_plots/model_predictions/W2.20H5.40Y1.52_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/slots/figure_plots/model_predictions/W2.20H5.40Y1.52_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/slots/figure_plots/model_predictions/W2.20H5.40Y1.52_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/slots/figure_plots/model_predictions/W2.20H5.40Y1.99_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/slots/figure_plots/model_predictions/W2.20H5.40Y1.99_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/slots/figure_plots/model_predictions/W2.20H5.40Y1.99_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/slots/figure_plots/model_predictions/W2.20H5.40Y1.99_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/slots/figure_plots/model_predictions/W4.20H11.47Y2.43_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/slots/figure_plots/model_predictions/W4.20H11.47Y2.43_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/slots/figure_plots/model_predictions/W4.20H11.47Y2.43_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/slots/figure_plots/model_predictions/W4.20H11.47Y2.43_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/slots/figure_plots/model_predictions/W4.20H11.47Y3.43_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/slots/figure_plots/model_predictions/W4.20H11.47Y3.43_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/slots/figure_plots/model_predictions/W4.20H11.47Y3.43_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/slots/figure_plots/model_predictions/W4.20H11.47Y3.43_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/slots/figure_plots/util/analyse_slot.py b/packaged-code/slots/figure_plots/util/analyse_slot.py similarity index 100% rename from paper_code/slots/figure_plots/util/analyse_slot.py rename to packaged-code/slots/figure_plots/util/analyse_slot.py diff --git a/paper_code/slots/figure_plots/util/analysis_utils.py b/packaged-code/slots/figure_plots/util/analysis_utils.py similarity index 100% rename from paper_code/slots/figure_plots/util/analysis_utils.py rename to packaged-code/slots/figure_plots/util/analysis_utils.py diff --git a/paper_code/slots/figure_plots/util/config_utils.py b/packaged-code/slots/figure_plots/util/config_utils.py similarity index 100% rename from paper_code/slots/figure_plots/util/config_utils.py rename to packaged-code/slots/figure_plots/util/config_utils.py diff --git a/paper_code/slots/figure_plots/util/file_utils.py b/packaged-code/slots/figure_plots/util/file_utils.py similarity index 100% rename from paper_code/slots/figure_plots/util/file_utils.py rename to packaged-code/slots/figure_plots/util/file_utils.py diff --git a/paper_code/slots/figure_plots/util/plotting_utils.py b/packaged-code/slots/figure_plots/util/plotting_utils.py similarity index 100% rename from paper_code/slots/figure_plots/util/plotting_utils.py rename to packaged-code/slots/figure_plots/util/plotting_utils.py diff --git a/paper_code/thesis/chapter 2/fig_data/plasma.mp4 b/packaged-code/thesis/chapter 2/fig_data/plasma.mp4 similarity index 100% rename from paper_code/thesis/chapter 2/fig_data/plasma.mp4 rename to packaged-code/thesis/chapter 2/fig_data/plasma.mp4 diff --git a/paper_code/thesis/chapter 2/figure5.py b/packaged-code/thesis/chapter 2/figure5.py similarity index 100% rename from paper_code/thesis/chapter 2/figure5.py rename to packaged-code/thesis/chapter 2/figure5.py diff --git a/paper_code/thesis/chapter 2/figure6.py b/packaged-code/thesis/chapter 2/figure6.py similarity index 100% rename from paper_code/thesis/chapter 2/figure6.py rename to packaged-code/thesis/chapter 2/figure6.py diff --git a/paper_code/thesis/chapter 2/figure7.py b/packaged-code/thesis/chapter 2/figure7.py similarity index 100% rename from paper_code/thesis/chapter 2/figure7.py rename to packaged-code/thesis/chapter 2/figure7.py diff --git a/paper_code/thesis/chapter 4/util/analysis_utils.py b/packaged-code/thesis/chapter 2/util/analysis_utils.py similarity index 100% rename from paper_code/thesis/chapter 4/util/analysis_utils.py rename to packaged-code/thesis/chapter 2/util/analysis_utils.py diff --git a/paper_code/thesis/chapter 4/util/determineDisplacement.py b/packaged-code/thesis/chapter 2/util/determineDisplacement.py similarity index 100% rename from paper_code/thesis/chapter 4/util/determineDisplacement.py rename to packaged-code/thesis/chapter 2/util/determineDisplacement.py diff --git a/paper_code/thesis/chapter 4/util/file_utils.py b/packaged-code/thesis/chapter 2/util/file_utils.py similarity index 100% rename from paper_code/thesis/chapter 4/util/file_utils.py rename to packaged-code/thesis/chapter 2/util/file_utils.py diff --git a/paper_code/thesis/chapter 4/util/mp4.py b/packaged-code/thesis/chapter 2/util/mp4.py similarity index 100% rename from paper_code/thesis/chapter 4/util/mp4.py rename to packaged-code/thesis/chapter 2/util/mp4.py diff --git a/paper_code/thesis/chapter 4/util/mraw.py b/packaged-code/thesis/chapter 2/util/mraw.py similarity index 100% rename from paper_code/thesis/chapter 4/util/mraw.py rename to packaged-code/thesis/chapter 2/util/mraw.py diff --git a/paper_code/thesis/chapter 4/util/plotting_utils.py b/packaged-code/thesis/chapter 2/util/plotting_utils.py similarity index 100% rename from paper_code/thesis/chapter 4/util/plotting_utils.py rename to packaged-code/thesis/chapter 2/util/plotting_utils.py diff --git a/paper_code/thesis/chapter 2/util/raytrace.py b/packaged-code/thesis/chapter 2/util/raytrace.py similarity index 100% rename from paper_code/thesis/chapter 2/util/raytrace.py rename to packaged-code/thesis/chapter 2/util/raytrace.py diff --git a/paper_code/thesis/chapter 3/bem/bem.py b/packaged-code/thesis/chapter 3/bem/bem.py similarity index 100% rename from paper_code/thesis/chapter 3/bem/bem.py rename to packaged-code/thesis/chapter 3/bem/bem.py diff --git a/paper_code/thesis/chapter 3/bem/slot.py b/packaged-code/thesis/chapter 3/bem/slot.py similarity index 100% rename from paper_code/thesis/chapter 3/bem/slot.py rename to packaged-code/thesis/chapter 3/bem/slot.py diff --git a/paper_code/thesis/chapter 3/bem/util/file_utils.py b/packaged-code/thesis/chapter 3/bem/util/file_utils.py similarity index 100% rename from paper_code/thesis/chapter 3/bem/util/file_utils.py rename to packaged-code/thesis/chapter 3/bem/util/file_utils.py diff --git a/paper_code/thesis/chapter 3/bem/util/gen_utils.py b/packaged-code/thesis/chapter 3/bem/util/gen_utils.py similarity index 100% rename from paper_code/thesis/chapter 3/bem/util/gen_utils.py rename to packaged-code/thesis/chapter 3/bem/util/gen_utils.py diff --git a/paper_code/thesis/chapter 3/bem/util/plotting_utils.py b/packaged-code/thesis/chapter 3/bem/util/plotting_utils.py similarity index 100% rename from paper_code/thesis/chapter 3/bem/util/plotting_utils.py rename to packaged-code/thesis/chapter 3/bem/util/plotting_utils.py diff --git a/paper_code/thesis/chapter 3/figure_plots/util/vector_utils.py b/packaged-code/thesis/chapter 3/bem/util/vector_utils.py similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/util/vector_utils.py rename to packaged-code/thesis/chapter 3/bem/util/vector_utils.py diff --git a/paper_code/thesis/chapter 3/figure_plots/all_direct_comparisons.py b/packaged-code/thesis/chapter 3/figure_plots/all_direct_comparisons.py similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/all_direct_comparisons.py rename to packaged-code/thesis/chapter 3/figure_plots/all_direct_comparisons.py diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y1.94.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y1.94.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y1.94.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y1.94.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y2.91.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y2.91.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y2.91.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y2.91.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y3.89.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y3.89.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y3.89.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W1H3_Y3.89.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H12_Y2.63.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H12_Y2.63.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H12_Y2.63.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H12_Y2.63.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y1.77.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y1.77.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y1.77.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y1.77.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y2.29.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y2.29.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y2.29.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y2.29.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y2.81.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y2.81.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y2.81.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y2.81.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y3.32.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y3.32.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y3.32.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y3.32.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y3.84.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y3.84.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y3.84.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3a_Y3.84.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3b_Y2.66.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3b_Y2.66.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3b_Y2.66.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3b_Y2.66.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3b_Y3.68.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3b_Y3.68.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3b_Y3.68.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H3b_Y3.68.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y1.52.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y1.52.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y1.52.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y1.52.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y1.99.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y1.99.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y1.99.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y1.99.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y2.48.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y2.48.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y2.48.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y2.48.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y2.99.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y2.99.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y2.99.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y2.99.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y3.50.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y3.50.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y3.50.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H6_Y3.50.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H9_Y1.66.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H9_Y1.66.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H9_Y1.66.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H9_Y1.66.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H9_Y2.66.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H9_Y2.66.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H9_Y2.66.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W2H9_Y2.66.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W4H12_Y2.43.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W4H12_Y2.43.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W4H12_Y2.43.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W4H12_Y2.43.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W4H12_Y3.43.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W4H12_Y3.43.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W4H12_Y3.43.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/mean_data/mean_sweep_W4H12_Y3.43.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y1.94.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y1.94.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y1.94.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y1.94.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y2.91.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y2.91.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y2.91.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y2.91.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y3.89.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y3.89.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y3.89.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W1H3_Y3.89.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H12_Y2.63.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H12_Y2.63.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H12_Y2.63.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H12_Y2.63.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y1.77.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y1.77.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y1.77.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y1.77.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y2.29.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y2.29.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y2.29.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y2.29.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y2.81.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y2.81.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y2.81.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y2.81.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y3.32.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y3.32.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y3.32.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y3.32.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y3.84.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y3.84.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y3.84.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3a_Y3.84.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3b_Y2.66.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3b_Y2.66.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3b_Y2.66.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3b_Y2.66.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3b_Y3.68.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3b_Y3.68.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3b_Y3.68.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H3b_Y3.68.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y1.52.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y1.52.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y1.52.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y1.52.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y1.99.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y1.99.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y1.99.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y1.99.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y2.48.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y2.48.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y2.48.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y2.48.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y2.99.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y2.99.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y2.99.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y2.99.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y3.50.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y3.50.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y3.50.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H6_Y3.50.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H9_Y1.66.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H9_Y1.66.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H9_Y1.66.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H9_Y1.66.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H9_Y2.66.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H9_Y2.66.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H9_Y2.66.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W2H9_Y2.66.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W4H12_Y2.43.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W4H12_Y2.43.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W4H12_Y2.43.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W4H12_Y2.43.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W4H12_Y3.43.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W4H12_Y3.43.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W4H12_Y3.43.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/raw_data/raw_data_sweep_W4H12_Y3.43.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y1.94.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y1.94.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y1.94.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y1.94.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y2.91.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y2.91.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y2.91.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y2.91.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y3.89.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y3.89.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y3.89.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W1H3_Y3.89.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H12_Y2.63.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H12_Y2.63.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H12_Y2.63.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H12_Y2.63.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y1.77.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y1.77.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y1.77.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y1.77.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y2.29.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y2.29.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y2.29.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y2.29.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y2.81.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y2.81.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y2.81.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y2.81.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y3.32.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y3.32.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y3.32.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y3.32.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y3.84.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y3.84.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y3.84.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3a_Y3.84.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3b_Y2.66.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3b_Y2.66.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3b_Y2.66.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3b_Y2.66.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3b_Y3.68.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3b_Y3.68.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3b_Y3.68.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H3b_Y3.68.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y1.52.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y1.52.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y1.52.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y1.52.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y1.99.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y1.99.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y1.99.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y1.99.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y2.48.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y2.48.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y2.48.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y2.48.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y2.99.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y2.99.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y2.99.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y2.99.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y3.50.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y3.50.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y3.50.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H6_Y3.50.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H9_Y1.66.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H9_Y1.66.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H9_Y1.66.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H9_Y1.66.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H9_Y2.66.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H9_Y2.66.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H9_Y2.66.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W2H9_Y2.66.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W4H12_Y2.43.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W4H12_Y2.43.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W4H12_Y2.43.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W4H12_Y2.43.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W4H12_Y3.43.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W4H12_Y3.43.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W4H12_Y3.43.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_data/shifted_data_sweep_W4H12_Y3.43.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y1.94.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y1.94.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y1.94.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y1.94.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y2.91.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y2.91.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y2.91.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y2.91.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y3.89.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y3.89.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y3.89.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W1H3_Y3.89.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H12_Y2.63.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H12_Y2.63.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H12_Y2.63.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H12_Y2.63.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y1.77.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y1.77.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y1.77.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y1.77.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y2.29.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y2.29.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y2.29.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y2.29.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y2.81.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y2.81.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y2.81.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y2.81.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y3.32.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y3.32.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y3.32.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y3.32.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y3.84.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y3.84.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y3.84.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3a_Y3.84.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3b_Y2.66.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3b_Y2.66.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3b_Y2.66.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3b_Y2.66.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3b_Y3.68.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3b_Y3.68.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3b_Y3.68.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H3b_Y3.68.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y1.52.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y1.52.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y1.52.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y1.52.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y1.99.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y1.99.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y1.99.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y1.99.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y2.48.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y2.48.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y2.48.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y2.48.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y2.99.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y2.99.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y2.99.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y2.99.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y3.50.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y3.50.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y3.50.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H6_Y3.50.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H9_Y1.66.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H9_Y1.66.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H9_Y1.66.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H9_Y1.66.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H9_Y2.66.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H9_Y2.66.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H9_Y2.66.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W2H9_Y2.66.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W4H12_Y2.43.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W4H12_Y2.43.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W4H12_Y2.43.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W4H12_Y2.43.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W4H12_Y3.43.csv b/packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W4H12_Y3.43.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W4H12_Y3.43.csv rename to packaged-code/thesis/chapter 3/figure_plots/experiment_data/shifted_mean_data/mean_sweep_W4H12_Y3.43.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure10.py b/packaged-code/thesis/chapter 3/figure_plots/figure10.py similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure10.py rename to packaged-code/thesis/chapter 3/figure_plots/figure10.py diff --git a/paper_code/thesis/chapter 3/figure_plots/figure10_data/peak_sweep_20000_16x16_plate_100.csv b/packaged-code/thesis/chapter 3/figure_plots/figure10_data/peak_sweep_20000_16x16_plate_100.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure10_data/peak_sweep_20000_16x16_plate_100.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure10_data/peak_sweep_20000_16x16_plate_100.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure11.py b/packaged-code/thesis/chapter 3/figure_plots/figure11.py similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure11.py rename to packaged-code/thesis/chapter 3/figure_plots/figure11.py diff --git a/paper_code/thesis/chapter 3/figure_plots/figure12.py b/packaged-code/thesis/chapter 3/figure_plots/figure12.py similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure12.py rename to packaged-code/thesis/chapter 3/figure_plots/figure12.py diff --git a/paper_code/thesis/chapter 3/figure_plots/figure13.py b/packaged-code/thesis/chapter 3/figure_plots/figure13.py similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure13.py rename to packaged-code/thesis/chapter 3/figure_plots/figure13.py diff --git a/paper_code/thesis/chapter 3/figure_plots/figure14.py b/packaged-code/thesis/chapter 3/figure_plots/figure14.py similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure14.py rename to packaged-code/thesis/chapter 3/figure_plots/figure14.py diff --git a/paper_code/thesis/chapter 3/figure_plots/figure15.py b/packaged-code/thesis/chapter 3/figure_plots/figure15.py similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure15.py rename to packaged-code/thesis/chapter 3/figure_plots/figure15.py diff --git a/paper_code/thesis/chapter 3/figure_plots/figure15_data/W1H3_experimental b/packaged-code/thesis/chapter 3/figure_plots/figure15_data/W1H3_experimental similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure15_data/W1H3_experimental rename to packaged-code/thesis/chapter 3/figure_plots/figure15_data/W1H3_experimental diff --git a/paper_code/thesis/chapter 3/figure_plots/figure15_data/W1H3_numerical b/packaged-code/thesis/chapter 3/figure_plots/figure15_data/W1H3_numerical similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure15_data/W1H3_numerical rename to packaged-code/thesis/chapter 3/figure_plots/figure15_data/W1H3_numerical diff --git a/paper_code/thesis/chapter 3/figure_plots/figure15_data/W2H3a_experimental b/packaged-code/thesis/chapter 3/figure_plots/figure15_data/W2H3a_experimental similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure15_data/W2H3a_experimental rename to packaged-code/thesis/chapter 3/figure_plots/figure15_data/W2H3a_experimental diff --git a/paper_code/thesis/chapter 3/figure_plots/figure15_data/W2H3a_numerical b/packaged-code/thesis/chapter 3/figure_plots/figure15_data/W2H3a_numerical similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure15_data/W2H3a_numerical rename to packaged-code/thesis/chapter 3/figure_plots/figure15_data/W2H3a_numerical diff --git a/paper_code/thesis/chapter 3/figure_plots/figure4.py b/packaged-code/thesis/chapter 3/figure_plots/figure4.py similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure4.py rename to packaged-code/thesis/chapter 3/figure_plots/figure4.py diff --git a/paper_code/thesis/chapter 3/figure_plots/figure6.py b/packaged-code/thesis/chapter 3/figure_plots/figure6.py similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure6.py rename to packaged-code/thesis/chapter 3/figure_plots/figure6.py diff --git a/paper_code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_10.csv b/packaged-code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_10.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_10.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_10.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_100.csv b/packaged-code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_100.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_100.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_100.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_150.csv b/packaged-code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_150.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_150.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_150.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_20.csv b/packaged-code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_20.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_20.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_20.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_200.csv b/packaged-code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_200.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_200.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_200.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_250.csv b/packaged-code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_250.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_250.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_250.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_30.csv b/packaged-code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_30.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_30.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_30.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_40.csv b/packaged-code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_40.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_40.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_40.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_50.csv b/packaged-code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_50.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_50.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure6_data/uniform_corner_rms_between_panels_50.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure7.py b/packaged-code/thesis/chapter 3/figure_plots/figure7.py similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure7.py rename to packaged-code/thesis/chapter 3/figure_plots/figure7.py diff --git a/paper_code/thesis/chapter 3/figure_plots/figure7_data/centroids_n20000_w2.00_h2.00_drat0.1_wthresh12_len100.csv b/packaged-code/thesis/chapter 3/figure_plots/figure7_data/centroids_n20000_w2.00_h2.00_drat0.1_wthresh12_len100.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure7_data/centroids_n20000_w2.00_h2.00_drat0.1_wthresh12_len100.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure7_data/centroids_n20000_w2.00_h2.00_drat0.1_wthresh12_len100.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure7_data/normals_n20000_w2.00_h2.00_drat0.1_wthresh12_len100.csv b/packaged-code/thesis/chapter 3/figure_plots/figure7_data/normals_n20000_w2.00_h2.00_drat0.1_wthresh12_len100.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure7_data/normals_n20000_w2.00_h2.00_drat0.1_wthresh12_len100.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure7_data/normals_n20000_w2.00_h2.00_drat0.1_wthresh12_len100.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure7_data/vel_sweep_n20000_W2.00_H2.00_drat0.1_wthresh12_len100_N64.csv b/packaged-code/thesis/chapter 3/figure_plots/figure7_data/vel_sweep_n20000_W2.00_H2.00_drat0.1_wthresh12_len100_N64.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure7_data/vel_sweep_n20000_W2.00_H2.00_drat0.1_wthresh12_len100_N64.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure7_data/vel_sweep_n20000_W2.00_H2.00_drat0.1_wthresh12_len100_N64.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure8.py b/packaged-code/thesis/chapter 3/figure_plots/figure8.py similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure8.py rename to packaged-code/thesis/chapter 3/figure_plots/figure8.py diff --git a/paper_code/thesis/chapter 3/figure_plots/figure8_data/h_collapse_n20000_H1.0.csv b/packaged-code/thesis/chapter 3/figure_plots/figure8_data/h_collapse_n20000_H1.0.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure8_data/h_collapse_n20000_H1.0.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure8_data/h_collapse_n20000_H1.0.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure8_data/h_collapse_n20000_H2.0.csv b/packaged-code/thesis/chapter 3/figure_plots/figure8_data/h_collapse_n20000_H2.0.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure8_data/h_collapse_n20000_H2.0.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure8_data/h_collapse_n20000_H2.0.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure8_data/h_collapse_n20000_H3.0.csv b/packaged-code/thesis/chapter 3/figure_plots/figure8_data/h_collapse_n20000_H3.0.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure8_data/h_collapse_n20000_H3.0.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure8_data/h_collapse_n20000_H3.0.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure8_data/h_collapse_n20000_H4.0.csv b/packaged-code/thesis/chapter 3/figure_plots/figure8_data/h_collapse_n20000_H4.0.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure8_data/h_collapse_n20000_H4.0.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure8_data/h_collapse_n20000_H4.0.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure8_data/h_collapse_n20000_H5.0.csv b/packaged-code/thesis/chapter 3/figure_plots/figure8_data/h_collapse_n20000_H5.0.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure8_data/h_collapse_n20000_H5.0.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure8_data/h_collapse_n20000_H5.0.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure9.py b/packaged-code/thesis/chapter 3/figure_plots/figure9.py similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure9.py rename to packaged-code/thesis/chapter 3/figure_plots/figure9.py diff --git a/paper_code/thesis/chapter 3/figure_plots/figure9_data/y_collapse_n20000_Y1.0.csv b/packaged-code/thesis/chapter 3/figure_plots/figure9_data/y_collapse_n20000_Y1.0.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure9_data/y_collapse_n20000_Y1.0.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure9_data/y_collapse_n20000_Y1.0.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure9_data/y_collapse_n20000_Y2.0.csv b/packaged-code/thesis/chapter 3/figure_plots/figure9_data/y_collapse_n20000_Y2.0.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure9_data/y_collapse_n20000_Y2.0.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure9_data/y_collapse_n20000_Y2.0.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure9_data/y_collapse_n20000_Y3.0.csv b/packaged-code/thesis/chapter 3/figure_plots/figure9_data/y_collapse_n20000_Y3.0.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure9_data/y_collapse_n20000_Y3.0.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure9_data/y_collapse_n20000_Y3.0.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure9_data/y_collapse_n20000_Y4.0.csv b/packaged-code/thesis/chapter 3/figure_plots/figure9_data/y_collapse_n20000_Y4.0.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure9_data/y_collapse_n20000_Y4.0.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure9_data/y_collapse_n20000_Y4.0.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/figure9_data/y_collapse_n20000_Y5.0.csv b/packaged-code/thesis/chapter 3/figure_plots/figure9_data/y_collapse_n20000_Y5.0.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/figure9_data/y_collapse_n20000_Y5.0.csv rename to packaged-code/thesis/chapter 3/figure_plots/figure9_data/y_collapse_n20000_Y5.0.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/model_predictions/W1.23H2.74Y1.94_bem_slot_prediction_20000_0.25_15.csv b/packaged-code/thesis/chapter 3/figure_plots/model_predictions/W1.23H2.74Y1.94_bem_slot_prediction_20000_0.25_15.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/model_predictions/W1.23H2.74Y1.94_bem_slot_prediction_20000_0.25_15.csv rename to packaged-code/thesis/chapter 3/figure_plots/model_predictions/W1.23H2.74Y1.94_bem_slot_prediction_20000_0.25_15.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/model_predictions/W1.23H2.74Y2.91_bem_slot_prediction_20000_0.25_15.csv b/packaged-code/thesis/chapter 3/figure_plots/model_predictions/W1.23H2.74Y2.91_bem_slot_prediction_20000_0.25_15.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/model_predictions/W1.23H2.74Y2.91_bem_slot_prediction_20000_0.25_15.csv rename to packaged-code/thesis/chapter 3/figure_plots/model_predictions/W1.23H2.74Y2.91_bem_slot_prediction_20000_0.25_15.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/model_predictions/W1.23H2.74Y3.89_bem_slot_prediction_20000_0.25_15.csv b/packaged-code/thesis/chapter 3/figure_plots/model_predictions/W1.23H2.74Y3.89_bem_slot_prediction_20000_0.25_15.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/model_predictions/W1.23H2.74Y3.89_bem_slot_prediction_20000_0.25_15.csv rename to packaged-code/thesis/chapter 3/figure_plots/model_predictions/W1.23H2.74Y3.89_bem_slot_prediction_20000_0.25_15.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.14H8.21Y1.66_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.14H8.21Y1.66_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.14H8.21Y1.66_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.14H8.21Y1.66_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.14H8.21Y2.66_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.14H8.21Y2.66_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.14H8.21Y2.66_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.14H8.21Y2.66_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.20H11.50Y2.63_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.20H11.50Y2.63_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.20H11.50Y2.63_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.20H11.50Y2.63_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.70Y1.77_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.70Y1.77_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.70Y1.77_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.70Y1.77_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.70Y2.29_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.70Y2.29_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.70Y2.29_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.70Y2.29_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.70Y2.81_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.70Y2.81_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.70Y2.81_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.70Y2.81_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.70Y3.32_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.70Y3.32_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.70Y3.32_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.70Y3.32_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.70Y3.84_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.70Y3.84_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.70Y3.84_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.70Y3.84_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.90Y2.66_bem_slot_prediction_20000_0.25_8.csv b/packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.90Y2.66_bem_slot_prediction_20000_0.25_8.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.90Y2.66_bem_slot_prediction_20000_0.25_8.csv rename to packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.90Y2.66_bem_slot_prediction_20000_0.25_8.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.90Y3.68_bem_slot_prediction_20000_0.25_8.csv b/packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.90Y3.68_bem_slot_prediction_20000_0.25_8.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.90Y3.68_bem_slot_prediction_20000_0.25_8.csv rename to packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.20H2.90Y3.68_bem_slot_prediction_20000_0.25_8.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.20H5.40Y1.52_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.20H5.40Y1.52_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.20H5.40Y1.52_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.20H5.40Y1.52_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.20H5.40Y1.99_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.20H5.40Y1.99_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/model_predictions/W2.20H5.40Y1.99_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/thesis/chapter 3/figure_plots/model_predictions/W2.20H5.40Y1.99_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/model_predictions/W4.20H11.47Y2.43_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/thesis/chapter 3/figure_plots/model_predictions/W4.20H11.47Y2.43_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/model_predictions/W4.20H11.47Y2.43_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/thesis/chapter 3/figure_plots/model_predictions/W4.20H11.47Y2.43_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/model_predictions/W4.20H11.47Y3.43_bem_slot_prediction_20000_0.25_5.csv b/packaged-code/thesis/chapter 3/figure_plots/model_predictions/W4.20H11.47Y3.43_bem_slot_prediction_20000_0.25_5.csv similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/model_predictions/W4.20H11.47Y3.43_bem_slot_prediction_20000_0.25_5.csv rename to packaged-code/thesis/chapter 3/figure_plots/model_predictions/W4.20H11.47Y3.43_bem_slot_prediction_20000_0.25_5.csv diff --git a/paper_code/thesis/chapter 3/figure_plots/util/analyse_slot.py b/packaged-code/thesis/chapter 3/figure_plots/util/analyse_slot.py similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/util/analyse_slot.py rename to packaged-code/thesis/chapter 3/figure_plots/util/analyse_slot.py diff --git a/paper_code/thesis/chapter 3/figure_plots/util/analysis_utils.py b/packaged-code/thesis/chapter 3/figure_plots/util/analysis_utils.py similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/util/analysis_utils.py rename to packaged-code/thesis/chapter 3/figure_plots/util/analysis_utils.py diff --git a/paper_code/thesis/chapter 3/figure_plots/util/bem.py b/packaged-code/thesis/chapter 3/figure_plots/util/bem.py similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/util/bem.py rename to packaged-code/thesis/chapter 3/figure_plots/util/bem.py diff --git a/paper_code/thesis/chapter 3/figure_plots/util/config_utils.py b/packaged-code/thesis/chapter 3/figure_plots/util/config_utils.py similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/util/config_utils.py rename to packaged-code/thesis/chapter 3/figure_plots/util/config_utils.py diff --git a/paper_code/thesis/chapter 3/figure_plots/util/element_utils.py b/packaged-code/thesis/chapter 3/figure_plots/util/element_utils.py similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/util/element_utils.py rename to packaged-code/thesis/chapter 3/figure_plots/util/element_utils.py diff --git a/paper_code/thesis/chapter 3/figure_plots/util/elements.py b/packaged-code/thesis/chapter 3/figure_plots/util/elements.py similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/util/elements.py rename to packaged-code/thesis/chapter 3/figure_plots/util/elements.py diff --git a/paper_code/thesis/chapter 3/figure_plots/util/file_utils.py b/packaged-code/thesis/chapter 3/figure_plots/util/file_utils.py similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/util/file_utils.py rename to packaged-code/thesis/chapter 3/figure_plots/util/file_utils.py diff --git a/paper_code/thesis/chapter 3/figure_plots/util/gen_utils.py b/packaged-code/thesis/chapter 3/figure_plots/util/gen_utils.py similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/util/gen_utils.py rename to packaged-code/thesis/chapter 3/figure_plots/util/gen_utils.py diff --git a/paper_code/thesis/chapter 3/figure_plots/util/plotting_utils.py b/packaged-code/thesis/chapter 3/figure_plots/util/plotting_utils.py similarity index 100% rename from paper_code/thesis/chapter 3/figure_plots/util/plotting_utils.py rename to packaged-code/thesis/chapter 3/figure_plots/util/plotting_utils.py diff --git a/paper_code/thesis/chapter 4/util/vector_utils.py b/packaged-code/thesis/chapter 3/figure_plots/util/vector_utils.py similarity index 100% rename from paper_code/thesis/chapter 4/util/vector_utils.py rename to packaged-code/thesis/chapter 3/figure_plots/util/vector_utils.py diff --git a/paper_code/thesis/chapter 4/figure1.py b/packaged-code/thesis/chapter 4/figure1.py similarity index 100% rename from paper_code/thesis/chapter 4/figure1.py rename to packaged-code/thesis/chapter 4/figure1.py diff --git a/paper_code/thesis/chapter 4/figure2.py b/packaged-code/thesis/chapter 4/figure2.py similarity index 100% rename from paper_code/thesis/chapter 4/figure2.py rename to packaged-code/thesis/chapter 4/figure2.py diff --git a/paper_code/thesis/chapter 4/figure3.py b/packaged-code/thesis/chapter 4/figure3.py similarity index 100% rename from paper_code/thesis/chapter 4/figure3.py rename to packaged-code/thesis/chapter 4/figure3.py diff --git a/paper_code/thesis/chapter 4/figure4.py b/packaged-code/thesis/chapter 4/figure4.py similarity index 100% rename from paper_code/thesis/chapter 4/figure4.py rename to packaged-code/thesis/chapter 4/figure4.py diff --git a/paper_code/thesis/chapter 4/figure5.py b/packaged-code/thesis/chapter 4/figure5.py similarity index 100% rename from paper_code/thesis/chapter 4/figure5.py rename to packaged-code/thesis/chapter 4/figure5.py diff --git a/paper_code/thesis/chapter 4/figure6and7.py b/packaged-code/thesis/chapter 4/figure6and7.py similarity index 100% rename from paper_code/thesis/chapter 4/figure6and7.py rename to packaged-code/thesis/chapter 4/figure6and7.py diff --git a/paper_code/thesis/chapter 4/model_bem_flat_plate_experiment.py b/packaged-code/thesis/chapter 4/model_bem_flat_plate_experiment.py similarity index 100% rename from paper_code/thesis/chapter 4/model_bem_flat_plate_experiment.py rename to packaged-code/thesis/chapter 4/model_bem_flat_plate_experiment.py diff --git a/paper_code/thesis/chapter 4/model_bem_slot_experiment.py b/packaged-code/thesis/chapter 4/model_bem_slot_experiment.py similarity index 100% rename from paper_code/thesis/chapter 4/model_bem_slot_experiment.py rename to packaged-code/thesis/chapter 4/model_bem_slot_experiment.py diff --git a/paper_code/thesis/chapter 4/model_data/corner_anisotropy_data/R1.0_L20_n50000_cn3 b/packaged-code/thesis/chapter 4/model_data/corner_anisotropy_data/R1.0_L20_n50000_cn3 similarity index 100% rename from paper_code/thesis/chapter 4/model_data/corner_anisotropy_data/R1.0_L20_n50000_cn3 rename to packaged-code/thesis/chapter 4/model_data/corner_anisotropy_data/R1.0_L20_n50000_cn3 diff --git a/paper_code/thesis/chapter 4/model_data/corner_anisotropy_sweep.py b/packaged-code/thesis/chapter 4/model_data/corner_anisotropy_sweep.py similarity index 100% rename from paper_code/thesis/chapter 4/model_data/corner_anisotropy_sweep.py rename to packaged-code/thesis/chapter 4/model_data/corner_anisotropy_sweep.py diff --git a/paper_code/thesis/chapter 4/model_data/slot_anisotropy_data/anisotropy_sweep_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0_N33.csv b/packaged-code/thesis/chapter 4/model_data/slot_anisotropy_data/anisotropy_sweep_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0_N33.csv similarity index 100% rename from paper_code/thesis/chapter 4/model_data/slot_anisotropy_data/anisotropy_sweep_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0_N33.csv rename to packaged-code/thesis/chapter 4/model_data/slot_anisotropy_data/anisotropy_sweep_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0_N33.csv diff --git a/paper_code/thesis/chapter 4/model_data/slot_anisotropy_data/centroids_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0.csv b/packaged-code/thesis/chapter 4/model_data/slot_anisotropy_data/centroids_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0.csv similarity index 100% rename from paper_code/thesis/chapter 4/model_data/slot_anisotropy_data/centroids_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0.csv rename to packaged-code/thesis/chapter 4/model_data/slot_anisotropy_data/centroids_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0.csv diff --git a/paper_code/thesis/chapter 4/model_data/slot_anisotropy_data/normals_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0.csv b/packaged-code/thesis/chapter 4/model_data/slot_anisotropy_data/normals_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0.csv similarity index 100% rename from paper_code/thesis/chapter 4/model_data/slot_anisotropy_data/normals_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0.csv rename to packaged-code/thesis/chapter 4/model_data/slot_anisotropy_data/normals_n23000_W4.00_H4.00_drat0.1_wthresh12.00_len100.0.csv diff --git a/paper_code/thesis/chapter 4/model_data/slot_anisotropy_sweep.py b/packaged-code/thesis/chapter 4/model_data/slot_anisotropy_sweep.py similarity index 100% rename from paper_code/thesis/chapter 4/model_data/slot_anisotropy_sweep.py rename to packaged-code/thesis/chapter 4/model_data/slot_anisotropy_sweep.py diff --git a/paper_code/thesis/chapter 4/model_data/square_anisotropy_data/R1.0_L15_n20000_i32 b/packaged-code/thesis/chapter 4/model_data/square_anisotropy_data/R1.0_L15_n20000_i32 similarity index 100% rename from paper_code/thesis/chapter 4/model_data/square_anisotropy_data/R1.0_L15_n20000_i32 rename to packaged-code/thesis/chapter 4/model_data/square_anisotropy_data/R1.0_L15_n20000_i32 diff --git a/paper_code/thesis/chapter 4/model_data/square_anisotropy_sweep.py b/packaged-code/thesis/chapter 4/model_data/square_anisotropy_sweep.py similarity index 100% rename from paper_code/thesis/chapter 4/model_data/square_anisotropy_sweep.py rename to packaged-code/thesis/chapter 4/model_data/square_anisotropy_sweep.py diff --git a/paper_code/thesis/chapter 4/model_data/triangle_anisotropy_data/R1.0_L15_n20000_i32 b/packaged-code/thesis/chapter 4/model_data/triangle_anisotropy_data/R1.0_L15_n20000_i32 similarity index 100% rename from paper_code/thesis/chapter 4/model_data/triangle_anisotropy_data/R1.0_L15_n20000_i32 rename to packaged-code/thesis/chapter 4/model_data/triangle_anisotropy_data/R1.0_L15_n20000_i32 diff --git a/paper_code/thesis/chapter 4/model_data/triangle_anisotropy_sweep.py b/packaged-code/thesis/chapter 4/model_data/triangle_anisotropy_sweep.py similarity index 100% rename from paper_code/thesis/chapter 4/model_data/triangle_anisotropy_sweep.py rename to packaged-code/thesis/chapter 4/model_data/triangle_anisotropy_sweep.py diff --git a/paper_code/thesis/chapter 4/model_sa_corner_experiment.py b/packaged-code/thesis/chapter 4/model_sa_corner_experiment.py similarity index 100% rename from paper_code/thesis/chapter 4/model_sa_corner_experiment.py rename to packaged-code/thesis/chapter 4/model_sa_corner_experiment.py diff --git a/paper_code/thesis/chapter 4/model_sa_equi_triangle_experiment.py b/packaged-code/thesis/chapter 4/model_sa_equi_triangle_experiment.py similarity index 100% rename from paper_code/thesis/chapter 4/model_sa_equi_triangle_experiment.py rename to packaged-code/thesis/chapter 4/model_sa_equi_triangle_experiment.py diff --git a/paper_code/thesis/chapter 4/model_sa_square_experiment.py b/packaged-code/thesis/chapter 4/model_sa_square_experiment.py similarity index 100% rename from paper_code/thesis/chapter 4/model_sa_square_experiment.py rename to packaged-code/thesis/chapter 4/model_sa_square_experiment.py diff --git a/paper_code/thesis/chapter 5/util/analysis_utils.py b/packaged-code/thesis/chapter 4/util/analysis_utils.py similarity index 100% rename from paper_code/thesis/chapter 5/util/analysis_utils.py rename to packaged-code/thesis/chapter 4/util/analysis_utils.py diff --git a/paper_code/thesis/chapter 4/util/bem.py b/packaged-code/thesis/chapter 4/util/bem.py similarity index 100% rename from paper_code/thesis/chapter 4/util/bem.py rename to packaged-code/thesis/chapter 4/util/bem.py diff --git a/paper_code/thesis/chapter 5/util/determineDisplacement.py b/packaged-code/thesis/chapter 4/util/determineDisplacement.py similarity index 100% rename from paper_code/thesis/chapter 5/util/determineDisplacement.py rename to packaged-code/thesis/chapter 4/util/determineDisplacement.py diff --git a/paper_code/thesis/chapter 5/util/file_utils.py b/packaged-code/thesis/chapter 4/util/file_utils.py similarity index 100% rename from paper_code/thesis/chapter 5/util/file_utils.py rename to packaged-code/thesis/chapter 4/util/file_utils.py diff --git a/paper_code/thesis/chapter 4/util/gen_utils.py b/packaged-code/thesis/chapter 4/util/gen_utils.py similarity index 100% rename from paper_code/thesis/chapter 4/util/gen_utils.py rename to packaged-code/thesis/chapter 4/util/gen_utils.py diff --git a/paper_code/thesis/chapter 4/util/moi_utils.py b/packaged-code/thesis/chapter 4/util/moi_utils.py similarity index 100% rename from paper_code/thesis/chapter 4/util/moi_utils.py rename to packaged-code/thesis/chapter 4/util/moi_utils.py diff --git a/paper_code/thesis/chapter 5/util/mp4.py b/packaged-code/thesis/chapter 4/util/mp4.py similarity index 100% rename from paper_code/thesis/chapter 5/util/mp4.py rename to packaged-code/thesis/chapter 4/util/mp4.py diff --git a/paper_code/thesis/chapter 5/util/mraw.py b/packaged-code/thesis/chapter 4/util/mraw.py similarity index 100% rename from paper_code/thesis/chapter 5/util/mraw.py rename to packaged-code/thesis/chapter 4/util/mraw.py diff --git a/paper_code/thesis/chapter 5/util/plotting_utils.py b/packaged-code/thesis/chapter 4/util/plotting_utils.py similarity index 100% rename from paper_code/thesis/chapter 5/util/plotting_utils.py rename to packaged-code/thesis/chapter 4/util/plotting_utils.py diff --git a/packaged-code/thesis/chapter 4/util/vector_utils.py b/packaged-code/thesis/chapter 4/util/vector_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..77321384ab59d321c85d2bb1247548dac2201eb8 --- /dev/null +++ b/packaged-code/thesis/chapter 4/util/vector_utils.py @@ -0,0 +1,57 @@ +def mag(v): + if len(v) == 2: + return (v[0] ** 2 + v[1] ** 2) ** 0.5 + + if len(v) == 3: + return (v[0] ** 2 + v[1] ** 2 + v[2] ** 2) ** 0.5 + + +def unit(v): + m = mag(v) + if len(v) == 2: + return [v[0] / m, v[1] / m] + + if len(v) == 3: + return [v[0] / m, v[1] / m, v[2] / m] + + +def mag_sqrd(v): + if len(v) == 2: + return v[0] ** 2 + v[1] ** 2 + + if len(v) == 3: + return v[0] ** 2 + v[1] ** 2 + v[2] ** 2 + + +def dist(v1, v2): + if len(v1) != len(v2): + raise ValueError("Vector lengths do not match (v1: {0}, v2: {1}).".format(len(v1), len(v2))) + + if len(v1) == 2: + return mag([v2[0] - v1[0], v2[1] - v1[1]]) + + if len(v1) == 3: + return mag([v2[0] - v1[0], v2[1] - v1[1], v2[2] - v1[2]]) + + +def get_line_intersect(pos, vect, l_a, l_b): + """ + Calculates the intersect (if any) between a line and a vector from a point. + :param pos: Position from which to trace. + :param vect: Vector along which to trace. + :param l_a: Point a of the line. + :param l_b: Point b of the line. + :return: Position (x, y) of the intersect or None + """ + # Intersect = pos + zeta * vect + zeta = (((pos[0] - l_a[0]) * (l_b[1] - l_a[1])) - (pos[1] - l_a[1]) * (l_b[0] - l_a[0])) / ( + vect[1] * (l_b[0] - l_a[0]) - vect[0] * (l_b[1] - l_a[1])) + + # Intersect = l_a + kappa * l_b + kappa = (vect[0] * (l_a[1] - pos[1]) - vect[1] * (l_a[0] - pos[0])) / ( + vect[1] * (l_b[0] - l_a[0]) - vect[0] * (l_b[1] - l_a[1])) + + if zeta >= 0 and 0 <= kappa <= 1: + return [pos[0] + zeta * vect[0], pos[1] + zeta * vect[1]] + else: + return None diff --git a/paper_code/thesis/chapter 5/fig_data/complex_geometry_anisotropy_data.csv b/packaged-code/thesis/chapter 5/fig_data/complex_geometry_anisotropy_data.csv similarity index 100% rename from paper_code/thesis/chapter 5/fig_data/complex_geometry_anisotropy_data.csv rename to packaged-code/thesis/chapter 5/fig_data/complex_geometry_anisotropy_data.csv diff --git a/paper_code/thesis/chapter 5/fig_data/surface_nucleation.mp4 b/packaged-code/thesis/chapter 5/fig_data/surface_nucleation.mp4 similarity index 100% rename from paper_code/thesis/chapter 5/fig_data/surface_nucleation.mp4 rename to packaged-code/thesis/chapter 5/fig_data/surface_nucleation.mp4 diff --git a/paper_code/thesis/chapter 5/figure10.py b/packaged-code/thesis/chapter 5/figure10.py similarity index 100% rename from paper_code/thesis/chapter 5/figure10.py rename to packaged-code/thesis/chapter 5/figure10.py diff --git a/paper_code/thesis/chapter 5/figure11.py b/packaged-code/thesis/chapter 5/figure11.py similarity index 100% rename from paper_code/thesis/chapter 5/figure11.py rename to packaged-code/thesis/chapter 5/figure11.py diff --git a/paper_code/thesis/chapter 5/figure12and13.py b/packaged-code/thesis/chapter 5/figure12and13.py similarity index 100% rename from paper_code/thesis/chapter 5/figure12and13.py rename to packaged-code/thesis/chapter 5/figure12and13.py diff --git a/paper_code/thesis/chapter 5/figure2.py b/packaged-code/thesis/chapter 5/figure2.py similarity index 100% rename from paper_code/thesis/chapter 5/figure2.py rename to packaged-code/thesis/chapter 5/figure2.py diff --git a/paper_code/thesis/chapter 5/figure3.py b/packaged-code/thesis/chapter 5/figure3.py similarity index 100% rename from paper_code/thesis/chapter 5/figure3.py rename to packaged-code/thesis/chapter 5/figure3.py diff --git a/paper_code/thesis/chapter 5/figure4.py b/packaged-code/thesis/chapter 5/figure4.py similarity index 100% rename from paper_code/thesis/chapter 5/figure4.py rename to packaged-code/thesis/chapter 5/figure4.py diff --git a/paper_code/thesis/chapter 5/figure5.py b/packaged-code/thesis/chapter 5/figure5.py similarity index 100% rename from paper_code/thesis/chapter 5/figure5.py rename to packaged-code/thesis/chapter 5/figure5.py diff --git a/paper_code/thesis/chapter 5/figure6.py b/packaged-code/thesis/chapter 5/figure6.py similarity index 100% rename from paper_code/thesis/chapter 5/figure6.py rename to packaged-code/thesis/chapter 5/figure6.py diff --git a/paper_code/thesis/chapter 5/figure7.py b/packaged-code/thesis/chapter 5/figure7.py similarity index 100% rename from paper_code/thesis/chapter 5/figure7.py rename to packaged-code/thesis/chapter 5/figure7.py diff --git a/paper_code/thesis/chapter 5/figure8.py b/packaged-code/thesis/chapter 5/figure8.py similarity index 100% rename from paper_code/thesis/chapter 5/figure8.py rename to packaged-code/thesis/chapter 5/figure8.py diff --git a/paper_code/thesis/chapter 5/steel_porous_plate_anisotropy.py b/packaged-code/thesis/chapter 5/steel_porous_plate_anisotropy.py similarity index 100% rename from paper_code/thesis/chapter 5/steel_porous_plate_anisotropy.py rename to packaged-code/thesis/chapter 5/steel_porous_plate_anisotropy.py diff --git a/packaged-code/thesis/chapter 5/util/analysis_utils.py b/packaged-code/thesis/chapter 5/util/analysis_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..73d3481d99ab57e73392dda3f6a5d8be8fc3a75d --- /dev/null +++ b/packaged-code/thesis/chapter 5/util/analysis_utils.py @@ -0,0 +1,641 @@ +""" +This code is based on code by Ivo Peters. The original code can be found in util/determineDisplacement. + +TODO: +- Improve error detection. + -> Void fraction? (of both frames) + -> Frames too far along (>50?) +- Improve handling of sideways measurements (separate analysis from processing i.e. just x, y, z, idx, vectors etc.) +""" +import os +from typing import List +import sys +import importlib + +import matplotlib.pyplot as plt +import numpy as np +from skimage.measure import label, regionprops +from scipy.interpolate import interp1d + +import util.determineDisplacement as dd +import util.file_utils as file +from util.mp4 import MP4 + + +class Reading: + m_x, m_y, m_z = None, None, None # Measurement coordinates + idx = None + repeat_number = None + + disp_vect = None # Bubble displacement vector (pixels) + sup_disp_vect = None # Displacement vector between minima as in Supponen et al. (2016) + bubble_pos = None # Bubble position in the frame (px coords) + max_bubble_area = None # Maximum bubble area (pixels) + sec_max_area = None # Second maximum of bubble area (pixels) + inter_max_frames = None # Time between + ecc_at_max = None # Eccentricity at maximum area + model_anisotropy = None # Anisotropy vector generated from BEM model + + def __init__(self, idx, repeat_number, m_x=None, m_y=None, m_z=None): + self.idx = idx + self.repeat_number = repeat_number + self.m_x = m_x + self.m_y = m_y + self.m_z = m_z + + def __str__(self): + string = f"{self.idx}:{self.repeat_number},{self.m_x},{self.m_y},{self.m_z}," \ + f"{self.disp_vect[0]},{self.disp_vect[1]}," \ + f"{self.bubble_pos[0]},{self.bubble_pos[1]}," \ + f"{self.max_bubble_area},{self.sec_max_area},{self.inter_max_frames}," \ + f"{self.sup_disp_vect[0]},{self.sup_disp_vect[1]}," \ + f"{self.ecc_at_max}" + if self.model_anisotropy is not None: # Only include anisotropy if available + string += f",{self.model_anisotropy[0]},{self.model_anisotropy[1]},{self.model_anisotropy[2]}" + return string + + def get_bubble_pos_mm(self, mm_per_px, frame_height=264): + return np.array([self.bubble_pos[0] * mm_per_px + self.m_x, + (frame_height - self.bubble_pos[1]) * mm_per_px + self.m_y]) + + def is_complete(self): + return self.disp_vect and self.bubble_pos and self.max_bubble_area \ + and self.sec_max_area and self.inter_max_frames + + def get_jet_angle(self): + return np.arctan2(-self.disp_vect[1], self.disp_vect[0]) + np.pi / 2 + + def get_angle_dif(self): + """ Computes the angle difference between the experimental measurement and the predicted anisotropy. """ + if self.model_anisotropy is not None: + # mm_per_px scaling doesn't matter here, just using this function to get the right direction conventions + return np.arccos(np.dot(self.get_disp_mm(1), self.model_anisotropy) / + (np.linalg.norm(self.get_disp_mm(1)) * np.linalg.norm(self.model_anisotropy))) + + def get_normalised_displacement(self): + return self.disp_vect / np.sqrt(self.max_bubble_area / np.pi) + + def get_disp_mm(self, mm_per_px): + return np.array([self.disp_vect[0] * mm_per_px, - self.disp_vect[1] * mm_per_px, 0]) + + def get_radius_ratio(self): + return np.sqrt(self.sec_max_area / self.max_bubble_area) + + def get_max_radius(self, mm_per_px): + return mm_per_px * np.sqrt(self.max_bubble_area / np.pi) + + def get_scalar_anisotropy(self): + if self.model_anisotropy is not None: + return np.linalg.norm(self.model_anisotropy) + + @staticmethod + def from_str(string: str): + """ Deserializes and returns a Reading object. """ + string = string.strip() + split = string.split(",") + if split[1] == "None": + x = None + else: + x = float(split[1]) + if split[2] == "None": + y = None + else: + y = float(split[2]) + if split[3] == "None": + z = None + else: + z = float(split[3]) + reading = Reading(int(split[0].split(":")[0]), int(split[0].split(":")[1]), x, y, z) + reading.disp_vect = np.array([float(split[4]), float(split[5])]) + reading.bubble_pos = np.array([float(split[6]), float(split[7])]) + reading.max_bubble_area = np.array(int(split[8])) + if len(split) > 9: # Only include newer metrics if available + reading.sec_max_area = np.array(int(split[9])) + reading.inter_max_frames = np.array(int(split[10])) + if len(split) > 11: # Only include even newer metrics if available + reading.sup_disp_vect = np.array([float(split[11]), float(split[12])]) + if len(split) > 13: # Only include even even newer metric (eccentricity) if available + reading.ecc_at_max = np.array(float(split[13])) + if len(split) > 14: # Only include blah blah blah (anisotropy vector) + reading.model_anisotropy = np.array([float(split[14]), float(split[15]), float(split[16])]) + return reading + + +def load_readings(filename, include_invalid=False, do_flag_invalid=True): + if do_flag_invalid: + flag_invalid_readings(filename.rpartition("/")[0] + "/") + dump_file = open(filename) + lines = dump_file.readlines() + + readings = [] + + for line in lines[1:]: + if line[0] == "#" and not include_invalid: + continue + if line[0] == "#": + line = line[1:] + readings.append(Reading.from_str(line)) + + dump_file.close() + + return readings + + +def save_readings(dir_path, readings): + if os.path.exists(dir_path + "readings_dump.csv"): + bkp_num = 0 + while os.path.exists(dir_path + f"readings_dump.csv.bkp.{bkp_num}"): + bkp_num += 1 + os.rename(dir_path + "readings_dump.csv", dir_path + f"readings_dump.csv.bkp.{bkp_num}") + + dump_file = open(dir_path + "readings_dump.csv", "a") + dump_file.write("index:repeat number, measured x (mm), measured y (mm), measured z (mm), " + "peak-to-peak x displacement (px), peak-to-peak y displacement (px), " + "in-frame bubble position x (px), in-frame bubble position y (px), " + "maximum bubble area (px^2), second maximum of bubble area (px^2), frames between maxima, " + "minimum-to-minimum x displacement (px), minimum-to-minimum y displacement (px)," + "eccentricity at maximum size," + "model anisotropy x, model anisotropy y, model anisotropy z\n") + + for reading in readings: + dump_file.write(str(reading) + "\n") + + dump_file.close() + + +def plot_analysis(areas, xs, ys, dx, dy, ns, path, frames, frame_rate, repeat_number=0, show_plot=False): + areas = np.array(areas) + xs = np.array(xs) + ys = np.array(ys) + ns = np.array(ns) + + # calculate time (s) + t = ns / frame_rate + + # close the previous plot + plt.close() + # find and plot peaks + plt.figure() + plt.subplot(2, 3, 3) + plt.plot(1000 * t, areas) + plt.scatter(1000 * t, areas, c="red", s=1) + plt.xlabel('t (ms)') + plt.ylabel('area (sq. pix.)') + peak_idxs, yPeak = dd.findPeaks(ns, areas, kernel=4) + idx = ns[peak_idxs] + plt.plot(1000 * t[peak_idxs], yPeak, 'o') + + # plot raw images + if len(idx) > 0: + plt.subplot(2, 3, 1) + plt.imshow(frames[idx[0]], cmap=plt.cm.gray) + plt.plot(xs[peak_idxs[0]], ys[peak_idxs[0]], 'x') + plt.xticks([]) + plt.yticks([]) + plt.title("Frame {0}".format(idx[0])) + if len(idx) > 1: + plt.subplot(2, 3, 4) + plt.imshow(frames[idx[1]], cmap=plt.cm.gray) + plt.plot(xs[peak_idxs[1]], ys[peak_idxs[1]], 'x') + plt.xticks([]) + plt.yticks([]) + plt.title("Frame {0}".format(idx[1])) + + # plot binary processed bubble images + if len(idx) > 0: + plt.subplot(2, 3, 2) + binary1 = dd.makeBinary(frames[0] - np.int32(frames[idx[0]])) + plt.imshow(binary1, cmap=plt.cm.gray) + plt.xticks([]) + plt.yticks([]) + if len(idx) > 1: + plt.subplot(2, 3, 5) + binary2 = dd.makeBinary(frames[0] - np.int32(frames[idx[1]])) + plt.imshow(binary2, cmap=plt.cm.gray) + plt.xticks([]) + plt.yticks([]) + + # calculate and plot displacement on background image + if len(idx) > 1: + plt.subplot(2, 3, 6) + plt.imshow(frames[0], cmap=plt.cm.gray) + plt.plot(xs[peak_idxs[0]:peak_idxs[1] + 1], ys[peak_idxs[0]:peak_idxs[1] + 1], 'x') + + plt.quiver(xs[peak_idxs[0]], ys[peak_idxs[0]], dx, -dy, + scale_units='x', + scale=0.33, + width=0.02) + + plt.tight_layout() + if show_plot: + plt.show() + + # save figure for checking proper working of algorithms + plt.savefig(path + "analysis_plot_r{0}.png".format(repeat_number), dpi=150) + + +def analyse_frame(frame, bg_frame, max_ecc=0.6, min_sol=0.9, debug=False): + """ + Analyses a single frame to find the coordinates and area of the bubble region. Additional parameters returned if + debug is True. + + :param frame: Image frame. + :param bg_frame: Background image frame. + :return: x, y, area, [eccentricity, solidity] + """ + x, y, area, ecc, sol, jt = None, None, None, None, None, None + + img = np.int32(bg_frame) - np.int32(frame) + binary = dd.makeBinary(img) + label_img = label(binary) + props = regionprops(label_img, cache=False) + + if len(props) > 0: + if len(props) > 1: + max_area = 0.0 + for j in range(len(props)): + if props[j].area > max_area: + max_area = props[j].area + max_idx = j + y, x = props[max_idx].centroid + area = props[max_idx].area + ecc = props[max_idx].eccentricity + sol = props[max_idx].solidity + + coords = np.array(props[max_idx].coords) + dists = np.linalg.norm(np.subtract(coords, [y, x]), axis=1) + max_dist_idx = np.argmax(dists) + jt = coords[max_dist_idx] # np.arctan2(coords[max_dist_idx][1] - y, coords[max_dist_idx][0] - x) + + if props[max_idx].eccentricity > max_ecc or props[max_idx].solidity < min_sol: + area = None + else: + y, x = props[0].centroid + area = props[0].area + ecc = props[0].eccentricity + sol = props[0].solidity + + coords = np.array(props[0].coords) + dists = np.linalg.norm(np.subtract(coords, [y, x]), axis=1) + max_dist_idx = np.argmax(dists) + jt = coords[max_dist_idx] # np.arctan2(coords[max_dist_idx][1] - y, coords[max_dist_idx][0] - x) + + if props[0].eccentricity > max_ecc or props[0].solidity < min_sol: + area = None + + if not debug: + return x, y, area + else: + if jt is not None: + jet_tip = (jt[1], jt[0]) + else: + jet_tip = None + return x, y, area, ecc, sol, jet_tip + + +def estimate_supponen_disp(areas, idxs, frame_rate, xs, ys): + time_per_frame = 1 / frame_rate + times = np.array(idxs) * time_per_frame + + gradients = np.abs((areas[1:] - areas[:-1]) / (times[1:] - times[:-1])) + grad_change_of_sign = np.sign(gradients[1:] - gradients[:-1]) + abs_d_grad_cos = np.abs(grad_change_of_sign[1:] - grad_change_of_sign[:-1]) + + min_grad_idx = None + for i in range(len(abs_d_grad_cos)): + if all(abs_d_grad_cos[i:i + 3] == 2): + min_grad_idx = i + 2 + break + + if min_grad_idx is None: # TODO: Properly analyse these failures + return 0, 0 + + first_collapse_end_idx = min_grad_idx + scnd_collapse_start_idx = min_grad_idx + 1 + + try: + coeffs1 = np.polyfit(times[:first_collapse_end_idx + 1], areas[:first_collapse_end_idx + 1], 2) + coeffs2 = np.polyfit(times[scnd_collapse_start_idx:-1], areas[scnd_collapse_start_idx:-1], 2) + intersection = np.roots(coeffs1 - coeffs2) + interp_x = interp1d(times, xs - xs[0], "linear")(intersection[-1]) + interp_y = interp1d(times, ys - ys[0], "linear")(intersection[-1]) + except: + return 0, 0 + + return interp_x, interp_y + + +def calculate_displacement(frames, frame_rate, trigger_out_delay, save_path=None, repeat_num=0, laser_delay=100e-6, + warn=False): + """ + Calculate bubble displacement vector for a series of frames. + :param frames: Frames + :param frame_rate: Frame rate (fps) + :param trigger_out_delay: Camera trigger out delay + :param save_path: Path in which to save the analysis plot, if None does not save. + :param repeat_num: Number of the repeat, used to save the analysis plot for movies with multiple repeats. + :param laser_delay: Laser delay + :return: displacement vector [x, y], initial bubble centroid [x, y], max area, second max area, inter-max frames, + Supponen displacement vector [x, y] + """ + xs = [] + ys = [] + areas = [] + eccs = [] + idxs = [] + + bg_frame = np.int32(frames[0]) + + total_laser_delay = laser_delay + trigger_out_delay # determine total delay in firing the laser + laser_frame_idx = int(round(frame_rate * total_laser_delay)) # delay in frames + first_frame_idx = laser_frame_idx + 1 # first frame we will analyse + + for idx in range(first_frame_idx, len(frames)): + x, y, area, ecc, sol, _ = analyse_frame(frames[idx], bg_frame, debug=True) + if area is None: + continue # No bubble found. + xs.append(x) + ys.append(y) + areas.append(area) + idxs.append(idx) + eccs.append(ecc) + + xs = np.array(xs) + ys = np.array(ys) + areas = np.array(areas) + idxs = np.array(idxs) + + peak_idxs, peak_areas = dd.findPeaks(idxs, areas, kernel=4) + + if len(peak_idxs) > 1: + dx = xs[peak_idxs[1]] - xs[peak_idxs[0]] + dy = ys[peak_idxs[1]] - ys[peak_idxs[0]] + + sup_dx, sup_dy = estimate_supponen_disp(areas, idxs, frame_rate, xs, ys) + + if save_path is not None: + plot_analysis(areas, xs, ys, dx, dy, idxs, save_path, frames, frame_rate, repeat_number=repeat_num) + + return [dx, dy], [xs[peak_idxs[0]], ys[peak_idxs[0]]], areas[peak_idxs[0]], areas[peak_idxs[1]], \ + peak_idxs[1] - peak_idxs[0], [sup_dx, sup_dy], eccs[peak_idxs[0]] + else: + if save_path is not None: + plot_analysis(areas, xs, ys, 0, 0, idxs, save_path, frames, frame_rate, repeat_number=repeat_num) + if warn: + print("Warning: Less than two area peaks found.") + return None + + +def analyse_reading(dir_path, return_mean=False, warn=False, short_status=False): + """ + Analyses a reading in specified file path. + + :param dir_path: Reading directory path. + :param return_mean: Whether to return the mean displacement or a list of displacements. + :return: mean displacement vector [x, y], mean bubble position vector [x, y] + """ + if not os.path.exists(dir_path): + if warn: + print("Warning: " + dir_path + " does not exist.") + return + + if not short_status: + print("Analysing " + dir_path) + movie = file.get_mraw_from_dir(dir_path) + if movie.image_count % 100 != 0: + if warn: + print("Warning: {0} does not have a multiple of 100 frames. Assuming single collapse.".format(dir_path)) + repeats = 1 + else: + repeats = int(movie.image_count / 100) + + frame_rate = movie.get_fps() + trigger_out_delay = movie.trigger_out_delay + + disps = [] + positions = [] + areas = [] + sec_areas = [] + inter_max_frames = [] + sup_disps = [] + eccs = [] + for i in range(repeats): + frames = list(movie[i * 100: (i + 1) * 100]) + disp_out = calculate_displacement(frames, frame_rate, trigger_out_delay, save_path=dir_path, repeat_num=i, + warn=warn) + + if disp_out is not None: + disp, pos, area, sec_area, imf, sup_disp, ecc_at_max = disp_out + disps.append(disp) + positions.append(pos) + areas.append(area) + sec_areas.append(sec_area) + inter_max_frames.append(imf) + sup_disps.append(sup_disp) + eccs.append(ecc_at_max) + else: + disps.append(None) + positions.append(None) + areas.append(None) + sec_areas.append(None) + inter_max_frames.append(None) + sup_disps.append(None) + eccs.append(None) + + movie.close() + + if short_status: + print("|", end="", flush=True) # TODO: Make this work + + if return_mean: + mean_disp = np.mean([d for d in disps if d is not None], axis=1) + mean_pos = np.mean([p for p in positions if p is not None], axis=1) + return mean_disp, mean_pos + else: + return disps, positions, areas, sec_areas, inter_max_frames, sup_disps, eccs + + +def analyse_series(dir_path, frame_shape=(384, 264), warn=False): + index_file = open(dir_path + "index.csv") + index_lines = index_file.readlines() + index_file.close() + + if os.path.exists(dir_path + "readings_dump.csv"): + bkp_num = 0 + while os.path.exists(dir_path + f"readings_dump.csv.bkp.{bkp_num}"): + bkp_num += 1 + os.rename(dir_path + "readings_dump.csv", dir_path + f"readings_dump.csv.bkp.{bkp_num}") + + for root, _, files in os.walk(dir_path): + for name in files: + if "analysis_plot" in name and ".png" in name: + os.remove(os.path.join(root, name)) + + dump_file = open(dir_path + "readings_dump.csv", "a") + dump_file.write("index:repeat number, measured x (mm), measured y (mm), measured z (mm), " + "peak-to-peak x displacement (px), peak-to-peak y displacement (px), " + "in-frame bubble position x (px), in-frame bubble position y (px), " + "maximum bubble area (px^2), second maximum of bubble area (px^2), frames between maxima, " + "minimum-to-minimum x displacement (px), minimum-to-minimum y displacement (px)," + "eccentricity at maximum size\n") + + sideways = False + # Identify system: + headers = index_lines[0].strip().split(",") + for i, h in enumerate(headers): + headers[i] = h.strip() + if headers[0][0] == "x" and headers[1][0] == "y" and headers[2] == "idx": + sideways = False + frame_height = frame_shape[1] + elif headers[0][0] == "x" and headers[1][0] == "z" and headers[2] == "idx": + sideways = True + frame_height = frame_shape[0] + else: + raise ValueError("Index file format was not recognized.") + + # At code end this is formatted: + # x, y, index, displacement vector, bubble position vector (px), bubble position vector (mm) + # readings = [] # type: List[List[Union[float, float, str, np.ndarray, np.ndarray, np.ndarray]]] + readings = [] # type: List[Reading] + + input_data = [] # x, y, index + + for i in range(1, len(index_lines)): # Start at 1 to skip header. + split = index_lines[i].strip().split(",") + if sideways: + # In sideways configuration the actual x is the measured -z, actual y is measured x. + input_data.append([-float(split[1]), float(split[0]), split[2]]) # x, y, idx converted from x, z, idx + pass + else: + input_data.append([float(split[0]), float(split[1]), split[2]]) # x, y, idx + + reading_prefix = file.get_prefix_from_idxs(dir_path, np.array(input_data)[:, 2]) + for i in range(len(input_data)): + reading_path = dir_path + reading_prefix + str(input_data[i][2]).rjust(4, "0") + "/" + to_write = 0 + + disps, positions, areas, sec_areas, inter_max_frames, sup_disps, eccs = analyse_reading(reading_path, False, + warn=warn) + for d in range(len(disps)): + reading = Reading(input_data[i][2], d, m_x=input_data[i][0], m_y=input_data[i][1]) + # reading = input_data[i].copy() + + if sideways and disps[d] is not None and positions[d] is not None: + # Rotate into correct orientation. + disps[d] = [disps[d][1], -disps[d][0]] + positions[d] = [positions[d][1], frame_height - positions[d][0]] + + reading.disp_vect = disps[d] + reading.bubble_pos = positions[d] + reading.max_bubble_area = areas[d] + reading.sec_max_area = sec_areas[d] + reading.inter_max_frames = inter_max_frames[d] + reading.sup_disp_vect = sup_disps[d] + reading.ecc_at_max = eccs[d] + + readings.append(reading) + to_write += 1 + + for j in range(1, to_write + 1): + reading = readings[-j] + if reading.is_complete(): + dump_file.write(str(reading) + "\n") + + dump_file.close() + + try: + flag_invalid_readings(dir_path) + except ValueError: + if warn: + print(f"Could not flag invalid readings in {dir_path}") + else: + pass + return readings + + +def flag_invalid_readings(dir_path, error_on_not_found=False): + r_path = dir_path + "readings_dump.csv" + i_path = dir_path + "invalid_readings.txt" + if os.path.exists(i_path) and os.path.exists(r_path): + r_file = open(r_path, "r") + r_lines = r_file.readlines() + i_file = open(i_path, "r") + i_lines = i_file.readlines() + new_lines = [] + for r_line in r_lines: + flagged = False + for i_line in i_lines: + if r_line.split(",")[0] == i_line.strip() and r_line[0] != "#": + new_lines.append("#" + r_line) + flagged = True + break + if not flagged: + new_lines.append(r_line) + r_file.close() + i_file.close() + + r_file = open(r_path, "w") + r_file.writelines(new_lines) + r_file.close() + elif error_on_not_found: + raise ValueError("Path does not contain the required files.") + + +def get_collapse_variations(dir_path, idx, repeat, laser_delay=151.0e-6, geometry_type=None): + reading_prefix = file.get_prefix_from_idxs(dir_path, [idx]) + reading_path = dir_path + reading_prefix + str(idx).rjust(4, "0") + "/" + + movie = MP4(reading_path + f"video_{repeat}.mp4") + + frame_rate = movie.get_fps() + trigger_out_delay = movie.trigger_out_delay + + frames = list(movie[:100]) + + xs = [] + ys = [] + areas = [] + eccs = [] + idxs = [] + + bg_frame = np.int32(frames[0]) + + total_laser_delay = laser_delay + trigger_out_delay # determine total delay in firing the laser + laser_frame_idx = int(round(frame_rate * total_laser_delay)) # delay in frames + first_frame_idx = laser_frame_idx + 1 # first frame we will analyse + + for idx in range(first_frame_idx, len(frames)): + x, y, area, ecc, sol, _ = analyse_frame(frames[idx], bg_frame, debug=True) + if area is None: + continue # No bubble found. + xs.append(x) + ys.append(y) + areas.append(area) + idxs.append(idx) + eccs.append(ecc) + + xs = np.array(xs) + ys = np.array(ys) + areas = np.array(areas) + idxs = np.array(idxs) + + sys.path.append(dir_path) + import params + + importlib.reload(params) + sys.path.remove(dir_path) + + if geometry_type == 'slot': + xs = xs - (params.left_slot_wall_x + params.slot_width / 2) + ys = ys - params.upper_surface_y + + xs = xs * params.mm_per_px + ys = ys * params.mm_per_px + radii = np.sqrt(areas / np.pi) * params.mm_per_px + ts = idxs / frame_rate + + return xs, ys, radii, ts + + +if __name__ == "__main__": + flag_invalid_readings(file.select_dir("../../../../../")) diff --git a/paper_code/thesis/chapter 5/util/bem.py b/packaged-code/thesis/chapter 5/util/bem.py similarity index 100% rename from paper_code/thesis/chapter 5/util/bem.py rename to packaged-code/thesis/chapter 5/util/bem.py diff --git a/packaged-code/thesis/chapter 5/util/determineDisplacement.py b/packaged-code/thesis/chapter 5/util/determineDisplacement.py new file mode 100644 index 0000000000000000000000000000000000000000..0b3a936e3c7e1e65612a6f5a6a19a147e66c983c --- /dev/null +++ b/packaged-code/thesis/chapter 5/util/determineDisplacement.py @@ -0,0 +1,69 @@ +# -*- coding: utf-8 -*- +""" +Created on Sat May 6 20:43:51 2017 + +@author: Ivo Peters +ivo.r.peters@gmail.com + +version 1.5 + +Update version 1.2 (2017-12-07): + Added a catch in case only one peak is found for the bubble size. +Update version 1.3 (2017-12-10): + Reduced dpi of output images from 300 to 150. +Update version 1.4 (2018-03-29): + Added a catch in case the peak consists of two points with exactly the same + value. +Update version 1.5 (2018-04-08): + Fixed use of non-integer as index in findPeaks function. +""" + +import numpy as np +from skimage.filters import threshold_otsu +import skimage.morphology as morph +from scipy import ndimage + + +def findPeaks(x, y, n=2, kernel=5): + """ + Standard peak finding algorithm, finds the first n peaks using a kernel + of size kernel. + """ + peakIdx = [] # index of the peak + yPeak = [] # peak value + k = np.int((kernel - 1) / 2) + for i in range(len(x) - (kernel - 1)): + if np.max(y[i:i + kernel]) == y[i + k]: + # If this is the first peak that is found, then the peak is added + if len(peakIdx) < 1: + peakIdx.append(i + k) + yPeak.append(y[i + k]) + # Check if this is not a peak within the same range + elif (i + k - peakIdx[-1]) > k: + peakIdx.append(i + k) + yPeak.append(y[i + k]) + if len(peakIdx) == n: + break + return peakIdx, yPeak + + +def makeBinary(I): + """ + Turn a grayscale image into a binary image, trying to only keep the main + bubble as a uniform white object on a fully black background. + """ + # find a reasonable threshold + thresh = threshold_otsu(I) + # make a binary version of the image + binary = I > thresh + # try to separate small objects that are attached to the main bubble + morph.binary_opening(binary, footprint=None, out=binary) + # fill up holes to make the bright spot in the center of the bubble black + ndimage.binary_fill_holes(binary, output=binary) + # remove small objects (noise and object that we separated a few steps ago) + binary = morph.remove_small_objects(binary, min_size=128) + # return the binary image + return binary + + +laserDelay = 151.0e-6 # delay (s) for Q-switch after lamp was triggered (setting in laser) diff --git a/paper_code/thesis/chapter 5/util/drawing_utils.py b/packaged-code/thesis/chapter 5/util/drawing_utils.py similarity index 100% rename from paper_code/thesis/chapter 5/util/drawing_utils.py rename to packaged-code/thesis/chapter 5/util/drawing_utils.py diff --git a/packaged-code/thesis/chapter 5/util/file_utils.py b/packaged-code/thesis/chapter 5/util/file_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..1de6b12a44ed35649b74963c19d1b47546b7defd --- /dev/null +++ b/packaged-code/thesis/chapter 5/util/file_utils.py @@ -0,0 +1,118 @@ +import os +import re +from PyQt5.QtWidgets import QFileDialog, QApplication +import sys +import importlib +import numpy as np + +from util.mraw import mraw + + +def get_prefix_from_idxs(dir_path, idxs): + """ + Finds the prefix used in a directory for a series of indexes. e.g. movie0001 vs movie_S0001. + :param dir_path: Directory path. + :param idxs: Array of indexes to check. + :return: Prefix. + """ + files = os.listdir(dir_path) + + prefix = None + for idx in idxs: + for file in files: + if os.path.isdir(dir_path + file): + suffix = str(idx).rjust(4, '0') + match = re.match(r'(.*)' + suffix, file) + if match: + file_prefix = match.group(1) + if prefix is None: + prefix = file_prefix + else: + if prefix != file_prefix: + print("Warning: Multiple directory prefixes found. Only using {0}".format(prefix)) + return prefix + + +def get_mraw_from_dir(dir_path): + files = os.listdir(dir_path) + headers = [] + for file in files: + if re.match(r'(.*\.cih)', file): + headers.append(file) + + if len(headers) > 1: + print("Warning: Multiple headers found. Using {0}".format(headers[0])) + if len(headers) == 0: + print("Warning: No headers found in {0}".format(dir_path)) + return None + + return mraw(dir_path + headers[0]) + + +def select_dir(start_path="../../../../../", create_window=True): + if create_window: + window = QApplication([]) + dir_path = str(QFileDialog.getExistingDirectory(None, "Select Directory", start_path)) + "/" + return dir_path + + +def load_params(params_dir): + sys.path.append(params_dir) + import params + + importlib.reload(params) + sys.path.remove(params_dir) + return params + +def lists_to_csv(file_dir, filename, lists, headers=None, overwrite=False): + """ + Writes a list of lists to a CSV file where each list is a column + :param file_dir: The directory in which to save the CSV file. + :param filename: The name of the CSV file (including file extension). + :param lists: The lists to save. + :param headers: A list of header strings, one for each column, defaults to no headers. + :param overwrite: Whether to overwrite an existing file, defaults to false. + :return: Success of file write. + """ + if os.path.exists(file_dir + filename) and not overwrite: + print(f"Warning: file already exists. {file_dir + filename}") + return False + if file_dir != "": + os.makedirs(file_dir, exist_ok=True) + file = open(file_dir + filename, "w") + if headers: + line = "" + for h in headers: + line += h + "," + line = line[:-1] + "\n" + file.write(line) + zipped_lists = np.transpose(lists) + for entry in zipped_lists: + line = "" + for part in entry: + line += str(part) + "," + line = line[:-1] + "\n" + file.write(line) + file.close() + return True + + +def csv_to_lists(file_dir, filename, has_headers=False): + """ + Reads a CSV file to a list of lists where each column becomes a list. + :param file_dir: The directory from which to read the CSV file. + :param filename: The name of the CSV file (including file extension). + :param has_headers: Whether the CSV file has headers, defaults to False. + :return: List of lists. + """ + file = open(file_dir + filename, "r") + lines = file.readlines() + start_idx = 1 if has_headers else 0 + zipped_lists = [] + for line in lines[start_idx:]: + line = line.strip(',\n') + part_arr = [] + for part in line.split(","): + part_arr.append(float(part)) + zipped_lists.append(part_arr) + return np.transpose(zipped_lists) diff --git a/paper_code/thesis/chapter 5/util/gen_utils.py b/packaged-code/thesis/chapter 5/util/gen_utils.py similarity index 100% rename from paper_code/thesis/chapter 5/util/gen_utils.py rename to packaged-code/thesis/chapter 5/util/gen_utils.py diff --git a/packaged-code/thesis/chapter 5/util/mp4.py b/packaged-code/thesis/chapter 5/util/mp4.py new file mode 100644 index 0000000000000000000000000000000000000000..f6d84194c2af7c69caa458681e2caa60af8d81b8 --- /dev/null +++ b/packaged-code/thesis/chapter 5/util/mp4.py @@ -0,0 +1,45 @@ +import cv2 +import numpy as np + + +class MP4: + # Declared to allow IDE to find these properties automatically. + width, height, image_count = None, None, None + + # Hard code these for compatibility assuming that the movies are from MRAW data using the usual settings. + frame_rate = 100000 + trigger_out_delay = 100 * 100e-9 + + buf = None + + def __init__(self, fn): + cap = cv2.VideoCapture(fn) + self.image_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) + self.width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) + self.height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) + + self.buf = np.empty((self.image_count, self.height, self.width), np.dtype('uint8')) + + fc = 0 + ret = True + + while fc < self.image_count and ret: + self.buf[fc] = cv2.cvtColor(cap.read()[1], cv2.COLOR_BGR2GRAY) + fc += 1 + + cap.release() + + def __len__(self): + return self.image_count + + def __getitem__(self, key): + if type(key) == slice: + return map(self.get_frame, range(self.image_count)[key]) + + return self.get_frame(key) + + def get_frame(self, idx): + return self.buf[idx] + + def get_fps(self): + return self.frame_rate diff --git a/packaged-code/thesis/chapter 5/util/mraw.py b/packaged-code/thesis/chapter 5/util/mraw.py new file mode 100644 index 0000000000000000000000000000000000000000..8d79039347e8b448b941b584ddd3d73750e34e6f --- /dev/null +++ b/packaged-code/thesis/chapter 5/util/mraw.py @@ -0,0 +1,174 @@ +""" +Photron MRAW reader +Author: Ivo Peters (i.r.peters@soton.ac.uk) +Created on: 2016-10-26 +Last revision: 2016-10-27 +Version: 0.2 + +Chunks of code taken from: +CINE library: Dustin Kleckner (dkleckner@uchicago.edu) +pyMRAW.py: Jaka Javh (jaka.javh@fs.uni-lj.si) +""" + +from os import path +import numpy as np +import warnings +import xmltodict + +# Processing the data in chunks keeps it in the L2 catch of the processor, increasing speed for large arrays by ~50% +CHUNK_SIZE = 6 * 10 ** 5 # Should be divisible by 3, 4 and 5! This seems to be near-optimal. + +SUPPORTED_FILE_FORMATS = ['mraw', 'tiff'] +SUPPORTED_EFFECTIVE_BIT_SIDE = ['lower', 'higher'] + + +def read_cih(filename): + name, ext = path.splitext(filename) + if ext == '.cih': + cih = dict() + # read the cif header + with open(filename, 'r') as f: + for line in f: + if line == '\n': # end of cif header + break + line_sp = line.replace('\n', '').split(' : ') + if len(line_sp) == 2: + key, value = line_sp + try: + if '.' in value: + value = float(value) + else: + value = int(value) + cih[key] = value + except: + cih[key] = value + + elif ext == '.cihx': + with open(filename, 'r', encoding='utf-8', errors='ignore') as f: + lines = f.readlines() + first_last_line = [i for i in range(len(lines)) if '<cih>' in lines[i] or '</cih>' in lines[i]] + xml = ''.join(lines[first_last_line[0]:first_last_line[-1] + 1]) + + raw_cih_dict = xmltodict.parse(xml) + cih = { + 'Date': raw_cih_dict['cih']['fileInfo']['date'], + 'Camera Type': raw_cih_dict['cih']['deviceInfo']['deviceName'], + 'Record Rate(fps)': float(raw_cih_dict['cih']['recordInfo']['recordRate']), + 'Shutter Speed(s)': float(raw_cih_dict['cih']['recordInfo']['shutterSpeed']), + 'Total Frame': int(raw_cih_dict['cih']['frameInfo']['totalFrame']), + 'Original Total Frame': int(raw_cih_dict['cih']['frameInfo']['recordedFrame']), + 'Image Width': int(raw_cih_dict['cih']['imageDataInfo']['resolution']['width']), + 'Image Height': int(raw_cih_dict['cih']['imageDataInfo']['resolution']['height']), + 'File Format': raw_cih_dict['cih']['imageFileInfo']['fileFormat'], + 'EffectiveBit Depth': int(raw_cih_dict['cih']['imageDataInfo']['effectiveBit']['depth']), + 'EffectiveBit Side': raw_cih_dict['cih']['imageDataInfo']['effectiveBit']['side'], + 'Color Bit': int(raw_cih_dict['cih']['imageDataInfo']['colorInfo']['bit']), + 'Comment Text': raw_cih_dict['cih']['basicInfo'].get('comment', ''), + 'Signal Delay Trigger Out Width(nsec)': int( + raw_cih_dict['cih']['deviceInfo']['delayInfos']['delayInfo'][3]['value']) * 100 + # 4th signal is Trigger Out Width in 100ns units + } + + else: + raise Exception('Unsupported configuration file ({:s})!'.format(ext)) + + # check exceptions + # ff = cih['File Format'] + # if ff.lower() not in SUPPORTED_FILE_FORMATS: + # raise Exception('Unexpected File Format: {:g}.'.format(ff)) + # bits = cih['Color Bit'] + # if bits < 12: + # warnings.warn('Not 12bit ({:g} bits)! clipped values?'.format(bits)) + # - may cause overflow') + # 12-bit values are spaced over the 16bit resolution - in case of photron filming at 12bit + # this can be meanded by dividing images with //16 + # if cih['EffectiveBit Depth'] != 12: + # warnings.warn('Not 12bit image!') + # ebs = cih['EffectiveBit Side'] + # if ebs.lower() not in SUPPORTED_EFFECTIVE_BIT_SIDE: + # raise Exception('Unexpected EffectiveBit Side: {:g}'.format(ebs)) + # if (cih['File Format'].lower() == 'mraw') & (cih['Color Bit'] not in [8, 16]): + # raise Exception('pyMRAW only works for 8-bit and 16-bit files!') + # if cih['Original Total Frame'] > cih['Total Frame']: + # warnings.warn('Clipped footage! (Total frame: {}, Original total frame: {})'.format(cih['Total Frame'], cih[ + # 'Original Total Frame'])) + + return cih + + +def twelve2sixteen(a): + b = np.zeros(a.size // 3 * 2, dtype='u2') + + for j in range(0, len(a), CHUNK_SIZE): + (a0, a1, a2) = [a[j + i:j + CHUNK_SIZE:3].astype('u2') for i in range(3)] + + k = j // 3 * 2 + k2 = k + CHUNK_SIZE // 3 * 2 + + b[k + 0:k2:2] = ((a0 & 0xFF) << 4) + ((a1 & 0xF0) >> 4) + b[k + 1:k2:2] = ((a1 & 0x0F) << 8) + ((a2 & 0xFF) >> 0) + + return b + + +class mraw(object): + # Declared to allow IDE to find these properties automatically. + width, height, imageSize, image_count = None, None, None, None + + def __init__(self, fn): + cih = read_cih(fn) + self.cih = cih + + self.width = cih['Image Width'] + self.height = cih['Image Height'] + self.image_count = cih['Total Frame'] + self.bit_depth = cih['EffectiveBit Depth'] + self.frame_rate = float(cih[ + 'Record Rate(fps)']) # turn the frame rate into a float to avoid problems with creating unwanted integers by accident when using this property + self.trigger_out_delay = float(cih['Signal Delay Trigger Out Width(nsec)']) * 1e-9 + + # calculate the size of an image in bytes: + self.imageSize = self.width * self.height * self.bit_depth // 8 + + if fn[-4:] == '.cih': + self.fileName = fn[:-4] + '.mraw' + elif fn[-5:] == '.cihx': + self.fileName = fn[:-5] + '.mraw' + else: + raise ValueError("Input file is neither CIH or CIHX.") + self.f = open(self.fileName, 'rb') + + def __len__(self): + return self.image_count + + def __getitem__(self, key): + if type(key) == slice: + return map(self.get_frame, range(self.image_count)[key]) + + return self.get_frame(key) + + def get_fps(self): + return self.frame_rate + + def get_frame(self, number): + # calculate the position in bytes where the image is: + bytePosition = number * self.imageSize + # seek this position in the file: + self.f.seek(bytePosition) + # image = np.memmap(f, dtype=np.uint8, mode='r', shape=(self.width * self.height * 12 / 8)) + image = np.frombuffer(self.f.read(self.imageSize), np.uint8) + image = twelve2sixteen(image) + image = np.reshape(image, (self.height, self.width)) + return image + + def get_pixel_range(self): + """ Gets the pixel brightness range for the movie """ + # go to the start of the file + self.f.seek(0) + # read all the images + all_pixels = np.frombuffer(self.f.read(self.imageSize * self.image_count), np.uint8) + twelve2sixteen(all_pixels) + return np.min(all_pixels), np.max(all_pixels) + + def close(self): + self.f.close() diff --git a/packaged-code/thesis/chapter 5/util/plotting_utils.py b/packaged-code/thesis/chapter 5/util/plotting_utils.py new file mode 100644 index 0000000000000000000000000000000000000000..08dd8ba3d0b0878f515245487c3ea95b6d5f15cc --- /dev/null +++ b/packaged-code/thesis/chapter 5/util/plotting_utils.py @@ -0,0 +1,260 @@ +import matplotlib as mpl +import matplotlib.cm as cm +import matplotlib.pyplot as plt +import warnings +from matplotlib.pyplot import Axes +from matplotlib.axis import Axis +from matplotlib.colors import LinearSegmentedColormap +from matplotlib.ticker import StrMethodFormatter, LogLocator, AutoLocator, AutoMinorLocator +from mpl_toolkits.mplot3d import Axes3D +import seaborn as sns +import numpy as np + + +def fig_width(): + return 5.31445 + + +def plot_frame(frame, pos=None, show_immediately=True): + plt.figure() + plt.imshow(frame, cmap=plt.cm.gray) + if pos is not None: + plt.plot(pos[0], pos[1], 'rx') + plt.xticks([]) + plt.yticks([]) + if show_immediately: + plt.show() + + +def initialize_plt(font_size=10, line_scale=1, capsize=3, latex=True, dpi=300, colourblind=True): + warnings.filterwarnings("ignore", "cmr10") # STOP TELLING ME THIS PLEASE I KNOW WHAT FONT I WANT + if colourblind: + sns.set_palette("colorblind") + # plt.style.use('seaborn-colorblind') + if (latex): + plt.rc('text', usetex=True) + plt.rc('text.latex', + preamble=r'\usepackage{amsmath}\usepackage{amsfonts}\usepackage{amssymb}\DeclareMathAlphabet\mathsfbi{OT1}{cmss}{m}{sl}') + font = {'family': 'serif', 'size': font_size, 'serif': ['cmr10']} + plt.rc('font', **font) + plt.rc('lines', linewidth=line_scale, markersize=3 * line_scale) + plt.rc('xtick.major', width=line_scale / 2) + plt.rc('xtick.minor', width=line_scale / 2) + plt.rc('ytick.major', width=line_scale / 2) + plt.rc('ytick.minor', width=line_scale / 2) + plt.rc('axes', linewidth=0.5 * line_scale) + plt.rc('patch', linewidth=0.5 * line_scale) + plt.rc('figure', dpi=dpi) + plt.rc('errorbar', capsize=capsize) + + +def label_subplot(ax, label, color='k', loc='tl'): + xlim = ax.get_xlim() + ylim = ax.get_ylim() + font_size = plt.rcParams['font.size'] + x_off = 0.33 * font_size / 72 # inches + y_off = 0.33 * font_size / 72 + + ax_width = ax.get_window_extent().width / ax.figure.dpi # inches + ax_height = ax.get_window_extent().height / ax.figure.dpi # inches + + if loc == 'out': + height_frac = (ax_height - y_off) / ax_height + width_frac = - x_off / ax_width + valign = 'top' + halign = 'right' + else: + if loc[0] == 't': + height_frac = (ax_height - y_off) / ax_height + valign = 'top' + elif loc[0] == 'b': + height_frac = y_off / ax_height + valign = 'bottom' + else: + raise ValueError("loc must be tl, bl, tr, or br") + + if loc[1] == 'l': + width_frac = x_off / ax_width + halign = 'left' + elif loc[1] == 'r': + width_frac = (ax_width - x_off) / ax_width + halign = 'right' + else: + raise ValueError("loc must be tl, bl, tr, or br") + + ax.annotate(label, + xy=(np.mean(xlim), np.mean(ylim)), # ensure it shows up + xytext=(width_frac, height_frac), # points = inches * 72 + textcoords='axes fraction', color=color, + horizontalalignment=halign, verticalalignment=valign) + + +def format_axis_ticks_decimal(axis: Axis, decimal_places=2): + y_formatter = StrMethodFormatter("{x:.%0df}" % decimal_places) + axis.set_major_formatter(y_formatter) + axis.set_minor_formatter(y_formatter) + + axis.set_major_locator(AutoLocator()) + axis.set_minor_locator(AutoLocator()) + + +color_dict = {'red': ((0.0, 0.0, 0.0), + (0.9, 0.5, 1.0), + (1.0, 1.0, 1.0)), + 'green': ((0.0, 0.0, 0.0), + (0.5, 0.0, 0.0), + (1.0, 0.0, 0.0)), + 'blue': ((0.0, 0.0, 0.0), + (0.5, 0.0, 0.0), + (1.0, 0.0, 0.0))} + +heatmap_cm = LinearSegmentedColormap('heatmap', color_dict) + + +def set_axes_radius(ax, origin, radius): + """ https://stackoverflow.com/a/50664367/5270376 """ + ax.set_xlim3d([origin[0] - radius, origin[0] + radius]) + ax.set_ylim3d([origin[1] - radius, origin[1] + radius]) + ax.set_zlim3d([origin[2] - radius, origin[2] + radius]) + + +def set_axes_equal(ax): + """ + https://stackoverflow.com/a/50664367/5270376 + + Make axes of 3D plot have equal scale so that spheres appear as spheres, + cubes as cubes, etc.. This is one possible solution to Matplotlib's + ax.set_aspect('equal') and ax.axis('equal') not working for 3D. + + Input + ax: a matplotlib axis, e.g., as output from plt.gca(). + """ + + limits = np.array([ + ax.get_xlim3d(), + ax.get_ylim3d(), + ax.get_zlim3d(), + ]) + + origin = np.mean(limits, axis=1) + radius = 0.5 * np.max(np.abs(limits[:, 1] - limits[:, 0])) + set_axes_radius(ax, origin, radius) + + +def plot_3d_points(points, c=None, cmap_name="RdBu", center_cmap=True): + fig = plt.figure() + ax = fig.add_subplot(111, projection='3d') # type: Axes3D + points = np.array(points) + if c is not None: + if center_cmap: + scat = ax.scatter3D(points[:, 0], points[:, 2], points[:, 1], c=c, cmap=cm.get_cmap(cmap_name), + vmin=-np.max(np.abs(c)), vmax=np.max(np.abs(c))) + else: + scat = ax.scatter3D(points[:, 0], points[:, 2], points[:, 1], c=c, cmap=cm.get_cmap(cmap_name)) + fig.colorbar(scat) + else: + ax.scatter3D(points[:, 0], points[:, 2], points[:, 1]) + ax.set_xlabel('X') + ax.set_ylabel('Z') + ax.set_zlabel('Y') + + lim = [min([ax.get_xlim()[0], ax.get_ylim()[0], ax.get_zlim()[0]]), + max([ax.get_xlim()[1], ax.get_ylim()[1], ax.get_zlim()[1]])] + ax.set_xlim(lim) + ax.set_ylim(lim) + ax.set_zlim(lim) + plt.show() + + +def plot_2d_point_sets(point_sets): + colors = ["r", "b", "g", "orange", "k", "yellow"] + fig = plt.figure() + ax = fig.add_subplot(111, aspect='equal') + for i in range(len(point_sets)): + points = np.array(point_sets[i]) + ax.scatter(points[:, 0], points[:, 1], c=colors[i]) + ax.set_xlabel('X') + ax.set_ylabel('Y') + + lim = [min([ax.get_xlim()[0], ax.get_ylim()[0]]), + max([ax.get_xlim()[1], ax.get_ylim()[1]])] + ax.set_xlim(lim) + ax.set_ylim(lim) + plt.show() + + +def plot_3d_point_sets(point_sets, colors=("r", "b", "g", "orange", "k", "yellow"), colorbar=False): + fig = plt.figure() + ax = fig.add_subplot(111, projection='3d') # type: Axes3D + for i in range(len(point_sets)): + points = np.array(point_sets[i]) + scat = ax.scatter3D(points[:, 0], points[:, 2], points[:, 1], c=colors[i]) + if colorbar: + plt.colorbar(scat) + ax.set_xlabel('X') + ax.set_ylabel('Z') + ax.set_zlabel('Y') + + # lim = [min([ax.get_xlim()[0], ax.get_ylim()[0], ax.get_zlim()[0]]), + # max([ax.get_xlim()[1], ax.get_ylim()[1], ax.get_zlim()[1]])] + # ax.set_xlim(lim) + # ax.set_ylim(lim) + # ax.set_zlim(lim) + set_axes_equal(ax) + plt.show() + + +def plot_heatmap(points, x_bins=100, mode='smooth', filename=None, cmap_name='viridis'): + """ + Generate a heatmap plot of a number of points. + :param points: The points to use in the heatmap. + :param x_bins: The number of bins along the x-axis. + :param mode: 'smooth' for smooth bin edges, 'sharp' for sharp bin edges. + :param filename: The filename (and path) to save the plot, does not save if None. + """ + points = np.array(points) + x = points[:, 0] + y = points[:, 1] + + x_dim = abs(np.ptp(x)) + y_dim = abs(np.ptp(y)) + + # Generate heatmap + y_bins = int(round(x_bins * y_dim / x_dim)) + if y_bins == 0: + y_bins = 1 + heatmap, xedges, yedges = np.histogram2d(x, y, bins=(x_bins, y_bins)) + extent = [xedges[0] - 1, xedges[-1] + 1, yedges[0] - 1, yedges[-1] + 1] + + heatmap = heatmap.T + + fig = plt.figure() + if abs(yedges[-1] - yedges[0]) < 0.025: + yedges[0] = -0.025 # Ensure that the data is actually visible. + + if mode == 'smooth': + ax = fig.add_subplot(111, aspect='equal', xlim=xedges[[0, -1]], ylim=yedges[[0, -1]]) + im = mpl.image.NonUniformImage(ax, interpolation='bilinear') + xcenters = (xedges[:-1] + xedges[1:]) / 2 + ycenters = (yedges[:-1] + yedges[1:]) / 2 + im.set_data(xcenters, ycenters, heatmap) + ax.images.append(im) + elif mode == 'sharp': + ax = fig.add_subplot(111, aspect='equal') + X, Y = np.meshgrid(xedges, yedges) + cmap = None + if cmap_name == "heatmap": + cmap = heatmap_cm + else: + cmap = cm.get_cmap(cmap_name) + ax.pcolormesh(X, Y, heatmap, cmap=cmap) + else: + raise (ValueError("{0} is not a valid mode.".format(mode))) + if filename is not None: + plt.savefig(filename) + plt.show() + + +if __name__ == "__main__": + this_points = [[0, 1], [0, 2], [2, 3], [1, 3.5]] + plot_heatmap(this_points, x_bins=5, mode='sharp')