interactive-pipe 0.8.0__tar.gz → 0.8.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. {interactive_pipe-0.8.0/src/interactive_pipe.egg-info → interactive_pipe-0.8.2}/PKG-INFO +2 -2
  2. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/pyproject.toml +1 -1
  3. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/readme.md +1 -1
  4. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/__init__.py +1 -1
  5. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/core/engine.py +1 -1
  6. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/core/pipeline.py +4 -0
  7. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/data_objects/audio.py +6 -0
  8. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/graphical/gradio_control.py +18 -3
  9. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/graphical/gradio_gui.py +57 -14
  10. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/graphical/qt_gui.py +5 -0
  11. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2/src/interactive_pipe.egg-info}/PKG-INFO +2 -2
  12. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/LICENSE +0 -0
  13. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/setup.cfg +0 -0
  14. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/core/__init__.py +0 -0
  15. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/core/cache.py +0 -0
  16. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/core/filter.py +0 -0
  17. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/core/graph.py +0 -0
  18. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/core/signature.py +0 -0
  19. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/data_objects/__init__.py +0 -0
  20. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/data_objects/curves.py +0 -0
  21. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/data_objects/data.py +0 -0
  22. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/data_objects/image.py +0 -0
  23. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/data_objects/parameters.py +0 -0
  24. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/graphical/__init__.py +0 -0
  25. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/graphical/gui.py +0 -0
  26. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/graphical/mpl_control.py +0 -0
  27. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/graphical/mpl_gui.py +0 -0
  28. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/graphical/mpl_window.py +0 -0
  29. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/graphical/nb_control.py +0 -0
  30. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/graphical/nb_gui.py +0 -0
  31. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/graphical/qt_control.py +0 -0
  32. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/graphical/window.py +0 -0
  33. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/headless/__init__.py +0 -0
  34. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/headless/control.py +0 -0
  35. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/headless/keyboard.py +0 -0
  36. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/headless/pipeline.py +0 -0
  37. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/helper/__init__.py +0 -0
  38. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/helper/_private.py +0 -0
  39. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/helper/choose_backend.py +0 -0
  40. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/helper/control_abbreviation.py +0 -0
  41. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/helper/filter_decorator.py +0 -0
  42. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/helper/keyword_args_analyzer.py +0 -0
  43. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/helper/pipeline_decorator.py +0 -0
  44. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/thirdparty/images_openai_api.py +0 -0
  45. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe/thirdparty/music_spotify.py +0 -0
  46. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe.egg-info/SOURCES.txt +0 -0
  47. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe.egg-info/dependency_links.txt +0 -0
  48. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe.egg-info/requires.txt +0 -0
  49. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/src/interactive_pipe.egg-info/top_level.txt +0 -0
  50. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/test/test_cache.py +0 -0
  51. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/test/test_control_abbreviations.py +0 -0
  52. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/test/test_controller.py +0 -0
  53. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/test/test_core.py +0 -0
  54. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/test/test_curves.py +0 -0
  55. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/test/test_decorator.py +0 -0
  56. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/test/test_engine.py +0 -0
  57. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/test/test_filter.py +0 -0
  58. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/test/test_headless.py +0 -0
  59. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/test/test_image.py +0 -0
  60. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/test/test_parameters.py +0 -0
  61. {interactive_pipe-0.8.0 → interactive_pipe-0.8.2}/test/test_recorder.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: interactive_pipe
3
- Version: 0.8.0
3
+ Version: 0.8.2
4
4
  Summary: Library to create flexible interactive image processing pipelines and automatically add a graphical user interface without knowing anything about GUI coding!
5
5
  Author-email: Balthazar Neveu <balthazarneveu@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/balthazarneveu/interactive_pipe
@@ -106,7 +106,7 @@ pip install -e ".[full]"
106
106
 
107
107
  ## :scroll: Features
108
108
 
109
- **Version 0.8.0**
109
+ **Version 0.8.2**
110
110
  - Modular multi-image processing filters
111
111
  - Declarative: Easily make graphical user interface without having to learn anything about pyQt or matplotlib
112
112
  - Support in jupyter notebooks
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
5
5
 
6
6
  [project]
7
7
  name = "interactive_pipe"
8
- version = "0.8.0"
8
+ version = "0.8.2"
9
9
  authors = [
10
10
  { name="Balthazar Neveu", email="balthazarneveu@gmail.com" },
11
11
  ]
@@ -62,7 +62,7 @@ pip install -e ".[full]"
62
62
 
63
63
  ## :scroll: Features
64
64
 
65
- **Version 0.8.0**
65
+ **Version 0.8.2**
66
66
  - Modular multi-image processing filters
67
67
  - Declarative: Easily make graphical user interface without having to learn anything about pyQt or matplotlib
68
68
  - Support in jupyter notebooks
@@ -1,4 +1,4 @@
1
- __version__ = "0.8.0"
1
+ __version__ = "0.8.2"
2
2
  from interactive_pipe.helper.pipeline_decorator import pipeline, interactive_pipeline
3
3
  from interactive_pipe.headless.control import Control, CircularControl
4
4
  from interactive_pipe.data_objects.curves import Curve, SingleCurve
@@ -40,7 +40,7 @@ class PipelineEngine:
40
40
  # if cache not available or if cache available and values have changed, need to recalculate from now on
41
41
  # cache | has changed | skip_calculation
42
42
  # 0 | X | False -> no cache, cannot skip so calculate
43
- # 1 | 0 | True -> cache with no change, skip the calculation
43
+ # 1 | 0 | True -> cache with no change, skip the calculation
44
44
  # 1 | 1 | False -> cache and result changed, cannot skip so calculate
45
45
  skip_calculation &= (prc.cache_mem is not None) and (
46
46
  not prc.cache_mem.has_changed(prc.values))
@@ -78,6 +78,10 @@ class PipelineCore:
78
78
  """
79
79
  return self.engine.run(self.filters, imglst=self.inputs)
80
80
 
81
+ def _reset_global_params(self):
82
+ for filter in self.filters:
83
+ filter.global_params = self.global_params
84
+
81
85
  @property
82
86
  def parameters(self):
83
87
  parameters = {}
@@ -13,6 +13,8 @@ try:
13
13
  except ImportError:
14
14
  logging.info("Cannot import wavio")
15
15
 
16
+ __iter_audio_player = 0
17
+
16
18
 
17
19
  def audio_to_html(audio: Union[None, str, Path, Tuple[int, np.ndarray]], controls=True) -> str:
18
20
  if audio is None:
@@ -33,6 +35,10 @@ def audio_to_html(audio: Union[None, str, Path, Tuple[int, np.ndarray]], control
33
35
  if controls:
34
36
  audio_player += ' controls'
35
37
  audio_player += ' autoplay></audio>'
38
+ global __iter_audio_player
39
+ # to avoid reusing the same exact id and thus not updating the audio player
40
+ audio_player += "<p hidden>"+str(__iter_audio_player)+"</p>"
41
+ __iter_audio_player += 1
36
42
 
37
43
  return audio_player
38
44
 
@@ -1,5 +1,3 @@
1
-
2
- from functools import partial
3
1
  from interactive_pipe.headless.control import Control
4
2
  import logging
5
3
  import gradio as gr
@@ -31,7 +29,7 @@ class ControlFactory:
31
29
  bool: TickBoxControl,
32
30
  int: IntSliderControl,
33
31
  float: FloatSliderControl,
34
- str: DropdownMenuControl
32
+ str: DropdownMenuControl if control.icons is None else IconButtonsControl
35
33
  }
36
34
 
37
35
  if control_type not in control_class_map:
@@ -101,3 +99,20 @@ class DropdownMenuControl(BaseControl):
101
99
  if index >= 0:
102
100
  self.control_widget.setCurrentIndex(index)
103
101
  self.control_widget.setCurrentIndex(index)
102
+
103
+
104
+ class IconButtonsControl(BaseControl):
105
+ def check_control_type(self):
106
+ assert self.ctrl._type == str
107
+ if not hasattr(self.ctrl, 'value_range'):
108
+ raise ValueError("Invalid control type")
109
+
110
+ def create(self) -> gr.Radio:
111
+ self.control_widget = []
112
+ for idx, icon in enumerate(self.ctrl.icons):
113
+ # text = self.ctrl.value_range[idx]
114
+ text = ""
115
+ self.control_widget.append(
116
+ gr.Button(text, icon=self.ctrl.icons[idx])
117
+ )
118
+ return self.control_widget
@@ -8,6 +8,7 @@ from interactive_pipe.graphical.window import InteractivePipeWindow
8
8
  from interactive_pipe.graphical.gui import InteractivePipeGUI
9
9
  from interactive_pipe.headless.control import Control
10
10
  from interactive_pipe.data_objects.audio import audio_to_html
11
+ from copy import copy
11
12
  import logging
12
13
  PYQTVERSION = None
13
14
  MPL_SUPPORT = False
@@ -46,7 +47,18 @@ class InteractivePipeGradio(InteractivePipeGUI):
46
47
 
47
48
  def run(self) -> list:
48
49
  assert self.pipeline._PipelineCore__initialized_inputs, "Did you forget to initialize the pipeline inputs?"
50
+ # In gradio, the first run is a "dry run", used to get the output types...
51
+ try:
52
+ global_params_first_run = copy(self.pipeline.global_params)
53
+ # Do not use deepcopy, it will break the audio playback feature
54
+ except Exception as exc:
55
+ logging.warning(f"Cannot copy global_params: {exc}")
56
+ global_params_first_run = self.pipeline.global_params
57
+ pass
49
58
  out_list = self.window.process_inputs_fn(*self.window.default_values)
59
+ self.pipeline.global_params = global_params_first_run
60
+ # Reset global parameters... in case they were modified by the first run
61
+ self.pipeline._reset_global_params()
50
62
  self.window.refresh_display(out_list)
51
63
  out_list_gradio_containers = []
52
64
  for idx in range(len(out_list)):
@@ -147,7 +159,10 @@ class MainWindow(InteractivePipeWindow):
147
159
  out_tuple = process_outputs_fn(out)
148
160
  if self.audio:
149
161
  html_audio = audio_to_html(self.audio_content)
150
- return *out_tuple, html_audio
162
+ if isinstance(out_tuple, tuple):
163
+ return *out_tuple, html_audio
164
+ else:
165
+ return out_tuple, html_audio
151
166
  return out_tuple
152
167
  self.default_values = [self.ctrl[ctrl_key].value for ctrl_key in self.ctrl.keys()]
153
168
  self.process_inputs_fn = process_inputs_fn
@@ -221,9 +236,14 @@ class MainWindow(InteractivePipeWindow):
221
236
  continue
222
237
  if self.sliders_per_row_layout == 1:
223
238
  with selected_mode:
224
- for idx in ctrl_indices:
225
- elem = self.widget_list[idx]
226
- elem.render()
239
+ for idx in range(len(self.widget_list)):
240
+ if isinstance(self.widget_list[idx], list):
241
+ with gr.Row():
242
+ for elem in self.widget_list[idx]:
243
+ elem.render()
244
+ else:
245
+ elem = self.widget_list[idx]
246
+ elem.render()
227
247
  else:
228
248
  with selected_mode:
229
249
  for split_num in range(math.ceil(len(ctrl_indices)/self.sliders_per_row_layout)):
@@ -233,10 +253,19 @@ class MainWindow(InteractivePipeWindow):
233
253
  for idx in ctrl_indices[start:end]:
234
254
  elem = self.widget_list[idx]
235
255
  elem.render()
236
-
237
- with gr.Accordion("Reset to default values", open=False):
238
- gr.Examples([self.default_values], inputs=self.widget_list, label="Presets")
239
-
256
+ changing_inputs = []
257
+ discard_reset_button = False
258
+ for idx in range(len(self.widget_list)):
259
+ if isinstance(self.widget_list[idx], list):
260
+ changing_inputs.append(gr.State(self.ctrl[list(self.ctrl.keys())[idx]].value_default))
261
+ discard_reset_button = True # Do not show reset button if there are lists of buttons
262
+ self.ctrl[list(self.ctrl.keys())[idx]].filter_to_connect.cache = False
263
+ self.ctrl[list(self.ctrl.keys())[idx]].filter_to_connect.cache_mem = None
264
+ else:
265
+ changing_inputs.append(self.widget_list[idx])
266
+ if not discard_reset_button:
267
+ with gr.Accordion("Reset to default values", open=False):
268
+ gr.Examples([self.default_values], inputs=changing_inputs, label="Presets")
240
269
  if self.markdown_description is not None:
241
270
  title = "Description"
242
271
  try:
@@ -246,13 +275,27 @@ class MainWindow(InteractivePipeWindow):
246
275
  pass
247
276
  with gr.Accordion(title, open=False):
248
277
  gr.Markdown(self.markdown_description)
249
- io.load(fn=self.run_fn, inputs=self.widget_list, outputs=outputs)
278
+ io.load(fn=self.run_fn, inputs=changing_inputs, outputs=outputs)
250
279
  for idx in range(len(self.widget_list)):
251
- self.widget_list[idx].change(
252
- fn=self.run_fn, inputs=self.widget_list,
253
- outputs=outputs,
254
- show_progress="minimal"
255
- )
280
+ if isinstance(self.widget_list[idx], list):
281
+ for idy, elem in enumerate(self.widget_list[idx]):
282
+ changing_inputs_copy = changing_inputs.copy()
283
+ changing_inputs_copy[idx] = gr.State(
284
+ self.ctrl[list(self.ctrl.keys())[idx]].value_range[idy])
285
+ elem.click(
286
+ fn=self.run_fn,
287
+ inputs=changing_inputs_copy,
288
+ outputs=outputs,
289
+ show_progress="minimal"
290
+ )
291
+ else:
292
+ self.widget_list[idx].change(
293
+ fn=self.run_fn,
294
+ inputs=changing_inputs,
295
+ outputs=outputs,
296
+ show_progress="minimal"
297
+ )
298
+
256
299
  self.io = io
257
300
  self.io.launch(share=self.share_gradio_app)
258
301
 
@@ -318,6 +318,11 @@ class MainWindow(QWidget, InteractivePipeWindow):
318
318
  elif isinstance(ctrl, Control):
319
319
  slider_instance = control_factory.create_control(
320
320
  ctrl, self.update_parameter)
321
+ if ctrl._type == str and ctrl.icons is not None:
322
+ ctrl.filter_to_connect.cache = False
323
+ ctrl.filter_to_connect.cache_mem = None
324
+ # Disable cache for dropdown menu with icons!
325
+ # Allows clicking on the same item multiple times
321
326
  slider_or_layout = slider_instance.create()
322
327
  self.widget_list[slider_name] = slider_instance
323
328
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: interactive_pipe
3
- Version: 0.8.0
3
+ Version: 0.8.2
4
4
  Summary: Library to create flexible interactive image processing pipelines and automatically add a graphical user interface without knowing anything about GUI coding!
5
5
  Author-email: Balthazar Neveu <balthazarneveu@gmail.com>
6
6
  Project-URL: Homepage, https://github.com/balthazarneveu/interactive_pipe
@@ -106,7 +106,7 @@ pip install -e ".[full]"
106
106
 
107
107
  ## :scroll: Features
108
108
 
109
- **Version 0.8.0**
109
+ **Version 0.8.2**
110
110
  - Modular multi-image processing filters
111
111
  - Declarative: Easily make graphical user interface without having to learn anything about pyQt or matplotlib
112
112
  - Support in jupyter notebooks