UnitMatchPy 3.2.8__tar.gz → 3.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- unitmatchpy-3.3.0/PKG-INFO +128 -0
- unitmatchpy-3.3.0/README.md +90 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/default_params.py +2 -1
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/metric_functions.py +108 -19
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/param_functions.py +10 -2
- unitmatchpy-3.3.0/UnitMatchPy.egg-info/PKG-INFO +128 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/pyproject.toml +3 -2
- unitmatchpy-3.2.8/PKG-INFO +0 -69
- unitmatchpy-3.2.8/README.md +0 -31
- unitmatchpy-3.2.8/UnitMatchPy.egg-info/PKG-INFO +0 -69
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/LICENSE +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/MANIFEST.in +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/GUI.py +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/GUI_icon.png +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/LICENSE +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/README.txt +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/awdark.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/awlight.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/awtemplate.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/awthemes.n7 +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/awthemes.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/awwinxpblue.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/colorutils.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/demoscaled.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/demoscaledb.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/demottk.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/README.txt +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/chevron/arrow-down-d.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/chevron/arrow-down-n-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/chevron/arrow-down-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/chevron/arrow-down-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/chevron/arrow-left-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/chevron/arrow-right-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/chevron/arrow-right-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/chevron/arrow-up-d.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/chevron/arrow-up-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/open/arrow-down-n-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/open/arrow-down-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/open/arrow-down-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/open/arrow-left-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/open/arrow-right-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/open/arrow-right-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/open/arrow-up-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/solid/arrow-down-n-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/solid/arrow-down-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/solid/arrow-down-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/solid/arrow-left-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/solid/arrow-right-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/solid/arrow-right-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/solid/arrow-up-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/solid-bg/arrow-down-d.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/solid-bg/arrow-down-n-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/solid-bg/arrow-down-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/solid-bg/arrow-left-d.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/solid-bg/arrow-left-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/solid-bg/arrow-right-d.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/solid-bg/arrow-right-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/solid-bg/arrow-up-d.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/solid-bg/arrow-up-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/arrow/solid-bg/settings.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/button/roundedrect-accent-gradient/button-a.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/button/roundedrect-accent-gradient/button-d.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/button/roundedrect-accent-gradient/button-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/button/roundedrect-accent-gradient/button-p.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/button/roundedrect-accent-gradient/settings.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/button/roundedrect-flat/button-a.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/button/roundedrect-flat/button-af-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/button/roundedrect-flat/button-af.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/button/roundedrect-flat/button-d.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/button/roundedrect-flat/button-f.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/button/roundedrect-flat/button-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/button/roundedrect-flat/button-p.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/button/roundedrect-flat/settings.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/button/roundedrect-gradient/button-d.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/button/roundedrect-gradient/button-n-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/button/roundedrect-gradient/button-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/button/roundedrect-gradient/settings.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-check/cb-sa-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-check/cb-sa.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-check/cb-sd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-check/cb-sn-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-check/cb-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-check/cb-ua.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-check/cb-ud.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-check/cb-un.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-check-rev/cb-sa-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-check-rev/cb-sa.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-check-rev/cb-sd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-check-rev/cb-sn-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-check-rev/cb-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-check-rev/cb-ua.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-check-rev/cb-ud.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-check-rev/cb-un.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-square/cb-sa.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-square/cb-sd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-square/cb-sn-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-square/cb-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-square/cb-ua.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-square/cb-ud.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/roundedrect-square/cb-un.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/square-check-gradient/cb-sd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/square-check-gradient/cb-sn-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/square-check-gradient/cb-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/square-check-gradient/cb-ud.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/square-check-gradient/cb-un.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/square-x/cb-sd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/square-x/cb-sn-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/square-x/cb-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/square-x/cb-ud.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/checkbutton/square-x/cb-un.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/combobox/rounded/combo-arrow-down-d.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/combobox/rounded/combo-arrow-down-n-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/combobox/rounded/combo-arrow-down-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/combobox/rounded/combo-entry-a.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/combobox/rounded/combo-entry-d.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/combobox/rounded/combo-entry-f.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/combobox/rounded/combo-entry-n-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/combobox/rounded/combo-entry-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/combobox/rounded/settings.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/combobox/solid-bg/combo-arrow-down-a.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/combobox/solid-bg/combo-arrow-down-d-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/combobox/solid-bg/combo-arrow-down-d.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/combobox/solid-bg/combo-arrow-down-n-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/combobox/solid-bg/combo-arrow-down-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/combobox/solid-bg/settings.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/empty/empty/empty.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/entry/roundedrect/entry-a.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/entry/roundedrect/entry-d.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/entry/roundedrect/entry-f.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/entry/roundedrect/entry-n-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/entry/roundedrect/entry-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/entry/roundedrect/settings.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/labelframe/square/labelframe-d.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/labelframe/square/labelframe-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/menubutton/chevron/mb-arrow-down-a.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/menubutton/chevron/mb-arrow-down-d.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/menubutton/chevron/mb-arrow-down-n-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/menubutton/chevron/mb-arrow-down-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/menubutton/solid/mb-arrow-down-d-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/menubutton/solid/mb-arrow-down-d.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/menubutton/solid/mb-arrow-down-n-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/menubutton/solid/mb-arrow-down-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/notebook/roundedtop-dark/notebook-tab-a.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/notebook/roundedtop-dark/notebook-tab-d.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/notebook/roundedtop-dark/notebook-tab-h.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/notebook/roundedtop-dark/notebook-tab-i-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/notebook/roundedtop-dark/notebook-tab-i.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/notebook/roundedtop-dark/settings.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/notebook/roundedtop-light/notebook-tab-a.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/notebook/roundedtop-light/notebook-tab-d.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/notebook/roundedtop-light/notebook-tab-h.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/notebook/roundedtop-light/notebook-tab-i-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/notebook/roundedtop-light/notebook-tab-i.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/notebook/roundedtop-light/settings.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/notebook/roundedtop-light-accent/notebook-tab-a.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/notebook/roundedtop-light-accent/notebook-tab-d.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/notebook/roundedtop-light-accent/notebook-tab-h.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/notebook/roundedtop-light-accent/notebook-tab-i-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/notebook/roundedtop-light-accent/notebook-tab-i.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/notebook/roundedtop-light-accent/settings.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect/settings.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect/slider-hd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect/slider-hn-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect/slider-hn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect/slider-vd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect/slider-vn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect/trough-hd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect/trough-hn-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect/trough-hn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect/trough-vd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect/trough-vn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect-bord/settings.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect-bord/slider-hd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect-bord/slider-hn-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect-bord/slider-hn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect-bord/slider-vd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect-bord/slider-vn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect-diag/diag-mask.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect-diag/settings.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect-diag/slider-hd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect-diag/slider-hn-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect-diag/slider-hn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect-diag/slider-vd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect-diag/slider-vn-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rect-diag/slider-vn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rounded-line/settings.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rounded-line/slider-hd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rounded-line/slider-hn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rounded-line/slider-vd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rounded-line/slider-vn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rounded-line/trough-hd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rounded-line/trough-hn-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rounded-line/trough-hn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rounded-line/trough-vd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rounded-line/trough-vn-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/rounded-line/trough-vn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/progressbar/settings.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle/rb-sa.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle/rb-sd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle/rb-sn-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle/rb-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle/rb-ua.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle/rb-ud.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle/rb-un.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle-gradient/rb-sd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle-gradient/rb-sn-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle-gradient/rb-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle-gradient/rb-ud.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle-gradient/rb-un.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle-hlbg/rb-sa.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle-hlbg/rb-sd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle-hlbg/rb-sn-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle-hlbg/rb-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle-hlbg/rb-ua.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle-hlbg/rb-ud.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle-hlbg/rb-un.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle-rev/rb-sa.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle-rev/rb-sd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle-rev/rb-sn-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle-rev/rb-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle-rev/rb-ua.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle-rev/rb-ud.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/circle-circle-rev/rb-un.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/octagon-circle/rb-sd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/octagon-circle/rb-sn-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/octagon-circle/rb-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/octagon-circle/rb-ud.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/radiobutton/octagon-circle/rb-un.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/circle/scale-ha.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/circle/scale-hd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/circle/scale-hn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/circle-rev/scale-ha.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/circle-rev/scale-hd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/circle-rev/scale-hn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/rect-bord-grip/scale-hd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/rect-bord-grip/scale-hn-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/rect-bord-grip/scale-hn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/rect-bord-grip/scale-vd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/rect-bord-grip/scale-vn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/rect-narrow/scale-hd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/rect-narrow/scale-hn-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/rect-narrow/scale-hn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/rect-narrow/scale-trough-hd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/rect-narrow/scale-trough-hn-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/rect-narrow/scale-trough-hn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/rect-narrow/scale-trough-vd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/rect-narrow/scale-trough-vn-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/rect-narrow/scale-trough-vn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/rect-narrow/scale-vd.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/rect-narrow/scale-vn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scale/rect-narrow/settings.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scrollbar-grip/circle/sb-slider-h-grip-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scrollbar-grip/circle/sb-slider-h-grip.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scrollbar-grip/circle/sb-slider-v-grip-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/scrollbar-grip/circle/sb-slider-v-grip.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/sizegrip/circle/sizegrip-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/sizegrip/circle/sizegrip.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/chevron/tree-arrow-down-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/chevron/tree-arrow-down-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/chevron/tree-arrow-down-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/chevron/tree-arrow-right-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/chevron/tree-arrow-right-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/open/tree-arrow-down-n-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/open/tree-arrow-down-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/open/tree-arrow-down-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/open/tree-arrow-right-n-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/open/tree-arrow-right-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/open/tree-arrow-right-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/plusminus-box/tree-arrow-down-n-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/plusminus-box/tree-arrow-down-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/plusminus-box/tree-arrow-down-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/plusminus-box/tree-arrow-right-n-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/plusminus-box/tree-arrow-right-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/plusminus-box/tree-arrow-right-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/solid/tree-arrow-down-n-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/solid/tree-arrow-down-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/solid/tree-arrow-down-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/solid/tree-arrow-right-n-base.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/solid/tree-arrow-right-n.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/i/awthemes/treeview/solid/tree-arrow-right-sn.svg +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/TkinterTheme/awthemes-10.4.0/pkgIndex.tcl +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/UM Logo.ico +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/__init__.py +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/assign_unique_id.py +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/bayes_functions.py +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/extract_raw_data.py +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/overlord.py +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/run.py +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/save_utils.py +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy/utils.py +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy.egg-info/SOURCES.txt +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy.egg-info/dependency_links.txt +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy.egg-info/requires.txt +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/UnitMatchPy.egg-info/top_level.txt +0 -0
- {unitmatchpy-3.2.8 → unitmatchpy-3.3.0}/setup.cfg +0 -0
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: UnitMatchPy
|
|
3
|
+
Version: 3.3.0
|
|
4
|
+
Summary: Automatic matching of neurons across sessions
|
|
5
|
+
Author: Enny van Beest, Célian Bimbard, Suyash Agarwal, Wentao Qiu
|
|
6
|
+
License: CC BY-NC-SA 4.0 International
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Requires-Python: <3.13,>=3.9
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Requires-Dist: numpy<2.0,>=1.21
|
|
17
|
+
Requires-Dist: scipy<2.0,>=1.9
|
|
18
|
+
Requires-Dist: pandas<3.0,>=1.5
|
|
19
|
+
Requires-Dist: matplotlib<4.0,>=3.6
|
|
20
|
+
Requires-Dist: joblib<2.0,>=1.2
|
|
21
|
+
Requires-Dist: tqdm<5.0,>=4.64
|
|
22
|
+
Requires-Dist: h5py<4.0,>=3.8
|
|
23
|
+
Requires-Dist: scikit-learn<2.0,>=1.2
|
|
24
|
+
Requires-Dist: mtscomp
|
|
25
|
+
Requires-Dist: torch<3.0,>=2.1
|
|
26
|
+
Provides-Extra: full
|
|
27
|
+
Requires-Dist: mat73<1.0,>=0.62; extra == "full"
|
|
28
|
+
Requires-Dist: spikeinterface<0.120,>=0.100; extra == "full"
|
|
29
|
+
Provides-Extra: notebooks
|
|
30
|
+
Requires-Dist: ipykernel<7,>=6; extra == "notebooks"
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest; extra == "dev"
|
|
33
|
+
Requires-Dist: ruff; extra == "dev"
|
|
34
|
+
Requires-Dist: mypy; extra == "dev"
|
|
35
|
+
Requires-Dist: build; extra == "dev"
|
|
36
|
+
Requires-Dist: twine; extra == "dev"
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
|
|
39
|
+
# UnitMatchPy (UMPy) and DeepUnitMatch (DUM)
|
|
40
|
+
|
|
41
|
+
This repository contains:
|
|
42
|
+
- **UnitMatchPy (UMPy)**: automatic matching of neurons across sessions (Python package).
|
|
43
|
+
- **DeepUnitMatch (DUM)**: DeepUnitMatch pipeline and demos (see preprint below).
|
|
44
|
+
|
|
45
|
+
## References
|
|
46
|
+
|
|
47
|
+
- **UnitMatch (UMPy):** https://www.nature.com/articles/s41592-024-02440-1
|
|
48
|
+
- **DeepUnitMatch (DUM) preprint:** https://www.biorxiv.org/content/10.64898/2026.01.30.702777v1
|
|
49
|
+
|
|
50
|
+
## Versions
|
|
51
|
+
|
|
52
|
+
- **UnitMatchPy version:** `3.2.9` (from `pyproject.toml`)
|
|
53
|
+
- **DeepUnitMatch:** code lives under `DeepUnitMatch/` (see **DeepUnitMatch (DUM)** section)
|
|
54
|
+
|
|
55
|
+
## Installation
|
|
56
|
+
|
|
57
|
+
`pip install` (including `pip install -e .`) installs into whatever Python environment your `pip` points to (system Python, a conda env, or a virtualenv). `pip` does **not** create or name environments.
|
|
58
|
+
|
|
59
|
+
We recommend using Anaconda/Miniconda (conda) to create an isolated environment first:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# Create a new environment (pick any name you like; example: UMPy)
|
|
63
|
+
conda create -n UMPy python=3.11 pip #(press y when prompted)
|
|
64
|
+
conda activate UMPy
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Then install using pip (options below).
|
|
68
|
+
|
|
69
|
+
### Option A: Install the released package (PyPI)
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install UnitMatchPy
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Optional extras (heavier dependencies used by some notebooks and integration with SpikeInterface):
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install "UnitMatchPy[full,notebooks]"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Option B: Install a local, editable copy (for development / modified code)
|
|
82
|
+
|
|
83
|
+
First, open a terminal and navigate to this folder (the one containing `pyproject.toml`). The `pip install -e` command must be run from here:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# Windows (PowerShell)
|
|
87
|
+
cd $HOME\Documents\GitHub\DeepUnitMatch\UnitMatchPy
|
|
88
|
+
|
|
89
|
+
# macOS / Linux
|
|
90
|
+
cd ~/Documents/GitHub/DeepUnitMatch/UnitMatchPy
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
pip install -e .
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Optional extras (e.g. if you'd like to run the notebooks or integrate with SpikeInterface):
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
pip install -e ".[full,notebooks]"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Demo notebooks
|
|
104
|
+
|
|
105
|
+
All demo notebooks are in `Demo Notebooks/`.
|
|
106
|
+
|
|
107
|
+
### Run UnitMatchPy (UMPy)
|
|
108
|
+
|
|
109
|
+
To run UMPy, standard spike sorting data is needed (channel positions and extracted raw waveforms for each unit). Waveforms can be extracted externally (e.g. [BombCell](https://github.com/Julie-Fabre/bombcell)) or using the demo notebooks:
|
|
110
|
+
- `Demo Notebooks/extract_raw_data_demo.ipynb` (compressed `.cbin`/`.ch` or raw)
|
|
111
|
+
- `Demo Notebooks/extract_raw_data_demo_open_ephys.ipynb` (Open Ephys)
|
|
112
|
+
- `Demo Notebooks/UMPy_spike_interface_demo.ipynb` ([SpikeInterface](https://spikeinterface.readthedocs.io/en/latest/) workflow)
|
|
113
|
+
|
|
114
|
+
Example notebooks:
|
|
115
|
+
- `Demo Notebooks/UMPy_example.ipynb` (recommended starting point)
|
|
116
|
+
- `Demo Notebooks/UMPy_example_detailed.ipynb` (more modular / advanced)
|
|
117
|
+
|
|
118
|
+
The GUI is an optional step to curate and explore UnitMatch outputs; see `Demo Notebooks/GUI_Reference_Guide.md` for usage tips and shortcuts.
|
|
119
|
+
|
|
120
|
+
## DeepUnitMatch (DUM)
|
|
121
|
+
|
|
122
|
+
To try the DeepUnitMatch version, start with:
|
|
123
|
+
- `Demo Notebooks/DeepUnitMatch.ipynb`
|
|
124
|
+
|
|
125
|
+
If you want to train / fine-tune a model on your own data, see:
|
|
126
|
+
- `Demo Notebooks/DUM_training.ipynb`
|
|
127
|
+
|
|
128
|
+
Important note: DeepUnitMatch current trained model is for Npix 2.0 4-shank only. You will need to train a new model with your own data if you have any other type of probe. (For example, Mouse2 from the figshare data is a Npix 1 dataset, you'll notice the trained model won't give good results on this mouse for that reason.)
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# UnitMatchPy (UMPy) and DeepUnitMatch (DUM)
|
|
2
|
+
|
|
3
|
+
This repository contains:
|
|
4
|
+
- **UnitMatchPy (UMPy)**: automatic matching of neurons across sessions (Python package).
|
|
5
|
+
- **DeepUnitMatch (DUM)**: DeepUnitMatch pipeline and demos (see preprint below).
|
|
6
|
+
|
|
7
|
+
## References
|
|
8
|
+
|
|
9
|
+
- **UnitMatch (UMPy):** https://www.nature.com/articles/s41592-024-02440-1
|
|
10
|
+
- **DeepUnitMatch (DUM) preprint:** https://www.biorxiv.org/content/10.64898/2026.01.30.702777v1
|
|
11
|
+
|
|
12
|
+
## Versions
|
|
13
|
+
|
|
14
|
+
- **UnitMatchPy version:** `3.2.9` (from `pyproject.toml`)
|
|
15
|
+
- **DeepUnitMatch:** code lives under `DeepUnitMatch/` (see **DeepUnitMatch (DUM)** section)
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
`pip install` (including `pip install -e .`) installs into whatever Python environment your `pip` points to (system Python, a conda env, or a virtualenv). `pip` does **not** create or name environments.
|
|
20
|
+
|
|
21
|
+
We recommend using Anaconda/Miniconda (conda) to create an isolated environment first:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# Create a new environment (pick any name you like; example: UMPy)
|
|
25
|
+
conda create -n UMPy python=3.11 pip #(press y when prompted)
|
|
26
|
+
conda activate UMPy
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Then install using pip (options below).
|
|
30
|
+
|
|
31
|
+
### Option A: Install the released package (PyPI)
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
pip install UnitMatchPy
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Optional extras (heavier dependencies used by some notebooks and integration with SpikeInterface):
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install "UnitMatchPy[full,notebooks]"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Option B: Install a local, editable copy (for development / modified code)
|
|
44
|
+
|
|
45
|
+
First, open a terminal and navigate to this folder (the one containing `pyproject.toml`). The `pip install -e` command must be run from here:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Windows (PowerShell)
|
|
49
|
+
cd $HOME\Documents\GitHub\DeepUnitMatch\UnitMatchPy
|
|
50
|
+
|
|
51
|
+
# macOS / Linux
|
|
52
|
+
cd ~/Documents/GitHub/DeepUnitMatch/UnitMatchPy
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install -e .
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Optional extras (e.g. if you'd like to run the notebooks or integrate with SpikeInterface):
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
pip install -e ".[full,notebooks]"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Demo notebooks
|
|
66
|
+
|
|
67
|
+
All demo notebooks are in `Demo Notebooks/`.
|
|
68
|
+
|
|
69
|
+
### Run UnitMatchPy (UMPy)
|
|
70
|
+
|
|
71
|
+
To run UMPy, standard spike sorting data is needed (channel positions and extracted raw waveforms for each unit). Waveforms can be extracted externally (e.g. [BombCell](https://github.com/Julie-Fabre/bombcell)) or using the demo notebooks:
|
|
72
|
+
- `Demo Notebooks/extract_raw_data_demo.ipynb` (compressed `.cbin`/`.ch` or raw)
|
|
73
|
+
- `Demo Notebooks/extract_raw_data_demo_open_ephys.ipynb` (Open Ephys)
|
|
74
|
+
- `Demo Notebooks/UMPy_spike_interface_demo.ipynb` ([SpikeInterface](https://spikeinterface.readthedocs.io/en/latest/) workflow)
|
|
75
|
+
|
|
76
|
+
Example notebooks:
|
|
77
|
+
- `Demo Notebooks/UMPy_example.ipynb` (recommended starting point)
|
|
78
|
+
- `Demo Notebooks/UMPy_example_detailed.ipynb` (more modular / advanced)
|
|
79
|
+
|
|
80
|
+
The GUI is an optional step to curate and explore UnitMatch outputs; see `Demo Notebooks/GUI_Reference_Guide.md` for usage tips and shortcuts.
|
|
81
|
+
|
|
82
|
+
## DeepUnitMatch (DUM)
|
|
83
|
+
|
|
84
|
+
To try the DeepUnitMatch version, start with:
|
|
85
|
+
- `Demo Notebooks/DeepUnitMatch.ipynb`
|
|
86
|
+
|
|
87
|
+
If you want to train / fine-tune a model on your own data, see:
|
|
88
|
+
- `Demo Notebooks/DUM_training.ipynb`
|
|
89
|
+
|
|
90
|
+
Important note: DeepUnitMatch current trained model is for Npix 2.0 4-shank only. You will need to train a new model with your own data if you have any other type of probe. (For example, Mouse2 from the figshare data is a Npix 1 dataset, you'll notice the trained model won't give good results on this mouse for that reason.)
|
|
@@ -25,7 +25,8 @@ def get_default_param(param = None):
|
|
|
25
25
|
'min_angle_dist' : 0.1, # smallest distance for and angle to be consider
|
|
26
26
|
'min_new_shank_distance' : 100, #The smallest distance which separates 2 shanks
|
|
27
27
|
'units_per_shank_thrs' : 15, # threshold for doing per shank drift correction
|
|
28
|
-
'match_threshold' : 0.5 # probability threshold to consider as a match
|
|
28
|
+
'match_threshold' : 0.5, # probability threshold to consider as a match
|
|
29
|
+
'curve_fit_maxfev' : 10000, # max evaluations for decay curve fitting
|
|
29
30
|
}
|
|
30
31
|
|
|
31
32
|
tmp['score_vector'] = np.arange(tmp['stepsz']/2 ,1 ,tmp['stepsz'])
|
|
@@ -118,7 +118,7 @@ def get_waveforms_mse(avg_waveform, param):
|
|
|
118
118
|
waveform_mse = re_scale(raw_wave_mse_norm)
|
|
119
119
|
return waveform_mse
|
|
120
120
|
|
|
121
|
-
def flip_dim(avg_waveform_per_tp, param):
|
|
121
|
+
def flip_dim(avg_waveform_per_tp, param, n=None):
|
|
122
122
|
"""
|
|
123
123
|
Creates a version of the weighted average waveform per time point, where the x axis is flipped, due to the effect
|
|
124
124
|
where the average position tends to wards the center of the x coords when the wave is decaying
|
|
@@ -135,7 +135,10 @@ def flip_dim(avg_waveform_per_tp, param):
|
|
|
135
135
|
ndarray
|
|
136
136
|
The average waveform per time point with the x axis flipped and not flipped
|
|
137
137
|
"""
|
|
138
|
-
|
|
138
|
+
if n is not None:
|
|
139
|
+
n_units = n
|
|
140
|
+
else:
|
|
141
|
+
n_units = param['n_units']
|
|
139
142
|
spike_width = param['spike_width']
|
|
140
143
|
|
|
141
144
|
flip_dim = np.array((1,)) # BE CAREFUL HERE, Which dimension is the x-axis
|
|
@@ -152,7 +155,7 @@ def flip_dim(avg_waveform_per_tp, param):
|
|
|
152
155
|
|
|
153
156
|
return avg_waveform_per_tp_flip
|
|
154
157
|
|
|
155
|
-
def get_Euclidean_dist(avg_waveform_per_tp_flip,param):
|
|
158
|
+
def get_Euclidean_dist(avg_waveform_per_tp_flip,param, n=None):
|
|
156
159
|
"""
|
|
157
160
|
Calculated the Euclidean distance between the units at each time point and for the flipped axis case
|
|
158
161
|
|
|
@@ -170,7 +173,10 @@ def get_Euclidean_dist(avg_waveform_per_tp_flip,param):
|
|
|
170
173
|
"""
|
|
171
174
|
# Memory-efficient implementation using loops instead of massive tiling
|
|
172
175
|
waveidx = param['waveidx']
|
|
173
|
-
|
|
176
|
+
if n is not None:
|
|
177
|
+
n_units = n
|
|
178
|
+
else:
|
|
179
|
+
n_units = param['n_units']
|
|
174
180
|
|
|
175
181
|
# Extract the relevant slices once
|
|
176
182
|
data_cv0 = avg_waveform_per_tp_flip[:,:,waveidx,0,:] # (3, n_units, len(waveidx), n_flips)
|
|
@@ -186,13 +192,13 @@ def get_Euclidean_dist(avg_waveform_per_tp_flip,param):
|
|
|
186
192
|
unit_i_data = data_cv0[:, i, :, :] # (3, len(waveidx), n_flips)
|
|
187
193
|
unit_j_data = data_cv1[:, j, :, :] # (3, len(waveidx), n_flips)
|
|
188
194
|
|
|
189
|
-
# Check for NaN values
|
|
190
|
-
w = np.isnan(np.abs(unit_i_data[0,:,:] - unit_j_data[0,:,:]))
|
|
191
|
-
|
|
192
195
|
# Compute Euclidean distance between units i and j
|
|
193
196
|
diff = unit_i_data - unit_j_data # (3, len(waveidx), n_flips)
|
|
194
197
|
tmp_euclid = np.linalg.norm(diff, axis=0) # (len(waveidx), n_flips)
|
|
195
|
-
|
|
198
|
+
|
|
199
|
+
# Be explicit about NaNs across any spatial dimension
|
|
200
|
+
nan_mask = np.isnan(diff).any(axis=0)
|
|
201
|
+
tmp_euclid[nan_mask] = np.nan
|
|
196
202
|
|
|
197
203
|
# Store result
|
|
198
204
|
euclid_dist[i, :, :, j] = tmp_euclid
|
|
@@ -216,19 +222,30 @@ def centroid_metrics(euclid_dist, param):
|
|
|
216
222
|
An array (n_units, n_units) of scores for centroid distance and variance
|
|
217
223
|
"""
|
|
218
224
|
max_dist = param['max_dist']
|
|
219
|
-
waveidx = param['waveidx']
|
|
220
|
-
|
|
225
|
+
waveidx = np.asarray(param['waveidx'])
|
|
226
|
+
peak_loc = int(param['peak_loc'])
|
|
221
227
|
|
|
222
|
-
|
|
228
|
+
peak_matches = np.flatnonzero(waveidx == peak_loc)
|
|
229
|
+
if peak_matches.size == 0:
|
|
230
|
+
raise ValueError("param['peak_loc'] must be present in param['waveidx'].")
|
|
231
|
+
peak_idx = int(peak_matches[0])
|
|
223
232
|
|
|
233
|
+
# euclid_dist: (n_units, n_waveidx, n_flips, n_units)
|
|
234
|
+
centroid_dist = np.nanmin(euclid_dist[:, peak_idx, :, :], axis=1)
|
|
224
235
|
|
|
225
|
-
|
|
226
|
-
|
|
236
|
+
min_centroid_dist = np.nanmin(centroid_dist)
|
|
237
|
+
denom = max_dist - min_centroid_dist
|
|
238
|
+
if not np.isfinite(denom) or denom <= 0:
|
|
239
|
+
centroid_dist = np.zeros_like(centroid_dist)
|
|
240
|
+
else:
|
|
241
|
+
centroid_dist = 1 - ((centroid_dist - min_centroid_dist) / denom)
|
|
242
|
+
centroid_dist = np.clip(centroid_dist, 0, 1)
|
|
227
243
|
centroid_dist[np.isnan(centroid_dist)] = 0
|
|
228
244
|
|
|
229
245
|
#Centroid Var
|
|
230
246
|
# need ddof = 1 to match with ML
|
|
231
|
-
|
|
247
|
+
ddof = 1 if euclid_dist.shape[1] > 1 else 0
|
|
248
|
+
centroid_var = np.nanmin(np.nanvar(euclid_dist, axis=1, ddof=ddof), axis=1)
|
|
232
249
|
centroid_var = np.sqrt(centroid_var)
|
|
233
250
|
centroid_var = re_scale(centroid_var)
|
|
234
251
|
centroid_var[np.isnan(centroid_var)] = 0
|
|
@@ -696,6 +713,14 @@ def test_matches_per_shank(pairs, avg_centroid, sid, param):
|
|
|
696
713
|
Will return True if there is enough units per shank to do per shank drift correction
|
|
697
714
|
"""
|
|
698
715
|
|
|
716
|
+
pairs = np.asarray(pairs)
|
|
717
|
+
if pairs.size == 0:
|
|
718
|
+
return False
|
|
719
|
+
if pairs.ndim == 1:
|
|
720
|
+
pairs = np.expand_dims(pairs, axis=0)
|
|
721
|
+
if pairs.ndim != 2 or pairs.shape[1] != 2:
|
|
722
|
+
raise ValueError("pairs must have shape (n_pairs, 2).")
|
|
723
|
+
|
|
699
724
|
do_per_shank_correction = True
|
|
700
725
|
|
|
701
726
|
centroid_a = np.nanmean( avg_centroid[:,pairs[:,0],:], axis = 2)
|
|
@@ -718,10 +743,10 @@ def test_matches_per_shank(pairs, avg_centroid, sid, param):
|
|
|
718
743
|
|
|
719
744
|
if np.all(correct_shank_a == correct_shank_b) != True:
|
|
720
745
|
#delete pairs which are on different shanks
|
|
721
|
-
bad_idx = np.
|
|
746
|
+
bad_idx = np.flatnonzero(correct_shank_a != correct_shank_b)
|
|
722
747
|
print(f'These pairs may be bad {bad_idx}, so are excluded from drift correction')
|
|
723
|
-
correct_shank_a[bad_idx]=False
|
|
724
|
-
correct_shank_b[bad_idx]=False
|
|
748
|
+
correct_shank_a[bad_idx] = False
|
|
749
|
+
correct_shank_b[bad_idx] = False
|
|
725
750
|
|
|
726
751
|
shank_id_tmp[correct_shank_a] = i
|
|
727
752
|
|
|
@@ -771,8 +796,10 @@ def drift_n_sessions(candidate_pairs, session_switch, avg_centroid, avg_waveform
|
|
|
771
796
|
n_sessions = param['n_sessions']
|
|
772
797
|
best_pairs = np.argwhere(candidate_pairs == 1)
|
|
773
798
|
|
|
774
|
-
#
|
|
775
|
-
best_pairs
|
|
799
|
+
# Ensure each pair is ordered (small idx, large idx) regardless of matrix orientation
|
|
800
|
+
best_pairs = np.sort(best_pairs, axis=1)
|
|
801
|
+
if best_pairs.size > 0:
|
|
802
|
+
best_pairs = np.unique(best_pairs, axis=0)
|
|
776
803
|
|
|
777
804
|
drifts = np.zeros( (n_sessions - 1, 3))
|
|
778
805
|
|
|
@@ -799,6 +826,68 @@ def drift_n_sessions(candidate_pairs, session_switch, avg_centroid, avg_waveform
|
|
|
799
826
|
return drifts, avg_centroid, avg_waveform_per_tp
|
|
800
827
|
|
|
801
828
|
|
|
829
|
+
def drift_correct_session_pair(candidate_pairs, session_switch, avg_centroid, avg_waveform_per_tp, did, param):
|
|
830
|
+
"""
|
|
831
|
+
This function applies drift correction between n_sessions, currently this is done by aligning session 2 to session 1,
|
|
832
|
+
then session 3 to session 2 etc.
|
|
833
|
+
This function, calls another function to apply the drift correction, to be able to apply different type of drift correction
|
|
834
|
+
easily.
|
|
835
|
+
|
|
836
|
+
Parameters
|
|
837
|
+
----------
|
|
838
|
+
candidate_pairs : ndarray
|
|
839
|
+
An array of likely matches
|
|
840
|
+
session_switch : ndarray
|
|
841
|
+
What units does the session switch
|
|
842
|
+
avg_centroid : ndarray
|
|
843
|
+
The average centroid for each unit
|
|
844
|
+
avg_waveform_per_tp : ndarray
|
|
845
|
+
The average waveform per time point for each unit
|
|
846
|
+
did : int
|
|
847
|
+
The session id
|
|
848
|
+
param : dict
|
|
849
|
+
The param dictionary
|
|
850
|
+
|
|
851
|
+
Returns
|
|
852
|
+
-------
|
|
853
|
+
ndarray
|
|
854
|
+
avg_waveform_per_tp arrays drift corrected
|
|
855
|
+
"""
|
|
856
|
+
session_switch = np.asarray(session_switch).astype(int)
|
|
857
|
+
n_units = avg_centroid.shape[1]
|
|
858
|
+
if candidate_pairs.shape != (n_units, n_units):
|
|
859
|
+
raise ValueError("candidate_pairs must have shape (n_units, n_units) matching avg_centroid/avg_waveform_per_tp.")
|
|
860
|
+
if session_switch.ndim != 1 or session_switch.size < 3:
|
|
861
|
+
raise ValueError("session_switch must be a 1D array with at least 3 entries (start, boundary, end).")
|
|
862
|
+
if session_switch[0] != 0 or session_switch[-1] != n_units:
|
|
863
|
+
raise ValueError("session_switch must be relative to the provided arrays (session_switch[0]==0 and session_switch[-1]==n_units).")
|
|
864
|
+
if did < 0 or (did + 2) >= session_switch.size:
|
|
865
|
+
raise IndexError("did out of range for session_switch.")
|
|
866
|
+
|
|
867
|
+
best_pairs = np.argwhere(candidate_pairs == 1)
|
|
868
|
+
|
|
869
|
+
# Ensure each pair is ordered (small idx, large idx) regardless of matrix orientation
|
|
870
|
+
best_pairs = np.sort(best_pairs, axis=1)
|
|
871
|
+
if best_pairs.size > 0:
|
|
872
|
+
best_pairs = np.unique(best_pairs, axis=0)
|
|
873
|
+
|
|
874
|
+
idx = np.argwhere( ( (best_pairs[:,0] >= session_switch[did]) * (best_pairs[:,0] < session_switch[did + 1]) *
|
|
875
|
+
(best_pairs[:,1] >= session_switch[did + 1]) * (best_pairs[:,1] < session_switch[did + 2]) ) == True)
|
|
876
|
+
|
|
877
|
+
pairs = best_pairs[idx,:].squeeze()
|
|
878
|
+
if pairs.ndim == 1:
|
|
879
|
+
pairs = np.expand_dims(pairs, axis = 0)
|
|
880
|
+
|
|
881
|
+
#Test to see if there are enough matches to do drift correction per shank
|
|
882
|
+
if test_matches_per_shank(pairs, avg_centroid, did, param) == True:
|
|
883
|
+
_, avg_waveform_per_tp,_ = apply_drift_correction_per_shank(pairs, did, session_switch, avg_centroid, avg_waveform_per_tp, param)
|
|
884
|
+
print(f'Done drift correction per shank for session pair {did+1} and {did+2}')
|
|
885
|
+
elif len(pairs)>0: #if there exist pairs across sessions:
|
|
886
|
+
_, avg_waveform_per_tp,_ = apply_drift_correction_basic(pairs, did, session_switch, avg_centroid, avg_waveform_per_tp)
|
|
887
|
+
elif len(pairs)==0:
|
|
888
|
+
print('No pairs across sessions to perform drift correction.')
|
|
889
|
+
return avg_waveform_per_tp
|
|
890
|
+
|
|
802
891
|
|
|
803
892
|
def get_total_score(scores_to_include, param):
|
|
804
893
|
"""
|
|
@@ -175,6 +175,7 @@ def decay_and_average_waveform(waveform, channel_pos, good_idx, max_site, max_si
|
|
|
175
175
|
new_peak_loc = param['peak_loc']
|
|
176
176
|
waveidx = param['waveidx']
|
|
177
177
|
channel_radius = param['channel_radius']
|
|
178
|
+
maxfev = param.get('curve_fit_maxfev', 10000)
|
|
178
179
|
session_id = clus_info['session_id']
|
|
179
180
|
|
|
180
181
|
spatial_decay_fit = np.zeros((n_units,2))
|
|
@@ -196,7 +197,14 @@ def decay_and_average_waveform(waveform, channel_pos, good_idx, max_site, max_si
|
|
|
196
197
|
dist_to_max_chan = dist_to_max_chan[dist_to_max_chan != 0]
|
|
197
198
|
|
|
198
199
|
# there is variation in how different programming languages/options fit to a curve
|
|
199
|
-
popt, pcurve = sp.optimize.curve_fit(
|
|
200
|
+
popt, pcurve = sp.optimize.curve_fit(
|
|
201
|
+
exponential_func,
|
|
202
|
+
dist_to_max_chan.T,
|
|
203
|
+
tmp_amp,
|
|
204
|
+
p0=(np.max(tmp_amp), 0.05),
|
|
205
|
+
method='trf',
|
|
206
|
+
maxfev=maxfev,
|
|
207
|
+
)
|
|
200
208
|
#popt, pcurve = sp.optimize.least_squares(exponential_func, Dist2MaxChan, TmpAmp, p0 = (np.max(TmpAmp), 0.05) )
|
|
201
209
|
|
|
202
210
|
spatial_decay_fit[i,cv] = popt[1]
|
|
@@ -406,4 +414,4 @@ def get_avg_waveform_per_tp(waveform, channel_pos, d_10, max_site_mean, amplitud
|
|
|
406
414
|
avg_waveform_per_tp[dim, uid, good_wave_idxs[uid,:,cv].astype(bool), cv] = gaussian_filter(avg_waveform_per_tp[dim, uid, good_wave_idxs[uid,:,cv].astype(bool), cv], 1, radius = 2, axes = 0)
|
|
407
415
|
|
|
408
416
|
return waveform_duration, avg_waveform_per_tp, good_wave_idxs
|
|
409
|
-
|
|
417
|
+
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: UnitMatchPy
|
|
3
|
+
Version: 3.3.0
|
|
4
|
+
Summary: Automatic matching of neurons across sessions
|
|
5
|
+
Author: Enny van Beest, Célian Bimbard, Suyash Agarwal, Wentao Qiu
|
|
6
|
+
License: CC BY-NC-SA 4.0 International
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
9
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
10
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Requires-Python: <3.13,>=3.9
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Requires-Dist: numpy<2.0,>=1.21
|
|
17
|
+
Requires-Dist: scipy<2.0,>=1.9
|
|
18
|
+
Requires-Dist: pandas<3.0,>=1.5
|
|
19
|
+
Requires-Dist: matplotlib<4.0,>=3.6
|
|
20
|
+
Requires-Dist: joblib<2.0,>=1.2
|
|
21
|
+
Requires-Dist: tqdm<5.0,>=4.64
|
|
22
|
+
Requires-Dist: h5py<4.0,>=3.8
|
|
23
|
+
Requires-Dist: scikit-learn<2.0,>=1.2
|
|
24
|
+
Requires-Dist: mtscomp
|
|
25
|
+
Requires-Dist: torch<3.0,>=2.1
|
|
26
|
+
Provides-Extra: full
|
|
27
|
+
Requires-Dist: mat73<1.0,>=0.62; extra == "full"
|
|
28
|
+
Requires-Dist: spikeinterface<0.120,>=0.100; extra == "full"
|
|
29
|
+
Provides-Extra: notebooks
|
|
30
|
+
Requires-Dist: ipykernel<7,>=6; extra == "notebooks"
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest; extra == "dev"
|
|
33
|
+
Requires-Dist: ruff; extra == "dev"
|
|
34
|
+
Requires-Dist: mypy; extra == "dev"
|
|
35
|
+
Requires-Dist: build; extra == "dev"
|
|
36
|
+
Requires-Dist: twine; extra == "dev"
|
|
37
|
+
Dynamic: license-file
|
|
38
|
+
|
|
39
|
+
# UnitMatchPy (UMPy) and DeepUnitMatch (DUM)
|
|
40
|
+
|
|
41
|
+
This repository contains:
|
|
42
|
+
- **UnitMatchPy (UMPy)**: automatic matching of neurons across sessions (Python package).
|
|
43
|
+
- **DeepUnitMatch (DUM)**: DeepUnitMatch pipeline and demos (see preprint below).
|
|
44
|
+
|
|
45
|
+
## References
|
|
46
|
+
|
|
47
|
+
- **UnitMatch (UMPy):** https://www.nature.com/articles/s41592-024-02440-1
|
|
48
|
+
- **DeepUnitMatch (DUM) preprint:** https://www.biorxiv.org/content/10.64898/2026.01.30.702777v1
|
|
49
|
+
|
|
50
|
+
## Versions
|
|
51
|
+
|
|
52
|
+
- **UnitMatchPy version:** `3.2.9` (from `pyproject.toml`)
|
|
53
|
+
- **DeepUnitMatch:** code lives under `DeepUnitMatch/` (see **DeepUnitMatch (DUM)** section)
|
|
54
|
+
|
|
55
|
+
## Installation
|
|
56
|
+
|
|
57
|
+
`pip install` (including `pip install -e .`) installs into whatever Python environment your `pip` points to (system Python, a conda env, or a virtualenv). `pip` does **not** create or name environments.
|
|
58
|
+
|
|
59
|
+
We recommend using Anaconda/Miniconda (conda) to create an isolated environment first:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# Create a new environment (pick any name you like; example: UMPy)
|
|
63
|
+
conda create -n UMPy python=3.11 pip #(press y when prompted)
|
|
64
|
+
conda activate UMPy
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Then install using pip (options below).
|
|
68
|
+
|
|
69
|
+
### Option A: Install the released package (PyPI)
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install UnitMatchPy
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Optional extras (heavier dependencies used by some notebooks and integration with SpikeInterface):
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
pip install "UnitMatchPy[full,notebooks]"
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Option B: Install a local, editable copy (for development / modified code)
|
|
82
|
+
|
|
83
|
+
First, open a terminal and navigate to this folder (the one containing `pyproject.toml`). The `pip install -e` command must be run from here:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
# Windows (PowerShell)
|
|
87
|
+
cd $HOME\Documents\GitHub\DeepUnitMatch\UnitMatchPy
|
|
88
|
+
|
|
89
|
+
# macOS / Linux
|
|
90
|
+
cd ~/Documents/GitHub/DeepUnitMatch/UnitMatchPy
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
pip install -e .
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Optional extras (e.g. if you'd like to run the notebooks or integrate with SpikeInterface):
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
pip install -e ".[full,notebooks]"
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## Demo notebooks
|
|
104
|
+
|
|
105
|
+
All demo notebooks are in `Demo Notebooks/`.
|
|
106
|
+
|
|
107
|
+
### Run UnitMatchPy (UMPy)
|
|
108
|
+
|
|
109
|
+
To run UMPy, standard spike sorting data is needed (channel positions and extracted raw waveforms for each unit). Waveforms can be extracted externally (e.g. [BombCell](https://github.com/Julie-Fabre/bombcell)) or using the demo notebooks:
|
|
110
|
+
- `Demo Notebooks/extract_raw_data_demo.ipynb` (compressed `.cbin`/`.ch` or raw)
|
|
111
|
+
- `Demo Notebooks/extract_raw_data_demo_open_ephys.ipynb` (Open Ephys)
|
|
112
|
+
- `Demo Notebooks/UMPy_spike_interface_demo.ipynb` ([SpikeInterface](https://spikeinterface.readthedocs.io/en/latest/) workflow)
|
|
113
|
+
|
|
114
|
+
Example notebooks:
|
|
115
|
+
- `Demo Notebooks/UMPy_example.ipynb` (recommended starting point)
|
|
116
|
+
- `Demo Notebooks/UMPy_example_detailed.ipynb` (more modular / advanced)
|
|
117
|
+
|
|
118
|
+
The GUI is an optional step to curate and explore UnitMatch outputs; see `Demo Notebooks/GUI_Reference_Guide.md` for usage tips and shortcuts.
|
|
119
|
+
|
|
120
|
+
## DeepUnitMatch (DUM)
|
|
121
|
+
|
|
122
|
+
To try the DeepUnitMatch version, start with:
|
|
123
|
+
- `Demo Notebooks/DeepUnitMatch.ipynb`
|
|
124
|
+
|
|
125
|
+
If you want to train / fine-tune a model on your own data, see:
|
|
126
|
+
- `Demo Notebooks/DUM_training.ipynb`
|
|
127
|
+
|
|
128
|
+
Important note: DeepUnitMatch current trained model is for Npix 2.0 4-shank only. You will need to train a new model with your own data if you have any other type of probe. (For example, Mouse2 from the figshare data is a Npix 1 dataset, you'll notice the trained model won't give good results on this mouse for that reason.)
|
|
@@ -4,12 +4,13 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "UnitMatchPy"
|
|
7
|
-
version = "3.
|
|
7
|
+
version = "3.3.0" # bump on each release
|
|
8
8
|
description = "Automatic matching of neurons across sessions"
|
|
9
9
|
readme = "README.md" # keep a README.md inside UnitMatchPy/
|
|
10
|
-
requires-python = ">=3.9"
|
|
10
|
+
requires-python = ">=3.9,<3.13"
|
|
11
11
|
authors = [
|
|
12
12
|
{ name = "Enny van Beest" },
|
|
13
|
+
{ name = "Célian Bimbard" },
|
|
13
14
|
{ name = "Suyash Agarwal" },
|
|
14
15
|
{ name = "Wentao Qiu" },
|
|
15
16
|
]
|
unitmatchpy-3.2.8/PKG-INFO
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: UnitMatchPy
|
|
3
|
-
Version: 3.2.8
|
|
4
|
-
Summary: Automatic matching of neurons across sessions
|
|
5
|
-
Author: Enny van Beest, Suyash Agarwal, Wentao Qiu
|
|
6
|
-
License: CC BY-NC-SA 4.0 International
|
|
7
|
-
Classifier: Programming Language :: Python :: 3
|
|
8
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
9
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
10
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
11
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
12
|
-
Classifier: Operating System :: OS Independent
|
|
13
|
-
Requires-Python: >=3.9
|
|
14
|
-
Description-Content-Type: text/markdown
|
|
15
|
-
License-File: LICENSE
|
|
16
|
-
Requires-Dist: numpy<2.0,>=1.21
|
|
17
|
-
Requires-Dist: scipy<2.0,>=1.9
|
|
18
|
-
Requires-Dist: pandas<3.0,>=1.5
|
|
19
|
-
Requires-Dist: matplotlib<4.0,>=3.6
|
|
20
|
-
Requires-Dist: joblib<2.0,>=1.2
|
|
21
|
-
Requires-Dist: tqdm<5.0,>=4.64
|
|
22
|
-
Requires-Dist: h5py<4.0,>=3.8
|
|
23
|
-
Requires-Dist: scikit-learn<2.0,>=1.2
|
|
24
|
-
Requires-Dist: mtscomp
|
|
25
|
-
Requires-Dist: torch<3.0,>=2.1
|
|
26
|
-
Provides-Extra: full
|
|
27
|
-
Requires-Dist: mat73<1.0,>=0.62; extra == "full"
|
|
28
|
-
Requires-Dist: spikeinterface<0.120,>=0.100; extra == "full"
|
|
29
|
-
Provides-Extra: notebooks
|
|
30
|
-
Requires-Dist: ipykernel<7,>=6; extra == "notebooks"
|
|
31
|
-
Provides-Extra: dev
|
|
32
|
-
Requires-Dist: pytest; extra == "dev"
|
|
33
|
-
Requires-Dist: ruff; extra == "dev"
|
|
34
|
-
Requires-Dist: mypy; extra == "dev"
|
|
35
|
-
Requires-Dist: build; extra == "dev"
|
|
36
|
-
Requires-Dist: twine; extra == "dev"
|
|
37
|
-
Dynamic: license-file
|
|
38
|
-
|
|
39
|
-
# Unit Match - Python
|
|
40
|
-
|
|
41
|
-
## Run UMPy
|
|
42
|
-
|
|
43
|
-
To run UMPy standard spike sorting data is needed; channel positions and 2 extracted raw waveforms for each unit. This can be calculated externally [BombCell](https://github.com/Julie-Fabre/bombcell) or using *extract_raw_demo.ipynb* to extract these waveforms from compressed data (.cbin and .ch) or raw data. There is also a [Spike Interface](https://spikeinterface.readthedocs.io/en/latest/) integrated notebook *UMPy_spike_interface_demo.ipynb* which uses spike interface to get this data.
|
|
44
|
-
Be careful not to mix and match the different ways of extracting raw waveforms, as there are difference between the methods.
|
|
45
|
-
|
|
46
|
-
There are to example notebooks for running UMPy *UMPy_example.ipynb* and *UMPy_example_detailed.ipynb*. These notebooks will guide you through running Unit Match all you need to supply is paths to the data. *UMPy_example.ipynb* is recommended to use first as it is simpler, however *UMPy_example_detailed.ipynb* may be useful in unique cases as it is more modular.
|
|
47
|
-
|
|
48
|
-
The GUI is a optional step to curated and investigate the information Unit Match has calculated; for efficient usage of the GUI please look at *GUI_Reference_Guide.md* in the Demo Notebooks folder.
|
|
49
|
-
|
|
50
|
-
## Dependencies
|
|
51
|
-
|
|
52
|
-
This version relies on many core python packages: [numpy](https://numpy.org/), [scipy](https://scipy.org/), [JobLib](https://joblib.readthedocs.io/en/stable/), [pandas](https://pandas.pydata.org/), [tkinter](https://docs.python.org/3/library/tkinter.html) and [matplotlib](https://matplotlib.org/). All of these libaries come with a [Anaconda](https://www.anaconda.com/download/) version of python.
|
|
53
|
-
For extracting raw data, the library [mtscomp](https://github.com/int-brain-lab/mtscomp) is needed, and can be installed by `pip install mtscomp`.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
## Installation
|
|
57
|
-
|
|
58
|
-
After creating an python environment
|
|
59
|
-
|
|
60
|
-
```
|
|
61
|
-
conda create --name UnitMatch python==3.9
|
|
62
|
-
conda activate UnitMatch
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
You can install UnitMatchPy with pip. It will automatically install all the dependencies.
|
|
66
|
-
|
|
67
|
-
```
|
|
68
|
-
pip install UnitMatchPy
|
|
69
|
-
```
|