Name | floopy JSON |
Version |
0.1.2
JSON |
| download |
home_page | None |
Summary | Tester-Agnostic Sequencer for Hardware-Testing in Python |
upload_time | 2024-10-11 18:53:39 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.10 |
license | GPL 3 |
keywords |
test
sequencer
task
loop
sweep
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
<h3 align="center">
<img width="66%" alt="FLooPy" src="https://raw.githubusercontent.com/floopy-systems/floopy/refs/heads/main/logo-floopy.svg">
<br><em>Tester-Agnostic Sequencer for Hardware-Testing in Python</em>
<hr />
</h3>
### Tests
* ... can performed within different **test-environments**
* ... can organized in **hierarchical** layers with (sub-) tasks
* ... can have `setup`, `task/test`, `teardown`, `final` and output functions
* Every variable
- ... has an unique **namespace**
- ... is stored as a **time-signal** with timestamps
- ... can be **sub-classed**
* Data **dependencies** between functions are **resolved** by a graph-based approach
* Auto-Save for loop-recovery and post-processing (experimental)
* Can handle **non-reentrant** tests by an extra extension (unpublished)
### Loops
* Flexible **loop configuration** (nested, zipped, concatenated)
* Standard loops: `loop_items`, `loop_lin`, `loop_log`, `loop_bisect`
* Feedback for **HiL** possible
## Getting Started
Suppose we want to test if the internal resistance of an battery `rbat` is inside the test-limits:
* The test-environment is abstracted by the namespace of the `dut` input and must be specified later, just before running the test-case.
* The loop over the load current `i_load` can be either configured locally inside the test-case or later, just before running the test-case.
### Test-Case
```python
import floopy as fly
class Test_Rbat_Charged(fly.Task):
dut = fly.Input() # object to stimulate device-under-test and measure response
i_load = fly.Input(min=0, max=1.5, unit='A', default=fly.loop_lin(num=3))
def task(dut, i_load):
dut.current = i_load
return dut.voltage
def final_fit(i=fly.Squeeze(task.i_load), v=fly.Squeeze(task)):
import numpy as np
return np.polyfit(i, v, deg=1)
@fly.Output(min=0, ltl=0.2, utl=2, max=10, unit='ohm')
def rbat(coeffs=final_fit):
return coeffs[0]
```
### Test-Plan
Now, the test-case `Test_Rbat_Charged` can be used with different loop-configurations and within different test-environments. For demonstration we just use the simple resistor equation as a simulation-environment.
```python
class TestPlan_BatterCheck(fly.Task):
def dut():
class Dut:
@property
def voltage(self):
resistance = 0.8 # ohm
return resistance * self.current
return Dut()
test_rbat_charged = Test_Rbat_Charged(dut, i_load=fly.loop_log(0.1, 1, num=5))
```
Note, that we changed the default loop-configuration of `i_load` to a logarithmic scaling.
In order to perform the Test-Plan we need a `DataManager` saving all loop-states and measurement results as time-signals in a json-file.
```python
>>> dm = fly.DataManager()
>>> dm.run_live(TestPlan_BatterCheck)
╭─ TestPlan_BatterCheck ─╮
│ ✔ test_rbat_charged │
╰────────────────────────╯
File: dm/dm_2024-10-10_16:00:29.json
```
The test results and all variables can be analyzed via pandas-tables.
```python
>>> dm.read_task(TestPlan_BatterCheck)
```
<div>
<table border="1" class="dataframe">
<thead>
<tr>
<th colspan="2" halign="left">test_rbat_charged</th>
</tr>
<tr>
<th>rbat</th>
<th>check</th>
</tr>
</thead>
<tbody>
<tr>
<td>0.8</td>
<td>True</td>
</tr>
</tbody>
</table>
</div>
```python
>>> tp = TestPlan_BatterCheck()
>>> dm.read_task(tp.test_rbat_charged.task)
```
<div>
<table border="1" class="dataframe">
<thead>
<tr style="text-align: right;">
<th></th>
<th>i_load</th>
<th>__return__</th>
</tr>
<tr>
<th>TestPlan_BatterCheck.test_rbat_charged.i_load</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<th>0.100000</th>
<td>0.100000</td>
<td>0.080000</td>
</tr>
<tr>
<th>0.177828</th>
<td>0.177828</td>
<td>0.142262</td>
</tr>
<tr>
<th>0.316228</th>
<td>0.316228</td>
<td>0.252982</td>
</tr>
<tr>
<th>0.562341</th>
<td>0.562341</td>
<td>0.449873</td>
</tr>
<tr>
<th>1.000000</th>
<td>1.000000</td>
<td>0.800000</td>
</tr>
</tbody>
</table>
</div>
For a real measurement we leave the test-case unchanged and just need to replace the `dut` function in the test-plan with something like
```python
def dut():
import instruments
dut = instruments.PowerSupply()
return dut
```
assuming an equal namespace
```python
dut.voltage
dut.current
```
with an equal behavior.
*Further information can be found in the **[FLooPy-Tutorial](./tutorial.ipynb)** which is more detailed.*
## Install
Simply do either
pip install floopy
or download the repository for a more recent version, change into
the `floopy` folder and
pip install . --user
If necessary you can run the tests with
python -m pytest
## Licence
LoopyPlot is licenced under GPL 3.
Raw data
{
"_id": null,
"home_page": null,
"name": "floopy",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.10",
"maintainer_email": null,
"keywords": "test, sequencer, task, loop, sweep",
"author": null,
"author_email": "Friedrich Hagedorn <friedrich_h@gmx.de>",
"download_url": "https://files.pythonhosted.org/packages/4c/04/826501db2f4f37413b0a3ee7fd1d008dd5c3d4613805f3bc79ef182f0407/floopy-0.1.2.tar.gz",
"platform": null,
"description": "<h3 align=\"center\">\n <img width=\"66%\" alt=\"FLooPy\" src=\"https://raw.githubusercontent.com/floopy-systems/floopy/refs/heads/main/logo-floopy.svg\">\n <br><em>Tester-Agnostic Sequencer for Hardware-Testing in Python</em>\n <hr />\n</h3>\n\n### Tests\n* ... can performed within different **test-environments**\n* ... can organized in **hierarchical** layers with (sub-) tasks\n* ... can have `setup`, `task/test`, `teardown`, `final` and output functions\n* Every variable\n - ... has an unique **namespace**\n - ... is stored as a **time-signal** with timestamps\n - ... can be **sub-classed**\n* Data **dependencies** between functions are **resolved** by a graph-based approach\n* Auto-Save for loop-recovery and post-processing (experimental)\n* Can handle **non-reentrant** tests by an extra extension (unpublished)\n\n### Loops\n* Flexible **loop configuration** (nested, zipped, concatenated)\n* Standard loops: `loop_items`, `loop_lin`, `loop_log`, `loop_bisect`\n* Feedback for **HiL** possible\n\n## Getting Started\n\nSuppose we want to test if the internal resistance of an battery `rbat` is inside the test-limits:\n\n* The test-environment is abstracted by the namespace of the `dut` input and must be specified later, just before running the test-case.\n* The loop over the load current `i_load` can be either configured locally inside the test-case or later, just before running the test-case.\n\n### Test-Case\n\n\n```python\nimport floopy as fly\n\n\nclass Test_Rbat_Charged(fly.Task):\n dut = fly.Input() # object to stimulate device-under-test and measure response\n \n i_load = fly.Input(min=0, max=1.5, unit='A', default=fly.loop_lin(num=3))\n \n def task(dut, i_load):\n dut.current = i_load\n return dut.voltage\n\n def final_fit(i=fly.Squeeze(task.i_load), v=fly.Squeeze(task)):\n import numpy as np\n return np.polyfit(i, v, deg=1)\n \n @fly.Output(min=0, ltl=0.2, utl=2, max=10, unit='ohm')\n def rbat(coeffs=final_fit):\n return coeffs[0]\n```\n\n### Test-Plan\n\nNow, the test-case `Test_Rbat_Charged` can be used with different loop-configurations and within different test-environments. For demonstration we just use the simple resistor equation as a simulation-environment.\n\n\n```python\nclass TestPlan_BatterCheck(fly.Task):\n def dut():\n class Dut:\n @property\n def voltage(self):\n resistance = 0.8 # ohm\n return resistance * self.current\n return Dut()\n\n test_rbat_charged = Test_Rbat_Charged(dut, i_load=fly.loop_log(0.1, 1, num=5))\n```\n\nNote, that we changed the default loop-configuration of `i_load` to a logarithmic scaling.\n\nIn order to perform the Test-Plan we need a `DataManager` saving all loop-states and measurement results as time-signals in a json-file.\n\n```python\n>>> dm = fly.DataManager()\n>>> dm.run_live(TestPlan_BatterCheck)\n\n\u256d\u2500 TestPlan_BatterCheck \u2500\u256e\n\u2502 \u2714 test_rbat_charged \u2502\n\u2570\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256f\nFile: dm/dm_2024-10-10_16:00:29.json\n```\n\nThe test results and all variables can be analyzed via pandas-tables.\n\n```python\n>>> dm.read_task(TestPlan_BatterCheck)\n```\n<div>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr>\n <th colspan=\"2\" halign=\"left\">test_rbat_charged</th>\n </tr>\n <tr>\n <th>rbat</th>\n <th>check</th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <td>0.8</td>\n <td>True</td>\n </tr>\n </tbody>\n</table>\n</div>\n\n```python\n>>> tp = TestPlan_BatterCheck()\n>>> dm.read_task(tp.test_rbat_charged.task)\n```\n<div>\n<table border=\"1\" class=\"dataframe\">\n <thead>\n <tr style=\"text-align: right;\">\n <th></th>\n <th>i_load</th>\n <th>__return__</th>\n </tr>\n <tr>\n <th>TestPlan_BatterCheck.test_rbat_charged.i_load</th>\n <th></th>\n <th></th>\n </tr>\n </thead>\n <tbody>\n <tr>\n <th>0.100000</th>\n <td>0.100000</td>\n <td>0.080000</td>\n </tr>\n <tr>\n <th>0.177828</th>\n <td>0.177828</td>\n <td>0.142262</td>\n </tr>\n <tr>\n <th>0.316228</th>\n <td>0.316228</td>\n <td>0.252982</td>\n </tr>\n <tr>\n <th>0.562341</th>\n <td>0.562341</td>\n <td>0.449873</td>\n </tr>\n <tr>\n <th>1.000000</th>\n <td>1.000000</td>\n <td>0.800000</td>\n </tr>\n </tbody>\n</table>\n</div>\n\nFor a real measurement we leave the test-case unchanged and just need to replace the `dut` function in the test-plan with something like\n\n```python\ndef dut():\n import instruments\n dut = instruments.PowerSupply()\n return dut\n```\n\nassuming an equal namespace\n\n```python\ndut.voltage\ndut.current\n```\n\nwith an equal behavior.\n\n*Further information can be found in the **[FLooPy-Tutorial](./tutorial.ipynb)** which is more detailed.*\n\n## Install\n\n\nSimply do either\n\n pip install floopy\n\nor download the repository for a more recent version, change into\nthe `floopy` folder and\n\n pip install . --user\n\nIf necessary you can run the tests with\n\n python -m pytest\n\n## Licence\n\nLoopyPlot is licenced under GPL 3.\n",
"bugtrack_url": null,
"license": "GPL 3",
"summary": "Tester-Agnostic Sequencer for Hardware-Testing in Python",
"version": "0.1.2",
"project_urls": {
"Homepage": "https://github.com/floopy-systems/floopy"
},
"split_keywords": [
"test",
" sequencer",
" task",
" loop",
" sweep"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "aed0d13cd6224b07be4e76aad077ac47ad09839d2b31e97610782187d57f1809",
"md5": "9b8c21df3c7df58f37069e583c4a5c39",
"sha256": "ae8e80a9824976538511eacf36f0b0b92c3a1d5c7e6714539298d892fdf976b0"
},
"downloads": -1,
"filename": "floopy-0.1.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "9b8c21df3c7df58f37069e583c4a5c39",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.10",
"size": 43243,
"upload_time": "2024-10-11T18:53:37",
"upload_time_iso_8601": "2024-10-11T18:53:37.889145Z",
"url": "https://files.pythonhosted.org/packages/ae/d0/d13cd6224b07be4e76aad077ac47ad09839d2b31e97610782187d57f1809/floopy-0.1.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "4c04826501db2f4f37413b0a3ee7fd1d008dd5c3d4613805f3bc79ef182f0407",
"md5": "3b1ed95837489998effa27786896954f",
"sha256": "3500cc2ed75f681a44cad752adb57cb0bc5612c8ba7d632677b37e46f03d0fa6"
},
"downloads": -1,
"filename": "floopy-0.1.2.tar.gz",
"has_sig": false,
"md5_digest": "3b1ed95837489998effa27786896954f",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.10",
"size": 60442,
"upload_time": "2024-10-11T18:53:39",
"upload_time_iso_8601": "2024-10-11T18:53:39.430950Z",
"url": "https://files.pythonhosted.org/packages/4c/04/826501db2f4f37413b0a3ee7fd1d008dd5c3d4613805f3bc79ef182f0407/floopy-0.1.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-10-11 18:53:39",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "floopy-systems",
"github_project": "floopy",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "floopy"
}