├── .gitignore ├── LICENSE ├── QKeithleyControl.py ├── README.md ├── doc ├── 2400S-900-01_K-Sep2011_User.pdf ├── 2400_quick.pdf └── img │ ├── QKeithelySweep.png │ ├── QKeithleyBias.png │ ├── QKeithleyBiasStep-2.png │ ├── QKeithleyBiasStep-3.png │ ├── QKeithleyBiasStep-4.png │ ├── QKeithleyBiasStep-5.png │ ├── QKeithleyBiasStep.png │ ├── QKeithleyConfiguration.png │ ├── QKeithleySolar.png │ ├── mpp-tracking-gaas-p.png │ ├── mpp-tracking-gaas.png │ ├── mpp-tracking.png │ ├── voc-tracking-gaas-p.png │ ├── voc-tracking-gaas.png │ └── voc-tracking.png ├── examples ├── 2N7000-Q4(nMOS) │ ├── dat │ │ ├── 2N7000-Q4(nMOS)-OC.dat │ │ └── 2N7000-Q4(nMOS)-TC.dat │ ├── png │ │ ├── 2N7000-Q4(nMOS)-OC.png │ │ └── 2N7000-Q4(nMOS)-TC.png │ └── python │ │ ├── outputCharacteristics.py │ │ └── transferCharacteristics.py ├── BC177B-pnp(BJT) │ ├── dat │ │ ├── BJT-BC177B(pnp)-CE-ice(ibe).dat │ │ ├── BJT-BC177B(pnp)-CE-ice(vbe).dat │ │ └── BJT-BC177B(pnp)-CE-ice(vce).dat │ ├── png │ │ ├── BJT-BC177B(pnp)-GC.png │ │ ├── BJT-BC177B(pnp)-OC.png │ │ └── BJT-BC177B(pnp)-TC.png │ └── python │ │ ├── gainCharacteristics.py │ │ ├── outputCharacteristics.py │ │ └── transferCharacteristics.py ├── BC547C-npn(BJT) │ ├── dat │ │ ├── BJT-BC547C(npn)-CE-ice(ibe).dat │ │ ├── BJT-BC547C(npn)-CE-ice(vbe).dat │ │ └── BJT-BC547C(npn)-CE-ice(vce).dat │ ├── png │ │ ├── BJT-BC547C(npn)-GC.png │ │ ├── BJT-BC547C(npn)-OC.png │ │ └── BJT-BC547C(npn)-TC.png │ └── python │ │ ├── gainCharacteristics.py │ │ ├── outputCharacteristics.py │ │ └── transferCharacteristics.py ├── DiodeResistor │ ├── dat │ │ ├── iv-sweep.dat │ │ └── stability.dat │ ├── png │ │ ├── iv-sweep.png │ │ └── stability.png │ └── python │ │ ├── processStability.py │ │ └── processSweep.py └── SolarReference │ ├── dat │ ├── GaAs │ │ ├── gaas-ref-datasheet.pdf │ │ ├── gaas-ref-extract.dat │ │ ├── gaas-ref-stability.dat │ │ ├── gaas-ref-sweep.dat │ │ └── gaas-ref-tracking.dat │ └── Si │ │ ├── si-ref-datasheet.pdf │ │ ├── si-ref-extract.dat │ │ ├── si-ref-stability.dat │ │ ├── si-ref-sweep.dat │ │ └── si-ref-tracking.dat │ ├── png │ ├── gaas-ref │ │ ├── gaas-ref-mpp-tracking.png │ │ ├── gaas-ref-sweep.png │ │ └── gaas-ref-voc-tracking.png │ ├── si-ref │ │ ├── si-ref-mpp-tracking.png │ │ ├── si-ref-sweep.png │ │ └── si-ref-voc-tracking.png │ └── stability │ │ └── comp-ref-stability.png │ └── python │ ├── processStability.py │ ├── processSweep.py │ └── processTracking.py └── src ├── QKeithleyMain.py ├── __init__.py ├── app ├── QKeithleyBias.py ├── QKeithleyConfig.py ├── QKeithleySolar.py ├── QKeithleySweep.py └── __init__.py ├── python.ico └── widgets ├── QKeithleyBiasWidget.py ├── QKeithleyConfigWidget.py └── __init__.py /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 mwchalmers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /QKeithleyControl.py: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------------- 2 | # QKeithleyControl 3 | # Copyright (C) 2019 Michael Winters 4 | # mwchalmers@protonmail.com 5 | # --------------------------------------------------------------------------------- 6 | # 7 | # Permission is hereby granted, free of charge, to any person obtaining a copy 8 | # of this software and associated documentation files (the "Software"), to deal 9 | # in the Software without restriction, including without limitation the rights 10 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | # copies of the Software, and to permit persons to whom the Software is 12 | # furnished to do so, subject to the following conditions: 13 | # 14 | # The above copyright notice and this permission notice shall be included in all 15 | # copies or substantial portions of the Software. 16 | # 17 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | # SOFTWARE. 24 | # 25 | 26 | #!/usr/bin/env python 27 | import sys 28 | from PyQt5.QtWidgets import QApplication 29 | from src.QKeithleyMain import QKeithleyMain 30 | 31 | # Main event loop handler instance 32 | _app = QApplication(sys.argv) 33 | 34 | # Instantiate the application 35 | window = QKeithleyMain(_app) 36 | window.show() 37 | 38 | # Enter event loop 39 | _app.exec_() -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # QKeithleyControl 2 | QKeithleyControl is a user interface designed for automation of common laboratory measurement routines using **Keithley 2400 sourcemeters**. QKeithleyControl currently offers three applications which interact with the Keithely: The **IV-bias** application allows one to use the Keithley as a programable variable voltage(current) source, and the **IV-sweep** application allows one to make current/voltage sweeps of electronic devices and test structures. The **PV-characterization** application is oriented towards the characterization of photovoltaic devices. QKeithleyControl also contains a **Hardware Configuration** application which allows one to initialize and configure one or more Keithley sourcemeters for use in other applications. 3 | 4 | # Hardware Configuration 5 | When first running the program, the user will first be greeted with the hardware configuration application. This mode allows one to initialize Keithley sourcemeters. To initialize a device, simply enter the GPIB address and click on **Initialize Keithley GPIB**. The device will then appear as selectable in the **Select Insturment** dropdown menu. Note that the lists of available insturments is populated dynamically for both GPIB and RS-232 ports. 6 | 7 | ![QKeithleyConfiguration](https://github.com/mwchalmers/QKeithleyControl/blob/master/doc/img/QKeithleyConfiguration.png) 8 | 9 | When an insuremnt is selected, the user can modify several of its system parameters dynamically. For each Keithley initialized in the software, one has access to the following the following system level parameters. 10 | 11 | Control | Input | Comment 12 | ------------ | ------------- | ------------- 13 | Sense Mode | `2-wire OR 4-wire` | Configuration option to select 2-wire or 4-wire measurements 14 | Output Route | `Front OR Rear` | Select front or rear output terminals on device 15 | Integration Time | `0.01-10.0` | Specified in *Power Line Cycles*(PLCs). 1PLC = 20ms(50Hz) OR 16.7ms(60Hz) 16 | 17 | # IV-Bias Mode 18 | 19 | IV bias mode allows one to use the Keithley as a programable **voltage source** or a **current source**. To enter IV-Bias mode, select the **IV-Bias Control** application option in the **Select Measurement** menu. To operate the sourcemeter, select the level and corresponding compliance value in the configuration panel. These values will be transmitted dynamically to the Keithley. To turn on the output and monitor data, click the **Output** button. To turn off the output, simply clicking **Output** when operating. Since, the measurement will terminate after the next data point is aquired. 20 | 21 | The **Measurement Interval** setting can be used to determine how often the sourcemeter aquires data. Note that in the case of long, **Measurement Intervals** it will take one measurement interval before the output terminates. Be sure to set a corresponding current(voltage) compliance level when operating in voltage(current) source mode respectively. The **compliance level** determines the maximum amount of current(voltage) to apply when operating the sourcementer in voltage(current) source mode. Voltage source or current source mode operation can be selected in the dropdown menu in the configuration panel. The compliance cannot be changed dynamically while the output is on and measuring. 22 | 23 | ### IV-Bias Operation 24 | ![QKeithleyBias](https://github.com/mwchalmers/QKeithleyControl/blob/master/doc/img/QKeithleyBias.png) 25 | 26 | The **Output** button reflects the state of the output on the insturment. When operating, it is possible to dynamically change the output level without turning off the output by editing the **Bias Level** parameter. The plot shows the corresponding measured value as a function of time. The **Measurement Interval** parameter allows one to control the time between individual sense samples. When set to zero, the delay will reflect the insuturment integration time assinged in **Configuration** along with software runtime. In order to protect the unit, the following `20W` hard limits are placed on bias mode operation. 27 | 28 | Mode | Limit | Compliance 29 | ------------ | ------------- | ------------- 30 | Voltage Source | `+/-20V` | `1A` 31 | Current Source | `+/-1A` | `+/-20V` 32 | 33 | After performing a measurement in bias mode, QKeithleyBias gives you the option to save your data traces. This is done by selecting **Save Data**. Bias mode data will be saved in a *tab deliminated* with four columns: **elapsed time(s)**, **voltage(V)**, **current (A)**, **dissapated power (W)**. **NOTE:** The data will be saved is tied to the traces that are shown in plot. When axes are cleared by invoking **Clear Data** in the plot, data will be deleted from application memory. Be sure to save your data before clearing plots. Also, changing operation from voltage source to current source mode will invoke **Clear Data**. A dialogue is always presented to the user if data is to be deleted. 34 | 35 | # IV-Characterization Mode 36 | 37 | IV-characterization mode may be used to acquire the DC charachteristics of electronic devices and test circutis. Basic operation in this mode is similar to bias mode operation. To measure a device characteristic, first enter your desired parameters. After reviewing your measurement parameters, click **Measure Sweep** to acquire data from your device under test. Note that in IV-characterization mode, it is always possible to abort measurements by clicking the **Abort Sweep** button mid measurement. In case of measurements with long measurement intervals, the measurement will terminate after the next data point has been collected. In order to save data traces, click on **Save Data**. Note that it is not possible to save data while measurements are underway. Below is shown an extract of data produced via an IV-Sweep mode measurement. 38 | 39 | ### IV-Sweep Operation 40 | ![QKeithleySweep](https://github.com/mwchalmers/QKeithleyControl/blob/master/doc/img/QKeithelySweep.png) 41 | 42 | IV-characterization mode may be used to charachterize both two terminal (Resistances, Diodes, PV devices) and three terminal devices (FET, BJT). For two terminal devices, only one Keithley sourcemeter is required whereas for three terminal devices two Keithleys are required. In two terminal operation, a range of voltages(currents) is applied and the corresponding current(voltage) is measured for each bias point respectively. In basic two terminal operation, one only needs to specify a **start value**, **stop value** and the **number of points** in the controller. 43 | 44 | To measure a three terminal device such as a field effect transistor, one would like to perform repeated two terminal **IV-sweeps** while varying the voltage of the gate of the device via a **V-step**. This behaviour of **IV-sweep** and **V-step** can be configured independently via the **Configure Parameters** dropdown menu. By default, the three terminal **V-step** behaviour is disabled thus providing two terminal operation. To enable **V-step** simply toggle the **V-step (ON/OFF)** button. 45 | 46 | In order to perform a three terminal measurement, it is important that one first initializes two Keithley sourcemeters in the **Hardware Configuration**. These devices will then appear in the **Select Device**´dropdown in the IV-characterization application. Take note of the GPIB addresses of your IV-sweep and V-step sourcemeters when you are initializing your insturments. Note that the application will allow for the selection of the same device for the IV-sweep and V-step parameters. However, in this case, a warning message will be displayed indicating that the same sourcemeter has been selected for sweep and step operation and hardware operation will default to multiple identical sweeps. 47 | 48 | ### IV-Hysteresis Measurements 49 | The QKeithleySweep application has a **Hysteresis Mode** selector embedded into the **IV-sweep** controller allowing one to configure a variety of sweep conditions. Hysteresis measurements can be useful to characterize electronic devices that are unstable due to electronic trapping effects. The application summarizes the hysteresis modes available in QKeithleySweep. Note that the number of points in hysteresis modes is approximately `2n`. 50 | 51 | Hysteresis Mode | Bias Operation | nPoints 52 | ------------ | ------------- | ------------- 53 | `None` | `start - stop` | `n` 54 | `Reverse-sweep` | `start - stop - start` | `2*n - 1` 55 | `Zero-centered` | `0V - start - 0V -stop - 0V` | `2*n + 2` 56 | 57 | ### Bias step for transistor charachterization 58 | 59 | QKeithleyControl offers a bias step mode which is useful for characterizing active devices such as field effect transistors (FETs) and bipolar junction transistors (BJTs). During a typical FET transistor measurement (output charachteristic), a varying voltage bias is applied between the soure-drain terminals of the FET and drain current is measured for a series of gate voltages *(voltage sweep, voltage step)*. In the case of a BJT, varying voltage bias is applied between the emitter-collector terminals and collector current is measured for varying base currents *(voltage sweep, current step)*. When operating in bias step mode, two independent Keithleys should be initialized in the Hardware Configuration setup for the sweep bias supply and step bias supply respectively. To configure a bias step measurement, select the **IV-step** option in the **configure parameters** menu and select the step source mode (voltage/current) and desired step parameters. Note that the QKeithleyControl will not perform the bias step loop unless the **Step Bias** button is in the ON state. 60 | 61 | ![QKeithleyBiasStep](https://github.com/mesoic/QKeithleyControl/blob/master/doc/img/QKeithleyBiasStep.png) 62 | 63 | ### Measuring Unstable Devices 64 | 65 | Keithley sourcemeters can only supply starcase sweeps in which the voltage(current) is stepped from value to value in a discrete fashion. In the case of unstable devices, a sudden change in voltage may generate some transient behaviour in the current. However, IV-characterization mode only measures once for each applied bias, leaving integration of unstable currents and voltages up to the hardware itself. In all cases, the software will measure the current as soon as possible (i.e. before applying the measurement dealy cycle) such that the measuremnt settle time is determined by the hardware integration time. To investivate slow transients when quickly changing the bias, it is advised to use IV-bias mode with a short hardware integration time. 66 | 67 | # PV-Characterization Mode 68 | 69 | 70 | ### Voc and MPP tracking modes 71 | 72 | ![QKeithleySolar](https://github.com/mesoic/QKeithleyControl/blob/master/doc/img/QKeithleySolar.png) 73 | 74 | 75 | # Data Format 76 | QKeithleyControl is built upon the [QVisaFramework](https://github.com/mesoic/PyQtVisa). This allows for a unified method of handling data for all application modes. The file below shows an example measurement consisting of two IV-sweeps. The data format is *tab-deliminated* and is designed to be easy to manipulate in commercial software. Data header lines are always preceeded by the `*!` prefix. Measurement header lines will always take the following form `#! `. The type wiil injected by the calling application (e.g. QKeithleyBias, QKeithleySweep, etc.), and the hash value provides for a cryptographically unique stamp which can be used to identify the data in user built postprocessing applications. 77 | 78 | ``` 79 | *! QVisaDataObject v1.1 80 | *! hash d9bf90b 81 | 82 | #! __data__ d896f10 83 | #! __type__ i-bias 84 | #! __desc__ diode-resistor(100OHM)-meas1 85 | t V I P 86 | 0.3202240467071533 0.7315464 0.001000023 0.0007315632255672001 87 | 0.6902480125427246 0.7315202 0.001000024 0.0007315377564847999 88 | 1.0602588653564453 0.7314978 0.001000024 0.0007315153559472 89 | 1.420255184173584 0.7314824 0.001000024 0.0007314999555775999 90 | 1.7702603340148926 0.7314693 0.001000023 0.0007314861237939 91 | 2.1302578449249268 0.731465 0.001000024 0.00073148255516 92 | 2.490250587463379 0.7314622 0.001000023 0.0007314790236306 93 | 94 | 95 | #! __data__ 308e69d 96 | #! __type__ i-bias 97 | #! __desc__ diode-resistor(100OHM)-meas2 98 | t V I P 99 | 0.32025790214538574 0.7315596 0.001000023 0.0007315764258708001 100 | 0.6802637577056885 0.7315525 0.001000023 0.0007315693257075001 101 | 1.0402534008026123 0.7315519 0.001000023 0.0007315687256937 102 | 1.4002594947814941 0.7315536 0.001000023 0.0007315704257328001 103 | 1.7602622509002686 0.7315568 0.001000023 0.0007315736258064001 104 | 2.12026047706604 0.731561 0.001000022 0.000731577094342 105 | 2.4802584648132324 0.7315661 0.001000023 0.0007315829260203001 106 | 107 | ``` 108 | 109 | # Installation 110 | 111 | Since QKeithleyControl is written in [python](https://www.python.org/downloads/), be sure to install [python](https://www.python.org/downloads/) before continuing. To get QKeithleyControl, simply clone this [repository](https://github.com/mesoic/QKeithleyControl). Alternatively you can download `.zip` file. Assuming you have all dependencies installed properly you can run QKeithleyControl directly out of the source directory. 112 | 113 | ``` 114 | cd QKeithleyControl/ 115 | python QKeithleyControl.py 116 | ``` 117 | It may be desired to create a softlink shortcut to the program contol. To do this in Windows, navigate to your `QKeithleyControl` directory, left click on `QKeithleyControl.py` and create your shortcut. In Linux, execute the following commands with your specific source and destination paths. 118 | ``` 119 | ln -s /QKeithleyControl/QKeithleyControl.py /QKeithleyControl.py 120 | ``` 121 | 122 | # Dependencies 123 | 124 | QKeithleyControl requires both hardware and software dependencies prior to installation and operation. To communicate with Keithely over GPIB the following resources are needed. 125 | 126 | 1. [NI 488.2](https://www.ni.com/sv-se/support/downloads/drivers/download.ni-488-2.html#329025) is an NI instrument driver with several utilities that help in developing and debugging an application program. NI-488.2 includes high-level commands that automatically handle all bus management, so you do not have to learn the programming details of the GPIB hardware product or the IEEE 488.2 protocol. 127 | 2. [NI VISA](https://www.ni.com/sv-se/support/downloads/drivers/download.ni-visa.html#329456) is an NI instrument driver that is an implementation of the Virtual Instrument Software Architecture (VISA) I/O standard. VISA is a standard for configuring, programming, and troubleshooting instrumentation systems comprising GPIB, VXI, PXI, serial (RS232/RS485), Ethernet/LXI, and/or USB interfaces. 128 | 129 | The following python dependencies are also required. 130 | 131 | 1. [pyVisa](https://pyvisa.readthedocs.io/en/latest/) Python bindings for NI-VISA driver 132 | 2. [PyQt5](https://wiki.python.org/moin/PyQt) Python bindings for Qt development framework 133 | 3. [numpy](https://numpy.org/) Python numerics library 134 | 4. [matplotlib](https://matplotlib.org/) Python plotting library 135 | 5. [PyQtVisa](https://github.com/mesoic/PyQtVisa) Qt Framework for building pyVisa applications. 136 | 137 | The python modules can be installed using pip. To get pip run the following commands: 138 | ``` 139 | curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py 140 | python get-pip.py 141 | ``` 142 | 143 | To install the python dependencies simply run the following commands 144 | ``` 145 | pip install pyvisa 146 | pip install PyQt5 147 | pip install numpy 148 | pip install matplotlib 149 | pip install PyQtVisa 150 | ``` 151 | -------------------------------------------------------------------------------- /doc/2400S-900-01_K-Sep2011_User.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/doc/2400S-900-01_K-Sep2011_User.pdf -------------------------------------------------------------------------------- /doc/2400_quick.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/doc/2400_quick.pdf -------------------------------------------------------------------------------- /doc/img/QKeithelySweep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/doc/img/QKeithelySweep.png -------------------------------------------------------------------------------- /doc/img/QKeithleyBias.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/doc/img/QKeithleyBias.png -------------------------------------------------------------------------------- /doc/img/QKeithleyBiasStep-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/doc/img/QKeithleyBiasStep-2.png -------------------------------------------------------------------------------- /doc/img/QKeithleyBiasStep-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/doc/img/QKeithleyBiasStep-3.png -------------------------------------------------------------------------------- /doc/img/QKeithleyBiasStep-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/doc/img/QKeithleyBiasStep-4.png -------------------------------------------------------------------------------- /doc/img/QKeithleyBiasStep-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/doc/img/QKeithleyBiasStep-5.png -------------------------------------------------------------------------------- /doc/img/QKeithleyBiasStep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/doc/img/QKeithleyBiasStep.png -------------------------------------------------------------------------------- /doc/img/QKeithleyConfiguration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/doc/img/QKeithleyConfiguration.png -------------------------------------------------------------------------------- /doc/img/QKeithleySolar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/doc/img/QKeithleySolar.png -------------------------------------------------------------------------------- /doc/img/mpp-tracking-gaas-p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/doc/img/mpp-tracking-gaas-p.png -------------------------------------------------------------------------------- /doc/img/mpp-tracking-gaas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/doc/img/mpp-tracking-gaas.png -------------------------------------------------------------------------------- /doc/img/mpp-tracking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/doc/img/mpp-tracking.png -------------------------------------------------------------------------------- /doc/img/voc-tracking-gaas-p.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/doc/img/voc-tracking-gaas-p.png -------------------------------------------------------------------------------- /doc/img/voc-tracking-gaas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/doc/img/voc-tracking-gaas.png -------------------------------------------------------------------------------- /doc/img/voc-tracking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/doc/img/voc-tracking.png -------------------------------------------------------------------------------- /examples/2N7000-Q4(nMOS)/png/2N7000-Q4(nMOS)-OC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/examples/2N7000-Q4(nMOS)/png/2N7000-Q4(nMOS)-OC.png -------------------------------------------------------------------------------- /examples/2N7000-Q4(nMOS)/png/2N7000-Q4(nMOS)-TC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/examples/2N7000-Q4(nMOS)/png/2N7000-Q4(nMOS)-TC.png -------------------------------------------------------------------------------- /examples/2N7000-Q4(nMOS)/python/outputCharacteristics.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import numpy as np 4 | 5 | # Import QVisaDataObject 6 | from PyQtVisa.utils import QVisaDataObject 7 | 8 | # Import matplotlib 9 | import matplotlib.pyplot as plt 10 | import matplotlib as mpl 11 | if __name__ == "__main__": 12 | 13 | # Path to data files 14 | #path = "../dat/BJT-BC547C-CE(npn).dat" 15 | path = "../dat/2N7000-Q4(nMOS)-OC.dat" 16 | 17 | # Read data object 18 | data = QVisaDataObject.QVisaDataObject() 19 | data.read_from_file( path ) 20 | 21 | # Extract current bias steps 22 | vgs_step = [] 23 | 24 | for _key in data.keys(): 25 | 26 | if data.get_key_data(_key) != {}: 27 | 28 | vgs_step.append( float( data.get_metadata(_key, "__step__") ) ) 29 | 30 | 31 | # Use the base current to create a colormap for traces. Normalize 32 | # colobar values to minimum and maximum base current 33 | norm = mpl.colors.Normalize( vmin=min(vgs_step), vmax=max(vgs_step) ) 34 | cmap = mpl.cm.ScalarMappable( norm=norm, cmap=mpl.cm.cividis ) 35 | cmap.set_array([]) 36 | 37 | # Set up mpl figure 38 | fig = plt.figure() 39 | ax0 = fig.add_subplot(111) 40 | 41 | # # Loop through data keys and plot traces 42 | for _key in data.keys(): 43 | 44 | if data.get_key_data(_key) != {}: 45 | 46 | # Extract current bias step 47 | vgs = ( float( data.get_metadata(_key, "__step__") ) ) 48 | 49 | # Extract voltage and current 50 | vds = data.get_subkey_data(_key, "V0") 51 | ids = data.get_subkey_data(_key, "I0") 52 | 53 | # plot the data 54 | ax0.plot( vds[1:], [ 1e3 * _ for _ in ids[1:] ], color = cmap.to_rgba(vgs) ) 55 | 56 | 57 | # Add axes lables and show plot 58 | ax0.set_title("2N7000-Q4(nMOS) : Output Characteristics") 59 | ax0.set_xlabel("$V_{ds}$ $(V)$") 60 | ax0.set_ylabel("$I_{ds}$ $(mA)$") 61 | 62 | # Add the colorbar 63 | cbar = fig.colorbar(cmap, ticks=vgs_step) 64 | cbar.ax.get_yaxis().labelpad = 20 65 | cbar.ax.set_ylabel("$V_{gs}$ $(V)$", rotation=270) 66 | 67 | # Show plot 68 | plt.tight_layout() 69 | plt.show() 70 | -------------------------------------------------------------------------------- /examples/2N7000-Q4(nMOS)/python/transferCharacteristics.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import numpy as np 4 | 5 | # Import QVisaDataObject 6 | from PyQtVisa.utils import QVisaDataObject 7 | 8 | # Import matplotlib 9 | import matplotlib.pyplot as plt 10 | import matplotlib as mpl 11 | if __name__ == "__main__": 12 | 13 | # Path to data files 14 | #path = "../dat/BJT-BC547C-CE(npn).dat" 15 | path = "../dat/2N7000-Q4(nMOS)-TC.dat" 16 | 17 | # Read data object 18 | data = QVisaDataObject.QVisaDataObject() 19 | data.read_from_file( path ) 20 | 21 | # Extract current bias steps 22 | vds_step = [] 23 | 24 | for _key in data.keys(): 25 | 26 | if data.get_key_data(_key) != {}: 27 | 28 | vds_step.append( float( data.get_metadata(_key, "__step__") ) ) 29 | 30 | 31 | # Use the base current to create a colormap for traces. Normalize 32 | # colobar values to minimum and maximum base current 33 | norm = mpl.colors.Normalize( vmin=min(vds_step), vmax=max(vds_step) ) 34 | cmap = mpl.cm.ScalarMappable( norm=norm, cmap=mpl.cm.cividis ) 35 | cmap.set_array([]) 36 | 37 | # Set up mpl figure 38 | fig = plt.figure() 39 | ax0 = fig.add_subplot(111) 40 | 41 | # # Loop through data keys and plot traces 42 | for _key in data.keys(): 43 | 44 | if data.get_key_data(_key) != {}: 45 | 46 | # Extract current bias step 47 | vds = ( float( data.get_metadata(_key, "__step__") ) ) 48 | 49 | # Extract voltage and current 50 | vgs = data.get_subkey_data(_key, "V0") 51 | ids = data.get_subkey_data(_key, "I1") 52 | 53 | # plot the data 54 | ax0.plot( vgs[1:], [ 1e3 * _ for _ in ids[1:] ], color = cmap.to_rgba(vds) ) 55 | 56 | 57 | # Add axes lables and show plot 58 | ax0.set_title("2N7000-Q4(nMOS) : Transfer Characteristics") 59 | ax0.set_xlabel("$V_{gs}$ $(V)$") 60 | ax0.set_ylabel("$I_{ds}$ $(mA)$") 61 | 62 | # Add the colorbar 63 | cbar = fig.colorbar(cmap, ticks=vds_step) 64 | cbar.ax.get_yaxis().labelpad = 20 65 | cbar.ax.set_ylabel("$V_{ds}$ $(V)$", rotation=270) 66 | 67 | # Show plot 68 | plt.tight_layout() 69 | plt.show() 70 | -------------------------------------------------------------------------------- /examples/BC177B-pnp(BJT)/png/BJT-BC177B(pnp)-GC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/examples/BC177B-pnp(BJT)/png/BJT-BC177B(pnp)-GC.png -------------------------------------------------------------------------------- /examples/BC177B-pnp(BJT)/png/BJT-BC177B(pnp)-OC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/examples/BC177B-pnp(BJT)/png/BJT-BC177B(pnp)-OC.png -------------------------------------------------------------------------------- /examples/BC177B-pnp(BJT)/png/BJT-BC177B(pnp)-TC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/examples/BC177B-pnp(BJT)/png/BJT-BC177B(pnp)-TC.png -------------------------------------------------------------------------------- /examples/BC177B-pnp(BJT)/python/gainCharacteristics.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import numpy as np 4 | 5 | # Import QVisaDataObject 6 | from PyQtVisa.utils import QVisaDataObject 7 | 8 | # Import matplotlib 9 | import matplotlib.pyplot as plt 10 | import matplotlib as mpl 11 | if __name__ == "__main__": 12 | 13 | # Path to data files 14 | path = "../dat/BJT-BC177B(pnp)-CE-ice(ibe).dat" 15 | 16 | # Read data object 17 | data = QVisaDataObject.QVisaDataObject() 18 | data.read_from_file( path ) 19 | 20 | # Extract voltage bias steps 21 | vce_step, ibe_unit, ice_unit = [], 1e6, 1e3 22 | 23 | for _key in data.keys(): 24 | 25 | if data.get_key_data(_key) != {}: 26 | 27 | vce_step.append( float( data.get_metadata(_key, "__step__") ) ) 28 | 29 | 30 | # Use the base current to create a colormap for traces. Normalize 31 | # colobar values to minimum and maximum base current 32 | norm = mpl.colors.Normalize( vmin=min(vce_step), vmax=max(vce_step) ) 33 | cmap = mpl.cm.ScalarMappable( norm=norm, cmap=mpl.cm.cividis ) 34 | cmap.set_array([]) 35 | 36 | # Set up mpl figure 37 | fig = plt.figure() 38 | ax0 = fig.add_subplot(111) 39 | 40 | # Loop through data keys and plot traces 41 | for _key in data.keys(): 42 | 43 | if data.get_key_data(_key) != {}: 44 | 45 | # Extract current bias step 46 | vce = ( float( data.get_metadata(_key, "__step__") ) ) 47 | 48 | # Extract voltage and current 49 | ibe = data.get_subkey_data(_key, "I0") 50 | ice = data.get_subkey_data(_key, "I1") 51 | 52 | # Calculate gain 53 | beta = [ _ice/_ibe for _ice, _ibe in zip(ice, ibe) ] 54 | 55 | # plot the data 56 | ax0.plot( [ ibe_unit * _ for _ in ibe[70:] ], beta[70:], color = cmap.to_rgba(vce) ) 57 | 58 | 59 | # Add axes lables and show plot 60 | #ax0.set_title("BJT BC547C(npn) : Common Emitter") 61 | ax0.set_title("BJT BC177B(pnp) : Gain Characteristics") 62 | ax0.set_xlabel("$I_{be}$ $(\\mu A)$") 63 | ax0.set_ylabel("$\\beta $") 64 | 65 | # Add the colorbar 66 | cbar = fig.colorbar(cmap, ticks=vce_step) 67 | cbar.ax.get_yaxis().labelpad = 20 68 | cbar.ax.set_ylabel("$V_{ce}$ $(V)$", rotation=270) 69 | 70 | # Show plot 71 | plt.tight_layout() 72 | plt.show() 73 | -------------------------------------------------------------------------------- /examples/BC177B-pnp(BJT)/python/outputCharacteristics.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import numpy as np 4 | 5 | # Import QVisaDataObject 6 | from PyQtVisa.utils import QVisaDataObject 7 | 8 | # Import matplotlib 9 | import matplotlib.pyplot as plt 10 | import matplotlib as mpl 11 | if __name__ == "__main__": 12 | 13 | # Path to data files 14 | #path = "../dat/BJT-BC547C-CE(npn).dat" 15 | path = "../dat/BJT-BC177B(pnp)-CE-ice(vce).dat" 16 | 17 | # Read data object 18 | data = QVisaDataObject.QVisaDataObject() 19 | data.read_from_file( path ) 20 | 21 | # Extract current bias steps 22 | ibe_step, ibe_unit, ice_unit = [], 1e6, 1e3 23 | 24 | for _key in data.keys(): 25 | 26 | if data.get_key_data(_key) != {}: 27 | 28 | ibe_step.append( ibe_unit * float( data.get_metadata(_key, "__step__") ) ) 29 | 30 | 31 | # Use the base current to create a colormap for traces. Normalize 32 | # colobar values to minimum and maximum base current 33 | norm = mpl.colors.Normalize( vmin=min(ibe_step), vmax=max(ibe_step) ) 34 | cmap = mpl.cm.ScalarMappable( norm=norm, cmap=mpl.cm.cividis ) 35 | cmap.set_array([]) 36 | 37 | # Set up mpl figure 38 | fig = plt.figure() 39 | ax0 = fig.add_subplot(111) 40 | 41 | # Loop through data keys and plot traces 42 | for _key in data.keys(): 43 | 44 | if data.get_key_data(_key) != {}: 45 | 46 | # Extract current bias step 47 | ibe = ( ibe_unit * float( data.get_metadata(_key, "__step__") ) ) 48 | 49 | # Extract voltage and current 50 | voltage = data.get_subkey_data(_key, "V0") 51 | current = data.get_subkey_data(_key, "I0") 52 | 53 | # plot the data 54 | ax0.plot( voltage[1:], [ ice_unit * _ for _ in current[1:] ], color = cmap.to_rgba(ibe) ) 55 | 56 | 57 | # Add axes lables and show plot 58 | #ax0.set_title("BJT BC547C(npn) : Common Emitter") 59 | ax0.set_title("BJT BC177B(pnp) : Output Characteristics") 60 | ax0.set_xlabel("$V_{ce}$ $(V)$") 61 | ax0.set_ylabel("$I_{ce}$ $(mA)$") 62 | 63 | # Add the colorbar 64 | cbar = fig.colorbar(cmap, ticks=ibe_step) 65 | cbar.ax.get_yaxis().labelpad = 20 66 | cbar.ax.set_ylabel("$I_{be}$ $(\\mu A)$", rotation=270) 67 | 68 | # Show plot 69 | plt.tight_layout() 70 | plt.show() 71 | -------------------------------------------------------------------------------- /examples/BC177B-pnp(BJT)/python/transferCharacteristics.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import numpy as np 4 | 5 | # Import QVisaDataObject 6 | from PyQtVisa.utils import QVisaDataObject 7 | 8 | # Import matplotlib 9 | import matplotlib.pyplot as plt 10 | import matplotlib as mpl 11 | if __name__ == "__main__": 12 | 13 | # Path to data files 14 | path = "../dat/BJT-BC177B(pnp)-CE-ice(vbe).dat" 15 | 16 | # Read data object 17 | data = QVisaDataObject.QVisaDataObject() 18 | data.read_from_file( path ) 19 | 20 | # Extract voltage bias steps 21 | vce_step, ice_unit = [], 1e3 22 | 23 | for _key in data.keys(): 24 | 25 | if data.get_key_data(_key) != {}: 26 | 27 | vce_step.append( float( data.get_metadata(_key, "__step__") ) ) 28 | 29 | 30 | # Use the base current to create a colormap for traces. Normalize 31 | # colobar values to minimum and maximum base current 32 | norm = mpl.colors.Normalize( vmin=min(vce_step), vmax=max(vce_step) ) 33 | cmap = mpl.cm.ScalarMappable( norm=norm, cmap=mpl.cm.cividis ) 34 | cmap.set_array([]) 35 | 36 | # Set up mpl figure 37 | fig = plt.figure() 38 | ax0 = fig.add_subplot(111) 39 | 40 | # Loop through data keys and plot traces 41 | for _key in data.keys(): 42 | 43 | if data.get_key_data(_key) != {}: 44 | 45 | # Extract current bias step 46 | vce = ( float( data.get_metadata(_key, "__step__") ) ) 47 | 48 | # Extract voltage and current 49 | vbe = data.get_subkey_data(_key, "V0") 50 | ice = data.get_subkey_data(_key, "I1") 51 | 52 | 53 | # plot the data 54 | ax0.plot( vbe[1:], [ ice_unit * _ for _ in ice[1:] ], color = cmap.to_rgba(vce) ) 55 | 56 | 57 | # Add axes lables and show plot 58 | #ax0.set_title("BJT BC547C(npn) : Common Emitter") 59 | ax0.set_title("BJT BC177B(pnp) : Transfer Characteristics") 60 | ax0.set_xlabel("$V_{be}$ $(V)$") 61 | ax0.set_ylabel("$I_{ce}$ $(mA)$") 62 | 63 | # Add the colorbar 64 | cbar = fig.colorbar(cmap, ticks=vce_step) 65 | cbar.ax.get_yaxis().labelpad = 20 66 | cbar.ax.set_ylabel("$V_{ce}$ $(V)$", rotation=270) 67 | 68 | # Show plot 69 | plt.tight_layout() 70 | plt.show() 71 | -------------------------------------------------------------------------------- /examples/BC547C-npn(BJT)/png/BJT-BC547C(npn)-GC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/examples/BC547C-npn(BJT)/png/BJT-BC547C(npn)-GC.png -------------------------------------------------------------------------------- /examples/BC547C-npn(BJT)/png/BJT-BC547C(npn)-OC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/examples/BC547C-npn(BJT)/png/BJT-BC547C(npn)-OC.png -------------------------------------------------------------------------------- /examples/BC547C-npn(BJT)/png/BJT-BC547C(npn)-TC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/examples/BC547C-npn(BJT)/png/BJT-BC547C(npn)-TC.png -------------------------------------------------------------------------------- /examples/BC547C-npn(BJT)/python/gainCharacteristics.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import numpy as np 4 | 5 | # Import QVisaDataObject 6 | from PyQtVisa.utils import QVisaDataObject 7 | 8 | # Import matplotlib 9 | import matplotlib.pyplot as plt 10 | import matplotlib as mpl 11 | if __name__ == "__main__": 12 | 13 | # Path to data files 14 | path = "../dat/BJT-BC547C(npn)-CE-ice(ibe).dat" 15 | 16 | # Read data object 17 | data = QVisaDataObject.QVisaDataObject() 18 | data.read_from_file( path ) 19 | 20 | # Extract voltage bias steps 21 | vce_step, ibe_unit, ice_unit = [], 1e6, 1e3 22 | 23 | for _key in data.keys(): 24 | 25 | if data.get_key_data(_key) != {}: 26 | 27 | vce_step.append( float( data.get_metadata(_key, "__step__") ) ) 28 | 29 | 30 | # Use the base current to create a colormap for traces. Normalize 31 | # colobar values to minimum and maximum base current 32 | norm = mpl.colors.Normalize( vmin=min(vce_step), vmax=max(vce_step) ) 33 | cmap = mpl.cm.ScalarMappable( norm=norm, cmap=mpl.cm.cividis ) 34 | cmap.set_array([]) 35 | 36 | # Set up mpl figure 37 | fig = plt.figure() 38 | ax0 = fig.add_subplot(111) 39 | 40 | # Loop through data keys and plot traces 41 | for _key in data.keys(): 42 | 43 | if data.get_key_data(_key) != {}: 44 | 45 | # Extract current bias step 46 | vce = ( float( data.get_metadata(_key, "__step__") ) ) 47 | 48 | # Extract voltage and current 49 | ibe = data.get_subkey_data(_key, "I0") 50 | ice = data.get_subkey_data(_key, "I1") 51 | 52 | # Calculate gain 53 | beta = [ _ice/_ibe for _ice, _ibe in zip(ice, ibe) ] 54 | 55 | # plot the data 56 | ax0.plot( [ ibe_unit * _ for _ in ibe[2:] ], beta[2:], color = cmap.to_rgba(vce) ) 57 | 58 | 59 | # Add axes lables and show plot 60 | #ax0.set_title("BJT BC547C(npn) : Common Emitter") 61 | ax0.set_title("BJT BC547C(npn) : Gain Characteristics") 62 | ax0.set_xlabel("$I_{be}$ $(\\mu A)$") 63 | ax0.set_ylabel("$\\beta $") 64 | 65 | # Add the colorbar 66 | cbar = fig.colorbar(cmap, ticks=vce_step) 67 | cbar.ax.get_yaxis().labelpad = 20 68 | cbar.ax.set_ylabel("$V_{ce}$ $(V)$", rotation=270) 69 | 70 | # Show plot 71 | plt.tight_layout() 72 | plt.show() 73 | -------------------------------------------------------------------------------- /examples/BC547C-npn(BJT)/python/outputCharacteristics.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import numpy as np 4 | 5 | # Import QVisaDataObject 6 | from PyQtVisa.utils import QVisaDataObject 7 | 8 | # Import matplotlib 9 | import matplotlib.pyplot as plt 10 | import matplotlib as mpl 11 | if __name__ == "__main__": 12 | 13 | # Path to data files 14 | #path = "../dat/BJT-BC547C-CE(npn).dat" 15 | path = "../dat/BJT-BC547C(npn)-CE-ice(vce).dat" 16 | 17 | # Read data object 18 | data = QVisaDataObject.QVisaDataObject() 19 | data.read_from_file( path ) 20 | 21 | # Extract current bias steps 22 | ibe_step, ibe_unit, ice_unit = [], 1e6, 1e3 23 | 24 | for _key in data.keys(): 25 | 26 | if data.get_key_data(_key) != {}: 27 | 28 | ibe_step.append( ibe_unit * float( data.get_metadata(_key, "__step__") ) ) 29 | 30 | 31 | # Use the base current to create a colormap for traces. Normalize 32 | # colobar values to minimum and maximum base current 33 | norm = mpl.colors.Normalize( vmin=min(ibe_step), vmax=max(ibe_step) ) 34 | cmap = mpl.cm.ScalarMappable( norm=norm, cmap=mpl.cm.cividis ) 35 | cmap.set_array([]) 36 | 37 | # Set up mpl figure 38 | fig = plt.figure() 39 | ax0 = fig.add_subplot(111) 40 | 41 | # Loop through data keys and plot traces 42 | for _key in data.keys(): 43 | 44 | if data.get_key_data(_key) != {}: 45 | 46 | # Extract current bias step 47 | ibe = ( ibe_unit * float( data.get_metadata(_key, "__step__") ) ) 48 | 49 | # Extract voltage and current 50 | voltage = data.get_subkey_data(_key, "V0") 51 | current = data.get_subkey_data(_key, "I0") 52 | 53 | # plot the data 54 | ax0.plot( voltage[1:], [ ice_unit * _ for _ in current[1:] ], color = cmap.to_rgba(ibe) ) 55 | 56 | 57 | # Add axes lables and show plot 58 | #ax0.set_title("BJT BC547C(npn) : Common Emitter") 59 | ax0.set_title("BJT BC547C(npn) : Output Characteristics") 60 | ax0.set_xlabel("$V_{ce}$ $(V)$") 61 | ax0.set_ylabel("$I_{ce}$ $(mA)$") 62 | 63 | # Add the colorbar 64 | cbar = fig.colorbar(cmap, ticks=ibe_step) 65 | cbar.ax.get_yaxis().labelpad = 20 66 | cbar.ax.set_ylabel("$I_{be}$ $(\\mu A)$", rotation=270) 67 | 68 | # Show plot 69 | plt.tight_layout() 70 | plt.show() 71 | -------------------------------------------------------------------------------- /examples/BC547C-npn(BJT)/python/transferCharacteristics.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import numpy as np 4 | 5 | # Import QVisaDataObject 6 | from PyQtVisa.utils import QVisaDataObject 7 | 8 | # Import matplotlib 9 | import matplotlib.pyplot as plt 10 | import matplotlib as mpl 11 | if __name__ == "__main__": 12 | 13 | # Path to data files 14 | path = "../dat/BJT-BC547C(npn)-CE-ice(vbe).dat" 15 | 16 | # Read data object 17 | data = QVisaDataObject.QVisaDataObject() 18 | data.read_from_file( path ) 19 | 20 | # Extract voltage bias steps 21 | vce_step, ice_unit = [], 1e3 22 | 23 | for _key in data.keys(): 24 | 25 | if data.get_key_data(_key) != {}: 26 | 27 | vce_step.append( float( data.get_metadata(_key, "__step__") ) ) 28 | 29 | 30 | # Use the base current to create a colormap for traces. Normalize 31 | # colobar values to minimum and maximum base current 32 | norm = mpl.colors.Normalize( vmin=min(vce_step), vmax=max(vce_step) ) 33 | cmap = mpl.cm.ScalarMappable( norm=norm, cmap=mpl.cm.cividis ) 34 | cmap.set_array([]) 35 | 36 | # Set up mpl figure 37 | fig = plt.figure() 38 | ax0 = fig.add_subplot(111) 39 | 40 | # Loop through data keys and plot traces 41 | for _key in data.keys(): 42 | 43 | if data.get_key_data(_key) != {}: 44 | 45 | # Extract current bias step 46 | vce = ( float( data.get_metadata(_key, "__step__") ) ) 47 | 48 | # Extract voltage and current 49 | vbe = data.get_subkey_data(_key, "V0") 50 | ice = data.get_subkey_data(_key, "I1") 51 | 52 | 53 | # plot the data 54 | ax0.plot( vbe[1:], [ ice_unit * _ for _ in ice[1:] ], color = cmap.to_rgba(vce) ) 55 | 56 | 57 | # Add axes lables and show plot 58 | #ax0.set_title("BJT BC547C(npn) : Common Emitter") 59 | ax0.set_title("BJT BC547C(npn) : Transfer Characteristics") 60 | ax0.set_xlabel("$V_{be}$ $(V)$") 61 | ax0.set_ylabel("$I_{ce}$ $(mA)$") 62 | 63 | # Add the colorbar 64 | cbar = fig.colorbar(cmap, ticks=vce_step) 65 | cbar.ax.get_yaxis().labelpad = 20 66 | cbar.ax.set_ylabel("$V_{ce}$ $(V)$", rotation=270) 67 | 68 | # Show plot 69 | plt.tight_layout() 70 | plt.show() 71 | -------------------------------------------------------------------------------- /examples/DiodeResistor/dat/iv-sweep.dat: -------------------------------------------------------------------------------- 1 | *! QVisaDataObject v1.1 2 | *! hash 8e9e321 3 | 4 | #! __data__ e604902 5 | #! __type__ iv-sweep 6 | #! __desc__ diode-resistor(100OHM) 7 | t V I P 8 | 0.36013364791870117 -1.0 -1.807935e-09 1.807935e-09 9 | 0.7101409435272217 -0.98 -1.796949e-09 1.76101002e-09 10 | 1.0401456356048584 -0.96 -1.794548e-09 1.72276608e-09 11 | 1.3701434135437012 -0.94 -1.778007e-09 1.67132658e-09 12 | 1.7001264095306396 -0.92 -1.75452e-09 1.6141584e-09 13 | 2.0301384925842285 -0.9 -1.762011e-09 1.5858098999999999e-09 14 | 2.3601531982421875 -0.88 -1.756455e-09 1.5456804000000001e-09 15 | 2.6901304721832275 -0.86 -1.744081e-09 1.49990966e-09 16 | 3.000133514404297 -0.84 -1.754392e-09 1.47368928e-09 17 | 3.340134859085083 -0.82 -1.715371e-09 1.4066042199999999e-09 18 | 3.680142402648926 -0.8 -1.718698e-09 1.3749584e-09 19 | 4.010137557983398 -0.78 -1.699502e-09 1.32561156e-09 20 | 4.340134143829346 -0.76 -1.701987e-09 1.29351012e-09 21 | 4.670139312744141 -0.74 -1.691673e-09 1.25183802e-09 22 | 5.000133275985718 -0.72 -1.684685e-09 1.2129732e-09 23 | 5.330140113830566 -0.7 -1.671005e-09 1.1697034999999999e-09 24 | 5.6501405239105225 -0.68 -1.665449e-09 1.13250532e-09 25 | 5.990135192871094 -0.66 -1.651013e-09 1.0896685800000001e-09 26 | 6.320137977600098 -0.64 -1.643813e-09 1.05204032e-09 27 | 6.650142669677734 -0.62 -1.633627e-09 1.01284874e-09 28 | 6.980133533477783 -0.6 -1.625166e-09 9.750996e-10 29 | 7.31014084815979 -0.58 -1.613169e-09 9.3563802e-10 30 | 7.64013147354126 -0.56 -1.606182e-09 8.994619200000001e-10 31 | 7.950140714645386 -0.54 -1.591406e-09 8.5935924e-10 32 | 8.29013466835022 -0.52 -1.581515e-09 8.223878e-10 33 | 8.630135297775269 -0.5 -1.568424e-09 7.84212e-10 34 | 8.960134506225586 -0.48 -1.562447e-09 7.4997456e-10 35 | 9.280131340026855 -0.46 -1.547925e-09 7.120454999999999e-10 36 | 9.600101232528687 -0.44 -1.534792e-09 6.753084800000001e-10 37 | 9.930148124694824 -0.42 -1.527804e-09 6.4167768e-10 38 | 10.240135908126831 -0.4 -1.513873e-09 6.055492e-10 39 | 10.580135822296143 -0.38 -1.499264e-09 5.697203200000001e-10 40 | 10.90013861656189 -0.36 -1.4903e-09 5.365079999999999e-10 41 | 11.240138530731201 -0.34 -1.466053e-09 4.9845802e-10 42 | 11.570142030715942 -0.32 -1.470641e-09 4.7060512e-10 43 | 11.900095462799072 -0.3 -1.446859e-09 4.340577e-10 44 | 12.230136632919312 -0.28 -1.430401e-09 4.0051228000000007e-10 45 | 12.560136556625366 -0.26 -1.449258e-09 3.7680708000000004e-10 46 | 12.890140295028687 -0.24 -1.411501e-09 3.3876024e-10 47 | 13.220137596130371 -0.22 -1.39037e-09 3.058814e-10 48 | 13.550132274627686 -0.2 -1.37509e-09 2.7501800000000003e-10 49 | 13.870137214660645 -0.18 -1.360483e-09 2.4488694e-10 50 | 14.210140228271484 -0.16 -1.339774e-09 2.1436384000000002e-10 51 | 14.540138959884644 -0.14 -1.317169e-09 1.8440366000000002e-10 52 | 14.870137453079224 -0.12 -1.288082e-09 1.5456984e-10 53 | 15.20013689994812 -0.1 -1.254871e-09 1.254871e-10 54 | 15.53011417388916 -0.08 -1.196656e-09 9.573248000000001e-11 55 | 15.860128402709961 -0.06 -1.103419e-09 6.620514e-11 56 | 16.19012427330017 -0.04 -9.326895e-10 3.7307580000000004e-11 57 | 16.530142068862915 -0.02 -6.137486e-10 1.2274972000000001e-11 58 | 16.860138654708862 0.0 -1.682467e-11 -0.0 59 | 17.20008373260498 0.02 1.063795e-09 2.12759e-11 60 | 17.540138959884644 0.04 2.9289e-09 1.17156e-10 61 | 17.88013219833374 0.06 5.986163e-09 3.5916977999999996e-10 62 | 18.220139265060425 0.08 1.079686e-08 8.637488000000001e-10 63 | 18.550132036209106 0.1 1.806776e-08 1.806776e-09 64 | 18.890136003494263 0.12 2.8864e-08 3.4636799999999998e-09 65 | 19.22014021873474 0.14 4.458208e-08 6.2414912000000005e-09 66 | 19.550144910812378 0.16 6.73633e-08 1.0778128e-08 67 | 19.880141735076904 0.18 1.00353e-07 1.8063539999999998e-08 68 | 20.210143089294434 0.2 1.48101e-07 2.9620200000000004e-08 69 | 20.550128698349 0.22 2.173905e-07 4.782591e-08 70 | 20.89013433456421 0.24 3.178287e-07 7.6278888e-08 71 | 21.230140209197998 0.26 4.65018e-07 1.2090468000000001e-07 72 | 21.56013774871826 0.28 6.805657e-07 1.90558396e-07 73 | 21.87014079093933 0.3 9.992137e-07 2.9976411e-07 74 | 22.3301362991333 0.32 1.470946e-06 4.7070272e-07 75 | 22.67014503479004 0.34 2.172875e-06 7.387775e-07 76 | 23.000139951705933 0.36 3.221991e-06 1.1599167600000001e-06 77 | 23.33014440536499 0.38 4.799426e-06 1.82378188e-06 78 | 23.66013479232788 0.4 7.184418e-06 2.8737672000000004e-06 79 | 24.120139122009277 0.42 1.077232e-05 4.5243744e-06 80 | 24.450145959854126 0.44 1.617625e-05 7.11755e-06 81 | 24.77013874053955 0.46 2.423967e-05 1.11502482e-05 82 | 25.09013867378235 0.48 3.614126e-05 1.73478048e-05 83 | 25.420140981674194 0.5 5.335794e-05 2.667897e-05 84 | 25.75013279914856 0.52 7.785454e-05 4.0484360800000005e-05 85 | 26.20013952255249 0.54 0.0001108471 5.9857434e-05 86 | 26.530125617980957 0.56 0.0001547386 8.665361600000002e-05 87 | 26.860142707824707 0.58 0.0002106537 0.000122179146 88 | 27.190139532089233 0.6 0.0002792251 0.00016753506 89 | 27.520143747329712 0.62 0.000360378 0.00022343436 90 | 27.85014247894287 0.64 0.0004537316 0.000290388224 91 | 28.180129289627075 0.66 0.0005580654 0.000368323164 92 | 28.510136365890503 0.68 0.0006723285 0.00045718338 93 | 28.840137720108032 0.7 0.0007953115 0.00055671805 94 | 29.170129776000977 0.72 0.000925741 0.00066653352 95 | 29.62013578414917 0.74 0.001062546 0.0007862840399999999 96 | 29.950134992599487 0.76 0.001205115 0.0009158874000000001 97 | 30.27013850212097 0.78 0.001352508 0.00105495624 98 | 30.58014225959778 0.8 0.001504173 0.0012033384000000001 99 | 30.91014790534973 0.82 0.001659568 0.0013608457599999998 100 | 31.240135669708252 0.84 0.001818245 0.0015273258 101 | 31.560136318206787 0.86 0.001980017 0.00170281462 102 | 31.880136013031006 0.88 0.002144734 0.0018873659200000002 103 | 32.19012784957886 0.9 0.002311425 0.0020802825000000003 104 | 32.510143756866455 0.92 0.002480132 0.00228172144 105 | 32.8301362991333 0.94 0.002650765 0.0024917190999999995 106 | 33.16012239456177 0.96 0.002823088 0.00271016448 107 | 33.490137338638306 0.98 0.002996967 0.00293702766 108 | 33.81357502937317 1.0 0.003172126 0.003172126 109 | 110 | 111 | -------------------------------------------------------------------------------- /examples/DiodeResistor/png/iv-sweep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/examples/DiodeResistor/png/iv-sweep.png -------------------------------------------------------------------------------- /examples/DiodeResistor/png/stability.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/examples/DiodeResistor/png/stability.png -------------------------------------------------------------------------------- /examples/DiodeResistor/python/processStability.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import numpy as np 4 | 5 | # Import QVisaDataObject 6 | from PyQtVisa.utils import QVisaDataObject 7 | 8 | # Import matplotlib 9 | import matplotlib.pyplot as plt 10 | 11 | if __name__ == "__main__": 12 | 13 | 14 | # Path to data files 15 | path = "../dat/stability.dat" 16 | 17 | # Read data object 18 | data = QVisaDataObject.QVisaDataObject() 19 | data.read_from_file( path ) 20 | 21 | # Set up mpl figure 22 | fig = plt.figure() 23 | ax0 = fig.add_subplot(111) 24 | 25 | # Extract time 26 | for _key in data.keys(): 27 | 28 | time = data.get_subkey_data(_key, "t") 29 | 30 | # Extract voltage and current 31 | voltage = data.get_subkey_data(_key, "V") 32 | current = data.get_subkey_data(_key, "I") 33 | 34 | # Plot data 35 | ax0.plot( time, voltage ) 36 | 37 | # Add axes lables and show plot 38 | ax0.set_title("Diode Resistor Circuit Stability : Current Bias = 1mA") 39 | ax0.set_xlabel("Time $(s)$") 40 | ax0.set_ylabel("Voltage $(V)$") 41 | 42 | # Show plot 43 | plt.tight_layout() 44 | plt.show() 45 | -------------------------------------------------------------------------------- /examples/DiodeResistor/python/processSweep.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import numpy as np 4 | 5 | # Import QVisaDataObject 6 | from PyQtVisa.utils import QVisaDataObject 7 | 8 | # Import matplotlib 9 | import matplotlib.pyplot as plt 10 | 11 | if __name__ == "__main__": 12 | 13 | # Path to data files 14 | path = "../dat/iv-sweep.dat" 15 | 16 | # Read data object 17 | data = QVisaDataObject.QVisaDataObject() 18 | data.read_from_file( path ) 19 | 20 | # Set up mpl figure 21 | fig = plt.figure() 22 | ax0 = fig.add_subplot(111) 23 | 24 | # Extract time 25 | for _key in data.keys(): 26 | 27 | # Extract voltage and current 28 | voltage = data.get_subkey_data(_key, "V") 29 | current = data.get_subkey_data(_key, "I") 30 | 31 | # Plot data 32 | ax0.semilogy( voltage, [ np.abs(_) for _ in current ] ) 33 | 34 | # Add axes lables and show plot 35 | ax0.set_title("Diode Resistor Circuit : IV Charachteristics") 36 | ax0.set_xlabel("Voltage $(V)$") 37 | ax0.set_ylabel("Current $(A)$") 38 | 39 | # Show plot 40 | plt.tight_layout() 41 | plt.show() 42 | -------------------------------------------------------------------------------- /examples/SolarReference/dat/GaAs/gaas-ref-datasheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/examples/SolarReference/dat/GaAs/gaas-ref-datasheet.pdf -------------------------------------------------------------------------------- /examples/SolarReference/dat/GaAs/gaas-ref-extract.dat: -------------------------------------------------------------------------------- 1 | #! GaAs Reference: Extract 2 | 3 | Voc 1.0273500000000002 4 | Isc 108.6301 5 | Jsc 27.157525 6 | Vm 0.85235 7 | Im 101.2183 8 | Jm 25.304575 9 | FF 0.7730514512189846 10 | ETA 21.568354501250003 11 | -------------------------------------------------------------------------------- /examples/SolarReference/dat/GaAs/gaas-ref-stability.dat: -------------------------------------------------------------------------------- 1 | *! QVisaDataObject v1.1 2 | *! hash 11ca295 3 | 4 | #! __data__ 2b59211 5 | #! __type__ v-bias 6 | t V I P 7 | 0.3302600383758545 0.0 -0.1255667 -0.0 8 | 0.6503162384033203 0.0 -0.1235962 -0.0 9 | 0.9502518177032471 0.0 -0.1222956 -0.0 10 | 1.2502481937408447 0.0 -0.1213723 -0.0 11 | 1.540243148803711 0.0 -0.120655 -0.0 12 | 1.8402783870697021 0.0 -0.1200413 -0.0 13 | 2.1402480602264404 0.0 -0.1195051 -0.0 14 | 2.440248966217041 0.0 -0.1190102 -0.0 15 | 2.7402491569519043 0.0 -0.118607 -0.0 16 | 3.04026460647583 0.0 -0.1182396 -0.0 17 | 3.3502724170684814 0.0 -0.1179029 -0.0 18 | 3.660248041152954 0.0 -0.1175797 -0.0 19 | 3.970250129699707 0.0 -0.1172721 -0.0 20 | 4.279989719390869 0.0 -0.1170097 -0.0 21 | 4.560285568237305 0.0 -0.1167706 -0.0 22 | 4.870264053344727 0.0 -0.116543 -0.0 23 | 5.200255870819092 0.0 -0.1163195 -0.0 24 | 5.510263442993164 0.0 -0.1161103 -0.0 25 | 5.810257911682129 0.0 -0.1159196 -0.0 26 | 6.110251426696777 0.0 -0.1157463 -0.0 27 | 6.410244464874268 0.0 -0.1155876 -0.0 28 | 6.710247993469238 0.0 -0.1154314 -0.0 29 | 7.010251522064209 0.0 -0.1152769 -0.0 30 | 7.3102357387542725 0.0 -0.1151347 -0.0 31 | 7.610257625579834 0.0 -0.1150064 -0.0 32 | 7.9100182056427 0.0 -0.1148716 -0.0 33 | 8.210245847702026 0.0 -0.1147425 -0.0 34 | 8.510024309158325 0.0 -0.114633 -0.0 35 | 8.810267686843872 0.0 -0.1145177 -0.0 36 | 9.100246667861938 0.0 -0.1144138 -0.0 37 | 9.400258302688599 0.0 -0.1143076 -0.0 38 | 9.7002854347229 0.0 -0.1142038 -0.0 39 | 10.020246982574463 0.0 -0.1141065 -0.0 40 | 10.320266962051392 0.0 -0.1140173 -0.0 41 | 10.62025499343872 0.0 -0.1139301 -0.0 42 | 10.91999888420105 0.0 -0.1138456 -0.0 43 | 11.210259675979614 0.0 -0.1137668 -0.0 44 | 11.510013341903687 0.0 -0.1136986 -0.0 45 | 11.810246706008911 0.0 -0.1136153 -0.0 46 | 12.110260725021362 0.0 -0.1135521 -0.0 47 | 12.410250902175903 0.0 -0.1134853 -0.0 48 | 12.710252285003662 0.0 -0.113409 -0.0 49 | 13.010310888290405 0.0 -0.1133552 -0.0 50 | 13.310295820236206 0.0 -0.1132976 -0.0 51 | 13.610251426696777 0.0 -0.1132256 -0.0 52 | 13.910253524780273 0.0 -0.1131713 -0.0 53 | 14.230010509490967 0.0 -0.113122 -0.0 54 | 14.53025484085083 0.0 -0.1130669 -0.0 55 | 14.830280542373657 0.0 -0.1130156 -0.0 56 | 15.130251407623291 0.0 -0.1129696 -0.0 57 | 15.43024230003357 0.0 -0.112925 -0.0 58 | 15.730242013931274 0.0 -0.1128763 -0.0 59 | 16.030245542526245 0.0 -0.1128372 -0.0 60 | 16.33024501800537 0.0 -0.1127879 -0.0 61 | 16.630249977111816 0.0 -0.1127529 -0.0 62 | 16.93025302886963 0.0 -0.1127277 -0.0 63 | 17.23024892807007 0.0 -0.1126727 -0.0 64 | 17.53025460243225 0.0 -0.1126411 -0.0 65 | 17.83025360107422 0.0 -0.1126107 -0.0 66 | 18.15025520324707 0.0 -0.1125685 -0.0 67 | 18.46025586128235 0.0 -0.1125294 -0.0 68 | 18.770203113555908 0.0 -0.1125101 -0.0 69 | 19.070257663726807 0.0 -0.1124723 -0.0 70 | 19.370251893997192 0.0 -0.1124391 -0.0 71 | 19.670283317565918 0.0 -0.1124087 -0.0 72 | 19.97026538848877 0.0 -0.1123926 -0.0 73 | 20.270249128341675 0.0 -0.1123535 -0.0 74 | 20.570253610610962 0.0 -0.1123355 -0.0 75 | 20.87025213241577 0.0 -0.1123072 -0.0 76 | 21.16026282310486 0.0 -0.1122803 -0.0 77 | 21.46025013923645 0.0 -0.1122631 -0.0 78 | 21.760249614715576 0.0 -0.1122525 -0.0 79 | 22.060255765914917 0.0 -0.112221 -0.0 80 | 22.360240697860718 0.0 -0.1121995 -0.0 81 | 22.65025496482849 0.0 -0.1121608 -0.0 82 | 22.950287103652954 0.0 -0.1121489 -0.0 83 | 23.250247716903687 0.0 -0.112128 -0.0 84 | 23.55008554458618 0.0 -0.1121204 -0.0 85 | 23.83025336265564 0.0 -0.1120975 -0.0 86 | 24.13018012046814 0.0 -0.1120758 -0.0 87 | 24.429991483688354 0.0 -0.1120492 -0.0 88 | 24.710257291793823 0.0 -0.1120382 -0.0 89 | 25.00024724006653 0.0 -0.1120362 -0.0 90 | 25.300263166427612 0.0 -0.1120016 -0.0 91 | 25.60023808479309 0.0 -0.1120004 -0.0 92 | 25.900246381759644 0.0 -0.1119869 -0.0 93 | 26.210254192352295 0.0 -0.111963 -0.0 94 | 26.500263452529907 0.0 -0.1119385 -0.0 95 | 26.800249576568604 0.0 -0.1119343 -0.0 96 | 27.10025453567505 0.0 -0.111923 -0.0 97 | 27.400326013565063 0.0 -0.1119061 -0.0 98 | 27.670246362686157 0.0 -0.1118893 -0.0 99 | 27.970250606536865 0.0 -0.1118762 -0.0 100 | 28.27025270462036 0.0 -0.111848 -0.0 101 | 28.569989442825317 0.0 -0.1118429 -0.0 102 | 28.850252628326416 0.0 -0.1118362 -0.0 103 | 29.140254020690918 0.0 -0.1118333 -0.0 104 | 29.440249919891357 0.0 -0.1118223 -0.0 105 | 29.75003981590271 0.0 -0.1118033 -0.0 106 | 30.04024362564087 0.0 -0.111782 -0.0 107 | 30.35024857521057 0.0 -0.1117748 -0.0 108 | 30.650249481201172 0.0 -0.1117718 -0.0 109 | 30.940248012542725 0.0 -0.1117424 -0.0 110 | 31.240249633789062 0.0 -0.1117475 -0.0 111 | 31.540260076522827 0.0 -0.1117369 -0.0 112 | 31.840240955352783 0.0 -0.1117222 -0.0 113 | 32.14025044441223 0.0 -0.1116994 -0.0 114 | 32.4402973651886 0.0 -0.1116961 -0.0 115 | 32.71025228500366 0.0 -0.1116759 -0.0 116 | 33.010255098342896 0.0 -0.1116645 -0.0 117 | 33.320279359817505 0.0 -0.1116565 -0.0 118 | 33.60999011993408 0.0 -0.1116511 -0.0 119 | 33.890252113342285 0.0 -0.1116409 -0.0 120 | 34.19024872779846 0.0 -0.1116434 -0.0 121 | 34.49025535583496 0.0 -0.1116442 -0.0 122 | 34.79003953933716 0.0 -0.1116461 -0.0 123 | 35.08027696609497 0.0 -0.1116363 -0.0 124 | 35.39024901390076 0.0 -0.1116225 -0.0 125 | 35.69025015830994 0.0 -0.1116069 -0.0 126 | 35.990243434906006 0.0 -0.1116022 -0.0 127 | 36.29025602340698 0.0 -0.1116043 -0.0 128 | 36.59869933128357 0.0 -0.111585 -0.0 129 | 36.906176805496216 0.0 -0.1115816 -0.0 130 | 37.21307182312012 0.0 -0.1115601 -0.0 131 | 37.512874364852905 0.0 -0.1115614 -0.0 132 | 37.84292411804199 0.0 -0.1115513 -0.0 133 | 38.12008309364319 0.0 -0.1115499 -0.0 134 | 38.40042424201965 0.0 -0.1115324 -0.0 135 | 38.71032166481018 0.0 -0.1115526 -0.0 136 | 39.030441999435425 0.0 -0.1115169 -0.0 137 | 39.34017491340637 0.0 -0.1115151 -0.0 138 | 39.660216331481934 0.0 -0.111505 -0.0 139 | 39.970176458358765 0.0 -0.1115058 -0.0 140 | 40.30041575431824 0.0 -0.1114935 -0.0 141 | 40.61038684844971 0.0 -0.1114983 -0.0 142 | 40.92041015625 0.0 -0.1114823 -0.0 143 | 41.21042799949646 0.0 -0.1114836 -0.0 144 | 41.51044058799744 0.0 -0.1114642 -0.0 145 | 41.800442934036255 0.0 -0.1114591 -0.0 146 | 42.120182275772095 0.0 -0.1114667 -0.0 147 | 42.49017000198364 0.0 -0.1114562 -0.0 148 | 42.790194034576416 0.0 -0.1114482 -0.0 149 | 43.10018444061279 0.0 -0.1114528 -0.0 150 | 43.4101927280426 0.0 -0.1114242 -0.0 151 | 43.710333585739136 0.0 -0.1114288 -0.0 152 | 44.00043177604675 0.0 -0.1114174 -0.0 153 | 44.300222635269165 0.0 -0.1114133 -0.0 154 | 44.61044788360596 0.0 -0.1114141 -0.0 155 | 44.9004340171814 0.0 -0.11142 -0.0 156 | 45.210163593292236 0.0 -0.1113897 -0.0 157 | 45.54016375541687 0.0 -0.111388 -0.0 158 | 45.83017301559448 0.0 -0.1113977 -0.0 159 | 46.11018681526184 0.0 -0.1113922 -0.0 160 | 46.400413274765015 0.0 -0.1113859 -0.0 161 | 46.71046423912048 0.0 -0.1113893 -0.0 162 | 47.000205516815186 0.0 -0.1113602 -0.0 163 | 47.31040072441101 0.0 -0.1113876 -0.0 164 | 47.600443601608276 0.0 -0.1113648 -0.0 165 | 47.89038014411926 0.0 -0.1113627 -0.0 166 | 48.18962025642395 0.0 -0.1113569 -0.0 167 | 48.46970725059509 0.0 -0.1113425 -0.0 168 | 48.75969910621643 0.0 -0.1113531 -0.0 169 | 49.06968140602112 0.0 -0.1113374 -0.0 170 | 49.36966037750244 0.0 -0.1113295 -0.0 171 | 49.66966152191162 0.0 -0.1113321 -0.0 172 | 49.94970726966858 0.0 -0.1113316 -0.0 173 | 50.24968385696411 0.0 -0.1113177 -0.0 174 | 50.539658308029175 0.0 -0.1113072 -0.0 175 | 50.84968852996826 0.0 -0.1113034 -0.0 176 | 51.15945792198181 0.0 -0.1113126 -0.0 177 | 51.47968554496765 0.0 -0.1112992 -0.0 178 | 51.75274896621704 0.0 -0.1112919 -0.0 179 | 52.04804015159607 0.0 -0.1112967 -0.0 180 | 52.35374426841736 0.0 -0.1112883 -0.0 181 | 52.66398096084595 0.0 -0.1112735 -0.0 182 | 52.963974714279175 0.0 -0.111276 -0.0 183 | 53.26375675201416 0.0 -0.1112799 -0.0 184 | 53.56370258331299 0.0 -0.1112593 -0.0 185 | 53.85370635986328 0.0 -0.1112647 -0.0 186 | 54.13370323181152 0.0 -0.1112626 -0.0 187 | 54.42370653152466 0.0 -0.1112659 -0.0 188 | 54.72461199760437 0.0 -0.1112566 -0.0 189 | 55.024600982666016 0.0 -0.111257 -0.0 190 | 55.32447338104248 0.0 -0.1112508 -0.0 191 | 55.624603271484375 0.0 -0.1112449 -0.0 192 | 55.92458653450012 0.0 -0.1112486 -0.0 193 | 56.214619398117065 0.0 -0.1112348 -0.0 194 | 56.50462603569031 0.0 -0.1111869 -0.0 195 | 56.804580211639404 0.0 -0.1112264 -0.0 196 | 57.094634771347046 0.0 -0.1112095 -0.0 197 | 57.39462995529175 0.0 -0.1112061 -0.0 198 | 57.69461965560913 0.0 -0.111204 -0.0 199 | 57.99462890625 0.0 -0.1111977 -0.0 200 | 58.29461860656738 0.0 -0.1111922 -0.0 201 | 58.59116554260254 0.0 -0.1112044 -0.0 202 | 58.89244031906128 0.0 -0.1111901 -0.0 203 | 59.172436475753784 0.0 -0.1111977 -0.0 204 | 59.4822256565094 0.0 -0.1111918 -0.0 205 | 59.79248523712158 0.0 -0.111183 -0.0 206 | 60.08246159553528 0.0 -0.1111939 -0.0 207 | 60.38223576545715 0.0 -0.1111737 -0.0 208 | 60.712260484695435 0.0 -0.1111708 -0.0 209 | 61.00229096412659 0.0 -0.1111817 -0.0 210 | 61.30224347114563 0.0 -0.1111649 -0.0 211 | 61.62243151664734 0.0 -0.111161 -0.0 212 | 61.95244097709656 0.0 -0.1111707 -0.0 213 | 62.262471199035645 0.0 -0.1111561 -0.0 214 | 62.56248354911804 0.0 -0.1111548 -0.0 215 | 62.872451305389404 0.0 -0.1111523 -0.0 216 | 63.17222619056702 0.0 -0.1111325 -0.0 217 | 63.472217321395874 0.0 -0.1111509 -0.0 218 | 63.78260111808777 0.0 -0.1111438 -0.0 219 | 64.08260107040405 0.0 -0.1111485 -0.0 220 | 64.37262487411499 0.0 -0.1111355 -0.0 221 | 64.69261288642883 0.0 -0.1111236 -0.0 222 | 64.99260187149048 0.0 -0.1111186 -0.0 223 | 65.28281497955322 0.0 -0.1111228 -0.0 224 | 65.5728371143341 0.0 -0.111111 -0.0 225 | 65.88281512260437 0.0 -0.1111064 -0.0 226 | 66.20285987854004 0.0 -0.1111111 -0.0 227 | 66.49260020256042 0.0 -0.1111102 -0.0 228 | 66.84264302253723 0.0 -0.1110971 -0.0 229 | 67.12286567687988 0.0 -0.1110891 -0.0 230 | 67.43289995193481 0.0 -0.1110949 -0.0 231 | 67.71264386177063 0.0 -0.1111009 -0.0 232 | 68.02285575866699 0.0 -0.1110895 -0.0 233 | 68.36266994476318 0.0 -0.111068 -0.0 234 | 68.66277194023132 0.0 -0.1110874 -0.0 235 | 68.93675184249878 0.0 -0.1110701 -0.0 236 | 69.24813222885132 0.0 -0.111074 -0.0 237 | 69.55146765708923 0.0 -0.1110693 -0.0 238 | 69.861487865448 0.0 -0.1110693 -0.0 239 | 70.1715018749237 0.0 -0.1110554 -0.0 240 | 70.49176168441772 0.0 -0.1110592 -0.0 241 | 70.79176139831543 0.0 -0.1110601 -0.0 242 | 71.0915174484253 0.0 -0.1110629 -0.0 243 | 71.38176655769348 0.0 -0.1110517 -0.0 244 | 71.68175625801086 0.0 -0.1110491 -0.0 245 | 71.99176573753357 0.0 -0.1110495 -0.0 246 | 72.2917549610138 0.0 -0.1110331 -0.0 247 | 72.59177732467651 0.0 -0.111036 -0.0 248 | 72.89175844192505 0.0 -0.1110407 -0.0 249 | 73.20176219940186 0.0 -0.1110336 -0.0 250 | 73.50175714492798 0.0 -0.1110343 -0.0 251 | 73.80176115036011 0.0 -0.1110286 -0.0 252 | 74.12176156044006 0.0 -0.1110201 -0.0 253 | 74.41170763969421 0.0 -0.1110323 -0.0 254 | 74.7117555141449 0.0 -0.1110188 -0.0 255 | 75.01172685623169 0.0 -0.1110159 -0.0 256 | 75.33175706863403 0.0 -0.1110104 -0.0 257 | 75.6417543888092 0.0 -0.111007 -0.0 258 | 75.94175100326538 0.0 -0.111012 -0.0 259 | 76.2417643070221 0.0 -0.1109996 -0.0 260 | 76.54152941703796 0.0 -0.1110007 -0.0 261 | 76.84176135063171 0.0 -0.1109881 -0.0 262 | 77.17176127433777 0.0 -0.1109843 -0.0 263 | 77.47178030014038 0.0 -0.1109889 -0.0 264 | 77.77176022529602 0.0 -0.1109785 -0.0 265 | 78.07176065444946 0.0 -0.110986 -0.0 266 | 78.37151622772217 0.0 -0.1109827 -0.0 267 | 78.65175938606262 0.0 -0.1109847 -0.0 268 | 78.9517593383789 0.0 -0.1109587 -0.0 269 | 79.25176215171814 0.0 -0.1109797 -0.0 270 | 79.55177569389343 0.0 -0.1109557 -0.0 271 | 79.84179472923279 0.0 -0.1109612 -0.0 272 | 80.12175869941711 0.0 -0.1109603 -0.0 273 | 80.43168497085571 0.0 -0.1109679 -0.0 274 | 80.72175931930542 0.0 -0.1109658 -0.0 275 | 81.03175473213196 0.0 -0.1109532 -0.0 276 | 81.3317551612854 0.0 -0.1109397 -0.0 277 | 81.63175868988037 0.0 -0.1109507 -0.0 278 | 81.93177032470703 0.0 -0.1109444 -0.0 279 | 82.22178196907043 0.0 -0.1109359 -0.0 280 | 82.52175521850586 0.0 -0.1109444 -0.0 281 | 82.82175755500793 0.0 -0.1109406 -0.0 282 | 83.11176180839539 0.0 -0.1109499 -0.0 283 | 83.41149973869324 0.0 -0.1109355 -0.0 284 | 83.6917622089386 0.0 -0.1109275 -0.0 285 | 83.98176217079163 0.0 -0.1109276 -0.0 286 | 84.28175139427185 0.0 -0.1109224 -0.0 287 | 84.5817608833313 0.0 -0.1109233 -0.0 288 | 84.88161444664001 0.0 -0.1109301 -0.0 289 | 85.16175031661987 0.0 -0.1109161 -0.0 290 | 85.45151543617249 0.0 -0.1109169 -0.0 291 | 85.75175666809082 0.0 -0.1109132 -0.0 292 | 86.05152535438538 0.0 -0.1109066 -0.0 293 | 86.34176230430603 0.0 -0.1109119 -0.0 294 | 86.64176630973816 0.0 -0.1109167 -0.0 295 | 86.94154787063599 0.0 -0.1108905 -0.0 296 | 87.24173712730408 0.0 -0.1108926 -0.0 297 | 87.54175114631653 0.0 -0.1108867 -0.0 298 | 87.84173607826233 0.0 -0.1108914 -0.0 299 | 88.15175676345825 0.0 -0.1108918 -0.0 300 | 88.4615170955658 0.0 -0.1108955 -0.0 301 | 88.73175930976868 0.0 -0.1108934 -0.0 302 | 89.02176332473755 0.0 -0.1108741 -0.0 303 | 89.32175588607788 0.0 -0.1108724 -0.0 304 | 89.63175535202026 0.0 -0.110891 -0.0 305 | 89.9215521812439 0.0 -0.1108812 -0.0 306 | 90.20176339149475 0.0 -0.1108736 -0.0 307 | 90.51166105270386 0.0 -0.1108644 -0.0 308 | 90.78176856040955 0.0 -0.1108745 -0.0 309 | 91.08175659179688 0.0 -0.1108686 -0.0 310 | 91.38176012039185 0.0 -0.1108421 -0.0 311 | 91.68175220489502 0.0 -0.1108506 -0.0 312 | 92.00175261497498 0.0 -0.110866 -0.0 313 | 92.30176496505737 0.0 -0.1108458 -0.0 314 | 92.59174370765686 0.0 -0.1108531 -0.0 315 | 92.8917624950409 0.0 -0.1108681 -0.0 316 | 93.19173693656921 0.0 -0.1108425 -0.0 317 | 93.49151754379272 0.0 -0.1108635 -0.0 318 | 93.7717616558075 0.0 -0.1108358 -0.0 319 | 94.06176781654358 0.0 -0.1108412 -0.0 320 | 94.36187982559204 0.0 -0.110845 -0.0 321 | 94.66228151321411 0.0 -0.1108476 -0.0 322 | 94.96214175224304 0.0 -0.1108396 -0.0 323 | 95.24226880073547 0.0 -0.1108371 -0.0 324 | 95.53206968307495 0.0 -0.1108483 -0.0 325 | 95.82225584983826 0.0 -0.1108273 -0.0 326 | 96.11228322982788 0.0 -0.1108341 -0.0 327 | 96.4022765159607 0.0 -0.1108374 -0.0 328 | 96.70227336883545 0.0 -0.1108223 -0.0 329 | 97.00205993652344 0.0 -0.1108337 -0.0 330 | 97.28227138519287 0.0 -0.1108282 -0.0 331 | 97.58227896690369 0.0 -0.1108164 -0.0 332 | 97.87201309204102 0.0 -0.1108076 -0.0 333 | 98.16226887702942 0.0 -0.1108075 -0.0 334 | 98.46228313446045 0.0 -0.1108067 -0.0 335 | 98.77228355407715 0.0 -0.1108063 -0.0 336 | 99.07230877876282 0.0 -0.1108003 -0.0 337 | 99.37227773666382 0.0 -0.1107971 -0.0 338 | 99.69228029251099 0.0 -0.1108025 -0.0 339 | 99.99214267730713 0.0 -0.1107949 -0.0 340 | 100.28228545188904 0.0 -0.1107827 -0.0 341 | 100.58202838897705 0.0 -0.1107991 -0.0 342 | 100.8622817993164 0.0 -0.1107933 -0.0 343 | 101.18223261833191 0.0 -0.1107907 -0.0 344 | 101.48227548599243 0.0 -0.1107954 -0.0 345 | 101.78227686882019 0.0 -0.1107773 -0.0 346 | 102.07228779792786 0.0 -0.1107693 -0.0 347 | 102.3722677230835 0.0 -0.110773 -0.0 348 | 102.67228198051453 0.0 -0.1107794 -0.0 349 | 102.97212886810303 0.0 -0.1107786 -0.0 350 | 103.27227354049683 0.0 -0.1107629 -0.0 351 | 103.57226586341858 0.0 -0.1107714 -0.0 352 | 103.88227391242981 0.0 -0.1107713 -0.0 353 | 104.17227697372437 0.0 -0.1107722 -0.0 354 | 104.47227549552917 0.0 -0.1107642 -0.0 355 | 104.77227425575256 0.0 -0.1107612 -0.0 356 | 105.0722804069519 0.0 -0.1107567 -0.0 357 | 105.37228465080261 0.0 -0.1107424 -0.0 358 | 105.68226599693298 0.0 -0.1107542 -0.0 359 | 105.98225045204163 0.0 -0.1107508 -0.0 360 | 106.27227759361267 0.0 -0.1107513 -0.0 361 | 106.57228064537048 0.0 -0.1107389 -0.0 362 | 106.89227175712585 0.0 -0.1107491 -0.0 363 | 107.20227432250977 0.0 -0.1107306 -0.0 364 | 107.5122721195221 0.0 -0.1107289 -0.0 365 | 107.81227946281433 0.0 -0.1107419 -0.0 366 | 108.1022641658783 0.0 -0.110739 -0.0 367 | 108.40227365493774 0.0 -0.1107273 -0.0 368 | 108.7022659778595 0.0 -0.110723 -0.0 369 | 109.00227308273315 0.0 -0.1107294 -0.0 370 | 109.30228662490845 0.0 -0.1107193 -0.0 371 | 109.60227704048157 0.0 -0.1107323 -0.0 372 | 109.90226554870605 0.0 -0.1107306 -0.0 373 | 110.20227646827698 0.0 -0.1107285 -0.0 374 | 110.50227284431458 0.0 -0.110713 -0.0 375 | 110.80227828025818 0.0 -0.1107121 -0.0 376 | 111.12227368354797 0.0 -0.1107197 -0.0 377 | 111.4222617149353 0.0 -0.110702 -0.0 378 | 111.71228218078613 0.0 -0.1107084 -0.0 379 | 112.00227189064026 0.0 -0.1107118 -0.0 380 | 112.3022952079773 0.0 -0.1107036 -0.0 381 | 112.60227251052856 0.0 -0.1107057 -0.0 382 | 112.90227198600769 0.0 -0.1106927 -0.0 383 | 113.20227599143982 0.0 -0.110702 -0.0 384 | 113.50228810310364 0.0 -0.1107019 -0.0 385 | 113.80227732658386 0.0 -0.1106889 -0.0 386 | 114.10227274894714 0.0 -0.1106818 -0.0 387 | 114.42227387428284 0.0 -0.1106981 -0.0 388 | 114.72227263450623 0.0 -0.110678 -0.0 389 | 115.03226399421692 0.0 -0.1106873 -0.0 390 | 115.34227204322815 0.0 -0.1106852 -0.0 391 | 115.64223146438599 0.0 -0.1106792 -0.0 392 | 115.93980526924133 0.0 -0.1106763 -0.0 393 | 116.26535153388977 0.0 -0.1106839 -0.0 394 | 116.5697340965271 0.0 -0.1106755 -0.0 395 | 116.87727761268616 0.0 -0.1106649 -0.0 396 | 117.18728804588318 0.0 -0.1106658 -0.0 397 | 398 | 399 | -------------------------------------------------------------------------------- /examples/SolarReference/dat/GaAs/gaas-ref-tracking.dat: -------------------------------------------------------------------------------- 1 | *! QVisaDataObject v1.1 2 | *! hash 2ffb56f 3 | 4 | #! __data__ 0dd389f 5 | #! __type__ pv-voc 6 | #! __desc__ gaas-voc-conv 7 | t Voc Ioc 8 | 0.6599934101104736 0.3 0.1102532 9 | 1.4801833629608154 0.305 0.1102363 10 | 2.2902233600616455 0.31 0.1102309 11 | 3.1100406646728516 0.315 0.1102292 12 | 3.9001967906951904 0.32 0.1102179 13 | 4.710177421569824 0.325 0.1102273 14 | 5.499981641769409 0.33 0.1102108 15 | 6.290037631988525 0.335 0.1102103 16 | 7.090190172195435 0.34 0.1101952 17 | 7.880227327346802 0.345 0.1101956 18 | 8.690027713775635 0.35 0.110188 19 | 9.480245590209961 0.355 0.1101876 20 | 10.280173063278198 0.36 0.1101838 21 | 11.079981088638306 0.365 0.110172 22 | 11.910179853439331 0.37 0.1101645 23 | 12.700184106826782 0.375 0.1101631 24 | 13.500189542770386 0.38 0.1101665 25 | 14.309985160827637 0.385 0.1101505 26 | 15.080188512802124 0.39 0.1101476 27 | 15.879992008209229 0.395 0.1101425 28 | 16.660212993621826 0.4 0.110151 29 | 17.459991693496704 0.405 0.1101337 30 | 18.270208835601807 0.41 0.1101215 31 | 19.069980144500732 0.415 0.110122 32 | 19.860223054885864 0.42 0.1101035 33 | 20.690056562423706 0.425 0.1101113 34 | 21.510186672210693 0.43 0.1100988 35 | 22.31023359298706 0.435 0.110103 36 | 23.110194206237793 0.44 0.1100971 37 | 23.899962663650513 0.445 0.1100799 38 | 24.670223712921143 0.45 0.1100853 39 | 25.46022891998291 0.455 0.110073 40 | 26.2699875831604 0.46 0.1100718 41 | 27.080168962478638 0.465 0.1100781 42 | 27.879978895187378 0.47 0.1100563 43 | 28.680197715759277 0.475 0.1100562 44 | 29.480217456817627 0.48 0.1100479 45 | 30.27021837234497 0.485 0.1100546 46 | 31.07014775276184 0.49 0.1100407 47 | 31.880174160003662 0.495 0.1100412 48 | 32.66102719306946 0.5 0.1100311 49 | 33.471060276031494 0.505 0.1100125 50 | 34.280914068222046 0.51 0.1100223 51 | 35.091063022613525 0.515 0.1100201 52 | 35.88105797767639 0.52 0.1100084 53 | 36.67114210128784 0.525 0.1100037 54 | 37.44105672836304 0.53 0.1099949 55 | 38.23105263710022 0.535 0.1099882 56 | 39.04112505912781 0.54 0.1099755 57 | 39.8110556602478 0.545 0.1099676 58 | 40.610907316207886 0.55 0.1099718 59 | 41.43094515800476 0.555 0.1099507 60 | 42.24109768867493 0.56 0.1099478 61 | 43.041038036346436 0.565 0.1099452 62 | 43.84110355377197 0.57 0.1099335 63 | 44.67106342315674 0.575 0.1099352 64 | 45.47085428237915 0.58 0.1099129 65 | 46.25104284286499 0.585 0.1099069 66 | 47.050867319107056 0.59 0.1098922 67 | 47.86103391647339 0.595 0.1098817 68 | 48.67110347747803 0.6 0.1098649 69 | 49.49110174179077 0.605 0.1098556 70 | 50.30109643936157 0.61 0.1098543 71 | 51.111043214797974 0.615 0.1098286 72 | 51.93105173110962 0.62 0.1098088 73 | 52.72108507156372 0.625 0.1098092 74 | 53.52089834213257 0.63 0.1097824 75 | 54.3210608959198 0.635 0.1097705 76 | 55.12104320526123 0.64 0.1097444 77 | 55.93109583854675 0.645 0.109715 78 | 56.741032123565674 0.65 0.1096978 79 | 57.56087350845337 0.65495 0.1096755 80 | 58.37090444564819 0.6599 0.1096473 81 | 59.17085146903992 0.66485 0.1096157 82 | 59.99105882644653 0.6698 0.1095858 83 | 60.81086087226868 0.67475 0.1095479 84 | 61.611058950424194 0.6797 0.1095109 85 | 62.41091251373291 0.68465 0.1094721 86 | 63.22104501724243 0.6896 0.1094397 87 | 64.02105355262756 0.69455 0.1093908 88 | 64.82104516029358 0.6995 0.1093506 89 | 65.62083959579468 0.70445 0.1092839 90 | 66.42085528373718 0.7094 0.1091704 91 | 67.22094392776489 0.71435 0.1091624 92 | 68.02104091644287 0.7193 0.1090883 93 | 68.82106137275696 0.72425 0.1090188 94 | 69.6210618019104 0.7292 0.1089355 95 | 70.4209291934967 0.73415 0.1088539 96 | 71.2310438156128 0.7391 0.1087432 97 | 72.05104422569275 0.74405 0.108664 98 | 72.86105251312256 0.749 0.1085365 99 | 73.67100691795349 0.7539 0.1084111 100 | 74.45103931427002 0.7588 0.108305 101 | 75.26102828979492 0.7637 0.108151 102 | 76.06104183197021 0.7686 0.1080221 103 | 76.88102841377258 0.7735 0.1077915 104 | 77.69103717803955 0.7784 0.1076438 105 | 78.49094223976135 0.7833 0.1074321 106 | 79.29087686538696 0.78815 0.1072806 107 | 80.11103987693787 0.793 0.107015 108 | 80.93105101585388 0.79785 0.1067807 109 | 81.73104214668274 0.8027 0.1065112 110 | 82.54104828834534 0.80755 0.1062507 111 | 83.35086846351624 0.81235 0.1059329 112 | 84.16086745262146 0.81715 0.105568 113 | 84.96104049682617 0.82195 0.1052326 114 | 85.77104377746582 0.8267 0.1047924 115 | 86.57090330123901 0.83145 0.1043626 116 | 87.37109518051147 0.8362 0.1038937 117 | 88.1808614730835 0.8409 0.103435 118 | 88.98110508918762 0.8456 0.1028736 119 | 89.79103660583496 0.85025 0.1022321 120 | 90.61104154586792 0.8549 0.1017086 121 | 91.41103935241699 0.8595 0.1010263 122 | 92.21104764938354 0.8641 0.1002093 123 | 93.07110381126404 0.86865 0.09964447 124 | 93.88090682029724 0.87315 0.09873389 125 | 94.68091082572937 0.87765 0.09779369 126 | 95.49085450172424 0.8821 0.09674412 127 | 96.29106020927429 0.8865 0.09567333 128 | 97.0908555984497 0.89085 0.09450293 129 | 97.87086534500122 0.89515 0.09331287 130 | 98.69085884094238 0.8994 0.09200494 131 | 99.50104355812073 0.90355 0.09056676 132 | 100.3111023902893 0.90765 0.08919559 133 | 101.11094164848328 0.9117 0.0876722 134 | 101.9208652973175 0.9157 0.08605614 135 | 102.7308669090271 0.9196 0.08438691 136 | 103.53106451034546 0.92345 0.08264343 137 | 104.34104013442993 0.9272 0.08082914 138 | 105.15104484558105 0.93085 0.07899249 139 | 105.96085476875305 0.93445 0.07706953 140 | 106.74103856086731 0.93795 0.07516874 141 | 107.55094766616821 0.94135 0.07315043 142 | 108.360848903656 0.94465 0.07117051 143 | 109.17104387283325 0.9479 0.06912036 144 | 109.98085927963257 0.95105 0.06708216 145 | 110.76103973388672 0.9541 0.06500902 146 | 111.57104992866516 0.95705 0.06296847 147 | 112.37104558944702 0.9599 0.06091466 148 | 113.17086338996887 0.96265 0.05886517 149 | 113.98109674453735 0.9653 0.0568612 150 | 114.76104784011841 0.9679 0.05485361 151 | 115.57104158401489 0.9704 0.05286934 152 | 116.38106226921082 0.9728 0.05094817 153 | 117.19102931022644 0.9751 0.04903798 154 | 118.00106644630432 0.9773 0.04718084 155 | 118.81091141700745 0.97945 0.04535519 156 | 119.62088918685913 0.9815 0.04358861 157 | 120.41104388237 0.9835 0.04183433 158 | 121.21085381507874 0.9854 0.04011578 159 | 122.01105403900146 0.9872 0.03849311 160 | 122.82088685035706 0.98895 0.03688007 161 | 123.62103748321533 0.9906 0.0353925 162 | 124.42104411125183 0.9922 0.03388694 163 | 125.23084664344788 0.99375 0.0324147 164 | 126.03104829788208 0.9952 0.03105291 165 | 126.8510594367981 0.9966 0.02971572 166 | 127.67106056213379 0.99795 0.0283821 167 | 128.47106075286865 0.99925 0.02714018 168 | 129.27105712890625 1.0005 0.02589243 169 | 130.07086086273193 1.00165 0.02476426 170 | 130.88087630271912 1.00275 0.02366964 171 | 131.68090796470642 1.0038 0.02263575 172 | 132.50086879730225 1.00485 0.02155882 173 | 133.3010482788086 1.00585 0.02054426 174 | 134.10109972953796 1.0068 0.0195926 175 | 134.90106081962585 1.0077 0.01868435 176 | 135.7010576725006 1.00855 0.0178003 177 | 136.51105403900146 1.00935 0.01698466 178 | 137.3108606338501 1.0101 0.01619919 179 | 138.11091256141663 1.01085 0.01541842 180 | 138.9210753440857 1.01155 0.01470051 181 | 139.7208514213562 1.0122 0.01400939 182 | 140.53087496757507 1.01285 0.01331851 183 | 141.33084988594055 1.01345 0.01270422 184 | 142.13105416297913 1.01405 0.01205429 185 | 142.93105840682983 1.0146 0.01150365 186 | 143.7310390472412 1.0151 0.01095294 187 | 144.61103892326355 1.0156 0.01044192 188 | 145.62100100517273 1.01605 0.009937513 189 | 146.43106341362 1.0165 0.009456701 190 | 147.23106336593628 1.01695 0.008978837 191 | 148.03104734420776 1.01735 0.008565604 192 | 148.83104753494263 1.01775 0.008126971 193 | 149.64110112190247 1.0181 0.007754012 194 | 150.4510622024536 1.01845 0.0073803 195 | 151.26106190681458 1.0188 0.007006698 196 | 152.06104707717896 1.0191 0.006671168 197 | 152.86105847358704 1.0194 0.006334345 198 | 153.65103721618652 1.0197 0.006033488 199 | 154.45104598999023 1.01995 0.005734215 200 | 155.26088666915894 1.0202 0.005469242 201 | 156.0810477733612 1.02045 0.005205201 202 | 156.88105988502502 1.0207 0.0049438 203 | 157.70086908340454 1.0209 0.004716454 204 | 158.5010495185852 1.0211 0.004492692 205 | 159.31084179878235 1.0213 0.004259964 206 | 160.10085654258728 1.0215 0.004035148 207 | 160.90091252326965 1.0217 0.003845224 208 | 161.71104550361633 1.02185 0.003657541 209 | 162.52090311050415 1.022 0.003503563 210 | 163.3310239315033 1.02215 0.003352141 211 | 164.13104391098022 1.0223 0.003165023 212 | 164.93105483055115 1.02245 0.003008512 213 | 165.74086117744446 1.0226 0.002816495 214 | 166.54090547561646 1.02275 0.002667772 215 | 167.35085606575012 1.02285 0.00255317 216 | 168.16089510917664 1.02295 0.002435764 217 | 168.97089338302612 1.02305 0.002320862 218 | 169.78086829185486 1.02315 0.002247261 219 | 170.58087134361267 1.02325 0.002135834 220 | 171.39094734191895 1.02335 0.002021533 221 | 172.19089889526367 1.02345 0.001897699 222 | 172.99105095863342 1.02355 0.001788993 223 | 173.79085516929626 1.02365 0.001665478 224 | 174.60106420516968 1.02375 0.001559405 225 | 175.4809672832489 1.0238 0.001514629 226 | 176.45084524154663 1.02385 0.001440885 227 | 177.45104789733887 1.0239 0.001397558 228 | 178.45109486579895 1.02395 0.001321713 229 | 179.46103882789612 1.024 0.00128356 230 | 180.46087431907654 1.02405 0.001206586 231 | 181.47086429595947 1.0241 0.001165702 232 | 182.4711048603058 1.02415 0.001124676 233 | 183.48357272148132 1.0242 0.001044299 234 | 184.4656319618225 1.02425 0.001014442 235 | 185.52046060562134 1.0243 0.0009378876 236 | 186.5269365310669 1.02435 0.000896927 237 | 187.52791905403137 1.0244 0.0008193676 238 | 188.5110809803009 1.02445 0.00078226 239 | 189.52156949043274 1.0245 0.0007056367 240 | 190.62156987190247 1.02455 0.0006582345 241 | 191.86674976348877 1.0246 0.0005798846 242 | 193.28170728683472 1.02465 0.0005431299 243 | 194.2399880886078 1.0247 0.0005016767 244 | 195.237651348114 1.0247 0.0005019139 245 | 196.25213289260864 1.0247 0.0004939107 246 | 197.3458390235901 1.0247 0.0004912012 247 | 198.37582778930664 1.0247 0.0004918895 248 | 199.37561321258545 1.0247 0.000493666 249 | 200.3756241798401 1.0247 0.0004906018 250 | 201.37582445144653 1.0247 0.0004847418 251 | 202.3858196735382 1.0247 0.0004843526 252 | 203.40562868118286 1.0247 0.000481203 253 | 204.42663168907166 1.0247 0.0004757781 254 | 205.44664120674133 1.0247 0.0004798264 255 | 206.45642352104187 1.0247 0.0004772368 256 | 207.47950100898743 1.0247 0.0004739602 257 | 208.5206298828125 1.0247 0.0004729613 258 | 209.68274927139282 1.0247 0.0004698899 259 | 210.67727398872375 1.0247 0.0004716339 260 | 212.041841506958 1.0247 0.0004710346 261 | 213.11217093467712 1.0247 0.0004683415 262 | 214.41197896003723 1.0247 0.0004651479 263 | 215.57488441467285 1.0247 0.0004635467 264 | 216.8324522972107 1.0247 0.0004598041 265 | 218.1073603630066 1.0247 0.0004581312 266 | 219.0435552597046 1.0247 0.0004558758 267 | 220.05378770828247 1.0247 0.0004517538 268 | 221.06355953216553 1.0247 0.0004531718 269 | 222.01353430747986 1.0247 0.0004456502 270 | 223.24354100227356 1.0247 0.00045178 271 | 224.26372289657593 1.0247 0.0004556457 272 | 225.2936098575592 1.0247 0.0004482155 273 | 226.303555727005 1.0247 0.0004459779 274 | 227.34361791610718 1.0247 0.0004406962 275 | 228.36351704597473 1.0247 0.00044653 276 | 229.26351308822632 1.0247 0.000444074 277 | 230.33373188972473 1.0247 0.0004406577 278 | 231.3237500190735 1.0247 0.0004402965 279 | 232.36371040344238 1.0247 0.0004373467 280 | 233.36354613304138 1.0247 0.0004405297 281 | 234.37372589111328 1.0247 0.0004311262 282 | 235.37366342544556 1.0247 0.0004338805 283 | 236.39373564720154 1.0247 0.0004316392 284 | 237.39377689361572 1.0247 0.0004308845 285 | 238.41357517242432 1.0247 0.0004292011 286 | 239.423752784729 1.0247 0.0004267063 287 | 240.42372512817383 1.0247 0.0004280356 288 | 241.4335334300995 1.0247 0.0004224828 289 | 242.46353268623352 1.0247 0.0004199773 290 | 243.53351259231567 1.0247 0.0004256123 291 | 244.53476643562317 1.0247 0.0004196021 292 | 245.5574517250061 1.0247 0.000418369 293 | 294 | 295 | #! __data__ a0f4bfd 296 | #! __type__ pv-mpp 297 | #! __desc__ gaas-mpp-conv 298 | t Vmpp Impp Pmpp 299 | 1.038266658782959 0.3 0.1097906 0.032937179999999996 300 | 2.1682610511779785 0.305 0.1097793 0.0334826865 301 | 3.298236131668091 0.31 0.1097869 0.034033939 302 | 4.418256759643555 0.315 0.1097714 0.034577991 303 | 5.558041334152222 0.32 0.1097713 0.035126816 304 | 6.668257236480713 0.325 0.1097651 0.035673657500000004 305 | 7.768070220947266 0.33 0.1097692 0.036223836 306 | 8.908069849014282 0.335 0.1097621 0.036770303500000004 307 | 10.028271913528442 0.34 0.1097605 0.03731857 308 | 11.148083209991455 0.345 0.1097486 0.037863267 309 | 12.288278341293335 0.35 0.1097495 0.038412325 310 | 13.408163785934448 0.355 0.1097529 0.038962279499999995 311 | 14.508152961730957 0.36 0.1097381 0.039505716 312 | 15.618316411972046 0.365 0.1097478 0.040057947 313 | 16.748136281967163 0.37 0.1097339 0.040601543 314 | 17.878122091293335 0.375 0.109736 0.041151 315 | 19.008336305618286 0.38 0.1097284 0.041696792 316 | 20.108062028884888 0.385 0.1097326 0.042247051 317 | 21.23829960823059 0.39 0.1097301 0.042794739 318 | 22.35811948776245 0.395 0.1097297 0.0433432315 319 | 23.48829960823059 0.4 0.1097272 0.04389088 320 | 24.618141889572144 0.40495 0.1097284 0.04443451558 321 | 25.748257875442505 0.40995 0.1097175 0.044978689125 322 | 26.878194093704224 0.41495 0.109715 0.045526239249999996 323 | 28.00812816619873 0.41995 0.1097116 0.04607338642 324 | 29.128268718719482 0.42495 0.1097023 0.046617992385 325 | 30.25871706008911 0.42995 0.1097153 0.047172093235000004 326 | 31.358699321746826 0.43495 0.1097027 0.047715189365 327 | 32.46869778633118 0.4399 0.1096961 0.048255314390000005 328 | 33.58871364593506 0.4449 0.1097011 0.04880601939 329 | 34.71870255470276 0.44985 0.1097015 0.049349219775 330 | 35.83869743347168 0.4548 0.1096951 0.04988933148 331 | 36.95870566368103 0.4598 0.1096897 0.05043532406 332 | 38.07869839668274 0.4648 0.1096884 0.05098316832 333 | 39.20854449272156 0.4698 0.1096884 0.051531610320000004 334 | 40.3285551071167 0.4748 0.1096825 0.052077251 335 | 41.45868897438049 0.4798 0.10968 0.052624464 336 | 42.58868408203125 0.4848 0.1096804 0.05317305792 337 | 43.7185480594635 0.4898 0.1096799 0.05372121502 338 | 44.8386766910553 0.4948 0.1096779 0.05426862492 339 | 45.96853590011597 0.49975 0.1096699 0.054807532525 340 | 47.098698139190674 0.50475 0.1096593 0.055350531675 341 | 48.21856880187988 0.5097 0.1096568 0.055892070960000005 342 | 49.328532695770264 0.51465 0.1096505 0.056431629825 343 | 50.45855712890625 0.51965 0.1096493 0.056979258745 344 | 51.5786919593811 0.5246 0.1096521 0.057523491659999995 345 | 52.68855619430542 0.52955 0.1096466 0.05806335702999999 346 | 53.8186891078949 0.5345 0.1096416 0.0586034352 347 | 54.91856908798218 0.53945 0.1096396 0.05914508222 348 | 56.02871775627136 0.5444 0.1096349 0.05968523956 349 | 57.148693561553955 0.54935 0.1096353 0.060228152055000005 350 | 58.26850605010986 0.5543 0.109616 0.060760148800000004 351 | 59.37868785858154 0.55925 0.1096147 0.061302020975 352 | 60.50856018066406 0.5642 0.1096063 0.061839874460000006 353 | 61.628543853759766 0.56915 0.1096063 0.06238242564500001 354 | 62.75850868225098 0.57405 0.1095957 0.062913411585 355 | 63.87851119041443 0.579 0.1095891 0.0634520889 356 | 64.9985134601593 0.58395 0.1095869 0.063993270255 357 | 66.11869215965271 0.5889 0.1095776 0.06453024864 358 | 67.2385482788086 0.59385 0.109568 0.06506695679999999 359 | 68.35850119590759 0.5988 0.1095587 0.06560374956 360 | 69.46855449676514 0.6037 0.1095424 0.06613074688 361 | 70.58853507041931 0.60865 0.109531 0.06666604315 362 | 71.7085165977478 0.61355 0.1095285 0.06720121117500001 363 | 72.83858036994934 0.61845 0.1095133 0.067728500385 364 | 73.94871091842651 0.62335 0.1095108 0.06826355718 365 | 75.06870198249817 0.62825 0.1094906 0.06878746945 366 | 76.17850732803345 0.63315 0.1094679 0.069309600885 367 | 77.29868626594543 0.63805 0.109459 0.06984031495 368 | 78.40850615501404 0.6429 0.1094401 0.07035904029000001 369 | 79.53851771354675 0.64775 0.1094212 0.0708775823 370 | 80.65871047973633 0.6526 0.1094005 0.0713947663 371 | 81.77853846549988 0.65745 0.1093736 0.07190767332 372 | 82.89859747886658 0.6623 0.1093382 0.07241468985999999 373 | 84.02870297431946 0.6671 0.1093176 0.07292577096 374 | 85.12863087654114 0.6719 0.1093092 0.07344485148 375 | 86.24857783317566 0.67665 0.1092697 0.07393734250499999 376 | 87.36869382858276 0.6814 0.1092237 0.07442502918 377 | 88.48850512504578 0.68615 0.1092002 0.07492771723 378 | 89.60868787765503 0.6909 0.109175 0.07542900749999999 379 | 90.71865630149841 0.69565 0.1091273 0.075914406245 380 | 91.8396110534668 0.7003 0.1090541 0.07637058623000001 381 | 92.96960997581482 0.705 0.1090242 0.076862061 382 | 94.08945894241333 0.70965 0.1089602 0.07732360593 383 | 95.2196524143219 0.7142 0.1089081 0.07778216501999999 384 | 96.32966923713684 0.71885 0.1088605 0.078254370425 385 | 97.449471950531 0.7234 0.1087923 0.07870034982 386 | 98.56960725784302 0.72785 0.1087195 0.07913148807499999 387 | 99.67942476272583 0.73225 0.1086711 0.079574412975 388 | 100.78942656517029 0.7366 0.1085878 0.07998577348000001 389 | 101.90964460372925 0.7409 0.108501 0.0803883909 390 | 103.01961851119995 0.74515 0.1084207 0.080789684605 391 | 104.1294572353363 0.74935 0.1083062 0.08115925097 392 | 105.23943662643433 0.75355 0.1082207 0.08154970848500001 393 | 106.3594422340393 0.75765 0.1081009 0.081902646885 394 | 107.46962475776672 0.76165 0.1079897 0.082250355005 395 | 108.56946539878845 0.7655 0.1078992 0.0825968376 396 | 109.67961120605469 0.7693 0.1077827 0.08291723110999999 397 | 110.8094732761383 0.77305 0.1076618 0.08322795449 398 | 111.92942762374878 0.77665 0.1075305 0.083513562825 399 | 113.03960490226746 0.78025 0.107387 0.08378870675 400 | 114.14940643310547 0.7839 0.1072658 0.08408566062 401 | 115.24947762489319 0.7873 0.1070894 0.08431148462 402 | 116.35943508148193 0.79065 0.1069439 0.08455519453499999 403 | 117.48950266838074 0.7939 0.1068066 0.08479375974 404 | 118.58946108818054 0.797 0.1066791 0.0850232427 405 | 119.70961141586304 0.7999 0.1065507 0.08522990493 406 | 120.81953239440918 0.80275 0.1062957 0.085328873175 407 | 121.9205973148346 0.80555 0.106121 0.08548577154999999 408 | 123.0514223575592 0.8081 0.1060006 0.08565908486 409 | 124.16141533851624 0.81065 0.1058301 0.08579117056499999 410 | 125.28139185905457 0.8132 0.1056808 0.08593962656000001 411 | 126.37146282196045 0.8155 0.1054931 0.08602962305 412 | 127.49150919914246 0.81755 0.1053752 0.08614949476 413 | 128.6115961074829 0.81965 0.1051723 0.08620447569499999 414 | 129.7115352153778 0.82145 0.1050557 0.086298004765 415 | 130.82160139083862 0.82345 0.1049421 0.086414572245 416 | 131.9325132369995 0.82495 0.10473 0.0863970135 417 | 133.05264711380005 0.8265 0.1046088 0.0864591732 418 | 134.18269300460815 0.82805 0.1045028 0.08653354354000001 419 | 135.29267239570618 0.8295 0.104456 0.08664625199999999 420 | 136.41252040863037 0.83065 0.1042632 0.08660622708 421 | 137.50266981124878 0.8318 0.1041484 0.08663063912 422 | 138.6226978302002 0.833 0.1040645 0.0866857285 423 | 139.73253679275513 0.83405 0.1039467 0.086696745135 424 | 140.85268807411194 0.83485 0.1039202 0.08675777897 425 | 141.95258212089539 0.8357 0.1038381 0.08677750017000001 426 | 143.0626838207245 0.83645 0.1037094 0.08674772763 427 | 144.1625738143921 0.8374 0.1035696 0.08672918304 428 | 145.2926881313324 0.83815 0.1034859 0.086736707085 429 | 146.39267802238464 0.839 0.103469 0.086810491 430 | 147.50252842903137 0.83975 0.1032977 0.086744243575 431 | 148.62254333496094 0.84025 0.1032779 0.08677925547500001 432 | 149.74249029159546 0.8407 0.1032501 0.08680235907 433 | 150.87268829345703 0.8412 0.1031786 0.08679383832 434 | 151.98298144340515 0.84175 0.1031542 0.08683004785 435 | 153.06320786476135 0.84195 0.103078 0.0867865221 436 | 154.18322253227234 0.8423 0.103091 0.0868335493 437 | 155.30300569534302 0.84265 0.1030965 0.086874265725 438 | 156.41322469711304 0.84305 0.1029547 0.08679595983499999 439 | 157.5230257511139 0.8434 0.102982 0.0868550188 440 | 158.63391256332397 0.8436 0.1028608 0.08677337088 441 | 159.74390721321106 0.8439 0.1029134 0.08684861826 442 | 160.85404562950134 0.844 0.102857 0.086811308 443 | 161.9740719795227 0.8443 0.1028326 0.08682156418 444 | 163.07385206222534 0.84445 0.1028057 0.086814273365 445 | 164.16387224197388 0.84455 0.1028435 0.08685647792500001 446 | 165.28387761116028 0.8447 0.102761 0.0868022167 447 | 166.40405535697937 0.84475 0.1028048 0.0868443548 448 | 167.51386904716492 0.84485 0.1027127 0.086776824595 449 | 168.62391066551208 0.84495 0.1027384 0.08680881107999999 450 | 169.73386645317078 0.8451 0.102695 0.0867875445 451 | 170.8538830280304 0.84525 0.102716 0.086820699 452 | 171.95409774780273 0.8452 0.1027072 0.08680812544 453 | 173.0638825893402 0.84545 0.1027157 0.086840988565 454 | 174.18385863304138 0.8455 0.1026689 0.08680655495 455 | 175.28387999534607 0.84555 0.1025704 0.08672840172 456 | 176.39387011528015 0.8455 0.1027038 0.0868360629 457 | 177.51386904716492 0.84545 0.102623 0.08676261535 458 | 178.6139361858368 0.8455 0.1026108 0.0867574314 459 | 179.72403931617737 0.8456 0.102631 0.0867847736 460 | 180.83407020568848 0.84565 0.1025548 0.08672546662 461 | 181.94390726089478 0.8456 0.102679 0.08682536240000001 462 | 183.05391573905945 0.8456 0.1026007 0.08675915192 463 | 184.16390705108643 0.8456 0.1026184 0.08677411904 464 | 185.2741084098816 0.8456 0.1026255 0.0867801228 465 | 186.37407398223877 0.84565 0.1026618 0.08681595117 466 | 187.48385643959045 0.8456 0.1026319 0.08678553464 467 | 188.60411381721497 0.84545 0.1026652 0.08679829334 468 | 189.7139928340912 0.84535 0.1026976 0.08681541616 469 | 190.8238663673401 0.84545 0.1026445 0.086780792525 470 | 191.94404339790344 0.8454 0.1027275 0.0868458285 471 | 193.06408715248108 0.84545 0.1026193 0.086759487185 472 | 194.183908700943 0.8456 0.1026824 0.08682823744 473 | 195.29388666152954 0.8455 0.1025818 0.0867329119 474 | 196.42389607429504 0.84575 0.1026336 0.08680236720000001 475 | 197.53387570381165 0.84565 0.1026029 0.086766142385 476 | 198.65387558937073 0.8456 0.1026642 0.08681284752 477 | 199.7638623714447 0.8457 0.1026415 0.08680391655 478 | 200.85384035110474 0.8459 0.1025755 0.08676861545 479 | 201.9438557624817 0.8457 0.1025759 0.08674843863 480 | 203.03410840034485 0.84565 0.1026176 0.08677857344 481 | 204.15395188331604 0.8458 0.1026307 0.08680504606 482 | 205.27385878562927 0.84565 0.1025986 0.08676250609 483 | 206.3841028213501 0.84565 0.1025498 0.08672123837 484 | 207.51405119895935 0.8456 0.1026193 0.08677488008 485 | 208.61391162872314 0.84545 0.1026483 0.086784005235 486 | 209.73402333259583 0.84555 0.1026129 0.086764337595 487 | 210.8547773361206 0.8457 0.1025999 0.08676873543 488 | 211.97556591033936 0.8454 0.1026559 0.08678529786 489 | 213.06564450263977 0.84535 0.1026466 0.08677230331 490 | 214.18564629554749 0.8453 0.1026765 0.08679244545 491 | 215.3057279586792 0.84515 0.1027164 0.08681076546 492 | 216.4355823993683 0.84525 0.1026694 0.08678131034999999 493 | 217.54745888710022 0.84525 0.1026731 0.086784437775 494 | 218.66214179992676 0.84515 0.1026786 0.08677881878999999 495 | 219.79991269111633 0.84505 0.1026676 0.08675925538 496 | 220.92192101478577 0.84515 0.1026474 0.08675245010999999 497 | 222.04221439361572 0.845 0.1026773 0.08676231849999999 498 | 223.16246700286865 0.84515 0.1026314 0.08673892771 499 | 224.2922146320343 0.84515 0.1026917 0.08678989025499999 500 | 225.4224374294281 0.84515 0.1026546 0.08675853519 501 | 226.52246594429016 0.84505 0.1026942 0.08678173371 502 | 227.64239501953125 0.8452 0.1027076 0.08680846351999999 503 | 228.74221539497375 0.8451 0.1026533 0.08675230383 504 | 229.8524467945099 0.8451 0.1026436 0.08674410636 505 | 230.9621970653534 0.8451 0.1027198 0.08680850298 506 | 232.09237265586853 0.84525 0.1025999 0.08672256547499999 507 | 233.2123908996582 0.84515 0.1026491 0.08675388686499999 508 | 234.33220410346985 0.84515 0.1026971 0.086794454065 509 | 235.46221351623535 0.8453 0.102692 0.0868055476 510 | 511 | 512 | -------------------------------------------------------------------------------- /examples/SolarReference/dat/Si/si-ref-datasheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/examples/SolarReference/dat/Si/si-ref-datasheet.pdf -------------------------------------------------------------------------------- /examples/SolarReference/dat/Si/si-ref-extract.dat: -------------------------------------------------------------------------------- 1 | #! Si Reference: Extract 2 | 3 | Voc 0.5917749999999999 4 | Isc 124.03999999999999 5 | Jsc 31.009999999999998 6 | Vm 0.45645 7 | Im 109.8759 8 | Jm 27.468975 9 | FF 0.6832462947305529 10 | ETA 12.538213638750001 11 | -------------------------------------------------------------------------------- /examples/SolarReference/dat/Si/si-ref-stability.dat: -------------------------------------------------------------------------------- 1 | *! QVisaDataObject v1.1 2 | *! hash 358fb4a 3 | 4 | #! __data__ 511d887 5 | #! __type__ v-bias 6 | t V I P 7 | 0.2702157497406006 0.0 -0.139326 -0.0 8 | 0.5802147388458252 0.0 -0.137411 -0.0 9 | 0.890216588973999 0.0 -0.1361768 -0.0 10 | 1.190220594406128 0.0 -0.1352338 -0.0 11 | 1.480219841003418 0.0 -0.1345216 -0.0 12 | 1.780219554901123 0.0 -0.1339256 -0.0 13 | 2.0902135372161865 0.0 -0.1333839 -0.0 14 | 2.400217294692993 0.0 -0.132928 -0.0 15 | 2.7002272605895996 0.0 -0.1325224 -0.0 16 | 3.0002174377441406 0.0 -0.1321516 -0.0 17 | 3.3002376556396484 0.0 -0.1318149 -0.0 18 | 3.6002156734466553 0.0 -0.1315144 -0.0 19 | 3.900221586227417 0.0 -0.1312404 -0.0 20 | 4.20021915435791 0.0 -0.1309699 -0.0 21 | 4.50022554397583 0.0 -0.1307121 -0.0 22 | 4.8102126121521 0.0 -0.1304882 -0.0 23 | 5.110231637954712 0.0 -0.1302665 -0.0 24 | 5.410227298736572 0.0 -0.1300779 -0.0 25 | 5.710216999053955 0.0 -0.1298839 -0.0 26 | 6.010220289230347 0.0 -0.1297055 -0.0 27 | 6.320216417312622 0.0 -0.1295328 -0.0 28 | 6.610220432281494 0.0 -0.1293851 -0.0 29 | 6.910222291946411 0.0 -0.1292235 -0.0 30 | 7.210225343704224 0.0 -0.1290883 -0.0 31 | 7.510216951370239 0.0 -0.1289579 -0.0 32 | 7.810218572616577 0.0 -0.1288299 -0.0 33 | 8.120218276977539 0.0 -0.1287193 -0.0 34 | 8.420229434967041 0.0 -0.1285993 -0.0 35 | 8.710223913192749 0.0 -0.1284933 -0.0 36 | 9.010224342346191 0.0 -0.128393 -0.0 37 | 9.31022572517395 0.0 -0.1282976 -0.0 38 | 9.610223293304443 0.0 -0.1282158 -0.0 39 | 9.910224437713623 0.0 -0.1281203 -0.0 40 | 10.230213403701782 0.0 -0.1280244 -0.0 41 | 10.540226221084595 0.0 -0.127941 -0.0 42 | 10.840224027633667 0.0 -0.1278652 -0.0 43 | 11.140230417251587 0.0 -0.1277882 -0.0 44 | 11.440225601196289 0.0 -0.1277162 -0.0 45 | 11.740219354629517 0.0 -0.1276595 -0.0 46 | 12.050231218338013 0.0 -0.1275942 -0.0 47 | 12.350225925445557 0.0 -0.1275322 -0.0 48 | 12.6402268409729 0.0 -0.1274721 -0.0 49 | 12.94023084640503 0.0 -0.1274187 -0.0 50 | 13.240222454071045 0.0 -0.1273699 -0.0 51 | 13.540221452713013 0.0 -0.1273054 -0.0 52 | 13.840226173400879 0.0 -0.1272646 -0.0 53 | 14.160227060317993 0.0 -0.1272028 -0.0 54 | 14.4602210521698 0.0 -0.1271598 -0.0 55 | 14.760220289230347 0.0 -0.1271152 -0.0 56 | 15.060237884521484 0.0 -0.1270761 -0.0 57 | 15.36022162437439 0.0 -0.1270377 -0.0 58 | 15.670220851898193 0.0 -0.126994 -0.0 59 | 15.970228910446167 0.0 -0.1269539 -0.0 60 | 16.270217418670654 0.0 -0.1269136 -0.0 61 | 16.570237159729004 0.0 -0.1268862 -0.0 62 | 16.870254516601562 0.0 -0.1268521 -0.0 63 | 17.170217037200928 0.0 -0.1268037 -0.0 64 | 17.490222930908203 0.0 -0.1267839 -0.0 65 | 17.790225505828857 0.0 -0.1267452 -0.0 66 | 18.090214490890503 0.0 -0.126707 -0.0 67 | 18.391067266464233 0.0 -0.12668 -0.0 68 | 18.691064834594727 0.0 -0.1266538 -0.0 69 | 19.001063346862793 0.0 -0.1266249 -0.0 70 | 19.311065912246704 0.0 -0.1266139 -0.0 71 | 19.611067533493042 0.0 -0.126568 -0.0 72 | 19.921064138412476 0.0 -0.12655 -0.0 73 | 20.221068859100342 0.0 -0.1265222 -0.0 74 | 20.531068086624146 0.0 -0.1265024 -0.0 75 | 20.84106707572937 0.0 -0.1264869 -0.0 76 | 21.141067504882812 0.0 -0.1264641 -0.0 77 | 21.44080686569214 0.0 -0.1264469 -0.0 78 | 21.721065759658813 0.0 -0.1264217 -0.0 79 | 22.02106809616089 0.0 -0.1263981 -0.0 80 | 22.321068048477173 0.0 -0.1263879 -0.0 81 | 22.621050119400024 0.0 -0.1263615 -0.0 82 | 22.911064624786377 0.0 -0.1263454 -0.0 83 | 23.211074352264404 0.0 -0.1263189 -0.0 84 | 23.521061658859253 0.0 -0.126316 -0.0 85 | 23.8210871219635 0.0 -0.1262979 -0.0 86 | 24.121070384979248 0.0 -0.1262756 -0.0 87 | 24.421088695526123 0.0 -0.1262643 -0.0 88 | 24.73107361793518 0.0 -0.1262487 -0.0 89 | 25.031063318252563 0.0 -0.1262296 -0.0 90 | 25.321069717407227 0.0 -0.126209 -0.0 91 | 25.621070623397827 0.0 -0.1262061 -0.0 92 | 25.931070566177368 0.0 -0.1261868 -0.0 93 | 26.231062173843384 0.0 -0.1261687 -0.0 94 | 26.541064739227295 0.0 -0.1261645 -0.0 95 | 26.85107183456421 0.0 -0.1261464 -0.0 96 | 27.151070594787598 0.0 -0.1261324 -0.0 97 | 27.451072931289673 0.0 -0.1261182 -0.0 98 | 27.751084804534912 0.0 -0.1261178 -0.0 99 | 28.051068544387817 0.0 -0.1261072 -0.0 100 | 28.351064920425415 0.0 -0.1260954 -0.0 101 | 28.66107153892517 0.0 -0.1260764 -0.0 102 | 28.95106077194214 0.0 -0.1260753 -0.0 103 | 29.251068830490112 0.0 -0.1260635 -0.0 104 | 29.55107307434082 0.0 -0.1260511 -0.0 105 | 29.85106873512268 0.0 -0.1260323 -0.0 106 | 30.151060581207275 0.0 -0.1260281 -0.0 107 | 30.471070766448975 0.0 -0.1260154 -0.0 108 | 30.771073579788208 0.0 -0.1260012 -0.0 109 | 31.071069955825806 0.0 -0.126004 -0.0 110 | 31.37106156349182 0.0 -0.125981 -0.0 111 | 31.671075105667114 0.0 -0.1259793 -0.0 112 | 31.9810688495636 0.0 -0.125967 -0.0 113 | 32.29107618331909 0.0 -0.1259633 -0.0 114 | 32.60107135772705 0.0 -0.1259607 -0.0 115 | 32.9010694026947 0.0 -0.1259413 -0.0 116 | 33.201069593429565 0.0 -0.1259435 -0.0 117 | 33.50106334686279 0.0 -0.1259258 -0.0 118 | 33.801074504852295 0.0 -0.1259215 -0.0 119 | 34.111071825027466 0.0 -0.1259177 -0.0 120 | 34.421069622039795 0.0 -0.1259106 -0.0 121 | 34.72106671333313 0.0 -0.1258988 -0.0 122 | 35.03106999397278 0.0 -0.1258962 -0.0 123 | 35.34107851982117 0.0 -0.1258929 -0.0 124 | 35.6510705947876 0.0 -0.1258828 -0.0 125 | 35.95107173919678 0.0 -0.125879 -0.0 126 | 36.261061668395996 0.0 -0.1258711 -0.0 127 | 36.571054220199585 0.0 -0.1258816 -0.0 128 | 36.87107539176941 0.0 -0.1258509 -0.0 129 | 37.17106604576111 0.0 -0.1258513 -0.0 130 | 37.47106695175171 0.0 -0.1258585 -0.0 131 | 37.77107048034668 0.0 -0.1258379 -0.0 132 | 38.07107615470886 0.0 -0.1258348 -0.0 133 | 38.371068239212036 0.0 -0.1258243 -0.0 134 | 38.67107367515564 0.0 -0.1258366 -0.0 135 | 38.991060733795166 0.0 -0.1258163 -0.0 136 | 39.30107116699219 0.0 -0.1258042 -0.0 137 | 39.62106919288635 0.0 -0.1258045 -0.0 138 | 39.93107461929321 0.0 -0.1258004 -0.0 139 | 40.231069564819336 0.0 -0.1258007 -0.0 140 | 40.531073570251465 0.0 -0.1257981 -0.0 141 | 40.84105968475342 0.0 -0.1257788 -0.0 142 | 41.14106321334839 0.0 -0.1257805 -0.0 143 | 41.451069593429565 0.0 -0.1257747 -0.0 144 | 41.751073360443115 0.0 -0.1257578 -0.0 145 | 42.05107116699219 0.0 -0.1257633 -0.0 146 | 42.35106873512268 0.0 -0.1257557 -0.0 147 | 42.650808811187744 0.0 -0.1257579 -0.0 148 | 42.940812826156616 0.0 -0.1257607 -0.0 149 | 43.22106909751892 0.0 -0.125741 -0.0 150 | 43.52107238769531 0.0 -0.1257288 -0.0 151 | 43.820863246917725 0.0 -0.1257213 -0.0 152 | 44.11106824874878 0.0 -0.1257267 -0.0 153 | 44.401060581207275 0.0 -0.1257208 -0.0 154 | 44.71107530593872 0.0 -0.1257166 -0.0 155 | 45.011064529418945 0.0 -0.125712 -0.0 156 | 45.30108976364136 0.0 -0.1257183 -0.0 157 | 45.601059913635254 0.0 -0.1257073 -0.0 158 | 45.90106177330017 0.0 -0.1257043 -0.0 159 | 46.201061964035034 0.0 -0.1257002 -0.0 160 | 46.511075258255005 0.0 -0.1257009 -0.0 161 | 46.80106806755066 0.0 -0.12569 -0.0 162 | 47.111093282699585 0.0 -0.1256884 -0.0 163 | 47.421085834503174 0.0 -0.1256736 -0.0 164 | 47.73106527328491 0.0 -0.1256749 -0.0 165 | 48.03110432624817 0.0 -0.1256758 -0.0 166 | 48.33106851577759 0.0 -0.1256723 -0.0 167 | 48.64108991622925 0.0 -0.1256716 -0.0 168 | 48.931071519851685 0.0 -0.1256521 -0.0 169 | 49.231064319610596 0.0 -0.1256556 -0.0 170 | 49.53107047080994 0.0 -0.1256488 -0.0 171 | 49.8310866355896 0.0 -0.1256416 -0.0 172 | 50.13106918334961 0.0 -0.1256471 -0.0 173 | 50.441073417663574 0.0 -0.1256215 -0.0 174 | 50.7510666847229 0.0 -0.1256332 -0.0 175 | 51.0510675907135 0.0 -0.1256344 -0.0 176 | 51.35107922554016 0.0 -0.1256319 -0.0 177 | 51.651068449020386 0.0 -0.1256378 -0.0 178 | 51.951072454452515 0.0 -0.1256172 -0.0 179 | 52.25106620788574 0.0 -0.1256185 -0.0 180 | 52.551077127456665 0.0 -0.1256155 -0.0 181 | 52.85107135772705 0.0 -0.1256008 -0.0 182 | 53.151074171066284 0.0 -0.1256109 -0.0 183 | 53.45109462738037 0.0 -0.1255996 -0.0 184 | 53.751060009002686 0.0 -0.1256084 -0.0 185 | 54.05107307434082 0.0 -0.1255966 -0.0 186 | 54.35106062889099 0.0 -0.1255953 -0.0 187 | 54.66107511520386 0.0 -0.1255835 -0.0 188 | 54.961084842681885 0.0 -0.1255848 -0.0 189 | 55.261062145233154 0.0 -0.1255828 -0.0 190 | 55.561070680618286 0.0 -0.1255701 -0.0 191 | 55.86107540130615 0.0 -0.1255669 -0.0 192 | 56.17107653617859 0.0 -0.1255748 -0.0 193 | 56.47106862068176 0.0 -0.1255723 -0.0 194 | 56.78108596801758 0.0 -0.1255899 -0.0 195 | 57.08104658126831 0.0 -0.1255576 -0.0 196 | 57.371071577072144 0.0 -0.1255566 -0.0 197 | 57.68107485771179 0.0 -0.1255583 -0.0 198 | 57.98107314109802 0.0 -0.1255524 -0.0 199 | 58.281068325042725 0.0 -0.1255511 -0.0 200 | 58.581074476242065 0.0 -0.1255516 -0.0 201 | 58.88106298446655 0.0 -0.1255548 -0.0 202 | 59.1910719871521 0.0 -0.1255487 -0.0 203 | 59.50107717514038 0.0 -0.125541 -0.0 204 | 59.80108070373535 0.0 -0.1255322 -0.0 205 | 60.101075887680054 0.0 -0.1255305 -0.0 206 | 60.40106534957886 0.0 -0.1255415 -0.0 207 | 60.70106387138367 0.0 -0.1255381 -0.0 208 | 60.99106478691101 0.0 -0.1255255 -0.0 209 | 61.29107475280762 0.0 -0.1255285 -0.0 210 | 61.60106921195984 0.0 -0.1255129 -0.0 211 | 61.90107011795044 0.0 -0.1255175 -0.0 212 | 62.20106649398804 0.0 -0.1255224 -0.0 213 | 62.501100301742554 0.0 -0.1255242 -0.0 214 | 62.80107140541077 0.0 -0.1255167 -0.0 215 | 63.101070404052734 0.0 -0.1255015 -0.0 216 | 63.401084423065186 0.0 -0.1254995 -0.0 217 | 63.70108604431152 0.0 -0.1254902 -0.0 218 | 64.01107144355774 0.0 -0.1255095 -0.0 219 | 64.3110625743866 0.0 -0.1254885 -0.0 220 | 64.61106967926025 0.0 -0.1254934 -0.0 221 | 64.91108059883118 0.0 -0.1254931 -0.0 222 | 65.21107363700867 0.0 -0.1254922 -0.0 223 | 65.53108215332031 0.0 -0.1254897 -0.0 224 | 65.82106924057007 0.0 -0.1254855 -0.0 225 | 66.12107634544373 0.0 -0.1254884 -0.0 226 | 66.4210638999939 0.0 -0.125477 -0.0 227 | 66.72106695175171 0.0 -0.1254732 -0.0 228 | 67.02107262611389 0.0 -0.1254648 -0.0 229 | 67.33106064796448 0.0 -0.1254712 -0.0 230 | 67.64109086990356 0.0 -0.1254825 -0.0 231 | 67.94106888771057 0.0 -0.1254687 -0.0 232 | 68.24107050895691 0.0 -0.1254573 -0.0 233 | 68.54106426239014 0.0 -0.1254582 -0.0 234 | 68.8410747051239 0.0 -0.125459 -0.0 235 | 69.15106987953186 0.0 -0.1254581 -0.0 236 | 69.451101064682 0.0 -0.1254547 -0.0 237 | 69.75108313560486 0.0 -0.1254501 -0.0 238 | 70.05107641220093 0.0 -0.125448 -0.0 239 | 70.3510754108429 0.0 -0.1254485 -0.0 240 | 70.66107439994812 0.0 -0.1254362 -0.0 241 | 70.97106885910034 0.0 -0.1254383 -0.0 242 | 71.27108526229858 0.0 -0.1254366 -0.0 243 | 71.57107758522034 0.0 -0.1254375 -0.0 244 | 71.87107515335083 0.0 -0.1254312 -0.0 245 | 72.17106819152832 0.0 -0.1254303 -0.0 246 | 72.4710853099823 0.0 -0.12544 -0.0 247 | 72.79108810424805 0.0 -0.1254286 -0.0 248 | 73.10107827186584 0.0 -0.1254223 -0.0 249 | 73.411062002182 0.0 -0.1254295 -0.0 250 | 73.72106981277466 0.0 -0.1254202 -0.0 251 | 74.02106857299805 0.0 -0.1254189 -0.0 252 | 74.32108640670776 0.0 -0.1254059 -0.0 253 | 74.62107706069946 0.0 -0.1254126 -0.0 254 | 74.92107844352722 0.0 -0.1254256 -0.0 255 | 75.22106218338013 0.0 -0.1254123 -0.0 256 | 75.52110314369202 0.0 -0.1254071 -0.0 257 | 75.82106947898865 0.0 -0.1254047 -0.0 258 | 76.13109183311462 0.0 -0.1253979 -0.0 259 | 76.44125890731812 0.0 -0.1254068 -0.0 260 | 76.74161028862 0.0 -0.1253966 -0.0 261 | 77.0416214466095 0.0 -0.1254139 -0.0 262 | 77.36161708831787 0.0 -0.1253824 -0.0 263 | 77.66162323951721 0.0 -0.1253879 -0.0 264 | 77.97161197662354 0.0 -0.1253807 -0.0 265 | 78.27160215377808 0.0 -0.1253898 -0.0 266 | 78.58160448074341 0.0 -0.1253761 -0.0 267 | 78.88162016868591 0.0 -0.1253824 -0.0 268 | 79.18162202835083 0.0 -0.1253757 -0.0 269 | 79.4816198348999 0.0 -0.1253921 -0.0 270 | 79.7916100025177 0.0 -0.1253668 -0.0 271 | 80.09164118766785 0.0 -0.1253618 -0.0 272 | 80.39161157608032 0.0 -0.1253685 -0.0 273 | 80.69160389900208 0.0 -0.1253659 -0.0 274 | 80.99162578582764 0.0 -0.1253495 -0.0 275 | 81.31161594390869 0.0 -0.1253631 -0.0 276 | 81.61136865615845 0.0 -0.1253673 -0.0 277 | 81.90161728858948 0.0 -0.1253513 -0.0 278 | 82.20161437988281 0.0 -0.1253613 -0.0 279 | 82.5016074180603 0.0 -0.1253453 -0.0 280 | 82.80160975456238 0.0 -0.1253458 -0.0 281 | 83.1116087436676 0.0 -0.125339 -0.0 282 | 83.42161202430725 0.0 -0.1253444 -0.0 283 | 83.72161650657654 0.0 -0.1253499 -0.0 284 | 84.02161312103271 0.0 -0.1253394 -0.0 285 | 84.32161378860474 0.0 -0.1253503 -0.0 286 | 84.6216242313385 0.0 -0.1253322 -0.0 287 | 84.93159675598145 0.0 -0.1253201 -0.0 288 | 85.2316312789917 0.0 -0.1253331 -0.0 289 | 85.52162194252014 0.0 -0.1253352 -0.0 290 | 85.83161759376526 0.0 -0.1253184 -0.0 291 | 86.14161229133606 0.0 -0.1253327 -0.0 292 | 86.44161438941956 0.0 -0.1253213 -0.0 293 | 86.73162150382996 0.0 -0.1253331 -0.0 294 | 87.03161525726318 0.0 -0.1253239 -0.0 295 | 87.33161783218384 0.0 -0.1253217 -0.0 296 | 87.63162183761597 0.0 -0.1253062 -0.0 297 | 87.93162035942078 0.0 -0.1253044 -0.0 298 | 88.24161791801453 0.0 -0.1253159 -0.0 299 | 88.55161762237549 0.0 -0.1253209 -0.0 300 | 88.86160922050476 0.0 -0.1253007 -0.0 301 | 89.16162276268005 0.0 -0.1253141 -0.0 302 | 89.44783902168274 0.0 -0.1253019 -0.0 303 | 89.73852181434631 0.0 -0.125312 -0.0 304 | 90.04852867126465 0.0 -0.1252957 -0.0 305 | 90.33835625648499 0.0 -0.1252986 -0.0 306 | 90.6385247707367 0.0 -0.1252982 -0.0 307 | 90.93852925300598 0.0 -0.1252876 -0.0 308 | 91.23852229118347 0.0 -0.1252952 -0.0 309 | 91.53852796554565 0.0 -0.1253002 -0.0 310 | 91.84852528572083 0.0 -0.1252834 -0.0 311 | 92.15853190422058 0.0 -0.125294 -0.0 312 | 92.45852398872375 0.0 -0.1252898 -0.0 313 | 92.7585301399231 0.0 -0.1252909 -0.0 314 | 93.0585241317749 0.0 -0.1252767 -0.0 315 | 93.37853479385376 0.0 -0.1252816 -0.0 316 | 93.66852903366089 0.0 -0.1252783 -0.0 317 | 93.96852493286133 0.0 -0.12527 -0.0 318 | 94.2685604095459 0.0 -0.1252718 -0.0 319 | 94.56852126121521 0.0 -0.125267 -0.0 320 | 94.87852501869202 0.0 -0.1252654 -0.0 321 | 95.18852710723877 0.0 -0.125257 -0.0 322 | 95.48853349685669 0.0 -0.1252687 -0.0 323 | 95.7885229587555 0.0 -0.125272 -0.0 324 | 96.08852553367615 0.0 -0.1252657 -0.0 325 | 96.38853240013123 0.0 -0.1252649 -0.0 326 | 96.68853211402893 0.0 -0.1252515 -0.0 327 | 97.00853395462036 0.0 -0.1252624 -0.0 328 | 97.29850363731384 0.0 -0.1252481 -0.0 329 | 97.59852933883667 0.0 -0.125262 -0.0 330 | 97.89852023124695 0.0 -0.1252443 -0.0 331 | 98.19853234291077 0.0 -0.1252472 -0.0 332 | 98.51852989196777 0.0 -0.1252414 -0.0 333 | 98.82852482795715 0.0 -0.1252468 -0.0 334 | 99.12852358818054 0.0 -0.125233 -0.0 335 | 99.42853164672852 0.0 -0.125238 -0.0 336 | 99.72848868370056 0.0 -0.1252493 -0.0 337 | 100.02852606773376 0.0 -0.125243 -0.0 338 | 100.34851932525635 0.0 -0.1252359 -0.0 339 | 100.6585283279419 0.0 -0.1252363 -0.0 340 | 100.9582633972168 0.0 -0.125227 -0.0 341 | 101.25852656364441 0.0 -0.1252295 -0.0 342 | 101.55852270126343 0.0 -0.1252363 -0.0 343 | 101.85852766036987 0.0 -0.125232 -0.0 344 | 102.16852736473083 0.0 -0.1252197 -0.0 345 | 102.47853326797485 0.0 -0.1252291 -0.0 346 | 102.77852869033813 0.0 -0.1252274 -0.0 347 | 103.08852982521057 0.0 -0.1252208 -0.0 348 | 103.38852214813232 0.0 -0.1252292 -0.0 349 | 103.68829107284546 0.0 -0.125222 -0.0 350 | 103.99852800369263 0.0 -0.1252035 -0.0 351 | 104.29852724075317 0.0 -0.1252182 -0.0 352 | 104.60852026939392 0.0 -0.1252172 -0.0 353 | 104.90852808952332 0.0 -0.1252026 -0.0 354 | 105.20852518081665 0.0 -0.1252169 -0.0 355 | 105.50853085517883 0.0 -0.1252064 -0.0 356 | 105.80853295326233 0.0 -0.1251996 -0.0 357 | 106.11852216720581 0.0 -0.1251996 -0.0 358 | 106.41851687431335 0.0 -0.1251963 -0.0 359 | 106.7185320854187 0.0 -0.1252081 -0.0 360 | 107.01853775978088 0.0 -0.1252072 -0.0 361 | 107.31851840019226 0.0 -0.1251979 -0.0 362 | 107.6185257434845 0.0 -0.1252034 -0.0 363 | 107.91851687431335 0.0 -0.1252101 -0.0 364 | 108.21853137016296 0.0 -0.1251883 -0.0 365 | 108.51852583885193 0.0 -0.1251992 -0.0 366 | 108.818519115448 0.0 -0.1251849 -0.0 367 | 109.11851906776428 0.0 -0.1251979 -0.0 368 | 109.4385232925415 0.0 -0.1251879 -0.0 369 | 109.73848342895508 0.0 -0.125182 -0.0 370 | 110.03852915763855 0.0 -0.1251744 -0.0 371 | 110.33853530883789 0.0 -0.1251828 -0.0 372 | 110.63852953910828 0.0 -0.1251853 -0.0 373 | 110.94852876663208 0.0 -0.1251806 -0.0 374 | 111.24852752685547 0.0 -0.125171 -0.0 375 | 111.54851984977722 0.0 -0.1251785 -0.0 376 | 111.84852266311646 0.0 -0.125176 -0.0 377 | 112.14852094650269 0.0 -0.1251748 -0.0 378 | 112.45851969718933 0.0 -0.1251685 -0.0 379 | 112.76852297782898 0.0 -0.1251643 -0.0 380 | 113.07850956916809 0.0 -0.1251655 -0.0 381 | 113.37852883338928 0.0 -0.1251614 -0.0 382 | 113.67853856086731 0.0 -0.1251579 -0.0 383 | 113.97852754592896 0.0 -0.1251647 -0.0 384 | 114.27852702140808 0.0 -0.1251588 -0.0 385 | 114.58853268623352 0.0 -0.1251609 -0.0 386 | 114.88851857185364 0.0 -0.1251592 -0.0 387 | 115.19853925704956 0.0 -0.1251516 -0.0 388 | 115.49854302406311 0.0 -0.1251508 -0.0 389 | 115.79852843284607 0.0 -0.1251546 -0.0 390 | 116.09852337837219 0.0 -0.1251567 -0.0 391 | 116.39852166175842 0.0 -0.1251488 -0.0 392 | 116.70852780342102 0.0 -0.1251567 -0.0 393 | 117.01858568191528 0.0 -0.1251554 -0.0 394 | 395 | 396 | -------------------------------------------------------------------------------- /examples/SolarReference/dat/Si/si-ref-tracking.dat: -------------------------------------------------------------------------------- 1 | *! QVisaDataObject v1.1 2 | *! hash 1b41b90 3 | 4 | #! __data__ 1d8c382 5 | #! __type__ pv-voc 6 | #! __desc__ SiRef-voc-conv 7 | t Voc Ioc 8 | 0.7985508441925049 0.3 0.122766 9 | 1.5963878631591797 0.305 0.1226872 10 | 2.413339138031006 0.31 0.122574 11 | 3.2421164512634277 0.315 0.122473 12 | 4.027169704437256 0.32 0.1223387 13 | 4.825051546096802 0.325 0.1222289 14 | 5.642358303070068 0.33 0.1220491 15 | 6.462575435638428 0.33495 0.1219262 16 | 7.24233603477478 0.3399 0.1217516 17 | 8.052538871765137 0.34485 0.1215765 18 | 8.852534770965576 0.3498 0.1213904 19 | 9.652341842651367 0.35475 0.1211901 20 | 10.482909917831421 0.3597 0.1210104 21 | 11.272959232330322 0.36465 0.1207418 22 | 12.072925806045532 0.36955 0.1205503 23 | 12.859275341033936 0.37445 0.1202454 24 | 13.654071807861328 0.37935 0.1199756 25 | 14.464534282684326 0.38425 0.119756 26 | 15.264321565628052 0.38915 0.1193131 27 | 16.074401378631592 0.394 0.1190059 28 | 16.89452028274536 0.39885 0.1186515 29 | 17.714465856552124 0.4037 0.1183262 30 | 18.52151083946228 0.4085 0.1179318 31 | 19.333040714263916 0.4133 0.1174923 32 | 20.13355541229248 0.4181 0.1169961 33 | 20.95376181602478 0.42285 0.1165621 34 | 21.76380491256714 0.4276 0.1160667 35 | 22.573965072631836 0.43235 0.1154374 36 | 23.37394428253174 0.43705 0.1147315 37 | 24.1837637424469 0.4417 0.1140017 38 | 24.98395299911499 0.44635 0.1131986 39 | 25.783954620361328 0.45095 0.1122848 40 | 26.583805799484253 0.4555 0.1113066 41 | 27.38396716117859 0.46005 0.1101634 42 | 28.183886528015137 0.46455 0.1089381 43 | 28.993957042694092 0.469 0.1075631 44 | 29.803958415985107 0.4734 0.1060629 45 | 30.613771200180054 0.4777 0.1044361 46 | 31.42389440536499 0.48195 0.1027062 47 | 32.233805656433105 0.48615 0.1008209 48 | 33.11395025253296 0.49025 0.0988559 49 | 33.933961391448975 0.4943 0.09670955 50 | 34.74375557899475 0.49825 0.09451324 51 | 35.55396604537964 0.5021 0.09219234 52 | 36.363961696624756 0.50585 0.08980262 53 | 37.1739616394043 0.5095 0.08735811 54 | 37.975807666778564 0.51305 0.08484086 55 | 38.78584313392639 0.5165 0.08223616 56 | 39.59582591056824 0.51985 0.07964249 57 | 40.40584444999695 0.5231 0.07701405 58 | 41.21583676338196 0.52625 0.07437424 59 | 42.01581263542175 0.5293 0.07170539 60 | 42.81582283973694 0.5322 0.06910098 61 | 43.61585092544556 0.535 0.06651852 62 | 44.41113066673279 0.5377 0.06397173 63 | 45.22863960266113 0.5403 0.06142221 64 | 46.02479386329651 0.5428 0.05895006 65 | 46.7957923412323 0.5452 0.05649929 66 | 47.568145513534546 0.5475 0.0541158 67 | 48.378458738327026 0.5497 0.05183071 68 | 49.16104245185852 0.5518 0.04958141 69 | 49.97498965263367 0.5538 0.04740685 70 | 50.76497721672058 0.55575 0.04524508 71 | 51.544190883636475 0.5576 0.04316992 72 | 52.344125509262085 0.55935 0.04122215 73 | 53.15418553352356 0.56105 0.03925008 74 | 53.96419334411621 0.56265 0.03742541 75 | 54.75418972969055 0.56415 0.03565501 76 | 55.56409549713135 0.5656 0.03395368 77 | 56.364018201828 0.567 0.03232145 78 | 57.18419790267944 0.5683 0.03075444 79 | 57.98417353630066 0.56955 0.02926774 80 | 58.77417016029358 0.57075 0.02780478 81 | 59.574042558670044 0.5719 0.02642122 82 | 60.3641152381897 0.573 0.02506887 83 | 61.164000272750854 0.574 0.02384038 84 | 61.974183320999146 0.57495 0.02264712 85 | 62.77419400215149 0.57585 0.0215278 86 | 63.574121952056885 0.57675 0.02040994 87 | 64.37418222427368 0.5776 0.01933013 88 | 65.17401719093323 0.5784 0.01833442 89 | 65.97419023513794 0.57915 0.01737312 90 | 66.78405737876892 0.57985 0.01649535 91 | 67.59419226646423 0.5805 0.01565857 92 | 68.39404368400574 0.58115 0.01482609 93 | 69.2041757106781 0.58175 0.01407176 94 | 69.99418663978577 0.5823 0.01336529 95 | 70.80418848991394 0.58285 0.01265352 96 | 71.61418271064758 0.58335 0.012031 97 | 72.42418837547302 0.58385 0.01136182 98 | 73.30418276786804 0.5843 0.01078149 99 | 74.32004046440125 0.58475 0.0102083 100 | 75.32058596611023 0.58515 0.009667719 101 | 76.1207480430603 0.58555 0.009170176 102 | 76.92078471183777 0.5859 0.008722896 103 | 77.73060774803162 0.58625 0.008221362 104 | 78.55079078674316 0.5866 0.007769761 105 | 79.35061812400818 0.5869 0.007405632 106 | 80.16056871414185 0.5872 0.00699811 107 | 80.97062182426453 0.5875 0.006588861 108 | 81.77075242996216 0.58775 0.006269797 109 | 82.57060074806213 0.588 0.005947531 110 | 83.37078309059143 0.58825 0.005585975 111 | 84.17060446739197 0.5885 0.005263792 112 | 84.9707682132721 0.5887 0.004988403 113 | 85.7706344127655 0.5889 0.004756863 114 | 86.57073998451233 0.5891 0.004481813 115 | 87.36054110527039 0.5893 0.004205947 116 | 88.14073324203491 0.58945 0.004019227 117 | 88.94153833389282 0.5896 0.00379086 118 | 89.73219060897827 0.58975 0.003606569 119 | 90.51173281669617 0.5899 0.003419996 120 | 91.29771065711975 0.59005 0.003191673 121 | 92.10559391975403 0.5902 0.003003481 122 | 92.92013502120972 0.5903 0.002865283 123 | 93.74802923202515 0.5904 0.002720738 124 | 94.54198122024536 0.5905 0.0025791 125 | 95.32984828948975 0.5906 0.002445533 126 | 96.2148129940033 0.5907 0.002304983 127 | 97.19294476509094 0.5908 0.00216156 128 | 98.20440363883972 0.5909 0.002068757 129 | 99.20419383049011 0.591 0.001926824 130 | 100.18446230888367 0.5911 0.001785916 131 | 101.19422388076782 0.59115 0.001688952 132 | 102.20421886444092 0.5912 0.001638483 133 | 103.21422529220581 0.59125 0.001544423 134 | 104.23446774482727 0.5913 0.001494752 135 | 105.24446749687195 0.59135 0.001447008 136 | 106.26440238952637 0.5914 0.001353795 137 | 107.35442018508911 0.59145 0.001301826 138 | 108.64443922042847 0.5915 0.001203757 139 | 109.78426814079285 0.59155 0.001154798 140 | 110.78439664840698 0.5916 0.001061004 141 | 111.79424047470093 0.59165 0.001024947 142 | 112.80424547195435 0.5917 0.0009293878 143 | 113.82445979118347 0.59175 0.0008807305 144 | 114.84427905082703 0.5918 0.0007840337 145 | 115.86446857452393 0.59185 0.0007365249 146 | 116.8842179775238 0.5919 0.0006869878 147 | 117.9054307937622 0.59195 0.0005892034 148 | 118.92548632621765 0.59195 0.0005875143 149 | 119.94545221328735 0.59195 0.0005851079 150 | 120.97543263435364 0.59195 0.0005847242 151 | 121.98547792434692 0.59195 0.0005789751 152 | 123.00560688972473 0.59195 0.0005763752 153 | 124.0154447555542 0.59195 0.0005715103 154 | 125.03560447692871 0.59195 0.0005668545 155 | 126.04282093048096 0.59195 0.0005640508 156 | 127.06919574737549 0.59195 0.0005590207 157 | 158 | 159 | #! __data__ f5a1d04 160 | #! __type__ pv-mpp 161 | #! __desc__ SiRef-mpp-conv 162 | t Vmpp Impp Pmpp 163 | 0.977269172668457 0.3 0.122791 0.036837299999999996 164 | 2.13165020942688 0.305 0.1226593 0.037411086499999996 165 | 3.257789373397827 0.30995 0.1225077 0.037971261615 166 | 4.421543121337891 0.3149 0.1224231 0.03855103419000001 167 | 5.552127122879028 0.31985 0.1222964 0.03911650354 168 | 6.682298183441162 0.32475 0.1221608 0.0396717198 169 | 7.792236089706421 0.32965 0.1219984 0.04021677256 170 | 8.922225952148438 0.33455 0.1218216 0.040755416280000005 171 | 10.042261123657227 0.3393 0.1217353 0.04130478729 172 | 11.162257671356201 0.344 0.1215522 0.041813956799999996 173 | 12.26206922531128 0.3487 0.1213443 0.04231275741 174 | 13.402259349822998 0.35335 0.1211658 0.04281393543 175 | 14.522249221801758 0.35795 0.120931 0.043287251449999994 176 | 15.632052183151245 0.3625 0.120715 0.0437591875 177 | 16.743561267852783 0.367 0.1204991 0.044223169699999995 178 | 17.872528791427612 0.37145 0.1202782 0.04467733739 179 | 19.00882363319397 0.3758 0.1201005 0.0451337679 180 | 20.097416162490845 0.3799 0.1197861 0.04550673939 181 | 21.230726957321167 0.38415 0.1195647 0.045930779505 182 | 22.357271194458008 0.38805 0.1193227 0.046303173735 183 | 23.47429084777832 0.3921 0.1190339 0.04667319219 184 | 24.575420379638672 0.3961 0.1187186 0.04702443746 185 | 25.696549654006958 0.3998 0.1184649 0.04736226702 186 | 26.81648302078247 0.40335 0.1181546 0.04765765791 187 | 27.936503887176514 0.4069 0.117903 0.047974730699999996 188 | 29.066487312316895 0.4106 0.117591 0.0482828646 189 | 30.176307201385498 0.4142 0.1172813 0.04857791446 190 | 31.306463479995728 0.41735 0.1169608 0.04881358988 191 | 32.41627287864685 0.4206 0.1165813 0.049034094779999995 192 | 33.53527212142944 0.42395 0.1162412 0.04928045674 193 | 34.651543855667114 0.4268 0.115923 0.049475936400000003 194 | 35.76178693771362 0.4298 0.1154743 0.04963085414 195 | 36.88175439834595 0.4325 0.1152019 0.04982482175 196 | 37.99175047874451 0.43485 0.1148926 0.049961047110000004 197 | 39.10174298286438 0.43735 0.114505 0.05007876175 198 | 40.21173167228699 0.43945 0.1141362 0.050157153089999996 199 | 41.341750621795654 0.44135 0.113845 0.05024549075 200 | 42.46173977851868 0.44315 0.1135503 0.050319815445 201 | 43.581737756729126 0.44465 0.1132342 0.05034958703 202 | 44.7015426158905 0.4459 0.1130427 0.05040573993 203 | 45.81178402900696 0.4471 0.1128213 0.05044240323 204 | 46.93175148963928 0.44835 0.1125595 0.050466051825000004 205 | 48.06174445152283 0.4493 0.1123834 0.05049386162 206 | 49.18154573440552 0.4501 0.1122215 0.05051089715 207 | 50.28177762031555 0.4509 0.1120472 0.05052208248 208 | 51.40155553817749 0.4516 0.1119125 0.050539685 209 | 52.52175307273865 0.45215 0.1117854 0.05054376861 210 | 53.641550064086914 0.4527 0.1116494 0.050543683379999996 211 | 54.761542081832886 0.45315 0.1115661 0.050556178215 212 | 55.881755113601685 0.4536 0.1114558 0.050556350879999996 213 | 57.00155782699585 0.4539 0.1113679 0.050549889810000005 214 | 58.13172793388367 0.4542 0.1113014 0.050553095879999996 215 | 59.25172996520996 0.4546 0.111197 0.0505501562 216 | 60.37155365943909 0.4548 0.1111961 0.05057198628 217 | 61.49154353141785 0.45505 0.1111405 0.050574484525000005 218 | 62.60717511177063 0.45525 0.1110413 0.050551551825 219 | 63.725829124450684 0.45555 0.1110159 0.050573293245000005 220 | 64.84293222427368 0.45565 0.1109613 0.050559516345 221 | 65.93054008483887 0.45575 0.1109355 0.050558854125000004 222 | 67.04031920433044 0.4558 0.1109376 0.05056535808 223 | 68.17462539672852 0.4559 0.1109153 0.05056628527 224 | 69.31023406982422 0.456 0.1109095 0.050574732 225 | 70.41244721412659 0.4561 0.1108408 0.050554488880000005 226 | 71.51708030700684 0.4562 0.1108425 0.0505663485 227 | 72.6369297504425 0.4563 0.1108033 0.05055954578999999 228 | 73.75711154937744 0.45625 0.11084 0.05057075 229 | 74.86711931228638 0.45635 0.1107954 0.05056148079 230 | 75.98715329170227 0.4563 0.1108206 0.05056743978 231 | 77.11711239814758 0.45635 0.1107659 0.050548018465 232 | 78.2471067905426 0.45635 0.1107651 0.050547653385 233 | 79.36710238456726 0.45635 0.110792 0.0505599292 234 | 80.47711658477783 0.45625 0.1108215 0.050562309375 235 | 81.58712124824524 0.4564 0.1107899 0.050564510359999995 236 | 82.71712398529053 0.45635 0.1108046 0.05056567921 237 | 83.8371205329895 0.45635 0.1108147 0.050570288345 238 | 84.94712281227112 0.45635 0.1107971 0.05056225658499999 239 | 86.06712198257446 0.4563 0.1108222 0.05056816986 240 | 87.18713092803955 0.4563 0.1107982 0.05055721866 241 | 88.3171169757843 0.45635 0.1107776 0.05055335776 242 | 89.43789029121399 0.45635 0.1107861 0.050557236735 243 | 90.54798173904419 0.4564 0.1107553 0.05054871892 244 | 91.66778588294983 0.4564 0.1107915 0.0505652406 245 | 92.76800894737244 0.45635 0.1108105 0.050568371675 246 | 93.88800716400146 0.45635 0.11076 0.050545325999999995 247 | 95.0080099105835 0.45615 0.1108366 0.050558115089999994 248 | 96.1280164718628 0.4562 0.110813 0.0505528906 249 | 97.24801993370056 0.4562 0.1108134 0.050553073080000004 250 | 98.34783720970154 0.45625 0.1108038 0.05055423375 251 | 99.4680163860321 0.4563 0.1107911 0.05055397893 252 | 100.57780981063843 0.4563 0.1107957 0.05055607791 253 | 101.68802785873413 0.45645 0.1107469 0.050550422505 254 | 102.79805612564087 0.4563 0.1107225 0.05052267675 255 | 103.92801523208618 0.4563 0.1107999 0.05055799437 256 | 105.04802346229553 0.4563 0.1107713 0.050544944189999996 257 | 106.16800451278687 0.45635 0.1108185 0.050572022475 258 | 107.27799129486084 0.4563 0.1107662 0.050542617059999996 259 | 108.40283536911011 0.45635 0.1108025 0.050564720875 260 | 109.50349569320679 0.4563 0.110818 0.0505662534 261 | 110.60378551483154 0.45625 0.1108049 0.050554735625 262 | 111.72861576080322 0.45615 0.1108269 0.050553690435 263 | 112.82621717453003 0.4561 0.1108053 0.050538297329999995 264 | 113.92656898498535 0.45595 0.1108862 0.050558562890000006 265 | 115.01512503623962 0.456 0.1108874 0.0505646544 266 | 116.14402079582214 0.45595 0.1108365 0.050535902175 267 | 117.26377367973328 0.45605 0.1108491 0.050552732055 268 | 118.40400242805481 0.4561 0.1108567 0.05056174087 269 | 119.52401328086853 0.456 0.1108327 0.050539711200000004 270 | 271 | 272 | -------------------------------------------------------------------------------- /examples/SolarReference/png/gaas-ref/gaas-ref-mpp-tracking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/examples/SolarReference/png/gaas-ref/gaas-ref-mpp-tracking.png -------------------------------------------------------------------------------- /examples/SolarReference/png/gaas-ref/gaas-ref-sweep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/examples/SolarReference/png/gaas-ref/gaas-ref-sweep.png -------------------------------------------------------------------------------- /examples/SolarReference/png/gaas-ref/gaas-ref-voc-tracking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/examples/SolarReference/png/gaas-ref/gaas-ref-voc-tracking.png -------------------------------------------------------------------------------- /examples/SolarReference/png/si-ref/si-ref-mpp-tracking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/examples/SolarReference/png/si-ref/si-ref-mpp-tracking.png -------------------------------------------------------------------------------- /examples/SolarReference/png/si-ref/si-ref-sweep.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/examples/SolarReference/png/si-ref/si-ref-sweep.png -------------------------------------------------------------------------------- /examples/SolarReference/png/si-ref/si-ref-voc-tracking.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/examples/SolarReference/png/si-ref/si-ref-voc-tracking.png -------------------------------------------------------------------------------- /examples/SolarReference/png/stability/comp-ref-stability.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/examples/SolarReference/png/stability/comp-ref-stability.png -------------------------------------------------------------------------------- /examples/SolarReference/python/processStability.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import numpy as np 4 | 5 | # Import QVisaDataObject 6 | from PyQtVisa.utils import QVisaDataObject 7 | 8 | # Import matplotlib 9 | import matplotlib.pyplot as plt 10 | 11 | if __name__ == "__main__": 12 | 13 | # Path to data files 14 | paths = [ 15 | "../dat/Si/si-ref-stability.dat", 16 | "../dat/GaAs/gaas-ref-stability.dat" 17 | ] 18 | 19 | # Set up mpl figure 20 | fig = plt.figure() 21 | ax0 = fig.add_subplot(111) 22 | 23 | # Plot handle list 24 | hx = [] 25 | 26 | # Loop through paths 27 | for path in paths: 28 | 29 | # Build data object 30 | data = QVisaDataObject.QVisaDataObject() 31 | data.read_from_file( path ) 32 | 33 | # Extract data 34 | for _key in data.keys(): 35 | 36 | # Extract time 37 | time = data.get_subkey_data(_key, "t") 38 | 39 | # Extract voltage and current 40 | voltage = data.get_subkey_data(_key, "V") 41 | current = data.get_subkey_data(_key, "I") 42 | 43 | # Plot the data 44 | h, = ax0.plot(time, (1000. / 4.) * abs( np.array(current) ) ) 45 | hx.append(h) 46 | 47 | # Add axes lables and show plot 48 | ax0.set_title("AM1.5G Spectrum Stabilization") 49 | ax0.set_xlabel("Time $(s)$") 50 | ax0.set_ylabel("$J_{sc}$ $(mA/cm^2)$") 51 | ax0.legend( hx, ["Reference: Si ($25^{\\circ}C$)", "Reference: GaAs ($25^{\\circ}C$)"] ) 52 | 53 | # Show plot 54 | plt.show() -------------------------------------------------------------------------------- /examples/SolarReference/python/processSweep.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import numpy as np 4 | 5 | # Import QVisaDataObject 6 | from PyQtVisa.utils import QVisaDataObject 7 | 8 | # Import matplotlib 9 | import matplotlib.pyplot as plt 10 | 11 | # Routine to plot reference cell data and extract cell parameters 12 | if __name__ == "__main__": 13 | 14 | # Define refence cell 15 | ref_cell, ref_cell_area = "Si", 4.0 16 | 17 | if ref_cell == "Si": 18 | 19 | # Path to reference data file 20 | data_path = "../dat/Si/si-ref-sweep.dat" 21 | 22 | # Path to dump extracted measurement parameters 23 | extract_path = "../dat/Si/si-ref-extract.dat" 24 | 25 | if ref_cell == "GaAs": 26 | 27 | # Path to reference data file 28 | data_path = "../dat/GaAs/gaas-ref-sweep.dat" 29 | 30 | # Path to dump extracted measurement parameters 31 | extract_path = "../dat/GaAs/gaas-ref-extract.dat" 32 | 33 | # Build data object 34 | data = QVisaDataObject.QVisaDataObject() 35 | data.read_from_file( data_path ) 36 | 37 | # Set up mpl figure 38 | fig = plt.figure() 39 | ax0 = fig.add_subplot(111) 40 | ax1 = ax0.twinx() 41 | 42 | # List of measurements to exclude from plotting 43 | exclude = ["AM9.0", "AM10.0", "DARK"] 44 | 45 | # Extract data 46 | for _key in data.keys(): 47 | 48 | # Exclude certain keys 49 | if data.get_metadata(_key, "__desc__") not in exclude: 50 | 51 | # Extract time 52 | time = data.get_subkey_data(_key, "t") 53 | 54 | # Extract voltage and current 55 | voltage = data.get_subkey_data(_key, "V") 56 | current = data.get_subkey_data(_key, "I") 57 | 58 | # Plot the AM1.5G spectrum solid 59 | if data.get_metadata(_key, "__desc__") == "AM1.5G": 60 | 61 | ax0.plot( 62 | voltage, 63 | (-1000. / ref_cell_area) * np.array(current), 64 | color="tab:blue" 65 | ) 66 | 67 | ax1.plot( 68 | voltage, 69 | (-1000. ) * np.array(current) * voltage, 70 | color="tab:orange" 71 | ) 72 | 73 | # Approximate Voc and Jsc from measurement data 74 | idx = np.argmax( np.array(current) > 0.0) 75 | Voc = ( voltage[ idx ] + voltage[ idx - 1 ] ) / 2.0 76 | Jsc = ( current[ 0 ] ) * ( -1000. / ref_cell_area ) 77 | 78 | # Find max power 79 | P = np.array(voltage) * np.array(current) * (-1000 ) 80 | idx = np.where(P == np.amax(P))[0][0] 81 | Vm = voltage[idx] 82 | Jm = current[idx] * ( -1000. / ref_cell_area ) 83 | 84 | # Use pandas to create a dataframe 85 | ref_data = { 86 | "Voc" : Voc, 87 | "Isc" : current[ 0 ] * ( -1000.), 88 | "Jsc" : Jsc, 89 | "Vm" : Vm, 90 | "Im" : current[idx] * ( -1000.), 91 | "Jm" : Jm, 92 | "FF" : (Vm * Jm) / (Voc * Jsc), 93 | "ETA" : Vm * Jm 94 | } 95 | 96 | # Print ref_data into file 97 | with open( extract_path, "w" ) as f: 98 | 99 | f.write( "#! %s Reference: Extract\n\n"%(ref_cell) ) 100 | 101 | for key, val in ref_data.items(): 102 | 103 | f.write("%s\t\t %s\n"%(key, val) ) 104 | 105 | f.close() 106 | 107 | else: 108 | 109 | ax0.plot( 110 | voltage, 111 | (-1000. / ref_cell_area) * np.array(current), 112 | color="tab:blue", linestyle=":", linewidth=0.5 ) 113 | 114 | ax1.plot( 115 | voltage, 116 | (-1000 ) * np.array(current) * voltage, 117 | color="tab:orange", linestyle=":", linewidth=0.5 ) 118 | 119 | 120 | # Clean up the plot limits 121 | ax0.set_xlim(min(voltage), max(voltage)) 122 | 123 | # Si Reference 124 | if ref_cell == "Si": 125 | 126 | ax0.set_title("Si Reference : $AM[0.0\\ldots 8.0]$ : $T = 25^{\\circ}C$") 127 | ax0.set_ylim(0.0, 40) 128 | ax1.set_ylim(0.0, 60) 129 | 130 | # GaAs Reference 131 | if ref_cell == "GaAs": 132 | 133 | ax0.set_title("GaAs Reference : $AM[0.0\\ldots 8.0]$ : $T = 25^{\\circ}C$") 134 | ax0.set_ylim(0.0, 35) 135 | ax1.set_ylim(0.0, 110) 136 | 137 | # Set plot lables 138 | ax0.set_xlabel("Voltage $(V)$") 139 | ax0.set_ylabel("Current Density $(mA/cm^2)$") 140 | ax1.set_ylabel("Output Power $(mW)$") 141 | 142 | # Show the plot 143 | fig.tight_layout() 144 | plt.show() 145 | -------------------------------------------------------------------------------- /examples/SolarReference/python/processTracking.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import os 3 | import numpy as np 4 | 5 | # Import QVisaDataObject 6 | from PyQtVisa.utils import QVisaDataObject 7 | 8 | # Import matplotlib 9 | import matplotlib.pyplot as plt 10 | 11 | # Routine to plot reference cell data and extract cell parameters 12 | if __name__ == "__main__": 13 | 14 | # Define refence cell 15 | ref_cell, ref_cell_area = "Si", 4.0 16 | 17 | if ref_cell == "Si": 18 | 19 | # Path to reference data file 20 | data_path = "../dat/Si/si-ref-tracking.dat" 21 | 22 | 23 | if ref_cell == "GaAs": 24 | 25 | # Path to reference data file 26 | data_path = "../dat/GaAs/gaas-ref-tracking.dat" 27 | 28 | 29 | # Build data object 30 | data = QVisaDataObject.QVisaDataObject() 31 | data.read_from_file( data_path ) 32 | 33 | # Extract data 34 | for _key in data.keys(): 35 | 36 | # Voc tracking curves 37 | if data.get_metadata(_key, "__type__") == "pv-voc": 38 | 39 | # Set up mpl figure 40 | fig = plt.figure() 41 | ax0 = fig.add_subplot(111) 42 | ax1 = ax0.twinx() 43 | 44 | # Extract time 45 | time = data.get_subkey_data(_key, "t") 46 | 47 | # Extract voltage and current 48 | voltage = data.get_subkey_data(_key, "Voc") 49 | current = data.get_subkey_data(_key, "Ioc") 50 | 51 | # Plot Voc Data 52 | ax0.plot( time, voltage, "tab:blue") 53 | ax1.plot( time, (1000. / ref_cell_area) * np.array(current), "tab:orange" ) 54 | 55 | # Axes lables 56 | ax0.set_xlabel("Time $(s)$") 57 | ax0.set_ylabel("$V_{oc}$ $(V)$") 58 | ax1.set_ylabel("$J_{sc}$ $(mA/cm^2)$") 59 | 60 | # Axes title 61 | ax0.set_title("%s Reference : $V_{oc}$ Tracking : $AM1.5G$ : $T = 25^{\\circ}C$"%(ref_cell)) 62 | 63 | # Vmpp tracking curves 64 | if data.get_metadata(_key, "__type__") == "pv-mpp": 65 | 66 | # Set up mpl figure 67 | fig = plt.figure() 68 | ax0 = fig.add_subplot(111) 69 | ax1 = ax0.twinx() 70 | 71 | # Extract time 72 | time = data.get_subkey_data(_key, "t") 73 | 74 | # Extract voltage and current 75 | voltage = data.get_subkey_data(_key, "Vmpp") 76 | power = data.get_subkey_data(_key, "Pmpp") 77 | 78 | # Plot Voc Data 79 | ax0.plot( time, voltage, "tab:blue") 80 | ax1.plot( time, 1000. * np.array(power), "tab:orange" ) 81 | 82 | # Axes lables 83 | ax0.set_xlabel("Time $(s)$") 84 | ax0.set_ylabel("$V_{mpp}$ $(V)$") 85 | ax1.set_ylabel("$P_{mpp}$ $(mW)$") 86 | 87 | # Axes title 88 | ax0.set_title("%s Reference : MPP Tracking : $AM1.5G$ : $T = 25^{\\circ}C$"%(ref_cell)) 89 | 90 | plt.show() 91 | -------------------------------------------------------------------------------- /src/QKeithleyMain.py: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------------- 2 | # QKeithleyControl -> QMainWindow 3 | # Copyright (C) 2019 Michael Winters 4 | # github: https://github.com/mesoic 5 | # email: mesoic@protonmail.com 6 | # --------------------------------------------------------------------------------- 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | #!/usr/bin/env python 28 | import os 29 | import threading 30 | 31 | # Import Keithley control widgets 32 | from src.app.QKeithleyConfig import QKeithleyConfig 33 | from src.app.QKeithleyBias import QKeithleyBias 34 | from src.app.QKeithleySweep import QKeithleySweep 35 | from src.app.QKeithleySolar import QKeithleySolar 36 | 37 | # Import QT backends 38 | from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QAction, QStackedWidget, QMessageBox, QMenu 39 | from PyQt5.QtCore import Qt, QUrl 40 | from PyQt5.QtGui import QIcon, QDesktopServices 41 | 42 | # Subclass QMainWindow to customise your application's main window 43 | class QKeithleyMain(QMainWindow): 44 | 45 | def __init__(self, _application, *args, **kwargs): 46 | 47 | # Instantiate super 48 | super(QKeithleyMain, self).__init__(*args, **kwargs) 49 | 50 | # Application handle and window title 51 | self.app = _application 52 | self.version = '1.2' 53 | self.setWindowTitle("QKeithleyControl (v%s)"%self.version) 54 | 55 | # Create Icon for QMainWindow and QMessageBox 56 | self.icon = QIcon(os.path.join(os.path.dirname(os.path.realpath(__file__)), "python.ico")) 57 | self.setWindowIcon(self.icon) 58 | 59 | # Generate main menu and toplevel widget. We will 60 | # Render our controls into self.toplevel on menu selection 61 | self._gen_menu() 62 | self.ui_stack = QStackedWidget(self) 63 | 64 | # Create QVisaWidget for configuration mode 65 | self.ui_config = QKeithleyConfig() 66 | 67 | # Create QVisaWidget for each measurement mode 68 | self.ui_bias = QKeithleyBias(self.ui_config) 69 | self.ui_sweep = QKeithleySweep(self.ui_config) 70 | self.ui_solar = QKeithleySolar(self.ui_config) 71 | 72 | # Add ui-mode widgets to stack 73 | self.ui_stack.addWidget(self.ui_config) 74 | self.ui_stack.addWidget(self.ui_bias) 75 | self.ui_stack.addWidget(self.ui_sweep) 76 | self.ui_stack.addWidget(self.ui_solar) 77 | 78 | # Set window central widget to stacked widget 79 | self.setCentralWidget(self.ui_stack) 80 | 81 | # Callback to handle main menu actions. For each menu action, need 82 | # to check to see if there are any application threads running 83 | # other than main thread (i.e. if there are ongoing measurements). 84 | def main_menu_callback(self, q): 85 | 86 | if q.text() == "Hardware Config" and self.ui_stack.currentIndex() != 0: 87 | 88 | if len( threading.enumerate() ) > 1: 89 | self.thread_running_msg() 90 | else: 91 | self.ui_stack.setCurrentIndex(0) 92 | 93 | if q.text() == "IV-Bias Control" and self.ui_stack.currentIndex() != 1: 94 | 95 | if len( threading.enumerate() ) > 1: 96 | self.thread_running_msg() 97 | else: 98 | self.ui_bias.refresh() 99 | self.ui_stack.setCurrentIndex(1) 100 | 101 | if q.text() == "IV-Sweep Control" and self.ui_stack.currentIndex() != 2: 102 | 103 | if len( threading.enumerate() ) > 1: 104 | self.thread_running_msg() 105 | else: 106 | self.ui_sweep.refresh() 107 | self.ui_stack.setCurrentIndex(2) 108 | 109 | if q.text() == "PV-Tracking" and self.ui_stack.currentIndex() != 3: 110 | 111 | if len( threading.enumerate() ) > 1: 112 | self.thread_running_msg() 113 | else: 114 | self.ui_solar.refresh() 115 | self.ui_stack.setCurrentIndex(3) 116 | 117 | if q.text() == "Exit": 118 | 119 | if len( threading.enumerate() ) > 1: 120 | self.thread_running_msg() 121 | 122 | # Otherwise enter the close dialog 123 | else: 124 | self.ui_config.close_devices() 125 | self.app.exit() 126 | 127 | # Message box for thread running 128 | def thread_running_msg(self): 129 | 130 | # Dialogue to check quit 131 | msg = QMessageBox() 132 | msg.setIcon(QMessageBox.Warning) 133 | msg.setText("Measurement is running") 134 | msg.setWindowTitle("QKeithleyControl") 135 | msg.setWindowIcon(self.icon) 136 | msg.setStandardButtons(QMessageBox.Ok) 137 | msg.exec_() 138 | 139 | # Callback to handle help menu actions 140 | def help_menu_callback(self, q): 141 | 142 | if q.text() == "Documentation": 143 | QDesktopServices.openUrl( QUrl( "https://github.com/mesoic/QKeithleyControl") ) 144 | 145 | if q.text() == "About": 146 | 147 | # Message box to display error 148 | msg = QMessageBox() 149 | msg.setWindowTitle("QKeithleyControl") 150 | msg.setWindowIcon(self.icon) 151 | msg.setText("

QKeithleyControl

Version 1.1 ©2019-2020 by github.com/mesoic

QKeithleyControl is open source software built on the PyQtVisa framework.

") 152 | msg.setStandardButtons(QMessageBox.Ok) 153 | msg.exec_() 154 | 155 | # Callback to handle x-button closeEvent 156 | def closeEvent(self, q): 157 | 158 | # Check to see if there are any threads running 159 | # other than main thread 160 | if len( threading.enumerate() ) > 1: 161 | 162 | # Dialogue to check quit 163 | msg = QMessageBox() 164 | msg.setIcon(QMessageBox.Warning) 165 | msg.setText("Measurement is running") 166 | msg.setWindowTitle("QKeithleyControl") 167 | msg.setWindowIcon(self.icon) 168 | msg.setStandardButtons(QMessageBox.Ok) 169 | self.msg_quit = msg.exec_() 170 | 171 | q.ignore() 172 | 173 | # Otherwise enter the close dialog 174 | else: 175 | 176 | # Dialogue to check quit 177 | msg = QMessageBox() 178 | msg.setIcon(QMessageBox.Information) 179 | msg.setText("Are you sure you want to quit?") 180 | msg.setWindowTitle("QKeithleyControl") 181 | msg.setWindowIcon(self.icon) 182 | msg.setStandardButtons(QMessageBox.No | QMessageBox.Yes) 183 | self.msg_quit = msg.exec_() 184 | 185 | if self.msg_quit == QMessageBox.Yes: 186 | 187 | # Clean up pyvisa device sessions 188 | self.ui_config.close_devices() 189 | q.accept() 190 | 191 | else: 192 | q.ignore() 193 | 194 | # Generate Menu 195 | def _gen_menu(self): 196 | 197 | # Main Menu 198 | self.menu_bar = self.menuBar() 199 | 200 | # Add a selector menu items 201 | self.main_menu = self.menu_bar.addMenu('Select Measurement') 202 | 203 | # Add submenu for applications 204 | self.app_submenu = QMenu("Applications", parent=self.main_menu) 205 | 206 | # Bias Mode 207 | self.app_bias = QAction("IV-Bias Control",self) 208 | self.app_submenu.addAction(self.app_bias) 209 | 210 | # Sweep Mode 211 | self.app_sweep = QAction("IV-Sweep Control",self) 212 | self.app_submenu.addAction(self.app_sweep) 213 | 214 | # Solar Mode 215 | self.app_solar = QAction("PV-Tracking") 216 | self.app_submenu.addAction(self.app_solar) 217 | 218 | # Add app submenu to main menu 219 | self.main_menu.addMenu(self.app_submenu) 220 | 221 | # Add hardware configuration app 222 | self.app_config = QAction("Hardware Config",self) 223 | self.main_menu.addAction(self.app_config) 224 | 225 | # Add exit app 226 | self.app_exit = QAction("Exit",self) 227 | self.main_menu.addAction(self.app_exit) 228 | 229 | # Add a selector menu items 230 | self.help_menu = self.menu_bar.addMenu('Help') 231 | 232 | self.app_docs = QAction("Documentation",self) 233 | self.help_menu.addAction(self.app_docs) 234 | 235 | self.app_about = QAction("About",self) 236 | self.help_menu.addAction(self.app_about) 237 | 238 | # Close button cleanup 239 | self.finish = QAction("Quit", self) 240 | self.finish.triggered.connect(self.closeEvent) 241 | 242 | # Callback Triggered 243 | self.main_menu.triggered[QAction].connect(self.main_menu_callback) 244 | self.help_menu.triggered[QAction].connect(self.help_menu_callback) 245 | 246 | 247 | # Method to generate warning box 248 | def _gen_warning_box(self, _title, _text): 249 | 250 | # Message box to display error 251 | msg = QMessageBox() 252 | msg.setWindowTitle(_title) 253 | msg.setWindowIcon(self.icon) 254 | msg.setIcon(QMessageBox.Warning) 255 | msg.setText(_text) 256 | msg.setStandardButtons(QMessageBox.Ok) 257 | msg.exec_() 258 | -------------------------------------------------------------------------------- /src/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/src/__init__.py -------------------------------------------------------------------------------- /src/app/QKeithleyBias.py: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------------- 2 | # QKeithleyBias -> QVisaApplication 3 | # Copyright (C) 2019 Michael Winters 4 | # github: https://github.com/mesoic 5 | # email: mesoic@protonmail.com 6 | # --------------------------------------------------------------------------------- 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | #!/usr/bin/env python 28 | import os 29 | 30 | # Import QVisaApplication 31 | from PyQtVisa import QVisaApplication 32 | 33 | # Import QKeithleyWidget 34 | from src.widgets.QKeithleyBiasWidget import QKeithleyBiasWidget 35 | 36 | # Import QT backends 37 | from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QStackedWidget, QLabel 38 | from PyQt5.QtGui import QIcon 39 | 40 | 41 | # Container class to construct bias measurement widget 42 | class QKeithleyBias(QVisaApplication.QVisaApplication): 43 | 44 | def __init__(self, _config): 45 | 46 | # Inherits QVisaApplication -> QWidget 47 | super(QKeithleyBias, self).__init__(_config) 48 | 49 | # Generate Main Layout 50 | self.gen_main_layout() 51 | 52 | # Method to refresh the widget 53 | def refresh(self): 54 | 55 | # If add insturments have been initialized 56 | if self.get_devices() is not None: 57 | 58 | # Get all available insturment names 59 | for _name in self.get_device_names(): 60 | 61 | # Check if name has already been registered to inst widget 62 | if self.device_select.isRegistered(_name) == False: 63 | 64 | # If not rgister it and add output widget to stack 65 | self.device_select.registerInst(_name) 66 | 67 | # Generate bias widget 68 | self.bias_widgets[_name] = QKeithleyBiasWidget(self, _name) 69 | 70 | # Add widgets to layout 71 | self.outputs.addWidget(self.bias_widgets[_name].get_output_widget()) 72 | self.ctrls.addWidget(self.bias_widgets[_name].get_ctrl_widget()) 73 | self.plots.addWidget(self.bias_widgets[_name].get_plot_widget()) 74 | 75 | # Force update bias pages 76 | self.update_bias_pages() 77 | 78 | # Update all widgets 79 | def update_bias_pages(self): 80 | 81 | # Get current name 82 | _name = self.device_select.currentText() 83 | 84 | # Check if name has been added to bias widgets 85 | if _name in self.bias_widgets.keys(): 86 | 87 | # Call set current widget method 88 | self.outputs.setCurrentWidget(self.bias_widgets[_name].get_output_widget()) 89 | self.ctrls.setCurrentWidget(self.bias_widgets[_name].get_ctrl_widget()) 90 | self.plots.setCurrentWidget(self.bias_widgets[_name].get_plot_widget()) 91 | 92 | # Sync meta widget to data object 93 | def _sync_meta_widget_to_data_object(self): 94 | 95 | # Application keys 96 | _data_keys = self._get_data_object().keys() 97 | _widget_keys = self.meta_widget.get_meta_keys() 98 | 99 | # Check if widget keys are not in data keys 100 | for _key in _widget_keys: 101 | 102 | # If not then delete the key from meta_widget 103 | if _key not in _data_keys: 104 | 105 | self.meta_widget.del_meta_key(_key) 106 | 107 | # Main Layout 108 | def gen_main_layout(self): 109 | 110 | # Create Icon for QMessageBox 111 | self._set_icon( QIcon(os.path.join(os.path.dirname(os.path.realpath(__file__)), "python.ico"))) 112 | 113 | # Dictionary to hold QKeithleyBiasWidgets 114 | self.bias_widgets = {} 115 | 116 | # Create layout objects and set layout 117 | self.layout = QHBoxLayout() 118 | 119 | ##################################### 120 | # CONTROLS LAYOUT 121 | # 122 | 123 | self.meas_layout = QVBoxLayout() 124 | 125 | # Create dummy widgets for visaul symmetry 126 | self.bias_widgets["__none__"] = QKeithleyBiasWidget(self, "__none__") 127 | 128 | # Bias output buttons 129 | self.outputs = QStackedWidget() 130 | self.outputs.addWidget(self.bias_widgets["__none__"].get_output_widget()) 131 | 132 | # Insturement selector 133 | self.device_select_label = QLabel("Select Output") 134 | self.device_select = self._gen_device_select() 135 | self.device_select.setFixedWidth(200) 136 | self.device_select.set_callback("update_bias_pages") 137 | 138 | # Controls for source 139 | self.ctrls = QStackedWidget() 140 | self.ctrls.addWidget(self.bias_widgets["__none__"].get_ctrl_widget()) 141 | 142 | # Meta widget for trace description 143 | self.meta_widget_label = QLabel("Trace Description") 144 | self.meta_widget = self._gen_meta_widget() 145 | self.meta_widget.set_meta_subkey("__desc__") 146 | 147 | # Save widget 148 | self.save_widget = self._gen_save_widget() 149 | 150 | # Pack widgets 151 | self.meas_layout.addWidget(self.outputs) 152 | self.meas_layout.addWidget(self._gen_hbox_widget([self.device_select, self.device_select_label])) 153 | self.meas_layout.addWidget(self.ctrls) 154 | self.meas_layout.addStretch(1) 155 | self.meas_layout.addWidget(self.meta_widget_label) 156 | self.meas_layout.addWidget(self.meta_widget) 157 | self.meas_layout.addWidget(self.save_widget) 158 | 159 | ##################################### 160 | # PLOT LAYOUT 161 | # 162 | 163 | # Plotting 164 | self.plot_layout = QVBoxLayout() 165 | self.plots = QStackedWidget() 166 | self.plots.addWidget(self.bias_widgets["__none__"].get_plot_widget()) 167 | self.plot_layout.addWidget(self.plots) 168 | 169 | # Add layouts to main layout and set layout 170 | self.layout.addLayout(self.meas_layout, 1) 171 | self.layout.addLayout(self.plot_layout, 3) 172 | self.setLayout(self.layout) 173 | -------------------------------------------------------------------------------- /src/app/QKeithleyConfig.py: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------------- 2 | # QKeithleyConfigure -> QVisaConfigure 3 | # Copyright (C) 2019 Michael Winters 4 | # github: https://github.com/mesoic 5 | # email: mesoic@protonmail.com 6 | # --------------------------------------------------------------------------------- 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | #!/usr/bin/env python 28 | import time 29 | import pyvisa 30 | import numpy as np 31 | 32 | # Import device drivers 33 | from PyQtVisa.drivers import keithley2400 34 | 35 | # Import QVisaConfigure 36 | from PyQtVisa import QVisaConfigure 37 | 38 | # Import QKeithleyWidget 39 | from src.widgets.QKeithleyConfigWidget import QKeithleyConfigWidget 40 | 41 | # Import QT backends 42 | import os 43 | import sys 44 | from PyQt5.QtWidgets import QWidget, QMessageBox, QVBoxLayout, QHBoxLayout, QComboBox, QSpinBox, QPushButton, QLabel, QStackedWidget, QDoubleSpinBox 45 | from PyQt5.QtCore import Qt, QSize 46 | from PyQt5.QtGui import QIcon 47 | 48 | # Configuration application to initalize and manage multiple Keithley insturments 49 | # in a single context handles. Devices are uniquely addressable via QVisaConfigure 50 | # built-ins 51 | class QKeithleyConfig(QVisaConfigure.QVisaConfigure): 52 | 53 | def __init__(self): 54 | 55 | # Inherits QVisaConfigure -> QWidget 56 | super(QKeithleyConfig, self).__init__() 57 | 58 | # Create Icon for QMessageBox 59 | self.gen_main_layout() 60 | 61 | # Main layout 62 | def gen_main_layout(self): 63 | 64 | # Create configuration layout 65 | self._layout = QVBoxLayout() 66 | 67 | # Set application icon 68 | self._icon = QIcon(os.path.join(os.path.dirname(os.path.realpath(__file__)), "python.ico")) 69 | 70 | # Insturment initialization widget 71 | self._device_widget = self._gen_device_control() 72 | self._device_widget.set_init_callback("init_keithley") 73 | self._device_widget.set_select_callback("update_device_pages") 74 | 75 | # QStackedWidget for insturment configurations 76 | self.device_pages = QStackedWidget() 77 | 78 | # Add comm widget and inst pages 79 | self._layout.addWidget(self._device_widget) 80 | self._layout.addStretch(1) 81 | self._layout.addWidget(self.device_pages) 82 | 83 | # Set application layout 84 | self.setLayout(self._layout) 85 | self.setFixedWidth(350) 86 | 87 | 88 | # Callback to handle addr initialization 89 | def init_keithley(self): 90 | 91 | # Initialize Keithley 92 | Device = self._device_widget.init( keithley2400.keithley2400 ) 93 | 94 | # Build configuration widget for Keithley 95 | if Device is not None: 96 | self.device_pages.addWidget( QKeithleyConfigWidget( self, Device.get_property("name") ) ) 97 | 98 | 99 | # This will update the QStackedWidget to show the correct QKeithleyWidget 100 | def update_device_pages(self): 101 | 102 | # Get current text 103 | Device = self._device_widget.get_current_device() 104 | if Device is not None: 105 | 106 | # Loop through QStacked widget children 107 | for _page in list( self.device_pages.findChildren(QKeithleyConfigWidget) ): 108 | 109 | # If insturment name matches page name 110 | if _page.name == Device.get_property("name"): 111 | 112 | # Set widget page 113 | self.device_pages.setCurrentWidget(_page) -------------------------------------------------------------------------------- /src/app/QKeithleySolar.py: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------------- 2 | # QKeithleySolar -> QVisaApplication 3 | # Copyright (C) 2019 Michael Winters 4 | # github: https://github.com/mesoic 5 | # email: mesoic@protonmail.com 6 | # --------------------------------------------------------------------------------- 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | #!/usr/bin/env python 28 | import os 29 | import sys 30 | import time 31 | import html 32 | import threading 33 | 34 | # Import numpy 35 | import numpy as np 36 | 37 | # Import QVisaApplication 38 | from PyQtVisa import QVisaApplication 39 | 40 | # Import PyQtVisa widgets 41 | from PyQtVisa.widgets import QVisaUnitSelector 42 | from PyQtVisa.widgets import QVisaDynamicPlot 43 | 44 | # Import QT backends 45 | from PyQt5.QtWidgets import QApplication, QWidget, QStackedWidget, QVBoxLayout, QHBoxLayout, QMessageBox, QComboBox, QSpinBox, QDoubleSpinBox, QPushButton, QCheckBox, QLabel, QFileDialog, QSizePolicy, QLineEdit 46 | from PyQt5.QtCore import Qt, QStateMachine, QState, QObject 47 | from PyQt5.QtGui import QIcon 48 | 49 | # Container class to construct photovoltaic characterization widget 50 | class QKeithleySolar(QVisaApplication.QVisaApplication): 51 | 52 | def __init__(self, _config): 53 | 54 | # Inherits QVisaApplication -> QWidget 55 | super(QKeithleySolar, self).__init__(_config) 56 | 57 | # Generate Main Layout 58 | self.gen_main_layout() 59 | 60 | 61 | ##################################### 62 | # APPLICATION HELPER METHODS 63 | # 64 | 65 | # Wrapper method to get keitley write handle 66 | # Returns the pyVisaDevice object 67 | def keithley(self): 68 | return self.get_device_by_name( self.device_select.currentText() ) 69 | 70 | # Update bias on keithley 71 | def update_bias(self, _value): 72 | if self.keithley() is not None: 73 | self.keithley().set_voltage(_value) 74 | 75 | # Method to refresh the widget 76 | def refresh(self): 77 | 78 | # If add insturments have been initialized 79 | if self.get_devices() is not None: 80 | 81 | # Reset the widget and add insturments 82 | self.device_select.refresh( self ) 83 | 84 | # Enable measurement buttons 85 | self.voc_meas_button.setEnabled(True) 86 | self.mpp_meas_button.setEnabled(True) 87 | 88 | else: 89 | 90 | # Disable measurement buttons 91 | self.voc_meas_button.setEnabled(False) 92 | self.mpp_meas_button.setEnabled(False) 93 | 94 | 95 | ##################################### 96 | # SOLAR APP MAIN LAYOUTS 97 | # 98 | # *) gen_main_layout() 99 | # 1) gen_solar_ctrl() 100 | # a) gen_voc_ctrl() 101 | # b) gen_mpp_crtl() 102 | # 2) gen_solar_plot() 103 | # 104 | 105 | def gen_main_layout(self): 106 | 107 | # Create Icon for QMessageBox 108 | self._set_icon( QIcon(os.path.join(os.path.dirname(os.path.realpath(__file__)), "python.ico")) ) 109 | 110 | # Create layout objects and set layout 111 | self.layout = QHBoxLayout() 112 | self.layout.addLayout(self.gen_solar_ctrl(), 1) 113 | self.layout.addWidget(self.gen_solar_plot(), 3) 114 | self.setLayout(self.layout) 115 | 116 | 117 | # Method to generate solar characterization controls 118 | def gen_solar_ctrl(self): 119 | 120 | # Solar mode layout 121 | self.ctl_layout = QVBoxLayout() 122 | 123 | # Add insturement selector 124 | self.device_select_label = QLabel("Select Device") 125 | self.device_select = self._gen_device_select() 126 | self.device_select.setFixedWidth(200) 127 | 128 | # Generate (IV, Voc, MPP) container widgets 129 | # These methods will pack self.inst_select 130 | self.gen_voc_ctrl() # self.voc_ctrl 131 | self.gen_mpp_ctrl() # self.mpp_ctrl 132 | 133 | # Add measurement widgets to QStackedWidget 134 | self.meas_pages = QStackedWidget() 135 | self.meas_pages.addWidget(self.voc_ctrl) 136 | self.meas_pages.addWidget(self.mpp_ctrl) 137 | self.meas_pages.setCurrentIndex(0); 138 | 139 | # Measurement select QComboBox 140 | self.meas_select_label = QLabel("Measurement Mode") 141 | self.meas_select = QComboBox() 142 | self.meas_select.setFixedWidth(200) 143 | self.meas_select.addItems(["Voc", "MPP"]) 144 | self.meas_select.currentTextChanged.connect(self.update_meas_pages) 145 | 146 | # Include convergence data checkbox 147 | self.meas_conv = QCheckBox("Include Convergence Data") 148 | 149 | # Meta widget for trace description 150 | self.meta_widget_label = QLabel("Trace Description") 151 | self.meta_widget = self._gen_meta_widget() 152 | self.meta_widget.set_meta_subkey("__desc__") 153 | self.save_widget = self._gen_save_widget() 154 | 155 | 156 | ##################################### 157 | # ADD CONTROLS 158 | # 159 | 160 | # Add measurement select and measurement pages 161 | self.ctl_layout.addWidget(self.meas_pages) 162 | self.ctl_layout.addWidget(self._gen_hbox_widget([self.meas_select, self.meas_select_label])) 163 | self.ctl_layout.addWidget(self._gen_hbox_widget([self.device_select,self.device_select_label])) 164 | self.ctl_layout.addWidget(self.meas_conv) 165 | 166 | # Pack the standard save widget 167 | self.ctl_layout.addStretch(1) 168 | self.ctl_layout.addWidget(self.meta_widget_label) 169 | self.ctl_layout.addWidget(self.meta_widget) 170 | self.ctl_layout.addWidget(self.save_widget) 171 | 172 | # Positioning 173 | self.ctl_layout.setContentsMargins(0,15,0,20) 174 | return self.ctl_layout 175 | 176 | 177 | ##################################### 178 | # MEASUREMENT MODE CONTROLS 179 | # 180 | 181 | # Method to generate Voc controls 182 | def gen_voc_ctrl(self): 183 | 184 | # Voc control layout 185 | self.voc_ctrl = QWidget() 186 | self.voc_ctrl_layout = QVBoxLayout() 187 | 188 | # Create QStateMachine for output state 189 | self.voc_state = QStateMachine() 190 | self.voc_meas_button = QPushButton() 191 | self.voc_meas_button.setStyleSheet( 192 | "background-color: #dddddd; border-style: solid; border-width: 1px; border-color: #aaaaaa; padding: 7px;" ) 193 | 194 | # Create output states 195 | self.voc_meas_off = QState() 196 | self.voc_meas_on = QState() 197 | 198 | # Attach states to output button and define state transitions 199 | self.voc_meas_off.assignProperty(self.voc_meas_button, 'text', 'Voc Monitor OFF') 200 | self.voc_meas_off.addTransition(self.voc_meas_button.clicked, self.voc_meas_on) 201 | self.voc_meas_off.entered.connect(self.exec_voc_stop) 202 | 203 | self.voc_meas_on.assignProperty(self.voc_meas_button, 'text', 'Voc Monitor ON') 204 | self.voc_meas_on.addTransition(self.voc_meas_button.clicked, self.voc_meas_off) 205 | self.voc_meas_on.entered.connect(self.exec_voc_run) 206 | 207 | # Add states, set initial state, and start machine 208 | self.voc_state.addState(self.voc_meas_off) 209 | self.voc_state.addState(self.voc_meas_on) 210 | self.voc_state.setInitialState(self.voc_meas_off) 211 | self.voc_state.start() 212 | 213 | # Tracking mode initialization 214 | # Note this example of passing arguments to a callback 215 | self.voc_bias_config={ 216 | "unit" : "V", 217 | "min" : "m", 218 | "max" : "", 219 | "label" : "Voc Initialization (V)", 220 | "signed" : True, 221 | "limit" : [2.0, ""], 222 | "default" : [0.0, ""] 223 | } 224 | self.voc_bias = QVisaUnitSelector.QVisaUnitSelector(self.voc_bias_config) 225 | self.voc_bias.unit_value.valueChanged.connect(lambda arg=self.voc_bias.value(): self.update_bias(arg)) 226 | 227 | # Compliance Spinbox 228 | self.voc_cmpl_config={ 229 | "unit" : "A", 230 | "min" : "u", 231 | "max" : "", 232 | "label" : "Compliance (A)", 233 | "signed" : False, 234 | "limit" : [1.0, "" ], 235 | "default" : [150, "m"] 236 | } 237 | self.voc_cmpl = QVisaUnitSelector.QVisaUnitSelector(self.voc_cmpl_config) 238 | 239 | # Tracking mode convergence 240 | self.voc_ampl_config={ 241 | "unit" : "V", 242 | "min" : "u", 243 | "max" : "m", 244 | "label" : "Sense amplitude (mV)", 245 | "signed" : False, 246 | "limit" : [100.,"m"], 247 | "default" : [1.0 ,"m"] 248 | } 249 | self.voc_ampl = QVisaUnitSelector.QVisaUnitSelector(self.voc_ampl_config) 250 | 251 | # Convergence value 252 | self.voc_conv_config={ 253 | "unit" : "", 254 | "min" : "u", 255 | "max" : "", 256 | "label" : "Convergence", 257 | "signed" : False, 258 | "limit" : [10., "" ], 259 | "default" : [1.0, "m"] 260 | } 261 | self.voc_conv = QVisaUnitSelector.QVisaUnitSelector(self.voc_conv_config) 262 | 263 | # Delay 264 | self.voc_gain_config={ 265 | "unit" : "__DOUBLE__", 266 | "label" : html.unescape("Proportional Gain (‰)"), 267 | "signed" : False, 268 | "limit" : [1000], 269 | "default" : [30.0] 270 | } 271 | self.voc_gain = QVisaUnitSelector.QVisaUnitSelector(self.voc_gain_config) 272 | 273 | # Delay 274 | self.voc_delay_config={ 275 | "unit" : "__DOUBLE__", 276 | "label" : "Measurement Interval (s)", 277 | "signed" : False, 278 | "limit" : [60.0], 279 | "default" : [0.10] 280 | } 281 | self.voc_delay = QVisaUnitSelector.QVisaUnitSelector(self.voc_delay_config) 282 | 283 | # Add voc widgets to layout 284 | self.voc_ctrl_layout.addWidget(self.voc_meas_button) 285 | self.voc_ctrl_layout.addWidget(self.voc_bias) 286 | self.voc_ctrl_layout.addWidget(self.voc_cmpl) 287 | self.voc_ctrl_layout.addWidget(self.voc_ampl) 288 | self.voc_ctrl_layout.addWidget(self.voc_conv) 289 | self.voc_ctrl_layout.addWidget(self.voc_gain) 290 | self.voc_ctrl_layout.addWidget(self.voc_delay) 291 | 292 | self.voc_ctrl_layout.setContentsMargins(0,0,0,0) 293 | 294 | # Set widget layout 295 | self.voc_ctrl.setLayout(self.voc_ctrl_layout) 296 | 297 | 298 | # Method to generate MPP controls 299 | def gen_mpp_ctrl(self): 300 | 301 | ################################# 302 | # mpp tracking controls 303 | # 304 | self.mpp_ctrl = QWidget() 305 | self.mpp_ctrl_layout = QVBoxLayout() 306 | 307 | 308 | # Create QStateMachine for output state 309 | self.mpp_state = QStateMachine() 310 | self.mpp_meas_button = QPushButton() 311 | self.mpp_meas_button.setStyleSheet( 312 | "background-color: #dddddd; border-style: solid; border-width: 1px; border-color: #aaaaaa; padding: 7px;" ) 313 | 314 | # Create output states 315 | self.mpp_meas_off = QState() 316 | self.mpp_meas_on = QState() 317 | 318 | # Attach states to output button and define state transitions 319 | self.mpp_meas_off.assignProperty(self.mpp_meas_button, 'text', 'MPP Monitor OFF') 320 | self.mpp_meas_off.addTransition(self.mpp_meas_button.clicked, self.mpp_meas_on) 321 | self.mpp_meas_off.entered.connect(self.exec_mpp_stop) 322 | 323 | self.mpp_meas_on.assignProperty(self.mpp_meas_button, 'text', 'MPP Monitor ON') 324 | self.mpp_meas_on.addTransition(self.mpp_meas_button.clicked, self.mpp_meas_off) 325 | self.mpp_meas_on.entered.connect(self.exec_mpp_run) 326 | 327 | # Add states, set initial state, and start machine 328 | self.mpp_state.addState(self.mpp_meas_off) 329 | self.mpp_state.addState(self.mpp_meas_on) 330 | self.mpp_state.setInitialState(self.mpp_meas_off) 331 | self.mpp_state.start() 332 | 333 | # Tracking mode initialization 334 | # Note this example of passing arguments to a callback 335 | self.mpp_bias_config={ 336 | "unit" : "V", 337 | "min" : "m", 338 | "max" : "", 339 | "label" : "MPP Initialization (V)", 340 | "signed" : True, 341 | "limit" : [2.00, ""], 342 | "default" : [0.00, ""] 343 | } 344 | self.mpp_bias = QVisaUnitSelector.QVisaUnitSelector(self.mpp_bias_config) 345 | self.mpp_bias.unit_value.valueChanged.connect(lambda arg=self.mpp_bias.value(): self.update_bias(arg)) 346 | 347 | # Compliance Spinbox 348 | self.mpp_cmpl_config={ 349 | "unit" : "A", 350 | "min" : "u", 351 | "max" : "", 352 | "label" : "Compliance (A)", 353 | "signed" : False, 354 | "limit" : [1.0, "" ], 355 | "default" : [150, "m"] 356 | } 357 | self.mpp_cmpl = QVisaUnitSelector.QVisaUnitSelector(self.mpp_cmpl_config) 358 | 359 | # Tracking mode convergence 360 | self.mpp_ampl_config={ 361 | "unit" : "V", 362 | "min" : "u", 363 | "max" : "m", 364 | "label" : "Sense amplitude (mV)", 365 | "signed" : False, 366 | "limit" : [100., "m"], 367 | "default" : [10.0, "m"] 368 | } 369 | self.mpp_ampl = QVisaUnitSelector.QVisaUnitSelector(self.mpp_ampl_config) 370 | 371 | # Convergence value 372 | self.mpp_conv_config ={ 373 | "unit" : "", 374 | "min" : "u", 375 | "max" : "", 376 | "label" : "Convergence", 377 | "signed" : False, 378 | "limit" : [10., "" ], 379 | "default" : [10., "m"] 380 | } 381 | self.mpp_conv = QVisaUnitSelector.QVisaUnitSelector(self.mpp_conv_config) 382 | 383 | # Delay 384 | self.mpp_gain_config={ 385 | "unit" : "__DOUBLE__", 386 | "label" : html.unescape("Proportional Gain (‰)"), 387 | "signed" : False, 388 | "limit" : [1000], 389 | "default" : [30.0] 390 | } 391 | self.mpp_gain = QVisaUnitSelector.QVisaUnitSelector(self.mpp_gain_config) 392 | 393 | 394 | # Delay 395 | self.mpp_delay_config={ 396 | "unit" : "__DOUBLE__", 397 | "label" : "Measurement Interval (s)", 398 | "signed" : False, 399 | "limit" : [60.0], 400 | "default" : [0.10] 401 | } 402 | self.mpp_delay = QVisaUnitSelector.QVisaUnitSelector(self.mpp_delay_config) 403 | 404 | # Add mpp widgets to layout 405 | self.mpp_ctrl_layout.addWidget(self.mpp_meas_button) 406 | self.mpp_ctrl_layout.addWidget(self.mpp_bias) 407 | self.mpp_ctrl_layout.addWidget(self.mpp_cmpl) 408 | self.mpp_ctrl_layout.addWidget(self.mpp_ampl) 409 | self.mpp_ctrl_layout.addWidget(self.mpp_conv) 410 | self.mpp_ctrl_layout.addWidget(self.mpp_gain) 411 | self.mpp_ctrl_layout.addWidget(self.mpp_delay) 412 | self.mpp_ctrl_layout.setContentsMargins(0,0,0,0) 413 | 414 | # Set widget layout 415 | self.mpp_ctrl.setLayout(self.mpp_ctrl_layout) 416 | 417 | 418 | # Method to generate solar cell plots. This will be implemented 419 | # as three QVisaDynamicPlots packed into a QStackedWidget 420 | def gen_solar_plot(self): 421 | 422 | # Call QStackedWidget constructor 423 | self.plot_stack = QStackedWidget() 424 | 425 | # Voc tracking plot 426 | self.voc_plot = QVisaDynamicPlot.QVisaDynamicPlot(self) 427 | self.voc_plot.add_subplot(111, twinx=True) 428 | self.voc_plot.set_axes_labels("111", "Time (s)", "Voc (V)") 429 | self.voc_plot.set_axes_labels("111t", "Time (s)", "Ioc (V)") 430 | self.voc_plot.set_axes_adjust(_left=0.15, _right=0.85, _top=0.9, _bottom=0.1) 431 | self.voc_plot.refresh_canvas(supress_warning=True) 432 | 433 | # MPP tracking plot 434 | self.mpp_plot = QVisaDynamicPlot.QVisaDynamicPlot(self) 435 | self.mpp_plot.add_subplot(111, twinx=True) 436 | self.mpp_plot.set_axes_labels("111", "Time (s)", "Vmpp (V)") 437 | self.mpp_plot.set_axes_labels("111t", "Time (s)", "Pmpp (mW)") 438 | self.mpp_plot.set_axes_adjust(_left=0.15, _right=0.85, _top=0.9, _bottom=0.1) 439 | self.mpp_plot.refresh_canvas(supress_warning=True) 440 | 441 | # Sync plot clear data buttons with application data 442 | self.voc_plot.sync_application_data(True) 443 | self.mpp_plot.sync_application_data(True) 444 | 445 | # Sync meta widget when clearing data from plots 446 | self.voc_plot.set_mpl_refresh_callback("_sync_meta_widget_to_data_object") 447 | self.mpp_plot.set_mpl_refresh_callback("_sync_meta_widget_to_data_object") 448 | 449 | # Add QVisaDynamicPlots to QStackedWidget 450 | self.plot_stack.addWidget(self.voc_plot) 451 | self.plot_stack.addWidget(self.mpp_plot) 452 | 453 | # Return the stacked widget 454 | self.plot_stack.setCurrentIndex(0); 455 | return self.plot_stack 456 | 457 | 458 | # Sync meta widget to data object 459 | def _sync_meta_widget_to_data_object(self): 460 | 461 | # Application keys 462 | _data_keys = self._get_data_object().keys() 463 | _widget_keys = self.meta_widget.get_meta_keys() 464 | 465 | # Check if widget keys are not in data keys 466 | for _key in _widget_keys: 467 | 468 | # If not then delete the key from meta_widget 469 | if _key not in _data_keys: 470 | 471 | self.meta_widget.del_meta_key(_key) 472 | 473 | 474 | # Flip between controls when measurement mode selector is updated 475 | def update_meas_pages(self): 476 | 477 | if self.meas_select.currentText() == "Voc": 478 | self.meas_pages.setCurrentIndex(0) 479 | self.plot_stack.setCurrentIndex(0) 480 | 481 | if self.meas_select.currentText() == "MPP": 482 | self.meas_pages.setCurrentIndex(1) 483 | self.plot_stack.setCurrentIndex(1) 484 | 485 | 486 | # Callback method to delete data when traces are cleared 487 | def sync_mpl_clear(self): 488 | 489 | # Extract plot and data object 490 | _plot = self.plot_stack.currentWidget() 491 | _data = self._get_data_object() 492 | 493 | # Note that plot subkeys map to data keys 494 | for _subkey in _plot.get_axes_handles().subkeys("111"): 495 | _data.del_key(_subkey) 496 | 497 | 498 | ##################################### 499 | # Voc-TRACKING MEASUREMENT MODE 500 | # 501 | def exec_voc_thread(self): 502 | 503 | # Get QVisaDataObject 504 | data = self._get_data_object() 505 | key = data.add_hash_key("pv-voc") 506 | 507 | # Add data fields to key 508 | data.set_subkeys(key, ["t", "Voc", "Ioc"]) 509 | data.set_metadata(key, "__type__", "pv-voc") 510 | 511 | # Add key to meta widget 512 | self.meta_widget.add_meta_key(key) 513 | 514 | # Generate colors 515 | _c0 = self.voc_plot.gen_next_color() 516 | _c1 = self.voc_plot.gen_next_color() 517 | 518 | # Clear plot and zero arrays 519 | self.voc_plot.add_axes_handle('111' , key, _color=_c0) 520 | self.voc_plot.add_axes_handle('111t', key, _color=_c1) 521 | 522 | # Thread start time 523 | start = float(time.time()) 524 | 525 | # Set bias to initial value in voltas and turn output ON 526 | self.keithley().set_voltage( self.voc_bias.value() ) 527 | self.keithley().current_cmp( self.voc_cmpl.value() ) 528 | self.keithley().output_on() 529 | 530 | # Iteration timer 531 | _iter_start = float(time.time()) 532 | 533 | # Initialize dynamic current normalization 534 | _Inorm = 0.0 535 | 536 | # Initialize convergence 537 | converged = False 538 | 539 | # Ambipolar tracking algorithm (zero-crossing). 540 | # Need to adjust bias in direction of lower current. 541 | while self.voc_thread_running is True: 542 | 543 | # Get data from buffer 544 | _buffer = self.keithley().meas().split(",") 545 | 546 | # Create 1mV sense amplitude 547 | _amplitude = self.voc_ampl.value() 548 | _v, _i = np.add(float(_buffer[0]), np.linspace(-0.5 * _amplitude, 0.5 * _amplitude, 3)), [] 549 | 550 | # Measure current over sense amplitude array 551 | for _ in _v: 552 | self.keithley().set_voltage(_) 553 | _b = self.keithley().meas().split(",") 554 | _i.append( float( _b[1] ) ) 555 | 556 | # Reset the voltage 557 | self.keithley().set_voltage( float(_buffer[0] ) ) 558 | 559 | # Normalization 560 | _Inorm = max(_Inorm, abs( float(_buffer[1]) ) ) 561 | 562 | # Solar cell current is positive: bias is above Voc 563 | if np.mean(_i) >= 0.0: 564 | self.update_bias( float(_buffer[0]) - abs( float(_buffer[1]) / _Inorm ) * self.voc_gain.value() / 1000. ) 565 | 566 | # Solar cell current is negative: bias is below Voc 567 | else: 568 | self.update_bias( float(_buffer[0]) + abs( float(_buffer[1]) / _Inorm ) * self.voc_gain.value() / 1000. ) 569 | 570 | _now = float(time.time() - start) 571 | 572 | # Check convergence condition 573 | if abs( float(_buffer[1]) / _Inorm ) < self.voc_conv.value(): 574 | 575 | converged = True 576 | 577 | # Case of excluding convergence data 578 | if ( self.meas_conv.isChecked() == False ) and converged: 579 | 580 | data.append_subkey_data(key, "t" , _now) 581 | data.append_subkey_data(key, "Voc", 1.0 * float(_buffer[0]) ) 582 | data.append_subkey_data(key, "Ioc", -1.0 * float(_buffer[1]) ) # Sanity check 583 | 584 | # Append handle data and update canvas 585 | self.voc_plot.append_handle_data("111" , key, _now, 1.0 * float(_buffer[0]) ) 586 | self.voc_plot.append_handle_data("111t", key, _now, -1.0 * float(_buffer[1]) ) 587 | self.voc_plot.update_canvas() 588 | 589 | # Case of including convergence data 590 | if ( self.meas_conv.isChecked() == True ): 591 | 592 | data.append_subkey_data(key, "t" , _now) 593 | data.append_subkey_data(key, "Voc", 1.0 * float(_buffer[0]) ) 594 | data.append_subkey_data(key, "Ioc", -1.0 * float(_buffer[1]) ) # Sanity check 595 | 596 | # Append handle data and update canvas 597 | self.voc_plot.append_handle_data("111" , key, _now, 1.0 * float(_buffer[0]) ) 598 | self.voc_plot.append_handle_data("111t", key, _now, -1.0 * float(_buffer[1]) ) 599 | self.voc_plot.update_canvas() 600 | 601 | # Measurement delay 602 | if self.voc_delay.value() != 0: 603 | time.sleep(self.voc_delay.value()) 604 | 605 | # Cleanup after thread termination 606 | self.keithley().set_voltage(0.0) 607 | self.keithley().output_off() 608 | 609 | # Tracking measurement ON 610 | def exec_voc_run(self): 611 | 612 | if self.keithley() is not None: 613 | 614 | # Update UI for ON state 615 | self.voc_meas_button.setStyleSheet( 616 | "background-color: #cce6ff; border-style: solid; border-width: 1px; border-color: #1a75ff; padding: 7px;") 617 | 618 | # Disable controls 619 | self.save_widget.setEnabled(False) 620 | self.device_select.setEnabled(False) 621 | self.meas_select.setEnabled(False) 622 | self.meas_conv.setEnabled(False) 623 | self.voc_bias.setEnabled(False) 624 | self.voc_cmpl.setEnabled(False) 625 | self.voc_plot.mpl_refresh_setEnabled(False) 626 | self.mpp_plot.mpl_refresh_setEnabled(False) 627 | 628 | # Run the measurement thread function 629 | self.voc_thread = threading.Thread(target=self.exec_voc_thread, args=()) 630 | self.voc_thread.daemon = True # Daemonize thread 631 | self.voc_thread.start() # Start the execution 632 | self.voc_thread_running = True # Set execution flag 633 | 634 | 635 | # Tracking measurement OFF 636 | def exec_voc_stop(self): 637 | 638 | if self.keithley() is not None: 639 | 640 | # Put measurement button in measure state 641 | self.voc_meas_button.setStyleSheet( 642 | "background-color: #dddddd; border-style: solid; border-width: 1px; border-color: #aaaaaa; padding: 7px;" ) 643 | 644 | # Enable controls 645 | self.save_widget.setEnabled(True) 646 | self.device_select.setEnabled(True) 647 | self.meas_select.setEnabled(True) 648 | self.meas_conv.setEnabled(True) 649 | self.voc_bias.setEnabled(True) 650 | self.voc_cmpl.setEnabled(True) 651 | self.voc_plot.mpl_refresh_setEnabled(True) 652 | self.mpp_plot.mpl_refresh_setEnabled(True) 653 | 654 | # Set thread running to False. This will break the sweep measurements 655 | # execution loop on next iteration. 656 | self.voc_thread_running = False 657 | self.voc_thread.join() # Waits for thread to complete 658 | 659 | 660 | ##################################### 661 | # MPP-TRACKING MEASUREMENT MODE 662 | # 663 | 664 | def exec_mpp_thread(self): 665 | 666 | # Get QVisaDataObject 667 | data = self._get_data_object() 668 | key = data.add_hash_key("pv-mpp") 669 | 670 | # Add data fields to key 671 | data.set_subkeys(key, ["t", "Vmpp", "Impp", "Pmpp"]) 672 | data.set_metadata(key, "__type__", "pv-mpp") 673 | 674 | # Add key to meta widget 675 | self.meta_widget.add_meta_key(key) 676 | 677 | # Generate colors 678 | _c0 = self.mpp_plot.gen_next_color() 679 | _c1 = self.mpp_plot.gen_next_color() 680 | 681 | # Clear plot and zero arrays 682 | self.mpp_plot.add_axes_handle('111' , key, _color=_c0) 683 | self.mpp_plot.add_axes_handle('111t', key, _color=_c1) 684 | 685 | # Thread start time 686 | start = float(time.time()) 687 | 688 | # Set bias to initial value in volts and turn output ON 689 | self.keithley().set_voltage( self.mpp_bias.value() ) 690 | self.keithley().current_cmp( self.mpp_cmpl.value() ) 691 | self.keithley().output_on() 692 | 693 | # Iteration timer 694 | _iter_start = float(time.time()) 695 | 696 | # Initialize dynamic current normalization 697 | _dPnorm = 0.0 698 | 699 | # Initialize convergence 700 | converged = False 701 | 702 | # Thread loop 703 | while self.mpp_thread_running is True: 704 | 705 | # Get data from buffer 706 | _buffer = self.keithley().meas().split(",") 707 | 708 | # Create 1mV sense amplitude 709 | _amplitude = self.mpp_ampl.value() 710 | _v, _i = np.add(float(_buffer[0]), np.linspace(-0.5 * _amplitude, 0.5 * _amplitude, 5)), [] 711 | 712 | # Measure current over sense amplitude array 713 | for _ in _v: 714 | self.keithley().set_voltage(_) 715 | _b = self.keithley().meas().split(",") 716 | _i.append( -1.0 * float( _b[1] ) ) 717 | 718 | # Reset the voltage 719 | self.keithley().set_voltage( float(_buffer[0] ) ) 720 | 721 | # Calculate derivative of current and power 722 | _p = np.multiply(_i, _v) 723 | _dp = np.divide( np.gradient(np.multiply(_i, _v)) , _amplitude) 724 | 725 | # Calculate dP norm 726 | _dPnorm = max( _dPnorm, abs( np.mean(_dp) ) ) 727 | 728 | # Ambipolar tracking algorithm 729 | if np.mean(_dp) <= 0.0: 730 | self.update_bias( float(_buffer[0]) - abs( np.mean(_dp) / _dPnorm ) * self.voc_gain.value() / 1000. ) 731 | 732 | # Solar cell current is negative: bias is below Voc 733 | else: 734 | self.update_bias( float(_buffer[0]) + abs( np.mean(_dp) / _dPnorm ) * self.voc_gain.value() / 1000. ) 735 | 736 | # Extract data from buffer 737 | _now = float(time.time() - start) 738 | 739 | # Check convergence condition 740 | if abs( np.mean(_dp) / _dPnorm ) < self.mpp_conv.value(): 741 | 742 | converged = True 743 | 744 | # Case of excluding convergence data 745 | if ( self.meas_conv.isChecked() == False ) and converged: 746 | 747 | data.append_subkey_data(key, "t" , _now) 748 | data.append_subkey_data(key, "Vmpp", 1.0 * float(_buffer[0]) ) 749 | data.append_subkey_data(key, "Impp", -1.0 * float(_buffer[1]) ) 750 | data.append_subkey_data(key, "Pmpp", -1.0 * float(_buffer[1]) * float(_buffer[0]) ) 751 | 752 | # Append handle data and update canvas 753 | self.mpp_plot.append_handle_data("111" , key, _now, float(_buffer[0])) 754 | self.mpp_plot.append_handle_data("111t", key, _now, float(_buffer[0]) * -1.0 * float(_buffer[1]) * 1000.) 755 | self.mpp_plot.update_canvas() 756 | 757 | # Case of including convergence data 758 | if ( self.meas_conv.isChecked() == True ): 759 | 760 | data.append_subkey_data(key, "t" , _now) 761 | data.append_subkey_data(key, "Vmpp", 1.0 * float(_buffer[0]) ) 762 | data.append_subkey_data(key, "Impp", -1.0 * float(_buffer[1]) ) 763 | data.append_subkey_data(key, "Pmpp", -1.0 * float(_buffer[1]) * float(_buffer[0]) ) 764 | 765 | # Append handle data and update canvas 766 | self.mpp_plot.append_handle_data("111" , key, _now, float(_buffer[0])) 767 | self.mpp_plot.append_handle_data("111t", key, _now, float(_buffer[0]) * -1.0 * float(_buffer[1]) * 1000.) 768 | self.mpp_plot.update_canvas() 769 | 770 | 771 | # Measurement delay 772 | if self.mpp_delay.value() != 0: 773 | time.sleep(self.mpp_delay.value()) 774 | 775 | # Cleanup after thread termination 776 | self.keithley().set_voltage(0.0) 777 | self.keithley().output_off() 778 | 779 | # Tracking measurement ON 780 | def exec_mpp_run(self): 781 | 782 | if self.keithley() is not None: 783 | 784 | # Update UI for ON state 785 | self.mpp_meas_button.setStyleSheet( 786 | "background-color: #cce6ff; border-style: solid; border-width: 1px; border-color: #1a75ff; padding: 7px;") 787 | 788 | # Disable widgets 789 | self.save_widget.setEnabled(False) 790 | self.device_select.setEnabled(False) 791 | self.meas_select.setEnabled(False) 792 | self.meas_conv.setEnabled(False) 793 | self.mpp_bias.setEnabled(False) 794 | self.mpp_cmpl.setEnabled(False) 795 | self.voc_plot.mpl_refresh_setEnabled(False) 796 | self.mpp_plot.mpl_refresh_setEnabled(False) 797 | 798 | # Run the measurement thread function 799 | self.mpp_thread = threading.Thread(target=self.exec_mpp_thread, args=()) 800 | self.mpp_thread.daemon = True # Daemonize thread 801 | self.mpp_thread.start() # Start the execution 802 | self.mpp_thread_running = True # Set execution flag 803 | 804 | # Tracking measurement OFF 805 | def exec_mpp_stop(self): 806 | 807 | if self.keithley() is not None: 808 | 809 | # Put measurement button in measure state 810 | self.mpp_meas_button.setStyleSheet( 811 | "background-color: #dddddd; border-style: solid; border-width: 1px; border-color: #aaaaaa; padding: 7px;" ) 812 | 813 | # Enable widgets 814 | self.save_widget.setEnabled(True) 815 | self.device_select.setEnabled(True) 816 | self.meas_select.setEnabled(True) 817 | self.meas_conv.setEnabled(True) 818 | self.mpp_bias.setEnabled(True) 819 | self.mpp_cmpl.setEnabled(True) 820 | self.voc_plot.mpl_refresh_setEnabled(True) 821 | self.mpp_plot.mpl_refresh_setEnabled(True) 822 | 823 | # Set thread running to False. This will break the sweep measurements 824 | # execution loop on next iteration. 825 | self.mpp_thread_running = False 826 | self.mpp_thread.join() # Waits for thread to complete 827 | -------------------------------------------------------------------------------- /src/app/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/src/app/__init__.py -------------------------------------------------------------------------------- /src/python.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/src/python.ico -------------------------------------------------------------------------------- /src/widgets/QKeithleyBiasWidget.py: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------------- 2 | # QKeithleyBiasWidget -> QWidget 3 | # Copyright (C) 2019 Michael Winters 4 | # github: https://github.com/mesoic 5 | # email: mesoic@protonmail.com 6 | # --------------------------------------------------------------------------------- 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | #!/usr/bin/env python 28 | import numpy as np 29 | import threading 30 | import time 31 | 32 | # Import QT backends 33 | from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QMessageBox, QComboBox, QPushButton, QLabel, QStackedWidget 34 | from PyQt5.QtCore import Qt, QStateMachine, QState, QObject 35 | from PyQt5.QtGui import QIcon 36 | 37 | 38 | # Import PyQtVisa widgets 39 | from PyQtVisa.widgets import QVisaUnitSelector 40 | from PyQtVisa.widgets import QVisaDynamicPlot 41 | 42 | # Container class for Keithley to render keithley controls in the bias appicaton. 43 | # QKeithleyBiasWidget is not itself a widget, but it contains several widgets. Note 44 | # that _app must be QVisaApplication widget 45 | 46 | class QKeithleyBiasWidget: 47 | 48 | def __init__(self, _app, _name): 49 | 50 | # Cache a reference to the calling application 51 | self._app = _app 52 | self._name = _name 53 | 54 | # Set thread variables 55 | self.thread, self.thread_running = None, False 56 | 57 | # Generate widgets 58 | self.gen_ctrl_widget() 59 | self.gen_plot_widget() 60 | self.gen_output_widget() 61 | 62 | # Reset the keithley 63 | if self._name != "__none__": 64 | 65 | self.keithley().rst() 66 | self.keithley().set_voltage( self.voltage_bias.value() ) 67 | self.keithley().current_cmp( self.voltage_cmpl.value() ) 68 | 69 | def keithley(self): 70 | return self._app.get_device_by_name( self._name ) 71 | 72 | ##################################### 73 | # APPLICATION HELPER METHODS 74 | # 75 | 76 | def get_output_widget(self): 77 | return self.output_widget[0] 78 | 79 | def get_ctrl_widget(self): 80 | return self.ctl_widget 81 | 82 | def get_plot_widget(self): 83 | return self.plot_stack 84 | 85 | # Create a QStateMachine and output button for each connected insturment 86 | def gen_output_widget(self): 87 | 88 | if self._name != "__none__": 89 | 90 | # Each output is a tuple [QPushButton, QStateMachine] 91 | self.output_widget = ( QPushButton(), QStateMachine() ) 92 | self.output_widget[0].setStyleSheet( 93 | "background-color: #dddddd; border-style: solid; border-width: 1px; border-color: #aaaaaa; padding: 7px;" ) 94 | 95 | # Create output states 96 | output_off = QState() 97 | output_on = QState() 98 | 99 | # Attach states to output button and define state transitions 100 | output_off.assignProperty(self.output_widget[0], 'text', "%s Output OFF"%self._name.split()[1]) 101 | output_off.addTransition(self.output_widget[0].clicked, output_on) 102 | output_off.entered.connect(self.exec_output_off) 103 | 104 | output_on.assignProperty(self.output_widget[0], 'text','%s Output ON'%self._name.split()[1]) 105 | output_on.addTransition(self.output_widget[0].clicked, output_off) 106 | output_on.entered.connect(self.exec_output_on) 107 | 108 | # Add states, set initial state, and start machine 109 | self.output_widget[1].addState(output_off) 110 | self.output_widget[1].addState(output_on) 111 | self.output_widget[1].setInitialState(output_off) 112 | self.output_widget[1].start() 113 | 114 | else: 115 | 116 | self.output_widget = ( QPushButton(), False ) 117 | self.output_widget[0].setStyleSheet( 118 | "background-color: #dddddd; border-style: solid; border-width: 1px; border-color: #aaaaaa; padding: 7px;" ) 119 | self.output_widget[0].setEnabled(False) 120 | self.output_widget[0].setText("Keithley not Initialized") 121 | 122 | # Generate bias control widget 123 | def gen_ctrl_widget(self): 124 | 125 | # Control layout 126 | self.ctl_widget = QWidget() 127 | self.ctl_layout = QVBoxLayout() 128 | 129 | # Main mode selctor 130 | self.src_select_label = QLabel("Bias Mode") 131 | self.src_select = QComboBox() 132 | self.src_select.setFixedWidth(200) 133 | self.src_select.addItems(["Voltage", "Current"]) 134 | self.src_select.currentTextChanged.connect(self.update_bias_ctrl) 135 | 136 | # Generate voltage and current source widgets 137 | self.gen_voltage_src() # self.voltage_src 138 | self.gen_current_src() # self.current_src 139 | 140 | # Add to stacked widget 141 | self.src_pages = QStackedWidget() 142 | self.src_pages.addWidget(self.voltage_src) 143 | self.src_pages.addWidget(self.current_src) 144 | self.src_pages.setCurrentIndex(0) 145 | 146 | # Disable controls if "__none__ passed as name" 147 | if self._name == "__none__": 148 | self.src_select_label.setEnabled(False) 149 | self.src_select.setEnabled(False) 150 | self.src_pages.setEnabled(False) 151 | 152 | ##################################### 153 | # ADD CONTROLS 154 | # 155 | 156 | # Main output and controls 157 | self.ctl_layout.addWidget(self._app._gen_hbox_widget([self.src_select, self.src_select_label])) 158 | self.ctl_layout.addWidget(self.src_pages) 159 | self.ctl_layout.setContentsMargins(0,0,0,0) 160 | 161 | # Set layouth 162 | self.ctl_widget.setLayout(self.ctl_layout) 163 | 164 | # Generate voltage and current sources 165 | def gen_voltage_src(self): 166 | 167 | # New QWidget 168 | self.voltage_src = QWidget() 169 | self.voltage_layout = QVBoxLayout() 170 | 171 | # Configuration for bias level unit box 172 | self.voltage_bias_config={ 173 | "unit" : "V", 174 | "min" : "u", 175 | "max" : "", 176 | "label" : "Bias Level", 177 | "signed" : True, 178 | "limit" : [20.0, ""], 179 | "default" : [00.0, ""] 180 | } 181 | self.voltage_bias = QVisaUnitSelector.QVisaUnitSelector(self.voltage_bias_config) 182 | self.voltage_bias.unit_value.valueChanged.connect(self.update_bias) 183 | self.voltage_bias.unit_select.currentTextChanged.connect(self.update_bias) 184 | 185 | # Compliance Spinbox 186 | self.voltage_cmpl_config={ 187 | "unit" : "A", 188 | "min" : "u", 189 | "max" : "", 190 | "label" : "Compliance", 191 | "signed" : False, 192 | "limit" : [1.0, ""], 193 | "default" : [150, "m"] 194 | } 195 | self.voltage_cmpl = QVisaUnitSelector.QVisaUnitSelector(self.voltage_cmpl_config) 196 | self.voltage_cmpl.unit_value.valueChanged.connect(self.update_cmpl) 197 | self.voltage_cmpl.unit_select.currentTextChanged.connect(self.update_cmpl) 198 | 199 | # Measurement Delay 200 | self.voltage_delay_config={ 201 | "unit" : "__DOUBLE__", 202 | "label" : "Measurement Interval (s)", 203 | "signed" : False, 204 | "limit" : [60.0], 205 | "default" : [0.10] 206 | } 207 | self.voltage_delay = QVisaUnitSelector.QVisaUnitSelector(self.voltage_delay_config) 208 | 209 | # Pack selectors into layout 210 | self.voltage_layout.addWidget(self.voltage_bias) 211 | self.voltage_layout.addWidget(self.voltage_cmpl) 212 | self.voltage_layout.addWidget(self.voltage_delay) 213 | self.voltage_layout.setContentsMargins(0,0,0,0) 214 | 215 | # Set layout 216 | self.voltage_src.setLayout(self.voltage_layout) 217 | 218 | def gen_current_src(self): 219 | 220 | # New QWidget 221 | self.current_src = QWidget() 222 | self.current_layout = QVBoxLayout() 223 | 224 | # Configuration for bias level unit box 225 | self.current_bias_config={ 226 | "unit" : "A", 227 | "min" : "u", 228 | "max" : "", 229 | "label" : "Bias Level", 230 | "signed" : True, 231 | "limit" : [1.0, ""], 232 | "default" : [1.0, "m"] 233 | } 234 | self.current_bias = QVisaUnitSelector.QVisaUnitSelector(self.current_bias_config) 235 | self.current_bias.unit_value.valueChanged.connect(self.update_bias) 236 | self.current_bias.unit_select.currentTextChanged.connect(self.update_bias) 237 | 238 | # Compliance Spinbox 239 | self.current_cmpl_config={ 240 | "unit" : "V", 241 | "min" : "u", 242 | "max" : "", 243 | "label" : "Compliance", 244 | "signed" : False, 245 | "limit" : [20.0, ""], 246 | "default" : [1.00, ""] 247 | } 248 | self.current_cmpl = QVisaUnitSelector.QVisaUnitSelector(self.current_cmpl_config) 249 | self.current_cmpl.unit_value.valueChanged.connect(self.update_cmpl) 250 | self.current_cmpl.unit_select.currentTextChanged.connect(self.update_cmpl) 251 | 252 | # Measurement Delay 253 | self.current_delay_config={ 254 | "unit" : "__DOUBLE__", 255 | "label" : "Measurement Interval (s)", 256 | "signed" : False, 257 | "limit" : [60.0], 258 | "default" : [0.10] 259 | } 260 | self.current_delay = QVisaUnitSelector.QVisaUnitSelector(self.current_delay_config) 261 | 262 | # Pack selectors into layout 263 | self.current_layout.addWidget(self.current_bias) 264 | self.current_layout.addWidget(self.current_cmpl) 265 | self.current_layout.addWidget(self.current_delay) 266 | self.current_layout.setContentsMargins(0,0,0,0) 267 | 268 | # Set layout 269 | self.current_src.setLayout(self.current_layout) 270 | 271 | # Dynamic Plotting Capability 272 | def gen_plot_widget(self): 273 | 274 | # Create QVisaDynamicPlot Object (inherits QWidget) 275 | self.voltage_plot = QVisaDynamicPlot.QVisaDynamicPlot(self._app) 276 | self.voltage_plot.add_subplot("111") 277 | self.voltage_plot.set_axes_labels("111", "Time (s)", "Current (A)") 278 | 279 | self.voltage_plot.refresh_canvas(supress_warning=True) 280 | 281 | # Create QVisaDynamicPlot Object (inherits QWidget) 282 | self.current_plot = QVisaDynamicPlot.QVisaDynamicPlot(self._app) 283 | self.current_plot.add_subplot("111") 284 | self.current_plot.set_axes_labels("111", "Time (s)", "Voltage (V)") 285 | self.current_plot.refresh_canvas(supress_warning=True) 286 | 287 | # Add to plot stack 288 | self.plot_stack = QStackedWidget() 289 | self.plot_stack.addWidget(self.voltage_plot) 290 | self.plot_stack.addWidget(self.current_plot) 291 | self.plot_stack.setCurrentIndex(0) 292 | 293 | # Sync plot clear data button with application data 294 | self.voltage_plot.sync_application_data(True) 295 | self.current_plot.sync_application_data(True) 296 | 297 | # Sync meta widget when clearing data from plots 298 | self.voltage_plot.set_mpl_refresh_callback("_sync_meta_widget_to_data_object") 299 | self.current_plot.set_mpl_refresh_callback("_sync_meta_widget_to_data_object") 300 | 301 | 302 | ##################################### 303 | # BIAS CONTROL UPDATE METHODS 304 | # 305 | 306 | # Update bias values 307 | def update_bias(self): 308 | 309 | if self.src_select.currentText() == "Voltage": 310 | self.keithley().set_voltage( self.voltage_bias.value() ) 311 | 312 | if self.src_select.currentText() == "Current": 313 | self.keithley().set_current( self.current_bias.value() ) 314 | 315 | # Update compliance values 316 | def update_cmpl(self): 317 | 318 | if self.src_select.currentText() == "Voltage": 319 | self.keithley().current_cmp( self.voltage_cmpl.value() ) 320 | 321 | if self.src_select.currentText() == "Current": 322 | self.keithley().voltage_cmp( self.current_cmpl.value() ) 323 | 324 | # Update bias control selectors 325 | def update_bias_ctrl(self): 326 | 327 | # Switch to voltage page 328 | if self.src_select.currentText() == "Voltage": 329 | 330 | # Update src_pages and plot 331 | self.src_pages.setCurrentIndex(0) 332 | self.plot_stack.setCurrentIndex(0) 333 | 334 | # Keithley to voltage source 335 | if self.keithley() is not None: 336 | 337 | self.keithley().voltage_src() 338 | self.update_bias() 339 | self.update_cmpl() 340 | 341 | # Switch to current page 342 | if self.src_select.currentText() == "Current": 343 | 344 | # Update src_pages and plot 345 | self.src_pages.setCurrentIndex(1) 346 | self.plot_stack.setCurrentIndex(1) 347 | 348 | # Keithley to current source 349 | if self.keithley() is not None: 350 | 351 | self.keithley().current_src() 352 | self.update_bias() 353 | self.update_cmpl() 354 | 355 | 356 | ##################################### 357 | # MEASUREMENT EXECUTION THREADS 358 | # 359 | 360 | # Measurement thread 361 | def exec_output_thread(self): 362 | 363 | # Check mesurement type for datafile 364 | if self.src_select.currentText() == "Voltage": 365 | _type = "v-bias" 366 | 367 | if self.src_select.currentText() == "Current": 368 | _type = "i-bias" 369 | 370 | 371 | # Get QVisaDataObject 372 | data = self._app._get_data_object() 373 | key = data.add_hash_key(_type) 374 | 375 | # Add key to meta widget 376 | self._app.meta_widget.add_meta_key(key) 377 | 378 | # Add data fields to key 379 | data.set_subkeys(key, ["t", "V", "I", "P"]) 380 | data.set_metadata(key, "__type__", _type) 381 | 382 | # Voltage and current arrays 383 | _plot = self.plot_stack.currentWidget() 384 | handle = _plot.add_axes_handle("111", key) 385 | start = time.time() 386 | 387 | # Thread loop 388 | while self.thread_running: 389 | 390 | # Get data from buffer 391 | _buffer = self.keithley().meas().split(",") 392 | 393 | # If in current mode, plot voltage 394 | if self.src_select.currentText() == "Current": 395 | _p = _buffer[0] 396 | 397 | # Measurement delay 398 | if self.current_delay.value() != 0: 399 | time.sleep(self.current_delay.value()) 400 | 401 | # It in voltage mode plot current 402 | if self.src_select.currentText() == "Voltage": 403 | _p = _buffer[1] 404 | 405 | # Measurement delay 406 | if self.voltage_delay.value() != 0: 407 | time.sleep(self.voltage_delay.value()) 408 | 409 | # Extract data from buffer 410 | _now = float(time.time() - start) 411 | 412 | # Append measured values to data arrays 413 | data.append_subkey_data(key, "t", _now ) 414 | data.append_subkey_data(key, "V", float(_buffer[0]) ) 415 | data.append_subkey_data(key, "I", float(_buffer[1]) ) 416 | data.append_subkey_data(key, "P", float(_buffer[0]) * float(_buffer[1]) ) 417 | 418 | # Append data to handle 419 | _plot.append_handle_data("111", key, _now, float(_p)) 420 | _plot.update_canvas() 421 | 422 | 423 | # UI output on state (measurement) 424 | def exec_output_on(self): 425 | 426 | if self.keithley() is not None: 427 | 428 | # Update UI for ON state 429 | self.output_widget[0].setStyleSheet( 430 | "background-color: #cce6ff; border-style: solid; border-width: 1px; border-color: #1a75ff; padding: 7px;") 431 | 432 | # Disable controls 433 | self.src_select.setEnabled(False) 434 | self.voltage_cmpl.setEnabled(False) 435 | self.current_cmpl.setEnabled(False) 436 | _plot = self.plot_stack.currentWidget() 437 | _plot.mpl_refresh_setEnabled(False) 438 | 439 | # Disable save widget if it exists 440 | if hasattr(self._app, 'save_widget'): 441 | self._app.save_widget.setEnabled(False) 442 | 443 | # Turn output ON 444 | self.keithley().output_on() 445 | 446 | # Each output is a list [QPushButton, QStateMachine, thrading.Thread, threadRunning(bool)] 447 | # Create execution thread for measurement 448 | self.thread = threading.Thread(target=self.exec_output_thread, args=()) 449 | self.thread.daemon = True # Daemonize thread 450 | self.thread.start() # Start the execution 451 | self.thread_running = True 452 | 453 | # UI output on state 454 | def exec_output_off(self): 455 | 456 | if self.keithley() is not None: 457 | 458 | # Get output name from inst_widget 459 | self.output_widget[0].setStyleSheet( 460 | "background-color: #dddddd; border-style: solid; border-width: 1px; border-color: #aaaaaa; padding: 7px;" ) 461 | 462 | # Set thread halt boolean 463 | self.thread_running = False 464 | 465 | # Wait for thread termination 466 | if self.thread is not None: 467 | self.thread.join() 468 | 469 | # Enable controls 470 | self.src_select.setEnabled(True) 471 | self.voltage_cmpl.setEnabled(True) 472 | self.current_cmpl.setEnabled(True) 473 | _plot = self.plot_stack.currentWidget() 474 | _plot.mpl_refresh_setEnabled(True) 475 | 476 | # Enable save widget if it exists 477 | if hasattr(self._app, 'save_widget'): 478 | self._app.save_widget.setEnabled(True) 479 | 480 | 481 | # Turn output OFF 482 | self.keithley().output_off() 483 | -------------------------------------------------------------------------------- /src/widgets/QKeithleyConfigWidget.py: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------------------------------------- 2 | # QKeithleyConfigWidget -> QWidget 3 | # Copyright (C) 2019 Michael Winters 4 | # github: https://github.com/mesoic 5 | # email: mesoic@protonmail.com 6 | # --------------------------------------------------------------------------------- 7 | # 8 | # Permission is hereby granted, free of charge, to any person obtaining a copy 9 | # of this software and associated documentation files (the "Software"), to deal 10 | # in the Software without restriction, including without limitation the rights 11 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | # copies of the Software, and to permit persons to whom the Software is 13 | # furnished to do so, subject to the following conditions: 14 | # 15 | # The above copyright notice and this permission notice shall be included in all 16 | # copies or substantial portions of the Software. 17 | # 18 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 24 | # SOFTWARE. 25 | # 26 | 27 | #!/usr/bin/env python 28 | 29 | # Import QT backends 30 | from PyQt5.QtWidgets import QWidget, QMessageBox, QVBoxLayout, QHBoxLayout, QComboBox, QPushButton, QLabel, QStackedWidget, QDoubleSpinBox 31 | from PyQt5.QtCore import Qt, QSize 32 | from PyQt5.QtGui import QIcon 33 | 34 | # Container class for Keithley to render keithley controls in the configuration script. 35 | # Note that _app must be QVisaConfigure widget or QVisaApplication widget 36 | 37 | class QKeithleyConfigWidget(QWidget): 38 | 39 | def __init__(self, _app, _name): 40 | 41 | # Extends QWidget 42 | QWidget.__init__(self) 43 | 44 | # Cache a reference to the calling application 45 | self._app = _app 46 | self.name = _name 47 | 48 | # Generate main layout 49 | self.gen_main_layout() 50 | 51 | def gen_main_layout(self): 52 | 53 | self.layout = QVBoxLayout() 54 | self.name_label = QLabel("Configure %s"%str(self.name)) 55 | 56 | self.sense_mode_label = QLabel("Sense Mode") 57 | self.sense_mode = QComboBox() 58 | self.sense_mode.addItems(["2-wire", "4-wire"]) 59 | 60 | self.output_route_label = QLabel("Output Route") 61 | self.output_route = QComboBox() 62 | self.output_route.addItems(["Front", "Rear"]) 63 | 64 | # Intergration time control. Note that integration time 65 | # is specified in power line cycles (50/60Hz) 66 | self.config_nplc_label = QLabel("Integration Time (nPLC)") 67 | self.config_nplc_note = QLabel("Power Line Cycle (50|60)Hz") 68 | self.config_nplc = QDoubleSpinBox() 69 | self.config_nplc.setDecimals(3) 70 | self.config_nplc.setMinimum(0.01) 71 | self.config_nplc.setMaximum(10.0) 72 | self.config_nplc.setSingleStep(0.01) 73 | self.config_nplc.setValue(1.00) 74 | 75 | # Update button 76 | self.inst_update = QPushButton("Update Configuration") 77 | self.inst_update.clicked.connect(self.update_config) 78 | 79 | # Add widgets to layout 80 | self.layout.addWidget(self.name_label) 81 | self.layout.addWidget(self.sense_mode_label) 82 | self.layout.addWidget(self.sense_mode) 83 | self.layout.addWidget(self.output_route_label) 84 | self.layout.addWidget(self.output_route) 85 | self.layout.addWidget(self.config_nplc_label) 86 | self.layout.addWidget(self.config_nplc_note) 87 | self.layout.addWidget(self.config_nplc) 88 | self.layout.addWidget(self.inst_update) 89 | 90 | # Set layout 91 | self.setLayout(self.layout) 92 | 93 | # Callback for sense mode 94 | def update_config(self): 95 | 96 | # Check to see if Keithley has been initilaized 97 | if self._app.get_device_by_name(self.name) is not None: 98 | 99 | # Update sense mode 100 | if self.sense_mode.currentText() == "2-wire": 101 | self._app.get_device_by_name(self.name).four_wire_sense_off() 102 | 103 | if self.sense_mode.currentText() == "4-wire": 104 | self._app.get_device_by_name(self.name).four_wire_sense_on() 105 | 106 | # Update output route 107 | if self.output_route.currentText() == "Front": 108 | self._app.get_device_by_name(self.name).output_route_front() 109 | 110 | if self.output_route.currentText() == "Rear": 111 | self._app.get_device_by_name(self.name).output_route_rear() 112 | 113 | # Update integration time 114 | self._app.get_device_by_name(self.name).update_nplc(self.config_nplc.value()) 115 | 116 | # Message box to indicate successful update 117 | msg = QMessageBox() 118 | msg.setIcon(QMessageBox.Information) 119 | msg.setText("Keithley Configuration Updated") 120 | msg.setWindowTitle("QKeithleyControl") 121 | msg.setWindowIcon(self._app._icon) 122 | msg.setStandardButtons(QMessageBox.Ok) 123 | msg.exec_() 124 | -------------------------------------------------------------------------------- /src/widgets/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/solarpx/QKeithleyControl/94e85cd8bc42d54f2cef4d0cfdb3ee4b62bcba41/src/widgets/__init__.py --------------------------------------------------------------------------------