{"id":13654586,"url":"https://github.com/brjdenis/pyqaserver","last_synced_at":"2025-12-14T07:02:03.413Z","repository":{"id":43047604,"uuid":"225212431","full_name":"brjdenis/pyqaserver","owner":"brjdenis","description":"Pylinac and Orthanc web interface for faster quality assurance","archived":false,"fork":false,"pushed_at":"2025-05-25T18:10:24.000Z","size":47213,"stargazers_count":42,"open_issues_count":4,"forks_count":11,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-11-07T00:25:33.493Z","etag":null,"topics":["assurance","bottle","calibration","elekta","flexmap","linac","orthanc","pylinac","quality","winston-lutz"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/brjdenis.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,"zenodo":null}},"created_at":"2019-12-01T18:56:30.000Z","updated_at":"2025-10-09T15:16:05.000Z","dependencies_parsed_at":"2025-05-18T21:39:55.794Z","dependency_job_id":null,"html_url":"https://github.com/brjdenis/pyqaserver","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/brjdenis/pyqaserver","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brjdenis%2Fpyqaserver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brjdenis%2Fpyqaserver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brjdenis%2Fpyqaserver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brjdenis%2Fpyqaserver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/brjdenis","download_url":"https://codeload.github.com/brjdenis/pyqaserver/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/brjdenis%2Fpyqaserver/sbom","scorecard":{"id":254166,"data":{"date":"2025-08-11","repo":{"name":"github.com/brjdenis/pyqaserver","commit":"93a4c3272cf38199e7ef67d1285a9ffacef46883"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.7,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"Signed-Releases","score":0,"reason":"Project has not signed or included provenance with any releases.","details":["Warn: release artifact v2.0.1 not signed: https://api.github.com/repos/brjdenis/pyqaserver/releases/33399669","Warn: release artifact v2.0.0 not signed: https://api.github.com/repos/brjdenis/pyqaserver/releases/32767126","Warn: release artifact v2.0.1 does not have provenance: https://api.github.com/repos/brjdenis/pyqaserver/releases/33399669","Warn: release artifact v2.0.0 does not have provenance: https://api.github.com/repos/brjdenis/pyqaserver/releases/32767126"],"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}}]},"last_synced_at":"2025-08-17T09:12:31.736Z","repository_id":43047604,"created_at":"2025-08-17T09:12:31.737Z","updated_at":"2025-08-17T09:12:31.737Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":27720794,"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","status":"online","status_checked_at":"2025-12-14T02:00:11.348Z","response_time":56,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["assurance","bottle","calibration","elekta","flexmap","linac","orthanc","pylinac","quality","winston-lutz"],"created_at":"2024-08-02T03:00:37.562Z","updated_at":"2025-12-14T07:02:03.408Z","avatar_url":"https://github.com/brjdenis.png","language":"Python","funding_links":[],"categories":["Applications"],"sub_categories":[],"readme":"# pyQAserver\n\nPyqaserver connects [Pylinac](https://github.com/jrkerns/pylinac) and [Orthanc](https://github.com/jodogne/Orthanc) with a simplistic web interface. It was built to speed up the image analysis process with Pylinac, without having to switch computers or work manually with dicom files. The procedure is easy: acquire the image, send the image from the imaging computer directly to Orthanc, and then analyze it with Pylinac by using pyqaserver. Since all images are stored in Orthanc, you can re-analyze them anytime you want. You can do the analysis on any computer in your network.\n\nPyqaserver also contains a small database where you can store and review your measurements. And some additional modules that are handy when checking post-maintenance consistency of the linac.\n\n![image](files/image.png)\n\n![image](files/image2.png)\n\n## Compatibility and dependency\n\nIt works on Windows 7 and 10. It should work on Linux as well. Currently, it is compatible with Pylinac 2.3.2 and Python 3.8. Because of the way pyqaserver is constructed, it is highly likely that it will not work with newer versions of Pylinac.\n\nNot all Pylinac's capabilities are implemented. Trajectory logs cannot be analyzed, the calibration module is missing, and there are some missing features in other modules. Basically, this are the modules you can use:\n\n* Winston Lutz\n* Starshot\n* Picket fence\n* Planar imaging\n* CT\n* Dynalog\n* Flatness/Symmetry\n* VMAT\n\nAdditional modules are:\n\n* **Field size** for measuring field size, radiation to light field match and focal spot position.\n \n* **Field rotation** for measuring collimator angle calibration in absolute terms, couch rotation and EPID twist.\n \n\nPyqaserver contains little original code, just enough to connect Pylinac and Orthanc. The code is hideously written! But I will improve it. Some dependencies are included in the distribution of pyqaserver, other dependencies must be installed separately. Orthanc is not included in the distribution of pyqaserver.\n\nHere is a list of some of the software used (common packages like scipy, numpy etc. are not listed):\n\n* [Pylinac](https://github.com/jrkerns/pylinac)\n* [Bottle](https://bottlepy.org/docs/dev/)\n* [httplib2](https://github.com/httplib2/httplib2)\n* [prettytable](https://github.com/jazzband/prettytable)\n* [Resttoolbox.py](https://github.com/jodogne/OrthancMirror/tree/master/Resources/Samples/Python)\n* [Bokeh](https://docs.bokeh.org/en/latest/index.html)\n* [mpld3](https://mpld3.github.io/)\n* [Bootstrap](https://getbootstrap.com/docs/3.4/)\n* [Bootstrap-datepicker](https://bootstrap-datepicker.readthedocs.io/en/latest/)\n* [Popper](https://popper.js.org/)\n* [math.js](https://mathjs.org/)\n* [minimumboundingbox.py](https://bitbucket.org/william_rusnack/minimumboundingbox/src/master/)\n* [plotly.js](https://plotly.com/javascript/getting-started/)\n* [tabulator.js](http://tabulator.info/)\n\n\n## Installation and running\n\nPyqaserver can be installed as a Python package starting with version 2.0.0.  See https://pyqaserver.readthedocs.io/en/latest/\n\n~~~\npip install pyqaserver\n~~~\n\nThe current version of pyqaserver will only work with matplotlib version 3.3.1. So make sure you install exactly this version.\n\nAfter that you can run pyqaserver with this:\n\n~~~\npyqaserver IP_ADDRESS:PORT PATH_TO_DATABASE_FOLDER\n~~~\n\nFor example, if you wish to run it as localhost:\n\n~~~\npyqaserver 127.0.0.1:8080 PATH_TO_DATABASE_FOLDER\n~~~\n\n\nThe web page is available at http://127.0.0.1:8080 ...\nThe default username/password is: admin/admin.\n\nPATH_TO_DATABASE_FOLDER must be the full absolute path of pyqserver's database. If you are running pyqaserver for the first time, this should be an empty directory where pyqaserver will install a small sqlite database. Anytime you restart the server, point to the same directory. \n\nWhen upgrading to a new version, make a backup copy of the database folder, but do not change it. First, uninstall pyqaserver with\n\n~~~\npip uninstall pyqaserver\n~~~\n\nAnd then install the new version:\n\n~~~\npip install pyqaserver==2.0.1\n~~~\n\nPoint the server to the same database directory and it should work. If you encounter problem with matplotlib, use version 3.3.1\n\n~~~\npip install matplotlib==3.3.1\n~~~\n\n\nThe entrance module for running pyqaserver from forked source is pyqaserver.py. Run it like this:\n\n~~~\npython pyqaserver.py 127.0.0.1:8080 PATH_TO_DATABASE_FOLDER\n~~~\n\n\n## Documentation\n\nDocumentation is available here:\n\n\n* [https://pyqaserver.readthedocs.io/en/latest/](https://pyqaserver.readthedocs.io/en/latest/)\n\nOlder versions:\n\n* [Version 1.0](https://brjdenis.github.io/pyqaserver/docs/version1.0/html/) , [PDF](/pdf/pyqaserver1.0.pdf)\n\n\n## Versions\n\n* Version 2.0.1 (latest)\n* Version 2.0.0\n* Version 1.0 (not on PyPI)\n\n\n## Bugs and requests\n\nYou can contribute to this project with suggestions or bug reports to: brjdenis2000@gmail.com.\n\nThe best way to reach me is to send me an email, or you can create a new issue on Github.\n\nWhat is the point of this project? Well, it started as an experiment. I wanted to do the Winston-Lutz test on an Elekta linac a couple of years ago, but didn't have the faintest idea how to do it. I stumbled upon Pylinac and learned a lot from it. Pylinac is really great because you can see the code, so you can understand how the analysis is performed. I liked this so much that I wanted to make a simple web interface for it. That way I could analyze images while I am still at the linac.\n\n\n## Some notes on doing tests on Elekta linacs\n\nI put together some personal notes on doing tests on Elekta linacs with Pylinac and QAserver: \n\n[Notes on doing tests on Elekta linacs](https://synergyqatips.readthedocs.io/en/latest/)\n\n\n## Dynalog review\n\nYou can review MLC dynamic in the web interface by re-analysing stored dynalogs on-the-fly. You get this:\n\n![MLC dynamics](files/dynalog_dynamic.gif)","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrjdenis%2Fpyqaserver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbrjdenis%2Fpyqaserver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbrjdenis%2Fpyqaserver/lists"}