Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Piecewise process #1100

Merged
merged 1 commit into from
Sep 21, 2017
Merged

Add Piecewise process #1100

merged 1 commit into from
Sep 21, 2017

Conversation

hunse
Copy link
Collaborator

@hunse hunse commented Jun 17, 2016

Description:
Turns the piecewise function into a Process. This adds all the normal amenities, such as running the process for a length of time outside a Nengo simulator.

Motivation and context:

Addresses issue #1036. It should make this easier to use.

I'm also adding interpolation, so that we can do e.g. linear interpolation rather than just the current zero-order hold behaviour.

If we really want to go the whole nine yards, we could actually allow this to take other Processes in addition to callables and constants, so that we can e.g. run one process for 5 seconds, then another for the next 3 seconds, etc.

How has this been tested?

Still TODO. I'm planning on pulling over all the tests from the old piecewise function, so we maintain all that behaviour.

Where should a reviewer start?

Look at the new process first, and read the documentation (still TODO).

How long should this take to review?

still unknown

  • Quick (less than 40 lines changed or changes are straightforward)
  • Average (neither quick nor lengthy)
  • Lengthy (more than 150 lines changed or changes are complicated)

Types of changes:

  • Breaking change (fix or feature that causes existing functionality to change)

Checklist:

  • I have read the CONTRIBUTING.rst document.
  • I have updated the documentation accordingly.
  • I have included a changelog entry.
  • I have added tests to cover my changes.
  • All new and existing tests passed.

Still to do:

  • Support callables as outputs
  • Support Processes as outputs if we want to do that (would it be useful?)
  • Update old tests so they work with the new Process
  • Test interpolation
  • Update examples that use old piecewise
  • Remove old piecewise function and tests, or perhaps just add a deprecation warning.

@mention-bot
Copy link

By analyzing the blame information on this pull request, we identified @tbekolay to be a potential reviewer

@AllenHW
Copy link
Contributor

AllenHW commented Sep 8, 2017

After discussing with @hunse, we decided to support callable in another PR. To do it we would require another parameter type that lets user pass an array of callable AND floats/list of floats

@nengo nengo deleted a comment from codecov-io Sep 9, 2017
Copy link
Member

@tbekolay tbekolay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall this is looking great, thanks @AllenHW!

I've made some inline comments here for you to address. Normally in a review we would make commits for the changes, but because this is your first PR I thought it would be better to provide more justifications for the changes requested and to have you make them. Later on (after a few accepted PRs), I'll make the changes myself, as it tends to lower the amount of back-and-forth needed for each PR.

Additionally, this PR is currently failing unit tests; check out the TravisCI build for details, but also it's helpful to run the tests locally because pushing and waiting for TravisCI is almost always slower than running the tests locally.

CHANGES.rst Outdated
**Changed**

- piecewise() function is now a process. Support for interpolation of
points was also added
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

restructedText is pretty strict about some things, one of which being that this second line must be indented to the same level as "piecewise" above. So this line needs some whitespace at the beginning.

Also, we always (manually) add a link to the pull request at the end of the changelog entry; see the other entries in this file for examples.

class Piecewise(Process):
"""Present a piecewise input with different options for interpolation.

Given an input of tp = [0, 0.5, 0.75, 1], yp = [[0], [1], [-1], [0]] this will generate a
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With very few exceptions, we stick to a strict line-length limit of 79 characters, as espoused by PEP8 and enforced by flake8. If possible, it would be great to configure your text editor or IDE to run the flake8 checks on Python files as you're editing them! Most editors can be configured to do this if you google around a bit.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, any text that corresponds to code we usually render in a monospaced font, which is done in docstrings and other restructedText snippets with two backticks before and after the code. I would probably do that for tp and yp here.

Elements in tp must be times (floats or ints). The values in yp can be floats for
1d or lists for multi-dimensional function. All lists must be of the same length.

Interpolations on the data points using scipy.interpolation are also supported. The default
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Interpolations" -> "Interpolation"
"are" -> "is"


Interpolations on the data points using scipy.interpolation are also supported. The default
interpolation is 'zero', which simply creates a piecewise function whose values begin
at the specified time points. So the above example would be shortcut for:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To render the below snippet as a source code snippet properly, you have to change the colon at the end of this line do a double colon (... would be a shortcut for::) and add a newline separating this paragraph from the code snippet.

For times before the first specified time, it will default to zero (of
the correct length). This means that the above can be simplified to:

Piecewise([0.5, 0.75, 1], yp = [[1], [-1], [0]])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When passing arguments to a function or class, PEP8 tells us not put spaces around the =.

Additionally, this doesn't seem to match with the current __init__ for this class, which accepts a data dictionary; the tp and yp are extracted from the data dictionary. Was your intention to change what gets passed to Piecewise?

import scipy.interpolate
self.sp_interpolate = scipy.interpolate
except ImportError:
raise ValidationError(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block is overindented by 4 spaces; it should line up with the try block above.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I think this should raise an ImportError rather than a ValidationError.

I am also wondering if, rather than raising an error, we should instead raise a warning and set interpolate to 'zero' instead of crashing. What do you think?


class TestPiecewise(object):

dt = 0.001
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless there's some reason to change the dt in a specific test, it's probably best not to specify it, as specifying it indicates to the reader that we're going to be using a non-standard dt in some tests (which I don't believe we are here).

process = nengo.processes.Piecewise(data, 'cubic')
assert process

def test_interpolation(self, Simulator):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At the moment, this test requires scipy, which is not a required dependency of Nengo. In order to not fail unit tests when scipy is not installed, please use pytest.importorskip (see test_dists.py for an example).

def piecewise(data):
warnings.warn("piecewise() function is deprecated. Use Piecewise process instead.",
DeprecationWarning)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is overindented, according to PEP8. It should line up with the p in piecewise.

@@ -4,6 +4,10 @@
from nengo.exceptions import ValidationError
from nengo.utils.functions import piecewise

"""
note:: piecewise() function is deprecated. Use Piecewise process instead.
"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This note isn't necessary, as it's very unlikely anyone will be touching this test file. We raise the deprecation warning in utils/functions.py already, which is something that will be seen when running these tests anyhow.

@AllenHW AllenHW mentioned this pull request Sep 11, 2017
5 tasks
@tbekolay tbekolay changed the title WIP: Add Piecewise process Add Piecewise process Sep 15, 2017
Copy link
Member

@tbekolay tbekolay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fixes @AllenHW! There were a few lingering issues, but since there weren't many I went ahead and made the changes in commits which I've pushed here. Please look them over @AllenHW and make sure they look good to you.

@hunse
Copy link
Collaborator Author

hunse commented Sep 15, 2017

I looked it over, and it all looks great to me! Thanks @AllenHW!

I added a little fixup to use interpolation as a keyword argument only, just because I'm nit-picky like that sometimes.

Copy link
Member

@drasmuss drasmuss left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pushed a small fixup commit. Mainly minor documentation/typo fixes. The only substantive changes are

  1. I removed a validation check that wasn't necessary (no way for that validation to fail)
  2. I added a check that all the Piecewise values have the same length (previously this would just fail when
    you tried to create an ndarray with mismatched values, which wasn't very informative)

If those changes look good then this looks good to me.

raise ValidationError(
"`tp.shape[0]` (%d) must equal `yp.shape[0]` (%d)"
% (self.tp.shape[0], self.yp.shape[0]),
attr='yp', obj=self)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no way this ValidationError could ever trigger (since a dictionary always has the same number of keys and values).

@tbekolay
Copy link
Member

Those changes look good to me @drasmuss! Can you approve this so I can merge it in?

And deprecate the old piecewise function.

Also updated all tests and examples to use the new process.

Currently we do not yet deal with callables. There are no examples
that use callables, but regardless we should implement that
functionality and test it.

Fixes #1036.

Co-authored by: Allen Wang <allen.houze.wang@gmail.com>
@tbekolay tbekolay merged commit 736a92a into master Sep 21, 2017
@tbekolay tbekolay deleted the piecewise-process branch September 21, 2017 19:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

None yet

5 participants