pySimBlocks 0.1.1__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (307) hide show
  1. {pysimblocks-0.1.1/pySimBlocks.egg-info → pysimblocks-0.2.0}/PKG-INFO +3 -2
  2. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/README.md +1 -1
  3. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/interfaces/__init__.py +5 -1
  4. pysimblocks-0.2.0/pySimBlocks/blocks/interfaces/bus_from.py +88 -0
  5. pysimblocks-0.2.0/pySimBlocks/blocks/interfaces/goto.py +78 -0
  6. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/file_source.py +30 -5
  7. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/__init__.py +2 -0
  8. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/linear_state_space.py +40 -5
  9. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/non_linear_state_space.py +2 -4
  10. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/sofa/sofa_controller.py +151 -16
  11. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/sofa/sofa_plant.py +2 -1
  12. pysimblocks-0.2.0/pySimBlocks/blocks/systems/transfer_function.py +380 -0
  13. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/cli.py +45 -19
  14. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/core/config.py +27 -3
  15. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/core/model.py +42 -0
  16. pysimblocks-0.2.0/pySimBlocks/core/signal_bus.py +37 -0
  17. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/core/simulator.py +3 -0
  18. pysimblocks-0.2.0/pySimBlocks/docs/blocks/interfaces/bus_from.md +63 -0
  19. pysimblocks-0.2.0/pySimBlocks/docs/blocks/interfaces/goto.md +59 -0
  20. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/file_source.md +4 -1
  21. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/systems/linear_state_space.md +22 -5
  22. pysimblocks-0.2.0/pySimBlocks/docs/blocks/systems/transfer_function.md +89 -0
  23. pysimblocks-0.2.0/pySimBlocks/gui/addons/sofa/slider_params_dialog.py +513 -0
  24. pysimblocks-0.2.0/pySimBlocks/gui/addons/sofa/sofa_dialog.py +324 -0
  25. pysimblocks-0.2.0/pySimBlocks/gui/addons/sofa/sofa_service.py +397 -0
  26. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/block_dialog_session.py +13 -6
  27. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/block_meta.py +4 -1
  28. pysimblocks-0.2.0/pySimBlocks/gui/blocks/interfaces/bus_from.py +228 -0
  29. pysimblocks-0.2.0/pySimBlocks/gui/blocks/interfaces/goto.py +74 -0
  30. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/file_source.py +16 -2
  31. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/systems/linear_state_space.py +9 -1
  32. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/systems/sofa/sofa_exchange_i_o.py +5 -1
  33. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/systems/sofa/sofa_plant.py +5 -1
  34. pysimblocks-0.2.0/pySimBlocks/gui/blocks/systems/transfer_function.py +122 -0
  35. pysimblocks-0.2.0/pySimBlocks/gui/diagram_clipboard.py +694 -0
  36. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/block_dialog.py +6 -2
  37. pysimblocks-0.2.0/pySimBlocks/gui/dialogs/export_npz_dialog.py +171 -0
  38. pysimblocks-0.2.0/pySimBlocks/gui/dialogs/plot_dialog.py +1564 -0
  39. pysimblocks-0.2.0/pySimBlocks/gui/dialogs/plot_series_style_dialog.py +268 -0
  40. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/settings/plots.py +53 -3
  41. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/settings/project.py +24 -0
  42. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/editor.py +6 -2
  43. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/graphics/__init__.py +7 -1
  44. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/graphics/block_item.py +58 -7
  45. pysimblocks-0.2.0/pySimBlocks/gui/graphics/connection_item.py +497 -0
  46. pysimblocks-0.2.0/pySimBlocks/gui/graphics/group_item.py +490 -0
  47. pysimblocks-0.2.0/pySimBlocks/gui/graphics/group_proxy_item.py +245 -0
  48. pysimblocks-0.2.0/pySimBlocks/gui/graphics/manual_boundary_wire_item.py +53 -0
  49. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/graphics/theme.py +8 -0
  50. pysimblocks-0.2.0/pySimBlocks/gui/group_boundary_labels.py +38 -0
  51. pysimblocks-0.2.0/pySimBlocks/gui/group_ports.py +10 -0
  52. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/main_window.py +74 -32
  53. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/models/__init__.py +4 -1
  54. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/models/project_state.py +61 -5
  55. pysimblocks-0.2.0/pySimBlocks/gui/models/visual_group.py +130 -0
  56. pysimblocks-0.2.0/pySimBlocks/gui/project_controller.py +2611 -0
  57. pysimblocks-0.2.0/pySimBlocks/gui/services/group_boundary_service.py +168 -0
  58. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/services/project_loader.py +105 -7
  59. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/services/simulation_runner.py +3 -9
  60. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/services/yaml_tools.py +72 -37
  61. pysimblocks-0.2.0/pySimBlocks/gui/undo_redo/commands.py +775 -0
  62. pysimblocks-0.2.0/pySimBlocks/gui/undo_redo/undo_redo_manager.py +60 -0
  63. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/widgets/block_list.py +19 -2
  64. pysimblocks-0.2.0/pySimBlocks/gui/widgets/diagram_view.py +1366 -0
  65. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/widgets/toolbar_view.py +135 -15
  66. pysimblocks-0.2.0/pySimBlocks/gui/widgets/view_navigation_bar.py +86 -0
  67. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/project/generate_run_script.py +54 -19
  68. pysimblocks-0.2.0/pySimBlocks/project/generate_sofa_scaffold.py +191 -0
  69. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/project/load_project_config.py +42 -0
  70. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/project/load_simulation_config.py +67 -0
  71. pysimblocks-0.2.0/pySimBlocks/project/plot_from_config.py +272 -0
  72. pysimblocks-0.2.0/pySimBlocks/project/plot_series.py +337 -0
  73. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/project/pySimBlocks_blocks_index.yaml +9 -0
  74. {pysimblocks-0.1.1 → pysimblocks-0.2.0/pySimBlocks.egg-info}/PKG-INFO +3 -2
  75. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks.egg-info/SOURCES.txt +27 -91
  76. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks.egg-info/requires.txt +1 -0
  77. pysimblocks-0.2.0/pySimBlocks.egg-info/top_level.txt +1 -0
  78. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pyproject.toml +3 -1
  79. pysimblocks-0.1.1/docs/_build/html/_downloads/005a2fbb3c705d1ad26b3514425388ea/filter.py +0 -35
  80. pysimblocks-0.1.1/docs/_build/html/_downloads/55a3b8989a3f25f02b02155793932456/run.py +0 -14
  81. pysimblocks-0.1.1/docs/_build/html/_downloads/6f0602c197379a812604b0c5d14a0785/main.py +0 -99
  82. pysimblocks-0.1.1/docs/source/_ext/api_generator.py +0 -295
  83. pysimblocks-0.1.1/docs/source/conf.py +0 -116
  84. pysimblocks-0.1.1/examples/advanced/hardware/block_diagram.py +0 -162
  85. pysimblocks-0.1.1/examples/advanced/hardware/camera.py +0 -93
  86. pysimblocks-0.1.1/examples/advanced/hardware/gui_emio.py +0 -231
  87. pysimblocks-0.1.1/examples/advanced/hardware/lmi.py +0 -69
  88. pysimblocks-0.1.1/examples/advanced/hardware/main.py +0 -57
  89. pysimblocks-0.1.1/examples/advanced/hardware/parameters.py +0 -54
  90. pysimblocks-0.1.1/examples/advanced/qp_problem/params.py +0 -10
  91. pysimblocks-0.1.1/examples/advanced/qp_problem/run.py +0 -14
  92. pysimblocks-0.1.1/examples/advanced/sofa/gui/finger/Finger.py +0 -108
  93. pysimblocks-0.1.1/examples/advanced/sofa/gui/finger/FingerController.py +0 -53
  94. pysimblocks-0.1.1/examples/advanced/sofa/gui/finger/parameters_auto.py +0 -22
  95. pysimblocks-0.1.1/examples/advanced/sofa/gui/sofa_plant/run.py +0 -14
  96. pysimblocks-0.1.1/examples/advanced/sofa/python/Finger.py +0 -107
  97. pysimblocks-0.1.1/examples/advanced/sofa/python/FingerController.py +0 -48
  98. pysimblocks-0.1.1/examples/advanced/sofa/python/closedloop.py +0 -64
  99. pysimblocks-0.1.1/examples/advanced/sofa/python/openloop.py +0 -58
  100. pysimblocks-0.1.1/examples/basics/algebraic_function/g.py +0 -7
  101. pysimblocks-0.1.1/examples/basics/algebraic_function/run.py +0 -14
  102. pysimblocks-0.1.1/examples/basics/dc_motor/gui/run.py +0 -14
  103. pysimblocks-0.1.1/examples/basics/dc_motor/multiple_order.py +0 -91
  104. pysimblocks-0.1.1/examples/basics/dc_motor/openloop.py +0 -62
  105. pysimblocks-0.1.1/examples/basics/dc_motor/pi.py +0 -99
  106. pysimblocks-0.1.1/examples/basics/dc_motor/pid.py +0 -118
  107. pysimblocks-0.1.1/examples/basics/dc_motor/pid_block.py +0 -82
  108. pysimblocks-0.1.1/examples/basics/dc_motor/pid_block_vs_manual.py +0 -143
  109. pysimblocks-0.1.1/examples/basics/external/parameters.py +0 -4
  110. pysimblocks-0.1.1/examples/basics/external/run.py +0 -14
  111. pysimblocks-0.1.1/examples/basics/file_sources/temp.py +0 -16
  112. pysimblocks-0.1.1/examples/basics/observer.py +0 -76
  113. pysimblocks-0.1.1/examples/basics/state_feedback/gui/parameters.py +0 -9
  114. pysimblocks-0.1.1/examples/basics/state_feedback/gui/run.py +0 -14
  115. pysimblocks-0.1.1/examples/basics/state_feedback/state_feedback.py +0 -102
  116. pysimblocks-0.1.1/examples/basics/state_space/linear/gui/run.py +0 -14
  117. pysimblocks-0.1.1/examples/basics/state_space/linear/ss_block.py +0 -89
  118. pysimblocks-0.1.1/examples/basics/state_space/linear/ss_manual.py +0 -105
  119. pysimblocks-0.1.1/examples/basics/state_space/non_linear/nlss.py +0 -47
  120. pysimblocks-0.1.1/examples/basics/state_space/non_linear/run.py +0 -14
  121. pysimblocks-0.1.1/examples/basics/state_space/polytope/params.py +0 -39
  122. pysimblocks-0.1.1/examples/basics/state_space/polytope/weights.py +0 -12
  123. pysimblocks-0.1.1/examples/comparison/simulink/convert.py +0 -29
  124. pysimblocks-0.1.1/examples/comparison/simulink/openloop.py +0 -127
  125. pysimblocks-0.1.1/examples/comparison/simulink/pi.py +0 -148
  126. pysimblocks-0.1.1/examples/comparison/simulink/pid.py +0 -154
  127. pysimblocks-0.1.1/examples/comparison/simulink/pid_backward.py +0 -155
  128. pysimblocks-0.1.1/examples/quick_start/filter.py +0 -35
  129. pysimblocks-0.1.1/examples/quick_start/gui/run.py +0 -14
  130. pysimblocks-0.1.1/examples/tutorials/tutorial_1_python/main.py +0 -99
  131. pysimblocks-0.1.1/examples/tutorials/tutorial_2_gui/run.py +0 -14
  132. pysimblocks-0.1.1/examples/tutorials/tutorial_3_sofa/finger/Finger.py +0 -120
  133. pysimblocks-0.1.1/examples/tutorials/tutorial_3_sofa/finger/FingerController.py +0 -35
  134. pysimblocks-0.1.1/pySimBlocks/gui/addons/sofa/sofa_dialog.py +0 -238
  135. pysimblocks-0.1.1/pySimBlocks/gui/addons/sofa/sofa_service.py +0 -250
  136. pysimblocks-0.1.1/pySimBlocks/gui/dialogs/plot_dialog.py +0 -245
  137. pysimblocks-0.1.1/pySimBlocks/gui/graphics/connection_item.py +0 -325
  138. pysimblocks-0.1.1/pySimBlocks/gui/project_controller.py +0 -437
  139. pysimblocks-0.1.1/pySimBlocks/gui/widgets/diagram_view.py +0 -420
  140. pysimblocks-0.1.1/pySimBlocks/project/generate_sofa_controller.py +0 -259
  141. pysimblocks-0.1.1/pySimBlocks/project/plot_from_config.py +0 -158
  142. pysimblocks-0.1.1/pySimBlocks.egg-info/top_level.txt +0 -7
  143. pysimblocks-0.1.1/tests/blocks/controllers/test_pid.py +0 -143
  144. pysimblocks-0.1.1/tests/blocks/controllers/test_state_feedback.py +0 -193
  145. pysimblocks-0.1.1/tests/blocks/observers/test_luenberger.py +0 -225
  146. pysimblocks-0.1.1/tests/blocks/operators/test_algebraic_function.py +0 -230
  147. pysimblocks-0.1.1/tests/blocks/operators/test_dead_zone.py +0 -106
  148. pysimblocks-0.1.1/tests/blocks/operators/test_delay.py +0 -167
  149. pysimblocks-0.1.1/tests/blocks/operators/test_demux.py +0 -111
  150. pysimblocks-0.1.1/tests/blocks/operators/test_discrete_derivator.py +0 -160
  151. pysimblocks-0.1.1/tests/blocks/operators/test_discrete_integrator.py +0 -149
  152. pysimblocks-0.1.1/tests/blocks/operators/test_gain.py +0 -182
  153. pysimblocks-0.1.1/tests/blocks/operators/test_mux.py +0 -101
  154. pysimblocks-0.1.1/tests/blocks/operators/test_product.py +0 -171
  155. pysimblocks-0.1.1/tests/blocks/operators/test_rate_limiter.py +0 -166
  156. pysimblocks-0.1.1/tests/blocks/operators/test_saturation.py +0 -157
  157. pysimblocks-0.1.1/tests/blocks/operators/test_sum.py +0 -183
  158. pysimblocks-0.1.1/tests/blocks/operators/test_zero_order_hold.py +0 -106
  159. pysimblocks-0.1.1/tests/blocks/sources/test_chirp.py +0 -157
  160. pysimblocks-0.1.1/tests/blocks/sources/test_constant.py +0 -55
  161. pysimblocks-0.1.1/tests/blocks/sources/test_file_source.py +0 -185
  162. pysimblocks-0.1.1/tests/blocks/sources/test_function_source.py +0 -135
  163. pysimblocks-0.1.1/tests/blocks/sources/test_ramp.py +0 -110
  164. pysimblocks-0.1.1/tests/blocks/sources/test_sinusoidal.py +0 -113
  165. pysimblocks-0.1.1/tests/blocks/sources/test_step.py +0 -76
  166. pysimblocks-0.1.1/tests/blocks/sources/test_white_noise.py +0 -108
  167. pysimblocks-0.1.1/tests/blocks/systems/test_linear_state_space.py +0 -135
  168. pysimblocks-0.1.1/tests/blocks/systems/test_polytopic_state_space.py +0 -133
  169. pysimblocks-0.1.1/tests/core/test_core_errors_and_determinism.py +0 -82
  170. pysimblocks-0.1.1/tests/core/test_core_multirate_tasks.py +0 -97
  171. pysimblocks-0.1.1/tests/core/test_core_two_phase_and_propagation.py +0 -132
  172. pysimblocks-0.1.1/tests/gui/main_window_open_test.py +0 -162
  173. pysimblocks-0.1.1/tests/gui/test_block_meta_param_cache.py +0 -16
  174. pysimblocks-0.1.1/tests/gui/test_file_source_meta.py +0 -17
  175. pysimblocks-0.1.1/tests/gui/test_function_source_meta.py +0 -28
  176. pysimblocks-0.1.1/tests/regression/test_simulink_dc_motor.py +0 -217
  177. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/LICENSE.md +0 -0
  178. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/__init__.py +0 -0
  179. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/__init__.py +0 -0
  180. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/controllers/__init__.py +0 -0
  181. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/controllers/pid.py +0 -0
  182. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/controllers/state_feedback.py +0 -0
  183. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/interfaces/external_input.py +0 -0
  184. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/interfaces/external_output.py +0 -0
  185. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/observers/__init__.py +0 -0
  186. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/observers/luenberger.py +0 -0
  187. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/__init__.py +0 -0
  188. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/algebraic_function.py +0 -0
  189. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/dead_zone.py +0 -0
  190. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/delay.py +0 -0
  191. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/demux.py +0 -0
  192. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/discrete_derivator.py +0 -0
  193. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/discrete_integrator.py +0 -0
  194. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/gain.py +0 -0
  195. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/mux.py +0 -0
  196. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/product.py +0 -0
  197. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/rate_limiter.py +0 -0
  198. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/saturation.py +0 -0
  199. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/sum.py +0 -0
  200. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/operators/zero_order_hold.py +0 -0
  201. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/optimizers/__init__.py +0 -0
  202. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/optimizers/quadratic_program.py +0 -0
  203. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/__init__.py +0 -0
  204. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/chirp.py +0 -0
  205. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/constant.py +0 -0
  206. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/function_source.py +0 -0
  207. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/ramp.py +0 -0
  208. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/sinusoidal.py +0 -0
  209. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/step.py +0 -0
  210. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/sources/white_noise.py +0 -0
  211. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/polytopic_state_space.py +0 -0
  212. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/sofa/__init__.py +0 -0
  213. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/blocks/systems/sofa/sofa_exchange_i_o.py +0 -0
  214. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/core/__init__.py +0 -0
  215. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/core/block.py +0 -0
  216. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/core/block_source.py +0 -0
  217. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/core/fixed_time_manager.py +0 -0
  218. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/core/scheduler.py +0 -0
  219. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/core/task.py +0 -0
  220. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/controllers/pid.md +0 -0
  221. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/controllers/state_feedback.md +0 -0
  222. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/interfaces/external_input.md +0 -0
  223. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/interfaces/external_output.md +0 -0
  224. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/observers/luenberger.md +0 -0
  225. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/algebraic_function.md +0 -0
  226. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/dead_zone.md +0 -0
  227. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/delay.md +0 -0
  228. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/demux.md +0 -0
  229. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/discrete_derivator.md +0 -0
  230. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/discrete_integrator.md +0 -0
  231. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/gain.md +0 -0
  232. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/mux.md +0 -0
  233. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/product.md +0 -0
  234. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/rate_limiter.md +0 -0
  235. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/saturation.md +0 -0
  236. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/sum.md +0 -0
  237. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/operators/zero_order_hold.md +0 -0
  238. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/optimizers/quadratic_program.md +0 -0
  239. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/chirp.md +0 -0
  240. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/constant.md +0 -0
  241. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/function_source.md +0 -0
  242. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/ramp.md +0 -0
  243. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/sinusoidal.md +0 -0
  244. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/step.md +0 -0
  245. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/sources/white_noise.md +0 -0
  246. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/systems/non_linear_state_space.md +0 -0
  247. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/systems/polytopic_state_space.md +0 -0
  248. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/systems/sofa/sofa_exchange_i_o.md +0 -0
  249. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/docs/blocks/systems/sofa/sofa_plant.md +0 -0
  250. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/__init__.py +0 -0
  251. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/addons/__init__.py +0 -0
  252. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/addons/sofa/__init__.py +0 -0
  253. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/controllers/pid.py +0 -0
  254. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/controllers/state_feedback.py +0 -0
  255. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/interfaces/external_input.py +0 -0
  256. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/interfaces/external_output.py +0 -0
  257. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/observers/luenberger.py +0 -0
  258. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/algebraic_function.py +0 -0
  259. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/dead_zone.py +0 -0
  260. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/delay.py +0 -0
  261. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/demux.py +0 -0
  262. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/discrete_derivator.py +0 -0
  263. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/discrete_integrator.py +0 -0
  264. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/gain.py +0 -0
  265. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/mux.py +0 -0
  266. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/product.py +0 -0
  267. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/rate_limiter.py +0 -0
  268. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/saturation.py +0 -0
  269. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/sum.py +0 -0
  270. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/operators/zero_order_hold.py +0 -0
  271. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/optimizers/quadratic_program.py +0 -0
  272. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/parameter_meta.py +0 -0
  273. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/port_meta.py +0 -0
  274. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/chirp.py +0 -0
  275. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/constant.py +0 -0
  276. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/function_source.py +0 -0
  277. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/ramp.py +0 -0
  278. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/sinusoidal.py +0 -0
  279. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/step.py +0 -0
  280. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/sources/white_noise.py +0 -0
  281. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/systems/non_linear_state_space.py +0 -0
  282. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/blocks/systems/polytopic_state_space.py +0 -0
  283. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/__init__.py +0 -0
  284. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/display_yaml_dialog.py +0 -0
  285. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/help_dialog.py +0 -0
  286. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/settings/simulation.py +0 -0
  287. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/settings_dialog.py +0 -0
  288. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/dialogs/unsaved_dialog.py +0 -0
  289. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/graphics/port_item.py +0 -0
  290. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/models/block_instance.py +0 -0
  291. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/models/connection_instance.py +0 -0
  292. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/models/port_instance.py +0 -0
  293. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/models/project_simulation_params.py +0 -0
  294. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/services/__init__.py +0 -0
  295. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/services/project_saver.py +0 -0
  296. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/gui/widgets/__init__.py +0 -0
  297. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/project/__init__.py +0 -0
  298. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/project/build_model.py +0 -0
  299. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/project/load_simulator.py +0 -0
  300. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/real_time/__init__.py +0 -0
  301. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/real_time/real_time_runner.py +0 -0
  302. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/tools/__init__.py +0 -0
  303. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/tools/blocks_registry.py +0 -0
  304. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks/tools/generate_blocks_index.py +0 -0
  305. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks.egg-info/dependency_links.txt +0 -0
  306. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/pySimBlocks.egg-info/entry_points.txt +0 -0
  307. {pysimblocks-0.1.1 → pysimblocks-0.2.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pySimBlocks
3
- Version: 0.1.1
3
+ Version: 0.2.0
4
4
  Summary: A block-diagram simulation environment with PySide6 editor
5
5
  Author-email: Antoine Alessandrini <antoine.alessandrini@univ-lille.fr>
6
6
  License-Expression: LGPL-3.0-or-later
@@ -28,6 +28,7 @@ Provides-Extra: docs
28
28
  Requires-Dist: sphinx; extra == "docs"
29
29
  Requires-Dist: myst-parser; extra == "docs"
30
30
  Requires-Dist: furo; extra == "docs"
31
+ Requires-Dist: sphinxcontrib-video; extra == "docs"
31
32
  Provides-Extra: tests
32
33
  Requires-Dist: pytest; extra == "tests"
33
34
  Requires-Dist: pytest-qt; extra == "tests"
@@ -153,7 +154,7 @@ A collection of basic and advanced examples is available in the
153
154
  [examples](./examples) directory, including:
154
155
 
155
156
  - Control system demonstrations
156
- - SOFA-based simulations (tested with SOFA v24.06 and later.)
157
+ - SOFA-based simulations (tested with SOFA v26.06 and later.)
157
158
  - Hardware and real-time use cases
158
159
  - Comparisons with external tools
159
160
 
@@ -118,7 +118,7 @@ A collection of basic and advanced examples is available in the
118
118
  [examples](./examples) directory, including:
119
119
 
120
120
  - Control system demonstrations
121
- - SOFA-based simulations (tested with SOFA v24.06 and later.)
121
+ - SOFA-based simulations (tested with SOFA v26.06 and later.)
122
122
  - Hardware and real-time use cases
123
123
  - Comparisons with external tools
124
124
 
@@ -20,8 +20,12 @@
20
20
 
21
21
  from pySimBlocks.blocks.interfaces.external_input import ExternalInput
22
22
  from pySimBlocks.blocks.interfaces.external_output import ExternalOutput
23
+ from pySimBlocks.blocks.interfaces.goto import Goto
24
+ from pySimBlocks.blocks.interfaces.bus_from import BusFrom
23
25
 
24
26
  __all__ = [
25
27
  "ExternalInput",
26
- "ExternalOutput"
28
+ "ExternalOutput",
29
+ "Goto",
30
+ "BusFrom",
27
31
  ]
@@ -0,0 +1,88 @@
1
+ # ******************************************************************************
2
+ # pySimBlocks
3
+ # Copyright (c) 2026 Université de Lille & INRIA
4
+ # ******************************************************************************
5
+ # This program is free software: you can redistribute it and/or modify it
6
+ # under the terms of the GNU Lesser General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or (at your
8
+ # option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful, but WITHOUT
11
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13
+ # for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+ # ******************************************************************************
18
+ # Authors: see Authors.txt
19
+ # ******************************************************************************
20
+
21
+ from pySimBlocks.core.block import Block
22
+ from pySimBlocks.core import signal_bus
23
+
24
+
25
+ class BusFrom(Block):
26
+ """Read a signal from the global signal bus by tag.
27
+
28
+ BusFrom and Goto blocks implement a virtual wiring mechanism: a Goto writes
29
+ its input to ``signal_bus._signal_bus[tag]`` each tick, and this block
30
+ reads that value without requiring an explicit connection in the model
31
+ graph.
32
+
33
+ The model's topological sort injects a virtual edge from each Goto to every
34
+ BusFrom sharing the same tag, ensuring the Goto executes before this block
35
+ within the same tick.
36
+ """
37
+
38
+ direct_feedthrough = True
39
+
40
+ def __init__(self, name: str, tag: str, sample_time: float | None = None):
41
+ """Initialize a BusFrom block.
42
+
43
+ Args:
44
+ name: Unique identifier for this block instance.
45
+ tag: Signal bus tag to read from. Must match the tag of the
46
+ corresponding Goto block.
47
+ sample_time: Sampling period in seconds, or None to use the
48
+ global simulation dt.
49
+ """
50
+ super().__init__(name, sample_time)
51
+ self.tag = tag
52
+ self.outputs["out"] = None
53
+
54
+ # --------------------------------------------------------------------------
55
+ # Public methods
56
+ # --------------------------------------------------------------------------
57
+
58
+ def initialize(self, t0: float) -> None:
59
+ """Read the initial value from the signal bus if available.
60
+
61
+ If the tag is not yet in the bus (Goto not yet initialized), the
62
+ output is set to None.
63
+
64
+ Args:
65
+ t0: Initial simulation time in seconds.
66
+ """
67
+ self.outputs["out"] = signal_bus._signal_bus.get(self.tag)
68
+
69
+ def output_update(self, t: float, dt: float) -> None:
70
+ """Read the current value from the signal bus.
71
+
72
+ Args:
73
+ t: Current simulation time in seconds.
74
+ dt: Current time step in seconds.
75
+
76
+ Raises:
77
+ KeyError: If no Goto with the matching tag has written to the bus
78
+ in this run.
79
+ """
80
+ if self.tag not in signal_bus._signal_bus:
81
+ raise KeyError(
82
+ f"[{self.name}] Tag '{self.tag}' not found in signal bus. "
83
+ "Ensure a Goto block with the same tag exists in the model."
84
+ )
85
+ self.outputs["out"] = signal_bus._signal_bus[self.tag]
86
+
87
+ def state_update(self, t: float, dt: float) -> None:
88
+ """No-op: BusFrom carries no internal state."""
@@ -0,0 +1,78 @@
1
+ # ******************************************************************************
2
+ # pySimBlocks
3
+ # Copyright (c) 2026 Université de Lille & INRIA
4
+ # ******************************************************************************
5
+ # This program is free software: you can redistribute it and/or modify it
6
+ # under the terms of the GNU Lesser General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or (at your
8
+ # option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful, but WITHOUT
11
+ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12
+ # FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
13
+ # for more details.
14
+ #
15
+ # You should have received a copy of the GNU Lesser General Public License
16
+ # along with this program. If not, see <https://www.gnu.org/licenses/>.
17
+ # ******************************************************************************
18
+ # Authors: see Authors.txt
19
+ # ******************************************************************************
20
+
21
+ from pySimBlocks.core.block import Block
22
+ from pySimBlocks.core import signal_bus
23
+
24
+
25
+ class Goto(Block):
26
+ """Publish a signal to the global signal bus under a named tag.
27
+
28
+ Goto and From blocks implement a virtual wiring mechanism: a Goto writes
29
+ its input to ``signal_bus._signal_bus[tag]`` each tick, and any From block
30
+ with the same tag reads that value without requiring an explicit connection
31
+ in the model graph.
32
+
33
+ The model's topological sort injects a virtual edge from each Goto to every
34
+ From sharing the same tag, ensuring the Goto executes before its consumers
35
+ within the same tick.
36
+ """
37
+
38
+ direct_feedthrough = True
39
+
40
+ def __init__(self, name: str, tag: str, sample_time: float | None = None):
41
+ """Initialize a Goto block.
42
+
43
+ Args:
44
+ name: Unique identifier for this block instance.
45
+ tag: Signal bus tag under which the input value is published.
46
+ Must match the tag of the corresponding From block(s).
47
+ sample_time: Sampling period in seconds, or None to use the
48
+ global simulation dt.
49
+ """
50
+ super().__init__(name, sample_time)
51
+ self.tag = tag
52
+ self.inputs["in"] = None
53
+
54
+ # --------------------------------------------------------------------------
55
+ # Public methods
56
+ # --------------------------------------------------------------------------
57
+
58
+ def initialize(self, t0: float) -> None:
59
+ """Publish the current input to the signal bus.
60
+
61
+ If no input has been connected yet (None), the bus entry is set to None.
62
+
63
+ Args:
64
+ t0: Initial simulation time in seconds.
65
+ """
66
+ signal_bus._signal_bus[self.tag] = self.inputs["in"]
67
+
68
+ def output_update(self, t: float, dt: float) -> None:
69
+ """Write the input value to the signal bus under this block's tag.
70
+
71
+ Args:
72
+ t: Current simulation time in seconds.
73
+ dt: Current time step in seconds.
74
+ """
75
+ signal_bus._signal_bus[self.tag] = self.inputs["in"]
76
+
77
+ def state_update(self, t: float, dt: float) -> None:
78
+ """No-op: Goto carries no internal state."""
@@ -38,9 +38,12 @@ class FileSource(BlockSource):
38
38
 
39
39
  - ``.npz`` / ``.npy``: 1D ``(N,)`` treated as ``(N, 1)``, or 2D ``(N, n)``
40
40
  where N is the number of samples and n the signal dimension. Each step
41
- outputs a ``(n, 1)`` column vector.
41
+ outputs a ``(n, 1)`` column vector. If the stored array is instead
42
+ ``(n, N)`` (signals in rows, samples in columns), set ``transpose=True``
43
+ to have it transposed to ``(N, n)`` before use.
42
44
  - ``.csv``: a single column is selected by ``key``, always producing shape
43
- ``(N, 1)``. Output per step is ``(1, 1)``.
45
+ ``(N, 1)``. Output per step is ``(1, 1)``. ``transpose`` is not
46
+ applicable to CSV input.
44
47
 
45
48
  Alternatively, when ``use_time=True``, the output is selected by
46
49
  looking up the closest past timestamp in a time column bundled with
@@ -52,6 +55,8 @@ class FileSource(BlockSource):
52
55
  key: Array key (NPZ) or column name (CSV) to load. None for NPY files.
53
56
  repeat: If True, restart from the first sample after the last one.
54
57
  use_time: If True, select samples by time lookup instead of index.
58
+ transpose: If True (NPZ/NPY only), transpose the loaded 2D array
59
+ before use, i.e. treat it as ``(n, N)`` instead of ``(N, n)``.
55
60
  """
56
61
 
57
62
  VALID_FILE_TYPES = {"npz", "npy", "csv"}
@@ -63,6 +68,7 @@ class FileSource(BlockSource):
63
68
  key: str | None = None,
64
69
  repeat: bool = False,
65
70
  use_time: bool = False,
71
+ transpose: bool = False,
66
72
  sample_time: float | None = None,
67
73
  ):
68
74
  """Initialize a FileSource block.
@@ -77,13 +83,18 @@ class FileSource(BlockSource):
77
83
  use_time: If True, select samples by nearest past timestamp
78
84
  instead of advancing by step index. Requires a ``"time"``
79
85
  key or column in the file.
86
+ transpose: If True, transpose the loaded 2D array before use.
87
+ Only supported for NPZ and NPY inputs, where it allows
88
+ loading data stored as ``(n, N)`` (signals in rows) instead
89
+ of the expected ``(N, n)`` (samples in rows).
80
90
  sample_time: Sampling period in seconds, or None to use the
81
91
  global simulation dt.
82
92
 
83
93
  Raises:
84
94
  ValueError: If the file extension is unsupported, if ``use_time``
85
- is combined with an NPY file or with ``repeat=True``, or if
86
- the loaded data is invalid.
95
+ is combined with an NPY file or with ``repeat=True``, if
96
+ ``transpose`` is combined with a CSV file, or if the loaded
97
+ data is invalid.
87
98
  FileNotFoundError: If the file does not exist.
88
99
  """
89
100
  super().__init__(name, sample_time)
@@ -93,6 +104,7 @@ class FileSource(BlockSource):
93
104
  self.key = key
94
105
  self.repeat = self._to_bool(repeat, "repeat")
95
106
  self.use_time = self._to_bool(use_time, "use_time")
107
+ self.transpose = self._to_bool(transpose, "transpose")
96
108
 
97
109
  if self.use_time and self.file_type == "npy":
98
110
  raise ValueError(
@@ -102,6 +114,10 @@ class FileSource(BlockSource):
102
114
  raise ValueError(
103
115
  f"[{self.name}] repeat cannot be used when use_time=True."
104
116
  )
117
+ if self.transpose and self.file_type == "csv":
118
+ raise ValueError(
119
+ f"[{self.name}] transpose is supported only for NPZ and NPY inputs."
120
+ )
105
121
 
106
122
  self._time: np.ndarray | None = None
107
123
  self._samples = self._load_samples()
@@ -198,7 +214,10 @@ class FileSource(BlockSource):
198
214
 
199
215
  if arr.ndim == 1:
200
216
  arr = arr.reshape(-1, 1)
201
- elif arr.ndim != 2:
217
+ elif arr.ndim == 2:
218
+ if self.transpose:
219
+ arr = arr.T
220
+ else:
202
221
  raise ValueError(
203
222
  f"[{self.name}] Loaded data must be 1D or 2D. Got shape {arr.shape}."
204
223
  )
@@ -206,6 +225,12 @@ class FileSource(BlockSource):
206
225
  if arr.shape[0] == 0:
207
226
  raise ValueError(f"[{self.name}] Loaded file contains no samples.")
208
227
 
228
+ if time is not None and time.shape[0] != arr.shape[0]:
229
+ raise ValueError(
230
+ f"[{self.name}] time length ({time.shape[0]}) must match number "
231
+ f"of samples ({arr.shape[0]}) after applying transpose."
232
+ )
233
+
209
234
  self._time = time
210
235
 
211
236
  return arr.astype(float, copy=False)
@@ -20,8 +20,10 @@
20
20
 
21
21
  from pySimBlocks.blocks.systems.linear_state_space import LinearStateSpace
22
22
  from pySimBlocks.blocks.systems.polytopic_state_space import PolytopicStateSpace
23
+ from pySimBlocks.blocks.systems.transfer_function import TransferFunction
23
24
 
24
25
  __all__ = [
25
26
  "LinearStateSpace",
26
27
  "PolytopicStateSpace",
28
+ "TransferFunction"
27
29
  ]
@@ -29,20 +29,25 @@ from pySimBlocks.core.block import Block
29
29
  class LinearStateSpace(Block):
30
30
  """Discrete-time linear state-space system block.
31
31
 
32
- Implements a strictly proper discrete-time linear system:
32
+ Implements a discrete-time linear system:
33
33
 
34
34
  x[k+1] = A x[k] + B u[k]
35
-
36
- y[k] = C x[k]
37
35
 
38
- The D matrix is intentionally not supported to avoid algebraic loops.
36
+ y[k] = C x[k] (if D is None)
37
+ y[k] = C x[k] + D u[k] (if D is provided)
38
+
39
+ When D is None the block is strictly proper (no direct feedthrough).
40
+ When D is provided the block has direct feedthrough and algebraic loops
41
+ involving this block will be detected and rejected at compile time.
39
42
 
40
43
  Attributes:
41
44
  A: State transition matrix of shape (n, n).
42
45
  B: Input matrix of shape (n, m).
43
46
  C: Output matrix of shape (p, n).
47
+ D: Feedthrough matrix of shape (p, m), or None.
44
48
  """
45
49
 
50
+ # Default at class level; overridden per-instance when D is provided.
46
51
  direct_feedthrough = False
47
52
 
48
53
  def __init__(
@@ -51,6 +56,7 @@ class LinearStateSpace(Block):
51
56
  A: ArrayLike,
52
57
  B: ArrayLike,
53
58
  C: ArrayLike,
59
+ D: ArrayLike | None = None,
54
60
  x0: ArrayLike | None = None,
55
61
  sample_time: float | None = None,
56
62
  ):
@@ -61,6 +67,9 @@ class LinearStateSpace(Block):
61
67
  A: State transition matrix, array-like of shape (n, n).
62
68
  B: Input matrix, array-like of shape (n, m).
63
69
  C: Output matrix, array-like of shape (p, n).
70
+ D: Feedthrough matrix, array-like of shape (p, m), or None.
71
+ When provided, the block gains direct feedthrough and
72
+ y[k] = C x[k] + D u[k].
64
73
  x0: Initial state vector, array-like of shape (n, 1) or (n,).
65
74
  Defaults to zeros.
66
75
  sample_time: Sampling period in seconds, or None to use the
@@ -101,6 +110,23 @@ class LinearStateSpace(Block):
101
110
  self._m = self.B.shape[1]
102
111
  self._p = self.C.shape[0]
103
112
 
113
+ # --- D matrix (optional) ---
114
+ if D is not None:
115
+ self.D = np.asarray(D, dtype=float)
116
+ if self.D.ndim != 2:
117
+ raise ValueError(f"[{self.name}] D must be 2D. Got shape {self.D.shape}.")
118
+ if self.D.shape != (self._p, self._m):
119
+ raise ValueError(
120
+ f"[{self.name}] D must have shape ({self._p}, {self._m}). "
121
+ f"Got {self.D.shape}."
122
+ )
123
+ # Override direct_feedthrough at the instance level so the
124
+ # scheduler sees this block as having direct feedthrough.
125
+ self.direct_feedthrough = True
126
+ else:
127
+ self.D = None
128
+
129
+ # --- Initial state ---
104
130
  if x0 is None:
105
131
  x0_arr = np.zeros((n, 1), dtype=float)
106
132
  else:
@@ -143,12 +169,21 @@ class LinearStateSpace(Block):
143
169
  def output_update(self, t: float, dt: float) -> None:
144
170
  """Compute y and x outputs from the committed state.
145
171
 
172
+ When D is provided, u[k] is read at this step (direct feedthrough).
173
+
146
174
  Args:
147
175
  t: Current simulation time in seconds.
148
176
  dt: Current time step in seconds.
149
177
  """
150
178
  x = self.state["x"]
151
- self.outputs["y"] = self.C @ x
179
+ if self.D is not None:
180
+ u = self.inputs["u"]
181
+ if u is None:
182
+ raise RuntimeError(f"[{self.name}] Input 'u' is not connected or not set.")
183
+ u_vec = self._to_col_vec("u", u, self._m)
184
+ self.outputs["y"] = self.C @ x + self.D @ u_vec
185
+ else:
186
+ self.outputs["y"] = self.C @ x
152
187
  self.outputs["x"] = x.copy()
153
188
 
154
189
  def state_update(self, t: float, dt: float) -> None:
@@ -22,6 +22,7 @@ import importlib.util
22
22
  import inspect
23
23
  from pathlib import Path
24
24
  from typing import Any, Callable, Dict, List
25
+ from numpy.typing import ArrayLike
25
26
 
26
27
  import numpy as np
27
28
 
@@ -87,10 +88,7 @@ class NonLinearStateSpace(Block):
87
88
  self.input_keys = list(input_keys)
88
89
  self.output_keys = list(output_keys)
89
90
 
90
- if not isinstance(x0, np.ndarray):
91
- raise TypeError(
92
- f"{self.name}: x0 must be a numpy array"
93
- )
91
+ x0 = np.asarray(x0, dtype=float) # <-- conversion, comme dans les autres blocs
94
92
  if x0.ndim == 1:
95
93
  x0 = x0.reshape(-1, 1)
96
94
  elif x0.ndim != 2 or x0.shape[1] != 1: