# PyCftool
Heavily inspired by matlabs interactive curvefitter (Cftool), this program attempts to copy its fantastic features for use in python.
<p align="center">
<img src="https://user-images.githubusercontent.com/126679979/224439240-eed3dccd-48ca-4e11-8626-7d01737bfc71.png" width="850">
</p>
## Features
#### Easy access to data via dropdown menu
Using the argument `local_vars` you can pass multiple arrays to the GUI. From two dropdown menus (**X Data** and **Y Data**) you can choose to select, which x and y data the program should fit to.
#### Automatic fitting
Everytime the program detects a change in any option, it will automatically fit a new line using these new options. This can be disabled by unchecking **Auto Fit** in the top right corner. By doing so, a fit will only be computed once the **Fit** button, located under **Auto Fit**, is pressed.
#### Multiple equation support
From a dropdown menu it's possible to use a wide variety of predefined functions. So far these include
| Name | Equation |
| ------------- | ------------- |
| Polynomial of N degree | $$y= \sum_{k=0}^N a_kx^{(N-k)}$$ |
| Exponential | $$y= be^{ax}$$ |
| Resonance 1 | $$y=\frac{ax}{\sqrt{(x^2-b)^2+cx^2}}$$ |
| Resonance 2 | $$y=\frac{a}{\sqrt{(x^2-b)^2+cx^2}}$$ |
| Custom Equation | Text input |
#### Custom Equation support
Choosing **Custom Equation** from the dropdown menu, it's possible to fit to any equation you desire!
#### Interpolation
The fit will by default contain as many datapoints as the input data. When using a small amount of datapoints or fitting "pointy" functions, checking the **Interpolation** box will give the fit line a smoother appearence. Note that this ONLY influences how the fit appear on the graph and not any of the actual fit parameters.
#### Display Window
The left hand side contains a window that displays the current fit model, best fit parameters and GOF analysis.<br>
The best fit parameters come with a one $\sigma$ (68%) confidence interval. The program calculates the **SSE, R-Squard, Adjusted R-Squared, RMSE**, and
if weights have been given, the $\chi$**-squared** of the model.<br>
#### Export to .py file
Under **"File"** you can choose to **"Export"**, which will create a .py file. This file will contain code, that generates the fit parameters that are used in plotting the graph.
#### Robust
The dropdown menu **Robust** gives access to different fitting algorithms. Default is the [Levenberg–Marquardt algorithm](https://en.wikipedia.org/wiki/Levenberg%E2%80%93Marquardt_algorithm) (least squares). For bounded problems, the algorithm is automatically set to **TRF**. For more information on the different fitting algorithms check the [scipy.optimize.curve_fit](https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.curve_fit.html) documentation.
#### Fit Options
Fit options opens a window in which it's possible to adjust the initial variable guess as well as their boundaries.
<p align="center">
<img src="https://user-images.githubusercontent.com/126679979/224429671-37055759-0699-423b-ac3a-c03bb2786744.png">
</p>
#### To be implemented
- Residual options
- Save
- Multiple plots
- 3D curve fit
## Prerequisite
Is currently supported for Python >=3.7.<br>
Requires the following packages to be installed: [PySide6](https://pypi.org/project/PySide6), Matplotlib, Scipy and Numpy.
## Installation
You can install pyCftool with: `pip install pyCftool`.
## Usage
Import the function `from pyCftool import cftool`
### pyCftool
#### cftool(x=None ,y=None ,weights=None ,local_vars={})
Opens an interactive fitting program.<br>
**Parameters: x : one-dimensional numpy array of length N, optional**<br>
The x component of the data that will immediately be displayed and fitted for once the GUI opens. <br><br>
**y : one-dimensional numpy array of length N, optional**<br>
The y component of the data that will immediately be displayed and fitted for once the GUI opens. <br><br>
**weights : float or one-dimensional numpy arrayof length N, optional**<br>
The weights of each datapoint. Defined as being $w=1/\sigma$, where $\sigma$ is the uncertainty of the datapoints.<br><br>
**local_vars : dictionary, optional**<br>
A dictionary can be passed, but only values that are of type `np.ndarray` will be accessable by the GUI. A dropdown menu in the GUI allows the user to freely choose between the arrays contained in the dictionary. Passing the built-in function `locals()` will give the GUI access to all previously defined numpy arrays.<br><br>
## Examples
### Polynomial fit
```Python
import numpy as np
from pyCftool import cftool
x = np.linspace(-5,5,100)+np.random.normal(0,scale=0.01,size=100)
noise = np.random.normal(0,scale=0.1,size=100)
y = 6.6*x**2-3*x+0.3+noise # Polynomial
lv = locals().copy()
cftool(x,y,local_vars=lv)
```
Will produce a window like this:
<p align="center">
<img src="https://user-images.githubusercontent.com/126679979/224442985-5fab6f97-f30e-434c-a589-4333bb88d86b.png" width="750">
</p>
The 'best-fit' parameters are listed in the window on the right hand side. The bounds are within one σ (68%) standard deviation. Since this is a second order polynomial, we can select Degree = 2 from the dropdown menu. The fitter will automatically fit unless **"Auto Fit"** has been unchecked. The resultning image will become
<p align="center">
<img src="https://user-images.githubusercontent.com/126679979/224443057-5b3694d3-3b18-4388-8119-e2d7481b9e04.png" width="750">
</p>
### Custom Fit
We can also make the program fit any function we desire.
```Python
import numpy as np
from pyCftool import cftool
x = np.linspace(-5,5,100)+np.random.normal(0,scale=0.01,size=100)
noise = np.random.normal(0,scale=0.1,size=100)
y = 2*x+0.2+2.2*np.sin(1.1*x)+noise # Linear with sinus wave
lv = locals().copy()
cftool(x,y,local_vars=lv)
```
By selecting `Custom Equation` from the dropdown menu at the top, we can input our own equations. In this case we want to use the formula $y=ax+b+A\sin(\omega x)$.
<p align="center">
<img src="https://user-images.githubusercontent.com/126679979/224443276-b7090965-3f31-4869-9dba-ec738aa47ac0.png" width="800">
</p>
Raw data
{
"_id": null,
"home_page": "",
"name": "pyCftool",
"maintainer": "",
"docs_url": null,
"requires_python": "",
"maintainer_email": "",
"keywords": "python,fit,statistics,modelling,science",
"author": "Andreas Forum (TehForum)",
"author_email": "<andforum@hotmail.com>",
"download_url": "https://files.pythonhosted.org/packages/cf/7e/633a8d73ea18d517e7db196b1690f83a7a052dbb78cdc6c5cc43d9f8136d/pyCftool-1.0.0.tar.gz",
"platform": null,
"description": "# PyCftool\r\nHeavily inspired by matlabs interactive curvefitter (Cftool), this program attempts to copy its fantastic features for use in python.\r\n<p align=\"center\">\r\n <img src=\"https://user-images.githubusercontent.com/126679979/224439240-eed3dccd-48ca-4e11-8626-7d01737bfc71.png\" width=\"850\">\r\n</p>\r\n\r\n\r\n\r\n## Features\r\n\r\n#### Easy access to data via dropdown menu\r\nUsing the argument `local_vars` you can pass multiple arrays to the GUI. From two dropdown menus (**X Data** and **Y Data**) you can choose to select, which x and y data the program should fit to.\r\n\r\n#### Automatic fitting\r\nEverytime the program detects a change in any option, it will automatically fit a new line using these new options. This can be disabled by unchecking **Auto Fit** in the top right corner. By doing so, a fit will only be computed once the **Fit** button, located under **Auto Fit**, is pressed.\r\n\r\n#### Multiple equation support\r\nFrom a dropdown menu it's possible to use a wide variety of predefined functions. So far these include\r\n| Name | Equation |\r\n| ------------- | ------------- |\r\n| Polynomial of N degree | $$y= \\sum_{k=0}^N a_kx^{(N-k)}$$ |\r\n| Exponential | $$y= be^{ax}$$ |\r\n| Resonance 1 | $$y=\\frac{ax}{\\sqrt{(x^2-b)^2+cx^2}}$$ |\r\n| Resonance 2 | $$y=\\frac{a}{\\sqrt{(x^2-b)^2+cx^2}}$$ |\r\n| Custom Equation | Text input |\r\n\r\n#### Custom Equation support\r\nChoosing **Custom Equation** from the dropdown menu, it's possible to fit to any equation you desire! \r\n\r\n#### Interpolation\r\nThe fit will by default contain as many datapoints as the input data. When using a small amount of datapoints or fitting \"pointy\" functions, checking the **Interpolation** box will give the fit line a smoother appearence. Note that this ONLY influences how the fit appear on the graph and not any of the actual fit parameters.\r\n\r\n#### Display Window\r\nThe left hand side contains a window that displays the current fit model, best fit parameters and GOF analysis.<br>\r\nThe best fit parameters come with a one $\\sigma$ (68%) confidence interval. The program calculates the **SSE, R-Squard, Adjusted R-Squared, RMSE**, and \r\nif weights have been given, the $\\chi$**-squared** of the model.<br>\r\n\r\n#### Export to .py file\r\nUnder **\"File\"** you can choose to **\"Export\"**, which will create a .py file. This file will contain code, that generates the fit parameters that are used in plotting the graph.\r\n\r\n\r\n#### Robust\r\nThe dropdown menu **Robust** gives access to different fitting algorithms. Default is the [Levenberg\u00e2\u20ac\u201cMarquardt algorithm](https://en.wikipedia.org/wiki/Levenberg%E2%80%93Marquardt_algorithm) (least squares). For bounded problems, the algorithm is automatically set to **TRF**. For more information on the different fitting algorithms check the [scipy.optimize.curve_fit](https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.curve_fit.html) documentation.\r\n\r\n\r\n#### Fit Options\r\nFit options opens a window in which it's possible to adjust the initial variable guess as well as their boundaries.\r\n<p align=\"center\">\r\n <img src=\"https://user-images.githubusercontent.com/126679979/224429671-37055759-0699-423b-ac3a-c03bb2786744.png\">\r\n</p>\r\n\r\n\r\n\r\n\r\n#### To be implemented\r\n\r\n- Residual options\r\n- Save\r\n- Multiple plots\r\n- 3D curve fit\r\n## Prerequisite\r\nIs currently supported for Python >=3.7.<br>\r\nRequires the following packages to be installed: [PySide6](https://pypi.org/project/PySide6), Matplotlib, Scipy and Numpy.\r\n\r\n## Installation\r\nYou can install pyCftool with: `pip install pyCftool`.\r\n\r\n## Usage\r\nImport the function `from pyCftool import cftool`\r\n\r\n### pyCftool\r\n#### cftool(x=None ,y=None ,weights=None ,local_vars={})\r\n Opens an interactive fitting program.<br>\r\n\r\n **Parameters: x : one-dimensional numpy array of length N, optional**<br>\r\n The x component of the data that will immediately be displayed and fitted for once the GUI opens. <br><br>\r\n **y : one-dimensional numpy array of length N, optional**<br>\r\n The y component of the data that will immediately be displayed and fitted for once the GUI opens. <br><br>\r\n **weights : float or one-dimensional numpy arrayof length N, optional**<br>\r\n The weights of each datapoint. Defined as being $w=1/\\sigma$, where $\\sigma$ is the uncertainty of the datapoints.<br><br>\r\n **local_vars : dictionary, optional**<br>\r\n A dictionary can be passed, but only values that are of type `np.ndarray` will be accessable by the GUI. A dropdown menu in the GUI allows the user to freely choose between the arrays contained in the dictionary. Passing the built-in function `locals()` will give the GUI access to all previously defined numpy arrays.<br><br>\r\n\r\n## Examples\r\n### Polynomial fit\r\n```Python\r\nimport numpy as np\r\nfrom pyCftool import cftool\r\n\r\nx = np.linspace(-5,5,100)+np.random.normal(0,scale=0.01,size=100)\r\nnoise = np.random.normal(0,scale=0.1,size=100)\r\ny = 6.6*x**2-3*x+0.3+noise # Polynomial\r\nlv = locals().copy()\r\ncftool(x,y,local_vars=lv)\r\n```\r\nWill produce a window like this:\r\n<p align=\"center\">\r\n <img src=\"https://user-images.githubusercontent.com/126679979/224442985-5fab6f97-f30e-434c-a589-4333bb88d86b.png\" width=\"750\">\r\n</p>\r\n\r\nThe 'best-fit' parameters are listed in the window on the right hand side. The bounds are within one \u00cf\u0192 (68%) standard deviation. Since this is a second order polynomial, we can select Degree = 2 from the dropdown menu. The fitter will automatically fit unless **\"Auto Fit\"** has been unchecked. The resultning image will become\r\n<p align=\"center\">\r\n <img src=\"https://user-images.githubusercontent.com/126679979/224443057-5b3694d3-3b18-4388-8119-e2d7481b9e04.png\" width=\"750\">\r\n</p>\r\n\r\n### Custom Fit\r\nWe can also make the program fit any function we desire.\r\n\r\n```Python\r\nimport numpy as np\r\nfrom pyCftool import cftool\r\n\r\nx = np.linspace(-5,5,100)+np.random.normal(0,scale=0.01,size=100)\r\nnoise = np.random.normal(0,scale=0.1,size=100)\r\ny = 2*x+0.2+2.2*np.sin(1.1*x)+noise # Linear with sinus wave\r\nlv = locals().copy()\r\ncftool(x,y,local_vars=lv)\r\n```\r\nBy selecting `Custom Equation` from the dropdown menu at the top, we can input our own equations. In this case we want to use the formula $y=ax+b+A\\sin(\\omega x)$.\r\n<p align=\"center\">\r\n <img src=\"https://user-images.githubusercontent.com/126679979/224443276-b7090965-3f31-4869-9dba-ec738aa47ac0.png\" width=\"800\">\r\n</p>\r\n",
"bugtrack_url": null,
"license": "",
"summary": "Interactive python fitting interface",
"version": "1.0.0",
"split_keywords": [
"python",
"fit",
"statistics",
"modelling",
"science"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "8dd5e2975127087f5b14d23409b622f087f8e9309ebbb4a324cfe38d0ae5cb96",
"md5": "0c844e400f71bd316fc6f0abc9f99eef",
"sha256": "36eaa627e0918f7a0a4427c53c3d24b529beb790da277109bef83402284b99dd"
},
"downloads": -1,
"filename": "pyCftool-1.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "0c844e400f71bd316fc6f0abc9f99eef",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": null,
"size": 15520,
"upload_time": "2023-03-13T20:31:58",
"upload_time_iso_8601": "2023-03-13T20:31:58.378424Z",
"url": "https://files.pythonhosted.org/packages/8d/d5/e2975127087f5b14d23409b622f087f8e9309ebbb4a324cfe38d0ae5cb96/pyCftool-1.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "cf7e633a8d73ea18d517e7db196b1690f83a7a052dbb78cdc6c5cc43d9f8136d",
"md5": "464a9bf6562cf6c78d69afcad1491cfb",
"sha256": "b6eb6e869778f80dcfbf82a1aa6248fb12870a8579c3e7c03b56f6a236524449"
},
"downloads": -1,
"filename": "pyCftool-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "464a9bf6562cf6c78d69afcad1491cfb",
"packagetype": "sdist",
"python_version": "source",
"requires_python": null,
"size": 17315,
"upload_time": "2023-03-13T20:32:00",
"upload_time_iso_8601": "2023-03-13T20:32:00.910203Z",
"url": "https://files.pythonhosted.org/packages/cf/7e/633a8d73ea18d517e7db196b1690f83a7a052dbb78cdc6c5cc43d9f8136d/pyCftool-1.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-03-13 20:32:00",
"github": false,
"gitlab": false,
"bitbucket": false,
"lcname": "pycftool"
}