{"id":21722785,"url":"https://github.com/qt3uw/qt3-utils","last_synced_at":"2025-04-12T21:53:10.061Z","repository":{"id":39746079,"uuid":"496731709","full_name":"qt3uw/qt3-utils","owner":"qt3uw","description":"Data Acquisition for Confocal Microscope and Spin Control Experiments","archived":false,"fork":false,"pushed_at":"2024-07-26T21:52:34.000Z","size":25385,"stargazers_count":4,"open_issues_count":56,"forks_count":5,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-12T21:53:08.073Z","etag":null,"topics":["confocal-microscopy","nidaqmx","nitrogen-vacancy","odmr","quantum-computing","quantum-information-science","spin-control"],"latest_commit_sha":null,"homepage":"https://sites.google.com/uw.edu/qt3-lab/projects","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/qt3uw.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-05-26T18:32:16.000Z","updated_at":"2024-11-11T15:55:59.000Z","dependencies_parsed_at":"2023-10-31T02:24:52.551Z","dependency_job_id":"e9291cbf-d2ed-4380-9ad5-aef651b832fd","html_url":"https://github.com/qt3uw/qt3-utils","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qt3uw%2Fqt3-utils","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qt3uw%2Fqt3-utils/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qt3uw%2Fqt3-utils/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/qt3uw%2Fqt3-utils/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/qt3uw","download_url":"https://codeload.github.com/qt3uw/qt3-utils/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248637834,"owners_count":21137538,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["confocal-microscopy","nidaqmx","nitrogen-vacancy","odmr","quantum-computing","quantum-information-science","spin-control"],"created_at":"2024-11-26T02:33:06.911Z","updated_at":"2025-04-12T21:53:10.040Z","avatar_url":"https://github.com/qt3uw.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Utility Classes and Functions for the QT3 Lab\n\nThis package provides a number of tools and fully-packaged programs for usage\nin the Quantum Technologies Teaching and Test-Bed (QT3) lab at the University of Washington.\n\nThe QT3 lab confocal microscope utilizes the following hardware to perform\nvarious spin-control experiments on quantum systems, such as NV centers in diamond:\n\n * TTL pulsers\n   * Quantum Composer Sapphire\n   * Spin Core PulseBlaster\n * Excelitas SPCM for photon detection\n * NI-DAQ card (PCIx 6363) for data acquisition and control\n * Jena System's Piezo Actuator Stage Control Amplifier\n * [Future] spectrometer\n\nThe code in this package facilitates usages of these devices to perform\nexperiments.\n\n# Setup\n\n### Prerequisites\n\nThe utilities in this package depend on publicly available Python packages found\non PyPI and drivers built by National Instruments for DAQmx and\nSpinCore for the PulseBlaster. These libraries must be installed separately.\n\n* [National Instruments DAQmx](https://nidaqmx-python.readthedocs.io/en/latest/)\n  * [driver downloads](http://www.ni.com/downloads/)\n* [SpinCore's PulseBlaster](https://www.spincore.com/pulseblaster.html)\n  * [spinAPI driver](http://www.spincore.com/support/spinapi/)\n\n## Installation\n\nOnce the prerequisite packages have been installed, qt3utils can be installed from pip.\n\n### Normal Installation\n\n```\npip install qt3utils\n```\n\nThe `qt3utils` package depends on a handful of other [qt3 packages](https://github.com/qt3uw) and will be installed for you by default.\nAdditional information may also be [found here](https://github.com/qt3uw/qt3softwaredocs).\n\n#### Update Tk/Tcl\n\nUpgrading Tcl/Tk via Anaconda overcomes some GUI bugs on Mac OS Sonoma\n\n```\nconda install 'tk\u003e=8.6.13'\n```\n\n\n# Usage\n\nThis package provides GUI applications and a Python API for controlling the hardware and running experiments.\n\nFor instructions on using the python API,\nthe simplest way to get started is to see one of the [example](examples) Jupyter notebooks.\n\nThe following notebooks demonstrate usage of their respective experiment classes and\nthe necessary hardware control objects for those experiments\n\n  * [CWODMR](examples/default_cwodmr.ipynb)\n  * [Pulsed ODMR](examples/default_podmr.ipynb)\n  * [Rabi Oscillations](examples/default_rabi.ipynb)\n  * [Ramsey](examples/default_ramsey.ipynb) (similar usage for spin/Hahn echo and dynamical decoupling)\n\nAdditionally, there are two notebooks that demonstrate some basic hardware tests\n\n  * [Pulse Blaster Tests](examples/pulse_blaster_testing.ipynb)\n  * [MW Switch Tests](examples/testing_MW_switch.ipynb)\n\nMost classes and methods contain docstrings that describe functionality, which you can\ndiscover through the python help() function.\n\nDetails of how the experiment classes work and how you can modify\nthem are found in [ExperimentsDoc.md](docs/ExeperimentsDoc.md)\n\nHelp to [automatically generate documentation](https://github.com/qt3uw/qt3-utils/issues/66) would be appreciated.\n\n\n## Applications\n\n### QT3 Oscilloscope\n\nThe console program `qt3scope` comes with this package. It allows you to run\na simple program from the command-line that reads the count rate on a particular\ndigital input terminal on the NI DAQ. Further development may allow it to \ndisplay count rates from other hardware.\n\nIt can be from the command line / terminal\n\n```\n\u003e qt3scope\n```\n\nAfter `pip install`, there will be an executible file in your python environment. You\nshould be able to create a softlink to that executable to a desktop or task bar icon, allowing\nto launch the program from a mouse click.\n\nStarting in version 1.0.3, graphical dropdown menus and configuration windows\nwill allow users to configure various hardware options. \n\n\n#### YAML Configuration\n\nData Acquisition hardware supported by QT3Scope can also be configured by selecting a YAML file.\nThe YAML file must contain a specific structure and names as shown below. \n\n\n###### Default NIDAQ Edge Counter YAML configuration:\n\n```yaml\nQT3Scope:\n  DAQController:\n    import_path : qt3utils.applications.controllers.nidaqedgecounter\n    class_name  : QT3ScopeNIDAQEdgeCounterController\n    configure : \n      daq_name : Dev1  # NI DAQ Device Name\n      signal_terminal : PFI0  # NI DAQ terminal connected to input digital TTL signal\n      clock_terminal :    # Specifies the digital input terminal to the NI DAQ to use for a clock. If left blank, interprets as None or NULL\n      clock_rate: 100000  # NI DAQ clock rate in Hz\n      num_data_samples_per_batch : 1000\n      read_write_timeout : 10  # timeout in seconds for read/write operations\n      signal_counter : ctr2  # NI DAQ counter to use for counting the input signal, e.g. ctr0, ctr1, ctr2, or ctr3\n```\n\n###### Default Random Data Generator configuration:\n\n```yaml\nQT3Scope:\n  DAQController:\n    import_path : qt3utils.applications.controllers.random_data_generator\n    class_name  : QT3ScopeRandomDataController\n    configure : \n      simulate_single_light_source : False\n      num_data_samples_per_batch : 10\n      default_offset: 100\n      signal_noise_amp: 0.5\n```\n\nAll hardware controllers built for QT3Scope have a default\nconfiguration YAML file, which are found in \n[src/qt3utils/applications/controllers](src/qt3utils/applications/controllers).\n\n### QT3 Confocal Scan\n\nThe console program `qt3scan` performs a 2D (x,y) scan using a data acquisition\ncontroller object and a position controller object. The default controllers use\nan NIDAQ device that counts TTL edges (typically from an SPCM) and sets\nanalog voltage values on a Jena system piezo actuator.\n\n```\n\u003e qt3scan\n```\n\nSimilar to `qt3scope`, the supported hardware can be configured via GUI or YAML file. \n\nAll hardware controllers that are built for QT3Scope have a default\nconfiguration YAML file, which will be found in \n[src/qt3utils/applications/controllers](src/qt3utils/applications/controllers).\n\n###### Default NIDAQ Edge Counter YAML configuration:\n\n```yaml\nQT3Scan:\n  DAQController:\n    import_path : qt3utils.applications.controllers.nidaqedgecounter\n    class_name  : QT3ScanNIDAQEdgeCounterController\n    configure : \n      daq_name : Dev1  # NI DAQ Device Name\n      signal_terminal : PFI0  # NI DAQ terminal connected to input digital TTL signal\n      clock_terminal :    # Specifies the digital input terminal to the NI DAQ to use for a clock. If left blank, interprets as None or NULL\n      clock_rate: 100000  # NI DAQ clock rate in Hz\n      num_data_samples_per_batch : 250\n      read_write_timeout : 10  # timeout in seconds for read/write operations\n      signal_counter : ctr2  # NI DAQ counter to use for counting the input signal, e.g. ctr0, ctr1, ctr2, or ctr3\n\n  PositionController:\n    import_path : qt3utils.applications.controllers.nidaqpiezocontroller    \n    class_name  : QT3ScanNIDAQPositionController\n    configure : \n      daq_name : Dev1  # NI DAQ Device Name\n      write_channels : ao0,ao1,ao2  # NI DAQ analog output channels to use for writing position\n      read_channels : ai0,ai1,ai2  # NI DAQ analog input channels to use for reading position\n      scale_microns_per_volt : 8  # conversion factor from volts to microns, can also supply a list [8,8,8] or [6,4.2,5] \n      zero_microns_volt_offset: 0  # the voltage value that defines the position 0,0,0, can also supply a list [0,0,0] or [5,5,5] \n      minimum_allowed_position : 0  # microns\n      maximum_allowed_position : 80  # microns\n      settling_time_in_seconds : 0.001\n\n```\n\n###### Default Princeton Spectrometer YAML configuration:\n\n```yaml\nQT3Scan:\n  DAQController:\n    import_path : qt3utils.applications.controllers.princeton_spectrometer\n    class_name  : QT3ScanPrincetonSpectrometerController\n    configure :\n      exposure_time : 2000 # This is in ms\n      center_wavelength : 700 # This is in nm\n      sensor_temperature_set_point : -70 # This is in Celsius\n      grating_selected : \"[500nm,300][2][0]\" # Varies based on spectrometer type\n      wave_start : 600\n      wave_end : 850\n      experiment_name: \"LF_Control\"\n\n  PositionController:\n    import_path : qt3utils.applications.controllers.nidaqpiezocontroller\n    class_name  : QT3ScanNIDAQPositionController\n    configure :\n      daq_name : Dev1  # NI DAQ Device Name\n      write_channels : ao0,ao1,ao2  # NI DAQ analog output channels to use for writing position\n      read_channels : ai0,ai1,ai2  # NI DAQ analog input channels to use for reading position\n      scale_microns_per_volt : 8  # conversion factor from volts to microns, can also supply a list [8,8,8] or [6,4.2,5]\n      zero_microns_volt_offset: 0  # the voltage value that defines the position 0,0,0, can also supply a list [0,0,0] or [5,5,5]\n      minimum_allowed_position : 0  # microns\n      maximum_allowed_position : 80  # microns\n      settling_time_in_seconds : 0.001\n\n```\n\n###### Default Random Data Generator configuration:\n\n```yaml\nQT3Scan:\n  PositionController:\n    import_path : qt3utils.applications.controllers.random_data_generator    \n    class_name  : QT3ScanDummyPositionController\n    configure : \n      maximum_allowed_position : 80\n      minimum_allowed_position : 0\n\n  DAQController:\n    import_path : qt3utils.applications.controllers.random_data_generator\n    class_name  : QT3ScanRandomDataController\n    configure : \n      simulate_single_light_source : True\n      num_data_samples_per_batch : 10\n      default_offset: 100\n      signal_noise_amp: 0.1\n\n```\n\n###### Default Spectrometer Random Data Generator configuration:\n\n```yaml\nQT3Scope:\n  DAQController:\n    import_path : qt3utils.applications.controllers.random_data_generator\n    class_name  : QT3ScopeRandomDataController\n    configure : \n      simulate_single_light_source : False\n      num_data_samples_per_batch : 10\n      default_offset: 100\n      signal_noise_amp: 0.5\n\nQT3Scan:\n  PositionController:\n    import_path : qt3utils.applications.controllers.random_data_generator    \n    class_name  : QT3ScanDummyPositionController\n    configure : \n      maximum_allowed_position : 80\n      minimum_allowed_position : 0\n\n  DAQController:\n    import_path : qt3utils.applications.controllers.random_data_generator\n    class_name  : QT3ScanRandomDataController\n    configure : \n      simulate_single_light_source : True\n      num_data_samples_per_batch : 10\n      default_offset: 100\n      signal_noise_amp: 0.1\n\n```\n\n### QT3 Piezo Controller\n\nThe console program `qt3piezo` comes installed via the 'nipiezojenapy' package, and may be launched from the command line.\n\n```\n\u003e qt3piezo\n```\n\nThis application can only be configured via command line options at this time.\nThe `nipiezojenapy` python package should probably be moved into `qt3utils`. \n\n\n# QT3Scope / QT3Scan Hardware Development\n\nFollow these instructions in order to add new hardware support to `qt3scope` or `qt3scan`.\n\nFor each application, you'll need to build a Python classes that adheres to each application's interfaces.\n\n## QT3Scope\n\n\n1. Build a class that adheres to `QT3ScopeDAQControllerInterface` as defined in\n[src/qt3utils/applications/qt3scope/interface.py](src/qt3utils/applications/qt3scope/interface.py). There are a number of methods\nthat you must construct. Two examples are [QT3ScopeRandomDataController](src/qt3utils/applications/controllers/random_data_generator.py)\nand [QT3ScopeNIDAQEdgeCounterController](src/qt3utils/applications/controllers/nidaqedgecounter.py#L13). \nIn addition to controlling hardware and returning data, they must also supply a way to configure the object via \nPython dictionary (`configure` method) and graphically (`configure_view` method).\n2. Create a YAML file with a default configuration, similar to that found in \n[random_data_generator.yaml](src/qt3utils/applications/controllers/random_data_generator.yaml) or [](src/qt3utils/applications/controllers/nidaq_edge_counter.yaml)\n3. Add your new controller to `SUPPORTED_CONTROLLERS` found in [qt3scope](src/qt3utils/applications/qt3scope/main.py#L51)\n\n## QT3Scan\n\nSimilar to `qt3scope` but with a little more work.\n\nThere are three controllers that are needed by `qt3scan`:\n* Application Controller -- [QT3ScanApplicationControllerInterface](src/qt3utils/applications/qt3scan/interface.py#L106) \n* DAQ Controller -- [QT3ScanDAQControllerInterface](src/qt3utils/applications/qt3scan/interface.py#L59) \n* Position Controller -- [QT3ScanPositionControllerInterface](src/qt3utils/applications/qt3scan/interface.py#L7)\n\n### 1. Application Controller \n\nCurrently there are two implementations of the Application Controller. [The first application controller](src/qt3utils/applications/qt3scan/controller.py#L14) is made to support standard 2D (x,y) scans. It is used for scans using the NIDAQ Edge Counter\nController, NIDAQ Position Controller, Random Data Generator and Dummy \nPosition Controller. \n\nIf you do not need any changes to the save function \nor special functionality to right-click on the scan image, then you can probably \nre-use this Application Controller. \n\n[The second application controller](https://github.com/qt3uw/qt3-utils/blob/134sub-changes-to-interface/src/qt3utils/applications/qt3scan/controller.py#L180) is an implements the hyperspectral image where each pixel each pixel in the 2D scan is based on a spectrum\nof counts over a range of wavelengths.\n`QT3ScanHyperSpectralApplicationController` class implements this \ndata view when a user right-clicks on the scan and along with a function\nto save the full 3-dimensional data set. \n\n### 2. DAQ Controller\n\nTo support new hardware that acquires data, build an implementation of `QT3ScanDAQControllerInterface`.\nThe DAQ controller interface is now split into two distinct interfaces:\n\n- Counter DAQ Controller (`QT3ScanCounterDAQControllerInterface`): This interface is specifically designed for hardware that functions primarily as counters, such as devices measuring photon counts or other discrete events. It extends the base DAQ controller interface by adding methods tailored to sampling counts and computing count rates.\n\n- Spectrometer DAQ Controller (`QT3ScanSpectrometerDAQControllerInterface`): This is tailored for spectrometers that acquire spectral data. This interface adds a method to sample the spectrum, making it easier for developers to integrate spectrometers into the QT3Scan framework.\n\nExamples are [QT3ScanRandomDataController](src/qt3utils/applications/controllers/random_data_generator.py#L124),\n[QT3ScanNIDAQEdgeCounterController](src/qt3utils/applications/controllers/nidaqedgecounter.py#L139), and `QT3ScanPrincetonSpectrometerController`\n\nCreate a new python module in in `src/qt3utils/applications/controllers` for your hardware controller.\n\n### 3. Position Controller\n\nTo support a new Position Controller build an implementation of `QT3ScanPositionControllerInterface`.\nExamples are [QT3ScanDummyPositionController](src/qt3utils/applications/controllers/random_data_generator.py#L160),\nand [QT3ScanNIDAQPositionController](src/qt3utils/applications/controllers/nidaqpiezocontroller.py#L9)\n\nCreate a new python module in in `src/qt3utils/applications/controllers` for your position controller.\n\n### 4. Default YAML file\n\nCreate a default YAML file that configures your DAQ and Position Controllers. Place the YAML file in\n`src/qt3utils/applications/controllers`\n\n### 5. Update QT3Scan.main\n\nAdd your new controllers to [qt3scan.main.py](src/qt3utils/applications/qt3scan/main.py#L46)\n\n\n# General Python Development\n\nIf you wish you make changes to qt3-utils (and hopefully merge those improvements into this repository) here are some brief instructions to get started. These instructions assume you are a \nmember of the QT3 development team and have permission to push branches to this repo. If you are not, you can \ninstead fork this repo into your own GitHub account, perform development and then issue a pull-request from \nyour forked repo to this repo through GitHub. Alternatively, reach out to a maintainer of this repo to be added as a developer. \n\nThese are mostly general guidelines for software development and \ncould be followed for other projects.\n\n### 1. Create a development environment \n\nUse Conda, venv or virtualenv with Python = 3.9. \n\n```\n\u003e conda create --name qt3utilsdev python=3.9\n```\n\nAs of this writing, we have primarily tested and used Python 3.9. \nReach out to a Maintainer to discuss moving to newer versions of\nPython if this is needed. \n\n### 2. Activate that environment\n\n```\n\u003e conda activate qt3utilsdev\n```\n\n### 3. Clone this repository\n\n```\n\u003e git clone https://github.com/qt3uw/qt3-utils.git\n```\n\n### 4. Install qt3-utils in \"editor\" mode\n\n```\n\u003e cd qt3-utils\n\u003e pip install -e . \n```\n\nThe `pip install -e .` command installs the package in editor mode. \nThis allows you to make changes to the source code and immediately\nsee the effects of those changes in a Python interpreter. It saves\nyou from having to call \"pip install\" each time you make a change and \nwant to test it. \n\n\n### 5. Create a new Issue\n\nIt's generally good practice to first create an Issue in this GitHub\nrepository which describes the problem that needs to be addressed. \nIt's also a good idea to be familiar with the current Issues that \nalready exist. The change you want to make may already be \nreported by another user. In that case, you could collaborate \nwith that person. \n\n### 6. Create a new branch for your work\n\n```\n\u003e git checkout -b X-add-my-fancy-new-feature\n```\nwhere it's good practice to use X to refer to a specific Issue to fix \nin this repository. \n\nYou should create a new branch only for a specific piece of new work\nthat will be added to this repository. It is highly discouraged to create\na separate branch for your microscope only and to use that branch\nto perform version control for Python scripts or Jupyter notebooks \nthat run experiments. \nIf you need version control for your exerpiment scripts and notebooks, you\nshould create a separate git repository and install qt3utils \nin the normal way (`pip install -U qt3utils`) in a Python environment \nfor your experimental work. If you need to have recent changes to qt3utils\npublished to PyPI for your work, reach out to a Maintainer of this \nrepo to ask them to release a new version. \n\n### 7. Add your code and test with your hardware!\n\nWe do not have an official style convention, unfortunately. However\nplease try to follow best-practices as outlined either in \n[PEP 8 styleguide](https://peps.python.org/pep-0008/)\nor [Google's styleguide](https://google.github.io/styleguide/pyguide.html).\nThere are other resources online, of course, that provide \"best-practices\"\nadvice. Having said that, you will certainly find places where I've \nbroken those guides. (Ideally, somebody would go through with a linter\nand fix all of these.). Please heavily document your source code. \n\nWe do not have an automatic test rig. This *could* be added by somebody\nif desired. But that could be complicated given that this code requires\nspecific local hardware and the setup for each experiment \nis likely to be different. So, be sure to test your code rigorously and \nmake sure there are no unintended side-effects. \n\nHistorically, documentation for this project has been \"just okay\". Please \nhelp this by adding any documentation for your changes where appropriate.\nThere is now a `docs` folder that you can use to include any major\nadditions or changes. \n\n### 8. Push your branch\n\nOnce development and testing are complete you will want to push your\nbranch to Github in order to merge it into the rest of the code-base.\n\nWhen you first push a branch to Github, you will need to issue this \ncommand.\n\n```\n\u003e git push -u origin X-add-my-fancy-new-feature\n```\n\nAs you add more commits to your branch, you'll still want to \npush those changes every once in a while with a simple\n\n```\n\u003e git push\n```\n\n(assuming that X-add-my-fancy-new-feature is your current \nlocal working branch)\n\nFinally, before you issue a pull request, you will want to\nsynchrononize your branch with any other changes made in 'main'\nto ensure there are no conflicting changes.\n\nThis is the following \"flow\" that has been used successfully in\nvarious development projects. However, there are other ways\nto do this. \n\n```\n\u003e git checkout main\n\u003e git pull\n\u003e git checkout X-add-my-fancy-new-feature\n\u003e git rebase main\n\u003e git push -f\n```\n\nThe series of commands above will pull down new changes from \nGithub's main branch to your local working copy. The `rebase` \ncommand will then \"replay\" your changes on top of the \nmost recent HEAD of the main branch. If there are conflicts,\ngit will notify you and you will be forced to fix those\nconflicts before continuing with the rebase. If it seems too\ncomplicated, you can `git rebase --abort` to recover and\nthen figure out what to do next. Reach out to a more experienced\ncolleague, perhaps, for help. \n\nThe final `git push -f` is necessary (if there were indeed new\ncommits on the main branch) and will \"force\" push your branch\nto Github. This is necessary due to the way git works. \n\nYou should then test your local branch with your hardware again!\n\nThis particular flow has the benefit of making a very clear git\nhistory that shows all the commits for each branch being\nmerged in logical order. \n\nInstead of following the instructions above, you may consider\ntrying GitHub's \"rebase\" option when issuing a pull request. \nIt will attempt the same set of operations. However, you may \nnot have the opportunity to test the changes locally. \n\n### 9. Issue a pull request\n\nAt the top of this qt3-utils GitHub repository is a 'pull-request' tab,\nfrom where you can create a request to merge your branch to another\nbranch (usually you merge to main)\n\nWhen you issue a pull request, be very clear and verbose about the \nchanges you are making. New code must be reviewed by another colleague\nbefore it gets merged to master. Your pull request should include things like\n\n* a statement describing what is changed or new\n* a reference to the Issue being fixed here (Github will automatically generate a handy link)\n* a statement describing why you chose your specific implementation\n* results of tests on your hardware setup, which could be data, screenshots, etc. There should be a clear record demonstrating functionality.\n* a Jupyter notebook in the \"examples\" folder that demonstrate usage and changes\n* documentation\n\n### 10. Perform Self Review\n\nBefore asking a colleague to review your changes, it's generally\na good idea to review the changes yourself in Github. \nWhen you see your updates from this perspective you may find\ntypos and changes that you wish to address first.\n\n### 11. Obtain a Code Review from a colleague\n\nDue to our lack of a test rig, merging should be done with care and\ncode reviews should be taken seriously. If you are asked by a colleague\nto review their code, make sure to ask a lot of questions as you read\nthrough it. You may even want to test the branch on your own setup \nto ensure it doesn't break anything. \n\n### 12. Address Changes\n\nIf you and your reviewer decide changes are needed, go back \nto your branch, make changes and push new commits. Repeat\nsteps 7, 8, 10, 11 and 12 until you are satisfied. \n\n### 13. Merge!\n\nIf you are satisfied and confident that your changes are \nready, and your reviewer has approved the changes, press the\ngreen Merge button. \n## Notes\n\n\n\n# Debugging\n\n# LICENSE\n\n[LICENCE](LICENSE)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqt3uw%2Fqt3-utils","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fqt3uw%2Fqt3-utils","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fqt3uw%2Fqt3-utils/lists"}