kececilayout 0.5.9__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 +57 -2
- kececilayout/_version.py +1 -1
- kececilayout/kececi_layout.py +1378 -11
- {kececilayout-0.5.9.dist-info → kececilayout-0.6.0.dist-info}/METADATA +55 -1
- kececilayout-0.6.0.dist-info/RECORD +10 -0
- kececilayout-0.5.9.dist-info/RECORD +0 -10
- {kececilayout-0.5.9.dist-info → kececilayout-0.6.0.dist-info}/WHEEL +0 -0
- {kececilayout-0.5.9.dist-info → kececilayout-0.6.0.dist-info}/licenses/LICENSE +0 -0
- {kececilayout-0.5.9.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
|
|
@@ -2843,6 +2846,1381 @@ def draw_kececi(graph, style='curved', ax=None, **kwargs):
|
|
|
2843
2846
|
return ax
|
|
2844
2847
|
"""
|
|
2845
2848
|
|
|
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
|
+
|
|
2846
4224
|
# =============================================================================
|
|
2847
4225
|
# MODULE TEST CODE
|
|
2848
4226
|
# =============================================================================
|
|
@@ -2888,14 +4266,3 @@ if __name__ == '__main__':
|
|
|
2888
4266
|
draw_kececi(G_test, style='3d', ax=fig_styles.add_subplot(2, 2, (3, 4), projection='3d'))
|
|
2889
4267
|
plt.tight_layout(rect=[0, 0, 1, 0.96])
|
|
2890
4268
|
plt.show()
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2894
|
-
|
|
2895
|
-
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2901
|
-
|