164 lines
4.7 KiB
Python
164 lines
4.7 KiB
Python
from numpy import zeros
|
|
from numpy.typing import NDArray
|
|
from typing import NamedTuple, Any
|
|
|
|
|
|
def compute_matrix(number: int):
|
|
"""
|
|
Compute the index order (from 1 because it will be used by MATLAB) of measurmenet taken with a "snail" shape.
|
|
Used for the backscattermeter analysis MATLAB script
|
|
|
|
Parameters
|
|
----------
|
|
number: int
|
|
Number of block from center to the extremity of the map
|
|
"""
|
|
matrix = zeros((number * 2 + 1, number * 2 + 1), dtype=int)
|
|
cursor = [number, number]
|
|
counter = 1
|
|
matrix[*cursor] = counter
|
|
for i in range(number * 2):
|
|
for _ in range(i + 1):
|
|
if i % 2 == 0:
|
|
cursor[1] += 1
|
|
else:
|
|
cursor[1] -= 1
|
|
counter += 1
|
|
matrix[*cursor] = counter
|
|
for _ in range(i + 1):
|
|
if i % 2 == 0:
|
|
cursor[0] -= 1
|
|
else:
|
|
cursor[0] += 1
|
|
counter += 1
|
|
matrix[*cursor] = counter
|
|
for i in range(number):
|
|
cursor[1] += 1
|
|
counter += 1
|
|
matrix[*cursor] = counter
|
|
for i in range(number):
|
|
cursor[1] += 1
|
|
counter += 1
|
|
matrix[*cursor] = counter
|
|
return matrix
|
|
|
|
|
|
def diff_matrix(number: int) -> list[list[int]]:
|
|
posX, negX, posY, negY = [], [], [], []
|
|
index = 0
|
|
for i in range(number * 2):
|
|
for _ in range(i + 1):
|
|
if i % 2 == 0:
|
|
posX.append(index)
|
|
else:
|
|
negX.append(index)
|
|
index += 1
|
|
for _ in range(i + 1):
|
|
if i % 2 == 0:
|
|
posY.append(index)
|
|
else:
|
|
negY.append(index)
|
|
index += 1
|
|
for _ in range(number):
|
|
posX.append(index)
|
|
index += 1
|
|
for _ in range(number):
|
|
posY.append(index)
|
|
index += 1
|
|
return [posX, negX, posY, negY]
|
|
|
|
|
|
def python2matlab(array: NDArray[Any]):
|
|
"""
|
|
Return the MATLAB representation of a 2d python numpy array
|
|
|
|
Parameters
|
|
----------
|
|
array: NDArray[Any]
|
|
2d array
|
|
"""
|
|
if len(array.shape) != 2:
|
|
raise ValueError("Can only show the representation of 2D numpy array")
|
|
result = "matrix = [ "
|
|
for column_index in range(array.shape[1]):
|
|
for row_index in range(array.shape[0]):
|
|
result += "{} ".format(array[row_index, column_index])
|
|
if column_index != array.shape[1] - 1:
|
|
result += "; "
|
|
result += "]';"
|
|
return result
|
|
|
|
|
|
class Vector(NamedTuple):
|
|
x: float
|
|
y: float
|
|
|
|
def __truediv__(self, other: "Vector | float | int") -> "Vector":
|
|
if type(other) is type(self):
|
|
return Vector(x=self.x / other.x, y=self.y / other.y)
|
|
return Vector(x=self.x / other, y=self.y / other)
|
|
|
|
def __mul__(self, other: "Vector | float | int") -> "Vector":
|
|
if type(other) is type(self):
|
|
return Vector(x=self.x * other.x, y=self.y * other.y)
|
|
return Vector(x=self.x * other, y=self.y * other)
|
|
|
|
def add(self, other: "Point | Vector | float | int") -> "Vector":
|
|
if type(other) == type(self) or type(other) is Point:
|
|
return Vector(x=self.x + other.x, y=self.y + other.y)
|
|
return Vector(x=self.x + other, y=self.y + other)
|
|
|
|
|
|
class Point(NamedTuple):
|
|
x: float
|
|
y: float
|
|
|
|
def add(self, other: "Point | Vector | float | int") -> "Point":
|
|
if type(other) == type(self) or type(other) is Vector:
|
|
return Point(x=self.x + other.x, y=self.y + other.y)
|
|
return Point(x=self.x + other, y=self.y + other)
|
|
|
|
|
|
class Axis(NamedTuple):
|
|
pos: Vector
|
|
neg: Vector
|
|
|
|
|
|
class Directions(NamedTuple):
|
|
x: Axis
|
|
y: Axis
|
|
|
|
|
|
def convert_to_base(base: tuple[Vector, Vector], vector: Vector) -> Vector:
|
|
y = (vector.y - (base[0].y * vector.x / base[0].x)) / (
|
|
base[1].y - (base[0].y * base[1].x / base[0].x)
|
|
)
|
|
x = vector.x / base[0].x - y * (base[1].x / base[0].x)
|
|
return Vector(x=x, y=y)
|
|
|
|
|
|
def move_snail(
|
|
n_grid: int, point: Point, directions: Directions
|
|
) -> tuple[list[Vector], Point]:
|
|
movement: list[Vector] = []
|
|
for i in range(2 * n_grid):
|
|
for _ in range(i + 1):
|
|
if (i % 2) == 0:
|
|
movement.append(directions.x.pos)
|
|
else:
|
|
movement.append(directions.x.neg)
|
|
point = point.add(movement[-1])
|
|
for _ in range(i + 1):
|
|
if (i % 2) == 0:
|
|
movement.append(directions.y.pos)
|
|
else:
|
|
movement.append(directions.y.neg)
|
|
point = point.add(movement[-1])
|
|
# go back
|
|
for i in range(n_grid):
|
|
movement.append(directions.x.pos)
|
|
point = point.add(movement[-1])
|
|
for i in range(n_grid):
|
|
movement.append(directions.y.pos)
|
|
point = point.add(movement[-1])
|
|
return movement, point
|