├── VERSION
├── tests
├── __init__.py
└── sciplot
│ ├── baseline
│ ├── test_plot_1.png
│ ├── test_plot_2.png
│ ├── test_style_basic.png
│ ├── test_style_clean.png
│ ├── test_style_dark.png
│ ├── test_style_empty.png
│ ├── test_style_serif.png
│ ├── test_style_default.png
│ ├── test_style_no_latex.png
│ ├── test_style_colors_dark.png
│ ├── test_style_latex_serif.png
│ ├── test_style_typesetting.png
│ ├── test_style_colors_light.png
│ ├── test_style_locale_en_US.png
│ ├── test_style_alpha_beta_gamma.png
│ ├── test_style_clean_sans_serif.png
│ ├── test_style_fonts_cm_serif.png
│ ├── test_style_latex_sans_serif.png
│ ├── test_style_no_latex_serif.png
│ └── test_style_fonts_cm_sans_serif.png
│ └── test_main.py
├── sciplot
├── parameters
│ ├── alpha.yml
│ ├── beta.yml
│ ├── gamma.yml
│ ├── no_latex.yml
│ ├── fonts_cm_serif.yml
│ ├── colors.yml
│ ├── fonts_cm_sans_serif.yml
│ ├── colors_dark.yml
│ ├── colors_light.yml
│ ├── typesetting.yml
│ ├── latex_serif.yml
│ ├── latex_sans_serif.yml
│ ├── basic.yml
│ └── locales.csv
├── __init__.py
└── main.py
├── setup.cfg
├── .markdownlint.yaml
├── example_plots
├── Line_plot_2021-05-23T13.37.png
├── MWE_plot_2021-05-23T13.33.png
├── Histogram_plot_2021-05-23T13.38.png
├── mwe.py
└── example_plots.py
├── pyproject.toml
├── CHANGES.txt
├── LICENSE.txt
├── setup.py
├── .github
└── workflows
│ ├── test.yaml
│ └── release.yaml
├── .gitignore
├── update_version.py
└── README.md
/VERSION:
--------------------------------------------------------------------------------
1 | 0.8.1
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/sciplot/parameters/alpha.yml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/sciplot/parameters/beta.yml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/sciplot/parameters/gamma.yml:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | [metadata]
2 | license_files = LICENSE.txt
--------------------------------------------------------------------------------
/sciplot/__init__.py:
--------------------------------------------------------------------------------
1 | from sciplot.main import * # noqa F401
2 |
--------------------------------------------------------------------------------
/sciplot/parameters/no_latex.yml:
--------------------------------------------------------------------------------
1 | text.usetex: false # Use LaTeX
--------------------------------------------------------------------------------
/tests/sciplot/baseline/test_plot_1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/tests/sciplot/baseline/test_plot_1.png
--------------------------------------------------------------------------------
/tests/sciplot/baseline/test_plot_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/tests/sciplot/baseline/test_plot_2.png
--------------------------------------------------------------------------------
/.markdownlint.yaml:
--------------------------------------------------------------------------------
1 | # Linting file for makrdown-cli
2 | default: true
3 | MD013: false
4 | MD032: false
5 | MD033: false
6 | MD036: false
--------------------------------------------------------------------------------
/example_plots/Line_plot_2021-05-23T13.37.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/example_plots/Line_plot_2021-05-23T13.37.png
--------------------------------------------------------------------------------
/example_plots/MWE_plot_2021-05-23T13.33.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/example_plots/MWE_plot_2021-05-23T13.33.png
--------------------------------------------------------------------------------
/tests/sciplot/baseline/test_style_basic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/tests/sciplot/baseline/test_style_basic.png
--------------------------------------------------------------------------------
/tests/sciplot/baseline/test_style_clean.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/tests/sciplot/baseline/test_style_clean.png
--------------------------------------------------------------------------------
/tests/sciplot/baseline/test_style_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/tests/sciplot/baseline/test_style_dark.png
--------------------------------------------------------------------------------
/tests/sciplot/baseline/test_style_empty.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/tests/sciplot/baseline/test_style_empty.png
--------------------------------------------------------------------------------
/tests/sciplot/baseline/test_style_serif.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/tests/sciplot/baseline/test_style_serif.png
--------------------------------------------------------------------------------
/tests/sciplot/baseline/test_style_default.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/tests/sciplot/baseline/test_style_default.png
--------------------------------------------------------------------------------
/tests/sciplot/baseline/test_style_no_latex.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/tests/sciplot/baseline/test_style_no_latex.png
--------------------------------------------------------------------------------
/example_plots/Histogram_plot_2021-05-23T13.38.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/example_plots/Histogram_plot_2021-05-23T13.38.png
--------------------------------------------------------------------------------
/tests/sciplot/baseline/test_style_colors_dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/tests/sciplot/baseline/test_style_colors_dark.png
--------------------------------------------------------------------------------
/tests/sciplot/baseline/test_style_latex_serif.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/tests/sciplot/baseline/test_style_latex_serif.png
--------------------------------------------------------------------------------
/tests/sciplot/baseline/test_style_typesetting.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/tests/sciplot/baseline/test_style_typesetting.png
--------------------------------------------------------------------------------
/tests/sciplot/baseline/test_style_colors_light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/tests/sciplot/baseline/test_style_colors_light.png
--------------------------------------------------------------------------------
/tests/sciplot/baseline/test_style_locale_en_US.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/tests/sciplot/baseline/test_style_locale_en_US.png
--------------------------------------------------------------------------------
/tests/sciplot/baseline/test_style_alpha_beta_gamma.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/tests/sciplot/baseline/test_style_alpha_beta_gamma.png
--------------------------------------------------------------------------------
/tests/sciplot/baseline/test_style_clean_sans_serif.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/tests/sciplot/baseline/test_style_clean_sans_serif.png
--------------------------------------------------------------------------------
/tests/sciplot/baseline/test_style_fonts_cm_serif.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/tests/sciplot/baseline/test_style_fonts_cm_serif.png
--------------------------------------------------------------------------------
/tests/sciplot/baseline/test_style_latex_sans_serif.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/tests/sciplot/baseline/test_style_latex_sans_serif.png
--------------------------------------------------------------------------------
/tests/sciplot/baseline/test_style_no_latex_serif.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/tests/sciplot/baseline/test_style_no_latex_serif.png
--------------------------------------------------------------------------------
/tests/sciplot/baseline/test_style_fonts_cm_sans_serif.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/andreasfuhr/sciplot/HEAD/tests/sciplot/baseline/test_style_fonts_cm_sans_serif.png
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [build-system]
2 | requires = [
3 | 'setuptools >= 38.6.0',
4 | 'wheel >= 0.31.0',
5 | 'twine >= 1.11.0'
6 | ]
7 | build-backend = 'setuptools.build_meta'
--------------------------------------------------------------------------------
/sciplot/parameters/fonts_cm_serif.yml:
--------------------------------------------------------------------------------
1 | # Fonts
2 | font.family: serif
3 | font.serif: Computer Modern # Serif font
4 | mathtext.fontset: cm # Text in math mode
5 | font.size: 7 # General font size
--------------------------------------------------------------------------------
/sciplot/parameters/colors.yml:
--------------------------------------------------------------------------------
1 | # Colours
2 | image.cmap: cubehelix # Colourmap
3 | axes.prop_cycle : (cycler('color', ['k', 'r', 'b', 'g']) + cycler('ls', ['-', '--', ':', '-.'])) # Set color and style cycle
--------------------------------------------------------------------------------
/sciplot/parameters/fonts_cm_sans_serif.yml:
--------------------------------------------------------------------------------
1 | # Fonts
2 | font.family: sans-serif # Font type
3 | font.serif: Computer Modern Sans Serif # Sans-serif font
4 | mathtext.fontset: cm # Text in math mode
5 | font.size: 7 # General font size
--------------------------------------------------------------------------------
/sciplot/parameters/colors_dark.yml:
--------------------------------------------------------------------------------
1 | # Colours
2 | image.cmap: cubehelix # Colourmap
3 | axes.prop_cycle : (cycler('color', ['r', 'b', 'g', 'c', 'm', 'y', 'w']) + cycler('ls', ['-', '--', ':', '-.', '-', '--', ':'])) # Set color and style cycle
--------------------------------------------------------------------------------
/sciplot/parameters/colors_light.yml:
--------------------------------------------------------------------------------
1 | # Colours
2 | image.cmap: cubehelix # Colourmap
3 | axes.prop_cycle : (cycler('color', ['k', 'r', 'b', 'g', 'c', 'm', 'y']) + cycler('ls', ['-', '--', ':', '-.', '-', '--', ':'])) # Set color and style cycle
--------------------------------------------------------------------------------
/sciplot/parameters/typesetting.yml:
--------------------------------------------------------------------------------
1 | # Title
2 | figure.titlesize: 10
3 | figure.titleweight: bold
4 | axes.titlesize: 9 # Title font size
5 | axes.titleweight: normal # Title font weight
6 |
7 | # Axes
8 | axes.labelsize: 9 # x and y labels font size
9 | axes.labelweight: normal # x and y labels font weight
10 |
11 | # Ticks
12 | xtick.labelsize: 7 # x ticks font size
13 | ytick.labelsize: 7 # y ticks font size
14 | xtick.major.size : 3
15 | ytick.major.size : 3
16 | xtick.minor.size : 1.5
17 | ytick.minor.size : 1.5
18 |
19 | # Legend
20 | legend.fontsize: 6 # Legend font size
21 | legend.edgecolor: grey
--------------------------------------------------------------------------------
/CHANGES.txt:
--------------------------------------------------------------------------------
1 | # 0.8.1
2 |
3 | - Fixed typo in setup.py name parameter that caused an incorrect `pip install` command
4 |
5 | # 0.8.0
6 |
7 | - Beta version.
8 | - Updated Sciplot's main module and sciplot.style() and know works with themes (and locale)
9 | - A new testing suite to test the most common features and scenarios, outside of package. There are however still
10 | important tests missing.
11 | - Three empty, ready-to-go user parameter files created: alpha, beta and gamma.
12 | - A new method that prints out all available locale settings (from Oracle) in console
13 |
14 | # 0.7.9
15 |
16 | - Alpha version.
17 |
18 |
--------------------------------------------------------------------------------
/sciplot/parameters/latex_serif.yml:
--------------------------------------------------------------------------------
1 | # TODO: Write description
2 | text.usetex: true # Use LaTeX
3 |
4 | # LaTeX standard math and physics preamble with serif font in math mode
5 | text.latex.preamble: >
6 | \usepackage{amsmath}
7 | \usepackage{amssymb}
8 | \usepackage{mathtools}
9 | \usepackage{bbm}
10 | \usepackage{gensymb}
11 | \usepackage[italicdiff]{physics}
12 | \usepackage{icomma}
13 | \usepackage{siunitx}
14 | \sisetup{
15 | locale=DE,
16 | detect-all,
17 | range-phrase=\text{--},
18 | seperr,
19 | range-units=single,
20 | bracket-unit-denominator=false,
21 | sticky-per,
22 | per-mode=symbol
23 | }
--------------------------------------------------------------------------------
/example_plots/mwe.py:
--------------------------------------------------------------------------------
1 | import matplotlib.pyplot as plt
2 | import numpy as np
3 | import sciplot
4 | from pathlib import Path
5 |
6 | x = np.arange(0, 2 * np.pi, 1e-2)
7 | y1 = np.sin(2 * x + np.pi)
8 | y2 = np.cos(2 * x + np.pi)
9 |
10 | sciplot.set_size_cm(5)
11 |
12 | with sciplot.style():
13 | plt.plot(x, y1, x, y2)
14 | plt.xticks(
15 | np.linspace(0, 2 * np.pi, 5),
16 | ['$0$', r'$\frac{\pi}{2}$', r'$\pi$', r'$\frac{3\pi}{2}$', r'$2\pi$']
17 | )
18 |
19 | sciplot.save_time_stamped_figure(
20 | plot_file_name='MWE_plot',
21 | save_directory=(Path(__file__).parent)
22 | )
23 | plt.show()
24 |
--------------------------------------------------------------------------------
/sciplot/parameters/latex_sans_serif.yml:
--------------------------------------------------------------------------------
1 | # TODO: Write description
2 | text.usetex: true # Use LaTeX
3 |
4 | # LaTeX standard math and physics preamble with sans-serif font in math mode
5 | text.latex.preamble: >
6 | \usepackage{amsmath}
7 | \usepackage{amssymb}
8 | \usepackage{mathtools}
9 | \usepackage{bbm}
10 | \usepackage{gensymb}
11 | \usepackage[italicdiff]{physics}
12 | \usepackage{icomma}
13 | \usepackage{sansmath}
14 | \sansmath
15 | \usepackage{siunitx}
16 | \sisetup{
17 | locale=DE,
18 | detect-all,
19 | range-phrase=\text{--},
20 | seperr,
21 | range-units=single,
22 | bracket-unit-denominator=false,
23 | sticky-per,
24 | per-mode=symbol
25 | }
--------------------------------------------------------------------------------
/sciplot/parameters/basic.yml:
--------------------------------------------------------------------------------
1 | figure.autolayout: True # Automatic figure layout
2 | figure.subplot.left : 0.5
3 | figure.dpi : 600
4 | savefig.bbox : tight # Always save as 'tight'
5 | savefig.pad_inches : 0.04
6 |
7 |
8 |
9 | # Linewidths
10 | axes.linewidth: 0.25 # Border linewidth
11 | grid.linewidth: 0.25 # Grid linewidth
12 | xtick.major.width: 0.25 # x ticks major linewidth
13 | xtick.minor.width: 0.25 # x ticks minor linewidth
14 | ytick.major.width: 0.25 # y ticks major linewidth
15 | ytick.minor.width: 0.25 # y ticks minor linewidth
16 |
17 | # Plots
18 | lines.linewidth : 0.5 # Width of plotted lines
19 | lines.markersize : 2 # Size of plotted markers
20 |
21 | # Axes
22 | axes.formatter.use_locale: True # Use local decimal separator etc.
23 | axes.grid: False # Grid turned off
24 |
25 | # Ticks
26 | xtick.direction : in
27 | ytick.direction : in
28 | xtick.minor.visible : True
29 | ytick.minor.visible : True
30 | xtick.top : True
31 | ytick.right : True
32 |
33 | # Legend
34 | patch.linewidth: 0.25
35 | legend.frameon: True
36 | legend.fancybox: False
37 | legend.loc: upper left
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 Andreas Führ
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | import setuptools
2 |
3 | with open('README.md', 'r', encoding='utf-8') as fh:
4 | long_description = fh.read()
5 |
6 | setuptools.setup(
7 | name='sciplot',
8 | version='0.8.1',
9 | author='Andreas Führ',
10 | author_email='andreas.fuhr@outlook.com',
11 | license='MIT',
12 | description='Format Matplotlib scientific plots',
13 | long_description=long_description,
14 | long_description_content_type='text/markdown',
15 | url='https://github.com/andreasfuhr/sciplot',
16 | classifiers=[
17 | 'Programming Language :: Python :: 3.7',
18 | 'Programming Language :: Python :: 3.8',
19 | 'Programming Language :: Python :: 3.9',
20 | 'License :: OSI Approved :: MIT License',
21 | 'Operating System :: OS Independent',
22 | 'Development Status :: 4 - Beta',
23 | 'Natural Language :: English',
24 | 'Framework :: Matplotlib',
25 | 'Topic :: Scientific/Engineering'
26 | ],
27 | packages=['sciplot'],
28 | package_data={'sciplot': ['parameters/*.yml', '../README.md']},
29 | include_package_data=True,
30 | python_requires='>=3.7',
31 | install_requires=['matplotlib>=3.3.4', 'pyyaml', 'seaborn'],
32 | )
33 |
--------------------------------------------------------------------------------
/.github/workflows/test.yaml:
--------------------------------------------------------------------------------
1 | # This workflow will install Python dependencies, run tests and lint with a variety of Python versions
2 |
3 | name: Test Python package
4 |
5 | on: [push]
6 |
7 | jobs:
8 | lint:
9 | name: Lint package files
10 | runs-on: ubuntu-latest
11 | steps:
12 | - uses: actions/checkout@v2
13 | - name: Set up Python 3.9
14 | uses: actions/setup-python@v2
15 | with:
16 | python-version: 3.9
17 | - name: Install dependencies
18 | run: |
19 | python -m pip install --upgrade pip
20 | pip install pylint
21 | python -m pip install flake8
22 | pip install -e .
23 | - name: Python linting with flake8
24 | run: |
25 | flake8 . --count --max-complexity=10 --max-line-length=127 --show-source --statistics --format=pylint --exit-zero
26 | - name: Markdown and YAML lintning with markdownlint-cli
27 | uses: nosborn/github-action-markdown-cli@v2.0.0
28 | with:
29 | files: .
30 | config_file: .markdownlint.yaml
31 | test:
32 | name: Test package
33 | runs-on: ubuntu-latest
34 | strategy:
35 | fail-fast: false
36 | steps:
37 | - uses: actions/checkout@v2
38 | - name: Set up Python 3.9
39 | uses: actions/setup-python@v2
40 | with:
41 | python-version: 3.9
42 | - name: Prepare Github Actions
43 | uses: actions/checkout@v2
44 | - name: Install TeXLive
45 | uses: xu-cheng/texlive-action/full@v1
46 | - name: Set up Python ${{ matrix.python-version }}
47 | uses: actions/setup-python@v2
48 | with:
49 | python-version: ${{ matrix.python-version }}
50 | - name: Install dependencies
51 | run: |
52 | python -m pip install --upgrade pip
53 | python -m pip install pytest
54 | python -m pip install pytest-mpl
55 | pip install -e .
56 | - name: Test with pytest
57 | run: |
58 | sudo locale-gen en_US.UTF-8
59 | sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
60 | pytest --mpl-baseline-relative
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | pip-wheel-metadata/
24 | share/python-wheels/
25 | *.egg-info/
26 | .installed.cfg
27 | *.egg
28 | MANIFEST
29 |
30 | # PyInstaller
31 | # Usually these files are written by a python script from a template
32 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
33 | *.manifest
34 | *.spec
35 |
36 | # Installer logs
37 | pip-log.txt
38 | pip-delete-this-directory.txt
39 |
40 | # Unit test / coverage reports
41 | htmlcov/
42 | .tox/
43 | .nox/
44 | .coverage
45 | .coverage.*
46 | .cache
47 | nosetests.xml
48 | coverage.xml
49 | *.cover
50 | *.py,cover
51 | .hypothesis/
52 | .pytest_cache/
53 |
54 | # Translations
55 | *.mo
56 | *.pot
57 |
58 | # Django stuff:
59 | *.log
60 | local_settings.py
61 | db.sqlite3
62 | db.sqlite3-journal
63 |
64 | # Flask stuff:
65 | instance/
66 | .webassets-cache
67 |
68 | # Scrapy stuff:
69 | .scrapy
70 |
71 | # Sphinx documentation
72 | docs/_build/
73 |
74 | # PyBuilder
75 | target/
76 |
77 | # Jupyter Notebook
78 | .ipynb_checkpoints
79 |
80 | # IPython
81 | profile_default/
82 | ipython_config.py
83 |
84 | # pyenv
85 | .python-version
86 |
87 | # pipenv
88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies
90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not
91 | # install all needed dependencies.
92 | #Pipfile.lock
93 |
94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow
95 | __pypackages__/
96 |
97 | # Celery stuff
98 | celerybeat-schedule
99 | celerybeat.pid
100 |
101 | # SageMath parsed files
102 | *.sage.py
103 |
104 | # Environments
105 | .env
106 | .venv
107 | env/
108 | venv/
109 | ENV/
110 | env.bak/
111 | venv.bak/
112 |
113 | # Spyder project settings
114 | .spyderproject
115 | .spyproject
116 |
117 | # Rope project settings
118 | .ropeproject
119 |
120 | # mkdocs documentation
121 | /site
122 |
123 | # mypy
124 | .mypy_cache/
125 | .dmypy.json
126 | dmypy.json
127 |
128 | # Pyre type checker
129 | .pyre/
130 |
131 | # PyCharm settings
132 | .idea/
133 | .DS_Store
134 |
--------------------------------------------------------------------------------
/example_plots/example_plots.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | from scipy.stats import pareto
3 | import matplotlib.pyplot as plt
4 | from matplotlib.patches import Rectangle
5 | from pathlib import Path
6 |
7 | import sciplot
8 |
9 | # Plot 1
10 | with sciplot.style(theme='no-latex', locale_setting='en_US.UTF-8'):
11 | x_m = 2 # scale
12 | alpha_lst = [1, 2, 3, 4] # shape parameters
13 | x = np.linspace(0, 6, 1000)
14 |
15 | pdf = np.array([pareto.pdf(x, scale=x_m, b=a) for a in alpha_lst])
16 |
17 | sciplot.set_size_cm(7)
18 | fig, ax = plt.subplots(1, 1)
19 |
20 | fig.suptitle(r'Pareto PDF' +
21 | r' $p(x \,|\, x_\mathrm{m}, \alpha) = \frac{\alpha x_\mathrm{m}^\alpha}{x^{\alpha+1}}$' +
22 | r' with $x_\mathrm{m}=2$')
23 |
24 | line_plot = ax.plot(x, pdf.T)
25 |
26 | label_lst = []
27 | for alpha in alpha_lst:
28 | label_lst.append(r'$\alpha=' + str(alpha) + '$')
29 |
30 | sciplot.set_legend(
31 | ax=ax,
32 | plot_tpl=line_plot,
33 | label_tpl=tuple(label_lst),
34 | loc='upper right'
35 | )
36 |
37 | ax.set_xlabel('$x$')
38 | ax.set_ylabel(r'$p(x \,|\, x_\mathrm{m}, \alpha)$')
39 |
40 | sciplot.save_time_stamped_figure(
41 | plot_file_name='Line_plot',
42 | save_directory=(Path(__file__).parent)
43 | )
44 |
45 | plt.show()
46 |
47 |
48 | # Plot 2
49 | with sciplot.style(theme=['no-latex', 'dark'], locale_setting='en_US.UTF-8'):
50 | np.random.seed(42)
51 | n = 10000
52 | mean_ar = np.array([4.5, 6.1, 8.3])
53 | std_ar = np.array([0.2, 0.9, 0.5])
54 | data_ar = np.array([
55 | np.random.normal(mean_ar[0], std_ar[0], n),
56 | np.random.normal(mean_ar[1], std_ar[1], n),
57 | np.random.normal(mean_ar[2], std_ar[2], n)
58 | ])
59 |
60 | sciplot.set_size_cm(16, 8)
61 | fig, ax = plt.subplots(1, 1)
62 |
63 | fig.suptitle(r'Histogram of normally distributed velocities with \SI{' + str(n) + r'}{} samples')
64 |
65 | plot_lst = []
66 | color_lst = sciplot.get_color_lst(len(data_ar), seaborn_color_map='rocket', colorful=False)
67 |
68 | for i, data in enumerate(data_ar):
69 | ax.hist(data, density=True, bins=100, alpha=0.7, color=color_lst[i])
70 | plot_lst.append(Rectangle((0, 0), 1, 1, color=color_lst[i], alpha=0.7))
71 |
72 | label_lst = []
73 | for i in range(len(data_ar)):
74 | label_lst.append(r'$\mu=\SI{' + str(mean_ar[i]) + r'}{}$, $\sigma=\SI{' + str(std_ar[i]) + r'}{}$')
75 |
76 | sciplot.set_legend(
77 | ax=ax,
78 | plot_tpl=tuple(plot_lst),
79 | label_tpl=tuple(label_lst),
80 | loc='lower right',
81 | outside_plot=True
82 | )
83 |
84 | ax.set_xlabel(r'Velocity (\si{\metre\per\second})')
85 | ax.set_ylabel(r'Relative frequency')
86 |
87 | sciplot.save_time_stamped_figure(
88 | plot_file_name='Histogram_plot',
89 | save_directory=(Path(__file__).parent)
90 | )
91 |
92 | plt.show()
93 |
--------------------------------------------------------------------------------
/update_version.py:
--------------------------------------------------------------------------------
1 | import argparse
2 | import pathlib
3 | import re
4 |
5 |
6 | VERSION_REGEX_STR = r'[0-9]+\.[0-9]+\.[0-9]+'
7 | VERSION_V_REGEX_STR = r'v[0-9]+\.[0-9]+\.[0-9]+'
8 |
9 | IN_FILE_VERSION_REGEX_DICT = {
10 | 'changes': {
11 | 'file_name': 'CHANGES.txt'
12 | },
13 | 'version': {
14 | 'file_name': 'VERSION',
15 | 'version_prefix': '',
16 | 'version_suffix': ''
17 | },
18 | 'readme': {
19 | 'file_name': 'README.md',
20 | 'version_prefix': r'{',
21 | 'version_suffix': r'}'
22 | },
23 | 'setup': {
24 | 'file_name': 'setup.py',
25 | 'version_prefix': r"version='",
26 | 'version_suffix': "'"
27 | },
28 | }
29 |
30 |
31 | def version_regex_type(arg_value, pat=re.compile(VERSION_REGEX_STR)):
32 | if not pat.match(arg_value):
33 | alt_version_val = re.compile(VERSION_V_REGEX_STR)
34 | if alt_version_val.match(arg_value):
35 | arg_value = arg_value[1:]
36 | else:
37 | raise argparse.ArgumentTypeError
38 | return arg_value
39 |
40 |
41 | def check_changes(file_path, file_type_dict, version_new):
42 | with open(file_path, 'r') as file:
43 | content = file.read()
44 |
45 | result_lst = re.findall(version_new, content)
46 | if version_new not in result_lst:
47 | raise ValueError(
48 | "Changes list " + file_type_dict['file_name'] + " not updated for version '" +
49 | version_new + "'.")
50 |
51 | print('Checked version in ' + file_type_dict['file_name'])
52 |
53 |
54 | def update_file(file_path, file_type_dict, version_new):
55 | with open(file_path, 'r') as file:
56 | content = file.read()
57 |
58 | content_new = re.sub(
59 | file_type_dict['version_prefix'] + VERSION_REGEX_STR + file_type_dict['version_suffix'],
60 | file_type_dict['version_prefix'] + version_new + file_type_dict['version_suffix'],
61 | content,
62 | flags=re.M
63 | )
64 |
65 | with open(file_path, 'w') as file:
66 | file.write(content_new)
67 |
68 | print("Updated version in " + file_type_dict['file_name'] + " to '" + version_new + "'")
69 |
70 |
71 | def main(version_new):
72 | # Get all files in directory .
73 | file_path_lst = [str(p.absolute()) for p in pathlib.Path('.').iterdir() if p.is_file()]
74 |
75 | for file_type in ['changes', 'version', 'readme', 'setup']:
76 | file_type_dict = IN_FILE_VERSION_REGEX_DICT[file_type]
77 | for file_path in file_path_lst:
78 | if file_type == 'changes' and file_path.endswith(file_type_dict['file_name']):
79 | check_changes(file_path, file_type_dict, version_new)
80 | continue
81 |
82 | if file_path.endswith(file_type_dict['file_name']):
83 | update_file(file_path, file_type_dict, version_new)
84 | continue
85 |
86 |
87 | if __name__ == '__main__':
88 | PARSER = argparse.ArgumentParser()
89 | PARSER.add_argument(
90 | '-v',
91 | '--version',
92 | type=version_regex_type,
93 | help='Semantic version, e.g. 1.2.3 or v1.2.3',
94 | required=True
95 | )
96 | ARGS = PARSER.parse_args()
97 |
98 | main(ARGS.version)
99 |
--------------------------------------------------------------------------------
/.github/workflows/release.yaml:
--------------------------------------------------------------------------------
1 | # This workflow will install Python dependencies, run tests and lint with a variety of Python versions and releases the
2 | # package on GitHub and to PyPI. It also increments the semantic version.
3 |
4 | name: Release Python package
5 |
6 | on:
7 | push:
8 | # Sequence of patterns matched against refs/tags
9 | tags:
10 | - 'v*' # Push events to matching v*, i.e. v1.0, v20.15.10
11 |
12 | jobs:
13 | lint:
14 | name: Lint package files
15 | runs-on: ubuntu-latest
16 | steps:
17 | - uses: actions/checkout@v2
18 | - name: Set up Python 3.9
19 | uses: actions/setup-python@v2
20 | with:
21 | python-version: 3.9
22 | - name: Install dependencies
23 | run: |
24 | python -m pip install --upgrade pip
25 | pip install pylint
26 | python -m pip install flake8
27 | pip install -e .
28 | - name: Python linting with flake8
29 | run: |
30 | flake8 . --count --max-complexity=10 --max-line-length=127 --show-source --statistics --format=pylint --exit-zero
31 | - name: Markdown and YAML lintning with markdownlint-cli
32 | uses: nosborn/github-action-markdown-cli@v2.0.0
33 | with:
34 | files: .
35 | config_file: .yaml
36 | test:
37 | name: Run package tests
38 | needs: linting
39 | runs-on: ${{matrix.os}}
40 | strategy:
41 | fail-fast: true
42 | matrix:
43 | python-version: [3.7, 3.8, 3.9]
44 | os: [ubuntu-latest, windows-latest, macos-latest]
45 | steps:
46 | - name: Prepare Github Actions
47 | uses: actions/checkout@v2
48 | - name: Install TeXLive
49 | uses: xu-cheng/texlive-action/full@v1
50 | - name: Set up Python ${{ matrix.python-version }}
51 | uses: actions/setup-python@v2
52 | with:
53 | python-version: ${{ matrix.python-version }}
54 | - name: Install dependencies
55 | run: |
56 | python -m pip install --upgrade pip
57 | python -m pip install pytest
58 | python -m pip install pytest-mpl
59 | pip install -e .
60 | - name: Test with pytest
61 | run: |
62 | sudo locale-gen en_US.UTF-8
63 | sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8
64 | pytest --mpl-baseline-relative
65 | release-prep:
66 | name: Prepare release
67 | needs: testing
68 | runs-on: ubuntu-latest
69 | steps:
70 | - uses: actions/checkout@v2
71 | - name: Update version in repo
72 | run: python3 update_version.py --version ${{ github.event.release.tag_name }}
73 | - name: Commit files
74 | run: |
75 | git config --local user.name "Sciplot release workflow"
76 | git add .
77 | git commit -m "[RELEASE] Incremented semantic version"
78 | - name: Push changes to Github
79 | uses: ad-m/github-push-action@master
80 | with:
81 | github_token: ${{ secrets.GITHUB_TOKEN }}
82 | force: true
83 | - name: Update GitHub repo version badge
84 | uses: schneegans/dynamic-badges-action@v1.1.0
85 | with:
86 | auth: ${{ secrets.GIST_SECRET }}
87 | gistID: ae1a5002566bdc7d8d143aab72331657
88 | filename: Sciplot-github-version.json
89 | label: repo
90 | message: ${{ github.event.release.tag_name }}
91 | color: blue
92 | style: flat
93 | logo: github
94 | - name: Update PyPI version badge
95 | uses: schneegans/dynamic-badges-action@v1.1.0
96 | with:
97 | auth: ${{ secrets.GIST_SECRET }}
98 | gistID: 38e0946c4456d70028d4482fe18dcc45
99 | filename: Sciplot-pypi-version.json
100 | label: repo
101 | message: ${{ github.event.release.tag_name }}
102 | color: blue
103 | style: flat
104 | logo: github
105 | release:
106 | name: Create release
107 | needs: release-prep
108 | runs-on: ubuntu-latest
109 | steps:
110 | - name: Checkout code
111 | uses: actions/checkout@master
112 | - name: Create Release
113 | id: create_release
114 | uses: actions/create-release@v1
115 | env:
116 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # This token is provided by Actions, you do not need to create your own token
117 | with:
118 | tag_name: ${{ github.ref }}
119 | release_name: Release ${{ github.ref }}
120 | body: |
121 | Changes in this Release
122 | draft: false
123 | prerelease: false
124 | deploy:
125 | name: Publish package to PyPI
126 | needs: release
127 | runs-on: ubuntu-latest
128 | steps:
129 | - uses: actions/checkout@v1
130 | - name: Set up Python
131 | uses: actions/setup-python@v1
132 | with:
133 | python-version: '3.x'
134 | - name: Install dependencies
135 | run: |
136 | python -m pip install --upgrade pip
137 | pip install setuptools wheel twine
138 | - name: Build and publish
139 | env:
140 | TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }}
141 | TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }}
142 | run: |
143 | python setup.py sdist bdist_wheel
144 | twine upload dist/*
--------------------------------------------------------------------------------
/tests/sciplot/test_main.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import pytest
3 | import numpy as np
4 | from scipy.stats import pareto
5 | import matplotlib.pyplot as plt
6 | from matplotlib.patches import Rectangle
7 | from pathlib import Path
8 | import locale
9 |
10 | sys.path.append(str(Path(__file__).parent / '..' / '..'))
11 | import sciplot.main as sciplot # noqa: E402
12 |
13 | locale.setlocale(locale.LC_NUMERIC, 'en_US.UTF-8')
14 |
15 |
16 | def test_get_parameters_dir():
17 | parameters_dir = str(Path(__file__).parent / '..' / '..' / 'sciplot' / 'parameters')
18 | print(parameters_dir)
19 | assert '/'.split(sciplot.get_parameters_dir())[-4:] == '/'.split(str(parameters_dir))[-4:]
20 |
21 |
22 | def test_get_theme_priority_lst():
23 | theme_priority_lst = [
24 | 'alpha',
25 | 'beta',
26 | 'gamma',
27 | 'no-latex',
28 | 'serif',
29 | 'sans-serif',
30 | 'dark',
31 | 'default'
32 | ]
33 | assert sciplot.get_theme_priority_lst() == theme_priority_lst
34 |
35 |
36 | def test_get_theme_lst_with_string():
37 | theme = 'theme'
38 | assert sciplot._get_theme_lst(theme) == [theme]
39 |
40 |
41 | def test_get_theme_lst_with_capital_string():
42 | theme = 'THEME'
43 | assert sciplot._get_theme_lst(theme) == [theme.lower()]
44 |
45 |
46 | def test_get_theme_lst_with_list():
47 | theme = ['theme1', 'theme2']
48 | assert sciplot._get_theme_lst(theme) == theme
49 |
50 |
51 | def test_get_theme_lst_with_float():
52 | theme = 100.
53 | with pytest.raises(sciplot.SciplotException):
54 | sciplot._get_theme_lst(theme)
55 |
56 |
57 | def test_get_theme_lst_with_float_in_list():
58 | theme = ['theme1', 100.]
59 | with pytest.raises(sciplot.SciplotException):
60 | sciplot._get_theme_lst(theme)
61 |
62 |
63 | def test_color_lst_one_color():
64 | color_no = 1
65 | color_lst = ['#000000']
66 | assert sciplot.get_color_lst(color_no) == color_lst
67 |
68 |
69 | def test_color_lst_zero_colors():
70 | color_no = 0
71 | with pytest.raises(sciplot.SciplotException):
72 | sciplot.get_color_lst(color_no)
73 |
74 |
75 | def test_color_lst_float_color_no():
76 | color_no = 2.5
77 | with pytest.raises(sciplot.SciplotException):
78 | sciplot.get_color_lst(color_no)
79 |
80 |
81 | # Does not work ATM
82 | def test_style_locale_incorrect():
83 | local = 'Undefined_local'
84 | x = np.linspace(0, 1, 2)
85 | y = 2 * x
86 | with pytest.raises(locale.Error):
87 | with sciplot.style(locale_setting=local):
88 | plt.plot(x, y)
89 | return plt.gcf()
90 |
91 |
92 | def test_get_available_locals():
93 | sciplot.get_available_locals()
94 |
95 |
96 | @pytest.mark.mpl_image_compare
97 | def test_style_empty():
98 | x = np.linspace(0, 1, 2)
99 | y = 2 * x
100 | with sciplot.style(locale_setting='en_US.UTF-8'):
101 | plt.plot(x, y)
102 | return plt.gcf()
103 |
104 |
105 | @pytest.mark.mpl_image_compare
106 | def test_style_default():
107 | x = np.linspace(0, 1, 2)
108 | y = 2 * x
109 | with sciplot.style(locale_setting='en_US.UTF-8'):
110 | plt.plot(x, y)
111 | return plt.gcf()
112 |
113 |
114 | @pytest.mark.mpl_image_compare
115 | def test_style_clean():
116 | x = np.linspace(0, 1, 2)
117 | y = 2 * x
118 | with sciplot.style(theme='clean', locale_setting='en_US.UTF-8'):
119 | plt.plot(x, y)
120 | return plt.gcf()
121 |
122 |
123 | @pytest.mark.mpl_image_compare
124 | def test_style_dark():
125 | x = np.linspace(0, 1, 2)
126 | y = 2 * x
127 | with sciplot.style(theme='dark', locale_setting='en_US.UTF-8'):
128 | plt.plot(x, y)
129 | return plt.gcf()
130 |
131 |
132 | @pytest.mark.mpl_image_compare
133 | def test_style_serif():
134 | x = np.linspace(0, 1, 2)
135 | y = 2 * x
136 | with sciplot.style(theme='serif', locale_setting='en_US.UTF-8'):
137 | plt.plot(x, y)
138 | return plt.gcf()
139 |
140 |
141 | @pytest.mark.mpl_image_compare
142 | def test_style_clean_sans_serif():
143 | x = np.linspace(0, 1, 2)
144 | y = 2 * x
145 | with sciplot.style(theme=['clean', 'sans-serif'], locale_setting='en_US.UTF-8'):
146 | plt.plot(x, y)
147 | return plt.gcf()
148 |
149 |
150 | @pytest.mark.mpl_image_compare
151 | def test_style_no_latex():
152 | x = np.linspace(0, 1, 2)
153 | y = 2 * x
154 | with sciplot.style(theme='no-latex', locale_setting='en_US.UTF-8'):
155 | plt.plot(x, y)
156 | return plt.gcf()
157 |
158 |
159 | @pytest.mark.mpl_image_compare
160 | def test_style_no_latex_serif():
161 | x = np.linspace(0, 1, 2)
162 | y = 2 * x
163 | with sciplot.style(theme=['no-latex', 'serif'], locale_setting='en_US.UTF-8'):
164 | plt.plot(x, y)
165 | return plt.gcf()
166 |
167 |
168 | @pytest.mark.mpl_image_compare
169 | def test_style_basic():
170 | x = np.linspace(0, 1, 2)
171 | y = 2 * x
172 | with sciplot.style(theme='basic', locale_setting='en_US.UTF-8'):
173 | plt.plot(x, y)
174 | return plt.gcf()
175 |
176 |
177 | @pytest.mark.mpl_image_compare
178 | def test_style_typesetting():
179 | x = np.linspace(0, 1, 2)
180 | y = 2 * x
181 | with sciplot.style(theme='typesetting', locale_setting='en_US.UTF-8'):
182 | plt.plot(x, y)
183 | return plt.gcf()
184 |
185 |
186 | @pytest.mark.mpl_image_compare
187 | def test_style_colors_light():
188 | x = np.linspace(0, 1, 2)
189 | y = 2 * x
190 | with sciplot.style(theme='colors_light', locale_setting='en_US.UTF-8'):
191 | plt.plot(x, y)
192 | return plt.gcf()
193 |
194 |
195 | @pytest.mark.mpl_image_compare
196 | def test_style_colors_dark():
197 | x = np.linspace(0, 1, 2)
198 | y = 2 * x
199 | with sciplot.style(theme='colors_dark', locale_setting='en_US.UTF-8'):
200 | plt.plot(x, y)
201 | return plt.gcf()
202 |
203 |
204 | @pytest.mark.mpl_image_compare
205 | def test_style_fonts_cm_sans_serif():
206 | x = np.linspace(0, 1, 2)
207 | y = 2 * x
208 | with sciplot.style(theme='fonts_cm_sans_serif', locale_setting='en_US.UTF-8'):
209 | plt.plot(x, y)
210 | return plt.gcf()
211 |
212 |
213 | @pytest.mark.mpl_image_compare
214 | def test_style_fonts_cm_serif():
215 | x = np.linspace(0, 1, 2)
216 | y = 2 * x
217 | with sciplot.style(theme='fonts_cm_serif', locale_setting='en_US.UTF-8'):
218 | plt.plot(x, y)
219 | return plt.gcf()
220 |
221 |
222 | @pytest.mark.mpl_image_compare
223 | def test_style_latex_sans_serif():
224 | x = np.linspace(0, 1, 2)
225 | y = 2 * x
226 | with sciplot.style(theme='latex_sans_serif', locale_setting='en_US.UTF-8'):
227 | plt.plot(x, y)
228 | return plt.gcf()
229 |
230 |
231 | @pytest.mark.mpl_image_compare
232 | def test_style_latex_serif():
233 | x = np.linspace(0, 1, 2)
234 | y = 2 * x
235 | with sciplot.style(theme='latex_serif', locale_setting='en_US.UTF-8'):
236 | plt.plot(x, y)
237 | return plt.gcf()
238 |
239 |
240 | @pytest.mark.mpl_image_compare
241 | def test_style_alpha_beta_gamma():
242 | x = np.linspace(0, 1, 2)
243 | y = 2 * x
244 | with sciplot.style(['alpha', 'beta', 'gamma'], locale_setting='en_US.UTF-8'):
245 | plt.plot(x, y)
246 | return plt.gcf()
247 |
248 |
249 | # Plot 1
250 | @pytest.mark.mpl_image_compare
251 | def test_plot_1():
252 | with sciplot.style(locale_setting='en_US.UTF-8'):
253 | x_m = 2 # scale
254 | alpha_lst = [1, 2, 3, 4] # shape parameters
255 | x = np.linspace(0, 6, 1000)
256 |
257 | pdf = np.array([pareto.pdf(x, scale=x_m, b=a) for a in alpha_lst])
258 |
259 | sciplot.set_size_cm(7)
260 | fig, ax = plt.subplots(1, 1)
261 |
262 | fig.suptitle(r'Pareto PDF' +
263 | r' $p(x \,|\, x_\mathrm{m}, \alpha) = \frac{\alpha x_\mathrm{m}^\alpha}{x^{\alpha+1}}$' +
264 | r' with $x_\mathrm{m}=2$')
265 |
266 | line_plot = ax.plot(x, pdf.T)
267 |
268 | label_lst = []
269 | for alpha in alpha_lst:
270 | label_lst.append(r'$\alpha=' + str(alpha) + '$')
271 |
272 | sciplot.set_legend(
273 | ax=ax,
274 | plot_tpl=line_plot,
275 | label_tpl=tuple(label_lst),
276 | loc='upper right'
277 | )
278 |
279 | ax.set_xlabel('$x$')
280 | ax.set_ylabel(r'$p(x \,|\, x_\mathrm{m}, \alpha)$')
281 |
282 | return fig
283 |
284 |
285 | # Plot 2
286 | @pytest.mark.mpl_image_compare
287 | def test_plot_2():
288 | with sciplot.style(locale_setting='en_US.UTF-8'):
289 | np.random.seed(42)
290 | n = 10000
291 | mean_ar = np.array([4.5, 6.1, 8.3])
292 | std_ar = np.array([0.2, 0.9, 0.5])
293 | data_ar = np.array([
294 | np.random.normal(mean_ar[0], std_ar[0], n),
295 | np.random.normal(mean_ar[1], std_ar[1], n),
296 | np.random.normal(mean_ar[2], std_ar[2], n)
297 | ])
298 |
299 | sciplot.set_size_cm(16, 8)
300 | fig, ax = plt.subplots(1, 1)
301 |
302 | fig.suptitle('Histogram of normally distributed velocities with ' + str(n) + ' samples')
303 |
304 | plot_lst = []
305 | color_lst = sciplot.get_color_lst(len(data_ar), seaborn_color_map='rocket', colorful=False)
306 |
307 | for i, data in enumerate(data_ar):
308 | ax.hist(data, density=True, bins=100, alpha=0.7, color=color_lst[i])
309 | plot_lst.append(Rectangle((0, 0), 1, 1, color=color_lst[i], alpha=0.7))
310 |
311 | label_lst = []
312 | for i in range(len(data_ar)):
313 | label_lst.append(r'$\mu=' + str(mean_ar[i]) + r'$, $\sigma=' + str(std_ar[i]) + r'$')
314 |
315 | sciplot.set_legend(
316 | ax=ax,
317 | plot_tpl=tuple(plot_lst),
318 | label_tpl=tuple(label_lst),
319 | loc='lower right',
320 | outside_plot=True
321 | )
322 |
323 | ax.set_xlabel('Velocity (m/s)')
324 | ax.set_ylabel(r'Relative frequency')
325 |
326 | return fig
327 |
--------------------------------------------------------------------------------
/sciplot/main.py:
--------------------------------------------------------------------------------
1 | import contextlib
2 | import csv
3 | import locale
4 | import logging
5 | import os
6 | import re
7 | import warnings
8 | from datetime import datetime
9 | from pathlib import Path
10 | from typing import List, Tuple, Union, OrderedDict
11 | import matplotlib
12 | import matplotlib.pyplot as plt
13 | import seaborn as sns
14 | import yaml
15 |
16 | # Reset Matplotlib style library (use in case of unresolved errors)
17 | # plt.style.reload_library()
18 |
19 | # Disable "findfont: Font family ['serif'] not found. Falling back to DejaVu Sans."
20 | logging.getLogger('matplotlib.font_manager').disabled = True
21 |
22 | # Dark mode boolean operator
23 | dark_mode = False
24 |
25 |
26 | # sciplot warning class
27 | class SciplotWarning(UserWarning):
28 | pass
29 |
30 |
31 | # sciplot exception class
32 | class SciplotException(Exception):
33 | pass
34 |
35 |
36 | def _get_theme_lst(theme_input):
37 | theme_lst = []
38 | if isinstance(theme_input, str):
39 | theme_lst.append(theme_input)
40 | elif isinstance(theme_input, list):
41 | for theme in theme_input:
42 | if not isinstance(theme, str):
43 | raise SciplotException(
44 | "Incorrect theme input type in list for theme '" +
45 | str(theme) +
46 | "': '" +
47 | str(type(theme_input)) +
48 | "'. Correct input type is 'str'.")
49 | theme_lst = theme_input
50 | else:
51 | raise SciplotException(
52 | "Incorrect theme input type: '" +
53 | str(type(theme_input)) +
54 | "'. Correct input type is 'str' or 'list'.")
55 |
56 | # Remove double entries and make theme inputs lowercase
57 | theme_lst = [theme.lower() for theme in OrderedDict.fromkeys(theme_lst)]
58 |
59 | return theme_lst
60 |
61 |
62 | def _get_default_theme_lst(
63 | theme_lst: List[str]
64 | ) -> List[str]:
65 | if 'clean' in theme_lst:
66 | if 'default' in theme_lst:
67 | theme_lst.remove('default')
68 |
69 | theme_lst.remove('clean')
70 | else:
71 | if 'default' not in theme_lst:
72 | theme_lst.append('default')
73 |
74 | return theme_lst
75 |
76 |
77 | def _get_parameter_file_lst(
78 | theme: str
79 | ) -> List[str]:
80 | if theme == 'default':
81 | parameter_file_lst = ['basic', 'typesetting', 'colors_light', 'fonts_cm_sans_serif', 'latex_sans_serif']
82 | elif theme == 'dark':
83 | plt.style.use('dark_background')
84 | global dark_mode
85 | dark_mode = True
86 | parameter_file_lst = ['colors_dark']
87 | elif theme == 'serif':
88 | parameter_file_lst = ['fonts_cm_serif', 'latex_serif']
89 | elif theme == 'sans-serif':
90 | parameter_file_lst = ['fonts_cm_sans_serif', 'latex_sans_serif']
91 | elif theme == 'no-latex':
92 | parameter_file_lst = ['no_latex']
93 | else:
94 | parameter_file_lst = [theme]
95 |
96 | return parameter_file_lst
97 |
98 |
99 | def _theme_exists(
100 | theme: str
101 | ) -> bool:
102 | if not (theme in get_theme_priority_lst()):
103 | try:
104 | parameters_dir = Path(__file__).parent / 'parameters'
105 | parameters_path = parameters_dir / (theme + '.yml')
106 | with parameters_path.open():
107 | pass
108 | return True
109 | except FileNotFoundError:
110 | warnings.warn("Invalid theme ignored by Sciplot: '" + theme + "'", SciplotWarning)
111 | return False
112 | else:
113 | return False
114 |
115 |
116 | def _get_parameters_lst(
117 | parameter_file_lst: List[str]
118 | ) -> List[object]:
119 | # Empty list of parameters
120 | parameters_lst = []
121 |
122 | parameters_dir = Path(__file__).parent / 'parameters'
123 |
124 | # Import parameters
125 | for parameter_file in parameter_file_lst:
126 | try:
127 | parameters_path = parameters_dir / (parameter_file + '.yml')
128 | with parameters_path.open() as setup_file:
129 | parameters = yaml.safe_load(setup_file.read())
130 | if parameters:
131 | parameters_lst.append(parameters)
132 | except FileNotFoundError:
133 | raise SciplotException(
134 | "Unable to import theme parameter file: '" + parameter_file + "'")
135 |
136 | return parameters_lst
137 |
138 |
139 | @contextlib.contextmanager
140 | def style(
141 | theme: Union[str, List[str]] = 'default',
142 | locale_setting: str = 'sv_SE'
143 | ):
144 | # Set locale (to get correct decimal separater etc)
145 | locale.setlocale(locale.LC_NUMERIC, locale_setting)
146 |
147 | # Get requested themes as list
148 | theme_lst = _get_theme_lst(theme)
149 |
150 | # Get list with or without default theme
151 | theme_lst = _get_default_theme_lst(theme_lst)
152 |
153 | # Get ordered list if parameter files
154 | parameter_file_lst = []
155 | theme_priority_lst = get_theme_priority_lst()
156 | theme_priority_lst.reverse()
157 |
158 | # Add themes' associated parameter files to list
159 | for theme_priority in theme_priority_lst:
160 | for theme in theme_lst:
161 | if theme == theme_priority:
162 | parameter_file_lst += _get_parameter_file_lst(theme)
163 |
164 | # Add user defined themes to parameter_file_lst
165 | if any(theme not in theme_priority_lst for theme in theme_lst):
166 | for theme in theme_lst:
167 | if _theme_exists(theme):
168 | parameter_file_lst += _get_parameter_file_lst(theme)
169 |
170 | # Get list of parameter objects from file list
171 | parameters_lst = _get_parameters_lst(parameter_file_lst)
172 |
173 | # Set all parameters in list
174 | for parameters in parameters_lst:
175 | plt.rcParams.update(parameters)
176 |
177 | yield
178 |
179 | plt.style.use('default')
180 | global dark_mode
181 | dark_mode = False
182 |
183 |
184 | def get_parameters_dir() -> str:
185 | return str(Path(__file__).parent / 'parameters')
186 |
187 |
188 | def get_theme_priority_lst() -> List[str]:
189 | theme_priority_lst = [
190 | 'alpha',
191 | 'beta',
192 | 'gamma',
193 | 'no-latex',
194 | 'serif',
195 | 'sans-serif',
196 | 'dark',
197 | 'default'
198 | ]
199 | return theme_priority_lst
200 |
201 |
202 | def get_available_locals():
203 | locales_file_path = Path(__file__).parent / 'parameters' / 'locales.csv'
204 | with open(locales_file_path, 'r') as file:
205 | csv_reader = csv.reader(file, delimiter='\t')
206 | print('=' * 89 + '\n', ' ' * 35, 'Available locales', ' ' * 35, '\n' + '=' * 89 + '\n')
207 | print('{0:<30}{1:<20}{2}'.format(*['Locale', 'Code set', 'Description']))
208 | print('-' * 89)
209 | for row in csv_reader:
210 | print('{0:<30}{1:<20}{2}'.format(*row))
211 |
212 |
213 | def set_size_cm(
214 | width: float,
215 | height: float = None
216 | ):
217 | if height is None:
218 | height = width
219 |
220 | cm2in = 1 / 2.54
221 | plt.rcParams['figure.figsize'] = (width * cm2in, height * cm2in)
222 |
223 |
224 | def set_legend(
225 | ax: matplotlib.axes.Axes,
226 | plot_tpl: Tuple[matplotlib.artist.Artist],
227 | label_tpl: Tuple[str],
228 | loc: str = 'lower left',
229 | outside_plot: bool = False,
230 | handle_scale_factor: float = 5.
231 | ):
232 | if outside_plot:
233 | if 'right' in loc:
234 | horizontal_anchor = 1.04
235 | loc = loc.replace('right', 'left')
236 | elif 'left' in loc:
237 | horizontal_anchor = 0.94
238 | loc = loc.replace('left', 'right')
239 | else:
240 | horizontal_anchor = 0.5
241 |
242 | if 'upper' in loc:
243 | vertical_anchor = 1.
244 | elif 'lower' in loc:
245 | vertical_anchor = 0.
246 | else:
247 | vertical_anchor = 0.5
248 |
249 | lgnd = ax.legend(
250 | plot_tpl,
251 | label_tpl,
252 | scatterpoints=1,
253 | loc=loc,
254 | bbox_to_anchor=(horizontal_anchor, vertical_anchor)
255 | )
256 | else:
257 | lgnd = ax.legend(
258 | plot_tpl,
259 | label_tpl,
260 | scatterpoints=1,
261 | loc=loc,
262 | )
263 |
264 | for lgnd_handle in lgnd.legendHandles:
265 | lgnd_handle._sizes = [handle_scale_factor]
266 |
267 |
268 | def get_color_lst(
269 | color_no: int,
270 | seaborn_color_map: str = 'cubehelix',
271 | colorful: bool = False
272 | ) -> List[str]:
273 | if color_no == 0 or not isinstance(color_no, int):
274 | raise SciplotException("Invalid number of colors: '" + str(color_no) + "'")
275 |
276 | if color_no > 4 and colorful:
277 | color_lst = sns.color_palette(seaborn_color_map, color_no).as_hex()
278 | elif color_no == 1 and not dark_mode:
279 | color_lst = ['#000000']
280 | elif color_no == 1 and dark_mode:
281 | color_lst = ['#FFFFFF']
282 | elif not colorful and dark_mode:
283 | color_lst = sns.color_palette(seaborn_color_map, color_no).as_hex()[:-1] + ['#FFFFFF']
284 | else:
285 | color_lst = ['#000000'] + sns.color_palette(seaborn_color_map, color_no).as_hex()[:-1]
286 |
287 | return color_lst
288 |
289 |
290 | def save_time_stamped_figure(
291 | plot_file_name: str, # filnamn/filsökväg med eller utan ändelse, t.ex. .png eller .pdf
292 | save_directory: str = '', # valfri uppdelning i filnamn och mappsökväg
293 | file_type: str = 'png' # filtyp
294 | ):
295 | time_stamp = datetime.today().strftime('%Y-%m-%dT%H.%M')
296 | if 'png' in plot_file_name:
297 | plot_file_name = str(re.sub(r'\.png$', '', plot_file_name))
298 | elif 'pdf' in plot_file_name:
299 | plot_file_name = str(re.sub(r'\.pdf$', '', plot_file_name))
300 |
301 | if save_directory == '':
302 | plot_file_path = plot_file_name + '_' + time_stamp + '.' + file_type
303 | else:
304 | plot_file_path = os.path.join(
305 | save_directory,
306 | plot_file_name + '_' + time_stamp + '.' + file_type
307 | )
308 |
309 | plt.savefig(plot_file_path, bbox_inches='tight', pad_inches=0.04)
310 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Sciplot
2 |
3 | [
](https://pypi.org/project/sciplot)
4 | [
](https://github.com/andreasfuhr/sciplot)
5 |
6 | *Format Matplotlib scientific plots*
7 |
8 | *Sciplot* is a Python package that formats scientific plots created with Matplotlib in a
9 | user-friendly, yet highly customizable way.
10 | It makes typesetting in LaTeX possible and comes with several methods that makes plotting more
11 | straightforward and less cluttered, without sacrificing full control over plot settings.
12 |
13 | Two examples of plots created with Sciplot:
14 |
15 |
16 |
17 |
18 | The Sciplot package was developed by [Andreas Führ](https://www.linkedin.com/in/fuhrandreas/) in May 2021.
19 |
20 | ## Installation and getting started
21 |
22 | To install the latest release from PyPI, use the following command:
23 |
24 | ```bash
25 | pip install sciplot
26 | ```
27 |
28 | To install the latest commit, please use:
29 |
30 | ```bash
31 | pip install git+https://github.com/andreasfuhr/sciplot.git
32 | ```
33 |
34 |
35 | Formatting plots in Matplotlib is based on a functional `with`-statement context. A MWE can be demonstrated as follows:
36 |
37 | ```python
38 | import matplotlib.pyplot as plt
39 | import numpy as np
40 | import sciplot
41 |
42 | x = np.arange(0, 2 * np.pi, 1e-2)
43 | y1 = np.sin(2 * x + np.pi)
44 | y2 = np.cos(2 * x + np.pi)
45 |
46 | sciplot.set_size_cm(5) # Alternatively, set figure size with Matplotlib directly
47 |
48 | with sciplot.style():
49 | plt.plot(x, y1, x, y2)
50 | plt.xticks(
51 | np.linspace(0, 2 * np.pi, 5),
52 | ['$0$', r'$\frac{\pi}{2}$', r'$\pi$', r'$\frac{3\pi}{2}$', r'$2\pi$']
53 | )
54 | plt.show()
55 | ```
56 |
57 | This produces the following output:
58 |
59 |
60 |
61 | ## Overview
62 |
63 | ### Key Features
64 |
65 | * User-friendly. A *style context manager* is used for all Matplotlib related user code and can be passed several
66 | themes and arguments to alter the look of the plot, such as:
67 | * LaTeX typesetting
68 | * serif or sans serif font
69 | * dark mode
70 | * [locale](https://docs.oracle.com/cd/E23824_01/html/E26033/glset.html) string (for correct decimal
71 | separator etc.)
72 | * Implements LaTeX kernel for typesetting plots. A versatile LaTeX preamble is included that is specifically
73 | created and optionally editable for mathematics- and physics-oriented papers, theses and presentations. Both the
74 | [siunitx](https://ctan.org/pkg/siunitx) and [physics](https://www.ctan.org/pkg/physics) LaTeX packages are included by
75 | default in the parameter settings.
76 | * Easy customization. Most settings have been moved to parameters files, which are imported to the context manager and
77 | configured with `matplotlibrc`. The **user is encouraged to edit** these accessible and highly readable YAML parameters
78 | files, or **create new theme-associated parameter files**, whom are found with the `sciplot.get_paramters_dir()`
79 | method.
80 | * Includes a set of useful methods relevant during plotting:
81 | * `sciplot.set_size_cm()` for setting figure sizes in centimeters
82 | * `sciplot.set_legend()` for customizing the content and position of plot legends
83 | * `sciplot.get_color_lst()` for extracting a list of colors of specified length and from a given Seaborn colormap
84 | * `sciplot.save_time_stamped_figure` for saving plots in an easy manner with time stamped file names
85 |
86 | ### Disadvantages
87 |
88 | * Slow. LaTeX typesetting, turned on by default, can take quite some time to compile. Loading the parameters is however
89 | not known from experience to be time consuming.
90 | * Only compatible with Python 3.7 and later. The 3.3.4 version of Matplotlib fixes several bugs that directly solves
91 | some earlier issues with this package.
92 |
93 | It should be noted that although this package is in many ways similar to [[1]](#1), which is a recommended
94 | alternative approach, Sciplot has been independently developed and has a multitude of structural and functional
95 | differences.
96 |
97 | ## How to use Sciplot
98 |
99 | ### The style context and themes
100 |
101 | The `sciplot.style()` context manager is the core feature of Sciplot. It is a powerful and versetile tool for a
102 | complete control of the looks of plots created with Matplotlib. The context manager operates with two input arguments:
103 | `theme` and `locale_setting`. By default, creating plots within the style context
104 |
105 | ```python
106 | with sciplot.style():
107 | ...
108 | ```
109 |
110 | is equivalent to the following style context:
111 |
112 | ```python
113 | with sciplot.style(theme='default', locale_setting='sv_SE.UTF-8'):
114 | ...
115 | ```
116 |
117 | #### Themes
118 |
119 | A handful of themes are bundled with Sciplot. The `theme` argument can be passed either a single theme as a *string* or
120 | a *list of theme strings*. Since all themes are not mutually exclusive w.r.t. Matplotlib settings, the themes are
121 | segmented such that Sciplot distinguishes which style settings are more important and becomes prioritized (higher
122 | number means lower priority):
123 |
124 | Priority | Theme | Description
125 | :------- | :--------------- | :----------
126 | 0 | *Custom theme* | A theme entirely made by the user. This is done by creating a parameter file in the `sciplot.parameter` directory. A theme named **my_fabulous_theme** will for example extract parameter settings from a file named `my_fabulous_theme.yml`.
127 | 1 | ***alpha*** | Predefined, contentless user theme. Intended for editing by user.
128 | 2 | ***beta*** | Predefined, contentless user theme. Intended for editing by user.
129 | 3 | ***gamma*** | Predefined, contentless user theme. Intended for editing by user.
130 | 4 | ***no-latex*** | No local LaTeX kernel is used for typesetting.
131 | 5 | ***serif*** | *Computer Modern Roman* used as text and math font, with typesetting in LaTeX.
132 | 6 | ***sans-serif*** | *Computer Modern Roman Sans Serif* used as text and math font, with typesetting in LaTeX.
133 | 7 | ***dark*** | Uses Matplotlib's `dark_background` style and comes with a set of colours suitable for plotting against a black background.
134 | 8 | ***default*** | The default theme. Always active unless the ***clean*** "theme" is used. Uses LaTeX typesetting and *Computer Modern Roman Sans Serif* as text and math font. Initialises basic figure settings for linewidths, ticks, legends, font sizes, dpi, margins, etc. Also comes with the *cubehelix* colourmap [[2]](#2) as well as basic plot colours and styles.
135 | – | ***clean*** | Not technically a theme. Simpy inactivates the ***default*** theme.
136 |
137 | #### Locales
138 |
139 | The `locale_setting` argument lets the user determine the *locale* to be used in a plot, thereby determining a set of
140 | parameters that defines the user's language, region and other regionally based settings and whom are used by Matplotlib
141 | to alter the appearance of a plot. To see all available locales, one can call the `sciplot.get_available_locals`
142 | method for a console printout.
143 |
144 | #### Code example
145 |
146 | If a plot style with dark theme, LaTeX, a serif font (Computer Modern Roman) and local settings for the United States
147 | is requested, the style context should be initiated with
148 |
149 | ```python
150 | with sciplot.style(['dark', 'serif'], 'en_US'):
151 | ...
152 | ```
153 |
154 | ## Future improvements
155 |
156 | The package is still in its infancy and is planned to be expanded in features and configurability. Here is a list of
157 | what is in the pipeline:
158 | * Documentation of source code
159 | * Instructions on how to install a local LaTeX distribution
160 | * Making it possible to choose LaTeX fonts. As of currently, *Computer Modern Roman* and *Computer Modern Roman Sans
161 | Serif* are the only two font options for both text and mathematical notation.
162 | * Include more example plots in documentation
163 | * Write instructions on how to use the package
164 | * Address potential issues with user defined themes and updating sciplot
165 | * Move sciplot methods not used by the user outside of `sciplot.main`
166 |
167 | ### Table of proposed themes not yet implemented
168 |
169 | Name of theme | Priority | Background color | Font | Seaborn colormap | Figure size
170 | :--------------------------------------- | :------- | :--------------- | :--------------------------- | :--------------- | :--------------------------------
171 | ***antique*** | low | white | Garamond | *TBD* | -
172 | ***ieee_column*** | medium | white | ?[1](#f1) | *TBD* | 88 mm[2](#f2)
173 | ***ieee_page*** | low | white | ?[1](#f1) | *TBD* | 181 mm[2](#f2)
174 | ***grid*** | high
175 |
176 | 1: One of the following Open Type fonts are suggested to be used: Times New Roman, Helvetica, Arial,
177 | Cambria or Symbol [[3]](#3).
178 |
179 | 2: See [[3]](#3) for a description of sizes that graphics should be.
180 |
181 | ## Citing Sciplot
182 |
183 | To cite this Python package, please use the following BibTeX citation:
184 |
185 | ```tex
186 | @article{Sciplot,
187 | author = {Andreas H. Führ},
188 | title = {{andreasfuhr/sciplot}},
189 | month = May,
190 | year = 2021,
191 | version = {0.8.1},
192 | url = {https://github.com/andreasfuhr/sciplot}
193 | }
194 | ```
195 |
196 | Note that under the current license, citing this package is not necessary. The creator will however be happy and
197 | thankful for any recognition.
198 |
199 | ## References
200 |
201 | [1]
202 | J.D. Garrett and H. Peng,
203 | *garrettj403/SciencePlots*,
204 | ver. 1.0.7.
205 | Zenodo,
206 | Feb. 2021.
207 | \[Online].
208 | doi: [10.5281/zenodo.4106649](http://doi.org/10.5281/zenodo.4106649)
209 |
210 | [2]
211 | D.A. Green,
212 | "A colour scheme for the display of astronomical intensity images,"
213 | in *Bulletin of the Astronomical Society of India*, vol. 39, pp. 289–295, 2011.
214 | \[Online].
215 | Available: [arXiv:1108.5083](https://arxiv.org/abs/1108.5083).
216 |
217 | [3]
218 | "Preparation of papers for IEEE Transactions and Journals (December 2013),"
219 | in IEEE Transactions on Consumer Electronics,
220 | vol. 63,
221 | no. 1,
222 | pp. c3-c3,
223 | February 2017,
224 | doi: [10.1109/TCE.2017.7932035](http://doi.org/10.1109/TCE.2017.7932035)
225 |
--------------------------------------------------------------------------------
/sciplot/parameters/locales.csv:
--------------------------------------------------------------------------------
1 | C US-ASCII C,POSIX
2 | POSIX US-ASCII C,POSIX
3 | af_ZA.UTF-8 UTF-8 Afrikaans,SouthAfrica
4 | ar_AE.UTF-8 UTF-8 Arabic,UnitedArabEmirates
5 | ar_BH.UTF-8 UTF-8 Arabic,Bahrain
6 | ar_DZ.UTF-8 UTF-8 Arabic,Algeria
7 | ar_EG.UTF-8 UTF-8 Arabic,Egypt
8 | ar_IQ.UTF-8 UTF-8 Arabic,Iraq
9 | ar_JO.UTF-8 UTF-8 Arabic,Jordan
10 | ar_KW.UTF-8 UTF-8 Arabic,Kuwait
11 | ar_LY.UTF-8 UTF-8 Arabic,Libya
12 | ar_MA.UTF-8 UTF-8 Arabic,Morocco
13 | ar_OM.UTF-8 UTF-8 Arabic,Oman
14 | ar_QA.UTF-8 UTF-8 Arabic,Qatar
15 | ar_SA.UTF-8 UTF-8 Arabic,SaudiArabia
16 | ar_TN.UTF-8 UTF-8 Arabic,Tunisia
17 | ar_YE.UTF-8 UTF-8 Arabic,Yemen
18 | as_IN.UTF-8 UTF-8 Assamese,India
19 | az_AZ.UTF-8 UTF-8 Azerbaijani,Azerbaijan
20 | be_BY.UTF-8 UTF-8 Belarusian,Belarus
21 | bg_BG.UTF-8 UTF-8 Bulgarian,Bulgaria
22 | bn_IN.UTF-8 UTF-8 Bengali,India
23 | bs_BA.UTF-8 UTF-8 Bosnian,BosniaandHerzegovina
24 | ca_ES.UTF-8 UTF-8 Catalan,Spain
25 | cs_CZ.UTF-8 UTF-8 Czech,CzechRepublic
26 | da_DK.UTF-8 UTF-8 Danish,Denmark
27 | de_AT.UTF-8 UTF-8 German,Austria
28 | de_BE.UTF-8 UTF-8 German,Belgium
29 | de_CH.UTF-8 UTF-8 German,Switzerland
30 | de_DE.UTF-8 UTF-8 German,Germany
31 | de_LI.UTF-8 UTF-8 German,Liechtenstein
32 | de_LU.UTF-8 UTF-8 German,Luxembourg
33 | el_CY.UTF-8 UTF-8 Greek,Cyprus
34 | el_GR.UTF-8 UTF-8 Greek,Greece
35 | en_AU.UTF-8 UTF-8 English,Australia
36 | en_BW.UTF-8 UTF-8 English,Botswana
37 | en_CA.UTF-8 UTF-8 English,Canada
38 | en_GB.UTF-8 UTF-8 English,UnitedKingdom
39 | en_HK.UTF-8 UTF-8 English,HongKongSARChina
40 | en_IE.UTF-8 UTF-8 English,Ireland
41 | en_IN.UTF-8 UTF-8 English,India
42 | en_MT.UTF-8 UTF-8 English,Malta
43 | en_NZ.UTF-8 UTF-8 English,NewZealand
44 | en_PH.UTF-8 UTF-8 English,Philippines
45 | en_SG.UTF-8 UTF-8 English,Singapore
46 | en_US.UTF-8 UTF-8 English,U.S.A.
47 | en_ZW.UTF-8 UTF-8 English,Zimbabwe
48 | es_AR.UTF-8 UTF-8 Spanish,Argentina
49 | es_BO.UTF-8 UTF-8 Spanish,Bolivia
50 | es_CL.UTF-8 UTF-8 Spanish,Chile
51 | es_CO.UTF-8 UTF-8 Spanish,Colombia
52 | es_CR.UTF-8 UTF-8 Spanish,CostaRica
53 | es_DO.UTF-8 UTF-8 Spanish,DominicanRepublic
54 | es_EC.UTF-8 UTF-8 Spanish,Ecuador
55 | es_ES.UTF-8 UTF-8 Spanish,Spain
56 | es_GT.UTF-8 UTF-8 Spanish,Guatemala
57 | es_HN.UTF-8 UTF-8 Spanish,Honduras
58 | es_MX.UTF-8 UTF-8 Spanish,Mexico
59 | es_NI.UTF-8 UTF-8 Spanish,Nicaragua
60 | es_PA.UTF-8 UTF-8 Spanish,Panama
61 | es_PE.UTF-8 UTF-8 Spanish,Peru
62 | es_PR.UTF-8 UTF-8 Spanish,PuertoRico
63 | es_PY.UTF-8 UTF-8 Spanish,Paraguay
64 | es_SV.UTF-8 UTF-8 Spanish,ElSalvador
65 | es_US.UTF-8 UTF-8 Spanish,U.S.A.
66 | es_UY.UTF-8 UTF-8 Spanish,Uruguay
67 | es_VE.UTF-8 UTF-8 Spanish,Venezuela
68 | et_EE.UTF-8 UTF-8 Estonian,Estonia
69 | fi_FI.UTF-8 UTF-8 Finnish,Finland
70 | fr_BE.UTF-8 UTF-8 French,Belgium
71 | fr_CA.UTF-8 UTF-8 French,Canada
72 | fr_CH.UTF-8 UTF-8 French,Switzerland
73 | fr_FR.UTF-8 UTF-8 French,France
74 | fr_LU.UTF-8 UTF-8 French,Luxembourg
75 | gu_IN.UTF-8 UTF-8 Gujarati,India
76 | he_IL.UTF-8 UTF-8 Hebrew,Israel
77 | hi_IN.UTF-8 UTF-8 Hindi,India
78 | hr_HR.UTF-8 UTF-8 Croatian,Croatia
79 | hu_HU.UTF-8 UTF-8 Hungarian,Hungary
80 | hy_AM.UTF-8 UTF-8 Armenian,Armenia
81 | id_ID.UTF-8 UTF-8 Indonesian,Indonesia
82 | is_IS.UTF-8 UTF-8 Icelandic,Iceland
83 | it_CH.UTF-8 UTF-8 Italian,Switzerland
84 | it_IT.UTF-8 UTF-8 Italian,Italy
85 | ja_JP.UTF-8 UTF-8 Japanese,Japan
86 | ka_GE.UTF-8 UTF-8 Georgian,Georgia
87 | kk_KZ.UTF-8 UTF-8 Kazakh,Kazakhstan
88 | kn_IN.UTF-8 UTF-8 Kannada,India
89 | ko_KR.UTF-8 UTF-8 Korean,Korea
90 | ks_IN.UTF-8 UTF-8 Kashmiri,India
91 | ku_TR.UTF-8 UTF-8 Kurdish,Turkey
92 | ku_TR.UTF-8@sorani UTF-8 Kurdish(Sorani),Turkey
93 | ky_KG.UTF-8 UTF-8 Kirghiz,Kyrgyzstan
94 | lt_LT.UTF-8 UTF-8 Lithuanian,Lithuania
95 | lv_LV.UTF-8 UTF-8 Latvian,Latvia
96 | mk_MK.UTF-8 UTF-8 Macedonian,Macedonia
97 | ml_IN.UTF-8 UTF-8 Malayalam,India
98 | mr_IN.UTF-8 UTF-8 Marathi,India
99 | ms_MY.UTF-8 UTF-8 Malay,Malaysia
100 | mt_MT.UTF-8 UTF-8 Maltese,Malta
101 | nb_NO.UTF-8 UTF-8 Bokmal,Norway
102 | nl_BE.UTF-8 UTF-8 Dutch,Belgium
103 | nl_NL.UTF-8 UTF-8 Dutch,Netherlands
104 | nn_NO.UTF-8 UTF-8 Nynorsk,Norway
105 | or_IN.UTF-8 UTF-8 Oriya,India
106 | pa_IN.UTF-8 UTF-8 Punjabi,India
107 | pl_PL.UTF-8 UTF-8 Polish,Poland
108 | pt_BR.UTF-8 UTF-8 Portuguese,Brazil
109 | pt_PT.UTF-8 UTF-8 Portuguese,Portugal
110 | ro_RO.UTF-8 UTF-8 Romanian,Romania
111 | ru_RU.UTF-8 UTF-8 Russian,Russia
112 | ru_UA.UTF-8 UTF-8 Russian,Ukraine
113 | sa_IN.UTF-8 UTF-8 Sanskrit,India
114 | sk_SK.UTF-8 UTF-8 Slovak,Slovakia
115 | sl_SI.UTF-8 UTF-8 Slovenian,Slovenia
116 | sq_AL.UTF-8 UTF-8 Albanian,Albania
117 | sr_ME.UTF-8 UTF-8 Serbian,Montenegro
118 | sr_ME.UTF-8@latin UTF-8 Serbian,Montenegro(Latin)
119 | sr_RS.UTF-8 UTF-8 Serbian,Serbia
120 | sr_RS.UTF-8@latin UTF-8 Serbian,Serbia(Latin)
121 | sv_SE.UTF-8 UTF-8 Swedish,Sweden
122 | ta_IN.UTF-8 UTF-8 Tamil,India
123 | te_IN.UTF-8 UTF-8 Telugu,India
124 | th_TH.UTF-8 UTF-8 Thai,Thailand
125 | tr_TR.UTF-8 UTF-8 Turkish,Turkey
126 | uk_UA.UTF-8 UTF-8 Ukrainian,Ukraine
127 | vi_VN.UTF-8 UTF-8 Vietnamese,Vietnam
128 | zh_CN.UTF-8 UTF-8 SimplifiedChinese,China
129 | zh_HK.UTF-8 UTF-8 TraditionalChinese,HongKongSARChina
130 | zh_SG.UTF-8 UTF-8 Chinese,Singapore
131 | zh_TW.UTF-8 UTF-8 TraditionalChinese,Taiwan
132 | ar_EG.ISO8859-6 ISO8859-6 Arabic,Egypt
133 | bg_BG.ISO8859-5 ISO8859-5 Bulgarian,Bulgaria
134 | bs_BA.ISO8859-2 ISO8859-2 Bosnian,BosniaandHerzegovina
135 | ca_ES.ISO8859-1 ISO8859-1 Catalan,Spain
136 | ca_ES.ISO8859-15 ISO8859-15 Catalan,Spain
137 | cs_CZ.ISO8859-2 ISO8859-2 Czech,CzechRepublic
138 | CZ.UTF-8@euro UTF-8 Czech,CzechRepublic(Euro)
139 | da_DK.ISO8859-1 ISO8859-1 Danish,Denmark
140 | da_DK.ISO8859-15 ISO8859-15 Danish,Denmark
141 | da_DK.ISO8859-15@euro ISO8859-15 Danish,Denmark(Euro)
142 | de_AT.ISO8859-1 ISO8859-1 German,Austria
143 | de_AT.ISO8859-15 ISO8859-15 German,Austria
144 | de_CH.ISO8859-1 ISO8859-1 German,Switzerland
145 | de_DE.ISO8859-1 ISO8859-1 German,Germany
146 | de_DE.ISO8859-15 ISO8859-15 German,Germany
147 | el_GR.ISO8859-7 ISO8859-7 Greek,Greece
148 | en_AU.ISO8859-1 ISO8859-1 English,Australia
149 | en_CA.ISO8859-1 ISO8859-1 English,Canada
150 | en_GB.ISO8859-1 ISO8859-1 English,UnitedKingdom
151 | en_GB.ISO8859-15 ISO8859-15 English,UnitedKingdom
152 | en_GB.ISO8859-15@euro ISO8859-15 English,UnitedKingdom(Euro)
153 | en_IE.ISO8859-1 ISO8859-1 English,Ireland
154 | en_IE.ISO8859-15 ISO8859-15 English,Ireland
155 | en_NZ.ISO8859-1 ISO8859-1 English,NewZealand
156 | en_US.ISO8859-1 ISO8859-1 English,U.S.A.
157 | en_US.ISO8859-15 ISO8859-15 English,U.S.A.
158 | en_US.ISO8859-15@euro ISO8859-15 English,U.S.A.(Euro)
159 | es_AR.ISO8859-1 ISO8859-1 Spanish,Argentina
160 | es_BO.ISO8859-1 ISO8859-1 Spanish,Bolivia
161 | es_CL.ISO8859-1 ISO8859-1 Spanish,Chile
162 | es_CO.ISO8859-1 ISO8859-1 Spanish,Colombia
163 | es_CR.ISO8859-1 ISO8859-1 Spanish,CostaRica
164 | es_EC.ISO8859-1 ISO8859-1 Spanish,Ecuador
165 | es_ES.ISO8859-1 ISO8859-1 Spanish,Spain
166 | es_ES.ISO8859-15 ISO8859-15 Spanish,Spain
167 | es_GT.ISO8859-1 ISO8859-1 Spanish,Guatemala
168 | es_MX.ISO8859-1 ISO8859-1 Spanish,Mexico
169 | es_NI.ISO8859-1 ISO8859-1 Spanish,Nicaragua
170 | es_PA.ISO8859-1 ISO8859-1 Spanish,Panama
171 | es_PE.ISO8859-1 ISO8859-1 Spanish,Peru
172 | es_PY.ISO8859-1 ISO8859-1 Spanish,Paraguay
173 | es_SV.ISO8859-1 ISO8859-1 Spanish,ElSalvador
174 | es_UY.ISO8859-1 ISO8859-1 Spanish,Uruguay
175 | es_VE.ISO8859-1 ISO8859-1 Spanish,Venezuela
176 | et_EE.ISO8859-15 ISO8859-15 Estonian,Estonia
177 | fi_FI.ISO8859-1 ISO8859-1 Finnish,Finland
178 | fi_FI.ISO8859-15 ISO8859-15 Finnish,Finland
179 | fr_BE.ISO8859-1 ISO8859-1 French,Belgium
180 | fr_BE.ISO8859-15 ISO8859-15 French,Belgium
181 | fr_CA.ISO8859-1 ISO8859-1 French,Canada
182 | fr_CH.ISO8859-1 ISO8859-1 French,Switzerland
183 | fr_FR.ISO8859-1 ISO8859-1 French,France
184 | fr_FR.ISO8859-15 ISO8859-15 French,France
185 | he_IL.ISO8859-8 ISO8859-8 Hebrew,Israel
186 | hr_HR.ISO8859-2 ISO8859-2 Croatian,Croatia
187 | hu_HU.ISO8859-2 ISO8859-2 Hungarian,Hungary
188 | is_IS.ISO8859-1 ISO8859-1 Icelandic,Iceland
189 | it_IT.ISO8859-1 ISO8859-1 Italian,Italy
190 | it_IT.ISO8859-15 ISO8859-15 Italian,Italy
191 | ja_JP.PCK PCK Japanese,Japan(PCKanjicode,aka.Shift-JIS)
192 | ja_JP.eucJP EUC-JP JapaneseEUCenvironment.ComplianttoUI-OSFJapaneseEnvironmentImplementationAgreementVersion1.1
193 | ko_KR.EUC KSX1001 Korean,Korea
194 | ko_KR.EUC@dict KSX1001 Korean,Korea(dict)
195 | ko_KR.UTF-8@dict UTF-8 Korean,Korea(dict)
196 | lt_LT.ISO8859-13 ISO8859-13 Lithuanian,Lithuania
197 | lv_LV.ISO8859-13 ISO8859-13 Latvian,Latvia
198 | mk_MK.ISO8859-5 ISO8859-5 Macedonian,Macedonia
199 | nb_NO.ISO8859-1 ISO8859-1 NorwegianBokmal,Norway
200 | nl_BE.ISO8859-1 ISO8859-1 Dutch,Belgium
201 | nl_BE.ISO8859-15 ISO8859-15 Dutch,Belgium
202 | nl_NL.ISO8859-1 ISO8859-1 Dutch,Netherlands
203 | nl_NL.ISO8859-15 ISO8859-15 Dutch,Netherlands
204 | nn_NO.ISO8859-1 ISO8859-1 NorwegianNynorsk,Norway
205 | pl_PL.ISO8859-2 ISO8859-2 Polish,Poland
206 | pt_BR.ISO8859-1 ISO8859-1 Portuguese,Brazil
207 | pt_PT.ISO8859-1 ISO8859-1 Portuguese,Portugal
208 | pt_PT.ISO8859-15 ISO8859-15 Portuguese,Portugal
209 | ro_RO.ISO8859-2 ISO8859-2 Romanian,Romania
210 | ru_RU.ANSI1251 ANSI1251 Russian,Russia
211 | ru_RU.ISO8859-5 ISO8859-5 Russian,Russia
212 | ru_RU.KOI8-R KOI8-R Russian,Russia
213 | sk_SK.ISO8859-2 ISO8859-2 Slovak,Slovakia
214 | sl_SI.ISO8859-2 ISO8859-2 Slovenian,Slovenia
215 | sq_AL.ISO8859-2 ISO8859-2 Albanian,Albania
216 | sr_ME.ISO8859-5 ISO8859-5 Serbian,Montenegro
217 | sv_SE.ISO8859-1 ISO8859-1 Swedish,Sweden
218 | sv_SE.ISO8859-15 ISO8859-15 Swedish,Sweden
219 | sv_SE.ISO8859-15@euro ISO8859-15 Swedish,Sweden(Euro)
220 | sv_SE.UTF-8@euro UTF-8 Swedish,Sweden(Euro)
221 | th_TH.TIS620 TIS-620 Thai,Thailand
222 | tr_TR.ISO8859-9 ISO8859-9 Turkish,Turkey
223 | zh_CN.EUC GB2312 SimplifiedChinese,China
224 | zh_CN.EUC@pinyin GB2312 SimplifiedChinese,China(pinyin)
225 | zh_CN.EUC@radical GB2312 SimplifiedChinese,China(radical)
226 | zh_CN.EUC@stroke GB2312 SimplifiedChinese,China(stroke)
227 | zh_CN.GB18030 GB18030 SimplifiedChinese,China
228 | zh_CN.GB18030@pinyin GB18030 SimplifiedChinese,China(pinyin)
229 | zh_CN.GB18030@radical GB18030 SimplifiedChinese,China(radical)
230 | zh_CN.GB18030@stroke GB18030 SimplifiedChinese,China(stroke)
231 | zh_CN.GBK GBK SimplifiedChinese,China
232 | zh_CN.GBK@pinyin GBK SimplifiedChinese,China(pinyin)
233 | zh_CN.GBK@radical GBK SimplifiedChinese,China(radical)
234 | zh_CN.GBK@stroke GBK SimplifiedChinese,China(stroke)
235 | zh_CN.UTF-8@pinyin UTF-8 SimplifiedChinese,China(pinyin)
236 | zh_CN.UTF-8@radical UTF-8 SimplifiedChinese,China(radical)
237 | zh_CN.UTF-8@stroke UTF-8 SimplifiedChinese,China(stroke)
238 | zh_HK.BIG5HK BIG5-HKSCS TraditionalChinese,HongKongSARChina
239 | zh_HK.BIG5HK@radical BIG5-HKSCS TraditionalChinese,HongKongSARChina(radical)
240 | zh_HK.BIG5HK@stroke BIG5-HKSCS TraditionalChinese,HongKongSARChina(stroke)
241 | zh_HK.UTF-8@radical UTF-8 TraditionalChinese,HongKongSARChina(radical)
242 | zh_HK.UTF-8@stroke UTF-8 TraditionalChinese,HongKongSARChina(stroke)
243 | zh_TW.BIG5 BIG5 TraditionalChinese,Taiwan
244 | zh_TW.BIG5@pinyin BIG5 TraditionalChinese,Taiwan(pinyin)
245 | zh_TW.BIG5@radical BIG5 TraditionalChinese,Taiwan(radical)
246 | zh_TW.BIG5@stroke BIG5 TraditionalChinese,Taiwan(stroke)
247 | zh_TW.BIG5@zhuyin BIG5 TraditionalChinese,Taiwan(zhuyin)
248 | zh_TW.EUC CNS11643-1992 TraditionalChinese,Taiwan
249 | zh_TW.EUC@pinyin CNS11643 TraditionalChinese,Taiwan(pinyin)
250 | zh_TW.EUC@radical CNS11643 TraditionalChinese,Taiwan(radical)
251 | zh_TW.EUC@stroke CNS11643 TraditionalChinese,Taiwan(stroke)
252 | zh_TW.EUC@zhuyin CNS11643 TraditionalChinese,Taiwan(zhuyin)
253 | zh_TW.UTF-8@pinyin UTF-8 TraditionalChinese,Taiwan(pinyin)
254 | zh_TW.UTF-8@radical UTF-8 TraditionalChinese,Taiwan(radical)
255 | zh_TW.UTF-8@stroke UTF-8 TraditionalChinese,Taiwan(stroke)
256 | zh_TW.UTF-8@zhuyin UTF-8 TraditionalChinese,Taiwan(zhuyin)
--------------------------------------------------------------------------------