Source code for MEDiml.biomarkers.get_oriented_bound_box

#!/usr/bin/env python3
# -*- coding: utf-8 -*-


from typing import List

import numpy as np
import pandas as pd


[docs] def rot_matrix(theta: float, dim: int=2, rot_axis: int=-1) -> np.ndarray: """Creates a 2d or 3d rotation matrix Args: theta (float): angle in radian dim (int, optional): dimension size. Defaults to 2. rot_axis (int, optional): rotation axis value. Defaults to -1. Returns: ndarray: rotation matrix """ if dim == 2: rot_mat = np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]]) elif dim == 3: if rot_axis == 0: rot_mat = np.array([[1.0, 0.0, 0.0], [0.0, np.cos(theta), -np.sin(theta)], [0.0, np.sin(theta), np.cos(theta)]]) elif rot_axis == 1: rot_mat = np.array([[np.cos(theta), 0.0, np.sin(theta)], [0.0, 1.0, 0.0], [-np.sin(theta), 0.0, np.cos(theta)]]) elif rot_axis == 2: rot_mat = np.array([[np.cos(theta), -np.sin(theta), 0.0], [np.sin(theta), np.cos(theta), 0.0], [0.0, 0.0, 1.0]]) else: rot_mat = None else: rot_mat = None return rot_mat
[docs] def sig_proc_segmentise(x: List) -> List: """Produces a list of segments from input x with values (0,1) Args: x (List): list of values Returns: List: list of segments from input x with values (0,1) """ # Create a difference vector y = np.diff(x) # Find start and end indices of sections with value 1 ind_1_start = np.array(np.where(y == 1)).flatten() if np.shape(ind_1_start)[0] > 0: ind_1_start += 1 ind_1_end = np.array(np.where(y == -1)).flatten() # Check for boundary effects if x[0] == 1: ind_1_start = np.insert(ind_1_start, 0, 0) if x[-1] == 1: ind_1_end = np.append(ind_1_end, np.shape(x)[0]-1) # Generate segment df for segments with value 1 if np.shape(ind_1_start)[0] == 0: df_one = pd.DataFrame({"i": [], "j": [], "val": []}) else: df_one = pd.DataFrame({"i": ind_1_start, "j": ind_1_end, "val": np.ones(np.shape(ind_1_start)[0])}) # Find start and end indices for section with value 0 if np.shape(ind_1_start)[0] == 0: ind_0_start = np.array([0]) ind_0_end = np.array([np.shape(x)[0]-1]) else: ind_0_end = ind_1_start - 1 ind_0_start = ind_1_end + 1 # Check for boundary effect if x[0] == 0: ind_0_start = np.insert(ind_0_start, 0, 0) if x[-1] == 0: ind_0_end = np.append(ind_0_end, np.shape(x)[0]-1) # Check for out-of-range boundary effects if ind_0_end[0] < 0: ind_0_end = np.delete(ind_0_end, 0) if ind_0_start[-1] >= np.shape(x)[0]: ind_0_start = np.delete(ind_0_start, -1) # Generate segment df for segments with value 0 if np.shape(ind_0_start)[0] == 0: df_zero = pd.DataFrame({"i": [], "j": [], "val": []}) else: df_zero = pd.DataFrame({"i": ind_0_start, "j": ind_0_end, "val": np.zeros(np.shape(ind_0_start)[0])}) df_segm = df_one.append(df_zero).sort_values(by="i").reset_index(drop=True) return df_segm
[docs] def sig_proc_find_peaks(x: float, ddir: str="pos") -> pd.DataFrame: """Determines peak positions in array of values Args: x (float): value ddir (str, optional): positive or negative value. Defaults to "pos". Returns: pd.DataFrame: peak positions in array of values """ # Invert when looking for local minima if ddir == "neg": x = -x # Generate segments where slope is negative df_segm = sig_proc_segmentise(x=(np.diff(x) < 0.0)*1) # Start of slope coincides with position of peak (due to index shift induced by np.diff) ind_peak = df_segm.loc[df_segm.val == 1, "i"].values # Check right boundary if x[-1] > x[-2]: ind_peak = np.append(ind_peak, np.shape(x)[0]-1) # Construct dataframe with index and corresponding value if np.shape(ind_peak)[0] == 0: df_peak = pd.DataFrame({"ind": [], "val": []}) else: if ddir == "pos": df_peak = pd.DataFrame({"ind": ind_peak, "val": x[ind_peak]}) if ddir == "neg": df_peak = pd.DataFrame({"ind": ind_peak, "val": -x[ind_peak]}) return df_peak