|
1 | | -""" pyplots.ai |
| 1 | +"""pyplots.ai |
2 | 2 | stereonet-equal-area: Structural Geology Stereonet (Equal-Area Projection) |
3 | 3 | Library: matplotlib 3.10.8 | Python 3.14.3 |
4 | 4 | Quality: 82/100 | Created: 2026-03-15 |
|
23 | 23 | all_strikes = np.concatenate([bedding_strike, joint_strike, fault_strike]) |
24 | 24 | all_dips = np.concatenate([bedding_dip, joint_dip, fault_dip]) |
25 | 25 | feature_types = ["Bedding"] * 30 + ["Joint"] * 25 + ["Fault"] * 20 |
26 | | -colors = {"Bedding": "#306998", "Joint": "#E8833A", "Fault": "#9B2335"} |
| 26 | +colors = {"Bedding": "#306998", "Joint": "#E8833A", "Fault": "#8B2252"} |
27 | 27 | markers = {"Bedding": "o", "Joint": "s", "Fault": "^"} |
28 | 28 |
|
29 | 29 | # Pole orientations in equal-area (Schmidt) projection |
|
59 | 59 | cos_dist = gx * pole_vx[j] + gy * pole_vy[j] + gz * pole_vz[j] |
60 | 60 | Z += np.exp(-(np.arccos(np.clip(cos_dist, -1, 1)) ** 2) / (2 * sigma**2)) |
61 | 61 |
|
62 | | -ax.contourf(THETA, R, Z, levels=8, cmap="Greys", alpha=0.25, zorder=1) |
| 62 | +contour_fill = ax.contourf(THETA, R, Z, levels=8, cmap="YlOrBr", alpha=0.3, zorder=1) |
| 63 | +ax.contour(THETA, R, Z, levels=8, colors="#B87333", alpha=0.4, linewidths=0.6, zorder=1) |
63 | 64 |
|
64 | | -# Great circles for each plane |
| 65 | +# Great circles for each plane - increased visibility |
65 | 66 | t_param = np.linspace(0, np.pi, 180) |
66 | 67 | for i in range(len(all_strikes)): |
67 | 68 | alpha = np.deg2rad(all_strikes[i]) |
|
74 | 75 | plunge = np.arctan2(pz, horiz) |
75 | 76 | colat = np.pi / 2 - plunge |
76 | 77 | r = np.sqrt(2) * np.sin(colat / 2) |
77 | | - ax.plot(trend, r, color=colors[feature_types[i]], alpha=0.15, linewidth=0.7, zorder=2) |
| 78 | + ax.plot(trend, r, color=colors[feature_types[i]], alpha=0.35, linewidth=1.2, zorder=2) |
78 | 79 |
|
79 | 80 | # Poles as scatter points with distinct markers per feature type |
80 | 81 | for feat in colors: |
|
83 | 84 | pole_trend_rad[mask], |
84 | 85 | pole_r[mask], |
85 | 86 | c=colors[feat], |
86 | | - s=150, |
| 87 | + s=160, |
87 | 88 | marker=markers[feat], |
88 | 89 | edgecolors="white", |
89 | | - linewidth=0.8, |
| 90 | + linewidth=1.0, |
90 | 91 | label=f"{feat} poles", |
91 | 92 | zorder=5, |
92 | 93 | ) |
93 | 94 |
|
| 95 | +# N label emphasis at top |
| 96 | +ax.annotate( |
| 97 | + "N", |
| 98 | + xy=(0, 1.08), |
| 99 | + xycoords="axes fraction", |
| 100 | + ha="center", |
| 101 | + va="center", |
| 102 | + fontsize=24, |
| 103 | + fontweight="bold", |
| 104 | + color="#333333", |
| 105 | +) |
| 106 | + |
94 | 107 | # Style |
95 | 108 | ax.set_rlim(0, 1) |
96 | 109 | ax.set_rticks([]) |
|
99 | 112 | tick_labels = [] |
100 | 113 | for d in theta_ticks: |
101 | 114 | if d == 0: |
102 | | - tick_labels.append("N") |
| 115 | + tick_labels.append("") |
103 | 116 | elif d == 90: |
104 | 117 | tick_labels.append("E") |
105 | 118 | elif d == 180: |
|
113 | 126 | ax.set_xticklabels(tick_labels, fontsize=16) |
114 | 127 | ax.grid(True, alpha=0.15, linewidth=0.5, color="gray") |
115 | 128 |
|
| 129 | +# Primitive circle emphasis |
| 130 | +circle_theta = np.linspace(0, 2 * np.pi, 200) |
| 131 | +ax.plot(circle_theta, np.ones_like(circle_theta), color="#444444", linewidth=1.5, zorder=3) |
| 132 | + |
| 133 | +# Legend inside the plot area for better layout balance |
116 | 134 | ax.legend( |
117 | | - loc="upper right", bbox_to_anchor=(1.22, 1.05), fontsize=16, framealpha=0.9, edgecolor="none", markerscale=1.2 |
| 135 | + loc="upper left", |
| 136 | + bbox_to_anchor=(0.02, 0.98), |
| 137 | + fontsize=16, |
| 138 | + framealpha=0.92, |
| 139 | + edgecolor="#cccccc", |
| 140 | + fancybox=True, |
| 141 | + markerscale=1.2, |
118 | 142 | ) |
119 | | -ax.set_title("stereonet-equal-area · matplotlib · pyplots.ai", fontsize=22, fontweight="medium", pad=30) |
| 143 | +ax.set_title("stereonet-equal-area · matplotlib · pyplots.ai", fontsize=24, fontweight="medium", pad=35) |
120 | 144 |
|
121 | 145 | plt.tight_layout() |
122 | 146 | plt.savefig("plot.png", dpi=300, bbox_inches="tight") |
0 commit comments