├── .coveragerc ├── .flake8 ├── .github └── workflows │ ├── tests.yml │ └── wheels.yml ├── .gitignore ├── .readthedocs.yaml ├── INSTALL.md ├── MANUAL_INSTALL.md ├── README.md ├── _layouts └── default.html ├── developer_tools ├── deep_get_referrers.py ├── list_quibbler_methods.py ├── notes │ ├── thoughts_on_divergence_1.ipynb │ ├── thoughts_on_divergence_2.ipynb │ └── thoughts_on_divergence_3.ipynb └── old_code │ ├── rounding.py │ └── unoverride_all.py ├── google56763903e901c5f9.html ├── install.py ├── license ├── pyquibbler-documentations ├── Makefile ├── README.md ├── convert_doc_notebooks_to_rst.py ├── docs │ ├── Diverged-evaluation.rst │ ├── Examples.rst │ ├── Graphics.rst │ ├── Installation.rst │ ├── Introduction.rst │ ├── Inverse-assignments.rst │ ├── Jupyter-lab-ext.rst │ ├── List-of-quiby-functions.rst │ ├── List_of_functions.rst │ ├── Overriding-default-functionality.rst │ ├── Project-save-load.rst │ ├── Quib-naming.rst │ ├── Quib-relationships.rst │ ├── Quibbler_Enums.rst │ ├── Quibbler_display_classes.rst │ ├── Quiby-ipywidgets.rst │ ├── Quickstart.rst │ ├── Random-functions.rst │ ├── Rationale.md │ ├── User-defined-functions.rst │ ├── What-is-it.md │ ├── _static │ │ └── custom.css │ ├── _templates │ │ ├── custom-class-template.rst │ │ └── custom-module-template.rst │ ├── classes │ │ ├── pyquibbler.AssignmentTemplate.rst │ │ ├── pyquibbler.CacheMode.rst │ │ ├── pyquibbler.CacheStatus.rst │ │ ├── pyquibbler.GraphicsUpdateType.rst │ │ ├── pyquibbler.QuibPropertiesViewer.rst │ │ ├── pyquibbler.SaveFormat.rst │ │ ├── pyquibbler.ipywidget_viewer.QuibWidget.rst │ │ └── pyquibbler.quib_network.Direction.rst │ ├── conceptual_view.gif │ ├── conf.py │ ├── examples │ │ ├── quibdemo_COVID_analysis.rst │ │ ├── quibdemo_CheckButtons.rst │ │ ├── quibdemo_LotkaVolterra.rst │ │ ├── quibdemo_Mandelbrot.rst │ │ ├── quibdemo_compare_images.rst │ │ ├── quibdemo_default_overriding.rst │ │ ├── quibdemo_default_overriding_two_levels.rst │ │ ├── quibdemo_drag_fixed_values.rst │ │ ├── quibdemo_drag_multiple_points.rst │ │ ├── quibdemo_drag_on_curve.rst │ │ ├── quibdemo_drag_segments.rst │ │ ├── quibdemo_drag_vertical_horizontal.rst │ │ ├── quibdemo_drag_whole_object_vs_individual_points.rst │ │ ├── quibdemo_drag_xy.rst │ │ ├── quibdemo_dragging_fixed_object.rst │ │ ├── quibdemo_fft.rst │ │ ├── quibdemo_fit_stocks.rst │ │ ├── quibdemo_gear.rst │ │ ├── quibdemo_image_ROI.rst │ │ ├── quibdemo_image_probing.rst │ │ ├── quibdemo_image_thresholding.rst │ │ ├── quibdemo_ipywidgets_quadratic_eq.rst │ │ ├── quibdemo_making_the_quib_icon.rst │ │ ├── quibdemo_percolation.rst │ │ ├── quibdemo_periodic_functions.rst │ │ ├── quibdemo_pythagoras.rst │ │ ├── quibdemo_quiby_axes.rst │ │ ├── quibdemo_random_quibs_dice.rst │ │ ├── quibdemo_repressilator.rst │ │ ├── quibdemo_rushhour.rst │ │ ├── quibdemo_same_data_in_many_forms.rst │ │ └── quibdemo_slider.rst │ ├── functions │ │ ├── pyquibbler.can_redo.rst │ │ ├── pyquibbler.can_undo.rst │ │ ├── pyquibbler.default.rst │ │ ├── pyquibbler.get_project.rst │ │ ├── pyquibbler.get_project_directory.rst │ │ ├── pyquibbler.initialize_quibbler.rst │ │ ├── pyquibbler.iquib.rst │ │ ├── pyquibbler.is_quiby.rst │ │ ├── pyquibbler.list_quiby_funcs.rst │ │ ├── pyquibbler.load_quibs.rst │ │ ├── pyquibbler.obj2quib.rst │ │ ├── pyquibbler.q.rst │ │ ├── pyquibbler.quib_network.dependency_graph.rst │ │ ├── pyquibbler.quibapp.rst │ │ ├── pyquibbler.quiby.rst │ │ ├── pyquibbler.redo.rst │ │ ├── pyquibbler.refresh_graphics.rst │ │ ├── pyquibbler.reset_file_loading_quibs.rst │ │ ├── pyquibbler.reset_impure_quibs.rst │ │ ├── pyquibbler.reset_random_quibs.rst │ │ ├── pyquibbler.save_quibs.rst │ │ ├── pyquibbler.set_project_directory.rst │ │ ├── pyquibbler.sync_quibs.rst │ │ └── pyquibbler.undo.rst │ ├── images │ │ ├── Quickstart_assign_d_and_drag.gif │ │ ├── Quickstart_assign_xy_and_drag.gif │ │ ├── Quickstart_interactive_image_cut.gif │ │ ├── Quickstart_load_image.gif │ │ ├── Quickstart_widget_box_size.gif │ │ ├── User_defined_functions_pass_quibs.gif │ │ ├── assignments_assignment_template.gif │ │ ├── assignments_jupyter_undo_redo.gif │ │ ├── conceptual_view.gif │ │ ├── conceptual_view.png │ │ ├── demo_gif │ │ │ ├── quibdemo_COVID_analysis.gif │ │ │ ├── quibdemo_CheckButtons.gif │ │ │ ├── quibdemo_LotkaVolterra.gif │ │ │ ├── quibdemo_Mandelbrot.gif │ │ │ ├── quibdemo_compare_images.gif │ │ │ ├── quibdemo_default_overriding.gif │ │ │ ├── quibdemo_default_overriding_two_levels.gif │ │ │ ├── quibdemo_drag_fixed_values.gif │ │ │ ├── quibdemo_drag_multiple_points.gif │ │ │ ├── quibdemo_drag_on_curve.gif │ │ │ ├── quibdemo_drag_vertical_horizontal.gif │ │ │ ├── quibdemo_drag_whole_object_vs_individual_points.gif │ │ │ ├── quibdemo_drag_xy.gif │ │ │ ├── quibdemo_dragging_fixed_object.gif │ │ │ ├── quibdemo_fft.gif │ │ │ ├── quibdemo_fit_stocks.gif │ │ │ ├── quibdemo_gear.gif │ │ │ ├── quibdemo_image_ROI.gif │ │ │ ├── quibdemo_image_probing.gif │ │ │ ├── quibdemo_image_thresholding.gif │ │ │ ├── quibdemo_ipywidgets_quadratic_eq.gif │ │ │ ├── quibdemo_making_the_quib_icon.gif │ │ │ ├── quibdemo_percolation.gif │ │ │ ├── quibdemo_periodic_functions.gif │ │ │ ├── quibdemo_pythagoras.gif │ │ │ ├── quibdemo_quiby_axes.gif │ │ │ ├── quibdemo_random_quibs_dice.gif │ │ │ ├── quibdemo_repressilator.gif │ │ │ ├── quibdemo_rushhour.gif │ │ │ ├── quibdemo_same_data_in_many_forms.gif │ │ │ └── quibdemo_slider.gif │ │ ├── dependency_graph_1.png │ │ ├── dialog_box_per_item_factor.png │ │ ├── divergence_gif │ │ │ ├── Divergence_arrows.gif │ │ │ └── Divergence_passquibs.gif │ │ ├── graphics_gif │ │ │ ├── graphics_rgb_probing_of_image.gif │ │ │ ├── graphics_slider_for_box_size.gif │ │ │ ├── graphics_xy_axis_labels.gif │ │ │ ├── graphics_xy_drag.gif │ │ │ ├── graphics_xy_drag_horz_vert.gif │ │ │ └── graphics_xy_refresh.gif │ │ ├── graphics_inverse.gif │ │ ├── graphics_refresh.gif │ │ ├── inverse_assignment_age_dob.gif │ │ ├── inverse_assignment_choice.png │ │ ├── inverse_assignment_illustrate.gif │ │ ├── labext_open.png │ │ ├── labext_quibbler_menu.png │ │ ├── labext_undo_redo.gif │ │ ├── minimal_app_3.gif │ │ ├── network_tracing.png │ │ ├── overriding_default_by_dragging.gif │ │ ├── overriding_set_back_to_default.gif │ │ ├── quib_editor_save_load.gif │ │ ├── quib_editor_thresholds_rgb.gif │ │ ├── quib_transparent.png │ │ ├── quibicon.gif │ │ ├── quiby_ipywidgets_gif │ │ │ ├── quiby-ipywidgets-bidirectional.gif │ │ │ ├── quiby-ipywidgets-bob-alice.gif │ │ │ ├── quiby-ipywidgets-linked-widgets-quiby.gif │ │ │ ├── quiby-ipywidgets-linked-widgets.gif │ │ │ ├── quiby-ipywidgets-lorenz.gif │ │ │ └── quiby-ipywidgets-min-max.gif │ │ ├── tile_7_5_inverse.gif │ │ └── tile_7_5_override.gif │ ├── index.rst │ ├── major_classes │ │ ├── Project_class.rst │ │ └── Quib_class.rst │ ├── requirements.txt │ └── zips_for_download │ │ └── examples.zip ├── docs_notebooks │ ├── Diverged-evaluation.ipynb │ ├── Graphics.ipynb │ ├── Introduction.ipynb │ ├── Inverse-assignments.ipynb │ ├── Jupyter-lab-ext.ipynb │ ├── List-of-quiby-functions.ipynb │ ├── Overriding-default-functionality.ipynb │ ├── Project-save-load.ipynb │ ├── Quib-naming.ipynb │ ├── Quib-relationships.ipynb │ ├── Quiby-ipywidgets.ipynb │ ├── Quickstart.ipynb │ ├── Random-functions.ipynb │ ├── User-defined-functions.ipynb │ ├── bacteria_drop.tif │ ├── bacteria_in_a_droplet.tif │ ├── bacteria_in_droplets.tif │ └── notebook_for_videos │ │ └── Quiby-ipywidgets-videos.ipynb ├── examples │ ├── AAPL.csv │ ├── README.md │ ├── bacteria_drop.tif │ ├── bacteria_in_droplets.tif │ ├── covid_fatality.csv │ ├── pipes.jpg │ ├── quibdemo_COVID_analysis.ipynb │ ├── quibdemo_CheckButtons.ipynb │ ├── quibdemo_LotkaVolterra.ipynb │ ├── quibdemo_Mandelbrot.ipynb │ ├── quibdemo_compare_images.ipynb │ ├── quibdemo_default_overriding.ipynb │ ├── quibdemo_default_overriding_two_levels.ipynb │ ├── quibdemo_drag_fixed_values.ipynb │ ├── quibdemo_drag_multiple_points.ipynb │ ├── quibdemo_drag_on_curve.ipynb │ ├── quibdemo_drag_segments.ipynb │ ├── quibdemo_drag_vertical_horizontal.ipynb │ ├── quibdemo_drag_whole_object_vs_individual_points.ipynb │ ├── quibdemo_drag_xy.ipynb │ ├── quibdemo_dragging_fixed_object.ipynb │ ├── quibdemo_fft.ipynb │ ├── quibdemo_fit_stocks.ipynb │ ├── quibdemo_gear.ipynb │ ├── quibdemo_image_ROI.ipynb │ ├── quibdemo_image_probing.ipynb │ ├── quibdemo_image_thresholding.ipynb │ ├── quibdemo_ipywidgets_quadratic_eq.ipynb │ ├── quibdemo_making_the_quib_icon.ipynb │ ├── quibdemo_percolation.ipynb │ ├── quibdemo_periodic_functions.ipynb │ ├── quibdemo_pythagoras.ipynb │ ├── quibdemo_quiby_axes.ipynb │ ├── quibdemo_random_quibs_dice.ipynb │ ├── quibdemo_repressilator.ipynb │ ├── quibdemo_rushhour.ipynb │ ├── quibdemo_same_data_in_many_forms.ipynb │ └── quibdemo_slider.ipynb ├── make.bat └── powerpoint_files │ ├── images_lab_extension.pptx │ ├── inverse.pptx │ └── network_tracing.pptx ├── pyquibbler-labextension ├── .github_temp │ └── workflows │ │ ├── binder-on-pr.yml │ │ ├── build.yml │ │ └── check-release.yml ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .stylelintrc ├── CHANGELOG.md ├── MANIFEST.in ├── README.md ├── RELEASE.md ├── binder │ ├── environment.yml │ └── postBuild ├── images │ └── close.svg ├── install.json ├── package-lock.json ├── package.json ├── pyproject.toml ├── pyquibbler_labextension │ ├── __init__.py │ └── _version.py ├── schema │ └── settings.json ├── setup.py ├── src │ ├── custom.d.ts │ ├── globalConfig.ts │ ├── index.ts │ ├── requester.ts │ ├── session.ts │ ├── toolbarButtonExtension.ts │ └── utils.ts ├── style │ ├── base.css │ ├── index.css │ └── index.js └── tsconfig.json ├── pyquibbler ├── README.md ├── internal_docs │ └── nomenclature.md ├── pyproject.toml ├── pyquibbler │ ├── __init__.py │ ├── assignment │ │ ├── __init__.py │ │ ├── assignment.py │ │ ├── assignment_template.py │ │ ├── assignment_to_from_text.py │ │ ├── default_value.py │ │ ├── exceptions.py │ │ ├── override_choice │ │ │ ├── __init__.py │ │ │ ├── choice_context.py │ │ │ ├── exceptions.py │ │ │ ├── override_choice.py │ │ │ ├── override_dialog.py │ │ │ └── types.py │ │ ├── overrider.py │ │ ├── rounding.py │ │ ├── simplify_assignment.py │ │ └── utils.py │ ├── cache │ │ ├── __init__.py │ │ ├── cache.py │ │ ├── cache_utils.py │ │ ├── holistic_cache.py │ │ └── shallow │ │ │ ├── __init__.py │ │ │ ├── dict_cache.py │ │ │ ├── indexable_cache.py │ │ │ ├── nd_cache │ │ │ ├── __init__.py │ │ │ ├── nd_field_array_cache.py │ │ │ ├── nd_indexable_cache.py │ │ │ ├── nd_unstructured_array_cache.py │ │ │ └── nd_void_cache.py │ │ │ └── shallow_cache.py │ ├── debug_utils │ │ ├── __init__.py │ │ ├── logger.py │ │ ├── timer.py │ │ └── track_instances.py │ ├── env.py │ ├── exceptions.py │ ├── file_syncing │ │ ├── __init__.py │ │ ├── file_syncer.py │ │ ├── quib_file_syncer.py │ │ └── types.py │ ├── function_definitions │ │ ├── __init__.py │ │ ├── definitions.py │ │ ├── func_call.py │ │ ├── func_definition.py │ │ ├── location.py │ │ ├── types.py │ │ └── utils.py │ ├── function_overriding │ │ ├── __init__.py │ │ ├── attribute_override.py │ │ ├── defintion_without_override │ │ │ ├── __init__.py │ │ │ └── python_functions.py │ │ ├── exceptionhook.py │ │ ├── function_override.py │ │ ├── is_initiated.py │ │ ├── override_all.py │ │ ├── quib_overrides │ │ │ ├── __init__.py │ │ │ ├── operators │ │ │ │ ├── __init__.py │ │ │ │ ├── func_definitions.py │ │ │ │ ├── helpers.py │ │ │ │ └── overrides.py │ │ │ └── quib_methods.py │ │ └── third_party_overriding │ │ │ ├── __init__.py │ │ │ ├── general_helpers.py │ │ │ ├── ipywidgets │ │ │ ├── __init__.py │ │ │ ├── denounce_timer.py │ │ │ ├── overrides.py │ │ │ └── quiby_widget_trait.py │ │ │ ├── matplotlib │ │ │ ├── __init__.py │ │ │ ├── func_definitions.py │ │ │ ├── helpers.py │ │ │ └── overrides.py │ │ │ ├── non_quib_overrides │ │ │ ├── __init__.py │ │ │ ├── axes_overrides.py │ │ │ └── widgets_override.py │ │ │ └── numpy │ │ │ ├── __init__.py │ │ │ ├── func_definitions.py │ │ │ ├── helpers.py │ │ │ ├── inverse_functions.py │ │ │ ├── overrides.py │ │ │ ├── quiby_attributes.py │ │ │ └── vectorize_overrides.py │ ├── graphics │ │ ├── __init__.py │ │ ├── global_collecting.py │ │ ├── graphics_collection.py │ │ ├── process_plot_var_args.py │ │ ├── update_new_artists.py │ │ ├── utils.py │ │ ├── widget_utils.py │ │ └── widgets │ │ │ ├── __init__.py │ │ │ ├── base_q_widget.py │ │ │ ├── q_radio_buttons.py │ │ │ ├── q_rectangle_selector.py │ │ │ ├── q_slider.py │ │ │ ├── q_text_box.py │ │ │ └── utils.py │ ├── inversion │ │ ├── __init__.py │ │ ├── invert.py │ │ ├── inverter.py │ │ └── inverters │ │ │ ├── __init__.py │ │ │ ├── casting.py │ │ │ ├── elementwise.py │ │ │ ├── elementwise_single_arg_no_shape.py │ │ │ ├── getitem.py │ │ │ ├── list_operators.py │ │ │ ├── numpy.py │ │ │ ├── obj2quib.py │ │ │ └── transpositional.py │ ├── ipywidget_viewer │ │ ├── __init__.py │ │ └── quib_widget.py │ ├── optional_packages │ │ ├── __init__.py │ │ ├── emulate_missing_packages.py │ │ ├── exceptions.py │ │ ├── get_IPython.py │ │ ├── get_ipycytoscape.py │ │ └── get_ipywidgets.py │ ├── path │ │ ├── __init__.py │ │ ├── data_accessing.py │ │ ├── hashable.py │ │ ├── path_component.py │ │ └── utils.py │ ├── path_translation │ │ ├── __init__.py │ │ ├── array_index_codes.py │ │ ├── array_translation_utils.py │ │ ├── base_translators.py │ │ ├── create_source_func_call.py │ │ ├── exceptions.py │ │ ├── source_func_call.py │ │ ├── translate.py │ │ ├── translators │ │ │ ├── __init__.py │ │ │ ├── apply_along_axis.py │ │ │ ├── axis_accumulation.py │ │ │ ├── axis_all_to_all.py │ │ │ ├── axis_reduction.py │ │ │ ├── elementwise.py │ │ │ ├── getitem.py │ │ │ ├── list_operators.py │ │ │ ├── numpy.py │ │ │ ├── obj2quib.py │ │ │ ├── quiby_name.py │ │ │ ├── shape_only.py │ │ │ ├── transpositional.py │ │ │ └── vectorize.py │ │ ├── types.py │ │ └── utils.py │ ├── project │ │ ├── __init__.py │ │ ├── actions.py │ │ ├── exceptions.py │ │ ├── jupyer_project │ │ │ ├── __init__.py │ │ │ ├── archive_folder.py │ │ │ ├── flask_dialog_server.py │ │ │ ├── jupyter_project.py │ │ │ └── utils.py │ │ ├── project.py │ │ └── undo_group.py │ ├── quib │ │ ├── __init__.py │ │ ├── consts.py │ │ ├── exceptions.py │ │ ├── external_call_failed_exception_handling.py │ │ ├── factory.py │ │ ├── func_calling │ │ │ ├── __init__.py │ │ │ ├── cache_mode.py │ │ │ ├── cached_quib_func_call.py │ │ │ ├── func_calls │ │ │ │ ├── __init__.py │ │ │ │ ├── apply_along_axis_call.py │ │ │ │ ├── known_graphics │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── plot_call.py │ │ │ │ │ └── widgets │ │ │ │ │ │ ├── __init__.py │ │ │ │ │ │ ├── checkbuttons_call.py │ │ │ │ │ │ ├── radio_buttons_call.py │ │ │ │ │ │ ├── rectangle_selector_call.py │ │ │ │ │ │ ├── slider_call.py │ │ │ │ │ │ ├── textbox_call.py │ │ │ │ │ │ └── widget_call.py │ │ │ │ └── vectorize │ │ │ │ │ ├── __init__.py │ │ │ │ │ ├── utils.py │ │ │ │ │ ├── vectorize_call.py │ │ │ │ │ └── vectorize_metadata.py │ │ │ ├── iquib_call.py │ │ │ ├── quib_func_call.py │ │ │ ├── quiby_name_func_call.py │ │ │ └── utils.py │ │ ├── get_value_context_manager.py │ │ ├── graphics │ │ │ ├── __init__.py │ │ │ ├── artist_wrapper.py │ │ │ ├── event_handling │ │ │ │ ├── __init__.py │ │ │ │ ├── affected_args_and_paths.py │ │ │ │ ├── canvas_event_handler.py │ │ │ │ ├── enhance_pick_event.py │ │ │ │ ├── graphics_inverse_assigner.py │ │ │ │ ├── graphics_inverse_assigners.py │ │ │ │ ├── graphics_inverse_assignment.py │ │ │ │ ├── plt_plot_parser.py │ │ │ │ ├── set_lim_inverse_assigner.py │ │ │ │ ├── solvers.py │ │ │ │ └── utils.py │ │ │ ├── graphics_assignment_mode.py │ │ │ ├── graphics_update.py │ │ │ ├── persist.py │ │ │ └── redraw.py │ │ ├── pretty_converters │ │ │ ├── __init__.py │ │ │ ├── math_expressions │ │ │ │ ├── __init__.py │ │ │ │ ├── call_method_expression.py │ │ │ │ ├── func_call_expression.py │ │ │ │ ├── getattr_expression.py │ │ │ │ ├── getitem_expression.py │ │ │ │ ├── math_expression.py │ │ │ │ ├── operators_expressions.py │ │ │ │ └── simple_expressions.py │ │ │ ├── math_precedence.py │ │ │ ├── operators.py │ │ │ └── pretty_convert.py │ │ ├── quib.py │ │ ├── quib_guard.py │ │ ├── quib_properties_viewer.py │ │ ├── specialized_functions │ │ │ ├── __init__.py │ │ │ ├── getattr.py │ │ │ ├── iquib.py │ │ │ ├── proxy.py │ │ │ └── quiby_methods.py │ │ ├── types.py │ │ ├── utils │ │ │ ├── __init__.py │ │ │ ├── iterators.py │ │ │ └── miscellaneous.py │ │ └── variable_metadata.py │ ├── quib_network │ │ ├── __init__.py │ │ ├── network_properties.py │ │ ├── quib_network.py │ │ └── types.py │ ├── reset_all.py │ ├── type_translation │ │ ├── __init__.py │ │ ├── run_conditions.py │ │ ├── translate.py │ │ ├── translators.py │ │ └── utils.py │ ├── user_utils │ │ ├── __init__.py │ │ ├── gui_apps.py │ │ ├── obj2quib.py │ │ ├── project_wraps.py │ │ ├── quibapp.py │ │ └── quiby_funcs.py │ └── utilities │ │ ├── __init__.py │ │ ├── basic_types.py │ │ ├── decorators.py │ │ ├── file_path.py │ │ ├── general_utils.py │ │ ├── get_original_func.py │ │ ├── input_validation_utils.py │ │ ├── iterators.py │ │ ├── missing_value.py │ │ ├── multiple_instance_runner.py │ │ ├── numpy_original_functions.py │ │ ├── operators_with_reverse.py │ │ ├── unpacker.py │ │ └── warning_messages.py └── setup.py ├── tests ├── __init__.py ├── conftest.py ├── functional │ ├── __init__.py │ ├── assignment │ │ ├── __init__.py │ │ ├── overriding_choice │ │ │ ├── __init__.py │ │ │ ├── test_override_choice.py │ │ │ └── test_override_dialog.py │ │ ├── test_assignment_simplifier.py │ │ ├── test_assignment_template.py │ │ ├── test_assignment_to_from_text.py │ │ └── test_overrider.py │ ├── cache │ │ ├── __init__.py │ │ ├── cache_test.py │ │ ├── test_dict_cache.py │ │ ├── test_indexable_cache.py │ │ ├── test_nd_field_array_cache.py │ │ ├── test_nd_unstructured_array_cache.py │ │ ├── test_nd_void_cache.py │ │ └── test_shallow_cache.py │ ├── conftest.py │ ├── file_syncing │ │ ├── __init__.py │ │ └── test_file_syncer.py │ ├── graphics │ │ ├── __init__.py │ │ └── test_global_collecting.py │ ├── inversion │ │ ├── __init__.py │ │ ├── inverters │ │ │ ├── __init__.py │ │ │ ├── test_elementwise_inverter.py │ │ │ ├── test_getitem_inverter.py │ │ │ ├── test_no_shape_elementwise_inverter.py │ │ │ ├── test_transpositional_inverter.py │ │ │ └── utils.py │ │ └── test_invert.py │ ├── path │ │ ├── __init__.py │ │ ├── test_hashable.py │ │ └── test_utils.py │ ├── quib │ │ ├── __init__.py │ │ ├── assignment │ │ │ ├── __init__.py │ │ │ └── test_assignments.py │ │ ├── conftest.py │ │ ├── graphics │ │ │ ├── __init__.py │ │ │ ├── event_handling │ │ │ │ ├── __init__.py │ │ │ │ ├── test_canvas_event_handler.py │ │ │ │ ├── test_plot_inverse_assigner.py │ │ │ │ └── test_set_lim_inverse_assigner.py │ │ │ ├── test_redraw.py │ │ │ └── test_solvers.py │ │ ├── quib_widget │ │ │ ├── __init__.py │ │ │ └── test_quib_widget.py │ │ ├── test_iquib.py │ │ ├── test_quib │ │ │ ├── __init__.py │ │ │ ├── conftest.py │ │ │ ├── get_value │ │ │ │ ├── __init__.py │ │ │ │ ├── conftest.py │ │ │ │ ├── test_accumulation.py │ │ │ │ ├── test_apply_along_axis.py │ │ │ │ ├── test_axiswise.py │ │ │ │ ├── test_elementwise.py │ │ │ │ ├── test_general.py │ │ │ │ ├── test_iquib.py │ │ │ │ ├── test_list_operatos.py │ │ │ │ ├── test_minor_sources.py │ │ │ │ ├── test_proxy.py │ │ │ │ ├── test_reduction.py │ │ │ │ ├── test_transpositional.py │ │ │ │ ├── test_vectorize_call.py │ │ │ │ ├── test_vectorize_metadata.py │ │ │ │ └── utils.py │ │ │ ├── invalidation │ │ │ │ ├── __init__.py │ │ │ │ ├── test_accumulation.py │ │ │ │ ├── test_apply_along_axis.py │ │ │ │ ├── test_axiswise.py │ │ │ │ ├── test_elementwise.py │ │ │ │ ├── test_general.py │ │ │ │ ├── test_list_operators.py │ │ │ │ ├── test_proxy.py │ │ │ │ ├── test_reduction.py │ │ │ │ ├── test_shape_only_data_arg.py │ │ │ │ ├── test_transpositional.py │ │ │ │ ├── test_vectorize_call.py │ │ │ │ └── utils.py │ │ │ ├── pretty_repr │ │ │ │ ├── __init__.py │ │ │ │ ├── test_general.py │ │ │ │ ├── test_operators.py │ │ │ │ ├── test_overrider.py │ │ │ │ └── test_vectorize.py │ │ │ ├── test_array_operator_quib.py │ │ │ ├── test_assign_default.py │ │ │ ├── test_cache_behavior.py │ │ │ ├── test_display_props.py │ │ │ ├── test_exception_causing_assignments.py │ │ │ ├── test_exception_handling.py │ │ │ ├── test_file_management.py │ │ │ ├── test_functions_returning_array_view.py │ │ │ ├── test_general.py │ │ │ ├── test_get_shape_and_type.py │ │ │ ├── test_getattr.py │ │ │ ├── test_graphics.py │ │ │ ├── test_invalidate_and_redraw.py │ │ │ ├── test_inversal.py │ │ │ ├── test_list_operator_inveral.py │ │ │ ├── test_naming.py │ │ │ ├── test_operators.py │ │ │ ├── test_overriding.py │ │ │ ├── test_quib_callback.py │ │ │ ├── test_quib_creation.py │ │ │ ├── test_quib_persistence.py │ │ │ ├── test_quib_relationships.py │ │ │ ├── test_quiby_methods.py │ │ │ ├── test_quiby_name.py │ │ │ └── test_set_get_quib_properties.py │ │ ├── test_quib_guard.py │ │ └── test_uninitiated.py │ ├── quib_network │ │ ├── __init__.py │ │ ├── test_quib_network.py │ │ └── test_quib_network_without_ipywidgets.py │ ├── test_iterators.py │ ├── test_performance_utils.py │ ├── test_project.py │ ├── test_project_wraps.py │ ├── test_quibapp.py │ ├── test_quibbler_user_function.py │ ├── test_utilities.py │ ├── test_utils.py │ ├── third_party_overriding │ │ ├── __init__.py │ │ ├── conftest.py │ │ ├── test_graphics_definition.py │ │ ├── test_not_implemented.py │ │ ├── test_numpy_special.py │ │ ├── test_overriding_definition.py │ │ ├── test_overriding_ipywidgets.py │ │ ├── test_patches.py │ │ └── test_q_rectangle_selector.py │ └── utils.py ├── integration │ ├── __init__.py │ ├── benchmarks │ │ ├── __init__.py │ │ └── test_benchmarks.py │ ├── demos │ │ ├── __init__.py │ │ ├── baseline_images │ │ │ ├── test_covid_demo │ │ │ │ └── covid_demo.png │ │ │ └── test_gear_demo │ │ │ │ └── gear_demo.png │ │ ├── covid_fatality.csv │ │ ├── test_covid_demo.py │ │ └── test_gear_demo.py │ └── quib │ │ ├── __init__.py │ │ └── graphics │ │ ├── __init__.py │ │ ├── test_general.py │ │ ├── test_graphics_assignment.py │ │ ├── test_graphics_assignment_x_y_conflict.py │ │ └── widgets │ │ ├── __init__.py │ │ ├── baseline_images │ │ ├── test_checkbuttons │ │ │ ├── multiple_sets.png │ │ │ └── unset.png │ │ ├── test_radio_buttons │ │ │ └── set_active_multiple_times.png │ │ ├── test_rectangle_selector │ │ │ ├── move.png │ │ │ └── move_list.png │ │ └── test_slider │ │ │ ├── keeps_same_widget.png │ │ │ ├── multiple_times.png │ │ │ └── press_and_release_changes.png │ │ ├── conftest.py │ │ ├── test_checkbuttons.py │ │ ├── test_normal_slider.py │ │ ├── test_radio_buttons.py │ │ ├── test_range_slider.py │ │ ├── test_rectangle_selector.py │ │ ├── test_slider.py │ │ ├── test_textbox.py │ │ └── utils.py └── lab_extension │ ├── README.md │ ├── __init__.py │ ├── notebooks │ ├── example_notebook.ipynb │ ├── notebook_with_error.ipynb │ └── test_saving.ipynb │ └── test_labextension.py └── tox.ini /.coveragerc: -------------------------------------------------------------------------------- 1 | [report] 2 | exclude_lines = 3 | pragma: no cover 4 | if TYPE_CHECKING: 5 | raise AssertionError 6 | raise NotImplementedError 7 | omit = 8 | pyquibbler/user_utils.py 9 | 10 | [run] 11 | concurrency = multiprocessing, thread -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 120 3 | 4 | per-file-ignores = 5 | __init__.py:F401 6 | function_overriding/third_party_overriding/numpy/overrides.py:E241 7 | function_overriding/operators/overrides.py:E241 8 | 9 | ignore = E731,W503,E126,E121,W504 -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | build: 9 | os: "ubuntu-20.04" 10 | tools: 11 | python: "3.10" 12 | 13 | sphinx: 14 | configuration: pyquibbler-documentations/docs/conf.py 15 | 16 | python: 17 | # Install our python package before building the docs 18 | install: 19 | - method: pip 20 | path: ./pyquibbler 21 | extra_requirements: 22 | - sphinx 23 | -------------------------------------------------------------------------------- /MANUAL_INSTALL.md: -------------------------------------------------------------------------------- 1 | ## Manual install for development. 2 | 3 | For users, we recommend installing using `pip install` (see [here](INSTALL.md)). 4 | 5 | 6 | For development, we recommend installing using the `install.py` script 7 | ([here](INSTALL.md)). 8 | 9 | If `install.py` fails, or you otherwise prefer to install manually, follow these steps: 10 | 11 | #### 1. Create environment: 12 | 13 | ```conda create -n pyquibbler --override-channels --strict-channel-priority -c conda-forge -c nodefaults jupyterlab=3 cookiecutter nodejs jupyter-packaging git``` 14 | 15 | ```conda activate pyquibbler``` 16 | 17 | #### 2. Install pyquibbler-labextension: 18 | In the quibbler root directory: 19 | 20 | ```cd pyquibbler-labextension``` 21 | 22 | ```pip install -e .``` 23 | 24 | ```jupyter labextension develop . --overwrite``` 25 | 26 | ```jlpm run build``` 27 | 28 | ```jupyter lab build --minimize=False``` 29 | 30 | If you are developing the client code, then to automatically build following changes, run: 31 | 32 | ```jlpm run watch``` 33 | 34 | 35 | #### 3. Install pyquibbler: 36 | 37 | ```cd ../pyquibbler``` 38 | 39 | ```pip install -e ".[dev, sphinx]"``` 40 | 41 | #### 4. Install chromedriver (for lab tests) 42 | 43 | If you are developing the *pyquibbler jupyter-lab extension*, to be able to run 44 | the specific jupyterlab-extension tests, you will also need to install 45 | `chromedriver` (see [here](tests/lab_extension/README.md)). 46 | -------------------------------------------------------------------------------- /developer_tools/deep_get_referrers.py: -------------------------------------------------------------------------------- 1 | import gc 2 | 3 | 4 | def deep_get_referrers(obj, depth: int, number_sequence=None): 5 | if obj is None: 6 | return 7 | if depth < 0: 8 | return 9 | number_sequence = number_sequence or [] 10 | refs = gc.get_referrers(obj) 11 | for num, ref in enumerate(refs): 12 | current_number_sequence = [*number_sequence, num] 13 | print(f'SEQ={current_number_sequence}: TYPE={type(ref)}', ref, end='\n\n') 14 | deep_get_referrers(ref, depth-1, current_number_sequence) 15 | -------------------------------------------------------------------------------- /developer_tools/list_quibbler_methods.py: -------------------------------------------------------------------------------- 1 | from pyquibbler import iquib, initialize_quibbler 2 | initialize_quibbler() 3 | import numpy as np 4 | 5 | quib = iquib(None) 6 | 7 | dir_quib = np.array(dir(quib)) 8 | 9 | is_magic = np.vectorize(lambda x: x.startswith('__') and x.endswith('__'))(dir_quib) 10 | is_private = np.vectorize(lambda x: x.startswith('__') and not x.endswith('__'))(dir_quib) 11 | is_protected = np.vectorize(lambda x: x.startswith('_') and not x.startswith('__'))(dir_quib) 12 | is_public = ~(is_magic | is_private | is_protected) 13 | 14 | print('Public properties/methods:') 15 | for prop in dir_quib[is_public]: 16 | print(prop) 17 | 18 | print('Protected attributes/methods:') 19 | for prop in dir_quib[is_protected]: 20 | print(prop) 21 | -------------------------------------------------------------------------------- /developer_tools/old_code/rounding.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | TYPE_TO_NUMBER_DIGITS = dict() 4 | 5 | 6 | def get_number_of_digits(value): 7 | type_ = type(value) 8 | if type_ not in TYPE_TO_NUMBER_DIGITS: 9 | 10 | eps = type_(1) 11 | while 1 + eps > 1: 12 | eps = type_(eps / 10) 13 | TYPE_TO_NUMBER_DIGITS[type_] = -np.log10(eps) 14 | 15 | return TYPE_TO_NUMBER_DIGITS[type_] 16 | 17 | -------------------------------------------------------------------------------- /developer_tools/old_code/unoverride_all.py: -------------------------------------------------------------------------------- 1 | import importlib 2 | 3 | 4 | def deactivate_pyquibbler(): 5 | 6 | import matplotlib 7 | importlib.reload(matplotlib) 8 | 9 | import numpy 10 | importlib.reload(numpy) 11 | 12 | from pyquibbler.quib import quib 13 | importlib.reload(quib) 14 | 15 | import ipywidgets 16 | from pyquibbler.function_overriding import override_all 17 | importlib.reload(ipywidgets) 18 | importlib.reload(override_all) 19 | -------------------------------------------------------------------------------- /google56763903e901c5f9.html: -------------------------------------------------------------------------------- 1 | google-site-verification: google56763903e901c5f9.html -------------------------------------------------------------------------------- /license: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Kishony lab, Technion - Israel Institute of Technology 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /pyquibbler-documentations/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = docs 9 | BUILDDIR = build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /pyquibbler-documentations/README.md: -------------------------------------------------------------------------------- 1 | ## Building pyquibbler documentations 2 | 3 | Documentations are written mostly as Jupyter lab notebooks, 4 | stored in `./examples` and `./docs_notebooks.` 5 | 6 | Run `convert_doc_notebooks_to_rst` to convert the notebooks 7 | into rst files which will be created in the `docs` and `docs/examples`. 8 | 9 | There are also `rst` and `md` files in the `docs` folder that are not generated 10 | from notebooks, and can instead be edited directly: 11 | `index.rst`, `Examples.rst`, `What-is-it.md`, 12 | `Rationale.md`, `Quibbler_Enums.rst`, `List_of_functions.rst` 13 | `Installation.rst`. 14 | 15 | The documentations are built by `readthedocs` with any push to master. 16 | 17 | To build the documentations into html locally, run at the project route directory: 18 | `make html` 19 | 20 | happy documenting! 21 | -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/Installation.rst: -------------------------------------------------------------------------------- 1 | Installing Quibbler 2 | ------------------- 3 | 4 | To install *pyquibbler* run: 5 | 6 | ``pip install pyquibbler`` 7 | 8 | If you have Jupyter lab installed, you can also add the 9 | *pyquibbler Jupyter Lab extensions*: 10 | 11 | ``pip install pyquibbler_labextension`` 12 | -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/Quibbler_Enums.rst: -------------------------------------------------------------------------------- 1 | Quibbler special property classes 2 | ================================= 3 | .. currentmodule:: pyquibbler 4 | 5 | .. autosummary:: 6 | :toctree: classes 7 | :nosignatures: 8 | 9 | SaveFormat 10 | GraphicsUpdateType 11 | CacheMode 12 | CacheStatus 13 | AssignmentTemplate 14 | 15 | 16 | .. currentmodule:: pyquibbler.quib_network 17 | 18 | .. autosummary:: 19 | :toctree: classes 20 | :nosignatures: 21 | 22 | Direction 23 | -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/Quibbler_display_classes.rst: -------------------------------------------------------------------------------- 1 | Quibbler display classes 2 | ======================== 3 | .. currentmodule:: pyquibbler 4 | 5 | .. autosummary:: 6 | :toctree: classes 7 | :nosignatures: 8 | 9 | QuibPropertiesViewer 10 | 11 | 12 | .. currentmodule:: pyquibbler.ipywidget_viewer 13 | 14 | .. autosummary:: 15 | :toctree: classes 16 | :nosignatures: 17 | 18 | QuibWidget 19 | -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/_static/custom.css: -------------------------------------------------------------------------------- 1 | .highlight-none { 2 | color: #a0a0a0; 3 | background: none; 4 | border: none; 5 | } 6 | 7 | .highlight-python { 8 | color: #000000; 9 | background: #f8f8f8; 10 | } 11 | 12 | .highlight { 13 | background: none; 14 | } -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/_templates/custom-class-template.rst: -------------------------------------------------------------------------------- 1 | {{ fullname | escape | underline}} 2 | 3 | .. currentmodule:: {{ module }} 4 | 5 | .. autoclass:: {{ objname }} 6 | :members: 7 | :show-inheritance: 8 | :inherited-members: 9 | 10 | {% block methods %} 11 | .. automethod:: __init__ 12 | 13 | {% if methods %} 14 | .. rubric:: {{ _('Methods') }} 15 | 16 | .. autosummary:: 17 | {% for item in methods %} 18 | ~{{ name }}.{{ item }} 19 | {%- endfor %} 20 | {% endif %} 21 | {% endblock %} 22 | 23 | {% block attributes %} 24 | {% if attributes %} 25 | .. rubric:: {{ _('Attributes') }} 26 | 27 | .. autosummary:: 28 | {% for item in attributes %} 29 | ~{{ name }}.{{ item }} 30 | {%- endfor %} 31 | {% endif %} 32 | {% endblock %} -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/_templates/custom-module-template.rst: -------------------------------------------------------------------------------- 1 | {{ fullname | escape | underline}} 2 | 3 | .. automodule:: {{ fullname }} 4 | 5 | {% block attributes %} 6 | {% if attributes %} 7 | .. rubric:: Module Attributes 8 | 9 | .. autosummary:: 10 | :toctree: 11 | {% for item in attributes %} 12 | {{ item }} 13 | {%- endfor %} 14 | {% endif %} 15 | {% endblock %} 16 | 17 | {% block functions %} 18 | {% if functions %} 19 | .. rubric:: {{ _('Functions') }} 20 | 21 | .. autosummary:: 22 | :toctree: 23 | {% for item in functions %} 24 | {{ item }} 25 | {%- endfor %} 26 | {% endif %} 27 | {% endblock %} 28 | 29 | {% block classes %} 30 | {% if classes %} 31 | .. rubric:: {{ _('Classes') }} 32 | 33 | .. autosummary:: 34 | :toctree: 35 | :template: custom-class-template.rst 36 | {% for item in classes %} 37 | {{ item }} 38 | {%- endfor %} 39 | {% endif %} 40 | {% endblock %} 41 | 42 | {% block exceptions %} 43 | {% if exceptions %} 44 | .. rubric:: {{ _('Exceptions') }} 45 | 46 | .. autosummary:: 47 | :toctree: 48 | {% for item in exceptions %} 49 | {{ item }} 50 | {%- endfor %} 51 | {% endif %} 52 | {% endblock %} 53 | 54 | {% block modules %} 55 | {% if modules %} 56 | .. rubric:: Modules 57 | 58 | .. autosummary:: 59 | :toctree: 60 | :template: custom-module-template.rst 61 | :recursive: 62 | {% for item in modules %} 63 | {{ item }} 64 | {%- endfor %} 65 | {% endif %} 66 | {% endblock %} -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/classes/pyquibbler.AssignmentTemplate.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.AssignmentTemplate 2 | ============================= 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autoclass:: AssignmentTemplate 7 | 8 | 9 | .. automethod:: __init__ 10 | 11 | 12 | .. rubric:: Methods 13 | 14 | .. autosummary:: 15 | 16 | ~AssignmentTemplate.__init__ 17 | ~AssignmentTemplate.convert 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/classes/pyquibbler.CacheMode.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.CacheMode 2 | ==================== 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autoclass:: CacheMode 7 | 8 | 9 | .. automethod:: __init__ 10 | 11 | 12 | 13 | 14 | 15 | 16 | .. rubric:: Attributes 17 | 18 | .. autosummary:: 19 | 20 | ~CacheMode.AUTO 21 | ~CacheMode.OFF 22 | ~CacheMode.ON 23 | 24 | -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/classes/pyquibbler.CacheStatus.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.CacheStatus 2 | ====================== 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autoclass:: CacheStatus 7 | 8 | 9 | .. automethod:: __init__ 10 | 11 | 12 | 13 | 14 | 15 | 16 | .. rubric:: Attributes 17 | 18 | .. autosummary:: 19 | 20 | ~CacheStatus.ALL_INVALID 21 | ~CacheStatus.ALL_VALID 22 | ~CacheStatus.PARTIAL 23 | 24 | -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/classes/pyquibbler.GraphicsUpdateType.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.GraphicsUpdateType 2 | ============================= 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autoclass:: GraphicsUpdateType 7 | 8 | 9 | .. automethod:: __init__ 10 | 11 | 12 | 13 | 14 | 15 | 16 | .. rubric:: Attributes 17 | 18 | .. autosummary:: 19 | 20 | ~GraphicsUpdateType.DRAG 21 | ~GraphicsUpdateType.DROP 22 | ~GraphicsUpdateType.CENTRAL 23 | ~GraphicsUpdateType.NEVER 24 | 25 | -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/classes/pyquibbler.QuibPropertiesViewer.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.QuibPropertiesViewer 2 | =============================== 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autoclass:: QuibPropertiesViewer 7 | 8 | 9 | .. automethod:: __init__ 10 | 11 | 12 | .. rubric:: Methods 13 | 14 | .. autosummary:: 15 | 16 | ~QuibPropertiesViewer.__init__ 17 | ~QuibPropertiesViewer.get_html_repr 18 | ~QuibPropertiesViewer.get_text_repr 19 | 20 | 21 | 22 | 23 | 24 | .. rubric:: Attributes 25 | 26 | .. autosummary:: 27 | 28 | ~QuibPropertiesViewer.quib 29 | 30 | -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/classes/pyquibbler.SaveFormat.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.SaveFormat 2 | ===================== 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autoclass:: SaveFormat 7 | 8 | 9 | .. automethod:: __init__ 10 | 11 | 12 | 13 | 14 | 15 | 16 | .. rubric:: Attributes 17 | 18 | .. autosummary:: 19 | 20 | ~SaveFormat.OFF 21 | ~SaveFormat.TXT 22 | ~SaveFormat.BIN 23 | 24 | -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/classes/pyquibbler.ipywidget_viewer.QuibWidget.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.ipywidget\_viewer.QuibWidget 2 | ======================================= 3 | 4 | .. currentmodule:: pyquibbler.ipywidget_viewer 5 | 6 | .. autoclass:: QuibWidget 7 | 8 | 9 | .. automethod:: __init__ 10 | 11 | 12 | .. rubric:: Methods 13 | 14 | .. autosummary:: 15 | 16 | ~QuibWidget.__init__ 17 | ~QuibWidget.build_widget 18 | ~QuibWidget.disable_widget 19 | ~QuibWidget.get_widget 20 | ~QuibWidget.refresh 21 | ~QuibWidget.show_quib_properties_as_pop_up 22 | 23 | 24 | 25 | 26 | 27 | .. rubric:: Attributes 28 | 29 | .. autosummary:: 30 | 31 | ~QuibWidget.quib 32 | ~QuibWidget.quib_ref 33 | 34 | -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/classes/pyquibbler.quib_network.Direction.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.quib\_network.Direction 2 | ================================== 3 | 4 | .. currentmodule:: pyquibbler.quib_network 5 | 6 | .. autoclass:: Direction 7 | 8 | 9 | .. automethod:: __init__ 10 | 11 | 12 | 13 | 14 | 15 | 16 | .. rubric:: Attributes 17 | 18 | .. autosummary:: 19 | 20 | ~Direction.UPSTREAM 21 | ~Direction.DOWNSTREAM 22 | ~Direction.BOTH 23 | ~Direction.ALL 24 | 25 | -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/conceptual_view.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/conceptual_view.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/examples/quibdemo_CheckButtons.rst: -------------------------------------------------------------------------------- 1 | Quib-linked CheckButtons widget 2 | ------------------------------- 3 | 4 | **A demo of interactive quib-linked matplotlib CheckButtons widget.** 5 | 6 | - **Features:** 7 | 8 | - Quiby widgets. 9 | - Quiby axis attributes. 10 | 11 | - **Try me:** 12 | 13 | - Try playing with the check-buttons. 14 | 15 | .. code:: python 16 | 17 | from pyquibbler import iquib, initialize_quibbler, q 18 | initialize_quibbler() 19 | import matplotlib.pyplot as plt 20 | from matplotlib import widgets 21 | %matplotlib tk 22 | 23 | .. code:: python 24 | 25 | # Prepare figure 26 | plt.figure(figsize=(3, 3)) 27 | ax = plt.gca() 28 | 29 | .. code:: python 30 | 31 | # Define input quib for colors 32 | colors = iquib([True, True, True]) 33 | 34 | .. code:: python 35 | 36 | # Define a quib-widget 37 | widgets.CheckButtons(ax=ax, labels=['Red', 'Green', 'Blue'], actives=colors); 38 | 39 | .. code:: python 40 | 41 | # Set the color of the axis to the quib colors 42 | ax.set_facecolor(colors); 43 | .. image:: ../images/demo_gif/quibdemo_CheckButtons.gif 44 | -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/examples/quibdemo_drag_on_curve.rst: -------------------------------------------------------------------------------- 1 | Dragging graphics along a curved line 2 | ------------------------------------- 3 | 4 | **A demo of interactively dragging a point along a curved line.** 5 | 6 | - **Features** 7 | 8 | - Graphics quibs 9 | - Graphics-driven assignments 10 | - Dragging with functional constrains 11 | 12 | - **Try me** 13 | 14 | - Try dragging the circle along the functional curve. 15 | 16 | .. code:: python 17 | 18 | from pyquibbler import iquib, initialize_quibbler, q 19 | initialize_quibbler() 20 | import matplotlib.pyplot as plt 21 | import numpy as np 22 | %matplotlib tk 23 | 24 | .. code:: python 25 | 26 | # Define and plot a curve: 27 | curve_function = lambda v: 4 * v ** 2 - v ** 3 28 | graph_xs = np.arange(0, 4, .2) 29 | graph_ys = curve_function(graph_xs) 30 | plt.figure(figsize=(4, 3)) 31 | plt.plot(graph_xs, graph_ys, 'k') 32 | plt.axis([0, 4, 0, 12]) 33 | 34 | # Define x-y quibs: 35 | point_x = iquib(3.) 36 | point_y = q(curve_function, point_x) 37 | 38 | # Plot the x-y point: 39 | plt.plot(point_x, point_y, 40 | marker='o', markerfacecolor='c', 41 | markersize=18, pickradius=20) 42 | 43 | # Define and plot text: 44 | xy_str = q("X={:.2f}, Y={:.2f}".format, point_x, point_y) 45 | plt.text(point_x, point_y + .6, xy_str, 46 | ha="center", va="bottom", fontsize=13); 47 | .. image:: ../images/demo_gif/quibdemo_drag_on_curve.gif 48 | -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/examples/quibdemo_drag_segments.rst: -------------------------------------------------------------------------------- 1 | Dragging graphics vertically/horizontally 2 | ========================================= 3 | 4 | **A demo of interactive graphics-driven assignments with 5 | vertical/horizontal dragging.** 6 | 7 | - **Features** 8 | 9 | - Graphics-driven assignments 10 | - Horizontal/vertical dragging 11 | - Inverse assignments 12 | 13 | - **Try me** 14 | 15 | - Try dragging the corners ver 16 | - Try dragging the edge 17 | 18 | .. code:: python 19 | 20 | from pyquibbler import iquib, initialize_quibbler, q 21 | initialize_quibbler() 22 | import matplotlib.pyplot as plt 23 | import numpy as np 24 | %matplotlib tk 25 | 26 | .. code:: python 27 | 28 | # Figure setup and graphic properties 29 | plt.figure(figsize=(4, 4)) 30 | plt.axis('square') 31 | plt.axis([-4, 10, -1, 11]) 32 | 33 | # Define x-y coordinates 34 | x0 = iquib(0.) 35 | x1 = iquib(6.) 36 | x2 = iquib(6.) 37 | y = 8. 38 | 39 | # Plot parallelogram 40 | plt.plot([x0, x2 - x1 + x0, x2 + x0, x1 + x0, x0], [0, y, y, 0, 0], 'k:D', linewidth=2); 41 | 42 | 43 | -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/examples/quibdemo_drag_xy.rst: -------------------------------------------------------------------------------- 1 | Dragging graphics affects upstream quibs 2 | ---------------------------------------- 3 | 4 | **A simple demo of interactive graphics-driven assignments.** 5 | 6 | - **Features:** 7 | 8 | - Graphics quibs 9 | - Graphics-driven assignments 10 | - Inverse assignments 11 | 12 | - **Try me:** 13 | 14 | - Try dragging the red marker; note the change in X,Y text, square, 15 | ellipse. 16 | 17 | .. code:: python 18 | 19 | from pyquibbler import iquib, initialize_quibbler, q 20 | import matplotlib.pyplot as plt 21 | import numpy as np 22 | initialize_quibbler() 23 | %matplotlib tk 24 | 25 | .. code:: python 26 | 27 | # Figure setup: 28 | fig1 = plt.figure(figsize=(4, 3)) 29 | plt.axis('square') 30 | plt.axis([-10, 10, -10, 10]); 31 | 32 | .. code:: python 33 | 34 | # Define input quibs for x-y coordinates: 35 | xy = iquib(np.array([3., 4.])) 36 | x, y = xy 37 | 38 | .. code:: python 39 | 40 | # Plot graphics based on x and y: 41 | 42 | # Text: 43 | plt.text(-9, 9, q('X={:.2f}, Y={:.2f}'.format, x, y), 44 | fontsize=16, va='top') 45 | 46 | # Rectangle: 47 | plt.plot(x * np.array([-1, 1, 1, -1, -1]), 48 | y * np.array([-1, -1, 1, 1, -1]), 49 | 'k--o', linewidth=1) 50 | 51 | # Ellipse: 52 | phi = np.linspace(0, 2 * np.pi, 50) 53 | plt.plot(x * np.cos(phi), y * np.sin(phi), 'r-', linewidth=4); 54 | 55 | .. image:: ../images/demo_gif/quibdemo_drag_xy.gif 56 | -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/examples/quibdemo_dragging_fixed_object.rst: -------------------------------------------------------------------------------- 1 | Dragging a fixed object to affect another 2 | ----------------------------------------- 3 | 4 | **A demo of interactively “dragging” a non-movable object.** 5 | 6 | - **Features** 7 | 8 | - Graphics quibs 9 | - Graphics-driven assignments 10 | - Inverse assignments of binary operators 11 | 12 | - **Try me** 13 | 14 | - Try dragging the fixed diamond. It won’t move but will affect the 15 | position of the circle. 16 | 17 | .. code:: python 18 | 19 | from pyquibbler import iquib, initialize_quibbler, q 20 | initialize_quibbler() 21 | import matplotlib.pyplot as plt 22 | import numpy as np 23 | %matplotlib tk 24 | 25 | .. code:: python 26 | 27 | # define and plot a point at xy coordinates: 28 | xy = iquib(np.array([2., 3.])) 29 | plt.axis('square') 30 | plt.axis([-10, 10, -10, 10]) 31 | plt.plot(xy[0], xy[1], 'o', markersize=20) 32 | plt.text(-9, 9, np.array2string(xy, precision=2)) 33 | 34 | # define and plot a differential function quib, 35 | # which is by defintion fixed at [0, 0]: 36 | dxy = xy - xy 37 | plt.plot(dxy[0], dxy[1], 'd', markersize=20); 38 | .. image:: ../images/demo_gif/quibdemo_dragging_fixed_object.gif 39 | -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/examples/quibdemo_image_probing.rst: -------------------------------------------------------------------------------- 1 | Simple quib-app for probing image RGB 2 | ------------------------------------- 3 | 4 | **A simple demo of a quib-based GUI.** 5 | 6 | - **Features** 7 | 8 | - Graphics quibs 9 | - Graphics-driven assignments 10 | - Inverse assignments 11 | 12 | - **Try me** 13 | 14 | - Try dragging the marker and see the RGB values of the image. 15 | 16 | .. code:: python 17 | 18 | from pyquibbler import iquib, initialize_quibbler, q 19 | initialize_quibbler() 20 | import matplotlib.pyplot as plt 21 | import numpy as np 22 | %matplotlib tk 23 | 24 | .. code:: python 25 | 26 | # Load and plot an image: 27 | file = iquib('bacteria_drop.tif') 28 | img = plt.imread(file) 29 | plt.figure(figsize=(8, 3)) 30 | plt.subplot(1, 2, 1) 31 | plt.imshow(img) 32 | 33 | # Choose and plot an x-y point: 34 | xy = iquib([50, 45]) 35 | x, y = xy 36 | plt.plot(x, y, 'w+', markersize=18) 37 | plt.text(5, 10, xy, color='w', fontsize=14) 38 | 39 | # Plot the RGB at the chosen point: 40 | ax = plt.subplot(1, 2, 2) 41 | rgb = img[y, x, :] 42 | plt.bar(['R', 'G', 'B'], rgb, color=list('rgb')) 43 | ax.set_ylim([0, 255]); 44 | 45 | .. image:: ../images/demo_gif/quibdemo_image_probing.gif 46 | -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.can_redo.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.can\_redo 2 | ==================== 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autofunction:: can_redo -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.can_undo.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.can\_undo 2 | ==================== 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autofunction:: can_undo -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.default.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.default 2 | ================== 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autodata:: default -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.get_project.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.get\_project 2 | ======================= 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autofunction:: get_project -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.get_project_directory.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.get\_project\_directory 2 | ================================== 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autofunction:: get_project_directory -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.initialize_quibbler.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.initialize\_quibbler 2 | =============================== 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autofunction:: initialize_quibbler -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.iquib.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.iquib 2 | ================ 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autofunction:: iquib -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.is_quiby.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.is\_quiby 2 | ==================== 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autofunction:: is_quiby -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.list_quiby_funcs.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.list\_quiby\_funcs 2 | ============================= 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autofunction:: list_quiby_funcs -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.load_quibs.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.load\_quibs 2 | ====================== 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autofunction:: load_quibs -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.obj2quib.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.obj2quib 2 | =================== 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autofunction:: obj2quib -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.q.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.q 2 | ============ 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autofunction:: q -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.quib_network.dependency_graph.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.quib\_network.dependency\_graph 2 | ========================================== 3 | 4 | .. currentmodule:: pyquibbler.quib_network 5 | 6 | .. autofunction:: dependency_graph -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.quibapp.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.quibapp 2 | ================== 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autofunction:: quibapp -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.quiby.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.quiby 2 | ================ 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autofunction:: quiby -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.redo.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.redo 2 | =============== 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autofunction:: redo -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.refresh_graphics.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.refresh\_graphics 2 | ============================ 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autofunction:: refresh_graphics -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.reset_file_loading_quibs.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.reset\_file\_loading\_quibs 2 | ====================================== 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autofunction:: reset_file_loading_quibs -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.reset_impure_quibs.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.reset\_impure\_quibs 2 | =============================== 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autofunction:: reset_impure_quibs -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.reset_random_quibs.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.reset\_random\_quibs 2 | =============================== 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autofunction:: reset_random_quibs -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.save_quibs.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.save\_quibs 2 | ====================== 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autofunction:: save_quibs -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.set_project_directory.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.set\_project\_directory 2 | ================================== 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autofunction:: set_project_directory -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.sync_quibs.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.sync\_quibs 2 | ====================== 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autofunction:: sync_quibs -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/functions/pyquibbler.undo.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.undo 2 | =============== 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autofunction:: undo -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/Quickstart_assign_d_and_drag.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/Quickstart_assign_d_and_drag.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/Quickstart_assign_xy_and_drag.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/Quickstart_assign_xy_and_drag.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/Quickstart_interactive_image_cut.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/Quickstart_interactive_image_cut.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/Quickstart_load_image.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/Quickstart_load_image.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/Quickstart_widget_box_size.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/Quickstart_widget_box_size.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/User_defined_functions_pass_quibs.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/User_defined_functions_pass_quibs.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/assignments_assignment_template.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/assignments_assignment_template.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/assignments_jupyter_undo_redo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/assignments_jupyter_undo_redo.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/conceptual_view.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/conceptual_view.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/conceptual_view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/conceptual_view.png -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_COVID_analysis.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_COVID_analysis.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_CheckButtons.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_CheckButtons.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_LotkaVolterra.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_LotkaVolterra.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_Mandelbrot.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_Mandelbrot.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_compare_images.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_compare_images.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_default_overriding.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_default_overriding.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_default_overriding_two_levels.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_default_overriding_two_levels.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_drag_fixed_values.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_drag_fixed_values.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_drag_multiple_points.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_drag_multiple_points.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_drag_on_curve.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_drag_on_curve.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_drag_vertical_horizontal.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_drag_vertical_horizontal.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_drag_whole_object_vs_individual_points.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_drag_whole_object_vs_individual_points.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_drag_xy.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_drag_xy.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_dragging_fixed_object.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_dragging_fixed_object.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_fft.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_fft.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_fit_stocks.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_fit_stocks.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_gear.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_gear.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_image_ROI.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_image_ROI.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_image_probing.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_image_probing.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_image_thresholding.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_image_thresholding.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_ipywidgets_quadratic_eq.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_ipywidgets_quadratic_eq.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_making_the_quib_icon.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_making_the_quib_icon.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_percolation.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_percolation.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_periodic_functions.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_periodic_functions.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_pythagoras.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_pythagoras.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_quiby_axes.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_quiby_axes.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_random_quibs_dice.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_random_quibs_dice.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_repressilator.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_repressilator.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_rushhour.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_rushhour.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_same_data_in_many_forms.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_same_data_in_many_forms.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/demo_gif/quibdemo_slider.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/demo_gif/quibdemo_slider.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/dependency_graph_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/dependency_graph_1.png -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/dialog_box_per_item_factor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/dialog_box_per_item_factor.png -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/divergence_gif/Divergence_arrows.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/divergence_gif/Divergence_arrows.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/divergence_gif/Divergence_passquibs.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/divergence_gif/Divergence_passquibs.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/graphics_gif/graphics_rgb_probing_of_image.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/graphics_gif/graphics_rgb_probing_of_image.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/graphics_gif/graphics_slider_for_box_size.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/graphics_gif/graphics_slider_for_box_size.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/graphics_gif/graphics_xy_axis_labels.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/graphics_gif/graphics_xy_axis_labels.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/graphics_gif/graphics_xy_drag.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/graphics_gif/graphics_xy_drag.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/graphics_gif/graphics_xy_drag_horz_vert.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/graphics_gif/graphics_xy_drag_horz_vert.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/graphics_gif/graphics_xy_refresh.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/graphics_gif/graphics_xy_refresh.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/graphics_inverse.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/graphics_inverse.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/graphics_refresh.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/graphics_refresh.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/inverse_assignment_age_dob.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/inverse_assignment_age_dob.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/inverse_assignment_choice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/inverse_assignment_choice.png -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/inverse_assignment_illustrate.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/inverse_assignment_illustrate.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/labext_open.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/labext_open.png -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/labext_quibbler_menu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/labext_quibbler_menu.png -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/labext_undo_redo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/labext_undo_redo.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/minimal_app_3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/minimal_app_3.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/network_tracing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/network_tracing.png -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/overriding_default_by_dragging.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/overriding_default_by_dragging.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/overriding_set_back_to_default.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/overriding_set_back_to_default.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/quib_editor_save_load.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/quib_editor_save_load.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/quib_editor_thresholds_rgb.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/quib_editor_thresholds_rgb.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/quib_transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/quib_transparent.png -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/quibicon.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/quibicon.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/quiby_ipywidgets_gif/quiby-ipywidgets-bidirectional.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/quiby_ipywidgets_gif/quiby-ipywidgets-bidirectional.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/quiby_ipywidgets_gif/quiby-ipywidgets-bob-alice.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/quiby_ipywidgets_gif/quiby-ipywidgets-bob-alice.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/quiby_ipywidgets_gif/quiby-ipywidgets-linked-widgets-quiby.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/quiby_ipywidgets_gif/quiby-ipywidgets-linked-widgets-quiby.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/quiby_ipywidgets_gif/quiby-ipywidgets-linked-widgets.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/quiby_ipywidgets_gif/quiby-ipywidgets-linked-widgets.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/quiby_ipywidgets_gif/quiby-ipywidgets-lorenz.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/quiby_ipywidgets_gif/quiby-ipywidgets-lorenz.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/quiby_ipywidgets_gif/quiby-ipywidgets-min-max.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/quiby_ipywidgets_gif/quiby-ipywidgets-min-max.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/tile_7_5_inverse.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/tile_7_5_inverse.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/images/tile_7_5_override.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/images/tile_7_5_override.gif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/index.rst: -------------------------------------------------------------------------------- 1 | .. image:: images/quibicon.gif 2 | :width: 300 3 | :align: right 4 | 5 | Data Quibbler 6 | ============= 7 | 8 | **Interactive, transparent, and efficient data analytics.** 9 | 10 | .. toctree:: 11 | :maxdepth: 1 12 | 13 | What-is-it 14 | Rationale 15 | 16 | 17 | Getting started 18 | --------------- 19 | 20 | .. toctree:: 21 | :maxdepth: 1 22 | 23 | Installation 24 | Quickstart 25 | Examples 26 | 27 | 28 | User guide 29 | ---------- 30 | .. toctree:: 31 | :maxdepth: 1 32 | 33 | Introduction 34 | Graphics 35 | Inverse-assignments 36 | Overriding-default-functionality 37 | User-defined-functions 38 | Diverged-evaluation 39 | Random-functions 40 | Quib-naming 41 | Project-save-load 42 | Jupyter-lab-ext 43 | Quiby-ipywidgets 44 | Quib-relationships 45 | 46 | 47 | Functions 48 | --------- 49 | .. toctree:: 50 | :maxdepth: 1 51 | 52 | List_of_functions 53 | List-of-quiby-functions 54 | 55 | 56 | Classes 57 | ------- 58 | .. toctree:: 59 | :maxdepth: 1 60 | 61 | major_classes/Quib_class 62 | major_classes/Project_class 63 | Quibbler_Enums 64 | Quibbler_display_classes 65 | 66 | 67 | Index 68 | ----- 69 | 70 | * :ref:`genindex` 71 | 72 | 73 | -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/major_classes/Project_class.rst: -------------------------------------------------------------------------------- 1 | pyquibbler.Project 2 | ================== 3 | 4 | .. currentmodule:: pyquibbler 5 | 6 | .. autoclass:: Project 7 | :members: 8 | :show-inheritance: 9 | :inherited-members: 10 | 11 | 12 | .. rubric:: Project 13 | 14 | .. autosummary:: 15 | 16 | ~Project.get_or_create 17 | ~Project.quibs 18 | 19 | 20 | .. rubric:: Undo/Redo 21 | 22 | .. autosummary:: 23 | 24 | ~Project.undo 25 | ~Project.redo 26 | ~Project.can_undo 27 | ~Project.can_redo 28 | ~Project.clear_undo_and_redo_stacks 29 | 30 | 31 | .. rubric:: File syncing 32 | 33 | .. autosummary:: 34 | 35 | ~Project.DEFAULT_SAVE_FORMAT 36 | ~Project.save_format 37 | ~Project.directory 38 | ~Project.load_quibs 39 | ~Project.save_quibs 40 | ~Project.sync_quibs 41 | 42 | 43 | .. rubric:: Reset quibs 44 | 45 | .. autosummary:: 46 | 47 | ~Project.reset_file_loading_quibs 48 | ~Project.reset_impure_quibs 49 | ~Project.reset_random_quibs 50 | 51 | 52 | .. rubric:: Graphics 53 | 54 | .. autosummary:: 55 | 56 | ~Project.DEFAULT_GRAPHICS_UPDATE 57 | ~Project.graphics_update 58 | ~Project.refresh_graphics 59 | 60 | -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx 2 | myst_parser 3 | pydata_sphinx_theme 4 | prometheus_client 5 | -------------------------------------------------------------------------------- /pyquibbler-documentations/docs/zips_for_download/examples.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs/zips_for_download/examples.zip -------------------------------------------------------------------------------- /pyquibbler-documentations/docs_notebooks/bacteria_drop.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs_notebooks/bacteria_drop.tif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs_notebooks/bacteria_in_a_droplet.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs_notebooks/bacteria_in_a_droplet.tif -------------------------------------------------------------------------------- /pyquibbler-documentations/docs_notebooks/bacteria_in_droplets.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/docs_notebooks/bacteria_in_droplets.tif -------------------------------------------------------------------------------- /pyquibbler-documentations/examples/README.md: -------------------------------------------------------------------------------- 1 | # Notebook examples 2 | ## Prerequisites 3 | For interactive matplotlib plots we use `ipympl` (`%matplotlib widget`). To install it run: 4 | ```bash 5 | pip install ipympl 6 | pip install ipywidgets 7 | jupyter nbextension install --py widgetsnbextension --user 8 | jupyter nbextension enable widgetsnbextension --user --py 9 | ``` 10 | -------------------------------------------------------------------------------- /pyquibbler-documentations/examples/bacteria_drop.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/examples/bacteria_drop.tif -------------------------------------------------------------------------------- /pyquibbler-documentations/examples/bacteria_in_droplets.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/examples/bacteria_in_droplets.tif -------------------------------------------------------------------------------- /pyquibbler-documentations/examples/pipes.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/examples/pipes.jpg -------------------------------------------------------------------------------- /pyquibbler-documentations/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=source 11 | set BUILDDIR=build 12 | 13 | %SPHINXBUILD% >NUL 2>NUL 14 | if errorlevel 9009 ( 15 | echo. 16 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 17 | echo.installed, then set the SPHINXBUILD environment variable to point 18 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 19 | echo.may add the Sphinx directory to PATH. 20 | echo. 21 | echo.If you don't have Sphinx installed, grab it from 22 | echo.https://www.sphinx-doc.org/ 23 | exit /b 1 24 | ) 25 | 26 | if "%1" == "" goto help 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /pyquibbler-documentations/powerpoint_files/images_lab_extension.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/powerpoint_files/images_lab_extension.pptx -------------------------------------------------------------------------------- /pyquibbler-documentations/powerpoint_files/inverse.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/powerpoint_files/inverse.pptx -------------------------------------------------------------------------------- /pyquibbler-documentations/powerpoint_files/network_tracing.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler-documentations/powerpoint_files/network_tracing.pptx -------------------------------------------------------------------------------- /pyquibbler-labextension/.github_temp/workflows/binder-on-pr.yml: -------------------------------------------------------------------------------- 1 | # Reference https://mybinder.readthedocs.io/en/latest/howto/gh-actions-badges.html 2 | name: Binder Badge 3 | on: 4 | pull_request_target: 5 | types: [opened] 6 | 7 | permissions: 8 | pull-requests: write 9 | 10 | 11 | jobs: 12 | binder: 13 | runs-on: ubuntu-latest 14 | steps: 15 | - name: comment on PR with Binder link 16 | uses: actions/github-script@v3 17 | with: 18 | github-token: ${{secrets.GITHUB_TOKEN}} 19 | script: | 20 | var PR_HEAD_USERREPO = process.env.PR_HEAD_USERREPO; 21 | var PR_HEAD_REF = process.env.PR_HEAD_REF; 22 | github.issues.createComment({ 23 | issue_number: context.issue.number, 24 | owner: context.repo.owner, 25 | repo: context.repo.repo, 26 | body: `[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/${PR_HEAD_USERREPO}/${PR_HEAD_REF}?urlpath=lab) :point_left: Launch a Binder on branch _${PR_HEAD_USERREPO}/${PR_HEAD_REF}_` 27 | }) 28 | env: 29 | PR_HEAD_REF: ${{ github.event.pull_request.head.ref }} 30 | PR_HEAD_USERREPO: ${{ github.event.pull_request.head.repo.full_name }} 31 | 32 | -------------------------------------------------------------------------------- /pyquibbler-labextension/.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | **/node_modules 3 | **/lib 4 | **/package.json 5 | pyquibbler_labextension 6 | -------------------------------------------------------------------------------- /pyquibbler-labextension/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "none", 4 | "arrowParens": "avoid" 5 | } 6 | -------------------------------------------------------------------------------- /pyquibbler-labextension/.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "stylelint-config-recommended", 4 | "stylelint-config-standard", 5 | "stylelint-prettier/recommended" 6 | ], 7 | "rules": { 8 | "property-no-vendor-prefix": null, 9 | "selector-no-vendor-prefix": null, 10 | "value-no-vendor-prefix": null, 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /pyquibbler-labextension/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /pyquibbler-labextension/MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE 2 | include *.md 3 | include pyproject.toml 4 | 5 | include package.json 6 | include install.json 7 | include ts*.json 8 | include yarn.lock 9 | 10 | graft pyquibbler_labextension/labextension 11 | 12 | # Javascript files 13 | graft src 14 | graft style 15 | prune **/node_modules 16 | prune lib 17 | prune binder 18 | 19 | # Patterns to exclude from any directory 20 | global-exclude *~ 21 | global-exclude *.pyc 22 | global-exclude *.pyo 23 | global-exclude .git 24 | global-exclude .ipynb_checkpoints 25 | -------------------------------------------------------------------------------- /pyquibbler-labextension/binder/environment.yml: -------------------------------------------------------------------------------- 1 | # a mybinder.org-ready environment for demoing pyquibbler_labextension 2 | # this environment may also be used locally on Linux/MacOS/Windows, e.g. 3 | # 4 | # conda env update --file binder/environment.yml 5 | # conda activate pyquibbler-labextension-demo 6 | # 7 | name: pyquibbler-labextension-demo 8 | 9 | channels: 10 | - conda-forge 11 | 12 | dependencies: 13 | # runtime dependencies 14 | - python >=3.8,<3.9.0a0 15 | - jupyterlab >=3,<4.0.0a0 16 | # labextension build dependencies 17 | - nodejs >=14,<15 18 | - pip 19 | - wheel 20 | # additional packages for demos 21 | # - ipywidgets 22 | -------------------------------------------------------------------------------- /pyquibbler-labextension/images/close.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /pyquibbler-labextension/install.json: -------------------------------------------------------------------------------- 1 | { 2 | "packageManager": "python", 3 | "packageName": "pyquibbler_labextension", 4 | "uninstallInstructions": "Use your Python package manager (pip, conda, etc.) to uninstall the package pyquibbler_labextension" 5 | } 6 | -------------------------------------------------------------------------------- /pyquibbler-labextension/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = [ 3 | "setuptools>=68", 4 | "wheel", 5 | "jupyter_packaging>=0.12", 6 | "jupyterlab>=3,<4" 7 | ] 8 | build-backend = "setuptools.build_meta" 9 | -------------------------------------------------------------------------------- /pyquibbler-labextension/pyquibbler_labextension/__init__.py: -------------------------------------------------------------------------------- 1 | import json 2 | from pathlib import Path 3 | 4 | from ._version import __version__ 5 | 6 | 7 | HERE = Path(__file__).parent.resolve() 8 | 9 | 10 | with (HERE / "labextension" / "package.json").open() as fid: 11 | data = json.load(fid) 12 | 13 | 14 | def _jupyter_labextension_paths(): 15 | return [{ 16 | "src": "labextension", 17 | "dest": data["name"] 18 | }] 19 | -------------------------------------------------------------------------------- /pyquibbler-labextension/pyquibbler_labextension/_version.py: -------------------------------------------------------------------------------- 1 | import json 2 | from pathlib import Path 3 | 4 | __all__ = ["__version__"] 5 | HERE = Path(__file__).parent.resolve() 6 | 7 | 8 | def _fetchVersion(): 9 | for settings in HERE.rglob("package.json"): 10 | try: 11 | with settings.open() as f: 12 | version = json.load(f)["version"] 13 | return ( 14 | version.replace("-alpha.", "a") 15 | .replace("-beta.", "b") 16 | .replace("-rc.", "rc") 17 | ) 18 | except FileNotFoundError: 19 | pass 20 | 21 | raise FileNotFoundError(f"Could not find package.json under dir {HERE!s}") 22 | 23 | 24 | __version__ = _fetchVersion() 25 | -------------------------------------------------------------------------------- /pyquibbler-labextension/schema/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "title": "Settings", 3 | "description": "Settings.", 4 | "jupyter.lab.menus": { 5 | "main": [ 6 | { 7 | "id": "pyquibbler-menu", 8 | "label": "Quibbler", 9 | "rank": 80, 10 | "items": [ 11 | { 12 | "command": "quibbler:save" 13 | }, 14 | { 15 | "command": "quibbler:load" 16 | }, 17 | { 18 | "command": "quibbler:sync" 19 | }, 20 | { 21 | "command": "quibbler:save-in-notebook" 22 | }, 23 | { 24 | "command": "quibbler:clear-data" 25 | } 26 | ] 27 | } 28 | ] 29 | }, 30 | "additionalProperties": false, 31 | "type": "object" 32 | } 33 | -------------------------------------------------------------------------------- /pyquibbler-labextension/src/custom.d.ts: -------------------------------------------------------------------------------- 1 | declare module '*.svg' { 2 | import React = require('react'); 3 | export const ReactComponent: React.FC>; 4 | const src: string; 5 | export default src; 6 | } -------------------------------------------------------------------------------- /pyquibbler-labextension/src/globalConfig.ts: -------------------------------------------------------------------------------- 1 | 2 | let shouldSaveLoadWithinNotebook = true; 3 | 4 | export const getShouldSaveLoadWithinNotebook = () => { 5 | return shouldSaveLoadWithinNotebook; 6 | } 7 | 8 | export const setShouldSaveLoadWithinNotebook = (should: boolean) => { 9 | shouldSaveLoadWithinNotebook = should; 10 | } 11 | -------------------------------------------------------------------------------- /pyquibbler-labextension/src/toolbarButtonExtension.ts: -------------------------------------------------------------------------------- 1 | import { DocumentRegistry } from '@jupyterlab/docregistry'; 2 | import { INotebookModel, NotebookPanel } from '@jupyterlab/notebook'; 3 | import { IDisposable } from '@lumino/disposable'; 4 | import { ToolbarButton } from '@jupyterlab/apputils'; 5 | 6 | export class ButtonExtension implements DocumentRegistry.IWidgetExtension { 7 | 8 | private readonly label: string; 9 | private readonly callback: () => void; 10 | button: ToolbarButton 11 | 12 | constructor(label: string, callback: () => void) { 13 | this.label = label; 14 | this.callback = callback; 15 | this.button = new ToolbarButton(); 16 | } 17 | 18 | createNew(panel: NotebookPanel): IDisposable { 19 | const button = new ToolbarButton({ 20 | label: this.label, 21 | onClick: this.callback 22 | }); 23 | 24 | panel.toolbar.insertItem(10, this.label, button); 25 | button.enabled = false 26 | this.button = button 27 | return button; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /pyquibbler-labextension/style/base.css: -------------------------------------------------------------------------------- 1 | /* 2 | See the JupyterLab Developer Guide for useful CSS Patterns: 3 | 4 | https://jupyterlab.readthedocs.io/en/stable/developer/css.html 5 | */ 6 | -------------------------------------------------------------------------------- /pyquibbler-labextension/style/index.css: -------------------------------------------------------------------------------- 1 | 2 | @import url('base.css'); 3 | -------------------------------------------------------------------------------- /pyquibbler-labextension/style/index.js: -------------------------------------------------------------------------------- 1 | import './base.css'; 2 | -------------------------------------------------------------------------------- /pyquibbler-labextension/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "allowSyntheticDefaultImports": true, 4 | "composite": true, 5 | "declaration": true, 6 | "esModuleInterop": true, 7 | "incremental": true, 8 | "jsx": "react", 9 | "module": "esnext", 10 | "moduleResolution": "node", 11 | "noEmitOnError": true, 12 | "noImplicitAny": true, 13 | "noUnusedLocals": true, 14 | "preserveWatchOutput": true, 15 | "resolveJsonModule": true, 16 | "outDir": "lib", 17 | "rootDir": "src", 18 | "strict": true, 19 | "strictNullChecks": true, 20 | "target": "es2017", 21 | "types": [] 22 | }, 23 | "include": ["src"] 24 | } 25 | -------------------------------------------------------------------------------- /pyquibbler/pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=64", "wheel"] 3 | build-backend = "setuptools.build_meta" 4 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/__init__.py: -------------------------------------------------------------------------------- 1 | from .cache import CacheStatus 2 | from .quib.factory import create_quib 3 | from .assignment import Assignment, AssignmentTemplate 4 | from .quib import CacheMode, iquib, Quib 5 | from .file_syncing import SaveFormat, ResponseToFileNotDefined 6 | from .quib.graphics import GraphicsUpdateType 7 | from .function_overriding.override_all import initialize_quibbler 8 | from .quib.quib_properties_viewer import QuibPropertiesViewer 9 | from .utilities.file_path import NotebookArchiveMirrorPath 10 | from pyquibbler.debug_utils.timer import timer, timeit 11 | from .user_utils.gui_apps import quibapp 12 | from .user_utils.quiby_funcs import list_quiby_funcs, is_quiby, quiby, q 13 | from .user_utils.project_wraps import get_project, reset_random_quibs, reset_file_loading_quibs, reset_impure_quibs, \ 14 | get_project_directory, set_project_directory, load_quibs, save_quibs, sync_quibs, undo, redo, can_undo, can_redo, \ 15 | refresh_graphics 16 | from .user_utils.obj2quib import obj2quib 17 | from .assignment.default_value import default 18 | from .project import Project 19 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/assignment/__init__.py: -------------------------------------------------------------------------------- 1 | from .overrider import Overrider 2 | from .assignment import Assignment, AssignmentToQuib, AssignmentWithTolerance, create_assignment 3 | from .assignment_template import AssignmentTemplate, RangeAssignmentTemplate, BoundAssignmentTemplate, \ 4 | BoundMaxBelowMinException, RangeStopBelowStartException, InvalidTypeException, \ 5 | TypesMustBeSameInAssignmentTemplateException, create_assignment_template 6 | from .override_choice import get_override_group_for_quib_change, OverrideChoice, OverrideGroup, \ 7 | override_dialog, AssignmentCancelledByUserException, OverrideOptionsTree, CannotChangeQuibAtPathException, \ 8 | OverrideChoiceType, get_override_group_for_quib_changes 9 | from .simplify_assignment import AssignmentSimplifier 10 | from .utils import get_axes_x_y_tolerance 11 | from .default_value import default 12 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/assignment/default_value.py: -------------------------------------------------------------------------------- 1 | from pyquibbler.utilities.basic_types import Singleton 2 | 3 | 4 | class Default(Singleton): 5 | """ 6 | A default value for reverting overriding assignments. 7 | 8 | `default` is a singleton instance which is used as value in quib assignments to indicate 9 | reseting the quib's value back to its default functional value (namely, overruling prior overriding assignments). 10 | 11 | Examples 12 | -------- 13 | >>> n = iquib(7) 14 | >>> x = np.arange(n).setp(allow_overriding=True) 15 | >>> x.get_value() 16 | array([ 0, 1, 2, 3, 4, 5, 6]) 17 | >>> 18 | >>> x[1:-1] = 100 # override functional values 19 | >>> x.get_value() 20 | array([ 0, 100, 100, 100, 100, 100, 6]) 21 | >>> 22 | >>> x[2:-2] = default # set specified elements back to default 23 | >>> x.get_value() 24 | array([ 0, 100, 2, 3, 4, 100, 6]) 25 | >>> 26 | >>> x.assign(default) # reset all the array back to default 27 | >>> x.get_value() 28 | array([ 0, 1, 2, 3, 4, 5, 6]) 29 | """ 30 | 31 | def __repr__(self): 32 | return 'default' 33 | 34 | 35 | default = Default() 36 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/assignment/exceptions.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | from dataclasses import dataclass 3 | 4 | from pyquibbler.exceptions import PyQuibblerException 5 | 6 | 7 | @dataclass 8 | class CannotConvertTextToAssignmentsException(PyQuibblerException): 9 | text: str 10 | 11 | def __str__(self): 12 | return f'Failed loading assignments from file: {self.text}' 13 | 14 | 15 | @dataclass 16 | class CannotConvertAssignmentsToTextException(PyQuibblerException): 17 | 18 | def __str__(self): 19 | return "The quib assignments contain objects that cannot be converted to text." \ 20 | "To save the quib, set the save_format to binary (quib.save_format = 'bin')." 21 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/assignment/override_choice/__init__.py: -------------------------------------------------------------------------------- 1 | from .override_choice import get_override_group_for_quib_change, CannotChangeQuibAtPathException, OverrideOptionsTree, \ 2 | get_override_group_for_quib_changes 3 | from .types import OverrideGroup, QuibChangeWithOverrideRemovals 4 | from .override_dialog import AssignmentCancelledByUserException, OverrideChoice, OverrideChoiceType, \ 5 | choose_override_dialog 6 | from .choice_context import ChoiceContext 7 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/assignment/override_choice/choice_context.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | from dataclasses import dataclass 3 | from typing import TYPE_CHECKING, Tuple 4 | 5 | if TYPE_CHECKING: 6 | from pyquibbler.quib.quib import Quib 7 | 8 | 9 | @dataclass(frozen=True) 10 | class ChoiceContext: 11 | """ 12 | The context in which a choice was taken. 13 | Implements __hash__ and __eq__ to allow caching of user override choices. 14 | A choice can be reused in the context of a new assignment, if the options are the same. 15 | The override options for an inversed quib might change because when different indices are assigned to, the 16 | inversion tree might change (for example if one of the quib's parents is concat). 17 | """ 18 | quibs_available_for_override: Tuple[Quib, ...] 19 | can_diverge: bool 20 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/assignment/override_choice/exceptions.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from pyquibbler.assignment import AssignmentToQuib 4 | from pyquibbler.exceptions import PyQuibblerException 5 | 6 | 7 | @dataclass 8 | class CannotChangeQuibAtPathException(PyQuibblerException): 9 | quib_change: AssignmentToQuib 10 | 11 | def __str__(self): 12 | return f'Cannot perform {self.quib_change.assignment} on {self.quib_change.quib}.\n' \ 13 | f'The quib cannot be overridden and an overridable parent quib to inverse assign into was not found.\n' \ 14 | f'Note that function quibs are not overridable by default.\n' \ 15 | f'To allow overriding, try setting "{self.quib_change.quib}.allow_overriding = True"' 16 | 17 | 18 | @dataclass 19 | class AssignmentCancelledByUserException(PyQuibblerException): 20 | 21 | def __str__(self): 22 | return "User canceled inverse assignment dialog." 23 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/cache/__init__.py: -------------------------------------------------------------------------------- 1 | from typing import Any 2 | 3 | from .holistic_cache import HolisticCache 4 | from .shallow import NdVoidCache 5 | from .shallow.dict_cache import DictCache 6 | from .shallow.indexable_cache import IndexableCache 7 | from .shallow.nd_cache import NdFieldArrayShallowCache, NdUnstructuredArrayCache 8 | from .shallow.shallow_cache import ShallowCache 9 | from .cache import Cache, CacheStatus 10 | from .holistic_cache import PathCannotHaveComponentsException 11 | from .cache_utils import get_uncached_paths_matching_path, \ 12 | get_cached_data_at_truncated_path_given_result_at_uncached_path 13 | 14 | 15 | def create_cache(result: Any) -> ShallowCache: 16 | """ 17 | Create a new cache object matching the result- if no cache is found that specifically supports the requested 18 | object, a shallow cache will be created which does not support partial invalidation (paths must be whole in 19 | validation and invalidation) 20 | """ 21 | 22 | cache_classes = { 23 | NdFieldArrayShallowCache, 24 | NdUnstructuredArrayCache, 25 | IndexableCache, 26 | NdVoidCache, 27 | DictCache 28 | } 29 | for cache_class in cache_classes: 30 | if cache_class.supports_result(result): 31 | return cache_class.create_invalid_cache_from_result(result) 32 | return HolisticCache.create_invalid_cache_from_result(result) 33 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/cache/shallow/__init__.py: -------------------------------------------------------------------------------- 1 | from .dict_cache import DictCache 2 | from .indexable_cache import IndexableCache 3 | from .nd_cache import NdUnstructuredArrayCache, NdFieldArrayShallowCache, NdVoidCache 4 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/cache/shallow/nd_cache/__init__.py: -------------------------------------------------------------------------------- 1 | from .nd_unstructured_array_cache import NdUnstructuredArrayCache 2 | from .nd_field_array_cache import NdFieldArrayShallowCache 3 | from .nd_void_cache import NdVoidCache 4 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/cache/shallow/nd_cache/nd_indexable_cache.py: -------------------------------------------------------------------------------- 1 | from abc import ABC 2 | from typing import List 3 | 4 | import numpy as np 5 | 6 | from pyquibbler.path import PathComponent 7 | from pyquibbler.cache.shallow.shallow_cache import ShallowCache 8 | 9 | 10 | class NdIndexableCache(ShallowCache, ABC): 11 | """ 12 | A base class for an ndarray cache (both unstructured and field array) 13 | """ 14 | 15 | SUPPORTING_TYPES = (np.ndarray,) 16 | 17 | def matches_result(self, result) -> bool: 18 | return super(NdIndexableCache, self).matches_result(result) \ 19 | and result.shape == self.get_value().shape and result.dtype == self.get_value().dtype 20 | 21 | def _set_valid_at_all_paths(self): 22 | mask = np.full(self._value.shape, False, dtype=self._invalid_mask.dtype) 23 | if isinstance(self._invalid_mask, np.void): 24 | self._invalid_mask = np.void(mask) 25 | else: 26 | self._invalid_mask = mask 27 | 28 | @staticmethod 29 | def _filter_empty_paths(paths): 30 | return list(filter(lambda p: np.any(p[-1].component), paths)) 31 | 32 | def _get_all_uncached_paths(self) -> List[List[PathComponent]]: 33 | return self._get_uncached_paths_at_path_component(PathComponent(True)) 34 | 35 | def make_a_copy_if_value_is_a_view(self): 36 | if isinstance(self._value, np.ndarray) and self._value.base is not None: 37 | # array is a "view". We need to make a copy. 38 | self._value = np.array(self._value) 39 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/debug_utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .timer import timer, timeit 2 | from .logger import logger 3 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/debug_utils/logger.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from pathlib import Path 3 | 4 | from pyquibbler.env import LOG_TO_STDOUT, LOG_TO_FILE 5 | 6 | logger = logging.getLogger('pyquibblerLogger') 7 | logger.setLevel(logging.ERROR) 8 | 9 | 10 | if LOG_TO_STDOUT: 11 | logger.addHandler(logging.StreamHandler()) 12 | 13 | if LOG_TO_FILE: 14 | import __main__ 15 | file = Path(__main__.__file__).parent / "pyquibbler.log" 16 | logger.addHandler(logging.FileHandler(file)) 17 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/debug_utils/track_instances.py: -------------------------------------------------------------------------------- 1 | import contextlib 2 | import functools 3 | import gc 4 | from weakref import WeakSet 5 | from typing import Type 6 | 7 | 8 | @contextlib.contextmanager 9 | def track_instances_of_class(cls: Type, raise_if_any_left_alive=True): 10 | """ 11 | Track all instances of a class (weak pointers) 12 | """ 13 | prev_init = cls.__init__ 14 | live_instances = WeakSet() 15 | 16 | @functools.wraps(prev_init) 17 | def _wrapped_init(self, *args, **kwargs): 18 | res = prev_init(self, *args, **kwargs) 19 | live_instances.add(self) 20 | return res 21 | 22 | cls.__init__ = _wrapped_init 23 | 24 | try: 25 | yield live_instances 26 | finally: 27 | gc.collect() 28 | cls.__init__ = prev_init 29 | if raise_if_any_left_alive and len(live_instances) > 0: 30 | raise ValueError(f"Found {len(live_instances)} instances of {cls} left alive") 31 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/exceptions.py: -------------------------------------------------------------------------------- 1 | from abc import ABCMeta, abstractmethod 2 | from dataclasses import dataclass 3 | 4 | 5 | @dataclass 6 | class PyQuibblerException(Exception, metaclass=ABCMeta): 7 | @abstractmethod 8 | def __str__(self): 9 | pass 10 | 11 | 12 | @dataclass 13 | class DebugException(PyQuibblerException, metaclass=ABCMeta): 14 | pass 15 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/file_syncing/__init__.py: -------------------------------------------------------------------------------- 1 | from .types import SaveFormat, ResponseToFileNotDefined, FileNotDefinedException 2 | from .quib_file_syncer import QuibFileSyncer 3 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/function_definitions/__init__.py: -------------------------------------------------------------------------------- 1 | from .definitions import get_definition_for_function, add_definition_for_function 2 | from .types import KeywordArgument, PositionalArgument, SubArgument 3 | from .location import SourceLocation, PositionalSourceLocation, KeywordSourceLocation 4 | from .func_call import FuncCall, FuncArgsKwargs 5 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/function_overriding/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler/pyquibbler/function_overriding/__init__.py -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/function_overriding/attribute_override.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from pyquibbler.function_definitions.func_definition import FuncDefinition 4 | 5 | 6 | @dataclass 7 | class AttributeOverride: 8 | attribute: str 9 | func_definition: FuncDefinition 10 | 11 | 12 | class MethodOverride(AttributeOverride): 13 | pass 14 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/function_overriding/defintion_without_override/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler/pyquibbler/function_overriding/defintion_without_override/__init__.py -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/function_overriding/is_initiated.py: -------------------------------------------------------------------------------- 1 | from pyquibbler.utilities.basic_types import Flag 2 | from pyquibbler.utilities.warning_messages import no_header_warn 3 | 4 | IS_QUIBBLER_INITIATED = Flag(False) 5 | 6 | 7 | def set_quibbler_initialized(value: bool = True): 8 | IS_QUIBBLER_INITIATED.val = value 9 | 10 | 11 | def is_quibbler_initialized(): 12 | return IS_QUIBBLER_INITIATED.val 13 | 14 | 15 | def warn_if_quibbler_not_initialized(message: str = ''): 16 | if not is_quibbler_initialized(): 17 | no_header_warn(message + 'WARNING:\n' 18 | 'Quibbler has not been initialized.\n' 19 | 'Your code will run without quibs.\n' 20 | 'To initiate Quibbler, run initialize_quibbler()\n', 21 | once_only=True) 22 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/function_overriding/quib_overrides/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler/pyquibbler/function_overriding/quib_overrides/__init__.py -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/function_overriding/quib_overrides/operators/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler/pyquibbler/function_overriding/quib_overrides/operators/__init__.py -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/function_overriding/quib_overrides/operators/func_definitions.py: -------------------------------------------------------------------------------- 1 | from pyquibbler.function_definitions.func_definition import create_or_reuse_func_definition 2 | 3 | from pyquibbler.inversion.inverters.list_operators import ListOperatorInverter 4 | from pyquibbler.path_translation.translators.list_operators import \ 5 | ListOperatorBackwardsPathTranslator, ListOperatorForwardsPathTranslator 6 | 7 | from pyquibbler.function_overriding.third_party_overriding.numpy.func_definitions import \ 8 | FUNC_DEFINITION_BINARY_ELEMENTWISE 9 | 10 | FUNC_DEFINITION_BINARY_ELEMENTWISE_AND_LIST = create_or_reuse_func_definition( 11 | base_func_definition=FUNC_DEFINITION_BINARY_ELEMENTWISE, 12 | backwards_path_translators=[ListOperatorBackwardsPathTranslator, 13 | *FUNC_DEFINITION_BINARY_ELEMENTWISE.backwards_path_translators], 14 | forwards_path_translators=[ListOperatorForwardsPathTranslator, 15 | *FUNC_DEFINITION_BINARY_ELEMENTWISE.forwards_path_translators], 16 | inverters=[ListOperatorInverter] + FUNC_DEFINITION_BINARY_ELEMENTWISE.inverters) 17 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/function_overriding/third_party_overriding/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler/pyquibbler/function_overriding/third_party_overriding/__init__.py -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/function_overriding/third_party_overriding/ipywidgets/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler/pyquibbler/function_overriding/third_party_overriding/ipywidgets/__init__.py -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/function_overriding/third_party_overriding/matplotlib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler/pyquibbler/function_overriding/third_party_overriding/matplotlib/__init__.py -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/function_overriding/third_party_overriding/matplotlib/func_definitions.py: -------------------------------------------------------------------------------- 1 | from pyquibbler.function_definitions.func_definition import create_or_reuse_func_definition 2 | 3 | 4 | FUNC_DEFINITION_GRAPHICS = create_or_reuse_func_definition( 5 | is_graphics=True, 6 | ) 7 | 8 | FUNC_DEFINITION_GRAPHICS_AXES_SETTER = create_or_reuse_func_definition( 9 | is_graphics=True, 10 | is_artist_setter=True, 11 | ) 12 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/function_overriding/third_party_overriding/non_quib_overrides/__init__.py: -------------------------------------------------------------------------------- 1 | from .axes_overrides import override_axes_methods 2 | from .widgets_override import switch_widgets_to_quib_supporting_widgets 3 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/function_overriding/third_party_overriding/non_quib_overrides/widgets_override.py: -------------------------------------------------------------------------------- 1 | import matplotlib.widgets 2 | 3 | from pyquibbler.graphics.widgets import QRadioButtons, QSlider, QRangeSlider, \ 4 | QRectangleSelector, QTextBox 5 | 6 | widget_class_names_to_quib_supporting_widget = { 7 | 'RadioButtons': QRadioButtons, 8 | 'Slider': QSlider, 9 | 'RangeSlider': QRangeSlider, 10 | 'RectangleSelector': QRectangleSelector, 11 | 'TextBox': QTextBox, 12 | } 13 | 14 | 15 | def switch_widgets_to_quib_supporting_widgets(): 16 | for widget_class_name, quib_supporting_widget in widget_class_names_to_quib_supporting_widget.items(): 17 | setattr(matplotlib.widgets, widget_class_name, quib_supporting_widget) 18 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/function_overriding/third_party_overriding/numpy/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler/pyquibbler/function_overriding/third_party_overriding/numpy/__init__.py -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/graphics/__init__.py: -------------------------------------------------------------------------------- 1 | from .graphics_collection import GraphicsCollection 2 | 3 | SUPPORTED_BACKENDS = {'MacOSX', 'TkAgg'} 4 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/graphics/process_plot_var_args.py: -------------------------------------------------------------------------------- 1 | from typing import Optional, Callable 2 | 3 | from matplotlib.axes._base import _process_plot_var_args 4 | 5 | 6 | class quibbler_process_plot_var_args(_process_plot_var_args): 7 | """ 8 | make _idx a property to be able to set a callback on it 9 | """ 10 | callback: Optional[Callable] = None 11 | 12 | @property 13 | def _idx(self): 14 | return self.__idx 15 | 16 | @_idx.setter 17 | def _idx(self, value): 18 | if self.callback: 19 | self.callback(self, self.__idx) 20 | self.__idx = value 21 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/graphics/widgets/__init__.py: -------------------------------------------------------------------------------- 1 | from .q_slider import QSlider, QRangeSlider 2 | from .q_radio_buttons import QRadioButtons 3 | from .q_rectangle_selector import QRectangleSelector 4 | from .q_text_box import QTextBox 5 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/graphics/widgets/base_q_widget.py: -------------------------------------------------------------------------------- 1 | import contextlib 2 | 3 | from matplotlib.widgets import Widget 4 | 5 | from pyquibbler.quib.get_value_context_manager import is_within_get_value_context 6 | 7 | 8 | class QWidget(Widget): 9 | 10 | def __init__(self, *args, **kwargs): 11 | self.created_in_get_value_context = False 12 | super().__init__(*args, **kwargs) 13 | self.created_in_get_value_context = is_within_get_value_context() 14 | 15 | @contextlib.contextmanager 16 | def avoid_redraws_if_created_in_get_value_context(self): 17 | if self.created_in_get_value_context: 18 | drawon = self.drawon 19 | self.drawon = False 20 | try: 21 | yield 22 | finally: 23 | self.drawon = drawon 24 | else: 25 | yield 26 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/graphics/widgets/q_radio_buttons.py: -------------------------------------------------------------------------------- 1 | from matplotlib.axes import Axes 2 | from matplotlib.widgets import RadioButtons 3 | from typing import List 4 | 5 | from .base_q_widget import QWidget 6 | 7 | 8 | class QRadioButtons(QWidget, RadioButtons): 9 | """ 10 | Like Radio buttons, also featuring: 11 | - Exposing selected index via the selected_index attribute 12 | """ 13 | 14 | def __init__(self, ax: Axes, labels: List[str], active=0, **kwargs): 15 | self.selected_index = active 16 | super().__init__(ax, labels, active=active, **kwargs) 17 | 18 | def set_active(self, index: int): 19 | self.selected_index = index 20 | with self.avoid_redraws_if_created_in_get_value_context(): 21 | super().set_active(index) 22 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/graphics/widgets/q_text_box.py: -------------------------------------------------------------------------------- 1 | from matplotlib.widgets import TextBox 2 | 3 | 4 | class QTextBox(TextBox): 5 | """ 6 | Like TextBox, also featuring: 7 | - text does not need to be a str. If text is not str, it is converted to str and then converted back to original 8 | type for callback functions. 9 | """ 10 | 11 | def __init__(self, ax, label, initial, **kwargs): 12 | self._type = type(initial) 13 | initial = str(initial) 14 | super().__init__(ax, label, initial, **kwargs) 15 | 16 | def convert_text_to_original_type(self, text): 17 | return self._type(text) 18 | 19 | def on_text_change(self, func): 20 | super().on_text_change(lambda text: func(self.convert_text_to_original_type(text))) 21 | 22 | def on_submit(self, func): 23 | super().on_submit(lambda text: func(self.convert_text_to_original_type(text))) 24 | 25 | # old matplotlib: 26 | # def _rendercursor(self): 27 | # # Matplotlib has a bug - does not update on MacOSX. To fix, we run our own redraw_canvas: 28 | # super()._rendercursor() 29 | # redraw_canvas(self.ax.figure.canvas) 30 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/graphics/widgets/utils.py: -------------------------------------------------------------------------------- 1 | from matplotlib import get_backend 2 | from pyquibbler.utilities.general_utils import Args, Kwargs 3 | 4 | 5 | def prevent_squash(args: Args, kwargs: Kwargs): 6 | obj = args[0] 7 | return not (obj.created_in_get_value_context and get_backend() == 'TkAgg') 8 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/inversion/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler/pyquibbler/inversion/__init__.py -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/inversion/invert.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | from typing import List 3 | 4 | from pyquibbler.assignment import Assignment, default 5 | from pyquibbler.path.data_accessing import deep_get 6 | from pyquibbler.path_translation.source_func_call import SourceFuncCall 7 | from pyquibbler.path_translation.types import Inversal 8 | from pyquibbler.utilities.multiple_instance_runner import MultipleInstanceRunner 9 | 10 | 11 | def invert(func_call: SourceFuncCall, assignment: Assignment, previous_result) -> List[Inversal]: 12 | """ 13 | Get all the inversions for a given assignment on the result of a funccall 14 | """ 15 | 16 | is_default = assignment.is_default() 17 | if is_default: 18 | actual_assignment = Assignment(value=deep_get(previous_result, assignment.path), 19 | path=assignment.path) 20 | else: 21 | actual_assignment = assignment 22 | 23 | inversals = MultipleInstanceRunner(run_condition=None, runner_types=func_call.func_definition.inverters, 24 | func_call=func_call, assignment=actual_assignment, 25 | previous_result=previous_result).run() 26 | 27 | for inversal in inversals: 28 | if is_default: 29 | inversal.assignment.value = default 30 | else: 31 | inversal.cast_assigned_value_by_source_value() 32 | 33 | return inversals 34 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/inversion/inverters/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler/pyquibbler/inversion/inverters/__init__.py -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/inversion/inverters/getitem.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from pyquibbler.assignment.assignment import create_assignment_from_nominal_down_up_values 4 | from pyquibbler.path_translation.base_translators import BackwardsTranslationRunCondition 5 | from pyquibbler.path_translation.translate import backwards_translate 6 | from pyquibbler.path_translation.types import Inversal 7 | 8 | from ..inverter import Inverter 9 | 10 | 11 | class GetItemInverter(Inverter): 12 | 13 | def get_inversals(self): 14 | sources_to_paths_in_sources = backwards_translate( 15 | run_condition=BackwardsTranslationRunCondition.WITH_SHAPE_AND_TYPE, 16 | func_call=self._func_call, 17 | path=self._assignment.path, 18 | shape=np.shape(self._previous_result), 19 | type_=type(self._previous_result) 20 | ) 21 | if len(sources_to_paths_in_sources) != 1: 22 | self._raise_run_failed_exception() 23 | 24 | source = list(sources_to_paths_in_sources.keys())[0] 25 | path_in_source = sources_to_paths_in_sources[source] 26 | nominal_down_up_values = self._get_assignment_nominal_down_up_values() 27 | new_assignment = create_assignment_from_nominal_down_up_values(nominal_down_up_values=nominal_down_up_values, 28 | path=path_in_source) 29 | return [Inversal(source=source, assignment=new_assignment)] 30 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/inversion/inverters/transpositional.py: -------------------------------------------------------------------------------- 1 | from typing import Type, Any 2 | 3 | from pyquibbler.path import Path 4 | from pyquibbler.function_definitions import SourceLocation 5 | from pyquibbler.path_translation import BackwardsPathTranslator, ForwardsPathTranslator, Source 6 | from pyquibbler.path_translation.translators.transpositional import \ 7 | TranspositionalBackwardsPathTranslator, TranspositionalForwardsPathTranslator 8 | 9 | from .numpy import NumpyInverter 10 | 11 | 12 | class TranspositionalOneToOneInverter(NumpyInverter): 13 | """ 14 | Inverts assignments to transpositional functions (like `rot90`, `transpose`, `concatenate`, etc). 15 | Uses the transpositional path translators (based on array index code masks). 16 | """ 17 | BACKWARDS_TRANSLATOR_TYPE: Type[BackwardsPathTranslator] = TranspositionalBackwardsPathTranslator 18 | FORWARDS_TRANSLATOR_TYPE: Type[ForwardsPathTranslator] = TranspositionalForwardsPathTranslator 19 | IS_ONE_TO_MANY_FUNC: bool = False 20 | 21 | def _invert_value(self, source: Source, source_location: SourceLocation, path_in_source: Path, 22 | result_value: Any, path_in_result: Path) -> Any: 23 | return result_value 24 | 25 | 26 | class TranspositionalOneToManyInverter(TranspositionalOneToOneInverter): 27 | """ 28 | Inverts assignments to transpositional functions that can create multiple copies of each element. 29 | (like `full`, `repeat`, etc). 30 | """ 31 | IS_ONE_TO_MANY_FUNC: bool = True 32 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/ipywidget_viewer/__init__.py: -------------------------------------------------------------------------------- 1 | from .quib_widget import QuibWidget 2 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/optional_packages/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler/pyquibbler/optional_packages/__init__.py -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/optional_packages/emulate_missing_packages.py: -------------------------------------------------------------------------------- 1 | from pyquibbler.utilities.basic_types import Mutable 2 | 3 | EMULATE_MISSING_PACKAGES = Mutable([]) 4 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/optional_packages/exceptions.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | from typing import List 3 | 4 | from pyquibbler.exceptions import PyQuibblerException 5 | 6 | 7 | @dataclass 8 | class MissingPackagesForFunctionException(PyQuibblerException): 9 | function_name: str 10 | package_names: List[str] 11 | 12 | def __str__(self): 13 | return f'Using {self.function_name} requires installing the following packages:\n' \ 14 | ', '.join(self.package_names) 15 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/optional_packages/get_IPython.py: -------------------------------------------------------------------------------- 1 | from pyquibbler.optional_packages.emulate_missing_packages import EMULATE_MISSING_PACKAGES 2 | 3 | PACKAGE_NAME = 'IPython' 4 | 5 | if PACKAGE_NAME in EMULATE_MISSING_PACKAGES.val: 6 | raise ImportError 7 | 8 | from IPython.display import display, HTML # noqa: F401, E402 9 | from IPython import get_ipython # noqa: F401, E402 10 | 11 | # noinspection PyPackageRequirements 12 | from ipykernel.comm import Comm # noqa: F401, E402 13 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/optional_packages/get_ipycytoscape.py: -------------------------------------------------------------------------------- 1 | from pyquibbler.optional_packages.emulate_missing_packages import EMULATE_MISSING_PACKAGES 2 | 3 | PACKAGE_NAME = 'ipycytoscape' 4 | 5 | if PACKAGE_NAME in EMULATE_MISSING_PACKAGES.val: 6 | raise ImportError 7 | 8 | # noinspection PyPackageRequirements 9 | import ipycytoscape # noqa 10 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/optional_packages/get_ipywidgets.py: -------------------------------------------------------------------------------- 1 | from pyquibbler.optional_packages.emulate_missing_packages import EMULATE_MISSING_PACKAGES 2 | 3 | PACKAGE_NAME = 'ipywidgets' 4 | 5 | if PACKAGE_NAME in EMULATE_MISSING_PACKAGES.val: 6 | raise ImportError 7 | 8 | # noinspection PyPackageRequirements 9 | import ipywidgets # noqa: F401, E402 10 | 11 | # noinspection PyPackageRequirements 12 | from traitlets import TraitType # noqa: F401, E402 13 | 14 | from ipywidgets.widgets.widget_int import _BoundedIntRange # noqa: F401, E402 15 | from ipywidgets.widgets.widget_float import _BoundedFloatRange # noqa: F401, E402 16 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/path/__init__.py: -------------------------------------------------------------------------------- 1 | from .path_component import Path, Paths, PathComponent, SpecialComponent 2 | from .data_accessing import deep_get, deep_set, FailedToDeepAssignException 3 | from .hashable import get_hashable_path 4 | from .utils import split_path_at_end_of_object 5 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/path/hashable.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | import numpy as np 4 | 5 | from pyquibbler.path import Path 6 | 7 | 8 | @dataclass(frozen=True) 9 | class FrozenSlice: 10 | start: int 11 | step: int 12 | stop: int 13 | 14 | 15 | def _hash_component_value(inner_component): 16 | if isinstance(inner_component, list): 17 | return tuple([_hash_component_value(x) for x in inner_component]) 18 | elif isinstance(inner_component, np.ndarray): 19 | return inner_component.tobytes() 20 | elif isinstance(inner_component, slice): 21 | return FrozenSlice(inner_component.start, inner_component.step, inner_component.stop) 22 | elif isinstance(inner_component, tuple): 23 | return tuple([_hash_component_value(x) for x in inner_component]) 24 | return inner_component 25 | 26 | 27 | def get_hashable_path(path: Path): 28 | """ 29 | Get a hashable path (list of pathcomponents)- this supports known indexing methods 30 | """ 31 | return tuple([ 32 | _hash_component_value(p.component) for p in path 33 | ]) 34 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/path_translation/__init__.py: -------------------------------------------------------------------------------- 1 | from .base_translators import BackwardsPathTranslator, ForwardsPathTranslator 2 | from .source_func_call import SourceFuncCall 3 | from .types import Source, NoMetadataSource, Inversal 4 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/path_translation/array_index_codes.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | from typing import Union 3 | 4 | import numpy as np 5 | from numpy.typing import NDArray 6 | 7 | 8 | INDEX_TYPE = np.int64 9 | 10 | 11 | class IndexCode(INDEX_TYPE, Enum): 12 | """ 13 | Codes for array elements representing a focal source or other objects 14 | """ 15 | OTHERS_ELEMENT = -7 16 | NON_CHOSEN_ELEMENT = -6 17 | SCALAR_NOT_CONTAINING_FOCAL_SOURCE = -5 18 | LIST_NOT_CONTAINING_CHOSEN_ELEMENTS = -4 19 | LIST_CONTAINING_CHOSEN_ELEMENTS = -3 20 | SCALAR_CONTAINING_FOCAL_SOURCE = -2 21 | FOCAL_SOURCE_SCALAR = -1 22 | # otherwise, source elements are represented by their linear index ( >= 0) 23 | 24 | 25 | IndexCodeArray = NDArray[Union[INDEX_TYPE, IndexCode]] 26 | 27 | 28 | MAXIMAL_NON_CHOSEN_ELEMENTS = IndexCode.LIST_NOT_CONTAINING_CHOSEN_ELEMENTS 29 | 30 | 31 | def is_focal_element(obj: NDArray): 32 | return obj > MAXIMAL_NON_CHOSEN_ELEMENTS 33 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/path_translation/exceptions.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from pyquibbler.exceptions import PyQuibblerException 4 | from pyquibbler.utilities.multiple_instance_runner import BaseRunnerFailedException 5 | 6 | 7 | class FailedToTranslateException(BaseRunnerFailedException): 8 | def __str__(self): 9 | return "Failed to translate func call" 10 | 11 | 12 | class PyQuibblerRaggedArrayException(PyQuibblerException): 13 | def __str__(self): 14 | return 'Arrays of ragged arrays or lists are not supported.' 15 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/path_translation/translators/__init__.py: -------------------------------------------------------------------------------- 1 | from .transpositional import TranspositionalForwardsPathTranslator, TranspositionalBackwardsPathTranslator 2 | from .getitem import GetItemBackwardsPathTranslator, GetItemForwardsPathTranslator 3 | from .axis_reduction import AxisReductionForwardsPathTranslator, AxisReductionBackwardsPathTranslator 4 | from .axis_accumulation import \ 5 | AxisAccumulationForwardsPathTranslator, AxisAccumulationBackwardsPathTranslator 6 | from .axis_all_to_all import AxisAllToAllBackwardsPathTranslator, AxisAllToAllForwardsPathTranslator 7 | from .shape_only import ShapeOnlyBackwardsPathTranslator, ShapeOnlyForwardsPathTranslator 8 | from .elementwise import BinaryElementwiseBackwardsPathTranslator, BinaryElementwiseForwardsPathTranslator 9 | from .elementwise import UnaryElementwiseBackwardsPathTranslator, UnaryElementwiseForwardsPathTranslator 10 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/path_translation/translators/obj2quib.py: -------------------------------------------------------------------------------- 1 | from typing import Dict 2 | 3 | from pyquibbler.utilities.iterators import iter_objects_of_type_in_object_recursively 4 | from pyquibbler.path import Path, Paths, split_path_at_end_of_object 5 | 6 | from ..base_translators import BackwardsTranslationRunCondition, BackwardsPathTranslator, ForwardsPathTranslator 7 | from ..types import Source 8 | 9 | 10 | class Obj2QuibBackwardsPathTranslator(BackwardsPathTranslator): 11 | 12 | RUN_CONDITIONS = [BackwardsTranslationRunCondition.NO_SHAPE_AND_TYPE] 13 | 14 | def _backwards_translate(self) -> Dict[Source, Path]: 15 | path_within_object, remaining_path, obj = split_path_at_end_of_object(self._func_call.args[0], self._path) 16 | 17 | if isinstance(obj, Source): 18 | return {obj: remaining_path} 19 | 20 | sources_within_the_referenced_path = iter_objects_of_type_in_object_recursively(Source, obj) 21 | return {source: [] for source in sources_within_the_referenced_path} 22 | 23 | 24 | class Obj2QuibForwardsPathTranslator(ForwardsPathTranslator): 25 | 26 | def _forward_translate(self) -> Paths: 27 | return [self._source_location.path + self._path] 28 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/path_translation/translators/quiby_name.py: -------------------------------------------------------------------------------- 1 | from typing import Dict 2 | 3 | from pyquibbler.path.path_component import Path, Paths 4 | 5 | from pyquibbler.path_translation.base_translators import ForwardsPathTranslator, BackwardsPathTranslator 6 | from pyquibbler.path_translation.types import Source 7 | 8 | 9 | class QuibyNameBackwardsPathTranslator(BackwardsPathTranslator): 10 | """ 11 | We need no data from the sources. 12 | """ 13 | def _backwards_translate(self) -> Dict[Source, Path]: 14 | sources_to_paths = {} 15 | for source in self._func_call.get_data_sources(): 16 | sources_to_paths[source] = [] 17 | return sources_to_paths 18 | 19 | 20 | class QuibyNameForwardsPathTranslator(ForwardsPathTranslator): 21 | """ 22 | We are not affected by change the sources. 23 | """ 24 | def _forward_translate(self) -> Paths: 25 | return [] 26 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/path_translation/translators/shape_only.py: -------------------------------------------------------------------------------- 1 | from typing import Dict 2 | 3 | from pyquibbler.path.path_component import PathComponent, Path, Paths 4 | 5 | from pyquibbler.path_translation.base_translators import ForwardsPathTranslator, BackwardsPathTranslator 6 | from pyquibbler.path_translation.types import Source 7 | 8 | 9 | class ShapeOnlyBackwardsPathTranslator(BackwardsPathTranslator): 10 | """ 11 | For functions like, np.ones_like, np.zeros_like, np.shape, 12 | we only need the shape of sources. Not their value. 13 | """ 14 | def _backwards_translate(self) -> Dict[Source, Path]: 15 | sources_to_paths = {} 16 | for source in self._func_call.get_data_sources(): 17 | sources_to_paths[source] = [PathComponent(None)] 18 | return sources_to_paths 19 | 20 | 21 | class ShapeOnlyForwardsPathTranslator(ForwardsPathTranslator): 22 | """ 23 | We are only affected if sources change their shape. Element-wise changes are not affecting us. 24 | We need to take care of lists that can change their size due to assignment. 25 | """ 26 | def _forward_translate(self) -> Paths: 27 | path = self._path 28 | is_list_extension_possible = \ 29 | len(path) \ 30 | and self._get_source_type() is list \ 31 | and isinstance(path[0].component, slice) 32 | return [] if len(path) and not is_list_extension_possible else [[]] 33 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/path_translation/utils.py: -------------------------------------------------------------------------------- 1 | from copy import copy 2 | from typing import Any 3 | 4 | from pyquibbler.utilities.iterators import SHALLOW_MAX_LENGTH, SHALLOW_MAX_DEPTH, recursively_run_func_on_object 5 | 6 | from .types import Source 7 | 8 | 9 | def copy_and_replace_sources_with_vals(obj: Any): 10 | """ 11 | Copy `obj` while replacing quibs with their values, with a limited depth and length. 12 | """ 13 | from matplotlib.artist import Artist 14 | 15 | def replace_with_value_if_source_or_copy(o): 16 | if isinstance(o, Source): 17 | return o.value 18 | if isinstance(o, Artist): 19 | return o 20 | try: 21 | return copy(o) 22 | except NotImplementedError: 23 | return o 24 | 25 | result = recursively_run_func_on_object(func=replace_with_value_if_source_or_copy, max_depth=SHALLOW_MAX_DEPTH, 26 | max_length=SHALLOW_MAX_LENGTH, obj=obj) 27 | return result 28 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/project/__init__.py: -------------------------------------------------------------------------------- 1 | from .project import Project, NothingToUndoException, NothingToRedoException 2 | from .actions import Action, AddAssignmentAction 3 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/project/exceptions.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from pyquibbler.exceptions import PyQuibblerException 4 | 5 | 6 | class NothingToUndoException(PyQuibblerException): 7 | 8 | def __str__(self): 9 | return "There are no actions left to undo." 10 | 11 | 12 | class NothingToRedoException(PyQuibblerException): 13 | 14 | def __str__(self): 15 | return "There are no actions left to redo." 16 | 17 | 18 | @dataclass 19 | class NoProjectDirectoryException(PyQuibblerException): 20 | action: str 21 | 22 | def __str__(self): 23 | return f"The project directory is not defined.\n" \ 24 | f"To {self.action} quibs, set the project directory (see set_project_directory)." 25 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/project/jupyer_project/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler/pyquibbler/project/jupyer_project/__init__.py -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/project/jupyer_project/flask_dialog_server.py: -------------------------------------------------------------------------------- 1 | 2 | # TODO: werkzeug version compatibility fix. 3 | # Need to resolve werkzeug version 4 | # I tried setting the version to 2.0.3 in setup.py, which has 5 | # the matching import, but then the installation fails on the build of matplotlib. 6 | # For now, I'm doing his ad-hoc patch. 7 | try: 8 | from flask import Flask, request 9 | except ImportError: 10 | from urllib.parse import quote as url_quote 11 | from werkzeug import urls 12 | urls.url_quote = url_quote 13 | from flask import Flask, request 14 | 15 | from flask_cors import CORS 16 | 17 | 18 | def run_flask_app(port, answer_queue): 19 | app = Flask(__name__) 20 | CORS(app) 21 | 22 | @app.route('/ping') 23 | def pong(): 24 | return 'pong' 25 | 26 | @app.route('/answer', methods=['POST']) 27 | def dialog_answer(): 28 | answer_queue.put(request.json["option"]) 29 | return 'done' 30 | 31 | app.run('0.0.0.0', port=port) 32 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/project/jupyer_project/utils.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import sys 3 | 4 | 5 | def find_free_port(): 6 | with socket.socket() as s: 7 | s.bind(('', 0)) # Bind to a free port provided by the host. 8 | return s.getsockname()[1] # Return the port number assigned. 9 | 10 | 11 | def is_within_jupyter_lab() -> bool: 12 | try: 13 | from pyquibbler.optional_packages.get_IPython import get_ipython, Comm # noqa: F401 14 | shell = get_ipython().__class__.__name__ 15 | if shell == 'ZMQInteractiveShell': 16 | return True # Jupyter notebook or qtconsole 17 | elif shell == 'TerminalInteractiveShell': 18 | return False # Terminal running IPython 19 | else: 20 | return False # Other type (?) 21 | except (NameError, ImportError): 22 | return False # Probably standard Python interpreter 23 | 24 | 25 | def is_within_colab() -> bool: 26 | return 'google.colab' in sys.modules 27 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/__init__.py: -------------------------------------------------------------------------------- 1 | from pyquibbler.quib.specialized_functions.iquib import iquib 2 | from .func_calling.cache_mode import CacheMode 3 | from .quib import Quib 4 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/consts.py: -------------------------------------------------------------------------------- 1 | MAX_BYTES_PER_SECOND = 2 ** 30 2 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/func_calling/__init__.py: -------------------------------------------------------------------------------- 1 | from .quib_func_call import QuibFuncCall, WholeValueNonGraphicQuibFuncCall 2 | from .cached_quib_func_call import CachedQuibFuncCall 3 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/func_calling/cache_mode.py: -------------------------------------------------------------------------------- 1 | from pyquibbler.utilities.basic_types import StrEnum 2 | 3 | 4 | class CacheMode(StrEnum): 5 | """ 6 | Modes of quib caching. 7 | 8 | Dictates whether a quib should cache its function result, to avoid recalculations on repeated calls. 9 | 10 | Options are listed below (see Attributes). 11 | 12 | Note 13 | ---- 14 | Quibs with random functions and graphics quibs are always cached (even with cache mode set to ``'off'``). 15 | 16 | See Also 17 | -------- 18 | Quib.cache_mode, CacheStatus 19 | """ 20 | AUTO = 'auto' 21 | "Auto cache decision based on the ratio between evaluation time and memory consumption (``'auto'``)." 22 | 23 | OFF = 'off' 24 | "Do not cache, unless the quib's function is random or graphics (``'off'``)." 25 | 26 | ON = 'on' 27 | "Always cache (``'on'``)." 28 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/func_calling/func_calls/__init__.py: -------------------------------------------------------------------------------- 1 | from .known_graphics import PlotQuibFuncCall, SliderQuibFuncCall, RangeSliderQuibFuncCall, RadioButtonsQuibFuncCall, \ 2 | RectangleSelectorQuibFuncCall, CheckButtonsQuibFuncCall 3 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/func_calling/func_calls/known_graphics/__init__.py: -------------------------------------------------------------------------------- 1 | from .widgets import SliderQuibFuncCall, RangeSliderQuibFuncCall, RadioButtonsQuibFuncCall, \ 2 | RectangleSelectorQuibFuncCall, CheckButtonsQuibFuncCall 3 | from .plot_call import PlotQuibFuncCall 4 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/func_calling/func_calls/known_graphics/plot_call.py: -------------------------------------------------------------------------------- 1 | from pyquibbler.path.path_component import Path 2 | from pyquibbler.quib.func_calling import CachedQuibFuncCall 3 | 4 | 5 | class PlotQuibFuncCall(CachedQuibFuncCall): 6 | 7 | def _run_on_path(self, valid_path: Path): 8 | res = super(PlotQuibFuncCall, self)._run_on_path(valid_path) 9 | graphics_collection = self.graphics_collections[()] 10 | for i, artist in enumerate(graphics_collection.artists): 11 | artist._index_in_plot = i 12 | 13 | return res 14 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/func_calling/func_calls/known_graphics/widgets/__init__.py: -------------------------------------------------------------------------------- 1 | from .slider_call import SliderQuibFuncCall, RangeSliderQuibFuncCall 2 | from .radio_buttons_call import RadioButtonsQuibFuncCall 3 | from .rectangle_selector_call import RectangleSelectorQuibFuncCall 4 | from .checkbuttons_call import CheckButtonsQuibFuncCall 5 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/func_calling/func_calls/known_graphics/widgets/checkbuttons_call.py: -------------------------------------------------------------------------------- 1 | import functools 2 | from typing import Optional 3 | 4 | from matplotlib.widgets import CheckButtons 5 | 6 | from pyquibbler.path import PathComponent 7 | from .widget_call import WidgetQuibFuncCall 8 | 9 | 10 | class CheckButtonsQuibFuncCall(WidgetQuibFuncCall): 11 | 12 | @staticmethod 13 | def _get_control_variable() -> Optional[str]: 14 | return 'actives' 15 | 16 | def on_change_checkbuttons(self, widget, new_value): 17 | from pyquibbler.quib.quib import Quib 18 | actives = self.func_args_kwargs.get('actives') 19 | buttons_checked = widget.get_status() 20 | labels = self.func_args_kwargs.get('labels') 21 | new_value_index = labels.index(new_value) 22 | if isinstance(actives, Quib): 23 | self._inverse_assign(actives, [PathComponent(new_value_index)], 24 | value=buttons_checked[new_value_index]) 25 | elif isinstance(actives[new_value_index], Quib): 26 | self._inverse_assign(actives[new_value_index], [], 27 | value=buttons_checked[new_value_index]) 28 | 29 | def _connect_callbacks(self, widget: CheckButtons): 30 | widget.on_clicked(functools.partial(self.on_change_checkbuttons, widget)) 31 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/func_calling/func_calls/known_graphics/widgets/radio_buttons_call.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from matplotlib.widgets import RadioButtons 4 | 5 | from pyquibbler.quib.func_calling.func_calls.known_graphics.widgets.widget_call import WidgetQuibFuncCall 6 | 7 | 8 | class RadioButtonsQuibFuncCall(WidgetQuibFuncCall): 9 | 10 | @staticmethod 11 | def _get_control_variable() -> Optional[str]: 12 | return 'active' 13 | 14 | def _on_clicked(self, new_value): 15 | from pyquibbler.quib.quib import Quib 16 | active = self.func_args_kwargs.get('active') 17 | if isinstance(active, Quib): 18 | self._inverse_assign(active, [], self.func_args_kwargs.get('labels').index(new_value)) 19 | 20 | def _connect_callbacks(self, widget: RadioButtons): 21 | widget.on_clicked(self._on_clicked) 22 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/func_calling/func_calls/known_graphics/widgets/textbox_call.py: -------------------------------------------------------------------------------- 1 | from typing import Optional 2 | 3 | from matplotlib.widgets import TextBox 4 | 5 | from pyquibbler.quib.quib import Quib 6 | from .widget_call import WidgetQuibFuncCall 7 | 8 | 9 | class TextBoxQuibFuncCall(WidgetQuibFuncCall): 10 | 11 | @staticmethod 12 | def _get_control_variable() -> Optional[str]: 13 | return 'initial' 14 | 15 | def _on_change(self, new_value: str): 16 | val = self.func_args_kwargs.get('initial') 17 | if isinstance(val, Quib): 18 | self._inverse_assign(val, [], new_value) 19 | 20 | def _connect_callbacks(self, widget: TextBox): 21 | widget.on_submit(self._on_change) 22 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/func_calling/func_calls/vectorize/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler/pyquibbler/quib/func_calling/func_calls/vectorize/__init__.py -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/func_calling/iquib_call.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from typing import Any, List, Union 4 | 5 | from pyquibbler.path import Path 6 | from pyquibbler.quib.func_calling import WholeValueNonGraphicQuibFuncCall 7 | 8 | 9 | class IQuibFuncCall(WholeValueNonGraphicQuibFuncCall): 10 | """ 11 | Represents a FuncCall with identity function applied to a single argument with no quibs. 12 | No need to cache. Also no graphics. 13 | """ 14 | 15 | @property 16 | def _value(self): 17 | return self.func_args_kwargs.get_arg_values_by_position()[0] 18 | 19 | def _run(self, valid_paths: List[Union[None, Path]]) -> Any: 20 | # func is identity_function, so we this will simply return the "value", which is the first argument: 21 | return self._value 22 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/func_calling/quiby_name_func_call.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from typing import Any, List, Union 4 | 5 | from pyquibbler.path import Path 6 | from pyquibbler.quib.func_calling.quib_func_call import WholeValueNonGraphicQuibFuncCall 7 | 8 | 9 | class QuibyNameFuncCall(WholeValueNonGraphicQuibFuncCall): 10 | """ 11 | Represents a FuncCall that of a quiby_name quib: returning the name of its quib argument. 12 | """ 13 | 14 | def _run(self, valid_paths: List[Union[None, Path]]) -> Any: 15 | # func is get_quib_name 16 | return self.func_args_kwargs.func(*self.func_args_kwargs.args, **self.func_args_kwargs.kwargs) 17 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/get_value_context_manager.py: -------------------------------------------------------------------------------- 1 | from contextlib import contextmanager 2 | from typing import Optional 3 | 4 | GET_VALUE_CONTEXT_PASS_QUIBS: Optional[bool] = None 5 | 6 | 7 | def reset_all_get_value_context(): 8 | """ 9 | Reset all global variables to their initial state 10 | """ 11 | global GET_VALUE_CONTEXT_PASS_QUIBS 12 | GET_VALUE_CONTEXT_PASS_QUIBS = None 13 | 14 | 15 | def is_reset_all_get_value_context() -> bool: 16 | """ 17 | Check if all the global variables are in their initial state 18 | """ 19 | return GET_VALUE_CONTEXT_PASS_QUIBS is None 20 | 21 | 22 | @contextmanager 23 | def get_value_context(pass_quibs: bool = False): 24 | """ 25 | Change IS_WITHIN_GET_VALUE_CONTEXT while in the process of running get_value. 26 | This has to be a static method as the IS_WITHIN_GET_VALUE_CONTEXT is a global state for all quib types 27 | """ 28 | global GET_VALUE_CONTEXT_PASS_QUIBS 29 | if GET_VALUE_CONTEXT_PASS_QUIBS is not None: 30 | yield 31 | else: 32 | GET_VALUE_CONTEXT_PASS_QUIBS = pass_quibs 33 | try: 34 | yield 35 | finally: 36 | GET_VALUE_CONTEXT_PASS_QUIBS = None 37 | 38 | 39 | def is_within_get_value_context() -> bool: 40 | return GET_VALUE_CONTEXT_PASS_QUIBS is not None 41 | 42 | 43 | def get_value_context_pass_quibs() -> Optional[bool]: 44 | return GET_VALUE_CONTEXT_PASS_QUIBS 45 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/graphics/__init__.py: -------------------------------------------------------------------------------- 1 | from .graphics_update import GraphicsUpdateType 2 | from .redraw import aggregate_redraw_mode, redraw_quib_with_graphics_or_add_in_aggregate_mode 3 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/graphics/event_handling/__init__.py: -------------------------------------------------------------------------------- 1 | from .graphics_inverse_assigners import get_override_group_for_axes_plot, get_override_group_for_axes_scatter 2 | from .set_lim_inverse_assigner import get_override_group_for_axes_set_lim 3 | from .canvas_event_handler import CanvasEventHandler 4 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/graphics/graphics_assignment_mode.py: -------------------------------------------------------------------------------- 1 | from contextlib import contextmanager 2 | from typing import Optional 3 | 4 | from matplotlib.axes import Axes 5 | 6 | GRAPHICS_ASSIGNMENT_MODE_AXES: Optional[Axes] = None 7 | 8 | 9 | def reset_all_graphics_assignment_mode(): 10 | """ 11 | Resets the graphics assignment mode to its initial state. 12 | """ 13 | global GRAPHICS_ASSIGNMENT_MODE_AXES 14 | GRAPHICS_ASSIGNMENT_MODE_AXES = None 15 | 16 | 17 | def is_reset_all_graphics_assignment_mode() -> bool: 18 | """ 19 | Checks if the graphics assignment mode is in its initial state. 20 | """ 21 | return GRAPHICS_ASSIGNMENT_MODE_AXES is None 22 | 23 | 24 | @contextmanager 25 | def graphics_assignment_mode(axes: Axes): 26 | """ 27 | In graphics assignment mode. Indicating the axes invoking the assignment. 28 | """ 29 | 30 | global GRAPHICS_ASSIGNMENT_MODE_AXES 31 | GRAPHICS_ASSIGNMENT_MODE_AXES = axes 32 | try: 33 | yield 34 | finally: 35 | GRAPHICS_ASSIGNMENT_MODE_AXES = None 36 | 37 | 38 | def get_graphics_assignment_mode_axes() -> Optional[Axes]: 39 | return GRAPHICS_ASSIGNMENT_MODE_AXES 40 | 41 | 42 | def is_within_graphics_assignment_mode() -> bool: 43 | return GRAPHICS_ASSIGNMENT_MODE_AXES is not None 44 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/graphics/graphics_update.py: -------------------------------------------------------------------------------- 1 | from pyquibbler.utilities.basic_types import StrEnum 2 | 3 | 4 | class GraphicsUpdateType(StrEnum): 5 | """ 6 | Options for specifying when to refresh a graphics quib. 7 | 8 | See Also 9 | -------- 10 | pyquibbler.refresh_graphics, Quib.graphics_update 11 | """ 12 | 13 | DRAG = 'drag' 14 | "Refresh immediately as graphics object are dragged (``'drag'``)." 15 | 16 | DROP = 'drop' 17 | "Refresh at end of dragging, upon mouse drop (``'drop'``)." 18 | 19 | CENTRAL = 'central' 20 | "Do not refresh automatically; only refresh upon explicit `refresh_graphics` command (``'central'``)." 21 | 22 | NEVER = 'never' 23 | "Do not refresh (``'never'``)." 24 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/pretty_converters/__init__.py: -------------------------------------------------------------------------------- 1 | from .math_expressions.math_expression import MathExpression 2 | from .math_expressions.simple_expressions import FailedMathExpression, NameMathExpression 3 | from .math_expressions.func_call_expression import FunctionCallMathExpression 4 | from .pretty_convert import get_math_expression_of_func_with_args_and_kwargs 5 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/pretty_converters/math_expressions/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler/pyquibbler/quib/pretty_converters/math_expressions/__init__.py -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/pretty_converters/math_expressions/call_method_expression.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | 3 | from dataclasses import dataclass 4 | 5 | from pyquibbler.utilities.general_utils import Args, Kwargs 6 | from .func_call_expression import FunctionCallMathExpression 7 | from ..math_precedence import MathPrecedence 8 | 9 | from typing import TYPE_CHECKING 10 | if TYPE_CHECKING: 11 | from pyquibbler.quib.specialized_functions.quiby_methods import CallObjectMethod 12 | 13 | 14 | @dataclass 15 | class CallMethodExpression(FunctionCallMathExpression): 16 | 17 | def get_str(self, with_spaces: bool = True): 18 | obj, *args = self.get_pretty_args() 19 | return f'{obj}.{self.func_name}({", ".join([*args, *self.get_pretty_kwargs()])})' 20 | 21 | @property 22 | def precedence(self) -> MathPrecedence: 23 | return MathPrecedence.SUBSCRIPTION 24 | 25 | 26 | def call_method_converter(func: CallObjectMethod, args: Args, kwargs: Kwargs) -> CallMethodExpression: 27 | return CallMethodExpression(func_name=func.method, 28 | args=args, 29 | kwargs=kwargs) 30 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/pretty_converters/math_expressions/getattr_expression.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | from typing import Callable, Any 3 | 4 | from pyquibbler.utilities.general_utils import Args 5 | from .math_expression import MathExpression 6 | from ..math_precedence import MathPrecedence 7 | 8 | 9 | @dataclass 10 | class GetAttrExpression(MathExpression): 11 | obj: Any 12 | item: str 13 | 14 | def get_str(self, with_spaces: bool = True): 15 | return f"{self.obj}.{self.item}" 16 | 17 | @property 18 | def precedence(self) -> MathPrecedence: 19 | return MathPrecedence.SUBSCRIPTION 20 | 21 | 22 | def getattr_converter(func: Callable, args: Args) -> GetAttrExpression: 23 | obj, item = args 24 | return GetAttrExpression(obj, item) 25 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/pretty_converters/math_expressions/math_expression.py: -------------------------------------------------------------------------------- 1 | from abc import ABC, abstractmethod 2 | 3 | from pyquibbler.env import REPR_RETURNS_SHORT_NAME 4 | from ..math_precedence import MathPrecedence 5 | 6 | 7 | class MathExpression(ABC): 8 | def __str__(self): 9 | with REPR_RETURNS_SHORT_NAME.temporary_set(True): 10 | return self.get_str() 11 | 12 | def get_math_expression(self): 13 | return self 14 | 15 | @abstractmethod 16 | def get_str(self, with_spaces: bool = True): 17 | pass 18 | 19 | @property 20 | @abstractmethod 21 | def precedence(self) -> MathPrecedence: 22 | pass 23 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/pretty_converters/math_precedence.py: -------------------------------------------------------------------------------- 1 | import enum 2 | 3 | 4 | class MathPrecedence(enum.IntEnum): 5 | VAR_NAME = 20 6 | PARENTHESIS = 19 7 | FUNCTION_CALL = 18 8 | SLICING = 17 9 | SUBSCRIPTION = 16 10 | ATTRIBUTE = 15 11 | EXPONENTIATION = 14 12 | BITWISE_NOT = 13 13 | POSNEG = 12 14 | MULDIV = 11 15 | ADDSUB = 10 16 | BITWISE_SHIFT = 9 17 | BITWISE_AND = 8 18 | BITWISE_XOR = 7 19 | BITWISE_OR = 6 20 | COMPARISON = 5 21 | BOOL_NOT = 4 22 | BOOL_AND = 3 23 | BOOL_OR = 2 24 | LAMBDA = 1 25 | VAR_NAME_WITH_SPACES = 0 26 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/specialized_functions/__init__.py: -------------------------------------------------------------------------------- 1 | from .iquib import iquib 2 | from .proxy import proxy 3 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/specialized_functions/getattr.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from pyquibbler.exceptions import PyQuibblerException 4 | from pyquibbler.function_overriding.attribute_override import MethodOverride 5 | from pyquibbler.function_overriding.override_all import ATTRIBUTES_TO_ATTRIBUTE_OVERRIDES 6 | from pyquibbler.quib.specialized_functions.quiby_methods import QuibyMethod 7 | 8 | 9 | @dataclass 10 | class PyQuibblerAttributeError(PyQuibblerException, AttributeError): 11 | item: str 12 | 13 | def __str__(self): 14 | return f"Quib has no attribute {self.item}." 15 | 16 | 17 | def create_getattr_quib_or_quiby_method(quib, item): 18 | from pyquibbler.quib.factory import create_quib 19 | 20 | attribute_override = ATTRIBUTES_TO_ATTRIBUTE_OVERRIDES.get(item, None) 21 | if attribute_override is None: 22 | raise PyQuibblerAttributeError(item) 23 | 24 | if isinstance(attribute_override, MethodOverride): 25 | return QuibyMethod(quib, method_override=attribute_override) 26 | else: 27 | return create_quib(func=getattr, 28 | args=(quib, item), 29 | func_definition=attribute_override.func_definition) 30 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/specialized_functions/quiby_methods.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | 3 | from pyquibbler.quib.quib import Quib 4 | from pyquibbler.function_definitions.func_definition import FuncDefinition 5 | from pyquibbler.function_overriding.attribute_override import MethodOverride 6 | 7 | 8 | @dataclass(frozen=True) 9 | class CallObjectMethod: 10 | method: str 11 | func_definition: FuncDefinition 12 | 13 | def __call__(self, *args, **kwargs): 14 | obj, *args = args 15 | return getattr(obj, self.method)(*args, **kwargs) 16 | 17 | 18 | @dataclass 19 | class QuibyMethod: 20 | quib: Quib 21 | method_override: MethodOverride 22 | 23 | def __call__(self, *args, **kwargs): 24 | """ 25 | Create a function quib that calls the specified method of self.quib 26 | """ 27 | from pyquibbler.quib.factory import create_quib 28 | return create_quib(func=CallObjectMethod(method=self.method_override.attribute, 29 | func_definition=self.method_override.func_definition), 30 | args=(self.quib, *args), 31 | kwargs=kwargs, 32 | ) 33 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/types.py: -------------------------------------------------------------------------------- 1 | from __future__ import annotations 2 | from dataclasses import dataclass 3 | from typing import Optional 4 | 5 | from pyquibbler.utilities.numpy_original_functions import np_array 6 | 7 | 8 | @dataclass 9 | class FileAndLineNumber: 10 | """ 11 | Points to a specific line number within a specified file. 12 | """ 13 | 14 | file_path: str 15 | line_no: Optional[int] 16 | 17 | def __repr__(self): 18 | return f'file: {self.file_path}, line={self.line_no}' 19 | 20 | def _repr_html_(self): 21 | return f'{self}' 22 | 23 | 24 | PointArray = np_array 25 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .miscellaneous import deep_copy_without_quibs_or_graphics, is_there_a_quib_in_args 2 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib_network/__init__.py: -------------------------------------------------------------------------------- 1 | from .types import Direction 2 | from .quib_network import dependency_graph 3 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/quib_network/types.py: -------------------------------------------------------------------------------- 1 | from pyquibbler.utilities.basic_types import StrEnum 2 | 3 | 4 | class Direction(StrEnum): 5 | """ 6 | Define upstream/downstream directions in quib dependency graph. 7 | 8 | See Also 9 | -------- 10 | dependency_graph 11 | """ 12 | 13 | UPSTREAM = 'upstream' 14 | "Towards quibs affecting current quib (``'upstream'``)." 15 | 16 | DOWNSTREAM = 'downstream' 17 | "Towards quibs affected by current quib (``'downstream'``)." 18 | 19 | BOTH = 'both' 20 | "Towards both upstream and downstream directions (``'both'``)." 21 | 22 | ALL = 'all' 23 | "Fully explore the network from the current quib (``'all'``)." 24 | 25 | 26 | def reverse_direction(direction: Direction) -> Direction: 27 | if direction is Direction.UPSTREAM: 28 | return Direction.DOWNSTREAM 29 | if direction is Direction.DOWNSTREAM: 30 | return Direction.UPSTREAM 31 | return direction 32 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/reset_all.py: -------------------------------------------------------------------------------- 1 | from pyquibbler.assignment.override_choice.types import reset_all_override_group, is_reset_all_override_group 2 | from pyquibbler.project.undo_group import reset_all_undo_group, is_reset_all_undo_group 3 | from pyquibbler.quib.get_value_context_manager import reset_all_get_value_context, is_reset_all_get_value_context 4 | from pyquibbler.quib.graphics.graphics_assignment_mode import reset_all_graphics_assignment_mode, \ 5 | is_reset_all_graphics_assignment_mode 6 | from pyquibbler.quib.graphics.redraw import reset_all_redraw, is_reset_all_redraw 7 | 8 | 9 | def reset_all(): 10 | """ 11 | Reset all global variables to their initial state 12 | """ 13 | reset_all_graphics_assignment_mode() 14 | reset_all_undo_group() 15 | reset_all_redraw() 16 | reset_all_override_group() 17 | reset_all_get_value_context() 18 | 19 | 20 | def is_reset_all(): 21 | return is_reset_all_graphics_assignment_mode() \ 22 | and is_reset_all_undo_group() \ 23 | and is_reset_all_redraw() \ 24 | and is_reset_all_override_group() \ 25 | and is_reset_all_get_value_context() 26 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/type_translation/__init__.py: -------------------------------------------------------------------------------- 1 | from .translators import TypeTranslator 2 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/type_translation/run_conditions.py: -------------------------------------------------------------------------------- 1 | from pyquibbler.utilities.multiple_instance_runner import RunCondition 2 | 3 | 4 | class TypeTranslateRunCondition(RunCondition): 5 | NO_ARGUMENTS_TYPES = 1 6 | WITH_ARGUMENTS_TYPES = 2 7 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/type_translation/translate.py: -------------------------------------------------------------------------------- 1 | from typing import Type, List, Optional 2 | 3 | from pyquibbler.utilities.multiple_instance_runner import MultipleInstanceRunner 4 | from pyquibbler.function_definitions.func_definition import FuncDefinition 5 | 6 | from .run_conditions import TypeTranslateRunCondition 7 | 8 | 9 | def translate_type( 10 | run_condition: TypeTranslateRunCondition, 11 | func_definition: FuncDefinition, 12 | data_arguments_types: Optional[List[Type]] = None) -> Optional[Type]: 13 | """ 14 | Try getting the type of the quib value without evaluating the function. 15 | Return None if type cannot be calculated. 16 | """ 17 | return MultipleInstanceRunner(run_condition=run_condition, 18 | runner_types=func_definition.result_type_or_type_translators, 19 | func_definition=func_definition, data_arguments_types=data_arguments_types).run() 20 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/type_translation/utils.py: -------------------------------------------------------------------------------- 1 | from dataclasses import dataclass 2 | from typing import Type, Mapping 3 | 4 | from pyquibbler.exceptions import PyQuibblerException 5 | from pyquibbler.utilities.missing_value import missing 6 | 7 | 8 | @dataclass 9 | class CannotFindRepresentativeValueForType(PyQuibblerException): 10 | type_: Type 11 | 12 | def __str__(self): 13 | return f"cannot find representative value for type {self._type}" 14 | 15 | 16 | def get_representative_value_of_type(type_: Type): 17 | value = missing 18 | try: 19 | # important to start with scalar typing, because type(np.int64([])) is not np.int64 20 | value = type_(0) 21 | except TypeError: 22 | try: 23 | value = type_([]) 24 | except TypeError: 25 | if issubclass(type_, Mapping): 26 | value = type_({}) 27 | 28 | if type(value) is not type_: 29 | raise CannotFindRepresentativeValueForType(type_) 30 | 31 | return value 32 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/user_utils/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler/pyquibbler/user_utils/__init__.py -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/user_utils/gui_apps.py: -------------------------------------------------------------------------------- 1 | from .quibapp import QuibApp 2 | 3 | 4 | def quibapp(): 5 | """ 6 | Open the Quibbler App 7 | 8 | See Also 9 | -------- 10 | Project 11 | """ 12 | return QuibApp.get_or_create() 13 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/utilities/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/pyquibbler/pyquibbler/utilities/__init__.py -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/utilities/basic_types.py: -------------------------------------------------------------------------------- 1 | import contextlib 2 | from typing import Any 3 | from dataclasses import dataclass 4 | from enum import Enum 5 | 6 | 7 | class Singleton(object): 8 | """ 9 | A base class for allowing only one instance 10 | """ 11 | _instance = None 12 | 13 | def __new__(cls, *args, **kwargs): 14 | if not isinstance(cls._instance, cls): 15 | cls._instance = object.__new__(cls, *args, **kwargs) 16 | return cls._instance 17 | 18 | 19 | @dataclass 20 | class Mutable: 21 | val: Any 22 | 23 | def set(self, val: Any): 24 | self.val = val 25 | 26 | @contextlib.contextmanager 27 | def temporary_set(self, val): 28 | current = self.val 29 | self.set(val) 30 | try: 31 | yield 32 | finally: 33 | self.set(current) 34 | 35 | 36 | @dataclass 37 | class Flag(Mutable): 38 | 39 | def __bool__(self): 40 | return self.val 41 | 42 | def __eq__(self, other): 43 | return self.val == other 44 | 45 | def __ne__(self, other): 46 | return self.val != other 47 | 48 | 49 | class StrEnum(str, Enum): 50 | pass 51 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/utilities/file_path.py: -------------------------------------------------------------------------------- 1 | import pathlib 2 | 3 | 4 | class PathWithHyperLink(type(pathlib.Path())): 5 | def _repr_html_(self): 6 | return f'{self.name}' 7 | 8 | 9 | class NotebookArchiveMirrorPath(PathWithHyperLink): 10 | 11 | name = '[Save in notebook]' 12 | 13 | def _repr_html_(self): 14 | return self.name 15 | 16 | def __repr__(self): 17 | return self.name 18 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/utilities/get_original_func.py: -------------------------------------------------------------------------------- 1 | from typing import Callable 2 | 3 | 4 | def get_original_func(func: Callable): 5 | """ 6 | Get the original func- if this function is already overrided, get the original func it's function_definitions. 7 | 8 | So for example, if the OVERLOADED np.array is given as `func`, then the ORIGINAL np.array will be returned 9 | If the ORIGINAL np.array is given as `func`, then `func` will be returned 10 | """ 11 | while hasattr(func, '__quibbler_wrapped__'): 12 | func = func.__quibbler_wrapped__ 13 | return func 14 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/utilities/missing_value.py: -------------------------------------------------------------------------------- 1 | from pyquibbler.utilities.basic_types import Singleton 2 | 3 | 4 | class Missing(Singleton): 5 | """ 6 | Designates a missing value in a function call 7 | """ 8 | 9 | def __repr__(self): 10 | return 'missing' 11 | 12 | 13 | missing = Missing() 14 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/utilities/numpy_original_functions.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from pyquibbler.utilities.get_original_func import get_original_func 4 | 5 | np_logical_and = get_original_func(np.logical_and) 6 | np_logical_or = get_original_func(np.logical_or) 7 | np_cumsum = get_original_func(np.cumsum) 8 | np_sum = get_original_func(np.sum) 9 | np_all = get_original_func(np.all) 10 | np_any = get_original_func(np.any) 11 | np_full = get_original_func(np.full) 12 | np_ndarray = get_original_func(np.ndarray) 13 | np_array = get_original_func(np.array) 14 | np_log10 = get_original_func(np.log10) 15 | np_abs = get_original_func(np.abs) 16 | np_vectorize = get_original_func(np.vectorize) 17 | np_maximum = get_original_func(np.maximum) 18 | np_minimum = get_original_func(np.minimum) 19 | np_round = get_original_func(np.round) 20 | np_zeros = get_original_func(np.zeros) 21 | np_True = np.bool_(True) 22 | np_shape = get_original_func(np.shape) 23 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/utilities/operators_with_reverse.py: -------------------------------------------------------------------------------- 1 | import operator 2 | from typing import Callable 3 | 4 | 5 | def get_reversed_func(func: Callable): 6 | def _reversed(quib, obj): 7 | return func(obj, quib) 8 | _reversed.__name__ = f"{func.__name__}_reversed" 9 | _reversed.__qualname__ = f"{func.__name__}_reversed" 10 | return _reversed 11 | 12 | 13 | BINARY_OPERATOR_NAMES = [ 14 | '__add__', 15 | '__sub__', 16 | '__mul__', 17 | '__matmul__', 18 | '__truediv__', 19 | '__floordiv__', 20 | '__mod__', 21 | '__pow__', 22 | '__and__', 23 | '__xor__', 24 | '__or__', 25 | '__lshift__', 26 | '__rshift__', 27 | ] 28 | 29 | REVERSE_OPERATOR_NAMES_TO_FUNCS = {} 30 | 31 | for func_name in BINARY_OPERATOR_NAMES: 32 | reversed_func_name = '__r' + func_name[2:] 33 | func = getattr(operator, func_name) 34 | REVERSE_OPERATOR_NAMES_TO_FUNCS[reversed_func_name] = get_reversed_func(func) 35 | -------------------------------------------------------------------------------- /pyquibbler/pyquibbler/utilities/warning_messages.py: -------------------------------------------------------------------------------- 1 | import contextlib 2 | import warnings 3 | from typing import Tuple, Optional, Union 4 | 5 | 6 | def _no_header_formatwarning(msg, *args, **kwargs): 7 | return str(msg) + '\n' 8 | 9 | 10 | @contextlib.contextmanager 11 | def _no_header_warning(): 12 | original_formatwarning = warnings.formatwarning 13 | warnings.formatwarning = _no_header_formatwarning 14 | yield 15 | warnings.formatwarning = original_formatwarning 16 | 17 | 18 | def no_header_warn(msg: Union[str, Tuple[str, ...]], add_frame: bool = False, once_only: bool = False): 19 | """ 20 | Issue a bare warning message. 21 | Do not include in the warning a header with the file path. 22 | """ 23 | if isinstance(msg, str): 24 | msg = (msg, ) 25 | if add_frame: 26 | msg = create_frame(msg) 27 | msg = '\n'.join(msg) 28 | with _no_header_warning(): 29 | if once_only: 30 | warnings.warn(msg) 31 | else: 32 | warnings.showwarning(msg, category=UserWarning, filename=None, lineno=None) 33 | 34 | 35 | def create_frame(message_lines: Tuple[str, ...], width: Optional[int] = None): 36 | if width is None: 37 | max_length = max(len(line) for line in message_lines) 38 | width = max_length + 4 39 | 40 | return ( 41 | '-' * width, 42 | *('| ' + line + ' ' * (width - len(line) - 3) + '|' for line in message_lines), 43 | '-' * width, 44 | ) 45 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | # When this __init__ file is not present we get a warning when using pytest-cov 2 | -------------------------------------------------------------------------------- /tests/functional/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/functional/__init__.py -------------------------------------------------------------------------------- /tests/functional/assignment/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/functional/assignment/__init__.py -------------------------------------------------------------------------------- /tests/functional/assignment/overriding_choice/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/functional/assignment/overriding_choice/__init__.py -------------------------------------------------------------------------------- /tests/functional/cache/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/functional/cache/__init__.py -------------------------------------------------------------------------------- /tests/functional/cache/test_shallow_cache.py: -------------------------------------------------------------------------------- 1 | from unittest import mock 2 | 3 | import pytest 4 | 5 | from pyquibbler.cache.holistic_cache import HolisticCache, PathCannotHaveComponentsException 6 | from pyquibbler.path import PathComponent 7 | from tests.functional.cache.cache_test import CacheTest 8 | 9 | 10 | class TestShallowCache(CacheTest): 11 | 12 | cls = HolisticCache 13 | 14 | @pytest.fixture() 15 | def result(self): 16 | return 1 17 | 18 | def test_shallow_cache_matches_all(self, cache): 19 | assert cache.matches_result(object) 20 | 21 | def test_shallow_cache_does_not_allow_specifying_paths_in_invalidate(self, cache): 22 | with pytest.raises(PathCannotHaveComponentsException, match='.*'): 23 | cache.set_invalid_at_path([PathComponent(7)]) 24 | 25 | def test_shallow_cache_does_not_allow_specifying_paths_in_set_valid(self, cache): 26 | with pytest.raises(PathCannotHaveComponentsException, match='.*'): 27 | cache.set_valid_value_at_path([PathComponent(7)], 1) 28 | -------------------------------------------------------------------------------- /tests/functional/conftest.py: -------------------------------------------------------------------------------- 1 | from unittest.mock import Mock, MagicMock 2 | 3 | from pytest import fixture 4 | 5 | 6 | @fixture 7 | def function_mock_return_val(): 8 | return [1, 2, 3, 4, 3, 2, 1] 9 | 10 | 11 | @fixture 12 | def function_mock(function_mock_return_val): 13 | func_mock = MagicMock(return_value=function_mock_return_val) 14 | func_mock.__name__ = 'func_mock' 15 | return func_mock 16 | -------------------------------------------------------------------------------- /tests/functional/file_syncing/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/functional/file_syncing/__init__.py -------------------------------------------------------------------------------- /tests/functional/graphics/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/functional/graphics/__init__.py -------------------------------------------------------------------------------- /tests/functional/inversion/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/functional/inversion/__init__.py -------------------------------------------------------------------------------- /tests/functional/inversion/inverters/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/functional/inversion/inverters/__init__.py -------------------------------------------------------------------------------- /tests/functional/inversion/inverters/test_no_shape_elementwise_inverter.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | from typing import Iterable 4 | 5 | from pyquibbler.path_translation.types import Source 6 | from tests.functional.inversion.inverters.utils import inverse 7 | 8 | 9 | @pytest.mark.parametrize("func,func_arg,indices,value,expected_value", [ 10 | (np.log2, Source(np.array([4, 4, 4])), slice(None, None, None), 3, np.array([8, 8, 8])), 11 | (np.log2, Source(np.array([[4, 4], [4, 4]])), (0, slice(0, None, None)), 3, np.array([[8, 8], [4, 4]])), 12 | ], ids=[ 13 | "log2: array[:]", 14 | "log2: array[0, 0:]", 15 | ]) 16 | def test_inverse_elementwise_no_shape_single_argument(func, func_arg, indices, value, expected_value): 17 | sources_to_results, inversals = inverse(func, indices=indices, value=value, args=(func_arg,), empty_path=indices is None) 18 | assert inversals[0].assignment.path[0].component == indices 19 | value = sources_to_results[func_arg] 20 | if isinstance(expected_value, Iterable): 21 | assert np.array_equal(value, expected_value) 22 | else: 23 | assert value == expected_value 24 | -------------------------------------------------------------------------------- /tests/functional/inversion/inverters/utils.py: -------------------------------------------------------------------------------- 1 | from typing import Callable, Any, Tuple, Mapping 2 | 3 | from pyquibbler import Assignment 4 | from pyquibbler.inversion.invert import invert 5 | from pyquibbler.path.data_accessing import deep_set 6 | from pyquibbler.utilities.get_original_func import get_original_func 7 | from pyquibbler.path_translation.source_func_call import SourceFuncCall 8 | from pyquibbler.path import PathComponent 9 | 10 | 11 | def inverse(func: Callable, indices: Any, value: Any, args: Tuple[Any, ...] = None, kwargs: Mapping[str, Any] = None, 12 | empty_path: bool = False, assignment: Assignment = None): 13 | func = get_original_func(func) 14 | if indices is not None and empty_path is True: 15 | raise Exception("The indices cannot be set if empty path is True") 16 | 17 | args = args or tuple() 18 | kwargs = kwargs or {} 19 | previous_value = SourceFuncCall.from_(func, args, kwargs).run() 20 | assignment = assignment or Assignment(path=[PathComponent(indices)] if not empty_path else [], value=value) 21 | inversals = invert( 22 | func_call=SourceFuncCall.from_(func, args, kwargs), 23 | previous_result=previous_value, 24 | assignment=assignment 25 | ) 26 | 27 | return ({ 28 | inversal.source: deep_set(inversal.source.value, inversal.assignment.path, inversal.assignment.value) 29 | for inversal in inversals 30 | }, 31 | inversals) 32 | 33 | -------------------------------------------------------------------------------- /tests/functional/inversion/test_invert.py: -------------------------------------------------------------------------------- 1 | from unittest import mock 2 | 3 | import pytest 4 | 5 | from pyquibbler.inversion.invert import invert 6 | from pyquibbler.path_translation.source_func_call import SourceFuncCall 7 | from pyquibbler.utilities.multiple_instance_runner import NoRunnerWorkedException 8 | 9 | 10 | def test_invert_raises_exception_on_unknown_func(): 11 | assignment = mock.Mock() 12 | assignment.is_default = mock.Mock(return_value=False) 13 | 14 | with pytest.raises(NoRunnerWorkedException, match='.*'): 15 | invert( 16 | func_call=SourceFuncCall.from_(func=mock.MagicMock(__name__='unknown'), 17 | func_args=tuple(), 18 | func_kwargs={}, 19 | data_source_locations=[], 20 | parameter_source_locations=[] 21 | ), 22 | assignment=assignment, 23 | previous_result=0 24 | ) 25 | -------------------------------------------------------------------------------- /tests/functional/path/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/functional/path/__init__.py -------------------------------------------------------------------------------- /tests/functional/path/test_hashable.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | 4 | from pyquibbler.path import PathComponent, get_hashable_path 5 | 6 | 7 | @pytest.mark.parametrize("components_in_path", [ 8 | [slice(None, None, None)], 9 | [np.array([1, 2, 3]), np.array([1, 2, 3])], 10 | [(np.array([1, 2, 3]), np.array([1, 2, 3]))], 11 | [np.array([1, 2, 3])], 12 | [([slice(None, None, None)],)], 13 | ]) 14 | def test_hash_path(components_in_path): 15 | path = [PathComponent(c) for c in components_in_path] 16 | 17 | # Make sure we don't raise an exception 18 | hash(get_hashable_path(path)) 19 | -------------------------------------------------------------------------------- /tests/functional/quib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/functional/quib/__init__.py -------------------------------------------------------------------------------- /tests/functional/quib/assignment/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/functional/quib/assignment/__init__.py -------------------------------------------------------------------------------- /tests/functional/quib/assignment/test_assignments.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | 4 | from pyquibbler import iquib 5 | from pyquibbler.assignment import AssignmentWithTolerance 6 | from pyquibbler.path import PathComponent 7 | 8 | 9 | def test_assignment_do_not_change_each_other(): 10 | a = iquib([1, 2]) 11 | a.assign([10, 20, 30]) 12 | a[1] = 21 13 | assert a.handler.overrider.get([]).value == [10, 20, 30], "sanity" 14 | a.get_value() 15 | 16 | assert a.handler.overrider.get([]).value == [10, 20, 30] 17 | 18 | 19 | @pytest.mark.parametrize(['x0', 'a', 'b', 'new_y', 'new_dy', 'component', 'expected'], [ 20 | (10., 1., 0., 10.123456, 0.005, [], 10.12), 21 | (10., 1., 10., 10.123456, 0.005, [], 0.12), 22 | (10., 0.1, 0., 10.123456, 0.005, [], 101.2), 23 | (10., 10., 0., 10.123456, 0.005, [], 1.012), 24 | (np.array([10., 20.]), 10., 0., 10.123456, 0.005, 0, 1.012), 25 | ]) 26 | def test_assignment_with_tolerance(x0, a, b, new_y, new_dy, component, expected): 27 | x = iquib(x0) 28 | y = a * x + b 29 | 30 | assignment = AssignmentWithTolerance.from_value_path_tolerance( 31 | value=new_y, 32 | path=[] if component == [] else [PathComponent(component)], 33 | tolerance=new_dy) 34 | 35 | y.handler.apply_assignment(assignment) 36 | assert x.handler.overrider.get(assignment.path).value == expected 37 | -------------------------------------------------------------------------------- /tests/functional/quib/conftest.py: -------------------------------------------------------------------------------- 1 | from unittest import mock 2 | 3 | import numpy as np 4 | import pytest 5 | 6 | from pyquibbler.quib.quib import Quib, QuibHandler 7 | 8 | 9 | @pytest.fixture() 10 | def create_mock_quib(): 11 | def _create(shape=None, get_value_result=None, children=None): 12 | shape = shape or (3, 1) 13 | get_value_result = get_value_result or [[1, 2, 3]] 14 | mock_quib = mock.Mock(spec=Quib) 15 | mock_quib.get_value_valid_at_path.return_value = get_value_result 16 | mock_quib.get_shape.return_value = shape 17 | mock_quib.get_ndim.return_value = len(shape) 18 | mock_quib.handler = mock.Mock(spec=QuibHandler) 19 | mock_quib.handler.quib_function_call = mock.Mock() 20 | mock_quib.handler.quib_function_call.result_shape = np.shape(get_value_result) 21 | mock_quib.handler.quib_function_call.result_type = type(get_value_result) 22 | mock_quib.handler.get_figures.return_value = [] 23 | mock_quib.pass_quibs = False 24 | mock_quib.is_proxy = False 25 | mock_quib.get_descendants.return_value = children or set() 26 | return mock_quib 27 | return _create 28 | 29 | 30 | @pytest.fixture() 31 | def mock_axes(): 32 | axes = mock.Mock() 33 | axes.figure.canvas.supports_blit = False 34 | axes._children = [] 35 | return axes 36 | -------------------------------------------------------------------------------- /tests/functional/quib/graphics/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/functional/quib/graphics/__init__.py -------------------------------------------------------------------------------- /tests/functional/quib/graphics/event_handling/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/functional/quib/graphics/event_handling/__init__.py -------------------------------------------------------------------------------- /tests/functional/quib/quib_widget/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/functional/quib/quib_widget/__init__.py -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/functional/quib/test_quib/__init__.py -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/get_value/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/functional/quib/test_quib/get_value/__init__.py -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/get_value/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from pyquibbler.quib.factory import create_quib 3 | from pyquibbler.quib.quib import Quib 4 | from pyquibbler.quib.specialized_functions.iquib import identity_function 5 | from pyquibbler import CacheMode 6 | import numpy as np 7 | 8 | @pytest.fixture() 9 | def uncached_array_quib() -> Quib: 10 | return create_quib(func=identity_function, args=(np.arange(6),), 11 | allow_overriding=True, 12 | lazy=False, 13 | cache_mode=CacheMode.OFF, 14 | ) 15 | 16 | @pytest.fixture() 17 | def uncached_scalar_quib() -> Quib: 18 | return create_quib(func=identity_function, args=(3,), 19 | allow_overriding=True, 20 | lazy=False, 21 | cache_mode=CacheMode.OFF, 22 | ) 23 | -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/get_value/test_axiswise.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | 4 | from pyquibbler.path import PathComponent 5 | from tests.functional.quib.test_quib.get_value.test_apply_along_axis import parametrize_data 6 | from tests.functional.quib.test_quib.get_value.utils import check_get_value_valid_at_path 7 | 8 | 9 | @parametrize_data 10 | @pytest.mark.parametrize(['axis', 'indices_to_get_value_at'], [ 11 | (-1, 0), 12 | (2, (0, 0)), 13 | ]) 14 | def test_axiswise_get_value_valid_at_path(axis, data, indices_to_get_value_at): 15 | path_to_get_value_at = [PathComponent(indices_to_get_value_at)] 16 | check_get_value_valid_at_path(lambda quib: np.sort(quib, axis=axis), data, path_to_get_value_at) 17 | -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/get_value/test_iquib.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from pytest import mark 3 | 4 | from pyquibbler import iquib 5 | from pyquibbler.path import PathComponent 6 | 7 | 8 | @mark.regression 9 | def test_get_partial_value_of_a_list_iquib_with_boolean_indexing(): 10 | value = [[1, 2], [3, 4]] 11 | a = iquib(value) 12 | 13 | index = np.array([[0, 1], [0, 0]], dtype=bool) 14 | partial_value = a.get_value_valid_at_path([PathComponent(index)]) 15 | 16 | assert partial_value[0][1] == value[0][1] 17 | 18 | 19 | @mark.regression 20 | def test_array_of_iquib_list(): 21 | value = [[1, 2], [3, 4]] 22 | a = iquib(value) 23 | 24 | index = np.array([[0, 1], [0, 0]], dtype=bool) 25 | b = np.array(a) 26 | c = b[index] 27 | 28 | assert c.get_value() == np.array(value)[index] 29 | -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/get_value/test_list_operatos.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/functional/quib/test_quib/get_value/test_list_operatos.py -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/get_value/test_minor_sources.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | 4 | from pyquibbler import iquib 5 | 6 | 7 | @pytest.mark.regression 8 | def test_array_with_quib_inner_source(): 9 | a = iquib([1]) 10 | b = np.array([a]) 11 | 12 | assert b.get_value() == np.array([[1]]) 13 | -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/get_value/test_proxy.py: -------------------------------------------------------------------------------- 1 | from pyquibbler.path.path_component import PathComponent 2 | from pyquibbler.quib.specialized_functions.proxy import create_proxy 3 | from tests.functional.quib.test_quib.get_value.utils import collecting_quib 4 | 5 | 6 | def test_proxy_get_value(): 7 | val = [1, 2, 3] 8 | path_collector_quib = collecting_quib(val) 9 | proxy = create_proxy(path_collector_quib) 10 | 11 | with path_collector_quib.collect_valid_paths() as valid_paths: 12 | res = proxy.get_value_valid_at_path([PathComponent(0)]) 13 | 14 | assert valid_paths == [[PathComponent(0)]] 15 | assert res == val -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/invalidation/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/functional/quib/test_quib/invalidation/__init__.py -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/invalidation/test_accumulation.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | 4 | from tests.functional.quib.test_quib.get_value.test_apply_along_axis import parametrize_indices_to_invalidate, \ 5 | parametrize_data 6 | from tests.functional.quib.test_quib.invalidation.utils import check_invalidation 7 | 8 | 9 | @parametrize_indices_to_invalidate 10 | @parametrize_data 11 | @pytest.mark.parametrize('axis', [-1, 0, 1, 2, None]) 12 | def test_accumulation_axiswise_invalidation(indices_to_invalidate, axis, data): 13 | check_invalidation(lambda quib: np.cumsum(quib, axis=axis), data, indices_to_invalidate) 14 | -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/invalidation/test_apply_along_axis.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | 4 | from tests.functional.quib.test_quib.get_value.test_apply_along_axis import parametrize_indices_to_invalidate, \ 5 | parametrize_data, parametrize_path_to_invalidate 6 | from tests.functional.quib.test_quib.invalidation.utils import check_invalidation 7 | 8 | 9 | @parametrize_indices_to_invalidate 10 | @parametrize_data 11 | @pytest.mark.parametrize('axis', [0, 1, 2, -1, -2]) 12 | @pytest.mark.parametrize('func_out_dims', [0, 1, 2]) 13 | def test_apply_along_axis_invalidation_(indices_to_invalidate, axis, func_out_dims, data): 14 | func1d = lambda slice: np.sum(slice).reshape((1,) * func_out_dims) 15 | check_invalidation(lambda quib: np.apply_along_axis(func1d, axis, quib), data, indices_to_invalidate) 16 | 17 | 18 | @parametrize_path_to_invalidate 19 | @parametrize_data 20 | def test_apply_along_axis_invalidation_list(path_to_invalidate, data, axis=0, func_out_dims=0): 21 | data = data.tolist() 22 | func1d = lambda slice: np.sum(slice).reshape((1,) * func_out_dims) 23 | check_invalidation(lambda quib: np.apply_along_axis(func1d, axis, quib), data, path_to_invalidate) 24 | 25 | -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/invalidation/test_list_operators.py: -------------------------------------------------------------------------------- 1 | from pyquibbler import iquib, CacheStatus 2 | 3 | 4 | def test_list_addition(): 5 | a = iquib([10, 20, 30]) 6 | b = (a + [40, 50]).setp(cache_mode='on') 7 | b0 = b[0] 8 | b1 = b[1] 9 | b2 = b[2] 10 | 11 | b0.get_value() 12 | b1.get_value() 13 | b2.get_value() 14 | 15 | assert b.get_value() == [10, 20, 30, 40, 50] 16 | a[1] = 21 17 | assert b.get_value() == [10, 21, 30, 40, 50] 18 | 19 | assert b0.cache_status == CacheStatus.ALL_VALID 20 | assert b1.cache_status == CacheStatus.ALL_INVALID 21 | assert b2.cache_status == CacheStatus.ALL_VALID 22 | 23 | 24 | def test_list_multiplication(): 25 | a = iquib([10, 20, 30]) 26 | n = iquib(3) 27 | b = (n * a).setp(cache_mode='on') 28 | 29 | assert b.get_value() == [10, 20, 30, 10, 20, 30, 10, 20, 30] 30 | 31 | b0 = b[0] 32 | b1 = b[1] 33 | b4 = b[4] 34 | 35 | b0.get_value() 36 | b1.get_value() 37 | b4.get_value() 38 | 39 | a[1] = 21 40 | assert b.get_value() == [10, 21, 30, 10, 21, 30, 10, 21, 30] 41 | 42 | assert b0.cache_status == CacheStatus.ALL_VALID 43 | assert b1.cache_status == CacheStatus.ALL_INVALID 44 | assert b4.cache_status == CacheStatus.ALL_INVALID 45 | -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/invalidation/test_proxy.py: -------------------------------------------------------------------------------- 1 | from pyquibbler import iquib 2 | from pyquibbler.cache.cache import CacheStatus 3 | from pyquibbler.quib.specialized_functions.proxy import create_proxy 4 | 5 | 6 | def test_proxy_never_invalidates(): 7 | arg = iquib([100]) 8 | proxy = create_proxy(arg) 9 | child = proxy[0] 10 | child.get_value() 11 | 12 | arg.handler.invalidate_and_aggregate_redraw_at_path([]) 13 | 14 | assert child.cache_status == CacheStatus.ALL_VALID 15 | -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/invalidation/test_reduction.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | 4 | from pyquibbler import iquib 5 | from pyquibbler.cache import CacheStatus 6 | from tests.functional.quib.test_quib.get_value.test_apply_along_axis import parametrize_indices_to_invalidate, \ 7 | parametrize_data, parametrize_keepdims, parametrize_where 8 | from tests.functional.quib.test_quib.invalidation.utils import check_invalidation 9 | 10 | 11 | @parametrize_indices_to_invalidate 12 | @parametrize_data 13 | @pytest.mark.parametrize('axis', [-1, (-1, 1), 0, 1, 2, (0, 2), (0, 1), None]) 14 | @parametrize_keepdims 15 | @parametrize_where 16 | def test_reduction_axiswise_invalidation(indices_to_invalidate, axis, keepdims, where, data): 17 | kwargs = dict(axis=axis) 18 | if keepdims is not None: 19 | kwargs['keepdims'] = keepdims 20 | if where is not None: 21 | kwargs['where'] = where 22 | check_invalidation(lambda quib: np.sum(quib, **kwargs), data, indices_to_invalidate) 23 | 24 | 25 | @pytest.mark.regression 26 | def test_sum_invalidation(): 27 | z = iquib(np.array([3, 1, 2])) 28 | sum_z = np.sum(z).setp(cache_mode='on') 29 | sum_z.get_value() 30 | assert sum_z.cache_status == CacheStatus.ALL_VALID, "Sanity" 31 | 32 | z[1] = 0 33 | 34 | assert sum_z.cache_status == CacheStatus.ALL_INVALID 35 | -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/pretty_repr/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/functional/quib/test_quib/pretty_repr/__init__.py -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/pretty_repr/test_overrider.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | 4 | from pyquibbler.quib.specialized_functions.iquib import iquib 5 | 6 | 7 | @pytest.mark.parametrize("assignments", [ 8 | ["a[1] = 3"], 9 | ["a[:, 0] = 1"], 10 | ["a[0] = 1", "a[0, 1] = 2"] 11 | ]) 12 | @pytest.mark.get_variable_names(True) 13 | def test_overrider_pretty_repr_array_assignments(assignments): 14 | data = np.array([[1, 2, 3]]) 15 | a = iquib(data) 16 | for assignment in assignments: 17 | exec(assignment) 18 | expected = "a = iquib(array([[1, 2, 3]]))" + f"\n" + f"\n".join(assignments) 19 | assert repr(a) == expected 20 | 21 | @pytest.mark.parametrize("assignments", [ 22 | ["a['name'] = 'Wow'"], 23 | ["a['short_name'] = 'quib'"], 24 | ["a['numbers'] = [1, 2, 3]", "a['numbers'][1] = 20"], 25 | ]) 26 | @pytest.mark.get_variable_names(True) 27 | def test_overrider_pretty_repr_dict_assignments(assignments): 28 | data = {'name': 'Quibbler'} 29 | a = iquib(data) 30 | for assignment in assignments: 31 | exec(assignment) 32 | expected = "a = iquib({'name': 'Quibbler'})" + f"\n" + f"\n".join(assignments) 33 | assert repr(a) == expected 34 | 35 | -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/pretty_repr/test_vectorize.py: -------------------------------------------------------------------------------- 1 | import functools 2 | 3 | import numpy as np 4 | import pytest 5 | 6 | from pyquibbler import iquib 7 | from pyquibbler.env import PRETTY_REPR 8 | 9 | 10 | def test_qvectorize_pretty_repr(): 11 | @np.vectorize 12 | def my_func(): 13 | pass 14 | 15 | with PRETTY_REPR.temporary_set(True): 16 | assert repr(my_func) == "np.vectorize(my_func)" 17 | 18 | 19 | @pytest.fixture 20 | def signature(): 21 | return '(w,h,c),(x)->(w2,h2,c)' 22 | 23 | 24 | @pytest.fixture 25 | def vectorized_func_with_signature(signature): 26 | @functools.partial(np.vectorize, signature=signature) 27 | def my_func(): 28 | pass 29 | 30 | return my_func 31 | 32 | 33 | def test_qvectorize_pretty_repr_with_signature(vectorized_func_with_signature, signature): 34 | with PRETTY_REPR.temporary_set(True): 35 | assert repr(vectorized_func_with_signature) == f"np.vectorize(my_func, {signature})" 36 | 37 | 38 | @pytest.mark.get_variable_names(True) 39 | def test_vectorize_pretty_repr(vectorized_func_with_signature, signature): 40 | a = iquib("pasten") 41 | b = iquib(np.array([42, 42, 42])) 42 | quib = vectorized_func_with_signature(a, b) 43 | 44 | with PRETTY_REPR.temporary_set(True): 45 | assert quib.pretty_repr == f"quib = np.vectorize(my_func, {signature})(a, b)" 46 | 47 | -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/test_array_operator_quib.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | 4 | from pyquibbler import iquib, Quib 5 | from pyquibbler.quib.exceptions import QuibsShouldPrecedeException 6 | 7 | 8 | def test_add_array_and_quib(): 9 | w = iquib(10) 10 | a = np.array([1, 2, 3]) 11 | wa = w + a 12 | assert isinstance(wa, Quib), "sanity" 13 | with pytest.raises(QuibsShouldPrecedeException, match='.*'): 14 | aw = a + w 15 | -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/test_assign_default.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | import pytest 4 | 5 | from pyquibbler import iquib, q, default 6 | from pyquibbler.quib.quib import Quib 7 | 8 | 9 | def test_default_repr(): 10 | assert repr(default) == 'default' 11 | 12 | 13 | def test_quib_assign_default(create_quib_with_return_value): 14 | a = create_quib_with_return_value(np.array([1, 2, 3]), allow_overriding=False) 15 | b = (a + 10).setp(allow_overriding=True) 16 | 17 | b.assign(0, 1) 18 | assert np.array_equal(b.get_value(), [11, 0, 13]), "sanity" 19 | b.assign(default) 20 | assert np.array_equal(b.get_value(), [11, 12, 13]) 21 | 22 | 23 | @pytest.mark.parametrize(['item', 'value', 'expected_before_removal', 'item_removal', 'expected_after_removal'], [ 24 | (1, 0, [11, 0, 13], 0, [11, 0, 13]), 25 | (1, 0, [11, 0, 13], 1, [11, 12, 13]), 26 | (1, 0, [11, 0, 13], slice(0, 2), [11, 12, 13]), 27 | (2, 0, [11, 12, 0], slice(0, 2), [11, 12, 0]), 28 | ]) 29 | def test_quib_setitem_default(create_quib_with_return_value, item, value, expected_before_removal, 30 | item_removal, expected_after_removal): 31 | a = create_quib_with_return_value(np.array([1, 2, 3]), allow_overriding=False) 32 | b = (a + 10).setp(allow_overriding=True) 33 | 34 | b[item] = value 35 | assert np.array_equal(b.get_value(), expected_before_removal) 36 | 37 | b[item_removal] = default 38 | assert np.array_equal(b.get_value(), expected_after_removal) 39 | -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/test_cache_behavior.py: -------------------------------------------------------------------------------- 1 | from unittest import mock 2 | 3 | import pytest 4 | 5 | from pyquibbler.function_definitions import add_definition_for_function 6 | from pyquibbler.function_definitions.func_definition import FuncDefinition 7 | from pyquibbler.utilities.input_validation_utils import InvalidArgumentTypeException, UnknownEnumException 8 | from pyquibbler.quib.func_calling.cache_mode import CacheMode 9 | from pyquibbler.quib.factory import create_quib 10 | 11 | 12 | def test_quib_set_cache_behaviour_forces_correct_type(quib): 13 | with pytest.raises(InvalidArgumentTypeException, match='.*'): 14 | quib.cache_mode = 1 15 | 16 | 17 | def test_quib_setp(quib): 18 | quib.setp(cache_mode='off') 19 | 20 | assert quib.cache_mode == CacheMode.OFF 21 | 22 | 23 | def test_quib_setp_with_invalid_cache_mode(quib): 24 | with pytest.raises(UnknownEnumException, match='.*'): 25 | quib.setp(cache_mode='ondfdd') 26 | 27 | 28 | @pytest.fixture() 29 | def random_quib(): 30 | func = mock.Mock() 31 | add_definition_for_function(func=func, func_definition=FuncDefinition(is_random=True)) 32 | return create_quib(func=func) 33 | 34 | 35 | def test_can_set_quib_cache_mode_to_on_when_random(random_quib): 36 | random_quib.cache_mode = CacheMode.ON 37 | 38 | 39 | def test_quib_cache_mode_on_by_default_when_is_random(random_quib): 40 | assert random_quib.cache_mode == CacheMode.ON 41 | -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/test_display_props.py: -------------------------------------------------------------------------------- 1 | from pyquibbler import iquib 2 | 3 | 4 | def test_display_properties_of_iquib(): 5 | a = iquib(0) 6 | a.display_properties().get_html_repr() 7 | a.display_properties().get_text_repr() 8 | 9 | 10 | def test_display_properties_of_fquib(): 11 | a = iquib(0) 12 | b = a + 1 13 | a.display_properties().get_html_repr() 14 | a.display_properties().get_text_repr() 15 | -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/test_functions_returning_array_view.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | import numpy as np 4 | from pyquibbler import iquib, quiby, CacheStatus 5 | 6 | 7 | @pytest.mark.regression 8 | def test_assignment_into_array_view(): 9 | a = iquib(np.array([0, 0])) 10 | b = np.ravel(a).setp(cache_mode='on') 11 | b.get_value() 12 | 13 | a[0] = 7 14 | assert a.args[0][0] == 0, "sanity" 15 | 16 | b.get_value() 17 | assert a.args[0][0] == 0 18 | 19 | 20 | @pytest.mark.regression 21 | def test_view_should_be_able_to_cache(): 22 | @quiby 23 | def get_a_view(): 24 | # this simulates functions like np.genfromtxt which returns a view 25 | # of an internal array they create 26 | # when this bug exists we get very slow dragging in `quibdemo_fit_stock` 27 | return np.ravel(np.array([1, 2, 3])) 28 | 29 | view_quib = get_a_view() 30 | view_quib.cache_mode = 'on' 31 | view_quib.get_value() 32 | 33 | assert view_quib.cache_status == CacheStatus.ALL_VALID 34 | -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/test_getattr.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | 4 | from pyquibbler import iquib 5 | from pytest import fixture 6 | 7 | from pyquibbler.quib.specialized_functions.getattr import PyQuibblerAttributeError 8 | 9 | 10 | @fixture 11 | def array_value(): 12 | return np.array([[1, 2, 3]]) 13 | 14 | 15 | @fixture 16 | def quib(array_value): 17 | a = iquib(array_value, assigned_name='a') 18 | return a 19 | 20 | 21 | @fixture 22 | def quib_T(quib): 23 | return quib.T 24 | 25 | 26 | def test_getattr_T_get_value(quib, quib_T): 27 | assert np.array_equal(quib.get_value().T, quib_T.get_value()) 28 | 29 | 30 | def test_getattr_T_inverse(quib, quib_T): 31 | quib_T[2, 0] = 10 32 | assert np.array_equal(quib.get_value(), [[1, 2, 10]]) 33 | 34 | 35 | def test_getattr_T_invalidate(quib, quib_T): 36 | quib_T.get_value() 37 | quib[0, 1] = 10 38 | assert np.array_equal(quib_T.handler.quib_function_call.cache._invalid_mask, [[False], [True], [False]]) 39 | 40 | 41 | def test_getattr_T_repr(quib, quib_T): 42 | assert repr(quib_T) == 'a.T' 43 | 44 | 45 | def test_getattr_raises_on_wrong_attr(quib): 46 | with pytest.raises(PyQuibblerAttributeError, match='wrong_attr'): 47 | quib.wrong_attr 48 | -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/test_list_operator_inveral.py: -------------------------------------------------------------------------------- 1 | from pyquibbler import iquib 2 | 3 | 4 | def test_list_addition_inversal(): 5 | a = iquib([10, 20, 30]) 6 | b = iquib([40, 50]) 7 | ab = a + b 8 | 9 | assert ab.get_value() == [10, 20, 30, 40, 50] 10 | ab[1] = 21 11 | 12 | assert a.get_value() == [10, 21, 30] 13 | assert ab.get_value() == [10, 21, 30, 40, 50] 14 | 15 | 16 | def test_list_multiplication_inversal(): 17 | a = iquib([10, 20, 30]) 18 | n = iquib(4) 19 | c = n * a 20 | 21 | assert c.get_value() == 4 * [10, 20, 30] 22 | c[4] = 100 23 | 24 | assert a.get_value() == [10, 100, 30] 25 | assert c.get_value() == 4 * [10, 100, 30] 26 | -------------------------------------------------------------------------------- /tests/functional/quib/test_quib/test_quib_creation.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from matplotlib import pyplot as plt 3 | 4 | from pyquibbler import iquib, Quib 5 | from pyquibbler.env import ALLOW_ARRAY_WITH_DTYPE_OBJECT 6 | 7 | 8 | def test_allow_array_with_dtype_object_off(): 9 | a = iquib(1) 10 | with ALLOW_ARRAY_WITH_DTYPE_OBJECT.temporary_set(False): 11 | assert isinstance(np.array([a], dtype=object), np.ndarray) 12 | 13 | 14 | def test_allow_array_with_dtype_object_on(): 15 | a = iquib(1) 16 | with ALLOW_ARRAY_WITH_DTYPE_OBJECT.temporary_set(True): 17 | assert isinstance(np.array([a], dtype=object), Quib) 18 | 19 | 20 | def test_plot_quib_converts_quib_containing_args_to_quib_arrays(): 21 | a = iquib(1) 22 | b = plt.plot([0, a, 2]) 23 | arg = b.args[1] 24 | assert isinstance(arg, Quib) and np.array_equal(arg.get_value(), [0, 1, 2]) 25 | -------------------------------------------------------------------------------- /tests/functional/quib/test_uninitiated.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from pyquibbler import iquib, quiby, q, is_quiby, Quib 4 | from pyquibbler.function_overriding.is_initiated import IS_QUIBBLER_INITIATED 5 | 6 | 7 | def test_iquib_does_not_create_quib_when_uninitiated(): 8 | with IS_QUIBBLER_INITIATED.temporary_set(False): 9 | with pytest.warns(UserWarning): 10 | quib = iquib(3) 11 | assert not isinstance(quib, Quib) and quib == 3 12 | quib = iquib(3) 13 | assert isinstance(quib, Quib) and quib.get_value() == 3, "sanity" 14 | 15 | 16 | def test_quiby_does_not_create_quiby_func_when_uninitiated(): 17 | with IS_QUIBBLER_INITIATED.temporary_set(False): 18 | with pytest.warns(UserWarning): 19 | quiby_str = quiby(str) 20 | with pytest.warns(UserWarning): 21 | assert not is_quiby(quiby_str) 22 | quiby_str = quiby(str) 23 | assert is_quiby(quiby_str), "sanity" 24 | 25 | 26 | def test_q_does_not_create_quib_when_uninitiated(): 27 | with IS_QUIBBLER_INITIATED.temporary_set(False): 28 | with pytest.warns(UserWarning): 29 | quib = q(str, 3) 30 | assert not isinstance(quib, Quib) and quib == '3' 31 | quib = q(str, 3) 32 | assert isinstance(quib, Quib) and quib.get_value() == '3' 33 | -------------------------------------------------------------------------------- /tests/functional/quib_network/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/functional/quib_network/__init__.py -------------------------------------------------------------------------------- /tests/functional/quib_network/test_quib_network_without_ipywidgets.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from pyquibbler.optional_packages.exceptions import MissingPackagesForFunctionException 4 | 5 | 6 | # def test_dependency_graph_exception_with_no_ipywidget(): 7 | # with pytest.raises(MissingPackagesForFunctionException, match='.*'): 8 | # from pyquibbler.quib_network.quib_network import dependency_graph 9 | -------------------------------------------------------------------------------- /tests/functional/test_project_wraps.py: -------------------------------------------------------------------------------- 1 | 2 | import pyquibbler as qb 3 | 4 | 5 | def test_get_project(project): 6 | assert qb.get_project() is project 7 | 8 | 9 | def test_get_set_project_directory(): 10 | qb.set_project_directory(None) 11 | assert qb.get_project_directory() is None 12 | 13 | -------------------------------------------------------------------------------- /tests/functional/test_utils.py: -------------------------------------------------------------------------------- 1 | from unittest import mock 2 | 3 | import pytest 4 | import numpy as np 5 | 6 | from pyquibbler.utilities.decorators import ensure_only_run_once_globally 7 | from pyquibbler.utilities.general_utils import get_shared_shape 8 | 9 | 10 | def test_ensure_run_once_globally_runs_once(): 11 | global_func = mock.Mock() 12 | 13 | wrapped_func = ensure_only_run_once_globally(global_func) 14 | res = wrapped_func() 15 | wrapped_func() 16 | 17 | global_func.assert_called_once() 18 | assert res == global_func.return_value 19 | 20 | 21 | @pytest.mark.parametrize('shapes, expected', [ 22 | [[(2, 3), (2, 3)], (2, 3)], 23 | [[(2, 3), (2, 4)], (2,)], 24 | [[(2, 3), ], (2, 3)], 25 | [[(1, 3), (2, 3)], tuple()], 26 | [[], tuple()], 27 | ]) 28 | def test_get_shared_shape(shapes, expected): 29 | assert get_shared_shape([np.zeros(shape) for shape in shapes]) == expected 30 | -------------------------------------------------------------------------------- /tests/functional/third_party_overriding/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/functional/third_party_overriding/__init__.py -------------------------------------------------------------------------------- /tests/functional/third_party_overriding/conftest.py: -------------------------------------------------------------------------------- 1 | from unittest import mock 2 | 3 | import pytest 4 | 5 | from pyquibbler import Quib 6 | from pyquibbler.quib.factory import create_quib 7 | 8 | 9 | @pytest.fixture() 10 | def quib() -> Quib: 11 | return create_quib(func=mock.Mock()) 12 | 13 | 14 | @pytest.fixture 15 | def mock_module(): 16 | mdl = mock.Mock() 17 | mdl.__name__ = 'MockModule' 18 | return mdl 19 | 20 | @pytest.fixture 21 | def func_name_to_override(): 22 | return "hello_my_good_good_friend" 23 | 24 | 25 | @pytest.fixture 26 | def func_mock_on_module(mock_module, func_name_to_override): 27 | return getattr(mock_module, func_name_to_override) 28 | 29 | 30 | @pytest.fixture() 31 | def overridden_func(mock_module, func_name_to_override): 32 | return lambda *a: getattr(mock_module, func_name_to_override)(*a) 33 | -------------------------------------------------------------------------------- /tests/functional/third_party_overriding/test_graphics_definition.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from pyquibbler.env import GRAPHICS_LAZY 4 | from pyquibbler.function_overriding.third_party_overriding.matplotlib.helpers import graphics_override 5 | 6 | 7 | @pytest.fixture(autouse=True) 8 | def graphics_definition(mock_module, func_name_to_override, func_mock_on_module): 9 | definition = graphics_override(func_name=func_name_to_override, module_or_cls=mock_module) 10 | definition.override() 11 | return definition 12 | 13 | 14 | def test_graphics_func_does_run_by_default(overridden_func, func_mock_on_module, quib): 15 | overridden_func(quib, ) 16 | 17 | assert func_mock_on_module.call_count == 1 18 | 19 | 20 | def test_graphics_func_does_not_run_when_lazy_flag_set_to_true(overridden_func, func_mock_on_module, quib): 21 | with GRAPHICS_LAZY.temporary_set(True): 22 | overridden_func(quib, ) 23 | 24 | assert func_mock_on_module.call_count == 0 25 | -------------------------------------------------------------------------------- /tests/functional/third_party_overriding/test_not_implemented.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pytest 3 | 4 | from pyquibbler import iquib 5 | from pyquibbler.function_overriding.function_override import NotImplementedFunc 6 | 7 | 8 | def test_function_defined_as_unimplemented_does_runs_on_non_quibs(axes): 9 | axes.axis([0, 7, 0, 5]) 10 | assert np.array_equal(axes.get_xlim(), [0, 7]) 11 | assert np.array_equal(axes.get_ylim(), [0, 5]) 12 | 13 | 14 | def test_function_defined_as_unimplemented_raises_exception_on_quibs(axes): 15 | x = iquib(7) 16 | with pytest.raises(NotImplementedFunc, match='.*'): 17 | axes.grid(x) 18 | -------------------------------------------------------------------------------- /tests/functional/third_party_overriding/test_numpy_special.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from numpy import ogrid, mgrid 3 | from numpy.lib._index_tricks_impl import nd_grid 4 | 5 | from pyquibbler import iquib 6 | 7 | 8 | def test_orgrid_getitem_without_quibs(): 9 | grid = mgrid[0:3] 10 | assert np.array_equal(grid, [0, 1, 2]) 11 | 12 | 13 | def my_getitem(self, key): 14 | return key 15 | 16 | 17 | def test_orgrid_getitem_with_quibs(): 18 | n = iquib(3) 19 | grid = mgrid[0:n] 20 | assert np.array_equal(grid.get_value(), [0, 1, 2]) 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /tests/functional/third_party_overriding/test_patches.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | import numpy as np 4 | from matplotlib.patches import Rectangle 5 | from pyquibbler import iquib 6 | 7 | 8 | def check_rectangle_location(rectangle: Rectangle, args): 9 | xy, w, h = args 10 | return np.array_equal(rectangle.get_xy(), xy) \ 11 | and rectangle.get_width() == w \ 12 | and rectangle.get_height() == h 13 | 14 | 15 | @pytest.fixture() 16 | def get_only_patch_from_axes(axes): 17 | 18 | def get_(): 19 | assert len(axes.patches) == 1 20 | return axes.patches[0] 21 | 22 | return get_ 23 | 24 | 25 | def test_axes_add_patch_on_non_quib(axes, get_only_patch_from_axes): 26 | p = Rectangle((1, 2), 3, 4) 27 | axes.add_patch(p) 28 | assert p is get_only_patch_from_axes() 29 | 30 | 31 | def test_axes_add_patch_on_quib(axes, get_only_patch_from_axes): 32 | w = iquib(3) 33 | p = Rectangle((1, 2), w, 4) 34 | axes.add_patch(p) 35 | assert p.get_value() is get_only_patch_from_axes() 36 | 37 | 38 | def test_patch_update(axes, get_only_patch_from_axes): 39 | w = iquib(3) 40 | p = Rectangle((1, 2), w, 4) 41 | axes.add_patch(p) 42 | assert check_rectangle_location(p.get_value(), ((1, 2), 3, 4)), "sanity" 43 | 44 | w.assign(10) 45 | assert p.get_value() is get_only_patch_from_axes() 46 | assert check_rectangle_location(p.get_value(), ((1, 2), 10, 4)) 47 | -------------------------------------------------------------------------------- /tests/functional/third_party_overriding/test_q_rectangle_selector.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from pyquibbler.graphics.widgets import QRectangleSelector 4 | 5 | 6 | def test_move_only_one_rectangle_selector(axes, create_axes_mouse_press_move_release_events): 7 | w1 = QRectangleSelector(axes, extents=[0.4, 0.6, 0.4, 0.6]) 8 | w2 = QRectangleSelector(axes, extents=[0.4, 0.6, 0.4, 0.6]) 9 | 10 | create_axes_mouse_press_move_release_events([(0.5, 0.5), (0.6, 0.6), (0.7, 0.7)]) 11 | assert np.array_equal(np.round(w1.extents, 2), [0.6, 0.8, 0.6, 0.8]) 12 | assert np.array_equal(np.round(w2.extents, 2), [0.4, 0.6, 0.4, 0.6]) # this fails in normal RectangleSelector 13 | 14 | create_axes_mouse_press_move_release_events([(0.5, 0.5), (0.6, 0.6), (0.7, 0.7)]) 15 | assert np.array_equal(np.round(w1.extents, 2), [0.6, 0.8, 0.6, 0.8]) 16 | assert np.array_equal(np.round(w2.extents, 2), [0.6, 0.8, 0.6, 0.8]) 17 | -------------------------------------------------------------------------------- /tests/functional/utils.py: -------------------------------------------------------------------------------- 1 | from unittest import mock 2 | from unittest.mock import Mock 3 | from dataclasses import dataclass, field 4 | from typing import List 5 | 6 | from pyquibbler.quib.quib import Quib 7 | from pyquibbler.path import PathComponent, Path 8 | 9 | 10 | def get_mock_with_repr(repr_value: str): 11 | mock = Mock() 12 | mock.__repr__ = Mock(return_value=repr_value) 13 | return mock 14 | 15 | 16 | slicer = type('Slicer', (), dict(__getitem__=lambda self, item: item))() 17 | 18 | 19 | @dataclass 20 | class PathBuilder: 21 | quib: Quib 22 | path: Path = field(default_factory=list) 23 | 24 | def __getitem__(self, item): 25 | self.quib.get_type() # legacy from when PathComponent had type 26 | return PathBuilder(self.quib[item], [*self.path, PathComponent(item)]) 27 | 28 | 29 | def get_func_mock(func): 30 | return mock.create_autospec(func, side_effect=func) 31 | -------------------------------------------------------------------------------- /tests/integration/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/integration/__init__.py -------------------------------------------------------------------------------- /tests/integration/benchmarks/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/integration/benchmarks/__init__.py -------------------------------------------------------------------------------- /tests/integration/demos/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/integration/demos/__init__.py -------------------------------------------------------------------------------- /tests/integration/demos/baseline_images/test_covid_demo/covid_demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/integration/demos/baseline_images/test_covid_demo/covid_demo.png -------------------------------------------------------------------------------- /tests/integration/demos/baseline_images/test_gear_demo/gear_demo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/integration/demos/baseline_images/test_gear_demo/gear_demo.png -------------------------------------------------------------------------------- /tests/integration/quib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/integration/quib/__init__.py -------------------------------------------------------------------------------- /tests/integration/quib/graphics/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/integration/quib/graphics/__init__.py -------------------------------------------------------------------------------- /tests/integration/quib/graphics/test_general.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import pytest 3 | 4 | from pyquibbler import initialize_quibbler, iquib, Quib, quiby 5 | from pyquibbler.graphics.global_collecting import AxesCreatedDuringQuibEvaluationException 6 | 7 | 8 | @pytest.mark.regression 9 | def test_graphics_function_quib_doesnt_fail_on_removal_of_artists(axes): 10 | input_quib = iquib([1, 2, 3]) 11 | plt.plot(input_quib) 12 | plt.cla() 13 | 14 | input_quib[0] = 10 15 | 16 | 17 | @pytest.mark.regression 18 | def test_graphics_quiby_function_doesnt_fail_when_creating_axes(): 19 | def plot_draggable(y: Quib): 20 | plt.plot(y) 21 | 22 | plt.close("all") 23 | data = iquib([1, 2]) 24 | with pytest.raises(AxesCreatedDuringQuibEvaluationException, match='.*'): 25 | quiby(plot_draggable, is_graphics=True)(data) 26 | -------------------------------------------------------------------------------- /tests/integration/quib/graphics/widgets/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/integration/quib/graphics/widgets/__init__.py -------------------------------------------------------------------------------- /tests/integration/quib/graphics/widgets/baseline_images/test_checkbuttons/multiple_sets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/integration/quib/graphics/widgets/baseline_images/test_checkbuttons/multiple_sets.png -------------------------------------------------------------------------------- /tests/integration/quib/graphics/widgets/baseline_images/test_checkbuttons/unset.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/integration/quib/graphics/widgets/baseline_images/test_checkbuttons/unset.png -------------------------------------------------------------------------------- /tests/integration/quib/graphics/widgets/baseline_images/test_radio_buttons/set_active_multiple_times.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/integration/quib/graphics/widgets/baseline_images/test_radio_buttons/set_active_multiple_times.png -------------------------------------------------------------------------------- /tests/integration/quib/graphics/widgets/baseline_images/test_rectangle_selector/move.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/integration/quib/graphics/widgets/baseline_images/test_rectangle_selector/move.png -------------------------------------------------------------------------------- /tests/integration/quib/graphics/widgets/baseline_images/test_rectangle_selector/move_list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/integration/quib/graphics/widgets/baseline_images/test_rectangle_selector/move_list.png -------------------------------------------------------------------------------- /tests/integration/quib/graphics/widgets/baseline_images/test_slider/keeps_same_widget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/integration/quib/graphics/widgets/baseline_images/test_slider/keeps_same_widget.png -------------------------------------------------------------------------------- /tests/integration/quib/graphics/widgets/baseline_images/test_slider/multiple_times.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/integration/quib/graphics/widgets/baseline_images/test_slider/multiple_times.png -------------------------------------------------------------------------------- /tests/integration/quib/graphics/widgets/baseline_images/test_slider/press_and_release_changes.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/integration/quib/graphics/widgets/baseline_images/test_slider/press_and_release_changes.png -------------------------------------------------------------------------------- /tests/integration/quib/graphics/widgets/conftest.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | from matplotlib.widgets import AxesWidget 3 | 4 | from pyquibbler.debug_utils.track_instances import track_instances_of_class 5 | 6 | 7 | @pytest.fixture() 8 | def get_only_live_widget(live_widgets): 9 | def _get(): 10 | assert len(live_widgets) == 1 11 | return list(live_widgets)[0] 12 | 13 | return _get 14 | 15 | 16 | @pytest.fixture() 17 | def live_widgets(): 18 | with track_instances_of_class(AxesWidget, False) as tracker: 19 | yield tracker 20 | -------------------------------------------------------------------------------- /tests/lab_extension/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Technion-Kishony-lab/quibbler/fb371d899b4aa1e56fa8c2074962177607ff5af6/tests/lab_extension/__init__.py -------------------------------------------------------------------------------- /tests/lab_extension/notebooks/notebook_with_error.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "id": "5dc0e2e4", 7 | "metadata": {}, 8 | "outputs": [], 9 | "source": [ 10 | "# notebook with error\n", 11 | "assert False" 12 | ] 13 | } 14 | ], 15 | "metadata": { 16 | "kernelspec": { 17 | "display_name": "Python 3 (ipykernel)", 18 | "language": "python", 19 | "name": "python3" 20 | }, 21 | "language_info": { 22 | "codemirror_mode": { 23 | "name": "ipython", 24 | "version": 3 25 | }, 26 | "file_extension": ".py", 27 | "mimetype": "text/x-python", 28 | "name": "python", 29 | "nbconvert_exporter": "python", 30 | "pygments_lexer": "ipython3", 31 | "version": "3.11.9" 32 | } 33 | }, 34 | "nbformat": 4, 35 | "nbformat_minor": 5 36 | } 37 | -------------------------------------------------------------------------------- /tests/lab_extension/notebooks/test_saving.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "id": "5dc0e2e4", 7 | "metadata": {}, 8 | "outputs": [], 9 | "source": [ 10 | "from pyquibbler import iquib, initialize_quibbler\n", 11 | "initialize_quibbler()" 12 | ] 13 | }, 14 | { 15 | "metadata": {}, 16 | "cell_type": "code", 17 | "outputs": [], 18 | "execution_count": null, 19 | "source": [ 20 | "# Verify kernel restarts\n", 21 | "try:\n", 22 | " ID += 1\n", 23 | "except NameError:\n", 24 | " ID = 0\n", 25 | "assert ID == 0" 26 | ], 27 | "id": "ce3b0011760ef619" 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": null, 32 | "id": "3c3674c5", 33 | "metadata": { 34 | "pycharm": { 35 | "name": "#%%\n" 36 | } 37 | }, 38 | "outputs": [], 39 | "source": [ 40 | "name = iquib('michael')\n", 41 | "nums = iquib([1, 2., 3])" 42 | ] 43 | } 44 | ], 45 | "metadata": { 46 | "kernelspec": { 47 | "display_name": "Python 3 (ipykernel)", 48 | "language": "python", 49 | "name": "python3" 50 | }, 51 | "language_info": { 52 | "codemirror_mode": { 53 | "name": "ipython", 54 | "version": 3 55 | }, 56 | "file_extension": ".py", 57 | "mimetype": "text/x-python", 58 | "name": "python", 59 | "nbconvert_exporter": "python", 60 | "pygments_lexer": "ipython3", 61 | "version": "3.11.9" 62 | } 63 | }, 64 | "nbformat": 4, 65 | "nbformat_minor": 5 66 | } 67 | --------------------------------------------------------------------------------