• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

bjmorgan / polyhedral-analysis / 10147868343

29 Jul 2024 04:09PM UTC coverage: 73.608% (+1.4%) from 72.251%
10147868343

push

github

bjmorgan
Added orientation plotting

43 of 44 new or added lines in 1 file covered. (97.73%)

608 of 826 relevant lines covered (73.61%)

2.94 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.73
/polyhedral_analysis/plotting.py
1
import numpy as np
4✔
2
from scipy.stats import gaussian_kde
4✔
3
import matplotlib.pyplot as plt
4✔
4
from cmcrameri import cm
4✔
5
from typing import List, Tuple, Optional, Dict, Any
4✔
6

7
def _process_orientation_data(orientations: List[Tuple[float, float]]) -> Dict[str, Any]:
4✔
8
    """
9
    Process orientation data to prepare for plotting.
10

11
    Args:
12
        orientations (List[Tuple[float, float]]): List of (theta, phi) tuples.
13

14
    Returns:
15
        Dict[str, Any]: Dictionary containing processed data for plotting.
16

17
    Raises:
18
        ValueError: If orientations is empty, contains invalid data, or results in singular covariance matrix.
19
    """
20
    orientations_array = np.array(orientations)
4✔
21
    
22
    if orientations_array.size == 0:
4✔
23
        raise ValueError("The orientations list is empty.")
4✔
24
    
25
    if orientations_array.shape[1] != 2:
4✔
26
        raise ValueError("Each orientation should be a tuple of (theta, phi).")
4✔
27

28
    phi_grid, theta_grid = np.mgrid[-180:180:100j, 0:180:100j]
4✔
29
    positions = np.vstack([phi_grid.ravel(), theta_grid.ravel()])
4✔
30

31
    values = orientations_array.T[::-1]  # Swap and transpose
4✔
32
    
33
    try:
4✔
34
        kernel = gaussian_kde(values, bw_method=0.1)
4✔
35
        z = np.reshape(kernel(positions).T, phi_grid.shape)
4✔
36
    except np.linalg.LinAlgError:
4✔
37
        raise ValueError("The data resulted in a singular covariance matrix. Consider adding more varied data points.")
4✔
38

39
    return {
4✔
40
        'phi_grid': phi_grid,
41
        'theta_grid': theta_grid,
42
        'z': z
43
    }
44

45
def plot_orientation_distribution(orientations: List[Tuple[float, float]],
4✔
46
                                  title: Optional[str] = None,
47
                                  figsize: Tuple[int, int] = (10, 8),
48
                                  cmap = cm.lipari,
49
                                  fontsize: Optional[int] = None,
50
                                  plot: bool = False) -> plt.Figure:
51
    """
52
    Create a contour map of the probability distribution for (phi, theta) orientations.
53
    
54
    Args:
55
        orientations (List[Tuple[float, float]]): List of (theta, phi) tuples.
56
        title (Optional[str], optional): Title for the plot. Defaults to None.
57
        figsize (Tuple[int, int], optional): Figure size as (width, height). Defaults to (10, 8).
58
        cmap (matplotlib.colors.Colormap, optional): Colormap to use for the contour plot. Defaults to cm.lipari.
59
        fontsize (Optional[int], optional): Font size for labels and title. If None, uses matplotlib defaults.
60
        plot (bool, optional): Whether to display the plot immediately. Defaults to False.
61
    
62
    Returns:
63
        matplotlib.figure.Figure: The generated figure object.
64

65
    Raises:
66
        ValueError: If orientations is empty or contains invalid data.
67
    """
68
    processed_data = _process_orientation_data(orientations)
4✔
69

70
    fig, ax = plt.subplots(figsize=figsize)
4✔
71

72
    contour = ax.contourf(processed_data['phi_grid'], processed_data['theta_grid'], 
4✔
73
                          processed_data['z'], levels=20, cmap=cmap)
74
    if title:
4✔
75
        ax.set_title(title, fontsize=fontsize)
4✔
76
    ax.set_xlabel(r'$\phi$ (degrees)', fontsize=fontsize)
4✔
77
    ax.set_ylabel(r'$\theta$ (degrees)', fontsize=fontsize)
4✔
78
    if fontsize:
4✔
79
        ax.tick_params(axis='both', which='major', labelsize=fontsize)
4✔
80

81
    cbar = fig.colorbar(contour)
4✔
82
    cbar.set_label('Probability Density', fontsize=fontsize)
4✔
83
    if fontsize:
4✔
84
        cbar.ax.tick_params(labelsize=fontsize)
4✔
85
        cbar.ax.yaxis.get_offset_text().set_fontsize(fontsize)
4✔
86

87
    cbar.formatter.set_powerlimits((0, 0))
4✔
88
    cbar.update_ticks()
4✔
89

90
    ax.set_xlim(-180, 180)
4✔
91
    ax.set_ylim(0, 180)
4✔
92

93
    plt.tight_layout()
4✔
94
    
95
    if plot:
4✔
NEW
96
        plt.show()
×
97
    else:
98
        plt.close(fig)  # Close the figure to prevent it from being displayed
4✔
99
    
100
    return fig
4✔
101

102
# Example usage:
103
# orientations = [(theta1, phi1), (theta2, phi2), ...]
104
# fig = plot_orientation_distribution(orientations, title="Optional Title", fontsize=14)
105
# plt.show()
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc