Miscellaneous improvements to filter design functionality

- Perform prototype transformations directly on ZPKFilters. This avoids converting from ZPKFilter->TFFilter->ZPKFilter and the corresponding numerical error from root finding.
- Remove zeros and poles that exactly cancel when constructing ZPKFilters.
- Allow filter specifications to accept an optional `fs` keyword arg.
- More error checking when designing filters.
- Improve filter design documentation and add examples.
- Reorganize and improve tests.