From bcf99e3ee552be71c4570bc8f1b2dbdb04644d09 Mon Sep 17 00:00:00 2001 From: Joe Stanley Date: Fri, 12 May 2023 21:45:48 -0700 Subject: [PATCH 1/4] cleanup and addition of .readthedocs.yaml file --- .github/workflows/pytest.yml | 2 +- .github/workflows/sphinx.yml | 4 +-- .readthedocs.yaml | 29 +++++++++++++++++++ cspell.json | 17 +++++++++++ docsource/conf.py | 2 +- .../{sphinxrequires.txt => requirements.txt} | 0 electricpy/__init__.py | 4 +-- test/{pytestrequires.txt => requirements.txt} | 0 8 files changed, 52 insertions(+), 6 deletions(-) create mode 100644 .readthedocs.yaml create mode 100644 cspell.json rename docsource/{sphinxrequires.txt => requirements.txt} (100%) rename test/{pytestrequires.txt => requirements.txt} (100%) diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index 10c9abb1..6a638168 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -25,7 +25,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - if [ -f test/pytestrequires.txt ]; then pip install -r test/pytestrequires.txt; fi + if [ -f test/requirements.txt ]; then pip install -r test/requirements.txt; fi pip install . python3 -c "import electricpy; print('electricpy.__file__')" - name: Test with pytest diff --git a/.github/workflows/sphinx.yml b/.github/workflows/sphinx.yml index e2d72070..ed5a7f00 100644 --- a/.github/workflows/sphinx.yml +++ b/.github/workflows/sphinx.yml @@ -23,7 +23,7 @@ jobs: run: | python -m pip install --upgrade pip cp logo/ElectricpyLogo.svg docsource/static/ElectricpyLogo.svg - pip install -r docsource/sphinxrequires.txt + pip install -r docsource/requirements.txt - name: Build Sphinx docs if: success() run: | @@ -33,7 +33,7 @@ jobs: - name: Generate Coverage Badge if: success() run: | - pip install -r test/pytestrequires.txt + pip install -r test/requirements.txt coverage run --source=./electricpy -m pytest coverage-badge -o docs/html/coverage.svg diff --git a/.readthedocs.yaml b/.readthedocs.yaml new file mode 100644 index 00000000..febe6212 --- /dev/null +++ b/.readthedocs.yaml @@ -0,0 +1,29 @@ +# .readthedocs.yaml +# Read the Docs configuration file +# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details + +# Required +version: 2 + +# Set the version of Python and other tools you might need +build: + os: ubuntu-22.04 + tools: + python: "3.11" + # You can also specify other tool versions: + # nodejs: "19" + # rust: "1.64" + # golang: "1.19" + +# Build documentation in the docs/ directory with Sphinx +sphinx: + configuration: docsource/conf.py + +# If using Sphinx, optionally build your docs in additional formats such as PDF +# formats: +# - pdf + +# Optionally declare the Python requirements required to build your docs +python: + install: + - requirements: docsource/requirements.txt \ No newline at end of file diff --git a/cspell.json b/cspell.json new file mode 100644 index 00000000..0091ee48 --- /dev/null +++ b/cspell.json @@ -0,0 +1,17 @@ +{ + "version": "0.2", + "ignorePaths": [], + "dictionaryDefinitions": [], + "dictionaries": [], + "words": [ + "electricpy", + "matplotlib", + "parallelz", + "phasor", + "phasors", + "pyplot", + "scipy" + ], + "ignoreWords": [], + "import": [] +} diff --git a/docsource/conf.py b/docsource/conf.py index e0a9498a..3b2a9882 100644 --- a/docsource/conf.py +++ b/docsource/conf.py @@ -83,7 +83,7 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', "sphinxrequires.txt"] +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', "requirements.txt"] templates_path = ["_templates"] diff --git a/docsource/sphinxrequires.txt b/docsource/requirements.txt similarity index 100% rename from docsource/sphinxrequires.txt rename to docsource/requirements.txt diff --git a/electricpy/__init__.py b/electricpy/__init__.py index 701852b6..d836a235 100644 --- a/electricpy/__init__.py +++ b/electricpy/__init__.py @@ -25,8 +25,8 @@ from scipy.integrate import quad as integrate # Import Submodules -from .constants import * -from .phasors import phasor, parallelz +from electricpy.constants import * +from electricpy.phasors import phasor, parallelz __version__ = VERSION diff --git a/test/pytestrequires.txt b/test/requirements.txt similarity index 100% rename from test/pytestrequires.txt rename to test/requirements.txt From ceda1dfe0c8a58a55dbcd49b06b06cb3eab14b8a Mon Sep 17 00:00:00 2001 From: Joe Stanley Date: Fri, 12 May 2023 22:06:14 -0700 Subject: [PATCH 2/4] additional cleanup --- README.md | 1 - cspell.json | 8 ++- electricpy/__init__.py | 4 +- electricpy/bode.py | 4 +- electricpy/constants.py | 1 - electricpy/conversions.py | 1 - electricpy/fault.py | 6 +- electricpy/latex.py | 1 - electricpy/machines.py | 4 +- electricpy/math.py | 1 - electricpy/passive.py | 1 + electricpy/phasors.py | 1 - electricpy/thermal.py | 5 +- electricpy/version.py | 3 +- electricpy/visu.py | 112 ++++++++++++++++++++------------------ 15 files changed, 77 insertions(+), 76 deletions(-) diff --git a/README.md b/README.md index 2afe2579..01a3dbf3 100644 --- a/README.md +++ b/README.md @@ -153,7 +153,6 @@ opportunity to take advantage of this project. For more information regarding this resource, please contact Joe Stanley - -- ## License and Usage diff --git a/cspell.json b/cspell.json index 0091ee48..2e7da734 100644 --- a/cspell.json +++ b/cspell.json @@ -5,12 +5,18 @@ "dictionaries": [], "words": [ "electricpy", + "epmath", + "fsolve", "matplotlib", "parallelz", "phasor", + "phasorlist", + "phasorplot", "phasors", + "powerset", "pyplot", - "scipy" + "scipy", + "visu" ], "ignoreWords": [], "import": [] diff --git a/electricpy/__init__.py b/electricpy/__init__.py index d836a235..41076c8d 100644 --- a/electricpy/__init__.py +++ b/electricpy/__init__.py @@ -13,18 +13,16 @@ ################################################################################ -from .version import NAME, VERSION import cmath as _c from inspect import getframeinfo as _getframeinfo from inspect import stack as _stack from warnings import showwarning as _showwarning import matplotlib.pyplot as _plt -# Import Supporting Modules import numpy as _np from scipy.integrate import quad as integrate -# Import Submodules +from electricpy.version import NAME, VERSION from electricpy.constants import * from electricpy.phasors import phasor, parallelz diff --git a/electricpy/bode.py b/electricpy/bode.py index 3db8ab1c..d62a8914 100644 --- a/electricpy/bode.py +++ b/electricpy/bode.py @@ -8,12 +8,12 @@ from cmath import exp as _exp -# Import External Dependencies + import matplotlib.pyplot as _plt import numpy as _np import scipy.signal as _sig from numpy import pi as _pi -# Import Local Dependencies + from electricpy.math import convolve # Define System Conditioning Function diff --git a/electricpy/constants.py b/electricpy/constants.py index 930f0b6e..cf8aa790 100644 --- a/electricpy/constants.py +++ b/electricpy/constants.py @@ -7,7 +7,6 @@ """ ################################################################################ -# Import Supporting Dependencies import numpy as _np import cmath as _c diff --git a/electricpy/conversions.py b/electricpy/conversions.py index 43321a16..af24905a 100644 --- a/electricpy/conversions.py +++ b/electricpy/conversions.py @@ -12,7 +12,6 @@ """ ################################################################################ -# Import Local Requirements from electricpy.constants import WATTS_PER_HP, Aabc, A012, KWH_PER_BTU # Import Required Packages diff --git a/electricpy/fault.py b/electricpy/fault.py index 00e5e899..db20b0f1 100644 --- a/electricpy/fault.py +++ b/electricpy/fault.py @@ -6,14 +6,12 @@ """ ################################################################################ -# Import Necessary Dependencies import numpy as _np import matplotlib.pyplot as _plt from scipy.optimize import fsolve as _fsolve -# Import Local Dependencies -from .constants import * -from .conversions import seq_to_abc +from electricpy.constants import * +from electricpy.conversions import seq_to_abc def _phaseroll(M012, reference): diff --git a/electricpy/latex.py b/electricpy/latex.py index 50399308..f8e6ab9c 100644 --- a/electricpy/latex.py +++ b/electricpy/latex.py @@ -15,7 +15,6 @@ import cmath as _c -# Import Required Packages import numpy as _np diff --git a/electricpy/machines.py b/electricpy/machines.py index ecf8cc87..efadc749 100644 --- a/electricpy/machines.py +++ b/electricpy/machines.py @@ -6,13 +6,11 @@ """ ################################################################################ -# Required Imports import cmath as _c import numpy as _np from scipy.optimize import fsolve as _fsolve -# Import Locals -from .phasors import compose +from electricpy.phasors import compose # Define Transformer Short-Circuit/Open-Circuit Function diff --git a/electricpy/math.py b/electricpy/math.py index 5ea31a34..9188d577 100644 --- a/electricpy/math.py +++ b/electricpy/math.py @@ -13,7 +13,6 @@ """ ################################################################################ -# Import Required Packages import numpy as _np import scipy.signal as _sig from scipy.integrate import quad as integrate diff --git a/electricpy/passive.py b/electricpy/passive.py index eaf457d0..54da14a5 100644 --- a/electricpy/passive.py +++ b/electricpy/passive.py @@ -5,6 +5,7 @@ Filled with methods related capacitors. """ ################################################################################ + import numpy as _np diff --git a/electricpy/phasors.py b/electricpy/phasors.py index 0413d496..c856ccc9 100644 --- a/electricpy/phasors.py +++ b/electricpy/phasors.py @@ -13,7 +13,6 @@ """ ################################################################################ -# Import Required Packages import numpy as _np import cmath as _c diff --git a/electricpy/thermal.py b/electricpy/thermal.py index 9322b206..272246da 100644 --- a/electricpy/thermal.py +++ b/electricpy/thermal.py @@ -7,12 +7,9 @@ """ ################################################################################ - -# Import Supporting Modules import numpy as _np -# Import Submodules -from .constants import * +from electricpy.constants import * # Define Cold-Junction-Voltage Calculator def coldjunction(Tcj, coupletype="K", To=None, Vo=None, P1=None, P2=None, diff --git a/electricpy/version.py b/electricpy/version.py index 9c7f3855..94c21e35 100644 --- a/electricpy/version.py +++ b/electricpy/version.py @@ -7,5 +7,6 @@ This file is to keep track of Name, Current Version of electricpy for CI and CD """ ################################################################################ + NAME = "electricpy" -VERSION = "0.3.0" \ No newline at end of file +VERSION = "0.3.0" diff --git a/electricpy/visu.py b/electricpy/visu.py index c6206ca5..82e2e02e 100644 --- a/electricpy/visu.py +++ b/electricpy/visu.py @@ -7,9 +7,8 @@ """ ################################################################################ -import cmath - import cmath as _c + import numpy as _np import matplotlib as _matplotlib import matplotlib.pyplot as _plt @@ -60,47 +59,53 @@ def powertriangle(P=None, Q=None, S=None, PF=None, color="red", P, Q, S, PF = powerset(P, Q, S, PF) # Generate Lines - Plnx = [0, P] - Plny = [0, 0] - Qlnx = [P, P] - Qlny = [0, Q] - Slnx = [0, P] - Slny = [0, Q] + p_line_x = [0, P] + p_line_y = [0, 0] + q_line_x = [P, P] + q_line_y = [0, Q] + s_line_x = [0, P] + s_line_y = [0, Q] # Plot Power Triangle _plt.figure(1) _plt.title(text) - _plt.plot(Plnx, Plny, color=color) - _plt.plot(Qlnx, Qlny, color=color) - _plt.plot(Slnx, Slny, color=color) + _plt.plot(p_line_x, p_line_y, color=color) + _plt.plot(q_line_x, q_line_y, color=color) + _plt.plot(s_line_x, s_line_y, color=color) _plt.xlabel("Real Power (W)") _plt.ylabel("Reactive Power (VAR)") - mx = max(abs(P), abs(Q)) + maximum = max(abs(P), abs(Q)) if P > 0: - _plt.xlim(0, mx * 1.1) - x = mx + _plt.xlim(0, maximum * 1.1) + x = maximum else: - _plt.xlim(-mx * 1.1, 0) - x = -mx + _plt.xlim(-maximum * 1.1, 0) + x = -maximum if Q > 0: - _plt.ylim(0, mx * 1.1) - y = mx + _plt.ylim(0, maximum * 1.1) + y = maximum else: - _plt.ylim(-mx * 1.1, 0) - y = -mx + _plt.ylim(-maximum * 1.1, 0) + y = -maximum if PF > 0: - PFtext = " Lagging" + power_factor_text = "Lagging" else: - PFtext = " Leading" - text = "P: " + str(P) + " W\n" - text = text + "Q: " + str(Q) + " VAR\n" - text = text + "S: " + str(S) + " VA\n" - text = text + "PF: " + str(abs(PF)) + PFtext + "\n" - text = text + "ΘPF: " + str(_np.degrees(_np.arccos(PF))) + "°" + PFtext + power_factor_text = "Leading" # Print all values if asked to if printval: - _plt.text(x / 20, y * 4 / 5, text, color=color) + _plt.text( + x/20, + y*4/5, + ( + f"P: {P} W\n" + f"Q: {Q} VAR\n" + f"S: {S} VA\n" + f"PF: {abs(PF)} {power_factor_text}\n" + f"ΘPF: {_np.degrees(_np.arccos(PF))}° {power_factor_text}" + ), + color=color + ) return _plt @@ -247,20 +252,18 @@ def phasorplot(phasors, title="Phasor Diagram", legend=False, bg=None, # Set Tolerance if tolerance is None: tolerance = radius / 25 - elif tolerance == False: + elif tolerance is False: tolerance = -1 # Set Background Color if bg is None: bg = "#FFFFFF" # Load labels if handled in other argument - if label != False: + if label: legend = label - if labels != False: + if labels: legend = labels # Check for more phasors than colors - numphs = len(phasors) - numclr = len(colors) - if numphs > numclr: + if len(phasors) > len(colors): raise ValueError( "ERROR: Too many phasors provided. Specify more line colors." ) @@ -276,23 +279,26 @@ def phasorplot(phasors, title="Phasor Diagram", legend=False, bg=None, # Plot the diagram _plt.title(title + "\n") - handles = _np.array([]) # Empty array for plot handles - for i in range(numphs): - mag, ang_r = _c.polar(phasors[i]) + arrows = [] + for i, phasor in enumerate(phasors): + mag, ang_r = _c.polar(phasor) # Plot with labels if legend: if mag > tolerance: - hand = _plt.arrow(0, 0, ang_r, mag, color=colors[i], + arrows.append( + _plt.arrow(0, 0, ang_r, mag, color=colors[i], label=legend[i], linewidth=linewidth) + ) else: - hand = _plt.plot(0, 0, 'o', markersize=linewidth * 3, + arrows.append( + _plt.plot(0, 0, 'o', markersize=linewidth * 3, label=legend[i], color=colors[i]) - handles = _np.append(handles, [hand]) + ) # Plot without labels else: _plt.arrow(0, 0, ang_r, mag, color=colors[i], linewidth=linewidth) if legend: - _plt.legend(handles, legend) + _plt.legend(arrows, legend) # Set Minimum and Maximum Radius Terms ax.set_rmax(radius) ax.set_rmin(0) @@ -337,7 +343,7 @@ class InductionMotorCircle: output_power: int Desired power output from the induction motor torque_ration: float - Ration between rotor resitance to stator resistance + Ration between rotor resistance to stator resistance (i.e., R2/R1) frequency: int AC supply frequency @@ -350,7 +356,7 @@ def __init__(self, no_load_data, blocked_rotor_data, output_power, """Primary Entrypoint.""" self.no_load_data = no_load_data self.blocked_rotor_data = blocked_rotor_data - self.f = frequency + self.frequency = frequency self.operating_power = output_power self.torque_ratio = torque_ration self.poles = poles @@ -636,7 +642,7 @@ class PowerCircle: Plot Power Circle Diagram of Transmission System. This class is designed to plot the power circle diagram of a transmission - system both sending and reciving ends. + system both sending and receiving ends. Examples -------- @@ -723,14 +729,14 @@ def __init__(self, power_circle_type: str, power_factor: float = None, def _build_circle(a1, a2, circle_type, V, P=None, Q=None, S=None, power_factor=None, V_ref=None): k = (abs(V) ** 2) * abs(a1) / abs(a2) - alpha = cmath.phase(a1) - beta = cmath.phase(a2) + alpha = _c.phase(a1) + beta = _c.phase(a2) if circle_type == "receiving_end": - center = Point(-k * cmath.cos(alpha - beta), -k * cmath.sin(alpha - beta)) + center = Point(-k * _c.cos(alpha - beta), -k * _c.sin(alpha - beta)) elif circle_type == "sending_end": - center = Point(k * cmath.cos(alpha - beta), -k * cmath.sin(alpha - beta)) + center = Point(k * _c.cos(alpha - beta), -k * _c.sin(alpha - beta)) if V_ref is not None and P is not None and Q is not None: radius = abs(V) * abs(V_ref) / (abs(a2)) @@ -750,21 +756,23 @@ def _build_circle(a1, a2, circle_type, V, P=None, Q=None, S=None, power_factor=N elif P is not None and power_factor is not None: - Q = P * cmath.sqrt(1 / power_factor ** 2 - 1).real + Q = P * _c.sqrt(1 / power_factor ** 2 - 1).real if power_factor < 0: - Q = -Q + Q = -1 * Q radius = geometry.distance(center, Point(P, Q)) operation_point = Point(P, Q) elif Q is not None and power_factor is not None: - P = Q / cmath.sqrt(1 / power_factor ** 2 - 1).real + P = Q / _c.sqrt(1 / power_factor ** 2 - 1).real radius = geometry.distance(center, Point(P, Q)) operation_point = Point(P, Q) else: - raise AttributeError("Enought attributes to calculate not found") + raise AttributeError( + "Not enough attributes found to perform calculation" + ) return radius, center, operation_point From f3f19978aa0256d3ff813a0ff5c3120e144acf90 Mon Sep 17 00:00:00 2001 From: Joe Stanley Date: Fri, 12 May 2023 22:14:28 -0700 Subject: [PATCH 3/4] additional cleanup --- .github/workflows/pythonpackage.yml | 37 ----------------------------- electricpy/__init__.py | 8 +++---- pyproject.toml | 6 +++++ tox.ini | 23 ------------------ 4 files changed, 9 insertions(+), 65 deletions(-) delete mode 100644 .github/workflows/pythonpackage.yml delete mode 100644 tox.ini diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml deleted file mode 100644 index 8dedf33f..00000000 --- a/.github/workflows/pythonpackage.yml +++ /dev/null @@ -1,37 +0,0 @@ -# This workflow will install Python dependencies, run tests and lint with a variety of Python versions -# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions - -name: Python Package Tests - -on: - push: - branches: ["master"] - pull_request: - branches: ["master"] - -jobs: - tests: - name: "Python ${{ matrix.python-version }}" - runs-on: "ubuntu-latest" - env: - USING_COVERAGE: '3.7,3.11' - - strategy: - matrix: - python-version: ["3.7", "3.8", "3.9", "3.11"] - - steps: - - uses: "actions/checkout@v2" - - uses: "actions/setup-python@v1" - with: - python-version: "${{ matrix.python-version }}" - - name: "Install dependencies" - run: | - set -xe - python -VV - python -m site - python -m pip install --upgrade pip setuptools wheel - python -m pip install --upgrade coverage[toml] virtualenv tox tox-gh-actions - - - name: "Run tox targets for ${{ matrix.python-version }}" - run: "python -m tox" diff --git a/electricpy/__init__.py b/electricpy/__init__.py index 41076c8d..04b2022a 100644 --- a/electricpy/__init__.py +++ b/electricpy/__init__.py @@ -22,15 +22,13 @@ import numpy as _np from scipy.integrate import quad as integrate -from electricpy.version import NAME, VERSION -from electricpy.constants import * -from electricpy.phasors import phasor, parallelz +from .version import NAME, VERSION +from .constants import * +from .phasors import phasor, parallelz __version__ = VERSION # Define Cycle Time Function - - def tcycle(ncycles=1, freq=60): r""" Time of Electrical Cycles. diff --git a/pyproject.toml b/pyproject.toml index b5704e46..2ca60057 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -28,6 +28,7 @@ classifiers = [ "Operating System :: OS Independent" ] dynamic = ["version"] + dependencies = [ "NumPy", "matplotlib", @@ -36,6 +37,11 @@ dependencies = [ "numdifftools", ] +[project.optional-dependencies] +numerical = ["numdifftools"] +fault = ["arcflash"] +full = ["numdifftools", "arcflash"] + [project.urls] Home = "https://electricpy.readthedocs.io/en/latest/index.html" Repository = "https://github.com/engineerjoe440/ElectricPy" diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 0da62eb9..00000000 --- a/tox.ini +++ /dev/null @@ -1,23 +0,0 @@ -# tox (https://tox.readthedocs.io/) is a tool for running tests -# in multiple virtualenvs. This configuration file will run the -# test suite on all supported python versions. To use it, "pip install tox" -# and then run "tox" from this directory. - -[tox] -envlist = py36, py37, py38 - -[gh-actions] -python = - 3.6: py36 - 3.7: py37, docs - 3.8: py38, lint, manifest - -[testenv] -deps = - scipy - sympy - numpy - matplotlib - numdifftools -commands = - - python setup.py test From ad7b11dcedf20cbb0aa35713d04754bb5c726a5f Mon Sep 17 00:00:00 2001 From: Joe Stanley Date: Fri, 12 May 2023 22:21:04 -0700 Subject: [PATCH 4/4] updated readme with installation options --- README.md | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 01a3dbf3..fc5ac887 100644 --- a/README.md +++ b/README.md @@ -54,10 +54,11 @@ notebooks!) ## Installing / Getting Started -1. Install ElectricPy with `pip` +1. ElectricPy has a few basic installation options for use with `pip`. For most +common users, use the following command to install ElectricPy with `pip` ``` -pip install electricpy +pip install electricpy[full] ``` 2. Check installation success in Python environment: @@ -103,8 +104,17 @@ and installing locally. - [matplotlib](https://matplotlib.org/) - [SciPy](https://scipy.org/) - [SymPy](https://www.sympy.org/en/index.html) + +#### Optional Dependencies + +For numerical analysis (install with `pip install electricpy[numerical]`): + - [numdifftools](https://numdifftools.readthedocs.io/en/latest/) +For fault analysis (install with `pip install electricpy[fault]`) + +- [arcflash](https://github.com/LiaungYip/arcflash) + ## Get Involved / Contribute