pypsbuilder 2.3.6__tar.gz → 2.4.0__tar.gz
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.
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/CHANGELOG.md +6 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/PKG-INFO +7 -1
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/docs/conf.py +47 -36
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder/__init__.py +1 -1
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder/psexplorer.py +220 -72
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder.egg-info/PKG-INFO +7 -1
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/setup.cfg +1 -1
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/setup.py +17 -24
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/AUTHORS.md +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/CONTRIBUTING.md +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/LICENSE +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/MANIFEST.in +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/README.md +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/docs/Makefile +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/docs/api/pypsbuilder.psclasses.Dogmin.rst +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/docs/api/pypsbuilder.psclasses.InvPoint.rst +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/docs/api/pypsbuilder.psclasses.PTsection.rst +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/docs/api/pypsbuilder.psclasses.PXsection.rst +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/docs/api/pypsbuilder.psclasses.TCResult.rst +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/docs/api/pypsbuilder.psclasses.TCResultSet.rst +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/docs/api/pypsbuilder.psclasses.TXsection.rst +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/docs/api/pypsbuilder.psclasses.UniLine.rst +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/docs/api/pypsbuilder.psexplorer.PTPS.rst +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/docs/api/pypsbuilder.psexplorer.PXPS.rst +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/docs/api/pypsbuilder.psexplorer.TXPS.rst +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/docs/api/pypsbuilder.tcapi.TC34API.rst +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/docs/api/pypsbuilder.tcapi.TC35API.rst +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/docs/api.rst +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/docs/authors.rst +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/docs/command-line.rst +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/docs/index.rst +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/docs/installation.rst +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/docs/psbuilders-tutorial.rst +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/docs/psexplorer-tutorial.rst +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder/images/__init__.py +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder/images/ptbuilder.png +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder/images/pxbuilder.png +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder/images/pypsbuilder.png +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder/images/txbuilder.png +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder/psbuilders.py +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder/psclasses.py +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder/tcapi.py +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder/tcinit.py +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder/tests/__init__.py +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder/tests/test_pclasses.py +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder/ui_addinv.py +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder/ui_adduni.py +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder/ui_ptbuilder.py +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder/ui_pxbuilder.py +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder/ui_txbuilder.py +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder/ui_uniguess.py +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder.egg-info/SOURCES.txt +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder.egg-info/dependency_links.txt +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder.egg-info/entry_points.txt +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder.egg-info/not-zip-safe +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder.egg-info/requires.txt +0 -0
- {pypsbuilder-2.3.6 → pypsbuilder-2.4.0}/pypsbuilder.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
All notable pypsbuilder changes.
|
|
3
3
|
|
|
4
|
+
## [2.4.0] - 2023-12-21
|
|
5
|
+
### Fixed
|
|
6
|
+
- important collect_grid_data bug causing isopleths twisting fixed.
|
|
7
|
+
- collect_ptpath missing field check added
|
|
8
|
+
- remove_grid_data method added
|
|
9
|
+
- isopleths bivariate spline method added
|
|
4
10
|
## [2.3.6] - 2023-12-13
|
|
5
11
|
### Added
|
|
6
12
|
- search_composition method added to PTPS to find best estimate for isopleths intersection
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pypsbuilder
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.0
|
|
4
4
|
Summary: THERMOCALC front-end for constructing and analyzing PT pseudosections
|
|
5
5
|
Home-page: https://github.com/ondrolexa/pypsbuilder
|
|
6
6
|
Author: Ondrej Lexa
|
|
@@ -88,6 +88,12 @@ pypsbuilder is free software: you can redistribute it and/or modify it under the
|
|
|
88
88
|
# Changelog
|
|
89
89
|
All notable pypsbuilder changes.
|
|
90
90
|
|
|
91
|
+
## [2.4.0] - 2023-12-21
|
|
92
|
+
### Fixed
|
|
93
|
+
- important collect_grid_data bug causing isopleths twisting fixed.
|
|
94
|
+
- collect_ptpath missing field check added
|
|
95
|
+
- remove_grid_data method added
|
|
96
|
+
- isopleths bivariate spline method added
|
|
91
97
|
## [2.3.6] - 2023-12-13
|
|
92
98
|
### Added
|
|
93
99
|
- search_composition method added to PTPS to find best estimate for isopleths intersection
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
import os
|
|
21
21
|
import sys
|
|
22
22
|
|
|
23
|
-
sys.path.insert(0, os.path.abspath(
|
|
24
|
-
sys.path.insert(0, os.path.abspath(
|
|
25
|
-
sys.path.insert(0, os.path.abspath(
|
|
23
|
+
sys.path.insert(0, os.path.abspath("."))
|
|
24
|
+
sys.path.insert(0, os.path.abspath(".."))
|
|
25
|
+
sys.path.insert(0, os.path.abspath("../"))
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
# -- General configuration ------------------------------------------------
|
|
@@ -35,42 +35,49 @@ sys.path.insert(0, os.path.abspath('../'))
|
|
|
35
35
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
|
36
36
|
# ones.
|
|
37
37
|
extensions = [
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
"sphinx.ext.todo",
|
|
39
|
+
"sphinx.ext.autodoc",
|
|
40
|
+
"sphinx.ext.napoleon",
|
|
41
|
+
"sphinx.ext.autosummary",
|
|
42
42
|
]
|
|
43
43
|
|
|
44
44
|
napoleon_google_docstring = True
|
|
45
45
|
napoleon_numpy_docstring = False
|
|
46
46
|
|
|
47
|
-
autodoc_mock_imports = [
|
|
48
|
-
|
|
47
|
+
autodoc_mock_imports = [
|
|
48
|
+
"numpy",
|
|
49
|
+
"matplotlib",
|
|
50
|
+
"scipy",
|
|
51
|
+
"shapely",
|
|
52
|
+
"networkx",
|
|
53
|
+
"tqdm",
|
|
54
|
+
"mpl_toolkits",
|
|
55
|
+
]
|
|
49
56
|
# Add any paths that contain templates here, relative to this directory.
|
|
50
|
-
templates_path = [
|
|
57
|
+
templates_path = ["_templates"]
|
|
51
58
|
|
|
52
59
|
# The suffix(es) of source filenames.
|
|
53
60
|
# You can specify multiple suffix as a list of string:
|
|
54
61
|
#
|
|
55
62
|
# source_suffix = ['.rst', '.md']
|
|
56
|
-
source_suffix =
|
|
63
|
+
source_suffix = ".rst"
|
|
57
64
|
|
|
58
65
|
# The master toctree document.
|
|
59
|
-
master_doc =
|
|
66
|
+
master_doc = "index"
|
|
60
67
|
|
|
61
68
|
# General information about the project.
|
|
62
|
-
project =
|
|
63
|
-
copyright =
|
|
64
|
-
author =
|
|
69
|
+
project = "pypsbuilder"
|
|
70
|
+
copyright = "2020, Ondrej Lexa"
|
|
71
|
+
author = "Ondrej Lexa"
|
|
65
72
|
|
|
66
73
|
# The version info for the project you're documenting, acts as replacement for
|
|
67
74
|
# |version| and |release|, also used in various other places throughout the
|
|
68
75
|
# built documents.
|
|
69
76
|
#
|
|
70
77
|
# The short X.Y version.
|
|
71
|
-
version =
|
|
78
|
+
version = "2.4"
|
|
72
79
|
# The full version, including alpha/beta/rc tags.
|
|
73
|
-
release =
|
|
80
|
+
release = "2.4.0"
|
|
74
81
|
|
|
75
82
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
|
76
83
|
# for a list of supported languages.
|
|
@@ -82,22 +89,21 @@ language = None
|
|
|
82
89
|
# List of patterns, relative to source directory, that match files and
|
|
83
90
|
# directories to ignore when looking for source files.
|
|
84
91
|
# This patterns also effect to html_static_path and html_extra_path
|
|
85
|
-
exclude_patterns = [
|
|
92
|
+
exclude_patterns = ["_build", "**.ipynb_checkpoints", "Thumbs.db", ".DS_Store"]
|
|
86
93
|
|
|
87
94
|
# The name of the Pygments (syntax highlighting) style to use.
|
|
88
|
-
pygments_style =
|
|
95
|
+
pygments_style = "sphinx"
|
|
89
96
|
|
|
90
97
|
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
|
91
98
|
todo_include_todos = True
|
|
92
99
|
|
|
93
|
-
autodoc_default_options = {
|
|
94
|
-
'show-inheritance': True}
|
|
100
|
+
autodoc_default_options = {"member-order": "bysource", "show-inheritance": True}
|
|
95
101
|
autosummary_generate = True
|
|
96
102
|
# -- Options for HTML output ----------------------------------------------
|
|
97
103
|
|
|
98
104
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
|
99
105
|
# a list of builtin themes.
|
|
100
|
-
html_theme =
|
|
106
|
+
html_theme = "sphinx_rtd_theme"
|
|
101
107
|
|
|
102
108
|
# Theme options are theme-specific and customize the look and feel of a theme
|
|
103
109
|
# further. For a list of options available for each theme, see the
|
|
@@ -108,7 +114,7 @@ html_theme = 'sphinx_rtd_theme'
|
|
|
108
114
|
# Add any paths that contain custom static files (such as style sheets) here,
|
|
109
115
|
# relative to this directory. They are copied after the builtin static files,
|
|
110
116
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
|
111
|
-
html_static_path = [
|
|
117
|
+
html_static_path = ["_static"]
|
|
112
118
|
|
|
113
119
|
# Hide source link
|
|
114
120
|
html_show_sourcelink = False
|
|
@@ -116,7 +122,7 @@ html_show_sourcelink = False
|
|
|
116
122
|
# -- Options for HTMLHelp output ------------------------------------------
|
|
117
123
|
|
|
118
124
|
# Output file base name for HTML help builder.
|
|
119
|
-
htmlhelp_basename =
|
|
125
|
+
htmlhelp_basename = "pypsbuilderdoc"
|
|
120
126
|
|
|
121
127
|
|
|
122
128
|
# -- Options for LaTeX output ---------------------------------------------
|
|
@@ -125,15 +131,12 @@ latex_elements = {
|
|
|
125
131
|
# The paper size ('letterpaper' or 'a4paper').
|
|
126
132
|
#
|
|
127
133
|
# 'papersize': 'letterpaper',
|
|
128
|
-
|
|
129
134
|
# The font size ('10pt', '11pt' or '12pt').
|
|
130
135
|
#
|
|
131
136
|
# 'pointsize': '10pt',
|
|
132
|
-
|
|
133
137
|
# Additional stuff for the LaTeX preamble.
|
|
134
138
|
#
|
|
135
139
|
# 'preamble': '',
|
|
136
|
-
|
|
137
140
|
# Latex figure (float) alignment
|
|
138
141
|
#
|
|
139
142
|
# 'figure_align': 'htbp',
|
|
@@ -143,8 +146,13 @@ latex_elements = {
|
|
|
143
146
|
# (source start file, target name, title,
|
|
144
147
|
# author, documentclass [howto, manual, or own class]).
|
|
145
148
|
latex_documents = [
|
|
146
|
-
(
|
|
147
|
-
|
|
149
|
+
(
|
|
150
|
+
master_doc,
|
|
151
|
+
"pypsbuilder.tex",
|
|
152
|
+
"pypsbuilder Documentation",
|
|
153
|
+
"Ondrej Lexa",
|
|
154
|
+
"manual",
|
|
155
|
+
),
|
|
148
156
|
]
|
|
149
157
|
|
|
150
158
|
|
|
@@ -152,10 +160,7 @@ latex_documents = [
|
|
|
152
160
|
|
|
153
161
|
# One entry per manual page. List of tuples
|
|
154
162
|
# (source start file, name, description, authors, manual section).
|
|
155
|
-
man_pages = [
|
|
156
|
-
(master_doc, 'pypsbuilder', 'pypsbuilder Documentation',
|
|
157
|
-
[author], 1)
|
|
158
|
-
]
|
|
163
|
+
man_pages = [(master_doc, "pypsbuilder", "pypsbuilder Documentation", [author], 1)]
|
|
159
164
|
|
|
160
165
|
|
|
161
166
|
# -- Options for Texinfo output -------------------------------------------
|
|
@@ -164,7 +169,13 @@ man_pages = [
|
|
|
164
169
|
# (source start file, target name, title, author,
|
|
165
170
|
# dir menu entry, description, category)
|
|
166
171
|
texinfo_documents = [
|
|
167
|
-
(
|
|
168
|
-
|
|
169
|
-
|
|
172
|
+
(
|
|
173
|
+
master_doc,
|
|
174
|
+
"pypsbuilder",
|
|
175
|
+
"pypsbuilder Documentation",
|
|
176
|
+
author,
|
|
177
|
+
"pypsbuilder",
|
|
178
|
+
"One line description of project.",
|
|
179
|
+
"Miscellaneous",
|
|
180
|
+
),
|
|
170
181
|
]
|
|
@@ -46,7 +46,7 @@ from matplotlib import ticker
|
|
|
46
46
|
|
|
47
47
|
from shapely.geometry import MultiPoint, Point, LineString
|
|
48
48
|
from shapely.ops import linemerge
|
|
49
|
-
from scipy.interpolate import Rbf, interp1d
|
|
49
|
+
from scipy.interpolate import Rbf, interp1d, SmoothBivariateSpline
|
|
50
50
|
from scipy.linalg import LinAlgWarning, lstsq
|
|
51
51
|
from scipy.interpolate import griddata # interp2d
|
|
52
52
|
from tqdm import tqdm, trange
|
|
@@ -539,17 +539,18 @@ class PS:
|
|
|
539
539
|
if self.gridded:
|
|
540
540
|
for ix, grid in self.grids.items():
|
|
541
541
|
if key in grid.masks:
|
|
542
|
-
|
|
542
|
+
ok = grid.masks[key] & (grid.status == 1)
|
|
543
|
+
results = grid.gridcalcs[ok]
|
|
543
544
|
if len(results) > 0:
|
|
544
545
|
if phase in results[0].phases:
|
|
545
546
|
gdt = zip(
|
|
546
|
-
grid.xg[
|
|
547
|
-
grid.yg[
|
|
547
|
+
grid.xg[ok],
|
|
548
|
+
grid.yg[ok],
|
|
548
549
|
results,
|
|
549
|
-
grid.status[
|
|
550
|
+
grid.status[ok],
|
|
550
551
|
)
|
|
551
|
-
for x, y, res,
|
|
552
|
-
if
|
|
552
|
+
for x, y, res, status in gdt:
|
|
553
|
+
if status == 1:
|
|
553
554
|
dt["pts"].append((x, y))
|
|
554
555
|
dt["data"].append(eval_expr(expr, res[phase]))
|
|
555
556
|
# else:
|
|
@@ -912,12 +913,15 @@ class PS:
|
|
|
912
913
|
"""
|
|
913
914
|
if self.check_phase_expr(phase, expr):
|
|
914
915
|
dt = self.collect_data(key, phase, expr, which=which)
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
916
|
+
if dt["pts"]:
|
|
917
|
+
x, y = np.array(dt["pts"]).T
|
|
918
|
+
fig, ax = plt.subplots()
|
|
919
|
+
pts = ax.scatter(x, y, c=dt["data"])
|
|
920
|
+
ax.set_title("{} - {}({})".format(" ".join(key), phase, expr))
|
|
921
|
+
plt.colorbar(pts)
|
|
922
|
+
plt.show()
|
|
923
|
+
else:
|
|
924
|
+
print("No data collected")
|
|
921
925
|
|
|
922
926
|
def show_grid(
|
|
923
927
|
self, phase, expr=None, interpolation=None, label=False, skiplabels=0, labelfs=6
|
|
@@ -991,6 +995,8 @@ class PS:
|
|
|
991
995
|
fig=None,
|
|
992
996
|
fig_kw={},
|
|
993
997
|
isopleths=False,
|
|
998
|
+
which=7,
|
|
999
|
+
smooth=0,
|
|
994
1000
|
):
|
|
995
1001
|
"""Function to plot root squared error of calculated and estimated values.
|
|
996
1002
|
|
|
@@ -1013,6 +1019,9 @@ class PS:
|
|
|
1013
1019
|
Default None
|
|
1014
1020
|
fig_kw: dict passed to subplots method.
|
|
1015
1021
|
isopleths (bool): When True, searched isoplots are shown.Default False
|
|
1022
|
+
which (int): Bitopt defining from where data are collected. 0 bit -
|
|
1023
|
+
invariant points, 1 bit - uniariant lines and 2 bit - GridData
|
|
1024
|
+
points
|
|
1016
1025
|
|
|
1017
1026
|
Example:
|
|
1018
1027
|
>>> pt.search_composition(
|
|
@@ -1027,16 +1036,25 @@ class PS:
|
|
|
1027
1036
|
err = []
|
|
1028
1037
|
for phase, expr, val in zip(args[::3], args[1::3], args[2::3]):
|
|
1029
1038
|
if self.check_phase_expr(phase, expr):
|
|
1030
|
-
err.append(
|
|
1039
|
+
err.append(
|
|
1040
|
+
(
|
|
1041
|
+
self.get_gridded(
|
|
1042
|
+
phase, expr, which=which, smooth=smooth
|
|
1043
|
+
)
|
|
1044
|
+
- val
|
|
1045
|
+
)
|
|
1046
|
+
** 2
|
|
1047
|
+
)
|
|
1031
1048
|
|
|
1032
|
-
err = np.sqrt(sum(err))
|
|
1049
|
+
err = np.sqrt(sum(err)) / len(err)
|
|
1033
1050
|
r, c = np.unravel_index(np.nanargmin(err), err.shape)
|
|
1034
1051
|
p = self.yspace[r]
|
|
1035
1052
|
T = self.xspace[c]
|
|
1053
|
+
minerr = err[r, c]
|
|
1036
1054
|
if geterror:
|
|
1037
1055
|
return err
|
|
1038
1056
|
elif getpt:
|
|
1039
|
-
return p, T,
|
|
1057
|
+
return p, T, minerr
|
|
1040
1058
|
else:
|
|
1041
1059
|
if fig is None:
|
|
1042
1060
|
fig, ax = plt.subplots(**fig_kw)
|
|
@@ -1064,7 +1082,7 @@ class PS:
|
|
|
1064
1082
|
ax.set_ylim(self.yrange)
|
|
1065
1083
|
fig.colorbar(im)
|
|
1066
1084
|
|
|
1067
|
-
ax.set_title(f"RMSE -
|
|
1085
|
+
ax.set_title(f"RMSE - MinErr={minerr:g} at {T} {p}")
|
|
1068
1086
|
fig.tight_layout()
|
|
1069
1087
|
plt.show()
|
|
1070
1088
|
else:
|
|
@@ -1245,6 +1263,38 @@ class PS:
|
|
|
1245
1263
|
print(output)
|
|
1246
1264
|
return res[0]
|
|
1247
1265
|
|
|
1266
|
+
def remove_grid_data(self, key, phase, expr):
|
|
1267
|
+
"""Remove calculated data from grid and mark as failed
|
|
1268
|
+
|
|
1269
|
+
Note: Click on all data to be discarded by mouse and finish be Enter
|
|
1270
|
+
|
|
1271
|
+
Args:
|
|
1272
|
+
key (frozenset): Key identifying divariant field
|
|
1273
|
+
phase (str): Phase or end-member named
|
|
1274
|
+
expr (str): Expression to evaluate. It could use any variable
|
|
1275
|
+
existing for given phase. Check `all_data_keys` property for
|
|
1276
|
+
possible variables.
|
|
1277
|
+
"""
|
|
1278
|
+
|
|
1279
|
+
if self.gridded:
|
|
1280
|
+
dt = self.collect_data(key, phase, expr, which=4)
|
|
1281
|
+
x, y = np.array(dt["pts"]).T
|
|
1282
|
+
fig, ax = plt.subplots()
|
|
1283
|
+
pts = ax.scatter(x, y, c=dt["data"])
|
|
1284
|
+
plt.colorbar(pts)
|
|
1285
|
+
xy = plt.ginput(0)
|
|
1286
|
+
plt.close(fig)
|
|
1287
|
+
for x, y in xy:
|
|
1288
|
+
ix = self.get_section_id(x, y)
|
|
1289
|
+
if ix is not None:
|
|
1290
|
+
r, c = self.grids[ix].get_indexes(x, y)
|
|
1291
|
+
self.grids[ix].status[r, c] = 0
|
|
1292
|
+
# self.grids[ix].masks[key][r, c] = False
|
|
1293
|
+
self.grids[ix].gridcalcs[r, c] = None
|
|
1294
|
+
self.grids[ix].delta[r, c] = np.nan
|
|
1295
|
+
else:
|
|
1296
|
+
print("Not yet gridded...")
|
|
1297
|
+
|
|
1248
1298
|
def ginput_path(self, label=False, skiplabels=0, labelfs=6):
|
|
1249
1299
|
"""Collect Path data by mouse digitizing.
|
|
1250
1300
|
|
|
@@ -1293,7 +1343,8 @@ class PS:
|
|
|
1293
1343
|
invariant points, 1 bit - uniariant lines and 2 bit - GridData
|
|
1294
1344
|
points. Default 7 (all data)
|
|
1295
1345
|
method: Interpolation method. Default is 'rbf', other option is
|
|
1296
|
-
'quadratic', which uses least-square fit to quadratic surface
|
|
1346
|
+
'quadratic', which uses least-square fit to quadratic surface
|
|
1347
|
+
or 'spline' for bivariate spline interpolation.
|
|
1297
1348
|
rbf_func: Default 'thin_plate'. See scipy.interpolation.Rbf
|
|
1298
1349
|
smooth (int): Values greater than zero increase the smoothness
|
|
1299
1350
|
of the approximation. 0 is for interpolation (default),
|
|
@@ -1301,7 +1352,9 @@ class PS:
|
|
|
1301
1352
|
epsilon (int): Adjustable constant for gaussian or multiquadrics
|
|
1302
1353
|
functions - defaults to approximate average distance between
|
|
1303
1354
|
nodes (which is a good start).
|
|
1355
|
+
degree (int): Degrees of the bivariate spline. Default is 3.
|
|
1304
1356
|
refine (int): Degree of grid refinement. Default 1
|
|
1357
|
+
filter_outliers (bool): Whether to filter outliers. Defaut False.
|
|
1305
1358
|
filled (bool): Whether to contours should be filled. Defaut True.
|
|
1306
1359
|
filled_over (bool): Whether to overlay contourline over filled
|
|
1307
1360
|
contours. Defaut False.
|
|
@@ -1346,6 +1399,8 @@ class PS:
|
|
|
1346
1399
|
gradient = kwargs.get("gradient", False)
|
|
1347
1400
|
dx = kwargs.get("dx", True)
|
|
1348
1401
|
only = kwargs.get("only", None)
|
|
1402
|
+
filter_outliers = kwargs.get("only", False)
|
|
1403
|
+
degree = kwargs.get("degree", 3)
|
|
1349
1404
|
refine = kwargs.get("refine", 1)
|
|
1350
1405
|
method = kwargs.get("method", "rbf")
|
|
1351
1406
|
rbf_func = kwargs.get("rbf_func", "thin_plate")
|
|
@@ -1424,9 +1479,22 @@ class PS:
|
|
|
1424
1479
|
self.gridystep / refine,
|
|
1425
1480
|
)
|
|
1426
1481
|
tg, pg = np.meshgrid(ttspace, ppspace)
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
data = recs[key]["data"]
|
|
1482
|
+
pts = np.array(recs[key]["pts"])
|
|
1483
|
+
x, y = pts.T
|
|
1484
|
+
data = np.array(recs[key]["data"])
|
|
1485
|
+
# filter outliers
|
|
1486
|
+
if filter_outliers:
|
|
1487
|
+
A = np.c_[np.ones_like(x), x, y, x * y, x**2, y**2]
|
|
1488
|
+
C, _, _, _ = lstsq(A, data)
|
|
1489
|
+
# evaluate it on a grid
|
|
1490
|
+
vals = np.dot(
|
|
1491
|
+
np.c_[np.ones_like(x), x, y, x * y, x**2, y**2], C
|
|
1492
|
+
)
|
|
1493
|
+
err = abs(vals - data)
|
|
1494
|
+
ok = err < err.std()
|
|
1495
|
+
pts = pts[ok, :]
|
|
1496
|
+
x, y = pts.T
|
|
1497
|
+
data = data[ok]
|
|
1430
1498
|
try:
|
|
1431
1499
|
if method == "quadratic":
|
|
1432
1500
|
tgg = tg.flatten()
|
|
@@ -1445,6 +1513,11 @@ class PS:
|
|
|
1445
1513
|
],
|
|
1446
1514
|
C,
|
|
1447
1515
|
).reshape(tg.shape)
|
|
1516
|
+
elif method == "spline":
|
|
1517
|
+
interp = SmoothBivariateSpline(
|
|
1518
|
+
x, self.ratio * y, data, kx=degree, ky=degree
|
|
1519
|
+
)
|
|
1520
|
+
zg = interp(tg, self.ratio * pg)
|
|
1448
1521
|
else:
|
|
1449
1522
|
with warnings.catch_warnings():
|
|
1450
1523
|
warnings.filterwarnings("error")
|
|
@@ -1461,29 +1534,19 @@ class PS:
|
|
|
1461
1534
|
if self.show_errors:
|
|
1462
1535
|
print(e)
|
|
1463
1536
|
try:
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
data,
|
|
1473
|
-
(tg, pg),
|
|
1474
|
-
method="nearest",
|
|
1475
|
-
rescale=True,
|
|
1476
|
-
)
|
|
1477
|
-
else:
|
|
1478
|
-
# preprocess with griddata
|
|
1479
|
-
zg_tmp = griddata(
|
|
1480
|
-
pts, data, (tg, pg), method="linear", rescale=True
|
|
1481
|
-
)
|
|
1537
|
+
zg = griddata(
|
|
1538
|
+
np.array(pts),
|
|
1539
|
+
data,
|
|
1540
|
+
(tg, pg),
|
|
1541
|
+
method="nearest",
|
|
1542
|
+
rescale=True,
|
|
1543
|
+
)
|
|
1544
|
+
if method == "rbf":
|
|
1482
1545
|
# locate valid data
|
|
1483
|
-
ri, ci = np.nonzero(np.isfinite(
|
|
1546
|
+
ri, ci = np.nonzero(np.isfinite(zg))
|
|
1484
1547
|
x, y, z = np.array(
|
|
1485
1548
|
[
|
|
1486
|
-
[tg[r, c], pg[r, c],
|
|
1549
|
+
[tg[r, c], pg[r, c], zg[r, c]]
|
|
1487
1550
|
for r, c in zip(ri, ci)
|
|
1488
1551
|
]
|
|
1489
1552
|
).T
|
|
@@ -1501,19 +1564,25 @@ class PS:
|
|
|
1501
1564
|
epsilon=epsilon,
|
|
1502
1565
|
)
|
|
1503
1566
|
zg = rbf(tg, self.ratio * pg)
|
|
1567
|
+
if method == "spline":
|
|
1568
|
+
# locate valid data
|
|
1569
|
+
ri, ci = np.nonzero(np.isfinite(zg))
|
|
1570
|
+
x, y, z = np.array(
|
|
1571
|
+
[
|
|
1572
|
+
[tg[r, c], pg[r, c], zg[r, c]]
|
|
1573
|
+
for r, c in zip(ri, ci)
|
|
1574
|
+
]
|
|
1575
|
+
).T
|
|
1576
|
+
interp = SmoothBivariateSpline(
|
|
1577
|
+
x, self.ratio * y, z, kx=degree, ky=degree
|
|
1578
|
+
)
|
|
1579
|
+
zg = interp(tg, self.ratio * pg)
|
|
1504
1580
|
except Exception:
|
|
1505
1581
|
print(
|
|
1506
1582
|
"Using nearest method in {}".format(
|
|
1507
1583
|
" ".join(sorted(list(key)))
|
|
1508
1584
|
)
|
|
1509
1585
|
)
|
|
1510
|
-
zg = griddata(
|
|
1511
|
-
np.array(pts),
|
|
1512
|
-
data,
|
|
1513
|
-
(tg, pg),
|
|
1514
|
-
method="nearest",
|
|
1515
|
-
rescale=True,
|
|
1516
|
-
)
|
|
1517
1586
|
# experimental
|
|
1518
1587
|
if gradient:
|
|
1519
1588
|
grd = np.gradient(zg, self.gridxstep, self.gridystep)
|
|
@@ -1674,6 +1743,9 @@ class PS:
|
|
|
1674
1743
|
epsilon (int): Adjustable constant for gaussian or multiquadrics
|
|
1675
1744
|
functions - defaults to approximate average distance between
|
|
1676
1745
|
nodes (which is a good start).
|
|
1746
|
+
degree (int): Degrees of the bivariate spline. Default is 3.
|
|
1747
|
+
refine (int): Degree of grid refinement. Default 1
|
|
1748
|
+
filter_outliers (bool): Whether to filter outliers. Defaut False.
|
|
1677
1749
|
out (str or list): Highligt zero-mode lines for given phases.
|
|
1678
1750
|
overlay (bool): Whether to show assemblage fields. Default True
|
|
1679
1751
|
high (frozenset or list): Highlight divariant fields identified
|
|
@@ -1707,6 +1779,8 @@ class PS:
|
|
|
1707
1779
|
cdf = kwargs.get("cdf", False)
|
|
1708
1780
|
overlay = kwargs.get("overlay", True)
|
|
1709
1781
|
only = kwargs.get("only", None)
|
|
1782
|
+
filter_outliers = kwargs.get("only", False)
|
|
1783
|
+
degree = kwargs.get("degree", 3)
|
|
1710
1784
|
refine = kwargs.get("refine", 1)
|
|
1711
1785
|
method = kwargs.get("method", "rbf")
|
|
1712
1786
|
rbf_func = kwargs.get("rbf_func", "thin_plate")
|
|
@@ -1782,6 +1856,19 @@ class PS:
|
|
|
1782
1856
|
x, y = np.array(recs[key]["pts"]).T
|
|
1783
1857
|
pts = recs[key]["pts"]
|
|
1784
1858
|
data = recs[key]["data"]
|
|
1859
|
+
# filter outliers
|
|
1860
|
+
if filter_outliers:
|
|
1861
|
+
A = np.c_[np.ones_like(x), x, y, x * y, x**2, y**2]
|
|
1862
|
+
C, _, _, _ = lstsq(A, data)
|
|
1863
|
+
# evaluate it on a grid
|
|
1864
|
+
vals = np.dot(
|
|
1865
|
+
np.c_[np.ones_like(x), x, y, x * y, x**2, y**2], C
|
|
1866
|
+
)
|
|
1867
|
+
err = abs(vals - data)
|
|
1868
|
+
ok = err < err.std()
|
|
1869
|
+
pts = pts[ok, :]
|
|
1870
|
+
x, y = pts.T
|
|
1871
|
+
data = data[ok]
|
|
1785
1872
|
try:
|
|
1786
1873
|
if method == "quadratic":
|
|
1787
1874
|
tgg = tg.flatten()
|
|
@@ -1800,22 +1887,76 @@ class PS:
|
|
|
1800
1887
|
],
|
|
1801
1888
|
C,
|
|
1802
1889
|
).reshape(tg.shape)
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
x,
|
|
1806
|
-
self.ratio * y,
|
|
1807
|
-
data,
|
|
1808
|
-
function=rbf_func,
|
|
1809
|
-
smooth=smooth,
|
|
1810
|
-
epsilon=epsilon,
|
|
1890
|
+
elif method == "spline":
|
|
1891
|
+
interp = SmoothBivariateSpline(
|
|
1892
|
+
x, self.ratio * y, data, kx=degree, ky=degree
|
|
1811
1893
|
)
|
|
1812
|
-
zg =
|
|
1894
|
+
zg = interp(tg, self.ratio * pg)
|
|
1895
|
+
else:
|
|
1896
|
+
with warnings.catch_warnings():
|
|
1897
|
+
warnings.filterwarnings("error")
|
|
1898
|
+
rbf = Rbf(
|
|
1899
|
+
x,
|
|
1900
|
+
self.ratio * y,
|
|
1901
|
+
data,
|
|
1902
|
+
function=rbf_func,
|
|
1903
|
+
smooth=smooth,
|
|
1904
|
+
epsilon=epsilon,
|
|
1905
|
+
)
|
|
1906
|
+
zg = rbf(tg, self.ratio * pg)
|
|
1813
1907
|
except Exception as e:
|
|
1814
1908
|
if self.show_errors:
|
|
1815
1909
|
print(e)
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1910
|
+
try:
|
|
1911
|
+
zg = griddata(
|
|
1912
|
+
np.array(pts),
|
|
1913
|
+
data,
|
|
1914
|
+
(tg, pg),
|
|
1915
|
+
method="nearest",
|
|
1916
|
+
rescale=True,
|
|
1917
|
+
)
|
|
1918
|
+
if method == "rbf":
|
|
1919
|
+
# locate valid data
|
|
1920
|
+
ri, ci = np.nonzero(np.isfinite(zg))
|
|
1921
|
+
x, y, z = np.array(
|
|
1922
|
+
[
|
|
1923
|
+
[tg[r, c], pg[r, c], zg[r, c]]
|
|
1924
|
+
for r, c in zip(ri, ci)
|
|
1925
|
+
]
|
|
1926
|
+
).T
|
|
1927
|
+
# do Rbf extrapolation
|
|
1928
|
+
with warnings.catch_warnings():
|
|
1929
|
+
warnings.filterwarnings(
|
|
1930
|
+
"ignore", category=LinAlgWarning
|
|
1931
|
+
)
|
|
1932
|
+
rbf = Rbf(
|
|
1933
|
+
x,
|
|
1934
|
+
self.ratio * y,
|
|
1935
|
+
z,
|
|
1936
|
+
function=rbf_func,
|
|
1937
|
+
smooth=smooth,
|
|
1938
|
+
epsilon=epsilon,
|
|
1939
|
+
)
|
|
1940
|
+
zg = rbf(tg, self.ratio * pg)
|
|
1941
|
+
if method == "spline":
|
|
1942
|
+
# locate valid data
|
|
1943
|
+
ri, ci = np.nonzero(np.isfinite(zg))
|
|
1944
|
+
x, y, z = np.array(
|
|
1945
|
+
[
|
|
1946
|
+
[tg[r, c], pg[r, c], zg[r, c]]
|
|
1947
|
+
for r, c in zip(ri, ci)
|
|
1948
|
+
]
|
|
1949
|
+
).T
|
|
1950
|
+
interp = SmoothBivariateSpline(
|
|
1951
|
+
x, self.ratio * y, z, kx=degree, ky=degree
|
|
1952
|
+
)
|
|
1953
|
+
zg = interp(tg, self.ratio * pg)
|
|
1954
|
+
except Exception:
|
|
1955
|
+
print(
|
|
1956
|
+
"Using nearest method in {}".format(
|
|
1957
|
+
" ".join(sorted(list(key)))
|
|
1958
|
+
)
|
|
1959
|
+
)
|
|
1819
1960
|
# ------------
|
|
1820
1961
|
scx = (tmax - tmin + 2 * self.gridxstep) / zg.shape[1]
|
|
1821
1962
|
scy = (pmax - pmin + 2 * self.gridystep) / zg.shape[0]
|
|
@@ -2123,15 +2264,18 @@ class PS:
|
|
|
2123
2264
|
tg, pg = self.xg[slc], self.yg[slc]
|
|
2124
2265
|
x, y = np.array(recs[key]["pts"]).T
|
|
2125
2266
|
# Use scaling
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2267
|
+
try:
|
|
2268
|
+
rbf = Rbf(
|
|
2269
|
+
x,
|
|
2270
|
+
self.ratio * y,
|
|
2271
|
+
recs[key]["data"],
|
|
2272
|
+
function="linear",
|
|
2273
|
+
smooth=smooth,
|
|
2274
|
+
)
|
|
2275
|
+
zg = rbf(tg, self.ratio * pg)
|
|
2276
|
+
gd[self.masks[key]] = zg[self.masks[key][slc]]
|
|
2277
|
+
except Exception:
|
|
2278
|
+
pass # pass silently
|
|
2135
2279
|
return gd
|
|
2136
2280
|
else:
|
|
2137
2281
|
print("Not yet gridded...")
|
|
@@ -2364,7 +2508,7 @@ class PTPS(PS):
|
|
|
2364
2508
|
t, p = splt(step), splp(step)
|
|
2365
2509
|
key = self.identify(t, p)
|
|
2366
2510
|
ix = self.get_section_id(t, p)
|
|
2367
|
-
if ix is not None:
|
|
2511
|
+
if (ix is not None) and (key is not None):
|
|
2368
2512
|
r, c = self.grids[ix].get_indexes(t, p)
|
|
2369
2513
|
calc = None
|
|
2370
2514
|
if self.grids[ix].status[r, c] == 1:
|
|
@@ -2385,6 +2529,8 @@ class PTPS(PS):
|
|
|
2385
2529
|
results.append(res[0])
|
|
2386
2530
|
else:
|
|
2387
2531
|
err += 1
|
|
2532
|
+
else:
|
|
2533
|
+
err += 1
|
|
2388
2534
|
if err > 0:
|
|
2389
2535
|
print("Solution not found on {} points".format(err))
|
|
2390
2536
|
return PTpath(points, results)
|
|
@@ -2888,8 +3034,10 @@ class GridData:
|
|
|
2888
3034
|
y (float): y-coordiante of point
|
|
2889
3035
|
|
|
2890
3036
|
"""
|
|
2891
|
-
c = np.searchsorted(self.xspace, x)
|
|
2892
|
-
|
|
3037
|
+
# c = np.searchsorted(self.xspace, x)
|
|
3038
|
+
c = np.argmin((self.xspace - x) ** 2)
|
|
3039
|
+
# r = np.searchsorted(self.yspace, y)
|
|
3040
|
+
r = np.argmin((self.yspace - y) ** 2)
|
|
2893
3041
|
return r, c
|
|
2894
3042
|
|
|
2895
3043
|
def contains(self, x, y):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pypsbuilder
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.4.0
|
|
4
4
|
Summary: THERMOCALC front-end for constructing and analyzing PT pseudosections
|
|
5
5
|
Home-page: https://github.com/ondrolexa/pypsbuilder
|
|
6
6
|
Author: Ondrej Lexa
|
|
@@ -88,6 +88,12 @@ pypsbuilder is free software: you can redistribute it and/or modify it under the
|
|
|
88
88
|
# Changelog
|
|
89
89
|
All notable pypsbuilder changes.
|
|
90
90
|
|
|
91
|
+
## [2.4.0] - 2023-12-21
|
|
92
|
+
### Fixed
|
|
93
|
+
- important collect_grid_data bug causing isopleths twisting fixed.
|
|
94
|
+
- collect_ptpath missing field check added
|
|
95
|
+
- remove_grid_data method added
|
|
96
|
+
- isopleths bivariate spline method added
|
|
91
97
|
## [2.3.6] - 2023-12-13
|
|
92
98
|
### Added
|
|
93
99
|
- search_composition method added to PTPS to find best estimate for isopleths intersection
|
|
@@ -5,34 +5,27 @@ from setuptools import setup, find_packages
|
|
|
5
5
|
|
|
6
6
|
CURRENT_PATH = path.abspath(path.dirname(__file__))
|
|
7
7
|
|
|
8
|
-
with open(path.join(CURRENT_PATH,
|
|
8
|
+
with open(path.join(CURRENT_PATH, "README.md")) as readme_file:
|
|
9
9
|
readme = readme_file.read()
|
|
10
10
|
|
|
11
|
-
with open(path.join(CURRENT_PATH,
|
|
11
|
+
with open(path.join(CURRENT_PATH, "CHANGELOG.md")) as changelog_file:
|
|
12
12
|
changelog = changelog_file.read()
|
|
13
13
|
|
|
14
|
-
requirements = [
|
|
15
|
-
'numpy',
|
|
16
|
-
'matplotlib>=3',
|
|
17
|
-
'scipy',
|
|
18
|
-
'networkx',
|
|
19
|
-
'shapely>=2',
|
|
20
|
-
'tqdm'
|
|
21
|
-
]
|
|
14
|
+
requirements = ["numpy", "matplotlib>=3", "scipy", "networkx", "shapely>=2", "tqdm"]
|
|
22
15
|
|
|
23
16
|
setup(
|
|
24
|
-
name=
|
|
25
|
-
version=
|
|
17
|
+
name="pypsbuilder",
|
|
18
|
+
version="2.4.0",
|
|
26
19
|
description="THERMOCALC front-end for constructing and analyzing PT pseudosections",
|
|
27
|
-
long_description=readme +
|
|
20
|
+
long_description=readme + "\n\n" + changelog,
|
|
28
21
|
long_description_content_type="text/markdown",
|
|
29
22
|
author="Ondrej Lexa",
|
|
30
|
-
author_email=
|
|
31
|
-
url=
|
|
23
|
+
author_email="lexa.ondrej@gmail.com",
|
|
24
|
+
url="https://github.com/ondrolexa/pypsbuilder",
|
|
32
25
|
license="MIT",
|
|
33
26
|
python_requires=">=3.8",
|
|
34
27
|
packages=find_packages(),
|
|
35
|
-
package_data={
|
|
28
|
+
package_data={"pypsbuilder.images": ["*.png"]},
|
|
36
29
|
entry_points="""
|
|
37
30
|
[console_scripts]
|
|
38
31
|
ptbuilder=pypsbuilder.psbuilders:ptbuilder
|
|
@@ -46,13 +39,13 @@ setup(
|
|
|
46
39
|
""",
|
|
47
40
|
install_requires=requirements,
|
|
48
41
|
zip_safe=False,
|
|
49
|
-
keywords=
|
|
42
|
+
keywords="pypsbuilder",
|
|
50
43
|
classifiers=[
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
]
|
|
44
|
+
"Development Status :: 4 - Beta",
|
|
45
|
+
"Intended Audience :: Science/Research",
|
|
46
|
+
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
|
|
47
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
48
|
+
"Topic :: Scientific/Engineering",
|
|
49
|
+
"Topic :: Utilities",
|
|
50
|
+
],
|
|
58
51
|
)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|