pyCftool


NamepyCftool JSON
Version 1.0.0 PyPI version JSON
download
home_page
SummaryInteractive python fitting interface
upload_time2023-03-13 20:32:00
maintainer
docs_urlNone
authorAndreas Forum (TehForum)
requires_python
license
keywords python fit statistics modelling science
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # 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={})
&nbsp; Opens an interactive fitting program.<br>

&nbsp;&nbsp;  **Parameters:&nbsp;&nbsp; x :&nbsp;&nbsp; one-dimensional numpy array of length N, optional**<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The x component of the data that will immediately be displayed and fitted for once the GUI opens. <br><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**y :&nbsp;&nbsp; one-dimensional numpy array of length N, optional**<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The y component of the data that will immediately be displayed and fitted for once the GUI opens. <br><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**weights :&nbsp;&nbsp; float or one-dimensional numpy arrayof length N, optional**<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The weights of each datapoint. Defined as being $w=1/\sigma$, where $\sigma$ is the uncertainty of &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the datapoints.<br><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**local_vars :&nbsp;&nbsp; dictionary, optional**<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A dictionary can be passed, but only values that are of type `np.ndarray` will be accessable by the &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GUI.  A dropdown menu in the GUI allows the user to freely choose between the arrays contained in &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the dictionary. Passing the built-in function `locals()` will give the GUI access to all previously &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;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&nbsp; Opens an interactive fitting program.<br>\r\n\r\n&nbsp;&nbsp;  **Parameters:&nbsp;&nbsp; x :&nbsp;&nbsp; one-dimensional numpy array of length N, optional**<br>\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The x component of the data that will immediately be displayed and fitted for once the GUI opens. <br><br>\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**y :&nbsp;&nbsp; one-dimensional numpy array of length N, optional**<br>\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The y component of the data that will immediately be displayed and fitted for once the GUI opens. <br><br>\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**weights :&nbsp;&nbsp; float or one-dimensional numpy arrayof length N, optional**<br>\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; The weights of each datapoint. Defined as being $w=1/\\sigma$, where $\\sigma$ is the uncertainty of &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the datapoints.<br><br>\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;**local_vars :&nbsp;&nbsp; dictionary, optional**<br>\r\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A dictionary can be passed, but only values that are of type `np.ndarray` will be accessable by the &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GUI.  A dropdown menu in the GUI allows the user to freely choose between the arrays contained in &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;the dictionary. Passing the built-in function `locals()` will give the GUI access to all previously &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;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"
}
        
Elapsed time: 0.07044s