From cf08a29105e73317eeb67fea8388891cd0585c18 Mon Sep 17 00:00:00 2001 From: <> Date: Tue, 5 Mar 2024 17:58:23 +0000 Subject: [PATCH] Deployed 781a54a with MkDocs version: 1.5.3 --- .../applications/callable.ipynb | 2 +- .../applications/callable/index.html | 2 +- .../applications/callable_codeobj.pickle | Bin 4332 -> 4332 bytes .../applications/chaining.ipynb | 2 +- .../applications/chaining/index.html | 2 +- .../applications/chaining_codeobj.pickle | Bin 11097 -> 11097 bytes generated_examples/applications/hotdog.ipynb | 2 +- .../applications/hotdog/index.html | 2 +- .../applications/hotdog_codeobj.pickle | Bin 3103 -> 3103 bytes .../mg_execution_times/index.html | 12 +++++------ .../applications/pint_quantity.ipynb | 2 +- .../applications/pint_quantity/index.html | 2 +- .../applications/pint_quantity_codeobj.pickle | Bin 4514 -> 4514 bytes .../applications/snells_law.ipynb | 2 +- .../applications/snells_law/index.html | 2 +- .../applications/snells_law_codeobj.pickle | Bin 2601 -> 2601 bytes .../applications/values_dialog.ipynb | 2 +- generated_examples/basic_example.ipynb | 2 +- generated_examples/basic_example/index.html | 2 +- .../basic_example_codeobj.pickle | Bin 2159 -> 2159 bytes generated_examples/basic_widgets_demo.ipynb | 2 +- .../basic_widgets_demo/index.html | 4 ++-- .../basic_widgets_demo_codeobj.pickle | Bin 3340 -> 3340 bytes .../demo_widgets/change_label.ipynb | 2 +- .../demo_widgets/change_label/index.html | 2 +- .../demo_widgets/change_label_codeobj.pickle | Bin 2159 -> 2159 bytes generated_examples/demo_widgets/choices.ipynb | 2 +- .../demo_widgets/choices/index.html | 2 +- .../demo_widgets/choices_codeobj.pickle | Bin 4712 -> 4715 bytes .../demo_widgets/file_dialog.ipynb | 2 +- .../demo_widgets/file_dialog/index.html | 2 +- .../demo_widgets/file_dialog_codeobj.pickle | Bin 6584 -> 6587 bytes generated_examples/demo_widgets/image.ipynb | 2 +- .../demo_widgets/image/index.html | 2 +- .../demo_widgets/image_codeobj.pickle | Bin 2422 -> 2422 bytes .../images/mkd_glr_file_dialog_001.png | Bin 5893 -> 3784 bytes .../images/mkd_glr_file_dialog_002.png | Bin 3784 -> 4436 bytes .../images/mkd_glr_file_dialog_003.png | Bin 4436 -> 5893 bytes .../thumb/mkd_glr_file_dialog_thumb.png | Bin 9227 -> 8605 bytes .../demo_widgets/log_slider.ipynb | 2 +- .../demo_widgets/log_slider_codeobj.pickle | Bin 2060 -> 2060 bytes generated_examples/demo_widgets/login.ipynb | 2 +- .../demo_widgets/login/index.html | 2 +- .../mg_execution_times/index.html | 20 +++++++++--------- .../demo_widgets/optional.ipynb | 2 +- .../demo_widgets/optional/index.html | 2 +- .../demo_widgets/range_slider.ipynb | 2 +- .../demo_widgets/range_slider/index.html | 2 +- .../demo_widgets/selection.ipynb | 2 +- .../demo_widgets/selection_codeobj.pickle | Bin 2015 -> 2015 bytes generated_examples/demo_widgets/table.ipynb | 2 +- .../demo_widgets/table/index.html | 4 ++-- .../demo_widgets/table_codeobj.pickle | Bin 15901 -> 15910 bytes .../generated_examples_jupyter.zip | Bin 82533 -> 82533 bytes .../generated_examples_python.zip | Bin 49935 -> 49935 bytes .../images/mkd_glr_basic_widgets_demo_001.png | Bin 31544 -> 31299 bytes .../mkd_glr_basic_widgets_demo_thumb.png | Bin 25432 -> 25413 bytes .../matplotlib/mg_execution_times/index.html | 6 +++--- .../matplotlib/mpl_figure.ipynb | 2 +- .../matplotlib/mpl_figure/index.html | 2 +- .../matplotlib/mpl_figure_codeobj.pickle | Bin 8649 -> 8658 bytes generated_examples/matplotlib/waveform.ipynb | 2 +- .../matplotlib/waveform/index.html | 2 +- .../matplotlib/waveform_codeobj.pickle | Bin 8871 -> 8850 bytes .../mg_execution_times/index.html | 6 +++--- .../images/mkd_glr_napari_img_math_001.png | Bin 45596 -> 45675 bytes .../thumb/mkd_glr_napari_img_math_thumb.png | Bin 28455 -> 28403 bytes .../napari/mg_execution_times/index.html | 8 +++---- .../napari/napari_combine_qt.ipynb | 2 +- .../napari/napari_combine_qt/index.html | 2 +- .../napari/napari_combine_qt_codeobj.pickle | Bin 8040 -> 8079 bytes .../napari/napari_forward_refs.ipynb | 2 +- .../napari/napari_forward_refs_codeobj.pickle | Bin 2118 -> 2118 bytes .../napari/napari_img_math.ipynb | 2 +- .../napari/napari_img_math/index.html | 2 +- .../napari/napari_img_math_codeobj.pickle | Bin 7453 -> 7495 bytes .../napari/napari_parameter_sweep.ipynb | 2 +- .../napari/napari_parameter_sweep/index.html | 2 +- .../napari_parameter_sweep_codeobj.pickle | Bin 6879 -> 6873 bytes .../notebooks/magicgui_jupyter.ipynb | 2 +- .../mg_execution_times/index.html | 10 ++++----- .../progress_bars/progress.ipynb | 2 +- .../progress_bars/progress/index.html | 2 +- .../progress_bars/progress_codeobj.pickle | Bin 2219 -> 2219 bytes .../progress_indeterminate.ipynb | 2 +- .../progress_indeterminate/index.html | 2 +- .../progress_indeterminate_codeobj.pickle | Bin 2540 -> 2540 bytes .../progress_bars/progress_manual.ipynb | 2 +- .../progress_bars/progress_manual/index.html | 4 ++-- .../progress_manual_codeobj.pickle | Bin 3506 -> 3506 bytes .../progress_bars/progress_nested.ipynb | 2 +- .../progress_bars/progress_nested/index.html | 2 +- .../progress_nested_codeobj.pickle | Bin 3287 -> 3287 bytes .../under_the_hood/class_method.ipynb | 2 +- .../class_method_codeobj.pickle | Bin 4277 -> 4274 bytes .../under_the_hood/self_reference.ipynb | 2 +- .../self_reference_codeobj.pickle | Bin 3545 -> 3545 bytes scripts/__pycache__/_hooks.cpython-312.pyc | Bin 10118 -> 10118 bytes search/search_index.json | 2 +- sitemap.xml.gz | Bin 963 -> 963 bytes type_map/index.html | 2 +- 101 files changed, 91 insertions(+), 91 deletions(-) diff --git a/generated_examples/applications/callable.ipynb b/generated_examples/applications/callable.ipynb index 27112baa0..d2aa32a56 100644 --- a/generated_examples/applications/callable.ipynb +++ b/generated_examples/applications/callable.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/applications/callable/index.html b/generated_examples/applications/callable/index.html index d0641ee10..18c548e4b 100644 --- a/generated_examples/applications/callable/index.html +++ b/generated_examples/applications/callable/index.html @@ -2930,7 +2930,7 @@

Callable functions demoexample.func.changed.connect(update) example.show(run=True) -

Total running time of the script: ( 0 minutes 0.029 seconds)

+

Total running time of the script: ( 0 minutes 0.031 seconds)

Download Python source code: callable.py

diff --git a/generated_examples/applications/callable_codeobj.pickle b/generated_examples/applications/callable_codeobj.pickle index baec7d69af067e4fa895edb993acd4aa4f110cc6..9bdaf09934087a2869ac17da60cf4c3d869e314d 100644 GIT binary patch delta 581 zcmX}qUr19?90zc}x9#5jyLT6wES#IOwcK*unG{KeAVonzU<8U_>mrM-bV_Z|i|-kG zXnZe04>9Pmmk@*?5Q?BE7DW&iRuBk=OnNIH3OYL*z5Mu`-#OoN4xH2MZ}#7{qDKCf zJ-;}Yw~D2k`5R?t#z`$Xsj91F&*vRZDBZP-Ij$nihC4*R9;HtS^NXT02sfWAk^lWy z%6>$+t)vj6=}K~B&pOgV!^m*Q)yteKfvi;B6~VAn!`+QzLTQXJ>^_H4Q3tr}j$llx zH9syTPQ+>2YLX|_X`JU9H72xIDO?b=FhNU;w;PuPhcL;Ub`;a1#`!}vF~eQ0lei*i zVU`1)EUt3WGl(MBl)iR)PO_C)pou}0xzBqKOMLA8j5~bmi}H8i2-kga)VS+A2#0c4L&o$T+JQ~1@V%bobv=PqsYm`ErSL@X1fI&qkfCFZW5#hj6E(s6hKU#4 zFnW1A7{W`T3|@0I7?b0MkcD@A&>4Ravhb0AgYEU7gfiIRA@eZ4amq~NyS#4Q3}I7B z?5}PW^yNyPf%0^Y|{DRK&7qqJXOr>sjH>`$7wtwx$|ELAKXya<(uQYeU`*cfCXt!=E*popOb zL8%5YyupGfUIYbc!J{BOco4x75rkqt^! z>CuwSLRjr@ql$KV%I4}7n}cpQb+oafc+8+*=U>- zQ4a;70B5-r-HoEi1n);(oM%=`$o(0iUAV|aEzY{=zbq7>%nw=yb2RlnTot2t%ie38 z)H9gpQ#TVS+~OChaining functions together# notice which functions get called when you change each widget. -

Total running time of the script: ( 0 minutes 0.054 seconds)

+

Total running time of the script: ( 0 minutes 0.048 seconds)

Download Python source code: chaining.py

diff --git a/generated_examples/applications/chaining_codeobj.pickle b/generated_examples/applications/chaining_codeobj.pickle index fe740e2233b7c348038e0f823d298440dc6d2e8d..7e6b08eeaf99bc9c9f4f3cb942328f6e712a5ab7 100644 GIT binary patch delta 1052 zcmYk4Z)j6j7{+~1ZqmdyO}i%bCTY_oxA~(>?$oYY=D#_VxxpyKQJm`tS{+=G4(4#depBzo=wf6m);e0ap zM!q#l4SLO*DJD|6WU;7M zOB48|Ax14&Y@8xDrfdQ9w|qz4oK%XSb*&%Y+wRe3LH(g7ruAYm?8UiokZFA!dzrRP zOh#-j+9^obcH>|q%(Ojt61>B-0XV2a2Qk1Dd`0&uEoh$ENyC82gCE#q`WTZ^2tS(? z8W$9myfh&wBe|%|X){%@Bq?~M!AZwC^-vW)bC_z_Yu-qw@sT-3(|BO^3CCGZD$StJ zQrEMbRGPz#r9k*B9wCIo@AjlYnBtTGaKP{xRWQOuqFfhn4>-!u{llI7wX&}vNIRqKxBQZ%nxh! zYAIc_h?|f?xotrT8Luoj)V0|S%ljneyanpPr_S@zc4K?N6~d6~q4fHyXtzsm8sc_) z2deE$^bV}@2F$HfXh_hLbzVwv+C}eUpS+dVP?opz3d(X6UT+JH;7|EQ%Hx1LfO)r* zj&RyUV>s#F%Ii7lR)lLDsz-s_2F;=4EkTfv#xIDVvzj`lNomS)2xf(qCdmJ430pC o#Tmu}Y4$S1uYrWL%{V$0lra>1OL}cZ+zrNY$#LSEIr_HgKUkncBme*a delta 1050 zcmYL|Uuau(6vumhx%t;LZPzAklG|iSZkwk6(yq=`*R58@Dur%E#W9c?LYC#`()?j} zRVr>}Zi7j~Nci3ts|ez-qqu1qzNzTbnA+h`DO2!4kol)CD!zz{=iU^3Ils?2_uPB# z{eI8Af8zd$T58yFda0C6XN?6TdCo{yrBbGtGpe2$uAVKFOHV8njH;tpKDD%%Gf;2s zM5VK}t=iJ4q;<7?=B$C3)aj|Z3VJ%bn9+3u52VxN!*TmX3Zv#w@Q3|NN?Nqz@X`?O zIYT(A1hF#cMk(&c7hNuV>ukq@L&kaMi*yhlx%v=sDRkJPyi2BOi#D7-p&nrzry2a} znxI*Z3g+DHG=~Lug646_Jw{LAefKaugYVtrbQ1pN6g`Utywr7ZV@W*WcWv+zQIQnR^?69ZBuj&n~{fwy3UD= zV>Ul+SY&nFKt}4P_v+tVxb=9;ejDt*q*MLLe5nl1^01}0ec zTHp}NUJE2KB)7Blj^GeWuLfiIFzBNS(>~I%7M!5xIVx7yGNwWb20}g-c`Eb}t>Aj7 z(f=~jJ{H|8N382tm{PQgL-GN-$}w)<-%{sSwA`$^v$zqRwbpLcC(|0%qASu{<`>+H zMKBq=Bi-Ch_PC0fd?B0X-$3Hotdog or not appif __name__ == "__main__": is_hotdog.show(run=True) -

Total running time of the script: ( 0 minutes 0.033 seconds)

+

Total running time of the script: ( 0 minutes 0.042 seconds)

Download Python source code: hotdog.py

diff --git a/generated_examples/applications/hotdog_codeobj.pickle b/generated_examples/applications/hotdog_codeobj.pickle index f4727db42e6c52a660c6a42ded24b775453b875c..72fe3a18ade74d0ce1631cbafd892384cc401344 100644 GIT binary patch delta 388 zcmXAl-z!6L7{+_f&d#=Ttk71LnY2xoZOQK3up}->>`s;+Sthnac4W#uImvoXDWxez zqDUzbH?Fzy4{*ExKndR+H&37EdEVZ7-)c*> ziq6VwP>JOmc8na~vB|RZi8QYr?Yxxw`RnlW&5^+<7v&HK$)7p3=Phg6YvlCgy zoL|TbjZk-avCJnW%rWOU+gt&DD9hNelX_R?w(AEwOnai-ax`EeT1#h#ti+^yKR zsoUd6MNls+UU|a&_V{opD1{?7sX^Nx3yR}}Yifwost>1vk~rgu+KUUJA)afExT2)> l;F>8dj$6)Z3ET+{*xkK-Nm=vZQBVTUmD-^D#r~m@`~%_nelh?6 delta 402 zcmZ9IJxBs^7{+<^JWuVw!pOpk(#lFDDd=Odh@wrJYLUZGRPgSEJcy#8tq&vRxq>JV zf*=S2AqWa9YK*p83)-66n)`b;wLI_ddB5O&%kHwf7>bBComputation times#

-

00:00.776 total execution time for generated_examples_applications files:

+

00:00.841 total execution time for generated_examples_applications files:

+-----------------------------------------------------------------------------------+-----------+--------+ -| pint_quantity (docs/examples/applications/pint_quantity.py) | 00:00.617 | 0.0 MB | +| pint_quantity (docs/examples/applications/pint_quantity.py) | 00:00.670 | 0.0 MB | +-----------------------------------------------------------------------------------+-----------+--------+ -| chaining (docs/examples/applications/chaining.py) | 00:00.054 | 0.0 MB | +| snells_law (docs/examples/applications/snells_law.py) | 00:00.050 | 0.0 MB | +-----------------------------------------------------------------------------------+-----------+--------+ -| snells_law (docs/examples/applications/snells_law.py) | 00:00.043 | 0.0 MB | +| chaining (docs/examples/applications/chaining.py) | 00:00.048 | 0.0 MB | +-----------------------------------------------------------------------------------+-----------+--------+ -| hotdog (docs/examples/applications/hotdog.py) | 00:00.033 | 0.0 MB | +| hotdog (docs/examples/applications/hotdog.py) | 00:00.042 | 0.0 MB | +-----------------------------------------------------------------------------------+-----------+--------+ -| callable (docs/examples/applications/callable.py) | 00:00.029 | 0.0 MB | +| callable (docs/examples/applications/callable.py) | 00:00.031 | 0.0 MB | +-----------------------------------------------------------------------------------+-----------+--------+ | values_dialog (docs/examples/applications/values_dialog.py) | 00:00.000 | 0.0 MB | +-----------------------------------------------------------------------------------+-----------+--------+

diff --git a/generated_examples/applications/pint_quantity.ipynb b/generated_examples/applications/pint_quantity.ipynb index 176ce23a4..b86e680b4 100644 --- a/generated_examples/applications/pint_quantity.ipynb +++ b/generated_examples/applications/pint_quantity.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/applications/pint_quantity/index.html b/generated_examples/applications/pint_quantity/index.html index 66d4ac214..4e093f2c0 100644 --- a/generated_examples/applications/pint_quantity/index.html +++ b/generated_examples/applications/pint_quantity/index.html @@ -2918,7 +2918,7 @@

Quantities with pintwidget.show(run=True) -

Total running time of the script: ( 0 minutes 0.617 seconds)

+

Total running time of the script: ( 0 minutes 0.670 seconds)

Download Python source code: pint_quantity.py

diff --git a/generated_examples/applications/pint_quantity_codeobj.pickle b/generated_examples/applications/pint_quantity_codeobj.pickle index 462f029c52a7ec4ab9cc8ffdad653f81dd690288..75f399559a0114b1dc80d796cca1d63f5287390d 100644 GIT binary patch delta 825 zcmXYv%WD%+6vmmH$z+mwruZO_YU9*e(lFXs#nuNErJzWaKtT{wVp}s)@@SomA&YL@ z2@wwLtxE_qI1*2WDQK>HlUHPWpSZKM;M$nb&%|*XP-VNWawcLgmbk+afyyrA;wE`#6 zm0fRsp;qy{fW3+x*lRfIU4N;owB5z(Qp?6;ZF)fePliRsfqq+OC1H=C_IC#RUq(su zkabjcC6-~+0ven?i5ghw2Es6mpl%6OOtyp^y9gOJA4!GX!^mzJ=Xs9NoeAV0ky%WO zFoU%N(^%iaK{$s=O|)lT~l(^>DoMgfr@=Vl*tEla0 z9UOjM71T*7%O+#HV3BhHs;G`+!!qgvDGznjkJ1>dp#GK)frm=(O?Pf{ z9)k|*cI-6mo*WdNJJ|k`GwhqLv9f#^ZR(!M^Z|&z%LAN7us)Ax*+l$INcZDuPIlO< z@i?sGG$C;o9U+loYq|-KxRYX(K1JTAq}j{FDLg@xH#D{3*H=1$qc|^kTnHn&@EV;} zrHsz1GQ@r=$3vpQ?|3%E2fs&lwEgUfN`r|6Z6YK(`F WbtEl$lGhwtPEy}VS`z)zzWoolRps3P delta 890 zcmXw$&1(}u7{=MW$!62dY&IIuCh12^DKW;_)>@&Bg<@$ztoVU~pb2RjJ8PT7nye+z z6!9jkm^yo`mx_vl?ZHzog?jcNc<|uIA5akV=1F{KGG6BWz0dQ`v$Hc>$*p8NJEpH% z3ybAOwoYrS?rk^Ka#N1CTC9{^$DFaNrG{0j&e~STchpL4!Co%A8=n&=onWUa;MV&M z9Iq4?t3EUg;(&N(10D%m04lbdcgQM)ZC&u>RuXmwXBKRgJ&}!NV|z^^-3uw9A6ia1HB_8W-9P!5O%TwV)2c zEm7laTQ#A8ysu_qUeqYNh*}xB&wm1_s7Kg=&x9ppeh<682vjAbes+bD$9CD#{$H$o zAL@6sJMw8<8gR6E+gff|)w)Y{`hb#+hsU6aF<<=W@IIR19xr`_?Qbo{z8Qq&wNohb z?v2(h>4$bm&>*gF193JQn3VK15EYb_eJ~J!O-xg|rchD3x>?IG;e}AT8FybH_v%r$ z-Ic=$PU#Q{R_)5YCO_aiVP~YpH@rt>MbD$MqW803`j{jhyeGVV5xkE~NgsO|cQ!*h(zqFAA3`IN wLMG21H~HDQ!_WQ)zxl*Wpt57~v+SV$*EEnwctWfRb~nuXW;m(x=d`o`0L!WT6#xJL diff --git a/generated_examples/applications/snells_law.ipynb b/generated_examples/applications/snells_law.ipynb index b84f1f3f4..4c6e342ac 100644 --- a/generated_examples/applications/snells_law.ipynb +++ b/generated_examples/applications/snells_law.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/applications/snells_law/index.html b/generated_examples/applications/snells_law/index.html index be2ab0a7a..e575ebe29 100644 --- a/generated_examples/applications/snells_law/index.html +++ b/generated_examples/applications/snells_law/index.html @@ -2932,7 +2932,7 @@

Snell's law demonstration using snells_law.show(run=True) -

Total running time of the script: ( 0 minutes 0.043 seconds)

+

Total running time of the script: ( 0 minutes 0.050 seconds)

Download Python source code: snells_law.py

diff --git a/generated_examples/applications/snells_law_codeobj.pickle b/generated_examples/applications/snells_law_codeobj.pickle index 147f025860b11757d7a2602c83bda9de38f0f4c6..18756ee71ffcd1945727bb5e002ac67cb0d9e63f 100644 GIT binary patch delta 507 zcmZXQO-lk%6oxrD&PN#~7$l`ZW(esN3bt({CVfB<2!c#QPL1GG%|< zPkc?)*Zj@-FP^(0f)gsr^|Jn#WZfsit=s99L;!=@nzM{qP8ClJaY3W|o(?jM4n z2%?2Vn|48;!A(Ki)_sPI=CQf_&gDMN=?ER6C8nuV#n4Ee#12W!q$;we5Yz3Mj8-ie zWm_xujOlZ=q^s3hov8gLSJI{3vaIU_o7^Z2V3ALOfG>Q28CHGghSENnVuCiw*yTkC zV~>wQ6nk72;+Wyb7Zc8y>B}jFlA(zi=UARtUR2g(+%8dhlanM(E>$Fns9ts2y?D

>IA-10ni=l zQA4or&^+yj1~%ykc4+|)ESiNQe5I4VWBZY7&W|lR45v8A%)psd$FRW;!UfhWeTh$u z2yOgil0cAV6L5n&>2us%a2Z!w4NBm*4_{)1kY(Xj36h*g_Q<_{? L?bOdsNJIPwy?K!p diff --git a/generated_examples/applications/values_dialog.ipynb b/generated_examples/applications/values_dialog.ipynb index 20883a3cf..b85030cf1 100644 --- a/generated_examples/applications/values_dialog.ipynb +++ b/generated_examples/applications/values_dialog.ipynb @@ -35,7 +35,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/basic_example.ipynb b/generated_examples/basic_example.ipynb index b2cffa54d..7dceca2d2 100644 --- a/generated_examples/basic_example.ipynb +++ b/generated_examples/basic_example.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/basic_example/index.html b/generated_examples/basic_example/index.html index 8a5892abd..eb9b4e71c 100644 --- a/generated_examples/basic_example/index.html +++ b/generated_examples/basic_example/index.html @@ -2913,7 +2913,7 @@

Basic exampleexample.changed.connect(print) example.show(run=True) -

Total running time of the script: ( 0 minutes 0.780 seconds)

+

Total running time of the script: ( 0 minutes 0.740 seconds)

Download Python source code: basic_example.py

diff --git a/generated_examples/basic_example_codeobj.pickle b/generated_examples/basic_example_codeobj.pickle index 9f20705fc619c633b2ad484eb2c103720165cf01..5978143a2130040b7956347838ee14a425df73d1 100644 GIT binary patch delta 339 zcmaDa@Lphoo-|KtMPhD2PO4sUMt=E}*eM#dQ#5*5@)C1Xr%VoH6z1$<%gs+I%>nY# z7!~<@cp$uZpz5NMDU&C%2v1xnJb4*o2BXMiex^J|>B)6WYK(G|d6|_bpJ2Mos0n86 zXXc$;%fvnTI`bDs>&X*YRVP1ZmYmGR%Ef30=2@{yGdhA<)vTh7Esf9=A=&P;V&qzOwUWq(Tgw61kqD^ zcpy^o#TofUB~yCXp$ew-aAX$8C+8#<7f+dN!J*G6Fu9i9m{D}{Ms^hmi45M(($pTF z)QZI1f}B)6px*K+u~RfA{+6E1#v(Maf^Xs@lZh9C8C56yv&&AN#B4Y@l3jT66()(v za~WkA^(Sv+Ql5O5@iL&Z`*)$nzz-|TUtp~DnIhw$pEY$-5!yRxd diff --git a/generated_examples/basic_widgets_demo.ipynb b/generated_examples/basic_widgets_demo.ipynb index 00bd5b8cc..3d6c0855c 100644 --- a/generated_examples/basic_widgets_demo.ipynb +++ b/generated_examples/basic_widgets_demo.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/basic_widgets_demo/index.html b/generated_examples/basic_widgets_demo/index.html index e27d321ec..526989f72 100644 --- a/generated_examples/basic_widgets_demo/index.html +++ b/generated_examples/basic_widgets_demo/index.html @@ -2900,7 +2900,7 @@

Basic widgets demo

Out:

-
<MainFunctionGui widget_demo(boolean=True, integer=1, spin_float=3.14, slider_float=43.5, slider_int=550, string='Text goes here', dropdown=<Medium.Glass: 1.52>, radio_option=2, date=datetime.date(1999, 12, 31), time=datetime.time(1, 30, 20), datetime=datetime.datetime(2024, 3, 5, 17, 38, 27, 444000), filename=PosixPath('/Users/runner'))>
+
<MainFunctionGui widget_demo(boolean=True, integer=1, spin_float=3.14, slider_float=43.5, slider_int=550, string='Text goes here', dropdown=<Medium.Glass: 1.52>, radio_option=2, date=datetime.date(1999, 12, 31), time=datetime.time(1, 30, 20), datetime=datetime.datetime(2024, 3, 5, 17, 57, 54, 926000), filename=PosixPath('/Users/runner'))>
 


-

Total running time of the script: ( 0 minutes 0.129 seconds)

+

Total running time of the script: ( 0 minutes 0.131 seconds)

Download Python source code: basic_widgets_demo.py

diff --git a/generated_examples/basic_widgets_demo_codeobj.pickle b/generated_examples/basic_widgets_demo_codeobj.pickle index f56119513354481d16ae5d7d7f5fe0b99fa7c8f6..97854edfddf8895b7c1dc557fa4983173e0e5b11 100644 GIT binary patch delta 501 zcmYk2!AlfT9LM>&vorJNJyX|RYFAO&8EwJXC5i}&I)x`SiolD-{*>o;Us zF4b$T=~ijARf>#7UzzC4ATsMq)o?+D*0O3Z1drqDFz$!}>Oxg`l)){!YMz&(8T#>N zG2Ji4i!k1~aD6a|YEfs^Z`2w=y;e@(^p3P5LtDur`+uP&x%8xn*9Pb!n&KW^!Z%T( z3LbTw&`rEg4Pv9?Hh!jZ*h}4~F?1WtG=Vi^ksjc;F+x-5F+JQ!f1w#gmuVJcxynz1 zTX}pk=jn+~rmaqDfb4?Wm%(>4jd#{DJwt^JW8HS?xu&mnA2l`QSq{7Q$T_?2&jmAc zVUWCZ9dDV7A1q666kVY<{<8kWV}o%pr-);vfs=*cS^UxLVbl@$==5S++n~4r delta 439 zcmXv~J4hRG9Og?d$=&@g^+BvATodum5FtjSKEOrj=1^&+gHU_~a^(bLmV`pV!9h_t zwAU|!A_|@Q5UZ0=DA=L2P>|BDT^)4NK?;IG|6b|xJ$^6veO}5-y(|pGOU0^Fohdto zTT!2==jQ7a8PbVL%av0P&l+R)0+ z;yz4X3L6>!xG!qoP8FFpdeFsDqaArxjCJ%g89KuQZih1*QJd+6y7?yD!rf4>`0ZzYbNzHpXu$ib&KzG z!9_j6uX;wZjXnO>P1#N0K&m{agkZC?MBJnd1j>K5FJ mO!;5rZp_pC)nxdKYxoOUeDmMh_|9#N;Ri2}Q-1|}wZdQ7V~{BT diff --git a/generated_examples/demo_widgets/change_label.ipynb b/generated_examples/demo_widgets/change_label.ipynb index 90ab1b11a..da5a54873 100644 --- a/generated_examples/demo_widgets/change_label.ipynb +++ b/generated_examples/demo_widgets/change_label.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/demo_widgets/change_label/index.html b/generated_examples/demo_widgets/change_label/index.html index 96b713d76..b75b47ec1 100644 --- a/generated_examples/demo_widgets/change_label/index.html +++ b/generated_examples/demo_widgets/change_label/index.html @@ -2914,7 +2914,7 @@

Custom text labels for widgetsexample.changed.connect(print) example.show(run=True)

-

Total running time of the script: ( 0 minutes 0.032 seconds)

+

Total running time of the script: ( 0 minutes 0.034 seconds)

Download Python source code: change_label.py

diff --git a/generated_examples/demo_widgets/change_label_codeobj.pickle b/generated_examples/demo_widgets/change_label_codeobj.pickle index 9f20705fc619c633b2ad484eb2c103720165cf01..5978143a2130040b7956347838ee14a425df73d1 100644 GIT binary patch delta 339 zcmaDa@Lphoo-|KtMPhD2PO4sUMt=E}*eM#dQ#5*5@)C1Xr%VoH6z1$<%gs+I%>nY# z7!~<@cp$uZpz5NMDU&C%2v1xnJb4*o2BXMiex^J|>B)6WYK(G|d6|_bpJ2Mos0n86 zXXc$;%fvnTI`bDs>&X*YRVP1ZmYmGR%Ef30=2@{yGdhA<)vTh7Esf9=A=&P;V&qzOwUWq(Tgw61kqD^ zcpy^o#TofUB~yCXp$ew-aAX$8C+8#<7f+dN!J*G6Fu9i9m{D}{Ms^hmi45M(($pTF z)QZI1f}B)6px*K+u~RfA{+6E1#v(Maf^Xs@lZh9C8C56yv&&AN#B4Y@l3jT66()(v za~WkA^(Sv+Ql5O5@iL&Z`*)$nzz-|TUtp~DnIhw$pEY$-5!yRxd diff --git a/generated_examples/demo_widgets/choices.ipynb b/generated_examples/demo_widgets/choices.ipynb index 75bb950f5..568d6f7b7 100644 --- a/generated_examples/demo_widgets/choices.ipynb +++ b/generated_examples/demo_widgets/choices.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/demo_widgets/choices/index.html b/generated_examples/demo_widgets/choices/index.html index 69f74e632..18fb34efc 100644 --- a/generated_examples/demo_widgets/choices/index.html +++ b/generated_examples/demo_widgets/choices/index.html @@ -2950,7 +2950,7 @@

Dropdown selection widget) container.show(run=True) -

Total running time of the script: ( 0 minutes 0.049 seconds)

+

Total running time of the script: ( 0 minutes 0.060 seconds)

Download Python source code: choices.py

diff --git a/generated_examples/demo_widgets/choices_codeobj.pickle b/generated_examples/demo_widgets/choices_codeobj.pickle index bf057428afff812b47813e53ea79039416c3eb41..5749ec80553164476563b83ec3e63995f9a0f826 100644 GIT binary patch delta 509 zcmXZYPiWI%7zXe?X_~ZKnpUwmU0XNWNvCb*KYG>65R{%ocTuv;WlhV{GTR`CgMvdG z6r_7Hk3$5}qu{|IcoB;1;us<*2zv0KOfQ1sMdsJ&<>U7~54`ZcUvfJ+xgB1c>B>h+ zTG^hfdaf~Twd`yD6@SUkcjUU|+I~m*R|&X{Id4HE5z}<7YTY!u(`jwRvpTBPG#9GP z7QaWIB@Q?uvpe!s-E+mHJddlx$grrUFvgG39t{3bCULT#$R$U+(_L-jG`Epu32$&N zP*IAZ%x&o)FG`(hDkNW#sY(yJ)!guN`tg7~qCJ q8?HtBO2y~HwM1Xb@e20yTYO&J{X${}<4o@v;Z~xIg3wvXGyVcA;ij$t delta 560 zcmY+BO=uHQ6oq@o`AafMrdm;>hRDQFHO5#J#agML7KA`S@CPh$nojekW)jV01hL8# zH&$lRa>kVix^d-BPz1MH>sDL{3W6e{2)a;lBfgog+#J61?%{IpyI+f+i=r>xnphOK z9}|zZJtv$92d{>Mf!H=3D-2fN0@>+Id9BD>Q6|tcXNN4sUScTyh2Fr=6flyxM(<;Kn^{XABKkl435D!M<6ATzKNM2}Wz1?@UAqyo zL?HJrU$EQFsOfh+&Q1#KH}d+l!2V)hZ<2%``ZQ@c-G7eO;7LED9M_E)SzS&9is{x{ bw%fx(@{u&NgZldLIFile dialog widgetuse_app().run() -

Total running time of the script: ( 0 minutes 0.105 seconds)

+

Total running time of the script: ( 0 minutes 0.084 seconds)

Download Python source code: file_dialog.py

diff --git a/generated_examples/demo_widgets/file_dialog_codeobj.pickle b/generated_examples/demo_widgets/file_dialog_codeobj.pickle index 5b2d7aa4ebf38452507c99ad7c9ce900e3ff6bf0..d271bb75fe02a7d88a96b76aaf13b38a17b850b0 100644 GIT binary patch literal 6587 zcmd^E%WD%s7_U;>)U>vTP*I^55n3n_1VJbiN{gX|(9%GqP+2ycF+0=ECf$c^6{R3T zg}rt4KM({#6a+yK1VIo4K@bG5UIee+oy|TbGnt)CnuCw#l1%$xtX4M+pgFK^+P;@vwkp5^l?A9d{((QW>Q8#3H=qF;P}>An-q!2e{&j!y4!+)R zsx{zyV^>|XNiVoCyzdRv>J`_(_a3#{V;fegz_IhnjR>vatG+iJA{DG_IarIu z`(6gxie{*`?LTm_t3Jpv)Q31sJx5{=S~ob9w?kHD5O!6`FAd4r9pCpzO{O zyWs-BR!|GmiOmL_-3BzP!Kfw(ESHSxS~I%|d@>FrNqbqf0ZzUahoOY?fd##BKG>J= zNu~Cr+P(;I*i#b2q0%``2w5gQ?W;0M4@nAV49Q|(g4ZB|MsJqP-nlmIV!eL;#!#a$qjT+wyZvH?n9%LS$e zlBh>pw!FMr)`BpXBzV+Ti8)2W8Idws5fNDR5&@5{f}6myAr3|u#G07GI;^+A=aVWR zbl4D6SO0t^U@3HH#Y~B^-qH9CW3{VgJePSmnoBITIl*;CTMA%e19}xmu zU)tB-|5r92lkj^hn@^;K1ZDH7lmPE>(w|9DscC;fC|#A!ml8a7`+G$=a%Jl#B7ERkxgDx-z;A7Qj!`=<< z{ccpUX#5cIEbbh!$&aMtS3xe5csbpZxyw?Fq7zVUj%{{QClTC8>QG+KFi49}a}d^k(Qb pk&j;hk{QS;r3TQTYD91I=M1RgSE{XV^U)q{l!(x%d$En1{|(HPotOXs literal 6584 zcmd^D%WD)d9ImMC>b7o`rQk&mVrfBE5Jf={N{gjpY3bq%(P4Hr-6YP=u9KNQe1PCZ zVGe@hRqziG1VIo4K@bE%5ClOG1i`ESfCrP^oyjIZqW*fL z8oKoNK$BuzREeX(_9KhHh9AUmdz3@Oa$K8`_)bU_;6Rj{4}H)Qh1)n2=3xO2CYW|m z>HRJ^csB&m@FH>nX(Hze@Jlq#awj<|J$y3sTD44vsQrpc?5W!|r!D3vA>i_0b~M98jSlgd64I2B!fH zg`Biw{lRJzc{P^RIENL}tj@Lin8L@BGSUWDYyxPToumw_-FepP5jD80;hAwVsq0cz zbrv2rC|hXfQBKH9?fG^7b=t$5qR1hgf3lpW3u}>4VD&Rt&O<2wBrku&n)4B$^OvnD zvuFi*=|suwM4iD1n{P8lLfJilr;P+u)x$X>s!;a=rxa(yz^=HU46cU2b3j^kp=*gP z*%gPCdB%VzEX|a2o^ytbf?U)QWcAA&Tvz~0z$b_nqbRVU&X}aPnMnU-K@9}Ut>%7llnU*%DcEf+!Iv*O8Ewu9yC&(U?X&4*G zI-l_J*Jqtijf6DT`OHW_^*O=kMpR+gUvSErtn;M-PhJ9FagLdFzSa?B^*0=BYMpQO z6gk4XF1Vp}zSmRa2p>4y%sM~n2(tPo4mPmP&zWdh_X|fV7HySve$_H${cj8nqW#?` zPWC@L1(T8kZLdbR0rZ&TQD^1H(2+8#dA2*_k-%mkOn(;OIR3-p;SUa@ugN{zE%ds%2g(eXHO7wn1>}F^?RckI<=yK%E()Cg z(Bbhup#$qOc|2;WmF@F*+*CvLjo|~PY+)806j*C9e0<1^Dy`l4h(I&4eSEA3M~-n^ zz#E!BKGBmU$C(frW?KL})srR1nHCsE8v%T(2S<)EE8u%?2k^X(Agh-Ju-T>npY27G zqg?0^K*T3``-Ys|Zzs3QG4=agB}8t}zTCo>g*cqbaLGZCZV0fQ%8$#3_Vo9k-+f@5 zrn#?c1Cs2I{(=Nan&3c4fMqwEe2Image widgetimage.scale_widget_to_image_size() image.show(run=True) -

Total running time of the script: ( 0 minutes 0.037 seconds)

+

Total running time of the script: ( 0 minutes 0.038 seconds)

Download Python source code: image.py

diff --git a/generated_examples/demo_widgets/image_codeobj.pickle b/generated_examples/demo_widgets/image_codeobj.pickle index 5fad5dff39ec98170c14ec6710e929f7df979853..6e432e839fcbd5a0d748f217b9f58e0f5641202e 100644 GIT binary patch delta 258 zcmew+^i61jo+@i*Zen`sl-Ma6wNo^DSn?8cQ>XN>dV&Re*mCnzN^?@DOb%ogo>*Wy zIh<3RQDE{Prk#wElQ*)MPJYd-$tVM6d9g?{%7a<6SwtC?fGj6Q)ycP54JNCwDl=+; zSs*pqU=~P?9*||rXgFDd%|^^5gSWFZwTBDr7QNz({Bn?kCe9a~+{R=$aj6WW?c|k= z@)I8(XY>FvbQrxSuVs>&{DJWaW7OoUOlq955dEy4lleFuC(mP(XH1*CkL@~RA&``s eyn&sUv1IZ-_E(I}lUH&mGPX@V&EddQss{i%7*{L+ delta 272 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 diff --git a/generated_examples/demo_widgets/images/mkd_glr_file_dialog_002.png b/generated_examples/demo_widgets/images/mkd_glr_file_dialog_002.png index a39fe0703dbaf2f11f9c0c81ec4b650c7de31664..4ab55982815e3c689bf00d3539957d2af9c2e04e 100644 GIT binary patch literal 4436 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 IIoc}hKUd{g)&Kwi literal 3784 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 literal 4436 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 IIoc}hKUd{g)&Kwi diff --git a/generated_examples/demo_widgets/images/thumb/mkd_glr_file_dialog_thumb.png b/generated_examples/demo_widgets/images/thumb/mkd_glr_file_dialog_thumb.png index 151a026aecf0df48554d3cb14676eb5eabeea6aa..a575c585dc34f0d85951bd1b2ed8c1a09301a554 100644 GIT binary patch literal 8605 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 G=sy6Kvw5fh diff --git a/generated_examples/demo_widgets/log_slider.ipynb b/generated_examples/demo_widgets/log_slider.ipynb index e9893eb61..04df09c48 100644 --- a/generated_examples/demo_widgets/log_slider.ipynb +++ b/generated_examples/demo_widgets/log_slider.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/demo_widgets/log_slider_codeobj.pickle b/generated_examples/demo_widgets/log_slider_codeobj.pickle index 1f0381d6c88496d29d6d25b2faf577b6142c6c37..0508f407cc65ebbd0801569213d327ad49026500 100644 GIT binary patch delta 291 zcmeAX=nSX+!sswrk5zSYAB!@hGnjRqMViqK%#vaeVao6XGL0C0 zCMU9*Gx`Hb<;ikye_QT#}ieHzk9!ha;&pGp8gouXsuZcSdyv&%_2LjykZ` GQau1GI#*r* delta 238 zcmeAX=n2c8bPCbN9(l*cAl$Gk7{nQ+rr5^9o8!fD)7Uvnw!* zWbjO^xyGnCxsF|Sasgu?qsHVzjB1S9lLMKQC-X2}W;6q{ezEW}T22;Z{>SJsS%AfZ z(HlsrPOf8-X7mHI_OpmG27*~2l_8TISd}MFU=?8u2eOPAqb8TI8ZgFAUdpP&m@xSg zs}W=JWL7pk#fn#A7|5HESmgk%m4rY diff --git a/generated_examples/demo_widgets/login.ipynb b/generated_examples/demo_widgets/login.ipynb index c2bfe1582..309e22fa9 100644 --- a/generated_examples/demo_widgets/login.ipynb +++ b/generated_examples/demo_widgets/login.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/demo_widgets/login/index.html b/generated_examples/demo_widgets/login/index.html index 38d0f0d2e..6e41b1466 100644 --- a/generated_examples/demo_widgets/login/index.html +++ b/generated_examples/demo_widgets/login/index.html @@ -2917,7 +2917,7 @@

Password loginlogin.show(run=True) -

Total running time of the script: ( 0 minutes 0.035 seconds)

+

Total running time of the script: ( 0 minutes 0.033 seconds)

Download Python source code: login.py

diff --git a/generated_examples/demo_widgets/mg_execution_times/index.html b/generated_examples/demo_widgets/mg_execution_times/index.html index ed5299b1e..3a736fff5 100644 --- a/generated_examples/demo_widgets/mg_execution_times/index.html +++ b/generated_examples/demo_widgets/mg_execution_times/index.html @@ -2862,27 +2862,27 @@

Computation times#

-

00:00.439 total execution time for generated_examples_demo_widgets files:

+

00:00.424 total execution time for generated_examples_demo_widgets files:

+--------------------------------------------------------------------------------+-----------+--------+ -| file_dialog (docs/examples/demo_widgets/file_dialog.py) | 00:00.105 | 0.0 MB | +| file_dialog (docs/examples/demo_widgets/file_dialog.py) | 00:00.084 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ -| choices (docs/examples/demo_widgets/choices.py) | 00:00.049 | 0.0 MB | +| choices (docs/examples/demo_widgets/choices.py) | 00:00.060 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ -| range_slider (docs/examples/demo_widgets/range_slider.py) | 00:00.048 | 0.0 MB | +| range_slider (docs/examples/demo_widgets/range_slider.py) | 00:00.045 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ -| table (docs/examples/demo_widgets/table.py) | 00:00.040 | 0.0 MB | +| table (docs/examples/demo_widgets/table.py) | 00:00.038 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ -| image (docs/examples/demo_widgets/image.py) | 00:00.037 | 0.0 MB | +| image (docs/examples/demo_widgets/image.py) | 00:00.038 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ -| login (docs/examples/demo_widgets/login.py) | 00:00.035 | 0.0 MB | +| change_label (docs/examples/demo_widgets/change_label.py) | 00:00.034 | 0.0 MB | ++--------------------------------------------------------------------------------+-----------+--------+ +| login (docs/examples/demo_widgets/login.py) | 00:00.033 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ | selection (docs/examples/demo_widgets/selection.py) | 00:00.032 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ | log_slider (docs/examples/demo_widgets/log_slider.py) | 00:00.032 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ -| change_label (docs/examples/demo_widgets/change_label.py) | 00:00.032 | 0.0 MB | -+--------------------------------------------------------------------------------+-----------+--------+ -| optional (docs/examples/demo_widgets/optional.py) | 00:00.030 | 0.0 MB | +| optional (docs/examples/demo_widgets/optional.py) | 00:00.031 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+

diff --git a/generated_examples/demo_widgets/optional.ipynb b/generated_examples/demo_widgets/optional.ipynb index dc2b526e3..3eba91c39 100644 --- a/generated_examples/demo_widgets/optional.ipynb +++ b/generated_examples/demo_widgets/optional.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/demo_widgets/optional/index.html b/generated_examples/demo_widgets/optional/index.html index fc595ada5..2e87929dc 100644 --- a/generated_examples/demo_widgets/optional/index.html +++ b/generated_examples/demo_widgets/optional/index.html @@ -2915,7 +2915,7 @@

Optional user choicef.show(run=True) -

Total running time of the script: ( 0 minutes 0.030 seconds)

+

Total running time of the script: ( 0 minutes 0.031 seconds)

Download Python source code: optional.py

diff --git a/generated_examples/demo_widgets/range_slider.ipynb b/generated_examples/demo_widgets/range_slider.ipynb index 0640c46ff..a7c298a59 100644 --- a/generated_examples/demo_widgets/range_slider.ipynb +++ b/generated_examples/demo_widgets/range_slider.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/demo_widgets/range_slider/index.html b/generated_examples/demo_widgets/range_slider/index.html index 0cd702ec6..cbc2d32b5 100644 --- a/generated_examples/demo_widgets/range_slider/index.html +++ b/generated_examples/demo_widgets/range_slider/index.html @@ -2914,7 +2914,7 @@

Range slider widgetfunc.show(run=True) -

Total running time of the script: ( 0 minutes 0.048 seconds)

+

Total running time of the script: ( 0 minutes 0.045 seconds)

Download Python source code: range_slider.py

diff --git a/generated_examples/demo_widgets/selection.ipynb b/generated_examples/demo_widgets/selection.ipynb index ad42886e2..ccf3e709d 100644 --- a/generated_examples/demo_widgets/selection.ipynb +++ b/generated_examples/demo_widgets/selection.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/demo_widgets/selection_codeobj.pickle b/generated_examples/demo_widgets/selection_codeobj.pickle index dc22eb0c9905c4d7c8afcfde4d6d00dc736291d3..18e9b4ac237979f302007873f8d48ed547043b45 100644 GIT binary patch delta 439 zcmXYtKTE?v7>7yTGzpqok%+aeL#)+OYei6Ta1#{4A{2yzXi5K=M4CiQBUtbQ2pNob z;9_^bfTQjX4z7aqV>k%KH`grpJn!#*#~n9J4O0)5nr!Qa)iQjGp3&kREe3+4+Z`In z7rxW#S*}9^(RSN@H_Dp6)$Li1M+0S?H9XV3?oo3hkS(v#>gt|H$*Z&|rcCAD?}Te} zk6fC_!c5qo;?2qMOXZaCZ-G!KMpA;DsSr)djss?CE(v)|pSUGhM!s_f7p)qpLY6f7 z`FI-ev#`PTH4>fKM1O-c8S&fLh^z{g*ao~xUI6dLya0RHbcH-VD-ZjzAMhE$JY>TT z9L3?Mkc4COA7Kk>j2fwn({O^`Ph`kQP@&Ge1gFUFM2-|h70#KLK}YV2zJqkHk zH{QjgpTUdZXYg9@Qt;y4Ng5C@`+GC*Ewjw_WBu5@k{&VIrIudP)TUyQM$0{QGuLj$ z;moq3y1lnV*x`*v&8}ndA;+BPuqa{nvguNWOGF$|w@TG|*|J(bto1!e22&w^O0_7#wFqz{Dkn=fBU$_*k2l|T}h0US<|H5r-njx9KhLW)3>m}Gl zK8KWOkw|woE`wV$-+2Wp$RBzRSpg!uA>H%@i_7C8J8oGzZ(X0@p|OqYZmv104>rfyo^g0G0w MyPXo-{#9G~1+TM>rvLx| diff --git a/generated_examples/demo_widgets/table.ipynb b/generated_examples/demo_widgets/table.ipynb index e5732040b..7d624d1ec 100644 --- a/generated_examples/demo_widgets/table.ipynb +++ b/generated_examples/demo_widgets/table.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/demo_widgets/table/index.html b/generated_examples/demo_widgets/table/index.html index e6e307ff6..ce09b1325 100644 --- a/generated_examples/demo_widgets/table/index.html +++ b/generated_examples/demo_widgets/table/index.html @@ -2898,7 +2898,7 @@

Table widgettable

Out:

-
Table(shape=(6, 3) at 0x1389c54c0)
+
Table(shape=(6, 3) at 0x13360bf20)
 


-

Total running time of the script: ( 0 minutes 0.040 seconds)

+

Total running time of the script: ( 0 minutes 0.038 seconds)

Download Python source code: table.py

diff --git a/generated_examples/demo_widgets/table_codeobj.pickle b/generated_examples/demo_widgets/table_codeobj.pickle index 5bb074afc7a1592fd04befe5b329937e9c496495..526c3741775da55835a09f42d28167377c432fd6 100644 GIT binary patch literal 15910 zcmd5@Yp5Mp6;5kz?&I8ZAGtU8n%EkNRw97|#X_K<6e2BG8>2~^)@mFl=S=R*aL%0L zdF0`vwWX!CPJPg0!5jsi=D%`?1zp`!VPK zF@Hkltnd5wT6^~XX3gw;Y37^n_~5SmPg-ks+wGt^jJnBSoYqeCTR}f)eJE-U#}AI* zcXE61-QbCkq>7mA%T&qE9|NY)6xc9yr_$a?g zkNdq|lx&M!mzCww@Xt20Z{#F(p zq%(yD6#l`s^_ko{#w-J^U061D$x!(wlu&T{eYP0td_L4huiGo_jtzG{A8vka2SbJ| zm4^-CVCc8YIayYnEK8z-k%f1fdGxzRc()lzB^%yr#()g(m$7@1FO^AZcSvbV4_HYI z8GhXgCX;;73IlmQq=X|+D)S_kJh2UkoqsRQg4gM{rEZNoR4J$!)OTdmLTOO8>I;7g zAJKvhRsWtAL{|GzZ8)g%V=}D9okm~Y@Ns=OuHz46DBDl@qcz_-h`9@&G$Jtn4`uXx z;WCDC|5z7{S$`@67lp?dh@UaUWA0zb*t&EW1NpB^0L=cIEI8mzO3NSma@Q{VlleZD)(k;)jTb<;+AWww>Q)riSpkT$XD~^u znE;r50|d*?!6dNXg25VBfOzJ2ynir>9JGP3%Apbvq;=Mfd(klHc;};lzl~y#=S%tH zIWw-#;B@wbWwY0}9O9{oU?gwcBQTlCae#ZbAv5WBFZ_RHabsZ1h%FY4#I&ZXu zuC(nq0-=j#wlKZkrhlv(hyq$=T?eF<=%(AhymsFp*rv@=p@rx_-CB9+yWA5xIY7dLA3-Px~l%FoQqd|`92hDE3l^IY8%znt8 z0|4-00o=@^o065l~f#f8+!O+5ZGUHjoc0 z1<>xb(g}a&%4Nv@=dK)N0e zN+VQawbLW5@b@+j!?ZkS!;;hSybT4W;RO)A%neaVlB)lURunG$O8~J~@j;8!%Pv5y z_6h*i3ooYH5&WHwgu6 zBhE+5gKCPwRXN0AIE|>I*6$5dkWtl$N5<4Z6)u9%C1`9}A+$T9Ff)5dotJ{(*H)D-1cp}6kf1tJU5oTku0Xe{*@kebOIX$lny!~#zMfjMqN zQ)mDzmU$Y;%nR?CLI;Ae&@(`2ip@Sdma?yC!4wf4jWOOZlHqRy-(t0_h;-%+AbGTkK zhvhp_{xcho{-de+1Dux7d8zWF{8}ckaQ{$dTA1_!#Y9hKD^VP~&&GePNNK3d-zrj(#rb
TIiKrpmTqCSKV$N#Lz zfp?vM0sIE>!iOrG_06JD)=$J*-vyI!=HZnB$hP^@?Wz&5$NJFbc=ozYnL zT>$xZVfT*0?{9xF z1Po$NNyVaOl2NC3i5Yv`5Mm31UOO7{Z;FM9(O*H|Ut;{UJc4sR`(J5th~?3l;_40z z9P>~Mmwd$LzKsdM;=K+O2OPl>BX@OaL$k`qLJR1(v#BYmD#aghNETG*qX2-9>WBhq zcXrVc#~*iN(pMtB$&G@b%5y7bOKP1V(D*ylh literal 15901 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 L`N0et3~T=dgeJUo diff --git a/generated_examples/generated_examples_jupyter.zip b/generated_examples/generated_examples_jupyter.zip index 59b8c04f91fab0635c23745e8b7267e60c6cb250..e0f0cd27acea9e5d2208185d4daa0eb842895b4a 100644 GIT binary patch delta 1177 zcmY+CTS!z<6o${rnVP~enVC$=P`pfuiYR1`Gjq<2PFk2c8FYaNbd-{Wn1{qJQV$A2 zqNT#JUJ~&^yp*!RLufu^(HLb#iW!7GC`w>-0RxF>ujAQqI&dELzy5XEYk$kl=H+Jd z-e75z$sy6_Zm&Ikzpf_m&Lm0n+wq(W;@FFUTwo!ni-MfaDyL#2TgPzZd&DY9^v6rs z6(XYVN3dD=8S)^)u1&-99hhocw(C&cPO-OWBtwr zv%%LlzyBed&K%lq&~C3~{9;e?#zZdl_;hMjX5(^=o*U!k+Q$nUyWG+IhS8m)VLQ7S zh>bQ>8R^RX$vy-dLd4Mj#DQ{ubX#p{z6eNwu|)7jNF7H)Z;V9>fC z`73MfeI|BL%ze_eg)-JXU`x_{0j{l--<@PXUJmH<*{I%3c7K9tha}OTB;lw6$t-qm zMqHtUTLx1Wg3P&?mZp~?EjI+0)J_wG#B4{nxTu;oRM`s8{}UsxkEx|`@J64`PR{b4 zroa&2E&VBygnmDyYLux{i4YKbA!lFHomRCX6~+ZHBz~!0?N%!@pj~W>#C%_L)(47P% z{t-?>5lh^lXn6!7wz+u~fgjGhc|YnvxZyqz6lx~|4bOY@7=eYu9yq)i<4EC#2YlLz zV8TML9wUsf-K*yjKse{+b5aLF2a{w7Xx#}Kte5#@Gz;N^Oy-jbQ1G`5M=b&oEK~G6 zf&=d<{I-GvTv7Pcf&k3%@facUJ|E7 LjGho3g>d{Y(7c-3 delta 1177 zcmY+CTS!z<6o&WCIpY*g$jqQaSxV|qq?PlajdNEU3-LBVS%hFFVOcOQMiE+IDKRNH z!ct!npTr9(+ZxIe!o&6q@)GlOwLqi9oH>scMU#4P4JT9wvmUE9y}@kb+7T6LQ_nsr$gC6!i_ zI^N61Q+hY6wBp#&@9c5{?EAl&Z?P zi*LTNS4Gt#13NXAmJBaTge*&P#@%BN)V)mpwBKa?r^Wcd{)n;VP@?LTdK|$KCD+c`lFqlzdEc_Iz`RAPa9-`8!zKjTEXv$ zPb}E^RLo$W`(9tqC}geOh6Keo%Qfd-2`py#ndNPAvQi4Q4{cvAghLuyE_y>z%K!K)?9$WG4Wc!%Aepv}$y76*(RzhYm%U0A P+$4;M7_JaZS+w{cI;Ogf diff --git a/generated_examples/generated_examples_python.zip b/generated_examples/generated_examples_python.zip index e1d712e2f53cb2c871190467c2703692a511407a..d410c13b75ad0b4fa0fb90c6d29978c75f307e98 100644 GIT binary patch delta 498 zcmXAlKS%;$7{OgF!fDy!d!7k3$&Lk9OV3cp8;PjkFmf+rAyuY zVC0YolW5haz5vNr1Av!m3}6yN>IRY#BVadT4D4$VI%+|%gBq;cRdI=s)y8xq*0H985MdJFfyI***sf; zodd*QqHzFhWSW)&Sbc}i4zRqFUNczVapPXFe3)r4m|kr*1x!0yTwwv3BX0XZ97O*N z;bdXD(zBT*GD8}~&ntPw3ZkQ`EZLZ@^=zKnFj;}=de3I9h2K~}w9+y*Rxp3HG??$c z{yQUx@34`N8AJzcc?#y6Z{ufSI@2@RW0wsu1SYrbas*K)cXPn=79wc8#|b1?zQ+aVjLCcVI0AW-_PT<^-1mYwle_kMfTXVMbq4Vy_j!P*Q#%A!l6wd&xBE~C04~kkng9R* diff --git a/generated_examples/images/mkd_glr_basic_widgets_demo_001.png b/generated_examples/images/mkd_glr_basic_widgets_demo_001.png index 027a145d02ad4242778cc1d4c81e3b1d7a863ad4..f377e472843af9d209d6a1a608023d53cf758d40 100644 GIT binary patch delta 12034 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 RO^yQB5lwxK9JNb#{ts7>jw}EG diff --git a/generated_examples/images/thumb/mkd_glr_basic_widgets_demo_thumb.png b/generated_examples/images/thumb/mkd_glr_basic_widgets_demo_thumb.png index fa7177e29d32c68dea77c96306d0ed2a727129cc..fe9587b1df4b3aa356cdf17a9d63b55bb3596648 100644 GIT binary patch literal 25413 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 literal 25432 zcmaI82RPPm8$T?mjIw7UD^!vZNp@zTR6-d=X0mriLUux#NocCbC_6<~Wmh7SBqUj7 zWc@!^&-=XZ`ya>uIgXy=hnxF*f4|pto}YDIkw^5kHqmaTrJ$hLq@%5Vl!9W-Rs7?m zUXSm%ncniHps?Diqpo_~=f-%Sw-2l5%8RMFw=EwWWvfK49-++gws+&3jk8gvYb>?yY%k!C%!E=dOvgXQD5Ry7iLnSQe_Mk z6rha2*DmVn6ioQ~N<;^KzJ-hCDuYzz{ZT&6{&lKypVcWMRhVx%e3^YcFB2Is7}0z? zaip#1Tql*PTyO*h^BJL&r#PLROJ;g(xOb^?={Qs=-oNxF*Y%AA!?4H9TCLB_?Vdb3 z%+jLxTXK@?na`Z1>E%sL-rN0P_BE9ub?B{a6seMo6IXrDWQ2Ub7@95mZFsoIv0ExT zJ6j@EmqI%swA)eBV8wg+mME=F5m#c9y1o7Onc-F~1J=P=7YPH_bD}t*Ur$~rw*+hKAIMx_4rDuPlAW6y_4@U}qeqWM#Knnh z+qSN{zxCPqPfv`+JjOn3GD+%wdXB?9KlyXjg~2HwQBhG916EpE+WQY53hv#@@$mgY z0|Tb_@8AC(XV$V^4A9!ptxWH}{)d!-sMcl`|>IK}vY#wnIr0_8mfZ4`;TdNLqcY@ZMeW z*>7iLWTZd@bq$T0#~BSivkexEyz*?k@|!fz)=Y%g1X$FxqDg4vQ=p@roLX& zRGi~nS6j=#$@s-L)_6bHaC?bUUhRXc(M4dC=N= zTiV?$QQE8{5uu?}Qqs~~vW}d|=6>79y7F!N$~}LNc5X09GB9L&_&!QV$5@R0xS?Vr zJKd!=uE;la)Mt%6EFa1D|4f)4+%OrQB@y6y?nt|*OWlaEb=#iUSFhA7&38-Nwg~a_ z2h*?!GqSPO?aZ&dlr3uN)opG3_=Nd|aT&^B3fl}%cHB^*ZQERDyKQHFJj|DJ{;aTm z)8k_U$zHIwQ4Pwo{AH>nwfQpSRX}@H&NIcyiY# zAFrnwoBM-owVEC`H~FO3Th#lNm3oiuG1p1BYRy&MA6I9o+U2P$%o40ZVUiTveJnRO z+di#5fx5N4!;=R;?{nI~$4Z+uCXXGU*LhWl2LETxW!9xZ!E|MNd~Aso%bMG3_Z!Q5 z(@;Ac`7G4QdTq9%&-%TNyTb;vJApz%I?TbUb{qm1Jsh*?c2bUBG`XBtu-NLAuyP^O zE2j02fDeiQpTI?R(TopMSG0x1w;vW``YXdmA41KimQGW0mC~~C1I>Yi7miWA(L4if zC>K4URP$<2Z1Q#OLxl82MW`Rr{JmrUTh}4uG}FpQjhjzfRH+!V^is}#G~88Gbg)M3 zT%%uO>EVQ-4?^*l>n?~0wzEnV+2pHVQdEgCQ`72kes;6l(P{WR>y^vYd`vr-Z8e|H zpXzKI-nO2rr_bIr)=$y=xM3aFxMSBi%avW3%C9(1`M+Cu`!UB-`(QEmT$mdFW^Qg8 zDoTL}bqOrI;}V>&&Ppxc-igh-M{n$^(M$r>h&=s6-GlzuTo;r3ci$^4Oz2g9C_3tq}EYv0;9nI;w$^M2z zr31I^H|y!?-Os(8>s5JCWDAdBSNk3wR1tS~md<<1DtwHmUtU`0|L47t=Dv&C=XB^+ z1yAxZ30EfgzlvZ|*U~CF*Cj4^8dWM5Eh36+xXLL_hjZt;p9kz$yf7=YYgg>$%j;#G zdbR!i6~vRHV`4U=Ujbv1ms=6d(Xe*9?M zB0nZ3dB2B7XO(B-2y0kJ$HDc#x4w8^y}I_(v-5)$6VC^)9n+6&%rhPcLPL;95X#Ek zfhs(lbjoQUui{s>_r&LG$;s~ZT((DyjI>aq@7%eg@aNsJ+qZ8|w(Os9nW&nZ{#n#2 zpu@av+cvVJQ2A!+xt$reZf!+jiaJc~)vH%7 zV~aS)mU=kDn-?F&3bljWO56&im3b=%2M3?OqxZ`G{&;A>8sQORuW9H3sx63G;H_m(~hu{O-Ge7G<2=#JA3x*)%f_ADC{~qI$5}5 zXmvB6FHB7JdG|9>Q)wSQEV6xjWF(77M|Dupm!Ocz^X)qrjWRPb#oov{(tjP)yIr3~ zLv^5DBjm3AyZ7%S+3l!Ul7pDE6NKE{+)z46|4M8MeKRD0qEukjFx_pN8GrqH9cq1w zv@LzQ?0JEmJEITnuDa$q_JN5uOd`G6)U}Qce@fD}Wy{HvC$;tUg%uU6nr&R{(=PW< zI490A_uLE(6>E~)LO;vOKK&(xA$v@IVPWBIn#`M&HvW@*@rTY1j=!K!isd+YiZ(ab zQYw`?>}39r8s%3mXGDs+W4gv7dKxo zEc?F=v|P{j>)?;Ev9g8l>8TQDDAAMe=lZoBOcLOBZV)biB5+)kwP#{=?bFSdUfyD| z6Vmz05H!E`)H6qZC8e7;6)$}Kni+dRubnvBPb$G zZ{jd6Gv}j#I)egYU|_JpUy*Uw)hqhND*Aloc_prg27~tS6n^!XefQ(tLUvo^UyGa0 z?UN&00{zQa9GZhaNcUaVnd>;R`;64nn{L?NHbvd{J+`Y0w^NS3xZ+87yGn=oou5!{ z`l(i#uN{T%ot{rbukx;ymA30yO%S~-y>+Q~L919rUbdZ*sV64yz@-BsqhA!+)kJdE zrhWL!Fnf4VT-;nRlQe>k-&PiGMvS4e{2zjWBB{01i&a9s_}Sw!IA_Q2_IT&|`fOB> za1^*meO{cEmTBYqI+|}(j4dONa(@IqY&np{n0EI}fpL#7U04o3rMAenH`9T44lvB7 zJb8A|f>|jQDC$|$BF(r6=f?7<-Dt#dg;wj&G1ZQR49|KzXQ|jvr=bDKE?hBW{+N%-hBDJgN6aC((01? zheswMeNGJyPc5;Wf2}o1dhqb!;L75J?egD03Nvq|QT423(__2lr!J&4+mPa`qtm21 z!@hjfsU-c*q2!|`CT0EO<#|OH=A0;lFS?#WZ3OyL6vmQ{ovgcDJ3!FW240_wE6a;T zHqD#Aw`MvY7y217lpIz|>VM-|DYA14t=}{@Hr@(aU2*IyXG68YM;dI1yN5DTYAQZG zGxH!f7u`wfObwOb)k;9SpWQ{_*RHVwRUI+Be)q00`7oB2mYm9g3UzgL{&RiaXKige z^DUHb`hMpEd@UWmc_AVyO8)EC=h>pHY;3MwX5R71$qjV7D_`WqDIK)25eC#%n0m!h zxw^9GkE)4!*4EbcVkp_7<(6v5e1r0eYfRi-7lkku4?hLoz~wOu_s_n=21k$9M6vDc zxzHJEr9yR;TJVijV09*!v<<1>uV25WULUfw&>Hl;=Uo0!;$bBKp=XZWY9~&x1MAZJ z`uZL>G&C?WYA`f1vpzfFS!Rl^YgPGeAbhK^tZY(L6fL&nn#slG%E=l!Q}<>W&9U!x z8>(xqq)U3;=t954)8w?Er&xNI>6UXwa zdE*)mn49xb?Ay1`6s+N+qwHH7>HeTqMXa)Pr*fUQJy9yTxgBk7DrROphK7dky1I^? zI&}yw3E%`DcdAU20HY&(jC|-Z=km%fYecgbc#WT=rK2;c@Y?kzdAEq5;99*-G*8VT zHNDQ+{i7Q~RQ;8<=H`B#Ta1j2)#&m}+I6ZP%^DE8%zc=ww6BAMG+}Csv3gsYTM@6|t z{Q10Px%Y%VmgRwP`Z}AU_-ohHS67x}RT5HCwDBM9o*7vO!V}WcUT@ml`vSMHCC{uP zMfUt=0_y=sc+D!jwxJ&$JFIve=;_GGlYYn705uwznKc*Ncg}ZJuW0!C?!&9BTW;(l zh(ISHCT${U;f+O#yyp&Ve?b7Qn3xzVAEB_pT?&JFw{Beom&yP~BGAI7g>NftGs3ZaKmQDT)} zddVl8NJA(>>JibJEze`wxE`z3>P^zFpS@*?m6Zy9e}2?4 zC@-mC6#`(8Z$5e?W>ucwI*c{f`Se_upr1w7__`2PJaeop&CWeGtv8!dSOEC!JMT)m ze8CdRjhXlu9N}2WlTOXY^Ksy=yOAMVTtmp4p&yf6`krPD6LTzEx1u<|M7zt~fhLZ! zc-Q`ZZd9G6v0 zMoiC|)Y}w|C$DcfE5-G|HMDV?%^8|YF13rRLTXx7uijBp)j3La+4-)PUgXv}A8d3T{y=tb^Dogc=1 zD&={{J|EF?nov?+{8(JPN7ngs44ySB%^HT;g|HA+xi_kEe{@AzYn)0Zl26+7d-4{F zagW*pXV8ZqxScf`DzKU!bV({z7Yi0|g)I=Yy4Y_T@aKKyOw0aW|Cwg+X*@mm;g&mS zdpG=kJfH|wL%I0ihu6-D)y!`tZ`>vC(!Z^$uu@*@iika*29&(Wrx!yV~sH~hh zP#eyz@gVSuP_Q!9grlLT<5fw|6kfha6^X_NT>5{vXsTQlio_=b1!Oqst(0K=_`}*~ ztY=NW1OK9GIaM!vp{3M3%zqx$H8unm^8I(`VG&kZfDxZxWy2qzo#&3qc4^n(kaTz_ z`u%Nc?T_~lx%N73NfbFO%u4&T_A^aGG+3#2lJ)C1Z%m&1?@LWh1%)9p#qr~;z=dF$ zAM(r&K@1|z0R_9TQ0n>0-*bO|j~?iM9zggRS}yR7)Y(Qx?1|L<-r^`Zq}Ui31dF{P z&6t&gL)z=7F=Q#yOGJ0+!2}kY0cPcyXTlo9qWB61YCOGbKT_^gtWYb)P6v77%ko_RJ*_xi(Wsh|{=he20@|p} zz%;ryC{LJ>S(La6+j9!T>IRF z4qV=tWlZ(5eQRj@wLjY3^SzqAPCx4k?tG>VgQlNdS5oEeh8kW*O zA5MYZId&I@jejahjE`3Z<;F^Q;qcV0&$CO??VGj&F9S;Q?_YiC205Bs_5((FrcL=l z%jd+)zA=;g@9HYq-rj!P$mp1mQ-86O_3BcE5EkS{rlC##I?nNwsSmMO!5qpiUO2jbWz5Xi; z!;ehMnC+Ic)>E!Q?fY14&jJQ%IanX7xxF1E)ot`naz}}?g_W*gugGKj%}SYZDtxD7 zqHo{1LvRJz5XX+OjD2`)g?@L#?e%s|wO94^^%kaCM>_d$si|C-f2YjGaz#|c+S*#V zf&q)D{#$4ZyTYxfhjsv8UG)C!8?KiwTL96++H2|vsq(wwT!l6Ed{r>GCtbe2N;+nOy=gRETG_ikmbajQ~<oMX2L_`@cW;lYd+b;EzUNzA-5#k|UoU+3tnOx?k+U$L2MEDNsQ zxZ(ezp}4sCiB$u=l$4af^Ti*hj~fm}?aV{{nElyZo2?Pei6t17E#dvk6b!k`B1jPk zXlcp+@+Zm&eJ9zTA(?cF~xECrbmb;G?c#Vp^ll*kj_;r&F4w>2v1$?(OS^ zsmGyFs@iF#-Q|j;1v|x^#q$PyzJC4s{Bj_ZdMN!NF`=I?Ua8fz=ouR3Jo_6w?Ig2j z&k<}RFViJiwc5*oRQ1c zkvco1zKv2ll-5>zo#^)M1E}b>9k+E*aW8T^m9BxpSZ6taIwk}x+n%Gv&2_Za#M9aY z=q_jFA9=G*Hq$(LGA;g@AS-Qw`>=kw$Ee%eX%%~Uu}?dXwToq5RaM_G`O+jHn|^GH zK0G8hcZa`HziVIKGuD=QN2%1F3&%op_$alh60B1}QJy*X>!VwM(Aswj2QGf<^S=S@LPL;|?9l=$YEffF|2v8|39( zLF2+6022Q4cP!r)El-O_MNHWEl(>6)g}#F7kjst+FQpy7^)EiG=P{>s6V8TGo@Ht~D(IW@8XT~Z0y>E~{Slp>!iQsr-BjbWg{0A;e zSk-UD)xrZ(UR`KaSY4W7Wo304f7;dY^qkRI6B`Jy#00<|SB%-Je3K{!E&GO#n47n> zWbEGuAuG;rQHJO1xP++TohPa_9+X#V))__$J=~h#8rnCo)ZGxS#;=yeXj4>nEW=Sx z_}IOkOqO^89ukDGFE(x36vMsu%I(`iIXidYX?Tnt)r{R-2mP;kS4nS8eJnSz6^K-M z?!zN~W#z3G!R;ca1{((d_{FLn3|6_wtLP^IM6j|lSDjiSgi z*j3YaYDb1b9fP$K)IAM(3}uwcw`fw>J2*h;@GO^PWKs~oo?+7N+@rs5h!q#QieA5O zFh)8i3J)Hbyt~X@1oRO*^=f+hAxB3skgIL`_NA^_yZ#Bpi5!PB#yUTLZhsVY82iCLHoVo`%xqV=Unu=3)lZcO{{$h@8`#B+ zRZ5)t(22J`c<=zo@#wK*IwW%DBo;24Xhq@=veDK%-(4 z6BA(Vj?T{ZJ+Ziv_*E{6(-h9t%d){LUs5t&c~m{!KNh-lZ`AnwV;M~>*TBZXV#vKY zJ1lJ-0;n@WuoZ)O9Qm_^bQ%kFLHA|TiE5fRra3+>k>3?vJ0L+T__VnA^wX2E4NIje zM@!jQ@_ehDdH$&Iwb`$C*-vZMg+jmP7GM>0(ZQ5OeG38ek)5ML;^J4ZpP=9CXlwKB+qV!(-%AJ!{+$-M z-W17idZBOZ5A(+LlBv3QAA=wsa23{KfU-6ZUPHl-WGm+#ji3J7W&?Stv{T4 z8)ZbBP0fQ578Vw`8{<{`)HWP}h9JSYCn|>~ULz*hgE=aD>D!K94P|-qw60IL<7Q$p z9Za$oV~>viWeH(LQ_o$)08%umP7~Fuyin4zMKx6gbP^yoXR{wYiqYcr4JC31YGp8}Ma##$ zwSb3bfAy9%+>v41xZd}7yOzC^lhXJ6UDO#FBR(+_1FtT`DX)~eo&qp{Spgjlkg{xf z_EV~YuM~7h!eP+mMX*OsLlQ#A29WiKLntI9G>Pg=B>gi*-95J}cCym8qpa98r_~)` zP*lf~Fa6zd$QS$jW2LWjqOcwWJLu44{YG=_CVc#DN^rBy;NI$mO%y{zLvK^1Hvqw* zh;^B|Z_4zars)ruUL-{>81hZ&U598ucp)#V8teSOUYA;|eD ziWg*Gp1w-D1k|eN-OnRhhX*0ESwk`a)bE6UOR4}tR}hno%sknEQ5%+1XwCroCRD&O`77OrbC`bzMiyXBY!S7Sv6bjYaKE zE-fwf8dCx_gjkg%ZuYt+jEzy<51-4-pE*3rog-*7j6a(WFNhxoUG23{-pVgB<2;bJF?BLMB-pdQA(15@;r-{Q55i|v>|!(zCkFGGFAH>Z3Q7T39|$}y4E z=3zFB)-ia)y=9<(b!G3v6ORR8G4=LB+`#U;^~XWEH<$X}hLV$yLH!CqP#}hB>ghEH zYTWNh6Vh?)f1ZKPiTl=PNWn4pT!nQ*(gK%E-?rvaVFH*bcMcSv8K z9){pu+t!hY}~bzC&6{YQAqGPz&3XSSIrF<$be)jMR)9*K_T$ zW5m0}a7vPP`UH4_;AlenU@XBYy9KoYh?N2>>Rx7`d=L7^e7jEus;y7eoEHT2j{QTs}{dsY5ja`~e@wdyH zxHX{=lTU#yFz(h%m6gK?nE51gr~RkiUPr3+W?eK?l=U8;UF>@T!Z^+cV3+$Z|LLlC zd^Fm5ucYo5pANHmewXovLbM~?Yq0TexE@hRH_5(&Zbfu2ZR$76 z%jE}ahE>!lMnB@;iz`Mtr%;|#b?aYGKKo0Lz)kD0^ygJO(WpyZV`#-#6ZHEw8IP3W z@1J=1=T`p)qPt1P&QaYSlg~PG-|TajWx){(iy&Q_z%UMtXT`-^LLRg9q~(ploymEg z!q^i>%%cRM$k5Qx+0PrZLPqY7dWF^sqT77$aT}`Oqi%>xso(j3>RJEQ?o9jJvso?cYN_3b z(5ri#12qo|;)=OP>@tIdkUg*|iu}?Z`Oa@3>F^m7{`-FC1ciEN|0o?f`y_qfrmIxq zqWUqzV>@AM@yiPdno4lq&dd81ag$r$>0?{lWa8VZhC_0zNp+U{zASU^b^3oR6H-#R3*RNWM%sOsas_I}|yy>pqAHZ=tz zpaMYR$ea-G`g^Kv%tJr;sK@^nbvxF7x%1wk&Z&f3#7V=zrOfov$){0!`~6wag`v*6 zu{0Gr-oDJB+yEr1@c?Mb;E(lI(SSOX7a!1lfa~vQ5??aBKWCMeraV4XLizYXb$VJ_ zOhZX=@ewn#^OYasCOCTZ4>9`lPllhKR*~Dz^8Nhf>dc;=05)n>D+;yEi?MOk@p{FA zf>+Uf0kZM#i2yliX=(Q#JUD|-4ERO+G&&rRqb+iwg5C$C`}u=Wq+m! zX&yJc-m1KMgJ9?90gG-3B|L#FfR_NW61fSxdb8*2oSYnAd~Cq0jXd(KMcr?4QQ*2H z0|kGWH$-sP7ICxiTRrj-=11sC{3$EWow>kfckNQNezO zgA0;O3f*C)1tG7B3=Rwb_)C{4;lPpSL}W&&^Ah;M-p@WE3`+AC8+b2ljIOJ>tCtRq zpTw*1bH<17U&C&DjsJXss`3VbEc>(-&T*2iruZNr_B#7)R) zuR>g79#DX5zn9q7z70e#=v(&rvoJz95!h6gJk78zeLW zJ^KR}ccBfCYL8Y&lwS7T=DKJ|z@(>}61D*_{P^*sv8jn<4f3m3(o&^urL14GuKew) zMnvKW$%Dk%?{EUFgm*|_8o_la{7b*Qt7`|R+7K+!)!nGPG`SYC7&0&h;GbCUmzr$^ zp)TV+Q8gTXR=3R_e=HNBFuh5^o3}EMM&a)+|AL2}9}m1gX=_W95st2}+2y%~egkfZ zpmWt9cHmUqv^|k<9>6-oa&wnP4+niEvLP$2B%*!*)-LiH#5?}>{kt3C#E(zmR|hx2 zgdlC7MOgO*%u8h8hf>I5yPvvIlWoHHkDDn_(>&Ml;$+dm$49OU8 zW|uZF(6=4J{)Ic~U|AQ%2Ipg{^iD+Ap4h*C{Se!6l!cIjSe~X#O+f##1R>x&T$D)?gGr{D z0c#HH!~iG^JQdbH`4elO3)9T*5v?qgNqf(BqLM%L_kBjBoLvm!*u|psPh}(<8ZK*i zj$50^(#FGQmAvdq$zsLFG9v+AMg2CxtIgdC!OP z1jf41)epEl@%!Uo9<)rtpf67|nk3C#sGfAMEm=)q>44YM{R$$jI;PtCF^1VZ!^QT?x(M+b0mP1;HKRJJbdwg>5fK};) zJ6aM9f;$jy@EciUG8=EPU3 z-bcP&QI%Rsy=IV+21?dM&_%gRh z?mf~XKl>`WKH4DY^ytx^o3N=#;C|PxU5LZLyq{m1X~kdo`aRtl(Q_sINu(faV6Blb zJuDRPQnbEF9|ezz&phF^u5C$~Bb3pm$QGx#WX}BkGgdbJdM79t1B76pEV5ek2nDPuMn;r z;uiQIGzie|U=h*Zb8;P|pjwBg%+ypVN&)h7{XxojFa%pxul&guGcCP(Sb6!H^2$_P zwdh5abKVeHmex!}U%7HOH}|z1J%n0(-aUGQNX4INyQNyW@^=hzDfb@_?oGpC0-|bA>e0Dj!Pi-yfzwqvRnJY#8A!YEPG6jIuBs#C7=lQHOqVHHDRA5k4eOv= z=)efcubSP=#l_{nFa++`wC(MUeTfk9i%`Dus%B53@iJ8Pm$#(R(lrN`R&HGiv>R() z-OH53R`Xdi_0oD4UmCt9TBsstJMZd|$BTyufQYAsyrnBZr)7aL(M@n?9+_9A5#fP= z(zkDQNg9m!TsQW)lhK2)urS>W`G2Sx-t`{6oM+EI*cIS&P2qVbB13AM8BmW1);|^L z&5&A>^@qo&!qMN#%hOc&UKm*f)IqLYfLn`%4gwHvFV}HAfj{Ln-lL(WMhP|LYx!6n z42b3IiA!x$kD z&6=ng2>j$=-vAm(AwT%&#Lfhv_{_{!Zhw!Tv=RL9qy7fu&92S#=Rig2BvkbZ_!YJ!Nt9upC*-t*wwYN*!4E}H%8rhsXp(l0jzR$3 zAaNj%xI&Vc{7>jxGUAt8*++~D5qInT`}oAfqW<}&0o|ilg*cNopFR^D%kZq`vDZi@ ztPXkU5QMX{nASwdcG`4f} z8w#Bb+9tB}!1|URbep!wU48%12>Gv87~e5#MlDwVcA=?4C4GxWfjf!9CmFcp1Ihul z4%*SLsyTB@E32}>EBhNUX>{|#uPm%T%-STtx%pK&qYuaJ=f?uj_L$QW^U-syjHsc zxr%Td2>(QBWDFGdaVUSaPO-}0!VGEe+2IGh})Fqz#Jt&+{WR| zAXwD{NIm5|co2zjC5D%XoOdt7Ycs-6Ll5rVw4D6%68iGKpP#GJ!?y;eK>UOKVXpzWEsROORrM!cZglyuC z=JdTJcmfiPfW{zDM?FIAh+-D`FSupryTU^e1(k_EeuNEU5awmzIiZa|4-<<@~uGJ4X__AR9i zOhr!i4-9?)K!Kgx0HUh{sUvVqsV38RKILb6g78x5WWa_+anQgm^bM+OVe4NS>HqP9 z$fERYDpyJlERV!pKd_GRbak(B!y@g8f3^zJnW$qWI?2&u!Mmy6o3rp63iRYM*>+yN zrN_a{8}-lQ!zNix{1PCBVZd(k=X#_s7Kcq57WGd|FmjpHo)haStTsU&y|N0YalFv#G{pWarmB|qtY-WcrCsWL5uc|*Ny zK^EUnXKVOd${o?9;-7}|=RqBn9kH{WC8pFk!XI3Z=dxTDwc1&x#G?N#9g)=>dhZ}z zMhNFxCaQtb&OOcZ94*XGCJy@XOGQ!$6z{9%y>1e z2vRvpw+>7F7^(41K$eAM1O~+zsgFRks~zCu=U-!zv|U_W7~xGsdco-dEB~L-EMvK_ z3jmZD!&z*Ko78r=SiKWa3ocd<i<0@kQ>Wg%*j5%V=&O9&6%x^rh8yhoxWe4u|i?cJOv1AmCxZdcRa zZ;6Me;d>2WQx|*5Uue9Iy5?#=4AbMZCG8Nzw{pIaVMeY}k^kQV}B2pzP`-$(24TAiK5u8Nu zYHpDv{`PzS`i4G*IOt~O4xL2dDZqTn0~RAp$+Yv=uzmBKDfeti$9A@ zN}PBQx`*LJxFy+fyaB%rczwSy0rs>zEd~hC-t+L5&sh4CA9M#yfw(*HF*xVw;tv(8 z2*ilJflN!n!UPF`Q^N&Ckm-wu{JzoKiDZBZLF63J0g`@F!25k1_X2UpG=sy083q^Q zlalHocxt1`P!KJuda-X}1RMZ3m6e_StBV{biZ>woYG7TOc{o7* zYu4+GK&TTrf$k#P8N>yndwNcS+v{j(tivF~-ohJ*=AA&25Y3mo5cCTzh3oxd&#BTY z`(7Za@3S=3;QJ+bgZ9CLmiVNE?_%_;AYjo84^t11gCy4`t7(IY)QEeH8cm#Dl1c=5 z#X?X-TyzMi9{y{~8GL+@t|CS6xzO99v{>~hML;4T7cdCZaBZOI#B-d`W4&^TT)$Zt z*g!A*ZbF%X4O|hWAG*2doy6+wwBbqtUiwEPB??RI}roZpb0V)PN#WK{{ z!I=dgh~FfviSdjqn3j+jF_)r+31KWSO9XaMzHzl1Q~(S>9bmdjAh=2a>sTK*3d88x~_OT>oivm#oOS{5MPpymQ0I2rG=8LyB*_f>*VG#dh?f&B$ zY9>j5#PxjE7%FvmO8Ho|eqxR!O&`*U>m(FJ;&W0Bx{OL zuP^R@@Q1>C*e`fruA;`8{!hxwqlbxkP6+Zv^gql{xXNvzzy?DUr0MNj$1yX-0SvSf zT>--lunUM~LGS`r4fmi0s#jy7e_MBOw!oPNVM^@{A50GQT)xL1J|nQ~!=nNh5&r{A zq5L^lIyom}>gNSh^Y>U+tMSy9o9yKigEdBFUn@R8+oK0V7enO)-yoMT+BCHI#m~wM^*)=@p}+Z&AJ|7 zp8MIeBy1zAz7CuX@SiN7XFUa_fZ$l9P_J3JbF{?L+<^ZEbi|J&kMezXJc?O=qcT1F zSITU6#{V_K$C1QGecrO)X=i&__dYbYVmepKeUhOensQ?*K1UR9>{5*hQ^yEEsO<2} z!YkcJEO0y;-OlYUL*`@_vf>n!Q@>l2R-ui8BtWkImGgvXK^n*@R7V)lN^f&ZRVq*-qWRM60ITZkTktv8X;drow=j8}% zU!cxcX=!a8#yF=SkQ|9`qgO`|Ee%q@b?H`xL=Xi*9cD5_&7d&(uj&)qiWDS>vguQP zr1B6OXm{0bW|CZR|NeFW{NT*ouRg3QlKoiueNP$i|GbbfYmX)$BVn#6Z#XLfga+m| z3vC#tsRWUFgyytIPueYYImI~gbHUTqq5G537}G>-hIoVk=1Pd2!2k@LAJ~8=D+lI^ z+=DZ@tt4DV#&J+u&LDpR{c;*({=B~%dQQODTf2e&Eam}lJrpfUi;l>gl|hoi)__Eo zjQMM#R+YLAa$=;8q!a%9c)wWn;cHzqsUfi+QtB-E1qDNJ^S79F5g?680meR|ad0po zm}pGpApdV-qJzXKnh%UQ1>VCKoU>h6U-9`NY>C-%%eM|R-iQB8^k>3DfJ#8d!O#s* zX;CUr5y{~L#Hu`zP&260Y&Yp#D_-*Qr+CX!v7 zs$)+q1Q(^H$pcuQF`K!;IzgQI7*z}nv2>7(Be}_c!N8ZJ9$pcyjCOr-lYcKl^DDxN zy&3q|Uc7QrEwB8?4x)ntf4qdPM_MsC)nWWom(NPW)*xNfah}>k_5V{c71TYHq;HNm`2}1kG_vr&~B@i=D=0i%YL*6r}5)VKWq1B>T1V*)(IEjOxTc#HQ4 zn|!{@vp$#l;K^a}H-!doG$WuWQ=e~{n9C83D&0K(4f~(HyvI?Nh#z&gu-y0T-OEj9 z5!NV#!k;KaqhUaA9DgKfXsu1wrp!`|vB3s33O~<(LwEPKZFlrOAGTA*I)>wW}mkminUPrBq#ENZj)v6)}&VEv_&kAu*e-#dFh`4aYFC|oI|)S*j7 zv+uG*ZUXzhVGuxUGXi7%E3JVY1P)%S;O_x1AQ3icU26 zZQMofs&%)V>!NqSw zAW~t^;FJv#S|CL=aQUw*MrODcY6;r_C5WpX_yU>38Z?C{f<&YS$fh7IvPE&ulx*7^ zC8dnWyY~1rz{X8v$P;9X80xDCNvF!5Pt!JF86eZ7NF5?YF-;-?BCoK-ZwAboAhAy- zmCDM>$XPr@1%!kvg*}Y%F?3K{L{=bBg%CfANGu2gtYuJ8!PpnZU2q|=%!$E-zYKoK zufq(6vLM;?{hU9`hf#Gl#+oQdIIw^Dmp5>Z1cX>%PhYqMBYhQnK|^iO zFGwZRynA{e2=I_|BNF^|AZ`(O2oSagjjI2$rQMDEpcM+Mnh9G1=P&qzI+J%^05=Us zV9bCOdA*kV201=Bf1~luo59PGm5knYdKfm&+lTq1NxJcR7TNc1zufN?lUs6~Tb75|yfKMFuo9D}-q^pNO{Y(-Ox9+vfSN6K3Wt40(R zp?5w+Rd6g8nWp=hM-Ezoj%WqDTvPE6Ip1jdVxQB!L&@TpNbJA}4@T6;X#VlzPjIXO zR#EJD0G2J0SuvVIgi5$_%s8`3Yioe|nKS&hH(WKt9~5=O!=3r(=^$7@ax05gIdWfN;dUXbla~iU3nFb@}g@FU$|I!qp>hK@K+n(PPA7Xl}NK z2;d0xR=t^fU@CU<%ROkolGKnCM1+Ocn$ z8tjaH{8ZZ?E;8Sa?l<3 z4sQj0hEA##;3&_HW6t38VC{&R6ox{wM$Is(^pO-#rb8;m=CpYicVh!XoJ&kG{?T;7$3|I z(&}|`!l6Pv2AJVMUIvC(ToYe;Ztlj-dm^BfUEV)YnTXLgNzAb(iJ1`ZMm9Z``0>fr zOJT@c5j+dMWDS`XEGQ@-2V}%-*_ZGzublQGN*~!FR*atK@hnjI-D!9vnsruTa;J*tuAQAaH?WupLoc25i66VXL0%j z(SwMA0gDUry(qe!*pn}p;dA7e@E^=P0V8cu+XxO)~RCr zS*C(5EH+b&s$kuZ-~W8d?i4ft6kwPpIASFG{{0A&hR58eYp34cHIIY)f!jPZ%C(0- z|I6@t*8A~c=)JA&V%J#T#E&A#m^f%4cqD*h|K*C@E8iSE`@8ntSbSC7A&6WIi@5{_ zs;o^VAhG4_DY$Eoc@kJscq93dbN?NmBb0mbUMcndcabZncm4>wvP;3BW^f7?zs|vf zHP9b9)&YgqbAEXF|C00%6qL$U9UK7z@e`+al?Cjk54^#pdR!>R(UQ^3jzd|=HG(d+ z#k#+B<}?TGSLrx^%gy=!)5(F<|8vTS{Fb|A{rlbSav{y}9=dg3e24iF_`U04wyLo% zOW)()ur329-yXe1oySw!h+`LuMHkj*T>N+9n9%_b`3%hh;ej>`&LRgBT~}yvm3jkx zcx{1&+FNZ1swBH_9m+27FI$X5($bsR<3*}wQ4j(XhK#yAVLd{ZV&aZCFUyT33U-AV z6}w1vQ5=Ht?s+6@?Vq+<8TMH={qp%k4u+v)kw4Rq8yLQ~`k=?G)3ukar3v>&DB#EYu9kBd$oOXQ($q|4Ifhs~gn_phB_F#s`4}e>#*THUNrgIntJ;sg#4k;M;+#cSQUFB>~XLX@zifK_dWAQDkiq z;=B>GvVaL7Vr5nbE~6?zg9rO>#$+pG9CVsnxjTT8_C{$FK3r3yMsh6=ALcxN&TEoH zbUh&sxL;6&v1&+N1|@_mO@c5`8{fWtyL@o?S#sw7 zQCS4?@e$1f{utuL#9D`ML24L!s+8~a*&M0UXl6vmz=;`Tpa_3x1!vb3Vgda4B>(G{Ow%_w{bZav|e}Ht3yC$7g+QM}k5GC9J5Mc6vXeLnWfLw^A59ST%xeqlIS{@V#6XYrI z1t>2VXJGYKOe;X?Ag7+-yU0~lp8R3?uHE-)E}Cg<4UtS<}+<=|u_Ec6-hG&dmRLWtf7 zTGvBn)59n=r;@)MV%6epCk>`C_mhLE6+BE>Hm&)Ae|EyW0IT{+<}_Yk+fEQ7m_6=Q zXN%SWIddQus!vbOtR;3c>e$nhL~A385}7a}auY$cNO&RY$9v(YBnde{&PWg<%@NoG z`VkrIvdduaLCT99`J*F}@e08U654{0ii76>WeKb#8X38Lh^m$L{jyMqMw}M|jV;7| zPuf`gOm}vd7df{GYlCnezy+k?3*iq(MMcdwI|tT&Yf8k{0RBYx*K%?a$LImsq9__9 zUX6446mn*@OGT4}bWDSm|Ma5ql4lMDm~>TKB;hHw49aI0riVcFk07E)VoQh`bly80 zmy&n}8x5oLwkt~uWWaxE+&KutX*`g!K}*RXPm*wk`|PvN{(C%} z-{t%Le%_z==ly;gmUHYOjZW9jBI&qr=096sSRZ-ScFqHRQ?H03ZVU2GLQ9DkqRrU; zxV9KizxYO#aGczlTqa^^Sxv{2vv{LK-jH2nFen1~Ao~D7B1=9sHRM(ATE9#j%N!%9 z<~-TASy{5dF+NYR_y{pRug=24Li!>$vkVJGl*K3=fQUpwS}N%fK(|R4as$rzD$%b? z4+r)sbI1k!CSw1g&yi6LDk`q3o8z%D)OlZxON)r)j~szA`6kd2Mfrh=8FVomN?O{|ipjD9Ci~CR}qzn(>PG>*%`;e(ArwmODUZh2-vkv!l zUOpzC0`z6%G2snfg=rIdCFn#-S#S5F!!!SA3u(NHo}IpOub1-F+|5mHUgO)hh9pV{b0{+T8DG=U}7nv-nBdTaEM)Y^~R%5OE%5*R!^^q zhQ>L5pKz&>*~z636t{LJIwe<@89432k+I_F8r4c$o*YU@IKA?D zSy)z;<;jhjv`eRW^}u%4>9F30%TEg%hW~inX~vAE?vHy6$7uWl+0bYR^4ohXB`p|-`~(?U`K#|oh4^p%>}8uq-N$q7O9?2Q^bZ(#n8wrhJ327@I3|d^TWN>UltV9`8JvxTyF0AgEI}dxA)zfx%13L z@E_3{ek;uK4ZFzomF^`MldKGSt!X zL91JR)z!_QrBvl@vBTOCWlCB}*ti)p&Og}XqmTQiT}8eC;xccwnTt)h)`4wiK+$ur z46+_u*RdV)oMeEjc@C5JjZISakDbSW*L_qHBC2>0?G{G_-mwZp`+ z_Gg%0#r914-G$j7q}=X&-alu2U_|j4#_AbhH*7y@HIx+Hla}>n?7FXJpEr>MUUAW1 zjq~1Z8h`Xcq?sxQm?U~#*i8J@YZzox5rko6lOm0xKQoUmb-~iaP8GQoji^Z1m`BYV zy|dL?T3s|NOld%Ase6C<6XgvGZY?rJ+4w?hrKD7jJ2=agt3hNcBX8$X@jY{f5HA)p zBIZ_*diiqX>JgRe`UmuOX{4KGPru1=Ae1F>Q;ar5pvyQInromW0^uM`PcN~%{Qk<7 zM(1kMttfG#^8}I*(V9Z5y}4Sw{LGeSPZ0p1V-)N`*v_W%BJ;>cO9)@Cx_13KCd7DZ zoQ~vcVZVMsS%`YrS*{6H`rFazk{$9Ogv?n9u4Ww7{_IX|tuXz8j@|g!#pv_8CJm0_ z3_rOn(-s`)Kx@2S|nfO2_np^m@G7B3r%~o_@`0mv6CfDjPF}_mQXt> z(ro#O%Q7Vlm=}xsp$S`lBk31pml3xBFv9jhgl3F(SOXM3j5Uf%lYz($sON;q+VVtI zT|@LdMZCSokbrF;FzVKO6-u)gm!6Q2aH}TS^bkN&2GNKY*ya)wN=}lswJx{#uyX=B z1=b8*99tQ6sm0!M4q;2n#oTn;)~4-+oGyHf`V#9gykX*@Lt%K#sOrEUg^5X3Lt%ra z`tDuj!4<@f#Z~+Yy-!S?uj>`?JS&cem$$3&hC=+Zx1-F$D9@&Y zQQ$9C=NCCGRP33mO$Cm0O^X<0l=g@Kn{l)`rZ~QUt;{uicZ_j6&^0i@p#o)h{_`L7 z7rGEdHNL_Tnhb`AFwwV9+POuBj&;YbT)i>4vvPQRBA%}s)pbRGc4Ccf$eH+|k5A2w72`Q$ zBw-?x#{lmIqxLg`W!)}b|I{5neYd^A(M7Rm;?zMX&;0Kpr z8X7RIAPF&DqQD0If?CU^@X6Q^a#M0YL3$lUzYh;BF`lGIt7OE&d`mt@27>OqIfX@@~JY&CW*KkY=8cFF1h-PS?~Tld}%XY_H zy}1LGMCZYwLh9bLvo~yf@&XH?2L3!9l|3iV(sx`H^@r_(?uS`^oe`XoXk&nBg&0^s zA#5>;EL1+;5a@^f!rerD>ZKwnUi>D)+$JRfF8AAbh=d7M9uVK5#>njgwG1cT$=K1n zRim_t0sS*UF78M>?&h8 z+gZB-`Dgn1=@4Xfd+12*5;|I{+0eOIp;9n5E0E=L)OnS@Ys;AW_}}uF{)-*$)!d-7 X73(KlGppx6X6Sghd%5Mh2890`EksOt diff --git a/generated_examples/matplotlib/mg_execution_times/index.html b/generated_examples/matplotlib/mg_execution_times/index.html index 458ec18f9..05b76e068 100644 --- a/generated_examples/matplotlib/mg_execution_times/index.html +++ b/generated_examples/matplotlib/mg_execution_times/index.html @@ -2862,11 +2862,11 @@ -

00:00.404 total execution time for generated_examples_matplotlib files:

+

00:00.444 total execution time for generated_examples_matplotlib files:

+------------------------------------------------------------------------+-----------+--------+ -| waveform (docs/examples/matplotlib/waveform.py) | 00:00.240 | 0.0 MB | +| waveform (docs/examples/matplotlib/waveform.py) | 00:00.251 | 0.0 MB | +------------------------------------------------------------------------+-----------+--------+ -| mpl_figure (docs/examples/matplotlib/mpl_figure.py) | 00:00.164 | 0.0 MB | +| mpl_figure (docs/examples/matplotlib/mpl_figure.py) | 00:00.193 | 0.0 MB | +------------------------------------------------------------------------+-----------+--------+

diff --git a/generated_examples/matplotlib/mpl_figure.ipynb b/generated_examples/matplotlib/mpl_figure.ipynb index c7b7e2098..5126c3477 100644 --- a/generated_examples/matplotlib/mpl_figure.ipynb +++ b/generated_examples/matplotlib/mpl_figure.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/matplotlib/mpl_figure/index.html b/generated_examples/matplotlib/mpl_figure/index.html index 2cdf7906e..f7cb47aad 100644 --- a/generated_examples/matplotlib/mpl_figure/index.html +++ b/generated_examples/matplotlib/mpl_figure/index.html @@ -2931,7 +2931,7 @@

Computation times#

matplotlib figure examplef.show(run=True)

-

Total running time of the script: ( 0 minutes 0.164 seconds)

+

Total running time of the script: ( 0 minutes 0.193 seconds)

Download Python source code: mpl_figure.py

diff --git a/generated_examples/matplotlib/mpl_figure_codeobj.pickle b/generated_examples/matplotlib/mpl_figure_codeobj.pickle index 0ef4c0281e4ffb40f8708741f3affada1cc13328..c2ab0959d5cfefddc3a764c25449017a67d122ee 100644 GIT binary patch delta 1253 zcmY+DduZEL6vub3xxc*gOPfcVciJ=~Yu3~{v^t-)Oc?kW1w~hU#4Yaj+N7CjSlwD2 zO2t7c#&3oW2WA5q>f9KjA_xK?!t4SR5mK7v{4*Rtvh4pr>^>F8oau!Eyx1_F9DCgqlie-4HP%36OOM=0Nk zJZu83Qemw7;qWo>deHqH%m5&e# zJ}c$#W89af`~&Rwbx?j7R=?bhPpAANi7P1o1ik*0lTR=1#DU}f0OgJYto6pGWQgm2g4`@=4Y{qM&$oD~=x?As=p=WbJA4yaD`N_m!ftuo)8RJkj(Fv9PltQR z0GyFta<7c?2C{xX4oOn=K}oB~LkL9;e^yct*@*4YXrsPKQicdQcY8zU8zg&Ji*ib1 z2h;X8ncJ5Hq|MmZ(pCN2SDhJPqAq=ik~|ap6ityN6K^OA(*#bCIn0N2 zET;h+qYiY1b$m}RFmY5l>Zat2rgkP~76jIsf=qm|psF)oCT0!M!^D@0>@0yn=3(M1 zLtVqfDMdvVHuB#XD$T?hMYAl52~GOHGgKE7=M??JWXB&2iejCnGjU$2tk%uM&jy8Y zK;?f^>aezwi9ZYqKr_qyUrI$u1SeJhi&vDaQE?f8SjnVO>B!mSjCMu4Yzc>ONow4z GocR~o_lmgy delta 1174 zcmY+Ddu)?c7{+onCpjoG!-bAQ-Gha?oF(1Wmn!5uH)qq`Lp_;vd$y;T&sqC2 z_hx%j1-$I9cIO;L)v0Rl8!BL%r(!%`fz<&Yh6Bww=l9{(fP)DyrUGFV+R8)_p9T_4 zL~uSBhd+3RiF$=iOf=$hD1g?`PfV=GHQ{z9TGf`oL^!}i8{P=7W#T3?VjkI!hDZw& zo75J^Ld4C)X3RxG*c_=~VynXCOl;3bo0-^|k4EsgcHD_6g>P!dZiOqD=)_!9^}a`K zA;e%d~pY zmb1%%qGH>>U5SK@F3IA2CEc0-&n9bh;f$++%WE}#>k8Us!%|HO>#usB%T-F|ja6K> zXvd@x#~sGQT;6a+EgCK^Z`5kQUW26l0WRCGsL$;xw@Isc`xuwoH1(Axxx7u&WN9sz zw`)3I8pM35hs#|>rQ#i$+8r^pINV&`T~zg4c56E32x83P#MegV#OVDF>r$x#fsXUn)zWqwFio)BlNbr)5%$_sT;!RQ?-H z!|*oXctxCMO!}iDNUti|fQ6t7J5??ga^bMIiQd7ew+>r;9y*B?zG|HCdg+v+X8Hh~ zzBM$f);JDVdgx<(qV#8KjpJ?QpF>||(SKG^GkuBUl`H9MwW@zv`M*!rrMdnAFP5ujs5^mc7 diff --git a/generated_examples/matplotlib/waveform.ipynb b/generated_examples/matplotlib/waveform.ipynb index 8e439270a..020db8535 100644 --- a/generated_examples/matplotlib/waveform.ipynb +++ b/generated_examples/matplotlib/waveform.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/matplotlib/waveform/index.html b/generated_examples/matplotlib/waveform/index.html index 5cbb65443..499c5d977 100644 --- a/generated_examples/matplotlib/waveform/index.html +++ b/generated_examples/matplotlib/waveform/index.html @@ -3132,7 +3132,7 @@

Waveforms examplewaveform = WaveForm() waveform.show(run=True) -

Total running time of the script: ( 0 minutes 0.240 seconds)

+

Total running time of the script: ( 0 minutes 0.251 seconds)

Download Python source code: waveform.py

diff --git a/generated_examples/matplotlib/waveform_codeobj.pickle b/generated_examples/matplotlib/waveform_codeobj.pickle index fde77dc2e9b3376fa3facea5b5ffe6041b7b7112..9fb229cda16fb4575c3c030277d9083e63d6fcbe 100644 GIT binary patch delta 1148 zcmYk4ZETZO6vw%z&$F_pPhZw`UEB42t*dL-GNv06=S$d&!bHKDs05{?WoOr})Uif! znQ@8A)FxO@)h(I;Us#M{;ENhej06)k3rau|A;A#+;1^U#G$ax;?|oW~pYHGc&-vdx z=l-AN;kSmBm(;fpRF!U38JW&MTfJi&U0|uE7SvxWXKA=&0MJeI9aDe-I^pjmxBnbq z!azqr2TW2V@DJcdx*m+v1HmZZpnmO?SNyn z6p8~rOs7K`!0mJ+lmvW?c7}trIn)aHxWFF39ds}({7;D^NTU&9%u+Jqug~NJ3fBZx zBHp^f1ttKe#HR=9O36S=R5~a(4|a_!V9Dgy^Uz2e?9Z?~{P%sOTLByhy9w4*J=9 zKj0Ng__hN6O2>VEde?Uk;O}(FSD<(_26%(EMmqrirk5e3uA;tBrlQT$3~bFBS>)-E zHOb7hV(kKrQ6ajn#cs4jycKh?l-^s+S65>ycL|l|nP27Yl0H*rfrqKr5upkDw=5|r z&C;~X@f#bYYb~8LZk_`^Bya;8HH0yzRoN`9hn+#1bw0|r(f7`nGA^Z+wYycmLsF)B z51nz^>3r)>Hc7p%J*-5Fu3gG=vUy6&0e_KxvJKG@meTkEA=X35*`jMJMpfU>ez4KX zSCpah%zg^$T`I51OWv`hVtlF5o~tF$T!GSL4Vx=!u{>4UFJ7I$F9)w!dNqEeF_@)I zrXH0am5pghA4oc+uUGlUlFsX$8b8q(&XXAu4*rQzE{KOzAHnQC3g`)qf8LnMR{u(? z{7dPLvo4LF{?F^tdo=#dtueZ3?PF&sV@t8K^j%w@azR=iQuC}I#4_1>MXpXT@bpF8Jp z5BJ>gtHZ`Te{QK_6#RUzn4Bq9ddBcnpqJf()xZEI5*;LLoJnj8h_o=DE|;)owUfx< znw27v$9lAAh=MRH^V|KM`oJV^#9ITRSD2?1A5XTC=*JsLhr|HBk94vjgsdbNcdI(A z(CutDhC@41h^waia4@dM?Z@ACABl17NRD7M(7_Jlj1B}Y+x=*2D3d7TMneXtQ=gES zui|XlBykdBnPyx_e@o&VrW;+H&zvCfd=>khCK5{u)tndcv6I33jr&Nvfc;qo1A zYxQaDs(+HpcRg$4a!u2q=^$tx;qn7*kDKFMeyZtTGm4+gJGuN?n;V|s@`|Rp@F1zbl9(Y+@<1EJW6ccq)*;UIB9LKzh4E_cU><22VnI+d;kCd diff --git a/generated_examples/mg_execution_times/index.html b/generated_examples/mg_execution_times/index.html index 8b3271417..3ae5376bf 100644 --- a/generated_examples/mg_execution_times/index.html +++ b/generated_examples/mg_execution_times/index.html @@ -2862,11 +2862,11 @@

Computation times#

-

00:00.909 total execution time for generated_examples files:

+

00:00.871 total execution time for generated_examples files:

+-------------------------------------------------------------------------------------+-----------+--------+ -| basic_example (docs/examples/basic_example.py) | 00:00.780 | 0.0 MB | +| basic_example (docs/examples/basic_example.py) | 00:00.740 | 0.0 MB | +-------------------------------------------------------------------------------------+-----------+--------+ -| basic_widgets_demo (docs/examples/basic_widgets_demo.py) | 00:00.129 | 0.0 MB | +| basic_widgets_demo (docs/examples/basic_widgets_demo.py) | 00:00.131 | 0.0 MB | +-------------------------------------------------------------------------------------+-----------+--------+

diff --git a/generated_examples/napari/images/mkd_glr_napari_img_math_001.png b/generated_examples/napari/images/mkd_glr_napari_img_math_001.png index df296a1a7c91cf88a307e3eeb776a5ea899013b4..44d8424f308b6dbb7029c06672883975c6b51354 100644 GIT binary patch literal 45675 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�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�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 diff --git a/generated_examples/napari/images/thumb/mkd_glr_napari_img_math_thumb.png b/generated_examples/napari/images/thumb/mkd_glr_napari_img_math_thumb.png index a57c1cb397dcf4e9b66cd37ae8f38e6b1a2da025..208c850d8efc06ae1e34a015b05408a23d87f252 100644 GIT binary patch literal 28403 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 diff --git a/generated_examples/napari/mg_execution_times/index.html b/generated_examples/napari/mg_execution_times/index.html index 14e522ce1..09b2409b2 100644 --- a/generated_examples/napari/mg_execution_times/index.html +++ b/generated_examples/napari/mg_execution_times/index.html @@ -2862,13 +2862,13 @@

Computation times#

-

00:14.887 total execution time for generated_examples_napari files:

+

00:16.424 total execution time for generated_examples_napari files:

+--------------------------------------------------------------------------------------------------------+-----------+--------+ -| napari_combine_qt (docs/examples/napari/napari_combine_qt.py) | 00:09.604 | 0.0 MB | +| napari_combine_qt (docs/examples/napari/napari_combine_qt.py) | 00:10.193 | 0.0 MB | +--------------------------------------------------------------------------------------------------------+-----------+--------+ -| napari_parameter_sweep (docs/examples/napari/napari_parameter_sweep.py) | 00:02.986 | 0.0 MB | +| napari_parameter_sweep (docs/examples/napari/napari_parameter_sweep.py) | 00:03.764 | 0.0 MB | +--------------------------------------------------------------------------------------------------------+-----------+--------+ -| napari_img_math (docs/examples/napari/napari_img_math.py) | 00:02.262 | 0.0 MB | +| napari_img_math (docs/examples/napari/napari_img_math.py) | 00:02.432 | 0.0 MB | +--------------------------------------------------------------------------------------------------------+-----------+--------+ | napari_forward_refs (docs/examples/napari/napari_forward_refs.py) | 00:00.035 | 0.0 MB | +--------------------------------------------------------------------------------------------------------+-----------+--------+

diff --git a/generated_examples/napari/napari_combine_qt.ipynb b/generated_examples/napari/napari_combine_qt.ipynb index 54b91e974..646c88575 100644 --- a/generated_examples/napari/napari_combine_qt.ipynb +++ b/generated_examples/napari/napari_combine_qt.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/napari/napari_combine_qt/index.html b/generated_examples/napari/napari_combine_qt/index.html index da52157aa..e21ea60cd 100644 --- a/generated_examples/napari/napari_combine_qt/index.html +++ b/generated_examples/napari/napari_combine_qt/index.html @@ -2937,7 +2937,7 @@

napari Qt demonapari.run() -

Total running time of the script: ( 0 minutes 9.604 seconds)

+

Total running time of the script: ( 0 minutes 10.193 seconds)

Download Python source code: napari_combine_qt.py

diff --git a/generated_examples/napari/napari_combine_qt_codeobj.pickle b/generated_examples/napari/napari_combine_qt_codeobj.pickle index 4c1f2e04a716d98351e0b022cc2abe76968dcfd5..af4b83c0855930b48403529d7f6fba9aec433afa 100644 GIT binary patch delta 1015 zcmYL{TSyd97{~i&=d8Q#jLjyd4i-TQ>+2jU>7( z#rAEX5eP*g6{7SKg;)eap>!c3Fsy|j6~u}l=s`MXhQXJ^@Au6)|8KrCv+TdIUmha2 zh9hz@jyQM5h2?Iwt2K(REUDJ8xvQro)XD9u)9nb`bqfS(&zb&cI1yvcM0+%B=?Dgz zJJnz?iu{J%kct5kf^1wMDimUcxdD9m%aelp9Da$GFG(GDEi8iroJW+5+lXpkzGLjzGS zjSHJ<57b4eHEdE(H%FHSKV@A)I)idUe3_?Hg?N9ewOaL+M8ouLv;+{CVLX|5a6|bc6 znBRC?DTlu}r+Cc&M7(_qUMKI}EZvUCz-+aL$; zq|8GJUo-9IZnalE)4?ZZrFb*75h`#!wF~@sDlOMq%TH-dA|Pf>cuh zR+;h%W4cun)@9VS{k?{1!9ig)axRw04#Ljrwu`WHg8Jkt!p`gDby#}OwW!_w9pd}4 zK~e3rjuUoSP^ry_2jf=>L*4kf+k$HBUX0qjgpC^Z&F&)Xu3=e95@BPy@d@q;nzrZS zs6B_U2fFbI#*MnR|FL0BHalSx!rBy{#HKKoHVn^kB0UeUrsu*mrz&`;#t k;S+Zbj=G)jozpJ(fnVHJu*%m$^m`QB8h=CWKM48$0}Kf~KL7v# delta 970 zcmY+CTS!z<6oy^fIqJ-rX&jvy9i59cnWHh&P$qUk(~zhngg~LpI@Q4Le@5JAy}-l7ZjQ28JTMX&9>N4mVM^{s!cz0N*Ad$9gnon=6~ zzHi7<1$%)nH)ZKIx)Ny^1@3q%r>p01vNMrRIl7HwM(>f>sUwNgiQaU|o@wkq!Fzg7 zrc*hY_Ry>w2Mfv=&qutl9HRwK7%#=6!U$4@0mg#@YZ+gzly@E*<12B@U4>?Mi17-6 z8yT-sifTsD=UIhio^rT@ah>QIS|~=>@zVQ%@!MD|is50=JmVt@-}}TBMiKQzuK6O2j|pmId|V0` zD0VYGp-_!YV!_wM_>@Rtgo;ZTpH`^mW)-TrIn0;D7=MZy$9j5>PDg-VqSf-1KA}## zNMA(^;FG4)JPhYm#uu^ZtPJoU+;KU1E*;^ysqBWvt!ZveWg7<%rMb?3VJ2r2&RDB8 zGmEmaFlODOnYofOZq#Y!GFch6cFpui`s<2EGyPI=>U(TvSdjcoVkjELZT*dA#$~UC zqMEr*(mi{P&8$^ZSCR$>9Uatw1;>=7S$6BR3!1q*LjmOH>(q)4=OFFFf-_17;Lm?S zM@0<&7ne?6;y4RlfV5Vhim2wNq>xgD=TIEJ4yc; V|5+-+c+LDSY0T;s&oaW2vEP8rE~5Yd diff --git a/generated_examples/napari/napari_forward_refs.ipynb b/generated_examples/napari/napari_forward_refs.ipynb index 527e7d020..dd2038c52 100644 --- a/generated_examples/napari/napari_forward_refs.ipynb +++ b/generated_examples/napari/napari_forward_refs.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/napari/napari_forward_refs_codeobj.pickle b/generated_examples/napari/napari_forward_refs_codeobj.pickle index 2a2fcee8e1bd177c65584c1cbce936f908860fb3..6af19d7de58d786f5e72239baf3ad33353369dab 100644 GIT binary patch delta 457 zcmXYt&r1S96vx?p`-|8mDMP~|wu~fe(__$0v_g_XLn>rT({^Fq1=ocj3OYu6$Yzfr zbmD>B zzGycCpQ}5L75GBix%4btOLfn*x~A<0zC6x!*Kj)Bz?kwS)72Z+h3f`nURs4|Lne=6 z7NW?3xGcmB`N3=UHr3u|oJcUE=q=A~bWO+BuRN2yLyVDogFG#Z}J^Gu&SgFQO?+&G{0E|cF;#`3ELw!PO6|ytPk{Bn$cZF z-1P?qD1}@hXIuh~CjP?BL1p6f303qZUL|cl3a6oGp@uB;ntV=wi32o5Um;t(3Jq+0 z@EK@@TzD2DV4}_n8L*HAVFMhbCuqOXBQ1(33Zf7Dpa_aWP()3-LpDQ=Q?yWM8B9>z zy9)XN{el)j%jhSxY0;v8(W2vRR?qXk=RNQGyMAwSRT)kD#IBw-gs-oAcD-decEPhu zmpNC$SI?Yduh|fMQAzgsz5l6#w~LnG4@!U3k63P{-mJQ=;IGOsKOh-}qGiEglz(f9 zpy}GDLLq_eQD_WCke$#8ZabkQrzF8sFc_pV48WwkC*@BLy-i~L4Q6rCHA>9D%3yFt z44KAZ0hjr3ntzZqECsGXoUmmX=3q4_@4^%c=uhDp*pf{0n5M%H`n($FZ(#%Wq-S9t z`KS)@AJu?E={YDOe}k?hJqHzJNsG%}O?nm@$Xjg+81hA%fK%kRmIqrh!Oe&c=Zro) zPs1hRD>Zk`=&jfA=|ORCt+KMQwz9psTM%WDX^RZgd{T3qreHmOq~=-8mSwwwMOg=b MZ^k1x^4Bx}0BJ;wW&i*H diff --git a/generated_examples/napari/napari_img_math.ipynb b/generated_examples/napari/napari_img_math.ipynb index 057a3925a..02811487e 100644 --- a/generated_examples/napari/napari_img_math.ipynb +++ b/generated_examples/napari/napari_img_math.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/napari/napari_img_math/index.html b/generated_examples/napari/napari_img_math/index.html index 225973bd4..353ff31ba 100644 --- a/generated_examples/napari/napari_img_math/index.html +++ b/generated_examples/napari/napari_img_math/index.html @@ -3387,7 +3387,7 @@

Code napari.run() -

Total running time of the script: ( 0 minutes 2.262 seconds)

+

Total running time of the script: ( 0 minutes 2.432 seconds)

Download Python source code: napari_img_math.py

diff --git a/generated_examples/napari/napari_img_math_codeobj.pickle b/generated_examples/napari/napari_img_math_codeobj.pickle index fbd81e0a4e7687db8d520c2a0881f18a387470d9..c49aee8b1eb23b4b0d2f1e5a47307eb7e74c073c 100644 GIT binary patch delta 1564 zcmY+DZD?Cn7{`~Kn{)DZdz0op>091d&DM5Jo6ZGwZb*wSvr5@uDAcS8J2|FlXcKLx zla_(lai`RiF;S;(DEeVTiZXR$qKNpxFFNppU#ubuf-ou*24muL@5x!ZFFC*8|9Q?i z_vD^?Hve5-S+9?qSuO*HAROMfIm%%jGB>YahvM3Ij z=8AXVYN1w`FE^=+rXUKqhtNGRPPoUQ@kS`C&@AZJj;NBO>MQ(BM+)UdfbNI!M(3jn z-48JC8-@v|oGW+jG6fabMccB=A*!zO$HRFm3_pgt6gmw(FS$qJMJP0mH~T5k(R`!Y zqz-+{w4=~<%{`1NFk-bA&B3_n+Yh__5b9RwBIt(CINXrm2seCTe$ww$=m{un`eXc( zKM(Pye}_U(wxS0DP(KAS8F&h6lYwsT4tNyWG}a1iSLhi4HFyweYB0iI3=X#Fj}9+7 zZ`LAWlMg^_p%EzW2_+PI0rW^{FX;IYEb|E{JY*-mWSp?1JF1P@+R|X5Smc|I9(0AO zYcE96m(X?8vVx$6ziLTw&Dwv5H>@i99_m%=W3Xt|n&L)s4U+5D0rV4$!%BufjK-mA z&}B5*BF*Yo=&xqOZuC2hn@XJPN)r9q;>#$i(7#L>Lw~nIWA*F67i~MCIl|wwInh6+ zPoRHWxw-PqmKYOm0e_A&yk_^K|4iOPn8mVf8}JZGLhd6>k)9=t2tG&BqUMx7N|-A6 zXL2uL9?5B*w`+v?gdebv5f+r36t#%(tM(DXx+M3BTCZ^9?=znz(ROp)wD4aXyLPgS z$?`thXB(AzxmH;+E~U+Ueel7s0WqOpoiyLnJ~hUBG$&zWBEPLB__ykAcoVl(2oZbvs^4@u7vHX%7JdLI$Ku5IU2S}$P-+J08^5cY)hVZx>a*E~t?@T3Vl z)b@j(5MhUdwr zSeKYG8($OpWNaM2F0qeajfL^)w%&?)@f&w^>jS+d(#5WB{!CXVen)BspA+~|R}Q}~ zG2ye1mlVV?@7&bXU>)|y&s G4E_(LeW$7b delta 1475 zcmZ9MZD?Cn7{`};PR{AQNt&choA)+J8{5U2W{X{G8Lb_onVaH77!-9iwy`I7OFEle z#LBelz|BQ$IZ-z1R0LsI5UZjaQkXaqVP8c2GEs!Vn7C0<1jQG8?m72v;Ft6K{{QFY zoSd6`zZ^X?ikF~G*|u~KR_oW|oub*9-MmHAoY zuxW_OX2UIw=^C3~s5hC`XermGXAT!@wdM%}1~A${<~XL>EzHHd%zeTrHGJhtajrC7 zTqxIBrBpA^tc+7HG`J>VuX=gDS}@A|A8pj(Uisi|Sbj^R7<2QFwdWA@^Y67@e$dr_ zle2CQ+6ws%*S!vN?d7JE182;A2g*ZS@?`ia_atOZQayKCbkG&RY)ljkqX~$P)+GPV z(}Q*k-iZp9Ckppk!km5|@ZYTiP#or)ts2@dbOAkR`J&-~CCr8?VCu{8U%UbIu;9Be zn+7QOc3}3HfF8c;_hME8vEduRj0s3f_YjC-Ke$x^miq*Vbw5m~3$P|U38L7R5SuLu z9>nY@fO$FQ36?B|{haItcq-h3deL!kHb;zwtpI;jkxHHar;Seb`V7>nGm0)kJn!6wzJhqe*^MqiJk)+aRDIgshuOCvmjfy83Jil~QYnxTG=SNU zkaTyX`L#eCvnxUjVRqGWbDbJyKY@6rV-mCL0{ZwD*pD_X78SpOnCRSt+3x~+xPgP1 z{Q=_Z&OBy+S#CB6)BXi99^6hGjxAdRCb%c$Ay~?HgCm66m=+mL%BW)r&iwyN^HDu0 z^GW4)sz)S0fc80I8}xa}E?Do;;#41yevOzH^ttc}O;LSV`s*~x3lv@^ZqgYF zJB-ieY5sbRj>vJ)yzGO+oubLv*AAGn$KlWOq@ zyxL9X(x;?*OwB{xITg){rRG*i;sf1hf1;NL;>Ks+z zzq(h8QT=I|PlTpm(qbr0j!EN2sGDC5^^g~BIYeHvv77%Hc9EB*d?TFVi{UP^Y|A|1 zHl{@3Yf`=vfiFrVK~CS27s7t>x-AFEn-YD|1fT7^jl6Bk5%P|W30{r*$=O@dJjt4r kKS$&In`j$(&z2doE-@M#A|Kh9;w>?c>k}d2Giqf21D*Agn*aa+ diff --git a/generated_examples/napari/napari_parameter_sweep.ipynb b/generated_examples/napari/napari_parameter_sweep.ipynb index 43eaa09f1..973bd2db8 100644 --- a/generated_examples/napari/napari_parameter_sweep.ipynb +++ b/generated_examples/napari/napari_parameter_sweep.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/napari/napari_parameter_sweep/index.html b/generated_examples/napari/napari_parameter_sweep/index.html index 4f637fc59..dd68c00cc 100644 --- a/generated_examples/napari/napari_parameter_sweep/index.html +++ b/generated_examples/napari/napari_parameter_sweep/index.html @@ -3318,7 +3318,7 @@

Code napari.run() -

Total running time of the script: ( 0 minutes 2.986 seconds)

+

Total running time of the script: ( 0 minutes 3.764 seconds)

Download Python source code: napari_parameter_sweep.py

diff --git a/generated_examples/napari/napari_parameter_sweep_codeobj.pickle b/generated_examples/napari/napari_parameter_sweep_codeobj.pickle index cff1a02fcb2323dee09dfd02119ebc57ff9b5740..159524291b728e07630591b64c1c7b47271c0f04 100644 GIT binary patch delta 1374 zcmYk6O-vI(7>3#I*y+#q7g}1d{FGv~fr?a70Cw29;<*aCQP)LTQ3ADkMgO zsnKR?LX3$qo-`5;-aw;w6C--jkf<>pxZ%&q7!$vp>84y}-sk<^o%v?E+b_F5?Lsq~ z?!7Ib7#pgoOXZQ49v>;@Eu%SYcuLJ^#k_eub0IgTdqX*OY)aL##k?ZCb6Jv^oGKDq z-lAsD4UeU>*&=&f(;+GBiSIa!e|%9yf<$4n{xCb@-woER|0o~B?1$fmNCb*fbqbLv z7tO3K;6@}?0xbZMR)81PhY)GwA}S(@67Wa|z_maRBAr|`v7dozM7jZ7!2}}7lFN5Y z0bB|0K;$474Xn3DL8J#@Ew~$zUM`x2+Xt}MGXM?Gdm@OO0k%0%!DlaAL54#dkx3Bo zss?7NYDOf-0ot4{x%n!{UKX%%;j3U-eIcJ?;?jk*Hl+^7$J45&_cqHb+Yq@9qSFTl zxXDG>Z85TX>=u}V&MuQO$Lbv+nE_t5Y?tR@Ua;uD@VaZi{0J!F?gB#29r9D4J5e$wW~$`0CUoj zhX-C4uV0FAXI<|@YL$P%ESV;tBAH_BfoUhG6;o3F$Nd;&6-+CniVEOk@&Qa`LpMUY z22*pH|C*{WwU(Jbs|db>TA;n4dt9B?KOthLE~9V=Q?H?07+=I!X1+*3@cm6O_SIa8 zX|2JXnAQpHF*k`?qrvT%Mua|W-h*k>(9LW!c3~P5ysXz+4PC0W3Eqx7FijY`Nj%pf z_#sYU+G*$pQR^10Uo!7AS!TXxO7M3}3a+`%5yG@rI6YSV|6<;%`>WP4rYD6j*-n5X z*=pHVyBpI%!>#p{-vN4FxQn(kkX^KeME0WLhBjuYa9`SkY{uRV`Iq*?d%EE%(`ms2N&-^173l1maGonkaDFRMOm7GW&ZE#duHlu;#s32y%yCx$ delta 1361 zcmYk4UuaWT9LG)WNlyOU+nYa4bCdo_lQy)*{!wdN+ltn1PH_I{Bch9-k?B$-%=llDe zlat@Q&j$Yww4uYuOk;;p#PoIP1Ojkcp9saI5Kb47M`X}JbB zLt(ArSt!nZb2?Wn)>ca3Y3Kx1?^ZO6v%013n#zLFV~o#^;;?KBy6`OV&kBYUc&Yw zJPh^V#uQ;=mWclSmWcj?LiQ5&Il@#p1FMlRVTXl`5OxG%HH`O|6wm=%VV$rk6n7(T z`bt1rrqd{8GtCOH(pi-Ejd;SG0PBQ#l*PyZVR-@V@&tym9vLR=lz>i|7EoS#`;{WD z4Za~9)A6PWeBOw+5?03WPSY_|J!*z`nhfAkA7MXZ;c>JXE=5N%ejMFF*hMR9GqApf z(r?UQt>0*cx6uG$SIo1FF2b%NY#Lu9&-y-T=F);sy2|k%kVR~Q0r#2qAZmPHHM#CA-9-YS})b80JaGu}ejI{J)S#;%-}gb%8DN0TPCpt6azoYtdk z;d;n-Q27tn72g;A$WpuElY9?FxF6ZA96J8kX+(brXXag&Vn zNAwWoy*9VQh$l+<&bo`e1E2i=Hye`ahNl(QNRaXo+qYA`Px7QU1;gGDj`yl1BHmBuTbJCA0 zU9ja$P(EMxQ3Yp~w|y7oO!8k!2V7Iql%KMFl=6bj9k7$&zVGTT?zAlZI%$^^IA=S) ri}RA7lVQp)*qny@MD_8q@Rd@&+M586+CuqHBB}l|!eh_vT diff --git a/generated_examples/notebooks/magicgui_jupyter.ipynb b/generated_examples/notebooks/magicgui_jupyter.ipynb index 2ea4cd30e..4814d45cb 100644 --- a/generated_examples/notebooks/magicgui_jupyter.ipynb +++ b/generated_examples/notebooks/magicgui_jupyter.ipynb @@ -42,7 +42,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/progress_bars/mg_execution_times/index.html b/generated_examples/progress_bars/mg_execution_times/index.html index ebdc2ab24..89699f42a 100644 --- a/generated_examples/progress_bars/mg_execution_times/index.html +++ b/generated_examples/progress_bars/mg_execution_times/index.html @@ -2862,15 +2862,15 @@

Computation times#

-

00:00.172 total execution time for generated_examples_progress_bars files:

+

00:00.187 total execution time for generated_examples_progress_bars files:

+---------------------------------------------------------------------------------------------------------------+-----------+--------+ -| progress_nested (docs/examples/progress_bars/progress_nested.py) | 00:00.056 | 0.0 MB | +| progress_nested (docs/examples/progress_bars/progress_nested.py) | 00:00.059 | 0.0 MB | +---------------------------------------------------------------------------------------------------------------+-----------+--------+ -| progress_manual (docs/examples/progress_bars/progress_manual.py) | 00:00.043 | 0.0 MB | +| progress_manual (docs/examples/progress_bars/progress_manual.py) | 00:00.053 | 0.0 MB | +---------------------------------------------------------------------------------------------------------------+-----------+--------+ -| progress (docs/examples/progress_bars/progress.py) | 00:00.043 | 0.0 MB | +| progress (docs/examples/progress_bars/progress.py) | 00:00.042 | 0.0 MB | +---------------------------------------------------------------------------------------------------------------+-----------+--------+ -| progress_indeterminate (docs/examples/progress_bars/progress_indeterminate.py) | 00:00.031 | 0.0 MB | +| progress_indeterminate (docs/examples/progress_bars/progress_indeterminate.py) | 00:00.032 | 0.0 MB | +---------------------------------------------------------------------------------------------------------------+-----------+--------+

diff --git a/generated_examples/progress_bars/progress.ipynb b/generated_examples/progress_bars/progress.ipynb index 2d8fc312a..6b9581038 100644 --- a/generated_examples/progress_bars/progress.ipynb +++ b/generated_examples/progress_bars/progress.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/progress_bars/progress/index.html b/generated_examples/progress_bars/progress/index.html index ce6816e33..0c4a57841 100644 --- a/generated_examples/progress_bars/progress/index.html +++ b/generated_examples/progress_bars/progress/index.html @@ -2922,7 +2922,7 @@

Simple progress barlong_running.show(run=True) -

Total running time of the script: ( 0 minutes 0.043 seconds)

+

Total running time of the script: ( 0 minutes 0.042 seconds)

Download Python source code: progress.py

diff --git a/generated_examples/progress_bars/progress_codeobj.pickle b/generated_examples/progress_bars/progress_codeobj.pickle index d756a2953c6c0fcc3bfbe9fc996d9d2ac641b0ba..67d57d57b8cc05b55aa11e38dda502c7c696b923 100644 GIT binary patch delta 488 zcmXYuPfG$(6vff|W;AR2B}7^Is(6iOiof*_0nGaY9&2;x(`xcp;dR@%FUiu7Uk_t*O?VSnjEfref%}6;$gUmDzS_|>Ny#I0;1@g`d48YwE!{p<}YE_p%83y%E7vqJ%a=(c4tbAfgeVj}t`M2fT|Q)>jQT2MVV`S^{Rv?>K+cN`>{pcG zkaH4_P+!DF?j3VZ!3mW{0oOWnFa=di&I9ht3(iSUP#*&uK)KHH4VTDxj!{qs%|&is zBku(Zu^TEqn0I!91}s5uDaw^iCoE#9_)9cIZ>cnV--15M&&t%m=_;0JbZc5u8Gf$9 MJqG=(=-6iZA0f(*>Hq)$ delta 484 zcmXYu&q~8U5Qo`Lx~(>XLMpW?82^S^D?KPEXng>|A_#)0RE^zeo0cXK1dAYoSaPuJ zg5bs8`x1Kh;0p*|d7M79kq>4|z6P=e~ zoSU(+sOrViurAMa-XTM$Ftm^8dRj`;0*Z{pO9HqdLAy2B^qXR>3L`( zUuk&Pk)DGq;m4htX*LBL@D M<*^j&$ccM}e_~aSe*gdg diff --git a/generated_examples/progress_bars/progress_indeterminate.ipynb b/generated_examples/progress_bars/progress_indeterminate.ipynb index 4571325a2..832b6dcfa 100644 --- a/generated_examples/progress_bars/progress_indeterminate.ipynb +++ b/generated_examples/progress_bars/progress_indeterminate.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/progress_bars/progress_indeterminate/index.html b/generated_examples/progress_bars/progress_indeterminate/index.html index 8ccc0cdb1..08c5c201c 100644 --- a/generated_examples/progress_bars/progress_indeterminate/index.html +++ b/generated_examples/progress_bars/progress_indeterminate/index.html @@ -2928,7 +2928,7 @@

Indeterminate progress barlong_running.show(run=True) -

Total running time of the script: ( 0 minutes 0.031 seconds)

+

Total running time of the script: ( 0 minutes 0.032 seconds)

Download Python source code: progress_indeterminate.py

diff --git a/generated_examples/progress_bars/progress_indeterminate_codeobj.pickle b/generated_examples/progress_bars/progress_indeterminate_codeobj.pickle index 44826b545d0b27097410173759bb3edae09339cd..85371e9d967f306bd3ae955f216596775e2b8041 100644 GIT binary patch delta 617 zcmZXRQESss6vs)3 zR2I;A?~5P^iZ6TIn-9XC{Rn=5`LfS2Jh_ceKK*~^oL_QsZ_dhR?euZE&>;UC&#?t)%TJF!VkEom)H}HLqc}4rgQ041JyJEddXnG;` w1L{U2N?(Ylq9IoucIP_To~^_m#eNuNd%iN%ryrtCZ8S*sa5nv(O=;r(1;^>Tr2qf` delta 556 zcmZXRJxjwt7{^JUG)Zkl!T3_EVztH4)?g6}g6IbjL{Sg~(b~pdFtKVH5JW+6P|0Aq z178+(c64#nQE>1J2z~%(2M6)VHJi)*e$W5@$HCoK$5+RNk!Yz~j%m2IY3{I9rXMoh z7q?4}$>?>gf6SMhTE(+X<|`YXW!J53m-%WlTXRWmug*w|uUPI{*)F**qpz_fv=Nn_ z$OX`lPx6q|P1G~bY>f6&5PBM0gER$Qg4+1)r2P3q*h(;ek<5LD^u~`s@Xjbi)I7V#JqsT4P0GPO@<$qh17z?ZGqMIpp$GRKqc1AcL+YuAUqxhJtnXGF zMq<9=l&V&_>RF7$$vM^@mCV5ZTG)@123Ee6aeR<$Y%qF7uu9jJ0?r?D5$Manual progress bar

Out:

-
<FunctionGui manual(pbar: magicgui.widgets.ProgressBar = ProgressBar(value=<function match_type.<locals>.<lambda> at 0x136701260>, annotation=<class 'magicgui.widgets.ProgressBar'>, name='pbar'), increment: bool = 1)>
+
<FunctionGui manual(pbar: magicgui.widgets.ProgressBar = ProgressBar(value=<function match_type.<locals>.<lambda> at 0x131416de0>, annotation=<class 'magicgui.widgets.ProgressBar'>, name='pbar'), increment: bool = 1)>
 


-

Total running time of the script: ( 0 minutes 0.043 seconds)

+

Total running time of the script: ( 0 minutes 0.053 seconds)

Download Python source code: progress_manual.py

diff --git a/generated_examples/progress_bars/progress_manual_codeobj.pickle b/generated_examples/progress_bars/progress_manual_codeobj.pickle index aa09641ce3404409a7f40c423351a2df90176b91..0a00495d595bffee150e524ec569991ca2ec4486 100644 GIT binary patch delta 446 zcmY+=u}d3q6bEo#lDnk2JB^wM^=L>?OCm`O4P7d1(Um)^mNM7 zt#I0e?{z8!G6+I9hZaF4E+RTe>*!z|75@R3(%)StmoFc9-v^JkBk#zK(WezfHA!&cQvbNT=5?$jJos) zhJTi19Qq$q6#2j)gupo^UEKvGN+I;%FO8u)I7QD{4x=8FY24L8FhZ|fIn7DD5C-u@ z2-7rEj%H93vSMD7KAY@3&2LGV72-69U&0fbXBovaDMW9uEJiWH))tsDw1lr>mfqn= zOp%JX^bn#HCXFdcEAGKgS7%DoDq?(&*6^AiLdVbbs+N$i8pWzwtG!gJ&SRSGe%x_M zyyXJ8=0eS%5`99O~nEC#U(f4F*E-Fm&=iF delta 422 zcmYk%T|{JY7zS`popWaDbTZOt>*!0hCT7mG#jd(aQeE}6L>EJ+I?c?Qk2SN$Xw?!+ z%23mDNJKb#*q1b;@tLR{H*)dWsP!pZ_-Zhry{h#7E1Z}b z^KsOB4_&0r9!*07-<0e8SayMSp#Xvmt4;h|{smpGYE?hp3Wd+(d+OPXG0bxVud%@9k`_MT2FtE~Ng7u9Sn`Z5{w^KDw#YUPOFDL3tx10Dx+-q& z(I>ZXO0LGfP!|r^FL&UOwj9JUcjZo;@>Vu*#&=2syFJzTCS>58b4mv;xTys3oj;Ti WF8N1k$4~dV;@*`|$b0R6W*aZKZi(9f diff --git a/generated_examples/progress_bars/progress_nested.ipynb b/generated_examples/progress_bars/progress_nested.ipynb index 2a799acc6..c42c4499e 100644 --- a/generated_examples/progress_bars/progress_nested.ipynb +++ b/generated_examples/progress_bars/progress_nested.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/progress_bars/progress_nested/index.html b/generated_examples/progress_bars/progress_nested/index.html index 071b3e3fd..0bc3f5b8e 100644 --- a/generated_examples/progress_bars/progress_nested/index.html +++ b/generated_examples/progress_bars/progress_nested/index.html @@ -2931,7 +2931,7 @@

Nested progress barslong_function.show(run=True)

-

Total running time of the script: ( 0 minutes 0.056 seconds)

+

Total running time of the script: ( 0 minutes 0.059 seconds)

Download Python source code: progress_nested.py

diff --git a/generated_examples/progress_bars/progress_nested_codeobj.pickle b/generated_examples/progress_bars/progress_nested_codeobj.pickle index 695cc52740798f93599b7c07ea8375f2c04c2e50..1f1d1100c607dce70abca872340883bb7b2fb6a4 100644 GIT binary patch delta 709 zcmYL{-)qxQ6vt`L&Cewuu0ylVV&d{CTE z3K7=cpa_Bt6h#Jm7=k{?eDcvf_G#d&5B>|{xoO0ge7@gv&i9ggxILq1tXt>yH`|_5 zT@1Z?;I=)>r|s4FPF#E#7bD`;T6P@mtEA1@(CzmlvDI#bO*`)VGEYWY-&8TW65x2N z=D2kSXII^ZV+Vd5$*y0mH*3BhGc$8JqvQ7wJ1gjrqdMD>@@y+p#41<3n#U?+$Dn{T z!DLsn6`n!$1@i1i*66z~$q{-ynX#aZ+<=2@3C>`519$>`m+*smgC9JNLpMnUW)dD@ zUr8P=r1}pTf=j99v$Lqz1e5IwIk=MO3Am2@Bv{%Fsy_>HLsW`%))7p&g^fY+6x>Eu z#4^kwKZql23B&V=E<+XB6D?Rk%F+q2kyBC$D6%dcgS$w+0iN*^U4mugZ)qCtBTI4t z9v~;x1-#NrwFpnpZ4MOJPxT^JxZ2K6rpncZ;Ca$7!8&qHGgv?jrfDj$)Nf~p34M_o z9(a}LqwpH}Q5%Oh$anI2^X>op3VzeJ@5NM!NZ{h@pab+hPF<5HU=#UR9)&HWsLYJ& zPtzTdV7bxa5&7TK;IYp*wy2Eb|3=C%?4a9I4zO>^2v+u#!|=3%fsh(7t^qwfPj5C(z|10NhR{|`O)Cg@APpYy%na}T*^C%=i>@ z@It1<*3y^J;WSSQOwAPHDz6-ZEs>dk&!|l$k2|fxmzepMzQ)Y6+k%h5H`LooJ^h{k Io8eFW1<1JA_W%F@ diff --git a/generated_examples/under_the_hood/class_method.ipynb b/generated_examples/under_the_hood/class_method.ipynb index fe79f89c4..50639b127 100644 --- a/generated_examples/under_the_hood/class_method.ipynb +++ b/generated_examples/under_the_hood/class_method.ipynb @@ -46,7 +46,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.2" + "version": "3.12.1" } }, "nbformat": 4, diff --git a/generated_examples/under_the_hood/class_method_codeobj.pickle b/generated_examples/under_the_hood/class_method_codeobj.pickle index 65196bc75a52e7e617b44e989a266bded49e6cba..92168c1a7483e63a5d756fc4b19473bc6f12cd5c 100644 GIT binary patch delta 448 zcmW-bT}V@L7{-16+xggb&US{Ty42`Cllr?~DE> zflRUemTziwi2YVtxRrcqC4_79Z6JqQmV!|_z8-D_FY#5VhM$7HXpqxpH1jlcf!9L2 z=-{zY$2MaU*UMHsw}sm+ErlN5H={fcr|FpW=wsfD;T}Jj4h9$wk6@6`Bp>ld*ui7o zh&&W-jz1$+T#DQl?zpGxfkq|+PXl?^m>L}}=ox;+vO4P}u82v@v&;7v3zBg@@SFI^ zPUWI}rAvFzEdQiBy~9a!^n`C^@eYCAS0KS!7}~> Dh0&L4 delta 456 zcmXZYJ4ho@7zN;*IFHOalTnOlFgqBdg0Co~u@b~aC2C<|VOUIjWEc?yjSvjJKu~<( za9D(`cFPs3WknFTSr)-U5$ptI3mbQ>>_iZ+qs`BE&i#vf?~mv~R9cch@3~T=7U;_l zWSsHQS+}iQS<9t20~y|#zx;NXF*5;+LuRcOwe|Jf_$D$uGHYbJUPRuSzx{TC1+!7L z+h5PqJPItJli#!$Q`#kxo_ciy15AH-#wU&xcOxxk9nXuaFy_hB%aQf;y6JF7k8xfP zVM-{0Y5vjcF~f)v@!C0|X5?8gEH4*?;#lO3$frgKD?)LsvLpDmzb4d-4NeAIuq|eo zUyKsC3~C?wHyEO!SzfctygI9WeS4iJ{{RoAhf=}G2wq-(&ojKkFqh_~`N85Zqdw+n z`PY-S>jX!0*|a@nm9pvSjO*x=g>*4zyL^Va@%*MY~}37le3sj@iCd11=M2!968 z@q$~THS#he7K^qcCW`qt)7e7adYdVf+;O+9{NJRZ)s|;!comG%g9jW6gqatO(oL{A zVl>`2uZ%iAgg}li5-9Kpe=#d(T(xsNtZLwm=QkYYv=(`79PgDzG!q}C`mv<)nI^Ez zA6gGq<&1Mo4`H3d-cD?=|X@iJrm% g|LE;FRxchf!uTSU!dJdCy6}ykjb`6>^$SJo7Cmo^=Kufz delta 424 zcmXYrO-mb57=<}WIvHo?)_}<(O*5$RtB}MHDF_82P*f~}AP9m|S{<2ConY(uv2f$A zWu%5PJE5&mC+07S51{Gz2k-~FjCx*ZXg_+~5nZ%g10gSU^ zmM|gtm?blTNq#oVn3A-4EAupAl`$h}Qx^%mDbUh8qv8$;Ilt^OlEEo4>Ve{lLZ+`_WPVdyeg-9{s)NPgFyfQ diff --git a/scripts/__pycache__/_hooks.cpython-312.pyc b/scripts/__pycache__/_hooks.cpython-312.pyc index 29f5e29e000d2b1640e9bc1dae645157e2c1c98f..e616de4863403a655491ebe9fdf6358f837c10b5 100644 GIT binary patch delta 19 ZcmZqkZ}aCm&CAQh00dKGHgeUd0{}D^1oHp@ delta 19 YcmZqkZ}aCm&CAQh00e>&8@X!K0Wj+XYXATM diff --git a/search/search_index.json b/search/search_index.json index 7a9ebad88..96683a924 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"magicgui \ud83e\uddd9","text":"

magicgui is a python library for building graphical user interfaces (GUIs).

It aims to speed up data workflows by providing a simple, consistent API for creating GUIs to control various data types, that work across various environments.

GUIs may be built manually using a variety of widgets, or generated automatically from python type hints.

"},{"location":"#magicgui-organization","title":"magicgui organization","text":"

magicgui can be thought of as performing two distinct tasks:

  1. Providing an simplified abstraction layer for GUI frameworks, allowing you to use the same API to create UIs that can move between environments and frameworks (such as a desktop app, or a Jupyter notebook).
  2. Providing a mapping of python types to widgets, allowing you to autogenerate graphical user interfaces for functions and dataclasses by annotating with standard python type hints.

While there is some degree of customizeability, the emphasis is on rapid development of relatively simple GUIs, with minimal boilerplate. For highly customized GUIs with complex layouts, it may be more appropriate to use a lower-level GUI framework.

The API is organized into 2 main levels:

magicgui API layers"},{"location":"#python-type-mapping","title":"Python Type Mapping","text":"

At its highest level, magicgui provides a mapping of Python types to widgets. This API allows you to create graphical user interfaces for your functions and dataclasses simply by annotating them with standard python type hints.

Type hints??

Type hints are a way to annotate your code with information about the types of variables and function arguments. They are completely optional, but static type checkers and other libraries (like magicgui!) can use them to check your code and/or provide additional functionality.

Typically, they are provided after a colon following a variable name or function argument.

In the example below, param_a has been annotated as an int, param_b as a str, and the return value as a list.

def my_function(param_a: int, param_b: str) -> list:\n    ...\n

If you are new to type annotations in Python, here are a few resources to get you started:

  • PEP 484 - the Python Enhancement Proposal that introduced type hints to the language. (See also: PEP 483)
  • Python docs - the official Python documentation on type hints and the typing module.
  • The mypy documentation also has a lot of useful information, including this cheat sheet
"},{"location":"#create_widget","title":"create_widget","text":"

magicgui.widgets.create_widget is a general function, used throughout the library, that allows you to create a widget for a specific Python type or value:

from magicgui.widgets import create_widget\n\n# passing a type to create_widget\nwidget = create_widget(annotation=int)\nwidget.show()\n

# passing a value to create_widget\nwidget2 = create_widget(value=\"Hello World\")\nwidget2.show()\n

For more details on how magicgui maps types to widgets, see Type Mapping.

"},{"location":"#magicgui_1","title":"magicgui","text":"

The magicgui.magicgui function is one way to autogenerate a compound Widget based on the parameters of a function:

from typing import Annotated, Literal\n# for Python <= 3.8\n# from typing_extensions import Annotated\n# for Python <= 3.7\n# from typing_extensions import Annotated, Literal\n\nfrom magicgui import magicgui\n\n\n@magicgui\ndef my_function(\n    param_a: int,\n    param_b: Annotated[int, {'widget_type': \"Slider\", 'max': 100}] = 42,\n    param_c: Literal[\"First\", \"Second\", \"Third\"] = \"Second\"\n):\n    print(\"param_a:\", param_a)\n    print(\"param_b:\", param_b)\n    print(\"param_c:\", param_c)\n\n# my_function now IS a widget, in addition to being a callable function\nmy_function.show()\n

For more details on using magicgui and magic_factory, see the magicgui decorators page.

"},{"location":"#guiclass","title":"guiclass","text":"

magicgui.experimental.guiclass is a newer experimental feature that provides an object-oriented alternative to magicgui. It wraps dataclasses.dataclass and adds a gui attribute to the resulting class, which is a magicgui-generated widget that can be used to control the dataclass instance. (The widget is only created when the gui attribute is accessed for the first time.)

from magicgui.experimental import guiclass, button\n\n@guiclass\nclass MyDataclass:\n    a: int = 0\n    b: str = 'hello'\n    c: bool = True\n\n    @button\n    def compute(self):\n        print(self.a, self.b, self.c)\n\nobj = MyDataclass(a=10, b='foo')\nobj.gui.show()\n

For more details on using the guiclass decorator, see Dataclasses & guiclass.

"},{"location":"#widgets","title":"Widgets","text":"

At the lower level, magicgui is a library of widgets (the individual elements that make up a graphical user interface). Each widget is customized to display and interact with a specific type of data. In some cases, it makes more sense to create and arrange these widgets manually, rather than using the type-based autogeneration features described above.

Magicgui acts as an abstraction layer for a variety of different GUI toolkits, allowing you to use the same API to create UIs that can move between environments (such as a desktop app, or a Jupyter notebook).

Currently, magicgui supports the following backends:

  • Qt (via PySide2/PySide6 or PyQt5/PyQt6)
  • Jupyter Widgets (a.k.a. \"IPyWidgets\")

You can use magicgui.widgets to quickly build graphical user interfaces.

from magicgui import widgets\n\na = widgets.SpinBox(value=10, label=\"a\")\nb = widgets.Slider(value=20, min=0, max=100, label=\"b\")\nresult = widgets.LineEdit(value=a.value * b.value, label=\"result\")\nbutton = widgets.PushButton(text=\"multiply\")\n\n@button.clicked.connect\ndef on_button_click():\n    result.value = a.value * b.value\n\ncontainer = widgets.Container(widgets=[a, b, result, button])\ncontainer.show()\n

To learn more about the available widgets and how to use them, see the Widgets Overview.

...details

Behind the scenes, magicgui declares a set of WidgetProtocols that each backend must implement, and every magicgui Widget is a wrapper around a backend-specific widget. Most users will never need to worry about this, but it's good to know that it's there if you ever need to dig deeper.

"},{"location":"#events","title":"Events","text":"

All widgets (whether created directly or autogenerated based on type hints) emit events when their value changes or in response to interaction.

To learn about connecting custom functionality to these events, see Events.

"},{"location":"#installation","title":"Installation","text":"

See installing magicgui.

"},{"location":"CONTRIBUTING/","title":"Contributing","text":"

Contributions are welcome!

"},{"location":"CONTRIBUTING/#development","title":"Development","text":"

To install magicgui for development, first clone the repository:

git clone https://github.com/pyapp-kit/magicgui\ncd magicgui\n

Then install the package in editable mode with the dev extra:

pip install -e .[dev]\n

To run the tests:

pytest\n
"},{"location":"CONTRIBUTING/#code-quality","title":"Code Quality","text":"

magicgui attempts to adhere to strict coding rules and employs the following static analysis tools to prevent errors from being introduced into the codebase:

  • black - code formatting
  • ruff - linting
  • mypy - static type analysis
  • codecov - test coverage

To prevent continuous integration failures when contributing, please consider installing pre-commit in your environment to run all of these checks prior to checking in new code.

pre-commit install\n

To run the checks manually, you can use:

pre-commit run --all-files\n
"},{"location":"CONTRIBUTING/#adding-a-widget","title":"Adding a widget","text":"

These instructions may change in the future as the repo structures changes. If they appear outdated as you follow them, please open an issue.

To add a new widget, you will need to:

  1. Create a new class in magicgui/widgets/_concrete.py that inherits from the base class most appropriate for your widget (e.g. ValueWidget, or CategoricalWidget).

    In some (complex) cases, you may need to extend one of the base classes. If so, it is likely that you will also need to extend one of the Protocols found in magicgui.widgets.protocols. This is where all of protocols that backend classes need to implement to work with a given widget type. (Don't hesitate to open an issue if you're confused).

  2. Most likely, you will want to decorate the class with @backend_widget. Using this decorator implies that there is a class with the same name in any any backend modules that will support this widget type (e.g. magicgui.backends._qtpy.widgets for Qt support.).

  3. Make any changes necessary to your new concrete class. For example, you may need to change the value property and corresponding setter to handle a specific type. This part of the code should be backend agnostic.
  4. Export the new class in magicgui/widgets/__init__.py so that it can be imported from magicgui.widgets.
  5. Implement the backend widget class (using the same class name) in the appropriate backend module (e.g. magicgui.backends._qtpy.widgets for Qt support). Usually this will mean implementing the appropriate _mgui_get/set_... methods for the Protocol of the corresponding widget base class your chose to extend.
  6. Export the backend widget class in the __init__.py of the backend module (e.g. magicgui.backends._qtpy.__init__.py for Qt support). This is important, as that is where the @backend_widget decorator will look.
  7. Add a test for your new widget.

For an example of a minimal PR adding a new widget, see #483, which added a QuantityWidget to be used with pint.Quantity objects.

"},{"location":"CONTRIBUTING/#associating-a-widget-with-a-type","title":"Associating a widget with a type","text":"

To associate your new widget with a specific type such that it will be used when someone annotates a parameter with that type, you will need to update code in magicgui.type_map._type_map.

In the simplest of cases, this will mean adding a new entry to the magicgui.type_map._type_map._SIMPLE_TYPES dict. This is a mapping from a python type to a widget class. (Note that all subclasses of the type will also be matched.)

For more complex cases, you can add a new conditional to the body of the match_type function. That function should always return a tuple of widget type, and kwargs that will be passed to the widget constructor. For example: return widgets.MyNewWidget, {}.

"},{"location":"CONTRIBUTING/#building-the-documentation","title":"Building the documentation","text":"

To build the documentation locally, you will need to install the docs extra:

pip install -e .[docs]\n

Then, from the root of the repository, run:

mkdocs serve\n

This will start a local server at http://127.0.0.1:8000/ where you can view the documentation as you edit it.

"},{"location":"dataclasses/","title":"Dataclasses & guiclass","text":""},{"location":"dataclasses/#what-are-dataclasses","title":"What are dataclasses?","text":"

dataclasses are a feature added in Python 3.7 (PEP 557) that allow you to simply define classes that store a specific set of data. They encourage clear, type-annotated code, and are a great way to define data structures with minimal boilerplate.

New to dataclasses?

If you're totally new to dataclasses, you might want to start with the official documentation for the dataclasses module, or this Real Python post on dataclasses. The following is a very brief example of the key features:

Example dataclass
from dataclasses import dataclass\n\n@dataclass  # (1)!\nclass Person:\n    name: str # (2)!\n    age: int = 0  # (3)!\n\np = Person(name='John', age=30)  # (4)!\nprint(p) # (5)!\n
  1. The @dataclass decorator is used to mark a class as a dataclass. This will automatically generate an __init__ method with a parameter for each annotated class attribute.
  2. Attribute names are annotated with types. Note that, as with all Python type hints, these have no runtime effect (i.e. no validation is performed).
  3. Optional attributes can be defined with a default value. If no default value is specified, then the field is required when creating a new object.
  4. Creating a new object is as simple as passing in the required arguments.
  5. The __repr__ method is automatically generated and will print out the class name and all of the attributes and their current values.
"},{"location":"dataclasses/#dataclass-patterns-outside-the-standard-library","title":"dataclass patterns outside the standard library","text":"

The dataclasses module is not the only way to define data-focused classes in Python. There are other libraries that provide similar functionality, and some of them have additional features that are not available in the standard library.

  • attrs is a popular library that provides a number of additional features on top of the standard library dataclasses, including complex validation and type conversions.
  • pydantic is a library that provides runtime type enforcement and casting, serialization, and other features.
  • msgspec is a fast serialization library with a msgspec.Struct that is similar to a dataclass.
"},{"location":"dataclasses/#magicgui-guiclass","title":"magicgui guiclass","text":"

Experimental

This is an experimental feature. The API may change in the future without deprecations or warnings.

magicgui supports the dataclass API as a way to define the interface for compound widget, where each attribute of the dataclass is a separate widget. The magicgui.experimental.guiclass decorator can be used to mark a class as a \"GUI class\". A GUI class is a Python standard dataclass that has two additional features:

  1. A property (named \"gui\" by default) that returns a Container widget which contains a widget for each attribute of the dataclass.
  2. An property (named \"events\" by default) that returns a psygnal.SignalGroup object that allows you to connect callbacks to the change event of any of field in the dataclass. (Under the hood, this uses the @evented dataclass decorator from psygnal.)

Tip

You can still use all of the standard dataclass features, including field values, __post_init__ processing, and ClassVar.

Info

In the future, we may also support other dataclass-like objects, such as pydantic models, attrs classes, and traitlets classes.

from magicgui.experimental import guiclass\n\n@guiclass\nclass MyDataclass:\n    a: int = 0\n    b: str = 'hello'\n    c: bool = True\n\nobj = MyDataclass()\nobj.gui.show()\n

The individual widgets in the Container may be accessed by the same name as the corresponding attribute. For example, obj.gui.a will return the SpinBox widget that controls the value of the a attribute.

"},{"location":"dataclasses/#two-way-data-binding","title":"Two-way data binding","text":"

As you interact programmatically with the obj instance, the widgets in the obj.gui will update. Similarly, as you change the value of the widgets in the obj.gui, the values of the obj instance will be updated.

obj = MyDataclass(a=10)\nobj.b = 'world'\nobj.c = False\n\nobj.gui.show()\n

All magicgui-related stuff is in the gui attribute

The original dataclass instance (obj) is essentially untouched. Just as in a regular dataclass, obj.a returns the current value of a in the dataclass. The widget for the class will be at obj.gui (or whatever name you specified in the gui_name parameter) So, obj.gui.a.value, returns the current value of the widget. Unless you explicitly disconnect the gui from the underlying object/model, the two will always be in sync.

"},{"location":"dataclasses/#adding-buttons-and-callbacks","title":"Adding buttons and callbacks","text":"

Buttons are one of the few widget types that tend not to have an associated value, but simply trigger a callback when clicked. That is: it doesn't often make sense to add a field to a dataclass representing a button. To add a button to a guiclass, decorate a method with the magicgui.experimental.button decorator.

positioning buttons

Currently, all buttons are appended to the end of the widget. The ability to position the button in the layout will be added in the future.

Any additional keyword arguments to the button decorator will be passed to the magicgui.widgets.PushButton constructor (e.g. label, tooltip, etc.)

from magicgui.experimental import guiclass, button\n\n@guiclass\nclass Greeter:\n    first_name: str\n\n    @button\n    def say_hello(self):\n        print(f'Hello {self.first_name}')\n\ngreeter = Greeter('Talley')\ngreeter.gui.show()\n

clicking the \"say_hello\" button will print \"Hello Talley\" to the console

Tip

As your widget begins to manage more internal state, the guiclass pattern becomes much more useful than the magicgui decorator pattern -- which was designed with pure functions that take inputs and return outputs in mind.

"},{"location":"decorators/","title":"magicgui & magic_factory","text":""},{"location":"decorators/#from-object-to-gui","title":"From Object to GUI","text":"

The eponymous feature of magicgui is the magicgui.magicgui function, which converts an object into a widget.

Info

Currently, the only supported objects are functions, but in the future magicgui.magicgui may accept other objects, such as dataclass instances

When used to decorate a function, @magicgui will autogenerate a graphical user interface (GUI) by inspecting the function signature and adding an appropriate GUI widget for each parameter, as described in Type Hints to Widgets. Parameter types are taken from type hints, if provided, or inferred using the type of the default value otherwise.

import math\nfrom enum import Enum\nfrom magicgui import magicgui\n\n# dropdown boxes are best made by creating an enum\nclass Medium(Enum):\n    Glass = 1.520\n    Oil = 1.515\n    Water = 1.333\n    Air = 1.0003\n\n# decorate your function with the @magicgui decorator\n@magicgui(call_button=\"calculate\")\ndef snells_law(aoi=30.0, n1=Medium.Glass, n2=Medium.Water, degrees=True):\n    aoi = math.radians(aoi) if degrees else aoi\n    try:\n        result = math.asin(n1.value * math.sin(aoi) / n2.value)\n        return math.degrees(result) if degrees else result\n    except ValueError:\n        # beyond the critical angle\n        return \"Total internal reflection!\"\n\nsnells_law.show()\n

The object returned by the magicgui decorator is an instance of magicgui.widgets.FunctionGui. It can still be called like the original function, but it also knows how to present itself as a GUI.

"},{"location":"decorators/#two-way-data-binding","title":"Two-Way Data Binding","text":"

The modified snells_law object gains attributes named after each of the parameters in the function. Each attribute is an instance of a magicgui.widgets.Widget subclass (suitable for the data type represented by that parameter). As you make changes in your GUI, the attributes of the snells_law object will be kept in sync. For instance, change the first dropdown menu from \"Glass\" to \"Oil\", and the corresponding n1 object on snells_law will change its value to 1.515:

snells_law.n1.value  # 1.515\n

It goes both ways: set a parameter in the console and it will change in the GUI:

snells_law.aoi.value = 47\nsnells_law.show()\n

"},{"location":"decorators/#its-still-a-function","title":"It's still a function","text":"

magicgui tries very hard to make it so that the decorated object behaves as much like the original object as possible.

We can invoke the function in a few ways:

  • Because we provided the call_button argument to the magicgui decorator, a new button was created that will execute the function with the current gui parameters when clicked.

  • We can call the object just like the original function.

    snells_law()        # 34.7602\nsnells_law(aoi=12)  # 13.7142\n

    Now however, the current values from the GUI will be used as the default values for any arguments that are not explicitly provided to the function.

    snells_law.aoi.value = 12\nsnells_law()  # 13.7142\nsnells_law(aoi=30)  # 34.7602\n

    In essence, your original function now has a \"living\" signature whose defaults change as the user interacts with your GUI.

    import inspect\n\ninspect.signature(snells_law)\n# <MagicSignature(\n#   aoi=12.0, n1=<Medium.Glass: 1.52>, n2=<Medium.Water: 1.333>, degrees=True\n# )>\n# notice how the default `aoi` is now 12 ... because we changed it above\n
  • You can still override positional or keyword arguments in the original function, just as you would with a regular function.

    Note

    calling the function with values that differ from the GUI will not set the values in the GUI... It's just a one-time call.

    # in radians, overriding the value for the second medium (n2)\nsnells_law(0.8, n2=Medium.Air, degrees=False)  # 'Total internal reflection!'\n
"},{"location":"decorators/#connecting-events","title":"Connecting Events","text":""},{"location":"decorators/#function-calls","title":"Function Calls","text":"

With a GUI, you are usually looking for something to happen as a result of calling the function. The function will have a new called attribute that you can connect to an arbitrary callback function:

@snells_law.called.connect\ndef my_callback(value: str):\n    # The callback receives an `Event` object that has the result\n    # of the function call in the `value` attribute\n    print(f\"Your function was called! The result is: {value}\")\n\nresult = snells_law()\n

Now when you call snells_law(), or click the calculate button in the gui, my_callback will be called with the result of the calculation.

"},{"location":"decorators/#parameter-changes","title":"Parameter Changes","text":"

You can also listen for changes on individual function parameters by connecting to the <parameter_name>.changed signal:

# whenever the current value for n1 changes, print it to the console:\n@snells_law.n1.changed.connect\ndef _on_n1_changed(x: Medium):\n    print(f\"n1 was changed to {x}\")\n\nsnells_law.n1.value = Medium.Air\n

Note

This signal will be emitted regardless of whether the parameter was changed in the GUI or via by directly setting the paramaeter on the gui instance.

"},{"location":"decorators/#usage-as-a-decorator-is-optional","title":"Usage As a Decorator is Optional","text":"

Remember: the @decorator syntax is just syntactic sugar. You don't have to use @magicgui to decorate your function declaration. You can also just call it with your function as an argument:

This decorator usage:

@magicgui(auto_call=True)\ndef function():\n    pass\n

is equivalent to this:

def function():\n    pass\n\nfunction = magicgui(function, auto_call=True)\n

In many cases, it will actually be desirable not to use magicgui as a decorator if you don't need a widget immediately, but want to create one later (see also the magic_factory decorator.)

# some time later...\nwidget_instance = magicgui(function)\n
"},{"location":"decorators/#magic_factory","title":"magic_factory","text":"

The magicgui.magic_factory function/decorator acts very much like the magicgui decorator, with one important difference:

Unlike magicgui, magic_factory does not return a widget instance immediately. Instead, it returns a \"factory function\" that can be called to create a widget instance.

This is an important distinction to understand. In most cases, the @magicgui decorator is useful for interactive use or rapid prototyping. But if you are writing a library or package where someone else will be instantiating your widget (a napari plugin is a good example), you will likely want to use magic_factory instead, (or create your own Widget Container subclass).

it's just a partial

If you're familiar with functools.partial, you can think of magic_factory as a partial function application of the magicgui decorator (in fact, magic_factory is a subclass of partial). It is very roughly equivalent to:

def magic_factory(func, *args, **kwargs):\n    return partial(magicgui, func, *args, **kwargs)\n
"},{"location":"decorators/#widget_init","title":"widget_init","text":"

magic_factory gains one additional parameter: widget_init. This accepts a callable that will be called with the new widget instance each time the factory is called. This is a convenient place to add additional initialization or connect events.

from magicgui import magic_factory\n\ndef _on_init(widget):\n    print(\"widget created!\", widget)\n    widget.y.changed.connect(lambda x: print(\"y changed!\", x))\n\n@magic_factory(widget_init=_on_init)\ndef my_factory(x: int, y: str): ...\n\nnew_widget = my_factory()\n
"},{"location":"decorators/#the-lack-of-magic-in-magicgui","title":"The (lack of) \"magic\" in magicgui","text":"

Just to demystify the name a bit, there really isn't a whole lot of \"magic\" in the magicgui decorator. It's really just a thin wrapper around the magicgui.widgets.create_widget function, to create a Container with a sub-widget for each parameter in the function signature.

The widget creation is very roughly equivalent to something like this:

from inspect import signature, Parameter\nfrom magicgui.widgets import create_widget, Container\nfrom magicgui.types import Undefined\n\n\ndef pseudo_magicgui(func: 'Callable'):\n    return Container(\n        widgets=[\n            create_widget(p.default, annotation=p.annotation, name=p.name)\n            for p in signature(func).parameters.values()\n        ]\n    )\n\ndef some_func(x: int = 2, y: str = 'hello'):\n    return x, y\n\nmy_widget = pseudo_magicgui(some_func)\nmy_widget.show()\n

In the case of magicgui, a special subclass of Container (FunctionGui) is used, which additionally adds a __call__ method that allows the widget to behave like the original function.

"},{"location":"events/","title":"Events","text":"

All magicgui widgets emit events when certain properties change. For each event there is a corresponding signal attribute on the widget that can be connected to a callback function. For example, a PushButton emits an event when it is clicked, and all ValueWidget subclasses (like Slider or LineEdit) emit an event when their value changes.

"},{"location":"events/#connecting-to-events","title":"Connecting to events","text":"

To connect a callback to an event, use the connect method of the signal attribute. The exact signals available on each widget are mostly defined in the base classes, and are listed on the API page for each respective widget.

For example, to connect a callback to a LineEdit widget's changed event:

Widget APImagicgui decoratormagic_factory decorator
from magicgui import widgets\n\ntext = widgets.LineEdit(value='type something')\ntext.changed.connect(lambda val: print(f\"Text changed to: {val}\"))\n
from magicgui import magicgui\n\n@magicgui\ndef my_function(text: str):\n    ...\n\nmy_function.text.changed.connect(lambda val: print(f\"Text changed to: {val}\"))\n
from magicgui import magic_factory\n\ndef _on_init(widget):\n    widget.text.changed.connect(lambda val: print(f\"Text changed to: {val}\"))\n\n@magic_factory(widget_init=_on_init)\ndef my_function(text: str):\n    ...\n\nmy_widget = my_function()\n

It's all psygnal under the hood

magicgui uses psygnal for its event system. For greater detail on the connect method and its options, see the Usage section of psygnal's documentation, or the psygnal.SignalInstance.connect API reference.

Tip

Note that connect returns the callable that it was passed, so you can use it as a decorator if you prefer.

text = widgets.LineEdit(value='type something')\n\n# this works\ntext.changed.connect(lambda val: print(f\"Text changed to: {val}\"))\n\n# so does this\n@text.changed.connect\ndef on_text_changed(val):\n    print(f\"Text changed to: {val}\")\n
"},{"location":"installation/","title":"Installation","text":"

magicgui is a pure Python package, and can be installed with pip:

pip install magicgui\n

or with conda:

conda install -c conda-forge magicgui\n
"},{"location":"installation/#backends","title":"Backends","text":"

magicgui requires a backend to be installed in order to function, but it does not specify a particular backend by default. The following backends are available:

  • PyQt5: pip install magicgui[pyqt5]
  • PyQt6: pip install magicgui[pyqt6]
  • PySide2: pip install magicgui[pyside2]
  • PySide6: pip install magicgui[pyside6]
  • Jupyter Widgets: pip install magicgui[jupyter]

Important

Note not all widgets are necessarily implemented for all backends. Most widgets in the widget docs specify which backends are supported.

"},{"location":"installation/#extras","title":"Extras","text":"

The Image widget requires pillow. You may use the image extra:

pip install magicgui[image]\n

The magicgui.tqdm module requires tqdm. You may use the tqdm extra:

pip install magicgui[tqdm]\n

The QuantityEdit widget requires pint. You may use the quantity extra:

pip install magicgui[quantity]\n
"},{"location":"type_map/","title":"Type Hints to Widgets","text":"

One of the key offerings of magicgui is the ability to automatically generate Widgets from Python type hints. This page describes how type hints are mapped to Widgets, and how to customize that mapping.

"},{"location":"type_map/#default-type-mapping","title":"Default Type Mapping","text":"

By default, The following python Type Hint annotations are mapped to the corresponding Widget class, and parametrized with the corresponding kwargs (when applicable):

Type Hint Widget __init__ kwargs bool Slider int Slider float FloatSlider str LineEdit range RangeEdit slice SliceEdit list ListEdit tuple TupleEdit pathlib.Path FileEdit os.PathLike FileEdit Sequence[pathlib.Path] FileEdit {'mode': 'rm'} datetime.time TimeEdit datetime.timedelta TimeEdit datetime.date DateEdit datetime.datetime DateTimeEdit Literal['a', 'b'] ComboBox {'choices': ['a', 'b']} Set[Literal['a', 'b']] Select {'choices': ('a', 'b')} enum.Enum ComboBox {'choices': <enum 'Enum'>} magicgui.widgets.ProgressBar ProgressBar {'bind': <function match_type.<locals>.<lambda> at 0x13e8d7ce0>, 'visible': True} types.FunctionType FunctionGui {'function': ...} pint.Quantity QuantityEdit"},{"location":"type_map/#example","title":"Example","text":"

from magicgui import widgets\nimport pathlib\nimport os\nimport datetime\nfrom typing import Literal, Set, Sequence\nimport types\nimport pint\nimport enum\n\ntypes = [\n    bool, int, float, str, range, slice, list,\n    pathlib.Path, os.PathLike, Sequence[pathlib.Path],\n    datetime.time, datetime.timedelta, datetime.date, datetime.datetime,\n    Literal['a', 'b'], Set[Literal['a', 'b']], enum.Enum,\n    widgets.ProgressBar, pint.Quantity,\n]\n\nwdg = widgets.Container(\n    widgets=[\n        widgets.create_widget(annotation=t, label=str(t)) for t in types\n    ]\n)\nwdg.show()\n

"},{"location":"type_map/#customizing-widget-options-with-typingannotated","title":"Customizing Widget Options with typing.Annotated","text":"

Widget options and types may be embedded in the type hint itself using typing.Annotated.

Note

This is not the only way to customize the widget type or options in magicgui. Some functions (like magicgui.magicgui) also accept **param_options keyword arguments that map parameter names to dictionaries of widget options.

"},{"location":"type_map/#overriding-the-default-type","title":"Overriding the Default Type","text":"

To override the widget class used for a given object type, use the widget_type key in the Annotated kwargs. It can be either the string name of one of the built-in widgets, or any Widget subclass object.

Type Hint Widget __init__ kwargs Annotated[int, {'widget_type': 'Slider'}] Slider Annotated[float, {'widget_type': 'FloatSlider'}] FloatSlider"},{"location":"type_map/#overriding-the-default-options","title":"Overriding the Default Options","text":"

Any additional kwargs will be passed to the widget constructor (and must be valid for the corresponding widget type).

Type Hint Widget __init__ kwargs Annotated[int, {'step': 10, 'max': 50}] Slider {'step': 10, 'max': 50} Annotated[int, {'choices': [1, 2, 3]}] Slider {'choices': [1, 2, 3]}"},{"location":"type_map/#examples","title":"Examples","text":"

Create a widget using standard type map:

create_widgetmagicgui decoratorguiclass decorator
my_widget = widgets.create_widget(value=42, annotation=int)\n
from magicgui import magicgui\n\n@magicgui\ndef my_widget(x: int = 42):\n    return x\n
from magicgui.experimental import guiclass\n\n@guiclass\nclass MyObject:\n    x: int = 42\n\nobj = MyObject()\nmy_widget = obj.gui\n

Customize a widget using typing.Annotated:

create_widgetmagicgui decoratorguiclass decorator
from typing import Annotated\n\nInt10_50 = Annotated[int, (('widget_type', 'Slider'),('step', 10),('max', 50))]\nwdg2 = widgets.create_widget(value=42, annotation=Int10_50)\n
from magicgui import magicgui\nfrom typing import Annotated\n\nInt10_50 = Annotated[int, (('widget_type', 'Slider'),('step', 10),('max', 50))]\n\n@magicgui\ndef my_widget(x: Int10_50 = 42):\n    ...\n
from magicgui.experimental import guiclass\nfrom typing import Annotated\n\nInt10_50 = Annotated[int, (('widget_type', 'Slider'),('step', 10),('max', 50))]\n\n@guiclass\nclass MyObject:\n    x: Int10_50 = 42\n\nobj = MyObject()\nmy_widget = obj.gui\n

Note that you may also customize widget creation with kwargs to create_widget

from typing import Annotated\nfrom magicgui.widgets import Slider\n\noptions = {'step': 10, 'max': 50}\nwdg3 = widgets.create_widget(value=42, widget_type=Slider, options=options)\nwdg3.show()\n

... or to the magicgui decorator:

@magicgui(x={'widget_type': 'Slider', 'step': 10, 'max': 50})\ndef my_widget(x: int = 42):\n    ...\n\nmy_widget.show()\n

"},{"location":"type_map/#return-type-mapping","title":"Return Type Mapping","text":"

In some cases, magicgui may be able to create a widget for the return annotation of a function.

... more to come ...

"},{"location":"type_map/#postponed-annotations","title":"Postponed annotations","text":"

Using forward references and __future__.annotations with magicgui is possible, but requires some extra care. Read on for more details.

"},{"location":"type_map/#forward-references","title":"Forward References","text":"

When a type hint contains names that have not been defined yet, that definition may be expressed as a string literal, to be resolved later. This is called a Forward Reference (see PEP 484). This is useful when you want to use a type hint that refers to a type that has not yet been defined, or when you want to avoid importing a type that is only used in a type hint.

from typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    from mymodule import MyType\n\ndef my_function(x: 'MyType') -> None:\n    ...\n
"},{"location":"type_map/#__future__annotations","title":"__future__.annotations","text":"

In Python 3.7, the __future__.annotations feature was introduced (PEP 563), which postpones the evaluation of type annotations. The effect of this is that no type annotations will be evaluated at definition time, and all type annotations will be treated as strings (regardless of whether they are enclosed in quotes or not).

from __future__ import annotations\n\nfrom typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    from mymodule import MyType\n\n# no longer necessary to use quotes around 'MyType'\ndef my_function(x: MyType) -> None:\n    ...\n

While this is a useful feature for developers, it does make it significantly more difficult to use those type annotations at runtime.

Magicgui does attempt to resolve forward references it encounters (see Resolving type hints at runtime for gory details), but this is an imperfect process, and may not always work.

"},{"location":"type_map/#if-you-must-use-postponed-annotations","title":"If You Must Use Postponed Annotations","text":"

As a general rule, if you must use forward references or __future__.annotations in a module that uses magicgui, you should:

  • don't use typing syntax that is not valid for ALL python versions you wish to support (e.g. str | int instead of Union[str, int] in python < 3.10), as these will raise an exception when magicgui attempts to evaluate them at runtime.
  • use fully qualified names for all type hints, as these will be easier for magicgui to resolve without user-supplied namespaces.

    from __future__ import annotations\n\nfrom typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    import mymodule\n\n# this is easier for magicgui to resolve\ndef my_function(x: mymodule.MyType) -> None:\n    ...\n
"},{"location":"type_map/#registering-support-for-custom-types","title":"Registering Support for Custom Types","text":"

Any third-party library may use the magicgui.register_type function to register its types with magicgui. When a registered type is used as an annotation, the registered widget will be used.

"},{"location":"type_map/#known-third-party-support-for-magicgui","title":"Known Third-Party Support for magicgui","text":"

Hi developer!

Have a library that registers types with magicgui? Let us know and we'll add it to this list!

"},{"location":"type_map/#napari","title":"napari","text":"

napari has registered a number of its types to provide access to napari-specific objects using type annotations in magicgui. Details may be found in napari's documentation on using magicgui in napari.

"},{"location":"widgets/","title":"Widgets","text":"

Tip

If you're looking for an index of all available widgets, see the Widget Index.

All individual graphical elements in magicgui are \"widgets\", and all widgets are instances of magicgui.widgets.Widget. Widgets may be created directly:

from magicgui.widgets import LineEdit\n\nline_edit = LineEdit(value='hello!')\nline_edit.show()\n

Some widgets (such as magicgui.widgets.Container) are composite widgets that comprise other widgets:

from magicgui.widgets import LineEdit, SpinBox, Container\n\nline_edit = LineEdit(value='hello!')\nspin_box = SpinBox(value=400)\ncontainer = Container(widgets=[line_edit, spin_box])\ncontainer.show()\n

magicgui provides a way to automatically select a widget given a python value or type annotation using magicgui.widgets.create_widget. Here is an example that yields the same result as the one above:

from magicgui.widgets import create_widget\n\nx = 'hello!'\ny = 400\ncontainer = Container(widgets=[create_widget(i) for i in (x, y)])\ncontainer.show()\n

Tip

Because there are often multiple valid widget types for a given python object, you may sometimes wish to create widgets directly, or use the widget_type argument in create_widget()

"},{"location":"widgets/#the-widget-hierarchy","title":"The widget hierarchy","text":"
graph TB\n    A([Widget])-->B([ValueWidget])\n    A-->C([ContainerWidget])\n    B-->D([RangedWidget])\n    B-->E([ButtonWidget])\n    B-->F([CategoricalWidget])\n    C-->H([MainWindowWidget])\n    C-->G([FunctionGui])\n    D-->I([SliderWidget])\n    click A \"#widget\"\n    click B \"#valuewidget\"\n    click C \"#containerwidget\"\n    click D \"#rangedwidget\"\n    click E \"#buttonwidget\"\n    click F \"#categoricalwidget\"\n    click H \"#mainwindowwidget\"\n    click G \"#functiongui\"\n    click I \"#sliderwidget\"

Many widgets present similar types of information in different ways. magicgui tries to maintain a consistent API among all types of widgets that are designed to represent similar objects. The general class of widget you are working with will determine the properties and attributes it has.

Note

The categories shown below are sorted by their base class (such as ValueWidget and RangedWidget). The bases are not intended to be instantiated directly. Instead, you would create the widget type you wanted, such as LineEdit or SpinBox, respectively.

"},{"location":"widgets/#widget","title":"Widget","text":"

As mentioned above, all magicgui widgets derive from magicgui.widgets.Widget and have the following attributes (this list is not comprehensive, see the magicgui.widgets.Widget API):

Attribute Type Description name str The name or \"ID\" of this widget (such as a function parameter name to which this widget corresponds). annotation Any A type annotation for the value represented by the widget. label str A string to use for an associated Label widget (if this widget is being shown in a magicgui.widgets.Container widget, and container.labels is True). By default, name will be used. Note: name refers the name of the parameter, as might be used in a signature, whereas label is just the label for that widget in the GUI. tooltip str A tooltip to display when hovering over the widget. visible bool Whether the widget is visible."},{"location":"widgets/#valuewidget","title":"ValueWidget","text":"

In addition to the base Widget properties mentioned above, the following ValueWidgets track some value:

Widget Description Label A non-editable text display. LineEdit A one-line text editor. LiteralEvalLineEdit A one-line text editor that evaluates strings as python literals. Password A one-line text editor that obscures input. TextEdit A widget to edit and display both plain and rich text. FileEdit A LineEdit widget with a button that opens a FileDialog. RangeEdit A widget to represent a python range object, with start/stop/step. SliceEdit A widget to represent slice objects, with start/stop/step. DateTimeEdit A widget for editing dates and times. DateEdit A widget for editing dates. TimeEdit A widget for editing times. Table A widget to represent columnar or 2D data with headers. QuantityEdit A combined LineEdit and ComboBox to edit a pint.Quantity. Attribute Type Description value Any The current value of the widget. changed psygnal.SignalInstance A psygnal.SignalInstance that will emit an event when the value has changed. Connect callbacks to the change event using widget.changed.connect(callback) bind Any, optional A value or callback to bind this widget. If bound, whenever widget.value is accessed, the value provided here will be returned. The bound value can be a callable, in which case bound_value(self) will be returned (i.e. your callback must accept a single parameter, which is this widget instance.). see ValueWidget.bind for details.

Here is a demonstration of all these:

from magicgui import widgets\nimport datetime\n\nwdg_list = [\n    widgets.Label(value=\"label value\", label=\"Label:\"),\n    widgets.LineEdit(value=\"line edit value\", label=\"LineEdit:\"),\n    widgets.Password(value=\"super-secret!\", label=\"Password:\"),\n    widgets.TextEdit(value=\"text edit value...\", label=\"TextEdit:\"),\n    widgets.FileEdit(value=\"/home\", label=\"FileEdit:\"),\n    widgets.RangeEdit(value=range(0, 10, 2), label=\"RangeEdit:\"),\n    widgets.SliceEdit(value=slice(0, 10, 2), label=\"SliceEdit:\"),\n    widgets.DateTimeEdit(\n      value=datetime.datetime(1999, 12, 31, 11, 30), label=\"DateTimeEdit:\"\n    ),\n    widgets.DateEdit(value=datetime.date(81, 2, 18), label=\"DateEdit:\"),\n    widgets.TimeEdit(value=datetime.time(12, 20), label=\"TimeEdit:\"),\n    widgets.QuantityEdit(value='12 seconds', label=\"Quantity:\")\n]\ncontainer = widgets.Container(widgets=wdg_list)\ncontainer.max_height = 300\ncontainer.show()\n

"},{"location":"widgets/#rangedwidget","title":"RangedWidget","text":"

RangedWidgets are numerical ValueWidgets that have a restricted range of valid values, and a step size. RangedWidgets include:

Widget Description SpinBox A widget to edit an integer with clickable up/down arrows. FloatSpinBox A widget to edit a float with clickable up/down arrows.

In addition to all of the ValueWidget attributes, RangedWidget attributes include:

Attribute Type Description min float The minimum allowable value, by default 0 max float The maximum allowable value, by default 1000 step float The step size for incrementing the value, by default 1 range tuple of float A convenience attribute for getting/setting the (min, max) simultaneously

w1 = widgets.SpinBox(value=10, max=20, label='SpinBox:')\nw2 = widgets.FloatSpinBox(value=380, step=0.5, label='FloatSpinBox:')\ncontainer = widgets.Container(widgets=[w1, w2])\ncontainer.show()\n

"},{"location":"widgets/#sliderwidget","title":"SliderWidget","text":"

SliderWidgets are special RangedWidgets that additionally have an orientation, and a readout.

Widget Description Slider A slider widget to adjust an integer value within a range. FloatSlider A slider widget to adjust an integer value within a range. LogSlider A slider widget to adjust a numerical value logarithmically within a range. ProgressBar A progress bar widget.

In addition to all of the RangedWidget attributes, SliderWidget attributes include:

Attribute Type Description orientation str The orientation for the slider. Must be either 'horizontal' or 'vertical'. by default 'horizontal' readout bool Whether to show the value of the slider. By default, True.

w1 = widgets.Slider(value=10, max=25, label='Slider:')\nw2 = widgets.FloatSlider(value=10.5, max=18.5, label='FloatSlider:')\nw3 = widgets.ProgressBar(value=80, max=100, label='ProgressBar:')\ncontainer = widgets.Container(widgets=[w1, w2, w3])\ncontainer.show()\n

"},{"location":"widgets/#buttonwidget","title":"ButtonWidget","text":"

ButtonWidgets are boolean ValueWidgets that also have some text associated with them.

Widget Description PushButton A clickable command button. CheckBox A checkbox with a text label.

In addition to all of the ValueWidget attributes, ButtonWidget attributes include:

Attribute Type Description text str The text to display on the button. If not provided, will use name.

w1 = widgets.PushButton(value=True, text='PushButton Text')\nw2 = widgets.CheckBox(value=False, text='CheckBox Text')\ncontainer = widgets.Container(widgets=[w1, w2])\ncontainer.show()\n

"},{"location":"widgets/#categoricalwidget","title":"CategoricalWidget","text":"

CategoricalWidget are ValueWidgets that provide a set of valid choices. They can be created from:

  • an enum.Enum
  • an iterable of objects (or an iterable of 2-tuples (name, object))
  • a callable that returns an enum.Enum or an iterable
  • a typing.Literal annotation.
Widget Description ComboBox A dropdown menu, allowing selection between multiple choices. RadioButtons An exclusive group of radio buttons, providing a choice from multiple choices. Select A list of options, allowing selection between multiple choices.

In addition to all of the ValueWidget attributes, CategoricalWidget attributes include:

Attribute Type Description choices Enum, Iterable, or Callable Available choices displayed in the widget. value Any In the case of a CategoricalWidget the value is the data of the currently selected choice (see also: current_choice below). current_choice str The name associated with the current choice. For instance, if choices was provided as choices=[('one', 1), ('two', 2)], then an example value would be 1, and an example current_choice would be 'one'.

choices = ['one', 'two', 'three']\nw1 = widgets.ComboBox(choices=choices, value='two', label='ComboBox:')\nw2 = widgets.RadioButtons(choices=choices, label='RadioButtons:')\nw3 = widgets.Select(choices=choices, label='Select:')\ncontainer = widgets.Container(widgets=[w1, w2, w3])\ncontainer.max_height = 220\ncontainer.show()\n

"},{"location":"widgets/#containerwidget","title":"ContainerWidget","text":"

A ContainerWidget is a list-like Widget that can contain other widgets. Containers allow you to build more complex widgets from sub-widgets. A notable example of a Container is magicgui.widgets.FunctionGui) (the product of the @magicgui decorator).

Widget Description Container A Widget to contain other widgets. MainWindow A Widget to contain other widgets, includes a menu bar. FunctionGui Wrapper for a container of widgets representing a callable object. Attribute Type Description layout str The layout for the container. Must be either 'horizontal' or 'vertical'. widgets Sequence[Widget] The widgets that the container contains. labels bool Whether each widget should be shown with a corresponding Label widget to the left. Note: the text for each widget defaults to widget.name, but can be overridden by setting widget.label.

Container implements the full collections.abc.MutableSequence interface. You can add and remove widgets from it just as you would add or remove items from a list.

from magicgui.widgets import Container, Slider, FloatSlider, ProgressBar\n\ncontainer = widgets.Container()\ncontainer.append(widgets.LineEdit(value='Mookie', label='Your Name:'))\ncontainer.append(widgets.FloatSlider(value=10.5, label='FloatSlider:'))\ncontainer.show()\n

"},{"location":"widgets/#mainwindowwidget","title":"MainWindowWidget","text":"

A MainWindowWidget is a special type of ContainerWidget that also includes a menu bar.

"},{"location":"widgets/#functiongui","title":"FunctionGui","text":"

A FunctionGui is a special type of ContainerWidget that is created from a function. It is the product of the @magicgui decorator. It is a container that contains a widget for each of the parameters in the function. See magicgui.widgets.FunctionGui for details.

"},{"location":"widgets/#magicgui","title":"@magicgui","text":"

It's worth noting that @magicgui and @magic_factory decorators are just conveniences that build a special type of Container widget (a FunctionGui), with a widget representing each of the parameters in a decorated function.

from magicgui import magicgui\n\n@magicgui\ndef my_function(x='hello', y=400): ...\n\nmy_function.show()\n

In terms of simply building widgets, the following code performs a similar task to @magicgui.

from inspect import signature\n\ndef my_function(x='hello', y=400):\n  ...\n\nparams = signature(my_function).parameters.values()\ncontainer = Container(\n    widgets=[create_widget(p.default, name=p.name) for p in params]\n)\ncontainer.show()\n

Tip

Note that the FunctionGui widget produced by @magicgui is actually a callable object that behaves very much like the original function, except that it will use current values from the GUI as default parameters when calling the function.

"},{"location":"api/app/","title":"Application","text":""},{"location":"api/app/#magicgui.application.Application","title":"magicgui.application.Application","text":"

Magicgui Application, wrapping a native BaseApplicationBackend implementation.

"},{"location":"api/app/#magicgui.application.Application.backend_module","title":"backend_module: ModuleType property","text":"

Return module object that defines the backend.

"},{"location":"api/app/#magicgui.application.Application.backend_name","title":"backend_name: str property","text":"

Return name of the GUI backend that this app wraps.

"},{"location":"api/app/#magicgui.application.Application.native","title":"native: Any property","text":"

Return the native GUI application instance.

"},{"location":"api/app/#magicgui.application.Application.__enter__","title":"__enter__() -> Application","text":"

Context manager to start this application.

"},{"location":"api/app/#magicgui.application.Application.__exit__","title":"__exit__(*exc_details: Any) -> None","text":"

Exit context manager for this application.

"},{"location":"api/app/#magicgui.application.Application.__repr__","title":"__repr__() -> str","text":"

Return repr for this instance.

"},{"location":"api/app/#magicgui.application.Application.create","title":"create() -> None","text":"

Create the native application.

"},{"location":"api/app/#magicgui.application.Application.get_obj","title":"get_obj(name: str) -> Any","text":"

Get the backend object for the given name (such as a widget).

"},{"location":"api/app/#magicgui.application.Application.process_events","title":"process_events() -> None","text":"

Process all pending GUI events.

"},{"location":"api/app/#magicgui.application.Application.quit","title":"quit() -> None","text":"

Quit the native GUI event loop.

"},{"location":"api/app/#magicgui.application.Application.run","title":"run() -> None","text":"

Enter the native GUI event loop.

"},{"location":"api/app/#magicgui.application.Application.start_timer","title":"start_timer(interval: int = 1000, on_timeout: Callable[[], None] | None = None, single_shot: bool = False) -> None","text":"

Start a timer with a given interval, optional callback, and single_shot.

"},{"location":"api/app/#magicgui.application.use_app","title":"magicgui.application.use_app(app: AppRef | None = None) -> Application","text":"

Get/create the default Application object. See _use_app docstring.

"},{"location":"api/experimental/","title":"magicgui.experimental","text":"

Experimental

This module contains experimental features that are not yet ready for prime time. All of the features in this module are subject to change without warning or deprecation.

"},{"location":"api/experimental/#magicgui.experimental.guiclass","title":"magicgui.experimental.guiclass(cls: T | None = None, *, gui_name: str = 'gui', events_namespace: str = 'events', follow_changes: bool = True, **dataclass_kwargs: Any) -> T | Callable[[T], T]","text":"

Turn class into a dataclass with a property (gui_name) that returns a gui.

This decorator is similar to dataclasses.dataclass, but it will also add an events attribute to the class that is an instance of psygnal.SignalGroup (with a signal for each field in the dataclass; see https://psygnal.readthedocs.io/en/latest/dataclasses/ for details), and a gui property that returns a magicgui widget, bound to the values of the dataclass instance.

Note

This decorator is compatible with dataclasses using slots=True, however, there is a potential for a memory leak that the user should be aware of. If you create a guiclass instance, and then store a reference to its gui, and then delete the instance, the gui will still be bound to the instance, preventing it from being garbage collected. To avoid this, you can call unbind_gui_from_instance(gui, instance) before deleting the instance.

Parameters:

  • cls (type, default: None ) \u2013

    The class to turn into a dataclass.

  • gui_name (str, default: 'gui' ) \u2013

    The name of the property that will return a magicgui widget, by default \"gui\"

  • events_namespace (str, default: 'events' ) \u2013

    The name of the attribute that will be added to the class, by default \"events\". This attribute will be an instance of psygnal.SignalGroup that will be used to connect events to the class.

  • follow_changes (bool, default: True ) \u2013

    If True (default), changes to the dataclass instance will be reflected in the gui, and changes to the gui will be reflected in the dataclass instance.

  • dataclass_kwargs (dict, default: {} ) \u2013

    Additional keyword arguments to pass to dataclasses.dataclass.

Returns:

  • type \u2013

    The dataclass.

Examples:

>>> @guiclass\n... class MyData:\n...     x: int = 0\n...     y: str = 'hi'\n...\n...     @button\n...     def reset(self):\n...         self.x = 0\n...         self.y = 'hi'\n...\n>>> data = MyData()\n>>> data.gui.show()\n
"},{"location":"api/experimental/#magicgui.experimental.button","title":"magicgui.experimental.button(func: F | None = None, **button_kwargs: Any) -> F | Callable[[F], F]","text":"

Add a method as a button to a guiclass, which calls the decorated method.

Parameters:

  • func (callable, default: None ) \u2013

    The method to decorate. If None, returns a decorator that can be applied to a method.

  • button_kwargs (dict, default: {} ) \u2013

    Additional keyword arguments to pass to magicgui.widgets.PushButton.

"},{"location":"api/experimental/#magicgui.experimental.is_guiclass","title":"magicgui.experimental.is_guiclass(obj: object) -> TypeGuard[GuiClassProtocol]","text":"

Return True if obj is a guiclass or an instance of a guiclass.

"},{"location":"api/magic_factory/","title":"magicgui.magic_factory","text":""},{"location":"api/magic_factory/#magicgui.magic_factory","title":"magicgui.magic_factory(function=None, *, layout='vertical', scrollable=False, labels=True, tooltips=True, call_button=None, auto_call=False, result_widget=False, main_window=False, app=None, persist=False, widget_init=None, raise_on_unknown=False, **param_options)","text":"

Return a MagicFactory for function.

magic_factory is nearly identical to the magicgui decorator with the following differences:

  1. Whereas magicgui returns a FunctionGui instance, magic_factory returns a callable that returns a FunctionGui instance. (Technically, it returns an instance of MagicFactory which you behaves exactly like a functools.partial for a FunctionGui instance.)
  2. magic_factory adds a widget_init method: a callable that will be called immediately after the FunctionGui instance is created. This can be used to add additional widgets to the layout, or to connect signals to the widgets.

Important

Whereas decorating a function with magicgui will immediately create a widget instance, magic_factory will not create a widget instance until the decorated object is called. This is often what you want in a library, whereas magicgui is useful for rapid, interactive development.

Parameters:

  • function (Callable, default: None ) \u2013

    The function to decorate. Optional to allow bare decorator with optional arguments. by default None

  • layout (str, default: 'vertical' ) \u2013

    The type of layout to use. Must be horizontal or vertical by default \"vertical\".

  • scrollable (bool, default: False ) \u2013

    Whether to enable scroll bars or not. If enabled, scroll bars will only appear along the layout direction, not in both directions.

  • labels (bool, default: True ) \u2013

    Whether labels are shown in the widget. by default True

  • tooltips (bool, default: True ) \u2013

    Whether tooltips are shown when hovering over widgets. by default True

  • call_button (bool or str, default: None ) \u2013

    If True, create an additional button that calls the original function when clicked. If a str, set the button text. If None (the default), it defaults to True when auto_call is False, and False otherwise.

  • auto_call (bool, default: False ) \u2013

    If True, changing any parameter in either the GUI or the widget attributes will call the original function with the current settings. by default False

  • result_widget (bool, default: False ) \u2013

    Whether to display a LineEdit widget the output of the function when called, by default False

  • main_window (bool, default: False ) \u2013

    Whether this widget should be treated as the main app window, with menu bar, by default False.

  • app (Application or str, default: None ) \u2013

    A backend to use, by default None (use the default backend.)

  • persist (bool, default: False ) \u2013

    If True, when parameter values change in the widget, they will be stored to disk and restored when the widget is loaded again with persist = True. Call magicgui._util.user_cache_dir() to get the default cache location. By default False.

  • widget_init (callable, default: None ) \u2013

    A function that will be called with the newly created widget instance as its only argument. This can be used to customize the widget after it is created. by default None.

  • raise_on_unknown (bool, default: False ) \u2013

    If True, raise an error if magicgui cannot determine widget for function argument or return type. If False, ignore unknown types. By default False.

  • param_options (dict of dict, default: {} ) \u2013

    Any additional keyword arguments will be used as parameter-specific widget options. Keywords must match the name of one of the arguments in the function signature, and the value must be a dict of keyword arguments to pass to the widget constructor.

Returns:

  • result ( MagicFactory or Callable[[F], MagicFactory] ) \u2013

    If function is not None (such as when this is used as a bare decorator), returns a MagicFactory instance. If function is None such as when arguments are provided like magic_factory(auto_call=True), then returns a function that can be used as a decorator.

Examples:

>>> @magic_factory\n... def my_function(a: int = 1, b: str = 'hello'):\n...     pass\n...\n>>> my_widget = my_function()\n>>> my_widget.show()\n>>> my_widget.a.value == 1  # True\n>>> my_widget.b.value = 'world'\n
"},{"location":"api/magic_factory/#magicgui.type_map._magicgui.MagicFactory","title":"magicgui.type_map._magicgui.MagicFactory","text":"

Bases: partial, Generic[_FGuiVar]

Factory function that returns a FunctionGui instance.

While this can be used directly, (see example below) the preferred usage is via the magicgui.magic_factory decorator.

Examples:

>>> def func(x: int, y: str):\n...     pass\n...\n>>> factory = MagicFactory(function=func, labels=False)\n>>> # factory accepts all the same arguments as magicgui()\n>>> widget1 = factory(call_button=True)\n>>> # can also override magic_kwargs that were provided when creating the factory\n>>> widget2 = factory(auto_call=True, labels=True)\n
"},{"location":"api/magic_factory/#magicgui.type_map._magicgui.MagicFactory.__name__","title":"__name__: str property","text":"

Pass function name.

"},{"location":"api/magic_factory/#magicgui.type_map._magicgui.MagicFactory.__call__","title":"__call__(*args, **kwargs)","text":"

Call the wrapped _magicgui and return a FunctionGui.

"},{"location":"api/magic_factory/#magicgui.type_map._magicgui.MagicFactory.__getattr__","title":"__getattr__(name)","text":"

Allow accessing FunctionGui attributes without mypy error.

"},{"location":"api/magic_factory/#magicgui.type_map._magicgui.MagicFactory.__new__","title":"__new__(function, *args, magic_class=FunctionGui, widget_init=None, **keywords)","text":"

Create new MagicFactory.

"},{"location":"api/magic_factory/#magicgui.type_map._magicgui.MagicFactory.__repr__","title":"__repr__()","text":"

Return string repr.

"},{"location":"api/magicgui/","title":"magicgui.magicgui","text":""},{"location":"api/magicgui/#magicgui.magicgui","title":"magicgui.magicgui(function=None, *, layout='vertical', scrollable=False, labels=True, tooltips=True, call_button=None, auto_call=False, result_widget=False, main_window=False, app=None, persist=False, raise_on_unknown=False, **param_options)","text":"

Return a FunctionGui for function.

Parameters:

  • function (Callable, default: None ) \u2013

    The function to decorate. Optional to allow bare decorator with optional arguments. by default None

  • layout (str, default: 'vertical' ) \u2013

    The type of layout to use. Must be horizontal or vertical by default \"vertical\".

  • scrollable (bool, default: False ) \u2013

    Whether to enable scroll bars or not. If enabled, scroll bars will only appear along the layout direction, not in both directions.

  • labels (bool, default: True ) \u2013

    Whether labels are shown in the widget. by default True

  • tooltips (bool, default: True ) \u2013

    Whether tooltips are shown when hovering over widgets. by default True

  • call_button (bool or str, default: None ) \u2013

    If True, create an additional button that calls the original function when clicked. If a str, set the button text. If None (the default), it defaults to True when auto_call is False, and False otherwise.

  • auto_call (bool, default: False ) \u2013

    If True, changing any parameter in either the GUI or the widget attributes will call the original function with the current settings. by default False

  • result_widget (bool, default: False ) \u2013

    Whether to display a LineEdit widget the output of the function when called, by default False

  • main_window (bool, default: False ) \u2013

    Whether this widget should be treated as the main app window, with menu bar, by default False.

  • app (Application or str, default: None ) \u2013

    A backend to use, by default None (use the default backend.)

  • persist (bool, default: False ) \u2013

    If True, when parameter values change in the widget, they will be stored to disk and restored when the widget is loaded again with persist = True. Call magicgui._util.user_cache_dir() to get the default cache location. By default False.

  • raise_on_unknown (bool, default: False ) \u2013

    If True, raise an error if magicgui cannot determine widget for function argument or return type. If False, ignore unknown types. By default False.

  • param_options (dict[str, dict], default: {} ) \u2013

    Any additional keyword arguments will be used as parameter-specific options. Keywords must match the name of one of the arguments in the function signature, and the value must be a dict of keyword arguments to pass to the widget constructor.

Returns:

  • result ( FunctionGui or Callable[[F], FunctionGui] ) \u2013

    If function is not None (such as when this is used as a bare decorator), returns a FunctionGui instance, which is a list-like container of autogenerated widgets corresponding to each parameter in the function. If function is None such as when arguments are provided like magicgui(auto_call=True), then returns a function that can be used as a decorator.

Examples:

>>> @magicgui\n... def my_function(a: int = 1, b: str = 'hello'):\n...     pass\n...\n>>> my_function.show()\n>>> my_function.a.value == 1  # True\n>>> my_function.b.value = 'world'\n
"},{"location":"api/migration/","title":"migration guide","text":""},{"location":"api/migration/#v030-migration-guide","title":"v0.3.0 migration guide","text":"

October, 2021

Version 0.3.0 of magicgui introduced some changes to the events and callbacks API. See https://github.com/pyapp-kit/magicgui/pull/253 for details

"},{"location":"api/migration/#callbacks-now-receive-the-value-directly-instead-of-an-event-object","title":"Callbacks now receive the value directly, instead of an Event object","text":"

magicgui 0.3.0 is now using psygnal as its event/callback handler.

Callbacks connected to widget.changed (and other event emitters) may now receive the value(s) directly, instead of an event object:

\ud83d\udc4e Old Method (< v0.3.0)
@widget.changed.connect\ndef my_callback(event):\n    # event was an `Event` object with a `value` attribute\n    new_value = event.value\n

Existing code using callbacks with a single positional argument will continue to receive a single Event object (and a warning will be shown, until v0.4.0 where it will become an error).

To silence the warning and opt in to the new pattern of receiving value directly, you can do one of two things:

  1. type hint your single positional argument as anything other than magicgui.events.Event
  2. provide a callback that takes no arguments
\ud83d\udc4d New Method (>= v0.3.0)
@widget.changed.connect\ndef my_callback(new_value: int):\n    ...  # use new_value directly\n\n# or, if you don't need to use new_value\n@widget.changed.connect\ndef my_callback():\n    # something that didn't need the value\n    ...\n
"},{"location":"api/migration/#event-emitters-take-no-keyword-arguments","title":"Event emitters take no keyword arguments","text":"

For the few packages who were manually emitting change events, you should no longer provide the value= keyword when emitting.

\ud83d\udc4e Old Method (< v0.3.0)
widget.changed(value='whatever')\n
\ud83d\udc4d New Method (>= v0.3.0)
widget.changed.emit('whatever')\n# OR (if you prefer the direct __call__ syntax)\nwidget.changed('whatever')\n
"},{"location":"api/migration/#v020-migration-guide","title":"v0.2.0 migration guide","text":"

December, 2020

Version 0.2.0 of magicgui was a complete rewrite that introduced a couple breaking API changes

"},{"location":"api/migration/#gui-attribute-removed","title":".Gui() attribute removed","text":"

Before v0.2.0, the magicgui.magicgui decorator added a Gui attribute to the decorated function that was to be called to instantiate a widget. In v0.2.0 the object returned from the magicgui.magicgui decorator is already an instantiated magicgui.widgets.Widget.

\ud83d\udc4e Old Method (< v0.2.0)
from magicgui import magicgui, event_loop\n\n@magicgui\ndef function(x, y):\n    ...\n\nwith event_loop():\n    gui = function.Gui(show=True)\n
\ud83d\udc4d New Method (>= v0.2.0)
from magicgui import magicgui\n\n@magicgui\ndef function(x, y):\n    ...\n\nfunction.show(run=True)\n
"},{"location":"api/migration/#new-base-widget-type","title":"New base widget type","text":"

Before v0.2.0, the Gui() object returned by the magicgui.magicgui decorator was a MagicGuiBase widget class, which in turn was a direct subclass of a backend widget, such as a QtWidgets.QWidget. In v0.2.0, all widgets derive from [magicgui.widgets.Widget``][magicgui.widgets.Widget], and the *backend* is available atwidget.native. If you are incorporating magicgui widgets into a larger Qt-based GUI, please note that you will want to usewidget.nativeinstead ofwidget`

from magicgui import magicgui, use_app\n\nuse_app('qt')\n\n@magicgui\ndef function(x, y):\n    ...\n
>>> print(type(function))\n<class 'magicgui.widgets.FunctionGui'>\n>>> print(type(function.native))\n<class 'PyQt5.QtWidgets.QWidget'>\n
"},{"location":"api/migration/#starting-the-application","title":"Starting the application","text":"

It is now easier to show a widget and start an application by calling widget.show(run=True). Calling show(run=True) will immediately block execution of your script and show the widget. If you wanted to (for instance) show multiple widgets next to each other, then you would still want to use the event_loop context manager:

from magicgui import magicgui, event_loop\n\n@magicgui\ndef function_a(x=1, y=3):\n    ...\n\n@magicgui\ndef function_b(z='asdf'):\n    ...\n\nwith event_loop():\n    function_a.show()\n    function_b.show()\n# both widgets will show (though b may be on top of a)\n
"},{"location":"api/migration/#getting-and-setting-values","title":"Getting and setting values","text":"

To get or set the value of a widget programmatically, you no longer set the corresponding widget attribute directly, but rather use the widget.value attribute:

Old Method \ud83d\udc4e

gui.x used to be a descriptor object to get/set the value, but the actual underlying widget was at gui.x_widget

gui = function.Gui()\ngui.x = 10\n

New Method \ud83d\udc4d

now function.x IS the widget, and you set its value with function.x.value

function.x.value = 10\n
"},{"location":"api/migration/#connecting-callbacks-to-events","title":"Connecting callbacks to events","text":"

When binding callbacks to change events, you no longer connect to gui.<name>_changed, you now connect to function.<name>.changed:

\ud83d\udc4e Old Method (< v0.2.0)
gui = function.Gui()\ngui.x_changed.connect(my_callback)\n
\ud83d\udc4d New Method (>= v0.2.0)
function.x.changed.connect(my_callback)\n
"},{"location":"api/migration/#renamed","title":"Renamed","text":"
  • Widget.refresh_choices has been renamed to Widget.reset_choices.

  • @magicgui(result=True) has been renamed to @magicgui(result_widget=True)

"},{"location":"api/protocols/","title":"Backend Protocols","text":"

Advanced Topic

Most users of magicgui will not need to worry about this section.

These Protocol classes declare the interface that backend adapters must implement in order to be used by magicgui. All magicgui Widget objects compose a backend widget implementing one of these protocols, and control it using the methods defined herein.

magicgui developers may be interested in this page, but end-users needn't worry about it.

"},{"location":"api/protocols/#summary","title":"Summary","text":"Widget Description WidgetProtocol Base Widget Protocol: specifies methods that all widgets must provide. ValueWidgetProtocol Widget that has a current value, with getter/setter and on_change callback. ButtonWidgetProtocol The \"value\" in a ButtonWidget is the current (checked) state. TableWidgetProtocol ValueWidget subclass intended for 2D tabular data, with row & column headers. RangedWidgetProtocol Value widget that supports numbers within a provided min/max range. CategoricalWidgetProtocol Categorical widget, that has a set of valid choices, and a current value. SliderWidgetProtocol Protocol for implementing a slider widget. ContainerProtocol Widget that can contain other widgets. BaseApplicationBackend Backend Application object. DialogProtocol Protocol for modal (blocking) containers. SupportsChoices Widget that has a set of valid choices. SupportsOrientation Widget that can be reoriented. SupportsText Widget that have text (in addition to value)... like buttons. SupportsReadOnly Widget that can be read_only."},{"location":"api/protocols/#protocol-inheritance","title":"Protocol Inheritance","text":"

The visual hierarchy of protocols looks like this:

graph LR\n    A([WidgetProtocol])-->B([ValueWidgetProtocol])\n    A-->C([ContainerProtocol])\n    M([SupportsText])-->E\n    B-->E([ButtonWidgetProtocol])\n    B-->D([RangedWidgetProtocol])\n    B-->F([CategoricalWidgetProtocol])\n    D-->I([SliderWidgetProtocol])\n    B-->J([TableWidgetProtocol])\n    K([SupportsReadOnly])-->J([TableWidgetProtocol])\n    L([SupportsChoices])-->F\n    N([SupportsOrientation])-->C\n    N-->I\n    C-->O([DialogProtocol])\n    C-->P([MainWindowProtocol])\n\n    click A \"#magicgui.widgets.protocols.WidgetProtocol\"\n    click B \"#magicgui.widgets.protocols.ValueWidgetProtocol\"\n    click C \"#magicgui.widgets.protocols.ContainerProtocol\"\n    click D \"#magicgui.widgets.protocols.RangedWidgetProtocol\"\n    click E \"#magicgui.widgets.protocols.ButtonWidgetProtocol\"\n    click F \"#magicgui.widgets.protocols.CategoricalWidgetProtocol\"\n    click I \"#magicgui.widgets.protocols.SliderWidgetProtocol\"\n    click J \"#magicgui.widgets.protocols.TableWidgetProtocol\"\n    click K \"#magicgui.widgets.protocols.SupportsReadOnly\"\n    click L \"#magicgui.widgets.protocols.SupportsChoices\"\n    click M \"#magicgui.widgets.protocols.SupportsText\"\n    click N \"#magicgui.widgets.protocols.SupportsOrientation\"\n    click O \"#magicgui.widgets.protocols.DialogProtocol\"\n    click P \"#magicgui.widgets.protocols.MainWindowProtocol\"
"},{"location":"api/protocols/#widget-protocols","title":"Widget Protocols","text":""},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol","title":"magicgui.widgets.protocols.WidgetProtocol","text":"

Bases: Protocol

Base Widget Protocol: specifies methods that all widgets must provide.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_bind_parent_change_callback","title":"_mgui_bind_parent_change_callback(callback: Callable[[Any], None]) -> None abstractmethod","text":"

Bind callback to parent change event.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_close_widget","title":"_mgui_close_widget() -> None abstractmethod","text":"

Close widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_enabled","title":"_mgui_get_enabled() -> bool abstractmethod","text":"

Get the enabled state of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_height","title":"_mgui_get_height() -> int abstractmethod","text":"

Get the height of the widget.

The intention is to get the height of the widget after it is shown, for the purpose of unifying widget height in a layout. Backends may do what they need to accomplish this. For example, Qt can use sizeHint().height(), since height() may return something large if the widget has not yet been painted on screen.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_max_height","title":"_mgui_get_max_height() -> int abstractmethod","text":"

Get the maximum height of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_max_width","title":"_mgui_get_max_width() -> int abstractmethod","text":"

Get the maximum width of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_min_height","title":"_mgui_get_min_height() -> int abstractmethod","text":"

Get the minimum height of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_min_width","title":"_mgui_get_min_width() -> int abstractmethod","text":"

Get the minimum width of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_native_widget","title":"_mgui_get_native_widget() -> Any abstractmethod","text":"

Return the native backend widget instance.

This is generally the widget that has the layout.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_parent","title":"_mgui_get_parent() -> Widget abstractmethod","text":"

Return the parent widget of this widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_root_native_widget","title":"_mgui_get_root_native_widget() -> Any abstractmethod","text":"

Return the root native backend widget.

In most cases, this is the same as _mgui_get_native_widget. However, in cases where the native widget is in a scroll layout, this might be different.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_tooltip","title":"_mgui_get_tooltip() -> str abstractmethod","text":"

Get the tooltip for this widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_visible","title":"_mgui_get_visible() -> bool abstractmethod","text":"

Get widget visibility.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_width","title":"_mgui_get_width() -> int abstractmethod","text":"

Get the width of the widget.

The intention is to get the width of the widget after it is shown, for the purpose of unifying widget width in a layout. Backends may do what they need to accomplish this. For example, Qt can use sizeHint().width(), since width() may return something large if the widget has not yet been painted on screen.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_render","title":"_mgui_render() -> np.ndarray abstractmethod","text":"

Return an RGBA (MxNx4) numpy array bitmap of the rendered widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_set_enabled","title":"_mgui_set_enabled(enabled: bool) -> None abstractmethod","text":"

Set the enabled state of the widget to enabled.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_set_height","title":"_mgui_set_height(value: int) -> None abstractmethod","text":"

Set the height of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_set_max_height","title":"_mgui_set_max_height(value: int) -> None abstractmethod","text":"

Set the maximum height of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_set_max_width","title":"_mgui_set_max_width(value: int) -> None abstractmethod","text":"

Set the maximum width of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_set_min_height","title":"_mgui_set_min_height(value: int) -> None abstractmethod","text":"

Set the minimum height of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_set_min_width","title":"_mgui_set_min_width(value: int) -> None abstractmethod","text":"

Set the minimum width of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_set_parent","title":"_mgui_set_parent(widget: Widget) -> None abstractmethod","text":"

Set the parent widget of this widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_set_tooltip","title":"_mgui_set_tooltip(value: str | None) -> None abstractmethod","text":"

Set a tooltip for this widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_set_visible","title":"_mgui_set_visible(value: bool) -> None abstractmethod","text":"

Set widget visibility.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_set_width","title":"_mgui_set_width(value: int) -> None abstractmethod","text":"

Set the width of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.ValueWidgetProtocol","title":"magicgui.widgets.protocols.ValueWidgetProtocol","text":"

Bases: WidgetProtocol, Protocol

Widget that has a current value, with getter/setter and on_change callback.

It is worth noting that the widget is the thing that has a value. Magicgui does not maintain & synchronize an independent model.

"},{"location":"api/protocols/#magicgui.widgets.protocols.ValueWidgetProtocol._mgui_bind_change_callback","title":"_mgui_bind_change_callback(callback: Callable[[Any], Any]) -> None abstractmethod","text":"

Bind callback to value change event.

"},{"location":"api/protocols/#magicgui.widgets.protocols.ValueWidgetProtocol._mgui_get_value","title":"_mgui_get_value() -> Any abstractmethod","text":"

Get current value of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.ValueWidgetProtocol._mgui_set_value","title":"_mgui_set_value(value: Any) -> None abstractmethod","text":"

Set current value of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.ButtonWidgetProtocol","title":"magicgui.widgets.protocols.ButtonWidgetProtocol","text":"

Bases: ValueWidgetProtocol, SupportsText, SupportsIcon, Protocol

The \"value\" in a ButtonWidget is the current (checked) state.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol","title":"magicgui.widgets.protocols.TableWidgetProtocol","text":"

Bases: ValueWidgetProtocol, SupportsReadOnly, Protocol

ValueWidget subclass intended for 2D tabular data, with row & column headers.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_bind_change_callback","title":"_mgui_bind_change_callback(callback: Callable[[Any], Any]) -> None abstractmethod","text":"

Bind callback to value change event.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_bind_column_headers_change_callback","title":"_mgui_bind_column_headers_change_callback(callback: Callable[[Any], None]) -> None abstractmethod","text":"

Bind callback to column headers change event.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_bind_row_headers_change_callback","title":"_mgui_bind_row_headers_change_callback(callback: Callable[[Any], None]) -> None abstractmethod","text":"

Bind callback to row headers change event.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_get_cell","title":"_mgui_get_cell(row: int, col: int) -> Any abstractmethod","text":"

Get current value of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_get_column_count","title":"_mgui_get_column_count() -> int abstractmethod","text":"

Get the number of columns in the table.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_get_column_headers","title":"_mgui_get_column_headers() -> tuple abstractmethod","text":"

Get current column headers of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_get_row_count","title":"_mgui_get_row_count() -> int abstractmethod","text":"

Get the number of rows in the table.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_get_row_headers","title":"_mgui_get_row_headers() -> tuple abstractmethod","text":"

Get current row headers of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_remove_column","title":"_mgui_remove_column(column: int) -> None abstractmethod","text":"

Remove column at index column.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_remove_row","title":"_mgui_remove_row(row: int) -> None abstractmethod","text":"

Remove row at index row.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_set_cell","title":"_mgui_set_cell(row: int, col: int, value: Any) -> None abstractmethod","text":"

Set current value of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_set_column_count","title":"_mgui_set_column_count(ncols: int) -> None abstractmethod","text":"

Set the number of columns in the table. (Create/delete as needed).

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_set_column_headers","title":"_mgui_set_column_headers(headers: Sequence) -> None abstractmethod","text":"

Set current column headers of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_set_row_count","title":"_mgui_set_row_count(nrows: int) -> None abstractmethod","text":"

Set the number of rows in the table. (Create/delete as needed).

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_set_row_headers","title":"_mgui_set_row_headers(headers: Sequence) -> None abstractmethod","text":"

Set current row headers of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.RangedWidgetProtocol","title":"magicgui.widgets.protocols.RangedWidgetProtocol","text":"

Bases: ValueWidgetProtocol, Protocol

Value widget that supports numbers within a provided min/max range.

"},{"location":"api/protocols/#magicgui.widgets.protocols.RangedWidgetProtocol._mgui_get_adaptive_step","title":"_mgui_get_adaptive_step() -> bool abstractmethod","text":"

Get adaptive step status.

"},{"location":"api/protocols/#magicgui.widgets.protocols.RangedWidgetProtocol._mgui_get_max","title":"_mgui_get_max() -> float abstractmethod","text":"

Get the maximum possible value.

"},{"location":"api/protocols/#magicgui.widgets.protocols.RangedWidgetProtocol._mgui_get_min","title":"_mgui_get_min() -> float abstractmethod","text":"

Get the minimum possible value.

"},{"location":"api/protocols/#magicgui.widgets.protocols.RangedWidgetProtocol._mgui_get_step","title":"_mgui_get_step() -> float abstractmethod","text":"

Get the step size.

"},{"location":"api/protocols/#magicgui.widgets.protocols.RangedWidgetProtocol._mgui_set_adaptive_step","title":"_mgui_set_adaptive_step(value: bool) -> None abstractmethod","text":"

Set adaptive step status.

"},{"location":"api/protocols/#magicgui.widgets.protocols.RangedWidgetProtocol._mgui_set_max","title":"_mgui_set_max(value: float) -> None abstractmethod","text":"

Set the maximum possible value.

"},{"location":"api/protocols/#magicgui.widgets.protocols.RangedWidgetProtocol._mgui_set_min","title":"_mgui_set_min(value: float) -> None abstractmethod","text":"

Set the minimum possible value.

"},{"location":"api/protocols/#magicgui.widgets.protocols.RangedWidgetProtocol._mgui_set_step","title":"_mgui_set_step(value: float) -> None abstractmethod","text":"

Set the step size.

"},{"location":"api/protocols/#magicgui.widgets.protocols.CategoricalWidgetProtocol","title":"magicgui.widgets.protocols.CategoricalWidgetProtocol","text":"

Bases: ValueWidgetProtocol, SupportsChoices, Protocol

Categorical widget, that has a set of valid choices, and a current value.

It adds no additional methods.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SliderWidgetProtocol","title":"magicgui.widgets.protocols.SliderWidgetProtocol","text":"

Bases: RangedWidgetProtocol, SupportsOrientation, Protocol

Protocol for implementing a slider widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SliderWidgetProtocol._mgui_get_tracking","title":"_mgui_get_tracking() -> bool","text":"

If tracking is False, changed is only emitted when released.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SliderWidgetProtocol._mgui_set_readout_visibility","title":"_mgui_set_readout_visibility(visible: bool) -> None","text":"

Set visibility of readout widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SliderWidgetProtocol._mgui_set_tracking","title":"_mgui_set_tracking(tracking: bool) -> None","text":"

If tracking is False, changed is only emitted when released.

"},{"location":"api/protocols/#magicgui.widgets.protocols.ContainerProtocol","title":"magicgui.widgets.protocols.ContainerProtocol","text":"

Bases: WidgetProtocol, SupportsOrientation, Protocol

Widget that can contain other widgets.

This generally manages a backend Layout.

"},{"location":"api/protocols/#magicgui.widgets.protocols.ContainerProtocol._mgui_get_margins","title":"_mgui_get_margins() -> tuple[int, int, int, int] abstractmethod","text":"

Get the margins of the container.

"},{"location":"api/protocols/#magicgui.widgets.protocols.ContainerProtocol._mgui_insert_widget","title":"_mgui_insert_widget(position: int, widget: Widget) -> None abstractmethod","text":"

Insert widget at the given position in the layout.

"},{"location":"api/protocols/#magicgui.widgets.protocols.ContainerProtocol._mgui_remove_widget","title":"_mgui_remove_widget(widget: Widget) -> None abstractmethod","text":"

Remove the specified widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.ContainerProtocol._mgui_set_margins","title":"_mgui_set_margins(margins: tuple[int, int, int, int]) -> None abstractmethod","text":"

Set the margins of the container.

"},{"location":"api/protocols/#magicgui.widgets.protocols.DialogProtocol","title":"magicgui.widgets.protocols.DialogProtocol","text":"

Bases: ContainerProtocol, Protocol

Protocol for modal (blocking) containers.

"},{"location":"api/protocols/#magicgui.widgets.protocols.DialogProtocol._mgui_exec","title":"_mgui_exec() -> None abstractmethod","text":"

Show the dialog and block.

"},{"location":"api/protocols/#magicgui.widgets.protocols.MainWindowProtocol","title":"magicgui.widgets.protocols.MainWindowProtocol","text":"

Bases: ContainerProtocol, Protocol

Application main widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.MainWindowProtocol._mgui_create_menu_item","title":"_mgui_create_menu_item(menu_name: str, action_name: str, callback: Callable | None = None, shortcut: str | None = None) -> None abstractmethod","text":"

Create a new menu item.

Parameters:

  • menu_name (str) \u2013

    The name of the menu to add the item to.

  • action_name (str) \u2013

    The name of the action to add.

  • callback (Callable | None, default: None ) \u2013

    A callback to be called when the action is triggered, by default None.

  • shortcut (str | None, default: None ) \u2013

    A keyboard shortcut for the action, by default None.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsChoices","title":"magicgui.widgets.protocols.SupportsChoices","text":"

Bases: Protocol

Widget that has a set of valid choices.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsChoices._mgui_del_choice","title":"_mgui_del_choice(choice_name: str) -> None abstractmethod","text":"

Delete the provided choice_name and associated data.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsChoices._mgui_get_choice","title":"_mgui_get_choice(choice_name: str) -> Any abstractmethod","text":"

Get data for a single choice.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsChoices._mgui_get_choices","title":"_mgui_get_choices() -> tuple[tuple[str, Any], ...] abstractmethod","text":"

Get available choices.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsChoices._mgui_get_count","title":"_mgui_get_count() -> int abstractmethod","text":"

Return number of choices.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsChoices._mgui_get_current_choice","title":"_mgui_get_current_choice() -> str abstractmethod","text":"

Return the text of the currently selected choice.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsChoices._mgui_set_choice","title":"_mgui_set_choice(choice_name: str, data: Any) -> None abstractmethod","text":"

Set data for choice_name, or add a new item if choice_name doesn't exist.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsChoices._mgui_set_choices","title":"_mgui_set_choices(choices: Iterable[tuple[str, Any]]) -> None abstractmethod","text":"

Set available choices.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsOrientation","title":"magicgui.widgets.protocols.SupportsOrientation","text":"

Bases: Protocol

Widget that can be reoriented.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsOrientation._mgui_get_orientation","title":"_mgui_get_orientation() -> str abstractmethod","text":"

Get orientation, return either 'horizontal' or 'vertical'.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsOrientation._mgui_set_orientation","title":"_mgui_set_orientation(value: str) -> None abstractmethod","text":"

Set orientation, value will be 'horizontal' or 'vertical'.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsText","title":"magicgui.widgets.protocols.SupportsText","text":"

Bases: Protocol

Widget that have text (in addition to value)... like buttons.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsText._mgui_get_text","title":"_mgui_get_text() -> str abstractmethod","text":"

Get text.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsText._mgui_set_text","title":"_mgui_set_text(value: str) -> None abstractmethod","text":"

Set text.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsReadOnly","title":"magicgui.widgets.protocols.SupportsReadOnly","text":"

Bases: Protocol

Widget that can be read_only.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsReadOnly._mgui_get_read_only","title":"_mgui_get_read_only() -> bool abstractmethod","text":"

Get read_only status.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsReadOnly._mgui_set_read_only","title":"_mgui_set_read_only(value: bool) -> None abstractmethod","text":"

Set read_only.

"},{"location":"api/protocols/#application-protocol","title":"Application Protocol","text":""},{"location":"api/protocols/#magicgui.widgets.protocols.BaseApplicationBackend","title":"magicgui.widgets.protocols.BaseApplicationBackend","text":"

Bases: ABC

Backend Application object.

Abstract class that provides an interface between backends and Application. Each backend must implement a subclass of BaseApplicationBackend, and implement all of its _mgui_xxx methods.

"},{"location":"api/protocols/#magicgui.widgets.protocols.BaseApplicationBackend._mgui_get_backend_name","title":"_mgui_get_backend_name() -> str abstractmethod","text":"

Return the name of the backend.

"},{"location":"api/protocols/#magicgui.widgets.protocols.BaseApplicationBackend._mgui_get_native_app","title":"_mgui_get_native_app() -> Any abstractmethod","text":"

Return the native GUI application instance.

"},{"location":"api/protocols/#magicgui.widgets.protocols.BaseApplicationBackend._mgui_process_events","title":"_mgui_process_events() -> None abstractmethod","text":"

Process all pending GUI events.

"},{"location":"api/protocols/#magicgui.widgets.protocols.BaseApplicationBackend._mgui_quit","title":"_mgui_quit() -> None abstractmethod","text":"

Quit the native GUI event loop.

"},{"location":"api/protocols/#magicgui.widgets.protocols.BaseApplicationBackend._mgui_run","title":"_mgui_run() -> None abstractmethod","text":"

Start the application.

"},{"location":"api/protocols/#magicgui.widgets.protocols.BaseApplicationBackend._mgui_start_timer","title":"_mgui_start_timer(interval: int = 0, on_timeout: Callable[[], None] | None = None, single: bool = False) -> None abstractmethod","text":"

Create and start a timer.

Parameters:

  • interval (int, default: 0 ) \u2013

    Interval between timeouts, by default 0

  • on_timeout (Optional[Callable[[], None]], default: None ) \u2013

    Function to call when timer finishes, by default None

  • single (bool, default: False ) \u2013

    Whether the timer should only fire once, by default False

"},{"location":"api/protocols/#magicgui.widgets.protocols.BaseApplicationBackend._mgui_stop_timer","title":"_mgui_stop_timer() -> None abstractmethod","text":"

Stop timer. Should check for the existence of the timer.

"},{"location":"api/type_map/","title":"magicgui.type_map","text":"Widget Description get_widget_class Return a Widget subclass for the value/annotation. register_type Register a widget_type to be used for all parameters with type type_. type_registered Context manager that temporarily registers a widget type for a given type_. type2callback Return any callbacks that have been registered for type_."},{"location":"api/type_map/#magicgui.type_map.get_widget_class","title":"magicgui.type_map.get_widget_class(value: Any = Undefined, annotation: Any = Undefined, options: dict | None = None, is_result: bool = False, raise_on_unknown: bool = True) -> tuple[WidgetClass, dict]","text":"

Return a Widget subclass for the value/annotation.

Parameters:

  • value (Any, default: Undefined ) \u2013

    A python value. Will be used to determine the widget type if an annotation is not explicitly provided by default None

  • annotation (Optional[Type], default: Undefined ) \u2013

    A type annotation, by default None

  • options (dict, default: None ) \u2013

    Options to pass when constructing the widget, by default {}

  • is_result (bool, default: False ) \u2013

    Identifies whether the returned widget should be tailored to an input or to an output.

  • raise_on_unknown (bool, default: True ) \u2013

    Raise exception if no widget is found for the given type, by default True

Returns:

  • Tuple[WidgetClass, dict] \u2013

    The WidgetClass, and dict that can be used for params. dict may be different than the options passed in.

"},{"location":"api/type_map/#magicgui.type_map.register_type","title":"magicgui.type_map.register_type(type_: _T | None = None, *, widget_type: WidgetRef | None = None, return_callback: ReturnCallback | None = None, **options: Any) -> _T | Callable[[_T], _T]","text":"

Register a widget_type to be used for all parameters with type type_.

Note: registering a Union (or Optional) type effectively registers all types in the union with the arguments.

Parameters:

  • type_ (type, default: None ) \u2013

    The type for which a widget class or return callback will be provided.

  • widget_type (WidgetRef, default: None ) \u2013

    A widget class from the current backend that should be used whenever type_ is used as the type annotation for an argument in a decorated function, by default None

  • return_callback (ReturnCallback | None, default: None ) \u2013

    If provided, whenever type_ is declared as the return type of a decorated function, return_callback(widget, value, return_type) will be called whenever the decorated function is called... where widget is the Widget instance, and value is the return value of the decorated function.

  • options (Any, default: {} ) \u2013

    key value pairs where the keys are valid dict

Raises:

  • ValueError \u2013

    If none of widget_type, return_callback, bind or choices are provided.

"},{"location":"api/type_map/#magicgui.type_map.type_registered","title":"magicgui.type_map.type_registered(type_: _T, *, widget_type: WidgetRef | None = None, return_callback: ReturnCallback | None = None, **options: Any) -> Iterator[None]","text":"

Context manager that temporarily registers a widget type for a given type_.

When the context is exited, the previous widget type associations for type_ is restored.

Parameters:

  • type_ (_T) \u2013

    The type for which a widget class or return callback will be provided.

  • widget_type (Optional[WidgetRef], default: None ) \u2013

    A widget class from the current backend that should be used whenever type_ is used as the type annotation for an argument in a decorated function, by default None

  • return_callback (ReturnCallback | None, default: None ) \u2013

    If provided, whenever type_ is declared as the return type of a decorated function, return_callback(widget, value, return_type) will be called whenever the decorated function is called... where widget is the Widget instance, and value is the return value of the decorated function.

  • options (Any, default: {} ) \u2013

    key value pairs where the keys are valid dict

"},{"location":"api/type_map/#magicgui.type_map.type2callback","title":"magicgui.type_map.type2callback(type_: type) -> list[ReturnCallback]","text":"

Return any callbacks that have been registered for type_.

Parameters:

  • type_ (type) \u2013

    The type_ to look up.

Returns:

  • list of callable \u2013

    Where a return callback accepts two arguments (gui, value) and does something.

"},{"location":"api/widgets/","title":"Widget Index","text":"

Here you will find a list of all the widgets that are available in magicgui. Each widget has a link to its own documentation page, where you can find more information about the widget, including its parameters and events.

Widget Description CheckBox A checkbox with a text label. ComboBox A dropdown menu, allowing selection between multiple choices. Container A Widget to contain other widgets. DateEdit A widget for editing dates. DateTimeEdit A widget for editing dates and times. Dialog A modal container. EmptyWidget A base widget with no value. FileEdit A LineEdit widget with a button that opens a FileDialog. FloatRangeSlider A slider widget to adjust a range defined by two float values within a range. FloatSlider A slider widget to adjust an integer value within a range. FloatSpinBox A widget to edit a float with clickable up/down arrows. FunctionGui Wrapper for a container of widgets representing a callable object. Image A non-editable image display. Label A non-editable text display. LineEdit A one-line text editor. ListEdit A widget to represent a list of values. LiteralEvalLineEdit A one-line text editor that evaluates strings as python literals. LogSlider A slider widget to adjust a numerical value logarithmically within a range. MainFunctionGui Container of widgets as a Main Application Window. MainWindow A Widget to contain other widgets, includes a menu bar. Password A one-line text editor that obscures input. ProgressBar A progress bar widget. PushButton A clickable command button. QuantityEdit A combined LineEdit and ComboBox to edit a pint.Quantity. RadioButton A radio button with a text label. RadioButtons An exclusive group of radio buttons, providing a choice from multiple choices. RangeEdit A widget to represent a python range object, with start/stop/step. RangeSlider A slider widget to adjust a range between two integer values within a range. Select A list of options, allowing selection between multiple choices. SliceEdit A widget to represent slice objects, with start/stop/step. Slider A slider widget to adjust an integer value within a range. SpinBox A widget to edit an integer with clickable up/down arrows. Table A widget to represent columnar or 2D data with headers. TextEdit A widget to edit and display both plain and rich text. TimeEdit A widget for editing times. ToolBar Toolbar that contains a set of controls. TupleEdit A widget to represent a tuple of values."},{"location":"api/widgets/CheckBox/","title":"CheckBox","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/CheckBox/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the button is clicked (may also be connected at the alias clicked).
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/CheckBox/#magicgui.widgets.CheckBox","title":"CheckBox","text":"

Bases: ButtonWidget

A checkbox with a text label.

Parameters:

  • value (bool, default: Undefined ) \u2013

    The starting state of the widget.

  • text (str, default: None ) \u2013

    The text to display on the button. If not provided, will use name.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/ComboBox/","title":"ComboBox","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/ComboBox/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/ComboBox/#magicgui.widgets.ComboBox","title":"ComboBox","text":"

Bases: CategoricalWidget

A dropdown menu, allowing selection between multiple choices.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The initially selected choice.

  • choices (Enum, Iterable, or Callable, default: () ) \u2013

    Available choices displayed in the combo box.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/Container/","title":"Container","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/Container/#signals","title":"Signals","text":"
  • changed(object) - Emitted with self when any sub-widget in the container changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/Container/#magicgui.widgets.Container","title":"Container","text":"

Bases: ContainerWidget[WidgetVar]

A Widget to contain other widgets.

Note that `Container` implements the\n[`typing.MutableSequence`][typing.MutableSequence]\ninterface, so you can use it like a list to add and remove widgets.\n

Parameters:

  • widgets (Sequence[Widget], default: () ) \u2013

    A sequence of widgets with which to initialize the container, by default None.

  • layout (str, default: 'vertical' ) \u2013

    The layout for the container. must be one of {'horizontal', 'vertical'}. by default \"vertical\"

  • scrollable (bool, default: False ) \u2013

    Whether to enable scroll bars or not. If enabled, scroll bars will only appear along the layout direction, not in both directions.

  • labels (bool, default: True ) \u2013

    Whether each widget should be shown with a corresponding Label widget to the left, by default True. Note: the text for each widget defaults to widget.name, but can be overridden by setting widget.label.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/DateEdit/","title":"DateEdit","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/DateEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/DateEdit/#magicgui.widgets.DateEdit","title":"DateEdit","text":"

Bases: ValueWidget[date]

A widget for editing dates.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/DateTimeEdit/","title":"DateTimeEdit","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/DateTimeEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/DateTimeEdit/#magicgui.widgets.DateTimeEdit","title":"DateTimeEdit","text":"

Bases: ValueWidget[datetime]

A widget for editing dates and times.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/Dialog/","title":"Dialog","text":"

Available in backends: qt

"},{"location":"api/widgets/Dialog/#signals","title":"Signals","text":"
  • changed(object) - Emitted with self when any sub-widget in the container changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/Dialog/#magicgui.widgets.Dialog","title":"Dialog","text":"

Bases: DialogWidget

A modal container.

Parameters:

  • widgets (Sequence[Widget], default: () ) \u2013

    A sequence of widgets with which to initialize the container, by default None.

  • layout (str, default: 'vertical' ) \u2013

    The layout for the container. must be one of {'horizontal', 'vertical'}. by default \"vertical\"

  • scrollable (bool, default: False ) \u2013

    Whether to enable scroll bars or not. If enabled, scroll bars will only appear along the layout direction, not in both directions.

  • labels (bool, default: True ) \u2013

    Whether each widget should be shown with a corresponding Label widget to the left, by default True. Note: the text for each widget defaults to widget.name, but can be overridden by setting widget.label.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/EmptyWidget/","title":"EmptyWidget","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/EmptyWidget/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/EmptyWidget/#magicgui.widgets.EmptyWidget","title":"EmptyWidget","text":"

Bases: ValueWidget

A base widget with no value.

This widget is primarily here to serve as a \"hidden widget\" to which a value or\ncallback can be bound.\n

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/EmptyWidget/#magicgui.widgets.EmptyWidget.value","title":"value: Any property writable","text":"

Look for a bound value, otherwise fallback to get_value.

"},{"location":"api/widgets/EmptyWidget/#magicgui.widgets.EmptyWidget.__repr__","title":"__repr__() -> str","text":"

Return string repr (avoid looking for value).

"},{"location":"api/widgets/EmptyWidget/#magicgui.widgets.EmptyWidget.get_value","title":"get_value() -> Any","text":"

Return value if one has been manually set... otherwise return Param.empty.

"},{"location":"api/widgets/FileEdit/","title":"FileEdit","text":"

Available in backends:

"},{"location":"api/widgets/FileEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted with self when any sub-widget in the container changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/FileEdit/#magicgui.widgets.FileEdit","title":"FileEdit","text":"

Bases: Container

A LineEdit widget with a button that opens a FileDialog.

Parameters:

  • mode (FileDialogMode or str, default: EXISTING_FILE ) \u2013
    • 'r' returns one existing file.
    • 'rm' return one or more existing files.
    • 'w' return one file name that does not have to exist.
    • 'd' returns one existing directory.
  • filter (str, default: None ) \u2013

    The filter is used to specify the kind of files that should be shown. It should be a glob-style string, like '*.png' (this may be backend-specific)

"},{"location":"api/widgets/FileEdit/#magicgui.widgets.FileEdit.mode","title":"mode: FileDialogMode property writable","text":"

Mode for the FileDialog.

"},{"location":"api/widgets/FileEdit/#magicgui.widgets.FileEdit.value","title":"value: tuple[Path, ...] | Path | None property writable","text":"

Return current value of the widget. This may be interpreted by backends.

"},{"location":"api/widgets/FileEdit/#magicgui.widgets.FileEdit.__repr__","title":"__repr__() -> str","text":"

Return string representation.

"},{"location":"api/widgets/FloatRangeSlider/","title":"FloatRangeSlider","text":"

Available in backends: qt

"},{"location":"api/widgets/FloatRangeSlider/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/FloatRangeSlider/#magicgui.widgets.FloatRangeSlider","title":"FloatRangeSlider","text":"

Bases: MultiValuedSliderWidget

A slider widget to adjust a range defined by two float values within a range.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • min (float, default: Undefined ) \u2013

    The minimum allowable value, by default 0 (or value if value is less than 0)

  • max (float, default: Undefined ) \u2013

    The maximum allowable value, by default 999 (or value if value is greater than 999)

  • step (float, default: Undefined ) \u2013

    The step size for incrementing the value, by default adaptive step is used

  • orientation ((str, {'horizontal', 'vertical'}), default: 'horizontal' ) \u2013

    The orientation for the slider, by default \"horizontal\"

  • readout (bool, default: True ) \u2013

    Whether to show the editable spinbox next to the slider

  • tracking (bool, default: True ) \u2013

    If tracking is enabled (the default), the slider emits the changed signal while the slider is being dragged. If tracking is disabled, the slider emits the changed signal only after the user releases the slider.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/FloatSlider/","title":"FloatSlider","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/FloatSlider/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/FloatSlider/#magicgui.widgets.FloatSlider","title":"FloatSlider","text":"

Bases: SliderWidget[float]

A slider widget to adjust an integer value within a range.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • min (float, default: Undefined ) \u2013

    The minimum allowable value, by default 0 (or value if value is less than 0)

  • max (float, default: Undefined ) \u2013

    The maximum allowable value, by default 999 (or value if value is greater than 999)

  • step (float, default: Undefined ) \u2013

    The step size for incrementing the value, by default adaptive step is used

  • orientation ((str, {'horizontal', 'vertical'}), default: 'horizontal' ) \u2013

    The orientation for the slider, by default \"horizontal\"

  • readout (bool, default: True ) \u2013

    Whether to show the editable spinbox next to the slider

  • tracking (bool, default: True ) \u2013

    If tracking is enabled (the default), the slider emits the changed signal while the slider is being dragged. If tracking is disabled, the slider emits the changed signal only after the user releases the slider.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/FloatSpinBox/","title":"FloatSpinBox","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/FloatSpinBox/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/FloatSpinBox/#magicgui.widgets.FloatSpinBox","title":"FloatSpinBox","text":"

Bases: RangedWidget[float]

A widget to edit a float with clickable up/down arrows.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • min (float, default: Undefined ) \u2013

    The minimum allowable value, by default 0 (or value if value is less than 0)

  • max (float, default: Undefined ) \u2013

    The maximum allowable value, by default 999 (or value if value is greater than 999)

  • step (float, default: Undefined ) \u2013

    The step size for incrementing the value, by default adaptive step is used

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/FunctionGui/","title":"FunctionGui","text":"

Available in backends:

"},{"location":"api/widgets/FunctionGui/#signals","title":"Signals","text":"
  • called(object) - Emitted with the result after the function is called.
  • changed(object) - Emitted with self when any sub-widget in the container changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui","title":"FunctionGui","text":"

Bases: Container, Generic[_P, _R]

Wrapper for a container of widgets representing a callable object.

Parameters:

  • function (Callable) \u2013

    A callable to turn into a GUI

  • call_button (bool | str | None, default: None ) \u2013

    If True, create an additional button that calls the original function when clicked. If a str, set the button text. by default False when auto_call is True, and True otherwise. The button can be accessed from the .call_button property.

  • layout (str, default: 'vertical' ) \u2013

    The type of layout to use. Must be horizontal or vertical by default \"horizontal\".

  • scrollable (bool, default: False ) \u2013

    Whether to enable scroll bars or not. If enabled, scroll bars will only appear along the layout direction, not in both directions.

  • labels (bool, default: True ) \u2013

    Whether labels are shown in the widget. by default True

  • tooltips (bool, default: True ) \u2013

    Whether tooltips are shown when hovering over widgets. by default True

  • app (Application | str | None, default: None ) \u2013

    A backend to use, by default None (use the default backend.)

  • visible (bool, default: None ) \u2013

    Whether to immediately show the widget. If False, widget is explicitly hidden. If None, widget is not shown, but will be shown if a parent container is shown, by default None.

  • auto_call (bool, default: False ) \u2013

    If True, changing any parameter in either the GUI or the widget attributes will call the original function with the current settings. by default False

  • result_widget (bool, default: False ) \u2013

    Whether to display a LineEdit widget the output of the function when called, by default False

  • param_options (dict, default: None ) \u2013

    A dict of name: widget_options dict for each parameter in the function. Will be passed to magic_signature by default None

  • name (str, default: None ) \u2013

    A name to assign to the Container widget, by default function.__name__

  • persist (bool, default: False ) \u2013

    If True, when parameter values change in the widget, they will be stored to disk (in ~/.config/magicgui/cache) and restored when the widget is loaded again with persist = True. By default, False.

  • raise_on_unknown (bool, default: False ) \u2013

    If True, raise an error if a parameter annotation is not recognized.

Raises:

  • TypeError \u2013

    If unexpected keyword arguments are provided

"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.__signature__","title":"__signature__: MagicSignature property","text":"

Return a MagicSignature object representing the current state of the gui.

"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.call_button","title":"call_button: PushButton | None property","text":"

Return the call button.

"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.call_count","title":"call_count: int property","text":"

Return the number of times the function has been called.

"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.result_name","title":"result_name: str property writable","text":"

Return a name that can be used for the result of this magicfunction.

"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.return_annotation","title":"return_annotation: Any property","text":"

Return annotation for inspect.Signature conversion.

ForwardRefs will be resolve when setting the annotation.

"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.__call__","title":"__call__(*args: _P.args, **kwargs: _P.kwargs) -> _R","text":"

Call the original function with the current parameter values from the Gui.

You may pass a update_widget=True keyword argument to update the widget values to match the current parameter values before calling the function.

It is also possible to override the current parameter values from the GUI by providing args/kwargs to the function call. Only those provided will override the ones from the gui. A called signal will also be emitted with the results.

Returns:

  • result ( Any ) \u2013

    whatever the return value of the original function would have been.

Examples:

gui = FunctionGui(func, show=True)\n\n# then change parameters in the gui, or by setting:  gui.param.value = something\n\ngui()  # calls the original function with the current parameters\n
"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.__get__","title":"__get__(obj: object, objtype: type | None = None) -> FunctionGui","text":"

Provide descriptor protocol.

This allows the @magicgui decorator to work on a function as well as a method. If a method on a class is decorated with @magicgui, then accessing the attribute on an instance of that class will return a version of the FunctionGui in which the first argument of the function is bound to the instance. (Just like what you'd expect with the @property decorator.)

Returns:

  • bound ( FunctionGui ) \u2013

    A new FunctionGui instance.

Examples:

>>> class MyClass:\n...     @magicgui\n...     def my_method(self, x=1):\n...         print(locals())\n...\n>>> c = MyClass()\n>>> c.my_method  # the FunctionGui that can be used as a widget\n\n# calling it works as usual, with `c` provided as `self`\n>>> c.my_method(x=34)\n{'self': <__main__.MyClass object at 0x7fb610e455e0>, 'x': 34}\n
"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.__init__","title":"__init__(function: Callable[_P, _R], call_button: bool | str | None = None, layout: str = 'vertical', scrollable: bool = False, labels: bool = True, tooltips: bool = True, app: AppRef | None = None, visible: bool | None = None, auto_call: bool = False, result_widget: bool = False, param_options: dict[str, dict] | None = None, name: str | None = None, persist: bool = False, raise_on_unknown: bool = False, **kwargs: Any)","text":""},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.__repr__","title":"__repr__() -> str","text":"

Return string representation of instance.

"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.__set__","title":"__set__(obj: Any, value: Any) -> NoReturn","text":"

Prevent setting a magicgui attribute.

"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.copy","title":"copy() -> FunctionGui","text":"

Return a copy of this FunctionGui.

"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.reset_call_count","title":"reset_call_count() -> None","text":"

Reset the call count to 0.

"},{"location":"api/widgets/Image/","title":"Image","text":"

Available in backends: qt

"},{"location":"api/widgets/Image/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/Image/#magicgui.widgets.Image","title":"Image","text":"

Bases: ValueWidget

A non-editable image display.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/Image/#magicgui.widgets.Image.image_data","title":"image_data: np.ndarray | None property","text":"

Return image data.

"},{"location":"api/widgets/Image/#magicgui.widgets.Image.image_rgba","title":"image_rgba: np.ndarray | None property","text":"

Return rendered numpy array.

"},{"location":"api/widgets/Image/#magicgui.widgets.Image.value","title":"value property writable","text":"

Return current image array.

"},{"location":"api/widgets/Image/#magicgui.widgets.Image.__repr__","title":"__repr__() -> str","text":"

Return representation of widget of instance.

"},{"location":"api/widgets/Image/#magicgui.widgets.Image.get_clim","title":"get_clim() -> tuple[float | None, float | None]","text":"

Get contrast limits (for monochromatic images).

"},{"location":"api/widgets/Image/#magicgui.widgets.Image.scale_widget_to_image_size","title":"scale_widget_to_image_size()","text":"

Set the size of the widget to the size of the image.

"},{"location":"api/widgets/Image/#magicgui.widgets.Image.set_clim","title":"set_clim(vmin: float | None = None, vmax: float | None = None)","text":"

Set contrast limits (for monochromatic images).

Parameters:

  • vmin (float, default: None ) \u2013

    The min contrast limit to use when scaling monochromatic images

  • vmax (float, default: None ) \u2013

    The max contrast limit to use when scaling monochromatic images

"},{"location":"api/widgets/Image/#magicgui.widgets.Image.set_cmap","title":"set_cmap(cmap: str | Colormap | matplotlib.colors.Colormap)","text":"

Set colormap (for monochromatic images).

Parameters:

  • cmap (str, magicgui.types.Colormap, or matplotlib.colors.Colormap) \u2013

    A colormap to use for monochromatic images. If a string, matplotlib must be installed and the colormap will be selected with cm.get_cmap(cmap).

"},{"location":"api/widgets/Image/#magicgui.widgets.Image.set_data","title":"set_data(val: str | Path | np.ndarray | PIL.Image.Image, cmap: str | Colormap | matplotlib.colors.Colormap | None = None, norm: _mpl_image.Normalize | matplotlib.colors.Normalize | None = None, vmin: float | None = None, vmax: float | None = None, width: int | Literal['auto'] | None = None, height: int | Literal['auto'] | None = None, format: str | None = None)","text":"

Set image data with various optional display parameters.

Parameters:

  • val ((str, Path, ndarray or Image)) \u2013

    The image data or file to load. Data must be 2D (monochromatic), or 3D: MxNx3 (RGB) or MxNx4 (RGBA).

  • cmap (str, magicgui.types.Colormap, or matplotlib.colors.Colormap, default: None ) \u2013

    A colormap to use for monochromatic images. If a string, matplotlib must be installed and the colormap will be selected with cm.get_cmap(cmap).

  • norm (magicgui.types.Normalize, or matplotlib.colors.Normalize, default: None ) \u2013

    A normalization object to use for rendering images. Accepts matplotlib Normalize objects.

  • vmin (float, default: None ) \u2013

    The min contrast limit to use when scaling monochromatic images

  • vmax (float, default: None ) \u2013

    The max contrast limit to use when scaling monochromatic images

  • width (int or 'auto', default: None ) \u2013

    Set the width of the widget. If \"auto\", sets the widget size to the image size (1:1). If width is provided, height is auto-set based on aspect ratio.

  • height (int or 'auto', default: None ) \u2013

    Set the height of the widget. If \"auto\", sets the widget size to the image size (1:1). If width is provided, height is auto-set based on aspect ratio.

  • format (str, default: None ) \u2013

    Force image format type for imread when val is provided as a string, by default None

Raises:

  • TypeError \u2013

    If the provided data shape or type is invalid.

  • ImportError \u2013

    If a string is provided for val and PIL is not installed.

  • RuntimeError \u2013

    If a PIL.Image.Image instance is provided as data, with an unrecognized image mode.

"},{"location":"api/widgets/Image/#magicgui.widgets.Image.set_norm","title":"set_norm(norm: Normalize | matplotlib.colors.Normalize)","text":"

Set normalization method.

Parameters:

  • norm (magicgui.types.Normalize, or matplotlib.colors.Normalize) \u2013

    A normalization object to use for rendering images. Accepts matplotlib Normalize objects.

"},{"location":"api/widgets/Label/","title":"Label","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/Label/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/Label/#magicgui.widgets.Label","title":"Label","text":"

Bases: ValueWidget[str]

A non-editable text display.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/LineEdit/","title":"LineEdit","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/LineEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/LineEdit/#magicgui.widgets.LineEdit","title":"LineEdit","text":"

Bases: ValueWidget[str]

A one-line text editor.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/ListEdit/","title":"ListEdit","text":"

Available in backends:

"},{"location":"api/widgets/ListEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted with self when any sub-widget in the container changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/ListEdit/#magicgui.widgets.ListEdit","title":"ListEdit","text":"

Bases: Container[ValueWidget[_V]]

A widget to represent a list of values.

A ListEdit container can create a list with multiple objects of same type. It\nwill contain many child widgets and their value is represented as a Python list\nobject. If a list is given as the initial value, types of child widgets are\ndetermined from the contents. Number of contents can be adjusted with +/-\nbuttons.\n

Parameters:

  • value (Iterable, default: Undefined ) \u2013

    The starting value for the widget.

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • options (dict, default: None ) \u2013

    Widget options of child widgets.

"},{"location":"api/widgets/ListEdit/#magicgui.widgets.ListEdit.annotation","title":"annotation: Any property writable","text":"

Return type annotation for the parameter represented by the widget.

ForwardRefs will be resolve when setting the annotation. For ListEdit, annotation will be like 'list[str]'.

"},{"location":"api/widgets/ListEdit/#magicgui.widgets.ListEdit.data","title":"data: ListDataView[_V] property writable","text":"

Return a data view of current value.

"},{"location":"api/widgets/ListEdit/#magicgui.widgets.ListEdit.value","title":"value: list[_V] property writable","text":"

Return current value as a list object.

"},{"location":"api/widgets/ListEdit/#magicgui.widgets.ListEdit.__delitem__","title":"__delitem__(key: int | slice) -> None","text":"

Delete child widget(s).

"},{"location":"api/widgets/LiteralEvalLineEdit/","title":"LiteralEvalLineEdit","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/LiteralEvalLineEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/LiteralEvalLineEdit/#magicgui.widgets.LiteralEvalLineEdit","title":"LiteralEvalLineEdit","text":"

Bases: ValueWidget[str]

A one-line text editor that evaluates strings as python literals.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/LogSlider/","title":"LogSlider","text":"

Available in backends:

"},{"location":"api/widgets/LogSlider/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/LogSlider/#magicgui.widgets.LogSlider","title":"LogSlider","text":"

Bases: TransformedRangedWidget

A slider widget to adjust a numerical value logarithmically within a range.

Parameters:

  • base (Enum, Iterable, or Callable, default: e ) \u2013

    The base to use for the log, by default math.e.

"},{"location":"api/widgets/LogSlider/#magicgui.widgets.LogSlider.base","title":"base: float property writable","text":"

Return base used for the log.

"},{"location":"api/widgets/LogSlider/#magicgui.widgets.LogSlider.tracking","title":"tracking: bool property writable","text":"

Return whether slider tracking is enabled.

If tracking is enabled (the default), the slider emits the changed() signal while the slider is being dragged. If tracking is disabled, the slider emits the changed() signal only when the user releases the slider.

"},{"location":"api/widgets/MainFunctionGui/","title":"MainFunctionGui","text":"

Available in backends:

"},{"location":"api/widgets/MainFunctionGui/#signals","title":"Signals","text":"
  • called(object) - Emitted with the result after the function is called.
  • changed(object) - Emitted with self when any sub-widget in the container changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/MainFunctionGui/#magicgui.widgets.MainFunctionGui","title":"MainFunctionGui","text":"

Bases: FunctionGui[_P, _R], MainWindow

Container of widgets as a Main Application Window.

"},{"location":"api/widgets/MainWindow/","title":"MainWindow","text":"

Available in backends: qt

"},{"location":"api/widgets/MainWindow/#signals","title":"Signals","text":"
  • changed(object) - Emitted with self when any sub-widget in the container changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/MainWindow/#magicgui.widgets.MainWindow","title":"MainWindow","text":"

Bases: MainWindowWidget

A Widget to contain other widgets, includes a menu bar.

Parameters:

  • widgets (Sequence[Widget], default: () ) \u2013

    A sequence of widgets with which to initialize the container, by default None.

  • layout (str, default: 'vertical' ) \u2013

    The layout for the container. must be one of {'horizontal', 'vertical'}. by default \"vertical\"

  • scrollable (bool, default: False ) \u2013

    Whether to enable scroll bars or not. If enabled, scroll bars will only appear along the layout direction, not in both directions.

  • labels (bool, default: True ) \u2013

    Whether each widget should be shown with a corresponding Label widget to the left, by default True. Note: the text for each widget defaults to widget.name, but can be overridden by setting widget.label.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/Password/","title":"Password","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/Password/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/Password/#magicgui.widgets.Password","title":"Password","text":"

Bases: ValueWidget[str]

A one-line text editor that obscures input.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/ProgressBar/","title":"ProgressBar","text":"

Available in backends: qt

"},{"location":"api/widgets/ProgressBar/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/ProgressBar/#magicgui.widgets.ProgressBar","title":"ProgressBar","text":"

Bases: SliderWidget[float]

A progress bar widget.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • min (float, default: Undefined ) \u2013

    The minimum allowable value, by default 0 (or value if value is less than 0)

  • max (float, default: Undefined ) \u2013

    The maximum allowable value, by default 999 (or value if value is greater than 999)

  • step (float, default: Undefined ) \u2013

    The step size for incrementing the value, by default adaptive step is used

  • orientation ((str, {'horizontal', 'vertical'}), default: 'horizontal' ) \u2013

    The orientation for the slider, by default \"horizontal\"

  • readout (bool, default: True ) \u2013

    Whether to show the editable spinbox next to the slider

  • tracking (bool, default: True ) \u2013

    If tracking is enabled (the default), the slider emits the changed signal while the slider is being dragged. If tracking is disabled, the slider emits the changed signal only after the user releases the slider.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/ProgressBar/#magicgui.widgets.ProgressBar.step","title":"step: float property writable","text":"

Step size for widget values.

"},{"location":"api/widgets/ProgressBar/#magicgui.widgets.ProgressBar.decrement","title":"decrement(val: float | None = None) -> None","text":"

Decrease current value by step size, or provided value.

"},{"location":"api/widgets/ProgressBar/#magicgui.widgets.ProgressBar.increment","title":"increment(val: float | None = None) -> None","text":"

Increase current value by step size, or provided value.

"},{"location":"api/widgets/PushButton/","title":"PushButton","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/PushButton/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the button is clicked (may also be connected at the alias clicked).
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/PushButton/#magicgui.widgets.PushButton","title":"PushButton","text":"

Bases: ButtonWidget

A clickable command button.

Parameters:

  • value (bool, default: Undefined ) \u2013

    The starting state of the widget.

  • text (str, default: None ) \u2013

    The text to display on the button. If not provided, will use name.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/QuantityEdit/","title":"QuantityEdit","text":"

Available in backends: qt

"},{"location":"api/widgets/QuantityEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/QuantityEdit/#magicgui.widgets.QuantityEdit","title":"QuantityEdit","text":"

Bases: ValueWidget

A combined LineEdit and ComboBox to edit a pint.Quantity.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/RadioButton/","title":"RadioButton","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/RadioButton/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the button is clicked (may also be connected at the alias clicked).
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/RadioButton/#magicgui.widgets.RadioButton","title":"RadioButton","text":"

Bases: ButtonWidget

A radio button with a text label.

Parameters:

  • value (bool, default: Undefined ) \u2013

    The starting state of the widget.

  • text (str, default: None ) \u2013

    The text to display on the button. If not provided, will use name.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/RadioButtons/","title":"RadioButtons","text":"

Available in backends: qt

"},{"location":"api/widgets/RadioButtons/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/RadioButtons/#magicgui.widgets.RadioButtons","title":"RadioButtons","text":"

Bases: CategoricalWidget, _OrientationMixin

An exclusive group of radio buttons, providing a choice from multiple choices.

Parameters:

  • value (Any) \u2013

    The initially selected choice.

  • choices (Enum, Iterable, or Callable, default: () ) \u2013

    Available choices displayed in the combo box.

  • bind (Callable[[ValueWidget], Any] | Any) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/RangeEdit/","title":"RangeEdit","text":"

Available in backends:

"},{"location":"api/widgets/RangeEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted with self when any sub-widget in the container changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/RangeEdit/#magicgui.widgets.RangeEdit","title":"RangeEdit","text":"

Bases: Container[SpinBox]

A widget to represent a python range object, with start/stop/step.

A range object produces a sequence of integers from start (inclusive)\nto stop (exclusive) by step.  range(i, j) produces i, i+1, i+2, ..., j-1.\nstart defaults to 0, and stop is omitted!  range(4) produces 0, 1, 2, 3.\nThese are exactly the valid indices for a list of 4 elements.\nWhen step is given, it specifies the increment (or decrement).\n

Parameters:

  • start (int, default: 0 ) \u2013

    The range start value, by default 0

  • stop (int, default: 10 ) \u2013

    The range stop value, by default 10

  • step (int, default: 1 ) \u2013

    The range step value, by default 1

"},{"location":"api/widgets/RangeEdit/#magicgui.widgets.RangeEdit.value","title":"value: range property writable","text":"

Return current value of the widget. This may be interpreted by backends.

"},{"location":"api/widgets/RangeEdit/#magicgui.widgets.RangeEdit.__repr__","title":"__repr__() -> str","text":"

Return string representation.

"},{"location":"api/widgets/RangeSlider/","title":"RangeSlider","text":"

Available in backends: qt

"},{"location":"api/widgets/RangeSlider/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/RangeSlider/#magicgui.widgets.RangeSlider","title":"RangeSlider","text":"

Bases: MultiValuedSliderWidget

A slider widget to adjust a range between two integer values within a range.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • min (float, default: Undefined ) \u2013

    The minimum allowable value, by default 0 (or value if value is less than 0)

  • max (float, default: Undefined ) \u2013

    The maximum allowable value, by default 999 (or value if value is greater than 999)

  • step (float, default: Undefined ) \u2013

    The step size for incrementing the value, by default adaptive step is used

  • orientation ((str, {'horizontal', 'vertical'}), default: 'horizontal' ) \u2013

    The orientation for the slider, by default \"horizontal\"

  • readout (bool, default: True ) \u2013

    Whether to show the editable spinbox next to the slider

  • tracking (bool, default: True ) \u2013

    If tracking is enabled (the default), the slider emits the changed signal while the slider is being dragged. If tracking is disabled, the slider emits the changed signal only after the user releases the slider.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/Select/","title":"Select","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/Select/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/Select/#magicgui.widgets.Select","title":"Select","text":"

Bases: CategoricalWidget

A list of options, allowing selection between multiple choices.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The initially selected choice.

  • choices (Enum, Iterable, or Callable, default: () ) \u2013

    Available choices displayed in the combo box.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/SliceEdit/","title":"SliceEdit","text":"

Available in backends:

"},{"location":"api/widgets/SliceEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted with self when any sub-widget in the container changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/SliceEdit/#magicgui.widgets.SliceEdit","title":"SliceEdit","text":"

Bases: RangeEdit

A widget to represent slice objects, with start/stop/step.

slice(stop) slice(start, stop[, step])

Slice objects may be used for extended slicing (e.g. a[0:10:2])

"},{"location":"api/widgets/SliceEdit/#magicgui.widgets.SliceEdit.value","title":"value: slice property writable","text":"

Return current value of the widget. This may be interpreted by backends.

"},{"location":"api/widgets/Slider/","title":"Slider","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/Slider/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/Slider/#magicgui.widgets.Slider","title":"Slider","text":"

Bases: SliderWidget[int]

A slider widget to adjust an integer value within a range.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • min (float, default: Undefined ) \u2013

    The minimum allowable value, by default 0 (or value if value is less than 0)

  • max (float, default: Undefined ) \u2013

    The maximum allowable value, by default 999 (or value if value is greater than 999)

  • step (float, default: Undefined ) \u2013

    The step size for incrementing the value, by default adaptive step is used

  • orientation ((str, {'horizontal', 'vertical'}), default: 'horizontal' ) \u2013

    The orientation for the slider, by default \"horizontal\"

  • readout (bool, default: True ) \u2013

    Whether to show the editable spinbox next to the slider

  • tracking (bool, default: True ) \u2013

    If tracking is enabled (the default), the slider emits the changed signal while the slider is being dragged. If tracking is disabled, the slider emits the changed signal only after the user releases the slider.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/SpinBox/","title":"SpinBox","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/SpinBox/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/SpinBox/#magicgui.widgets.SpinBox","title":"SpinBox","text":"

Bases: RangedWidget[int]

A widget to edit an integer with clickable up/down arrows.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • min (float, default: Undefined ) \u2013

    The minimum allowable value, by default 0 (or value if value is less than 0)

  • max (float, default: Undefined ) \u2013

    The maximum allowable value, by default 999 (or value if value is greater than 999)

  • step (float, default: Undefined ) \u2013

    The step size for incrementing the value, by default adaptive step is used

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/Table/","title":"Table","text":"

Available in backends: qt

"},{"location":"api/widgets/Table/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/Table/#magicgui.widgets.Table","title":"Table","text":"

Bases: ValueWidget, _ReadOnlyMixin, MutableMapping[TblKey, list]

A widget to represent columnar or 2D data with headers.

Tables behave like plain dicts, where the keys are column headers and the (list-like) values are column data.

Parameters:

  • value ((dict, dataframe, list, array, tuple), default: None ) \u2013

    Table data (and/or header data), in one of the accepted formats:

    • list or list-of-lists : [column_values] or [[row_vals], ..., [row_vals]]
    • dict-of-dicts : {column_header -> {row_header -> value}}
    • dict-of-lists : {column_header -> [column_values]}
    • list-of-row-records : [{column_headers -> value}, ... , {column_headers -> value}]
    • split-dict-of-lists :
    • tuple-of-values : ([values], [row_headers], [column_headers])
    • dict-of-pandas-series : {column_header -> Series(values)}
  • index (Collection, default: None ) \u2013

    A sized iterable container of row headers. By default, row headers will be tuple(range(len(data))). Values provided here override any implied in value.

  • columns (Collection, default: None ) \u2013

    A sized iterable container of column headers. By default, column headers will be tuple(range(len(data[0]))). Values provided here override any implied in value.

  • **kwargs (Unpack[WidgetKwargs], default: {} ) \u2013

    Additional kwargs will be passed to the magicgui.widgets.Widget constructor.

Attributes:

  • value (dict) \u2013

    Returns a dict with the keys data, index, and columns ... representing the 2D (list of lists) tabular data, row headers, and column headers, respectively. If set, will clear and update the table using the new data.

  • data (DataView) \u2013

    A DataView instance that provides numpy-like indexing (with get/set/delete) onto the 2D data array, For example table.data[0,2] gets the data in the cell of the first row, 3rd column. Works with numpy slice syntax.

  • column_headers (tuple) \u2013

    The current column headers. Can be set with a new sequence to change

  • row_headers (tuple) \u2013

    The current row headers. Can be set with a new sequence to change

  • shape (tuple of int) \u2013

    The shape of the table in (rows, columns).

  • size (int) \u2013

    The number of cells in the table.

Methods:

  • keys \u2013

    Return a TableHeadersView, providing a view on this table's headers. Use axis='row' for row headers.

  • items \u2013

    Return a TableItemsView, providing a view on this table's items, as 2-tuples of (header, data). Use axis='row' for (row_header, row_data)

  • clear \u2013

    Clear all table data and headers.

  • to_dataframe \u2013

    Returns a pandas dataframe representation of this table. (requires pandas)

  • to_dict \u2013

    Return one of many different dict-like representations of table and header data. See docstring of :meth:to_dict for details.

Events

changed Emitted whenever a cell in the table changes. The value will have a dict of information regarding the cell that changed: {'data': x, 'row': int, 'column': int, 'column_header': str, 'row_header': str} CURRENTLY: only emitted on changes in the GUI. not programmatic changes.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.column_headers","title":"column_headers: tuple property writable","text":"

Return column headers.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.data","title":"data: DataView property writable","text":"

Return DataView object for this table.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.row_headers","title":"row_headers: tuple property writable","text":"

Return row headers.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.shape","title":"shape: tuple[int, int] property","text":"

Return shape of table widget (rows, cols).

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.size","title":"size: int property","text":"

Return shape of table widget (rows, cols).

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.value","title":"value: dict[TblKey, Collection] property writable","text":"

Return dict with current data, index, and columns of the widget.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.__delitem__","title":"__delitem__(key: TblKey) -> None","text":"

Delete a column from the table.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.__getitem__","title":"__getitem__(key: TblKey) -> list","text":"

Get a column from the table.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.__hash__","title":"__hash__() -> int","text":"

Make table hashable.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.__iter__","title":"__iter__() -> Iterator","text":"

Yield column headers.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.__len__","title":"__len__() -> int","text":"

Return number of columns.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.__new__","title":"__new__(value: TableData | None = None, *, index: Collection | None = None, columns: Collection | None = None, **kwargs: Any) -> Table","text":"

Just for the signature.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.__repr__","title":"__repr__() -> str","text":"

Return string repr.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.__setitem__","title":"__setitem__(key: TblKey, v: Collection) -> None","text":"

Set a column in the table. If k doesn't exist, make a new column.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.clear","title":"clear() -> None","text":"

Clear the table.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.delete_row","title":"delete_row(*, index: int | Sequence[int] | None = None, header: Any | Sequence[Any] | None = None) -> None","text":"

Delete row(s) by index or header.

Parameters:

  • index (int or Sequence[int], default: None ) \u2013

    Index or indices of row(s) to delete.

  • header (Any or Sequence[Any], default: None ) \u2013

    Header or headers of row(s) to delete.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.items","title":"items(axis: str = 'column') -> TableItemsView[TblKey, list]","text":"

Return a set-like object providing a view on this table's items.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.keys","title":"keys(axis: str = 'column') -> HeadersView[TblKey]","text":"

Return a set-like object providing a view on this table's headers.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.to_dataframe","title":"to_dataframe() -> pandas.DataFrame","text":"

Convert TableData to dataframe.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.to_dict","title":"to_dict(orient: str = 'dict') -> list | dict","text":"

Convert the Table to a dictionary.

The type of the key-value pairs can be customized with the parameters (see below).

Parameters:

  • orient (str {'dict', 'list', 'series', 'split', 'records', 'index'}, default: 'dict' ) \u2013

    Determines the type of the values of the dictionary.

    • 'dict' (default) : dict like {column -> {index -> value}}
    • 'list' : dict like {column -> [values]}
    • 'split' : dict like
    • 'records' : list like [{column -> value}, ... , {column -> value}]
    • 'index' : dict like {index -> {column -> value}}
    • 'series' : dict like {column -> Series(values)}
"},{"location":"api/widgets/TextEdit/","title":"TextEdit","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/TextEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/TextEdit/#magicgui.widgets.TextEdit","title":"TextEdit","text":"

Bases: ValueWidget[str], _ReadOnlyMixin

A widget to edit and display both plain and rich text.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/TimeEdit/","title":"TimeEdit","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/TimeEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/TimeEdit/#magicgui.widgets.TimeEdit","title":"TimeEdit","text":"

Bases: ValueWidget[TV]

A widget for editing times.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/ToolBar/","title":"ToolBar","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/ToolBar/#signals","title":"Signals","text":"
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/ToolBar/#magicgui.widgets.ToolBar","title":"ToolBar","text":"

Bases: ToolBarWidget

Toolbar that contains a set of controls.

Parameters:

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/TupleEdit/","title":"TupleEdit","text":"

Available in backends:

"},{"location":"api/widgets/TupleEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted with self when any sub-widget in the container changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/TupleEdit/#magicgui.widgets.TupleEdit","title":"TupleEdit","text":"

Bases: Container[ValueWidget]

A widget to represent a tuple of values.

A TupleEdit container has several child widgets of different type. Their value is\nrepresented as a Python tuple object. If a tuple is given as the initial value,\ntypes of child widgets are determined one by one. Unlike ListEdit, number of\ncontents is not editable.\n

Parameters:

  • value (Iterable, default: Undefined ) \u2013

    The starting value for the widget.

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • options (dict, default: None ) \u2013

    Widget options of child widgets.

"},{"location":"api/widgets/TupleEdit/#magicgui.widgets.TupleEdit.annotation","title":"annotation: Any property writable","text":"

Return type annotation for the parameter represented by the widget.

ForwardRefs will be resolve when setting the annotation. For TupleEdit, annotation will be like 'tuple[str, int]'.

"},{"location":"api/widgets/TupleEdit/#magicgui.widgets.TupleEdit.value","title":"value: tuple property writable","text":"

Return current value as a tuple.

"},{"location":"api/widgets/bases/","title":"magicgui.widgets.bases","text":"

The magicgui.widgets.bases module contains the base classes for all widgets.

While most users will never instantiate these classes directly, the methods and properties of these classes are inherited by all widgets, and define the common API for all widgets. Therefore, it is worth being aware of the type of widget you are working with.

"},{"location":"api/widgets/bases/#summary","title":"Summary","text":"Widget Description Widget Basic Widget, wrapping a class that implements WidgetProtocol. ButtonWidget Widget with a value, Wraps a widget implementing the ButtonWidgetProtocol. CategoricalWidget Widget with a value and choices. Wraps CategoricalWidgetProtocol. ContainerWidget Widget that can contain other widgets. DialogWidget Modal Container. MainWindowWidget Top level Application widget that can contain other widgets. RangedWidget Widget with a constrained value. Wraps RangedWidgetProtocol. SliderWidget Widget with a constrained value and orientation. Wraps SliderWidgetProtocol. ValueWidget Widget with a value, Wraps ValueWidgetProtocol."},{"location":"api/widgets/bases/#class-hierarchy","title":"Class Hierarchy","text":"

In visual form, the widget class hierarchy looks like this:

classDiagram\n    Widget <|-- ValueWidget\n    Widget <|-- ContainerWidget\n    BackendWidget ..|> WidgetProtocol : implements a\n    ValueWidget <|-- RangedWidget\n    ValueWidget <|-- ButtonWidget\n    ValueWidget <|-- CategoricalWidget\n    RangedWidget <|-- SliderWidget\n    Widget --* WidgetProtocol : controls a\n    <<Interface>> WidgetProtocol\n    class WidgetProtocol {\n        _mgui_get_X()\n        _mgui_set_X()\n    }\n    class Widget{\n        name: str\n        annotation: Any\n        label: str\n        tooltip: str\n        visible: bool\n        enabled: bool\n        native: Any\n        height: int\n        width: int\n        hide()\n        show()\n        close()\n        render()\n    }\n    class ValueWidget{\n        value: Any\n        changed: SignalInstance\n        bind(value, call) Any\n        unbind()\n    }\n    class RangedWidget{\n        value: float | tuple\n        min: float\n        max: float\n        step: float\n        adaptive_step: bool\n        range: tuple[float, float]\n    }\n    class SliderWidget{\n        orientation: str\n    }\n    class ButtonWidget{\n        value: bool\n        clicked: SignalInstance\n        text: str\n    }\n    class CategoricalWidget{\n        choices: List[Any]\n    }\n    class ContainerWidget{\n        widgets: List[Widget]\n        labels: bool\n        layout: str\n        margins: tuple[int, int, int, int]\n        reset_choices()\n        asdict() Dict[str, Any]\n        update(mapping)\n    }\n\n    click Widget href \"#magicgui.widgets.bases.Widget\"\n    click ValueWidget href \"#magicgui.widgets.bases.ValueWidget\"\n    click RangedWidget href \"#magicgui.widgets.bases.RangedWidget\"\n    click SliderWidget href \"#magicgui.widgets.bases.SliderWidget\"\n    click ButtonWidget href \"#magicgui.widgets.bases.ButtonWidget\"\n    click CategoricalWidget href \"#magicgui.widgets.bases.CategoricalWidget\"\n    click ContainerWidget href \"#magicgui.widgets.bases.ContainerWidget\"\n
"},{"location":"api/widgets/bases/#base-widget-classes","title":"Base Widget Classes","text":""},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget","title":"magicgui.widgets.bases.Widget","text":"

Basic Widget, wrapping a class that implements WidgetProtocol.

Parameters:

  • widget_type (type[WidgetProtocol]) \u2013

    A class implementing a widget protocol. Will be instantiated during init.

  • name (str, default: '' ) \u2013

    The name of the parameter represented by this widget. by default \"\"

  • annotation (Any, default: None ) \u2013

    The type annotation for the parameter represented by the widget, by default None

  • label (str, default: None ) \u2013

    A string to use for an associated Label widget (if this widget is being shown in a Container widget, and labels are on). By default, name will be used. Note: name refers the name of the parameter, as might be used in a signature, whereas label is just the label for that widget in the GUI.

  • tooltip (str, default: None ) \u2013

    A tooltip to display when hovering over the widget.

  • visible (bool, default: None ) \u2013

    Whether the widget is visible, by default True.

  • enabled (bool, default: True ) \u2013

    Whether the widget is enabled, by default True.

  • gui_only (bool, default: False ) \u2013

    If True, widget is excluded from any function signature representation. by default False. (This will likely be deprecated.)

  • parent (Any, default: None ) \u2013

    Optional parent widget of this widget. CAREFUL: if a parent is set, and subsequently deleted, this widget will likely be deleted as well (depending on the backend), and will no longer be usable.

  • backend_kwargs (dict, default: None ) \u2013

    keyword argument to pass to the backend widget constructor.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.annotation","title":"annotation: Any property writable","text":"

Return type annotation for the parameter represented by the widget.

ForwardRefs will be resolve when setting the annotation.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.enabled","title":"enabled: bool property writable","text":"

Whether widget is enabled (editable).

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.height","title":"height: int property writable","text":"

Return the current height of the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.label","title":"label: str property writable","text":"

Return a label to use for this widget when present in Containers.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.max_height","title":"max_height: int property writable","text":"

Get the maximum height of the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.max_width","title":"max_width: int property writable","text":"

Get the maximum width of the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.min_height","title":"min_height: int property writable","text":"

Get the minimum height of the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.min_width","title":"min_width: int property writable","text":"

Get the minimum width of the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.native","title":"native: Any property","text":"

Return native backend widget.

Note this is the widget that contains the layout, and not any parent widgets of this (e.g. a parent widget that is used to enable scroll bars)

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.options","title":"options: dict property","text":"

Return options currently being used in this widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.param_kind","title":"param_kind: inspect._ParameterKind property writable","text":"

Return :attr:inspect.Parameter.kind represented by this widget.

Used in building signatures from multiple widgets, by default :attr:~inspect.Parameter.POSITIONAL_OR_KEYWORD

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.parent","title":"parent: Widget property writable","text":"

Return the parent widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.parent_changed","title":"parent_changed: SignalInstance property","text":"

Signal emitted when the parent of the widget changes.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.root_native_widget","title":"root_native_widget: Any property","text":"

Return the root native backend widget.

This can be different from the .native widget if the layout is a child of some other widget, e.g. a widget used to enable scroll bars.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.tooltip","title":"tooltip: str | None property writable","text":"

Get the tooltip for this widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.visible","title":"visible: bool property writable","text":"

Return whether widget is visible.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.widget_type","title":"widget_type: str property","text":"

Return type of widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.width","title":"width: int property writable","text":"

Return the current width of the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.__repr__","title":"__repr__() -> str","text":"

Return representation of widget of instance.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.close","title":"close() -> None","text":"

Close widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.hide","title":"hide() -> None","text":"

Hide widget.

alias for widget.visible = False

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.render","title":"render() -> np.ndarray","text":"

Return an RGBA (MxNx4) numpy array bitmap of the rendered widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.show","title":"show(run: bool = False) -> Widget","text":"

Show widget.

alias for widget.visible = True

Parameters:

  • run (bool, default: False ) \u2013

    Whether to start the application event loop, by default False

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.shown","title":"shown() -> Iterator[Application]","text":"

Context manager to show the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ButtonWidget","title":"magicgui.widgets.bases.ButtonWidget","text":"

Bases: ValueWidget[bool]

Widget with a value, Wraps a widget implementing the ButtonWidgetProtocol.

see ButtonWidgetProtocol.

Parameters:

  • value (bool, default: Undefined ) \u2013

    The starting state of the widget.

  • text (str, default: None ) \u2013

    The text to display on the button. If not provided, will use name.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ButtonWidget.clicked","title":"clicked: SignalInstance property","text":"

Alias for changed event.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ButtonWidget.options","title":"options: dict property","text":"

Return options currently being used in this widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ButtonWidget.text","title":"text: str property writable","text":"

Text of the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.CategoricalWidget","title":"magicgui.widgets.bases.CategoricalWidget","text":"

Bases: ValueWidget[T]

Widget with a value and choices. Wraps CategoricalWidgetProtocol.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The initially selected choice.

  • choices (Enum, Iterable, or Callable, default: () ) \u2013

    Available choices displayed in the combo box.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.CategoricalWidget.choices","title":"choices: tuple[T | None, ...] property writable","text":"

Available value choices for this widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.CategoricalWidget.current_choice","title":"current_choice: str property","text":"

Return the text of the currently selected choice.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.CategoricalWidget.options","title":"options: dict property","text":"

Return options currently being used in this widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.CategoricalWidget.value","title":"value: T property writable","text":"

Return current value of the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.CategoricalWidget.__len__","title":"__len__() -> int","text":"

Return the number of choices.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.CategoricalWidget.del_choice","title":"del_choice(choice_name: str) -> None","text":"

Delete the provided choice_name and associated data.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.CategoricalWidget.get_choice","title":"get_choice(choice_name: str) -> T","text":"

Get data for the provided choice_name.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.CategoricalWidget.reset_choices","title":"reset_choices(*_: Any) -> None","text":"

Reset choices to the default state.

If self._default_choices is a callable, this may NOT be the exact same set of choices as when the widget was instantiated, if the callable relies on external state.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.CategoricalWidget.set_choice","title":"set_choice(choice_name: str, data: Any | None = None) -> None","text":"

Set data for the provided choice_name.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget","title":"magicgui.widgets.bases.ContainerWidget","text":"

Bases: Widget, _OrientationMixin, MutableSequence[WidgetVar]

Widget that can contain other widgets.

Wraps a widget that implements ContainerProtocol.

A ContainerWidget behaves like a python list of Widget objects. Subwidgets can be accessed using integer or slice-based indexing (container[0]), as well as by widget name (container.<widget_name>). Widgets can be added with append or insert, and removed with del or pop, etc...

There is a tight connection between a ContainerWidget and an inspect.Signature object, just as there is a tight connection between individual Widgetobjects an an :class:inspect.Parameter object. The signature representation of a ContainerWidget (with the current settings as default values) is accessible with the :meth:~ContainerWidget.__signature__ method (or by using :func:inspect.signature from the standard library)

For a ContainerWidget subclass that is tightly coupled to a specific function signature (as in the \"classic\" magicgui decorator), see magicgui.widgets.FunctionGui.

Parameters:

  • widgets (Sequence[Widget], default: () ) \u2013

    A sequence of widgets with which to initialize the container, by default None.

  • layout (str, default: 'vertical' ) \u2013

    The layout for the container. must be one of {'horizontal', 'vertical'}. by default \"vertical\"

  • scrollable (bool, default: False ) \u2013

    Whether to enable scroll bars or not. If enabled, scroll bars will only appear along the layout direction, not in both directions.

  • labels (bool, default: True ) \u2013

    Whether each widget should be shown with a corresponding Label widget to the left, by default True. Note: the text for each widget defaults to widget.name, but can be overridden by setting widget.label.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.__signature__","title":"__signature__: MagicSignature property","text":"

Return a MagicSignature object representing the current state of the gui.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.labels","title":"labels: bool property writable","text":"

Whether widgets are presented with labels.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.layout","title":"layout: str property writable","text":"

Return the layout of the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.margins","title":"margins: tuple[int, int, int, int] property writable","text":"

Return margin between the content and edges of the container.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.__delattr__","title":"__delattr__(name: str) -> None","text":"

Delete a widget by name.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.__delitem__","title":"__delitem__(key: int | slice) -> None","text":"

Delete a widget by integer or slice index.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.__dir__","title":"__dir__() -> list[str]","text":"

Add subwidget names to the dir() call for this widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.__getattr__","title":"__getattr__(name: str) -> WidgetVar","text":"

Return attribute name. Will return a widget if present.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.__getitem__","title":"__getitem__(key: int | str | slice) -> WidgetVar | MutableSequence[WidgetVar]","text":"

Get item by integer, str, or slice.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.__len__","title":"__len__() -> int","text":"

Return the count of widgets.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.__repr__","title":"__repr__() -> str","text":"

Return a repr.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.__setattr__","title":"__setattr__(name: str, value: Any) -> None","text":"

Set attribute name. Prevents changing widget if present, (use del).

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.__setitem__","title":"__setitem__(key: Any, value: Any) -> NoReturn","text":"

Prevent assignment by index.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.asdict","title":"asdict() -> dict[str, Any]","text":"

Return state of widget as dict.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.from_callable","title":"from_callable(obj: Callable, gui_options: dict | None = None, **kwargs: Unpack[ContainerKwargs]) -> Container classmethod","text":"

Create a Container widget from a callable object.

In most cases, it will be preferable to create a FunctionGui instead.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.from_signature","title":"from_signature(sig: inspect.Signature, **kwargs: Unpack[ContainerKwargs]) -> Container classmethod","text":"

Create a Container widget from an inspect.Signature object.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.index","title":"index(value: Any, start: int = 0, stop: int = 9223372036854775807) -> int","text":"

Return index of a specific widget instance (or widget name).

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.insert","title":"insert(key: int, widget: WidgetVar) -> None","text":"

Insert widget at key.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.remove","title":"remove(value: Widget | str) -> None","text":"

Remove a widget instance (may also be string name of widget).

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.reset_choices","title":"reset_choices(*_: Any) -> None","text":"

Reset choices for all Categorical subWidgets to the default state.

If widget._default_choices is a callable, this may NOT be the exact same set of choices as when the widget was instantiated, if the callable relies on external state.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.update","title":"update(mapping: Mapping | Iterable[tuple[str, Any]] | None = None, **kwargs: Any) -> None","text":"

Update the parameters in the widget from a mapping, iterable, or kwargs.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.DialogWidget","title":"magicgui.widgets.bases.DialogWidget","text":"

Bases: ContainerWidget

Modal Container.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.DialogWidget.exec","title":"exec() -> bool","text":"

Show the dialog, and block.

Return True if the dialog was accepted, False if rejected.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.MainWindowWidget","title":"magicgui.widgets.bases.MainWindowWidget","text":"

Bases: ContainerWidget

Top level Application widget that can contain other widgets.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.MainWindowWidget.create_menu_item","title":"create_menu_item(menu_name: str, item_name: str, callback: Callable | None = None, shortcut: str | None = None) -> None","text":"

Create a menu item item_name under menu menu_name.

menu_name will be created if it does not already exist.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.RangedWidget","title":"magicgui.widgets.bases.RangedWidget","text":"

Bases: ValueWidget[T]

Widget with a constrained value. Wraps RangedWidgetProtocol.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • min (float, default: Undefined ) \u2013

    The minimum allowable value, by default 0 (or value if value is less than 0)

  • max (float, default: Undefined ) \u2013

    The maximum allowable value, by default 999 (or value if value is greater than 999)

  • step (float, default: Undefined ) \u2013

    The step size for incrementing the value, by default adaptive step is used

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.RangedWidget.adaptive_step","title":"adaptive_step: bool property writable","text":"

Whether the step size is adaptive.

Adaptive decimal step means that the step size will continuously be adjusted to one power of ten below the current value. So when the value is 1100, the step is set to 100, so stepping up once increases it to 1200. For 1200 stepping up takes it to 1300. For negative values, stepping down from -1100 goes to -1200.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.RangedWidget.max","title":"max: float property writable","text":"

Maximum allowable value for the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.RangedWidget.min","title":"min: float property writable","text":"

Minimum allowable value for the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.RangedWidget.options","title":"options: dict property","text":"

Return options currently being used in this widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.RangedWidget.range","title":"range: tuple[float, float] property writable","text":"

Range of allowable values for the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.RangedWidget.step","title":"step: float | None property writable","text":"

Step size for widget values (None if adaptive step is turned on).

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.RangedWidget.value","title":"value(value: T) -> None","text":"

Set widget value, will raise Value error if not within min/max.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.SliderWidget","title":"magicgui.widgets.bases.SliderWidget","text":"

Bases: RangedWidget[T], _OrientationMixin

Widget with a constrained value and orientation. Wraps SliderWidgetProtocol.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • min (float, default: Undefined ) \u2013

    The minimum allowable value, by default 0 (or value if value is less than 0)

  • max (float, default: Undefined ) \u2013

    The maximum allowable value, by default 999 (or value if value is greater than 999)

  • step (float, default: Undefined ) \u2013

    The step size for incrementing the value, by default adaptive step is used

  • orientation ((str, {'horizontal', 'vertical'}), default: 'horizontal' ) \u2013

    The orientation for the slider, by default \"horizontal\"

  • readout (bool, default: True ) \u2013

    Whether to show the editable spinbox next to the slider

  • tracking (bool, default: True ) \u2013

    If tracking is enabled (the default), the slider emits the changed signal while the slider is being dragged. If tracking is disabled, the slider emits the changed signal only after the user releases the slider.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.SliderWidget.options","title":"options: dict property","text":"

Return options currently being used in this widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.SliderWidget.readout","title":"readout: bool property writable","text":"

Get visibility state of readout widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.SliderWidget.tracking","title":"tracking: bool property writable","text":"

Return whether slider tracking is enabled.

If tracking is enabled (the default), the slider emits the changed() signal while the slider is being dragged. If tracking is disabled, the slider emits the changed() signal only when the user releases the slider.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ValueWidget","title":"magicgui.widgets.bases.ValueWidget","text":"

Bases: Widget, Generic[T]

Widget with a value, Wraps ValueWidgetProtocol.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ValueWidget.annotation","title":"annotation: Any property writable","text":"

Return type annotation for the parameter represented by the widget.

ForwardRefs will be resolve when setting the annotation. If the widget is nullable (had a type annototation of Optional[Type]), annotation will return the first argument in the Optional clause.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ValueWidget.value","title":"value: T property writable","text":"

Return current value of the widget. This may be interpreted by backends.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ValueWidget.__repr__","title":"__repr__() -> str","text":"

Return representation of widget of instance.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ValueWidget.bind","title":"bind(value: T | Callable[[ValueWidget], T], call: bool = True) -> None","text":"

Binds value to self.value.

If a value is bound to this widget, then whenever widget.value is accessed, the value provided here will be returned. value can be a callable, in which case value(self) will be returned (i.e. your callback must accept a single parameter, which is this widget instance.).

If you provide a callable and you don't want it to be called (but rather just returned as a callable object, then use call=False when binding your value.

Note: if you need to access the \"original\" widget.value within your callback, please use widget.get_value() instead of the widget.value property, in order to avoid a RuntimeError.

Parameters:

  • value (Any) \u2013

    The value (or callback) to return when accessing this widget's value.

  • call (bool, default: True ) \u2013

    If value is a callable and call is True, the callback will be called as callback(self) when accessing self.value. If False, the callback will simply be returned as a callable object, by default, True.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ValueWidget.get_value","title":"get_value() -> T","text":"

Callable version of self.value.

The main API is to use self.value, however, this is here in order to provide an escape hatch if trying to access the widget's value inside of a callback bound to self._bound_value.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ValueWidget.unbind","title":"unbind() -> None","text":"

Unbinds any bound values. (see ValueWidget.bind).

"},{"location":"api/widgets/create_widget/","title":"magicgui.widgets.create_widget","text":""},{"location":"api/widgets/create_widget/#magicgui.widgets.create_widget","title":"magicgui.widgets.create_widget(value=Undefined, annotation=None, name='', param_kind='POSITIONAL_OR_KEYWORD', label=None, gui_only=False, app=None, widget_type=None, options=None, is_result=False, raise_on_unknown=True)","text":"

Create and return appropriate widget subclass.

This factory function can be used to create a widget appropriate for the provided value and/or annotation provided. See Type Mapping Docs for details on how the widget type is determined from type annotations.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget, by default None

  • annotation (Any, default: None ) \u2013

    The type annotation for the parameter represented by the widget, by default None.

  • name (str, default: '' ) \u2013

    The name of the parameter represented by this widget. by default \"\"

  • param_kind (str, default: 'POSITIONAL_OR_KEYWORD' ) \u2013

    The :attr:inspect.Parameter.kind represented by this widget. Used in building signatures from multiple widgets, by default \"POSITIONAL_OR_KEYWORD\"

  • label (str, default: None ) \u2013

    A string to use for an associated Label widget (if this widget is being shown in a Container widget, and labels are on). By default, name will be used. Note: name refers the name of the parameter, as might be used in a signature, whereas label is just the label for that widget in the GUI.

  • gui_only (bool, default: False ) \u2013

    Whether the widget should be considered \"only for the gui\", or if it should be included in any widget container signatures, by default False

  • app (str, default: None ) \u2013

    The backend to use, by default None

  • widget_type (str or Type[WidgetProtocol] or None, default: None ) \u2013

    A class implementing a widget protocol or a string with the name of a magicgui widget type (e.g. \"Label\", \"PushButton\", etc...). If provided, this widget type will be used instead of the type autodetermined from value and/or annotation above.

  • options (dict, default: None ) \u2013

    Dict of options to pass to the Widget constructor, by default dict()

  • is_result (boolean, default: False ) \u2013

    Whether the widget belongs to an input or an output. By default, an input is assumed.

  • raise_on_unknown (bool, default: True ) \u2013

    Raise exception if no widget is found for the given type, by default True

Returns:

  • Widget \u2013

    An instantiated widget subclass

Raises:

  • TypeError \u2013

    If the provided or autodetected widget_type does not implement any known widget protocols

Examples:

from magicgui.widgets import create_widget\n\n# create a widget from a string value\nwdg = create_widget(value=\"hello world\")\nassert wdg.value == \"hello world\"\n\n# create a widget from a string annotation\nwdg = create_widget(annotation=str)\nassert wdg.value == \"\"\n
"},{"location":"generated_examples/","title":"Examples","text":""},{"location":"generated_examples/#getting-started","title":"Getting started","text":"

A gallery of examples for magicgui.

Basic example

Basic widgets demo

"},{"location":"generated_examples/#demo-applications","title":"Demo applications","text":"

Example applications built with magicgui.

Input values dialog

Quantities with pint

Callable functions demo

Snell's law demonstration using magicgui

Hotdog or not app

Chaining functions together

"},{"location":"generated_examples/#demo-widget-types","title":"Demo widget types","text":"

Example gallery demonstrating the available widget types in magicgui.

Image widget

Custom text labels for widgets

Range slider widget

Log slider widget

Optional user choice

Multiple selection widget

Password login

File dialog widget

Dropdown selection widget

Table widget

"},{"location":"generated_examples/#matplotlib-and-magicgui","title":"matplotlib and magicgui","text":"

Examples involving matplotlib graphs and magicgui.

matplotlib figure example

Waveforms example

"},{"location":"generated_examples/#napari-and-magicgui","title":"napari and magicgui","text":"

Examples integrating magicgui with napari.

napari forward reference demo

napari Qt demo

napari parameter sweeps

napari image arithmetic widget

"},{"location":"generated_examples/#jupyter-notebooks-and-magicgui","title":"Jupyter notebooks and magicgui","text":"

Examples using jupyter notebooks together with magicgui.

Jupyter notebooks and magicgui

"},{"location":"generated_examples/#progress-bar-examples","title":"Progress bar examples","text":"

Examples of progress bars in magicgui.

Manual progress bar

Simple progress bar

Indeterminate progress bar

Nested progress bars

"},{"location":"generated_examples/#under-the-hood","title":"Under the hood","text":"

Learn more advanced usage patterns for magicgui, including self referencing widgets and decorating class methods with magicgui.

Self reference magicgui widgets

Deocrate class methods with magicgui

Download all examples in Python source code: generated_examples_python.zip

Download all examples in Jupyter notebooks: generated_examples_jupyter.zip

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/basic_example/","title":"Basic example","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/basic_example/#basic-example","title":"Basic example","text":"

A basic example using magicgui.

Out:

<FunctionGui example(x: int = 0, y='hi')>\n

from magicgui import magicgui\n\n\n@magicgui\ndef example(x: int, y=\"hi\"):\n    \"\"\"Basic example function.\"\"\"\n    return x, y\n\n\nexample.changed.connect(print)\nexample.show(run=True)\n

Total running time of the script: ( 0 minutes 0.780 seconds)

Download Python source code: basic_example.py

Download Jupyter notebook: basic_example.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/basic_widgets_demo/","title":"Basic widgets demo","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/basic_widgets_demo/#basic-widgets-demo","title":"Basic widgets demo","text":"

Widget demonstration with magicgui.

This code demonstrates a few of the widget types that magicgui can create based on the parameter types in your function.

Out:

<MainFunctionGui widget_demo(boolean=True, integer=1, spin_float=3.14, slider_float=43.5, slider_int=550, string='Text goes here', dropdown=<Medium.Glass: 1.52>, radio_option=2, date=datetime.date(1999, 12, 31), time=datetime.time(1, 30, 20), datetime=datetime.datetime(2024, 3, 5, 17, 38, 27, 444000), filename=PosixPath('/Users/runner'))>\n

import datetime\nfrom enum import Enum\nfrom pathlib import Path\n\nfrom magicgui import magicgui\n\n\nclass Medium(Enum):\n    \"\"\"Enum for various media and their refractive indices.\"\"\"\n\n    Glass = 1.520\n    Oil = 1.515\n    Water = 1.333\n    Air = 1.0003\n\n\n@magicgui(\n    main_window=True,\n    call_button=\"Calculate\",\n    layout=\"vertical\",\n    result_widget=True,\n    slider_float={\"widget_type\": \"FloatSlider\", \"max\": 100},\n    slider_int={\"widget_type\": \"Slider\", \"readout\": False},\n    radio_option={\n        \"widget_type\": \"RadioButtons\",\n        \"orientation\": \"horizontal\",\n        \"choices\": [(\"first option\", 1), (\"second option\", 2)],\n    },\n    filename={\"label\": \"Pick a file:\"},\n)\ndef widget_demo(\n    boolean=True,\n    integer=1,\n    spin_float=3.14159,\n    slider_float=43.5,\n    slider_int=550,\n    string=\"Text goes here\",\n    dropdown=Medium.Glass,\n    radio_option=2,\n    date=datetime.date(1999, 12, 31),\n    time=datetime.time(1, 30, 20),\n    datetime=datetime.datetime.now(),\n    filename=Path.home(),\n):\n    \"\"\"We can use numpy docstrings to provide tooltips.\n\n    Parameters\n    ----------\n    boolean : bool, optional\n        A checkbox for booleans, by default True\n    integer : int, optional\n        Some integer, by default 1\n    spin_float : float, optional\n        This one is a float, by default \"pi\"\n    slider_float : float, optional\n        Hey look! I'm a slider, by default 43.5\n    slider_int : float, optional\n        I only take integers, and I've hidden my readout, by default 550\n    string : str, optional\n        We'll use this string carefully, by default \"Text goes here\"\n    dropdown : Enum, optional\n        Pick a medium, by default Medium.Glass\n    radio_option : int\n        A set of radio buttons.\n    date : datetime.date, optional\n        Your birthday, by default datetime.date(1999, 12, 31)\n    time : datetime.time, optional\n        Some time, by default datetime.time(1, 30, 20)\n    datetime : datetime.datetime, optional\n        A very specific time and date, by default ``datetime.datetime.now()``\n    filename : str, optional\n        Pick a path, by default Path.home()\n    \"\"\"\n    return locals().values()\n\n\nwidget_demo.changed.connect(print)\nwidget_demo.show(run=True)\n

Total running time of the script: ( 0 minutes 0.129 seconds)

Download Python source code: basic_widgets_demo.py

Download Jupyter notebook: basic_widgets_demo.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/mg_execution_times/","title":"Computation times","text":"

00:00.909 total execution time for generated_examples files:

+-------------------------------------------------------------------------------------+-----------+--------+ | basic_example (docs/examples/basic_example.py) | 00:00.780 | 0.0 MB | +-------------------------------------------------------------------------------------+-----------+--------+ | basic_widgets_demo (docs/examples/basic_widgets_demo.py) | 00:00.129 | 0.0 MB | +-------------------------------------------------------------------------------------+-----------+--------+

"},{"location":"generated_examples/applications/callable/","title":"Callable functions demo","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/applications/callable/#callable-functions-demo","title":"Callable functions demo","text":"

This example demonstrates handling callable functions with magicgui.

Out:

<FunctionGui example(func='f')>\n

from magicgui import magicgui\n\n\ndef f(x: int, y=\"a string\") -> str:\n    \"\"\"Example function F.\"\"\"\n    return f\"{y} {x}\"\n\n\ndef g(x: int = 6, y=\"another string\") -> str:\n    \"\"\"Example function G.\"\"\"\n    return f\"{y} asdfsdf {x}\"\n\n\n@magicgui(call_button=True, func={\"choices\": [\"f\", \"g\"]})\ndef example(func=\"f\"):\n    \"\"\"\u00cbxample function.\"\"\"\n    pass\n\n\ndef update(f: str):\n    \"\"\"Update function.\"\"\"\n    if len(example) > 2:\n        del example[1]\n    example.insert(1, magicgui(globals()[f]))\n\n\nexample.func.changed.connect(update)\nexample.show(run=True)\n

Total running time of the script: ( 0 minutes 0.029 seconds)

Download Python source code: callable.py

Download Jupyter notebook: callable.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/applications/chaining/","title":"Chaining functions together","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/applications/chaining/#chaining-functions-together","title":"Chaining functions together","text":"

This example demonstrates chaining multiple functions together.

Out:

calling func_a\ncalling func_b\ncalling func_c\n\n\n<Container (func_a: NoneType, func_b: NoneType, func_c: NoneType)>\n

from magicgui import magicgui, widgets\n\n\n@magicgui(auto_call=True)\ndef func_a(x: int = 64, y: int = 64):\n    \"\"\"Callable function A.\"\"\"\n    print(\"calling func_a\")\n    return x + y\n\n\n@magicgui(auto_call=True, input={\"visible\": False, \"label\": \" \", \"max\": 100000})\ndef func_b(input: int, mult=1.0):\n    \"\"\"Callable function B.\"\"\"\n    print(\"calling func_b\")\n    result = input * mult\n    # since these function defs live in globals(), you can update them directly\n    func_c.input.value = result\n    return result\n\n\n# alternatively, you can the `widget.called` signal to connect a callback function\n# where the result of the function being called is at `value`\n@func_a.called.connect\ndef _on_func_a(value: str):\n    func_b.input.value = value\n\n\n@magicgui(\n    auto_call=True,\n    input={\"visible\": False, \"max\": 100000},\n    result_widget=True,\n    labels=False,\n)\ndef func_c(input: int, format: str = \"({} + {}) * {} is {}\") -> str:\n    \"\"\"Callable function C.\"\"\"\n    print(\"calling func_c\\n\")\n    return format.format(func_a.x.value, func_a.y.value, func_b.mult.value, input)\n\n\ncontainer = widgets.Container(\n    widgets=[func_a, func_b, func_c], layout=\"vertical\", labels=False\n)\ncontainer.native.setMinimumWidth(500)\nfunc_a()\ncontainer.show(run=True)\n\n# notice which functions get called when you change each widget.\n

Total running time of the script: ( 0 minutes 0.054 seconds)

Download Python source code: chaining.py

Download Jupyter notebook: chaining.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/applications/hotdog/","title":"Hotdog or not app","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/applications/hotdog/#hotdog-or-not-app","title":"Hotdog or not app","text":"

Demo app to upload an image and classify if it's an hotdog or not.

import pathlib\nfrom enum import Enum\n\nfrom magicgui import magicgui\n\n\nclass HotdogOptions(Enum):\n    \"\"\"All hotdog possibilities.\"\"\"\n\n    Hotdog = 1\n    NotHotdog = 0\n\n\n@magicgui(main_window=True, layout=\"form\", call_button=\"Classify\", result_widget=True)\ndef is_hotdog(img: pathlib.Path) -> HotdogOptions:\n    \"\"\"Classify possible hotdog images.\n\n    Upload an image and check whether it's an hotdog. For example, this image\n    will be classified as one: <br><br>\n\n    <img src=\"resources/hotdog.jpg\">\n\n    Parameters\n    ----------\n    img : pathlib.Path\n        Path to a possible hotdog image\n\n    Returns\n    -------\n    HotdogOptions\n        True if image contains an hotdog in it\n    \"\"\"\n    if \"hotdog\" in img.stem:\n        return HotdogOptions.Hotdog\n    return HotdogOptions.NotHotdog\n\n\nif __name__ == \"__main__\":\n    is_hotdog.show(run=True)\n

Total running time of the script: ( 0 minutes 0.033 seconds)

Download Python source code: hotdog.py

Download Jupyter notebook: hotdog.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/applications/mg_execution_times/","title":"Computation times","text":"

00:00.776 total execution time for generated_examples_applications files:

+-----------------------------------------------------------------------------------+-----------+--------+ | pint_quantity (docs/examples/applications/pint_quantity.py) | 00:00.617 | 0.0 MB | +-----------------------------------------------------------------------------------+-----------+--------+ | chaining (docs/examples/applications/chaining.py) | 00:00.054 | 0.0 MB | +-----------------------------------------------------------------------------------+-----------+--------+ | snells_law (docs/examples/applications/snells_law.py) | 00:00.043 | 0.0 MB | +-----------------------------------------------------------------------------------+-----------+--------+ | hotdog (docs/examples/applications/hotdog.py) | 00:00.033 | 0.0 MB | +-----------------------------------------------------------------------------------+-----------+--------+ | callable (docs/examples/applications/callable.py) | 00:00.029 | 0.0 MB | +-----------------------------------------------------------------------------------+-----------+--------+ | values_dialog (docs/examples/applications/values_dialog.py) | 00:00.000 | 0.0 MB | +-----------------------------------------------------------------------------------+-----------+--------+

"},{"location":"generated_examples/applications/pint_quantity/","title":"Quantities with pint","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/applications/pint_quantity/#quantities-with-pint","title":"Quantities with pint","text":"

Pint is a Python package to define, operate and manipulate physical quantities: the product of a numerical value and a unit of measurement. It allows arithmetic operations between them and conversions from and to different units. https://pint.readthedocs.io/en/stable/

Out:

<FunctionGui widget(q=<Quantity(1, 'millisecond')>)>\n

from pint import Quantity\n\nfrom magicgui import magicgui\n\n\n@magicgui\ndef widget(q=Quantity(\"1 ms\")):\n    \"\"\"Widget allowing users to input quantity measurements.\"\"\"\n    print(q)\n\n\nwidget.show(run=True)\n

Total running time of the script: ( 0 minutes 0.617 seconds)

Download Python source code: pint_quantity.py

Download Jupyter notebook: pint_quantity.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/applications/snells_law/","title":"Snell's law demonstration using magicgui","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/applications/snells_law/#snells-law-demonstration-using-magicgui","title":"Snell's law demonstration using magicgui","text":"

Demo app for calculating angles of refraction according to Snell's law.

Out:

<FunctionGui snells_law(aoi=1.0, n1=<Medium.Glass: 1.52>, n2=<Medium.Water: 1.333>, degrees=True)>\n

import math\nfrom enum import Enum\n\nfrom magicgui import magicgui\n\n\nclass Medium(Enum):\n    \"\"\"Enum for various media and their refractive indices.\"\"\"\n\n    Glass = 1.520\n    Oil = 1.515\n    Water = 1.333\n    Air = 1.0003\n\n\n@magicgui(call_button=\"calculate\", result_widget=True)\ndef snells_law(aoi=1.0, n1=Medium.Glass, n2=Medium.Water, degrees=True):\n    \"\"\"Calculate the angle of refraction given two media and an AOI.\"\"\"\n    if degrees:\n        aoi = math.radians(aoi)\n    try:\n        n1 = n1.value\n        n2 = n2.value\n        result = math.asin(n1 * math.sin(aoi) / n2)\n        return round(math.degrees(result) if degrees else result, 2)\n    except ValueError:  # math domain error\n        return \"TIR!\"\n\n\nsnells_law.show(run=True)\n

Total running time of the script: ( 0 minutes 0.043 seconds)

Download Python source code: snells_law.py

Download Jupyter notebook: snells_law.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/applications/values_dialog/","title":"Input values dialog","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/applications/values_dialog/#input-values-dialog","title":"Input values dialog","text":"

A basic example of a user input dialog.

This will pause code execution until the user responds.

"},{"location":"generated_examples/applications/values_dialog/#_1","title":"Input values dialog","text":"
from magicgui.widgets import request_values\n\nvals = request_values(\n    age=int,\n    name={\"annotation\": str, \"label\": \"Enter your name:\"},\n    title=\"Hi, who are you?\",\n)\nprint(repr(vals))\n

Total running time of the script: ( 0 minutes 0.000 seconds)

Download Python source code: values_dialog.py

Download Jupyter notebook: values_dialog.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/demo_widgets/change_label/","title":"Custom text labels for widgets","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/demo_widgets/change_label/#custom-text-labels-for-widgets","title":"Custom text labels for widgets","text":"

An example showing how to create custom text labels for your widgets.

Out:

<FunctionGui example(x=1, y='hi')>\n

from magicgui import magicgui\n\n\n# use a different label than the default (the parameter name) in the UI\n@magicgui(x={\"label\": \"widget to set x\"})\ndef example(x=1, y=\"hi\"):\n    \"\"\"Example function.\"\"\"\n    return x, y\n\n\nexample.changed.connect(print)\nexample.show(run=True)\n

Total running time of the script: ( 0 minutes 0.032 seconds)

Download Python source code: change_label.py

Download Jupyter notebook: change_label.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/demo_widgets/choices/","title":"Dropdown selection widget","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/demo_widgets/choices/#dropdown-selection-widget","title":"Dropdown selection widget","text":"

Choices for dropdowns can be provided in a few different ways.

Out:

<Container (as_list: NoneType, as_enum: NoneType, as_2tuple: NoneType, as_function: NoneType)>\n

from enum import Enum\n\nfrom magicgui import magicgui, widgets\n\n\nclass Medium(Enum):\n    \"\"\"Enum for various media and their refractive indices.\"\"\"\n\n    Oil = 1.515\n    Water = 1.333\n    Air = 1.0003\n\n\n@magicgui(ri={\"choices\": [\"Oil\", \"Water\", \"Air\"]}, auto_call=True)\ndef as_list(ri=\"Water\"):\n    \"\"\"Function decorated with magicgui list of choices.\"\"\"\n    print(\"refractive index is\", Medium[ri].value)\n\n\n@magicgui(auto_call=True)\ndef as_enum(ri: Medium = Medium.Water):\n    \"\"\"Function decorated with magicgui and enumeration.\"\"\"\n    print(\"refractive index is\", ri.value)\n\n\n@magicgui(\n    ri={\"choices\": [(\"Oil\", 1.515), (\"Water\", 1.33), (\"Air\", 1.0)]}, auto_call=True\n)\ndef as_2tuple(ri=1.33):\n    \"\"\"Function decorated with magicgui tuple of choices.\"\"\"\n    print(\"refractive index is\", ri)\n\n\ndef get_choices(gui):\n    \"\"\"Function returning tuple of material and refractive index value.\"\"\"\n    return [(\"Oil\", 1.515), (\"Water\", 1.33), (\"Air\", 1.0)]\n\n\n@magicgui(ri={\"choices\": get_choices}, auto_call=True)\ndef as_function(ri: float):\n    \"\"\"Function to calculate refractive index.\"\"\"\n    print(\"refractive index is\", ri)\n\n\ncontainer = widgets.Container(\n    widgets=[as_list, as_enum, as_2tuple, as_function], layout=\"vertical\"\n)\ncontainer.show(run=True)\n

Total running time of the script: ( 0 minutes 0.049 seconds)

Download Python source code: choices.py

Download Jupyter notebook: choices.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/demo_widgets/file_dialog/","title":"File dialog widget","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/demo_widgets/file_dialog/#file-dialog-widget","title":"File dialog widget","text":"

A file dialog widget example.

    %s
* ![file dialog](../images/mkd_glr_file_dialog_001.png){: .mkd-glr-multi-img srcset=\"../images/mkd_glr_file_dialog_001.png\"}\n\n* ![file dialog](../images/mkd_glr_file_dialog_002.png){: .mkd-glr-multi-img srcset=\"../images/mkd_glr_file_dialog_002.png\"}\n\n* ![file dialog](../images/mkd_glr_file_dialog_003.png){: .mkd-glr-multi-img srcset=\"../images/mkd_glr_file_dialog_003.png\"}\n
from pathlib import Path\nfrom typing import Sequence\n\nfrom magicgui import magicgui, use_app\n\n\n@magicgui(filename={\"mode\": \"r\"})\ndef filepicker(filename=Path(\"~\")):\n    \"\"\"Take a filename and do something with it.\"\"\"\n    print(\"The filename is:\", filename)\n    return filename\n\n\n# Sequence of paths\n# We change the label using \"label\" for added clarity\n# the filter argument restricts file types\n@magicgui(filenames={\"label\": \"Choose Tiff files:\", \"filter\": \"*.tif\"})\ndef filespicker(filenames: Sequence[Path]):\n    \"\"\"Take a filename and do something with it.\"\"\"\n    print(\"The filenames are:\", filenames)\n    return filenames\n\n\n# Select a directory, instead of file(s)\n@magicgui(directory={\"mode\": \"d\", \"label\": \"Choose a directory\"})\ndef directorypicker(directory=Path(\"~\")):\n    \"\"\"Take a directory name and do something with it.\"\"\"\n    print(\"The directory name is:\", directory)\n    return directory\n\n\nfilepicker.show()\nfilespicker.show()\ndirectorypicker.show()\nfilepicker.filename.changed.connect(print)\nfilespicker.filenames.changed.connect(print)\ndirectorypicker.directory.changed.connect(print)\n\nuse_app().run()\n

Total running time of the script: ( 0 minutes 0.105 seconds)

Download Python source code: file_dialog.py

Download Jupyter notebook: file_dialog.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/demo_widgets/image/","title":"Image widget","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/demo_widgets/image/#image-widget","title":"Image widget","text":"

Example of creating an Image Widget from a file.

(This requires pillow, or that magicgui was installed as magicgui[image])

Out:

Image(200x232x3, name='')\n

from magicgui.widgets import Image\n\nimage = Image(value=\"../../images/_test.jpg\")\nimage.scale_widget_to_image_size()\nimage.show(run=True)\n

Total running time of the script: ( 0 minutes 0.037 seconds)

Download Python source code: image.py

Download Jupyter notebook: image.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/demo_widgets/log_slider/","title":"Log slider widget","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/demo_widgets/log_slider/#log-slider-widget","title":"Log slider widget","text":"

A logarithmic scale range slider widget.

Out:

<FunctionGui slider(input=1.0)>\n

from magicgui import magicgui\n\n\n@magicgui(\n    auto_call=True,\n    result_widget=True,\n    input={\"widget_type\": \"LogSlider\", \"max\": 10000, \"min\": 1, \"tracking\": False},\n)\ndef slider(input=1):\n    \"\"\"Logarithmic scale slider.\"\"\"\n    return round(input, 4)\n\n\nslider.show(run=True)\n

Total running time of the script: ( 0 minutes 0.032 seconds)

Download Python source code: log_slider.py

Download Jupyter notebook: log_slider.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/demo_widgets/login/","title":"Password login","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/demo_widgets/login/#password-login","title":"Password login","text":"

A password login field widget.

Out:

<FunctionGui login(username: str = '', password: str = '', password2: str = '')>\n

from magicgui import magicgui\n\n\n# note that \"password\" is a special keyword argument\n# it will create a password field in the gui by default\n# (unless you override \"widget_type\")\n# whereas \"password2\" will be a normal text field\n# (unless you override \"widget_type\")\n@magicgui(password2={\"widget_type\": \"Password\"})\ndef login(username: str, password: str, password2: str):\n    \"\"\"User login credentials.\"\"\"\n    ...\n\n\nlogin.show(run=True)\n

Total running time of the script: ( 0 minutes 0.035 seconds)

Download Python source code: login.py

Download Jupyter notebook: login.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/demo_widgets/mg_execution_times/","title":"Computation times","text":"

00:00.439 total execution time for generated_examples_demo_widgets files:

+--------------------------------------------------------------------------------+-----------+--------+ | file_dialog (docs/examples/demo_widgets/file_dialog.py) | 00:00.105 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ | choices (docs/examples/demo_widgets/choices.py) | 00:00.049 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ | range_slider (docs/examples/demo_widgets/range_slider.py) | 00:00.048 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ | table (docs/examples/demo_widgets/table.py) | 00:00.040 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ | image (docs/examples/demo_widgets/image.py) | 00:00.037 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ | login (docs/examples/demo_widgets/login.py) | 00:00.035 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ | selection (docs/examples/demo_widgets/selection.py) | 00:00.032 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ | log_slider (docs/examples/demo_widgets/log_slider.py) | 00:00.032 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ | change_label (docs/examples/demo_widgets/change_label.py) | 00:00.032 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ | optional (docs/examples/demo_widgets/optional.py) | 00:00.030 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+

"},{"location":"generated_examples/demo_widgets/optional/","title":"Optional user choice","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/demo_widgets/optional/#optional-user-choice","title":"Optional user choice","text":"

Optional user input using a dropdown selection widget.

Out:

<FunctionGui f(path: str = None)>\n

from typing import Optional\n\nfrom magicgui import magicgui\n\n\n# Using optional will add a '----' to the combobox, which returns \"None\"\n@magicgui(path={\"choices\": [\"a\", \"b\"]})\ndef f(path: Optional[str] = None):\n    \"\"\"\u00d6ptional user input function.\"\"\"\n    print(path, type(path))\n\n\nf.show(run=True)\n

Total running time of the script: ( 0 minutes 0.030 seconds)

Download Python source code: optional.py

Download Jupyter notebook: optional.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/demo_widgets/range_slider/","title":"Range slider widget","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/demo_widgets/range_slider/#range-slider-widget","title":"Range slider widget","text":"

A double ended range slider widget.

Out:

<FunctionGui func(range_value: Tuple[int, int] = (20, 380))>\n

from typing import Tuple\n\nfrom magicgui import magicgui\n\n\n@magicgui(auto_call=True, range_value={\"widget_type\": \"RangeSlider\", \"max\": 500})\ndef func(range_value: Tuple[int, int] = (20, 380)):\n    \"\"\"Double ended range slider.\"\"\"\n    print(range_value)\n\n\nfunc.show(run=True)\n

Total running time of the script: ( 0 minutes 0.048 seconds)

Download Python source code: range_slider.py

Download Jupyter notebook: range_slider.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/demo_widgets/selection/","title":"Multiple selection widget","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/demo_widgets/selection/#multiple-selection-widget","title":"Multiple selection widget","text":"

A selection widget allowing multiple selections by the user.

Out:

<FunctionGui my_widget(pick_some=['first'])>\n

from magicgui import magicgui\n\n\n@magicgui(\n    pick_some={\n        \"choices\": (\"first\", \"second\", \"third\", \"fourth\"),\n        \"allow_multiple\": True,\n    }\n)\ndef my_widget(pick_some=(\"first\")):\n    \"\"\"Dropdown selection function.\"\"\"\n    print(\"you selected\", pick_some)\n\n\nmy_widget.show(run=True)\n

Total running time of the script: ( 0 minutes 0.032 seconds)

Download Python source code: selection.py

Download Jupyter notebook: selection.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/demo_widgets/table/","title":"Table widget","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/demo_widgets/table/#table-widget","title":"Table widget","text":"

Demonstrating a few ways to input tables.

Out:

Table(shape=(6, 3) at 0x1389c54c0)\n

import numpy as np\n\nfrom magicgui.widgets import Table\n\n# all of these are valid data types\ndict_of_lists = {\"col_1\": [1, 4], \"col_2\": [2, 5], \"col_3\": [3, 6]}\n# column-dict-of-row-dicts\ndict_of_dict = {\n    \"col_1\": {\"r1\": 1, \"r2\": 4},\n    \"col_2\": {\"r1\": 2, \"r2\": 5},\n    \"col_3\": {\"r1\": 3, \"r2\": 6},\n}\n# list-of-lists\nlist_of_list = [[1, 2, 3], [4, 5, 6]]\n# Records: List-of-column-dict\nlist_of_records = [\n    {\"col_1\": 1, \"col_2\": 2, \"col_3\": 3},\n    {\"col_1\": 4, \"col_2\": 5, \"col_3\": 6},\n]\n\n# 3-tuple of data, index, column\ndata_index_column_tuple = (([[1, 2, 3], [4, 5, 6]], (\"r1\", \"r2\"), (\"c1\", \"c2\", \"c3\")),)\n# split-dict\nsplit_dict = {\n    \"data\": [[1, 2, 3], [4, 5, 6]],\n    \"index\": (\"r1\", \"r2\"),\n    \"columns\": (\"c1\", \"c2\", \"c3\"),\n}\n\ntable = Table(value=dict_of_lists)\n\n# it behaves like a dict:\ntable[\"new_col\"] = [5, 5]\nassert table.pop(\"new_col\") == [5, 5]\n# keys and items have both regular (column) and \"row\" modes\ncol_item_view = table.items()  # iterate col_header/column\nrow_item_view = table.items(\"row\")  # iterate row_header/row\n\n# we can just call dict() to get back our dict of lists\nassert dict(table) == dict_of_lists\n# or use one of many other exports in `to_dict`\nassert table.to_dict(\"records\") == list_of_records\n\n# change headers\ntable.row_headers = (\"row1\", \"row2\")\ntable.column_headers = (\"a\", \"b\", \"c\")\n\n# setting value clears and resets the table:\ntable.value = np.arange(18).reshape(6, 3)\n# we can get/set/delete the 2D data table using numpy-style indexing:\n# get every other row\nassert table.data[::2] == [[0, 1, 2], [6, 7, 8], [12, 13, 14]]\n# set every other column in the 3rd row\ntable.data[2, ::2] = [99, 99]\n\n# export to numpy or pandas\n# table.data.to_numpy()\n# table.to_dataframe()\n\n# the table.changed event emits a dict of information on any cell change\n# e.g. {'data': 'sdfg', 'row': 1, 'column': 0, 'column_header': '1', 'row_header': '1'}\ntable.changed.connect(print)\ntable.show(run=True)\n

Total running time of the script: ( 0 minutes 0.040 seconds)

Download Python source code: table.py

Download Jupyter notebook: table.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/matplotlib/mg_execution_times/","title":"Computation times","text":"

00:00.404 total execution time for generated_examples_matplotlib files:

+------------------------------------------------------------------------+-----------+--------+ | waveform (docs/examples/matplotlib/waveform.py) | 00:00.240 | 0.0 MB | +------------------------------------------------------------------------+-----------+--------+ | mpl_figure (docs/examples/matplotlib/mpl_figure.py) | 00:00.164 | 0.0 MB | +------------------------------------------------------------------------+-----------+--------+

"},{"location":"generated_examples/matplotlib/mpl_figure/","title":"matplotlib figure example","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/matplotlib/mpl_figure/#matplotlib-figure-example","title":"matplotlib figure example","text":"

Basic example of adding a generic QWidget to a container.

Main lesson: add your QWidget to container.native.layout() as shown on line 30

Out:

<FunctionGui f(position: int = 0)>\n

import matplotlib.pyplot as plt\nimport numpy as np\nfrom matplotlib.backends.backend_qt5agg import FigureCanvas\n\nfrom magicgui import magicgui\n\nx = np.linspace(0, 5, 256)\ny = np.linspace(0, 5, 256)[:, np.newaxis]\ndata = np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)\n\nmpl_fig = plt.figure()\nax = mpl_fig.add_subplot(111)\n(line,) = ax.plot(data[123])  # linescan through the middle of the image\n\n\n@magicgui(position={\"widget_type\": \"Slider\", \"max\": 255}, auto_call=True)\ndef f(position: int):\n    \"\"\"Function demonstrating magicgui combined with matplotlib.\"\"\"\n    line.set_ydata(data[position])\n    line.figure.canvas.draw()\n\n\n# rather than using the Container.append (`f.append`) ...\n# grab the native layout and add the QWidget to it\nf.native.layout().addWidget(FigureCanvas(mpl_fig))\n\nf.show(run=True)\n

Total running time of the script: ( 0 minutes 0.164 seconds)

Download Python source code: mpl_figure.py

Download Jupyter notebook: mpl_figure.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/matplotlib/waveform/","title":"Waveforms example","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/matplotlib/waveform/#waveforms-example","title":"Waveforms example","text":"

Simple waveform generator widget, with plotting.

Out:

<Container (signal_widget: NoneType, sine: NoneType)>\n

from dataclasses import dataclass, field\nfrom enum import Enum\nfrom functools import partial\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom matplotlib.backends.backend_qt5agg import FigureCanvas\nfrom scipy import signal\nfrom typing_extensions import Annotated\n\nfrom magicgui import magicgui, register_type, widgets\n\nregister_type(float, widget_type=\"FloatSlider\")\nregister_type(int, widget_type=\"Slider\")\n\nFreq = Annotated[float, {\"min\": 0.001, \"max\": 30.0}]\nPhase = Annotated[float, {\"min\": 0.0, \"max\": 360.0}]\nDuty = Annotated[float, {\"min\": 0.0, \"max\": 1.0}]\nTime = Annotated[float, {\"min\": 0.01, \"max\": 100.0}]\n\n\n@dataclass\nclass Signal:\n    \"\"\"Constructs a 1D signal.\n\n    As is, this class is not very useful, but one could add callbacks\n    or more functionality here\n\n    Parameters\n    ----------\n    func : callable\n        func must take a 'time' array as sole argument and return a 1D array with the\n        same size as the input\n    duration : float\n        the maximum of the input time array\n    size : int\n        the number of samples in the time array\n\n    \"\"\"\n\n    func: callable\n    duration: Time = 1.0\n    size: int = 500\n    time: np.ndarray = field(init=False)\n    data: np.ndarray = field(init=False)\n\n    def __post_init__(self):\n        \"\"\"Evaluate the function at instantiation time.\"\"\"\n        self.time = np.linspace(0, self.duration, self.size)\n        self.data = self.func(self.time)\n\n    def plot(self, ax=None, **kwargs):\n        \"\"\"Plots the data.\n\n        Parameters\n        ----------\n        ax: matplotlib.axes.Axes instance, default None\n           if provided the plot is done on this axes instance.\n           If None a new ax is created\n        **kwargs: Keyword arguments that are passed on to\n            the matplotib ax.plot method\n\n        Returns\n        -------\n        fig: a matplotlib.figure.Figure instance\n        ax: matplotlib.axes.Axes instance\n        \"\"\"\n        if ax is None:\n            fig, ax = plt.subplots()\n        else:\n            fig = ax.get_figure()\n        ax.plot(self.time, self.data, **kwargs)\n        return fig, ax\n\n\ndef sine(\n    duration: Time = 10.0, size: int = 500, freq: Freq = 0.5, phase: Phase = 0.0\n) -> Signal:\n    \"\"\"Returns a 1D sine wave.\n\n    Parameters\n    ----------\n    duration: float\n       the duration of the signal in seconds\n    size: int\n        the number of samples in the signal time array\n    freq: float\n       the frequency of the signal in Hz\n    phase: Phase\n       the phase of the signal (in degrees)\n    \"\"\"\n    sig = Signal(\n        duration=duration,\n        size=size,\n        func=lambda t: np.sin(t * (2 * np.pi * freq) + phase * np.pi / 180),\n    )\n    return sig\n\n\ndef chirp(\n    duration: Time = 10.0,\n    size: int = 500,\n    f0: float = 1.0,\n    t1: Time = 5.0,\n    f1: float = 2.0,\n    phase: Phase = 0.0,\n) -> Signal:\n    \"\"\"Frequency-swept cosine generator.\n\n    See scipy.signal.chirp\n    \"\"\"\n    sig = Signal(\n        duration=duration,\n        size=size,\n        func=partial(signal.chirp, f0=f0, t1=t1, f1=f1, phi=phase),\n    )\n    return sig\n\n\ndef sawtooth(\n    duration: Time = 10.0,\n    size: int = 500,\n    freq: Freq = 1.0,\n    width: Duty = 1.0,\n    phase: Phase = 0.0,\n) -> Signal:\n    \"\"\"Return a periodic sawtooth or triangle waveform.\n\n    See scipy.signal.sawtooth\n    \"\"\"\n    sig = Signal(\n        duration=duration,\n        size=size,\n        func=lambda t: signal.sawtooth(\n            2 * np.pi * freq * t + phase * np.pi / 180, width=width\n        ),\n    )\n    return sig\n\n\ndef square(\n    duration: Time = 10.0, size: int = 500, freq: Freq = 1.0, duty: Duty = 0.5\n) -> Signal:\n    \"\"\"Return a periodic sawtooth or triangle waveform.\n\n    See scipy.signal.square\n    \"\"\"\n    sig = Signal(\n        duration=duration,\n        size=size,\n        func=lambda t: signal.square(2 * np.pi * freq * t, duty=duty),\n    )\n    return sig\n\n\ndef on_off(\n    duration: Time = 10.0, size: int = 500, t_on: Time = 0.01, t_off: Time = 0.01\n) -> Signal:\n    \"\"\"On/Off signal function.\"\"\"\n    data = np.ones(size)\n    data[: int(size * t_on / duration)] = -1\n    if t_off > 0:\n        data[int(size * t_off / duration) :] = -1\n    sig = Signal(duration=duration, size=size, func=lambda t: data)\n    return sig\n\n\nWAVEFORMS = {\n    \"sine\": sine,\n    \"chirp\": chirp,\n    \"sawtooth\": sawtooth,\n    \"square\": square,\n    \"on_off\": on_off,\n}\n\n\nclass Select(Enum):\n    \"\"\"Enumeration to select signal type.\"\"\"\n\n    OnOff = \"on_off\"\n    Sine = \"sine\"\n    Chirp = \"chirp\"\n    Sawtooth = \"sawtooth\"\n    Square = \"square\"\n\n\nclass WaveForm(widgets.Container):\n    \"\"\"Simple waveform generator widget, with plotting.\"\"\"\n\n    def __init__(self):\n        \"\"\"Creates the widget.\"\"\"\n        super().__init__()\n        self.fig, self.ax = plt.subplots()\n        self.native.layout().addWidget(FigureCanvas(self.fig))\n        self.waveform = sine\n        self.controls = None\n        self.append(self.signal_widget)\n        self.update_controls()\n        self.update_graph(sine())\n\n    @magicgui(auto_call=True)\n    def signal_widget(self, select: Select = Select.Sine) -> widgets.Container:\n        \"\"\"Waveform selection, from the WAVEFORMS dict.\"\"\"\n        self.waveform = WAVEFORMS[select.value]\n        self.update_controls()\n        self.update_graph(self.waveform())\n\n    def update_controls(self):\n        \"\"\"Reset controls according to the new function.\"\"\"\n        if self.controls is not None:\n            self.remove(self.controls)\n        self.controls = magicgui(auto_call=True)(self.waveform)\n        self.append(self.controls)\n        self.controls.called.connect(self.update_graph)\n\n    def update_graph(self, sig: Signal):\n        \"\"\"Re-plot when a parameter changes.\n\n        Note\n        ----\n        For big data, this could be slow, maybe `auto_call` should\n        not be true in the method above...\n        \"\"\"\n        self.ax.cla()\n        sig.plot(ax=self.ax)\n        self.fig.canvas.draw()\n\n\nwaveform = WaveForm()\nwaveform.show(run=True)\n

Total running time of the script: ( 0 minutes 0.240 seconds)

Download Python source code: waveform.py

Download Jupyter notebook: waveform.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/napari/mg_execution_times/","title":"Computation times","text":"

00:14.887 total execution time for generated_examples_napari files:

+--------------------------------------------------------------------------------------------------------+-----------+--------+ | napari_combine_qt (docs/examples/napari/napari_combine_qt.py) | 00:09.604 | 0.0 MB | +--------------------------------------------------------------------------------------------------------+-----------+--------+ | napari_parameter_sweep (docs/examples/napari/napari_parameter_sweep.py) | 00:02.986 | 0.0 MB | +--------------------------------------------------------------------------------------------------------+-----------+--------+ | napari_img_math (docs/examples/napari/napari_img_math.py) | 00:02.262 | 0.0 MB | +--------------------------------------------------------------------------------------------------------+-----------+--------+ | napari_forward_refs (docs/examples/napari/napari_forward_refs.py) | 00:00.035 | 0.0 MB | +--------------------------------------------------------------------------------------------------------+-----------+--------+

"},{"location":"generated_examples/napari/napari_combine_qt/","title":"napari Qt demo","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/napari/napari_combine_qt/#napari-qt-demo","title":"napari Qt demo","text":"

Napari provides a few conveniences with magicgui, and one of the most commonly used is the layer combo box that gets created when a parameter is annotated as napari.layers.Layer.

The layer box will stay in sync with the viewer model, adding and removing layers as needed.

This example shows how to use just that widget in the context of a larger custom QWidget.

import napari\nfrom qtpy.QtWidgets import QVBoxLayout, QWidget\n\nfrom magicgui.widgets import create_widget\n\n\nclass CustomWidget(QWidget):\n    \"\"\"A custom widget class.\"\"\"\n\n    def __init__(self) -> None:\n        super().__init__()\n        self.setLayout(QVBoxLayout())\n        # change annotation to napari.layers.Image (e.g) to restrict to just Images\n        self._layer_combo = create_widget(annotation=napari.layers.Layer)\n        # magicgui widgets hold the Qt widget at `widget.native`\n        self.layout().addWidget(self._layer_combo.native)\n\n\nviewer = napari.Viewer()\nviewer.add_points()\nviewer.add_points()\n\nmy_widget = CustomWidget()\nviewer.window.add_dock_widget(my_widget)\n\n# when my_widget is a magicgui.Widget, it will detect that it has been added\n# to a viewer, and automatically update the choices.  Otherwise, you need to\n# trigger this yourself:\nmy_widget._layer_combo.reset_choices()\nviewer.layers.events.inserted.connect(my_widget._layer_combo.reset_choices)\nviewer.layers.events.removed.connect(my_widget._layer_combo.reset_choices)\n\nnapari.run()\n

Total running time of the script: ( 0 minutes 9.604 seconds)

Download Python source code: napari_combine_qt.py

Download Jupyter notebook: napari_combine_qt.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/napari/napari_forward_refs/","title":"napari forward reference demo","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/napari/napari_forward_refs/#napari-forward-reference-demo","title":"napari forward reference demo","text":"

Example of using a ForwardRef to avoid importing a module that provides a widget.

In this example, one might want to create a widget that takes as an argument a napari Image layer, and returns an Image. In order to avoid needing to import napari (and therefore depending directly on napari), it's possible to annotate those parameters with a string representation of the type (rather than the type itself). This is called a \"forward reference\": https://www.python.org/dev/peps/pep-0484/#forward-references

Out:

<FunctionGui subtract_background(data: napari.types.ImageData = None, background: int = 50) -> napari.types.ImageData>\n

# Note: if you'd like to avoid circular imports, or just want to avoid having your\n# linter yell at you for an undefined type annotation, you can place the import\n# inside of an `if typing.TYPE_CHECKING` conditional.  This is not evaluated at runtime,\n# only when something like mypy is doing type checking.\nfrom typing import TYPE_CHECKING\n\nfrom magicgui import magicgui\n\nif TYPE_CHECKING:\n    import napari\n\n\n@magicgui(call_button=\"execute\", background={\"max\": 200})\ndef subtract_background(\n    data: \"napari.types.ImageData\", background: int = 50\n) -> \"napari.types.ImageData\":\n    \"\"\"Subtract a constant from the data.\"\"\"\n    if data:\n        return data - background\n\n\nsubtract_background.show(run=True)\n# now, this example isn't all that interesting on its own (since there will be no Image\n# layer in the dropdown) ... but in another package, where you DO import napari,\n# you could add this widget to a napari viewer with\n# viewer.window.add_dock_widget(subtract_background)\n

Total running time of the script: ( 0 minutes 0.035 seconds)

Download Python source code: napari_forward_refs.py

Download Jupyter notebook: napari_forward_refs.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/napari/napari_img_math/","title":"napari image arithmetic widget","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/napari/napari_img_math/#napari-image-arithmetic-widget","title":"napari image arithmetic widget","text":"

napari is a fast, interactive, multi-dimensional image viewer for python. It uses Qt for the GUI, so it's easy to extend napari with small, composable widgets created with magicgui. Here we're going to build this simple image arithmetic widget with a few additional lines of code.

For napari-specific magicgui documentation, see the napari docs

"},{"location":"generated_examples/napari/napari_img_math/#outline","title":"outline","text":"

This example demonstrates how to:

  1. Create a magicgui widget that can be used in another program (napari)

  2. Use an Enum to create a dropdown menu

  3. Connect some event listeners to create interactivity.

"},{"location":"generated_examples/napari/napari_img_math/#code","title":"code","text":"

Code follows, with explanation below... You can also get this example at github.

from enum import Enum\n\nimport napari\nimport numpy\nfrom napari.types import ImageData\n\nfrom magicgui import magicgui\n\n\nclass Operation(Enum):\n    # A set of valid arithmetic operations for image_arithmetic.\n    #\n    # To create nice dropdown menus with magicgui, it's best\n    # (but not required) to use Enums.  Here we make an Enum\n    # class for all of the image math operations we want to\n    # allow.\n    add = numpy.add\n    subtract = numpy.subtract\n    multiply = numpy.multiply\n    divide = numpy.divide\n\n\n# here's the magicgui!  We also use the additional\n# `call_button` option\n@magicgui(call_button=\"execute\")\ndef image_arithmetic(\n    layerA: ImageData, operation: Operation, layerB: ImageData\n) -> ImageData:\n    # Add, subtracts, multiplies, or divides to image layers.\n    return operation.value(layerA, layerB)\n\n# create a viewer and add a couple image layers\nviewer = napari.Viewer()\nviewer.add_image(numpy.random.rand(20, 20), name=\"Layer 1\")\nviewer.add_image(numpy.random.rand(20, 20), name=\"Layer 2\")\n\n# add our new magicgui widget to the viewer\nviewer.window.add_dock_widget(image_arithmetic)\n\n# keep the dropdown menus in the gui in sync with the layer model\nviewer.layers.events.inserted.connect(image_arithmetic.reset_choices)\nviewer.layers.events.removed.connect(image_arithmetic.reset_choices)\n\nnapari.run()\n
"},{"location":"generated_examples/napari/napari_img_math/#walkthrough","title":"walkthrough","text":"

We're going to go a little out of order so that the other code makes more sense. Let's start with the actual function we'd like to write to do some image arithmetic.

"},{"location":"generated_examples/napari/napari_img_math/#the-function","title":"the function","text":"

Our function takes two numpy arrays (in this case, from Image layers), and some mathematical operation (we'll restrict the options using an enum.Enum). When called, ourfunction calls the selected operation on the data.

def image_arithmetic(array1, operation, array2):\n    return operation.value(array1, array2)\n
"},{"location":"generated_examples/napari/napari_img_math/#type-annotations","title":"type annotations","text":"

magicgui works particularly well with type annotations, and allows third-party libraries to register widgets and behavior for handling their custom types (using magicgui.type_map.register_type). napari provides support for magicgui by registering a dropdown menu whenever a function parameter is annotated as one of the basic napari Layer types, or, in this case, ImageData indicates we just the data attribute of the layer. Furthermore, it recognizes when a function has a napari.layers.Layer or LayerData return type annotation, and will add the result to the viewer. So we gain a lot by annotating the above function with the appropriate napari types.

from napari.types import ImageData\n\ndef image_arithmetic(\n    layerA: ImageData, operation: Operation, layerB: ImageData\n) -> ImageData:\n    return operation.value(layerA, layerB)\n
"},{"location":"generated_examples/napari/napari_img_math/#the-magic-part","title":"the magic part","text":"

Finally, we decorate the function with @magicgui and tell it we'd like to have a call_button that we can click to execute the function.

@magicgui(call_button=\"execute\")\ndef image_arithmetic(layerA: ImageData, operation: Operation, layerB: ImageData):\n    return operation.value(layerA, layerB)\n

That's it! The image_arithmetic function is now a FunctionGui that can be shown, or incorporated into other GUIs (such as the napari GUI shown in this example)

!!! note While type hints aren't always required in magicgui, they are recommended ... and they are required for certain things, like the Operation(Enum) used here for the dropdown and the napari.types.ImageData annotations that napari has registered with magicgui.

"},{"location":"generated_examples/napari/napari_img_math/#create-dropdowns-with-enums","title":"create dropdowns with Enums","text":"

We'd like the user to be able to select the operation (add, subtract, multiply, divide) using a dropdown menu. enum.Enum offers a convenient way to restrict values to a strict set of options, while providing name: value pairs for each of the options. Here, the value for each choice is the actual function we would like to have called when that option is selected.

class Operation(enum.Enum):\n    add = numpy.add\n    subtract = numpy.subtract\n    multiply = numpy.multiply\n    divide = numpy.divide\n
"},{"location":"generated_examples/napari/napari_img_math/#add-it-to-napari","title":"add it to napari","text":"

When we decorated the image_arithmetic function above, it became a FunctionGui. Napari recognizes this type, so we can simply add it to the napari viewer as follows:

viewer.window.add_dock_widget(image_arithmetic)\n
"},{"location":"generated_examples/napari/napari_img_math/#connect-event-listeners-for-interactivity","title":"connect event listeners for interactivity","text":"

What fun is a GUI without some interactivity? Let's make stuff happen.

We connect the image_arithmetic.reset_choices function to the viewer.layers.events.inserted/removed event from napari, to make sure that the dropdown menus stay in sync if a layer gets added or removed from the napari window:

viewer.layers.events.inserted.connect(image_arithmetic.reset_choices)\nviewer.layers.events.removed.connect(image_arithmetic.reset_choices)\n

Tip

An additional offering from magicgui here is that the decorated function also acquires a new attribute \"called\" that can be connected to callback functions of your choice. Then, whenever the gui widget or the original function are called, the result will be passed to your callback function:

@image_arithmetic.called.connect\ndef print_mean(value):\n    # Callback function that accepts an event\n    # the value attribute has the result of calling the function\n    print(np.mean(value))\n
>>> image_arithmetic()\n1.0060037881040373\n
"},{"location":"generated_examples/napari/napari_img_math/#code_1","title":"Code","text":"

Here's the full code example again.

from enum import Enum\n\nimport napari\nimport numpy\nfrom napari.types import ImageData\n\nfrom magicgui import magicgui\n\n\nclass Operation(Enum):\n    # A set of valid arithmetic operations for image_arithmetic.\n    #\n    # To create nice dropdown menus with magicgui, it's best\n    # (but not required) to use Enums.  Here we make an Enum\n    # class for all of the image math operations we want to\n    # allow.\n    add = numpy.add\n    subtract = numpy.subtract\n    multiply = numpy.multiply\n    divide = numpy.divide\n\n\n# here's the magicgui!  We also use the additional\n# `call_button` option\n@magicgui(call_button=\"execute\")\ndef image_arithmetic(\n    layerA: ImageData, operation: Operation, layerB: ImageData\n) -> ImageData:\n    # Add, subtracts, multiplies, or divides to image layers.\n    return operation.value(layerA, layerB)\n\n\n# create a viewer and add a couple image layers\nviewer = napari.Viewer()\nviewer.add_image(numpy.random.rand(20, 20), name=\"Layer 1\")\nviewer.add_image(numpy.random.rand(20, 20), name=\"Layer 2\")\n\n# add our new magicgui widget to the viewer\nviewer.window.add_dock_widget(image_arithmetic)\n\n# keep the dropdown menus in the gui in sync with the layer model\nviewer.layers.events.inserted.connect(image_arithmetic.reset_choices)\nviewer.layers.events.removed.connect(image_arithmetic.reset_choices)\n\nnapari.run()\n

Total running time of the script: ( 0 minutes 2.262 seconds)

Download Python source code: napari_img_math.py

Download Jupyter notebook: napari_img_math.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/napari/napari_parameter_sweep/","title":"napari parameter sweeps","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/napari/napari_parameter_sweep/#napari-parameter-sweeps","title":"napari parameter sweeps","text":"

napari is a fast, interactive, multi-dimensional image viewer for python. It uses Qt for the GUI, so it's easy to extend napari with small, composable widgets created with magicgui. Here, we demonstrate how to build a interactive widget that lets you immediately see the effect of changing one of the parameters of your function.

For napari-specific magicgui documentation, see the napari docs

See also: Some of this tutorial overlaps with topics covered in the napari image arithmetic example.

"},{"location":"generated_examples/napari/napari_parameter_sweep/#outline","title":"outline","text":"

This example demonstrates how to:

  1. Create a magicgui widget that can be used in another program (napari)

  2. Automatically call our function when a parameter changes

  3. Provide magicgui with a custom widget for a specific argument

  4. Use the choices option to create a dropdown

  5. Connect some event listeners to create interactivity.

"},{"location":"generated_examples/napari/napari_parameter_sweep/#code","title":"code","text":"

Code follows, with explanation below... You can also get this example at github.

import napari\nimport skimage.data\nimport skimage.filters\nfrom napari.types import ImageData\n\nfrom magicgui import magicgui\n\n\n# turn the gaussian blur function into a magicgui\n# - 'auto_call' tells magicgui to call the function when a parameter changes\n# - we use 'widget_type' to override the default \"float\" widget on sigma,\n#   and provide a maximum valid value.\n# - we contstrain the possible choices for 'mode'\n@magicgui(\n    auto_call=True,\n    sigma={\"widget_type\": \"FloatSlider\", \"max\": 6},\n    mode={\"choices\": [\"reflect\", \"constant\", \"nearest\", \"mirror\", \"wrap\"]},\n    layout=\"horizontal\",\n)\ndef gaussian_blur(layer: ImageData, sigma: float = 1.0, mode=\"nearest\") -> ImageData:\n    # Apply a gaussian blur to 'layer'.\n    if layer is not None:\n        return skimage.filters.gaussian(layer, sigma=sigma, mode=mode)\n\n# create a viewer and add some images\nviewer = napari.Viewer()\nviewer.add_image(skimage.data.astronaut().mean(-1), name=\"astronaut\")\nviewer.add_image(skimage.data.grass().astype(\"float\"), name=\"grass\")\n\n# Add it to the napari viewer\nviewer.window.add_dock_widget(gaussian_blur)\n# update the layer dropdown menu when the layer list changes\nviewer.layers.events.changed.connect(gaussian_blur.reset_choices)\n\nnapari.run()\n
"},{"location":"generated_examples/napari/napari_parameter_sweep/#walkthrough","title":"walkthrough","text":"

We're going to go a little out of order so that the other code makes more sense. Let's start with the actual function we'd like to write to apply a gaussian filter to an image.

"},{"location":"generated_examples/napari/napari_parameter_sweep/#the-function","title":"the function","text":"

Our function is a very thin wrapper around skimage.filters.gaussian. It takes a napari Image layer, a sigma to control the blur radius, and a mode that determines how edges are handled.

def gaussian_blur(\n    layer: Image, sigma: float = 1, mode=\"nearest\"\n) -> Image:\n    return filters.gaussian(layer.data, sigma=sigma, mode=mode)\n

The reasons we are wrapping it here are:

  1. filters.gaussian accepts a numpy array, but we want to work with napari layers that store the data in a layer.data attribute. So we need an adapter.
  2. We'd like to add some type annotations to the signature that were not provided by filters.gaussian
"},{"location":"generated_examples/napari/napari_parameter_sweep/#type-annotations","title":"type annotations","text":"

As described in the image arithmetic example, we take advantage of napari's built in support for magicgui by annotating our function parameters and return value as napari Layer types. napari will then tell magicgui what to do with them, creating a dropdown with a list of current layers for our layer parameter, and automatically adding the result of our function to the viewer when called.

For documentation on napari types with magicgui, see the napari docs

"},{"location":"generated_examples/napari/napari_parameter_sweep/#the-magic-part","title":"the magic part","text":"

Finally, we decorate the function with @magicgui and provide some options.

@magicgui(\n    auto_call=True,\n    sigma={\"widget_type\": \"FloatSlider\", \"max\": 6},\n    mode={\"choices\": [\"reflect\", \"constant\", \"nearest\", \"mirror\", \"wrap\"]},\n)\ndef gaussian_blur(\n  layer: ImageData, sigma: float = 1.0, mode=\"nearest\"\n) -> ImageData:\n    # Apply a gaussian blur to ``layer``.\n    if layer is not None:\n        return skimage.filters.gaussian(layer, sigma=sigma, mode=mode)\n
  • auto_call=True makes it so that the gaussian_blur function will be called whenever one of the parameters changes (with the current parameters set in the GUI).
  • We then provide keyword arguments to modify the look & behavior of sigma and mode:

    • \"widget_type\": \"FloatSlider\" tells magicgui not to use the standard (float) widget for the sigma widget, but rather to use a slider widget.
    • we then set an upper limit on the slider values for sigma.
  • finally, we specify valid choices for the mode argument. This turns that parameter into a categorical/dropdown type widget, and sets the options.

"},{"location":"generated_examples/napari/napari_parameter_sweep/#connecting-events","title":"connecting events","text":"

As described in the Events documentation, we can also connect any callback to the gaussian_blur.called signal that will receive the result of our decorated function anytime it is called.

def do_something_with_result(result):\n    ...\n\ngaussian_blur.called.connect(do_something_with_result)\n
"},{"location":"generated_examples/napari/napari_parameter_sweep/#code_1","title":"Code","text":"

Here's the full code example again.

import napari\nimport skimage.data\nimport skimage.filters\nfrom napari.types import ImageData\n\nfrom magicgui import magicgui\n\n\n# turn the gaussian blur function into a magicgui\n# - 'auto_call' tells magicgui to call the function when a parameter changes\n# - we use 'widget_type' to override the default \"float\" widget on sigma,\n#   and provide a maximum valid value.\n# - we contstrain the possible choices for 'mode'\n@magicgui(\n    auto_call=True,\n    sigma={\"widget_type\": \"FloatSlider\", \"max\": 6},\n    mode={\"choices\": [\"reflect\", \"constant\", \"nearest\", \"mirror\", \"wrap\"]},\n    layout=\"horizontal\",\n)\ndef gaussian_blur(layer: ImageData, sigma: float = 1.0, mode=\"nearest\") -> ImageData:\n    # Apply a gaussian blur to 'layer'.\n    if layer is not None:\n        return skimage.filters.gaussian(layer, sigma=sigma, mode=mode)\n\n\n# create a viewer and add some images\nviewer = napari.Viewer()\nviewer.add_image(skimage.data.astronaut().mean(-1), name=\"astronaut\")\nviewer.add_image(skimage.data.grass().astype(\"float\"), name=\"grass\")\n\n# Add it to the napari viewer\nviewer.window.add_dock_widget(gaussian_blur)\n# update the layer dropdown menu when the layer list changes\nviewer.layers.events.changed.connect(gaussian_blur.reset_choices)\n\nnapari.run()\n

Total running time of the script: ( 0 minutes 2.986 seconds)

Download Python source code: napari_parameter_sweep.py

Download Jupyter notebook: napari_parameter_sweep.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/notebooks/magicgui_jupyter/","title":"Jupyter notebooks and magicgui","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/notebooks/magicgui_jupyter/#jupyter-notebooks-and-magicgui","title":"Jupyter notebooks and magicgui","text":"

This example shows magicgui widgets embedded in a jupyter notebook.

The key function here is use_app(\"ipynb\").

You can also get this example at github.

import math\nfrom enum import Enum\n\nfrom magicgui import magicgui, use_app\nuse_app(\"ipynb\")\n\nclass Medium(Enum):\n    # Various media and their refractive indices.\n    Glass = 1.520\n    Oil = 1.515\n    Water = 1.333\n    Air = 1.0003\n\n\n@magicgui(\n    call_button=\"calculate\", result_widget=True, layout='vertical', auto_call=True\n)\ndef snells_law(aoi=1.0, n1=Medium.Glass, n2=Medium.Water, degrees=True):\n    # Calculate the angle of refraction given two media and an angle of incidence.\n    if degrees:\n        aoi = math.radians(aoi)\n    try:\n        n1 = n1.value\n        n2 = n2.value\n        result = math.asin(n1 * math.sin(aoi) / n2)\n        return round(math.degrees(result) if degrees else result, 2)\n    except ValueError:  # math domain error\n        return \"TIR!\"\n\n\nsnells_law\n

Total running time of the script: ( 0 minutes 0.000 seconds)

Download Python source code: magicgui_jupyter.py

Download Jupyter notebook: magicgui_jupyter.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/notebooks/mg_execution_times/","title":"Computation times","text":"

00:00.000 total execution time for generated_examples_notebooks files:

+-----------------------------------------------------------------------------------------+-----------+--------+ | magicgui_jupyter (docs/examples/notebooks/magicgui_jupyter.py) | 00:00.000 | 0.0 MB | +-----------------------------------------------------------------------------------------+-----------+--------+

"},{"location":"generated_examples/progress_bars/mg_execution_times/","title":"Computation times","text":"

00:00.172 total execution time for generated_examples_progress_bars files:

+---------------------------------------------------------------------------------------------------------------+-----------+--------+ | progress_nested (docs/examples/progress_bars/progress_nested.py) | 00:00.056 | 0.0 MB | +---------------------------------------------------------------------------------------------------------------+-----------+--------+ | progress_manual (docs/examples/progress_bars/progress_manual.py) | 00:00.043 | 0.0 MB | +---------------------------------------------------------------------------------------------------------------+-----------+--------+ | progress (docs/examples/progress_bars/progress.py) | 00:00.043 | 0.0 MB | +---------------------------------------------------------------------------------------------------------------+-----------+--------+ | progress_indeterminate (docs/examples/progress_bars/progress_indeterminate.py) | 00:00.031 | 0.0 MB | +---------------------------------------------------------------------------------------------------------------+-----------+--------+

"},{"location":"generated_examples/progress_bars/progress/","title":"Simple progress bar","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/progress_bars/progress/#simple-progress-bar","title":"Simple progress bar","text":"

A simple progress bar demo with magicgui.

Out:

<FunctionGui long_running(steps=10, delay=0.1)>\n

from time import sleep\n\nfrom magicgui import magicgui\nfrom magicgui.tqdm import trange\n\n# if magicui.tqdm.tqdm or trange are used outside of a @magicgui function, (such as in\n# interactive use in IPython), then they fall back to the standard terminal output\n\n\n# If use inside of a magicgui-decorated function\n# a progress bar widget will be added to the magicgui container\n@magicgui(call_button=True, layout=\"horizontal\")\ndef long_running(steps=10, delay=0.1):\n    \"\"\"Long running computation with range iterator.\"\"\"\n    # trange(steps) is a shortcut for `tqdm(range(steps))`\n    for _i in trange(steps):\n        sleep(delay)\n\n\nlong_running.show(run=True)\n

Total running time of the script: ( 0 minutes 0.043 seconds)

Download Python source code: progress.py

Download Jupyter notebook: progress.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/progress_bars/progress_indeterminate/","title":"Indeterminate progress bar","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/progress_bars/progress_indeterminate/#indeterminate-progress-bar","title":"Indeterminate progress bar","text":"

Example of an indeterminate progress bar for a long running computation of unknown time.

Out:

<FunctionGui long_running(sleep_time=5)>\n

import time\n\nfrom superqt.utils import thread_worker\n\nfrom magicgui import magicgui\nfrom magicgui.tqdm import tqdm\n\n\n@magicgui(call_button=True, layout=\"horizontal\")\ndef long_running(sleep_time=5):\n    \"\"\"Long running computation with an indeterminate progress bar.\"\"\"\n    # Here tqdm is not provided an iterable argument, or the 'total' kwarg\n    # so it cannot calculate the expected number of iterations\n    # which means it will create an indeterminate progress bar\n    with tqdm() as pbar:\n        # It is best practice to use a separate thread for long running computations\n        # This makes the function non-blocking, you can still interact with the widget\n        @thread_worker(connect={\"finished\": lambda: pbar.progressbar.hide()})\n        def sleep(secs):\n            time.sleep(secs)\n\n        sleep(sleep_time)\n\n\nlong_running.show(run=True)\n

Total running time of the script: ( 0 minutes 0.031 seconds)

Download Python source code: progress_indeterminate.py

Download Jupyter notebook: progress_indeterminate.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/progress_bars/progress_manual/","title":"Manual progress bar","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/progress_bars/progress_manual/#manual-progress-bar","title":"Manual progress bar","text":"

Example of a progress bar being updated manually.

Out:

<FunctionGui manual(pbar: magicgui.widgets.ProgressBar = ProgressBar(value=<function match_type.<locals>.<lambda> at 0x136701260>, annotation=<class 'magicgui.widgets.ProgressBar'>, name='pbar'), increment: bool = 1)>\n

from magicgui import magicgui\nfrom magicgui.widgets import ProgressBar\n\n\n@magicgui(call_button=\"tick\", pbar={\"min\": 0, \"step\": 2, \"max\": 20, \"value\": 0})\ndef manual(pbar: ProgressBar, increment: bool = True):\n    \"\"\"Example of manual progress bar control.\"\"\"\n    if increment:\n        pbar.increment()\n    else:\n        pbar.decrement()\n\n\nmanual.show(run=True)\n

Total running time of the script: ( 0 minutes 0.043 seconds)

Download Python source code: progress_manual.py

Download Jupyter notebook: progress_manual.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/progress_bars/progress_nested/","title":"Nested progress bars","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/progress_bars/progress_nested/#nested-progress-bars","title":"Nested progress bars","text":"

Example using nested progress bars in magicgui.

Out:

<FunctionGui long_function(steps=10, repeats=4, choices='ABCDEFGHIJKLMNOP12345679', char='', delay=0.05)>\n

import random\nfrom time import sleep\n\nfrom magicgui import magicgui\nfrom magicgui.tqdm import tqdm, trange\n\n# if magicui.tqdm.tqdm or trange are used outside of a @magicgui function, (such as in\n# interactive use in IPython), then they fall back to the standard terminal output\n\n\n# If use inside of a magicgui-decorated function\n# a progress bar widget will be added to the magicgui container\n@magicgui(call_button=True, layout=\"vertical\")\ndef long_function(\n    steps=10, repeats=4, choices=\"ABCDEFGHIJKLMNOP12345679\", char=\"\", delay=0.05\n):\n    \"\"\"Long running computation with nested iterators.\"\"\"\n    # trange and tqdm accept all the kwargs from tqdm itself, as well as any\n    # valid kwargs for magicgui.widgets.ProgressBar, (such as \"label\")\n    for _r in trange(repeats, label=\"repeats\"):\n        letters = [random.choice(choices) for _ in range(steps)]\n        # `tqdm`, like `tqdm`, accepts any iterable\n        # this progress bar is nested and will be run & reset multiple times\n        for letter in tqdm(letters, label=\"steps\"):\n            long_function.char.value = letter\n            sleep(delay)\n\n\nlong_function.show(run=True)\n

Total running time of the script: ( 0 minutes 0.056 seconds)

Download Python source code: progress_nested.py

Download Jupyter notebook: progress_nested.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/under_the_hood/class_method/","title":"Deocrate class methods with magicgui","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/under_the_hood/class_method/#deocrate-class-methods-with-magicgui","title":"Deocrate class methods with magicgui","text":"

Demonstrates decorating a class method with magicgui.

Once the class is instantiated, instance.method_name will return a FunctionGui in which the instance will always be provided as the first argument (i.e. \"self\") when the FunctionGui or method is called.

Out:

instance: a, counter: 0.0, sigma: 0.0\ninstance: b, counter: 0.0, sigma: 0.0\n

from magicgui import event_loop, magicgui\nfrom magicgui.widgets import Container\n\n\nclass MyObject:\n    \"\"\"Example object class.\"\"\"\n\n    def __init__(self, name):\n        self.name = name\n        self.counter = 0.0\n\n    @magicgui(auto_call=True)\n    def method(self, sigma: float = 0):\n        \"\"\"Example class method.\"\"\"\n        print(f\"instance: {self.name}, counter: {self.counter}, sigma: {sigma}\")\n        self.counter = self.counter + sigma\n        return self.name\n\n\nwith event_loop():\n    a = MyObject(\"a\")\n    b = MyObject(\"b\")\n    container = Container(widgets=[a.method, b.method])\n    container.show()\n    assert a.method() == \"a\"\n    assert b.method() == \"b\"\n

Total running time of the script: ( 0 minutes 0.035 seconds)

Download Python source code: class_method.py

Download Jupyter notebook: class_method.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/under_the_hood/mg_execution_times/","title":"Computation times","text":"

00:00.075 total execution time for generated_examples_under_the_hood files:

+----------------------------------------------------------------------------------------+-----------+--------+ | self_reference (docs/examples/under_the_hood/self_reference.py) | 00:00.040 | 0.0 MB | +----------------------------------------------------------------------------------------+-----------+--------+ | class_method (docs/examples/under_the_hood/class_method.py) | 00:00.035 | 0.0 MB | +----------------------------------------------------------------------------------------+-----------+--------+

"},{"location":"generated_examples/under_the_hood/self_reference/","title":"Self reference magicgui widgets","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/under_the_hood/self_reference/#self-reference-magicgui-widgets","title":"Self reference magicgui widgets","text":"

Widgets created with magicgui can reference themselves, and use the widget API.

Out:

<FunctionGui function(width=400, x: int = 50)>\n

from magicgui import magicgui\n\n\n@magicgui(auto_call=True, width={\"max\": 800, \"min\": 100}, x={\"widget_type\": \"Slider\"})\ndef function(width=400, x: int = 50):\n    \"\"\"Example function.\"\"\"\n    # the widget can reference itself, and use the widget API\n    function.x.width = width\n\n\nfunction.show(run=True)\n

Total running time of the script: ( 0 minutes 0.040 seconds)

Download Python source code: self_reference.py

Download Jupyter notebook: self_reference.ipynb

Gallery generated by mkdocs-gallery

"}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"magicgui \ud83e\uddd9","text":"

magicgui is a python library for building graphical user interfaces (GUIs).

It aims to speed up data workflows by providing a simple, consistent API for creating GUIs to control various data types, that work across various environments.

GUIs may be built manually using a variety of widgets, or generated automatically from python type hints.

"},{"location":"#magicgui-organization","title":"magicgui organization","text":"

magicgui can be thought of as performing two distinct tasks:

  1. Providing an simplified abstraction layer for GUI frameworks, allowing you to use the same API to create UIs that can move between environments and frameworks (such as a desktop app, or a Jupyter notebook).
  2. Providing a mapping of python types to widgets, allowing you to autogenerate graphical user interfaces for functions and dataclasses by annotating with standard python type hints.

While there is some degree of customizeability, the emphasis is on rapid development of relatively simple GUIs, with minimal boilerplate. For highly customized GUIs with complex layouts, it may be more appropriate to use a lower-level GUI framework.

The API is organized into 2 main levels:

magicgui API layers"},{"location":"#python-type-mapping","title":"Python Type Mapping","text":"

At its highest level, magicgui provides a mapping of Python types to widgets. This API allows you to create graphical user interfaces for your functions and dataclasses simply by annotating them with standard python type hints.

Type hints??

Type hints are a way to annotate your code with information about the types of variables and function arguments. They are completely optional, but static type checkers and other libraries (like magicgui!) can use them to check your code and/or provide additional functionality.

Typically, they are provided after a colon following a variable name or function argument.

In the example below, param_a has been annotated as an int, param_b as a str, and the return value as a list.

def my_function(param_a: int, param_b: str) -> list:\n    ...\n

If you are new to type annotations in Python, here are a few resources to get you started:

  • PEP 484 - the Python Enhancement Proposal that introduced type hints to the language. (See also: PEP 483)
  • Python docs - the official Python documentation on type hints and the typing module.
  • The mypy documentation also has a lot of useful information, including this cheat sheet
"},{"location":"#create_widget","title":"create_widget","text":"

magicgui.widgets.create_widget is a general function, used throughout the library, that allows you to create a widget for a specific Python type or value:

from magicgui.widgets import create_widget\n\n# passing a type to create_widget\nwidget = create_widget(annotation=int)\nwidget.show()\n

# passing a value to create_widget\nwidget2 = create_widget(value=\"Hello World\")\nwidget2.show()\n

For more details on how magicgui maps types to widgets, see Type Mapping.

"},{"location":"#magicgui_1","title":"magicgui","text":"

The magicgui.magicgui function is one way to autogenerate a compound Widget based on the parameters of a function:

from typing import Annotated, Literal\n# for Python <= 3.8\n# from typing_extensions import Annotated\n# for Python <= 3.7\n# from typing_extensions import Annotated, Literal\n\nfrom magicgui import magicgui\n\n\n@magicgui\ndef my_function(\n    param_a: int,\n    param_b: Annotated[int, {'widget_type': \"Slider\", 'max': 100}] = 42,\n    param_c: Literal[\"First\", \"Second\", \"Third\"] = \"Second\"\n):\n    print(\"param_a:\", param_a)\n    print(\"param_b:\", param_b)\n    print(\"param_c:\", param_c)\n\n# my_function now IS a widget, in addition to being a callable function\nmy_function.show()\n

For more details on using magicgui and magic_factory, see the magicgui decorators page.

"},{"location":"#guiclass","title":"guiclass","text":"

magicgui.experimental.guiclass is a newer experimental feature that provides an object-oriented alternative to magicgui. It wraps dataclasses.dataclass and adds a gui attribute to the resulting class, which is a magicgui-generated widget that can be used to control the dataclass instance. (The widget is only created when the gui attribute is accessed for the first time.)

from magicgui.experimental import guiclass, button\n\n@guiclass\nclass MyDataclass:\n    a: int = 0\n    b: str = 'hello'\n    c: bool = True\n\n    @button\n    def compute(self):\n        print(self.a, self.b, self.c)\n\nobj = MyDataclass(a=10, b='foo')\nobj.gui.show()\n

For more details on using the guiclass decorator, see Dataclasses & guiclass.

"},{"location":"#widgets","title":"Widgets","text":"

At the lower level, magicgui is a library of widgets (the individual elements that make up a graphical user interface). Each widget is customized to display and interact with a specific type of data. In some cases, it makes more sense to create and arrange these widgets manually, rather than using the type-based autogeneration features described above.

Magicgui acts as an abstraction layer for a variety of different GUI toolkits, allowing you to use the same API to create UIs that can move between environments (such as a desktop app, or a Jupyter notebook).

Currently, magicgui supports the following backends:

  • Qt (via PySide2/PySide6 or PyQt5/PyQt6)
  • Jupyter Widgets (a.k.a. \"IPyWidgets\")

You can use magicgui.widgets to quickly build graphical user interfaces.

from magicgui import widgets\n\na = widgets.SpinBox(value=10, label=\"a\")\nb = widgets.Slider(value=20, min=0, max=100, label=\"b\")\nresult = widgets.LineEdit(value=a.value * b.value, label=\"result\")\nbutton = widgets.PushButton(text=\"multiply\")\n\n@button.clicked.connect\ndef on_button_click():\n    result.value = a.value * b.value\n\ncontainer = widgets.Container(widgets=[a, b, result, button])\ncontainer.show()\n

To learn more about the available widgets and how to use them, see the Widgets Overview.

...details

Behind the scenes, magicgui declares a set of WidgetProtocols that each backend must implement, and every magicgui Widget is a wrapper around a backend-specific widget. Most users will never need to worry about this, but it's good to know that it's there if you ever need to dig deeper.

"},{"location":"#events","title":"Events","text":"

All widgets (whether created directly or autogenerated based on type hints) emit events when their value changes or in response to interaction.

To learn about connecting custom functionality to these events, see Events.

"},{"location":"#installation","title":"Installation","text":"

See installing magicgui.

"},{"location":"CONTRIBUTING/","title":"Contributing","text":"

Contributions are welcome!

"},{"location":"CONTRIBUTING/#development","title":"Development","text":"

To install magicgui for development, first clone the repository:

git clone https://github.com/pyapp-kit/magicgui\ncd magicgui\n

Then install the package in editable mode with the dev extra:

pip install -e .[dev]\n

To run the tests:

pytest\n
"},{"location":"CONTRIBUTING/#code-quality","title":"Code Quality","text":"

magicgui attempts to adhere to strict coding rules and employs the following static analysis tools to prevent errors from being introduced into the codebase:

  • black - code formatting
  • ruff - linting
  • mypy - static type analysis
  • codecov - test coverage

To prevent continuous integration failures when contributing, please consider installing pre-commit in your environment to run all of these checks prior to checking in new code.

pre-commit install\n

To run the checks manually, you can use:

pre-commit run --all-files\n
"},{"location":"CONTRIBUTING/#adding-a-widget","title":"Adding a widget","text":"

These instructions may change in the future as the repo structures changes. If they appear outdated as you follow them, please open an issue.

To add a new widget, you will need to:

  1. Create a new class in magicgui/widgets/_concrete.py that inherits from the base class most appropriate for your widget (e.g. ValueWidget, or CategoricalWidget).

    In some (complex) cases, you may need to extend one of the base classes. If so, it is likely that you will also need to extend one of the Protocols found in magicgui.widgets.protocols. This is where all of protocols that backend classes need to implement to work with a given widget type. (Don't hesitate to open an issue if you're confused).

  2. Most likely, you will want to decorate the class with @backend_widget. Using this decorator implies that there is a class with the same name in any any backend modules that will support this widget type (e.g. magicgui.backends._qtpy.widgets for Qt support.).

  3. Make any changes necessary to your new concrete class. For example, you may need to change the value property and corresponding setter to handle a specific type. This part of the code should be backend agnostic.
  4. Export the new class in magicgui/widgets/__init__.py so that it can be imported from magicgui.widgets.
  5. Implement the backend widget class (using the same class name) in the appropriate backend module (e.g. magicgui.backends._qtpy.widgets for Qt support). Usually this will mean implementing the appropriate _mgui_get/set_... methods for the Protocol of the corresponding widget base class your chose to extend.
  6. Export the backend widget class in the __init__.py of the backend module (e.g. magicgui.backends._qtpy.__init__.py for Qt support). This is important, as that is where the @backend_widget decorator will look.
  7. Add a test for your new widget.

For an example of a minimal PR adding a new widget, see #483, which added a QuantityWidget to be used with pint.Quantity objects.

"},{"location":"CONTRIBUTING/#associating-a-widget-with-a-type","title":"Associating a widget with a type","text":"

To associate your new widget with a specific type such that it will be used when someone annotates a parameter with that type, you will need to update code in magicgui.type_map._type_map.

In the simplest of cases, this will mean adding a new entry to the magicgui.type_map._type_map._SIMPLE_TYPES dict. This is a mapping from a python type to a widget class. (Note that all subclasses of the type will also be matched.)

For more complex cases, you can add a new conditional to the body of the match_type function. That function should always return a tuple of widget type, and kwargs that will be passed to the widget constructor. For example: return widgets.MyNewWidget, {}.

"},{"location":"CONTRIBUTING/#building-the-documentation","title":"Building the documentation","text":"

To build the documentation locally, you will need to install the docs extra:

pip install -e .[docs]\n

Then, from the root of the repository, run:

mkdocs serve\n

This will start a local server at http://127.0.0.1:8000/ where you can view the documentation as you edit it.

"},{"location":"dataclasses/","title":"Dataclasses & guiclass","text":""},{"location":"dataclasses/#what-are-dataclasses","title":"What are dataclasses?","text":"

dataclasses are a feature added in Python 3.7 (PEP 557) that allow you to simply define classes that store a specific set of data. They encourage clear, type-annotated code, and are a great way to define data structures with minimal boilerplate.

New to dataclasses?

If you're totally new to dataclasses, you might want to start with the official documentation for the dataclasses module, or this Real Python post on dataclasses. The following is a very brief example of the key features:

Example dataclass
from dataclasses import dataclass\n\n@dataclass  # (1)!\nclass Person:\n    name: str # (2)!\n    age: int = 0  # (3)!\n\np = Person(name='John', age=30)  # (4)!\nprint(p) # (5)!\n
  1. The @dataclass decorator is used to mark a class as a dataclass. This will automatically generate an __init__ method with a parameter for each annotated class attribute.
  2. Attribute names are annotated with types. Note that, as with all Python type hints, these have no runtime effect (i.e. no validation is performed).
  3. Optional attributes can be defined with a default value. If no default value is specified, then the field is required when creating a new object.
  4. Creating a new object is as simple as passing in the required arguments.
  5. The __repr__ method is automatically generated and will print out the class name and all of the attributes and their current values.
"},{"location":"dataclasses/#dataclass-patterns-outside-the-standard-library","title":"dataclass patterns outside the standard library","text":"

The dataclasses module is not the only way to define data-focused classes in Python. There are other libraries that provide similar functionality, and some of them have additional features that are not available in the standard library.

  • attrs is a popular library that provides a number of additional features on top of the standard library dataclasses, including complex validation and type conversions.
  • pydantic is a library that provides runtime type enforcement and casting, serialization, and other features.
  • msgspec is a fast serialization library with a msgspec.Struct that is similar to a dataclass.
"},{"location":"dataclasses/#magicgui-guiclass","title":"magicgui guiclass","text":"

Experimental

This is an experimental feature. The API may change in the future without deprecations or warnings.

magicgui supports the dataclass API as a way to define the interface for compound widget, where each attribute of the dataclass is a separate widget. The magicgui.experimental.guiclass decorator can be used to mark a class as a \"GUI class\". A GUI class is a Python standard dataclass that has two additional features:

  1. A property (named \"gui\" by default) that returns a Container widget which contains a widget for each attribute of the dataclass.
  2. An property (named \"events\" by default) that returns a psygnal.SignalGroup object that allows you to connect callbacks to the change event of any of field in the dataclass. (Under the hood, this uses the @evented dataclass decorator from psygnal.)

Tip

You can still use all of the standard dataclass features, including field values, __post_init__ processing, and ClassVar.

Info

In the future, we may also support other dataclass-like objects, such as pydantic models, attrs classes, and traitlets classes.

from magicgui.experimental import guiclass\n\n@guiclass\nclass MyDataclass:\n    a: int = 0\n    b: str = 'hello'\n    c: bool = True\n\nobj = MyDataclass()\nobj.gui.show()\n

The individual widgets in the Container may be accessed by the same name as the corresponding attribute. For example, obj.gui.a will return the SpinBox widget that controls the value of the a attribute.

"},{"location":"dataclasses/#two-way-data-binding","title":"Two-way data binding","text":"

As you interact programmatically with the obj instance, the widgets in the obj.gui will update. Similarly, as you change the value of the widgets in the obj.gui, the values of the obj instance will be updated.

obj = MyDataclass(a=10)\nobj.b = 'world'\nobj.c = False\n\nobj.gui.show()\n

All magicgui-related stuff is in the gui attribute

The original dataclass instance (obj) is essentially untouched. Just as in a regular dataclass, obj.a returns the current value of a in the dataclass. The widget for the class will be at obj.gui (or whatever name you specified in the gui_name parameter) So, obj.gui.a.value, returns the current value of the widget. Unless you explicitly disconnect the gui from the underlying object/model, the two will always be in sync.

"},{"location":"dataclasses/#adding-buttons-and-callbacks","title":"Adding buttons and callbacks","text":"

Buttons are one of the few widget types that tend not to have an associated value, but simply trigger a callback when clicked. That is: it doesn't often make sense to add a field to a dataclass representing a button. To add a button to a guiclass, decorate a method with the magicgui.experimental.button decorator.

positioning buttons

Currently, all buttons are appended to the end of the widget. The ability to position the button in the layout will be added in the future.

Any additional keyword arguments to the button decorator will be passed to the magicgui.widgets.PushButton constructor (e.g. label, tooltip, etc.)

from magicgui.experimental import guiclass, button\n\n@guiclass\nclass Greeter:\n    first_name: str\n\n    @button\n    def say_hello(self):\n        print(f'Hello {self.first_name}')\n\ngreeter = Greeter('Talley')\ngreeter.gui.show()\n

clicking the \"say_hello\" button will print \"Hello Talley\" to the console

Tip

As your widget begins to manage more internal state, the guiclass pattern becomes much more useful than the magicgui decorator pattern -- which was designed with pure functions that take inputs and return outputs in mind.

"},{"location":"decorators/","title":"magicgui & magic_factory","text":""},{"location":"decorators/#from-object-to-gui","title":"From Object to GUI","text":"

The eponymous feature of magicgui is the magicgui.magicgui function, which converts an object into a widget.

Info

Currently, the only supported objects are functions, but in the future magicgui.magicgui may accept other objects, such as dataclass instances

When used to decorate a function, @magicgui will autogenerate a graphical user interface (GUI) by inspecting the function signature and adding an appropriate GUI widget for each parameter, as described in Type Hints to Widgets. Parameter types are taken from type hints, if provided, or inferred using the type of the default value otherwise.

import math\nfrom enum import Enum\nfrom magicgui import magicgui\n\n# dropdown boxes are best made by creating an enum\nclass Medium(Enum):\n    Glass = 1.520\n    Oil = 1.515\n    Water = 1.333\n    Air = 1.0003\n\n# decorate your function with the @magicgui decorator\n@magicgui(call_button=\"calculate\")\ndef snells_law(aoi=30.0, n1=Medium.Glass, n2=Medium.Water, degrees=True):\n    aoi = math.radians(aoi) if degrees else aoi\n    try:\n        result = math.asin(n1.value * math.sin(aoi) / n2.value)\n        return math.degrees(result) if degrees else result\n    except ValueError:\n        # beyond the critical angle\n        return \"Total internal reflection!\"\n\nsnells_law.show()\n

The object returned by the magicgui decorator is an instance of magicgui.widgets.FunctionGui. It can still be called like the original function, but it also knows how to present itself as a GUI.

"},{"location":"decorators/#two-way-data-binding","title":"Two-Way Data Binding","text":"

The modified snells_law object gains attributes named after each of the parameters in the function. Each attribute is an instance of a magicgui.widgets.Widget subclass (suitable for the data type represented by that parameter). As you make changes in your GUI, the attributes of the snells_law object will be kept in sync. For instance, change the first dropdown menu from \"Glass\" to \"Oil\", and the corresponding n1 object on snells_law will change its value to 1.515:

snells_law.n1.value  # 1.515\n

It goes both ways: set a parameter in the console and it will change in the GUI:

snells_law.aoi.value = 47\nsnells_law.show()\n

"},{"location":"decorators/#its-still-a-function","title":"It's still a function","text":"

magicgui tries very hard to make it so that the decorated object behaves as much like the original object as possible.

We can invoke the function in a few ways:

  • Because we provided the call_button argument to the magicgui decorator, a new button was created that will execute the function with the current gui parameters when clicked.

  • We can call the object just like the original function.

    snells_law()        # 34.7602\nsnells_law(aoi=12)  # 13.7142\n

    Now however, the current values from the GUI will be used as the default values for any arguments that are not explicitly provided to the function.

    snells_law.aoi.value = 12\nsnells_law()  # 13.7142\nsnells_law(aoi=30)  # 34.7602\n

    In essence, your original function now has a \"living\" signature whose defaults change as the user interacts with your GUI.

    import inspect\n\ninspect.signature(snells_law)\n# <MagicSignature(\n#   aoi=12.0, n1=<Medium.Glass: 1.52>, n2=<Medium.Water: 1.333>, degrees=True\n# )>\n# notice how the default `aoi` is now 12 ... because we changed it above\n
  • You can still override positional or keyword arguments in the original function, just as you would with a regular function.

    Note

    calling the function with values that differ from the GUI will not set the values in the GUI... It's just a one-time call.

    # in radians, overriding the value for the second medium (n2)\nsnells_law(0.8, n2=Medium.Air, degrees=False)  # 'Total internal reflection!'\n
"},{"location":"decorators/#connecting-events","title":"Connecting Events","text":""},{"location":"decorators/#function-calls","title":"Function Calls","text":"

With a GUI, you are usually looking for something to happen as a result of calling the function. The function will have a new called attribute that you can connect to an arbitrary callback function:

@snells_law.called.connect\ndef my_callback(value: str):\n    # The callback receives an `Event` object that has the result\n    # of the function call in the `value` attribute\n    print(f\"Your function was called! The result is: {value}\")\n\nresult = snells_law()\n

Now when you call snells_law(), or click the calculate button in the gui, my_callback will be called with the result of the calculation.

"},{"location":"decorators/#parameter-changes","title":"Parameter Changes","text":"

You can also listen for changes on individual function parameters by connecting to the <parameter_name>.changed signal:

# whenever the current value for n1 changes, print it to the console:\n@snells_law.n1.changed.connect\ndef _on_n1_changed(x: Medium):\n    print(f\"n1 was changed to {x}\")\n\nsnells_law.n1.value = Medium.Air\n

Note

This signal will be emitted regardless of whether the parameter was changed in the GUI or via by directly setting the paramaeter on the gui instance.

"},{"location":"decorators/#usage-as-a-decorator-is-optional","title":"Usage As a Decorator is Optional","text":"

Remember: the @decorator syntax is just syntactic sugar. You don't have to use @magicgui to decorate your function declaration. You can also just call it with your function as an argument:

This decorator usage:

@magicgui(auto_call=True)\ndef function():\n    pass\n

is equivalent to this:

def function():\n    pass\n\nfunction = magicgui(function, auto_call=True)\n

In many cases, it will actually be desirable not to use magicgui as a decorator if you don't need a widget immediately, but want to create one later (see also the magic_factory decorator.)

# some time later...\nwidget_instance = magicgui(function)\n
"},{"location":"decorators/#magic_factory","title":"magic_factory","text":"

The magicgui.magic_factory function/decorator acts very much like the magicgui decorator, with one important difference:

Unlike magicgui, magic_factory does not return a widget instance immediately. Instead, it returns a \"factory function\" that can be called to create a widget instance.

This is an important distinction to understand. In most cases, the @magicgui decorator is useful for interactive use or rapid prototyping. But if you are writing a library or package where someone else will be instantiating your widget (a napari plugin is a good example), you will likely want to use magic_factory instead, (or create your own Widget Container subclass).

it's just a partial

If you're familiar with functools.partial, you can think of magic_factory as a partial function application of the magicgui decorator (in fact, magic_factory is a subclass of partial). It is very roughly equivalent to:

def magic_factory(func, *args, **kwargs):\n    return partial(magicgui, func, *args, **kwargs)\n
"},{"location":"decorators/#widget_init","title":"widget_init","text":"

magic_factory gains one additional parameter: widget_init. This accepts a callable that will be called with the new widget instance each time the factory is called. This is a convenient place to add additional initialization or connect events.

from magicgui import magic_factory\n\ndef _on_init(widget):\n    print(\"widget created!\", widget)\n    widget.y.changed.connect(lambda x: print(\"y changed!\", x))\n\n@magic_factory(widget_init=_on_init)\ndef my_factory(x: int, y: str): ...\n\nnew_widget = my_factory()\n
"},{"location":"decorators/#the-lack-of-magic-in-magicgui","title":"The (lack of) \"magic\" in magicgui","text":"

Just to demystify the name a bit, there really isn't a whole lot of \"magic\" in the magicgui decorator. It's really just a thin wrapper around the magicgui.widgets.create_widget function, to create a Container with a sub-widget for each parameter in the function signature.

The widget creation is very roughly equivalent to something like this:

from inspect import signature, Parameter\nfrom magicgui.widgets import create_widget, Container\nfrom magicgui.types import Undefined\n\n\ndef pseudo_magicgui(func: 'Callable'):\n    return Container(\n        widgets=[\n            create_widget(p.default, annotation=p.annotation, name=p.name)\n            for p in signature(func).parameters.values()\n        ]\n    )\n\ndef some_func(x: int = 2, y: str = 'hello'):\n    return x, y\n\nmy_widget = pseudo_magicgui(some_func)\nmy_widget.show()\n

In the case of magicgui, a special subclass of Container (FunctionGui) is used, which additionally adds a __call__ method that allows the widget to behave like the original function.

"},{"location":"events/","title":"Events","text":"

All magicgui widgets emit events when certain properties change. For each event there is a corresponding signal attribute on the widget that can be connected to a callback function. For example, a PushButton emits an event when it is clicked, and all ValueWidget subclasses (like Slider or LineEdit) emit an event when their value changes.

"},{"location":"events/#connecting-to-events","title":"Connecting to events","text":"

To connect a callback to an event, use the connect method of the signal attribute. The exact signals available on each widget are mostly defined in the base classes, and are listed on the API page for each respective widget.

For example, to connect a callback to a LineEdit widget's changed event:

Widget APImagicgui decoratormagic_factory decorator
from magicgui import widgets\n\ntext = widgets.LineEdit(value='type something')\ntext.changed.connect(lambda val: print(f\"Text changed to: {val}\"))\n
from magicgui import magicgui\n\n@magicgui\ndef my_function(text: str):\n    ...\n\nmy_function.text.changed.connect(lambda val: print(f\"Text changed to: {val}\"))\n
from magicgui import magic_factory\n\ndef _on_init(widget):\n    widget.text.changed.connect(lambda val: print(f\"Text changed to: {val}\"))\n\n@magic_factory(widget_init=_on_init)\ndef my_function(text: str):\n    ...\n\nmy_widget = my_function()\n

It's all psygnal under the hood

magicgui uses psygnal for its event system. For greater detail on the connect method and its options, see the Usage section of psygnal's documentation, or the psygnal.SignalInstance.connect API reference.

Tip

Note that connect returns the callable that it was passed, so you can use it as a decorator if you prefer.

text = widgets.LineEdit(value='type something')\n\n# this works\ntext.changed.connect(lambda val: print(f\"Text changed to: {val}\"))\n\n# so does this\n@text.changed.connect\ndef on_text_changed(val):\n    print(f\"Text changed to: {val}\")\n
"},{"location":"installation/","title":"Installation","text":"

magicgui is a pure Python package, and can be installed with pip:

pip install magicgui\n

or with conda:

conda install -c conda-forge magicgui\n
"},{"location":"installation/#backends","title":"Backends","text":"

magicgui requires a backend to be installed in order to function, but it does not specify a particular backend by default. The following backends are available:

  • PyQt5: pip install magicgui[pyqt5]
  • PyQt6: pip install magicgui[pyqt6]
  • PySide2: pip install magicgui[pyside2]
  • PySide6: pip install magicgui[pyside6]
  • Jupyter Widgets: pip install magicgui[jupyter]

Important

Note not all widgets are necessarily implemented for all backends. Most widgets in the widget docs specify which backends are supported.

"},{"location":"installation/#extras","title":"Extras","text":"

The Image widget requires pillow. You may use the image extra:

pip install magicgui[image]\n

The magicgui.tqdm module requires tqdm. You may use the tqdm extra:

pip install magicgui[tqdm]\n

The QuantityEdit widget requires pint. You may use the quantity extra:

pip install magicgui[quantity]\n
"},{"location":"type_map/","title":"Type Hints to Widgets","text":"

One of the key offerings of magicgui is the ability to automatically generate Widgets from Python type hints. This page describes how type hints are mapped to Widgets, and how to customize that mapping.

"},{"location":"type_map/#default-type-mapping","title":"Default Type Mapping","text":"

By default, The following python Type Hint annotations are mapped to the corresponding Widget class, and parametrized with the corresponding kwargs (when applicable):

Type Hint Widget __init__ kwargs bool Slider int Slider float FloatSlider str LineEdit range RangeEdit slice SliceEdit list ListEdit tuple TupleEdit pathlib.Path FileEdit os.PathLike FileEdit Sequence[pathlib.Path] FileEdit {'mode': 'rm'} datetime.time TimeEdit datetime.timedelta TimeEdit datetime.date DateEdit datetime.datetime DateTimeEdit Literal['a', 'b'] ComboBox {'choices': ['a', 'b']} Set[Literal['a', 'b']] Select {'choices': ('a', 'b')} enum.Enum ComboBox {'choices': <enum 'Enum'>} magicgui.widgets.ProgressBar ProgressBar {'bind': <function match_type.<locals>.<lambda> at 0x139b8fec0>, 'visible': True} types.FunctionType FunctionGui {'function': ...} pint.Quantity QuantityEdit"},{"location":"type_map/#example","title":"Example","text":"

from magicgui import widgets\nimport pathlib\nimport os\nimport datetime\nfrom typing import Literal, Set, Sequence\nimport types\nimport pint\nimport enum\n\ntypes = [\n    bool, int, float, str, range, slice, list,\n    pathlib.Path, os.PathLike, Sequence[pathlib.Path],\n    datetime.time, datetime.timedelta, datetime.date, datetime.datetime,\n    Literal['a', 'b'], Set[Literal['a', 'b']], enum.Enum,\n    widgets.ProgressBar, pint.Quantity,\n]\n\nwdg = widgets.Container(\n    widgets=[\n        widgets.create_widget(annotation=t, label=str(t)) for t in types\n    ]\n)\nwdg.show()\n

"},{"location":"type_map/#customizing-widget-options-with-typingannotated","title":"Customizing Widget Options with typing.Annotated","text":"

Widget options and types may be embedded in the type hint itself using typing.Annotated.

Note

This is not the only way to customize the widget type or options in magicgui. Some functions (like magicgui.magicgui) also accept **param_options keyword arguments that map parameter names to dictionaries of widget options.

"},{"location":"type_map/#overriding-the-default-type","title":"Overriding the Default Type","text":"

To override the widget class used for a given object type, use the widget_type key in the Annotated kwargs. It can be either the string name of one of the built-in widgets, or any Widget subclass object.

Type Hint Widget __init__ kwargs Annotated[int, {'widget_type': 'Slider'}] Slider Annotated[float, {'widget_type': 'FloatSlider'}] FloatSlider"},{"location":"type_map/#overriding-the-default-options","title":"Overriding the Default Options","text":"

Any additional kwargs will be passed to the widget constructor (and must be valid for the corresponding widget type).

Type Hint Widget __init__ kwargs Annotated[int, {'step': 10, 'max': 50}] Slider {'step': 10, 'max': 50} Annotated[int, {'choices': [1, 2, 3]}] Slider {'choices': [1, 2, 3]}"},{"location":"type_map/#examples","title":"Examples","text":"

Create a widget using standard type map:

create_widgetmagicgui decoratorguiclass decorator
my_widget = widgets.create_widget(value=42, annotation=int)\n
from magicgui import magicgui\n\n@magicgui\ndef my_widget(x: int = 42):\n    return x\n
from magicgui.experimental import guiclass\n\n@guiclass\nclass MyObject:\n    x: int = 42\n\nobj = MyObject()\nmy_widget = obj.gui\n

Customize a widget using typing.Annotated:

create_widgetmagicgui decoratorguiclass decorator
from typing import Annotated\n\nInt10_50 = Annotated[int, (('widget_type', 'Slider'),('step', 10),('max', 50))]\nwdg2 = widgets.create_widget(value=42, annotation=Int10_50)\n
from magicgui import magicgui\nfrom typing import Annotated\n\nInt10_50 = Annotated[int, (('widget_type', 'Slider'),('step', 10),('max', 50))]\n\n@magicgui\ndef my_widget(x: Int10_50 = 42):\n    ...\n
from magicgui.experimental import guiclass\nfrom typing import Annotated\n\nInt10_50 = Annotated[int, (('widget_type', 'Slider'),('step', 10),('max', 50))]\n\n@guiclass\nclass MyObject:\n    x: Int10_50 = 42\n\nobj = MyObject()\nmy_widget = obj.gui\n

Note that you may also customize widget creation with kwargs to create_widget

from typing import Annotated\nfrom magicgui.widgets import Slider\n\noptions = {'step': 10, 'max': 50}\nwdg3 = widgets.create_widget(value=42, widget_type=Slider, options=options)\nwdg3.show()\n

... or to the magicgui decorator:

@magicgui(x={'widget_type': 'Slider', 'step': 10, 'max': 50})\ndef my_widget(x: int = 42):\n    ...\n\nmy_widget.show()\n

"},{"location":"type_map/#return-type-mapping","title":"Return Type Mapping","text":"

In some cases, magicgui may be able to create a widget for the return annotation of a function.

... more to come ...

"},{"location":"type_map/#postponed-annotations","title":"Postponed annotations","text":"

Using forward references and __future__.annotations with magicgui is possible, but requires some extra care. Read on for more details.

"},{"location":"type_map/#forward-references","title":"Forward References","text":"

When a type hint contains names that have not been defined yet, that definition may be expressed as a string literal, to be resolved later. This is called a Forward Reference (see PEP 484). This is useful when you want to use a type hint that refers to a type that has not yet been defined, or when you want to avoid importing a type that is only used in a type hint.

from typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    from mymodule import MyType\n\ndef my_function(x: 'MyType') -> None:\n    ...\n
"},{"location":"type_map/#__future__annotations","title":"__future__.annotations","text":"

In Python 3.7, the __future__.annotations feature was introduced (PEP 563), which postpones the evaluation of type annotations. The effect of this is that no type annotations will be evaluated at definition time, and all type annotations will be treated as strings (regardless of whether they are enclosed in quotes or not).

from __future__ import annotations\n\nfrom typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    from mymodule import MyType\n\n# no longer necessary to use quotes around 'MyType'\ndef my_function(x: MyType) -> None:\n    ...\n

While this is a useful feature for developers, it does make it significantly more difficult to use those type annotations at runtime.

Magicgui does attempt to resolve forward references it encounters (see Resolving type hints at runtime for gory details), but this is an imperfect process, and may not always work.

"},{"location":"type_map/#if-you-must-use-postponed-annotations","title":"If You Must Use Postponed Annotations","text":"

As a general rule, if you must use forward references or __future__.annotations in a module that uses magicgui, you should:

  • don't use typing syntax that is not valid for ALL python versions you wish to support (e.g. str | int instead of Union[str, int] in python < 3.10), as these will raise an exception when magicgui attempts to evaluate them at runtime.
  • use fully qualified names for all type hints, as these will be easier for magicgui to resolve without user-supplied namespaces.

    from __future__ import annotations\n\nfrom typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    import mymodule\n\n# this is easier for magicgui to resolve\ndef my_function(x: mymodule.MyType) -> None:\n    ...\n
"},{"location":"type_map/#registering-support-for-custom-types","title":"Registering Support for Custom Types","text":"

Any third-party library may use the magicgui.register_type function to register its types with magicgui. When a registered type is used as an annotation, the registered widget will be used.

"},{"location":"type_map/#known-third-party-support-for-magicgui","title":"Known Third-Party Support for magicgui","text":"

Hi developer!

Have a library that registers types with magicgui? Let us know and we'll add it to this list!

"},{"location":"type_map/#napari","title":"napari","text":"

napari has registered a number of its types to provide access to napari-specific objects using type annotations in magicgui. Details may be found in napari's documentation on using magicgui in napari.

"},{"location":"widgets/","title":"Widgets","text":"

Tip

If you're looking for an index of all available widgets, see the Widget Index.

All individual graphical elements in magicgui are \"widgets\", and all widgets are instances of magicgui.widgets.Widget. Widgets may be created directly:

from magicgui.widgets import LineEdit\n\nline_edit = LineEdit(value='hello!')\nline_edit.show()\n

Some widgets (such as magicgui.widgets.Container) are composite widgets that comprise other widgets:

from magicgui.widgets import LineEdit, SpinBox, Container\n\nline_edit = LineEdit(value='hello!')\nspin_box = SpinBox(value=400)\ncontainer = Container(widgets=[line_edit, spin_box])\ncontainer.show()\n

magicgui provides a way to automatically select a widget given a python value or type annotation using magicgui.widgets.create_widget. Here is an example that yields the same result as the one above:

from magicgui.widgets import create_widget\n\nx = 'hello!'\ny = 400\ncontainer = Container(widgets=[create_widget(i) for i in (x, y)])\ncontainer.show()\n

Tip

Because there are often multiple valid widget types for a given python object, you may sometimes wish to create widgets directly, or use the widget_type argument in create_widget()

"},{"location":"widgets/#the-widget-hierarchy","title":"The widget hierarchy","text":"
graph TB\n    A([Widget])-->B([ValueWidget])\n    A-->C([ContainerWidget])\n    B-->D([RangedWidget])\n    B-->E([ButtonWidget])\n    B-->F([CategoricalWidget])\n    C-->H([MainWindowWidget])\n    C-->G([FunctionGui])\n    D-->I([SliderWidget])\n    click A \"#widget\"\n    click B \"#valuewidget\"\n    click C \"#containerwidget\"\n    click D \"#rangedwidget\"\n    click E \"#buttonwidget\"\n    click F \"#categoricalwidget\"\n    click H \"#mainwindowwidget\"\n    click G \"#functiongui\"\n    click I \"#sliderwidget\"

Many widgets present similar types of information in different ways. magicgui tries to maintain a consistent API among all types of widgets that are designed to represent similar objects. The general class of widget you are working with will determine the properties and attributes it has.

Note

The categories shown below are sorted by their base class (such as ValueWidget and RangedWidget). The bases are not intended to be instantiated directly. Instead, you would create the widget type you wanted, such as LineEdit or SpinBox, respectively.

"},{"location":"widgets/#widget","title":"Widget","text":"

As mentioned above, all magicgui widgets derive from magicgui.widgets.Widget and have the following attributes (this list is not comprehensive, see the magicgui.widgets.Widget API):

Attribute Type Description name str The name or \"ID\" of this widget (such as a function parameter name to which this widget corresponds). annotation Any A type annotation for the value represented by the widget. label str A string to use for an associated Label widget (if this widget is being shown in a magicgui.widgets.Container widget, and container.labels is True). By default, name will be used. Note: name refers the name of the parameter, as might be used in a signature, whereas label is just the label for that widget in the GUI. tooltip str A tooltip to display when hovering over the widget. visible bool Whether the widget is visible."},{"location":"widgets/#valuewidget","title":"ValueWidget","text":"

In addition to the base Widget properties mentioned above, the following ValueWidgets track some value:

Widget Description Label A non-editable text display. LineEdit A one-line text editor. LiteralEvalLineEdit A one-line text editor that evaluates strings as python literals. Password A one-line text editor that obscures input. TextEdit A widget to edit and display both plain and rich text. FileEdit A LineEdit widget with a button that opens a FileDialog. RangeEdit A widget to represent a python range object, with start/stop/step. SliceEdit A widget to represent slice objects, with start/stop/step. DateTimeEdit A widget for editing dates and times. DateEdit A widget for editing dates. TimeEdit A widget for editing times. Table A widget to represent columnar or 2D data with headers. QuantityEdit A combined LineEdit and ComboBox to edit a pint.Quantity. Attribute Type Description value Any The current value of the widget. changed psygnal.SignalInstance A psygnal.SignalInstance that will emit an event when the value has changed. Connect callbacks to the change event using widget.changed.connect(callback) bind Any, optional A value or callback to bind this widget. If bound, whenever widget.value is accessed, the value provided here will be returned. The bound value can be a callable, in which case bound_value(self) will be returned (i.e. your callback must accept a single parameter, which is this widget instance.). see ValueWidget.bind for details.

Here is a demonstration of all these:

from magicgui import widgets\nimport datetime\n\nwdg_list = [\n    widgets.Label(value=\"label value\", label=\"Label:\"),\n    widgets.LineEdit(value=\"line edit value\", label=\"LineEdit:\"),\n    widgets.Password(value=\"super-secret!\", label=\"Password:\"),\n    widgets.TextEdit(value=\"text edit value...\", label=\"TextEdit:\"),\n    widgets.FileEdit(value=\"/home\", label=\"FileEdit:\"),\n    widgets.RangeEdit(value=range(0, 10, 2), label=\"RangeEdit:\"),\n    widgets.SliceEdit(value=slice(0, 10, 2), label=\"SliceEdit:\"),\n    widgets.DateTimeEdit(\n      value=datetime.datetime(1999, 12, 31, 11, 30), label=\"DateTimeEdit:\"\n    ),\n    widgets.DateEdit(value=datetime.date(81, 2, 18), label=\"DateEdit:\"),\n    widgets.TimeEdit(value=datetime.time(12, 20), label=\"TimeEdit:\"),\n    widgets.QuantityEdit(value='12 seconds', label=\"Quantity:\")\n]\ncontainer = widgets.Container(widgets=wdg_list)\ncontainer.max_height = 300\ncontainer.show()\n

"},{"location":"widgets/#rangedwidget","title":"RangedWidget","text":"

RangedWidgets are numerical ValueWidgets that have a restricted range of valid values, and a step size. RangedWidgets include:

Widget Description SpinBox A widget to edit an integer with clickable up/down arrows. FloatSpinBox A widget to edit a float with clickable up/down arrows.

In addition to all of the ValueWidget attributes, RangedWidget attributes include:

Attribute Type Description min float The minimum allowable value, by default 0 max float The maximum allowable value, by default 1000 step float The step size for incrementing the value, by default 1 range tuple of float A convenience attribute for getting/setting the (min, max) simultaneously

w1 = widgets.SpinBox(value=10, max=20, label='SpinBox:')\nw2 = widgets.FloatSpinBox(value=380, step=0.5, label='FloatSpinBox:')\ncontainer = widgets.Container(widgets=[w1, w2])\ncontainer.show()\n

"},{"location":"widgets/#sliderwidget","title":"SliderWidget","text":"

SliderWidgets are special RangedWidgets that additionally have an orientation, and a readout.

Widget Description Slider A slider widget to adjust an integer value within a range. FloatSlider A slider widget to adjust an integer value within a range. LogSlider A slider widget to adjust a numerical value logarithmically within a range. ProgressBar A progress bar widget.

In addition to all of the RangedWidget attributes, SliderWidget attributes include:

Attribute Type Description orientation str The orientation for the slider. Must be either 'horizontal' or 'vertical'. by default 'horizontal' readout bool Whether to show the value of the slider. By default, True.

w1 = widgets.Slider(value=10, max=25, label='Slider:')\nw2 = widgets.FloatSlider(value=10.5, max=18.5, label='FloatSlider:')\nw3 = widgets.ProgressBar(value=80, max=100, label='ProgressBar:')\ncontainer = widgets.Container(widgets=[w1, w2, w3])\ncontainer.show()\n

"},{"location":"widgets/#buttonwidget","title":"ButtonWidget","text":"

ButtonWidgets are boolean ValueWidgets that also have some text associated with them.

Widget Description PushButton A clickable command button. CheckBox A checkbox with a text label.

In addition to all of the ValueWidget attributes, ButtonWidget attributes include:

Attribute Type Description text str The text to display on the button. If not provided, will use name.

w1 = widgets.PushButton(value=True, text='PushButton Text')\nw2 = widgets.CheckBox(value=False, text='CheckBox Text')\ncontainer = widgets.Container(widgets=[w1, w2])\ncontainer.show()\n

"},{"location":"widgets/#categoricalwidget","title":"CategoricalWidget","text":"

CategoricalWidget are ValueWidgets that provide a set of valid choices. They can be created from:

  • an enum.Enum
  • an iterable of objects (or an iterable of 2-tuples (name, object))
  • a callable that returns an enum.Enum or an iterable
  • a typing.Literal annotation.
Widget Description ComboBox A dropdown menu, allowing selection between multiple choices. RadioButtons An exclusive group of radio buttons, providing a choice from multiple choices. Select A list of options, allowing selection between multiple choices.

In addition to all of the ValueWidget attributes, CategoricalWidget attributes include:

Attribute Type Description choices Enum, Iterable, or Callable Available choices displayed in the widget. value Any In the case of a CategoricalWidget the value is the data of the currently selected choice (see also: current_choice below). current_choice str The name associated with the current choice. For instance, if choices was provided as choices=[('one', 1), ('two', 2)], then an example value would be 1, and an example current_choice would be 'one'.

choices = ['one', 'two', 'three']\nw1 = widgets.ComboBox(choices=choices, value='two', label='ComboBox:')\nw2 = widgets.RadioButtons(choices=choices, label='RadioButtons:')\nw3 = widgets.Select(choices=choices, label='Select:')\ncontainer = widgets.Container(widgets=[w1, w2, w3])\ncontainer.max_height = 220\ncontainer.show()\n

"},{"location":"widgets/#containerwidget","title":"ContainerWidget","text":"

A ContainerWidget is a list-like Widget that can contain other widgets. Containers allow you to build more complex widgets from sub-widgets. A notable example of a Container is magicgui.widgets.FunctionGui) (the product of the @magicgui decorator).

Widget Description Container A Widget to contain other widgets. MainWindow A Widget to contain other widgets, includes a menu bar. FunctionGui Wrapper for a container of widgets representing a callable object. Attribute Type Description layout str The layout for the container. Must be either 'horizontal' or 'vertical'. widgets Sequence[Widget] The widgets that the container contains. labels bool Whether each widget should be shown with a corresponding Label widget to the left. Note: the text for each widget defaults to widget.name, but can be overridden by setting widget.label.

Container implements the full collections.abc.MutableSequence interface. You can add and remove widgets from it just as you would add or remove items from a list.

from magicgui.widgets import Container, Slider, FloatSlider, ProgressBar\n\ncontainer = widgets.Container()\ncontainer.append(widgets.LineEdit(value='Mookie', label='Your Name:'))\ncontainer.append(widgets.FloatSlider(value=10.5, label='FloatSlider:'))\ncontainer.show()\n

"},{"location":"widgets/#mainwindowwidget","title":"MainWindowWidget","text":"

A MainWindowWidget is a special type of ContainerWidget that also includes a menu bar.

"},{"location":"widgets/#functiongui","title":"FunctionGui","text":"

A FunctionGui is a special type of ContainerWidget that is created from a function. It is the product of the @magicgui decorator. It is a container that contains a widget for each of the parameters in the function. See magicgui.widgets.FunctionGui for details.

"},{"location":"widgets/#magicgui","title":"@magicgui","text":"

It's worth noting that @magicgui and @magic_factory decorators are just conveniences that build a special type of Container widget (a FunctionGui), with a widget representing each of the parameters in a decorated function.

from magicgui import magicgui\n\n@magicgui\ndef my_function(x='hello', y=400): ...\n\nmy_function.show()\n

In terms of simply building widgets, the following code performs a similar task to @magicgui.

from inspect import signature\n\ndef my_function(x='hello', y=400):\n  ...\n\nparams = signature(my_function).parameters.values()\ncontainer = Container(\n    widgets=[create_widget(p.default, name=p.name) for p in params]\n)\ncontainer.show()\n

Tip

Note that the FunctionGui widget produced by @magicgui is actually a callable object that behaves very much like the original function, except that it will use current values from the GUI as default parameters when calling the function.

"},{"location":"api/app/","title":"Application","text":""},{"location":"api/app/#magicgui.application.Application","title":"magicgui.application.Application","text":"

Magicgui Application, wrapping a native BaseApplicationBackend implementation.

"},{"location":"api/app/#magicgui.application.Application.backend_module","title":"backend_module: ModuleType property","text":"

Return module object that defines the backend.

"},{"location":"api/app/#magicgui.application.Application.backend_name","title":"backend_name: str property","text":"

Return name of the GUI backend that this app wraps.

"},{"location":"api/app/#magicgui.application.Application.native","title":"native: Any property","text":"

Return the native GUI application instance.

"},{"location":"api/app/#magicgui.application.Application.__enter__","title":"__enter__() -> Application","text":"

Context manager to start this application.

"},{"location":"api/app/#magicgui.application.Application.__exit__","title":"__exit__(*exc_details: Any) -> None","text":"

Exit context manager for this application.

"},{"location":"api/app/#magicgui.application.Application.__repr__","title":"__repr__() -> str","text":"

Return repr for this instance.

"},{"location":"api/app/#magicgui.application.Application.create","title":"create() -> None","text":"

Create the native application.

"},{"location":"api/app/#magicgui.application.Application.get_obj","title":"get_obj(name: str) -> Any","text":"

Get the backend object for the given name (such as a widget).

"},{"location":"api/app/#magicgui.application.Application.process_events","title":"process_events() -> None","text":"

Process all pending GUI events.

"},{"location":"api/app/#magicgui.application.Application.quit","title":"quit() -> None","text":"

Quit the native GUI event loop.

"},{"location":"api/app/#magicgui.application.Application.run","title":"run() -> None","text":"

Enter the native GUI event loop.

"},{"location":"api/app/#magicgui.application.Application.start_timer","title":"start_timer(interval: int = 1000, on_timeout: Callable[[], None] | None = None, single_shot: bool = False) -> None","text":"

Start a timer with a given interval, optional callback, and single_shot.

"},{"location":"api/app/#magicgui.application.use_app","title":"magicgui.application.use_app(app: AppRef | None = None) -> Application","text":"

Get/create the default Application object. See _use_app docstring.

"},{"location":"api/experimental/","title":"magicgui.experimental","text":"

Experimental

This module contains experimental features that are not yet ready for prime time. All of the features in this module are subject to change without warning or deprecation.

"},{"location":"api/experimental/#magicgui.experimental.guiclass","title":"magicgui.experimental.guiclass(cls: T | None = None, *, gui_name: str = 'gui', events_namespace: str = 'events', follow_changes: bool = True, **dataclass_kwargs: Any) -> T | Callable[[T], T]","text":"

Turn class into a dataclass with a property (gui_name) that returns a gui.

This decorator is similar to dataclasses.dataclass, but it will also add an events attribute to the class that is an instance of psygnal.SignalGroup (with a signal for each field in the dataclass; see https://psygnal.readthedocs.io/en/latest/dataclasses/ for details), and a gui property that returns a magicgui widget, bound to the values of the dataclass instance.

Note

This decorator is compatible with dataclasses using slots=True, however, there is a potential for a memory leak that the user should be aware of. If you create a guiclass instance, and then store a reference to its gui, and then delete the instance, the gui will still be bound to the instance, preventing it from being garbage collected. To avoid this, you can call unbind_gui_from_instance(gui, instance) before deleting the instance.

Parameters:

  • cls (type, default: None ) \u2013

    The class to turn into a dataclass.

  • gui_name (str, default: 'gui' ) \u2013

    The name of the property that will return a magicgui widget, by default \"gui\"

  • events_namespace (str, default: 'events' ) \u2013

    The name of the attribute that will be added to the class, by default \"events\". This attribute will be an instance of psygnal.SignalGroup that will be used to connect events to the class.

  • follow_changes (bool, default: True ) \u2013

    If True (default), changes to the dataclass instance will be reflected in the gui, and changes to the gui will be reflected in the dataclass instance.

  • dataclass_kwargs (dict, default: {} ) \u2013

    Additional keyword arguments to pass to dataclasses.dataclass.

Returns:

  • type \u2013

    The dataclass.

Examples:

>>> @guiclass\n... class MyData:\n...     x: int = 0\n...     y: str = 'hi'\n...\n...     @button\n...     def reset(self):\n...         self.x = 0\n...         self.y = 'hi'\n...\n>>> data = MyData()\n>>> data.gui.show()\n
"},{"location":"api/experimental/#magicgui.experimental.button","title":"magicgui.experimental.button(func: F | None = None, **button_kwargs: Any) -> F | Callable[[F], F]","text":"

Add a method as a button to a guiclass, which calls the decorated method.

Parameters:

  • func (callable, default: None ) \u2013

    The method to decorate. If None, returns a decorator that can be applied to a method.

  • button_kwargs (dict, default: {} ) \u2013

    Additional keyword arguments to pass to magicgui.widgets.PushButton.

"},{"location":"api/experimental/#magicgui.experimental.is_guiclass","title":"magicgui.experimental.is_guiclass(obj: object) -> TypeGuard[GuiClassProtocol]","text":"

Return True if obj is a guiclass or an instance of a guiclass.

"},{"location":"api/magic_factory/","title":"magicgui.magic_factory","text":""},{"location":"api/magic_factory/#magicgui.magic_factory","title":"magicgui.magic_factory(function=None, *, layout='vertical', scrollable=False, labels=True, tooltips=True, call_button=None, auto_call=False, result_widget=False, main_window=False, app=None, persist=False, widget_init=None, raise_on_unknown=False, **param_options)","text":"

Return a MagicFactory for function.

magic_factory is nearly identical to the magicgui decorator with the following differences:

  1. Whereas magicgui returns a FunctionGui instance, magic_factory returns a callable that returns a FunctionGui instance. (Technically, it returns an instance of MagicFactory which you behaves exactly like a functools.partial for a FunctionGui instance.)
  2. magic_factory adds a widget_init method: a callable that will be called immediately after the FunctionGui instance is created. This can be used to add additional widgets to the layout, or to connect signals to the widgets.

Important

Whereas decorating a function with magicgui will immediately create a widget instance, magic_factory will not create a widget instance until the decorated object is called. This is often what you want in a library, whereas magicgui is useful for rapid, interactive development.

Parameters:

  • function (Callable, default: None ) \u2013

    The function to decorate. Optional to allow bare decorator with optional arguments. by default None

  • layout (str, default: 'vertical' ) \u2013

    The type of layout to use. Must be horizontal or vertical by default \"vertical\".

  • scrollable (bool, default: False ) \u2013

    Whether to enable scroll bars or not. If enabled, scroll bars will only appear along the layout direction, not in both directions.

  • labels (bool, default: True ) \u2013

    Whether labels are shown in the widget. by default True

  • tooltips (bool, default: True ) \u2013

    Whether tooltips are shown when hovering over widgets. by default True

  • call_button (bool or str, default: None ) \u2013

    If True, create an additional button that calls the original function when clicked. If a str, set the button text. If None (the default), it defaults to True when auto_call is False, and False otherwise.

  • auto_call (bool, default: False ) \u2013

    If True, changing any parameter in either the GUI or the widget attributes will call the original function with the current settings. by default False

  • result_widget (bool, default: False ) \u2013

    Whether to display a LineEdit widget the output of the function when called, by default False

  • main_window (bool, default: False ) \u2013

    Whether this widget should be treated as the main app window, with menu bar, by default False.

  • app (Application or str, default: None ) \u2013

    A backend to use, by default None (use the default backend.)

  • persist (bool, default: False ) \u2013

    If True, when parameter values change in the widget, they will be stored to disk and restored when the widget is loaded again with persist = True. Call magicgui._util.user_cache_dir() to get the default cache location. By default False.

  • widget_init (callable, default: None ) \u2013

    A function that will be called with the newly created widget instance as its only argument. This can be used to customize the widget after it is created. by default None.

  • raise_on_unknown (bool, default: False ) \u2013

    If True, raise an error if magicgui cannot determine widget for function argument or return type. If False, ignore unknown types. By default False.

  • param_options (dict of dict, default: {} ) \u2013

    Any additional keyword arguments will be used as parameter-specific widget options. Keywords must match the name of one of the arguments in the function signature, and the value must be a dict of keyword arguments to pass to the widget constructor.

Returns:

  • result ( MagicFactory or Callable[[F], MagicFactory] ) \u2013

    If function is not None (such as when this is used as a bare decorator), returns a MagicFactory instance. If function is None such as when arguments are provided like magic_factory(auto_call=True), then returns a function that can be used as a decorator.

Examples:

>>> @magic_factory\n... def my_function(a: int = 1, b: str = 'hello'):\n...     pass\n...\n>>> my_widget = my_function()\n>>> my_widget.show()\n>>> my_widget.a.value == 1  # True\n>>> my_widget.b.value = 'world'\n
"},{"location":"api/magic_factory/#magicgui.type_map._magicgui.MagicFactory","title":"magicgui.type_map._magicgui.MagicFactory","text":"

Bases: partial, Generic[_FGuiVar]

Factory function that returns a FunctionGui instance.

While this can be used directly, (see example below) the preferred usage is via the magicgui.magic_factory decorator.

Examples:

>>> def func(x: int, y: str):\n...     pass\n...\n>>> factory = MagicFactory(function=func, labels=False)\n>>> # factory accepts all the same arguments as magicgui()\n>>> widget1 = factory(call_button=True)\n>>> # can also override magic_kwargs that were provided when creating the factory\n>>> widget2 = factory(auto_call=True, labels=True)\n
"},{"location":"api/magic_factory/#magicgui.type_map._magicgui.MagicFactory.__name__","title":"__name__: str property","text":"

Pass function name.

"},{"location":"api/magic_factory/#magicgui.type_map._magicgui.MagicFactory.__call__","title":"__call__(*args, **kwargs)","text":"

Call the wrapped _magicgui and return a FunctionGui.

"},{"location":"api/magic_factory/#magicgui.type_map._magicgui.MagicFactory.__getattr__","title":"__getattr__(name)","text":"

Allow accessing FunctionGui attributes without mypy error.

"},{"location":"api/magic_factory/#magicgui.type_map._magicgui.MagicFactory.__new__","title":"__new__(function, *args, magic_class=FunctionGui, widget_init=None, **keywords)","text":"

Create new MagicFactory.

"},{"location":"api/magic_factory/#magicgui.type_map._magicgui.MagicFactory.__repr__","title":"__repr__()","text":"

Return string repr.

"},{"location":"api/magicgui/","title":"magicgui.magicgui","text":""},{"location":"api/magicgui/#magicgui.magicgui","title":"magicgui.magicgui(function=None, *, layout='vertical', scrollable=False, labels=True, tooltips=True, call_button=None, auto_call=False, result_widget=False, main_window=False, app=None, persist=False, raise_on_unknown=False, **param_options)","text":"

Return a FunctionGui for function.

Parameters:

  • function (Callable, default: None ) \u2013

    The function to decorate. Optional to allow bare decorator with optional arguments. by default None

  • layout (str, default: 'vertical' ) \u2013

    The type of layout to use. Must be horizontal or vertical by default \"vertical\".

  • scrollable (bool, default: False ) \u2013

    Whether to enable scroll bars or not. If enabled, scroll bars will only appear along the layout direction, not in both directions.

  • labels (bool, default: True ) \u2013

    Whether labels are shown in the widget. by default True

  • tooltips (bool, default: True ) \u2013

    Whether tooltips are shown when hovering over widgets. by default True

  • call_button (bool or str, default: None ) \u2013

    If True, create an additional button that calls the original function when clicked. If a str, set the button text. If None (the default), it defaults to True when auto_call is False, and False otherwise.

  • auto_call (bool, default: False ) \u2013

    If True, changing any parameter in either the GUI or the widget attributes will call the original function with the current settings. by default False

  • result_widget (bool, default: False ) \u2013

    Whether to display a LineEdit widget the output of the function when called, by default False

  • main_window (bool, default: False ) \u2013

    Whether this widget should be treated as the main app window, with menu bar, by default False.

  • app (Application or str, default: None ) \u2013

    A backend to use, by default None (use the default backend.)

  • persist (bool, default: False ) \u2013

    If True, when parameter values change in the widget, they will be stored to disk and restored when the widget is loaded again with persist = True. Call magicgui._util.user_cache_dir() to get the default cache location. By default False.

  • raise_on_unknown (bool, default: False ) \u2013

    If True, raise an error if magicgui cannot determine widget for function argument or return type. If False, ignore unknown types. By default False.

  • param_options (dict[str, dict], default: {} ) \u2013

    Any additional keyword arguments will be used as parameter-specific options. Keywords must match the name of one of the arguments in the function signature, and the value must be a dict of keyword arguments to pass to the widget constructor.

Returns:

  • result ( FunctionGui or Callable[[F], FunctionGui] ) \u2013

    If function is not None (such as when this is used as a bare decorator), returns a FunctionGui instance, which is a list-like container of autogenerated widgets corresponding to each parameter in the function. If function is None such as when arguments are provided like magicgui(auto_call=True), then returns a function that can be used as a decorator.

Examples:

>>> @magicgui\n... def my_function(a: int = 1, b: str = 'hello'):\n...     pass\n...\n>>> my_function.show()\n>>> my_function.a.value == 1  # True\n>>> my_function.b.value = 'world'\n
"},{"location":"api/migration/","title":"migration guide","text":""},{"location":"api/migration/#v030-migration-guide","title":"v0.3.0 migration guide","text":"

October, 2021

Version 0.3.0 of magicgui introduced some changes to the events and callbacks API. See https://github.com/pyapp-kit/magicgui/pull/253 for details

"},{"location":"api/migration/#callbacks-now-receive-the-value-directly-instead-of-an-event-object","title":"Callbacks now receive the value directly, instead of an Event object","text":"

magicgui 0.3.0 is now using psygnal as its event/callback handler.

Callbacks connected to widget.changed (and other event emitters) may now receive the value(s) directly, instead of an event object:

\ud83d\udc4e Old Method (< v0.3.0)
@widget.changed.connect\ndef my_callback(event):\n    # event was an `Event` object with a `value` attribute\n    new_value = event.value\n

Existing code using callbacks with a single positional argument will continue to receive a single Event object (and a warning will be shown, until v0.4.0 where it will become an error).

To silence the warning and opt in to the new pattern of receiving value directly, you can do one of two things:

  1. type hint your single positional argument as anything other than magicgui.events.Event
  2. provide a callback that takes no arguments
\ud83d\udc4d New Method (>= v0.3.0)
@widget.changed.connect\ndef my_callback(new_value: int):\n    ...  # use new_value directly\n\n# or, if you don't need to use new_value\n@widget.changed.connect\ndef my_callback():\n    # something that didn't need the value\n    ...\n
"},{"location":"api/migration/#event-emitters-take-no-keyword-arguments","title":"Event emitters take no keyword arguments","text":"

For the few packages who were manually emitting change events, you should no longer provide the value= keyword when emitting.

\ud83d\udc4e Old Method (< v0.3.0)
widget.changed(value='whatever')\n
\ud83d\udc4d New Method (>= v0.3.0)
widget.changed.emit('whatever')\n# OR (if you prefer the direct __call__ syntax)\nwidget.changed('whatever')\n
"},{"location":"api/migration/#v020-migration-guide","title":"v0.2.0 migration guide","text":"

December, 2020

Version 0.2.0 of magicgui was a complete rewrite that introduced a couple breaking API changes

"},{"location":"api/migration/#gui-attribute-removed","title":".Gui() attribute removed","text":"

Before v0.2.0, the magicgui.magicgui decorator added a Gui attribute to the decorated function that was to be called to instantiate a widget. In v0.2.0 the object returned from the magicgui.magicgui decorator is already an instantiated magicgui.widgets.Widget.

\ud83d\udc4e Old Method (< v0.2.0)
from magicgui import magicgui, event_loop\n\n@magicgui\ndef function(x, y):\n    ...\n\nwith event_loop():\n    gui = function.Gui(show=True)\n
\ud83d\udc4d New Method (>= v0.2.0)
from magicgui import magicgui\n\n@magicgui\ndef function(x, y):\n    ...\n\nfunction.show(run=True)\n
"},{"location":"api/migration/#new-base-widget-type","title":"New base widget type","text":"

Before v0.2.0, the Gui() object returned by the magicgui.magicgui decorator was a MagicGuiBase widget class, which in turn was a direct subclass of a backend widget, such as a QtWidgets.QWidget. In v0.2.0, all widgets derive from [magicgui.widgets.Widget``][magicgui.widgets.Widget], and the *backend* is available atwidget.native. If you are incorporating magicgui widgets into a larger Qt-based GUI, please note that you will want to usewidget.nativeinstead ofwidget`

from magicgui import magicgui, use_app\n\nuse_app('qt')\n\n@magicgui\ndef function(x, y):\n    ...\n
>>> print(type(function))\n<class 'magicgui.widgets.FunctionGui'>\n>>> print(type(function.native))\n<class 'PyQt5.QtWidgets.QWidget'>\n
"},{"location":"api/migration/#starting-the-application","title":"Starting the application","text":"

It is now easier to show a widget and start an application by calling widget.show(run=True). Calling show(run=True) will immediately block execution of your script and show the widget. If you wanted to (for instance) show multiple widgets next to each other, then you would still want to use the event_loop context manager:

from magicgui import magicgui, event_loop\n\n@magicgui\ndef function_a(x=1, y=3):\n    ...\n\n@magicgui\ndef function_b(z='asdf'):\n    ...\n\nwith event_loop():\n    function_a.show()\n    function_b.show()\n# both widgets will show (though b may be on top of a)\n
"},{"location":"api/migration/#getting-and-setting-values","title":"Getting and setting values","text":"

To get or set the value of a widget programmatically, you no longer set the corresponding widget attribute directly, but rather use the widget.value attribute:

Old Method \ud83d\udc4e

gui.x used to be a descriptor object to get/set the value, but the actual underlying widget was at gui.x_widget

gui = function.Gui()\ngui.x = 10\n

New Method \ud83d\udc4d

now function.x IS the widget, and you set its value with function.x.value

function.x.value = 10\n
"},{"location":"api/migration/#connecting-callbacks-to-events","title":"Connecting callbacks to events","text":"

When binding callbacks to change events, you no longer connect to gui.<name>_changed, you now connect to function.<name>.changed:

\ud83d\udc4e Old Method (< v0.2.0)
gui = function.Gui()\ngui.x_changed.connect(my_callback)\n
\ud83d\udc4d New Method (>= v0.2.0)
function.x.changed.connect(my_callback)\n
"},{"location":"api/migration/#renamed","title":"Renamed","text":"
  • Widget.refresh_choices has been renamed to Widget.reset_choices.

  • @magicgui(result=True) has been renamed to @magicgui(result_widget=True)

"},{"location":"api/protocols/","title":"Backend Protocols","text":"

Advanced Topic

Most users of magicgui will not need to worry about this section.

These Protocol classes declare the interface that backend adapters must implement in order to be used by magicgui. All magicgui Widget objects compose a backend widget implementing one of these protocols, and control it using the methods defined herein.

magicgui developers may be interested in this page, but end-users needn't worry about it.

"},{"location":"api/protocols/#summary","title":"Summary","text":"Widget Description WidgetProtocol Base Widget Protocol: specifies methods that all widgets must provide. ValueWidgetProtocol Widget that has a current value, with getter/setter and on_change callback. ButtonWidgetProtocol The \"value\" in a ButtonWidget is the current (checked) state. TableWidgetProtocol ValueWidget subclass intended for 2D tabular data, with row & column headers. RangedWidgetProtocol Value widget that supports numbers within a provided min/max range. CategoricalWidgetProtocol Categorical widget, that has a set of valid choices, and a current value. SliderWidgetProtocol Protocol for implementing a slider widget. ContainerProtocol Widget that can contain other widgets. BaseApplicationBackend Backend Application object. DialogProtocol Protocol for modal (blocking) containers. SupportsChoices Widget that has a set of valid choices. SupportsOrientation Widget that can be reoriented. SupportsText Widget that have text (in addition to value)... like buttons. SupportsReadOnly Widget that can be read_only."},{"location":"api/protocols/#protocol-inheritance","title":"Protocol Inheritance","text":"

The visual hierarchy of protocols looks like this:

graph LR\n    A([WidgetProtocol])-->B([ValueWidgetProtocol])\n    A-->C([ContainerProtocol])\n    M([SupportsText])-->E\n    B-->E([ButtonWidgetProtocol])\n    B-->D([RangedWidgetProtocol])\n    B-->F([CategoricalWidgetProtocol])\n    D-->I([SliderWidgetProtocol])\n    B-->J([TableWidgetProtocol])\n    K([SupportsReadOnly])-->J([TableWidgetProtocol])\n    L([SupportsChoices])-->F\n    N([SupportsOrientation])-->C\n    N-->I\n    C-->O([DialogProtocol])\n    C-->P([MainWindowProtocol])\n\n    click A \"#magicgui.widgets.protocols.WidgetProtocol\"\n    click B \"#magicgui.widgets.protocols.ValueWidgetProtocol\"\n    click C \"#magicgui.widgets.protocols.ContainerProtocol\"\n    click D \"#magicgui.widgets.protocols.RangedWidgetProtocol\"\n    click E \"#magicgui.widgets.protocols.ButtonWidgetProtocol\"\n    click F \"#magicgui.widgets.protocols.CategoricalWidgetProtocol\"\n    click I \"#magicgui.widgets.protocols.SliderWidgetProtocol\"\n    click J \"#magicgui.widgets.protocols.TableWidgetProtocol\"\n    click K \"#magicgui.widgets.protocols.SupportsReadOnly\"\n    click L \"#magicgui.widgets.protocols.SupportsChoices\"\n    click M \"#magicgui.widgets.protocols.SupportsText\"\n    click N \"#magicgui.widgets.protocols.SupportsOrientation\"\n    click O \"#magicgui.widgets.protocols.DialogProtocol\"\n    click P \"#magicgui.widgets.protocols.MainWindowProtocol\"
"},{"location":"api/protocols/#widget-protocols","title":"Widget Protocols","text":""},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol","title":"magicgui.widgets.protocols.WidgetProtocol","text":"

Bases: Protocol

Base Widget Protocol: specifies methods that all widgets must provide.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_bind_parent_change_callback","title":"_mgui_bind_parent_change_callback(callback: Callable[[Any], None]) -> None abstractmethod","text":"

Bind callback to parent change event.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_close_widget","title":"_mgui_close_widget() -> None abstractmethod","text":"

Close widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_enabled","title":"_mgui_get_enabled() -> bool abstractmethod","text":"

Get the enabled state of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_height","title":"_mgui_get_height() -> int abstractmethod","text":"

Get the height of the widget.

The intention is to get the height of the widget after it is shown, for the purpose of unifying widget height in a layout. Backends may do what they need to accomplish this. For example, Qt can use sizeHint().height(), since height() may return something large if the widget has not yet been painted on screen.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_max_height","title":"_mgui_get_max_height() -> int abstractmethod","text":"

Get the maximum height of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_max_width","title":"_mgui_get_max_width() -> int abstractmethod","text":"

Get the maximum width of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_min_height","title":"_mgui_get_min_height() -> int abstractmethod","text":"

Get the minimum height of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_min_width","title":"_mgui_get_min_width() -> int abstractmethod","text":"

Get the minimum width of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_native_widget","title":"_mgui_get_native_widget() -> Any abstractmethod","text":"

Return the native backend widget instance.

This is generally the widget that has the layout.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_parent","title":"_mgui_get_parent() -> Widget abstractmethod","text":"

Return the parent widget of this widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_root_native_widget","title":"_mgui_get_root_native_widget() -> Any abstractmethod","text":"

Return the root native backend widget.

In most cases, this is the same as _mgui_get_native_widget. However, in cases where the native widget is in a scroll layout, this might be different.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_tooltip","title":"_mgui_get_tooltip() -> str abstractmethod","text":"

Get the tooltip for this widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_visible","title":"_mgui_get_visible() -> bool abstractmethod","text":"

Get widget visibility.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_get_width","title":"_mgui_get_width() -> int abstractmethod","text":"

Get the width of the widget.

The intention is to get the width of the widget after it is shown, for the purpose of unifying widget width in a layout. Backends may do what they need to accomplish this. For example, Qt can use sizeHint().width(), since width() may return something large if the widget has not yet been painted on screen.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_render","title":"_mgui_render() -> np.ndarray abstractmethod","text":"

Return an RGBA (MxNx4) numpy array bitmap of the rendered widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_set_enabled","title":"_mgui_set_enabled(enabled: bool) -> None abstractmethod","text":"

Set the enabled state of the widget to enabled.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_set_height","title":"_mgui_set_height(value: int) -> None abstractmethod","text":"

Set the height of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_set_max_height","title":"_mgui_set_max_height(value: int) -> None abstractmethod","text":"

Set the maximum height of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_set_max_width","title":"_mgui_set_max_width(value: int) -> None abstractmethod","text":"

Set the maximum width of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_set_min_height","title":"_mgui_set_min_height(value: int) -> None abstractmethod","text":"

Set the minimum height of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_set_min_width","title":"_mgui_set_min_width(value: int) -> None abstractmethod","text":"

Set the minimum width of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_set_parent","title":"_mgui_set_parent(widget: Widget) -> None abstractmethod","text":"

Set the parent widget of this widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_set_tooltip","title":"_mgui_set_tooltip(value: str | None) -> None abstractmethod","text":"

Set a tooltip for this widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_set_visible","title":"_mgui_set_visible(value: bool) -> None abstractmethod","text":"

Set widget visibility.

"},{"location":"api/protocols/#magicgui.widgets.protocols.WidgetProtocol._mgui_set_width","title":"_mgui_set_width(value: int) -> None abstractmethod","text":"

Set the width of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.ValueWidgetProtocol","title":"magicgui.widgets.protocols.ValueWidgetProtocol","text":"

Bases: WidgetProtocol, Protocol

Widget that has a current value, with getter/setter and on_change callback.

It is worth noting that the widget is the thing that has a value. Magicgui does not maintain & synchronize an independent model.

"},{"location":"api/protocols/#magicgui.widgets.protocols.ValueWidgetProtocol._mgui_bind_change_callback","title":"_mgui_bind_change_callback(callback: Callable[[Any], Any]) -> None abstractmethod","text":"

Bind callback to value change event.

"},{"location":"api/protocols/#magicgui.widgets.protocols.ValueWidgetProtocol._mgui_get_value","title":"_mgui_get_value() -> Any abstractmethod","text":"

Get current value of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.ValueWidgetProtocol._mgui_set_value","title":"_mgui_set_value(value: Any) -> None abstractmethod","text":"

Set current value of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.ButtonWidgetProtocol","title":"magicgui.widgets.protocols.ButtonWidgetProtocol","text":"

Bases: ValueWidgetProtocol, SupportsText, SupportsIcon, Protocol

The \"value\" in a ButtonWidget is the current (checked) state.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol","title":"magicgui.widgets.protocols.TableWidgetProtocol","text":"

Bases: ValueWidgetProtocol, SupportsReadOnly, Protocol

ValueWidget subclass intended for 2D tabular data, with row & column headers.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_bind_change_callback","title":"_mgui_bind_change_callback(callback: Callable[[Any], Any]) -> None abstractmethod","text":"

Bind callback to value change event.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_bind_column_headers_change_callback","title":"_mgui_bind_column_headers_change_callback(callback: Callable[[Any], None]) -> None abstractmethod","text":"

Bind callback to column headers change event.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_bind_row_headers_change_callback","title":"_mgui_bind_row_headers_change_callback(callback: Callable[[Any], None]) -> None abstractmethod","text":"

Bind callback to row headers change event.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_get_cell","title":"_mgui_get_cell(row: int, col: int) -> Any abstractmethod","text":"

Get current value of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_get_column_count","title":"_mgui_get_column_count() -> int abstractmethod","text":"

Get the number of columns in the table.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_get_column_headers","title":"_mgui_get_column_headers() -> tuple abstractmethod","text":"

Get current column headers of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_get_row_count","title":"_mgui_get_row_count() -> int abstractmethod","text":"

Get the number of rows in the table.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_get_row_headers","title":"_mgui_get_row_headers() -> tuple abstractmethod","text":"

Get current row headers of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_remove_column","title":"_mgui_remove_column(column: int) -> None abstractmethod","text":"

Remove column at index column.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_remove_row","title":"_mgui_remove_row(row: int) -> None abstractmethod","text":"

Remove row at index row.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_set_cell","title":"_mgui_set_cell(row: int, col: int, value: Any) -> None abstractmethod","text":"

Set current value of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_set_column_count","title":"_mgui_set_column_count(ncols: int) -> None abstractmethod","text":"

Set the number of columns in the table. (Create/delete as needed).

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_set_column_headers","title":"_mgui_set_column_headers(headers: Sequence) -> None abstractmethod","text":"

Set current column headers of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_set_row_count","title":"_mgui_set_row_count(nrows: int) -> None abstractmethod","text":"

Set the number of rows in the table. (Create/delete as needed).

"},{"location":"api/protocols/#magicgui.widgets.protocols.TableWidgetProtocol._mgui_set_row_headers","title":"_mgui_set_row_headers(headers: Sequence) -> None abstractmethod","text":"

Set current row headers of the widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.RangedWidgetProtocol","title":"magicgui.widgets.protocols.RangedWidgetProtocol","text":"

Bases: ValueWidgetProtocol, Protocol

Value widget that supports numbers within a provided min/max range.

"},{"location":"api/protocols/#magicgui.widgets.protocols.RangedWidgetProtocol._mgui_get_adaptive_step","title":"_mgui_get_adaptive_step() -> bool abstractmethod","text":"

Get adaptive step status.

"},{"location":"api/protocols/#magicgui.widgets.protocols.RangedWidgetProtocol._mgui_get_max","title":"_mgui_get_max() -> float abstractmethod","text":"

Get the maximum possible value.

"},{"location":"api/protocols/#magicgui.widgets.protocols.RangedWidgetProtocol._mgui_get_min","title":"_mgui_get_min() -> float abstractmethod","text":"

Get the minimum possible value.

"},{"location":"api/protocols/#magicgui.widgets.protocols.RangedWidgetProtocol._mgui_get_step","title":"_mgui_get_step() -> float abstractmethod","text":"

Get the step size.

"},{"location":"api/protocols/#magicgui.widgets.protocols.RangedWidgetProtocol._mgui_set_adaptive_step","title":"_mgui_set_adaptive_step(value: bool) -> None abstractmethod","text":"

Set adaptive step status.

"},{"location":"api/protocols/#magicgui.widgets.protocols.RangedWidgetProtocol._mgui_set_max","title":"_mgui_set_max(value: float) -> None abstractmethod","text":"

Set the maximum possible value.

"},{"location":"api/protocols/#magicgui.widgets.protocols.RangedWidgetProtocol._mgui_set_min","title":"_mgui_set_min(value: float) -> None abstractmethod","text":"

Set the minimum possible value.

"},{"location":"api/protocols/#magicgui.widgets.protocols.RangedWidgetProtocol._mgui_set_step","title":"_mgui_set_step(value: float) -> None abstractmethod","text":"

Set the step size.

"},{"location":"api/protocols/#magicgui.widgets.protocols.CategoricalWidgetProtocol","title":"magicgui.widgets.protocols.CategoricalWidgetProtocol","text":"

Bases: ValueWidgetProtocol, SupportsChoices, Protocol

Categorical widget, that has a set of valid choices, and a current value.

It adds no additional methods.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SliderWidgetProtocol","title":"magicgui.widgets.protocols.SliderWidgetProtocol","text":"

Bases: RangedWidgetProtocol, SupportsOrientation, Protocol

Protocol for implementing a slider widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SliderWidgetProtocol._mgui_get_tracking","title":"_mgui_get_tracking() -> bool","text":"

If tracking is False, changed is only emitted when released.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SliderWidgetProtocol._mgui_set_readout_visibility","title":"_mgui_set_readout_visibility(visible: bool) -> None","text":"

Set visibility of readout widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SliderWidgetProtocol._mgui_set_tracking","title":"_mgui_set_tracking(tracking: bool) -> None","text":"

If tracking is False, changed is only emitted when released.

"},{"location":"api/protocols/#magicgui.widgets.protocols.ContainerProtocol","title":"magicgui.widgets.protocols.ContainerProtocol","text":"

Bases: WidgetProtocol, SupportsOrientation, Protocol

Widget that can contain other widgets.

This generally manages a backend Layout.

"},{"location":"api/protocols/#magicgui.widgets.protocols.ContainerProtocol._mgui_get_margins","title":"_mgui_get_margins() -> tuple[int, int, int, int] abstractmethod","text":"

Get the margins of the container.

"},{"location":"api/protocols/#magicgui.widgets.protocols.ContainerProtocol._mgui_insert_widget","title":"_mgui_insert_widget(position: int, widget: Widget) -> None abstractmethod","text":"

Insert widget at the given position in the layout.

"},{"location":"api/protocols/#magicgui.widgets.protocols.ContainerProtocol._mgui_remove_widget","title":"_mgui_remove_widget(widget: Widget) -> None abstractmethod","text":"

Remove the specified widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.ContainerProtocol._mgui_set_margins","title":"_mgui_set_margins(margins: tuple[int, int, int, int]) -> None abstractmethod","text":"

Set the margins of the container.

"},{"location":"api/protocols/#magicgui.widgets.protocols.DialogProtocol","title":"magicgui.widgets.protocols.DialogProtocol","text":"

Bases: ContainerProtocol, Protocol

Protocol for modal (blocking) containers.

"},{"location":"api/protocols/#magicgui.widgets.protocols.DialogProtocol._mgui_exec","title":"_mgui_exec() -> None abstractmethod","text":"

Show the dialog and block.

"},{"location":"api/protocols/#magicgui.widgets.protocols.MainWindowProtocol","title":"magicgui.widgets.protocols.MainWindowProtocol","text":"

Bases: ContainerProtocol, Protocol

Application main widget.

"},{"location":"api/protocols/#magicgui.widgets.protocols.MainWindowProtocol._mgui_create_menu_item","title":"_mgui_create_menu_item(menu_name: str, action_name: str, callback: Callable | None = None, shortcut: str | None = None) -> None abstractmethod","text":"

Create a new menu item.

Parameters:

  • menu_name (str) \u2013

    The name of the menu to add the item to.

  • action_name (str) \u2013

    The name of the action to add.

  • callback (Callable | None, default: None ) \u2013

    A callback to be called when the action is triggered, by default None.

  • shortcut (str | None, default: None ) \u2013

    A keyboard shortcut for the action, by default None.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsChoices","title":"magicgui.widgets.protocols.SupportsChoices","text":"

Bases: Protocol

Widget that has a set of valid choices.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsChoices._mgui_del_choice","title":"_mgui_del_choice(choice_name: str) -> None abstractmethod","text":"

Delete the provided choice_name and associated data.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsChoices._mgui_get_choice","title":"_mgui_get_choice(choice_name: str) -> Any abstractmethod","text":"

Get data for a single choice.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsChoices._mgui_get_choices","title":"_mgui_get_choices() -> tuple[tuple[str, Any], ...] abstractmethod","text":"

Get available choices.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsChoices._mgui_get_count","title":"_mgui_get_count() -> int abstractmethod","text":"

Return number of choices.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsChoices._mgui_get_current_choice","title":"_mgui_get_current_choice() -> str abstractmethod","text":"

Return the text of the currently selected choice.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsChoices._mgui_set_choice","title":"_mgui_set_choice(choice_name: str, data: Any) -> None abstractmethod","text":"

Set data for choice_name, or add a new item if choice_name doesn't exist.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsChoices._mgui_set_choices","title":"_mgui_set_choices(choices: Iterable[tuple[str, Any]]) -> None abstractmethod","text":"

Set available choices.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsOrientation","title":"magicgui.widgets.protocols.SupportsOrientation","text":"

Bases: Protocol

Widget that can be reoriented.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsOrientation._mgui_get_orientation","title":"_mgui_get_orientation() -> str abstractmethod","text":"

Get orientation, return either 'horizontal' or 'vertical'.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsOrientation._mgui_set_orientation","title":"_mgui_set_orientation(value: str) -> None abstractmethod","text":"

Set orientation, value will be 'horizontal' or 'vertical'.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsText","title":"magicgui.widgets.protocols.SupportsText","text":"

Bases: Protocol

Widget that have text (in addition to value)... like buttons.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsText._mgui_get_text","title":"_mgui_get_text() -> str abstractmethod","text":"

Get text.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsText._mgui_set_text","title":"_mgui_set_text(value: str) -> None abstractmethod","text":"

Set text.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsReadOnly","title":"magicgui.widgets.protocols.SupportsReadOnly","text":"

Bases: Protocol

Widget that can be read_only.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsReadOnly._mgui_get_read_only","title":"_mgui_get_read_only() -> bool abstractmethod","text":"

Get read_only status.

"},{"location":"api/protocols/#magicgui.widgets.protocols.SupportsReadOnly._mgui_set_read_only","title":"_mgui_set_read_only(value: bool) -> None abstractmethod","text":"

Set read_only.

"},{"location":"api/protocols/#application-protocol","title":"Application Protocol","text":""},{"location":"api/protocols/#magicgui.widgets.protocols.BaseApplicationBackend","title":"magicgui.widgets.protocols.BaseApplicationBackend","text":"

Bases: ABC

Backend Application object.

Abstract class that provides an interface between backends and Application. Each backend must implement a subclass of BaseApplicationBackend, and implement all of its _mgui_xxx methods.

"},{"location":"api/protocols/#magicgui.widgets.protocols.BaseApplicationBackend._mgui_get_backend_name","title":"_mgui_get_backend_name() -> str abstractmethod","text":"

Return the name of the backend.

"},{"location":"api/protocols/#magicgui.widgets.protocols.BaseApplicationBackend._mgui_get_native_app","title":"_mgui_get_native_app() -> Any abstractmethod","text":"

Return the native GUI application instance.

"},{"location":"api/protocols/#magicgui.widgets.protocols.BaseApplicationBackend._mgui_process_events","title":"_mgui_process_events() -> None abstractmethod","text":"

Process all pending GUI events.

"},{"location":"api/protocols/#magicgui.widgets.protocols.BaseApplicationBackend._mgui_quit","title":"_mgui_quit() -> None abstractmethod","text":"

Quit the native GUI event loop.

"},{"location":"api/protocols/#magicgui.widgets.protocols.BaseApplicationBackend._mgui_run","title":"_mgui_run() -> None abstractmethod","text":"

Start the application.

"},{"location":"api/protocols/#magicgui.widgets.protocols.BaseApplicationBackend._mgui_start_timer","title":"_mgui_start_timer(interval: int = 0, on_timeout: Callable[[], None] | None = None, single: bool = False) -> None abstractmethod","text":"

Create and start a timer.

Parameters:

  • interval (int, default: 0 ) \u2013

    Interval between timeouts, by default 0

  • on_timeout (Optional[Callable[[], None]], default: None ) \u2013

    Function to call when timer finishes, by default None

  • single (bool, default: False ) \u2013

    Whether the timer should only fire once, by default False

"},{"location":"api/protocols/#magicgui.widgets.protocols.BaseApplicationBackend._mgui_stop_timer","title":"_mgui_stop_timer() -> None abstractmethod","text":"

Stop timer. Should check for the existence of the timer.

"},{"location":"api/type_map/","title":"magicgui.type_map","text":"Widget Description get_widget_class Return a Widget subclass for the value/annotation. register_type Register a widget_type to be used for all parameters with type type_. type_registered Context manager that temporarily registers a widget type for a given type_. type2callback Return any callbacks that have been registered for type_."},{"location":"api/type_map/#magicgui.type_map.get_widget_class","title":"magicgui.type_map.get_widget_class(value: Any = Undefined, annotation: Any = Undefined, options: dict | None = None, is_result: bool = False, raise_on_unknown: bool = True) -> tuple[WidgetClass, dict]","text":"

Return a Widget subclass for the value/annotation.

Parameters:

  • value (Any, default: Undefined ) \u2013

    A python value. Will be used to determine the widget type if an annotation is not explicitly provided by default None

  • annotation (Optional[Type], default: Undefined ) \u2013

    A type annotation, by default None

  • options (dict, default: None ) \u2013

    Options to pass when constructing the widget, by default {}

  • is_result (bool, default: False ) \u2013

    Identifies whether the returned widget should be tailored to an input or to an output.

  • raise_on_unknown (bool, default: True ) \u2013

    Raise exception if no widget is found for the given type, by default True

Returns:

  • Tuple[WidgetClass, dict] \u2013

    The WidgetClass, and dict that can be used for params. dict may be different than the options passed in.

"},{"location":"api/type_map/#magicgui.type_map.register_type","title":"magicgui.type_map.register_type(type_: _T | None = None, *, widget_type: WidgetRef | None = None, return_callback: ReturnCallback | None = None, **options: Any) -> _T | Callable[[_T], _T]","text":"

Register a widget_type to be used for all parameters with type type_.

Note: registering a Union (or Optional) type effectively registers all types in the union with the arguments.

Parameters:

  • type_ (type, default: None ) \u2013

    The type for which a widget class or return callback will be provided.

  • widget_type (WidgetRef, default: None ) \u2013

    A widget class from the current backend that should be used whenever type_ is used as the type annotation for an argument in a decorated function, by default None

  • return_callback (ReturnCallback | None, default: None ) \u2013

    If provided, whenever type_ is declared as the return type of a decorated function, return_callback(widget, value, return_type) will be called whenever the decorated function is called... where widget is the Widget instance, and value is the return value of the decorated function.

  • options (Any, default: {} ) \u2013

    key value pairs where the keys are valid dict

Raises:

  • ValueError \u2013

    If none of widget_type, return_callback, bind or choices are provided.

"},{"location":"api/type_map/#magicgui.type_map.type_registered","title":"magicgui.type_map.type_registered(type_: _T, *, widget_type: WidgetRef | None = None, return_callback: ReturnCallback | None = None, **options: Any) -> Iterator[None]","text":"

Context manager that temporarily registers a widget type for a given type_.

When the context is exited, the previous widget type associations for type_ is restored.

Parameters:

  • type_ (_T) \u2013

    The type for which a widget class or return callback will be provided.

  • widget_type (Optional[WidgetRef], default: None ) \u2013

    A widget class from the current backend that should be used whenever type_ is used as the type annotation for an argument in a decorated function, by default None

  • return_callback (ReturnCallback | None, default: None ) \u2013

    If provided, whenever type_ is declared as the return type of a decorated function, return_callback(widget, value, return_type) will be called whenever the decorated function is called... where widget is the Widget instance, and value is the return value of the decorated function.

  • options (Any, default: {} ) \u2013

    key value pairs where the keys are valid dict

"},{"location":"api/type_map/#magicgui.type_map.type2callback","title":"magicgui.type_map.type2callback(type_: type) -> list[ReturnCallback]","text":"

Return any callbacks that have been registered for type_.

Parameters:

  • type_ (type) \u2013

    The type_ to look up.

Returns:

  • list of callable \u2013

    Where a return callback accepts two arguments (gui, value) and does something.

"},{"location":"api/widgets/","title":"Widget Index","text":"

Here you will find a list of all the widgets that are available in magicgui. Each widget has a link to its own documentation page, where you can find more information about the widget, including its parameters and events.

Widget Description CheckBox A checkbox with a text label. ComboBox A dropdown menu, allowing selection between multiple choices. Container A Widget to contain other widgets. DateEdit A widget for editing dates. DateTimeEdit A widget for editing dates and times. Dialog A modal container. EmptyWidget A base widget with no value. FileEdit A LineEdit widget with a button that opens a FileDialog. FloatRangeSlider A slider widget to adjust a range defined by two float values within a range. FloatSlider A slider widget to adjust an integer value within a range. FloatSpinBox A widget to edit a float with clickable up/down arrows. FunctionGui Wrapper for a container of widgets representing a callable object. Image A non-editable image display. Label A non-editable text display. LineEdit A one-line text editor. ListEdit A widget to represent a list of values. LiteralEvalLineEdit A one-line text editor that evaluates strings as python literals. LogSlider A slider widget to adjust a numerical value logarithmically within a range. MainFunctionGui Container of widgets as a Main Application Window. MainWindow A Widget to contain other widgets, includes a menu bar. Password A one-line text editor that obscures input. ProgressBar A progress bar widget. PushButton A clickable command button. QuantityEdit A combined LineEdit and ComboBox to edit a pint.Quantity. RadioButton A radio button with a text label. RadioButtons An exclusive group of radio buttons, providing a choice from multiple choices. RangeEdit A widget to represent a python range object, with start/stop/step. RangeSlider A slider widget to adjust a range between two integer values within a range. Select A list of options, allowing selection between multiple choices. SliceEdit A widget to represent slice objects, with start/stop/step. Slider A slider widget to adjust an integer value within a range. SpinBox A widget to edit an integer with clickable up/down arrows. Table A widget to represent columnar or 2D data with headers. TextEdit A widget to edit and display both plain and rich text. TimeEdit A widget for editing times. ToolBar Toolbar that contains a set of controls. TupleEdit A widget to represent a tuple of values."},{"location":"api/widgets/CheckBox/","title":"CheckBox","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/CheckBox/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the button is clicked (may also be connected at the alias clicked).
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/CheckBox/#magicgui.widgets.CheckBox","title":"CheckBox","text":"

Bases: ButtonWidget

A checkbox with a text label.

Parameters:

  • value (bool, default: Undefined ) \u2013

    The starting state of the widget.

  • text (str, default: None ) \u2013

    The text to display on the button. If not provided, will use name.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/ComboBox/","title":"ComboBox","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/ComboBox/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/ComboBox/#magicgui.widgets.ComboBox","title":"ComboBox","text":"

Bases: CategoricalWidget

A dropdown menu, allowing selection between multiple choices.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The initially selected choice.

  • choices (Enum, Iterable, or Callable, default: () ) \u2013

    Available choices displayed in the combo box.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/Container/","title":"Container","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/Container/#signals","title":"Signals","text":"
  • changed(object) - Emitted with self when any sub-widget in the container changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/Container/#magicgui.widgets.Container","title":"Container","text":"

Bases: ContainerWidget[WidgetVar]

A Widget to contain other widgets.

Note that `Container` implements the\n[`typing.MutableSequence`][typing.MutableSequence]\ninterface, so you can use it like a list to add and remove widgets.\n

Parameters:

  • widgets (Sequence[Widget], default: () ) \u2013

    A sequence of widgets with which to initialize the container, by default None.

  • layout (str, default: 'vertical' ) \u2013

    The layout for the container. must be one of {'horizontal', 'vertical'}. by default \"vertical\"

  • scrollable (bool, default: False ) \u2013

    Whether to enable scroll bars or not. If enabled, scroll bars will only appear along the layout direction, not in both directions.

  • labels (bool, default: True ) \u2013

    Whether each widget should be shown with a corresponding Label widget to the left, by default True. Note: the text for each widget defaults to widget.name, but can be overridden by setting widget.label.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/DateEdit/","title":"DateEdit","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/DateEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/DateEdit/#magicgui.widgets.DateEdit","title":"DateEdit","text":"

Bases: ValueWidget[date]

A widget for editing dates.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/DateTimeEdit/","title":"DateTimeEdit","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/DateTimeEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/DateTimeEdit/#magicgui.widgets.DateTimeEdit","title":"DateTimeEdit","text":"

Bases: ValueWidget[datetime]

A widget for editing dates and times.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/Dialog/","title":"Dialog","text":"

Available in backends: qt

"},{"location":"api/widgets/Dialog/#signals","title":"Signals","text":"
  • changed(object) - Emitted with self when any sub-widget in the container changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/Dialog/#magicgui.widgets.Dialog","title":"Dialog","text":"

Bases: DialogWidget

A modal container.

Parameters:

  • widgets (Sequence[Widget], default: () ) \u2013

    A sequence of widgets with which to initialize the container, by default None.

  • layout (str, default: 'vertical' ) \u2013

    The layout for the container. must be one of {'horizontal', 'vertical'}. by default \"vertical\"

  • scrollable (bool, default: False ) \u2013

    Whether to enable scroll bars or not. If enabled, scroll bars will only appear along the layout direction, not in both directions.

  • labels (bool, default: True ) \u2013

    Whether each widget should be shown with a corresponding Label widget to the left, by default True. Note: the text for each widget defaults to widget.name, but can be overridden by setting widget.label.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/EmptyWidget/","title":"EmptyWidget","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/EmptyWidget/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/EmptyWidget/#magicgui.widgets.EmptyWidget","title":"EmptyWidget","text":"

Bases: ValueWidget

A base widget with no value.

This widget is primarily here to serve as a \"hidden widget\" to which a value or\ncallback can be bound.\n

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/EmptyWidget/#magicgui.widgets.EmptyWidget.value","title":"value: Any property writable","text":"

Look for a bound value, otherwise fallback to get_value.

"},{"location":"api/widgets/EmptyWidget/#magicgui.widgets.EmptyWidget.__repr__","title":"__repr__() -> str","text":"

Return string repr (avoid looking for value).

"},{"location":"api/widgets/EmptyWidget/#magicgui.widgets.EmptyWidget.get_value","title":"get_value() -> Any","text":"

Return value if one has been manually set... otherwise return Param.empty.

"},{"location":"api/widgets/FileEdit/","title":"FileEdit","text":"

Available in backends:

"},{"location":"api/widgets/FileEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted with self when any sub-widget in the container changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/FileEdit/#magicgui.widgets.FileEdit","title":"FileEdit","text":"

Bases: Container

A LineEdit widget with a button that opens a FileDialog.

Parameters:

  • mode (FileDialogMode or str, default: EXISTING_FILE ) \u2013
    • 'r' returns one existing file.
    • 'rm' return one or more existing files.
    • 'w' return one file name that does not have to exist.
    • 'd' returns one existing directory.
  • filter (str, default: None ) \u2013

    The filter is used to specify the kind of files that should be shown. It should be a glob-style string, like '*.png' (this may be backend-specific)

"},{"location":"api/widgets/FileEdit/#magicgui.widgets.FileEdit.mode","title":"mode: FileDialogMode property writable","text":"

Mode for the FileDialog.

"},{"location":"api/widgets/FileEdit/#magicgui.widgets.FileEdit.value","title":"value: tuple[Path, ...] | Path | None property writable","text":"

Return current value of the widget. This may be interpreted by backends.

"},{"location":"api/widgets/FileEdit/#magicgui.widgets.FileEdit.__repr__","title":"__repr__() -> str","text":"

Return string representation.

"},{"location":"api/widgets/FloatRangeSlider/","title":"FloatRangeSlider","text":"

Available in backends: qt

"},{"location":"api/widgets/FloatRangeSlider/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/FloatRangeSlider/#magicgui.widgets.FloatRangeSlider","title":"FloatRangeSlider","text":"

Bases: MultiValuedSliderWidget

A slider widget to adjust a range defined by two float values within a range.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • min (float, default: Undefined ) \u2013

    The minimum allowable value, by default 0 (or value if value is less than 0)

  • max (float, default: Undefined ) \u2013

    The maximum allowable value, by default 999 (or value if value is greater than 999)

  • step (float, default: Undefined ) \u2013

    The step size for incrementing the value, by default adaptive step is used

  • orientation ((str, {'horizontal', 'vertical'}), default: 'horizontal' ) \u2013

    The orientation for the slider, by default \"horizontal\"

  • readout (bool, default: True ) \u2013

    Whether to show the editable spinbox next to the slider

  • tracking (bool, default: True ) \u2013

    If tracking is enabled (the default), the slider emits the changed signal while the slider is being dragged. If tracking is disabled, the slider emits the changed signal only after the user releases the slider.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/FloatSlider/","title":"FloatSlider","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/FloatSlider/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/FloatSlider/#magicgui.widgets.FloatSlider","title":"FloatSlider","text":"

Bases: SliderWidget[float]

A slider widget to adjust an integer value within a range.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • min (float, default: Undefined ) \u2013

    The minimum allowable value, by default 0 (or value if value is less than 0)

  • max (float, default: Undefined ) \u2013

    The maximum allowable value, by default 999 (or value if value is greater than 999)

  • step (float, default: Undefined ) \u2013

    The step size for incrementing the value, by default adaptive step is used

  • orientation ((str, {'horizontal', 'vertical'}), default: 'horizontal' ) \u2013

    The orientation for the slider, by default \"horizontal\"

  • readout (bool, default: True ) \u2013

    Whether to show the editable spinbox next to the slider

  • tracking (bool, default: True ) \u2013

    If tracking is enabled (the default), the slider emits the changed signal while the slider is being dragged. If tracking is disabled, the slider emits the changed signal only after the user releases the slider.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/FloatSpinBox/","title":"FloatSpinBox","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/FloatSpinBox/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/FloatSpinBox/#magicgui.widgets.FloatSpinBox","title":"FloatSpinBox","text":"

Bases: RangedWidget[float]

A widget to edit a float with clickable up/down arrows.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • min (float, default: Undefined ) \u2013

    The minimum allowable value, by default 0 (or value if value is less than 0)

  • max (float, default: Undefined ) \u2013

    The maximum allowable value, by default 999 (or value if value is greater than 999)

  • step (float, default: Undefined ) \u2013

    The step size for incrementing the value, by default adaptive step is used

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/FunctionGui/","title":"FunctionGui","text":"

Available in backends:

"},{"location":"api/widgets/FunctionGui/#signals","title":"Signals","text":"
  • called(object) - Emitted with the result after the function is called.
  • changed(object) - Emitted with self when any sub-widget in the container changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui","title":"FunctionGui","text":"

Bases: Container, Generic[_P, _R]

Wrapper for a container of widgets representing a callable object.

Parameters:

  • function (Callable) \u2013

    A callable to turn into a GUI

  • call_button (bool | str | None, default: None ) \u2013

    If True, create an additional button that calls the original function when clicked. If a str, set the button text. by default False when auto_call is True, and True otherwise. The button can be accessed from the .call_button property.

  • layout (str, default: 'vertical' ) \u2013

    The type of layout to use. Must be horizontal or vertical by default \"horizontal\".

  • scrollable (bool, default: False ) \u2013

    Whether to enable scroll bars or not. If enabled, scroll bars will only appear along the layout direction, not in both directions.

  • labels (bool, default: True ) \u2013

    Whether labels are shown in the widget. by default True

  • tooltips (bool, default: True ) \u2013

    Whether tooltips are shown when hovering over widgets. by default True

  • app (Application | str | None, default: None ) \u2013

    A backend to use, by default None (use the default backend.)

  • visible (bool, default: None ) \u2013

    Whether to immediately show the widget. If False, widget is explicitly hidden. If None, widget is not shown, but will be shown if a parent container is shown, by default None.

  • auto_call (bool, default: False ) \u2013

    If True, changing any parameter in either the GUI or the widget attributes will call the original function with the current settings. by default False

  • result_widget (bool, default: False ) \u2013

    Whether to display a LineEdit widget the output of the function when called, by default False

  • param_options (dict, default: None ) \u2013

    A dict of name: widget_options dict for each parameter in the function. Will be passed to magic_signature by default None

  • name (str, default: None ) \u2013

    A name to assign to the Container widget, by default function.__name__

  • persist (bool, default: False ) \u2013

    If True, when parameter values change in the widget, they will be stored to disk (in ~/.config/magicgui/cache) and restored when the widget is loaded again with persist = True. By default, False.

  • raise_on_unknown (bool, default: False ) \u2013

    If True, raise an error if a parameter annotation is not recognized.

Raises:

  • TypeError \u2013

    If unexpected keyword arguments are provided

"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.__signature__","title":"__signature__: MagicSignature property","text":"

Return a MagicSignature object representing the current state of the gui.

"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.call_button","title":"call_button: PushButton | None property","text":"

Return the call button.

"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.call_count","title":"call_count: int property","text":"

Return the number of times the function has been called.

"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.result_name","title":"result_name: str property writable","text":"

Return a name that can be used for the result of this magicfunction.

"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.return_annotation","title":"return_annotation: Any property","text":"

Return annotation for inspect.Signature conversion.

ForwardRefs will be resolve when setting the annotation.

"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.__call__","title":"__call__(*args: _P.args, **kwargs: _P.kwargs) -> _R","text":"

Call the original function with the current parameter values from the Gui.

You may pass a update_widget=True keyword argument to update the widget values to match the current parameter values before calling the function.

It is also possible to override the current parameter values from the GUI by providing args/kwargs to the function call. Only those provided will override the ones from the gui. A called signal will also be emitted with the results.

Returns:

  • result ( Any ) \u2013

    whatever the return value of the original function would have been.

Examples:

gui = FunctionGui(func, show=True)\n\n# then change parameters in the gui, or by setting:  gui.param.value = something\n\ngui()  # calls the original function with the current parameters\n
"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.__get__","title":"__get__(obj: object, objtype: type | None = None) -> FunctionGui","text":"

Provide descriptor protocol.

This allows the @magicgui decorator to work on a function as well as a method. If a method on a class is decorated with @magicgui, then accessing the attribute on an instance of that class will return a version of the FunctionGui in which the first argument of the function is bound to the instance. (Just like what you'd expect with the @property decorator.)

Returns:

  • bound ( FunctionGui ) \u2013

    A new FunctionGui instance.

Examples:

>>> class MyClass:\n...     @magicgui\n...     def my_method(self, x=1):\n...         print(locals())\n...\n>>> c = MyClass()\n>>> c.my_method  # the FunctionGui that can be used as a widget\n\n# calling it works as usual, with `c` provided as `self`\n>>> c.my_method(x=34)\n{'self': <__main__.MyClass object at 0x7fb610e455e0>, 'x': 34}\n
"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.__init__","title":"__init__(function: Callable[_P, _R], call_button: bool | str | None = None, layout: str = 'vertical', scrollable: bool = False, labels: bool = True, tooltips: bool = True, app: AppRef | None = None, visible: bool | None = None, auto_call: bool = False, result_widget: bool = False, param_options: dict[str, dict] | None = None, name: str | None = None, persist: bool = False, raise_on_unknown: bool = False, **kwargs: Any)","text":""},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.__repr__","title":"__repr__() -> str","text":"

Return string representation of instance.

"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.__set__","title":"__set__(obj: Any, value: Any) -> NoReturn","text":"

Prevent setting a magicgui attribute.

"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.copy","title":"copy() -> FunctionGui","text":"

Return a copy of this FunctionGui.

"},{"location":"api/widgets/FunctionGui/#magicgui.widgets.FunctionGui.reset_call_count","title":"reset_call_count() -> None","text":"

Reset the call count to 0.

"},{"location":"api/widgets/Image/","title":"Image","text":"

Available in backends: qt

"},{"location":"api/widgets/Image/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/Image/#magicgui.widgets.Image","title":"Image","text":"

Bases: ValueWidget

A non-editable image display.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/Image/#magicgui.widgets.Image.image_data","title":"image_data: np.ndarray | None property","text":"

Return image data.

"},{"location":"api/widgets/Image/#magicgui.widgets.Image.image_rgba","title":"image_rgba: np.ndarray | None property","text":"

Return rendered numpy array.

"},{"location":"api/widgets/Image/#magicgui.widgets.Image.value","title":"value property writable","text":"

Return current image array.

"},{"location":"api/widgets/Image/#magicgui.widgets.Image.__repr__","title":"__repr__() -> str","text":"

Return representation of widget of instance.

"},{"location":"api/widgets/Image/#magicgui.widgets.Image.get_clim","title":"get_clim() -> tuple[float | None, float | None]","text":"

Get contrast limits (for monochromatic images).

"},{"location":"api/widgets/Image/#magicgui.widgets.Image.scale_widget_to_image_size","title":"scale_widget_to_image_size()","text":"

Set the size of the widget to the size of the image.

"},{"location":"api/widgets/Image/#magicgui.widgets.Image.set_clim","title":"set_clim(vmin: float | None = None, vmax: float | None = None)","text":"

Set contrast limits (for monochromatic images).

Parameters:

  • vmin (float, default: None ) \u2013

    The min contrast limit to use when scaling monochromatic images

  • vmax (float, default: None ) \u2013

    The max contrast limit to use when scaling monochromatic images

"},{"location":"api/widgets/Image/#magicgui.widgets.Image.set_cmap","title":"set_cmap(cmap: str | Colormap | matplotlib.colors.Colormap)","text":"

Set colormap (for monochromatic images).

Parameters:

  • cmap (str, magicgui.types.Colormap, or matplotlib.colors.Colormap) \u2013

    A colormap to use for monochromatic images. If a string, matplotlib must be installed and the colormap will be selected with cm.get_cmap(cmap).

"},{"location":"api/widgets/Image/#magicgui.widgets.Image.set_data","title":"set_data(val: str | Path | np.ndarray | PIL.Image.Image, cmap: str | Colormap | matplotlib.colors.Colormap | None = None, norm: _mpl_image.Normalize | matplotlib.colors.Normalize | None = None, vmin: float | None = None, vmax: float | None = None, width: int | Literal['auto'] | None = None, height: int | Literal['auto'] | None = None, format: str | None = None)","text":"

Set image data with various optional display parameters.

Parameters:

  • val ((str, Path, ndarray or Image)) \u2013

    The image data or file to load. Data must be 2D (monochromatic), or 3D: MxNx3 (RGB) or MxNx4 (RGBA).

  • cmap (str, magicgui.types.Colormap, or matplotlib.colors.Colormap, default: None ) \u2013

    A colormap to use for monochromatic images. If a string, matplotlib must be installed and the colormap will be selected with cm.get_cmap(cmap).

  • norm (magicgui.types.Normalize, or matplotlib.colors.Normalize, default: None ) \u2013

    A normalization object to use for rendering images. Accepts matplotlib Normalize objects.

  • vmin (float, default: None ) \u2013

    The min contrast limit to use when scaling monochromatic images

  • vmax (float, default: None ) \u2013

    The max contrast limit to use when scaling monochromatic images

  • width (int or 'auto', default: None ) \u2013

    Set the width of the widget. If \"auto\", sets the widget size to the image size (1:1). If width is provided, height is auto-set based on aspect ratio.

  • height (int or 'auto', default: None ) \u2013

    Set the height of the widget. If \"auto\", sets the widget size to the image size (1:1). If width is provided, height is auto-set based on aspect ratio.

  • format (str, default: None ) \u2013

    Force image format type for imread when val is provided as a string, by default None

Raises:

  • TypeError \u2013

    If the provided data shape or type is invalid.

  • ImportError \u2013

    If a string is provided for val and PIL is not installed.

  • RuntimeError \u2013

    If a PIL.Image.Image instance is provided as data, with an unrecognized image mode.

"},{"location":"api/widgets/Image/#magicgui.widgets.Image.set_norm","title":"set_norm(norm: Normalize | matplotlib.colors.Normalize)","text":"

Set normalization method.

Parameters:

  • norm (magicgui.types.Normalize, or matplotlib.colors.Normalize) \u2013

    A normalization object to use for rendering images. Accepts matplotlib Normalize objects.

"},{"location":"api/widgets/Label/","title":"Label","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/Label/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/Label/#magicgui.widgets.Label","title":"Label","text":"

Bases: ValueWidget[str]

A non-editable text display.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/LineEdit/","title":"LineEdit","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/LineEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/LineEdit/#magicgui.widgets.LineEdit","title":"LineEdit","text":"

Bases: ValueWidget[str]

A one-line text editor.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/ListEdit/","title":"ListEdit","text":"

Available in backends:

"},{"location":"api/widgets/ListEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted with self when any sub-widget in the container changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/ListEdit/#magicgui.widgets.ListEdit","title":"ListEdit","text":"

Bases: Container[ValueWidget[_V]]

A widget to represent a list of values.

A ListEdit container can create a list with multiple objects of same type. It\nwill contain many child widgets and their value is represented as a Python list\nobject. If a list is given as the initial value, types of child widgets are\ndetermined from the contents. Number of contents can be adjusted with +/-\nbuttons.\n

Parameters:

  • value (Iterable, default: Undefined ) \u2013

    The starting value for the widget.

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • options (dict, default: None ) \u2013

    Widget options of child widgets.

"},{"location":"api/widgets/ListEdit/#magicgui.widgets.ListEdit.annotation","title":"annotation: Any property writable","text":"

Return type annotation for the parameter represented by the widget.

ForwardRefs will be resolve when setting the annotation. For ListEdit, annotation will be like 'list[str]'.

"},{"location":"api/widgets/ListEdit/#magicgui.widgets.ListEdit.data","title":"data: ListDataView[_V] property writable","text":"

Return a data view of current value.

"},{"location":"api/widgets/ListEdit/#magicgui.widgets.ListEdit.value","title":"value: list[_V] property writable","text":"

Return current value as a list object.

"},{"location":"api/widgets/ListEdit/#magicgui.widgets.ListEdit.__delitem__","title":"__delitem__(key: int | slice) -> None","text":"

Delete child widget(s).

"},{"location":"api/widgets/LiteralEvalLineEdit/","title":"LiteralEvalLineEdit","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/LiteralEvalLineEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/LiteralEvalLineEdit/#magicgui.widgets.LiteralEvalLineEdit","title":"LiteralEvalLineEdit","text":"

Bases: ValueWidget[str]

A one-line text editor that evaluates strings as python literals.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/LogSlider/","title":"LogSlider","text":"

Available in backends:

"},{"location":"api/widgets/LogSlider/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/LogSlider/#magicgui.widgets.LogSlider","title":"LogSlider","text":"

Bases: TransformedRangedWidget

A slider widget to adjust a numerical value logarithmically within a range.

Parameters:

  • base (Enum, Iterable, or Callable, default: e ) \u2013

    The base to use for the log, by default math.e.

"},{"location":"api/widgets/LogSlider/#magicgui.widgets.LogSlider.base","title":"base: float property writable","text":"

Return base used for the log.

"},{"location":"api/widgets/LogSlider/#magicgui.widgets.LogSlider.tracking","title":"tracking: bool property writable","text":"

Return whether slider tracking is enabled.

If tracking is enabled (the default), the slider emits the changed() signal while the slider is being dragged. If tracking is disabled, the slider emits the changed() signal only when the user releases the slider.

"},{"location":"api/widgets/MainFunctionGui/","title":"MainFunctionGui","text":"

Available in backends:

"},{"location":"api/widgets/MainFunctionGui/#signals","title":"Signals","text":"
  • called(object) - Emitted with the result after the function is called.
  • changed(object) - Emitted with self when any sub-widget in the container changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/MainFunctionGui/#magicgui.widgets.MainFunctionGui","title":"MainFunctionGui","text":"

Bases: FunctionGui[_P, _R], MainWindow

Container of widgets as a Main Application Window.

"},{"location":"api/widgets/MainWindow/","title":"MainWindow","text":"

Available in backends: qt

"},{"location":"api/widgets/MainWindow/#signals","title":"Signals","text":"
  • changed(object) - Emitted with self when any sub-widget in the container changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/MainWindow/#magicgui.widgets.MainWindow","title":"MainWindow","text":"

Bases: MainWindowWidget

A Widget to contain other widgets, includes a menu bar.

Parameters:

  • widgets (Sequence[Widget], default: () ) \u2013

    A sequence of widgets with which to initialize the container, by default None.

  • layout (str, default: 'vertical' ) \u2013

    The layout for the container. must be one of {'horizontal', 'vertical'}. by default \"vertical\"

  • scrollable (bool, default: False ) \u2013

    Whether to enable scroll bars or not. If enabled, scroll bars will only appear along the layout direction, not in both directions.

  • labels (bool, default: True ) \u2013

    Whether each widget should be shown with a corresponding Label widget to the left, by default True. Note: the text for each widget defaults to widget.name, but can be overridden by setting widget.label.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/Password/","title":"Password","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/Password/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/Password/#magicgui.widgets.Password","title":"Password","text":"

Bases: ValueWidget[str]

A one-line text editor that obscures input.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/ProgressBar/","title":"ProgressBar","text":"

Available in backends: qt

"},{"location":"api/widgets/ProgressBar/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/ProgressBar/#magicgui.widgets.ProgressBar","title":"ProgressBar","text":"

Bases: SliderWidget[float]

A progress bar widget.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • min (float, default: Undefined ) \u2013

    The minimum allowable value, by default 0 (or value if value is less than 0)

  • max (float, default: Undefined ) \u2013

    The maximum allowable value, by default 999 (or value if value is greater than 999)

  • step (float, default: Undefined ) \u2013

    The step size for incrementing the value, by default adaptive step is used

  • orientation ((str, {'horizontal', 'vertical'}), default: 'horizontal' ) \u2013

    The orientation for the slider, by default \"horizontal\"

  • readout (bool, default: True ) \u2013

    Whether to show the editable spinbox next to the slider

  • tracking (bool, default: True ) \u2013

    If tracking is enabled (the default), the slider emits the changed signal while the slider is being dragged. If tracking is disabled, the slider emits the changed signal only after the user releases the slider.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/ProgressBar/#magicgui.widgets.ProgressBar.step","title":"step: float property writable","text":"

Step size for widget values.

"},{"location":"api/widgets/ProgressBar/#magicgui.widgets.ProgressBar.decrement","title":"decrement(val: float | None = None) -> None","text":"

Decrease current value by step size, or provided value.

"},{"location":"api/widgets/ProgressBar/#magicgui.widgets.ProgressBar.increment","title":"increment(val: float | None = None) -> None","text":"

Increase current value by step size, or provided value.

"},{"location":"api/widgets/PushButton/","title":"PushButton","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/PushButton/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the button is clicked (may also be connected at the alias clicked).
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/PushButton/#magicgui.widgets.PushButton","title":"PushButton","text":"

Bases: ButtonWidget

A clickable command button.

Parameters:

  • value (bool, default: Undefined ) \u2013

    The starting state of the widget.

  • text (str, default: None ) \u2013

    The text to display on the button. If not provided, will use name.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/QuantityEdit/","title":"QuantityEdit","text":"

Available in backends: qt

"},{"location":"api/widgets/QuantityEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/QuantityEdit/#magicgui.widgets.QuantityEdit","title":"QuantityEdit","text":"

Bases: ValueWidget

A combined LineEdit and ComboBox to edit a pint.Quantity.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/RadioButton/","title":"RadioButton","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/RadioButton/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the button is clicked (may also be connected at the alias clicked).
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/RadioButton/#magicgui.widgets.RadioButton","title":"RadioButton","text":"

Bases: ButtonWidget

A radio button with a text label.

Parameters:

  • value (bool, default: Undefined ) \u2013

    The starting state of the widget.

  • text (str, default: None ) \u2013

    The text to display on the button. If not provided, will use name.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/RadioButtons/","title":"RadioButtons","text":"

Available in backends: qt

"},{"location":"api/widgets/RadioButtons/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/RadioButtons/#magicgui.widgets.RadioButtons","title":"RadioButtons","text":"

Bases: CategoricalWidget, _OrientationMixin

An exclusive group of radio buttons, providing a choice from multiple choices.

Parameters:

  • value (Any) \u2013

    The initially selected choice.

  • choices (Enum, Iterable, or Callable, default: () ) \u2013

    Available choices displayed in the combo box.

  • bind (Callable[[ValueWidget], Any] | Any) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/RangeEdit/","title":"RangeEdit","text":"

Available in backends:

"},{"location":"api/widgets/RangeEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted with self when any sub-widget in the container changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/RangeEdit/#magicgui.widgets.RangeEdit","title":"RangeEdit","text":"

Bases: Container[SpinBox]

A widget to represent a python range object, with start/stop/step.

A range object produces a sequence of integers from start (inclusive)\nto stop (exclusive) by step.  range(i, j) produces i, i+1, i+2, ..., j-1.\nstart defaults to 0, and stop is omitted!  range(4) produces 0, 1, 2, 3.\nThese are exactly the valid indices for a list of 4 elements.\nWhen step is given, it specifies the increment (or decrement).\n

Parameters:

  • start (int, default: 0 ) \u2013

    The range start value, by default 0

  • stop (int, default: 10 ) \u2013

    The range stop value, by default 10

  • step (int, default: 1 ) \u2013

    The range step value, by default 1

"},{"location":"api/widgets/RangeEdit/#magicgui.widgets.RangeEdit.value","title":"value: range property writable","text":"

Return current value of the widget. This may be interpreted by backends.

"},{"location":"api/widgets/RangeEdit/#magicgui.widgets.RangeEdit.__repr__","title":"__repr__() -> str","text":"

Return string representation.

"},{"location":"api/widgets/RangeSlider/","title":"RangeSlider","text":"

Available in backends: qt

"},{"location":"api/widgets/RangeSlider/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/RangeSlider/#magicgui.widgets.RangeSlider","title":"RangeSlider","text":"

Bases: MultiValuedSliderWidget

A slider widget to adjust a range between two integer values within a range.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • min (float, default: Undefined ) \u2013

    The minimum allowable value, by default 0 (or value if value is less than 0)

  • max (float, default: Undefined ) \u2013

    The maximum allowable value, by default 999 (or value if value is greater than 999)

  • step (float, default: Undefined ) \u2013

    The step size for incrementing the value, by default adaptive step is used

  • orientation ((str, {'horizontal', 'vertical'}), default: 'horizontal' ) \u2013

    The orientation for the slider, by default \"horizontal\"

  • readout (bool, default: True ) \u2013

    Whether to show the editable spinbox next to the slider

  • tracking (bool, default: True ) \u2013

    If tracking is enabled (the default), the slider emits the changed signal while the slider is being dragged. If tracking is disabled, the slider emits the changed signal only after the user releases the slider.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/Select/","title":"Select","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/Select/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/Select/#magicgui.widgets.Select","title":"Select","text":"

Bases: CategoricalWidget

A list of options, allowing selection between multiple choices.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The initially selected choice.

  • choices (Enum, Iterable, or Callable, default: () ) \u2013

    Available choices displayed in the combo box.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/SliceEdit/","title":"SliceEdit","text":"

Available in backends:

"},{"location":"api/widgets/SliceEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted with self when any sub-widget in the container changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/SliceEdit/#magicgui.widgets.SliceEdit","title":"SliceEdit","text":"

Bases: RangeEdit

A widget to represent slice objects, with start/stop/step.

slice(stop) slice(start, stop[, step])

Slice objects may be used for extended slicing (e.g. a[0:10:2])

"},{"location":"api/widgets/SliceEdit/#magicgui.widgets.SliceEdit.value","title":"value: slice property writable","text":"

Return current value of the widget. This may be interpreted by backends.

"},{"location":"api/widgets/Slider/","title":"Slider","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/Slider/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/Slider/#magicgui.widgets.Slider","title":"Slider","text":"

Bases: SliderWidget[int]

A slider widget to adjust an integer value within a range.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • min (float, default: Undefined ) \u2013

    The minimum allowable value, by default 0 (or value if value is less than 0)

  • max (float, default: Undefined ) \u2013

    The maximum allowable value, by default 999 (or value if value is greater than 999)

  • step (float, default: Undefined ) \u2013

    The step size for incrementing the value, by default adaptive step is used

  • orientation ((str, {'horizontal', 'vertical'}), default: 'horizontal' ) \u2013

    The orientation for the slider, by default \"horizontal\"

  • readout (bool, default: True ) \u2013

    Whether to show the editable spinbox next to the slider

  • tracking (bool, default: True ) \u2013

    If tracking is enabled (the default), the slider emits the changed signal while the slider is being dragged. If tracking is disabled, the slider emits the changed signal only after the user releases the slider.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/SpinBox/","title":"SpinBox","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/SpinBox/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/SpinBox/#magicgui.widgets.SpinBox","title":"SpinBox","text":"

Bases: RangedWidget[int]

A widget to edit an integer with clickable up/down arrows.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • min (float, default: Undefined ) \u2013

    The minimum allowable value, by default 0 (or value if value is less than 0)

  • max (float, default: Undefined ) \u2013

    The maximum allowable value, by default 999 (or value if value is greater than 999)

  • step (float, default: Undefined ) \u2013

    The step size for incrementing the value, by default adaptive step is used

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/Table/","title":"Table","text":"

Available in backends: qt

"},{"location":"api/widgets/Table/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/Table/#magicgui.widgets.Table","title":"Table","text":"

Bases: ValueWidget, _ReadOnlyMixin, MutableMapping[TblKey, list]

A widget to represent columnar or 2D data with headers.

Tables behave like plain dicts, where the keys are column headers and the (list-like) values are column data.

Parameters:

  • value ((dict, dataframe, list, array, tuple), default: None ) \u2013

    Table data (and/or header data), in one of the accepted formats:

    • list or list-of-lists : [column_values] or [[row_vals], ..., [row_vals]]
    • dict-of-dicts : {column_header -> {row_header -> value}}
    • dict-of-lists : {column_header -> [column_values]}
    • list-of-row-records : [{column_headers -> value}, ... , {column_headers -> value}]
    • split-dict-of-lists :
    • tuple-of-values : ([values], [row_headers], [column_headers])
    • dict-of-pandas-series : {column_header -> Series(values)}
  • index (Collection, default: None ) \u2013

    A sized iterable container of row headers. By default, row headers will be tuple(range(len(data))). Values provided here override any implied in value.

  • columns (Collection, default: None ) \u2013

    A sized iterable container of column headers. By default, column headers will be tuple(range(len(data[0]))). Values provided here override any implied in value.

  • **kwargs (Unpack[WidgetKwargs], default: {} ) \u2013

    Additional kwargs will be passed to the magicgui.widgets.Widget constructor.

Attributes:

  • value (dict) \u2013

    Returns a dict with the keys data, index, and columns ... representing the 2D (list of lists) tabular data, row headers, and column headers, respectively. If set, will clear and update the table using the new data.

  • data (DataView) \u2013

    A DataView instance that provides numpy-like indexing (with get/set/delete) onto the 2D data array, For example table.data[0,2] gets the data in the cell of the first row, 3rd column. Works with numpy slice syntax.

  • column_headers (tuple) \u2013

    The current column headers. Can be set with a new sequence to change

  • row_headers (tuple) \u2013

    The current row headers. Can be set with a new sequence to change

  • shape (tuple of int) \u2013

    The shape of the table in (rows, columns).

  • size (int) \u2013

    The number of cells in the table.

Methods:

  • keys \u2013

    Return a TableHeadersView, providing a view on this table's headers. Use axis='row' for row headers.

  • items \u2013

    Return a TableItemsView, providing a view on this table's items, as 2-tuples of (header, data). Use axis='row' for (row_header, row_data)

  • clear \u2013

    Clear all table data and headers.

  • to_dataframe \u2013

    Returns a pandas dataframe representation of this table. (requires pandas)

  • to_dict \u2013

    Return one of many different dict-like representations of table and header data. See docstring of :meth:to_dict for details.

Events

changed Emitted whenever a cell in the table changes. The value will have a dict of information regarding the cell that changed: {'data': x, 'row': int, 'column': int, 'column_header': str, 'row_header': str} CURRENTLY: only emitted on changes in the GUI. not programmatic changes.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.column_headers","title":"column_headers: tuple property writable","text":"

Return column headers.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.data","title":"data: DataView property writable","text":"

Return DataView object for this table.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.row_headers","title":"row_headers: tuple property writable","text":"

Return row headers.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.shape","title":"shape: tuple[int, int] property","text":"

Return shape of table widget (rows, cols).

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.size","title":"size: int property","text":"

Return shape of table widget (rows, cols).

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.value","title":"value: dict[TblKey, Collection] property writable","text":"

Return dict with current data, index, and columns of the widget.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.__delitem__","title":"__delitem__(key: TblKey) -> None","text":"

Delete a column from the table.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.__getitem__","title":"__getitem__(key: TblKey) -> list","text":"

Get a column from the table.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.__hash__","title":"__hash__() -> int","text":"

Make table hashable.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.__iter__","title":"__iter__() -> Iterator","text":"

Yield column headers.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.__len__","title":"__len__() -> int","text":"

Return number of columns.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.__new__","title":"__new__(value: TableData | None = None, *, index: Collection | None = None, columns: Collection | None = None, **kwargs: Any) -> Table","text":"

Just for the signature.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.__repr__","title":"__repr__() -> str","text":"

Return string repr.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.__setitem__","title":"__setitem__(key: TblKey, v: Collection) -> None","text":"

Set a column in the table. If k doesn't exist, make a new column.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.clear","title":"clear() -> None","text":"

Clear the table.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.delete_row","title":"delete_row(*, index: int | Sequence[int] | None = None, header: Any | Sequence[Any] | None = None) -> None","text":"

Delete row(s) by index or header.

Parameters:

  • index (int or Sequence[int], default: None ) \u2013

    Index or indices of row(s) to delete.

  • header (Any or Sequence[Any], default: None ) \u2013

    Header or headers of row(s) to delete.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.items","title":"items(axis: str = 'column') -> TableItemsView[TblKey, list]","text":"

Return a set-like object providing a view on this table's items.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.keys","title":"keys(axis: str = 'column') -> HeadersView[TblKey]","text":"

Return a set-like object providing a view on this table's headers.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.to_dataframe","title":"to_dataframe() -> pandas.DataFrame","text":"

Convert TableData to dataframe.

"},{"location":"api/widgets/Table/#magicgui.widgets.Table.to_dict","title":"to_dict(orient: str = 'dict') -> list | dict","text":"

Convert the Table to a dictionary.

The type of the key-value pairs can be customized with the parameters (see below).

Parameters:

  • orient (str {'dict', 'list', 'series', 'split', 'records', 'index'}, default: 'dict' ) \u2013

    Determines the type of the values of the dictionary.

    • 'dict' (default) : dict like {column -> {index -> value}}
    • 'list' : dict like {column -> [values]}
    • 'split' : dict like
    • 'records' : list like [{column -> value}, ... , {column -> value}]
    • 'index' : dict like {index -> {column -> value}}
    • 'series' : dict like {column -> Series(values)}
"},{"location":"api/widgets/TextEdit/","title":"TextEdit","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/TextEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/TextEdit/#magicgui.widgets.TextEdit","title":"TextEdit","text":"

Bases: ValueWidget[str], _ReadOnlyMixin

A widget to edit and display both plain and rich text.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/TimeEdit/","title":"TimeEdit","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/TimeEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted when the widget value changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/TimeEdit/#magicgui.widgets.TimeEdit","title":"TimeEdit","text":"

Bases: ValueWidget[TV]

A widget for editing times.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/ToolBar/","title":"ToolBar","text":"

Available in backends: qt, ipynb

"},{"location":"api/widgets/ToolBar/#signals","title":"Signals","text":"
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/ToolBar/#magicgui.widgets.ToolBar","title":"ToolBar","text":"

Bases: ToolBarWidget

Toolbar that contains a set of controls.

Parameters:

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/TupleEdit/","title":"TupleEdit","text":"

Available in backends:

"},{"location":"api/widgets/TupleEdit/#signals","title":"Signals","text":"
  • changed(object) - Emitted with self when any sub-widget in the container changes.
  • label_changed(str) - Emitted when the widget label changes.
  • native_parent_changed(object) - Emitted with the backend widget when the widget parent changes.
"},{"location":"api/widgets/TupleEdit/#magicgui.widgets.TupleEdit","title":"TupleEdit","text":"

Bases: Container[ValueWidget]

A widget to represent a tuple of values.

A TupleEdit container has several child widgets of different type. Their value is\nrepresented as a Python tuple object. If a tuple is given as the initial value,\ntypes of child widgets are determined one by one. Unlike ListEdit, number of\ncontents is not editable.\n

Parameters:

  • value (Iterable, default: Undefined ) \u2013

    The starting value for the widget.

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • options (dict, default: None ) \u2013

    Widget options of child widgets.

"},{"location":"api/widgets/TupleEdit/#magicgui.widgets.TupleEdit.annotation","title":"annotation: Any property writable","text":"

Return type annotation for the parameter represented by the widget.

ForwardRefs will be resolve when setting the annotation. For TupleEdit, annotation will be like 'tuple[str, int]'.

"},{"location":"api/widgets/TupleEdit/#magicgui.widgets.TupleEdit.value","title":"value: tuple property writable","text":"

Return current value as a tuple.

"},{"location":"api/widgets/bases/","title":"magicgui.widgets.bases","text":"

The magicgui.widgets.bases module contains the base classes for all widgets.

While most users will never instantiate these classes directly, the methods and properties of these classes are inherited by all widgets, and define the common API for all widgets. Therefore, it is worth being aware of the type of widget you are working with.

"},{"location":"api/widgets/bases/#summary","title":"Summary","text":"Widget Description Widget Basic Widget, wrapping a class that implements WidgetProtocol. ButtonWidget Widget with a value, Wraps a widget implementing the ButtonWidgetProtocol. CategoricalWidget Widget with a value and choices. Wraps CategoricalWidgetProtocol. ContainerWidget Widget that can contain other widgets. DialogWidget Modal Container. MainWindowWidget Top level Application widget that can contain other widgets. RangedWidget Widget with a constrained value. Wraps RangedWidgetProtocol. SliderWidget Widget with a constrained value and orientation. Wraps SliderWidgetProtocol. ValueWidget Widget with a value, Wraps ValueWidgetProtocol."},{"location":"api/widgets/bases/#class-hierarchy","title":"Class Hierarchy","text":"

In visual form, the widget class hierarchy looks like this:

classDiagram\n    Widget <|-- ValueWidget\n    Widget <|-- ContainerWidget\n    BackendWidget ..|> WidgetProtocol : implements a\n    ValueWidget <|-- RangedWidget\n    ValueWidget <|-- ButtonWidget\n    ValueWidget <|-- CategoricalWidget\n    RangedWidget <|-- SliderWidget\n    Widget --* WidgetProtocol : controls a\n    <<Interface>> WidgetProtocol\n    class WidgetProtocol {\n        _mgui_get_X()\n        _mgui_set_X()\n    }\n    class Widget{\n        name: str\n        annotation: Any\n        label: str\n        tooltip: str\n        visible: bool\n        enabled: bool\n        native: Any\n        height: int\n        width: int\n        hide()\n        show()\n        close()\n        render()\n    }\n    class ValueWidget{\n        value: Any\n        changed: SignalInstance\n        bind(value, call) Any\n        unbind()\n    }\n    class RangedWidget{\n        value: float | tuple\n        min: float\n        max: float\n        step: float\n        adaptive_step: bool\n        range: tuple[float, float]\n    }\n    class SliderWidget{\n        orientation: str\n    }\n    class ButtonWidget{\n        value: bool\n        clicked: SignalInstance\n        text: str\n    }\n    class CategoricalWidget{\n        choices: List[Any]\n    }\n    class ContainerWidget{\n        widgets: List[Widget]\n        labels: bool\n        layout: str\n        margins: tuple[int, int, int, int]\n        reset_choices()\n        asdict() Dict[str, Any]\n        update(mapping)\n    }\n\n    click Widget href \"#magicgui.widgets.bases.Widget\"\n    click ValueWidget href \"#magicgui.widgets.bases.ValueWidget\"\n    click RangedWidget href \"#magicgui.widgets.bases.RangedWidget\"\n    click SliderWidget href \"#magicgui.widgets.bases.SliderWidget\"\n    click ButtonWidget href \"#magicgui.widgets.bases.ButtonWidget\"\n    click CategoricalWidget href \"#magicgui.widgets.bases.CategoricalWidget\"\n    click ContainerWidget href \"#magicgui.widgets.bases.ContainerWidget\"\n
"},{"location":"api/widgets/bases/#base-widget-classes","title":"Base Widget Classes","text":""},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget","title":"magicgui.widgets.bases.Widget","text":"

Basic Widget, wrapping a class that implements WidgetProtocol.

Parameters:

  • widget_type (type[WidgetProtocol]) \u2013

    A class implementing a widget protocol. Will be instantiated during init.

  • name (str, default: '' ) \u2013

    The name of the parameter represented by this widget. by default \"\"

  • annotation (Any, default: None ) \u2013

    The type annotation for the parameter represented by the widget, by default None

  • label (str, default: None ) \u2013

    A string to use for an associated Label widget (if this widget is being shown in a Container widget, and labels are on). By default, name will be used. Note: name refers the name of the parameter, as might be used in a signature, whereas label is just the label for that widget in the GUI.

  • tooltip (str, default: None ) \u2013

    A tooltip to display when hovering over the widget.

  • visible (bool, default: None ) \u2013

    Whether the widget is visible, by default True.

  • enabled (bool, default: True ) \u2013

    Whether the widget is enabled, by default True.

  • gui_only (bool, default: False ) \u2013

    If True, widget is excluded from any function signature representation. by default False. (This will likely be deprecated.)

  • parent (Any, default: None ) \u2013

    Optional parent widget of this widget. CAREFUL: if a parent is set, and subsequently deleted, this widget will likely be deleted as well (depending on the backend), and will no longer be usable.

  • backend_kwargs (dict, default: None ) \u2013

    keyword argument to pass to the backend widget constructor.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.annotation","title":"annotation: Any property writable","text":"

Return type annotation for the parameter represented by the widget.

ForwardRefs will be resolve when setting the annotation.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.enabled","title":"enabled: bool property writable","text":"

Whether widget is enabled (editable).

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.height","title":"height: int property writable","text":"

Return the current height of the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.label","title":"label: str property writable","text":"

Return a label to use for this widget when present in Containers.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.max_height","title":"max_height: int property writable","text":"

Get the maximum height of the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.max_width","title":"max_width: int property writable","text":"

Get the maximum width of the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.min_height","title":"min_height: int property writable","text":"

Get the minimum height of the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.min_width","title":"min_width: int property writable","text":"

Get the minimum width of the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.native","title":"native: Any property","text":"

Return native backend widget.

Note this is the widget that contains the layout, and not any parent widgets of this (e.g. a parent widget that is used to enable scroll bars)

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.options","title":"options: dict property","text":"

Return options currently being used in this widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.param_kind","title":"param_kind: inspect._ParameterKind property writable","text":"

Return :attr:inspect.Parameter.kind represented by this widget.

Used in building signatures from multiple widgets, by default :attr:~inspect.Parameter.POSITIONAL_OR_KEYWORD

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.parent","title":"parent: Widget property writable","text":"

Return the parent widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.parent_changed","title":"parent_changed: SignalInstance property","text":"

Signal emitted when the parent of the widget changes.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.root_native_widget","title":"root_native_widget: Any property","text":"

Return the root native backend widget.

This can be different from the .native widget if the layout is a child of some other widget, e.g. a widget used to enable scroll bars.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.tooltip","title":"tooltip: str | None property writable","text":"

Get the tooltip for this widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.visible","title":"visible: bool property writable","text":"

Return whether widget is visible.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.widget_type","title":"widget_type: str property","text":"

Return type of widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.width","title":"width: int property writable","text":"

Return the current width of the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.__repr__","title":"__repr__() -> str","text":"

Return representation of widget of instance.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.close","title":"close() -> None","text":"

Close widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.hide","title":"hide() -> None","text":"

Hide widget.

alias for widget.visible = False

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.render","title":"render() -> np.ndarray","text":"

Return an RGBA (MxNx4) numpy array bitmap of the rendered widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.show","title":"show(run: bool = False) -> Widget","text":"

Show widget.

alias for widget.visible = True

Parameters:

  • run (bool, default: False ) \u2013

    Whether to start the application event loop, by default False

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.Widget.shown","title":"shown() -> Iterator[Application]","text":"

Context manager to show the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ButtonWidget","title":"magicgui.widgets.bases.ButtonWidget","text":"

Bases: ValueWidget[bool]

Widget with a value, Wraps a widget implementing the ButtonWidgetProtocol.

see ButtonWidgetProtocol.

Parameters:

  • value (bool, default: Undefined ) \u2013

    The starting state of the widget.

  • text (str, default: None ) \u2013

    The text to display on the button. If not provided, will use name.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ButtonWidget.clicked","title":"clicked: SignalInstance property","text":"

Alias for changed event.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ButtonWidget.options","title":"options: dict property","text":"

Return options currently being used in this widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ButtonWidget.text","title":"text: str property writable","text":"

Text of the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.CategoricalWidget","title":"magicgui.widgets.bases.CategoricalWidget","text":"

Bases: ValueWidget[T]

Widget with a value and choices. Wraps CategoricalWidgetProtocol.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The initially selected choice.

  • choices (Enum, Iterable, or Callable, default: () ) \u2013

    Available choices displayed in the combo box.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.CategoricalWidget.choices","title":"choices: tuple[T | None, ...] property writable","text":"

Available value choices for this widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.CategoricalWidget.current_choice","title":"current_choice: str property","text":"

Return the text of the currently selected choice.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.CategoricalWidget.options","title":"options: dict property","text":"

Return options currently being used in this widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.CategoricalWidget.value","title":"value: T property writable","text":"

Return current value of the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.CategoricalWidget.__len__","title":"__len__() -> int","text":"

Return the number of choices.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.CategoricalWidget.del_choice","title":"del_choice(choice_name: str) -> None","text":"

Delete the provided choice_name and associated data.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.CategoricalWidget.get_choice","title":"get_choice(choice_name: str) -> T","text":"

Get data for the provided choice_name.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.CategoricalWidget.reset_choices","title":"reset_choices(*_: Any) -> None","text":"

Reset choices to the default state.

If self._default_choices is a callable, this may NOT be the exact same set of choices as when the widget was instantiated, if the callable relies on external state.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.CategoricalWidget.set_choice","title":"set_choice(choice_name: str, data: Any | None = None) -> None","text":"

Set data for the provided choice_name.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget","title":"magicgui.widgets.bases.ContainerWidget","text":"

Bases: Widget, _OrientationMixin, MutableSequence[WidgetVar]

Widget that can contain other widgets.

Wraps a widget that implements ContainerProtocol.

A ContainerWidget behaves like a python list of Widget objects. Subwidgets can be accessed using integer or slice-based indexing (container[0]), as well as by widget name (container.<widget_name>). Widgets can be added with append or insert, and removed with del or pop, etc...

There is a tight connection between a ContainerWidget and an inspect.Signature object, just as there is a tight connection between individual Widgetobjects an an :class:inspect.Parameter object. The signature representation of a ContainerWidget (with the current settings as default values) is accessible with the :meth:~ContainerWidget.__signature__ method (or by using :func:inspect.signature from the standard library)

For a ContainerWidget subclass that is tightly coupled to a specific function signature (as in the \"classic\" magicgui decorator), see magicgui.widgets.FunctionGui.

Parameters:

  • widgets (Sequence[Widget], default: () ) \u2013

    A sequence of widgets with which to initialize the container, by default None.

  • layout (str, default: 'vertical' ) \u2013

    The layout for the container. must be one of {'horizontal', 'vertical'}. by default \"vertical\"

  • scrollable (bool, default: False ) \u2013

    Whether to enable scroll bars or not. If enabled, scroll bars will only appear along the layout direction, not in both directions.

  • labels (bool, default: True ) \u2013

    Whether each widget should be shown with a corresponding Label widget to the left, by default True. Note: the text for each widget defaults to widget.name, but can be overridden by setting widget.label.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.__signature__","title":"__signature__: MagicSignature property","text":"

Return a MagicSignature object representing the current state of the gui.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.labels","title":"labels: bool property writable","text":"

Whether widgets are presented with labels.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.layout","title":"layout: str property writable","text":"

Return the layout of the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.margins","title":"margins: tuple[int, int, int, int] property writable","text":"

Return margin between the content and edges of the container.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.__delattr__","title":"__delattr__(name: str) -> None","text":"

Delete a widget by name.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.__delitem__","title":"__delitem__(key: int | slice) -> None","text":"

Delete a widget by integer or slice index.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.__dir__","title":"__dir__() -> list[str]","text":"

Add subwidget names to the dir() call for this widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.__getattr__","title":"__getattr__(name: str) -> WidgetVar","text":"

Return attribute name. Will return a widget if present.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.__getitem__","title":"__getitem__(key: int | str | slice) -> WidgetVar | MutableSequence[WidgetVar]","text":"

Get item by integer, str, or slice.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.__len__","title":"__len__() -> int","text":"

Return the count of widgets.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.__repr__","title":"__repr__() -> str","text":"

Return a repr.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.__setattr__","title":"__setattr__(name: str, value: Any) -> None","text":"

Set attribute name. Prevents changing widget if present, (use del).

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.__setitem__","title":"__setitem__(key: Any, value: Any) -> NoReturn","text":"

Prevent assignment by index.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.asdict","title":"asdict() -> dict[str, Any]","text":"

Return state of widget as dict.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.from_callable","title":"from_callable(obj: Callable, gui_options: dict | None = None, **kwargs: Unpack[ContainerKwargs]) -> Container classmethod","text":"

Create a Container widget from a callable object.

In most cases, it will be preferable to create a FunctionGui instead.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.from_signature","title":"from_signature(sig: inspect.Signature, **kwargs: Unpack[ContainerKwargs]) -> Container classmethod","text":"

Create a Container widget from an inspect.Signature object.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.index","title":"index(value: Any, start: int = 0, stop: int = 9223372036854775807) -> int","text":"

Return index of a specific widget instance (or widget name).

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.insert","title":"insert(key: int, widget: WidgetVar) -> None","text":"

Insert widget at key.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.remove","title":"remove(value: Widget | str) -> None","text":"

Remove a widget instance (may also be string name of widget).

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.reset_choices","title":"reset_choices(*_: Any) -> None","text":"

Reset choices for all Categorical subWidgets to the default state.

If widget._default_choices is a callable, this may NOT be the exact same set of choices as when the widget was instantiated, if the callable relies on external state.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ContainerWidget.update","title":"update(mapping: Mapping | Iterable[tuple[str, Any]] | None = None, **kwargs: Any) -> None","text":"

Update the parameters in the widget from a mapping, iterable, or kwargs.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.DialogWidget","title":"magicgui.widgets.bases.DialogWidget","text":"

Bases: ContainerWidget

Modal Container.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.DialogWidget.exec","title":"exec() -> bool","text":"

Show the dialog, and block.

Return True if the dialog was accepted, False if rejected.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.MainWindowWidget","title":"magicgui.widgets.bases.MainWindowWidget","text":"

Bases: ContainerWidget

Top level Application widget that can contain other widgets.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.MainWindowWidget.create_menu_item","title":"create_menu_item(menu_name: str, item_name: str, callback: Callable | None = None, shortcut: str | None = None) -> None","text":"

Create a menu item item_name under menu menu_name.

menu_name will be created if it does not already exist.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.RangedWidget","title":"magicgui.widgets.bases.RangedWidget","text":"

Bases: ValueWidget[T]

Widget with a constrained value. Wraps RangedWidgetProtocol.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • min (float, default: Undefined ) \u2013

    The minimum allowable value, by default 0 (or value if value is less than 0)

  • max (float, default: Undefined ) \u2013

    The maximum allowable value, by default 999 (or value if value is greater than 999)

  • step (float, default: Undefined ) \u2013

    The step size for incrementing the value, by default adaptive step is used

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.RangedWidget.adaptive_step","title":"adaptive_step: bool property writable","text":"

Whether the step size is adaptive.

Adaptive decimal step means that the step size will continuously be adjusted to one power of ten below the current value. So when the value is 1100, the step is set to 100, so stepping up once increases it to 1200. For 1200 stepping up takes it to 1300. For negative values, stepping down from -1100 goes to -1200.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.RangedWidget.max","title":"max: float property writable","text":"

Maximum allowable value for the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.RangedWidget.min","title":"min: float property writable","text":"

Minimum allowable value for the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.RangedWidget.options","title":"options: dict property","text":"

Return options currently being used in this widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.RangedWidget.range","title":"range: tuple[float, float] property writable","text":"

Range of allowable values for the widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.RangedWidget.step","title":"step: float | None property writable","text":"

Step size for widget values (None if adaptive step is turned on).

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.RangedWidget.value","title":"value(value: T) -> None","text":"

Set widget value, will raise Value error if not within min/max.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.SliderWidget","title":"magicgui.widgets.bases.SliderWidget","text":"

Bases: RangedWidget[T], _OrientationMixin

Widget with a constrained value and orientation. Wraps SliderWidgetProtocol.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • min (float, default: Undefined ) \u2013

    The minimum allowable value, by default 0 (or value if value is less than 0)

  • max (float, default: Undefined ) \u2013

    The maximum allowable value, by default 999 (or value if value is greater than 999)

  • step (float, default: Undefined ) \u2013

    The step size for incrementing the value, by default adaptive step is used

  • orientation ((str, {'horizontal', 'vertical'}), default: 'horizontal' ) \u2013

    The orientation for the slider, by default \"horizontal\"

  • readout (bool, default: True ) \u2013

    Whether to show the editable spinbox next to the slider

  • tracking (bool, default: True ) \u2013

    If tracking is enabled (the default), the slider emits the changed signal while the slider is being dragged. If tracking is disabled, the slider emits the changed signal only after the user releases the slider.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.SliderWidget.options","title":"options: dict property","text":"

Return options currently being used in this widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.SliderWidget.readout","title":"readout: bool property writable","text":"

Get visibility state of readout widget.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.SliderWidget.tracking","title":"tracking: bool property writable","text":"

Return whether slider tracking is enabled.

If tracking is enabled (the default), the slider emits the changed() signal while the slider is being dragged. If tracking is disabled, the slider emits the changed() signal only when the user releases the slider.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ValueWidget","title":"magicgui.widgets.bases.ValueWidget","text":"

Bases: Widget, Generic[T]

Widget with a value, Wraps ValueWidgetProtocol.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget.

  • bind (Callable[[ValueWidget], Any] | Any, default: Undefined ) \u2013

    A value or callback to bind this widget. If provided, whenever widget.value is accessed, the value provided here will be returned instead. bind may be a callable, in which case bind(self) will be returned (i.e. your bound callback must accept a single parameter, which is this widget instance).

  • nullable (bool, default: False ) \u2013

    If True, the widget will accepts None as a valid value, by default False.

  • **base_widget_kwargs (Any, default: {} ) \u2013

    All additional keyword arguments are passed to the base magicgui.widgets.Widget constructor.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ValueWidget.annotation","title":"annotation: Any property writable","text":"

Return type annotation for the parameter represented by the widget.

ForwardRefs will be resolve when setting the annotation. If the widget is nullable (had a type annototation of Optional[Type]), annotation will return the first argument in the Optional clause.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ValueWidget.value","title":"value: T property writable","text":"

Return current value of the widget. This may be interpreted by backends.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ValueWidget.__repr__","title":"__repr__() -> str","text":"

Return representation of widget of instance.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ValueWidget.bind","title":"bind(value: T | Callable[[ValueWidget], T], call: bool = True) -> None","text":"

Binds value to self.value.

If a value is bound to this widget, then whenever widget.value is accessed, the value provided here will be returned. value can be a callable, in which case value(self) will be returned (i.e. your callback must accept a single parameter, which is this widget instance.).

If you provide a callable and you don't want it to be called (but rather just returned as a callable object, then use call=False when binding your value.

Note: if you need to access the \"original\" widget.value within your callback, please use widget.get_value() instead of the widget.value property, in order to avoid a RuntimeError.

Parameters:

  • value (Any) \u2013

    The value (or callback) to return when accessing this widget's value.

  • call (bool, default: True ) \u2013

    If value is a callable and call is True, the callback will be called as callback(self) when accessing self.value. If False, the callback will simply be returned as a callable object, by default, True.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ValueWidget.get_value","title":"get_value() -> T","text":"

Callable version of self.value.

The main API is to use self.value, however, this is here in order to provide an escape hatch if trying to access the widget's value inside of a callback bound to self._bound_value.

"},{"location":"api/widgets/bases/#magicgui.widgets.bases.ValueWidget.unbind","title":"unbind() -> None","text":"

Unbinds any bound values. (see ValueWidget.bind).

"},{"location":"api/widgets/create_widget/","title":"magicgui.widgets.create_widget","text":""},{"location":"api/widgets/create_widget/#magicgui.widgets.create_widget","title":"magicgui.widgets.create_widget(value=Undefined, annotation=None, name='', param_kind='POSITIONAL_OR_KEYWORD', label=None, gui_only=False, app=None, widget_type=None, options=None, is_result=False, raise_on_unknown=True)","text":"

Create and return appropriate widget subclass.

This factory function can be used to create a widget appropriate for the provided value and/or annotation provided. See Type Mapping Docs for details on how the widget type is determined from type annotations.

Parameters:

  • value (Any, default: Undefined ) \u2013

    The starting value for the widget, by default None

  • annotation (Any, default: None ) \u2013

    The type annotation for the parameter represented by the widget, by default None.

  • name (str, default: '' ) \u2013

    The name of the parameter represented by this widget. by default \"\"

  • param_kind (str, default: 'POSITIONAL_OR_KEYWORD' ) \u2013

    The :attr:inspect.Parameter.kind represented by this widget. Used in building signatures from multiple widgets, by default \"POSITIONAL_OR_KEYWORD\"

  • label (str, default: None ) \u2013

    A string to use for an associated Label widget (if this widget is being shown in a Container widget, and labels are on). By default, name will be used. Note: name refers the name of the parameter, as might be used in a signature, whereas label is just the label for that widget in the GUI.

  • gui_only (bool, default: False ) \u2013

    Whether the widget should be considered \"only for the gui\", or if it should be included in any widget container signatures, by default False

  • app (str, default: None ) \u2013

    The backend to use, by default None

  • widget_type (str or Type[WidgetProtocol] or None, default: None ) \u2013

    A class implementing a widget protocol or a string with the name of a magicgui widget type (e.g. \"Label\", \"PushButton\", etc...). If provided, this widget type will be used instead of the type autodetermined from value and/or annotation above.

  • options (dict, default: None ) \u2013

    Dict of options to pass to the Widget constructor, by default dict()

  • is_result (boolean, default: False ) \u2013

    Whether the widget belongs to an input or an output. By default, an input is assumed.

  • raise_on_unknown (bool, default: True ) \u2013

    Raise exception if no widget is found for the given type, by default True

Returns:

  • Widget \u2013

    An instantiated widget subclass

Raises:

  • TypeError \u2013

    If the provided or autodetected widget_type does not implement any known widget protocols

Examples:

from magicgui.widgets import create_widget\n\n# create a widget from a string value\nwdg = create_widget(value=\"hello world\")\nassert wdg.value == \"hello world\"\n\n# create a widget from a string annotation\nwdg = create_widget(annotation=str)\nassert wdg.value == \"\"\n
"},{"location":"generated_examples/","title":"Examples","text":""},{"location":"generated_examples/#getting-started","title":"Getting started","text":"

A gallery of examples for magicgui.

Basic example

Basic widgets demo

"},{"location":"generated_examples/#demo-applications","title":"Demo applications","text":"

Example applications built with magicgui.

Input values dialog

Quantities with pint

Callable functions demo

Snell's law demonstration using magicgui

Hotdog or not app

Chaining functions together

"},{"location":"generated_examples/#demo-widget-types","title":"Demo widget types","text":"

Example gallery demonstrating the available widget types in magicgui.

Image widget

Custom text labels for widgets

Range slider widget

Log slider widget

Optional user choice

Multiple selection widget

Password login

File dialog widget

Dropdown selection widget

Table widget

"},{"location":"generated_examples/#matplotlib-and-magicgui","title":"matplotlib and magicgui","text":"

Examples involving matplotlib graphs and magicgui.

matplotlib figure example

Waveforms example

"},{"location":"generated_examples/#napari-and-magicgui","title":"napari and magicgui","text":"

Examples integrating magicgui with napari.

napari forward reference demo

napari Qt demo

napari parameter sweeps

napari image arithmetic widget

"},{"location":"generated_examples/#jupyter-notebooks-and-magicgui","title":"Jupyter notebooks and magicgui","text":"

Examples using jupyter notebooks together with magicgui.

Jupyter notebooks and magicgui

"},{"location":"generated_examples/#progress-bar-examples","title":"Progress bar examples","text":"

Examples of progress bars in magicgui.

Manual progress bar

Simple progress bar

Indeterminate progress bar

Nested progress bars

"},{"location":"generated_examples/#under-the-hood","title":"Under the hood","text":"

Learn more advanced usage patterns for magicgui, including self referencing widgets and decorating class methods with magicgui.

Self reference magicgui widgets

Deocrate class methods with magicgui

Download all examples in Python source code: generated_examples_python.zip

Download all examples in Jupyter notebooks: generated_examples_jupyter.zip

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/basic_example/","title":"Basic example","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/basic_example/#basic-example","title":"Basic example","text":"

A basic example using magicgui.

Out:

<FunctionGui example(x: int = 0, y='hi')>\n

from magicgui import magicgui\n\n\n@magicgui\ndef example(x: int, y=\"hi\"):\n    \"\"\"Basic example function.\"\"\"\n    return x, y\n\n\nexample.changed.connect(print)\nexample.show(run=True)\n

Total running time of the script: ( 0 minutes 0.740 seconds)

Download Python source code: basic_example.py

Download Jupyter notebook: basic_example.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/basic_widgets_demo/","title":"Basic widgets demo","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/basic_widgets_demo/#basic-widgets-demo","title":"Basic widgets demo","text":"

Widget demonstration with magicgui.

This code demonstrates a few of the widget types that magicgui can create based on the parameter types in your function.

Out:

<MainFunctionGui widget_demo(boolean=True, integer=1, spin_float=3.14, slider_float=43.5, slider_int=550, string='Text goes here', dropdown=<Medium.Glass: 1.52>, radio_option=2, date=datetime.date(1999, 12, 31), time=datetime.time(1, 30, 20), datetime=datetime.datetime(2024, 3, 5, 17, 57, 54, 926000), filename=PosixPath('/Users/runner'))>\n

import datetime\nfrom enum import Enum\nfrom pathlib import Path\n\nfrom magicgui import magicgui\n\n\nclass Medium(Enum):\n    \"\"\"Enum for various media and their refractive indices.\"\"\"\n\n    Glass = 1.520\n    Oil = 1.515\n    Water = 1.333\n    Air = 1.0003\n\n\n@magicgui(\n    main_window=True,\n    call_button=\"Calculate\",\n    layout=\"vertical\",\n    result_widget=True,\n    slider_float={\"widget_type\": \"FloatSlider\", \"max\": 100},\n    slider_int={\"widget_type\": \"Slider\", \"readout\": False},\n    radio_option={\n        \"widget_type\": \"RadioButtons\",\n        \"orientation\": \"horizontal\",\n        \"choices\": [(\"first option\", 1), (\"second option\", 2)],\n    },\n    filename={\"label\": \"Pick a file:\"},\n)\ndef widget_demo(\n    boolean=True,\n    integer=1,\n    spin_float=3.14159,\n    slider_float=43.5,\n    slider_int=550,\n    string=\"Text goes here\",\n    dropdown=Medium.Glass,\n    radio_option=2,\n    date=datetime.date(1999, 12, 31),\n    time=datetime.time(1, 30, 20),\n    datetime=datetime.datetime.now(),\n    filename=Path.home(),\n):\n    \"\"\"We can use numpy docstrings to provide tooltips.\n\n    Parameters\n    ----------\n    boolean : bool, optional\n        A checkbox for booleans, by default True\n    integer : int, optional\n        Some integer, by default 1\n    spin_float : float, optional\n        This one is a float, by default \"pi\"\n    slider_float : float, optional\n        Hey look! I'm a slider, by default 43.5\n    slider_int : float, optional\n        I only take integers, and I've hidden my readout, by default 550\n    string : str, optional\n        We'll use this string carefully, by default \"Text goes here\"\n    dropdown : Enum, optional\n        Pick a medium, by default Medium.Glass\n    radio_option : int\n        A set of radio buttons.\n    date : datetime.date, optional\n        Your birthday, by default datetime.date(1999, 12, 31)\n    time : datetime.time, optional\n        Some time, by default datetime.time(1, 30, 20)\n    datetime : datetime.datetime, optional\n        A very specific time and date, by default ``datetime.datetime.now()``\n    filename : str, optional\n        Pick a path, by default Path.home()\n    \"\"\"\n    return locals().values()\n\n\nwidget_demo.changed.connect(print)\nwidget_demo.show(run=True)\n

Total running time of the script: ( 0 minutes 0.131 seconds)

Download Python source code: basic_widgets_demo.py

Download Jupyter notebook: basic_widgets_demo.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/mg_execution_times/","title":"Computation times","text":"

00:00.871 total execution time for generated_examples files:

+-------------------------------------------------------------------------------------+-----------+--------+ | basic_example (docs/examples/basic_example.py) | 00:00.740 | 0.0 MB | +-------------------------------------------------------------------------------------+-----------+--------+ | basic_widgets_demo (docs/examples/basic_widgets_demo.py) | 00:00.131 | 0.0 MB | +-------------------------------------------------------------------------------------+-----------+--------+

"},{"location":"generated_examples/applications/callable/","title":"Callable functions demo","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/applications/callable/#callable-functions-demo","title":"Callable functions demo","text":"

This example demonstrates handling callable functions with magicgui.

Out:

<FunctionGui example(func='f')>\n

from magicgui import magicgui\n\n\ndef f(x: int, y=\"a string\") -> str:\n    \"\"\"Example function F.\"\"\"\n    return f\"{y} {x}\"\n\n\ndef g(x: int = 6, y=\"another string\") -> str:\n    \"\"\"Example function G.\"\"\"\n    return f\"{y} asdfsdf {x}\"\n\n\n@magicgui(call_button=True, func={\"choices\": [\"f\", \"g\"]})\ndef example(func=\"f\"):\n    \"\"\"\u00cbxample function.\"\"\"\n    pass\n\n\ndef update(f: str):\n    \"\"\"Update function.\"\"\"\n    if len(example) > 2:\n        del example[1]\n    example.insert(1, magicgui(globals()[f]))\n\n\nexample.func.changed.connect(update)\nexample.show(run=True)\n

Total running time of the script: ( 0 minutes 0.031 seconds)

Download Python source code: callable.py

Download Jupyter notebook: callable.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/applications/chaining/","title":"Chaining functions together","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/applications/chaining/#chaining-functions-together","title":"Chaining functions together","text":"

This example demonstrates chaining multiple functions together.

Out:

calling func_a\ncalling func_b\ncalling func_c\n\n\n<Container (func_a: NoneType, func_b: NoneType, func_c: NoneType)>\n

from magicgui import magicgui, widgets\n\n\n@magicgui(auto_call=True)\ndef func_a(x: int = 64, y: int = 64):\n    \"\"\"Callable function A.\"\"\"\n    print(\"calling func_a\")\n    return x + y\n\n\n@magicgui(auto_call=True, input={\"visible\": False, \"label\": \" \", \"max\": 100000})\ndef func_b(input: int, mult=1.0):\n    \"\"\"Callable function B.\"\"\"\n    print(\"calling func_b\")\n    result = input * mult\n    # since these function defs live in globals(), you can update them directly\n    func_c.input.value = result\n    return result\n\n\n# alternatively, you can the `widget.called` signal to connect a callback function\n# where the result of the function being called is at `value`\n@func_a.called.connect\ndef _on_func_a(value: str):\n    func_b.input.value = value\n\n\n@magicgui(\n    auto_call=True,\n    input={\"visible\": False, \"max\": 100000},\n    result_widget=True,\n    labels=False,\n)\ndef func_c(input: int, format: str = \"({} + {}) * {} is {}\") -> str:\n    \"\"\"Callable function C.\"\"\"\n    print(\"calling func_c\\n\")\n    return format.format(func_a.x.value, func_a.y.value, func_b.mult.value, input)\n\n\ncontainer = widgets.Container(\n    widgets=[func_a, func_b, func_c], layout=\"vertical\", labels=False\n)\ncontainer.native.setMinimumWidth(500)\nfunc_a()\ncontainer.show(run=True)\n\n# notice which functions get called when you change each widget.\n

Total running time of the script: ( 0 minutes 0.048 seconds)

Download Python source code: chaining.py

Download Jupyter notebook: chaining.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/applications/hotdog/","title":"Hotdog or not app","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/applications/hotdog/#hotdog-or-not-app","title":"Hotdog or not app","text":"

Demo app to upload an image and classify if it's an hotdog or not.

import pathlib\nfrom enum import Enum\n\nfrom magicgui import magicgui\n\n\nclass HotdogOptions(Enum):\n    \"\"\"All hotdog possibilities.\"\"\"\n\n    Hotdog = 1\n    NotHotdog = 0\n\n\n@magicgui(main_window=True, layout=\"form\", call_button=\"Classify\", result_widget=True)\ndef is_hotdog(img: pathlib.Path) -> HotdogOptions:\n    \"\"\"Classify possible hotdog images.\n\n    Upload an image and check whether it's an hotdog. For example, this image\n    will be classified as one: <br><br>\n\n    <img src=\"resources/hotdog.jpg\">\n\n    Parameters\n    ----------\n    img : pathlib.Path\n        Path to a possible hotdog image\n\n    Returns\n    -------\n    HotdogOptions\n        True if image contains an hotdog in it\n    \"\"\"\n    if \"hotdog\" in img.stem:\n        return HotdogOptions.Hotdog\n    return HotdogOptions.NotHotdog\n\n\nif __name__ == \"__main__\":\n    is_hotdog.show(run=True)\n

Total running time of the script: ( 0 minutes 0.042 seconds)

Download Python source code: hotdog.py

Download Jupyter notebook: hotdog.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/applications/mg_execution_times/","title":"Computation times","text":"

00:00.841 total execution time for generated_examples_applications files:

+-----------------------------------------------------------------------------------+-----------+--------+ | pint_quantity (docs/examples/applications/pint_quantity.py) | 00:00.670 | 0.0 MB | +-----------------------------------------------------------------------------------+-----------+--------+ | snells_law (docs/examples/applications/snells_law.py) | 00:00.050 | 0.0 MB | +-----------------------------------------------------------------------------------+-----------+--------+ | chaining (docs/examples/applications/chaining.py) | 00:00.048 | 0.0 MB | +-----------------------------------------------------------------------------------+-----------+--------+ | hotdog (docs/examples/applications/hotdog.py) | 00:00.042 | 0.0 MB | +-----------------------------------------------------------------------------------+-----------+--------+ | callable (docs/examples/applications/callable.py) | 00:00.031 | 0.0 MB | +-----------------------------------------------------------------------------------+-----------+--------+ | values_dialog (docs/examples/applications/values_dialog.py) | 00:00.000 | 0.0 MB | +-----------------------------------------------------------------------------------+-----------+--------+

"},{"location":"generated_examples/applications/pint_quantity/","title":"Quantities with pint","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/applications/pint_quantity/#quantities-with-pint","title":"Quantities with pint","text":"

Pint is a Python package to define, operate and manipulate physical quantities: the product of a numerical value and a unit of measurement. It allows arithmetic operations between them and conversions from and to different units. https://pint.readthedocs.io/en/stable/

Out:

<FunctionGui widget(q=<Quantity(1, 'millisecond')>)>\n

from pint import Quantity\n\nfrom magicgui import magicgui\n\n\n@magicgui\ndef widget(q=Quantity(\"1 ms\")):\n    \"\"\"Widget allowing users to input quantity measurements.\"\"\"\n    print(q)\n\n\nwidget.show(run=True)\n

Total running time of the script: ( 0 minutes 0.670 seconds)

Download Python source code: pint_quantity.py

Download Jupyter notebook: pint_quantity.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/applications/snells_law/","title":"Snell's law demonstration using magicgui","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/applications/snells_law/#snells-law-demonstration-using-magicgui","title":"Snell's law demonstration using magicgui","text":"

Demo app for calculating angles of refraction according to Snell's law.

Out:

<FunctionGui snells_law(aoi=1.0, n1=<Medium.Glass: 1.52>, n2=<Medium.Water: 1.333>, degrees=True)>\n

import math\nfrom enum import Enum\n\nfrom magicgui import magicgui\n\n\nclass Medium(Enum):\n    \"\"\"Enum for various media and their refractive indices.\"\"\"\n\n    Glass = 1.520\n    Oil = 1.515\n    Water = 1.333\n    Air = 1.0003\n\n\n@magicgui(call_button=\"calculate\", result_widget=True)\ndef snells_law(aoi=1.0, n1=Medium.Glass, n2=Medium.Water, degrees=True):\n    \"\"\"Calculate the angle of refraction given two media and an AOI.\"\"\"\n    if degrees:\n        aoi = math.radians(aoi)\n    try:\n        n1 = n1.value\n        n2 = n2.value\n        result = math.asin(n1 * math.sin(aoi) / n2)\n        return round(math.degrees(result) if degrees else result, 2)\n    except ValueError:  # math domain error\n        return \"TIR!\"\n\n\nsnells_law.show(run=True)\n

Total running time of the script: ( 0 minutes 0.050 seconds)

Download Python source code: snells_law.py

Download Jupyter notebook: snells_law.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/applications/values_dialog/","title":"Input values dialog","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/applications/values_dialog/#input-values-dialog","title":"Input values dialog","text":"

A basic example of a user input dialog.

This will pause code execution until the user responds.

"},{"location":"generated_examples/applications/values_dialog/#_1","title":"Input values dialog","text":"
from magicgui.widgets import request_values\n\nvals = request_values(\n    age=int,\n    name={\"annotation\": str, \"label\": \"Enter your name:\"},\n    title=\"Hi, who are you?\",\n)\nprint(repr(vals))\n

Total running time of the script: ( 0 minutes 0.000 seconds)

Download Python source code: values_dialog.py

Download Jupyter notebook: values_dialog.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/demo_widgets/change_label/","title":"Custom text labels for widgets","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/demo_widgets/change_label/#custom-text-labels-for-widgets","title":"Custom text labels for widgets","text":"

An example showing how to create custom text labels for your widgets.

Out:

<FunctionGui example(x=1, y='hi')>\n

from magicgui import magicgui\n\n\n# use a different label than the default (the parameter name) in the UI\n@magicgui(x={\"label\": \"widget to set x\"})\ndef example(x=1, y=\"hi\"):\n    \"\"\"Example function.\"\"\"\n    return x, y\n\n\nexample.changed.connect(print)\nexample.show(run=True)\n

Total running time of the script: ( 0 minutes 0.034 seconds)

Download Python source code: change_label.py

Download Jupyter notebook: change_label.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/demo_widgets/choices/","title":"Dropdown selection widget","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/demo_widgets/choices/#dropdown-selection-widget","title":"Dropdown selection widget","text":"

Choices for dropdowns can be provided in a few different ways.

Out:

<Container (as_list: NoneType, as_enum: NoneType, as_2tuple: NoneType, as_function: NoneType)>\n

from enum import Enum\n\nfrom magicgui import magicgui, widgets\n\n\nclass Medium(Enum):\n    \"\"\"Enum for various media and their refractive indices.\"\"\"\n\n    Oil = 1.515\n    Water = 1.333\n    Air = 1.0003\n\n\n@magicgui(ri={\"choices\": [\"Oil\", \"Water\", \"Air\"]}, auto_call=True)\ndef as_list(ri=\"Water\"):\n    \"\"\"Function decorated with magicgui list of choices.\"\"\"\n    print(\"refractive index is\", Medium[ri].value)\n\n\n@magicgui(auto_call=True)\ndef as_enum(ri: Medium = Medium.Water):\n    \"\"\"Function decorated with magicgui and enumeration.\"\"\"\n    print(\"refractive index is\", ri.value)\n\n\n@magicgui(\n    ri={\"choices\": [(\"Oil\", 1.515), (\"Water\", 1.33), (\"Air\", 1.0)]}, auto_call=True\n)\ndef as_2tuple(ri=1.33):\n    \"\"\"Function decorated with magicgui tuple of choices.\"\"\"\n    print(\"refractive index is\", ri)\n\n\ndef get_choices(gui):\n    \"\"\"Function returning tuple of material and refractive index value.\"\"\"\n    return [(\"Oil\", 1.515), (\"Water\", 1.33), (\"Air\", 1.0)]\n\n\n@magicgui(ri={\"choices\": get_choices}, auto_call=True)\ndef as_function(ri: float):\n    \"\"\"Function to calculate refractive index.\"\"\"\n    print(\"refractive index is\", ri)\n\n\ncontainer = widgets.Container(\n    widgets=[as_list, as_enum, as_2tuple, as_function], layout=\"vertical\"\n)\ncontainer.show(run=True)\n

Total running time of the script: ( 0 minutes 0.060 seconds)

Download Python source code: choices.py

Download Jupyter notebook: choices.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/demo_widgets/file_dialog/","title":"File dialog widget","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/demo_widgets/file_dialog/#file-dialog-widget","title":"File dialog widget","text":"

A file dialog widget example.

    %s
* ![file dialog](../images/mkd_glr_file_dialog_001.png){: .mkd-glr-multi-img srcset=\"../images/mkd_glr_file_dialog_001.png\"}\n\n* ![file dialog](../images/mkd_glr_file_dialog_002.png){: .mkd-glr-multi-img srcset=\"../images/mkd_glr_file_dialog_002.png\"}\n\n* ![file dialog](../images/mkd_glr_file_dialog_003.png){: .mkd-glr-multi-img srcset=\"../images/mkd_glr_file_dialog_003.png\"}\n
from pathlib import Path\nfrom typing import Sequence\n\nfrom magicgui import magicgui, use_app\n\n\n@magicgui(filename={\"mode\": \"r\"})\ndef filepicker(filename=Path(\"~\")):\n    \"\"\"Take a filename and do something with it.\"\"\"\n    print(\"The filename is:\", filename)\n    return filename\n\n\n# Sequence of paths\n# We change the label using \"label\" for added clarity\n# the filter argument restricts file types\n@magicgui(filenames={\"label\": \"Choose Tiff files:\", \"filter\": \"*.tif\"})\ndef filespicker(filenames: Sequence[Path]):\n    \"\"\"Take a filename and do something with it.\"\"\"\n    print(\"The filenames are:\", filenames)\n    return filenames\n\n\n# Select a directory, instead of file(s)\n@magicgui(directory={\"mode\": \"d\", \"label\": \"Choose a directory\"})\ndef directorypicker(directory=Path(\"~\")):\n    \"\"\"Take a directory name and do something with it.\"\"\"\n    print(\"The directory name is:\", directory)\n    return directory\n\n\nfilepicker.show()\nfilespicker.show()\ndirectorypicker.show()\nfilepicker.filename.changed.connect(print)\nfilespicker.filenames.changed.connect(print)\ndirectorypicker.directory.changed.connect(print)\n\nuse_app().run()\n

Total running time of the script: ( 0 minutes 0.084 seconds)

Download Python source code: file_dialog.py

Download Jupyter notebook: file_dialog.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/demo_widgets/image/","title":"Image widget","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/demo_widgets/image/#image-widget","title":"Image widget","text":"

Example of creating an Image Widget from a file.

(This requires pillow, or that magicgui was installed as magicgui[image])

Out:

Image(200x232x3, name='')\n

from magicgui.widgets import Image\n\nimage = Image(value=\"../../images/_test.jpg\")\nimage.scale_widget_to_image_size()\nimage.show(run=True)\n

Total running time of the script: ( 0 minutes 0.038 seconds)

Download Python source code: image.py

Download Jupyter notebook: image.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/demo_widgets/log_slider/","title":"Log slider widget","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/demo_widgets/log_slider/#log-slider-widget","title":"Log slider widget","text":"

A logarithmic scale range slider widget.

Out:

<FunctionGui slider(input=1.0)>\n

from magicgui import magicgui\n\n\n@magicgui(\n    auto_call=True,\n    result_widget=True,\n    input={\"widget_type\": \"LogSlider\", \"max\": 10000, \"min\": 1, \"tracking\": False},\n)\ndef slider(input=1):\n    \"\"\"Logarithmic scale slider.\"\"\"\n    return round(input, 4)\n\n\nslider.show(run=True)\n

Total running time of the script: ( 0 minutes 0.032 seconds)

Download Python source code: log_slider.py

Download Jupyter notebook: log_slider.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/demo_widgets/login/","title":"Password login","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/demo_widgets/login/#password-login","title":"Password login","text":"

A password login field widget.

Out:

<FunctionGui login(username: str = '', password: str = '', password2: str = '')>\n

from magicgui import magicgui\n\n\n# note that \"password\" is a special keyword argument\n# it will create a password field in the gui by default\n# (unless you override \"widget_type\")\n# whereas \"password2\" will be a normal text field\n# (unless you override \"widget_type\")\n@magicgui(password2={\"widget_type\": \"Password\"})\ndef login(username: str, password: str, password2: str):\n    \"\"\"User login credentials.\"\"\"\n    ...\n\n\nlogin.show(run=True)\n

Total running time of the script: ( 0 minutes 0.033 seconds)

Download Python source code: login.py

Download Jupyter notebook: login.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/demo_widgets/mg_execution_times/","title":"Computation times","text":"

00:00.424 total execution time for generated_examples_demo_widgets files:

+--------------------------------------------------------------------------------+-----------+--------+ | file_dialog (docs/examples/demo_widgets/file_dialog.py) | 00:00.084 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ | choices (docs/examples/demo_widgets/choices.py) | 00:00.060 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ | range_slider (docs/examples/demo_widgets/range_slider.py) | 00:00.045 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ | table (docs/examples/demo_widgets/table.py) | 00:00.038 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ | image (docs/examples/demo_widgets/image.py) | 00:00.038 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ | change_label (docs/examples/demo_widgets/change_label.py) | 00:00.034 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ | login (docs/examples/demo_widgets/login.py) | 00:00.033 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ | selection (docs/examples/demo_widgets/selection.py) | 00:00.032 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ | log_slider (docs/examples/demo_widgets/log_slider.py) | 00:00.032 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+ | optional (docs/examples/demo_widgets/optional.py) | 00:00.031 | 0.0 MB | +--------------------------------------------------------------------------------+-----------+--------+

"},{"location":"generated_examples/demo_widgets/optional/","title":"Optional user choice","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/demo_widgets/optional/#optional-user-choice","title":"Optional user choice","text":"

Optional user input using a dropdown selection widget.

Out:

<FunctionGui f(path: str = None)>\n

from typing import Optional\n\nfrom magicgui import magicgui\n\n\n# Using optional will add a '----' to the combobox, which returns \"None\"\n@magicgui(path={\"choices\": [\"a\", \"b\"]})\ndef f(path: Optional[str] = None):\n    \"\"\"\u00d6ptional user input function.\"\"\"\n    print(path, type(path))\n\n\nf.show(run=True)\n

Total running time of the script: ( 0 minutes 0.031 seconds)

Download Python source code: optional.py

Download Jupyter notebook: optional.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/demo_widgets/range_slider/","title":"Range slider widget","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/demo_widgets/range_slider/#range-slider-widget","title":"Range slider widget","text":"

A double ended range slider widget.

Out:

<FunctionGui func(range_value: Tuple[int, int] = (20, 380))>\n

from typing import Tuple\n\nfrom magicgui import magicgui\n\n\n@magicgui(auto_call=True, range_value={\"widget_type\": \"RangeSlider\", \"max\": 500})\ndef func(range_value: Tuple[int, int] = (20, 380)):\n    \"\"\"Double ended range slider.\"\"\"\n    print(range_value)\n\n\nfunc.show(run=True)\n

Total running time of the script: ( 0 minutes 0.045 seconds)

Download Python source code: range_slider.py

Download Jupyter notebook: range_slider.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/demo_widgets/selection/","title":"Multiple selection widget","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/demo_widgets/selection/#multiple-selection-widget","title":"Multiple selection widget","text":"

A selection widget allowing multiple selections by the user.

Out:

<FunctionGui my_widget(pick_some=['first'])>\n

from magicgui import magicgui\n\n\n@magicgui(\n    pick_some={\n        \"choices\": (\"first\", \"second\", \"third\", \"fourth\"),\n        \"allow_multiple\": True,\n    }\n)\ndef my_widget(pick_some=(\"first\")):\n    \"\"\"Dropdown selection function.\"\"\"\n    print(\"you selected\", pick_some)\n\n\nmy_widget.show(run=True)\n

Total running time of the script: ( 0 minutes 0.032 seconds)

Download Python source code: selection.py

Download Jupyter notebook: selection.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/demo_widgets/table/","title":"Table widget","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/demo_widgets/table/#table-widget","title":"Table widget","text":"

Demonstrating a few ways to input tables.

Out:

Table(shape=(6, 3) at 0x13360bf20)\n

import numpy as np\n\nfrom magicgui.widgets import Table\n\n# all of these are valid data types\ndict_of_lists = {\"col_1\": [1, 4], \"col_2\": [2, 5], \"col_3\": [3, 6]}\n# column-dict-of-row-dicts\ndict_of_dict = {\n    \"col_1\": {\"r1\": 1, \"r2\": 4},\n    \"col_2\": {\"r1\": 2, \"r2\": 5},\n    \"col_3\": {\"r1\": 3, \"r2\": 6},\n}\n# list-of-lists\nlist_of_list = [[1, 2, 3], [4, 5, 6]]\n# Records: List-of-column-dict\nlist_of_records = [\n    {\"col_1\": 1, \"col_2\": 2, \"col_3\": 3},\n    {\"col_1\": 4, \"col_2\": 5, \"col_3\": 6},\n]\n\n# 3-tuple of data, index, column\ndata_index_column_tuple = (([[1, 2, 3], [4, 5, 6]], (\"r1\", \"r2\"), (\"c1\", \"c2\", \"c3\")),)\n# split-dict\nsplit_dict = {\n    \"data\": [[1, 2, 3], [4, 5, 6]],\n    \"index\": (\"r1\", \"r2\"),\n    \"columns\": (\"c1\", \"c2\", \"c3\"),\n}\n\ntable = Table(value=dict_of_lists)\n\n# it behaves like a dict:\ntable[\"new_col\"] = [5, 5]\nassert table.pop(\"new_col\") == [5, 5]\n# keys and items have both regular (column) and \"row\" modes\ncol_item_view = table.items()  # iterate col_header/column\nrow_item_view = table.items(\"row\")  # iterate row_header/row\n\n# we can just call dict() to get back our dict of lists\nassert dict(table) == dict_of_lists\n# or use one of many other exports in `to_dict`\nassert table.to_dict(\"records\") == list_of_records\n\n# change headers\ntable.row_headers = (\"row1\", \"row2\")\ntable.column_headers = (\"a\", \"b\", \"c\")\n\n# setting value clears and resets the table:\ntable.value = np.arange(18).reshape(6, 3)\n# we can get/set/delete the 2D data table using numpy-style indexing:\n# get every other row\nassert table.data[::2] == [[0, 1, 2], [6, 7, 8], [12, 13, 14]]\n# set every other column in the 3rd row\ntable.data[2, ::2] = [99, 99]\n\n# export to numpy or pandas\n# table.data.to_numpy()\n# table.to_dataframe()\n\n# the table.changed event emits a dict of information on any cell change\n# e.g. {'data': 'sdfg', 'row': 1, 'column': 0, 'column_header': '1', 'row_header': '1'}\ntable.changed.connect(print)\ntable.show(run=True)\n

Total running time of the script: ( 0 minutes 0.038 seconds)

Download Python source code: table.py

Download Jupyter notebook: table.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/matplotlib/mg_execution_times/","title":"Computation times","text":"

00:00.444 total execution time for generated_examples_matplotlib files:

+------------------------------------------------------------------------+-----------+--------+ | waveform (docs/examples/matplotlib/waveform.py) | 00:00.251 | 0.0 MB | +------------------------------------------------------------------------+-----------+--------+ | mpl_figure (docs/examples/matplotlib/mpl_figure.py) | 00:00.193 | 0.0 MB | +------------------------------------------------------------------------+-----------+--------+

"},{"location":"generated_examples/matplotlib/mpl_figure/","title":"matplotlib figure example","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/matplotlib/mpl_figure/#matplotlib-figure-example","title":"matplotlib figure example","text":"

Basic example of adding a generic QWidget to a container.

Main lesson: add your QWidget to container.native.layout() as shown on line 30

Out:

<FunctionGui f(position: int = 0)>\n

import matplotlib.pyplot as plt\nimport numpy as np\nfrom matplotlib.backends.backend_qt5agg import FigureCanvas\n\nfrom magicgui import magicgui\n\nx = np.linspace(0, 5, 256)\ny = np.linspace(0, 5, 256)[:, np.newaxis]\ndata = np.sin(x) ** 10 + np.cos(10 + y * x) * np.cos(x)\n\nmpl_fig = plt.figure()\nax = mpl_fig.add_subplot(111)\n(line,) = ax.plot(data[123])  # linescan through the middle of the image\n\n\n@magicgui(position={\"widget_type\": \"Slider\", \"max\": 255}, auto_call=True)\ndef f(position: int):\n    \"\"\"Function demonstrating magicgui combined with matplotlib.\"\"\"\n    line.set_ydata(data[position])\n    line.figure.canvas.draw()\n\n\n# rather than using the Container.append (`f.append`) ...\n# grab the native layout and add the QWidget to it\nf.native.layout().addWidget(FigureCanvas(mpl_fig))\n\nf.show(run=True)\n

Total running time of the script: ( 0 minutes 0.193 seconds)

Download Python source code: mpl_figure.py

Download Jupyter notebook: mpl_figure.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/matplotlib/waveform/","title":"Waveforms example","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/matplotlib/waveform/#waveforms-example","title":"Waveforms example","text":"

Simple waveform generator widget, with plotting.

Out:

<Container (signal_widget: NoneType, sine: NoneType)>\n

from dataclasses import dataclass, field\nfrom enum import Enum\nfrom functools import partial\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom matplotlib.backends.backend_qt5agg import FigureCanvas\nfrom scipy import signal\nfrom typing_extensions import Annotated\n\nfrom magicgui import magicgui, register_type, widgets\n\nregister_type(float, widget_type=\"FloatSlider\")\nregister_type(int, widget_type=\"Slider\")\n\nFreq = Annotated[float, {\"min\": 0.001, \"max\": 30.0}]\nPhase = Annotated[float, {\"min\": 0.0, \"max\": 360.0}]\nDuty = Annotated[float, {\"min\": 0.0, \"max\": 1.0}]\nTime = Annotated[float, {\"min\": 0.01, \"max\": 100.0}]\n\n\n@dataclass\nclass Signal:\n    \"\"\"Constructs a 1D signal.\n\n    As is, this class is not very useful, but one could add callbacks\n    or more functionality here\n\n    Parameters\n    ----------\n    func : callable\n        func must take a 'time' array as sole argument and return a 1D array with the\n        same size as the input\n    duration : float\n        the maximum of the input time array\n    size : int\n        the number of samples in the time array\n\n    \"\"\"\n\n    func: callable\n    duration: Time = 1.0\n    size: int = 500\n    time: np.ndarray = field(init=False)\n    data: np.ndarray = field(init=False)\n\n    def __post_init__(self):\n        \"\"\"Evaluate the function at instantiation time.\"\"\"\n        self.time = np.linspace(0, self.duration, self.size)\n        self.data = self.func(self.time)\n\n    def plot(self, ax=None, **kwargs):\n        \"\"\"Plots the data.\n\n        Parameters\n        ----------\n        ax: matplotlib.axes.Axes instance, default None\n           if provided the plot is done on this axes instance.\n           If None a new ax is created\n        **kwargs: Keyword arguments that are passed on to\n            the matplotib ax.plot method\n\n        Returns\n        -------\n        fig: a matplotlib.figure.Figure instance\n        ax: matplotlib.axes.Axes instance\n        \"\"\"\n        if ax is None:\n            fig, ax = plt.subplots()\n        else:\n            fig = ax.get_figure()\n        ax.plot(self.time, self.data, **kwargs)\n        return fig, ax\n\n\ndef sine(\n    duration: Time = 10.0, size: int = 500, freq: Freq = 0.5, phase: Phase = 0.0\n) -> Signal:\n    \"\"\"Returns a 1D sine wave.\n\n    Parameters\n    ----------\n    duration: float\n       the duration of the signal in seconds\n    size: int\n        the number of samples in the signal time array\n    freq: float\n       the frequency of the signal in Hz\n    phase: Phase\n       the phase of the signal (in degrees)\n    \"\"\"\n    sig = Signal(\n        duration=duration,\n        size=size,\n        func=lambda t: np.sin(t * (2 * np.pi * freq) + phase * np.pi / 180),\n    )\n    return sig\n\n\ndef chirp(\n    duration: Time = 10.0,\n    size: int = 500,\n    f0: float = 1.0,\n    t1: Time = 5.0,\n    f1: float = 2.0,\n    phase: Phase = 0.0,\n) -> Signal:\n    \"\"\"Frequency-swept cosine generator.\n\n    See scipy.signal.chirp\n    \"\"\"\n    sig = Signal(\n        duration=duration,\n        size=size,\n        func=partial(signal.chirp, f0=f0, t1=t1, f1=f1, phi=phase),\n    )\n    return sig\n\n\ndef sawtooth(\n    duration: Time = 10.0,\n    size: int = 500,\n    freq: Freq = 1.0,\n    width: Duty = 1.0,\n    phase: Phase = 0.0,\n) -> Signal:\n    \"\"\"Return a periodic sawtooth or triangle waveform.\n\n    See scipy.signal.sawtooth\n    \"\"\"\n    sig = Signal(\n        duration=duration,\n        size=size,\n        func=lambda t: signal.sawtooth(\n            2 * np.pi * freq * t + phase * np.pi / 180, width=width\n        ),\n    )\n    return sig\n\n\ndef square(\n    duration: Time = 10.0, size: int = 500, freq: Freq = 1.0, duty: Duty = 0.5\n) -> Signal:\n    \"\"\"Return a periodic sawtooth or triangle waveform.\n\n    See scipy.signal.square\n    \"\"\"\n    sig = Signal(\n        duration=duration,\n        size=size,\n        func=lambda t: signal.square(2 * np.pi * freq * t, duty=duty),\n    )\n    return sig\n\n\ndef on_off(\n    duration: Time = 10.0, size: int = 500, t_on: Time = 0.01, t_off: Time = 0.01\n) -> Signal:\n    \"\"\"On/Off signal function.\"\"\"\n    data = np.ones(size)\n    data[: int(size * t_on / duration)] = -1\n    if t_off > 0:\n        data[int(size * t_off / duration) :] = -1\n    sig = Signal(duration=duration, size=size, func=lambda t: data)\n    return sig\n\n\nWAVEFORMS = {\n    \"sine\": sine,\n    \"chirp\": chirp,\n    \"sawtooth\": sawtooth,\n    \"square\": square,\n    \"on_off\": on_off,\n}\n\n\nclass Select(Enum):\n    \"\"\"Enumeration to select signal type.\"\"\"\n\n    OnOff = \"on_off\"\n    Sine = \"sine\"\n    Chirp = \"chirp\"\n    Sawtooth = \"sawtooth\"\n    Square = \"square\"\n\n\nclass WaveForm(widgets.Container):\n    \"\"\"Simple waveform generator widget, with plotting.\"\"\"\n\n    def __init__(self):\n        \"\"\"Creates the widget.\"\"\"\n        super().__init__()\n        self.fig, self.ax = plt.subplots()\n        self.native.layout().addWidget(FigureCanvas(self.fig))\n        self.waveform = sine\n        self.controls = None\n        self.append(self.signal_widget)\n        self.update_controls()\n        self.update_graph(sine())\n\n    @magicgui(auto_call=True)\n    def signal_widget(self, select: Select = Select.Sine) -> widgets.Container:\n        \"\"\"Waveform selection, from the WAVEFORMS dict.\"\"\"\n        self.waveform = WAVEFORMS[select.value]\n        self.update_controls()\n        self.update_graph(self.waveform())\n\n    def update_controls(self):\n        \"\"\"Reset controls according to the new function.\"\"\"\n        if self.controls is not None:\n            self.remove(self.controls)\n        self.controls = magicgui(auto_call=True)(self.waveform)\n        self.append(self.controls)\n        self.controls.called.connect(self.update_graph)\n\n    def update_graph(self, sig: Signal):\n        \"\"\"Re-plot when a parameter changes.\n\n        Note\n        ----\n        For big data, this could be slow, maybe `auto_call` should\n        not be true in the method above...\n        \"\"\"\n        self.ax.cla()\n        sig.plot(ax=self.ax)\n        self.fig.canvas.draw()\n\n\nwaveform = WaveForm()\nwaveform.show(run=True)\n

Total running time of the script: ( 0 minutes 0.251 seconds)

Download Python source code: waveform.py

Download Jupyter notebook: waveform.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/napari/mg_execution_times/","title":"Computation times","text":"

00:16.424 total execution time for generated_examples_napari files:

+--------------------------------------------------------------------------------------------------------+-----------+--------+ | napari_combine_qt (docs/examples/napari/napari_combine_qt.py) | 00:10.193 | 0.0 MB | +--------------------------------------------------------------------------------------------------------+-----------+--------+ | napari_parameter_sweep (docs/examples/napari/napari_parameter_sweep.py) | 00:03.764 | 0.0 MB | +--------------------------------------------------------------------------------------------------------+-----------+--------+ | napari_img_math (docs/examples/napari/napari_img_math.py) | 00:02.432 | 0.0 MB | +--------------------------------------------------------------------------------------------------------+-----------+--------+ | napari_forward_refs (docs/examples/napari/napari_forward_refs.py) | 00:00.035 | 0.0 MB | +--------------------------------------------------------------------------------------------------------+-----------+--------+

"},{"location":"generated_examples/napari/napari_combine_qt/","title":"napari Qt demo","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/napari/napari_combine_qt/#napari-qt-demo","title":"napari Qt demo","text":"

Napari provides a few conveniences with magicgui, and one of the most commonly used is the layer combo box that gets created when a parameter is annotated as napari.layers.Layer.

The layer box will stay in sync with the viewer model, adding and removing layers as needed.

This example shows how to use just that widget in the context of a larger custom QWidget.

import napari\nfrom qtpy.QtWidgets import QVBoxLayout, QWidget\n\nfrom magicgui.widgets import create_widget\n\n\nclass CustomWidget(QWidget):\n    \"\"\"A custom widget class.\"\"\"\n\n    def __init__(self) -> None:\n        super().__init__()\n        self.setLayout(QVBoxLayout())\n        # change annotation to napari.layers.Image (e.g) to restrict to just Images\n        self._layer_combo = create_widget(annotation=napari.layers.Layer)\n        # magicgui widgets hold the Qt widget at `widget.native`\n        self.layout().addWidget(self._layer_combo.native)\n\n\nviewer = napari.Viewer()\nviewer.add_points()\nviewer.add_points()\n\nmy_widget = CustomWidget()\nviewer.window.add_dock_widget(my_widget)\n\n# when my_widget is a magicgui.Widget, it will detect that it has been added\n# to a viewer, and automatically update the choices.  Otherwise, you need to\n# trigger this yourself:\nmy_widget._layer_combo.reset_choices()\nviewer.layers.events.inserted.connect(my_widget._layer_combo.reset_choices)\nviewer.layers.events.removed.connect(my_widget._layer_combo.reset_choices)\n\nnapari.run()\n

Total running time of the script: ( 0 minutes 10.193 seconds)

Download Python source code: napari_combine_qt.py

Download Jupyter notebook: napari_combine_qt.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/napari/napari_forward_refs/","title":"napari forward reference demo","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/napari/napari_forward_refs/#napari-forward-reference-demo","title":"napari forward reference demo","text":"

Example of using a ForwardRef to avoid importing a module that provides a widget.

In this example, one might want to create a widget that takes as an argument a napari Image layer, and returns an Image. In order to avoid needing to import napari (and therefore depending directly on napari), it's possible to annotate those parameters with a string representation of the type (rather than the type itself). This is called a \"forward reference\": https://www.python.org/dev/peps/pep-0484/#forward-references

Out:

<FunctionGui subtract_background(data: napari.types.ImageData = None, background: int = 50) -> napari.types.ImageData>\n

# Note: if you'd like to avoid circular imports, or just want to avoid having your\n# linter yell at you for an undefined type annotation, you can place the import\n# inside of an `if typing.TYPE_CHECKING` conditional.  This is not evaluated at runtime,\n# only when something like mypy is doing type checking.\nfrom typing import TYPE_CHECKING\n\nfrom magicgui import magicgui\n\nif TYPE_CHECKING:\n    import napari\n\n\n@magicgui(call_button=\"execute\", background={\"max\": 200})\ndef subtract_background(\n    data: \"napari.types.ImageData\", background: int = 50\n) -> \"napari.types.ImageData\":\n    \"\"\"Subtract a constant from the data.\"\"\"\n    if data:\n        return data - background\n\n\nsubtract_background.show(run=True)\n# now, this example isn't all that interesting on its own (since there will be no Image\n# layer in the dropdown) ... but in another package, where you DO import napari,\n# you could add this widget to a napari viewer with\n# viewer.window.add_dock_widget(subtract_background)\n

Total running time of the script: ( 0 minutes 0.035 seconds)

Download Python source code: napari_forward_refs.py

Download Jupyter notebook: napari_forward_refs.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/napari/napari_img_math/","title":"napari image arithmetic widget","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/napari/napari_img_math/#napari-image-arithmetic-widget","title":"napari image arithmetic widget","text":"

napari is a fast, interactive, multi-dimensional image viewer for python. It uses Qt for the GUI, so it's easy to extend napari with small, composable widgets created with magicgui. Here we're going to build this simple image arithmetic widget with a few additional lines of code.

For napari-specific magicgui documentation, see the napari docs

"},{"location":"generated_examples/napari/napari_img_math/#outline","title":"outline","text":"

This example demonstrates how to:

  1. Create a magicgui widget that can be used in another program (napari)

  2. Use an Enum to create a dropdown menu

  3. Connect some event listeners to create interactivity.

"},{"location":"generated_examples/napari/napari_img_math/#code","title":"code","text":"

Code follows, with explanation below... You can also get this example at github.

from enum import Enum\n\nimport napari\nimport numpy\nfrom napari.types import ImageData\n\nfrom magicgui import magicgui\n\n\nclass Operation(Enum):\n    # A set of valid arithmetic operations for image_arithmetic.\n    #\n    # To create nice dropdown menus with magicgui, it's best\n    # (but not required) to use Enums.  Here we make an Enum\n    # class for all of the image math operations we want to\n    # allow.\n    add = numpy.add\n    subtract = numpy.subtract\n    multiply = numpy.multiply\n    divide = numpy.divide\n\n\n# here's the magicgui!  We also use the additional\n# `call_button` option\n@magicgui(call_button=\"execute\")\ndef image_arithmetic(\n    layerA: ImageData, operation: Operation, layerB: ImageData\n) -> ImageData:\n    # Add, subtracts, multiplies, or divides to image layers.\n    return operation.value(layerA, layerB)\n\n# create a viewer and add a couple image layers\nviewer = napari.Viewer()\nviewer.add_image(numpy.random.rand(20, 20), name=\"Layer 1\")\nviewer.add_image(numpy.random.rand(20, 20), name=\"Layer 2\")\n\n# add our new magicgui widget to the viewer\nviewer.window.add_dock_widget(image_arithmetic)\n\n# keep the dropdown menus in the gui in sync with the layer model\nviewer.layers.events.inserted.connect(image_arithmetic.reset_choices)\nviewer.layers.events.removed.connect(image_arithmetic.reset_choices)\n\nnapari.run()\n
"},{"location":"generated_examples/napari/napari_img_math/#walkthrough","title":"walkthrough","text":"

We're going to go a little out of order so that the other code makes more sense. Let's start with the actual function we'd like to write to do some image arithmetic.

"},{"location":"generated_examples/napari/napari_img_math/#the-function","title":"the function","text":"

Our function takes two numpy arrays (in this case, from Image layers), and some mathematical operation (we'll restrict the options using an enum.Enum). When called, ourfunction calls the selected operation on the data.

def image_arithmetic(array1, operation, array2):\n    return operation.value(array1, array2)\n
"},{"location":"generated_examples/napari/napari_img_math/#type-annotations","title":"type annotations","text":"

magicgui works particularly well with type annotations, and allows third-party libraries to register widgets and behavior for handling their custom types (using magicgui.type_map.register_type). napari provides support for magicgui by registering a dropdown menu whenever a function parameter is annotated as one of the basic napari Layer types, or, in this case, ImageData indicates we just the data attribute of the layer. Furthermore, it recognizes when a function has a napari.layers.Layer or LayerData return type annotation, and will add the result to the viewer. So we gain a lot by annotating the above function with the appropriate napari types.

from napari.types import ImageData\n\ndef image_arithmetic(\n    layerA: ImageData, operation: Operation, layerB: ImageData\n) -> ImageData:\n    return operation.value(layerA, layerB)\n
"},{"location":"generated_examples/napari/napari_img_math/#the-magic-part","title":"the magic part","text":"

Finally, we decorate the function with @magicgui and tell it we'd like to have a call_button that we can click to execute the function.

@magicgui(call_button=\"execute\")\ndef image_arithmetic(layerA: ImageData, operation: Operation, layerB: ImageData):\n    return operation.value(layerA, layerB)\n

That's it! The image_arithmetic function is now a FunctionGui that can be shown, or incorporated into other GUIs (such as the napari GUI shown in this example)

!!! note While type hints aren't always required in magicgui, they are recommended ... and they are required for certain things, like the Operation(Enum) used here for the dropdown and the napari.types.ImageData annotations that napari has registered with magicgui.

"},{"location":"generated_examples/napari/napari_img_math/#create-dropdowns-with-enums","title":"create dropdowns with Enums","text":"

We'd like the user to be able to select the operation (add, subtract, multiply, divide) using a dropdown menu. enum.Enum offers a convenient way to restrict values to a strict set of options, while providing name: value pairs for each of the options. Here, the value for each choice is the actual function we would like to have called when that option is selected.

class Operation(enum.Enum):\n    add = numpy.add\n    subtract = numpy.subtract\n    multiply = numpy.multiply\n    divide = numpy.divide\n
"},{"location":"generated_examples/napari/napari_img_math/#add-it-to-napari","title":"add it to napari","text":"

When we decorated the image_arithmetic function above, it became a FunctionGui. Napari recognizes this type, so we can simply add it to the napari viewer as follows:

viewer.window.add_dock_widget(image_arithmetic)\n
"},{"location":"generated_examples/napari/napari_img_math/#connect-event-listeners-for-interactivity","title":"connect event listeners for interactivity","text":"

What fun is a GUI without some interactivity? Let's make stuff happen.

We connect the image_arithmetic.reset_choices function to the viewer.layers.events.inserted/removed event from napari, to make sure that the dropdown menus stay in sync if a layer gets added or removed from the napari window:

viewer.layers.events.inserted.connect(image_arithmetic.reset_choices)\nviewer.layers.events.removed.connect(image_arithmetic.reset_choices)\n

Tip

An additional offering from magicgui here is that the decorated function also acquires a new attribute \"called\" that can be connected to callback functions of your choice. Then, whenever the gui widget or the original function are called, the result will be passed to your callback function:

@image_arithmetic.called.connect\ndef print_mean(value):\n    # Callback function that accepts an event\n    # the value attribute has the result of calling the function\n    print(np.mean(value))\n
>>> image_arithmetic()\n1.0060037881040373\n
"},{"location":"generated_examples/napari/napari_img_math/#code_1","title":"Code","text":"

Here's the full code example again.

from enum import Enum\n\nimport napari\nimport numpy\nfrom napari.types import ImageData\n\nfrom magicgui import magicgui\n\n\nclass Operation(Enum):\n    # A set of valid arithmetic operations for image_arithmetic.\n    #\n    # To create nice dropdown menus with magicgui, it's best\n    # (but not required) to use Enums.  Here we make an Enum\n    # class for all of the image math operations we want to\n    # allow.\n    add = numpy.add\n    subtract = numpy.subtract\n    multiply = numpy.multiply\n    divide = numpy.divide\n\n\n# here's the magicgui!  We also use the additional\n# `call_button` option\n@magicgui(call_button=\"execute\")\ndef image_arithmetic(\n    layerA: ImageData, operation: Operation, layerB: ImageData\n) -> ImageData:\n    # Add, subtracts, multiplies, or divides to image layers.\n    return operation.value(layerA, layerB)\n\n\n# create a viewer and add a couple image layers\nviewer = napari.Viewer()\nviewer.add_image(numpy.random.rand(20, 20), name=\"Layer 1\")\nviewer.add_image(numpy.random.rand(20, 20), name=\"Layer 2\")\n\n# add our new magicgui widget to the viewer\nviewer.window.add_dock_widget(image_arithmetic)\n\n# keep the dropdown menus in the gui in sync with the layer model\nviewer.layers.events.inserted.connect(image_arithmetic.reset_choices)\nviewer.layers.events.removed.connect(image_arithmetic.reset_choices)\n\nnapari.run()\n

Total running time of the script: ( 0 minutes 2.432 seconds)

Download Python source code: napari_img_math.py

Download Jupyter notebook: napari_img_math.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/napari/napari_parameter_sweep/","title":"napari parameter sweeps","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/napari/napari_parameter_sweep/#napari-parameter-sweeps","title":"napari parameter sweeps","text":"

napari is a fast, interactive, multi-dimensional image viewer for python. It uses Qt for the GUI, so it's easy to extend napari with small, composable widgets created with magicgui. Here, we demonstrate how to build a interactive widget that lets you immediately see the effect of changing one of the parameters of your function.

For napari-specific magicgui documentation, see the napari docs

See also: Some of this tutorial overlaps with topics covered in the napari image arithmetic example.

"},{"location":"generated_examples/napari/napari_parameter_sweep/#outline","title":"outline","text":"

This example demonstrates how to:

  1. Create a magicgui widget that can be used in another program (napari)

  2. Automatically call our function when a parameter changes

  3. Provide magicgui with a custom widget for a specific argument

  4. Use the choices option to create a dropdown

  5. Connect some event listeners to create interactivity.

"},{"location":"generated_examples/napari/napari_parameter_sweep/#code","title":"code","text":"

Code follows, with explanation below... You can also get this example at github.

import napari\nimport skimage.data\nimport skimage.filters\nfrom napari.types import ImageData\n\nfrom magicgui import magicgui\n\n\n# turn the gaussian blur function into a magicgui\n# - 'auto_call' tells magicgui to call the function when a parameter changes\n# - we use 'widget_type' to override the default \"float\" widget on sigma,\n#   and provide a maximum valid value.\n# - we contstrain the possible choices for 'mode'\n@magicgui(\n    auto_call=True,\n    sigma={\"widget_type\": \"FloatSlider\", \"max\": 6},\n    mode={\"choices\": [\"reflect\", \"constant\", \"nearest\", \"mirror\", \"wrap\"]},\n    layout=\"horizontal\",\n)\ndef gaussian_blur(layer: ImageData, sigma: float = 1.0, mode=\"nearest\") -> ImageData:\n    # Apply a gaussian blur to 'layer'.\n    if layer is not None:\n        return skimage.filters.gaussian(layer, sigma=sigma, mode=mode)\n\n# create a viewer and add some images\nviewer = napari.Viewer()\nviewer.add_image(skimage.data.astronaut().mean(-1), name=\"astronaut\")\nviewer.add_image(skimage.data.grass().astype(\"float\"), name=\"grass\")\n\n# Add it to the napari viewer\nviewer.window.add_dock_widget(gaussian_blur)\n# update the layer dropdown menu when the layer list changes\nviewer.layers.events.changed.connect(gaussian_blur.reset_choices)\n\nnapari.run()\n
"},{"location":"generated_examples/napari/napari_parameter_sweep/#walkthrough","title":"walkthrough","text":"

We're going to go a little out of order so that the other code makes more sense. Let's start with the actual function we'd like to write to apply a gaussian filter to an image.

"},{"location":"generated_examples/napari/napari_parameter_sweep/#the-function","title":"the function","text":"

Our function is a very thin wrapper around skimage.filters.gaussian. It takes a napari Image layer, a sigma to control the blur radius, and a mode that determines how edges are handled.

def gaussian_blur(\n    layer: Image, sigma: float = 1, mode=\"nearest\"\n) -> Image:\n    return filters.gaussian(layer.data, sigma=sigma, mode=mode)\n

The reasons we are wrapping it here are:

  1. filters.gaussian accepts a numpy array, but we want to work with napari layers that store the data in a layer.data attribute. So we need an adapter.
  2. We'd like to add some type annotations to the signature that were not provided by filters.gaussian
"},{"location":"generated_examples/napari/napari_parameter_sweep/#type-annotations","title":"type annotations","text":"

As described in the image arithmetic example, we take advantage of napari's built in support for magicgui by annotating our function parameters and return value as napari Layer types. napari will then tell magicgui what to do with them, creating a dropdown with a list of current layers for our layer parameter, and automatically adding the result of our function to the viewer when called.

For documentation on napari types with magicgui, see the napari docs

"},{"location":"generated_examples/napari/napari_parameter_sweep/#the-magic-part","title":"the magic part","text":"

Finally, we decorate the function with @magicgui and provide some options.

@magicgui(\n    auto_call=True,\n    sigma={\"widget_type\": \"FloatSlider\", \"max\": 6},\n    mode={\"choices\": [\"reflect\", \"constant\", \"nearest\", \"mirror\", \"wrap\"]},\n)\ndef gaussian_blur(\n  layer: ImageData, sigma: float = 1.0, mode=\"nearest\"\n) -> ImageData:\n    # Apply a gaussian blur to ``layer``.\n    if layer is not None:\n        return skimage.filters.gaussian(layer, sigma=sigma, mode=mode)\n
  • auto_call=True makes it so that the gaussian_blur function will be called whenever one of the parameters changes (with the current parameters set in the GUI).
  • We then provide keyword arguments to modify the look & behavior of sigma and mode:

    • \"widget_type\": \"FloatSlider\" tells magicgui not to use the standard (float) widget for the sigma widget, but rather to use a slider widget.
    • we then set an upper limit on the slider values for sigma.
  • finally, we specify valid choices for the mode argument. This turns that parameter into a categorical/dropdown type widget, and sets the options.

"},{"location":"generated_examples/napari/napari_parameter_sweep/#connecting-events","title":"connecting events","text":"

As described in the Events documentation, we can also connect any callback to the gaussian_blur.called signal that will receive the result of our decorated function anytime it is called.

def do_something_with_result(result):\n    ...\n\ngaussian_blur.called.connect(do_something_with_result)\n
"},{"location":"generated_examples/napari/napari_parameter_sweep/#code_1","title":"Code","text":"

Here's the full code example again.

import napari\nimport skimage.data\nimport skimage.filters\nfrom napari.types import ImageData\n\nfrom magicgui import magicgui\n\n\n# turn the gaussian blur function into a magicgui\n# - 'auto_call' tells magicgui to call the function when a parameter changes\n# - we use 'widget_type' to override the default \"float\" widget on sigma,\n#   and provide a maximum valid value.\n# - we contstrain the possible choices for 'mode'\n@magicgui(\n    auto_call=True,\n    sigma={\"widget_type\": \"FloatSlider\", \"max\": 6},\n    mode={\"choices\": [\"reflect\", \"constant\", \"nearest\", \"mirror\", \"wrap\"]},\n    layout=\"horizontal\",\n)\ndef gaussian_blur(layer: ImageData, sigma: float = 1.0, mode=\"nearest\") -> ImageData:\n    # Apply a gaussian blur to 'layer'.\n    if layer is not None:\n        return skimage.filters.gaussian(layer, sigma=sigma, mode=mode)\n\n\n# create a viewer and add some images\nviewer = napari.Viewer()\nviewer.add_image(skimage.data.astronaut().mean(-1), name=\"astronaut\")\nviewer.add_image(skimage.data.grass().astype(\"float\"), name=\"grass\")\n\n# Add it to the napari viewer\nviewer.window.add_dock_widget(gaussian_blur)\n# update the layer dropdown menu when the layer list changes\nviewer.layers.events.changed.connect(gaussian_blur.reset_choices)\n\nnapari.run()\n

Total running time of the script: ( 0 minutes 3.764 seconds)

Download Python source code: napari_parameter_sweep.py

Download Jupyter notebook: napari_parameter_sweep.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/notebooks/magicgui_jupyter/","title":"Jupyter notebooks and magicgui","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/notebooks/magicgui_jupyter/#jupyter-notebooks-and-magicgui","title":"Jupyter notebooks and magicgui","text":"

This example shows magicgui widgets embedded in a jupyter notebook.

The key function here is use_app(\"ipynb\").

You can also get this example at github.

import math\nfrom enum import Enum\n\nfrom magicgui import magicgui, use_app\nuse_app(\"ipynb\")\n\nclass Medium(Enum):\n    # Various media and their refractive indices.\n    Glass = 1.520\n    Oil = 1.515\n    Water = 1.333\n    Air = 1.0003\n\n\n@magicgui(\n    call_button=\"calculate\", result_widget=True, layout='vertical', auto_call=True\n)\ndef snells_law(aoi=1.0, n1=Medium.Glass, n2=Medium.Water, degrees=True):\n    # Calculate the angle of refraction given two media and an angle of incidence.\n    if degrees:\n        aoi = math.radians(aoi)\n    try:\n        n1 = n1.value\n        n2 = n2.value\n        result = math.asin(n1 * math.sin(aoi) / n2)\n        return round(math.degrees(result) if degrees else result, 2)\n    except ValueError:  # math domain error\n        return \"TIR!\"\n\n\nsnells_law\n

Total running time of the script: ( 0 minutes 0.000 seconds)

Download Python source code: magicgui_jupyter.py

Download Jupyter notebook: magicgui_jupyter.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/notebooks/mg_execution_times/","title":"Computation times","text":"

00:00.000 total execution time for generated_examples_notebooks files:

+-----------------------------------------------------------------------------------------+-----------+--------+ | magicgui_jupyter (docs/examples/notebooks/magicgui_jupyter.py) | 00:00.000 | 0.0 MB | +-----------------------------------------------------------------------------------------+-----------+--------+

"},{"location":"generated_examples/progress_bars/mg_execution_times/","title":"Computation times","text":"

00:00.187 total execution time for generated_examples_progress_bars files:

+---------------------------------------------------------------------------------------------------------------+-----------+--------+ | progress_nested (docs/examples/progress_bars/progress_nested.py) | 00:00.059 | 0.0 MB | +---------------------------------------------------------------------------------------------------------------+-----------+--------+ | progress_manual (docs/examples/progress_bars/progress_manual.py) | 00:00.053 | 0.0 MB | +---------------------------------------------------------------------------------------------------------------+-----------+--------+ | progress (docs/examples/progress_bars/progress.py) | 00:00.042 | 0.0 MB | +---------------------------------------------------------------------------------------------------------------+-----------+--------+ | progress_indeterminate (docs/examples/progress_bars/progress_indeterminate.py) | 00:00.032 | 0.0 MB | +---------------------------------------------------------------------------------------------------------------+-----------+--------+

"},{"location":"generated_examples/progress_bars/progress/","title":"Simple progress bar","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/progress_bars/progress/#simple-progress-bar","title":"Simple progress bar","text":"

A simple progress bar demo with magicgui.

Out:

<FunctionGui long_running(steps=10, delay=0.1)>\n

from time import sleep\n\nfrom magicgui import magicgui\nfrom magicgui.tqdm import trange\n\n# if magicui.tqdm.tqdm or trange are used outside of a @magicgui function, (such as in\n# interactive use in IPython), then they fall back to the standard terminal output\n\n\n# If use inside of a magicgui-decorated function\n# a progress bar widget will be added to the magicgui container\n@magicgui(call_button=True, layout=\"horizontal\")\ndef long_running(steps=10, delay=0.1):\n    \"\"\"Long running computation with range iterator.\"\"\"\n    # trange(steps) is a shortcut for `tqdm(range(steps))`\n    for _i in trange(steps):\n        sleep(delay)\n\n\nlong_running.show(run=True)\n

Total running time of the script: ( 0 minutes 0.042 seconds)

Download Python source code: progress.py

Download Jupyter notebook: progress.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/progress_bars/progress_indeterminate/","title":"Indeterminate progress bar","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/progress_bars/progress_indeterminate/#indeterminate-progress-bar","title":"Indeterminate progress bar","text":"

Example of an indeterminate progress bar for a long running computation of unknown time.

Out:

<FunctionGui long_running(sleep_time=5)>\n

import time\n\nfrom superqt.utils import thread_worker\n\nfrom magicgui import magicgui\nfrom magicgui.tqdm import tqdm\n\n\n@magicgui(call_button=True, layout=\"horizontal\")\ndef long_running(sleep_time=5):\n    \"\"\"Long running computation with an indeterminate progress bar.\"\"\"\n    # Here tqdm is not provided an iterable argument, or the 'total' kwarg\n    # so it cannot calculate the expected number of iterations\n    # which means it will create an indeterminate progress bar\n    with tqdm() as pbar:\n        # It is best practice to use a separate thread for long running computations\n        # This makes the function non-blocking, you can still interact with the widget\n        @thread_worker(connect={\"finished\": lambda: pbar.progressbar.hide()})\n        def sleep(secs):\n            time.sleep(secs)\n\n        sleep(sleep_time)\n\n\nlong_running.show(run=True)\n

Total running time of the script: ( 0 minutes 0.032 seconds)

Download Python source code: progress_indeterminate.py

Download Jupyter notebook: progress_indeterminate.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/progress_bars/progress_manual/","title":"Manual progress bar","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/progress_bars/progress_manual/#manual-progress-bar","title":"Manual progress bar","text":"

Example of a progress bar being updated manually.

Out:

<FunctionGui manual(pbar: magicgui.widgets.ProgressBar = ProgressBar(value=<function match_type.<locals>.<lambda> at 0x131416de0>, annotation=<class 'magicgui.widgets.ProgressBar'>, name='pbar'), increment: bool = 1)>\n

from magicgui import magicgui\nfrom magicgui.widgets import ProgressBar\n\n\n@magicgui(call_button=\"tick\", pbar={\"min\": 0, \"step\": 2, \"max\": 20, \"value\": 0})\ndef manual(pbar: ProgressBar, increment: bool = True):\n    \"\"\"Example of manual progress bar control.\"\"\"\n    if increment:\n        pbar.increment()\n    else:\n        pbar.decrement()\n\n\nmanual.show(run=True)\n

Total running time of the script: ( 0 minutes 0.053 seconds)

Download Python source code: progress_manual.py

Download Jupyter notebook: progress_manual.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/progress_bars/progress_nested/","title":"Nested progress bars","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/progress_bars/progress_nested/#nested-progress-bars","title":"Nested progress bars","text":"

Example using nested progress bars in magicgui.

Out:

<FunctionGui long_function(steps=10, repeats=4, choices='ABCDEFGHIJKLMNOP12345679', char='', delay=0.05)>\n

import random\nfrom time import sleep\n\nfrom magicgui import magicgui\nfrom magicgui.tqdm import tqdm, trange\n\n# if magicui.tqdm.tqdm or trange are used outside of a @magicgui function, (such as in\n# interactive use in IPython), then they fall back to the standard terminal output\n\n\n# If use inside of a magicgui-decorated function\n# a progress bar widget will be added to the magicgui container\n@magicgui(call_button=True, layout=\"vertical\")\ndef long_function(\n    steps=10, repeats=4, choices=\"ABCDEFGHIJKLMNOP12345679\", char=\"\", delay=0.05\n):\n    \"\"\"Long running computation with nested iterators.\"\"\"\n    # trange and tqdm accept all the kwargs from tqdm itself, as well as any\n    # valid kwargs for magicgui.widgets.ProgressBar, (such as \"label\")\n    for _r in trange(repeats, label=\"repeats\"):\n        letters = [random.choice(choices) for _ in range(steps)]\n        # `tqdm`, like `tqdm`, accepts any iterable\n        # this progress bar is nested and will be run & reset multiple times\n        for letter in tqdm(letters, label=\"steps\"):\n            long_function.char.value = letter\n            sleep(delay)\n\n\nlong_function.show(run=True)\n

Total running time of the script: ( 0 minutes 0.059 seconds)

Download Python source code: progress_nested.py

Download Jupyter notebook: progress_nested.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/under_the_hood/class_method/","title":"Deocrate class methods with magicgui","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/under_the_hood/class_method/#deocrate-class-methods-with-magicgui","title":"Deocrate class methods with magicgui","text":"

Demonstrates decorating a class method with magicgui.

Once the class is instantiated, instance.method_name will return a FunctionGui in which the instance will always be provided as the first argument (i.e. \"self\") when the FunctionGui or method is called.

Out:

instance: a, counter: 0.0, sigma: 0.0\ninstance: b, counter: 0.0, sigma: 0.0\n

from magicgui import event_loop, magicgui\nfrom magicgui.widgets import Container\n\n\nclass MyObject:\n    \"\"\"Example object class.\"\"\"\n\n    def __init__(self, name):\n        self.name = name\n        self.counter = 0.0\n\n    @magicgui(auto_call=True)\n    def method(self, sigma: float = 0):\n        \"\"\"Example class method.\"\"\"\n        print(f\"instance: {self.name}, counter: {self.counter}, sigma: {sigma}\")\n        self.counter = self.counter + sigma\n        return self.name\n\n\nwith event_loop():\n    a = MyObject(\"a\")\n    b = MyObject(\"b\")\n    container = Container(widgets=[a.method, b.method])\n    container.show()\n    assert a.method() == \"a\"\n    assert b.method() == \"b\"\n

Total running time of the script: ( 0 minutes 0.035 seconds)

Download Python source code: class_method.py

Download Jupyter notebook: class_method.ipynb

Gallery generated by mkdocs-gallery

"},{"location":"generated_examples/under_the_hood/mg_execution_times/","title":"Computation times","text":"

00:00.075 total execution time for generated_examples_under_the_hood files:

+----------------------------------------------------------------------------------------+-----------+--------+ | self_reference (docs/examples/under_the_hood/self_reference.py) | 00:00.040 | 0.0 MB | +----------------------------------------------------------------------------------------+-----------+--------+ | class_method (docs/examples/under_the_hood/class_method.py) | 00:00.035 | 0.0 MB | +----------------------------------------------------------------------------------------+-----------+--------+

"},{"location":"generated_examples/under_the_hood/self_reference/","title":"Self reference magicgui widgets","text":"

Note

Click here to download the full example code

"},{"location":"generated_examples/under_the_hood/self_reference/#self-reference-magicgui-widgets","title":"Self reference magicgui widgets","text":"

Widgets created with magicgui can reference themselves, and use the widget API.

Out:

<FunctionGui function(width=400, x: int = 50)>\n

from magicgui import magicgui\n\n\n@magicgui(auto_call=True, width={\"max\": 800, \"min\": 100}, x={\"widget_type\": \"Slider\"})\ndef function(width=400, x: int = 50):\n    \"\"\"Example function.\"\"\"\n    # the widget can reference itself, and use the widget API\n    function.x.width = width\n\n\nfunction.show(run=True)\n

Total running time of the script: ( 0 minutes 0.040 seconds)

Download Python source code: self_reference.py

Download Jupyter notebook: self_reference.ipynb

Gallery generated by mkdocs-gallery

"}]} \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index f2618a2d6a9c37ef062b1c35143bafe8593f8318..83c6908e03e814a64e95681a8797b315c49d394d 100644 GIT binary patch delta 15 WcmX@iewdw2zMF%?E_Nf^USDefault Type Mappingmagicgui.widgets.ProgressBar ProgressBar -{'bind': <function match_type.<locals>.<lambda> at 0x13e8d7ce0>, 'visible': True} +{'bind': <function match_type.<locals>.<lambda> at 0x139b8fec0>, 'visible': True} types.FunctionType