kececilayout 0.5.8__py3-none-any.whl → 0.6.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kececilayout/__init__.py +60 -2
- kececilayout/_version.py +1 -2
- kececilayout/kececi_layout.py +1753 -33
- {kececilayout-0.5.8.dist-info → kececilayout-0.6.0.dist-info}/METADATA +55 -1
- kececilayout-0.6.0.dist-info/RECORD +10 -0
- kececilayout-0.5.8.dist-info/RECORD +0 -10
- {kececilayout-0.5.8.dist-info → kececilayout-0.6.0.dist-info}/WHEEL +0 -0
- {kececilayout-0.5.8.dist-info → kececilayout-0.6.0.dist-info}/licenses/LICENSE +0 -0
- {kececilayout-0.5.8.dist-info → kececilayout-0.6.0.dist-info}/top_level.txt +0 -0
kececilayout/kececi_layout.py
CHANGED
|
@@ -21,6 +21,8 @@ layouts = ['2d', 'cylindrical', 'cubic', 'spherical', 'elliptical', 'toric']
|
|
|
21
21
|
styles = ['standard', 'default', 'curved', 'helix', '3d', 'weighted', 'colored']
|
|
22
22
|
|
|
23
23
|
**v0.5.1:** edge (kececi_layout_edge)
|
|
24
|
+
|
|
25
|
+
**v0.6.0:** periodic table
|
|
24
26
|
"""
|
|
25
27
|
|
|
26
28
|
from collections import defaultdict
|
|
@@ -29,6 +31,7 @@ import igraph as ig
|
|
|
29
31
|
import itertools # Graphillion için eklendi
|
|
30
32
|
import math
|
|
31
33
|
import matplotlib.pyplot as plt
|
|
34
|
+
from matplotlib.colors import hsv_to_rgb
|
|
32
35
|
from mpl_toolkits.mplot3d import Axes3D
|
|
33
36
|
import networkit as nk
|
|
34
37
|
import networkx as nx
|
|
@@ -2085,6 +2088,148 @@ def kececi_layout_toric(
|
|
|
2085
2088
|
return pos_3d
|
|
2086
2089
|
|
|
2087
2090
|
# Ağırlıklı Çizim (draw_kececi_weighted)
|
|
2091
|
+
def draw_kececi_weighted(
|
|
2092
|
+
nx_graph: nx.Graph,
|
|
2093
|
+
pos: Dict[int, Tuple[float, ...]],
|
|
2094
|
+
ax: Optional[plt.Axes] = None,
|
|
2095
|
+
node_size: int = 300,
|
|
2096
|
+
edge_width_scale: float = 2.0,
|
|
2097
|
+
with_labels: bool = True,
|
|
2098
|
+
font_weight: str = 'bold',
|
|
2099
|
+
**kwargs
|
|
2100
|
+
) -> plt.Axes:
|
|
2101
|
+
"""
|
|
2102
|
+
2D/3D Weighted edges ile Keçeci layout çizimi.
|
|
2103
|
+
"""
|
|
2104
|
+
if ax is None:
|
|
2105
|
+
# 2D mi 3D mi kontrol et
|
|
2106
|
+
is_3d = len(pos[next(iter(pos))]) == 3
|
|
2107
|
+
fig = plt.figure(figsize=(10, 8))
|
|
2108
|
+
if is_3d:
|
|
2109
|
+
ax = fig.add_subplot(111, projection='3d')
|
|
2110
|
+
else:
|
|
2111
|
+
ax = fig.add_subplot(111)
|
|
2112
|
+
|
|
2113
|
+
# Node'ları çiz
|
|
2114
|
+
node_color = kwargs.get('node_color', 'lightblue')
|
|
2115
|
+
nx.draw_networkx_nodes(nx_graph, pos, ax=ax, node_size=node_size,
|
|
2116
|
+
node_color=node_color, **kwargs)
|
|
2117
|
+
|
|
2118
|
+
# Etiketleri çiz
|
|
2119
|
+
if with_labels:
|
|
2120
|
+
is_3d = len(pos[next(iter(pos))]) == 3
|
|
2121
|
+
if is_3d:
|
|
2122
|
+
# 3D için özel etiket çizimi
|
|
2123
|
+
for node, coord in pos.items():
|
|
2124
|
+
ax.text(coord[0], coord[1], coord[2], # 3D koordinatlar
|
|
2125
|
+
str(node), # 's' parametresi - etiket metni
|
|
2126
|
+
size=10,
|
|
2127
|
+
zorder=1,
|
|
2128
|
+
color='black',
|
|
2129
|
+
fontweight=font_weight)
|
|
2130
|
+
else:
|
|
2131
|
+
# 2D için NetworkX etiket çizimi
|
|
2132
|
+
nx.draw_networkx_labels(nx_graph, pos, ax=ax, font_weight=font_weight)
|
|
2133
|
+
|
|
2134
|
+
# Edge'leri çiz (weight'e göre)
|
|
2135
|
+
weights = nx.get_edge_attributes(nx_graph, 'weight')
|
|
2136
|
+
if not weights:
|
|
2137
|
+
weights = {edge: 1.0 for edge in nx_graph.edges()}
|
|
2138
|
+
|
|
2139
|
+
is_3d = len(pos[next(iter(pos))]) == 3
|
|
2140
|
+
for (u, v), weight in weights.items():
|
|
2141
|
+
width = weight * edge_width_scale
|
|
2142
|
+
if is_3d:
|
|
2143
|
+
# 3D edge çizimi
|
|
2144
|
+
ax.plot(
|
|
2145
|
+
[pos[u][0], pos[v][0]],
|
|
2146
|
+
[pos[u][1], pos[v][1]],
|
|
2147
|
+
[pos[u][2], pos[v][2]],
|
|
2148
|
+
linewidth=width,
|
|
2149
|
+
color='gray',
|
|
2150
|
+
alpha=0.7
|
|
2151
|
+
)
|
|
2152
|
+
else:
|
|
2153
|
+
# 2D edge çizimi
|
|
2154
|
+
ax.plot(
|
|
2155
|
+
[pos[u][0], pos[v][0]],
|
|
2156
|
+
[pos[u][1], pos[v][1]],
|
|
2157
|
+
linewidth=width,
|
|
2158
|
+
color='gray',
|
|
2159
|
+
alpha=0.7
|
|
2160
|
+
)
|
|
2161
|
+
|
|
2162
|
+
ax.set_title("Keçeci Layout: Weighted Edges")
|
|
2163
|
+
return ax
|
|
2164
|
+
|
|
2165
|
+
def draw_kececi_colored(
|
|
2166
|
+
nx_graph: nx.Graph,
|
|
2167
|
+
pos: Dict[int, Tuple[float, ...]],
|
|
2168
|
+
ax: Optional[plt.Axes] = None,
|
|
2169
|
+
node_size: int = 300,
|
|
2170
|
+
with_labels: bool = True,
|
|
2171
|
+
font_weight: str = 'bold',
|
|
2172
|
+
**kwargs
|
|
2173
|
+
) -> plt.Axes:
|
|
2174
|
+
"""
|
|
2175
|
+
2D/3D Renkli node'lar ile Keçeci layout çizimi.
|
|
2176
|
+
"""
|
|
2177
|
+
if ax is None:
|
|
2178
|
+
# 2D mi 3D mi kontrol et
|
|
2179
|
+
is_3d = len(pos[next(iter(pos))]) == 3
|
|
2180
|
+
fig = plt.figure(figsize=(10, 8))
|
|
2181
|
+
if is_3d:
|
|
2182
|
+
ax = fig.add_subplot(111, projection='3d')
|
|
2183
|
+
else:
|
|
2184
|
+
ax = fig.add_subplot(111)
|
|
2185
|
+
|
|
2186
|
+
# Dereceye göre renk hesapla
|
|
2187
|
+
degrees = dict(nx_graph.degree())
|
|
2188
|
+
max_degree = max(degrees.values()) if degrees else 1
|
|
2189
|
+
node_colors = [plt.cm.viridis(deg / max_degree) for deg in degrees.values()]
|
|
2190
|
+
|
|
2191
|
+
# Node'ları çiz
|
|
2192
|
+
nx.draw_networkx_nodes(
|
|
2193
|
+
nx_graph, pos, ax=ax,
|
|
2194
|
+
node_color=node_colors,
|
|
2195
|
+
node_size=node_size,
|
|
2196
|
+
**kwargs
|
|
2197
|
+
)
|
|
2198
|
+
|
|
2199
|
+
# Etiketleri çiz
|
|
2200
|
+
if with_labels:
|
|
2201
|
+
is_3d = len(pos[next(iter(pos))]) == 3
|
|
2202
|
+
if is_3d:
|
|
2203
|
+
# 3D için özel etiket çizimi
|
|
2204
|
+
for node, coord in pos.items():
|
|
2205
|
+
ax.text(coord[0], coord[1], coord[2], # 3D koordinatlar
|
|
2206
|
+
str(node), # 's' parametresi - etiket metni
|
|
2207
|
+
size=10,
|
|
2208
|
+
zorder=1,
|
|
2209
|
+
color='black',
|
|
2210
|
+
fontweight=font_weight)
|
|
2211
|
+
else:
|
|
2212
|
+
# 2D için NetworkX etiket çizimi
|
|
2213
|
+
nx.draw_networkx_labels(nx_graph, pos, ax=ax, font_weight=font_weight)
|
|
2214
|
+
|
|
2215
|
+
# Edge'leri çiz
|
|
2216
|
+
is_3d = len(pos[next(iter(pos))]) == 3
|
|
2217
|
+
if is_3d:
|
|
2218
|
+
for u, v in nx_graph.edges():
|
|
2219
|
+
ax.plot(
|
|
2220
|
+
[pos[u][0], pos[v][0]],
|
|
2221
|
+
[pos[u][1], pos[v][1]],
|
|
2222
|
+
[pos[u][2], pos[v][2]],
|
|
2223
|
+
color='gray',
|
|
2224
|
+
alpha=0.5
|
|
2225
|
+
)
|
|
2226
|
+
else:
|
|
2227
|
+
nx.draw_networkx_edges(nx_graph, pos, ax=ax, alpha=0.5)
|
|
2228
|
+
|
|
2229
|
+
ax.set_title("Keçeci Layout: Colored Nodes")
|
|
2230
|
+
return ax
|
|
2231
|
+
|
|
2232
|
+
"""
|
|
2088
2233
|
def draw_kececi_weighted(
|
|
2089
2234
|
nx_graph: nx.Graph,
|
|
2090
2235
|
pos: Dict[int, Tuple[float, ...]],
|
|
@@ -2132,7 +2277,8 @@ def draw_kececi_weighted(
|
|
|
2132
2277
|
|
|
2133
2278
|
ax.set_title("Keçeci Layout: Weighted Edges")
|
|
2134
2279
|
return ax
|
|
2135
|
-
|
|
2280
|
+
"""
|
|
2281
|
+
"""
|
|
2136
2282
|
# Renkli Çizim (draw_kececi_colored)
|
|
2137
2283
|
def draw_kececi_colored(
|
|
2138
2284
|
nx_graph: nx.Graph,
|
|
@@ -2177,6 +2323,7 @@ def draw_kececi_colored(
|
|
|
2177
2323
|
|
|
2178
2324
|
ax.set_title("Keçeci Layout: Colored Nodes")
|
|
2179
2325
|
return ax
|
|
2326
|
+
"""
|
|
2180
2327
|
|
|
2181
2328
|
# =============================================================================
|
|
2182
2329
|
# 3. INTERNAL DRAWING STYLE IMPLEMENTATIONS
|
|
@@ -2288,13 +2435,16 @@ def draw_kececi(
|
|
|
2288
2435
|
style: str = 'default',
|
|
2289
2436
|
ax: Optional[plt.Axes] = None,
|
|
2290
2437
|
with_labels: bool = True,
|
|
2291
|
-
node_color: str = 'lightblue',
|
|
2438
|
+
node_color: Union[str, List] = 'lightblue',
|
|
2292
2439
|
node_size: int = 500,
|
|
2293
2440
|
font_weight: str = 'bold',
|
|
2441
|
+
edge_color: str = 'gray',
|
|
2442
|
+
edge_alpha: float = 0.5,
|
|
2443
|
+
edge_width: float = 1.0,
|
|
2294
2444
|
**kwargs
|
|
2295
2445
|
) -> plt.Axes:
|
|
2296
2446
|
"""
|
|
2297
|
-
Keçeci Layout ile graf çizimi.
|
|
2447
|
+
Keçeci Layout ile 2D/3D uyumlu graf çizimi.
|
|
2298
2448
|
|
|
2299
2449
|
Args:
|
|
2300
2450
|
graph: Graf objesi (NetworkX, igraph, vb.).
|
|
@@ -2303,9 +2453,12 @@ def draw_kececi(
|
|
|
2303
2453
|
style: 'default', 'weighted', 'colored'.
|
|
2304
2454
|
ax: Matplotlib ekseni.
|
|
2305
2455
|
with_labels: Düğüm etiketlerini göster.
|
|
2306
|
-
node_color: Düğüm rengi.
|
|
2456
|
+
node_color: Düğüm rengi (tek renk veya renk listesi).
|
|
2307
2457
|
node_size: Düğüm boyutu.
|
|
2308
2458
|
font_weight: Yazı kalınlığı.
|
|
2459
|
+
edge_color: Kenar rengi.
|
|
2460
|
+
edge_alpha: Kenar şeffaflığı.
|
|
2461
|
+
edge_width: Kenar kalınlığı.
|
|
2309
2462
|
**kwargs: Ek parametreler.
|
|
2310
2463
|
|
|
2311
2464
|
Returns:
|
|
@@ -2313,6 +2466,209 @@ def draw_kececi(
|
|
|
2313
2466
|
"""
|
|
2314
2467
|
nx_graph = to_networkx(graph)
|
|
2315
2468
|
|
|
2469
|
+
# Eğer pos verilmemişse, layout'a göre hesapla
|
|
2470
|
+
if pos is None:
|
|
2471
|
+
if layout is None:
|
|
2472
|
+
layout = '2d' # Varsayılan layout
|
|
2473
|
+
|
|
2474
|
+
if layout == '2d':
|
|
2475
|
+
pos = kececi_layout_2d(nx_graph, **kwargs)
|
|
2476
|
+
elif layout == 'cylindrical':
|
|
2477
|
+
pos = kececi_layout_cylindrical(nx_graph, **kwargs)
|
|
2478
|
+
elif layout == 'cubic':
|
|
2479
|
+
pos = kececi_layout_cubic(nx_graph, **kwargs)
|
|
2480
|
+
elif layout == 'spherical':
|
|
2481
|
+
pos = kececi_layout_spherical(nx_graph, **kwargs)
|
|
2482
|
+
elif layout == 'elliptical':
|
|
2483
|
+
pos = kececi_layout_elliptical(nx_graph, **kwargs)
|
|
2484
|
+
elif layout == 'toric':
|
|
2485
|
+
pos = kececi_layout_toric(nx_graph, **kwargs)
|
|
2486
|
+
else:
|
|
2487
|
+
raise ValueError(f"Geçersiz layout: {layout}")
|
|
2488
|
+
|
|
2489
|
+
# 2D mi 3D mi kontrol et
|
|
2490
|
+
is_3d = len(pos[next(iter(pos))]) == 3
|
|
2491
|
+
|
|
2492
|
+
# Eksen oluştur (eğer verilmemişse)
|
|
2493
|
+
if ax is None:
|
|
2494
|
+
fig = plt.figure(figsize=(10, 8))
|
|
2495
|
+
if is_3d:
|
|
2496
|
+
ax = fig.add_subplot(111, projection='3d')
|
|
2497
|
+
else:
|
|
2498
|
+
ax = fig.add_subplot(111)
|
|
2499
|
+
|
|
2500
|
+
# Stile göre çizim yap
|
|
2501
|
+
if style == 'weighted':
|
|
2502
|
+
draw_kececi_weighted(nx_graph, pos, ax, node_size=node_size,
|
|
2503
|
+
with_labels=with_labels, font_weight=font_weight, **kwargs)
|
|
2504
|
+
elif style == 'colored':
|
|
2505
|
+
draw_kececi_colored(nx_graph, pos, ax, node_size=node_size,
|
|
2506
|
+
with_labels=with_labels, font_weight=font_weight, **kwargs)
|
|
2507
|
+
else: # 'default'
|
|
2508
|
+
# Node'ları çiz
|
|
2509
|
+
nx.draw_networkx_nodes(nx_graph, pos, ax=ax,
|
|
2510
|
+
node_color=node_color,
|
|
2511
|
+
node_size=node_size,
|
|
2512
|
+
**kwargs)
|
|
2513
|
+
|
|
2514
|
+
# Etiketleri çiz
|
|
2515
|
+
if with_labels:
|
|
2516
|
+
if is_3d:
|
|
2517
|
+
# 3D için özel etiket çizimi
|
|
2518
|
+
for node, coord in pos.items():
|
|
2519
|
+
ax.text(coord[0], coord[1], coord[2], # 3D koordinatlar
|
|
2520
|
+
str(node), # 's' parametresi - etiket metni
|
|
2521
|
+
size=10,
|
|
2522
|
+
zorder=1,
|
|
2523
|
+
color='black',
|
|
2524
|
+
fontweight=font_weight,
|
|
2525
|
+
ha='center', # Yatayda ortala
|
|
2526
|
+
va='center') # Dikeyde ortala
|
|
2527
|
+
else:
|
|
2528
|
+
# 2D için NetworkX etiket çizimi
|
|
2529
|
+
nx.draw_networkx_labels(nx_graph, pos, ax=ax, font_weight=font_weight)
|
|
2530
|
+
|
|
2531
|
+
# Edge'leri çiz
|
|
2532
|
+
if is_3d:
|
|
2533
|
+
for u, v in nx_graph.edges():
|
|
2534
|
+
ax.plot(
|
|
2535
|
+
[pos[u][0], pos[v][0]],
|
|
2536
|
+
[pos[u][1], pos[v][1]],
|
|
2537
|
+
[pos[u][2], pos[v][2]],
|
|
2538
|
+
color=edge_color,
|
|
2539
|
+
alpha=edge_alpha,
|
|
2540
|
+
linewidth=edge_width
|
|
2541
|
+
)
|
|
2542
|
+
else:
|
|
2543
|
+
nx.draw_networkx_edges(nx_graph, pos, ax=ax,
|
|
2544
|
+
alpha=edge_alpha,
|
|
2545
|
+
edge_color=edge_color,
|
|
2546
|
+
width=edge_width)
|
|
2547
|
+
|
|
2548
|
+
title = f"Keçeci Layout: {layout.capitalize() if layout else 'Custom'} ({style})"
|
|
2549
|
+
ax.set_title(title)
|
|
2550
|
+
|
|
2551
|
+
# Eksenleri kapat
|
|
2552
|
+
ax.set_axis_off()
|
|
2553
|
+
|
|
2554
|
+
return ax
|
|
2555
|
+
|
|
2556
|
+
def draw_kececi_custom_labels(
|
|
2557
|
+
graph,
|
|
2558
|
+
pos: Dict[int, Tuple[float, ...]],
|
|
2559
|
+
labels: Dict[int, str],
|
|
2560
|
+
ax: Optional[plt.Axes] = None,
|
|
2561
|
+
node_size: int = 500,
|
|
2562
|
+
node_color: Union[str, List] = 'lightblue',
|
|
2563
|
+
font_size: int = 10,
|
|
2564
|
+
font_color: Union[str, List] = 'black',
|
|
2565
|
+
font_weight: str = 'bold',
|
|
2566
|
+
**kwargs
|
|
2567
|
+
) -> plt.Axes:
|
|
2568
|
+
"""
|
|
2569
|
+
Özel etiketlerle Keçeci layout çizimi (2D/3D uyumlu).
|
|
2570
|
+
|
|
2571
|
+
Args:
|
|
2572
|
+
graph: Graf objesi
|
|
2573
|
+
pos: Node pozisyonları
|
|
2574
|
+
labels: Özel etiketler (node_id: label_text)
|
|
2575
|
+
ax: Matplotlib ekseni
|
|
2576
|
+
node_size: Node boyutu
|
|
2577
|
+
node_color: Node rengi
|
|
2578
|
+
font_size: Yazı boyutu
|
|
2579
|
+
font_color: Yazı rengi
|
|
2580
|
+
font_weight: Yazı kalınlığı
|
|
2581
|
+
**kwargs: Ek parametreler
|
|
2582
|
+
|
|
2583
|
+
Returns:
|
|
2584
|
+
Matplotlib ekseni
|
|
2585
|
+
"""
|
|
2586
|
+
nx_graph = to_networkx(graph)
|
|
2587
|
+
|
|
2588
|
+
# 2D mi 3D mi kontrol et
|
|
2589
|
+
is_3d = len(pos[next(iter(pos))]) == 3
|
|
2590
|
+
|
|
2591
|
+
# Eksen oluştur (eğer verilmemişse)
|
|
2592
|
+
if ax is None:
|
|
2593
|
+
fig = plt.figure(figsize=(10, 8))
|
|
2594
|
+
if is_3d:
|
|
2595
|
+
ax = fig.add_subplot(111, projection='3d')
|
|
2596
|
+
else:
|
|
2597
|
+
ax = fig.add_subplot(111)
|
|
2598
|
+
|
|
2599
|
+
# Node'ları çiz
|
|
2600
|
+
nx.draw_networkx_nodes(nx_graph, pos, ax=ax,
|
|
2601
|
+
node_color=node_color,
|
|
2602
|
+
node_size=node_size,
|
|
2603
|
+
**kwargs)
|
|
2604
|
+
|
|
2605
|
+
# Edge'leri çiz
|
|
2606
|
+
if is_3d:
|
|
2607
|
+
for u, v in nx_graph.edges():
|
|
2608
|
+
ax.plot(
|
|
2609
|
+
[pos[u][0], pos[v][0]],
|
|
2610
|
+
[pos[u][1], pos[v][1]],
|
|
2611
|
+
[pos[u][2], pos[v][2]],
|
|
2612
|
+
color='gray',
|
|
2613
|
+
alpha=0.5
|
|
2614
|
+
)
|
|
2615
|
+
else:
|
|
2616
|
+
nx.draw_networkx_edges(nx_graph, pos, ax=ax, alpha=0.5)
|
|
2617
|
+
|
|
2618
|
+
# Özel etiketleri çiz
|
|
2619
|
+
if is_3d:
|
|
2620
|
+
for node, coord in pos.items():
|
|
2621
|
+
if node in labels:
|
|
2622
|
+
ax.text(coord[0], coord[1], coord[2],
|
|
2623
|
+
labels[node],
|
|
2624
|
+
fontsize=font_size,
|
|
2625
|
+
fontweight=font_weight,
|
|
2626
|
+
color=font_color if isinstance(font_color, str) else font_color[node-1],
|
|
2627
|
+
ha='center',
|
|
2628
|
+
va='center',
|
|
2629
|
+
zorder=10)
|
|
2630
|
+
else:
|
|
2631
|
+
# 2D için NetworkX etiket çizimi
|
|
2632
|
+
nx.draw_networkx_labels(nx_graph, pos, labels=labels, ax=ax,
|
|
2633
|
+
font_size=font_size,
|
|
2634
|
+
font_color=font_color,
|
|
2635
|
+
font_weight=font_weight)
|
|
2636
|
+
|
|
2637
|
+
ax.set_title("Keçeci Layout with Custom Labels")
|
|
2638
|
+
ax.set_axis_off()
|
|
2639
|
+
|
|
2640
|
+
return ax
|
|
2641
|
+
"""
|
|
2642
|
+
def draw_kececi(
|
|
2643
|
+
graph,
|
|
2644
|
+
pos: Optional[Dict[int, Tuple[float, ...]]] = None,
|
|
2645
|
+
layout: Optional[str] = None,
|
|
2646
|
+
style: str = 'default',
|
|
2647
|
+
ax: Optional[plt.Axes] = None,
|
|
2648
|
+
with_labels: bool = True,
|
|
2649
|
+
node_color: str = 'lightblue',
|
|
2650
|
+
node_size: int = 500,
|
|
2651
|
+
font_weight: str = 'bold',
|
|
2652
|
+
**kwargs
|
|
2653
|
+
) -> plt.Axes:
|
|
2654
|
+
|
|
2655
|
+
Keçeci Layout ile graf çizimi.
|
|
2656
|
+
Args:
|
|
2657
|
+
graph: Graf objesi (NetworkX, igraph, vb.).
|
|
2658
|
+
pos: Önceden hesaplanmış koordinatlar (opsiyonel).
|
|
2659
|
+
layout: '2d', 'cylindrical', 'cubic', 'spherical', 'elliptical', 'toric' (opsiyonel).
|
|
2660
|
+
style: 'default', 'weighted', 'colored'.
|
|
2661
|
+
ax: Matplotlib ekseni.
|
|
2662
|
+
with_labels: Düğüm etiketlerini göster.
|
|
2663
|
+
node_color: Düğüm rengi.
|
|
2664
|
+
node_size: Düğüm boyutu.
|
|
2665
|
+
font_weight: Yazı kalınlığı.
|
|
2666
|
+
**kwargs: Ek parametreler.
|
|
2667
|
+
Returns:
|
|
2668
|
+
Matplotlib ekseni.
|
|
2669
|
+
|
|
2670
|
+
nx_graph = to_networkx(graph)
|
|
2671
|
+
|
|
2316
2672
|
# Eğer pos verilmemişse, layout'a göre hesapla
|
|
2317
2673
|
if pos is None:
|
|
2318
2674
|
if layout is None:
|
|
@@ -2374,6 +2730,7 @@ def draw_kececi(
|
|
|
2374
2730
|
ax.set_title(f"Keçeci Layout: {layout.capitalize() if layout else 'Custom'} ({style})")
|
|
2375
2731
|
return ax
|
|
2376
2732
|
"""
|
|
2733
|
+
"""
|
|
2377
2734
|
def draw_kececi(
|
|
2378
2735
|
graph,
|
|
2379
2736
|
layout: str = '2d',
|
|
@@ -2383,14 +2740,12 @@ def draw_kececi(
|
|
|
2383
2740
|
) -> plt.Axes:
|
|
2384
2741
|
|
|
2385
2742
|
Keçeci Layout ile graf çizimi.
|
|
2386
|
-
|
|
2387
2743
|
Args:
|
|
2388
2744
|
graph: Graf objesi (NetworkX, igraph, vb.).
|
|
2389
2745
|
layout: '2d', 'cylindrical', 'cubic', 'spherical', 'elliptical', 'toric'.
|
|
2390
2746
|
style: 'default', 'weighted', 'colored'.
|
|
2391
2747
|
ax: Matplotlib ekseni.
|
|
2392
2748
|
**kwargs: Ek parametreler.
|
|
2393
|
-
|
|
2394
2749
|
Returns:
|
|
2395
2750
|
Matplotlib ekseni.
|
|
2396
2751
|
|
|
@@ -2491,23 +2846,1398 @@ def draw_kececi(graph, style='curved', ax=None, **kwargs):
|
|
|
2491
2846
|
return ax
|
|
2492
2847
|
"""
|
|
2493
2848
|
|
|
2494
|
-
|
|
2495
|
-
|
|
2496
|
-
|
|
2497
|
-
|
|
2498
|
-
|
|
2499
|
-
|
|
2500
|
-
|
|
2501
|
-
|
|
2502
|
-
|
|
2503
|
-
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
|
|
2510
|
-
|
|
2849
|
+
def draw_kececi_periodic_table(
|
|
2850
|
+
graph,
|
|
2851
|
+
periodic_elements: Dict[int, Tuple[str, int]],
|
|
2852
|
+
layout_type: str = '3d_helix',
|
|
2853
|
+
layout_params: Optional[Dict] = None,
|
|
2854
|
+
ax: Optional[plt.Axes] = None,
|
|
2855
|
+
dimension: str = 'auto', # '2d', '3d', or 'auto'
|
|
2856
|
+
color_scheme: str = 'vibrant', # 'vibrant', 'distinct', 'pastel', 'group', 'period', 'block', 'electronegativity'
|
|
2857
|
+
node_size: Union[int, List[int]] = 1600,
|
|
2858
|
+
font_size: Union[int, List[int]] = 10,
|
|
2859
|
+
edge_style: str = 'standard', # 'standard', 'light', 'bold', 'hidden'
|
|
2860
|
+
label_position: str = 'center', # 'center', 'above', 'below', 'right', 'left'
|
|
2861
|
+
zorder_strategy: str = 'smart', # 'smart', 'fixed', 'z_based'
|
|
2862
|
+
show_legend: bool = False,
|
|
2863
|
+
title: Optional[str] = None,
|
|
2864
|
+
**kwargs
|
|
2865
|
+
) -> Tuple[plt.Axes, Dict]:
|
|
2866
|
+
"""
|
|
2867
|
+
Gelişmiş periyodik tablo çizimi - Hem 2D hem 3D uyumlu.
|
|
2868
|
+
"""
|
|
2869
|
+
# Graph'ı NetworkX'e çevir
|
|
2870
|
+
nx_graph = to_networkx(graph)
|
|
2871
|
+
node_count = len(periodic_elements)
|
|
2872
|
+
|
|
2873
|
+
# Dimension belirleme
|
|
2874
|
+
if dimension == 'auto':
|
|
2875
|
+
if '3d' in layout_type.lower():
|
|
2876
|
+
dimension = '3d'
|
|
2877
|
+
else:
|
|
2878
|
+
dimension = '2d'
|
|
2879
|
+
|
|
2880
|
+
# Layout parametreleri
|
|
2881
|
+
if layout_params is None:
|
|
2882
|
+
layout_params = {}
|
|
2883
|
+
|
|
2884
|
+
# Layout hesapla
|
|
2885
|
+
pos = _calculate_layout(nx_graph, layout_type, layout_params, dimension, node_count)
|
|
2886
|
+
|
|
2887
|
+
# Renkleri oluştur
|
|
2888
|
+
node_colors = _generate_colors(node_count, color_scheme, periodic_elements)
|
|
2889
|
+
|
|
2890
|
+
# Etiketleri oluştur
|
|
2891
|
+
custom_labels = _generate_labels(nx_graph, periodic_elements)
|
|
2892
|
+
|
|
2893
|
+
# Eksen oluştur (eğer verilmemişse)
|
|
2894
|
+
if ax is None:
|
|
2895
|
+
fig_size = kwargs.get('figsize', (20, 20) if dimension == '3d' else (16, 16))
|
|
2896
|
+
fig = plt.figure(figsize=fig_size)
|
|
2897
|
+
if dimension == '3d':
|
|
2898
|
+
ax = fig.add_subplot(111, projection='3d')
|
|
2899
|
+
else:
|
|
2900
|
+
ax = fig.add_subplot(111)
|
|
2901
|
+
|
|
2902
|
+
# Çizim sırasını belirle
|
|
2903
|
+
draw_order = _get_draw_order(nx_graph, pos, zorder_strategy, dimension)
|
|
2904
|
+
|
|
2905
|
+
# Edge stilleri
|
|
2906
|
+
edge_config = _get_edge_config(edge_style)
|
|
2907
|
+
|
|
2908
|
+
# Edge'leri çiz (ilk sırada)
|
|
2909
|
+
_draw_edges(nx_graph, pos, ax, edge_config, dimension)
|
|
2910
|
+
|
|
2911
|
+
# Node'ları çiz (çizim sırasına göre)
|
|
2912
|
+
_draw_nodes(nx_graph, pos, node_colors, ax, node_size, draw_order, dimension, **kwargs)
|
|
2913
|
+
|
|
2914
|
+
# Etiketleri çiz
|
|
2915
|
+
_draw_labels(nx_graph, pos, custom_labels, node_colors, ax, font_size,
|
|
2916
|
+
label_position, dimension, **kwargs)
|
|
2917
|
+
|
|
2918
|
+
# Başlık
|
|
2919
|
+
if title is None:
|
|
2920
|
+
title = _generate_title(layout_type, node_count, color_scheme, dimension)
|
|
2921
|
+
ax.set_title(title, fontsize=20, fontweight='bold', pad=25)
|
|
2922
|
+
|
|
2923
|
+
# Eksen ayarları
|
|
2924
|
+
_configure_axes(ax, pos, dimension, layout_params, **kwargs)
|
|
2925
|
+
|
|
2926
|
+
# Açıklama (legend)
|
|
2927
|
+
if show_legend and color_scheme in ['group', 'period', 'block']:
|
|
2928
|
+
_add_legend(ax, color_scheme, dimension, periodic_elements)
|
|
2929
|
+
|
|
2930
|
+
return ax, pos
|
|
2931
|
+
|
|
2932
|
+
|
|
2933
|
+
# Yardımcı fonksiyonlar (öncekiyle aynı)
|
|
2934
|
+
def _calculate_layout(graph, layout_type, params, dimension, node_count=None):
|
|
2935
|
+
"""Layout hesapla."""
|
|
2936
|
+
if layout_type == '3d_helix':
|
|
2937
|
+
return kececi_layout_3d_helix_parametric(
|
|
2938
|
+
graph,
|
|
2939
|
+
z_spacing=params.get('z_spacing', 8.0),
|
|
2940
|
+
radius=params.get('radius', 25.0),
|
|
2941
|
+
turns=params.get('turns', 3.0)
|
|
2942
|
+
)
|
|
2943
|
+
|
|
2944
|
+
elif layout_type == '2d_linear':
|
|
2945
|
+
return kececi_layout_2d(
|
|
2946
|
+
graph,
|
|
2947
|
+
primary_spacing=params.get('primary_spacing', 2.0),
|
|
2948
|
+
secondary_spacing=params.get('secondary_spacing', 2.0),
|
|
2949
|
+
primary_direction=params.get('primary_direction', 'left-to-right'),
|
|
2950
|
+
secondary_start=params.get('secondary_start', 'up'),
|
|
2951
|
+
expanding=params.get('expanding', True)
|
|
2952
|
+
)
|
|
2953
|
+
|
|
2954
|
+
elif layout_type == '2d_circular':
|
|
2955
|
+
return nx.circular_layout(graph, scale=params.get('scale', 1.0))
|
|
2956
|
+
|
|
2957
|
+
elif layout_type == '3d_spherical':
|
|
2958
|
+
pos = {}
|
|
2959
|
+
n = len(graph.nodes())
|
|
2960
|
+
for i, node in enumerate(graph.nodes()):
|
|
2961
|
+
phi = np.arccos(1 - 2 * (i + 0.5) / n)
|
|
2962
|
+
theta = np.pi * (1 + 5**0.5) * i
|
|
2963
|
+
radius = params.get('radius', 20.0)
|
|
2964
|
+
pos[node] = (
|
|
2965
|
+
radius * np.sin(phi) * np.cos(theta),
|
|
2966
|
+
radius * np.sin(phi) * np.sin(theta),
|
|
2967
|
+
radius * np.cos(phi)
|
|
2968
|
+
)
|
|
2969
|
+
return pos
|
|
2970
|
+
|
|
2971
|
+
elif layout_type == '2d_spring':
|
|
2972
|
+
return nx.spring_layout(graph, k=params.get('k', 2.0),
|
|
2973
|
+
iterations=params.get('iterations', 50))
|
|
2974
|
+
|
|
2975
|
+
elif layout_type == '2d_grid':
|
|
2976
|
+
return _generate_grid_layout(graph, params, node_count)
|
|
2977
|
+
|
|
2978
|
+
else:
|
|
2979
|
+
return kececi_layout_2d(
|
|
2980
|
+
graph,
|
|
2981
|
+
primary_spacing=params.get('primary_spacing', 2.0),
|
|
2982
|
+
secondary_spacing=params.get('secondary_spacing', 2.0),
|
|
2983
|
+
primary_direction=params.get('primary_direction', 'left-to-right'),
|
|
2984
|
+
secondary_start=params.get('secondary_start', 'up'),
|
|
2985
|
+
expanding=params.get('expanding', True)
|
|
2986
|
+
)
|
|
2987
|
+
|
|
2988
|
+
def _generate_grid_layout(graph, params, node_count):
|
|
2989
|
+
"""Manuel grid layout oluştur."""
|
|
2990
|
+
rows = params.get('rows', None)
|
|
2991
|
+
cols = params.get('cols', None)
|
|
2992
|
+
spacing = params.get('spacing', 2.0)
|
|
2993
|
+
|
|
2994
|
+
if rows is None and cols is None:
|
|
2995
|
+
cols = int(np.ceil(np.sqrt(node_count)))
|
|
2996
|
+
rows = int(np.ceil(node_count / cols))
|
|
2997
|
+
elif rows is None:
|
|
2998
|
+
rows = int(np.ceil(node_count / cols))
|
|
2999
|
+
elif cols is None:
|
|
3000
|
+
cols = int(np.ceil(node_count / rows))
|
|
3001
|
+
|
|
3002
|
+
pos = {}
|
|
3003
|
+
for i, node in enumerate(sorted(graph.nodes())):
|
|
3004
|
+
row = i // cols
|
|
3005
|
+
col = i % cols
|
|
3006
|
+
|
|
3007
|
+
x_offset = -(cols - 1) * spacing / 2
|
|
3008
|
+
y_offset = (rows - 1) * spacing / 2
|
|
3009
|
+
|
|
3010
|
+
x = col * spacing + x_offset
|
|
3011
|
+
y = -row * spacing + y_offset
|
|
3012
|
+
|
|
3013
|
+
pos[node] = (x, y)
|
|
3014
|
+
|
|
3015
|
+
return pos
|
|
3016
|
+
|
|
3017
|
+
|
|
3018
|
+
def _generate_colors(node_count, scheme, periodic_elements=None):
|
|
3019
|
+
"""Renkleri oluştur."""
|
|
3020
|
+
colors = []
|
|
3021
|
+
|
|
3022
|
+
if scheme == 'vibrant':
|
|
3023
|
+
for i in range(node_count):
|
|
3024
|
+
hue = (i * 0.618033988749895) % 1.0
|
|
3025
|
+
saturation = 0.7 + np.random.random() * 0.3
|
|
3026
|
+
value = 0.8 + np.random.random() * 0.2
|
|
3027
|
+
colors.append(hsv_to_rgb([hue, saturation, value]))
|
|
3028
|
+
|
|
3029
|
+
elif scheme == 'distinct':
|
|
3030
|
+
colors = generate_distinct_colors(node_count)
|
|
3031
|
+
|
|
3032
|
+
elif scheme == 'pastel':
|
|
3033
|
+
for i in range(node_count):
|
|
3034
|
+
hue = i / max(node_count, 1)
|
|
3035
|
+
saturation = 0.4 + np.random.random() * 0.3
|
|
3036
|
+
value = 0.9 + np.random.random() * 0.1
|
|
3037
|
+
colors.append(hsv_to_rgb([hue, saturation, value]))
|
|
3038
|
+
|
|
3039
|
+
elif scheme == 'group' and periodic_elements:
|
|
3040
|
+
colors = _get_group_colors(node_count, periodic_elements)
|
|
3041
|
+
|
|
3042
|
+
elif scheme == 'period' and periodic_elements:
|
|
3043
|
+
colors = _get_period_colors(node_count, periodic_elements)
|
|
3044
|
+
|
|
3045
|
+
elif scheme == 'block' and periodic_elements:
|
|
3046
|
+
colors = _get_block_colors(node_count, periodic_elements)
|
|
3047
|
+
|
|
3048
|
+
elif scheme == 'electronegativity' and periodic_elements:
|
|
3049
|
+
colors = _get_electronegativity_colors(node_count, periodic_elements)
|
|
3050
|
+
|
|
3051
|
+
else:
|
|
3052
|
+
cmap = plt.cm.tab20
|
|
3053
|
+
colors = [cmap(i % 20) for i in range(node_count)]
|
|
3054
|
+
|
|
3055
|
+
return colors
|
|
3056
|
+
|
|
3057
|
+
def _get_group_colors(node_count, periodic_elements):
|
|
3058
|
+
"""Gruplara göre renkler."""
|
|
3059
|
+
colors = []
|
|
3060
|
+
group_colors = {
|
|
3061
|
+
1: (1.0, 0.6, 0.6), # Alkali metals
|
|
3062
|
+
2: (1.0, 0.8, 0.6), # Alkaline earth
|
|
3063
|
+
3: (0.8, 1.0, 0.6), # Group 3
|
|
3064
|
+
4: (0.7, 0.9, 0.8), # Group 4
|
|
3065
|
+
5: (0.6, 0.9, 0.9), # Group 5
|
|
3066
|
+
6: (0.6, 0.8, 1.0), # Group 6
|
|
3067
|
+
7: (0.8, 0.6, 1.0), # Group 7
|
|
3068
|
+
8: (0.9, 0.9, 0.6), # Group 8
|
|
3069
|
+
9: (1.0, 0.9, 0.6), # Group 9
|
|
3070
|
+
10: (0.9, 0.8, 0.7), # Group 10
|
|
3071
|
+
11: (1.0, 0.8, 0.8), # Group 11
|
|
3072
|
+
12: (0.8, 1.0, 0.8), # Group 12
|
|
3073
|
+
13: (0.8, 0.9, 1.0), # Boron group
|
|
3074
|
+
14: (0.9, 0.8, 1.0), # Carbon group
|
|
3075
|
+
15: (1.0, 0.8, 0.9), # Nitrogen group
|
|
3076
|
+
16: (0.8, 1.0, 0.9), # Oxygen group
|
|
3077
|
+
17: (1.0, 0.9, 0.8), # Halogens
|
|
3078
|
+
18: (0.9, 0.9, 0.9), # Noble gases
|
|
3079
|
+
}
|
|
3080
|
+
|
|
3081
|
+
lanthanide_color = (0.7, 1.0, 0.7)
|
|
3082
|
+
actinide_color = (1.0, 0.7, 0.7)
|
|
3083
|
+
|
|
3084
|
+
for node_id in range(1, node_count + 1):
|
|
3085
|
+
if node_id in list(range(57, 72)):
|
|
3086
|
+
colors.append(lanthanide_color)
|
|
3087
|
+
elif node_id in list(range(89, 104)):
|
|
3088
|
+
colors.append(actinide_color)
|
|
3089
|
+
else:
|
|
3090
|
+
group = _determine_group(node_id)
|
|
3091
|
+
colors.append(group_colors.get(group, (0.8, 0.8, 0.8)))
|
|
3092
|
+
|
|
3093
|
+
return colors
|
|
3094
|
+
|
|
3095
|
+
def _determine_group(atomic_num):
|
|
3096
|
+
"""Atom numarasına göre grup belirle."""
|
|
3097
|
+
if atomic_num <= 2:
|
|
3098
|
+
return atomic_num
|
|
3099
|
+
elif atomic_num <= 10:
|
|
3100
|
+
return atomic_num - 2
|
|
3101
|
+
elif atomic_num <= 18:
|
|
3102
|
+
return atomic_num - 10
|
|
3103
|
+
elif atomic_num <= 36:
|
|
3104
|
+
if atomic_num <= 20:
|
|
3105
|
+
return atomic_num - 18
|
|
3106
|
+
elif atomic_num <= 30:
|
|
3107
|
+
return atomic_num - 20
|
|
3108
|
+
else:
|
|
3109
|
+
return atomic_num - 28
|
|
3110
|
+
elif atomic_num <= 54:
|
|
3111
|
+
if atomic_num <= 38:
|
|
3112
|
+
return atomic_num - 36
|
|
3113
|
+
elif atomic_num <= 48:
|
|
3114
|
+
return atomic_num - 38
|
|
3115
|
+
else:
|
|
3116
|
+
return atomic_num - 46
|
|
3117
|
+
else:
|
|
3118
|
+
return 18
|
|
3119
|
+
|
|
3120
|
+
def _get_period_colors(node_count, periodic_elements):
|
|
3121
|
+
"""Periyotlara göre renkler."""
|
|
3122
|
+
colors = []
|
|
3123
|
+
period_colors = [
|
|
3124
|
+
(1.0, 0.7, 0.7), # Period 1
|
|
3125
|
+
(1.0, 0.9, 0.7), # Period 2
|
|
3126
|
+
(0.9, 1.0, 0.7), # Period 3
|
|
3127
|
+
(0.7, 1.0, 0.8), # Period 4
|
|
3128
|
+
(0.7, 0.9, 1.0), # Period 5
|
|
3129
|
+
(0.8, 0.7, 1.0), # Period 6
|
|
3130
|
+
(1.0, 0.7, 0.9), # Period 7
|
|
3131
|
+
]
|
|
3132
|
+
|
|
3133
|
+
for atomic_num in range(1, node_count + 1):
|
|
3134
|
+
if atomic_num <= 2:
|
|
3135
|
+
period = 0
|
|
3136
|
+
elif atomic_num <= 10:
|
|
3137
|
+
period = 1
|
|
3138
|
+
elif atomic_num <= 18:
|
|
3139
|
+
period = 2
|
|
3140
|
+
elif atomic_num <= 36:
|
|
3141
|
+
period = 3
|
|
3142
|
+
elif atomic_num <= 54:
|
|
3143
|
+
period = 4
|
|
3144
|
+
elif atomic_num <= 86:
|
|
3145
|
+
period = 5
|
|
3146
|
+
else:
|
|
3147
|
+
period = 6
|
|
3148
|
+
|
|
3149
|
+
colors.append(period_colors[period % len(period_colors)])
|
|
3150
|
+
|
|
3151
|
+
return colors
|
|
3152
|
+
|
|
3153
|
+
def _get_block_colors(node_count, periodic_elements):
|
|
3154
|
+
"""Bloklara göre renkler."""
|
|
3155
|
+
colors = []
|
|
3156
|
+
|
|
3157
|
+
for atomic_num in range(1, node_count + 1):
|
|
3158
|
+
if atomic_num in [1, 2, 3, 4, 11, 12, 19, 20, 37, 38, 55, 56, 87, 88]:
|
|
3159
|
+
colors.append((1.0, 0.6, 0.6)) # s-block
|
|
3160
|
+
elif atomic_num in (list(range(5, 11)) + list(range(13, 19)) +
|
|
3161
|
+
list(range(31, 37)) + list(range(49, 55)) +
|
|
3162
|
+
list(range(81, 87)) + list(range(113, 119))):
|
|
3163
|
+
colors.append((0.6, 0.8, 1.0)) # p-block
|
|
3164
|
+
elif atomic_num in (list(range(21, 31)) + list(range(39, 49)) +
|
|
3165
|
+
list(range(72, 81)) + list(range(104, 113))):
|
|
3166
|
+
colors.append((0.6, 1.0, 0.6)) # d-block
|
|
3167
|
+
elif atomic_num in list(range(57, 72)) + list(range(89, 104)):
|
|
3168
|
+
colors.append((1.0, 0.6, 1.0)) # f-block
|
|
3169
|
+
else:
|
|
3170
|
+
colors.append((0.8, 0.8, 0.8))
|
|
3171
|
+
|
|
3172
|
+
return colors
|
|
3173
|
+
|
|
3174
|
+
def _get_electronegativity_colors(node_count, periodic_elements):
|
|
3175
|
+
"""Elektronegativiteye göre renkler."""
|
|
3176
|
+
colors = []
|
|
3177
|
+
electronegativity_data = {
|
|
3178
|
+
1: 2.20, 3: 0.98, 4: 1.57, 5: 2.04, 6: 2.55, 7: 3.04, 8: 3.44,
|
|
3179
|
+
9: 3.98, 11: 0.93, 12: 1.31, 13: 1.61, 14: 1.90, 15: 2.19,
|
|
3180
|
+
16: 2.58, 17: 3.16, 19: 0.82, 20: 1.00, 21: 1.36, 22: 1.54,
|
|
3181
|
+
23: 1.63, 24: 1.66, 25: 1.55, 26: 1.83, 27: 1.88, 28: 1.91, 29: 1.90,
|
|
3182
|
+
30: 1.65, 31: 1.81, 32: 2.01, 33: 2.18, 34: 2.55, 35: 2.96,
|
|
3183
|
+
37: 0.82, 38: 0.95, 39: 1.22, 40: 1.33, 41: 1.60, 42: 2.16, 43: 1.90,
|
|
3184
|
+
44: 2.20, 45: 2.28, 46: 2.20, 47: 1.93, 48: 1.69, 49: 1.78, 50: 1.96,
|
|
3185
|
+
51: 2.05, 52: 2.10, 53: 2.66, 55: 0.79, 56: 0.89, 57: 1.10,
|
|
3186
|
+
58: 1.12, 59: 1.13, 60: 1.14, 62: 1.17, 63: 1.20, 64: 1.20, 65: 1.20,
|
|
3187
|
+
66: 1.22, 67: 1.23, 68: 1.24, 69: 1.25, 70: 1.10, 71: 1.27, 72: 1.30,
|
|
3188
|
+
73: 1.50, 74: 2.36, 75: 1.90, 76: 2.20, 77: 2.20, 78: 2.28, 79: 2.54,
|
|
3189
|
+
80: 2.00, 81: 1.62, 82: 1.87, 83: 2.02, 84: 2.00, 85: 2.20,
|
|
3190
|
+
87: 0.70, 88: 0.89, 89: 1.10, 90: 1.30, 91: 1.50, 92: 1.38, 93: 1.36,
|
|
3191
|
+
94: 1.28, 95: 1.30, 96: 1.30, 97: 1.30, 98: 1.30, 99: 1.30, 100: 1.30,
|
|
3192
|
+
101: 1.30, 102: 1.30, 103: 1.30
|
|
3193
|
+
}
|
|
3194
|
+
|
|
3195
|
+
for atomic_num in range(1, node_count + 1):
|
|
3196
|
+
en = electronegativity_data.get(atomic_num, 1.5)
|
|
3197
|
+
if en < 1.0:
|
|
3198
|
+
color = (0.0, 0.0, 0.8)
|
|
3199
|
+
elif en < 1.5:
|
|
3200
|
+
color = (0.0, 0.5, 1.0)
|
|
3201
|
+
elif en < 2.0:
|
|
3202
|
+
color = (0.0, 0.8, 0.8)
|
|
3203
|
+
elif en < 2.5:
|
|
3204
|
+
color = (0.5, 1.0, 0.5)
|
|
3205
|
+
elif en < 3.0:
|
|
3206
|
+
color = (1.0, 0.8, 0.0)
|
|
3207
|
+
elif en < 3.5:
|
|
3208
|
+
color = (1.0, 0.5, 0.0)
|
|
3209
|
+
else:
|
|
3210
|
+
color = (1.0, 0.0, 0.0)
|
|
3211
|
+
|
|
3212
|
+
colors.append(color)
|
|
3213
|
+
|
|
3214
|
+
return colors
|
|
3215
|
+
|
|
3216
|
+
|
|
3217
|
+
def _generate_labels(graph, periodic_elements):
|
|
3218
|
+
"""Etiketleri oluştur."""
|
|
3219
|
+
return {node_id: f"{periodic_elements[node_id][0]}\n{periodic_elements[node_id][1]}"
|
|
3220
|
+
for node_id in graph.nodes()}
|
|
3221
|
+
|
|
3222
|
+
def _get_draw_order(graph, pos, strategy, dimension):
|
|
3223
|
+
"""Çizim sırasını belirle."""
|
|
3224
|
+
if strategy == 'fixed':
|
|
3225
|
+
return list(graph.nodes())
|
|
3226
|
+
elif strategy == 'z_based' and dimension == '3d':
|
|
3227
|
+
return sorted(graph.nodes(), key=lambda n: pos[n][2], reverse=True)
|
|
3228
|
+
elif strategy == 'smart':
|
|
3229
|
+
nodes = list(graph.nodes())
|
|
3230
|
+
if len(nodes) == 0:
|
|
3231
|
+
return nodes
|
|
3232
|
+
|
|
3233
|
+
if dimension == '3d':
|
|
3234
|
+
positions = np.array([pos[n] for n in nodes])
|
|
3235
|
+
center = np.mean(positions, axis=0)
|
|
3236
|
+
distances = np.linalg.norm(positions - center, axis=1)
|
|
3237
|
+
else:
|
|
3238
|
+
positions = np.array([pos[n] for n in nodes])
|
|
3239
|
+
center = np.mean(positions, axis=0)
|
|
3240
|
+
distances = np.linalg.norm(positions - center, axis=1)
|
|
3241
|
+
|
|
3242
|
+
sorted_indices = np.argsort(distances)[::-1]
|
|
3243
|
+
return [nodes[i] for i in sorted_indices]
|
|
3244
|
+
else:
|
|
3245
|
+
return list(graph.nodes())
|
|
3246
|
+
|
|
3247
|
+
def _get_edge_config(style):
|
|
3248
|
+
"""Edge stilini belirle."""
|
|
3249
|
+
configs = {
|
|
3250
|
+
'standard': {'color': 'gray', 'alpha': 0.5, 'width': 1.0},
|
|
3251
|
+
'light': {'color': 'lightgray', 'alpha': 0.3, 'width': 0.8},
|
|
3252
|
+
'bold': {'color': 'black', 'alpha': 0.7, 'width': 2.0},
|
|
3253
|
+
'hidden': {'color': 'none', 'alpha': 0.0, 'width': 0.0}
|
|
3254
|
+
}
|
|
3255
|
+
return configs.get(style, configs['standard'])
|
|
3256
|
+
|
|
3257
|
+
|
|
3258
|
+
def _draw_edges(graph, pos, ax, config, dimension):
|
|
3259
|
+
"""Edge'leri çiz."""
|
|
3260
|
+
if config['color'] == 'none':
|
|
3261
|
+
return
|
|
3262
|
+
|
|
3263
|
+
for u, v in graph.edges():
|
|
3264
|
+
if dimension == '3d':
|
|
3265
|
+
ax.plot(
|
|
3266
|
+
[pos[u][0], pos[v][0]],
|
|
3267
|
+
[pos[u][1], pos[v][1]],
|
|
3268
|
+
[pos[u][2], pos[v][2]],
|
|
3269
|
+
color=config['color'],
|
|
3270
|
+
alpha=config['alpha'],
|
|
3271
|
+
linewidth=config['width'],
|
|
3272
|
+
zorder=1
|
|
3273
|
+
)
|
|
3274
|
+
else:
|
|
3275
|
+
ax.plot(
|
|
3276
|
+
[pos[u][0], pos[v][0]],
|
|
3277
|
+
[pos[u][1], pos[v][1]],
|
|
3278
|
+
color=config['color'],
|
|
3279
|
+
alpha=config['alpha'],
|
|
3280
|
+
linewidth=config['width'],
|
|
3281
|
+
zorder=1
|
|
3282
|
+
)
|
|
3283
|
+
|
|
3284
|
+
def _draw_nodes(graph, pos, colors, ax, node_size, draw_order, dimension, **kwargs):
|
|
3285
|
+
"""Node'ları çiz."""
|
|
3286
|
+
edge_width = kwargs.get('edge_width', 2.0)
|
|
3287
|
+
alpha = kwargs.get('node_alpha', 1.0)
|
|
3288
|
+
|
|
3289
|
+
for node_id in draw_order:
|
|
3290
|
+
if dimension == '3d':
|
|
3291
|
+
x, y, z = pos[node_id]
|
|
3292
|
+
ax.scatter(x, y, z,
|
|
3293
|
+
s=node_size if isinstance(node_size, int) else node_size[node_id-1],
|
|
3294
|
+
c=[colors[node_id-1]],
|
|
3295
|
+
edgecolors='black',
|
|
3296
|
+
linewidths=edge_width,
|
|
3297
|
+
alpha=alpha,
|
|
3298
|
+
depthshade=False if kwargs.get('no_depth_shade', False) else True,
|
|
3299
|
+
zorder=10)
|
|
3300
|
+
else:
|
|
3301
|
+
x, y = pos[node_id]
|
|
3302
|
+
ax.scatter(x, y,
|
|
3303
|
+
s=node_size if isinstance(node_size, int) else node_size[node_id-1],
|
|
3304
|
+
c=[colors[node_id-1]],
|
|
3305
|
+
edgecolors='black',
|
|
3306
|
+
linewidths=edge_width,
|
|
3307
|
+
alpha=alpha,
|
|
3308
|
+
zorder=10)
|
|
3309
|
+
|
|
3310
|
+
def _draw_labels(graph, pos, labels, colors, ax, font_size, position, dimension, **kwargs):
|
|
3311
|
+
"""Etiketleri çiz."""
|
|
3312
|
+
label_offset = kwargs.get('label_offset', 0.0)
|
|
3313
|
+
|
|
3314
|
+
for node_id in graph.nodes():
|
|
3315
|
+
if dimension == '3d':
|
|
3316
|
+
x, y, z = pos[node_id]
|
|
3317
|
+
if position == 'above':
|
|
3318
|
+
z += label_offset
|
|
3319
|
+
elif position == 'below':
|
|
3320
|
+
z -= label_offset
|
|
3321
|
+
elif position == 'right':
|
|
3322
|
+
x += label_offset
|
|
3323
|
+
elif position == 'left':
|
|
3324
|
+
x -= label_offset
|
|
3325
|
+
|
|
3326
|
+
bg_color = colors[node_id-1]
|
|
3327
|
+
text_color = get_text_color_for_bg(bg_color)
|
|
3328
|
+
|
|
3329
|
+
ax.text(x, y, z,
|
|
3330
|
+
labels[node_id],
|
|
3331
|
+
fontsize=font_size if isinstance(font_size, int) else font_size[node_id-1],
|
|
3332
|
+
fontweight='bold',
|
|
3333
|
+
color=text_color,
|
|
3334
|
+
ha='center',
|
|
3335
|
+
va='center',
|
|
3336
|
+
zorder=1000)
|
|
3337
|
+
else:
|
|
3338
|
+
x, y = pos[node_id]
|
|
3339
|
+
if position == 'above':
|
|
3340
|
+
y += label_offset
|
|
3341
|
+
elif position == 'below':
|
|
3342
|
+
y -= label_offset
|
|
3343
|
+
elif position == 'right':
|
|
3344
|
+
x += label_offset
|
|
3345
|
+
elif position == 'left':
|
|
3346
|
+
x -= label_offset
|
|
3347
|
+
|
|
3348
|
+
bg_color = colors[node_id-1]
|
|
3349
|
+
text_color = get_text_color_for_bg(bg_color)
|
|
3350
|
+
|
|
3351
|
+
ax.text(x, y,
|
|
3352
|
+
labels[node_id],
|
|
3353
|
+
fontsize=font_size if isinstance(font_size, int) else font_size[node_id-1],
|
|
3354
|
+
fontweight='bold',
|
|
3355
|
+
color=text_color,
|
|
3356
|
+
ha='center',
|
|
3357
|
+
va='center',
|
|
3358
|
+
zorder=1000)
|
|
3359
|
+
|
|
3360
|
+
def _generate_title(layout_type, node_count, color_scheme, dimension):
|
|
3361
|
+
"""Başlık oluştur."""
|
|
3362
|
+
dim_text = "3D" if dimension == '3d' else "2D"
|
|
3363
|
+
scheme_text = color_scheme.capitalize()
|
|
3364
|
+
|
|
3365
|
+
layout_names = {
|
|
3366
|
+
'3d_helix': '3D Heliks Layout',
|
|
3367
|
+
'2d_linear': '2D Lineer Layout',
|
|
3368
|
+
'2d_circular': 'Dairesel Layout',
|
|
3369
|
+
'3d_spherical': '3D Küresel Layout',
|
|
3370
|
+
'2d_spring': '2D Yay Layout',
|
|
3371
|
+
'2d_grid': '2D Grid Layout'
|
|
3372
|
+
}
|
|
3373
|
+
|
|
3374
|
+
layout_name = layout_names.get(layout_type, layout_type.replace('_', ' ').title())
|
|
3375
|
+
|
|
3376
|
+
title = f"Keçeci Layout ile Periyodik Tablo\n"
|
|
3377
|
+
title += f"{dim_text} {layout_name}\n"
|
|
3378
|
+
title += f"({node_count} Element, {scheme_text} Renk Şeması)"
|
|
3379
|
+
|
|
3380
|
+
return title
|
|
3381
|
+
|
|
3382
|
+
def _configure_axes(ax, pos, dimension, layout_params, **kwargs):
|
|
3383
|
+
"""Eksenleri yapılandır."""
|
|
3384
|
+
ax.set_axis_off()
|
|
3385
|
+
|
|
3386
|
+
if dimension == '3d':
|
|
3387
|
+
elev = kwargs.get('elevation', -25)
|
|
3388
|
+
azim = kwargs.get('azimuth', 15)
|
|
3389
|
+
ax.view_init(elev=elev, azim=azim)
|
|
3390
|
+
|
|
3391
|
+
positions = list(pos.values())
|
|
3392
|
+
if positions:
|
|
3393
|
+
xs, ys, zs = zip(*positions)
|
|
3394
|
+
|
|
3395
|
+
padding = kwargs.get('padding', 0.2)
|
|
3396
|
+
x_range = max(xs) - min(xs)
|
|
3397
|
+
y_range = max(ys) - min(ys)
|
|
3398
|
+
z_range = max(zs) - min(zs)
|
|
3399
|
+
|
|
3400
|
+
x_range = max(x_range, 10)
|
|
3401
|
+
y_range = max(y_range, 10)
|
|
3402
|
+
z_range = max(z_range, 10)
|
|
3403
|
+
|
|
3404
|
+
ax.set_xlim(min(xs) - x_range*padding, max(xs) + x_range*padding)
|
|
3405
|
+
ax.set_ylim(min(ys) - y_range*padding, max(ys) + y_range*padding)
|
|
3406
|
+
ax.set_zlim(min(zs) - z_range*padding, max(zs) + z_range*padding)
|
|
3407
|
+
else:
|
|
3408
|
+
ax.set_aspect('equal')
|
|
3409
|
+
ax.autoscale_view()
|
|
3410
|
+
|
|
3411
|
+
def _add_legend(ax, color_scheme, dimension, periodic_elements):
|
|
3412
|
+
"""Renk şeması açıklaması ekle."""
|
|
3413
|
+
legend_text = f"Renk Şeması: {color_scheme.capitalize()}\n"
|
|
3414
|
+
|
|
3415
|
+
if color_scheme == 'group':
|
|
3416
|
+
legend_text += "• Kırmızı: Alkali Metaller\n"
|
|
3417
|
+
legend_text += "• Turuncu: Toprak Alkali\n"
|
|
3418
|
+
legend_text += "• Yeşil: Geçiş Metalleri\n"
|
|
3419
|
+
legend_text += "• Mavi: Ametaller\n"
|
|
3420
|
+
legend_text += "• Mor: Halojenler\n"
|
|
3421
|
+
legend_text += "• Gri: Soygazlar"
|
|
3422
|
+
|
|
3423
|
+
elif color_scheme == 'period':
|
|
3424
|
+
legend_text += "• Her periyot farklı renk\n"
|
|
3425
|
+
legend_text += "• 7 periyot, 7 renk"
|
|
3426
|
+
|
|
3427
|
+
elif color_scheme == 'block':
|
|
3428
|
+
legend_text += "• Kırmızı: s-blok\n"
|
|
3429
|
+
legend_text += "• Mavi: p-blok\n"
|
|
3430
|
+
legend_text += "• Yeşil: d-blok\n"
|
|
3431
|
+
legend_text += "• Mor: f-blok"
|
|
3432
|
+
|
|
3433
|
+
if dimension == '3d':
|
|
3434
|
+
ax.text2D(0.02, 0.98, legend_text, transform=ax.transAxes,
|
|
3435
|
+
fontsize=9, verticalalignment='top',
|
|
3436
|
+
bbox=dict(boxstyle='round', facecolor='white', alpha=0.8))
|
|
3437
|
+
else:
|
|
3438
|
+
ax.text(0.02, 0.98, legend_text, transform=ax.transAxes,
|
|
3439
|
+
fontsize=9, verticalalignment='top',
|
|
3440
|
+
bbox=dict(boxstyle='round', facecolor='white', alpha=0.8))
|
|
3441
|
+
|
|
3442
|
+
# Ana fonksiyonlar
|
|
3443
|
+
def quick_periodic_table_3d():
|
|
3444
|
+
"""
|
|
3445
|
+
Hızlı 3D periyodik tablo görselleştirmesi.
|
|
3446
|
+
Boş şablonlar oluşmaz.
|
|
3447
|
+
"""
|
|
3448
|
+
# Önceki figürleri temizle
|
|
3449
|
+
plt.close('all')
|
|
3450
|
+
|
|
3451
|
+
# Periyodik tabloyu yükle
|
|
3452
|
+
periodic_elements, _ = generate_complete_periodic_table()
|
|
3453
|
+
|
|
3454
|
+
# Graf oluştur
|
|
3455
|
+
node_count = len(periodic_elements)
|
|
3456
|
+
G = nx.DiGraph()
|
|
3457
|
+
G.add_nodes_from(range(1, node_count + 1))
|
|
3458
|
+
for i in range(1, node_count):
|
|
3459
|
+
G.add_edge(i, i + 1)
|
|
3460
|
+
|
|
3461
|
+
# Tek figür oluştur
|
|
3462
|
+
fig = plt.figure(figsize=(20, 20))
|
|
3463
|
+
ax = fig.add_subplot(111, projection='3d')
|
|
3464
|
+
|
|
3465
|
+
ax, pos = draw_kececi_periodic_table(
|
|
3466
|
+
G,
|
|
3467
|
+
periodic_elements,
|
|
3468
|
+
layout_type='3d_helix',
|
|
3469
|
+
color_scheme='vibrant',
|
|
3470
|
+
node_size=2000,
|
|
3471
|
+
font_size=10,
|
|
3472
|
+
edge_style='light',
|
|
3473
|
+
title="Keçeci Layout ile Periyodik Tablo\n3D Heliks Layout",
|
|
3474
|
+
elevation=-25,
|
|
3475
|
+
azimuth=15
|
|
3476
|
+
)
|
|
3477
|
+
|
|
3478
|
+
plt.tight_layout()
|
|
3479
|
+
plt.show()
|
|
3480
|
+
|
|
3481
|
+
# Kullanıcıya bilgi ver
|
|
3482
|
+
print(f"\n3D periyodik tablo oluşturuldu!")
|
|
3483
|
+
print(f"Toplam {node_count} element gösteriliyor.")
|
|
3484
|
+
print("Grafı kapatmak için figür penceresini kapatın.")
|
|
3485
|
+
|
|
3486
|
+
return ax, pos
|
|
3487
|
+
|
|
3488
|
+
def generate_comparison_figure():
|
|
3489
|
+
"""
|
|
3490
|
+
4 farklı görseli bir figürde karşılaştırma.
|
|
3491
|
+
Boş şablon oluşmaz.
|
|
3492
|
+
"""
|
|
3493
|
+
# Önceki figürleri temizle
|
|
3494
|
+
plt.close('all')
|
|
3495
|
+
|
|
3496
|
+
# Periyodik tabloyu yükle
|
|
3497
|
+
periodic_elements, _ = generate_complete_periodic_table()
|
|
3498
|
+
|
|
3499
|
+
# Graf oluştur
|
|
3500
|
+
node_count = len(periodic_elements)
|
|
3501
|
+
G = nx.DiGraph()
|
|
3502
|
+
G.add_nodes_from(range(1, node_count + 1))
|
|
3503
|
+
for i in range(1, node_count):
|
|
3504
|
+
G.add_edge(i, i + 1)
|
|
3505
|
+
|
|
3506
|
+
# 2x2 grid şeklinde 4 alt figür oluştur
|
|
3507
|
+
fig = plt.figure(figsize=(24, 20))
|
|
3508
|
+
fig.suptitle('Keçeci Layout ile Periyodik Tablo Görselleştirme Karşılaştırması',
|
|
3509
|
+
fontsize=24, fontweight='bold', y=0.98)
|
|
3510
|
+
|
|
3511
|
+
# 1. 3D Heliks Layout
|
|
3512
|
+
ax1 = fig.add_subplot(221, projection='3d')
|
|
3513
|
+
ax1, pos1 = draw_kececi_periodic_table(
|
|
3514
|
+
G,
|
|
3515
|
+
periodic_elements,
|
|
3516
|
+
layout_type='3d_helix',
|
|
3517
|
+
layout_params={'z_spacing': 6.0, 'radius': 20.0, 'turns': 3.0},
|
|
3518
|
+
ax=ax1,
|
|
3519
|
+
color_scheme='vibrant',
|
|
3520
|
+
node_size=1200,
|
|
3521
|
+
font_size=8,
|
|
3522
|
+
edge_style='light',
|
|
3523
|
+
label_position='center',
|
|
3524
|
+
title="3D Heliks Layout\n(Vibrant Renkler)",
|
|
3525
|
+
elevation=-25,
|
|
3526
|
+
azimuth=15,
|
|
3527
|
+
figsize=None # Figsize'ı burada kullanmıyoruz
|
|
3528
|
+
)
|
|
3529
|
+
|
|
3530
|
+
# 2. 2D Linear Layout
|
|
3531
|
+
ax2 = fig.add_subplot(222)
|
|
3532
|
+
ax2, pos2 = draw_kececi_periodic_table(
|
|
3533
|
+
G,
|
|
3534
|
+
periodic_elements,
|
|
3535
|
+
layout_type='2d_linear',
|
|
3536
|
+
layout_params={'primary_spacing': 2.5, 'secondary_spacing': 2.5},
|
|
3537
|
+
ax=ax2,
|
|
3538
|
+
color_scheme='group',
|
|
3539
|
+
dimension='2d',
|
|
3540
|
+
node_size=800,
|
|
3541
|
+
font_size=7,
|
|
3542
|
+
edge_style='standard',
|
|
3543
|
+
show_legend=False,
|
|
3544
|
+
title="2D Linear Layout\n(Grup Renkleri)"
|
|
3545
|
+
)
|
|
3546
|
+
|
|
3547
|
+
# 3. 2D Grid Layout
|
|
3548
|
+
ax3 = fig.add_subplot(223)
|
|
3549
|
+
ax3, pos3 = draw_kececi_periodic_table(
|
|
3550
|
+
G,
|
|
3551
|
+
periodic_elements,
|
|
3552
|
+
layout_type='2d_grid',
|
|
3553
|
+
layout_params={'rows': 9, 'cols': 14, 'spacing': 2.2},
|
|
3554
|
+
ax=ax3,
|
|
3555
|
+
color_scheme='period',
|
|
3556
|
+
dimension='2d',
|
|
3557
|
+
node_size=600,
|
|
3558
|
+
font_size=6,
|
|
3559
|
+
edge_style='light',
|
|
3560
|
+
show_legend=False,
|
|
3561
|
+
title="2D Grid Layout\n(Periyot Renkleri)"
|
|
3562
|
+
)
|
|
3563
|
+
|
|
3564
|
+
# 4. 2D Circular Layout
|
|
3565
|
+
ax4 = fig.add_subplot(224)
|
|
3566
|
+
ax4, pos4 = draw_kececi_periodic_table(
|
|
3567
|
+
G,
|
|
3568
|
+
periodic_elements,
|
|
3569
|
+
layout_type='2d_circular',
|
|
3570
|
+
layout_params={'scale': 2.0},
|
|
3571
|
+
ax=ax4,
|
|
3572
|
+
color_scheme='block',
|
|
3573
|
+
dimension='2d',
|
|
3574
|
+
node_size=800,
|
|
3575
|
+
font_size=7,
|
|
3576
|
+
edge_style='light',
|
|
3577
|
+
show_legend=False,
|
|
3578
|
+
title="2D Dairesel Layout\n(Blok Renkleri)"
|
|
3579
|
+
)
|
|
3580
|
+
|
|
3581
|
+
plt.tight_layout(rect=[0, 0, 1, 0.96])
|
|
3582
|
+
plt.show()
|
|
3583
|
+
|
|
3584
|
+
return fig, (ax1, ax2, ax3, ax4)
|
|
3585
|
+
|
|
3586
|
+
def save_periodic_table_visualization(
|
|
3587
|
+
filename: str = "periodic_table_kececi",
|
|
3588
|
+
format: str = "png",
|
|
3589
|
+
dpi: int = 300,
|
|
3590
|
+
layout_type: str = "3d_helix",
|
|
3591
|
+
color_scheme: str = "vibrant"
|
|
3592
|
+
):
|
|
3593
|
+
"""
|
|
3594
|
+
Periyodik tablo görselleştirmesini kaydet.
|
|
3595
|
+
|
|
3596
|
+
Parameters:
|
|
3597
|
+
-----------
|
|
3598
|
+
filename : str
|
|
3599
|
+
Kaydedilecek dosyanın adı (uzantı olmadan)
|
|
3600
|
+
format : str
|
|
3601
|
+
Kayıt formatı: 'png', 'jpg', 'svg', 'pdf'
|
|
3602
|
+
dpi : int
|
|
3603
|
+
Çözünürlük (dots per inch)
|
|
3604
|
+
layout_type : str
|
|
3605
|
+
Layout tipi
|
|
3606
|
+
color_scheme : str
|
|
3607
|
+
Renk şeması
|
|
3608
|
+
"""
|
|
3609
|
+
# Önceki figürleri temizle
|
|
3610
|
+
plt.close('all')
|
|
3611
|
+
|
|
3612
|
+
# Periyodik tabloyu yükle
|
|
3613
|
+
periodic_elements, _ = generate_complete_periodic_table()
|
|
3614
|
+
|
|
3615
|
+
# Graf oluştur
|
|
3616
|
+
node_count = len(periodic_elements)
|
|
3617
|
+
G = nx.DiGraph()
|
|
3618
|
+
G.add_nodes_from(range(1, node_count + 1))
|
|
3619
|
+
for i in range(1, node_count):
|
|
3620
|
+
G.add_edge(i, i + 1)
|
|
3621
|
+
|
|
3622
|
+
# Figür oluştur
|
|
3623
|
+
if '3d' in layout_type.lower():
|
|
3624
|
+
fig = plt.figure(figsize=(16, 16))
|
|
3625
|
+
ax = fig.add_subplot(111, projection='3d')
|
|
3626
|
+
else:
|
|
3627
|
+
fig = plt.figure(figsize=(14, 14))
|
|
3628
|
+
ax = fig.add_subplot(111)
|
|
3629
|
+
|
|
3630
|
+
# Görseli çiz
|
|
3631
|
+
ax, pos = draw_kececi_periodic_table(
|
|
3632
|
+
G,
|
|
3633
|
+
periodic_elements,
|
|
3634
|
+
layout_type=layout_type,
|
|
3635
|
+
ax=ax,
|
|
3636
|
+
color_scheme=color_scheme,
|
|
3637
|
+
node_size=1500 if '3d' in layout_type.lower() else 1000,
|
|
3638
|
+
font_size=9 if '3d' in layout_type.lower() else 8,
|
|
3639
|
+
edge_style='light',
|
|
3640
|
+
show_legend=True if color_scheme in ['group', 'period', 'block'] else False
|
|
3641
|
+
)
|
|
3642
|
+
|
|
3643
|
+
# Kaydet
|
|
3644
|
+
full_filename = f"{filename}.{format}"
|
|
3645
|
+
plt.savefig(full_filename, dpi=dpi, bbox_inches='tight',
|
|
3646
|
+
facecolor='white', edgecolor='none')
|
|
3647
|
+
plt.close()
|
|
3648
|
+
|
|
3649
|
+
print(f"Görsel kaydedildi: {full_filename}")
|
|
3650
|
+
return full_filename
|
|
3651
|
+
|
|
3652
|
+
def highlight_elements(element_symbols: List[str],
|
|
3653
|
+
highlight_color: Tuple[float, float, float] = (1.0, 0.0, 0.0),
|
|
3654
|
+
**kwargs):
|
|
3655
|
+
"""
|
|
3656
|
+
Belirli elementleri vurgula.
|
|
3657
|
+
|
|
3658
|
+
Parameters:
|
|
3659
|
+
-----------
|
|
3660
|
+
element_symbols : List[str]
|
|
3661
|
+
Vurgulanacak element sembolleri
|
|
3662
|
+
highlight_color : Tuple[float, float, float]
|
|
3663
|
+
Vurgulama rengi (RGB)
|
|
3664
|
+
**kwargs : diğer parametreler draw_kececi_periodic_table'a aktarılır
|
|
3665
|
+
"""
|
|
3666
|
+
# Önceki figürleri temizle
|
|
3667
|
+
plt.close('all')
|
|
3668
|
+
|
|
3669
|
+
# Periyodik tabloyu yükle
|
|
3670
|
+
periodic_elements, _ = generate_complete_periodic_table()
|
|
3671
|
+
|
|
3672
|
+
# Vurgulanacak elementlerin atom numaralarını bul
|
|
3673
|
+
highlight_indices = []
|
|
3674
|
+
element_symbols_found = []
|
|
3675
|
+
valid_symbols = []
|
|
3676
|
+
|
|
3677
|
+
# Element sembolünden isim eşleştirmesi için sabit sözlük
|
|
3678
|
+
# Güncellenmiş Türkçe element isimleri
|
|
3679
|
+
element_name_map = {
|
|
3680
|
+
'H': 'Hidrojen', 'He': 'Helyum', 'Li': 'Lityum', 'Be': 'Berilyum',
|
|
3681
|
+
'B': 'Bor', 'C': 'Karbon', 'N': 'Azot', 'O': 'Oksijen', 'F': 'Flor',
|
|
3682
|
+
'Ne': 'Neon', 'Na': 'Sodyum', 'Mg': 'Magnezyum', 'Al': 'Alüminyum',
|
|
3683
|
+
'Si': 'Silisyum', 'P': 'Fosfor', 'S': 'Kükürt', 'Cl': 'Klor',
|
|
3684
|
+
'Ar': 'Argon', 'K': 'Potasyum', 'Ca': 'Kalsiyum', 'Sc': 'Skandiyum',
|
|
3685
|
+
'Ti': 'Titanyum', 'V': 'Vanadyum', 'Cr': 'Krom', 'Mn': 'Mangan',
|
|
3686
|
+
'Fe': 'Demir', 'Co': 'Kobalt', 'Ni': 'Nikel', 'Cu': 'Bakır',
|
|
3687
|
+
'Zn': 'Çinko', 'Ga': 'Galyum', 'Ge': 'Germanyum', 'As': 'Arsenik',
|
|
3688
|
+
'Se': 'Selenyum', 'Br': 'Brom', 'Kr': 'Kripton', 'Rb': 'Rubidyum',
|
|
3689
|
+
'Sr': 'Stronsiyum', 'Y': 'İtriyum', 'Zr': 'Zirkonyum', 'Nb': 'Niyobyum',
|
|
3690
|
+
'Mo': 'Molibden', 'Tc': 'Teknesyum', 'Ru': 'Rutenyum', 'Rh': 'Rodyum',
|
|
3691
|
+
'Pd': 'Paladyum', 'Ag': 'Gümüş', 'Cd': 'Kadmiyum', 'In': 'İndiyum',
|
|
3692
|
+
'Sn': 'Kalay', 'Sb': 'Antimon', 'Te': 'Tellür', 'I': 'İyot',
|
|
3693
|
+
'Xe': 'Ksenon', 'Cs': 'Sezyum', 'Ba': 'Baryum', 'La': 'Lantan',
|
|
3694
|
+
'Ce': 'Seryum', 'Pr': 'Praseodim', 'Nd': 'Neodimyum', 'Pm': 'Prometyum',
|
|
3695
|
+
'Sm': 'Samaryum', 'Eu': 'Europyum', 'Gd': 'Gadolinyum', 'Tb': 'Terbiyum',
|
|
3696
|
+
'Dy': 'Disprozyum', 'Ho': 'Holmiyum', 'Er': 'Erbiyum', 'Tm': 'Tulyum',
|
|
3697
|
+
'Yb': 'İterbiyum', 'Lu': 'Lutesyum', 'Hf': 'Hafniyum', 'Ta': 'Tantal',
|
|
3698
|
+
'W': 'Tungsten', 'Re': 'Renyum', 'Os': 'Osmiyum', 'Ir': 'İridyum',
|
|
3699
|
+
'Pt': 'Platin', 'Au': 'Altın', 'Hg': 'Cıva', 'Tl': 'Talyum',
|
|
3700
|
+
'Pb': 'Kurşun', 'Bi': 'Bizmut', 'Po': 'Polonyum', 'At': 'Astatin',
|
|
3701
|
+
'Rn': 'Radon', 'Fr': 'Fransiyum', 'Ra': 'Radyum', 'Ac': 'Aktinyum',
|
|
3702
|
+
'Th': 'Toryum', 'Pa': 'Protaktinyum', 'U': 'Uranyum', 'Np': 'Neptünyum',
|
|
3703
|
+
'Pu': 'Plütonyum', 'Am': 'Amerikyum', 'Cm': 'Küriyum', 'Bk': 'Berkelyum',
|
|
3704
|
+
'Cf': 'Kaliforniyum', 'Es': 'Einsteinyum', 'Fm': 'Fermiyum', 'Md': 'Mendelevyum',
|
|
3705
|
+
'No': 'Nobelyum', 'Lr': 'Lawrensiyum', 'Rf': 'Rutherfordiyum', 'Db': 'Dubniyum',
|
|
3706
|
+
'Sg': 'Seaborgiyum', 'Bh': 'Bohriyum', 'Hs': 'Hassiyum', 'Mt': 'Meitneriyum',
|
|
3707
|
+
'Ds': 'Darmstadtiyum', 'Rg': 'Röntgenyum', 'Cn': 'Kopernikyum', 'Nh': 'Nihonyum',
|
|
3708
|
+
'Fl': 'Flerovyum', 'Mc': 'Moscovyum', 'Lv': 'Livermoryum', 'Ts': 'Tenesin',
|
|
3709
|
+
'Og': 'Oganesson/Oganesyan'
|
|
3710
|
+
}
|
|
3711
|
+
|
|
3712
|
+
for input_symbol in element_symbols:
|
|
3713
|
+
input_symbol_clean = str(input_symbol).strip()
|
|
3714
|
+
found = False
|
|
3715
|
+
for atomic_num, (sym, atomic_num_in_tuple) in periodic_elements.items():
|
|
3716
|
+
# Periyodik tablodaki sembol ile kullanıcının girdiği sembolü karşılaştır
|
|
3717
|
+
# Büyük/küçük harf duyarsız karşılaştırma
|
|
3718
|
+
if sym.upper() == input_symbol_clean.upper():
|
|
3719
|
+
highlight_indices.append(atomic_num - 1) # 0-based index
|
|
3720
|
+
# Orijinal sembolü (büyük/küçük harf korunarak) ekle
|
|
3721
|
+
element_symbols_found.append(sym) # Burada sym kullanıyoruz (periyodik tablodaki orijinal)
|
|
3722
|
+
valid_symbols.append(sym) # Orijinal sembolü sakla
|
|
3723
|
+
found = True
|
|
3724
|
+
break
|
|
3725
|
+
|
|
3726
|
+
if not found:
|
|
3727
|
+
print(f"Uyarı: '{input_symbol_clean}' elementi bulunamadı!")
|
|
3728
|
+
|
|
3729
|
+
if not highlight_indices:
|
|
3730
|
+
print("Vurgulanacak geçerli element bulunamadı!")
|
|
3731
|
+
return None, None
|
|
3732
|
+
|
|
3733
|
+
# Element isimlerini bul
|
|
3734
|
+
element_names = [element_name_map.get(sym, sym) for sym in element_symbols_found]
|
|
3735
|
+
|
|
3736
|
+
print(f"Vurgulanan elementler: {', '.join(element_names)}")
|
|
3737
|
+
|
|
3738
|
+
# Graf oluştur
|
|
3739
|
+
node_count = len(periodic_elements)
|
|
3740
|
+
G = nx.DiGraph()
|
|
3741
|
+
G.add_nodes_from(range(1, node_count + 1))
|
|
3742
|
+
for i in range(1, node_count):
|
|
3743
|
+
G.add_edge(i, i + 1)
|
|
3744
|
+
|
|
3745
|
+
# Özel renk şeması oluştur
|
|
3746
|
+
colors = []
|
|
3747
|
+
for i in range(1, node_count + 1):
|
|
3748
|
+
if (i - 1) in highlight_indices:
|
|
3749
|
+
colors.append(highlight_color)
|
|
3750
|
+
else:
|
|
3751
|
+
# Gri tonlarında diğer elementler
|
|
3752
|
+
colors.append((0.9, 0.9, 0.9))
|
|
3753
|
+
|
|
3754
|
+
# Layout tipini belirle
|
|
3755
|
+
layout_type = kwargs.get('layout_type', '3d_helix')
|
|
3756
|
+
dimension = '3d' if '3d' in layout_type.lower() else '2d'
|
|
3757
|
+
|
|
3758
|
+
# Figür oluştur
|
|
3759
|
+
if dimension == '3d':
|
|
3760
|
+
fig = plt.figure(figsize=(16, 16))
|
|
3761
|
+
ax = fig.add_subplot(111, projection='3d')
|
|
3762
|
+
else:
|
|
3763
|
+
fig = plt.figure(figsize=(14, 14))
|
|
3764
|
+
ax = fig.add_subplot(111)
|
|
3765
|
+
|
|
3766
|
+
# Layout hesapla
|
|
3767
|
+
layout_params = kwargs.get('layout_params', {})
|
|
3768
|
+
pos = _calculate_layout(G, layout_type, layout_params, dimension, node_count)
|
|
3769
|
+
|
|
3770
|
+
# Özel etiketler oluştur
|
|
3771
|
+
custom_labels = _generate_labels(G, periodic_elements)
|
|
3772
|
+
|
|
3773
|
+
# Node boyutlarını ayarla (vurgulananlar daha büyük)
|
|
3774
|
+
node_sizes = []
|
|
3775
|
+
for i in range(1, node_count + 1):
|
|
3776
|
+
if (i - 1) in highlight_indices:
|
|
3777
|
+
node_sizes.append(kwargs.get('highlight_size', 2000))
|
|
3778
|
+
else:
|
|
3779
|
+
node_sizes.append(kwargs.get('normal_size', 800))
|
|
3780
|
+
|
|
3781
|
+
# Font boyutlarını ayarla
|
|
3782
|
+
font_sizes = []
|
|
3783
|
+
for i in range(1, node_count + 1):
|
|
3784
|
+
if (i - 1) in highlight_indices:
|
|
3785
|
+
font_sizes.append(kwargs.get('highlight_font_size', 12))
|
|
3786
|
+
else:
|
|
3787
|
+
font_sizes.append(kwargs.get('normal_font_size', 7))
|
|
3788
|
+
|
|
3789
|
+
# Çizim sırasını belirle
|
|
3790
|
+
draw_order = _get_draw_order(G, pos, 'smart', dimension)
|
|
3791
|
+
|
|
3792
|
+
# Edge stilini al
|
|
3793
|
+
edge_config = _get_edge_config(kwargs.get('edge_style', 'light'))
|
|
3794
|
+
|
|
3795
|
+
# Çiz
|
|
3796
|
+
_draw_edges(G, pos, ax, edge_config, dimension)
|
|
3797
|
+
_draw_nodes(G, pos, colors, ax, node_sizes, draw_order, dimension,
|
|
3798
|
+
edge_width=kwargs.get('edge_width', 2.0),
|
|
3799
|
+
node_alpha=kwargs.get('node_alpha', 1.0))
|
|
3800
|
+
|
|
3801
|
+
# Etiketleri çiz
|
|
3802
|
+
_draw_labels(G, pos, custom_labels, colors, ax, font_sizes,
|
|
3803
|
+
kwargs.get('label_position', 'center'), dimension,
|
|
3804
|
+
label_offset=kwargs.get('label_offset', 0.0))
|
|
3805
|
+
|
|
3806
|
+
# Başlık
|
|
3807
|
+
title = kwargs.get('title')
|
|
3808
|
+
if title is None:
|
|
3809
|
+
# Orijinal sembolleri (büyük/küçük harf korunarak) kullan
|
|
3810
|
+
element_symbols_str = ', '.join(element_symbols_found)
|
|
3811
|
+
element_names_str = ', '.join(element_names)
|
|
3812
|
+
title = f"Keçeci Layout ile Vurgulanan Elementler\nHighlighted Elements with Keçeci Layout:\n: {element_names_str} ({element_symbols_str})\n"
|
|
3813
|
+
title += f"Layout: {layout_type}, Toplam/Total {node_count} Element"
|
|
3814
|
+
|
|
3815
|
+
ax.set_title(title, fontsize=18, fontweight='bold', pad=20)
|
|
3816
|
+
|
|
3817
|
+
# Eksen ayarları
|
|
3818
|
+
_configure_axes(ax, pos, dimension, layout_params,
|
|
3819
|
+
elevation=kwargs.get('elevation', -25),
|
|
3820
|
+
azimuth=kwargs.get('azimuth', 15))
|
|
3821
|
+
|
|
3822
|
+
plt.tight_layout()
|
|
3823
|
+
|
|
3824
|
+
# Açıklama ekle
|
|
3825
|
+
if dimension == '3d':
|
|
3826
|
+
ax.text2D(0.02, 0.98,
|
|
3827
|
+
f"Kırmızı: {', '.join(element_names)}\nGri: Diğer elementler",
|
|
3828
|
+
transform=ax.transAxes,
|
|
3829
|
+
fontsize=10, verticalalignment='top',
|
|
3830
|
+
bbox=dict(boxstyle='round', facecolor='white', alpha=0.8))
|
|
3831
|
+
else:
|
|
3832
|
+
ax.text(0.02, 0.98,
|
|
3833
|
+
f"Kırmızı: {', '.join(element_names)}\nGri: Diğer elementler",
|
|
3834
|
+
transform=ax.transAxes,
|
|
3835
|
+
fontsize=10, verticalalignment='top',
|
|
3836
|
+
bbox=dict(boxstyle='round', facecolor='white', alpha=0.8))
|
|
3837
|
+
|
|
3838
|
+
plt.show()
|
|
3839
|
+
|
|
3840
|
+
print(f"\nVurgulama tamamlandı!")
|
|
3841
|
+
print(f"Toplam {node_count} element, {len(highlight_indices)} element vurgulandı.")
|
|
3842
|
+
print("Grafı kapatmak için figür penceresini kapatın.")
|
|
3843
|
+
|
|
3844
|
+
return ax, pos
|
|
3845
|
+
|
|
3846
|
+
def demo_periodic_table_visualizations():
|
|
3847
|
+
"""
|
|
3848
|
+
Periyodik tablo görselleştirmelerinin demo gösterimi.
|
|
3849
|
+
Her görsel ayrı ayrı gösterilir, boş şablonlar oluşmaz.
|
|
3850
|
+
"""
|
|
3851
|
+
# Tüm figürleri temizle
|
|
3852
|
+
plt.close('all')
|
|
3853
|
+
|
|
3854
|
+
# Periyodik tabloyu yükle
|
|
3855
|
+
print("Periyodik tablo yükleniyor...")
|
|
3856
|
+
periodic_elements, _ = generate_complete_periodic_table()
|
|
3857
|
+
|
|
3858
|
+
# Graf oluştur
|
|
3859
|
+
node_count = len(periodic_elements)
|
|
3860
|
+
G = nx.DiGraph()
|
|
3861
|
+
G.add_nodes_from(range(1, node_count + 1))
|
|
3862
|
+
for i in range(1, node_count):
|
|
3863
|
+
G.add_edge(i, i + 1)
|
|
3864
|
+
|
|
3865
|
+
print("=" * 70)
|
|
3866
|
+
print("PERİYODİK TABLO GÖRSELLEŞTİRME DEMOLARI")
|
|
3867
|
+
print("=" * 70)
|
|
3868
|
+
print(f"Toplam {node_count} element gösterilecek.")
|
|
3869
|
+
print("Her görsel 5 saniye boyunca gösterilecek...")
|
|
3870
|
+
|
|
3871
|
+
demos = [
|
|
3872
|
+
{
|
|
3873
|
+
"name": "3D Heliks Layout",
|
|
3874
|
+
"layout_type": "3d_helix",
|
|
3875
|
+
"color_scheme": "vibrant",
|
|
3876
|
+
"params": {'z_spacing': 8.0, 'radius': 25.0, 'turns': 3.0},
|
|
3877
|
+
"figsize": (20, 20),
|
|
3878
|
+
"projection": '3d'
|
|
3879
|
+
},
|
|
3880
|
+
{
|
|
3881
|
+
"name": "2D Linear Layout",
|
|
3882
|
+
"layout_type": "2d_linear",
|
|
3883
|
+
"color_scheme": "group",
|
|
3884
|
+
"params": {'primary_spacing': 3.0, 'secondary_spacing': 3.0},
|
|
3885
|
+
"figsize": (16, 16),
|
|
3886
|
+
"projection": None
|
|
3887
|
+
},
|
|
3888
|
+
{
|
|
3889
|
+
"name": "2D Grid Layout",
|
|
3890
|
+
"layout_type": "2d_grid",
|
|
3891
|
+
"color_scheme": "period",
|
|
3892
|
+
"params": {'rows': 9, 'cols': 14, 'spacing': 3.0},
|
|
3893
|
+
"figsize": (18, 18),
|
|
3894
|
+
"projection": None
|
|
3895
|
+
},
|
|
3896
|
+
{
|
|
3897
|
+
"name": "2D Circular Layout",
|
|
3898
|
+
"layout_type": "2d_circular",
|
|
3899
|
+
"color_scheme": "block",
|
|
3900
|
+
"params": {'scale': 2.0},
|
|
3901
|
+
"figsize": (16, 16),
|
|
3902
|
+
"projection": None
|
|
3903
|
+
}
|
|
3904
|
+
]
|
|
3905
|
+
|
|
3906
|
+
for i, demo in enumerate(demos, 1):
|
|
3907
|
+
print(f"\n{i}. {demo['name']} ({demo['color_scheme']} renkler) oluşturuluyor...")
|
|
3908
|
+
|
|
3909
|
+
if demo['projection'] == '3d':
|
|
3910
|
+
fig = plt.figure(figsize=demo['figsize'])
|
|
3911
|
+
ax = fig.add_subplot(111, projection='3d')
|
|
3912
|
+
else:
|
|
3913
|
+
fig = plt.figure(figsize=demo['figsize'])
|
|
3914
|
+
ax = fig.add_subplot(111)
|
|
3915
|
+
|
|
3916
|
+
ax, pos = draw_kececi_periodic_table(
|
|
3917
|
+
G,
|
|
3918
|
+
periodic_elements,
|
|
3919
|
+
layout_type=demo['layout_type'],
|
|
3920
|
+
layout_params=demo['params'],
|
|
3921
|
+
ax=ax,
|
|
3922
|
+
color_scheme=demo['color_scheme'],
|
|
3923
|
+
node_size=2000 if demo['projection'] == '3d' else 1000,
|
|
3924
|
+
font_size=10 if demo['projection'] == '3d' else 8,
|
|
3925
|
+
edge_style='light',
|
|
3926
|
+
show_legend=True if demo['color_scheme'] in ['group', 'period', 'block'] else False,
|
|
3927
|
+
title=f"Keçeci Layout ile\n {i}/4: {demo['name']}\n{demo['color_scheme'].capitalize()} Renk Şeması"
|
|
3928
|
+
)
|
|
3929
|
+
|
|
3930
|
+
plt.tight_layout()
|
|
3931
|
+
plt.show(block=False)
|
|
3932
|
+
plt.pause(5)
|
|
3933
|
+
plt.close(fig)
|
|
3934
|
+
|
|
3935
|
+
print("\n" + "=" * 70)
|
|
3936
|
+
print("TÜM DEMOLAR TAMAMLANDI!")
|
|
3937
|
+
print("=" * 70)
|
|
3938
|
+
|
|
3939
|
+
return True
|
|
3940
|
+
|
|
3941
|
+
def get_element_info(element_symbol: str) -> Dict[str, Any]:
|
|
3942
|
+
"""
|
|
3943
|
+
Element sembolünden element bilgilerini getir.
|
|
3944
|
+
|
|
3945
|
+
Parameters:
|
|
3946
|
+
-----------
|
|
3947
|
+
element_symbol : str
|
|
3948
|
+
Element sembolü (örn: 'H', 'He', 'Fe')
|
|
3949
|
+
|
|
3950
|
+
Returns:
|
|
3951
|
+
--------
|
|
3952
|
+
dict : Element bilgileri
|
|
3953
|
+
"""
|
|
3954
|
+
# Periyodik tabloyu yükle
|
|
3955
|
+
periodic_elements, element_dict = generate_complete_periodic_table()
|
|
3956
|
+
|
|
3957
|
+
# Element sembolünden atom numarasını bul
|
|
3958
|
+
atomic_num_found = None
|
|
3959
|
+
original_symbol = None
|
|
3960
|
+
|
|
3961
|
+
for atomic_num, (sym, atomic_num_in_tuple) in periodic_elements.items():
|
|
3962
|
+
if sym.upper() == element_symbol.upper():
|
|
3963
|
+
atomic_num_found = atomic_num
|
|
3964
|
+
original_symbol = sym # Orijinal sembolü sakla
|
|
3965
|
+
break
|
|
3966
|
+
|
|
3967
|
+
if atomic_num_found is None:
|
|
3968
|
+
raise ValueError(f"Element bulunamadı: {element_symbol}")
|
|
3969
|
+
|
|
3970
|
+
# Element ismini bul - Güncellenmiş Türkçe isimler
|
|
3971
|
+
element_name_map = {
|
|
3972
|
+
'H': 'Hidrojen', 'He': 'Helyum', 'Li': 'Lityum', 'Be': 'Berilyum',
|
|
3973
|
+
'B': 'Bor', 'C': 'Karbon', 'N': 'Azot', 'O': 'Oksijen', 'F': 'Flor',
|
|
3974
|
+
'Ne': 'Neon', 'Na': 'Sodyum', 'Mg': 'Magnezyum', 'Al': 'Alüminyum',
|
|
3975
|
+
'Si': 'Silisyum', 'P': 'Fosfor', 'S': 'Kükürt', 'Cl': 'Klor',
|
|
3976
|
+
'Ar': 'Argon', 'K': 'Potasyum', 'Ca': 'Kalsiyum', 'Sc': 'Skandiyum',
|
|
3977
|
+
'Ti': 'Titanyum', 'V': 'Vanadyum', 'Cr': 'Krom', 'Mn': 'Mangan',
|
|
3978
|
+
'Fe': 'Demir', 'Co': 'Kobalt', 'Ni': 'Nikel', 'Cu': 'Bakır',
|
|
3979
|
+
'Zn': 'Çinko', 'Ga': 'Galyum', 'Ge': 'Germanyum', 'As': 'Arsenik',
|
|
3980
|
+
'Se': 'Selenyum', 'Br': 'Brom', 'Kr': 'Kripton', 'Rb': 'Rubidyum',
|
|
3981
|
+
'Sr': 'Stronsiyum', 'Y': 'İtriyum', 'Zr': 'Zirkonyum', 'Nb': 'Niyobyum',
|
|
3982
|
+
'Mo': 'Molibden', 'Tc': 'Teknesyum', 'Ru': 'Rutenyum', 'Rh': 'Rodyum',
|
|
3983
|
+
'Pd': 'Paladyum', 'Ag': 'Gümüş', 'Cd': 'Kadmiyum', 'In': 'İndiyum',
|
|
3984
|
+
'Sn': 'Kalay', 'Sb': 'Antimon', 'Te': 'Tellür', 'I': 'İyot',
|
|
3985
|
+
'Xe': 'Ksenon', 'Cs': 'Sezyum', 'Ba': 'Baryum', 'La': 'Lantan',
|
|
3986
|
+
'Ce': 'Seryum', 'Pr': 'Praseodim', 'Nd': 'Neodimyum', 'Pm': 'Prometyum',
|
|
3987
|
+
'Sm': 'Samaryum', 'Eu': 'Europyum', 'Gd': 'Gadolinyum', 'Tb': 'Terbiyum',
|
|
3988
|
+
'Dy': 'Disprozyum', 'Ho': 'Holmiyum', 'Er': 'Erbiyum', 'Tm': 'Tulyum',
|
|
3989
|
+
'Yb': 'İterbiyum', 'Lu': 'Lutesyum', 'Hf': 'Hafniyum', 'Ta': 'Tantal',
|
|
3990
|
+
'W': 'Tungsten', 'Re': 'Renyum', 'Os': 'Osmiyum', 'Ir': 'İridyum',
|
|
3991
|
+
'Pt': 'Platin', 'Au': 'Altın', 'Hg': 'Cıva', 'Tl': 'Talyum',
|
|
3992
|
+
'Pb': 'Kurşun', 'Bi': 'Bizmut', 'Po': 'Polonyum', 'At': 'Astatin',
|
|
3993
|
+
'Rn': 'Radon', 'Fr': 'Fransiyum', 'Ra': 'Radyum', 'Ac': 'Aktinyum',
|
|
3994
|
+
'Th': 'Toryum', 'Pa': 'Protaktinyum', 'U': 'Uranyum', 'Np': 'Neptünyum',
|
|
3995
|
+
'Pu': 'Plütonyum', 'Am': 'Amerikyum', 'Cm': 'Küriyum', 'Bk': 'Berkelyum',
|
|
3996
|
+
'Cf': 'Kaliforniyum', 'Es': 'Einsteinyum', 'Fm': 'Fermiyum', 'Md': 'Mendelevyum',
|
|
3997
|
+
'No': 'Nobelyum', 'Lr': 'Lawrensiyum', 'Rf': 'Rutherfordiyum', 'Db': 'Dubniyum',
|
|
3998
|
+
'Sg': 'Seaborgiyum', 'Bh': 'Bohriyum', 'Hs': 'Hassiyum', 'Mt': 'Meitneriyum',
|
|
3999
|
+
'Ds': 'Darmstadtiyum', 'Rg': 'Röntgenyum', 'Cn': 'Kopernikyum', 'Nh': 'Nihonyum',
|
|
4000
|
+
'Fl': 'Flerovyum', 'Mc': 'Moscovyum', 'Lv': 'Livermoryum', 'Ts': 'Tenesin',
|
|
4001
|
+
'Og': 'Oganesson/Oganesyan'
|
|
4002
|
+
}
|
|
4003
|
+
|
|
4004
|
+
element_name = element_name_map.get(original_symbol.upper(), original_symbol)
|
|
4005
|
+
|
|
4006
|
+
# Yuri Oganessian hakkında ek bilgi
|
|
4007
|
+
additional_info = ""
|
|
4008
|
+
if original_symbol.upper() == 'OG':
|
|
4009
|
+
additional_info = "\n Not: Element, Rus-Armeni fizikçi Yuri Oganessian (Юрий Оганесян) onuruna adlandırılmıştır."
|
|
4010
|
+
|
|
4011
|
+
# Grup ve periyot bilgilerini hesapla
|
|
4012
|
+
group = _determine_group(atomic_num_found)
|
|
4013
|
+
|
|
4014
|
+
# Periyot hesapla
|
|
4015
|
+
if atomic_num_found <= 2:
|
|
4016
|
+
period = 1
|
|
4017
|
+
elif atomic_num_found <= 10:
|
|
4018
|
+
period = 2
|
|
4019
|
+
elif atomic_num_found <= 18:
|
|
4020
|
+
period = 3
|
|
4021
|
+
elif atomic_num_found <= 36:
|
|
4022
|
+
period = 4
|
|
4023
|
+
elif atomic_num_found <= 54:
|
|
4024
|
+
period = 5
|
|
4025
|
+
elif atomic_num_found <= 86:
|
|
4026
|
+
period = 6
|
|
4027
|
+
else:
|
|
4028
|
+
period = 7
|
|
4029
|
+
|
|
4030
|
+
# Blok bilgisi
|
|
4031
|
+
if atomic_num_found in [1, 2, 3, 4, 11, 12, 19, 20, 37, 38, 55, 56, 87, 88]:
|
|
4032
|
+
block = "s"
|
|
4033
|
+
elif atomic_num_found in (list(range(5, 11)) + list(range(13, 19)) +
|
|
4034
|
+
list(range(31, 37)) + list(range(49, 55)) +
|
|
4035
|
+
list(range(81, 87)) + list(range(113, 119))):
|
|
4036
|
+
block = "p"
|
|
4037
|
+
elif atomic_num_found in (list(range(21, 31)) + list(range(39, 49)) +
|
|
4038
|
+
list(range(72, 81)) + list(range(104, 113))):
|
|
4039
|
+
block = "d"
|
|
4040
|
+
elif atomic_num_found in list(range(57, 72)) + list(range(89, 104)):
|
|
4041
|
+
block = "f"
|
|
4042
|
+
else:
|
|
4043
|
+
block = "unknown"
|
|
4044
|
+
|
|
4045
|
+
# Elektronegativite verisi
|
|
4046
|
+
electronegativity_data = {
|
|
4047
|
+
1: 2.20, 2: None, 3: 0.98, 4: 1.57, 5: 2.04, 6: 2.55, 7: 3.04, 8: 3.44,
|
|
4048
|
+
9: 3.98, 10: None, 11: 0.93, 12: 1.31, 13: 1.61, 14: 1.90, 15: 2.19,
|
|
4049
|
+
16: 2.58, 17: 3.16, 18: None, 19: 0.82, 20: 1.00, 21: 1.36, 22: 1.54,
|
|
4050
|
+
23: 1.63, 24: 1.66, 25: 1.55, 26: 1.83, 27: 1.88, 28: 1.91, 29: 1.90,
|
|
4051
|
+
30: 1.65, 31: 1.81, 32: 2.01, 33: 2.18, 34: 2.55, 35: 2.96, 36: None,
|
|
4052
|
+
37: 0.82, 38: 0.95, 39: 1.22, 40: 1.33, 41: 1.60, 42: 2.16, 43: 1.90,
|
|
4053
|
+
44: 2.20, 45: 2.28, 46: 2.20, 47: 1.93, 48: 1.69, 49: 1.78, 50: 1.96,
|
|
4054
|
+
51: 2.05, 52: 2.10, 53: 2.66, 54: None, 55: 0.79, 56: 0.89, 57: 1.10,
|
|
4055
|
+
58: 1.12, 59: 1.13, 60: 1.14, 61: 1.13, 62: 1.17, 63: 1.20, 64: 1.20,
|
|
4056
|
+
65: 1.20, 66: 1.22, 67: 1.23, 68: 1.24, 69: 1.25, 70: 1.10, 71: 1.27,
|
|
4057
|
+
72: 1.30, 73: 1.50, 74: 2.36, 75: 1.90, 76: 2.20, 77: 2.20, 78: 2.28,
|
|
4058
|
+
79: 2.54, 80: 2.00, 81: 1.62, 82: 1.87, 83: 2.02, 84: 2.00, 85: 2.20,
|
|
4059
|
+
86: None, 87: 0.70, 88: 0.89, 89: 1.10, 90: 1.30, 91: 1.50, 92: 1.38,
|
|
4060
|
+
93: 1.36, 94: 1.28, 95: 1.30, 96: 1.30, 97: 1.30, 98: 1.30, 99: 1.30,
|
|
4061
|
+
100: 1.30, 101: 1.30, 102: 1.30, 103: 1.30, 118: None # Oganesson
|
|
4062
|
+
}
|
|
4063
|
+
|
|
4064
|
+
result = {
|
|
4065
|
+
'atomic_number': atomic_num_found,
|
|
4066
|
+
'symbol': original_symbol, # Orijinal sembolü döndür
|
|
4067
|
+
'name': element_name,
|
|
4068
|
+
'group': group,
|
|
4069
|
+
'period': period,
|
|
4070
|
+
'block': block,
|
|
4071
|
+
'electronegativity': electronegativity_data.get(atomic_num_found, None)
|
|
4072
|
+
}
|
|
4073
|
+
|
|
4074
|
+
# Ek bilgiyi de döndürelim
|
|
4075
|
+
result['additional_info'] = additional_info
|
|
4076
|
+
|
|
4077
|
+
return result
|
|
4078
|
+
|
|
4079
|
+
def custom_visualization():
|
|
4080
|
+
"""
|
|
4081
|
+
Özelleştirilmiş görselleştirme menüsü.
|
|
4082
|
+
"""
|
|
4083
|
+
print("\n" + "=" * 70)
|
|
4084
|
+
print("Custom Visualization")
|
|
4085
|
+
print("=" * 70)
|
|
4086
|
+
|
|
4087
|
+
# Periyodik tabloyu yükle
|
|
4088
|
+
periodic_elements, _ = generate_complete_periodic_table()
|
|
4089
|
+
|
|
4090
|
+
# Graf oluştur
|
|
4091
|
+
node_count = len(periodic_elements)
|
|
4092
|
+
G = nx.DiGraph()
|
|
4093
|
+
G.add_nodes_from(range(1, node_count + 1))
|
|
4094
|
+
for i in range(1, node_count):
|
|
4095
|
+
G.add_edge(i, i + 1)
|
|
4096
|
+
|
|
4097
|
+
# Layout seçenekleri
|
|
4098
|
+
layouts = {
|
|
4099
|
+
'1': ('3d_helix', '3D Heliks Layout'),
|
|
4100
|
+
'2': ('2d_linear', '2D Linear Layout'),
|
|
4101
|
+
'3': ('2d_grid', '2D Grid Layout'),
|
|
4102
|
+
'4': ('2d_circular', '2D Dairesel Layout'),
|
|
4103
|
+
'5': ('2d_spring', '2D Yay Layout')
|
|
4104
|
+
}
|
|
4105
|
+
|
|
4106
|
+
print("\nLayout Tipleri:")
|
|
4107
|
+
for key, (_, name) in layouts.items():
|
|
4108
|
+
print(f"{key}. {name}")
|
|
4109
|
+
|
|
4110
|
+
layout_choice = input("\nLayout tipi seçin (1-5): ").strip()
|
|
4111
|
+
if layout_choice not in layouts:
|
|
4112
|
+
print("Varsayılan olarak 3D Heliks seçildi.")
|
|
4113
|
+
layout_type = '3d_helix'
|
|
4114
|
+
else:
|
|
4115
|
+
layout_type, layout_name = layouts[layout_choice]
|
|
4116
|
+
|
|
4117
|
+
# Renk şeması seçenekleri
|
|
4118
|
+
color_schemes = {
|
|
4119
|
+
'1': 'vibrant',
|
|
4120
|
+
'2': 'distinct',
|
|
4121
|
+
'3': 'pastel',
|
|
4122
|
+
'4': 'group',
|
|
4123
|
+
'5': 'period',
|
|
4124
|
+
'6': 'block'
|
|
4125
|
+
}
|
|
4126
|
+
|
|
4127
|
+
print("\nRenk Şemaları:")
|
|
4128
|
+
print("1. Vibrant (Canlı renkler)")
|
|
4129
|
+
print("2. Distinct (Farklı renkler)")
|
|
4130
|
+
print("3. Pastel (Pastel tonlar)")
|
|
4131
|
+
print("4. Group (Gruplara göre)")
|
|
4132
|
+
print("5. Period (Periyotlara göre)")
|
|
4133
|
+
print("6. Block (Bloklara göre)")
|
|
4134
|
+
|
|
4135
|
+
color_choice = input("\nRenk şeması seçin (1-6): ").strip()
|
|
4136
|
+
if color_choice not in color_schemes:
|
|
4137
|
+
print("Varsayılan olarak Vibrant seçildi.")
|
|
4138
|
+
color_scheme = 'vibrant'
|
|
4139
|
+
else:
|
|
4140
|
+
color_scheme = color_schemes[color_choice]
|
|
4141
|
+
|
|
4142
|
+
# Boyut seçimi
|
|
4143
|
+
try:
|
|
4144
|
+
node_size = int(input(f"\nNode boyutu (varsayılan: 1600): ") or "1600")
|
|
4145
|
+
except:
|
|
4146
|
+
node_size = 1600
|
|
4147
|
+
|
|
4148
|
+
try:
|
|
4149
|
+
font_size = int(input(f"Font boyutu (varsayılan: 10): ") or "10")
|
|
4150
|
+
except:
|
|
4151
|
+
font_size = 10
|
|
4152
|
+
|
|
4153
|
+
# 3D için özel parametreler
|
|
4154
|
+
if '3d' in layout_type:
|
|
4155
|
+
fig = plt.figure(figsize=(20, 20))
|
|
4156
|
+
ax = fig.add_subplot(111, projection='3d')
|
|
4157
|
+
else:
|
|
4158
|
+
fig = plt.figure(figsize=(16, 16))
|
|
4159
|
+
ax = fig.add_subplot(111)
|
|
4160
|
+
|
|
4161
|
+
# Özel başlık
|
|
4162
|
+
custom_title = input("\nÖzel başlık (boş bırakırsanız otomatik oluşturulur): ").strip()
|
|
4163
|
+
|
|
4164
|
+
# Çizim yap
|
|
4165
|
+
ax, pos = draw_kececi_periodic_table(
|
|
4166
|
+
G,
|
|
4167
|
+
periodic_elements,
|
|
4168
|
+
layout_type=layout_type,
|
|
4169
|
+
ax=ax,
|
|
4170
|
+
color_scheme=color_scheme,
|
|
4171
|
+
node_size=node_size,
|
|
4172
|
+
font_size=font_size,
|
|
4173
|
+
title=custom_title if custom_title else None,
|
|
4174
|
+
show_legend=(color_scheme in ['group', 'period', 'block'])
|
|
4175
|
+
)
|
|
4176
|
+
|
|
4177
|
+
plt.tight_layout()
|
|
4178
|
+
plt.show()
|
|
4179
|
+
|
|
4180
|
+
print(f"\n{layout_name} ile {color_scheme} renk şeması başarıyla oluşturuldu!")
|
|
4181
|
+
return ax, pos
|
|
4182
|
+
|
|
4183
|
+
def debug_periodic_table_structure():
|
|
4184
|
+
"""Periyodik tablo veri yapısını kontrol et."""
|
|
4185
|
+
print("Periyodik tablo veri yapısı kontrol ediliyor...")
|
|
4186
|
+
periodic_elements, _ = generate_complete_periodic_table()
|
|
4187
|
+
|
|
4188
|
+
print(f"\nToplam element sayısı: {len(periodic_elements)}")
|
|
4189
|
+
|
|
4190
|
+
# İlk 5 elementi göster
|
|
4191
|
+
print("\nİlk 5 element:")
|
|
4192
|
+
for i, (atomic_num, value) in enumerate(list(periodic_elements.items())[:5]):
|
|
4193
|
+
print(f" Atom numarası {atomic_num}:")
|
|
4194
|
+
print(f" Değer: {value}")
|
|
4195
|
+
print(f" Tip: {type(value)}")
|
|
4196
|
+
|
|
4197
|
+
if isinstance(value, tuple):
|
|
4198
|
+
print(f" Tuple uzunluğu: {len(value)}")
|
|
4199
|
+
for j, item in enumerate(value):
|
|
4200
|
+
print(f" Item {j}: {item} (tip: {type(item)})")
|
|
4201
|
+
|
|
4202
|
+
# Rastgele bir element kontrolü
|
|
4203
|
+
print("\nRastgele element kontrolü (atom numarası 26 - Demir):")
|
|
4204
|
+
if 26 in periodic_elements:
|
|
4205
|
+
value = periodic_elements[26]
|
|
4206
|
+
print(f" Değer: {value}")
|
|
4207
|
+
print(f" Tip: {type(value)}")
|
|
4208
|
+
if isinstance(value, tuple) and len(value) >= 2:
|
|
4209
|
+
print(f" Sembol: {value[0]}")
|
|
4210
|
+
print(f" İsim: {value[1]}")
|
|
4211
|
+
|
|
4212
|
+
def _generate_labels(graph, periodic_elements):
|
|
4213
|
+
"""Etiketleri oluştur."""
|
|
4214
|
+
labels = {}
|
|
4215
|
+
for node_id in graph.nodes():
|
|
4216
|
+
if node_id in periodic_elements:
|
|
4217
|
+
sym, atomic_num = periodic_elements[node_id]
|
|
4218
|
+
# Etiket formatı: Sembol\nAtom Numarası
|
|
4219
|
+
labels[node_id] = f"{sym}\n{atomic_num}"
|
|
4220
|
+
else:
|
|
4221
|
+
labels[node_id] = str(node_id)
|
|
4222
|
+
return labels
|
|
4223
|
+
|
|
4224
|
+
# =============================================================================
|
|
4225
|
+
# MODULE TEST CODE
|
|
4226
|
+
# =============================================================================
|
|
4227
|
+
|
|
4228
|
+
if __name__ == '__main__':
|
|
4229
|
+
print("Testing kececilayout.py module...")
|
|
4230
|
+
G_test = nx.gnp_random_graph(12, 0.3, seed=42)
|
|
4231
|
+
|
|
4232
|
+
# graph-tool grafi oluşturma ve test etme
|
|
4233
|
+
if gt:
|
|
4234
|
+
g = gt.Graph()
|
|
4235
|
+
g.add_vertex(12)
|
|
4236
|
+
for u, v in G_test.edges():
|
|
4237
|
+
g.add_edge(g.vertex(u), g.vertex(v))
|
|
4238
|
+
fig_gt = plt.figure(figsize=(10, 8))
|
|
4239
|
+
draw_kececi(g, ax=fig_gt.add_subplot(111), style='curved')
|
|
4240
|
+
plt.title("Keçeci Layout: graph-tool Graph")
|
|
2511
4241
|
plt.show()
|
|
2512
4242
|
|
|
2513
4243
|
# Compare expanding=False (parallel) vs. expanding=True ('v4' style)
|
|
@@ -2536,13 +4266,3 @@ if __name__ == '__main__':
|
|
|
2536
4266
|
draw_kececi(G_test, style='3d', ax=fig_styles.add_subplot(2, 2, (3, 4), projection='3d'))
|
|
2537
4267
|
plt.tight_layout(rect=[0, 0, 1, 0.96])
|
|
2538
4268
|
plt.show()
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2544
|
-
|
|
2545
|
-
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|