{ "info": { "author": "Nico Schl\u00f6mer", "author_email": "nico.schloemer@gmail.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 3 - Alpha", "Intended Audience :: Science/Research", "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python", "Programming Language :: Python :: 3", "Topic :: Scientific/Engineering" ], "description": "

\n \"smoothfit\"\n

\n\n[![CircleCI](https://img.shields.io/circleci/project/github/nschloe/smoothfit/master.svg?style=flat-square)](https://circleci.com/gh/nschloe/smoothfit)\n[![codecov](https://img.shields.io/codecov/c/github/nschloe/smoothfit.svg?style=flat-square)](https://codecov.io/gh/nschloe/smoothfit)\n[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg?style=flat-square)](https://github.com/psf/black)\n[![smooth](https://img.shields.io/badge/smooth-yes-8209ba.svg?style=flat-square)](https://github.com/nschloe/smoothfit)\n[![PyPi Version](https://img.shields.io/pypi/v/smoothfit.svg?style=flat-square)](https://pypi.org/project/smoothfit)\n[![GitHub stars](https://img.shields.io/github/stars/nschloe/smoothfit.svg?style=flat-square&logo=github&label=Stars&logoColor=white)](https://github.com/nschloe/smoothfit)\n[![PyPi downloads](https://img.shields.io/pypi/dm/smoothfit.svg?style=flat-square)](https://pypistats.org/packages/smoothfit)\n\nGiven experimental data, it is often desirable to produce a function whose values match\nthe data to some degree. This package implements a robust approach to data fitting based\non the minimization problem\n\n\n\n(A similar idea is used in for data smoothing in signal processing; see, e.g.,\nsection 8.3 in [this\ndocument](http://eeweb.poly.edu/iselesni/lecture_notes/least_squares/least_squares_SP.pdf).)\n\nUnlike [polynomial\nregression](https://en.wikipedia.org/wiki/Polynomial_regression) or\n[Gauss-Newton](https://en.wikipedia.org/wiki/Gauss%E2%80%93Newton_algorithm),\nsmoothfit makes no assumptions about the function other than that it is smooth.\n\nThe generality of the approach makes it suitable for function whose domain is\nmultidimensional, too.\n\n### Pics or it didn't happen\n\n#### Runge's example\n\n\n\n```python\nimport matplotlib.pyplot as plt\nimport numpy\nimport smoothfit\n\na = -1.5\nb = +1.5\n\n# plot original function\nx = numpy.linspace(a, b, 201)\nplt.plot(x, 1 / (1 + 25 * x ** 2), \"-\", color=\"0.8\", label=\"1 / (1 + 25 * x**2)\")\n\n# 21 sample points\nx0 = numpy.linspace(-1.0, 1.0, 21)\ny0 = 1 / (1 + 25 * x0 ** 2)\nplt.plot(x0, y0, \"xk\")\n\nu = smoothfit.fit1d(x0, y0, a, b, 1000, degree=1, lmbda=1.0e-6)\nx = numpy.linspace(a, b, 201)\nvals = [u(xx) for xx in x]\nplt.plot(x, vals, \"-\", label=\"smooth fit\")\n\nplt.ylim(-0.1)\nplt.grid()\nplt.show()\n```\n\n[Runge's example function](https://en.wikipedia.org/wiki/Runge%27s_phenomenon) is a\ntough nut for classical polynomial regression.\n\nIf there is no noise in the input data, the parameter `lmbda` can be chosen quite small\nsuch that all data points are approximated well. Note that there are no oscillations\nin the output function `u`.\n\n\n#### Runge's example with noise\n\n |\n |\n\n:-------------------:|:------------------:|:----------:|\n`lmbda = 0.001` | `lmbda = 0.05` | `lmbda = 0.2` |\n\n```python\nimport matplotlib.pyplot as plt\nimport numpy\nimport smoothfit\n\na = -1.5\nb = +1.5\n\n# plot original function\nx = numpy.linspace(a, b, 201)\nplt.plot(x, 1 / (1 + 25 * x ** 2), \"-\", color=\"0.8\", label=\"1 / (1 + 25 * x**2)\")\n\n# 21 sample points\nnumpy.random.seed(0)\nn = 51\nx0 = numpy.linspace(-1.0, 1.0, n)\ny0 = 1 / (1 + 25 * x0 ** 2)\ny0 += 1.0e-1 * (2 * numpy.random.rand(n) - 1)\nplt.plot(x0, y0, \"xk\")\n\nlmbda = 5.0e-2\nu = smoothfit.fit1d(x0, y0, a, b, 1000, degree=1, lmbda=lmbda)\nx = numpy.linspace(a, b, 201)\nvals = [u(xx) for xx in x]\nplt.plot(x, vals, \"-\", label=\"smooth fit\")\n\nplt.grid()\nplt.show()\n```\n\nIf the data is noisy, `lmbda` needs to be chosen more carefully. If too small, the\napproximation tries to resolve _all_ data points, resulting in many small oscillations.\nIf it's chosen too large, no details are resolved, not even those of the underlying\ndata.\n\n\n#### Few samples\n\n\n\n```python\nimport numpy\nimport smoothfit\n\nx0 = numpy.array([0.038, 0.194, 0.425, 0.626, 1.253, 2.500, 3.740])\ny0 = numpy.array([0.050, 0.127, 0.094, 0.2122, 0.2729, 0.2665, 0.3317])\nu = smoothfit.fit1d(x0, y0, 0, 4, 1000, degree=1, lmbda=1.0)\n```\nSome noisy example data taken from\n[Wikipedia](https://en.wikipedia.org/wiki/Gauss%E2%80%93Newton_algorithm#Example).\n\n\n#### A two-dimensional example\n\n\n\n```python\nimport meshzoo\nimport numpy\nimport smoothfit \n\nn = 200\nnumpy.random.seed(123)\nx0 = numpy.random.rand(n, 2) - 0.5\ny0 = numpy.cos(numpy.pi * numpy.sqrt(x0.T[0] ** 2 + x0.T[1] ** 2))\n\n# create a triangle mesh for the square\npoints, cells = meshzoo.rectangle(-1.0, 1.0, -1.0, 1.0, 32, 32)\n\nu = smoothfit.fit2d(x0, y0, points, cells, lmbda=1.0e-4, solver=\"dense-direct\")\n\n# Write the function to a file\nfrom dolfin import XDMFFile\nxdmf = XDMFFile(\"temp.xdmf\")\nxdmf.write(u)\n```\n\nThis example approximates a function from _R2_ to _R_ (without noise in the\nsamples). Note that the absence of noise the data allows us to pick a rather small\n`lmbda` such that all sample points are approximated well.\n\n\n### Comparison with other approaches\n\n#### Polynomial fitting/regression\n\n\n\nThe classical approach to data fitting is [polynomial\nregression](https://en.wikipedia.org/wiki/Polynomial_regression). Polynomials are\nchosen because they are very simple, can be evaluated quickly, and [can be made to fit\nany function very closely](https://en.wikipedia.org/wiki/Stone\u2013Weierstrass_theorem).\n\nThere are, however, some fundamental problems:\n\n * Your data might not actually fit a polynomial of low degree.\n * [Runge's phenomenon](//en.wikipedia.org/wiki/Runge%27s_phenomenon).\n\nThis above plot highlights the problem with oscillations.\n\n\n#### Fourier smoothing\n\n\n\nOne approach to data fitting with smoothing is to create a function with all data\npoints, and simply cut off the high frequencies after Fourier transformation.\n\nThis approach is fast, but only works for evenly spaced samples.\n\n```python\nimport matplotlib.pyplot as plt\nimport numpy\n\n\nnumpy.random.seed(0)\n\n# original function\nx0 = numpy.linspace(-1.0, 1.0, 1000)\ny0 = 1 / (1 + 25 * x0 ** 2)\nplt.plot(x0, y0, color=\"k\", alpha=0.2)\n\n# create sample points\nn = 51\nx1 = numpy.linspace(-1.0, 1.0, n) # only works if samples are evenly spaced\ny1 = 1 / (1 + 25 * x1 ** 2) + 1.0e-1 * (2 * numpy.random.rand(x1.shape[0]) - 1)\nplt.plot(x1, y1, \"xk\")\n\n# Cut off the high frequencies in the transformed space and transform back\nX = numpy.fft.rfft(y1)\nX[5:] = 0.0\ny2 = numpy.fft.irfft(X, n)\n#\nplt.plot(x1, y2, \"-\", label=\"5 lowest frequencies\")\n\nplt.grid()\nplt.show()\n```\n\n### Testing\n\nTo run the smoothfit unit tests, check out this repository and type\n```\npytest\n```\n\n### License\n\nsmoothfit is published under the [MIT license](https://en.wikipedia.org/wiki/MIT_License).\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/nschloe/smoothfit", "keywords": "", "license": "License :: OSI Approved :: MIT License", "maintainer": "", "maintainer_email": "", "name": "smoothfit", "package_url": "https://pypi.org/project/smoothfit/", "platform": "any", "project_url": "https://pypi.org/project/smoothfit/", "project_urls": { "Homepage": "https://github.com/nschloe/smoothfit" }, "release_url": "https://pypi.org/project/smoothfit/0.1.1/", "requires_dist": [ "numpy", "pykry", "scipy" ], "requires_python": ">=3", "summary": "Smooth data fitting", "version": "0.1.1" }, "last_serial": 5681379, "releases": { "0.1.0": [ { "comment_text": "", "digests": { "md5": "12af743eb84150c5ddf01413f74b961c", "sha256": "8a4754262d3a3e2d6140189b9c4647cd55c6d38c287ae9d570f86162c8b514c5" }, "downloads": -1, "filename": "smoothfit-0.1.0-py3-none-any.whl", "has_sig": false, "md5_digest": "12af743eb84150c5ddf01413f74b961c", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3", "size": 7555, "upload_time": "2019-08-14T22:51:01", "url": "https://files.pythonhosted.org/packages/f1/d8/ae65f0caac5e8da92d93d75c5e92580848c6c11dfc84d39d572c51f98cbc/smoothfit-0.1.0-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "7662291049d383573ad33169f932b59c", "sha256": "bc5d73a9fc1ea8a70ea7b77372968924f6025df5e503dbb43675d386bb17bab7" }, "downloads": -1, "filename": "smoothfit-0.1.0.tar.gz", "has_sig": false, "md5_digest": "7662291049d383573ad33169f932b59c", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3", "size": 7968, "upload_time": "2019-08-14T22:51:04", "url": "https://files.pythonhosted.org/packages/30/a3/ef3e2415ba0d9e464f174a561df185f688821e33e8fbd9d83a6d023561d9/smoothfit-0.1.0.tar.gz" } ], "0.1.1": [ { "comment_text": "", "digests": { "md5": "e170fea6936d50322cb562e6b68788cd", "sha256": "20ff7af470d0df56abad2e0666ad5515519c8d2a6789ae537aae856d026c88b4" }, "downloads": -1, "filename": "smoothfit-0.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "e170fea6936d50322cb562e6b68788cd", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3", "size": 7548, "upload_time": "2019-08-15T09:41:07", "url": "https://files.pythonhosted.org/packages/5b/e1/7e6a24ff731137380d33a60f9b04ab3201d0778b0886b2270a6a2986e0c6/smoothfit-0.1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "65c01524b7274425bbad1ace840c3398", "sha256": "b50724f120741f211343f0f81c10095ce65ffbf3a51cd2f8bd1cc2325baff6c5" }, "downloads": -1, "filename": "smoothfit-0.1.1.tar.gz", "has_sig": false, "md5_digest": "65c01524b7274425bbad1ace840c3398", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3", "size": 8060, "upload_time": "2019-08-15T09:41:09", "url": "https://files.pythonhosted.org/packages/60/b3/045bb142299f7ada3f5097a018f6eebec393da0e0ef0be744a108c910924/smoothfit-0.1.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "e170fea6936d50322cb562e6b68788cd", "sha256": "20ff7af470d0df56abad2e0666ad5515519c8d2a6789ae537aae856d026c88b4" }, "downloads": -1, "filename": "smoothfit-0.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "e170fea6936d50322cb562e6b68788cd", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3", "size": 7548, "upload_time": "2019-08-15T09:41:07", "url": "https://files.pythonhosted.org/packages/5b/e1/7e6a24ff731137380d33a60f9b04ab3201d0778b0886b2270a6a2986e0c6/smoothfit-0.1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "65c01524b7274425bbad1ace840c3398", "sha256": "b50724f120741f211343f0f81c10095ce65ffbf3a51cd2f8bd1cc2325baff6c5" }, "downloads": -1, "filename": "smoothfit-0.1.1.tar.gz", "has_sig": false, "md5_digest": "65c01524b7274425bbad1ace840c3398", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3", "size": 8060, "upload_time": "2019-08-15T09:41:09", "url": "https://files.pythonhosted.org/packages/60/b3/045bb142299f7ada3f5097a018f6eebec393da0e0ef0be744a108c910924/smoothfit-0.1.1.tar.gz" } ] }