From 9140c19d2a33088a19336af7dbc445d8f455e2b8 Mon Sep 17 00:00:00 2001 From: Chance Date: Wed, 18 Sep 2019 11:55:47 -0500 Subject: [PATCH 1/4] Redo the cookiecutter to update things --- .github/ISSUE_TEMPLATE.md | 2 +- .travis.yml | 16 ++++++++++++++-- CONTRIBUTING.rst | 12 ++++++------ Makefile | 2 +- README.rst | 11 +++++++---- docs/conf.py | 6 +++--- docs/index.rst | 2 +- docs/installation.rst | 8 ++++---- docs/usage.rst | 2 +- phypy/__init__.py | 2 +- phypy/cli.py | 18 ++++++++++++++++++ requirements.txt | 26 +++++++++++--------------- setup.cfg | 1 + setup.py | 15 +++++++++++---- tests/__init__.py | 3 +++ tests/test_phypy.py | 34 ++++++++++++++++++++++++++++++++++ tox.ini | 6 +++--- 17 files changed, 120 insertions(+), 46 deletions(-) create mode 100644 phypy/cli.py create mode 100644 tests/__init__.py diff --git a/.github/ISSUE_TEMPLATE.md b/.github/ISSUE_TEMPLATE.md index 75453f5..18ab33b 100644 --- a/.github/ISSUE_TEMPLATE.md +++ b/.github/ISSUE_TEMPLATE.md @@ -1,4 +1,4 @@ -* phypy version: +* PhyPy version: * Python version: * Operating System: diff --git a/.travis.yml b/.travis.yml index c56ed8c..e351425 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,20 @@ +# Config file for automatic testing at travis-ci.org + language: python python: -- 3.6 + - 3.7 + - 3.6 + +# Command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors install: pip install -U tox-travis + +# Command to run tests, e.g. python setup.py test script: tox + +# Assuming you have installed the travis-ci CLI tool, after you +# create the Github repo and add it to Travis, run the +# following command to finish PyPI deployment setup: +# $ travis encrypt --add deploy.password deploy: provider: pypi distributions: sdist bdist_wheel @@ -12,4 +24,4 @@ deploy: on: tags: true repo: ctarver/phypy - python: 3.6 + python: 3.7 diff --git a/CONTRIBUTING.rst b/CONTRIBUTING.rst index 8d922fe..cb8559c 100644 --- a/CONTRIBUTING.rst +++ b/CONTRIBUTING.rst @@ -38,8 +38,8 @@ and "help wanted" is open to whoever wants to implement it. Write Documentation ~~~~~~~~~~~~~~~~~~~ -phypy could always use more documentation, whether as part of the -official phypy docs, in docstrings, or even on the web in blog posts, +PhyPy could always use more documentation, whether as part of the +official PhyPy docs, in docstrings, or even on the web in blog posts, articles, and such. Submit Feedback @@ -80,7 +80,7 @@ Ready to contribute? Here's how to set up `phypy` for local development. tests, including testing other Python versions with tox:: $ flake8 phypy tests - $ python setup.py test or py.test + $ python setup.py test or pytest $ tox To get flake8 and tox, just pip install them into your virtualenv. @@ -102,7 +102,7 @@ Before you submit a pull request, check that it meets these guidelines: 2. If the pull request adds functionality, the docs should be updated. Put your new functionality into a function with a docstring, and add the feature to the list in README.rst. -3. The pull request should work for Python 2.7, 3.4, 3.5 and 3.6, and for PyPy. Check +3. The pull request should work for Python 3.6 and 3.7, and for PyPy. Check https://travis-ci.org/ctarver/phypy/pull_requests and make sure that the tests pass for all supported Python versions. @@ -111,7 +111,7 @@ Tips To run a subset of tests:: -$ py.test tests.test_phypy +$ pytest tests.test_phypy Deploying @@ -121,7 +121,7 @@ A reminder for the maintainers on how to deploy. Make sure all your changes are committed (including an entry in HISTORY.rst). Then run:: -$ bumpversion patch # possible: major / minor / patch +$ bump2version patch # possible: major / minor / patch $ git push $ git push --tags diff --git a/Makefile b/Makefile index 684fd16..1811cc2 100644 --- a/Makefile +++ b/Makefile @@ -54,7 +54,7 @@ lint: ## check style with flake8 flake8 phypy tests test: ## run tests quickly with the default Python - py.test + pytest test-all: ## run tests on every Python version with tox tox diff --git a/README.rst b/README.rst index cb364b3..f19ebb2 100644 --- a/README.rst +++ b/README.rst @@ -1,12 +1,12 @@ ===== -phypy +PhyPy ===== .. image:: https://img.shields.io/pypi/v/phypy.svg :target: https://pypi.python.org/pypi/phypy -.. image:: https://travis-ci.org/ctarver/phypy.svg?branch=master +.. image:: https://img.shields.io/travis/ctarver/phypy.svg :target: https://travis-ci.org/ctarver/phypy .. image:: https://readthedocs.org/projects/phypy/badge/?version=latest @@ -14,6 +14,10 @@ phypy :alt: Documentation Status +.. image:: https://pyup.io/repos/github/ctarver/phypy/shield.svg + :target: https://pyup.io/repos/github/ctarver/phypy/ + :alt: Updates + Library of tools for wireless, physical layer research, simulations, and testing. @@ -26,8 +30,7 @@ Library of tools for wireless, physical layer research, simulations, and testing Features -------- -* A power amplifier model with realistic coefficients extracted from a WARPv3 board PA. - +* TODO Credits ------- diff --git a/docs/conf.py b/docs/conf.py index eaa936b..9063d52 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -47,7 +47,7 @@ master_doc = 'index' # General information about the project. -project = u'phypy' +project = u'PhyPy' copyright = u"2019, Chance Tarver" author = u"Chance Tarver" @@ -129,7 +129,7 @@ # [howto, manual, or own class]). latex_documents = [ (master_doc, 'phypy.tex', - u'phypy Documentation', + u'PhyPy Documentation', u'Chance Tarver', 'manual'), ] @@ -152,7 +152,7 @@ # dir menu entry, description, category) texinfo_documents = [ (master_doc, 'phypy', - u'phypy Documentation', + u'PhyPy Documentation', author, 'phypy', 'One line description of project.', diff --git a/docs/index.rst b/docs/index.rst index 5bf9031..8ea5271 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,4 +1,4 @@ -Welcome to phypy's documentation! +Welcome to PhyPy's documentation! ====================================== .. toctree:: diff --git a/docs/installation.rst b/docs/installation.rst index d2e4609..19eb629 100644 --- a/docs/installation.rst +++ b/docs/installation.rst @@ -8,13 +8,13 @@ Installation Stable release -------------- -To install phypy, run this command in your terminal: +To install PhyPy, run this command in your terminal: .. code-block:: console $ pip install phypy -This is the preferred method to install phypy, as it will always install the most recent stable release. +This is the preferred method to install PhyPy, as it will always install the most recent stable release. If you don't have `pip`_ installed, this `Python installation guide`_ can guide you through the process. @@ -26,7 +26,7 @@ you through the process. From sources ------------ -The sources for phypy can be downloaded from the `Github repo`_. +The sources for PhyPy can be downloaded from the `Github repo`_. You can either clone the public repository: @@ -38,7 +38,7 @@ Or download the `tarball`_: .. code-block:: console - $ curl -OL https://github.com/ctarver/phypy/tarball/master + $ curl -OJL https://github.com/ctarver/phypy/tarball/master Once you have a copy of the source, you can install it with: diff --git a/docs/usage.rst b/docs/usage.rst index 0a0c407..e5bf9a9 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -2,6 +2,6 @@ Usage ===== -To use phypy in a project:: +To use PhyPy in a project:: import phypy diff --git a/phypy/__init__.py b/phypy/__init__.py index 5b77144..b018a25 100644 --- a/phypy/__init__.py +++ b/phypy/__init__.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -"""Top-level package for phypy.""" +"""Top-level package for PhyPy.""" __author__ = """Chance Tarver""" __email__ = 'tarver.chance@gmail.com' diff --git a/phypy/cli.py b/phypy/cli.py new file mode 100644 index 0000000..25ee453 --- /dev/null +++ b/phypy/cli.py @@ -0,0 +1,18 @@ +# -*- coding: utf-8 -*- + +"""Console script for phypy.""" +import sys +import click + + +@click.command() +def main(args=None): + """Console script for phypy.""" + click.echo("Replace this message by putting your code into " + "phypy.cli.main") + click.echo("See click documentation at https://click.palletsprojects.com/") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) # pragma: no cover diff --git a/requirements.txt b/requirements.txt index 10493d4..283f5d5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,16 +1,12 @@ -pip==18.1 -bumpversion==0.5.3 -wheel==0.32.1 +pip==19.2.3 +bump2version==0.5.11 +wheel==0.33.6 watchdog==0.9.0 -flake8==3.5.0 -tox==3.5.2 -coverage==4.5.1 -Sphinx==1.8.1 -twine==1.12.1 - -pytest==3.8.2 -pytest-runner==4.2 -mypy - -numpy -matplotlib +flake8==3.7.8 +tox==3.14.0 +coverage==4.5.4 +Sphinx==1.8.5 +twine==1.14.0 +Click==7.0 +pytest==4.6.5 +pytest-runner==5.1 \ No newline at end of file diff --git a/setup.cfg b/setup.cfg index 507ff2e..747f898 100644 --- a/setup.cfg +++ b/setup.cfg @@ -18,6 +18,7 @@ universal = 1 exclude = docs [aliases] +# Define setup.py command aliases here test = pytest [tool:pytest] diff --git a/setup.py b/setup.py index 9da45bf..9170ce5 100644 --- a/setup.py +++ b/setup.py @@ -11,30 +11,37 @@ with open('HISTORY.rst') as history_file: history = history_file.read() -requirements = ['numpy'] +requirements = ['Click>=7.0','numpy' ] setup_requirements = ['pytest-runner', ] -test_requirements = ['pytest', ] +test_requirements = ['pytest>=3', ] setup( author="Chance Tarver", author_email='tarver.chance@gmail.com', + python_requires='>=3.6', classifiers=[ 'Development Status :: 2 - Pre-Alpha', 'Intended Audience :: Developers', 'License :: OSI Approved :: MIT License', 'Natural Language :: English', - 'Programming Language :: Python :: 3.6' + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: 3.7', ], description="Library of tools for wireless, physical layer research, simulations, and testing.", + entry_points={ + 'console_scripts': [ + 'phypy=phypy.cli:main', + ], + }, install_requires=requirements, license="MIT license", long_description=readme + '\n\n' + history, include_package_data=True, keywords='phypy', name='phypy', - packages=find_packages(include=['phypy']), + packages=find_packages(include=['phypy', 'phypy.*']), setup_requires=setup_requirements, test_suite='tests', tests_require=test_requirements, diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..69d2fe2 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1,3 @@ +# -*- coding: utf-8 -*- + +"""Unit test package for phypy.""" diff --git a/tests/test_phypy.py b/tests/test_phypy.py index 0b1b4c3..ddab4ac 100644 --- a/tests/test_phypy.py +++ b/tests/test_phypy.py @@ -5,10 +5,44 @@ import pytest import numpy as np + +from click.testing import CliRunner + +from phypy import phypy +from phypy import cli from phypy import analog from phypy import modulators as mods from phypy import dsp + + +@pytest.fixture +def response(): + """Sample pytest fixture. + + See more at: http://doc.pytest.org/en/latest/fixture.html + """ + # import requests + # return requests.get('https://github.com/audreyr/cookiecutter-pypackage') + + +def test_content(response): + """Sample pytest test function with the pytest fixture as an argument.""" + # from bs4 import BeautifulSoup + # assert 'GitHub' in BeautifulSoup(response.content).title.string + + +def test_command_line_interface(): + """Test the CLI.""" + runner = CliRunner() + result = runner.invoke(cli.main) + assert result.exit_code == 0 + assert 'phypy.cli.main' in result.output + help_result = runner.invoke(cli.main, ['--help']) + assert help_result.exit_code == 0 + assert '--help Show this message and exit.' in help_result.output + + def test_pa_setup(): pa = analog.PowerAmp(order=5, memory_depth=2, noise_variance=0.01, add_lo_leakage=False, add_iq_imbalance=False) assert pa.order == 5 diff --git a/tox.ini b/tox.ini index 010c4d4..c724bac 100644 --- a/tox.ini +++ b/tox.ini @@ -1,8 +1,9 @@ [tox] -envlist = py36, flake8 +envlist = py36, py37 flake8 [travis] python = + 3.7: py37 3.6: py36 [testenv:flake8] @@ -20,6 +21,5 @@ deps = ; -r{toxinidir}/requirements.txt commands = pip install -U pip - py.test --basetemp={envtmpdir} - + pytest --basetemp={envtmpdir} From 6ce77c446a6beae22999c171a7097ff017f9e840 Mon Sep 17 00:00:00 2001 From: Chance Date: Wed, 18 Sep 2019 11:56:19 -0500 Subject: [PATCH 2/4] Also update sphinx conf --- docs/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 9063d52..9004275 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -32,7 +32,7 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode', 'sphinx.ext.napoleon', 'sphinx.ext.todo'] +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.viewcode'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] @@ -140,7 +140,7 @@ # (source start file, name, description, authors, manual section). man_pages = [ (master_doc, 'phypy', - u'phypy Documentation', + u'PhyPy Documentation', [author], 1) ] From 96f186cbb74ea0c3697bf99fae5bb69ae7b29159 Mon Sep 17 00:00:00 2001 From: Chance Date: Wed, 18 Sep 2019 13:10:30 -0500 Subject: [PATCH 3/4] Remove import from tests for nonexistent module --- tests/test_phypy.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/test_phypy.py b/tests/test_phypy.py index ddab4ac..8cd6db3 100644 --- a/tests/test_phypy.py +++ b/tests/test_phypy.py @@ -8,7 +8,6 @@ from click.testing import CliRunner -from phypy import phypy from phypy import cli from phypy import analog from phypy import modulators as mods From 1eeb46db05ce7734f77796cf0a3d99ccca21ca04 Mon Sep 17 00:00:00 2001 From: Chance Date: Thu, 26 Sep 2019 09:37:44 -0500 Subject: [PATCH 4/4] Working on a MIMO simulator --- phypy/mimo/__init__.py | 6 +++ phypy/mimo/channels.py | 0 phypy/mimo/mimo.py | 95 +++++++++++++++++++++++++++++++++++++++++ phypy/mimo/precoders.py | 0 requirements.txt | 4 +- 5 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 phypy/mimo/__init__.py create mode 100644 phypy/mimo/channels.py create mode 100644 phypy/mimo/mimo.py create mode 100644 phypy/mimo/precoders.py diff --git a/phypy/mimo/__init__.py b/phypy/mimo/__init__.py new file mode 100644 index 0000000..5cad29c --- /dev/null +++ b/phypy/mimo/__init__.py @@ -0,0 +1,6 @@ +# -*- coding: utf-8 -*- + +"""MIMO Module for PhyPy""" + +__author__ = """Chance Tarver""" +__email__ = 'tarver.chance@gmail.com' diff --git a/phypy/mimo/channels.py b/phypy/mimo/channels.py new file mode 100644 index 0000000..e69de29 diff --git a/phypy/mimo/mimo.py b/phypy/mimo/mimo.py new file mode 100644 index 0000000..a99d47d --- /dev/null +++ b/phypy/mimo/mimo.py @@ -0,0 +1,95 @@ +import numpy as np +import simpy + + +class MimoTransmitter: + """ Class that represents an entire MIMO Transmitter Array. Includes channel and precoder.""" + + def __init__(self, + n_antennas: int = 64, + n_users: int = 4, + precoder: str = 'zero_forcing', + update_precoder_frequency: int = 7): + self.n_antennas = n_antennas + self.n_users = n_users + self.channel_matrix = None # Will store the channel matrix when we get it. + self.precoder = ZeroForcing(self.channel_matrix, update_precoder_frequency) + + def update_channel(self, channel): + """ The channel object exists in its own object. Periodically, our transmitter will get new CSI/channel. + This method updates the classes copy of the channel""" + + def transmit(self, symbols): + pass + + +class LinearPrecoder: + def __init__(self): + pass + + def precode(self, symbols): + out = np.dot(self.precoding_matrix, symbols) + return out + + def precode_update_process(self, env): + env.timeout( + 0.001 + ) # Small delay so that we always update based on a new channel + while True: + print(f'Current Symbol = {env.now}. Updating precoder') + self.create_precoder_matrix(self.precoding_matrix) + yield env.timeout(self.update_rate) + + +class ZeroForcing(LinearPrecoder): + def __init__(self, channel_matrix, update_rate): + self.precoding_matrix = None # Will be set by create_precoder_matrix method + self.create_precoder_matrix(channel_matrix) + self.update_rate = update_rate + + def create_precoder_matrix(self, channel_matrix): + self.precoding_matrix = channel_matrix + + +class MIMO_Channel: + def channel_update_process(self, env): + while True: + print(f'Current Symbol = {env.now}. Updating channel') + self.update_channel() + yield env.timeout(self.update_rate) + + +class MimoAwgn(MIMO_Channel): + def __init__(self, n_users: int = 8, n_antennas: int = 64, n_subcarriers=1200, update_rate: int = 7): + self.n_users = n_users + self.n_antennas = n_antennas + self.n_subcarriers = n_subcarriers + self.update_rate = update_rate + self.matrix = 1 + + def update_channel(self): + new_channel = 0.9*old_channel + guassian + pass + + +if __name__ == "__main__": + env = simpy.Environment() + update_channel_frequency = 1 # Every 2 symbols, make new MIMO channel + update_precoder_frequency = 7 + n_users = 4 + n_antennas = 64 + n_subcarriers = 1200 + n_symbols = 64 + + channel = MimoAwgn(n_users=n_users, n_antennas=n_antennas, n_subcarriers=n_subcarriers) + tx = MimoTransmitter(n_users=n_users, n_antennas=n_antennas, + update_precoder_frequency=update_precoder_frequency) + env.process(channel.channel_update_process(env)) + env.process(tx.precoder.precode_update_process(env)) + env.run(until=n_symbols) + + print(tx.n_antennas) + print(tx.n_users) + print(tx.precoder) + + diff --git a/phypy/mimo/precoders.py b/phypy/mimo/precoders.py new file mode 100644 index 0000000..e69de29 diff --git a/requirements.txt b/requirements.txt index 283f5d5..19b9d6f 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,4 +9,6 @@ Sphinx==1.8.5 twine==1.14.0 Click==7.0 pytest==4.6.5 -pytest-runner==5.1 \ No newline at end of file +pytest-runner==5.1 +numpy +simpy