ararpy 0.0.24__py3-none-any.whl → 0.1.11__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.
- ararpy/__init__.py +3 -5
- ararpy/calc/age.py +2 -2
- ararpy/calc/arr.py +25 -21
- ararpy/calc/basic.py +23 -0
- ararpy/calc/corr.py +32 -17
- ararpy/calc/err.py +9 -2
- ararpy/calc/jvalue.py +3 -2
- ararpy/calc/raw_funcs.py +1 -1
- ararpy/calc/regression.py +64 -4
- ararpy/examples/22WHA0433.age +0 -0
- ararpy/examples/22WHA0433.arr +0 -0
- ararpy/files/basic.py +2 -2
- ararpy/files/calc_file.py +1 -2
- ararpy/files/raw_file.py +238 -125
- ararpy/smp/__init__.py +2 -3
- ararpy/smp/basic.py +79 -12
- ararpy/smp/corr.py +97 -60
- ararpy/smp/diffusion_funcs.py +4745 -0
- ararpy/smp/export.py +287 -343
- ararpy/smp/info.py +23 -0
- ararpy/smp/initial.py +43 -20
- ararpy/smp/json.py +2 -2
- ararpy/smp/plots.py +151 -20
- ararpy/smp/raw.py +20 -14
- ararpy/smp/sample.py +44 -29
- ararpy/smp/style.py +5 -4
- ararpy/smp/table.py +66 -15
- ararpy/test.py +5 -3
- {ararpy-0.0.24.dist-info → ararpy-0.1.11.dist-info}/METADATA +1 -1
- ararpy-0.1.11.dist-info/RECORD +60 -0
- {ararpy-0.0.24.dist-info → ararpy-0.1.11.dist-info}/WHEEL +1 -1
- ararpy-0.0.24.dist-info/RECORD +0 -58
- {ararpy-0.0.24.dist-info → ararpy-0.1.11.dist-info}/LICENSE +0 -0
- {ararpy-0.0.24.dist-info → ararpy-0.1.11.dist-info}/top_level.txt +0 -0
ararpy/smp/export.py
CHANGED
|
@@ -17,6 +17,7 @@ import sys
|
|
|
17
17
|
import pickle
|
|
18
18
|
import traceback
|
|
19
19
|
import pdf_maker as pm
|
|
20
|
+
from decimal import Decimal
|
|
20
21
|
|
|
21
22
|
from ..calc import arr, isochron
|
|
22
23
|
from . import basic, sample, consts
|
|
@@ -39,6 +40,7 @@ def to_pdf(file_path: str, figure: str, smp: Sample):
|
|
|
39
40
|
pdf = CreatePDF(filepath=file_path, sample=smp)
|
|
40
41
|
pdf.save(figure=figure)
|
|
41
42
|
|
|
43
|
+
|
|
42
44
|
class ExcelTemplate:
|
|
43
45
|
def __init__(self, **kwargs):
|
|
44
46
|
self.name = ""
|
|
@@ -937,314 +939,30 @@ class CreateOriginGraph:
|
|
|
937
939
|
|
|
938
940
|
class CreatePDF:
|
|
939
941
|
def __init__(self, **kwargs):
|
|
940
|
-
self.name = "PDF"
|
|
941
|
-
self.sample = Sample()
|
|
942
|
-
self.figure = Plot()
|
|
943
942
|
self.filepath = ""
|
|
944
|
-
self.
|
|
945
|
-
self.
|
|
946
|
-
self.
|
|
947
|
-
self.
|
|
948
|
-
self.
|
|
949
|
-
self.
|
|
950
|
-
#
|
|
951
|
-
#
|
|
943
|
+
self.sample = Sample()
|
|
944
|
+
# self.name = "PDF"
|
|
945
|
+
# self.figure = Plot()
|
|
946
|
+
# self.page_size = [595, 842]
|
|
947
|
+
# self.data_bytes = b""
|
|
948
|
+
# self.component = []
|
|
949
|
+
# self.text = []
|
|
950
|
+
# self.frame = []
|
|
951
|
+
# self.axis_area = [138, 400, 360, 270] # x0, y0, w, h
|
|
952
|
+
|
|
952
953
|
for key, value in kwargs.items():
|
|
953
954
|
setattr(self, key, value)
|
|
954
955
|
|
|
955
|
-
def
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
return float(self.figure.yaxis.min)
|
|
963
|
-
|
|
964
|
-
def _ymax(self):
|
|
965
|
-
return float(self.figure.yaxis.max)
|
|
966
|
-
|
|
967
|
-
def _get_transfer_pos(self, x, y):
|
|
968
|
-
x0, y0, w, h = self.axis_area
|
|
969
|
-
x = (x - self._xmin()) / (self._xmax() - self._xmin()) * w + x0
|
|
970
|
-
y = (y - self._ymin()) / (self._ymax() - self._ymin()) * h + y0
|
|
971
|
-
return [x, y]
|
|
972
|
-
|
|
973
|
-
def _get_isochron_line(self, point1, point2, color='1 0 0', width=1):
|
|
974
|
-
line_str = ''
|
|
975
|
-
if not len(point1) == len(point2) == 2:
|
|
976
|
-
return line_str
|
|
977
|
-
x0, y0, w, h = self.axis_area
|
|
978
|
-
|
|
979
|
-
def _get_line_points(k, m):
|
|
980
|
-
if k == 0:
|
|
981
|
-
return [
|
|
982
|
-
[x0, m], [x0 + w, m]
|
|
983
|
-
]
|
|
984
|
-
return [
|
|
985
|
-
[x0, x0 * k + m], [x0 + w, (x0 + w) * k + m],
|
|
986
|
-
[(y0 - m) / k, y0], [(y0 + h - m) / k, y0 + h]
|
|
987
|
-
]
|
|
988
|
-
|
|
989
|
-
point_1 = self._get_transfer_pos(*point1)
|
|
990
|
-
point_2 = self._get_transfer_pos(*point2)
|
|
991
|
-
k = (point_2[1] - point_1[1]) / (point_2[0] - point_1[0])
|
|
992
|
-
m = point_2[1] - point_2[0] * k
|
|
993
|
-
line = []
|
|
994
|
-
for point in _get_line_points(k, m):
|
|
995
|
-
if self.is_in_area(*point):
|
|
996
|
-
line.append(point)
|
|
997
|
-
if len(line) == 2:
|
|
998
|
-
line_str = f'{width} w\r{color} RG\r{line[0][0]} {line[0][1]} m {line[1][0]} {line[1][1]} l S\r'
|
|
999
|
-
return line_str
|
|
1000
|
-
|
|
1001
|
-
def _get_spectra_line(self, data, width=1, color='1 0 0'):
|
|
1002
|
-
"""
|
|
1003
|
-
data = [[x1, x2, ..., xn], [y1, y2, ..., yn]]
|
|
1004
|
-
"""
|
|
1005
|
-
x0, y0, w, h = self.axis_area
|
|
1006
|
-
num = 0
|
|
1007
|
-
line_str = ''
|
|
1008
|
-
if not data:
|
|
1009
|
-
return line_str
|
|
1010
|
-
data = arr.transpose(data)
|
|
1011
|
-
for index, point in enumerate(data):
|
|
1012
|
-
point = self._get_transfer_pos(*point)
|
|
1013
|
-
if not self.is_in_area(*point):
|
|
1014
|
-
if index == 0 and self.is_in_area(*self._get_transfer_pos(*data[index + 1])):
|
|
1015
|
-
point[0] = x0
|
|
1016
|
-
elif index == (len(data) - 1) and self.is_in_area(*self._get_transfer_pos(*data[index - 1])):
|
|
1017
|
-
point[0] = x0 + w
|
|
1018
|
-
elif 0 < index < (len(data) - 1) and (
|
|
1019
|
-
self.is_in_area(*self._get_transfer_pos(*data[index + 1])) or self.is_in_area(
|
|
1020
|
-
*self._get_transfer_pos(*data[index - 1]))):
|
|
1021
|
-
if x0 < point[0] < (x0 + w):
|
|
1022
|
-
point[1] = [y0, y0 + h][point[1] >= y0 + h]
|
|
1023
|
-
else:
|
|
1024
|
-
point[0] = [x0, x0 + w][point[0] >= x0 + w]
|
|
1025
|
-
else:
|
|
1026
|
-
continue
|
|
1027
|
-
line_str = line_str + f'{point[0]} {point[1]} {"m " if num == 0 else "l "}'
|
|
1028
|
-
num += 1
|
|
1029
|
-
line_str = f'{width} w\r{color} RG\r' + line_str + 'S\r'
|
|
1030
|
-
return line_str
|
|
1031
|
-
|
|
1032
|
-
def is_in_area(self, x, y):
|
|
1033
|
-
x0, y0, w, h = self.axis_area
|
|
1034
|
-
if x == -999:
|
|
1035
|
-
x = x0
|
|
1036
|
-
if y == -999:
|
|
1037
|
-
y = y0
|
|
1038
|
-
return x0 <= x <= x0 + w and y0 <= y <= y0 + h
|
|
1039
|
-
|
|
1040
|
-
def set_axis_frame(self):
|
|
1041
|
-
from decimal import Decimal
|
|
1042
|
-
frame = ''
|
|
1043
|
-
x0, y0, w, h = self.axis_area
|
|
1044
|
-
frame += f'1 w\r0 0 0 RG\r{x0} {y0} {w} {h} re S\r' # % 四个参数:最小x,最小y,宽度和高度
|
|
1045
|
-
|
|
1046
|
-
xmin, xmax = float(self.figure.xaxis.min), float(self.figure.xaxis.max)
|
|
1047
|
-
nx, dx = int(self.figure.xaxis.split_number), float(self.figure.xaxis.interval)
|
|
1048
|
-
ymin, ymax = float(self.figure.yaxis.min), float(self.figure.yaxis.max)
|
|
1049
|
-
ny, dy = int(self.figure.yaxis.split_number), float(self.figure.yaxis.interval)
|
|
1050
|
-
|
|
1051
|
-
for i in range(ny + 1):
|
|
1052
|
-
yi = y0 + i * h * dy / (ymax - ymin)
|
|
1053
|
-
if self.is_in_area(-999, yi):
|
|
1054
|
-
frame += f'{x0} {yi} m {x0 - 4} {yi} l S\r'
|
|
1055
|
-
frame += f'BT\r1 0 0 1 {x0 - 4 - 32} {yi - 4} Tm\r/F1 12 Tf\r0 0 0 rg\r({Decimal(str(ymin)) + i * Decimal(str(dy))}) Tj\rET\r'
|
|
1056
|
-
for i in range(nx + 1):
|
|
1057
|
-
xi = x0 + i * w * dx / (xmax - xmin)
|
|
1058
|
-
if self.is_in_area(xi, -999):
|
|
1059
|
-
frame += f'{xi} {y0} m {xi} {y0 - 4} l S\r'
|
|
1060
|
-
frame += f'BT\r1 0 0 1 {xi - 12} {y0 - 16} Tm\r/F1 12 Tf\r0 0 0 rg\r({Decimal(str(xmin)) + i * Decimal(str(dx))}) Tj\rET\r'
|
|
1061
|
-
self.frame.append(frame)
|
|
1062
|
-
return frame
|
|
1063
|
-
|
|
1064
|
-
def set_main_content(self):
|
|
1065
|
-
content = ''
|
|
1066
|
-
if self.figure.type == 'isochron':
|
|
1067
|
-
scatter_w, scatter_h = 5, 5
|
|
1068
|
-
if not arr.is_empty(self.figure.line1.info):
|
|
1069
|
-
content += self._get_isochron_line(*self.figure.line1.data, width=1, color='1 0 0')
|
|
1070
|
-
if not arr.is_empty(self.figure.line2.info):
|
|
1071
|
-
content += self._get_isochron_line(*self.figure.line2.data, width=1, color='0 0 1')
|
|
1072
|
-
for point in arr.transpose(self.figure.data):
|
|
1073
|
-
x, y = self._get_transfer_pos(point[0], point[2])
|
|
1074
|
-
if self.is_in_area(x, y):
|
|
1075
|
-
if int(point[5]) - 1 in self.sample.SelectedSequence1:
|
|
1076
|
-
color = '0 0 0 RG\r1 0 0 rg\r'
|
|
1077
|
-
elif int(point[5]) - 1 in self.sample.SelectedSequence2:
|
|
1078
|
-
color = '0 0 0 RG\r0 0 1 rg\r'
|
|
1079
|
-
else:
|
|
1080
|
-
color = '0 0 0 RG\r1 1 1 rg\r'
|
|
1081
|
-
content = content + color + \
|
|
1082
|
-
f'{x - scatter_w / 2} {y - scatter_h / 2} {scatter_w} {scatter_h} re b\r'
|
|
1083
|
-
elif self.figure.type == 'spectra':
|
|
1084
|
-
for index, data in enumerate([self.figure.data, self.figure.set1.data, self.figure.set2.data]):
|
|
1085
|
-
color = ['0 0 0', '1 0 0', '0 0 1'][index]
|
|
1086
|
-
data = arr.transpose(data)
|
|
1087
|
-
content = content + self._get_spectra_line(data[:2], color=color) + \
|
|
1088
|
-
self._get_spectra_line([data[0], data[2]], color=color)
|
|
1089
|
-
self.component.append(content)
|
|
1090
|
-
return content
|
|
1091
|
-
|
|
1092
|
-
def set_text(self):
|
|
1093
|
-
text = ''
|
|
1094
|
-
x0, y0, w, h = self.axis_area
|
|
1095
|
-
# Figure Title
|
|
1096
|
-
text += f'BT\r1 0 0 1 {x0 + 10} {y0 - 20 + h} Tm\n/F1 12 Tf\r({self.sample.Info.sample.name}) Tj\rET\r'
|
|
1097
|
-
if self.figure.type == 'isochron':
|
|
1098
|
-
xaxis_title_number = ''.join(list(filter(str.isdigit, self.figure.xaxis.title.text)))
|
|
1099
|
-
yaxis_title_number = ''.join(list(filter(str.isdigit, self.figure.yaxis.title.text)))
|
|
1100
|
-
# X axis title
|
|
1101
|
-
x_title_length = 5 * 12 # length * font point size
|
|
1102
|
-
text += '\n'.join([
|
|
1103
|
-
'BT', f'1 0 0 1 {x0 + w / 2 - x_title_length / 2} {y0 - 30} Tm',
|
|
1104
|
-
# % 使用Tm将文本位置设置为(35,530)前四个参数是cosx, sinx, -sinx, cosx表示逆时针旋转弧度
|
|
1105
|
-
'/F1 8 Tf', '5 Ts', f'({xaxis_title_number[:2]}) Tj', '/F1 12 Tf', '0 Ts', '(Ar / ) Tj',
|
|
1106
|
-
'/F1 8 Tf', '5 Ts', f'({xaxis_title_number[2:4]}) Tj', '/F1 12 Tf', '0 Ts', '(Ar) Tj', 'ET',
|
|
1107
|
-
])
|
|
1108
|
-
# Y axis title
|
|
1109
|
-
y_title_length = 5 * 12 # length * font point size
|
|
1110
|
-
text += '\n'.join([
|
|
1111
|
-
'BT', f'0 1 -1 0 {x0 - 40} {y0 + h / 2 - y_title_length / 2} Tm',
|
|
1112
|
-
# % 使用Tm将文本位置设置为(35,530)前四个参数是cosx, sinx, -sinx, cosx表示逆时针旋转弧度
|
|
1113
|
-
'/F1 8 Tf', '5 Ts', f'({yaxis_title_number[:2]}) Tj', '/F1 12 Tf', '0 Ts', '(Ar / ) Tj',
|
|
1114
|
-
'/F1 8 Tf', '5 Ts', f'({yaxis_title_number[2:4]}) Tj', '/F1 12 Tf', '0 Ts', '(Ar) Tj', 'ET',
|
|
1115
|
-
])
|
|
1116
|
-
|
|
1117
|
-
elif self.figure.type == 'spectra':
|
|
1118
|
-
# X axis title
|
|
1119
|
-
x_title_length = 13 * 12 # length * font point size
|
|
1120
|
-
text += '\n'.join([
|
|
1121
|
-
'BT', f'1 0 0 1 {x0 + w / 2 - x_title_length / 2} {y0 - 30} Tm',
|
|
1122
|
-
'/F1 12 Tf', '0 Ts', '(Cumulative ) Tj', '/F1 8 Tf', '5 Ts', f'(39) Tj',
|
|
1123
|
-
'/F1 12 Tf', '0 Ts', '(Ar Released (%)) Tj', 'ET',
|
|
1124
|
-
])
|
|
1125
|
-
# Y axis title
|
|
1126
|
-
y_title_length = 9 * 12 # length * font point size
|
|
1127
|
-
text += '\n'.join([
|
|
1128
|
-
'BT', f'0 1 -1 0 {x0 - 40} {y0 + h / 2 - y_title_length / 2} Tm',
|
|
1129
|
-
'/F1 12 Tf', '0 Ts', f'(Apparent Age (Ma)) Tj', 'ET',
|
|
1130
|
-
])
|
|
1131
|
-
# Text 1
|
|
1132
|
-
info = self.figure.set1.info
|
|
1133
|
-
if len(info) == 8 and self.figure.text1.text != '':
|
|
1134
|
-
sum39 = findall('∑{sup|39}Ar = (.*)', self.figure.text1.text)[1]
|
|
1135
|
-
text += '\n'.join([
|
|
1136
|
-
'BT', f'1 0 0 1 {x0 + w / 4} {y0 + h / 2} Tm',
|
|
1137
|
-
'/F1 12 Tf', '0 Ts', f'(t) Tj', '/F1 8 Tf', '-2 Ts', f'(p) Tj',
|
|
1138
|
-
'/F1 12 Tf', '0 Ts',
|
|
1139
|
-
f'( = {info[4]:.2f} <261> {info[6]:.2f} Ma, MSMD = {info[3]:.2f}, ∑) Tj',
|
|
1140
|
-
'/F1 8 Tf', '5 Ts', f'(39) Tj',
|
|
1141
|
-
'/F1 12 Tf', '0 Ts',
|
|
1142
|
-
f'(Ar = {sum39}) Tj',
|
|
1143
|
-
'ET',
|
|
1144
|
-
])
|
|
1145
|
-
# Text 2
|
|
1146
|
-
text2 = findall('∑{sup|39}Ar = (.*)', self.figure.text2.text)[1]
|
|
1147
|
-
|
|
1148
|
-
self.text.append(text)
|
|
1149
|
-
return text
|
|
1150
|
-
|
|
1151
|
-
def set_split_line(self):
|
|
1152
|
-
others = []
|
|
1153
|
-
for i in range(200):
|
|
1154
|
-
if i * 50 >= self.page_size[0]:
|
|
1155
|
-
break
|
|
1156
|
-
others.append(f'[2] 0 d\n{i * 50} 0 m {i * 50} {self.page_size[1]} l S')
|
|
1157
|
-
for i in range(200):
|
|
1158
|
-
if i * 50 >= self.page_size[1]:
|
|
1159
|
-
break
|
|
1160
|
-
others.append(f'[2] 0 d\n0 {i * 50} m {self.page_size[0]} {i * 50} l S')
|
|
1161
|
-
self.data_str = self.data_str.replace(
|
|
1162
|
-
'% <flag: others>\r',
|
|
1163
|
-
'% <flag: others>\r' + '0.75 G\n' + '\n'.join(others),
|
|
1164
|
-
)
|
|
1165
|
-
|
|
1166
|
-
def set_info(self):
|
|
1167
|
-
from datetime import datetime, timezone, timedelta
|
|
1168
|
-
date = str(datetime.now(tz=timezone(offset=timedelta(hours=8))))
|
|
1169
|
-
date = findall('(.*)-(.*)-(.*) (.*):(.*):(.*)\.(.*)', date)[0]
|
|
1170
|
-
date = ''.join(date[0:6])
|
|
1171
|
-
date = 'D:' + date + "+08'00'"
|
|
1172
|
-
self.data_str = self.data_str.replace(
|
|
1173
|
-
'% <flag: info CreationDate>',
|
|
1174
|
-
f"{date}",
|
|
1175
|
-
)
|
|
1176
|
-
self.data_str = self.data_str.replace(
|
|
1177
|
-
'% <flag: info ModDate>',
|
|
1178
|
-
f"{date}",
|
|
1179
|
-
)
|
|
1180
|
-
|
|
1181
|
-
self.data_str = self.data_str.replace(
|
|
1182
|
-
'% <flag: info Title>',
|
|
1183
|
-
f'{self.sample.Info.sample.name} - {self.figure.name}'
|
|
1184
|
-
)
|
|
1185
|
-
self.data_str = self.data_str.replace(
|
|
1186
|
-
'% <flag: page title>\r',
|
|
1187
|
-
'% <flag: page title>\r' +
|
|
1188
|
-
f'(<This is a demo of the exported PDF.>) Tj T*\n'
|
|
1189
|
-
f'(<The PDFs can be freely edited in Adobe Illustrator.>) Tj\n'
|
|
1190
|
-
)
|
|
1191
|
-
|
|
1192
|
-
def set_replace(self):
|
|
1193
|
-
self.data_str = self.data_str.replace(
|
|
1194
|
-
'% <main contents>\r',
|
|
1195
|
-
'% <main contents>\r' + '\r\n'.join(self.component)
|
|
1196
|
-
)
|
|
1197
|
-
self.data_str = self.data_str.replace(
|
|
1198
|
-
'% <frames>\r',
|
|
1199
|
-
'% <frames>\r' + '\r\n'.join(self.frame)
|
|
1200
|
-
)
|
|
1201
|
-
self.data_str = self.data_str.replace(
|
|
1202
|
-
'% <texts>\r',
|
|
1203
|
-
'% <texts>\r' + '\r\n'.join(self.text)
|
|
1204
|
-
)
|
|
1205
|
-
|
|
1206
|
-
def get_pdf(self):
|
|
1207
|
-
self.do_function(
|
|
1208
|
-
self.set_main_content,
|
|
1209
|
-
self.set_axis_frame,
|
|
1210
|
-
self.set_text,
|
|
1211
|
-
self.set_info,
|
|
1212
|
-
self.set_replace,
|
|
1213
|
-
# self.set_split_line,
|
|
1214
|
-
self.toBetys,
|
|
1215
|
-
self.save,
|
|
1216
|
-
)
|
|
1217
|
-
|
|
1218
|
-
def get_contents(self):
|
|
1219
|
-
self.do_function(
|
|
1220
|
-
self.set_main_content,
|
|
1221
|
-
self.set_axis_frame,
|
|
1222
|
-
self.set_text,
|
|
1223
|
-
)
|
|
1224
|
-
return {
|
|
1225
|
-
'component': self.component,
|
|
1226
|
-
'frame': self.frame,
|
|
1227
|
-
'text': self.text,
|
|
1228
|
-
}
|
|
1229
|
-
|
|
1230
|
-
def toBetys(self):
|
|
1231
|
-
self.data_bytes = self.data_str.encode('utf-8')
|
|
1232
|
-
return self.data_bytes
|
|
1233
|
-
|
|
1234
|
-
# def save(self):
|
|
1235
|
-
# with open(self.filepath, 'wb') as f:
|
|
1236
|
-
# f.write(self.data_bytes)
|
|
956
|
+
def color_hex_to_rgb(self, color: str):
|
|
957
|
+
if color.startswith("#"):
|
|
958
|
+
color = color[1:]
|
|
959
|
+
r = int(color[:2], 16)
|
|
960
|
+
g = int(color[2:4], 16)
|
|
961
|
+
b = int(color[4:6], 16)
|
|
962
|
+
return r, g, b
|
|
1237
963
|
|
|
1238
|
-
def
|
|
1239
|
-
for
|
|
1240
|
-
try:
|
|
1241
|
-
handler()
|
|
1242
|
-
except Exception:
|
|
1243
|
-
print(traceback.format_exc())
|
|
1244
|
-
continue
|
|
1245
|
-
|
|
1246
|
-
def create_pdf(self):
|
|
1247
|
-
pass
|
|
964
|
+
def color_rgb_normalized(self, rgb):
|
|
965
|
+
return [round(i / 255, 6) for i in rgb]
|
|
1248
966
|
|
|
1249
967
|
def save(self, figure: str = "figure_3", use_split_number: bool = True):
|
|
1250
968
|
|
|
@@ -1262,9 +980,10 @@ class CreatePDF:
|
|
|
1262
980
|
file = pm.NewPDF(filepath=self.filepath)
|
|
1263
981
|
# rich text tags should follow this priority: color > script > break
|
|
1264
982
|
file.text(page=0, x=50, y=780, line_space=1.2, size=12, base=0, h_align="left",
|
|
1265
|
-
text=f"The PDF
|
|
1266
|
-
f"
|
|
1267
|
-
f"<r
|
|
983
|
+
text=f"The PDF can be edited with Adobe Acrobat, Illustrator and CorelDRAW.<r>"
|
|
984
|
+
f"<r> Sample Name: {self.sample.name()}"
|
|
985
|
+
f"<r> Figure Title: {basic.get_component_byid(self.sample, figure).name}",
|
|
986
|
+
)
|
|
1268
987
|
file.canvas(page=1, margin_top=5, canvas=cv, unit="cm", h_align="middle")
|
|
1269
988
|
|
|
1270
989
|
# save pdf
|
|
@@ -1318,9 +1037,26 @@ class CreatePDF:
|
|
|
1318
1037
|
|
|
1319
1038
|
# isochron scatters
|
|
1320
1039
|
data = arr.transpose(plot.data)
|
|
1040
|
+
colors = [
|
|
1041
|
+
self.color_rgb_normalized(self.color_hex_to_rgb(plot.set1.color)),
|
|
1042
|
+
self.color_rgb_normalized(self.color_hex_to_rgb(plot.set2.color)),
|
|
1043
|
+
self.color_rgb_normalized(self.color_hex_to_rgb(plot.set3.color)),
|
|
1044
|
+
]
|
|
1045
|
+
stroke_colors = [
|
|
1046
|
+
self.color_rgb_normalized(self.color_hex_to_rgb(plot.set1.border_color)),
|
|
1047
|
+
self.color_rgb_normalized(self.color_hex_to_rgb(plot.set2.border_color)),
|
|
1048
|
+
self.color_rgb_normalized(self.color_hex_to_rgb(plot.set3.border_color))
|
|
1049
|
+
]
|
|
1321
1050
|
for (x, sx, y, sy, r, i) in data:
|
|
1322
|
-
|
|
1323
|
-
|
|
1051
|
+
if (i - 1) in set1.data:
|
|
1052
|
+
pt.scatter(x, y, stroke_color=stroke_colors[0], fill_color=colors[0], line_width=int(float(plot.set1.border_width) / 2),
|
|
1053
|
+
size=int(float(plot.set1.symbol_size) / 3), z_index=10)
|
|
1054
|
+
elif (i - 1) in set2.data:
|
|
1055
|
+
pt.scatter(x, y, stroke_color=stroke_colors[1], fill_color=colors[1], line_width=int(float(plot.set2.border_width) / 2),
|
|
1056
|
+
size=int(float(plot.set2.symbol_size) / 3), z_index=10)
|
|
1057
|
+
else:
|
|
1058
|
+
pt.scatter(x, y, stroke_color=stroke_colors[2], fill_color=colors[2], line_width=int(float(plot.set3.border_width) / 2),
|
|
1059
|
+
size=int(float(plot.set3.symbol_size) / 3), z_index=10)
|
|
1324
1060
|
|
|
1325
1061
|
# split sticks
|
|
1326
1062
|
# xaxis.interval = (xaxis_max - xaxis_min) / xaxis.split_number
|
|
@@ -1330,45 +1066,61 @@ class CreatePDF:
|
|
|
1330
1066
|
end = pt.scale_to_points(xaxis_min + xaxis.interval * i, yaxis_min)
|
|
1331
1067
|
end = (end[0], start[1] - 5)
|
|
1332
1068
|
if not pt.is_out_side(*start):
|
|
1333
|
-
pt.line(start=start, end=end, width=1, line_style="solid", clip=False, coordinate="pt")
|
|
1334
|
-
pt.text(x=start[0], y=end[1] - 15,
|
|
1335
|
-
|
|
1069
|
+
pt.line(start=start, end=end, width=1, line_style="solid", clip=False, coordinate="pt", z_index=100)
|
|
1070
|
+
pt.text(x=start[0], y=end[1] - 15, clip=False, coordinate="pt", h_align="middle",
|
|
1071
|
+
text=f"{Decimal(str(xaxis_min)) + Decimal(str(xaxis.interval)) * Decimal(str(i))}", z_index=150)
|
|
1336
1072
|
for i in range(yaxis.split_number + 1):
|
|
1337
1073
|
start = pt.scale_to_points(xaxis_min, yaxis_min + yaxis.interval * i)
|
|
1338
1074
|
end = pt.scale_to_points(xaxis_min, yaxis_min + yaxis.interval * i)
|
|
1339
1075
|
end = (start[0] - 5, end[1])
|
|
1340
1076
|
if not pt.is_out_side(*start):
|
|
1341
|
-
pt.line(start=start, end=end, width=1, line_style="solid", clip=False, coordinate="pt")
|
|
1342
|
-
pt.text(x=end[0] - 5, y=end[1],
|
|
1343
|
-
|
|
1344
|
-
# pt.text(x=end[0] - 5, y=end[1], text=arr.change_number_format([f"{yaxis_min + yaxis.interval * i}"], flag="Scientific", precision=1)[0], clip=False,
|
|
1345
|
-
# coordinate="pt", h_align="right", v_align="center")
|
|
1346
|
-
|
|
1077
|
+
pt.line(start=start, end=end, width=1, line_style="solid", clip=False, coordinate="pt", z_index=100)
|
|
1078
|
+
pt.text(x=end[0] - 5, y=end[1], clip=False, coordinate="pt", h_align="right", v_align="center",
|
|
1079
|
+
text=f"{Decimal(str(yaxis_min)) + Decimal(str(yaxis.interval)) * Decimal(str(i))}", z_index=150)
|
|
1347
1080
|
|
|
1348
1081
|
# axis titles
|
|
1349
|
-
|
|
1350
1082
|
p = pt.scale_to_points((xaxis_max + xaxis_min) / 2, yaxis_min)
|
|
1351
|
-
pt.text(x=p[0], y=p[1] - 30, text=x_title, clip=False, coordinate="pt",
|
|
1083
|
+
pt.text(x=p[0], y=p[1] - 30, text=x_title, clip=False, coordinate="pt",
|
|
1084
|
+
h_align="middle", v_align="top", z_index=150)
|
|
1352
1085
|
p = pt.scale_to_points(xaxis_min, (yaxis_max + yaxis_min) / 2)
|
|
1353
1086
|
pt.text(x=p[0] - 50, y=p[1], text=y_title, clip=False, coordinate="pt",
|
|
1354
|
-
h_align="middle", v_align="bottom", rotate=90)
|
|
1087
|
+
h_align="middle", v_align="bottom", rotate=90, z_index=150)
|
|
1355
1088
|
|
|
1356
1089
|
# inside text
|
|
1090
|
+
colors = [self.color_rgb_normalized(self.color_hex_to_rgb(plot.line1.color)),
|
|
1091
|
+
self.color_rgb_normalized(self.color_hex_to_rgb(plot.line2.color))]
|
|
1092
|
+
widths = [int(float(plot.line1.line_width) / 2), int(float(plot.line2.line_width) / 2)]
|
|
1093
|
+
styles = [plot.line1.line_type, plot.line2.line_type]
|
|
1357
1094
|
for index, data in enumerate([plot.line1.data, plot.line2.data]):
|
|
1358
1095
|
# isochron line
|
|
1359
1096
|
try:
|
|
1360
|
-
pt.line(start=data[0], end=data[1], clip=True,
|
|
1097
|
+
pt.line(start=data[0], end=data[1], clip=True, color=colors[index],
|
|
1098
|
+
width=widths[index], line_style=styles[index], line_caps='square', z_index=50)
|
|
1361
1099
|
except IndexError:
|
|
1362
1100
|
pass
|
|
1363
1101
|
if data != []:
|
|
1102
|
+
if index == 0:
|
|
1103
|
+
pos = [round(i / 100, 2) for i in plot.text1.pos]
|
|
1104
|
+
color = self.color_rgb_normalized(self.color_hex_to_rgb(plot.text1.color))
|
|
1105
|
+
elif index == 1:
|
|
1106
|
+
pos = [round(i / 100, 2) for i in plot.text2.pos]
|
|
1107
|
+
color = self.color_rgb_normalized(self.color_hex_to_rgb(plot.text2.color))
|
|
1108
|
+
else:
|
|
1109
|
+
pos = (0.6, 0.7)
|
|
1110
|
+
color = "black"
|
|
1364
1111
|
age, sage = round(age_results[index]['age'], 2), round(age_results[index]['s2'], 2)
|
|
1365
1112
|
F, sF = round(age_results[index]['F'], 2), round(age_results[index]['sF'], 2)
|
|
1366
1113
|
R0, sR0 = round(age_results[index]['initial'], 2), round(age_results[index]['sinitial'], 2)
|
|
1367
|
-
|
|
1368
|
-
|
|
1114
|
+
MSWD, R2 = round(age_results[index]['MSWD'], 2), round(age_results[index]['R2'], 4)
|
|
1115
|
+
Chisq, p = round(age_results[index]['Chisq'], 2), round(age_results[index]['Pvalue'], 2)
|
|
1116
|
+
pt.text(x=(xaxis_max - xaxis_min) * pos[0] + xaxis_min,
|
|
1117
|
+
y=(yaxis_max - yaxis_min) * pos[1] + yaxis_min,
|
|
1369
1118
|
text=f"Age ={age} {chr(0xb1)} {sage} Ma<r>F = {F} {chr(0xb1)} {sF}<r>"
|
|
1370
|
-
f"R<sub>0</sub> = {R0} {chr(0xb1)} {sR0}"
|
|
1371
|
-
|
|
1119
|
+
f"R<sub>0</sub> = {R0} {chr(0xb1)} {sR0}<r>"
|
|
1120
|
+
f"{MSWD = }, R<sup>2</sup> = {R2}<r>"
|
|
1121
|
+
f"{Chisq = }, {p = }",
|
|
1122
|
+
size=10, clip=True, coordinate="scale", h_align="left", v_align="bottom",
|
|
1123
|
+
color=color, rotate=0, z_index=150)
|
|
1372
1124
|
return cv
|
|
1373
1125
|
|
|
1374
1126
|
def plot_spectra(self, smp: Sample = None, figure: str = "figure_1"):
|
|
@@ -1396,7 +1148,6 @@ class CreatePDF:
|
|
|
1396
1148
|
yaxis_max = float(yaxis.max)
|
|
1397
1149
|
|
|
1398
1150
|
plot_scale = (xaxis_min, xaxis_max, yaxis_min, yaxis_max)
|
|
1399
|
-
colors = ['red', 'color']
|
|
1400
1151
|
|
|
1401
1152
|
# create a canvas
|
|
1402
1153
|
cv = pm.Canvas(width=17, height=12, unit="cm", show_frame=True, clip_outside_plot_areas=False)
|
|
@@ -1406,32 +1157,62 @@ class CreatePDF:
|
|
|
1406
1157
|
|
|
1407
1158
|
# spectra lines
|
|
1408
1159
|
data = plot.data
|
|
1160
|
+
colors = [
|
|
1161
|
+
self.color_rgb_normalized(self.color_hex_to_rgb(plot.line1.color)),
|
|
1162
|
+
self.color_rgb_normalized(self.color_hex_to_rgb(plot.line2.color)),
|
|
1163
|
+
]
|
|
1164
|
+
widths = [int(float(plot.line1.line_width) / 2), int(float(plot.line2.line_width) / 2)]
|
|
1165
|
+
styles = [plot.line1.line_type, plot.line2.line_type]
|
|
1409
1166
|
for index in range(len(data) - 1):
|
|
1410
1167
|
pt.line(start=(data[index][0], data[index][1]), end=(data[index + 1][0], data[index + 1][1]),
|
|
1411
|
-
|
|
1168
|
+
width=widths[0], line_style=styles[0], color=colors[0],
|
|
1169
|
+
clip=True, line_caps="square", z_index=9)
|
|
1412
1170
|
pt.line(start=(data[index][0], data[index][2]), end=(data[index + 1][0], data[index + 1][2]),
|
|
1413
|
-
|
|
1414
|
-
|
|
1171
|
+
width=widths[1], line_style=styles[1], color=colors[1],
|
|
1172
|
+
clip=True, line_caps="square", z_index=9)
|
|
1173
|
+
|
|
1174
|
+
colors = [
|
|
1175
|
+
[self.color_rgb_normalized(self.color_hex_to_rgb(plot.line3.color)),
|
|
1176
|
+
self.color_rgb_normalized(self.color_hex_to_rgb(plot.line4.color))],
|
|
1177
|
+
[self.color_rgb_normalized(self.color_hex_to_rgb(plot.line5.color)),
|
|
1178
|
+
self.color_rgb_normalized(self.color_hex_to_rgb(plot.line6.color))]
|
|
1179
|
+
]
|
|
1180
|
+
widths = [
|
|
1181
|
+
[int(float(plot.line3.line_width) / 2), int(float(plot.line4.line_width) / 2)],
|
|
1182
|
+
[int(float(plot.line5.line_width) / 2), int(float(plot.line6.line_width) / 2)]
|
|
1183
|
+
]
|
|
1184
|
+
styles = [[plot.line3.line_type, plot.line4.line_type], [plot.line5.line_type, plot.line6.line_type]]
|
|
1415
1185
|
for index, data in enumerate([plot.set1.data, plot.set2.data]):
|
|
1416
1186
|
if not data:
|
|
1417
1187
|
continue
|
|
1418
|
-
color = colors[index]
|
|
1419
1188
|
for i in range(len(data) - 1):
|
|
1420
1189
|
pt.line(start=(data[i][0], data[i][1]), end=(data[i + 1][0], data[i + 1][1]),
|
|
1421
|
-
|
|
1190
|
+
width=widths[index][0], line_style=styles[index][0], color=colors[index][0],
|
|
1191
|
+
clip=True, line_caps="square", z_index=99)
|
|
1422
1192
|
pt.line(start=(data[i][0], data[i][2]), end=(data[i + 1][0], data[i + 1][2]),
|
|
1423
|
-
|
|
1193
|
+
width=widths[index][1], line_style=styles[index][1], color=colors[index][1],
|
|
1194
|
+
clip=True, line_caps="square", z_index=99)
|
|
1195
|
+
if index == 0:
|
|
1196
|
+
pos = [round(i / 100, 2) for i in plot.text1.pos]
|
|
1197
|
+
color = self.color_rgb_normalized(self.color_hex_to_rgb(plot.text1.color))
|
|
1198
|
+
elif index == 1:
|
|
1199
|
+
pos = [round(i / 100, 2) for i in plot.text2.pos]
|
|
1200
|
+
color = self.color_rgb_normalized(self.color_hex_to_rgb(plot.text2.color))
|
|
1201
|
+
else:
|
|
1202
|
+
pos = (0.6, 0.7)
|
|
1203
|
+
color = "black"
|
|
1424
1204
|
age, sage = round(age_results[index]['age'], 2), round(age_results[index]['s2'], 2)
|
|
1425
1205
|
F, sF = round(age_results[index]['F'], 2), round(age_results[index]['sF'], 2)
|
|
1426
1206
|
Num = int(age_results[index]['Num'])
|
|
1427
1207
|
MSWD, Ar39 = round(age_results[index]['MSWD'], 2), round(age_results[index]['Ar39'], 2)
|
|
1428
1208
|
Chisq, Pvalue = round(age_results[index]['Chisq'], 2), round(age_results[index]['Pvalue'], 2)
|
|
1429
|
-
pt.text(x=(xaxis_max - xaxis_min) * 0
|
|
1430
|
-
y=(yaxis_max - yaxis_min) *
|
|
1209
|
+
pt.text(x=(xaxis_max - xaxis_min) * pos[0] + xaxis_min,
|
|
1210
|
+
y=(yaxis_max - yaxis_min) * pos[1] + yaxis_min,
|
|
1431
1211
|
text=f"Age ={age} {chr(0xb1)} {sage} Ma<r>WMF = {F} {chr(0xb1)} {sF}, n = {Num}<r>"
|
|
1432
1212
|
f"MSWD = {MSWD}, <sup>39</sup>Ar = {Ar39}%<r>"
|
|
1433
1213
|
f"Chisq = {Chisq}, p = {Pvalue}",
|
|
1434
|
-
clip=True, coordinate="scale", h_align="middle", v_align="center",
|
|
1214
|
+
size=10, clip=True, coordinate="scale", h_align="middle", v_align="center",
|
|
1215
|
+
color=color, rotate=0, z_index=150)
|
|
1435
1216
|
|
|
1436
1217
|
# split sticks
|
|
1437
1218
|
for i in range(xaxis.split_number + 1):
|
|
@@ -1439,8 +1220,87 @@ class CreatePDF:
|
|
|
1439
1220
|
end = pt.scale_to_points(xaxis_min + xaxis.interval * i, yaxis_min)
|
|
1440
1221
|
end = (end[0], start[1] - 5)
|
|
1441
1222
|
if not pt.is_out_side(*start):
|
|
1442
|
-
pt.line(start=start, end=end, width=1, line_style="solid", clip=False, coordinate="pt")
|
|
1223
|
+
pt.line(start=start, end=end, width=1, line_style="solid", clip=False, coordinate="pt", z_index=100)
|
|
1443
1224
|
pt.text(x=start[0], y=end[1] - 15, text=f"{xaxis_min + xaxis.interval * i}", clip=False,
|
|
1225
|
+
coordinate="pt", h_align="middle", z_index=150)
|
|
1226
|
+
for i in range(yaxis.split_number + 1):
|
|
1227
|
+
start = pt.scale_to_points(xaxis_min, yaxis_min + yaxis.interval * i)
|
|
1228
|
+
end = pt.scale_to_points(xaxis_min, yaxis_min + yaxis.interval * i)
|
|
1229
|
+
end = (start[0] - 5, end[1])
|
|
1230
|
+
if not pt.is_out_side(*start):
|
|
1231
|
+
pt.line(start=start, end=end, width=1, line_style="solid", clip=False, coordinate="pt", z_index=100)
|
|
1232
|
+
pt.text(x=end[0] - 5, y=end[1], text=f"{yaxis_min + yaxis.interval * i}", clip=False,
|
|
1233
|
+
coordinate="pt", h_align="right", v_align="center", z_index=150)
|
|
1234
|
+
|
|
1235
|
+
# axis titles
|
|
1236
|
+
p = pt.scale_to_points((xaxis_max + xaxis_min) / 2, yaxis_min)
|
|
1237
|
+
pt.text(x=p[0], y=p[1] - 30, text=x_title, clip=False, coordinate="pt",
|
|
1238
|
+
h_align="middle", v_align="top", z_index=150)
|
|
1239
|
+
p = pt.scale_to_points(xaxis_min, (yaxis_max + yaxis_min) / 2)
|
|
1240
|
+
pt.text(x=p[0] - 50, y=p[1], text=y_title, clip=False, coordinate="pt",
|
|
1241
|
+
h_align="middle", v_align="bottom", rotate=90, z_index=150)
|
|
1242
|
+
|
|
1243
|
+
return cv
|
|
1244
|
+
|
|
1245
|
+
def plot_degas(self, smp: Sample = None, figure: str = 'figure_8'): # create a canvas
|
|
1246
|
+
if smp is None:
|
|
1247
|
+
smp = self.sample
|
|
1248
|
+
if figure != "figure_8":
|
|
1249
|
+
raise ValueError
|
|
1250
|
+
|
|
1251
|
+
x_title = f""
|
|
1252
|
+
y_title = f""
|
|
1253
|
+
|
|
1254
|
+
plot: Plot = smp.DegasPatternPlot
|
|
1255
|
+
title = plot.title.text
|
|
1256
|
+
xaxis: Plot.Axis = plot.xaxis
|
|
1257
|
+
yaxis: Plot.Axis = plot.yaxis
|
|
1258
|
+
x_title = xaxis.title.text
|
|
1259
|
+
y_title = yaxis.title.text
|
|
1260
|
+
xaxis_min = float(xaxis.min)
|
|
1261
|
+
xaxis_max = float(xaxis.max) + 2
|
|
1262
|
+
yaxis_min = float(yaxis.min)
|
|
1263
|
+
yaxis_max = float(yaxis.max)
|
|
1264
|
+
plot_scale = (xaxis_min, xaxis_max, yaxis_min, yaxis_max)
|
|
1265
|
+
|
|
1266
|
+
colors = ['red', 'color']
|
|
1267
|
+
|
|
1268
|
+
# data
|
|
1269
|
+
data = plot.data # 36a, 37ca, 38cl, 39k, 40r, 36, 37, 38, 39, 40
|
|
1270
|
+
|
|
1271
|
+
# create a canvas
|
|
1272
|
+
cv = pm.Canvas(width=17, height=12, unit="cm", show_frame=True, clip_outside_plot_areas=False)
|
|
1273
|
+
# change frame outline style
|
|
1274
|
+
cv.show_frame(color="grey", line_width=0.5)
|
|
1275
|
+
pt = cv.add_plot_area(name="Plot1", plot_area=(0.15, 0.15, 0.8, 0.8), plot_scale=plot_scale, show_frame=True)
|
|
1276
|
+
|
|
1277
|
+
COLOR_MAP_1: list = [
|
|
1278
|
+
# 3399FF, 33FF99, CCCC00, FF6666,
|
|
1279
|
+
[0.200, 0.600, 1.000], [0.200, 1.000, 0.600], [0.800, 0.800, 0.000], [1.000, 0.400, 0.400],
|
|
1280
|
+
# 00FFFF, 00994C, FF8000, 7F00FF
|
|
1281
|
+
[0.000, 1.000, 1.000], [0.000, 0.600, 0.298], [1.000, 0.502, 0.000], [0.498, 0.000, 1.000],
|
|
1282
|
+
# 3333FF, FF3399
|
|
1283
|
+
[1.000, 0.200, 0.600], [0.200, 0.200, 1.000],
|
|
1284
|
+
]
|
|
1285
|
+
|
|
1286
|
+
# spectra lines
|
|
1287
|
+
data = plot.data
|
|
1288
|
+
for i, isotope in enumerate(data):
|
|
1289
|
+
color = COLOR_MAP_1[i]
|
|
1290
|
+
for index, point in enumerate(isotope):
|
|
1291
|
+
# plot scatter pints
|
|
1292
|
+
pt.scatter(index + 1, point, fill_color="white", stroke_color=color, size=2)
|
|
1293
|
+
if index != 0:
|
|
1294
|
+
pt.line(start=(index, isotope[index - 1]), end=(index + 1, point), clip=True, width=1, color=color)
|
|
1295
|
+
|
|
1296
|
+
# split sticks
|
|
1297
|
+
for i in range(xaxis.split_number + 1):
|
|
1298
|
+
start = pt.scale_to_points(xaxis_min + xaxis.interval * i, yaxis_min)
|
|
1299
|
+
end = pt.scale_to_points(xaxis_min + xaxis.interval * i, yaxis_min)
|
|
1300
|
+
end = (end[0], start[1] - 5)
|
|
1301
|
+
if not pt.is_out_side(*start):
|
|
1302
|
+
pt.line(start=start, end=end, width=1, line_style="solid", clip=False, coordinate="pt")
|
|
1303
|
+
pt.text(x=start[0], y=end[1] - 15, text=f"{int(xaxis_min + xaxis.interval * i)}", clip=False,
|
|
1444
1304
|
coordinate="pt", h_align="middle")
|
|
1445
1305
|
for i in range(yaxis.split_number + 1):
|
|
1446
1306
|
start = pt.scale_to_points(xaxis_min, yaxis_min + yaxis.interval * i)
|
|
@@ -1460,19 +1320,103 @@ class CreatePDF:
|
|
|
1460
1320
|
|
|
1461
1321
|
return cv
|
|
1462
1322
|
|
|
1463
|
-
def
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1323
|
+
def plot_age_distribution(self, smp: Sample = None, figure: str = 'figure_9'):
|
|
1324
|
+
if smp is None:
|
|
1325
|
+
smp = self.sample
|
|
1326
|
+
if figure != "figure_9":
|
|
1327
|
+
raise ValueError
|
|
1328
|
+
|
|
1329
|
+
plot: Plot = smp.AgeDistributionPlot
|
|
1330
|
+
title = plot.title.text
|
|
1331
|
+
xaxis: Plot.Axis = plot.xaxis
|
|
1332
|
+
yaxis: Plot.Axis = plot.yaxis
|
|
1333
|
+
x_title = f"<sup>40</sup>Ar/<sup>39</sup>Ar Age (Ma)"
|
|
1334
|
+
y_title = yaxis.title.text
|
|
1335
|
+
xaxis_min = float(xaxis.min)
|
|
1336
|
+
xaxis_max = float(xaxis.max)
|
|
1337
|
+
yaxis_min = float(yaxis.min)
|
|
1338
|
+
yaxis_max = float(yaxis.max)
|
|
1339
|
+
plot_scale = (xaxis_min, xaxis_max, yaxis_min, yaxis_max)
|
|
1468
1340
|
|
|
1469
|
-
def plot_age_distribution(self, figure: str = 'figure_9'): # create a canvas
|
|
1470
1341
|
cv = pm.Canvas(width=17, height=12, unit="cm", show_frame=True, clip_outside_plot_areas=False)
|
|
1471
1342
|
# change frame outline style
|
|
1472
1343
|
cv.show_frame(color="grey", line_width=0.5)
|
|
1473
|
-
|
|
1344
|
+
pt = cv.add_plot_area(name="Plot1", plot_area=(0.15, 0.15, 0.8, 0.8), plot_scale=plot_scale, show_frame=True)
|
|
1345
|
+
|
|
1346
|
+
# histogram
|
|
1347
|
+
color = self.color_rgb_normalized(self.color_hex_to_rgb(plot.set1.border_color))
|
|
1348
|
+
fill_color = self.color_rgb_normalized(self.color_hex_to_rgb(plot.set1.color))
|
|
1349
|
+
for i in range(plot.set1.bin_count):
|
|
1350
|
+
pt.rect(left_bottom=[plot.set1.data[2][i][0], 0], width=plot.set1.bin_width, height=plot.set1.data[1][i],
|
|
1351
|
+
line_width=0, color=fill_color, fill_color=fill_color, fill=True, coordinate='scale', z_index=0)
|
|
1352
|
+
pt.line(start=[plot.set1.data[2][i][0], 0], end=[plot.set1.data[2][i][0], plot.set1.data[1][i]],
|
|
1353
|
+
color=color, line_style=plot.set1.border_type, width=plot.set1.border_width,
|
|
1354
|
+
coordinate='scale', z_index=1)
|
|
1355
|
+
pt.line(start=[plot.set1.data[2][i][0], plot.set1.data[1][i]],
|
|
1356
|
+
end=[plot.set1.data[2][i][0] + plot.set1.bin_width, plot.set1.data[1][i]],
|
|
1357
|
+
color=color, line_style=plot.set1.border_type, width=plot.set1.border_width,
|
|
1358
|
+
coordinate='scale', z_index=1)
|
|
1359
|
+
pt.line(start=[plot.set1.data[2][i][0] + plot.set1.bin_width, plot.set1.data[1][i]],
|
|
1360
|
+
end=[plot.set1.data[2][i][0] + plot.set1.bin_width, 0],
|
|
1361
|
+
color=color, line_style=plot.set1.border_type, width=plot.set1.border_width,
|
|
1362
|
+
coordinate='scale', z_index=1)
|
|
1363
|
+
|
|
1364
|
+
# KDE
|
|
1365
|
+
scale = max(plot.set1.data[1]) / max(plot.set2.data[1])
|
|
1366
|
+
color = self.color_rgb_normalized(self.color_hex_to_rgb(plot.set2.color))
|
|
1367
|
+
for i in range(plot.set2.band_points):
|
|
1368
|
+
pt.line(start=[plot.set2.data[0][i], plot.set2.data[1][i] * scale],
|
|
1369
|
+
end=[plot.set2.data[0][i + 1], plot.set2.data[1][i + 1] * scale],
|
|
1370
|
+
color=color, line_style=plot.set2.line_type, width=plot.set2.line_width,
|
|
1371
|
+
coordinate='scale', z_index=5)
|
|
1372
|
+
|
|
1373
|
+
# age bars
|
|
1374
|
+
ages = sorted(zip(*plot.set3.data), key=lambda x: x[0])
|
|
1375
|
+
color = self.color_rgb_normalized(self.color_hex_to_rgb(plot.set3.color))
|
|
1376
|
+
fill_color = self.color_rgb_normalized(self.color_hex_to_rgb(plot.set3.border_color))
|
|
1377
|
+
ppu_y = pt.ppu("y")
|
|
1378
|
+
height = float(plot.set3.bar_height) / ppu_y
|
|
1379
|
+
interval = float(plot.set3.bar_interval) / ppu_y if plot.set3.vertical_align == "bottom" else ((yaxis_max - yaxis_min) - height * len(ages)) / (len(ages) + 1)
|
|
1380
|
+
for index, age in enumerate(ages):
|
|
1381
|
+
pt.rect(left_bottom=[age[0] - age[1], interval + index * (interval + height)],
|
|
1382
|
+
width=age[1] * 2, height=height, color=color, fill_color=fill_color, fill=True,
|
|
1383
|
+
line_width=plot.set3.border_width, coordinate='scale', z_index=1)
|
|
1384
|
+
|
|
1385
|
+
pos = [round(i / 100, 2) for i in plot.text1.pos]
|
|
1386
|
+
color = self.color_rgb_normalized(self.color_hex_to_rgb(plot.text1.color))
|
|
1387
|
+
text = plot.text1.text.replace('\n', '<r>')
|
|
1388
|
+
pt.text(x=(xaxis_max - xaxis_min) * pos[0] + xaxis_min,
|
|
1389
|
+
y=(yaxis_max - yaxis_min) * pos[1] + yaxis_min,
|
|
1390
|
+
text=text, size=10, clip=True, coordinate="scale", color=color,
|
|
1391
|
+
h_align="middle", v_align="center", rotate=0, z_index=100)
|
|
1392
|
+
|
|
1393
|
+
# split sticks
|
|
1394
|
+
for i in range(xaxis.split_number + 1):
|
|
1395
|
+
start = pt.scale_to_points(xaxis_min + xaxis.interval * i, yaxis_min)
|
|
1396
|
+
end = pt.scale_to_points(xaxis_min + xaxis.interval * i, yaxis_min)
|
|
1397
|
+
end = (end[0], start[1] - 5)
|
|
1398
|
+
if not pt.is_out_side(*start):
|
|
1399
|
+
pt.line(start=start, end=end, width=1, line_style="solid", clip=False, coordinate="pt", z_index=50)
|
|
1400
|
+
pt.text(x=start[0], y=end[1] - 15, text=f"{int(xaxis_min + xaxis.interval * i)}", clip=False,
|
|
1401
|
+
coordinate="pt", h_align="middle", z_index=100)
|
|
1402
|
+
for i in range(yaxis.split_number + 1):
|
|
1403
|
+
start = pt.scale_to_points(xaxis_min, yaxis_min + yaxis.interval * i)
|
|
1404
|
+
end = pt.scale_to_points(xaxis_min, yaxis_min + yaxis.interval * i)
|
|
1405
|
+
end = (start[0] - 5, end[1])
|
|
1406
|
+
if not pt.is_out_side(*start):
|
|
1407
|
+
pt.line(start=start, end=end, width=1, line_style="solid", clip=False, coordinate="pt", z_index=50)
|
|
1408
|
+
pt.text(x=end[0] - 5, y=end[1], text=f"{yaxis_min + yaxis.interval * i}", clip=False,
|
|
1409
|
+
coordinate="pt", h_align="right", v_align="center", z_index=100)
|
|
1474
1410
|
|
|
1411
|
+
# axis titles
|
|
1412
|
+
p = pt.scale_to_points((xaxis_max + xaxis_min) / 2, yaxis_min)
|
|
1413
|
+
pt.text(x=p[0], y=p[1] - 30, text=x_title, clip=False, coordinate="pt",
|
|
1414
|
+
h_align="middle", v_align="top", z_index=150)
|
|
1415
|
+
p = pt.scale_to_points(xaxis_min, (yaxis_max + yaxis_min) / 2)
|
|
1416
|
+
pt.text(x=p[0] - 50, y=p[1], text=y_title, clip=False, coordinate="pt",
|
|
1417
|
+
h_align="middle", v_align="bottom", rotate=90, z_index=150)
|
|
1475
1418
|
|
|
1419
|
+
return cv
|
|
1476
1420
|
|
|
1477
1421
|
|
|
1478
1422
|
class CustomUnpickler(pickle.Unpickler):
|